difftreelog
feat Rewrite tuple to named structures for TokenPropertyPermission. fix: AbiCoder derive macro
in: master
23 files changed
crates/evm-coder/procedural/src/abi_derive/derive_enum.rsdiffbeforeafterboth1use quote::quote;23pub fn impl_solidity_option<'a>(4 name: &proc_macro2::Ident,5 enum_options: impl Iterator<Item = &'a syn::Ident>,6) -> proc_macro2::TokenStream {7 let enum_options = enum_options.map(|opt| {8 let s = name.to_string() + "." + opt.to_string().as_str();9 let as_string = proc_macro2::Literal::string(s.as_str());10 quote!(#name::#opt => #as_string,)11 });12 quote!(13 #[cfg(feature = "stubgen")]14 impl ::evm_coder::solidity::SolidityEnum for #name {15 fn solidity_option(&self) -> &str {16 match self {17 #(#enum_options)*18 }19 }20 }21 )22}2324pub fn impl_enum_from_u8<'a>(25 name: &proc_macro2::Ident,26 enum_options: impl Iterator<Item = &'a syn::Ident>,27) -> proc_macro2::TokenStream {28 let error_str = format!("Value not convertible into enum \"{name}\"");29 let error_str = proc_macro2::Literal::string(&error_str);30 let enum_options = enum_options.enumerate().map(|(i, opt)| {31 let n = proc_macro2::Literal::u8_suffixed(i as u8);32 quote! {#n => Ok(#name::#opt),}33 });3435 quote!(36 impl TryFrom<u8> for #name {37 type Error = &'static str;3839 fn try_from(value: u8) -> ::core::result::Result<Self, Self::Error> {40 const err: &'static str = #error_str;41 match value {42 #(#enum_options)*43 _ => Err(err)44 }45 }46 }47 )48}4950pub fn impl_enum_abi_type(name: &syn::Ident, option_count: usize) -> proc_macro2::TokenStream {51 quote! {52 impl ::evm_coder::abi::AbiType for #name {53 const SIGNATURE: ::evm_coder::custom_signature::SignatureUnit = <u8 as ::evm_coder::abi::AbiType>::SIGNATURE;54 const FIELDS_COUNT: usize = #option_count;5556 fn is_dynamic() -> bool {57 <u8 as ::evm_coder::abi::AbiType>::is_dynamic()58 }59 fn size() -> usize {60 <u8 as ::evm_coder::abi::AbiType>::size()61 }62 }63 }64}6566pub fn impl_enum_abi_read(name: &syn::Ident) -> proc_macro2::TokenStream {67 quote!(68 impl ::evm_coder::abi::AbiRead for #name {69 fn abi_read(reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result<Self> {70 Ok(71 <u8 as ::evm_coder::abi::AbiRead>::abi_read(reader)?72 .try_into()?73 )74 }75 }76 )77}7879pub fn impl_enum_abi_write(name: &syn::Ident) -> proc_macro2::TokenStream {80 quote!(81 impl ::evm_coder::abi::AbiWrite for #name {82 fn abi_write(&self, writer: &mut ::evm_coder::abi::AbiWriter) {83 ::evm_coder::abi::AbiWrite::abi_write(&(*self as u8), writer);84 }85 }86 )87}8889pub fn impl_enum_solidity_type_name(name: &syn::Ident) -> proc_macro2::TokenStream {90 quote!(91 #[cfg(feature = "stubgen")]92 impl ::evm_coder::solidity::SolidityTypeName for #name {93 fn solidity_name(94 writer: &mut impl ::core::fmt::Write,95 tc: &::evm_coder::solidity::TypeCollector,96 ) -> ::core::fmt::Result {97 write!(writer, "{}", tc.collect_struct::<Self>())98 }99100 fn is_simple() -> bool {101 true102 }103104 fn solidity_default(105 writer: &mut impl ::core::fmt::Write,106 tc: &::evm_coder::solidity::TypeCollector,107 ) -> ::core::fmt::Result {108 write!(writer, "{}", <#name as ::evm_coder::solidity::SolidityEnum>::solidity_option(&<#name>::default()))109 }110 }111 )112}113114pub fn impl_enum_solidity_struct_collect<'a>(115 name: &syn::Ident,116 enum_options: impl Iterator<Item = &'a syn::Ident>,117 option_count: usize,118 enum_options_docs: impl Iterator<Item = syn::Result<Vec<proc_macro2::TokenStream>>>,119 docs: &[proc_macro2::TokenStream],120) -> proc_macro2::TokenStream {121 let string_name = name.to_string();122 let enum_options = enum_options123 .zip(enum_options_docs)124 .enumerate()125 .map(|(i, (opt, doc))| {126 let opt = proc_macro2::Literal::string(opt.to_string().as_str());127 let doc = doc.expect("Doc parsing error");128 let comma = if i != option_count - 1 { "," } else { "" };129 quote! {130 #(#doc)*131 writeln!(str, "\t{}{}", #opt, #comma).expect("Enum format option");132 }133 });134135 quote!(136 #[cfg(feature = "stubgen")]137 impl ::evm_coder::solidity::StructCollect for #name {138 fn name() -> String {139 #string_name.into()140 }141142 fn declaration() -> String {143 use std::fmt::Write;144145 let mut str = String::new();146 #(#docs)*147 writeln!(str, "enum {} {{", <Self as ::evm_coder::solidity::StructCollect>::name()).unwrap();148 #(#enum_options)*149 writeln!(str, "}}").unwrap();150 str151 }152 }153 )154}155156pub fn check_and_count_options(de: &syn::DataEnum) -> syn::Result<usize> {157 let mut count = 0;158 for v in de.variants.iter() {159 if !v.fields.is_empty() {160 return Err(syn::Error::new(161 v.ident.span(),162 "Enumeration parameters should not have fields",163 ));164 } else if v.discriminant.is_some() {165 return Err(syn::Error::new(166 v.ident.span(),167 "Enumeration options should not have an explicit specified value",168 ));169 } else {170 count += 1;171 }172 }173174 Ok(count)175}176177pub fn check_repr_u8(name: &syn::Ident, attrs: &[syn::Attribute]) -> syn::Result<()> {178 let mut has_repr = false;179 for attr in attrs.iter() {180 if attr.path.is_ident("repr") {181 has_repr = true;182 let meta = attr.parse_meta()?;183 check_meta_u8(&meta)?;184 }185 }186187 if !has_repr {188 return Err(syn::Error::new(name.span(), "Enum is not \"repr(u8)\""));189 }190191 Ok(())192}193194fn check_meta_u8(meta: &syn::Meta) -> Result<(), syn::Error> {195 if let syn::Meta::List(p) = meta {196 for nm in p.nested.iter() {197 if let syn::NestedMeta::Meta(syn::Meta::Path(p)) = nm {198 if !p.is_ident("u8") {199 return Err(syn::Error::new(200 p.segments201 .first()202 .expect("repr segments are empty")203 .ident204 .span(),205 "Enum is not \"repr(u8)\"",206 ));207 }208 }209 }210 }211 Ok(())212}1use quote::quote;23pub fn impl_solidity_option<'a>(4 name: &proc_macro2::Ident,5 enum_options: impl Iterator<Item = &'a syn::Ident>,6) -> proc_macro2::TokenStream {7 let enum_options = enum_options.map(|opt| {8 let s = name.to_string() + "." + opt.to_string().as_str();9 let as_string = proc_macro2::Literal::string(s.as_str());10 quote!(#name::#opt => #as_string,)11 });12 quote!(13 #[cfg(feature = "stubgen")]14 impl ::evm_coder::solidity::SolidityEnum for #name {15 fn solidity_option(&self) -> &str {16 match self {17 #(#enum_options)*18 }19 }20 }21 )22}2324pub fn impl_enum_from_u8<'a>(25 name: &proc_macro2::Ident,26 enum_options: impl Iterator<Item = &'a syn::Ident>,27) -> proc_macro2::TokenStream {28 let error_str = format!("Value not convertible into enum \"{name}\"");29 let error_str = proc_macro2::Literal::string(&error_str);30 let enum_options = enum_options.enumerate().map(|(i, opt)| {31 let n = proc_macro2::Literal::u8_suffixed(i as u8);32 quote! {#n => Ok(#name::#opt),}33 });3435 quote!(36 impl TryFrom<u8> for #name {37 type Error = &'static str;3839 fn try_from(value: u8) -> ::core::result::Result<Self, Self::Error> {40 const err: &'static str = #error_str;41 match value {42 #(#enum_options)*43 _ => Err(err)44 }45 }46 }47 )48}4950pub fn impl_enum_abi_type(name: &syn::Ident, option_count: usize) -> proc_macro2::TokenStream {51 quote! {52 impl ::evm_coder::abi::AbiType for #name {53 const SIGNATURE: ::evm_coder::custom_signature::SignatureUnit = <u8 as ::evm_coder::abi::AbiType>::SIGNATURE;54 const FIELDS_COUNT: usize = #option_count;5556 fn is_dynamic() -> bool {57 <u8 as ::evm_coder::abi::AbiType>::is_dynamic()58 }59 fn size() -> usize {60 <u8 as ::evm_coder::abi::AbiType>::size()61 }62 }63 }64}6566pub fn impl_enum_abi_read(name: &syn::Ident) -> proc_macro2::TokenStream {67 quote!(68 impl ::evm_coder::abi::AbiRead for #name {69 fn abi_read(reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result<Self> {70 Ok(71 <u8 as ::evm_coder::abi::AbiRead>::abi_read(reader)?72 .try_into()?73 )74 }75 }76 )77}7879pub fn impl_enum_abi_write(name: &syn::Ident) -> proc_macro2::TokenStream {80 quote!(81 impl ::evm_coder::abi::AbiWrite for #name {82 fn abi_write(&self, writer: &mut ::evm_coder::abi::AbiWriter) {83 ::evm_coder::abi::AbiWrite::abi_write(&(*self as u8), writer);84 }85 }86 )87}8889pub fn impl_enum_solidity_type<'a>(name: &syn::Ident) -> proc_macro2::TokenStream {90 quote! {91 #[cfg(feature = "stubgen")]92 impl ::evm_coder::solidity::SolidityType for #name {93 fn names(tc: &::evm_coder::solidity::TypeCollector) -> Vec<String> {94 Vec::new()95 }9697 fn len() -> usize {98 199 }100 }101 }102}103104pub fn impl_enum_solidity_type_name(name: &syn::Ident) -> proc_macro2::TokenStream {105 quote!(106 #[cfg(feature = "stubgen")]107 impl ::evm_coder::solidity::SolidityTypeName for #name {108 fn solidity_name(109 writer: &mut impl ::core::fmt::Write,110 tc: &::evm_coder::solidity::TypeCollector,111 ) -> ::core::fmt::Result {112 write!(writer, "{}", tc.collect_struct::<Self>())113 }114115 fn is_simple() -> bool {116 true117 }118119 fn solidity_default(120 writer: &mut impl ::core::fmt::Write,121 tc: &::evm_coder::solidity::TypeCollector,122 ) -> ::core::fmt::Result {123 write!(writer, "{}", <#name as ::evm_coder::solidity::SolidityEnum>::solidity_option(&<#name>::default()))124 }125 }126 )127}128129pub fn impl_enum_solidity_struct_collect<'a>(130 name: &syn::Ident,131 enum_options: impl Iterator<Item = &'a syn::Ident>,132 option_count: usize,133 enum_options_docs: impl Iterator<Item = syn::Result<Vec<proc_macro2::TokenStream>>>,134 docs: &[proc_macro2::TokenStream],135) -> proc_macro2::TokenStream {136 let string_name = name.to_string();137 let enum_options = enum_options138 .zip(enum_options_docs)139 .enumerate()140 .map(|(i, (opt, doc))| {141 let opt = proc_macro2::Literal::string(opt.to_string().as_str());142 let doc = doc.expect("Doc parsing error");143 let comma = if i != option_count - 1 { "," } else { "" };144 quote! {145 #(#doc)*146 writeln!(str, "\t{}{}", #opt, #comma).expect("Enum format option");147 }148 });149150 quote!(151 #[cfg(feature = "stubgen")]152 impl ::evm_coder::solidity::StructCollect for #name {153 fn name() -> String {154 #string_name.into()155 }156157 fn declaration() -> String {158 use std::fmt::Write;159160 let mut str = String::new();161 #(#docs)*162 writeln!(str, "enum {} {{", <Self as ::evm_coder::solidity::StructCollect>::name()).unwrap();163 #(#enum_options)*164 writeln!(str, "}}").unwrap();165 str166 }167 }168 )169}170171pub fn check_and_count_options(de: &syn::DataEnum) -> syn::Result<usize> {172 let mut count = 0;173 for v in de.variants.iter() {174 if !v.fields.is_empty() {175 return Err(syn::Error::new(176 v.ident.span(),177 "Enumeration parameters should not have fields",178 ));179 } else if v.discriminant.is_some() {180 return Err(syn::Error::new(181 v.ident.span(),182 "Enumeration options should not have an explicit specified value",183 ));184 } else {185 count += 1;186 }187 }188189 Ok(count)190}191192pub fn check_repr_u8(name: &syn::Ident, attrs: &[syn::Attribute]) -> syn::Result<()> {193 let mut has_repr = false;194 for attr in attrs.iter() {195 if attr.path.is_ident("repr") {196 has_repr = true;197 let meta = attr.parse_meta()?;198 check_meta_u8(&meta)?;199 }200 }201202 if !has_repr {203 return Err(syn::Error::new(name.span(), "Enum is not \"repr(u8)\""));204 }205206 Ok(())207}208209fn check_meta_u8(meta: &syn::Meta) -> Result<(), syn::Error> {210 if let syn::Meta::List(p) = meta {211 for nm in p.nested.iter() {212 if let syn::NestedMeta::Meta(syn::Meta::Path(p)) = nm {213 if !p.is_ident("u8") {214 return Err(syn::Error::new(215 p.segments216 .first()217 .expect("repr segments are empty")218 .ident219 .span(),220 "Enum is not \"repr(u8)\"",221 ));222 }223 }224 }225 }226 Ok(())227}crates/evm-coder/procedural/src/abi_derive/mod.rsdiffbeforeafterboth--- a/crates/evm-coder/procedural/src/abi_derive/mod.rs
+++ b/crates/evm-coder/procedural/src/abi_derive/mod.rs
@@ -86,6 +86,7 @@
let abi_type = impl_enum_abi_type(name, option_count);
let abi_read = impl_enum_abi_read(name);
let abi_write = impl_enum_abi_write(name);
+ let solidity_type = impl_enum_solidity_type(name);
let solidity_type_name = impl_enum_solidity_type_name(name);
let solidity_struct_collect = impl_enum_solidity_struct_collect(
name,
@@ -102,6 +103,7 @@
#abi_type
#abi_read
#abi_write
+ #solidity_type
#solidity_type_name
#solidity_struct_collect
})
crates/evm-coder/src/abi/impls.rsdiffbeforeafterboth--- a/crates/evm-coder/src/abi/impls.rs
+++ b/crates/evm-coder/src/abi/impls.rs
@@ -184,6 +184,11 @@
}
}
+macro_rules! count {
+ () => (0usize);
+ ( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*));
+}
+
macro_rules! impl_tuples {
($($ident:ident)+) => {
impl<$($ident: AbiType,)+> AbiType for ($($ident,)+)
@@ -198,7 +203,7 @@
shift_left(1)
fixed(")")
);
- const FIELDS_COUNT: usize = 0 $(+ {let _ = <$ident as AbiType>::FIELDS_COUNT; 1})+;
+ const FIELDS_COUNT: usize = count!($($ident)*);
fn is_dynamic() -> bool {
false
crates/evm-coder/src/solidity/impls.rsdiffbeforeafterboth--- a/crates/evm-coder/src/solidity/impls.rs
+++ b/crates/evm-coder/src/solidity/impls.rs
@@ -74,6 +74,16 @@
}
}
+impl<T: StructCollect + sealed::CanBePlacedInVec> StructCollect for Vec<T> {
+ fn name() -> String {
+ <T as StructCollect>::name() + "[]"
+ }
+
+ fn declaration() -> String {
+ unimplemented!("Vectors have not declarations.")
+ }
+}
+
macro_rules! count {
() => (0usize);
( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*));
@@ -131,60 +141,3 @@
impl_tuples! {A B C D E F G H}
impl_tuples! {A B C D E F G H I}
impl_tuples! {A B C D E F G H I J}
-
-impl StructCollect for Property {
- fn name() -> String {
- "Property".into()
- }
-
- fn declaration() -> String {
- use std::fmt::Write;
-
- let mut str = String::new();
- writeln!(str, "/// @dev Property struct").unwrap();
- writeln!(str, "struct {} {{", Self::name()).unwrap();
- writeln!(str, "\tstring key;").unwrap();
- writeln!(str, "\tbytes value;").unwrap();
- writeln!(str, "}}").unwrap();
- str
- }
-}
-
-impl SolidityTypeName for Property {
- fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
- write!(writer, "{}", tc.collect_struct::<Self>())
- }
-
- fn is_simple() -> bool {
- false
- }
-
- fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
- write!(writer, "{}(", tc.collect_struct::<Self>())?;
- address::solidity_default(writer, tc)?;
- write!(writer, ",")?;
- uint256::solidity_default(writer, tc)?;
- write!(writer, ")")
- }
-}
-
-impl SolidityType for Property {
- fn names(tc: &TypeCollector) -> Vec<string> {
- let mut collected = Vec::with_capacity(Self::len());
- {
- let mut out = string::new();
- string::solidity_name(&mut out, tc).expect("no fmt error");
- collected.push(out);
- }
- {
- let mut out = string::new();
- bytes::solidity_name(&mut out, tc).expect("no fmt error");
- collected.push(out);
- }
- collected
- }
-
- fn len() -> usize {
- 2
- }
-}
crates/evm-coder/src/solidity/mod.rsdiffbeforeafterboth--- a/crates/evm-coder/src/solidity/mod.rs
+++ b/crates/evm-coder/src/solidity/mod.rs
@@ -76,7 +76,8 @@
self.anonymous.borrow_mut().insert(names, id);
format!("Tuple{}", id)
}
- pub fn collect_struct<T: StructCollect>(&self) -> String {
+ pub fn collect_struct<T: StructCollect + SolidityType>(&self) -> String {
+ let _names = T::names(self);
self.collect(<T as StructCollect>::declaration());
<T as StructCollect>::name()
}
crates/evm-coder/tests/abi_derive_generation.rsdiffbeforeafterboth--- a/crates/evm-coder/tests/abi_derive_generation.rs
+++ b/crates/evm-coder/tests/abi_derive_generation.rs
@@ -100,6 +100,15 @@
}
#[test]
+ #[cfg(feature = "stubgen")]
+ fn struct_collect_vec() {
+ assert_eq!(
+ <Vec<u8> as ::evm_coder::solidity::StructCollect>::name(),
+ "uint8[]"
+ );
+ }
+
+ #[test]
fn impl_abi_type_signature() {
assert_eq!(
<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::SIGNATURE
pallets/common/src/eth.rsdiffbeforeafterboth--- a/pallets/common/src/eth.rs
+++ b/pallets/common/src/eth.rs
@@ -16,6 +16,7 @@
//! The module contains a number of functions for converting and checking ethereum identifiers.
+use sp_std::{vec, vec::Vec};
use evm_coder::{
AbiCoder,
types::{uint256, address},
@@ -183,3 +184,102 @@
/// Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]
CollectionAdmin,
}
+
+/// Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) as an key and value.
+#[derive(Debug, Default, AbiCoder)]
+pub struct PropertyPermission {
+ /// TokenPermission field.
+ code: EthTokenPermissions,
+ /// TokenPermission value.
+ value: bool,
+}
+
+impl PropertyPermission {
+ pub fn into_vec(pp: up_data_structs::PropertyPermission) -> Vec<Self> {
+ vec![
+ PropertyPermission {
+ code: EthTokenPermissions::Mutable,
+ value: pp.mutable,
+ },
+ PropertyPermission {
+ code: EthTokenPermissions::TokenOwner,
+ value: pp.token_owner,
+ },
+ PropertyPermission {
+ code: EthTokenPermissions::CollectionAdmin,
+ value: pp.collection_admin,
+ },
+ ]
+ }
+
+ pub fn from_vec(permission: Vec<Self>) -> up_data_structs::PropertyPermission {
+ let mut token_permission = up_data_structs::PropertyPermission::default();
+
+ for PropertyPermission { code, value } in permission {
+ match code {
+ EthTokenPermissions::Mutable => token_permission.mutable = value,
+ EthTokenPermissions::TokenOwner => token_permission.token_owner = value,
+ EthTokenPermissions::CollectionAdmin => token_permission.collection_admin = value,
+ }
+ }
+ token_permission
+ }
+}
+
+/// Ethereum representation of Token Property Permissions.
+#[derive(Debug, Default, AbiCoder)]
+pub struct TokenPropertyPermission {
+ /// Token property key.
+ key: evm_coder::types::string,
+ /// Token property permissions.
+ permissions: Vec<PropertyPermission>,
+}
+
+impl
+ From<(
+ up_data_structs::PropertyKey,
+ up_data_structs::PropertyPermission,
+ )> for TokenPropertyPermission
+{
+ fn from(
+ value: (
+ up_data_structs::PropertyKey,
+ up_data_structs::PropertyPermission,
+ ),
+ ) -> Self {
+ let (key, permission) = value;
+ let key = evm_coder::types::string::from_utf8(key.into_inner())
+ .expect("Stored key must be valid");
+ let permissions = PropertyPermission::into_vec(permission);
+ Self { key, permissions }
+ }
+}
+
+impl TokenPropertyPermission {
+ pub fn into_property_key_permissions(
+ permissions: Vec<TokenPropertyPermission>,
+ ) -> evm_coder::execution::Result<Vec<up_data_structs::PropertyKeyPermission>> {
+ let mut perms = Vec::new();
+
+ for TokenPropertyPermission { key, permissions } in permissions {
+ if permissions.len() > <EthTokenPermissions as evm_coder::abi::AbiType>::FIELDS_COUNT {
+ return Err(alloc::format!(
+ "Actual number of fields {} for {}, which exceeds the maximum value of {}",
+ permissions.len(),
+ stringify!(EthTokenPermissions),
+ <EthTokenPermissions as evm_coder::abi::AbiType>::FIELDS_COUNT
+ )
+ .as_str()
+ .into());
+ }
+
+ let token_permission = PropertyPermission::from_vec(permissions);
+
+ perms.push(up_data_structs::PropertyKeyPermission {
+ key: key.into_bytes().try_into().map_err(|_| "too long key")?,
+ permission: token_permission,
+ });
+ }
+ Ok(perms)
+ }
+}
pallets/evm-contract-helpers/src/stubs/ContractHelpers.rawdiffbeforeafterbothbinary blob — no preview
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
@@ -470,9 +470,12 @@
uint256 sub;
}
+/// @dev Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.
enum CollectionPermissions {
- CollectionAdmin,
- TokenOwner
+ /// @dev Owner of token can nest tokens under it.
+ TokenOwner,
+ /// @dev Admin of token collection can nest tokens under token.
+ CollectionAdmin
}
/// @dev anonymous struct
@@ -516,9 +519,11 @@
uint256 field_2;
}
-/// @dev Property struct
+/// @dev Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).
struct Property {
+ /// @dev Property key.
string key;
+ /// @dev Property value.
bytes value;
}
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::{Property as PropertyStruct, EthCrossAccount, EthTokenPermissions},
+ eth::{Property as PropertyStruct, EthCrossAccount},
};
use pallet_evm::{account::CrossAccountId, PrecompileHandle};
use pallet_evm_coder_substrate::call;
@@ -94,40 +94,12 @@
fn set_token_property_permissions(
&mut self,
caller: caller,
- permissions: Vec<(string, Vec<(EthTokenPermissions, bool)>)>,
+ permissions: Vec<pallet_common::eth::TokenPropertyPermission>,
) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
- let mut perms = Vec::new();
-
- for (key, pp) in permissions {
- if pp.len() > EthTokenPermissions::FIELDS_COUNT {
- return Err(alloc::format!(
- "Actual number of fields {} for {}, which exceeds the maximum value of {}",
- pp.len(),
- stringify!(EthTokenPermissions),
- EthTokenPermissions::FIELDS_COUNT
- )
- .as_str()
- .into());
- }
-
- let mut token_permission = PropertyPermission::default();
-
- for (perm, value) in pp {
- match perm {
- EthTokenPermissions::Mutable => token_permission.mutable = value,
- EthTokenPermissions::TokenOwner => token_permission.token_owner = value,
- EthTokenPermissions::CollectionAdmin => {
- token_permission.collection_admin = value
- }
- }
- }
-
- perms.push(PropertyKeyPermission {
- key: key.into_bytes().try_into().map_err(|_| "too long key")?,
- permission: token_permission,
- });
- }
+ let perms = pallet_common::eth::TokenPropertyPermission::into_property_key_permissions(
+ permissions,
+ )?;
<Pallet<T>>::set_token_property_permissions(self, &caller, perms)
.map_err(dispatch_to_evm::<T>)
@@ -136,19 +108,11 @@
/// @notice Get permissions for token properties.
fn token_property_permissions(
&self,
- ) -> Result<Vec<(string, Vec<(EthTokenPermissions, bool)>)>> {
+ ) -> Result<Vec<pallet_common::eth::TokenPropertyPermission>> {
let perms = <Pallet<T>>::token_property_permission(self.id);
Ok(perms
.into_iter()
- .map(|(key, pp)| {
- let key = string::from_utf8(key.into_inner()).expect("Stored key must be valid");
- let pp = vec![
- (EthTokenPermissions::Mutable, pp.mutable),
- (EthTokenPermissions::TokenOwner, pp.token_owner),
- (EthTokenPermissions::CollectionAdmin, pp.collection_admin),
- ];
- (key, pp)
- })
+ .map(pallet_common::eth::TokenPropertyPermission::from)
.collect())
}
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
@@ -42,7 +42,7 @@
/// @param permissions Permissions for keys.
/// @dev EVM selector for this function is: 0xbd92983a,
/// or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])
- function setTokenPropertyPermissions(Tuple61[] memory permissions) public {
+ function setTokenPropertyPermissions(TokenPropertyPermission[] memory permissions) public {
require(false, stub_error);
permissions;
dummy = 0;
@@ -51,10 +51,10 @@
/// @notice Get permissions for token properties.
/// @dev EVM selector for this function is: 0xf23d7790,
/// or in textual repr: tokenPropertyPermissions()
- function tokenPropertyPermissions() public view returns (Tuple61[] memory) {
+ function tokenPropertyPermissions() public view returns (TokenPropertyPermission[] memory) {
require(false, stub_error);
dummy;
- return new Tuple61[](0);
+ return new TokenPropertyPermission[](0);
}
// /// @notice Set token property value.
@@ -127,12 +127,30 @@
}
}
-/// @dev Property struct
+/// @dev Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).
struct Property {
+ /// @dev Property key.
string key;
+ /// @dev Property value.
bytes value;
}
+/// @dev Ethereum representation of Token Property Permissions.
+struct TokenPropertyPermission {
+ /// @dev Token property key.
+ string key;
+ /// @dev Token property permissions.
+ PropertyPermission[] permissions;
+}
+
+/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) as an key and value.
+struct PropertyPermission {
+ /// @dev TokenPermission field.
+ EthTokenPermissions code;
+ /// @dev TokenPermission value.
+ bool value;
+}
+
/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.
enum EthTokenPermissions {
/// @dev Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]
@@ -141,18 +159,6 @@
TokenOwner,
/// @dev Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]
CollectionAdmin
-}
-
-/// @dev anonymous struct
-struct Tuple61 {
- string field_0;
- Tuple59[] field_1;
-}
-
-/// @dev anonymous struct
-struct Tuple59 {
- EthTokenPermissions field_0;
- bool field_1;
}
/// @title A contract that allows you to work with collections.
@@ -608,9 +614,12 @@
uint256 sub;
}
+/// @dev Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.
enum CollectionPermissions {
- CollectionAdmin,
- TokenOwner
+ /// @dev Owner of token can nest tokens under it.
+ TokenOwner,
+ /// @dev Admin of token collection can nest tokens under token.
+ CollectionAdmin
}
/// @dev anonymous struct
pallets/refungible/src/erc.rsdiffbeforeafterboth--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -33,7 +33,7 @@
use pallet_common::{
CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations,
erc::{CommonEvmHandler, CollectionCall, static_property::key},
- eth::{Property as PropertyStruct, EthCrossAccount, EthTokenPermissions},
+ eth::{Property as PropertyStruct, EthCrossAccount},
Error as CommonError,
};
use pallet_evm::{account::CrossAccountId, PrecompileHandle};
@@ -97,47 +97,13 @@
fn set_token_property_permissions(
&mut self,
caller: caller,
- permissions: Vec<(string, Vec<(EthTokenPermissions, bool)>)>,
+ permissions: Vec<pallet_common::eth::TokenPropertyPermission>,
) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
- const PERMISSIONS_FIELDS_COUNT: usize = 3;
-
- let mut perms = Vec::new();
-
- for (key, pp) in permissions {
- if pp.len() > PERMISSIONS_FIELDS_COUNT {
- return Err(alloc::format!(
- "Actual number of fields {} for {}, which exceeds the maximum value of {}",
- pp.len(),
- stringify!(EthTokenPermissions),
- PERMISSIONS_FIELDS_COUNT
- )
- .as_str()
- .into());
- }
-
- let mut token_permission = PropertyPermission {
- mutable: false,
- collection_admin: false,
- token_owner: false,
- };
+ let perms = pallet_common::eth::TokenPropertyPermission::into_property_key_permissions(
+ permissions,
+ )?;
- for (perm, value) in pp {
- match perm {
- EthTokenPermissions::Mutable => token_permission.mutable = value,
- EthTokenPermissions::TokenOwner => token_permission.token_owner = value,
- EthTokenPermissions::CollectionAdmin => {
- token_permission.collection_admin = value
- }
- }
- }
-
- perms.push(PropertyKeyPermission {
- key: key.into_bytes().try_into().map_err(|_| "too long key")?,
- permission: token_permission,
- });
- }
-
<Pallet<T>>::set_token_property_permissions(self, &caller, perms)
.map_err(dispatch_to_evm::<T>)
}
@@ -145,19 +111,11 @@
/// @notice Get permissions for token properties.
fn token_property_permissions(
&self,
- ) -> Result<Vec<(string, Vec<(EthTokenPermissions, bool)>)>> {
+ ) -> Result<Vec<pallet_common::eth::TokenPropertyPermission>> {
let perms = <Pallet<T>>::token_property_permission(self.id);
Ok(perms
.into_iter()
- .map(|(key, pp)| {
- let key = string::from_utf8(key.into_inner()).expect("Stored key must be valid");
- let pp = vec![
- (EthTokenPermissions::Mutable, pp.mutable),
- (EthTokenPermissions::TokenOwner, pp.token_owner),
- (EthTokenPermissions::CollectionAdmin, pp.collection_admin),
- ];
- (key, pp)
- })
+ .map(pallet_common::eth::TokenPropertyPermission::from)
.collect())
}
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
@@ -42,7 +42,7 @@
/// @param permissions Permissions for keys.
/// @dev EVM selector for this function is: 0xbd92983a,
/// or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])
- function setTokenPropertyPermissions(Tuple60[] memory permissions) public {
+ function setTokenPropertyPermissions(TokenPropertyPermission[] memory permissions) public {
require(false, stub_error);
permissions;
dummy = 0;
@@ -51,10 +51,10 @@
/// @notice Get permissions for token properties.
/// @dev EVM selector for this function is: 0xf23d7790,
/// or in textual repr: tokenPropertyPermissions()
- function tokenPropertyPermissions() public view returns (Tuple60[] memory) {
+ function tokenPropertyPermissions() public view returns (TokenPropertyPermission[] memory) {
require(false, stub_error);
dummy;
- return new Tuple60[](0);
+ return new TokenPropertyPermission[](0);
}
// /// @notice Set token property value.
@@ -127,12 +127,30 @@
}
}
-/// @dev Property struct
+/// @dev Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).
struct Property {
+ /// @dev Property key.
string key;
+ /// @dev Property value.
bytes value;
}
+/// @dev Ethereum representation of Token Property Permissions.
+struct TokenPropertyPermission {
+ /// @dev Token property key.
+ string key;
+ /// @dev Token property permissions.
+ PropertyPermission[] permissions;
+}
+
+/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) as an key and value.
+struct PropertyPermission {
+ /// @dev TokenPermission field.
+ EthTokenPermissions code;
+ /// @dev TokenPermission value.
+ bool value;
+}
+
/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.
enum EthTokenPermissions {
/// @dev Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]
@@ -141,18 +159,6 @@
TokenOwner,
/// @dev Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]
CollectionAdmin
-}
-
-/// @dev anonymous struct
-struct Tuple60 {
- string field_0;
- Tuple58[] field_1;
-}
-
-/// @dev anonymous struct
-struct Tuple58 {
- EthTokenPermissions field_0;
- bool field_1;
}
/// @title A contract that allows you to work with collections.
@@ -608,9 +614,12 @@
uint256 sub;
}
+/// @dev Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.
enum CollectionPermissions {
- CollectionAdmin,
- TokenOwner
+ /// @dev Owner of token can nest tokens under it.
+ TokenOwner,
+ /// @dev Admin of token collection can nest tokens under token.
+ CollectionAdmin
}
/// @dev anonymous struct
pallets/refungible/src/stubs/UniqueRefungibleToken.rawdiffbeforeafterbothbinary blob — no preview
pallets/unique/src/eth/stubs/CollectionHelpers.rawdiffbeforeafterbothbinary blob — no preview
tests/src/eth/abi/nonFungible.jsondiffbeforeafterboth--- a/tests/src/eth/abi/nonFungible.json
+++ b/tests/src/eth/abi/nonFungible.json
@@ -752,22 +752,22 @@
"inputs": [
{
"components": [
- { "internalType": "string", "name": "field_0", "type": "string" },
+ { "internalType": "string", "name": "key", "type": "string" },
{
"components": [
{
"internalType": "enum EthTokenPermissions",
- "name": "field_0",
+ "name": "code",
"type": "uint8"
},
- { "internalType": "bool", "name": "field_1", "type": "bool" }
+ { "internalType": "bool", "name": "value", "type": "bool" }
],
- "internalType": "struct Tuple59[]",
- "name": "field_1",
+ "internalType": "struct PropertyPermission[]",
+ "name": "permissions",
"type": "tuple[]"
}
],
- "internalType": "struct Tuple61[]",
+ "internalType": "struct TokenPropertyPermission[]",
"name": "permissions",
"type": "tuple[]"
}
@@ -818,22 +818,22 @@
"outputs": [
{
"components": [
- { "internalType": "string", "name": "field_0", "type": "string" },
+ { "internalType": "string", "name": "key", "type": "string" },
{
"components": [
{
"internalType": "enum EthTokenPermissions",
- "name": "field_0",
+ "name": "code",
"type": "uint8"
},
- { "internalType": "bool", "name": "field_1", "type": "bool" }
+ { "internalType": "bool", "name": "value", "type": "bool" }
],
- "internalType": "struct Tuple59[]",
- "name": "field_1",
+ "internalType": "struct PropertyPermission[]",
+ "name": "permissions",
"type": "tuple[]"
}
],
- "internalType": "struct Tuple61[]",
+ "internalType": "struct TokenPropertyPermission[]",
"name": "",
"type": "tuple[]"
}
tests/src/eth/abi/reFungible.jsondiffbeforeafterboth--- a/tests/src/eth/abi/reFungible.json
+++ b/tests/src/eth/abi/reFungible.json
@@ -734,22 +734,22 @@
"inputs": [
{
"components": [
- { "internalType": "string", "name": "field_0", "type": "string" },
+ { "internalType": "string", "name": "key", "type": "string" },
{
"components": [
{
"internalType": "enum EthTokenPermissions",
- "name": "field_0",
+ "name": "code",
"type": "uint8"
},
- { "internalType": "bool", "name": "field_1", "type": "bool" }
+ { "internalType": "bool", "name": "value", "type": "bool" }
],
- "internalType": "struct Tuple58[]",
- "name": "field_1",
+ "internalType": "struct PropertyPermission[]",
+ "name": "permissions",
"type": "tuple[]"
}
],
- "internalType": "struct Tuple60[]",
+ "internalType": "struct TokenPropertyPermission[]",
"name": "permissions",
"type": "tuple[]"
}
@@ -809,22 +809,22 @@
"outputs": [
{
"components": [
- { "internalType": "string", "name": "field_0", "type": "string" },
+ { "internalType": "string", "name": "key", "type": "string" },
{
"components": [
{
"internalType": "enum EthTokenPermissions",
- "name": "field_0",
+ "name": "code",
"type": "uint8"
},
- { "internalType": "bool", "name": "field_1", "type": "bool" }
+ { "internalType": "bool", "name": "value", "type": "bool" }
],
- "internalType": "struct Tuple58[]",
- "name": "field_1",
+ "internalType": "struct PropertyPermission[]",
+ "name": "permissions",
"type": "tuple[]"
}
],
- "internalType": "struct Tuple60[]",
+ "internalType": "struct TokenPropertyPermission[]",
"name": "",
"type": "tuple[]"
}
tests/src/eth/api/UniqueFungible.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueFungible.sol
+++ b/tests/src/eth/api/UniqueFungible.sol
@@ -316,9 +316,12 @@
bool field_1;
}
+/// @dev Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.
enum CollectionPermissions {
- CollectionAdmin,
- TokenOwner
+ /// @dev Owner of token can nest tokens under it.
+ TokenOwner,
+ /// @dev Admin of token collection can nest tokens under token.
+ CollectionAdmin
}
/// @dev anonymous struct
@@ -356,9 +359,11 @@
uint256 field_2;
}
-/// @dev Property struct
+/// @dev Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).
struct Property {
+ /// @dev Property key.
string key;
+ /// @dev Property value.
bytes value;
}
tests/src/eth/api/UniqueNFT.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -30,12 +30,12 @@
/// @param permissions Permissions for keys.
/// @dev EVM selector for this function is: 0xbd92983a,
/// or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])
- function setTokenPropertyPermissions(Tuple53[] memory permissions) external;
+ function setTokenPropertyPermissions(TokenPropertyPermission[] memory permissions) external;
/// @notice Get permissions for token properties.
/// @dev EVM selector for this function is: 0xf23d7790,
/// or in textual repr: tokenPropertyPermissions()
- function tokenPropertyPermissions() external view returns (Tuple53[] memory);
+ function tokenPropertyPermissions() external view returns (TokenPropertyPermission[] memory);
// /// @notice Set token property value.
// /// @dev Throws error if `msg.sender` has no permission to edit the property.
@@ -80,12 +80,30 @@
function property(uint256 tokenId, string memory key) external view returns (bytes memory);
}
-/// @dev Property struct
+/// @dev Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).
struct Property {
+ /// @dev Property key.
string key;
+ /// @dev Property value.
bytes value;
}
+/// @dev Ethereum representation of Token Property Permissions.
+struct TokenPropertyPermission {
+ /// @dev Token property key.
+ string key;
+ /// @dev Token property permissions.
+ PropertyPermission[] permissions;
+}
+
+/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) as an key and value.
+struct PropertyPermission {
+ /// @dev TokenPermission field.
+ EthTokenPermissions code;
+ /// @dev TokenPermission value.
+ bool value;
+}
+
/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.
enum EthTokenPermissions {
/// @dev Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]
@@ -96,18 +114,6 @@
CollectionAdmin
}
-/// @dev anonymous struct
-struct Tuple53 {
- string field_0;
- Tuple51[] field_1;
-}
-
-/// @dev anonymous struct
-struct Tuple51 {
- EthTokenPermissions field_0;
- bool field_1;
-}
-
/// @title A contract that allows you to work with collections.
/// @dev the ERC-165 identifier for this interface is 0x81172a75
interface Collection is Dummy, ERC165 {
@@ -412,9 +418,12 @@
bool field_1;
}
+/// @dev Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.
enum CollectionPermissions {
- CollectionAdmin,
- TokenOwner
+ /// @dev Owner of token can nest tokens under it.
+ TokenOwner,
+ /// @dev Admin of token collection can nest tokens under token.
+ CollectionAdmin
}
/// @dev anonymous struct
tests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueRefungible.sol
+++ b/tests/src/eth/api/UniqueRefungible.sol
@@ -30,12 +30,12 @@
/// @param permissions Permissions for keys.
/// @dev EVM selector for this function is: 0xbd92983a,
/// or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])
- function setTokenPropertyPermissions(Tuple52[] memory permissions) external;
+ function setTokenPropertyPermissions(TokenPropertyPermission[] memory permissions) external;
/// @notice Get permissions for token properties.
/// @dev EVM selector for this function is: 0xf23d7790,
/// or in textual repr: tokenPropertyPermissions()
- function tokenPropertyPermissions() external view returns (Tuple52[] memory);
+ function tokenPropertyPermissions() external view returns (TokenPropertyPermission[] memory);
// /// @notice Set token property value.
// /// @dev Throws error if `msg.sender` has no permission to edit the property.
@@ -80,12 +80,30 @@
function property(uint256 tokenId, string memory key) external view returns (bytes memory);
}
-/// @dev Property struct
+/// @dev Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).
struct Property {
+ /// @dev Property key.
string key;
+ /// @dev Property value.
bytes value;
}
+/// @dev Ethereum representation of Token Property Permissions.
+struct TokenPropertyPermission {
+ /// @dev Token property key.
+ string key;
+ /// @dev Token property permissions.
+ PropertyPermission[] permissions;
+}
+
+/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) as an key and value.
+struct PropertyPermission {
+ /// @dev TokenPermission field.
+ EthTokenPermissions code;
+ /// @dev TokenPermission value.
+ bool value;
+}
+
/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.
enum EthTokenPermissions {
/// @dev Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]
@@ -96,18 +114,6 @@
CollectionAdmin
}
-/// @dev anonymous struct
-struct Tuple52 {
- string field_0;
- Tuple50[] field_1;
-}
-
-/// @dev anonymous struct
-struct Tuple50 {
- EthTokenPermissions field_0;
- bool field_1;
-}
-
/// @title A contract that allows you to work with collections.
/// @dev the ERC-165 identifier for this interface is 0x81172a75
interface Collection is Dummy, ERC165 {
@@ -412,9 +418,12 @@
bool field_1;
}
+/// @dev Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.
enum CollectionPermissions {
- CollectionAdmin,
- TokenOwner
+ /// @dev Owner of token can nest tokens under it.
+ TokenOwner,
+ /// @dev Admin of token collection can nest tokens under token.
+ CollectionAdmin
}
/// @dev anonymous struct