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

difftreelog

refactor Make implementations of Abi* for EthCrossAccount via AbiCoder macro

Trubnikov Sergey2022-11-17parent: #0a8a6b0.patch.diff
in: master

9 files changed

modified.maintain/scripts/generate_abi.shdiffbeforeafterboth
--- a/.maintain/scripts/generate_abi.sh
+++ b/.maintain/scripts/generate_abi.sh
@@ -4,6 +4,7 @@
 dir=$PWD
 
 tmp=$(mktemp -d)
+echo "Tmp file: $tmp/input.sol"
 cd $tmp
 cp $dir/$INPUT input.sol
 solcjs --abi -p input.sol
modifiedcrates/evm-coder/src/abi/impls.rsdiffbeforeafterboth
before · crates/evm-coder/src/abi/impls.rs
1use crate::{2	execution::{Result, ResultWithPostInfo, WithPostDispatchInfo},3	types::*,4	make_signature,5	custom_signature::SignatureUnit,6};7use super::{traits::*, ABI_ALIGNMENT, AbiReader, AbiWriter};8use primitive_types::{U256, H160};910#[cfg(not(feature = "std"))]11use alloc::vec::Vec;1213macro_rules! impl_abi_readable {14	($ty:ty, $method:ident, $dynamic:literal) => {15		impl sealed::CanBePlacedInVec for $ty {}1617		impl AbiType for $ty {18			const SIGNATURE: SignatureUnit = make_signature!(new fixed(stringify!($ty)));1920			fn is_dynamic() -> bool {21				$dynamic22			}2324			fn size() -> usize {25				ABI_ALIGNMENT26			}27		}2829		impl AbiRead for $ty {30			fn abi_read(reader: &mut AbiReader) -> Result<$ty> {31				reader.$method()32			}33		}34	};35}3637impl_abi_readable!(uint32, uint32, false);38impl_abi_readable!(uint64, uint64, false);39impl_abi_readable!(uint128, uint128, false);40impl_abi_readable!(uint256, uint256, false);41impl_abi_readable!(bytes4, bytes4, false);42impl_abi_readable!(address, address, false);43impl_abi_readable!(string, string, true);4445impl sealed::CanBePlacedInVec for bool {}4647impl AbiType for bool {48	const SIGNATURE: SignatureUnit = make_signature!(new fixed("bool"));4950	fn is_dynamic() -> bool {51		false52	}53	fn size() -> usize {54		ABI_ALIGNMENT55	}56}57impl AbiRead for bool {58	fn abi_read(reader: &mut AbiReader) -> Result<bool> {59		reader.bool()60	}61}6263impl AbiType for uint8 {64	const SIGNATURE: SignatureUnit = make_signature!(new fixed("uint8"));6566	fn is_dynamic() -> bool {67		false68	}69	fn size() -> usize {70		ABI_ALIGNMENT71	}72}73impl AbiRead for uint8 {74	fn abi_read(reader: &mut AbiReader) -> Result<uint8> {75		reader.uint8()76	}77}7879impl AbiType for bytes {80	const SIGNATURE: SignatureUnit = make_signature!(new fixed("bytes"));8182	fn is_dynamic() -> bool {83		true84	}85	fn size() -> usize {86		ABI_ALIGNMENT87	}88}89impl AbiRead for bytes {90	fn abi_read(reader: &mut AbiReader) -> Result<bytes> {91		Ok(bytes(reader.bytes()?))92	}93}9495impl<R: AbiType + AbiRead + sealed::CanBePlacedInVec> AbiRead for Vec<R> {96	fn abi_read(reader: &mut AbiReader) -> Result<Vec<R>> {97		let mut sub = reader.subresult(None)?;98		let size = sub.uint32()? as usize;99		sub.subresult_offset = sub.offset;100		let mut out = Vec::with_capacity(size);101		for _ in 0..size {102			out.push(<R>::abi_read(&mut sub)?);103			if !<R>::is_dynamic() {104				sub.subresult_offset += <R>::size()105			};106		}107		Ok(out)108	}109}110111impl<R: AbiType> AbiType for Vec<R> {112	const SIGNATURE: SignatureUnit = make_signature!(new nameof(R::SIGNATURE) fixed("[]"));113114	fn is_dynamic() -> bool {115		true116	}117118	fn size() -> usize {119		ABI_ALIGNMENT120	}121}122123impl sealed::CanBePlacedInVec for EthCrossAccount {}124125impl AbiType for EthCrossAccount {126	const SIGNATURE: SignatureUnit = make_signature!(new fixed("(address,uint256)"));127128	fn is_dynamic() -> bool {129		address::is_dynamic() || uint256::is_dynamic()130	}131132	fn size() -> usize {133		<address as AbiType>::size() + <uint256 as AbiType>::size()134	}135}136137impl AbiRead for EthCrossAccount {138	fn abi_read(reader: &mut AbiReader) -> Result<EthCrossAccount> {139		let size = if !EthCrossAccount::is_dynamic() {140			Some(<EthCrossAccount as AbiType>::size())141		} else {142			None143		};144		let mut subresult = reader.subresult(size)?;145		let eth = <address>::abi_read(&mut subresult)?;146		let sub = <uint256>::abi_read(&mut subresult)?;147148		Ok(EthCrossAccount { eth, sub })149	}150}151152impl AbiWrite for EthCrossAccount {153	fn abi_write(&self, writer: &mut AbiWriter) {154		self.eth.abi_write(writer);155		self.sub.abi_write(writer);156	}157}158159impl sealed::CanBePlacedInVec for Property {}160161impl AbiType for Property {162	const SIGNATURE: SignatureUnit = make_signature!(new fixed("(string,bytes)"));163164	fn is_dynamic() -> bool {165		string::is_dynamic() || bytes::is_dynamic()166	}167168	fn size() -> usize {169		<string as AbiType>::size() + <bytes as AbiType>::size()170	}171}172173impl AbiRead for Property {174	fn abi_read(reader: &mut AbiReader) -> Result<Property> {175		let size = if !Property::is_dynamic() {176			Some(<Property as AbiType>::size())177		} else {178			None179		};180		let mut subresult = reader.subresult(size)?;181		let key = <string>::abi_read(&mut subresult)?;182		let value = <bytes>::abi_read(&mut subresult)?;183184		Ok(Property { key, value })185	}186}187188impl AbiWrite for Property {189	fn abi_write(&self, writer: &mut AbiWriter) {190		(&self.key, &self.value).abi_write(writer);191	}192}193194macro_rules! impl_abi_writeable {195	($ty:ty, $method:ident) => {196		impl AbiWrite for $ty {197			fn abi_write(&self, writer: &mut AbiWriter) {198				writer.$method(&self)199			}200		}201	};202}203204impl_abi_writeable!(u8, uint8);205impl_abi_writeable!(u32, uint32);206impl_abi_writeable!(u128, uint128);207impl_abi_writeable!(U256, uint256);208impl_abi_writeable!(H160, address);209impl_abi_writeable!(bool, bool);210impl_abi_writeable!(&str, string);211212impl AbiWrite for string {213	fn abi_write(&self, writer: &mut AbiWriter) {214		writer.string(self)215	}216}217218impl AbiWrite for bytes {219	fn abi_write(&self, writer: &mut AbiWriter) {220		writer.bytes(self.0.as_slice())221	}222}223224impl<T: AbiWrite + AbiType> AbiWrite for Vec<T> {225	fn abi_write(&self, writer: &mut AbiWriter) {226		let is_dynamic = T::is_dynamic();227		let mut sub = if is_dynamic {228			AbiWriter::new_dynamic(is_dynamic)229		} else {230			AbiWriter::new()231		};232233		// Write items count234		(self.len() as u32).abi_write(&mut sub);235236		for item in self {237			item.abi_write(&mut sub);238		}239		writer.write_subresult(sub);240	}241}242243impl AbiWrite for () {244	fn abi_write(&self, _writer: &mut AbiWriter) {}245}246247/// This particular AbiWrite implementation should be split to another trait,248/// which only implements `to_result`, but due to lack of specialization feature249/// in stable Rust, we can't have blanket impl of this trait `for T where T: AbiWrite`,250/// so here we abusing default trait methods for it251impl<T: AbiWrite> AbiWrite for ResultWithPostInfo<T> {252	fn abi_write(&self, _writer: &mut AbiWriter) {253		debug_assert!(false, "shouldn't be called, see comment")254	}255	fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {256		match self {257			Ok(v) => Ok(WithPostDispatchInfo {258				post_info: v.post_info.clone(),259				data: {260					let mut out = AbiWriter::new();261					v.data.abi_write(&mut out);262					out263				},264			}),265			Err(e) => Err(e.clone()),266		}267	}268}269270macro_rules! impl_tuples {271	($($ident:ident)+) => {272		impl<$($ident: AbiType,)+> AbiType for ($($ident,)+)273		where274        $(275            $ident: AbiType,276        )+277		{278            const SIGNATURE: SignatureUnit = make_signature!(279                new fixed("(")280                $(nameof(<$ident>::SIGNATURE) fixed(","))+281                shift_left(1)282                fixed(")")283            );284285			fn is_dynamic() -> bool {286				false287				$(288					|| <$ident>::is_dynamic()289				)*290			}291292			fn size() -> usize {293				0 $(+ <$ident>::size())+294			}295		}296297		impl<$($ident),+> sealed::CanBePlacedInVec for ($($ident,)+) {}298299		impl<$($ident),+> AbiRead for ($($ident,)+)300		where301			$($ident: AbiRead + AbiType,)+302			($($ident,)+): AbiType,303		{304			fn abi_read(reader: &mut AbiReader) -> Result<($($ident,)+)> {305				let is_dynamic = <($($ident,)+)>::is_dynamic();306				let size = if !is_dynamic { Some(<($($ident,)+)>::size()) } else { None };307				let mut subresult = reader.subresult(size)?;308				Ok((309					$({310						let value = <$ident>::abi_read(&mut subresult)?;311						if !is_dynamic {subresult.seek(<$ident as AbiType>::size())};312						value313					},)+314				))315			}316		}317318		#[allow(non_snake_case)]319		impl<$($ident),+> AbiWrite for ($($ident,)+)320		where321			$($ident: AbiWrite + AbiType,)+322		{323			fn abi_write(&self, writer: &mut AbiWriter) {324				let ($($ident,)+) = self;325				if <Self as AbiType>::is_dynamic() {326					let mut sub = AbiWriter::new();327					$($ident.abi_write(&mut sub);)+328					writer.write_subresult(sub);329				} else {330					$($ident.abi_write(writer);)+331				}332			}333		}334	};335}336337impl_tuples! {A}338impl_tuples! {A B}339impl_tuples! {A B C}340impl_tuples! {A B C D}341impl_tuples! {A B C D E}342impl_tuples! {A B C D E F}343impl_tuples! {A B C D E F G}344impl_tuples! {A B C D E F G H}345impl_tuples! {A B C D E F G H I}346impl_tuples! {A B C D E F G H I J}
modifiedcrates/evm-coder/src/lib.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/lib.rs
+++ b/crates/evm-coder/src/lib.rs
@@ -93,6 +93,7 @@
 pub use evm_coder_procedural::solidity;
 /// See [`solidity_interface`]
 pub use evm_coder_procedural::weight;
+pub use evm_coder_procedural::AbiCoder;
 pub use sha3_const;
 
 /// Derives [`ToLog`] for enum
@@ -119,7 +120,6 @@
 
 	#[cfg(not(feature = "std"))]
 	use alloc::{vec::Vec};
-	use pallet_evm::account::CrossAccountId;
 	use primitive_types::{U256, H160, H256};
 
 	pub type address = H160;
@@ -185,73 +185,7 @@
 		#[must_use]
 		pub fn is_empty(&self) -> bool {
 			self.len() == 0
-		}
-	}
-
-	#[derive(Debug, Default)]
-	pub struct EthCrossAccount {
-		pub(crate) eth: address,
-		pub(crate) sub: uint256,
-	}
-
-	impl EthCrossAccount {
-		pub fn from_sub_cross_account<T>(cross_account_id: &T::CrossAccountId) -> Self
-		where
-			T: pallet_evm::Config,
-			T::AccountId: AsRef<[u8; 32]>,
-		{
-			if cross_account_id.is_canonical_substrate() {
-				Self {
-					eth: Default::default(),
-					sub: convert_cross_account_to_uint256::<T>(cross_account_id),
-				}
-			} else {
-				Self {
-					eth: *cross_account_id.as_eth(),
-					sub: Default::default(),
-				}
-			}
-		}
-
-		pub fn into_sub_cross_account<T>(&self) -> crate::execution::Result<T::CrossAccountId>
-		where
-			T: pallet_evm::Config,
-			T::AccountId: From<[u8; 32]>,
-		{
-			if self.eth == Default::default() && self.sub == Default::default() {
-				Err("All fields of cross account is zeroed".into())
-			} else if self.eth == Default::default() {
-				Ok(convert_uint256_to_cross_account::<T>(self.sub))
-			} else if self.sub == Default::default() {
-				Ok(T::CrossAccountId::from_eth(self.eth))
-			} else {
-				Err("All fields of cross account is non zeroed".into())
-			}
 		}
-	}
-
-	/// Convert `CrossAccountId` to `uint256`.
-	pub fn convert_cross_account_to_uint256<T: pallet_evm::Config>(
-		from: &T::CrossAccountId,
-	) -> uint256
-	where
-		T::AccountId: AsRef<[u8; 32]>,
-	{
-		let slice = from.as_sub().as_ref();
-		uint256::from_big_endian(slice)
-	}
-
-	/// Convert `uint256` to `CrossAccountId`.
-	pub fn convert_uint256_to_cross_account<T: pallet_evm::Config>(
-		from: uint256,
-	) -> T::CrossAccountId
-	where
-		T::AccountId: From<[u8; 32]>,
-	{
-		let mut new_admin_arr = [0_u8; 32];
-		from.to_big_endian(&mut new_admin_arr);
-		let account_id = T::AccountId::from(new_admin_arr);
-		T::CrossAccountId::from_sub(account_id)
 	}
 
 	#[derive(Debug, Default)]
modifiedcrates/evm-coder/src/solidity.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/solidity.rs
+++ b/crates/evm-coder/src/solidity.rs
@@ -145,7 +145,7 @@
 	}
 }
 
-mod sealed {
+pub mod sealed {
 	/// Not every type should be directly placed in vec.
 	/// Vec encoding is not memory efficient, as every item will be padded
 	/// to 32 bytes.
@@ -156,7 +156,6 @@
 impl sealed::CanBePlacedInVec for uint256 {}
 impl sealed::CanBePlacedInVec for string {}
 impl sealed::CanBePlacedInVec for address {}
-impl sealed::CanBePlacedInVec for EthCrossAccount {}
 impl sealed::CanBePlacedInVec for Property {}
 
 impl<T: SolidityTypeName + sealed::CanBePlacedInVec> SolidityTypeName for Vec<T> {
@@ -171,61 +170,6 @@
 		write!(writer, "new ")?;
 		T::solidity_name(writer, tc)?;
 		write!(writer, "[](0)")
-	}
-}
-
-impl SolidityTupleType for EthCrossAccount {
-	fn names(tc: &TypeCollector) -> Vec<string> {
-		let mut collected = Vec::with_capacity(Self::len());
-		{
-			let mut out = string::new();
-			address::solidity_name(&mut out, tc).expect("no fmt error");
-			collected.push(out);
-		}
-		{
-			let mut out = string::new();
-			uint256::solidity_name(&mut out, tc).expect("no fmt error");
-			collected.push(out);
-		}
-		collected
-	}
-
-	fn len() -> usize {
-		2
-	}
-}
-
-impl SolidityTypeName for EthCrossAccount {
-	fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
-		write!(writer, "{}", tc.collect_struct::<Self>())
-	}
-
-	fn is_simple() -> bool {
-		false
-	}
-
-	fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
-		write!(writer, "{}(", tc.collect_struct::<Self>())?;
-		address::solidity_default(writer, tc)?;
-		write!(writer, ",")?;
-		uint256::solidity_default(writer, tc)?;
-		write!(writer, ")")
-	}
-}
-
-impl StructCollect for EthCrossAccount {
-	fn name() -> String {
-		"EthCrossAccount".into()
-	}
-
-	fn declaration() -> String {
-		let mut str = String::new();
-		writeln!(str, "/// @dev Cross account struct").unwrap();
-		writeln!(str, "struct {} {{", Self::name()).unwrap();
-		writeln!(str, "\taddress eth;").unwrap();
-		writeln!(str, "\tuint256 sub;").unwrap();
-		writeln!(str, "}}").unwrap();
-		str
 	}
 }
 
modifiedpallets/common/src/erc.rsdiffbeforeafterboth
--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -16,6 +16,7 @@
 
 //! This module contains the implementation of pallet methods for evm.
 
+pub use pallet_evm::{PrecompileOutput, PrecompileResult, PrecompileHandle, account::CrossAccountId};
 use evm_coder::{
 	abi::AbiType,
 	solidity_interface, solidity, ToLog,
@@ -24,7 +25,6 @@
 	execution::{Result, Error},
 	weight,
 };
-pub use pallet_evm::{PrecompileOutput, PrecompileResult, PrecompileHandle, account::CrossAccountId};
 use pallet_evm_coder_substrate::dispatch_to_evm;
 use sp_std::vec::Vec;
 use up_data_structs::{
@@ -35,7 +35,8 @@
 
 use crate::{
 	Pallet, CollectionHandle, Config, CollectionProperties, SelfWeightOf,
-	eth::convert_cross_account_to_uint256, weights::WeightInfo,
+	eth::{EthCrossAccount, convert_cross_account_to_uint256},
+	weights::WeightInfo,
 };
 
 /// Events for ethereum collection helper.
modifiedpallets/common/src/eth.rsdiffbeforeafterboth
--- a/pallets/common/src/eth.rs
+++ b/pallets/common/src/eth.rs
@@ -16,7 +16,10 @@
 
 //! The module contains a number of functions for converting and checking ethereum identifiers.
 
-use evm_coder::types::{uint256, address};
+use evm_coder::{
+	AbiCoder,
+	types::{uint256, address},
+};
 pub use pallet_evm::{Config, account::CrossAccountId};
 use sp_core::H160;
 use up_data_structs::CollectionId;
@@ -109,3 +112,111 @@
 		Err("All fields of cross account is non zeroed".into())
 	}
 }
+
+#[derive(Debug, Default, AbiCoder)]
+pub struct EthCrossAccount {
+	pub(crate) eth: address,
+	pub(crate) sub: uint256,
+}
+
+impl EthCrossAccount {
+	pub fn from_sub_cross_account<T>(cross_account_id: &T::CrossAccountId) -> Self
+	where
+		T: pallet_evm::account::Config,
+		T::AccountId: AsRef<[u8; 32]>,
+	{
+		if cross_account_id.is_canonical_substrate() {
+			Self {
+				eth: Default::default(),
+				sub: convert_cross_account_to_uint256::<T>(cross_account_id),
+			}
+		} else {
+			Self {
+				eth: *cross_account_id.as_eth(),
+				sub: Default::default(),
+			}
+		}
+	}
+
+	pub fn into_sub_cross_account<T>(&self) -> evm_coder::execution::Result<T::CrossAccountId>
+	where
+		T: pallet_evm::account::Config,
+		T::AccountId: From<[u8; 32]>,
+	{
+		if self.eth == Default::default() && self.sub == Default::default() {
+			Err("All fields of cross account is zeroed".into())
+		} else if self.eth == Default::default() {
+			Ok(convert_uint256_to_cross_account::<T>(self.sub))
+		} else if self.sub == Default::default() {
+			Ok(T::CrossAccountId::from_eth(self.eth))
+		} else {
+			Err("All fields of cross account is non zeroed".into())
+		}
+	}
+}
+
+impl ::evm_coder::solidity::sealed::CanBePlacedInVec for EthCrossAccount {}
+impl ::evm_coder::solidity::SolidityTupleType for EthCrossAccount {
+	fn names(tc: &::evm_coder::solidity::TypeCollector) -> Vec<String> {
+		let mut collected =
+			Vec::with_capacity(<Self as ::evm_coder::solidity::SolidityTupleType>::len());
+		{
+			let mut out = String::new();
+			<address as ::evm_coder::solidity::SolidityTypeName>::solidity_name(&mut out, tc)
+				.expect("no fmt error");
+			collected.push(out);
+		}
+		{
+			let mut out = String::new();
+			<uint256 as ::evm_coder::solidity::SolidityTypeName>::solidity_name(&mut out, tc)
+				.expect("no fmt error");
+			collected.push(out);
+		}
+		collected
+	}
+
+	fn len() -> usize {
+		2
+	}
+}
+impl ::evm_coder::solidity::SolidityTypeName for EthCrossAccount {
+	fn solidity_name(
+		writer: &mut impl ::core::fmt::Write,
+		tc: &::evm_coder::solidity::TypeCollector,
+	) -> ::core::fmt::Result {
+		write!(writer, "{}", tc.collect_struct::<Self>())
+	}
+
+	fn is_simple() -> bool {
+		false
+	}
+
+	fn solidity_default(
+		writer: &mut impl ::core::fmt::Write,
+		tc: &::evm_coder::solidity::TypeCollector,
+	) -> ::core::fmt::Result {
+		write!(writer, "{}(", tc.collect_struct::<Self>())?;
+		address::solidity_default(writer, tc)?;
+		write!(writer, ",")?;
+		uint256::solidity_default(writer, tc)?;
+		write!(writer, ")")
+	}
+}
+
+impl ::evm_coder::solidity::StructCollect for EthCrossAccount {
+	fn name() -> String {
+		"EthCrossAccount".into()
+	}
+
+	fn declaration() -> String {
+		use std::fmt::Write;
+
+		let mut str = String::new();
+		writeln!(str, "/// @dev Cross account struct").unwrap();
+		writeln!(str, "struct {} {{", Self::name()).unwrap();
+		writeln!(str, "\taddress eth;").unwrap();
+		writeln!(str, "\tuint256 sub;").unwrap();
+		writeln!(str, "}}").unwrap();
+		str
+	}
+}
modifiedpallets/fungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/fungible/src/erc.rs
+++ b/pallets/fungible/src/erc.rs
@@ -24,12 +24,15 @@
 	weight,
 };
 use up_data_structs::CollectionMode;
-use pallet_common::erc::{CommonEvmHandler, PrecompileResult};
+use pallet_common::{
+	CollectionHandle,
+	erc::{CommonEvmHandler, PrecompileResult, CollectionCall},
+	eth::EthCrossAccount,
+};
 use sp_std::vec::Vec;
 use pallet_evm::{account::CrossAccountId, PrecompileHandle};
 use pallet_evm_coder_substrate::{call, dispatch_to_evm};
 use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};
-use pallet_common::{CollectionHandle, erc::CollectionCall};
 use sp_core::Get;
 
 use crate::{
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -36,8 +36,9 @@
 use pallet_evm_coder_substrate::dispatch_to_evm;
 use sp_std::vec::Vec;
 use pallet_common::{
+	CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations,
 	erc::{CommonEvmHandler, PrecompileResult, CollectionCall, static_property::key},
-	CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations,
+	eth::EthCrossAccount,
 };
 use pallet_evm::{account::CrossAccountId, PrecompileHandle};
 use pallet_evm_coder_substrate::call;
modifiedpallets/refungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -33,6 +33,7 @@
 use pallet_common::{
 	CollectionHandle, CollectionPropertyPermissions,
 	erc::{CommonEvmHandler, CollectionCall, static_property::key},
+	eth::EthCrossAccount,
 	CommonCollectionOperations,
 };
 use pallet_evm::{account::CrossAccountId, PrecompileHandle};