From d85411e8d955e29f55b01678c8c2b3ad2b204fbd Mon Sep 17 00:00:00 2001 From: owen05 Date: Mon, 24 May 2021 20:32:05 +0800 Subject: [PATCH] drops testing --- .../impl/NFTCollateralVault.sol | 9 ++ contracts/DODODrops/DODODropsV2/BaseDrops.sol | 27 ++-- .../DODODrops/DODODropsV2/DropsERC1155.sol | 27 +++- .../DODODrops/DODODropsV2/DropsERC721.sol | 14 +- contracts/Factory/UpCrowdPoolingFactory.sol | 2 +- migrations/5_deploy_nft.js | 8 +- test/DODODrops/dropsV2-fixedAmount.test.ts | 108 +++++++++++++++ test/utils/Contracts.ts | 8 +- test/utils/DropsContext.ts | 129 ++++++++++++++++++ truffle-test.sh | 5 + 10 files changed, 315 insertions(+), 22 deletions(-) create mode 100644 test/DODODrops/dropsV2-fixedAmount.test.ts create mode 100644 test/utils/DropsContext.ts diff --git a/contracts/CollateralVault/impl/NFTCollateralVault.sol b/contracts/CollateralVault/impl/NFTCollateralVault.sol index 03f6756..2bf7ac1 100644 --- a/contracts/CollateralVault/impl/NFTCollateralVault.sol +++ b/contracts/CollateralVault/impl/NFTCollateralVault.sol @@ -37,6 +37,15 @@ contract NFTCollateralVault is InitializableOwnable, IERC721Receiver, IERC1155Re event RemoveNftToken(address nftContract, uint256 tokenId, uint256 amount); event AddNftToken(address nftContract, uint256 tokenId, uint256 amount); + // ============ TransferFrom NFT ============ + function depositERC721(address nftContract, uint256[] memory tokenIds) public { + + } + + function depoistERC1155(address nftContract, uint256[] memory tokenIds, uint256[] memory amounts) public { + + } + // ============ Ownable ============ function directTransferOwnership(address newOwner) external onlyOwner { diff --git a/contracts/DODODrops/DODODropsV2/BaseDrops.sol b/contracts/DODODrops/DODODropsV2/BaseDrops.sol index bac4a99..ce45bbf 100644 --- a/contracts/DODODrops/DODODropsV2/BaseDrops.sol +++ b/contracts/DODODrops/DODODropsV2/BaseDrops.sol @@ -82,15 +82,13 @@ contract BaseDrops is InitializableMintableERC20, ReentrancyGuard { function init( address[] memory addrList, //0 owner, 1 buyToken, 2 feeModel, 3 defaultMaintainer 4 rng 5 nftToken - uint256[][] memory sellingInfoList, //0 sellingTimeInterval, 1 sellingPrice, 2 sellingAmount - uint256[] memory probInterval, - uint256[][] memory tokenIdMap, - uint256[] memory tokenIdList, + uint256[] memory sellingTimeInterval, + uint256[] memory sellingPrice, + uint256[] memory sellingAmount, uint256 redeemAllowedTime, bool isRevealMode, bool isProbMode ) public { - initOwner(addrList[0]); _BUY_TOKEN_ = addrList[1]; _FEE_MODEL_ = addrList[2]; _MAINTAINER_ = payable(addrList[3]); @@ -101,18 +99,21 @@ contract BaseDrops is InitializableMintableERC20, ReentrancyGuard { _IS_PROB_MODE_ = isProbMode; _REDEEM_ALLOWED_TIME_ = redeemAllowedTime; - if(sellingInfoList.length > 0) _setSellingInfo(sellingInfoList[0], sellingInfoList[1], sellingInfoList[2]); + if(sellingTimeInterval.length > 0) _setSellingInfo(sellingTimeInterval, sellingPrice, sellingAmount); - if(isProbMode) { - if(probInterval.length > 0) _setProbInfo(probInterval, tokenIdMap); - }else { - if(tokenIdList.length > 0) _setFixedAmountInfo(tokenIdList); - } + // if(isProbMode) { + // // (uint256[][] memory tokenIdMap) = abi.decode(tokenIdMapBytes, (uint256[][])); + // // if(probInterval.length > 0) _setProbInfo(probInterval, tokenIdMap); + // }else { + // // if(tokenIdList.length > 0) _setFixedAmountInfo(tokenIdList); + // } string memory prefix = "DROPS_"; name = string(abi.encodePacked(prefix, addressToShortString(address(this)))); symbol = name; decimals = 0; + + //init Owner super.init(addrList[0], 0, name, symbol, decimals); } @@ -238,7 +239,9 @@ contract BaseDrops is InitializableMintableERC20, ReentrancyGuard { _setSellingInfo(sellingTimeIntervals, prices, amounts); } - function setProbInfo(uint256[] memory probIntervals,uint256[][] memory tokenIdMap) external notStart() onlyOwner { + //TODO: 待测试 + function setProbInfo(uint256[] memory probIntervals,bytes memory tokenIdMapBytes) external notStart() onlyOwner { + (uint256[][] memory tokenIdMap) = abi.decode(tokenIdMapBytes, (uint256[][])); _setProbInfo(probIntervals, tokenIdMap); } diff --git a/contracts/DODODrops/DODODropsV2/DropsERC1155.sol b/contracts/DODODrops/DODODropsV2/DropsERC1155.sol index 0ab8275..938bddc 100644 --- a/contracts/DODODrops/DODODropsV2/DropsERC1155.sol +++ b/contracts/DODODrops/DODODropsV2/DropsERC1155.sol @@ -6,12 +6,15 @@ */ pragma solidity 0.6.9; +pragma experimental ABIEncoderV2; import {ERC1155} from "../../external/ERC1155/ERC1155.sol"; import {InitializableOwnable} from "../../lib/InitializableOwnable.sol"; contract DropsERC1155 is ERC1155, InitializableOwnable { mapping (address => bool) public _IS_ALLOWED_MINT_; + mapping (uint256 => string) private _tokenURIs; + string internal _baseUri = ""; // ============ Event ============= event addMinter(address account); @@ -32,11 +35,33 @@ contract DropsERC1155 is ERC1155, InitializableOwnable { string memory uri ) public { initOwner(owner); - _setURI(uri); + _baseUri = uri; } function mint(address account, uint256 id, uint256 amount, bytes memory data) external { require(_IS_ALLOWED_MINT_[msg.sender], "Mint restricted"); _mint(account, id, amount, data); } + + function batchSetTokenURI(uint256[] calldata ids, string[] calldata urls) external onlyOwner { + require(ids.length == urls.length, "NOT_MATCH"); + for(uint256 i = 0; i < ids.length; i++) { + _setTokenURI(ids[i], urls[i]); + } + } + + function uri(uint256 tokenId) public view override returns (string memory) { + string memory _tokenURI = _tokenURIs[tokenId]; + string memory base = _baseUri; + + if (bytes(base).length == 0) { + return _tokenURI; + } + + return string(abi.encodePacked(base, _tokenURI)); + } + + function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal { + _tokenURIs[tokenId] = _tokenURI; + } } \ No newline at end of file diff --git a/contracts/DODODrops/DODODropsV2/DropsERC721.sol b/contracts/DODODrops/DODODropsV2/DropsERC721.sol index c283576..576f6f8 100644 --- a/contracts/DODODrops/DODODropsV2/DropsERC721.sol +++ b/contracts/DODODrops/DODODropsV2/DropsERC721.sol @@ -6,11 +6,12 @@ */ pragma solidity 0.6.9; +pragma experimental ABIEncoderV2; -import {ERC721} from "../../external/ERC721/ERC721.sol"; +import {ERC721URIStorage} from "../../external/ERC721/ERC721URIStorage.sol"; import {InitializableOwnable} from "../../lib/InitializableOwnable.sol"; -contract DropsERC721 is ERC721, InitializableOwnable { +contract DropsERC721 is ERC721URIStorage, InitializableOwnable { mapping (address => bool) public _IS_ALLOWED_MINT_; // ============ Event ============= @@ -40,7 +41,14 @@ contract DropsERC721 is ERC721, InitializableOwnable { } function mint(address to, uint256 tokenId) external { - require(_IS_ALLOWED_MINT_[msg.sender], "Mint restricted"); + require(_IS_ALLOWED_MINT_[msg.sender], "restricted"); _mint(to, tokenId); } + + function batchSetTokenURI(uint256[] calldata ids, string[] calldata urls) external onlyOwner { + require(ids.length == urls.length, "NOT_MATCH"); + for(uint256 i = 0; i < ids.length; i++) { + _setTokenURI(ids[i], urls[i]); + } + } } \ No newline at end of file diff --git a/contracts/Factory/UpCrowdPoolingFactory.sol b/contracts/Factory/UpCrowdPoolingFactory.sol index e46e9db..4cc9ae9 100644 --- a/contracts/Factory/UpCrowdPoolingFactory.sol +++ b/contracts/Factory/UpCrowdPoolingFactory.sol @@ -34,7 +34,7 @@ contract UpCrowdPoolingFactory is InitializableOwnable { // ============ Settings ============= uint256 public _FREEZE_DURATION_ = 30 days; - uint256 public _CALM_DURATION_ = 0; + uint256 public _CALM_DURATION_ = 600; uint256 public _VEST_DURATION_ = 0; uint256 public _CLIFF_RATE_ = 10**18; diff --git a/migrations/5_deploy_nft.js b/migrations/5_deploy_nft.js index 6fda4a4..45b0747 100644 --- a/migrations/5_deploy_nft.js +++ b/migrations/5_deploy_nft.js @@ -15,7 +15,7 @@ const InitializableERC721 = artifacts.require("InitializableERC721"); const InitializableERC1155 = artifacts.require("InitializableERC1155"); const NFTTokenFactory = artifacts.require("NFTTokenFactory"); -const MysteryBoxV1 = artifacts.require("MysteryBoxV1"); +const DODODropsV1 = artifacts.require("DODODropsV1"); const RandomGenerator = artifacts.require("RandomGenerator"); module.exports = async (deployer, network, accounts) => { @@ -61,10 +61,10 @@ module.exports = async (deployer, network, accounts) => { } if (MysteryBoxV1Address == "") { - await deployer.deploy(MysteryBoxV1); - MysteryBoxV1Address = MysteryBoxV1.address; + await deployer.deploy(DODODropsV1); + MysteryBoxV1Address = DODODropsV1.address; logger.log("MysteryBoxV1Address: ", MysteryBoxV1Address); - const MysteryBoxV1Instance = await MysteryBoxV1.at(MysteryBoxV1Address); + const MysteryBoxV1Instance = await DODODropsV1.at(MysteryBoxV1Address); var tx = await MysteryBoxV1Instance.init( "DODOMysteryBox", "DODOBox", diff --git a/test/DODODrops/dropsV2-fixedAmount.test.ts b/test/DODODrops/dropsV2-fixedAmount.test.ts new file mode 100644 index 0000000..8fdd652 --- /dev/null +++ b/test/DODODrops/dropsV2-fixedAmount.test.ts @@ -0,0 +1,108 @@ +/* + + Copyright 2020 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ +import { decimalStr, fromWei } from '../utils/Converter'; +import { logGas } from '../utils/Log'; +import { assert } from 'chai'; +import * as contracts from '../utils/Contracts'; +import { Contract } from 'web3-eth-contract'; +import { DropsContext, getDropsContext } from '../utils/DropsContext'; +const truffleAssert = require('truffle-assertions'); + +let maintainer: string; +let user1: string; +let user2: string; +let user3: string; + +async function init(ctx: DropsContext): Promise { + maintainer = ctx.SpareAccounts[0]; + user1 = ctx.SpareAccounts[1]; + user2 = ctx.SpareAccounts[2]; + user3 = ctx.SpareAccounts[3]; + + await ctx.mintTestToken(user1, ctx.DODO, decimalStr("10000")); + await ctx.mintTestToken(user2, ctx.DODO, decimalStr("10000")); + await ctx.mintTestToken(user3, ctx.DODO, decimalStr("10000")); + await ctx.approveProxy(ctx.DODO, user1); + await ctx.approveProxy(ctx.DODO, user2); + await ctx.approveProxy(ctx.DODO, user3); + + var addrList = [ + ctx.Deployer, + ctx.DODO.options.address, + ctx.DropsFeeModel.options.address, + maintainer, + "0x0000000000000000000000000000000000000000", + ctx.DropsERC721.options.address + ] + + var curTime = Math.floor(new Date().getTime() / 1000) + + await ctx.DropsV2.methods.init( + addrList, + [curTime + 10, curTime + 20, curTime + 30], + [10000000000000, 10000000000000, 10000000000000], + [10, 10, 0], + curTime+10, + true, + false + ).send(ctx.sendParam(ctx.Deployer)); + +} + +async function getTicketsInfo(ctx: DropsContext, user: string): Promise<[string, string]> { + var totalTickets = await ctx.DropsV2.methods.totalSupply().call(); + var userTickets = await ctx.DropsV2.methods.balanceOf(user).call(); + console.log("User Tickets:" + userTickets + " totalTickets:" + totalTickets); + return [totalTickets, userTickets]; +} + +async function getBuyTokenBalance(ctx: DropsContext, user: string, token: Contract): Promise<[string,string]> { + var userDodo = await token.methods.balanceOf(user).call(); + var dropsDodo = await token.methods.balanceOf(ctx.DropsV2.options.address).call(); + console.log("User Dodo:" + userDodo + " Drops Dodo:" + dropsDodo); + return [userDodo, dropsDodo]; +} + + +describe("DODODropsV2", () => { + let snapshotId: string; + let ctx: DropsContext; + + before(async () => { + ctx = await getDropsContext(); + await init(ctx); + }); + + beforeEach(async () => { + snapshotId = await ctx.EVM.snapshot(); + }); + + afterEach(async () => { + await ctx.EVM.reset(snapshotId); + }); + + describe("DODODropsV2", () => { + it("buyTicket", async () => { + // await ctx.EVM.increaseTime(10); + // await logGas(await ctx.DropsProxy.methods.buyTickets(ctx.DropsV2.options.address,2), ctx.sendParam(user1), "buyTickets"); + // await logGas(await ctx.DropsProxy.methods.buyTickets(ctx.DropsV2.options.address,3), ctx.sendParam(user2), "buyTickets"); + + // await getTicketsInfo(ctx, user1) + // await getTicketsInfo(ctx, user2) + + // await getBuyTokenBalance(ctx, user1, ctx.DODO) + // await getBuyTokenBalance(ctx, user2, ctx.DODO) + }); + + it("redeemPrize", async () => { + + }); + + //Owner 设置 + + }); +}); diff --git a/test/utils/Contracts.ts b/test/utils/Contracts.ts index bee1cd5..1c7a2a5 100644 --- a/test/utils/Contracts.ts +++ b/test/utils/Contracts.ts @@ -65,7 +65,13 @@ export const NFT_REGISTER = "DODONFTRegistry" export const NFT_PROXY = "DODONFTProxy" export const RANDOM_GENERATOR = "RandomGenerator" -export const MYSTERY_BOX_V1 = "MysteryBoxV1" +export const MYSTERY_BOX_V1 = "DODODropsV1" + +export const DROPS_V2 = "BaseDrops" +export const DROPS_ERC721 = "DropsERC721" +export const DROPS_ERC1155 = "DropsERC1155" +export const DROPS_FEE_MODEL = "DropsFeeModel" +export const DROPS_PROXY = "DODODropsProxy" interface ContractJson { abi: any; diff --git a/test/utils/DropsContext.ts b/test/utils/DropsContext.ts new file mode 100644 index 0000000..23766c7 --- /dev/null +++ b/test/utils/DropsContext.ts @@ -0,0 +1,129 @@ +/* + + Copyright 2021 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ + +import BigNumber from 'bignumber.js'; +import Web3 from 'web3'; +import { Contract } from 'web3-eth-contract'; + +import * as contracts from './Contracts'; +import { decimalStr, mweiStr, MAX_UINT256 } from './Converter'; +import { EVM, getDefaultWeb3 } from './EVM'; +import * as log from './Log'; + +BigNumber.config({ + EXPONENTIAL_AT: 1000, + DECIMAL_PLACES: 80, +}); + + +export class DropsContext { + EVM: EVM; + Web3: Web3; + + DropsV2: Contract; + DropsERC721: Contract; + DropsERC1155: Contract; + DropsFeeModel: Contract; + + DropsProxy: Contract; + DODOApprove: Contract; + DODOApproveProxy: Contract; + + //token + DODO: Contract; + + Deployer: string; + Maintainer: string; + SpareAccounts: string[]; + + constructor() { } + + async init() { + this.EVM = new EVM(); + this.Web3 = getDefaultWeb3(); + const allAccounts = await this.Web3.eth.getAccounts(); + this.Deployer = allAccounts[0]; + this.Maintainer = allAccounts[1]; + this.SpareAccounts = allAccounts.slice(2, 10); + + this.DODO = await contracts.newContract( + contracts.MINTABLE_ERC20_CONTRACT_NAME, + ["DODO Token", "DODO", 18] + ); + + this.DropsFeeModel = await contracts.newContract( + contracts.DROPS_FEE_MODEL + ) + + await this.DropsFeeModel.methods.initOwner(this.Deployer).send(this.sendParam(this.Deployer)); + + this.DropsERC721 = await contracts.newContract( + contracts.DROPS_ERC721 + ) + + await this.DropsERC721.methods.init(this.Deployer, "","","").send(this.sendParam(this.Deployer)); + + + this.DropsERC1155 = await contracts.newContract( + contracts.DROPS_ERC1155 + ) + + await this.DropsERC1155.methods.init(this.Deployer, "").send(this.sendParam(this.Deployer)); + + this.DODOApprove = await contracts.newContract( + contracts.SMART_APPROVE + ); + + this.DODOApproveProxy = await contracts.newContract( + contracts.SMART_APPROVE_PROXY, + [this.DODOApprove.options.address] + ) + + this.DropsProxy = await contracts.newContract(contracts.DROPS_PROXY, + [ + this.DODOApproveProxy.options.address + ] + ) + + this.DropsV2 = await contracts.newContract( + contracts.DROPS_V2 + ); + + await this.DropsERC721.methods.addMintAccount(this.DropsProxy.options.address).send(this.sendParam(this.Deployer)); + await this.DropsERC1155.methods.addMintAccount(this.DropsProxy.options.address).send(this.sendParam(this.Deployer)); + + await this.DODOApprove.methods.init(this.Deployer, this.DODOApproveProxy.options.address).send(this.sendParam(this.Deployer)); + await this.DODOApproveProxy.methods.init(this.Deployer, [this.DropsProxy.options.address]).send(this.sendParam(this.Deployer)); + + console.log(log.blueText("[Init DODODrops context]")); + } + + sendParam(sender, value = "0") { + return { + from: sender, + gas: process.env["COVERAGE"] ? 10000000000 : 7000000, + gasPrice: mweiStr("1000"), + value: decimalStr(value), + }; + } + + async mintTestToken(to: string, token: Contract, amount: string) { + await token.methods.mint(to, amount).send(this.sendParam(this.Deployer)); + } + + async approveProxy(token: Contract, account: string) { + await token.methods + .approve(this.DODOApprove.options.address, MAX_UINT256) + .send(this.sendParam(account)); + } +} + +export async function getDropsContext(): Promise { + var context = new DropsContext(); + await context.init(); + return context; +} diff --git a/truffle-test.sh b/truffle-test.sh index 18fd135..87b5252 100644 --- a/truffle-test.sh +++ b/truffle-test.sh @@ -66,6 +66,11 @@ then truffle test ./test/DODONFT/mysteryBoxV1.test.ts fi +if [ "$1"x = "boxV2"x ] +then + truffle test ./test/DODODrops/dropsV2-fixedAmount.test.ts +fi + # if [ "$1"x = "route-incentive"x ] # then # truffle test ./test/Route/Incentive.test.ts