git.delta.rocks / unique-network / refs/commits / 58315dd6eb2e

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 {ContractImports} from '../../eth/util/playgrounds/types';1213export const CONTRACT_IMPORT: ContractImports[] = [14  {15    fsPath: `${__dirname}/../../eth/api/CollectionHelpers.sol`,16    solPath: 'eth/api/CollectionHelpers.sol',17  },18  {19    fsPath: `${__dirname}/../../eth/api/ContractHelpers.sol`,20    solPath: 'eth/api/ContractHelpers.sol',21  },22  {23    fsPath: `${__dirname}/../../eth/api/UniqueRefungibleToken.sol`,24    solPath: 'eth/api/UniqueRefungibleToken.sol',25  },26  {27    fsPath: `${__dirname}/../../eth/api/UniqueRefungible.sol`,28    solPath: 'eth/api/UniqueRefungible.sol',29  },30  {31    fsPath: `${__dirname}/../../eth/api/UniqueNFT.sol`,32    solPath: 'eth/api/UniqueNFT.sol',33  },34];3536interface IBenchmarkResultForProp {37	propertiesNumber: number;38	substrateFee: number;39	ethFee: number;40	ethBulkFee: number;41  ethMintCrossFee: number;42	evmProxyContractFee: number;43	evmProxyContractBulkFee: number;44}4546const main = async () => {47  const benchmarks = [48    'substrateFee',49    'ethFee',50    'ethBulkFee',51    'ethMintCrossFee',52    'evmProxyContractFee',53    'evmProxyContractBulkFee',54  ];55  const headers = [56    'propertiesNumber',57    ...benchmarks,58  ];596061  const csvWriter = createObjectCsvWriter({62    path: 'properties.csv',63    header: headers,64  });6566  await usingEthPlaygrounds(async (helper, privateKey) => {67    const CONTRACT_SOURCE = (68      await readFile(`${__dirname}/proxyContract.sol`)69    ).toString();7071    const donor = await privateKey('//Alice'); // Seed from account with balance on this network72    const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);7374    const contract = await helper.ethContract.deployByCode(75      ethSigner,76      'ProxyMint',77      CONTRACT_SOURCE,78      CONTRACT_IMPORT,79    );8081    const fees = await benchMintFee(helper, privateKey, contract);82    console.log('Minting without properties');83    console.table(fees);8485    const result: IBenchmarkResultForProp[] = [];86    const csvResult: IBenchmarkResultForProp[] = [];8788    for (let i = 1; i <= 20; i++) {89      const benchResult = await benchMintWithProperties(helper, privateKey, contract, {90        propertiesNumber: i,91      }) as any;9293      csvResult.push(benchResult);9495      const minFee = Math.min(...(benchmarks.map(x => benchResult[x])));96      for(const key of benchmarks) {97        const keyPercent = Math.round((benchResult[key] / minFee) * 100);98        benchResult[key] = `${benchResult[key]} (${keyPercent}%)`;99      }100101      result.push(benchResult);102    }103104    await csvWriter.writeRecords(csvResult);105106    console.log('Minting with properties');107    console.table(result, headers);108  });109};110111main()112  .then(() => process.exit(0))113  .catch((e) => {114    console.log(e);115    process.exit(1);116  });117118119120async function benchMintFee(121  helper: EthUniqueHelper,122  privateKey: (seed: string) => Promise<IKeyringPair>,123  proxyContract: Contract,124): Promise<{125	substrateFee: number;126	ethFee: number;127	evmProxyContractFee: number;128}> {129  const donor = await privateKey('//Alice');130  const substrateReceiver = await privateKey('//Bob');131  const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);132133  const nominal = helper.balance.getOneTokenNominal();134135  await helper.eth.transferBalanceFromSubstrate(136    donor,137    proxyContract.options.address,138    100n,139  );140141  const collection = (await createCollectionForBenchmarks(142    'nft',143    helper,144    privateKey,145    ethSigner,146    proxyContract.options.address,147    PERMISSIONS,148  )) as UniqueNFTCollection;149150  const substrateFee = await helper.arrange.calculcateFee(151    {Substrate: donor.address},152    () => collection.mintToken(donor, {Substrate: substrateReceiver.address}),153  );154155  const collectionEthAddress = helper.ethAddress.fromCollectionId(collection.collectionId);156  const collectionContract = await helper.ethNativeContract.collection(157    collectionEthAddress,158    'nft',159  );160161  const receiverEthAddress = helper.address.substrateToEth(substrateReceiver.address);162163  const encodedCall = collectionContract.methods164    .mint(receiverEthAddress)165    .encodeABI();166167  const ethFee = await helper.arrange.calculcateFee(168    {Substrate: donor.address},169    async () => {170      await helper.eth.sendEVM(171        donor,172        collectionContract.options.address,173        encodedCall,174        '0',175      );176    },177  );178179  const evmProxyContractFee = await helper.arrange.calculcateFee(180    {Ethereum: ethSigner},181    async () => {182      await proxyContract.methods183        .mintToSubstrate(184          helper.ethAddress.fromCollectionId(collection.collectionId),185          substrateReceiver.addressRaw,186        )187        .send({from: ethSigner});188    },189  );190191  return {192    substrateFee: convertToTokens(substrateFee, nominal),193    ethFee: convertToTokens(ethFee, nominal),194    evmProxyContractFee: convertToTokens(evmProxyContractFee, nominal),195  };196}197198async function benchMintWithProperties(199  helper: EthUniqueHelper,200  privateKey: (seed: string) => Promise<IKeyringPair>,201  proxyContract: Contract,202  setup: { propertiesNumber: number },203): Promise<IBenchmarkResultForProp> {204  const donor = await privateKey('//Alice'); // Seed from account with balance on this network205  const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);206207  const susbstrateReceiver = await privateKey('//Bob');208  const receiverEthAddress = helper.address.substrateToEth(susbstrateReceiver.address);209210  const nominal = helper.balance.getOneTokenNominal();211212  const substrateFee = await calculateFeeNftMintWithProperties(213    helper,214    privateKey,215    {Substrate: donor.address},216    ethSigner,217    proxyContract.options.address,218    async (collection) => {219      await collection.mintToken(220        donor,221        {Substrate: susbstrateReceiver.address},222        PROPERTIES.slice(0, setup.propertiesNumber).map((p) => {223          return {key: p.key, value: Buffer.from(p.value).toString()};224        }),225      );226    },227  );228229  const ethFee = await calculateFeeNftMintWithProperties(230    helper,231    privateKey,232    {Substrate: donor.address},233    ethSigner,234    proxyContract.options.address,235    async (collection) => {236      const evmContract = await helper.ethNativeContract.collection(237        helper.ethAddress.fromCollectionId(collection.collectionId),238        'nft',239        undefined,240        true,241      );242243      const subTokenId = await evmContract.methods.nextTokenId().call();244245      let encodedCall = evmContract.methods246        .mint(receiverEthAddress)247        .encodeABI();248249      await helper.eth.sendEVM(250        donor,251        evmContract.options.address,252        encodedCall,253        '0',254      );255256      for (const val of PROPERTIES.slice(0, setup.propertiesNumber)) {257        encodedCall = await evmContract.methods258          .setProperty(subTokenId, val.key, Buffer.from(val.value))259          .encodeABI();260261        await helper.eth.sendEVM(262          donor,263          evmContract.options.address,264          encodedCall,265          '0',266        );267      }268    },269  );270271  const ethBulkFee = await calculateFeeNftMintWithProperties(272    helper,273    privateKey,274    {Substrate: donor.address},275    ethSigner,276    proxyContract.options.address,277    async (collection) => {278      const evmContract = await helper.ethNativeContract.collection(279        helper.ethAddress.fromCollectionId(collection.collectionId),280        'nft',281      );282283      const subTokenId = await evmContract.methods.nextTokenId().call();284285      let encodedCall = evmContract.methods286        .mint(receiverEthAddress)287        .encodeABI();288289      await helper.eth.sendEVM(290        donor,291        evmContract.options.address,292        encodedCall,293        '0',294      );295296      encodedCall = await evmContract.methods297        .setProperties(298          subTokenId,299          PROPERTIES.slice(0, setup.propertiesNumber),300        )301        .encodeABI();302303      await helper.eth.sendEVM(304        donor,305        evmContract.options.address,306        encodedCall,307        '0',308      );309    },310  );311312  const ethMintCrossFee = await calculateFeeNftMintWithProperties(313    helper,314    privateKey,315    {Ethereum: ethSigner},316    ethSigner,317    proxyContract.options.address,318    async (collection) => {319      const evmContract = await helper.ethNativeContract.collection(320        helper.ethAddress.fromCollectionId(collection.collectionId),321        'nft',322      );323324      await evmContract.methods.mintCross(325        helper.ethCrossAccount.fromAddress(receiverEthAddress),326        PROPERTIES.slice(0, setup.propertiesNumber),327      )328        .send({from: ethSigner});329    },330  );331332  const proxyContractFee = await calculateFeeNftMintWithProperties(333    helper,334    privateKey,335    {Ethereum: ethSigner},336    ethSigner,337    proxyContract.options.address,338    async (collection) => {339      await proxyContract.methods340        .mintToSubstrateWithProperty(341          helper.ethAddress.fromCollectionId(collection.collectionId),342          susbstrateReceiver.addressRaw,343          PROPERTIES.slice(0, setup.propertiesNumber),344        )345        .send({from: ethSigner});346    },347  );348349  const proxyContractBulkFee = await calculateFeeNftMintWithProperties(350    helper,351    privateKey,352    {Ethereum: ethSigner},353    ethSigner,354    proxyContract.options.address,355    async (collection) => {356      await proxyContract.methods357        .mintToSubstrateBulkProperty(358          helper.ethAddress.fromCollectionId(collection.collectionId),359          susbstrateReceiver.addressRaw,360          PROPERTIES.slice(0, setup.propertiesNumber),361        )362        .send({from: ethSigner, gas: 25_000_000});363    },364  );365366  return {367    propertiesNumber: setup.propertiesNumber,368    substrateFee: convertToTokens(substrateFee, nominal),369    ethFee: convertToTokens(ethFee, nominal),370    ethBulkFee: convertToTokens(ethBulkFee, nominal),371    ethMintCrossFee: convertToTokens(ethMintCrossFee, nominal),372    evmProxyContractFee: convertToTokens(proxyContractFee, nominal),373    evmProxyContractBulkFee: convertToTokens(proxyContractBulkFee, nominal),374  };375}376377async function calculateFeeNftMintWithProperties(378  helper: EthUniqueHelper,379  privateKey: (seed: string) => Promise<IKeyringPair>,380  payer: ICrossAccountId,381  ethSigner: string,382  proxyContractAddress: string,383  calculatedCall: (collection: UniqueNFTCollection) => Promise<any>,384): Promise<bigint> {385  const collection = (await createCollectionForBenchmarks(386    'nft',387    helper,388    privateKey,389    ethSigner,390    proxyContractAddress,391    PERMISSIONS,392  )) as UniqueNFTCollection;393  return helper.arrange.calculcateFee(payer, async () => {394    await calculatedCall(collection);395  });396}397398399