149 lines
7.1 KiB
TypeScript
149 lines
7.1 KiB
TypeScript
import { expect } from 'chai'
|
|
import hre from "hardhat";
|
|
import {
|
|
getBytes,
|
|
solidityPackedKeccak256,
|
|
} from 'ethers'
|
|
import {
|
|
loadFixture,
|
|
} from "@nomicfoundation/hardhat-toolbox/network-helpers";
|
|
|
|
describe('GameItemMall', function() {
|
|
async function deployOneContract() {
|
|
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 GameItemMall = await hre.ethers.getContractFactory("GameItemMall");
|
|
|
|
const mall = await GameItemMall.deploy( ft.target, verifier, verifier, 3600);
|
|
|
|
const chainId = hre.network.config.chainId
|
|
await operatorAllowlist.grantRegistrarRole(owner.address)
|
|
await operatorAllowlist.addAddressToAllowlist([mall.target])
|
|
return { mall, owner, otherAccount, verifier, ft, chainId };
|
|
}
|
|
describe("Deployment", function () {
|
|
it('should deploy GameIteMall with the correct verifier', async function() {
|
|
const { mall, verifier } = await loadFixture(deployOneContract);
|
|
expect(await mall.verifier()).to.equal(verifier);
|
|
});
|
|
it('should deploy GameItemMall with the correct FT address', async function() {
|
|
const { mall, ft } = await loadFixture(deployOneContract);
|
|
expect(await mall.erc20Supported(ft.target)).to.equal(true);
|
|
});
|
|
})
|
|
|
|
describe("buy", function () {
|
|
it('should buy item success', async function() {
|
|
const { mall, ft, otherAccount, owner, chainId } = await loadFixture(deployOneContract);
|
|
const amount = 100;
|
|
// @ts-ignore
|
|
await ft.connect(otherAccount).approve(mall.target, amount);
|
|
|
|
const nonce = (Math.random() * 1000) | 0;
|
|
const now = Date.now() / 1000 | 0;
|
|
const orderId = '100000001'
|
|
/**
|
|
function getMessageHash(
|
|
address _buyer,
|
|
address _passport,
|
|
uint256 _orderId,
|
|
address _currency,
|
|
uint256 _amount,
|
|
address _contract,
|
|
uint256 _chainId,
|
|
uint256 _signTime,
|
|
uint256 _saltNonce
|
|
)
|
|
*/
|
|
let localMsgHash = solidityPackedKeccak256(["address","address", "uint256", "address", "uint256", "address", "uint256", "uint256", "uint256"],
|
|
[otherAccount.address, otherAccount.address, orderId, ft.target, amount, mall.target, chainId, now, nonce]);
|
|
const signature = await owner.signMessage(getBytes(localMsgHash));
|
|
/**
|
|
* function buy(
|
|
address passport,
|
|
uint256 orderId,
|
|
address currency,
|
|
uint256 amount,
|
|
uint256 signTime,
|
|
uint256 saltNonce,
|
|
bytes calldata signature
|
|
)
|
|
*/
|
|
//@ts-ignore
|
|
await expect(mall.connect(otherAccount).buy(otherAccount.address, orderId, ft.target, amount, now, nonce, signature))
|
|
.to.emit(mall, "ItemSoldOut")
|
|
.withArgs(otherAccount.address, otherAccount.address, orderId, ft.target, amount);
|
|
expect(await ft.balanceOf(otherAccount.address)).to.equal(900);
|
|
});
|
|
|
|
it('should revert buy item for signature error', async function() {
|
|
const { mall, ft, otherAccount, owner, chainId } = await loadFixture(deployOneContract);
|
|
const amount = 100;
|
|
// @ts-ignore
|
|
await ft.connect(otherAccount).approve(mall.target, amount);
|
|
const nonce = (Math.random() * 1000) | 0;
|
|
const now = Date.now() / 1000 | 0;
|
|
const orderId = '100000001'
|
|
let localMsgHash = solidityPackedKeccak256(["address","address", "uint256", "address", "uint256", "address", "uint256", "uint256", "uint256"],
|
|
[otherAccount.address, otherAccount.address, orderId, ft.target, amount, mall.target, chainId, now, nonce]);
|
|
const signature = await owner.signMessage(getBytes(localMsgHash));
|
|
//@ts-ignore
|
|
await expect(mall.connect(otherAccount).buy(otherAccount.address, orderId, ft.target, amount + 1, now, nonce, signature)).to.be.revertedWith("invalid signature");
|
|
});
|
|
|
|
it('should revert buy item for not approval', async function() {
|
|
const { mall, ft, otherAccount, owner, chainId } = await loadFixture(deployOneContract);
|
|
const amount = 100;
|
|
const nonce = (Math.random() * 1000) | 0;
|
|
const now = Date.now() / 1000 | 0;
|
|
const orderId = '100000001'
|
|
let localMsgHash = solidityPackedKeccak256(["address","address", "uint256", "address", "uint256", "address", "uint256", "uint256", "uint256"],
|
|
[otherAccount.address, otherAccount.address, orderId, ft.target, amount, mall.target, chainId, now, nonce]);
|
|
const signature = await owner.signMessage(getBytes(localMsgHash));
|
|
//@ts-ignore
|
|
await expect(mall.connect(otherAccount).buy(otherAccount.address, orderId, ft.target, amount, now, nonce, signature)).to.be.revertedWith("ERC20: insufficient allowance");
|
|
});
|
|
|
|
it('should revert buy item for signature used', async function() {
|
|
const { mall, ft, otherAccount, owner, chainId } = await loadFixture(deployOneContract);
|
|
const amount = 100;
|
|
// @ts-ignore
|
|
await ft.connect(otherAccount).approve(mall.target, amount);
|
|
const nonce = (Math.random() * 1000) | 0;
|
|
const now = Date.now() / 1000 | 0;
|
|
const orderId = '100000001'
|
|
let localMsgHash = solidityPackedKeccak256(["address","address", "uint256", "address", "uint256", "address", "uint256", "uint256", "uint256"],
|
|
[otherAccount.address, otherAccount.address, orderId, ft.target, amount, mall.target, chainId, now, nonce]);
|
|
const signature = await owner.signMessage(getBytes(localMsgHash));
|
|
//@ts-ignore
|
|
await mall.connect(otherAccount).buy(otherAccount.address, orderId, ft.target, amount, now, nonce, signature)
|
|
//@ts-ignore
|
|
await expect(mall.connect(otherAccount).buy(otherAccount.address, orderId, ft.target, amount, now, nonce, signature)).to.be.revertedWith("signature used. please send another transaction with new signature");
|
|
});
|
|
|
|
it('should revert buy item for unsupport currency', async function() {
|
|
const { mall, ft, otherAccount, owner, chainId } = await loadFixture(deployOneContract);
|
|
const amount = 100;
|
|
// @ts-ignore
|
|
await ft.connect(otherAccount).approve(mall.target, amount);
|
|
const nonce = (Math.random() * 1000) | 0;
|
|
const now = Date.now() / 1000 | 0;
|
|
const orderId = '100000001'
|
|
await mall.removeERC20Support(ft.target);
|
|
let localMsgHash = solidityPackedKeccak256(["address","address", "uint256", "address", "uint256", "address", "uint256", "uint256", "uint256"],
|
|
[otherAccount.address, otherAccount.address, orderId, ft.target, amount, mall.target, chainId, now, nonce]);
|
|
const signature = await owner.signMessage(getBytes(localMsgHash));
|
|
//@ts-ignore
|
|
await expect(mall.connect(otherAccount).buy(otherAccount.address, orderId, ft.target, amount, now, nonce, signature)).to.be.revertedWith("currency is not supported");
|
|
});
|
|
})
|
|
})
|