difftreelog
Merge pull request #433 from UniqueNetwork/doc/evm-coder
in: master
Document evm related crates
58 files changed
.maintain/frame-weight-template.hbsdiffbeforeafterboth--- a/.maintain/frame-weight-template.hbs
+++ b/.maintain/frame-weight-template.hbs
@@ -14,6 +14,7 @@
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
+#![allow(missing_docs)]
#![allow(clippy::unnecessary_cast)]
use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1772,41 +1772,6 @@
]
[[package]]
-name = "darling"
-version = "0.13.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c"
-dependencies = [
- "darling_core",
- "darling_macro",
-]
-
-[[package]]
-name = "darling_core"
-version = "0.13.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610"
-dependencies = [
- "fnv",
- "ident_case",
- "proc-macro2",
- "quote",
- "strsim",
- "syn",
-]
-
-[[package]]
-name = "darling_macro"
-version = "0.13.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835"
-dependencies = [
- "darling_core",
- "quote",
- "syn",
-]
-
-[[package]]
name = "data-encoding"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2207,7 +2172,7 @@
version = "0.1.1"
dependencies = [
"ethereum",
- "evm-coder-macros",
+ "evm-coder-procedural",
"evm-core",
"hex",
"hex-literal",
@@ -2216,15 +2181,14 @@
]
[[package]]
-name = "evm-coder-macros"
-version = "0.1.0"
+name = "evm-coder-procedural"
+version = "0.2.0"
dependencies = [
"Inflector",
- "darling",
"hex",
"proc-macro2",
"quote",
- "sha3 0.9.1",
+ "sha3 0.10.2",
"syn",
]
@@ -3427,12 +3391,6 @@
"wasm-bindgen",
"winapi",
]
-
-[[package]]
-name = "ident_case"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "idna"
crates/evm-coder-macros/Cargo.tomldiffbeforeafterboth--- a/crates/evm-coder-macros/Cargo.toml
+++ /dev/null
@@ -1,17 +0,0 @@
-[package]
-name = "evm-coder-macros"
-version = "0.1.0"
-license = "GPLv3"
-edition = "2021"
-
-[lib]
-proc-macro = true
-
-[dependencies]
-sha3 = "0.9.1"
-quote = "1.0"
-proc-macro2 = "1.0"
-syn = { version = "1.0", features = ["full"] }
-hex = "0.4.3"
-Inflector = "0.11.4"
-darling = "0.13.0"
crates/evm-coder-macros/src/lib.rsdiffbeforeafterboth--- a/crates/evm-coder-macros/src/lib.rs
+++ /dev/null
@@ -1,300 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-#![allow(dead_code)]
-
-use darling::FromMeta;
-use inflector::cases;
-use proc_macro::TokenStream;
-use quote::quote;
-use sha3::{Digest, Keccak256};
-use syn::{
- AttributeArgs, DeriveInput, GenericArgument, Ident, ItemImpl, Pat, Path, PathArguments,
- PathSegment, Type, parse_macro_input, spanned::Spanned,
-};
-
-mod solidity_interface;
-mod to_log;
-
-fn fn_selector_str(input: &str) -> u32 {
- let mut hasher = Keccak256::new();
- hasher.update(input.as_bytes());
- let result = hasher.finalize();
-
- let mut selector_bytes = [0; 4];
- selector_bytes.copy_from_slice(&result[0..4]);
-
- u32::from_be_bytes(selector_bytes)
-}
-
-/// Returns solidity function selector (first 4 bytes of hash) by its
-/// textual representation
-///
-/// ```ignore
-/// use evm_coder_macros::fn_selector;
-///
-/// assert_eq!(fn_selector!(transfer(address, uint256)), 0xa9059cbb);
-/// ```
-#[proc_macro]
-pub fn fn_selector(input: TokenStream) -> TokenStream {
- let input = input.to_string().replace(' ', "");
- let selector = fn_selector_str(&input);
-
- (quote! {
- #selector
- })
- .into()
-}
-
-fn event_selector_str(input: &str) -> [u8; 32] {
- let mut hasher = Keccak256::new();
- hasher.update(input.as_bytes());
- let result = hasher.finalize();
-
- let mut selector_bytes = [0; 32];
- selector_bytes.copy_from_slice(&result[0..32]);
- selector_bytes
-}
-
-/// Returns solidity topic (hash) by its textual representation
-///
-/// ```ignore
-/// use evm_coder_macros::event_topic;
-///
-/// assert_eq!(
-/// format!("{:x}", event_topic!(Transfer(address, address, uint256))),
-/// "ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
-/// );
-/// ```
-#[proc_macro]
-pub fn event_topic(stream: TokenStream) -> TokenStream {
- let input = stream.to_string().replace(' ', "");
- let selector_bytes = event_selector_str(&input);
-
- (quote! {
- ::primitive_types::H256([#(
- #selector_bytes,
- )*])
- })
- .into()
-}
-
-fn parse_path(ty: &Type) -> syn::Result<&Path> {
- match &ty {
- syn::Type::Path(pat) => {
- if let Some(qself) = &pat.qself {
- return Err(syn::Error::new(qself.ty.span(), "no receiver expected"));
- }
- Ok(&pat.path)
- }
- _ => Err(syn::Error::new(ty.span(), "expected ty to be path")),
- }
-}
-
-fn parse_path_segment(path: &Path) -> syn::Result<&PathSegment> {
- if path.segments.len() != 1 {
- return Err(syn::Error::new(
- path.span(),
- "expected path to have only segment",
- ));
- }
- let last_segment = &path.segments.last().unwrap();
- Ok(last_segment)
-}
-
-fn parse_ident_from_pat(pat: &Pat) -> syn::Result<&Ident> {
- match pat {
- Pat::Ident(i) => Ok(&i.ident),
- _ => Err(syn::Error::new(pat.span(), "expected pat ident")),
- }
-}
-
-fn parse_ident_from_segment(segment: &PathSegment, allow_generics: bool) -> syn::Result<&Ident> {
- if segment.arguments != PathArguments::None && !allow_generics {
- return Err(syn::Error::new(
- segment.arguments.span(),
- "unexpected generic type",
- ));
- }
- Ok(&segment.ident)
-}
-
-fn parse_ident_from_path(path: &Path, allow_generics: bool) -> syn::Result<&Ident> {
- let segment = parse_path_segment(path)?;
- parse_ident_from_segment(segment, allow_generics)
-}
-
-fn parse_ident_from_type(ty: &Type, allow_generics: bool) -> syn::Result<&Ident> {
- let path = parse_path(ty)?;
- parse_ident_from_path(path, allow_generics)
-}
-
-// Gets T out of Result<T>
-fn parse_result_ok(ty: &Type) -> syn::Result<&Type> {
- let path = parse_path(ty)?;
- let segment = parse_path_segment(path)?;
-
- if segment.ident != "Result" {
- return Err(syn::Error::new(
- ty.span(),
- "expected Result as return type (no renamed aliases allowed)",
- ));
- }
- let args = match &segment.arguments {
- PathArguments::AngleBracketed(e) => e,
- _ => {
- return Err(syn::Error::new(
- segment.arguments.span(),
- "missing Result generics",
- ))
- }
- };
-
- let args = &args.args;
- let arg = args.first().unwrap();
-
- let ty = match arg {
- GenericArgument::Type(ty) => ty,
- _ => {
- return Err(syn::Error::new(
- arg.span(),
- "expected first generic to be type",
- ))
- }
- };
-
- Ok(ty)
-}
-
-fn pascal_ident_to_call(ident: &Ident) -> Ident {
- let name = format!("{}Call", ident);
- Ident::new(&name, ident.span())
-}
-fn snake_ident_to_pascal(ident: &Ident) -> Ident {
- let name = ident.to_string();
- let name = cases::pascalcase::to_pascal_case(&name);
- Ident::new(&name, ident.span())
-}
-fn snake_ident_to_screaming(ident: &Ident) -> Ident {
- let name = ident.to_string();
- let name = cases::screamingsnakecase::to_screaming_snake_case(&name);
- Ident::new(&name, ident.span())
-}
-fn pascal_ident_to_snake_call(ident: &Ident) -> Ident {
- let name = ident.to_string();
- let name = cases::snakecase::to_snake_case(&name);
- let name = format!("call_{}", name);
- Ident::new(&name, ident.span())
-}
-
-/// Derives call enum implementing [`evm_coder::Callable`], [`evm_coder::Weighted`]
-/// and [`evm_coder::Call`] from impl block
-///
-/// ## Macro syntax
-///
-/// `#[solidity_interface(name, is, inline_is, events)]`
-/// - *name*: used in generated code, and for Call enum name
-/// - *is*: used to provide call inheritance, not found methods will be delegated to all contracts
-/// specified in is/inline_is
-/// - *inline_is*: same as is, but selectors for passed contracts will be used by derived ERC165
-/// implementation
-///
-/// `#[weight(value)]`
-/// Can be added to every method of impl block, used for deriving [`evm_coder::Weighted`], which
-/// is used by substrate bridge
-/// - *value*: expression, which evaluates to weight required to call this method.
-/// This expression can use call arguments to calculate non-constant execution time.
-/// This expression should evaluate faster than actual execution does, and may provide worser case
-/// than one is called
-///
-/// `#[solidity_interface(rename_selector)]`
-/// - *rename_selector*: by default, selector name will be generated by transforming method name
-/// from snake_case to camelCase. Use this option, if other naming convention is required.
-/// I.e: method `token_uri` will be automatically renamed to `tokenUri` in selector, but name
-/// required by ERC721 standard is `tokenURI`, thus we need to specify `rename_selector = "tokenURI"`
-/// explicitly
-///
-/// Also, any contract method may have doc comments, which will be automatically added to generated
-/// solidity interface definitions
-///
-/// ## Example
-///
-/// ```ignore
-/// struct SuperContract;
-/// struct InlineContract;
-/// struct Contract;
-///
-/// #[derive(ToLog)]
-/// enum ContractEvents {
-/// Event(#[indexed] uint32),
-/// }
-///
-/// #[solidity_interface(name = "MyContract", is(SuperContract), inline_is(InlineContract))]
-/// impl Contract {
-/// /// Multiply two numbers
-/// #[weight(200 + a + b)]
-/// #[solidity_interface(rename_selector = "mul")]
-/// fn mul(&mut self, a: uint32, b: uint32) -> Result<uint32> {
-/// Ok(a.checked_mul(b).ok_or("overflow")?)
-/// }
-/// }
-/// ```
-#[proc_macro_attribute]
-pub fn solidity_interface(args: TokenStream, stream: TokenStream) -> TokenStream {
- let args = parse_macro_input!(args as AttributeArgs);
- let args = solidity_interface::InterfaceInfo::from_list(&args).unwrap();
-
- let input: ItemImpl = match syn::parse(stream) {
- Ok(t) => t,
- Err(e) => return e.to_compile_error().into(),
- };
-
- let expanded = match solidity_interface::SolidityInterface::try_from(args, &input) {
- Ok(v) => v.expand(),
- Err(e) => e.to_compile_error(),
- };
-
- (quote! {
- #input
-
- #expanded
- })
- .into()
-}
-
-#[proc_macro_attribute]
-pub fn solidity(_args: TokenStream, stream: TokenStream) -> TokenStream {
- stream
-}
-#[proc_macro_attribute]
-pub fn weight(_args: TokenStream, stream: TokenStream) -> TokenStream {
- stream
-}
-
-/// ## Syntax
-///
-/// `#[indexed]`
-/// Marks this field as indexed, so it will appear in [`ethereum::Log`] topics instead of data
-#[proc_macro_derive(ToLog, attributes(indexed))]
-pub fn to_log(value: TokenStream) -> TokenStream {
- let input = parse_macro_input!(value as DeriveInput);
-
- match to_log::Events::try_from(&input) {
- Ok(e) => e.expand(),
- Err(e) => e.to_compile_error(),
- }
- .into()
-}
crates/evm-coder-macros/src/solidity_interface.rsdiffbeforeafterboth--- a/crates/evm-coder-macros/src/solidity_interface.rs
+++ /dev/null
@@ -1,1005 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-#![allow(dead_code)]
-
-use quote::quote;
-use darling::{FromMeta, ToTokens};
-use inflector::cases;
-use std::fmt::Write;
-use syn::{
- Expr, FnArg, GenericArgument, Generics, Ident, ImplItem, ImplItemMethod, ItemImpl, Lit, Meta,
- MetaNameValue, NestedMeta, PatType, Path, PathArguments, ReturnType, Type, spanned::Spanned,
- parse_str,
-};
-
-use crate::{
- fn_selector_str, parse_ident_from_pat, parse_ident_from_path, parse_path, parse_path_segment,
- parse_result_ok, pascal_ident_to_call, pascal_ident_to_snake_call, snake_ident_to_pascal,
- snake_ident_to_screaming,
-};
-
-struct Is {
- name: Ident,
- pascal_call_name: Ident,
- snake_call_name: Ident,
- via: Option<(Type, Ident)>,
-}
-impl Is {
- fn new_via(path: &Path, via: Option<(Type, Ident)>) -> syn::Result<Self> {
- let name = parse_ident_from_path(path, false)?.clone();
- Ok(Self {
- pascal_call_name: pascal_ident_to_call(&name),
- snake_call_name: pascal_ident_to_snake_call(&name),
- name,
- via,
- })
- }
- fn new(path: &Path) -> syn::Result<Self> {
- Self::new_via(path, None)
- }
-
- fn expand_call_def(&self, gen_ref: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {
- let name = &self.name;
- let pascal_call_name = &self.pascal_call_name;
- quote! {
- #name(#pascal_call_name #gen_ref)
- }
- }
-
- fn expand_interface_id(&self) -> proc_macro2::TokenStream {
- let pascal_call_name = &self.pascal_call_name;
- quote! {
- interface_id ^= u32::from_be_bytes(#pascal_call_name::interface_id());
- }
- }
-
- fn expand_supports_interface(
- &self,
- generics: &proc_macro2::TokenStream,
- ) -> proc_macro2::TokenStream {
- let pascal_call_name = &self.pascal_call_name;
- quote! {
- <#pascal_call_name #generics>::supports_interface(interface_id)
- }
- }
-
- fn expand_variant_weight(&self) -> proc_macro2::TokenStream {
- let name = &self.name;
- quote! {
- Self::#name(call) => call.weight()
- }
- }
-
- fn expand_variant_call(
- &self,
- call_name: &proc_macro2::Ident,
- generics: &proc_macro2::TokenStream,
- ) -> proc_macro2::TokenStream {
- let name = &self.name;
- let pascal_call_name = &self.pascal_call_name;
- let via_typ = self
- .via
- .as_ref()
- .map(|(t, _)| quote! {#t})
- .unwrap_or_else(|| quote! {Self});
- let via_map = self
- .via
- .as_ref()
- .map(|(_, i)| quote! {.#i()})
- .unwrap_or_default();
- quote! {
- #call_name::#name(call) => return <#via_typ as ::evm_coder::Callable<#pascal_call_name #generics>>::call(self #via_map, Msg {
- call,
- caller: c.caller,
- value: c.value,
- })
- }
- }
-
- fn expand_parse(&self, generics: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {
- let name = &self.name;
- let pascal_call_name = &self.pascal_call_name;
- quote! {
- if let Some(parsed_call) = <#pascal_call_name #generics>::parse(method_id, reader)? {
- return Ok(Some(Self::#name(parsed_call)))
- }
- }
- }
-
- fn expand_generator(&self, generics: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {
- let pascal_call_name = &self.pascal_call_name;
- quote! {
- <#pascal_call_name #generics>::generate_solidity_interface(tc, is_impl);
- }
- }
-
- fn expand_event_generator(&self) -> proc_macro2::TokenStream {
- let name = &self.name;
- quote! {
- #name::generate_solidity_interface(tc, is_impl);
- }
- }
-}
-
-#[derive(Default)]
-struct IsList(Vec<Is>);
-impl FromMeta for IsList {
- fn from_list(items: &[NestedMeta]) -> darling::Result<Self> {
- let mut out = Vec::new();
- for item in items {
- match item {
- NestedMeta::Meta(Meta::Path(path)) => out.push(Is::new(path)?),
- // TODO: replace meta parsing with manual
- NestedMeta::Meta(Meta::List(list))
- if list.path.is_ident("via") && list.nested.len() == 3 =>
- {
- let mut data = list.nested.iter();
- let typ = match data.next().expect("len == 3") {
- NestedMeta::Lit(Lit::Str(s)) => {
- let v = s.value();
- let typ: Type = parse_str(&v)?;
- typ
- }
- _ => {
- return Err(syn::Error::new(
- item.span(),
- "via typ should be type in string",
- )
- .into())
- }
- };
- let via = match data.next().expect("len == 3") {
- NestedMeta::Meta(Meta::Path(path)) => path
- .get_ident()
- .ok_or_else(|| syn::Error::new(item.span(), "via should be ident"))?,
- _ => return Err(syn::Error::new(item.span(), "via should be ident").into()),
- };
- let path = match data.next().expect("len == 3") {
- NestedMeta::Meta(Meta::Path(path)) => path,
- _ => return Err(syn::Error::new(item.span(), "path should be path").into()),
- };
-
- out.push(Is::new_via(path, Some((typ, via.clone())))?)
- }
- _ => {
- return Err(syn::Error::new(
- item.span(),
- "expected either Name or via(\"Type\", getter, Name)",
- )
- .into())
- }
- }
- }
- Ok(Self(out))
- }
-}
-
-#[derive(FromMeta)]
-pub struct InterfaceInfo {
- name: Ident,
- #[darling(default)]
- is: IsList,
- #[darling(default)]
- inline_is: IsList,
- #[darling(default)]
- events: IsList,
-}
-
-#[derive(FromMeta)]
-struct MethodInfo {
- #[darling(default)]
- rename_selector: Option<String>,
-}
-
-enum AbiType {
- // type
- Plain(Ident),
- // (type1,type2)
- Tuple(Vec<AbiType>),
- // type[]
- Vec(Box<AbiType>),
- // type[20]
- Array(Box<AbiType>, usize),
-}
-impl AbiType {
- fn try_from(value: &Type) -> syn::Result<Self> {
- let value = Self::try_maybe_special_from(value)?;
- if value.is_special() {
- return Err(syn::Error::new(value.span(), "unexpected special type"));
- }
- Ok(value)
- }
- fn try_maybe_special_from(value: &Type) -> syn::Result<Self> {
- match value {
- Type::Array(arr) => {
- let wrapped = AbiType::try_from(&arr.elem)?;
- match &arr.len {
- Expr::Lit(l) => match &l.lit {
- Lit::Int(i) => {
- let num = i.base10_parse::<usize>()?;
- Ok(AbiType::Array(Box::new(wrapped), num as usize))
- }
- _ => Err(syn::Error::new(arr.len.span(), "should be int literal")),
- },
- _ => Err(syn::Error::new(arr.len.span(), "should be literal")),
- }
- }
- Type::Path(_) => {
- let path = parse_path(value)?;
- let segment = parse_path_segment(path)?;
- if segment.ident == "Vec" {
- let args = match &segment.arguments {
- PathArguments::AngleBracketed(e) => e,
- _ => {
- return Err(syn::Error::new(
- segment.arguments.span(),
- "missing Vec generic",
- ))
- }
- };
- let args = &args.args;
- if args.len() != 1 {
- return Err(syn::Error::new(
- args.span(),
- "expected only one generic for vec",
- ));
- }
- let arg = args.first().unwrap();
-
- let ty = match arg {
- GenericArgument::Type(ty) => ty,
- _ => {
- return Err(syn::Error::new(
- arg.span(),
- "expected first generic to be type",
- ))
- }
- };
-
- let wrapped = AbiType::try_from(ty)?;
- Ok(Self::Vec(Box::new(wrapped)))
- } else {
- if !segment.arguments.is_empty() {
- return Err(syn::Error::new(
- segment.arguments.span(),
- "unexpected generic arguments for non-vec type",
- ));
- }
- Ok(Self::Plain(segment.ident.clone()))
- }
- }
- Type::Tuple(t) => {
- let mut out = Vec::with_capacity(t.elems.len());
- for el in t.elems.iter() {
- out.push(AbiType::try_from(el)?)
- }
- Ok(Self::Tuple(out))
- }
- _ => Err(syn::Error::new(
- value.span(),
- "unexpected type, only arrays, plain types and tuples are supported",
- )),
- }
- }
- fn is_value(&self) -> bool {
- matches!(self, Self::Plain(v) if v == "value")
- }
- fn is_caller(&self) -> bool {
- matches!(self, Self::Plain(v) if v == "caller")
- }
- fn is_special(&self) -> bool {
- self.is_caller() || self.is_value()
- }
- fn selector_ty_buf(&self, buf: &mut String) -> std::fmt::Result {
- match self {
- AbiType::Plain(t) => {
- write!(buf, "{}", t)
- }
- AbiType::Tuple(t) => {
- write!(buf, "(")?;
- for (i, t) in t.iter().enumerate() {
- if i != 0 {
- write!(buf, ",")?;
- }
- t.selector_ty_buf(buf)?;
- }
- write!(buf, ")")
- }
- AbiType::Vec(v) => {
- v.selector_ty_buf(buf)?;
- write!(buf, "[]")
- }
- AbiType::Array(v, len) => {
- v.selector_ty_buf(buf)?;
- write!(buf, "[{}]", len)
- }
- }
- }
- fn selector_ty(&self) -> String {
- let mut out = String::new();
- self.selector_ty_buf(&mut out).expect("no fmt error");
- out
- }
-}
-impl ToTokens for AbiType {
- fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
- match self {
- AbiType::Plain(t) => tokens.extend(quote! {#t}),
- AbiType::Tuple(t) => {
- tokens.extend(quote! {(
- #(#t),*
- )});
- }
- AbiType::Vec(v) => tokens.extend(quote! {Vec<#v>}),
- AbiType::Array(v, l) => tokens.extend(quote! {[#v; #l]}),
- }
- }
-}
-
-struct MethodArg {
- name: Ident,
- camel_name: String,
- ty: AbiType,
-}
-impl MethodArg {
- fn try_from(value: &PatType) -> syn::Result<Self> {
- let name = parse_ident_from_pat(&value.pat)?.clone();
- Ok(Self {
- camel_name: cases::camelcase::to_camel_case(&name.to_string()),
- name,
- ty: AbiType::try_maybe_special_from(&value.ty)?,
- })
- }
- fn is_value(&self) -> bool {
- self.ty.is_value()
- }
- fn is_caller(&self) -> bool {
- self.ty.is_caller()
- }
- fn is_special(&self) -> bool {
- self.ty.is_special()
- }
- fn selector_ty(&self) -> String {
- assert!(!self.is_special());
- self.ty.selector_ty()
- }
-
- fn expand_call_def(&self) -> proc_macro2::TokenStream {
- assert!(!self.is_special());
- let name = &self.name;
- let ty = &self.ty;
-
- quote! {
- #name: #ty
- }
- }
-
- fn expand_parse(&self) -> proc_macro2::TokenStream {
- assert!(!self.is_special());
- let name = &self.name;
- quote! {
- #name: reader.abi_read()?
- }
- }
-
- fn expand_call_arg(&self) -> proc_macro2::TokenStream {
- if self.is_value() {
- quote! {
- c.value.clone()
- }
- } else if self.is_caller() {
- quote! {
- c.caller.clone()
- }
- } else {
- let name = &self.name;
- quote! {
- #name
- }
- }
- }
-
- fn expand_solidity_argument(&self) -> proc_macro2::TokenStream {
- let camel_name = &self.camel_name.to_string();
- let ty = &self.ty;
- quote! {
- <NamedArgument<#ty>>::new(#camel_name)
- }
- }
-}
-
-#[derive(PartialEq)]
-enum Mutability {
- Mutable,
- View,
- Pure,
-}
-
-pub struct WeightAttr(syn::Expr);
-
-mod keyword {
- syn::custom_keyword!(weight);
-}
-
-impl syn::parse::Parse for WeightAttr {
- fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
- input.parse::<syn::Token![#]>()?;
- let content;
- syn::bracketed!(content in input);
- content.parse::<keyword::weight>()?;
-
- let weight_content;
- syn::parenthesized!(weight_content in content);
- Ok(WeightAttr(weight_content.parse::<syn::Expr>()?))
- }
-}
-
-struct Method {
- name: Ident,
- camel_name: String,
- pascal_name: Ident,
- screaming_name: Ident,
- selector_str: String,
- selector: u32,
- args: Vec<MethodArg>,
- has_normal_args: bool,
- mutability: Mutability,
- result: Type,
- weight: Option<Expr>,
- docs: Vec<String>,
-}
-impl Method {
- fn try_from(value: &ImplItemMethod) -> syn::Result<Self> {
- let mut info = MethodInfo {
- rename_selector: None,
- };
- let mut docs = Vec::new();
- let mut weight = None;
- for attr in &value.attrs {
- let ident = parse_ident_from_path(&attr.path, false)?;
- if ident == "solidity" {
- let args = attr.parse_meta().unwrap();
- info = MethodInfo::from_meta(&args).unwrap();
- } else if ident == "doc" {
- let args = attr.parse_meta().unwrap();
- let value = match args {
- Meta::NameValue(MetaNameValue {
- lit: Lit::Str(str), ..
- }) => str.value(),
- _ => unreachable!(),
- };
- docs.push(value);
- } else if ident == "weight" {
- weight = Some(syn::parse2::<WeightAttr>(attr.to_token_stream())?.0);
- }
- }
- let ident = &value.sig.ident;
- let ident_str = ident.to_string();
- if !cases::snakecase::is_snake_case(&ident_str) {
- return Err(syn::Error::new(ident.span(), "method name should be snake_cased\nif alternative solidity name needs to be set - use #[solidity] attribute"));
- }
-
- let mut mutability = Mutability::Pure;
-
- if let Some(FnArg::Receiver(receiver)) = value
- .sig
- .inputs
- .iter()
- .find(|arg| matches!(arg, FnArg::Receiver(_)))
- {
- if receiver.reference.is_none() {
- return Err(syn::Error::new(
- receiver.span(),
- "receiver should be by ref",
- ));
- }
- if receiver.mutability.is_some() {
- mutability = Mutability::Mutable;
- } else {
- mutability = Mutability::View;
- }
- }
- let mut args = Vec::new();
- for typ in value
- .sig
- .inputs
- .iter()
- .filter(|arg| matches!(arg, FnArg::Typed(_)))
- {
- let typ = match typ {
- FnArg::Typed(typ) => typ,
- _ => unreachable!(),
- };
- args.push(MethodArg::try_from(typ)?);
- }
-
- if mutability != Mutability::Mutable && args.iter().any(|arg| arg.is_value()) {
- return Err(syn::Error::new(
- args.iter().find(|arg| arg.is_value()).unwrap().ty.span(),
- "payable function should be mutable",
- ));
- }
-
- let result = match &value.sig.output {
- ReturnType::Type(_, ty) => ty,
- _ => return Err(syn::Error::new(value.sig.output.span(), "interface method should return Result<value>\nif there is no value to return - specify void (which is alias to unit)")),
- };
- let result = parse_result_ok(result)?;
-
- let camel_name = info
- .rename_selector
- .unwrap_or_else(|| cases::camelcase::to_camel_case(&ident.to_string()));
- let mut selector_str = camel_name.clone();
- selector_str.push('(');
- let mut has_normal_args = false;
- for (i, arg) in args.iter().filter(|arg| !arg.is_special()).enumerate() {
- if i != 0 {
- selector_str.push(',');
- }
- write!(selector_str, "{}", arg.selector_ty()).unwrap();
- has_normal_args = true;
- }
- selector_str.push(')');
- let selector = fn_selector_str(&selector_str);
-
- Ok(Self {
- name: ident.clone(),
- camel_name,
- pascal_name: snake_ident_to_pascal(ident),
- screaming_name: snake_ident_to_screaming(ident),
- selector_str,
- selector,
- args,
- has_normal_args,
- mutability,
- result: result.clone(),
- weight,
- docs,
- })
- }
- fn expand_call_def(&self) -> proc_macro2::TokenStream {
- let defs = self
- .args
- .iter()
- .filter(|a| !a.is_special())
- .map(|a| a.expand_call_def());
- let pascal_name = &self.pascal_name;
-
- if self.has_normal_args {
- quote! {
- #pascal_name {
- #(
- #defs,
- )*
- }
- }
- } else {
- quote! {#pascal_name}
- }
- }
-
- fn expand_const(&self) -> proc_macro2::TokenStream {
- let screaming_name = &self.screaming_name;
- let selector = u32::to_be_bytes(self.selector);
- let selector_str = &self.selector_str;
- quote! {
- #[doc = #selector_str]
- const #screaming_name: ::evm_coder::types::bytes4 = [#(#selector,)*];
- }
- }
-
- fn expand_interface_id(&self) -> proc_macro2::TokenStream {
- let screaming_name = &self.screaming_name;
- quote! {
- interface_id ^= u32::from_be_bytes(Self::#screaming_name);
- }
- }
-
- fn expand_parse(&self) -> proc_macro2::TokenStream {
- let pascal_name = &self.pascal_name;
- let screaming_name = &self.screaming_name;
- if self.has_normal_args {
- let parsers = self
- .args
- .iter()
- .filter(|a| !a.is_special())
- .map(|a| a.expand_parse());
- quote! {
- Self::#screaming_name => return Ok(Some(Self::#pascal_name {
- #(
- #parsers,
- )*
- }))
- }
- } else {
- quote! { Self::#screaming_name => return Ok(Some(Self::#pascal_name)) }
- }
- }
-
- fn expand_variant_call(&self, call_name: &proc_macro2::Ident) -> proc_macro2::TokenStream {
- let pascal_name = &self.pascal_name;
- let name = &self.name;
-
- let matcher = if self.has_normal_args {
- let names = self
- .args
- .iter()
- .filter(|a| !a.is_special())
- .map(|a| &a.name);
-
- quote! {{
- #(
- #names,
- )*
- }}
- } else {
- quote! {}
- };
-
- let receiver = match self.mutability {
- Mutability::Mutable | Mutability::View => quote! {self.},
- Mutability::Pure => quote! {Self::},
- };
- let args = self.args.iter().map(|a| a.expand_call_arg());
-
- quote! {
- #call_name::#pascal_name #matcher => {
- let result = #receiver #name(
- #(
- #args,
- )*
- )?;
- (&result).to_result()
- }
- }
- }
-
- fn expand_variant_weight(&self) -> proc_macro2::TokenStream {
- let pascal_name = &self.pascal_name;
- if let Some(weight) = &self.weight {
- let matcher = if self.has_normal_args {
- let names = self
- .args
- .iter()
- .filter(|a| !a.is_special())
- .map(|a| &a.name);
-
- quote! {{
- #(
- #names,
- )*
- }}
- } else {
- quote! {}
- };
- quote! {
- Self::#pascal_name #matcher => (#weight).into()
- }
- } else {
- let matcher = if self.has_normal_args {
- quote! {{..}}
- } else {
- quote! {}
- };
- quote! {
- Self::#pascal_name #matcher => ().into()
- }
- }
- }
-
- fn expand_solidity_function(&self) -> proc_macro2::TokenStream {
- let camel_name = &self.camel_name;
- let mutability = match self.mutability {
- Mutability::Mutable => quote! {SolidityMutability::Mutable},
- Mutability::View => quote! { SolidityMutability::View },
- Mutability::Pure => quote! {SolidityMutability::Pure},
- };
- let result = &self.result;
-
- let args = self
- .args
- .iter()
- .filter(|a| !a.is_special())
- .map(MethodArg::expand_solidity_argument);
- let docs = self.docs.iter();
- let selector = format!("{} {:0>8x}", self.selector_str, self.selector);
-
- quote! {
- SolidityFunction {
- docs: &[#(#docs),*],
- selector: #selector,
- name: #camel_name,
- mutability: #mutability,
- args: (
- #(
- #args,
- )*
- ),
- result: <UnnamedArgument<#result>>::default(),
- }
- }
- }
-}
-
-fn generics_list(gen: &Generics) -> proc_macro2::TokenStream {
- if gen.params.is_empty() {
- return quote! {};
- }
- let params = gen.params.iter().map(|p| match p {
- syn::GenericParam::Type(id) => {
- let v = &id.ident;
- quote! {#v}
- }
- syn::GenericParam::Lifetime(lt) => {
- let v = <.lifetime;
- quote! {#v}
- }
- syn::GenericParam::Const(c) => {
- let i = &c.ident;
- quote! {#i}
- }
- });
- quote! { #(#params),* }
-}
-fn generics_reference(gen: &Generics) -> proc_macro2::TokenStream {
- if gen.params.is_empty() {
- return quote! {};
- }
- let list = generics_list(gen);
- quote! { <#list> }
-}
-fn generics_data(gen: &Generics) -> proc_macro2::TokenStream {
- let list = generics_list(gen);
- if gen.params.len() == 1 {
- quote! {#list}
- } else {
- quote! { (#list) }
- }
-}
-
-pub struct SolidityInterface {
- generics: Generics,
- name: Box<syn::Type>,
- info: InterfaceInfo,
- methods: Vec<Method>,
-}
-impl SolidityInterface {
- pub fn try_from(info: InterfaceInfo, value: &ItemImpl) -> syn::Result<Self> {
- let mut methods = Vec::new();
-
- for item in &value.items {
- if let ImplItem::Method(method) = item {
- methods.push(Method::try_from(method)?)
- }
- }
- Ok(Self {
- generics: value.generics.clone(),
- name: value.self_ty.clone(),
- info,
- methods,
- })
- }
- pub fn expand(self) -> proc_macro2::TokenStream {
- let name = self.name;
-
- let solidity_name = self.info.name.to_string();
- let call_name = pascal_ident_to_call(&self.info.name);
- let generics = self.generics;
- let gen_ref = generics_reference(&generics);
- let gen_data = generics_data(&generics);
- let gen_where = &generics.where_clause;
-
- let call_sub = self
- .info
- .inline_is
- .0
- .iter()
- .chain(self.info.is.0.iter())
- .map(|c| Is::expand_call_def(c, &gen_ref));
- let call_parse = self
- .info
- .inline_is
- .0
- .iter()
- .chain(self.info.is.0.iter())
- .map(|is| Is::expand_parse(is, &gen_ref));
- let call_variants = self
- .info
- .inline_is
- .0
- .iter()
- .chain(self.info.is.0.iter())
- .map(|c| Is::expand_variant_call(c, &call_name, &gen_ref));
- let weight_variants = self
- .info
- .inline_is
- .0
- .iter()
- .chain(self.info.is.0.iter())
- .map(Is::expand_variant_weight);
-
- let inline_interface_id = self.info.inline_is.0.iter().map(Is::expand_interface_id);
- let supports_interface = self
- .info
- .is
- .0
- .iter()
- .map(|is| Is::expand_supports_interface(is, &gen_ref));
-
- let calls = self.methods.iter().map(Method::expand_call_def);
- let consts = self.methods.iter().map(Method::expand_const);
- let interface_id = self.methods.iter().map(Method::expand_interface_id);
- let parsers = self.methods.iter().map(Method::expand_parse);
- let call_variants_this = self
- .methods
- .iter()
- .map(|m| Method::expand_variant_call(m, &call_name));
- let weight_variants_this = self.methods.iter().map(Method::expand_variant_weight);
- let solidity_functions = self.methods.iter().map(Method::expand_solidity_function);
-
- // TODO: Inline inline_is
- let solidity_is = self
- .info
- .is
- .0
- .iter()
- .chain(self.info.inline_is.0.iter())
- .map(|is| is.name.to_string());
- let solidity_events_is = self.info.events.0.iter().map(|is| is.name.to_string());
- let solidity_generators = self
- .info
- .is
- .0
- .iter()
- .chain(self.info.inline_is.0.iter())
- .map(|is| Is::expand_generator(is, &gen_ref));
- let solidity_event_generators = self.info.events.0.iter().map(Is::expand_event_generator);
-
- // let methods = self.methods.iter().map(Method::solidity_def);
-
- quote! {
- #[derive(Debug)]
- pub enum #call_name #gen_ref {
- ERC165Call(::evm_coder::ERC165Call, ::core::marker::PhantomData<#gen_data>),
- #(
- #calls,
- )*
- #(
- #call_sub,
- )*
- }
- impl #gen_ref #call_name #gen_ref {
- #(
- #consts
- )*
- pub fn interface_id() -> ::evm_coder::types::bytes4 {
- let mut interface_id = 0;
- #(#interface_id)*
- #(#inline_interface_id)*
- u32::to_be_bytes(interface_id)
- }
- pub fn supports_interface(interface_id: ::evm_coder::types::bytes4) -> bool {
- interface_id != u32::to_be_bytes(0xffffff) && (
- interface_id == ::evm_coder::ERC165Call::INTERFACE_ID ||
- interface_id == Self::interface_id()
- #(
- || #supports_interface
- )*
- )
- }
- pub fn generate_solidity_interface(tc: &evm_coder::solidity::TypeCollector, is_impl: bool) {
- use evm_coder::solidity::*;
- use core::fmt::Write;
- let interface = SolidityInterface {
- name: #solidity_name,
- selector: Self::interface_id(),
- is: &["Dummy", "ERC165", #(
- #solidity_is,
- )* #(
- #solidity_events_is,
- )* ],
- functions: (#(
- #solidity_functions,
- )*),
- };
- if is_impl {
- tc.collect("// Common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\ncontract ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool) {\n\t\trequire(false, stub_error);\n\t\tinterfaceID;\n\t\treturn true;\n\t}\n}\n".into());
- } else {
- tc.collect("// Common stubs holder\ninterface Dummy {\n}\ninterface ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n".into());
- }
- #(
- #solidity_generators
- )*
- #(
- #solidity_event_generators
- )*
-
- let mut out = string::new();
- // In solidity interface usage (is) should be preceeded by interface definition
- // This comment helps to sort it in a set
- if #solidity_name.starts_with("Inline") {
- out.push_str("// Inline\n");
- }
- let _ = interface.format(is_impl, &mut out, tc);
- tc.collect(out);
- }
- }
- impl #gen_ref ::evm_coder::Call for #call_name #gen_ref {
- fn parse(method_id: ::evm_coder::types::bytes4, reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result<Option<Self>> {
- use ::evm_coder::abi::AbiRead;
- match method_id {
- ::evm_coder::ERC165Call::INTERFACE_ID => return Ok(
- ::evm_coder::ERC165Call::parse(method_id, reader)?
- .map(|c| Self::ERC165Call(c, ::core::marker::PhantomData))
- ),
- #(
- #parsers,
- )*
- _ => {},
- }
- #(
- #call_parse
- )else*
- return Ok(None);
- }
- }
- impl #generics ::evm_coder::Weighted for #call_name #gen_ref
- #gen_where
- {
- #[allow(unused_variables)]
- fn weight(&self) -> ::evm_coder::execution::DispatchInfo {
- match self {
- #(
- #weight_variants,
- )*
- // TODO: It should be very cheap, but not free
- Self::ERC165Call(::evm_coder::ERC165Call::SupportsInterface {..}, _) => 100u64.into(),
- #(
- #weight_variants_this,
- )*
- }
- }
- }
- impl #generics ::evm_coder::Callable<#call_name #gen_ref> for #name
- #gen_where
- {
- #[allow(unreachable_code)] // In case of no inner calls
- fn call(&mut self, c: Msg<#call_name #gen_ref>) -> ::evm_coder::execution::ResultWithPostInfo<::evm_coder::abi::AbiWriter> {
- use ::evm_coder::abi::AbiWrite;
- match c.call {
- #(
- #call_variants,
- )*
- #call_name::ERC165Call(::evm_coder::ERC165Call::SupportsInterface {interface_id}, _) => {
- let mut writer = ::evm_coder::abi::AbiWriter::default();
- writer.bool(&<#call_name #gen_ref>::supports_interface(interface_id));
- return Ok(writer.into());
- }
- _ => {},
- }
- let mut writer = ::evm_coder::abi::AbiWriter::default();
- match c.call {
- #(
- #call_variants_this,
- )*
- _ => unreachable!()
- }
- }
- }
- }
- }
-}
crates/evm-coder-macros/src/to_log.rsdiffbeforeafterboth--- a/crates/evm-coder-macros/src/to_log.rs
+++ /dev/null
@@ -1,237 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-use inflector::cases;
-use syn::{Data, DeriveInput, Field, Fields, Ident, Variant, spanned::Spanned};
-use std::fmt::Write;
-use quote::quote;
-
-use crate::{parse_ident_from_path, parse_ident_from_type, snake_ident_to_screaming};
-
-struct EventField {
- name: Ident,
- camel_name: String,
- ty: Ident,
- indexed: bool,
-}
-
-impl EventField {
- fn try_from(field: &Field) -> syn::Result<Self> {
- let name = field.ident.as_ref().unwrap();
- let ty = parse_ident_from_type(&field.ty, false)?;
- let mut indexed = false;
- for attr in &field.attrs {
- if let Ok(ident) = parse_ident_from_path(&attr.path, false) {
- if ident == "indexed" {
- indexed = true;
- }
- }
- }
- Ok(Self {
- name: name.to_owned(),
- camel_name: cases::camelcase::to_camel_case(&name.to_string()),
- ty: ty.to_owned(),
- indexed,
- })
- }
- fn expand_solidity_argument(&self) -> proc_macro2::TokenStream {
- let camel_name = &self.camel_name;
- let ty = &self.ty;
- let indexed = self.indexed;
- quote! {
- <SolidityEventArgument<#ty>>::new(#indexed, #camel_name)
- }
- }
-}
-
-struct Event {
- name: Ident,
- name_screaming: Ident,
- fields: Vec<EventField>,
- selector: [u8; 32],
- selector_str: String,
-}
-
-impl Event {
- fn try_from(variant: &Variant) -> syn::Result<Self> {
- let name = &variant.ident;
- let name_screaming = snake_ident_to_screaming(name);
-
- let named = match &variant.fields {
- Fields::Named(named) => named,
- _ => {
- return Err(syn::Error::new(
- variant.fields.span(),
- "expected named fields",
- ))
- }
- };
- let mut fields = Vec::new();
- for field in &named.named {
- fields.push(EventField::try_from(field)?);
- }
- if fields.iter().filter(|f| f.indexed).count() > 3 {
- return Err(syn::Error::new(
- variant.fields.span(),
- "events can have at most 4 indexed fields (1 indexed field is reserved for event signature)"
- ));
- }
- let mut selector_str = format!("{}(", name);
- for (i, arg) in fields.iter().enumerate() {
- if i != 0 {
- write!(selector_str, ",").unwrap();
- }
- write!(selector_str, "{}", arg.ty).unwrap();
- }
- selector_str.push(')');
- let selector = crate::event_selector_str(&selector_str);
-
- Ok(Self {
- name: name.to_owned(),
- name_screaming,
- fields,
- selector,
- selector_str,
- })
- }
-
- fn expand_serializers(&self) -> proc_macro2::TokenStream {
- let name = &self.name;
- let name_screaming = &self.name_screaming;
- let fields = self.fields.iter().map(|f| &f.name);
-
- let indexed = self.fields.iter().filter(|f| f.indexed).map(|f| &f.name);
- let plain = self.fields.iter().filter(|f| !f.indexed).map(|f| &f.name);
-
- quote! {
- Self::#name {#(
- #fields,
- )*} => {
- topics.push(topic::from(Self::#name_screaming));
- #(
- topics.push(#indexed.to_topic());
- )*
- #(
- #plain.abi_write(&mut writer);
- )*
- }
- }
- }
-
- fn expand_consts(&self) -> proc_macro2::TokenStream {
- let name_screaming = &self.name_screaming;
- let selector_str = &self.selector_str;
- let selector = &self.selector;
-
- quote! {
- #[doc = #selector_str]
- const #name_screaming: [u8; 32] = [#(
- #selector,
- )*];
- }
- }
-
- fn expand_solidity_function(&self) -> proc_macro2::TokenStream {
- let name = self.name.to_string();
- let args = self.fields.iter().map(EventField::expand_solidity_argument);
- quote! {
- SolidityEvent {
- name: #name,
- args: (
- #(
- #args,
- )*
- ),
- }
- }
- }
-}
-
-pub struct Events {
- name: Ident,
- events: Vec<Event>,
-}
-
-impl Events {
- pub fn try_from(data: &DeriveInput) -> syn::Result<Self> {
- let name = &data.ident;
- let en = match &data.data {
- Data::Enum(en) => en,
- _ => return Err(syn::Error::new(data.span(), "expected enum")),
- };
- let mut events = Vec::new();
- for variant in &en.variants {
- events.push(Event::try_from(variant)?);
- }
- Ok(Self {
- name: name.to_owned(),
- events,
- })
- }
- pub fn expand(&self) -> proc_macro2::TokenStream {
- let name = &self.name;
-
- let consts = self.events.iter().map(Event::expand_consts);
- let serializers = self.events.iter().map(Event::expand_serializers);
- let solidity_name = self.name.to_string();
- let solidity_functions = self.events.iter().map(Event::expand_solidity_function);
-
- quote! {
- impl #name {
- #(
- #consts
- )*
-
- pub fn generate_solidity_interface(tc: &evm_coder::solidity::TypeCollector, is_impl: bool) {
- use evm_coder::solidity::*;
- use core::fmt::Write;
- let interface = SolidityInterface {
- selector: [0; 4],
- name: #solidity_name,
- is: &[],
- functions: (#(
- #solidity_functions,
- )*),
- };
- let mut out = string::new();
- out.push_str("// Inline\n");
- let _ = interface.format(is_impl, &mut out, tc);
- tc.collect(out);
- }
- }
-
- #[automatically_derived]
- impl ::evm_coder::events::ToLog for #name {
- fn to_log(&self, contract: address) -> ::ethereum::Log {
- use ::evm_coder::events::ToTopic;
- use ::evm_coder::abi::AbiWrite;
- let mut writer = ::evm_coder::abi::AbiWriter::new();
- let mut topics = Vec::new();
- match self {
- #(
- #serializers,
- )*
- }
- ::ethereum::Log {
- address: contract,
- topics,
- data: writer.finish(),
- }
- }
- }
- }
- }
-}
crates/evm-coder/Cargo.tomldiffbeforeafterboth--- a/crates/evm-coder/Cargo.toml
+++ b/crates/evm-coder/Cargo.toml
@@ -5,15 +5,21 @@
edition = "2021"
[dependencies]
-evm-coder-macros = { path = "../evm-coder-macros" }
+# evm-coder reexports those proc-macro
+evm-coder-procedural = { path = "./procedural" }
+# Evm uses primitive-types for H160, H256 and others
primitive-types = { version = "0.11.1", default-features = false }
-hex-literal = "0.3.3"
+# Evm doesn't have reexports for log and others
ethereum = { version = "0.12.0", default-features = false }
+# Error types for execution
evm-core = { default-features = false, git = "https://github.com/uniquenetwork/evm", branch = "unique-polkadot-v0.9.27" }
-impl-trait-for-tuples = "0.2.1"
+# We have tuple-heavy code in solidity.rs
+impl-trait-for-tuples = "0.2.2"
[dev-dependencies]
+# We want to assert some large binary blobs equality in tests
hex = "0.4.3"
+hex-literal = "0.3.4"
[features]
default = ["std"]
crates/evm-coder/README.mddiffbeforeafterboth--- /dev/null
+++ b/crates/evm-coder/README.md
@@ -0,0 +1,15 @@
+# evm-coder
+
+Library for seamless call translation between Rust and Solidity code
+
+By encoding solidity definitions in Rust, this library also provides generation of
+solidity interfaces for ethereum developers
+
+## Overview
+
+Most of this library functionality shouldn't be used directly, but via macros
+
+- [`solidity_interface`]
+- [`ToLog`]
+
+<!-- TODO: make links useable on github, by publishing crate to docs.rs, and linking it from here instead -->
\ No newline at end of file
crates/evm-coder/procedural/Cargo.tomldiffbeforeafterboth--- /dev/null
+++ b/crates/evm-coder/procedural/Cargo.toml
@@ -0,0 +1,19 @@
+[package]
+name = "evm-coder-procedural"
+version = "0.2.0"
+license = "GPLv3"
+edition = "2021"
+
+[lib]
+proc-macro = true
+
+[dependencies]
+# Ethereum uses keccak (=sha3) for selectors
+sha3 = "0.10.1"
+# Value formatting
+hex = "0.4.3"
+Inflector = "0.11.4"
+# General proc-macro utilities
+quote = "1.0"
+proc-macro2 = "1.0"
+syn = { version = "1.0", features = ["full"] }
crates/evm-coder/procedural/src/lib.rsdiffbeforeafterboth--- /dev/null
+++ b/crates/evm-coder/procedural/src/lib.rs
@@ -0,0 +1,244 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
+#![allow(dead_code)]
+
+use inflector::cases;
+use proc_macro::TokenStream;
+use quote::quote;
+use sha3::{Digest, Keccak256};
+use syn::{
+ DeriveInput, GenericArgument, Ident, ItemImpl, Pat, Path, PathArguments, PathSegment, Type,
+ parse_macro_input, spanned::Spanned,
+};
+
+mod solidity_interface;
+mod to_log;
+
+fn fn_selector_str(input: &str) -> u32 {
+ let mut hasher = Keccak256::new();
+ hasher.update(input.as_bytes());
+ let result = hasher.finalize();
+
+ let mut selector_bytes = [0; 4];
+ selector_bytes.copy_from_slice(&result[0..4]);
+
+ u32::from_be_bytes(selector_bytes)
+}
+
+/// Returns solidity function selector (first 4 bytes of hash) by its
+/// textual representation
+///
+/// ```ignore
+/// use evm_coder_macros::fn_selector;
+///
+/// assert_eq!(fn_selector!(transfer(address, uint256)), 0xa9059cbb);
+/// ```
+#[proc_macro]
+pub fn fn_selector(input: TokenStream) -> TokenStream {
+ let input = input.to_string().replace(' ', "");
+ let selector = fn_selector_str(&input);
+
+ (quote! {
+ #selector
+ })
+ .into()
+}
+
+fn event_selector_str(input: &str) -> [u8; 32] {
+ let mut hasher = Keccak256::new();
+ hasher.update(input.as_bytes());
+ let result = hasher.finalize();
+
+ let mut selector_bytes = [0; 32];
+ selector_bytes.copy_from_slice(&result[0..32]);
+ selector_bytes
+}
+
+/// Returns solidity topic (hash) by its textual representation
+///
+/// ```ignore
+/// use evm_coder_macros::event_topic;
+///
+/// assert_eq!(
+/// format!("{:x}", event_topic!(Transfer(address, address, uint256))),
+/// "ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+/// );
+/// ```
+#[proc_macro]
+pub fn event_topic(stream: TokenStream) -> TokenStream {
+ let input = stream.to_string().replace(' ', "");
+ let selector_bytes = event_selector_str(&input);
+
+ (quote! {
+ ::primitive_types::H256([#(
+ #selector_bytes,
+ )*])
+ })
+ .into()
+}
+
+fn parse_path(ty: &Type) -> syn::Result<&Path> {
+ match &ty {
+ syn::Type::Path(pat) => {
+ if let Some(qself) = &pat.qself {
+ return Err(syn::Error::new(qself.ty.span(), "no receiver expected"));
+ }
+ Ok(&pat.path)
+ }
+ _ => Err(syn::Error::new(ty.span(), "expected ty to be path")),
+ }
+}
+
+fn parse_path_segment(path: &Path) -> syn::Result<&PathSegment> {
+ if path.segments.len() != 1 {
+ return Err(syn::Error::new(
+ path.span(),
+ "expected path to have only segment",
+ ));
+ }
+ let last_segment = &path.segments.last().unwrap();
+ Ok(last_segment)
+}
+
+fn parse_ident_from_pat(pat: &Pat) -> syn::Result<&Ident> {
+ match pat {
+ Pat::Ident(i) => Ok(&i.ident),
+ _ => Err(syn::Error::new(pat.span(), "expected pat ident")),
+ }
+}
+
+fn parse_ident_from_segment(segment: &PathSegment, allow_generics: bool) -> syn::Result<&Ident> {
+ if segment.arguments != PathArguments::None && !allow_generics {
+ return Err(syn::Error::new(
+ segment.arguments.span(),
+ "unexpected generic type",
+ ));
+ }
+ Ok(&segment.ident)
+}
+
+fn parse_ident_from_path(path: &Path, allow_generics: bool) -> syn::Result<&Ident> {
+ let segment = parse_path_segment(path)?;
+ parse_ident_from_segment(segment, allow_generics)
+}
+
+fn parse_ident_from_type(ty: &Type, allow_generics: bool) -> syn::Result<&Ident> {
+ let path = parse_path(ty)?;
+ parse_ident_from_path(path, allow_generics)
+}
+
+// Gets T out of Result<T>
+fn parse_result_ok(ty: &Type) -> syn::Result<&Type> {
+ let path = parse_path(ty)?;
+ let segment = parse_path_segment(path)?;
+
+ if segment.ident != "Result" {
+ return Err(syn::Error::new(
+ ty.span(),
+ "expected Result as return type (no renamed aliases allowed)",
+ ));
+ }
+ let args = match &segment.arguments {
+ PathArguments::AngleBracketed(e) => e,
+ _ => {
+ return Err(syn::Error::new(
+ segment.arguments.span(),
+ "missing Result generics",
+ ))
+ }
+ };
+
+ let args = &args.args;
+ let arg = args.first().unwrap();
+
+ let ty = match arg {
+ GenericArgument::Type(ty) => ty,
+ _ => {
+ return Err(syn::Error::new(
+ arg.span(),
+ "expected first generic to be type",
+ ))
+ }
+ };
+
+ Ok(ty)
+}
+
+fn pascal_ident_to_call(ident: &Ident) -> Ident {
+ let name = format!("{}Call", ident);
+ Ident::new(&name, ident.span())
+}
+fn snake_ident_to_pascal(ident: &Ident) -> Ident {
+ let name = ident.to_string();
+ let name = cases::pascalcase::to_pascal_case(&name);
+ Ident::new(&name, ident.span())
+}
+fn snake_ident_to_screaming(ident: &Ident) -> Ident {
+ let name = ident.to_string();
+ let name = cases::screamingsnakecase::to_screaming_snake_case(&name);
+ Ident::new(&name, ident.span())
+}
+fn pascal_ident_to_snake_call(ident: &Ident) -> Ident {
+ let name = ident.to_string();
+ let name = cases::snakecase::to_snake_case(&name);
+ let name = format!("call_{}", name);
+ Ident::new(&name, ident.span())
+}
+
+/// See documentation for this proc-macro reexported in `evm-coder` crate
+#[proc_macro_attribute]
+pub fn solidity_interface(args: TokenStream, stream: TokenStream) -> TokenStream {
+ let args = parse_macro_input!(args as solidity_interface::InterfaceInfo);
+
+ let input: ItemImpl = match syn::parse(stream) {
+ Ok(t) => t,
+ Err(e) => return e.to_compile_error().into(),
+ };
+
+ let expanded = match solidity_interface::SolidityInterface::try_from(args, &input) {
+ Ok(v) => v.expand(),
+ Err(e) => e.to_compile_error(),
+ };
+
+ (quote! {
+ #input
+
+ #expanded
+ })
+ .into()
+}
+
+#[proc_macro_attribute]
+pub fn solidity(_args: TokenStream, stream: TokenStream) -> TokenStream {
+ stream
+}
+#[proc_macro_attribute]
+pub fn weight(_args: TokenStream, stream: TokenStream) -> TokenStream {
+ stream
+}
+
+/// See documentation for this proc-macro reexported in `evm-coder` crate
+#[proc_macro_derive(ToLog, attributes(indexed))]
+pub fn to_log(value: TokenStream) -> TokenStream {
+ let input = parse_macro_input!(value as DeriveInput);
+
+ match to_log::Events::try_from(&input) {
+ Ok(e) => e.expand(),
+ Err(e) => e.to_compile_error(),
+ }
+ .into()
+}
crates/evm-coder/procedural/src/solidity_interface.rsdiffbeforeafterboth--- /dev/null
+++ b/crates/evm-coder/procedural/src/solidity_interface.rs
@@ -0,0 +1,1110 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
+#![allow(dead_code)]
+
+// NOTE: In order to understand this Rust macro better, first read this chapter
+// about Procedural Macros in Rust book:
+// https://doc.rust-lang.org/reference/procedural-macros.html
+
+use quote::{quote, ToTokens};
+use inflector::cases;
+use std::fmt::Write;
+use syn::{
+ Expr, FnArg, GenericArgument, Generics, Ident, ImplItem, ImplItemMethod, ItemImpl, Lit, Meta,
+ MetaNameValue, PatType, PathArguments, ReturnType, Type,
+ spanned::Spanned,
+ parse::{Parse, ParseStream},
+ parenthesized, Token, LitInt, LitStr,
+};
+
+use crate::{
+ fn_selector_str, parse_ident_from_pat, parse_ident_from_path, parse_path, parse_path_segment,
+ parse_result_ok, pascal_ident_to_call, pascal_ident_to_snake_call, snake_ident_to_pascal,
+ snake_ident_to_screaming,
+};
+
+struct Is {
+ name: Ident,
+ pascal_call_name: Ident,
+ snake_call_name: Ident,
+ via: Option<(Type, Ident)>,
+}
+impl Is {
+ fn expand_call_def(&self, gen_ref: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {
+ let name = &self.name;
+ let pascal_call_name = &self.pascal_call_name;
+ quote! {
+ #name(#pascal_call_name #gen_ref)
+ }
+ }
+
+ fn expand_interface_id(&self) -> proc_macro2::TokenStream {
+ let pascal_call_name = &self.pascal_call_name;
+ quote! {
+ interface_id ^= u32::from_be_bytes(#pascal_call_name::interface_id());
+ }
+ }
+
+ fn expand_supports_interface(
+ &self,
+ generics: &proc_macro2::TokenStream,
+ ) -> proc_macro2::TokenStream {
+ let pascal_call_name = &self.pascal_call_name;
+ quote! {
+ <#pascal_call_name #generics>::supports_interface(interface_id)
+ }
+ }
+
+ fn expand_variant_weight(&self) -> proc_macro2::TokenStream {
+ let name = &self.name;
+ quote! {
+ Self::#name(call) => call.weight()
+ }
+ }
+
+ fn expand_variant_call(
+ &self,
+ call_name: &proc_macro2::Ident,
+ generics: &proc_macro2::TokenStream,
+ ) -> proc_macro2::TokenStream {
+ let name = &self.name;
+ let pascal_call_name = &self.pascal_call_name;
+ let via_typ = self
+ .via
+ .as_ref()
+ .map(|(t, _)| quote! {#t})
+ .unwrap_or_else(|| quote! {Self});
+ let via_map = self
+ .via
+ .as_ref()
+ .map(|(_, i)| quote! {.#i()})
+ .unwrap_or_default();
+ quote! {
+ #call_name::#name(call) => return <#via_typ as ::evm_coder::Callable<#pascal_call_name #generics>>::call(self #via_map, Msg {
+ call,
+ caller: c.caller,
+ value: c.value,
+ })
+ }
+ }
+
+ fn expand_parse(&self, generics: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {
+ let name = &self.name;
+ let pascal_call_name = &self.pascal_call_name;
+ quote! {
+ if let Some(parsed_call) = <#pascal_call_name #generics>::parse(method_id, reader)? {
+ return Ok(Some(Self::#name(parsed_call)))
+ }
+ }
+ }
+
+ fn expand_generator(&self, generics: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {
+ let pascal_call_name = &self.pascal_call_name;
+ quote! {
+ <#pascal_call_name #generics>::generate_solidity_interface(tc, is_impl);
+ }
+ }
+
+ fn expand_event_generator(&self) -> proc_macro2::TokenStream {
+ let name = &self.name;
+ quote! {
+ #name::generate_solidity_interface(tc, is_impl);
+ }
+ }
+}
+
+#[derive(Default)]
+struct IsList(Vec<Is>);
+impl Parse for IsList {
+ fn parse(input: ParseStream) -> syn::Result<Self> {
+ let mut out = vec![];
+ loop {
+ if input.is_empty() {
+ break;
+ }
+ let name = input.parse::<Ident>()?;
+ let lookahead = input.lookahead1();
+ let via = if lookahead.peek(syn::token::Paren) {
+ let contents;
+ parenthesized!(contents in input);
+ let method = contents.parse::<Ident>()?;
+ contents.parse::<Token![,]>()?;
+ let ty = contents.parse::<Type>()?;
+ Some((ty, method))
+ } else if lookahead.peek(Token![,]) {
+ None
+ } else if input.is_empty() {
+ None
+ } else {
+ return Err(lookahead.error());
+ };
+ out.push(Is {
+ pascal_call_name: pascal_ident_to_call(&name),
+ snake_call_name: pascal_ident_to_snake_call(&name),
+ name,
+ via,
+ });
+ if input.peek(Token![,]) {
+ input.parse::<Token![,]>()?;
+ continue;
+ } else {
+ break;
+ }
+ }
+ Ok(Self(out))
+ }
+}
+
+pub struct InterfaceInfo {
+ name: Ident,
+ is: IsList,
+ inline_is: IsList,
+ events: IsList,
+ expect_selector: Option<u32>,
+}
+impl Parse for InterfaceInfo {
+ fn parse(input: ParseStream) -> syn::Result<Self> {
+ let mut name = None;
+ let mut is = None;
+ let mut inline_is = None;
+ let mut events = None;
+ let mut expect_selector = None;
+ // TODO: create proc-macro to optimize proc-macro boilerplate? :D
+ loop {
+ let lookahead = input.lookahead1();
+ if lookahead.peek(kw::name) {
+ let k = input.parse::<kw::name>()?;
+ input.parse::<Token![=]>()?;
+ if name.replace(input.parse::<Ident>()?).is_some() {
+ return Err(syn::Error::new(k.span(), "name is already set"));
+ }
+ } else if lookahead.peek(kw::is) {
+ let k = input.parse::<kw::is>()?;
+ let contents;
+ parenthesized!(contents in input);
+ if is.replace(contents.parse::<IsList>()?).is_some() {
+ return Err(syn::Error::new(k.span(), "is is already set"));
+ }
+ } else if lookahead.peek(kw::inline_is) {
+ let k = input.parse::<kw::inline_is>()?;
+ let contents;
+ parenthesized!(contents in input);
+ if inline_is.replace(contents.parse::<IsList>()?).is_some() {
+ return Err(syn::Error::new(k.span(), "inline_is is already set"));
+ }
+ } else if lookahead.peek(kw::events) {
+ let k = input.parse::<kw::events>()?;
+ let contents;
+ parenthesized!(contents in input);
+ if events.replace(contents.parse::<IsList>()?).is_some() {
+ return Err(syn::Error::new(k.span(), "events is already set"));
+ }
+ } else if lookahead.peek(kw::expect_selector) {
+ let k = input.parse::<kw::expect_selector>()?;
+ input.parse::<Token![=]>()?;
+ let value = input.parse::<LitInt>()?;
+ if expect_selector
+ .replace(value.base10_parse::<u32>()?)
+ .is_some()
+ {
+ return Err(syn::Error::new(k.span(), "expect_selector is already set"));
+ }
+ } else if input.is_empty() {
+ break;
+ } else {
+ return Err(lookahead.error());
+ }
+ if input.peek(Token![,]) {
+ input.parse::<Token![,]>()?;
+ } else {
+ break;
+ }
+ }
+ Ok(Self {
+ name: name.ok_or_else(|| syn::Error::new(input.span(), "missing name"))?,
+ is: is.unwrap_or_default(),
+ inline_is: inline_is.unwrap_or_default(),
+ events: events.unwrap_or_default(),
+ expect_selector,
+ })
+ }
+}
+
+struct MethodInfo {
+ rename_selector: Option<String>,
+}
+impl Parse for MethodInfo {
+ fn parse(input: ParseStream) -> syn::Result<Self> {
+ let mut rename_selector = None;
+ let lookahead = input.lookahead1();
+ if lookahead.peek(kw::rename_selector) {
+ let k = input.parse::<kw::rename_selector>()?;
+ input.parse::<Token![=]>()?;
+ if rename_selector
+ .replace(input.parse::<LitStr>()?.value())
+ .is_some()
+ {
+ return Err(syn::Error::new(k.span(), "rename_selector is already set"));
+ }
+ }
+ Ok(Self { rename_selector })
+ }
+}
+
+enum AbiType {
+ // type
+ Plain(Ident),
+ // (type1,type2)
+ Tuple(Vec<AbiType>),
+ // type[]
+ Vec(Box<AbiType>),
+ // type[20]
+ Array(Box<AbiType>, usize),
+}
+impl AbiType {
+ fn try_from(value: &Type) -> syn::Result<Self> {
+ let value = Self::try_maybe_special_from(value)?;
+ if value.is_special() {
+ return Err(syn::Error::new(value.span(), "unexpected special type"));
+ }
+ Ok(value)
+ }
+ fn try_maybe_special_from(value: &Type) -> syn::Result<Self> {
+ match value {
+ Type::Array(arr) => {
+ let wrapped = AbiType::try_from(&arr.elem)?;
+ match &arr.len {
+ Expr::Lit(l) => match &l.lit {
+ Lit::Int(i) => {
+ let num = i.base10_parse::<usize>()?;
+ Ok(AbiType::Array(Box::new(wrapped), num as usize))
+ }
+ _ => Err(syn::Error::new(arr.len.span(), "should be int literal")),
+ },
+ _ => Err(syn::Error::new(arr.len.span(), "should be literal")),
+ }
+ }
+ Type::Path(_) => {
+ let path = parse_path(value)?;
+ let segment = parse_path_segment(path)?;
+ if segment.ident == "Vec" {
+ let args = match &segment.arguments {
+ PathArguments::AngleBracketed(e) => e,
+ _ => {
+ return Err(syn::Error::new(
+ segment.arguments.span(),
+ "missing Vec generic",
+ ))
+ }
+ };
+ let args = &args.args;
+ if args.len() != 1 {
+ return Err(syn::Error::new(
+ args.span(),
+ "expected only one generic for vec",
+ ));
+ }
+ let arg = args.first().expect("first arg");
+
+ let ty = match arg {
+ GenericArgument::Type(ty) => ty,
+ _ => {
+ return Err(syn::Error::new(
+ arg.span(),
+ "expected first generic to be type",
+ ))
+ }
+ };
+
+ let wrapped = AbiType::try_from(ty)?;
+ Ok(Self::Vec(Box::new(wrapped)))
+ } else {
+ if !segment.arguments.is_empty() {
+ return Err(syn::Error::new(
+ segment.arguments.span(),
+ "unexpected generic arguments for non-vec type",
+ ));
+ }
+ Ok(Self::Plain(segment.ident.clone()))
+ }
+ }
+ Type::Tuple(t) => {
+ let mut out = Vec::with_capacity(t.elems.len());
+ for el in t.elems.iter() {
+ out.push(AbiType::try_from(el)?)
+ }
+ Ok(Self::Tuple(out))
+ }
+ _ => Err(syn::Error::new(
+ value.span(),
+ "unexpected type, only arrays, plain types and tuples are supported",
+ )),
+ }
+ }
+ fn is_value(&self) -> bool {
+ matches!(self, Self::Plain(v) if v == "value")
+ }
+ fn is_caller(&self) -> bool {
+ matches!(self, Self::Plain(v) if v == "caller")
+ }
+ fn is_special(&self) -> bool {
+ self.is_caller() || self.is_value()
+ }
+ fn selector_ty_buf(&self, buf: &mut String) -> std::fmt::Result {
+ match self {
+ AbiType::Plain(t) => {
+ write!(buf, "{}", t)
+ }
+ AbiType::Tuple(t) => {
+ write!(buf, "(")?;
+ for (i, t) in t.iter().enumerate() {
+ if i != 0 {
+ write!(buf, ",")?;
+ }
+ t.selector_ty_buf(buf)?;
+ }
+ write!(buf, ")")
+ }
+ AbiType::Vec(v) => {
+ v.selector_ty_buf(buf)?;
+ write!(buf, "[]")
+ }
+ AbiType::Array(v, len) => {
+ v.selector_ty_buf(buf)?;
+ write!(buf, "[{}]", len)
+ }
+ }
+ }
+ fn selector_ty(&self) -> String {
+ let mut out = String::new();
+ self.selector_ty_buf(&mut out).expect("no fmt error");
+ out
+ }
+}
+impl ToTokens for AbiType {
+ fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
+ match self {
+ AbiType::Plain(t) => tokens.extend(quote! {#t}),
+ AbiType::Tuple(t) => {
+ tokens.extend(quote! {(
+ #(#t),*
+ )});
+ }
+ AbiType::Vec(v) => tokens.extend(quote! {Vec<#v>}),
+ AbiType::Array(v, l) => tokens.extend(quote! {[#v; #l]}),
+ }
+ }
+}
+
+struct MethodArg {
+ name: Ident,
+ camel_name: String,
+ ty: AbiType,
+}
+impl MethodArg {
+ fn try_from(value: &PatType) -> syn::Result<Self> {
+ let name = parse_ident_from_pat(&value.pat)?.clone();
+ Ok(Self {
+ camel_name: cases::camelcase::to_camel_case(&name.to_string()),
+ name,
+ ty: AbiType::try_maybe_special_from(&value.ty)?,
+ })
+ }
+ fn is_value(&self) -> bool {
+ self.ty.is_value()
+ }
+ fn is_caller(&self) -> bool {
+ self.ty.is_caller()
+ }
+ fn is_special(&self) -> bool {
+ self.ty.is_special()
+ }
+ fn selector_ty(&self) -> String {
+ assert!(!self.is_special());
+ self.ty.selector_ty()
+ }
+
+ fn expand_call_def(&self) -> proc_macro2::TokenStream {
+ assert!(!self.is_special());
+ let name = &self.name;
+ let ty = &self.ty;
+
+ quote! {
+ #name: #ty
+ }
+ }
+
+ fn expand_parse(&self) -> proc_macro2::TokenStream {
+ assert!(!self.is_special());
+ let name = &self.name;
+ quote! {
+ #name: reader.abi_read()?
+ }
+ }
+
+ fn expand_call_arg(&self) -> proc_macro2::TokenStream {
+ if self.is_value() {
+ quote! {
+ c.value.clone()
+ }
+ } else if self.is_caller() {
+ quote! {
+ c.caller.clone()
+ }
+ } else {
+ let name = &self.name;
+ quote! {
+ #name
+ }
+ }
+ }
+
+ fn expand_solidity_argument(&self) -> proc_macro2::TokenStream {
+ let camel_name = &self.camel_name.to_string();
+ let ty = &self.ty;
+ quote! {
+ <NamedArgument<#ty>>::new(#camel_name)
+ }
+ }
+}
+
+#[derive(PartialEq)]
+enum Mutability {
+ Mutable,
+ View,
+ Pure,
+}
+
+/// Group all keywords for this macro. Usage example:
+/// #[solidity_interface(name = "B", inline_is(A))]
+mod kw {
+ syn::custom_keyword!(weight);
+
+ syn::custom_keyword!(via);
+ syn::custom_keyword!(name);
+ syn::custom_keyword!(is);
+ syn::custom_keyword!(inline_is);
+ syn::custom_keyword!(events);
+ syn::custom_keyword!(expect_selector);
+
+ syn::custom_keyword!(rename_selector);
+}
+
+/// Rust methods are parsed into this structure when Solidity code is generated
+struct Method {
+ name: Ident,
+ camel_name: String,
+ pascal_name: Ident,
+ screaming_name: Ident,
+ selector_str: String,
+ selector: u32,
+ args: Vec<MethodArg>,
+ has_normal_args: bool,
+ mutability: Mutability,
+ result: Type,
+ weight: Option<Expr>,
+ docs: Vec<String>,
+}
+impl Method {
+ fn try_from(value: &ImplItemMethod) -> syn::Result<Self> {
+ let mut info = MethodInfo {
+ rename_selector: None,
+ };
+ let mut docs = Vec::new();
+ let mut weight = None;
+ for attr in &value.attrs {
+ let ident = parse_ident_from_path(&attr.path, false)?;
+ if ident == "solidity" {
+ info = attr.parse_args::<MethodInfo>()?;
+ } else if ident == "doc" {
+ let args = attr.parse_meta().unwrap();
+ let value = match args {
+ Meta::NameValue(MetaNameValue {
+ lit: Lit::Str(str), ..
+ }) => str.value(),
+ _ => unreachable!(),
+ };
+ docs.push(value);
+ } else if ident == "weight" {
+ weight = Some(attr.parse_args::<Expr>()?);
+ }
+ }
+ let ident = &value.sig.ident;
+ let ident_str = ident.to_string();
+ if !cases::snakecase::is_snake_case(&ident_str) {
+ return Err(syn::Error::new(ident.span(), "method name should be snake_cased\nif alternative solidity name needs to be set - use #[solidity] attribute"));
+ }
+
+ let mut mutability = Mutability::Pure;
+
+ if let Some(FnArg::Receiver(receiver)) = value
+ .sig
+ .inputs
+ .iter()
+ .find(|arg| matches!(arg, FnArg::Receiver(_)))
+ {
+ if receiver.reference.is_none() {
+ return Err(syn::Error::new(
+ receiver.span(),
+ "receiver should be by ref",
+ ));
+ }
+ if receiver.mutability.is_some() {
+ mutability = Mutability::Mutable;
+ } else {
+ mutability = Mutability::View;
+ }
+ }
+ let mut args = Vec::new();
+ for typ in value
+ .sig
+ .inputs
+ .iter()
+ .filter(|arg| matches!(arg, FnArg::Typed(_)))
+ {
+ let typ = match typ {
+ FnArg::Typed(typ) => typ,
+ _ => unreachable!(),
+ };
+ args.push(MethodArg::try_from(typ)?);
+ }
+
+ if mutability != Mutability::Mutable && args.iter().any(|arg| arg.is_value()) {
+ return Err(syn::Error::new(
+ args.iter().find(|arg| arg.is_value()).unwrap().ty.span(),
+ "payable function should be mutable",
+ ));
+ }
+
+ let result = match &value.sig.output {
+ ReturnType::Type(_, ty) => ty,
+ _ => return Err(syn::Error::new(value.sig.output.span(), "interface method should return Result<value>\nif there is no value to return - specify void (which is alias to unit)")),
+ };
+ let result = parse_result_ok(result)?;
+
+ let camel_name = info
+ .rename_selector
+ .unwrap_or_else(|| cases::camelcase::to_camel_case(&ident.to_string()));
+ let mut selector_str = camel_name.clone();
+ selector_str.push('(');
+ let mut has_normal_args = false;
+ for (i, arg) in args.iter().filter(|arg| !arg.is_special()).enumerate() {
+ if i != 0 {
+ selector_str.push(',');
+ }
+ write!(selector_str, "{}", arg.selector_ty()).unwrap();
+ has_normal_args = true;
+ }
+ selector_str.push(')');
+ let selector = fn_selector_str(&selector_str);
+
+ Ok(Self {
+ name: ident.clone(),
+ camel_name,
+ pascal_name: snake_ident_to_pascal(ident),
+ screaming_name: snake_ident_to_screaming(ident),
+ selector_str,
+ selector,
+ args,
+ has_normal_args,
+ mutability,
+ result: result.clone(),
+ weight,
+ docs,
+ })
+ }
+ fn expand_call_def(&self) -> proc_macro2::TokenStream {
+ let defs = self
+ .args
+ .iter()
+ .filter(|a| !a.is_special())
+ .map(|a| a.expand_call_def());
+ let pascal_name = &self.pascal_name;
+ let docs = &self.docs;
+
+ if self.has_normal_args {
+ quote! {
+ #(#[doc = #docs])*
+ #[allow(missing_docs)]
+ #pascal_name {
+ #(
+ #defs,
+ )*
+ }
+ }
+ } else {
+ quote! {#pascal_name}
+ }
+ }
+
+ fn expand_const(&self) -> proc_macro2::TokenStream {
+ let screaming_name = &self.screaming_name;
+ let selector = u32::to_be_bytes(self.selector);
+ let selector_str = &self.selector_str;
+ quote! {
+ #[doc = #selector_str]
+ const #screaming_name: ::evm_coder::types::bytes4 = [#(#selector,)*];
+ }
+ }
+
+ fn expand_interface_id(&self) -> proc_macro2::TokenStream {
+ let screaming_name = &self.screaming_name;
+ quote! {
+ interface_id ^= u32::from_be_bytes(Self::#screaming_name);
+ }
+ }
+
+ fn expand_parse(&self) -> proc_macro2::TokenStream {
+ let pascal_name = &self.pascal_name;
+ let screaming_name = &self.screaming_name;
+ if self.has_normal_args {
+ let parsers = self
+ .args
+ .iter()
+ .filter(|a| !a.is_special())
+ .map(|a| a.expand_parse());
+ quote! {
+ Self::#screaming_name => return Ok(Some(Self::#pascal_name {
+ #(
+ #parsers,
+ )*
+ }))
+ }
+ } else {
+ quote! { Self::#screaming_name => return Ok(Some(Self::#pascal_name)) }
+ }
+ }
+
+ fn expand_variant_call(&self, call_name: &proc_macro2::Ident) -> proc_macro2::TokenStream {
+ let pascal_name = &self.pascal_name;
+ let name = &self.name;
+
+ let matcher = if self.has_normal_args {
+ let names = self
+ .args
+ .iter()
+ .filter(|a| !a.is_special())
+ .map(|a| &a.name);
+
+ quote! {{
+ #(
+ #names,
+ )*
+ }}
+ } else {
+ quote! {}
+ };
+
+ let receiver = match self.mutability {
+ Mutability::Mutable | Mutability::View => quote! {self.},
+ Mutability::Pure => quote! {Self::},
+ };
+ let args = self.args.iter().map(|a| a.expand_call_arg());
+
+ quote! {
+ #call_name::#pascal_name #matcher => {
+ let result = #receiver #name(
+ #(
+ #args,
+ )*
+ )?;
+ (&result).to_result()
+ }
+ }
+ }
+
+ fn expand_variant_weight(&self) -> proc_macro2::TokenStream {
+ let pascal_name = &self.pascal_name;
+ if let Some(weight) = &self.weight {
+ let matcher = if self.has_normal_args {
+ let names = self
+ .args
+ .iter()
+ .filter(|a| !a.is_special())
+ .map(|a| &a.name);
+
+ quote! {{
+ #(
+ #names,
+ )*
+ }}
+ } else {
+ quote! {}
+ };
+ quote! {
+ Self::#pascal_name #matcher => (#weight).into()
+ }
+ } else {
+ let matcher = if self.has_normal_args {
+ quote! {{..}}
+ } else {
+ quote! {}
+ };
+ quote! {
+ Self::#pascal_name #matcher => ().into()
+ }
+ }
+ }
+
+ fn expand_solidity_function(&self) -> proc_macro2::TokenStream {
+ let camel_name = &self.camel_name;
+ let mutability = match self.mutability {
+ Mutability::Mutable => quote! {SolidityMutability::Mutable},
+ Mutability::View => quote! { SolidityMutability::View },
+ Mutability::Pure => quote! {SolidityMutability::Pure},
+ };
+ let result = &self.result;
+
+ let args = self
+ .args
+ .iter()
+ .filter(|a| !a.is_special())
+ .map(MethodArg::expand_solidity_argument);
+ let docs = &self.docs;
+ let selector_str = &self.selector_str;
+ let selector = self.selector;
+
+ quote! {
+ SolidityFunction {
+ docs: &[#(#docs),*],
+ selector_str: #selector_str,
+ selector: #selector,
+ name: #camel_name,
+ mutability: #mutability,
+ args: (
+ #(
+ #args,
+ )*
+ ),
+ result: <UnnamedArgument<#result>>::default(),
+ }
+ }
+ }
+}
+
+fn generics_list(gen: &Generics) -> proc_macro2::TokenStream {
+ if gen.params.is_empty() {
+ return quote! {};
+ }
+ let params = gen.params.iter().map(|p| match p {
+ syn::GenericParam::Type(id) => {
+ let v = &id.ident;
+ quote! {#v}
+ }
+ syn::GenericParam::Lifetime(lt) => {
+ let v = <.lifetime;
+ quote! {#v}
+ }
+ syn::GenericParam::Const(c) => {
+ let i = &c.ident;
+ quote! {#i}
+ }
+ });
+ quote! { #(#params),* }
+}
+fn generics_reference(gen: &Generics) -> proc_macro2::TokenStream {
+ if gen.params.is_empty() {
+ return quote! {};
+ }
+ let list = generics_list(gen);
+ quote! { <#list> }
+}
+fn generics_data(gen: &Generics) -> proc_macro2::TokenStream {
+ let list = generics_list(gen);
+ if gen.params.len() == 1 {
+ quote! {#list}
+ } else {
+ quote! { (#list) }
+ }
+}
+
+pub struct SolidityInterface {
+ generics: Generics,
+ name: Box<syn::Type>,
+ info: InterfaceInfo,
+ methods: Vec<Method>,
+ docs: Vec<String>,
+}
+impl SolidityInterface {
+ pub fn try_from(info: InterfaceInfo, value: &ItemImpl) -> syn::Result<Self> {
+ let mut methods = Vec::new();
+
+ for item in &value.items {
+ if let ImplItem::Method(method) = item {
+ methods.push(Method::try_from(method)?)
+ }
+ }
+ let mut docs = vec![];
+ for attr in &value.attrs {
+ let ident = parse_ident_from_path(&attr.path, false)?;
+ if ident == "doc" {
+ let args = attr.parse_meta().unwrap();
+ let value = match args {
+ Meta::NameValue(MetaNameValue {
+ lit: Lit::Str(str), ..
+ }) => str.value(),
+ _ => unreachable!(),
+ };
+ docs.push(value);
+ }
+ }
+ Ok(Self {
+ generics: value.generics.clone(),
+ name: value.self_ty.clone(),
+ info,
+ methods,
+ docs,
+ })
+ }
+ pub fn expand(self) -> proc_macro2::TokenStream {
+ let name = self.name;
+
+ let solidity_name = self.info.name.to_string();
+ let call_name = pascal_ident_to_call(&self.info.name);
+ let generics = self.generics;
+ let gen_ref = generics_reference(&generics);
+ let gen_data = generics_data(&generics);
+ let gen_where = &generics.where_clause;
+
+ let call_sub = self
+ .info
+ .inline_is
+ .0
+ .iter()
+ .chain(self.info.is.0.iter())
+ .map(|c| Is::expand_call_def(c, &gen_ref));
+ let call_parse = self
+ .info
+ .inline_is
+ .0
+ .iter()
+ .chain(self.info.is.0.iter())
+ .map(|is| Is::expand_parse(is, &gen_ref));
+ let call_variants = self
+ .info
+ .inline_is
+ .0
+ .iter()
+ .chain(self.info.is.0.iter())
+ .map(|c| Is::expand_variant_call(c, &call_name, &gen_ref));
+ let weight_variants = self
+ .info
+ .inline_is
+ .0
+ .iter()
+ .chain(self.info.is.0.iter())
+ .map(Is::expand_variant_weight);
+
+ let inline_interface_id = self.info.inline_is.0.iter().map(Is::expand_interface_id);
+ let supports_interface = self
+ .info
+ .is
+ .0
+ .iter()
+ .map(|is| Is::expand_supports_interface(is, &gen_ref));
+
+ let calls = self.methods.iter().map(Method::expand_call_def);
+ let consts = self.methods.iter().map(Method::expand_const);
+ let interface_id = self.methods.iter().map(Method::expand_interface_id);
+ let parsers = self.methods.iter().map(Method::expand_parse);
+ let call_variants_this = self
+ .methods
+ .iter()
+ .map(|m| Method::expand_variant_call(m, &call_name));
+ let weight_variants_this = self.methods.iter().map(Method::expand_variant_weight);
+ let solidity_functions = self.methods.iter().map(Method::expand_solidity_function);
+
+ // TODO: Inline inline_is
+ let solidity_is = self
+ .info
+ .is
+ .0
+ .iter()
+ .chain(self.info.inline_is.0.iter())
+ .map(|is| is.name.to_string());
+ let solidity_events_is = self.info.events.0.iter().map(|is| is.name.to_string());
+ let solidity_generators = self
+ .info
+ .is
+ .0
+ .iter()
+ .chain(self.info.inline_is.0.iter())
+ .map(|is| Is::expand_generator(is, &gen_ref));
+ let solidity_event_generators = self.info.events.0.iter().map(Is::expand_event_generator);
+
+ let docs = &self.docs;
+
+ if let Some(expect_selector) = &self.info.expect_selector {
+ if !self.info.inline_is.0.is_empty() {
+ return syn::Error::new(
+ name.span(),
+ "expect_selector is not compatible with inline_is",
+ )
+ .to_compile_error();
+ }
+ let selector = self
+ .methods
+ .iter()
+ .map(|m| m.selector)
+ .fold(0, |a, b| a ^ b);
+
+ if *expect_selector != selector {
+ let mut methods = String::new();
+ for meth in self.methods.iter() {
+ write!(methods, "\n- {}", meth.selector_str).expect("write to string");
+ }
+ return syn::Error::new(name.span(), format!("expected selector mismatch, expected {expect_selector:0>8x}, but implementation has {selector:0>8x}{methods}")).to_compile_error();
+ }
+ }
+ // let methods = self.methods.iter().map(Method::solidity_def);
+
+ quote! {
+ #[derive(Debug)]
+ #(#[doc = #docs])*
+ pub enum #call_name #gen_ref {
+ /// Inherited method
+ ERC165Call(::evm_coder::ERC165Call, ::core::marker::PhantomData<#gen_data>),
+ #(
+ #calls,
+ )*
+ #(
+ #call_sub,
+ )*
+ }
+ impl #gen_ref #call_name #gen_ref {
+ #(
+ #consts
+ )*
+ /// Return this call ERC165 selector
+ pub fn interface_id() -> ::evm_coder::types::bytes4 {
+ let mut interface_id = 0;
+ #(#interface_id)*
+ #(#inline_interface_id)*
+ u32::to_be_bytes(interface_id)
+ }
+ /// Is this contract implements specified ERC165 selector
+ pub fn supports_interface(interface_id: ::evm_coder::types::bytes4) -> bool {
+ interface_id != u32::to_be_bytes(0xffffff) && (
+ interface_id == ::evm_coder::ERC165Call::INTERFACE_ID ||
+ interface_id == Self::interface_id()
+ #(
+ || #supports_interface
+ )*
+ )
+ }
+ /// Generate solidity definitions for methods described in this interface
+ pub fn generate_solidity_interface(tc: &evm_coder::solidity::TypeCollector, is_impl: bool) {
+ use evm_coder::solidity::*;
+ use core::fmt::Write;
+ let interface = SolidityInterface {
+ docs: &[#(#docs),*],
+ name: #solidity_name,
+ selector: Self::interface_id(),
+ is: &["Dummy", "ERC165", #(
+ #solidity_is,
+ )* #(
+ #solidity_events_is,
+ )* ],
+ functions: (#(
+ #solidity_functions,
+ )*),
+ };
+
+ let mut out = string::new();
+ if #solidity_name.starts_with("Inline") {
+ out.push_str("/// @dev inlined interface\n");
+ }
+ let _ = interface.format(is_impl, &mut out, tc);
+ tc.collect(out);
+ #(
+ #solidity_event_generators
+ )*
+ #(
+ #solidity_generators
+ )*
+ if is_impl {
+ tc.collect("/// @dev common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\ncontract ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool) {\n\t\trequire(false, stub_error);\n\t\tinterfaceID;\n\t\treturn true;\n\t}\n}\n".into());
+ } else {
+ tc.collect("/// @dev common stubs holder\ninterface Dummy {\n}\ninterface ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n".into());
+ }
+ }
+ }
+ impl #gen_ref ::evm_coder::Call for #call_name #gen_ref {
+ fn parse(method_id: ::evm_coder::types::bytes4, reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result<Option<Self>> {
+ use ::evm_coder::abi::AbiRead;
+ match method_id {
+ ::evm_coder::ERC165Call::INTERFACE_ID => return Ok(
+ ::evm_coder::ERC165Call::parse(method_id, reader)?
+ .map(|c| Self::ERC165Call(c, ::core::marker::PhantomData))
+ ),
+ #(
+ #parsers,
+ )*
+ _ => {},
+ }
+ #(
+ #call_parse
+ )else*
+ return Ok(None);
+ }
+ }
+ impl #generics ::evm_coder::Weighted for #call_name #gen_ref
+ #gen_where
+ {
+ #[allow(unused_variables)]
+ fn weight(&self) -> ::evm_coder::execution::DispatchInfo {
+ match self {
+ #(
+ #weight_variants,
+ )*
+ // TODO: It should be very cheap, but not free
+ Self::ERC165Call(::evm_coder::ERC165Call::SupportsInterface {..}, _) => 100u64.into(),
+ #(
+ #weight_variants_this,
+ )*
+ }
+ }
+ }
+ impl #generics ::evm_coder::Callable<#call_name #gen_ref> for #name
+ #gen_where
+ {
+ #[allow(unreachable_code)] // In case of no inner calls
+ fn call(&mut self, c: Msg<#call_name #gen_ref>) -> ::evm_coder::execution::ResultWithPostInfo<::evm_coder::abi::AbiWriter> {
+ use ::evm_coder::abi::AbiWrite;
+ match c.call {
+ #(
+ #call_variants,
+ )*
+ #call_name::ERC165Call(::evm_coder::ERC165Call::SupportsInterface {interface_id}, _) => {
+ let mut writer = ::evm_coder::abi::AbiWriter::default();
+ writer.bool(&<#call_name #gen_ref>::supports_interface(interface_id));
+ return Ok(writer.into());
+ }
+ _ => {},
+ }
+ let mut writer = ::evm_coder::abi::AbiWriter::default();
+ match c.call {
+ #(
+ #call_variants_this,
+ )*
+ _ => unreachable!()
+ }
+ }
+ }
+ }
+ }
+}
crates/evm-coder/procedural/src/to_log.rsdiffbeforeafterboth--- /dev/null
+++ b/crates/evm-coder/procedural/src/to_log.rs
@@ -0,0 +1,238 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
+use inflector::cases;
+use syn::{Data, DeriveInput, Field, Fields, Ident, Variant, spanned::Spanned};
+use std::fmt::Write;
+use quote::quote;
+
+use crate::{parse_ident_from_path, parse_ident_from_type, snake_ident_to_screaming};
+
+struct EventField {
+ name: Ident,
+ camel_name: String,
+ ty: Ident,
+ indexed: bool,
+}
+
+impl EventField {
+ fn try_from(field: &Field) -> syn::Result<Self> {
+ let name = field.ident.as_ref().unwrap();
+ let ty = parse_ident_from_type(&field.ty, false)?;
+ let mut indexed = false;
+ for attr in &field.attrs {
+ if let Ok(ident) = parse_ident_from_path(&attr.path, false) {
+ if ident == "indexed" {
+ indexed = true;
+ }
+ }
+ }
+ Ok(Self {
+ name: name.to_owned(),
+ camel_name: cases::camelcase::to_camel_case(&name.to_string()),
+ ty: ty.to_owned(),
+ indexed,
+ })
+ }
+ fn expand_solidity_argument(&self) -> proc_macro2::TokenStream {
+ let camel_name = &self.camel_name;
+ let ty = &self.ty;
+ let indexed = self.indexed;
+ quote! {
+ <SolidityEventArgument<#ty>>::new(#indexed, #camel_name)
+ }
+ }
+}
+
+struct Event {
+ name: Ident,
+ name_screaming: Ident,
+ fields: Vec<EventField>,
+ selector: [u8; 32],
+ selector_str: String,
+}
+
+impl Event {
+ fn try_from(variant: &Variant) -> syn::Result<Self> {
+ let name = &variant.ident;
+ let name_screaming = snake_ident_to_screaming(name);
+
+ let named = match &variant.fields {
+ Fields::Named(named) => named,
+ _ => {
+ return Err(syn::Error::new(
+ variant.fields.span(),
+ "expected named fields",
+ ))
+ }
+ };
+ let mut fields = Vec::new();
+ for field in &named.named {
+ fields.push(EventField::try_from(field)?);
+ }
+ if fields.iter().filter(|f| f.indexed).count() > 3 {
+ return Err(syn::Error::new(
+ variant.fields.span(),
+ "events can have at most 4 indexed fields (1 indexed field is reserved for event signature)"
+ ));
+ }
+ let mut selector_str = format!("{}(", name);
+ for (i, arg) in fields.iter().enumerate() {
+ if i != 0 {
+ write!(selector_str, ",").unwrap();
+ }
+ write!(selector_str, "{}", arg.ty).unwrap();
+ }
+ selector_str.push(')');
+ let selector = crate::event_selector_str(&selector_str);
+
+ Ok(Self {
+ name: name.to_owned(),
+ name_screaming,
+ fields,
+ selector,
+ selector_str,
+ })
+ }
+
+ fn expand_serializers(&self) -> proc_macro2::TokenStream {
+ let name = &self.name;
+ let name_screaming = &self.name_screaming;
+ let fields = self.fields.iter().map(|f| &f.name);
+
+ let indexed = self.fields.iter().filter(|f| f.indexed).map(|f| &f.name);
+ let plain = self.fields.iter().filter(|f| !f.indexed).map(|f| &f.name);
+
+ quote! {
+ Self::#name {#(
+ #fields,
+ )*} => {
+ topics.push(topic::from(Self::#name_screaming));
+ #(
+ topics.push(#indexed.to_topic());
+ )*
+ #(
+ #plain.abi_write(&mut writer);
+ )*
+ }
+ }
+ }
+
+ fn expand_consts(&self) -> proc_macro2::TokenStream {
+ let name_screaming = &self.name_screaming;
+ let selector_str = &self.selector_str;
+ let selector = &self.selector;
+
+ quote! {
+ #[doc = #selector_str]
+ const #name_screaming: [u8; 32] = [#(
+ #selector,
+ )*];
+ }
+ }
+
+ fn expand_solidity_function(&self) -> proc_macro2::TokenStream {
+ let name = self.name.to_string();
+ let args = self.fields.iter().map(EventField::expand_solidity_argument);
+ quote! {
+ SolidityEvent {
+ name: #name,
+ args: (
+ #(
+ #args,
+ )*
+ ),
+ }
+ }
+ }
+}
+
+pub struct Events {
+ name: Ident,
+ events: Vec<Event>,
+}
+
+impl Events {
+ pub fn try_from(data: &DeriveInput) -> syn::Result<Self> {
+ let name = &data.ident;
+ let en = match &data.data {
+ Data::Enum(en) => en,
+ _ => return Err(syn::Error::new(data.span(), "expected enum")),
+ };
+ let mut events = Vec::new();
+ for variant in &en.variants {
+ events.push(Event::try_from(variant)?);
+ }
+ Ok(Self {
+ name: name.to_owned(),
+ events,
+ })
+ }
+ pub fn expand(&self) -> proc_macro2::TokenStream {
+ let name = &self.name;
+
+ let consts = self.events.iter().map(Event::expand_consts);
+ let serializers = self.events.iter().map(Event::expand_serializers);
+ let solidity_name = self.name.to_string();
+ let solidity_functions = self.events.iter().map(Event::expand_solidity_function);
+
+ quote! {
+ impl #name {
+ #(
+ #consts
+ )*
+
+ pub fn generate_solidity_interface(tc: &evm_coder::solidity::TypeCollector, is_impl: bool) {
+ use evm_coder::solidity::*;
+ use core::fmt::Write;
+ let interface = SolidityInterface {
+ docs: &[],
+ selector: [0; 4],
+ name: #solidity_name,
+ is: &[],
+ functions: (#(
+ #solidity_functions,
+ )*),
+ };
+ let mut out = string::new();
+ out.push_str("/// @dev inlined interface\n");
+ let _ = interface.format(is_impl, &mut out, tc);
+ tc.collect(out);
+ }
+ }
+
+ #[automatically_derived]
+ impl ::evm_coder::events::ToLog for #name {
+ fn to_log(&self, contract: address) -> ::ethereum::Log {
+ use ::evm_coder::events::ToTopic;
+ use ::evm_coder::abi::AbiWrite;
+ let mut writer = ::evm_coder::abi::AbiWriter::new();
+ let mut topics = Vec::new();
+ match self {
+ #(
+ #serializers,
+ )*
+ }
+ ::ethereum::Log {
+ address: contract,
+ topics,
+ data: writer.finish(),
+ }
+ }
+ }
+ }
+ }
+}
crates/evm-coder/src/abi.rsdiffbeforeafterboth--- a/crates/evm-coder/src/abi.rs
+++ b/crates/evm-coder/src/abi.rs
@@ -14,8 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-//! TODO: I misunterstood therminology, abi IS rlp encoded, so
-//! this module should be replaced with rlp crate
+//! Implementation of EVM RLP reader/writer
#![allow(dead_code)]
@@ -32,6 +31,7 @@
const ABI_ALIGNMENT: usize = 32;
+/// View into RLP data, which provides method to read typed items from it
#[derive(Clone)]
pub struct AbiReader<'i> {
buf: &'i [u8],
@@ -39,6 +39,7 @@
offset: usize,
}
impl<'i> AbiReader<'i> {
+ /// Start reading RLP buffer, assuming there is no padding bytes
pub fn new(buf: &'i [u8]) -> Self {
Self {
buf,
@@ -46,6 +47,7 @@
offset: 0,
}
}
+ /// Start reading RLP buffer, parsing first 4 bytes as selector
pub fn new_call(buf: &'i [u8]) -> Result<(types::bytes4, Self)> {
if buf.len() < 4 {
return Err(Error::Error(ExitError::OutOfOffset));
@@ -109,10 +111,12 @@
)
}
+ /// Read [`H160`] at current position, then advance
pub fn address(&mut self) -> Result<H160> {
Ok(H160(self.read_padleft()?))
}
+ /// Read [`bool`] at current position, then advance
pub fn bool(&mut self) -> Result<bool> {
let data: [u8; 1] = self.read_padleft()?;
match data[0] {
@@ -122,49 +126,61 @@
}
}
+ /// Read [`[u8; 4]`] at current position, then advance
pub fn bytes4(&mut self) -> Result<[u8; 4]> {
self.read_padright()
}
+ /// Read [`Vec<u8>`] at current position, then advance
pub fn bytes(&mut self) -> Result<Vec<u8>> {
let mut subresult = self.subresult()?;
- let length = subresult.read_usize()?;
+ let length = subresult.uint32()? as usize;
if subresult.buf.len() < subresult.offset + length {
return Err(Error::Error(ExitError::OutOfOffset));
}
Ok(subresult.buf[subresult.offset..subresult.offset + length].into())
}
+
+ /// Read [`string`] at current position, then advance
pub fn string(&mut self) -> Result<string> {
string::from_utf8(self.bytes()?).map_err(|_| Error::Error(ExitError::InvalidRange))
}
+ /// Read [`u8`] at current position, then advance
pub fn uint8(&mut self) -> Result<u8> {
Ok(self.read_padleft::<1>()?[0])
}
+ /// Read [`u32`] at current position, then advance
pub fn uint32(&mut self) -> Result<u32> {
Ok(u32::from_be_bytes(self.read_padleft()?))
}
+ /// Read [`u128`] at current position, then advance
pub fn uint128(&mut self) -> Result<u128> {
Ok(u128::from_be_bytes(self.read_padleft()?))
}
+ /// Read [`U256`] at current position, then advance
pub fn uint256(&mut self) -> Result<U256> {
let buf: [u8; 32] = self.read_padleft()?;
Ok(U256::from_big_endian(&buf))
}
+ /// Read [`u64`] at current position, then advance
pub fn uint64(&mut self) -> Result<u64> {
Ok(u64::from_be_bytes(self.read_padleft()?))
}
+ /// Read [`usize`] at current position, then advance
+ #[deprecated = "dangerous, as usize may have different width in wasm and native execution"]
pub fn read_usize(&mut self) -> Result<usize> {
Ok(usize::from_be_bytes(self.read_padleft()?))
}
+ /// Slice recursive buffer, advance one word for buffer offset
fn subresult(&mut self) -> Result<AbiReader<'i>> {
- let offset = self.read_usize()?;
+ let offset = self.uint32()? as usize;
if offset + self.subresult_offset > self.buf.len() {
return Err(Error::Error(ExitError::InvalidRange));
}
@@ -175,11 +191,13 @@
})
}
+ /// Is this parser reached end of buffer?
pub fn is_finished(&self) -> bool {
self.buf.len() == self.offset
}
}
+/// Writer for RLP encoded data
#[derive(Default)]
pub struct AbiWriter {
static_part: Vec<u8>,
@@ -187,9 +205,11 @@
had_call: bool,
}
impl AbiWriter {
+ /// Initialize internal buffers for output data, assuming no padding required
pub fn new() -> Self {
Self::default()
}
+ /// Initialize internal buffers, inserting method selector at beginning
pub fn new_call(method_id: u32) -> Self {
let mut val = Self::new();
val.static_part.extend(&method_id.to_be_bytes());
@@ -211,59 +231,71 @@
.extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - bytes.len()]);
}
+ /// Write [`H160`] to end of buffer
pub fn address(&mut self, address: &H160) {
self.write_padleft(&address.0)
}
+ /// Write [`bool`] to end of buffer
pub fn bool(&mut self, value: &bool) {
self.write_padleft(&[if *value { 1 } else { 0 }])
}
+ /// Write [`u8`] to end of buffer
pub fn uint8(&mut self, value: &u8) {
self.write_padleft(&[*value])
}
+ /// Write [`u32`] to end of buffer
pub fn uint32(&mut self, value: &u32) {
self.write_padleft(&u32::to_be_bytes(*value))
}
+ /// Write [`u128`] to end of buffer
pub fn uint128(&mut self, value: &u128) {
self.write_padleft(&u128::to_be_bytes(*value))
}
+ /// Write [`U256`] to end of buffer
pub fn uint256(&mut self, value: &U256) {
let mut out = [0; 32];
value.to_big_endian(&mut out);
self.write_padleft(&out)
}
+ /// Write [`usize`] to end of buffer
+ #[deprecated = "dangerous, as usize may have different width in wasm and native execution"]
pub fn write_usize(&mut self, value: &usize) {
self.write_padleft(&usize::to_be_bytes(*value))
}
+ /// Append recursive data, writing pending offset at end of buffer
pub fn write_subresult(&mut self, result: Self) {
self.dynamic_part.push((self.static_part.len(), result));
// Empty block, to be filled later
self.write_padleft(&[]);
}
- pub fn memory(&mut self, value: &[u8]) {
+ fn memory(&mut self, value: &[u8]) {
let mut sub = Self::new();
- sub.write_usize(&value.len());
+ sub.uint32(&(value.len() as u32));
for chunk in value.chunks(ABI_ALIGNMENT) {
sub.write_padright(chunk);
}
self.write_subresult(sub);
}
+ /// Append recursive [`str`] at end of buffer
pub fn string(&mut self, value: &str) {
self.memory(value.as_bytes())
}
+ /// Append recursive [`[u8]`] at end of buffer
pub fn bytes(&mut self, value: &[u8]) {
self.memory(value)
}
+ /// Finish writer, concatenating all internal buffers
pub fn finish(mut self) -> Vec<u8> {
for (static_offset, part) in self.dynamic_part {
let part_offset = self.static_part.len() - self.had_call.then(|| 4).unwrap_or(0);
@@ -278,7 +310,13 @@
}
}
+/// [`AbiReader`] implements reading of many types, but it should
+/// be limited to types defined in spec
+///
+/// As this trait can't be made sealed,
+/// instead of having `impl AbiRead for T`, we have `impl AbiRead<T> for AbiReader`
pub trait AbiRead<T> {
+ /// Read item from current position, advanding decoder
fn abi_read(&mut self) -> Result<T>;
}
@@ -318,7 +356,7 @@
{
fn abi_read(&mut self) -> Result<Vec<R>> {
let mut sub = self.subresult()?;
- let size = sub.read_usize()?;
+ let size = sub.uint32()? as usize;
sub.subresult_offset = sub.offset;
let mut out = Vec::with_capacity(size);
for _ in 0..size {
@@ -366,8 +404,13 @@
impl_tuples! {A B C D E F G H I}
impl_tuples! {A B C D E F G H I J}
+/// For questions about inability to provide custom implementations,
+/// see [`AbiRead`]
pub trait AbiWrite {
+ /// Write value to end of specified encoder
fn abi_write(&self, writer: &mut AbiWriter);
+ /// Specialization for [`crate::solidity_interface`] implementation,
+ /// see comment in `impl AbiWrite for ResultWithPostInfo`
fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {
let mut writer = AbiWriter::new();
self.abi_write(&mut writer);
@@ -375,13 +418,11 @@
}
}
+/// This particular AbiWrite implementation should be split to another trait,
+/// which only implements `to_result`, but due to lack of specialization feature
+/// in stable Rust, we can't have blanket impl of this trait `for T where T: AbiWrite`,
+/// so here we abusing default trait methods for it
impl<T: AbiWrite> AbiWrite for ResultWithPostInfo<T> {
- // this particular AbiWrite implementation should be split to another trait,
- // which only implements [`to_result`]
- //
- // But due to lack of specialization feature in stable Rust, we can't have
- // blanket impl of this trait `for T where T: AbiWrite`, so here we abusing
- // default trait methods for it
fn abi_write(&self, _writer: &mut AbiWriter) {
debug_assert!(false, "shouldn't be called, see comment")
}
@@ -432,6 +473,8 @@
fn abi_write(&self, _writer: &mut AbiWriter) {}
}
+/// Helper macros to parse reader into variables
+#[deprecated]
#[macro_export]
macro_rules! abi_decode {
($reader:expr, $($name:ident: $typ:ident),+ $(,)?) => {
@@ -440,6 +483,9 @@
)+
}
}
+
+/// Helper macros to construct RLP-encoded buffer
+#[deprecated]
#[macro_export]
macro_rules! abi_encode {
($($typ:ident($value:expr)),* $(,)?) => {{
crates/evm-coder/src/events.rsdiffbeforeafterboth--- a/crates/evm-coder/src/events.rs
+++ b/crates/evm-coder/src/events.rs
@@ -19,11 +19,23 @@
use crate::types::*;
+/// Implementation of this trait should not be written manually,
+/// instead use [`crate::ToLog`] proc macros.
+///
+/// See also [`evm_coder_procedural::ToLog`], [solidity docs on events](https://docs.soliditylang.org/en/develop/contracts.html#events)
pub trait ToLog {
+ /// Convert event to [`ethereum::Log`].
+ /// Because event by itself doesn't contains current contract
+ /// address, it should be specified manually.
fn to_log(&self, contract: H160) -> Log;
}
+/// Only items implementing `ToTopic` may be used as `#[indexed]` field
+/// in [`crate::ToLog`] macro usage.
+///
+/// See also (solidity docs on events)[<https://docs.soliditylang.org/en/develop/contracts.html#events>]
pub trait ToTopic {
+ /// Convert value to topic to be used in [`ethereum::Log`]
fn to_topic(&self) -> H256;
}
crates/evm-coder/src/execution.rsdiffbeforeafterboth--- a/crates/evm-coder/src/execution.rs
+++ b/crates/evm-coder/src/execution.rs
@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+//! Contract execution related types
+
#[cfg(not(feature = "std"))]
use alloc::string::{String, ToString};
use evm_core::{ExitError, ExitFatal};
@@ -22,10 +24,14 @@
use crate::Weight;
+/// Execution error, should be convertible between EVM and Substrate.
#[derive(Debug, Clone)]
pub enum Error {
+ /// Non-fatal contract error occured
Revert(String),
+ /// EVM fatal error
Fatal(ExitFatal),
+ /// EVM normal error
Error(ExitError),
}
@@ -38,9 +44,12 @@
}
}
+/// To be used in [`crate::solidity_interface`] implementation.
pub type Result<T> = core::result::Result<T, Error>;
+/// Static information collected from [`crate::weight`].
pub struct DispatchInfo {
+ /// Statically predicted call weight
pub weight: Weight,
}
@@ -55,16 +64,22 @@
}
}
+/// Weight information that is only available post dispatch.
+/// Note: This can only be used to reduce the weight or fee, not increase it.
#[derive(Default, Clone)]
pub struct PostDispatchInfo {
+ /// Actual weight consumed by call
actual_weight: Option<Weight>,
}
impl PostDispatchInfo {
+ /// Calculate amount to be returned back to user
pub fn calc_unspent(&self, info: &DispatchInfo) -> Weight {
info.weight - self.calc_actual_weight(info)
}
+ /// Calculate actual consumed weight, saturating to weight reported
+ /// pre-dispatch
pub fn calc_actual_weight(&self, info: &DispatchInfo) -> Weight {
if let Some(actual_weight) = self.actual_weight {
actual_weight.min(info.weight)
@@ -74,9 +89,12 @@
}
}
+/// Wrapper for PostDispatchInfo and any user-provided data
#[derive(Clone)]
pub struct WithPostDispatchInfo<T> {
+ /// User provided data
pub data: T,
+ /// Info known after dispatch
pub post_info: PostDispatchInfo,
}
@@ -89,5 +107,6 @@
}
}
+/// Return type of items in [`crate::solidity_interface`] definition
pub type ResultWithPostInfo<T> =
core::result::Result<WithPostDispatchInfo<T>, WithPostDispatchInfo<Error>>;
crates/evm-coder/src/lib.rsdiffbeforeafterboth--- a/crates/evm-coder/src/lib.rs
+++ b/crates/evm-coder/src/lib.rs
@@ -14,22 +14,103 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+#![doc = include_str!("../README.md")]
+#![deny(missing_docs)]
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(not(feature = "std"))]
extern crate alloc;
use abi::{AbiRead, AbiReader, AbiWriter};
-pub use evm_coder_macros::{event_topic, fn_selector, solidity_interface, solidity, weight, ToLog};
+pub use evm_coder_procedural::{event_topic, fn_selector};
pub mod abi;
-pub mod events;
-pub use events::ToLog;
+pub use events::{ToLog, ToTopic};
use execution::DispatchInfo;
pub mod execution;
+
+/// Derives call enum implementing [`crate::Callable`], [`crate::Weighted`]
+/// and [`crate::Call`] from impl block.
+///
+/// ## Macro syntax
+///
+/// `#[solidity_interface(name, is, inline_is, events)]`
+/// - *name* - used in generated code, and for Call enum name
+/// - *is* - used to provide inheritance in Solidity
+/// - *inline_is* - same as `is`, but ERC165::SupportsInterface will work differently: For `is` SupportsInterface(A) will return true
+/// if A is one of the interfaces the contract is inherited from (e.g. B is created as `is(A)`). If B is created as `inline_is(A)`
+/// SupportsInterface(A) will internally create a new interface that combines all methods of A and B, so SupportsInterface(A) will return
+/// false.
+///
+/// `#[weight(value)]`
+/// Can be added to every method of impl block, used for deriving [`crate::Weighted`], which
+/// is used by substrate bridge.
+/// - *value*: expression, which evaluates to weight required to call this method.
+/// This expression can use call arguments to calculate non-constant execution time.
+/// This expression should evaluate faster than actual execution does, and may provide worse case
+/// than one is called.
+///
+/// `#[solidity_interface(rename_selector)]`
+/// - *rename_selector* - by default, selector name will be generated by transforming method name
+/// from snake_case to camelCase. Use this option, if other naming convention is required.
+/// I.e: method `token_uri` will be automatically renamed to `tokenUri` in selector, but name
+/// required by ERC721 standard is `tokenURI`, thus we need to specify `rename_selector = "tokenURI"`
+/// explicitly.
+///
+/// Both contract and contract methods may have doccomments, which will end up in a generated
+/// solidity interface file, thus you should use [solidity syntax](https://docs.soliditylang.org/en/latest/natspec-format.html) for writing documentation in this macro
+///
+/// ## Example
+///
+/// ```ignore
+/// struct SuperContract;
+/// struct InlineContract;
+/// struct Contract;
+///
+/// #[derive(ToLog)]
+/// enum ContractEvents {
+/// Event(#[indexed] uint32),
+/// }
+///
+/// /// @dev This contract provides function to multiply two numbers
+/// #[solidity_interface(name = MyContract, is(SuperContract), inline_is(InlineContract))]
+/// impl Contract {
+/// /// Multiply two numbers
+/// /// @param a First number
+/// /// @param b Second number
+/// /// @return uint32 Product of two passed numbers
+/// /// @dev This function returns error in case of overflow
+/// #[weight(200 + a + b)]
+/// #[solidity_interface(rename_selector = "mul")]
+/// fn mul(&mut self, a: uint32, b: uint32) -> Result<uint32> {
+/// Ok(a.checked_mul(b).ok_or("overflow")?)
+/// }
+/// }
+/// ```
+pub use evm_coder_procedural::solidity_interface;
+/// See [`solidity_interface`]
+pub use evm_coder_procedural::solidity;
+/// See [`solidity_interface`]
+pub use evm_coder_procedural::weight;
+
+/// Derives [`ToLog`] for enum
+///
+/// Selectors will be derived from variant names, there is currently no way to have custom naming
+/// for them
+///
+/// `#[indexed]`
+/// Marks this field as indexed, so it will appear in [`ethereum::Log`] topics instead of data
+pub use evm_coder_procedural::ToLog;
+
+// Api of those modules shouldn't be consumed directly, it is only exported for usage in proc macros
+#[doc(hidden)]
+pub mod events;
+#[doc(hidden)]
pub mod solidity;
-/// Solidity type definitions
+/// Solidity type definitions (aliases from solidity name to rust type)
+/// To be used in [`solidity_interface`] definitions, to make sure there is no
+/// type conflict between Rust code and generated definitions
pub mod types {
- #![allow(non_camel_case_types)]
+ #![allow(non_camel_case_types, missing_docs)]
#[cfg(not(feature = "std"))]
use alloc::{vec::Vec};
@@ -54,6 +135,8 @@
pub type string = ::std::string::String;
pub type bytes = Vec<u8>;
+ /// Solidity doesn't have `void` type, however we have special implementation
+ /// for empty tuple return type
pub type void = ();
//#region Special types
@@ -63,36 +146,64 @@
pub type caller = address;
//#endregion
+ /// Ethereum typed call message, similar to solidity
+ /// `msg` object.
pub struct Msg<C> {
pub call: C,
+ /// Address of user, which called this contract.
pub caller: H160,
+ /// Payment amount to contract.
+ /// Contract should reject payment, if target call is not payable,
+ /// and there is no `receiver()` function defined.
pub value: U256,
}
}
+/// Parseable EVM call, this trait should be implemented with [`solidity_interface`] macro
pub trait Call: Sized {
+ /// Parse call buffer into typed call enum
fn parse(selector: types::bytes4, input: &mut AbiReader) -> execution::Result<Option<Self>>;
}
+/// Intended to be used as `#[weight]` output type
+/// Should be same between evm-coder and substrate to avoid confusion
+///
+/// Isn't same thing as gas, some mapping is required between those types
pub type Weight = u64;
+/// In substrate, we have benchmarking, which allows
+/// us to not rely on gas metering, but instead predict amount of gas to execute call
pub trait Weighted: Call {
+ /// Predict weight of this call
fn weight(&self) -> DispatchInfo;
}
+/// Type callable with ethereum message, may be implemented by [`solidity_interface`] macro
+/// on interface implementation, or for externally-owned real EVM contract
pub trait Callable<C: Call> {
+ /// Call contract using specified call data
fn call(&mut self, call: types::Msg<C>) -> execution::ResultWithPostInfo<AbiWriter>;
}
-/// Implementation is implicitly provided for all interfaces
+/// Implementation of ERC165 is implicitly generated for all interfaces in [`solidity_interface`],
+/// this structure holds parsed data for ERC165Call subvariant
+///
+/// Note: no [`Callable`] implementation is provided, call implementation is inlined into every
+/// implementing contract
///
-/// Note: no Callable implementation is provided
+/// See <https://eips.ethereum.org/EIPS/eip-165>
#[derive(Debug)]
pub enum ERC165Call {
- SupportsInterface { interface_id: types::bytes4 },
+ /// ERC165 provides single method, which returns true, if contract
+ /// implements specified interface
+ SupportsInterface {
+ /// Requested interface
+ interface_id: types::bytes4,
+ },
}
impl ERC165Call {
+ /// ERC165 selector is provided by standard
pub const INTERFACE_ID: types::bytes4 = u32::to_be_bytes(0x01ffc9a7);
}
crates/evm-coder/src/solidity.rsdiffbeforeafterboth--- a/crates/evm-coder/src/solidity.rs
+++ b/crates/evm-coder/src/solidity.rs
@@ -14,26 +14,31 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+//! Implementation detail of [`crate::solidity_interface`] macro code-generation.
+//! You should not rely on any public item from this module, as it is only intended to be used
+//! by procedural macro, API and output format may be changed at any time.
+//!
+//! Purpose of this module is to receive solidity contract definition in module-specified
+//! format, and then output string, representing interface of this contract in solidity language
+
#[cfg(not(feature = "std"))]
-use alloc::{
- string::String,
- vec::Vec,
- collections::{BTreeSet, BTreeMap},
- format,
-};
+use alloc::{string::String, vec::Vec, collections::BTreeMap, format};
#[cfg(feature = "std")]
-use std::collections::{BTreeSet, BTreeMap};
+use std::collections::BTreeMap;
use core::{
fmt::{self, Write},
marker::PhantomData,
cell::{Cell, RefCell},
+ cmp::Reverse,
};
use impl_trait_for_tuples::impl_for_tuples;
use crate::types::*;
#[derive(Default)]
pub struct TypeCollector {
- structs: RefCell<BTreeSet<string>>,
+ /// Code => id
+ /// id ordering is required to perform topo-sort on the resulting data
+ structs: RefCell<BTreeMap<string, usize>>,
anonymous: RefCell<BTreeMap<Vec<string>, usize>>,
id: Cell<usize>,
}
@@ -42,7 +47,8 @@
Self::default()
}
pub fn collect(&self, item: string) {
- self.structs.borrow_mut().insert(item);
+ let id = self.next_id();
+ self.structs.borrow_mut().insert(item, id);
}
pub fn next_id(&self) -> usize {
let v = self.id.get();
@@ -56,7 +62,7 @@
}
let id = self.next_id();
let mut str = String::new();
- writeln!(str, "// Anonymous struct").unwrap();
+ writeln!(str, "/// @dev anonymous struct").unwrap();
writeln!(str, "struct Tuple{} {{", id).unwrap();
for (i, name) in names.iter().enumerate() {
writeln!(str, "\t{} field_{};", name, i).unwrap();
@@ -66,15 +72,19 @@
self.anonymous.borrow_mut().insert(names, id);
format!("Tuple{}", id)
}
- pub fn finish(self) -> BTreeSet<string> {
- self.structs.into_inner()
+ pub fn finish(self) -> Vec<string> {
+ let mut data = self.structs.into_inner().into_iter().collect::<Vec<_>>();
+ data.sort_by_key(|(_, id)| Reverse(*id));
+ data.into_iter().map(|(code, _)| code).collect()
}
}
pub trait SolidityTypeName: 'static {
fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result;
+ /// "simple" types are stored inline, no `memory` modifier should be used in solidity
fn is_simple() -> bool;
fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result;
+ /// Specialization
fn is_void() -> bool {
false
}
@@ -125,6 +135,10 @@
}
mod sealed {
+ /// Not every type should be directly placed in vec.
+ /// Vec encoding is not memory efficient, as every item will be padded
+ /// to 32 bytes.
+ /// Instead you should use specialized types (`bytes` in case of `Vec<u8>`)
pub trait CanBePlacedInVec {}
}
@@ -402,7 +416,8 @@
}
pub struct SolidityFunction<A, R> {
pub docs: &'static [&'static str],
- pub selector: &'static str,
+ pub selector_str: &'static str,
+ pub selector: u32,
pub name: &'static str,
pub args: A,
pub result: R,
@@ -416,12 +431,14 @@
tc: &TypeCollector,
) -> fmt::Result {
for doc in self.docs {
- writeln!(writer, "\t//{}", doc)?;
- }
- if !self.docs.is_empty() {
- writeln!(writer, "\t//")?;
+ writeln!(writer, "\t///{}", doc)?;
}
- writeln!(writer, "\t// Selector: {}", self.selector)?;
+ writeln!(
+ writer,
+ "\t/// @dev EVM selector for this function is: 0x{:0>8x},",
+ self.selector
+ )?;
+ writeln!(writer, "\t/// or in textual repr: {}", self.selector_str)?;
write!(writer, "\tfunction {}(", self.name)?;
self.args.solidity_name(writer, tc)?;
write!(writer, ")")?;
@@ -481,6 +498,7 @@
}
pub struct SolidityInterface<F: SolidityFunctions> {
+ pub docs: &'static [&'static str],
pub selector: bytes4,
pub name: &'static str,
pub is: &'static [&'static str],
@@ -495,10 +513,13 @@
tc: &TypeCollector,
) -> fmt::Result {
const ZERO_BYTES: [u8; 4] = [0; 4];
+ for doc in self.docs {
+ writeln!(out, "///{}", doc)?;
+ }
if self.selector != ZERO_BYTES {
writeln!(
out,
- "// Selector: {:0>8x}",
+ "/// @dev the ERC-165 identifier for this interface is 0x{:0>8x}",
u32::from_be_bytes(self.selector)
)?;
}
crates/evm-coder/tests/generics.rsdiffbeforeafterboth--- a/crates/evm-coder/tests/generics.rs
+++ b/crates/evm-coder/tests/generics.rs
@@ -19,14 +19,14 @@
struct Generic<T>(PhantomData<T>);
-#[solidity_interface(name = "GenericIs")]
+#[solidity_interface(name = GenericIs)]
impl<T> Generic<T> {
fn test_1(&self) -> Result<uint256> {
unreachable!()
}
}
-#[solidity_interface(name = "Generic", is(GenericIs))]
+#[solidity_interface(name = Generic, is(GenericIs))]
impl<T: Into<u32>> Generic<T> {
fn test_2(&self) -> Result<uint256> {
unreachable!()
@@ -35,7 +35,7 @@
generate_stubgen!(gen_iface, GenericCall<()>, false);
-#[solidity_interface(name = "GenericWhere")]
+#[solidity_interface(name = GenericWhere)]
impl<T> Generic<T>
where
T: core::fmt::Debug,
crates/evm-coder/tests/random.rsdiffbeforeafterboth--- a/crates/evm-coder/tests/random.rs
+++ b/crates/evm-coder/tests/random.rs
@@ -21,14 +21,14 @@
struct Impls;
-#[solidity_interface(name = "OurInterface")]
+#[solidity_interface(name = OurInterface)]
impl Impls {
fn fn_a(&self, _input: uint256) -> Result<bool> {
unreachable!()
}
}
-#[solidity_interface(name = "OurInterface1")]
+#[solidity_interface(name = OurInterface1)]
impl Impls {
fn fn_b(&self, _input: uint128) -> Result<uint32> {
unreachable!()
@@ -48,7 +48,7 @@
}
#[solidity_interface(
- name = "OurInterface2",
+ name = OurInterface2,
is(OurInterface),
inline_is(OurInterface1),
events(OurEvents)
@@ -79,3 +79,9 @@
unreachable!()
}
}
+
+#[solidity_interface(
+ name = ValidSelector,
+ expect_selector = 0x00000000,
+)]
+impl Impls {}
crates/evm-coder/tests/solidity_generation.rsdiffbeforeafterboth--- a/crates/evm-coder/tests/solidity_generation.rs
+++ b/crates/evm-coder/tests/solidity_generation.rs
@@ -18,7 +18,7 @@
struct ERC20;
-#[solidity_interface(name = "ERC20")]
+#[solidity_interface(name = ERC20)]
impl ERC20 {
fn decimals(&self) -> Result<uint8> {
unreachable!()
node/cli/src/chain_spec.rsdiffbeforeafterboth--- a/node/cli/src/chain_spec.rs
+++ b/node/cli/src/chain_spec.rs
@@ -115,7 +115,7 @@
.public()
}
-/// The extensions for the [`ChainSpec`].
+/// The extensions for the [`DefaultChainSpec`].
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)]
#[serde(deny_unknown_fields)]
pub struct Extensions {
pallets/common/src/erc.rsdiffbeforeafterboth--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -60,7 +60,7 @@
}
/// @title A contract that allows you to work with collections.
-#[solidity_interface(name = "Collection")]
+#[solidity_interface(name = Collection)]
impl<T: Config> CollectionHandle<T>
where
T::AccountId: From<[u8; 32]>,
@@ -228,7 +228,7 @@
}
/// Add collection admin by substrate address.
- /// @param new_admin Substrate administrator address.
+ /// @param newAdmin Substrate administrator address.
fn add_collection_admin_substrate(
&mut self,
caller: caller,
@@ -254,7 +254,7 @@
}
/// Add collection admin.
- /// @param new_admin Address of the added administrator.
+ /// @param newAdmin Address of the added administrator.
fn add_collection_admin(&mut self, caller: caller, new_admin: address) -> Result<void> {
let caller = T::CrossAccountId::from_eth(caller);
let new_admin = T::CrossAccountId::from_eth(new_admin);
@@ -264,7 +264,7 @@
/// Remove collection admin.
///
- /// @param new_admin Address of the removed administrator.
+ /// @param admin Address of the removed administrator.
fn remove_collection_admin(&mut self, caller: caller, admin: address) -> Result<void> {
let caller = T::CrossAccountId::from_eth(caller);
let admin = T::CrossAccountId::from_eth(admin);
pallets/evm-contract-helpers/README.mddiffbeforeafterboth--- /dev/null
+++ b/pallets/evm-contract-helpers/README.md
@@ -0,0 +1,13 @@
+# EVM Contract Helpers
+
+This pallet extends pallet-evm contracts with several new functions.
+
+## Overview
+
+Evm contract helpers pallet provides ability to
+
+- Tracking and getting of user, which deployed contract
+- Sponsoring EVM contract calls (Make transaction calls to be free for users, instead making them being paid from contract address)
+- Allowlist access mode
+
+As most of those functions are intented to be consumed by ethereum users, only API provided by this pallet is [ContractHelpers magic contract](./src/stubs/ContractHelpers.sol)
\ No newline at end of file
pallets/evm-contract-helpers/src/eth.rsdiffbeforeafterboth--- a/pallets/evm-contract-helpers/src/eth.rs
+++ b/pallets/evm-contract-helpers/src/eth.rs
@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+//! Implementation of magic contract
+
use core::marker::PhantomData;
use evm_coder::{abi::AbiWriter, execution::Result, generate_stubgen, solidity_interface, types::*};
use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder, dispatch_to_evm};
@@ -31,7 +33,8 @@
use up_sponsorship::SponsorshipHandler;
use sp_std::vec::Vec;
-struct ContractHelpers<T: Config>(SubstrateRecorder<T>);
+/// See [`ContractHelpersCall`]
+pub struct ContractHelpers<T: Config>(SubstrateRecorder<T>);
impl<T: Config> WithRecorder<T> for ContractHelpers<T> {
fn recorder(&self) -> &SubstrateRecorder<T> {
&self.0
@@ -42,22 +45,25 @@
}
}
-#[solidity_interface(name = "ContractHelpers")]
+/// @title Magic contract, which allows users to reconfigure other contracts
+#[solidity_interface(name = ContractHelpers)]
impl<T: Config> ContractHelpers<T>
where
T::AccountId: AsRef<[u8; 32]>,
{
- /// Get contract ovner
- ///
- /// @param Contract_address contract for which the owner is being determined.
- /// @return Contract owner.
+ /// Get user, which deployed specified contract
+ /// @dev May return zero address in case if contract is deployed
+ /// using uniquenetwork evm-migration pallet, or using other terms not
+ /// intended by pallet-evm
+ /// @dev Returns zero address if contract does not exists
+ /// @param contractAddress Contract to get owner of
+ /// @return address Owner of contract
fn contract_owner(&self, contract_address: address) -> Result<address> {
Ok(<Owner<T>>::get(contract_address))
}
/// Set sponsor.
- ///
- /// @param contract_address Contract for which a sponsor is being established.
+ /// @param contractAddress Contract for which a sponsor is being established.
/// @param sponsor User address who set as pending sponsor.
fn set_sponsor(
&mut self,
@@ -80,7 +86,7 @@
/// Set contract as self sponsored.
///
- /// @param contract_address Contract for which a self sponsoring is being enabled.
+ /// @param contractAddress Contract for which a self sponsoring is being enabled.
fn self_sponsored_enable(&mut self, caller: caller, contract_address: address) -> Result<void> {
self.recorder().consume_sload()?;
self.recorder().consume_sstore()?;
@@ -93,7 +99,7 @@
/// Remove sponsor.
///
- /// @param contract_address Contract for which a sponsorship is being removed.
+ /// @param contractAddress Contract for which a sponsorship is being removed.
fn remove_sponsor(&mut self, caller: caller, contract_address: address) -> Result<void> {
self.recorder().consume_sload()?;
self.recorder().consume_sstore()?;
@@ -106,9 +112,9 @@
/// Confirm sponsorship.
///
- /// @dev Caller must be same that set via [`set_sponsor`].
+ /// @dev Caller must be same that set via [`setSponsor`].
///
- /// @param contract_address Сontract for which need to confirm sponsorship.
+ /// @param contractAddress Сontract for which need to confirm sponsorship.
fn confirm_sponsorship(&mut self, caller: caller, contract_address: address) -> Result<void> {
self.recorder().consume_sload()?;
self.recorder().consume_sstore()?;
@@ -121,7 +127,7 @@
/// Get current sponsor.
///
- /// @param contract_address The contract for which a sponsor is requested.
+ /// @param contractAddress The contract for which a sponsor is requested.
/// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.
fn get_sponsor(&self, contract_address: address) -> Result<(address, uint256)> {
let sponsor =
@@ -138,7 +144,7 @@
/// Check tat contract has confirmed sponsor.
///
- /// @param contract_address The contract for which the presence of a confirmed sponsor is checked.
+ /// @param contractAddress The contract for which the presence of a confirmed sponsor is checked.
/// @return **true** if contract has confirmed sponsor.
fn has_sponsor(&self, contract_address: address) -> Result<bool> {
Ok(Pallet::<T>::get_sponsor(contract_address).is_some())
@@ -146,7 +152,7 @@
/// Check tat contract has pending sponsor.
///
- /// @param contract_address The contract for which the presence of a pending sponsor is checked.
+ /// @param contractAddress The contract for which the presence of a pending sponsor is checked.
/// @return **true** if contract has pending sponsor.
fn has_pending_sponsor(&self, contract_address: address) -> Result<bool> {
Ok(match Sponsoring::<T>::get(contract_address) {
@@ -163,6 +169,7 @@
&mut self,
caller: caller,
contract_address: address,
+ // TODO: implement support for enums in evm-coder
mode: uint8,
) -> Result<void> {
self.recorder().consume_sload()?;
@@ -175,10 +182,21 @@
Ok(())
}
- fn sponsoring_mode(&self, contract_address: address) -> Result<uint8> {
- Ok(<Pallet<T>>::sponsoring_mode(contract_address).to_eth())
+ /// Get current contract sponsoring rate limit
+ /// @param contractAddress Contract to get sponsoring mode of
+ /// @return uint32 Amount of blocks between two sponsored transactions
+ fn get_sponsoring_rate_limit(&self, contract_address: address) -> Result<uint32> {
+ Ok(<SponsoringRateLimit<T>>::get(contract_address)
+ .try_into()
+ .map_err(|_| "rate limit > u32::MAX")?)
}
+ /// Set contract sponsoring rate limit
+ /// @dev Sponsoring rate limit - is a minimum amount of blocks that should
+ /// pass between two sponsored transactions
+ /// @param contractAddress Contract to change sponsoring rate limit of
+ /// @param rateLimit Target rate limit
+ /// @dev Only contract owner can change this setting
fn set_sponsoring_rate_limit(
&mut self,
caller: caller,
@@ -190,57 +208,70 @@
<Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;
<Pallet<T>>::set_sponsoring_rate_limit(contract_address, rate_limit.into());
-
Ok(())
}
- fn get_sponsoring_rate_limit(&self, contract_address: address) -> Result<uint32> {
- Ok(<SponsoringRateLimit<T>>::get(contract_address)
- .try_into()
- .map_err(|_| "rate limit > u32::MAX")?)
- }
-
+ /// Is specified user present in contract allow list
+ /// @dev Contract owner always implicitly included
+ /// @param contractAddress Contract to check allowlist of
+ /// @param user User to check
+ /// @return bool Is specified users exists in contract allowlist
fn allowed(&self, contract_address: address, user: address) -> Result<bool> {
self.0.consume_sload()?;
Ok(<Pallet<T>>::allowed(contract_address, user))
}
- fn allowlist_enabled(&self, contract_address: address) -> Result<bool> {
- Ok(<AllowlistEnabled<T>>::get(contract_address))
- }
-
- fn toggle_allowlist(
+ /// Toggle user presence in contract allowlist
+ /// @param contractAddress Contract to change allowlist of
+ /// @param user Which user presence should be toggled
+ /// @param isAllowed `true` if user should be allowed to be sponsored
+ /// or call this contract, `false` otherwise
+ /// @dev Only contract owner can change this setting
+ fn toggle_allowed(
&mut self,
caller: caller,
contract_address: address,
- enabled: bool,
+ user: address,
+ is_allowed: bool,
) -> Result<void> {
self.recorder().consume_sload()?;
self.recorder().consume_sstore()?;
<Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;
- <Pallet<T>>::toggle_allowlist(contract_address, enabled);
+ <Pallet<T>>::toggle_allowed(contract_address, user, is_allowed);
Ok(())
}
- fn toggle_allowed(
+ /// Is this contract has allowlist access enabled
+ /// @dev Allowlist always can have users, and it is used for two purposes:
+ /// in case of allowlist sponsoring mode, users will be sponsored if they exist in allowlist
+ /// in case of allowlist access enabled, only users from allowlist may call this contract
+ /// @param contractAddress Contract to get allowlist access of
+ /// @return bool Is specified contract has allowlist access enabled
+ fn allowlist_enabled(&self, contract_address: address) -> Result<bool> {
+ Ok(<AllowlistEnabled<T>>::get(contract_address))
+ }
+
+ /// Toggle contract allowlist access
+ /// @param contractAddress Contract to change allowlist access of
+ /// @param enabled Should allowlist access to be enabled?
+ fn toggle_allowlist(
&mut self,
caller: caller,
contract_address: address,
- user: address,
- allowed: bool,
+ enabled: bool,
) -> Result<void> {
self.recorder().consume_sload()?;
self.recorder().consume_sstore()?;
<Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;
- <Pallet<T>>::toggle_allowed(contract_address, user, allowed);
-
+ <Pallet<T>>::toggle_allowlist(contract_address, enabled);
Ok(())
}
}
+/// Implements [`OnMethodCall`], which delegates call to [`ContractHelpers`]
pub struct HelpersOnMethodCall<T: Config>(PhantomData<*const T>);
impl<T: Config> OnMethodCall<T> for HelpersOnMethodCall<T>
where
@@ -283,6 +314,7 @@
}
}
+/// Hooks into contract creation, storing owner of newly deployed contract
pub struct HelpersOnCreate<T: Config>(PhantomData<*const T>);
impl<T: Config> OnCreate<T> for HelpersOnCreate<T> {
fn on_create(owner: H160, contract: H160) {
@@ -290,6 +322,7 @@
}
}
+/// Bridge to pallet-sponsoring
pub struct HelpersContractSponsoring<T: Config>(PhantomData<*const T>);
impl<T: Config> SponsorshipHandler<T::CrossAccountId, (H160, Vec<u8>)>
for HelpersContractSponsoring<T>
pallets/evm-contract-helpers/src/lib.rsdiffbeforeafterboth--- a/pallets/evm-contract-helpers/src/lib.rs
+++ b/pallets/evm-contract-helpers/src/lib.rs
@@ -14,7 +14,9 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+#![doc = include_str!("../README.md")]
#![cfg_attr(not(feature = "std"), no_std)]
+#![deny(missing_docs)]
use codec::{Decode, Encode, MaxEncodedLen};
pub use pallet::*;
@@ -35,13 +37,16 @@
pub trait Config:
frame_system::Config + pallet_evm_coder_substrate::Config + pallet_evm::account::Config
{
+ /// Address, under which magic contract will be available
type ContractAddress: Get<H160>;
+ /// In case of enabled sponsoring, but no sponsoring rate limit set,
+ /// this value will be used implicitly
type DefaultSponsoringRateLimit: Get<Self::BlockNumber>;
}
#[pallet::error]
pub enum Error<T> {
- /// This method is only executable by owner.
+ /// This method is only executable by contract owner
NoPermission,
/// No pending sponsor for contract.
@@ -217,6 +222,7 @@
}
}
+ /// Get current sponsoring mode, performing lazy migration from legacy storage
pub fn sponsoring_mode(contract: H160) -> SponsoringModeT {
<SponsoringMode<T>>::get(contract)
.or_else(|| {
@@ -225,6 +231,7 @@
.unwrap_or_default()
}
+ /// Reconfigure contract sponsoring mode
pub fn set_sponsoring_mode(contract: H160, mode: SponsoringModeT) {
if mode == SponsoringModeT::Disabled {
<SponsoringMode<T>>::remove(contract);
@@ -234,22 +241,27 @@
<SelfSponsoring<T>>::remove(contract)
}
+ /// Set duration between two sponsored contract calls
pub fn set_sponsoring_rate_limit(contract: H160, rate_limit: T::BlockNumber) {
<SponsoringRateLimit<T>>::insert(contract, rate_limit);
}
+ /// Is user added to allowlist, or he is owner of specified contract
pub fn allowed(contract: H160, user: H160) -> bool {
<Allowlist<T>>::get(&contract, &user) || <Owner<T>>::get(&contract) == user
}
+ /// Toggle contract allowlist access
pub fn toggle_allowlist(contract: H160, enabled: bool) {
<AllowlistEnabled<T>>::insert(contract, enabled)
}
+ /// Toggle user presence in contract's allowlist
pub fn toggle_allowed(contract: H160, user: H160, allowed: bool) {
<Allowlist<T>>::insert(contract, user, allowed);
}
+ /// Throw error if user is not allowed to reconfigure target contract
pub fn ensure_owner(contract: H160, user: H160) -> DispatchResult {
ensure!(<Owner<T>>::get(&contract) == user, Error::<T>::NoPermission);
Ok(())
@@ -257,10 +269,15 @@
}
}
-#[derive(Encode, Decode, PartialEq, TypeInfo, MaxEncodedLen)]
+/// Available contract sponsoring modes
+#[derive(Encode, Decode, PartialEq, TypeInfo, MaxEncodedLen, Default)]
pub enum SponsoringModeT {
+ /// Sponsoring is disabled
+ #[default]
Disabled,
+ /// Only users from allowlist will be sponsored
Allowlisted,
+ /// All users will be sponsored
Generous,
}
@@ -279,11 +296,5 @@
SponsoringModeT::Allowlisted => 1,
SponsoringModeT::Generous => 2,
}
- }
-}
-
-impl Default for SponsoringModeT {
- fn default() -> Self {
- Self::Disabled
}
}
pallets/evm-contract-helpers/src/stubs/ContractHelpers.rawdiffbeforeafterbothbinary blob — no preview
pallets/evm-contract-helpers/src/stubs/ContractHelpers.soldiffbeforeafterboth--- a/pallets/evm-contract-helpers/src/stubs/ContractHelpers.sol
+++ b/pallets/evm-contract-helpers/src/stubs/ContractHelpers.sol
@@ -3,13 +3,7 @@
pragma solidity >=0.8.0 <0.9.0;
-// Anonymous struct
-struct Tuple0 {
- address field_0;
- uint256 field_1;
-}
-
-// Common stubs holder
+/// @dev common stubs holder
contract Dummy {
uint8 dummy;
string stub_error = "this contract is implemented in native";
@@ -27,14 +21,18 @@
}
}
-// Selector: 6073d917
+/// @title Magic contract, which allows users to reconfigure other contracts
+/// @dev the ERC-165 identifier for this interface is 0xd77fab70
contract ContractHelpers is Dummy, ERC165 {
- // Get contract ovner
- //
- // @param Contract_address contract for which the owner is being determined.
- // @return Contract owner.
- //
- // Selector: contractOwner(address) 5152b14c
+ /// Get user, which deployed specified contract
+ /// @dev May return zero address in case if contract is deployed
+ /// using uniquenetwork evm-migration pallet, or using other terms not
+ /// intended by pallet-evm
+ /// @dev Returns zero address if contract does not exists
+ /// @param contractAddress Contract to get owner of
+ /// @return address Owner of contract
+ /// @dev EVM selector for this function is: 0x5152b14c,
+ /// or in textual repr: contractOwner(address)
function contractOwner(address contractAddress)
public
view
@@ -46,12 +44,11 @@
return 0x0000000000000000000000000000000000000000;
}
- // Set sponsor.
- //
- // @param contract_address Contract for which a sponsor is being established.
- // @param sponsor User address who set as pending sponsor.
- //
- // Selector: setSponsor(address,address) f01fba93
+ /// Set sponsor.
+ /// @param contractAddress Contract for which a sponsor is being established.
+ /// @param sponsor User address who set as pending sponsor.
+ /// @dev EVM selector for this function is: 0xf01fba93,
+ /// or in textual repr: setSponsor(address,address)
function setSponsor(address contractAddress, address sponsor) public {
require(false, stub_error);
contractAddress;
@@ -59,47 +56,47 @@
dummy = 0;
}
- // Set contract as self sponsored.
- //
- // @param contract_address Contract for which a self sponsoring is being enabled.
- //
- // Selector: selfSponsoredEnable(address) 89f7d9ae
+ /// Set contract as self sponsored.
+ ///
+ /// @param contractAddress Contract for which a self sponsoring is being enabled.
+ /// @dev EVM selector for this function is: 0x89f7d9ae,
+ /// or in textual repr: selfSponsoredEnable(address)
function selfSponsoredEnable(address contractAddress) public {
require(false, stub_error);
contractAddress;
dummy = 0;
}
- // Remove sponsor.
- //
- // @param contract_address Contract for which a sponsorship is being removed.
- //
- // Selector: removeSponsor(address) ef784250
+ /// Remove sponsor.
+ ///
+ /// @param contractAddress Contract for which a sponsorship is being removed.
+ /// @dev EVM selector for this function is: 0xef784250,
+ /// or in textual repr: removeSponsor(address)
function removeSponsor(address contractAddress) public {
require(false, stub_error);
contractAddress;
dummy = 0;
}
- // Confirm sponsorship.
- //
- // @dev Caller must be same that set via [`set_sponsor`].
- //
- // @param contract_address Сontract for which need to confirm sponsorship.
- //
- // Selector: confirmSponsorship(address) abc00001
+ /// Confirm sponsorship.
+ ///
+ /// @dev Caller must be same that set via [`setSponsor`].
+ ///
+ /// @param contractAddress Сontract for which need to confirm sponsorship.
+ /// @dev EVM selector for this function is: 0xabc00001,
+ /// or in textual repr: confirmSponsorship(address)
function confirmSponsorship(address contractAddress) public {
require(false, stub_error);
contractAddress;
dummy = 0;
}
- // Get current sponsor.
- //
- // @param contract_address The contract for which a sponsor is requested.
- // @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.
- //
- // Selector: getSponsor(address) 743fc745
+ /// Get current sponsor.
+ ///
+ /// @param contractAddress The contract for which a sponsor is requested.
+ /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.
+ /// @dev EVM selector for this function is: 0x743fc745,
+ /// or in textual repr: getSponsor(address)
function getSponsor(address contractAddress)
public
view
@@ -111,12 +108,12 @@
return Tuple0(0x0000000000000000000000000000000000000000, 0);
}
- // Check tat contract has confirmed sponsor.
- //
- // @param contract_address The contract for which the presence of a confirmed sponsor is checked.
- // @return **true** if contract has confirmed sponsor.
- //
- // Selector: hasSponsor(address) 97418603
+ /// Check tat contract has confirmed sponsor.
+ ///
+ /// @param contractAddress The contract for which the presence of a confirmed sponsor is checked.
+ /// @return **true** if contract has confirmed sponsor.
+ /// @dev EVM selector for this function is: 0x97418603,
+ /// or in textual repr: hasSponsor(address)
function hasSponsor(address contractAddress) public view returns (bool) {
require(false, stub_error);
contractAddress;
@@ -124,12 +121,12 @@
return false;
}
- // Check tat contract has pending sponsor.
- //
- // @param contract_address The contract for which the presence of a pending sponsor is checked.
- // @return **true** if contract has pending sponsor.
- //
- // Selector: hasPendingSponsor(address) 39b9b242
+ /// Check tat contract has pending sponsor.
+ ///
+ /// @param contractAddress The contract for which the presence of a pending sponsor is checked.
+ /// @return **true** if contract has pending sponsor.
+ /// @dev EVM selector for this function is: 0x39b9b242,
+ /// or in textual repr: hasPendingSponsor(address)
function hasPendingSponsor(address contractAddress)
public
view
@@ -141,7 +138,8 @@
return false;
}
- // Selector: sponsoringEnabled(address) 6027dc61
+ /// @dev EVM selector for this function is: 0x6027dc61,
+ /// or in textual repr: sponsoringEnabled(address)
function sponsoringEnabled(address contractAddress)
public
view
@@ -153,7 +151,8 @@
return false;
}
- // Selector: setSponsoringMode(address,uint8) fde8a560
+ /// @dev EVM selector for this function is: 0xfde8a560,
+ /// or in textual repr: setSponsoringMode(address,uint8)
function setSponsoringMode(address contractAddress, uint8 mode) public {
require(false, stub_error);
contractAddress;
@@ -161,11 +160,15 @@
dummy = 0;
}
- // Selector: sponsoringMode(address) b70c7267
- function sponsoringMode(address contractAddress)
+ /// Get current contract sponsoring rate limit
+ /// @param contractAddress Contract to get sponsoring mode of
+ /// @return uint32 Amount of blocks between two sponsored transactions
+ /// @dev EVM selector for this function is: 0x610cfabd,
+ /// or in textual repr: getSponsoringRateLimit(address)
+ function getSponsoringRateLimit(address contractAddress)
public
view
- returns (uint8)
+ returns (uint32)
{
require(false, stub_error);
contractAddress;
@@ -173,7 +176,14 @@
return 0;
}
- // Selector: setSponsoringRateLimit(address,uint32) 77b6c908
+ /// Set contract sponsoring rate limit
+ /// @dev Sponsoring rate limit - is a minimum amount of blocks that should
+ /// pass between two sponsored transactions
+ /// @param contractAddress Contract to change sponsoring rate limit of
+ /// @param rateLimit Target rate limit
+ /// @dev Only contract owner can change this setting
+ /// @dev EVM selector for this function is: 0x77b6c908,
+ /// or in textual repr: setSponsoringRateLimit(address,uint32)
function setSponsoringRateLimit(address contractAddress, uint32 rateLimit)
public
{
@@ -183,32 +193,53 @@
dummy = 0;
}
- // Selector: getSponsoringRateLimit(address) 610cfabd
- function getSponsoringRateLimit(address contractAddress)
+ /// Is specified user present in contract allow list
+ /// @dev Contract owner always implicitly included
+ /// @param contractAddress Contract to check allowlist of
+ /// @param user User to check
+ /// @return bool Is specified users exists in contract allowlist
+ /// @dev EVM selector for this function is: 0x5c658165,
+ /// or in textual repr: allowed(address,address)
+ function allowed(address contractAddress, address user)
public
view
- returns (uint32)
+ returns (bool)
{
require(false, stub_error);
contractAddress;
+ user;
dummy;
- return 0;
+ return false;
}
- // Selector: allowed(address,address) 5c658165
- function allowed(address contractAddress, address user)
- public
- view
- returns (bool)
- {
+ /// Toggle user presence in contract allowlist
+ /// @param contractAddress Contract to change allowlist of
+ /// @param user Which user presence should be toggled
+ /// @param isAllowed `true` if user should be allowed to be sponsored
+ /// or call this contract, `false` otherwise
+ /// @dev Only contract owner can change this setting
+ /// @dev EVM selector for this function is: 0x4706cc1c,
+ /// or in textual repr: toggleAllowed(address,address,bool)
+ function toggleAllowed(
+ address contractAddress,
+ address user,
+ bool isAllowed
+ ) public {
require(false, stub_error);
contractAddress;
user;
- dummy;
- return false;
+ isAllowed;
+ dummy = 0;
}
- // Selector: allowlistEnabled(address) c772ef6c
+ /// Is this contract has allowlist access enabled
+ /// @dev Allowlist always can have users, and it is used for two purposes:
+ /// in case of allowlist sponsoring mode, users will be sponsored if they exist in allowlist
+ /// in case of allowlist access enabled, only users from allowlist may call this contract
+ /// @param contractAddress Contract to get allowlist access of
+ /// @return bool Is specified contract has allowlist access enabled
+ /// @dev EVM selector for this function is: 0xc772ef6c,
+ /// or in textual repr: allowlistEnabled(address)
function allowlistEnabled(address contractAddress)
public
view
@@ -220,24 +251,21 @@
return false;
}
- // Selector: toggleAllowlist(address,bool) 36de20f5
+ /// Toggle contract allowlist access
+ /// @param contractAddress Contract to change allowlist access of
+ /// @param enabled Should allowlist access to be enabled?
+ /// @dev EVM selector for this function is: 0x36de20f5,
+ /// or in textual repr: toggleAllowlist(address,bool)
function toggleAllowlist(address contractAddress, bool enabled) public {
require(false, stub_error);
contractAddress;
enabled;
dummy = 0;
}
+}
- // Selector: toggleAllowed(address,address,bool) 4706cc1c
- function toggleAllowed(
- address contractAddress,
- address user,
- bool allowed
- ) public {
- require(false, stub_error);
- contractAddress;
- user;
- allowed;
- dummy = 0;
- }
+/// @dev anonymous struct
+struct Tuple0 {
+ address field_0;
+ uint256 field_1;
}
pallets/evm-migration/README.mddiffbeforeafterboth--- /dev/null
+++ b/pallets/evm-migration/README.md
@@ -0,0 +1,18 @@
+# EVM contract migration pallet
+
+This pallet is only callable by root, it has functionality to migrate contract
+from other ethereum chain to pallet-evm
+
+Contract data includes contract code, and contract storage,
+where contract storage is a mapping from evm word to evm word (evm word = 32 byte)
+
+To import contract data into pallet-evm admin should call this pallet multiple times:
+1. Start migration via `begin`
+2. Insert all contract data using single or
+ multiple (If data can't be fit into single extrinsic) calls
+ to `set_data`
+3. Finish migration using `finish`, providing contract code
+
+During migration no one can insert code at address of this contract,
+as [`pallet::OnMethodCall`] prevents this, and no one can call this contract,
+as code is only supplied at final stage of contract deployment
\ No newline at end of file
pallets/evm-migration/src/benchmarking.rsdiffbeforeafterboth--- a/pallets/evm-migration/src/benchmarking.rs
+++ b/pallets/evm-migration/src/benchmarking.rs
@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+#![allow(missing_docs)]
+
use super::{Call, Config, Pallet};
use frame_benchmarking::benchmarks;
use frame_system::RawOrigin;
pallets/evm-migration/src/lib.rsdiffbeforeafterboth--- a/pallets/evm-migration/src/lib.rs
+++ b/pallets/evm-migration/src/lib.rs
@@ -14,7 +14,9 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+#![doc = include_str!("../README.md")]
#![cfg_attr(not(feature = "std"), no_std)]
+#![deny(missing_docs)]
pub use pallet::*;
#[cfg(feature = "runtime-benchmarks")]
@@ -32,6 +34,7 @@
#[pallet::config]
pub trait Config: frame_system::Config + pallet_evm::Config {
+ /// Weights
type WeightInfo: WeightInfo;
}
@@ -43,7 +46,9 @@
#[pallet::error]
pub enum Error<T> {
+ /// Can only migrate to empty address.
AccountNotEmpty,
+ /// Migration of this account is not yet started, or already finished.
AccountIsNotMigrating,
}
@@ -53,6 +58,8 @@
#[pallet::call]
impl<T: Config> Pallet<T> {
+ /// Start contract migration, inserts contract stub at target address,
+ /// and marks account as pending, allowing to insert storage
#[pallet::weight(<SelfWeightOf<T>>::begin())]
pub fn begin(origin: OriginFor<T>, address: H160) -> DispatchResult {
ensure_root(origin)?;
@@ -65,6 +72,8 @@
Ok(())
}
+ /// Insert items into contract storage, this method can be called
+ /// multiple times
#[pallet::weight(<SelfWeightOf<T>>::set_data(data.len() as u32))]
pub fn set_data(
origin: OriginFor<T>,
@@ -83,6 +92,9 @@
Ok(())
}
+ /// Finish contract migration, allows it to be called.
+ /// It is not possible to alter contract storage via [`Self::set_data`]
+ /// after this call.
#[pallet::weight(<SelfWeightOf<T>>::finish(code.len() as u32))]
pub fn finish(origin: OriginFor<T>, address: H160, code: Vec<u8>) -> DispatchResult {
ensure_root(origin)?;
@@ -97,6 +109,7 @@
}
}
+ /// Implements [`pallet_evm::OnMethodCall`], which reserves accounts with pending migration
pub struct OnMethodCall<T>(PhantomData<T>);
impl<T: Config> pallet_evm::OnMethodCall<T> for OnMethodCall<T> {
fn is_reserved(contract: &H160) -> bool {
pallets/evm-migration/src/weights.rsdiffbeforeafterboth--- a/pallets/evm-migration/src/weights.rs
+++ b/pallets/evm-migration/src/weights.rs
@@ -26,6 +26,7 @@
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
+#![allow(missing_docs)]
#![allow(clippy::unnecessary_cast)]
use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
pallets/evm-transaction-payment/README.mddiffbeforeafterboth--- /dev/null
+++ b/pallets/evm-transaction-payment/README.md
@@ -0,0 +1,5 @@
+# Evm transaction payment pallet
+
+pallet-evm-transaction-payment is a bridge between pallet-evm substrate calls and pallet-sponsoring.
+It doesn't provide any sponsoring logic by itself, instead all sponsoring handlers
+are loosly coupled via [`Config::EvmSponsorshipHandler`] trait.
\ No newline at end of file
pallets/evm-transaction-payment/src/lib.rsdiffbeforeafterboth--- a/pallets/evm-transaction-payment/src/lib.rs
+++ b/pallets/evm-transaction-payment/src/lib.rs
@@ -14,7 +14,9 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+#![doc = include_str!("../README.md")]
#![cfg_attr(not(feature = "std"), no_std)]
+#![deny(missing_docs)]
use core::marker::PhantomData;
use fp_evm::WithdrawReason;
@@ -29,13 +31,12 @@
pub mod pallet {
use super::*;
- use frame_support::traits::Currency;
use sp_std::vec::Vec;
#[pallet::config]
pub trait Config: frame_system::Config + pallet_evm::account::Config {
+ /// Loosly-coupled handlers for evm call sponsoring
type EvmSponsorshipHandler: SponsorshipHandler<Self::CrossAccountId, (H160, Vec<u8>)>;
- type Currency: Currency<Self::AccountId>;
}
#[pallet::pallet]
@@ -43,6 +44,7 @@
pub struct Pallet<T>(_);
}
+/// Implements [`fp_evm::TransactionValidityHack`], which provides sponsor address to pallet-evm
pub struct TransactionValidityHack<T: Config>(PhantomData<*const T>);
impl<T: Config> fp_evm::TransactionValidityHack<T::CrossAccountId> for TransactionValidityHack<T> {
fn who_pays_fee(origin: H160, reason: &WithdrawReason) -> Option<T::CrossAccountId> {
pallets/fungible/src/erc.rsdiffbeforeafterboth--- a/pallets/fungible/src/erc.rs
+++ b/pallets/fungible/src/erc.rs
@@ -50,7 +50,7 @@
},
}
-#[solidity_interface(name = "ERC20", events(ERC20Events))]
+#[solidity_interface(name = ERC20, events(ERC20Events))]
impl<T: Config> FungibleHandle<T> {
fn name(&self) -> Result<string> {
Ok(decode_utf16(self.name.iter().copied())
@@ -129,7 +129,7 @@
}
}
-#[solidity_interface(name = "ERC20UniqueExtensions")]
+#[solidity_interface(name = ERC20UniqueExtensions)]
impl<T: Config> FungibleHandle<T> {
#[weight(<SelfWeightOf<T>>::burn_from())]
fn burn_from(&mut self, caller: caller, from: address, amount: uint256) -> Result<bool> {
@@ -147,11 +147,11 @@
}
#[solidity_interface(
- name = "UniqueFungible",
+ name = UniqueFungible,
is(
ERC20,
ERC20UniqueExtensions,
- via("CollectionHandle<T>", common_mut, Collection)
+ Collection(common_mut, CollectionHandle<T>),
)
)]
impl<T: Config> FungibleHandle<T> where T::AccountId: From<[u8; 32]> {}
pallets/fungible/src/stubs/UniqueFungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth--- a/pallets/fungible/src/stubs/UniqueFungible.sol
+++ b/pallets/fungible/src/stubs/UniqueFungible.sol
@@ -3,7 +3,7 @@
pragma solidity >=0.8.0 <0.9.0;
-// Common stubs holder
+/// @dev common stubs holder
contract Dummy {
uint8 dummy;
string stub_error = "this contract is implemented in native";
@@ -19,122 +19,17 @@
interfaceID;
return true;
}
-}
-
-// Inline
-contract ERC20Events {
- event Transfer(address indexed from, address indexed to, uint256 value);
- event Approval(
- address indexed owner,
- address indexed spender,
- uint256 value
- );
}
-// Selector: 79cc6790
-contract ERC20UniqueExtensions is Dummy, ERC165 {
- // Selector: burnFrom(address,uint256) 79cc6790
- function burnFrom(address from, uint256 amount) public returns (bool) {
- require(false, stub_error);
- from;
- amount;
- dummy = 0;
- return false;
- }
-}
-
-// Selector: 942e8b22
-contract ERC20 is Dummy, ERC165, ERC20Events {
- // Selector: name() 06fdde03
- function name() public view returns (string memory) {
- require(false, stub_error);
- dummy;
- return "";
- }
-
- // Selector: symbol() 95d89b41
- function symbol() public view returns (string memory) {
- require(false, stub_error);
- dummy;
- return "";
- }
-
- // Selector: totalSupply() 18160ddd
- function totalSupply() public view returns (uint256) {
- require(false, stub_error);
- dummy;
- return 0;
- }
-
- // Selector: decimals() 313ce567
- function decimals() public view returns (uint8) {
- require(false, stub_error);
- dummy;
- return 0;
- }
-
- // Selector: balanceOf(address) 70a08231
- function balanceOf(address owner) public view returns (uint256) {
- require(false, stub_error);
- owner;
- dummy;
- return 0;
- }
-
- // Selector: transfer(address,uint256) a9059cbb
- function transfer(address to, uint256 amount) public returns (bool) {
- require(false, stub_error);
- to;
- amount;
- dummy = 0;
- return false;
- }
-
- // Selector: transferFrom(address,address,uint256) 23b872dd
- function transferFrom(
- address from,
- address to,
- uint256 amount
- ) public returns (bool) {
- require(false, stub_error);
- from;
- to;
- amount;
- dummy = 0;
- return false;
- }
-
- // Selector: approve(address,uint256) 095ea7b3
- function approve(address spender, uint256 amount) public returns (bool) {
- require(false, stub_error);
- spender;
- amount;
- dummy = 0;
- return false;
- }
-
- // Selector: allowance(address,address) dd62ed3e
- function allowance(address owner, address spender)
- public
- view
- returns (uint256)
- {
- require(false, stub_error);
- owner;
- spender;
- dummy;
- return 0;
- }
-}
-
-// Selector: ffe4da23
+/// @title A contract that allows you to work with collections.
+/// @dev the ERC-165 identifier for this interface is 0xffe4da23
contract Collection is Dummy, ERC165 {
- // Set collection property.
- //
- // @param key Property key.
- // @param value Propery value.
- //
- // Selector: setCollectionProperty(string,bytes) 2f073f66
+ /// Set collection property.
+ ///
+ /// @param key Property key.
+ /// @param value Propery value.
+ /// @dev EVM selector for this function is: 0x2f073f66,
+ /// or in textual repr: setCollectionProperty(string,bytes)
function setCollectionProperty(string memory key, bytes memory value)
public
{
@@ -144,25 +39,25 @@
dummy = 0;
}
- // Delete collection property.
- //
- // @param key Property key.
- //
- // Selector: deleteCollectionProperty(string) 7b7debce
+ /// Delete collection property.
+ ///
+ /// @param key Property key.
+ /// @dev EVM selector for this function is: 0x7b7debce,
+ /// or in textual repr: deleteCollectionProperty(string)
function deleteCollectionProperty(string memory key) public {
require(false, stub_error);
key;
dummy = 0;
}
- // Get collection property.
- //
- // @dev Throws error if key not found.
- //
- // @param key Property key.
- // @return bytes The property corresponding to the key.
- //
- // Selector: collectionProperty(string) cf24fd6d
+ /// Get collection property.
+ ///
+ /// @dev Throws error if key not found.
+ ///
+ /// @param key Property key.
+ /// @return bytes The property corresponding to the key.
+ /// @dev EVM selector for this function is: 0xcf24fd6d,
+ /// or in textual repr: collectionProperty(string)
function collectionProperty(string memory key)
public
view
@@ -174,41 +69,41 @@
return hex"";
}
- // Set the sponsor of the collection.
- //
- // @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.
- //
- // @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.
- //
- // Selector: setCollectionSponsor(address) 7623402e
+ /// Set the sponsor of the collection.
+ ///
+ /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.
+ ///
+ /// @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.
+ /// @dev EVM selector for this function is: 0x7623402e,
+ /// or in textual repr: setCollectionSponsor(address)
function setCollectionSponsor(address sponsor) public {
require(false, stub_error);
sponsor;
dummy = 0;
}
- // Collection sponsorship confirmation.
- //
- // @dev After setting the sponsor for the collection, it must be confirmed with this function.
- //
- // Selector: confirmCollectionSponsorship() 3c50e97a
+ /// Collection sponsorship confirmation.
+ ///
+ /// @dev After setting the sponsor for the collection, it must be confirmed with this function.
+ /// @dev EVM selector for this function is: 0x3c50e97a,
+ /// or in textual repr: confirmCollectionSponsorship()
function confirmCollectionSponsorship() public {
require(false, stub_error);
dummy = 0;
}
- // Set limits for the collection.
- // @dev Throws error if limit not found.
- // @param limit Name of the limit. Valid names:
- // "accountTokenOwnershipLimit",
- // "sponsoredDataSize",
- // "sponsoredDataRateLimit",
- // "tokenLimit",
- // "sponsorTransferTimeout",
- // "sponsorApproveTimeout"
- // @param value Value of the limit.
- //
- // Selector: setCollectionLimit(string,uint32) 6a3841db
+ /// Set limits for the collection.
+ /// @dev Throws error if limit not found.
+ /// @param limit Name of the limit. Valid names:
+ /// "accountTokenOwnershipLimit",
+ /// "sponsoredDataSize",
+ /// "sponsoredDataRateLimit",
+ /// "tokenLimit",
+ /// "sponsorTransferTimeout",
+ /// "sponsorApproveTimeout"
+ /// @param value Value of the limit.
+ /// @dev EVM selector for this function is: 0x6a3841db,
+ /// or in textual repr: setCollectionLimit(string,uint32)
function setCollectionLimit(string memory limit, uint32 value) public {
require(false, stub_error);
limit;
@@ -216,15 +111,15 @@
dummy = 0;
}
- // Set limits for the collection.
- // @dev Throws error if limit not found.
- // @param limit Name of the limit. Valid names:
- // "ownerCanTransfer",
- // "ownerCanDestroy",
- // "transfersEnabled"
- // @param value Value of the limit.
- //
- // Selector: setCollectionLimit(string,bool) 993b7fba
+ /// Set limits for the collection.
+ /// @dev Throws error if limit not found.
+ /// @param limit Name of the limit. Valid names:
+ /// "ownerCanTransfer",
+ /// "ownerCanDestroy",
+ /// "transfersEnabled"
+ /// @param value Value of the limit.
+ /// @dev EVM selector for this function is: 0x993b7fba,
+ /// or in textual repr: setCollectionLimit(string,bool)
function setCollectionLimit(string memory limit, bool value) public {
require(false, stub_error);
limit;
@@ -232,73 +127,73 @@
dummy = 0;
}
- // Get contract address.
- //
- // Selector: contractAddress() f6b4dfb4
+ /// Get contract address.
+ /// @dev EVM selector for this function is: 0xf6b4dfb4,
+ /// or in textual repr: contractAddress()
function contractAddress() public view returns (address) {
require(false, stub_error);
dummy;
return 0x0000000000000000000000000000000000000000;
}
- // Add collection admin by substrate address.
- // @param new_admin Substrate administrator address.
- //
- // Selector: addCollectionAdminSubstrate(uint256) 5730062b
+ /// Add collection admin by substrate address.
+ /// @param newAdmin Substrate administrator address.
+ /// @dev EVM selector for this function is: 0x5730062b,
+ /// or in textual repr: addCollectionAdminSubstrate(uint256)
function addCollectionAdminSubstrate(uint256 newAdmin) public {
require(false, stub_error);
newAdmin;
dummy = 0;
}
- // Remove collection admin by substrate address.
- // @param admin Substrate administrator address.
- //
- // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9
+ /// Remove collection admin by substrate address.
+ /// @param admin Substrate administrator address.
+ /// @dev EVM selector for this function is: 0x4048fcf9,
+ /// or in textual repr: removeCollectionAdminSubstrate(uint256)
function removeCollectionAdminSubstrate(uint256 admin) public {
require(false, stub_error);
admin;
dummy = 0;
}
- // Add collection admin.
- // @param new_admin Address of the added administrator.
- //
- // Selector: addCollectionAdmin(address) 92e462c7
+ /// Add collection admin.
+ /// @param newAdmin Address of the added administrator.
+ /// @dev EVM selector for this function is: 0x92e462c7,
+ /// or in textual repr: addCollectionAdmin(address)
function addCollectionAdmin(address newAdmin) public {
require(false, stub_error);
newAdmin;
dummy = 0;
}
- // Remove collection admin.
- //
- // @param new_admin Address of the removed administrator.
- //
- // Selector: removeCollectionAdmin(address) fafd7b42
+ /// Remove collection admin.
+ ///
+ /// @param admin Address of the removed administrator.
+ /// @dev EVM selector for this function is: 0xfafd7b42,
+ /// or in textual repr: removeCollectionAdmin(address)
function removeCollectionAdmin(address admin) public {
require(false, stub_error);
admin;
dummy = 0;
}
- // Toggle accessibility of collection nesting.
- //
- // @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'
- //
- // Selector: setCollectionNesting(bool) 112d4586
+ /// Toggle accessibility of collection nesting.
+ ///
+ /// @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'
+ /// @dev EVM selector for this function is: 0x112d4586,
+ /// or in textual repr: setCollectionNesting(bool)
function setCollectionNesting(bool enable) public {
require(false, stub_error);
enable;
dummy = 0;
}
- // Toggle accessibility of collection nesting.
- //
- // @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'
- // @param collections Addresses of collections that will be available for nesting.
- //
- // Selector: setCollectionNesting(bool,address[]) 64872396
+ /// Toggle accessibility of collection nesting.
+ ///
+ /// @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'
+ /// @param collections Addresses of collections that will be available for nesting.
+ /// @dev EVM selector for this function is: 0x64872396,
+ /// or in textual repr: setCollectionNesting(bool,address[])
function setCollectionNesting(bool enable, address[] memory collections)
public
{
@@ -308,57 +203,57 @@
dummy = 0;
}
- // Set the collection access method.
- // @param mode Access mode
- // 0 for Normal
- // 1 for AllowList
- //
- // Selector: setCollectionAccess(uint8) 41835d4c
+ /// Set the collection access method.
+ /// @param mode Access mode
+ /// 0 for Normal
+ /// 1 for AllowList
+ /// @dev EVM selector for this function is: 0x41835d4c,
+ /// or in textual repr: setCollectionAccess(uint8)
function setCollectionAccess(uint8 mode) public {
require(false, stub_error);
mode;
dummy = 0;
}
- // Add the user to the allowed list.
- //
- // @param user Address of a trusted user.
- //
- // Selector: addToCollectionAllowList(address) 67844fe6
+ /// Add the user to the allowed list.
+ ///
+ /// @param user Address of a trusted user.
+ /// @dev EVM selector for this function is: 0x67844fe6,
+ /// or in textual repr: addToCollectionAllowList(address)
function addToCollectionAllowList(address user) public {
require(false, stub_error);
user;
dummy = 0;
}
- // Remove the user from the allowed list.
- //
- // @param user Address of a removed user.
- //
- // Selector: removeFromCollectionAllowList(address) 85c51acb
+ /// Remove the user from the allowed list.
+ ///
+ /// @param user Address of a removed user.
+ /// @dev EVM selector for this function is: 0x85c51acb,
+ /// or in textual repr: removeFromCollectionAllowList(address)
function removeFromCollectionAllowList(address user) public {
require(false, stub_error);
user;
dummy = 0;
}
- // Switch permission for minting.
- //
- // @param mode Enable if "true".
- //
- // Selector: setCollectionMintMode(bool) 00018e84
+ /// Switch permission for minting.
+ ///
+ /// @param mode Enable if "true".
+ /// @dev EVM selector for this function is: 0x00018e84,
+ /// or in textual repr: setCollectionMintMode(bool)
function setCollectionMintMode(bool mode) public {
require(false, stub_error);
mode;
dummy = 0;
}
- // Check that account is the owner or admin of the collection
- //
- // @param user account to verify
- // @return "true" if account is the owner or admin
- //
- // Selector: isOwnerOrAdmin(address) 9811b0c7
+ /// Check that account is the owner or admin of the collection
+ ///
+ /// @param user account to verify
+ /// @return "true" if account is the owner or admin
+ /// @dev EVM selector for this function is: 0x9811b0c7,
+ /// or in textual repr: isOwnerOrAdmin(address)
function isOwnerOrAdmin(address user) public view returns (bool) {
require(false, stub_error);
user;
@@ -366,12 +261,12 @@
return false;
}
- // Check that substrate account is the owner or admin of the collection
- //
- // @param user account to verify
- // @return "true" if account is the owner or admin
- //
- // Selector: isOwnerOrAdminSubstrate(uint256) 68910e00
+ /// Check that substrate account is the owner or admin of the collection
+ ///
+ /// @param user account to verify
+ /// @return "true" if account is the owner or admin
+ /// @dev EVM selector for this function is: 0x68910e00,
+ /// or in textual repr: isOwnerOrAdminSubstrate(uint256)
function isOwnerOrAdminSubstrate(uint256 user) public view returns (bool) {
require(false, stub_error);
user;
@@ -379,35 +274,35 @@
return false;
}
- // Returns collection type
- //
- // @return `Fungible` or `NFT` or `ReFungible`
- //
- // Selector: uniqueCollectionType() d34b55b8
+ /// Returns collection type
+ ///
+ /// @return `Fungible` or `NFT` or `ReFungible`
+ /// @dev EVM selector for this function is: 0xd34b55b8,
+ /// or in textual repr: uniqueCollectionType()
function uniqueCollectionType() public returns (string memory) {
require(false, stub_error);
dummy = 0;
return "";
}
- // Changes collection owner to another account
- //
- // @dev Owner can be changed only by current owner
- // @param newOwner new owner account
- //
- // Selector: setOwner(address) 13af4035
+ /// Changes collection owner to another account
+ ///
+ /// @dev Owner can be changed only by current owner
+ /// @param newOwner new owner account
+ /// @dev EVM selector for this function is: 0x13af4035,
+ /// or in textual repr: setOwner(address)
function setOwner(address newOwner) public {
require(false, stub_error);
newOwner;
dummy = 0;
}
- // Changes collection owner to another substrate account
- //
- // @dev Owner can be changed only by current owner
- // @param newOwner new owner substrate account
- //
- // Selector: setOwnerSubstrate(uint256) b212138f
+ /// Changes collection owner to another substrate account
+ ///
+ /// @dev Owner can be changed only by current owner
+ /// @param newOwner new owner substrate account
+ /// @dev EVM selector for this function is: 0xb212138f,
+ /// or in textual repr: setOwnerSubstrate(uint256)
function setOwnerSubstrate(uint256 newOwner) public {
require(false, stub_error);
newOwner;
@@ -415,6 +310,122 @@
}
}
+/// @dev the ERC-165 identifier for this interface is 0x79cc6790
+contract ERC20UniqueExtensions is Dummy, ERC165 {
+ /// @dev EVM selector for this function is: 0x79cc6790,
+ /// or in textual repr: burnFrom(address,uint256)
+ function burnFrom(address from, uint256 amount) public returns (bool) {
+ require(false, stub_error);
+ from;
+ amount;
+ dummy = 0;
+ return false;
+ }
+}
+
+/// @dev inlined interface
+contract ERC20Events {
+ event Transfer(address indexed from, address indexed to, uint256 value);
+ event Approval(
+ address indexed owner,
+ address indexed spender,
+ uint256 value
+ );
+}
+
+/// @dev the ERC-165 identifier for this interface is 0x942e8b22
+contract ERC20 is Dummy, ERC165, ERC20Events {
+ /// @dev EVM selector for this function is: 0x06fdde03,
+ /// or in textual repr: name()
+ function name() public view returns (string memory) {
+ require(false, stub_error);
+ dummy;
+ return "";
+ }
+
+ /// @dev EVM selector for this function is: 0x95d89b41,
+ /// or in textual repr: symbol()
+ function symbol() public view returns (string memory) {
+ require(false, stub_error);
+ dummy;
+ return "";
+ }
+
+ /// @dev EVM selector for this function is: 0x18160ddd,
+ /// or in textual repr: totalSupply()
+ function totalSupply() public view returns (uint256) {
+ require(false, stub_error);
+ dummy;
+ return 0;
+ }
+
+ /// @dev EVM selector for this function is: 0x313ce567,
+ /// or in textual repr: decimals()
+ function decimals() public view returns (uint8) {
+ require(false, stub_error);
+ dummy;
+ return 0;
+ }
+
+ /// @dev EVM selector for this function is: 0x70a08231,
+ /// or in textual repr: balanceOf(address)
+ function balanceOf(address owner) public view returns (uint256) {
+ require(false, stub_error);
+ owner;
+ dummy;
+ return 0;
+ }
+
+ /// @dev EVM selector for this function is: 0xa9059cbb,
+ /// or in textual repr: transfer(address,uint256)
+ function transfer(address to, uint256 amount) public returns (bool) {
+ require(false, stub_error);
+ to;
+ amount;
+ dummy = 0;
+ return false;
+ }
+
+ /// @dev EVM selector for this function is: 0x23b872dd,
+ /// or in textual repr: transferFrom(address,address,uint256)
+ function transferFrom(
+ address from,
+ address to,
+ uint256 amount
+ ) public returns (bool) {
+ require(false, stub_error);
+ from;
+ to;
+ amount;
+ dummy = 0;
+ return false;
+ }
+
+ /// @dev EVM selector for this function is: 0x095ea7b3,
+ /// or in textual repr: approve(address,uint256)
+ function approve(address spender, uint256 amount) public returns (bool) {
+ require(false, stub_error);
+ spender;
+ amount;
+ dummy = 0;
+ return false;
+ }
+
+ /// @dev EVM selector for this function is: 0xdd62ed3e,
+ /// or in textual repr: allowance(address,address)
+ function allowance(address owner, address spender)
+ public
+ view
+ returns (uint256)
+ {
+ require(false, stub_error);
+ owner;
+ spender;
+ dummy;
+ return 0;
+ }
+}
+
contract UniqueFungible is
Dummy,
ERC165,
pallets/nonfungible/src/erc.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -50,14 +50,14 @@
};
/// @title A contract that allows to set and delete token properties and change token property permissions.
-#[solidity_interface(name = "TokenProperties")]
+#[solidity_interface(name = TokenProperties)]
impl<T: Config> NonfungibleHandle<T> {
/// @notice Set permissions for token property.
/// @dev Throws error if `msg.sender` is not admin or owner of the collection.
/// @param key Property key.
- /// @param is_mutable Permission to mutate property.
- /// @param collection_admin Permission to mutate property by collection admin if property is mutable.
- /// @param token_owner Permission to mutate property by token owner if property is mutable.
+ /// @param isMutable Permission to mutate property.
+ /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.
+ /// @param tokenOwner Permission to mutate property by token owner if property is mutable.
fn set_token_property_permission(
&mut self,
caller: caller,
@@ -201,7 +201,7 @@
/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
/// @dev See https://eips.ethereum.org/EIPS/eip-721
-#[solidity_interface(name = "ERC721Metadata")]
+#[solidity_interface(name = ERC721Metadata, expect_selector = 0x5b5e139f)]
impl<T: Config> NonfungibleHandle<T> {
/// @notice A descriptive name for a collection of NFTs in this contract
fn name(&self) -> Result<string> {
@@ -262,7 +262,7 @@
/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
/// @dev See https://eips.ethereum.org/EIPS/eip-721
-#[solidity_interface(name = "ERC721Enumerable")]
+#[solidity_interface(name = ERC721Enumerable, expect_selector = 0x780e9d63)]
impl<T: Config> NonfungibleHandle<T> {
/// @notice Enumerate valid NFTs
/// @param index A counter less than `totalSupply()`
@@ -289,7 +289,7 @@
/// @title ERC-721 Non-Fungible Token Standard
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
-#[solidity_interface(name = "ERC721", events(ERC721Events))]
+#[solidity_interface(name = ERC721, events(ERC721Events), expect_selector = 0x80ac58cd)]
impl<T: Config> NonfungibleHandle<T> {
/// @notice Count all NFTs assigned to an owner
/// @dev NFTs assigned to the zero address are considered invalid, and this
@@ -316,13 +316,13 @@
.as_eth())
}
/// @dev Not implemented
+ #[solidity(rename_selector = "safeTransferFrom")]
fn safe_transfer_from_with_data(
&mut self,
_from: address,
_to: address,
_token_id: uint256,
_data: bytes,
- _value: value,
) -> Result<void> {
// TODO: Not implemetable
Err("not implemented".into())
@@ -333,7 +333,6 @@
_from: address,
_to: address,
_token_id: uint256,
- _value: value,
) -> Result<void> {
// TODO: Not implemetable
Err("not implemented".into())
@@ -348,7 +347,6 @@
/// @param from The current owner of the NFT
/// @param to The new owner
/// @param tokenId The NFT to transfer
- /// @param _value Not used for an NFT
#[weight(<SelfWeightOf<T>>::transfer_from())]
fn transfer_from(
&mut self,
@@ -356,7 +354,6 @@
from: address,
to: address,
token_id: uint256,
- _value: value,
) -> Result<void> {
let caller = T::CrossAccountId::from_eth(caller);
let from = T::CrossAccountId::from_eth(from);
@@ -378,13 +375,7 @@
/// @param approved The new approved NFT controller
/// @param tokenId The NFT to approve
#[weight(<SelfWeightOf<T>>::approve())]
- fn approve(
- &mut self,
- caller: caller,
- approved: address,
- token_id: uint256,
- _value: value,
- ) -> Result<void> {
+ fn approve(&mut self, caller: caller, approved: address, token_id: uint256) -> Result<void> {
let caller = T::CrossAccountId::from_eth(caller);
let approved = T::CrossAccountId::from_eth(approved);
let token = token_id.try_into()?;
@@ -419,7 +410,7 @@
}
/// @title ERC721 Token that can be irreversibly burned (destroyed).
-#[solidity_interface(name = "ERC721Burnable")]
+#[solidity_interface(name = ERC721Burnable)]
impl<T: Config> NonfungibleHandle<T> {
/// @notice Burns a specific ERC721 token.
/// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized
@@ -436,7 +427,7 @@
}
/// @title ERC721 minting logic.
-#[solidity_interface(name = "ERC721Mintable", events(ERC721MintableEvents))]
+#[solidity_interface(name = ERC721Mintable, events(ERC721MintableEvents))]
impl<T: Config> NonfungibleHandle<T> {
fn minting_finished(&self) -> Result<bool> {
Ok(false)
@@ -597,22 +588,15 @@
}
/// @title Unique extensions for ERC721.
-#[solidity_interface(name = "ERC721UniqueExtensions")]
+#[solidity_interface(name = ERC721UniqueExtensions)]
impl<T: Config> NonfungibleHandle<T> {
/// @notice Transfer ownership of an NFT
/// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
/// is the zero address. Throws if `tokenId` is not a valid NFT.
/// @param to The new owner
/// @param tokenId The NFT to transfer
- /// @param _value Not used for an NFT
#[weight(<SelfWeightOf<T>>::transfer())]
- fn transfer(
- &mut self,
- caller: caller,
- to: address,
- token_id: uint256,
- _value: value,
- ) -> Result<void> {
+ fn transfer(&mut self, caller: caller, to: address, token_id: uint256) -> Result<void> {
let caller = T::CrossAccountId::from_eth(caller);
let to = T::CrossAccountId::from_eth(to);
let token = token_id.try_into()?;
@@ -630,15 +614,8 @@
/// if `to` is the zero address. Throws if `tokenId` is not a valid NFT.
/// @param from The current owner of the NFT
/// @param tokenId The NFT to transfer
- /// @param _value Not used for an NFT
#[weight(<SelfWeightOf<T>>::burn_from())]
- fn burn_from(
- &mut self,
- caller: caller,
- from: address,
- token_id: uint256,
- _value: value,
- ) -> Result<void> {
+ fn burn_from(&mut self, caller: caller, from: address, token_id: uint256) -> Result<void> {
let caller = T::CrossAccountId::from_eth(caller);
let from = T::CrossAccountId::from_eth(from);
let token = token_id.try_into()?;
@@ -751,7 +728,7 @@
}
#[solidity_interface(
- name = "UniqueNFT",
+ name = UniqueNFT,
is(
ERC721,
ERC721Metadata,
@@ -759,7 +736,7 @@
ERC721UniqueExtensions,
ERC721Mintable,
ERC721Burnable,
- via("CollectionHandle<T>", common_mut, Collection),
+ Collection(common_mut, CollectionHandle<T>),
TokenProperties,
)
)]
pallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterbothbinary blob — no preview
pallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth--- a/pallets/nonfungible/src/stubs/UniqueNFT.sol
+++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol
@@ -3,13 +3,7 @@
pragma solidity >=0.8.0 <0.9.0;
-// Anonymous struct
-struct Tuple0 {
- uint256 field_0;
- string field_1;
-}
-
-// Common stubs holder
+/// @dev common stubs holder
contract Dummy {
uint8 dummy;
string stub_error = "this contract is implemented in native";
@@ -27,40 +21,17 @@
}
}
-// Inline
-contract ERC721Events {
- event Transfer(
- address indexed from,
- address indexed to,
- uint256 indexed tokenId
- );
- event Approval(
- address indexed owner,
- address indexed approved,
- uint256 indexed tokenId
- );
- event ApprovalForAll(
- address indexed owner,
- address indexed operator,
- bool approved
- );
-}
-
-// Inline
-contract ERC721MintableEvents {
- event MintingFinished();
-}
-
-// Selector: 41369377
+/// @title A contract that allows to set and delete token properties and change token property permissions.
+/// @dev the ERC-165 identifier for this interface is 0x41369377
contract TokenProperties is Dummy, ERC165 {
- // @notice Set permissions for token property.
- // @dev Throws error if `msg.sender` is not admin or owner of the collection.
- // @param key Property key.
- // @param is_mutable Permission to mutate property.
- // @param collection_admin Permission to mutate property by collection admin if property is mutable.
- // @param token_owner Permission to mutate property by token owner if property is mutable.
- //
- // Selector: setTokenPropertyPermission(string,bool,bool,bool) 222d97fa
+ /// @notice Set permissions for token property.
+ /// @dev Throws error if `msg.sender` is not admin or owner of the collection.
+ /// @param key Property key.
+ /// @param isMutable Permission to mutate property.
+ /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.
+ /// @param tokenOwner Permission to mutate property by token owner if property is mutable.
+ /// @dev EVM selector for this function is: 0x222d97fa,
+ /// or in textual repr: setTokenPropertyPermission(string,bool,bool,bool)
function setTokenPropertyPermission(
string memory key,
bool isMutable,
@@ -75,13 +46,13 @@
dummy = 0;
}
- // @notice Set token property value.
- // @dev Throws error if `msg.sender` has no permission to edit the property.
- // @param tokenId ID of the token.
- // @param key Property key.
- // @param value Property value.
- //
- // Selector: setProperty(uint256,string,bytes) 1752d67b
+ /// @notice Set token property value.
+ /// @dev Throws error if `msg.sender` has no permission to edit the property.
+ /// @param tokenId ID of the token.
+ /// @param key Property key.
+ /// @param value Property value.
+ /// @dev EVM selector for this function is: 0x1752d67b,
+ /// or in textual repr: setProperty(uint256,string,bytes)
function setProperty(
uint256 tokenId,
string memory key,
@@ -94,12 +65,12 @@
dummy = 0;
}
- // @notice Delete token property value.
- // @dev Throws error if `msg.sender` has no permission to edit the property.
- // @param tokenId ID of the token.
- // @param key Property key.
- //
- // Selector: deleteProperty(uint256,string) 066111d1
+ /// @notice Delete token property value.
+ /// @dev Throws error if `msg.sender` has no permission to edit the property.
+ /// @param tokenId ID of the token.
+ /// @param key Property key.
+ /// @dev EVM selector for this function is: 0x066111d1,
+ /// or in textual repr: deleteProperty(uint256,string)
function deleteProperty(uint256 tokenId, string memory key) public {
require(false, stub_error);
tokenId;
@@ -107,13 +78,13 @@
dummy = 0;
}
- // @notice Get token property value.
- // @dev Throws error if key not found
- // @param tokenId ID of the token.
- // @param key Property key.
- // @return Property value bytes
- //
- // Selector: property(uint256,string) 7228c327
+ /// @notice Get token property value.
+ /// @dev Throws error if key not found
+ /// @param tokenId ID of the token.
+ /// @param key Property key.
+ /// @return Property value bytes
+ /// @dev EVM selector for this function is: 0x7228c327,
+ /// or in textual repr: property(uint256,string)
function property(uint256 tokenId, string memory key)
public
view
@@ -127,213 +98,334 @@
}
}
-// Selector: 42966c68
-contract ERC721Burnable is Dummy, ERC165 {
- // @notice Burns a specific ERC721 token.
- // @dev Throws unless `msg.sender` is the current NFT owner, or an authorized
- // operator of the current owner.
- // @param tokenId The NFT to approve
- //
- // Selector: burn(uint256) 42966c68
- function burn(uint256 tokenId) public {
+/// @title A contract that allows you to work with collections.
+/// @dev the ERC-165 identifier for this interface is 0xffe4da23
+contract Collection is Dummy, ERC165 {
+ /// Set collection property.
+ ///
+ /// @param key Property key.
+ /// @param value Propery value.
+ /// @dev EVM selector for this function is: 0x2f073f66,
+ /// or in textual repr: setCollectionProperty(string,bytes)
+ function setCollectionProperty(string memory key, bytes memory value)
+ public
+ {
require(false, stub_error);
- tokenId;
+ key;
+ value;
dummy = 0;
}
-}
-// Selector: 58800161
-contract ERC721 is Dummy, ERC165, ERC721Events {
- // @notice Count all NFTs assigned to an owner
- // @dev NFTs assigned to the zero address are considered invalid, and this
- // function throws for queries about the zero address.
- // @param owner An address for whom to query the balance
- // @return The number of NFTs owned by `owner`, possibly zero
- //
- // Selector: balanceOf(address) 70a08231
- function balanceOf(address owner) public view returns (uint256) {
+ /// Delete collection property.
+ ///
+ /// @param key Property key.
+ /// @dev EVM selector for this function is: 0x7b7debce,
+ /// or in textual repr: deleteCollectionProperty(string)
+ function deleteCollectionProperty(string memory key) public {
require(false, stub_error);
- owner;
- dummy;
- return 0;
+ key;
+ dummy = 0;
}
- // @notice Find the owner of an NFT
- // @dev NFTs assigned to zero address are considered invalid, and queries
- // about them do throw.
- // @param tokenId The identifier for an NFT
- // @return The address of the owner of the NFT
- //
- // Selector: ownerOf(uint256) 6352211e
- function ownerOf(uint256 tokenId) public view returns (address) {
+ /// Get collection property.
+ ///
+ /// @dev Throws error if key not found.
+ ///
+ /// @param key Property key.
+ /// @return bytes The property corresponding to the key.
+ /// @dev EVM selector for this function is: 0xcf24fd6d,
+ /// or in textual repr: collectionProperty(string)
+ function collectionProperty(string memory key)
+ public
+ view
+ returns (bytes memory)
+ {
require(false, stub_error);
- tokenId;
+ key;
dummy;
- return 0x0000000000000000000000000000000000000000;
+ return hex"";
}
- // @dev Not implemented
- //
- // Selector: safeTransferFromWithData(address,address,uint256,bytes) 60a11672
- function safeTransferFromWithData(
- address from,
- address to,
- uint256 tokenId,
- bytes memory data
- ) public {
+ /// Set the sponsor of the collection.
+ ///
+ /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.
+ ///
+ /// @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.
+ /// @dev EVM selector for this function is: 0x7623402e,
+ /// or in textual repr: setCollectionSponsor(address)
+ function setCollectionSponsor(address sponsor) public {
require(false, stub_error);
- from;
- to;
- tokenId;
- data;
+ sponsor;
dummy = 0;
}
- // @dev Not implemented
- //
- // Selector: safeTransferFrom(address,address,uint256) 42842e0e
- function safeTransferFrom(
- address from,
- address to,
- uint256 tokenId
- ) public {
+ /// Collection sponsorship confirmation.
+ ///
+ /// @dev After setting the sponsor for the collection, it must be confirmed with this function.
+ /// @dev EVM selector for this function is: 0x3c50e97a,
+ /// or in textual repr: confirmCollectionSponsorship()
+ function confirmCollectionSponsorship() public {
require(false, stub_error);
- from;
- to;
- tokenId;
dummy = 0;
}
- // @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
- // TO CONFIRM THAT `to` IS CAPABLE OF RECEIVING NFTS OR ELSE
- // THEY MAY BE PERMANENTLY LOST
- // @dev Throws unless `msg.sender` is the current owner or an authorized
- // operator for this NFT. Throws if `from` is not the current owner. Throws
- // if `to` is the zero address. Throws if `tokenId` is not a valid NFT.
- // @param from The current owner of the NFT
- // @param to The new owner
- // @param tokenId The NFT to transfer
- // @param _value Not used for an NFT
- //
- // Selector: transferFrom(address,address,uint256) 23b872dd
- function transferFrom(
- address from,
- address to,
- uint256 tokenId
- ) public {
+ /// Set limits for the collection.
+ /// @dev Throws error if limit not found.
+ /// @param limit Name of the limit. Valid names:
+ /// "accountTokenOwnershipLimit",
+ /// "sponsoredDataSize",
+ /// "sponsoredDataRateLimit",
+ /// "tokenLimit",
+ /// "sponsorTransferTimeout",
+ /// "sponsorApproveTimeout"
+ /// @param value Value of the limit.
+ /// @dev EVM selector for this function is: 0x6a3841db,
+ /// or in textual repr: setCollectionLimit(string,uint32)
+ function setCollectionLimit(string memory limit, uint32 value) public {
require(false, stub_error);
- from;
- to;
- tokenId;
+ limit;
+ value;
dummy = 0;
}
- // @notice Set or reaffirm the approved address for an NFT
- // @dev The zero address indicates there is no approved address.
- // @dev Throws unless `msg.sender` is the current NFT owner, or an authorized
- // operator of the current owner.
- // @param approved The new approved NFT controller
- // @param tokenId The NFT to approve
- //
- // Selector: approve(address,uint256) 095ea7b3
- function approve(address approved, uint256 tokenId) public {
+ /// Set limits for the collection.
+ /// @dev Throws error if limit not found.
+ /// @param limit Name of the limit. Valid names:
+ /// "ownerCanTransfer",
+ /// "ownerCanDestroy",
+ /// "transfersEnabled"
+ /// @param value Value of the limit.
+ /// @dev EVM selector for this function is: 0x993b7fba,
+ /// or in textual repr: setCollectionLimit(string,bool)
+ function setCollectionLimit(string memory limit, bool value) public {
require(false, stub_error);
- approved;
- tokenId;
+ limit;
+ value;
dummy = 0;
}
- // @dev Not implemented
- //
- // Selector: setApprovalForAll(address,bool) a22cb465
- function setApprovalForAll(address operator, bool approved) public {
+ /// Get contract address.
+ /// @dev EVM selector for this function is: 0xf6b4dfb4,
+ /// or in textual repr: contractAddress()
+ function contractAddress() public view returns (address) {
+ require(false, stub_error);
+ dummy;
+ return 0x0000000000000000000000000000000000000000;
+ }
+
+ /// Add collection admin by substrate address.
+ /// @param newAdmin Substrate administrator address.
+ /// @dev EVM selector for this function is: 0x5730062b,
+ /// or in textual repr: addCollectionAdminSubstrate(uint256)
+ function addCollectionAdminSubstrate(uint256 newAdmin) public {
+ require(false, stub_error);
+ newAdmin;
+ dummy = 0;
+ }
+
+ /// Remove collection admin by substrate address.
+ /// @param admin Substrate administrator address.
+ /// @dev EVM selector for this function is: 0x4048fcf9,
+ /// or in textual repr: removeCollectionAdminSubstrate(uint256)
+ function removeCollectionAdminSubstrate(uint256 admin) public {
+ require(false, stub_error);
+ admin;
+ dummy = 0;
+ }
+
+ /// Add collection admin.
+ /// @param newAdmin Address of the added administrator.
+ /// @dev EVM selector for this function is: 0x92e462c7,
+ /// or in textual repr: addCollectionAdmin(address)
+ function addCollectionAdmin(address newAdmin) public {
+ require(false, stub_error);
+ newAdmin;
+ dummy = 0;
+ }
+
+ /// Remove collection admin.
+ ///
+ /// @param admin Address of the removed administrator.
+ /// @dev EVM selector for this function is: 0xfafd7b42,
+ /// or in textual repr: removeCollectionAdmin(address)
+ function removeCollectionAdmin(address admin) public {
require(false, stub_error);
- operator;
- approved;
+ admin;
dummy = 0;
}
- // @dev Not implemented
- //
- // Selector: getApproved(uint256) 081812fc
- function getApproved(uint256 tokenId) public view returns (address) {
+ /// Toggle accessibility of collection nesting.
+ ///
+ /// @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'
+ /// @dev EVM selector for this function is: 0x112d4586,
+ /// or in textual repr: setCollectionNesting(bool)
+ function setCollectionNesting(bool enable) public {
require(false, stub_error);
- tokenId;
- dummy;
- return 0x0000000000000000000000000000000000000000;
+ enable;
+ dummy = 0;
}
- // @dev Not implemented
- //
- // Selector: isApprovedForAll(address,address) e985e9c5
- function isApprovedForAll(address owner, address operator)
+ /// Toggle accessibility of collection nesting.
+ ///
+ /// @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'
+ /// @param collections Addresses of collections that will be available for nesting.
+ /// @dev EVM selector for this function is: 0x64872396,
+ /// or in textual repr: setCollectionNesting(bool,address[])
+ function setCollectionNesting(bool enable, address[] memory collections)
public
- view
- returns (address)
{
require(false, stub_error);
- owner;
- operator;
+ enable;
+ collections;
+ dummy = 0;
+ }
+
+ /// Set the collection access method.
+ /// @param mode Access mode
+ /// 0 for Normal
+ /// 1 for AllowList
+ /// @dev EVM selector for this function is: 0x41835d4c,
+ /// or in textual repr: setCollectionAccess(uint8)
+ function setCollectionAccess(uint8 mode) public {
+ require(false, stub_error);
+ mode;
+ dummy = 0;
+ }
+
+ /// Add the user to the allowed list.
+ ///
+ /// @param user Address of a trusted user.
+ /// @dev EVM selector for this function is: 0x67844fe6,
+ /// or in textual repr: addToCollectionAllowList(address)
+ function addToCollectionAllowList(address user) public {
+ require(false, stub_error);
+ user;
+ dummy = 0;
+ }
+
+ /// Remove the user from the allowed list.
+ ///
+ /// @param user Address of a removed user.
+ /// @dev EVM selector for this function is: 0x85c51acb,
+ /// or in textual repr: removeFromCollectionAllowList(address)
+ function removeFromCollectionAllowList(address user) public {
+ require(false, stub_error);
+ user;
+ dummy = 0;
+ }
+
+ /// Switch permission for minting.
+ ///
+ /// @param mode Enable if "true".
+ /// @dev EVM selector for this function is: 0x00018e84,
+ /// or in textual repr: setCollectionMintMode(bool)
+ function setCollectionMintMode(bool mode) public {
+ require(false, stub_error);
+ mode;
+ dummy = 0;
+ }
+
+ /// Check that account is the owner or admin of the collection
+ ///
+ /// @param user account to verify
+ /// @return "true" if account is the owner or admin
+ /// @dev EVM selector for this function is: 0x9811b0c7,
+ /// or in textual repr: isOwnerOrAdmin(address)
+ function isOwnerOrAdmin(address user) public view returns (bool) {
+ require(false, stub_error);
+ user;
dummy;
- return 0x0000000000000000000000000000000000000000;
+ return false;
}
-}
-// Selector: 5b5e139f
-contract ERC721Metadata is Dummy, ERC165 {
- // @notice A descriptive name for a collection of NFTs in this contract
- //
- // Selector: name() 06fdde03
- function name() public view returns (string memory) {
+ /// Check that substrate account is the owner or admin of the collection
+ ///
+ /// @param user account to verify
+ /// @return "true" if account is the owner or admin
+ /// @dev EVM selector for this function is: 0x68910e00,
+ /// or in textual repr: isOwnerOrAdminSubstrate(uint256)
+ function isOwnerOrAdminSubstrate(uint256 user) public view returns (bool) {
require(false, stub_error);
+ user;
dummy;
+ return false;
+ }
+
+ /// Returns collection type
+ ///
+ /// @return `Fungible` or `NFT` or `ReFungible`
+ /// @dev EVM selector for this function is: 0xd34b55b8,
+ /// or in textual repr: uniqueCollectionType()
+ function uniqueCollectionType() public returns (string memory) {
+ require(false, stub_error);
+ dummy = 0;
return "";
}
- // @notice An abbreviated name for NFTs in this contract
- //
- // Selector: symbol() 95d89b41
- function symbol() public view returns (string memory) {
+ /// Changes collection owner to another account
+ ///
+ /// @dev Owner can be changed only by current owner
+ /// @param newOwner new owner account
+ /// @dev EVM selector for this function is: 0x13af4035,
+ /// or in textual repr: setOwner(address)
+ function setOwner(address newOwner) public {
+ require(false, stub_error);
+ newOwner;
+ dummy = 0;
+ }
+
+ /// Changes collection owner to another substrate account
+ ///
+ /// @dev Owner can be changed only by current owner
+ /// @param newOwner new owner substrate account
+ /// @dev EVM selector for this function is: 0xb212138f,
+ /// or in textual repr: setOwnerSubstrate(uint256)
+ function setOwnerSubstrate(uint256 newOwner) public {
require(false, stub_error);
- dummy;
- return "";
+ newOwner;
+ dummy = 0;
}
+}
- // @notice A distinct Uniform Resource Identifier (URI) for a given asset.
- //
- // @dev If the token has a `url` property and it is not empty, it is returned.
- // Else If the collection does not have a property with key `schemaName` or its value is not equal to `ERC721Metadata`, it return an error `tokenURI not set`.
- // If the collection property `baseURI` is empty or absent, return "" (empty string)
- // otherwise, if token property `suffix` present and is non-empty, return concatenation of baseURI and suffix
- // otherwise, return concatenation of `baseURI` and stringified token id (decimal stringifying, without paddings).
- //
- // @return token's const_metadata
- //
- // Selector: tokenURI(uint256) c87b56dd
- function tokenURI(uint256 tokenId) public view returns (string memory) {
+/// @title ERC721 Token that can be irreversibly burned (destroyed).
+/// @dev the ERC-165 identifier for this interface is 0x42966c68
+contract ERC721Burnable is Dummy, ERC165 {
+ /// @notice Burns a specific ERC721 token.
+ /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized
+ /// operator of the current owner.
+ /// @param tokenId The NFT to approve
+ /// @dev EVM selector for this function is: 0x42966c68,
+ /// or in textual repr: burn(uint256)
+ function burn(uint256 tokenId) public {
require(false, stub_error);
tokenId;
- dummy;
- return "";
+ dummy = 0;
}
}
-// Selector: 68ccfe89
+/// @dev inlined interface
+contract ERC721MintableEvents {
+ event MintingFinished();
+}
+
+/// @title ERC721 minting logic.
+/// @dev the ERC-165 identifier for this interface is 0x68ccfe89
contract ERC721Mintable is Dummy, ERC165, ERC721MintableEvents {
- // Selector: mintingFinished() 05d2035b
+ /// @dev EVM selector for this function is: 0x05d2035b,
+ /// or in textual repr: mintingFinished()
function mintingFinished() public view returns (bool) {
require(false, stub_error);
dummy;
return false;
}
- // @notice Function to mint token.
- // @dev `tokenId` should be obtained with `nextTokenId` method,
- // unlike standard, you can't specify it manually
- // @param to The new owner
- // @param tokenId ID of the minted NFT
- //
- // Selector: mint(address,uint256) 40c10f19
+ /// @notice Function to mint token.
+ /// @dev `tokenId` should be obtained with `nextTokenId` method,
+ /// unlike standard, you can't specify it manually
+ /// @param to The new owner
+ /// @param tokenId ID of the minted NFT
+ /// @dev EVM selector for this function is: 0x40c10f19,
+ /// or in textual repr: mint(address,uint256)
function mint(address to, uint256 tokenId) public returns (bool) {
require(false, stub_error);
to;
@@ -342,14 +434,14 @@
return false;
}
- // @notice Function to mint token with the given tokenUri.
- // @dev `tokenId` should be obtained with `nextTokenId` method,
- // unlike standard, you can't specify it manually
- // @param to The new owner
- // @param tokenId ID of the minted NFT
- // @param tokenUri Token URI that would be stored in the NFT properties
- //
- // Selector: mintWithTokenURI(address,uint256,string) 50bb4e7f
+ /// @notice Function to mint token with the given tokenUri.
+ /// @dev `tokenId` should be obtained with `nextTokenId` method,
+ /// unlike standard, you can't specify it manually
+ /// @param to The new owner
+ /// @param tokenId ID of the minted NFT
+ /// @param tokenUri Token URI that would be stored in the NFT properties
+ /// @dev EVM selector for this function is: 0x50bb4e7f,
+ /// or in textual repr: mintWithTokenURI(address,uint256,string)
function mintWithTokenURI(
address to,
uint256 tokenId,
@@ -363,9 +455,9 @@
return false;
}
- // @dev Not implemented
- //
- // Selector: finishMinting() 7d64bcb4
+ /// @dev Not implemented
+ /// @dev EVM selector for this function is: 0x7d64bcb4,
+ /// or in textual repr: finishMinting()
function finishMinting() public returns (bool) {
require(false, stub_error);
dummy = 0;
@@ -373,58 +465,16 @@
}
}
-// Selector: 780e9d63
-contract ERC721Enumerable is Dummy, ERC165 {
- // @notice Enumerate valid NFTs
- // @param index A counter less than `totalSupply()`
- // @return The token identifier for the `index`th NFT,
- // (sort order not specified)
- //
- // Selector: tokenByIndex(uint256) 4f6ccce7
- function tokenByIndex(uint256 index) public view returns (uint256) {
- require(false, stub_error);
- index;
- dummy;
- return 0;
- }
-
- // @dev Not implemented
- //
- // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59
- function tokenOfOwnerByIndex(address owner, uint256 index)
- public
- view
- returns (uint256)
- {
- require(false, stub_error);
- owner;
- index;
- dummy;
- return 0;
- }
-
- // @notice Count NFTs tracked by this contract
- // @return A count of valid NFTs tracked by this contract, where each one of
- // them has an assigned and queryable owner not equal to the zero address
- //
- // Selector: totalSupply() 18160ddd
- function totalSupply() public view returns (uint256) {
- require(false, stub_error);
- dummy;
- return 0;
- }
-}
-
-// Selector: d74d154f
+/// @title Unique extensions for ERC721.
+/// @dev the ERC-165 identifier for this interface is 0xd74d154f
contract ERC721UniqueExtensions is Dummy, ERC165 {
- // @notice Transfer ownership of an NFT
- // @dev Throws unless `msg.sender` is the current owner. Throws if `to`
- // is the zero address. Throws if `tokenId` is not a valid NFT.
- // @param to The new owner
- // @param tokenId The NFT to transfer
- // @param _value Not used for an NFT
- //
- // Selector: transfer(address,uint256) a9059cbb
+ /// @notice Transfer ownership of an NFT
+ /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
+ /// is the zero address. Throws if `tokenId` is not a valid NFT.
+ /// @param to The new owner
+ /// @param tokenId The NFT to transfer
+ /// @dev EVM selector for this function is: 0xa9059cbb,
+ /// or in textual repr: transfer(address,uint256)
function transfer(address to, uint256 tokenId) public {
require(false, stub_error);
to;
@@ -432,15 +482,14 @@
dummy = 0;
}
- // @notice Burns a specific ERC721 token.
- // @dev Throws unless `msg.sender` is the current owner or an authorized
- // operator for this NFT. Throws if `from` is not the current owner. Throws
- // if `to` is the zero address. Throws if `tokenId` is not a valid NFT.
- // @param from The current owner of the NFT
- // @param tokenId The NFT to transfer
- // @param _value Not used for an NFT
- //
- // Selector: burnFrom(address,uint256) 79cc6790
+ /// @notice Burns a specific ERC721 token.
+ /// @dev Throws unless `msg.sender` is the current owner or an authorized
+ /// operator for this NFT. Throws if `from` is not the current owner. Throws
+ /// if `to` is the zero address. Throws if `tokenId` is not a valid NFT.
+ /// @param from The current owner of the NFT
+ /// @param tokenId The NFT to transfer
+ /// @dev EVM selector for this function is: 0x79cc6790,
+ /// or in textual repr: burnFrom(address,uint256)
function burnFrom(address from, uint256 tokenId) public {
require(false, stub_error);
from;
@@ -448,22 +497,22 @@
dummy = 0;
}
- // @notice Returns next free NFT ID.
- //
- // Selector: nextTokenId() 75794a3c
+ /// @notice Returns next free NFT ID.
+ /// @dev EVM selector for this function is: 0x75794a3c,
+ /// or in textual repr: nextTokenId()
function nextTokenId() public view returns (uint256) {
require(false, stub_error);
dummy;
return 0;
}
- // @notice Function to mint multiple tokens.
- // @dev `tokenIds` should be an array of consecutive numbers and first number
- // should be obtained with `nextTokenId` method
- // @param to The new owner
- // @param tokenIds IDs of the minted NFTs
- //
- // Selector: mintBulk(address,uint256[]) 44a9945e
+ /// @notice Function to mint multiple tokens.
+ /// @dev `tokenIds` should be an array of consecutive numbers and first number
+ /// should be obtained with `nextTokenId` method
+ /// @param to The new owner
+ /// @param tokenIds IDs of the minted NFTs
+ /// @dev EVM selector for this function is: 0x44a9945e,
+ /// or in textual repr: mintBulk(address,uint256[])
function mintBulk(address to, uint256[] memory tokenIds)
public
returns (bool)
@@ -475,14 +524,14 @@
return false;
}
- // @notice Function to mint multiple tokens with the given tokenUris.
- // @dev `tokenIds` is array of pairs of token ID and token URI. Token IDs should be consecutive
- // numbers and first number should be obtained with `nextTokenId` method
- // @param to The new owner
- // @param tokens array of pairs of token ID and token URI for minted tokens
- //
- // Selector: mintBulkWithTokenURI(address,(uint256,string)[]) 36543006
- function mintBulkWithTokenURI(address to, Tuple0[] memory tokens)
+ /// @notice Function to mint multiple tokens with the given tokenUris.
+ /// @dev `tokenIds` is array of pairs of token ID and token URI. Token IDs should be consecutive
+ /// numbers and first number should be obtained with `nextTokenId` method
+ /// @param to The new owner
+ /// @param tokens array of pairs of token ID and token URI for minted tokens
+ /// @dev EVM selector for this function is: 0x36543006,
+ /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])
+ function mintBulkWithTokenURI(address to, Tuple8[] memory tokens)
public
returns (bool)
{
@@ -494,291 +543,251 @@
}
}
-// Selector: ffe4da23
-contract Collection is Dummy, ERC165 {
- // Set collection property.
- //
- // @param key Property key.
- // @param value Propery value.
- //
- // Selector: setCollectionProperty(string,bytes) 2f073f66
- function setCollectionProperty(string memory key, bytes memory value)
- public
- {
- require(false, stub_error);
- key;
- value;
- dummy = 0;
- }
+/// @dev anonymous struct
+struct Tuple8 {
+ uint256 field_0;
+ string field_1;
+}
- // Delete collection property.
- //
- // @param key Property key.
- //
- // Selector: deleteCollectionProperty(string) 7b7debce
- function deleteCollectionProperty(string memory key) public {
+/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
+/// @dev See https://eips.ethereum.org/EIPS/eip-721
+/// @dev the ERC-165 identifier for this interface is 0x780e9d63
+contract ERC721Enumerable is Dummy, ERC165 {
+ /// @notice Enumerate valid NFTs
+ /// @param index A counter less than `totalSupply()`
+ /// @return The token identifier for the `index`th NFT,
+ /// (sort order not specified)
+ /// @dev EVM selector for this function is: 0x4f6ccce7,
+ /// or in textual repr: tokenByIndex(uint256)
+ function tokenByIndex(uint256 index) public view returns (uint256) {
require(false, stub_error);
- key;
- dummy = 0;
+ index;
+ dummy;
+ return 0;
}
- // Get collection property.
- //
- // @dev Throws error if key not found.
- //
- // @param key Property key.
- // @return bytes The property corresponding to the key.
- //
- // Selector: collectionProperty(string) cf24fd6d
- function collectionProperty(string memory key)
+ /// @dev Not implemented
+ /// @dev EVM selector for this function is: 0x2f745c59,
+ /// or in textual repr: tokenOfOwnerByIndex(address,uint256)
+ function tokenOfOwnerByIndex(address owner, uint256 index)
public
view
- returns (bytes memory)
+ returns (uint256)
{
require(false, stub_error);
- key;
+ owner;
+ index;
dummy;
- return hex"";
+ return 0;
}
- // Set the sponsor of the collection.
- //
- // @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.
- //
- // @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.
- //
- // Selector: setCollectionSponsor(address) 7623402e
- function setCollectionSponsor(address sponsor) public {
+ /// @notice Count NFTs tracked by this contract
+ /// @return A count of valid NFTs tracked by this contract, where each one of
+ /// them has an assigned and queryable owner not equal to the zero address
+ /// @dev EVM selector for this function is: 0x18160ddd,
+ /// or in textual repr: totalSupply()
+ function totalSupply() public view returns (uint256) {
require(false, stub_error);
- sponsor;
- dummy = 0;
+ dummy;
+ return 0;
}
+}
- // Collection sponsorship confirmation.
- //
- // @dev After setting the sponsor for the collection, it must be confirmed with this function.
- //
- // Selector: confirmCollectionSponsorship() 3c50e97a
- function confirmCollectionSponsorship() public {
+/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
+/// @dev See https://eips.ethereum.org/EIPS/eip-721
+/// @dev the ERC-165 identifier for this interface is 0x5b5e139f
+contract ERC721Metadata is Dummy, ERC165 {
+ /// @notice A descriptive name for a collection of NFTs in this contract
+ /// @dev EVM selector for this function is: 0x06fdde03,
+ /// or in textual repr: name()
+ function name() public view returns (string memory) {
require(false, stub_error);
- dummy = 0;
+ dummy;
+ return "";
}
- // Set limits for the collection.
- // @dev Throws error if limit not found.
- // @param limit Name of the limit. Valid names:
- // "accountTokenOwnershipLimit",
- // "sponsoredDataSize",
- // "sponsoredDataRateLimit",
- // "tokenLimit",
- // "sponsorTransferTimeout",
- // "sponsorApproveTimeout"
- // @param value Value of the limit.
- //
- // Selector: setCollectionLimit(string,uint32) 6a3841db
- function setCollectionLimit(string memory limit, uint32 value) public {
+ /// @notice An abbreviated name for NFTs in this contract
+ /// @dev EVM selector for this function is: 0x95d89b41,
+ /// or in textual repr: symbol()
+ function symbol() public view returns (string memory) {
require(false, stub_error);
- limit;
- value;
- dummy = 0;
+ dummy;
+ return "";
}
- // Set limits for the collection.
- // @dev Throws error if limit not found.
- // @param limit Name of the limit. Valid names:
- // "ownerCanTransfer",
- // "ownerCanDestroy",
- // "transfersEnabled"
- // @param value Value of the limit.
- //
- // Selector: setCollectionLimit(string,bool) 993b7fba
- function setCollectionLimit(string memory limit, bool value) public {
+ /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
+ ///
+ /// @dev If the token has a `url` property and it is not empty, it is returned.
+ /// Else If the collection does not have a property with key `schemaName` or its value is not equal to `ERC721Metadata`, it return an error `tokenURI not set`.
+ /// If the collection property `baseURI` is empty or absent, return "" (empty string)
+ /// otherwise, if token property `suffix` present and is non-empty, return concatenation of baseURI and suffix
+ /// otherwise, return concatenation of `baseURI` and stringified token id (decimal stringifying, without paddings).
+ ///
+ /// @return token's const_metadata
+ /// @dev EVM selector for this function is: 0xc87b56dd,
+ /// or in textual repr: tokenURI(uint256)
+ function tokenURI(uint256 tokenId) public view returns (string memory) {
require(false, stub_error);
- limit;
- value;
- dummy = 0;
- }
-
- // Get contract address.
- //
- // Selector: contractAddress() f6b4dfb4
- function contractAddress() public view returns (address) {
- require(false, stub_error);
+ tokenId;
dummy;
- return 0x0000000000000000000000000000000000000000;
+ return "";
}
+}
- // Add collection admin by substrate address.
- // @param new_admin Substrate administrator address.
- //
- // Selector: addCollectionAdminSubstrate(uint256) 5730062b
- function addCollectionAdminSubstrate(uint256 newAdmin) public {
- require(false, stub_error);
- newAdmin;
- dummy = 0;
- }
+/// @dev inlined interface
+contract ERC721Events {
+ event Transfer(
+ address indexed from,
+ address indexed to,
+ uint256 indexed tokenId
+ );
+ event Approval(
+ address indexed owner,
+ address indexed approved,
+ uint256 indexed tokenId
+ );
+ event ApprovalForAll(
+ address indexed owner,
+ address indexed operator,
+ bool approved
+ );
+}
- // Remove collection admin by substrate address.
- // @param admin Substrate administrator address.
- //
- // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9
- function removeCollectionAdminSubstrate(uint256 admin) public {
+/// @title ERC-721 Non-Fungible Token Standard
+/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
+/// @dev the ERC-165 identifier for this interface is 0x80ac58cd
+contract ERC721 is Dummy, ERC165, ERC721Events {
+ /// @notice Count all NFTs assigned to an owner
+ /// @dev NFTs assigned to the zero address are considered invalid, and this
+ /// function throws for queries about the zero address.
+ /// @param owner An address for whom to query the balance
+ /// @return The number of NFTs owned by `owner`, possibly zero
+ /// @dev EVM selector for this function is: 0x70a08231,
+ /// or in textual repr: balanceOf(address)
+ function balanceOf(address owner) public view returns (uint256) {
require(false, stub_error);
- admin;
- dummy = 0;
+ owner;
+ dummy;
+ return 0;
}
- // Add collection admin.
- // @param new_admin Address of the added administrator.
- //
- // Selector: addCollectionAdmin(address) 92e462c7
- function addCollectionAdmin(address newAdmin) public {
+ /// @notice Find the owner of an NFT
+ /// @dev NFTs assigned to zero address are considered invalid, and queries
+ /// about them do throw.
+ /// @param tokenId The identifier for an NFT
+ /// @return The address of the owner of the NFT
+ /// @dev EVM selector for this function is: 0x6352211e,
+ /// or in textual repr: ownerOf(uint256)
+ function ownerOf(uint256 tokenId) public view returns (address) {
require(false, stub_error);
- newAdmin;
- dummy = 0;
+ tokenId;
+ dummy;
+ return 0x0000000000000000000000000000000000000000;
}
- // Remove collection admin.
- //
- // @param new_admin Address of the removed administrator.
- //
- // Selector: removeCollectionAdmin(address) fafd7b42
- function removeCollectionAdmin(address admin) public {
+ /// @dev Not implemented
+ /// @dev EVM selector for this function is: 0xb88d4fde,
+ /// or in textual repr: safeTransferFrom(address,address,uint256,bytes)
+ function safeTransferFrom(
+ address from,
+ address to,
+ uint256 tokenId,
+ bytes memory data
+ ) public {
require(false, stub_error);
- admin;
+ from;
+ to;
+ tokenId;
+ data;
dummy = 0;
}
- // Toggle accessibility of collection nesting.
- //
- // @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'
- //
- // Selector: setCollectionNesting(bool) 112d4586
- function setCollectionNesting(bool enable) public {
+ /// @dev Not implemented
+ /// @dev EVM selector for this function is: 0x42842e0e,
+ /// or in textual repr: safeTransferFrom(address,address,uint256)
+ function safeTransferFrom(
+ address from,
+ address to,
+ uint256 tokenId
+ ) public {
require(false, stub_error);
- enable;
+ from;
+ to;
+ tokenId;
dummy = 0;
}
- // Toggle accessibility of collection nesting.
- //
- // @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'
- // @param collections Addresses of collections that will be available for nesting.
- //
- // Selector: setCollectionNesting(bool,address[]) 64872396
- function setCollectionNesting(bool enable, address[] memory collections)
- public
- {
+ /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
+ /// TO CONFIRM THAT `to` IS CAPABLE OF RECEIVING NFTS OR ELSE
+ /// THEY MAY BE PERMANENTLY LOST
+ /// @dev Throws unless `msg.sender` is the current owner or an authorized
+ /// operator for this NFT. Throws if `from` is not the current owner. Throws
+ /// if `to` is the zero address. Throws if `tokenId` is not a valid NFT.
+ /// @param from The current owner of the NFT
+ /// @param to The new owner
+ /// @param tokenId The NFT to transfer
+ /// @dev EVM selector for this function is: 0x23b872dd,
+ /// or in textual repr: transferFrom(address,address,uint256)
+ function transferFrom(
+ address from,
+ address to,
+ uint256 tokenId
+ ) public {
require(false, stub_error);
- enable;
- collections;
+ from;
+ to;
+ tokenId;
dummy = 0;
}
- // Set the collection access method.
- // @param mode Access mode
- // 0 for Normal
- // 1 for AllowList
- //
- // Selector: setCollectionAccess(uint8) 41835d4c
- function setCollectionAccess(uint8 mode) public {
+ /// @notice Set or reaffirm the approved address for an NFT
+ /// @dev The zero address indicates there is no approved address.
+ /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized
+ /// operator of the current owner.
+ /// @param approved The new approved NFT controller
+ /// @param tokenId The NFT to approve
+ /// @dev EVM selector for this function is: 0x095ea7b3,
+ /// or in textual repr: approve(address,uint256)
+ function approve(address approved, uint256 tokenId) public {
require(false, stub_error);
- mode;
+ approved;
+ tokenId;
dummy = 0;
}
- // Add the user to the allowed list.
- //
- // @param user Address of a trusted user.
- //
- // Selector: addToCollectionAllowList(address) 67844fe6
- function addToCollectionAllowList(address user) public {
+ /// @dev Not implemented
+ /// @dev EVM selector for this function is: 0xa22cb465,
+ /// or in textual repr: setApprovalForAll(address,bool)
+ function setApprovalForAll(address operator, bool approved) public {
require(false, stub_error);
- user;
- dummy = 0;
- }
-
- // Remove the user from the allowed list.
- //
- // @param user Address of a removed user.
- //
- // Selector: removeFromCollectionAllowList(address) 85c51acb
- function removeFromCollectionAllowList(address user) public {
- require(false, stub_error);
- user;
+ operator;
+ approved;
dummy = 0;
}
- // Switch permission for minting.
- //
- // @param mode Enable if "true".
- //
- // Selector: setCollectionMintMode(bool) 00018e84
- function setCollectionMintMode(bool mode) public {
+ /// @dev Not implemented
+ /// @dev EVM selector for this function is: 0x081812fc,
+ /// or in textual repr: getApproved(uint256)
+ function getApproved(uint256 tokenId) public view returns (address) {
require(false, stub_error);
- mode;
- dummy = 0;
- }
-
- // Check that account is the owner or admin of the collection
- //
- // @param user account to verify
- // @return "true" if account is the owner or admin
- //
- // Selector: isOwnerOrAdmin(address) 9811b0c7
- function isOwnerOrAdmin(address user) public view returns (bool) {
- require(false, stub_error);
- user;
+ tokenId;
dummy;
- return false;
+ return 0x0000000000000000000000000000000000000000;
}
- // Check that substrate account is the owner or admin of the collection
- //
- // @param user account to verify
- // @return "true" if account is the owner or admin
- //
- // Selector: isOwnerOrAdminSubstrate(uint256) 68910e00
- function isOwnerOrAdminSubstrate(uint256 user) public view returns (bool) {
+ /// @dev Not implemented
+ /// @dev EVM selector for this function is: 0xe985e9c5,
+ /// or in textual repr: isApprovedForAll(address,address)
+ function isApprovedForAll(address owner, address operator)
+ public
+ view
+ returns (address)
+ {
require(false, stub_error);
- user;
+ owner;
+ operator;
dummy;
- return false;
- }
-
- // Returns collection type
- //
- // @return `Fungible` or `NFT` or `ReFungible`
- //
- // Selector: uniqueCollectionType() d34b55b8
- function uniqueCollectionType() public returns (string memory) {
- require(false, stub_error);
- dummy = 0;
- return "";
- }
-
- // Changes collection owner to another account
- //
- // @dev Owner can be changed only by current owner
- // @param newOwner new owner account
- //
- // Selector: setOwner(address) 13af4035
- function setOwner(address newOwner) public {
- require(false, stub_error);
- newOwner;
- dummy = 0;
- }
-
- // Changes collection owner to another substrate account
- //
- // @dev Owner can be changed only by current owner
- // @param newOwner new owner substrate account
- //
- // Selector: setOwnerSubstrate(uint256) b212138f
- function setOwnerSubstrate(uint256 newOwner) public {
- require(false, stub_error);
- newOwner;
- dummy = 0;
+ return 0x0000000000000000000000000000000000000000;
}
}
pallets/refungible/src/erc.rsdiffbeforeafterboth--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -53,14 +53,14 @@
pub const ADDRESS_FOR_PARTIALLY_OWNED_TOKENS: H160 = H160::repeat_byte(0xff);
/// @title A contract that allows to set and delete token properties and change token property permissions.
-#[solidity_interface(name = "TokenProperties")]
+#[solidity_interface(name = TokenProperties)]
impl<T: Config> RefungibleHandle<T> {
/// @notice Set permissions for token property.
/// @dev Throws error if `msg.sender` is not admin or owner of the collection.
/// @param key Property key.
- /// @param is_mutable Permission to mutate property.
- /// @param collection_admin Permission to mutate property by collection admin if property is mutable.
- /// @param token_owner Permission to mutate property by token owner if property is mutable.
+ /// @param isMutable Permission to mutate property.
+ /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.
+ /// @param tokenOwner Permission to mutate property by token owner if property is mutable.
fn set_token_property_permission(
&mut self,
caller: caller,
@@ -197,7 +197,7 @@
MintingFinished {},
}
-#[solidity_interface(name = "ERC721Metadata")]
+#[solidity_interface(name = ERC721Metadata)]
impl<T: Config> RefungibleHandle<T> {
/// @notice A descriptive name for a collection of RFTs in this contract
fn name(&self) -> Result<string> {
@@ -258,7 +258,7 @@
/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
/// @dev See https://eips.ethereum.org/EIPS/eip-721
-#[solidity_interface(name = "ERC721Enumerable")]
+#[solidity_interface(name = ERC721Enumerable)]
impl<T: Config> RefungibleHandle<T> {
/// @notice Enumerate valid RFTs
/// @param index A counter less than `totalSupply()`
@@ -285,7 +285,7 @@
/// @title ERC-721 Non-Fungible Token Standard
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
-#[solidity_interface(name = "ERC721", events(ERC721Events))]
+#[solidity_interface(name = ERC721, events(ERC721Events))]
impl<T: Config> RefungibleHandle<T> {
/// @notice Count all RFTs assigned to an owner
/// @dev RFTs assigned to the zero address are considered invalid, and this
@@ -322,7 +322,6 @@
_to: address,
_token_id: uint256,
_data: bytes,
- _value: value,
) -> Result<void> {
// TODO: Not implemetable
Err("not implemented".into())
@@ -334,7 +333,6 @@
_from: address,
_to: address,
_token_id: uint256,
- _value: value,
) -> Result<void> {
// TODO: Not implemetable
Err("not implemented".into())
@@ -350,7 +348,6 @@
/// @param from The current owner of the NFT
/// @param to The new owner
/// @param tokenId The NFT to transfer
- /// @param _value Not used for an NFT
#[weight(<SelfWeightOf<T>>::transfer_from_creating_removing())]
fn transfer_from(
&mut self,
@@ -358,7 +355,6 @@
from: address,
to: address,
token_id: uint256,
- _value: value,
) -> Result<void> {
let caller = T::CrossAccountId::from_eth(caller);
let from = T::CrossAccountId::from_eth(from);
@@ -378,13 +374,7 @@
}
/// @dev Not implemented
- fn approve(
- &mut self,
- _caller: caller,
- _approved: address,
- _token_id: uint256,
- _value: value,
- ) -> Result<void> {
+ fn approve(&mut self, _caller: caller, _approved: address, _token_id: uint256) -> Result<void> {
Err("not implemented".into())
}
@@ -438,7 +428,7 @@
}
/// @title ERC721 Token that can be irreversibly burned (destroyed).
-#[solidity_interface(name = "ERC721Burnable")]
+#[solidity_interface(name = ERC721Burnable)]
impl<T: Config> RefungibleHandle<T> {
/// @notice Burns a specific ERC721 token.
/// @dev Throws unless `msg.sender` is the current RFT owner, or an authorized
@@ -458,7 +448,7 @@
}
/// @title ERC721 minting logic.
-#[solidity_interface(name = "ERC721Mintable", events(ERC721MintableEvents))]
+#[solidity_interface(name = ERC721Mintable, events(ERC721MintableEvents))]
impl<T: Config> RefungibleHandle<T> {
fn minting_finished(&self) -> Result<bool> {
Ok(false)
@@ -616,7 +606,7 @@
}
/// @title Unique extensions for ERC721.
-#[solidity_interface(name = "ERC721UniqueExtensions")]
+#[solidity_interface(name = ERC721UniqueExtensions)]
impl<T: Config> RefungibleHandle<T> {
/// @notice Transfer ownership of an RFT
/// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
@@ -624,15 +614,8 @@
/// Throws if RFT pieces have multiple owners.
/// @param to The new owner
/// @param tokenId The RFT to transfer
- /// @param _value Not used for an RFT
#[weight(<SelfWeightOf<T>>::transfer_creating_removing())]
- fn transfer(
- &mut self,
- caller: caller,
- to: address,
- token_id: uint256,
- _value: value,
- ) -> Result<void> {
+ fn transfer(&mut self, caller: caller, to: address, token_id: uint256) -> Result<void> {
let caller = T::CrossAccountId::from_eth(caller);
let to = T::CrossAccountId::from_eth(to);
let token = token_id.try_into()?;
@@ -655,15 +638,8 @@
/// Throws if RFT pieces have multiple owners.
/// @param from The current owner of the RFT
/// @param tokenId The RFT to transfer
- /// @param _value Not used for an RFT
#[weight(<SelfWeightOf<T>>::burn_from())]
- fn burn_from(
- &mut self,
- caller: caller,
- from: address,
- token_id: uint256,
- _value: value,
- ) -> Result<void> {
+ fn burn_from(&mut self, caller: caller, from: address, token_id: uint256) -> Result<void> {
let caller = T::CrossAccountId::from_eth(caller);
let from = T::CrossAccountId::from_eth(from);
let token = token_id.try_into()?;
@@ -801,7 +777,7 @@
}
#[solidity_interface(
- name = "UniqueRefungible",
+ name = UniqueRefungible,
is(
ERC721,
ERC721Metadata,
@@ -809,7 +785,7 @@
ERC721UniqueExtensions,
ERC721Mintable,
ERC721Burnable,
- via("CollectionHandle<T>", common_mut, Collection),
+ Collection(common_mut, CollectionHandle<T>),
TokenProperties,
)
)]
pallets/refungible/src/erc_token.rsdiffbeforeafterboth--- a/pallets/refungible/src/erc_token.rs
+++ b/pallets/refungible/src/erc_token.rs
@@ -49,7 +49,7 @@
pub struct RefungibleTokenHandle<T: Config>(pub RefungibleHandle<T>, pub TokenId);
-#[solidity_interface(name = "ERC1633")]
+#[solidity_interface(name = ERC1633)]
impl<T: Config> RefungibleTokenHandle<T> {
fn parent_token(&self) -> Result<address> {
self.consume_store_reads(2)?;
@@ -87,7 +87,7 @@
}
}
-#[solidity_interface(name = "ERC1633UniqueExtensions")]
+#[solidity_interface(name = ERC1633UniqueExtensions)]
impl<T: Config> RefungibleTokenHandle<T> {
#[solidity(rename_selector = "setParentNFT")]
#[weight(<CommonWeights<T>>::token_owner() + <SelfWeightOf<T>>::set_parent_nft_unchecked())]
@@ -137,7 +137,7 @@
///
/// @dev Implementation of the basic standard token.
/// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
-#[solidity_interface(name = "ERC20", events(ERC20Events))]
+#[solidity_interface(name = ERC20, events(ERC20Events))]
impl<T: Config> RefungibleTokenHandle<T> {
/// @return the name of the token.
fn name(&self) -> Result<string> {
@@ -246,7 +246,7 @@
}
}
-#[solidity_interface(name = "ERC20UniqueExtensions")]
+#[solidity_interface(name = ERC20UniqueExtensions)]
impl<T: Config> RefungibleTokenHandle<T> {
/// @dev Function that burns an amount of the token of a given account,
/// deducting from the sender's allowance for said account.
@@ -306,7 +306,7 @@
}
#[solidity_interface(
- name = "UniqueRefungibleToken",
+ name = UniqueRefungibleToken,
is(ERC20, ERC20UniqueExtensions, ERC1633, ERC1633UniqueExtensions)
)]
impl<T: Config> RefungibleTokenHandle<T> where T::AccountId: From<[u8; 32]> {}
pallets/refungible/src/stubs/UniqueRefungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth--- a/pallets/refungible/src/stubs/UniqueRefungible.sol
+++ b/pallets/refungible/src/stubs/UniqueRefungible.sol
@@ -3,13 +3,7 @@
pragma solidity >=0.8.0 <0.9.0;
-// Anonymous struct
-struct Tuple0 {
- uint256 field_0;
- string field_1;
-}
-
-// Common stubs holder
+/// @dev common stubs holder
contract Dummy {
uint8 dummy;
string stub_error = "this contract is implemented in native";
@@ -27,40 +21,17 @@
}
}
-// Inline
-contract ERC721Events {
- event Transfer(
- address indexed from,
- address indexed to,
- uint256 indexed tokenId
- );
- event Approval(
- address indexed owner,
- address indexed approved,
- uint256 indexed tokenId
- );
- event ApprovalForAll(
- address indexed owner,
- address indexed operator,
- bool approved
- );
-}
-
-// Inline
-contract ERC721MintableEvents {
- event MintingFinished();
-}
-
-// Selector: 41369377
+/// @title A contract that allows to set and delete token properties and change token property permissions.
+/// @dev the ERC-165 identifier for this interface is 0x41369377
contract TokenProperties is Dummy, ERC165 {
- // @notice Set permissions for token property.
- // @dev Throws error if `msg.sender` is not admin or owner of the collection.
- // @param key Property key.
- // @param is_mutable Permission to mutate property.
- // @param collection_admin Permission to mutate property by collection admin if property is mutable.
- // @param token_owner Permission to mutate property by token owner if property is mutable.
- //
- // Selector: setTokenPropertyPermission(string,bool,bool,bool) 222d97fa
+ /// @notice Set permissions for token property.
+ /// @dev Throws error if `msg.sender` is not admin or owner of the collection.
+ /// @param key Property key.
+ /// @param isMutable Permission to mutate property.
+ /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.
+ /// @param tokenOwner Permission to mutate property by token owner if property is mutable.
+ /// @dev EVM selector for this function is: 0x222d97fa,
+ /// or in textual repr: setTokenPropertyPermission(string,bool,bool,bool)
function setTokenPropertyPermission(
string memory key,
bool isMutable,
@@ -75,13 +46,13 @@
dummy = 0;
}
- // @notice Set token property value.
- // @dev Throws error if `msg.sender` has no permission to edit the property.
- // @param tokenId ID of the token.
- // @param key Property key.
- // @param value Property value.
- //
- // Selector: setProperty(uint256,string,bytes) 1752d67b
+ /// @notice Set token property value.
+ /// @dev Throws error if `msg.sender` has no permission to edit the property.
+ /// @param tokenId ID of the token.
+ /// @param key Property key.
+ /// @param value Property value.
+ /// @dev EVM selector for this function is: 0x1752d67b,
+ /// or in textual repr: setProperty(uint256,string,bytes)
function setProperty(
uint256 tokenId,
string memory key,
@@ -94,12 +65,12 @@
dummy = 0;
}
- // @notice Delete token property value.
- // @dev Throws error if `msg.sender` has no permission to edit the property.
- // @param tokenId ID of the token.
- // @param key Property key.
- //
- // Selector: deleteProperty(uint256,string) 066111d1
+ /// @notice Delete token property value.
+ /// @dev Throws error if `msg.sender` has no permission to edit the property.
+ /// @param tokenId ID of the token.
+ /// @param key Property key.
+ /// @dev EVM selector for this function is: 0x066111d1,
+ /// or in textual repr: deleteProperty(uint256,string)
function deleteProperty(uint256 tokenId, string memory key) public {
require(false, stub_error);
tokenId;
@@ -107,13 +78,13 @@
dummy = 0;
}
- // @notice Get token property value.
- // @dev Throws error if key not found
- // @param tokenId ID of the token.
- // @param key Property key.
- // @return Property value bytes
- //
- // Selector: property(uint256,string) 7228c327
+ /// @notice Get token property value.
+ /// @dev Throws error if key not found
+ /// @param tokenId ID of the token.
+ /// @param key Property key.
+ /// @return Property value bytes
+ /// @dev EVM selector for this function is: 0x7228c327,
+ /// or in textual repr: property(uint256,string)
function property(uint256 tokenId, string memory key)
public
view
@@ -127,211 +98,334 @@
}
}
-// Selector: 42966c68
-contract ERC721Burnable is Dummy, ERC165 {
- // @notice Burns a specific ERC721 token.
- // @dev Throws unless `msg.sender` is the current RFT owner, or an authorized
- // operator of the current owner.
- // @param tokenId The RFT to approve
- //
- // Selector: burn(uint256) 42966c68
- function burn(uint256 tokenId) public {
+/// @title A contract that allows you to work with collections.
+/// @dev the ERC-165 identifier for this interface is 0xffe4da23
+contract Collection is Dummy, ERC165 {
+ /// Set collection property.
+ ///
+ /// @param key Property key.
+ /// @param value Propery value.
+ /// @dev EVM selector for this function is: 0x2f073f66,
+ /// or in textual repr: setCollectionProperty(string,bytes)
+ function setCollectionProperty(string memory key, bytes memory value)
+ public
+ {
require(false, stub_error);
- tokenId;
+ key;
+ value;
dummy = 0;
}
-}
-// Selector: 58800161
-contract ERC721 is Dummy, ERC165, ERC721Events {
- // @notice Count all RFTs assigned to an owner
- // @dev RFTs assigned to the zero address are considered invalid, and this
- // function throws for queries about the zero address.
- // @param owner An address for whom to query the balance
- // @return The number of RFTs owned by `owner`, possibly zero
- //
- // Selector: balanceOf(address) 70a08231
- function balanceOf(address owner) public view returns (uint256) {
+ /// Delete collection property.
+ ///
+ /// @param key Property key.
+ /// @dev EVM selector for this function is: 0x7b7debce,
+ /// or in textual repr: deleteCollectionProperty(string)
+ function deleteCollectionProperty(string memory key) public {
require(false, stub_error);
- owner;
- dummy;
- return 0;
+ key;
+ dummy = 0;
}
- // @notice Find the owner of an RFT
- // @dev RFTs assigned to zero address are considered invalid, and queries
- // about them do throw.
- // Returns special 0xffffffffffffffffffffffffffffffffffffffff address for
- // the tokens that are partially owned.
- // @param tokenId The identifier for an RFT
- // @return The address of the owner of the RFT
- //
- // Selector: ownerOf(uint256) 6352211e
- function ownerOf(uint256 tokenId) public view returns (address) {
+ /// Get collection property.
+ ///
+ /// @dev Throws error if key not found.
+ ///
+ /// @param key Property key.
+ /// @return bytes The property corresponding to the key.
+ /// @dev EVM selector for this function is: 0xcf24fd6d,
+ /// or in textual repr: collectionProperty(string)
+ function collectionProperty(string memory key)
+ public
+ view
+ returns (bytes memory)
+ {
require(false, stub_error);
- tokenId;
+ key;
dummy;
- return 0x0000000000000000000000000000000000000000;
+ return hex"";
}
- // @dev Not implemented
- //
- // Selector: safeTransferFromWithData(address,address,uint256,bytes) 60a11672
- function safeTransferFromWithData(
- address from,
- address to,
- uint256 tokenId,
- bytes memory data
- ) public {
+ /// Set the sponsor of the collection.
+ ///
+ /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.
+ ///
+ /// @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.
+ /// @dev EVM selector for this function is: 0x7623402e,
+ /// or in textual repr: setCollectionSponsor(address)
+ function setCollectionSponsor(address sponsor) public {
require(false, stub_error);
- from;
- to;
- tokenId;
- data;
+ sponsor;
dummy = 0;
}
- // @dev Not implemented
- //
- // Selector: safeTransferFrom(address,address,uint256) 42842e0e
- function safeTransferFrom(
- address from,
- address to,
- uint256 tokenId
- ) public {
+ /// Collection sponsorship confirmation.
+ ///
+ /// @dev After setting the sponsor for the collection, it must be confirmed with this function.
+ /// @dev EVM selector for this function is: 0x3c50e97a,
+ /// or in textual repr: confirmCollectionSponsorship()
+ function confirmCollectionSponsorship() public {
require(false, stub_error);
- from;
- to;
- tokenId;
dummy = 0;
}
- // @notice Transfer ownership of an RFT -- THE CALLER IS RESPONSIBLE
- // TO CONFIRM THAT `to` IS CAPABLE OF RECEIVING NFTS OR ELSE
- // THEY MAY BE PERMANENTLY LOST
- // @dev Throws unless `msg.sender` is the current owner or an authorized
- // operator for this RFT. Throws if `from` is not the current owner. Throws
- // if `to` is the zero address. Throws if `tokenId` is not a valid RFT.
- // Throws if RFT pieces have multiple owners.
- // @param from The current owner of the NFT
- // @param to The new owner
- // @param tokenId The NFT to transfer
- // @param _value Not used for an NFT
- //
- // Selector: transferFrom(address,address,uint256) 23b872dd
- function transferFrom(
- address from,
- address to,
- uint256 tokenId
- ) public {
+ /// Set limits for the collection.
+ /// @dev Throws error if limit not found.
+ /// @param limit Name of the limit. Valid names:
+ /// "accountTokenOwnershipLimit",
+ /// "sponsoredDataSize",
+ /// "sponsoredDataRateLimit",
+ /// "tokenLimit",
+ /// "sponsorTransferTimeout",
+ /// "sponsorApproveTimeout"
+ /// @param value Value of the limit.
+ /// @dev EVM selector for this function is: 0x6a3841db,
+ /// or in textual repr: setCollectionLimit(string,uint32)
+ function setCollectionLimit(string memory limit, uint32 value) public {
require(false, stub_error);
- from;
- to;
- tokenId;
+ limit;
+ value;
dummy = 0;
}
- // @dev Not implemented
- //
- // Selector: approve(address,uint256) 095ea7b3
- function approve(address approved, uint256 tokenId) public {
+ /// Set limits for the collection.
+ /// @dev Throws error if limit not found.
+ /// @param limit Name of the limit. Valid names:
+ /// "ownerCanTransfer",
+ /// "ownerCanDestroy",
+ /// "transfersEnabled"
+ /// @param value Value of the limit.
+ /// @dev EVM selector for this function is: 0x993b7fba,
+ /// or in textual repr: setCollectionLimit(string,bool)
+ function setCollectionLimit(string memory limit, bool value) public {
require(false, stub_error);
- approved;
- tokenId;
+ limit;
+ value;
dummy = 0;
}
- // @dev Not implemented
- //
- // Selector: setApprovalForAll(address,bool) a22cb465
- function setApprovalForAll(address operator, bool approved) public {
+ /// Get contract address.
+ /// @dev EVM selector for this function is: 0xf6b4dfb4,
+ /// or in textual repr: contractAddress()
+ function contractAddress() public view returns (address) {
require(false, stub_error);
- operator;
- approved;
+ dummy;
+ return 0x0000000000000000000000000000000000000000;
+ }
+
+ /// Add collection admin by substrate address.
+ /// @param newAdmin Substrate administrator address.
+ /// @dev EVM selector for this function is: 0x5730062b,
+ /// or in textual repr: addCollectionAdminSubstrate(uint256)
+ function addCollectionAdminSubstrate(uint256 newAdmin) public {
+ require(false, stub_error);
+ newAdmin;
dummy = 0;
}
- // @dev Not implemented
- //
- // Selector: getApproved(uint256) 081812fc
- function getApproved(uint256 tokenId) public view returns (address) {
+ /// Remove collection admin by substrate address.
+ /// @param admin Substrate administrator address.
+ /// @dev EVM selector for this function is: 0x4048fcf9,
+ /// or in textual repr: removeCollectionAdminSubstrate(uint256)
+ function removeCollectionAdminSubstrate(uint256 admin) public {
require(false, stub_error);
- tokenId;
- dummy;
- return 0x0000000000000000000000000000000000000000;
+ admin;
+ dummy = 0;
}
- // @dev Not implemented
- //
- // Selector: isApprovedForAll(address,address) e985e9c5
- function isApprovedForAll(address owner, address operator)
+ /// Add collection admin.
+ /// @param newAdmin Address of the added administrator.
+ /// @dev EVM selector for this function is: 0x92e462c7,
+ /// or in textual repr: addCollectionAdmin(address)
+ function addCollectionAdmin(address newAdmin) public {
+ require(false, stub_error);
+ newAdmin;
+ dummy = 0;
+ }
+
+ /// Remove collection admin.
+ ///
+ /// @param admin Address of the removed administrator.
+ /// @dev EVM selector for this function is: 0xfafd7b42,
+ /// or in textual repr: removeCollectionAdmin(address)
+ function removeCollectionAdmin(address admin) public {
+ require(false, stub_error);
+ admin;
+ dummy = 0;
+ }
+
+ /// Toggle accessibility of collection nesting.
+ ///
+ /// @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'
+ /// @dev EVM selector for this function is: 0x112d4586,
+ /// or in textual repr: setCollectionNesting(bool)
+ function setCollectionNesting(bool enable) public {
+ require(false, stub_error);
+ enable;
+ dummy = 0;
+ }
+
+ /// Toggle accessibility of collection nesting.
+ ///
+ /// @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'
+ /// @param collections Addresses of collections that will be available for nesting.
+ /// @dev EVM selector for this function is: 0x64872396,
+ /// or in textual repr: setCollectionNesting(bool,address[])
+ function setCollectionNesting(bool enable, address[] memory collections)
public
- view
- returns (address)
{
require(false, stub_error);
- owner;
- operator;
+ enable;
+ collections;
+ dummy = 0;
+ }
+
+ /// Set the collection access method.
+ /// @param mode Access mode
+ /// 0 for Normal
+ /// 1 for AllowList
+ /// @dev EVM selector for this function is: 0x41835d4c,
+ /// or in textual repr: setCollectionAccess(uint8)
+ function setCollectionAccess(uint8 mode) public {
+ require(false, stub_error);
+ mode;
+ dummy = 0;
+ }
+
+ /// Add the user to the allowed list.
+ ///
+ /// @param user Address of a trusted user.
+ /// @dev EVM selector for this function is: 0x67844fe6,
+ /// or in textual repr: addToCollectionAllowList(address)
+ function addToCollectionAllowList(address user) public {
+ require(false, stub_error);
+ user;
+ dummy = 0;
+ }
+
+ /// Remove the user from the allowed list.
+ ///
+ /// @param user Address of a removed user.
+ /// @dev EVM selector for this function is: 0x85c51acb,
+ /// or in textual repr: removeFromCollectionAllowList(address)
+ function removeFromCollectionAllowList(address user) public {
+ require(false, stub_error);
+ user;
+ dummy = 0;
+ }
+
+ /// Switch permission for minting.
+ ///
+ /// @param mode Enable if "true".
+ /// @dev EVM selector for this function is: 0x00018e84,
+ /// or in textual repr: setCollectionMintMode(bool)
+ function setCollectionMintMode(bool mode) public {
+ require(false, stub_error);
+ mode;
+ dummy = 0;
+ }
+
+ /// Check that account is the owner or admin of the collection
+ ///
+ /// @param user account to verify
+ /// @return "true" if account is the owner or admin
+ /// @dev EVM selector for this function is: 0x9811b0c7,
+ /// or in textual repr: isOwnerOrAdmin(address)
+ function isOwnerOrAdmin(address user) public view returns (bool) {
+ require(false, stub_error);
+ user;
dummy;
- return 0x0000000000000000000000000000000000000000;
+ return false;
}
-}
-// Selector: 5b5e139f
-contract ERC721Metadata is Dummy, ERC165 {
- // @notice A descriptive name for a collection of RFTs in this contract
- //
- // Selector: name() 06fdde03
- function name() public view returns (string memory) {
+ /// Check that substrate account is the owner or admin of the collection
+ ///
+ /// @param user account to verify
+ /// @return "true" if account is the owner or admin
+ /// @dev EVM selector for this function is: 0x68910e00,
+ /// or in textual repr: isOwnerOrAdminSubstrate(uint256)
+ function isOwnerOrAdminSubstrate(uint256 user) public view returns (bool) {
require(false, stub_error);
+ user;
dummy;
- return "";
+ return false;
}
- // @notice An abbreviated name for RFTs in this contract
- //
- // Selector: symbol() 95d89b41
- function symbol() public view returns (string memory) {
+ /// Returns collection type
+ ///
+ /// @return `Fungible` or `NFT` or `ReFungible`
+ /// @dev EVM selector for this function is: 0xd34b55b8,
+ /// or in textual repr: uniqueCollectionType()
+ function uniqueCollectionType() public returns (string memory) {
require(false, stub_error);
- dummy;
+ dummy = 0;
return "";
}
- // @notice A distinct Uniform Resource Identifier (URI) for a given asset.
- //
- // @dev If the token has a `url` property and it is not empty, it is returned.
- // Else If the collection does not have a property with key `schemaName` or its value is not equal to `ERC721Metadata`, it return an error `tokenURI not set`.
- // If the collection property `baseURI` is empty or absent, return "" (empty string)
- // otherwise, if token property `suffix` present and is non-empty, return concatenation of baseURI and suffix
- // otherwise, return concatenation of `baseURI` and stringified token id (decimal stringifying, without paddings).
- //
- // @return token's const_metadata
- //
- // Selector: tokenURI(uint256) c87b56dd
- function tokenURI(uint256 tokenId) public view returns (string memory) {
+ /// Changes collection owner to another account
+ ///
+ /// @dev Owner can be changed only by current owner
+ /// @param newOwner new owner account
+ /// @dev EVM selector for this function is: 0x13af4035,
+ /// or in textual repr: setOwner(address)
+ function setOwner(address newOwner) public {
require(false, stub_error);
+ newOwner;
+ dummy = 0;
+ }
+
+ /// Changes collection owner to another substrate account
+ ///
+ /// @dev Owner can be changed only by current owner
+ /// @param newOwner new owner substrate account
+ /// @dev EVM selector for this function is: 0xb212138f,
+ /// or in textual repr: setOwnerSubstrate(uint256)
+ function setOwnerSubstrate(uint256 newOwner) public {
+ require(false, stub_error);
+ newOwner;
+ dummy = 0;
+ }
+}
+
+/// @title ERC721 Token that can be irreversibly burned (destroyed).
+/// @dev the ERC-165 identifier for this interface is 0x42966c68
+contract ERC721Burnable is Dummy, ERC165 {
+ /// @notice Burns a specific ERC721 token.
+ /// @dev Throws unless `msg.sender` is the current RFT owner, or an authorized
+ /// operator of the current owner.
+ /// @param tokenId The RFT to approve
+ /// @dev EVM selector for this function is: 0x42966c68,
+ /// or in textual repr: burn(uint256)
+ function burn(uint256 tokenId) public {
+ require(false, stub_error);
tokenId;
- dummy;
- return "";
+ dummy = 0;
}
}
-// Selector: 68ccfe89
+/// @dev inlined interface
+contract ERC721MintableEvents {
+ event MintingFinished();
+}
+
+/// @title ERC721 minting logic.
+/// @dev the ERC-165 identifier for this interface is 0x68ccfe89
contract ERC721Mintable is Dummy, ERC165, ERC721MintableEvents {
- // Selector: mintingFinished() 05d2035b
+ /// @dev EVM selector for this function is: 0x05d2035b,
+ /// or in textual repr: mintingFinished()
function mintingFinished() public view returns (bool) {
require(false, stub_error);
dummy;
return false;
}
- // @notice Function to mint token.
- // @dev `tokenId` should be obtained with `nextTokenId` method,
- // unlike standard, you can't specify it manually
- // @param to The new owner
- // @param tokenId ID of the minted RFT
- //
- // Selector: mint(address,uint256) 40c10f19
+ /// @notice Function to mint token.
+ /// @dev `tokenId` should be obtained with `nextTokenId` method,
+ /// unlike standard, you can't specify it manually
+ /// @param to The new owner
+ /// @param tokenId ID of the minted RFT
+ /// @dev EVM selector for this function is: 0x40c10f19,
+ /// or in textual repr: mint(address,uint256)
function mint(address to, uint256 tokenId) public returns (bool) {
require(false, stub_error);
to;
@@ -340,14 +434,14 @@
return false;
}
- // @notice Function to mint token with the given tokenUri.
- // @dev `tokenId` should be obtained with `nextTokenId` method,
- // unlike standard, you can't specify it manually
- // @param to The new owner
- // @param tokenId ID of the minted RFT
- // @param tokenUri Token URI that would be stored in the RFT properties
- //
- // Selector: mintWithTokenURI(address,uint256,string) 50bb4e7f
+ /// @notice Function to mint token with the given tokenUri.
+ /// @dev `tokenId` should be obtained with `nextTokenId` method,
+ /// unlike standard, you can't specify it manually
+ /// @param to The new owner
+ /// @param tokenId ID of the minted RFT
+ /// @param tokenUri Token URI that would be stored in the RFT properties
+ /// @dev EVM selector for this function is: 0x50bb4e7f,
+ /// or in textual repr: mintWithTokenURI(address,uint256,string)
function mintWithTokenURI(
address to,
uint256 tokenId,
@@ -361,9 +455,9 @@
return false;
}
- // @dev Not implemented
- //
- // Selector: finishMinting() 7d64bcb4
+ /// @dev Not implemented
+ /// @dev EVM selector for this function is: 0x7d64bcb4,
+ /// or in textual repr: finishMinting()
function finishMinting() public returns (bool) {
require(false, stub_error);
dummy = 0;
@@ -371,59 +465,17 @@
}
}
-// Selector: 780e9d63
-contract ERC721Enumerable is Dummy, ERC165 {
- // @notice Enumerate valid RFTs
- // @param index A counter less than `totalSupply()`
- // @return The token identifier for the `index`th NFT,
- // (sort order not specified)
- //
- // Selector: tokenByIndex(uint256) 4f6ccce7
- function tokenByIndex(uint256 index) public view returns (uint256) {
- require(false, stub_error);
- index;
- dummy;
- return 0;
- }
-
- // Not implemented
- //
- // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59
- function tokenOfOwnerByIndex(address owner, uint256 index)
- public
- view
- returns (uint256)
- {
- require(false, stub_error);
- owner;
- index;
- dummy;
- return 0;
- }
-
- // @notice Count RFTs tracked by this contract
- // @return A count of valid RFTs tracked by this contract, where each one of
- // them has an assigned and queryable owner not equal to the zero address
- //
- // Selector: totalSupply() 18160ddd
- function totalSupply() public view returns (uint256) {
- require(false, stub_error);
- dummy;
- return 0;
- }
-}
-
-// Selector: 7c3bef89
+/// @title Unique extensions for ERC721.
+/// @dev the ERC-165 identifier for this interface is 0x7c3bef89
contract ERC721UniqueExtensions is Dummy, ERC165 {
- // @notice Transfer ownership of an RFT
- // @dev Throws unless `msg.sender` is the current owner. Throws if `to`
- // is the zero address. Throws if `tokenId` is not a valid RFT.
- // Throws if RFT pieces have multiple owners.
- // @param to The new owner
- // @param tokenId The RFT to transfer
- // @param _value Not used for an RFT
- //
- // Selector: transfer(address,uint256) a9059cbb
+ /// @notice Transfer ownership of an RFT
+ /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
+ /// is the zero address. Throws if `tokenId` is not a valid RFT.
+ /// Throws if RFT pieces have multiple owners.
+ /// @param to The new owner
+ /// @param tokenId The RFT to transfer
+ /// @dev EVM selector for this function is: 0xa9059cbb,
+ /// or in textual repr: transfer(address,uint256)
function transfer(address to, uint256 tokenId) public {
require(false, stub_error);
to;
@@ -431,16 +483,15 @@
dummy = 0;
}
- // @notice Burns a specific ERC721 token.
- // @dev Throws unless `msg.sender` is the current owner or an authorized
- // operator for this RFT. Throws if `from` is not the current owner. Throws
- // if `to` is the zero address. Throws if `tokenId` is not a valid RFT.
- // Throws if RFT pieces have multiple owners.
- // @param from The current owner of the RFT
- // @param tokenId The RFT to transfer
- // @param _value Not used for an RFT
- //
- // Selector: burnFrom(address,uint256) 79cc6790
+ /// @notice Burns a specific ERC721 token.
+ /// @dev Throws unless `msg.sender` is the current owner or an authorized
+ /// operator for this RFT. Throws if `from` is not the current owner. Throws
+ /// if `to` is the zero address. Throws if `tokenId` is not a valid RFT.
+ /// Throws if RFT pieces have multiple owners.
+ /// @param from The current owner of the RFT
+ /// @param tokenId The RFT to transfer
+ /// @dev EVM selector for this function is: 0x79cc6790,
+ /// or in textual repr: burnFrom(address,uint256)
function burnFrom(address from, uint256 tokenId) public {
require(false, stub_error);
from;
@@ -448,22 +499,22 @@
dummy = 0;
}
- // @notice Returns next free RFT ID.
- //
- // Selector: nextTokenId() 75794a3c
+ /// @notice Returns next free RFT ID.
+ /// @dev EVM selector for this function is: 0x75794a3c,
+ /// or in textual repr: nextTokenId()
function nextTokenId() public view returns (uint256) {
require(false, stub_error);
dummy;
return 0;
}
- // @notice Function to mint multiple tokens.
- // @dev `tokenIds` should be an array of consecutive numbers and first number
- // should be obtained with `nextTokenId` method
- // @param to The new owner
- // @param tokenIds IDs of the minted RFTs
- //
- // Selector: mintBulk(address,uint256[]) 44a9945e
+ /// @notice Function to mint multiple tokens.
+ /// @dev `tokenIds` should be an array of consecutive numbers and first number
+ /// should be obtained with `nextTokenId` method
+ /// @param to The new owner
+ /// @param tokenIds IDs of the minted RFTs
+ /// @dev EVM selector for this function is: 0x44a9945e,
+ /// or in textual repr: mintBulk(address,uint256[])
function mintBulk(address to, uint256[] memory tokenIds)
public
returns (bool)
@@ -475,14 +526,14 @@
return false;
}
- // @notice Function to mint multiple tokens with the given tokenUris.
- // @dev `tokenIds` is array of pairs of token ID and token URI. Token IDs should be consecutive
- // numbers and first number should be obtained with `nextTokenId` method
- // @param to The new owner
- // @param tokens array of pairs of token ID and token URI for minted tokens
- //
- // Selector: mintBulkWithTokenURI(address,(uint256,string)[]) 36543006
- function mintBulkWithTokenURI(address to, Tuple0[] memory tokens)
+ /// @notice Function to mint multiple tokens with the given tokenUris.
+ /// @dev `tokenIds` is array of pairs of token ID and token URI. Token IDs should be consecutive
+ /// numbers and first number should be obtained with `nextTokenId` method
+ /// @param to The new owner
+ /// @param tokens array of pairs of token ID and token URI for minted tokens
+ /// @dev EVM selector for this function is: 0x36543006,
+ /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])
+ function mintBulkWithTokenURI(address to, Tuple8[] memory tokens)
public
returns (bool)
{
@@ -493,11 +544,11 @@
return false;
}
- // Returns EVM address for refungible token
- //
- // @param token ID of the token
- //
- // Selector: tokenContractAddress(uint256) ab76fac6
+ /// Returns EVM address for refungible token
+ ///
+ /// @param token ID of the token
+ /// @dev EVM selector for this function is: 0xab76fac6,
+ /// or in textual repr: tokenContractAddress(uint256)
function tokenContractAddress(uint256 token) public view returns (address) {
require(false, stub_error);
token;
@@ -506,291 +557,247 @@
}
}
-// Selector: ffe4da23
-contract Collection is Dummy, ERC165 {
- // Set collection property.
- //
- // @param key Property key.
- // @param value Propery value.
- //
- // Selector: setCollectionProperty(string,bytes) 2f073f66
- function setCollectionProperty(string memory key, bytes memory value)
- public
- {
- require(false, stub_error);
- key;
- value;
- dummy = 0;
- }
+/// @dev anonymous struct
+struct Tuple8 {
+ uint256 field_0;
+ string field_1;
+}
- // Delete collection property.
- //
- // @param key Property key.
- //
- // Selector: deleteCollectionProperty(string) 7b7debce
- function deleteCollectionProperty(string memory key) public {
+/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
+/// @dev See https://eips.ethereum.org/EIPS/eip-721
+/// @dev the ERC-165 identifier for this interface is 0x780e9d63
+contract ERC721Enumerable is Dummy, ERC165 {
+ /// @notice Enumerate valid RFTs
+ /// @param index A counter less than `totalSupply()`
+ /// @return The token identifier for the `index`th NFT,
+ /// (sort order not specified)
+ /// @dev EVM selector for this function is: 0x4f6ccce7,
+ /// or in textual repr: tokenByIndex(uint256)
+ function tokenByIndex(uint256 index) public view returns (uint256) {
require(false, stub_error);
- key;
- dummy = 0;
+ index;
+ dummy;
+ return 0;
}
- // Get collection property.
- //
- // @dev Throws error if key not found.
- //
- // @param key Property key.
- // @return bytes The property corresponding to the key.
- //
- // Selector: collectionProperty(string) cf24fd6d
- function collectionProperty(string memory key)
+ /// Not implemented
+ /// @dev EVM selector for this function is: 0x2f745c59,
+ /// or in textual repr: tokenOfOwnerByIndex(address,uint256)
+ function tokenOfOwnerByIndex(address owner, uint256 index)
public
view
- returns (bytes memory)
+ returns (uint256)
{
require(false, stub_error);
- key;
+ owner;
+ index;
dummy;
- return hex"";
+ return 0;
}
- // Set the sponsor of the collection.
- //
- // @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.
- //
- // @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.
- //
- // Selector: setCollectionSponsor(address) 7623402e
- function setCollectionSponsor(address sponsor) public {
+ /// @notice Count RFTs tracked by this contract
+ /// @return A count of valid RFTs tracked by this contract, where each one of
+ /// them has an assigned and queryable owner not equal to the zero address
+ /// @dev EVM selector for this function is: 0x18160ddd,
+ /// or in textual repr: totalSupply()
+ function totalSupply() public view returns (uint256) {
require(false, stub_error);
- sponsor;
- dummy = 0;
+ dummy;
+ return 0;
}
+}
- // Collection sponsorship confirmation.
- //
- // @dev After setting the sponsor for the collection, it must be confirmed with this function.
- //
- // Selector: confirmCollectionSponsorship() 3c50e97a
- function confirmCollectionSponsorship() public {
+/// @dev the ERC-165 identifier for this interface is 0x5b5e139f
+contract ERC721Metadata is Dummy, ERC165 {
+ /// @notice A descriptive name for a collection of RFTs in this contract
+ /// @dev EVM selector for this function is: 0x06fdde03,
+ /// or in textual repr: name()
+ function name() public view returns (string memory) {
require(false, stub_error);
- dummy = 0;
+ dummy;
+ return "";
}
- // Set limits for the collection.
- // @dev Throws error if limit not found.
- // @param limit Name of the limit. Valid names:
- // "accountTokenOwnershipLimit",
- // "sponsoredDataSize",
- // "sponsoredDataRateLimit",
- // "tokenLimit",
- // "sponsorTransferTimeout",
- // "sponsorApproveTimeout"
- // @param value Value of the limit.
- //
- // Selector: setCollectionLimit(string,uint32) 6a3841db
- function setCollectionLimit(string memory limit, uint32 value) public {
+ /// @notice An abbreviated name for RFTs in this contract
+ /// @dev EVM selector for this function is: 0x95d89b41,
+ /// or in textual repr: symbol()
+ function symbol() public view returns (string memory) {
require(false, stub_error);
- limit;
- value;
- dummy = 0;
+ dummy;
+ return "";
}
- // Set limits for the collection.
- // @dev Throws error if limit not found.
- // @param limit Name of the limit. Valid names:
- // "ownerCanTransfer",
- // "ownerCanDestroy",
- // "transfersEnabled"
- // @param value Value of the limit.
- //
- // Selector: setCollectionLimit(string,bool) 993b7fba
- function setCollectionLimit(string memory limit, bool value) public {
+ /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
+ ///
+ /// @dev If the token has a `url` property and it is not empty, it is returned.
+ /// Else If the collection does not have a property with key `schemaName` or its value is not equal to `ERC721Metadata`, it return an error `tokenURI not set`.
+ /// If the collection property `baseURI` is empty or absent, return "" (empty string)
+ /// otherwise, if token property `suffix` present and is non-empty, return concatenation of baseURI and suffix
+ /// otherwise, return concatenation of `baseURI` and stringified token id (decimal stringifying, without paddings).
+ ///
+ /// @return token's const_metadata
+ /// @dev EVM selector for this function is: 0xc87b56dd,
+ /// or in textual repr: tokenURI(uint256)
+ function tokenURI(uint256 tokenId) public view returns (string memory) {
require(false, stub_error);
- limit;
- value;
- dummy = 0;
- }
-
- // Get contract address.
- //
- // Selector: contractAddress() f6b4dfb4
- function contractAddress() public view returns (address) {
- require(false, stub_error);
+ tokenId;
dummy;
- return 0x0000000000000000000000000000000000000000;
+ return "";
}
+}
- // Add collection admin by substrate address.
- // @param new_admin Substrate administrator address.
- //
- // Selector: addCollectionAdminSubstrate(uint256) 5730062b
- function addCollectionAdminSubstrate(uint256 newAdmin) public {
- require(false, stub_error);
- newAdmin;
- dummy = 0;
- }
+/// @dev inlined interface
+contract ERC721Events {
+ event Transfer(
+ address indexed from,
+ address indexed to,
+ uint256 indexed tokenId
+ );
+ event Approval(
+ address indexed owner,
+ address indexed approved,
+ uint256 indexed tokenId
+ );
+ event ApprovalForAll(
+ address indexed owner,
+ address indexed operator,
+ bool approved
+ );
+}
- // Remove collection admin by substrate address.
- // @param admin Substrate administrator address.
- //
- // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9
- function removeCollectionAdminSubstrate(uint256 admin) public {
+/// @title ERC-721 Non-Fungible Token Standard
+/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
+/// @dev the ERC-165 identifier for this interface is 0x58800161
+contract ERC721 is Dummy, ERC165, ERC721Events {
+ /// @notice Count all RFTs assigned to an owner
+ /// @dev RFTs assigned to the zero address are considered invalid, and this
+ /// function throws for queries about the zero address.
+ /// @param owner An address for whom to query the balance
+ /// @return The number of RFTs owned by `owner`, possibly zero
+ /// @dev EVM selector for this function is: 0x70a08231,
+ /// or in textual repr: balanceOf(address)
+ function balanceOf(address owner) public view returns (uint256) {
require(false, stub_error);
- admin;
- dummy = 0;
+ owner;
+ dummy;
+ return 0;
}
- // Add collection admin.
- // @param new_admin Address of the added administrator.
- //
- // Selector: addCollectionAdmin(address) 92e462c7
- function addCollectionAdmin(address newAdmin) public {
+ /// @notice Find the owner of an RFT
+ /// @dev RFTs assigned to zero address are considered invalid, and queries
+ /// about them do throw.
+ /// Returns special 0xffffffffffffffffffffffffffffffffffffffff address for
+ /// the tokens that are partially owned.
+ /// @param tokenId The identifier for an RFT
+ /// @return The address of the owner of the RFT
+ /// @dev EVM selector for this function is: 0x6352211e,
+ /// or in textual repr: ownerOf(uint256)
+ function ownerOf(uint256 tokenId) public view returns (address) {
require(false, stub_error);
- newAdmin;
- dummy = 0;
+ tokenId;
+ dummy;
+ return 0x0000000000000000000000000000000000000000;
}
- // Remove collection admin.
- //
- // @param new_admin Address of the removed administrator.
- //
- // Selector: removeCollectionAdmin(address) fafd7b42
- function removeCollectionAdmin(address admin) public {
+ /// @dev Not implemented
+ /// @dev EVM selector for this function is: 0x60a11672,
+ /// or in textual repr: safeTransferFromWithData(address,address,uint256,bytes)
+ function safeTransferFromWithData(
+ address from,
+ address to,
+ uint256 tokenId,
+ bytes memory data
+ ) public {
require(false, stub_error);
- admin;
+ from;
+ to;
+ tokenId;
+ data;
dummy = 0;
}
- // Toggle accessibility of collection nesting.
- //
- // @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'
- //
- // Selector: setCollectionNesting(bool) 112d4586
- function setCollectionNesting(bool enable) public {
+ /// @dev Not implemented
+ /// @dev EVM selector for this function is: 0x42842e0e,
+ /// or in textual repr: safeTransferFrom(address,address,uint256)
+ function safeTransferFrom(
+ address from,
+ address to,
+ uint256 tokenId
+ ) public {
require(false, stub_error);
- enable;
+ from;
+ to;
+ tokenId;
dummy = 0;
}
- // Toggle accessibility of collection nesting.
- //
- // @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'
- // @param collections Addresses of collections that will be available for nesting.
- //
- // Selector: setCollectionNesting(bool,address[]) 64872396
- function setCollectionNesting(bool enable, address[] memory collections)
- public
- {
- require(false, stub_error);
- enable;
- collections;
- dummy = 0;
- }
-
- // Set the collection access method.
- // @param mode Access mode
- // 0 for Normal
- // 1 for AllowList
- //
- // Selector: setCollectionAccess(uint8) 41835d4c
- function setCollectionAccess(uint8 mode) public {
+ /// @notice Transfer ownership of an RFT -- THE CALLER IS RESPONSIBLE
+ /// TO CONFIRM THAT `to` IS CAPABLE OF RECEIVING NFTS OR ELSE
+ /// THEY MAY BE PERMANENTLY LOST
+ /// @dev Throws unless `msg.sender` is the current owner or an authorized
+ /// operator for this RFT. Throws if `from` is not the current owner. Throws
+ /// if `to` is the zero address. Throws if `tokenId` is not a valid RFT.
+ /// Throws if RFT pieces have multiple owners.
+ /// @param from The current owner of the NFT
+ /// @param to The new owner
+ /// @param tokenId The NFT to transfer
+ /// @dev EVM selector for this function is: 0x23b872dd,
+ /// or in textual repr: transferFrom(address,address,uint256)
+ function transferFrom(
+ address from,
+ address to,
+ uint256 tokenId
+ ) public {
require(false, stub_error);
- mode;
- dummy = 0;
- }
-
- // Add the user to the allowed list.
- //
- // @param user Address of a trusted user.
- //
- // Selector: addToCollectionAllowList(address) 67844fe6
- function addToCollectionAllowList(address user) public {
- require(false, stub_error);
- user;
+ from;
+ to;
+ tokenId;
dummy = 0;
}
- // Remove the user from the allowed list.
- //
- // @param user Address of a removed user.
- //
- // Selector: removeFromCollectionAllowList(address) 85c51acb
- function removeFromCollectionAllowList(address user) public {
+ /// @dev Not implemented
+ /// @dev EVM selector for this function is: 0x095ea7b3,
+ /// or in textual repr: approve(address,uint256)
+ function approve(address approved, uint256 tokenId) public {
require(false, stub_error);
- user;
+ approved;
+ tokenId;
dummy = 0;
}
- // Switch permission for minting.
- //
- // @param mode Enable if "true".
- //
- // Selector: setCollectionMintMode(bool) 00018e84
- function setCollectionMintMode(bool mode) public {
+ /// @dev Not implemented
+ /// @dev EVM selector for this function is: 0xa22cb465,
+ /// or in textual repr: setApprovalForAll(address,bool)
+ function setApprovalForAll(address operator, bool approved) public {
require(false, stub_error);
- mode;
+ operator;
+ approved;
dummy = 0;
}
- // Check that account is the owner or admin of the collection
- //
- // @param user account to verify
- // @return "true" if account is the owner or admin
- //
- // Selector: isOwnerOrAdmin(address) 9811b0c7
- function isOwnerOrAdmin(address user) public view returns (bool) {
+ /// @dev Not implemented
+ /// @dev EVM selector for this function is: 0x081812fc,
+ /// or in textual repr: getApproved(uint256)
+ function getApproved(uint256 tokenId) public view returns (address) {
require(false, stub_error);
- user;
+ tokenId;
dummy;
- return false;
+ return 0x0000000000000000000000000000000000000000;
}
- // Check that substrate account is the owner or admin of the collection
- //
- // @param user account to verify
- // @return "true" if account is the owner or admin
- //
- // Selector: isOwnerOrAdminSubstrate(uint256) 68910e00
- function isOwnerOrAdminSubstrate(uint256 user) public view returns (bool) {
+ /// @dev Not implemented
+ /// @dev EVM selector for this function is: 0xe985e9c5,
+ /// or in textual repr: isApprovedForAll(address,address)
+ function isApprovedForAll(address owner, address operator)
+ public
+ view
+ returns (address)
+ {
require(false, stub_error);
- user;
+ owner;
+ operator;
dummy;
- return false;
- }
-
- // Returns collection type
- //
- // @return `Fungible` or `NFT` or `ReFungible`
- //
- // Selector: uniqueCollectionType() d34b55b8
- function uniqueCollectionType() public returns (string memory) {
- require(false, stub_error);
- dummy = 0;
- return "";
- }
-
- // Changes collection owner to another account
- //
- // @dev Owner can be changed only by current owner
- // @param newOwner new owner account
- //
- // Selector: setOwner(address) 13af4035
- function setOwner(address newOwner) public {
- require(false, stub_error);
- newOwner;
- dummy = 0;
- }
-
- // Changes collection owner to another substrate account
- //
- // @dev Owner can be changed only by current owner
- // @param newOwner new owner substrate account
- //
- // Selector: setOwnerSubstrate(uint256) b212138f
- function setOwnerSubstrate(uint256 newOwner) public {
- require(false, stub_error);
- newOwner;
- dummy = 0;
+ return 0x0000000000000000000000000000000000000000;
}
}
pallets/refungible/src/stubs/UniqueRefungibleToken.rawdiffbeforeafterbothbinary blob — no preview
pallets/refungible/src/stubs/UniqueRefungibleToken.soldiffbeforeafterboth--- a/pallets/refungible/src/stubs/UniqueRefungibleToken.sol
+++ b/pallets/refungible/src/stubs/UniqueRefungibleToken.sol
@@ -3,7 +3,7 @@
pragma solidity >=0.8.0 <0.9.0;
-// Common stubs holder
+/// @dev common stubs holder
contract Dummy {
uint8 dummy;
string stub_error = "this contract is implemented in native";
@@ -21,19 +21,10 @@
}
}
-// Inline
-contract ERC20Events {
- event Transfer(address indexed from, address indexed to, uint256 value);
- event Approval(
- address indexed owner,
- address indexed spender,
- uint256 value
- );
-}
-
-// Selector: 042f1106
+/// @dev the ERC-165 identifier for this interface is 0x042f1106
contract ERC1633UniqueExtensions is Dummy, ERC165 {
- // Selector: setParentNFT(address,uint256) 042f1106
+ /// @dev EVM selector for this function is: 0x042f1106,
+ /// or in textual repr: setParentNFT(address,uint256)
function setParentNFT(address collection, uint256 nftId)
public
returns (bool)
@@ -46,16 +37,18 @@
}
}
-// Selector: 5755c3f2
+/// @dev the ERC-165 identifier for this interface is 0x5755c3f2
contract ERC1633 is Dummy, ERC165 {
- // Selector: parentToken() 80a54001
+ /// @dev EVM selector for this function is: 0x80a54001,
+ /// or in textual repr: parentToken()
function parentToken() public view returns (address) {
require(false, stub_error);
dummy;
return 0x0000000000000000000000000000000000000000;
}
- // Selector: parentTokenId() d7f083f3
+ /// @dev EVM selector for this function is: 0xd7f083f3,
+ /// or in textual repr: parentTokenId()
function parentTokenId() public view returns (uint256) {
require(false, stub_error);
dummy;
@@ -63,49 +56,92 @@
}
}
-// Selector: 942e8b22
+/// @dev the ERC-165 identifier for this interface is 0xab8deb37
+contract ERC20UniqueExtensions is Dummy, ERC165 {
+ /// @dev Function that burns an amount of the token of a given account,
+ /// deducting from the sender's allowance for said account.
+ /// @param from The account whose tokens will be burnt.
+ /// @param amount The amount that will be burnt.
+ /// @dev EVM selector for this function is: 0x79cc6790,
+ /// or in textual repr: burnFrom(address,uint256)
+ function burnFrom(address from, uint256 amount) public returns (bool) {
+ require(false, stub_error);
+ from;
+ amount;
+ dummy = 0;
+ return false;
+ }
+
+ /// @dev Function that changes total amount of the tokens.
+ /// Throws if `msg.sender` doesn't owns all of the tokens.
+ /// @param amount New total amount of the tokens.
+ /// @dev EVM selector for this function is: 0xd2418ca7,
+ /// or in textual repr: repartition(uint256)
+ function repartition(uint256 amount) public returns (bool) {
+ require(false, stub_error);
+ amount;
+ dummy = 0;
+ return false;
+ }
+}
+
+/// @dev inlined interface
+contract ERC20Events {
+ event Transfer(address indexed from, address indexed to, uint256 value);
+ event Approval(
+ address indexed owner,
+ address indexed spender,
+ uint256 value
+ );
+}
+
+/// @title Standard ERC20 token
+///
+/// @dev Implementation of the basic standard token.
+/// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
+/// @dev the ERC-165 identifier for this interface is 0x942e8b22
contract ERC20 is Dummy, ERC165, ERC20Events {
- // @return the name of the token.
- //
- // Selector: name() 06fdde03
+ /// @return the name of the token.
+ /// @dev EVM selector for this function is: 0x06fdde03,
+ /// or in textual repr: name()
function name() public view returns (string memory) {
require(false, stub_error);
dummy;
return "";
}
- // @return the symbol of the token.
- //
- // Selector: symbol() 95d89b41
+ /// @return the symbol of the token.
+ /// @dev EVM selector for this function is: 0x95d89b41,
+ /// or in textual repr: symbol()
function symbol() public view returns (string memory) {
require(false, stub_error);
dummy;
return "";
}
- // @dev Total number of tokens in existence
- //
- // Selector: totalSupply() 18160ddd
+ /// @dev Total number of tokens in existence
+ /// @dev EVM selector for this function is: 0x18160ddd,
+ /// or in textual repr: totalSupply()
function totalSupply() public view returns (uint256) {
require(false, stub_error);
dummy;
return 0;
}
- // @dev Not supported
- //
- // Selector: decimals() 313ce567
+ /// @dev Not supported
+ /// @dev EVM selector for this function is: 0x313ce567,
+ /// or in textual repr: decimals()
function decimals() public view returns (uint8) {
require(false, stub_error);
dummy;
return 0;
}
- // @dev Gets the balance of the specified address.
- // @param owner The address to query the balance of.
- // @return An uint256 representing the amount owned by the passed address.
- //
- // Selector: balanceOf(address) 70a08231
+ /// @dev Gets the balance of the specified address.
+ /// @param owner The address to query the balance of.
+ /// @return An uint256 representing the amount owned by the passed address.
+ /// @dev EVM selector for this function is: 0x70a08231,
+ /// or in textual repr: balanceOf(address)
function balanceOf(address owner) public view returns (uint256) {
require(false, stub_error);
owner;
@@ -113,11 +149,11 @@
return 0;
}
- // @dev Transfer token for a specified address
- // @param to The address to transfer to.
- // @param amount The amount to be transferred.
- //
- // Selector: transfer(address,uint256) a9059cbb
+ /// @dev Transfer token for a specified address
+ /// @param to The address to transfer to.
+ /// @param amount The amount to be transferred.
+ /// @dev EVM selector for this function is: 0xa9059cbb,
+ /// or in textual repr: transfer(address,uint256)
function transfer(address to, uint256 amount) public returns (bool) {
require(false, stub_error);
to;
@@ -126,12 +162,12 @@
return false;
}
- // @dev Transfer tokens from one address to another
- // @param from address The address which you want to send tokens from
- // @param to address The address which you want to transfer to
- // @param amount uint256 the amount of tokens to be transferred
- //
- // Selector: transferFrom(address,address,uint256) 23b872dd
+ /// @dev Transfer tokens from one address to another
+ /// @param from address The address which you want to send tokens from
+ /// @param to address The address which you want to transfer to
+ /// @param amount uint256 the amount of tokens to be transferred
+ /// @dev EVM selector for this function is: 0x23b872dd,
+ /// or in textual repr: transferFrom(address,address,uint256)
function transferFrom(
address from,
address to,
@@ -145,15 +181,15 @@
return false;
}
- // @dev Approve the passed address to spend the specified amount of tokens on behalf of `msg.sender`.
- // Beware that changing an allowance with this method brings the risk that someone may use both the old
- // and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
- // race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
- // https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
- // @param spender The address which will spend the funds.
- // @param amount The amount of tokens to be spent.
- //
- // Selector: approve(address,uint256) 095ea7b3
+ /// @dev Approve the passed address to spend the specified amount of tokens on behalf of `msg.sender`.
+ /// Beware that changing an allowance with this method brings the risk that someone may use both the old
+ /// and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
+ /// race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
+ /// https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
+ /// @param spender The address which will spend the funds.
+ /// @param amount The amount of tokens to be spent.
+ /// @dev EVM selector for this function is: 0x095ea7b3,
+ /// or in textual repr: approve(address,uint256)
function approve(address spender, uint256 amount) public returns (bool) {
require(false, stub_error);
spender;
@@ -162,12 +198,12 @@
return false;
}
- // @dev Function to check the amount of tokens that an owner allowed to a spender.
- // @param owner address The address which owns the funds.
- // @param spender address The address which will spend the funds.
- // @return A uint256 specifying the amount of tokens still available for the spender.
- //
- // Selector: allowance(address,address) dd62ed3e
+ /// @dev Function to check the amount of tokens that an owner allowed to a spender.
+ /// @param owner address The address which owns the funds.
+ /// @param spender address The address which will spend the funds.
+ /// @return A uint256 specifying the amount of tokens still available for the spender.
+ /// @dev EVM selector for this function is: 0xdd62ed3e,
+ /// or in textual repr: allowance(address,address)
function allowance(address owner, address spender)
public
view
@@ -178,35 +214,6 @@
spender;
dummy;
return 0;
- }
-}
-
-// Selector: ab8deb37
-contract ERC20UniqueExtensions is Dummy, ERC165 {
- // @dev Function that burns an amount of the token of a given account,
- // deducting from the sender's allowance for said account.
- // @param from The account whose tokens will be burnt.
- // @param amount The amount that will be burnt.
- //
- // Selector: burnFrom(address,uint256) 79cc6790
- function burnFrom(address from, uint256 amount) public returns (bool) {
- require(false, stub_error);
- from;
- amount;
- dummy = 0;
- return false;
- }
-
- // @dev Function that changes total amount of the tokens.
- // Throws if `msg.sender` doesn't owns all of the tokens.
- // @param amount New total amount of the tokens.
- //
- // Selector: repartition(uint256) d2418ca7
- function repartition(uint256 amount) public returns (bool) {
- require(false, stub_error);
- amount;
- dummy = 0;
- return false;
}
}
pallets/unique/src/eth/mod.rsdiffbeforeafterboth--- a/pallets/unique/src/eth/mod.rs
+++ b/pallets/unique/src/eth/mod.rs
@@ -203,7 +203,7 @@
}
/// @title Contract, which allows users to operate with collections
-#[solidity_interface(name = "CollectionHelpers", events(CollectionHelpersEvents))]
+#[solidity_interface(name = CollectionHelpers, events(CollectionHelpersEvents))]
impl<T> EvmCollectionHelpers<T>
where
T: Config + pallet_nonfungible::Config + pallet_refungible::Config,
@@ -211,7 +211,7 @@
/// Create an NFT collection
/// @param name Name of the collection
/// @param description Informative description of the collection
- /// @param token_prefix Token prefix to represent the collection tokens in UI and user applications
+ /// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications
/// @return address Address of the newly created collection
#[weight(<SelfWeightOf<T>>::create_collection())]
fn create_nonfungible_collection(
@@ -304,7 +304,7 @@
}
/// Check if a collection exists
- /// @param collection_address Address of the collection in question
+ /// @param collectionAddress Address of the collection in question
/// @return bool Does the collection exist?
fn is_collection_exist(&self, _caller: caller, collection_address: address) -> Result<bool> {
if let Some(id) = pallet_common::eth::map_eth_to_id(&collection_address) {
pallets/unique/src/eth/stubs/CollectionHelpers.rawdiffbeforeafterbothbinary blob — no preview
pallets/unique/src/eth/stubs/CollectionHelpers.soldiffbeforeafterboth--- a/pallets/unique/src/eth/stubs/CollectionHelpers.sol
+++ b/pallets/unique/src/eth/stubs/CollectionHelpers.sol
@@ -3,7 +3,7 @@
pragma solidity >=0.8.0 <0.9.0;
-// Common stubs holder
+/// @dev common stubs holder
contract Dummy {
uint8 dummy;
string stub_error = "this contract is implemented in native";
@@ -21,7 +21,7 @@
}
}
-// Inline
+/// @dev inlined interface
contract CollectionHelpersEvents {
event CollectionCreated(
address indexed owner,
@@ -29,15 +29,16 @@
);
}
-// Selector: 675f3074
+/// @title Contract, which allows users to operate with collections
+/// @dev the ERC-165 identifier for this interface is 0x675f3074
contract CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents {
- // Create an NFT collection
- // @param name Name of the collection
- // @param description Informative description of the collection
- // @param token_prefix Token prefix to represent the collection tokens in UI and user applications
- // @return address Address of the newly created collection
- //
- // Selector: createNonfungibleCollection(string,string,string) e34a6844
+ /// Create an NFT collection
+ /// @param name Name of the collection
+ /// @param description Informative description of the collection
+ /// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications
+ /// @return address Address of the newly created collection
+ /// @dev EVM selector for this function is: 0xe34a6844,
+ /// or in textual repr: createNonfungibleCollection(string,string,string)
function createNonfungibleCollection(
string memory name,
string memory description,
@@ -51,7 +52,8 @@
return 0x0000000000000000000000000000000000000000;
}
- // Selector: createERC721MetadataCompatibleCollection(string,string,string,string) a634a5f9
+ /// @dev EVM selector for this function is: 0xa634a5f9,
+ /// or in textual repr: createERC721MetadataCompatibleCollection(string,string,string,string)
function createERC721MetadataCompatibleCollection(
string memory name,
string memory description,
@@ -67,7 +69,8 @@
return 0x0000000000000000000000000000000000000000;
}
- // Selector: createRefungibleCollection(string,string,string) 44a68ad5
+ /// @dev EVM selector for this function is: 0x44a68ad5,
+ /// or in textual repr: createRefungibleCollection(string,string,string)
function createRefungibleCollection(
string memory name,
string memory description,
@@ -81,7 +84,8 @@
return 0x0000000000000000000000000000000000000000;
}
- // Selector: createERC721MetadataCompatibleRFTCollection(string,string,string,string) a5596388
+ /// @dev EVM selector for this function is: 0xa5596388,
+ /// or in textual repr: createERC721MetadataCompatibleRFTCollection(string,string,string,string)
function createERC721MetadataCompatibleRFTCollection(
string memory name,
string memory description,
@@ -97,11 +101,11 @@
return 0x0000000000000000000000000000000000000000;
}
- // Check if a collection exists
- // @param collection_address Address of the collection in question
- // @return bool Does the collection exist?
- //
- // Selector: isCollectionExist(address) c3de1494
+ /// Check if a collection exists
+ /// @param collectionAddress Address of the collection in question
+ /// @return bool Does the collection exist?
+ /// @dev EVM selector for this function is: 0xc3de1494,
+ /// or in textual repr: isCollectionExist(address)
function isCollectionExist(address collectionAddress)
public
view
runtime/common/config/ethereum.rsdiffbeforeafterboth--- a/runtime/common/config/ethereum.rs
+++ b/runtime/common/config/ethereum.rs
@@ -120,5 +120,4 @@
impl pallet_evm_transaction_payment::Config for Runtime {
type EvmSponsorshipHandler = EvmSponsorshipHandler;
- type Currency = Balances;
}
tests/src/eth/api/CollectionHelpers.soldiffbeforeafterboth--- a/tests/src/eth/api/CollectionHelpers.sol
+++ b/tests/src/eth/api/CollectionHelpers.sol
@@ -3,7 +3,7 @@
pragma solidity >=0.8.0 <0.9.0;
-// Common stubs holder
+/// @dev common stubs holder
interface Dummy {
}
@@ -12,7 +12,7 @@
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
-// Inline
+/// @dev inlined interface
interface CollectionHelpersEvents {
event CollectionCreated(
address indexed owner,
@@ -20,22 +20,24 @@
);
}
-// Selector: 675f3074
+/// @title Contract, which allows users to operate with collections
+/// @dev the ERC-165 identifier for this interface is 0x675f3074
interface CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents {
- // Create an NFT collection
- // @param name Name of the collection
- // @param description Informative description of the collection
- // @param token_prefix Token prefix to represent the collection tokens in UI and user applications
- // @return address Address of the newly created collection
- //
- // Selector: createNonfungibleCollection(string,string,string) e34a6844
+ /// Create an NFT collection
+ /// @param name Name of the collection
+ /// @param description Informative description of the collection
+ /// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications
+ /// @return address Address of the newly created collection
+ /// @dev EVM selector for this function is: 0xe34a6844,
+ /// or in textual repr: createNonfungibleCollection(string,string,string)
function createNonfungibleCollection(
string memory name,
string memory description,
string memory tokenPrefix
) external returns (address);
- // Selector: createERC721MetadataCompatibleCollection(string,string,string,string) a634a5f9
+ /// @dev EVM selector for this function is: 0xa634a5f9,
+ /// or in textual repr: createERC721MetadataCompatibleCollection(string,string,string,string)
function createERC721MetadataCompatibleCollection(
string memory name,
string memory description,
@@ -43,14 +45,16 @@
string memory baseUri
) external returns (address);
- // Selector: createRefungibleCollection(string,string,string) 44a68ad5
+ /// @dev EVM selector for this function is: 0x44a68ad5,
+ /// or in textual repr: createRefungibleCollection(string,string,string)
function createRefungibleCollection(
string memory name,
string memory description,
string memory tokenPrefix
) external returns (address);
- // Selector: createERC721MetadataCompatibleRFTCollection(string,string,string,string) a5596388
+ /// @dev EVM selector for this function is: 0xa5596388,
+ /// or in textual repr: createERC721MetadataCompatibleRFTCollection(string,string,string,string)
function createERC721MetadataCompatibleRFTCollection(
string memory name,
string memory description,
@@ -58,11 +62,11 @@
string memory baseUri
) external returns (address);
- // Check if a collection exists
- // @param collection_address Address of the collection in question
- // @return bool Does the collection exist?
- //
- // Selector: isCollectionExist(address) c3de1494
+ /// Check if a collection exists
+ /// @param collectionAddress Address of the collection in question
+ /// @return bool Does the collection exist?
+ /// @dev EVM selector for this function is: 0xc3de1494,
+ /// or in textual repr: isCollectionExist(address)
function isCollectionExist(address collectionAddress)
external
view
tests/src/eth/api/ContractHelpers.soldiffbeforeafterboth--- a/tests/src/eth/api/ContractHelpers.sol
+++ b/tests/src/eth/api/ContractHelpers.sol
@@ -3,13 +3,7 @@
pragma solidity >=0.8.0 <0.9.0;
-// Anonymous struct
-struct Tuple0 {
- address field_0;
- uint256 field_1;
-}
-
-// Common stubs holder
+/// @dev common stubs holder
interface Dummy {
}
@@ -18,124 +12,164 @@
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
-// Selector: 6073d917
+/// @title Magic contract, which allows users to reconfigure other contracts
+/// @dev the ERC-165 identifier for this interface is 0xd77fab70
interface ContractHelpers is Dummy, ERC165 {
- // Get contract ovner
- //
- // @param Contract_address contract for which the owner is being determined.
- // @return Contract owner.
- //
- // Selector: contractOwner(address) 5152b14c
+ /// Get user, which deployed specified contract
+ /// @dev May return zero address in case if contract is deployed
+ /// using uniquenetwork evm-migration pallet, or using other terms not
+ /// intended by pallet-evm
+ /// @dev Returns zero address if contract does not exists
+ /// @param contractAddress Contract to get owner of
+ /// @return address Owner of contract
+ /// @dev EVM selector for this function is: 0x5152b14c,
+ /// or in textual repr: contractOwner(address)
function contractOwner(address contractAddress)
external
view
returns (address);
- // Set sponsor.
- //
- // @param contract_address Contract for which a sponsor is being established.
- // @param sponsor User address who set as pending sponsor.
- //
- // Selector: setSponsor(address,address) f01fba93
+ /// Set sponsor.
+ /// @param contractAddress Contract for which a sponsor is being established.
+ /// @param sponsor User address who set as pending sponsor.
+ /// @dev EVM selector for this function is: 0xf01fba93,
+ /// or in textual repr: setSponsor(address,address)
function setSponsor(address contractAddress, address sponsor) external;
- // Set contract as self sponsored.
- //
- // @param contract_address Contract for which a self sponsoring is being enabled.
- //
- // Selector: selfSponsoredEnable(address) 89f7d9ae
+ /// Set contract as self sponsored.
+ ///
+ /// @param contractAddress Contract for which a self sponsoring is being enabled.
+ /// @dev EVM selector for this function is: 0x89f7d9ae,
+ /// or in textual repr: selfSponsoredEnable(address)
function selfSponsoredEnable(address contractAddress) external;
- // Remove sponsor.
- //
- // @param contract_address Contract for which a sponsorship is being removed.
- //
- // Selector: removeSponsor(address) ef784250
+ /// Remove sponsor.
+ ///
+ /// @param contractAddress Contract for which a sponsorship is being removed.
+ /// @dev EVM selector for this function is: 0xef784250,
+ /// or in textual repr: removeSponsor(address)
function removeSponsor(address contractAddress) external;
- // Confirm sponsorship.
- //
- // @dev Caller must be same that set via [`set_sponsor`].
- //
- // @param contract_address Сontract for which need to confirm sponsorship.
- //
- // Selector: confirmSponsorship(address) abc00001
+ /// Confirm sponsorship.
+ ///
+ /// @dev Caller must be same that set via [`setSponsor`].
+ ///
+ /// @param contractAddress Сontract for which need to confirm sponsorship.
+ /// @dev EVM selector for this function is: 0xabc00001,
+ /// or in textual repr: confirmSponsorship(address)
function confirmSponsorship(address contractAddress) external;
- // Get current sponsor.
- //
- // @param contract_address The contract for which a sponsor is requested.
- // @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.
- //
- // Selector: getSponsor(address) 743fc745
+ /// Get current sponsor.
+ ///
+ /// @param contractAddress The contract for which a sponsor is requested.
+ /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.
+ /// @dev EVM selector for this function is: 0x743fc745,
+ /// or in textual repr: getSponsor(address)
function getSponsor(address contractAddress)
external
view
returns (Tuple0 memory);
- // Check tat contract has confirmed sponsor.
- //
- // @param contract_address The contract for which the presence of a confirmed sponsor is checked.
- // @return **true** if contract has confirmed sponsor.
- //
- // Selector: hasSponsor(address) 97418603
+ /// Check tat contract has confirmed sponsor.
+ ///
+ /// @param contractAddress The contract for which the presence of a confirmed sponsor is checked.
+ /// @return **true** if contract has confirmed sponsor.
+ /// @dev EVM selector for this function is: 0x97418603,
+ /// or in textual repr: hasSponsor(address)
function hasSponsor(address contractAddress) external view returns (bool);
- // Check tat contract has pending sponsor.
- //
- // @param contract_address The contract for which the presence of a pending sponsor is checked.
- // @return **true** if contract has pending sponsor.
- //
- // Selector: hasPendingSponsor(address) 39b9b242
+ /// Check tat contract has pending sponsor.
+ ///
+ /// @param contractAddress The contract for which the presence of a pending sponsor is checked.
+ /// @return **true** if contract has pending sponsor.
+ /// @dev EVM selector for this function is: 0x39b9b242,
+ /// or in textual repr: hasPendingSponsor(address)
function hasPendingSponsor(address contractAddress)
external
view
returns (bool);
- // Selector: sponsoringEnabled(address) 6027dc61
+ /// @dev EVM selector for this function is: 0x6027dc61,
+ /// or in textual repr: sponsoringEnabled(address)
function sponsoringEnabled(address contractAddress)
external
view
returns (bool);
- // Selector: setSponsoringMode(address,uint8) fde8a560
+ /// @dev EVM selector for this function is: 0xfde8a560,
+ /// or in textual repr: setSponsoringMode(address,uint8)
function setSponsoringMode(address contractAddress, uint8 mode) external;
- // Selector: sponsoringMode(address) b70c7267
- function sponsoringMode(address contractAddress)
+ /// Get current contract sponsoring rate limit
+ /// @param contractAddress Contract to get sponsoring mode of
+ /// @return uint32 Amount of blocks between two sponsored transactions
+ /// @dev EVM selector for this function is: 0x610cfabd,
+ /// or in textual repr: getSponsoringRateLimit(address)
+ function getSponsoringRateLimit(address contractAddress)
external
view
- returns (uint8);
+ returns (uint32);
- // Selector: setSponsoringRateLimit(address,uint32) 77b6c908
+ /// Set contract sponsoring rate limit
+ /// @dev Sponsoring rate limit - is a minimum amount of blocks that should
+ /// pass between two sponsored transactions
+ /// @param contractAddress Contract to change sponsoring rate limit of
+ /// @param rateLimit Target rate limit
+ /// @dev Only contract owner can change this setting
+ /// @dev EVM selector for this function is: 0x77b6c908,
+ /// or in textual repr: setSponsoringRateLimit(address,uint32)
function setSponsoringRateLimit(address contractAddress, uint32 rateLimit)
external;
- // Selector: getSponsoringRateLimit(address) 610cfabd
- function getSponsoringRateLimit(address contractAddress)
- external
- view
- returns (uint32);
-
- // Selector: allowed(address,address) 5c658165
+ /// Is specified user present in contract allow list
+ /// @dev Contract owner always implicitly included
+ /// @param contractAddress Contract to check allowlist of
+ /// @param user User to check
+ /// @return bool Is specified users exists in contract allowlist
+ /// @dev EVM selector for this function is: 0x5c658165,
+ /// or in textual repr: allowed(address,address)
function allowed(address contractAddress, address user)
external
view
returns (bool);
- // Selector: allowlistEnabled(address) c772ef6c
+ /// Toggle user presence in contract allowlist
+ /// @param contractAddress Contract to change allowlist of
+ /// @param user Which user presence should be toggled
+ /// @param isAllowed `true` if user should be allowed to be sponsored
+ /// or call this contract, `false` otherwise
+ /// @dev Only contract owner can change this setting
+ /// @dev EVM selector for this function is: 0x4706cc1c,
+ /// or in textual repr: toggleAllowed(address,address,bool)
+ function toggleAllowed(
+ address contractAddress,
+ address user,
+ bool isAllowed
+ ) external;
+
+ /// Is this contract has allowlist access enabled
+ /// @dev Allowlist always can have users, and it is used for two purposes:
+ /// in case of allowlist sponsoring mode, users will be sponsored if they exist in allowlist
+ /// in case of allowlist access enabled, only users from allowlist may call this contract
+ /// @param contractAddress Contract to get allowlist access of
+ /// @return bool Is specified contract has allowlist access enabled
+ /// @dev EVM selector for this function is: 0xc772ef6c,
+ /// or in textual repr: allowlistEnabled(address)
function allowlistEnabled(address contractAddress)
external
view
returns (bool);
- // Selector: toggleAllowlist(address,bool) 36de20f5
+ /// Toggle contract allowlist access
+ /// @param contractAddress Contract to change allowlist access of
+ /// @param enabled Should allowlist access to be enabled?
+ /// @dev EVM selector for this function is: 0x36de20f5,
+ /// or in textual repr: toggleAllowlist(address,bool)
function toggleAllowlist(address contractAddress, bool enabled) external;
+}
- // Selector: toggleAllowed(address,address,bool) 4706cc1c
- function toggleAllowed(
- address contractAddress,
- address user,
- bool allowed
- ) external;
+/// @dev anonymous struct
+struct Tuple0 {
+ address field_0;
+ uint256 field_1;
}
tests/src/eth/api/UniqueFungible.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueFungible.sol
+++ b/tests/src/eth/api/UniqueFungible.sol
@@ -3,7 +3,7 @@
pragma solidity >=0.8.0 <0.9.0;
-// Common stubs holder
+/// @dev common stubs holder
interface Dummy {
}
@@ -12,246 +12,257 @@
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
-// Inline
-interface ERC20Events {
- event Transfer(address indexed from, address indexed to, uint256 value);
- event Approval(
- address indexed owner,
- address indexed spender,
- uint256 value
- );
-}
-
-// Selector: 79cc6790
-interface ERC20UniqueExtensions is Dummy, ERC165 {
- // Selector: burnFrom(address,uint256) 79cc6790
- function burnFrom(address from, uint256 amount) external returns (bool);
-}
-
-// Selector: 942e8b22
-interface ERC20 is Dummy, ERC165, ERC20Events {
- // Selector: name() 06fdde03
- function name() external view returns (string memory);
-
- // Selector: symbol() 95d89b41
- function symbol() external view returns (string memory);
-
- // Selector: totalSupply() 18160ddd
- function totalSupply() external view returns (uint256);
-
- // Selector: decimals() 313ce567
- function decimals() external view returns (uint8);
-
- // Selector: balanceOf(address) 70a08231
- function balanceOf(address owner) external view returns (uint256);
-
- // Selector: transfer(address,uint256) a9059cbb
- function transfer(address to, uint256 amount) external returns (bool);
-
- // Selector: transferFrom(address,address,uint256) 23b872dd
- function transferFrom(
- address from,
- address to,
- uint256 amount
- ) external returns (bool);
-
- // Selector: approve(address,uint256) 095ea7b3
- function approve(address spender, uint256 amount) external returns (bool);
-
- // Selector: allowance(address,address) dd62ed3e
- function allowance(address owner, address spender)
- external
- view
- returns (uint256);
-}
-
-// Selector: ffe4da23
+/// @title A contract that allows you to work with collections.
+/// @dev the ERC-165 identifier for this interface is 0xffe4da23
interface Collection is Dummy, ERC165 {
- // Set collection property.
- //
- // @param key Property key.
- // @param value Propery value.
- //
- // Selector: setCollectionProperty(string,bytes) 2f073f66
+ /// Set collection property.
+ ///
+ /// @param key Property key.
+ /// @param value Propery value.
+ /// @dev EVM selector for this function is: 0x2f073f66,
+ /// or in textual repr: setCollectionProperty(string,bytes)
function setCollectionProperty(string memory key, bytes memory value)
external;
- // Delete collection property.
- //
- // @param key Property key.
- //
- // Selector: deleteCollectionProperty(string) 7b7debce
+ /// Delete collection property.
+ ///
+ /// @param key Property key.
+ /// @dev EVM selector for this function is: 0x7b7debce,
+ /// or in textual repr: deleteCollectionProperty(string)
function deleteCollectionProperty(string memory key) external;
- // Get collection property.
- //
- // @dev Throws error if key not found.
- //
- // @param key Property key.
- // @return bytes The property corresponding to the key.
- //
- // Selector: collectionProperty(string) cf24fd6d
+ /// Get collection property.
+ ///
+ /// @dev Throws error if key not found.
+ ///
+ /// @param key Property key.
+ /// @return bytes The property corresponding to the key.
+ /// @dev EVM selector for this function is: 0xcf24fd6d,
+ /// or in textual repr: collectionProperty(string)
function collectionProperty(string memory key)
external
view
returns (bytes memory);
- // Set the sponsor of the collection.
- //
- // @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.
- //
- // @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.
- //
- // Selector: setCollectionSponsor(address) 7623402e
+ /// Set the sponsor of the collection.
+ ///
+ /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.
+ ///
+ /// @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.
+ /// @dev EVM selector for this function is: 0x7623402e,
+ /// or in textual repr: setCollectionSponsor(address)
function setCollectionSponsor(address sponsor) external;
- // Collection sponsorship confirmation.
- //
- // @dev After setting the sponsor for the collection, it must be confirmed with this function.
- //
- // Selector: confirmCollectionSponsorship() 3c50e97a
+ /// Collection sponsorship confirmation.
+ ///
+ /// @dev After setting the sponsor for the collection, it must be confirmed with this function.
+ /// @dev EVM selector for this function is: 0x3c50e97a,
+ /// or in textual repr: confirmCollectionSponsorship()
function confirmCollectionSponsorship() external;
- // Set limits for the collection.
- // @dev Throws error if limit not found.
- // @param limit Name of the limit. Valid names:
- // "accountTokenOwnershipLimit",
- // "sponsoredDataSize",
- // "sponsoredDataRateLimit",
- // "tokenLimit",
- // "sponsorTransferTimeout",
- // "sponsorApproveTimeout"
- // @param value Value of the limit.
- //
- // Selector: setCollectionLimit(string,uint32) 6a3841db
+ /// Set limits for the collection.
+ /// @dev Throws error if limit not found.
+ /// @param limit Name of the limit. Valid names:
+ /// "accountTokenOwnershipLimit",
+ /// "sponsoredDataSize",
+ /// "sponsoredDataRateLimit",
+ /// "tokenLimit",
+ /// "sponsorTransferTimeout",
+ /// "sponsorApproveTimeout"
+ /// @param value Value of the limit.
+ /// @dev EVM selector for this function is: 0x6a3841db,
+ /// or in textual repr: setCollectionLimit(string,uint32)
function setCollectionLimit(string memory limit, uint32 value) external;
- // Set limits for the collection.
- // @dev Throws error if limit not found.
- // @param limit Name of the limit. Valid names:
- // "ownerCanTransfer",
- // "ownerCanDestroy",
- // "transfersEnabled"
- // @param value Value of the limit.
- //
- // Selector: setCollectionLimit(string,bool) 993b7fba
+ /// Set limits for the collection.
+ /// @dev Throws error if limit not found.
+ /// @param limit Name of the limit. Valid names:
+ /// "ownerCanTransfer",
+ /// "ownerCanDestroy",
+ /// "transfersEnabled"
+ /// @param value Value of the limit.
+ /// @dev EVM selector for this function is: 0x993b7fba,
+ /// or in textual repr: setCollectionLimit(string,bool)
function setCollectionLimit(string memory limit, bool value) external;
- // Get contract address.
- //
- // Selector: contractAddress() f6b4dfb4
+ /// Get contract address.
+ /// @dev EVM selector for this function is: 0xf6b4dfb4,
+ /// or in textual repr: contractAddress()
function contractAddress() external view returns (address);
- // Add collection admin by substrate address.
- // @param new_admin Substrate administrator address.
- //
- // Selector: addCollectionAdminSubstrate(uint256) 5730062b
+ /// Add collection admin by substrate address.
+ /// @param newAdmin Substrate administrator address.
+ /// @dev EVM selector for this function is: 0x5730062b,
+ /// or in textual repr: addCollectionAdminSubstrate(uint256)
function addCollectionAdminSubstrate(uint256 newAdmin) external;
- // Remove collection admin by substrate address.
- // @param admin Substrate administrator address.
- //
- // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9
+ /// Remove collection admin by substrate address.
+ /// @param admin Substrate administrator address.
+ /// @dev EVM selector for this function is: 0x4048fcf9,
+ /// or in textual repr: removeCollectionAdminSubstrate(uint256)
function removeCollectionAdminSubstrate(uint256 admin) external;
- // Add collection admin.
- // @param new_admin Address of the added administrator.
- //
- // Selector: addCollectionAdmin(address) 92e462c7
+ /// Add collection admin.
+ /// @param newAdmin Address of the added administrator.
+ /// @dev EVM selector for this function is: 0x92e462c7,
+ /// or in textual repr: addCollectionAdmin(address)
function addCollectionAdmin(address newAdmin) external;
- // Remove collection admin.
- //
- // @param new_admin Address of the removed administrator.
- //
- // Selector: removeCollectionAdmin(address) fafd7b42
+ /// Remove collection admin.
+ ///
+ /// @param admin Address of the removed administrator.
+ /// @dev EVM selector for this function is: 0xfafd7b42,
+ /// or in textual repr: removeCollectionAdmin(address)
function removeCollectionAdmin(address admin) external;
- // Toggle accessibility of collection nesting.
- //
- // @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'
- //
- // Selector: setCollectionNesting(bool) 112d4586
+ /// Toggle accessibility of collection nesting.
+ ///
+ /// @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'
+ /// @dev EVM selector for this function is: 0x112d4586,
+ /// or in textual repr: setCollectionNesting(bool)
function setCollectionNesting(bool enable) external;
- // Toggle accessibility of collection nesting.
- //
- // @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'
- // @param collections Addresses of collections that will be available for nesting.
- //
- // Selector: setCollectionNesting(bool,address[]) 64872396
+ /// Toggle accessibility of collection nesting.
+ ///
+ /// @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'
+ /// @param collections Addresses of collections that will be available for nesting.
+ /// @dev EVM selector for this function is: 0x64872396,
+ /// or in textual repr: setCollectionNesting(bool,address[])
function setCollectionNesting(bool enable, address[] memory collections)
external;
- // Set the collection access method.
- // @param mode Access mode
- // 0 for Normal
- // 1 for AllowList
- //
- // Selector: setCollectionAccess(uint8) 41835d4c
+ /// Set the collection access method.
+ /// @param mode Access mode
+ /// 0 for Normal
+ /// 1 for AllowList
+ /// @dev EVM selector for this function is: 0x41835d4c,
+ /// or in textual repr: setCollectionAccess(uint8)
function setCollectionAccess(uint8 mode) external;
- // Add the user to the allowed list.
- //
- // @param user Address of a trusted user.
- //
- // Selector: addToCollectionAllowList(address) 67844fe6
+ /// Add the user to the allowed list.
+ ///
+ /// @param user Address of a trusted user.
+ /// @dev EVM selector for this function is: 0x67844fe6,
+ /// or in textual repr: addToCollectionAllowList(address)
function addToCollectionAllowList(address user) external;
- // Remove the user from the allowed list.
- //
- // @param user Address of a removed user.
- //
- // Selector: removeFromCollectionAllowList(address) 85c51acb
+ /// Remove the user from the allowed list.
+ ///
+ /// @param user Address of a removed user.
+ /// @dev EVM selector for this function is: 0x85c51acb,
+ /// or in textual repr: removeFromCollectionAllowList(address)
function removeFromCollectionAllowList(address user) external;
- // Switch permission for minting.
- //
- // @param mode Enable if "true".
- //
- // Selector: setCollectionMintMode(bool) 00018e84
+ /// Switch permission for minting.
+ ///
+ /// @param mode Enable if "true".
+ /// @dev EVM selector for this function is: 0x00018e84,
+ /// or in textual repr: setCollectionMintMode(bool)
function setCollectionMintMode(bool mode) external;
- // Check that account is the owner or admin of the collection
- //
- // @param user account to verify
- // @return "true" if account is the owner or admin
- //
- // Selector: isOwnerOrAdmin(address) 9811b0c7
+ /// Check that account is the owner or admin of the collection
+ ///
+ /// @param user account to verify
+ /// @return "true" if account is the owner or admin
+ /// @dev EVM selector for this function is: 0x9811b0c7,
+ /// or in textual repr: isOwnerOrAdmin(address)
function isOwnerOrAdmin(address user) external view returns (bool);
- // Check that substrate account is the owner or admin of the collection
- //
- // @param user account to verify
- // @return "true" if account is the owner or admin
- //
- // Selector: isOwnerOrAdminSubstrate(uint256) 68910e00
+ /// Check that substrate account is the owner or admin of the collection
+ ///
+ /// @param user account to verify
+ /// @return "true" if account is the owner or admin
+ /// @dev EVM selector for this function is: 0x68910e00,
+ /// or in textual repr: isOwnerOrAdminSubstrate(uint256)
function isOwnerOrAdminSubstrate(uint256 user) external view returns (bool);
- // Returns collection type
- //
- // @return `Fungible` or `NFT` or `ReFungible`
- //
- // Selector: uniqueCollectionType() d34b55b8
+ /// Returns collection type
+ ///
+ /// @return `Fungible` or `NFT` or `ReFungible`
+ /// @dev EVM selector for this function is: 0xd34b55b8,
+ /// or in textual repr: uniqueCollectionType()
function uniqueCollectionType() external returns (string memory);
- // Changes collection owner to another account
- //
- // @dev Owner can be changed only by current owner
- // @param newOwner new owner account
- //
- // Selector: setOwner(address) 13af4035
+ /// Changes collection owner to another account
+ ///
+ /// @dev Owner can be changed only by current owner
+ /// @param newOwner new owner account
+ /// @dev EVM selector for this function is: 0x13af4035,
+ /// or in textual repr: setOwner(address)
function setOwner(address newOwner) external;
- // Changes collection owner to another substrate account
- //
- // @dev Owner can be changed only by current owner
- // @param newOwner new owner substrate account
- //
- // Selector: setOwnerSubstrate(uint256) b212138f
+ /// Changes collection owner to another substrate account
+ ///
+ /// @dev Owner can be changed only by current owner
+ /// @param newOwner new owner substrate account
+ /// @dev EVM selector for this function is: 0xb212138f,
+ /// or in textual repr: setOwnerSubstrate(uint256)
function setOwnerSubstrate(uint256 newOwner) external;
}
+/// @dev the ERC-165 identifier for this interface is 0x79cc6790
+interface ERC20UniqueExtensions is Dummy, ERC165 {
+ /// @dev EVM selector for this function is: 0x79cc6790,
+ /// or in textual repr: burnFrom(address,uint256)
+ function burnFrom(address from, uint256 amount) external returns (bool);
+}
+
+/// @dev inlined interface
+interface ERC20Events {
+ event Transfer(address indexed from, address indexed to, uint256 value);
+ event Approval(
+ address indexed owner,
+ address indexed spender,
+ uint256 value
+ );
+}
+
+/// @dev the ERC-165 identifier for this interface is 0x942e8b22
+interface ERC20 is Dummy, ERC165, ERC20Events {
+ /// @dev EVM selector for this function is: 0x06fdde03,
+ /// or in textual repr: name()
+ function name() external view returns (string memory);
+
+ /// @dev EVM selector for this function is: 0x95d89b41,
+ /// or in textual repr: symbol()
+ function symbol() external view returns (string memory);
+
+ /// @dev EVM selector for this function is: 0x18160ddd,
+ /// or in textual repr: totalSupply()
+ function totalSupply() external view returns (uint256);
+
+ /// @dev EVM selector for this function is: 0x313ce567,
+ /// or in textual repr: decimals()
+ function decimals() external view returns (uint8);
+
+ /// @dev EVM selector for this function is: 0x70a08231,
+ /// or in textual repr: balanceOf(address)
+ function balanceOf(address owner) external view returns (uint256);
+
+ /// @dev EVM selector for this function is: 0xa9059cbb,
+ /// or in textual repr: transfer(address,uint256)
+ function transfer(address to, uint256 amount) external returns (bool);
+
+ /// @dev EVM selector for this function is: 0x23b872dd,
+ /// or in textual repr: transferFrom(address,address,uint256)
+ function transferFrom(
+ address from,
+ address to,
+ uint256 amount
+ ) external returns (bool);
+
+ /// @dev EVM selector for this function is: 0x095ea7b3,
+ /// or in textual repr: approve(address,uint256)
+ function approve(address spender, uint256 amount) external returns (bool);
+
+ /// @dev EVM selector for this function is: 0xdd62ed3e,
+ /// or in textual repr: allowance(address,address)
+ function allowance(address owner, address spender)
+ external
+ view
+ returns (uint256);
+}
+
interface UniqueFungible is
Dummy,
ERC165,
tests/src/eth/api/UniqueNFT.soldiffbeforeafterboth334pragma solidity >=0.8.0 <0.9.0;4pragma solidity >=0.8.0 <0.9.0;56// Anonymous struct7struct Tuple0 {8 uint256 field_0;9 string field_1;10}11512// Common stubs holder6/// @dev common stubs holder13interface Dummy {7interface Dummy {14815}9}18 function supportsInterface(bytes4 interfaceID) external view returns (bool);12 function supportsInterface(bytes4 interfaceID) external view returns (bool);19}13}201421// Inline15/// @title A contract that allows to set and delete token properties and change token property permissions.16/// @dev the ERC-165 identifier for this interface is 0x4136937717interface TokenProperties is Dummy, ERC165 {18 /// @notice Set permissions for token property.19 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.20 /// @param key Property key.21 /// @param isMutable Permission to mutate property.22 /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.23 /// @param tokenOwner Permission to mutate property by token owner if property is mutable.24 /// @dev EVM selector for this function is: 0x222d97fa,25 /// or in textual repr: setTokenPropertyPermission(string,bool,bool,bool)26 function setTokenPropertyPermission(27 string memory key,28 bool isMutable,29 bool collectionAdmin,30 bool tokenOwner31 ) external;3233 /// @notice Set token property value.34 /// @dev Throws error if `msg.sender` has no permission to edit the property.35 /// @param tokenId ID of the token.36 /// @param key Property key.37 /// @param value Property value.38 /// @dev EVM selector for this function is: 0x1752d67b,39 /// or in textual repr: setProperty(uint256,string,bytes)40 function setProperty(41 uint256 tokenId,42 string memory key,43 bytes memory value44 ) external;4546 /// @notice Delete token property value.47 /// @dev Throws error if `msg.sender` has no permission to edit the property.48 /// @param tokenId ID of the token.49 /// @param key Property key.50 /// @dev EVM selector for this function is: 0x066111d1,51 /// or in textual repr: deleteProperty(uint256,string)52 function deleteProperty(uint256 tokenId, string memory key) external;5354 /// @notice Get token property value.55 /// @dev Throws error if key not found56 /// @param tokenId ID of the token.57 /// @param key Property key.58 /// @return Property value bytes59 /// @dev EVM selector for this function is: 0x7228c327,60 /// or in textual repr: property(uint256,string)61 function property(uint256 tokenId, string memory key)62 external63 view64 returns (bytes memory);65}6667/// @title A contract that allows you to work with collections.68/// @dev the ERC-165 identifier for this interface is 0xffe4da2369interface Collection is Dummy, ERC165 {70 /// Set collection property.71 ///72 /// @param key Property key.73 /// @param value Propery value.74 /// @dev EVM selector for this function is: 0x2f073f66,75 /// or in textual repr: setCollectionProperty(string,bytes)76 function setCollectionProperty(string memory key, bytes memory value)77 external;7879 /// Delete collection property.80 ///81 /// @param key Property key.82 /// @dev EVM selector for this function is: 0x7b7debce,83 /// or in textual repr: deleteCollectionProperty(string)84 function deleteCollectionProperty(string memory key) external;8586 /// Get collection property.87 ///88 /// @dev Throws error if key not found.89 ///90 /// @param key Property key.91 /// @return bytes The property corresponding to the key.92 /// @dev EVM selector for this function is: 0xcf24fd6d,93 /// or in textual repr: collectionProperty(string)94 function collectionProperty(string memory key)95 external96 view97 returns (bytes memory);9899 /// Set the sponsor of the collection.100 ///101 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.102 ///103 /// @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.104 /// @dev EVM selector for this function is: 0x7623402e,105 /// or in textual repr: setCollectionSponsor(address)106 function setCollectionSponsor(address sponsor) external;107108 /// Collection sponsorship confirmation.109 ///110 /// @dev After setting the sponsor for the collection, it must be confirmed with this function.111 /// @dev EVM selector for this function is: 0x3c50e97a,112 /// or in textual repr: confirmCollectionSponsorship()113 function confirmCollectionSponsorship() external;114115 /// Set limits for the collection.116 /// @dev Throws error if limit not found.117 /// @param limit Name of the limit. Valid names:118 /// "accountTokenOwnershipLimit",119 /// "sponsoredDataSize",120 /// "sponsoredDataRateLimit",121 /// "tokenLimit",122 /// "sponsorTransferTimeout",123 /// "sponsorApproveTimeout"124 /// @param value Value of the limit.125 /// @dev EVM selector for this function is: 0x6a3841db,126 /// or in textual repr: setCollectionLimit(string,uint32)127 function setCollectionLimit(string memory limit, uint32 value) external;128129 /// Set limits for the collection.130 /// @dev Throws error if limit not found.131 /// @param limit Name of the limit. Valid names:132 /// "ownerCanTransfer",133 /// "ownerCanDestroy",134 /// "transfersEnabled"135 /// @param value Value of the limit.136 /// @dev EVM selector for this function is: 0x993b7fba,137 /// or in textual repr: setCollectionLimit(string,bool)138 function setCollectionLimit(string memory limit, bool value) external;139140 /// Get contract address.141 /// @dev EVM selector for this function is: 0xf6b4dfb4,142 /// or in textual repr: contractAddress()143 function contractAddress() external view returns (address);144145 /// Add collection admin by substrate address.146 /// @param newAdmin Substrate administrator address.147 /// @dev EVM selector for this function is: 0x5730062b,148 /// or in textual repr: addCollectionAdminSubstrate(uint256)149 function addCollectionAdminSubstrate(uint256 newAdmin) external;150151 /// Remove collection admin by substrate address.152 /// @param admin Substrate administrator address.153 /// @dev EVM selector for this function is: 0x4048fcf9,154 /// or in textual repr: removeCollectionAdminSubstrate(uint256)155 function removeCollectionAdminSubstrate(uint256 admin) external;156157 /// Add collection admin.158 /// @param newAdmin Address of the added administrator.159 /// @dev EVM selector for this function is: 0x92e462c7,160 /// or in textual repr: addCollectionAdmin(address)161 function addCollectionAdmin(address newAdmin) external;162163 /// Remove collection admin.164 ///165 /// @param admin Address of the removed administrator.166 /// @dev EVM selector for this function is: 0xfafd7b42,167 /// or in textual repr: removeCollectionAdmin(address)168 function removeCollectionAdmin(address admin) external;169170 /// Toggle accessibility of collection nesting.171 ///172 /// @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'173 /// @dev EVM selector for this function is: 0x112d4586,174 /// or in textual repr: setCollectionNesting(bool)175 function setCollectionNesting(bool enable) external;176177 /// Toggle accessibility of collection nesting.178 ///179 /// @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'180 /// @param collections Addresses of collections that will be available for nesting.181 /// @dev EVM selector for this function is: 0x64872396,182 /// or in textual repr: setCollectionNesting(bool,address[])183 function setCollectionNesting(bool enable, address[] memory collections)184 external;185186 /// Set the collection access method.187 /// @param mode Access mode188 /// 0 for Normal189 /// 1 for AllowList190 /// @dev EVM selector for this function is: 0x41835d4c,191 /// or in textual repr: setCollectionAccess(uint8)192 function setCollectionAccess(uint8 mode) external;193194 /// Add the user to the allowed list.195 ///196 /// @param user Address of a trusted user.197 /// @dev EVM selector for this function is: 0x67844fe6,198 /// or in textual repr: addToCollectionAllowList(address)199 function addToCollectionAllowList(address user) external;200201 /// Remove the user from the allowed list.202 ///203 /// @param user Address of a removed user.204 /// @dev EVM selector for this function is: 0x85c51acb,205 /// or in textual repr: removeFromCollectionAllowList(address)206 function removeFromCollectionAllowList(address user) external;207208 /// Switch permission for minting.209 ///210 /// @param mode Enable if "true".211 /// @dev EVM selector for this function is: 0x00018e84,212 /// or in textual repr: setCollectionMintMode(bool)213 function setCollectionMintMode(bool mode) external;214215 /// Check that account is the owner or admin of the collection216 ///217 /// @param user account to verify218 /// @return "true" if account is the owner or admin219 /// @dev EVM selector for this function is: 0x9811b0c7,220 /// or in textual repr: isOwnerOrAdmin(address)221 function isOwnerOrAdmin(address user) external view returns (bool);222223 /// Check that substrate account is the owner or admin of the collection224 ///225 /// @param user account to verify226 /// @return "true" if account is the owner or admin227 /// @dev EVM selector for this function is: 0x68910e00,228 /// or in textual repr: isOwnerOrAdminSubstrate(uint256)229 function isOwnerOrAdminSubstrate(uint256 user) external view returns (bool);230231 /// Returns collection type232 ///233 /// @return `Fungible` or `NFT` or `ReFungible`234 /// @dev EVM selector for this function is: 0xd34b55b8,235 /// or in textual repr: uniqueCollectionType()236 function uniqueCollectionType() external returns (string memory);237238 /// Changes collection owner to another account239 ///240 /// @dev Owner can be changed only by current owner241 /// @param newOwner new owner account242 /// @dev EVM selector for this function is: 0x13af4035,243 /// or in textual repr: setOwner(address)244 function setOwner(address newOwner) external;245246 /// Changes collection owner to another substrate account247 ///248 /// @dev Owner can be changed only by current owner249 /// @param newOwner new owner substrate account250 /// @dev EVM selector for this function is: 0xb212138f,251 /// or in textual repr: setOwnerSubstrate(uint256)252 function setOwnerSubstrate(uint256 newOwner) external;253}254255/// @title ERC721 Token that can be irreversibly burned (destroyed).256/// @dev the ERC-165 identifier for this interface is 0x42966c68257interface ERC721Burnable is Dummy, ERC165 {258 /// @notice Burns a specific ERC721 token.259 /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized260 /// operator of the current owner.261 /// @param tokenId The NFT to approve262 /// @dev EVM selector for this function is: 0x42966c68,263 /// or in textual repr: burn(uint256)264 function burn(uint256 tokenId) external;265}266267/// @dev inlined interface268interface ERC721MintableEvents {269 event MintingFinished();270}271272/// @title ERC721 minting logic.273/// @dev the ERC-165 identifier for this interface is 0x68ccfe89274interface ERC721Mintable is Dummy, ERC165, ERC721MintableEvents {275 /// @dev EVM selector for this function is: 0x05d2035b,276 /// or in textual repr: mintingFinished()277 function mintingFinished() external view returns (bool);278279 /// @notice Function to mint token.280 /// @dev `tokenId` should be obtained with `nextTokenId` method,281 /// unlike standard, you can't specify it manually282 /// @param to The new owner283 /// @param tokenId ID of the minted NFT284 /// @dev EVM selector for this function is: 0x40c10f19,285 /// or in textual repr: mint(address,uint256)286 function mint(address to, uint256 tokenId) external returns (bool);287288 /// @notice Function to mint token with the given tokenUri.289 /// @dev `tokenId` should be obtained with `nextTokenId` method,290 /// unlike standard, you can't specify it manually291 /// @param to The new owner292 /// @param tokenId ID of the minted NFT293 /// @param tokenUri Token URI that would be stored in the NFT properties294 /// @dev EVM selector for this function is: 0x50bb4e7f,295 /// or in textual repr: mintWithTokenURI(address,uint256,string)296 function mintWithTokenURI(297 address to,298 uint256 tokenId,299 string memory tokenUri300 ) external returns (bool);301302 /// @dev Not implemented303 /// @dev EVM selector for this function is: 0x7d64bcb4,304 /// or in textual repr: finishMinting()305 function finishMinting() external returns (bool);306}307308/// @title Unique extensions for ERC721.309/// @dev the ERC-165 identifier for this interface is 0xd74d154f310interface ERC721UniqueExtensions is Dummy, ERC165 {311 /// @notice Transfer ownership of an NFT312 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`313 /// is the zero address. Throws if `tokenId` is not a valid NFT.314 /// @param to The new owner315 /// @param tokenId The NFT to transfer316 /// @dev EVM selector for this function is: 0xa9059cbb,317 /// or in textual repr: transfer(address,uint256)318 function transfer(address to, uint256 tokenId) external;319320 /// @notice Burns a specific ERC721 token.321 /// @dev Throws unless `msg.sender` is the current owner or an authorized322 /// operator for this NFT. Throws if `from` is not the current owner. Throws323 /// if `to` is the zero address. Throws if `tokenId` is not a valid NFT.324 /// @param from The current owner of the NFT325 /// @param tokenId The NFT to transfer326 /// @dev EVM selector for this function is: 0x79cc6790,327 /// or in textual repr: burnFrom(address,uint256)328 function burnFrom(address from, uint256 tokenId) external;329330 /// @notice Returns next free NFT ID.331 /// @dev EVM selector for this function is: 0x75794a3c,332 /// or in textual repr: nextTokenId()333 function nextTokenId() external view returns (uint256);334335 /// @notice Function to mint multiple tokens.336 /// @dev `tokenIds` should be an array of consecutive numbers and first number337 /// should be obtained with `nextTokenId` method338 /// @param to The new owner339 /// @param tokenIds IDs of the minted NFTs340 /// @dev EVM selector for this function is: 0x44a9945e,341 /// or in textual repr: mintBulk(address,uint256[])342 function mintBulk(address to, uint256[] memory tokenIds)343 external344 returns (bool);345346 /// @notice Function to mint multiple tokens with the given tokenUris.347 /// @dev `tokenIds` is array of pairs of token ID and token URI. Token IDs should be consecutive348 /// numbers and first number should be obtained with `nextTokenId` method349 /// @param to The new owner350 /// @param tokens array of pairs of token ID and token URI for minted tokens351 /// @dev EVM selector for this function is: 0x36543006,352 /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])353 function mintBulkWithTokenURI(address to, Tuple8[] memory tokens)354 external355 returns (bool);356}357358/// @dev anonymous struct359struct Tuple8 {360 uint256 field_0;361 string field_1;362}363364/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension365/// @dev See https://eips.ethereum.org/EIPS/eip-721366/// @dev the ERC-165 identifier for this interface is 0x780e9d63367interface ERC721Enumerable is Dummy, ERC165 {368 /// @notice Enumerate valid NFTs369 /// @param index A counter less than `totalSupply()`370 /// @return The token identifier for the `index`th NFT,371 /// (sort order not specified)372 /// @dev EVM selector for this function is: 0x4f6ccce7,373 /// or in textual repr: tokenByIndex(uint256)374 function tokenByIndex(uint256 index) external view returns (uint256);375376 /// @dev Not implemented377 /// @dev EVM selector for this function is: 0x2f745c59,378 /// or in textual repr: tokenOfOwnerByIndex(address,uint256)379 function tokenOfOwnerByIndex(address owner, uint256 index)380 external381 view382 returns (uint256);383384 /// @notice Count NFTs tracked by this contract385 /// @return A count of valid NFTs tracked by this contract, where each one of386 /// them has an assigned and queryable owner not equal to the zero address387 /// @dev EVM selector for this function is: 0x18160ddd,388 /// or in textual repr: totalSupply()389 function totalSupply() external view returns (uint256);390}391392/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension393/// @dev See https://eips.ethereum.org/EIPS/eip-721394/// @dev the ERC-165 identifier for this interface is 0x5b5e139f395interface ERC721Metadata is Dummy, ERC165 {396 /// @notice A descriptive name for a collection of NFTs in this contract397 /// @dev EVM selector for this function is: 0x06fdde03,398 /// or in textual repr: name()399 function name() external view returns (string memory);400401 /// @notice An abbreviated name for NFTs in this contract402 /// @dev EVM selector for this function is: 0x95d89b41,403 /// or in textual repr: symbol()404 function symbol() external view returns (string memory);405406 /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.407 ///408 /// @dev If the token has a `url` property and it is not empty, it is returned.409 /// Else If the collection does not have a property with key `schemaName` or its value is not equal to `ERC721Metadata`, it return an error `tokenURI not set`.410 /// If the collection property `baseURI` is empty or absent, return "" (empty string)411 /// otherwise, if token property `suffix` present and is non-empty, return concatenation of baseURI and suffix412 /// otherwise, return concatenation of `baseURI` and stringified token id (decimal stringifying, without paddings).413 ///414 /// @return token's const_metadata415 /// @dev EVM selector for this function is: 0xc87b56dd,416 /// or in textual repr: tokenURI(uint256)417 function tokenURI(uint256 tokenId) external view returns (string memory);418}419420/// @dev inlined interface22interface ERC721Events {421interface ERC721Events {23 event Transfer(422 event Transfer(24 address indexed from,423 address indexed from,37 );436 );38}437}3943840// Inline439/// @title ERC-721 Non-Fungible Token Standard41interface ERC721MintableEvents {440/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md42 event MintingFinished();441/// @dev the ERC-165 identifier for this interface is 0x80ac58cd43}4445// Selector: 4136937746interface TokenProperties is Dummy, ERC165 {47 // @notice Set permissions for token property.48 // @dev Throws error if `msg.sender` is not admin or owner of the collection.49 // @param key Property key.50 // @param is_mutable Permission to mutate property.51 // @param collection_admin Permission to mutate property by collection admin if property is mutable.52 // @param token_owner Permission to mutate property by token owner if property is mutable.53 //54 // Selector: setTokenPropertyPermission(string,bool,bool,bool) 222d97fa55 function setTokenPropertyPermission(56 string memory key,57 bool isMutable,58 bool collectionAdmin,59 bool tokenOwner60 ) external;6162 // @notice Set token property value.63 // @dev Throws error if `msg.sender` has no permission to edit the property.64 // @param tokenId ID of the token.65 // @param key Property key.66 // @param value Property value.67 //68 // Selector: setProperty(uint256,string,bytes) 1752d67b69 function setProperty(70 uint256 tokenId,71 string memory key,72 bytes memory value73 ) external;7475 // @notice Delete token property value.76 // @dev Throws error if `msg.sender` has no permission to edit the property.77 // @param tokenId ID of the token.78 // @param key Property key.79 //80 // Selector: deleteProperty(uint256,string) 066111d181 function deleteProperty(uint256 tokenId, string memory key) external;8283 // @notice Get token property value.84 // @dev Throws error if key not found85 // @param tokenId ID of the token.86 // @param key Property key.87 // @return Property value bytes88 //89 // Selector: property(uint256,string) 7228c32790 function property(uint256 tokenId, string memory key)91 external92 view93 returns (bytes memory);94}9596// Selector: 42966c6897interface ERC721Burnable is Dummy, ERC165 {98 // @notice Burns a specific ERC721 token.99 // @dev Throws unless `msg.sender` is the current NFT owner, or an authorized100 // operator of the current owner.101 // @param tokenId The NFT to approve102 //103 // Selector: burn(uint256) 42966c68104 function burn(uint256 tokenId) external;105}106107// Selector: 58800161108interface ERC721 is Dummy, ERC165, ERC721Events {442interface ERC721 is Dummy, ERC165, ERC721Events {109 // @notice Count all NFTs assigned to an owner443 /// @notice Count all NFTs assigned to an owner110 // @dev NFTs assigned to the zero address are considered invalid, and this444 /// @dev NFTs assigned to the zero address are considered invalid, and this111 // function throws for queries about the zero address.445 /// function throws for queries about the zero address.112 // @param owner An address for whom to query the balance446 /// @param owner An address for whom to query the balance113 // @return The number of NFTs owned by `owner`, possibly zero447 /// @return The number of NFTs owned by `owner`, possibly zero114 //448 /// @dev EVM selector for this function is: 0x70a08231,115 // Selector: balanceOf(address) 70a08231449 /// or in textual repr: balanceOf(address)116 function balanceOf(address owner) external view returns (uint256);450 function balanceOf(address owner) external view returns (uint256);117451118 // @notice Find the owner of an NFT452 /// @notice Find the owner of an NFT119 // @dev NFTs assigned to zero address are considered invalid, and queries453 /// @dev NFTs assigned to zero address are considered invalid, and queries120 // about them do throw.454 /// about them do throw.121 // @param tokenId The identifier for an NFT455 /// @param tokenId The identifier for an NFT122 // @return The address of the owner of the NFT456 /// @return The address of the owner of the NFT123 //457 /// @dev EVM selector for this function is: 0x6352211e,124 // Selector: ownerOf(uint256) 6352211e458 /// or in textual repr: ownerOf(uint256)125 function ownerOf(uint256 tokenId) external view returns (address);459 function ownerOf(uint256 tokenId) external view returns (address);126460127 // @dev Not implemented461 /// @dev Not implemented128 //462 /// @dev EVM selector for this function is: 0xb88d4fde,129 // Selector: safeTransferFromWithData(address,address,uint256,bytes) 60a11672463 /// or in textual repr: safeTransferFrom(address,address,uint256,bytes)130 function safeTransferFromWithData(464 function safeTransferFrom(131 address from,465 address from,132 address to,466 address to,133 uint256 tokenId,467 uint256 tokenId,134 bytes memory data468 bytes memory data135 ) external;469 ) external;136470137 // @dev Not implemented471 /// @dev Not implemented138 //472 /// @dev EVM selector for this function is: 0x42842e0e,139 // Selector: safeTransferFrom(address,address,uint256) 42842e0e473 /// or in textual repr: safeTransferFrom(address,address,uint256)140 function safeTransferFrom(474 function safeTransferFrom(141 address from,475 address from,142 address to,476 address to,143 uint256 tokenId477 uint256 tokenId144 ) external;478 ) external;145479146 // @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE480 /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE147 // TO CONFIRM THAT `to` IS CAPABLE OF RECEIVING NFTS OR ELSE481 /// TO CONFIRM THAT `to` IS CAPABLE OF RECEIVING NFTS OR ELSE148 // THEY MAY BE PERMANENTLY LOST482 /// THEY MAY BE PERMANENTLY LOST149 // @dev Throws unless `msg.sender` is the current owner or an authorized483 /// @dev Throws unless `msg.sender` is the current owner or an authorized150 // operator for this NFT. Throws if `from` is not the current owner. Throws484 /// operator for this NFT. Throws if `from` is not the current owner. Throws151 // if `to` is the zero address. Throws if `tokenId` is not a valid NFT.485 /// if `to` is the zero address. Throws if `tokenId` is not a valid NFT.152 // @param from The current owner of the NFT486 /// @param from The current owner of the NFT153 // @param to The new owner487 /// @param to The new owner154 // @param tokenId The NFT to transfer488 /// @param tokenId The NFT to transfer155 // @param _value Not used for an NFT489 /// @dev EVM selector for this function is: 0x23b872dd,156 //157 // Selector: transferFrom(address,address,uint256) 23b872dd490 /// or in textual repr: transferFrom(address,address,uint256)158 function transferFrom(491 function transferFrom(159 address from,492 address from,160 address to,493 address to,161 uint256 tokenId494 uint256 tokenId162 ) external;495 ) external;163496164 // @notice Set or reaffirm the approved address for an NFT497 /// @notice Set or reaffirm the approved address for an NFT165 // @dev The zero address indicates there is no approved address.498 /// @dev The zero address indicates there is no approved address.166 // @dev Throws unless `msg.sender` is the current NFT owner, or an authorized499 /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized167 // operator of the current owner.500 /// operator of the current owner.168 // @param approved The new approved NFT controller501 /// @param approved The new approved NFT controller169 // @param tokenId The NFT to approve502 /// @param tokenId The NFT to approve170 //503 /// @dev EVM selector for this function is: 0x095ea7b3,171 // Selector: approve(address,uint256) 095ea7b3504 /// or in textual repr: approve(address,uint256)172 function approve(address approved, uint256 tokenId) external;505 function approve(address approved, uint256 tokenId) external;173506174 // @dev Not implemented507 /// @dev Not implemented175 //508 /// @dev EVM selector for this function is: 0xa22cb465,176 // Selector: setApprovalForAll(address,bool) a22cb465509 /// or in textual repr: setApprovalForAll(address,bool)177 function setApprovalForAll(address operator, bool approved) external;510 function setApprovalForAll(address operator, bool approved) external;178511179 // @dev Not implemented512 /// @dev Not implemented180 //513 /// @dev EVM selector for this function is: 0x081812fc,181 // Selector: getApproved(uint256) 081812fc514 /// or in textual repr: getApproved(uint256)182 function getApproved(uint256 tokenId) external view returns (address);515 function getApproved(uint256 tokenId) external view returns (address);183516184 // @dev Not implemented517 /// @dev Not implemented185 //518 /// @dev EVM selector for this function is: 0xe985e9c5,186 // Selector: isApprovedForAll(address,address) e985e9c5519 /// or in textual repr: isApprovedForAll(address,address)187 function isApprovedForAll(address owner, address operator)520 function isApprovedForAll(address owner, address operator)188 external521 external189 view522 view190 returns (address);523 returns (address);191}524}192193// Selector: 5b5e139f194interface ERC721Metadata is Dummy, ERC165 {195 // @notice A descriptive name for a collection of NFTs in this contract196 //197 // Selector: name() 06fdde03198 function name() external view returns (string memory);199200 // @notice An abbreviated name for NFTs in this contract201 //202 // Selector: symbol() 95d89b41203 function symbol() external view returns (string memory);204205 // @notice A distinct Uniform Resource Identifier (URI) for a given asset.206 //207 // @dev If the token has a `url` property and it is not empty, it is returned.208 // Else If the collection does not have a property with key `schemaName` or its value is not equal to `ERC721Metadata`, it return an error `tokenURI not set`.209 // If the collection property `baseURI` is empty or absent, return "" (empty string)210 // otherwise, if token property `suffix` present and is non-empty, return concatenation of baseURI and suffix211 // otherwise, return concatenation of `baseURI` and stringified token id (decimal stringifying, without paddings).212 //213 // @return token's const_metadata214 //215 // Selector: tokenURI(uint256) c87b56dd216 function tokenURI(uint256 tokenId) external view returns (string memory);217}218219// Selector: 68ccfe89220interface ERC721Mintable is Dummy, ERC165, ERC721MintableEvents {221 // Selector: mintingFinished() 05d2035b222 function mintingFinished() external view returns (bool);223224 // @notice Function to mint token.225 // @dev `tokenId` should be obtained with `nextTokenId` method,226 // unlike standard, you can't specify it manually227 // @param to The new owner228 // @param tokenId ID of the minted NFT229 //230 // Selector: mint(address,uint256) 40c10f19231 function mint(address to, uint256 tokenId) external returns (bool);232233 // @notice Function to mint token with the given tokenUri.234 // @dev `tokenId` should be obtained with `nextTokenId` method,235 // unlike standard, you can't specify it manually236 // @param to The new owner237 // @param tokenId ID of the minted NFT238 // @param tokenUri Token URI that would be stored in the NFT properties239 //240 // Selector: mintWithTokenURI(address,uint256,string) 50bb4e7f241 function mintWithTokenURI(242 address to,243 uint256 tokenId,244 string memory tokenUri245 ) external returns (bool);246247 // @dev Not implemented248 //249 // Selector: finishMinting() 7d64bcb4250 function finishMinting() external returns (bool);251}252253// Selector: 780e9d63254interface ERC721Enumerable is Dummy, ERC165 {255 // @notice Enumerate valid NFTs256 // @param index A counter less than `totalSupply()`257 // @return The token identifier for the `index`th NFT,258 // (sort order not specified)259 //260 // Selector: tokenByIndex(uint256) 4f6ccce7261 function tokenByIndex(uint256 index) external view returns (uint256);262263 // @dev Not implemented264 //265 // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59266 function tokenOfOwnerByIndex(address owner, uint256 index)267 external268 view269 returns (uint256);270271 // @notice Count NFTs tracked by this contract272 // @return A count of valid NFTs tracked by this contract, where each one of273 // them has an assigned and queryable owner not equal to the zero address274 //275 // Selector: totalSupply() 18160ddd276 function totalSupply() external view returns (uint256);277}278279// Selector: d74d154f280interface ERC721UniqueExtensions is Dummy, ERC165 {281 // @notice Transfer ownership of an NFT282 // @dev Throws unless `msg.sender` is the current owner. Throws if `to`283 // is the zero address. Throws if `tokenId` is not a valid NFT.284 // @param to The new owner285 // @param tokenId The NFT to transfer286 // @param _value Not used for an NFT287 //288 // Selector: transfer(address,uint256) a9059cbb289 function transfer(address to, uint256 tokenId) external;290291 // @notice Burns a specific ERC721 token.292 // @dev Throws unless `msg.sender` is the current owner or an authorized293 // operator for this NFT. Throws if `from` is not the current owner. Throws294 // if `to` is the zero address. Throws if `tokenId` is not a valid NFT.295 // @param from The current owner of the NFT296 // @param tokenId The NFT to transfer297 // @param _value Not used for an NFT298 //299 // Selector: burnFrom(address,uint256) 79cc6790300 function burnFrom(address from, uint256 tokenId) external;301302 // @notice Returns next free NFT ID.303 //304 // Selector: nextTokenId() 75794a3c305 function nextTokenId() external view returns (uint256);306307 // @notice Function to mint multiple tokens.308 // @dev `tokenIds` should be an array of consecutive numbers and first number309 // should be obtained with `nextTokenId` method310 // @param to The new owner311 // @param tokenIds IDs of the minted NFTs312 //313 // Selector: mintBulk(address,uint256[]) 44a9945e314 function mintBulk(address to, uint256[] memory tokenIds)315 external316 returns (bool);317318 // @notice Function to mint multiple tokens with the given tokenUris.319 // @dev `tokenIds` is array of pairs of token ID and token URI. Token IDs should be consecutive320 // numbers and first number should be obtained with `nextTokenId` method321 // @param to The new owner322 // @param tokens array of pairs of token ID and token URI for minted tokens323 //324 // Selector: mintBulkWithTokenURI(address,(uint256,string)[]) 36543006325 function mintBulkWithTokenURI(address to, Tuple0[] memory tokens)326 external327 returns (bool);328}329330// Selector: ffe4da23331interface Collection is Dummy, ERC165 {332 // Set collection property.333 //334 // @param key Property key.335 // @param value Propery value.336 //337 // Selector: setCollectionProperty(string,bytes) 2f073f66338 function setCollectionProperty(string memory key, bytes memory value)339 external;340341 // Delete collection property.342 //343 // @param key Property key.344 //345 // Selector: deleteCollectionProperty(string) 7b7debce346 function deleteCollectionProperty(string memory key) external;347348 // Get collection property.349 //350 // @dev Throws error if key not found.351 //352 // @param key Property key.353 // @return bytes The property corresponding to the key.354 //355 // Selector: collectionProperty(string) cf24fd6d356 function collectionProperty(string memory key)357 external358 view359 returns (bytes memory);360361 // Set the sponsor of the collection.362 //363 // @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.364 //365 // @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.366 //367 // Selector: setCollectionSponsor(address) 7623402e368 function setCollectionSponsor(address sponsor) external;369370 // Collection sponsorship confirmation.371 //372 // @dev After setting the sponsor for the collection, it must be confirmed with this function.373 //374 // Selector: confirmCollectionSponsorship() 3c50e97a375 function confirmCollectionSponsorship() external;376377 // Set limits for the collection.378 // @dev Throws error if limit not found.379 // @param limit Name of the limit. Valid names:380 // "accountTokenOwnershipLimit",381 // "sponsoredDataSize",382 // "sponsoredDataRateLimit",383 // "tokenLimit",384 // "sponsorTransferTimeout",385 // "sponsorApproveTimeout"386 // @param value Value of the limit.387 //388 // Selector: setCollectionLimit(string,uint32) 6a3841db389 function setCollectionLimit(string memory limit, uint32 value) external;390391 // Set limits for the collection.392 // @dev Throws error if limit not found.393 // @param limit Name of the limit. Valid names:394 // "ownerCanTransfer",395 // "ownerCanDestroy",396 // "transfersEnabled"397 // @param value Value of the limit.398 //399 // Selector: setCollectionLimit(string,bool) 993b7fba400 function setCollectionLimit(string memory limit, bool value) external;401402 // Get contract address.403 //404 // Selector: contractAddress() f6b4dfb4405 function contractAddress() external view returns (address);406407 // Add collection admin by substrate address.408 // @param new_admin Substrate administrator address.409 //410 // Selector: addCollectionAdminSubstrate(uint256) 5730062b411 function addCollectionAdminSubstrate(uint256 newAdmin) external;412413 // Remove collection admin by substrate address.414 // @param admin Substrate administrator address.415 //416 // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9417 function removeCollectionAdminSubstrate(uint256 admin) external;418419 // Add collection admin.420 // @param new_admin Address of the added administrator.421 //422 // Selector: addCollectionAdmin(address) 92e462c7423 function addCollectionAdmin(address newAdmin) external;424425 // Remove collection admin.426 //427 // @param new_admin Address of the removed administrator.428 //429 // Selector: removeCollectionAdmin(address) fafd7b42430 function removeCollectionAdmin(address admin) external;431432 // Toggle accessibility of collection nesting.433 //434 // @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'435 //436 // Selector: setCollectionNesting(bool) 112d4586437 function setCollectionNesting(bool enable) external;438439 // Toggle accessibility of collection nesting.440 //441 // @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'442 // @param collections Addresses of collections that will be available for nesting.443 //444 // Selector: setCollectionNesting(bool,address[]) 64872396445 function setCollectionNesting(bool enable, address[] memory collections)446 external;447448 // Set the collection access method.449 // @param mode Access mode450 // 0 for Normal451 // 1 for AllowList452 //453 // Selector: setCollectionAccess(uint8) 41835d4c454 function setCollectionAccess(uint8 mode) external;455456 // Add the user to the allowed list.457 //458 // @param user Address of a trusted user.459 //460 // Selector: addToCollectionAllowList(address) 67844fe6461 function addToCollectionAllowList(address user) external;462463 // Remove the user from the allowed list.464 //465 // @param user Address of a removed user.466 //467 // Selector: removeFromCollectionAllowList(address) 85c51acb468 function removeFromCollectionAllowList(address user) external;469470 // Switch permission for minting.471 //472 // @param mode Enable if "true".473 //474 // Selector: setCollectionMintMode(bool) 00018e84475 function setCollectionMintMode(bool mode) external;476477 // Check that account is the owner or admin of the collection478 //479 // @param user account to verify480 // @return "true" if account is the owner or admin481 //482 // Selector: isOwnerOrAdmin(address) 9811b0c7483 function isOwnerOrAdmin(address user) external view returns (bool);484485 // Check that substrate account is the owner or admin of the collection486 //487 // @param user account to verify488 // @return "true" if account is the owner or admin489 //490 // Selector: isOwnerOrAdminSubstrate(uint256) 68910e00491 function isOwnerOrAdminSubstrate(uint256 user) external view returns (bool);492493 // Returns collection type494 //495 // @return `Fungible` or `NFT` or `ReFungible`496 //497 // Selector: uniqueCollectionType() d34b55b8498 function uniqueCollectionType() external returns (string memory);499500 // Changes collection owner to another account501 //502 // @dev Owner can be changed only by current owner503 // @param newOwner new owner account504 //505 // Selector: setOwner(address) 13af4035506 function setOwner(address newOwner) external;507508 // Changes collection owner to another substrate account509 //510 // @dev Owner can be changed only by current owner511 // @param newOwner new owner substrate account512 //513 // Selector: setOwnerSubstrate(uint256) b212138f514 function setOwnerSubstrate(uint256 newOwner) external;515}516525517interface UniqueNFT is526interface UniqueNFT is518 Dummy,527 Dummy,tests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueRefungible.sol
+++ b/tests/src/eth/api/UniqueRefungible.sol
@@ -3,13 +3,7 @@
pragma solidity >=0.8.0 <0.9.0;
-// Anonymous struct
-struct Tuple0 {
- uint256 field_0;
- string field_1;
-}
-
-// Common stubs holder
+/// @dev common stubs holder
interface Dummy {
}
@@ -18,40 +12,17 @@
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
-// Inline
-interface ERC721Events {
- event Transfer(
- address indexed from,
- address indexed to,
- uint256 indexed tokenId
- );
- event Approval(
- address indexed owner,
- address indexed approved,
- uint256 indexed tokenId
- );
- event ApprovalForAll(
- address indexed owner,
- address indexed operator,
- bool approved
- );
-}
-
-// Inline
-interface ERC721MintableEvents {
- event MintingFinished();
-}
-
-// Selector: 41369377
+/// @title A contract that allows to set and delete token properties and change token property permissions.
+/// @dev the ERC-165 identifier for this interface is 0x41369377
interface TokenProperties is Dummy, ERC165 {
- // @notice Set permissions for token property.
- // @dev Throws error if `msg.sender` is not admin or owner of the collection.
- // @param key Property key.
- // @param is_mutable Permission to mutate property.
- // @param collection_admin Permission to mutate property by collection admin if property is mutable.
- // @param token_owner Permission to mutate property by token owner if property is mutable.
- //
- // Selector: setTokenPropertyPermission(string,bool,bool,bool) 222d97fa
+ /// @notice Set permissions for token property.
+ /// @dev Throws error if `msg.sender` is not admin or owner of the collection.
+ /// @param key Property key.
+ /// @param isMutable Permission to mutate property.
+ /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.
+ /// @param tokenOwner Permission to mutate property by token owner if property is mutable.
+ /// @dev EVM selector for this function is: 0x222d97fa,
+ /// or in textual repr: setTokenPropertyPermission(string,bool,bool,bool)
function setTokenPropertyPermission(
string memory key,
bool isMutable,
@@ -59,469 +30,505 @@
bool tokenOwner
) external;
- // @notice Set token property value.
- // @dev Throws error if `msg.sender` has no permission to edit the property.
- // @param tokenId ID of the token.
- // @param key Property key.
- // @param value Property value.
- //
- // Selector: setProperty(uint256,string,bytes) 1752d67b
+ /// @notice Set token property value.
+ /// @dev Throws error if `msg.sender` has no permission to edit the property.
+ /// @param tokenId ID of the token.
+ /// @param key Property key.
+ /// @param value Property value.
+ /// @dev EVM selector for this function is: 0x1752d67b,
+ /// or in textual repr: setProperty(uint256,string,bytes)
function setProperty(
uint256 tokenId,
string memory key,
bytes memory value
) external;
- // @notice Delete token property value.
- // @dev Throws error if `msg.sender` has no permission to edit the property.
- // @param tokenId ID of the token.
- // @param key Property key.
- //
- // Selector: deleteProperty(uint256,string) 066111d1
+ /// @notice Delete token property value.
+ /// @dev Throws error if `msg.sender` has no permission to edit the property.
+ /// @param tokenId ID of the token.
+ /// @param key Property key.
+ /// @dev EVM selector for this function is: 0x066111d1,
+ /// or in textual repr: deleteProperty(uint256,string)
function deleteProperty(uint256 tokenId, string memory key) external;
- // @notice Get token property value.
- // @dev Throws error if key not found
- // @param tokenId ID of the token.
- // @param key Property key.
- // @return Property value bytes
- //
- // Selector: property(uint256,string) 7228c327
+ /// @notice Get token property value.
+ /// @dev Throws error if key not found
+ /// @param tokenId ID of the token.
+ /// @param key Property key.
+ /// @return Property value bytes
+ /// @dev EVM selector for this function is: 0x7228c327,
+ /// or in textual repr: property(uint256,string)
function property(uint256 tokenId, string memory key)
external
view
returns (bytes memory);
}
-// Selector: 42966c68
-interface ERC721Burnable is Dummy, ERC165 {
- // @notice Burns a specific ERC721 token.
- // @dev Throws unless `msg.sender` is the current RFT owner, or an authorized
- // operator of the current owner.
- // @param tokenId The RFT to approve
- //
- // Selector: burn(uint256) 42966c68
- function burn(uint256 tokenId) external;
-}
+/// @title A contract that allows you to work with collections.
+/// @dev the ERC-165 identifier for this interface is 0xffe4da23
+interface Collection is Dummy, ERC165 {
+ /// Set collection property.
+ ///
+ /// @param key Property key.
+ /// @param value Propery value.
+ /// @dev EVM selector for this function is: 0x2f073f66,
+ /// or in textual repr: setCollectionProperty(string,bytes)
+ function setCollectionProperty(string memory key, bytes memory value)
+ external;
-// Selector: 58800161
-interface ERC721 is Dummy, ERC165, ERC721Events {
- // @notice Count all RFTs assigned to an owner
- // @dev RFTs assigned to the zero address are considered invalid, and this
- // function throws for queries about the zero address.
- // @param owner An address for whom to query the balance
- // @return The number of RFTs owned by `owner`, possibly zero
- //
- // Selector: balanceOf(address) 70a08231
- function balanceOf(address owner) external view returns (uint256);
+ /// Delete collection property.
+ ///
+ /// @param key Property key.
+ /// @dev EVM selector for this function is: 0x7b7debce,
+ /// or in textual repr: deleteCollectionProperty(string)
+ function deleteCollectionProperty(string memory key) external;
- // @notice Find the owner of an RFT
- // @dev RFTs assigned to zero address are considered invalid, and queries
- // about them do throw.
- // Returns special 0xffffffffffffffffffffffffffffffffffffffff address for
- // the tokens that are partially owned.
- // @param tokenId The identifier for an RFT
- // @return The address of the owner of the RFT
- //
- // Selector: ownerOf(uint256) 6352211e
- function ownerOf(uint256 tokenId) external view returns (address);
+ /// Get collection property.
+ ///
+ /// @dev Throws error if key not found.
+ ///
+ /// @param key Property key.
+ /// @return bytes The property corresponding to the key.
+ /// @dev EVM selector for this function is: 0xcf24fd6d,
+ /// or in textual repr: collectionProperty(string)
+ function collectionProperty(string memory key)
+ external
+ view
+ returns (bytes memory);
- // @dev Not implemented
- //
- // Selector: safeTransferFromWithData(address,address,uint256,bytes) 60a11672
- function safeTransferFromWithData(
- address from,
- address to,
- uint256 tokenId,
- bytes memory data
- ) external;
+ /// Set the sponsor of the collection.
+ ///
+ /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.
+ ///
+ /// @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.
+ /// @dev EVM selector for this function is: 0x7623402e,
+ /// or in textual repr: setCollectionSponsor(address)
+ function setCollectionSponsor(address sponsor) external;
- // @dev Not implemented
- //
- // Selector: safeTransferFrom(address,address,uint256) 42842e0e
- function safeTransferFrom(
- address from,
- address to,
- uint256 tokenId
- ) external;
+ /// Collection sponsorship confirmation.
+ ///
+ /// @dev After setting the sponsor for the collection, it must be confirmed with this function.
+ /// @dev EVM selector for this function is: 0x3c50e97a,
+ /// or in textual repr: confirmCollectionSponsorship()
+ function confirmCollectionSponsorship() external;
- // @notice Transfer ownership of an RFT -- THE CALLER IS RESPONSIBLE
- // TO CONFIRM THAT `to` IS CAPABLE OF RECEIVING NFTS OR ELSE
- // THEY MAY BE PERMANENTLY LOST
- // @dev Throws unless `msg.sender` is the current owner or an authorized
- // operator for this RFT. Throws if `from` is not the current owner. Throws
- // if `to` is the zero address. Throws if `tokenId` is not a valid RFT.
- // Throws if RFT pieces have multiple owners.
- // @param from The current owner of the NFT
- // @param to The new owner
- // @param tokenId The NFT to transfer
- // @param _value Not used for an NFT
- //
- // Selector: transferFrom(address,address,uint256) 23b872dd
- function transferFrom(
- address from,
- address to,
- uint256 tokenId
- ) external;
+ /// Set limits for the collection.
+ /// @dev Throws error if limit not found.
+ /// @param limit Name of the limit. Valid names:
+ /// "accountTokenOwnershipLimit",
+ /// "sponsoredDataSize",
+ /// "sponsoredDataRateLimit",
+ /// "tokenLimit",
+ /// "sponsorTransferTimeout",
+ /// "sponsorApproveTimeout"
+ /// @param value Value of the limit.
+ /// @dev EVM selector for this function is: 0x6a3841db,
+ /// or in textual repr: setCollectionLimit(string,uint32)
+ function setCollectionLimit(string memory limit, uint32 value) external;
- // @dev Not implemented
- //
- // Selector: approve(address,uint256) 095ea7b3
- function approve(address approved, uint256 tokenId) external;
+ /// Set limits for the collection.
+ /// @dev Throws error if limit not found.
+ /// @param limit Name of the limit. Valid names:
+ /// "ownerCanTransfer",
+ /// "ownerCanDestroy",
+ /// "transfersEnabled"
+ /// @param value Value of the limit.
+ /// @dev EVM selector for this function is: 0x993b7fba,
+ /// or in textual repr: setCollectionLimit(string,bool)
+ function setCollectionLimit(string memory limit, bool value) external;
- // @dev Not implemented
- //
- // Selector: setApprovalForAll(address,bool) a22cb465
- function setApprovalForAll(address operator, bool approved) external;
+ /// Get contract address.
+ /// @dev EVM selector for this function is: 0xf6b4dfb4,
+ /// or in textual repr: contractAddress()
+ function contractAddress() external view returns (address);
- // @dev Not implemented
- //
- // Selector: getApproved(uint256) 081812fc
- function getApproved(uint256 tokenId) external view returns (address);
+ /// Add collection admin by substrate address.
+ /// @param newAdmin Substrate administrator address.
+ /// @dev EVM selector for this function is: 0x5730062b,
+ /// or in textual repr: addCollectionAdminSubstrate(uint256)
+ function addCollectionAdminSubstrate(uint256 newAdmin) external;
- // @dev Not implemented
- //
- // Selector: isApprovedForAll(address,address) e985e9c5
- function isApprovedForAll(address owner, address operator)
- external
- view
- returns (address);
-}
+ /// Remove collection admin by substrate address.
+ /// @param admin Substrate administrator address.
+ /// @dev EVM selector for this function is: 0x4048fcf9,
+ /// or in textual repr: removeCollectionAdminSubstrate(uint256)
+ function removeCollectionAdminSubstrate(uint256 admin) external;
-// Selector: 5b5e139f
-interface ERC721Metadata is Dummy, ERC165 {
- // @notice A descriptive name for a collection of RFTs in this contract
- //
- // Selector: name() 06fdde03
- function name() external view returns (string memory);
+ /// Add collection admin.
+ /// @param newAdmin Address of the added administrator.
+ /// @dev EVM selector for this function is: 0x92e462c7,
+ /// or in textual repr: addCollectionAdmin(address)
+ function addCollectionAdmin(address newAdmin) external;
- // @notice An abbreviated name for RFTs in this contract
- //
- // Selector: symbol() 95d89b41
- function symbol() external view returns (string memory);
+ /// Remove collection admin.
+ ///
+ /// @param admin Address of the removed administrator.
+ /// @dev EVM selector for this function is: 0xfafd7b42,
+ /// or in textual repr: removeCollectionAdmin(address)
+ function removeCollectionAdmin(address admin) external;
- // @notice A distinct Uniform Resource Identifier (URI) for a given asset.
- //
- // @dev If the token has a `url` property and it is not empty, it is returned.
- // Else If the collection does not have a property with key `schemaName` or its value is not equal to `ERC721Metadata`, it return an error `tokenURI not set`.
- // If the collection property `baseURI` is empty or absent, return "" (empty string)
- // otherwise, if token property `suffix` present and is non-empty, return concatenation of baseURI and suffix
- // otherwise, return concatenation of `baseURI` and stringified token id (decimal stringifying, without paddings).
- //
- // @return token's const_metadata
- //
- // Selector: tokenURI(uint256) c87b56dd
- function tokenURI(uint256 tokenId) external view returns (string memory);
+ /// Toggle accessibility of collection nesting.
+ ///
+ /// @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'
+ /// @dev EVM selector for this function is: 0x112d4586,
+ /// or in textual repr: setCollectionNesting(bool)
+ function setCollectionNesting(bool enable) external;
+
+ /// Toggle accessibility of collection nesting.
+ ///
+ /// @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'
+ /// @param collections Addresses of collections that will be available for nesting.
+ /// @dev EVM selector for this function is: 0x64872396,
+ /// or in textual repr: setCollectionNesting(bool,address[])
+ function setCollectionNesting(bool enable, address[] memory collections)
+ external;
+
+ /// Set the collection access method.
+ /// @param mode Access mode
+ /// 0 for Normal
+ /// 1 for AllowList
+ /// @dev EVM selector for this function is: 0x41835d4c,
+ /// or in textual repr: setCollectionAccess(uint8)
+ function setCollectionAccess(uint8 mode) external;
+
+ /// Add the user to the allowed list.
+ ///
+ /// @param user Address of a trusted user.
+ /// @dev EVM selector for this function is: 0x67844fe6,
+ /// or in textual repr: addToCollectionAllowList(address)
+ function addToCollectionAllowList(address user) external;
+
+ /// Remove the user from the allowed list.
+ ///
+ /// @param user Address of a removed user.
+ /// @dev EVM selector for this function is: 0x85c51acb,
+ /// or in textual repr: removeFromCollectionAllowList(address)
+ function removeFromCollectionAllowList(address user) external;
+
+ /// Switch permission for minting.
+ ///
+ /// @param mode Enable if "true".
+ /// @dev EVM selector for this function is: 0x00018e84,
+ /// or in textual repr: setCollectionMintMode(bool)
+ function setCollectionMintMode(bool mode) external;
+
+ /// Check that account is the owner or admin of the collection
+ ///
+ /// @param user account to verify
+ /// @return "true" if account is the owner or admin
+ /// @dev EVM selector for this function is: 0x9811b0c7,
+ /// or in textual repr: isOwnerOrAdmin(address)
+ function isOwnerOrAdmin(address user) external view returns (bool);
+
+ /// Check that substrate account is the owner or admin of the collection
+ ///
+ /// @param user account to verify
+ /// @return "true" if account is the owner or admin
+ /// @dev EVM selector for this function is: 0x68910e00,
+ /// or in textual repr: isOwnerOrAdminSubstrate(uint256)
+ function isOwnerOrAdminSubstrate(uint256 user) external view returns (bool);
+
+ /// Returns collection type
+ ///
+ /// @return `Fungible` or `NFT` or `ReFungible`
+ /// @dev EVM selector for this function is: 0xd34b55b8,
+ /// or in textual repr: uniqueCollectionType()
+ function uniqueCollectionType() external returns (string memory);
+
+ /// Changes collection owner to another account
+ ///
+ /// @dev Owner can be changed only by current owner
+ /// @param newOwner new owner account
+ /// @dev EVM selector for this function is: 0x13af4035,
+ /// or in textual repr: setOwner(address)
+ function setOwner(address newOwner) external;
+
+ /// Changes collection owner to another substrate account
+ ///
+ /// @dev Owner can be changed only by current owner
+ /// @param newOwner new owner substrate account
+ /// @dev EVM selector for this function is: 0xb212138f,
+ /// or in textual repr: setOwnerSubstrate(uint256)
+ function setOwnerSubstrate(uint256 newOwner) external;
+}
+
+/// @title ERC721 Token that can be irreversibly burned (destroyed).
+/// @dev the ERC-165 identifier for this interface is 0x42966c68
+interface ERC721Burnable is Dummy, ERC165 {
+ /// @notice Burns a specific ERC721 token.
+ /// @dev Throws unless `msg.sender` is the current RFT owner, or an authorized
+ /// operator of the current owner.
+ /// @param tokenId The RFT to approve
+ /// @dev EVM selector for this function is: 0x42966c68,
+ /// or in textual repr: burn(uint256)
+ function burn(uint256 tokenId) external;
}
-// Selector: 68ccfe89
+/// @dev inlined interface
+interface ERC721MintableEvents {
+ event MintingFinished();
+}
+
+/// @title ERC721 minting logic.
+/// @dev the ERC-165 identifier for this interface is 0x68ccfe89
interface ERC721Mintable is Dummy, ERC165, ERC721MintableEvents {
- // Selector: mintingFinished() 05d2035b
+ /// @dev EVM selector for this function is: 0x05d2035b,
+ /// or in textual repr: mintingFinished()
function mintingFinished() external view returns (bool);
- // @notice Function to mint token.
- // @dev `tokenId` should be obtained with `nextTokenId` method,
- // unlike standard, you can't specify it manually
- // @param to The new owner
- // @param tokenId ID of the minted RFT
- //
- // Selector: mint(address,uint256) 40c10f19
+ /// @notice Function to mint token.
+ /// @dev `tokenId` should be obtained with `nextTokenId` method,
+ /// unlike standard, you can't specify it manually
+ /// @param to The new owner
+ /// @param tokenId ID of the minted RFT
+ /// @dev EVM selector for this function is: 0x40c10f19,
+ /// or in textual repr: mint(address,uint256)
function mint(address to, uint256 tokenId) external returns (bool);
- // @notice Function to mint token with the given tokenUri.
- // @dev `tokenId` should be obtained with `nextTokenId` method,
- // unlike standard, you can't specify it manually
- // @param to The new owner
- // @param tokenId ID of the minted RFT
- // @param tokenUri Token URI that would be stored in the RFT properties
- //
- // Selector: mintWithTokenURI(address,uint256,string) 50bb4e7f
+ /// @notice Function to mint token with the given tokenUri.
+ /// @dev `tokenId` should be obtained with `nextTokenId` method,
+ /// unlike standard, you can't specify it manually
+ /// @param to The new owner
+ /// @param tokenId ID of the minted RFT
+ /// @param tokenUri Token URI that would be stored in the RFT properties
+ /// @dev EVM selector for this function is: 0x50bb4e7f,
+ /// or in textual repr: mintWithTokenURI(address,uint256,string)
function mintWithTokenURI(
address to,
uint256 tokenId,
string memory tokenUri
) external returns (bool);
- // @dev Not implemented
- //
- // Selector: finishMinting() 7d64bcb4
+ /// @dev Not implemented
+ /// @dev EVM selector for this function is: 0x7d64bcb4,
+ /// or in textual repr: finishMinting()
function finishMinting() external returns (bool);
}
-
-// Selector: 780e9d63
-interface ERC721Enumerable is Dummy, ERC165 {
- // @notice Enumerate valid RFTs
- // @param index A counter less than `totalSupply()`
- // @return The token identifier for the `index`th NFT,
- // (sort order not specified)
- //
- // Selector: tokenByIndex(uint256) 4f6ccce7
- function tokenByIndex(uint256 index) external view returns (uint256);
- // Not implemented
- //
- // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59
- function tokenOfOwnerByIndex(address owner, uint256 index)
- external
- view
- returns (uint256);
-
- // @notice Count RFTs tracked by this contract
- // @return A count of valid RFTs tracked by this contract, where each one of
- // them has an assigned and queryable owner not equal to the zero address
- //
- // Selector: totalSupply() 18160ddd
- function totalSupply() external view returns (uint256);
-}
-
-// Selector: 7c3bef89
+/// @title Unique extensions for ERC721.
+/// @dev the ERC-165 identifier for this interface is 0x7c3bef89
interface ERC721UniqueExtensions is Dummy, ERC165 {
- // @notice Transfer ownership of an RFT
- // @dev Throws unless `msg.sender` is the current owner. Throws if `to`
- // is the zero address. Throws if `tokenId` is not a valid RFT.
- // Throws if RFT pieces have multiple owners.
- // @param to The new owner
- // @param tokenId The RFT to transfer
- // @param _value Not used for an RFT
- //
- // Selector: transfer(address,uint256) a9059cbb
+ /// @notice Transfer ownership of an RFT
+ /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
+ /// is the zero address. Throws if `tokenId` is not a valid RFT.
+ /// Throws if RFT pieces have multiple owners.
+ /// @param to The new owner
+ /// @param tokenId The RFT to transfer
+ /// @dev EVM selector for this function is: 0xa9059cbb,
+ /// or in textual repr: transfer(address,uint256)
function transfer(address to, uint256 tokenId) external;
- // @notice Burns a specific ERC721 token.
- // @dev Throws unless `msg.sender` is the current owner or an authorized
- // operator for this RFT. Throws if `from` is not the current owner. Throws
- // if `to` is the zero address. Throws if `tokenId` is not a valid RFT.
- // Throws if RFT pieces have multiple owners.
- // @param from The current owner of the RFT
- // @param tokenId The RFT to transfer
- // @param _value Not used for an RFT
- //
- // Selector: burnFrom(address,uint256) 79cc6790
+ /// @notice Burns a specific ERC721 token.
+ /// @dev Throws unless `msg.sender` is the current owner or an authorized
+ /// operator for this RFT. Throws if `from` is not the current owner. Throws
+ /// if `to` is the zero address. Throws if `tokenId` is not a valid RFT.
+ /// Throws if RFT pieces have multiple owners.
+ /// @param from The current owner of the RFT
+ /// @param tokenId The RFT to transfer
+ /// @dev EVM selector for this function is: 0x79cc6790,
+ /// or in textual repr: burnFrom(address,uint256)
function burnFrom(address from, uint256 tokenId) external;
- // @notice Returns next free RFT ID.
- //
- // Selector: nextTokenId() 75794a3c
+ /// @notice Returns next free RFT ID.
+ /// @dev EVM selector for this function is: 0x75794a3c,
+ /// or in textual repr: nextTokenId()
function nextTokenId() external view returns (uint256);
- // @notice Function to mint multiple tokens.
- // @dev `tokenIds` should be an array of consecutive numbers and first number
- // should be obtained with `nextTokenId` method
- // @param to The new owner
- // @param tokenIds IDs of the minted RFTs
- //
- // Selector: mintBulk(address,uint256[]) 44a9945e
+ /// @notice Function to mint multiple tokens.
+ /// @dev `tokenIds` should be an array of consecutive numbers and first number
+ /// should be obtained with `nextTokenId` method
+ /// @param to The new owner
+ /// @param tokenIds IDs of the minted RFTs
+ /// @dev EVM selector for this function is: 0x44a9945e,
+ /// or in textual repr: mintBulk(address,uint256[])
function mintBulk(address to, uint256[] memory tokenIds)
external
returns (bool);
- // @notice Function to mint multiple tokens with the given tokenUris.
- // @dev `tokenIds` is array of pairs of token ID and token URI. Token IDs should be consecutive
- // numbers and first number should be obtained with `nextTokenId` method
- // @param to The new owner
- // @param tokens array of pairs of token ID and token URI for minted tokens
- //
- // Selector: mintBulkWithTokenURI(address,(uint256,string)[]) 36543006
- function mintBulkWithTokenURI(address to, Tuple0[] memory tokens)
+ /// @notice Function to mint multiple tokens with the given tokenUris.
+ /// @dev `tokenIds` is array of pairs of token ID and token URI. Token IDs should be consecutive
+ /// numbers and first number should be obtained with `nextTokenId` method
+ /// @param to The new owner
+ /// @param tokens array of pairs of token ID and token URI for minted tokens
+ /// @dev EVM selector for this function is: 0x36543006,
+ /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])
+ function mintBulkWithTokenURI(address to, Tuple8[] memory tokens)
external
returns (bool);
- // Returns EVM address for refungible token
- //
- // @param token ID of the token
- //
- // Selector: tokenContractAddress(uint256) ab76fac6
+ /// Returns EVM address for refungible token
+ ///
+ /// @param token ID of the token
+ /// @dev EVM selector for this function is: 0xab76fac6,
+ /// or in textual repr: tokenContractAddress(uint256)
function tokenContractAddress(uint256 token)
external
view
returns (address);
}
-// Selector: ffe4da23
-interface Collection is Dummy, ERC165 {
- // Set collection property.
- //
- // @param key Property key.
- // @param value Propery value.
- //
- // Selector: setCollectionProperty(string,bytes) 2f073f66
- function setCollectionProperty(string memory key, bytes memory value)
- external;
+/// @dev anonymous struct
+struct Tuple8 {
+ uint256 field_0;
+ string field_1;
+}
- // Delete collection property.
- //
- // @param key Property key.
- //
- // Selector: deleteCollectionProperty(string) 7b7debce
- function deleteCollectionProperty(string memory key) external;
+/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
+/// @dev See https://eips.ethereum.org/EIPS/eip-721
+/// @dev the ERC-165 identifier for this interface is 0x780e9d63
+interface ERC721Enumerable is Dummy, ERC165 {
+ /// @notice Enumerate valid RFTs
+ /// @param index A counter less than `totalSupply()`
+ /// @return The token identifier for the `index`th NFT,
+ /// (sort order not specified)
+ /// @dev EVM selector for this function is: 0x4f6ccce7,
+ /// or in textual repr: tokenByIndex(uint256)
+ function tokenByIndex(uint256 index) external view returns (uint256);
- // Get collection property.
- //
- // @dev Throws error if key not found.
- //
- // @param key Property key.
- // @return bytes The property corresponding to the key.
- //
- // Selector: collectionProperty(string) cf24fd6d
- function collectionProperty(string memory key)
+ /// Not implemented
+ /// @dev EVM selector for this function is: 0x2f745c59,
+ /// or in textual repr: tokenOfOwnerByIndex(address,uint256)
+ function tokenOfOwnerByIndex(address owner, uint256 index)
external
view
- returns (bytes memory);
+ returns (uint256);
- // Set the sponsor of the collection.
- //
- // @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.
- //
- // @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.
- //
- // Selector: setCollectionSponsor(address) 7623402e
- function setCollectionSponsor(address sponsor) external;
+ /// @notice Count RFTs tracked by this contract
+ /// @return A count of valid RFTs tracked by this contract, where each one of
+ /// them has an assigned and queryable owner not equal to the zero address
+ /// @dev EVM selector for this function is: 0x18160ddd,
+ /// or in textual repr: totalSupply()
+ function totalSupply() external view returns (uint256);
+}
- // Collection sponsorship confirmation.
- //
- // @dev After setting the sponsor for the collection, it must be confirmed with this function.
- //
- // Selector: confirmCollectionSponsorship() 3c50e97a
- function confirmCollectionSponsorship() external;
+/// @dev the ERC-165 identifier for this interface is 0x5b5e139f
+interface ERC721Metadata is Dummy, ERC165 {
+ /// @notice A descriptive name for a collection of RFTs in this contract
+ /// @dev EVM selector for this function is: 0x06fdde03,
+ /// or in textual repr: name()
+ function name() external view returns (string memory);
- // Set limits for the collection.
- // @dev Throws error if limit not found.
- // @param limit Name of the limit. Valid names:
- // "accountTokenOwnershipLimit",
- // "sponsoredDataSize",
- // "sponsoredDataRateLimit",
- // "tokenLimit",
- // "sponsorTransferTimeout",
- // "sponsorApproveTimeout"
- // @param value Value of the limit.
- //
- // Selector: setCollectionLimit(string,uint32) 6a3841db
- function setCollectionLimit(string memory limit, uint32 value) external;
+ /// @notice An abbreviated name for RFTs in this contract
+ /// @dev EVM selector for this function is: 0x95d89b41,
+ /// or in textual repr: symbol()
+ function symbol() external view returns (string memory);
- // Set limits for the collection.
- // @dev Throws error if limit not found.
- // @param limit Name of the limit. Valid names:
- // "ownerCanTransfer",
- // "ownerCanDestroy",
- // "transfersEnabled"
- // @param value Value of the limit.
- //
- // Selector: setCollectionLimit(string,bool) 993b7fba
- function setCollectionLimit(string memory limit, bool value) external;
-
- // Get contract address.
- //
- // Selector: contractAddress() f6b4dfb4
- function contractAddress() external view returns (address);
-
- // Add collection admin by substrate address.
- // @param new_admin Substrate administrator address.
- //
- // Selector: addCollectionAdminSubstrate(uint256) 5730062b
- function addCollectionAdminSubstrate(uint256 newAdmin) external;
+ /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
+ ///
+ /// @dev If the token has a `url` property and it is not empty, it is returned.
+ /// Else If the collection does not have a property with key `schemaName` or its value is not equal to `ERC721Metadata`, it return an error `tokenURI not set`.
+ /// If the collection property `baseURI` is empty or absent, return "" (empty string)
+ /// otherwise, if token property `suffix` present and is non-empty, return concatenation of baseURI and suffix
+ /// otherwise, return concatenation of `baseURI` and stringified token id (decimal stringifying, without paddings).
+ ///
+ /// @return token's const_metadata
+ /// @dev EVM selector for this function is: 0xc87b56dd,
+ /// or in textual repr: tokenURI(uint256)
+ function tokenURI(uint256 tokenId) external view returns (string memory);
+}
- // Remove collection admin by substrate address.
- // @param admin Substrate administrator address.
- //
- // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9
- function removeCollectionAdminSubstrate(uint256 admin) external;
-
- // Add collection admin.
- // @param new_admin Address of the added administrator.
- //
- // Selector: addCollectionAdmin(address) 92e462c7
- function addCollectionAdmin(address newAdmin) external;
-
- // Remove collection admin.
- //
- // @param new_admin Address of the removed administrator.
- //
- // Selector: removeCollectionAdmin(address) fafd7b42
- function removeCollectionAdmin(address admin) external;
-
- // Toggle accessibility of collection nesting.
- //
- // @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'
- //
- // Selector: setCollectionNesting(bool) 112d4586
- function setCollectionNesting(bool enable) external;
-
- // Toggle accessibility of collection nesting.
- //
- // @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'
- // @param collections Addresses of collections that will be available for nesting.
- //
- // Selector: setCollectionNesting(bool,address[]) 64872396
- function setCollectionNesting(bool enable, address[] memory collections)
- external;
+/// @dev inlined interface
+interface ERC721Events {
+ event Transfer(
+ address indexed from,
+ address indexed to,
+ uint256 indexed tokenId
+ );
+ event Approval(
+ address indexed owner,
+ address indexed approved,
+ uint256 indexed tokenId
+ );
+ event ApprovalForAll(
+ address indexed owner,
+ address indexed operator,
+ bool approved
+ );
+}
- // Set the collection access method.
- // @param mode Access mode
- // 0 for Normal
- // 1 for AllowList
- //
- // Selector: setCollectionAccess(uint8) 41835d4c
- function setCollectionAccess(uint8 mode) external;
+/// @title ERC-721 Non-Fungible Token Standard
+/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
+/// @dev the ERC-165 identifier for this interface is 0x58800161
+interface ERC721 is Dummy, ERC165, ERC721Events {
+ /// @notice Count all RFTs assigned to an owner
+ /// @dev RFTs assigned to the zero address are considered invalid, and this
+ /// function throws for queries about the zero address.
+ /// @param owner An address for whom to query the balance
+ /// @return The number of RFTs owned by `owner`, possibly zero
+ /// @dev EVM selector for this function is: 0x70a08231,
+ /// or in textual repr: balanceOf(address)
+ function balanceOf(address owner) external view returns (uint256);
- // Add the user to the allowed list.
- //
- // @param user Address of a trusted user.
- //
- // Selector: addToCollectionAllowList(address) 67844fe6
- function addToCollectionAllowList(address user) external;
+ /// @notice Find the owner of an RFT
+ /// @dev RFTs assigned to zero address are considered invalid, and queries
+ /// about them do throw.
+ /// Returns special 0xffffffffffffffffffffffffffffffffffffffff address for
+ /// the tokens that are partially owned.
+ /// @param tokenId The identifier for an RFT
+ /// @return The address of the owner of the RFT
+ /// @dev EVM selector for this function is: 0x6352211e,
+ /// or in textual repr: ownerOf(uint256)
+ function ownerOf(uint256 tokenId) external view returns (address);
- // Remove the user from the allowed list.
- //
- // @param user Address of a removed user.
- //
- // Selector: removeFromCollectionAllowList(address) 85c51acb
- function removeFromCollectionAllowList(address user) external;
+ /// @dev Not implemented
+ /// @dev EVM selector for this function is: 0x60a11672,
+ /// or in textual repr: safeTransferFromWithData(address,address,uint256,bytes)
+ function safeTransferFromWithData(
+ address from,
+ address to,
+ uint256 tokenId,
+ bytes memory data
+ ) external;
- // Switch permission for minting.
- //
- // @param mode Enable if "true".
- //
- // Selector: setCollectionMintMode(bool) 00018e84
- function setCollectionMintMode(bool mode) external;
+ /// @dev Not implemented
+ /// @dev EVM selector for this function is: 0x42842e0e,
+ /// or in textual repr: safeTransferFrom(address,address,uint256)
+ function safeTransferFrom(
+ address from,
+ address to,
+ uint256 tokenId
+ ) external;
- // Check that account is the owner or admin of the collection
- //
- // @param user account to verify
- // @return "true" if account is the owner or admin
- //
- // Selector: isOwnerOrAdmin(address) 9811b0c7
- function isOwnerOrAdmin(address user) external view returns (bool);
+ /// @notice Transfer ownership of an RFT -- THE CALLER IS RESPONSIBLE
+ /// TO CONFIRM THAT `to` IS CAPABLE OF RECEIVING NFTS OR ELSE
+ /// THEY MAY BE PERMANENTLY LOST
+ /// @dev Throws unless `msg.sender` is the current owner or an authorized
+ /// operator for this RFT. Throws if `from` is not the current owner. Throws
+ /// if `to` is the zero address. Throws if `tokenId` is not a valid RFT.
+ /// Throws if RFT pieces have multiple owners.
+ /// @param from The current owner of the NFT
+ /// @param to The new owner
+ /// @param tokenId The NFT to transfer
+ /// @dev EVM selector for this function is: 0x23b872dd,
+ /// or in textual repr: transferFrom(address,address,uint256)
+ function transferFrom(
+ address from,
+ address to,
+ uint256 tokenId
+ ) external;
- // Check that substrate account is the owner or admin of the collection
- //
- // @param user account to verify
- // @return "true" if account is the owner or admin
- //
- // Selector: isOwnerOrAdminSubstrate(uint256) 68910e00
- function isOwnerOrAdminSubstrate(uint256 user) external view returns (bool);
+ /// @dev Not implemented
+ /// @dev EVM selector for this function is: 0x095ea7b3,
+ /// or in textual repr: approve(address,uint256)
+ function approve(address approved, uint256 tokenId) external;
- // Returns collection type
- //
- // @return `Fungible` or `NFT` or `ReFungible`
- //
- // Selector: uniqueCollectionType() d34b55b8
- function uniqueCollectionType() external returns (string memory);
+ /// @dev Not implemented
+ /// @dev EVM selector for this function is: 0xa22cb465,
+ /// or in textual repr: setApprovalForAll(address,bool)
+ function setApprovalForAll(address operator, bool approved) external;
- // Changes collection owner to another account
- //
- // @dev Owner can be changed only by current owner
- // @param newOwner new owner account
- //
- // Selector: setOwner(address) 13af4035
- function setOwner(address newOwner) external;
+ /// @dev Not implemented
+ /// @dev EVM selector for this function is: 0x081812fc,
+ /// or in textual repr: getApproved(uint256)
+ function getApproved(uint256 tokenId) external view returns (address);
- // Changes collection owner to another substrate account
- //
- // @dev Owner can be changed only by current owner
- // @param newOwner new owner substrate account
- //
- // Selector: setOwnerSubstrate(uint256) b212138f
- function setOwnerSubstrate(uint256 newOwner) external;
+ /// @dev Not implemented
+ /// @dev EVM selector for this function is: 0xe985e9c5,
+ /// or in textual repr: isApprovedForAll(address,address)
+ function isApprovedForAll(address owner, address operator)
+ external
+ view
+ returns (address);
}
interface UniqueRefungible is
tests/src/eth/api/UniqueRefungibleToken.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueRefungibleToken.sol
+++ b/tests/src/eth/api/UniqueRefungibleToken.sol
@@ -3,7 +3,7 @@
pragma solidity >=0.8.0 <0.9.0;
-// Common stubs holder
+/// @dev common stubs holder
interface Dummy {
}
@@ -12,120 +12,127 @@
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
-// Inline
-interface ERC20Events {
- event Transfer(address indexed from, address indexed to, uint256 value);
- event Approval(
- address indexed owner,
- address indexed spender,
- uint256 value
- );
-}
-
-// Selector: 042f1106
+/// @dev the ERC-165 identifier for this interface is 0x042f1106
interface ERC1633UniqueExtensions is Dummy, ERC165 {
- // Selector: setParentNFT(address,uint256) 042f1106
+ /// @dev EVM selector for this function is: 0x042f1106,
+ /// or in textual repr: setParentNFT(address,uint256)
function setParentNFT(address collection, uint256 nftId)
external
returns (bool);
}
-// Selector: 5755c3f2
+/// @dev the ERC-165 identifier for this interface is 0x5755c3f2
interface ERC1633 is Dummy, ERC165 {
- // Selector: parentToken() 80a54001
+ /// @dev EVM selector for this function is: 0x80a54001,
+ /// or in textual repr: parentToken()
function parentToken() external view returns (address);
- // Selector: parentTokenId() d7f083f3
+ /// @dev EVM selector for this function is: 0xd7f083f3,
+ /// or in textual repr: parentTokenId()
function parentTokenId() external view returns (uint256);
}
-// Selector: 942e8b22
+/// @dev the ERC-165 identifier for this interface is 0xab8deb37
+interface ERC20UniqueExtensions is Dummy, ERC165 {
+ /// @dev Function that burns an amount of the token of a given account,
+ /// deducting from the sender's allowance for said account.
+ /// @param from The account whose tokens will be burnt.
+ /// @param amount The amount that will be burnt.
+ /// @dev EVM selector for this function is: 0x79cc6790,
+ /// or in textual repr: burnFrom(address,uint256)
+ function burnFrom(address from, uint256 amount) external returns (bool);
+
+ /// @dev Function that changes total amount of the tokens.
+ /// Throws if `msg.sender` doesn't owns all of the tokens.
+ /// @param amount New total amount of the tokens.
+ /// @dev EVM selector for this function is: 0xd2418ca7,
+ /// or in textual repr: repartition(uint256)
+ function repartition(uint256 amount) external returns (bool);
+}
+
+/// @dev inlined interface
+interface ERC20Events {
+ event Transfer(address indexed from, address indexed to, uint256 value);
+ event Approval(
+ address indexed owner,
+ address indexed spender,
+ uint256 value
+ );
+}
+
+/// @title Standard ERC20 token
+///
+/// @dev Implementation of the basic standard token.
+/// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
+/// @dev the ERC-165 identifier for this interface is 0x942e8b22
interface ERC20 is Dummy, ERC165, ERC20Events {
- // @return the name of the token.
- //
- // Selector: name() 06fdde03
+ /// @return the name of the token.
+ /// @dev EVM selector for this function is: 0x06fdde03,
+ /// or in textual repr: name()
function name() external view returns (string memory);
- // @return the symbol of the token.
- //
- // Selector: symbol() 95d89b41
+ /// @return the symbol of the token.
+ /// @dev EVM selector for this function is: 0x95d89b41,
+ /// or in textual repr: symbol()
function symbol() external view returns (string memory);
- // @dev Total number of tokens in existence
- //
- // Selector: totalSupply() 18160ddd
+ /// @dev Total number of tokens in existence
+ /// @dev EVM selector for this function is: 0x18160ddd,
+ /// or in textual repr: totalSupply()
function totalSupply() external view returns (uint256);
- // @dev Not supported
- //
- // Selector: decimals() 313ce567
+ /// @dev Not supported
+ /// @dev EVM selector for this function is: 0x313ce567,
+ /// or in textual repr: decimals()
function decimals() external view returns (uint8);
- // @dev Gets the balance of the specified address.
- // @param owner The address to query the balance of.
- // @return An uint256 representing the amount owned by the passed address.
- //
- // Selector: balanceOf(address) 70a08231
+ /// @dev Gets the balance of the specified address.
+ /// @param owner The address to query the balance of.
+ /// @return An uint256 representing the amount owned by the passed address.
+ /// @dev EVM selector for this function is: 0x70a08231,
+ /// or in textual repr: balanceOf(address)
function balanceOf(address owner) external view returns (uint256);
- // @dev Transfer token for a specified address
- // @param to The address to transfer to.
- // @param amount The amount to be transferred.
- //
- // Selector: transfer(address,uint256) a9059cbb
+ /// @dev Transfer token for a specified address
+ /// @param to The address to transfer to.
+ /// @param amount The amount to be transferred.
+ /// @dev EVM selector for this function is: 0xa9059cbb,
+ /// or in textual repr: transfer(address,uint256)
function transfer(address to, uint256 amount) external returns (bool);
- // @dev Transfer tokens from one address to another
- // @param from address The address which you want to send tokens from
- // @param to address The address which you want to transfer to
- // @param amount uint256 the amount of tokens to be transferred
- //
- // Selector: transferFrom(address,address,uint256) 23b872dd
+ /// @dev Transfer tokens from one address to another
+ /// @param from address The address which you want to send tokens from
+ /// @param to address The address which you want to transfer to
+ /// @param amount uint256 the amount of tokens to be transferred
+ /// @dev EVM selector for this function is: 0x23b872dd,
+ /// or in textual repr: transferFrom(address,address,uint256)
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
- // @dev Approve the passed address to spend the specified amount of tokens on behalf of `msg.sender`.
- // Beware that changing an allowance with this method brings the risk that someone may use both the old
- // and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
- // race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
- // https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
- // @param spender The address which will spend the funds.
- // @param amount The amount of tokens to be spent.
- //
- // Selector: approve(address,uint256) 095ea7b3
+ /// @dev Approve the passed address to spend the specified amount of tokens on behalf of `msg.sender`.
+ /// Beware that changing an allowance with this method brings the risk that someone may use both the old
+ /// and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
+ /// race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
+ /// https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
+ /// @param spender The address which will spend the funds.
+ /// @param amount The amount of tokens to be spent.
+ /// @dev EVM selector for this function is: 0x095ea7b3,
+ /// or in textual repr: approve(address,uint256)
function approve(address spender, uint256 amount) external returns (bool);
- // @dev Function to check the amount of tokens that an owner allowed to a spender.
- // @param owner address The address which owns the funds.
- // @param spender address The address which will spend the funds.
- // @return A uint256 specifying the amount of tokens still available for the spender.
- //
- // Selector: allowance(address,address) dd62ed3e
+ /// @dev Function to check the amount of tokens that an owner allowed to a spender.
+ /// @param owner address The address which owns the funds.
+ /// @param spender address The address which will spend the funds.
+ /// @return A uint256 specifying the amount of tokens still available for the spender.
+ /// @dev EVM selector for this function is: 0xdd62ed3e,
+ /// or in textual repr: allowance(address,address)
function allowance(address owner, address spender)
external
view
returns (uint256);
-}
-
-// Selector: ab8deb37
-interface ERC20UniqueExtensions is Dummy, ERC165 {
- // @dev Function that burns an amount of the token of a given account,
- // deducting from the sender's allowance for said account.
- // @param from The account whose tokens will be burnt.
- // @param amount The amount that will be burnt.
- //
- // Selector: burnFrom(address,uint256) 79cc6790
- function burnFrom(address from, uint256 amount) external returns (bool);
-
- // @dev Function that changes total amount of the tokens.
- // Throws if `msg.sender` doesn't owns all of the tokens.
- // @param amount New total amount of the tokens.
- //
- // Selector: repartition(uint256) d2418ca7
- function repartition(uint256 amount) external returns (bool);
}
interface UniqueRefungibleToken is
tests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth--- a/tests/src/eth/nonFungibleAbi.json
+++ b/tests/src/eth/nonFungibleAbi.json
@@ -255,7 +255,7 @@
{ "internalType": "uint256", "name": "field_0", "type": "uint256" },
{ "internalType": "string", "name": "field_1", "type": "string" }
],
- "internalType": "struct Tuple0[]",
+ "internalType": "struct Tuple8[]",
"name": "tokens",
"type": "tuple[]"
}
@@ -361,7 +361,7 @@
{ "internalType": "uint256", "name": "tokenId", "type": "uint256" },
{ "internalType": "bytes", "name": "data", "type": "bytes" }
],
- "name": "safeTransferFromWithData",
+ "name": "safeTransferFrom",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
tests/src/eth/reFungibleAbi.jsondiffbeforeafterboth--- a/tests/src/eth/reFungibleAbi.json
+++ b/tests/src/eth/reFungibleAbi.json
@@ -255,7 +255,7 @@
{ "internalType": "uint256", "name": "field_0", "type": "uint256" },
{ "internalType": "string", "name": "field_1", "type": "string" }
],
- "internalType": "struct Tuple0[]",
+ "internalType": "struct Tuple8[]",
"name": "tokens",
"type": "tuple[]"
}
tests/src/eth/util/contractHelpersAbi.jsondiffbeforeafterboth--- a/tests/src/eth/util/contractHelpersAbi.json
+++ b/tests/src/eth/util/contractHelpersAbi.json
@@ -197,19 +197,6 @@
},
{
"inputs": [
- {
- "internalType": "address",
- "name": "contractAddress",
- "type": "address"
- }
- ],
- "name": "sponsoringMode",
- "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }],
- "stateMutability": "view",
- "type": "function"
- },
- {
- "inputs": [
{ "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }
],
"name": "supportsInterface",
@@ -225,7 +212,7 @@
"type": "address"
},
{ "internalType": "address", "name": "user", "type": "address" },
- { "internalType": "bool", "name": "allowed", "type": "bool" }
+ { "internalType": "bool", "name": "isAllowed", "type": "bool" }
],
"name": "toggleAllowed",
"outputs": [],