difftreelog
feat impl transfer, transer_from, transfer_cross, transfer_from_cross,
in: master
6 files changed
pallets/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]> {}
pallets/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>;
pallets/balances-adapter/src/stubs/UniqueNativeFungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/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 {}
tests/src/eth/abi/nativeFungible.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 { "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]tests/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 {}