git.delta.rocks / unique-network / refs/commits / f64e9cf11092

difftreelog

fix abi `mintBulk`

PraetorP2023-02-06parent: #f23307e.patch.diff
in: master

1 file changed

modifiedtests/src/benchmarks/mintFee/benchmark.tsdiffbeforeafterboth
after · tests/src/benchmarks/mintFee/benchmark.ts
1import {EthUniqueHelper, usingEthPlaygrounds} from '../../eth/util';2import {readFile} from 'fs/promises';3import {CollectionLimitField, ContractImports, TokenPermissionField} from '../../eth/util/playgrounds/types';4import {5  ICrossAccountId,6  ITokenPropertyPermission,7  TCollectionMode,8} from '../../util/playgrounds/types';9import {IKeyringPair} from '@polkadot/types/types';10import {UniqueFTCollection, UniqueNFTCollection, UniqueRFTCollection} from '../../util/playgrounds/unique';11import {Contract} from 'web3-eth-contract';12import {createObjectCsvWriter} from 'csv-writer';13import {FunctionFeeVM, IFunctionFee} from './types';1415const CONTRACT_IMPORT: ContractImports[] = [16  {17    fsPath: `${__dirname}/../../eth/api/CollectionHelpers.sol`,18    solPath: 'eth/api/CollectionHelpers.sol',19  },20  {21    fsPath: `${__dirname}/../../eth/api/ContractHelpers.sol`,22    solPath: 'eth/api/ContractHelpers.sol',23  },24  {25    fsPath: `${__dirname}/../../eth/api/UniqueRefungibleToken.sol`,26    solPath: 'eth/api/UniqueRefungibleToken.sol',27  },28  {29    fsPath: `${__dirname}/../../eth/api/UniqueRefungible.sol`,30    solPath: 'eth/api/UniqueRefungible.sol',31  },32  {33    fsPath: `${__dirname}/../../eth/api/UniqueNFT.sol`,34    solPath: 'eth/api/UniqueNFT.sol',35  },36];3738const PROPERTIES = Array(40)39  .fill(0)40  .map((_, i) => {41    return {42      key: `key_${i}`,43      value: Uint8Array.from(Buffer.from(`value_${i}`)),44    };45  });4647const SUBS_PROPERTIES = Array(40)48  .fill(0)49  .map((_, i) => {50    return {51      key: `key_${i}`,52      value: `value_${i}`,53    };54  });5556const PERMISSIONS: ITokenPropertyPermission[] = PROPERTIES.map((p) => {57  return {58    key: p.key,59    permission: {60      tokenOwner: true,61      collectionAdmin: true,62      mutable: true,63    },64  };65});6667interface IBenchmarkResultForProp {68	propertiesNumber: number;69	substrateFee: number;70	ethFee: number;71	ethBulkFee: number;72  ethMintCrossFee: number;73	evmProxyContractFee: number;74	evmProxyContractBulkFee: number;75}7677const main = async () => {78  const benchmarks = [79    'substrateFee',80    'ethFee',81    'ethBulkFee',82    'ethMintCrossFee',83    'evmProxyContractFee',84    'evmProxyContractBulkFee',85  ];86  const headers = [87    'propertiesNumber',88    ...benchmarks,89  ];909192  const csvWriter = createObjectCsvWriter({93    path: 'properties.csv',94    header: headers,95  });9697  await usingEthPlaygrounds(async (helper, privateKey) => {98    const NOMINAL = helper.balance.getOneTokenNominal();99    const CONTRACT_SOURCE = (100      await readFile(`${__dirname}/proxyContract.sol`)101    ).toString();102103    console.log('\n ERC20 ops fees');104    console.table(FunctionFeeVM.fromModel(await erc20CalculateFeeGas(helper, privateKey)));105106    console.log('\n ERC721 ops fees');107    const erc721 = await erc721CalculateFeeGas(helper, privateKey);108    console.table(FunctionFeeVM.fromModel(erc721));109110    const donor = await privateKey('//Alice'); // Seed from account with balance on this network111    const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);112113    const contract = await helper.ethContract.deployByCode(114      ethSigner,115      'ProxyMint',116      CONTRACT_SOURCE,117      CONTRACT_IMPORT,118    );119120    const fees = await benchMintFee(helper, privateKey, contract);121    console.log('Minting without properties');122    console.table(fees);123124    const result: IBenchmarkResultForProp[] = [];125    const csvResult: IBenchmarkResultForProp[] = [];126127    for (let i = 1; i <= 20; i++) {128      const benchResult = await benchMintWithProperties(helper, privateKey, contract, {129        propertiesNumber: i,130      }) as any;131132      csvResult.push(benchResult);133134      const minFee = Math.min(...(benchmarks.map(x => benchResult[x])));135      for(const key of benchmarks) {136        const keyPercent = Math.round((benchResult[key] / minFee) * 100);137        benchResult[key] = `${benchResult[key]} (${keyPercent}%)`;138      }139140      result.push(benchResult);141    }142143    await csvWriter.writeRecords(csvResult);144145    console.log('Minting with properties');146    console.table(result, headers);147  });148};149150main()151  .then(() => process.exit(0))152  .catch((e) => {153    console.log(e);154    process.exit(1);155  });156157async function createCollectionForBenchmarks(158  mode : TCollectionMode,159  helper: EthUniqueHelper,160  privateKey: (seed: string) => Promise<IKeyringPair>,161  ethSigner: string,162  proxyContract: string | null,163  permissions: ITokenPropertyPermission[],164) {165  const donor = await privateKey('//Alice');166167  const collection = await helper[mode].mintCollection(donor, {168    name: 'test mintToSubstrate',169    description: 'EVMHelpers',170    tokenPrefix: mode,171    ...(mode != 'ft' ? {172      tokenPropertyPermissions: [173        {174          key: 'url',175          permission: {176            tokenOwner: true,177            collectionAdmin: true,178            mutable: true,179          },180        },181        {182          key: 'URI',183          permission: {184            tokenOwner: true,185            collectionAdmin: true,186            mutable: true,187          },188        },189      ],190    } : {}),191    limits: {sponsorTransferTimeout: 0, sponsorApproveTimeout: 0},192    permissions: {mintMode: true},193  });194195  await collection.addToAllowList(donor, {196    Ethereum: helper.address.substrateToEth(donor.address),197  });198  await collection.addToAllowList(donor, {Substrate: donor.address});199  await collection.addAdmin(donor, {Ethereum: ethSigner});200  await collection.addAdmin(donor, {201    Ethereum: helper.address.substrateToEth(donor.address),202  });203204  if (proxyContract) {205    await collection.addToAllowList(donor, {Ethereum: proxyContract});206    await collection.addAdmin(donor, {Ethereum: proxyContract});207  }208  if (collection instanceof UniqueNFTCollection || collection instanceof UniqueRFTCollection)209    await collection.setTokenPropertyPermissions(donor, permissions);210211  return collection;212}213214async function benchMintFee(215  helper: EthUniqueHelper,216  privateKey: (seed: string) => Promise<IKeyringPair>,217  proxyContract: Contract,218): Promise<{219	substrateFee: number;220	ethFee: number;221	evmProxyContractFee: number;222}> {223  const donor = await privateKey('//Alice');224  const substrateReceiver = await privateKey('//Bob');225  const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);226227  const nominal = helper.balance.getOneTokenNominal();228229  await helper.eth.transferBalanceFromSubstrate(230    donor,231    proxyContract.options.address,232    100n,233  );234235  const collection = (await createCollectionForBenchmarks(236    'nft',237    helper,238    privateKey,239    ethSigner,240    proxyContract.options.address,241    PERMISSIONS,242  )) as UniqueNFTCollection;243244  const substrateFee = await helper.arrange.calculcateFee(245    {Substrate: donor.address},246    () => collection.mintToken(donor, {Substrate: substrateReceiver.address}),247  );248249  const collectionEthAddress = helper.ethAddress.fromCollectionId(collection.collectionId);250  const collectionContract = await helper.ethNativeContract.collection(251    collectionEthAddress,252    'nft',253  );254255  const receiverEthAddress = helper.address.substrateToEth(substrateReceiver.address);256257  const encodedCall = collectionContract.methods258    .mint(receiverEthAddress)259    .encodeABI();260261  const ethFee = await helper.arrange.calculcateFee(262    {Substrate: donor.address},263    async () => {264      await helper.eth.sendEVM(265        donor,266        collectionContract.options.address,267        encodedCall,268        '0',269      );270    },271  );272273  const evmProxyContractFee = await helper.arrange.calculcateFee(274    {Ethereum: ethSigner},275    async () => {276      await proxyContract.methods277        .mintToSubstrate(278          helper.ethAddress.fromCollectionId(collection.collectionId),279          substrateReceiver.addressRaw,280        )281        .send({from: ethSigner});282    },283  );284285  return {286    substrateFee: convertToTokens(substrateFee, nominal),287    ethFee: convertToTokens(ethFee, nominal),288    evmProxyContractFee: convertToTokens(evmProxyContractFee, nominal),289  };290}291292async function benchMintWithProperties(293  helper: EthUniqueHelper,294  privateKey: (seed: string) => Promise<IKeyringPair>,295  proxyContract: Contract,296  setup: { propertiesNumber: number },297): Promise<IBenchmarkResultForProp> {298  const donor = await privateKey('//Alice'); // Seed from account with balance on this network299  const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);300301  const susbstrateReceiver = await privateKey('//Bob');302  const receiverEthAddress = helper.address.substrateToEth(susbstrateReceiver.address);303304  const nominal = helper.balance.getOneTokenNominal();305306  const substrateFee = await calculateFeeNftMintWithProperties(307    helper,308    privateKey,309    {Substrate: donor.address},310    ethSigner,311    proxyContract.options.address,312    async (collection) => {313      await collection.mintToken(314        donor,315        {Substrate: susbstrateReceiver.address},316        PROPERTIES.slice(0, setup.propertiesNumber).map((p) => {317          return {key: p.key, value: Buffer.from(p.value).toString()};318        }),319      );320    },321  );322323  const ethFee = await calculateFeeNftMintWithProperties(324    helper,325    privateKey,326    {Substrate: donor.address},327    ethSigner,328    proxyContract.options.address,329    async (collection) => {330      const evmContract = await helper.ethNativeContract.collection(331        helper.ethAddress.fromCollectionId(collection.collectionId),332        'nft',333        undefined,334        true,335      );336337      const subTokenId = await evmContract.methods.nextTokenId().call();338339      let encodedCall = evmContract.methods340        .mint(receiverEthAddress)341        .encodeABI();342343      await helper.eth.sendEVM(344        donor,345        evmContract.options.address,346        encodedCall,347        '0',348      );349350      for (const val of PROPERTIES.slice(0, setup.propertiesNumber)) {351        encodedCall = await evmContract.methods352          .setProperty(subTokenId, val.key, Buffer.from(val.value))353          .encodeABI();354355        await helper.eth.sendEVM(356          donor,357          evmContract.options.address,358          encodedCall,359          '0',360        );361      }362    },363  );364365  const ethBulkFee = await calculateFeeNftMintWithProperties(366    helper,367    privateKey,368    {Substrate: donor.address},369    ethSigner,370    proxyContract.options.address,371    async (collection) => {372      const evmContract = await helper.ethNativeContract.collection(373        helper.ethAddress.fromCollectionId(collection.collectionId),374        'nft',375      );376377      const subTokenId = await evmContract.methods.nextTokenId().call();378379      let encodedCall = evmContract.methods380        .mint(receiverEthAddress)381        .encodeABI();382383      await helper.eth.sendEVM(384        donor,385        evmContract.options.address,386        encodedCall,387        '0',388      );389390      encodedCall = await evmContract.methods391        .setProperties(392          subTokenId,393          PROPERTIES.slice(0, setup.propertiesNumber),394        )395        .encodeABI();396397      await helper.eth.sendEVM(398        donor,399        evmContract.options.address,400        encodedCall,401        '0',402      );403    },404  );405406  const ethMintCrossFee = await calculateFeeNftMintWithProperties(407    helper,408    privateKey,409    {Ethereum: ethSigner},410    ethSigner,411    proxyContract.options.address,412    async (collection) => {413      const evmContract = await helper.ethNativeContract.collection(414        helper.ethAddress.fromCollectionId(collection.collectionId),415        'nft',416      );417418      await evmContract.methods.mintCross(419        helper.ethCrossAccount.fromAddress(receiverEthAddress),420        PROPERTIES.slice(0, setup.propertiesNumber),421      )422        .send({from: ethSigner});423    },424  );425426  const proxyContractFee = await calculateFeeNftMintWithProperties(427    helper,428    privateKey,429    {Ethereum: ethSigner},430    ethSigner,431    proxyContract.options.address,432    async (collection) => {433      await proxyContract.methods434        .mintToSubstrateWithProperty(435          helper.ethAddress.fromCollectionId(collection.collectionId),436          susbstrateReceiver.addressRaw,437          PROPERTIES.slice(0, setup.propertiesNumber),438        )439        .send({from: ethSigner});440    },441  );442443  const proxyContractBulkFee = await calculateFeeNftMintWithProperties(444    helper,445    privateKey,446    {Ethereum: ethSigner},447    ethSigner,448    proxyContract.options.address,449    async (collection) => {450      await proxyContract.methods451        .mintToSubstrateBulkProperty(452          helper.ethAddress.fromCollectionId(collection.collectionId),453          susbstrateReceiver.addressRaw,454          PROPERTIES.slice(0, setup.propertiesNumber),455        )456        .send({from: ethSigner, gas: 25_000_000});457    },458  );459460  return {461    propertiesNumber: setup.propertiesNumber,462    substrateFee: convertToTokens(substrateFee, nominal),463    ethFee: convertToTokens(ethFee, nominal),464    ethBulkFee: convertToTokens(ethBulkFee, nominal),465    ethMintCrossFee: convertToTokens(ethMintCrossFee, nominal),466    evmProxyContractFee: convertToTokens(proxyContractFee, nominal),467    evmProxyContractBulkFee: convertToTokens(proxyContractBulkFee, nominal),468  };469}470471async function calculateFeeNftMintWithProperties(472  helper: EthUniqueHelper,473  privateKey: (seed: string) => Promise<IKeyringPair>,474  payer: ICrossAccountId,475  ethSigner: string,476  proxyContractAddress: string,477  calculatedCall: (collection: UniqueNFTCollection) => Promise<any>,478): Promise<bigint> {479  const collection = (await createCollectionForBenchmarks(480    'nft',481    helper,482    privateKey,483    ethSigner,484    proxyContractAddress,485    PERMISSIONS,486  )) as UniqueNFTCollection;487  return helper.arrange.calculcateFee(payer, async () => {488    await calculatedCall(collection);489  });490}491492function convertToTokens(value: bigint, nominal = 1000_000_000_000_000_000n): number {493  return Number((value * 1000n) / nominal) / 1000;494}495496async function erc721CalculateFeeGas(497  helper: EthUniqueHelper,498  privateKey: (seed: string) => Promise<IKeyringPair>,499500): Promise<IFunctionFee> {501  const res: IFunctionFee = {};502  const donor = await privateKey('//Alice');503  const [subReceiver] = await helper.arrange.createAccounts([10n], donor);504  const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);505  const ethReceiver = await helper.eth.createAccountWithBalance(donor, 10n);506  const crossSigner = helper.ethCrossAccount.fromAddress(ethSigner);507  const crossReceiver = helper.ethCrossAccount.fromAddress(ethReceiver);508  const collection = (await createCollectionForBenchmarks(509    'nft',510    helper,511    privateKey,512    ethSigner,513    null,514    PERMISSIONS,515  )) as UniqueNFTCollection;516517  const helperContract = await helper.ethNativeContract.collectionHelpers(ethSigner);518  let zeppelelinContract: Contract | null = null;519  const ZEPPELIN_OBJECT = '0x' + (await readFile(`${__dirname}/openZeppelin/ERC721/bin/ZeppelinContract.bin`)).toString();520  const ZEPPELIN_ABI = JSON.parse((await readFile(`${__dirname}/openZeppelin/ERC721/bin/ZeppelinContract.abi`)).toString());521522  const evmContract = await helper.ethNativeContract.collection(523    helper.ethAddress.fromCollectionId(collection.collectionId),524    'nft',525    ethSigner,526    true,527  );528529  res['createCollection'] = await helper.arrange.calculcateFeeGas(530    {Ethereum: ethSigner},531    () => helperContract.methods.createNFTCollection('test','test','test').send({from: ethSigner, value: Number(2n * helper.balance.getOneTokenNominal())}),532  );533534  res['createCollection'].substrate = convertToTokens((await helper.arrange.calculcateFee(535    {Substrate: donor.address},536    () => helper.nft.mintCollection(537      donor,538      {name: 'test', description: 'test', tokenPrefix: 'test'},539    ),540  )));541542  res['createCollection'].zeppelin = await helper.arrange.calculcateFeeGas(543    {Ethereum: ethSigner},544    async () => {545      zeppelelinContract = await helper.ethContract.deployByAbi(546        ethSigner,547        ZEPPELIN_ABI,548        ZEPPELIN_OBJECT,549      );550    },551  );552553  res['mint'] =554    await helper.arrange.calculcateFeeGas(555      {Ethereum: ethSigner},556      () => evmContract.methods.mint(ethSigner).send(),557    );558559  res['mint'].zeppelin =560    await helper.arrange.calculcateFeeGas(561      {Ethereum: ethSigner},562      () => zeppelelinContract!.methods.safeMint(ethSigner, 'test').send({from: ethSigner}),563    );564565  res['mintCross'] =566    await helper.arrange.calculcateFeeGas(567      {Ethereum: ethSigner},568      () => evmContract.methods.mintCross(crossSigner, []).send(),569    );570571  res['mint'].substrate = convertToTokens((await helper.arrange.calculcateFee(572    {Substrate: donor.address},573    () => collection.mintToken(574      donor,575      {Substrate: donor.address},576    ),577  )));578579  res['mintCross'].substrate = convertToTokens((await helper.arrange.calculcateFee(580    {Substrate: donor.address},581    () => collection.mintMultipleTokens(donor, [{582      owner: {Substrate: donor.address},583    }]),584  )));585586  res['mintWithTokenURI'] =587    await helper.arrange.calculcateFeeGas(588      {Ethereum: ethSigner},589      () => evmContract.methods.mintWithTokenURI(ethSigner, 'Test URI').send(),590    );591592  res['mintWithTokenURI'].substrate = convertToTokens((await helper.arrange.calculcateFee(593    {Substrate: donor.address},594    () => collection.mintToken(595      donor,596      {Ethereum: ethSigner},597      [{key: 'URI', value: 'Test URI'}],598    ),599  )));600601  res['setProperties'] =602    await helper.arrange.calculcateFeeGas(603      {Ethereum: ethSigner},604      () => evmContract.methods.setProperties(1, PROPERTIES.slice(0,1)).send(),605    );606607  res['deleteProperties'] =608    await helper.arrange.calculcateFeeGas(609      {Ethereum: ethSigner},610      () => evmContract.methods.deleteProperties(1, [PROPERTIES[0].key]).send(),611    );612613  res['setProperties'].substrate = convertToTokens((await helper.arrange.calculcateFee(614    {Substrate: donor.address},615    () => collection.setTokenProperties(616      donor,617      1,618      SUBS_PROPERTIES.slice(0, 1),619    ),620  )));621622  res['deleteProperties'].substrate = convertToTokens((await helper.arrange.calculcateFee(623    {Substrate: donor.address},624    () => collection.deleteTokenProperties(625      donor,626      1,627      SUBS_PROPERTIES.slice(0, 1)628        .map(p => p.key),629    ),630  )));631632  res['transfer'] =633    await helper.arrange.calculcateFeeGas(634      {Ethereum: ethSigner},635      () => evmContract.methods.transfer(ethReceiver, 1).send(),636    );637638  res['safeTransferFrom*'] = {639    zeppelin:640      await helper.arrange.calculcateFeeGas(641        {Ethereum: ethSigner},642        () => zeppelelinContract!.methods.safeTransferFrom(ethSigner, ethReceiver, 0).send({from: ethSigner}),643      ),644  };645646  res['transferCross'] =647    await helper.arrange.calculcateFeeGas(648      {Ethereum: ethReceiver},649      () => evmContract.methods.transferCross(crossSigner, 1).send({from: ethReceiver}),650    );651652  res['transferCross'].substrate = convertToTokens((await helper.arrange.calculcateFee(653    {Substrate: donor.address},654    () => collection.transferToken(655      donor,656      3,657      {Substrate: subReceiver.address},658    ),659  )));660  await collection.approveToken(subReceiver, 3, {Substrate: donor.address});661662  res['transferFrom*'] =663    await helper.arrange.calculcateFeeGas(664      {Ethereum: ethSigner},665      () => evmContract.methods.transferFrom(ethSigner, ethReceiver, 1).send(),666    );667668  res['transferFrom*'].zeppelin =669    await helper.arrange.calculcateFeeGas(670      {Ethereum: ethReceiver},671      () => zeppelelinContract!.methods.transferFrom(ethReceiver, ethSigner, 0).send({from: ethReceiver}),672    );673674675  res['transferFromCross'] =676    await helper.arrange.calculcateFeeGas(677      {Ethereum: ethReceiver},678      () => evmContract.methods.transferFromCross(crossReceiver, crossSigner, 1).send({from:ethReceiver}),679    );680681  res['transferFromCross'].substrate = convertToTokens((await helper.arrange.calculcateFee(682    {Substrate: donor.address},683    () => collection.transferTokenFrom(donor, 3, {Substrate: subReceiver.address}, {Substrate: donor.address}),684  )));685686  res['burn'] =687    await helper.arrange.calculcateFeeGas(688      {Ethereum: ethSigner},689      () => evmContract.methods.burn(1).send(),690    );691692  res['burn'].substrate = convertToTokens((await helper.arrange.calculcateFee(693    {Substrate: donor.address},694    () => collection.burnToken(donor, 3),695  )));696697  res['approve*'] =698    await helper.arrange.calculcateFeeGas(699      {Ethereum: ethSigner},700      () => evmContract.methods.approve(ethReceiver, 2).send(),701    );702703  res['approve*'].zeppelin =704    await helper.arrange.calculcateFeeGas(705      {Ethereum: ethSigner},706      () => zeppelelinContract!.methods.approve(ethReceiver, 0).send({from: ethSigner}),707    );708709  res['approveCross'] =710    await helper.arrange.calculcateFeeGas(711      {Ethereum: ethSigner},712      () => evmContract.methods.approveCross(crossReceiver, 2).send(),713    );714715  res['approveCross'].substrate = convertToTokens((await helper.arrange.calculcateFee(716    {Substrate: donor.address},717    () => collection.approveToken(donor, 4, {Substrate: subReceiver.address}),718  )));719720  res['setApprovalForAll*'] =721    await helper.arrange.calculcateFeeGas(722      {Ethereum: ethSigner},723      () => evmContract.methods.setApprovalForAll(ethReceiver, true).send(),724    );725726  res['setApprovalForAll*'].zeppelin =727    await helper.arrange.calculcateFeeGas(728      {Ethereum: ethSigner},729      () => zeppelelinContract!.methods.setApprovalForAll(ethReceiver, true).send({from: ethSigner}),730    );731732  res['setApprovalForAll*'].substrate = convertToTokens((await helper.arrange.calculcateFee(733    {Substrate: donor.address},734    () => helper.nft.setAllowanceForAll(donor, collection.collectionId, {Substrate: subReceiver.address}, true),735  )));736737  res['burnFromCross'] =738    await helper.arrange.calculcateFeeGas(739      {Ethereum: ethReceiver},740      () => evmContract.methods.burnFromCross(crossSigner, 2).send({from:ethReceiver}),741    );742743  res['burnFromCross'].substrate = convertToTokens((await helper.arrange.calculcateFee(744    {Substrate: subReceiver.address},745    () => collection.burnTokenFrom(subReceiver, 4, {Substrate: donor.address}),746  )));747748  res['setTokenPropertyPermissions'] =749    await helper.arrange.calculcateFeeGas(750      {Ethereum: ethSigner},751      () =>  evmContract.methods.setTokenPropertyPermissions([752        ['url', [753          [TokenPermissionField.Mutable, true],754          [TokenPermissionField.TokenOwner, true],755          [TokenPermissionField.CollectionAdmin, true]],756        ],757      ]).send(),758    );759760  res['setTokenPropertyPermissions'].substrate = convertToTokens((await helper.arrange.calculcateFee(761    {Substrate: donor.address},762    () => collection.setTokenPropertyPermissions(donor, [{key: 'url', permission: {763      tokenOwner: true,764      collectionAdmin: true,765      mutable: true,766    }}]),767  )));768769  res['setCollectionSponsorCross'] =770    await helper.arrange.calculcateFeeGas(771      {Ethereum: ethSigner},772      () =>  evmContract.methods.setCollectionSponsorCross(crossReceiver).send(),773    );774775  res['confirmCollectionSponsorship'] =776    await helper.arrange.calculcateFeeGas(777      {Ethereum: ethReceiver},778      () =>  evmContract.methods.confirmCollectionSponsorship().send({from: ethReceiver}),779    );780781  res['removeCollectionSponsor'] =782    await helper.arrange.calculcateFeeGas(783      {Ethereum: ethSigner},784      () =>  evmContract.methods.removeCollectionSponsor().send(),785    );786787  res['setCollectionSponsorCross'].substrate = convertToTokens((await helper.arrange.calculcateFee(788    {Substrate: donor.address},789    () => collection.setSponsor(donor, subReceiver.address),790  )));791792  res['confirmCollectionSponsorship'].substrate = convertToTokens((await helper.arrange.calculcateFee(793    {Substrate: subReceiver.address},794    () => collection.confirmSponsorship(subReceiver),795  )));796797  res['removeCollectionSponsor'].substrate = convertToTokens((await helper.arrange.calculcateFee(798    {Substrate: donor.address},799    () => collection.removeSponsor(donor),800  )));801802  res['setCollectionProperties'] =803    await helper.arrange.calculcateFeeGas(804      {Ethereum: ethSigner},805      () => evmContract.methods.setCollectionProperties(PROPERTIES.slice(0, 1)).send(),806    );807808  res['deleteCollectionProperties'] =809    await helper.arrange.calculcateFeeGas(810      {Ethereum: ethSigner},811      () =>  evmContract.methods.deleteCollectionProperties(PROPERTIES.slice(0,1).map(p => p.key)).send(),812    );813  res['setCollectionProperties'].substrate = convertToTokens((await helper.arrange.calculcateFee(814    {Substrate: donor.address},815    () => collection.setProperties(donor, PROPERTIES.slice(0, 1)816      .map(p => { return {key: p.key, value: p.value.toString()}; })),817  )));818819  res['deleteCollectionProperties'].substrate = convertToTokens((await helper.arrange.calculcateFee(820    {Substrate: donor.address},821    () => collection.deleteProperties(donor, PROPERTIES.slice(0, 1)822      .map(p => p.key)),823  )));824825  res['setCollectionLimit'] =826    await helper.arrange.calculcateFeeGas(827      {Ethereum: ethSigner},828      () =>  evmContract.methods.setCollectionLimit({field: CollectionLimitField.AccountTokenOwnership, value: {status: true, value: 1000}}).send(),829    );830831  res['setCollectionLimit'].substrate = convertToTokens((await helper.arrange.calculcateFee(832    {Substrate: donor.address},833    () => collection.setLimits(donor, {accountTokenOwnershipLimit: 1000}),834  )));835836  const {collectionAddress} = await helper.eth.createCollection('nft', ethSigner, 'A', 'B', 'C');837  const collectionWithEthOwner = await helper.ethNativeContract.collection(collectionAddress, 'nft', ethSigner, true);838839840  res['addCollectionAdminCross'] =841    await helper.arrange.calculcateFeeGas(842      {Ethereum: ethSigner},843      () =>  collectionWithEthOwner.methods.addCollectionAdminCross(crossReceiver).send(),844    );845846  res['removeCollectionAdminCross'] =847    await helper.arrange.calculcateFeeGas(848      {Ethereum: ethSigner},849      () =>  collectionWithEthOwner.methods.removeCollectionAdminCross(crossReceiver).send(),850    );851852  res['addCollectionAdminCross'].substrate = convertToTokens((await helper.arrange.calculcateFee(853    {Substrate: donor.address},854    () => collection.addAdmin(donor, {Ethereum: ethReceiver}),855  )));856857  res['removeCollectionAdminCross'].substrate = convertToTokens((await helper.arrange.calculcateFee(858    {Substrate: donor.address},859    () => collection.removeAdmin(donor, {Ethereum: ethReceiver}),860  )));861862  res['setCollectionNesting'] =863    await helper.arrange.calculcateFeeGas(864      {Ethereum: ethSigner},865      () =>  evmContract.methods.setCollectionNesting(true).send(),866    );867868  res['setCollectionNesting[]'] =869    await helper.arrange.calculcateFeeGas(870      {Ethereum: ethSigner},871      () =>  evmContract.methods.setCollectionNesting(true, [collectionAddress]).send(),872    );873874  res['setCollectionNesting'].substrate = convertToTokens((await helper.arrange.calculcateFee(875    {Substrate: donor.address},876    () => collection.disableNesting(donor),877  )));878879  res['setCollectionNesting[]'].substrate = convertToTokens((await helper.arrange.calculcateFee(880    {Substrate: donor.address},881    () => collection.setPermissions(882      donor,883      {884        nesting: {885          tokenOwner: true,886          restricted: [collection.collectionId],887        },888      },889    ),890  )));891892  res['setCollectionAccess'] =893    await helper.arrange.calculcateFeeGas(894      {Ethereum: ethSigner},895      () =>  evmContract.methods.setCollectionAccess(1).send(),896    );897898  res['setCollectionAccess'].substrate = convertToTokens((await helper.arrange.calculcateFee(899    {Substrate: donor.address},900    () => collection.setPermissions(donor, {access: 'AllowList'}),901  )));902903  res['addToCollectionAllowListCross'] =904    await helper.arrange.calculcateFeeGas(905      {Ethereum: ethSigner},906      () =>  evmContract.methods.addToCollectionAllowListCross(crossReceiver).send(),907    );908909  res['removeFromCollectionAllowListCross'] =910    await helper.arrange.calculcateFeeGas(911      {Ethereum: ethSigner},912      () =>  evmContract.methods.removeFromCollectionAllowListCross(crossReceiver).send(),913    );914915  res['addToCollectionAllowListCross'].substrate = convertToTokens((await helper.arrange.calculcateFee(916    {Substrate: donor.address},917    () => collection.addToAllowList(donor, {Ethereum: ethReceiver}),918  )));919920  res['removeFromCollectionAllowListCross'].substrate = convertToTokens((await helper.arrange.calculcateFee(921    {Substrate: donor.address},922    () => collection.removeFromAllowList(donor, {Ethereum: ethReceiver}),923  )));924925  res['setCollectionMintMode'] =926    await helper.arrange.calculcateFeeGas(927      {Ethereum: ethSigner},928      () =>  evmContract.methods.setCollectionMintMode(true).send(),929    );930931  res['setCollectionMintMode'].substrate = convertToTokens((await helper.arrange.calculcateFee(932    {Substrate: donor.address},933    () => collection.setPermissions(donor, {mintMode: false}),934  )));935936  res['changeCollectionOwnerCross'] =937    await helper.arrange.calculcateFeeGas(938      {Ethereum: ethSigner},939      () =>  collectionWithEthOwner.methods.changeCollectionOwnerCross(crossReceiver).send(),940    );941942  res['changeCollectionOwnerCross'].substrate = convertToTokens((await helper.arrange.calculcateFee(943    {Substrate: donor.address},944    () => collection.changeOwner(donor, subReceiver.address),945  )));946947  return res;948}949950async function erc20CalculateFeeGas(951  helper: EthUniqueHelper,952  privateKey: (seed: string) => Promise<IKeyringPair>,953954): Promise<IFunctionFee> {955  const res: IFunctionFee = {};956  const donor = await privateKey('//Alice');957  const [subReceiver] = await helper.arrange.createAccounts([10n], donor);958  const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);959  const ethReceiver = await helper.eth.createAccountWithBalance(donor, 10n);960  const crossSigner = helper.ethCrossAccount.fromAddress(ethSigner);961  const crossReceiver = helper.ethCrossAccount.fromAddress(ethReceiver);962  const collection = (await createCollectionForBenchmarks(963    'ft',964    helper,965    privateKey,966    ethSigner,967    null,968    PERMISSIONS,969  )) as UniqueFTCollection;970971  const helperContract = await helper.ethNativeContract.collectionHelpers(ethSigner);972  let zeppelelinContract: Contract | null = null;973  const ZEPPELIN_OBJECT = '0x' + (await readFile(`${__dirname}/openZeppelin/ERC20/bin/ZeppelinContract.bin`)).toString();974  const ZEPPELIN_ABI = JSON.parse((await readFile(`${__dirname}/openZeppelin/ERC20/bin/ZeppelinContract.abi`)).toString());975976  const evmContract = await helper.ethNativeContract.collection(977    helper.ethAddress.fromCollectionId(collection.collectionId),978    'ft',979    ethSigner,980    true,981  );982983  res['createCollection'] = await helper.arrange.calculcateFeeGas(984    {Ethereum: ethSigner},985    () => helperContract.methods.createFTCollection('test', 18,'test','test').send({from: ethSigner, value: Number(2n * helper.balance.getOneTokenNominal())}),986  );987988  res['createCollection'].substrate = convertToTokens((await helper.arrange.calculcateFee(989    {Substrate: donor.address},990    () => helper.ft.mintCollection(991      donor,992      {name: 'test', description: 'test', tokenPrefix: 'test'},993      18,994    ),995  )));996997  res['createCollection'].zeppelin = await helper.arrange.calculcateFeeGas(998    {Ethereum: ethSigner},999    async () => {1000      zeppelelinContract = await helper.ethContract.deployByAbi(1001        ethSigner,1002        ZEPPELIN_ABI,1003        ZEPPELIN_OBJECT,1004      );1005    },1006  );10071008  res['mint'] =1009    await helper.arrange.calculcateFeeGas(1010      {Ethereum: ethSigner},1011      () => evmContract.methods.mint(ethSigner, 1).send(),1012    );10131014  res['mint'].zeppelin =1015    await helper.arrange.calculcateFeeGas(1016      {Ethereum: ethSigner},1017      () => zeppelelinContract!.methods.mint(ethSigner, 1).send(),1018    );10191020  res['mintCross'] =1021    await helper.arrange.calculcateFeeGas(1022      {Ethereum: ethSigner},1023      () => evmContract.methods.mintCross(crossSigner, 1).send(),1024    );10251026  res['mintCross'].substrate = convertToTokens((await helper.arrange.calculcateFee(1027    {Substrate: donor.address},1028    () => collection.mint(1029      donor,1030      10n,1031      {Substrate: donor.address},1032    ),1033  )));10341035  res['mintBulk'] =1036    await helper.arrange.calculcateFeeGas(1037      {Ethereum: ethSigner},1038      () => evmContract.methods.mintBulk([{to: ethSigner, amount: 1}]).send(),1039    );10401041  res['mintBulk'].substrate = convertToTokens((await helper.arrange.calculcateFee(1042    {Substrate: donor.address},1043    () => helper.executeExtrinsic(donor, 'api.tx.unique.createMultipleItemsEx',[collection.collectionId, {1044      Fungible: new Map([1045        [JSON.stringify({Ethereum: ethSigner}), 1],10461047      ]),1048    }], true),1049  )));10501051  res['transfer*'] =1052    await helper.arrange.calculcateFeeGas(1053      {Ethereum: ethSigner},1054      () => evmContract.methods.transfer(ethReceiver, 1).send(),1055    );10561057  res['transfer*'].zeppelin =1058    await helper.arrange.calculcateFeeGas(1059      {Ethereum: ethSigner},1060      () => zeppelelinContract!.methods.transfer(ethReceiver, 1).send(),1061    );10621063  res['transferCross'] =1064    await helper.arrange.calculcateFeeGas(1065      {Ethereum: ethReceiver},1066      () => evmContract.methods.transferCross(crossSigner, 1).send({from: ethReceiver}),1067    );10681069  res['transferCross'].substrate = convertToTokens((await helper.arrange.calculcateFee(1070    {Substrate: donor.address},1071    () => collection.transfer(1072      donor,1073      {Substrate: subReceiver.address},1074      1n,1075    ),1076  )));1077  await collection.approveTokens(subReceiver, {Substrate: donor.address}, 1n);10781079  res['transferFrom*'] =1080    await helper.arrange.calculcateFeeGas(1081      {Ethereum: ethSigner},1082      () => evmContract.methods.transferFrom(ethSigner, ethReceiver, 1).send(),1083    );10841085  res['transferFrom*'].zeppelin =1086    await helper.arrange.calculcateFeeGas(1087      {Ethereum: ethReceiver},1088      () => zeppelelinContract!.methods.transferFrom(ethReceiver, ethSigner, 0).send({from: ethReceiver}),1089    );10901091  res['transferFromCross'] =1092    await helper.arrange.calculcateFeeGas(1093      {Ethereum: ethReceiver},1094      () => evmContract.methods.transferFromCross(crossReceiver, crossSigner, 1).send({from:ethReceiver}),1095    );10961097  res['transferFromCross'].substrate = convertToTokens((await helper.arrange.calculcateFee(1098    {Substrate: donor.address},1099    () => collection.transferFrom(donor, {Substrate: subReceiver.address}, {Substrate: donor.address}, 1n),1100  )));110111021103  res['burnTokens'] = {fee: 0n, gas: 0n};1104  res['burnTokens'].substrate = convertToTokens((await helper.arrange.calculcateFee(1105    {Substrate: donor.address},1106    () => collection.burnTokens(donor, 1n),1107  )));110811091110  res['approve*'] =1111    await helper.arrange.calculcateFeeGas(1112      {Ethereum: ethSigner},1113      () => evmContract.methods.approve(ethReceiver, 2).send(),1114    );11151116  res['approve*'].zeppelin =1117    await helper.arrange.calculcateFeeGas(1118      {Ethereum: ethSigner},1119      () => zeppelelinContract!.methods.approve(ethReceiver, 0).send(),1120    );11211122  res['approveCross'] =1123    await helper.arrange.calculcateFeeGas(1124      {Ethereum: ethSigner},1125      () => evmContract.methods.approveCross(crossReceiver, 2).send(),1126    );11271128  res['approveCross'].substrate = convertToTokens((await helper.arrange.calculcateFee(1129    {Substrate: donor.address},1130    () => collection.approveTokens(donor, {Substrate: subReceiver.address}, 1n),1131  )));11321133  res['burnFromCross'] =1134    await helper.arrange.calculcateFeeGas(1135      {Ethereum: ethReceiver},1136      () => evmContract.methods.burnFromCross(crossSigner, 1).send({from:ethReceiver}),1137    );11381139  res['burnFromCross'].substrate = convertToTokens((await helper.arrange.calculcateFee(1140    {Substrate: subReceiver.address},1141    () => collection.burnTokensFrom(subReceiver, {Substrate: donor.address}, 1n),1142  )));11431144  res['setCollectionSponsorCross'] =1145    await helper.arrange.calculcateFeeGas(1146      {Ethereum: ethSigner},1147      () =>  evmContract.methods.setCollectionSponsorCross(crossReceiver).send(),1148    );11491150  res['confirmCollectionSponsorship'] =1151    await helper.arrange.calculcateFeeGas(1152      {Ethereum: ethReceiver},1153      () =>  evmContract.methods.confirmCollectionSponsorship().send({from: ethReceiver}),1154    );11551156  res['removeCollectionSponsor'] =1157    await helper.arrange.calculcateFeeGas(1158      {Ethereum: ethSigner},1159      () =>  evmContract.methods.removeCollectionSponsor().send(),1160    );11611162  res['setCollectionSponsorCross'].substrate = convertToTokens((await helper.arrange.calculcateFee(1163    {Substrate: donor.address},1164    () => collection.setSponsor(donor, subReceiver.address),1165  )));11661167  res['confirmCollectionSponsorship'].substrate = convertToTokens((await helper.arrange.calculcateFee(1168    {Substrate: subReceiver.address},1169    () => collection.confirmSponsorship(subReceiver),1170  )));11711172  res['removeCollectionSponsor'].substrate = convertToTokens((await helper.arrange.calculcateFee(1173    {Substrate: donor.address},1174    () => collection.removeSponsor(donor),1175  )));11761177  res['setCollectionProperties'] =1178    await helper.arrange.calculcateFeeGas(1179      {Ethereum: ethSigner},1180      () => evmContract.methods.setCollectionProperties(PROPERTIES.slice(0, 1)).send(),1181    );11821183  res['deleteCollectionProperties'] =1184    await helper.arrange.calculcateFeeGas(1185      {Ethereum: ethSigner},1186      () =>  evmContract.methods.deleteCollectionProperties(PROPERTIES.slice(0,1).map(p => p.key)).send(),1187    );1188  res['setCollectionProperties'].substrate = convertToTokens((await helper.arrange.calculcateFee(1189    {Substrate: donor.address},1190    () => collection.setProperties(donor, PROPERTIES.slice(0, 1)1191      .map(p => { return {key: p.key, value: p.value.toString()}; })),1192  )));11931194  res['deleteCollectionProperties'].substrate = convertToTokens((await helper.arrange.calculcateFee(1195    {Substrate: donor.address},1196    () => collection.deleteProperties(donor, PROPERTIES.slice(0, 1)1197      .map(p => p.key)),1198  )));11991200  res['setCollectionLimit'] =1201    await helper.arrange.calculcateFeeGas(1202      {Ethereum: ethSigner},1203      () =>  evmContract.methods.setCollectionLimit({field: CollectionLimitField.AccountTokenOwnership, value: {status: true, value: 1000}}).send(),1204    );12051206  res['setCollectionLimit'].substrate = convertToTokens((await helper.arrange.calculcateFee(1207    {Substrate: donor.address},1208    () => collection.setLimits(donor, {accountTokenOwnershipLimit: 1000}),1209  )));12101211  const {collectionAddress} = await helper.eth.createCollection('nft', ethSigner, 'A', 'B', 'C');1212  const collectionWithEthOwner = await helper.ethNativeContract.collection(collectionAddress, 'nft', ethSigner, true);121312141215  res['addCollectionAdminCross'] =1216    await helper.arrange.calculcateFeeGas(1217      {Ethereum: ethSigner},1218      () =>  collectionWithEthOwner.methods.addCollectionAdminCross(crossReceiver).send(),1219    );12201221  res['removeCollectionAdminCross'] =1222    await helper.arrange.calculcateFeeGas(1223      {Ethereum: ethSigner},1224      () =>  collectionWithEthOwner.methods.removeCollectionAdminCross(crossReceiver).send(),1225    );12261227  res['addCollectionAdminCross'].substrate = convertToTokens((await helper.arrange.calculcateFee(1228    {Substrate: donor.address},1229    () => collection.addAdmin(donor, {Ethereum: ethReceiver}),1230  )));12311232  res['removeCollectionAdminCross'].substrate = convertToTokens((await helper.arrange.calculcateFee(1233    {Substrate: donor.address},1234    () => collection.removeAdmin(donor, {Ethereum: ethReceiver}),1235  )));12361237  res['setCollectionNesting'] =1238    await helper.arrange.calculcateFeeGas(1239      {Ethereum: ethSigner},1240      () =>  evmContract.methods.setCollectionNesting(true).send(),1241    );12421243  res['setCollectionNesting[]'] =1244    await helper.arrange.calculcateFeeGas(1245      {Ethereum: ethSigner},1246      () =>  evmContract.methods.setCollectionNesting(true, [collectionAddress]).send(),1247    );12481249  res['setCollectionNesting'].substrate = convertToTokens((await helper.arrange.calculcateFee(1250    {Substrate: donor.address},1251    () => collection.disableNesting(donor),1252  )));12531254  res['setCollectionNesting[]'].substrate = convertToTokens((await helper.arrange.calculcateFee(1255    {Substrate: donor.address},1256    () => collection.setPermissions(1257      donor,1258      {1259        nesting: {1260          tokenOwner: true,1261          restricted: [collection.collectionId],1262        },1263      },1264    ),1265  )));12661267  res['setCollectionAccess'] =1268    await helper.arrange.calculcateFeeGas(1269      {Ethereum: ethSigner},1270      () =>  evmContract.methods.setCollectionAccess(1).send(),1271    );12721273  res['setCollectionAccess'].substrate = convertToTokens((await helper.arrange.calculcateFee(1274    {Substrate: donor.address},1275    () => collection.setPermissions(donor, {access: 'AllowList'}),1276  )));12771278  res['addToCollectionAllowListCross'] =1279    await helper.arrange.calculcateFeeGas(1280      {Ethereum: ethSigner},1281      () =>  evmContract.methods.addToCollectionAllowListCross(crossReceiver).send(),1282    );12831284  res['removeFromCollectionAllowListCross'] =1285    await helper.arrange.calculcateFeeGas(1286      {Ethereum: ethSigner},1287      () =>  evmContract.methods.removeFromCollectionAllowListCross(crossReceiver).send(),1288    );12891290  res['addToCollectionAllowListCross'].substrate = convertToTokens((await helper.arrange.calculcateFee(1291    {Substrate: donor.address},1292    () => collection.addToAllowList(donor, {Ethereum: ethReceiver}),1293  )));12941295  res['removeFromCollectionAllowListCross'].substrate = convertToTokens((await helper.arrange.calculcateFee(1296    {Substrate: donor.address},1297    () => collection.removeFromAllowList(donor, {Ethereum: ethReceiver}),1298  )));12991300  res['setCollectionMintMode'] =1301    await helper.arrange.calculcateFeeGas(1302      {Ethereum: ethSigner},1303      () =>  evmContract.methods.setCollectionMintMode(true).send(),1304    );13051306  res['setCollectionMintMode'].substrate = convertToTokens((await helper.arrange.calculcateFee(1307    {Substrate: donor.address},1308    () => collection.setPermissions(donor, {mintMode: false}),1309  )));13101311  res['changeCollectionOwnerCross'] =1312    await helper.arrange.calculcateFeeGas(1313      {Ethereum: ethSigner},1314      () =>  collectionWithEthOwner.methods.changeCollectionOwnerCross(crossReceiver).send(),1315    );13161317  res['changeCollectionOwnerCross'].substrate = convertToTokens((await helper.arrange.calculcateFee(1318    {Substrate: donor.address},1319    () => collection.changeOwner(donor, subReceiver.address),1320  )));13211322  return res;1323}