difftreelog
name anonymous tuples
in: master
15 files changed
pallets/common/src/eth.rsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! The module contains a number of functions for converting and checking ethereum identifiers.1819use 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;2526// 0x17c4e6453Cc49AAAaEACA894e6D9683e00000001 - collection 127// TODO: Unhardcode prefix28const ETH_COLLECTION_PREFIX: [u8; 16] = [29 0x17, 0xc4, 0xe6, 0x45, 0x3c, 0xc4, 0x9a, 0xaa, 0xae, 0xac, 0xa8, 0x94, 0xe6, 0xd9, 0x68, 0x3e,30];3132/// Maps the ethereum address of the collection in substrate.33pub 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}4142/// Maps the substrate collection id in ethereum.43pub 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}4950/// Check if the ethereum address is a collection.51pub fn is_collection(address: &Address) -> bool {52 address[0..16] == ETH_COLLECTION_PREFIX53}5455/// Convert `U256` to `CrossAccountId`.56pub 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}6566/// Cross account struct67#[derive(Debug, Default, AbiCoder)]68pub struct CrossAddress {69 pub(crate) eth: Address,70 pub(crate) sub: U256,71}7273impl CrossAddress {74 /// Converts `CrossAccountId` to [`CrossAddress`] to be correctly usable with Ethereum.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 /// Creates [`CrossAddress`] from Substrate account.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 /// Creates [`CrossAddress`] from Ethereum account.98 pub fn from_eth(address: Address) -> Self {99 Self {100 eth: address,101 sub: Default::default(),102 }103 }104 /// Converts [`CrossAddress`] to `CrossAccountId`.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}121122/// Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).123#[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}153154/// [`CollectionLimits`](up_data_structs::CollectionLimits) fields representation for EVM.155#[derive(Debug, Default, Clone, Copy, AbiCoder)]156#[repr(u8)]157pub enum CollectionLimitField {158 /// How many tokens can a user have on one account.159 #[default]160 AccountTokenOwnership,161162 /// How many bytes of data are available for sponsorship.163 SponsoredDataSize,164165 /// In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]166 SponsoredDataRateLimit,167168 /// How many tokens can be mined into this collection.169 TokenLimit,170171 /// Timeouts for transfer sponsoring.172 SponsorTransferTimeout,173174 /// Timeout for sponsoring an approval in passed blocks.175 SponsorApproveTimeout,176177 /// Whether the collection owner of the collection can send tokens (which belong to other users).178 OwnerCanTransfer,179180 /// Can the collection owner burn other people's tokens.181 OwnerCanDestroy,182183 /// Is it possible to send tokens from this collection between users.184 TransferEnabled,185}186187/// [`CollectionLimits`](up_data_structs::CollectionLimits) field representation for EVM.188#[derive(Debug, Default, AbiCoder)]189pub struct CollectionLimit {190 field: CollectionLimitField,191 value: Option<U256>,192}193194impl CollectionLimit {195 /// Create [`CollectionLimit`] from field and value.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 /// Whether the field contains a value.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}274275/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.276#[derive(Default, Debug, Clone, Copy, AbiCoder)]277#[repr(u8)]278pub enum CollectionPermissionField {279 /// Owner of token can nest tokens under it.280 #[default]281 TokenOwner,282283 /// Admin of token collection can nest tokens under token.284 CollectionAdmin,285}286287/// Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.288#[derive(AbiCoder, Copy, Clone, Default, Debug)]289#[repr(u8)]290pub enum TokenPermissionField {291 /// Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]292 #[default]293 Mutable,294295 /// Change permission for the collection administrator. See [`up_data_structs::PropertyPermission::token_owner`]296 TokenOwner,297298 /// Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]299 CollectionAdmin,300}301302/// Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) as an key and value.303#[derive(Debug, Default, AbiCoder)]304pub struct PropertyPermission {305 /// TokenPermission field.306 code: TokenPermissionField,307 /// TokenPermission value.308 value: bool,309}310311impl PropertyPermission {312 /// Make vector of [`PropertyPermission`] from [`up_data_structs::PropertyPermission`].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 /// Make [`up_data_structs::PropertyPermission`] from vector of [`PropertyPermission`].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}344345/// Ethereum representation of Token Property Permissions.346#[derive(Debug, Default, AbiCoder)]347pub struct TokenPropertyPermission {348 /// Token property key.349 key: evm_coder::types::String,350 /// Token property permissions.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 /// Convert vector of [`TokenPropertyPermission`] into vector of [`up_data_structs::PropertyKeyPermission`].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}392393/// Nested collections.394#[derive(Debug, Default, AbiCoder)]395pub struct CollectionNesting {396 token_owner: bool,397 ids: Vec<U256>,398}399400impl CollectionNesting {401 /// Create [`CollectionNesting`].402 pub fn new(token_owner: bool, ids: Vec<U256>) -> Self {403 Self { token_owner, ids }404 }405}406407/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.408#[derive(Debug, Default, AbiCoder)]409pub struct CollectionNestingPermission {410 field: CollectionPermissionField,411 value: bool,412}413414impl CollectionNestingPermission {415 /// Create [`CollectionNestingPermission`].416 pub fn new(field: CollectionPermissionField, value: bool) -> Self {417 Self { field, value }418 }419}420421/// Ethereum representation of `AccessMode` (see [`up_data_structs::AccessMode`]).422#[derive(AbiCoder, Copy, Clone, Default, Debug)]423#[repr(u8)]424pub enum AccessMode {425 /// Access grant for owner and admins. Used as default.426 #[default]427 Normal,428 /// Like a [`Normal`](AccessMode::Normal) but also users in allow list.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}1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! The module contains a number of functions for converting and checking ethereum identifiers.1819use alloc::format;20use sp_std::{vec, vec::Vec};21use evm_coder::{22 AbiCoder,23 types::{Address, String},24};25pub use pallet_evm::{Config, account::CrossAccountId};26use sp_core::{H160, U256};27use up_data_structs::CollectionId;2829// 0x17c4e6453Cc49AAAaEACA894e6D9683e00000001 - collection 130// TODO: Unhardcode prefix31const ETH_COLLECTION_PREFIX: [u8; 16] = [32 0x17, 0xc4, 0xe6, 0x45, 0x3c, 0xc4, 0x9a, 0xaa, 0xae, 0xac, 0xa8, 0x94, 0xe6, 0xd9, 0x68, 0x3e,33];3435/// Maps the ethereum address of the collection in substrate.36pub fn map_eth_to_id(eth: &Address) -> Option<CollectionId> {37 if eth[0..16] != ETH_COLLECTION_PREFIX {38 return None;39 }40 let mut id_bytes = [0; 4];41 id_bytes.copy_from_slice(ð[16..20]);42 Some(CollectionId(u32::from_be_bytes(id_bytes)))43}4445/// Maps the substrate collection id in ethereum.46pub fn collection_id_to_address(id: CollectionId) -> Address {47 let mut out = [0; 20];48 out[0..16].copy_from_slice(Ð_COLLECTION_PREFIX);49 out[16..20].copy_from_slice(&u32::to_be_bytes(id.0));50 H160(out)51}5253/// Check if the ethereum address is a collection.54pub fn is_collection(address: &Address) -> bool {55 address[0..16] == ETH_COLLECTION_PREFIX56}5758/// Convert `U256` to `CrossAccountId`.59pub fn convert_uint256_to_cross_account<T: Config>(from: U256) -> T::CrossAccountId60where61 T::AccountId: From<[u8; 32]>,62{63 let mut new_admin_arr = [0_u8; 32];64 from.to_big_endian(&mut new_admin_arr);65 let account_id = T::AccountId::from(new_admin_arr);66 T::CrossAccountId::from_sub(account_id)67}6869/// Cross account struct70#[derive(Debug, Default, AbiCoder)]71pub struct CrossAddress {72 pub(crate) eth: Address,73 pub(crate) sub: U256,74}7576impl CrossAddress {77 /// Converts `CrossAccountId` to [`CrossAddress`] to be correctly usable with Ethereum.78 pub fn from_sub_cross_account<T>(cross_account_id: &T::CrossAccountId) -> Self79 where80 T: pallet_evm::Config,81 T::AccountId: AsRef<[u8; 32]>,82 {83 if cross_account_id.is_canonical_substrate() {84 Self::from_sub::<T>(cross_account_id.as_sub())85 } else {86 Self::from_eth(*cross_account_id.as_eth())87 }88 }89 /// Creates [`CrossAddress`] from Substrate account.90 pub fn from_sub<T>(account_id: &T::AccountId) -> Self91 where92 T: pallet_evm::Config,93 T::AccountId: AsRef<[u8; 32]>,94 {95 Self {96 eth: Default::default(),97 sub: U256::from_big_endian(account_id.as_ref()),98 }99 }100 /// Creates [`CrossAddress`] from Ethereum account.101 pub fn from_eth(address: Address) -> Self {102 Self {103 eth: address,104 sub: Default::default(),105 }106 }107 /// Converts [`CrossAddress`] to `CrossAccountId`.108 pub fn into_sub_cross_account<T>(&self) -> evm_coder::execution::Result<T::CrossAccountId>109 where110 T: pallet_evm::Config,111 T::AccountId: From<[u8; 32]>,112 {113 if self.eth == Default::default() && self.sub == Default::default() {114 Err("All fields of cross account is zeroed".into())115 } else if self.eth == Default::default() {116 Ok(convert_uint256_to_cross_account::<T>(self.sub))117 } else if self.sub == Default::default() {118 Ok(T::CrossAccountId::from_eth(self.eth))119 } else {120 Err("All fields of cross account is non zeroed".into())121 }122 }123}124125/// Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).126#[derive(Debug, Default, AbiCoder)]127pub struct Property {128 key: evm_coder::types::String,129 value: evm_coder::types::Bytes,130}131132impl TryFrom<up_data_structs::Property> for Property {133 type Error = evm_coder::execution::Error;134135 fn try_from(from: up_data_structs::Property) -> Result<Self, Self::Error> {136 let key = evm_coder::types::String::from_utf8(from.key.into())137 .map_err(|e| Self::Error::Revert(format!("utf8 conversion error: {}", e)))?;138 let value = evm_coder::types::Bytes(from.value.to_vec());139 Ok(Property { key, value })140 }141}142143impl TryInto<up_data_structs::Property> for Property {144 type Error = evm_coder::execution::Error;145146 fn try_into(self) -> Result<up_data_structs::Property, Self::Error> {147 let key = <Vec<u8>>::from(self.key)148 .try_into()149 .map_err(|_| "key too large")?;150151 let value = self.value.0.try_into().map_err(|_| "value too large")?;152153 Ok(up_data_structs::Property { key, value })154 }155}156157/// [`CollectionLimits`](up_data_structs::CollectionLimits) fields representation for EVM.158#[derive(Debug, Default, Clone, Copy, AbiCoder)]159#[repr(u8)]160pub enum CollectionLimitField {161 /// How many tokens can a user have on one account.162 #[default]163 AccountTokenOwnership,164165 /// How many bytes of data are available for sponsorship.166 SponsoredDataSize,167168 /// In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]169 SponsoredDataRateLimit,170171 /// How many tokens can be mined into this collection.172 TokenLimit,173174 /// Timeouts for transfer sponsoring.175 SponsorTransferTimeout,176177 /// Timeout for sponsoring an approval in passed blocks.178 SponsorApproveTimeout,179180 /// Whether the collection owner of the collection can send tokens (which belong to other users).181 OwnerCanTransfer,182183 /// Can the collection owner burn other people's tokens.184 OwnerCanDestroy,185186 /// Is it possible to send tokens from this collection between users.187 TransferEnabled,188}189190/// [`CollectionLimits`](up_data_structs::CollectionLimits) field representation for EVM.191#[derive(Debug, Default, AbiCoder)]192pub struct CollectionLimit {193 field: CollectionLimitField,194 value: Option<U256>,195}196197impl CollectionLimit {198 /// Create [`CollectionLimit`] from field and value.199 pub fn new(field: CollectionLimitField, value: Option<u32>) -> Self {200 Self {201 field,202 value: match value {203 Some(value) => Some(value.into()),204 None => None,205 },206 }207 }208 /// Whether the field contains a value.209 pub fn has_value(&self) -> bool {210 self.value.is_some()211 }212}213214impl TryInto<up_data_structs::CollectionLimits> for CollectionLimit {215 type Error = evm_coder::execution::Error;216217 fn try_into(self) -> Result<up_data_structs::CollectionLimits, Self::Error> {218 let value = self219 .value220 .ok_or::<Self::Error>("can't convert `None` value to boolean".into())?;221 let value = Some(value.try_into().map_err(|error| {222 Self::Error::Revert(format!(223 "can't convert value to u32 \"{}\" because: \"{error}\"",224 value225 ))226 })?);227228 let convert_value_to_bool = || match value {229 Some(value) => match value {230 0 => Ok(Some(false)),231 1 => Ok(Some(true)),232 _ => {233 return Err(Self::Error::Revert(format!(234 "can't convert value to boolean \"{value}\""235 )))236 }237 },238 None => Ok(None),239 };240241 let mut limits = up_data_structs::CollectionLimits::default();242 match self.field {243 CollectionLimitField::AccountTokenOwnership => {244 limits.account_token_ownership_limit = value;245 }246 CollectionLimitField::SponsoredDataSize => {247 limits.sponsored_data_size = value;248 }249 CollectionLimitField::SponsoredDataRateLimit => {250 limits.sponsored_data_rate_limit = match value {251 Some(value) => Some(up_data_structs::SponsoringRateLimit::Blocks(value)),252 None => None,253 };254 }255 CollectionLimitField::TokenLimit => {256 limits.token_limit = value;257 }258 CollectionLimitField::SponsorTransferTimeout => {259 limits.sponsor_transfer_timeout = value;260 }261 CollectionLimitField::SponsorApproveTimeout => {262 limits.sponsor_approve_timeout = value;263 }264 CollectionLimitField::OwnerCanTransfer => {265 limits.owner_can_transfer = convert_value_to_bool()?;266 }267 CollectionLimitField::OwnerCanDestroy => {268 limits.owner_can_destroy = convert_value_to_bool()?;269 }270 CollectionLimitField::TransferEnabled => {271 limits.transfers_enabled = convert_value_to_bool()?;272 }273 };274 Ok(limits)275 }276}277278/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.279#[derive(Default, Debug, Clone, Copy, AbiCoder)]280#[repr(u8)]281pub enum CollectionPermissionField {282 /// Owner of token can nest tokens under it.283 #[default]284 TokenOwner,285286 /// Admin of token collection can nest tokens under token.287 CollectionAdmin,288}289290/// Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.291#[derive(AbiCoder, Copy, Clone, Default, Debug)]292#[repr(u8)]293pub enum TokenPermissionField {294 /// Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]295 #[default]296 Mutable,297298 /// Change permission for the collection administrator. See [`up_data_structs::PropertyPermission::token_owner`]299 TokenOwner,300301 /// Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]302 CollectionAdmin,303}304305/// Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) as an key and value.306#[derive(Debug, Default, AbiCoder)]307pub struct PropertyPermission {308 /// TokenPermission field.309 code: TokenPermissionField,310 /// TokenPermission value.311 value: bool,312}313314impl PropertyPermission {315 /// Make vector of [`PropertyPermission`] from [`up_data_structs::PropertyPermission`].316 pub fn into_vec(pp: up_data_structs::PropertyPermission) -> Vec<Self> {317 vec![318 PropertyPermission {319 code: TokenPermissionField::Mutable,320 value: pp.mutable,321 },322 PropertyPermission {323 code: TokenPermissionField::TokenOwner,324 value: pp.token_owner,325 },326 PropertyPermission {327 code: TokenPermissionField::CollectionAdmin,328 value: pp.collection_admin,329 },330 ]331 }332333 /// Make [`up_data_structs::PropertyPermission`] from vector of [`PropertyPermission`].334 pub fn from_vec(permission: Vec<Self>) -> up_data_structs::PropertyPermission {335 let mut token_permission = up_data_structs::PropertyPermission::default();336337 for PropertyPermission { code, value } in permission {338 match code {339 TokenPermissionField::Mutable => token_permission.mutable = value,340 TokenPermissionField::TokenOwner => token_permission.token_owner = value,341 TokenPermissionField::CollectionAdmin => token_permission.collection_admin = value,342 }343 }344 token_permission345 }346}347348/// Ethereum representation of Token Property Permissions.349#[derive(Debug, Default, AbiCoder)]350pub struct TokenPropertyPermission {351 /// Token property key.352 key: evm_coder::types::String,353 /// Token property permissions.354 permissions: Vec<PropertyPermission>,355}356357impl358 From<(359 up_data_structs::PropertyKey,360 up_data_structs::PropertyPermission,361 )> for TokenPropertyPermission362{363 fn from(364 value: (365 up_data_structs::PropertyKey,366 up_data_structs::PropertyPermission,367 ),368 ) -> Self {369 let (key, permission) = value;370 let key = evm_coder::types::String::from_utf8(key.into_inner())371 .expect("Stored key must be valid");372 let permissions = PropertyPermission::into_vec(permission);373 Self { key, permissions }374 }375}376377impl TokenPropertyPermission {378 /// Convert vector of [`TokenPropertyPermission`] into vector of [`up_data_structs::PropertyKeyPermission`].379 pub fn into_property_key_permissions(380 permissions: Vec<TokenPropertyPermission>,381 ) -> evm_coder::execution::Result<Vec<up_data_structs::PropertyKeyPermission>> {382 let mut perms = Vec::new();383384 for TokenPropertyPermission { key, permissions } in permissions {385 let token_permission = PropertyPermission::from_vec(permissions);386387 perms.push(up_data_structs::PropertyKeyPermission {388 key: key.into_bytes().try_into().map_err(|_| "too long key")?,389 permission: token_permission,390 });391 }392 Ok(perms)393 }394}395396/// Data for creation token with uri.397#[derive(Debug, AbiCoder)]398pub struct TokenUri {399 /// Id of new token.400 pub id: U256,401402 /// Uri of new token.403 pub uri: String,404}405406/// Nested collections.407#[derive(Debug, Default, AbiCoder)]408pub struct CollectionNesting {409 token_owner: bool,410 ids: Vec<U256>,411}412413impl CollectionNesting {414 /// Create [`CollectionNesting`].415 pub fn new(token_owner: bool, ids: Vec<U256>) -> Self {416 Self { token_owner, ids }417 }418}419420/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.421#[derive(Debug, Default, AbiCoder)]422pub struct CollectionNestingPermission {423 field: CollectionPermissionField,424 value: bool,425}426427impl CollectionNestingPermission {428 /// Create [`CollectionNestingPermission`].429 pub fn new(field: CollectionPermissionField, value: bool) -> Self {430 Self { field, value }431 }432}433434/// Ethereum representation of `AccessMode` (see [`up_data_structs::AccessMode`]).435#[derive(AbiCoder, Copy, Clone, Default, Debug)]436#[repr(u8)]437pub enum AccessMode {438 /// Access grant for owner and admins. Used as default.439 #[default]440 Normal,441 /// Like a [`Normal`](AccessMode::Normal) but also users in allow list.442 AllowList,443}444445impl From<up_data_structs::AccessMode> for AccessMode {446 fn from(value: up_data_structs::AccessMode) -> Self {447 match value {448 up_data_structs::AccessMode::Normal => AccessMode::Normal,449 up_data_structs::AccessMode::AllowList => AccessMode::AllowList,450 }451 }452}453454impl Into<up_data_structs::AccessMode> for AccessMode {455 fn into(self) -> up_data_structs::AccessMode {456 match self {457 AccessMode::Normal => up_data_structs::AccessMode::Normal,458 AccessMode::AllowList => up_data_structs::AccessMode::AllowList,459 }460 }461}pallets/fungible/src/erc.rsdiffbeforeafterboth--- a/pallets/fungible/src/erc.rs
+++ b/pallets/fungible/src/erc.rs
@@ -6,7 +6,7 @@
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-// Unique Network is distributed in the hope that it will be useful,
+// Unique Network is disaddress: tod in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
@@ -19,6 +19,7 @@
extern crate alloc;
use core::char::{REPLACEMENT_CHARACTER, decode_utf16};
use core::convert::TryInto;
+use evm_coder::AbiCoder;
use evm_coder::{
abi::AbiType, ToLog, execution::*, generate_stubgen, solidity, solidity_interface, types::*,
weight,
@@ -57,6 +58,12 @@
},
}
+#[derive(AbiCoder, Debug)]
+pub struct AmountForAddress {
+ to: Address,
+ amount: U256,
+}
+
#[solidity_interface(name = ERC20, events(ERC20Events), expect_selector = 0x942e8b22)]
impl<T: Config> FungibleHandle<T> {
fn name(&self) -> Result<String> {
@@ -264,14 +271,14 @@
/// Mint tokens for multiple accounts.
/// @param amounts array of pairs of account address and amount
#[weight(<SelfWeightOf<T>>::create_multiple_items_ex(amounts.len() as u32))]
- fn mint_bulk(&mut self, caller: Caller, amounts: Vec<(Address, U256)>) -> Result<bool> {
+ fn mint_bulk(&mut self, caller: Caller, amounts: Vec<AmountForAddress>) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
let budget = self
.recorder
.weight_calls_budget(<StructureWeight<T>>::find_parent());
let amounts = amounts
.into_iter()
- .map(|(to, amount)| {
+ .map(|AmountForAddress { to, amount }| {
Ok((
T::CrossAccountId::from_eth(to),
amount.try_into().map_err(|_| "amount overflow")?,
pallets/fungible/src/stubs/UniqueFungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth--- a/pallets/fungible/src/stubs/UniqueFungible.sol
+++ b/pallets/fungible/src/stubs/UniqueFungible.sol
@@ -590,7 +590,7 @@
/// @param amounts array of pairs of account address and amount
/// @dev EVM selector for this function is: 0x1acf2d55,
/// or in textual repr: mintBulk((address,uint256)[])
- function mintBulk(Tuple11[] memory amounts) public returns (bool) {
+ function mintBulk(AmountForAddress[] memory amounts) public returns (bool) {
require(false, stub_error);
amounts;
dummy = 0;
@@ -632,10 +632,9 @@
}
}
-/// @dev anonymous struct
-struct Tuple11 {
- address field_0;
- uint256 field_1;
+struct AmountForAddress {
+ address to;
+ uint256 amount;
}
/// @dev the ERC-165 identifier for this interface is 0x40c10f19
pallets/nonfungible/src/erc.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -38,7 +38,7 @@
use pallet_common::{
CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations,
erc::{CommonEvmHandler, PrecompileResult, CollectionCall, static_property::key},
- eth,
+ eth::{self, TokenUri},
};
use pallet_evm::{account::CrossAccountId, PrecompileHandle};
use pallet_evm_coder_substrate::call;
@@ -948,7 +948,7 @@
&mut self,
caller: Caller,
to: Address,
- tokens: Vec<(U256, String)>,
+ tokens: Vec<TokenUri>,
) -> Result<bool> {
let key = key::url();
let caller = T::CrossAccountId::from_eth(caller);
@@ -961,7 +961,7 @@
.weight_calls_budget(<StructureWeight<T>>::find_parent());
let mut data = Vec::with_capacity(tokens.len());
- for (id, token_uri) in tokens {
+ for TokenUri { id, uri } in tokens {
let id: u32 = id.try_into().map_err(|_| "token id overflow")?;
if id != expected_index {
return Err("item id should be next".into());
@@ -972,7 +972,7 @@
properties
.try_push(Property {
key: key.clone(),
- value: token_uri
+ value: uri
.into_bytes()
.try_into()
.map_err(|_| "token uri is too long")?,
pallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterbothbinary blob — no preview
pallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth--- a/pallets/nonfungible/src/stubs/UniqueNFT.sol
+++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol
@@ -949,7 +949,7 @@
// /// @param tokens array of pairs of token ID and token URI for minted tokens
// /// @dev EVM selector for this function is: 0x36543006,
// /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])
- // function mintBulkWithTokenURI(address to, Tuple15[] memory tokens) public returns (bool) {
+ // function mintBulkWithTokenURI(address to, TokenUri[] memory tokens) public returns (bool) {
// require(false, stub_error);
// to;
// tokens;
@@ -981,10 +981,12 @@
}
}
-/// @dev anonymous struct
-struct Tuple15 {
- uint256 field_0;
- string field_1;
+/// Data for creation token with uri.
+struct TokenUri {
+ /// Id of new token.
+ uint256 id;
+ /// Uri of new token.
+ string uri;
}
/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
pallets/refungible/src/erc.rsdiffbeforeafterboth--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -34,7 +34,7 @@
CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations,
Error as CommonError,
erc::{CommonEvmHandler, CollectionCall, static_property::key},
- eth,
+ eth::{self, TokenUri},
};
use pallet_evm::{account::CrossAccountId, PrecompileHandle};
use pallet_evm_coder_substrate::{call, dispatch_to_evm};
@@ -999,7 +999,7 @@
&mut self,
caller: Caller,
to: Address,
- tokens: Vec<(U256, String)>,
+ tokens: Vec<TokenUri>,
) -> Result<bool> {
let key = key::url();
let caller = T::CrossAccountId::from_eth(caller);
@@ -1017,7 +1017,7 @@
.collect::<BTreeMap<_, _>>()
.try_into()
.unwrap();
- for (id, token_uri) in tokens {
+ for TokenUri { id, uri } in tokens {
let id: u32 = id.try_into().map_err(|_| "token id overflow")?;
if id != expected_index {
return Err("item id should be next".into());
@@ -1028,7 +1028,7 @@
properties
.try_push(Property {
key: key.clone(),
- value: token_uri
+ value: uri
.into_bytes()
.try_into()
.map_err(|_| "token uri is too long")?,
pallets/refungible/src/stubs/UniqueRefungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth--- a/pallets/refungible/src/stubs/UniqueRefungible.sol
+++ b/pallets/refungible/src/stubs/UniqueRefungible.sol
@@ -938,7 +938,7 @@
// /// @param tokens array of pairs of token ID and token URI for minted tokens
// /// @dev EVM selector for this function is: 0x36543006,
// /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])
- // function mintBulkWithTokenURI(address to, Tuple14[] memory tokens) public returns (bool) {
+ // function mintBulkWithTokenURI(address to, TokenUri[] memory tokens) public returns (bool) {
// require(false, stub_error);
// to;
// tokens;
@@ -982,10 +982,12 @@
}
}
-/// @dev anonymous struct
-struct Tuple14 {
- uint256 field_0;
- string field_1;
+/// Data for creation token with uri.
+struct TokenUri {
+ /// Id of new token.
+ uint256 id;
+ /// Uri of new token.
+ string uri;
}
/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
tests/src/eth/abi/fungible.jsondiffbeforeafterboth--- a/tests/src/eth/abi/fungible.json
+++ b/tests/src/eth/abi/fungible.json
@@ -434,10 +434,10 @@
"inputs": [
{
"components": [
- { "internalType": "address", "name": "field_0", "type": "address" },
- { "internalType": "uint256", "name": "field_1", "type": "uint256" }
+ { "internalType": "address", "name": "to", "type": "address" },
+ { "internalType": "uint256", "name": "amount", "type": "uint256" }
],
- "internalType": "struct Tuple11[]",
+ "internalType": "struct AmountForAddress[]",
"name": "amounts",
"type": "tuple[]"
}
tests/src/eth/api/UniqueFungible.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueFungible.sol
+++ b/tests/src/eth/api/UniqueFungible.sol
@@ -398,7 +398,7 @@
/// @param amounts array of pairs of account address and amount
/// @dev EVM selector for this function is: 0x1acf2d55,
/// or in textual repr: mintBulk((address,uint256)[])
- function mintBulk(Tuple11[] memory amounts) external returns (bool);
+ function mintBulk(AmountForAddress[] memory amounts) external returns (bool);
/// @dev EVM selector for this function is: 0x2ada85ff,
/// or in textual repr: transferCross((address,uint256),uint256)
@@ -418,10 +418,9 @@
function collectionHelperAddress() external view returns (address);
}
-/// @dev anonymous struct
-struct Tuple11 {
- address field_0;
- uint256 field_1;
+struct AmountForAddress {
+ address to;
+ uint256 amount;
}
/// @dev the ERC-165 identifier for this interface is 0x40c10f19
tests/src/eth/api/UniqueNFT.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -644,7 +644,7 @@
// /// @param tokens array of pairs of token ID and token URI for minted tokens
// /// @dev EVM selector for this function is: 0x36543006,
// /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])
- // function mintBulkWithTokenURI(address to, Tuple13[] memory tokens) external returns (bool);
+ // function mintBulkWithTokenURI(address to, TokenUri[] memory tokens) external returns (bool);
/// @notice Function to mint a token.
/// @param to The new owner crossAccountId
@@ -660,10 +660,12 @@
function collectionHelperAddress() external view returns (address);
}
-/// @dev anonymous struct
-struct Tuple13 {
- uint256 field_0;
- string field_1;
+/// Data for creation token with uri.
+struct TokenUri {
+ /// Id of new token.
+ uint256 id;
+ /// Uri of new token.
+ string uri;
}
/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
tests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueRefungible.sol
+++ b/tests/src/eth/api/UniqueRefungible.sol
@@ -638,7 +638,7 @@
// /// @param tokens array of pairs of token ID and token URI for minted tokens
// /// @dev EVM selector for this function is: 0x36543006,
// /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])
- // function mintBulkWithTokenURI(address to, Tuple12[] memory tokens) external returns (bool);
+ // function mintBulkWithTokenURI(address to, TokenUri[] memory tokens) external returns (bool);
/// @notice Function to mint a token.
/// @param to The new owner crossAccountId
@@ -661,10 +661,12 @@
function collectionHelperAddress() external view returns (address);
}
-/// @dev anonymous struct
-struct Tuple12 {
- uint256 field_0;
- string field_1;
+/// Data for creation token with uri.
+struct TokenUri {
+ /// Id of new token.
+ uint256 id;
+ /// Uri of new token.
+ string uri;
}
/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
tests/src/eth/proxy/UniqueNFTProxy.soldiffbeforeafterboth--- a/tests/src/eth/proxy/UniqueNFTProxy.sol
+++ b/tests/src/eth/proxy/UniqueNFTProxy.sol
@@ -168,7 +168,7 @@
return proxied.mintBulk(to, tokenIds);
}
- function mintBulkWithTokenURI(address to, Tuple6[] memory tokens)
+ function mintBulkWithTokenURI(address to, TokenUri[] memory tokens)
external
override
returns (bool)