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

difftreelog

source

tests/src/benchmarks/mintFee/index.ts10.9 KiBsourcehistory
1import {EthUniqueHelper, usingEthPlaygrounds} from '../../eth/util';2import {readFile} from 'fs/promises';3import {4  ICrossAccountId,5} from '../../util/playgrounds/types';6import {IKeyringPair} from '@polkadot/types/types';7import {UniqueNFTCollection} from '../../util/playgrounds/unique';8import {Contract} from 'web3-eth-contract';9import {createObjectCsvWriter} from 'csv-writer';10import {convertToTokens, createCollectionForBenchmarks, PERMISSIONS, PROPERTIES} from '../utils/common';11import {makeNames} from '../../util';12import {ContractImports} from '../../eth/util/playgrounds/types';1314const {dirname} = makeNames(import.meta.url);1516export const CONTRACT_IMPORT: ContractImports[] = [17  {18    fsPath: `${dirname}/../../eth/api/CollectionHelpers.sol`,19    solPath: 'eth/api/CollectionHelpers.sol',20  },21  {22    fsPath: `${dirname}/../../eth/api/ContractHelpers.sol`,23    solPath: 'eth/api/ContractHelpers.sol',24  },25  {26    fsPath: `${dirname}/../../eth/api/UniqueRefungibleToken.sol`,27    solPath: 'eth/api/UniqueRefungibleToken.sol',28  },29  {30    fsPath: `${dirname}/../../eth/api/UniqueRefungible.sol`,31    solPath: 'eth/api/UniqueRefungible.sol',32  },33  {34    fsPath: `${dirname}/../../eth/api/UniqueNFT.sol`,35    solPath: 'eth/api/UniqueNFT.sol',36  },37];3839interface IBenchmarkResultForProp {40	propertiesNumber: number;41	substrateFee: number;42	ethFee: number;43	ethBulkFee: number;44  ethMintCrossFee: number;45	evmProxyContractFee: number;46	evmProxyContractBulkFee: number;47}4849const main = async () => {50  const benchmarks = [51    'substrateFee',52    'ethFee',53    'ethBulkFee',54    'ethMintCrossFee',55    'evmProxyContractFee',56    'evmProxyContractBulkFee',57  ];58  const headers = [59    'propertiesNumber',60    ...benchmarks,61  ];626364  const csvWriter = createObjectCsvWriter({65    path: 'properties.csv',66    header: headers,67  });6869  await usingEthPlaygrounds(async (helper, privateKey) => {70    const CONTRACT_SOURCE = (71      await readFile(`${dirname}/proxyContract.sol`)72    ).toString();7374    const donor = await privateKey('//Alice'); // Seed from account with balance on this network75    const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);7677    const contract = await helper.ethContract.deployByCode(78      ethSigner,79      'ProxyMint',80      CONTRACT_SOURCE,81      CONTRACT_IMPORT,82    );8384    const fees = await benchMintFee(helper, privateKey, contract);85    console.log('Minting without properties');86    console.table(fees);8788    const result: IBenchmarkResultForProp[] = [];89    const csvResult: IBenchmarkResultForProp[] = [];9091    for (let i = 1; i <= 20; i++) {92      const benchResult = await benchMintWithProperties(helper, privateKey, contract, {93        propertiesNumber: i,94      }) as any;9596      csvResult.push(benchResult);9798      const minFee = Math.min(...(benchmarks.map(x => benchResult[x])));99      for(const key of benchmarks) {100        const keyPercent = Math.round((benchResult[key] / minFee) * 100);101        benchResult[key] = `${benchResult[key]} (${keyPercent}%)`;102      }103104      result.push(benchResult);105    }106107    await csvWriter.writeRecords(csvResult);108109    console.log('Minting with properties');110    console.table(result, headers);111  });112};113114main()115  .then(() => process.exit(0))116  .catch((e) => {117    console.log(e);118    process.exit(1);119  });120121122123async function benchMintFee(124  helper: EthUniqueHelper,125  privateKey: (seed: string) => Promise<IKeyringPair>,126  proxyContract: Contract,127): Promise<{128	substrateFee: number;129	ethFee: number;130	evmProxyContractFee: number;131}> {132  const donor = await privateKey('//Alice');133  const substrateReceiver = await privateKey('//Bob');134  const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);135136  const nominal = helper.balance.getOneTokenNominal();137138  await helper.eth.transferBalanceFromSubstrate(139    donor,140    proxyContract.options.address,141    100n,142  );143144  const collection = (await createCollectionForBenchmarks(145    'nft',146    helper,147    privateKey,148    ethSigner,149    proxyContract.options.address,150    PERMISSIONS,151  )) as UniqueNFTCollection;152153  const substrateFee = await helper.arrange.calculcateFee(154    {Substrate: donor.address},155    () => collection.mintToken(donor, {Substrate: substrateReceiver.address}),156  );157158  const collectionEthAddress = helper.ethAddress.fromCollectionId(collection.collectionId);159  const collectionContract = await helper.ethNativeContract.collection(160    collectionEthAddress,161    'nft',162  );163164  const receiverEthAddress = helper.address.substrateToEth(substrateReceiver.address);165166  const encodedCall = collectionContract.methods167    .mint(receiverEthAddress)168    .encodeABI();169170  const ethFee = await helper.arrange.calculcateFee(171    {Substrate: donor.address},172    async () => {173      await helper.eth.sendEVM(174        donor,175        collectionContract.options.address,176        encodedCall,177        '0',178      );179    },180  );181182  const evmProxyContractFee = await helper.arrange.calculcateFee(183    {Ethereum: ethSigner},184    async () => {185      await proxyContract.methods186        .mintToSubstrate(187          helper.ethAddress.fromCollectionId(collection.collectionId),188          substrateReceiver.addressRaw,189        )190        .send({from: ethSigner});191    },192  );193194  return {195    substrateFee: convertToTokens(substrateFee, nominal),196    ethFee: convertToTokens(ethFee, nominal),197    evmProxyContractFee: convertToTokens(evmProxyContractFee, nominal),198  };199}200201async function benchMintWithProperties(202  helper: EthUniqueHelper,203  privateKey: (seed: string) => Promise<IKeyringPair>,204  proxyContract: Contract,205  setup: { propertiesNumber: number },206): Promise<IBenchmarkResultForProp> {207  const donor = await privateKey('//Alice'); // Seed from account with balance on this network208  const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);209210  const susbstrateReceiver = await privateKey('//Bob');211  const receiverEthAddress = helper.address.substrateToEth(susbstrateReceiver.address);212213  const nominal = helper.balance.getOneTokenNominal();214215  const substrateFee = await calculateFeeNftMintWithProperties(216    helper,217    privateKey,218    {Substrate: donor.address},219    ethSigner,220    proxyContract.options.address,221    async (collection) => {222      await collection.mintToken(223        donor,224        {Substrate: susbstrateReceiver.address},225        PROPERTIES.slice(0, setup.propertiesNumber).map((p) => {226          return {key: p.key, value: Buffer.from(p.value).toString()};227        }),228      );229    },230  );231232  const ethFee = await calculateFeeNftMintWithProperties(233    helper,234    privateKey,235    {Substrate: donor.address},236    ethSigner,237    proxyContract.options.address,238    async (collection) => {239      const evmContract = await helper.ethNativeContract.collection(240        helper.ethAddress.fromCollectionId(collection.collectionId),241        'nft',242        undefined,243        true,244      );245246      const subTokenId = await evmContract.methods.nextTokenId().call();247248      let encodedCall = evmContract.methods249        .mint(receiverEthAddress)250        .encodeABI();251252      await helper.eth.sendEVM(253        donor,254        evmContract.options.address,255        encodedCall,256        '0',257      );258259      for (const val of PROPERTIES.slice(0, setup.propertiesNumber)) {260        encodedCall = await evmContract.methods261          .setProperty(subTokenId, val.key, Buffer.from(val.value))262          .encodeABI();263264        await helper.eth.sendEVM(265          donor,266          evmContract.options.address,267          encodedCall,268          '0',269        );270      }271    },272  );273274  const ethBulkFee = await calculateFeeNftMintWithProperties(275    helper,276    privateKey,277    {Substrate: donor.address},278    ethSigner,279    proxyContract.options.address,280    async (collection) => {281      const evmContract = await helper.ethNativeContract.collection(282        helper.ethAddress.fromCollectionId(collection.collectionId),283        'nft',284      );285286      const subTokenId = await evmContract.methods.nextTokenId().call();287288      let encodedCall = evmContract.methods289        .mint(receiverEthAddress)290        .encodeABI();291292      await helper.eth.sendEVM(293        donor,294        evmContract.options.address,295        encodedCall,296        '0',297      );298299      encodedCall = await evmContract.methods300        .setProperties(301          subTokenId,302          PROPERTIES.slice(0, setup.propertiesNumber),303        )304        .encodeABI();305306      await helper.eth.sendEVM(307        donor,308        evmContract.options.address,309        encodedCall,310        '0',311      );312    },313  );314315  const ethMintCrossFee = await calculateFeeNftMintWithProperties(316    helper,317    privateKey,318    {Ethereum: ethSigner},319    ethSigner,320    proxyContract.options.address,321    async (collection) => {322      const evmContract = await helper.ethNativeContract.collection(323        helper.ethAddress.fromCollectionId(collection.collectionId),324        'nft',325      );326327      await evmContract.methods.mintCross(328        helper.ethCrossAccount.fromAddress(receiverEthAddress),329        PROPERTIES.slice(0, setup.propertiesNumber),330      )331        .send({from: ethSigner});332    },333  );334335  const proxyContractFee = await calculateFeeNftMintWithProperties(336    helper,337    privateKey,338    {Ethereum: ethSigner},339    ethSigner,340    proxyContract.options.address,341    async (collection) => {342      await proxyContract.methods343        .mintToSubstrateWithProperty(344          helper.ethAddress.fromCollectionId(collection.collectionId),345          susbstrateReceiver.addressRaw,346          PROPERTIES.slice(0, setup.propertiesNumber),347        )348        .send({from: ethSigner});349    },350  );351352  const proxyContractBulkFee = await calculateFeeNftMintWithProperties(353    helper,354    privateKey,355    {Ethereum: ethSigner},356    ethSigner,357    proxyContract.options.address,358    async (collection) => {359      await proxyContract.methods360        .mintToSubstrateBulkProperty(361          helper.ethAddress.fromCollectionId(collection.collectionId),362          susbstrateReceiver.addressRaw,363          PROPERTIES.slice(0, setup.propertiesNumber),364        )365        .send({from: ethSigner, gas: 25_000_000});366    },367  );368369  return {370    propertiesNumber: setup.propertiesNumber,371    substrateFee: convertToTokens(substrateFee, nominal),372    ethFee: convertToTokens(ethFee, nominal),373    ethBulkFee: convertToTokens(ethBulkFee, nominal),374    ethMintCrossFee: convertToTokens(ethMintCrossFee, nominal),375    evmProxyContractFee: convertToTokens(proxyContractFee, nominal),376    evmProxyContractBulkFee: convertToTokens(proxyContractBulkFee, nominal),377  };378}379380async function calculateFeeNftMintWithProperties(381  helper: EthUniqueHelper,382  privateKey: (seed: string) => Promise<IKeyringPair>,383  payer: ICrossAccountId,384  ethSigner: string,385  proxyContractAddress: string,386  calculatedCall: (collection: UniqueNFTCollection) => Promise<any>,387): Promise<bigint> {388  const collection = (await createCollectionForBenchmarks(389    'nft',390    helper,391    privateKey,392    ethSigner,393    proxyContractAddress,394    PERMISSIONS,395  )) as UniqueNFTCollection;396  return helper.arrange.calculcateFee(payer, async () => {397    await calculatedCall(collection);398  });399}400401402