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

difftreelog

feat impl transfer, transer_from, transfer_cross, transfer_from_cross,

Trubnikov Sergey2023-04-21parent: #1e5b247.patch.diff
in: master

6 files changed

modifiedpallets/balances-adapter/src/erc.rsdiffbeforeafterboth
--- a/pallets/balances-adapter/src/erc.rs
+++ b/pallets/balances-adapter/src/erc.rs
@@ -1,7 +1,10 @@
 use crate::Config;
 use evm_coder::{abi::AbiType, AbiCoder, ToLog, generate_stubgen, solidity_interface, types::*};
-use frame_support::traits::Currency;
-use pallet_common::erc::{CommonEvmHandler, CrossAccountId, PrecompileHandle, PrecompileResult};
+use frame_support::traits::{Currency, ExistenceRequirement};
+use pallet_common::{
+	erc::{CommonEvmHandler, CrossAccountId, PrecompileHandle, PrecompileResult},
+	eth::CrossAddress,
+};
 use pallet_evm_coder_substrate::{
 	call, dispatch_to_evm,
 	execution::{PreDispatch, Result},
@@ -82,16 +85,22 @@
 
 	// #[weight(<SelfWeightOf<T>>::transfer())]
 	fn transfer(&mut self, caller: Caller, to: Address, amount: U256) -> Result<bool> {
-		// let caller = T::CrossAccountId::from_eth(caller);
-		// let to = T::CrossAccountId::from_eth(to);
-		// let amount = amount.try_into().map_err(|_| "amount overflow")?;
+		let caller = T::CrossAccountId::from_eth(caller);
+		let to = T::CrossAccountId::from_eth(to);
+		let amount = amount.try_into().map_err(|_| "amount overflow")?;
 		// let budget = self
 		// 	.recorder
 		// 	.weight_calls_budget(<StructureWeight<T>>::find_parent());
 
 		// <Pallet<T>>::transfer(self, &caller, &to, amount, &budget).map_err(|_| "transfer error")?;
-		// Ok(true)
-		todo!()
+		<T as Config>::Currency::transfer(
+			caller.as_sub(),
+			to.as_sub(),
+			amount,
+			ExistenceRequirement::KeepAlive,
+		)
+		.map_err(dispatch_to_evm::<T>);
+		Ok(true)
 	}
 
 	// #[weight(<SelfWeightOf<T>>::transfer_from())]
@@ -102,24 +111,93 @@
 		to: Address,
 		amount: U256,
 	) -> Result<bool> {
-		// let caller = T::CrossAccountId::from_eth(caller);
-		// let from = T::CrossAccountId::from_eth(from);
-		// let to = T::CrossAccountId::from_eth(to);
-		// let amount = amount.try_into().map_err(|_| "amount overflow")?;
+		let caller = T::CrossAccountId::from_eth(caller);
+		let from = T::CrossAccountId::from_eth(from);
+		let to = T::CrossAccountId::from_eth(to);
+		let amount = amount.try_into().map_err(|_| "amount overflow")?;
+
+		if (from != to) {
+			return Err("no permission".into());
+		}
+		// let budget = self
+		// 	.recorder
+		// 	.weight_calls_budget(<StructureWeight<T>>::find_parent());
+
+		// <Pallet<T>>::transfer_from(self, &caller, &from, &to, amount, &budget)
+		// 	.map_err(dispatch_to_evm::<T>)?;
+		<T as Config>::Currency::transfer(
+			caller.as_sub(),
+			to.as_sub(),
+			amount,
+			ExistenceRequirement::KeepAlive,
+		)
+		.map_err(dispatch_to_evm::<T>);
+		Ok(true)
+	}
+}
+
+#[solidity_interface(name = ERC20UniqueExtensions, enum(derive(PreDispatch)), enum_attr(weight))]
+impl<T: Config> NativeFungibleHandle<T>
+where
+	T::AccountId: From<[u8; 32]>,
+{
+	// #[weight(<SelfWeightOf<T>>::transfer())]
+	fn transfer_cross(&mut self, caller: Caller, to: CrossAddress, amount: U256) -> Result<bool> {
+		let caller = T::CrossAccountId::from_eth(caller);
+		let to = to.into_sub_cross_account::<T>()?;
+		let amount = amount.try_into().map_err(|_| "amount overflow")?;
+		// let budget = self
+		// 	.recorder
+		// 	.weight_calls_budget(<StructureWeight<T>>::find_parent());
+
+		// <Pallet<T>>::transfer(self, &caller, &to, amount, &budget).map_err(|_| "transfer error")?;
+		<T as Config>::Currency::transfer(
+			caller.as_sub(),
+			to.as_sub(),
+			amount,
+			ExistenceRequirement::KeepAlive,
+		)
+		.map_err(dispatch_to_evm::<T>);
+		Ok(true)
+	}
+
+	// #[weight(<SelfWeightOf<T>>::transfer_from())]
+	fn transfer_from_cross(
+		&mut self,
+		caller: Caller,
+		from: CrossAddress,
+		to: CrossAddress,
+		amount: U256,
+	) -> Result<bool> {
+		let caller = T::CrossAccountId::from_eth(caller);
+		let from = from.into_sub_cross_account::<T>()?;
+		let to = to.into_sub_cross_account::<T>()?;
+		let amount = amount.try_into().map_err(|_| "amount overflow")?;
+
+		if (from != to) {
+			return Err("no permission".into());
+		}
+
 		// let budget = self
 		// 	.recorder
 		// 	.weight_calls_budget(<StructureWeight<T>>::find_parent());
 
 		// <Pallet<T>>::transfer_from(self, &caller, &from, &to, amount, &budget)
 		// 	.map_err(dispatch_to_evm::<T>)?;
-		// Ok(true)
-		todo!()
+		<T as Config>::Currency::transfer(
+			caller.as_sub(),
+			to.as_sub(),
+			amount,
+			ExistenceRequirement::KeepAlive,
+		)
+		.map_err(dispatch_to_evm::<T>);
+		Ok(true)
 	}
 }
 
 #[solidity_interface(
 	name = UniqueNativeFungible,
-	is(ERC20),
+	is(ERC20, ERC20UniqueExtensions),
 	enum(derive(PreDispatch))
 )]
 impl<T: Config> NativeFungibleHandle<T> where T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]> {}
modifiedpallets/balances-adapter/src/lib.rsdiffbeforeafterboth
--- a/pallets/balances-adapter/src/lib.rs
+++ b/pallets/balances-adapter/src/lib.rs
@@ -17,7 +17,7 @@
 			Self::AccountId,
 			Balance = Self::CurrencyBalance,
 		>;
-		type CurrencyBalance: Into<U256>;
+		type CurrencyBalance: Into<U256> + TryFrom<U256>;
 
 		type Decimals: Get<u8>;
 		type Name: Get<String>;
modifiedpallets/balances-adapter/src/stubs/UniqueNativeFungible.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/balances-adapter/src/stubs/UniqueNativeFungible.soldiffbeforeafterboth
--- a/pallets/balances-adapter/src/stubs/UniqueNativeFungible.sol
+++ b/pallets/balances-adapter/src/stubs/UniqueNativeFungible.sol
@@ -17,6 +17,40 @@
 	}
 }
 
+/// @dev the ERC-165 identifier for this interface is 0xff15c6f4
+contract ERC20UniqueExtensions is Dummy, ERC165 {
+	/// @dev EVM selector for this function is: 0x2ada85ff,
+	///  or in textual repr: transferCross((address,uint256),uint256)
+	function transferCross(CrossAddress memory to, uint256 amount) public returns (bool) {
+		require(false, stub_error);
+		to;
+		amount;
+		dummy = 0;
+		return false;
+	}
+
+	/// @dev EVM selector for this function is: 0xd5cf430b,
+	///  or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)
+	function transferFromCross(
+		CrossAddress memory from,
+		CrossAddress memory to,
+		uint256 amount
+	) public returns (bool) {
+		require(false, stub_error);
+		from;
+		to;
+		amount;
+		dummy = 0;
+		return false;
+	}
+}
+
+/// Cross account struct
+struct CrossAddress {
+	address eth;
+	uint256 sub;
+}
+
 /// @dev inlined interface
 contract ERC20Events {
 	event Transfer(address indexed from, address indexed to, uint256 value);
@@ -25,26 +59,31 @@
 
 /// @dev the ERC-165 identifier for this interface is 0x942e8b22
 contract ERC20 is Dummy, ERC165, ERC20Events {
-	/// @dev EVM selector for this function is: 0x06fdde03,
-	///  or in textual repr: name()
-	function name() public view returns (string memory) {
+	/// @dev EVM selector for this function is: 0xdd62ed3e,
+	///  or in textual repr: allowance(address,address)
+	function allowance(address owner, address spender) public view returns (uint256) {
 		require(false, stub_error);
+		owner;
+		spender;
 		dummy;
-		return "";
+		return 0;
 	}
 
-	/// @dev EVM selector for this function is: 0x95d89b41,
-	///  or in textual repr: symbol()
-	function symbol() public view returns (string memory) {
+	/// @dev EVM selector for this function is: 0x095ea7b3,
+	///  or in textual repr: approve(address,uint256)
+	function approve(address spender, uint256 amount) public returns (bool) {
 		require(false, stub_error);
-		dummy;
-		return "";
+		spender;
+		amount;
+		dummy = 0;
+		return false;
 	}
 
-	/// @dev EVM selector for this function is: 0x18160ddd,
-	///  or in textual repr: totalSupply()
-	function totalSupply() public view returns (uint256) {
+	/// @dev EVM selector for this function is: 0x70a08231,
+	///  or in textual repr: balanceOf(address)
+	function balanceOf(address owner) public view returns (uint256) {
 		require(false, stub_error);
+		owner;
 		dummy;
 		return 0;
 	}
@@ -57,11 +96,26 @@
 		return 0;
 	}
 
-	/// @dev EVM selector for this function is: 0x70a08231,
-	///  or in textual repr: balanceOf(address)
-	function balanceOf(address owner) public view returns (uint256) {
+	/// @dev EVM selector for this function is: 0x06fdde03,
+	///  or in textual repr: name()
+	function name() public view returns (string memory) {
+		require(false, stub_error);
+		dummy;
+		return "";
+	}
+
+	/// @dev EVM selector for this function is: 0x95d89b41,
+	///  or in textual repr: symbol()
+	function symbol() public view returns (string memory) {
+		require(false, stub_error);
+		dummy;
+		return "";
+	}
+
+	/// @dev EVM selector for this function is: 0x18160ddd,
+	///  or in textual repr: totalSupply()
+	function totalSupply() public view returns (uint256) {
 		require(false, stub_error);
-		owner;
 		dummy;
 		return 0;
 	}
@@ -90,26 +144,6 @@
 		dummy = 0;
 		return false;
 	}
-
-	/// @dev EVM selector for this function is: 0x095ea7b3,
-	///  or in textual repr: approve(address,uint256)
-	function approve(address spender, uint256 amount) public returns (bool) {
-		require(false, stub_error);
-		spender;
-		amount;
-		dummy = 0;
-		return false;
-	}
-
-	/// @dev EVM selector for this function is: 0xdd62ed3e,
-	///  or in textual repr: allowance(address,address)
-	function allowance(address owner, address spender) public view returns (uint256) {
-		require(false, stub_error);
-		owner;
-		spender;
-		dummy;
-		return 0;
-	}
 }
 
-contract UniqueNativeFungible is Dummy, ERC165, ERC20 {}
+contract UniqueNativeFungible is Dummy, ERC165, ERC20, ERC20UniqueExtensions {}
modifiedtests/src/eth/abi/nativeFungible.jsondiffbeforeafterboth
before · tests/src/eth/abi/nativeFungible.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    "name": "decimals",84    "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }],85    "stateMutability": "view",86    "type": "function"87  },88  {89    "inputs": [],90    "name": "name",91    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],92    "stateMutability": "view",93    "type": "function"94  },95  {96    "inputs": [97      { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }98    ],99    "name": "supportsInterface",100    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],101    "stateMutability": "view",102    "type": "function"103  },104  {105    "inputs": [],106    "name": "symbol",107    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],108    "stateMutability": "view",109    "type": "function"110  },111  {112    "inputs": [],113    "name": "totalSupply",114    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],115    "stateMutability": "view",116    "type": "function"117  },118  {119    "inputs": [120      { "internalType": "address", "name": "to", "type": "address" },121      { "internalType": "uint256", "name": "amount", "type": "uint256" }122    ],123    "name": "transfer",124    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],125    "stateMutability": "nonpayable",126    "type": "function"127  },128  {129    "inputs": [130      { "internalType": "address", "name": "from", "type": "address" },131      { "internalType": "address", "name": "to", "type": "address" },132      { "internalType": "uint256", "name": "amount", "type": "uint256" }133    ],134    "name": "transferFrom",135    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],136    "stateMutability": "nonpayable",137    "type": "function"138  }139]
after · tests/src/eth/abi/nativeFungible.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    "name": "decimals",84    "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }],85    "stateMutability": "view",86    "type": "function"87  },88  {89    "inputs": [],90    "name": "name",91    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],92    "stateMutability": "view",93    "type": "function"94  },95  {96    "inputs": [97      { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }98    ],99    "name": "supportsInterface",100    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],101    "stateMutability": "view",102    "type": "function"103  },104  {105    "inputs": [],106    "name": "symbol",107    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],108    "stateMutability": "view",109    "type": "function"110  },111  {112    "inputs": [],113    "name": "totalSupply",114    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],115    "stateMutability": "view",116    "type": "function"117  },118  {119    "inputs": [120      { "internalType": "address", "name": "to", "type": "address" },121      { "internalType": "uint256", "name": "amount", "type": "uint256" }122    ],123    "name": "transfer",124    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],125    "stateMutability": "nonpayable",126    "type": "function"127  },128  {129    "inputs": [130      {131        "components": [132          { "internalType": "address", "name": "eth", "type": "address" },133          { "internalType": "uint256", "name": "sub", "type": "uint256" }134        ],135        "internalType": "struct CrossAddress",136        "name": "to",137        "type": "tuple"138      },139      { "internalType": "uint256", "name": "amount", "type": "uint256" }140    ],141    "name": "transferCross",142    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],143    "stateMutability": "nonpayable",144    "type": "function"145  },146  {147    "inputs": [148      { "internalType": "address", "name": "from", "type": "address" },149      { "internalType": "address", "name": "to", "type": "address" },150      { "internalType": "uint256", "name": "amount", "type": "uint256" }151    ],152    "name": "transferFrom",153    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],154    "stateMutability": "nonpayable",155    "type": "function"156  },157  {158    "inputs": [159      {160        "components": [161          { "internalType": "address", "name": "eth", "type": "address" },162          { "internalType": "uint256", "name": "sub", "type": "uint256" }163        ],164        "internalType": "struct CrossAddress",165        "name": "from",166        "type": "tuple"167      },168      {169        "components": [170          { "internalType": "address", "name": "eth", "type": "address" },171          { "internalType": "uint256", "name": "sub", "type": "uint256" }172        ],173        "internalType": "struct CrossAddress",174        "name": "to",175        "type": "tuple"176      },177      { "internalType": "uint256", "name": "amount", "type": "uint256" }178    ],179    "name": "transferFromCross",180    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],181    "stateMutability": "nonpayable",182    "type": "function"183  }184]
modifiedtests/src/eth/api/UniqueNativeFungible.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueNativeFungible.sol
+++ b/tests/src/eth/api/UniqueNativeFungible.sol
@@ -12,6 +12,27 @@
 	function supportsInterface(bytes4 interfaceID) external view returns (bool);
 }
 
+/// @dev the ERC-165 identifier for this interface is 0xff15c6f4
+interface ERC20UniqueExtensions is Dummy, ERC165 {
+	/// @dev EVM selector for this function is: 0x2ada85ff,
+	///  or in textual repr: transferCross((address,uint256),uint256)
+	function transferCross(CrossAddress memory to, uint256 amount) external returns (bool);
+
+	/// @dev EVM selector for this function is: 0xd5cf430b,
+	///  or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)
+	function transferFromCross(
+		CrossAddress memory from,
+		CrossAddress memory to,
+		uint256 amount
+	) external returns (bool);
+}
+
+/// Cross account struct
+struct CrossAddress {
+	address eth;
+	uint256 sub;
+}
+
 /// @dev inlined interface
 interface ERC20Events {
 	event Transfer(address indexed from, address indexed to, uint256 value);
@@ -20,6 +41,22 @@
 
 /// @dev the ERC-165 identifier for this interface is 0x942e8b22
 interface ERC20 is Dummy, ERC165, ERC20Events {
+	/// @dev EVM selector for this function is: 0xdd62ed3e,
+	///  or in textual repr: allowance(address,address)
+	function allowance(address owner, address spender) external view returns (uint256);
+
+	/// @dev EVM selector for this function is: 0x095ea7b3,
+	///  or in textual repr: approve(address,uint256)
+	function approve(address spender, uint256 amount) external returns (bool);
+
+	/// @dev EVM selector for this function is: 0x70a08231,
+	///  or in textual repr: balanceOf(address)
+	function balanceOf(address owner) external view returns (uint256);
+
+	/// @dev EVM selector for this function is: 0x313ce567,
+	///  or in textual repr: decimals()
+	function decimals() external view returns (uint8);
+
 	/// @dev EVM selector for this function is: 0x06fdde03,
 	///  or in textual repr: name()
 	function name() external view returns (string memory);
@@ -32,14 +69,6 @@
 	///  or in textual repr: totalSupply()
 	function totalSupply() external view returns (uint256);
 
-	/// @dev EVM selector for this function is: 0x313ce567,
-	///  or in textual repr: decimals()
-	function decimals() external view returns (uint8);
-
-	/// @dev EVM selector for this function is: 0x70a08231,
-	///  or in textual repr: balanceOf(address)
-	function balanceOf(address owner) external view returns (uint256);
-
 	/// @dev EVM selector for this function is: 0xa9059cbb,
 	///  or in textual repr: transfer(address,uint256)
 	function transfer(address to, uint256 amount) external returns (bool);
@@ -51,14 +80,6 @@
 		address to,
 		uint256 amount
 	) external returns (bool);
-
-	/// @dev EVM selector for this function is: 0x095ea7b3,
-	///  or in textual repr: approve(address,uint256)
-	function approve(address spender, uint256 amount) external returns (bool);
-
-	/// @dev EVM selector for this function is: 0xdd62ed3e,
-	///  or in textual repr: allowance(address,address)
-	function allowance(address owner, address spender) external view returns (uint256);
 }
 
-interface UniqueNativeFungible is Dummy, ERC165, ERC20 {}
+interface UniqueNativeFungible is Dummy, ERC165, ERC20, ERC20UniqueExtensions {}