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;26pub use up_evm_mapping::EvmBackwardsAddressMapping;2728pub trait CrossAccountId<AccountId>:29 Encode + EncodeLike + Decode + TypeInfo + MaxEncodedLen + Clone + PartialEq + Ord + core::fmt::Debug303132{33 fn as_sub(&self) -> &AccountId;34 fn as_eth(&self) -> &H160;3536 fn from_sub(account: AccountId) -> Self;37 fn from_eth(account: H160) -> Self;3839 fn conv_eq(&self, other: &Self) -> bool;40}4142#[derive(Encode, Decode, Serialize, Deserialize, TypeInfo, MaxEncodedLen)]43#[serde(rename_all = "camelCase")]44enum BasicCrossAccountIdRepr<AccountId> {45 Substrate(AccountId),46 Ethereum(H160),47}4849#[derive(PartialEq, Eq)]50pub struct BasicCrossAccountId<T: Config> {51 52 from_ethereum: bool,53 substrate: T::AccountId,54 ethereum: H160,55}5657impl<T: Config> MaxEncodedLen for BasicCrossAccountId<T> {58 fn max_encoded_len() -> usize {59 <BasicCrossAccountIdRepr<T::AccountId>>::max_encoded_len()60 }61}6263impl<T: Config> TypeInfo for BasicCrossAccountId<T> {64 type Identity = Self;6566 fn type_info() -> Type {67 <BasicCrossAccountIdRepr<T::AccountId>>::type_info()68 }69}7071impl<T: Config> core::fmt::Debug for BasicCrossAccountId<T> {72 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {73 if self.from_ethereum {74 fmt.debug_tuple("CrossAccountId::Ethereum")75 .field(&self.ethereum)76 .finish()77 } else {78 fmt.debug_tuple("CrossAccountId::Substrate")79 .field(&self.substrate)80 .finish()81 }82 }83}8485impl<T: Config> PartialOrd for BasicCrossAccountId<T> {86 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {87 Some(self.substrate.cmp(&other.substrate))88 }89}9091impl<T: Config> Ord for BasicCrossAccountId<T> {92 fn cmp(&self, other: &Self) -> Ordering {93 self.partial_cmp(other)94 .expect("substrate account is total ordered")95 }96}9798impl<T: Config> Clone for BasicCrossAccountId<T> {99 fn clone(&self) -> Self {100 Self {101 from_ethereum: self.from_ethereum,102 substrate: self.substrate.clone(),103 ethereum: self.ethereum,104 }105 }106}107impl<T: Config> Encode for BasicCrossAccountId<T> {108 fn encode(&self) -> Vec<u8> {109 BasicCrossAccountIdRepr::from(self.clone()).encode()110 }111}112impl<T: Config> EncodeLike for BasicCrossAccountId<T> {}113impl<T: Config> Decode for BasicCrossAccountId<T> {114 fn decode<I>(input: &mut I) -> Result<Self, codec::Error>115 where116 I: codec::Input,117 {118 Ok(BasicCrossAccountIdRepr::decode(input)?.into())119 }120}121impl<T> Serialize for BasicCrossAccountId<T>122where123 T: Config,124 T::AccountId: Serialize,125{126 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>127 where128 S: serde::Serializer,129 {130 let repr = BasicCrossAccountIdRepr::from(self.clone());131 (&repr).serialize(serializer)132 }133}134impl<'de, T> Deserialize<'de> for BasicCrossAccountId<T>135where136 T: Config,137 T::AccountId: Deserialize<'de>,138{139 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>140 where141 D: serde::Deserializer<'de>,142 {143 Ok(BasicCrossAccountIdRepr::deserialize(deserializer)?.into())144 }145}146impl<T: Config> CrossAccountId<T::AccountId> for BasicCrossAccountId<T> {147 fn as_sub(&self) -> &T::AccountId {148 &self.substrate149 }150 fn as_eth(&self) -> &H160 {151 &self.ethereum152 }153 fn from_sub(substrate: T::AccountId) -> Self {154 Self {155 ethereum: T::EvmBackwardsAddressMapping::from_account_id(substrate.clone()),156 substrate,157 from_ethereum: false,158 }159 }160 fn from_eth(ethereum: H160) -> Self {161 Self {162 ethereum,163 substrate: T::EvmAddressMapping::into_account_id(ethereum),164 from_ethereum: true,165 }166 }167 fn conv_eq(&self, other: &Self) -> bool {168 if self.from_ethereum == other.from_ethereum {169 self.substrate == other.substrate && self.ethereum == other.ethereum170 } else if self.from_ethereum {171 172 self.substrate == other.substrate173 } else {174 self.ethereum == other.ethereum175 }176 }177}178impl<T: Config> From<BasicCrossAccountIdRepr<T::AccountId>> for BasicCrossAccountId<T> {179 fn from(repr: BasicCrossAccountIdRepr<T::AccountId>) -> Self {180 match repr {181 BasicCrossAccountIdRepr::Substrate(s) => Self::from_sub(s),182 BasicCrossAccountIdRepr::Ethereum(e) => Self::from_eth(e),183 }184 }185}186impl<T: Config> From<BasicCrossAccountId<T>> for BasicCrossAccountIdRepr<T::AccountId> {187 fn from(v: BasicCrossAccountId<T>) -> Self {188 if v.from_ethereum {189 BasicCrossAccountIdRepr::Ethereum(*v.as_eth())190 } else {191 BasicCrossAccountIdRepr::Substrate(v.as_sub().clone())192 }193 }194}