git.delta.rocks / unique-network / refs/commits / 3fb62366cc89

difftreelog

source

pallets/nft/src/eth/account.rs3.5 KiBsourcehistory
1use crate::Config;2use codec::{Encode, EncodeLike, Decode};3use sp_core::crypto::AccountId32;4use primitive_types::H160;5use core::cmp::Ordering;6use serde::{Serialize, Deserialize};7use pallet_evm::AddressMapping;8use sp_std::vec::Vec;9use sp_std::clone::Clone;1011pub trait CrossAccountId<AccountId>:12	Encode + EncodeLike + Decode + Clone + PartialEq + Ord + core::fmt::Debug13// +14// Serialize + Deserialize<'static>15{16	fn as_sub(&self) -> &AccountId;17	fn as_eth(&self) -> &H160;1819	fn from_sub(account: AccountId) -> Self;20	fn from_eth(account: H160) -> Self;21}2223#[derive(Eq, Serialize, Deserialize)]24pub struct BasicCrossAccountId<T: Config> {25	/// If true - then ethereum is canonical encoding26	from_ethereum: bool,27	substrate: T::AccountId,28	ethereum: H160,29}3031impl<T: Config> core::fmt::Debug for BasicCrossAccountId<T> {32	fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {33		if self.from_ethereum {34			fmt.debug_tuple("CrossAccountId::Ethereum")35				.field(&self.ethereum)36				.finish()37		} else {38			fmt.debug_tuple("CrossAccountId::Substrate")39				.field(&self.substrate)40				.finish()41		}42	}43}4445impl<T: Config> PartialOrd for BasicCrossAccountId<T> {46	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {47		Some(self.substrate.cmp(&other.substrate))48	}49}5051impl<T: Config> Ord for BasicCrossAccountId<T> {52	fn cmp(&self, other: &Self) -> Ordering {53		self.partial_cmp(other)54			.expect("substrate account is total ordered")55	}56}5758impl<T: Config> PartialEq for BasicCrossAccountId<T> {59	fn eq(&self, other: &Self) -> bool {60		if self.from_ethereum == other.from_ethereum {61			self.substrate == other.substrate && self.ethereum == other.ethereum62		} else if self.from_ethereum {63			// ethereum is canonical encoding, but we need to compare derived address64			self.substrate == other.substrate65		} else {66			self.ethereum == other.ethereum67		}68	}69}70impl<T: Config> Clone for BasicCrossAccountId<T> {71	fn clone(&self) -> Self {72		Self {73			from_ethereum: self.from_ethereum,74			substrate: self.substrate.clone(),75			ethereum: self.ethereum,76		}77	}78}79impl<T: Config> Encode for BasicCrossAccountId<T> {80	fn encode(&self) -> Vec<u8> {81		let as_result = if !self.from_ethereum {82			Ok(self.substrate.clone())83		} else {84			Err(self.ethereum)85		};86		as_result.encode()87	}88}89impl<T: Config> EncodeLike for BasicCrossAccountId<T> {}90impl<T: Config> Decode for BasicCrossAccountId<T> {91	fn decode<I>(input: &mut I) -> Result<Self, codec::Error>92	where93		I: codec::Input,94	{95		Ok(match <Result<T::AccountId, H160>>::decode(input)? {96			Ok(s) => Self::from_sub(s),97			Err(e) => Self::from_eth(e),98		})99	}100}101impl<T: Config> CrossAccountId<T::AccountId> for BasicCrossAccountId<T> {102	fn as_sub(&self) -> &T::AccountId {103		&self.substrate104	}105	fn as_eth(&self) -> &H160 {106		&self.ethereum107	}108	fn from_sub(substrate: T::AccountId) -> Self {109		Self {110			ethereum: T::EvmBackwardsAddressMapping::from_account_id(substrate.clone()),111			substrate,112			from_ethereum: false,113		}114	}115	fn from_eth(ethereum: H160) -> Self {116		Self {117			ethereum,118			substrate: T::EvmAddressMapping::into_account_id(ethereum),119			from_ethereum: true,120		}121	}122}123124pub trait EvmBackwardsAddressMapping<AccountId> {125	fn from_account_id(account_id: AccountId) -> H160;126}127128/// Should have same mapping as EnsureAddressTruncated129pub struct MapBackwardsAddressTruncated;130impl EvmBackwardsAddressMapping<AccountId32> for MapBackwardsAddressTruncated {131	fn from_account_id(account_id: AccountId32) -> H160 {132		let mut out = [0; 20];133		out.copy_from_slice(&(account_id.as_ref() as &[u8])[0..20]);134		H160(out)135	}136}