difftreelog
refactor Make implementations of Abi* for EthCrossAccount via AbiCoder macro
in: master
9 files changed
.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
crates/evm-coder/src/abi/impls.rsdiffbeforeafterboth1use 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}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 Property {}124125impl AbiType for Property {126 const SIGNATURE: SignatureUnit = make_signature!(new fixed("(string,bytes)"));127128 fn is_dynamic() -> bool {129 string::is_dynamic() || bytes::is_dynamic()130 }131132 fn size() -> usize {133 <string as AbiType>::size() + <bytes as AbiType>::size()134 }135}136137impl AbiRead for Property {138 fn abi_read(reader: &mut AbiReader) -> Result<Property> {139 let size = if !Property::is_dynamic() {140 Some(<Property as AbiType>::size())141 } else {142 None143 };144 let mut subresult = reader.subresult(size)?;145 let key = <string>::abi_read(&mut subresult)?;146 let value = <bytes>::abi_read(&mut subresult)?;147148 Ok(Property { key, value })149 }150}151152impl AbiWrite for Property {153 fn abi_write(&self, writer: &mut AbiWriter) {154 (&self.key, &self.value).abi_write(writer);155 }156}157158macro_rules! impl_abi_writeable {159 ($ty:ty, $method:ident) => {160 impl AbiWrite for $ty {161 fn abi_write(&self, writer: &mut AbiWriter) {162 writer.$method(&self)163 }164 }165 };166}167168impl_abi_writeable!(u8, uint8);169impl_abi_writeable!(u32, uint32);170impl_abi_writeable!(u128, uint128);171impl_abi_writeable!(U256, uint256);172impl_abi_writeable!(H160, address);173impl_abi_writeable!(bool, bool);174impl_abi_writeable!(&str, string);175176impl AbiWrite for string {177 fn abi_write(&self, writer: &mut AbiWriter) {178 writer.string(self)179 }180}181182impl AbiWrite for bytes {183 fn abi_write(&self, writer: &mut AbiWriter) {184 writer.bytes(self.0.as_slice())185 }186}187188impl<T: AbiWrite + AbiType> AbiWrite for Vec<T> {189 fn abi_write(&self, writer: &mut AbiWriter) {190 let is_dynamic = T::is_dynamic();191 let mut sub = if is_dynamic {192 AbiWriter::new_dynamic(is_dynamic)193 } else {194 AbiWriter::new()195 };196197 // Write items count198 (self.len() as u32).abi_write(&mut sub);199200 for item in self {201 item.abi_write(&mut sub);202 }203 writer.write_subresult(sub);204 }205}206207impl AbiWrite for () {208 fn abi_write(&self, _writer: &mut AbiWriter) {}209}210211/// This particular AbiWrite implementation should be split to another trait,212/// which only implements `to_result`, but due to lack of specialization feature213/// in stable Rust, we can't have blanket impl of this trait `for T where T: AbiWrite`,214/// so here we abusing default trait methods for it215impl<T: AbiWrite> AbiWrite for ResultWithPostInfo<T> {216 fn abi_write(&self, _writer: &mut AbiWriter) {217 debug_assert!(false, "shouldn't be called, see comment")218 }219 fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {220 match self {221 Ok(v) => Ok(WithPostDispatchInfo {222 post_info: v.post_info.clone(),223 data: {224 let mut out = AbiWriter::new();225 v.data.abi_write(&mut out);226 out227 },228 }),229 Err(e) => Err(e.clone()),230 }231 }232}233234macro_rules! impl_tuples {235 ($($ident:ident)+) => {236 impl<$($ident: AbiType,)+> AbiType for ($($ident,)+)237 where238 $(239 $ident: AbiType,240 )+241 {242 const SIGNATURE: SignatureUnit = make_signature!(243 new fixed("(")244 $(nameof(<$ident>::SIGNATURE) fixed(","))+245 shift_left(1)246 fixed(")")247 );248249 fn is_dynamic() -> bool {250 false251 $(252 || <$ident>::is_dynamic()253 )*254 }255256 fn size() -> usize {257 0 $(+ <$ident>::size())+258 }259 }260261 impl<$($ident),+> sealed::CanBePlacedInVec for ($($ident,)+) {}262263 impl<$($ident),+> AbiRead for ($($ident,)+)264 where265 $($ident: AbiRead + AbiType,)+266 ($($ident,)+): AbiType,267 {268 fn abi_read(reader: &mut AbiReader) -> Result<($($ident,)+)> {269 let is_dynamic = <($($ident,)+)>::is_dynamic();270 let size = if !is_dynamic { Some(<($($ident,)+)>::size()) } else { None };271 let mut subresult = reader.subresult(size)?;272 Ok((273 $({274 let value = <$ident>::abi_read(&mut subresult)?;275 if !is_dynamic {subresult.seek(<$ident as AbiType>::size())};276 value277 },)+278 ))279 }280 }281282 #[allow(non_snake_case)]283 impl<$($ident),+> AbiWrite for ($($ident,)+)284 where285 $($ident: AbiWrite + AbiType,)+286 {287 fn abi_write(&self, writer: &mut AbiWriter) {288 let ($($ident,)+) = self;289 if <Self as AbiType>::is_dynamic() {290 let mut sub = AbiWriter::new();291 $($ident.abi_write(&mut sub);)+292 writer.write_subresult(sub);293 } else {294 $($ident.abi_write(writer);)+295 }296 }297 }298 };299}300301impl_tuples! {A}302impl_tuples! {A B}303impl_tuples! {A B C}304impl_tuples! {A B C D}305impl_tuples! {A B C D E}306impl_tuples! {A B C D E F}307impl_tuples! {A B C D E F G}308impl_tuples! {A B C D E F G H}309impl_tuples! {A B C D E F G H I}310impl_tuples! {A B C D E F G H I J}crates/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)]
crates/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
}
}
pallets/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.
pallets/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
+ }
+}
pallets/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::{
pallets/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;
pallets/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};