git.delta.rocks / unique-network / refs/commits / 5fc39c3d8a70

difftreelog

refactor rewrite nft pallet to evm helpers

Yaroslav Bolyukin2021-07-27parent: #b905ada.patch.diff
in: master

7 files changed

modifiedpallets/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"
modifiedpallets/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> {}
deletedpallets/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)
-	}
-}
deletedpallets/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()
-	}
-}
modifiedpallets/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)
 	}
 }
modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
36use sp_std::vec;36use sp_std::vec;
37use sp_runtime::sp_std::prelude::Vec;37use sp_runtime::sp_std::prelude::Vec;
38use core::ops::{Deref, DerefMut};38use core::ops::{Deref, DerefMut};
39use core::cell::RefCell;
40use nft_data_structs::{39use nft_data_structs::{
41 MAX_DECIMAL_POINTS, MAX_SPONSOR_TIMEOUT, MAX_TOKEN_OWNERSHIP, MAX_REFUNGIBLE_PIECES,40 MAX_DECIMAL_POINTS, MAX_SPONSOR_TIMEOUT, MAX_TOKEN_OWNERSHIP, MAX_REFUNGIBLE_PIECES,
42 AccessMode, ChainLimits, Collection, CreateItemData, CollectionLimits, CollectionId,41 AccessMode, ChainLimits, Collection, CreateItemData, CollectionLimits, CollectionId,
43 CollectionMode, TokenId, SchemaVersion, SponsorshipState, Ownership, NftItemType,42 CollectionMode, TokenId, SchemaVersion, SponsorshipState, Ownership, NftItemType,
44 FungibleItemType, ReFungibleItemType,43 FungibleItemType, ReFungibleItemType,
45};44};
46use pallet_ethereum::EthereumTransactionSender;
4745
48#[cfg(test)]46#[cfg(test)]
49mod mock;47mod mock;
55mod eth;53mod eth;
56mod sponsorship;54mod sponsorship;
57pub use sponsorship::NftSponsorshipHandler;55pub use sponsorship::NftSponsorshipHandler;
56pub use eth::sponsoring::NftEthSponsorshipHandler;
5857
59pub use eth::NftErcSupport;58pub use eth::NftErcSupport;
60pub use eth::account::*;59pub use eth::account::*;
178 }177 }
179}178}
180179
180#[must_use = "Should call submit_logs or save, otherwise some data will be lost for evm side"]
181pub struct CollectionHandle<T: Config> {181pub struct CollectionHandle<T: Config> {
182 pub id: CollectionId,182 pub id: CollectionId,
183 collection: Collection<T>,183 collection: Collection<T>,
184 logs: eth::log::LogRecorder,184 recorder: pallet_evm_coder_substrate::SubstrateRecorder<T>,
185 evm_address: H160,
186 gas_limit: RefCell<u64>,
187}185}
188impl<T: Config> CollectionHandle<T> {186impl<T: Config> CollectionHandle<T> {
189 pub fn get_with_gas_limit(id: CollectionId, gas_limit: u64) -> Option<Self> {187 pub fn get_with_gas_limit(id: CollectionId, gas_limit: u64) -> Option<Self> {
190 <CollectionById<T>>::get(id).map(|collection| Self {188 <CollectionById<T>>::get(id).map(|collection| Self {
191 id,189 id,
192 collection,190 collection,
193 logs: eth::log::LogRecorder::default(),
194 evm_address: eth::collection_id_to_address(id),191 recorder: pallet_evm_coder_substrate::SubstrateRecorder::new(
195 gas_limit: RefCell::new(gas_limit),192 eth::collection_id_to_address(id),
193 gas_limit,
194 ),
196 })195 })
197 }196 }
198 pub fn get(id: CollectionId) -> Option<Self> {197 pub fn get(id: CollectionId) -> Option<Self> {
199 Self::get_with_gas_limit(id, u64::MAX)198 Self::get_with_gas_limit(id, u64::MAX)
200 }199 }
201 pub fn gas_left(&self) -> u64 {200 pub fn log(&self, log: impl evm_coder::ToLog) -> DispatchResult {
202 *self.gas_limit.borrow()201 self.recorder.log_sub(log)
203 }202 }
204 pub fn consume_gas(&self, gas: u64) -> DispatchResult {203 fn consume_gas(&self, gas: u64) -> DispatchResult {
205 let mut gas_limit = self.gas_limit.borrow_mut();204 self.recorder.consume_gas_sub(gas)
206 if *gas_limit < gas {
207 fail!(Error::<T>::OutOfGas);
208 }
209 *gas_limit -= gas;
210 Ok(())
211 }205 }
212 pub fn log(&self, log: impl evm_coder::ToLog) {206 pub fn submit_logs(self) -> DispatchResult {
213 self.logs.log(log.to_log(self.evm_address))207 self.recorder.submit_logs()
214 }208 }
215 pub fn into_inner(self) -> Collection<T> {209 pub fn save(self) -> DispatchResult {
210 self.recorder.submit_logs()?;
216 self.collection211 <CollectionById<T>>::insert(self.id, self.collection);
217 }212 Ok(())
213 }
218}214}
219impl<T: Config> Deref for CollectionHandle<T> {215impl<T: Config> Deref for CollectionHandle<T> {
220 type Target = Collection<T>;216 type Target = Collection<T>;
230 }226 }
231}227}
232228
233pub trait Config: system::Config + Sized {229pub trait Config: system::Config + pallet_evm_coder_substrate::Config + Sized {
234 type Event: From<Event<Self>> + Into<<Self as system::Config>::Event>;230 type Event: From<Event<Self>> + Into<<Self as system::Config>::Event>;
235231
236 /// Weight information for extrinsics in this pallet.232 /// Weight information for extrinsics in this pallet.
246 >;242 >;
247 type TreasuryAccountId: Get<Self::AccountId>;243 type TreasuryAccountId: Get<Self::AccountId>;
248
249 type EthereumChainId: Get<u64>;
250 type EthereumTransactionSender: pallet_ethereum::EthereumTransactionSender;
251}244}
252245
253// # Used definitions246// # Used definitions
564 fail!(Error::<T>::NoPermission);557 fail!(Error::<T>::NoPermission);
565 }558 }
566559
567 <AddressTokens<T>>::remove_prefix(collection_id);560 <AddressTokens<T>>::remove_prefix(collection_id, None);
568 <Allowances<T>>::remove_prefix(collection_id);561 <Allowances<T>>::remove_prefix(collection_id, None);
569 <Balance<T>>::remove_prefix(collection_id);562 <Balance<T>>::remove_prefix(collection_id, None);
570 <ItemListIndex>::remove(collection_id);563 <ItemListIndex>::remove(collection_id);
571 <AdminList<T>>::remove(collection_id);564 <AdminList<T>>::remove(collection_id);
572 <CollectionById<T>>::remove(collection_id);565 <CollectionById<T>>::remove(collection_id);
573 <WhiteList<T>>::remove_prefix(collection_id);566 <WhiteList<T>>::remove_prefix(collection_id, None);
574567
575 <NftItemList<T>>::remove_prefix(collection_id);568 <NftItemList<T>>::remove_prefix(collection_id, None);
576 <FungibleItemList<T>>::remove_prefix(collection_id);569 <FungibleItemList<T>>::remove_prefix(collection_id, None);
577 <ReFungibleItemList<T>>::remove_prefix(collection_id);570 <ReFungibleItemList<T>>::remove_prefix(collection_id, None);
578571
579 <NftTransferBasket<T>>::remove_prefix(collection_id);572 <NftTransferBasket<T>>::remove_prefix(collection_id, None);
580 <FungibleTransferBasket<T>>::remove_prefix(collection_id);573 <FungibleTransferBasket<T>>::remove_prefix(collection_id, None);
581 <ReFungibleTransferBasket<T>>::remove_prefix(collection_id);574 <ReFungibleTransferBasket<T>>::remove_prefix(collection_id, None);
582575
583 <VariableMetaDataBasket<T>>::remove_prefix(collection_id);576 <VariableMetaDataBasket<T>>::remove_prefix(collection_id, None);
584577
585 DestroyedCollectionCount::put(DestroyedCollectionCount::get()578 DestroyedCollectionCount::put(DestroyedCollectionCount::get()
586 .checked_add(1)579 .checked_add(1)
667 let mut target_collection = Self::get_collection(collection_id)?;660 let mut target_collection = Self::get_collection(collection_id)?;
668 Self::check_owner_permissions(&target_collection, &sender)?;661 Self::check_owner_permissions(&target_collection, &sender)?;
669 target_collection.access = mode;662 target_collection.access = mode;
670 Self::save_collection(target_collection);663 target_collection.save()
671
672 Ok(())
673 }664 }
674665
675 /// Allows Anyone to create tokens if:666 /// Allows Anyone to create tokens if:
694 let mut target_collection = Self::get_collection(collection_id)?;685 let mut target_collection = Self::get_collection(collection_id)?;
695 Self::check_owner_permissions(&target_collection, &sender)?;686 Self::check_owner_permissions(&target_collection, &sender)?;
696 target_collection.mint_mode = mint_permission;687 target_collection.mint_mode = mint_permission;
697 Self::save_collection(target_collection);688 target_collection.save()
698
699 Ok(())
700 }689 }
701690
702 /// Change the owner of the collection.691 /// Change the owner of the collection.
718 let mut target_collection = Self::get_collection(collection_id)?;707 let mut target_collection = Self::get_collection(collection_id)?;
719 Self::check_owner_permissions(&target_collection, &sender)?;708 Self::check_owner_permissions(&target_collection, &sender)?;
720 target_collection.owner = new_owner;709 target_collection.owner = new_owner;
721 Self::save_collection(target_collection);710 target_collection.save()
722
723 Ok(())
724 }711 }
725712
726 /// Adds an admin of the Collection.713 /// Adds an admin of the Collection.
800 Self::check_owner_permissions(&target_collection, &sender)?;787 Self::check_owner_permissions(&target_collection, &sender)?;
801788
802 target_collection.sponsorship = SponsorshipState::Unconfirmed(new_sponsor);789 target_collection.sponsorship = SponsorshipState::Unconfirmed(new_sponsor);
803 Self::save_collection(target_collection);790 target_collection.save()
804
805 Ok(())
806 }791 }
807792
808 /// # Permissions793 /// # Permissions
824 );809 );
825810
826 target_collection.sponsorship = SponsorshipState::Confirmed(sender);811 target_collection.sponsorship = SponsorshipState::Confirmed(sender);
827 Self::save_collection(target_collection);812 target_collection.save()
828
829 Ok(())
830 }813 }
831814
832 /// Switch back to pay-per-own-transaction model.815 /// Switch back to pay-per-own-transaction model.
847 Self::check_owner_permissions(&target_collection, &sender)?;830 Self::check_owner_permissions(&target_collection, &sender)?;
848831
849 target_collection.sponsorship = SponsorshipState::Disabled;832 target_collection.sponsorship = SponsorshipState::Disabled;
850 Self::save_collection(target_collection);833 target_collection.save()
851
852 Ok(())
853 }834 }
854835
855 /// This method creates a concrete instance of NFT Collection created with CreateCollection method.836 /// This method creates a concrete instance of NFT Collection created with CreateCollection method.
884865
885 Self::create_item_internal(&sender, &collection, &owner, data)?;866 Self::create_item_internal(&sender, &collection, &owner, data)?;
886867
887 Self::submit_logs(collection)?;868 collection.submit_logs()
888 Ok(())
889 }869 }
890870
891 /// This method creates multiple items in a collection created with CreateCollection method.871 /// This method creates multiple items in a collection created with CreateCollection method.
918898
919 Self::create_multiple_items_internal(&sender, &collection, &owner, items_data)?;899 Self::create_multiple_items_internal(&sender, &collection, &owner, items_data)?;
920900
921 Self::submit_logs(collection)?;901 collection.submit_logs()
922 Ok(())
923 }902 }
924903
925 /// Destroys a concrete instance of NFT.904 /// Destroys a concrete instance of NFT.
944923
945 Self::burn_item_internal(&sender, &target_collection, item_id, value)?;924 Self::burn_item_internal(&sender, &target_collection, item_id, value)?;
946925
947 Self::submit_logs(target_collection)?;926 target_collection.submit_logs()
948 Ok(())
949 }927 }
950928
951 /// Change ownership of the token.929 /// Change ownership of the token.
979957
980 Self::transfer_internal(&sender, &recipient, &collection, item_id, value)?;958 Self::transfer_internal(&sender, &recipient, &collection, item_id, value)?;
981959
982 Self::submit_logs(collection)?;960 collection.submit_logs()
983 Ok(())
984 }961 }
985962
986 /// Set, change, or remove approved address to transfer the ownership of the NFT.963 /// Set, change, or remove approved address to transfer the ownership of the NFT.
1006983
1007 Self::approve_internal(&sender, &spender, &collection, item_id, amount)?;984 Self::approve_internal(&sender, &spender, &collection, item_id, amount)?;
1008985
1009 Self::submit_logs(collection)?;986 collection.submit_logs()
1010 Ok(())
1011 }987 }
1012988
1013 /// 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.989 /// 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.
10371013
1038 Self::transfer_from_internal(&sender, &from, &recipient, &collection, item_id, value)?;1014 Self::transfer_from_internal(&sender, &from, &recipient, &collection, item_id, value)?;
10391015
1040 Self::submit_logs(collection)?;1016 collection.submit_logs()
1041 Ok(())
1042 }1017 }
1043 // #[weight = 0]1018 // #[weight = 0]
1044 // // let no_perm_mes = "You do not have permissions to modify this collection";1019 // // let no_perm_mes = "You do not have permissions to modify this collection";
1107 let mut target_collection = Self::get_collection(collection_id)?;1082 let mut target_collection = Self::get_collection(collection_id)?;
1108 Self::check_owner_or_admin_permissions(&target_collection, &sender)?;1083 Self::check_owner_or_admin_permissions(&target_collection, &sender)?;
1109 target_collection.schema_version = version;1084 target_collection.schema_version = version;
1110 Self::save_collection(target_collection);1085 target_collection.save()
1111
1112 Ok(())
1113 }1086 }
11141087
1115 /// Set off-chain data schema.1088 /// Set off-chain data schema.
1139 ensure!(schema.len() as u32 <= ChainLimit::get().offchain_schema_limit, "");1112 ensure!(schema.len() as u32 <= ChainLimit::get().offchain_schema_limit, "");
11401113
1141 target_collection.offchain_schema = schema;1114 target_collection.offchain_schema = schema;
1142 Self::save_collection(target_collection);1115 target_collection.save()
1143
1144 Ok(())
1145 }1116 }
11461117
1147 /// Set const on-chain data schema.1118 /// Set const on-chain data schema.
1171 ensure!(schema.len() as u32 <= ChainLimit::get().const_on_chain_schema_limit, "");1142 ensure!(schema.len() as u32 <= ChainLimit::get().const_on_chain_schema_limit, "");
11721143
1173 target_collection.const_on_chain_schema = schema;1144 target_collection.const_on_chain_schema = schema;
1174 Self::save_collection(target_collection);1145 target_collection.save()
1175
1176 Ok(())
1177 }1146 }
11781147
1179 /// Set variable on-chain data schema.1148 /// Set variable on-chain data schema.
1203 ensure!(schema.len() as u32 <= ChainLimit::get().variable_on_chain_schema_limit, "");1172 ensure!(schema.len() as u32 <= ChainLimit::get().variable_on_chain_schema_limit, "");
12041173
1205 target_collection.variable_on_chain_schema = schema;1174 target_collection.variable_on_chain_schema = schema;
1206 Self::save_collection(target_collection);1175 target_collection.save()
1207
1208 Ok(())
1209 }1176 }
12101177
1211 // Sudo permissions function1178 // Sudo permissions function
12541221
1255 target_collection.limits = new_limits;1222 target_collection.limits = new_limits;
1223
1256 Self::save_collection(target_collection);1224 target_collection.save()
1257
1258 Ok(())
1259 }1225 }
1260 }1226 }
1261}1227}
1376 owner: *sender.as_eth(),1342 owner: *sender.as_eth(),
1377 approved: *spender.as_eth(),1343 approved: *spender.as_eth(),
1378 token_id: item_id.into(),1344 token_id: item_id.into(),
1379 });1345 })?;
1380 }1346 }
13811347
1382 if matches!(collection.mode, CollectionMode::Fungible(_)) {1348 if matches!(collection.mode, CollectionMode::Fungible(_)) {
1385 owner: *sender.as_eth(),1351 owner: *sender.as_eth(),
1386 spender: *spender.as_eth(),1352 spender: *spender.as_eth(),
1387 value: allowance.into(),1353 value: allowance.into(),
1388 });1354 })?;
1389 }1355 }
13901356
1391 Self::deposit_event(RawEvent::Approved(1357 Self::deposit_event(RawEvent::Approved(
1461 owner: *from.as_eth(),1427 owner: *from.as_eth(),
1462 spender: *sender.as_eth(),1428 spender: *sender.as_eth(),
1463 value: allowance.into(),1429 value: allowance.into(),
1464 });1430 })?;
1465 }1431 }
14661432
1467 Ok(())1433 Ok(())
1789 from: H160::default(),1755 from: H160::default(),
1790 to: *item_owner.as_eth(),1756 to: *item_owner.as_eth(),
1791 token_id: current_index.into(),1757 token_id: current_index.into(),
1792 });1758 })?;
1793 Self::deposit_event(RawEvent::ItemCreated(1759 Self::deposit_event(RawEvent::ItemCreated(
1794 collection_id,1760 collection_id,
1795 current_index,1761 current_index,
1886 from: *owner.as_eth(),1852 from: *owner.as_eth(),
1887 to: H160::default(),1853 to: H160::default(),
1888 value: value.into(),1854 value: value.into(),
1889 });1855 })?;
1890 Ok(())1856 Ok(())
1891 }1857 }
18921858
1896 Ok(<CollectionHandle<T>>::get(collection_id).ok_or(Error::<T>::CollectionNotFound)?)1862 Ok(<CollectionHandle<T>>::get(collection_id).ok_or(Error::<T>::CollectionNotFound)?)
1897 }1863 }
1898
1899 fn save_collection(collection: CollectionHandle<T>) {
1900 <CollectionById<T>>::insert(collection.id, collection.into_inner());
1901 }
1902
1903 pub fn submit_logs(collection: CollectionHandle<T>) -> DispatchResult {
1904 if collection.logs.is_empty() {
1905 return Ok(());
1906 }
1907 T::EthereumTransactionSender::submit_logs_transaction(
1908 eth::generate_transaction(collection.id, T::EthereumChainId::get()),
1909 collection.logs.retrieve_logs(),
1910 )
1911 }
19121864
1913 fn check_owner_permissions(1865 fn check_owner_permissions(
1914 target_collection: &CollectionHandle<T>,1866 target_collection: &CollectionHandle<T>,
2037 from: *owner.as_eth(),1989 from: *owner.as_eth(),
2038 to: *recipient.as_eth(),1990 to: *recipient.as_eth(),
2039 value: value.into(),1991 value: value.into(),
2040 });1992 })?;
2041 Self::deposit_event(RawEvent::Transfer(1993 Self::deposit_event(RawEvent::Transfer(
2042 collection.id,1994 collection.id,
2043 1,1995 1,
2173 from: *sender.as_eth(),2125 from: *sender.as_eth(),
2174 to: *new_owner.as_eth(),2126 to: *new_owner.as_eth(),
2175 token_id: item_id.into(),2127 token_id: item_id.into(),
2176 });2128 })?;
2177 Self::deposit_event(RawEvent::Transfer(2129 Self::deposit_event(RawEvent::Transfer(
2178 collection.id,2130 collection.id,
2179 item_id,2131 item_id,
modifiedpallets/nft/src/mock.rsdiffbeforeafterboth
--- a/pallets/nft/src/mock.rs
+++ b/pallets/nft/src/mock.rs
@@ -193,7 +193,6 @@
 	type EvmAddressMapping = TestEvmAddressMapping;
 	type EvmBackwardsAddressMapping = TestEvmBackwardsAddressMapping;
 	type CrossAccountId = TestCrossAccountId;
-	type EthereumChainId = EthereumChainId;
 	type EthereumTransactionSender = TestEtheremTransactionSender;
 }