contracts-imtbl/test/testNFTClaim.ts

260 lines
12 KiB
TypeScript

import { expect } from 'chai'
import hre from "hardhat";
import {
getBytes,
solidityPackedKeccak256,
} from 'ethers'
import {
loadFixture,
} from "@nomicfoundation/hardhat-toolbox/network-helpers";
describe('NFTClaimStage2', 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("NFTClaimStage2");
const mintConfig = [
1000,
2000,
ft.target,
100,
owner.address
]
const nftClaimer = await NFTClaimStage2.deploy( nftAddress, verifier, mintConfig);
await nft.grantMinterRole(nftClaimer.target)
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 } = await loadFixture(deployOneContract);
expect((await nftClaimer.mintConfig()).mintPrice).to.equal(100);
});
it('should deploy NFTClaimStage2 with the correct verifier', async function() {
const { nftClaimer, verifier } = await loadFixture(deployOneContract);
expect(await nftClaimer.verifier()).to.equal(verifier);
});
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 = [
1000,
2000,
'0xaa34B79A0Ab433eaC900fB3CB9f191F5Cd27501D',
200,
'0x5Ab03Aa79Ab91B7420b5CFF134a4188388888888'
]
await nftClaimer.updateMintConfig(mintConfig);
expect((await nftClaimer.mintConfig()).mintPrice).to.equal(200);
});
it('should update verifier', async function() {
const { nftClaimer, otherAccount } = await loadFixture(deployOneContract);
await nftClaimer.updateVerifier(otherAccount.address);
expect(await nftClaimer.verifier()).to.equal(otherAccount.address);
});
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);
const price = 100
//use ft.connect() to send a transaction from another account
// @ts-ignore
await ft.connect(otherAccount).approve(nftClaimer.target, price)
const nonce = (Math.random() * 1000) | 0;
const ids = ['1002']
let localMsgHash = solidityPackedKeccak256(["address", "address", "uint256", "address", "uint256", "uint256", ...ids.map(() => "uint256")],
[otherAccount.address, nft.target, price, nftClaimer.target, chainId, nonce, ...ids]);
const contractMsgHash = await nftClaimer.getMessageHash(
otherAccount.address, nft.target, ids, price, nftClaimer.target, chainId, nonce
)
expect(localMsgHash).equal(contractMsgHash);
expect(await nftClaimer.verifier()).equal(owner.address);
expect(await nftClaimer.nftAddress()).equal(nft.target);
const signature = await owner.signMessage(getBytes(contractMsgHash));
// @ts-ignore
await nftClaimer.connect(otherAccount).claim(ids, price, nonce, signature);
expect(await nft.balanceOf(otherAccount.address)).to.equal(1);
expect(await nftClaimer.totalCount()).to.equal(1);
});
it('should claim NFTS', async function() {
const { nftClaimer, owner, otherAccount, ft, nft, chainId } = await loadFixture(deployOneContract);
await nftClaimer.updateMintParse(1);
const price = 100
const ids = ['1002', '1003', '1004']
const tokenAmount = price * ids.length
// @ts-ignore
await ft.connect(otherAccount).approve(nftClaimer.target, tokenAmount)
const nonce = (Math.random() * 1000) | 0;
let localMsgHash = solidityPackedKeccak256(["address", "address", "uint256", "address", "uint256", "uint256", ...ids.map(() => "uint256")],
[otherAccount.address, nft.target, tokenAmount, nftClaimer.target, chainId, nonce, ...ids]);
const signature = await owner.signMessage(getBytes(localMsgHash));
// @ts-ignore
await nftClaimer.connect(otherAccount).claim(ids, tokenAmount, nonce, signature);
expect(await nft.balanceOf(otherAccount.address)).to.equal(ids.length);
expect(await ft.balanceOf(owner.address)).to.equal(tokenAmount)
});
it('should revert claim NFT if the signature error', 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)
const nonce = (Math.random() * 1000) | 0;
const ids = ['1002']
let localMsgHash = solidityPackedKeccak256(["address", "address", "uint256", "address", "uint256", "uint256", ...ids.map(() => "uint256")],
[otherAccount.address, nft.target, price, nftClaimer.target, chainId, nonce, ...ids]);
const signature = await owner.signMessage(getBytes(localMsgHash));
const nonce2 = (Math.random() * 1000) | 0;
// @ts-ignore
await expect(nftClaimer.connect(otherAccount).claim(ids, price, nonce2, signature)).to.be.revertedWith(
"invalid signature"
);
});
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 = [
1000,
2000,
ft.target,
price,
owner.address
]
await nftClaimer.updateMintConfig(mintConfig);
// @ts-ignore
await ft.connect(otherAccount).approve(nftClaimer.target, price)
const nonce = (Math.random() * 1000) | 0;
const ids = ['1002']
let localMsgHash = solidityPackedKeccak256(["address", "address", "uint256", "address", "uint256", "uint256", ...ids.map(() => "uint256")],
[otherAccount.address, nft.target, price, nftClaimer.target, chainId, nonce, ...ids]);
const signature = await owner.signMessage(getBytes(localMsgHash));
// @ts-ignore
await expect(nftClaimer.connect(otherAccount).claim(ids, price, nonce, signature)).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)
const nonce = (Math.random() * 1000) | 0;
const ids = ['1002']
let localMsgHash = solidityPackedKeccak256(["address", "address", "uint256", "address", "uint256", "uint256", ...ids.map(() => "uint256")],
[otherAccount.address, nft.target, price, nftClaimer.target, chainId, nonce, ...ids]);
const signature = await owner.signMessage(getBytes(localMsgHash));
// @ts-ignore
await expect(nftClaimer.connect(otherAccount).claim(ids, price, nonce, signature)).to.be.revertedWith(
"ERC20: insufficient allowance"
);
});
it('should revert claim NFT if the price not correct', async function() {
const { nftClaimer, owner, otherAccount, ft, nft, chainId } = await loadFixture(deployOneContract);
await nftClaimer.updateMintParse(1);
const price = 99
// @ts-ignore
await ft.connect(otherAccount).approve(nftClaimer.target, price)
const nonce = (Math.random() * 1000) | 0;
const ids = ['1002']
let localMsgHash = solidityPackedKeccak256(["address", "address", "uint256", "address", "uint256", "uint256", ...ids.map(() => "uint256")],
[otherAccount.address, nft.target, price, nftClaimer.target, chainId, nonce, ...ids]);
const signature = await owner.signMessage(getBytes(localMsgHash));
// @ts-ignore
await expect(nftClaimer.connect(otherAccount).claim(ids, price, nonce, signature)).to.be.revertedWith(
"NFTClaimer: insufficient token amount"
);
});
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)
const nonce = (Math.random() * 1000) | 0;
const ids = ['1002']
let localMsgHash = solidityPackedKeccak256(["address", "address", "uint256", "address", "uint256", "uint256", ...ids.map(() => "uint256")],
[otherAccount.address, nft.target, price, nftClaimer.target, chainId, nonce, ...ids]);
const signature = await owner.signMessage(getBytes(localMsgHash));
// @ts-ignore
await expect(nftClaimer.connect(otherAccount).claim(ids, price, nonce, signature)).to.be.revertedWith(
"NFTClaimer: not begin or ended"
);
});
it('should revert claim NFT if the exceed parse1 max num', async function() {
const { nftClaimer, owner, otherAccount, ft, nft, chainId } = await loadFixture(deployOneContract);
await nftClaimer.updateMintParse(1);
const price = 100
const mintConfig = [
1,
2000,
ft.target,
price,
owner.address
]
await nftClaimer.updateMintConfig(mintConfig);
const ids = ['1002', '1003']
// @ts-ignore
await ft.connect(otherAccount).approve(nftClaimer.target, price * ids.length)
const nonce = (Math.random() * 1000) | 0;
let localMsgHash = solidityPackedKeccak256(["address", "address", "uint256", "address", "uint256", "uint256", ...ids.map(() => "uint256")],
[otherAccount.address, nft.target, price * ids.length, nftClaimer.target, chainId, nonce, ...ids]);
const signature = await owner.signMessage(getBytes(localMsgHash));
// @ts-ignore
await expect(nftClaimer.connect(otherAccount).claim(ids, price, nonce, signature)).to.be.revertedWith(
"NFTClaimer: exceed parse 1 max supply"
);
});
it('should revert claim NFT if the exceed total num', async function() {
const { nftClaimer, owner, otherAccount, ft, nft, chainId } = await loadFixture(deployOneContract);
await nftClaimer.updateMintParse(2);
const price = 100
const mintConfig = [
1000,
1,
ft.target,
price,
owner.address
]
await nftClaimer.updateMintConfig(mintConfig);
const ids = ['1002', '1003']
// @ts-ignore
await ft.connect(otherAccount).approve(nftClaimer.target, price * ids.length)
const nonce = (Math.random() * 1000) | 0;
let localMsgHash = solidityPackedKeccak256(["address", "address", "uint256", "address", "uint256", "uint256", ...ids.map(() => "uint256")],
[otherAccount.address, nft.target, price * ids.length, nftClaimer.target, chainId, nonce, ...ids]);
const signature = await owner.signMessage(getBytes(localMsgHash));
// @ts-ignore
await expect(nftClaimer.connect(otherAccount).claim(ids, price, nonce, signature)).to.be.revertedWith(
"NFTClaimer: exceed max supply"
);
});
});
})