12345678910111213141516171819use alloc::format;20use sp_std::{vec, vec::Vec};21use evm_coder::{AbiCoder, types::Address};22pub use pallet_evm::{Config, account::CrossAccountId};23use sp_core::{H160, U256};24use up_data_structs::CollectionId;25262728const ETH_COLLECTION_PREFIX: [u8; 16] = [29 0x17, 0xc4, 0xe6, 0x45, 0x3c, 0xc4, 0x9a, 0xaa, 0xae, 0xac, 0xa8, 0x94, 0xe6, 0xd9, 0x68, 0x3e,30];313233pub fn map_eth_to_id(eth: &Address) -> Option<CollectionId> {34 if eth[0..16] != ETH_COLLECTION_PREFIX {35 return None;36 }37 let mut id_bytes = [0; 4];38 id_bytes.copy_from_slice(ð[16..20]);39 Some(CollectionId(u32::from_be_bytes(id_bytes)))40}414243pub fn collection_id_to_address(id: CollectionId) -> Address {44 let mut out = [0; 20];45 out[0..16].copy_from_slice(Ð_COLLECTION_PREFIX);46 out[16..20].copy_from_slice(&u32::to_be_bytes(id.0));47 H160(out)48}495051pub fn is_collection(address: &Address) -> bool {52 address[0..16] == ETH_COLLECTION_PREFIX53}545556pub fn convert_uint256_to_cross_account<T: Config>(from: U256) -> T::CrossAccountId57where58 T::AccountId: From<[u8; 32]>,59{60 let mut new_admin_arr = [0_u8; 32];61 from.to_big_endian(&mut new_admin_arr);62 let account_id = T::AccountId::from(new_admin_arr);63 T::CrossAccountId::from_sub(account_id)64}656667#[derive(Debug, Default, AbiCoder)]68pub struct CrossAddress {69 pub(crate) eth: Address,70 pub(crate) sub: U256,71}7273impl CrossAddress {74 75 pub fn from_sub_cross_account<T>(cross_account_id: &T::CrossAccountId) -> Self76 where77 T: pallet_evm::Config,78 T::AccountId: AsRef<[u8; 32]>,79 {80 if cross_account_id.is_canonical_substrate() {81 Self::from_sub::<T>(cross_account_id.as_sub())82 } else {83 Self::from_eth(*cross_account_id.as_eth())84 }85 }86 87 pub fn from_sub<T>(account_id: &T::AccountId) -> Self88 where89 T: pallet_evm::Config,90 T::AccountId: AsRef<[u8; 32]>,91 {92 Self {93 eth: Default::default(),94 sub: U256::from_big_endian(account_id.as_ref()),95 }96 }97 98 pub fn from_eth(address: Address) -> Self {99 Self {100 eth: address,101 sub: Default::default(),102 }103 }104 105 pub fn into_sub_cross_account<T>(&self) -> evm_coder::execution::Result<T::CrossAccountId>106 where107 T: pallet_evm::Config,108 T::AccountId: From<[u8; 32]>,109 {110 if self.eth == Default::default() && self.sub == Default::default() {111 Err("All fields of cross account is zeroed".into())112 } else if self.eth == Default::default() {113 Ok(convert_uint256_to_cross_account::<T>(self.sub))114 } else if self.sub == Default::default() {115 Ok(T::CrossAccountId::from_eth(self.eth))116 } else {117 Err("All fields of cross account is non zeroed".into())118 }119 }120}121122123#[derive(Debug, Default, AbiCoder)]124pub struct Property {125 key: evm_coder::types::String,126 value: evm_coder::types::Bytes,127}128129impl TryFrom<up_data_structs::Property> for Property {130 type Error = evm_coder::execution::Error;131132 fn try_from(from: up_data_structs::Property) -> Result<Self, Self::Error> {133 let key = evm_coder::types::String::from_utf8(from.key.into())134 .map_err(|e| Self::Error::Revert(format!("utf8 conversion error: {}", e)))?;135 let value = evm_coder::types::Bytes(from.value.to_vec());136 Ok(Property { key, value })137 }138}139140impl TryInto<up_data_structs::Property> for Property {141 type Error = evm_coder::execution::Error;142143 fn try_into(self) -> Result<up_data_structs::Property, Self::Error> {144 let key = <Vec<u8>>::from(self.key)145 .try_into()146 .map_err(|_| "key too large")?;147148 let value = self.value.0.try_into().map_err(|_| "value too large")?;149150 Ok(up_data_structs::Property { key, value })151 }152}153154155#[derive(Debug, Default, Clone, Copy, AbiCoder)]156#[repr(u8)]157pub enum CollectionLimitField {158 159 #[default]160 AccountTokenOwnership,161162 163 SponsoredDataSize,164165 166 SponsoredDataRateLimit,167168 169 TokenLimit,170171 172 SponsorTransferTimeout,173174 175 SponsorApproveTimeout,176177 178 OwnerCanTransfer,179180 181 OwnerCanDestroy,182183 184 TransferEnabled,185}186187188#[derive(Debug, Default, AbiCoder)]189pub struct CollectionLimit {190 field: CollectionLimitField,191 value: Option<U256>,192}193194impl CollectionLimit {195 196 pub fn new(field: CollectionLimitField, value: Option<u32>) -> Self {197 Self {198 field,199 value: match value {200 Some(value) => Some(value.into()),201 None => None,202 },203 }204 }205 206 pub fn has_value(&self) -> bool {207 self.value.is_some()208 }209}210211impl TryInto<up_data_structs::CollectionLimits> for CollectionLimit {212 type Error = evm_coder::execution::Error;213214 fn try_into(self) -> Result<up_data_structs::CollectionLimits, Self::Error> {215 let value = self216 .value217 .ok_or::<Self::Error>("can't convert `None` value to boolean".into())?;218 let value = Some(value.try_into().map_err(|error| {219 Self::Error::Revert(format!(220 "can't convert value to u32 \"{}\" because: \"{error}\"",221 value222 ))223 })?);224225 let convert_value_to_bool = || match value {226 Some(value) => match value {227 0 => Ok(Some(false)),228 1 => Ok(Some(true)),229 _ => {230 return Err(Self::Error::Revert(format!(231 "can't convert value to boolean \"{value}\""232 )))233 }234 },235 None => Ok(None),236 };237238 let mut limits = up_data_structs::CollectionLimits::default();239 match self.field {240 CollectionLimitField::AccountTokenOwnership => {241 limits.account_token_ownership_limit = value;242 }243 CollectionLimitField::SponsoredDataSize => {244 limits.sponsored_data_size = value;245 }246 CollectionLimitField::SponsoredDataRateLimit => {247 limits.sponsored_data_rate_limit = match value {248 Some(value) => Some(up_data_structs::SponsoringRateLimit::Blocks(value)),249 None => None,250 };251 }252 CollectionLimitField::TokenLimit => {253 limits.token_limit = value;254 }255 CollectionLimitField::SponsorTransferTimeout => {256 limits.sponsor_transfer_timeout = value;257 }258 CollectionLimitField::SponsorApproveTimeout => {259 limits.sponsor_approve_timeout = value;260 }261 CollectionLimitField::OwnerCanTransfer => {262 limits.owner_can_transfer = convert_value_to_bool()?;263 }264 CollectionLimitField::OwnerCanDestroy => {265 limits.owner_can_destroy = convert_value_to_bool()?;266 }267 CollectionLimitField::TransferEnabled => {268 limits.transfers_enabled = convert_value_to_bool()?;269 }270 };271 Ok(limits)272 }273}274275276#[derive(Default, Debug, Clone, Copy, AbiCoder)]277#[repr(u8)]278pub enum CollectionPermissionField {279 280 #[default]281 TokenOwner,282283 284 CollectionAdmin,285}286287288#[derive(AbiCoder, Copy, Clone, Default, Debug)]289#[repr(u8)]290pub enum TokenPermissionField {291 292 #[default]293 Mutable,294295 296 TokenOwner,297298 299 CollectionAdmin,300}301302303#[derive(Debug, Default, AbiCoder)]304pub struct PropertyPermission {305 306 code: TokenPermissionField,307 308 value: bool,309}310311impl PropertyPermission {312 313 pub fn into_vec(pp: up_data_structs::PropertyPermission) -> Vec<Self> {314 vec![315 PropertyPermission {316 code: TokenPermissionField::Mutable,317 value: pp.mutable,318 },319 PropertyPermission {320 code: TokenPermissionField::TokenOwner,321 value: pp.token_owner,322 },323 PropertyPermission {324 code: TokenPermissionField::CollectionAdmin,325 value: pp.collection_admin,326 },327 ]328 }329330 331 pub fn from_vec(permission: Vec<Self>) -> up_data_structs::PropertyPermission {332 let mut token_permission = up_data_structs::PropertyPermission::default();333334 for PropertyPermission { code, value } in permission {335 match code {336 TokenPermissionField::Mutable => token_permission.mutable = value,337 TokenPermissionField::TokenOwner => token_permission.token_owner = value,338 TokenPermissionField::CollectionAdmin => token_permission.collection_admin = value,339 }340 }341 token_permission342 }343}344345346#[derive(Debug, Default, AbiCoder)]347pub struct TokenPropertyPermission {348 349 key: evm_coder::types::String,350 351 permissions: Vec<PropertyPermission>,352}353354impl355 From<(356 up_data_structs::PropertyKey,357 up_data_structs::PropertyPermission,358 )> for TokenPropertyPermission359{360 fn from(361 value: (362 up_data_structs::PropertyKey,363 up_data_structs::PropertyPermission,364 ),365 ) -> Self {366 let (key, permission) = value;367 let key = evm_coder::types::String::from_utf8(key.into_inner())368 .expect("Stored key must be valid");369 let permissions = PropertyPermission::into_vec(permission);370 Self { key, permissions }371 }372}373374impl TokenPropertyPermission {375 376 pub fn into_property_key_permissions(377 permissions: Vec<TokenPropertyPermission>,378 ) -> evm_coder::execution::Result<Vec<up_data_structs::PropertyKeyPermission>> {379 let mut perms = Vec::new();380381 for TokenPropertyPermission { key, permissions } in permissions {382 let token_permission = PropertyPermission::from_vec(permissions);383384 perms.push(up_data_structs::PropertyKeyPermission {385 key: key.into_bytes().try_into().map_err(|_| "too long key")?,386 permission: token_permission,387 });388 }389 Ok(perms)390 }391}392393394#[derive(Debug, Default, AbiCoder)]395pub struct CollectionNesting {396 token_owner: bool,397 ids: Vec<U256>,398}399400impl CollectionNesting {401 402 pub fn new(token_owner: bool, ids: Vec<U256>) -> Self {403 Self { token_owner, ids }404 }405}406407408#[derive(Debug, Default, AbiCoder)]409pub struct CollectionNestingPermission {410 field: CollectionPermissionField,411 value: bool,412}413414impl CollectionNestingPermission {415 416 pub fn new(field: CollectionPermissionField, value: bool) -> Self {417 Self { field, value }418 }419}420421422#[derive(AbiCoder, Copy, Clone, Default, Debug)]423#[repr(u8)]424pub enum AccessMode {425 426 #[default]427 Normal,428 429 AllowList,430}431432impl From<up_data_structs::AccessMode> for AccessMode {433 fn from(value: up_data_structs::AccessMode) -> Self {434 match value {435 up_data_structs::AccessMode::Normal => AccessMode::Normal,436 up_data_structs::AccessMode::AllowList => AccessMode::AllowList,437 }438 }439}440441impl Into<up_data_structs::AccessMode> for AccessMode {442 fn into(self) -> up_data_structs::AccessMode {443 match self {444 AccessMode::Normal => up_data_structs::AccessMode::Normal,445 AccessMode::AllowList => up_data_structs::AccessMode::AllowList,446 }447 }448}