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

difftreelog

fix bencmark for fee calculation

PraetorP2023-01-16parent: #028059e.patch.diff
in: master
Fixed bugs caused by changes in the signatures of interface functions and data structures

2 files changed

modifiedtests/src/benchmarks/mintFee/benchmark.tsdiffbeforeafterboth
before · tests/src/benchmarks/mintFee/benchmark.ts
1import {EthUniqueHelper, usingEthPlaygrounds} from '../../eth/util';2import {readFile} from 'fs/promises';3import {ContractImports} from '../../eth/util/playgrounds/types';4import {5  ICrossAccountId,6  ITokenPropertyPermission,7} from '../../util/playgrounds/types';8import {IKeyringPair} from '@polkadot/types/types';9import {UniqueNFTCollection} from '../../util/playgrounds/unique';10import {Contract} from 'web3-eth-contract';11import {createObjectCsvWriter} from 'csv-writer';1213const 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];3536const PROPERTIES = Array(40)37  .fill(0)38  .map((_, i) => {39    return {40      key: `key_${i}`,41      value: Uint8Array.from(Buffer.from(`value_${i}`)),42    };43  });4445const PERMISSIONS: ITokenPropertyPermission[] = PROPERTIES.map((p) => {46  return {47    key: p.key,48    permission: {49      tokenOwner: true,50      collectionAdmin: true,51      mutable: true,52    },53  };54});5556interface IBenchmarkResultForProp {57	propertiesNumber: number;58	substrateFee: number;59	ethFee: number;60	ethBulkFee: number;61	evmProxyContractFee: number;62	evmProxyContractBulkFee: number;63}6465const main = async () => {66  const benchmarks = [67    'substrateFee',68    'ethFee',69    'ethBulkFee',70    'evmProxyContractFee',71    'evmProxyContractBulkFee',72  ];73  const headers = [74    'propertiesNumber',75    ...benchmarks,76  ];777879  const csvWriter = createObjectCsvWriter({80    path: 'properties.csv',81    header: headers,82  });8384  await usingEthPlaygrounds(async (helper, privateKey) => {85    const CONTRACT_SOURCE = (86      await readFile(`${__dirname}/proxyContract.sol`)87    ).toString();8889    const donor = await privateKey('//Alice'); // Seed from account with balance on this network90    const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);9192    const contract = await helper.ethContract.deployByCode(93      ethSigner,94      'ProxyMint',95      CONTRACT_SOURCE,96      CONTRACT_IMPORT,97    );9899    const fees = await benchMintFee(helper, privateKey, contract);100    console.log('Minting without properties');101    console.table(fees);102103    const result: IBenchmarkResultForProp[] = [];104    const csvResult: IBenchmarkResultForProp[] = [];105106    for (let i = 1; i <= 20; i++) {107      const benchResult = await benchMintWithProperties(helper, privateKey, contract, {108        propertiesNumber: i,109      }) as any;110111      csvResult.push(benchResult);112113      const minFee = Math.min(...(benchmarks.map(x => benchResult[x])));114      for(const key of benchmarks) {115        const keyPercent = Math.round((benchResult[key] / minFee) * 100);116        benchResult[key] = `${benchResult[key]} (${keyPercent}%)`;117      }118119      result.push(benchResult);120    }121122    await csvWriter.writeRecords(csvResult);123124    console.log('Minting with properties');125    console.table(result, headers);126  });127};128129main()130  .then(() => process.exit(0))131  .catch((e) => {132    console.log(e);133    process.exit(1);134  });135136async function createCollectionForBenchmarks(137  helper: EthUniqueHelper,138  privateKey: (seed: string) => Promise<IKeyringPair>,139  ethSigner: string,140  proxyContract: string,141  permissions: ITokenPropertyPermission[],142) {143  const donor = await privateKey('//Alice');144145  const collection = await helper.nft.mintCollection(donor, {146    name: 'test mintToSubstrate',147    description: 'EVMHelpers',148    tokenPrefix: 'ap',149    tokenPropertyPermissions: [150      {151        key: 'url',152        permission: {153          tokenOwner: true,154          collectionAdmin: true,155          mutable: true,156        },157      },158    ],159    limits: {sponsorTransferTimeout: 0, sponsorApproveTimeout: 0},160    permissions: {mintMode: true},161  });162163  await collection.addToAllowList(donor, {164    Ethereum: helper.address.substrateToEth(donor.address),165  });166  await collection.addToAllowList(donor, {Substrate: donor.address});167  await collection.addAdmin(donor, {Ethereum: ethSigner});168  await collection.addAdmin(donor, {169    Ethereum: helper.address.substrateToEth(donor.address),170  });171  await collection.addToAllowList(donor, {Ethereum: proxyContract});172  await collection.addAdmin(donor, {Ethereum: proxyContract});173  await collection.setTokenPropertyPermissions(donor, permissions);174175  return collection;176}177178async function benchMintFee(179  helper: EthUniqueHelper,180  privateKey: (seed: string) => Promise<IKeyringPair>,181  proxyContract: Contract,182): Promise<{183	substrateFee: number;184	ethFee: number;185	evmProxyContractFee: number;186}> {187  const donor = await privateKey('//Alice');188  const substrateReceiver = await privateKey('//Bob');189  const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);190191  const nominal = helper.balance.getOneTokenNominal();192193  await helper.eth.transferBalanceFromSubstrate(194    donor,195    proxyContract.options.address,196    100n,197  );198199  const collection = await createCollectionForBenchmarks(200    helper,201    privateKey,202    ethSigner,203    proxyContract.options.address,204    PERMISSIONS,205  );206207  const substrateFee = await helper.arrange.calculcateFee(208    {Substrate: donor.address},209    () => collection.mintToken(donor, {Substrate: substrateReceiver.address}),210  );211212  const collectionEthAddress = helper.ethAddress.fromCollectionId(collection.collectionId);213  const collectionContract = await helper.ethNativeContract.collection(214    collectionEthAddress,215    'nft',216  );217218  const receiverEthAddress = helper.address.substrateToEth(substrateReceiver.address);219220  const encodedCall = collectionContract.methods221    .mint(receiverEthAddress)222    .encodeABI();223224  const ethFee = await helper.arrange.calculcateFee(225    {Substrate: donor.address},226    async () => {227      await helper.eth.sendEVM(228        donor,229        collectionContract.options.address,230        encodedCall,231        '0',232      );233    },234  );235236  const evmProxyContractFee = await helper.arrange.calculcateFee(237    {Ethereum: ethSigner},238    async () => {239      await proxyContract.methods240        .mintToSubstrate(241          helper.ethAddress.fromCollectionId(collection.collectionId),242          substrateReceiver.addressRaw,243        )244        .send({from: ethSigner});245    },246  );247248  return {249    substrateFee: convertToTokens(substrateFee, nominal),250    ethFee: convertToTokens(ethFee, nominal),251    evmProxyContractFee: convertToTokens(evmProxyContractFee, nominal),252  };253}254255async function benchMintWithProperties(256  helper: EthUniqueHelper,257  privateKey: (seed: string) => Promise<IKeyringPair>,258  proxyContract: Contract,259  setup: { propertiesNumber: number },260): Promise<IBenchmarkResultForProp> {261  const donor = await privateKey('//Alice'); // Seed from account with balance on this network262  const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);263264  const susbstrateReceiver = await privateKey('//Bob');265  const receiverEthAddress = helper.address.substrateToEth(susbstrateReceiver.address);266267  const nominal = helper.balance.getOneTokenNominal();268269  const substrateFee = await calculateFeeNftMintWithProperties(270    helper,271    privateKey,272    {Substrate: donor.address},273    ethSigner,274    proxyContract.options.address,275    async (collection) => {276      await collection.mintToken(277        donor,278        {Substrate: susbstrateReceiver.address},279        PROPERTIES.slice(0, setup.propertiesNumber).map((p) => {280          return {key: p.key, value: Buffer.from(p.value).toString()};281        }),282      );283    },284  );285286  const ethFee = await calculateFeeNftMintWithProperties(287    helper,288    privateKey,289    {Substrate: donor.address},290    ethSigner,291    proxyContract.options.address,292    async (collection) => {293      const evmContract = await helper.ethNativeContract.collection(294        helper.ethAddress.fromCollectionId(collection.collectionId),295        'nft',296      );297298      const subTokenId = await evmContract.methods.nextTokenId().call();299300      let encodedCall = evmContract.methods301        .mint(receiverEthAddress)302        .encodeABI();303304      await helper.eth.sendEVM(305        donor,306        evmContract.options.address,307        encodedCall,308        '0',309      );310311      for (const val of PROPERTIES.slice(0, setup.propertiesNumber)) {312        encodedCall = await evmContract.methods313          .setProperty(subTokenId, val.key, Buffer.from(val.value))314          .encodeABI();315316        await helper.eth.sendEVM(317          donor,318          evmContract.options.address,319          encodedCall,320          '0',321        );322      }323    },324  );325326  const ethBulkFee = await calculateFeeNftMintWithProperties(327    helper,328    privateKey,329    {Substrate: donor.address},330    ethSigner,331    proxyContract.options.address,332    async (collection) => {333      const evmContract = await helper.ethNativeContract.collection(334        helper.ethAddress.fromCollectionId(collection.collectionId),335        'nft',336      );337338      const subTokenId = await evmContract.methods.nextTokenId().call();339340      let encodedCall = evmContract.methods341        .mint(receiverEthAddress)342        .encodeABI();343344      await helper.eth.sendEVM(345        donor,346        evmContract.options.address,347        encodedCall,348        '0',349      );350351      encodedCall = await evmContract.methods352        .setProperties(353          subTokenId,354          PROPERTIES.slice(0, setup.propertiesNumber).map((p) => {355            return {field_0: p.key, field_1: p.value};356          }),357        )358        .encodeABI();359360      await helper.eth.sendEVM(361        donor,362        evmContract.options.address,363        encodedCall,364        '0',365      );366    },367  );368369  const proxyContractFee = await calculateFeeNftMintWithProperties(370    helper,371    privateKey,372    {Ethereum: ethSigner},373    ethSigner,374    proxyContract.options.address,375    async (collection) => {376      await proxyContract.methods377        .mintToSubstrateWithProperty(378          helper.ethAddress.fromCollectionId(collection.collectionId),379          susbstrateReceiver.addressRaw,380          PROPERTIES.slice(0, setup.propertiesNumber),381        )382        .send({from: ethSigner});383    },384  );385386  const proxyContractBulkFee = await calculateFeeNftMintWithProperties(387    helper,388    privateKey,389    {Ethereum: ethSigner},390    ethSigner,391    proxyContract.options.address,392    async (collection) => {393      await proxyContract.methods394        .mintToSubstrateBulkProperty(395          helper.ethAddress.fromCollectionId(collection.collectionId),396          susbstrateReceiver.addressRaw,397          PROPERTIES.slice(0, setup.propertiesNumber).map((p) => {398            return {field_0: p.key, field_1: p.value};399          }),400        )401        .send({from: ethSigner, gas: 25_000_000});402    },403  );404405  return {406    propertiesNumber: setup.propertiesNumber,407    substrateFee: convertToTokens(substrateFee, nominal),408    ethFee: convertToTokens(ethFee, nominal),409    ethBulkFee: convertToTokens(ethBulkFee, nominal),410    evmProxyContractFee: convertToTokens(proxyContractFee, nominal),411    evmProxyContractBulkFee: convertToTokens(proxyContractBulkFee, nominal),412  };413}414415async function calculateFeeNftMintWithProperties(416  helper: EthUniqueHelper,417  privateKey: (seed: string) => Promise<IKeyringPair>,418  payer: ICrossAccountId,419  ethSigner: string,420  proxyContractAddress: string,421  calculatedCall: (collection: UniqueNFTCollection) => Promise<any>,422): Promise<bigint> {423  const collection = await createCollectionForBenchmarks(424    helper,425    privateKey,426    ethSigner,427    proxyContractAddress,428    PERMISSIONS,429  );430  return helper.arrange.calculcateFee(payer, async () => {431    await calculatedCall(collection);432  });433}434function convertToTokens(value: bigint, nominal: bigint): number {435  return Number((value * 1000n) / nominal) / 1000;436}
after · tests/src/benchmarks/mintFee/benchmark.ts
1import {EthUniqueHelper, usingEthPlaygrounds} from '../../eth/util';2import {readFile} from 'fs/promises';3import {ContractImports} from '../../eth/util/playgrounds/types';4import {5  ICrossAccountId,6  ITokenPropertyPermission,7} from '../../util/playgrounds/types';8import {IKeyringPair} from '@polkadot/types/types';9import {UniqueNFTCollection} from '../../util/playgrounds/unique';10import {Contract} from 'web3-eth-contract';11import {createObjectCsvWriter} from 'csv-writer';1213const 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];3536const PROPERTIES = Array(40)37  .fill(0)38  .map((_, i) => {39    return {40      key: `key_${i}`,41      value: Uint8Array.from(Buffer.from(`value_${i}`)),42    };43  });4445const PERMISSIONS: ITokenPropertyPermission[] = PROPERTIES.map((p) => {46  return {47    key: p.key,48    permission: {49      tokenOwner: true,50      collectionAdmin: true,51      mutable: true,52    },53  };54});5556interface IBenchmarkResultForProp {57	propertiesNumber: number;58	substrateFee: number;59	ethFee: number;60	ethBulkFee: number;61	evmProxyContractFee: number;62	evmProxyContractBulkFee: number;63}6465const main = async () => {66  const benchmarks = [67    'substrateFee',68    'ethFee',69    'ethBulkFee',70    'evmProxyContractFee',71    'evmProxyContractBulkFee',72  ];73  const headers = [74    'propertiesNumber',75    ...benchmarks,76  ];777879  const csvWriter = createObjectCsvWriter({80    path: 'properties.csv',81    header: headers,82  });8384  await usingEthPlaygrounds(async (helper, privateKey) => {85    const CONTRACT_SOURCE = (86      await readFile(`${__dirname}/proxyContract.sol`)87    ).toString();8889    const donor = await privateKey('//Alice'); // Seed from account with balance on this network90    const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);9192    const contract = await helper.ethContract.deployByCode(93      ethSigner,94      'ProxyMint',95      CONTRACT_SOURCE,96      CONTRACT_IMPORT,97    );9899    const fees = await benchMintFee(helper, privateKey, contract);100    console.log('Minting without properties');101    console.table(fees);102103    const result: IBenchmarkResultForProp[] = [];104    const csvResult: IBenchmarkResultForProp[] = [];105106    for (let i = 1; i <= 20; i++) {107      const benchResult = await benchMintWithProperties(helper, privateKey, contract, {108        propertiesNumber: i,109      }) as any;110111      csvResult.push(benchResult);112113      const minFee = Math.min(...(benchmarks.map(x => benchResult[x])));114      for(const key of benchmarks) {115        const keyPercent = Math.round((benchResult[key] / minFee) * 100);116        benchResult[key] = `${benchResult[key]} (${keyPercent}%)`;117      }118119      result.push(benchResult);120    }121122    await csvWriter.writeRecords(csvResult);123124    console.log('Minting with properties');125    console.table(result, headers);126  });127};128129main()130  .then(() => process.exit(0))131  .catch((e) => {132    console.log(e);133    process.exit(1);134  });135136async function createCollectionForBenchmarks(137  helper: EthUniqueHelper,138  privateKey: (seed: string) => Promise<IKeyringPair>,139  ethSigner: string,140  proxyContract: string,141  permissions: ITokenPropertyPermission[],142) {143  const donor = await privateKey('//Alice');144145  const collection = await helper.nft.mintCollection(donor, {146    name: 'test mintToSubstrate',147    description: 'EVMHelpers',148    tokenPrefix: 'ap',149    tokenPropertyPermissions: [150      {151        key: 'url',152        permission: {153          tokenOwner: true,154          collectionAdmin: true,155          mutable: true,156        },157      },158    ],159    limits: {sponsorTransferTimeout: 0, sponsorApproveTimeout: 0},160    permissions: {mintMode: true},161  });162163  await collection.addToAllowList(donor, {164    Ethereum: helper.address.substrateToEth(donor.address),165  });166  await collection.addToAllowList(donor, {Substrate: donor.address});167  await collection.addAdmin(donor, {Ethereum: ethSigner});168  await collection.addAdmin(donor, {169    Ethereum: helper.address.substrateToEth(donor.address),170  });171  await collection.addToAllowList(donor, {Ethereum: proxyContract});172  await collection.addAdmin(donor, {Ethereum: proxyContract});173  await collection.setTokenPropertyPermissions(donor, permissions);174175  return collection;176}177178async function benchMintFee(179  helper: EthUniqueHelper,180  privateKey: (seed: string) => Promise<IKeyringPair>,181  proxyContract: Contract,182): Promise<{183	substrateFee: number;184	ethFee: number;185	evmProxyContractFee: number;186}> {187  const donor = await privateKey('//Alice');188  const substrateReceiver = await privateKey('//Bob');189  const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);190191  const nominal = helper.balance.getOneTokenNominal();192193  await helper.eth.transferBalanceFromSubstrate(194    donor,195    proxyContract.options.address,196    100n,197  );198199  const collection = await createCollectionForBenchmarks(200    helper,201    privateKey,202    ethSigner,203    proxyContract.options.address,204    PERMISSIONS,205  );206207  const substrateFee = await helper.arrange.calculcateFee(208    {Substrate: donor.address},209    () => collection.mintToken(donor, {Substrate: substrateReceiver.address}),210  );211212  const collectionEthAddress = helper.ethAddress.fromCollectionId(collection.collectionId);213  const collectionContract = await helper.ethNativeContract.collection(214    collectionEthAddress,215    'nft',216  );217218  const receiverEthAddress = helper.address.substrateToEth(substrateReceiver.address);219220  const encodedCall = collectionContract.methods221    .mint(receiverEthAddress)222    .encodeABI();223224  const ethFee = await helper.arrange.calculcateFee(225    {Substrate: donor.address},226    async () => {227      await helper.eth.sendEVM(228        donor,229        collectionContract.options.address,230        encodedCall,231        '0',232      );233    },234  );235236  const evmProxyContractFee = await helper.arrange.calculcateFee(237    {Ethereum: ethSigner},238    async () => {239      await proxyContract.methods240        .mintToSubstrate(241          helper.ethAddress.fromCollectionId(collection.collectionId),242          substrateReceiver.addressRaw,243        )244        .send({from: ethSigner});245    },246  );247248  return {249    substrateFee: convertToTokens(substrateFee, nominal),250    ethFee: convertToTokens(ethFee, nominal),251    evmProxyContractFee: convertToTokens(evmProxyContractFee, nominal),252  };253}254255async function benchMintWithProperties(256  helper: EthUniqueHelper,257  privateKey: (seed: string) => Promise<IKeyringPair>,258  proxyContract: Contract,259  setup: { propertiesNumber: number },260): Promise<IBenchmarkResultForProp> {261  const donor = await privateKey('//Alice'); // Seed from account with balance on this network262  const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);263264  const susbstrateReceiver = await privateKey('//Bob');265  const receiverEthAddress = helper.address.substrateToEth(susbstrateReceiver.address);266267  const nominal = helper.balance.getOneTokenNominal();268269  const substrateFee = await calculateFeeNftMintWithProperties(270    helper,271    privateKey,272    {Substrate: donor.address},273    ethSigner,274    proxyContract.options.address,275    async (collection) => {276      await collection.mintToken(277        donor,278        {Substrate: susbstrateReceiver.address},279        PROPERTIES.slice(0, setup.propertiesNumber).map((p) => {280          return {key: p.key, value: Buffer.from(p.value).toString()};281        }),282      );283    },284  );285286  const ethFee = await calculateFeeNftMintWithProperties(287    helper,288    privateKey,289    {Substrate: donor.address},290    ethSigner,291    proxyContract.options.address,292    async (collection) => {293      const evmContract = await helper.ethNativeContract.collection(294        helper.ethAddress.fromCollectionId(collection.collectionId),295        'nft',296        undefined,297        true,298      );299300      const subTokenId = await evmContract.methods.nextTokenId().call();301302      let encodedCall = evmContract.methods303        .mint(receiverEthAddress)304        .encodeABI();305306      await helper.eth.sendEVM(307        donor,308        evmContract.options.address,309        encodedCall,310        '0',311      );312313      for (const val of PROPERTIES.slice(0, setup.propertiesNumber)) {314        encodedCall = await evmContract.methods315          .setProperty(subTokenId, val.key, Buffer.from(val.value))316          .encodeABI();317318        await helper.eth.sendEVM(319          donor,320          evmContract.options.address,321          encodedCall,322          '0',323        );324      }325    },326  );327328  const ethBulkFee = await calculateFeeNftMintWithProperties(329    helper,330    privateKey,331    {Substrate: donor.address},332    ethSigner,333    proxyContract.options.address,334    async (collection) => {335      const evmContract = await helper.ethNativeContract.collection(336        helper.ethAddress.fromCollectionId(collection.collectionId),337        'nft',338      );339340      const subTokenId = await evmContract.methods.nextTokenId().call();341342      let encodedCall = evmContract.methods343        .mint(receiverEthAddress)344        .encodeABI();345346      await helper.eth.sendEVM(347        donor,348        evmContract.options.address,349        encodedCall,350        '0',351      );352353      encodedCall = await evmContract.methods354        .setProperties(355          subTokenId,356          PROPERTIES.slice(0, setup.propertiesNumber),357        )358        .encodeABI();359360      await helper.eth.sendEVM(361        donor,362        evmContract.options.address,363        encodedCall,364        '0',365      );366    },367  );368369  const proxyContractFee = await calculateFeeNftMintWithProperties(370    helper,371    privateKey,372    {Ethereum: ethSigner},373    ethSigner,374    proxyContract.options.address,375    async (collection) => {376      await proxyContract.methods377        .mintToSubstrateWithProperty(378          helper.ethAddress.fromCollectionId(collection.collectionId),379          susbstrateReceiver.addressRaw,380          PROPERTIES.slice(0, setup.propertiesNumber),381        )382        .send({from: ethSigner});383    },384  );385386  const proxyContractBulkFee = await calculateFeeNftMintWithProperties(387    helper,388    privateKey,389    {Ethereum: ethSigner},390    ethSigner,391    proxyContract.options.address,392    async (collection) => {393      await proxyContract.methods394        .mintToSubstrateBulkProperty(395          helper.ethAddress.fromCollectionId(collection.collectionId),396          susbstrateReceiver.addressRaw,397          PROPERTIES.slice(0, setup.propertiesNumber),398        )399        .send({from: ethSigner, gas: 25_000_000});400    },401  );402403  return {404    propertiesNumber: setup.propertiesNumber,405    substrateFee: convertToTokens(substrateFee, nominal),406    ethFee: convertToTokens(ethFee, nominal),407    ethBulkFee: convertToTokens(ethBulkFee, nominal),408    evmProxyContractFee: convertToTokens(proxyContractFee, nominal),409    evmProxyContractBulkFee: convertToTokens(proxyContractBulkFee, nominal),410  };411}412413async function calculateFeeNftMintWithProperties(414  helper: EthUniqueHelper,415  privateKey: (seed: string) => Promise<IKeyringPair>,416  payer: ICrossAccountId,417  ethSigner: string,418  proxyContractAddress: string,419  calculatedCall: (collection: UniqueNFTCollection) => Promise<any>,420): Promise<bigint> {421  const collection = await createCollectionForBenchmarks(422    helper,423    privateKey,424    ethSigner,425    proxyContractAddress,426    PERMISSIONS,427  );428  return helper.arrange.calculcateFee(payer, async () => {429    await calculatedCall(collection);430  });431}432function convertToTokens(value: bigint, nominal: bigint): number {433  return Number((value * 1000n) / nominal) / 1000;434}
modifiedtests/src/benchmarks/mintFee/proxyContract.soldiffbeforeafterboth
--- a/tests/src/benchmarks/mintFee/proxyContract.sol
+++ b/tests/src/benchmarks/mintFee/proxyContract.sol
@@ -3,21 +3,44 @@
 import {CollectionHelpers} from "../../eth/api/CollectionHelpers.sol";
 import {ContractHelpers} from "../../eth/api/ContractHelpers.sol";
 import {UniqueRefungibleToken} from "../../eth/api/UniqueRefungibleToken.sol";
-import {UniqueRefungible, Collection, EthCrossAccount as RftCrossAccountId, Tuple20 as RftProperties} from "../../eth/api/UniqueRefungible.sol";
-import {UniqueNFT, EthCrossAccount as NftCrossAccountId, Tuple21 as NftProperty, TokenProperties} from "../../eth/api/UniqueNFT.sol";
+import {UniqueRefungible, Collection, CrossAddress as RftCrossAccountId, Property as RftProperty} from "../../eth/api/UniqueRefungible.sol";
+import {UniqueNFT, CrossAddress as NftCrossAccountId, Property as NftProperty} from "../../eth/api/UniqueNFT.sol";
 
 struct Property {
 	string key;
 	bytes value;
 }
 
+interface SoftDeprecatedMethods {
+	/// @notice Set token property value.
+	/// @dev Throws error if `msg.sender` has no permission to edit the property.
+	/// @param tokenId ID of the token.
+	/// @param key Property key.
+	/// @param value Property value.
+	/// @dev EVM selector for this function is: 0x1752d67b,
+	///  or in textual repr: setProperty(uint256,string,bytes)
+	function setProperty(
+		uint256 tokenId,
+		string memory key,
+		bytes memory value
+	) external;
+}
+
+interface BenchUniqueRefungible is UniqueRefungible, SoftDeprecatedMethods {}
+interface BenchUniqueNFT is UniqueNFT, SoftDeprecatedMethods {}
+
+
+
 contract ProxyMint {
 	bytes32 constant REFUNGIBLE_COLLECTION_TYPE = keccak256(bytes("ReFungible"));
 	bytes32 constant NONFUNGIBLE_COLLECTION_TYPE = keccak256(bytes("NFT"));
 
 	modifier checkRestrictions(address _collection) {
 		Collection commonContract = Collection(_collection);
-		require(commonContract.isOwnerOrAdmin(msg.sender), "Only collection admin/owner can call this method");
+		require(
+			commonContract.isOwnerOrAdminCross(RftCrossAccountId(msg.sender, 0)),
+			"Only collection admin/owner can call this method"
+		);
 		_;
 	}
 
@@ -58,9 +81,9 @@
 	function mintToSubstrateWithProperty(
 		address _collection,
 		uint256 _substrateReceiver,
-		Property[] calldata properties
+		Property[] calldata _properties
 	) external checkRestrictions(_collection) {
-		uint256 propertiesLength = properties.length;
+		uint256 propertiesLength = _properties.length;
 		require(propertiesLength > 0, "Properies is empty");
 
 		Collection commonContract = Collection(_collection);
@@ -68,11 +91,12 @@
 		uint256 tokenId;
 
 		if (collectionType == REFUNGIBLE_COLLECTION_TYPE) {
-			UniqueRefungible rftCollection = UniqueRefungible(_collection);
+			BenchUniqueRefungible rftCollection = BenchUniqueRefungible(_collection);
 			tokenId = rftCollection.nextTokenId();
 			rftCollection.mint(address(this));
+
 			for (uint256 i = 0; i < propertiesLength; ++i) {
-				rftCollection.setProperty(tokenId, properties[i].key, properties[i].value);
+				rftCollection.setProperty(tokenId, _properties[i].key, _properties[i].value);
 			}
 			rftCollection.transferFromCross(
 				RftCrossAccountId(address(this), 0),
@@ -80,10 +104,10 @@
 				tokenId
 			);
 		} else if (collectionType == NONFUNGIBLE_COLLECTION_TYPE) {
-			UniqueNFT nftCollection = UniqueNFT(_collection);
+			BenchUniqueNFT nftCollection = BenchUniqueNFT(_collection);
 			tokenId = nftCollection.mint(address(this));
 			for (uint256 i = 0; i < propertiesLength; ++i) {
-				nftCollection.setProperty(tokenId, properties[i].key, properties[i].value);
+				nftCollection.setProperty(tokenId, _properties[i].key, _properties[i].value);
 			}
 			nftCollection.transferFromCross(
 				NftCrossAccountId(address(this), 0),