difftreelog
Merge pull request #714 from UniqueNetwork/research/tokenMintFee
in: master
Research/token mint fee
11 files changed
pallets/evm-contract-helpers/src/stubs/ContractHelpers.rawdiffbeforeafterbothbinary blob — no preview
pallets/fungible/src/stubs/UniqueFungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterbothbinary blob — no preview
pallets/refungible/src/stubs/UniqueRefungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/refungible/src/stubs/UniqueRefungibleToken.rawdiffbeforeafterbothbinary blob — no preview
pallets/unique/src/eth/stubs/CollectionHelpers.rawdiffbeforeafterbothbinary blob — no preview
tests/.gitignorediffbeforeafterboth--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -1 +1,2 @@
/node_modules/
+properties.csv
tests/package.jsondiffbeforeafterboth1{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 "find-process": "^1.4.7",120 "solc": "0.8.17",121 "web3": "^1.8.0"122 }123}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 "benchMintingFee": "ts-node src/benchmarks/mintFee/benchmark.ts",105 "load": "mocha --timeout 9999999 -r ts-node/register './**/*.load.ts'",106 "loadTransfer": "ts-node src/transfer.nload.ts",107 "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",108 "polkadot-types-from-defs": "ts-node ./node_modules/.bin/polkadot-types-from-defs --endpoint src/interfaces/metadata.json --input src/interfaces/ --package .",109 "polkadot-types-from-chain": "ts-node ./node_modules/.bin/polkadot-types-from-chain --endpoint src/interfaces/metadata.json --output src/interfaces/ --package .",110 "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"111 },112 "author": "",113 "license": "SEE LICENSE IN ../LICENSE",114 "homepage": "",115 "dependencies": {116 "@polkadot/api": "9.5.2",117 "@polkadot/util-crypto": "10.1.11",118 "chai-as-promised": "^7.1.1",119 "chai-like": "^1.1.1",120 "csv-writer": "^1.6.0",121 "find-process": "^1.4.7",122 "solc": "0.8.17",123 "web3": "^1.8.0"124 }125}tests/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;
+}
tests/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);
+ }
+}
tests/yarn.lockdiffbeforeafterboth--- a/tests/yarn.lock
+++ b/tests/yarn.lock
@@ -1852,6 +1852,11 @@
randombytes "^2.0.0"
randomfill "^1.0.3"
+csv-writer@^1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/csv-writer/-/csv-writer-1.6.0.tgz#d0cea44b6b4d7d3baa2ecc6f3f7209233514bcf9"
+ integrity sha512-NOx7YDFWEsM/fTRAJjRpPp8t+MKRVvniAg9wQlUKx20MFrPs73WLJhFf5iteqrxNYnsy924K3Iroh3yNHeYd2g==
+
d@1, d@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a"