1234567891011121314151617use crate::Config;18use codec::{Encode, EncodeLike, Decode, MaxEncodedLen};19use sp_core::H160;20use scale_info::{Type, TypeInfo};21use core::cmp::Ordering;22use serde::{Serialize, Deserialize};23use pallet_evm::AddressMapping;24use sp_std::vec::Vec;25use sp_std::clone::Clone;2627pub use up_evm_mapping::EvmBackwardsAddressMapping;2829pub trait CrossAccountId<AccountId>:30 Encode + EncodeLike + Decode + TypeInfo + MaxEncodedLen + Clone + PartialEq + Ord + core::fmt::Debug313233{34 fn as_sub(&self) -> &AccountId;35 fn as_eth(&self) -> &H160;3637 fn from_sub(account: AccountId) -> Self;38 fn from_eth(account: H160) -> Self;3940 fn conv_eq(&self, other: &Self) -> bool;41}4243#[derive(Encode, Decode, Serialize, Deserialize, TypeInfo, MaxEncodedLen)]44#[serde(rename_all = "camelCase")]45enum BasicCrossAccountIdRepr<AccountId> {46 Substrate(AccountId),47 Ethereum(H160),48}4950#[derive(PartialEq, Eq)]51pub struct BasicCrossAccountId<T: Config> {52 53 from_ethereum: bool,54 substrate: T::AccountId,55 ethereum: H160,56}5758impl<T: Config> MaxEncodedLen for BasicCrossAccountId<T> {59 fn max_encoded_len() -> usize {60 <BasicCrossAccountIdRepr<T::AccountId>>::max_encoded_len()61 }62}6364impl<T: Config> TypeInfo for BasicCrossAccountId<T> {65 type Identity = Self;6667 fn type_info() -> Type {68 <BasicCrossAccountIdRepr<T::AccountId>>::type_info()69 }70}7172impl<T: Config> core::fmt::Debug for BasicCrossAccountId<T> {73 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {74 if self.from_ethereum {75 fmt.debug_tuple("CrossAccountId::Ethereum")76 .field(&self.ethereum)77 .finish()78 } else {79 fmt.debug_tuple("CrossAccountId::Substrate")80 .field(&self.substrate)81 .finish()82 }83 }84}8586impl<T: Config> PartialOrd for BasicCrossAccountId<T> {87 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {88 Some(self.substrate.cmp(&other.substrate))89 }90}9192impl<T: Config> Ord for BasicCrossAccountId<T> {93 fn cmp(&self, other: &Self) -> Ordering {94 self.partial_cmp(other)95 .expect("substrate account is total ordered")96 }97}9899impl<T: Config> Clone for BasicCrossAccountId<T> {100 fn clone(&self) -> Self {101 Self {102 from_ethereum: self.from_ethereum,103 substrate: self.substrate.clone(),104 ethereum: self.ethereum,105 }106 }107}108impl<T: Config> Encode for BasicCrossAccountId<T> {109 fn encode(&self) -> Vec<u8> {110 BasicCrossAccountIdRepr::from(self.clone()).encode()111 }112}113impl<T: Config> EncodeLike for BasicCrossAccountId<T> {}114impl<T: Config> Decode for BasicCrossAccountId<T> {115 fn decode<I>(input: &mut I) -> Result<Self, codec::Error>116 where117 I: codec::Input,118 {119 Ok(BasicCrossAccountIdRepr::decode(input)?.into())120 }121}122impl<T> Serialize for BasicCrossAccountId<T>123where124 T: Config,125 T::AccountId: Serialize,126{127 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>128 where129 S: serde::Serializer,130 {131 let repr = BasicCrossAccountIdRepr::from(self.clone());132 (&repr).serialize(serializer)133 }134}135impl<'de, T> Deserialize<'de> for BasicCrossAccountId<T>136where137 T: Config,138 T::AccountId: Deserialize<'de>,139{140 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>141 where142 D: serde::Deserializer<'de>,143 {144 Ok(BasicCrossAccountIdRepr::deserialize(deserializer)?.into())145 }146}147impl<T: Config> CrossAccountId<T::AccountId> for BasicCrossAccountId<T> {148 fn as_sub(&self) -> &T::AccountId {149 &self.substrate150 }151 fn as_eth(&self) -> &H160 {152 &self.ethereum153 }154 fn from_sub(substrate: T::AccountId) -> Self {155 Self {156 ethereum: T::EvmBackwardsAddressMapping::from_account_id(substrate.clone()),157 substrate,158 from_ethereum: false,159 }160 }161 fn from_eth(ethereum: H160) -> Self {162 Self {163 ethereum,164 substrate: T::EvmAddressMapping::into_account_id(ethereum),165 from_ethereum: true,166 }167 }168 fn conv_eq(&self, other: &Self) -> bool {169 if self.from_ethereum == other.from_ethereum {170 self.substrate == other.substrate && self.ethereum == other.ethereum171 } else if self.from_ethereum {172 173 self.substrate == other.substrate174 } else {175 self.ethereum == other.ethereum176 }177 }178}179impl<T: Config> From<BasicCrossAccountIdRepr<T::AccountId>> for BasicCrossAccountId<T> {180 fn from(repr: BasicCrossAccountIdRepr<T::AccountId>) -> Self {181 match repr {182 BasicCrossAccountIdRepr::Substrate(s) => Self::from_sub(s),183 BasicCrossAccountIdRepr::Ethereum(e) => Self::from_eth(e),184 }185 }186}187impl<T: Config> From<BasicCrossAccountId<T>> for BasicCrossAccountIdRepr<T::AccountId> {188 fn from(v: BasicCrossAccountId<T>) -> Self {189 if v.from_ethereum {190 BasicCrossAccountIdRepr::Ethereum(*v.as_eth())191 } else {192 BasicCrossAccountIdRepr::Substrate(v.as_sub().clone())193 }194 }195}