12345678910111213141516171819use core::marker::PhantomData;2021use sp_core::H160;2223use crate::{CollectionId, TokenId};24use pallet_evm::account::CrossAccountId;252627pub trait TokenAddressMapping<Address> {28 29 fn token_to_address(collection: CollectionId, token: TokenId) -> Address;3031 32 fn address_to_token(address: &Address) -> Option<(CollectionId, TokenId)>;3334 35 fn is_token_address(address: &Address) -> bool;36}373839pub struct EvmTokenAddressMapping;404142const ETH_COLLECTION_TOKEN_PREFIX: [u8; 12] = [43 0xf8, 0x23, 0x8c, 0xcf, 0xff, 0x8e, 0xd8, 0x87, 0x46, 0x3f, 0xd5, 0xe0,44];4546impl TokenAddressMapping<H160> for EvmTokenAddressMapping {47 fn token_to_address(collection: CollectionId, token: TokenId) -> H160 {48 let mut out = [0; 20];49 out[0..12].copy_from_slice(Ð_COLLECTION_TOKEN_PREFIX);50 out[12..16].copy_from_slice(&u32::to_be_bytes(collection.0));51 out[16..20].copy_from_slice(&u32::to_be_bytes(token.0));52 H160(out)53 }5455 fn address_to_token(eth: &H160) -> Option<(CollectionId, TokenId)> {56 if eth[0..12] != ETH_COLLECTION_TOKEN_PREFIX {57 return None;58 }59 let mut id_bytes = [0; 4];60 let mut token_id_bytes = [0; 4];61 id_bytes.copy_from_slice(ð[12..16]);62 token_id_bytes.copy_from_slice(ð[16..20]);63 Some((64 CollectionId(u32::from_be_bytes(id_bytes)),65 TokenId(u32::from_be_bytes(token_id_bytes)),66 ))67 }6869 fn is_token_address(address: &H160) -> bool {70 address[0..12] == ETH_COLLECTION_TOKEN_PREFIX71 }72}737475pub struct CrossTokenAddressMapping<A>(PhantomData<A>);7677impl<A, C: CrossAccountId<A>> TokenAddressMapping<C> for CrossTokenAddressMapping<A> {78 fn token_to_address(collection: CollectionId, token: TokenId) -> C {79 C::from_eth(EvmTokenAddressMapping::token_to_address(collection, token))80 }8182 fn address_to_token(address: &C) -> Option<(CollectionId, TokenId)> {83 EvmTokenAddressMapping::address_to_token(address.as_eth())84 }8586 fn is_token_address(address: &C) -> bool {87 EvmTokenAddressMapping::is_token_address(address.as_eth())88 }89}