1import {EthUniqueHelper, usingEthPlaygrounds} from '../../eth/util';2import {readFile} from 'fs/promises';3import {IKeyringPair} from '@polkadot/types/types';4import {Contract} from 'web3-eth-contract';5import {convertToTokens} from '../utils/common';6import {makeNames} from '../../util';7import {ContractImports} from '../../eth/util/playgrounds/types';8import {RMRKNestableMintable} from './ABIGEN';910const {dirname} = makeNames(import.meta.url);1112export const CONTRACT_IMPORT: ContractImports[] = [13 {14 fsPath: `${dirname}/../../../node_modules/@rmrk-team/evm-contracts/contracts/RMRK/nestable/RMRKNestable.sol`,15 solPath: '@rmrk-team/evm-contracts/contracts/RMRK/nestable/RMRKNestable.sol',16 },17 {18 fsPath: `${dirname}/../../../node_modules/@rmrk-team/evm-contracts/contracts/RMRK/nestable/IERC6059.sol`,19 solPath: '@rmrk-team/evm-contracts/contracts/RMRK/nestable/IERC6059.sol',20 },21 {22 fsPath: `${dirname}/../../../node_modules/@rmrk-team/evm-contracts/contracts/RMRK/core/RMRKCore.sol`,23 solPath: '@rmrk-team/evm-contracts/contracts/RMRK/core/RMRKCore.sol',24 },25 {26 fsPath: `${dirname}/../../../node_modules/@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol`,27 solPath: '@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol',28 },29 {30 fsPath: `${dirname}/../../../node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol`,31 solPath: '@openzeppelin/contracts/token/ERC721/IERC721.sol',32 },33 {34 fsPath: `${dirname}/../../../node_modules/@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol`,35 solPath: '@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol',36 },37 {38 fsPath: `${dirname}/../../../node_modules/@openzeppelin/contracts/utils/Address.sol`,39 solPath: '@openzeppelin/contracts/utils/Address.sol',40 },41 {42 fsPath: `${dirname}/../../../node_modules/@openzeppelin/contracts/utils/Context.sol`,43 solPath: '@openzeppelin/contracts/utils/Context.sol',44 },45 {46 fsPath: `${dirname}/../../../node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol`,47 solPath: '@openzeppelin/contracts/utils/introspection/IERC165.sol',48 },49 {50 fsPath: `${dirname}/../../../node_modules/@rmrk-team/evm-contracts/contracts/RMRK/library/RMRKErrors.sol`,51 solPath: '@rmrk-team/evm-contracts/contracts/RMRK/library/RMRKErrors.sol',52 },53 {54 fsPath: `${dirname}/../../../node_modules/@rmrk-team/evm-contracts/contracts/RMRK/core/IRMRKCore.sol`,55 solPath: '@rmrk-team/evm-contracts/contracts/RMRK/core/IRMRKCore.sol',56 },57 {58 fsPath: `${dirname}/RMRKNestableMintable.sol`,59 solPath: 'RMRKNestableMintable.sol',60 },61];626364const main = async () => {6566 await usingEthPlaygrounds(async (helper, privateKey) => {6768 const donor = await privateKey('//Alice'); 6970 const eth = await measureEth(helper, donor);71 const sub = await measureSub(helper, donor);72 const rmrk = await measureRMRK(helper, donor);73 console.table({susbtrate: sub, eth: eth, rmrk: rmrk});74 });75};7677async function measureRMRK(helper: EthUniqueHelper, donor: IKeyringPair) {78 const CONTRACT_SOURCE = (79 await readFile(`${dirname}/RMRKNestableMintable.sol`)80 ).toString();81 const RELAYER_SOURCE = (await readFile(`${dirname}/relayer.sol`)).toString();8283 const ethSigner = await helper.eth.createAccountWithBalance(donor);8485 const contract = await helper.ethContract.deployByCode(86 ethSigner,87 'RMRKNestableMintable',88 CONTRACT_SOURCE,89 CONTRACT_IMPORT,90 5000000,91 );9293 const relayer = await helper.ethContract.deployByCode(94 ethSigner,95 'Relayer',96 RELAYER_SOURCE,97 CONTRACT_IMPORT,98 5000000,99 [contract.options.address],100 );101102 const relayerAddress = relayer.options.address;103104 const rmrk = contract as any as RMRKNestableMintable;105 const createTokenFor = async (receiver: string) => {106 const tokenReceipt = await rmrk.methods.safeMint(receiver).send({from: ethSigner});107 return tokenReceipt.events!['Transfer'].returnValues.tokenId as number;108 };109110111 const nestId = await createTokenFor(ethSigner);112 const outerCollectionNestedId = 10;113 const contractOwnedNestId = await createTokenFor(relayerAddress);114 const nextTokenId = contractOwnedNestId + 1;115116 const nestTransfer = await helper.arrange.calculcateFee({Ethereum: ethSigner}, async () => {117 const addChildData = rmrk.methods.addChild(nestId, outerCollectionNestedId, []).encodeABI();118 await relayer.methods.relay(addChildData).send({from: ethSigner});119 await rmrk.methods.acceptChild(nestId, 0, relayerAddress, outerCollectionNestedId).send({from: ethSigner});120 });121122123 const nestMint = await helper.arrange.calculcateFee({Ethereum: ethSigner}, async () => {124 const nestMintData = rmrk.methods.nestMint(rmrk.options.address, nextTokenId, contractOwnedNestId).encodeABI();125 await relayer.methods.relay(nestMintData).send({from: ethSigner});126 const acceptNestedToken = rmrk.methods.acceptChild(contractOwnedNestId, 0, rmrk.options.address, nextTokenId).encodeABI();127 await relayer.methods.relay(acceptNestedToken).send({from: ethSigner});128 });129130131 const unnestToken = await helper.arrange.calculcateFee({Ethereum: ethSigner}, async () => {132 const unnestData = rmrk.methods.transferChild(contractOwnedNestId, ethSigner, 0, 0, rmrk.options.address, nextTokenId, false, []).encodeABI();133 await relayer.methods.relay(unnestData).send({from: ethSigner});134 });135136 return {mint: convertToTokens(nestMint), transfer: convertToTokens(nestTransfer), unnest: convertToTokens(unnestToken)};137}138139async function measureEth(helper: EthUniqueHelper, donor: IKeyringPair) {140 const owner = await helper.eth.createAccountWithBalance(donor);141 const {collectionId, contract} = await createNestingCollection(helper, owner);142143 144 const mintingTargetNFTTokenIdResult = await contract.methods.mint(owner).send({from: owner});145 const targetNFTTokenId = mintingTargetNFTTokenIdResult.events.Transfer.returnValues.tokenId;146 const targetNftTokenAddress = helper.ethAddress.fromTokenId(collectionId, targetNFTTokenId);147148 149 const nestMint = await helper.arrange.calculcateFee({Ethereum: owner}, async () => {150 await contract.methods.mint(targetNftTokenAddress).send({from: owner});151 });152153 154 const mintingSecondTokenIdResult = await contract.methods.mint(owner).send({from: owner});155 const nestedTokenId = mintingSecondTokenIdResult.events.Transfer.returnValues.tokenId;156157 const nestTransfer = await helper.arrange.calculcateFee({Ethereum: owner}, async () => {158 await contract.methods.transfer(targetNftTokenAddress, nestedTokenId).send({from: owner});159 });160161 const unnestToken = await helper.arrange.calculcateFee({Ethereum: owner}, async () => {162 await contract.methods.transferFrom(targetNftTokenAddress, owner, nestedTokenId).send({from: owner});163 });164 return {mint: convertToTokens(nestMint), transfer: convertToTokens(nestTransfer), unnest: convertToTokens(unnestToken)};165}166167async function measureSub(helper: EthUniqueHelper, donor: IKeyringPair) {168169 const [alice, bob] = await helper.arrange.createAccounts([100n, 100n], donor);170171 const targetNFTCollection = await helper.nft.mintCollection(alice);172 const targetTokenBob = await targetNFTCollection.mintToken(alice, {Substrate: bob.address});173174175 const collectionForNesting = await helper.nft.mintCollection(bob);176 177 await targetNFTCollection.setPermissions(alice, {178 nesting: {tokenOwner: true},179 });180181 const nestMint = await helper.arrange.calculcateFee({Substrate: bob.address}, async () => {182 await (collectionForNesting.mintToken(bob, targetTokenBob.nestingAccount()));183 });184185 const nestedToken2 = await collectionForNesting.mintToken(bob);186 const nestTransfer = await helper.arrange.calculcateFee({Substrate: bob.address}, async () => {187 await nestedToken2.nest(bob, targetTokenBob);188 });189190 const unnestToken = await helper.arrange.calculcateFee({Substrate: bob.address}, async () => {191 await nestedToken2.transferFrom(bob, targetTokenBob.nestingAccount(), {Substrate: bob.address});192 });193194 return {mint: convertToTokens(nestMint), transfer: convertToTokens(nestTransfer), unnest: convertToTokens(unnestToken)};195}196197198const createNestingCollection = async (199 helper: EthUniqueHelper,200 owner: string,201): Promise<{ collectionId: number, collectionAddress: string, contract: Contract }> => {202 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');203204 const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);205 await contract.methods.setCollectionNesting(true).send({from: owner});206207 return {collectionId, collectionAddress, contract};208};209210main()211 .then(() => process.exit(0))212 .catch((e) => {213 console.log(e);214 process.exit(1);215 });216217218219220221