difftreelog
refactor rewrite nft pallet to evm helpers
in: master
7 files changed
pallets/nft/Cargo.tomldiffbeforeafterboth--- a/pallets/nft/Cargo.toml
+++ b/pallets/nft/Cargo.toml
@@ -39,7 +39,7 @@
'primitive-types/std',
'evm-coder/std',
- 'evm-coder-substrate/std',
+ 'pallet-evm-coder-substrate/std',
]
################################################################################
@@ -144,10 +144,12 @@
sp-api = { default-features = false, version = '3.0.0', git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.8" }
evm-coder = { default-features = false, path = "../../crates/evm-coder" }
-evm-coder-substrate = { default-features = false, path = "../../crates/evm-coder-substrate" }
-primitive-types = { version = "0.9.0", default-features = false, features = ["serde_no_std"] }
+pallet-evm-coder-substrate = { default-features = false, path = "../../pallets/evm-coder-substrate" }
+primitive-types = { version = "0.9.0", default-features = false, features = [
+ "serde_no_std",
+] }
pallet-evm = { default-features = false, version = "5.0.0-dev", git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
pallet-ethereum = { default-features = false, version = "3.0.0-dev", git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
fp-evm = { default-features = false, version = '2.0.0', git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
-hex-literal = "0.3.1"
\ No newline at end of file
+hex-literal = "0.3.1"
pallets/nft/src/eth/erc.rsdiffbeforeafterboth--- a/pallets/nft/src/eth/erc.rs
+++ b/pallets/nft/src/eth/erc.rs
@@ -1,46 +1,63 @@
-use evm_coder::{solidity_interface, solidity, types::*, ToLog};
+use core::char::{decode_utf16, REPLACEMENT_CHARACTER};
+use evm_coder::{ToLog, execution::Result, solidity, solidity_interface, types::*};
+use core::convert::TryInto;
+use alloc::format;
+use crate::{Allowances, Module, Balance, CollectionHandle, CollectionMode, Config, NftItemList};
+use frame_support::storage::StorageDoubleMap;
+use pallet_evm::AddressMapping;
+use super::account::CrossAccountId;
use sp_std::vec::Vec;
-#[solidity_interface]
-pub trait InlineNameSymbol {
- type Error;
-
- fn name(&self) -> Result<string, Self::Error>;
- fn symbol(&self) -> Result<string, Self::Error>;
+#[solidity_interface(name = "ERC165")]
+impl<T: Config> CollectionHandle<T> {
+ fn supports_interface(&self, interface_id: bytes4) -> Result<bool> {
+ Ok(match self.mode {
+ CollectionMode::Fungible(_) => UniqueFungibleCall::supports_interface(interface_id),
+ CollectionMode::NFT => UniqueNFTCall::supports_interface(interface_id),
+ _ => false,
+ })
+ }
}
-#[solidity_interface]
-pub trait InlineTotalSupply {
- type Error;
+#[solidity_interface(name = "InlineNameSymbol")]
+impl<T: Config> CollectionHandle<T> {
+ fn name(&self) -> Result<string> {
+ Ok(decode_utf16(self.name.iter().copied())
+ .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
+ .collect::<string>())
+ }
- fn total_supply(&self) -> Result<uint256, Self::Error>;
+ fn symbol(&self) -> Result<string> {
+ Ok(string::from_utf8_lossy(&self.token_prefix).into())
+ }
}
-#[solidity_interface]
-pub trait ERC165 {
- type Error;
-
- fn supports_interface(&self, interface_id: bytes4) -> Result<bool, Self::Error>;
+#[solidity_interface(name = "InlineTotalSupply")]
+impl<T: Config> CollectionHandle<T> {
+ fn total_supply(&self) -> Result<uint256> {
+ // TODO: we do not track total amount of all tokens
+ Ok(0.into())
+ }
}
-#[solidity_interface(inline_is(InlineNameSymbol))]
-pub trait ERC721Metadata {
- type Error;
-
- #[solidity(rename_selector = "tokenURI")]
- fn token_uri(&self, token_id: uint256) -> Result<string, Self::Error>;
+#[solidity_interface(name = "ERC721Metadata", inline_is(InlineNameSymbol))]
+impl<T: Config> CollectionHandle<T> {
+ fn token_uri(&self, token_id: uint256) -> Result<string> {
+ // TODO: We should standartize url prefix, maybe via offchain schema?
+ Ok(format!("unique.network/{}/{}", self.id, token_id))
+ }
}
-#[solidity_interface(inline_is(InlineTotalSupply))]
-pub trait ERC721Enumerable {
- type Error;
+#[solidity_interface(name = "ERC721Enumerable", inline_is(InlineTotalSupply))]
+impl<T: Config> CollectionHandle<T> {
+ fn token_by_index(&self, index: uint256) -> Result<uint256> {
+ Ok(index)
+ }
- fn token_by_index(&self, index: uint256) -> Result<uint256, Self::Error>;
- fn token_of_owner_by_index(
- &self,
- owner: address,
- index: uint256,
- ) -> Result<uint256, Self::Error>;
+ fn token_of_owner_by_index(&self, _owner: address, _index: uint256) -> Result<uint256> {
+ // TODO: Not implemetable
+ Err("not implemented".into())
+ }
}
#[derive(ToLog)]
@@ -71,29 +88,40 @@
},
}
-#[solidity_interface(is(ERC165), events(ERC721Events))]
-pub trait ERC721 {
- type Error;
-
- fn balance_of(&self, owner: address) -> Result<uint256, Self::Error>;
- fn owner_of(&self, token_id: uint256) -> Result<address, Self::Error>;
-
- #[solidity(rename_selector = "safeTransferFrom")]
+#[solidity_interface(name = "ERC721", is(ERC165), events(ERC721Events))]
+impl<T: Config> CollectionHandle<T> {
+ #[solidity(rename_selector = "balanceOf")]
+ fn balance_of_nft(&self, owner: address) -> Result<uint256> {
+ let owner = T::EvmAddressMapping::into_account_id(owner);
+ let balance = <Balance<T>>::get(self.id, owner);
+ Ok(balance.into())
+ }
+ fn owner_of(&self, token_id: uint256) -> Result<address> {
+ let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
+ let token = <NftItemList<T>>::get(self.id, token_id).ok_or("unknown token")?;
+ Ok(*token.owner.as_eth())
+ }
fn safe_transfer_from_with_data(
&mut self,
- from: address,
- to: address,
- token_id: uint256,
- data: bytes,
- value: value,
- ) -> Result<void, Self::Error>;
+ _from: address,
+ _to: address,
+ _token_id: uint256,
+ _data: bytes,
+ _value: value,
+ ) -> Result<void> {
+ // TODO: Not implemetable
+ Err("not implemented".into())
+ }
fn safe_transfer_from(
&mut self,
- from: address,
- to: address,
- token_id: uint256,
- value: value,
- ) -> Result<void, Self::Error>;
+ _from: address,
+ _to: address,
+ _token_id: uint256,
+ _value: value,
+ ) -> Result<void> {
+ // TODO: Not implemetable
+ Err("not implemented".into())
+ }
fn transfer_from(
&mut self,
@@ -101,53 +129,86 @@
from: address,
to: address,
token_id: uint256,
- value: value,
- ) -> Result<void, Self::Error>;
+ _value: value,
+ ) -> Result<void> {
+ let caller = T::CrossAccountId::from_eth(caller);
+ let from = T::CrossAccountId::from_eth(from);
+ let to = T::CrossAccountId::from_eth(to);
+ let token_id = token_id.try_into().map_err(|_| "token_id overflow")?;
+
+ <Module<T>>::transfer_from_internal(&caller, &from, &to, self, token_id, 1)
+ .map_err(|_| "transferFrom error")?;
+ Ok(())
+ }
+
fn approve(
&mut self,
caller: caller,
approved: address,
token_id: uint256,
- value: value,
- ) -> Result<void, Self::Error>;
+ _value: value,
+ ) -> Result<void> {
+ let caller = T::CrossAccountId::from_eth(caller);
+ let approved = T::CrossAccountId::from_eth(approved);
+ let token_id = token_id.try_into().map_err(|_| "token_id overflow")?;
+
+ <Module<T>>::approve_internal(&caller, &approved, self, token_id, 1)
+ .map_err(|_| "approve internal")?;
+ Ok(())
+ }
+
fn set_approval_for_all(
&mut self,
- caller: caller,
- operator: address,
- approved: bool,
- ) -> Result<void, Self::Error>;
+ _caller: caller,
+ _operator: address,
+ _approved: bool,
+ ) -> Result<void> {
+ // TODO: Not implemetable
+ Err("not implemented".into())
+ }
+
+ fn get_approved(&self, _token_id: uint256) -> Result<address> {
+ // TODO: Not implemetable
+ Err("not implemented".into())
+ }
- fn get_approved(&self, token_id: uint256) -> Result<address, Self::Error>;
- fn is_approved_for_all(
- &self,
- owner: address,
- operator: address,
- ) -> Result<address, Self::Error>;
+ fn is_approved_for_all(&self, _owner: address, _operator: address) -> Result<address> {
+ // TODO: Not implemetable
+ Err("not implemented".into())
+ }
}
-#[solidity_interface]
-pub trait ERC721UniqueExtensions {
- type Error;
-
- fn transfer(
+#[solidity_interface(name = "ERC721UniqueExtensions")]
+impl<T: Config> CollectionHandle<T> {
+ #[solidity(rename_selector = "transfer")]
+ fn transfer_nft(
&mut self,
caller: caller,
to: address,
token_id: uint256,
- value: value,
- ) -> Result<void, Self::Error>;
+ _value: value,
+ ) -> Result<void> {
+ let caller = T::CrossAccountId::from_eth(caller);
+ let to = T::CrossAccountId::from_eth(to);
+ let token_id = token_id.try_into().map_err(|_| "amount overflow")?;
+
+ <Module<T>>::transfer_internal(&caller, &to, self, token_id, 1)
+ .map_err(|_| "transfer error")?;
+ Ok(())
+ }
}
-#[solidity_interface(is(
- ERC165,
- ERC721,
- ERC721Metadata,
- ERC721Enumerable,
- ERC721UniqueExtensions
-))]
-pub trait UniqueNFT {
- type Error;
-}
+#[solidity_interface(
+ name = "UniqueNFT",
+ is(
+ ERC165,
+ ERC721,
+ ERC721Metadata,
+ ERC721Enumerable,
+ ERC721UniqueExtensions
+ )
+)]
+impl<T: Config> CollectionHandle<T> {}
#[derive(ToLog)]
pub enum ERC20Events {
@@ -167,35 +228,72 @@
},
}
-#[solidity_interface(inline_is(InlineNameSymbol, InlineTotalSupply), events(ERC20Events))]
-pub trait ERC20 {
- type Error;
+#[solidity_interface(
+ name = "ERC20",
+ inline_is(InlineNameSymbol, InlineTotalSupply),
+ events(ERC20Events)
+)]
+impl<T: Config> CollectionHandle<T> {
+ fn decimals(&self) -> Result<uint8> {
+ Ok(if let CollectionMode::Fungible(decimals) = &self.mode {
+ *decimals
+ } else {
+ unreachable!()
+ })
+ }
+ fn balance_of(&self, owner: address) -> Result<uint256> {
+ let owner = T::EvmAddressMapping::into_account_id(owner);
+ let balance = <Balance<T>>::get(self.id, owner);
+ Ok(balance.into())
+ }
+ fn transfer(&mut self, caller: caller, to: address, amount: uint256) -> 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")?;
- fn decimals(&self) -> Result<uint8, Self::Error>;
- fn balance_of(&self, owner: address) -> Result<uint256, Self::Error>;
- fn transfer(
- &mut self,
- caller: caller,
- to: address,
- value: uint256,
- ) -> Result<bool, Self::Error>;
- fn transfer_from(
+ <Module<T>>::transfer_internal(&caller, &to, self, 1, amount)
+ .map_err(|_| "transfer error")?;
+ Ok(true)
+ }
+ #[solidity(rename_selector = "transferFrom")]
+ fn transfer_from_fungible(
&mut self,
caller: caller,
from: address,
to: address,
- value: uint256,
- ) -> Result<bool, Self::Error>;
- fn approve(
+ amount: uint256,
+ ) -> 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")?;
+
+ <Module<T>>::transfer_from_internal(&caller, &from, &to, self, 1, amount)
+ .map_err(|_| "transferFrom error")?;
+ Ok(true)
+ }
+ #[solidity(rename_selector = "approve")]
+ fn approve_fungible(
&mut self,
caller: caller,
spender: address,
- value: uint256,
- ) -> Result<bool, Self::Error>;
- fn allowance(&self, owner: address, spender: address) -> Result<uint256, Self::Error>;
-}
+ amount: uint256,
+ ) -> Result<bool> {
+ let caller = T::CrossAccountId::from_eth(caller);
+ let spender = T::CrossAccountId::from_eth(spender);
+ let amount = amount.try_into().map_err(|_| "amount overflow")?;
+
+ <Module<T>>::approve_internal(&caller, &spender, self, 1, amount)
+ .map_err(|_| "approve internal")?;
+ Ok(true)
+ }
+ fn allowance(&self, owner: address, spender: address) -> Result<uint256> {
+ let owner = T::CrossAccountId::from_eth(owner);
+ let spender = T::CrossAccountId::from_eth(spender);
-#[solidity_interface(is(ERC165, ERC20))]
-pub trait UniqueFungible {
- type Error;
+ Ok(<Allowances<T>>::get(self.id, (1, owner.as_sub(), spender.as_sub())).into())
+ }
}
+
+#[solidity_interface(name = "UniqueFungible", is(ERC165, ERC20))]
+impl<T: Config> CollectionHandle<T> {}
pallets/nft/src/eth/erc_impl.rsdiffbeforeafterboth--- a/pallets/nft/src/eth/erc_impl.rs
+++ /dev/null
@@ -1,283 +0,0 @@
-use core::char::{decode_utf16, REPLACEMENT_CHARACTER};
-use evm_coder::{
- abi::{AbiWriter, StringError},
- types::*,
-};
-use core::convert::TryInto;
-use alloc::format;
-use crate::{Allowances, Module, Balance, CollectionHandle, CollectionMode, Config, NftItemList};
-use frame_support::storage::StorageDoubleMap;
-use pallet_evm::AddressMapping;
-use super::erc::*;
-use super::account::CrossAccountId;
-
-type Result<T> = core::result::Result<T, StringError>;
-
-impl<T: Config> InlineNameSymbol for CollectionHandle<T> {
- type Error = StringError;
-
- fn name(&self) -> Result<string> {
- Ok(decode_utf16(self.name.iter().copied())
- .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
- .collect::<string>())
- }
-
- fn symbol(&self) -> Result<string> {
- Ok(string::from_utf8_lossy(&self.token_prefix).into())
- }
-}
-
-impl<T: Config> InlineTotalSupply for CollectionHandle<T> {
- type Error = StringError;
-
- fn total_supply(&self) -> Result<uint256> {
- // TODO: we do not track total amount of all tokens
- Ok(0.into())
- }
-}
-
-impl<T: Config> ERC721Metadata for CollectionHandle<T> {
- type Error = StringError;
-
- fn token_uri(&self, token_id: uint256) -> Result<string> {
- // TODO: We should standartize url prefix, maybe via offchain schema?
- Ok(format!("unique.network/{}/{}", self.id, token_id))
- }
-
- fn call_inline_name_symbol(&mut self, c: Msg<InlineNameSymbolCall>) -> Result<AbiWriter> {
- <Self as InlineNameSymbol>::call(self, c)
- }
-}
-
-impl<T: Config> ERC721Enumerable for CollectionHandle<T> {
- type Error = StringError;
-
- fn token_by_index(&self, index: uint256) -> Result<uint256> {
- Ok(index)
- }
-
- fn token_of_owner_by_index(&self, _owner: address, _index: uint256) -> Result<uint256> {
- // TODO: Not implemetable
- Err("not implemented".into())
- }
-
- fn call_inline_total_supply(&mut self, c: Msg<InlineTotalSupplyCall>) -> Result<AbiWriter> {
- <Self as InlineTotalSupply>::call(self, c)
- }
-}
-
-impl<T: Config> ERC721 for CollectionHandle<T> {
- type Error = StringError;
-
- fn balance_of(&self, owner: address) -> Result<uint256> {
- let owner = T::EvmAddressMapping::into_account_id(owner);
- let balance = <Balance<T>>::get(self.id, owner);
- Ok(balance.into())
- }
- fn owner_of(&self, token_id: uint256) -> Result<address> {
- let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
- let token = <NftItemList<T>>::get(self.id, token_id).ok_or("unknown token")?;
- Ok(*token.owner.as_eth())
- }
- fn safe_transfer_from_with_data(
- &mut self,
- _from: address,
- _to: address,
- _token_id: uint256,
- _data: bytes,
- _value: value,
- ) -> Result<void> {
- // TODO: Not implemetable
- Err("not implemented".into())
- }
- fn safe_transfer_from(
- &mut self,
- _from: address,
- _to: address,
- _token_id: uint256,
- _value: value,
- ) -> Result<void> {
- // TODO: Not implemetable
- Err("not implemented".into())
- }
-
- fn transfer_from(
- &mut self,
- caller: caller,
- from: address,
- to: address,
- token_id: uint256,
- _value: value,
- ) -> Result<void> {
- let caller = T::CrossAccountId::from_eth(caller);
- let from = T::CrossAccountId::from_eth(from);
- let to = T::CrossAccountId::from_eth(to);
- let token_id = token_id.try_into().map_err(|_| "token_id overflow")?;
-
- <Module<T>>::transfer_from_internal(&caller, &from, &to, self, token_id, 1)
- .map_err(|_| "transferFrom error")?;
- Ok(())
- }
-
- fn approve(
- &mut self,
- caller: caller,
- approved: address,
- token_id: uint256,
- _value: value,
- ) -> Result<void> {
- let caller = T::CrossAccountId::from_eth(caller);
- let approved = T::CrossAccountId::from_eth(approved);
- let token_id = token_id.try_into().map_err(|_| "token_id overflow")?;
-
- <Module<T>>::approve_internal(&caller, &approved, self, token_id, 1)
- .map_err(|_| "approve internal")?;
- Ok(())
- }
-
- fn set_approval_for_all(
- &mut self,
- _caller: caller,
- _operator: address,
- _approved: bool,
- ) -> Result<void> {
- // TODO: Not implemetable
- Err("not implemented".into())
- }
-
- fn get_approved(&self, _token_id: uint256) -> Result<address> {
- // TODO: Not implemetable
- Err("not implemented".into())
- }
-
- fn is_approved_for_all(&self, _owner: address, _operator: address) -> Result<address> {
- // TODO: Not implemetable
- Err("not implemented".into())
- }
-
- fn call_erc165(&mut self, c: Msg<ERC165Call>) -> Result<AbiWriter> {
- let ERC165Call::SupportsInterface { interface_id } = c.call;
- Ok(evm_coder::abi_encode!(bool(
- &ERC721Call::supports_interface(interface_id)
- )))
- }
-}
-
-impl<T: Config> ERC721UniqueExtensions for CollectionHandle<T> {
- type Error = StringError;
- fn transfer(
- &mut self,
- caller: caller,
- to: address,
- token_id: uint256,
- _value: value,
- ) -> Result<void> {
- let caller = T::CrossAccountId::from_eth(caller);
- let to = T::CrossAccountId::from_eth(to);
- let token_id = token_id.try_into().map_err(|_| "amount overflow")?;
-
- <Module<T>>::transfer_internal(&caller, &to, self, token_id, 1)
- .map_err(|_| "transfer error")?;
- Ok(())
- }
-}
-
-impl<T: Config> UniqueNFT for CollectionHandle<T> {
- type Error = StringError;
- fn call_erc165(&mut self, c: Msg<ERC165Call>) -> Result<AbiWriter> {
- let ERC165Call::SupportsInterface { interface_id } = c.call;
- Ok(evm_coder::abi_encode!(bool(
- &UniqueNFTCall::supports_interface(interface_id)
- )))
- }
- fn call_erc721(&mut self, c: Msg<ERC721Call>) -> Result<AbiWriter> {
- <Self as ERC721>::call(self, c)
- }
- fn call_erc721_metadata(&mut self, c: Msg<ERC721MetadataCall>) -> Result<AbiWriter> {
- <Self as ERC721Metadata>::call(self, c)
- }
- fn call_erc721_enumerable(&mut self, c: Msg<ERC721EnumerableCall>) -> Result<AbiWriter> {
- <Self as ERC721Enumerable>::call(self, c)
- }
- fn call_erc721_unique_extensions(
- &mut self,
- c: Msg<ERC721UniqueExtensionsCall>,
- ) -> Result<AbiWriter> {
- <Self as ERC721UniqueExtensions>::call(self, c)
- }
-}
-
-impl<T: Config> ERC20 for CollectionHandle<T> {
- type Error = StringError;
- fn decimals(&self) -> Result<uint8> {
- Ok(if let CollectionMode::Fungible(decimals) = &self.mode {
- *decimals
- } else {
- unreachable!()
- })
- }
- fn balance_of(&self, owner: address) -> Result<uint256> {
- let owner = T::EvmAddressMapping::into_account_id(owner);
- let balance = <Balance<T>>::get(self.id, owner);
- Ok(balance.into())
- }
- fn transfer(&mut self, caller: caller, to: address, amount: uint256) -> 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")?;
-
- <Module<T>>::transfer_internal(&caller, &to, self, 1, amount)
- .map_err(|_| "transfer error")?;
- Ok(true)
- }
- fn transfer_from(
- &mut self,
- caller: caller,
- from: address,
- to: address,
- amount: uint256,
- ) -> 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")?;
-
- <Module<T>>::transfer_from_internal(&caller, &from, &to, self, 1, amount)
- .map_err(|_| "transferFrom error")?;
- Ok(true)
- }
- fn approve(&mut self, caller: caller, spender: address, amount: uint256) -> Result<bool> {
- let caller = T::CrossAccountId::from_eth(caller);
- let spender = T::CrossAccountId::from_eth(spender);
- let amount = amount.try_into().map_err(|_| "amount overflow")?;
-
- <Module<T>>::approve_internal(&caller, &spender, self, 1, amount)
- .map_err(|_| "approve internal")?;
- Ok(true)
- }
- fn allowance(&self, owner: address, spender: address) -> Result<uint256> {
- let owner = T::CrossAccountId::from_eth(owner);
- let spender = T::CrossAccountId::from_eth(spender);
-
- Ok(<Allowances<T>>::get(self.id, (1, owner.as_sub(), spender.as_sub())).into())
- }
- fn call_inline_name_symbol(&mut self, c: Msg<InlineNameSymbolCall>) -> Result<AbiWriter> {
- <Self as InlineNameSymbol>::call(self, c)
- }
- fn call_inline_total_supply(&mut self, c: Msg<InlineTotalSupplyCall>) -> Result<AbiWriter> {
- <Self as InlineTotalSupply>::call(self, c)
- }
-}
-
-impl<T: Config> UniqueFungible for CollectionHandle<T> {
- type Error = StringError;
- fn call_erc165(&mut self, c: Msg<ERC165Call>) -> Result<AbiWriter> {
- let ERC165Call::SupportsInterface { interface_id } = c.call;
- Ok(evm_coder::abi_encode!(bool(
- &UniqueNFTCall::supports_interface(interface_id)
- )))
- }
- fn call_erc20(&mut self, c: Msg<ERC20Call>) -> Result<AbiWriter> {
- <Self as ERC20>::call(self, c)
- }
-}
pallets/nft/src/eth/log.rsdiffbeforeafterboth--- a/pallets/nft/src/eth/log.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-use sp_std::cell::RefCell;
-use sp_std::vec::Vec;
-
-use ethereum::Log;
-
-#[derive(Default)]
-pub struct LogRecorder(RefCell<Vec<Log>>);
-
-impl LogRecorder {
- pub fn is_empty(&self) -> bool {
- self.0.borrow().is_empty()
- }
- pub fn log(&self, log: Log) {
- self.0.borrow_mut().push(log);
- }
- pub fn retrieve_logs(self) -> Vec<Log> {
- self.0.into_inner()
- }
-}
pallets/nft/src/eth/mod.rsdiffbeforeafterboth--- a/pallets/nft/src/eth/mod.rs
+++ b/pallets/nft/src/eth/mod.rs
@@ -1,23 +1,15 @@
pub mod account;
pub mod erc;
-mod erc_impl;
-pub mod log;
pub mod sponsoring;
-use evm_coder::abi::AbiWriter;
-use evm_coder::abi::StringError;
-use sp_std::prelude::*;
+use pallet_evm_coder_substrate::call_internal;
use sp_std::borrow::ToOwned;
use sp_std::vec::Vec;
-
-use pallet_evm::{PrecompileOutput, ExitReason, ExitRevert, ExitSucceed};
+use pallet_evm::{PrecompileOutput};
use sp_core::{H160, U256};
use frame_support::storage::StorageMap;
-
use crate::{Config, CollectionById, CollectionHandle, CollectionId, CollectionMode};
-
-use erc::{UniqueFungible, UniqueFungibleCall, UniqueNFT, UniqueNFTCall};
-use evm_coder::{types::*, abi::AbiReader};
+use erc::{UniqueFungibleCall, UniqueNFTCall};
pub struct NftErcSupport<T: Config>(core::marker::PhantomData<T>);
@@ -42,19 +34,17 @@
H160(out)
}
+/*
fn call_internal<T: Config>(
collection: &mut CollectionHandle<T>,
caller: caller,
method_id: u32,
mut input: AbiReader,
value: U256,
-) -> Result<Option<AbiWriter>, evm_coder::abi::StringError> {
+) -> Result<Option<AbiWriter>> {
match collection.mode.clone() {
CollectionMode::Fungible(_) => {
- #[cfg(feature = "std")]
- {
- println!("Parse fungible call {:x}", method_id);
- }
+ call_internal();
let call = match UniqueFungibleCall::parse(method_id, &mut input)? {
Some(v) => v,
None => {
@@ -65,10 +55,6 @@
return Ok(None);
}
};
- #[cfg(feature = "std")]
- {
- dbg!(&call);
- }
Ok(Some(<CollectionHandle<T> as UniqueFungible>::call(
collection,
Msg {
@@ -92,11 +78,9 @@
},
)?))
}
- _ => Err(StringError::from(
- "erc calls only supported to fungible and nft collections for now",
- )),
+ _ => Err("erc calls only supported to fungible and nft collections for now".into()),
}
-}
+}*/
impl<T: Config> pallet_evm::OnMethodCall<T> for NftErcSupport<T> {
fn is_reserved(target: &H160) -> bool {
@@ -129,56 +113,15 @@
) -> Option<PrecompileOutput> {
let mut collection = map_eth_to_id(target)
.and_then(|id| <CollectionHandle<T>>::get_with_gas_limit(id, gas_limit))?;
- let (method_id, input) = AbiReader::new_call(input).unwrap();
- let result = call_internal(&mut collection, *source, method_id, input, value);
- let cost = gas_limit - collection.gas_left();
- let logs = collection.logs.retrieve_logs();
- match result {
- Ok(Some(v)) => Some(PrecompileOutput {
- exit_status: ExitReason::Succeed(ExitSucceed::Returned),
- cost,
- logs,
- output: v.finish(),
- }),
- Ok(None) => None,
- Err(e) => Some(PrecompileOutput {
- exit_status: ExitReason::Revert(ExitRevert::Reverted),
- cost: 0,
- logs: Default::default(),
- output: AbiWriter::from(e).finish(),
- }),
- }
- }
-}
-
-// TODO: This function is slow, and output can be memoized
-pub fn generate_transaction(collection_id: u32, chain_id: u64) -> ethereum::Transaction {
- // FIXME: Can be done on wasm runtime with https://github.com/paritytech/substrate/pull/8728
- #[cfg(feature = "std")]
- {
- let contract = collection_id_to_address(collection_id);
- let signed = ethereum_tx_sign::RawTransaction {
- nonce: 0.into(),
- to: Some(contract.0.into()),
- value: 0.into(),
- gas_price: 0.into(),
- gas: 0.into(),
- // zero selector, this transaction always have same sender, so all data should be acquired from logs
- data: Vec::from([0, 0, 0, 0]),
- }
- .sign(
- // TODO: move to pallet config
- // 0xF70631E55faff9f3FD3681545aa6c724226a3853
- // 9dbaef9b3ebc00e53f67c6a77bcfbf2c4f2aebe4d70d94af4f2df01744b7a91a
- &hex_literal::hex!("9dbaef9b3ebc00e53f67c6a77bcfbf2c4f2aebe4d70d94af4f2df01744b7a91a")
- .into(),
- &chain_id,
- );
- rlp::decode::<ethereum::Transaction>(&signed)
- .expect("transaction is just created, it can't be broken")
- }
- #[cfg(not(feature = "std"))]
- {
- panic!("transaction generation not yet supported by wasm runtime while generating transaction for collection_id {}, chain_id {}", collection_id, chain_id)
+ let result = match collection.mode {
+ CollectionMode::NFT => {
+ call_internal::<UniqueNFTCall, _>(*source, &mut collection, value, input)
+ }
+ CollectionMode::Fungible(_) => {
+ call_internal::<UniqueFungibleCall, _>(*source, &mut collection, value, input)
+ }
+ _ => return None,
+ };
+ collection.recorder.evm_to_precompile_output(result)
}
}
pallets/nft/src/lib.rsdiffbeforeafterboth--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -36,14 +36,12 @@
use sp_std::vec;
use sp_runtime::sp_std::prelude::Vec;
use core::ops::{Deref, DerefMut};
-use core::cell::RefCell;
use nft_data_structs::{
MAX_DECIMAL_POINTS, MAX_SPONSOR_TIMEOUT, MAX_TOKEN_OWNERSHIP, MAX_REFUNGIBLE_PIECES,
AccessMode, ChainLimits, Collection, CreateItemData, CollectionLimits, CollectionId,
CollectionMode, TokenId, SchemaVersion, SponsorshipState, Ownership, NftItemType,
FungibleItemType, ReFungibleItemType,
};
-use pallet_ethereum::EthereumTransactionSender;
#[cfg(test)]
mod mock;
@@ -55,6 +53,7 @@
mod eth;
mod sponsorship;
pub use sponsorship::NftSponsorshipHandler;
+pub use eth::sponsoring::NftEthSponsorshipHandler;
pub use eth::NftErcSupport;
pub use eth::account::*;
@@ -178,42 +177,39 @@
}
}
+#[must_use = "Should call submit_logs or save, otherwise some data will be lost for evm side"]
pub struct CollectionHandle<T: Config> {
pub id: CollectionId,
collection: Collection<T>,
- logs: eth::log::LogRecorder,
- evm_address: H160,
- gas_limit: RefCell<u64>,
+ recorder: pallet_evm_coder_substrate::SubstrateRecorder<T>,
}
impl<T: Config> CollectionHandle<T> {
pub fn get_with_gas_limit(id: CollectionId, gas_limit: u64) -> Option<Self> {
<CollectionById<T>>::get(id).map(|collection| Self {
id,
collection,
- logs: eth::log::LogRecorder::default(),
- evm_address: eth::collection_id_to_address(id),
- gas_limit: RefCell::new(gas_limit),
+ recorder: pallet_evm_coder_substrate::SubstrateRecorder::new(
+ eth::collection_id_to_address(id),
+ gas_limit,
+ ),
})
}
pub fn get(id: CollectionId) -> Option<Self> {
Self::get_with_gas_limit(id, u64::MAX)
}
- pub fn gas_left(&self) -> u64 {
- *self.gas_limit.borrow()
+ pub fn log(&self, log: impl evm_coder::ToLog) -> DispatchResult {
+ self.recorder.log_sub(log)
}
- pub fn consume_gas(&self, gas: u64) -> DispatchResult {
- let mut gas_limit = self.gas_limit.borrow_mut();
- if *gas_limit < gas {
- fail!(Error::<T>::OutOfGas);
- }
- *gas_limit -= gas;
- Ok(())
+ fn consume_gas(&self, gas: u64) -> DispatchResult {
+ self.recorder.consume_gas_sub(gas)
}
- pub fn log(&self, log: impl evm_coder::ToLog) {
- self.logs.log(log.to_log(self.evm_address))
+ pub fn submit_logs(self) -> DispatchResult {
+ self.recorder.submit_logs()
}
- pub fn into_inner(self) -> Collection<T> {
- self.collection
+ pub fn save(self) -> DispatchResult {
+ self.recorder.submit_logs()?;
+ <CollectionById<T>>::insert(self.id, self.collection);
+ Ok(())
}
}
impl<T: Config> Deref for CollectionHandle<T> {
@@ -230,7 +226,7 @@
}
}
-pub trait Config: system::Config + Sized {
+pub trait Config: system::Config + pallet_evm_coder_substrate::Config + Sized {
type Event: From<Event<Self>> + Into<<Self as system::Config>::Event>;
/// Weight information for extrinsics in this pallet.
@@ -245,9 +241,6 @@
<<Self as Config>::Currency as Currency<Self::AccountId>>::Balance,
>;
type TreasuryAccountId: Get<Self::AccountId>;
-
- type EthereumChainId: Get<u64>;
- type EthereumTransactionSender: pallet_ethereum::EthereumTransactionSender;
}
// # Used definitions
@@ -564,23 +557,23 @@
fail!(Error::<T>::NoPermission);
}
- <AddressTokens<T>>::remove_prefix(collection_id);
- <Allowances<T>>::remove_prefix(collection_id);
- <Balance<T>>::remove_prefix(collection_id);
+ <AddressTokens<T>>::remove_prefix(collection_id, None);
+ <Allowances<T>>::remove_prefix(collection_id, None);
+ <Balance<T>>::remove_prefix(collection_id, None);
<ItemListIndex>::remove(collection_id);
<AdminList<T>>::remove(collection_id);
<CollectionById<T>>::remove(collection_id);
- <WhiteList<T>>::remove_prefix(collection_id);
+ <WhiteList<T>>::remove_prefix(collection_id, None);
- <NftItemList<T>>::remove_prefix(collection_id);
- <FungibleItemList<T>>::remove_prefix(collection_id);
- <ReFungibleItemList<T>>::remove_prefix(collection_id);
+ <NftItemList<T>>::remove_prefix(collection_id, None);
+ <FungibleItemList<T>>::remove_prefix(collection_id, None);
+ <ReFungibleItemList<T>>::remove_prefix(collection_id, None);
- <NftTransferBasket<T>>::remove_prefix(collection_id);
- <FungibleTransferBasket<T>>::remove_prefix(collection_id);
- <ReFungibleTransferBasket<T>>::remove_prefix(collection_id);
+ <NftTransferBasket<T>>::remove_prefix(collection_id, None);
+ <FungibleTransferBasket<T>>::remove_prefix(collection_id, None);
+ <ReFungibleTransferBasket<T>>::remove_prefix(collection_id, None);
- <VariableMetaDataBasket<T>>::remove_prefix(collection_id);
+ <VariableMetaDataBasket<T>>::remove_prefix(collection_id, None);
DestroyedCollectionCount::put(DestroyedCollectionCount::get()
.checked_add(1)
@@ -667,9 +660,7 @@
let mut target_collection = Self::get_collection(collection_id)?;
Self::check_owner_permissions(&target_collection, &sender)?;
target_collection.access = mode;
- Self::save_collection(target_collection);
-
- Ok(())
+ target_collection.save()
}
/// Allows Anyone to create tokens if:
@@ -694,9 +685,7 @@
let mut target_collection = Self::get_collection(collection_id)?;
Self::check_owner_permissions(&target_collection, &sender)?;
target_collection.mint_mode = mint_permission;
- Self::save_collection(target_collection);
-
- Ok(())
+ target_collection.save()
}
/// Change the owner of the collection.
@@ -718,9 +707,7 @@
let mut target_collection = Self::get_collection(collection_id)?;
Self::check_owner_permissions(&target_collection, &sender)?;
target_collection.owner = new_owner;
- Self::save_collection(target_collection);
-
- Ok(())
+ target_collection.save()
}
/// Adds an admin of the Collection.
@@ -800,9 +787,7 @@
Self::check_owner_permissions(&target_collection, &sender)?;
target_collection.sponsorship = SponsorshipState::Unconfirmed(new_sponsor);
- Self::save_collection(target_collection);
-
- Ok(())
+ target_collection.save()
}
/// # Permissions
@@ -824,9 +809,7 @@
);
target_collection.sponsorship = SponsorshipState::Confirmed(sender);
- Self::save_collection(target_collection);
-
- Ok(())
+ target_collection.save()
}
/// Switch back to pay-per-own-transaction model.
@@ -847,9 +830,7 @@
Self::check_owner_permissions(&target_collection, &sender)?;
target_collection.sponsorship = SponsorshipState::Disabled;
- Self::save_collection(target_collection);
-
- Ok(())
+ target_collection.save()
}
/// This method creates a concrete instance of NFT Collection created with CreateCollection method.
@@ -884,8 +865,7 @@
Self::create_item_internal(&sender, &collection, &owner, data)?;
- Self::submit_logs(collection)?;
- Ok(())
+ collection.submit_logs()
}
/// This method creates multiple items in a collection created with CreateCollection method.
@@ -918,8 +898,7 @@
Self::create_multiple_items_internal(&sender, &collection, &owner, items_data)?;
- Self::submit_logs(collection)?;
- Ok(())
+ collection.submit_logs()
}
/// Destroys a concrete instance of NFT.
@@ -944,8 +923,7 @@
Self::burn_item_internal(&sender, &target_collection, item_id, value)?;
- Self::submit_logs(target_collection)?;
- Ok(())
+ target_collection.submit_logs()
}
/// Change ownership of the token.
@@ -979,8 +957,7 @@
Self::transfer_internal(&sender, &recipient, &collection, item_id, value)?;
- Self::submit_logs(collection)?;
- Ok(())
+ collection.submit_logs()
}
/// Set, change, or remove approved address to transfer the ownership of the NFT.
@@ -1006,8 +983,7 @@
Self::approve_internal(&sender, &spender, &collection, item_id, amount)?;
- Self::submit_logs(collection)?;
- Ok(())
+ collection.submit_logs()
}
/// Change ownership of a NFT on behalf of the owner. See Approve method for additional information. After this method executes, the approval is removed so that the approved address will not be able to transfer this NFT again from this owner.
@@ -1037,8 +1013,7 @@
Self::transfer_from_internal(&sender, &from, &recipient, &collection, item_id, value)?;
- Self::submit_logs(collection)?;
- Ok(())
+ collection.submit_logs()
}
// #[weight = 0]
// // let no_perm_mes = "You do not have permissions to modify this collection";
@@ -1107,9 +1082,7 @@
let mut target_collection = Self::get_collection(collection_id)?;
Self::check_owner_or_admin_permissions(&target_collection, &sender)?;
target_collection.schema_version = version;
- Self::save_collection(target_collection);
-
- Ok(())
+ target_collection.save()
}
/// Set off-chain data schema.
@@ -1139,9 +1112,7 @@
ensure!(schema.len() as u32 <= ChainLimit::get().offchain_schema_limit, "");
target_collection.offchain_schema = schema;
- Self::save_collection(target_collection);
-
- Ok(())
+ target_collection.save()
}
/// Set const on-chain data schema.
@@ -1171,9 +1142,7 @@
ensure!(schema.len() as u32 <= ChainLimit::get().const_on_chain_schema_limit, "");
target_collection.const_on_chain_schema = schema;
- Self::save_collection(target_collection);
-
- Ok(())
+ target_collection.save()
}
/// Set variable on-chain data schema.
@@ -1203,9 +1172,7 @@
ensure!(schema.len() as u32 <= ChainLimit::get().variable_on_chain_schema_limit, "");
target_collection.variable_on_chain_schema = schema;
- Self::save_collection(target_collection);
-
- Ok(())
+ target_collection.save()
}
// Sudo permissions function
@@ -1253,9 +1220,8 @@
);
target_collection.limits = new_limits;
- Self::save_collection(target_collection);
- Ok(())
+ target_collection.save()
}
}
}
@@ -1376,7 +1342,7 @@
owner: *sender.as_eth(),
approved: *spender.as_eth(),
token_id: item_id.into(),
- });
+ })?;
}
if matches!(collection.mode, CollectionMode::Fungible(_)) {
@@ -1385,7 +1351,7 @@
owner: *sender.as_eth(),
spender: *spender.as_eth(),
value: allowance.into(),
- });
+ })?;
}
Self::deposit_event(RawEvent::Approved(
@@ -1461,7 +1427,7 @@
owner: *from.as_eth(),
spender: *sender.as_eth(),
value: allowance.into(),
- });
+ })?;
}
Ok(())
@@ -1789,7 +1755,7 @@
from: H160::default(),
to: *item_owner.as_eth(),
token_id: current_index.into(),
- });
+ })?;
Self::deposit_event(RawEvent::ItemCreated(
collection_id,
current_index,
@@ -1886,7 +1852,7 @@
from: *owner.as_eth(),
to: H160::default(),
value: value.into(),
- });
+ })?;
Ok(())
}
@@ -1894,22 +1860,8 @@
collection_id: CollectionId,
) -> Result<CollectionHandle<T>, sp_runtime::DispatchError> {
Ok(<CollectionHandle<T>>::get(collection_id).ok_or(Error::<T>::CollectionNotFound)?)
- }
-
- fn save_collection(collection: CollectionHandle<T>) {
- <CollectionById<T>>::insert(collection.id, collection.into_inner());
}
- pub fn submit_logs(collection: CollectionHandle<T>) -> DispatchResult {
- if collection.logs.is_empty() {
- return Ok(());
- }
- T::EthereumTransactionSender::submit_logs_transaction(
- eth::generate_transaction(collection.id, T::EthereumChainId::get()),
- collection.logs.retrieve_logs(),
- )
- }
-
fn check_owner_permissions(
target_collection: &CollectionHandle<T>,
subject: &T::AccountId,
@@ -2037,7 +1989,7 @@
from: *owner.as_eth(),
to: *recipient.as_eth(),
value: value.into(),
- });
+ })?;
Self::deposit_event(RawEvent::Transfer(
collection.id,
1,
@@ -2173,7 +2125,7 @@
from: *sender.as_eth(),
to: *new_owner.as_eth(),
token_id: item_id.into(),
- });
+ })?;
Self::deposit_event(RawEvent::Transfer(
collection.id,
item_id,
pallets/nft/src/mock.rsdiffbeforeafterboth1#![allow(clippy::from_over_into)]23use crate as pallet_template;4use sp_core::H256;5use frame_support::{parameter_types, weights::IdentityFee};6use sp_runtime::{7 traits::{BlakeTwo256, IdentityLookup},8 testing::Header,9 Perbill,10};11use pallet_transaction_payment::{CurrencyAdapter};12use frame_system as system;13use pallet_evm::AddressMapping;14use crate::{EvmBackwardsAddressMapping, CrossAccountId};15use codec::{Encode, Decode};1617type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;18type Block = frame_system::mocking::MockBlock<Test>;1920// Configure a mock runtime to test the pallet.21frame_support::construct_runtime!(22 pub enum Test where23 Block = Block,24 NodeBlock = Block,25 UncheckedExtrinsic = UncheckedExtrinsic,26 {27 System: frame_system::{Pallet, Call, Config, Storage, Event<T>},28 TemplateModule: pallet_template::{Pallet, Call, Storage},29 Balances: pallet_balances::{Pallet, Call, Storage},30 }31);3233parameter_types! {34 pub const BlockHashCount: u64 = 250;35 pub const SS58Prefix: u8 = 42;36}3738impl system::Config for Test {39 type BaseCallFilter = ();40 type BlockWeights = ();41 type BlockLength = ();42 type DbWeight = ();43 type Origin = Origin;44 type Call = Call;45 type Index = u64;46 type BlockNumber = u64;47 type Hash = H256;48 type Hashing = BlakeTwo256;49 type AccountId = u64;50 type Lookup = IdentityLookup<Self::AccountId>;51 type Header = Header;52 type Event = ();53 type BlockHashCount = BlockHashCount;54 type Version = ();55 type PalletInfo = PalletInfo;56 type AccountData = pallet_balances::AccountData<u64>;57 type OnNewAccount = ();58 type OnKilledAccount = ();59 type SystemWeightInfo = ();60 type SS58Prefix = SS58Prefix;61 type OnSetCode = ();62}6364parameter_types! {65 pub const ExistentialDeposit: u64 = 1;66 pub const MaxLocks: u32 = 50;67}68//frame_system::Module<Test>;69impl pallet_balances::Config for Test {70 type AccountStore = System;71 type Balance = u64;72 type DustRemoval = ();73 type Event = ();74 type ExistentialDeposit = ExistentialDeposit;75 type WeightInfo = ();76 type MaxLocks = MaxLocks;77}7879parameter_types! {80 pub const TransactionByteFee: u64 = 1;81}8283impl pallet_transaction_payment::Config for Test {84 type OnChargeTransaction = CurrencyAdapter<pallet_balances::Pallet<Test>, ()>;85 type TransactionByteFee = TransactionByteFee;86 type WeightToFee = IdentityFee<u64>;87 type FeeMultiplierUpdate = ();88}8990parameter_types! {91 pub const MinimumPeriod: u64 = 1;92}93impl pallet_timestamp::Config for Test {94 type Moment = u64;95 type OnTimestampSet = ();96 type MinimumPeriod = MinimumPeriod;97 type WeightInfo = ();98}99100type Timestamp = pallet_timestamp::Pallet<Test>;101type Randomness = pallet_randomness_collective_flip::Pallet<Test>;102103parameter_types! {104 pub const TombstoneDeposit: u64 = 1;105 pub const DepositPerContract: u64 = 1;106 pub const DepositPerStorageByte: u64 = 1;107 pub const DepositPerStorageItem: u64 = 1;108 pub RentFraction: Perbill = Perbill::from_rational(1u32, 30 * 24 * 60 * 10);109 pub const SurchargeReward: u64 = 1;110 pub const SignedClaimHandicap: u32 = 2;111 pub DeletionWeightLimit: u64 = u64::MAX;//Perbill::from_percent(10);112 pub DeletionQueueDepth: u32 = 10;113 pub Schedule: pallet_contracts::Schedule<Test> = Default::default();114}115116impl pallet_contracts::Config for Test {117 type Time = Timestamp;118 type Randomness = Randomness;119 type Currency = pallet_balances::Pallet<Test>;120 type Event = ();121 type RentPayment = ();122 type SignedClaimHandicap = SignedClaimHandicap;123 type TombstoneDeposit = TombstoneDeposit;124 type DepositPerContract = DepositPerContract;125 type DepositPerStorageByte = DepositPerStorageByte;126 type DepositPerStorageItem = DepositPerStorageItem;127 type RentFraction = RentFraction;128 type SurchargeReward = SurchargeReward;129 type DeletionWeightLimit = DeletionWeightLimit;130 type DeletionQueueDepth = DeletionQueueDepth;131 type ChainExtension = ();132 type WeightPrice = ();133 type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;134 type Schedule = Schedule;135 type CallStack = [pallet_contracts::Frame<Self>; 31];136}137138parameter_types! {139 pub const CollectionCreationPrice: u32 = 0;140 pub TreasuryAccountId: u64 = 1234;141 pub EthereumChainId: u32 = 1111;142}143144pub struct TestEvmAddressMapping;145impl AddressMapping<u64> for TestEvmAddressMapping {146 fn into_account_id(_addr: sp_core::H160) -> u64 {147 unimplemented!()148 }149}150151pub struct TestEvmBackwardsAddressMapping;152impl EvmBackwardsAddressMapping<u64> for TestEvmBackwardsAddressMapping {153 fn from_account_id(_account_id: u64) -> sp_core::H160 {154 unimplemented!()155 }156}157158#[derive(Encode, Decode, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]159pub struct TestCrossAccountId(u64, sp_core::H160);160impl CrossAccountId<u64> for TestCrossAccountId {161 fn from_sub(sub: u64) -> Self {162 let mut eth = [0; 20];163 eth[12..20].copy_from_slice(&sub.to_be_bytes());164 Self(sub, sp_core::H160(eth))165 }166 fn as_sub(&self) -> &u64 {167 &self.0168 }169 fn from_eth(_eth: sp_core::H160) -> Self {170 unimplemented!()171 }172 fn as_eth(&self) -> &sp_core::H160 {173 &self.1174 }175}176177pub struct TestEtheremTransactionSender;178impl pallet_ethereum::EthereumTransactionSender for TestEtheremTransactionSender {179 fn submit_logs_transaction(180 _tx: pallet_ethereum::Transaction,181 _logs: Vec<pallet_ethereum::Log>,182 ) -> Result<(), sp_runtime::DispatchError> {183 Ok(())184 }185}186187impl pallet_template::Config for Test {188 type Event = ();189 type WeightInfo = ();190 type CollectionCreationPrice = CollectionCreationPrice;191 type Currency = pallet_balances::Pallet<Test>;192 type TreasuryAccountId = TreasuryAccountId;193 type EvmAddressMapping = TestEvmAddressMapping;194 type EvmBackwardsAddressMapping = TestEvmBackwardsAddressMapping;195 type CrossAccountId = TestCrossAccountId;196 type EthereumChainId = EthereumChainId;197 type EthereumTransactionSender = TestEtheremTransactionSender;198}199200// Build genesis storage according to the mock runtime.201pub fn new_test_ext() -> sp_io::TestExternalities {202 system::GenesisConfig::default()203 .build_storage::<Test>()204 .unwrap()205 .into()206}1#![allow(clippy::from_over_into)]23use crate as pallet_template;4use sp_core::H256;5use frame_support::{parameter_types, weights::IdentityFee};6use sp_runtime::{7 traits::{BlakeTwo256, IdentityLookup},8 testing::Header,9 Perbill,10};11use pallet_transaction_payment::{CurrencyAdapter};12use frame_system as system;13use pallet_evm::AddressMapping;14use crate::{EvmBackwardsAddressMapping, CrossAccountId};15use codec::{Encode, Decode};1617type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;18type Block = frame_system::mocking::MockBlock<Test>;1920// Configure a mock runtime to test the pallet.21frame_support::construct_runtime!(22 pub enum Test where23 Block = Block,24 NodeBlock = Block,25 UncheckedExtrinsic = UncheckedExtrinsic,26 {27 System: frame_system::{Pallet, Call, Config, Storage, Event<T>},28 TemplateModule: pallet_template::{Pallet, Call, Storage},29 Balances: pallet_balances::{Pallet, Call, Storage},30 }31);3233parameter_types! {34 pub const BlockHashCount: u64 = 250;35 pub const SS58Prefix: u8 = 42;36}3738impl system::Config for Test {39 type BaseCallFilter = ();40 type BlockWeights = ();41 type BlockLength = ();42 type DbWeight = ();43 type Origin = Origin;44 type Call = Call;45 type Index = u64;46 type BlockNumber = u64;47 type Hash = H256;48 type Hashing = BlakeTwo256;49 type AccountId = u64;50 type Lookup = IdentityLookup<Self::AccountId>;51 type Header = Header;52 type Event = ();53 type BlockHashCount = BlockHashCount;54 type Version = ();55 type PalletInfo = PalletInfo;56 type AccountData = pallet_balances::AccountData<u64>;57 type OnNewAccount = ();58 type OnKilledAccount = ();59 type SystemWeightInfo = ();60 type SS58Prefix = SS58Prefix;61 type OnSetCode = ();62}6364parameter_types! {65 pub const ExistentialDeposit: u64 = 1;66 pub const MaxLocks: u32 = 50;67}68//frame_system::Module<Test>;69impl pallet_balances::Config for Test {70 type AccountStore = System;71 type Balance = u64;72 type DustRemoval = ();73 type Event = ();74 type ExistentialDeposit = ExistentialDeposit;75 type WeightInfo = ();76 type MaxLocks = MaxLocks;77}7879parameter_types! {80 pub const TransactionByteFee: u64 = 1;81}8283impl pallet_transaction_payment::Config for Test {84 type OnChargeTransaction = CurrencyAdapter<pallet_balances::Pallet<Test>, ()>;85 type TransactionByteFee = TransactionByteFee;86 type WeightToFee = IdentityFee<u64>;87 type FeeMultiplierUpdate = ();88}8990parameter_types! {91 pub const MinimumPeriod: u64 = 1;92}93impl pallet_timestamp::Config for Test {94 type Moment = u64;95 type OnTimestampSet = ();96 type MinimumPeriod = MinimumPeriod;97 type WeightInfo = ();98}99100type Timestamp = pallet_timestamp::Pallet<Test>;101type Randomness = pallet_randomness_collective_flip::Pallet<Test>;102103parameter_types! {104 pub const TombstoneDeposit: u64 = 1;105 pub const DepositPerContract: u64 = 1;106 pub const DepositPerStorageByte: u64 = 1;107 pub const DepositPerStorageItem: u64 = 1;108 pub RentFraction: Perbill = Perbill::from_rational(1u32, 30 * 24 * 60 * 10);109 pub const SurchargeReward: u64 = 1;110 pub const SignedClaimHandicap: u32 = 2;111 pub DeletionWeightLimit: u64 = u64::MAX;//Perbill::from_percent(10);112 pub DeletionQueueDepth: u32 = 10;113 pub Schedule: pallet_contracts::Schedule<Test> = Default::default();114}115116impl pallet_contracts::Config for Test {117 type Time = Timestamp;118 type Randomness = Randomness;119 type Currency = pallet_balances::Pallet<Test>;120 type Event = ();121 type RentPayment = ();122 type SignedClaimHandicap = SignedClaimHandicap;123 type TombstoneDeposit = TombstoneDeposit;124 type DepositPerContract = DepositPerContract;125 type DepositPerStorageByte = DepositPerStorageByte;126 type DepositPerStorageItem = DepositPerStorageItem;127 type RentFraction = RentFraction;128 type SurchargeReward = SurchargeReward;129 type DeletionWeightLimit = DeletionWeightLimit;130 type DeletionQueueDepth = DeletionQueueDepth;131 type ChainExtension = ();132 type WeightPrice = ();133 type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;134 type Schedule = Schedule;135 type CallStack = [pallet_contracts::Frame<Self>; 31];136}137138parameter_types! {139 pub const CollectionCreationPrice: u32 = 0;140 pub TreasuryAccountId: u64 = 1234;141 pub EthereumChainId: u32 = 1111;142}143144pub struct TestEvmAddressMapping;145impl AddressMapping<u64> for TestEvmAddressMapping {146 fn into_account_id(_addr: sp_core::H160) -> u64 {147 unimplemented!()148 }149}150151pub struct TestEvmBackwardsAddressMapping;152impl EvmBackwardsAddressMapping<u64> for TestEvmBackwardsAddressMapping {153 fn from_account_id(_account_id: u64) -> sp_core::H160 {154 unimplemented!()155 }156}157158#[derive(Encode, Decode, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]159pub struct TestCrossAccountId(u64, sp_core::H160);160impl CrossAccountId<u64> for TestCrossAccountId {161 fn from_sub(sub: u64) -> Self {162 let mut eth = [0; 20];163 eth[12..20].copy_from_slice(&sub.to_be_bytes());164 Self(sub, sp_core::H160(eth))165 }166 fn as_sub(&self) -> &u64 {167 &self.0168 }169 fn from_eth(_eth: sp_core::H160) -> Self {170 unimplemented!()171 }172 fn as_eth(&self) -> &sp_core::H160 {173 &self.1174 }175}176177pub struct TestEtheremTransactionSender;178impl pallet_ethereum::EthereumTransactionSender for TestEtheremTransactionSender {179 fn submit_logs_transaction(180 _tx: pallet_ethereum::Transaction,181 _logs: Vec<pallet_ethereum::Log>,182 ) -> Result<(), sp_runtime::DispatchError> {183 Ok(())184 }185}186187impl pallet_template::Config for Test {188 type Event = ();189 type WeightInfo = ();190 type CollectionCreationPrice = CollectionCreationPrice;191 type Currency = pallet_balances::Pallet<Test>;192 type TreasuryAccountId = TreasuryAccountId;193 type EvmAddressMapping = TestEvmAddressMapping;194 type EvmBackwardsAddressMapping = TestEvmBackwardsAddressMapping;195 type CrossAccountId = TestCrossAccountId;196 type EthereumTransactionSender = TestEtheremTransactionSender;197}198199// Build genesis storage according to the mock runtime.200pub fn new_test_ext() -> sp_io::TestExternalities {201 system::GenesisConfig::default()202 .build_storage::<Test>()203 .unwrap()204 .into()205}