12345678910111213141516171819use sp_std::{vec, vec::Vec};20use evm_coder::{21 AbiCoder,22 types::{uint256, address},23};24pub use pallet_evm::{Config, account::CrossAccountId};25use sp_core::H160;26use up_data_structs::CollectionId;27282930const ETH_COLLECTION_PREFIX: [u8; 16] = [31 0x17, 0xc4, 0xe6, 0x45, 0x3c, 0xc4, 0x9a, 0xaa, 0xae, 0xac, 0xa8, 0x94, 0xe6, 0xd9, 0x68, 0x3e,32];333435pub fn map_eth_to_id(eth: &H160) -> Option<CollectionId> {36 if eth[0..16] != ETH_COLLECTION_PREFIX {37 return None;38 }39 let mut id_bytes = [0; 4];40 id_bytes.copy_from_slice(ð[16..20]);41 Some(CollectionId(u32::from_be_bytes(id_bytes)))42}434445pub fn collection_id_to_address(id: CollectionId) -> H160 {46 let mut out = [0; 20];47 out[0..16].copy_from_slice(Ð_COLLECTION_PREFIX);48 out[16..20].copy_from_slice(&u32::to_be_bytes(id.0));49 H160(out)50}515253pub fn is_collection(address: &H160) -> bool {54 address[0..16] == ETH_COLLECTION_PREFIX55}565758pub fn convert_uint256_to_cross_account<T: Config>(from: uint256) -> T::CrossAccountId59where60 T::AccountId: From<[u8; 32]>,61{62 let mut new_admin_arr = [0_u8; 32];63 from.to_big_endian(&mut new_admin_arr);64 let account_id = T::AccountId::from(new_admin_arr);65 T::CrossAccountId::from_sub(account_id)66}676869#[derive(Debug, Default, AbiCoder)]70pub struct EthCrossAccount {71 pub(crate) eth: address,72 pub(crate) sub: uint256,73}7475impl EthCrossAccount {76 77 pub fn from_sub_cross_account<T>(cross_account_id: &T::CrossAccountId) -> Self78 where79 T: pallet_evm::Config,80 T::AccountId: AsRef<[u8; 32]>,81 {82 if cross_account_id.is_canonical_substrate() {83 Self::from_sub::<T>(cross_account_id.as_sub())84 } else {85 Self {86 eth: *cross_account_id.as_eth(),87 sub: Default::default(),88 }89 }90 }91 92 pub fn from_sub<T>(account_id: &T::AccountId) -> Self93 where94 T: pallet_evm::Config,95 T::AccountId: AsRef<[u8; 32]>,96 {97 Self {98 eth: Default::default(),99 sub: uint256::from_big_endian(account_id.as_ref()),100 }101 }102 103 pub fn into_sub_cross_account<T>(&self) -> evm_coder::execution::Result<T::CrossAccountId>104 where105 T: pallet_evm::Config,106 T::AccountId: From<[u8; 32]>,107 {108 if self.eth == Default::default() && self.sub == Default::default() {109 Err("All fields of cross account is zeroed".into())110 } else if self.eth == Default::default() {111 Ok(convert_uint256_to_cross_account::<T>(self.sub))112 } else if self.sub == Default::default() {113 Ok(T::CrossAccountId::from_eth(self.eth))114 } else {115 Err("All fields of cross account is non zeroed".into())116 }117 }118}119120121#[derive(Debug, Default, AbiCoder)]122pub struct Property {123 124 pub key: evm_coder::types::string,125 126 pub value: evm_coder::types::bytes,127}128129130#[derive(Debug, Default, Clone, Copy, AbiCoder)]131#[repr(u8)]132pub enum CollectionLimits {133 134 #[default]135 AccountTokenOwnership,136137 138 SponsoredDataSize,139140 141 SponsoredDataRateLimit,142143 144 TokenLimit,145146 147 SponsorTransferTimeout,148149 150 SponsorApproveTimeout,151152 153 OwnerCanTransfer,154155 156 OwnerCanDestroy,157158 159 TransferEnabled,160}161162#[derive(Default, Debug, Clone, Copy, AbiCoder)]163#[repr(u8)]164pub enum CollectionPermissions {165 166 #[default]167 TokenOwner,168169 170 CollectionAdmin,171}172173174#[derive(AbiCoder, Copy, Clone, Default, Debug)]175#[repr(u8)]176pub enum EthTokenPermissions {177 178 #[default]179 Mutable,180181 182 TokenOwner,183184 185 CollectionAdmin,186}187188189#[derive(Debug, Default, AbiCoder)]190pub struct PropertyPermission {191 192 code: EthTokenPermissions,193 194 value: bool,195}196197impl PropertyPermission {198 pub fn into_vec(pp: up_data_structs::PropertyPermission) -> Vec<Self> {199 vec![200 PropertyPermission {201 code: EthTokenPermissions::Mutable,202 value: pp.mutable,203 },204 PropertyPermission {205 code: EthTokenPermissions::TokenOwner,206 value: pp.token_owner,207 },208 PropertyPermission {209 code: EthTokenPermissions::CollectionAdmin,210 value: pp.collection_admin,211 },212 ]213 }214215 pub fn from_vec(permission: Vec<Self>) -> up_data_structs::PropertyPermission {216 let mut token_permission = up_data_structs::PropertyPermission::default();217218 for PropertyPermission { code, value } in permission {219 match code {220 EthTokenPermissions::Mutable => token_permission.mutable = value,221 EthTokenPermissions::TokenOwner => token_permission.token_owner = value,222 EthTokenPermissions::CollectionAdmin => token_permission.collection_admin = value,223 }224 }225 token_permission226 }227}228229230#[derive(Debug, Default, AbiCoder)]231pub struct TokenPropertyPermission {232 233 key: evm_coder::types::string,234 235 permissions: Vec<PropertyPermission>,236}237238impl239 From<(240 up_data_structs::PropertyKey,241 up_data_structs::PropertyPermission,242 )> for TokenPropertyPermission243{244 fn from(245 value: (246 up_data_structs::PropertyKey,247 up_data_structs::PropertyPermission,248 ),249 ) -> Self {250 let (key, permission) = value;251 let key = evm_coder::types::string::from_utf8(key.into_inner())252 .expect("Stored key must be valid");253 let permissions = PropertyPermission::into_vec(permission);254 Self { key, permissions }255 }256}257258impl TokenPropertyPermission {259 pub fn into_property_key_permissions(260 permissions: Vec<TokenPropertyPermission>,261 ) -> evm_coder::execution::Result<Vec<up_data_structs::PropertyKeyPermission>> {262 let mut perms = Vec::new();263264 for TokenPropertyPermission { key, permissions } in permissions {265 if permissions.len() > <EthTokenPermissions as evm_coder::abi::AbiType>::FIELDS_COUNT {266 return Err(alloc::format!(267 "Actual number of fields {} for {}, which exceeds the maximum value of {}",268 permissions.len(),269 stringify!(EthTokenPermissions),270 <EthTokenPermissions as evm_coder::abi::AbiType>::FIELDS_COUNT271 )272 .as_str()273 .into());274 }275276 let token_permission = PropertyPermission::from_vec(permissions);277278 perms.push(up_data_structs::PropertyKeyPermission {279 key: key.into_bytes().try_into().map_err(|_| "too long key")?,280 permission: token_permission,281 });282 }283 Ok(perms)284 }285}