add mint stage2 with wl
This commit is contained in:
parent
5e6e4f30eb
commit
54682fbfc7
594
build/contracts/NFTClaimStage2WL.json
Normal file
594
build/contracts/NFTClaimStage2WL.json
Normal file
File diff suppressed because one or more lines are too long
@ -22,14 +22,27 @@ const admins = {
|
||||
|
||||
const token = {
|
||||
baseTokenURIHero: "https://nft-test.kingsome.cn/hero/meta/13473/",
|
||||
contractURI: 'https://nft-test.kingsome.cn/hero/meta/13473/',
|
||||
contractURIHero: 'https://nft-test.kingsome.cn/hero/home_meta/13473',
|
||||
royaltyReceiver: '0x5Ab03Aa79Ab91B7420b5CFF134a4188388888888',
|
||||
baseTokenURIGold: "https://nft-test.kingsome.cn/gold_bullion/meta/13473/",
|
||||
contractURIGold: 'https://nft-test.kingsome.cn/gold_bullion/home_meta/13473',
|
||||
royaltyFee: 5,
|
||||
};
|
||||
|
||||
const imtbl = {
|
||||
operatorAllowlist: '0x6b969FD89dE634d8DE3271EbE97734FEFfcd58eE'
|
||||
operatorAllowlist: '0x6b969FD89dE634d8DE3271EbE97734FEFfcd58eE',
|
||||
}
|
||||
const mint = {
|
||||
// 2期mint支付的代币
|
||||
mintCurrency: '0xFd42bfb03212dA7e1A4608a44d7658641D99CF34',
|
||||
// 2期mint, 单个nft价格
|
||||
mintPrice: '100',
|
||||
// 2期mint接收代币的钱包地址
|
||||
mintFeeAddress: '0x50A8e60041A206AcaA5F844a1104896224be6F39',
|
||||
// 2期mint nftid 开始
|
||||
mintStartNftId: '6240603010000001',
|
||||
// 2期mint 最大可mint数量
|
||||
maxSupply: 2000,
|
||||
}
|
||||
|
||||
var config = {
|
||||
@ -37,6 +50,7 @@ var config = {
|
||||
admins,
|
||||
token,
|
||||
imtbl,
|
||||
mint
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
|
144
contracts/activity/NFTClaimStage2WL.sol
Normal file
144
contracts/activity/NFTClaimStage2WL.sol
Normal file
@ -0,0 +1,144 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity 0.8.19;
|
||||
|
||||
import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
|
||||
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";
|
||||
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
|
||||
/**
|
||||
* Contract for the activity of NFT claim stage 2.
|
||||
*/
|
||||
interface IClaimAbleNFT {
|
||||
function safeMint(address to, uint256 tokenID) external;
|
||||
}
|
||||
|
||||
contract NFTClaimStage2WL is ReentrancyGuard, AccessControl {
|
||||
using EnumerableSet for EnumerableSet.UintSet;
|
||||
/// @notice Only UPDATE_WL_ROLE can add white listing
|
||||
bytes32 public constant UPDATE_WL_ROLE = bytes32("UPDATE_WL_ROLE");
|
||||
/// @notice Only MANAGE_ROLE can change mint config
|
||||
bytes32 public constant MANAGE_ROLE = keccak256("MANAGE_ROLE");
|
||||
|
||||
struct MintConfig {
|
||||
uint256 maxSupply; // max supply for phase2
|
||||
address currency; // token address which user must pay to mint
|
||||
uint256 mintPrice; // in wei
|
||||
address feeToAddress; // wallet address to receive mint fee
|
||||
}
|
||||
// parse: 0: not open or end, 1: phase1, 2: phase2
|
||||
uint256 public mintParse = 0;
|
||||
address public immutable nftAddress;
|
||||
uint256 public immutable nftIdStart;
|
||||
|
||||
MintConfig public mintConfig;
|
||||
uint256 public totalCount;
|
||||
mapping(address user => uint256 num) private _whitelist1;
|
||||
mapping(address user => uint256 num) private _whitelist2;
|
||||
mapping(address user => EnumerableSet.UintSet tokenIdSet) private _mintedRecords;
|
||||
|
||||
|
||||
event NFTClaimed(address indexed nftAddress, address indexed to, uint256[] ids);
|
||||
|
||||
event ParseUpdated(uint256 _parse);
|
||||
event MintConfigUpdated(MintConfig config);
|
||||
|
||||
constructor(address _nftAddress, uint256 _nftIdStart, MintConfig memory _mintConfig) {
|
||||
_grantRole(DEFAULT_ADMIN_ROLE, _msgSender());
|
||||
_grantRole(UPDATE_WL_ROLE, _msgSender());
|
||||
_grantRole(MANAGE_ROLE, _msgSender());
|
||||
nftAddress = _nftAddress;
|
||||
mintConfig = _mintConfig;
|
||||
nftIdStart = _nftIdStart;
|
||||
}
|
||||
|
||||
modifier whenNotPaused() {
|
||||
require(mintParse > 0, "NFTClaimer: not begin or ended");
|
||||
_;
|
||||
}
|
||||
|
||||
function updateMintParse(uint256 _mintParse) external onlyRole(MANAGE_ROLE) {
|
||||
require(_mintParse == 0 || _mintParse == 1 || _mintParse == 2, "NFTClaimer: invalid mintParse");
|
||||
mintParse = _mintParse;
|
||||
emit ParseUpdated(_mintParse);
|
||||
}
|
||||
|
||||
function updateMintConfig(MintConfig calldata config) external onlyRole(MANAGE_ROLE) {
|
||||
mintConfig = config;
|
||||
emit MintConfigUpdated(config);
|
||||
}
|
||||
|
||||
function addParse1WL(address[] calldata _addressList, uint256[] calldata _nums) external onlyRole(UPDATE_WL_ROLE) {
|
||||
require(_addressList.length == _nums.length, "NFTClaimer: invalid whitelist");
|
||||
for (uint256 i = 0; i < _addressList.length; i++) {
|
||||
_whitelist1[_addressList[i]] = _nums[i];
|
||||
}
|
||||
}
|
||||
|
||||
function revokeParse1WL(address[] calldata _addressList) external onlyRole(MANAGE_ROLE) {
|
||||
for (uint256 i = 0; i < _addressList.length; i++) {
|
||||
delete _whitelist1[_addressList[i]];
|
||||
}
|
||||
}
|
||||
|
||||
function addParse2WL(address[] calldata _addressList) external onlyRole(UPDATE_WL_ROLE){
|
||||
for (uint256 i = 0; i < _addressList.length; i++) {
|
||||
_whitelist2[_addressList[i]] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
function revokeParse2WL(address[] calldata _addressList) external onlyRole(MANAGE_ROLE) {
|
||||
for (uint256 i = 0; i < _addressList.length; i++) {
|
||||
delete _whitelist2[_addressList[i]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @dev claim NFT
|
||||
* Get whitelist signature from a third-party service, then call this method to claim NFT
|
||||
*/
|
||||
function claim(
|
||||
uint256 nftCount
|
||||
) external nonReentrant whenNotPaused {
|
||||
require(nftCount > 0, "NFTClaimer: nft count must be greater than 0");
|
||||
require(nftCount <= mintConfig.maxSupply - totalCount, "NFTClaimer: exceed max supply");
|
||||
address to = _msgSender();
|
||||
uint256 _mintedCount = _mintedRecords[to].length();
|
||||
if (mintParse == 1) {
|
||||
require(_whitelist1[to] >= _mintedCount + nftCount, "NFTClaimer: not in whitelist or exceed limit");
|
||||
} else if (mintParse == 2) {
|
||||
require(_whitelist1[to] + _whitelist2[to] >= _mintedCount + nftCount, "NFTClaimer: not in whitelist or exceed limit");
|
||||
}
|
||||
uint256 _tokenAmount = mintConfig.mintPrice * nftCount;
|
||||
IERC20(mintConfig.currency).transferFrom(to, mintConfig.feeToAddress, _tokenAmount);
|
||||
uint256[] memory ids = new uint256[](nftCount);
|
||||
for (uint256 i = 0; i < nftCount; ++i) {
|
||||
uint256 _nftId = nftIdStart + totalCount + i;
|
||||
ids[i] = _nftId;
|
||||
IClaimAbleNFT(nftAddress).safeMint(to, _nftId);
|
||||
_mintedRecords[to].add(_nftId);
|
||||
}
|
||||
totalCount += nftCount;
|
||||
// add list
|
||||
emit NFTClaimed(nftAddress, to, ids);
|
||||
}
|
||||
|
||||
function whiteCount() external view returns (uint256){
|
||||
uint256 _count1 = _whitelist1[_msgSender()];
|
||||
uint256 _count2 = _whitelist2[_msgSender()];
|
||||
if (mintParse == 2) {
|
||||
return _count1 + _count2 - _mintedRecords[_msgSender()].length();
|
||||
} else {
|
||||
return _count1 - _mintedRecords[_msgSender()].length();
|
||||
}
|
||||
}
|
||||
|
||||
function mintedNum() external view returns (uint256){
|
||||
return _mintedRecords[_msgSender()].length();
|
||||
}
|
||||
|
||||
function mintedNft() external view returns (uint256[] memory){
|
||||
return _mintedRecords[_msgSender()].values();
|
||||
}
|
||||
|
||||
}
|
@ -26,8 +26,8 @@ const deployNFTForGame: DeployFunction =
|
||||
// testnet: 0x6b969FD89dE634d8DE3271EbE97734FEFfcd58eE
|
||||
// mainnet: 0x5F5EBa8133f68ea22D712b0926e2803E78D89221
|
||||
// testnet_CF: 0x3c5991E9A0e6c713163cD0a91f246dc61f18d918
|
||||
const { royaltyReceiver, royaltyFee, baseTokenURIHero, baseTokenURIGold, contractURI } = config.token;
|
||||
console.log(owner, name, symbol, baseTokenURIHero, contractURI, operatorAllowlist, royaltyReceiver, royaltyFee)
|
||||
const { royaltyReceiver, royaltyFee, baseTokenURIHero, baseTokenURIGold, contractURIHero, contractURIGold } = config.token;
|
||||
console.log(owner, name, symbol, baseTokenURIHero, contractURIHero, operatorAllowlist, royaltyReceiver, royaltyFee)
|
||||
// const ret = await hre.deployments.deploy("CFNFTGame", {
|
||||
// from,
|
||||
// args: [owner, name, symbol, baseTokenURIHero, contractURI, operatorAllowlist, royaltyReceiver, royaltyFee],
|
||||
@ -45,7 +45,7 @@ const deployNFTForGame: DeployFunction =
|
||||
const symbolGold = "CFG";
|
||||
const ret = await hre.deployments.deploy("CFNFTGame", {
|
||||
from,
|
||||
args: [owner, nameGold, symbolGold, baseTokenURIGold, contractURI, operatorAllowlist, royaltyReceiver, royaltyFee],
|
||||
args: [owner, nameGold, symbolGold, baseTokenURIGold, contractURIGold, operatorAllowlist, royaltyReceiver, royaltyFee],
|
||||
log: true,
|
||||
});
|
||||
console.log("==CFNFTGame addr=", ret.address);
|
||||
|
36
deploy/2_1_deploy_nftclaimer_wl.ts
Normal file
36
deploy/2_1_deploy_nftclaimer_wl.ts
Normal file
@ -0,0 +1,36 @@
|
||||
import { HardhatRuntimeEnvironment } from "hardhat/types";
|
||||
import { DeployFunction } from "hardhat-deploy/types";
|
||||
import { loadData, updateArray } from "../scripts/utils"
|
||||
|
||||
|
||||
const deployNFTClaim: DeployFunction =
|
||||
async function (hre: HardhatRuntimeEnvironment) {
|
||||
const provider = hre.ethers.provider;
|
||||
const from = await (await provider.getSigner()).getAddress();
|
||||
const config = require(`../config/config_${hre.network.name}`);
|
||||
const cfgs = loadData({network: hre.network.name})
|
||||
const nftAddress = cfgs.find((c: any) => c.name === "CFHero").address
|
||||
const mintConfig = [
|
||||
config.mint.maxSupply,
|
||||
config.mint.mintCurrency,
|
||||
config.mint.mintPrice,
|
||||
config.mint.mintFeeAddress
|
||||
]
|
||||
const startNftId = config.mint.mintStartNftId
|
||||
const ret = await hre.deployments.deploy("NFTClaimStage2WL", {
|
||||
from,
|
||||
args: [nftAddress, startNftId, mintConfig],
|
||||
log: true,
|
||||
});
|
||||
updateArray({
|
||||
name: "NFTClaimStage2WL",
|
||||
type: "logic",
|
||||
json: "assets/contracts/NFTClaimStage2WL.json",
|
||||
address: ret.address,
|
||||
network: hre.network.name,
|
||||
});
|
||||
};
|
||||
|
||||
deployNFTClaim.tags = ["NFTClaimStage2WL"];
|
||||
|
||||
export default deployNFTClaim;
|
@ -7,8 +7,8 @@ const deployNFTClaim: DeployFunction =
|
||||
async function (hre: HardhatRuntimeEnvironment) {
|
||||
const provider = hre.ethers.provider;
|
||||
const from = await (await provider.getSigner()).getAddress();
|
||||
|
||||
const verifier = '0x50A8e60041A206AcaA5F844a1104896224be6F39'
|
||||
const config = require(`../config/config_${hre.network.name}`);
|
||||
const verifier = config.admins.admin
|
||||
const ret = await hre.deployments.deploy("NFTLock", {
|
||||
from,
|
||||
args: [3600, verifier],
|
||||
|
File diff suppressed because one or more lines are too long
946
deployments/imtbl_test/NFTClaimStage2WL.json
Normal file
946
deployments/imtbl_test/NFTClaimStage2WL.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -28,5 +28,11 @@
|
||||
"type": "erc721",
|
||||
"json": "assets/contracts/CFNFTGame.json",
|
||||
"address": "0x2036A0708AC2F17F67b08357d8b4A7d47cF49c29"
|
||||
},
|
||||
{
|
||||
"name": "NFTClaimStage2WL",
|
||||
"type": "logic",
|
||||
"json": "assets/contracts/NFTClaimStage2WL.json",
|
||||
"address": "0x31F29C9A3D0c1c13C825475aebF0d964b5B47c45"
|
||||
}
|
||||
]
|
@ -9,6 +9,7 @@
|
||||
"clean": "hardhat clean",
|
||||
"deploy": "hardhat deploy --network imtbl_test",
|
||||
"deploy:nftclaim": "hardhat deploy --tags NFTClaimStage2 --network imtbl_test --reset",
|
||||
"deploy:nftclaimwl": "hardhat deploy --tags NFTClaimStage2WL --network imtbl_test --reset",
|
||||
"deploy:nft": "hardhat deploy --tags CFNFTGame --network imtbl_test --reset",
|
||||
"deploy:nftlock": "hardhat deploy --tags NFTLock --network imtbl_test --reset",
|
||||
"deploy:testtoken": "hardhat deploy --tags TestToken --network imtbl_test --reset",
|
||||
|
182
test/testNFTClaimWL.ts
Normal file
182
test/testNFTClaimWL.ts
Normal file
@ -0,0 +1,182 @@
|
||||
import { expect } from 'chai'
|
||||
import hre from "hardhat";
|
||||
import {
|
||||
getBytes,
|
||||
solidityPackedKeccak256,
|
||||
} from 'ethers'
|
||||
import {
|
||||
loadFixture,
|
||||
} from "@nomicfoundation/hardhat-toolbox/network-helpers";
|
||||
|
||||
describe('NFTClaimStage2WL', function() {
|
||||
async function deployOneContract() {
|
||||
// Contracts are deployed using the first signer/account by default
|
||||
const [owner, otherAccount] = await hre.ethers.getSigners();
|
||||
const verifier = owner.address;
|
||||
const OperatorAllowlist = await hre.ethers.getContractFactory("OperatorAllowlist");
|
||||
const operatorAllowlist = await OperatorAllowlist.deploy(owner.address);
|
||||
const CFFT = await hre.ethers.getContractFactory("ImmutableERC20MinterBurnerPermit");
|
||||
const ft = await CFFT.deploy(owner.address, owner.address, owner.address, "test usdc", "usdc", '100000000000000000000000000');
|
||||
await ft.grantMinterRole(owner.address);
|
||||
await ft.mint(otherAccount.address, '1000');
|
||||
const CFNFTGame = await hre.ethers.getContractFactory("CFNFTGame");
|
||||
const nft = await CFNFTGame.deploy(owner.address, 'name', 'symbol', 'baseURI', 'contractURI', operatorAllowlist.target, owner.address, 5);
|
||||
const nftAddress = nft.target;
|
||||
const NFTClaimStage2 = await hre.ethers.getContractFactory("NFTClaimStage2WL");
|
||||
const mintConfig = [
|
||||
2000,
|
||||
ft.target,
|
||||
100,
|
||||
owner.address
|
||||
]
|
||||
const nftClaimer = await NFTClaimStage2.deploy( nftAddress, '6240603010000001', mintConfig);
|
||||
await nft.grantMinterRole(nftClaimer.target)
|
||||
await nftClaimer.addParse1WL([otherAccount.address], [3])
|
||||
const chainId = hre.network.config.chainId
|
||||
return { nftClaimer, owner, otherAccount, verifier, nftAddress, ft, nft, chainId };
|
||||
}
|
||||
describe("Deployment", function () {
|
||||
it('should deploy NFTClaimStage2', async function() {
|
||||
const { nftClaimer, otherAccount } = await loadFixture(deployOneContract);
|
||||
expect((await nftClaimer.mintConfig()).mintPrice).to.equal(100);
|
||||
// @ts-ignore
|
||||
expect((await nftClaimer.connect(otherAccount).whiteCount())).to.equal(3);
|
||||
});
|
||||
it('should deploy NFTClaimStage2 with the correct NFT address', async function() {
|
||||
const { nftClaimer, nftAddress } = await loadFixture(deployOneContract);
|
||||
expect(await nftClaimer.nftAddress()).to.equal(nftAddress);
|
||||
});
|
||||
})
|
||||
|
||||
describe("update settings", function () {
|
||||
it('should update mintConfig', async function() {
|
||||
const { nftClaimer } = await loadFixture(deployOneContract);
|
||||
const mintConfig = [
|
||||
2000,
|
||||
'0xaa34B79A0Ab433eaC900fB3CB9f191F5Cd27501D',
|
||||
200,
|
||||
'0x5Ab03Aa79Ab91B7420b5CFF134a4188388888888'
|
||||
]
|
||||
await nftClaimer.updateMintConfig(mintConfig);
|
||||
expect((await nftClaimer.mintConfig()).mintPrice).to.equal(200);
|
||||
});
|
||||
|
||||
it('should update parse', async function() {
|
||||
const { nftClaimer } = await loadFixture(deployOneContract);
|
||||
await nftClaimer.updateMintParse(1);
|
||||
expect(await nftClaimer.mintParse()).to.equal(1);
|
||||
});
|
||||
});
|
||||
describe("claim", function () {
|
||||
it('should claim NFT', async function() {
|
||||
const { nftClaimer, owner, otherAccount, ft, nft, chainId } = await loadFixture(deployOneContract);
|
||||
await nftClaimer.updateMintParse(1);
|
||||
//use ft.connect() to send a transaction from another account
|
||||
// @ts-ignore
|
||||
await ft.connect(otherAccount).approve(nftClaimer.target, 200)
|
||||
expect(await nftClaimer.nftAddress()).equal(nft.target);
|
||||
// @ts-ignore
|
||||
await nftClaimer.connect(otherAccount).claim(2);
|
||||
expect(await nft.balanceOf(otherAccount.address)).to.equal(2);
|
||||
expect(await nftClaimer.totalCount()).to.equal(2);
|
||||
// @ts-ignore
|
||||
expect((await nftClaimer.connect(otherAccount).whiteCount())).to.equal(1);
|
||||
});
|
||||
it('should claim NFTS in parse2', async function() {
|
||||
const { nftClaimer, owner, otherAccount, ft, nft, chainId } = await loadFixture(deployOneContract);
|
||||
await nftClaimer.updateMintParse(2);
|
||||
const count = 4
|
||||
const price = 100
|
||||
await nftClaimer.addParse2WL([otherAccount.address])
|
||||
// @ts-ignore
|
||||
expect((await nftClaimer.connect(otherAccount).whiteCount())).to.equal(count);
|
||||
const tokenAmount = price * count
|
||||
// @ts-ignore
|
||||
await ft.connect(otherAccount).approve(nftClaimer.target, tokenAmount)
|
||||
|
||||
// @ts-ignore
|
||||
await nftClaimer.connect(otherAccount).claim(count);
|
||||
expect(await nft.balanceOf(otherAccount.address)).to.equal(count);
|
||||
expect(await ft.balanceOf(owner.address)).to.equal(tokenAmount)
|
||||
});
|
||||
it('should revert claim NFT not in whitelist or exceed limit', async function() {
|
||||
const { nftClaimer, owner, otherAccount, ft, nft, chainId } = await loadFixture(deployOneContract);
|
||||
await nftClaimer.updateMintParse(1);
|
||||
//use ft.connect() to send a transaction from another account
|
||||
// @ts-ignore
|
||||
await ft.connect(otherAccount).approve(nftClaimer.target, 400)
|
||||
expect(await nftClaimer.nftAddress()).equal(nft.target);
|
||||
// @ts-ignore
|
||||
await expect(nftClaimer.connect(otherAccount).claim(4)).to.be.revertedWith(
|
||||
"NFTClaimer: not in whitelist or exceed limit"
|
||||
);
|
||||
});
|
||||
it('should revert claim NFT if the balance not enough', async function() {
|
||||
const { nftClaimer, owner, otherAccount, ft, nft, chainId } = await loadFixture(deployOneContract);
|
||||
await nftClaimer.updateMintParse(1);
|
||||
const price = 1001
|
||||
const mintConfig = [
|
||||
2000,
|
||||
ft.target,
|
||||
price,
|
||||
owner.address
|
||||
]
|
||||
await nftClaimer.updateMintConfig(mintConfig);
|
||||
// @ts-ignore
|
||||
await ft.connect(otherAccount).approve(nftClaimer.target, price)
|
||||
|
||||
// @ts-ignore
|
||||
await expect(nftClaimer.connect(otherAccount).claim(1)).to.be.revertedWith(
|
||||
"ERC20: transfer amount exceeds balance"
|
||||
);
|
||||
});
|
||||
it('should revert claim NFT if allowance not enough', async function() {
|
||||
const { nftClaimer, owner, otherAccount, ft, nft, chainId } = await loadFixture(deployOneContract);
|
||||
await nftClaimer.updateMintParse(1);
|
||||
const price = 100
|
||||
// @ts-ignore
|
||||
await ft.connect(otherAccount).approve(nftClaimer.target, price - 1)
|
||||
|
||||
// @ts-ignore
|
||||
await expect(nftClaimer.connect(otherAccount).claim(1)).to.be.revertedWith(
|
||||
"ERC20: insufficient allowance"
|
||||
);
|
||||
});
|
||||
|
||||
it('should revert claim NFT if the activity not open', async function() {
|
||||
const { nftClaimer, owner, otherAccount, ft, nft, chainId } = await loadFixture(deployOneContract);
|
||||
await nftClaimer.updateMintParse(0);
|
||||
const price = 100
|
||||
// @ts-ignore
|
||||
await ft.connect(otherAccount).approve(nftClaimer.target, price)
|
||||
|
||||
// @ts-ignore
|
||||
await expect(nftClaimer.connect(otherAccount).claim(1)).to.be.revertedWith(
|
||||
"NFTClaimer: not begin or ended"
|
||||
);
|
||||
});
|
||||
it('should revert claim NFT if the exceed max num', async function() {
|
||||
const { nftClaimer, owner, otherAccount, ft, nft, chainId } = await loadFixture(deployOneContract);
|
||||
await nftClaimer.updateMintParse(1);
|
||||
const price = 100
|
||||
const mintConfig = [
|
||||
1,
|
||||
ft.target,
|
||||
price,
|
||||
owner.address
|
||||
]
|
||||
await nftClaimer.updateMintConfig(mintConfig);
|
||||
|
||||
// @ts-ignore
|
||||
await ft.connect(otherAccount).approve(nftClaimer.target, price * 2)
|
||||
const nonce = (Math.random() * 1000) | 0;
|
||||
|
||||
|
||||
// @ts-ignore
|
||||
await expect(nftClaimer.connect(otherAccount).claim(2)).to.be.revertedWith(
|
||||
"NFTClaimer: exceed max supply"
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
})
|
Loading…
x
Reference in New Issue
Block a user