git.delta.rocks / unique-network / refs/commits / 2e1cabd3ad66

difftreelog

feat configure min gas price

Yaroslav Bolyukin2021-11-05parent: #540e85d.patch.diff
in: master

9 files changed

modifiedruntime/src/lib.rsdiffbeforeafterboth
--- a/runtime/src/lib.rs
+++ b/runtime/src/lib.rs
@@ -243,7 +243,8 @@
 pub struct FixedFee;
 impl FeeCalculator for FixedFee {
 	fn min_gas_price() -> U256 {
-		1.into()
+		// Targeting 0.15 UNQ per transfer
+		(1 * MICROUNIQUE).into()
 	}
 }
 
modifiedtests/src/creditFeesToTreasury.test.tsdiffbeforeafterboth
--- a/tests/src/creditFeesToTreasury.test.ts
+++ b/tests/src/creditFeesToTreasury.test.ts
@@ -14,6 +14,7 @@
   createItemExpectSuccess,
   getGenericResult,
   transferExpectSuccess,
+  UNIQUE,
 } from './util/helpers';
 
 import {default as waitNewBlocks} from './substrate/wait-new-blocks';
@@ -169,12 +170,11 @@
       const aliceBalanceBefore: bigint = (await api.query.system.account(alicesPublicKey)).data.free.toBigInt();
       await transferExpectSuccess(collectionId, tokenId, alice, bob, 1, 'NFT');
       const aliceBalanceAfter: bigint = (await api.query.system.account(alicesPublicKey)).data.free.toBigInt();
-      const fee = aliceBalanceBefore - aliceBalanceAfter;
+      const fee = Number(aliceBalanceBefore - aliceBalanceAfter) / Number(UNIQUE);
 
-      // console.log(fee.toString());
       const expectedTransferFee = 0.1;
       const tolerance = 0.001;
-      expect(Number(fee) / 1e15 - expectedTransferFee).to.be.lessThan(tolerance);
+      expect(Number(fee) / Number(UNIQUE) - expectedTransferFee).to.be.lessThan(tolerance);
     });
   });
 
modifiedtests/src/eth/base.test.tsdiffbeforeafterboth
--- a/tests/src/eth/base.test.ts
+++ b/tests/src/eth/base.test.ts
@@ -1,7 +1,9 @@
 
-import {createEthAccount, createEthAccountWithBalance, deployFlipper, ethBalanceViaSub, GAS_ARGS, itWeb3, recordEthFee} from './util/helpers';
+import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, deployFlipper, ethBalanceViaSub, GAS_ARGS, itWeb3, recordEthFee} from './util/helpers';
 import {expect} from 'chai';
-import {UNIQUE} from '../util/helpers';
+import {createCollectionExpectSuccess, createItemExpectSuccess, UNIQUE} from '../util/helpers';
+import nonFungibleAbi from './nonFungibleAbi.json';
+import privateKey from '../substrate/privateKey';
 
 describe('Contract calls', () => {
   itWeb3('Call of simple contract fee is less than 0.2 UNQ', async ({web3, api}) => {
@@ -19,4 +21,26 @@
     const cost = await recordEthFee(api, userA, () => web3.eth.sendTransaction({from: userA, to: userB, value: '1000000', ...GAS_ARGS}));
     expect(cost - await ethBalanceViaSub(api, userB) < BigInt(0.2 * Number(UNIQUE))).to.be.true;
   });
+
+  itWeb3('NFT transfer is close to 0.15 UNQ', async ({web3, api}) => {
+    const caller = await createEthAccountWithBalance(api, web3);
+    const receiver = createEthAccount(web3);
+
+    const alice = privateKey('//Alice');
+    const collection = await createCollectionExpectSuccess({
+      mode: {type: 'NFT'},
+    });
+    const itemId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});
+
+    const address = collectionIdToAddress(collection);
+    const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
+
+    const cost = await recordEthFee(api, caller, () => contract.methods.transfer(receiver, itemId).send(caller));
+
+    const fee = Number(cost) / Number(UNIQUE);
+    const expectedFee = 0.15;
+    const tolerance = 0.002;
+
+    expect(Math.abs(fee - expectedFee) < tolerance).to.be.true;
+  });
 });
modifiedtests/src/eth/fungible.test.tsdiffbeforeafterboth
--- a/tests/src/eth/fungible.test.ts
+++ b/tests/src/eth/fungible.test.ts
@@ -95,12 +95,12 @@
     const alice = privateKey('//Alice');
 
     const owner = createEthAccount(web3);
-    await transferBalanceToEth(api, alice, owner, 999999999999999);
+    await transferBalanceToEth(api, alice, owner);
 
     await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});
 
     const spender = createEthAccount(web3);
-    await transferBalanceToEth(api, alice, spender, 999999999999999);
+    await transferBalanceToEth(api, alice, spender);
 
     const receiver = createEthAccount(web3);
 
@@ -153,12 +153,12 @@
     const alice = privateKey('//Alice');
 
     const owner = createEthAccount(web3);
-    await transferBalanceToEth(api, alice, owner, 999999999999999);
+    await transferBalanceToEth(api, alice, owner);
 
     await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});
 
     const receiver = createEthAccount(web3);
-    await transferBalanceToEth(api, alice, receiver, 999999999999999);
+    await transferBalanceToEth(api, alice, receiver);
 
     const address = collectionIdToAddress(collection);
     const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS});
modifiedtests/src/eth/marketplace/marketplace.test.tsdiffbeforeafterboth
--- a/tests/src/eth/marketplace/marketplace.test.ts
+++ b/tests/src/eth/marketplace/marketplace.test.ts
@@ -38,8 +38,8 @@
 
     // Ask
     {
-      await executeEthTxOnSub(api, seller, evmCollection, m => m.approve(matcher.options.address, tokenId));
-      await executeEthTxOnSub(api, seller, matcher, m => m.setAsk(PRICE, '0x0000000000000000000000000000000000000000', evmCollection.options.address, tokenId, 1));
+      await executeEthTxOnSub(web3, api, seller, evmCollection, m => m.approve(matcher.options.address, tokenId));
+      await executeEthTxOnSub(web3, api, seller, matcher, m => m.setAsk(PRICE, '0x0000000000000000000000000000000000000000', evmCollection.options.address, tokenId, 1));
     }
 
     // Token is transferred to matcher
@@ -49,7 +49,7 @@
     {
       const sellerBalanceBeforePurchase = await getBalanceSingle(api, seller.address);
       // There is two functions named 'buy', so we should provide full signature
-      await executeEthTxOnSub(api, alice, matcher, m => m['buy(address,uint256)'](evmCollection.options.address, tokenId), {value: PRICE});
+      await executeEthTxOnSub(web3, api, alice, matcher, m => m['buy(address,uint256)'](evmCollection.options.address, tokenId), {value: PRICE});
       expect(await getBalanceSingle(api, seller.address) - sellerBalanceBeforePurchase === PRICE);
     }
 
@@ -95,8 +95,8 @@
 
     // Ask
     {
-      await executeEthTxOnSub(api, seller, evmCollection, m => m.approve(matcher.options.address, tokenId));
-      await executeEthTxOnSub(api, seller, matcher, m => m.setAsk(PRICE, evmFungible.options.address, evmCollection.options.address, tokenId, 1));
+      await executeEthTxOnSub(web3, api, seller, evmCollection, m => m.approve(matcher.options.address, tokenId));
+      await executeEthTxOnSub(web3, api, seller, matcher, m => m.setAsk(PRICE, evmFungible.options.address, evmCollection.options.address, tokenId, 1));
     }
 
     // Token is transferred to matcher
@@ -107,9 +107,9 @@
       const sellerBalanceBeforePurchase = BigInt(await evmFungible.methods.balanceOf(subToEth(seller.address)).call());
       const buyerBalanceBeforePurchase = BigInt(await evmFungible.methods.balanceOf(subToEth(alice.address)).call());
 
-      await executeEthTxOnSub(api, alice, evmFungible, m => m.approve(matcher.options.address, PRICE));
+      await executeEthTxOnSub(web3, api, alice, evmFungible, m => m.approve(matcher.options.address, PRICE));
       // There is two functions named 'buy', so we should provide full signature
-      await executeEthTxOnSub(api, alice, matcher, m =>
+      await executeEthTxOnSub(web3, api, alice, matcher, m =>
         m['buy(address,uint256,address,uint256)'](evmCollection.options.address, tokenId, evmFungible.options.address, PRICE));
 
       // Approved price is removed from buyer balance, and added to seller
@@ -158,8 +158,8 @@
 
     // Ask
     {
-      await executeEthTxOnSub(api, seller, evmCollection, m => m.approve(matcher.options.address, tokenId));
-      await executeEthTxOnSub(api, seller, matcher, m => m.setAsk(PRICE, ksmToken, evmCollection.options.address, tokenId, 1));
+      await executeEthTxOnSub(web3, api, seller, evmCollection, m => m.approve(matcher.options.address, tokenId));
+      await executeEthTxOnSub(web3, api, seller, matcher, m => m.setAsk(PRICE, ksmToken, evmCollection.options.address, tokenId, 1));
     }
 
     // Token is transferred to matcher
@@ -173,7 +173,7 @@
       expect(await matcher.methods.escrowBalance(ksmToken, subToEth(seller.address)).call()).to.be.equal('0');
       expect(await matcher.methods.escrowBalance(ksmToken, subToEth(alice.address)).call()).to.be.equal(PRICE.toString());
 
-      await executeEthTxOnSub(api, alice, matcher, m => m.buy(evmCollection.options.address, tokenId));
+      await executeEthTxOnSub(web3, api, alice, matcher, m => m.buy(evmCollection.options.address, tokenId));
 
       // Price is removed from buyer balance, and added to seller
       expect(await matcher.methods.escrowBalance(ksmToken, subToEth(alice.address)).call()).to.be.equal('0');
modifiedtests/src/eth/nonFungible.test.tsdiffbeforeafterboth
--- a/tests/src/eth/nonFungible.test.ts
+++ b/tests/src/eth/nonFungible.test.ts
@@ -203,7 +203,7 @@
     const alice = privateKey('//Alice');
 
     const owner = createEthAccount(web3);
-    await transferBalanceToEth(api, alice, owner, 999999999999999);
+    await transferBalanceToEth(api, alice, owner);
 
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
 
@@ -213,7 +213,7 @@
     const contract = new web3.eth.Contract(nonFungibleAbi as any, address);
 
     {
-      const result = await contract.methods.approve(spender, tokenId).send({from: owner, gas: '0x1000000', gasPrice: '0x01'});
+      const result = await contract.methods.approve(spender, tokenId).send({from: owner, ...GAS_ARGS});
       const events = normalizeEvents(result.events);
 
       expect(events).to.be.deep.equal([
@@ -237,12 +237,12 @@
     const alice = privateKey('//Alice');
 
     const owner = createEthAccount(web3);
-    await transferBalanceToEth(api, alice, owner, 999999999999999);
+    await transferBalanceToEth(api, alice, owner);
 
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
 
     const spender = createEthAccount(web3);
-    await transferBalanceToEth(api, alice, spender, 999999999999999);
+    await transferBalanceToEth(api, alice, spender);
 
     const receiver = createEthAccount(web3);
 
@@ -285,12 +285,12 @@
     const alice = privateKey('//Alice');
 
     const owner = createEthAccount(web3);
-    await transferBalanceToEth(api, alice, owner, 999999999999999);
+    await transferBalanceToEth(api, alice, owner);
 
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
 
     const receiver = createEthAccount(web3);
-    await transferBalanceToEth(api, alice, receiver, 999999999999999);
+    await transferBalanceToEth(api, alice, receiver);
 
     const address = collectionIdToAddress(collection);
     const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});
modifiedtests/src/eth/payable.test.tsdiffbeforeafterboth
--- a/tests/src/eth/payable.test.ts
+++ b/tests/src/eth/payable.test.ts
@@ -32,7 +32,7 @@
         contract.methods.giveMoney().encodeABI(),
         '10000',
         GAS_ARGS.gas,
-        GAS_ARGS.gasPrice,
+        await web3.eth.getGasPrice(),
         null,
       );
       const events = await submitTransactionAsync(alice, tx);
modifiedtests/src/eth/proxy/nonFungibleProxy.test.tsdiffbeforeafterboth
before · tests/src/eth/proxy/nonFungibleProxy.test.ts
1//2// This file is subject to the terms and conditions defined in3// file 'LICENSE', which is part of this source code package.4//56import privateKey from '../../substrate/privateKey';7import {createCollectionExpectSuccess, createItemExpectSuccess, setVariableMetaDataExpectSuccess, setMetadataUpdatePermissionFlagExpectSuccess} from '../../util/helpers';8import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, GAS_ARGS, itWeb3, normalizeEvents} from '../util/helpers';9import nonFungibleAbi from '../nonFungibleAbi.json';10import {expect} from 'chai';11import {submitTransactionAsync} from '../../substrate/substrate-api';12import Web3 from 'web3';13import {readFile} from 'fs/promises';14import {ApiPromise} from '@polkadot/api';1516async function proxyWrap(api: ApiPromise, web3: Web3, wrapped: any) {17  // Proxy owner has no special privilegies, we don't need to reuse them18  const owner = await createEthAccountWithBalance(api, web3);19  const proxyContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/UniqueNFTProxy.abi`)).toString()), undefined, {20    from: owner,21    ...GAS_ARGS,22  });23  const proxy = await proxyContract.deploy({data: (await readFile(`${__dirname}/UniqueNFTProxy.bin`)).toString(), arguments: [wrapped.options.address]}).send({from: owner});24  return proxy;25}2627describe('NFT (Via EVM proxy): Information getting', () => {28  itWeb3('totalSupply', async ({api, web3}) => {29    const collection = await createCollectionExpectSuccess({30      mode: {type: 'NFT'},31    });32    const alice = privateKey('//Alice');33    const caller = await createEthAccountWithBalance(api, web3);3435    await createItemExpectSuccess(alice, collection, 'NFT', {Substrate: alice.address});3637    const address = collectionIdToAddress(collection);38    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));39    const totalSupply = await contract.methods.totalSupply().call();4041    expect(totalSupply).to.equal('1');42  });4344  itWeb3('balanceOf', async ({api, web3}) => {45    const collection = await createCollectionExpectSuccess({46      mode: {type: 'NFT'},47    });48    const alice = privateKey('//Alice');4950    const caller = await createEthAccountWithBalance(api, web3);51    await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});52    await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});53    await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});5455    const address = collectionIdToAddress(collection);56    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));57    const balance = await contract.methods.balanceOf(caller).call();5859    expect(balance).to.equal('3');60  });6162  itWeb3('ownerOf', async ({api, web3}) => {63    const collection = await createCollectionExpectSuccess({64      mode: {type: 'NFT'},65    });66    const alice = privateKey('//Alice');6768    const caller = await createEthAccountWithBalance(api, web3);69    const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});7071    const address = collectionIdToAddress(collection);72    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));73    const owner = await contract.methods.ownerOf(tokenId).call();7475    expect(owner).to.equal(caller);76  });77});7879describe('NFT (Via EVM proxy): Plain calls', () => {80  itWeb3('Can perform mint()', async ({web3, api}) => {81    const collection = await createCollectionExpectSuccess({82      mode: {type: 'NFT'},83    });84    const alice = privateKey('//Alice');85    const caller = await createEthAccountWithBalance(api, web3);86    const receiver = createEthAccount(web3);8788    const address = collectionIdToAddress(collection);89    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));9091    const changeAdminTx = api.tx.nft.addCollectionAdmin(collection, {Ethereum: contract.options.address});92    await submitTransactionAsync(alice, changeAdminTx);9394    {95      const nextTokenId = await contract.methods.nextTokenId().call();96      expect(nextTokenId).to.be.equal('1');97      const result = await contract.methods.mintWithTokenURI(98        receiver,99        nextTokenId,100        'Test URI',101      ).send({from: caller});102      const events = normalizeEvents(result.events);103104      expect(events).to.be.deep.equal([105        {106          address,107          event: 'Transfer',108          args: {109            from: '0x0000000000000000000000000000000000000000',110            to: receiver,111            tokenId: nextTokenId,112          },113        },114      ]);115116      expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');117    }118  });119  itWeb3('Can perform mintBulk()', async ({web3, api}) => {120    const collection = await createCollectionExpectSuccess({121      mode: {type: 'NFT'},122    });123    const alice = privateKey('//Alice');124125    const caller = await createEthAccountWithBalance(api, web3);126    const receiver = createEthAccount(web3);127128    const address = collectionIdToAddress(collection);129    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));130    const changeAdminTx = api.tx.nft.addCollectionAdmin(collection, {Ethereum: contract.options.address});131    await submitTransactionAsync(alice, changeAdminTx);132133    {134      const nextTokenId = await contract.methods.nextTokenId().call();135      expect(nextTokenId).to.be.equal('1');136      const result = await contract.methods.mintBulkWithTokenURI(137        receiver,138        [139          [nextTokenId, 'Test URI 0'],140          [+nextTokenId + 1, 'Test URI 1'],141          [+nextTokenId + 2, 'Test URI 2'],142        ],143      ).send({from: caller});144      const events = normalizeEvents(result.events);145146      expect(events).to.be.deep.equal([147        {148          address,149          event: 'Transfer',150          args: {151            from: '0x0000000000000000000000000000000000000000',152            to: receiver,153            tokenId: nextTokenId,154          },155        },156        {157          address,158          event: 'Transfer',159          args: {160            from: '0x0000000000000000000000000000000000000000',161            to: receiver,162            tokenId: String(+nextTokenId + 1),163          },164        },165        {166          address,167          event: 'Transfer',168          args: {169            from: '0x0000000000000000000000000000000000000000',170            to: receiver,171            tokenId: String(+nextTokenId + 2),172          },173        },174      ]);175176      expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI 0');177      expect(await contract.methods.tokenURI(+nextTokenId + 1).call()).to.be.equal('Test URI 1');178      expect(await contract.methods.tokenURI(+nextTokenId + 2).call()).to.be.equal('Test URI 2');179    }180  });181182  itWeb3('Can perform burn()', async ({web3, api}) => {183    const collection = await createCollectionExpectSuccess({184      mode: {type: 'NFT'},185    });186    const alice = privateKey('//Alice');187    const caller = await createEthAccountWithBalance(api, web3);188189    const address = collectionIdToAddress(collection);190    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));191    const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: contract.options.address});192193    const changeAdminTx = api.tx.nft.addCollectionAdmin(collection, {Ethereum: contract.options.address});194    await submitTransactionAsync(alice, changeAdminTx);195196    {197      const result = await contract.methods.burn(tokenId).send({from: caller});198      const events = normalizeEvents(result.events);199200      expect(events).to.be.deep.equal([201        {202          address,203          event: 'Transfer',204          args: {205            from: contract.options.address,206            to: '0x0000000000000000000000000000000000000000',207            tokenId: tokenId.toString(),208          },209        },210      ]);211    }212  });213214  itWeb3('Can perform approve()', async ({web3, api}) => {215    const collection = await createCollectionExpectSuccess({216      mode: {type: 'NFT'},217    });218    const alice = privateKey('//Alice');219    const caller = await createEthAccountWithBalance(api, web3);220    const spender = createEthAccount(web3);221222    const address = collectionIdToAddress(collection);223    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address));224    const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: contract.options.address});225226    {227      const result = await contract.methods.approve(spender, tokenId).send({from: caller, gas: '0x1000000', gasPrice: '0x01'});228      const events = normalizeEvents(result.events);229230      expect(events).to.be.deep.equal([231        {232          address,233          event: 'Approval',234          args: {235            owner: contract.options.address,236            approved: spender,237            tokenId: tokenId.toString(),238          },239        },240      ]);241    }242  });243244  itWeb3('Can perform transferFrom()', async ({web3, api}) => {245    const collection = await createCollectionExpectSuccess({246      mode: {type: 'NFT'},247    });248    const alice = privateKey('//Alice');249    const caller = await createEthAccountWithBalance(api, web3);250    const owner = await createEthAccountWithBalance(api, web3);251252    const receiver = createEthAccount(web3);253254    const address = collectionIdToAddress(collection);255    const evmCollection = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});256    const contract = await proxyWrap(api, web3, evmCollection);257    const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});258259    await evmCollection.methods.approve(contract.options.address, tokenId).send({from: owner});260261    {262      const result = await contract.methods.transferFrom(owner, receiver, tokenId).send({from: caller});263      const events = normalizeEvents(result.events);264      expect(events).to.be.deep.equal([265        {266          address,267          event: 'Transfer',268          args: {269            from: owner,270            to: receiver,271            tokenId: tokenId.toString(),272          },273        },274      ]);275    }276277    {278      const balance = await contract.methods.balanceOf(receiver).call();279      expect(+balance).to.equal(1);280    }281282    {283      const balance = await contract.methods.balanceOf(contract.options.address).call();284      expect(+balance).to.equal(0);285    }286  });287288  itWeb3('Can perform transfer()', async ({web3, api}) => {289    const collection = await createCollectionExpectSuccess({290      mode: {type: 'NFT'},291    });292    const alice = privateKey('//Alice');293    const caller = await createEthAccountWithBalance(api, web3);294    const receiver = createEthAccount(web3);295296    const address = collectionIdToAddress(collection);297    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));298    const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: contract.options.address});299300    {301      const result = await contract.methods.transfer(receiver, tokenId).send({from: caller});302      const events = normalizeEvents(result.events);303      expect(events).to.be.deep.equal([304        {305          address,306          event: 'Transfer',307          args: {308            from: contract.options.address,309            to: receiver,310            tokenId: tokenId.toString(),311          },312        },313      ]);314    }315316    {317      const balance = await contract.methods.balanceOf(contract.options.address).call();318      expect(+balance).to.equal(0);319    }320321    {322      const balance = await contract.methods.balanceOf(receiver).call();323      expect(+balance).to.equal(1);324    }325  });326327  itWeb3('Can perform getVariableMetadata', async ({web3, api}) => {328    const collection = await createCollectionExpectSuccess({329      mode: {type: 'NFT'},330    });331    const alice = privateKey('//Alice');332    const caller = await createEthAccountWithBalance(api, web3);333334    const address = collectionIdToAddress(collection);335    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));336    const item = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: contract.options.address});337    await setMetadataUpdatePermissionFlagExpectSuccess(alice, collection, 'Admin');338    await setVariableMetaDataExpectSuccess(alice, collection, item, [1, 2, 3]);339340    expect(await contract.methods.getVariableMetadata(item).call()).to.be.equal('0x010203');341  });342343  itWeb3('Can perform setVariableMetadata', async ({web3, api}) => {344    const collection = await createCollectionExpectSuccess({345      mode: {type: 'NFT'},346    });347    const alice = privateKey('//Alice');348    const caller = await createEthAccountWithBalance(api, web3);349350    const address = collectionIdToAddress(collection);351    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));352    const item = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: contract.options.address});353354    expect(await contract.methods.setVariableMetadata(item, '0x010203').send({from: caller}));355    expect(await contract.methods.getVariableMetadata(item).call()).to.be.equal('0x010203');356  });357});
after · tests/src/eth/proxy/nonFungibleProxy.test.ts
1//2// This file is subject to the terms and conditions defined in3// file 'LICENSE', which is part of this source code package.4//56import privateKey from '../../substrate/privateKey';7import {createCollectionExpectSuccess, createItemExpectSuccess, setVariableMetaDataExpectSuccess, setMetadataUpdatePermissionFlagExpectSuccess} from '../../util/helpers';8import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, GAS_ARGS, itWeb3, normalizeEvents} from '../util/helpers';9import nonFungibleAbi from '../nonFungibleAbi.json';10import {expect} from 'chai';11import {submitTransactionAsync} from '../../substrate/substrate-api';12import Web3 from 'web3';13import {readFile} from 'fs/promises';14import {ApiPromise} from '@polkadot/api';1516async function proxyWrap(api: ApiPromise, web3: Web3, wrapped: any) {17  // Proxy owner has no special privilegies, we don't need to reuse them18  const owner = await createEthAccountWithBalance(api, web3);19  const proxyContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/UniqueNFTProxy.abi`)).toString()), undefined, {20    from: owner,21    ...GAS_ARGS,22  });23  const proxy = await proxyContract.deploy({data: (await readFile(`${__dirname}/UniqueNFTProxy.bin`)).toString(), arguments: [wrapped.options.address]}).send({from: owner});24  return proxy;25}2627describe('NFT (Via EVM proxy): Information getting', () => {28  itWeb3('totalSupply', async ({api, web3}) => {29    const collection = await createCollectionExpectSuccess({30      mode: {type: 'NFT'},31    });32    const alice = privateKey('//Alice');33    const caller = await createEthAccountWithBalance(api, web3);3435    await createItemExpectSuccess(alice, collection, 'NFT', {Substrate: alice.address});3637    const address = collectionIdToAddress(collection);38    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));39    const totalSupply = await contract.methods.totalSupply().call();4041    expect(totalSupply).to.equal('1');42  });4344  itWeb3('balanceOf', async ({api, web3}) => {45    const collection = await createCollectionExpectSuccess({46      mode: {type: 'NFT'},47    });48    const alice = privateKey('//Alice');4950    const caller = await createEthAccountWithBalance(api, web3);51    await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});52    await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});53    await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});5455    const address = collectionIdToAddress(collection);56    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));57    const balance = await contract.methods.balanceOf(caller).call();5859    expect(balance).to.equal('3');60  });6162  itWeb3('ownerOf', async ({api, web3}) => {63    const collection = await createCollectionExpectSuccess({64      mode: {type: 'NFT'},65    });66    const alice = privateKey('//Alice');6768    const caller = await createEthAccountWithBalance(api, web3);69    const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});7071    const address = collectionIdToAddress(collection);72    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));73    const owner = await contract.methods.ownerOf(tokenId).call();7475    expect(owner).to.equal(caller);76  });77});7879describe('NFT (Via EVM proxy): Plain calls', () => {80  itWeb3('Can perform mint()', async ({web3, api}) => {81    const collection = await createCollectionExpectSuccess({82      mode: {type: 'NFT'},83    });84    const alice = privateKey('//Alice');85    const caller = await createEthAccountWithBalance(api, web3);86    const receiver = createEthAccount(web3);8788    const address = collectionIdToAddress(collection);89    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));9091    const changeAdminTx = api.tx.nft.addCollectionAdmin(collection, {Ethereum: contract.options.address});92    await submitTransactionAsync(alice, changeAdminTx);9394    {95      const nextTokenId = await contract.methods.nextTokenId().call();96      expect(nextTokenId).to.be.equal('1');97      const result = await contract.methods.mintWithTokenURI(98        receiver,99        nextTokenId,100        'Test URI',101      ).send({from: caller});102      const events = normalizeEvents(result.events);103104      expect(events).to.be.deep.equal([105        {106          address,107          event: 'Transfer',108          args: {109            from: '0x0000000000000000000000000000000000000000',110            to: receiver,111            tokenId: nextTokenId,112          },113        },114      ]);115116      expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');117    }118  });119  itWeb3('Can perform mintBulk()', async ({web3, api}) => {120    const collection = await createCollectionExpectSuccess({121      mode: {type: 'NFT'},122    });123    const alice = privateKey('//Alice');124125    const caller = await createEthAccountWithBalance(api, web3);126    const receiver = createEthAccount(web3);127128    const address = collectionIdToAddress(collection);129    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));130    const changeAdminTx = api.tx.nft.addCollectionAdmin(collection, {Ethereum: contract.options.address});131    await submitTransactionAsync(alice, changeAdminTx);132133    {134      const nextTokenId = await contract.methods.nextTokenId().call();135      expect(nextTokenId).to.be.equal('1');136      const result = await contract.methods.mintBulkWithTokenURI(137        receiver,138        [139          [nextTokenId, 'Test URI 0'],140          [+nextTokenId + 1, 'Test URI 1'],141          [+nextTokenId + 2, 'Test URI 2'],142        ],143      ).send({from: caller});144      const events = normalizeEvents(result.events);145146      expect(events).to.be.deep.equal([147        {148          address,149          event: 'Transfer',150          args: {151            from: '0x0000000000000000000000000000000000000000',152            to: receiver,153            tokenId: nextTokenId,154          },155        },156        {157          address,158          event: 'Transfer',159          args: {160            from: '0x0000000000000000000000000000000000000000',161            to: receiver,162            tokenId: String(+nextTokenId + 1),163          },164        },165        {166          address,167          event: 'Transfer',168          args: {169            from: '0x0000000000000000000000000000000000000000',170            to: receiver,171            tokenId: String(+nextTokenId + 2),172          },173        },174      ]);175176      expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI 0');177      expect(await contract.methods.tokenURI(+nextTokenId + 1).call()).to.be.equal('Test URI 1');178      expect(await contract.methods.tokenURI(+nextTokenId + 2).call()).to.be.equal('Test URI 2');179    }180  });181182  itWeb3('Can perform burn()', async ({web3, api}) => {183    const collection = await createCollectionExpectSuccess({184      mode: {type: 'NFT'},185    });186    const alice = privateKey('//Alice');187    const caller = await createEthAccountWithBalance(api, web3);188189    const address = collectionIdToAddress(collection);190    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));191    const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: contract.options.address});192193    const changeAdminTx = api.tx.nft.addCollectionAdmin(collection, {Ethereum: contract.options.address});194    await submitTransactionAsync(alice, changeAdminTx);195196    {197      const result = await contract.methods.burn(tokenId).send({from: caller});198      const events = normalizeEvents(result.events);199200      expect(events).to.be.deep.equal([201        {202          address,203          event: 'Transfer',204          args: {205            from: contract.options.address,206            to: '0x0000000000000000000000000000000000000000',207            tokenId: tokenId.toString(),208          },209        },210      ]);211    }212  });213214  itWeb3('Can perform approve()', async ({web3, api}) => {215    const collection = await createCollectionExpectSuccess({216      mode: {type: 'NFT'},217    });218    const alice = privateKey('//Alice');219    const caller = await createEthAccountWithBalance(api, web3);220    const spender = createEthAccount(web3);221222    const address = collectionIdToAddress(collection);223    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address));224    const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: contract.options.address});225226    {227      const result = await contract.methods.approve(spender, tokenId).send({from: caller, ...GAS_ARGS});228      const events = normalizeEvents(result.events);229230      expect(events).to.be.deep.equal([231        {232          address,233          event: 'Approval',234          args: {235            owner: contract.options.address,236            approved: spender,237            tokenId: tokenId.toString(),238          },239        },240      ]);241    }242  });243244  itWeb3('Can perform transferFrom()', async ({web3, api}) => {245    const collection = await createCollectionExpectSuccess({246      mode: {type: 'NFT'},247    });248    const alice = privateKey('//Alice');249    const caller = await createEthAccountWithBalance(api, web3);250    const owner = await createEthAccountWithBalance(api, web3);251252    const receiver = createEthAccount(web3);253254    const address = collectionIdToAddress(collection);255    const evmCollection = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});256    const contract = await proxyWrap(api, web3, evmCollection);257    const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});258259    await evmCollection.methods.approve(contract.options.address, tokenId).send({from: owner});260261    {262      const result = await contract.methods.transferFrom(owner, receiver, tokenId).send({from: caller});263      const events = normalizeEvents(result.events);264      expect(events).to.be.deep.equal([265        {266          address,267          event: 'Transfer',268          args: {269            from: owner,270            to: receiver,271            tokenId: tokenId.toString(),272          },273        },274      ]);275    }276277    {278      const balance = await contract.methods.balanceOf(receiver).call();279      expect(+balance).to.equal(1);280    }281282    {283      const balance = await contract.methods.balanceOf(contract.options.address).call();284      expect(+balance).to.equal(0);285    }286  });287288  itWeb3('Can perform transfer()', async ({web3, api}) => {289    const collection = await createCollectionExpectSuccess({290      mode: {type: 'NFT'},291    });292    const alice = privateKey('//Alice');293    const caller = await createEthAccountWithBalance(api, web3);294    const receiver = createEthAccount(web3);295296    const address = collectionIdToAddress(collection);297    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));298    const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: contract.options.address});299300    {301      const result = await contract.methods.transfer(receiver, tokenId).send({from: caller});302      const events = normalizeEvents(result.events);303      expect(events).to.be.deep.equal([304        {305          address,306          event: 'Transfer',307          args: {308            from: contract.options.address,309            to: receiver,310            tokenId: tokenId.toString(),311          },312        },313      ]);314    }315316    {317      const balance = await contract.methods.balanceOf(contract.options.address).call();318      expect(+balance).to.equal(0);319    }320321    {322      const balance = await contract.methods.balanceOf(receiver).call();323      expect(+balance).to.equal(1);324    }325  });326327  itWeb3('Can perform getVariableMetadata', async ({web3, api}) => {328    const collection = await createCollectionExpectSuccess({329      mode: {type: 'NFT'},330    });331    const alice = privateKey('//Alice');332    const caller = await createEthAccountWithBalance(api, web3);333334    const address = collectionIdToAddress(collection);335    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));336    const item = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: contract.options.address});337    await setMetadataUpdatePermissionFlagExpectSuccess(alice, collection, 'Admin');338    await setVariableMetaDataExpectSuccess(alice, collection, item, [1, 2, 3]);339340    expect(await contract.methods.getVariableMetadata(item).call()).to.be.equal('0x010203');341  });342343  itWeb3('Can perform setVariableMetadata', async ({web3, api}) => {344    const collection = await createCollectionExpectSuccess({345      mode: {type: 'NFT'},346    });347    const alice = privateKey('//Alice');348    const caller = await createEthAccountWithBalance(api, web3);349350    const address = collectionIdToAddress(collection);351    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));352    const item = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: contract.options.address});353354    expect(await contract.methods.setVariableMetadata(item, '0x010203').send({from: caller}));355    expect(await contract.methods.getVariableMetadata(item).call()).to.be.equal('0x010203');356  });357});
modifiedtests/src/eth/util/helpers.tsdiffbeforeafterboth
--- a/tests/src/eth/util/helpers.ts
+++ b/tests/src/eth/util/helpers.ts
@@ -12,14 +12,14 @@
 import usingApi, {submitTransactionAsync} from '../../substrate/substrate-api';
 import {IKeyringPair} from '@polkadot/types/types';
 import {expect} from 'chai';
-import {getGenericResult} from '../../util/helpers';
+import {getGenericResult, UNIQUE} from '../../util/helpers';
 import * as solc from 'solc';
 import config from '../../config';
 import privateKey from '../../substrate/privateKey';
 import contractHelpersAbi from './contractHelpersAbi.json';
 import getBalance from '../../substrate/get-balance';
 
-export const GAS_ARGS = {gas: 0x1000000, gasPrice: '0x01'};
+export const GAS_ARGS = {gas: 1000000};
 
 let web3Connected = false;
 export async function usingWeb3<T>(cb: (web3: Web3) => Promise<T> | T): Promise<T> {
@@ -63,7 +63,7 @@
   return account;
 }
 
-export async function transferBalanceToEth(api: ApiPromise, source: IKeyringPair, target: string, amount = 999999999999999) {
+export async function transferBalanceToEth(api: ApiPromise, source: IKeyringPair, target: string, amount = 10000n * UNIQUE) {
   const tx = api.tx.balances.transfer(evmToAddress(target), amount);
   const events = await submitTransactionAsync(source, tx);
   const result = getGenericResult(events);
@@ -228,14 +228,14 @@
   return new web3.eth.Contract(contractHelpersAbi as any, '0x842899ECF380553E8a4de75bF534cdf6fBF64049', {from: caller, ...GAS_ARGS});
 }
 
-export async function executeEthTxOnSub(api: ApiPromise, from: IKeyringPair, to: any, mkTx: (methods: any) => any, {value = 0}: {value?: bigint | number} = { }) {
+export async function executeEthTxOnSub(web3: Web3, api: ApiPromise, from: IKeyringPair, to: any, mkTx: (methods: any) => any, {value = 0}: {value?: bigint | number} = { }) {
   const tx = api.tx.evm.call(
     subToEth(from.address),
     to.options.address,
     mkTx(to.methods).encodeABI(),
     value,
     GAS_ARGS.gas,
-    GAS_ARGS.gasPrice,
+    await web3.eth.getGasPrice(),
     null,
   );
   const events = await submitTransactionAsync(from, tx);