git.delta.rocks / unique-network / refs/commits / d58cb79d60f8

difftreelog

added repartition method to refungible erc20 extensions

Grigoriy Simonov2022-07-22parent: #4fbe604.patch.diff
in: master

7 files changed

modifiedpallets/refungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -1,3 +1,19 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
 extern crate alloc;
 use evm_coder::{generate_stubgen, solidity_interface, types::*};
 
modifiedpallets/refungible/src/erc_token.rsdiffbeforeafterboth
--- a/pallets/refungible/src/erc_token.rs
+++ b/pallets/refungible/src/erc_token.rs
@@ -149,6 +149,15 @@
 			.map_err(dispatch_to_evm::<T>)?;
 		Ok(true)
 	}
+
+	#[weight(<SelfWeightOf<T>>::repartition_item())]
+	fn repartition(&mut self, caller: caller, amount: uint256) -> Result<bool> {
+		let caller = T::CrossAccountId::from_eth(caller);
+		let amount = amount.try_into().map_err(|_| "amount overflow")?;
+
+		<Pallet<T>>::repartition(self, &caller, self.1, amount).map_err(dispatch_to_evm::<T>)?;
+		Ok(true)
+	}
 }
 
 impl<T: Config> RefungibleTokenHandle<T> {
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
@@ -31,18 +31,6 @@
 	);
 }
 
-// Selector: 79cc6790
-contract ERC20UniqueExtensions is Dummy, ERC165 {
-	// Selector: burnFrom(address,uint256) 79cc6790
-	function burnFrom(address from, uint256 amount) public returns (bool) {
-		require(false, stub_error);
-		from;
-		amount;
-		dummy = 0;
-		return false;
-	}
-}
-
 // Selector: 942e8b22
 contract ERC20 is Dummy, ERC165, ERC20Events {
 	// Selector: name() 06fdde03
@@ -127,4 +115,24 @@
 	}
 }
 
+// Selector: ab8deb37
+contract ERC20UniqueExtensions is Dummy, ERC165 {
+	// Selector: burnFrom(address,uint256) 79cc6790
+	function burnFrom(address from, uint256 amount) public returns (bool) {
+		require(false, stub_error);
+		from;
+		amount;
+		dummy = 0;
+		return false;
+	}
+
+	// Selector: repartition(uint256) d2418ca7
+	function repartition(uint256 amount) public returns (bool) {
+		require(false, stub_error);
+		amount;
+		dummy = 0;
+		return false;
+	}
+}
+
 contract UniqueRefungibleToken is Dummy, ERC165, ERC20, ERC20UniqueExtensions {}
modifiedtests/src/eth/api/UniqueRefungibleToken.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueRefungibleToken.sol
+++ b/tests/src/eth/api/UniqueRefungibleToken.sol
@@ -22,12 +22,6 @@
 	);
 }
 
-// Selector: 79cc6790
-interface ERC20UniqueExtensions is Dummy, ERC165 {
-	// Selector: burnFrom(address,uint256) 79cc6790
-	function burnFrom(address from, uint256 amount) external returns (bool);
-}
-
 // Selector: 942e8b22
 interface ERC20 is Dummy, ERC165, ERC20Events {
 	// Selector: name() 06fdde03
@@ -65,6 +59,15 @@
 		returns (uint256);
 }
 
+// Selector: ab8deb37
+interface ERC20UniqueExtensions is Dummy, ERC165 {
+	// Selector: burnFrom(address,uint256) 79cc6790
+	function burnFrom(address from, uint256 amount) external returns (bool);
+
+	// Selector: repartition(uint256) d2418ca7
+	function repartition(uint256 amount) external returns (bool);
+}
+
 interface UniqueRefungibleToken is
 	Dummy,
 	ERC165,
modifiedtests/src/eth/reFungibleToken.test.tsdiffbeforeafterboth
--- a/tests/src/eth/reFungibleToken.test.ts
+++ b/tests/src/eth/reFungibleToken.test.ts
@@ -210,6 +210,39 @@
       expect(+balance).to.equal(50);
     }
   });
+
+  itWeb3('Can perform repartition()', async ({web3, api, privateKeyWrapper}) => {
+    const alice = privateKeyWrapper('//Alice');
+
+    const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId;
+
+    const owner = createEthAccount(web3);
+    await transferBalanceToEth(api, alice, owner);
+
+    const receiver = createEthAccount(web3);
+    await transferBalanceToEth(api, alice, receiver);
+
+    const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n, {Ethereum: owner})).itemId;
+
+    const address = tokenIdToAddress(collectionId, tokenId);
+    const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});
+
+    await contract.methods.repartition(200).send({from: owner});
+    expect(+await contract.methods.balanceOf(owner).call()).to.be.equal(200);
+    await contract.methods.transfer(receiver, 110).send({from: owner});
+    expect(+await contract.methods.balanceOf(owner).call()).to.be.equal(90);
+    expect(+await contract.methods.balanceOf(receiver).call()).to.be.equal(110);
+    
+    await expect(contract.methods.repartition(80).send({from: owner})).to.eventually.be.rejected;
+
+    await contract.methods.transfer(receiver, 90).send({from: owner});
+    expect(+await contract.methods.balanceOf(owner).call()).to.be.equal(0);
+    expect(+await contract.methods.balanceOf(receiver).call()).to.be.equal(200);
+
+    await contract.methods.repartition(150).send({from: receiver});
+    await expect(contract.methods.transfer(owner, 160).send({from: receiver})).to.eventually.be.rejected;
+    expect(+await contract.methods.balanceOf(receiver).call()).to.be.equal(150);
+  });
 });
 
 describe('Refungible: Fees', () => {
modifiedtests/src/eth/reFungibleTokenAbi.jsondiffbeforeafterboth
before · tests/src/eth/reFungibleTokenAbi.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      { "internalType": "address", "name": "spender", "type": "address" },65      { "internalType": "uint256", "name": "amount", "type": "uint256" }66    ],67    "name": "approve",68    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],69    "stateMutability": "nonpayable",70    "type": "function"71  },72  {73    "inputs": [74      { "internalType": "address", "name": "owner", "type": "address" }75    ],76    "name": "balanceOf",77    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],78    "stateMutability": "view",79    "type": "function"80  },81  {82    "inputs": [83      { "internalType": "address", "name": "from", "type": "address" },84      { "internalType": "uint256", "name": "amount", "type": "uint256" }85    ],86    "name": "burnFrom",87    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],88    "stateMutability": "nonpayable",89    "type": "function"90  },91  {92    "inputs": [],93    "name": "decimals",94    "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }],95    "stateMutability": "view",96    "type": "function"97  },98  {99    "inputs": [],100    "name": "name",101    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],102    "stateMutability": "view",103    "type": "function"104  },105  {106    "inputs": [107      { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }108    ],109    "name": "supportsInterface",110    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],111    "stateMutability": "view",112    "type": "function"113  },114  {115    "inputs": [],116    "name": "symbol",117    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],118    "stateMutability": "view",119    "type": "function"120  },121  {122    "inputs": [],123    "name": "totalSupply",124    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],125    "stateMutability": "view",126    "type": "function"127  },128  {129    "inputs": [130      { "internalType": "address", "name": "to", "type": "address" },131      { "internalType": "uint256", "name": "amount", "type": "uint256" }132    ],133    "name": "transfer",134    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],135    "stateMutability": "nonpayable",136    "type": "function"137  },138  {139    "inputs": [140      { "internalType": "address", "name": "from", "type": "address" },141      { "internalType": "address", "name": "to", "type": "address" },142      { "internalType": "uint256", "name": "amount", "type": "uint256" }143    ],144    "name": "transferFrom",145    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],146    "stateMutability": "nonpayable",147    "type": "function"148  }149]
after · tests/src/eth/reFungibleTokenAbi.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      { "internalType": "address", "name": "spender", "type": "address" },65      { "internalType": "uint256", "name": "amount", "type": "uint256" }66    ],67    "name": "approve",68    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],69    "stateMutability": "nonpayable",70    "type": "function"71  },72  {73    "inputs": [74      { "internalType": "address", "name": "owner", "type": "address" }75    ],76    "name": "balanceOf",77    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],78    "stateMutability": "view",79    "type": "function"80  },81  {82    "inputs": [83      { "internalType": "address", "name": "from", "type": "address" },84      { "internalType": "uint256", "name": "amount", "type": "uint256" }85    ],86    "name": "burnFrom",87    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],88    "stateMutability": "nonpayable",89    "type": "function"90  },91  {92    "inputs": [],93    "name": "decimals",94    "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }],95    "stateMutability": "view",96    "type": "function"97  },98  {99    "inputs": [],100    "name": "name",101    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],102    "stateMutability": "view",103    "type": "function"104  },105  {106    "inputs": [107      { "internalType": "uint256", "name": "amount", "type": "uint256" }108    ],109    "name": "repartition",110    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],111    "stateMutability": "nonpayable",112    "type": "function"113  },114  {115    "inputs": [116      { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }117    ],118    "name": "supportsInterface",119    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],120    "stateMutability": "view",121    "type": "function"122  },123  {124    "inputs": [],125    "name": "symbol",126    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],127    "stateMutability": "view",128    "type": "function"129  },130  {131    "inputs": [],132    "name": "totalSupply",133    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],134    "stateMutability": "view",135    "type": "function"136  },137  {138    "inputs": [139      { "internalType": "address", "name": "to", "type": "address" },140      { "internalType": "uint256", "name": "amount", "type": "uint256" }141    ],142    "name": "transfer",143    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],144    "stateMutability": "nonpayable",145    "type": "function"146  },147  {148    "inputs": [149      { "internalType": "address", "name": "from", "type": "address" },150      { "internalType": "address", "name": "to", "type": "address" },151      { "internalType": "uint256", "name": "amount", "type": "uint256" }152    ],153    "name": "transferFrom",154    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],155    "stateMutability": "nonpayable",156    "type": "function"157  }158]