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.rsdiffbeforeafterboth--- a/crates/evm-coder/procedural/src/abi_derive/derive_enum.rs
+++ b/crates/evm-coder/procedural/src/abi_derive/derive_enum.rs
@@ -86,6 +86,21 @@
)
}
+pub fn impl_enum_solidity_type<'a>(name: &syn::Ident) -> proc_macro2::TokenStream {
+ quote! {
+ #[cfg(feature = "stubgen")]
+ impl ::evm_coder::solidity::SolidityType for #name {
+ fn names(tc: &::evm_coder::solidity::TypeCollector) -> Vec<String> {
+ Vec::new()
+ }
+
+ fn len() -> usize {
+ 1
+ }
+ }
+ }
+}
+
pub fn impl_enum_solidity_type_name(name: &syn::Ident) -> proc_macro2::TokenStream {
quote!(
#[cfg(feature = "stubgen")]
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.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//! Implementation detail of [`crate::solidity_interface`] macro code-generation.18//! You should not rely on any public item from this module, as it is only intended to be used19//! by procedural macro, API and output format may be changed at any time.20//!21//! Purpose of this module is to receive solidity contract definition in module-specified22//! format, and then output string, representing interface of this contract in solidity language2324mod traits;25pub use traits::*;26mod impls;2728#[cfg(not(feature = "std"))]29use alloc::{string::String, vec::Vec, collections::BTreeMap, format};30#[cfg(feature = "std")]31use std::collections::BTreeMap;32use core::{33 fmt::{self, Write},34 marker::PhantomData,35 cell::{Cell, RefCell},36 cmp::Reverse,37};38use impl_trait_for_tuples::impl_for_tuples;39use crate::{types::*, custom_signature::SignatureUnit};4041#[derive(Default)]42pub struct TypeCollector {43 /// Code => id44 /// id ordering is required to perform topo-sort on the resulting data45 structs: RefCell<BTreeMap<string, usize>>,46 anonymous: RefCell<BTreeMap<Vec<string>, usize>>,47 id: Cell<usize>,48}49impl TypeCollector {50 pub fn new() -> Self {51 Self::default()52 }53 pub fn collect(&self, item: string) {54 let id = self.next_id();55 self.structs.borrow_mut().insert(item, id);56 }57 pub fn next_id(&self) -> usize {58 let v = self.id.get();59 self.id.set(v + 1);60 v61 }62 pub fn collect_tuple<T: SolidityType>(&self) -> String {63 let names = T::names(self);64 if let Some(id) = self.anonymous.borrow().get(&names).cloned() {65 return format!("Tuple{}", id);66 }67 let id = self.next_id();68 let mut str = String::new();69 writeln!(str, "/// @dev anonymous struct").unwrap();70 writeln!(str, "struct Tuple{} {{", id).unwrap();71 for (i, name) in names.iter().enumerate() {72 writeln!(str, "\t{} field_{};", name, i).unwrap();73 }74 writeln!(str, "}}").unwrap();75 self.collect(str);76 self.anonymous.borrow_mut().insert(names, id);77 format!("Tuple{}", id)78 }79 pub fn collect_struct<T: StructCollect>(&self) -> String {80 self.collect(<T as StructCollect>::declaration());81 <T as StructCollect>::name()82 }83 pub fn finish(self) -> Vec<string> {84 let mut data = self.structs.into_inner().into_iter().collect::<Vec<_>>();85 data.sort_by_key(|(_, id)| Reverse(*id));86 data.into_iter().map(|(code, _)| code).collect()87 }88}89#[derive(Default)]90pub struct UnnamedArgument<T>(PhantomData<*const T>);9192impl<T: SolidityTypeName> SolidityArguments for UnnamedArgument<T> {93 fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {94 if !T::is_void() {95 T::solidity_name(writer, tc)?;96 if !T::is_simple() {97 write!(writer, " memory")?;98 }99 Ok(())100 } else {101 Ok(())102 }103 }104 fn solidity_get(&self, _prefix: &str, _writer: &mut impl fmt::Write) -> fmt::Result {105 Ok(())106 }107 fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {108 T::solidity_default(writer, tc)109 }110 fn len(&self) -> usize {111 if T::is_void() {112 0113 } else {114 1115 }116 }117}118119pub struct NamedArgument<T>(&'static str, PhantomData<*const T>);120121impl<T> NamedArgument<T> {122 pub fn new(name: &'static str) -> Self {123 Self(name, Default::default())124 }125}126127impl<T: SolidityTypeName> SolidityArguments for NamedArgument<T> {128 fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {129 if !T::is_void() {130 T::solidity_name(writer, tc)?;131 if !T::is_simple() {132 write!(writer, " memory")?;133 }134 write!(writer, " {}", self.0)135 } else {136 Ok(())137 }138 }139 fn solidity_get(&self, prefix: &str, writer: &mut impl fmt::Write) -> fmt::Result {140 writeln!(writer, "\t{prefix}\t{};", self.0)141 }142 fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {143 T::solidity_default(writer, tc)144 }145 fn len(&self) -> usize {146 if T::is_void() {147 0148 } else {149 1150 }151 }152}153154pub struct SolidityEventArgument<T>(pub bool, &'static str, PhantomData<*const T>);155156impl<T> SolidityEventArgument<T> {157 pub fn new(indexed: bool, name: &'static str) -> Self {158 Self(indexed, name, Default::default())159 }160}161162impl<T: SolidityTypeName> SolidityArguments for SolidityEventArgument<T> {163 fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {164 if !T::is_void() {165 T::solidity_name(writer, tc)?;166 if self.0 {167 write!(writer, " indexed")?;168 }169 write!(writer, " {}", self.1)170 } else {171 Ok(())172 }173 }174 fn solidity_get(&self, prefix: &str, writer: &mut impl fmt::Write) -> fmt::Result {175 writeln!(writer, "\t{prefix}\t{};", self.1)176 }177 fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {178 T::solidity_default(writer, tc)179 }180 fn len(&self) -> usize {181 if T::is_void() {182 0183 } else {184 1185 }186 }187}188189impl SolidityArguments for () {190 fn solidity_name(&self, _writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result {191 Ok(())192 }193 fn solidity_get(&self, _prefix: &str, _writer: &mut impl fmt::Write) -> fmt::Result {194 Ok(())195 }196 fn solidity_default(&self, _writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result {197 Ok(())198 }199 fn len(&self) -> usize {200 0201 }202}203204#[impl_for_tuples(1, 12)]205impl SolidityArguments for Tuple {206 for_tuples!( where #( Tuple: SolidityArguments ),* );207208 fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {209 let mut first = true;210 for_tuples!( #(211 if !Tuple.is_empty() {212 if !first {213 write!(writer, ", ")?;214 }215 first = false;216 Tuple.solidity_name(writer, tc)?;217 }218 )* );219 Ok(())220 }221 fn solidity_get(&self, prefix: &str, writer: &mut impl fmt::Write) -> fmt::Result {222 for_tuples!( #(223 Tuple.solidity_get(prefix, writer)?;224 )* );225 Ok(())226 }227 fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {228 if self.is_empty() {229 Ok(())230 } else if self.len() == 1 {231 for_tuples!( #(232 Tuple.solidity_default(writer, tc)?;233 )* );234 Ok(())235 } else {236 write!(writer, "(")?;237 let mut first = true;238 for_tuples!( #(239 if !Tuple.is_empty() {240 if !first {241 write!(writer, ", ")?;242 }243 first = false;244 Tuple.solidity_default(writer, tc)?;245 }246 )* );247 write!(writer, ")")?;248 Ok(())249 }250 }251 fn len(&self) -> usize {252 for_tuples!( #( Tuple.len() )+* )253 }254}255256pub enum SolidityMutability {257 Pure,258 View,259 Mutable,260}261pub struct SolidityFunction<A, R> {262 pub docs: &'static [&'static str],263 pub selector: u32,264 pub hide: bool,265 pub custom_signature: SignatureUnit,266 pub name: &'static str,267 pub args: A,268 pub result: R,269 pub mutability: SolidityMutability,270 pub is_payable: bool,271}272impl<A: SolidityArguments, R: SolidityArguments> SolidityFunctions for SolidityFunction<A, R> {273 fn solidity_name(274 &self,275 is_impl: bool,276 writer: &mut impl fmt::Write,277 tc: &TypeCollector,278 ) -> fmt::Result {279 let hide_comment = self.hide.then_some("// ").unwrap_or("");280 for doc in self.docs {281 writeln!(writer, "\t{hide_comment}///{}", doc)?;282 }283 writeln!(284 writer,285 "\t{hide_comment}/// @dev EVM selector for this function is: 0x{:0>8x},",286 self.selector287 )?;288 writeln!(289 writer,290 "\t{hide_comment}/// or in textual repr: {}",291 self.custom_signature.as_str().expect("bad utf-8")292 )?;293 write!(writer, "\t{hide_comment}function {}(", self.name)?;294 self.args.solidity_name(writer, tc)?;295 write!(writer, ")")?;296 if is_impl {297 write!(writer, " public")?;298 } else {299 write!(writer, " external")?;300 }301 match &self.mutability {302 SolidityMutability::Pure => write!(writer, " pure")?,303 SolidityMutability::View => write!(writer, " view")?,304 SolidityMutability::Mutable => {}305 }306 if self.is_payable {307 write!(writer, " payable")?;308 }309 if !self.result.is_empty() {310 write!(writer, " returns (")?;311 self.result.solidity_name(writer, tc)?;312 write!(writer, ")")?;313 }314 if is_impl {315 writeln!(writer, " {{")?;316 writeln!(writer, "\t{hide_comment}\trequire(false, stub_error);")?;317 self.args.solidity_get(hide_comment, writer)?;318 match &self.mutability {319 SolidityMutability::Pure => {}320 SolidityMutability::View => writeln!(writer, "\t{hide_comment}\tdummy;")?,321 SolidityMutability::Mutable => writeln!(writer, "\t{hide_comment}\tdummy = 0;")?,322 }323 if !self.result.is_empty() {324 write!(writer, "\t{hide_comment}\treturn ")?;325 self.result.solidity_default(writer, tc)?;326 writeln!(writer, ";")?;327 }328 writeln!(writer, "\t{hide_comment}}}")?;329 } else {330 writeln!(writer, ";")?;331 }332 if self.hide {333 writeln!(writer, "// FORMATTING: FORCE NEWLINE")?;334 }335 Ok(())336 }337}338339#[impl_for_tuples(0, 48)]340impl SolidityFunctions for Tuple {341 for_tuples!( where #( Tuple: SolidityFunctions ),* );342343 fn solidity_name(344 &self,345 is_impl: bool,346 writer: &mut impl fmt::Write,347 tc: &TypeCollector,348 ) -> fmt::Result {349 let mut first = false;350 for_tuples!( #(351 Tuple.solidity_name(is_impl, writer, tc)?;352 )* );353 Ok(())354 }355}356357pub struct SolidityInterface<F: SolidityFunctions> {358 pub docs: &'static [&'static str],359 pub selector: bytes4,360 pub name: &'static str,361 pub is: &'static [&'static str],362 pub functions: F,363}364365impl<F: SolidityFunctions> SolidityInterface<F> {366 pub fn format(367 &self,368 is_impl: bool,369 out: &mut impl fmt::Write,370 tc: &TypeCollector,371 ) -> fmt::Result {372 const ZERO_BYTES: [u8; 4] = [0; 4];373 for doc in self.docs {374 writeln!(out, "///{}", doc)?;375 }376 if self.selector != ZERO_BYTES {377 writeln!(378 out,379 "/// @dev the ERC-165 identifier for this interface is 0x{:0>8x}",380 u32::from_be_bytes(self.selector)381 )?;382 }383 if is_impl {384 write!(out, "contract ")?;385 } else {386 write!(out, "interface ")?;387 }388 write!(out, "{}", self.name)?;389 if !self.is.is_empty() {390 write!(out, " is")?;391 for (i, n) in self.is.iter().enumerate() {392 if i != 0 {393 write!(out, ",")?;394 }395 write!(out, " {}", n)?;396 }397 }398 writeln!(out, " {{")?;399 self.functions.solidity_name(is_impl, out, tc)?;400 writeln!(out, "}}")?;401 Ok(())402 }403}404405pub struct SolidityEvent<A> {406 pub name: &'static str,407 pub args: A,408}409410impl<A: SolidityArguments> SolidityFunctions for SolidityEvent<A> {411 fn solidity_name(412 &self,413 _is_impl: bool,414 writer: &mut impl fmt::Write,415 tc: &TypeCollector,416 ) -> fmt::Result {417 write!(writer, "\tevent {}(", self.name)?;418 self.args.solidity_name(writer, tc)?;419 writeln!(writer, ");")420 }421}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//! Implementation detail of [`crate::solidity_interface`] macro code-generation.18//! You should not rely on any public item from this module, as it is only intended to be used19//! by procedural macro, API and output format may be changed at any time.20//!21//! Purpose of this module is to receive solidity contract definition in module-specified22//! format, and then output string, representing interface of this contract in solidity language2324mod traits;25pub use traits::*;26mod impls;2728#[cfg(not(feature = "std"))]29use alloc::{string::String, vec::Vec, collections::BTreeMap, format};30#[cfg(feature = "std")]31use std::collections::BTreeMap;32use core::{33 fmt::{self, Write},34 marker::PhantomData,35 cell::{Cell, RefCell},36 cmp::Reverse,37};38use impl_trait_for_tuples::impl_for_tuples;39use crate::{types::*, custom_signature::SignatureUnit};4041#[derive(Default)]42pub struct TypeCollector {43 /// Code => id44 /// id ordering is required to perform topo-sort on the resulting data45 structs: RefCell<BTreeMap<string, usize>>,46 anonymous: RefCell<BTreeMap<Vec<string>, usize>>,47 id: Cell<usize>,48}49impl TypeCollector {50 pub fn new() -> Self {51 Self::default()52 }53 pub fn collect(&self, item: string) {54 let id = self.next_id();55 self.structs.borrow_mut().insert(item, id);56 }57 pub fn next_id(&self) -> usize {58 let v = self.id.get();59 self.id.set(v + 1);60 v61 }62 pub fn collect_tuple<T: SolidityType>(&self) -> String {63 let names = T::names(self);64 if let Some(id) = self.anonymous.borrow().get(&names).cloned() {65 return format!("Tuple{}", id);66 }67 let id = self.next_id();68 let mut str = String::new();69 writeln!(str, "/// @dev anonymous struct").unwrap();70 writeln!(str, "struct Tuple{} {{", id).unwrap();71 for (i, name) in names.iter().enumerate() {72 writeln!(str, "\t{} field_{};", name, i).unwrap();73 }74 writeln!(str, "}}").unwrap();75 self.collect(str);76 self.anonymous.borrow_mut().insert(names, id);77 format!("Tuple{}", id)78 }79 pub fn collect_struct<T: StructCollect + SolidityType>(&self) -> String {80 let _names = T::names(self);81 self.collect(<T as StructCollect>::declaration());82 <T as StructCollect>::name()83 }84 pub fn finish(self) -> Vec<string> {85 let mut data = self.structs.into_inner().into_iter().collect::<Vec<_>>();86 data.sort_by_key(|(_, id)| Reverse(*id));87 data.into_iter().map(|(code, _)| code).collect()88 }89}90#[derive(Default)]91pub struct UnnamedArgument<T>(PhantomData<*const T>);9293impl<T: SolidityTypeName> SolidityArguments for UnnamedArgument<T> {94 fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {95 if !T::is_void() {96 T::solidity_name(writer, tc)?;97 if !T::is_simple() {98 write!(writer, " memory")?;99 }100 Ok(())101 } else {102 Ok(())103 }104 }105 fn solidity_get(&self, _prefix: &str, _writer: &mut impl fmt::Write) -> fmt::Result {106 Ok(())107 }108 fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {109 T::solidity_default(writer, tc)110 }111 fn len(&self) -> usize {112 if T::is_void() {113 0114 } else {115 1116 }117 }118}119120pub struct NamedArgument<T>(&'static str, PhantomData<*const T>);121122impl<T> NamedArgument<T> {123 pub fn new(name: &'static str) -> Self {124 Self(name, Default::default())125 }126}127128impl<T: SolidityTypeName> SolidityArguments for NamedArgument<T> {129 fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {130 if !T::is_void() {131 T::solidity_name(writer, tc)?;132 if !T::is_simple() {133 write!(writer, " memory")?;134 }135 write!(writer, " {}", self.0)136 } else {137 Ok(())138 }139 }140 fn solidity_get(&self, prefix: &str, writer: &mut impl fmt::Write) -> fmt::Result {141 writeln!(writer, "\t{prefix}\t{};", self.0)142 }143 fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {144 T::solidity_default(writer, tc)145 }146 fn len(&self) -> usize {147 if T::is_void() {148 0149 } else {150 1151 }152 }153}154155pub struct SolidityEventArgument<T>(pub bool, &'static str, PhantomData<*const T>);156157impl<T> SolidityEventArgument<T> {158 pub fn new(indexed: bool, name: &'static str) -> Self {159 Self(indexed, name, Default::default())160 }161}162163impl<T: SolidityTypeName> SolidityArguments for SolidityEventArgument<T> {164 fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {165 if !T::is_void() {166 T::solidity_name(writer, tc)?;167 if self.0 {168 write!(writer, " indexed")?;169 }170 write!(writer, " {}", self.1)171 } else {172 Ok(())173 }174 }175 fn solidity_get(&self, prefix: &str, writer: &mut impl fmt::Write) -> fmt::Result {176 writeln!(writer, "\t{prefix}\t{};", self.1)177 }178 fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {179 T::solidity_default(writer, tc)180 }181 fn len(&self) -> usize {182 if T::is_void() {183 0184 } else {185 1186 }187 }188}189190impl SolidityArguments for () {191 fn solidity_name(&self, _writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result {192 Ok(())193 }194 fn solidity_get(&self, _prefix: &str, _writer: &mut impl fmt::Write) -> fmt::Result {195 Ok(())196 }197 fn solidity_default(&self, _writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result {198 Ok(())199 }200 fn len(&self) -> usize {201 0202 }203}204205#[impl_for_tuples(1, 12)]206impl SolidityArguments for Tuple {207 for_tuples!( where #( Tuple: SolidityArguments ),* );208209 fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {210 let mut first = true;211 for_tuples!( #(212 if !Tuple.is_empty() {213 if !first {214 write!(writer, ", ")?;215 }216 first = false;217 Tuple.solidity_name(writer, tc)?;218 }219 )* );220 Ok(())221 }222 fn solidity_get(&self, prefix: &str, writer: &mut impl fmt::Write) -> fmt::Result {223 for_tuples!( #(224 Tuple.solidity_get(prefix, writer)?;225 )* );226 Ok(())227 }228 fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {229 if self.is_empty() {230 Ok(())231 } else if self.len() == 1 {232 for_tuples!( #(233 Tuple.solidity_default(writer, tc)?;234 )* );235 Ok(())236 } else {237 write!(writer, "(")?;238 let mut first = true;239 for_tuples!( #(240 if !Tuple.is_empty() {241 if !first {242 write!(writer, ", ")?;243 }244 first = false;245 Tuple.solidity_default(writer, tc)?;246 }247 )* );248 write!(writer, ")")?;249 Ok(())250 }251 }252 fn len(&self) -> usize {253 for_tuples!( #( Tuple.len() )+* )254 }255}256257pub enum SolidityMutability {258 Pure,259 View,260 Mutable,261}262pub struct SolidityFunction<A, R> {263 pub docs: &'static [&'static str],264 pub selector: u32,265 pub hide: bool,266 pub custom_signature: SignatureUnit,267 pub name: &'static str,268 pub args: A,269 pub result: R,270 pub mutability: SolidityMutability,271 pub is_payable: bool,272}273impl<A: SolidityArguments, R: SolidityArguments> SolidityFunctions for SolidityFunction<A, R> {274 fn solidity_name(275 &self,276 is_impl: bool,277 writer: &mut impl fmt::Write,278 tc: &TypeCollector,279 ) -> fmt::Result {280 let hide_comment = self.hide.then_some("// ").unwrap_or("");281 for doc in self.docs {282 writeln!(writer, "\t{hide_comment}///{}", doc)?;283 }284 writeln!(285 writer,286 "\t{hide_comment}/// @dev EVM selector for this function is: 0x{:0>8x},",287 self.selector288 )?;289 writeln!(290 writer,291 "\t{hide_comment}/// or in textual repr: {}",292 self.custom_signature.as_str().expect("bad utf-8")293 )?;294 write!(writer, "\t{hide_comment}function {}(", self.name)?;295 self.args.solidity_name(writer, tc)?;296 write!(writer, ")")?;297 if is_impl {298 write!(writer, " public")?;299 } else {300 write!(writer, " external")?;301 }302 match &self.mutability {303 SolidityMutability::Pure => write!(writer, " pure")?,304 SolidityMutability::View => write!(writer, " view")?,305 SolidityMutability::Mutable => {}306 }307 if self.is_payable {308 write!(writer, " payable")?;309 }310 if !self.result.is_empty() {311 write!(writer, " returns (")?;312 self.result.solidity_name(writer, tc)?;313 write!(writer, ")")?;314 }315 if is_impl {316 writeln!(writer, " {{")?;317 writeln!(writer, "\t{hide_comment}\trequire(false, stub_error);")?;318 self.args.solidity_get(hide_comment, writer)?;319 match &self.mutability {320 SolidityMutability::Pure => {}321 SolidityMutability::View => writeln!(writer, "\t{hide_comment}\tdummy;")?,322 SolidityMutability::Mutable => writeln!(writer, "\t{hide_comment}\tdummy = 0;")?,323 }324 if !self.result.is_empty() {325 write!(writer, "\t{hide_comment}\treturn ")?;326 self.result.solidity_default(writer, tc)?;327 writeln!(writer, ";")?;328 }329 writeln!(writer, "\t{hide_comment}}}")?;330 } else {331 writeln!(writer, ";")?;332 }333 if self.hide {334 writeln!(writer, "// FORMATTING: FORCE NEWLINE")?;335 }336 Ok(())337 }338}339340#[impl_for_tuples(0, 48)]341impl SolidityFunctions for Tuple {342 for_tuples!( where #( Tuple: SolidityFunctions ),* );343344 fn solidity_name(345 &self,346 is_impl: bool,347 writer: &mut impl fmt::Write,348 tc: &TypeCollector,349 ) -> fmt::Result {350 let mut first = false;351 for_tuples!( #(352 Tuple.solidity_name(is_impl, writer, tc)?;353 )* );354 Ok(())355 }356}357358pub struct SolidityInterface<F: SolidityFunctions> {359 pub docs: &'static [&'static str],360 pub selector: bytes4,361 pub name: &'static str,362 pub is: &'static [&'static str],363 pub functions: F,364}365366impl<F: SolidityFunctions> SolidityInterface<F> {367 pub fn format(368 &self,369 is_impl: bool,370 out: &mut impl fmt::Write,371 tc: &TypeCollector,372 ) -> fmt::Result {373 const ZERO_BYTES: [u8; 4] = [0; 4];374 for doc in self.docs {375 writeln!(out, "///{}", doc)?;376 }377 if self.selector != ZERO_BYTES {378 writeln!(379 out,380 "/// @dev the ERC-165 identifier for this interface is 0x{:0>8x}",381 u32::from_be_bytes(self.selector)382 )?;383 }384 if is_impl {385 write!(out, "contract ")?;386 } else {387 write!(out, "interface ")?;388 }389 write!(out, "{}", self.name)?;390 if !self.is.is_empty() {391 write!(out, " is")?;392 for (i, n) in self.is.iter().enumerate() {393 if i != 0 {394 write!(out, ",")?;395 }396 write!(out, " {}", n)?;397 }398 }399 writeln!(out, " {{")?;400 self.functions.solidity_name(is_impl, out, tc)?;401 writeln!(out, "}}")?;402 Ok(())403 }404}405406pub struct SolidityEvent<A> {407 pub name: &'static str,408 pub args: A,409}410411impl<A: SolidityArguments> SolidityFunctions for SolidityEvent<A> {412 fn solidity_name(413 &self,414 _is_impl: bool,415 writer: &mut impl fmt::Write,416 tc: &TypeCollector,417 ) -> fmt::Result {418 write!(writer, "\tevent {}(", self.name)?;419 self.args.solidity_name(writer, tc)?;420 writeln!(writer, ");")421 }422}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