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

difftreelog

build update frontier

Yaroslav Bolyukin2021-11-26parent: #f2dde26.patch.diff
in: master

14 files changed

modifiedcrates/evm-coder/Cargo.tomldiffbeforeafterboth
--- a/crates/evm-coder/Cargo.toml
+++ b/crates/evm-coder/Cargo.toml
@@ -7,8 +7,8 @@
 evm-coder-macros = { path = "../evm-coder-macros" }
 primitive-types = { version = "0.10.1", default-features = false }
 hex-literal = "0.3.3"
-ethereum = { version = "0.9", git = "https://github.com/purestake/ethereum", branch = "joshy-scale-info", default-features = false }
-evm-core = { default-features = false, git = "https://github.com/uniquenetwork/evm.git", branch="precompile-output-parachain" }
+ethereum = { version = "0.10.0", default-features = false }
+evm-core = { default-features = false, git = "https://github.com/uniquenetwork/evm.git", branch = "unique-weights" }
 impl-trait-for-tuples = "0.2.1"
 
 [dev-dependencies]
modifiedpallets/common/src/erc.rsdiffbeforeafterboth
--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -1,4 +1,5 @@
 pub use pallet_evm::PrecompileOutput;
+pub use pallet_evm::PrecompileResult;
 use sp_core::{H160, U256};
 
 /// Does not always represent a full collection, for RFT it is either
@@ -6,5 +7,5 @@
 pub trait CommonEvmHandler {
 	const CODE: &'static [u8];
 
-	fn call(self, source: &H160, input: &[u8], value: U256) -> Option<PrecompileOutput>;
+	fn call(self, source: &H160, input: &[u8], value: U256) -> Option<PrecompileResult>;
 }
modifiedpallets/evm-coder-substrate/Cargo.tomldiffbeforeafterboth
--- a/pallets/evm-coder-substrate/Cargo.toml
+++ b/pallets/evm-coder-substrate/Cargo.toml
@@ -9,7 +9,7 @@
 ] }
 sp-std = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
 sp-core = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
-ethereum = { version = "0.9", git = "https://github.com/purestake/ethereum", branch = "joshy-scale-info", default-features = false }
+ethereum = { version = "0.10.0", default-features = false }
 evm-coder = { default-features = false, path = "../../crates/evm-coder" }
 pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
 pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
modifiedpallets/evm-coder-substrate/src/lib.rsdiffbeforeafterboth
--- a/pallets/evm-coder-substrate/src/lib.rs
+++ b/pallets/evm-coder-substrate/src/lib.rs
@@ -20,7 +20,8 @@
 	};
 	use frame_support::{ensure};
 	use pallet_evm::{
-		ExitError, ExitReason, ExitRevert, ExitSucceed, PrecompileOutput, GasWeightMapping,
+		ExitError, ExitRevert, ExitSucceed, GasWeightMapping, PrecompileFailure, PrecompileOutput,
+		PrecompileResult,
 	};
 	use frame_system::ensure_signed;
 	pub use frame_support::dispatch::DispatchResult;
@@ -158,26 +159,28 @@
 		pub fn evm_to_precompile_output(
 			self,
 			result: evm_coder::execution::Result<Option<AbiWriter>>,
-		) -> Option<PrecompileOutput> {
+		) -> Option<PrecompileResult> {
 			use evm_coder::execution::Error;
-			let (writer, reason) = match result {
-				Ok(Some(v)) => (v, ExitReason::Succeed(ExitSucceed::Returned)),
+			Some(match result {
+				Ok(Some(v)) => Ok(PrecompileOutput {
+					exit_status: ExitSucceed::Returned,
+					cost: self.initial_gas - self.gas_left(),
+					logs: self.retrieve_logs(),
+					output: v.finish(),
+				}),
 				Ok(None) => return None,
 				Err(Error::Revert(e)) => {
 					let mut writer = AbiWriter::new_call(evm_coder::fn_selector!(Error(string)));
 					(&e as &str).abi_write(&mut writer);
 
-					(writer, ExitReason::Revert(ExitRevert::Reverted))
+					Err(PrecompileFailure::Revert {
+						exit_status: ExitRevert::Reverted,
+						cost: self.initial_gas - self.gas_left(),
+						output: writer.finish(),
+					})
 				}
-				Err(Error::Fatal(f)) => (AbiWriter::new(), ExitReason::Fatal(f)),
-				Err(Error::Error(e)) => (AbiWriter::new(), ExitReason::Error(e)),
-			};
-
-			Some(PrecompileOutput {
-				cost: self.initial_gas - self.gas_left(),
-				exit_status: reason,
-				logs: self.retrieve_logs(),
-				output: writer.finish(),
+				Err(Error::Fatal(f)) => Err(f.into()),
+				Err(Error::Error(e)) => Err(e.into()),
 			})
 		}
 
@@ -234,7 +237,7 @@
 		mut e: E,
 		value: value,
 		input: &[u8],
-	) -> Option<PrecompileOutput> {
+	) -> Option<PrecompileResult> {
 		let result = call_internal(caller, &mut e, value, input);
 		e.into_recorder().evm_to_precompile_output(result)
 	}
modifiedpallets/evm-contract-helpers/src/eth.rsdiffbeforeafterboth
--- a/pallets/evm-contract-helpers/src/eth.rs
+++ b/pallets/evm-contract-helpers/src/eth.rs
@@ -1,7 +1,10 @@
 use core::marker::PhantomData;
 use evm_coder::{abi::AbiWriter, execution::Result, generate_stubgen, solidity_interface, types::*};
 use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};
-use pallet_evm::{ExitReason, ExitRevert, OnCreate, OnMethodCall, PrecompileOutput};
+use pallet_evm::{
+	ExitReason, ExitRevert, OnCreate, OnMethodCall, PrecompileOutput, PrecompileResult,
+	PrecompileFailure,
+};
 use sp_core::H160;
 use crate::{
 	AllowlistEnabled, Config, Owner, Pallet, SelfSponsoring, SponsorBasket, SponsoringRateLimit,
@@ -109,19 +112,18 @@
 		gas_left: u64,
 		input: &[u8],
 		value: sp_core::U256,
-	) -> Option<PrecompileOutput> {
+	) -> Option<PrecompileResult> {
 		// TODO: Extract to another OnMethodCall handler
 		if <AllowlistEnabled<T>>::get(target) && !<Pallet<T>>::allowed(*target, *source) {
-			return Some(PrecompileOutput {
-				exit_status: ExitReason::Revert(ExitRevert::Reverted),
+			return Some(Err(PrecompileFailure::Revert {
+				exit_status: ExitRevert::Reverted,
 				cost: 0,
 				output: {
 					let mut writer = AbiWriter::new_call(evm_coder::fn_selector!(Error(string)));
 					writer.string("Target contract is allowlisted");
 					writer.finish()
 				},
-				logs: sp_std::vec![],
-			});
+			}));
 		}
 
 		if target != &T::ContractAddress::get() {
modifiedpallets/evm-migration/src/lib.rsdiffbeforeafterboth
--- a/pallets/evm-migration/src/lib.rs
+++ b/pallets/evm-migration/src/lib.rs
@@ -98,7 +98,7 @@
 			_gas_left: u64,
 			_input: &[u8],
 			_value: sp_core::U256,
-		) -> Option<pallet_evm::PrecompileOutput> {
+		) -> Option<pallet_evm::PrecompileResult> {
 			None
 		}
 
modifiedpallets/fungible/Cargo.tomldiffbeforeafterboth
--- a/pallets/fungible/Cargo.toml
+++ b/pallets/fungible/Cargo.toml
@@ -19,7 +19,7 @@
 nft-data-structs = { default-features = false, path = '../../primitives/nft' }
 evm-coder = { default-features = false, path = '../../crates/evm-coder' }
 pallet-evm-coder-substrate = { default-features = false, path = '../evm-coder-substrate' }
-ethereum = { git = "https://github.com/purestake/ethereum", branch = "joshy-scale-info", default-features = false }
+ethereum = { version = "0.10.0", default-features = false }
 frame-benchmarking = { default-features = false, optional = true, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
 scale-info = { version = "1.0.0", default-features = false, features = [
     "derive",
modifiedpallets/fungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/fungible/src/erc.rs
+++ b/pallets/fungible/src/erc.rs
@@ -2,7 +2,7 @@
 use core::convert::TryInto;
 use evm_coder::{ToLog, execution::*, generate_stubgen, solidity_interface, types::*, weight};
 use nft_data_structs::CollectionMode;
-use pallet_common::erc::CommonEvmHandler;
+use pallet_common::erc::{CommonEvmHandler, PrecompileResult};
 use sp_core::{H160, U256};
 use sp_std::vec::Vec;
 use pallet_common::account::CrossAccountId;
@@ -127,7 +127,7 @@
 impl<T: Config> CommonEvmHandler for FungibleHandle<T> {
 	const CODE: &'static [u8] = include_bytes!("./stubs/UniqueFungible.raw");
 
-	fn call(self, source: &H160, input: &[u8], value: U256) -> Option<PrecompileOutput> {
+	fn call(self, source: &H160, input: &[u8], value: U256) -> Option<PrecompileResult> {
 		call::<T, UniqueFungibleCall<T>, _>(*source, self, value, input)
 	}
 }
modifiedpallets/nft/Cargo.tomldiffbeforeafterboth
--- a/pallets/nft/Cargo.toml
+++ b/pallets/nft/Cargo.toml
@@ -131,7 +131,7 @@
 scale-info = { version = "1.0.0", default-features = false, features = [
     "derive",
 ] }
-ethereum = { version = "0.9", git = "https://github.com/purestake/ethereum", branch = "joshy-scale-info", default-features = false }
+ethereum = { version = "0.10.0", default-features = false }
 rlp = { default-features = false, version = "0.5.0" }
 sp-api = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.12" }
 
modifiedpallets/nft/src/eth/mod.rsdiffbeforeafterboth
--- a/pallets/nft/src/eth/mod.rs
+++ b/pallets/nft/src/eth/mod.rs
@@ -1,5 +1,6 @@
 pub mod sponsoring;
 
+use fp_evm::PrecompileResult;
 use pallet_common::{
 	CollectionById,
 	erc::CommonEvmHandler,
@@ -10,7 +11,6 @@
 use pallet_refungible::{RefungibleHandle, erc::RefungibleTokenHandle};
 use sp_std::borrow::ToOwned;
 use sp_std::vec::Vec;
-use pallet_evm::{PrecompileOutput};
 use sp_core::{H160, U256};
 use crate::{CollectionMode, Config, dispatch::Dispatched};
 use pallet_common::CollectionHandle;
@@ -54,7 +54,7 @@
 		gas_limit: u64,
 		input: &[u8],
 		value: U256,
-	) -> Option<PrecompileOutput> {
+	) -> Option<PrecompileResult> {
 		if let Some(collection_id) = map_eth_to_id(target) {
 			let collection = <CollectionHandle<T>>::new_with_gas_limit(collection_id, gas_limit)?;
 			let dispatched = Dispatched::dispatch(collection);
modifiedpallets/nft/src/eth/sponsoring.rsdiffbeforeafterboth
--- a/pallets/nft/src/eth/sponsoring.rs
+++ b/pallets/nft/src/eth/sponsoring.rs
@@ -27,7 +27,7 @@
 		let (method_id, mut reader) = AbiReader::new_call(&call.1).ok()?;
 		match &collection.mode {
 			crate::CollectionMode::NFT => {
-				let call = UniqueNFTCall::parse(method_id, &mut reader).ok()??;
+				let call = <UniqueNFTCall<T>>::parse(method_id, &mut reader).ok()??;
 				match call {
 					UniqueNFTCall::ERC721UniqueExtensions(
 						ERC721UniqueExtensionsCall::Transfer { token_id, .. },
@@ -49,7 +49,7 @@
 				}
 			}
 			crate::CollectionMode::Fungible(_) => {
-				let call = UniqueFungibleCall::parse(method_id, &mut reader).ok()??;
+				let call = <UniqueFungibleCall<T>>::parse(method_id, &mut reader).ok()??;
 				#[allow(clippy::single_match)]
 				match call {
 					UniqueFungibleCall::ERC20(ERC20Call::Transfer { .. }) => {
modifiedpallets/nonfungible/Cargo.tomldiffbeforeafterboth
--- a/pallets/nonfungible/Cargo.toml
+++ b/pallets/nonfungible/Cargo.toml
@@ -19,7 +19,7 @@
 nft-data-structs = { default-features = false, path = '../../primitives/nft' }
 evm-coder = { default-features = false, path = '../../crates/evm-coder' }
 pallet-evm-coder-substrate = { default-features = false, path = '../evm-coder-substrate' }
-ethereum = { git = "https://github.com/purestake/ethereum", branch = "joshy-scale-info", default-features = false }
+ethereum = { version = "0.10.0", default-features = false }
 frame-benchmarking = { default-features = false, optional = true, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
 scale-info = { version = "1.0.0", default-features = false, features = [
     "derive",
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
before · pallets/nonfungible/src/erc.rs
1use core::{2	char::{REPLACEMENT_CHARACTER, decode_utf16},3	convert::TryInto,4};5use evm_coder::{ToLog, execution::*, generate_stubgen, solidity, solidity_interface, types::*, weight};6use frame_support::BoundedVec;7use nft_data_structs::TokenId;8use pallet_evm_coder_substrate::dispatch_to_evm;9use sp_core::{H160, U256};10use sp_std::{vec::Vec, vec};11use pallet_common::{account::CrossAccountId, erc::CommonEvmHandler};12use pallet_evm_coder_substrate::call;13use pallet_common::erc::PrecompileOutput;1415use crate::{16	AccountBalance, Config, CreateItemData, NonfungibleHandle, Pallet, TokenData, TokensMinted,17	SelfWeightOf, weights::WeightInfo,18};1920#[derive(ToLog)]21pub enum ERC721Events {22	Transfer {23		#[indexed]24		from: address,25		#[indexed]26		to: address,27		#[indexed]28		token_id: uint256,29	},30	Approval {31		#[indexed]32		owner: address,33		#[indexed]34		approved: address,35		#[indexed]36		token_id: uint256,37	},38	#[allow(dead_code)]39	ApprovalForAll {40		#[indexed]41		owner: address,42		#[indexed]43		operator: address,44		approved: bool,45	},46}4748#[derive(ToLog)]49pub enum ERC721MintableEvents {50	#[allow(dead_code)]51	MintingFinished {},52}5354#[solidity_interface(name = "ERC721Metadata")]55impl<T: Config> NonfungibleHandle<T> {56	fn name(&self) -> Result<string> {57		Ok(decode_utf16(self.name.iter().copied())58			.map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))59			.collect::<string>())60	}61	fn symbol(&self) -> Result<string> {62		Ok(string::from_utf8_lossy(&self.token_prefix).into())63	}6465	/// Returns token's const_metadata66	#[solidity(rename_selector = "tokenURI")]67	fn token_uri(&self, token_id: uint256) -> Result<string> {68		self.consume_store_reads(1)?;69		let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;70		Ok(string::from_utf8_lossy(71			&<TokenData<T>>::get((self.id, token_id))72				.ok_or("token not found")?73				.const_data,74		)75		.into())76	}77}7879#[solidity_interface(name = "ERC721Enumerable")]80impl<T: Config> NonfungibleHandle<T> {81	fn token_by_index(&self, index: uint256) -> Result<uint256> {82		Ok(index)83	}8485	/// Not implemented86	fn token_of_owner_by_index(&self, _owner: address, _index: uint256) -> Result<uint256> {87		// TODO: Not implemetable88		Err("not implemented".into())89	}9091	fn total_supply(&self) -> Result<uint256> {92		self.consume_store_reads(1)?;93		Ok(<Pallet<T>>::total_supply(self).into())94	}95}9697#[solidity_interface(name = "ERC721", events(ERC721Events))]98impl<T: Config> NonfungibleHandle<T> {99	fn balance_of(&self, owner: address) -> Result<uint256> {100		self.consume_store_reads(1)?;101		let owner = T::CrossAccountId::from_eth(owner);102		let balance = <AccountBalance<T>>::get((self.id, owner));103		Ok(balance.into())104	}105	fn owner_of(&self, token_id: uint256) -> Result<address> {106		self.consume_store_reads(1)?;107		let token: TokenId = token_id.try_into()?;108		Ok(*<TokenData<T>>::get((self.id, token))109			.ok_or("token not found")?110			.owner111			.as_eth())112	}113	/// Not implemented114	fn safe_transfer_from_with_data(115		&mut self,116		_from: address,117		_to: address,118		_token_id: uint256,119		_data: bytes,120		_value: value,121	) -> Result<void> {122		// TODO: Not implemetable123		Err("not implemented".into())124	}125	/// Not implemented126	fn safe_transfer_from(127		&mut self,128		_from: address,129		_to: address,130		_token_id: uint256,131		_value: value,132	) -> Result<void> {133		// TODO: Not implemetable134		Err("not implemented".into())135	}136137	#[weight(<SelfWeightOf<T>>::transfer_from())]138	fn transfer_from(139		&mut self,140		caller: caller,141		from: address,142		to: address,143		token_id: uint256,144		_value: value,145	) -> Result<void> {146		let caller = T::CrossAccountId::from_eth(caller);147		let from = T::CrossAccountId::from_eth(from);148		let to = T::CrossAccountId::from_eth(to);149		let token = token_id.try_into()?;150151		<Pallet<T>>::transfer_from(self, &caller, &from, &to, token)152			.map_err(dispatch_to_evm::<T>)?;153		Ok(())154	}155156	#[weight(<SelfWeightOf<T>>::approve())]157	fn approve(158		&mut self,159		caller: caller,160		approved: address,161		token_id: uint256,162		_value: value,163	) -> Result<void> {164		let caller = T::CrossAccountId::from_eth(caller);165		let approved = T::CrossAccountId::from_eth(approved);166		let token = token_id.try_into()?;167168		<Pallet<T>>::set_allowance(self, &caller, token, Some(&approved))169			.map_err(dispatch_to_evm::<T>)?;170		Ok(())171	}172173	/// Not implemented174	fn set_approval_for_all(175		&mut self,176		_caller: caller,177		_operator: address,178		_approved: bool,179	) -> Result<void> {180		// TODO: Not implemetable181		Err("not implemented".into())182	}183184	/// Not implemented185	fn get_approved(&self, _token_id: uint256) -> Result<address> {186		// TODO: Not implemetable187		Err("not implemented".into())188	}189190	/// Not implemented191	fn is_approved_for_all(&self, _owner: address, _operator: address) -> Result<address> {192		// TODO: Not implemetable193		Err("not implemented".into())194	}195}196197#[solidity_interface(name = "ERC721Burnable")]198impl<T: Config> NonfungibleHandle<T> {199	#[weight(<SelfWeightOf<T>>::burn_item())]200	fn burn(&mut self, caller: caller, token_id: uint256) -> Result<void> {201		let caller = T::CrossAccountId::from_eth(caller);202		let token = token_id.try_into()?;203204		<Pallet<T>>::burn(self, &caller, token).map_err(dispatch_to_evm::<T>)?;205		Ok(())206	}207}208209#[solidity_interface(name = "ERC721Mintable", events(ERC721MintableEvents))]210impl<T: Config> NonfungibleHandle<T> {211	fn minting_finished(&self) -> Result<bool> {212		Ok(false)213	}214215	/// `token_id` should be obtained with `next_token_id` method,216	/// unlike standard, you can't specify it manually217	#[weight(<SelfWeightOf<T>>::create_item())]218	fn mint(&mut self, caller: caller, to: address, token_id: uint256) -> Result<bool> {219		let caller = T::CrossAccountId::from_eth(caller);220		let to = T::CrossAccountId::from_eth(to);221		let token_id: u32 = token_id.try_into()?;222		if <TokensMinted<T>>::get(self.id)223			.checked_add(1)224			.ok_or("item id overflow")?225			!= token_id226		{227			return Err("item id should be next".into());228		}229230		<Pallet<T>>::create_item(231			self,232			&caller,233			CreateItemData {234				const_data: BoundedVec::default(),235				variable_data: BoundedVec::default(),236				owner: to,237			},238		)239		.map_err(dispatch_to_evm::<T>)?;240241		Ok(true)242	}243244	/// `token_id` should be obtained with `next_token_id` method,245	/// unlike standard, you can't specify it manually246	#[solidity(rename_selector = "mintWithTokenURI")]247	#[weight(<SelfWeightOf<T>>::create_item())]248	fn mint_with_token_uri(249		&mut self,250		caller: caller,251		to: address,252		token_id: uint256,253		token_uri: string,254	) -> Result<bool> {255		let caller = T::CrossAccountId::from_eth(caller);256		let to = T::CrossAccountId::from_eth(to);257		let token_id: u32 = token_id.try_into().map_err(|_| "amount overflow")?;258		if <TokensMinted<T>>::get(self.id)259			.checked_add(1)260			.ok_or("item id overflow")?261			!= token_id262		{263			return Err("item id should be next".into());264		}265266		<Pallet<T>>::create_item(267			self,268			&caller,269			CreateItemData {270				const_data: Vec::<u8>::from(token_uri)271					.try_into()272					.map_err(|_| "token uri is too long")?,273				variable_data: BoundedVec::default(),274				owner: to,275			},276		)277		.map_err(dispatch_to_evm::<T>)?;278		Ok(true)279	}280281	/// Not implemented282	fn finish_minting(&mut self, _caller: caller) -> Result<bool> {283		Err("not implementable".into())284	}285}286287#[solidity_interface(name = "ERC721UniqueExtensions")]288impl<T: Config> NonfungibleHandle<T> {289	#[weight(<SelfWeightOf<T>>::transfer())]290	fn transfer(291		&mut self,292		caller: caller,293		to: address,294		token_id: uint256,295		_value: value,296	) -> Result<void> {297		let caller = T::CrossAccountId::from_eth(caller);298		let to = T::CrossAccountId::from_eth(to);299		let token = token_id.try_into()?;300301		<Pallet<T>>::transfer(self, &caller, &to, token).map_err(dispatch_to_evm::<T>)?;302		Ok(())303	}304305	#[weight(<SelfWeightOf<T>>::burn_from())]306	fn burn_from(307		&mut self,308		caller: caller,309		from: address,310		token_id: uint256,311		_value: value,312	) -> Result<void> {313		let caller = T::CrossAccountId::from_eth(caller);314		let from = T::CrossAccountId::from_eth(from);315		let token = token_id.try_into()?;316317		<Pallet<T>>::burn_from(self, &caller, &from, token).map_err(dispatch_to_evm::<T>)?;318		Ok(())319	}320321	fn next_token_id(&self) -> Result<uint256> {322		self.consume_store_reads(1)?;323		Ok(<TokensMinted<T>>::get(self.id)324			.checked_add(1)325			.ok_or("item id overflow")?326			.into())327	}328329	#[weight(<SelfWeightOf<T>>::set_variable_metadata(data.len() as u32))]330	fn set_variable_metadata(331		&mut self,332		caller: caller,333		token_id: uint256,334		data: bytes,335	) -> Result<void> {336		let caller = T::CrossAccountId::from_eth(caller);337		let token = token_id.try_into()?;338339		<Pallet<T>>::set_variable_metadata(self, &caller, token, data)340			.map_err(dispatch_to_evm::<T>)?;341		Ok(())342	}343344	fn get_variable_metadata(&self, token_id: uint256) -> Result<bytes> {345		self.consume_store_reads(1)?;346		let token: TokenId = token_id.try_into()?;347348		Ok(<TokenData<T>>::get((self.id, token))349			.ok_or("token not found")?350			.variable_data)351	}352353	#[weight(<SelfWeightOf<T>>::create_multiple_items(token_ids.len() as u32))]354	fn mint_bulk(&mut self, caller: caller, to: address, token_ids: Vec<uint256>) -> Result<bool> {355		let caller = T::CrossAccountId::from_eth(caller);356		let to = T::CrossAccountId::from_eth(to);357		let mut expected_index = <TokensMinted<T>>::get(self.id)358			.checked_add(1)359			.ok_or("item id overflow")?;360361		let total_tokens = token_ids.len();362		for id in token_ids.into_iter() {363			let id: u32 = id.try_into().map_err(|_| "token id overflow")?;364			if id != expected_index {365				return Err("item id should be next".into());366			}367			expected_index = expected_index.checked_add(1).ok_or("item id overflow")?;368		}369		let data = (0..total_tokens)370			.map(|_| CreateItemData {371				const_data: BoundedVec::default(),372				variable_data: BoundedVec::default(),373				owner: to.clone(),374			})375			.collect();376377		<Pallet<T>>::create_multiple_items(self, &caller, data).map_err(dispatch_to_evm::<T>)?;378		Ok(true)379	}380381	#[solidity(rename_selector = "mintBulkWithTokenURI")]382	#[weight(<SelfWeightOf<T>>::create_multiple_items(tokens.len() as u32))]383	fn mint_bulk_with_token_uri(384		&mut self,385		caller: caller,386		to: address,387		tokens: Vec<(uint256, string)>,388	) -> Result<bool> {389		let caller = T::CrossAccountId::from_eth(caller);390		let to = T::CrossAccountId::from_eth(to);391		let mut expected_index = <TokensMinted<T>>::get(self.id)392			.checked_add(1)393			.ok_or("item id overflow")?;394395		let mut data = Vec::with_capacity(tokens.len());396		for (id, token_uri) in tokens {397			let id: u32 = id.try_into().map_err(|_| "token id overflow")?;398			if id != expected_index {399				panic!("item id should be next ({}) but got {}", expected_index, id);400			}401			expected_index = expected_index.checked_add(1).ok_or("item id overflow")?;402403			data.push(CreateItemData {404				const_data: Vec::<u8>::from(token_uri)405					.try_into()406					.map_err(|_| "token uri is too long")?,407				variable_data: vec![].try_into().unwrap(),408				owner: to.clone(),409			});410		}411412		<Pallet<T>>::create_multiple_items(self, &caller, data).map_err(dispatch_to_evm::<T>)?;413		Ok(true)414	}415}416417#[solidity_interface(418	name = "UniqueNFT",419	is(420		ERC721,421		ERC721Metadata,422		ERC721Enumerable,423		ERC721UniqueExtensions,424		ERC721Mintable,425		ERC721Burnable,426	)427)]428impl<T: Config> NonfungibleHandle<T> {}429430// Not a tests, but code generators431generate_stubgen!(gen_impl, UniqueNFTCall<()>, true);432generate_stubgen!(gen_iface, UniqueNFTCall<()>, false);433434impl<T: Config> CommonEvmHandler for NonfungibleHandle<T> {435	const CODE: &'static [u8] = include_bytes!("./stubs/UniqueNFT.raw");436437	fn call(self, source: &H160, input: &[u8], value: U256) -> Option<PrecompileOutput> {438		call::<T, UniqueNFTCall<T>, _>(*source, self, value, input)439	}440}
after · pallets/nonfungible/src/erc.rs
1use core::{2	char::{REPLACEMENT_CHARACTER, decode_utf16},3	convert::TryInto,4};5use evm_coder::{ToLog, execution::*, generate_stubgen, solidity, solidity_interface, types::*, weight};6use frame_support::BoundedVec;7use nft_data_structs::TokenId;8use pallet_evm_coder_substrate::dispatch_to_evm;9use sp_core::{H160, U256};10use sp_std::{vec::Vec, vec};11use pallet_common::{12	account::CrossAccountId,13	erc::{CommonEvmHandler, PrecompileResult},14};15use pallet_evm_coder_substrate::call;16use pallet_common::erc::PrecompileOutput;1718use crate::{19	AccountBalance, Config, CreateItemData, NonfungibleHandle, Pallet, TokenData, TokensMinted,20	SelfWeightOf, weights::WeightInfo,21};2223#[derive(ToLog)]24pub enum ERC721Events {25	Transfer {26		#[indexed]27		from: address,28		#[indexed]29		to: address,30		#[indexed]31		token_id: uint256,32	},33	Approval {34		#[indexed]35		owner: address,36		#[indexed]37		approved: address,38		#[indexed]39		token_id: uint256,40	},41	#[allow(dead_code)]42	ApprovalForAll {43		#[indexed]44		owner: address,45		#[indexed]46		operator: address,47		approved: bool,48	},49}5051#[derive(ToLog)]52pub enum ERC721MintableEvents {53	#[allow(dead_code)]54	MintingFinished {},55}5657#[solidity_interface(name = "ERC721Metadata")]58impl<T: Config> NonfungibleHandle<T> {59	fn name(&self) -> Result<string> {60		Ok(decode_utf16(self.name.iter().copied())61			.map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))62			.collect::<string>())63	}64	fn symbol(&self) -> Result<string> {65		Ok(string::from_utf8_lossy(&self.token_prefix).into())66	}6768	/// Returns token's const_metadata69	#[solidity(rename_selector = "tokenURI")]70	fn token_uri(&self, token_id: uint256) -> Result<string> {71		self.consume_store_reads(1)?;72		let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;73		Ok(string::from_utf8_lossy(74			&<TokenData<T>>::get((self.id, token_id))75				.ok_or("token not found")?76				.const_data,77		)78		.into())79	}80}8182#[solidity_interface(name = "ERC721Enumerable")]83impl<T: Config> NonfungibleHandle<T> {84	fn token_by_index(&self, index: uint256) -> Result<uint256> {85		Ok(index)86	}8788	/// Not implemented89	fn token_of_owner_by_index(&self, _owner: address, _index: uint256) -> Result<uint256> {90		// TODO: Not implemetable91		Err("not implemented".into())92	}9394	fn total_supply(&self) -> Result<uint256> {95		self.consume_store_reads(1)?;96		Ok(<Pallet<T>>::total_supply(self).into())97	}98}99100#[solidity_interface(name = "ERC721", events(ERC721Events))]101impl<T: Config> NonfungibleHandle<T> {102	fn balance_of(&self, owner: address) -> Result<uint256> {103		self.consume_store_reads(1)?;104		let owner = T::CrossAccountId::from_eth(owner);105		let balance = <AccountBalance<T>>::get((self.id, owner));106		Ok(balance.into())107	}108	fn owner_of(&self, token_id: uint256) -> Result<address> {109		self.consume_store_reads(1)?;110		let token: TokenId = token_id.try_into()?;111		Ok(*<TokenData<T>>::get((self.id, token))112			.ok_or("token not found")?113			.owner114			.as_eth())115	}116	/// Not implemented117	fn safe_transfer_from_with_data(118		&mut self,119		_from: address,120		_to: address,121		_token_id: uint256,122		_data: bytes,123		_value: value,124	) -> Result<void> {125		// TODO: Not implemetable126		Err("not implemented".into())127	}128	/// Not implemented129	fn safe_transfer_from(130		&mut self,131		_from: address,132		_to: address,133		_token_id: uint256,134		_value: value,135	) -> Result<void> {136		// TODO: Not implemetable137		Err("not implemented".into())138	}139140	#[weight(<SelfWeightOf<T>>::transfer_from())]141	fn transfer_from(142		&mut self,143		caller: caller,144		from: address,145		to: address,146		token_id: uint256,147		_value: value,148	) -> Result<void> {149		let caller = T::CrossAccountId::from_eth(caller);150		let from = T::CrossAccountId::from_eth(from);151		let to = T::CrossAccountId::from_eth(to);152		let token = token_id.try_into()?;153154		<Pallet<T>>::transfer_from(self, &caller, &from, &to, token)155			.map_err(dispatch_to_evm::<T>)?;156		Ok(())157	}158159	#[weight(<SelfWeightOf<T>>::approve())]160	fn approve(161		&mut self,162		caller: caller,163		approved: address,164		token_id: uint256,165		_value: value,166	) -> Result<void> {167		let caller = T::CrossAccountId::from_eth(caller);168		let approved = T::CrossAccountId::from_eth(approved);169		let token = token_id.try_into()?;170171		<Pallet<T>>::set_allowance(self, &caller, token, Some(&approved))172			.map_err(dispatch_to_evm::<T>)?;173		Ok(())174	}175176	/// Not implemented177	fn set_approval_for_all(178		&mut self,179		_caller: caller,180		_operator: address,181		_approved: bool,182	) -> Result<void> {183		// TODO: Not implemetable184		Err("not implemented".into())185	}186187	/// Not implemented188	fn get_approved(&self, _token_id: uint256) -> Result<address> {189		// TODO: Not implemetable190		Err("not implemented".into())191	}192193	/// Not implemented194	fn is_approved_for_all(&self, _owner: address, _operator: address) -> Result<address> {195		// TODO: Not implemetable196		Err("not implemented".into())197	}198}199200#[solidity_interface(name = "ERC721Burnable")]201impl<T: Config> NonfungibleHandle<T> {202	#[weight(<SelfWeightOf<T>>::burn_item())]203	fn burn(&mut self, caller: caller, token_id: uint256) -> Result<void> {204		let caller = T::CrossAccountId::from_eth(caller);205		let token = token_id.try_into()?;206207		<Pallet<T>>::burn(self, &caller, token).map_err(dispatch_to_evm::<T>)?;208		Ok(())209	}210}211212#[solidity_interface(name = "ERC721Mintable", events(ERC721MintableEvents))]213impl<T: Config> NonfungibleHandle<T> {214	fn minting_finished(&self) -> Result<bool> {215		Ok(false)216	}217218	/// `token_id` should be obtained with `next_token_id` method,219	/// unlike standard, you can't specify it manually220	#[weight(<SelfWeightOf<T>>::create_item())]221	fn mint(&mut self, caller: caller, to: address, token_id: uint256) -> Result<bool> {222		let caller = T::CrossAccountId::from_eth(caller);223		let to = T::CrossAccountId::from_eth(to);224		let token_id: u32 = token_id.try_into()?;225		if <TokensMinted<T>>::get(self.id)226			.checked_add(1)227			.ok_or("item id overflow")?228			!= token_id229		{230			return Err("item id should be next".into());231		}232233		<Pallet<T>>::create_item(234			self,235			&caller,236			CreateItemData {237				const_data: BoundedVec::default(),238				variable_data: BoundedVec::default(),239				owner: to,240			},241		)242		.map_err(dispatch_to_evm::<T>)?;243244		Ok(true)245	}246247	/// `token_id` should be obtained with `next_token_id` method,248	/// unlike standard, you can't specify it manually249	#[solidity(rename_selector = "mintWithTokenURI")]250	#[weight(<SelfWeightOf<T>>::create_item())]251	fn mint_with_token_uri(252		&mut self,253		caller: caller,254		to: address,255		token_id: uint256,256		token_uri: string,257	) -> Result<bool> {258		let caller = T::CrossAccountId::from_eth(caller);259		let to = T::CrossAccountId::from_eth(to);260		let token_id: u32 = token_id.try_into().map_err(|_| "amount overflow")?;261		if <TokensMinted<T>>::get(self.id)262			.checked_add(1)263			.ok_or("item id overflow")?264			!= token_id265		{266			return Err("item id should be next".into());267		}268269		<Pallet<T>>::create_item(270			self,271			&caller,272			CreateItemData {273				const_data: Vec::<u8>::from(token_uri)274					.try_into()275					.map_err(|_| "token uri is too long")?,276				variable_data: BoundedVec::default(),277				owner: to,278			},279		)280		.map_err(dispatch_to_evm::<T>)?;281		Ok(true)282	}283284	/// Not implemented285	fn finish_minting(&mut self, _caller: caller) -> Result<bool> {286		Err("not implementable".into())287	}288}289290#[solidity_interface(name = "ERC721UniqueExtensions")]291impl<T: Config> NonfungibleHandle<T> {292	#[weight(<SelfWeightOf<T>>::transfer())]293	fn transfer(294		&mut self,295		caller: caller,296		to: address,297		token_id: uint256,298		_value: value,299	) -> Result<void> {300		let caller = T::CrossAccountId::from_eth(caller);301		let to = T::CrossAccountId::from_eth(to);302		let token = token_id.try_into()?;303304		<Pallet<T>>::transfer(self, &caller, &to, token).map_err(dispatch_to_evm::<T>)?;305		Ok(())306	}307308	#[weight(<SelfWeightOf<T>>::burn_from())]309	fn burn_from(310		&mut self,311		caller: caller,312		from: address,313		token_id: uint256,314		_value: value,315	) -> Result<void> {316		let caller = T::CrossAccountId::from_eth(caller);317		let from = T::CrossAccountId::from_eth(from);318		let token = token_id.try_into()?;319320		<Pallet<T>>::burn_from(self, &caller, &from, token).map_err(dispatch_to_evm::<T>)?;321		Ok(())322	}323324	fn next_token_id(&self) -> Result<uint256> {325		self.consume_store_reads(1)?;326		Ok(<TokensMinted<T>>::get(self.id)327			.checked_add(1)328			.ok_or("item id overflow")?329			.into())330	}331332	#[weight(<SelfWeightOf<T>>::set_variable_metadata(data.len() as u32))]333	fn set_variable_metadata(334		&mut self,335		caller: caller,336		token_id: uint256,337		data: bytes,338	) -> Result<void> {339		let caller = T::CrossAccountId::from_eth(caller);340		let token = token_id.try_into()?;341342		<Pallet<T>>::set_variable_metadata(self, &caller, token, data)343			.map_err(dispatch_to_evm::<T>)?;344		Ok(())345	}346347	fn get_variable_metadata(&self, token_id: uint256) -> Result<bytes> {348		self.consume_store_reads(1)?;349		let token: TokenId = token_id.try_into()?;350351		Ok(<TokenData<T>>::get((self.id, token))352			.ok_or("token not found")?353			.variable_data)354	}355356	#[weight(<SelfWeightOf<T>>::create_multiple_items(token_ids.len() as u32))]357	fn mint_bulk(&mut self, caller: caller, to: address, token_ids: Vec<uint256>) -> Result<bool> {358		let caller = T::CrossAccountId::from_eth(caller);359		let to = T::CrossAccountId::from_eth(to);360		let mut expected_index = <TokensMinted<T>>::get(self.id)361			.checked_add(1)362			.ok_or("item id overflow")?;363364		let total_tokens = token_ids.len();365		for id in token_ids.into_iter() {366			let id: u32 = id.try_into().map_err(|_| "token id overflow")?;367			if id != expected_index {368				return Err("item id should be next".into());369			}370			expected_index = expected_index.checked_add(1).ok_or("item id overflow")?;371		}372		let data = (0..total_tokens)373			.map(|_| CreateItemData {374				const_data: BoundedVec::default(),375				variable_data: BoundedVec::default(),376				owner: to.clone(),377			})378			.collect();379380		<Pallet<T>>::create_multiple_items(self, &caller, data).map_err(dispatch_to_evm::<T>)?;381		Ok(true)382	}383384	#[solidity(rename_selector = "mintBulkWithTokenURI")]385	#[weight(<SelfWeightOf<T>>::create_multiple_items(tokens.len() as u32))]386	fn mint_bulk_with_token_uri(387		&mut self,388		caller: caller,389		to: address,390		tokens: Vec<(uint256, string)>,391	) -> Result<bool> {392		let caller = T::CrossAccountId::from_eth(caller);393		let to = T::CrossAccountId::from_eth(to);394		let mut expected_index = <TokensMinted<T>>::get(self.id)395			.checked_add(1)396			.ok_or("item id overflow")?;397398		let mut data = Vec::with_capacity(tokens.len());399		for (id, token_uri) in tokens {400			let id: u32 = id.try_into().map_err(|_| "token id overflow")?;401			if id != expected_index {402				panic!("item id should be next ({}) but got {}", expected_index, id);403			}404			expected_index = expected_index.checked_add(1).ok_or("item id overflow")?;405406			data.push(CreateItemData {407				const_data: Vec::<u8>::from(token_uri)408					.try_into()409					.map_err(|_| "token uri is too long")?,410				variable_data: vec![].try_into().unwrap(),411				owner: to.clone(),412			});413		}414415		<Pallet<T>>::create_multiple_items(self, &caller, data).map_err(dispatch_to_evm::<T>)?;416		Ok(true)417	}418}419420#[solidity_interface(421	name = "UniqueNFT",422	is(423		ERC721,424		ERC721Metadata,425		ERC721Enumerable,426		ERC721UniqueExtensions,427		ERC721Mintable,428		ERC721Burnable,429	)430)]431impl<T: Config> NonfungibleHandle<T> {}432433// Not a tests, but code generators434generate_stubgen!(gen_impl, UniqueNFTCall<()>, true);435generate_stubgen!(gen_iface, UniqueNFTCall<()>, false);436437impl<T: Config> CommonEvmHandler for NonfungibleHandle<T> {438	const CODE: &'static [u8] = include_bytes!("./stubs/UniqueNFT.raw");439440	fn call(self, source: &H160, input: &[u8], value: U256) -> Option<PrecompileResult> {441		call::<T, UniqueNFTCall<T>, _>(*source, self, value, input)442	}443}
modifiedpallets/refungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -11,7 +11,7 @@
 		_source: &sp_core::H160,
 		_input: &[u8],
 		_value: sp_core::U256,
-	) -> Option<pallet_common::erc::PrecompileOutput> {
+	) -> Option<pallet_common::erc::PrecompileResult> {
 		// TODO: Implement RFT variant of ERC721
 		None
 	}
@@ -27,7 +27,7 @@
 		_source: &sp_core::H160,
 		_input: &[u8],
 		_value: sp_core::U256,
-	) -> Option<pallet_common::erc::PrecompileOutput> {
+	) -> Option<pallet_common::erc::PrecompileResult> {
 		// TODO: Implement RFT variant of ERC20
 		None
 	}