difftreelog
feat balanceOfCross for RFT token
in: master
7 files changed
pallets/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.
pallets/refungible/src/stubs/UniqueRefungibleToken.rawdiffbeforeafterbothbinary blob — no preview
pallets/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.
runtime/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;
tests/src/eth/abi/reFungibleToken.jsondiffbeforeafterboth1[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]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]tests/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.
tests/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', () => {