Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions contracts/nft/erc721m/ERC721CM.sol
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,11 @@ contract ERC721CM is
uint256 timestampExpirySeconds,
address mintCurrency,
address fundReceiver,
uint256 mintFee
) ERC721ACQueryable(collectionName, collectionSymbol) Ownable() {
uint256 mintFee,
address initialOwner
) ERC721ACQueryable(collectionName, collectionSymbol) {
_transferOwnership(initialOwner);

if (globalWalletLimit > maxMintableSupply) {
revert GlobalWalletLimitOverflow();
}
Expand Down
69 changes: 69 additions & 0 deletions scripts-foundry/common/100a-create2-magicdrop-impl.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/bin/bash

if [ -f .env ]
then
export $(grep -v '^#' .env | xargs)
else
echo "Please set your .env file"
exit 1
fi

NAME=""
SYMBOL=""
TOKEN_URI_SUFFIX=""
MAX_MINTABLE_SUPPLY="1000"
GLOBAL_WALLET_LIMIT="0"
COSIGNER="0x0000000000000000000000000000000000000000"
TIMESTAMP_EXPIRY_SECONDS="60"
MINT_CURRENCY="0x0000000000000000000000000000000000000000"
FUND_RECEIVER=""
MINT_FEE="0"
INITIAL_OWNER=""

# Function to display usage
usage() {
echo "Usage: $0 --impl <path to implementation> --name <name> --symbol <symbol> --fund-receiver <fund receiver address> --mint-fee <mint fee> --initial-owner <initial owner address>"
exit 1
}

# Process arguments
while [[ "$#" -gt 0 ]]; do
case $1 in
--impl) IMPL_PATH=$2; shift ;;
--name) NAME=$2; shift ;;
--symbol) SYMBOL=$2; shift ;;
--fund-receiver) FUND_RECEIVER=$2; shift ;;
--mint-fee) MINT_FEE=$2; shift ;;
--initial-owner) INITIAL_OWNER=$2; shift ;;
*) usage ;;
esac
shift
done

echo "IMPL_PATH: $IMPL_PATH"
echo "NAME: $NAME"
echo "SYMBOL: $SYMBOL"
echo "FUND_RECEIVER: $FUND_RECEIVER"
echo "MINT_FEE: $MINT_FEE"
echo "INITIAL_OWNER: $INITIAL_OWNER"

# Check if all parameters are set
if [ -z "$IMPL_PATH" ] || [ -z "$NAME" ] || [ -z "$SYMBOL" ] || [ -z "$FUND_RECEIVER" ] || [ -z "$MINT_FEE" ] || [ -z "$INITIAL_OWNER" ]; then
usage
fi

# NOTE: If you change the number of optimizer runs, you must also change the number in the deploy script, otherwise the CREATE2 address will be different

echo "create2 MagicDropImpl START"

implByteCode="$(forge inspect contracts/nft/erc721m/ERC721CM.sol:ERC721CM bytecode --optimizer-runs 777 --via-ir)"
constructorArgs=$(cast abi-encode "constructor(string,string,string,uint256,uint256,address,uint256,address,address,uint256,address)" "$NAME" "$SYMBOL" "$TOKEN_URI_SUFFIX" "$MAX_MINTABLE_SUPPLY" "$GLOBAL_WALLET_LIMIT" "$COSIGNER" "$TIMESTAMP_EXPIRY_SECONDS" "$MINT_CURRENCY" "$FUND_RECEIVER" "$MINT_FEE" "$INITIAL_OWNER")
constructorArgsNoPrefix=${constructorArgs#0x}
implInitCode=$(cast concat-hex $implByteCode $constructorArgsNoPrefix)

echo $constructorArgs

cast create2 --starts-with 88888888 --case-sensitive --init-code $implInitCode
echo "create2 MagicDropImpl END"
echo "-------------------------------------"
echo ""
111 changes: 111 additions & 0 deletions scripts-foundry/common/101a-deploy-magicdrop-impl-direct.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#!/usr/bin/env bash

if [ -f .env ]
then
export $(grep -v '^#' .env | xargs)
else
echo "Please set your .env file"
exit 1
fi

# Note: Update the contract in the deploy script if you want to deploy a different version. Default is 1_0_0

source ./utils

# Exit on error
set -e

# Initialize variables with environment values
CHAIN_ID=${CHAIN_ID:-""}
RPC_URL=""
STANDARD=""
IS_ERC721C=false #optional
IMPL_EXPECTED_ADDRESS=""
IMPL_SALT=""
NAME=""
SYMBOL=""
FUND_RECEIVER=""
MINT_FEE=0
INITIAL_OWNER=""

# Function to display usage
usage() {
# Example Usage: ./2a-deploy-magicdrop-impl.sh --chain-id 137 --token-standard ERC721 --is-erc721c true --expected-address 0x0000000000000000000000000000000000000000 --salt 0x0000000000000000000000000000000000000000000000000000000000000000
echo "Usage: $0 --chain-id <chain id> --token-standard <token standard> --is-erc721c <bool> --expected-address <expected address> --salt <salt> --name <name> --symbol <symbol> --fund-receiver <fund receiver address> --mint-fee <mint fee> --initial-owner <initial owner>"
exit 1
}

# Process arguments
while [[ "$#" -gt 0 ]]; do
case $1 in
--chain-id) CHAIN_ID=$2; shift ;;
--token-standard) STANDARD=$2; shift ;;
--is-erc721c) IS_ERC721C=$2; shift ;;
--expected-address) IMPL_EXPECTED_ADDRESS=$2; shift ;;
--salt) IMPL_SALT=$2; shift ;;
--name) NAME=$2; shift ;;
--symbol) SYMBOL=$2; shift ;;
--fund-receiver) FUND_RECEIVER=$2; shift ;;
--mint-fee) MINT_FEE=$2; shift ;;
--initial-owner) INITIAL_OWNER=$2; shift ;;
*) usage ;;
esac
shift
done

# Check if all parameters are set
if [ -z "$CHAIN_ID" ] || [ -z "$STANDARD" ] || [ -z "$IMPL_EXPECTED_ADDRESS" ] || [ -z "$IMPL_SALT" ] || [ -z "$NAME" ] || [ -z "$SYMBOL" ] || [ -z "$FUND_RECEIVER" ] || [ -z "$MINT_FEE" ] || [ -z "$INITIAL_OWNER" ]; then
usage
fi

# Set the RPC URL based on chain ID
set_rpc_url $CHAIN_ID

# Set the ETHERSCAN API KEY based on chain ID
set_etherscan_api_key $CHAIN_ID

# Convert STANDARD to lowercase for the path
STANDARD_LOWERCASE=$(echo $STANDARD | tr '[:upper:]' '[:lower:]')

echo ""
echo "==================== DEPLOYMENT DETAILS ===================="
echo "Chain ID: $CHAIN_ID"
echo "RPC URL: $RPC_URL"
echo "Token Standard: $STANDARD"
echo "Is ERC721C: $IS_ERC721C"
echo "Expected Address: $IMPL_EXPECTED_ADDRESS"
echo "Salt: $IMPL_SALT"
echo "Name: $NAME"
echo "Symbol: $SYMBOL"
echo "Fund Reciever: $FUND_RECEIVER"
echo "Mint Fee: $MINT_FEE"
echo "Initial Owner: $INITIAL_OWNER"
echo "============================================================"
echo ""
read -p "Do you want to proceed? (yes/no) " yn

case $yn in
yes ) echo ok, we will proceed;;
no ) echo exiting...;
exit;;
* ) echo invalid response;
exit 1;;
esac

echo ""
echo "============= DEPLOYING MAGICDROP IMPLEMENTATION ============="
echo ""

# remove --verify when deploying on Sei Chain. You will need to verify manually.
CHAIN_ID=$CHAIN_ID RPC_URL=$RPC_URL TOKEN_STANDARD=$STANDARD IS_ERC721C=$IS_ERC721C IMPL_EXPECTED_ADDRESS=$IMPL_EXPECTED_ADDRESS IMPL_SALT=$IMPL_SALT NAME=$NAME SYMBOL=$SYMBOL FUND_RECEIVER=$FUND_RECEIVER MINT_FEE=$MINT_FEE INITIAL_OWNER=$INITIAL_OWNER forge script ./DeployMagicDropImplementationDirect.s.sol:DeployMagicDropImplementationDirect \
--rpc-url $RPC_URL \
--broadcast \
--optimizer-runs 777 \
--via-ir \
--verify \
--verifier custom \
-v

echo ""
echo "============= DEPLOYED MAGICDROP IMPLEMENTATION ============="
echo ""
75 changes: 75 additions & 0 deletions scripts-foundry/common/DeployMagicDropImplementationDirect.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;

import {Script, console} from "forge-std/Script.sol";
import {ERC721M} from "contracts/nft/erc721m/ERC721M.sol";
import {ERC721CM} from "contracts/nft/erc721m/ERC721CM.sol";
import {ERC1155M} from "contracts/nft/erc1155m/ERC1155M.sol";
import {TokenStandard} from "contracts/common/Structs.sol";

contract DeployMagicDropImplementationDirect is Script {
error AddressMismatch(address expected, address actual);
error InvalidTokenStandard(string standard);
error NotImplementedYet();

function run() external {
bytes32 salt = vm.envBytes32("IMPL_SALT");
address expectedAddress = address(uint160(vm.envUint("IMPL_EXPECTED_ADDRESS")));
TokenStandard standard = parseTokenStandard(vm.envString("TOKEN_STANDARD"));
bool isERC721C = vm.envBool("IS_ERC721C");
uint256 privateKey = vm.envUint("PRIVATE_KEY");
string memory name = vm.envString("NAME");
string memory symbol = vm.envString("SYMBOL");
string memory tokenUriSuffix = "";
uint256 maxMintableSupply = 1000;
uint256 globalWalletLimit = 0;
address cosigner = address(0);
uint256 timestampExpirySeconds = 60;
address mintCurrency = address(0);
address fundReceiver = address(uint160(vm.envUint("FUND_RECEIVER")));
uint256 mintFee = vm.envUint("MINT_FEE");
address initialOwner = address(uint160(vm.envUint("INITIAL_OWNER")));

vm.startBroadcast(privateKey);

address deployedAddress;

if (standard == TokenStandard.ERC721) {
if (isERC721C) {
deployedAddress = address(new ERC721CM{salt: salt}(
name,
symbol,
tokenUriSuffix,
maxMintableSupply,
globalWalletLimit,
cosigner,
timestampExpirySeconds,
mintCurrency,
fundReceiver,
mintFee,
initialOwner
));
} else {
revert NotImplementedYet();
}
} else if (standard == TokenStandard.ERC1155) {
revert NotImplementedYet();
}

if (address(deployedAddress) != expectedAddress) {
revert AddressMismatch(expectedAddress, deployedAddress);
}

vm.stopBroadcast();
}

function parseTokenStandard(string memory standardString) internal pure returns (TokenStandard) {
if (keccak256(abi.encodePacked(standardString)) == keccak256(abi.encodePacked("ERC721"))) {
return TokenStandard.ERC721;
} else if (keccak256(abi.encodePacked(standardString)) == keccak256(abi.encodePacked("ERC1155"))) {
return TokenStandard.ERC1155;
} else {
revert InvalidTokenStandard(standardString);
}
}
}
4 changes: 4 additions & 0 deletions test/erc721m/ERC721CM.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ describe('ERC721CM', function () {
ethers.constants.AddressZero,
fundReceiver.address,
MINT_FEE,
owner.address,
);
await erc721cm.deployed();

Expand Down Expand Up @@ -1670,6 +1671,7 @@ describe('ERC721CM', function () {
ethers.constants.AddressZero,
fundReceiver.address,
MINT_FEE,
owner.address,
),
).to.be.revertedWith('GlobalWalletLimitOverflow');
});
Expand Down Expand Up @@ -1786,6 +1788,7 @@ describe('ERC721CM', function () {
ethers.constants.AddressZero,
fundReceiver.address,
MINT_FEE,
owner.address,
);
await erc721cm.deployed();
const ownerConn = erc721cm.connect(owner);
Expand Down Expand Up @@ -1816,6 +1819,7 @@ describe('ERC721CM', function () {
ethers.constants.AddressZero,
fundReceiver.address,
MINT_FEE,
owner.address,
);
await erc721cm.deployed();

Expand Down
17 changes: 10 additions & 7 deletions test/erc721m/mintCurrency.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { ERC721CM, ERC721M } from '../../typechain-types';
import { Contract, Signer } from 'ethers';
import { Contract } from 'ethers';
import { ethers } from 'hardhat';
import { expect } from 'chai';
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';

describe('ERC721M: Mint Currency', () => {
let erc721M: ERC721M;
let contract: ERC721M;
let erc20: Contract;
let owner: Signer;
let fundReceiver: Signer;
let minter: Signer;
let owner: SignerWithAddress;
let fundReceiver: SignerWithAddress;
let minter: SignerWithAddress;
const mintPrice = 50;
const mintFee = 10;
const mintQty = 3;
Expand Down Expand Up @@ -216,9 +217,9 @@ describe('ERC721CM: Mint Currency', () => {
let erc721CM: ERC721CM;
let contract: ERC721CM;
let erc20: Contract;
let owner: Signer;
let fundReceiver: Signer;
let minter: Signer;
let owner: SignerWithAddress;
let fundReceiver: SignerWithAddress;
let minter: SignerWithAddress;
const mintPrice = 50;
const mintFee = 10;
const mintQty = 3;
Expand Down Expand Up @@ -246,6 +247,7 @@ describe('ERC721CM: Mint Currency', () => {
erc20.address,
fundReceiver.getAddress(),
mintFee,
owner.address,
);
await erc721CM.deployed();

Expand Down Expand Up @@ -395,6 +397,7 @@ describe('ERC721CM: Mint Currency', () => {
ethers.constants.AddressZero,
fundReceiver.getAddress(),
mintFee,
owner.address,
);
await erc721CM.deployed();

Expand Down
Loading