difftreelog
Merge branch 'feature/refinement_on_named_structures' into develop
in: master
50 files changed
crates/evm-coder/procedural/src/abi_derive/derive_enum.rsdiffbeforeafterboth1use quote::quote;1use quote::quote;23use super::extract_docs;243pub fn impl_solidity_option<'a>(5pub fn impl_solidity_option<'a>(6 docs: Vec<String>,4 name: &proc_macro2::Ident,7 name: &proc_macro2::Ident,5 enum_options: impl Iterator<Item = &'a syn::Ident>,8 enum_options: impl Iterator<Item = &'a syn::Variant> + Clone,6) -> proc_macro2::TokenStream {9) -> proc_macro2::TokenStream {7 let enum_options = enum_options.map(|opt| {10 let variant_names = enum_options.clone().map(|opt| {11 let opt = &opt.ident;8 let s = name.to_string() + "." + opt.to_string().as_str();12 let s = name.to_string() + "." + opt.to_string().as_str();9 let as_string = proc_macro2::Literal::string(s.as_str());13 let as_string = proc_macro2::Literal::string(s.as_str());10 quote!(#name::#opt => #as_string,)14 quote!(#name::#opt => #as_string,)11 });15 });16 let solidity_name = name.to_string();1718 let solidity_fields = enum_options.map(|v| {19 let docs = extract_docs(&v.attrs).expect("TODO: handle bad docs");20 let name = v.ident.to_string();21 quote! {22 SolidityEnumVariant {23 docs: &[#(#docs),*],24 name: #name,25 }26 }27 });2812 quote!(29 quote!(13 #[cfg(feature = "stubgen")]30 #[cfg(feature = "stubgen")]14 impl ::evm_coder::solidity::SolidityEnum for #name {31 impl ::evm_coder::solidity::SolidityEnumTy for #name {32 fn generate_solidity_interface(tc: &evm_coder::solidity::TypeCollector) -> String {33 use evm_coder::solidity::*;34 use core::fmt::Write;35 let interface = SolidityEnum {36 docs: &[#(#docs),*],37 name: #solidity_name,38 fields: &[#(39 #solidity_fields,40 )*],41 };42 let mut out = String::new();43 let _ = interface.format(&mut out, tc);44 tc.collect(out);45 #solidity_name.to_string()46 }15 fn solidity_option(&self) -> &str {47 fn solidity_option(&self) -> &str {16 match self {48 match self {17 #(#enum_options)*49 #(#variant_names)*18 }50 }19 }51 }20 }52 }235524pub fn impl_enum_from_u8<'a>(56pub fn impl_enum_from_u8<'a>(25 name: &proc_macro2::Ident,57 name: &proc_macro2::Ident,26 enum_options: impl Iterator<Item = &'a syn::Ident>,58 enum_options: impl Iterator<Item = &'a syn::Variant>,27) -> proc_macro2::TokenStream {59) -> proc_macro2::TokenStream {28 let error_str = format!("Value not convertible into enum \"{name}\"");60 let error_str = format!("Value not convertible into enum \"{name}\"");29 let error_str = proc_macro2::Literal::string(&error_str);61 let error_str = proc_macro2::Literal::string(&error_str);30 let enum_options = enum_options.enumerate().map(|(i, opt)| {62 let enum_options = enum_options.enumerate().map(|(i, opt)| {63 let opt = &opt.ident;31 let n = proc_macro2::Literal::u8_suffixed(i as u8);64 let n = proc_macro2::Literal::u8_suffixed(i as u8);32 quote! {#n => Ok(#name::#opt),}65 quote! {#n => Ok(#name::#opt),}33 });66 });93 writer: &mut impl ::core::fmt::Write,126 writer: &mut impl ::core::fmt::Write,94 tc: &::evm_coder::solidity::TypeCollector,127 tc: &::evm_coder::solidity::TypeCollector,95 ) -> ::core::fmt::Result {128 ) -> ::core::fmt::Result {96 write!(writer, "{}", tc.collect_struct::<Self>())129 write!(writer, "{}", tc.collect_enum::<Self>())97 }130 }9813199 fn is_simple() -> bool {132 fn is_simple() -> bool {104 writer: &mut impl ::core::fmt::Write,137 writer: &mut impl ::core::fmt::Write,105 tc: &::evm_coder::solidity::TypeCollector,138 tc: &::evm_coder::solidity::TypeCollector,106 ) -> ::core::fmt::Result {139 ) -> ::core::fmt::Result {107 write!(writer, "{}", <#name as ::evm_coder::solidity::SolidityEnum>::solidity_option(&<#name>::default()))140 write!(writer, "{}", <#name as ::evm_coder::solidity::SolidityEnumTy>::solidity_option(&<#name>::default()))108 }141 }109 }142 }110 )143 )111}144}112113pub fn impl_enum_solidity_struct_collect<'a>(114 name: &syn::Ident,115 enum_options: impl Iterator<Item = &'a syn::Ident>,116 option_count: usize,117 enum_options_docs: impl Iterator<Item = syn::Result<Vec<proc_macro2::TokenStream>>>,118 docs: &[proc_macro2::TokenStream],119) -> proc_macro2::TokenStream {120 let string_name = name.to_string();121 let enum_options = enum_options122 .zip(enum_options_docs)123 .enumerate()124 .map(|(i, (opt, doc))| {125 let opt = proc_macro2::Literal::string(opt.to_string().as_str());126 let doc = doc.expect("Doc parsing error");127 let comma = if i != option_count - 1 { "," } else { "" };128 quote! {129 #(#doc)*130 writeln!(str, "\t{}{}", #opt, #comma).expect("Enum format option");131 }132 });133134 quote!(135 #[cfg(feature = "stubgen")]136 impl ::evm_coder::solidity::StructCollect for #name {137 fn name() -> String {138 #string_name.into()139 }140141 fn declaration() -> String {142 use std::fmt::Write;143144 let mut str = String::new();145 #(#docs)*146 writeln!(str, "enum {} {{", <Self as ::evm_coder::solidity::StructCollect>::name()).unwrap();147 #(#enum_options)*148 writeln!(str, "}}").unwrap();149 str150 }151 }152 )153}154145155pub fn check_and_count_options(de: &syn::DataEnum) -> syn::Result<usize> {146pub fn check_and_count_options(de: &syn::DataEnum) -> syn::Result<usize> {156 let mut count = 0;147 let mut count = 0;crates/evm-coder/procedural/src/abi_derive/derive_struct.rsdiffbeforeafterboth1use super::extract_docs;1use super::extract_docs;2use quote::quote;2use quote::quote;3use syn::Field;344pub fn tuple_type<'a>(5pub fn tuple_type<'a>(5 field_types: impl Iterator<Item = &'a syn::Type> + Clone,6 field_types: impl Iterator<Item = &'a syn::Type> + Clone,87 &field.ty88 &field.ty88}89}8990pub fn map_field_to_doc(field: &syn::Field) -> syn::Result<Vec<proc_macro2::TokenStream>> {91 extract_docs(&field.attrs, true)92}939094pub fn impl_can_be_placed_in_vec(ident: &syn::Ident) -> proc_macro2::TokenStream {91pub fn impl_can_be_placed_in_vec(ident: &syn::Ident) -> proc_macro2::TokenStream {95 quote! {92 quote! {147144148pub fn impl_struct_solidity_type<'a>(145pub fn impl_struct_solidity_type<'a>(149 name: &syn::Ident,146 name: &syn::Ident,147 docs: Vec<String>,150 field_types: impl Iterator<Item = &'a syn::Type> + Clone,148 fields: impl Iterator<Item = &'a Field> + Clone,151 params_count: usize,152) -> proc_macro2::TokenStream {149) -> proc_macro2::TokenStream {150 let solidity_name = name.to_string();153 let len = proc_macro2::Literal::usize_suffixed(params_count);151 let solidity_fields = fields.enumerate().map(|(i, f)| {152 let name = f153 .ident154 .as_ref()155 .map(|i| i.to_string())156 .unwrap_or_else(|| format!("field_{i}"));157 let ty = &f.ty;158 let docs = extract_docs(&f.attrs).expect("TODO: handle bad docs");159 quote! {160 SolidityStructField::<#ty> {161 docs: &[#(#docs),*],162 name: #name,163 ty: ::core::marker::PhantomData,164 }165 }166 });154 quote! {167 quote! {155 #[cfg(feature = "stubgen")]168 #[cfg(feature = "stubgen")]156 impl ::evm_coder::solidity::SolidityType for #name {169 impl ::evm_coder::solidity::SolidityStructTy for #name {170 /// Generate solidity definitions for methods described in this struct157 fn names(tc: &::evm_coder::solidity::TypeCollector) -> Vec<String> {171 fn generate_solidity_interface(tc: &evm_coder::solidity::TypeCollector) -> String {158 let mut collected =159 Vec::with_capacity(<Self as ::evm_coder::solidity::SolidityType>::len());172 use evm_coder::solidity::*;173 use core::fmt::Write;174 let interface = SolidityStruct {175 docs: &[#(#docs),*],160 #({176 name: #solidity_name,177 fields: (#(178 #solidity_fields,179 )*),180 };161 let mut out = String::new();181 let mut out = String::new();162 <#field_types as ::evm_coder::solidity::SolidityTypeName>::solidity_name(&mut out, tc)182 let _ = interface.format(&mut out, tc);163 .expect("no fmt error");164 collected.push(out);183 tc.collect(out);165 })*166 collected167 }168169 fn len() -> usize {170 #len184 #solidity_name.to_string()171 }185 }172 }186 }173 }187 }174}188}216 }230 }217}231}218219pub fn impl_struct_solidity_struct_collect<'a>(220 name: &syn::Ident,221 field_names: impl Iterator<Item = proc_macro2::Ident> + Clone,222 field_types: impl Iterator<Item = &'a syn::Type> + Clone,223 field_docs: impl Iterator<Item = syn::Result<Vec<proc_macro2::TokenStream>>> + Clone,224 docs: &[proc_macro2::TokenStream],225) -> syn::Result<proc_macro2::TokenStream> {226 let string_name = name.to_string();227 let name_type = field_names228 .into_iter()229 .zip(field_types)230 .zip(field_docs)231 .map(|((name, ty), doc)| {232 let field_docs = doc.expect("Doc parse error");233 let name = format!("{}", name);234 quote!(235 #(#field_docs)*236 write!(str, "\t{} ", <#ty as ::evm_coder::solidity::StructCollect>::name()).unwrap();237 writeln!(str, "{};", #name).unwrap();238 )239 });240241 Ok(quote! {242 #[cfg(feature = "stubgen")]243 impl ::evm_coder::solidity::StructCollect for #name {244 fn name() -> String {245 #string_name.into()246 }247248 fn declaration() -> String {249 use std::fmt::Write;250251 let mut str = String::new();252 #(#docs)*253 writeln!(str, "struct {} {{", Self::name()).unwrap();254 #(#name_type)*255 writeln!(str, "}}").unwrap();256 str257 }258 }259 })260}261232crates/evm-coder/procedural/src/abi_derive/mod.rsdiffbeforeafterboth19 ast: &syn::DeriveInput,19 ast: &syn::DeriveInput,20) -> syn::Result<proc_macro2::TokenStream> {20) -> syn::Result<proc_macro2::TokenStream> {21 let name = &ast.ident;21 let name = &ast.ident;22 let docs = extract_docs(&ast.attrs, false)?;22 let docs = extract_docs(&ast.attrs)?;23 let (is_named_fields, field_names, field_types, field_docs, params_count) = match ds.fields {23 let (is_named_fields, field_names, field_types, params_count) = match ds.fields {24 syn::Fields::Named(ref fields) => Ok((24 syn::Fields::Named(ref fields) => Ok((25 true,25 true,26 fields.named.iter().enumerate().map(map_field_to_name),26 fields.named.iter().enumerate().map(map_field_to_name),27 fields.named.iter().map(map_field_to_type),27 fields.named.iter().map(map_field_to_type),28 fields.named.iter().map(map_field_to_doc),29 fields.named.len(),28 fields.named.len(),30 )),29 )),31 syn::Fields::Unnamed(ref fields) => Ok((30 syn::Fields::Unnamed(ref fields) => Ok((32 false,31 false,33 fields.unnamed.iter().enumerate().map(map_field_to_name),32 fields.unnamed.iter().enumerate().map(map_field_to_name),34 fields.unnamed.iter().map(map_field_to_type),33 fields.unnamed.iter().map(map_field_to_type),35 fields.unnamed.iter().map(map_field_to_doc),36 fields.unnamed.len(),34 fields.unnamed.len(),37 )),35 )),38 syn::Fields::Unit => Err(syn::Error::new(name.span(), "Unit structs not supported")),36 syn::Fields::Unit => Err(syn::Error::new(name.span(), "Unit structs not supported")),52 let abi_type = impl_struct_abi_type(name, tuple_type.clone());50 let abi_type = impl_struct_abi_type(name, tuple_type.clone());53 let abi_read = impl_struct_abi_read(name, tuple_type, tuple_names, struct_from_tuple);51 let abi_read = impl_struct_abi_read(name, tuple_type, tuple_names, struct_from_tuple);54 let abi_write = impl_struct_abi_write(name, is_named_fields, tuple_ref_type, tuple_data);52 let abi_write = impl_struct_abi_write(name, is_named_fields, tuple_ref_type, tuple_data);55 let solidity_type = impl_struct_solidity_type(name, field_types.clone(), params_count);53 let solidity_type = impl_struct_solidity_type(name, docs, ds.fields.iter());56 let solidity_type_name =54 let solidity_type_name =57 impl_struct_solidity_type_name(name, field_types.clone(), params_count);55 impl_struct_solidity_type_name(name, field_types.clone(), params_count);58 let solidity_struct_collect =59 impl_struct_solidity_struct_collect(name, field_names, field_types, field_docs, &docs)?;605661 Ok(quote! {57 Ok(quote! {62 #can_be_plcaed_in_vec58 #can_be_plcaed_in_vec65 #abi_write61 #abi_write66 #solidity_type62 #solidity_type67 #solidity_type_name63 #solidity_type_name68 #solidity_struct_collect69 })64 })70}65}716675) -> syn::Result<proc_macro2::TokenStream> {70) -> syn::Result<proc_macro2::TokenStream> {76 let name = &ast.ident;71 let name = &ast.ident;77 check_repr_u8(name, &ast.attrs)?;72 check_repr_u8(name, &ast.attrs)?;78 let docs = extract_docs(&ast.attrs, false)?;73 let docs = extract_docs(&ast.attrs)?;79 let option_count = check_and_count_options(de)?;80 let enum_options = de.variants.iter().map(|v| &v.ident);74 let enum_options = de.variants.iter();81 let enum_options_docs = de.variants.iter().map(|v| extract_docs(&v.attrs, true));827583 let from = impl_enum_from_u8(name, enum_options.clone());76 let from = impl_enum_from_u8(name, enum_options.clone());84 let solidity_option = impl_solidity_option(name, enum_options.clone());77 let solidity_option = impl_solidity_option(docs, name, enum_options.clone());85 let can_be_plcaed_in_vec = impl_can_be_placed_in_vec(name);78 let can_be_plcaed_in_vec = impl_can_be_placed_in_vec(name);86 let abi_type = impl_enum_abi_type(name);79 let abi_type = impl_enum_abi_type(name);87 let abi_read = impl_enum_abi_read(name);80 let abi_read = impl_enum_abi_read(name);88 let abi_write = impl_enum_abi_write(name);81 let abi_write = impl_enum_abi_write(name);89 let solidity_type_name = impl_enum_solidity_type_name(name);82 let solidity_type_name = impl_enum_solidity_type_name(name);90 let solidity_struct_collect = impl_enum_solidity_struct_collect(91 name,92 enum_options,93 option_count,94 enum_options_docs,95 &docs,96 );978398 Ok(quote! {84 Ok(quote! {99 #from85 #from103 #abi_read89 #abi_read104 #abi_write90 #abi_write105 #solidity_type_name91 #solidity_type_name106 #solidity_struct_collect107 })92 })108}93}10994110fn extract_docs(95fn extract_docs(attrs: &[syn::Attribute]) -> syn::Result<Vec<String>> {111 attrs: &[syn::Attribute],112 is_field_doc: bool,113) -> syn::Result<Vec<proc_macro2::TokenStream>> {114 attrs96 attrs115 .iter()97 .iter()116 .filter_map(|attr| {98 .filter_map(|attr| {131 }113 }132 None114 None133 })115 })134 .enumerate()135 .map(|(i, doc)| {136 let doc = doc?;137 let doc = doc.trim();138 let dev = if i == 0 { " @dev" } else { "" };139 let tab = if is_field_doc { "\t" } else { "" };140 Ok(quote! {141 writeln!(str, "{}///{} {}", #tab, #dev, #doc).unwrap();142 })143 })144 .collect()116 .collect()145}117}146118crates/evm-coder/src/abi/impls.rsdiffbeforeafterboth135 }135 }136}136}137138impl sealed::CanBePlacedInVec for Property {}139140impl AbiType for Property {141 const SIGNATURE: SignatureUnit = make_signature!(new fixed("(string,bytes)"));142143 fn is_dynamic() -> bool {144 string::is_dynamic() || bytes::is_dynamic()145 }146147 fn size() -> usize {148 <string as AbiType>::size() + <bytes as AbiType>::size()149 }150}151152impl AbiRead for Property {153 fn abi_read(reader: &mut AbiReader) -> Result<Property> {154 let size = if !Property::is_dynamic() {155 Some(<Property as AbiType>::size())156 } else {157 None158 };159 let mut subresult = reader.subresult(size)?;160 let key = <string>::abi_read(&mut subresult)?;161 let value = <bytes>::abi_read(&mut subresult)?;162163 Ok(Property { key, value })164 }165}166167impl AbiWrite for Property {168 fn abi_write(&self, writer: &mut AbiWriter) {169 (&self.key, &self.value).abi_write(writer);170 }171}172137173impl<T: AbiWrite + AbiType> AbiWrite for Vec<T> {138impl<T: AbiWrite + AbiType> AbiWrite for Vec<T> {174 fn abi_write(&self, writer: &mut AbiWriter) {139 fn abi_write(&self, writer: &mut AbiWriter) {crates/evm-coder/src/lib.rsdiffbeforeafterboth197 }197 }198 }198 }199200 #[derive(Debug, Default)]201 pub struct Property {202 pub key: string,203 pub value: bytes,204 }205}199}206200207/// Parseable EVM call, this trait should be implemented with [`solidity_interface`] macro201/// Parseable EVM call, this trait should be implemented with [`solidity_interface`] macrocrates/evm-coder/src/solidity/impls.rsdiffbeforeafterboth1use super::{TypeCollector, SolidityTypeName, SolidityType, StructCollect};1use super::{TypeCollector, SolidityTypeName, SolidityTupleTy};2use crate::{sealed, types::*};2use crate::{sealed, types::*};3use core::fmt;3use core::fmt;4use primitive_types::{U256, H160};4use primitive_types::{U256, H160};18 }18 }19 }19 }2021 impl StructCollect for $ty {22 fn name() -> String {23 $name.to_string()24 }2526 fn declaration() -> String {27 String::default()28 }29 }30 )*20 )*31 };21 };32}22}817182macro_rules! impl_tuples {72macro_rules! impl_tuples {83 ($($ident:ident)+) => {73 ($($ident:ident)+) => {84 impl<$($ident: SolidityTypeName + 'static),+> SolidityType for ($($ident,)+) {74 impl<$($ident: SolidityTypeName + 'static),+> SolidityTupleTy for ($($ident,)+) {85 fn names(tc: &TypeCollector) -> Vec<string> {75 fn fields(tc: &TypeCollector) -> Vec<string> {86 let mut collected = Vec::with_capacity(Self::len());76 let mut collected = Vec::with_capacity(Self::len());87 $({77 $({88 let mut out = string::new();78 let mut out = string::new();132impl_tuples! {A B C D E F G H I}122impl_tuples! {A B C D E F G H I}133impl_tuples! {A B C D E F G H I J}123impl_tuples! {A B C D E F G H I J}134135impl StructCollect for Property {136 fn name() -> String {137 "Property".into()138 }139140 fn declaration() -> String {141 use std::fmt::Write;142143 let mut str = String::new();144 writeln!(str, "/// @dev Property struct").unwrap();145 writeln!(str, "struct {} {{", Self::name()).unwrap();146 writeln!(str, "\tstring key;").unwrap();147 writeln!(str, "\tbytes value;").unwrap();148 writeln!(str, "}}").unwrap();149 str150 }151}152153impl SolidityTypeName for Property {154 fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {155 write!(writer, "{}", tc.collect_struct::<Self>())156 }157158 fn is_simple() -> bool {159 false160 }161162 fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {163 write!(writer, "{}(", tc.collect_struct::<Self>())?;164 address::solidity_default(writer, tc)?;165 write!(writer, ",")?;166 uint256::solidity_default(writer, tc)?;167 write!(writer, ")")168 }169}170171impl SolidityType for Property {172 fn names(tc: &TypeCollector) -> Vec<string> {173 let mut collected = Vec::with_capacity(Self::len());174 {175 let mut out = string::new();176 string::solidity_name(&mut out, tc).expect("no fmt error");177 collected.push(out);178 }179 {180 let mut out = string::new();181 bytes::solidity_name(&mut out, tc).expect("no fmt error");182 collected.push(out);183 }184 collected185 }186187 fn len() -> usize {188 2189 }190}191124crates/evm-coder/src/solidity/mod.rsdiffbeforeafterboth44 /// id ordering is required to perform topo-sort on the resulting data44 /// id ordering is required to perform topo-sort on the resulting data45 structs: RefCell<BTreeMap<string, usize>>,45 structs: RefCell<BTreeMap<string, usize>>,46 anonymous: RefCell<BTreeMap<Vec<string>, usize>>,46 anonymous: RefCell<BTreeMap<Vec<string>, usize>>,47 // generic: RefCell<BTreeMap<string, usize>>,47 id: Cell<usize>,48 id: Cell<usize>,48}49}49impl TypeCollector {50impl TypeCollector {59 self.id.set(v + 1);60 self.id.set(v + 1);60 v61 v61 }62 }63 /// Collect typle, deduplicating it by type, and returning generated name62 pub fn collect_tuple<T: SolidityType>(&self) -> String {64 pub fn collect_tuple<T: SolidityTupleTy>(&self) -> String {63 let names = T::names(self);65 let names = T::fields(self);64 if let Some(id) = self.anonymous.borrow().get(&names).cloned() {66 if let Some(id) = self.anonymous.borrow().get(&names).cloned() {65 return format!("Tuple{}", id);67 return format!("Tuple{}", id);66 }68 }76 self.anonymous.borrow_mut().insert(names, id);78 self.anonymous.borrow_mut().insert(names, id);77 format!("Tuple{}", id)79 format!("Tuple{}", id)78 }80 }79 pub fn collect_struct<T: StructCollect>(&self) -> String {81 pub fn collect_struct<T: SolidityStructTy>(&self) -> String {80 self.collect(<T as StructCollect>::declaration());81 <T as StructCollect>::name()82 T::generate_solidity_interface(self)82 }83 }84 pub fn collect_enum<T: SolidityEnumTy>(&self) -> String {85 T::generate_solidity_interface(self)86 }83 pub fn finish(self) -> Vec<string> {87 pub fn finish(self) -> Vec<string> {84 let mut data = self.structs.into_inner().into_iter().collect::<Vec<_>>();88 let mut data = self.structs.into_inner().into_iter().collect::<Vec<_>>();85 data.sort_by_key(|(_, id)| Reverse(*id));89 data.sort_by_key(|(_, id)| Reverse(*id));420 }424 }421}425}426427#[impl_for_tuples(0, 48)]428impl SolidityItems for Tuple {429 for_tuples!( where #( Tuple: SolidityItems ),* );430431 fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {432 for_tuples!( #(433 Tuple.solidity_name(writer, tc)?;434 )* );435 Ok(())436 }437}438439pub struct SolidityStructField<T> {440 pub docs: &'static [&'static str],441 pub name: &'static str,442 pub ty: PhantomData<*const T>,443}444445impl<T> SolidityItems for SolidityStructField<T>446where447 T: SolidityTypeName,448{449 fn solidity_name(&self, out: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {450 for doc in self.docs {451 writeln!(out, "///{}", doc)?;452 }453 write!(out, "\t")?;454 T::solidity_name(out, tc)?;455 writeln!(out, " {};", self.name)?;456 Ok(())457 }458}459pub struct SolidityStruct<F> {460 pub docs: &'static [&'static str],461 // pub generics:462 pub name: &'static str,463 pub fields: F,464}465impl<F> SolidityStruct<F>466where467 F: SolidityItems,468{469 pub fn format(&self, out: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {470 for doc in self.docs {471 writeln!(out, "///{}", doc)?;472 }473 writeln!(out, "struct {} {{", self.name)?;474 self.fields.solidity_name(out, tc)?;475 writeln!(out, "}}")?;476 Ok(())477 }478}479480pub struct SolidityEnumVariant {481 pub docs: &'static [&'static str],482 pub name: &'static str,483}484impl SolidityItems for SolidityEnumVariant {485 fn solidity_name(&self, out: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result {486 for doc in self.docs {487 writeln!(out, "///{}", doc)?;488 }489 write!(out, "\t{}", self.name)?;490 Ok(())491 }492}493pub struct SolidityEnum {494 pub docs: &'static [&'static str],495 pub name: &'static str,496 pub fields: &'static [SolidityEnumVariant],497}498impl SolidityEnum {499 pub fn format(&self, out: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {500 for doc in self.docs {501 writeln!(out, "///{}", doc)?;502 }503 write!(out, "enum {} {{", self.name)?;504 for (i, field) in self.fields.iter().enumerate() {505 if i != 0 {506 write!(out, ",")?;507 }508 writeln!(out)?;509 field.solidity_name(out, tc)?;510 }511 writeln!(out)?;512 writeln!(out, "}}")?;513 Ok(())514 }515}422516crates/evm-coder/src/solidity/traits.rsdiffbeforeafterboth1use super::TypeCollector;1use super::TypeCollector;2use core::fmt;2use core::fmt;34pub trait StructCollect: 'static {5 /// Structure name.6 fn name() -> String;7 /// Structure declaration.8 fn declaration() -> String;9}1011pub trait SolidityEnum: 'static {12 fn solidity_option(&self) -> &str;13}14315pub trait SolidityTypeName: 'static {4pub trait SolidityTypeName: 'static {16 fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result;5 fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result;23 }12 }24}13}251426pub trait SolidityType {15pub trait SolidityTupleTy: 'static {27 fn names(tc: &TypeCollector) -> Vec<String>;16 fn fields(tc: &TypeCollector) -> Vec<String>;28 fn len() -> usize;17 fn len() -> usize;29}18}19pub trait SolidityStructTy: 'static {20 fn generate_solidity_interface(tc: &TypeCollector) -> String;21}22pub trait SolidityEnumTy: 'static {23 fn generate_solidity_interface(tc: &TypeCollector) -> String;24 fn solidity_option(&self) -> &str;25}302631pub trait SolidityArguments {27pub trait SolidityArguments {32 fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result;28 fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result;47 ) -> fmt::Result;43 ) -> fmt::Result;48}44}4546pub trait SolidityItems {47 fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result;48 // For PhantomData fields49 // fn is_void()50}4951crates/evm-coder/tests/abi_derive_generation.rsdiffbeforeafterboth73 _c: TypeStruct2MixedParam,73 _c: TypeStruct2MixedParam,74 }74 }7576 #[test]77 #[cfg(feature = "stubgen")]78 fn struct_collect_type_struct3_derived_mixed_param() {79 assert_eq!(80 <TypeStruct3DerivedMixedParam as ::evm_coder::solidity::StructCollect>::name(),81 "TypeStruct3DerivedMixedParam"82 );83 similar_asserts::assert_eq!(84 <TypeStruct3DerivedMixedParam as ::evm_coder::solidity::StructCollect>::declaration(),85 r#"/// @dev Some docs86/// At multi87/// line88struct TypeStruct3DerivedMixedParam {89 /// @dev Docs for A90 /// multi91 /// line92 TypeStruct1SimpleParam _a;93 /// @dev Docs for B94 TypeStruct2DynamicParam _b;95 /// @dev Docs for C96 TypeStruct2MixedParam _c;97}98"#99 );100 }10175102 #[test]76 #[test]103 fn impl_abi_type_signature() {77 fn impl_abi_type_signature() {293 TupleStruct2MixedParam,267 TupleStruct2MixedParam,294 );268 );295296 #[test]297 #[cfg(feature = "stubgen")]298 fn struct_collect_tuple_struct3_derived_mixed_param() {299 assert_eq!(300 <TupleStruct3DerivedMixedParam as ::evm_coder::solidity::StructCollect>::name(),301 "TupleStruct3DerivedMixedParam"302 );303 similar_asserts::assert_eq!(304 <TupleStruct3DerivedMixedParam as ::evm_coder::solidity::StructCollect>::declaration(),305 r#"/// @dev Some docs306/// At multi307/// line308struct TupleStruct3DerivedMixedParam {309 /// @dev Docs for A310 /// multi311 /// line312 TupleStruct1SimpleParam field0;313 TupleStruct2DynamicParam field1;314 /// @dev Docs for C315 TupleStruct2MixedParam field2;316}317"#318 );319 }320269321 #[test]270 #[test]322 fn impl_abi_type_signature_same_for_structs() {271 fn impl_abi_type_signature_same_for_structs() {814 }763 }815 }764 }816817 #[test]818 #[cfg(feature = "stubgen")]819 fn struct_collect_enum() {820 assert_eq!(821 <Color as ::evm_coder::solidity::StructCollect>::name(),822 "Color"823 );824 similar_asserts::assert_eq!(825 <Color as ::evm_coder::solidity::StructCollect>::declaration(),826 r#"/// @dev Some docs827/// At multi828/// line829enum Color {830 /// @dev Docs for Red831 /// multi832 /// line833 Red,834 Green,835 /// @dev Docs for Blue836 Blue837}838"#839 );840 }841}765}842766pallets/common/src/erc.rsdiffbeforeafterboth21 abi::AbiType,21 abi::AbiType,22 solidity_interface, solidity, ToLog,22 solidity_interface, solidity, ToLog,23 types::*,23 types::*,24 types::Property as PropertyStruct,25 execution::{Result, Error},24 execution::{Result, Error},26 weight,25 weight,27};26};31 AccessMode, CollectionMode, CollectionPermissions, OwnerRestrictedSet, Property,30 AccessMode, CollectionMode, CollectionPermissions, OwnerRestrictedSet, Property,32 SponsoringRateLimit, SponsorshipState,31 SponsoringRateLimit, SponsorshipState,33};32};34use alloc::format;353336use crate::{34use crate::{37 Pallet, CollectionHandle, Config, CollectionProperties, SelfWeightOf,35 Pallet, CollectionHandle, Config, CollectionProperties, SelfWeightOf, eth, weights::WeightInfo,38 eth::{39 EthCrossAccount, CollectionPermissions as EvmPermissions,40 CollectionLimits as EvmCollectionLimits,41 },42 weights::WeightInfo,43};36};443745/// Events for ethereum collection helper.38/// Events for ethereum collection helper.123 fn set_collection_properties(116 fn set_collection_properties(124 &mut self,117 &mut self,125 caller: caller,118 caller: caller,126 properties: Vec<PropertyStruct>,119 properties: Vec<eth::Property>,127 ) -> Result<void> {120 ) -> Result<void> {128 let caller = T::CrossAccountId::from_eth(caller);121 let caller = T::CrossAccountId::from_eth(caller);129122130 let properties = properties123 let properties = properties131 .into_iter()124 .into_iter()132 .map(|PropertyStruct { key, value }| {125 .map(eth::Property::try_into)133 let key = <Vec<u8>>::from(key)134 .try_into()135 .map_err(|_| "key too large")?;136137 let value = value.0.try_into().map_err(|_| "value too large")?;138139 Ok(Property { key, value })140 })141 .collect::<Result<Vec<_>>>()?;126 .collect::<Result<Vec<_>>>()?;142127143 <Pallet<T>>::set_collection_properties(self, &caller, properties)128 <Pallet<T>>::set_collection_properties(self, &caller, properties)197 ///182 ///198 /// @param keys Properties keys. Empty keys for all propertyes.183 /// @param keys Properties keys. Empty keys for all propertyes.199 /// @return Vector of properties key/value pairs.184 /// @return Vector of properties key/value pairs.200 fn collection_properties(&self, keys: Vec<string>) -> Result<Vec<PropertyStruct>> {185 fn collection_properties(&self, keys: Vec<string>) -> Result<Vec<eth::Property>> {201 let keys = keys186 let keys = keys202 .into_iter()187 .into_iter()203 .map(|key| {188 .map(|key| {215200216 let properties = properties201 let properties = properties217 .into_iter()202 .into_iter()218 .map(|p| {203 .map(Property::try_into)219 let key =220 string::from_utf8(p.key.into()).map_err(|e| Error::Revert(format!("{}", e)))?;221 let value = bytes(p.value.to_vec());222 Ok(PropertyStruct { key, value })223 })224 .collect::<Result<Vec<_>>>()?;204 .collect::<Result<Vec<_>>>()?;225 Ok(properties)205 Ok(properties)226 }206 }249 fn set_collection_sponsor_cross(229 fn set_collection_sponsor_cross(250 &mut self,230 &mut self,251 caller: caller,231 caller: caller,252 sponsor: EthCrossAccount,232 sponsor: eth::CrossAddress,253 ) -> Result<void> {233 ) -> Result<void> {254 self.consume_store_reads_and_writes(1, 1)?;234 self.consume_store_reads_and_writes(1, 1)?;255235289 /// Get current sponsor.269 /// Get current sponsor.290 ///270 ///291 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.271 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.292 fn collection_sponsor(&self) -> Result<EthCrossAccount> {272 fn collection_sponsor(&self) -> Result<eth::CrossAddress> {293 let sponsor = match self.collection.sponsorship.sponsor() {273 let sponsor = match self.collection.sponsorship.sponsor() {294 Some(sponsor) => sponsor,274 Some(sponsor) => sponsor,295 None => return Ok(Default::default()),275 None => return Ok(Default::default()),296 };276 };297277298 Ok(EthCrossAccount::from_sub::<T>(&sponsor))278 Ok(eth::CrossAddress::from_sub::<T>(&sponsor))299 }279 }300280301 /// Get current collection limits.281 /// Get current collection limits.302 ///282 ///303 /// @return Array of tuples (byte, bool, uint256) with limits and their values. Order of limits:283 /// @return Array of collection limits304 /// "accountTokenOwnershipLimit",284 fn collection_limits(&self) -> Result<Vec<eth::CollectionLimit>> {305 /// "sponsoredDataSize",306 /// "sponsoredDataRateLimit",307 /// "tokenLimit",308 /// "sponsorTransferTimeout",309 /// "sponsorApproveTimeout"310 /// "ownerCanTransfer",311 /// "ownerCanDestroy",312 /// "transfersEnabled"313 /// Return `false` if a limit not set.314 fn collection_limits(&self) -> Result<Vec<(EvmCollectionLimits, bool, uint256)>> {315 let convert_value_limit = |limit: EvmCollectionLimits,316 value: Option<u32>|317 -> (EvmCollectionLimits, bool, uint256) {318 value319 .map(|v| (limit, true, v.into()))320 .unwrap_or((limit, false, Default::default()))321 };322323 let convert_bool_limit = |limit: EvmCollectionLimits,324 value: Option<bool>|325 -> (EvmCollectionLimits, bool, uint256) {326 value327 .map(|v| {328 (329 limit,330 true,331 if v {332 uint256::from(1)333 } else {334 Default::default()335 },336 )337 })338 .unwrap_or((limit, false, Default::default()))339 };340341 let limits = &self.collection.limits;285 let limits = &self.collection.limits;342286343 Ok(vec![287 Ok(vec![344 convert_value_limit(288 eth::CollectionLimit::new(345 EvmCollectionLimits::AccountTokenOwnership,289 eth::CollectionLimitField::AccountTokenOwnership,346 limits.account_token_ownership_limit,290 limits.account_token_ownership_limit,347 ),291 ),348 convert_value_limit(292 eth::CollectionLimit::new(349 EvmCollectionLimits::SponsoredDataSize,293 eth::CollectionLimitField::SponsoredDataSize,350 limits.sponsored_data_size,294 limits.sponsored_data_size,351 ),295 ),352 limits296 limits353 .sponsored_data_rate_limit297 .sponsored_data_rate_limit354 .and_then(|limit| {298 .and_then(|limit| {355 if let SponsoringRateLimit::Blocks(blocks) = limit {299 if let SponsoringRateLimit::Blocks(blocks) = limit {356 Some((300 Some(eth::CollectionLimit::new::<u32>(357 EvmCollectionLimits::SponsoredDataRateLimit,301 eth::CollectionLimitField::SponsoredDataRateLimit,358 true,302 blocks,359 blocks.into(),360 ))303 ))361 } else {304 } else {362 None305 None363 }306 }364 })307 })365 .unwrap_or((308 .unwrap_or(eth::CollectionLimit::new::<u32>(366 EvmCollectionLimits::SponsoredDataRateLimit,309 eth::CollectionLimitField::SponsoredDataRateLimit,367 false,368 Default::default(),310 Default::default(),369 )),311 )),370 convert_value_limit(EvmCollectionLimits::TokenLimit, limits.token_limit),312 eth::CollectionLimit::new(eth::CollectionLimitField::TokenLimit, limits.token_limit),371 convert_value_limit(313 eth::CollectionLimit::new(372 EvmCollectionLimits::SponsorTransferTimeout,314 eth::CollectionLimitField::SponsorTransferTimeout,373 limits.sponsor_transfer_timeout,315 limits.sponsor_transfer_timeout,374 ),316 ),375 convert_value_limit(317 eth::CollectionLimit::new(376 EvmCollectionLimits::SponsorApproveTimeout,318 eth::CollectionLimitField::SponsorApproveTimeout,377 limits.sponsor_approve_timeout,319 limits.sponsor_approve_timeout,378 ),320 ),379 convert_bool_limit(321 eth::CollectionLimit::new(380 EvmCollectionLimits::OwnerCanTransfer,322 eth::CollectionLimitField::OwnerCanTransfer,381 limits.owner_can_transfer,323 limits.owner_can_transfer,382 ),324 ),383 convert_bool_limit(325 eth::CollectionLimit::new(384 EvmCollectionLimits::OwnerCanDestroy,326 eth::CollectionLimitField::OwnerCanDestroy,385 limits.owner_can_destroy,327 limits.owner_can_destroy,386 ),328 ),387 convert_bool_limit(329 eth::CollectionLimit::new(388 EvmCollectionLimits::TransferEnabled,330 eth::CollectionLimitField::TransferEnabled,389 limits.transfers_enabled,331 limits.transfers_enabled,390 ),332 ),391 ])333 ])392 }334 }393335394 /// Set limits for the collection.336 /// Set limits for the collection.395 /// @dev Throws error if limit not found.337 /// @dev Throws error if limit not found.396 /// @param limit Name of the limit. Valid names:338 /// @param limit Some limit.397 /// "accountTokenOwnershipLimit",398 /// "sponsoredDataSize",399 /// "sponsoredDataRateLimit",400 /// "tokenLimit",401 /// "sponsorTransferTimeout",402 /// "sponsorApproveTimeout"403 /// "ownerCanTransfer",404 /// "ownerCanDestroy",405 /// "transfersEnabled"406 /// @param status enable\disable limit. Works only with `true`.407 /// @param value Value of the limit.408 #[solidity(rename_selector = "setCollectionLimit")]339 #[solidity(rename_selector = "setCollectionLimit")]409 fn set_collection_limit(340 fn set_collection_limit(410 &mut self,341 &mut self,411 caller: caller,342 caller: caller,412 limit: EvmCollectionLimits,343 limit: eth::CollectionLimit,413 status: bool,414 value: uint256,415 ) -> Result<void> {344 ) -> Result<void> {416 self.consume_store_reads_and_writes(1, 1)?;345 self.consume_store_reads_and_writes(1, 1)?;417346418 if !status {347 if !limit.has_value() {419 return Err(Error::Revert("user can't disable limits".into()));348 return Err(Error::Revert("user can't disable limits".into()));420 }349 }421350422 let value = value423 .try_into()424 .map_err(|_| Error::Revert(format!("can't convert value to u32 \"{}\"", value)))?;425426 let convert_value_to_bool = || match value {427 0 => Ok(false),428 1 => Ok(true),429 _ => {430 return Err(Error::Revert(format!(431 "can't convert value to boolean \"{}\"",432 value433 )))434 }435 };436437 let mut limits = self.limits.clone();438439 match limit {440 EvmCollectionLimits::AccountTokenOwnership => {441 limits.account_token_ownership_limit = Some(value);442 }443 EvmCollectionLimits::SponsoredDataSize => {444 limits.sponsored_data_size = Some(value);445 }446 EvmCollectionLimits::SponsoredDataRateLimit => {447 limits.sponsored_data_rate_limit = Some(SponsoringRateLimit::Blocks(value));448 }449 EvmCollectionLimits::TokenLimit => {450 limits.token_limit = Some(value);451 }452 EvmCollectionLimits::SponsorTransferTimeout => {453 limits.sponsor_transfer_timeout = Some(value);454 }455 EvmCollectionLimits::SponsorApproveTimeout => {456 limits.sponsor_approve_timeout = Some(value);457 }458 EvmCollectionLimits::OwnerCanTransfer => {459 limits.owner_can_transfer = Some(convert_value_to_bool()?);460 }461 EvmCollectionLimits::OwnerCanDestroy => {462 limits.owner_can_destroy = Some(convert_value_to_bool()?);463 }464 EvmCollectionLimits::TransferEnabled => {465 limits.transfers_enabled = Some(convert_value_to_bool()?);466 }467 _ => return Err(Error::Revert(format!("unknown limit \"{:?}\"", limit))),468 }469470 let caller = T::CrossAccountId::from_eth(caller);351 let caller = T::CrossAccountId::from_eth(caller);471 <Pallet<T>>::update_limits(&caller, self, limits).map_err(dispatch_to_evm::<T>)352 <Pallet<T>>::update_limits(&caller, self, limit.try_into()?).map_err(dispatch_to_evm::<T>)472 }353 }473354474 /// Get contract address.355 /// Get contract address.481 fn add_collection_admin_cross(362 fn add_collection_admin_cross(482 &mut self,363 &mut self,483 caller: caller,364 caller: caller,484 new_admin: EthCrossAccount,365 new_admin: eth::CrossAddress,485 ) -> Result<void> {366 ) -> Result<void> {486 self.consume_store_reads_and_writes(2, 2)?;367 self.consume_store_reads_and_writes(2, 2)?;487368496 fn remove_collection_admin_cross(377 fn remove_collection_admin_cross(497 &mut self,378 &mut self,498 caller: caller,379 caller: caller,499 admin: EthCrossAccount,380 admin: eth::CrossAddress,500 ) -> Result<void> {381 ) -> Result<void> {501 self.consume_store_reads_and_writes(2, 2)?;382 self.consume_store_reads_and_writes(2, 2)?;502383595476596 /// Returns nesting for a collection477 /// Returns nesting for a collection597 #[solidity(rename_selector = "collectionNestingRestrictedCollectionIds")]478 #[solidity(rename_selector = "collectionNestingRestrictedCollectionIds")]598 fn collection_nesting_restricted_ids(&self) -> Result<(bool, Vec<uint256>)> {479 fn collection_nesting_restricted_ids(&self) -> Result<eth::CollectionNesting> {599 let nesting = self.collection.permissions.nesting();480 let nesting = self.collection.permissions.nesting();600481601 Ok((482 Ok(eth::CollectionNesting::new(602 nesting.token_owner,483 nesting.token_owner,603 nesting484 nesting604 .restricted485 .restricted609 }490 }610491611 /// Returns permissions for a collection492 /// Returns permissions for a collection612 fn collection_nesting_permissions(&self) -> Result<Vec<(EvmPermissions, bool)>> {493 fn collection_nesting_permissions(&self) -> Result<Vec<eth::CollectionNestingPermission>> {613 let nesting = self.collection.permissions.nesting();494 let nesting = self.collection.permissions.nesting();614 Ok(vec![495 Ok(vec![615 (EvmPermissions::CollectionAdmin, nesting.collection_admin),496 eth::CollectionNestingPermission::new(497 eth::CollectionPermissionField::CollectionAdmin,498 nesting.collection_admin,499 ),616 (EvmPermissions::TokenOwner, nesting.token_owner),500 eth::CollectionNestingPermission::new(501 eth::CollectionPermissionField::TokenOwner,502 nesting.token_owner,503 ),617 ])504 ])618 }505 }619 /// Set the collection access method.506 /// Set the collection access method.638 /// Checks that user allowed to operate with collection.525 /// Checks that user allowed to operate with collection.639 ///526 ///640 /// @param user User address to check.527 /// @param user User address to check.641 fn allowlisted_cross(&self, user: EthCrossAccount) -> Result<bool> {528 fn allowlisted_cross(&self, user: eth::CrossAddress) -> Result<bool> {642 let user = user.into_sub_cross_account::<T>()?;529 let user = user.into_sub_cross_account::<T>()?;643 Ok(Pallet::<T>::allowed(self.id, user))530 Ok(Pallet::<T>::allowed(self.id, user))644 }531 }662 fn add_to_collection_allow_list_cross(549 fn add_to_collection_allow_list_cross(663 &mut self,550 &mut self,664 caller: caller,551 caller: caller,665 user: EthCrossAccount,552 user: eth::CrossAddress,666 ) -> Result<void> {553 ) -> Result<void> {667 self.consume_store_writes(1)?;554 self.consume_store_writes(1)?;668555691 fn remove_from_collection_allow_list_cross(578 fn remove_from_collection_allow_list_cross(692 &mut self,579 &mut self,693 caller: caller,580 caller: caller,694 user: EthCrossAccount,581 user: eth::CrossAddress,695 ) -> Result<void> {582 ) -> Result<void> {696 self.consume_store_writes(1)?;583 self.consume_store_writes(1)?;697584729 ///616 ///730 /// @param user User cross account to verify617 /// @param user User cross account to verify731 /// @return "true" if account is the owner or admin618 /// @return "true" if account is the owner or admin732 fn is_owner_or_admin_cross(&self, user: EthCrossAccount) -> Result<bool> {619 fn is_owner_or_admin_cross(&self, user: eth::CrossAddress) -> Result<bool> {733 let user = user.into_sub_cross_account::<T>()?;620 let user = user.into_sub_cross_account::<T>()?;734 Ok(self.is_owner_or_admin(&user))621 Ok(self.is_owner_or_admin(&user))735 }622 }750 ///637 ///751 /// @return Tuble with sponsor address and his substrate mirror.638 /// @return Tuble with sponsor address and his substrate mirror.752 /// If address is canonical then substrate mirror is zero and vice versa.639 /// If address is canonical then substrate mirror is zero and vice versa.753 fn collection_owner(&self) -> Result<EthCrossAccount> {640 fn collection_owner(&self) -> Result<eth::CrossAddress> {754 Ok(EthCrossAccount::from_sub_cross_account::<T>(641 Ok(eth::CrossAddress::from_sub_cross_account::<T>(755 &T::CrossAccountId::from_sub(self.owner.clone()),642 &T::CrossAccountId::from_sub(self.owner.clone()),756 ))643 ))757 }644 }774 ///661 ///775 /// @return Vector of tuples with admins address and his substrate mirror.662 /// @return Vector of tuples with admins address and his substrate mirror.776 /// If address is canonical then substrate mirror is zero and vice versa.663 /// If address is canonical then substrate mirror is zero and vice versa.777 fn collection_admins(&self) -> Result<Vec<EthCrossAccount>> {664 fn collection_admins(&self) -> Result<Vec<eth::CrossAddress>> {778 let result = crate::IsAdmin::<T>::iter_prefix((self.id,))665 let result = crate::IsAdmin::<T>::iter_prefix((self.id,))779 .map(|(admin, _)| EthCrossAccount::from_sub_cross_account::<T>(&admin))666 .map(|(admin, _)| eth::CrossAddress::from_sub_cross_account::<T>(&admin))780 .collect();667 .collect();781 Ok(result)668 Ok(result)782 }669 }788 fn change_collection_owner_cross(675 fn change_collection_owner_cross(789 &mut self,676 &mut self,790 caller: caller,677 caller: caller,791 new_owner: EthCrossAccount,678 new_owner: eth::CrossAddress,792 ) -> Result<void> {679 ) -> Result<void> {793 self.consume_store_writes(1)?;680 self.consume_store_writes(1)?;794681797 self.change_owner(caller, new_owner)684 self.change_owner(caller, new_owner)798 .map_err(dispatch_to_evm::<T>)685 .map_err(dispatch_to_evm::<T>)799 }686 }800}801802/// ### Note803/// Do not forget to add: `self.consume_store_reads(1)?;`804fn check_is_owner_or_admin<T: Config>(805 caller: caller,806 collection: &CollectionHandle<T>,807) -> Result<T::CrossAccountId> {808 let caller = T::CrossAccountId::from_eth(caller);809 collection810 .check_is_owner_or_admin(&caller)811 .map_err(dispatch_to_evm::<T>)?;812 Ok(caller)813}814815/// ### Note816/// Do not forget to add: `self.consume_store_writes(1)?;`817fn save<T: Config>(collection: &CollectionHandle<T>) -> Result<void> {818 collection819 .check_is_internal()820 .map_err(dispatch_to_evm::<T>)?;821 collection.save().map_err(dispatch_to_evm::<T>)?;822 Ok(())823}687}824688825/// Contains static property keys and values.689/// Contains static property keys and values.pallets/common/src/eth.rsdiffbeforeafterboth161617//! The module contains a number of functions for converting and checking ethereum identifiers.17//! The module contains a number of functions for converting and checking ethereum identifiers.181819use alloc::format;20use sp_std::{vec, vec::Vec};19use evm_coder::{21use evm_coder::{20 AbiCoder,22 AbiCoder,21 types::{uint256, address},23 types::{uint256, address},64 T::CrossAccountId::from_sub(account_id)66 T::CrossAccountId::from_sub(account_id)65}67}6869/// Ethereum representation of Optional value with uint256.70#[derive(Debug, Default, AbiCoder)]71pub struct OptionUint {72 status: bool,73 value: uint256,74}7576impl From<u32> for OptionUint {77 fn from(value: u32) -> Self {78 Self {79 status: true,80 value: uint256::from(value),81 }82 }83}8485impl From<Option<u32>> for OptionUint {86 fn from(value: Option<u32>) -> Self {87 match value {88 Some(value) => Self {89 status: true,90 value: value.into(),91 },92 None => Self {93 status: false,94 value: Default::default(),95 },96 }97 }98}99100impl From<bool> for OptionUint {101 fn from(value: bool) -> Self {102 Self {103 status: true,104 value: if value {105 uint256::from(1)106 } else {107 Default::default()108 },109 }110 }111}112113impl From<Option<bool>> for OptionUint {114 fn from(value: Option<bool>) -> Self {115 match value {116 Some(value) => Self::from(value),117 None => Self {118 status: false,119 value: Default::default(),120 },121 }122 }123}124125/// Ethereum representation of Optional value with CrossAddress.126#[derive(Debug, Default, AbiCoder)]127pub struct OptionCrossAddress {128 pub status: bool,129 pub value: CrossAddress,130}6613167/// Cross account struct132/// Cross account struct68#[derive(Debug, Default, AbiCoder)]133#[derive(Debug, Default, AbiCoder)]69pub struct EthCrossAccount {134pub struct CrossAddress {70 pub(crate) eth: address,135 pub(crate) eth: address,71 pub(crate) sub: uint256,136 pub(crate) sub: uint256,72}137}7313874impl EthCrossAccount {139impl CrossAddress {75 /// Converts `CrossAccountId` to `EthCrossAccountId`140 /// Converts `CrossAccountId` to [`CrossAddress`]76 pub fn from_sub_cross_account<T>(cross_account_id: &T::CrossAccountId) -> Self141 pub fn from_sub_cross_account<T>(cross_account_id: &T::CrossAccountId) -> Self77 where142 where78 T: pallet_evm::Config,143 T: pallet_evm::Config,87 }152 }88 }153 }89 }154 }90 /// Creates `EthCrossAccount` from substrate account155 /// Creates [`CrossAddress`] from substrate account91 pub fn from_sub<T>(account_id: &T::AccountId) -> Self156 pub fn from_sub<T>(account_id: &T::AccountId) -> Self92 where157 where93 T: pallet_evm::Config,158 T: pallet_evm::Config,98 sub: uint256::from_big_endian(account_id.as_ref()),163 sub: uint256::from_big_endian(account_id.as_ref()),99 }164 }100 }165 }101 /// Converts `EthCrossAccount` to `CrossAccountId`166 /// Converts [`CrossAddress`] to `CrossAccountId`102 pub fn into_sub_cross_account<T>(&self) -> evm_coder::execution::Result<T::CrossAccountId>167 pub fn into_sub_cross_account<T>(&self) -> evm_coder::execution::Result<T::CrossAccountId>103 where168 where104 T: pallet_evm::Config,169 T: pallet_evm::Config,116 }181 }117}182}183184/// Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).185#[derive(Debug, Default, AbiCoder)]186pub struct Property {187 key: evm_coder::types::string,188 value: evm_coder::types::bytes,189}190191impl TryFrom<up_data_structs::Property> for Property {192 type Error = evm_coder::execution::Error;193194 fn try_from(from: up_data_structs::Property) -> Result<Self, Self::Error> {195 let key = evm_coder::types::string::from_utf8(from.key.into())196 .map_err(|e| Self::Error::Revert(format!("utf8 conversion error: {}", e)))?;197 let value = evm_coder::types::bytes(from.value.to_vec());198 Ok(Property { key, value })199 }200}201202impl TryInto<up_data_structs::Property> for Property {203 type Error = evm_coder::execution::Error;204205 fn try_into(self) -> Result<up_data_structs::Property, Self::Error> {206 let key = <Vec<u8>>::from(self.key)207 .try_into()208 .map_err(|_| "key too large")?;209210 let value = self.value.0.try_into().map_err(|_| "value too large")?;211212 Ok(up_data_structs::Property { key, value })213 }214}118215119/// [`CollectionLimits`](up_data_structs::CollectionLimits) representation for EVM.216/// [`CollectionLimits`](up_data_structs::CollectionLimits) fields representation for EVM.120#[derive(Debug, Default, Clone, Copy, AbiCoder)]217#[derive(Debug, Default, Clone, Copy, AbiCoder)]121#[repr(u8)]218#[repr(u8)]122pub enum CollectionLimits {219pub enum CollectionLimitField {123 /// How many tokens can a user have on one account.220 /// How many tokens can a user have on one account.124 #[default]221 #[default]125 AccountTokenOwnership,222 AccountTokenOwnership,149 TransferEnabled,246 TransferEnabled,150}247}248249/// [`CollectionLimits`](up_data_structs::CollectionLimits) field representation for EVM.250#[derive(Debug, Default, AbiCoder)]251pub struct CollectionLimit {252 field: CollectionLimitField,253 value: OptionUint,254}255256impl CollectionLimit {257 /// Create [`CollectionLimit`] from field and value.258 pub fn new<T>(field: CollectionLimitField, value: T) -> Self259 where260 OptionUint: From<T>,261 {262 Self {263 field,264 value: value.into(),265 }266 }267 /// Whether the field contains a value.268 pub fn has_value(&self) -> bool {269 self.value.status270 }271}272273impl TryInto<up_data_structs::CollectionLimits> for CollectionLimit {274 type Error = evm_coder::execution::Error;275276 fn try_into(self) -> Result<up_data_structs::CollectionLimits, Self::Error> {277 let value = self.value.value.try_into().map_err(|error| {278 Self::Error::Revert(format!(279 "can't convert value to u32 \"{}\" because: \"{error}\"",280 self.value.value281 ))282 })?;283284 let convert_value_to_bool = || match value {285 0 => Ok(false),286 1 => Ok(true),287 _ => {288 return Err(Self::Error::Revert(format!(289 "can't convert value to boolean \"{value}\""290 )))291 }292 };293294 let mut limits = up_data_structs::CollectionLimits::default();295 match self.field {296 CollectionLimitField::AccountTokenOwnership => {297 limits.account_token_ownership_limit = Some(value);298 }299 CollectionLimitField::SponsoredDataSize => {300 limits.sponsored_data_size = Some(value);301 }302 CollectionLimitField::SponsoredDataRateLimit => {303 limits.sponsored_data_rate_limit =304 Some(up_data_structs::SponsoringRateLimit::Blocks(value));305 }306 CollectionLimitField::TokenLimit => {307 limits.token_limit = Some(value);308 }309 CollectionLimitField::SponsorTransferTimeout => {310 limits.sponsor_transfer_timeout = Some(value);311 }312 CollectionLimitField::SponsorApproveTimeout => {313 limits.sponsor_approve_timeout = Some(value);314 }315 CollectionLimitField::OwnerCanTransfer => {316 limits.owner_can_transfer = Some(convert_value_to_bool()?);317 }318 CollectionLimitField::OwnerCanDestroy => {319 limits.owner_can_destroy = Some(convert_value_to_bool()?);320 }321 CollectionLimitField::TransferEnabled => {322 limits.transfers_enabled = Some(convert_value_to_bool()?);323 }324 };325 Ok(limits)326 }327}328151/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.329/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.152#[derive(Default, Debug, Clone, Copy, AbiCoder)]330#[derive(Default, Debug, Clone, Copy, AbiCoder)]153#[repr(u8)]331#[repr(u8)]154pub enum CollectionPermissions {332pub enum CollectionPermissionField {155 /// Owner of token can nest tokens under it.333 /// Owner of token can nest tokens under it.156 #[default]334 #[default]157 TokenOwner,335 TokenOwner,163/// Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.341/// Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.164#[derive(AbiCoder, Copy, Clone, Default, Debug)]342#[derive(AbiCoder, Copy, Clone, Default, Debug)]165#[repr(u8)]343#[repr(u8)]166pub enum EthTokenPermissions {344pub enum TokenPermissionField {167 /// Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]345 /// Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]168 #[default]346 #[default]169 Mutable,347 Mutable,175 CollectionAdmin,353 CollectionAdmin,176}354}355356/// Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) as an key and value.357#[derive(Debug, Default, AbiCoder)]358pub struct PropertyPermission {359 /// TokenPermission field.360 code: TokenPermissionField,361 /// TokenPermission value.362 value: bool,363}364365impl PropertyPermission {366 /// Make vector of [`PropertyPermission`] from [`up_data_structs::PropertyPermission`].367 pub fn into_vec(pp: up_data_structs::PropertyPermission) -> Vec<Self> {368 vec![369 PropertyPermission {370 code: TokenPermissionField::Mutable,371 value: pp.mutable,372 },373 PropertyPermission {374 code: TokenPermissionField::TokenOwner,375 value: pp.token_owner,376 },377 PropertyPermission {378 code: TokenPermissionField::CollectionAdmin,379 value: pp.collection_admin,380 },381 ]382 }383384 /// Make [`up_data_structs::PropertyPermission`] from vector of [`PropertyPermission`].385 pub fn from_vec(permission: Vec<Self>) -> up_data_structs::PropertyPermission {386 let mut token_permission = up_data_structs::PropertyPermission::default();387388 for PropertyPermission { code, value } in permission {389 match code {390 TokenPermissionField::Mutable => token_permission.mutable = value,391 TokenPermissionField::TokenOwner => token_permission.token_owner = value,392 TokenPermissionField::CollectionAdmin => token_permission.collection_admin = value,393 }394 }395 token_permission396 }397}398399/// Ethereum representation of Token Property Permissions.400#[derive(Debug, Default, AbiCoder)]401pub struct TokenPropertyPermission {402 /// Token property key.403 key: evm_coder::types::string,404 /// Token property permissions.405 permissions: Vec<PropertyPermission>,406}407408impl409 From<(410 up_data_structs::PropertyKey,411 up_data_structs::PropertyPermission,412 )> for TokenPropertyPermission413{414 fn from(415 value: (416 up_data_structs::PropertyKey,417 up_data_structs::PropertyPermission,418 ),419 ) -> Self {420 let (key, permission) = value;421 let key = evm_coder::types::string::from_utf8(key.into_inner())422 .expect("Stored key must be valid");423 let permissions = PropertyPermission::into_vec(permission);424 Self { key, permissions }425 }426}427428impl TokenPropertyPermission {429 /// Convert vector of [`TokenPropertyPermission`] into vector of [`up_data_structs::PropertyKeyPermission`].430 pub fn into_property_key_permissions(431 permissions: Vec<TokenPropertyPermission>,432 ) -> evm_coder::execution::Result<Vec<up_data_structs::PropertyKeyPermission>> {433 let mut perms = Vec::new();434435 for TokenPropertyPermission { key, permissions } in permissions {436 let token_permission = PropertyPermission::from_vec(permissions);437438 perms.push(up_data_structs::PropertyKeyPermission {439 key: key.into_bytes().try_into().map_err(|_| "too long key")?,440 permission: token_permission,441 });442 }443 Ok(perms)444 }445}446447/// Nested collections.448#[derive(Debug, Default, AbiCoder)]449pub struct CollectionNesting {450 token_owner: bool,451 ids: Vec<uint256>,452}453454impl CollectionNesting {455 /// Create [`CollectionNesting`].456 pub fn new(token_owner: bool, ids: Vec<uint256>) -> Self {457 Self { token_owner, ids }458 }459}460461/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.462#[derive(Debug, Default, AbiCoder)]463pub struct CollectionNestingPermission {464 field: CollectionPermissionField,465 value: bool,466}467468impl CollectionNestingPermission {469 /// Create [`CollectionNestingPermission`].470 pub fn new(field: CollectionPermissionField, value: bool) -> Self {471 Self { field, value }472 }473}177474pallets/evm-contract-helpers/src/eth.rsdiffbeforeafterboth23 execution::Result,23 execution::Result,24 generate_stubgen, solidity_interface,24 generate_stubgen, solidity_interface,25 types::*,25 types::*,26 ToLog,26 ToLog, AbiCoder,27};27};28use pallet_common::eth::EthCrossAccount;28use pallet_common::eth;29use pallet_evm::{29use pallet_evm::{30 ExitRevert, OnCreate, OnMethodCall, PrecompileResult, PrecompileFailure, PrecompileHandle,30 ExitRevert, OnCreate, OnMethodCall, PrecompileResult, PrecompileFailure, PrecompileHandle,31 account::CrossAccountId,31 account::CrossAccountId,175 ///175 ///176 /// @param contractAddress The contract for which a sponsor is requested.176 /// @param contractAddress The contract for which a sponsor is requested.177 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.177 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.178 fn sponsor(&self, contract_address: address) -> Result<EthCrossAccount> {178 fn sponsor(&self, contract_address: address) -> Result<eth::OptionCrossAddress> {179 Ok(EthCrossAccount::from_sub_cross_account::<T>(179 Ok(match Pallet::<T>::get_sponsor(contract_address) {180 &Pallet::<T>::get_sponsor(contract_address).ok_or("Contract has no sponsor")?,180 Some(ref value) => eth::OptionCrossAddress {181 status: true,182 value: eth::CrossAddress::from_sub_cross_account::<T>(value),183 },184 None => eth::OptionCrossAddress {185 status: false,186 value: Default::default(),187 },181 ))188 })182 }189 }183190184 /// Check tat contract has confirmed sponsor.191 /// Check tat contract has confirmed sponsor.208 &mut self,215 &mut self,209 caller: caller,216 caller: caller,210 contract_address: address,217 contract_address: address,211 // TODO: implement support for enums in evm-coder212 mode: uint8,218 mode: SponsoringModeT,213 ) -> Result<void> {219 ) -> Result<void> {214 self.recorder().consume_sload()?;220 self.recorder().consume_sload()?;215 self.recorder().consume_sstore()?;221 self.recorder().consume_sstore()?;216222217 <Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;223 <Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;218 let mode = SponsoringModeT::from_eth(mode).ok_or("unknown mode")?;219 <Pallet<T>>::set_sponsoring_mode(contract_address, mode);224 <Pallet<T>>::set_sponsoring_mode(contract_address, mode);220225221 Ok(())226 Ok(())pallets/evm-contract-helpers/src/lib.rsdiffbeforeafterboth19#![warn(missing_docs)]19#![warn(missing_docs)]202021use codec::{Decode, Encode, MaxEncodedLen};21use codec::{Decode, Encode, MaxEncodedLen};22use evm_coder::AbiCoder;22pub use pallet::*;23pub use pallet::*;23pub use eth::*;24pub use eth::*;24use scale_info::TypeInfo;25use scale_info::TypeInfo;408409409/// Available contract sponsoring modes410/// Available contract sponsoring modes410#[derive(Encode, Decode, PartialEq, TypeInfo, MaxEncodedLen, Default)]411#[derive(412 Encode, Decode, Debug, PartialEq, TypeInfo, MaxEncodedLen, Default, AbiCoder, Clone, Copy,413)]414#[repr(u8)]411pub enum SponsoringModeT {415pub enum SponsoringModeT {412 /// Sponsoring is disabled416 /// Sponsoring is disabled413 #[default]417 #[default]418 Generous,422 Generous,419}423}420421impl SponsoringModeT {422 fn from_eth(v: u8) -> Option<Self> {423 Some(match v {424 0 => Self::Disabled,425 1 => Self::Allowlisted,426 2 => Self::Generous,427 _ => return None,428 })429 }430 #[allow(dead_code)]431 fn to_eth(self) -> u8 {432 match self {433 SponsoringModeT::Disabled => 0,434 SponsoringModeT::Allowlisted => 1,435 SponsoringModeT::Generous => 2,436 }437 }438}439424pallets/evm-contract-helpers/src/stubs/ContractHelpers.rawdiffbeforeafterbothbinary blob — no preview
pallets/evm-contract-helpers/src/stubs/ContractHelpers.soldiffbeforeafterboth96 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.96 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.97 /// @dev EVM selector for this function is: 0x766c4f37,97 /// @dev EVM selector for this function is: 0x766c4f37,98 /// or in textual repr: sponsor(address)98 /// or in textual repr: sponsor(address)99 function sponsor(address contractAddress) public view returns (EthCrossAccount memory) {99 function sponsor(address contractAddress) public view returns (OptionCrossAddress memory) {100 require(false, stub_error);100 require(false, stub_error);101 contractAddress;101 contractAddress;102 dummy;102 dummy;103 return EthCrossAccount(0x0000000000000000000000000000000000000000, 0);103 return OptionCrossAddress(false, CrossAddress(0x0000000000000000000000000000000000000000, 0));104 }104 }105105106 /// Check tat contract has confirmed sponsor.106 /// Check tat contract has confirmed sponsor.140140141 /// @dev EVM selector for this function is: 0xfde8a560,141 /// @dev EVM selector for this function is: 0xfde8a560,142 /// or in textual repr: setSponsoringMode(address,uint8)142 /// or in textual repr: setSponsoringMode(address,uint8)143 function setSponsoringMode(address contractAddress, uint8 mode) public {143 function setSponsoringMode(address contractAddress, SponsoringModeT mode) public {144 require(false, stub_error);144 require(false, stub_error);145 contractAddress;145 contractAddress;146 mode;146 mode;265 }265 }266}266}267268/// Available contract sponsoring modes269enum SponsoringModeT {270 /// Sponsoring is disabled271 Disabled,272 /// Only users from allowlist will be sponsored273 Allowlisted,274 /// All users will be sponsored275 Generous276}267277268/// @dev Cross account struct278/// Cross account struct269struct EthCrossAccount {279struct CrossAddress {270 address eth;280 address eth;271 uint256 sub;281 uint256 sub;272}282}283284/// Ethereum representation of Optional value with CrossAddress.285struct OptionCrossAddress {286 bool status;287 CrossAddress value;288}273289pallets/fungible/src/erc.rsdiffbeforeafterboth27use pallet_common::{27use pallet_common::{28 CollectionHandle,28 CollectionHandle,29 erc::{CommonEvmHandler, PrecompileResult, CollectionCall},29 erc::{CommonEvmHandler, PrecompileResult, CollectionCall},30 eth::EthCrossAccount,31};30};32use sp_std::vec::Vec;31use sp_std::vec::Vec;33use pallet_evm::{account::CrossAccountId, PrecompileHandle};32use pallet_evm::{account::CrossAccountId, PrecompileHandle};175 }174 }176175177 #[weight(<SelfWeightOf<T>>::create_item())]176 #[weight(<SelfWeightOf<T>>::create_item())]178 fn mint_cross(&mut self, caller: caller, to: EthCrossAccount, amount: uint256) -> Result<bool> {177 fn mint_cross(178 &mut self,179 caller: caller,180 to: pallet_common::eth::CrossAddress,181 amount: uint256,182 ) -> Result<bool> {179 let caller = T::CrossAccountId::from_eth(caller);183 let caller = T::CrossAccountId::from_eth(caller);180 let to = to.into_sub_cross_account::<T>()?;184 let to = to.into_sub_cross_account::<T>()?;191 fn approve_cross(195 fn approve_cross(192 &mut self,196 &mut self,193 caller: caller,197 caller: caller,194 spender: EthCrossAccount,198 spender: pallet_common::eth::CrossAddress,195 amount: uint256,199 amount: uint256,196 ) -> Result<bool> {200 ) -> Result<bool> {197 let caller = T::CrossAccountId::from_eth(caller);201 let caller = T::CrossAccountId::from_eth(caller);232 fn burn_from_cross(236 fn burn_from_cross(233 &mut self,237 &mut self,234 caller: caller,238 caller: caller,235 from: EthCrossAccount,239 from: pallet_common::eth::CrossAddress,236 amount: uint256,240 amount: uint256,237 ) -> Result<bool> {241 ) -> Result<bool> {238 let caller = T::CrossAccountId::from_eth(caller);242 let caller = T::CrossAccountId::from_eth(caller);274 fn transfer_cross(278 fn transfer_cross(275 &mut self,279 &mut self,276 caller: caller,280 caller: caller,277 to: EthCrossAccount,281 to: pallet_common::eth::CrossAddress,278 amount: uint256,282 amount: uint256,279 ) -> Result<bool> {283 ) -> Result<bool> {280 let caller = T::CrossAccountId::from_eth(caller);284 let caller = T::CrossAccountId::from_eth(caller);292 fn transfer_from_cross(296 fn transfer_from_cross(293 &mut self,297 &mut self,294 caller: caller,298 caller: caller,295 from: EthCrossAccount,299 from: pallet_common::eth::CrossAddress,296 to: EthCrossAccount,300 to: pallet_common::eth::CrossAddress,297 amount: uint256,301 amount: uint256,298 ) -> Result<bool> {302 ) -> Result<bool> {299 let caller = T::CrossAccountId::from_eth(caller);303 let caller = T::CrossAccountId::from_eth(caller);pallets/fungible/src/stubs/UniqueFungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth18}18}191920/// @title A contract that allows you to work with collections.20/// @title A contract that allows you to work with collections.21/// @dev the ERC-165 identifier for this interface is 0x81172a7521/// @dev the ERC-165 identifier for this interface is 0x2a14cfd122contract Collection is Dummy, ERC165 {22contract Collection is Dummy, ERC165 {23 // /// Set collection property.23 // /// Set collection property.24 // ///24 // ///114 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.114 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.115 /// @dev EVM selector for this function is: 0x84a1d5a8,115 /// @dev EVM selector for this function is: 0x84a1d5a8,116 /// or in textual repr: setCollectionSponsorCross((address,uint256))116 /// or in textual repr: setCollectionSponsorCross((address,uint256))117 function setCollectionSponsorCross(EthCrossAccount memory sponsor) public {117 function setCollectionSponsorCross(CrossAddress memory sponsor) public {118 require(false, stub_error);118 require(false, stub_error);119 sponsor;119 sponsor;120 dummy = 0;120 dummy = 0;152 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.152 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.153 /// @dev EVM selector for this function is: 0x6ec0a9f1,153 /// @dev EVM selector for this function is: 0x6ec0a9f1,154 /// or in textual repr: collectionSponsor()154 /// or in textual repr: collectionSponsor()155 function collectionSponsor() public view returns (EthCrossAccount memory) {155 function collectionSponsor() public view returns (CrossAddress memory) {156 require(false, stub_error);156 require(false, stub_error);157 dummy;157 dummy;158 return EthCrossAccount(0x0000000000000000000000000000000000000000, 0);158 return CrossAddress(0x0000000000000000000000000000000000000000, 0);159 }159 }160160161 /// Get current collection limits.161 /// Get current collection limits.162 ///162 ///163 /// @return Array of tuples (byte, bool, uint256) with limits and their values. Order of limits:163 /// @return Array of collection limits164 /// "accountTokenOwnershipLimit",165 /// "sponsoredDataSize",166 /// "sponsoredDataRateLimit",167 /// "tokenLimit",168 /// "sponsorTransferTimeout",169 /// "sponsorApproveTimeout"170 /// "ownerCanTransfer",171 /// "ownerCanDestroy",172 /// "transfersEnabled"173 /// Return `false` if a limit not set.174 /// @dev EVM selector for this function is: 0xf63bc572,164 /// @dev EVM selector for this function is: 0xf63bc572,175 /// or in textual repr: collectionLimits()165 /// or in textual repr: collectionLimits()176 function collectionLimits() public view returns (Tuple23[] memory) {166 function collectionLimits() public view returns (CollectionLimit[] memory) {177 require(false, stub_error);167 require(false, stub_error);178 dummy;168 dummy;179 return new Tuple23[](0);169 return new CollectionLimit[](0);180 }170 }181171182 /// Set limits for the collection.172 /// Set limits for the collection.183 /// @dev Throws error if limit not found.173 /// @dev Throws error if limit not found.184 /// @param limit Name of the limit. Valid names:185 /// "accountTokenOwnershipLimit",186 /// "sponsoredDataSize",187 /// "sponsoredDataRateLimit",188 /// "tokenLimit",189 /// "sponsorTransferTimeout",190 /// "sponsorApproveTimeout"191 /// "ownerCanTransfer",192 /// "ownerCanDestroy",193 /// "transfersEnabled"194 /// @param status enable\disable limit. Works only with `true`.195 /// @param value Value of the limit.174 /// @param limit Some limit.196 /// @dev EVM selector for this function is: 0x88150bd0,175 /// @dev EVM selector for this function is: 0x2316ee74,197 /// or in textual repr: setCollectionLimit(uint8,bool,uint256)176 /// or in textual repr: setCollectionLimit((uint8,(bool,uint256)))198 function setCollectionLimit(177 function setCollectionLimit(CollectionLimit memory limit) public {199 CollectionLimits limit,200 bool status,201 uint256 value202 ) public {203 require(false, stub_error);178 require(false, stub_error);204 limit;179 limit;205 status;206 value;207 dummy = 0;180 dummy = 0;208 }181 }209182220 /// @param newAdmin Cross account administrator address.193 /// @param newAdmin Cross account administrator address.221 /// @dev EVM selector for this function is: 0x859aa7d6,194 /// @dev EVM selector for this function is: 0x859aa7d6,222 /// or in textual repr: addCollectionAdminCross((address,uint256))195 /// or in textual repr: addCollectionAdminCross((address,uint256))223 function addCollectionAdminCross(EthCrossAccount memory newAdmin) public {196 function addCollectionAdminCross(CrossAddress memory newAdmin) public {224 require(false, stub_error);197 require(false, stub_error);225 newAdmin;198 newAdmin;226 dummy = 0;199 dummy = 0;230 /// @param admin Cross account administrator address.203 /// @param admin Cross account administrator address.231 /// @dev EVM selector for this function is: 0x6c0cd173,204 /// @dev EVM selector for this function is: 0x6c0cd173,232 /// or in textual repr: removeCollectionAdminCross((address,uint256))205 /// or in textual repr: removeCollectionAdminCross((address,uint256))233 function removeCollectionAdminCross(EthCrossAccount memory admin) public {206 function removeCollectionAdminCross(CrossAddress memory admin) public {234 require(false, stub_error);207 require(false, stub_error);235 admin;208 admin;236 dummy = 0;209 dummy = 0;284 /// Returns nesting for a collection257 /// Returns nesting for a collection285 /// @dev EVM selector for this function is: 0x22d25bfe,258 /// @dev EVM selector for this function is: 0x22d25bfe,286 /// or in textual repr: collectionNestingRestrictedCollectionIds()259 /// or in textual repr: collectionNestingRestrictedCollectionIds()287 function collectionNestingRestrictedCollectionIds() public view returns (Tuple29 memory) {260 function collectionNestingRestrictedCollectionIds() public view returns (CollectionNesting memory) {288 require(false, stub_error);261 require(false, stub_error);289 dummy;262 dummy;290 return Tuple29(false, new uint256[](0));263 return CollectionNesting(false, new uint256[](0));291 }264 }292265293 /// Returns permissions for a collection266 /// Returns permissions for a collection294 /// @dev EVM selector for this function is: 0x5b2eaf4b,267 /// @dev EVM selector for this function is: 0x5b2eaf4b,295 /// or in textual repr: collectionNestingPermissions()268 /// or in textual repr: collectionNestingPermissions()296 function collectionNestingPermissions() public view returns (Tuple32[] memory) {269 function collectionNestingPermissions() public view returns (CollectionNestingPermission[] memory) {297 require(false, stub_error);270 require(false, stub_error);298 dummy;271 dummy;299 return new Tuple32[](0);272 return new CollectionNestingPermission[](0);300 }273 }301274302 /// Set the collection access method.275 /// Set the collection access method.316 /// @param user User address to check.289 /// @param user User address to check.317 /// @dev EVM selector for this function is: 0x91b6df49,290 /// @dev EVM selector for this function is: 0x91b6df49,318 /// or in textual repr: allowlistedCross((address,uint256))291 /// or in textual repr: allowlistedCross((address,uint256))319 function allowlistedCross(EthCrossAccount memory user) public view returns (bool) {292 function allowlistedCross(CrossAddress memory user) public view returns (bool) {320 require(false, stub_error);293 require(false, stub_error);321 user;294 user;322 dummy;295 dummy;339 /// @param user User cross account address.312 /// @param user User cross account address.340 /// @dev EVM selector for this function is: 0xa0184a3a,313 /// @dev EVM selector for this function is: 0xa0184a3a,341 /// or in textual repr: addToCollectionAllowListCross((address,uint256))314 /// or in textual repr: addToCollectionAllowListCross((address,uint256))342 function addToCollectionAllowListCross(EthCrossAccount memory user) public {315 function addToCollectionAllowListCross(CrossAddress memory user) public {343 require(false, stub_error);316 require(false, stub_error);344 user;317 user;345 dummy = 0;318 dummy = 0;361 /// @param user User cross account address.334 /// @param user User cross account address.362 /// @dev EVM selector for this function is: 0x09ba452a,335 /// @dev EVM selector for this function is: 0x09ba452a,363 /// or in textual repr: removeFromCollectionAllowListCross((address,uint256))336 /// or in textual repr: removeFromCollectionAllowListCross((address,uint256))364 function removeFromCollectionAllowListCross(EthCrossAccount memory user) public {337 function removeFromCollectionAllowListCross(CrossAddress memory user) public {365 require(false, stub_error);338 require(false, stub_error);366 user;339 user;367 dummy = 0;340 dummy = 0;397 /// @return "true" if account is the owner or admin370 /// @return "true" if account is the owner or admin398 /// @dev EVM selector for this function is: 0x3e75a905,371 /// @dev EVM selector for this function is: 0x3e75a905,399 /// or in textual repr: isOwnerOrAdminCross((address,uint256))372 /// or in textual repr: isOwnerOrAdminCross((address,uint256))400 function isOwnerOrAdminCross(EthCrossAccount memory user) public view returns (bool) {373 function isOwnerOrAdminCross(CrossAddress memory user) public view returns (bool) {401 require(false, stub_error);374 require(false, stub_error);402 user;375 user;403 dummy;376 dummy;421 /// If address is canonical then substrate mirror is zero and vice versa.394 /// If address is canonical then substrate mirror is zero and vice versa.422 /// @dev EVM selector for this function is: 0xdf727d3b,395 /// @dev EVM selector for this function is: 0xdf727d3b,423 /// or in textual repr: collectionOwner()396 /// or in textual repr: collectionOwner()424 function collectionOwner() public view returns (EthCrossAccount memory) {397 function collectionOwner() public view returns (CrossAddress memory) {425 require(false, stub_error);398 require(false, stub_error);426 dummy;399 dummy;427 return EthCrossAccount(0x0000000000000000000000000000000000000000, 0);400 return CrossAddress(0x0000000000000000000000000000000000000000, 0);428 }401 }429402430 // /// Changes collection owner to another account403 // /// Changes collection owner to another account445 /// If address is canonical then substrate mirror is zero and vice versa.418 /// If address is canonical then substrate mirror is zero and vice versa.446 /// @dev EVM selector for this function is: 0x5813216b,419 /// @dev EVM selector for this function is: 0x5813216b,447 /// or in textual repr: collectionAdmins()420 /// or in textual repr: collectionAdmins()448 function collectionAdmins() public view returns (EthCrossAccount[] memory) {421 function collectionAdmins() public view returns (CrossAddress[] memory) {449 require(false, stub_error);422 require(false, stub_error);450 dummy;423 dummy;451 return new EthCrossAccount[](0);424 return new CrossAddress[](0);452 }425 }453426454 /// Changes collection owner to another account427 /// Changes collection owner to another account457 /// @param newOwner new owner cross account430 /// @param newOwner new owner cross account458 /// @dev EVM selector for this function is: 0x6496c497,431 /// @dev EVM selector for this function is: 0x6496c497,459 /// or in textual repr: changeCollectionOwnerCross((address,uint256))432 /// or in textual repr: changeCollectionOwnerCross((address,uint256))460 function changeCollectionOwnerCross(EthCrossAccount memory newOwner) public {433 function changeCollectionOwnerCross(CrossAddress memory newOwner) public {461 require(false, stub_error);434 require(false, stub_error);462 newOwner;435 newOwner;463 dummy = 0;436 dummy = 0;464 }437 }465}438}466439467/// @dev Cross account struct440/// Cross account struct468struct EthCrossAccount {441struct CrossAddress {469 address eth;442 address eth;470 uint256 sub;443 uint256 sub;471}444}472445446/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.447struct CollectionNestingPermission {448 CollectionPermissionField field;449 bool value;450}451452/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.473enum CollectionPermissions {453enum CollectionPermissionField {474 CollectionAdmin,454 /// Owner of token can nest tokens under it.475 TokenOwner455 TokenOwner,456 /// Admin of token collection can nest tokens under token.457 CollectionAdmin476}458}477459478/// @dev anonymous struct460/// Nested collections.479struct Tuple32 {461struct CollectionNesting {480 CollectionPermissions field_0;462 bool token_owner;481 bool field_1;463 uint256[] ids;482}464}483465484/// @dev anonymous struct466/// [`CollectionLimits`](up_data_structs::CollectionLimits) field representation for EVM.467struct CollectionLimit {468 CollectionLimitField field;469 OptionUint value;470}471472/// Ethereum representation of Optional value with uint256.485struct Tuple29 {473struct OptionUint {486 bool field_0;474 bool status;487 uint256[] field_1;475 uint256 value;488}476}489477490/// @dev [`CollectionLimits`](up_data_structs::CollectionLimits) representation for EVM.478/// [`CollectionLimits`](up_data_structs::CollectionLimits) fields representation for EVM.491enum CollectionLimits {479enum CollectionLimitField {492 /// @dev How many tokens can a user have on one account.480 /// How many tokens can a user have on one account.493 AccountTokenOwnership,481 AccountTokenOwnership,494 /// @dev How many bytes of data are available for sponsorship.482 /// How many bytes of data are available for sponsorship.495 SponsoredDataSize,483 SponsoredDataSize,496 /// @dev In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]484 /// In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]497 SponsoredDataRateLimit,485 SponsoredDataRateLimit,498 /// @dev How many tokens can be mined into this collection.486 /// How many tokens can be mined into this collection.499 TokenLimit,487 TokenLimit,500 /// @dev Timeouts for transfer sponsoring.488 /// Timeouts for transfer sponsoring.501 SponsorTransferTimeout,489 SponsorTransferTimeout,502 /// @dev Timeout for sponsoring an approval in passed blocks.490 /// Timeout for sponsoring an approval in passed blocks.503 SponsorApproveTimeout,491 SponsorApproveTimeout,504 /// @dev Whether the collection owner of the collection can send tokens (which belong to other users).492 /// Whether the collection owner of the collection can send tokens (which belong to other users).505 OwnerCanTransfer,493 OwnerCanTransfer,506 /// @dev Can the collection owner burn other people's tokens.494 /// Can the collection owner burn other people's tokens.507 OwnerCanDestroy,495 OwnerCanDestroy,508 /// @dev Is it possible to send tokens from this collection between users.496 /// Is it possible to send tokens from this collection between users.509 TransferEnabled497 TransferEnabled510}498}511499512/// @dev anonymous struct500/// Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).513struct Tuple23 {514 CollectionLimits field_0;515 bool field_1;516 uint256 field_2;517}518519/// @dev Property struct520struct Property {501struct Property {521 string key;502 string key;522 bytes value;503 bytes value;535516536 /// @dev EVM selector for this function is: 0x269e6158,517 /// @dev EVM selector for this function is: 0x269e6158,537 /// or in textual repr: mintCross((address,uint256),uint256)518 /// or in textual repr: mintCross((address,uint256),uint256)538 function mintCross(EthCrossAccount memory to, uint256 amount) public returns (bool) {519 function mintCross(CrossAddress memory to, uint256 amount) public returns (bool) {539 require(false, stub_error);520 require(false, stub_error);540 to;521 to;541 amount;522 amount;545526546 /// @dev EVM selector for this function is: 0x0ecd0ab0,527 /// @dev EVM selector for this function is: 0x0ecd0ab0,547 /// or in textual repr: approveCross((address,uint256),uint256)528 /// or in textual repr: approveCross((address,uint256),uint256)548 function approveCross(EthCrossAccount memory spender, uint256 amount) public returns (bool) {529 function approveCross(CrossAddress memory spender, uint256 amount) public returns (bool) {549 require(false, stub_error);530 require(false, stub_error);550 spender;531 spender;551 amount;532 amount;575 /// @param amount The amount that will be burnt.556 /// @param amount The amount that will be burnt.576 /// @dev EVM selector for this function is: 0xbb2f5a58,557 /// @dev EVM selector for this function is: 0xbb2f5a58,577 /// or in textual repr: burnFromCross((address,uint256),uint256)558 /// or in textual repr: burnFromCross((address,uint256),uint256)578 function burnFromCross(EthCrossAccount memory from, uint256 amount) public returns (bool) {559 function burnFromCross(CrossAddress memory from, uint256 amount) public returns (bool) {579 require(false, stub_error);560 require(false, stub_error);580 from;561 from;581 amount;562 amount;596577597 /// @dev EVM selector for this function is: 0x2ada85ff,578 /// @dev EVM selector for this function is: 0x2ada85ff,598 /// or in textual repr: transferCross((address,uint256),uint256)579 /// or in textual repr: transferCross((address,uint256),uint256)599 function transferCross(EthCrossAccount memory to, uint256 amount) public returns (bool) {580 function transferCross(CrossAddress memory to, uint256 amount) public returns (bool) {600 require(false, stub_error);581 require(false, stub_error);601 to;582 to;602 amount;583 amount;607 /// @dev EVM selector for this function is: 0xd5cf430b,588 /// @dev EVM selector for this function is: 0xd5cf430b,608 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)589 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)609 function transferFromCross(590 function transferFromCross(610 EthCrossAccount memory from,591 CrossAddress memory from,611 EthCrossAccount memory to,592 CrossAddress memory to,612 uint256 amount593 uint256 amount613 ) public returns (bool) {594 ) public returns (bool) {614 require(false, stub_error);595 require(false, stub_error);pallets/nonfungible/src/erc.rsdiffbeforeafterboth26};26};27use evm_coder::{27use evm_coder::{28 abi::AbiType, ToLog, execution::*, generate_stubgen, solidity, solidity_interface, types::*,28 abi::AbiType, ToLog, execution::*, generate_stubgen, solidity, solidity_interface, types::*,29 types::Property as PropertyStruct, weight,29 weight,30};30};31use frame_support::BoundedVec;31use frame_support::BoundedVec;32use up_data_structs::{32use up_data_structs::{38use pallet_common::{38use pallet_common::{39 CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations,39 CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations,40 erc::{CommonEvmHandler, PrecompileResult, CollectionCall, static_property::key},40 erc::{CommonEvmHandler, PrecompileResult, CollectionCall, static_property::key},41 eth::{EthCrossAccount, EthTokenPermissions},41 eth,42};42};43use pallet_evm::{account::CrossAccountId, PrecompileHandle};43use pallet_evm::{account::CrossAccountId, PrecompileHandle};44use pallet_evm_coder_substrate::call;44use pallet_evm_coder_substrate::call;94 fn set_token_property_permissions(94 fn set_token_property_permissions(95 &mut self,95 &mut self,96 caller: caller,96 caller: caller,97 permissions: Vec<(string, Vec<(EthTokenPermissions, bool)>)>,97 permissions: Vec<eth::TokenPropertyPermission>,98 ) -> Result<()> {98 ) -> Result<()> {99 let caller = T::CrossAccountId::from_eth(caller);99 let caller = T::CrossAccountId::from_eth(caller);100 const PERMISSIONS_FIELDS_COUNT: usize = 3;101102 let mut perms = Vec::new();103104 for (key, pp) in permissions {105 if pp.len() > PERMISSIONS_FIELDS_COUNT {106 return Err(alloc::format!(107 "Actual number of fields {} for {}, which exceeds the maximum value of {}",108 pp.len(),109 stringify!(EthTokenPermissions),110 PERMISSIONS_FIELDS_COUNT111 )112 .as_str()113 .into());114 }115116 let mut token_permission = PropertyPermission::default();100 let perms = eth::TokenPropertyPermission::into_property_key_permissions(permissions)?;117118 for (perm, value) in pp {119 match perm {120 EthTokenPermissions::Mutable => token_permission.mutable = value,121 EthTokenPermissions::TokenOwner => token_permission.token_owner = value,122 EthTokenPermissions::CollectionAdmin => {123 token_permission.collection_admin = value124 }125 }126 }127128 perms.push(PropertyKeyPermission {129 key: key.into_bytes().try_into().map_err(|_| "too long key")?,130 permission: token_permission,131 });132 }133101134 <Pallet<T>>::set_token_property_permissions(self, &caller, perms)102 <Pallet<T>>::set_token_property_permissions(self, &caller, perms)135 .map_err(dispatch_to_evm::<T>)103 .map_err(dispatch_to_evm::<T>)136 }104 }137105138 /// @notice Get permissions for token properties.106 /// @notice Get permissions for token properties.139 fn token_property_permissions(107 fn token_property_permissions(&self) -> Result<Vec<eth::TokenPropertyPermission>> {140 &self,141 ) -> Result<Vec<(string, Vec<(EthTokenPermissions, bool)>)>> {142 let perms = <Pallet<T>>::token_property_permission(self.id);108 let perms = <Pallet<T>>::token_property_permission(self.id);143 Ok(perms109 Ok(perms144 .into_iter()110 .into_iter()145 .map(|(key, pp)| {111 .map(eth::TokenPropertyPermission::from)146 let key = string::from_utf8(key.into_inner()).expect("Stored key must be valid");147 let pp = vec![148 (EthTokenPermissions::Mutable, pp.mutable),149 (EthTokenPermissions::TokenOwner, pp.token_owner),150 (EthTokenPermissions::CollectionAdmin, pp.collection_admin),151 ];152 (key, pp)153 })154 .collect())112 .collect())155 }113 }156114198 &mut self,156 &mut self,199 caller: caller,157 caller: caller,200 token_id: uint256,158 token_id: uint256,201 properties: Vec<PropertyStruct>,159 properties: Vec<eth::Property>,202 ) -> Result<()> {160 ) -> Result<()> {203 let caller = T::CrossAccountId::from_eth(caller);161 let caller = T::CrossAccountId::from_eth(caller);204 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;162 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;209167210 let properties = properties168 let properties = properties211 .into_iter()169 .into_iter()212 .map(|PropertyStruct { key, value }| {170 .map(eth::Property::try_into)213 let key = <Vec<u8>>::from(key)214 .try_into()215 .map_err(|_| "key too large")?;216217 let value = value.0.try_into().map_err(|_| "value too large")?;218219 Ok(Property { key, value })220 })221 .collect::<Result<Vec<_>>>()?;171 .collect::<Result<Vec<_>>>()?;222172223 <Pallet<T>>::set_token_properties(173 <Pallet<T>>::set_token_properties(800 /// Returns the owner (in cross format) of the token.750 /// Returns the owner (in cross format) of the token.801 ///751 ///802 /// @param tokenId Id for the token.752 /// @param tokenId Id for the token.803 fn cross_owner_of(&self, token_id: uint256) -> Result<EthCrossAccount> {753 fn cross_owner_of(&self, token_id: uint256) -> Result<eth::CrossAddress> {804 Self::token_owner(&self, token_id.try_into()?)754 Self::token_owner(&self, token_id.try_into()?)805 .map(|o| EthCrossAccount::from_sub_cross_account::<T>(&o))755 .map(|o| eth::CrossAddress::from_sub_cross_account::<T>(&o))806 .ok_or(Error::Revert("key too large".into()))756 .ok_or(Error::Revert("key too large".into()))807 }757 }808758811 /// @param tokenId Id for the token.761 /// @param tokenId Id for the token.812 /// @param keys Properties keys. Empty keys for all propertyes.762 /// @param keys Properties keys. Empty keys for all propertyes.813 /// @return Vector of properties key/value pairs.763 /// @return Vector of properties key/value pairs.814 fn properties(&self, token_id: uint256, keys: Vec<string>) -> Result<Vec<PropertyStruct>> {764 fn properties(&self, token_id: uint256, keys: Vec<string>) -> Result<Vec<eth::Property>> {815 let keys = keys765 let keys = keys816 .into_iter()766 .into_iter()817 .map(|key| {767 .map(|key| {827 if keys.is_empty() { None } else { Some(keys) },777 if keys.is_empty() { None } else { Some(keys) },828 )778 )829 .into_iter()779 .into_iter()830 .map(|p| {780 .map(eth::Property::try_from)831 let key = string::from_utf8(p.key.to_vec())832 .map_err(|e| Error::Revert(alloc::format!("{}", e)))?;833 let value = bytes(p.value.to_vec());834 Ok(PropertyStruct { key, value })835 })836 .collect::<Result<Vec<_>>>()781 .collect::<Result<Vec<_>>>()837 }782 }838783846 fn approve_cross(791 fn approve_cross(847 &mut self,792 &mut self,848 caller: caller,793 caller: caller,849 approved: EthCrossAccount,794 approved: eth::CrossAddress,850 token_id: uint256,795 token_id: uint256,851 ) -> Result<void> {796 ) -> Result<void> {852 let caller = T::CrossAccountId::from_eth(caller);797 let caller = T::CrossAccountId::from_eth(caller);885 fn transfer_cross(830 fn transfer_cross(886 &mut self,831 &mut self,887 caller: caller,832 caller: caller,888 to: EthCrossAccount,833 to: eth::CrossAddress,889 token_id: uint256,834 token_id: uint256,890 ) -> Result<void> {835 ) -> Result<void> {891 let caller = T::CrossAccountId::from_eth(caller);836 let caller = T::CrossAccountId::from_eth(caller);909 fn transfer_from_cross(854 fn transfer_from_cross(910 &mut self,855 &mut self,911 caller: caller,856 caller: caller,912 from: EthCrossAccount,857 from: eth::CrossAddress,913 to: EthCrossAccount,858 to: eth::CrossAddress,914 token_id: uint256,859 token_id: uint256,915 ) -> Result<void> {860 ) -> Result<void> {916 let caller = T::CrossAccountId::from_eth(caller);861 let caller = T::CrossAccountId::from_eth(caller);956 fn burn_from_cross(901 fn burn_from_cross(957 &mut self,902 &mut self,958 caller: caller,903 caller: caller,959 from: EthCrossAccount,904 from: eth::CrossAddress,960 token_id: uint256,905 token_id: uint256,961 ) -> Result<void> {906 ) -> Result<void> {962 let caller = T::CrossAccountId::from_eth(caller);907 let caller = T::CrossAccountId::from_eth(caller);1078 fn mint_cross(1023 fn mint_cross(1079 &mut self,1024 &mut self,1080 caller: caller,1025 caller: caller,1081 to: EthCrossAccount,1026 to: eth::CrossAddress,1082 properties: Vec<PropertyStruct>,1027 properties: Vec<eth::Property>,1083 ) -> Result<uint256> {1028 ) -> Result<uint256> {1084 let token_id = <TokensMinted<T>>::get(self.id)1029 let token_id = <TokensMinted<T>>::get(self.id)1085 .checked_add(1)1030 .checked_add(1)108910341090 let properties = properties1035 let properties = properties1091 .into_iter()1036 .into_iter()1092 .map(|PropertyStruct { key, value }| {1037 .map(eth::Property::try_into)1093 let key = <Vec<u8>>::from(key)1094 .try_into()1095 .map_err(|_| "key too large")?;10961097 let value = value.0.try_into().map_err(|_| "value too large")?;10981099 Ok(Property { key, value })1100 })1101 .collect::<Result<Vec<_>>>()?1038 .collect::<Result<Vec<_>>>()?1102 .try_into()1039 .try_into()1103 .map_err(|_| Error::Revert(alloc::format!("too many properties")))?;1040 .map_err(|_| Error::Revert(alloc::format!("too many properties")))?;pallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterbothbinary blob — no preview
pallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth42 /// @param permissions Permissions for keys.42 /// @param permissions Permissions for keys.43 /// @dev EVM selector for this function is: 0xbd92983a,43 /// @dev EVM selector for this function is: 0xbd92983a,44 /// or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])44 /// or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])45 function setTokenPropertyPermissions(Tuple61[] memory permissions) public {45 function setTokenPropertyPermissions(TokenPropertyPermission[] memory permissions) public {46 require(false, stub_error);46 require(false, stub_error);47 permissions;47 permissions;48 dummy = 0;48 dummy = 0;51 /// @notice Get permissions for token properties.51 /// @notice Get permissions for token properties.52 /// @dev EVM selector for this function is: 0xf23d7790,52 /// @dev EVM selector for this function is: 0xf23d7790,53 /// or in textual repr: tokenPropertyPermissions()53 /// or in textual repr: tokenPropertyPermissions()54 function tokenPropertyPermissions() public view returns (Tuple61[] memory) {54 function tokenPropertyPermissions() public view returns (TokenPropertyPermission[] memory) {55 require(false, stub_error);55 require(false, stub_error);56 dummy;56 dummy;57 return new Tuple61[](0);57 return new TokenPropertyPermission[](0);58 }58 }595960 // /// @notice Set token property value.60 // /// @notice Set token property value.127 }127 }128}128}129129130/// @dev Property struct130/// Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).131struct Property {131struct Property {132 string key;132 string key;133 bytes value;133 bytes value;134}134}135135136/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.136/// Ethereum representation of Token Property Permissions.137enum EthTokenPermissions {138 /// @dev Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]139 Mutable,140 /// @dev Change permission for the collection administrator. See [`up_data_structs::PropertyPermission::token_owner`]141 TokenOwner,142 /// @dev Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]143 CollectionAdmin144}145146/// @dev anonymous struct147struct Tuple61 {137struct TokenPropertyPermission {138 /// Token property key.148 string field_0;139 string key;140 /// Token property permissions.149 Tuple59[] field_1;141 PropertyPermission[] permissions;150}142}151143152/// @dev anonymous struct144/// Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) as an key and value.153struct Tuple59 {145struct PropertyPermission {146 /// TokenPermission field.154 EthTokenPermissions field_0;147 TokenPermissionField code;148 /// TokenPermission value.155 bool field_1;149 bool value;156}150}151152/// Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.153enum TokenPermissionField {154 /// Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]155 Mutable,156 /// Change permission for the collection administrator. See [`up_data_structs::PropertyPermission::token_owner`]157 TokenOwner,158 /// Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]159 CollectionAdmin160}157161158/// @title A contract that allows you to work with collections.162/// @title A contract that allows you to work with collections.159/// @dev the ERC-165 identifier for this interface is 0x81172a75163/// @dev the ERC-165 identifier for this interface is 0x2a14cfd1160contract Collection is Dummy, ERC165 {164contract Collection is Dummy, ERC165 {161 // /// Set collection property.165 // /// Set collection property.162 // ///166 // ///252 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.256 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.253 /// @dev EVM selector for this function is: 0x84a1d5a8,257 /// @dev EVM selector for this function is: 0x84a1d5a8,254 /// or in textual repr: setCollectionSponsorCross((address,uint256))258 /// or in textual repr: setCollectionSponsorCross((address,uint256))255 function setCollectionSponsorCross(EthCrossAccount memory sponsor) public {259 function setCollectionSponsorCross(CrossAddress memory sponsor) public {256 require(false, stub_error);260 require(false, stub_error);257 sponsor;261 sponsor;258 dummy = 0;262 dummy = 0;290 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.294 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.291 /// @dev EVM selector for this function is: 0x6ec0a9f1,295 /// @dev EVM selector for this function is: 0x6ec0a9f1,292 /// or in textual repr: collectionSponsor()296 /// or in textual repr: collectionSponsor()293 function collectionSponsor() public view returns (EthCrossAccount memory) {297 function collectionSponsor() public view returns (CrossAddress memory) {294 require(false, stub_error);298 require(false, stub_error);295 dummy;299 dummy;296 return EthCrossAccount(0x0000000000000000000000000000000000000000, 0);300 return CrossAddress(0x0000000000000000000000000000000000000000, 0);297 }301 }298302299 /// Get current collection limits.303 /// Get current collection limits.300 ///304 ///301 /// @return Array of tuples (byte, bool, uint256) with limits and their values. Order of limits:305 /// @return Array of collection limits302 /// "accountTokenOwnershipLimit",303 /// "sponsoredDataSize",304 /// "sponsoredDataRateLimit",305 /// "tokenLimit",306 /// "sponsorTransferTimeout",307 /// "sponsorApproveTimeout"308 /// "ownerCanTransfer",309 /// "ownerCanDestroy",310 /// "transfersEnabled"311 /// Return `false` if a limit not set.312 /// @dev EVM selector for this function is: 0xf63bc572,306 /// @dev EVM selector for this function is: 0xf63bc572,313 /// or in textual repr: collectionLimits()307 /// or in textual repr: collectionLimits()314 function collectionLimits() public view returns (Tuple35[] memory) {308 function collectionLimits() public view returns (CollectionLimit[] memory) {315 require(false, stub_error);309 require(false, stub_error);316 dummy;310 dummy;317 return new Tuple35[](0);311 return new CollectionLimit[](0);318 }312 }319313320 /// Set limits for the collection.314 /// Set limits for the collection.321 /// @dev Throws error if limit not found.315 /// @dev Throws error if limit not found.322 /// @param limit Name of the limit. Valid names:323 /// "accountTokenOwnershipLimit",324 /// "sponsoredDataSize",325 /// "sponsoredDataRateLimit",326 /// "tokenLimit",327 /// "sponsorTransferTimeout",328 /// "sponsorApproveTimeout"329 /// "ownerCanTransfer",330 /// "ownerCanDestroy",331 /// "transfersEnabled"332 /// @param status enable\disable limit. Works only with `true`.333 /// @param value Value of the limit.316 /// @param limit Some limit.334 /// @dev EVM selector for this function is: 0x88150bd0,317 /// @dev EVM selector for this function is: 0x2316ee74,335 /// or in textual repr: setCollectionLimit(uint8,bool,uint256)318 /// or in textual repr: setCollectionLimit((uint8,(bool,uint256)))336 function setCollectionLimit(319 function setCollectionLimit(CollectionLimit memory limit) public {337 CollectionLimits limit,338 bool status,339 uint256 value340 ) public {341 require(false, stub_error);320 require(false, stub_error);342 limit;321 limit;343 status;344 value;345 dummy = 0;322 dummy = 0;346 }323 }347324358 /// @param newAdmin Cross account administrator address.335 /// @param newAdmin Cross account administrator address.359 /// @dev EVM selector for this function is: 0x859aa7d6,336 /// @dev EVM selector for this function is: 0x859aa7d6,360 /// or in textual repr: addCollectionAdminCross((address,uint256))337 /// or in textual repr: addCollectionAdminCross((address,uint256))361 function addCollectionAdminCross(EthCrossAccount memory newAdmin) public {338 function addCollectionAdminCross(CrossAddress memory newAdmin) public {362 require(false, stub_error);339 require(false, stub_error);363 newAdmin;340 newAdmin;364 dummy = 0;341 dummy = 0;368 /// @param admin Cross account administrator address.345 /// @param admin Cross account administrator address.369 /// @dev EVM selector for this function is: 0x6c0cd173,346 /// @dev EVM selector for this function is: 0x6c0cd173,370 /// or in textual repr: removeCollectionAdminCross((address,uint256))347 /// or in textual repr: removeCollectionAdminCross((address,uint256))371 function removeCollectionAdminCross(EthCrossAccount memory admin) public {348 function removeCollectionAdminCross(CrossAddress memory admin) public {372 require(false, stub_error);349 require(false, stub_error);373 admin;350 admin;374 dummy = 0;351 dummy = 0;422 /// Returns nesting for a collection399 /// Returns nesting for a collection423 /// @dev EVM selector for this function is: 0x22d25bfe,400 /// @dev EVM selector for this function is: 0x22d25bfe,424 /// or in textual repr: collectionNestingRestrictedCollectionIds()401 /// or in textual repr: collectionNestingRestrictedCollectionIds()425 function collectionNestingRestrictedCollectionIds() public view returns (Tuple41 memory) {402 function collectionNestingRestrictedCollectionIds() public view returns (CollectionNesting memory) {426 require(false, stub_error);403 require(false, stub_error);427 dummy;404 dummy;428 return Tuple41(false, new uint256[](0));405 return CollectionNesting(false, new uint256[](0));429 }406 }430407431 /// Returns permissions for a collection408 /// Returns permissions for a collection432 /// @dev EVM selector for this function is: 0x5b2eaf4b,409 /// @dev EVM selector for this function is: 0x5b2eaf4b,433 /// or in textual repr: collectionNestingPermissions()410 /// or in textual repr: collectionNestingPermissions()434 function collectionNestingPermissions() public view returns (Tuple44[] memory) {411 function collectionNestingPermissions() public view returns (CollectionNestingPermission[] memory) {435 require(false, stub_error);412 require(false, stub_error);436 dummy;413 dummy;437 return new Tuple44[](0);414 return new CollectionNestingPermission[](0);438 }415 }439416440 /// Set the collection access method.417 /// Set the collection access method.454 /// @param user User address to check.431 /// @param user User address to check.455 /// @dev EVM selector for this function is: 0x91b6df49,432 /// @dev EVM selector for this function is: 0x91b6df49,456 /// or in textual repr: allowlistedCross((address,uint256))433 /// or in textual repr: allowlistedCross((address,uint256))457 function allowlistedCross(EthCrossAccount memory user) public view returns (bool) {434 function allowlistedCross(CrossAddress memory user) public view returns (bool) {458 require(false, stub_error);435 require(false, stub_error);459 user;436 user;460 dummy;437 dummy;477 /// @param user User cross account address.454 /// @param user User cross account address.478 /// @dev EVM selector for this function is: 0xa0184a3a,455 /// @dev EVM selector for this function is: 0xa0184a3a,479 /// or in textual repr: addToCollectionAllowListCross((address,uint256))456 /// or in textual repr: addToCollectionAllowListCross((address,uint256))480 function addToCollectionAllowListCross(EthCrossAccount memory user) public {457 function addToCollectionAllowListCross(CrossAddress memory user) public {481 require(false, stub_error);458 require(false, stub_error);482 user;459 user;483 dummy = 0;460 dummy = 0;499 /// @param user User cross account address.476 /// @param user User cross account address.500 /// @dev EVM selector for this function is: 0x09ba452a,477 /// @dev EVM selector for this function is: 0x09ba452a,501 /// or in textual repr: removeFromCollectionAllowListCross((address,uint256))478 /// or in textual repr: removeFromCollectionAllowListCross((address,uint256))502 function removeFromCollectionAllowListCross(EthCrossAccount memory user) public {479 function removeFromCollectionAllowListCross(CrossAddress memory user) public {503 require(false, stub_error);480 require(false, stub_error);504 user;481 user;505 dummy = 0;482 dummy = 0;535 /// @return "true" if account is the owner or admin512 /// @return "true" if account is the owner or admin536 /// @dev EVM selector for this function is: 0x3e75a905,513 /// @dev EVM selector for this function is: 0x3e75a905,537 /// or in textual repr: isOwnerOrAdminCross((address,uint256))514 /// or in textual repr: isOwnerOrAdminCross((address,uint256))538 function isOwnerOrAdminCross(EthCrossAccount memory user) public view returns (bool) {515 function isOwnerOrAdminCross(CrossAddress memory user) public view returns (bool) {539 require(false, stub_error);516 require(false, stub_error);540 user;517 user;541 dummy;518 dummy;559 /// If address is canonical then substrate mirror is zero and vice versa.536 /// If address is canonical then substrate mirror is zero and vice versa.560 /// @dev EVM selector for this function is: 0xdf727d3b,537 /// @dev EVM selector for this function is: 0xdf727d3b,561 /// or in textual repr: collectionOwner()538 /// or in textual repr: collectionOwner()562 function collectionOwner() public view returns (EthCrossAccount memory) {539 function collectionOwner() public view returns (CrossAddress memory) {563 require(false, stub_error);540 require(false, stub_error);564 dummy;541 dummy;565 return EthCrossAccount(0x0000000000000000000000000000000000000000, 0);542 return CrossAddress(0x0000000000000000000000000000000000000000, 0);566 }543 }567544568 // /// Changes collection owner to another account545 // /// Changes collection owner to another account583 /// If address is canonical then substrate mirror is zero and vice versa.560 /// If address is canonical then substrate mirror is zero and vice versa.584 /// @dev EVM selector for this function is: 0x5813216b,561 /// @dev EVM selector for this function is: 0x5813216b,585 /// or in textual repr: collectionAdmins()562 /// or in textual repr: collectionAdmins()586 function collectionAdmins() public view returns (EthCrossAccount[] memory) {563 function collectionAdmins() public view returns (CrossAddress[] memory) {587 require(false, stub_error);564 require(false, stub_error);588 dummy;565 dummy;589 return new EthCrossAccount[](0);566 return new CrossAddress[](0);590 }567 }591568592 /// Changes collection owner to another account569 /// Changes collection owner to another account595 /// @param newOwner new owner cross account572 /// @param newOwner new owner cross account596 /// @dev EVM selector for this function is: 0x6496c497,573 /// @dev EVM selector for this function is: 0x6496c497,597 /// or in textual repr: changeCollectionOwnerCross((address,uint256))574 /// or in textual repr: changeCollectionOwnerCross((address,uint256))598 function changeCollectionOwnerCross(EthCrossAccount memory newOwner) public {575 function changeCollectionOwnerCross(CrossAddress memory newOwner) public {599 require(false, stub_error);576 require(false, stub_error);600 newOwner;577 newOwner;601 dummy = 0;578 dummy = 0;602 }579 }603}580}604581605/// @dev Cross account struct582/// Cross account struct606struct EthCrossAccount {583struct CrossAddress {607 address eth;584 address eth;608 uint256 sub;585 uint256 sub;609}586}610587588/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.589struct CollectionNestingPermission {590 CollectionPermissionField field;591 bool value;592}593594/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.611enum CollectionPermissions {595enum CollectionPermissionField {612 CollectionAdmin,596 /// Owner of token can nest tokens under it.613 TokenOwner597 TokenOwner,598 /// Admin of token collection can nest tokens under token.599 CollectionAdmin614}600}615601616/// @dev anonymous struct602/// Nested collections.617struct Tuple44 {603struct CollectionNesting {618 CollectionPermissions field_0;604 bool token_owner;619 bool field_1;605 uint256[] ids;620}606}621607622/// @dev anonymous struct608/// [`CollectionLimits`](up_data_structs::CollectionLimits) field representation for EVM.609struct CollectionLimit {610 CollectionLimitField field;611 OptionUint value;612}613614/// Ethereum representation of Optional value with uint256.623struct Tuple41 {615struct OptionUint {624 bool field_0;616 bool status;625 uint256[] field_1;617 uint256 value;626}618}627619628/// @dev [`CollectionLimits`](up_data_structs::CollectionLimits) representation for EVM.620/// [`CollectionLimits`](up_data_structs::CollectionLimits) fields representation for EVM.629enum CollectionLimits {621enum CollectionLimitField {630 /// @dev How many tokens can a user have on one account.622 /// How many tokens can a user have on one account.631 AccountTokenOwnership,623 AccountTokenOwnership,632 /// @dev How many bytes of data are available for sponsorship.624 /// How many bytes of data are available for sponsorship.633 SponsoredDataSize,625 SponsoredDataSize,634 /// @dev In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]626 /// In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]635 SponsoredDataRateLimit,627 SponsoredDataRateLimit,636 /// @dev How many tokens can be mined into this collection.628 /// How many tokens can be mined into this collection.637 TokenLimit,629 TokenLimit,638 /// @dev Timeouts for transfer sponsoring.630 /// Timeouts for transfer sponsoring.639 SponsorTransferTimeout,631 SponsorTransferTimeout,640 /// @dev Timeout for sponsoring an approval in passed blocks.632 /// Timeout for sponsoring an approval in passed blocks.641 SponsorApproveTimeout,633 SponsorApproveTimeout,642 /// @dev Whether the collection owner of the collection can send tokens (which belong to other users).634 /// Whether the collection owner of the collection can send tokens (which belong to other users).643 OwnerCanTransfer,635 OwnerCanTransfer,644 /// @dev Can the collection owner burn other people's tokens.636 /// Can the collection owner burn other people's tokens.645 OwnerCanDestroy,637 OwnerCanDestroy,646 /// @dev Is it possible to send tokens from this collection between users.638 /// Is it possible to send tokens from this collection between users.647 TransferEnabled639 TransferEnabled648}640}649650/// @dev anonymous struct651struct Tuple35 {652 CollectionLimits field_0;653 bool field_1;654 uint256 field_2;655}656641657/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension642/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension658/// @dev See https://eips.ethereum.org/EIPS/eip-721643/// @dev See https://eips.ethereum.org/EIPS/eip-721832 /// @param tokenId Id for the token.817 /// @param tokenId Id for the token.833 /// @dev EVM selector for this function is: 0x2b29dace,818 /// @dev EVM selector for this function is: 0x2b29dace,834 /// or in textual repr: crossOwnerOf(uint256)819 /// or in textual repr: crossOwnerOf(uint256)835 function crossOwnerOf(uint256 tokenId) public view returns (EthCrossAccount memory) {820 function crossOwnerOf(uint256 tokenId) public view returns (CrossAddress memory) {836 require(false, stub_error);821 require(false, stub_error);837 tokenId;822 tokenId;838 dummy;823 dummy;839 return EthCrossAccount(0x0000000000000000000000000000000000000000, 0);824 return CrossAddress(0x0000000000000000000000000000000000000000, 0);840 }825 }841826842 /// Returns the token properties.827 /// Returns the token properties.862 /// @param tokenId The NFT to approve847 /// @param tokenId The NFT to approve863 /// @dev EVM selector for this function is: 0x0ecd0ab0,848 /// @dev EVM selector for this function is: 0x0ecd0ab0,864 /// or in textual repr: approveCross((address,uint256),uint256)849 /// or in textual repr: approveCross((address,uint256),uint256)865 function approveCross(EthCrossAccount memory approved, uint256 tokenId) public {850 function approveCross(CrossAddress memory approved, uint256 tokenId) public {866 require(false, stub_error);851 require(false, stub_error);867 approved;852 approved;868 tokenId;853 tokenId;890 /// @param tokenId The NFT to transfer875 /// @param tokenId The NFT to transfer891 /// @dev EVM selector for this function is: 0x2ada85ff,876 /// @dev EVM selector for this function is: 0x2ada85ff,892 /// or in textual repr: transferCross((address,uint256),uint256)877 /// or in textual repr: transferCross((address,uint256),uint256)893 function transferCross(EthCrossAccount memory to, uint256 tokenId) public {878 function transferCross(CrossAddress memory to, uint256 tokenId) public {894 require(false, stub_error);879 require(false, stub_error);895 to;880 to;896 tokenId;881 tokenId;906 /// @dev EVM selector for this function is: 0xd5cf430b,891 /// @dev EVM selector for this function is: 0xd5cf430b,907 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)892 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)908 function transferFromCross(893 function transferFromCross(909 EthCrossAccount memory from,894 CrossAddress memory from,910 EthCrossAccount memory to,895 CrossAddress memory to,911 uint256 tokenId896 uint256 tokenId912 ) public {897 ) public {913 require(false, stub_error);898 require(false, stub_error);940 /// @param tokenId The NFT to transfer925 /// @param tokenId The NFT to transfer941 /// @dev EVM selector for this function is: 0xbb2f5a58,926 /// @dev EVM selector for this function is: 0xbb2f5a58,942 /// or in textual repr: burnFromCross((address,uint256),uint256)927 /// or in textual repr: burnFromCross((address,uint256),uint256)943 function burnFromCross(EthCrossAccount memory from, uint256 tokenId) public {928 function burnFromCross(CrossAddress memory from, uint256 tokenId) public {944 require(false, stub_error);929 require(false, stub_error);945 from;930 from;946 tokenId;931 tokenId;992 /// @return uint256 The id of the newly minted token977 /// @return uint256 The id of the newly minted token993 /// @dev EVM selector for this function is: 0xb904db03,978 /// @dev EVM selector for this function is: 0xb904db03,994 /// or in textual repr: mintCross((address,uint256),(string,bytes)[])979 /// or in textual repr: mintCross((address,uint256),(string,bytes)[])995 function mintCross(EthCrossAccount memory to, Property[] memory properties) public returns (uint256) {980 function mintCross(CrossAddress memory to, Property[] memory properties) public returns (uint256) {996 require(false, stub_error);981 require(false, stub_error);997 to;982 to;998 properties;983 properties;pallets/refungible/src/erc.rsdiffbeforeafterboth27};27};28use evm_coder::{28use evm_coder::{29 abi::AbiType, ToLog, execution::*, generate_stubgen, solidity, solidity_interface, types::*,29 abi::AbiType, ToLog, execution::*, generate_stubgen, solidity, solidity_interface, types::*,30 types::Property as PropertyStruct, weight,30 weight,31};31};32use frame_support::{BoundedBTreeMap, BoundedVec};32use frame_support::{BoundedBTreeMap, BoundedVec};33use pallet_common::{33use pallet_common::{34 CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations,34 CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations,35 Error as CommonError,35 erc::{CommonEvmHandler, CollectionCall, static_property::key},36 erc::{CommonEvmHandler, CollectionCall, static_property::key},36 eth::{EthCrossAccount, EthTokenPermissions},37 eth,37 Error as CommonError,38};38};39use pallet_evm::{account::CrossAccountId, PrecompileHandle};39use pallet_evm::{account::CrossAccountId, PrecompileHandle};40use pallet_evm_coder_substrate::{call, dispatch_to_evm};40use pallet_evm_coder_substrate::{call, dispatch_to_evm};97 fn set_token_property_permissions(97 fn set_token_property_permissions(98 &mut self,98 &mut self,99 caller: caller,99 caller: caller,100 permissions: Vec<(string, Vec<(EthTokenPermissions, bool)>)>,100 permissions: Vec<eth::TokenPropertyPermission>,101 ) -> Result<()> {101 ) -> Result<()> {102 let caller = T::CrossAccountId::from_eth(caller);102 let caller = T::CrossAccountId::from_eth(caller);103 const PERMISSIONS_FIELDS_COUNT: usize = 3;104105 let mut perms = Vec::new();106107 for (key, pp) in permissions {108 if pp.len() > PERMISSIONS_FIELDS_COUNT {109 return Err(alloc::format!(110 "Actual number of fields {} for {}, which exceeds the maximum value of {}",111 pp.len(),112 stringify!(EthTokenPermissions),113 PERMISSIONS_FIELDS_COUNT114 )115 .as_str()116 .into());117 }118119 let mut token_permission = PropertyPermission {103 let perms = eth::TokenPropertyPermission::into_property_key_permissions(permissions)?;120 mutable: false,121 collection_admin: false,122 token_owner: false,123 };124125 for (perm, value) in pp {126 match perm {127 EthTokenPermissions::Mutable => token_permission.mutable = value,128 EthTokenPermissions::TokenOwner => token_permission.token_owner = value,129 EthTokenPermissions::CollectionAdmin => {130 token_permission.collection_admin = value131 }132 }133 }134135 perms.push(PropertyKeyPermission {136 key: key.into_bytes().try_into().map_err(|_| "too long key")?,137 permission: token_permission,138 });139 }140104141 <Pallet<T>>::set_token_property_permissions(self, &caller, perms)105 <Pallet<T>>::set_token_property_permissions(self, &caller, perms)142 .map_err(dispatch_to_evm::<T>)106 .map_err(dispatch_to_evm::<T>)143 }107 }144108145 /// @notice Get permissions for token properties.109 /// @notice Get permissions for token properties.146 fn token_property_permissions(110 fn token_property_permissions(&self) -> Result<Vec<eth::TokenPropertyPermission>> {147 &self,148 ) -> Result<Vec<(string, Vec<(EthTokenPermissions, bool)>)>> {149 let perms = <Pallet<T>>::token_property_permission(self.id);111 let perms = <Pallet<T>>::token_property_permission(self.id);150 Ok(perms112 Ok(perms151 .into_iter()113 .into_iter()152 .map(|(key, pp)| {114 .map(eth::TokenPropertyPermission::from)153 let key = string::from_utf8(key.into_inner()).expect("Stored key must be valid");154 let pp = vec![155 (EthTokenPermissions::Mutable, pp.mutable),156 (EthTokenPermissions::TokenOwner, pp.token_owner),157 (EthTokenPermissions::CollectionAdmin, pp.collection_admin),158 ];159 (key, pp)160 })161 .collect())115 .collect())162 }116 }163117205 &mut self,159 &mut self,206 caller: caller,160 caller: caller,207 token_id: uint256,161 token_id: uint256,208 properties: Vec<PropertyStruct>,162 properties: Vec<eth::Property>,209 ) -> Result<()> {163 ) -> Result<()> {210 let caller = T::CrossAccountId::from_eth(caller);164 let caller = T::CrossAccountId::from_eth(caller);211 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;165 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;216170217 let properties = properties171 let properties = properties218 .into_iter()172 .into_iter()219 .map(|PropertyStruct { key, value }| {173 .map(eth::Property::try_into)220 let key = <Vec<u8>>::from(key)221 .try_into()222 .map_err(|_| "key too large")?;223224 let value = value.0.try_into().map_err(|_| "value too large")?;225226 Ok(Property { key, value })227 })228 .collect::<Result<Vec<_>>>()?;174 .collect::<Result<Vec<_>>>()?;229175230 <Pallet<T>>::set_token_properties(176 <Pallet<T>>::set_token_properties(839 /// Returns the owner (in cross format) of the token.785 /// Returns the owner (in cross format) of the token.840 ///786 ///841 /// @param tokenId Id for the token.787 /// @param tokenId Id for the token.842 fn cross_owner_of(&self, token_id: uint256) -> Result<EthCrossAccount> {788 fn cross_owner_of(&self, token_id: uint256) -> Result<eth::CrossAddress> {843 Self::token_owner(&self, token_id.try_into()?)789 Self::token_owner(&self, token_id.try_into()?)844 .map(|o| EthCrossAccount::from_sub_cross_account::<T>(&o))790 .map(|o| eth::CrossAddress::from_sub_cross_account::<T>(&o))845 .ok_or(Error::Revert("key too large".into()))791 .ok_or(Error::Revert("key too large".into()))846 }792 }847793850 /// @param tokenId Id for the token.796 /// @param tokenId Id for the token.851 /// @param keys Properties keys. Empty keys for all propertyes.797 /// @param keys Properties keys. Empty keys for all propertyes.852 /// @return Vector of properties key/value pairs.798 /// @return Vector of properties key/value pairs.853 fn properties(&self, token_id: uint256, keys: Vec<string>) -> Result<Vec<PropertyStruct>> {799 fn properties(&self, token_id: uint256, keys: Vec<string>) -> Result<Vec<eth::Property>> {854 let keys = keys800 let keys = keys855 .into_iter()801 .into_iter()856 .map(|key| {802 .map(|key| {866 if keys.is_empty() { None } else { Some(keys) },812 if keys.is_empty() { None } else { Some(keys) },867 )813 )868 .into_iter()814 .into_iter()869 .map(|p| {815 .map(eth::Property::try_from)870 let key = string::from_utf8(p.key.to_vec())871 .map_err(|e| Error::Revert(alloc::format!("{}", e)))?;872 let value = bytes(p.value.to_vec());873 Ok(PropertyStruct { key, value })874 })875 .collect::<Result<Vec<_>>>()816 .collect::<Result<Vec<_>>>()876 }817 }877 /// @notice Transfer ownership of an RFT818 /// @notice Transfer ownership of an RFT907 fn transfer_cross(848 fn transfer_cross(908 &mut self,849 &mut self,909 caller: caller,850 caller: caller,910 to: EthCrossAccount,851 to: eth::CrossAddress,911 token_id: uint256,852 token_id: uint256,912 ) -> Result<void> {853 ) -> Result<void> {913 let caller = T::CrossAccountId::from_eth(caller);854 let caller = T::CrossAccountId::from_eth(caller);935 fn transfer_from_cross(876 fn transfer_from_cross(936 &mut self,877 &mut self,937 caller: caller,878 caller: caller,938 from: EthCrossAccount,879 from: eth::CrossAddress,939 to: EthCrossAccount,880 to: eth::CrossAddress,940 token_id: uint256,881 token_id: uint256,941 ) -> Result<void> {882 ) -> Result<void> {942 let caller = T::CrossAccountId::from_eth(caller);883 let caller = T::CrossAccountId::from_eth(caller);991 fn burn_from_cross(932 fn burn_from_cross(992 &mut self,933 &mut self,993 caller: caller,934 caller: caller,994 from: EthCrossAccount,935 from: eth::CrossAddress,995 token_id: uint256,936 token_id: uint256,996 ) -> Result<void> {937 ) -> Result<void> {997 let caller = T::CrossAccountId::from_eth(caller);938 let caller = T::CrossAccountId::from_eth(caller);1128 fn mint_cross(1069 fn mint_cross(1129 &mut self,1070 &mut self,1130 caller: caller,1071 caller: caller,1131 to: EthCrossAccount,1072 to: eth::CrossAddress,1132 properties: Vec<PropertyStruct>,1073 properties: Vec<eth::Property>,1133 ) -> Result<uint256> {1074 ) -> Result<uint256> {1134 let token_id = <TokensMinted<T>>::get(self.id)1075 let token_id = <TokensMinted<T>>::get(self.id)1135 .checked_add(1)1076 .checked_add(1)113910801140 let properties = properties1081 let properties = properties1141 .into_iter()1082 .into_iter()1142 .map(|PropertyStruct { key, value }| {1083 .map(eth::Property::try_into)1143 let key = <Vec<u8>>::from(key)1144 .try_into()1145 .map_err(|_| "key too large")?;11461147 let value = value.0.try_into().map_err(|_| "value too large")?;11481149 Ok(Property { key, value })1150 })1151 .collect::<Result<Vec<_>>>()?1084 .collect::<Result<Vec<_>>>()?1152 .try_into()1085 .try_into()1153 .map_err(|_| Error::Revert(alloc::format!("too many properties")))?;1086 .map_err(|_| Error::Revert(alloc::format!("too many properties")))?;pallets/refungible/src/erc_token.rsdiffbeforeafterboth30use pallet_common::{30use pallet_common::{31 CommonWeightInfo,31 CommonWeightInfo,32 erc::{CommonEvmHandler, PrecompileResult},32 erc::{CommonEvmHandler, PrecompileResult},33 eth::{collection_id_to_address, EthCrossAccount},33 eth::collection_id_to_address,34};34};35use pallet_evm::{account::CrossAccountId, PrecompileHandle};35use pallet_evm::{account::CrossAccountId, PrecompileHandle};36use pallet_evm_coder_substrate::{call, dispatch_to_evm, WithRecorder};36use pallet_evm_coder_substrate::{call, dispatch_to_evm, WithRecorder};224 fn burn_from_cross(224 fn burn_from_cross(225 &mut self,225 &mut self,226 caller: caller,226 caller: caller,227 from: EthCrossAccount,227 from: pallet_common::eth::CrossAddress,228 amount: uint256,228 amount: uint256,229 ) -> Result<bool> {229 ) -> Result<bool> {230 let caller = T::CrossAccountId::from_eth(caller);230 let caller = T::CrossAccountId::from_eth(caller);250 fn approve_cross(250 fn approve_cross(251 &mut self,251 &mut self,252 caller: caller,252 caller: caller,253 spender: EthCrossAccount,253 spender: pallet_common::eth::CrossAddress,254 amount: uint256,254 amount: uint256,255 ) -> Result<bool> {255 ) -> Result<bool> {256 let caller = T::CrossAccountId::from_eth(caller);256 let caller = T::CrossAccountId::from_eth(caller);280 fn transfer_cross(280 fn transfer_cross(281 &mut self,281 &mut self,282 caller: caller,282 caller: caller,283 to: EthCrossAccount,283 to: pallet_common::eth::CrossAddress,284 amount: uint256,284 amount: uint256,285 ) -> Result<bool> {285 ) -> Result<bool> {286 let caller = T::CrossAccountId::from_eth(caller);286 let caller = T::CrossAccountId::from_eth(caller);303 fn transfer_from_cross(303 fn transfer_from_cross(304 &mut self,304 &mut self,305 caller: caller,305 caller: caller,306 from: EthCrossAccount,306 from: pallet_common::eth::CrossAddress,307 to: EthCrossAccount,307 to: pallet_common::eth::CrossAddress,308 amount: uint256,308 amount: uint256,309 ) -> Result<bool> {309 ) -> Result<bool> {310 let caller = T::CrossAccountId::from_eth(caller);310 let caller = T::CrossAccountId::from_eth(caller);pallets/refungible/src/lib.rsdiffbeforeafterboth929293use codec::{Encode, Decode, MaxEncodedLen};93use codec::{Encode, Decode, MaxEncodedLen};94use core::ops::Deref;94use core::ops::Deref;95use derivative::Derivative;96use evm_coder::ToLog;95use evm_coder::ToLog;97use frame_support::{96use frame_support::{BoundedVec, ensure, fail, storage::with_transaction, transactional};98 BoundedBTreeMap, BoundedVec, ensure, fail, storage::with_transaction, transactional,99 pallet_prelude::ConstU32,100};101use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};97use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};102use pallet_evm_coder_substrate::WithRecorder;98use pallet_evm_coder_substrate::WithRecorder;110use sp_runtime::{ArithmeticError, DispatchError, DispatchResult, TransactionOutcome};106use sp_runtime::{ArithmeticError, DispatchError, DispatchResult, TransactionOutcome};111use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};107use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};112use up_data_structs::{108use up_data_structs::{113 AccessMode, budget::Budget, CollectionId, CollectionFlags, CollectionPropertiesVec,109 AccessMode, budget::Budget, CollectionId, CollectionFlags, CreateCollectionData,114 CreateCollectionData, CustomDataLimit, mapping::TokenAddressMapping, MAX_ITEMS_PER_BATCH,110 CustomDataLimit, mapping::TokenAddressMapping, MAX_REFUNGIBLE_PIECES, Property, PropertyKey,115 MAX_REFUNGIBLE_PIECES, Property, PropertyKey, PropertyKeyPermission, PropertyPermission,111 PropertyKeyPermission, PropertyPermission, PropertyScope, PropertyValue, TokenId,116 PropertyScope, PropertyValue, TokenId, TrySetProperty, PropertiesPermissionMap,112 TrySetProperty, PropertiesPermissionMap, CreateRefungibleExMultipleOwners,117 CreateRefungibleExMultipleOwners,pallets/refungible/src/stubs/UniqueRefungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth42 /// @param permissions Permissions for keys.42 /// @param permissions Permissions for keys.43 /// @dev EVM selector for this function is: 0xbd92983a,43 /// @dev EVM selector for this function is: 0xbd92983a,44 /// or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])44 /// or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])45 function setTokenPropertyPermissions(Tuple60[] memory permissions) public {45 function setTokenPropertyPermissions(TokenPropertyPermission[] memory permissions) public {46 require(false, stub_error);46 require(false, stub_error);47 permissions;47 permissions;48 dummy = 0;48 dummy = 0;51 /// @notice Get permissions for token properties.51 /// @notice Get permissions for token properties.52 /// @dev EVM selector for this function is: 0xf23d7790,52 /// @dev EVM selector for this function is: 0xf23d7790,53 /// or in textual repr: tokenPropertyPermissions()53 /// or in textual repr: tokenPropertyPermissions()54 function tokenPropertyPermissions() public view returns (Tuple60[] memory) {54 function tokenPropertyPermissions() public view returns (TokenPropertyPermission[] memory) {55 require(false, stub_error);55 require(false, stub_error);56 dummy;56 dummy;57 return new Tuple60[](0);57 return new TokenPropertyPermission[](0);58 }58 }595960 // /// @notice Set token property value.60 // /// @notice Set token property value.127 }127 }128}128}129129130/// @dev Property struct130/// Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).131struct Property {131struct Property {132 string key;132 string key;133 bytes value;133 bytes value;134}134}135135136/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.136/// Ethereum representation of Token Property Permissions.137enum EthTokenPermissions {138 /// @dev Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]139 Mutable,140 /// @dev Change permission for the collection administrator. See [`up_data_structs::PropertyPermission::token_owner`]141 TokenOwner,142 /// @dev Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]143 CollectionAdmin144}145146/// @dev anonymous struct147struct Tuple60 {137struct TokenPropertyPermission {138 /// Token property key.148 string field_0;139 string key;140 /// Token property permissions.149 Tuple58[] field_1;141 PropertyPermission[] permissions;150}142}151143152/// @dev anonymous struct144/// Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) as an key and value.153struct Tuple58 {145struct PropertyPermission {146 /// TokenPermission field.154 EthTokenPermissions field_0;147 TokenPermissionField code;148 /// TokenPermission value.155 bool field_1;149 bool value;156}150}151152/// Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.153enum TokenPermissionField {154 /// Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]155 Mutable,156 /// Change permission for the collection administrator. See [`up_data_structs::PropertyPermission::token_owner`]157 TokenOwner,158 /// Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]159 CollectionAdmin160}157161158/// @title A contract that allows you to work with collections.162/// @title A contract that allows you to work with collections.159/// @dev the ERC-165 identifier for this interface is 0x81172a75163/// @dev the ERC-165 identifier for this interface is 0x2a14cfd1160contract Collection is Dummy, ERC165 {164contract Collection is Dummy, ERC165 {161 // /// Set collection property.165 // /// Set collection property.162 // ///166 // ///252 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.256 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.253 /// @dev EVM selector for this function is: 0x84a1d5a8,257 /// @dev EVM selector for this function is: 0x84a1d5a8,254 /// or in textual repr: setCollectionSponsorCross((address,uint256))258 /// or in textual repr: setCollectionSponsorCross((address,uint256))255 function setCollectionSponsorCross(EthCrossAccount memory sponsor) public {259 function setCollectionSponsorCross(CrossAddress memory sponsor) public {256 require(false, stub_error);260 require(false, stub_error);257 sponsor;261 sponsor;258 dummy = 0;262 dummy = 0;290 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.294 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.291 /// @dev EVM selector for this function is: 0x6ec0a9f1,295 /// @dev EVM selector for this function is: 0x6ec0a9f1,292 /// or in textual repr: collectionSponsor()296 /// or in textual repr: collectionSponsor()293 function collectionSponsor() public view returns (EthCrossAccount memory) {297 function collectionSponsor() public view returns (CrossAddress memory) {294 require(false, stub_error);298 require(false, stub_error);295 dummy;299 dummy;296 return EthCrossAccount(0x0000000000000000000000000000000000000000, 0);300 return CrossAddress(0x0000000000000000000000000000000000000000, 0);297 }301 }298302299 /// Get current collection limits.303 /// Get current collection limits.300 ///304 ///301 /// @return Array of tuples (byte, bool, uint256) with limits and their values. Order of limits:305 /// @return Array of collection limits302 /// "accountTokenOwnershipLimit",303 /// "sponsoredDataSize",304 /// "sponsoredDataRateLimit",305 /// "tokenLimit",306 /// "sponsorTransferTimeout",307 /// "sponsorApproveTimeout"308 /// "ownerCanTransfer",309 /// "ownerCanDestroy",310 /// "transfersEnabled"311 /// Return `false` if a limit not set.312 /// @dev EVM selector for this function is: 0xf63bc572,306 /// @dev EVM selector for this function is: 0xf63bc572,313 /// or in textual repr: collectionLimits()307 /// or in textual repr: collectionLimits()314 function collectionLimits() public view returns (Tuple34[] memory) {308 function collectionLimits() public view returns (CollectionLimit[] memory) {315 require(false, stub_error);309 require(false, stub_error);316 dummy;310 dummy;317 return new Tuple34[](0);311 return new CollectionLimit[](0);318 }312 }319313320 /// Set limits for the collection.314 /// Set limits for the collection.321 /// @dev Throws error if limit not found.315 /// @dev Throws error if limit not found.322 /// @param limit Name of the limit. Valid names:323 /// "accountTokenOwnershipLimit",324 /// "sponsoredDataSize",325 /// "sponsoredDataRateLimit",326 /// "tokenLimit",327 /// "sponsorTransferTimeout",328 /// "sponsorApproveTimeout"329 /// "ownerCanTransfer",330 /// "ownerCanDestroy",331 /// "transfersEnabled"332 /// @param status enable\disable limit. Works only with `true`.333 /// @param value Value of the limit.316 /// @param limit Some limit.334 /// @dev EVM selector for this function is: 0x88150bd0,317 /// @dev EVM selector for this function is: 0x2316ee74,335 /// or in textual repr: setCollectionLimit(uint8,bool,uint256)318 /// or in textual repr: setCollectionLimit((uint8,(bool,uint256)))336 function setCollectionLimit(319 function setCollectionLimit(CollectionLimit memory limit) public {337 CollectionLimits limit,338 bool status,339 uint256 value340 ) public {341 require(false, stub_error);320 require(false, stub_error);342 limit;321 limit;343 status;344 value;345 dummy = 0;322 dummy = 0;346 }323 }347324358 /// @param newAdmin Cross account administrator address.335 /// @param newAdmin Cross account administrator address.359 /// @dev EVM selector for this function is: 0x859aa7d6,336 /// @dev EVM selector for this function is: 0x859aa7d6,360 /// or in textual repr: addCollectionAdminCross((address,uint256))337 /// or in textual repr: addCollectionAdminCross((address,uint256))361 function addCollectionAdminCross(EthCrossAccount memory newAdmin) public {338 function addCollectionAdminCross(CrossAddress memory newAdmin) public {362 require(false, stub_error);339 require(false, stub_error);363 newAdmin;340 newAdmin;364 dummy = 0;341 dummy = 0;368 /// @param admin Cross account administrator address.345 /// @param admin Cross account administrator address.369 /// @dev EVM selector for this function is: 0x6c0cd173,346 /// @dev EVM selector for this function is: 0x6c0cd173,370 /// or in textual repr: removeCollectionAdminCross((address,uint256))347 /// or in textual repr: removeCollectionAdminCross((address,uint256))371 function removeCollectionAdminCross(EthCrossAccount memory admin) public {348 function removeCollectionAdminCross(CrossAddress memory admin) public {372 require(false, stub_error);349 require(false, stub_error);373 admin;350 admin;374 dummy = 0;351 dummy = 0;422 /// Returns nesting for a collection399 /// Returns nesting for a collection423 /// @dev EVM selector for this function is: 0x22d25bfe,400 /// @dev EVM selector for this function is: 0x22d25bfe,424 /// or in textual repr: collectionNestingRestrictedCollectionIds()401 /// or in textual repr: collectionNestingRestrictedCollectionIds()425 function collectionNestingRestrictedCollectionIds() public view returns (Tuple40 memory) {402 function collectionNestingRestrictedCollectionIds() public view returns (CollectionNesting memory) {426 require(false, stub_error);403 require(false, stub_error);427 dummy;404 dummy;428 return Tuple40(false, new uint256[](0));405 return CollectionNesting(false, new uint256[](0));429 }406 }430407431 /// Returns permissions for a collection408 /// Returns permissions for a collection432 /// @dev EVM selector for this function is: 0x5b2eaf4b,409 /// @dev EVM selector for this function is: 0x5b2eaf4b,433 /// or in textual repr: collectionNestingPermissions()410 /// or in textual repr: collectionNestingPermissions()434 function collectionNestingPermissions() public view returns (Tuple43[] memory) {411 function collectionNestingPermissions() public view returns (CollectionNestingPermission[] memory) {435 require(false, stub_error);412 require(false, stub_error);436 dummy;413 dummy;437 return new Tuple43[](0);414 return new CollectionNestingPermission[](0);438 }415 }439416440 /// Set the collection access method.417 /// Set the collection access method.454 /// @param user User address to check.431 /// @param user User address to check.455 /// @dev EVM selector for this function is: 0x91b6df49,432 /// @dev EVM selector for this function is: 0x91b6df49,456 /// or in textual repr: allowlistedCross((address,uint256))433 /// or in textual repr: allowlistedCross((address,uint256))457 function allowlistedCross(EthCrossAccount memory user) public view returns (bool) {434 function allowlistedCross(CrossAddress memory user) public view returns (bool) {458 require(false, stub_error);435 require(false, stub_error);459 user;436 user;460 dummy;437 dummy;477 /// @param user User cross account address.454 /// @param user User cross account address.478 /// @dev EVM selector for this function is: 0xa0184a3a,455 /// @dev EVM selector for this function is: 0xa0184a3a,479 /// or in textual repr: addToCollectionAllowListCross((address,uint256))456 /// or in textual repr: addToCollectionAllowListCross((address,uint256))480 function addToCollectionAllowListCross(EthCrossAccount memory user) public {457 function addToCollectionAllowListCross(CrossAddress memory user) public {481 require(false, stub_error);458 require(false, stub_error);482 user;459 user;483 dummy = 0;460 dummy = 0;499 /// @param user User cross account address.476 /// @param user User cross account address.500 /// @dev EVM selector for this function is: 0x09ba452a,477 /// @dev EVM selector for this function is: 0x09ba452a,501 /// or in textual repr: removeFromCollectionAllowListCross((address,uint256))478 /// or in textual repr: removeFromCollectionAllowListCross((address,uint256))502 function removeFromCollectionAllowListCross(EthCrossAccount memory user) public {479 function removeFromCollectionAllowListCross(CrossAddress memory user) public {503 require(false, stub_error);480 require(false, stub_error);504 user;481 user;505 dummy = 0;482 dummy = 0;535 /// @return "true" if account is the owner or admin512 /// @return "true" if account is the owner or admin536 /// @dev EVM selector for this function is: 0x3e75a905,513 /// @dev EVM selector for this function is: 0x3e75a905,537 /// or in textual repr: isOwnerOrAdminCross((address,uint256))514 /// or in textual repr: isOwnerOrAdminCross((address,uint256))538 function isOwnerOrAdminCross(EthCrossAccount memory user) public view returns (bool) {515 function isOwnerOrAdminCross(CrossAddress memory user) public view returns (bool) {539 require(false, stub_error);516 require(false, stub_error);540 user;517 user;541 dummy;518 dummy;559 /// If address is canonical then substrate mirror is zero and vice versa.536 /// If address is canonical then substrate mirror is zero and vice versa.560 /// @dev EVM selector for this function is: 0xdf727d3b,537 /// @dev EVM selector for this function is: 0xdf727d3b,561 /// or in textual repr: collectionOwner()538 /// or in textual repr: collectionOwner()562 function collectionOwner() public view returns (EthCrossAccount memory) {539 function collectionOwner() public view returns (CrossAddress memory) {563 require(false, stub_error);540 require(false, stub_error);564 dummy;541 dummy;565 return EthCrossAccount(0x0000000000000000000000000000000000000000, 0);542 return CrossAddress(0x0000000000000000000000000000000000000000, 0);566 }543 }567544568 // /// Changes collection owner to another account545 // /// Changes collection owner to another account583 /// If address is canonical then substrate mirror is zero and vice versa.560 /// If address is canonical then substrate mirror is zero and vice versa.584 /// @dev EVM selector for this function is: 0x5813216b,561 /// @dev EVM selector for this function is: 0x5813216b,585 /// or in textual repr: collectionAdmins()562 /// or in textual repr: collectionAdmins()586 function collectionAdmins() public view returns (EthCrossAccount[] memory) {563 function collectionAdmins() public view returns (CrossAddress[] memory) {587 require(false, stub_error);564 require(false, stub_error);588 dummy;565 dummy;589 return new EthCrossAccount[](0);566 return new CrossAddress[](0);590 }567 }591568592 /// Changes collection owner to another account569 /// Changes collection owner to another account595 /// @param newOwner new owner cross account572 /// @param newOwner new owner cross account596 /// @dev EVM selector for this function is: 0x6496c497,573 /// @dev EVM selector for this function is: 0x6496c497,597 /// or in textual repr: changeCollectionOwnerCross((address,uint256))574 /// or in textual repr: changeCollectionOwnerCross((address,uint256))598 function changeCollectionOwnerCross(EthCrossAccount memory newOwner) public {575 function changeCollectionOwnerCross(CrossAddress memory newOwner) public {599 require(false, stub_error);576 require(false, stub_error);600 newOwner;577 newOwner;601 dummy = 0;578 dummy = 0;602 }579 }603}580}604581605/// @dev Cross account struct582/// Cross account struct606struct EthCrossAccount {583struct CrossAddress {607 address eth;584 address eth;608 uint256 sub;585 uint256 sub;609}586}610587588/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.589struct CollectionNestingPermission {590 CollectionPermissionField field;591 bool value;592}593594/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.611enum CollectionPermissions {595enum CollectionPermissionField {612 CollectionAdmin,596 /// Owner of token can nest tokens under it.613 TokenOwner597 TokenOwner,598 /// Admin of token collection can nest tokens under token.599 CollectionAdmin614}600}615601616/// @dev anonymous struct602/// Nested collections.617struct Tuple43 {603struct CollectionNesting {618 CollectionPermissions field_0;604 bool token_owner;619 bool field_1;605 uint256[] ids;620}606}621607622/// @dev anonymous struct608/// [`CollectionLimits`](up_data_structs::CollectionLimits) field representation for EVM.609struct CollectionLimit {610 CollectionLimitField field;611 OptionUint value;612}613614/// Ethereum representation of Optional value with uint256.623struct Tuple40 {615struct OptionUint {624 bool field_0;616 bool status;625 uint256[] field_1;617 uint256 value;626}618}627619628/// @dev [`CollectionLimits`](up_data_structs::CollectionLimits) representation for EVM.620/// [`CollectionLimits`](up_data_structs::CollectionLimits) fields representation for EVM.629enum CollectionLimits {621enum CollectionLimitField {630 /// @dev How many tokens can a user have on one account.622 /// How many tokens can a user have on one account.631 AccountTokenOwnership,623 AccountTokenOwnership,632 /// @dev How many bytes of data are available for sponsorship.624 /// How many bytes of data are available for sponsorship.633 SponsoredDataSize,625 SponsoredDataSize,634 /// @dev In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]626 /// In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]635 SponsoredDataRateLimit,627 SponsoredDataRateLimit,636 /// @dev How many tokens can be mined into this collection.628 /// How many tokens can be mined into this collection.637 TokenLimit,629 TokenLimit,638 /// @dev Timeouts for transfer sponsoring.630 /// Timeouts for transfer sponsoring.639 SponsorTransferTimeout,631 SponsorTransferTimeout,640 /// @dev Timeout for sponsoring an approval in passed blocks.632 /// Timeout for sponsoring an approval in passed blocks.641 SponsorApproveTimeout,633 SponsorApproveTimeout,642 /// @dev Whether the collection owner of the collection can send tokens (which belong to other users).634 /// Whether the collection owner of the collection can send tokens (which belong to other users).643 OwnerCanTransfer,635 OwnerCanTransfer,644 /// @dev Can the collection owner burn other people's tokens.636 /// Can the collection owner burn other people's tokens.645 OwnerCanDestroy,637 OwnerCanDestroy,646 /// @dev Is it possible to send tokens from this collection between users.638 /// Is it possible to send tokens from this collection between users.647 TransferEnabled639 TransferEnabled648}640}649650/// @dev anonymous struct651struct Tuple34 {652 CollectionLimits field_0;653 bool field_1;654 uint256 field_2;655}656641657/// @dev the ERC-165 identifier for this interface is 0x5b5e139f642/// @dev the ERC-165 identifier for this interface is 0x5b5e139f658contract ERC721Metadata is Dummy, ERC165 {643contract ERC721Metadata is Dummy, ERC165 {830 /// @param tokenId Id for the token.815 /// @param tokenId Id for the token.831 /// @dev EVM selector for this function is: 0x2b29dace,816 /// @dev EVM selector for this function is: 0x2b29dace,832 /// or in textual repr: crossOwnerOf(uint256)817 /// or in textual repr: crossOwnerOf(uint256)833 function crossOwnerOf(uint256 tokenId) public view returns (EthCrossAccount memory) {818 function crossOwnerOf(uint256 tokenId) public view returns (CrossAddress memory) {834 require(false, stub_error);819 require(false, stub_error);835 tokenId;820 tokenId;836 dummy;821 dummy;837 return EthCrossAccount(0x0000000000000000000000000000000000000000, 0);822 return CrossAddress(0x0000000000000000000000000000000000000000, 0);838 }823 }839824840 /// Returns the token properties.825 /// Returns the token properties.875 /// @param tokenId The RFT to transfer860 /// @param tokenId The RFT to transfer876 /// @dev EVM selector for this function is: 0x2ada85ff,861 /// @dev EVM selector for this function is: 0x2ada85ff,877 /// or in textual repr: transferCross((address,uint256),uint256)862 /// or in textual repr: transferCross((address,uint256),uint256)878 function transferCross(EthCrossAccount memory to, uint256 tokenId) public {863 function transferCross(CrossAddress memory to, uint256 tokenId) public {879 require(false, stub_error);864 require(false, stub_error);880 to;865 to;881 tokenId;866 tokenId;891 /// @dev EVM selector for this function is: 0xd5cf430b,876 /// @dev EVM selector for this function is: 0xd5cf430b,892 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)877 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)893 function transferFromCross(878 function transferFromCross(894 EthCrossAccount memory from,879 CrossAddress memory from,895 EthCrossAccount memory to,880 CrossAddress memory to,896 uint256 tokenId881 uint256 tokenId897 ) public {882 ) public {898 require(false, stub_error);883 require(false, stub_error);927 /// @param tokenId The RFT to transfer912 /// @param tokenId The RFT to transfer928 /// @dev EVM selector for this function is: 0xbb2f5a58,913 /// @dev EVM selector for this function is: 0xbb2f5a58,929 /// or in textual repr: burnFromCross((address,uint256),uint256)914 /// or in textual repr: burnFromCross((address,uint256),uint256)930 function burnFromCross(EthCrossAccount memory from, uint256 tokenId) public {915 function burnFromCross(CrossAddress memory from, uint256 tokenId) public {931 require(false, stub_error);916 require(false, stub_error);932 from;917 from;933 tokenId;918 tokenId;979 /// @return uint256 The id of the newly minted token964 /// @return uint256 The id of the newly minted token980 /// @dev EVM selector for this function is: 0xb904db03,965 /// @dev EVM selector for this function is: 0xb904db03,981 /// or in textual repr: mintCross((address,uint256),(string,bytes)[])966 /// or in textual repr: mintCross((address,uint256),(string,bytes)[])982 function mintCross(EthCrossAccount memory to, Property[] memory properties) public returns (uint256) {967 function mintCross(CrossAddress memory to, Property[] memory properties) public returns (uint256) {983 require(false, stub_error);968 require(false, stub_error);984 to;969 to;985 properties;970 properties;pallets/refungible/src/stubs/UniqueRefungibleToken.rawdiffbeforeafterbothbinary blob — no preview
pallets/refungible/src/stubs/UniqueRefungibleToken.soldiffbeforeafterboth58 /// @param amount The amount that will be burnt.58 /// @param amount The amount that will be burnt.59 /// @dev EVM selector for this function is: 0xbb2f5a58,59 /// @dev EVM selector for this function is: 0xbb2f5a58,60 /// or in textual repr: burnFromCross((address,uint256),uint256)60 /// or in textual repr: burnFromCross((address,uint256),uint256)61 function burnFromCross(EthCrossAccount memory from, uint256 amount) public returns (bool) {61 function burnFromCross(CrossAddress memory from, uint256 amount) public returns (bool) {62 require(false, stub_error);62 require(false, stub_error);63 from;63 from;64 amount;64 amount;75 /// @param amount The amount of tokens to be spent.75 /// @param amount The amount of tokens to be spent.76 /// @dev EVM selector for this function is: 0x0ecd0ab0,76 /// @dev EVM selector for this function is: 0x0ecd0ab0,77 /// or in textual repr: approveCross((address,uint256),uint256)77 /// or in textual repr: approveCross((address,uint256),uint256)78 function approveCross(EthCrossAccount memory spender, uint256 amount) public returns (bool) {78 function approveCross(CrossAddress memory spender, uint256 amount) public returns (bool) {79 require(false, stub_error);79 require(false, stub_error);80 spender;80 spender;81 amount;81 amount;100 /// @param amount The amount to be transferred.100 /// @param amount The amount to be transferred.101 /// @dev EVM selector for this function is: 0x2ada85ff,101 /// @dev EVM selector for this function is: 0x2ada85ff,102 /// or in textual repr: transferCross((address,uint256),uint256)102 /// or in textual repr: transferCross((address,uint256),uint256)103 function transferCross(EthCrossAccount memory to, uint256 amount) public returns (bool) {103 function transferCross(CrossAddress memory to, uint256 amount) public returns (bool) {104 require(false, stub_error);104 require(false, stub_error);105 to;105 to;106 amount;106 amount;115 /// @dev EVM selector for this function is: 0xd5cf430b,115 /// @dev EVM selector for this function is: 0xd5cf430b,116 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)116 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)117 function transferFromCross(117 function transferFromCross(118 EthCrossAccount memory from,118 CrossAddress memory from,119 EthCrossAccount memory to,119 CrossAddress memory to,120 uint256 amount120 uint256 amount121 ) public returns (bool) {121 ) public returns (bool) {122 require(false, stub_error);122 require(false, stub_error);128 }128 }129}129}130130131/// @dev Cross account struct131/// Cross account struct132struct EthCrossAccount {132struct CrossAddress {133 address eth;133 address eth;134 uint256 sub;134 uint256 sub;135}135}pallets/unique/src/eth/stubs/CollectionHelpers.rawdiffbeforeafterbothbinary blob — no preview
pallets/unique/src/lib.rsdiffbeforeafterboth74extern crate alloc;74extern crate alloc;757576use frame_support::{76use frame_support::{77 decl_module, decl_storage, decl_error, decl_event,77 decl_module, decl_storage, decl_error,78 dispatch::DispatchResult,78 dispatch::DispatchResult,79 ensure, fail,79 ensure, fail,80 weights::{Weight},80 weights::{Weight},tests/src/eth/abi/contractHelpers.jsondiffbeforeafterboth190 "name": "contractAddress",190 "name": "contractAddress",191 "type": "address"191 "type": "address"192 },192 },193 { "internalType": "uint8", "name": "mode", "type": "uint8" }193 {194 "internalType": "enum SponsoringModeT",195 "name": "mode",196 "type": "uint8"197 }222 "name": "sponsor",226 "name": "sponsor",223 "outputs": [227 "outputs": [224 {228 {229 "components": [230 { "internalType": "bool", "name": "status", "type": "bool" },231 {225 "components": [232 "components": [226 { "internalType": "address", "name": "eth", "type": "address" },233 { "internalType": "address", "name": "eth", "type": "address" },227 { "internalType": "uint256", "name": "sub", "type": "uint256" }234 { "internalType": "uint256", "name": "sub", "type": "uint256" }228 ],235 ],236 "internalType": "struct CrossAddress",237 "name": "value",238 "type": "tuple"239 }240 ],229 "internalType": "struct EthCrossAccount",241 "internalType": "struct OptionCrossAddress",230 "name": "",242 "name": "",231 "type": "tuple"243 "type": "tuple"232 }244 }tests/src/eth/abi/fungible.jsondiffbeforeafterboth56 { "internalType": "address", "name": "eth", "type": "address" },56 { "internalType": "address", "name": "eth", "type": "address" },57 { "internalType": "uint256", "name": "sub", "type": "uint256" }57 { "internalType": "uint256", "name": "sub", "type": "uint256" }58 ],58 ],59 "internalType": "struct EthCrossAccount",59 "internalType": "struct CrossAddress",60 "name": "newAdmin",60 "name": "newAdmin",61 "type": "tuple"61 "type": "tuple"62 }62 }73 { "internalType": "address", "name": "eth", "type": "address" },73 { "internalType": "address", "name": "eth", "type": "address" },74 { "internalType": "uint256", "name": "sub", "type": "uint256" }74 { "internalType": "uint256", "name": "sub", "type": "uint256" }75 ],75 ],76 "internalType": "struct EthCrossAccount",76 "internalType": "struct CrossAddress",77 "name": "user",77 "name": "user",78 "type": "tuple"78 "type": "tuple"79 }79 }100 { "internalType": "address", "name": "eth", "type": "address" },100 { "internalType": "address", "name": "eth", "type": "address" },101 { "internalType": "uint256", "name": "sub", "type": "uint256" }101 { "internalType": "uint256", "name": "sub", "type": "uint256" }102 ],102 ],103 "internalType": "struct EthCrossAccount",103 "internalType": "struct CrossAddress",104 "name": "user",104 "name": "user",105 "type": "tuple"105 "type": "tuple"106 }106 }127 { "internalType": "address", "name": "eth", "type": "address" },127 { "internalType": "address", "name": "eth", "type": "address" },128 { "internalType": "uint256", "name": "sub", "type": "uint256" }128 { "internalType": "uint256", "name": "sub", "type": "uint256" }129 ],129 ],130 "internalType": "struct EthCrossAccount",130 "internalType": "struct CrossAddress",131 "name": "spender",131 "name": "spender",132 "type": "tuple"132 "type": "tuple"133 },133 },154 { "internalType": "address", "name": "eth", "type": "address" },154 { "internalType": "address", "name": "eth", "type": "address" },155 { "internalType": "uint256", "name": "sub", "type": "uint256" }155 { "internalType": "uint256", "name": "sub", "type": "uint256" }156 ],156 ],157 "internalType": "struct EthCrossAccount",157 "internalType": "struct CrossAddress",158 "name": "from",158 "name": "from",159 "type": "tuple"159 "type": "tuple"160 },160 },172 { "internalType": "address", "name": "eth", "type": "address" },172 { "internalType": "address", "name": "eth", "type": "address" },173 { "internalType": "uint256", "name": "sub", "type": "uint256" }173 { "internalType": "uint256", "name": "sub", "type": "uint256" }174 ],174 ],175 "internalType": "struct EthCrossAccount",175 "internalType": "struct CrossAddress",176 "name": "newOwner",176 "name": "newOwner",177 "type": "tuple"177 "type": "tuple"178 }178 }191 { "internalType": "address", "name": "eth", "type": "address" },191 { "internalType": "address", "name": "eth", "type": "address" },192 { "internalType": "uint256", "name": "sub", "type": "uint256" }192 { "internalType": "uint256", "name": "sub", "type": "uint256" }193 ],193 ],194 "internalType": "struct EthCrossAccount[]",194 "internalType": "struct CrossAddress[]",195 "name": "",195 "name": "",196 "type": "tuple[]"196 "type": "tuple[]"197 }197 }213 {213 {214 "components": [214 "components": [215 {215 {216 "internalType": "enum CollectionLimits",216 "internalType": "enum CollectionLimitField",217 "name": "field_0",217 "name": "field",218 "type": "uint8"218 "type": "uint8"219 },219 },220 {221 "components": [220 { "internalType": "bool", "name": "field_1", "type": "bool" },222 { "internalType": "bool", "name": "status", "type": "bool" },221 { "internalType": "uint256", "name": "field_2", "type": "uint256" }223 { "internalType": "uint256", "name": "value", "type": "uint256" }224 ],225 "internalType": "struct OptionUint",226 "name": "value",227 "type": "tuple"228 }222 ],229 ],223 "internalType": "struct Tuple23[]",230 "internalType": "struct CollectionLimit[]",224 "name": "",231 "name": "",225 "type": "tuple[]"232 "type": "tuple[]"226 }233 }235 {242 {236 "components": [243 "components": [237 {244 {238 "internalType": "enum CollectionPermissions",245 "internalType": "enum CollectionPermissionField",239 "name": "field_0",246 "name": "field",240 "type": "uint8"247 "type": "uint8"241 },248 },242 { "internalType": "bool", "name": "field_1", "type": "bool" }249 { "internalType": "bool", "name": "value", "type": "bool" }243 ],250 ],244 "internalType": "struct Tuple32[]",251 "internalType": "struct CollectionNestingPermission[]",245 "name": "",252 "name": "",246 "type": "tuple[]"253 "type": "tuple[]"247 }254 }255 "outputs": [262 "outputs": [256 {263 {257 "components": [264 "components": [258 { "internalType": "bool", "name": "field_0", "type": "bool" },265 { "internalType": "bool", "name": "token_owner", "type": "bool" },259 {266 { "internalType": "uint256[]", "name": "ids", "type": "uint256[]" }260 "internalType": "uint256[]",261 "name": "field_1",262 "type": "uint256[]"263 }264 ],267 ],265 "internalType": "struct Tuple29",268 "internalType": "struct CollectionNesting",266 "name": "",269 "name": "",267 "type": "tuple"270 "type": "tuple"268 }271 }279 { "internalType": "address", "name": "eth", "type": "address" },282 { "internalType": "address", "name": "eth", "type": "address" },280 { "internalType": "uint256", "name": "sub", "type": "uint256" }283 { "internalType": "uint256", "name": "sub", "type": "uint256" }281 ],284 ],282 "internalType": "struct EthCrossAccount",285 "internalType": "struct CrossAddress",283 "name": "",286 "name": "",284 "type": "tuple"287 "type": "tuple"285 }288 }322 { "internalType": "address", "name": "eth", "type": "address" },325 { "internalType": "address", "name": "eth", "type": "address" },323 { "internalType": "uint256", "name": "sub", "type": "uint256" }326 { "internalType": "uint256", "name": "sub", "type": "uint256" }324 ],327 ],325 "internalType": "struct EthCrossAccount",328 "internalType": "struct CrossAddress",326 "name": "",329 "name": "",327 "type": "tuple"330 "type": "tuple"328 }331 }381 { "internalType": "address", "name": "eth", "type": "address" },384 { "internalType": "address", "name": "eth", "type": "address" },382 { "internalType": "uint256", "name": "sub", "type": "uint256" }385 { "internalType": "uint256", "name": "sub", "type": "uint256" }383 ],386 ],384 "internalType": "struct EthCrossAccount",387 "internalType": "struct CrossAddress",385 "name": "user",388 "name": "user",386 "type": "tuple"389 "type": "tuple"387 }390 }425 { "internalType": "address", "name": "eth", "type": "address" },428 { "internalType": "address", "name": "eth", "type": "address" },426 { "internalType": "uint256", "name": "sub", "type": "uint256" }429 { "internalType": "uint256", "name": "sub", "type": "uint256" }427 ],430 ],428 "internalType": "struct EthCrossAccount",431 "internalType": "struct CrossAddress",429 "name": "to",432 "name": "to",430 "type": "tuple"433 "type": "tuple"431 },434 },450 { "internalType": "address", "name": "eth", "type": "address" },453 { "internalType": "address", "name": "eth", "type": "address" },451 { "internalType": "uint256", "name": "sub", "type": "uint256" }454 { "internalType": "uint256", "name": "sub", "type": "uint256" }452 ],455 ],453 "internalType": "struct EthCrossAccount",456 "internalType": "struct CrossAddress",454 "name": "admin",457 "name": "admin",455 "type": "tuple"458 "type": "tuple"456 }459 }474 { "internalType": "address", "name": "eth", "type": "address" },477 { "internalType": "address", "name": "eth", "type": "address" },475 { "internalType": "uint256", "name": "sub", "type": "uint256" }478 { "internalType": "uint256", "name": "sub", "type": "uint256" }476 ],479 ],477 "internalType": "struct EthCrossAccount",480 "internalType": "struct CrossAddress",478 "name": "user",481 "name": "user",479 "type": "tuple"482 "type": "tuple"480 }483 }492 "type": "function"495 "type": "function"493 },496 },494 {497 {495 "inputs": [498 "inputs": [499 {500 "components": [496 {501 {497 "internalType": "enum CollectionLimits",502 "internalType": "enum CollectionLimitField",498 "name": "limit",503 "name": "field",499 "type": "uint8"504 "type": "uint8"500 },505 },506 {507 "components": [501 { "internalType": "bool", "name": "status", "type": "bool" },508 { "internalType": "bool", "name": "status", "type": "bool" },502 { "internalType": "uint256", "name": "value", "type": "uint256" }509 { "internalType": "uint256", "name": "value", "type": "uint256" }510 ],511 "internalType": "struct OptionUint",512 "name": "value",513 "type": "tuple"514 }515 ],516 "internalType": "struct CollectionLimit",517 "name": "limit",518 "type": "tuple"519 }503 ],520 ],504 "name": "setCollectionLimit",521 "name": "setCollectionLimit",505 "outputs": [],522 "outputs": [],506 "stateMutability": "nonpayable",523 "stateMutability": "nonpayable",558 { "internalType": "address", "name": "eth", "type": "address" },575 { "internalType": "address", "name": "eth", "type": "address" },559 { "internalType": "uint256", "name": "sub", "type": "uint256" }576 { "internalType": "uint256", "name": "sub", "type": "uint256" }560 ],577 ],561 "internalType": "struct EthCrossAccount",578 "internalType": "struct CrossAddress",562 "name": "sponsor",579 "name": "sponsor",563 "type": "tuple"580 "type": "tuple"564 }581 }608 { "internalType": "address", "name": "eth", "type": "address" },625 { "internalType": "address", "name": "eth", "type": "address" },609 { "internalType": "uint256", "name": "sub", "type": "uint256" }626 { "internalType": "uint256", "name": "sub", "type": "uint256" }610 ],627 ],611 "internalType": "struct EthCrossAccount",628 "internalType": "struct CrossAddress",612 "name": "to",629 "name": "to",613 "type": "tuple"630 "type": "tuple"614 },631 },637 { "internalType": "address", "name": "eth", "type": "address" },654 { "internalType": "address", "name": "eth", "type": "address" },638 { "internalType": "uint256", "name": "sub", "type": "uint256" }655 { "internalType": "uint256", "name": "sub", "type": "uint256" }639 ],656 ],640 "internalType": "struct EthCrossAccount",657 "internalType": "struct CrossAddress",641 "name": "from",658 "name": "from",642 "type": "tuple"659 "type": "tuple"643 },660 },646 { "internalType": "address", "name": "eth", "type": "address" },663 { "internalType": "address", "name": "eth", "type": "address" },647 { "internalType": "uint256", "name": "sub", "type": "uint256" }664 { "internalType": "uint256", "name": "sub", "type": "uint256" }648 ],665 ],649 "internalType": "struct EthCrossAccount",666 "internalType": "struct CrossAddress",650 "name": "to",667 "name": "to",651 "type": "tuple"668 "type": "tuple"652 },669 },tests/src/eth/abi/nonFungible.jsondiffbeforeafterboth87 { "internalType": "address", "name": "eth", "type": "address" },87 { "internalType": "address", "name": "eth", "type": "address" },88 { "internalType": "uint256", "name": "sub", "type": "uint256" }88 { "internalType": "uint256", "name": "sub", "type": "uint256" }89 ],89 ],90 "internalType": "struct EthCrossAccount",90 "internalType": "struct CrossAddress",91 "name": "newAdmin",91 "name": "newAdmin",92 "type": "tuple"92 "type": "tuple"93 }93 }104 { "internalType": "address", "name": "eth", "type": "address" },104 { "internalType": "address", "name": "eth", "type": "address" },105 { "internalType": "uint256", "name": "sub", "type": "uint256" }105 { "internalType": "uint256", "name": "sub", "type": "uint256" }106 ],106 ],107 "internalType": "struct EthCrossAccount",107 "internalType": "struct CrossAddress",108 "name": "user",108 "name": "user",109 "type": "tuple"109 "type": "tuple"110 }110 }121 { "internalType": "address", "name": "eth", "type": "address" },121 { "internalType": "address", "name": "eth", "type": "address" },122 { "internalType": "uint256", "name": "sub", "type": "uint256" }122 { "internalType": "uint256", "name": "sub", "type": "uint256" }123 ],123 ],124 "internalType": "struct EthCrossAccount",124 "internalType": "struct CrossAddress",125 "name": "user",125 "name": "user",126 "type": "tuple"126 "type": "tuple"127 }127 }148 { "internalType": "address", "name": "eth", "type": "address" },148 { "internalType": "address", "name": "eth", "type": "address" },149 { "internalType": "uint256", "name": "sub", "type": "uint256" }149 { "internalType": "uint256", "name": "sub", "type": "uint256" }150 ],150 ],151 "internalType": "struct EthCrossAccount",151 "internalType": "struct CrossAddress",152 "name": "approved",152 "name": "approved",153 "type": "tuple"153 "type": "tuple"154 },154 },184 { "internalType": "address", "name": "eth", "type": "address" },184 { "internalType": "address", "name": "eth", "type": "address" },185 { "internalType": "uint256", "name": "sub", "type": "uint256" }185 { "internalType": "uint256", "name": "sub", "type": "uint256" }186 ],186 ],187 "internalType": "struct EthCrossAccount",187 "internalType": "struct CrossAddress",188 "name": "from",188 "name": "from",189 "type": "tuple"189 "type": "tuple"190 },190 },202 { "internalType": "address", "name": "eth", "type": "address" },202 { "internalType": "address", "name": "eth", "type": "address" },203 { "internalType": "uint256", "name": "sub", "type": "uint256" }203 { "internalType": "uint256", "name": "sub", "type": "uint256" }204 ],204 ],205 "internalType": "struct EthCrossAccount",205 "internalType": "struct CrossAddress",206 "name": "newOwner",206 "name": "newOwner",207 "type": "tuple"207 "type": "tuple"208 }208 }221 { "internalType": "address", "name": "eth", "type": "address" },221 { "internalType": "address", "name": "eth", "type": "address" },222 { "internalType": "uint256", "name": "sub", "type": "uint256" }222 { "internalType": "uint256", "name": "sub", "type": "uint256" }223 ],223 ],224 "internalType": "struct EthCrossAccount[]",224 "internalType": "struct CrossAddress[]",225 "name": "",225 "name": "",226 "type": "tuple[]"226 "type": "tuple[]"227 }227 }243 {243 {244 "components": [244 "components": [245 {245 {246 "internalType": "enum CollectionLimits",246 "internalType": "enum CollectionLimitField",247 "name": "field_0",247 "name": "field",248 "type": "uint8"248 "type": "uint8"249 },249 },250 {251 "components": [250 { "internalType": "bool", "name": "field_1", "type": "bool" },252 { "internalType": "bool", "name": "status", "type": "bool" },251 { "internalType": "uint256", "name": "field_2", "type": "uint256" }253 { "internalType": "uint256", "name": "value", "type": "uint256" }254 ],255 "internalType": "struct OptionUint",256 "name": "value",257 "type": "tuple"258 }252 ],259 ],253 "internalType": "struct Tuple35[]",260 "internalType": "struct CollectionLimit[]",254 "name": "",261 "name": "",255 "type": "tuple[]"262 "type": "tuple[]"256 }263 }265 {272 {266 "components": [273 "components": [267 {274 {268 "internalType": "enum CollectionPermissions",275 "internalType": "enum CollectionPermissionField",269 "name": "field_0",276 "name": "field",270 "type": "uint8"277 "type": "uint8"271 },278 },272 { "internalType": "bool", "name": "field_1", "type": "bool" }279 { "internalType": "bool", "name": "value", "type": "bool" }273 ],280 ],274 "internalType": "struct Tuple44[]",281 "internalType": "struct CollectionNestingPermission[]",275 "name": "",282 "name": "",276 "type": "tuple[]"283 "type": "tuple[]"277 }284 }285 "outputs": [292 "outputs": [286 {293 {287 "components": [294 "components": [288 { "internalType": "bool", "name": "field_0", "type": "bool" },295 { "internalType": "bool", "name": "token_owner", "type": "bool" },289 {296 { "internalType": "uint256[]", "name": "ids", "type": "uint256[]" }290 "internalType": "uint256[]",291 "name": "field_1",292 "type": "uint256[]"293 }294 ],297 ],295 "internalType": "struct Tuple41",298 "internalType": "struct CollectionNesting",296 "name": "",299 "name": "",297 "type": "tuple"300 "type": "tuple"298 }301 }309 { "internalType": "address", "name": "eth", "type": "address" },312 { "internalType": "address", "name": "eth", "type": "address" },310 { "internalType": "uint256", "name": "sub", "type": "uint256" }313 { "internalType": "uint256", "name": "sub", "type": "uint256" }311 ],314 ],312 "internalType": "struct EthCrossAccount",315 "internalType": "struct CrossAddress",313 "name": "",316 "name": "",314 "type": "tuple"317 "type": "tuple"315 }318 }352 { "internalType": "address", "name": "eth", "type": "address" },355 { "internalType": "address", "name": "eth", "type": "address" },353 { "internalType": "uint256", "name": "sub", "type": "uint256" }356 { "internalType": "uint256", "name": "sub", "type": "uint256" }354 ],357 ],355 "internalType": "struct EthCrossAccount",358 "internalType": "struct CrossAddress",356 "name": "",359 "name": "",357 "type": "tuple"360 "type": "tuple"358 }361 }385 { "internalType": "address", "name": "eth", "type": "address" },388 { "internalType": "address", "name": "eth", "type": "address" },386 { "internalType": "uint256", "name": "sub", "type": "uint256" }389 { "internalType": "uint256", "name": "sub", "type": "uint256" }387 ],390 ],388 "internalType": "struct EthCrossAccount",391 "internalType": "struct CrossAddress",389 "name": "",392 "name": "",390 "type": "tuple"393 "type": "tuple"391 }394 }459 { "internalType": "address", "name": "eth", "type": "address" },462 { "internalType": "address", "name": "eth", "type": "address" },460 { "internalType": "uint256", "name": "sub", "type": "uint256" }463 { "internalType": "uint256", "name": "sub", "type": "uint256" }461 ],464 ],462 "internalType": "struct EthCrossAccount",465 "internalType": "struct CrossAddress",463 "name": "user",466 "name": "user",464 "type": "tuple"467 "type": "tuple"465 }468 }483 { "internalType": "address", "name": "eth", "type": "address" },486 { "internalType": "address", "name": "eth", "type": "address" },484 { "internalType": "uint256", "name": "sub", "type": "uint256" }487 { "internalType": "uint256", "name": "sub", "type": "uint256" }485 ],488 ],486 "internalType": "struct EthCrossAccount",489 "internalType": "struct CrossAddress",487 "name": "to",490 "name": "to",488 "type": "tuple"491 "type": "tuple"489 },492 },579 { "internalType": "address", "name": "eth", "type": "address" },582 { "internalType": "address", "name": "eth", "type": "address" },580 { "internalType": "uint256", "name": "sub", "type": "uint256" }583 { "internalType": "uint256", "name": "sub", "type": "uint256" }581 ],584 ],582 "internalType": "struct EthCrossAccount",585 "internalType": "struct CrossAddress",583 "name": "admin",586 "name": "admin",584 "type": "tuple"587 "type": "tuple"585 }588 }603 { "internalType": "address", "name": "eth", "type": "address" },606 { "internalType": "address", "name": "eth", "type": "address" },604 { "internalType": "uint256", "name": "sub", "type": "uint256" }607 { "internalType": "uint256", "name": "sub", "type": "uint256" }605 ],608 ],606 "internalType": "struct EthCrossAccount",609 "internalType": "struct CrossAddress",607 "name": "user",610 "name": "user",608 "type": "tuple"611 "type": "tuple"609 }612 }654 "type": "function"657 "type": "function"655 },658 },656 {659 {657 "inputs": [660 "inputs": [661 {662 "components": [658 {663 {659 "internalType": "enum CollectionLimits",664 "internalType": "enum CollectionLimitField",660 "name": "limit",665 "name": "field",661 "type": "uint8"666 "type": "uint8"662 },667 },668 {669 "components": [663 { "internalType": "bool", "name": "status", "type": "bool" },670 { "internalType": "bool", "name": "status", "type": "bool" },664 { "internalType": "uint256", "name": "value", "type": "uint256" }671 { "internalType": "uint256", "name": "value", "type": "uint256" }672 ],673 "internalType": "struct OptionUint",674 "name": "value",675 "type": "tuple"676 }677 ],678 "internalType": "struct CollectionLimit",679 "name": "limit",680 "type": "tuple"681 }665 ],682 ],666 "name": "setCollectionLimit",683 "name": "setCollectionLimit",667 "outputs": [],684 "outputs": [],668 "stateMutability": "nonpayable",685 "stateMutability": "nonpayable",720 { "internalType": "address", "name": "eth", "type": "address" },737 { "internalType": "address", "name": "eth", "type": "address" },721 { "internalType": "uint256", "name": "sub", "type": "uint256" }738 { "internalType": "uint256", "name": "sub", "type": "uint256" }722 ],739 ],723 "internalType": "struct EthCrossAccount",740 "internalType": "struct CrossAddress",724 "name": "sponsor",741 "name": "sponsor",725 "type": "tuple"742 "type": "tuple"726 }743 }752 "inputs": [769 "inputs": [753 {770 {754 "components": [771 "components": [755 { "internalType": "string", "name": "field_0", "type": "string" },772 { "internalType": "string", "name": "key", "type": "string" },756 {773 {757 "components": [774 "components": [758 {775 {759 "internalType": "enum EthTokenPermissions",776 "internalType": "enum TokenPermissionField",760 "name": "field_0",777 "name": "code",761 "type": "uint8"778 "type": "uint8"762 },779 },763 { "internalType": "bool", "name": "field_1", "type": "bool" }780 { "internalType": "bool", "name": "value", "type": "bool" }764 ],781 ],765 "internalType": "struct Tuple59[]",782 "internalType": "struct PropertyPermission[]",766 "name": "field_1",783 "name": "permissions",767 "type": "tuple[]"784 "type": "tuple[]"768 }785 }769 ],786 ],770 "internalType": "struct Tuple61[]",787 "internalType": "struct TokenPropertyPermission[]",771 "name": "permissions",788 "name": "permissions",772 "type": "tuple[]"789 "type": "tuple[]"773 }790 }818 "outputs": [835 "outputs": [819 {836 {820 "components": [837 "components": [821 { "internalType": "string", "name": "field_0", "type": "string" },838 { "internalType": "string", "name": "key", "type": "string" },822 {839 {823 "components": [840 "components": [824 {841 {825 "internalType": "enum EthTokenPermissions",842 "internalType": "enum TokenPermissionField",826 "name": "field_0",843 "name": "code",827 "type": "uint8"844 "type": "uint8"828 },845 },829 { "internalType": "bool", "name": "field_1", "type": "bool" }846 { "internalType": "bool", "name": "value", "type": "bool" }830 ],847 ],831 "internalType": "struct Tuple59[]",848 "internalType": "struct PropertyPermission[]",832 "name": "field_1",849 "name": "permissions",833 "type": "tuple[]"850 "type": "tuple[]"834 }851 }835 ],852 ],836 "internalType": "struct Tuple61[]",853 "internalType": "struct TokenPropertyPermission[]",837 "name": "",854 "name": "",838 "type": "tuple[]"855 "type": "tuple[]"839 }856 }874 { "internalType": "address", "name": "eth", "type": "address" },891 { "internalType": "address", "name": "eth", "type": "address" },875 { "internalType": "uint256", "name": "sub", "type": "uint256" }892 { "internalType": "uint256", "name": "sub", "type": "uint256" }876 ],893 ],877 "internalType": "struct EthCrossAccount",894 "internalType": "struct CrossAddress",878 "name": "to",895 "name": "to",879 "type": "tuple"896 "type": "tuple"880 },897 },903 { "internalType": "address", "name": "eth", "type": "address" },920 { "internalType": "address", "name": "eth", "type": "address" },904 { "internalType": "uint256", "name": "sub", "type": "uint256" }921 { "internalType": "uint256", "name": "sub", "type": "uint256" }905 ],922 ],906 "internalType": "struct EthCrossAccount",923 "internalType": "struct CrossAddress",907 "name": "from",924 "name": "from",908 "type": "tuple"925 "type": "tuple"909 },926 },912 { "internalType": "address", "name": "eth", "type": "address" },929 { "internalType": "address", "name": "eth", "type": "address" },913 { "internalType": "uint256", "name": "sub", "type": "uint256" }930 { "internalType": "uint256", "name": "sub", "type": "uint256" }914 ],931 ],915 "internalType": "struct EthCrossAccount",932 "internalType": "struct CrossAddress",916 "name": "to",933 "name": "to",917 "type": "tuple"934 "type": "tuple"918 },935 },tests/src/eth/abi/reFungible.jsondiffbeforeafterboth87 { "internalType": "address", "name": "eth", "type": "address" },87 { "internalType": "address", "name": "eth", "type": "address" },88 { "internalType": "uint256", "name": "sub", "type": "uint256" }88 { "internalType": "uint256", "name": "sub", "type": "uint256" }89 ],89 ],90 "internalType": "struct EthCrossAccount",90 "internalType": "struct CrossAddress",91 "name": "newAdmin",91 "name": "newAdmin",92 "type": "tuple"92 "type": "tuple"93 }93 }104 { "internalType": "address", "name": "eth", "type": "address" },104 { "internalType": "address", "name": "eth", "type": "address" },105 { "internalType": "uint256", "name": "sub", "type": "uint256" }105 { "internalType": "uint256", "name": "sub", "type": "uint256" }106 ],106 ],107 "internalType": "struct EthCrossAccount",107 "internalType": "struct CrossAddress",108 "name": "user",108 "name": "user",109 "type": "tuple"109 "type": "tuple"110 }110 }121 { "internalType": "address", "name": "eth", "type": "address" },121 { "internalType": "address", "name": "eth", "type": "address" },122 { "internalType": "uint256", "name": "sub", "type": "uint256" }122 { "internalType": "uint256", "name": "sub", "type": "uint256" }123 ],123 ],124 "internalType": "struct EthCrossAccount",124 "internalType": "struct CrossAddress",125 "name": "user",125 "name": "user",126 "type": "tuple"126 "type": "tuple"127 }127 }166 { "internalType": "address", "name": "eth", "type": "address" },166 { "internalType": "address", "name": "eth", "type": "address" },167 { "internalType": "uint256", "name": "sub", "type": "uint256" }167 { "internalType": "uint256", "name": "sub", "type": "uint256" }168 ],168 ],169 "internalType": "struct EthCrossAccount",169 "internalType": "struct CrossAddress",170 "name": "from",170 "name": "from",171 "type": "tuple"171 "type": "tuple"172 },172 },184 { "internalType": "address", "name": "eth", "type": "address" },184 { "internalType": "address", "name": "eth", "type": "address" },185 { "internalType": "uint256", "name": "sub", "type": "uint256" }185 { "internalType": "uint256", "name": "sub", "type": "uint256" }186 ],186 ],187 "internalType": "struct EthCrossAccount",187 "internalType": "struct CrossAddress",188 "name": "newOwner",188 "name": "newOwner",189 "type": "tuple"189 "type": "tuple"190 }190 }203 { "internalType": "address", "name": "eth", "type": "address" },203 { "internalType": "address", "name": "eth", "type": "address" },204 { "internalType": "uint256", "name": "sub", "type": "uint256" }204 { "internalType": "uint256", "name": "sub", "type": "uint256" }205 ],205 ],206 "internalType": "struct EthCrossAccount[]",206 "internalType": "struct CrossAddress[]",207 "name": "",207 "name": "",208 "type": "tuple[]"208 "type": "tuple[]"209 }209 }225 {225 {226 "components": [226 "components": [227 {227 {228 "internalType": "enum CollectionLimits",228 "internalType": "enum CollectionLimitField",229 "name": "field_0",229 "name": "field",230 "type": "uint8"230 "type": "uint8"231 },231 },232 {233 "components": [232 { "internalType": "bool", "name": "field_1", "type": "bool" },234 { "internalType": "bool", "name": "status", "type": "bool" },233 { "internalType": "uint256", "name": "field_2", "type": "uint256" }235 { "internalType": "uint256", "name": "value", "type": "uint256" }236 ],237 "internalType": "struct OptionUint",238 "name": "value",239 "type": "tuple"240 }234 ],241 ],235 "internalType": "struct Tuple34[]",242 "internalType": "struct CollectionLimit[]",236 "name": "",243 "name": "",237 "type": "tuple[]"244 "type": "tuple[]"238 }245 }247 {254 {248 "components": [255 "components": [249 {256 {250 "internalType": "enum CollectionPermissions",257 "internalType": "enum CollectionPermissionField",251 "name": "field_0",258 "name": "field",252 "type": "uint8"259 "type": "uint8"253 },260 },254 { "internalType": "bool", "name": "field_1", "type": "bool" }261 { "internalType": "bool", "name": "value", "type": "bool" }255 ],262 ],256 "internalType": "struct Tuple43[]",263 "internalType": "struct CollectionNestingPermission[]",257 "name": "",264 "name": "",258 "type": "tuple[]"265 "type": "tuple[]"259 }266 }267 "outputs": [274 "outputs": [268 {275 {269 "components": [276 "components": [270 { "internalType": "bool", "name": "field_0", "type": "bool" },277 { "internalType": "bool", "name": "token_owner", "type": "bool" },271 {278 { "internalType": "uint256[]", "name": "ids", "type": "uint256[]" }272 "internalType": "uint256[]",273 "name": "field_1",274 "type": "uint256[]"275 }276 ],279 ],277 "internalType": "struct Tuple40",280 "internalType": "struct CollectionNesting",278 "name": "",281 "name": "",279 "type": "tuple"282 "type": "tuple"280 }283 }291 { "internalType": "address", "name": "eth", "type": "address" },294 { "internalType": "address", "name": "eth", "type": "address" },292 { "internalType": "uint256", "name": "sub", "type": "uint256" }295 { "internalType": "uint256", "name": "sub", "type": "uint256" }293 ],296 ],294 "internalType": "struct EthCrossAccount",297 "internalType": "struct CrossAddress",295 "name": "",298 "name": "",296 "type": "tuple"299 "type": "tuple"297 }300 }334 { "internalType": "address", "name": "eth", "type": "address" },337 { "internalType": "address", "name": "eth", "type": "address" },335 { "internalType": "uint256", "name": "sub", "type": "uint256" }338 { "internalType": "uint256", "name": "sub", "type": "uint256" }336 ],339 ],337 "internalType": "struct EthCrossAccount",340 "internalType": "struct CrossAddress",338 "name": "",341 "name": "",339 "type": "tuple"342 "type": "tuple"340 }343 }367 { "internalType": "address", "name": "eth", "type": "address" },370 { "internalType": "address", "name": "eth", "type": "address" },368 { "internalType": "uint256", "name": "sub", "type": "uint256" }371 { "internalType": "uint256", "name": "sub", "type": "uint256" }369 ],372 ],370 "internalType": "struct EthCrossAccount",373 "internalType": "struct CrossAddress",371 "name": "",374 "name": "",372 "type": "tuple"375 "type": "tuple"373 }376 }441 { "internalType": "address", "name": "eth", "type": "address" },444 { "internalType": "address", "name": "eth", "type": "address" },442 { "internalType": "uint256", "name": "sub", "type": "uint256" }445 { "internalType": "uint256", "name": "sub", "type": "uint256" }443 ],446 ],444 "internalType": "struct EthCrossAccount",447 "internalType": "struct CrossAddress",445 "name": "user",448 "name": "user",446 "type": "tuple"449 "type": "tuple"447 }450 }465 { "internalType": "address", "name": "eth", "type": "address" },468 { "internalType": "address", "name": "eth", "type": "address" },466 { "internalType": "uint256", "name": "sub", "type": "uint256" }469 { "internalType": "uint256", "name": "sub", "type": "uint256" }467 ],470 ],468 "internalType": "struct EthCrossAccount",471 "internalType": "struct CrossAddress",469 "name": "to",472 "name": "to",470 "type": "tuple"473 "type": "tuple"471 },474 },561 { "internalType": "address", "name": "eth", "type": "address" },564 { "internalType": "address", "name": "eth", "type": "address" },562 { "internalType": "uint256", "name": "sub", "type": "uint256" }565 { "internalType": "uint256", "name": "sub", "type": "uint256" }563 ],566 ],564 "internalType": "struct EthCrossAccount",567 "internalType": "struct CrossAddress",565 "name": "admin",568 "name": "admin",566 "type": "tuple"569 "type": "tuple"567 }570 }585 { "internalType": "address", "name": "eth", "type": "address" },588 { "internalType": "address", "name": "eth", "type": "address" },586 { "internalType": "uint256", "name": "sub", "type": "uint256" }589 { "internalType": "uint256", "name": "sub", "type": "uint256" }587 ],590 ],588 "internalType": "struct EthCrossAccount",591 "internalType": "struct CrossAddress",589 "name": "user",592 "name": "user",590 "type": "tuple"593 "type": "tuple"591 }594 }636 "type": "function"639 "type": "function"637 },640 },638 {641 {639 "inputs": [642 "inputs": [643 {644 "components": [640 {645 {641 "internalType": "enum CollectionLimits",646 "internalType": "enum CollectionLimitField",642 "name": "limit",647 "name": "field",643 "type": "uint8"648 "type": "uint8"644 },649 },650 {651 "components": [645 { "internalType": "bool", "name": "status", "type": "bool" },652 { "internalType": "bool", "name": "status", "type": "bool" },646 { "internalType": "uint256", "name": "value", "type": "uint256" }653 { "internalType": "uint256", "name": "value", "type": "uint256" }654 ],655 "internalType": "struct OptionUint",656 "name": "value",657 "type": "tuple"658 }659 ],660 "internalType": "struct CollectionLimit",661 "name": "limit",662 "type": "tuple"663 }647 ],664 ],648 "name": "setCollectionLimit",665 "name": "setCollectionLimit",649 "outputs": [],666 "outputs": [],650 "stateMutability": "nonpayable",667 "stateMutability": "nonpayable",702 { "internalType": "address", "name": "eth", "type": "address" },719 { "internalType": "address", "name": "eth", "type": "address" },703 { "internalType": "uint256", "name": "sub", "type": "uint256" }720 { "internalType": "uint256", "name": "sub", "type": "uint256" }704 ],721 ],705 "internalType": "struct EthCrossAccount",722 "internalType": "struct CrossAddress",706 "name": "sponsor",723 "name": "sponsor",707 "type": "tuple"724 "type": "tuple"708 }725 }734 "inputs": [751 "inputs": [735 {752 {736 "components": [753 "components": [737 { "internalType": "string", "name": "field_0", "type": "string" },754 { "internalType": "string", "name": "key", "type": "string" },738 {755 {739 "components": [756 "components": [740 {757 {741 "internalType": "enum EthTokenPermissions",758 "internalType": "enum TokenPermissionField",742 "name": "field_0",759 "name": "code",743 "type": "uint8"760 "type": "uint8"744 },761 },745 { "internalType": "bool", "name": "field_1", "type": "bool" }762 { "internalType": "bool", "name": "value", "type": "bool" }746 ],763 ],747 "internalType": "struct Tuple58[]",764 "internalType": "struct PropertyPermission[]",748 "name": "field_1",765 "name": "permissions",749 "type": "tuple[]"766 "type": "tuple[]"750 }767 }751 ],768 ],752 "internalType": "struct Tuple60[]",769 "internalType": "struct TokenPropertyPermission[]",753 "name": "permissions",770 "name": "permissions",754 "type": "tuple[]"771 "type": "tuple[]"755 }772 }809 "outputs": [826 "outputs": [810 {827 {811 "components": [828 "components": [812 { "internalType": "string", "name": "field_0", "type": "string" },829 { "internalType": "string", "name": "key", "type": "string" },813 {830 {814 "components": [831 "components": [815 {832 {816 "internalType": "enum EthTokenPermissions",833 "internalType": "enum TokenPermissionField",817 "name": "field_0",834 "name": "code",818 "type": "uint8"835 "type": "uint8"819 },836 },820 { "internalType": "bool", "name": "field_1", "type": "bool" }837 { "internalType": "bool", "name": "value", "type": "bool" }821 ],838 ],822 "internalType": "struct Tuple58[]",839 "internalType": "struct PropertyPermission[]",823 "name": "field_1",840 "name": "permissions",824 "type": "tuple[]"841 "type": "tuple[]"825 }842 }826 ],843 ],827 "internalType": "struct Tuple60[]",844 "internalType": "struct TokenPropertyPermission[]",828 "name": "",845 "name": "",829 "type": "tuple[]"846 "type": "tuple[]"830 }847 }865 { "internalType": "address", "name": "eth", "type": "address" },882 { "internalType": "address", "name": "eth", "type": "address" },866 { "internalType": "uint256", "name": "sub", "type": "uint256" }883 { "internalType": "uint256", "name": "sub", "type": "uint256" }867 ],884 ],868 "internalType": "struct EthCrossAccount",885 "internalType": "struct CrossAddress",869 "name": "to",886 "name": "to",870 "type": "tuple"887 "type": "tuple"871 },888 },894 { "internalType": "address", "name": "eth", "type": "address" },911 { "internalType": "address", "name": "eth", "type": "address" },895 { "internalType": "uint256", "name": "sub", "type": "uint256" }912 { "internalType": "uint256", "name": "sub", "type": "uint256" }896 ],913 ],897 "internalType": "struct EthCrossAccount",914 "internalType": "struct CrossAddress",898 "name": "from",915 "name": "from",899 "type": "tuple"916 "type": "tuple"900 },917 },903 { "internalType": "address", "name": "eth", "type": "address" },920 { "internalType": "address", "name": "eth", "type": "address" },904 { "internalType": "uint256", "name": "sub", "type": "uint256" }921 { "internalType": "uint256", "name": "sub", "type": "uint256" }905 ],922 ],906 "internalType": "struct EthCrossAccount",923 "internalType": "struct CrossAddress",907 "name": "to",924 "name": "to",908 "type": "tuple"925 "type": "tuple"909 },926 },tests/src/eth/abi/reFungibleToken.jsondiffbeforeafterboth76 { "internalType": "address", "name": "eth", "type": "address" },76 { "internalType": "address", "name": "eth", "type": "address" },77 { "internalType": "uint256", "name": "sub", "type": "uint256" }77 { "internalType": "uint256", "name": "sub", "type": "uint256" }78 ],78 ],79 "internalType": "struct EthCrossAccount",79 "internalType": "struct CrossAddress",80 "name": "spender",80 "name": "spender",81 "type": "tuple"81 "type": "tuple"82 },82 },113 { "internalType": "address", "name": "eth", "type": "address" },113 { "internalType": "address", "name": "eth", "type": "address" },114 { "internalType": "uint256", "name": "sub", "type": "uint256" }114 { "internalType": "uint256", "name": "sub", "type": "uint256" }115 ],115 ],116 "internalType": "struct EthCrossAccount",116 "internalType": "struct CrossAddress",117 "name": "from",117 "name": "from",118 "type": "tuple"118 "type": "tuple"119 },119 },201 { "internalType": "address", "name": "eth", "type": "address" },201 { "internalType": "address", "name": "eth", "type": "address" },202 { "internalType": "uint256", "name": "sub", "type": "uint256" }202 { "internalType": "uint256", "name": "sub", "type": "uint256" }203 ],203 ],204 "internalType": "struct EthCrossAccount",204 "internalType": "struct CrossAddress",205 "name": "to",205 "name": "to",206 "type": "tuple"206 "type": "tuple"207 },207 },230 { "internalType": "address", "name": "eth", "type": "address" },230 { "internalType": "address", "name": "eth", "type": "address" },231 { "internalType": "uint256", "name": "sub", "type": "uint256" }231 { "internalType": "uint256", "name": "sub", "type": "uint256" }232 ],232 ],233 "internalType": "struct EthCrossAccount",233 "internalType": "struct CrossAddress",234 "name": "from",234 "name": "from",235 "type": "tuple"235 "type": "tuple"236 },236 },239 { "internalType": "address", "name": "eth", "type": "address" },239 { "internalType": "address", "name": "eth", "type": "address" },240 { "internalType": "uint256", "name": "sub", "type": "uint256" }240 { "internalType": "uint256", "name": "sub", "type": "uint256" }241 ],241 ],242 "internalType": "struct EthCrossAccount",242 "internalType": "struct CrossAddress",243 "name": "to",243 "name": "to",244 "type": "tuple"244 "type": "tuple"245 },245 },tests/src/eth/api/ContractHelpers.soldiffbeforeafterboth69 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.69 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.70 /// @dev EVM selector for this function is: 0x766c4f37,70 /// @dev EVM selector for this function is: 0x766c4f37,71 /// or in textual repr: sponsor(address)71 /// or in textual repr: sponsor(address)72 function sponsor(address contractAddress) external view returns (EthCrossAccount memory);72 function sponsor(address contractAddress) external view returns (OptionCrossAddress memory);737374 /// Check tat contract has confirmed sponsor.74 /// Check tat contract has confirmed sponsor.75 ///75 ///939394 /// @dev EVM selector for this function is: 0xfde8a560,94 /// @dev EVM selector for this function is: 0xfde8a560,95 /// or in textual repr: setSponsoringMode(address,uint8)95 /// or in textual repr: setSponsoringMode(address,uint8)96 function setSponsoringMode(address contractAddress, uint8 mode) external;96 function setSponsoringMode(address contractAddress, SponsoringModeT mode) external;979798 /// Get current contract sponsoring rate limit98 /// Get current contract sponsoring rate limit99 /// @param contractAddress Contract to get sponsoring rate limit of99 /// @param contractAddress Contract to get sponsoring rate limit of171 function toggleAllowlist(address contractAddress, bool enabled) external;171 function toggleAllowlist(address contractAddress, bool enabled) external;172}172}173174/// Available contract sponsoring modes175enum SponsoringModeT {176 /// Sponsoring is disabled177 Disabled,178 /// Only users from allowlist will be sponsored179 Allowlisted,180 /// All users will be sponsored181 Generous182}183184/// Ethereum representation of Optional value with CrossAddress.185struct OptionCrossAddress {186 bool status;187 CrossAddress value;188}173189174/// @dev Cross account struct190/// Cross account struct175struct EthCrossAccount {191struct CrossAddress {176 address eth;192 address eth;177 uint256 sub;193 uint256 sub;178}194}tests/src/eth/api/UniqueFungible.soldiffbeforeafterboth13}13}141415/// @title A contract that allows you to work with collections.15/// @title A contract that allows you to work with collections.16/// @dev the ERC-165 identifier for this interface is 0x81172a7516/// @dev the ERC-165 identifier for this interface is 0x2a14cfd117interface Collection is Dummy, ERC165 {17interface Collection is Dummy, ERC165 {18 // /// Set collection property.18 // /// Set collection property.19 // ///19 // ///78 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.78 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.79 /// @dev EVM selector for this function is: 0x84a1d5a8,79 /// @dev EVM selector for this function is: 0x84a1d5a8,80 /// or in textual repr: setCollectionSponsorCross((address,uint256))80 /// or in textual repr: setCollectionSponsorCross((address,uint256))81 function setCollectionSponsorCross(EthCrossAccount memory sponsor) external;81 function setCollectionSponsorCross(CrossAddress memory sponsor) external;828283 /// Whether there is a pending sponsor.83 /// Whether there is a pending sponsor.84 /// @dev EVM selector for this function is: 0x058ac185,84 /// @dev EVM selector for this function is: 0x058ac185,102 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.102 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.103 /// @dev EVM selector for this function is: 0x6ec0a9f1,103 /// @dev EVM selector for this function is: 0x6ec0a9f1,104 /// or in textual repr: collectionSponsor()104 /// or in textual repr: collectionSponsor()105 function collectionSponsor() external view returns (EthCrossAccount memory);105 function collectionSponsor() external view returns (CrossAddress memory);106106107 /// Get current collection limits.107 /// Get current collection limits.108 ///108 ///109 /// @return Array of tuples (byte, bool, uint256) with limits and their values. Order of limits:109 /// @return Array of collection limits110 /// "accountTokenOwnershipLimit",111 /// "sponsoredDataSize",112 /// "sponsoredDataRateLimit",113 /// "tokenLimit",114 /// "sponsorTransferTimeout",115 /// "sponsorApproveTimeout"116 /// "ownerCanTransfer",117 /// "ownerCanDestroy",118 /// "transfersEnabled"119 /// Return `false` if a limit not set.120 /// @dev EVM selector for this function is: 0xf63bc572,110 /// @dev EVM selector for this function is: 0xf63bc572,121 /// or in textual repr: collectionLimits()111 /// or in textual repr: collectionLimits()122 function collectionLimits() external view returns (Tuple21[] memory);112 function collectionLimits() external view returns (CollectionLimit[] memory);123113124 /// Set limits for the collection.114 /// Set limits for the collection.125 /// @dev Throws error if limit not found.115 /// @dev Throws error if limit not found.126 /// @param limit Name of the limit. Valid names:127 /// "accountTokenOwnershipLimit",128 /// "sponsoredDataSize",129 /// "sponsoredDataRateLimit",130 /// "tokenLimit",131 /// "sponsorTransferTimeout",132 /// "sponsorApproveTimeout"133 /// "ownerCanTransfer",134 /// "ownerCanDestroy",135 /// "transfersEnabled"136 /// @param status enable\disable limit. Works only with `true`.137 /// @param value Value of the limit.116 /// @param limit Some limit.138 /// @dev EVM selector for this function is: 0x88150bd0,117 /// @dev EVM selector for this function is: 0x2316ee74,139 /// or in textual repr: setCollectionLimit(uint8,bool,uint256)118 /// or in textual repr: setCollectionLimit((uint8,(bool,uint256)))140 function setCollectionLimit(119 function setCollectionLimit(CollectionLimit memory limit) external;141 CollectionLimits limit,142 bool status,143 uint256 value144 ) external;145120146 /// Get contract address.121 /// Get contract address.152 /// @param newAdmin Cross account administrator address.127 /// @param newAdmin Cross account administrator address.153 /// @dev EVM selector for this function is: 0x859aa7d6,128 /// @dev EVM selector for this function is: 0x859aa7d6,154 /// or in textual repr: addCollectionAdminCross((address,uint256))129 /// or in textual repr: addCollectionAdminCross((address,uint256))155 function addCollectionAdminCross(EthCrossAccount memory newAdmin) external;130 function addCollectionAdminCross(CrossAddress memory newAdmin) external;156131157 /// Remove collection admin.132 /// Remove collection admin.158 /// @param admin Cross account administrator address.133 /// @param admin Cross account administrator address.159 /// @dev EVM selector for this function is: 0x6c0cd173,134 /// @dev EVM selector for this function is: 0x6c0cd173,160 /// or in textual repr: removeCollectionAdminCross((address,uint256))135 /// or in textual repr: removeCollectionAdminCross((address,uint256))161 function removeCollectionAdminCross(EthCrossAccount memory admin) external;136 function removeCollectionAdminCross(CrossAddress memory admin) external;162137163 // /// Add collection admin.138 // /// Add collection admin.164 // /// @param newAdmin Address of the added administrator.139 // /// @param newAdmin Address of the added administrator.191 /// Returns nesting for a collection166 /// Returns nesting for a collection192 /// @dev EVM selector for this function is: 0x22d25bfe,167 /// @dev EVM selector for this function is: 0x22d25bfe,193 /// or in textual repr: collectionNestingRestrictedCollectionIds()168 /// or in textual repr: collectionNestingRestrictedCollectionIds()194 function collectionNestingRestrictedCollectionIds() external view returns (Tuple26 memory);169 function collectionNestingRestrictedCollectionIds() external view returns (CollectionNesting memory);195170196 /// Returns permissions for a collection171 /// Returns permissions for a collection197 /// @dev EVM selector for this function is: 0x5b2eaf4b,172 /// @dev EVM selector for this function is: 0x5b2eaf4b,198 /// or in textual repr: collectionNestingPermissions()173 /// or in textual repr: collectionNestingPermissions()199 function collectionNestingPermissions() external view returns (Tuple29[] memory);174 function collectionNestingPermissions() external view returns (CollectionNestingPermission[] memory);200175201 /// Set the collection access method.176 /// Set the collection access method.202 /// @param mode Access mode177 /// @param mode Access mode211 /// @param user User address to check.186 /// @param user User address to check.212 /// @dev EVM selector for this function is: 0x91b6df49,187 /// @dev EVM selector for this function is: 0x91b6df49,213 /// or in textual repr: allowlistedCross((address,uint256))188 /// or in textual repr: allowlistedCross((address,uint256))214 function allowlistedCross(EthCrossAccount memory user) external view returns (bool);189 function allowlistedCross(CrossAddress memory user) external view returns (bool);215190216 // /// Add the user to the allowed list.191 // /// Add the user to the allowed list.217 // ///192 // ///225 /// @param user User cross account address.200 /// @param user User cross account address.226 /// @dev EVM selector for this function is: 0xa0184a3a,201 /// @dev EVM selector for this function is: 0xa0184a3a,227 /// or in textual repr: addToCollectionAllowListCross((address,uint256))202 /// or in textual repr: addToCollectionAllowListCross((address,uint256))228 function addToCollectionAllowListCross(EthCrossAccount memory user) external;203 function addToCollectionAllowListCross(CrossAddress memory user) external;229204230 // /// Remove the user from the allowed list.205 // /// Remove the user from the allowed list.231 // ///206 // ///239 /// @param user User cross account address.214 /// @param user User cross account address.240 /// @dev EVM selector for this function is: 0x09ba452a,215 /// @dev EVM selector for this function is: 0x09ba452a,241 /// or in textual repr: removeFromCollectionAllowListCross((address,uint256))216 /// or in textual repr: removeFromCollectionAllowListCross((address,uint256))242 function removeFromCollectionAllowListCross(EthCrossAccount memory user) external;217 function removeFromCollectionAllowListCross(CrossAddress memory user) external;243218244 /// Switch permission for minting.219 /// Switch permission for minting.245 ///220 ///262 /// @return "true" if account is the owner or admin237 /// @return "true" if account is the owner or admin263 /// @dev EVM selector for this function is: 0x3e75a905,238 /// @dev EVM selector for this function is: 0x3e75a905,264 /// or in textual repr: isOwnerOrAdminCross((address,uint256))239 /// or in textual repr: isOwnerOrAdminCross((address,uint256))265 function isOwnerOrAdminCross(EthCrossAccount memory user) external view returns (bool);240 function isOwnerOrAdminCross(CrossAddress memory user) external view returns (bool);266241267 /// Returns collection type242 /// Returns collection type268 ///243 ///277 /// If address is canonical then substrate mirror is zero and vice versa.252 /// If address is canonical then substrate mirror is zero and vice versa.278 /// @dev EVM selector for this function is: 0xdf727d3b,253 /// @dev EVM selector for this function is: 0xdf727d3b,279 /// or in textual repr: collectionOwner()254 /// or in textual repr: collectionOwner()280 function collectionOwner() external view returns (EthCrossAccount memory);255 function collectionOwner() external view returns (CrossAddress memory);281256282 // /// Changes collection owner to another account257 // /// Changes collection owner to another account283 // ///258 // ///293 /// If address is canonical then substrate mirror is zero and vice versa.268 /// If address is canonical then substrate mirror is zero and vice versa.294 /// @dev EVM selector for this function is: 0x5813216b,269 /// @dev EVM selector for this function is: 0x5813216b,295 /// or in textual repr: collectionAdmins()270 /// or in textual repr: collectionAdmins()296 function collectionAdmins() external view returns (EthCrossAccount[] memory);271 function collectionAdmins() external view returns (CrossAddress[] memory);297272298 /// Changes collection owner to another account273 /// Changes collection owner to another account299 ///274 ///300 /// @dev Owner can be changed only by current owner275 /// @dev Owner can be changed only by current owner301 /// @param newOwner new owner cross account276 /// @param newOwner new owner cross account302 /// @dev EVM selector for this function is: 0x6496c497,277 /// @dev EVM selector for this function is: 0x6496c497,303 /// or in textual repr: changeCollectionOwnerCross((address,uint256))278 /// or in textual repr: changeCollectionOwnerCross((address,uint256))304 function changeCollectionOwnerCross(EthCrossAccount memory newOwner) external;279 function changeCollectionOwnerCross(CrossAddress memory newOwner) external;305}280}306281307/// @dev Cross account struct282/// Cross account struct308struct EthCrossAccount {283struct CrossAddress {309 address eth;284 address eth;310 uint256 sub;285 uint256 sub;311}286}312287313/// @dev anonymous struct288/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.314struct Tuple29 {289struct CollectionNestingPermission {315 CollectionPermissions field_0;290 CollectionPermissionField field;316 bool field_1;291 bool value;317}292}318293294/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.319enum CollectionPermissions {295enum CollectionPermissionField {320 CollectionAdmin,296 /// Owner of token can nest tokens under it.321 TokenOwner297 TokenOwner,298 /// Admin of token collection can nest tokens under token.299 CollectionAdmin322}300}323301324/// @dev anonymous struct302/// Nested collections.325struct Tuple26 {303struct CollectionNesting {326 bool field_0;304 bool token_owner;327 uint256[] field_1;305 uint256[] ids;328}306}329307330/// @dev [`CollectionLimits`](up_data_structs::CollectionLimits) representation for EVM.308/// [`CollectionLimits`](up_data_structs::CollectionLimits) field representation for EVM.309struct CollectionLimit {310 CollectionLimitField field;311 OptionUint value;312}313314/// Ethereum representation of Optional value with uint256.315struct OptionUint {316 bool status;317 uint256 value;318}319320/// [`CollectionLimits`](up_data_structs::CollectionLimits) fields representation for EVM.331enum CollectionLimits {321enum CollectionLimitField {332 /// @dev How many tokens can a user have on one account.322 /// How many tokens can a user have on one account.333 AccountTokenOwnership,323 AccountTokenOwnership,334 /// @dev How many bytes of data are available for sponsorship.324 /// How many bytes of data are available for sponsorship.335 SponsoredDataSize,325 SponsoredDataSize,336 /// @dev In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]326 /// In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]337 SponsoredDataRateLimit,327 SponsoredDataRateLimit,338 /// @dev How many tokens can be mined into this collection.328 /// How many tokens can be mined into this collection.339 TokenLimit,329 TokenLimit,340 /// @dev Timeouts for transfer sponsoring.330 /// Timeouts for transfer sponsoring.341 SponsorTransferTimeout,331 SponsorTransferTimeout,342 /// @dev Timeout for sponsoring an approval in passed blocks.332 /// Timeout for sponsoring an approval in passed blocks.343 SponsorApproveTimeout,333 SponsorApproveTimeout,344 /// @dev Whether the collection owner of the collection can send tokens (which belong to other users).334 /// Whether the collection owner of the collection can send tokens (which belong to other users).345 OwnerCanTransfer,335 OwnerCanTransfer,346 /// @dev Can the collection owner burn other people's tokens.336 /// Can the collection owner burn other people's tokens.347 OwnerCanDestroy,337 OwnerCanDestroy,348 /// @dev Is it possible to send tokens from this collection between users.338 /// Is it possible to send tokens from this collection between users.349 TransferEnabled339 TransferEnabled350}340}351341352/// @dev anonymous struct342/// Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).353struct Tuple21 {354 CollectionLimits field_0;355 bool field_1;356 uint256 field_2;357}358359/// @dev Property struct360struct Property {343struct Property {361 string key;344 string key;362 bytes value;345 bytes value;371354372 /// @dev EVM selector for this function is: 0x269e6158,355 /// @dev EVM selector for this function is: 0x269e6158,373 /// or in textual repr: mintCross((address,uint256),uint256)356 /// or in textual repr: mintCross((address,uint256),uint256)374 function mintCross(EthCrossAccount memory to, uint256 amount) external returns (bool);357 function mintCross(CrossAddress memory to, uint256 amount) external returns (bool);375358376 /// @dev EVM selector for this function is: 0x0ecd0ab0,359 /// @dev EVM selector for this function is: 0x0ecd0ab0,377 /// or in textual repr: approveCross((address,uint256),uint256)360 /// or in textual repr: approveCross((address,uint256),uint256)378 function approveCross(EthCrossAccount memory spender, uint256 amount) external returns (bool);361 function approveCross(CrossAddress memory spender, uint256 amount) external returns (bool);379362380 // /// Burn tokens from account363 // /// Burn tokens from account381 // /// @dev Function that burns an `amount` of the tokens of a given account,364 // /// @dev Function that burns an `amount` of the tokens of a given account,393 /// @param amount The amount that will be burnt.376 /// @param amount The amount that will be burnt.394 /// @dev EVM selector for this function is: 0xbb2f5a58,377 /// @dev EVM selector for this function is: 0xbb2f5a58,395 /// or in textual repr: burnFromCross((address,uint256),uint256)378 /// or in textual repr: burnFromCross((address,uint256),uint256)396 function burnFromCross(EthCrossAccount memory from, uint256 amount) external returns (bool);379 function burnFromCross(CrossAddress memory from, uint256 amount) external returns (bool);397380398 /// Mint tokens for multiple accounts.381 /// Mint tokens for multiple accounts.399 /// @param amounts array of pairs of account address and amount382 /// @param amounts array of pairs of account address and amount403386404 /// @dev EVM selector for this function is: 0x2ada85ff,387 /// @dev EVM selector for this function is: 0x2ada85ff,405 /// or in textual repr: transferCross((address,uint256),uint256)388 /// or in textual repr: transferCross((address,uint256),uint256)406 function transferCross(EthCrossAccount memory to, uint256 amount) external returns (bool);389 function transferCross(CrossAddress memory to, uint256 amount) external returns (bool);407390408 /// @dev EVM selector for this function is: 0xd5cf430b,391 /// @dev EVM selector for this function is: 0xd5cf430b,409 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)392 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)410 function transferFromCross(393 function transferFromCross(411 EthCrossAccount memory from,394 CrossAddress memory from,412 EthCrossAccount memory to,395 CrossAddress memory to,413 uint256 amount396 uint256 amount414 ) external returns (bool);397 ) external returns (bool);415}398}tests/src/eth/api/UniqueNFT.soldiffbeforeafterboth30 /// @param permissions Permissions for keys.30 /// @param permissions Permissions for keys.31 /// @dev EVM selector for this function is: 0xbd92983a,31 /// @dev EVM selector for this function is: 0xbd92983a,32 /// or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])32 /// or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])33 function setTokenPropertyPermissions(Tuple53[] memory permissions) external;33 function setTokenPropertyPermissions(TokenPropertyPermission[] memory permissions) external;343435 /// @notice Get permissions for token properties.35 /// @notice Get permissions for token properties.36 /// @dev EVM selector for this function is: 0xf23d7790,36 /// @dev EVM selector for this function is: 0xf23d7790,37 /// or in textual repr: tokenPropertyPermissions()37 /// or in textual repr: tokenPropertyPermissions()38 function tokenPropertyPermissions() external view returns (Tuple53[] memory);38 function tokenPropertyPermissions() external view returns (TokenPropertyPermission[] memory);393940 // /// @notice Set token property value.40 // /// @notice Set token property value.41 // /// @dev Throws error if `msg.sender` has no permission to edit the property.41 // /// @dev Throws error if `msg.sender` has no permission to edit the property.80 function property(uint256 tokenId, string memory key) external view returns (bytes memory);80 function property(uint256 tokenId, string memory key) external view returns (bytes memory);81}81}828283/// @dev Property struct83/// Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).84struct Property {84struct Property {85 string key;85 string key;86 bytes value;86 bytes value;87}87}888889/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.89/// Ethereum representation of Token Property Permissions.90enum EthTokenPermissions {91 /// @dev Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]92 Mutable,93 /// @dev Change permission for the collection administrator. See [`up_data_structs::PropertyPermission::token_owner`]94 TokenOwner,95 /// @dev Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]96 CollectionAdmin97}9899/// @dev anonymous struct100struct Tuple53 {90struct TokenPropertyPermission {91 /// Token property key.101 string field_0;92 string key;93 /// Token property permissions.102 Tuple51[] field_1;94 PropertyPermission[] permissions;103}95}10496105/// @dev anonymous struct97/// Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) as an key and value.106struct Tuple51 {98struct PropertyPermission {99 /// TokenPermission field.107 EthTokenPermissions field_0;100 TokenPermissionField code;101 /// TokenPermission value.108 bool field_1;102 bool value;109}103}104105/// Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.106enum TokenPermissionField {107 /// Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]108 Mutable,109 /// Change permission for the collection administrator. See [`up_data_structs::PropertyPermission::token_owner`]110 TokenOwner,111 /// Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]112 CollectionAdmin113}110114111/// @title A contract that allows you to work with collections.115/// @title A contract that allows you to work with collections.112/// @dev the ERC-165 identifier for this interface is 0x81172a75116/// @dev the ERC-165 identifier for this interface is 0x2a14cfd1113interface Collection is Dummy, ERC165 {117interface Collection is Dummy, ERC165 {114 // /// Set collection property.118 // /// Set collection property.115 // ///119 // ///174 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.178 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.175 /// @dev EVM selector for this function is: 0x84a1d5a8,179 /// @dev EVM selector for this function is: 0x84a1d5a8,176 /// or in textual repr: setCollectionSponsorCross((address,uint256))180 /// or in textual repr: setCollectionSponsorCross((address,uint256))177 function setCollectionSponsorCross(EthCrossAccount memory sponsor) external;181 function setCollectionSponsorCross(CrossAddress memory sponsor) external;178182179 /// Whether there is a pending sponsor.183 /// Whether there is a pending sponsor.180 /// @dev EVM selector for this function is: 0x058ac185,184 /// @dev EVM selector for this function is: 0x058ac185,198 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.202 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.199 /// @dev EVM selector for this function is: 0x6ec0a9f1,203 /// @dev EVM selector for this function is: 0x6ec0a9f1,200 /// or in textual repr: collectionSponsor()204 /// or in textual repr: collectionSponsor()201 function collectionSponsor() external view returns (EthCrossAccount memory);205 function collectionSponsor() external view returns (CrossAddress memory);202206203 /// Get current collection limits.207 /// Get current collection limits.204 ///208 ///205 /// @return Array of tuples (byte, bool, uint256) with limits and their values. Order of limits:209 /// @return Array of collection limits206 /// "accountTokenOwnershipLimit",207 /// "sponsoredDataSize",208 /// "sponsoredDataRateLimit",209 /// "tokenLimit",210 /// "sponsorTransferTimeout",211 /// "sponsorApproveTimeout"212 /// "ownerCanTransfer",213 /// "ownerCanDestroy",214 /// "transfersEnabled"215 /// Return `false` if a limit not set.216 /// @dev EVM selector for this function is: 0xf63bc572,210 /// @dev EVM selector for this function is: 0xf63bc572,217 /// or in textual repr: collectionLimits()211 /// or in textual repr: collectionLimits()218 function collectionLimits() external view returns (Tuple31[] memory);212 function collectionLimits() external view returns (CollectionLimit[] memory);219213220 /// Set limits for the collection.214 /// Set limits for the collection.221 /// @dev Throws error if limit not found.215 /// @dev Throws error if limit not found.222 /// @param limit Name of the limit. Valid names:223 /// "accountTokenOwnershipLimit",224 /// "sponsoredDataSize",225 /// "sponsoredDataRateLimit",226 /// "tokenLimit",227 /// "sponsorTransferTimeout",228 /// "sponsorApproveTimeout"229 /// "ownerCanTransfer",230 /// "ownerCanDestroy",231 /// "transfersEnabled"232 /// @param status enable\disable limit. Works only with `true`.233 /// @param value Value of the limit.216 /// @param limit Some limit.234 /// @dev EVM selector for this function is: 0x88150bd0,217 /// @dev EVM selector for this function is: 0x2316ee74,235 /// or in textual repr: setCollectionLimit(uint8,bool,uint256)218 /// or in textual repr: setCollectionLimit((uint8,(bool,uint256)))236 function setCollectionLimit(219 function setCollectionLimit(CollectionLimit memory limit) external;237 CollectionLimits limit,238 bool status,239 uint256 value240 ) external;241220242 /// Get contract address.221 /// Get contract address.248 /// @param newAdmin Cross account administrator address.227 /// @param newAdmin Cross account administrator address.249 /// @dev EVM selector for this function is: 0x859aa7d6,228 /// @dev EVM selector for this function is: 0x859aa7d6,250 /// or in textual repr: addCollectionAdminCross((address,uint256))229 /// or in textual repr: addCollectionAdminCross((address,uint256))251 function addCollectionAdminCross(EthCrossAccount memory newAdmin) external;230 function addCollectionAdminCross(CrossAddress memory newAdmin) external;252231253 /// Remove collection admin.232 /// Remove collection admin.254 /// @param admin Cross account administrator address.233 /// @param admin Cross account administrator address.255 /// @dev EVM selector for this function is: 0x6c0cd173,234 /// @dev EVM selector for this function is: 0x6c0cd173,256 /// or in textual repr: removeCollectionAdminCross((address,uint256))235 /// or in textual repr: removeCollectionAdminCross((address,uint256))257 function removeCollectionAdminCross(EthCrossAccount memory admin) external;236 function removeCollectionAdminCross(CrossAddress memory admin) external;258237259 // /// Add collection admin.238 // /// Add collection admin.260 // /// @param newAdmin Address of the added administrator.239 // /// @param newAdmin Address of the added administrator.287 /// Returns nesting for a collection266 /// Returns nesting for a collection288 /// @dev EVM selector for this function is: 0x22d25bfe,267 /// @dev EVM selector for this function is: 0x22d25bfe,289 /// or in textual repr: collectionNestingRestrictedCollectionIds()268 /// or in textual repr: collectionNestingRestrictedCollectionIds()290 function collectionNestingRestrictedCollectionIds() external view returns (Tuple36 memory);269 function collectionNestingRestrictedCollectionIds() external view returns (CollectionNesting memory);291270292 /// Returns permissions for a collection271 /// Returns permissions for a collection293 /// @dev EVM selector for this function is: 0x5b2eaf4b,272 /// @dev EVM selector for this function is: 0x5b2eaf4b,294 /// or in textual repr: collectionNestingPermissions()273 /// or in textual repr: collectionNestingPermissions()295 function collectionNestingPermissions() external view returns (Tuple39[] memory);274 function collectionNestingPermissions() external view returns (CollectionNestingPermission[] memory);296275297 /// Set the collection access method.276 /// Set the collection access method.298 /// @param mode Access mode277 /// @param mode Access mode307 /// @param user User address to check.286 /// @param user User address to check.308 /// @dev EVM selector for this function is: 0x91b6df49,287 /// @dev EVM selector for this function is: 0x91b6df49,309 /// or in textual repr: allowlistedCross((address,uint256))288 /// or in textual repr: allowlistedCross((address,uint256))310 function allowlistedCross(EthCrossAccount memory user) external view returns (bool);289 function allowlistedCross(CrossAddress memory user) external view returns (bool);311290312 // /// Add the user to the allowed list.291 // /// Add the user to the allowed list.313 // ///292 // ///321 /// @param user User cross account address.300 /// @param user User cross account address.322 /// @dev EVM selector for this function is: 0xa0184a3a,301 /// @dev EVM selector for this function is: 0xa0184a3a,323 /// or in textual repr: addToCollectionAllowListCross((address,uint256))302 /// or in textual repr: addToCollectionAllowListCross((address,uint256))324 function addToCollectionAllowListCross(EthCrossAccount memory user) external;303 function addToCollectionAllowListCross(CrossAddress memory user) external;325304326 // /// Remove the user from the allowed list.305 // /// Remove the user from the allowed list.327 // ///306 // ///335 /// @param user User cross account address.314 /// @param user User cross account address.336 /// @dev EVM selector for this function is: 0x09ba452a,315 /// @dev EVM selector for this function is: 0x09ba452a,337 /// or in textual repr: removeFromCollectionAllowListCross((address,uint256))316 /// or in textual repr: removeFromCollectionAllowListCross((address,uint256))338 function removeFromCollectionAllowListCross(EthCrossAccount memory user) external;317 function removeFromCollectionAllowListCross(CrossAddress memory user) external;339318340 /// Switch permission for minting.319 /// Switch permission for minting.341 ///320 ///358 /// @return "true" if account is the owner or admin337 /// @return "true" if account is the owner or admin359 /// @dev EVM selector for this function is: 0x3e75a905,338 /// @dev EVM selector for this function is: 0x3e75a905,360 /// or in textual repr: isOwnerOrAdminCross((address,uint256))339 /// or in textual repr: isOwnerOrAdminCross((address,uint256))361 function isOwnerOrAdminCross(EthCrossAccount memory user) external view returns (bool);340 function isOwnerOrAdminCross(CrossAddress memory user) external view returns (bool);362341363 /// Returns collection type342 /// Returns collection type364 ///343 ///373 /// If address is canonical then substrate mirror is zero and vice versa.352 /// If address is canonical then substrate mirror is zero and vice versa.374 /// @dev EVM selector for this function is: 0xdf727d3b,353 /// @dev EVM selector for this function is: 0xdf727d3b,375 /// or in textual repr: collectionOwner()354 /// or in textual repr: collectionOwner()376 function collectionOwner() external view returns (EthCrossAccount memory);355 function collectionOwner() external view returns (CrossAddress memory);377356378 // /// Changes collection owner to another account357 // /// Changes collection owner to another account379 // ///358 // ///389 /// If address is canonical then substrate mirror is zero and vice versa.368 /// If address is canonical then substrate mirror is zero and vice versa.390 /// @dev EVM selector for this function is: 0x5813216b,369 /// @dev EVM selector for this function is: 0x5813216b,391 /// or in textual repr: collectionAdmins()370 /// or in textual repr: collectionAdmins()392 function collectionAdmins() external view returns (EthCrossAccount[] memory);371 function collectionAdmins() external view returns (CrossAddress[] memory);393372394 /// Changes collection owner to another account373 /// Changes collection owner to another account395 ///374 ///396 /// @dev Owner can be changed only by current owner375 /// @dev Owner can be changed only by current owner397 /// @param newOwner new owner cross account376 /// @param newOwner new owner cross account398 /// @dev EVM selector for this function is: 0x6496c497,377 /// @dev EVM selector for this function is: 0x6496c497,399 /// or in textual repr: changeCollectionOwnerCross((address,uint256))378 /// or in textual repr: changeCollectionOwnerCross((address,uint256))400 function changeCollectionOwnerCross(EthCrossAccount memory newOwner) external;379 function changeCollectionOwnerCross(CrossAddress memory newOwner) external;401}380}402381403/// @dev Cross account struct382/// Cross account struct404struct EthCrossAccount {383struct CrossAddress {405 address eth;384 address eth;406 uint256 sub;385 uint256 sub;407}386}408387409/// @dev anonymous struct388/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.410struct Tuple39 {389struct CollectionNestingPermission {411 CollectionPermissions field_0;390 CollectionPermissionField field;412 bool field_1;391 bool value;413}392}414393394/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.415enum CollectionPermissions {395enum CollectionPermissionField {416 CollectionAdmin,396 /// Owner of token can nest tokens under it.417 TokenOwner397 TokenOwner,398 /// Admin of token collection can nest tokens under token.399 CollectionAdmin418}400}419401420/// @dev anonymous struct402/// Nested collections.421struct Tuple36 {403struct CollectionNesting {422 bool field_0;404 bool token_owner;423 uint256[] field_1;405 uint256[] ids;424}406}425407426/// @dev [`CollectionLimits`](up_data_structs::CollectionLimits) representation for EVM.408/// [`CollectionLimits`](up_data_structs::CollectionLimits) field representation for EVM.409struct CollectionLimit {410 CollectionLimitField field;411 OptionUint value;412}413414/// Ethereum representation of Optional value with uint256.415struct OptionUint {416 bool status;417 uint256 value;418}419420/// [`CollectionLimits`](up_data_structs::CollectionLimits) fields representation for EVM.427enum CollectionLimits {421enum CollectionLimitField {428 /// @dev How many tokens can a user have on one account.422 /// How many tokens can a user have on one account.429 AccountTokenOwnership,423 AccountTokenOwnership,430 /// @dev How many bytes of data are available for sponsorship.424 /// How many bytes of data are available for sponsorship.431 SponsoredDataSize,425 SponsoredDataSize,432 /// @dev In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]426 /// In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]433 SponsoredDataRateLimit,427 SponsoredDataRateLimit,434 /// @dev How many tokens can be mined into this collection.428 /// How many tokens can be mined into this collection.435 TokenLimit,429 TokenLimit,436 /// @dev Timeouts for transfer sponsoring.430 /// Timeouts for transfer sponsoring.437 SponsorTransferTimeout,431 SponsorTransferTimeout,438 /// @dev Timeout for sponsoring an approval in passed blocks.432 /// Timeout for sponsoring an approval in passed blocks.439 SponsorApproveTimeout,433 SponsorApproveTimeout,440 /// @dev Whether the collection owner of the collection can send tokens (which belong to other users).434 /// Whether the collection owner of the collection can send tokens (which belong to other users).441 OwnerCanTransfer,435 OwnerCanTransfer,442 /// @dev Can the collection owner burn other people's tokens.436 /// Can the collection owner burn other people's tokens.443 OwnerCanDestroy,437 OwnerCanDestroy,444 /// @dev Is it possible to send tokens from this collection between users.438 /// Is it possible to send tokens from this collection between users.445 TransferEnabled439 TransferEnabled446}440}447448/// @dev anonymous struct449struct Tuple31 {450 CollectionLimits field_0;451 bool field_1;452 uint256 field_2;453}454441455/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension442/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension456/// @dev See https://eips.ethereum.org/EIPS/eip-721443/// @dev See https://eips.ethereum.org/EIPS/eip-721569 /// @param tokenId Id for the token.556 /// @param tokenId Id for the token.570 /// @dev EVM selector for this function is: 0x2b29dace,557 /// @dev EVM selector for this function is: 0x2b29dace,571 /// or in textual repr: crossOwnerOf(uint256)558 /// or in textual repr: crossOwnerOf(uint256)572 function crossOwnerOf(uint256 tokenId) external view returns (EthCrossAccount memory);559 function crossOwnerOf(uint256 tokenId) external view returns (CrossAddress memory);573560574 /// Returns the token properties.561 /// Returns the token properties.575 ///562 ///588 /// @param tokenId The NFT to approve575 /// @param tokenId The NFT to approve589 /// @dev EVM selector for this function is: 0x0ecd0ab0,576 /// @dev EVM selector for this function is: 0x0ecd0ab0,590 /// or in textual repr: approveCross((address,uint256),uint256)577 /// or in textual repr: approveCross((address,uint256),uint256)591 function approveCross(EthCrossAccount memory approved, uint256 tokenId) external;578 function approveCross(CrossAddress memory approved, uint256 tokenId) external;592579593 /// @notice Transfer ownership of an NFT580 /// @notice Transfer ownership of an NFT594 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`581 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`606 /// @param tokenId The NFT to transfer593 /// @param tokenId The NFT to transfer607 /// @dev EVM selector for this function is: 0x2ada85ff,594 /// @dev EVM selector for this function is: 0x2ada85ff,608 /// or in textual repr: transferCross((address,uint256),uint256)595 /// or in textual repr: transferCross((address,uint256),uint256)609 function transferCross(EthCrossAccount memory to, uint256 tokenId) external;596 function transferCross(CrossAddress memory to, uint256 tokenId) external;610597611 /// @notice Transfer ownership of an NFT from cross account address to cross account address598 /// @notice Transfer ownership of an NFT from cross account address to cross account address612 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`599 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`617 /// @dev EVM selector for this function is: 0xd5cf430b,604 /// @dev EVM selector for this function is: 0xd5cf430b,618 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)605 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)619 function transferFromCross(606 function transferFromCross(620 EthCrossAccount memory from,607 CrossAddress memory from,621 EthCrossAccount memory to,608 CrossAddress memory to,622 uint256 tokenId609 uint256 tokenId623 ) external;610 ) external;624611640 /// @param tokenId The NFT to transfer627 /// @param tokenId The NFT to transfer641 /// @dev EVM selector for this function is: 0xbb2f5a58,628 /// @dev EVM selector for this function is: 0xbb2f5a58,642 /// or in textual repr: burnFromCross((address,uint256),uint256)629 /// or in textual repr: burnFromCross((address,uint256),uint256)643 function burnFromCross(EthCrossAccount memory from, uint256 tokenId) external;630 function burnFromCross(CrossAddress memory from, uint256 tokenId) external;644631645 /// @notice Returns next free NFT ID.632 /// @notice Returns next free NFT ID.646 /// @dev EVM selector for this function is: 0x75794a3c,633 /// @dev EVM selector for this function is: 0x75794a3c,671 /// @return uint256 The id of the newly minted token658 /// @return uint256 The id of the newly minted token672 /// @dev EVM selector for this function is: 0xb904db03,659 /// @dev EVM selector for this function is: 0xb904db03,673 /// or in textual repr: mintCross((address,uint256),(string,bytes)[])660 /// or in textual repr: mintCross((address,uint256),(string,bytes)[])674 function mintCross(EthCrossAccount memory to, Property[] memory properties) external returns (uint256);661 function mintCross(CrossAddress memory to, Property[] memory properties) external returns (uint256);675}662}676663677/// @dev anonymous struct664/// @dev anonymous structtests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth30 /// @param permissions Permissions for keys.30 /// @param permissions Permissions for keys.31 /// @dev EVM selector for this function is: 0xbd92983a,31 /// @dev EVM selector for this function is: 0xbd92983a,32 /// or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])32 /// or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])33 function setTokenPropertyPermissions(Tuple52[] memory permissions) external;33 function setTokenPropertyPermissions(TokenPropertyPermission[] memory permissions) external;343435 /// @notice Get permissions for token properties.35 /// @notice Get permissions for token properties.36 /// @dev EVM selector for this function is: 0xf23d7790,36 /// @dev EVM selector for this function is: 0xf23d7790,37 /// or in textual repr: tokenPropertyPermissions()37 /// or in textual repr: tokenPropertyPermissions()38 function tokenPropertyPermissions() external view returns (Tuple52[] memory);38 function tokenPropertyPermissions() external view returns (TokenPropertyPermission[] memory);393940 // /// @notice Set token property value.40 // /// @notice Set token property value.41 // /// @dev Throws error if `msg.sender` has no permission to edit the property.41 // /// @dev Throws error if `msg.sender` has no permission to edit the property.80 function property(uint256 tokenId, string memory key) external view returns (bytes memory);80 function property(uint256 tokenId, string memory key) external view returns (bytes memory);81}81}828283/// @dev Property struct83/// Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).84struct Property {84struct Property {85 string key;85 string key;86 bytes value;86 bytes value;87}87}888889/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.89/// Ethereum representation of Token Property Permissions.90enum EthTokenPermissions {91 /// @dev Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]92 Mutable,93 /// @dev Change permission for the collection administrator. See [`up_data_structs::PropertyPermission::token_owner`]94 TokenOwner,95 /// @dev Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]96 CollectionAdmin97}9899/// @dev anonymous struct100struct Tuple52 {90struct TokenPropertyPermission {91 /// Token property key.101 string field_0;92 string key;93 /// Token property permissions.102 Tuple50[] field_1;94 PropertyPermission[] permissions;103}95}10496105/// @dev anonymous struct97/// Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) as an key and value.106struct Tuple50 {98struct PropertyPermission {99 /// TokenPermission field.107 EthTokenPermissions field_0;100 TokenPermissionField code;101 /// TokenPermission value.108 bool field_1;102 bool value;109}103}104105/// Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.106enum TokenPermissionField {107 /// Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]108 Mutable,109 /// Change permission for the collection administrator. See [`up_data_structs::PropertyPermission::token_owner`]110 TokenOwner,111 /// Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]112 CollectionAdmin113}110114111/// @title A contract that allows you to work with collections.115/// @title A contract that allows you to work with collections.112/// @dev the ERC-165 identifier for this interface is 0x81172a75116/// @dev the ERC-165 identifier for this interface is 0x2a14cfd1113interface Collection is Dummy, ERC165 {117interface Collection is Dummy, ERC165 {114 // /// Set collection property.118 // /// Set collection property.115 // ///119 // ///174 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.178 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.175 /// @dev EVM selector for this function is: 0x84a1d5a8,179 /// @dev EVM selector for this function is: 0x84a1d5a8,176 /// or in textual repr: setCollectionSponsorCross((address,uint256))180 /// or in textual repr: setCollectionSponsorCross((address,uint256))177 function setCollectionSponsorCross(EthCrossAccount memory sponsor) external;181 function setCollectionSponsorCross(CrossAddress memory sponsor) external;178182179 /// Whether there is a pending sponsor.183 /// Whether there is a pending sponsor.180 /// @dev EVM selector for this function is: 0x058ac185,184 /// @dev EVM selector for this function is: 0x058ac185,198 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.202 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.199 /// @dev EVM selector for this function is: 0x6ec0a9f1,203 /// @dev EVM selector for this function is: 0x6ec0a9f1,200 /// or in textual repr: collectionSponsor()204 /// or in textual repr: collectionSponsor()201 function collectionSponsor() external view returns (EthCrossAccount memory);205 function collectionSponsor() external view returns (CrossAddress memory);202206203 /// Get current collection limits.207 /// Get current collection limits.204 ///208 ///205 /// @return Array of tuples (byte, bool, uint256) with limits and their values. Order of limits:209 /// @return Array of collection limits206 /// "accountTokenOwnershipLimit",207 /// "sponsoredDataSize",208 /// "sponsoredDataRateLimit",209 /// "tokenLimit",210 /// "sponsorTransferTimeout",211 /// "sponsorApproveTimeout"212 /// "ownerCanTransfer",213 /// "ownerCanDestroy",214 /// "transfersEnabled"215 /// Return `false` if a limit not set.216 /// @dev EVM selector for this function is: 0xf63bc572,210 /// @dev EVM selector for this function is: 0xf63bc572,217 /// or in textual repr: collectionLimits()211 /// or in textual repr: collectionLimits()218 function collectionLimits() external view returns (Tuple30[] memory);212 function collectionLimits() external view returns (CollectionLimit[] memory);219213220 /// Set limits for the collection.214 /// Set limits for the collection.221 /// @dev Throws error if limit not found.215 /// @dev Throws error if limit not found.222 /// @param limit Name of the limit. Valid names:223 /// "accountTokenOwnershipLimit",224 /// "sponsoredDataSize",225 /// "sponsoredDataRateLimit",226 /// "tokenLimit",227 /// "sponsorTransferTimeout",228 /// "sponsorApproveTimeout"229 /// "ownerCanTransfer",230 /// "ownerCanDestroy",231 /// "transfersEnabled"232 /// @param status enable\disable limit. Works only with `true`.233 /// @param value Value of the limit.216 /// @param limit Some limit.234 /// @dev EVM selector for this function is: 0x88150bd0,217 /// @dev EVM selector for this function is: 0x2316ee74,235 /// or in textual repr: setCollectionLimit(uint8,bool,uint256)218 /// or in textual repr: setCollectionLimit((uint8,(bool,uint256)))236 function setCollectionLimit(219 function setCollectionLimit(CollectionLimit memory limit) external;237 CollectionLimits limit,238 bool status,239 uint256 value240 ) external;241220242 /// Get contract address.221 /// Get contract address.248 /// @param newAdmin Cross account administrator address.227 /// @param newAdmin Cross account administrator address.249 /// @dev EVM selector for this function is: 0x859aa7d6,228 /// @dev EVM selector for this function is: 0x859aa7d6,250 /// or in textual repr: addCollectionAdminCross((address,uint256))229 /// or in textual repr: addCollectionAdminCross((address,uint256))251 function addCollectionAdminCross(EthCrossAccount memory newAdmin) external;230 function addCollectionAdminCross(CrossAddress memory newAdmin) external;252231253 /// Remove collection admin.232 /// Remove collection admin.254 /// @param admin Cross account administrator address.233 /// @param admin Cross account administrator address.255 /// @dev EVM selector for this function is: 0x6c0cd173,234 /// @dev EVM selector for this function is: 0x6c0cd173,256 /// or in textual repr: removeCollectionAdminCross((address,uint256))235 /// or in textual repr: removeCollectionAdminCross((address,uint256))257 function removeCollectionAdminCross(EthCrossAccount memory admin) external;236 function removeCollectionAdminCross(CrossAddress memory admin) external;258237259 // /// Add collection admin.238 // /// Add collection admin.260 // /// @param newAdmin Address of the added administrator.239 // /// @param newAdmin Address of the added administrator.287 /// Returns nesting for a collection266 /// Returns nesting for a collection288 /// @dev EVM selector for this function is: 0x22d25bfe,267 /// @dev EVM selector for this function is: 0x22d25bfe,289 /// or in textual repr: collectionNestingRestrictedCollectionIds()268 /// or in textual repr: collectionNestingRestrictedCollectionIds()290 function collectionNestingRestrictedCollectionIds() external view returns (Tuple35 memory);269 function collectionNestingRestrictedCollectionIds() external view returns (CollectionNesting memory);291270292 /// Returns permissions for a collection271 /// Returns permissions for a collection293 /// @dev EVM selector for this function is: 0x5b2eaf4b,272 /// @dev EVM selector for this function is: 0x5b2eaf4b,294 /// or in textual repr: collectionNestingPermissions()273 /// or in textual repr: collectionNestingPermissions()295 function collectionNestingPermissions() external view returns (Tuple38[] memory);274 function collectionNestingPermissions() external view returns (CollectionNestingPermission[] memory);296275297 /// Set the collection access method.276 /// Set the collection access method.298 /// @param mode Access mode277 /// @param mode Access mode307 /// @param user User address to check.286 /// @param user User address to check.308 /// @dev EVM selector for this function is: 0x91b6df49,287 /// @dev EVM selector for this function is: 0x91b6df49,309 /// or in textual repr: allowlistedCross((address,uint256))288 /// or in textual repr: allowlistedCross((address,uint256))310 function allowlistedCross(EthCrossAccount memory user) external view returns (bool);289 function allowlistedCross(CrossAddress memory user) external view returns (bool);311290312 // /// Add the user to the allowed list.291 // /// Add the user to the allowed list.313 // ///292 // ///321 /// @param user User cross account address.300 /// @param user User cross account address.322 /// @dev EVM selector for this function is: 0xa0184a3a,301 /// @dev EVM selector for this function is: 0xa0184a3a,323 /// or in textual repr: addToCollectionAllowListCross((address,uint256))302 /// or in textual repr: addToCollectionAllowListCross((address,uint256))324 function addToCollectionAllowListCross(EthCrossAccount memory user) external;303 function addToCollectionAllowListCross(CrossAddress memory user) external;325304326 // /// Remove the user from the allowed list.305 // /// Remove the user from the allowed list.327 // ///306 // ///335 /// @param user User cross account address.314 /// @param user User cross account address.336 /// @dev EVM selector for this function is: 0x09ba452a,315 /// @dev EVM selector for this function is: 0x09ba452a,337 /// or in textual repr: removeFromCollectionAllowListCross((address,uint256))316 /// or in textual repr: removeFromCollectionAllowListCross((address,uint256))338 function removeFromCollectionAllowListCross(EthCrossAccount memory user) external;317 function removeFromCollectionAllowListCross(CrossAddress memory user) external;339318340 /// Switch permission for minting.319 /// Switch permission for minting.341 ///320 ///358 /// @return "true" if account is the owner or admin337 /// @return "true" if account is the owner or admin359 /// @dev EVM selector for this function is: 0x3e75a905,338 /// @dev EVM selector for this function is: 0x3e75a905,360 /// or in textual repr: isOwnerOrAdminCross((address,uint256))339 /// or in textual repr: isOwnerOrAdminCross((address,uint256))361 function isOwnerOrAdminCross(EthCrossAccount memory user) external view returns (bool);340 function isOwnerOrAdminCross(CrossAddress memory user) external view returns (bool);362341363 /// Returns collection type342 /// Returns collection type364 ///343 ///373 /// If address is canonical then substrate mirror is zero and vice versa.352 /// If address is canonical then substrate mirror is zero and vice versa.374 /// @dev EVM selector for this function is: 0xdf727d3b,353 /// @dev EVM selector for this function is: 0xdf727d3b,375 /// or in textual repr: collectionOwner()354 /// or in textual repr: collectionOwner()376 function collectionOwner() external view returns (EthCrossAccount memory);355 function collectionOwner() external view returns (CrossAddress memory);377356378 // /// Changes collection owner to another account357 // /// Changes collection owner to another account379 // ///358 // ///389 /// If address is canonical then substrate mirror is zero and vice versa.368 /// If address is canonical then substrate mirror is zero and vice versa.390 /// @dev EVM selector for this function is: 0x5813216b,369 /// @dev EVM selector for this function is: 0x5813216b,391 /// or in textual repr: collectionAdmins()370 /// or in textual repr: collectionAdmins()392 function collectionAdmins() external view returns (EthCrossAccount[] memory);371 function collectionAdmins() external view returns (CrossAddress[] memory);393372394 /// Changes collection owner to another account373 /// Changes collection owner to another account395 ///374 ///396 /// @dev Owner can be changed only by current owner375 /// @dev Owner can be changed only by current owner397 /// @param newOwner new owner cross account376 /// @param newOwner new owner cross account398 /// @dev EVM selector for this function is: 0x6496c497,377 /// @dev EVM selector for this function is: 0x6496c497,399 /// or in textual repr: changeCollectionOwnerCross((address,uint256))378 /// or in textual repr: changeCollectionOwnerCross((address,uint256))400 function changeCollectionOwnerCross(EthCrossAccount memory newOwner) external;379 function changeCollectionOwnerCross(CrossAddress memory newOwner) external;401}380}402381403/// @dev Cross account struct382/// Cross account struct404struct EthCrossAccount {383struct CrossAddress {405 address eth;384 address eth;406 uint256 sub;385 uint256 sub;407}386}408387409/// @dev anonymous struct388/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.410struct Tuple38 {389struct CollectionNestingPermission {411 CollectionPermissions field_0;390 CollectionPermissionField field;412 bool field_1;391 bool value;413}392}414393394/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) fields as an enumeration.415enum CollectionPermissions {395enum CollectionPermissionField {416 CollectionAdmin,396 /// Owner of token can nest tokens under it.417 TokenOwner397 TokenOwner,398 /// Admin of token collection can nest tokens under token.399 CollectionAdmin418}400}419401420/// @dev anonymous struct402/// Nested collections.421struct Tuple35 {403struct CollectionNesting {422 bool field_0;404 bool token_owner;423 uint256[] field_1;405 uint256[] ids;424}406}425407426/// @dev [`CollectionLimits`](up_data_structs::CollectionLimits) representation for EVM.408/// [`CollectionLimits`](up_data_structs::CollectionLimits) field representation for EVM.409struct CollectionLimit {410 CollectionLimitField field;411 OptionUint value;412}413414/// Ethereum representation of Optional value with uint256.415struct OptionUint {416 bool status;417 uint256 value;418}419420/// [`CollectionLimits`](up_data_structs::CollectionLimits) fields representation for EVM.427enum CollectionLimits {421enum CollectionLimitField {428 /// @dev How many tokens can a user have on one account.422 /// How many tokens can a user have on one account.429 AccountTokenOwnership,423 AccountTokenOwnership,430 /// @dev How many bytes of data are available for sponsorship.424 /// How many bytes of data are available for sponsorship.431 SponsoredDataSize,425 SponsoredDataSize,432 /// @dev In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]426 /// In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]433 SponsoredDataRateLimit,427 SponsoredDataRateLimit,434 /// @dev How many tokens can be mined into this collection.428 /// How many tokens can be mined into this collection.435 TokenLimit,429 TokenLimit,436 /// @dev Timeouts for transfer sponsoring.430 /// Timeouts for transfer sponsoring.437 SponsorTransferTimeout,431 SponsorTransferTimeout,438 /// @dev Timeout for sponsoring an approval in passed blocks.432 /// Timeout for sponsoring an approval in passed blocks.439 SponsorApproveTimeout,433 SponsorApproveTimeout,440 /// @dev Whether the collection owner of the collection can send tokens (which belong to other users).434 /// Whether the collection owner of the collection can send tokens (which belong to other users).441 OwnerCanTransfer,435 OwnerCanTransfer,442 /// @dev Can the collection owner burn other people's tokens.436 /// Can the collection owner burn other people's tokens.443 OwnerCanDestroy,437 OwnerCanDestroy,444 /// @dev Is it possible to send tokens from this collection between users.438 /// Is it possible to send tokens from this collection between users.445 TransferEnabled439 TransferEnabled446}440}447448/// @dev anonymous struct449struct Tuple30 {450 CollectionLimits field_0;451 bool field_1;452 uint256 field_2;453}454441455/// @dev the ERC-165 identifier for this interface is 0x5b5e139f442/// @dev the ERC-165 identifier for this interface is 0x5b5e139f456interface ERC721Metadata is Dummy, ERC165 {443interface ERC721Metadata is Dummy, ERC165 {567 /// @param tokenId Id for the token.554 /// @param tokenId Id for the token.568 /// @dev EVM selector for this function is: 0x2b29dace,555 /// @dev EVM selector for this function is: 0x2b29dace,569 /// or in textual repr: crossOwnerOf(uint256)556 /// or in textual repr: crossOwnerOf(uint256)570 function crossOwnerOf(uint256 tokenId) external view returns (EthCrossAccount memory);557 function crossOwnerOf(uint256 tokenId) external view returns (CrossAddress memory);571558572 /// Returns the token properties.559 /// Returns the token properties.573 ///560 ///596 /// @param tokenId The RFT to transfer583 /// @param tokenId The RFT to transfer597 /// @dev EVM selector for this function is: 0x2ada85ff,584 /// @dev EVM selector for this function is: 0x2ada85ff,598 /// or in textual repr: transferCross((address,uint256),uint256)585 /// or in textual repr: transferCross((address,uint256),uint256)599 function transferCross(EthCrossAccount memory to, uint256 tokenId) external;586 function transferCross(CrossAddress memory to, uint256 tokenId) external;600587601 /// @notice Transfer ownership of an RFT588 /// @notice Transfer ownership of an RFT602 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`589 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`607 /// @dev EVM selector for this function is: 0xd5cf430b,594 /// @dev EVM selector for this function is: 0xd5cf430b,608 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)595 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)609 function transferFromCross(596 function transferFromCross(610 EthCrossAccount memory from,597 CrossAddress memory from,611 EthCrossAccount memory to,598 CrossAddress memory to,612 uint256 tokenId599 uint256 tokenId613 ) external;600 ) external;614601632 /// @param tokenId The RFT to transfer619 /// @param tokenId The RFT to transfer633 /// @dev EVM selector for this function is: 0xbb2f5a58,620 /// @dev EVM selector for this function is: 0xbb2f5a58,634 /// or in textual repr: burnFromCross((address,uint256),uint256)621 /// or in textual repr: burnFromCross((address,uint256),uint256)635 function burnFromCross(EthCrossAccount memory from, uint256 tokenId) external;622 function burnFromCross(CrossAddress memory from, uint256 tokenId) external;636623637 /// @notice Returns next free RFT ID.624 /// @notice Returns next free RFT ID.638 /// @dev EVM selector for this function is: 0x75794a3c,625 /// @dev EVM selector for this function is: 0x75794a3c,663 /// @return uint256 The id of the newly minted token650 /// @return uint256 The id of the newly minted token664 /// @dev EVM selector for this function is: 0xb904db03,651 /// @dev EVM selector for this function is: 0xb904db03,665 /// or in textual repr: mintCross((address,uint256),(string,bytes)[])652 /// or in textual repr: mintCross((address,uint256),(string,bytes)[])666 function mintCross(EthCrossAccount memory to, Property[] memory properties) external returns (uint256);653 function mintCross(CrossAddress memory to, Property[] memory properties) external returns (uint256);667654668 /// Returns EVM address for refungible token655 /// Returns EVM address for refungible token669 ///656 ///tests/src/eth/api/UniqueRefungibleToken.soldiffbeforeafterboth39 /// @param amount The amount that will be burnt.39 /// @param amount The amount that will be burnt.40 /// @dev EVM selector for this function is: 0xbb2f5a58,40 /// @dev EVM selector for this function is: 0xbb2f5a58,41 /// or in textual repr: burnFromCross((address,uint256),uint256)41 /// or in textual repr: burnFromCross((address,uint256),uint256)42 function burnFromCross(EthCrossAccount memory from, uint256 amount) external returns (bool);42 function burnFromCross(CrossAddress memory from, uint256 amount) external returns (bool);434344 /// @dev Approve the passed address to spend the specified amount of tokens on behalf of `msg.sender`.44 /// @dev Approve the passed address to spend the specified amount of tokens on behalf of `msg.sender`.45 /// Beware that changing an allowance with this method brings the risk that someone may use both the old45 /// Beware that changing an allowance with this method brings the risk that someone may use both the old50 /// @param amount The amount of tokens to be spent.50 /// @param amount The amount of tokens to be spent.51 /// @dev EVM selector for this function is: 0x0ecd0ab0,51 /// @dev EVM selector for this function is: 0x0ecd0ab0,52 /// or in textual repr: approveCross((address,uint256),uint256)52 /// or in textual repr: approveCross((address,uint256),uint256)53 function approveCross(EthCrossAccount memory spender, uint256 amount) external returns (bool);53 function approveCross(CrossAddress memory spender, uint256 amount) external returns (bool);545455 /// @dev Function that changes total amount of the tokens.55 /// @dev Function that changes total amount of the tokens.56 /// Throws if `msg.sender` doesn't owns all of the tokens.56 /// Throws if `msg.sender` doesn't owns all of the tokens.64 /// @param amount The amount to be transferred.64 /// @param amount The amount to be transferred.65 /// @dev EVM selector for this function is: 0x2ada85ff,65 /// @dev EVM selector for this function is: 0x2ada85ff,66 /// or in textual repr: transferCross((address,uint256),uint256)66 /// or in textual repr: transferCross((address,uint256),uint256)67 function transferCross(EthCrossAccount memory to, uint256 amount) external returns (bool);67 function transferCross(CrossAddress memory to, uint256 amount) external returns (bool);686869 /// @dev Transfer tokens from one address to another69 /// @dev Transfer tokens from one address to another70 /// @param from The address which you want to send tokens from70 /// @param from The address which you want to send tokens from73 /// @dev EVM selector for this function is: 0xd5cf430b,73 /// @dev EVM selector for this function is: 0xd5cf430b,74 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)74 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)75 function transferFromCross(75 function transferFromCross(76 EthCrossAccount memory from,76 CrossAddress memory from,77 EthCrossAccount memory to,77 CrossAddress memory to,78 uint256 amount78 uint256 amount79 ) external returns (bool);79 ) external returns (bool);80}80}818182/// @dev Cross account struct82/// Cross account struct83struct EthCrossAccount {83struct CrossAddress {84 address eth;84 address eth;85 uint256 sub;85 uint256 sub;86}86}tests/src/eth/collectionLimits.test.tsdiffbeforeafterboth1import {IKeyringPair} from '@polkadot/types/types';1import {IKeyringPair} from '@polkadot/types/types';2import {Pallets} from '../util';2import {Pallets} from '../util';3import {expect, itEth, usingEthPlaygrounds} from './util';3import {expect, itEth, usingEthPlaygrounds} from './util';4import {CollectionLimits} from './util/playgrounds/types';4import {CollectionLimitField} from './util/playgrounds/types';55667describe('Can set collection limits', () => {7describe('Can set collection limits', () => {46 };46 };474748 const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, testCase.case, owner);48 const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, testCase.case, owner);49 await collectionEvm.methods.setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, limits.accountTokenOwnershipLimit).send();49 await collectionEvm.methods.setCollectionLimit({field: CollectionLimitField.AccountTokenOwnership, value: {status: true, value: limits.accountTokenOwnershipLimit}}).send();50 await collectionEvm.methods.setCollectionLimit(CollectionLimits.SponsoredDataSize, true, limits.sponsoredDataSize).send();50 await collectionEvm.methods.setCollectionLimit({field: CollectionLimitField.SponsoredDataSize, value: {status: true, value: limits.sponsoredDataSize}}).send();51 await collectionEvm.methods.setCollectionLimit(CollectionLimits.SponsoredDataRateLimit, true, limits.sponsoredDataRateLimit).send();51 await collectionEvm.methods.setCollectionLimit({field: CollectionLimitField.SponsoredDataRateLimit, value: {status: true, value: limits.sponsoredDataRateLimit}}).send();52 await collectionEvm.methods.setCollectionLimit(CollectionLimits.TokenLimit, true, limits.tokenLimit).send();52 await collectionEvm.methods.setCollectionLimit({field: CollectionLimitField.TokenLimit, value: {status: true, value: limits.tokenLimit}}).send();53 await collectionEvm.methods.setCollectionLimit(CollectionLimits.SponsorTransferTimeout, true, limits.sponsorTransferTimeout).send();53 await collectionEvm.methods.setCollectionLimit({field: CollectionLimitField.SponsorTransferTimeout, value: {status: true, value: limits.sponsorTransferTimeout}}).send();54 await collectionEvm.methods.setCollectionLimit(CollectionLimits.SponsorApproveTimeout, true, limits.sponsorApproveTimeout).send();54 await collectionEvm.methods.setCollectionLimit({field: CollectionLimitField.SponsorApproveTimeout, value: {status: true, value: limits.sponsorApproveTimeout}}).send();55 await collectionEvm.methods.setCollectionLimit(CollectionLimits.OwnerCanTransfer, true, limits.ownerCanTransfer).send();55 await collectionEvm.methods.setCollectionLimit({field: CollectionLimitField.OwnerCanTransfer, value: {status: true, value: limits.ownerCanTransfer}}).send();56 await collectionEvm.methods.setCollectionLimit(CollectionLimits.OwnerCanDestroy, true, limits.ownerCanDestroy).send();56 await collectionEvm.methods.setCollectionLimit({field: CollectionLimitField.OwnerCanDestroy, value: {status: true, value: limits.ownerCanDestroy}}).send();57 await collectionEvm.methods.setCollectionLimit(CollectionLimits.TransferEnabled, true, limits.transfersEnabled).send();57 await collectionEvm.methods.setCollectionLimit({field: CollectionLimitField.TransferEnabled, value: {status: true, value: limits.transfersEnabled}}).send();585859 // Check limits from sub:59 // Check limits from sub:60 const data = (await helper.rft.getData(collectionId))!;60 const data = (await helper.rft.getData(collectionId))!;63 // Check limits from eth:63 // Check limits from eth:64 const limitsEvm = await collectionEvm.methods.collectionLimits().call({from: owner});64 const limitsEvm = await collectionEvm.methods.collectionLimits().call({from: owner});65 expect(limitsEvm).to.have.length(9);65 expect(limitsEvm).to.have.length(9);66 expect(limitsEvm[0]).to.deep.eq([CollectionLimits.AccountTokenOwnership.toString(), true, limits.accountTokenOwnershipLimit.toString()]);66 expect(limitsEvm[0]).to.deep.eq([CollectionLimitField.AccountTokenOwnership.toString(), [true, limits.accountTokenOwnershipLimit.toString()]]);67 expect(limitsEvm[1]).to.deep.eq([CollectionLimits.SponsoredDataSize.toString(), true, limits.sponsoredDataSize.toString()]);67 expect(limitsEvm[1]).to.deep.eq([CollectionLimitField.SponsoredDataSize.toString(), [true, limits.sponsoredDataSize.toString()]]);68 expect(limitsEvm[2]).to.deep.eq([CollectionLimits.SponsoredDataRateLimit.toString(), true, limits.sponsoredDataRateLimit.toString()]);68 expect(limitsEvm[2]).to.deep.eq([CollectionLimitField.SponsoredDataRateLimit.toString(), [true, limits.sponsoredDataRateLimit.toString()]]);69 expect(limitsEvm[3]).to.deep.eq([CollectionLimits.TokenLimit.toString(), true, limits.tokenLimit.toString()]);69 expect(limitsEvm[3]).to.deep.eq([CollectionLimitField.TokenLimit.toString(), [true, limits.tokenLimit.toString()]]);70 expect(limitsEvm[4]).to.deep.eq([CollectionLimits.SponsorTransferTimeout.toString(), true, limits.sponsorTransferTimeout.toString()]);70 expect(limitsEvm[4]).to.deep.eq([CollectionLimitField.SponsorTransferTimeout.toString(), [true, limits.sponsorTransferTimeout.toString()]]);71 expect(limitsEvm[5]).to.deep.eq([CollectionLimits.SponsorApproveTimeout.toString(), true, limits.sponsorApproveTimeout.toString()]);71 expect(limitsEvm[5]).to.deep.eq([CollectionLimitField.SponsorApproveTimeout.toString(), [true, limits.sponsorApproveTimeout.toString()]]);72 expect(limitsEvm[6]).to.deep.eq([CollectionLimits.OwnerCanTransfer.toString(), true, limits.ownerCanTransfer.toString()]);72 expect(limitsEvm[6]).to.deep.eq([CollectionLimitField.OwnerCanTransfer.toString(), [true, limits.ownerCanTransfer.toString()]]);73 expect(limitsEvm[7]).to.deep.eq([CollectionLimits.OwnerCanDestroy.toString(), true, limits.ownerCanDestroy.toString()]);73 expect(limitsEvm[7]).to.deep.eq([CollectionLimitField.OwnerCanDestroy.toString(), [true, limits.ownerCanDestroy.toString()]]);74 expect(limitsEvm[8]).to.deep.eq([CollectionLimits.TransferEnabled.toString(), true, limits.transfersEnabled.toString()]);74 expect(limitsEvm[8]).to.deep.eq([CollectionLimitField.TransferEnabled.toString(), [true, limits.transfersEnabled.toString()]]);75 }));75 }));76});76});7777101101102 // Cannot set non-existing limit102 // Cannot set non-existing limit103 await expect(collectionEvm.methods103 await expect(collectionEvm.methods104 .setCollectionLimit(9, true, 1)104 .setCollectionLimit({field: 9, value: {status: true, value: 1}})105 .call()).to.be.rejectedWith('Returned error: VM Exception while processing transaction: revert Value not convertible into enum "CollectionLimits"');105 .call()).to.be.rejectedWith('Returned error: VM Exception while processing transaction: revert Value not convertible into enum "CollectionLimitField"');106106107 // Cannot disable limits107 // Cannot disable limits108 await expect(collectionEvm.methods108 await expect(collectionEvm.methods109 .setCollectionLimit(CollectionLimits.AccountTokenOwnership, false, 200)109 .setCollectionLimit({field: CollectionLimitField.AccountTokenOwnership, value: {status: false, value: 200}})110 .call()).to.be.rejectedWith('Returned error: VM Exception while processing transaction: revert user can\'t disable limits');110 .call()).to.be.rejectedWith('user can\'t disable limits');111111112 await expect(collectionEvm.methods112 await expect(collectionEvm.methods113 .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, invalidLimits.accountTokenOwnershipLimit)113 .setCollectionLimit({field: CollectionLimitField.AccountTokenOwnership, value: {status: true, value: invalidLimits.accountTokenOwnershipLimit}})114 .call()).to.be.rejectedWith(`can't convert value to u32 "${invalidLimits.accountTokenOwnershipLimit}"`);114 .call()).to.be.rejectedWith(`can't convert value to u32 "${invalidLimits.accountTokenOwnershipLimit}"`);115115116 await expect(collectionEvm.methods116 await expect(collectionEvm.methods117 .setCollectionLimit(CollectionLimits.TransferEnabled, true, 3)117 .setCollectionLimit({field: CollectionLimitField.TransferEnabled, value: {status: true, value: 3}})118 .call()).to.be.rejectedWith(`can't convert value to boolean "${invalidLimits.transfersEnabled}"`);118 .call()).to.be.rejectedWith(`can't convert value to boolean "${invalidLimits.transfersEnabled}"`);119119120 expect(() => collectionEvm.methods120 expect(() => collectionEvm.methods121 .setCollectionLimit(CollectionLimits.SponsoredDataSize, true, -1).send()).to.throw('value out-of-bounds');121 .setCollectionLimit({field: CollectionLimitField.SponsoredDataSize, value: {status: true, value: -1}}).send()).to.throw('value out-of-bounds');122 }));122 }));123123124 [124 [133133134 const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, testCase.case, owner);134 const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, testCase.case, owner);135 await expect(collectionEvm.methods135 await expect(collectionEvm.methods136 .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)136 .setCollectionLimit({field: CollectionLimitField.AccountTokenOwnership, value: {status: true, value: 1000}})137 .call({from: nonOwner}))137 .call({from: nonOwner}))138 .to.be.rejectedWith('NoPermission');138 .to.be.rejectedWith('NoPermission');139139140 await expect(collectionEvm.methods140 await expect(collectionEvm.methods141 .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)141 .setCollectionLimit({field: CollectionLimitField.AccountTokenOwnership, value: {status: true, value: 1000}})142 .send({from: nonOwner}))142 .send({from: nonOwner}))143 .to.be.rejected;143 .to.be.rejected;144 }));144 }));tests/src/eth/contractSponsoring.test.tsdiffbeforeafterboth42 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;42 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;434344 // 1.1 Can get sponsor using methods.sponsor:44 // 1.1 Can get sponsor using methods.sponsor:45 const actualSponsor = await helpers.methods.sponsor(flipper.options.address).call();45 const actualSponsorOpt = await helpers.methods.sponsor(flipper.options.address).call();46 expect(actualSponsorOpt.status).to.be.true;47 const actualSponsor = actualSponsorOpt.value;46 expect(actualSponsor.eth).to.eq(flipper.options.address);48 expect(actualSponsor.eth).to.eq(flipper.options.address);47 expect(actualSponsor.sub).to.eq('0');49 expect(actualSponsor.sub).to.eq('0');4850151 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;153 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;152154153 // 1.1 Can get sponsor using methods.sponsor:155 // 1.1 Can get sponsor using methods.sponsor:154 const actualSponsor = await helpers.methods.sponsor(flipper.options.address).call();156 const actualSponsorOpt = await helpers.methods.sponsor(flipper.options.address).call();157 expect(actualSponsorOpt.status).to.be.true;158 const actualSponsor = actualSponsorOpt.value;155 expect(actualSponsor.eth).to.eq(sponsor);159 expect(actualSponsor.eth).to.eq(sponsor);156 expect(actualSponsor.sub).to.eq('0');160 expect(actualSponsor.sub).to.eq('0');157161tests/src/eth/createFTCollection.test.tsdiffbeforeafterboth18import {evmToAddress} from '@polkadot/util-crypto';18import {evmToAddress} from '@polkadot/util-crypto';19import {Pallets, requirePalletsOrSkip} from '../util';19import {Pallets, requirePalletsOrSkip} from '../util';20import {expect, itEth, usingEthPlaygrounds} from './util';20import {expect, itEth, usingEthPlaygrounds} from './util';21import {CollectionLimits} from './util/playgrounds/types';21import {CollectionLimitField} from './util/playgrounds/types';222223const DECIMALS = 18;23const DECIMALS = 18;2424199 }199 }200 {200 {201 await expect(peasantCollection.methods201 await expect(peasantCollection.methods202 .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)202 .setCollectionLimit({field: CollectionLimitField.AccountTokenOwnership, value: {status: true, value: 1000}})203 .call()).to.be.rejectedWith(EXPECTED_ERROR);203 .call()).to.be.rejectedWith(EXPECTED_ERROR);204 }204 }205 });205 });224 }224 }225 {225 {226 await expect(peasantCollection.methods226 await expect(peasantCollection.methods227 .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)227 .setCollectionLimit({field: CollectionLimitField.AccountTokenOwnership, value: {status: true, value: 1000}})228 .call()).to.be.rejectedWith(EXPECTED_ERROR);228 .call()).to.be.rejectedWith(EXPECTED_ERROR);229 }229 }230 });230 });tests/src/eth/createNFTCollection.test.tsdiffbeforeafterboth17import {evmToAddress} from '@polkadot/util-crypto';17import {evmToAddress} from '@polkadot/util-crypto';18import {IKeyringPair} from '@polkadot/types/types';18import {IKeyringPair} from '@polkadot/types/types';19import {expect, itEth, usingEthPlaygrounds} from './util';19import {expect, itEth, usingEthPlaygrounds} from './util';20import {CollectionLimits} from './util/playgrounds/types';20import {CollectionLimitField} from './util/playgrounds/types';2121222223describe('Create NFT collection from EVM', () => {23describe('Create NFT collection from EVM', () => {210 }210 }211 {211 {212 await expect(malfeasantCollection.methods212 await expect(malfeasantCollection.methods213 .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)213 .setCollectionLimit({field: CollectionLimitField.AccountTokenOwnership, value: {status: true, value: 1000}})214 .call()).to.be.rejectedWith(EXPECTED_ERROR);214 .call()).to.be.rejectedWith(EXPECTED_ERROR);215 }215 }216 });216 });235 }235 }236 {236 {237 await expect(malfeasantCollection.methods237 await expect(malfeasantCollection.methods238 .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)238 .setCollectionLimit({field: CollectionLimitField.AccountTokenOwnership, value: {status: true, value: 1000}})239 .call()).to.be.rejectedWith(EXPECTED_ERROR);239 .call()).to.be.rejectedWith(EXPECTED_ERROR);240 }240 }241 });241 });tests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth18import {IKeyringPair} from '@polkadot/types/types';18import {IKeyringPair} from '@polkadot/types/types';19import {Pallets, requirePalletsOrSkip} from '../util';19import {Pallets, requirePalletsOrSkip} from '../util';20import {expect, itEth, usingEthPlaygrounds} from './util';20import {expect, itEth, usingEthPlaygrounds} from './util';21import {CollectionLimits} from './util/playgrounds/types';21import {CollectionLimitField} from './util/playgrounds/types';2222232324describe('Create RFT collection from EVM', () => {24describe('Create RFT collection from EVM', () => {242 }242 }243 {243 {244 await expect(peasantCollection.methods244 await expect(peasantCollection.methods245 .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)245 .setCollectionLimit({field: CollectionLimitField.AccountTokenOwnership, value: {status: true, value: 1000}})246 .call()).to.be.rejectedWith(EXPECTED_ERROR);246 .call()).to.be.rejectedWith(EXPECTED_ERROR);247 }247 }248 });248 });267 }267 }268 {268 {269 await expect(peasantCollection.methods269 await expect(peasantCollection.methods270 .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)270 .setCollectionLimit({field: CollectionLimitField.AccountTokenOwnership, value: {status: true, value: 1000}})271 .call()).to.be.rejectedWith(EXPECTED_ERROR);271 .call()).to.be.rejectedWith(EXPECTED_ERROR);272 }272 }273 });273 });tests/src/eth/events.test.tsdiffbeforeafterboth19import {EthUniqueHelper, itEth, usingEthPlaygrounds} from './util';19import {EthUniqueHelper, itEth, usingEthPlaygrounds} from './util';20import {IEvent, TCollectionMode} from '../util/playgrounds/types';20import {IEvent, TCollectionMode} from '../util/playgrounds/types';21import {Pallets, requirePalletsOrSkip} from '../util';21import {Pallets, requirePalletsOrSkip} from '../util';22import {CollectionLimits, EthTokenPermissions, NormalizedEvent} from './util/playgrounds/types';22import {CollectionLimitField, TokenPermissionField, NormalizedEvent} from './util/playgrounds/types';232324let donor: IKeyringPair;24let donor: IKeyringPair;2525121 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['PropertyPermissionSet']}]);121 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['PropertyPermissionSet']}]);122 await collection.methods.setTokenPropertyPermissions([122 await collection.methods.setTokenPropertyPermissions([123 ['A', [123 ['A', [124 [EthTokenPermissions.Mutable, true],124 [TokenPermissionField.Mutable, true],125 [EthTokenPermissions.TokenOwner, true],125 [TokenPermissionField.TokenOwner, true],126 [EthTokenPermissions.CollectionAdmin, true]],126 [TokenPermissionField.CollectionAdmin, true]],127 ],127 ],128 ]).send({from: owner});128 ]).send({from: owner});129 await helper.wait.newBlocks(1);129 await helper.wait.newBlocks(1);233 });233 });234 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionLimitSet']}]);234 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionLimitSet']}]);235 {235 {236 await collection.methods.setCollectionLimit(CollectionLimits.OwnerCanTransfer, true, 0).send({from: owner});236 await collection.methods.setCollectionLimit({field: CollectionLimitField.OwnerCanTransfer, value: {status: true, value: 0}}).send({from: owner});237 await helper.wait.newBlocks(1);237 await helper.wait.newBlocks(1);238 expect(ethEvents).to.containSubset([238 expect(ethEvents).to.containSubset([239 {239 {379 const tokenId = result.events.Transfer.returnValues.tokenId;379 const tokenId = result.events.Transfer.returnValues.tokenId;380 await collection.methods.setTokenPropertyPermissions([380 await collection.methods.setTokenPropertyPermissions([381 ['A', [381 ['A', [382 [EthTokenPermissions.Mutable, true],382 [TokenPermissionField.Mutable, true],383 [EthTokenPermissions.TokenOwner, true],383 [TokenPermissionField.TokenOwner, true],384 [EthTokenPermissions.CollectionAdmin, true]],384 [TokenPermissionField.CollectionAdmin, true]],385 ],385 ],386 ]).send({from: owner});386 ]).send({from: owner});387387tests/src/eth/fractionalizer/Fractionalizer.soldiffbeforeafterboth3import {CollectionHelpers} from "../api/CollectionHelpers.sol";3import {CollectionHelpers} from "../api/CollectionHelpers.sol";4import {ContractHelpers} from "../api/ContractHelpers.sol";4import {ContractHelpers} from "../api/ContractHelpers.sol";5import {UniqueRefungibleToken} from "../api/UniqueRefungibleToken.sol";5import {UniqueRefungibleToken} from "../api/UniqueRefungibleToken.sol";6import {UniqueRefungible, EthCrossAccount} from "../api/UniqueRefungible.sol";6import {UniqueRefungible, CrossAddress} from "../api/UniqueRefungible.sol";7import {UniqueNFT} from "../api/UniqueNFT.sol";7import {UniqueNFT} from "../api/UniqueNFT.sol";889/// @dev Fractionalization contract. It stores mappings between NFT and RFT tokens,9/// @dev Fractionalization contract. It stores mappings between NFT and RFT tokens,63 "Wrong collection type. Collection is not refungible."63 "Wrong collection type. Collection is not refungible."64 );64 );65 require(65 require(66 refungibleContract.isOwnerOrAdminCross(EthCrossAccount({eth: address(this), sub: uint256(0)})),66 refungibleContract.isOwnerOrAdminCross(CrossAddress({eth: address(this), sub: uint256(0)})),67 "Fractionalizer contract should be an admin of the collection"67 "Fractionalizer contract should be an admin of the collection"68 );68 );69 rftCollection = _collection;69 rftCollection = _collection;tests/src/eth/tokenProperties.test.tsdiffbeforeafterboth20import {ITokenPropertyPermission} from '../util/playgrounds/types';20import {ITokenPropertyPermission} from '../util/playgrounds/types';21import {Pallets} from '../util';21import {Pallets} from '../util';22import {UniqueNFTCollection, UniqueNFToken, UniqueRFTCollection} from '../util/playgrounds/unique';22import {UniqueNFTCollection, UniqueNFToken, UniqueRFTCollection} from '../util/playgrounds/unique';23import {EthTokenPermissions} from './util/playgrounds/types';23import {TokenPermissionField} from './util/playgrounds/types';242425describe('EVM token properties', () => {25describe('EVM token properties', () => {26 let donor: IKeyringPair;26 let donor: IKeyringPair;474748 await collection.methods.setTokenPropertyPermissions([48 await collection.methods.setTokenPropertyPermissions([49 ['testKey', [49 ['testKey', [50 [EthTokenPermissions.Mutable, mutable],50 [TokenPermissionField.Mutable, mutable],51 [EthTokenPermissions.TokenOwner, tokenOwner],51 [TokenPermissionField.TokenOwner, tokenOwner],52 [EthTokenPermissions.CollectionAdmin, collectionAdmin]],52 [TokenPermissionField.CollectionAdmin, collectionAdmin]],53 ],53 ],54 ]).send({from: caller.eth});54 ]).send({from: caller.eth});5555606061 expect(await collection.methods.tokenPropertyPermissions().call({from: caller.eth})).to.be.like([61 expect(await collection.methods.tokenPropertyPermissions().call({from: caller.eth})).to.be.like([62 ['testKey', [62 ['testKey', [63 [EthTokenPermissions.Mutable.toString(), mutable],63 [TokenPermissionField.Mutable.toString(), mutable],64 [EthTokenPermissions.TokenOwner.toString(), tokenOwner],64 [TokenPermissionField.TokenOwner.toString(), tokenOwner],65 [EthTokenPermissions.CollectionAdmin.toString(), collectionAdmin]],65 [TokenPermissionField.CollectionAdmin.toString(), collectionAdmin]],66 ],66 ],67 ]);67 ]);68 }68 }808081 await collection.methods.setTokenPropertyPermissions([81 await collection.methods.setTokenPropertyPermissions([82 ['testKey_0', [82 ['testKey_0', [83 [EthTokenPermissions.Mutable, true],83 [TokenPermissionField.Mutable, true],84 [EthTokenPermissions.TokenOwner, true],84 [TokenPermissionField.TokenOwner, true],85 [EthTokenPermissions.CollectionAdmin, true]],85 [TokenPermissionField.CollectionAdmin, true]],86 ],86 ],87 ['testKey_1', [87 ['testKey_1', [88 [EthTokenPermissions.Mutable, true],88 [TokenPermissionField.Mutable, true],89 [EthTokenPermissions.TokenOwner, false],89 [TokenPermissionField.TokenOwner, false],90 [EthTokenPermissions.CollectionAdmin, true]],90 [TokenPermissionField.CollectionAdmin, true]],91 ],91 ],92 ['testKey_2', [92 ['testKey_2', [93 [EthTokenPermissions.Mutable, false],93 [TokenPermissionField.Mutable, false],94 [EthTokenPermissions.TokenOwner, true],94 [TokenPermissionField.TokenOwner, true],95 [EthTokenPermissions.CollectionAdmin, false]],95 [TokenPermissionField.CollectionAdmin, false]],96 ],96 ],97 ]).send({from: owner});97 ]).send({from: owner});9898113113114 expect(await collection.methods.tokenPropertyPermissions().call({from: owner})).to.be.like([114 expect(await collection.methods.tokenPropertyPermissions().call({from: owner})).to.be.like([115 ['testKey_0', [115 ['testKey_0', [116 [EthTokenPermissions.Mutable.toString(), true],116 [TokenPermissionField.Mutable.toString(), true],117 [EthTokenPermissions.TokenOwner.toString(), true],117 [TokenPermissionField.TokenOwner.toString(), true],118 [EthTokenPermissions.CollectionAdmin.toString(), true]],118 [TokenPermissionField.CollectionAdmin.toString(), true]],119 ],119 ],120 ['testKey_1', [120 ['testKey_1', [121 [EthTokenPermissions.Mutable.toString(), true],121 [TokenPermissionField.Mutable.toString(), true],122 [EthTokenPermissions.TokenOwner.toString(), false],122 [TokenPermissionField.TokenOwner.toString(), false],123 [EthTokenPermissions.CollectionAdmin.toString(), true]],123 [TokenPermissionField.CollectionAdmin.toString(), true]],124 ],124 ],125 ['testKey_2', [125 ['testKey_2', [126 [EthTokenPermissions.Mutable.toString(), false],126 [TokenPermissionField.Mutable.toString(), false],127 [EthTokenPermissions.TokenOwner.toString(), true],127 [TokenPermissionField.TokenOwner.toString(), true],128 [EthTokenPermissions.CollectionAdmin.toString(), false]],128 [TokenPermissionField.CollectionAdmin.toString(), false]],129 ],129 ],130 ]);130 ]);131 }));131 }));144144145 await collection.methods.setTokenPropertyPermissions([145 await collection.methods.setTokenPropertyPermissions([146 ['testKey_0', [146 ['testKey_0', [147 [EthTokenPermissions.Mutable, true],147 [TokenPermissionField.Mutable, true],148 [EthTokenPermissions.TokenOwner, true],148 [TokenPermissionField.TokenOwner, true],149 [EthTokenPermissions.CollectionAdmin, true]],149 [TokenPermissionField.CollectionAdmin, true]],150 ],150 ],151 ['testKey_1', [151 ['testKey_1', [152 [EthTokenPermissions.Mutable, true],152 [TokenPermissionField.Mutable, true],153 [EthTokenPermissions.TokenOwner, false],153 [TokenPermissionField.TokenOwner, false],154 [EthTokenPermissions.CollectionAdmin, true]],154 [TokenPermissionField.CollectionAdmin, true]],155 ],155 ],156 ['testKey_2', [156 ['testKey_2', [157 [EthTokenPermissions.Mutable, false],157 [TokenPermissionField.Mutable, false],158 [EthTokenPermissions.TokenOwner, true],158 [TokenPermissionField.TokenOwner, true],159 [EthTokenPermissions.CollectionAdmin, false]],159 [TokenPermissionField.CollectionAdmin, false]],160 ],160 ],161 ]).send({from: caller.eth});161 ]).send({from: caller.eth});162162177177178 expect(await collection.methods.tokenPropertyPermissions().call({from: caller.eth})).to.be.like([178 expect(await collection.methods.tokenPropertyPermissions().call({from: caller.eth})).to.be.like([179 ['testKey_0', [179 ['testKey_0', [180 [EthTokenPermissions.Mutable.toString(), true],180 [TokenPermissionField.Mutable.toString(), true],181 [EthTokenPermissions.TokenOwner.toString(), true],181 [TokenPermissionField.TokenOwner.toString(), true],182 [EthTokenPermissions.CollectionAdmin.toString(), true]],182 [TokenPermissionField.CollectionAdmin.toString(), true]],183 ],183 ],184 ['testKey_1', [184 ['testKey_1', [185 [EthTokenPermissions.Mutable.toString(), true],185 [TokenPermissionField.Mutable.toString(), true],186 [EthTokenPermissions.TokenOwner.toString(), false],186 [TokenPermissionField.TokenOwner.toString(), false],187 [EthTokenPermissions.CollectionAdmin.toString(), true]],187 [TokenPermissionField.CollectionAdmin.toString(), true]],188 ],188 ],189 ['testKey_2', [189 ['testKey_2', [190 [EthTokenPermissions.Mutable.toString(), false],190 [TokenPermissionField.Mutable.toString(), false],191 [EthTokenPermissions.TokenOwner.toString(), true],191 [TokenPermissionField.TokenOwner.toString(), true],192 [EthTokenPermissions.CollectionAdmin.toString(), false]],192 [TokenPermissionField.CollectionAdmin.toString(), false]],193 ],193 ],194 ]);194 ]);195195460460461 await expect(collection.methods.setTokenPropertyPermissions([461 await expect(collection.methods.setTokenPropertyPermissions([462 ['testKey_0', [462 ['testKey_0', [463 [EthTokenPermissions.Mutable, true],463 [TokenPermissionField.Mutable, true],464 [EthTokenPermissions.TokenOwner, true],464 [TokenPermissionField.TokenOwner, true],465 [EthTokenPermissions.CollectionAdmin, true]],465 [TokenPermissionField.CollectionAdmin, true]],466 ],466 ],467 ]).call({from: caller})).to.be.rejectedWith('NoPermission');467 ]).call({from: caller})).to.be.rejectedWith('NoPermission');468 }));468 }));480 await expect(collection.methods.setTokenPropertyPermissions([480 await expect(collection.methods.setTokenPropertyPermissions([481 // "Space" is invalid character481 // "Space" is invalid character482 ['testKey 0', [482 ['testKey 0', [483 [EthTokenPermissions.Mutable, true],483 [TokenPermissionField.Mutable, true],484 [EthTokenPermissions.TokenOwner, true],484 [TokenPermissionField.TokenOwner, true],485 [EthTokenPermissions.CollectionAdmin, true]],485 [TokenPermissionField.CollectionAdmin, true]],486 ],486 ],487 ]).call({from: owner})).to.be.rejectedWith('InvalidCharacterInPropertyKey');487 ]).call({from: owner})).to.be.rejectedWith('InvalidCharacterInPropertyKey');488 }));488 }));500 // 1. Owner sets strict property-permissions:500 // 1. Owner sets strict property-permissions:501 await collection.methods.setTokenPropertyPermissions([501 await collection.methods.setTokenPropertyPermissions([502 ['testKey', [502 ['testKey', [503 [EthTokenPermissions.Mutable, true],503 [TokenPermissionField.Mutable, true],504 [EthTokenPermissions.TokenOwner, true],504 [TokenPermissionField.TokenOwner, true],505 [EthTokenPermissions.CollectionAdmin, true]],505 [TokenPermissionField.CollectionAdmin, true]],506 ],506 ],507 ]).send({from: owner});507 ]).send({from: owner});508508509 // 2. Owner can set stricter property-permissions:509 // 2. Owner can set stricter property-permissions:510 for(const values of [[true, true, false], [true, false, false], [false, false, false]]) {510 for(const values of [[true, true, false], [true, false, false], [false, false, false]]) {511 await collection.methods.setTokenPropertyPermissions([511 await collection.methods.setTokenPropertyPermissions([512 ['testKey', [512 ['testKey', [513 [EthTokenPermissions.Mutable, values[0]],513 [TokenPermissionField.Mutable, values[0]],514 [EthTokenPermissions.TokenOwner, values[1]],514 [TokenPermissionField.TokenOwner, values[1]],515 [EthTokenPermissions.CollectionAdmin, values[2]]],515 [TokenPermissionField.CollectionAdmin, values[2]]],516 ],516 ],517 ]).send({from: owner});517 ]).send({from: owner});518 }518 }536 // 1. Owner sets strict property-permissions:536 // 1. Owner sets strict property-permissions:537 await collection.methods.setTokenPropertyPermissions([537 await collection.methods.setTokenPropertyPermissions([538 ['testKey', [538 ['testKey', [539 [EthTokenPermissions.Mutable, false],539 [TokenPermissionField.Mutable, false],540 [EthTokenPermissions.TokenOwner, false],540 [TokenPermissionField.TokenOwner, false],541 [EthTokenPermissions.CollectionAdmin, false]],541 [TokenPermissionField.CollectionAdmin, false]],542 ],542 ],543 ]).send({from: owner});543 ]).send({from: owner});544544545 // 2. Owner cannot set less strict property-permissions:545 // 2. Owner cannot set less strict property-permissions:546 for(const values of [[true, false, false], [false, true, false], [false, false, true]]) {546 for(const values of [[true, false, false], [false, true, false], [false, false, true]]) {547 await expect(collection.methods.setTokenPropertyPermissions([547 await expect(collection.methods.setTokenPropertyPermissions([548 ['testKey', [548 ['testKey', [549 [EthTokenPermissions.Mutable, values[0]],549 [TokenPermissionField.Mutable, values[0]],550 [EthTokenPermissions.TokenOwner, values[1]],550 [TokenPermissionField.TokenOwner, values[1]],551 [EthTokenPermissions.CollectionAdmin, values[2]]],551 [TokenPermissionField.CollectionAdmin, values[2]]],552 ],552 ],553 ]).call({from: owner})).to.be.rejectedWith('NoPermission');553 ]).call({from: owner})).to.be.rejectedWith('NoPermission');554 }554 }tests/src/eth/util/playgrounds/types.tsdiffbeforeafterboth14 args: { [key: string]: string }14 args: { [key: string]: string }15};15};1617export interface OptionUint {18 status: boolean,19 value: bigint,20}2116export interface TEthCrossAccount {22export interface CrossAddress {17 readonly eth: string,23 readonly eth: string,18 readonly sub: string | Uint8Array,24 readonly sub: string | Uint8Array,19}25}202621export type EthProperty = string[];27export type EthProperty = string[];222823export enum EthTokenPermissions {29export enum TokenPermissionField {24 Mutable,30 Mutable,25 TokenOwner,31 TokenOwner,26 CollectionAdmin32 CollectionAdmin27}33}3428export enum CollectionLimits {35export enum CollectionLimitField {29 AccountTokenOwnership,36 AccountTokenOwnership,30 SponsoredDataSize,37 SponsoredDataSize,31 SponsoredDataRateLimit,38 SponsoredDataRateLimit,37 TransferEnabled44 TransferEnabled38}45}4647export interface CollectionLimit {48 field: CollectionLimitField,49 value: OptionUint,50}3951tests/src/eth/util/playgrounds/unique.dev.tsdiffbeforeafterboth181819import {DevUniqueHelper} from '../../../util/playgrounds/unique.dev';19import {DevUniqueHelper} from '../../../util/playgrounds/unique.dev';202021import {ContractImports, CompiledContract, TEthCrossAccount, NormalizedEvent, EthProperty} from './types';21import {ContractImports, CompiledContract, CrossAddress, NormalizedEvent, EthProperty} from './types';222223// Native contracts ABI23// Native contracts ABI24import collectionHelpersAbi from '../../abi/collectionHelpers.json';24import collectionHelpersAbi from '../../abi/collectionHelpers.json';435export type EthUniqueHelperConstructor = new (...args: any[]) => EthUniqueHelper;435export type EthUniqueHelperConstructor = new (...args: any[]) => EthUniqueHelper;436436437export class EthCrossAccountGroup extends EthGroupBase {437export class EthCrossAccountGroup extends EthGroupBase {438 createAccount(): TEthCrossAccount {438 createAccount(): CrossAddress {439 return this.fromAddress(this.helper.eth.createAccount());439 return this.fromAddress(this.helper.eth.createAccount());440 }440 }441441442 async createAccountWithBalance(donor: IKeyringPair, amount=100n) {442 async createAccountWithBalance(donor: IKeyringPair, amount=100n) {443 return this.fromAddress(await this.helper.eth.createAccountWithBalance(donor, amount));443 return this.fromAddress(await this.helper.eth.createAccountWithBalance(donor, amount));444 }444 }445445446 fromAddress(address: TEthereumAccount): TEthCrossAccount {446 fromAddress(address: TEthereumAccount): CrossAddress {447 return {447 return {448 eth: address,448 eth: address,449 sub: '0',449 sub: '0',450 };450 };451 }451 }452452453 fromKeyringPair(keyring: IKeyringPair): TEthCrossAccount {453 fromKeyringPair(keyring: IKeyringPair): CrossAddress {454 return {454 return {455 eth: '0x0000000000000000000000000000000000000000',455 eth: '0x0000000000000000000000000000000000000000',456 sub: keyring.addressRaw,456 sub: keyring.addressRaw,