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

difftreelog

Style fixes

Andrey2022-11-11parent: #44da5f8.patch.diff
in: master

6 files changed

modifiedtests/.gitignorediffbeforeafterboth
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -1 +1,2 @@
 /node_modules/
+properties.csv
modifiedtests/package.jsondiffbeforeafterboth
before · tests/package.json
1{2  "name": "unique-tests",3  "version": "1.0.0",4  "description": "Unique Chain Tests",5  "main": "",6  "devDependencies": {7    "@polkadot/typegen": "9.5.2",8    "@types/chai": "^4.3.3",9    "@types/chai-as-promised": "^7.1.5",10    "@types/chai-like": "^1.1.1",11    "@types/mocha": "^10.0.0",12    "@types/node": "^18.11.2",13    "@typescript-eslint/eslint-plugin": "^5.40.1",14    "@typescript-eslint/parser": "^5.40.1",15    "chai": "^4.3.6",16    "eslint": "^8.25.0",17    "eslint-plugin-mocha": "^10.1.0",18    "mocha": "^10.1.0",19    "ts-node": "^10.9.1",20    "typescript": "^4.8.4"21  },22  "mocha": {23    "timeout": 9999999,24    "require": [25      "ts-node/register"26    ]27  },28  "scripts": {29    "lint": "eslint --ext .ts,.js src/",30    "fix": "eslint --ext .ts,.js src/ --fix",31    "setup": "ts-node ./src/util/globalSetup.ts",32    "test": "yarn setup && mocha --timeout 9999999 -r ts-node/register './src/**/*.*test.ts'",33    "testParallelFull": "yarn testParallel && yarn testSequential",34    "testParallel": "yarn setup && mocha --parallel --timeout 9999999 -r ts-node/register './src/**/*.test.ts'",35    "testSequential": "yarn setup && mocha --timeout 9999999 -r ts-node/register './src/**/*.seqtest.ts'",36    "testStructure": "yarn setup && mocha --timeout 9999999 -r ts-node/register ./**/nesting/*.*test.ts",37    "testEth": "yarn setup && mocha --timeout 9999999 -r ts-node/register './**/eth/**/*.*test.ts'",38    "testEthNesting": "yarn setup && mocha --timeout 9999999 -r ts-node/register './**/eth/nesting/**/*.*test.ts'",39    "testEthFractionalizer": "yarn setup && mocha --timeout 9999999 -r ts-node/register './**/eth/fractionalizer/**/*.*test.ts'",40    "testEthMarketplace": "yarn setup && mocha --timeout 9999999 -r ts-node/register './**/eth/marketplace/**/*.*test.ts'",41    "testEvent": "yarn setup && mocha --timeout 9999999 -r ts-node/register ./src/check-event/*.*test.ts",42    "testRmrk": "yarn setup && mocha --timeout 9999999 -r ts-node/register ./**/rmrk/*.*test.ts",43    "testEthPayable": "mocha --timeout 9999999 -r ts-node/register './**/eth/payable.test.ts'",44    "testEthTokenProperties": "mocha --timeout 9999999 -r ts-node/register ./**/eth/tokenProperties.test.ts",45    "testEvmCoder": "mocha --timeout 9999999 -r ts-node/register './**/eth/evmCoder.test.ts'",46    "testNesting": "mocha --timeout 9999999 -r ts-node/register ./**/nest.test.ts",47    "testUnnesting": "mocha --timeout 9999999 -r ts-node/register ./**/unnest.test.ts",48    "testProperties": "mocha --timeout 9999999 -r ts-node/register ./**/properties.test.ts ./**/getPropertiesRpc.test.ts",49    "testMigration": "mocha --timeout 9999999 -r ts-node/register ./**/nesting/migration-check.test.ts",50    "testAddCollectionAdmin": "mocha --timeout 9999999 -r ts-node/register ./**/addCollectionAdmin.test.ts",51    "testSetCollectionLimits": "mocha --timeout 9999999 -r ts-node/register ./**/setCollectionLimits.test.ts",52    "testChangeCollectionOwner": "mocha --timeout 9999999 -r ts-node/register ./**/change-collection-owner.test.ts",53    "testSetCollectionSponsor": "mocha --timeout 9999999 -r ts-node/register ./**/setCollectionSponsor.test.ts",54    "testConfirmSponsorship": "mocha --timeout 9999999 --parallel -r ts-node/register ./**/confirmSponsorship.test.ts",55    "testRemoveCollectionAdmin": "mocha --timeout 9999999 -r ts-node/register ./**/removeCollectionAdmin.test.ts",56    "testRemoveCollectionSponsor": "mocha --timeout 9999999 -r ts-node/register ./**/removeCollectionSponsor.test.ts",57    "testAllowLists": "mocha --timeout 9999999 -r ts-node/register ./**/allowLists.test.ts",58    "testConnection": "mocha --timeout 9999999 -r ts-node/register ./**/connection.test.ts",59    "testContracts": "mocha --timeout 9999999 -r ts-node/register ./**/contracts.test.ts",60    "testCreateItem": "mocha --timeout 9999999 -r ts-node/register ./**/createItem.test.ts",61    "testCreateMultipleItems": "mocha --timeout 9999999 -r ts-node/register ./**/createMultipleItems.test.ts",62    "testCreateMultipleItemsEx": "mocha --timeout 9999999 -r ts-node/register ./**/createMultipleItemsEx.test.ts",63    "testApprove": "mocha --timeout 9999999 -r ts-node/register ./**/approve.test.ts",64    "testTransferFrom": "mocha --timeout 9999999 -r ts-node/register ./**/transferFrom.test.ts",65    "testCreateCollection": "mocha --timeout 9999999 -r ts-node/register ./**/createCollection.test.ts",66    "testDestroyCollection": "mocha --timeout 9999999 -r ts-node/register ./**/destroyCollection.test.ts",67    "testToggleContractAllowList": "mocha --timeout 9999999 -r ts-node/register ./**/toggleContractAllowList.test.ts",68    "testAddToContractAllowList": "mocha --timeout 9999999 -r ts-node/register ./**/addToContractAllowList.test.ts",69    "testTransfer": "mocha --timeout 9999999 -r ts-node/register ./**/transfer.test.ts",70    "testBurnItem": "mocha --timeout 9999999 -r ts-node/register ./**/burnItem.test.ts",71    "testAdminTransferAndBurn": "mocha --timeout 9999999 -r ts-node/register ./**/adminTransferAndBurn.test.ts",72    "testSetPermissions": "mocha --timeout 9999999 -r ts-node/register ./**/setPermissions.test.ts",73    "testCreditFeesToTreasury": "mocha --timeout 9999999 -r ts-node/register ./**/creditFeesToTreasury.seqtest.ts",74    "testContractSponsoring": "mocha --timeout 9999999 -r ts-node/register ./**/eth/contractSponsoring.test.ts",75    "testEnableContractSponsoring": "mocha --timeout 9999999 -r ts-node/register ./**/enableContractSponsoring.test.ts",76    "testRemoveFromContractAllowList": "mocha --timeout 9999999 -r ts-node/register ./**/removeFromContractAllowList.test.ts",77    "testSetContractSponsoringRateLimit": "mocha --timeout 9999999 -r ts-node/register ./**/setContractSponsoringRateLimit.test.ts",78    "testSetOffchainSchema": "mocha --timeout 9999999 -r ts-node/register ./**/setOffchainSchema.test.ts",79    "testNextSponsoring": "mocha --timeout 9999999 -r ts-node/register ./**/nextSponsoring.test.ts",80    "testOverflow": "mocha --timeout 9999999 -r ts-node/register ./**/overflow.test.ts",81    "testMaintenance": "mocha --timeout 9999999 -r ts-node/register ./**/maintenanceMode.seqtest.ts",82    "testInflation": "mocha --timeout 9999999 -r ts-node/register ./**/inflation.seqtest.ts",83    "testScheduler": "mocha --timeout 9999999 -r ts-node/register ./**/scheduler.seqtest.ts",84    "testSchedulingEVM": "mocha --timeout 9999999 -r ts-node/register ./**/eth/scheduling.test.ts",85    "testPalletPresence": "mocha --timeout 9999999 -r ts-node/register ./**/pallet-presence.test.ts",86    "testBlockProduction": "mocha --timeout 9999999 -r ts-node/register ./**/block-production.test.ts",87    "testEnableDisableTransfers": "mocha --timeout 9999999 -r ts-node/register ./**/enableDisableTransfer.test.ts",88    "testLimits": "mocha --timeout 9999999 -r ts-node/register ./**/limits.test.ts",89    "testEthCreateNFTCollection": "mocha --timeout 9999999 -r ts-node/register ./**/eth/createNFTCollection.test.ts",90    "testEthCreateRFTCollection": "mocha --timeout 9999999 -r ts-node/register ./**/eth/createRFTCollection.test.ts",91    "testEthNFT": "mocha --timeout 9999999 -r ts-node/register ./**/eth/nonFungible.test.ts",92    "testRFT": "mocha --timeout 9999999 -r ts-node/register ./**/refungible.test.ts",93    "testEthRFT": "mocha --timeout 9999999 -r ts-node/register ./**/eth/reFungible.test.ts ./**/eth/reFungibleToken.test.ts",94    "testFT": "mocha --timeout 9999999 -r ts-node/register ./**/fungible.test.ts",95    "testEthFT": "mocha --timeout 9999999 -r ts-node/register ./**/eth/fungible.test.ts",96    "testRPC": "mocha --timeout 9999999 -r ts-node/register ./**/rpc.test.ts",97    "testPromotion": "yarn setup && mocha --timeout 9999999 -r ts-node/register ./**/app-promotion.*test.ts",98    "testXcmUnique": "RUN_XCM_TESTS=1 mocha --timeout 9999999 -r ts-node/register ./**/xcm/xcmUnique.test.ts",99    "testXcmQuartz": "RUN_XCM_TESTS=1 mocha --timeout 9999999 -r ts-node/register ./**/xcm/xcmQuartz.test.ts",100    "testXcmOpal": "RUN_XCM_TESTS=1 mocha --timeout 9999999 -r ts-node/register ./**/xcm/xcmOpal.test.ts",101    "testXcmTransferAcala": "mocha --timeout 9999999 -r ts-node/register ./**/xcm/xcmTransferAcala.test.ts acalaId=2000 uniqueId=5000",102    "testXcmTransferStatemine": "mocha --timeout 9999999 -r ts-node/register ./**/xcm/xcmTransferStatemine.test.ts statemineId=1000 uniqueId=5000",103    "testXcmTransferMoonbeam": "mocha --timeout 9999999 -r ts-node/register ./**/xcm/xcmTransferMoonbeam.test.ts",104    "load": "mocha --timeout 9999999 -r ts-node/register './**/*.load.ts'",105    "loadTransfer": "ts-node src/transfer.nload.ts",106    "polkadot-types-fetch-metadata": "curl -H 'Content-Type: application/json' -d '{\"id\":\"1\", \"jsonrpc\":\"2.0\", \"method\": \"state_getMetadata\", \"params\":[]}' http://localhost:9933 > src/interfaces/metadata.json",107    "polkadot-types-from-defs": "ts-node ./node_modules/.bin/polkadot-types-from-defs --endpoint src/interfaces/metadata.json --input src/interfaces/ --package .",108    "polkadot-types-from-chain": "ts-node ./node_modules/.bin/polkadot-types-from-chain --endpoint src/interfaces/metadata.json --output src/interfaces/ --package .",109    "polkadot-types": "echo \"export default {}\" > src/interfaces/lookup.ts && yarn polkadot-types-fetch-metadata && yarn polkadot-types-from-defs && yarn polkadot-types-from-defs && yarn polkadot-types-from-chain"110  },111  "author": "",112  "license": "SEE LICENSE IN ../LICENSE",113  "homepage": "",114  "dependencies": {115    "@polkadot/api": "9.5.2",116    "@polkadot/util-crypto": "10.1.11",117    "chai-as-promised": "^7.1.1",118    "chai-like": "^1.1.1",119    "csv-writer": "^1.6.0",120    "find-process": "^1.4.7",121    "solc": "0.8.17",122    "web3": "^1.8.0"123  }124}
addedtests/src/benchmarks/mintFee/benchmark.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/benchmarks/mintFee/benchmark.ts
@@ -0,0 +1,436 @@
+import {EthUniqueHelper, usingEthPlaygrounds} from '../../eth/util';
+import {readFile} from 'fs/promises';
+import {ContractImports} from '../../eth/util/playgrounds/types';
+import {
+  ICrossAccountId,
+  ITokenPropertyPermission,
+} from '../../util/playgrounds/types';
+import {IKeyringPair} from '@polkadot/types/types';
+import {UniqueNFTCollection} from '../../util/playgrounds/unique';
+import {Contract} from 'web3-eth-contract';
+import {createObjectCsvWriter} from 'csv-writer';
+
+const CONTRACT_IMPORT: ContractImports[] = [
+  {
+    fsPath: `${__dirname}/../../eth/api/CollectionHelpers.sol`,
+    solPath: 'eth/api/CollectionHelpers.sol',
+  },
+  {
+    fsPath: `${__dirname}/../../eth/api/ContractHelpers.sol`,
+    solPath: 'eth/api/ContractHelpers.sol',
+  },
+  {
+    fsPath: `${__dirname}/../../eth/api/UniqueRefungibleToken.sol`,
+    solPath: 'eth/api/UniqueRefungibleToken.sol',
+  },
+  {
+    fsPath: `${__dirname}/../../eth/api/UniqueRefungible.sol`,
+    solPath: 'eth/api/UniqueRefungible.sol',
+  },
+  {
+    fsPath: `${__dirname}/../../eth/api/UniqueNFT.sol`,
+    solPath: 'eth/api/UniqueNFT.sol',
+  },
+];
+
+const PROPERTIES = Array(40)
+  .fill(0)
+  .map((_, i) => {
+    return {
+      key: `key_${i}`,
+      value: Uint8Array.from(Buffer.from(`value_${i}`)),
+    };
+  });
+
+const PERMISSIONS: ITokenPropertyPermission[] = PROPERTIES.map((p) => {
+  return {
+    key: p.key,
+    permission: {
+      tokenOwner: true,
+      collectionAdmin: true,
+      mutable: true,
+    },
+  };
+});
+
+interface IBenchmarkResultForProp {
+	propertiesNumber: number;
+	substrateFee: number;
+	ethFee: number;
+	ethBulkFee: number;
+	evmProxyContractFee: number;
+	evmProxyContractBulkFee: number;
+}
+
+const main = async () => {
+  const benchmarks = [
+    'substrateFee',
+    'ethFee',
+    'ethBulkFee',
+    'evmProxyContractFee',
+    'evmProxyContractBulkFee',
+  ];
+  const headers = [
+    'propertiesNumber',
+    ...benchmarks,
+  ];
+
+
+  const csvWriter = createObjectCsvWriter({
+    path: 'properties.csv',
+    header: headers,
+  });
+
+  await usingEthPlaygrounds(async (helper, privateKey) => {
+    const CONTRACT_SOURCE = (
+      await readFile(`${__dirname}/proxyContract.sol`)
+    ).toString();
+
+    const donor = await privateKey('//Alice'); // Seed from account with balance on this network
+    const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);
+
+    const contract = await helper.ethContract.deployByCode(
+      ethSigner,
+      'ProxyMint',
+      CONTRACT_SOURCE,
+      CONTRACT_IMPORT,
+    );
+
+    const fees = await benchMintFee(helper, privateKey, contract);
+    console.log('Minting without properties');
+    console.table(fees);
+
+    const result: IBenchmarkResultForProp[] = [];
+    const csvResult: IBenchmarkResultForProp[] = [];
+
+    for (let i = 1; i <= 20; i++) {
+      const benchResult = await benchMintWithProperties(helper, privateKey, contract, {
+        propertiesNumber: i,
+      }) as any;
+
+      csvResult.push(benchResult);
+
+      const minFee = Math.min(...(benchmarks.map(x => benchResult[x])));
+      for(const key of benchmarks) {
+        const keyPercent = Math.round((benchResult[key] / minFee) * 100);
+        benchResult[key] = `${benchResult[key]} (${keyPercent}%)`;
+      }
+
+      result.push(benchResult);
+    }
+
+    await csvWriter.writeRecords(csvResult);
+
+    console.log('Minting with properties');
+    console.table(result, headers);
+  });
+};
+
+main()
+  .then(() => process.exit(0))
+  .catch((e) => {
+    console.log(e);
+    process.exit(1);
+  });
+
+async function createCollectionForBenchmarks(
+  helper: EthUniqueHelper,
+  privateKey: (seed: string) => Promise<IKeyringPair>,
+  ethSigner: string,
+  proxyContract: string,
+  permissions: ITokenPropertyPermission[],
+) {
+  const donor = await privateKey('//Alice');
+
+  const collection = await helper.nft.mintCollection(donor, {
+    name: 'test mintToSubstrate',
+    description: 'EVMHelpers',
+    tokenPrefix: 'ap',
+    tokenPropertyPermissions: [
+      {
+        key: 'url',
+        permission: {
+          tokenOwner: true,
+          collectionAdmin: true,
+          mutable: true,
+        },
+      },
+    ],
+    limits: {sponsorTransferTimeout: 0, sponsorApproveTimeout: 0},
+    permissions: {mintMode: true},
+  });
+
+  await collection.addToAllowList(donor, {
+    Ethereum: helper.address.substrateToEth(donor.address),
+  });
+  await collection.addToAllowList(donor, {Substrate: donor.address});
+  await collection.addAdmin(donor, {Ethereum: ethSigner});
+  await collection.addAdmin(donor, {
+    Ethereum: helper.address.substrateToEth(donor.address),
+  });
+  await collection.addToAllowList(donor, {Ethereum: proxyContract});
+  await collection.addAdmin(donor, {Ethereum: proxyContract});
+  await collection.setTokenPropertyPermissions(donor, permissions);
+
+  return collection;
+}
+
+async function benchMintFee(
+  helper: EthUniqueHelper,
+  privateKey: (seed: string) => Promise<IKeyringPair>,
+  proxyContract: Contract,
+): Promise<{
+	substrateFee: number;
+	ethFee: number;
+	evmProxyContractFee: number;
+}> {
+  const donor = await privateKey('//Alice');
+  const substrateReceiver = await privateKey('//Bob');
+  const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);
+
+  const nominal = helper.balance.getOneTokenNominal();
+
+  await helper.eth.transferBalanceFromSubstrate(
+    donor,
+    proxyContract.options.address,
+    100n,
+  );
+
+  const collection = await createCollectionForBenchmarks(
+    helper,
+    privateKey,
+    ethSigner,
+    proxyContract.options.address,
+    PERMISSIONS,
+  );
+
+  const substrateFee = await helper.arrange.calculcateFee(
+    {Substrate: donor.address},
+    () => collection.mintToken(donor, {Substrate: substrateReceiver.address}),
+  );
+
+  const collectionEthAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+  const collectionContract = helper.ethNativeContract.collection(
+    collectionEthAddress,
+    'nft',
+  );
+
+  const receiverEthAddress = helper.address.substrateToEth(substrateReceiver.address);
+
+  const encodedCall = collectionContract.methods
+    .mint(receiverEthAddress)
+    .encodeABI();
+
+  const ethFee = await helper.arrange.calculcateFee(
+    {Substrate: donor.address},
+    async () => {
+      await helper.eth.sendEVM(
+        donor,
+        collectionContract.options.address,
+        encodedCall,
+        '0',
+      );
+    },
+  );
+
+  const evmProxyContractFee = await helper.arrange.calculcateFee(
+    {Ethereum: ethSigner},
+    async () => {
+      await proxyContract.methods
+        .mintToSubstrate(
+          helper.ethAddress.fromCollectionId(collection.collectionId),
+          substrateReceiver.addressRaw,
+        )
+        .send({from: ethSigner});
+    },
+  );
+
+  return {
+    substrateFee: convertToTokens(substrateFee, nominal),
+    ethFee: convertToTokens(ethFee, nominal),
+    evmProxyContractFee: convertToTokens(evmProxyContractFee, nominal),
+  };
+}
+
+async function benchMintWithProperties(
+  helper: EthUniqueHelper,
+  privateKey: (seed: string) => Promise<IKeyringPair>,
+  proxyContract: Contract,
+  setup: { propertiesNumber: number },
+): Promise<IBenchmarkResultForProp> {
+  const donor = await privateKey('//Alice'); // Seed from account with balance on this network
+  const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);
+
+  const susbstrateReceiver = await privateKey('//Bob');
+  const receiverEthAddress = helper.address.substrateToEth(susbstrateReceiver.address);
+
+  const nominal = helper.balance.getOneTokenNominal();
+
+  const substrateFee = await calculateFeeNftMintWithProperties(
+    helper,
+    privateKey,
+    {Substrate: donor.address},
+    ethSigner,
+    proxyContract.options.address,
+    async (collection) => {
+      await collection.mintToken(
+        donor,
+        {Substrate: susbstrateReceiver.address},
+        PROPERTIES.slice(0, setup.propertiesNumber).map((p) => {
+          return {key: p.key, value: Buffer.from(p.value).toString()};
+        }),
+      );
+    },
+  );
+
+  const ethFee = await calculateFeeNftMintWithProperties(
+    helper,
+    privateKey,
+    {Substrate: donor.address},
+    ethSigner,
+    proxyContract.options.address,
+    async (collection) => {
+      const evmContract = helper.ethNativeContract.collection(
+        helper.ethAddress.fromCollectionId(collection.collectionId),
+        'nft',
+      );
+
+      const subTokenId = await evmContract.methods.nextTokenId().call();
+
+      let encodedCall = evmContract.methods
+        .mint(receiverEthAddress)
+        .encodeABI();
+
+      await helper.eth.sendEVM(
+        donor,
+        evmContract.options.address,
+        encodedCall,
+        '0',
+      );
+
+      for (const val of PROPERTIES.slice(0, setup.propertiesNumber)) {
+        encodedCall = await evmContract.methods
+          .setProperty(subTokenId, val.key, Buffer.from(val.value))
+          .encodeABI();
+
+        await helper.eth.sendEVM(
+          donor,
+          evmContract.options.address,
+          encodedCall,
+          '0',
+        );
+      }
+    },
+  );
+
+  const ethBulkFee = await calculateFeeNftMintWithProperties(
+    helper,
+    privateKey,
+    {Substrate: donor.address},
+    ethSigner,
+    proxyContract.options.address,
+    async (collection) => {
+      const evmContract = helper.ethNativeContract.collection(
+        helper.ethAddress.fromCollectionId(collection.collectionId),
+        'nft',
+      );
+
+      const subTokenId = await evmContract.methods.nextTokenId().call();
+
+      let encodedCall = evmContract.methods
+        .mint(receiverEthAddress)
+        .encodeABI();
+
+      await helper.eth.sendEVM(
+        donor,
+        evmContract.options.address,
+        encodedCall,
+        '0',
+      );
+
+      encodedCall = await evmContract.methods
+        .setProperties(
+          subTokenId,
+          PROPERTIES.slice(0, setup.propertiesNumber).map((p) => {
+            return {field_0: p.key, field_1: p.value};
+          }),
+        )
+        .encodeABI();
+
+      await helper.eth.sendEVM(
+        donor,
+        evmContract.options.address,
+        encodedCall,
+        '0',
+      );
+    },
+  );
+
+  const proxyContractFee = await calculateFeeNftMintWithProperties(
+    helper,
+    privateKey,
+    {Ethereum: ethSigner},
+    ethSigner,
+    proxyContract.options.address,
+    async (collection) => {
+      await proxyContract.methods
+        .mintToSubstrateWithProperty(
+          helper.ethAddress.fromCollectionId(collection.collectionId),
+          susbstrateReceiver.addressRaw,
+          PROPERTIES.slice(0, setup.propertiesNumber),
+        )
+        .send({from: ethSigner});
+    },
+  );
+
+  const proxyContractBulkFee = await calculateFeeNftMintWithProperties(
+    helper,
+    privateKey,
+    {Ethereum: ethSigner},
+    ethSigner,
+    proxyContract.options.address,
+    async (collection) => {
+      await proxyContract.methods
+        .mintToSubstrateBulkProperty(
+          helper.ethAddress.fromCollectionId(collection.collectionId),
+          susbstrateReceiver.addressRaw,
+          PROPERTIES.slice(0, setup.propertiesNumber).map((p) => {
+            return {field_0: p.key, field_1: p.value};
+          }),
+        )
+        .send({from: ethSigner, gas: 25_000_000});
+    },
+  );
+
+  return {
+    propertiesNumber: setup.propertiesNumber,
+    substrateFee: convertToTokens(substrateFee, nominal),
+    ethFee: convertToTokens(ethFee, nominal),
+    ethBulkFee: convertToTokens(ethBulkFee, nominal),
+    evmProxyContractFee: convertToTokens(proxyContractFee, nominal),
+    evmProxyContractBulkFee: convertToTokens(proxyContractBulkFee, nominal),
+  };
+}
+
+async function calculateFeeNftMintWithProperties(
+  helper: EthUniqueHelper,
+  privateKey: (seed: string) => Promise<IKeyringPair>,
+  payer: ICrossAccountId,
+  ethSigner: string,
+  proxyContractAddress: string,
+  calculatedCall: (collection: UniqueNFTCollection) => Promise<any>,
+): Promise<bigint> {
+  const collection = await createCollectionForBenchmarks(
+    helper,
+    privateKey,
+    ethSigner,
+    proxyContractAddress,
+    PERMISSIONS,
+  );
+  return helper.arrange.calculcateFee(payer, async () => {
+    await calculatedCall(collection);
+  });
+}
+function convertToTokens(value: bigint, nominal: bigint): number {
+  return Number((value * 1000n) / nominal) / 1000;
+}
addedtests/src/benchmarks/mintFee/proxyContract.soldiffbeforeafterboth
--- /dev/null
+++ b/tests/src/benchmarks/mintFee/proxyContract.sol
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier:  Apache License
+pragma solidity >=0.8.0;
+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";
+
+struct Property {
+	string key;
+	bytes value;
+}
+
+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");
+		_;
+	}
+
+	/// @dev This emits when a mint to a substrate address has been made.
+	event MintToSub(address _toEth, uint256 _toSub, address _collection, uint256 _tokenId);
+
+	function mintToSubstrate(address _collection, uint256 _substrateReceiver) external checkRestrictions(_collection) {
+		Collection commonContract = Collection(_collection);
+		bytes32 collectionType = keccak256(bytes(commonContract.uniqueCollectionType()));
+		uint256 tokenId;
+
+		if (collectionType == REFUNGIBLE_COLLECTION_TYPE) {
+			UniqueRefungible rftCollection = UniqueRefungible(_collection);
+
+			tokenId = rftCollection.mint(address(this));
+
+			rftCollection.transferFromCross(
+				RftCrossAccountId(address(this), 0),
+				RftCrossAccountId(address(0), _substrateReceiver),
+				tokenId
+			);
+		} else if (collectionType == NONFUNGIBLE_COLLECTION_TYPE) {
+			UniqueNFT nftCollection = UniqueNFT(_collection);
+			tokenId = nftCollection.mint(address(this));
+
+			nftCollection.transferFromCross(
+				NftCrossAccountId(address(this), 0),
+				NftCrossAccountId(address(0), _substrateReceiver),
+				tokenId
+			);
+		} else {
+			revert("Wrong collection type. Works only with NFT or RFT");
+		}
+
+		emit MintToSub(address(0), _substrateReceiver, _collection, tokenId);
+	}
+
+	function mintToSubstrateWithProperty(
+		address _collection,
+		uint256 _substrateReceiver,
+		Property[] calldata properties
+	) external checkRestrictions(_collection) {
+		uint256 propertiesLength = properties.length;
+		require(propertiesLength > 0, "Properies is empty");
+
+		Collection commonContract = Collection(_collection);
+		bytes32 collectionType = keccak256(bytes(commonContract.uniqueCollectionType()));
+		uint256 tokenId;
+
+		if (collectionType == REFUNGIBLE_COLLECTION_TYPE) {
+			UniqueRefungible rftCollection = UniqueRefungible(_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.transferFromCross(
+				RftCrossAccountId(address(this), 0),
+				RftCrossAccountId(address(0), _substrateReceiver),
+				tokenId
+			);
+		} else if (collectionType == NONFUNGIBLE_COLLECTION_TYPE) {
+			UniqueNFT nftCollection = UniqueNFT(_collection);
+			tokenId = nftCollection.mint(address(this));
+			for (uint256 i = 0; i < propertiesLength; ++i) {
+				nftCollection.setProperty(tokenId, properties[i].key, properties[i].value);
+			}
+			nftCollection.transferFromCross(
+				NftCrossAccountId(address(this), 0),
+				NftCrossAccountId(address(0), _substrateReceiver),
+				tokenId
+			);
+		} else {
+			revert("Wrong collection type. Works only with NFT or RFT");
+		}
+
+		emit MintToSub(address(0), _substrateReceiver, _collection, tokenId);
+	}
+
+	function mintToSubstrateBulkProperty(
+		address _collection,
+		uint256 _substrateReceiver,
+		NftProperty[] calldata _properties
+	) external checkRestrictions(_collection) {
+		uint256 propertiesLength = _properties.length;
+		require(propertiesLength > 0, "Properies is empty");
+
+		Collection commonContract = Collection(_collection);
+		bytes32 collectionType = keccak256(bytes(commonContract.uniqueCollectionType()));
+		uint256 tokenId;
+
+		if (collectionType == REFUNGIBLE_COLLECTION_TYPE) {} else if (collectionType == NONFUNGIBLE_COLLECTION_TYPE) {
+			UniqueNFT nftCollection = UniqueNFT(_collection);
+			tokenId = nftCollection.mint(address(this));
+
+			nftCollection.setProperties(tokenId, _properties);
+
+			nftCollection.transferFromCross(
+				NftCrossAccountId(address(this), 0),
+				NftCrossAccountId(address(0), _substrateReceiver),
+				tokenId
+			);
+		} else {
+			revert("Wrong collection type. Works only with NFT or RFT");
+		}
+
+		emit MintToSub(address(0), _substrateReceiver, _collection, tokenId);
+	}
+}
deletedtests/src/benchmarks/mintFeeBench/feeBench.tsdiffbeforeafterboth
--- a/tests/src/benchmarks/mintFeeBench/feeBench.ts
+++ /dev/null
@@ -1,418 +0,0 @@
-import {EthUniqueHelper, usingEthPlaygrounds} from '../../eth/util';
-import {readFile} from 'fs/promises';
-import {ContractImports} from '../../eth/util/playgrounds/types';
-import {
-  ICrossAccountId,
-  ITokenPropertyPermission,
-} from '../../util/playgrounds/types';
-import {IKeyringPair} from '@polkadot/types/types';
-import {UniqueNFTCollection} from '../../util/playgrounds/unique';
-import {Contract} from 'web3-eth-contract';
-import {createObjectCsvWriter} from 'csv-writer';
-
-const CONTRACT_IMPORT: ContractImports[] = [
-  {
-    fsPath: `${__dirname}/../../eth/api/CollectionHelpers.sol`,
-    solPath: 'eth/api/CollectionHelpers.sol',
-  },
-  {
-    fsPath: `${__dirname}/../../eth/api/ContractHelpers.sol`,
-    solPath: 'eth/api/ContractHelpers.sol',
-  },
-  {
-    fsPath: `${__dirname}/../../eth/api/UniqueRefungibleToken.sol`,
-    solPath: 'eth/api/UniqueRefungibleToken.sol',
-  },
-  {
-    fsPath: `${__dirname}/../../eth/api/UniqueRefungible.sol`,
-    solPath: 'eth/api/UniqueRefungible.sol',
-  },
-  {
-    fsPath: `${__dirname}/../../eth/api/UniqueNFT.sol`,
-    solPath: 'eth/api/UniqueNFT.sol',
-  },
-];
-
-const PROPERTIES = Array(40)
-  .fill(0)
-  .map((_, i) => {
-    return {
-      key: `key_${i}`,
-      value: Uint8Array.from(Buffer.from(`value_${i}`)),
-    };
-  });
-
-const PERMISSIONS: ITokenPropertyPermission[] = PROPERTIES.map((p) => {
-  return {
-    key: p.key,
-    permission: {
-      tokenOwner: true,
-      collectionAdmin: true,
-      mutable: true,
-    },
-  };
-});
-
-interface IBenchmarkResultForProp {
-	propertiesNumber: number;
-	substrateFee: number;
-	ethFee: number;
-	ethBulkFee: number;
-	evmProxyContractFee: number;
-	evmProxyContractBulkFee: number;
-}
-
-const main = async () => {
-  const csvWriter = createObjectCsvWriter({
-    path: 'properties.csv',
-    header: [
-      'propertiesNumber',
-      'substrateFee',
-      'ethFee',
-      'ethBulkFee',
-      'evmProxyContractFee',
-      'evmProxyContractBulkFee',
-    ],
-  });
-
-  await usingEthPlaygrounds(async (helper, privateKey) => {
-    const CONTRACT_SOURCE = (
-      await readFile(`${__dirname}/proxyContract.sol`)
-    ).toString();
-
-    const donor = await privateKey('//Alice'); // Seed from account with balance on this network
-    const myAccount = await privateKey('//Bob'); // replace with account from polkadot extension
-    const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);
-
-    const contract = await helper.ethContract.deployByCode(
-      ethSigner,
-      'ProxyMint',
-      CONTRACT_SOURCE,
-      CONTRACT_IMPORT,
-    );
-
-    const fees = await benchMintFee(helper, privateKey, contract);
-    console.log(fees);
-
-    const result: IBenchmarkResultForProp[] = [];
-
-    for (let i = 1; i <= 20; i++) {
-      result.push(await benchMintWithProperties(helper, privateKey, contract, {
-        propertiesNumber: i,
-      }));
-    }
-
-    await csvWriter.writeRecords(result);
-
-    console.table(result);
-  });
-};
-
-main()
-  .then(() => process.exit(0))
-  .catch((e) => {
-    console.log(e);
-    process.exit(1);
-  });
-
-async function createCollectionForBenchmarks(
-  helper: EthUniqueHelper,
-  privateKey: (seed: string) => Promise<IKeyringPair>,
-  ethSigner: string,
-  proxyContract: string,
-  permissions: ITokenPropertyPermission[],
-) {
-  const donor = await privateKey('//Alice');
-
-  const collection = await helper.nft.mintCollection(donor, {
-    name: 'test mintToSubstrate',
-    description: 'EVMHelpers',
-    tokenPrefix: 'ap',
-    tokenPropertyPermissions: [
-      {
-        key: 'url',
-        permission: {
-          tokenOwner: true,
-          collectionAdmin: true,
-          mutable: true,
-        },
-      },
-    ],
-    limits: {sponsorTransferTimeout: 0, sponsorApproveTimeout: 0},
-    permissions: {mintMode: true},
-  });
-
-  await collection.addToAllowList(donor, {
-    Ethereum: helper.address.substrateToEth(donor.address),
-  });
-  await collection.addToAllowList(donor, {Substrate: donor.address});
-  await collection.addAdmin(donor, {Ethereum: ethSigner});
-  await collection.addAdmin(donor, {
-    Ethereum: helper.address.substrateToEth(donor.address),
-  });
-  await collection.addToAllowList(donor, {Ethereum: proxyContract});
-  await collection.addAdmin(donor, {Ethereum: proxyContract});
-  await collection.setTokenPropertyPermissions(donor, permissions);
-
-  return collection;
-}
-
-async function benchMintFee(
-  helper: EthUniqueHelper,
-  privateKey: (seed: string) => Promise<IKeyringPair>,
-  proxyContract: Contract,
-): Promise<{
-	substrateFee: number;
-	ethFee: number;
-	evmProxyContractFee: number;
-}> {
-  const donor = await privateKey('//Alice');
-  const substrateReceiver = await privateKey('//Bob');
-  const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);
-
-  const nominal = helper.balance.getOneTokenNominal();
-
-  await helper.eth.transferBalanceFromSubstrate(
-    donor,
-    proxyContract.options.address,
-    100n,
-  );
-
-  const collection = await createCollectionForBenchmarks(
-    helper,
-    privateKey,
-    ethSigner,
-    proxyContract.options.address,
-    PERMISSIONS,
-  );
-
-  const substrateFee = await helper.arrange.calculcateFee(
-    {Substrate: donor.address},
-    () => collection.mintToken(donor, {Substrate: substrateReceiver.address}),
-  );
-
-  const collectionEthAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
-  const collectionContract = helper.ethNativeContract.collection(
-    collectionEthAddress,
-    'nft',
-  );
-
-  const receiverEthAddress = helper.address.substrateToEth(substrateReceiver.address);
-
-  const encodedCall = collectionContract.methods
-    .mint(receiverEthAddress)
-    .encodeABI();
-
-  const ethFee = await helper.arrange.calculcateFee(
-    {Substrate: donor.address},
-    async () => {
-      await helper.eth.sendEVM(
-        donor,
-        collectionContract.options.address,
-        encodedCall,
-        '0',
-      );
-    },
-  );
-
-  const evmProxyContractFee = await helper.arrange.calculcateFee(
-    {Ethereum: ethSigner},
-    async () => {
-      await proxyContract.methods
-        .mintToSubstrate(
-          helper.ethAddress.fromCollectionId(collection.collectionId),
-          substrateReceiver.addressRaw,
-        )
-        .send({from: ethSigner});
-    },
-  );
-
-  return {
-    substrateFee: convertToTokens(substrateFee, nominal),
-    ethFee: convertToTokens(ethFee, nominal),
-    evmProxyContractFee: convertToTokens(evmProxyContractFee, nominal),
-  };
-}
-
-async function benchMintWithProperties(
-  helper: EthUniqueHelper,
-  privateKey: (seed: string) => Promise<IKeyringPair>,
-  proxyContract: Contract,
-  setup: { propertiesNumber: number },
-): Promise<IBenchmarkResultForProp> {
-  const donor = await privateKey('//Alice'); // Seed from account with balance on this network
-  const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);
-
-  const susbstrateReceiver = await privateKey('//Bob');
-  const receiverEthAddress = helper.address.substrateToEth(susbstrateReceiver.address);
-
-  const nominal = helper.balance.getOneTokenNominal();
-
-  const substrateFee = await calculateFeeNftMintWithProperties(
-    helper,
-    privateKey,
-    {Substrate: donor.address},
-    ethSigner,
-    proxyContract.options.address,
-    async (collection) => {
-      await collection.mintToken(
-        donor,
-        {Substrate: susbstrateReceiver.address},
-        PROPERTIES.slice(0, setup.propertiesNumber).map((p) => {
-          return {key: p.key, value: Buffer.from(p.value).toString()};
-        }),
-      );
-    },
-  );
-
-  const ethFee = await calculateFeeNftMintWithProperties(
-    helper,
-    privateKey,
-    {Substrate: donor.address},
-    ethSigner,
-    proxyContract.options.address,
-    async (collection) => {
-      const evmContract = helper.ethNativeContract.collection(
-        helper.ethAddress.fromCollectionId(collection.collectionId),
-        'nft',
-      );
-
-      const subTokenId = await evmContract.methods.nextTokenId().call();
-
-      let encodedCall = evmContract.methods
-        .mint(receiverEthAddress)
-        .encodeABI();
-
-      await helper.eth.sendEVM(
-        donor,
-        evmContract.options.address,
-        encodedCall,
-        '0',
-      );
-
-      for (const val of PROPERTIES.slice(0, setup.propertiesNumber)) {
-        encodedCall = await evmContract.methods
-          .setProperty(subTokenId, val.key, Buffer.from(val.value))
-          .encodeABI();
-
-        await helper.eth.sendEVM(
-          donor,
-          evmContract.options.address,
-          encodedCall,
-          '0',
-        );
-      }
-    },
-  );
-
-  const ethBulkFee = await calculateFeeNftMintWithProperties(
-    helper,
-    privateKey,
-    {Substrate: donor.address},
-    ethSigner,
-    proxyContract.options.address,
-    async (collection) => {
-      const evmContract = helper.ethNativeContract.collection(
-        helper.ethAddress.fromCollectionId(collection.collectionId),
-        'nft',
-      );
-
-      const subTokenId = await evmContract.methods.nextTokenId().call();
-
-      let encodedCall = evmContract.methods
-        .mint(receiverEthAddress)
-        .encodeABI();
-
-      await helper.eth.sendEVM(
-        donor,
-        evmContract.options.address,
-        encodedCall,
-        '0',
-      );
-
-      encodedCall = await evmContract.methods
-        .setProperties(
-          subTokenId,
-          PROPERTIES.slice(0, setup.propertiesNumber).map((p) => {
-            return {field_0: p.key, field_1: p.value};
-          }),
-        )
-        .encodeABI();
-
-      await helper.eth.sendEVM(
-        donor,
-        evmContract.options.address,
-        encodedCall,
-        '0',
-      );
-    },
-  );
-
-  const proxyContractFee = await calculateFeeNftMintWithProperties(
-    helper,
-    privateKey,
-    {Ethereum: ethSigner},
-    ethSigner,
-    proxyContract.options.address,
-    async (collection) => {
-      await proxyContract.methods
-        .mintToSubstrateWithProperty(
-          helper.ethAddress.fromCollectionId(collection.collectionId),
-          susbstrateReceiver.addressRaw,
-          PROPERTIES.slice(0, setup.propertiesNumber),
-        )
-        .send({from: ethSigner});
-    },
-  );
-
-  const proxyContractBulkFee = await calculateFeeNftMintWithProperties(
-    helper,
-    privateKey,
-    {Ethereum: ethSigner},
-    ethSigner,
-    proxyContract.options.address,
-    async (collection) => {
-      await proxyContract.methods
-        .mintToSubstrateBulkProperty(
-          helper.ethAddress.fromCollectionId(collection.collectionId),
-          susbstrateReceiver.addressRaw,
-          PROPERTIES.slice(0, setup.propertiesNumber).map((p) => {
-            return {field_0: p.key, field_1: p.value};
-          }),
-        )
-        .send({from: ethSigner, gas: 25_000_000});
-    },
-  );
-
-  return {
-    propertiesNumber: setup.propertiesNumber,
-    substrateFee: convertToTokens(substrateFee, nominal),
-    ethFee: convertToTokens(ethFee, nominal),
-    ethBulkFee: convertToTokens(ethBulkFee, nominal),
-    evmProxyContractFee: convertToTokens(proxyContractFee, nominal),
-    evmProxyContractBulkFee: convertToTokens(proxyContractBulkFee, nominal),
-  };
-}
-
-async function calculateFeeNftMintWithProperties(
-  helper: EthUniqueHelper,
-  privateKey: (seed: string) => Promise<IKeyringPair>,
-  payer: ICrossAccountId,
-  ethSigner: string,
-  proxyContractAddress: string,
-  calculatedCall: (collection: UniqueNFTCollection) => Promise<any>,
-): Promise<bigint> {
-  const collection = await createCollectionForBenchmarks(
-    helper,
-    privateKey,
-    ethSigner,
-    proxyContractAddress,
-    PERMISSIONS,
-  );
-  return helper.arrange.calculcateFee(payer, async () => {
-    await calculatedCall(collection);
-  });
-}
-function convertToTokens(value: bigint, nominal: bigint): number {
-  return Number((value * 1000n) / nominal) / 1000;
-}
deletedtests/src/benchmarks/mintFeeBench/proxyContract.soldiffbeforeafterboth
--- a/tests/src/benchmarks/mintFeeBench/proxyContract.sol
+++ /dev/null
@@ -1,129 +0,0 @@
-// SPDX-License-Identifier:  Apache License
-pragma solidity >=0.8.0;
-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";
-
-struct Property {
-	string key;
-	bytes value;
-}
-
-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");
-		_;
-	}
-
-	/// @dev This emits when a mint to a substrate address has been made.
-	event MintToSub(address _toEth, uint256 _toSub, address _collection, uint256 _tokenId);
-
-	function mintToSubstrate(address _collection, uint256 _substrateReceiver) external checkRestrictions(_collection) {
-		Collection commonContract = Collection(_collection);
-		bytes32 collectionType = keccak256(bytes(commonContract.uniqueCollectionType()));
-		uint256 tokenId;
-
-		if (collectionType == REFUNGIBLE_COLLECTION_TYPE) {
-			UniqueRefungible rftCollection = UniqueRefungible(_collection);
-
-			tokenId = rftCollection.mint(address(this));
-
-			rftCollection.transferFromCross(
-				RftCrossAccountId(address(this), 0),
-				RftCrossAccountId(address(0), _substrateReceiver),
-				tokenId
-			);
-		} else if (collectionType == NONFUNGIBLE_COLLECTION_TYPE) {
-			UniqueNFT nftCollection = UniqueNFT(_collection);
-			tokenId = nftCollection.mint(address(this));
-
-			nftCollection.transferFromCross(
-				NftCrossAccountId(address(this), 0),
-				NftCrossAccountId(address(0), _substrateReceiver),
-				tokenId
-			);
-		} else {
-			revert("Wrong collection type. Works only with NFT or RFT");
-		}
-
-		emit MintToSub(address(0), _substrateReceiver, _collection, tokenId);
-	}
-
-	function mintToSubstrateWithProperty(
-		address _collection,
-		uint256 _substrateReceiver,
-		Property[] calldata properties
-	) external checkRestrictions(_collection) {
-		uint256 propertiesLength = properties.length;
-		require(propertiesLength > 0, "Properies is empty");
-
-		Collection commonContract = Collection(_collection);
-		bytes32 collectionType = keccak256(bytes(commonContract.uniqueCollectionType()));
-		uint256 tokenId;
-
-		if (collectionType == REFUNGIBLE_COLLECTION_TYPE) {
-			UniqueRefungible rftCollection = UniqueRefungible(_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.transferFromCross(
-				RftCrossAccountId(address(this), 0),
-				RftCrossAccountId(address(0), _substrateReceiver),
-				tokenId
-			);
-		} else if (collectionType == NONFUNGIBLE_COLLECTION_TYPE) {
-			UniqueNFT nftCollection = UniqueNFT(_collection);
-			tokenId = nftCollection.mint(address(this));
-			for (uint256 i = 0; i < propertiesLength; ++i) {
-				nftCollection.setProperty(tokenId, properties[i].key, properties[i].value);
-			}
-			nftCollection.transferFromCross(
-				NftCrossAccountId(address(this), 0),
-				NftCrossAccountId(address(0), _substrateReceiver),
-				tokenId
-			);
-		} else {
-			revert("Wrong collection type. Works only with NFT or RFT");
-		}
-
-		emit MintToSub(address(0), _substrateReceiver, _collection, tokenId);
-	}
-
-	function mintToSubstrateBulkProperty(
-		address _collection,
-		uint256 _substrateReceiver,
-		NftProperty[] calldata _properties
-	) external checkRestrictions(_collection) {
-		uint256 propertiesLength = _properties.length;
-		require(propertiesLength > 0, "Properies is empty");
-
-		Collection commonContract = Collection(_collection);
-		bytes32 collectionType = keccak256(bytes(commonContract.uniqueCollectionType()));
-		uint256 tokenId;
-
-		if (collectionType == REFUNGIBLE_COLLECTION_TYPE) {} else if (collectionType == NONFUNGIBLE_COLLECTION_TYPE) {
-			UniqueNFT nftCollection = UniqueNFT(_collection);
-			tokenId = nftCollection.mint(address(this));
-
-			nftCollection.setProperties(tokenId, _properties);
-
-			nftCollection.transferFromCross(
-				NftCrossAccountId(address(this), 0),
-				NftCrossAccountId(address(0), _substrateReceiver),
-				tokenId
-			);
-		} else {
-			revert("Wrong collection type. Works only with NFT or RFT");
-		}
-
-		emit MintToSub(address(0), _substrateReceiver, _collection, tokenId);
-	}
-}