1import {EthUniqueHelper, SponsoringMode, usingEthPlaygrounds} from '../../eth/util';2import {readFile} from 'fs/promises';3import {CollectionLimitField, ContractImports, TokenPermissionField} 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 ethMintCrossFee: number;62 evmProxyContractFee: number;63 evmProxyContractBulkFee: number;64}65interface IBenchmarkCollection {66 createFee: number,67 mintFee: number,68 transferFee: number,69}70const main = async () => {71 const benchmarks = [72 'substrateFee',73 'ethFee',74 'ethBulkFee',75 'ethMintCrossFee',76 'evmProxyContractFee',77 'evmProxyContractBulkFee',78 ];79 const headers = [80 'propertiesNumber',81 ...benchmarks,82 ];838485 const csvWriter = createObjectCsvWriter({86 path: 'properties.csv',87 header: headers,88 });8990 await usingEthPlaygrounds(async (helper, privateKey) => {91 const NOMINAL = helper.balance.getOneTokenNominal();92 const CONTRACT_SOURCE = (93 await readFile(`${__dirname}/proxyContract.sol`)94 ).toString();95 const ZEPPELIN_OBJECT = '0x' + (await readFile(`${__dirname}/openZeppelin/bin/ZeppelinContract.bin`)).toString();96 const ZEPPELIN_ABI = JSON.parse((await readFile(`${__dirname}/openZeppelin/bin/ZeppelinContract.abi`)).toString());9798 console.log('\n ERC721 ops fees');99 console.table(await ERC721CalculateFeeGas(helper, privateKey), ['fee', 'gas', 'substrate']);100101 const donor = await privateKey('//Alice'); 102 const [substrateReceiver] = await helper.arrange.createAccounts([10n], donor);103104 const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);105 const ethReceiver = await helper.eth.createAccountWithBalance(donor, 5n);106107 let susbtrateCollection: UniqueNFTCollection | null;108 const createCollectionSubstrateFee = convertToTokens(109 await helper.arrange.calculcateFee({Substrate: donor.address}, async () => {110 susbtrateCollection = await helper.nft.mintCollection(donor, {tokenPropertyPermissions: [111 {112 key: 'url',113 permission: {114 tokenOwner: true,115 collectionAdmin: true,116 mutable: true,117 },118 },119 ]});120 }),121 NOMINAL,122 );123124 const susbstrateMintFee = convertToTokens(125 await helper.arrange.calculcateFee(126 {Substrate: donor.address},127 () => susbtrateCollection!.mintToken(donor, {Substrate: substrateReceiver.address}, [{key: 'url', value: 'test'}]),128 ),129 NOMINAL,130 );131 const susbstrateTransferFee = convertToTokens(132 await helper.arrange.calculcateFee(133 {Substrate: substrateReceiver.address},134 () => susbtrateCollection!.transferToken(substrateReceiver, 1, {Substrate: donor.address}),135 ),136 NOMINAL,137 );138 const substrateFee: IBenchmarkCollection = {139 createFee: createCollectionSubstrateFee,140 mintFee: susbstrateMintFee,141 transferFee: susbstrateTransferFee,142 };143144 const helperContract = await helper.ethNativeContract.collectionHelpers(ethSigner);145146 let ethContract: Contract | null = null;147148 const createCollectionEthFee = convertToTokens(149 await helper.arrange.calculcateFee({Ethereum: ethSigner}, async () => {150 const result = await helperContract.methods.createNFTCollection('a', 'b', 'c').send({from: ethSigner, value: Number(2n * helper.balance.getOneTokenNominal())});151 ethContract = await helper.ethNativeContract.collection(helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId), 'nft', ethSigner);152 }),153 NOMINAL,154 );155156 await ethContract!.methods.setTokenPropertyPermissions([157 ['url', [158 [TokenPermissionField.Mutable, true],159 [TokenPermissionField.TokenOwner, true],160 [TokenPermissionField.CollectionAdmin, true]],161 ],162 ]).send({from: ethSigner});163164 const ethMintFee = convertToTokens(await helper.arrange.calculcateFee(165 {Ethereum: ethSigner},166 () => ethContract!.methods.mintCross(167 helper.ethCrossAccount.fromAddress(ethReceiver),168 [{key: 'url', value: Buffer.from('test')}],169 )170 .send({from: ethSigner}),171 ), NOMINAL);172173 const ethTransferFee = convertToTokens(await helper.arrange.calculcateFee(174 {Ethereum: ethReceiver},175 () => ethContract!.methods.transferFrom(ethReceiver, ethSigner, 1)176 .send({from: ethReceiver}),177 ), NOMINAL);178179 const ethFee: IBenchmarkCollection = {180 createFee: createCollectionEthFee,181 mintFee: ethMintFee,182 transferFee: ethTransferFee,183 };184185 let zeppelelinContract: Contract | null = null;186187 const zeppelinDeployFee = convertToTokens(188 await helper.arrange.calculcateFee({Ethereum: ethSigner}, async () => {189 zeppelelinContract = await helper.ethContract.deployByAbi(190 ethSigner,191 ZEPPELIN_ABI,192 ZEPPELIN_OBJECT,193 );194 }),195 NOMINAL,196 );197198 const zeppelinMintFee = convertToTokens(await helper.arrange.calculcateFee(199 {Ethereum: ethSigner},200 () => zeppelelinContract!.methods.safeMint(ethReceiver, 'test').send({from: ethSigner}),201 ), NOMINAL);202203204 const zeppelinTransferFee = convertToTokens(await helper.arrange.calculcateFee(205 {Ethereum: ethReceiver},206 () => zeppelelinContract!.methods.safeTransferFrom(ethReceiver, ethSigner, 0).send({from: ethReceiver}),207 ), NOMINAL);208209 const zeppelinFee: IBenchmarkCollection = {210 createFee: zeppelinDeployFee,211 mintFee: zeppelinMintFee,212 transferFee: zeppelinTransferFee,213 };214215 console.log('collection ops fees');216 const results = {substrate: substrateFee, eth: ethFee, zeppelin: zeppelinFee};217 console.table(results);218219 const contract = await helper.ethContract.deployByCode(220 ethSigner,221 'ProxyMint',222 CONTRACT_SOURCE,223 CONTRACT_IMPORT,224 );225226 const fees = await benchMintFee(helper, privateKey, contract);227 console.log('Minting without properties');228 console.table(fees);229230 const result: IBenchmarkResultForProp[] = [];231 const csvResult: IBenchmarkResultForProp[] = [];232233 for (let i = 1; i <= 20; i++) {234 const benchResult = await benchMintWithProperties(helper, privateKey, contract, {235 propertiesNumber: i,236 }) as any;237238 csvResult.push(benchResult);239240 const minFee = Math.min(...(benchmarks.map(x => benchResult[x])));241 for(const key of benchmarks) {242 const keyPercent = Math.round((benchResult[key] / minFee) * 100);243 benchResult[key] = `${benchResult[key]} (${keyPercent}%)`;244 }245246 result.push(benchResult);247 }248249 await csvWriter.writeRecords(csvResult);250251 console.log('Minting with properties');252 console.table(result, headers);253 });254};255256main()257 .then(() => process.exit(0))258 .catch((e) => {259 console.log(e);260 process.exit(1);261 });262263async function createCollectionForBenchmarks(264 helper: EthUniqueHelper,265 privateKey: (seed: string) => Promise<IKeyringPair>,266 ethSigner: string,267 proxyContract: string | null,268 permissions: ITokenPropertyPermission[],269) {270 const donor = await privateKey('//Alice');271272 const collection = await helper.nft.mintCollection(donor, {273 name: 'test mintToSubstrate',274 description: 'EVMHelpers',275 tokenPrefix: 'ap',276 tokenPropertyPermissions: [277 {278 key: 'url',279 permission: {280 tokenOwner: true,281 collectionAdmin: true,282 mutable: true,283 },284 },285 {286 key: 'URI',287 permission: {288 tokenOwner: true,289 collectionAdmin: true,290 mutable: true,291 },292 },293 ],294 limits: {sponsorTransferTimeout: 0, sponsorApproveTimeout: 0},295 permissions: {mintMode: true},296 });297298 await collection.addToAllowList(donor, {299 Ethereum: helper.address.substrateToEth(donor.address),300 });301 await collection.addToAllowList(donor, {Substrate: donor.address});302 await collection.addAdmin(donor, {Ethereum: ethSigner});303 await collection.addAdmin(donor, {304 Ethereum: helper.address.substrateToEth(donor.address),305 });306307 if (proxyContract) {308 await collection.addToAllowList(donor, {Ethereum: proxyContract});309 await collection.addAdmin(donor, {Ethereum: proxyContract});310 }311312 await collection.setTokenPropertyPermissions(donor, permissions);313314 return collection;315}316317async function benchMintFee(318 helper: EthUniqueHelper,319 privateKey: (seed: string) => Promise<IKeyringPair>,320 proxyContract: Contract,321): Promise<{322 substrateFee: number;323 ethFee: number;324 evmProxyContractFee: number;325}> {326 const donor = await privateKey('//Alice');327 const substrateReceiver = await privateKey('//Bob');328 const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);329330 const nominal = helper.balance.getOneTokenNominal();331332 await helper.eth.transferBalanceFromSubstrate(333 donor,334 proxyContract.options.address,335 100n,336 );337338 const collection = await createCollectionForBenchmarks(339 helper,340 privateKey,341 ethSigner,342 proxyContract.options.address,343 PERMISSIONS,344 );345346 const substrateFee = await helper.arrange.calculcateFee(347 {Substrate: donor.address},348 () => collection.mintToken(donor, {Substrate: substrateReceiver.address}),349 );350351 const collectionEthAddress = helper.ethAddress.fromCollectionId(collection.collectionId);352 const collectionContract = await helper.ethNativeContract.collection(353 collectionEthAddress,354 'nft',355 );356357 const receiverEthAddress = helper.address.substrateToEth(substrateReceiver.address);358359 const encodedCall = collectionContract.methods360 .mint(receiverEthAddress)361 .encodeABI();362363 const ethFee = await helper.arrange.calculcateFee(364 {Substrate: donor.address},365 async () => {366 await helper.eth.sendEVM(367 donor,368 collectionContract.options.address,369 encodedCall,370 '0',371 );372 },373 );374375 const evmProxyContractFee = await helper.arrange.calculcateFee(376 {Ethereum: ethSigner},377 async () => {378 await proxyContract.methods379 .mintToSubstrate(380 helper.ethAddress.fromCollectionId(collection.collectionId),381 substrateReceiver.addressRaw,382 )383 .send({from: ethSigner});384 },385 );386387 return {388 substrateFee: convertToTokens(substrateFee, nominal),389 ethFee: convertToTokens(ethFee, nominal),390 evmProxyContractFee: convertToTokens(evmProxyContractFee, nominal),391 };392}393394async function benchMintWithProperties(395 helper: EthUniqueHelper,396 privateKey: (seed: string) => Promise<IKeyringPair>,397 proxyContract: Contract,398 setup: { propertiesNumber: number },399): Promise<IBenchmarkResultForProp> {400 const donor = await privateKey('//Alice'); 401 const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);402403 const susbstrateReceiver = await privateKey('//Bob');404 const receiverEthAddress = helper.address.substrateToEth(susbstrateReceiver.address);405406 const nominal = helper.balance.getOneTokenNominal();407408 const substrateFee = await calculateFeeNftMintWithProperties(409 helper,410 privateKey,411 {Substrate: donor.address},412 ethSigner,413 proxyContract.options.address,414 async (collection) => {415 await collection.mintToken(416 donor,417 {Substrate: susbstrateReceiver.address},418 PROPERTIES.slice(0, setup.propertiesNumber).map((p) => {419 return {key: p.key, value: Buffer.from(p.value).toString()};420 }),421 );422 },423 );424425 const ethFee = await calculateFeeNftMintWithProperties(426 helper,427 privateKey,428 {Substrate: donor.address},429 ethSigner,430 proxyContract.options.address,431 async (collection) => {432 const evmContract = await helper.ethNativeContract.collection(433 helper.ethAddress.fromCollectionId(collection.collectionId),434 'nft',435 undefined,436 true,437 );438439 const subTokenId = await evmContract.methods.nextTokenId().call();440441 let encodedCall = evmContract.methods442 .mint(receiverEthAddress)443 .encodeABI();444445 await helper.eth.sendEVM(446 donor,447 evmContract.options.address,448 encodedCall,449 '0',450 );451452 for (const val of PROPERTIES.slice(0, setup.propertiesNumber)) {453 encodedCall = await evmContract.methods454 .setProperty(subTokenId, val.key, Buffer.from(val.value))455 .encodeABI();456457 await helper.eth.sendEVM(458 donor,459 evmContract.options.address,460 encodedCall,461 '0',462 );463 }464 },465 );466467 const ethBulkFee = await calculateFeeNftMintWithProperties(468 helper,469 privateKey,470 {Substrate: donor.address},471 ethSigner,472 proxyContract.options.address,473 async (collection) => {474 const evmContract = await helper.ethNativeContract.collection(475 helper.ethAddress.fromCollectionId(collection.collectionId),476 'nft',477 );478479 const subTokenId = await evmContract.methods.nextTokenId().call();480481 let encodedCall = evmContract.methods482 .mint(receiverEthAddress)483 .encodeABI();484485 await helper.eth.sendEVM(486 donor,487 evmContract.options.address,488 encodedCall,489 '0',490 );491492 encodedCall = await evmContract.methods493 .setProperties(494 subTokenId,495 PROPERTIES.slice(0, setup.propertiesNumber),496 )497 .encodeABI();498499 await helper.eth.sendEVM(500 donor,501 evmContract.options.address,502 encodedCall,503 '0',504 );505 },506 );507508 const ethMintCrossFee = await calculateFeeNftMintWithProperties(509 helper,510 privateKey,511 {Ethereum: ethSigner},512 ethSigner,513 proxyContract.options.address,514 async (collection) => {515 const evmContract = await helper.ethNativeContract.collection(516 helper.ethAddress.fromCollectionId(collection.collectionId),517 'nft',518 );519520 await evmContract.methods.mintCross(521 helper.ethCrossAccount.fromAddress(receiverEthAddress),522 PROPERTIES.slice(0, setup.propertiesNumber),523 )524 .send({from: ethSigner});525 },526 );527528 const proxyContractFee = await calculateFeeNftMintWithProperties(529 helper,530 privateKey,531 {Ethereum: ethSigner},532 ethSigner,533 proxyContract.options.address,534 async (collection) => {535 await proxyContract.methods536 .mintToSubstrateWithProperty(537 helper.ethAddress.fromCollectionId(collection.collectionId),538 susbstrateReceiver.addressRaw,539 PROPERTIES.slice(0, setup.propertiesNumber),540 )541 .send({from: ethSigner});542 },543 );544545 const proxyContractBulkFee = await calculateFeeNftMintWithProperties(546 helper,547 privateKey,548 {Ethereum: ethSigner},549 ethSigner,550 proxyContract.options.address,551 async (collection) => {552 await proxyContract.methods553 .mintToSubstrateBulkProperty(554 helper.ethAddress.fromCollectionId(collection.collectionId),555 susbstrateReceiver.addressRaw,556 PROPERTIES.slice(0, setup.propertiesNumber),557 )558 .send({from: ethSigner, gas: 25_000_000});559 },560 );561562 return {563 propertiesNumber: setup.propertiesNumber,564 substrateFee: convertToTokens(substrateFee, nominal),565 ethFee: convertToTokens(ethFee, nominal),566 ethBulkFee: convertToTokens(ethBulkFee, nominal),567 ethMintCrossFee: convertToTokens(ethMintCrossFee, nominal),568 evmProxyContractFee: convertToTokens(proxyContractFee, nominal),569 evmProxyContractBulkFee: convertToTokens(proxyContractBulkFee, nominal),570 };571}572573async function calculateFeeNftMintWithProperties(574 helper: EthUniqueHelper,575 privateKey: (seed: string) => Promise<IKeyringPair>,576 payer: ICrossAccountId,577 ethSigner: string,578 proxyContractAddress: string,579 calculatedCall: (collection: UniqueNFTCollection) => Promise<any>,580): Promise<bigint> {581 const collection = await createCollectionForBenchmarks(582 helper,583 privateKey,584 ethSigner,585 proxyContractAddress,586 PERMISSIONS,587 );588 return helper.arrange.calculcateFee(payer, async () => {589 await calculatedCall(collection);590 });591}592function convertToTokens(value: bigint, nominal = 1000_000_000_000_000_000n): number {593 return Number((value * 1000n) / nominal) / 1000;594}595596interface IFeeGas {597 fee: number | bigint,598 gas: number | bigint,599 substrate?: number,600}601interface IFunctionFee {602 [name: string]: IFeeGas603}604605async function ERC721CalculateFeeGas(606 helper: EthUniqueHelper,607 privateKey: (seed: string) => Promise<IKeyringPair>,608609): Promise<IFunctionFee> {610 const res: IFunctionFee = {};611 const donor = await privateKey('//Alice');612 const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);613 const ethReceiver = await helper.eth.createAccountWithBalance(donor, 10n);614 const crossSigner = helper.ethCrossAccount.fromAddress(ethSigner);615 const crossReceiver = helper.ethCrossAccount.fromAddress(ethReceiver);616 const collection = await createCollectionForBenchmarks(617 helper,618 privateKey,619 ethSigner,620 null,621 PERMISSIONS,622 );623624 const evmContract = await helper.ethNativeContract.collection(625 helper.ethAddress.fromCollectionId(collection.collectionId),626 'nft',627 ethSigner,628 true,629 );630631 res['mint'] =632 await helper.arrange.calculcateFeeGas(633 {Ethereum: ethSigner},634 () => evmContract.methods.mint(ethSigner).send(),635 );636637 res['mint'].substrate = convertToTokens((await helper.arrange.calculcateFee(638 {Substrate: donor.address},639 () => collection.mintToken(640 donor,641 {Ethereum: ethSigner},642 ),643 )));644645 res['mintCross'] =646 await helper.arrange.calculcateFeeGas(647 {Ethereum: ethSigner},648 () => evmContract.methods.mintCross(crossSigner, []).send(),649 );650651 res['mintCross'].substrate = convertToTokens((await helper.arrange.calculcateFee(652 {Substrate: donor.address},653 () => collection.mintMultipleTokens(donor, [{654 owner: {Ethereum: ethSigner},655 }]),656 )));657658 res['mintWithTokenURI'] =659 await helper.arrange.calculcateFeeGas(660 {Ethereum: ethSigner},661 () => evmContract.methods.mintWithTokenURI(ethSigner, 'Test URI').send(),662 );663664 res['setProperties'] =665 await helper.arrange.calculcateFeeGas(666 {Ethereum: ethSigner},667 () => evmContract.methods.setProperties(1, PROPERTIES.slice(0,1)).send(),668 );669670 res['deleteProperties'] =671 await helper.arrange.calculcateFeeGas(672 {Ethereum: ethSigner},673 () => evmContract.methods.deleteProperties(1, [PROPERTIES[0].key]).send(),674 );675676 res['transfer'] =677 await helper.arrange.calculcateFeeGas(678 {Ethereum: ethSigner},679 () => evmContract.methods.transfer(ethReceiver, 1).send(),680 );681682 res['transferCross'] =683 await helper.arrange.calculcateFeeGas(684 {Ethereum: ethReceiver},685 () => evmContract.methods.transferCross(crossSigner, 1).send({from: ethReceiver}),686 );687688 res['transferFrom'] =689 await helper.arrange.calculcateFeeGas(690 {Ethereum: ethSigner},691 () => evmContract.methods.transferFrom(ethSigner, ethReceiver, 1).send(),692 );693694 res['transferFromCross'] =695 await helper.arrange.calculcateFeeGas(696 {Ethereum: ethReceiver},697 () => evmContract.methods.transferFromCross(crossReceiver, crossSigner, 1).send({from:ethReceiver}),698 );699700 res['burn'] =701 await helper.arrange.calculcateFeeGas(702 {Ethereum: ethSigner},703 () => evmContract.methods.burn(1).send(),704 );705706 res['approveCross'] =707 await helper.arrange.calculcateFeeGas(708 {Ethereum: ethSigner},709 () => evmContract.methods.approveCross(crossReceiver, 2).send(),710 );711712 res['burnFromCross'] =713 await helper.arrange.calculcateFeeGas(714 {Ethereum: ethReceiver},715 () => evmContract.methods.burnFromCross(crossSigner, 2).send({from:ethReceiver}),716 );717718 res['setTokenPropertyPermissions'] =719 await helper.arrange.calculcateFeeGas(720 {Ethereum: ethSigner},721 () => evmContract.methods.setTokenPropertyPermissions([722 ['url', [723 [TokenPermissionField.Mutable, true],724 [TokenPermissionField.TokenOwner, true],725 [TokenPermissionField.CollectionAdmin, true]],726 ],727 ]).send(),728 );729730 res['setCollectionSponsorCross'] =731 await helper.arrange.calculcateFeeGas(732 {Ethereum: ethSigner},733 () => evmContract.methods.setCollectionSponsorCross(crossReceiver).send(),734 );735736 res['confirmCollectionSponsorship'] =737 await helper.arrange.calculcateFeeGas(738 {Ethereum: ethReceiver},739 () => evmContract.methods.confirmCollectionSponsorship().send({from: ethReceiver}),740 );741742 res['removeCollectionSponsor'] =743 await helper.arrange.calculcateFeeGas(744 {Ethereum: ethSigner},745 () => evmContract.methods.removeCollectionSponsor().send(),746 );747748 res['setCollectionProperties'] =749 await helper.arrange.calculcateFeeGas(750 {Ethereum: ethSigner},751 () => evmContract.methods.setCollectionProperties(PROPERTIES.slice(0, 1)).send(),752 );753754 res['deleteCollectionProperties'] =755 await helper.arrange.calculcateFeeGas(756 {Ethereum: ethSigner},757 () => evmContract.methods.deleteCollectionProperties(PROPERTIES.slice(0,1).map(p => p.key)).send(),758 );759 res['setCollectionProperties'].substrate = convertToTokens((await helper.arrange.calculcateFee(760 {Substrate: donor.address},761 () => collection.setProperties(donor, PROPERTIES.slice(0, 1)762 .map(p => { return {key: p.key, value: p.value.toString()}; })),763 )));764765 res['deleteCollectionProperties'].substrate = convertToTokens((await helper.arrange.calculcateFee(766 {Substrate: donor.address},767 () => collection.deleteProperties(donor, PROPERTIES.slice(0, 1)768 .map(p => p.key)),769 )));770771 res['setCollectionLimit'] =772 await helper.arrange.calculcateFeeGas(773 {Ethereum: ethSigner},774 () => evmContract.methods.setCollectionLimit({field: CollectionLimitField.AccountTokenOwnership, value: {status: true, value: 1000}}).send(),775 );776777 const {collectionAddress} = await helper.eth.createCollection('nft', ethSigner, 'A', 'B', 'C');778 const collectionWithEthOwner = await helper.ethNativeContract.collection(collectionAddress, 'nft', ethSigner, true);779780781 res['addCollectionAdminCross'] =782 await helper.arrange.calculcateFeeGas(783 {Ethereum: ethSigner},784 () => collectionWithEthOwner.methods.addCollectionAdminCross(crossReceiver).send(),785 );786787 res['removeCollectionAdminCross'] =788 await helper.arrange.calculcateFeeGas(789 {Ethereum: ethSigner},790 () => collectionWithEthOwner.methods.removeCollectionAdminCross(crossReceiver).send(),791 );792793 res['setCollectionNesting'] =794 await helper.arrange.calculcateFeeGas(795 {Ethereum: ethSigner},796 () => evmContract.methods.setCollectionNesting(true).send(),797 );798799 res['setCollectionNesting[]'] =800 await helper.arrange.calculcateFeeGas(801 {Ethereum: ethSigner},802 () => evmContract.methods.setCollectionNesting(true, [collectionAddress]).send(),803 );804805 res['setCollectionAcces'] =806 await helper.arrange.calculcateFeeGas(807 {Ethereum: ethSigner},808 () => evmContract.methods.setCollectionAccess(SponsoringMode.Allowlisted).send(),809 );810811 res['addToCollectionAllowListCross'] =812 await helper.arrange.calculcateFeeGas(813 {Ethereum: ethSigner},814 () => evmContract.methods.addToCollectionAllowListCross(crossReceiver).send(),815 );816817 res['removeFromCollectionAllowListCross'] =818 await helper.arrange.calculcateFeeGas(819 {Ethereum: ethSigner},820 () => evmContract.methods.removeFromCollectionAllowListCross(crossReceiver).send(),821 );822823 res['setCollectionMintMode'] =824 await helper.arrange.calculcateFeeGas(825 {Ethereum: ethSigner},826 () => evmContract.methods.setCollectionMintMode(true).send(),827 );828829 res['changeCollectionOwnerCross'] =830 await helper.arrange.calculcateFeeGas(831 {Ethereum: ethSigner},832 () => collectionWithEthOwner.methods.changeCollectionOwnerCross(crossReceiver).send(),833 );834835 return res;836}