git.delta.rocks / unique-network / refs/commits / 9871bd2fd605

difftreelog

feat balanceOfCross for RFT token

Trubnikov Sergey2023-04-18parent: #fc48e60.patch.diff
in: master

7 files changed

modifiedpallets/refungible/src/erc_token.rsdiffbeforeafterboth
--- a/pallets/refungible/src/erc_token.rs
+++ b/pallets/refungible/src/erc_token.rs
@@ -283,6 +283,16 @@
 			.map_err(dispatch_to_evm::<T>)?;
 		Ok(true)
 	}
+
+	/// @notice Balance of account
+	/// @param owner An cross address for whom to query the balance
+	/// @return The number of fingibles owned by `owner`, possibly zero
+	fn balance_of_cross(&self, owner: CrossAddress) -> Result<U256> {
+		self.consume_store_reads(1)?;
+		let balance = <Balance<T>>::get((self.id, self.1, owner.into_sub_cross_account::<T>()?));
+		Ok(balance.into())
+	}
+
 	/// @dev Function that changes total amount of the tokens.
 	///  Throws if `msg.sender` doesn't owns all of the tokens.
 	/// @param amount New total amount of the tokens.
modifiedpallets/refungible/src/stubs/UniqueRefungibleToken.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/refungible/src/stubs/UniqueRefungibleToken.soldiffbeforeafterboth
--- a/pallets/refungible/src/stubs/UniqueRefungibleToken.sol
+++ b/pallets/refungible/src/stubs/UniqueRefungibleToken.sol
@@ -36,7 +36,7 @@
 	}
 }
 
-/// @dev the ERC-165 identifier for this interface is 0x01d536fc
+/// @dev the ERC-165 identifier for this interface is 0xedd3a564
 contract ERC20UniqueExtensions is Dummy, ERC165 {
 	/// @dev Function to check the amount of tokens that an owner allowed to a spender.
 	/// @param owner crossAddress The address which owns the funds.
@@ -97,6 +97,18 @@
 		return false;
 	}
 
+	/// @notice Balance of account
+	/// @param owner An cross address for whom to query the balance
+	/// @return The number of fingibles owned by `owner`, possibly zero
+	/// @dev EVM selector for this function is: 0xec069398,
+	///  or in textual repr: balanceOfCross((address,uint256))
+	function balanceOfCross(CrossAddress memory owner) public view returns (uint256) {
+		require(false, stub_error);
+		owner;
+		dummy;
+		return 0;
+	}
+
 	/// @dev Function that changes total amount of the tokens.
 	///  Throws if `msg.sender` doesn't owns all of the tokens.
 	/// @param amount New total amount of the tokens.
modifiedruntime/common/ethereum/sponsoring/refungible.rsdiffbeforeafterboth
--- a/runtime/common/ethereum/sponsoring/refungible.rs
+++ b/runtime/common/ethereum/sponsoring/refungible.rs
@@ -343,9 +343,11 @@
 			ERC165Call(_, _) => None,
 
 			// Not sponsored
-			AllowanceCross { .. } | BurnFrom { .. } | BurnFromCross { .. } | Repartition { .. } => {
-				None
-			}
+			AllowanceCross { .. }
+			| BalanceOfCross { .. }
+			| BurnFrom { .. }
+			| BurnFromCross { .. }
+			| Repartition { .. } => None,
 
 			TransferCross { .. } | TransferFromCross { .. } => {
 				let RefungibleTokenHandle(handle, token_id) = token;
modifiedtests/src/eth/abi/reFungibleToken.jsondiffbeforeafterboth
before · tests/src/eth/abi/reFungibleToken.json
1[2  {3    "anonymous": false,4    "inputs": [5      {6        "indexed": true,7        "internalType": "address",8        "name": "owner",9        "type": "address"10      },11      {12        "indexed": true,13        "internalType": "address",14        "name": "spender",15        "type": "address"16      },17      {18        "indexed": false,19        "internalType": "uint256",20        "name": "value",21        "type": "uint256"22      }23    ],24    "name": "Approval",25    "type": "event"26  },27  {28    "anonymous": false,29    "inputs": [30      {31        "indexed": true,32        "internalType": "address",33        "name": "from",34        "type": "address"35      },36      {37        "indexed": true,38        "internalType": "address",39        "name": "to",40        "type": "address"41      },42      {43        "indexed": false,44        "internalType": "uint256",45        "name": "value",46        "type": "uint256"47      }48    ],49    "name": "Transfer",50    "type": "event"51  },52  {53    "inputs": [54      { "internalType": "address", "name": "owner", "type": "address" },55      { "internalType": "address", "name": "spender", "type": "address" }56    ],57    "name": "allowance",58    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],59    "stateMutability": "view",60    "type": "function"61  },62  {63    "inputs": [64      {65        "components": [66          { "internalType": "address", "name": "eth", "type": "address" },67          { "internalType": "uint256", "name": "sub", "type": "uint256" }68        ],69        "internalType": "struct CrossAddress",70        "name": "owner",71        "type": "tuple"72      },73      {74        "components": [75          { "internalType": "address", "name": "eth", "type": "address" },76          { "internalType": "uint256", "name": "sub", "type": "uint256" }77        ],78        "internalType": "struct CrossAddress",79        "name": "spender",80        "type": "tuple"81      }82    ],83    "name": "allowanceCross",84    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],85    "stateMutability": "view",86    "type": "function"87  },88  {89    "inputs": [90      { "internalType": "address", "name": "spender", "type": "address" },91      { "internalType": "uint256", "name": "amount", "type": "uint256" }92    ],93    "name": "approve",94    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],95    "stateMutability": "nonpayable",96    "type": "function"97  },98  {99    "inputs": [100      {101        "components": [102          { "internalType": "address", "name": "eth", "type": "address" },103          { "internalType": "uint256", "name": "sub", "type": "uint256" }104        ],105        "internalType": "struct CrossAddress",106        "name": "spender",107        "type": "tuple"108      },109      { "internalType": "uint256", "name": "amount", "type": "uint256" }110    ],111    "name": "approveCross",112    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],113    "stateMutability": "nonpayable",114    "type": "function"115  },116  {117    "inputs": [118      { "internalType": "address", "name": "owner", "type": "address" }119    ],120    "name": "balanceOf",121    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],122    "stateMutability": "view",123    "type": "function"124  },125  {126    "inputs": [127      {128        "components": [129          { "internalType": "address", "name": "eth", "type": "address" },130          { "internalType": "uint256", "name": "sub", "type": "uint256" }131        ],132        "internalType": "struct CrossAddress",133        "name": "from",134        "type": "tuple"135      },136      { "internalType": "uint256", "name": "amount", "type": "uint256" }137    ],138    "name": "burnFromCross",139    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],140    "stateMutability": "nonpayable",141    "type": "function"142  },143  {144    "inputs": [],145    "name": "decimals",146    "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }],147    "stateMutability": "view",148    "type": "function"149  },150  {151    "inputs": [],152    "name": "name",153    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],154    "stateMutability": "view",155    "type": "function"156  },157  {158    "inputs": [],159    "name": "parentToken",160    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],161    "stateMutability": "view",162    "type": "function"163  },164  {165    "inputs": [],166    "name": "parentTokenId",167    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],168    "stateMutability": "view",169    "type": "function"170  },171  {172    "inputs": [173      { "internalType": "uint256", "name": "amount", "type": "uint256" }174    ],175    "name": "repartition",176    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],177    "stateMutability": "nonpayable",178    "type": "function"179  },180  {181    "inputs": [182      { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }183    ],184    "name": "supportsInterface",185    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],186    "stateMutability": "view",187    "type": "function"188  },189  {190    "inputs": [],191    "name": "symbol",192    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],193    "stateMutability": "view",194    "type": "function"195  },196  {197    "inputs": [],198    "name": "totalSupply",199    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],200    "stateMutability": "view",201    "type": "function"202  },203  {204    "inputs": [205      { "internalType": "address", "name": "to", "type": "address" },206      { "internalType": "uint256", "name": "amount", "type": "uint256" }207    ],208    "name": "transfer",209    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],210    "stateMutability": "nonpayable",211    "type": "function"212  },213  {214    "inputs": [215      {216        "components": [217          { "internalType": "address", "name": "eth", "type": "address" },218          { "internalType": "uint256", "name": "sub", "type": "uint256" }219        ],220        "internalType": "struct CrossAddress",221        "name": "to",222        "type": "tuple"223      },224      { "internalType": "uint256", "name": "amount", "type": "uint256" }225    ],226    "name": "transferCross",227    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],228    "stateMutability": "nonpayable",229    "type": "function"230  },231  {232    "inputs": [233      { "internalType": "address", "name": "from", "type": "address" },234      { "internalType": "address", "name": "to", "type": "address" },235      { "internalType": "uint256", "name": "amount", "type": "uint256" }236    ],237    "name": "transferFrom",238    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],239    "stateMutability": "nonpayable",240    "type": "function"241  },242  {243    "inputs": [244      {245        "components": [246          { "internalType": "address", "name": "eth", "type": "address" },247          { "internalType": "uint256", "name": "sub", "type": "uint256" }248        ],249        "internalType": "struct CrossAddress",250        "name": "from",251        "type": "tuple"252      },253      {254        "components": [255          { "internalType": "address", "name": "eth", "type": "address" },256          { "internalType": "uint256", "name": "sub", "type": "uint256" }257        ],258        "internalType": "struct CrossAddress",259        "name": "to",260        "type": "tuple"261      },262      { "internalType": "uint256", "name": "amount", "type": "uint256" }263    ],264    "name": "transferFromCross",265    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],266    "stateMutability": "nonpayable",267    "type": "function"268  }269]
after · tests/src/eth/abi/reFungibleToken.json
1[2  {3    "anonymous": false,4    "inputs": [5      {6        "indexed": true,7        "internalType": "address",8        "name": "owner",9        "type": "address"10      },11      {12        "indexed": true,13        "internalType": "address",14        "name": "spender",15        "type": "address"16      },17      {18        "indexed": false,19        "internalType": "uint256",20        "name": "value",21        "type": "uint256"22      }23    ],24    "name": "Approval",25    "type": "event"26  },27  {28    "anonymous": false,29    "inputs": [30      {31        "indexed": true,32        "internalType": "address",33        "name": "from",34        "type": "address"35      },36      {37        "indexed": true,38        "internalType": "address",39        "name": "to",40        "type": "address"41      },42      {43        "indexed": false,44        "internalType": "uint256",45        "name": "value",46        "type": "uint256"47      }48    ],49    "name": "Transfer",50    "type": "event"51  },52  {53    "inputs": [54      { "internalType": "address", "name": "owner", "type": "address" },55      { "internalType": "address", "name": "spender", "type": "address" }56    ],57    "name": "allowance",58    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],59    "stateMutability": "view",60    "type": "function"61  },62  {63    "inputs": [64      {65        "components": [66          { "internalType": "address", "name": "eth", "type": "address" },67          { "internalType": "uint256", "name": "sub", "type": "uint256" }68        ],69        "internalType": "struct CrossAddress",70        "name": "owner",71        "type": "tuple"72      },73      {74        "components": [75          { "internalType": "address", "name": "eth", "type": "address" },76          { "internalType": "uint256", "name": "sub", "type": "uint256" }77        ],78        "internalType": "struct CrossAddress",79        "name": "spender",80        "type": "tuple"81      }82    ],83    "name": "allowanceCross",84    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],85    "stateMutability": "view",86    "type": "function"87  },88  {89    "inputs": [90      { "internalType": "address", "name": "spender", "type": "address" },91      { "internalType": "uint256", "name": "amount", "type": "uint256" }92    ],93    "name": "approve",94    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],95    "stateMutability": "nonpayable",96    "type": "function"97  },98  {99    "inputs": [100      {101        "components": [102          { "internalType": "address", "name": "eth", "type": "address" },103          { "internalType": "uint256", "name": "sub", "type": "uint256" }104        ],105        "internalType": "struct CrossAddress",106        "name": "spender",107        "type": "tuple"108      },109      { "internalType": "uint256", "name": "amount", "type": "uint256" }110    ],111    "name": "approveCross",112    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],113    "stateMutability": "nonpayable",114    "type": "function"115  },116  {117    "inputs": [118      { "internalType": "address", "name": "owner", "type": "address" }119    ],120    "name": "balanceOf",121    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],122    "stateMutability": "view",123    "type": "function"124  },125  {126    "inputs": [127      {128        "components": [129          { "internalType": "address", "name": "eth", "type": "address" },130          { "internalType": "uint256", "name": "sub", "type": "uint256" }131        ],132        "internalType": "struct CrossAddress",133        "name": "owner",134        "type": "tuple"135      }136    ],137    "name": "balanceOfCross",138    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],139    "stateMutability": "view",140    "type": "function"141  },142  {143    "inputs": [144      {145        "components": [146          { "internalType": "address", "name": "eth", "type": "address" },147          { "internalType": "uint256", "name": "sub", "type": "uint256" }148        ],149        "internalType": "struct CrossAddress",150        "name": "from",151        "type": "tuple"152      },153      { "internalType": "uint256", "name": "amount", "type": "uint256" }154    ],155    "name": "burnFromCross",156    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],157    "stateMutability": "nonpayable",158    "type": "function"159  },160  {161    "inputs": [],162    "name": "decimals",163    "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }],164    "stateMutability": "view",165    "type": "function"166  },167  {168    "inputs": [],169    "name": "name",170    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],171    "stateMutability": "view",172    "type": "function"173  },174  {175    "inputs": [],176    "name": "parentToken",177    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],178    "stateMutability": "view",179    "type": "function"180  },181  {182    "inputs": [],183    "name": "parentTokenId",184    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],185    "stateMutability": "view",186    "type": "function"187  },188  {189    "inputs": [190      { "internalType": "uint256", "name": "amount", "type": "uint256" }191    ],192    "name": "repartition",193    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],194    "stateMutability": "nonpayable",195    "type": "function"196  },197  {198    "inputs": [199      { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }200    ],201    "name": "supportsInterface",202    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],203    "stateMutability": "view",204    "type": "function"205  },206  {207    "inputs": [],208    "name": "symbol",209    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],210    "stateMutability": "view",211    "type": "function"212  },213  {214    "inputs": [],215    "name": "totalSupply",216    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],217    "stateMutability": "view",218    "type": "function"219  },220  {221    "inputs": [222      { "internalType": "address", "name": "to", "type": "address" },223      { "internalType": "uint256", "name": "amount", "type": "uint256" }224    ],225    "name": "transfer",226    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],227    "stateMutability": "nonpayable",228    "type": "function"229  },230  {231    "inputs": [232      {233        "components": [234          { "internalType": "address", "name": "eth", "type": "address" },235          { "internalType": "uint256", "name": "sub", "type": "uint256" }236        ],237        "internalType": "struct CrossAddress",238        "name": "to",239        "type": "tuple"240      },241      { "internalType": "uint256", "name": "amount", "type": "uint256" }242    ],243    "name": "transferCross",244    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],245    "stateMutability": "nonpayable",246    "type": "function"247  },248  {249    "inputs": [250      { "internalType": "address", "name": "from", "type": "address" },251      { "internalType": "address", "name": "to", "type": "address" },252      { "internalType": "uint256", "name": "amount", "type": "uint256" }253    ],254    "name": "transferFrom",255    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],256    "stateMutability": "nonpayable",257    "type": "function"258  },259  {260    "inputs": [261      {262        "components": [263          { "internalType": "address", "name": "eth", "type": "address" },264          { "internalType": "uint256", "name": "sub", "type": "uint256" }265        ],266        "internalType": "struct CrossAddress",267        "name": "from",268        "type": "tuple"269      },270      {271        "components": [272          { "internalType": "address", "name": "eth", "type": "address" },273          { "internalType": "uint256", "name": "sub", "type": "uint256" }274        ],275        "internalType": "struct CrossAddress",276        "name": "to",277        "type": "tuple"278      },279      { "internalType": "uint256", "name": "amount", "type": "uint256" }280    ],281    "name": "transferFromCross",282    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],283    "stateMutability": "nonpayable",284    "type": "function"285  }286]
modifiedtests/src/eth/api/UniqueRefungibleToken.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueRefungibleToken.sol
+++ b/tests/src/eth/api/UniqueRefungibleToken.sol
@@ -23,7 +23,7 @@
 	function parentTokenId() external view returns (uint256);
 }
 
-/// @dev the ERC-165 identifier for this interface is 0x01d536fc
+/// @dev the ERC-165 identifier for this interface is 0xedd3a564
 interface ERC20UniqueExtensions is Dummy, ERC165 {
 	/// @dev Function to check the amount of tokens that an owner allowed to a spender.
 	/// @param owner crossAddress The address which owns the funds.
@@ -60,6 +60,13 @@
 	///  or in textual repr: approveCross((address,uint256),uint256)
 	function approveCross(CrossAddress memory spender, uint256 amount) external returns (bool);
 
+	/// @notice Balance of account
+	/// @param owner An cross address for whom to query the balance
+	/// @return The number of fingibles owned by `owner`, possibly zero
+	/// @dev EVM selector for this function is: 0xec069398,
+	///  or in textual repr: balanceOfCross((address,uint256))
+	function balanceOfCross(CrossAddress memory owner) external view returns (uint256);
+
 	/// @dev Function that changes total amount of the tokens.
 	///  Throws if `msg.sender` doesn't owns all of the tokens.
 	/// @param amount New total amount of the tokens.
modifiedtests/src/eth/reFungibleToken.test.tsdiffbeforeafterboth
--- a/tests/src/eth/reFungibleToken.test.ts
+++ b/tests/src/eth/reFungibleToken.test.ts
@@ -466,6 +466,21 @@
       expect(await collection.getTokenBalance(tokenId, {Substrate: ownerSub.address})).to.be.equal(150n);
     }
   });
+
+  itEth('Check balanceOfCross()', async ({helper}) => {
+    const collection = await helper.rft.mintCollection(alice, {});
+    const owner = await helper.ethCrossAccount.createAccountWithBalance(donor);
+    const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner.eth});
+    const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);
+    const tokenContract = await helper.ethNativeContract.rftToken(tokenAddress, owner.eth);
+
+    expect(BigInt(await tokenContract.methods.balanceOfCross(owner).call({from: owner.eth})) === 200n).to.be.true;
+
+    for (let i = 1n; i < 100n; i++) {
+      await tokenContract.methods.repartition(i).send({from: owner.eth});
+      expect(BigInt(await tokenContract.methods.balanceOfCross(owner).call({from: owner.eth})) === i).to.be.true;
+    }
+  });
 });
 
 describe('Refungible: Fees', () => {