--- a/Cargo.lock +++ b/Cargo.lock @@ -2330,7 +2330,6 @@ "hex", "hex-literal", "impl-trait-for-tuples", - "pallet-evm", "primitive-types 0.12.1", "sha3-const", "similar-asserts", --- a/crates/evm-coder/Cargo.toml +++ b/crates/evm-coder/Cargo.toml @@ -19,8 +19,6 @@ # We have tuple-heavy code in solidity.rs impl-trait-for-tuples = "0.2.2" -pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.36" } - [dev-dependencies] # We want to assert some large binary blobs equality in tests hex = "0.4.3" --- a/crates/evm-coder/procedural/src/solidity_interface.rs +++ b/crates/evm-coder/procedural/src/solidity_interface.rs @@ -347,14 +347,14 @@ fn is_value(&self) -> bool { if let Ok(ident) = self.plain() { - return ident == "value"; + return ident == "Value"; } false } fn is_caller(&self) -> bool { if let Ok(ident) = self.plain() { - return ident == "caller"; + return ident == "Caller"; } false } @@ -610,7 +610,7 @@ let custom_signature = self.expand_custom_signature(); quote! { const #screaming_name_signature: ::evm_coder::custom_signature::SignatureUnit = #custom_signature; - const #screaming_name: ::evm_coder::types::bytes4 = { + const #screaming_name: ::evm_coder::types::Bytes4 = { let mut sum = ::evm_coder::sha3_const::Keccak256::new(); let mut pos = 0; while pos < Self::#screaming_name_signature.len { @@ -974,7 +974,7 @@ #consts )* /// Return this call ERC165 selector - pub const fn interface_id() -> ::evm_coder::types::bytes4 { + pub const fn interface_id() -> ::evm_coder::types::Bytes4 { let mut interface_id = 0; #(#interface_id)* #(#inline_interface_id)* @@ -999,7 +999,7 @@ )*), }; - let mut out = ::evm_coder::types::string::new(); + let mut out = ::evm_coder::types::String::new(); if #solidity_name.starts_with("Inline") { out.push_str("/// @dev inlined interface\n"); } @@ -1019,7 +1019,7 @@ } } 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> { + fn parse(method_id: ::evm_coder::types::Bytes4, reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result> { use ::evm_coder::abi::AbiRead; match method_id { ::evm_coder::ERC165Call::INTERFACE_ID => return Ok( @@ -1041,7 +1041,7 @@ #gen_where { /// Is this contract implements specified ERC165 selector - pub fn supports_interface(this: &#name, interface_id: ::evm_coder::types::bytes4) -> bool { + pub fn supports_interface(this: &#name, 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() --- a/crates/evm-coder/procedural/src/to_log.rs +++ b/crates/evm-coder/procedural/src/to_log.rs @@ -137,7 +137,7 @@ Self::#name {#( #fields, )*} => { - topics.push(topic::from(Self::#name_screaming)); + topics.push(::evm_coder::types::Topic::from(Self::#name_screaming)); #( topics.push(#indexed.to_topic()); )* @@ -222,7 +222,7 @@ #solidity_functions, )*), }; - let mut out = string::new(); + let mut out = ::evm_coder::types::String::new(); out.push_str("/// @dev inlined interface\n"); let _ = interface.format(is_impl, &mut out, tc); tc.collect(out); @@ -231,7 +231,7 @@ #[automatically_derived] impl ::evm_coder::events::ToLog for #name { - fn to_log(&self, contract: address) -> ::ethereum::Log { + 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(); --- a/crates/evm-coder/src/abi/impls.rs +++ b/crates/evm-coder/src/abi/impls.rs @@ -63,27 +63,27 @@ impl_abi!(u128, uint128, false); impl_abi!(U256, uint256, false); impl_abi!(H160, address, false); -impl_abi!(string, string, true); +impl_abi!(String, string, true); impl_abi_writeable!(&str, string); -impl_abi_type!(bytes, bytes, true); +impl_abi_type!(Bytes, bytes, true); -impl AbiRead for bytes { - fn abi_read(reader: &mut AbiReader) -> Result { - Ok(bytes(reader.bytes()?)) +impl AbiRead for Bytes { + fn abi_read(reader: &mut AbiReader) -> Result { + Ok(Bytes(reader.bytes()?)) } } -impl AbiWrite for bytes { +impl AbiWrite for Bytes { fn abi_write(&self, writer: &mut AbiWriter) { writer.bytes(self.0.as_slice()) } } -impl_abi_type!(bytes4, bytes4, false); -impl AbiRead for bytes4 { - fn abi_read(reader: &mut AbiReader) -> Result { +impl_abi_type!(Bytes4, bytes4, false); +impl AbiRead for Bytes4 { + fn abi_read(reader: &mut AbiReader) -> Result { reader.bytes4() } } --- a/crates/evm-coder/src/abi/mod.rs +++ b/crates/evm-coder/src/abi/mod.rs @@ -54,7 +54,7 @@ } } /// Start reading RLP buffer, parsing first 4 bytes as selector - pub fn new_call(buf: &'i [u8]) -> Result<(bytes4, Self)> { + pub fn new_call(buf: &'i [u8]) -> Result<(Bytes4, Self)> { if buf.len() < 4 { return Err(Error::Error(ExitError::OutOfOffset)); } @@ -148,8 +148,8 @@ } /// Read [`string`] at current position, then advance - pub fn string(&mut self) -> Result { - string::from_utf8(self.bytes()?).map_err(|_| Error::Error(ExitError::InvalidRange)) + pub fn string(&mut self) -> Result { + String::from_utf8(self.bytes()?).map_err(|_| Error::Error(ExitError::InvalidRange)) } /// Read [`u8`] at current position, then advance --- a/crates/evm-coder/src/abi/test.rs +++ b/crates/evm-coder/src/abi/test.rs @@ -39,22 +39,22 @@ #[test] fn encode_decode_uint8() { - test_impl_uint!(uint8); + test_impl_uint!(u8); } #[test] fn encode_decode_uint32() { - test_impl_uint!(uint32); + test_impl_uint!(u32); } #[test] fn encode_decode_uint128() { - test_impl_uint!(uint128); + test_impl_uint!(u128); } #[test] fn encode_decode_uint256() { - test_impl::( + test_impl::( 0xdeadbeef, U256([255, 0, 0, 0]), &hex!( @@ -101,7 +101,7 @@ #[test] fn encode_decode_vec_tuple_address_uint256() { - test_impl::>( + test_impl::>( 0x1ACF2D55, vec![ ( @@ -138,7 +138,7 @@ #[test] fn encode_decode_vec_tuple_uint256_string() { - test_impl::>( + test_impl::>( 0xdeadbeef, vec![ (1.into(), "Test URI 0".to_string()), @@ -261,7 +261,7 @@ let (call, mut decoder) = AbiReader::new_call(encoded_data).unwrap(); assert_eq!(call, u32::to_be_bytes(decoded_data.0)); let address = decoder.address().unwrap(); - let data = >::abi_read(&mut decoder).unwrap(); + let data = >::abi_read(&mut decoder).unwrap(); assert_eq!(data, decoded_data.1); let mut writer = AbiWriter::new_call(decoded_data.0); @@ -273,12 +273,12 @@ #[test] fn encode_decode_vec_tuple_string_bytes() { - test_impl::>( + test_impl::>( 0xdeadbeef, vec![ ( "Test URI 0".to_string(), - bytes(vec![ + Bytes(vec![ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, @@ -287,14 +287,14 @@ ), ( "Test URI 1".to_string(), - bytes(vec![ + Bytes(vec![ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, ]), ), - ("Test URI 2".to_string(), bytes(vec![0x33, 0x33])), + ("Test URI 2".to_string(), Bytes(vec![0x33, 0x33])), ], &hex!( " @@ -337,10 +337,10 @@ // #[ignore = "reason"] fn encode_decode_tuple0_tuple1_uint8_tuple1_string_bytes_tuple1_uint8_bytes() { let int = 0xff; - let by = bytes(vec![0x11, 0x22, 0x33]); + let by = Bytes(vec![0x11, 0x22, 0x33]); let string = "some string".to_string(); - test_impl::<((u8,), (String, bytes), (u8, bytes))>( + test_impl::<((u8,), (String, Bytes), (u8, Bytes))>( 0xdeadbeef, ((int,), (string.clone(), by.clone()), (int, by)), &hex!( @@ -485,9 +485,9 @@ #[test] fn encode_decode_tuple0_tuple1_string_bytes() { - test_impl::<((String, bytes),)>( + test_impl::<((String, Bytes),)>( 0xdeadbeef, - (("some string".to_string(), bytes(vec![1, 2, 3])),), + (("some string".to_string(), Bytes(vec![1, 2, 3])),), &hex!( " deadbeef --- a/crates/evm-coder/src/events.rs +++ b/crates/evm-coder/src/events.rs @@ -15,7 +15,7 @@ // along with Unique Network. If not, see . use ethereum::Log; -use primitive_types::{H160, H256}; +use primitive_types::{H160, H256, U256}; use crate::types::*; @@ -45,7 +45,7 @@ } } -impl ToTopic for uint256 { +impl ToTopic for U256 { fn to_topic(&self) -> H256 { let mut out = [0u8; 32]; self.to_big_endian(&mut out); @@ -53,7 +53,7 @@ } } -impl ToTopic for address { +impl ToTopic for Address { fn to_topic(&self) -> H256 { let mut out = [0u8; 32]; out[12..32].copy_from_slice(&self.0); @@ -61,7 +61,7 @@ } } -impl ToTopic for uint32 { +impl ToTopic for u32 { fn to_topic(&self) -> H256 { let mut out = [0u8; 32]; out[28..32].copy_from_slice(&self.to_be_bytes()); --- a/crates/evm-coder/src/lib.rs +++ b/crates/evm-coder/src/lib.rs @@ -131,33 +131,23 @@ use alloc::{vec::Vec}; use primitive_types::{U256, H160, H256}; - pub type address = H160; - pub type uint8 = u8; - pub type uint16 = u16; - pub type uint32 = u32; - pub type uint64 = u64; - pub type uint128 = u128; - pub type uint256 = U256; - pub type bytes4 = [u8; 4]; - pub type topic = H256; + pub type Address = H160; + pub type Bytes4 = [u8; 4]; + pub type Topic = H256; #[cfg(not(feature = "std"))] - pub type string = ::alloc::string::String; + pub type String = ::alloc::string::String; #[cfg(feature = "std")] - pub type string = ::std::string::String; + pub type String = ::std::string::String; #[derive(Default, Debug, PartialEq, Eq, Clone)] - pub struct bytes(pub Vec); - - /// Solidity doesn't have `void` type, however we have special implementation - /// for empty tuple return type - pub type void = (); + pub struct Bytes(pub Vec); //#region Special types /// Makes function payable - pub type value = U256; + pub type Value = U256; /// Makes function caller-sensitive - pub type caller = address; + pub type Caller = Address; //#endregion /// Ethereum typed call message, similar to solidity @@ -172,20 +162,20 @@ pub value: U256, } - impl From> for bytes { + impl From> for Bytes { fn from(src: Vec) -> Self { Self(src) } } #[allow(clippy::from_over_into)] - impl Into> for bytes { + impl Into> for Bytes { fn into(self) -> Vec { self.0 } } - impl bytes { + impl Bytes { #[must_use] pub fn len(&self) -> usize { self.0.len() @@ -201,7 +191,7 @@ /// 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>; + fn parse(selector: types::Bytes4, input: &mut AbiReader) -> execution::Result>; } /// Intended to be used as `#[weight]` output type @@ -237,22 +227,22 @@ /// implements specified interface SupportsInterface { /// Requested interface - interface_id: types::bytes4, + interface_id: types::Bytes4, }, } impl ERC165Call { /// ERC165 selector is provided by standard - pub const INTERFACE_ID: types::bytes4 = u32::to_be_bytes(0x01ffc9a7); + pub const INTERFACE_ID: types::Bytes4 = u32::to_be_bytes(0x01ffc9a7); } impl Call for ERC165Call { - fn parse(selector: types::bytes4, input: &mut AbiReader) -> execution::Result> { + fn parse(selector: types::Bytes4, input: &mut AbiReader) -> execution::Result> { if selector != Self::INTERFACE_ID { return Ok(None); } Ok(Some(Self::SupportsInterface { - interface_id: types::bytes4::abi_read(input)?, + interface_id: types::Bytes4::abi_read(input)?, })) } } --- a/crates/evm-coder/src/solidity/impls.rs +++ b/crates/evm-coder/src/solidity/impls.rs @@ -27,14 +27,14 @@ u64 => "uint64" true = "0", u128 => "uint128" true = "0", U256 => "uint256" true = "0", - bytes4 => "bytes4" true = "bytes4(0)", + Bytes4 => "bytes4" true = "bytes4(0)", H160 => "address" true = "0x0000000000000000000000000000000000000000", - string => "string" false = "\"\"", - bytes => "bytes" false = "hex\"\"", + String => "string" false = "\"\"", + Bytes => "bytes" false = "hex\"\"", bool => "bool" true = "false", } -impl SolidityTypeName for void { +impl SolidityTypeName for () { fn solidity_name(_writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result { Ok(()) } @@ -72,10 +72,10 @@ macro_rules! impl_tuples { ($($ident:ident)+) => { impl<$($ident: SolidityTypeName + 'static),+> SolidityTupleTy for ($($ident,)+) { - fn fields(tc: &TypeCollector) -> Vec { + fn fields(tc: &TypeCollector) -> Vec { let mut collected = Vec::with_capacity(Self::len()); $({ - let mut out = string::new(); + let mut out = String::new(); $ident::solidity_name(&mut out, tc).expect("no fmt error"); collected.push(out); })*; --- a/crates/evm-coder/src/solidity/mod.rs +++ b/crates/evm-coder/src/solidity/mod.rs @@ -26,7 +26,7 @@ mod impls; #[cfg(not(feature = "std"))] -use alloc::{string::String, vec::Vec, collections::BTreeMap, format}; +use alloc::{vec::Vec, collections::BTreeMap, format}; #[cfg(feature = "std")] use std::collections::BTreeMap; use core::{ @@ -42,16 +42,16 @@ pub struct TypeCollector { /// Code => id /// id ordering is required to perform topo-sort on the resulting data - structs: RefCell>, - anonymous: RefCell, usize>>, - // generic: RefCell>, + structs: RefCell>, + anonymous: RefCell, usize>>, + // generic: RefCell>, id: Cell, } impl TypeCollector { pub fn new() -> Self { Self::default() } - pub fn collect(&self, item: string) { + pub fn collect(&self, item: String) { let id = self.next_id(); self.structs.borrow_mut().insert(item, id); } @@ -84,7 +84,7 @@ pub fn collect_enum(&self) -> String { T::generate_solidity_interface(self) } - pub fn finish(self) -> Vec { + pub fn finish(self) -> Vec { let mut data = self.structs.into_inner().into_iter().collect::>(); data.sort_by_key(|(_, id)| Reverse(*id)); data.into_iter().map(|(code, _)| code).collect() @@ -360,7 +360,7 @@ pub struct SolidityInterface { pub docs: &'static [&'static str], - pub selector: bytes4, + pub selector: Bytes4, pub name: &'static str, pub is: &'static [&'static str], pub functions: F, --- a/crates/evm-coder/tests/abi_derive_generation.rs +++ b/crates/evm-coder/tests/abi_derive_generation.rs @@ -1,6 +1,6 @@ mod test_struct { use evm_coder_procedural::AbiCoder; - use evm_coder::types::bytes; + use evm_coder::types::Bytes; #[test] fn empty_struct() { @@ -27,13 +27,13 @@ #[derive(AbiCoder, PartialEq, Debug)] struct TypeStruct2DynamicParam { _a: String, - _b: bytes, + _b: Bytes, } #[derive(AbiCoder, PartialEq, Debug)] struct TypeStruct2MixedParam { _a: u8, - _b: bytes, + _b: Bytes, } #[derive(AbiCoder, PartialEq, Debug)] @@ -236,10 +236,10 @@ struct TupleStruct2SimpleParam(u8, u32); #[derive(AbiCoder, PartialEq, Debug)] - struct TupleStruct2DynamicParam(String, bytes); + struct TupleStruct2DynamicParam(String, Bytes); #[derive(AbiCoder, PartialEq, Debug)] - struct TupleStruct2MixedParam(u8, bytes); + struct TupleStruct2MixedParam(u8, Bytes); #[derive(AbiCoder, PartialEq, Debug)] struct TupleStruct1DerivedSimpleParam(TupleStruct1SimpleParam); @@ -562,8 +562,8 @@ #[test] fn codec_struct_2_dynamic() { let _a: String = "some string".into(); - let _b: bytes = bytes(vec![0x11, 0x22, 0x33]); - test_impl::<(String, bytes), TupleStruct2DynamicParam, TypeStruct2DynamicParam>( + let _b: Bytes = Bytes(vec![0x11, 0x22, 0x33]); + test_impl::<(String, Bytes), TupleStruct2DynamicParam, TypeStruct2DynamicParam>( (_a.clone(), _b.clone()), TupleStruct2DynamicParam(_a.clone(), _b.clone()), TypeStruct2DynamicParam { _a, _b }, @@ -573,8 +573,8 @@ #[test] fn codec_struct_2_mixed() { let _a: u8 = 0xff; - let _b: bytes = bytes(vec![0x11, 0x22, 0x33]); - test_impl::<(u8, bytes), TupleStruct2MixedParam, TypeStruct2MixedParam>( + let _b: Bytes = Bytes(vec![0x11, 0x22, 0x33]); + test_impl::<(u8, Bytes), TupleStruct2MixedParam, TypeStruct2MixedParam>( (_a.clone(), _b.clone()), TupleStruct2MixedParam(_a.clone(), _b.clone()), TypeStruct2MixedParam { _a, _b }, @@ -605,9 +605,9 @@ #[test] fn codec_struct_2_derived_dynamic() { let _a = "some string".to_string(); - let _b = bytes(vec![0x11, 0x22, 0x33]); + let _b = Bytes(vec![0x11, 0x22, 0x33]); test_impl::< - ((String,), (String, bytes)), + ((String,), (String, Bytes)), TupleStruct2DerivedDynamicParam, TypeStruct2DerivedDynamicParam, >( @@ -626,10 +626,10 @@ #[test] fn codec_struct_3_derived_mixed() { let int = 0xff; - let by = bytes(vec![0x11, 0x22, 0x33]); + let by = Bytes(vec![0x11, 0x22, 0x33]); let string = "some string".to_string(); test_impl::< - ((u8,), (String, bytes), (u8, bytes)), + ((u8,), (String, Bytes), (u8, Bytes)), TupleStruct3DerivedMixedParam, TypeStruct3DerivedMixedParam, >( --- a/crates/evm-coder/tests/conditional_is.rs +++ b/crates/evm-coder/tests/conditional_is.rs @@ -4,14 +4,14 @@ #[solidity_interface(name = A)] impl Contract { - fn method_a() -> Result { + fn method_a() -> Result<()> { Ok(()) } } #[solidity_interface(name = B)] impl Contract { - fn method_b() -> Result { + fn method_b() -> Result<()> { Ok(()) } } --- a/crates/evm-coder/tests/generics.rs +++ b/crates/evm-coder/tests/generics.rs @@ -16,19 +16,20 @@ use std::marker::PhantomData; use evm_coder::{execution::Result, generate_stubgen, solidity_interface, types::*}; +use primitive_types::U256; pub struct Generic(PhantomData); #[solidity_interface(name = GenericIs)] impl Generic { - fn test_1(&self) -> Result { + fn test_1(&self) -> Result { unreachable!() } } #[solidity_interface(name = Generic, is(GenericIs))] impl> Generic { - fn test_2(&self) -> Result { + fn test_2(&self) -> Result { unreachable!() } } @@ -40,7 +41,7 @@ where T: core::fmt::Debug, { - fn test_3(&self) -> Result { + fn test_3(&self) -> Result { unreachable!() } } --- a/crates/evm-coder/tests/log.rs +++ b/crates/evm-coder/tests/log.rs @@ -17,19 +17,20 @@ #![allow(dead_code)] use evm_coder::{ToLog, types::*}; +use primitive_types::U256; #[derive(ToLog)] enum ERC721Log { Transfer { #[indexed] - from: address, + from: Address, #[indexed] - to: address, - value: uint256, + to: Address, + value: U256, }, Eee { #[indexed] - aaa: address, - bbb: uint256, + aaa: Address, + bbb: U256, }, } --- a/crates/evm-coder/tests/random.rs +++ b/crates/evm-coder/tests/random.rs @@ -19,19 +19,20 @@ use evm_coder::{ abi::AbiType, ToLog, execution::Result, solidity_interface, types::*, solidity, weight, }; +use primitive_types::U256; pub struct Impls; #[solidity_interface(name = OurInterface)] impl Impls { - fn fn_a(&self, _input: uint256) -> Result { + fn fn_a(&self, _input: U256) -> Result { unreachable!() } } #[solidity_interface(name = OurInterface1)] impl Impls { - fn fn_b(&self, _input: uint128) -> Result { + fn fn_b(&self, _input: u128) -> Result { unreachable!() } } @@ -39,12 +40,12 @@ #[derive(ToLog)] enum OurEvents { Event1 { - field1: uint32, + field1: u32, }, Event2 { - field1: uint32, + field1: u32, #[indexed] - field2: uint32, + field2: u32, }, } @@ -56,27 +57,27 @@ )] impl Impls { #[solidity(rename_selector = "fnK")] - fn fn_c(&self, _input: uint32) -> Result { + fn fn_c(&self, _input: u32) -> Result { unreachable!() } - fn fn_d(&self, _value: uint32) -> Result { + fn fn_d(&self, _value: u32) -> Result { unreachable!() } - fn caller_sensitive(&self, _caller: caller) -> Result { + fn caller_sensitive(&self, _caller: Caller) -> Result { unreachable!() } - fn payable(&mut self, _value: value) -> Result { + fn payable(&mut self, _value: Value) -> Result { unreachable!() } #[weight(*_weight)] - fn with_weight(&self, _weight: uint64) -> Result { + fn with_weight(&self, _weight: u64) -> Result<()> { unreachable!() } /// Doccoment example - fn with_doc(&self) -> Result { + fn with_doc(&self) -> Result<()> { unreachable!() } } --- a/crates/evm-coder/tests/solidity_generation.rs +++ b/crates/evm-coder/tests/solidity_generation.rs @@ -15,34 +15,35 @@ // along with Unique Network. If not, see . use evm_coder::{abi::AbiType, execution::Result, generate_stubgen, solidity_interface, types::*}; +use primitive_types::U256; pub struct ERC20; #[solidity_interface(name = ERC20)] impl ERC20 { - fn decimals(&self) -> Result { + fn decimals(&self) -> Result { unreachable!() } /// Get balance of specified owner - fn balance_of(&self, _owner: address) -> Result { + fn balance_of(&self, _owner: Address) -> Result { unreachable!() } - fn transfer(&mut self, _caller: caller, _to: address, _value: uint256) -> Result { + fn transfer(&mut self, _caller: Caller, _to: Address, _value: U256) -> Result { unreachable!() } fn transfer_from( &mut self, - _caller: caller, - _from: address, - _to: address, - _value: uint256, + _caller: Caller, + _from: Address, + _to: Address, + _value: U256, ) -> Result { unreachable!() } - fn approve(&mut self, _caller: caller, _spender: address, _value: uint256) -> Result { + fn approve(&mut self, _caller: Caller, _spender: Address, _value: U256) -> Result { unreachable!() } - fn allowance(&self, _owner: address, _spender: address) -> Result { + fn allowance(&self, _owner: Address, _spender: Address) -> Result { unreachable!() } } --- a/pallets/common/src/erc.rs +++ b/pallets/common/src/erc.rs @@ -26,6 +26,7 @@ }; use pallet_evm_coder_substrate::dispatch_to_evm; use sp_std::{vec, vec::Vec}; +use sp_core::U256; use up_data_structs::{ AccessMode, CollectionMode, CollectionPermissions, OwnerRestrictedSet, Property, SponsoringRateLimit, SponsorshipState, @@ -42,32 +43,32 @@ CollectionCreated { /// Collection owner. #[indexed] - owner: address, + owner: Address, /// Collection ID. #[indexed] - collection_id: address, + collection_id: Address, }, /// The collection has been destroyed. CollectionDestroyed { /// Collection ID. #[indexed] - collection_id: address, + collection_id: Address, }, /// The collection has been changed. CollectionChanged { /// Collection ID. #[indexed] - collection_id: address, + collection_id: Address, }, /// The token has been changed. TokenChanged { /// Collection ID. #[indexed] - collection_id: address, + collection_id: Address, /// Token ID. - token_id: uint256, + token_id: U256, }, } @@ -93,12 +94,7 @@ /// @param value Propery value. #[solidity(hide)] #[weight(>::set_collection_properties(1))] - fn set_collection_property( - &mut self, - caller: caller, - key: string, - value: bytes, - ) -> Result { + fn set_collection_property(&mut self, caller: Caller, key: String, value: Bytes) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let key = >::from(key) .try_into() @@ -115,9 +111,9 @@ #[weight(>::set_collection_properties(properties.len() as u32))] fn set_collection_properties( &mut self, - caller: caller, + caller: Caller, properties: Vec, - ) -> Result { + ) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let properties = properties @@ -134,7 +130,7 @@ /// @param key Property key. #[solidity(hide)] #[weight(>::delete_collection_properties(1))] - fn delete_collection_property(&mut self, caller: caller, key: string) -> Result<()> { + fn delete_collection_property(&mut self, caller: Caller, key: String) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let key = >::from(key) .try_into() @@ -147,7 +143,7 @@ /// /// @param keys Properties keys. #[weight(>::delete_collection_properties(keys.len() as u32))] - fn delete_collection_properties(&mut self, caller: caller, keys: Vec) -> Result<()> { + fn delete_collection_properties(&mut self, caller: Caller, keys: Vec) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let keys = keys .into_iter() @@ -168,7 +164,7 @@ /// /// @param key Property key. /// @return bytes The property corresponding to the key. - fn collection_property(&self, key: string) -> Result { + fn collection_property(&self, key: String) -> Result { let key = >::from(key) .try_into() .map_err(|_| "key too large")?; @@ -176,14 +172,14 @@ let props = CollectionProperties::::get(self.id); let prop = props.get(&key).ok_or("key not found")?; - Ok(bytes(prop.to_vec())) + Ok(Bytes(prop.to_vec())) } /// Get collection properties. /// /// @param keys Properties keys. Empty keys for all propertyes. /// @return Vector of properties key/value pairs. - fn collection_properties(&self, keys: Vec) -> Result> { + fn collection_properties(&self, keys: Vec) -> Result> { let keys = keys .into_iter() .map(|key| { @@ -212,7 +208,7 @@ /// /// @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract. #[solidity(hide)] - fn set_collection_sponsor(&mut self, caller: caller, sponsor: address) -> Result { + fn set_collection_sponsor(&mut self, caller: Caller, sponsor: Address) -> Result<()> { self.consume_store_reads_and_writes(1, 1)?; let caller = T::CrossAccountId::from_eth(caller); @@ -229,9 +225,9 @@ /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract. fn set_collection_sponsor_cross( &mut self, - caller: caller, + caller: Caller, sponsor: eth::CrossAddress, - ) -> Result { + ) -> Result<()> { self.consume_store_reads_and_writes(1, 1)?; let caller = T::CrossAccountId::from_eth(caller); @@ -252,7 +248,7 @@ /// Collection sponsorship confirmation. /// /// @dev After setting the sponsor for the collection, it must be confirmed with this function. - fn confirm_collection_sponsorship(&mut self, caller: caller) -> Result { + fn confirm_collection_sponsorship(&mut self, caller: Caller) -> Result<()> { self.consume_store_writes(1)?; let caller = T::CrossAccountId::from_eth(caller); @@ -261,7 +257,7 @@ } /// Remove collection sponsor. - fn remove_collection_sponsor(&mut self, caller: caller) -> Result { + fn remove_collection_sponsor(&mut self, caller: Caller) -> Result<()> { self.consume_store_reads_and_writes(1, 1)?; let caller = T::CrossAccountId::from_eth(caller); self.remove_sponsor(&caller).map_err(dispatch_to_evm::) @@ -343,11 +339,7 @@ /// @dev Throws error if limit not found. /// @param limit Some limit. #[solidity(rename_selector = "setCollectionLimit")] - fn set_collection_limit( - &mut self, - caller: caller, - limit: eth::CollectionLimit, - ) -> Result { + fn set_collection_limit(&mut self, caller: Caller, limit: eth::CollectionLimit) -> Result<()> { self.consume_store_reads_and_writes(1, 1)?; if !limit.has_value() { @@ -359,7 +351,7 @@ } /// Get contract address. - fn contract_address(&self) -> Result
{ + fn contract_address(&self) -> Result
{ Ok(crate::eth::collection_id_to_address(self.id)) } @@ -367,9 +359,9 @@ /// @param newAdmin Cross account administrator address. fn add_collection_admin_cross( &mut self, - caller: caller, + caller: Caller, new_admin: eth::CrossAddress, - ) -> Result { + ) -> Result<()> { self.consume_store_reads_and_writes(2, 2)?; let caller = T::CrossAccountId::from_eth(caller); @@ -382,9 +374,9 @@ /// @param admin Cross account administrator address. fn remove_collection_admin_cross( &mut self, - caller: caller, + caller: Caller, admin: eth::CrossAddress, - ) -> Result { + ) -> Result<()> { self.consume_store_reads_and_writes(2, 2)?; let caller = T::CrossAccountId::from_eth(caller); @@ -396,7 +388,7 @@ /// Add collection admin. /// @param newAdmin Address of the added administrator. #[solidity(hide)] - fn add_collection_admin(&mut self, caller: caller, new_admin: address) -> Result { + fn add_collection_admin(&mut self, caller: Caller, new_admin: Address) -> Result<()> { self.consume_store_reads_and_writes(2, 2)?; let caller = T::CrossAccountId::from_eth(caller); @@ -409,7 +401,7 @@ /// /// @param admin Address of the removed administrator. #[solidity(hide)] - fn remove_collection_admin(&mut self, caller: caller, admin: address) -> Result { + fn remove_collection_admin(&mut self, caller: Caller, admin: Address) -> Result<()> { self.consume_store_reads_and_writes(2, 2)?; let caller = T::CrossAccountId::from_eth(caller); @@ -422,7 +414,7 @@ /// /// @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled' #[solidity(rename_selector = "setCollectionNesting")] - fn set_nesting_bool(&mut self, caller: caller, enable: bool) -> Result { + fn set_nesting_bool(&mut self, caller: Caller, enable: bool) -> Result<()> { self.consume_store_reads_and_writes(1, 1)?; let caller = T::CrossAccountId::from_eth(caller); @@ -443,10 +435,10 @@ #[solidity(rename_selector = "setCollectionNesting")] fn set_nesting( &mut self, - caller: caller, + caller: Caller, enable: bool, - collections: Vec
, - ) -> Result { + collections: Vec
, + ) -> Result<()> { self.consume_store_reads_and_writes(1, 1)?; if collections.is_empty() { @@ -511,18 +503,12 @@ } /// Set the collection access method. /// @param mode Access mode - /// 0 for Normal - /// 1 for AllowList - fn set_collection_access(&mut self, caller: caller, mode: uint8) -> Result { + fn set_collection_access(&mut self, caller: Caller, mode: eth::AccessMode) -> Result<()> { self.consume_store_reads_and_writes(1, 1)?; let caller = T::CrossAccountId::from_eth(caller); let permissions = CollectionPermissions { - access: Some(match mode { - 0 => AccessMode::Normal, - 1 => AccessMode::AllowList, - _ => return Err("not supported access mode".into()), - }), + access: Some(mode.into()), ..Default::default() }; >::update_permissions(&caller, self, permissions).map_err(dispatch_to_evm::) @@ -540,7 +526,7 @@ /// /// @param user Address of a trusted user. #[solidity(hide)] - fn add_to_collection_allow_list(&mut self, caller: caller, user: address) -> Result { + fn add_to_collection_allow_list(&mut self, caller: Caller, user: Address) -> Result<()> { self.consume_store_writes(1)?; let caller = T::CrossAccountId::from_eth(caller); @@ -554,9 +540,9 @@ /// @param user User cross account address. fn add_to_collection_allow_list_cross( &mut self, - caller: caller, + caller: Caller, user: eth::CrossAddress, - ) -> Result { + ) -> Result<()> { self.consume_store_writes(1)?; let caller = T::CrossAccountId::from_eth(caller); @@ -569,7 +555,7 @@ /// /// @param user Address of a removed user. #[solidity(hide)] - fn remove_from_collection_allow_list(&mut self, caller: caller, user: address) -> Result { + fn remove_from_collection_allow_list(&mut self, caller: Caller, user: Address) -> Result<()> { self.consume_store_writes(1)?; let caller = T::CrossAccountId::from_eth(caller); @@ -583,9 +569,9 @@ /// @param user User cross account address. fn remove_from_collection_allow_list_cross( &mut self, - caller: caller, + caller: Caller, user: eth::CrossAddress, - ) -> Result { + ) -> Result<()> { self.consume_store_writes(1)?; let caller = T::CrossAccountId::from_eth(caller); @@ -597,7 +583,7 @@ /// Switch permission for minting. /// /// @param mode Enable if "true". - fn set_collection_mint_mode(&mut self, caller: caller, mode: bool) -> Result { + fn set_collection_mint_mode(&mut self, caller: Caller, mode: bool) -> Result<()> { self.consume_store_reads_and_writes(1, 1)?; let caller = T::CrossAccountId::from_eth(caller); @@ -613,7 +599,7 @@ /// @param user account to verify /// @return "true" if account is the owner or admin #[solidity(hide, rename_selector = "isOwnerOrAdmin")] - fn is_owner_or_admin_eth(&self, user: address) -> Result { + fn is_owner_or_admin_eth(&self, user: Address) -> Result { let user = T::CrossAccountId::from_eth(user); Ok(self.is_owner_or_admin(&user)) } @@ -630,7 +616,7 @@ /// Returns collection type /// /// @return `Fungible` or `NFT` or `ReFungible` - fn unique_collection_type(&self) -> Result { + fn unique_collection_type(&self) -> Result { let mode = match self.collection.mode { CollectionMode::Fungible(_) => "Fungible", CollectionMode::NFT => "NFT", @@ -654,7 +640,7 @@ /// @dev Owner can be changed only by current owner /// @param newOwner new owner account #[solidity(hide, rename_selector = "changeCollectionOwner")] - fn set_owner(&mut self, caller: caller, new_owner: address) -> Result { + fn set_owner(&mut self, caller: Caller, new_owner: Address) -> Result<()> { self.consume_store_writes(1)?; let caller = T::CrossAccountId::from_eth(caller); @@ -680,9 +666,9 @@ /// @param newOwner new owner cross account fn change_collection_owner_cross( &mut self, - caller: caller, + caller: Caller, new_owner: eth::CrossAddress, - ) -> Result { + ) -> Result<()> { self.consume_store_writes(1)?; let caller = T::CrossAccountId::from_eth(caller); --- a/pallets/common/src/eth.rs +++ b/pallets/common/src/eth.rs @@ -18,12 +18,9 @@ use alloc::format; use sp_std::{vec, vec::Vec}; -use evm_coder::{ - AbiCoder, - types::{uint256, address}, -}; +use evm_coder::{AbiCoder, types::Address}; pub use pallet_evm::{Config, account::CrossAccountId}; -use sp_core::H160; +use sp_core::{H160, U256}; use up_data_structs::CollectionId; // 0x17c4e6453Cc49AAAaEACA894e6D9683e00000001 - collection 1 @@ -33,7 +30,7 @@ ]; /// Maps the ethereum address of the collection in substrate. -pub fn map_eth_to_id(eth: &H160) -> Option { +pub fn map_eth_to_id(eth: &Address) -> Option { if eth[0..16] != ETH_COLLECTION_PREFIX { return None; } @@ -43,7 +40,7 @@ } /// Maps the substrate collection id in ethereum. -pub fn collection_id_to_address(id: CollectionId) -> H160 { +pub fn collection_id_to_address(id: CollectionId) -> Address { let mut out = [0; 20]; out[0..16].copy_from_slice(Ð_COLLECTION_PREFIX); out[16..20].copy_from_slice(&u32::to_be_bytes(id.0)); @@ -51,12 +48,12 @@ } /// Check if the ethereum address is a collection. -pub fn is_collection(address: &H160) -> bool { +pub fn is_collection(address: &Address) -> bool { address[0..16] == ETH_COLLECTION_PREFIX } -/// Convert `uint256` to `CrossAccountId`. -pub fn convert_uint256_to_cross_account(from: uint256) -> T::CrossAccountId +/// Convert `U256` to `CrossAccountId`. +pub fn convert_uint256_to_cross_account(from: U256) -> T::CrossAccountId where T::AccountId: From<[u8; 32]>, { @@ -69,8 +66,8 @@ /// Cross account struct #[derive(Debug, Default, AbiCoder)] pub struct CrossAddress { - pub(crate) eth: address, - pub(crate) sub: uint256, + pub(crate) eth: Address, + pub(crate) sub: U256, } impl CrossAddress { @@ -97,7 +94,7 @@ { Self { eth: Default::default(), - sub: uint256::from_big_endian(account_id.as_ref()), + sub: U256::from_big_endian(account_id.as_ref()), } } /// Converts [`CrossAddress`] to `CrossAccountId`. @@ -121,17 +118,17 @@ /// Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue). #[derive(Debug, Default, AbiCoder)] pub struct Property { - key: evm_coder::types::string, - value: evm_coder::types::bytes, + key: evm_coder::types::String, + value: evm_coder::types::Bytes, } impl TryFrom for Property { type Error = evm_coder::execution::Error; fn try_from(from: up_data_structs::Property) -> Result { - let key = evm_coder::types::string::from_utf8(from.key.into()) + let key = evm_coder::types::String::from_utf8(from.key.into()) .map_err(|e| Self::Error::Revert(format!("utf8 conversion error: {}", e)))?; - let value = evm_coder::types::bytes(from.value.to_vec()); + let value = evm_coder::types::Bytes(from.value.to_vec()); Ok(Property { key, value }) } } @@ -187,7 +184,7 @@ #[derive(Debug, Default, AbiCoder)] pub struct CollectionLimit { field: CollectionLimitField, - value: Option, + value: Option, } impl CollectionLimit { @@ -345,7 +342,7 @@ #[derive(Debug, Default, AbiCoder)] pub struct TokenPropertyPermission { /// Token property key. - key: evm_coder::types::string, + key: evm_coder::types::String, /// Token property permissions. permissions: Vec, } @@ -363,7 +360,7 @@ ), ) -> Self { let (key, permission) = value; - let key = evm_coder::types::string::from_utf8(key.into_inner()) + let key = evm_coder::types::String::from_utf8(key.into_inner()) .expect("Stored key must be valid"); let permissions = PropertyPermission::into_vec(permission); Self { key, permissions } @@ -393,12 +390,12 @@ #[derive(Debug, Default, AbiCoder)] pub struct CollectionNesting { token_owner: bool, - ids: Vec, + ids: Vec, } impl CollectionNesting { /// Create [`CollectionNesting`]. - pub fn new(token_owner: bool, ids: Vec) -> Self { + pub fn new(token_owner: bool, ids: Vec) -> Self { Self { token_owner, ids } } } @@ -416,3 +413,32 @@ Self { field, value } } } + +/// Ethereum representation of `AccessMode` (see [`up_data_structs::AccessMode`]). +#[derive(AbiCoder, Copy, Clone, Default, Debug)] +#[repr(u8)] +pub enum AccessMode { + /// Access grant for owner and admins. Used as default. + #[default] + Normal, + /// Like a [`Normal`](AccessMode::Normal) but also users in allow list. + AllowList, +} + +impl From for AccessMode { + fn from(value: up_data_structs::AccessMode) -> Self { + match value { + up_data_structs::AccessMode::Normal => AccessMode::Normal, + up_data_structs::AccessMode::AllowList => AccessMode::AllowList, + } + } +} + +impl Into for AccessMode { + fn into(self) -> up_data_structs::AccessMode { + match self { + AccessMode::Normal => up_data_structs::AccessMode::Normal, + AccessMode::AllowList => up_data_structs::AccessMode::AllowList, + } + } +} --- a/pallets/common/src/lib.rs +++ b/pallets/common/src/lib.rs @@ -500,8 +500,16 @@ } } + impl Pallet { + /// Helper function that handles deposit events + pub fn deposit_event(event: Event) { + let event = ::RuntimeEvent::from(event); + let event = event.into(); + >::deposit_event(event) + } + } + #[pallet::event] - #[pallet::generate_deposit(pub fn deposit_event)] pub enum Event { /// New collection was created CollectionCreated( --- a/pallets/evm-coder-substrate/src/lib.rs +++ b/pallets/evm-coder-substrate/src/lib.rs @@ -41,7 +41,7 @@ use evm_coder::{ abi::{AbiReader, AbiWrite, AbiWriter}, execution, - types::{Msg, value}, + types::{Msg, Value}, }; pub use pallet::*; @@ -256,7 +256,7 @@ >( caller: H160, e: &mut E, - value: value, + value: Value, input: &[u8], ) -> execution::Result> { let (selector, mut reader) = AbiReader::new_call(input)?; --- a/pallets/evm-contract-helpers/src/eth.rs +++ b/pallets/evm-contract-helpers/src/eth.rs @@ -49,25 +49,25 @@ ContractSponsorSet { /// Contract address of the affected collection. #[indexed] - contract_address: address, + contract_address: Address, /// New sponsor address. - sponsor: address, + sponsor: Address, }, /// New sponsor was confirm. ContractSponsorshipConfirmed { /// Contract address of the affected collection. #[indexed] - contract_address: address, + contract_address: Address, /// New sponsor address. - sponsor: address, + sponsor: Address, }, /// Collection sponsor was removed. ContractSponsorRemoved { /// Contract address of the affected collection. #[indexed] - contract_address: address, + contract_address: Address, }, } @@ -96,7 +96,7 @@ /// @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
{ + fn contract_owner(&self, contract_address: Address) -> Result
{ Ok(>::get(contract_address)) } @@ -105,10 +105,10 @@ /// @param sponsor User address who set as pending sponsor. fn set_sponsor( &mut self, - caller: caller, - contract_address: address, - sponsor: address, - ) -> Result { + caller: Caller, + contract_address: Address, + sponsor: Address, + ) -> Result<()> { self.recorder().consume_sload()?; self.recorder().consume_sstore()?; @@ -125,7 +125,7 @@ /// Set contract as self sponsored. /// /// @param contractAddress Contract for which a self sponsoring is being enabled. - fn self_sponsored_enable(&mut self, caller: caller, contract_address: address) -> Result { + fn self_sponsored_enable(&mut self, caller: Caller, contract_address: Address) -> Result<()> { self.recorder().consume_sload()?; self.recorder().consume_sstore()?; @@ -146,7 +146,7 @@ /// Remove sponsor. /// /// @param contractAddress Contract for which a sponsorship is being removed. - fn remove_sponsor(&mut self, caller: caller, contract_address: address) -> Result { + fn remove_sponsor(&mut self, caller: Caller, contract_address: Address) -> Result<()> { self.recorder().consume_sload()?; self.recorder().consume_sstore()?; @@ -161,7 +161,7 @@ /// @dev Caller must be same that set via [`setSponsor`]. /// /// @param contractAddress Сontract for which need to confirm sponsorship. - fn confirm_sponsorship(&mut self, caller: caller, contract_address: address) -> Result { + fn confirm_sponsorship(&mut self, caller: Caller, contract_address: Address) -> Result<()> { self.recorder().consume_sload()?; self.recorder().consume_sstore()?; @@ -175,7 +175,7 @@ /// /// @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 sponsor(&self, contract_address: address) -> Result> { + fn sponsor(&self, contract_address: Address) -> Result> { Ok(match Pallet::::get_sponsor(contract_address) { Some(ref value) => Some(eth::CrossAddress::from_sub_cross_account::(value)), None => None, @@ -186,7 +186,7 @@ /// /// @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 { + fn has_sponsor(&self, contract_address: Address) -> Result { Ok(Pallet::::get_sponsor(contract_address).is_some()) } @@ -194,23 +194,23 @@ /// /// @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 { + fn has_pending_sponsor(&self, contract_address: Address) -> Result { Ok(match Sponsoring::::get(contract_address) { SponsorshipState::Disabled | SponsorshipState::Confirmed(_) => false, SponsorshipState::Unconfirmed(_) => true, }) } - fn sponsoring_enabled(&self, contract_address: address) -> Result { + fn sponsoring_enabled(&self, contract_address: Address) -> Result { Ok(>::sponsoring_mode(contract_address) != SponsoringModeT::Disabled) } fn set_sponsoring_mode( &mut self, - caller: caller, - contract_address: address, + caller: Caller, + contract_address: Address, mode: SponsoringModeT, - ) -> Result { + ) -> Result<()> { self.recorder().consume_sload()?; self.recorder().consume_sstore()?; @@ -223,7 +223,7 @@ /// Get current contract sponsoring rate limit /// @param contractAddress Contract to get sponsoring rate limit of /// @return uint32 Amount of blocks between two sponsored transactions - fn sponsoring_rate_limit(&self, contract_address: address) -> Result { + fn sponsoring_rate_limit(&self, contract_address: Address) -> Result { self.recorder().consume_sload()?; Ok(>::get(contract_address) @@ -239,10 +239,10 @@ /// @dev Only contract owner can change this setting fn set_sponsoring_rate_limit( &mut self, - caller: caller, - contract_address: address, - rate_limit: uint32, - ) -> Result { + caller: Caller, + contract_address: Address, + rate_limit: u32, + ) -> Result<()> { self.recorder().consume_sload()?; self.recorder().consume_sstore()?; @@ -259,10 +259,10 @@ /// @dev Only contract owner can change this setting fn set_sponsoring_fee_limit( &mut self, - caller: caller, - contract_address: address, - fee_limit: uint256, - ) -> Result { + caller: Caller, + contract_address: Address, + fee_limit: U256, + ) -> Result<()> { self.recorder().consume_sload()?; self.recorder().consume_sstore()?; @@ -276,7 +276,7 @@ /// @param contractAddress Contract to get sponsoring fee limit of /// @return uint256 Maximum amount of fee that could be spent by single /// transaction - fn sponsoring_fee_limit(&self, contract_address: address) -> Result { + fn sponsoring_fee_limit(&self, contract_address: Address) -> Result { self.recorder().consume_sload()?; Ok(get_sponsoring_fee_limit::(contract_address)) @@ -287,7 +287,7 @@ /// @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 { + fn allowed(&self, contract_address: Address, user: Address) -> Result { self.0.consume_sload()?; Ok(>::allowed(contract_address, user)) } @@ -300,11 +300,11 @@ /// @dev Only contract owner can change this setting fn toggle_allowed( &mut self, - caller: caller, - contract_address: address, - user: address, + caller: Caller, + contract_address: Address, + user: Address, is_allowed: bool, - ) -> Result { + ) -> Result<()> { self.recorder().consume_sload()?; self.recorder().consume_sstore()?; @@ -320,7 +320,7 @@ /// 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 { + fn allowlist_enabled(&self, contract_address: Address) -> Result { Ok(>::get(contract_address)) } @@ -329,10 +329,10 @@ /// @param enabled Should allowlist access to be enabled? fn toggle_allowlist( &mut self, - caller: caller, - contract_address: address, + caller: Caller, + contract_address: Address, enabled: bool, - ) -> Result { + ) -> Result<()> { self.recorder().consume_sload()?; self.recorder().consume_sstore()?; @@ -441,7 +441,7 @@ } } -fn get_sponsoring_fee_limit(contract_address: address) -> uint256 { +fn get_sponsoring_fee_limit(contract_address: Address) -> U256 { >::get(contract_address) .get(&0xffffffff) .cloned() --- a/pallets/evm-contract-helpers/src/lib.rs +++ b/pallets/evm-contract-helpers/src/lib.rs @@ -69,7 +69,7 @@ } #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] + #[pallet::generate_store(trait Store)] pub struct Pallet(_); /// Store owner for contract. @@ -80,9 +80,9 @@ pub(super) type Owner = StorageMap; + /// Deprecated: this storage is deprecated #[pallet::storage] - #[deprecated] - pub(super) type SelfSponsoring = + type SelfSponsoring = StorageMap; /// Store for contract sponsorship state. @@ -349,6 +349,7 @@ } /// Get current sponsoring mode, performing lazy migration from legacy storage + /// Deprecated: this method is for deprecated storage pub fn sponsoring_mode(contract: H160) -> SponsoringModeT { >::get(contract) .or_else(|| { @@ -359,6 +360,7 @@ } /// Reconfigure contract sponsoring mode + /// Deprecated: this method is for deprecated storage pub fn set_sponsoring_mode(contract: H160, mode: SponsoringModeT) { if mode == SponsoringModeT::Disabled { >::remove(contract); --- a/pallets/fungible/src/erc.rs +++ b/pallets/fungible/src/erc.rs @@ -32,7 +32,7 @@ use pallet_evm::{account::CrossAccountId, PrecompileHandle}; use pallet_evm_coder_substrate::{call, dispatch_to_evm}; use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _}; -use sp_core::Get; +use sp_core::{U256, Get}; use crate::{ Allowance, Balance, Config, FungibleHandle, Pallet, SelfWeightOf, TotalSupply, @@ -43,50 +43,50 @@ pub enum ERC20Events { Transfer { #[indexed] - from: address, + from: Address, #[indexed] - to: address, - value: uint256, + to: Address, + value: U256, }, Approval { #[indexed] - owner: address, + owner: Address, #[indexed] - spender: address, - value: uint256, + spender: Address, + value: U256, }, } #[solidity_interface(name = ERC20, events(ERC20Events))] impl FungibleHandle { - fn name(&self) -> Result { + fn name(&self) -> Result { Ok(decode_utf16(self.name.iter().copied()) .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER)) - .collect::()) + .collect::()) } - fn symbol(&self) -> Result { - Ok(string::from_utf8_lossy(&self.token_prefix).into()) + fn symbol(&self) -> Result { + Ok(String::from_utf8_lossy(&self.token_prefix).into()) } - fn total_supply(&self) -> Result { + fn total_supply(&self) -> Result { self.consume_store_reads(1)?; Ok(>::get(self.id).into()) } - fn decimals(&self) -> Result { + fn decimals(&self) -> Result { Ok(if let CollectionMode::Fungible(decimals) = &self.mode { *decimals } else { unreachable!() }) } - fn balance_of(&self, owner: address) -> Result { + fn balance_of(&self, owner: Address) -> Result { self.consume_store_reads(1)?; let owner = T::CrossAccountId::from_eth(owner); let balance = >::get((self.id, owner)); Ok(balance.into()) } #[weight(>::transfer())] - fn transfer(&mut self, caller: caller, to: address, amount: uint256) -> Result { + fn transfer(&mut self, caller: Caller, to: Address, amount: U256) -> Result { let caller = T::CrossAccountId::from_eth(caller); let to = T::CrossAccountId::from_eth(to); let amount = amount.try_into().map_err(|_| "amount overflow")?; @@ -101,10 +101,10 @@ #[weight(>::transfer_from())] fn transfer_from( &mut self, - caller: caller, - from: address, - to: address, - amount: uint256, + caller: Caller, + from: Address, + to: Address, + amount: U256, ) -> Result { let caller = T::CrossAccountId::from_eth(caller); let from = T::CrossAccountId::from_eth(from); @@ -119,7 +119,7 @@ Ok(true) } #[weight(>::approve())] - fn approve(&mut self, caller: caller, spender: address, amount: uint256) -> Result { + fn approve(&mut self, caller: Caller, spender: Address, amount: U256) -> Result { let caller = T::CrossAccountId::from_eth(caller); let spender = T::CrossAccountId::from_eth(spender); let amount = amount.try_into().map_err(|_| "amount overflow")?; @@ -128,7 +128,7 @@ .map_err(dispatch_to_evm::)?; Ok(true) } - fn allowance(&self, owner: address, spender: address) -> Result { + fn allowance(&self, owner: Address, spender: Address) -> Result { self.consume_store_reads(1)?; let owner = T::CrossAccountId::from_eth(owner); let spender = T::CrossAccountId::from_eth(spender); @@ -137,7 +137,7 @@ } /// @notice Returns collection helper contract address - fn collection_helper_address(&self) -> Result
{ + fn collection_helper_address(&self) -> Result
{ Ok(T::ContractAddress::get()) } } @@ -148,7 +148,7 @@ /// @param to account that will receive minted tokens /// @param amount amount of tokens to mint #[weight(>::create_item())] - fn mint(&mut self, caller: caller, to: address, amount: uint256) -> Result { + fn mint(&mut self, caller: Caller, to: Address, amount: U256) -> Result { let caller = T::CrossAccountId::from_eth(caller); let to = T::CrossAccountId::from_eth(to); let amount = amount.try_into().map_err(|_| "amount overflow")?; @@ -167,18 +167,18 @@ T::AccountId: From<[u8; 32]>, { /// @notice A description for the collection. - fn description(&self) -> Result { + fn description(&self) -> Result { Ok(decode_utf16(self.description.iter().copied()) .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER)) - .collect::()) + .collect::()) } #[weight(>::create_item())] fn mint_cross( &mut self, - caller: caller, + caller: Caller, to: pallet_common::eth::CrossAddress, - amount: uint256, + amount: U256, ) -> Result { let caller = T::CrossAccountId::from_eth(caller); let to = to.into_sub_cross_account::()?; @@ -194,9 +194,9 @@ #[weight(>::approve())] fn approve_cross( &mut self, - caller: caller, + caller: Caller, spender: pallet_common::eth::CrossAddress, - amount: uint256, + amount: U256, ) -> Result { let caller = T::CrossAccountId::from_eth(caller); let spender = spender.into_sub_cross_account::()?; @@ -214,7 +214,7 @@ /// @param amount The amount that will be burnt. #[solidity(hide)] #[weight(>::burn_from())] - fn burn_from(&mut self, caller: caller, from: address, amount: uint256) -> Result { + fn burn_from(&mut self, caller: Caller, from: Address, amount: U256) -> Result { let caller = T::CrossAccountId::from_eth(caller); let from = T::CrossAccountId::from_eth(from); let amount = amount.try_into().map_err(|_| "amount overflow")?; @@ -235,9 +235,9 @@ #[weight(>::burn_from())] fn burn_from_cross( &mut self, - caller: caller, + caller: Caller, from: pallet_common::eth::CrossAddress, - amount: uint256, + amount: U256, ) -> Result { let caller = T::CrossAccountId::from_eth(caller); let from = from.into_sub_cross_account::()?; @@ -254,7 +254,7 @@ /// Mint tokens for multiple accounts. /// @param amounts array of pairs of account address and amount #[weight(>::create_multiple_items_ex(amounts.len() as u32))] - fn mint_bulk(&mut self, caller: caller, amounts: Vec<(address, uint256)>) -> Result { + fn mint_bulk(&mut self, caller: Caller, amounts: Vec<(Address, U256)>) -> Result { let caller = T::CrossAccountId::from_eth(caller); let budget = self .recorder @@ -277,9 +277,9 @@ #[weight(>::transfer())] fn transfer_cross( &mut self, - caller: caller, + caller: Caller, to: pallet_common::eth::CrossAddress, - amount: uint256, + amount: U256, ) -> Result { let caller = T::CrossAccountId::from_eth(caller); let to = to.into_sub_cross_account::()?; @@ -295,10 +295,10 @@ #[weight(>::transfer_from())] fn transfer_from_cross( &mut self, - caller: caller, + caller: Caller, from: pallet_common::eth::CrossAddress, to: pallet_common::eth::CrossAddress, - amount: uint256, + amount: U256, ) -> Result { let caller = T::CrossAccountId::from_eth(caller); let from = from.into_sub_cross_account::()?; --- a/pallets/fungible/src/stubs/UniqueFungible.sol +++ b/pallets/fungible/src/stubs/UniqueFungible.sol @@ -274,11 +274,9 @@ /// 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 { + function setCollectionAccess(AccessMode mode) public { require(false, stub_error); mode; dummy = 0; @@ -443,6 +441,14 @@ uint256 sub; } +/// Ethereum representation of `AccessMode` (see [`up_data_structs::AccessMode`]). +enum AccessMode { + /// Access grant for owner and admins. Used as default. + Normal, + /// Like a [`Normal`](AccessMode::Normal) but also users in allow list. + AllowList +} + /// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field. struct CollectionNestingPermission { CollectionPermissionField field; --- a/pallets/nonfungible/src/erc.rs +++ b/pallets/nonfungible/src/erc.rs @@ -43,7 +43,7 @@ use pallet_evm::{account::CrossAccountId, PrecompileHandle}; use pallet_evm_coder_substrate::call; use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _}; -use sp_core::Get; +use sp_core::{U256, Get}; use crate::{ AccountBalance, Config, CreateItemData, NonfungibleHandle, Pallet, TokenData, TokensMinted, @@ -63,8 +63,8 @@ #[solidity(hide)] fn set_token_property_permission( &mut self, - caller: caller, - key: string, + caller: Caller, + key: String, is_mutable: bool, collection_admin: bool, token_owner: bool, @@ -93,7 +93,7 @@ #[weight(>::set_token_property_permissions(permissions.len() as u32))] fn set_token_property_permissions( &mut self, - caller: caller, + caller: Caller, permissions: Vec, ) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); @@ -121,10 +121,10 @@ #[weight(>::set_token_properties(1))] fn set_property( &mut self, - caller: caller, - token_id: uint256, - key: string, - value: bytes, + caller: Caller, + token_id: U256, + key: String, + value: Bytes, ) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?; @@ -154,8 +154,8 @@ #[weight(>::set_token_properties(properties.len() as u32))] fn set_properties( &mut self, - caller: caller, - token_id: uint256, + caller: Caller, + token_id: U256, properties: Vec, ) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); @@ -187,7 +187,7 @@ /// @param key Property key. #[solidity(hide)] #[weight(>::delete_token_properties(1))] - fn delete_property(&mut self, token_id: uint256, caller: caller, key: string) -> Result<()> { + fn delete_property(&mut self, token_id: U256, caller: Caller, key: String) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?; let key = >::from(key) @@ -209,9 +209,9 @@ #[weight(>::delete_token_properties(keys.len() as u32))] fn delete_properties( &mut self, - token_id: uint256, - caller: caller, - keys: Vec, + token_id: U256, + caller: Caller, + keys: Vec, ) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?; @@ -239,7 +239,7 @@ /// @param tokenId ID of the token. /// @param key Property key. /// @return Property value bytes - fn property(&self, token_id: uint256, key: string) -> Result { + fn property(&self, token_id: U256, key: String) -> Result { let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?; let key = >::from(key) .try_into() @@ -261,11 +261,11 @@ /// any transfer, the approved address for that NFT (if any) is reset to none. Transfer { #[indexed] - from: address, + from: Address, #[indexed] - to: address, + to: Address, #[indexed] - token_id: uint256, + token_id: U256, }, /// @dev This emits when the approved address for an NFT is changed or /// reaffirmed. The zero address indicates there is no approved address. @@ -273,30 +273,24 @@ /// address for that NFT (if any) is reset to none. Approval { #[indexed] - owner: address, + owner: Address, #[indexed] - approved: address, + approved: Address, #[indexed] - token_id: uint256, + token_id: U256, }, /// @dev This emits when an operator is enabled or disabled for an owner. /// The operator can manage all NFTs of the owner. #[allow(dead_code)] ApprovalForAll { #[indexed] - owner: address, + owner: Address, #[indexed] - operator: address, + operator: Address, approved: bool, }, } -#[derive(ToLog)] -pub enum ERC721UniqueMintableEvents { - #[allow(dead_code)] - MintingFinished {}, -} - /// @title ERC-721 Non-Fungible Token Standard, optional metadata extension /// @dev See https://eips.ethereum.org/EIPS/eip-721 #[solidity_interface(name = ERC721Metadata, expect_selector = 0x5b5e139f)] @@ -307,14 +301,14 @@ /// @notice A descriptive name for a collection of NFTs in this contract /// @dev real implementation of this function lies in `ERC721UniqueExtensions` #[solidity(hide, rename_selector = "name")] - fn name_proxy(&self) -> Result { + fn name_proxy(&self) -> Result { self.name() } /// @notice An abbreviated name for NFTs in this contract /// @dev real implementation of this function lies in `ERC721UniqueExtensions` #[solidity(hide, rename_selector = "symbol")] - fn symbol_proxy(&self) -> Result { + fn symbol_proxy(&self) -> Result { self.symbol() } @@ -328,7 +322,7 @@ /// /// @return token's const_metadata #[solidity(rename_selector = "tokenURI")] - fn token_uri(&self, token_id: uint256) -> Result { + fn token_uri(&self, token_id: U256) -> Result { let token_id_u32: u32 = token_id.try_into().map_err(|_| "token id overflow")?; match get_token_property(self, token_id_u32, &key::url()).as_deref() { @@ -341,7 +335,7 @@ let base_uri = pallet_common::Pallet::::get_collection_property(self.id, &key::base_uri()) .map(BoundedVec::into_inner) - .map(string::from_utf8) + .map(String::from_utf8) .transpose() .map_err(|e| { Error::Revert(alloc::format!( @@ -374,12 +368,12 @@ /// @param index A counter less than `totalSupply()` /// @return The token identifier for the `index`th NFT, /// (sort order not specified) - fn token_by_index(&self, index: uint256) -> Result { + fn token_by_index(&self, index: U256) -> Result { Ok(index) } /// @dev Not implemented - fn token_of_owner_by_index(&self, _owner: address, _index: uint256) -> Result { + fn token_of_owner_by_index(&self, _owner: Address, _index: U256) -> Result { // TODO: Not implemetable Err("not implemented".into()) } @@ -387,7 +381,7 @@ /// @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 - fn total_supply(&self) -> Result { + fn total_supply(&self) -> Result { self.consume_store_reads(1)?; Ok(>::total_supply(self).into()) } @@ -402,7 +396,7 @@ /// 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 - fn balance_of(&self, owner: address) -> Result { + fn balance_of(&self, owner: Address) -> Result { self.consume_store_reads(1)?; let owner = T::CrossAccountId::from_eth(owner); let balance = >::get((self.id, owner)); @@ -413,7 +407,7 @@ /// about them do throw. /// @param tokenId The identifier for an NFT /// @return The address of the owner of the NFT - fn owner_of(&self, token_id: uint256) -> Result
{ + fn owner_of(&self, token_id: U256) -> Result
{ self.consume_store_reads(1)?; let token: TokenId = token_id.try_into()?; Ok(*>::get((self.id, token)) @@ -425,21 +419,16 @@ #[solidity(rename_selector = "safeTransferFrom")] fn safe_transfer_from_with_data( &mut self, - _from: address, - _to: address, - _token_id: uint256, - _data: bytes, - ) -> Result { + _from: Address, + _to: Address, + _token_id: U256, + _data: Bytes, + ) -> Result<()> { // TODO: Not implemetable Err("not implemented".into()) } /// @dev Not implemented - fn safe_transfer_from( - &mut self, - _from: address, - _to: address, - _token_id: uint256, - ) -> Result { + fn safe_transfer_from(&mut self, _from: Address, _to: Address, _token_id: U256) -> Result<()> { // TODO: Not implemetable Err("not implemented".into()) } @@ -456,11 +445,11 @@ #[weight(>::transfer_from())] fn transfer_from( &mut self, - caller: caller, - from: address, - to: address, - token_id: uint256, - ) -> Result { + caller: Caller, + from: Address, + to: Address, + token_id: U256, + ) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let from = T::CrossAccountId::from_eth(from); let to = T::CrossAccountId::from_eth(to); @@ -481,7 +470,7 @@ /// @param approved The new approved NFT controller /// @param tokenId The NFT to approve #[weight(>::approve())] - fn approve(&mut self, caller: caller, approved: address, token_id: uint256) -> Result { + fn approve(&mut self, caller: Caller, approved: Address, token_id: U256) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let approved = T::CrossAccountId::from_eth(approved); let token = token_id.try_into()?; @@ -498,10 +487,10 @@ #[weight(>::set_allowance_for_all())] fn set_approval_for_all( &mut self, - caller: caller, - operator: address, + caller: Caller, + operator: Address, approved: bool, - ) -> Result { + ) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let operator = T::CrossAccountId::from_eth(operator); @@ -511,14 +500,14 @@ } /// @dev Not implemented - fn get_approved(&self, _token_id: uint256) -> Result
{ + fn get_approved(&self, _token_id: U256) -> Result
{ // TODO: Not implemetable Err("not implemented".into()) } /// @notice Tells whether the given `owner` approves the `operator`. #[weight(>::allowance_for_all())] - fn is_approved_for_all(&self, owner: address, operator: address) -> Result { + fn is_approved_for_all(&self, owner: Address, operator: Address) -> Result { let owner = T::CrossAccountId::from_eth(owner); let operator = T::CrossAccountId::from_eth(operator); @@ -534,7 +523,7 @@ /// operator of the current owner. /// @param tokenId The NFT to approve #[weight(>::burn_item())] - fn burn(&mut self, caller: caller, token_id: uint256) -> Result { + fn burn(&mut self, caller: Caller, token_id: U256) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let token = token_id.try_into()?; @@ -544,18 +533,14 @@ } /// @title ERC721 minting logic. -#[solidity_interface(name = ERC721UniqueMintable, events(ERC721UniqueMintableEvents))] +#[solidity_interface(name = ERC721UniqueMintable)] impl NonfungibleHandle { - fn minting_finished(&self) -> Result { - Ok(false) - } - /// @notice Function to mint a token. /// @param to The new owner /// @return uint256 The id of the newly minted token #[weight(>::create_item())] - fn mint(&mut self, caller: caller, to: address) -> Result { - let token_id: uint256 = >::get(self.id) + fn mint(&mut self, caller: Caller, to: Address) -> Result { + let token_id: U256 = >::get(self.id) .checked_add(1) .ok_or("item id overflow")? .into(); @@ -570,7 +555,7 @@ /// @param tokenId ID of the minted NFT #[solidity(hide, rename_selector = "mint")] #[weight(>::create_item())] - fn mint_check_id(&mut self, caller: caller, to: address, token_id: uint256) -> Result { + fn mint_check_id(&mut self, caller: Caller, to: Address, token_id: U256) -> Result { let caller = T::CrossAccountId::from_eth(caller); let to = T::CrossAccountId::from_eth(to); let token_id: u32 = token_id.try_into()?; @@ -608,11 +593,11 @@ #[weight(>::create_item())] fn mint_with_token_uri( &mut self, - caller: caller, - to: address, - token_uri: string, - ) -> Result { - let token_id: uint256 = >::get(self.id) + caller: Caller, + to: Address, + token_uri: String, + ) -> Result { + let token_id: U256 = >::get(self.id) .checked_add(1) .ok_or("item id overflow")? .into(); @@ -630,10 +615,10 @@ #[weight(>::create_item())] fn mint_with_token_uri_check_id( &mut self, - caller: caller, - to: address, - token_id: uint256, - token_uri: string, + caller: Caller, + to: Address, + token_id: U256, + token_uri: String, ) -> Result { let key = key::url(); let permission = get_token_permission::(self.id, &key)?; @@ -678,11 +663,6 @@ ) .map_err(dispatch_to_evm::)?; Ok(true) - } - - /// @dev Not implemented - fn finish_minting(&mut self, _caller: caller) -> Result { - Err("not implementable".into()) } } @@ -690,12 +670,12 @@ collection: &CollectionHandle, token_id: u32, key: &up_data_structs::PropertyKey, -) -> Result { +) -> Result { collection.consume_store_reads(1)?; let properties = >::try_get((collection.id, token_id)) .map_err(|_| Error::Revert("Token properties not found".into()))?; if let Some(property) = properties.get(key) { - return Ok(string::from_utf8_lossy(property).into()); + return Ok(String::from_utf8_lossy(property).into()); } Err("Property tokenURI not found".into()) @@ -711,7 +691,7 @@ .get(key) .map(Clone::clone) .ok_or_else(|| { - let key = string::from_utf8(key.clone().into_inner()).unwrap_or_default(); + let key = String::from_utf8(key.clone().into_inner()).unwrap_or_default(); Error::Revert(alloc::format!("No permission for key {}", key)) })?; Ok(a) @@ -724,28 +704,28 @@ T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>, { /// @notice A descriptive name for a collection of NFTs in this contract - fn name(&self) -> Result { + fn name(&self) -> Result { Ok(decode_utf16(self.name.iter().copied()) .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER)) - .collect::()) + .collect::()) } /// @notice An abbreviated name for NFTs in this contract - fn symbol(&self) -> Result { - Ok(string::from_utf8_lossy(&self.token_prefix).into()) + fn symbol(&self) -> Result { + Ok(String::from_utf8_lossy(&self.token_prefix).into()) } /// @notice A description for the collection. - fn description(&self) -> Result { + fn description(&self) -> Result { Ok(decode_utf16(self.description.iter().copied()) .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER)) - .collect::()) + .collect::()) } /// Returns the owner (in cross format) of the token. /// /// @param tokenId Id for the token. - fn cross_owner_of(&self, token_id: uint256) -> Result { + fn cross_owner_of(&self, token_id: U256) -> Result { Self::token_owner(&self, token_id.try_into()?) .map(|o| eth::CrossAddress::from_sub_cross_account::(&o)) .ok_or(Error::Revert("key too large".into())) @@ -756,7 +736,7 @@ /// @param tokenId Id for the token. /// @param keys Properties keys. Empty keys for all propertyes. /// @return Vector of properties key/value pairs. - fn properties(&self, token_id: uint256, keys: Vec) -> Result> { + fn properties(&self, token_id: U256, keys: Vec) -> Result> { let keys = keys .into_iter() .map(|key| { @@ -785,10 +765,10 @@ #[weight(>::approve())] fn approve_cross( &mut self, - caller: caller, + caller: Caller, approved: eth::CrossAddress, - token_id: uint256, - ) -> Result { + token_id: U256, + ) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let approved = approved.into_sub_cross_account::()?; let token = token_id.try_into()?; @@ -804,7 +784,7 @@ /// @param to The new owner /// @param tokenId The NFT to transfer #[weight(>::transfer())] - fn transfer(&mut self, caller: caller, to: address, token_id: uint256) -> Result { + fn transfer(&mut self, caller: Caller, to: Address, token_id: U256) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let to = T::CrossAccountId::from_eth(to); let token = token_id.try_into()?; @@ -824,10 +804,10 @@ #[weight(>::transfer())] fn transfer_cross( &mut self, - caller: caller, + caller: Caller, to: eth::CrossAddress, - token_id: uint256, - ) -> Result { + token_id: U256, + ) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let to = to.into_sub_cross_account::()?; let token = token_id.try_into()?; @@ -848,11 +828,11 @@ #[weight(>::transfer())] fn transfer_from_cross( &mut self, - caller: caller, + caller: Caller, from: eth::CrossAddress, to: eth::CrossAddress, - token_id: uint256, - ) -> Result { + token_id: U256, + ) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let from = from.into_sub_cross_account::()?; let to = to.into_sub_cross_account::()?; @@ -873,7 +853,7 @@ /// @param tokenId The NFT to transfer #[solidity(hide)] #[weight(>::burn_from())] - fn burn_from(&mut self, caller: caller, from: address, token_id: uint256) -> Result { + fn burn_from(&mut self, caller: Caller, from: Address, token_id: U256) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let from = T::CrossAccountId::from_eth(from); let token = token_id.try_into()?; @@ -895,10 +875,10 @@ #[weight(>::burn_from())] fn burn_from_cross( &mut self, - caller: caller, + caller: Caller, from: eth::CrossAddress, - token_id: uint256, - ) -> Result { + token_id: U256, + ) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let from = from.into_sub_cross_account::()?; let token = token_id.try_into()?; @@ -912,7 +892,7 @@ } /// @notice Returns next free NFT ID. - fn next_token_id(&self) -> Result { + fn next_token_id(&self) -> Result { self.consume_store_reads(1)?; Ok(>::get(self.id) .checked_add(1) @@ -927,7 +907,7 @@ /// @param tokenIds IDs of the minted NFTs #[solidity(hide)] #[weight(>::create_multiple_items(token_ids.len() as u32))] - fn mint_bulk(&mut self, caller: caller, to: address, token_ids: Vec) -> Result { + fn mint_bulk(&mut self, caller: Caller, to: Address, token_ids: Vec) -> Result { let caller = T::CrossAccountId::from_eth(caller); let to = T::CrossAccountId::from_eth(to); let mut expected_index = >::get(self.id) @@ -966,9 +946,9 @@ #[weight(>::create_multiple_items(tokens.len() as u32))] fn mint_bulk_with_token_uri( &mut self, - caller: caller, - to: address, - tokens: Vec<(uint256, string)>, + caller: Caller, + to: Address, + tokens: Vec<(U256, String)>, ) -> Result { let key = key::url(); let caller = T::CrossAccountId::from_eth(caller); @@ -1017,10 +997,10 @@ #[weight(>::create_item())] fn mint_cross( &mut self, - caller: caller, + caller: Caller, to: eth::CrossAddress, properties: Vec, - ) -> Result { + ) -> Result { let token_id = >::get(self.id) .checked_add(1) .ok_or("item id overflow")?; @@ -1055,7 +1035,7 @@ } /// @notice Returns collection helper contract address - fn collection_helper_address(&self) -> Result
{ + fn collection_helper_address(&self) -> Result
{ Ok(T::ContractAddress::get()) } } --- a/pallets/nonfungible/src/stubs/UniqueNFT.sol +++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol @@ -416,11 +416,9 @@ /// 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 { + function setCollectionAccess(AccessMode mode) public { require(false, stub_error); mode; dummy = 0; @@ -585,6 +583,14 @@ uint256 sub; } +/// Ethereum representation of `AccessMode` (see [`up_data_structs::AccessMode`]). +enum AccessMode { + /// Access grant for owner and admins. Used as default. + Normal, + /// Like a [`Normal`](AccessMode::Normal) but also users in allow list. + AllowList +} + /// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field. struct CollectionNestingPermission { CollectionPermissionField field; @@ -700,22 +706,9 @@ } } -/// @dev inlined interface -contract ERC721UniqueMintableEvents { - event MintingFinished(); -} - /// @title ERC721 minting logic. -/// @dev the ERC-165 identifier for this interface is 0x476ff149 -contract ERC721UniqueMintable is Dummy, ERC165, ERC721UniqueMintableEvents { - /// @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; - } - +/// @dev the ERC-165 identifier for this interface is 0x3fd94ea6 +contract ERC721UniqueMintable is Dummy, ERC165 { /// @notice Function to mint a token. /// @param to The new owner /// @return uint256 The id of the newly minted token @@ -756,7 +749,6 @@ dummy = 0; return 0; } - // /// @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 @@ -774,14 +766,6 @@ // return false; // } - /// @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; - return false; - } } /// @title Unique extensions for ERC721. --- a/pallets/refungible/src/erc.rs +++ b/pallets/refungible/src/erc.rs @@ -39,7 +39,7 @@ use pallet_evm::{account::CrossAccountId, PrecompileHandle}; use pallet_evm_coder_substrate::{call, dispatch_to_evm}; use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _}; -use sp_core::{H160, Get}; +use sp_core::{H160, U256, Get}; use sp_std::{collections::btree_map::BTreeMap, vec::Vec, vec}; use up_data_structs::{ CollectionId, CollectionPropertiesVec, mapping::TokenAddressMapping, Property, PropertyKey, @@ -66,8 +66,8 @@ #[solidity(hide)] fn set_token_property_permission( &mut self, - caller: caller, - key: string, + caller: Caller, + key: String, is_mutable: bool, collection_admin: bool, token_owner: bool, @@ -96,7 +96,7 @@ #[weight(>::set_token_property_permissions(permissions.len() as u32))] fn set_token_property_permissions( &mut self, - caller: caller, + caller: Caller, permissions: Vec, ) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); @@ -124,10 +124,10 @@ #[weight(>::set_token_properties(1))] fn set_property( &mut self, - caller: caller, - token_id: uint256, - key: string, - value: bytes, + caller: Caller, + token_id: U256, + key: String, + value: Bytes, ) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?; @@ -157,8 +157,8 @@ #[weight(>::set_token_properties(properties.len() as u32))] fn set_properties( &mut self, - caller: caller, - token_id: uint256, + caller: Caller, + token_id: U256, properties: Vec, ) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); @@ -190,7 +190,7 @@ /// @param key Property key. #[solidity(hide)] #[weight(>::delete_token_properties(1))] - fn delete_property(&mut self, token_id: uint256, caller: caller, key: string) -> Result<()> { + fn delete_property(&mut self, token_id: U256, caller: Caller, key: String) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?; let key = >::from(key) @@ -212,9 +212,9 @@ #[weight(>::delete_token_properties(keys.len() as u32))] fn delete_properties( &mut self, - token_id: uint256, - caller: caller, - keys: Vec, + token_id: U256, + caller: Caller, + keys: Vec, ) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?; @@ -242,7 +242,7 @@ /// @param tokenId ID of the token. /// @param key Property key. /// @return Property value bytes - fn property(&self, token_id: uint256, key: string) -> Result { + fn property(&self, token_id: U256, key: String) -> Result { let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?; let key = >::from(key) .try_into() @@ -262,37 +262,30 @@ /// may be created and assigned without emitting Transfer. Transfer { #[indexed] - from: address, + from: Address, #[indexed] - to: address, + to: Address, #[indexed] - token_id: uint256, + token_id: U256, }, /// @dev Not supported Approval { #[indexed] - owner: address, + owner: Address, #[indexed] - approved: address, + approved: Address, #[indexed] - token_id: uint256, + token_id: U256, }, /// @dev Not supported #[allow(dead_code)] ApprovalForAll { #[indexed] - owner: address, + owner: Address, #[indexed] - operator: address, + operator: Address, approved: bool, }, -} - -#[derive(ToLog)] -pub enum ERC721UniqueMintableEvents { - /// @dev Not supported - #[allow(dead_code)] - MintingFinished {}, } /// @title ERC-721 Non-Fungible Token Standard, optional metadata extension @@ -305,14 +298,14 @@ /// @notice A descriptive name for a collection of NFTs in this contract /// @dev real implementation of this function lies in `ERC721UniqueExtensions` #[solidity(hide, rename_selector = "name")] - fn name_proxy(&self) -> Result { + fn name_proxy(&self) -> Result { self.name() } /// @notice An abbreviated name for NFTs in this contract /// @dev real implementation of this function lies in `ERC721UniqueExtensions` #[solidity(hide, rename_selector = "symbol")] - fn symbol_proxy(&self) -> Result { + fn symbol_proxy(&self) -> Result { self.symbol() } @@ -326,7 +319,7 @@ /// /// @return token's const_metadata #[solidity(rename_selector = "tokenURI")] - fn token_uri(&self, token_id: uint256) -> Result { + fn token_uri(&self, token_id: U256) -> Result { let token_id_u32: u32 = token_id.try_into().map_err(|_| "token id overflow")?; match get_token_property(self, token_id_u32, &key::url()).as_deref() { @@ -339,7 +332,7 @@ let base_uri = pallet_common::Pallet::::get_collection_property(self.id, &key::base_uri()) .map(BoundedVec::into_inner) - .map(string::from_utf8) + .map(String::from_utf8) .transpose() .map_err(|e| { Error::Revert(alloc::format!( @@ -372,12 +365,12 @@ /// @param index A counter less than `totalSupply()` /// @return The token identifier for the `index`th NFT, /// (sort order not specified) - fn token_by_index(&self, index: uint256) -> Result { + fn token_by_index(&self, index: U256) -> Result { Ok(index) } /// Not implemented - fn token_of_owner_by_index(&self, _owner: address, _index: uint256) -> Result { + fn token_of_owner_by_index(&self, _owner: Address, _index: U256) -> Result { // TODO: Not implemetable Err("not implemented".into()) } @@ -385,7 +378,7 @@ /// @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 - fn total_supply(&self) -> Result { + fn total_supply(&self) -> Result { self.consume_store_reads(1)?; Ok(>::total_supply(self).into()) } @@ -400,7 +393,7 @@ /// 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 - fn balance_of(&self, owner: address) -> Result { + fn balance_of(&self, owner: Address) -> Result { self.consume_store_reads(1)?; let owner = T::CrossAccountId::from_eth(owner); let balance = >::get((self.id, owner)); @@ -414,7 +407,7 @@ /// the tokens that are partially owned. /// @param tokenId The identifier for an RFT /// @return The address of the owner of the RFT - fn owner_of(&self, token_id: uint256) -> Result
{ + fn owner_of(&self, token_id: U256) -> Result
{ self.consume_store_reads(2)?; let token = token_id.try_into()?; let owner = >::token_owner(self.id, token); @@ -427,23 +420,18 @@ #[solidity(rename_selector = "safeTransferFrom")] fn safe_transfer_from_with_data( &mut self, - _from: address, - _to: address, - _token_id: uint256, - _data: bytes, - ) -> Result { + _from: Address, + _to: Address, + _token_id: U256, + _data: Bytes, + ) -> Result<()> { // TODO: Not implemetable Err("not implemented".into()) } /// @dev Not implemented #[solidity(rename_selector = "safeTransferFrom")] - fn safe_transfer_from( - &mut self, - _from: address, - _to: address, - _token_id: uint256, - ) -> Result { + fn safe_transfer_from(&mut self, _from: Address, _to: Address, _token_id: U256) -> Result<()> { // TODO: Not implemetable Err("not implemented".into()) } @@ -461,11 +449,11 @@ #[weight(>::transfer_from_creating_removing())] fn transfer_from( &mut self, - caller: caller, - from: address, - to: address, - token_id: uint256, - ) -> Result { + caller: Caller, + from: Address, + to: Address, + token_id: U256, + ) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let from = T::CrossAccountId::from_eth(from); let to = T::CrossAccountId::from_eth(to); @@ -484,7 +472,7 @@ } /// @dev Not implemented - fn approve(&mut self, _caller: caller, _approved: address, _token_id: uint256) -> Result { + fn approve(&mut self, _caller: Caller, _approved: Address, _token_id: U256) -> Result<()> { Err("not implemented".into()) } @@ -495,10 +483,10 @@ #[weight(>::set_allowance_for_all())] fn set_approval_for_all( &mut self, - caller: caller, - operator: address, + caller: Caller, + operator: Address, approved: bool, - ) -> Result { + ) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let operator = T::CrossAccountId::from_eth(operator); @@ -508,14 +496,14 @@ } /// @dev Not implemented - fn get_approved(&self, _token_id: uint256) -> Result
{ + fn get_approved(&self, _token_id: U256) -> Result
{ // TODO: Not implemetable Err("not implemented".into()) } /// @notice Tells whether the given `owner` approves the `operator`. #[weight(>::allowance_for_all())] - fn is_approved_for_all(&self, owner: address, operator: address) -> Result { + fn is_approved_for_all(&self, owner: Address, operator: Address) -> Result { let owner = T::CrossAccountId::from_eth(owner); let operator = T::CrossAccountId::from_eth(operator); @@ -563,7 +551,7 @@ /// operator of the current owner. /// @param tokenId The RFT to approve #[weight(>::burn_item_fully())] - fn burn(&mut self, caller: caller, token_id: uint256) -> Result { + fn burn(&mut self, caller: Caller, token_id: U256) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let token = token_id.try_into()?; @@ -576,18 +564,14 @@ } /// @title ERC721 minting logic. -#[solidity_interface(name = ERC721UniqueMintable, events(ERC721UniqueMintableEvents))] +#[solidity_interface(name = ERC721UniqueMintable)] impl RefungibleHandle { - fn minting_finished(&self) -> Result { - Ok(false) - } - /// @notice Function to mint a token. /// @param to The new owner /// @return uint256 The id of the newly minted token #[weight(>::create_item())] - fn mint(&mut self, caller: caller, to: address) -> Result { - let token_id: uint256 = >::get(self.id) + fn mint(&mut self, caller: Caller, to: Address) -> Result { + let token_id: U256 = >::get(self.id) .checked_add(1) .ok_or("item id overflow")? .into(); @@ -602,7 +586,7 @@ /// @param tokenId ID of the minted RFT #[solidity(hide, rename_selector = "mint")] #[weight(>::create_item())] - fn mint_check_id(&mut self, caller: caller, to: address, token_id: uint256) -> Result { + fn mint_check_id(&mut self, caller: Caller, to: Address, token_id: U256) -> Result { let caller = T::CrossAccountId::from_eth(caller); let to = T::CrossAccountId::from_eth(to); let token_id: u32 = token_id.try_into()?; @@ -645,11 +629,11 @@ #[weight(>::create_item())] fn mint_with_token_uri( &mut self, - caller: caller, - to: address, - token_uri: string, - ) -> Result { - let token_id: uint256 = >::get(self.id) + caller: Caller, + to: Address, + token_uri: String, + ) -> Result { + let token_id: U256 = >::get(self.id) .checked_add(1) .ok_or("item id overflow")? .into(); @@ -667,10 +651,10 @@ #[weight(>::create_item())] fn mint_with_token_uri_check_id( &mut self, - caller: caller, - to: address, - token_id: uint256, - token_uri: string, + caller: Caller, + to: Address, + token_id: U256, + token_uri: String, ) -> Result { let key = key::url(); let permission = get_token_permission::(self.id, &key)?; @@ -717,11 +701,6 @@ ) .map_err(dispatch_to_evm::)?; Ok(true) - } - - /// @dev Not implemented - fn finish_minting(&mut self, _caller: caller) -> Result { - Err("not implementable".into()) } } @@ -729,12 +708,12 @@ collection: &CollectionHandle, token_id: u32, key: &up_data_structs::PropertyKey, -) -> Result { +) -> Result { collection.consume_store_reads(1)?; let properties = >::try_get((collection.id, token_id)) .map_err(|_| Error::Revert("Token properties not found".into()))?; if let Some(property) = properties.get(key) { - return Ok(string::from_utf8_lossy(property).into()); + return Ok(String::from_utf8_lossy(property).into()); } Err("Property tokenURI not found".into()) @@ -750,7 +729,7 @@ .get(key) .map(Clone::clone) .ok_or_else(|| { - let key = string::from_utf8(key.clone().into_inner()).unwrap_or_default(); + let key = String::from_utf8(key.clone().into_inner()).unwrap_or_default(); Error::Revert(alloc::format!("No permission for key {}", key)) })?; Ok(a) @@ -763,28 +742,28 @@ T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>, { /// @notice A descriptive name for a collection of NFTs in this contract - fn name(&self) -> Result { + fn name(&self) -> Result { Ok(decode_utf16(self.name.iter().copied()) .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER)) - .collect::()) + .collect::()) } /// @notice An abbreviated name for NFTs in this contract - fn symbol(&self) -> Result { - Ok(string::from_utf8_lossy(&self.token_prefix).into()) + fn symbol(&self) -> Result { + Ok(String::from_utf8_lossy(&self.token_prefix).into()) } /// @notice A description for the collection. - fn description(&self) -> Result { + fn description(&self) -> Result { Ok(decode_utf16(self.description.iter().copied()) .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER)) - .collect::()) + .collect::()) } /// Returns the owner (in cross format) of the token. /// /// @param tokenId Id for the token. - fn cross_owner_of(&self, token_id: uint256) -> Result { + fn cross_owner_of(&self, token_id: U256) -> Result { Self::token_owner(&self, token_id.try_into()?) .map(|o| eth::CrossAddress::from_sub_cross_account::(&o)) .ok_or(Error::Revert("key too large".into())) @@ -795,7 +774,7 @@ /// @param tokenId Id for the token. /// @param keys Properties keys. Empty keys for all propertyes. /// @return Vector of properties key/value pairs. - fn properties(&self, token_id: uint256, keys: Vec) -> Result> { + fn properties(&self, token_id: U256, keys: Vec) -> Result> { let keys = keys .into_iter() .map(|key| { @@ -821,7 +800,7 @@ /// @param to The new owner /// @param tokenId The RFT to transfer #[weight(>::transfer_creating_removing())] - fn transfer(&mut self, caller: caller, to: address, token_id: uint256) -> Result { + fn transfer(&mut self, caller: Caller, to: Address, token_id: U256) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let to = T::CrossAccountId::from_eth(to); let token = token_id.try_into()?; @@ -846,10 +825,10 @@ #[weight(>::transfer_creating_removing())] fn transfer_cross( &mut self, - caller: caller, + caller: Caller, to: eth::CrossAddress, - token_id: uint256, - ) -> Result { + token_id: U256, + ) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let to = to.into_sub_cross_account::()?; let token = token_id.try_into()?; @@ -874,11 +853,11 @@ #[weight(>::transfer_creating_removing())] fn transfer_from_cross( &mut self, - caller: caller, + caller: Caller, from: eth::CrossAddress, to: eth::CrossAddress, - token_id: uint256, - ) -> Result { + token_id: U256, + ) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let from = from.into_sub_cross_account::()?; let to = to.into_sub_cross_account::()?; @@ -904,7 +883,7 @@ /// @param tokenId The RFT to transfer #[solidity(hide)] #[weight(>::burn_from())] - fn burn_from(&mut self, caller: caller, from: address, token_id: uint256) -> Result { + fn burn_from(&mut self, caller: Caller, from: Address, token_id: U256) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let from = T::CrossAccountId::from_eth(from); let token = token_id.try_into()?; @@ -930,10 +909,10 @@ #[weight(>::burn_from())] fn burn_from_cross( &mut self, - caller: caller, + caller: Caller, from: eth::CrossAddress, - token_id: uint256, - ) -> Result { + token_id: U256, + ) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let from = from.into_sub_cross_account::()?; let token = token_id.try_into()?; @@ -950,7 +929,7 @@ } /// @notice Returns next free RFT ID. - fn next_token_id(&self) -> Result { + fn next_token_id(&self) -> Result { self.consume_store_reads(1)?; Ok(>::get(self.id) .checked_add(1) @@ -965,7 +944,7 @@ /// @param tokenIds IDs of the minted RFTs #[solidity(hide)] #[weight(>::create_multiple_items(token_ids.len() as u32))] - fn mint_bulk(&mut self, caller: caller, to: address, token_ids: Vec) -> Result { + fn mint_bulk(&mut self, caller: Caller, to: Address, token_ids: Vec) -> Result { let caller = T::CrossAccountId::from_eth(caller); let to = T::CrossAccountId::from_eth(to); let mut expected_index = >::get(self.id) @@ -1010,9 +989,9 @@ #[weight(>::create_multiple_items(tokens.len() as u32))] fn mint_bulk_with_token_uri( &mut self, - caller: caller, - to: address, - tokens: Vec<(uint256, string)>, + caller: Caller, + to: Address, + tokens: Vec<(U256, String)>, ) -> Result { let key = key::url(); let caller = T::CrossAccountId::from_eth(caller); @@ -1067,10 +1046,10 @@ #[weight(>::create_item())] fn mint_cross( &mut self, - caller: caller, + caller: Caller, to: eth::CrossAddress, properties: Vec, - ) -> Result { + ) -> Result { let token_id = >::get(self.id) .checked_add(1) .ok_or("item id overflow")?; @@ -1109,7 +1088,7 @@ /// Returns EVM address for refungible token /// /// @param token ID of the token - fn token_contract_address(&self, token: uint256) -> Result
{ + fn token_contract_address(&self, token: U256) -> Result
{ Ok(T::EvmTokenAddressMapping::token_to_address( self.id, token.try_into().map_err(|_| "token id overflow")?, @@ -1117,7 +1096,7 @@ } /// @notice Returns collection helper contract address - fn collection_helper_address(&self) -> Result
{ + fn collection_helper_address(&self) -> Result
{ Ok(T::ContractAddress::get()) } } --- a/pallets/refungible/src/erc_token.rs +++ b/pallets/refungible/src/erc_token.rs @@ -25,7 +25,8 @@ ops::Deref, }; use evm_coder::{ - abi::AbiType, ToLog, execution::*, generate_stubgen, solidity_interface, types::*, weight, + abi::AbiType, ToLog, execution::*, generate_stubgen, solidity_interface, solidity, types::*, + weight, }; use pallet_common::{ CommonWeightInfo, @@ -36,6 +37,7 @@ use pallet_evm_coder_substrate::{call, dispatch_to_evm, WithRecorder}; use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _}; use sp_std::vec::Vec; +use sp_core::U256; use up_data_structs::TokenId; use crate::{ @@ -50,11 +52,11 @@ #[solidity_interface(name = ERC1633)] impl RefungibleTokenHandle { - fn parent_token(&self) -> Result
{ + fn parent_token(&self) -> Result
{ Ok(collection_id_to_address(self.id)) } - fn parent_token_id(&self) -> Result { + fn parent_token_id(&self) -> Result { Ok(self.1.into()) } } @@ -67,19 +69,19 @@ /// of burning tokens the transfer is to 0. Transfer { #[indexed] - from: address, + from: Address, #[indexed] - to: address, - value: uint256, + to: Address, + value: U256, }, /// @dev This event is emitted when the amount of tokens (value) is approved /// by the owner to be used by the spender. Approval { #[indexed] - owner: address, + owner: Address, #[indexed] - spender: address, - value: uint256, + spender: Address, + value: U256, }, } @@ -90,25 +92,25 @@ #[solidity_interface(name = ERC20, events(ERC20Events))] impl RefungibleTokenHandle { /// @return the name of the token. - fn name(&self) -> Result { + fn name(&self) -> Result { Ok(decode_utf16(self.name.iter().copied()) .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER)) - .collect::()) + .collect::()) } /// @return the symbol of the token. - fn symbol(&self) -> Result { - Ok(string::from_utf8_lossy(&self.token_prefix).into()) + fn symbol(&self) -> Result { + Ok(String::from_utf8_lossy(&self.token_prefix).into()) } /// @dev Total number of tokens in existence - fn total_supply(&self) -> Result { + fn total_supply(&self) -> Result { self.consume_store_reads(1)?; Ok(>::get((self.id, self.1)).into()) } /// @dev Not supported - fn decimals(&self) -> Result { + fn decimals(&self) -> Result { // Decimals aren't supported for refungible tokens Ok(0) } @@ -116,7 +118,7 @@ /// @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. - fn balance_of(&self, owner: address) -> Result { + fn balance_of(&self, owner: Address) -> Result { self.consume_store_reads(1)?; let owner = T::CrossAccountId::from_eth(owner); let balance = >::get((self.id, self.1, owner)); @@ -127,7 +129,7 @@ /// @param to The address to transfer to. /// @param amount The amount to be transferred. #[weight(>::transfer())] - fn transfer(&mut self, caller: caller, to: address, amount: uint256) -> Result { + fn transfer(&mut self, caller: Caller, to: Address, amount: U256) -> Result { let caller = T::CrossAccountId::from_eth(caller); let to = T::CrossAccountId::from_eth(to); let amount = amount.try_into().map_err(|_| "amount overflow")?; @@ -147,10 +149,10 @@ #[weight(>::transfer_from())] fn transfer_from( &mut self, - caller: caller, - from: address, - to: address, - amount: uint256, + caller: Caller, + from: Address, + to: Address, + amount: U256, ) -> Result { let caller = T::CrossAccountId::from_eth(caller); let from = T::CrossAccountId::from_eth(from); @@ -173,7 +175,7 @@ /// @param spender The address which will spend the funds. /// @param amount The amount of tokens to be spent. #[weight(>::approve())] - fn approve(&mut self, caller: caller, spender: address, amount: uint256) -> Result { + fn approve(&mut self, caller: Caller, spender: Address, amount: U256) -> Result { let caller = T::CrossAccountId::from_eth(caller); let spender = T::CrossAccountId::from_eth(spender); let amount = amount.try_into().map_err(|_| "amount overflow")?; @@ -187,7 +189,7 @@ /// @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. - fn allowance(&self, owner: address, spender: address) -> Result { + fn allowance(&self, owner: Address, spender: Address) -> Result { self.consume_store_reads(1)?; let owner = T::CrossAccountId::from_eth(owner); let spender = T::CrossAccountId::from_eth(spender); @@ -206,7 +208,8 @@ /// @param from The account whose tokens will be burnt. /// @param amount The amount that will be burnt. #[weight(>::burn_from())] - fn burn_from(&mut self, caller: caller, from: address, amount: uint256) -> Result { + #[solidity(hide)] + fn burn_from(&mut self, caller: Caller, from: Address, amount: U256) -> Result { let caller = T::CrossAccountId::from_eth(caller); let from = T::CrossAccountId::from_eth(from); let amount = amount.try_into().map_err(|_| "amount overflow")?; @@ -226,9 +229,9 @@ #[weight(>::burn_from())] fn burn_from_cross( &mut self, - caller: caller, + caller: Caller, from: pallet_common::eth::CrossAddress, - amount: uint256, + amount: U256, ) -> Result { let caller = T::CrossAccountId::from_eth(caller); let from = from.into_sub_cross_account::()?; @@ -252,9 +255,9 @@ #[weight(>::approve())] fn approve_cross( &mut self, - caller: caller, + caller: Caller, spender: pallet_common::eth::CrossAddress, - amount: uint256, + amount: U256, ) -> Result { let caller = T::CrossAccountId::from_eth(caller); let spender = spender.into_sub_cross_account::()?; @@ -268,7 +271,7 @@ /// Throws if `msg.sender` doesn't owns all of the tokens. /// @param amount New total amount of the tokens. #[weight(>::repartition_item())] - fn repartition(&mut self, caller: caller, amount: uint256) -> Result { + fn repartition(&mut self, caller: Caller, amount: U256) -> Result { let caller = T::CrossAccountId::from_eth(caller); let amount = amount.try_into().map_err(|_| "amount overflow")?; @@ -282,9 +285,9 @@ #[weight(>::transfer())] fn transfer_cross( &mut self, - caller: caller, + caller: Caller, to: pallet_common::eth::CrossAddress, - amount: uint256, + amount: U256, ) -> Result { let caller = T::CrossAccountId::from_eth(caller); let to = to.into_sub_cross_account::()?; @@ -305,10 +308,10 @@ #[weight(>::transfer_from())] fn transfer_from_cross( &mut self, - caller: caller, + caller: Caller, from: pallet_common::eth::CrossAddress, to: pallet_common::eth::CrossAddress, - amount: uint256, + amount: U256, ) -> Result { let caller = T::CrossAccountId::from_eth(caller); let from = from.into_sub_cross_account::()?; --- a/pallets/refungible/src/stubs/UniqueRefungible.sol +++ b/pallets/refungible/src/stubs/UniqueRefungible.sol @@ -416,11 +416,9 @@ /// 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 { + function setCollectionAccess(AccessMode mode) public { require(false, stub_error); mode; dummy = 0; @@ -585,6 +583,14 @@ uint256 sub; } +/// Ethereum representation of `AccessMode` (see [`up_data_structs::AccessMode`]). +enum AccessMode { + /// Access grant for owner and admins. Used as default. + Normal, + /// Like a [`Normal`](AccessMode::Normal) but also users in allow list. + AllowList +} + /// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field. struct CollectionNestingPermission { CollectionPermissionField field; @@ -700,22 +706,9 @@ } } -/// @dev inlined interface -contract ERC721UniqueMintableEvents { - event MintingFinished(); -} - /// @title ERC721 minting logic. -/// @dev the ERC-165 identifier for this interface is 0x476ff149 -contract ERC721UniqueMintable is Dummy, ERC165, ERC721UniqueMintableEvents { - /// @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; - } - +/// @dev the ERC-165 identifier for this interface is 0x3fd94ea6 +contract ERC721UniqueMintable is Dummy, ERC165 { /// @notice Function to mint a token. /// @param to The new owner /// @return uint256 The id of the newly minted token @@ -756,7 +749,6 @@ dummy = 0; return 0; } - // /// @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 @@ -774,14 +766,6 @@ // return false; // } - /// @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; - return false; - } } /// @title Unique extensions for ERC721. --- a/pallets/refungible/src/stubs/UniqueRefungibleToken.sol +++ b/pallets/refungible/src/stubs/UniqueRefungibleToken.sol @@ -38,19 +38,19 @@ /// @dev the ERC-165 identifier for this interface is 0xe17a7d2b 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 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 burns an amount of the token of a given account, /// deducting from the sender's allowance for said account. --- a/pallets/unique/src/eth/mod.rs +++ b/pallets/unique/src/eth/mod.rs @@ -56,10 +56,10 @@ } fn convert_data( - caller: caller, - name: string, - description: string, - token_prefix: string, + caller: Caller, + name: String, + description: String, + token_prefix: String, ) -> Result<( T::CrossAccountId, CollectionName, @@ -87,13 +87,13 @@ #[inline(always)] fn create_collection_internal( - caller: caller, - value: value, - name: string, + caller: Caller, + value: Value, + name: String, collection_mode: CollectionMode, - description: string, - token_prefix: string, -) -> Result
{ + description: String, + token_prefix: String, +) -> Result
{ let (caller, name, description, token_prefix) = convert_data::(caller, name, description, token_prefix)?; let data = CreateCollectionData { @@ -118,7 +118,7 @@ Ok(address) } -fn check_sent_amount_equals_collection_creation_price(value: value) -> Result<()> { +fn check_sent_amount_equals_collection_creation_price(value: Value) -> Result<()> { let value = value.as_u128(); let creation_price: u128 = T::CollectionCreationPrice::get() .try_into() @@ -149,12 +149,12 @@ #[solidity(rename_selector = "createNFTCollection")] fn create_nft_collection( &mut self, - caller: caller, - value: value, - name: string, - description: string, - token_prefix: string, - ) -> Result
{ + caller: Caller, + value: Value, + name: String, + description: String, + token_prefix: String, + ) -> Result
{ let (caller, name, description, token_prefix) = convert_data::(caller, name, description, token_prefix)?; let data = CreateCollectionData { @@ -188,12 +188,12 @@ #[solidity(hide)] fn create_nonfungible_collection( &mut self, - caller: caller, - value: value, - name: string, - description: string, - token_prefix: string, - ) -> Result
{ + caller: Caller, + value: Value, + name: String, + description: String, + token_prefix: String, + ) -> Result
{ create_collection_internal::( caller, value, @@ -208,12 +208,12 @@ #[solidity(rename_selector = "createRFTCollection")] fn create_rft_collection( &mut self, - caller: caller, - value: value, - name: string, - description: string, - token_prefix: string, - ) -> Result
{ + caller: Caller, + value: Value, + name: String, + description: String, + token_prefix: String, + ) -> Result
{ create_collection_internal::( caller, value, @@ -228,13 +228,13 @@ #[solidity(rename_selector = "createFTCollection")] fn create_fungible_collection( &mut self, - caller: caller, - value: value, - name: string, - decimals: uint8, - description: string, - token_prefix: string, - ) -> Result
{ + caller: Caller, + value: Value, + name: String, + decimals: u8, + description: String, + token_prefix: String, + ) -> Result
{ create_collection_internal::( caller, value, @@ -248,9 +248,9 @@ #[solidity(rename_selector = "makeCollectionERC721MetadataCompatible")] fn make_collection_metadata_compatible( &mut self, - caller: caller, - collection: address, - base_uri: string, + caller: Caller, + collection: Address, + base_uri: String, ) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let collection = @@ -334,7 +334,7 @@ } #[weight(>::destroy_collection())] - fn destroy_collection(&mut self, caller: caller, collection_address: address) -> Result { + fn destroy_collection(&mut self, caller: Caller, collection_address: Address) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let collection_id = pallet_common::eth::map_eth_to_id(&collection_address) @@ -346,7 +346,7 @@ /// Check if a collection exists /// @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 { + fn is_collection_exist(&self, _caller: Caller, collection_address: Address) -> Result { if let Some(id) = pallet_common::eth::map_eth_to_id(&collection_address) { let collection_id = id; return Ok(>::contains_key(collection_id)); @@ -355,7 +355,7 @@ Ok(false) } - fn collection_creation_fee(&self) -> Result { + fn collection_creation_fee(&self) -> Result { let price: u128 = T::CollectionCreationPrice::get() .try_into() .map_err(|_| ()) // workaround for `expect` requiring `Debug` trait @@ -366,14 +366,14 @@ /// Returns address of a collection. /// @param collectionId - CollectionId of the collection /// @return eth mirror address of the collection - fn collection_address(&self, collection_id: uint32) -> Result
{ + fn collection_address(&self, collection_id: u32) -> Result
{ Ok(collection_id_to_address(collection_id.into())) } /// Returns collectionId of a collection. /// @param collectionAddress - Eth address of the collection /// @return collectionId of the collection - fn collection_id(&self, collection_address: address) -> Result { + fn collection_id(&self, collection_address: Address) -> Result { map_eth_to_id(&collection_address) .map(|id| id.0) .ok_or(Error::Revert(format!( --- a/pallets/unique/src/lib.rs +++ b/pallets/unique/src/lib.rs @@ -266,10 +266,12 @@ /// * `token_prefix`: Byte string containing the token prefix to mark a collection /// to which a token belongs (limit [`MAX_TOKEN_PREFIX_LENGTH`]). /// * `mode`: Type of items stored in the collection and type dependent data. - // returns collection ID + /// + /// returns collection ID + /// + /// Deprecated: `create_collection_ex` is more up-to-date and advanced, prefer it instead. #[weight = >::create_collection()] - #[deprecated(note = "`create_collection_ex` is more up-to-date and advanced, prefer it instead")] - pub fn create_collection( + fn create_collection( origin, collection_name: BoundedVec>, collection_description: BoundedVec>, --- a/runtime/common/ethereum/sponsoring/refungible.rs +++ b/runtime/common/ethereum/sponsoring/refungible.rs @@ -265,11 +265,9 @@ match call { // Readonly - ERC165Call(_, _) | MintingFinished => None, + ERC165Call(_, _) => None, - // Not sponsored - FinishMinting => None, - + // Sponsored Mint { .. } | MintCheckId { .. } | MintWithTokenUri { .. } --- a/runtime/tests/src/tests.rs +++ b/runtime/tests/src/tests.rs @@ -323,7 +323,7 @@ .map(|d| { d.into() }) .collect() )); - for (index, data) in items_data.into_iter().enumerate() { + for (index, _data) in items_data.into_iter().enumerate() { let balance = >::get(( CollectionId(1), TokenId((index + 1) as u32), --- a/tests/src/benchmarks/mintFee/benchmark.ts +++ b/tests/src/benchmarks/mintFee/benchmark.ts @@ -293,6 +293,8 @@ const evmContract = await helper.ethNativeContract.collection( helper.ethAddress.fromCollectionId(collection.collectionId), 'nft', + undefined, + true, ); const subTokenId = await evmContract.methods.nextTokenId().call(); @@ -351,9 +353,7 @@ encodedCall = await evmContract.methods .setProperties( subTokenId, - PROPERTIES.slice(0, setup.propertiesNumber).map((p) => { - return {field_0: p.key, field_1: p.value}; - }), + PROPERTIES.slice(0, setup.propertiesNumber), ) .encodeABI(); @@ -394,9 +394,7 @@ .mintToSubstrateBulkProperty( helper.ethAddress.fromCollectionId(collection.collectionId), susbstrateReceiver.addressRaw, - PROPERTIES.slice(0, setup.propertiesNumber).map((p) => { - return {field_0: p.key, field_1: p.value}; - }), + PROPERTIES.slice(0, setup.propertiesNumber), ) .send({from: ethSigner, gas: 25_000_000}); }, --- a/tests/src/benchmarks/mintFee/proxyContract.sol +++ b/tests/src/benchmarks/mintFee/proxyContract.sol @@ -3,21 +3,44 @@ import {CollectionHelpers} from "../../eth/api/CollectionHelpers.sol"; import {ContractHelpers} from "../../eth/api/ContractHelpers.sol"; import {UniqueRefungibleToken} from "../../eth/api/UniqueRefungibleToken.sol"; -import {UniqueRefungible, Collection, EthCrossAccount as RftCrossAccountId, Tuple20 as RftProperties} from "../../eth/api/UniqueRefungible.sol"; -import {UniqueNFT, EthCrossAccount as NftCrossAccountId, Tuple21 as NftProperty, TokenProperties} from "../../eth/api/UniqueNFT.sol"; +import {UniqueRefungible, Collection, CrossAddress as RftCrossAccountId, Property as RftProperty} from "../../eth/api/UniqueRefungible.sol"; +import {UniqueNFT, CrossAddress as NftCrossAccountId, Property as NftProperty} from "../../eth/api/UniqueNFT.sol"; struct Property { string key; bytes value; } +interface SoftDeprecatedMethods { + /// @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; +} + +interface BenchUniqueRefungible is UniqueRefungible, SoftDeprecatedMethods {} +interface BenchUniqueNFT is UniqueNFT, SoftDeprecatedMethods {} + + + contract ProxyMint { bytes32 constant REFUNGIBLE_COLLECTION_TYPE = keccak256(bytes("ReFungible")); bytes32 constant NONFUNGIBLE_COLLECTION_TYPE = keccak256(bytes("NFT")); modifier checkRestrictions(address _collection) { Collection commonContract = Collection(_collection); - require(commonContract.isOwnerOrAdmin(msg.sender), "Only collection admin/owner can call this method"); + require( + commonContract.isOwnerOrAdminCross(RftCrossAccountId(msg.sender, 0)), + "Only collection admin/owner can call this method" + ); _; } @@ -58,9 +81,9 @@ function mintToSubstrateWithProperty( address _collection, uint256 _substrateReceiver, - Property[] calldata properties + Property[] calldata _properties ) external checkRestrictions(_collection) { - uint256 propertiesLength = properties.length; + uint256 propertiesLength = _properties.length; require(propertiesLength > 0, "Properies is empty"); Collection commonContract = Collection(_collection); @@ -68,11 +91,12 @@ uint256 tokenId; if (collectionType == REFUNGIBLE_COLLECTION_TYPE) { - UniqueRefungible rftCollection = UniqueRefungible(_collection); + BenchUniqueRefungible rftCollection = BenchUniqueRefungible(_collection); tokenId = rftCollection.nextTokenId(); rftCollection.mint(address(this)); + for (uint256 i = 0; i < propertiesLength; ++i) { - rftCollection.setProperty(tokenId, properties[i].key, properties[i].value); + rftCollection.setProperty(tokenId, _properties[i].key, _properties[i].value); } rftCollection.transferFromCross( RftCrossAccountId(address(this), 0), @@ -80,10 +104,10 @@ tokenId ); } else if (collectionType == NONFUNGIBLE_COLLECTION_TYPE) { - UniqueNFT nftCollection = UniqueNFT(_collection); + BenchUniqueNFT nftCollection = BenchUniqueNFT(_collection); tokenId = nftCollection.mint(address(this)); for (uint256 i = 0; i < propertiesLength; ++i) { - nftCollection.setProperty(tokenId, properties[i].key, properties[i].value); + nftCollection.setProperty(tokenId, _properties[i].key, _properties[i].value); } nftCollection.transferFromCross( NftCrossAccountId(address(this), 0), --- a/tests/src/check-event/burnItemEvent.test.ts +++ b/tests/src/check-event/burnItemEvent.test.ts @@ -32,6 +32,7 @@ const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); const token = await collection.mintToken(alice, {Substrate: alice.address}); await token.burn(alice); + await helper.wait.newBlocks(1); const event = helper.chainLog[helper.chainLog.length - 1].events as IEvent[]; const eventStrings = event.map(e => `${e.section}.${e.method}`); --- a/tests/src/check-event/createCollectionEvent.test.ts +++ b/tests/src/check-event/createCollectionEvent.test.ts @@ -29,6 +29,7 @@ }); itSub('Check event from createCollection(): ', async ({helper}) => { await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); + await helper.wait.newBlocks(1); const event = helper.chainLog[helper.chainLog.length - 1].events as IEvent[]; const eventStrings = event.map(e => `${e.section}.${e.method}`); --- a/tests/src/check-event/createItemEvent.test.ts +++ b/tests/src/check-event/createItemEvent.test.ts @@ -30,6 +30,7 @@ itSub('Check event from createItem(): ', async ({helper}) => { const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); await collection.mintToken(alice, {Substrate: alice.address}); + await helper.wait.newBlocks(1); const event = helper.chainLog[helper.chainLog.length - 1].events as IEvent[]; const eventStrings = event.map(e => `${e.section}.${e.method}`); --- a/tests/src/check-event/createMultipleItemsEvent.test.ts +++ b/tests/src/check-event/createMultipleItemsEvent.test.ts @@ -35,6 +35,7 @@ {owner: {Substrate: alice.address}}, ]); + await helper.wait.newBlocks(1); const event = helper.chainLog[helper.chainLog.length - 1].events as IEvent[]; const eventStrings = event.map(e => `${e.section}.${e.method}`); --- a/tests/src/check-event/destroyCollectionEvent.test.ts +++ b/tests/src/check-event/destroyCollectionEvent.test.ts @@ -31,6 +31,7 @@ itSub('Check event from destroyCollection(): ', async ({helper}) => { const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); await collection.burn(alice); + await helper.wait.newBlocks(1); const event = helper.chainLog[helper.chainLog.length - 1].events as IEvent[]; const eventStrings = event.map(e => `${e.section}.${e.method}`); --- a/tests/src/check-event/transferEvent.test.ts +++ b/tests/src/check-event/transferEvent.test.ts @@ -34,6 +34,7 @@ const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); const token = await collection.mintToken(alice, {Substrate: alice.address}); await token.transfer(alice, {Substrate: bob.address}); + await helper.wait.newBlocks(1); const event = helper.chainLog[helper.chainLog.length - 1].events as IEvent[]; const eventStrings = event.map(e => `${e.section}.${e.method}`); --- a/tests/src/check-event/transferFromEvent.test.ts +++ b/tests/src/check-event/transferFromEvent.test.ts @@ -33,6 +33,7 @@ const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); const token = await collection.mintToken(alice, {Substrate: alice.address}); await token.transferFrom(alice, {Substrate: alice.address}, {Substrate: bob.address}); + await helper.wait.newBlocks(1); const event = helper.chainLog[helper.chainLog.length - 1].events as IEvent[]; const eventStrings = event.map(e => `${e.section}.${e.method}`); --- a/tests/src/eth/abi/fungible.json +++ b/tests/src/eth/abi/fungible.json @@ -488,7 +488,9 @@ "type": "function" }, { - "inputs": [{ "internalType": "uint8", "name": "mode", "type": "uint8" }], + "inputs": [ + { "internalType": "enum AccessMode", "name": "mode", "type": "uint8" } + ], "name": "setCollectionAccess", "outputs": [], "stateMutability": "nonpayable", --- a/tests/src/eth/abi/nonFungible.json +++ b/tests/src/eth/abi/nonFungible.json @@ -51,12 +51,6 @@ }, { "anonymous": false, - "inputs": [], - "name": "MintingFinished", - "type": "event" - }, - { - "anonymous": false, "inputs": [ { "indexed": true, @@ -420,13 +414,6 @@ "name": "description", "outputs": [{ "internalType": "string", "name": "", "type": "string" }], "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "finishMinting", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], - "stateMutability": "nonpayable", "type": "function" }, { @@ -513,13 +500,6 @@ "name": "mintWithTokenURI", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "mintingFinished", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], - "stateMutability": "view", "type": "function" }, { @@ -650,7 +630,9 @@ "type": "function" }, { - "inputs": [{ "internalType": "uint8", "name": "mode", "type": "uint8" }], + "inputs": [ + { "internalType": "enum AccessMode", "name": "mode", "type": "uint8" } + ], "name": "setCollectionAccess", "outputs": [], "stateMutability": "nonpayable", --- a/tests/src/eth/abi/reFungible.json +++ b/tests/src/eth/abi/reFungible.json @@ -51,12 +51,6 @@ }, { "anonymous": false, - "inputs": [], - "name": "MintingFinished", - "type": "event" - }, - { - "anonymous": false, "inputs": [ { "indexed": true, @@ -402,13 +396,6 @@ "name": "description", "outputs": [{ "internalType": "string", "name": "", "type": "string" }], "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "finishMinting", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], - "stateMutability": "nonpayable", "type": "function" }, { @@ -495,13 +482,6 @@ "name": "mintWithTokenURI", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "mintingFinished", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], - "stateMutability": "view", "type": "function" }, { @@ -632,7 +612,9 @@ "type": "function" }, { - "inputs": [{ "internalType": "uint8", "name": "mode", "type": "uint8" }], + "inputs": [ + { "internalType": "enum AccessMode", "name": "mode", "type": "uint8" } + ], "name": "setCollectionAccess", "outputs": [], "stateMutability": "nonpayable", --- a/tests/src/eth/abi/reFungibleToken.json +++ b/tests/src/eth/abi/reFungibleToken.json @@ -98,16 +98,6 @@ }, { "inputs": [ - { "internalType": "address", "name": "from", "type": "address" }, - { "internalType": "uint256", "name": "amount", "type": "uint256" } - ], - "name": "burnFrom", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ { "components": [ { "internalType": "address", "name": "eth", "type": "address" }, --- a/tests/src/eth/api/UniqueFungible.sol +++ b/tests/src/eth/api/UniqueFungible.sol @@ -175,11 +175,9 @@ /// 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; + function setCollectionAccess(AccessMode mode) external; /// Checks that user allowed to operate with collection. /// @@ -285,6 +283,14 @@ uint256 sub; } +/// Ethereum representation of `AccessMode` (see [`up_data_structs::AccessMode`]). +enum AccessMode { + /// Access grant for owner and admins. Used as default. + Normal, + /// Like a [`Normal`](AccessMode::Normal) but also users in allow list. + AllowList +} + /// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field. struct CollectionNestingPermission { CollectionPermissionField field; --- a/tests/src/eth/api/UniqueNFT.sol +++ b/tests/src/eth/api/UniqueNFT.sol @@ -275,11 +275,9 @@ /// 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; + function setCollectionAccess(AccessMode mode) external; /// Checks that user allowed to operate with collection. /// @@ -385,6 +383,14 @@ uint256 sub; } +/// Ethereum representation of `AccessMode` (see [`up_data_structs::AccessMode`]). +enum AccessMode { + /// Access grant for owner and admins. Used as default. + Normal, + /// Like a [`Normal`](AccessMode::Normal) but also users in allow list. + AllowList +} + /// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field. struct CollectionNestingPermission { CollectionPermissionField field; @@ -481,20 +487,11 @@ /// @dev EVM selector for this function is: 0x42966c68, /// or in textual repr: burn(uint256) function burn(uint256 tokenId) external; -} - -/// @dev inlined interface -interface ERC721UniqueMintableEvents { - event MintingFinished(); } /// @title ERC721 minting logic. -/// @dev the ERC-165 identifier for this interface is 0x476ff149 -interface ERC721UniqueMintable is Dummy, ERC165, ERC721UniqueMintableEvents { - /// @dev EVM selector for this function is: 0x05d2035b, - /// or in textual repr: mintingFinished() - function mintingFinished() external view returns (bool); - +/// @dev the ERC-165 identifier for this interface is 0x3fd94ea6 +interface ERC721UniqueMintable is Dummy, ERC165 { /// @notice Function to mint a token. /// @param to The new owner /// @return uint256 The id of the newly minted token @@ -518,7 +515,6 @@ /// @dev EVM selector for this function is: 0x45c17782, /// or in textual repr: mintWithTokenURI(address,string) function mintWithTokenURI(address to, string memory tokenUri) external returns (uint256); - // /// @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 @@ -529,10 +525,6 @@ // /// or in textual repr: mintWithTokenURI(address,uint256,string) // function mintWithTokenURI(address to, uint256 tokenId, string memory tokenUri) external returns (bool); - /// @dev Not implemented - /// @dev EVM selector for this function is: 0x7d64bcb4, - /// or in textual repr: finishMinting() - function finishMinting() external returns (bool); } /// @title Unique extensions for ERC721. --- a/tests/src/eth/api/UniqueRefungible.sol +++ b/tests/src/eth/api/UniqueRefungible.sol @@ -275,11 +275,9 @@ /// 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; + function setCollectionAccess(AccessMode mode) external; /// Checks that user allowed to operate with collection. /// @@ -385,6 +383,14 @@ uint256 sub; } +/// Ethereum representation of `AccessMode` (see [`up_data_structs::AccessMode`]). +enum AccessMode { + /// Access grant for owner and admins. Used as default. + Normal, + /// Like a [`Normal`](AccessMode::Normal) but also users in allow list. + AllowList +} + /// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field. struct CollectionNestingPermission { CollectionPermissionField field; @@ -481,20 +487,11 @@ /// @dev EVM selector for this function is: 0x42966c68, /// or in textual repr: burn(uint256) function burn(uint256 tokenId) external; -} - -/// @dev inlined interface -interface ERC721UniqueMintableEvents { - event MintingFinished(); } /// @title ERC721 minting logic. -/// @dev the ERC-165 identifier for this interface is 0x476ff149 -interface ERC721UniqueMintable is Dummy, ERC165, ERC721UniqueMintableEvents { - /// @dev EVM selector for this function is: 0x05d2035b, - /// or in textual repr: mintingFinished() - function mintingFinished() external view returns (bool); - +/// @dev the ERC-165 identifier for this interface is 0x3fd94ea6 +interface ERC721UniqueMintable is Dummy, ERC165 { /// @notice Function to mint a token. /// @param to The new owner /// @return uint256 The id of the newly minted token @@ -518,7 +515,6 @@ /// @dev EVM selector for this function is: 0x45c17782, /// or in textual repr: mintWithTokenURI(address,string) function mintWithTokenURI(address to, string memory tokenUri) external returns (uint256); - // /// @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 @@ -529,10 +525,6 @@ // /// or in textual repr: mintWithTokenURI(address,uint256,string) // function mintWithTokenURI(address to, uint256 tokenId, string memory tokenUri) external returns (bool); - /// @dev Not implemented - /// @dev EVM selector for this function is: 0x7d64bcb4, - /// or in textual repr: finishMinting() - function finishMinting() external returns (bool); } /// @title Unique extensions for ERC721. --- a/tests/src/eth/api/UniqueRefungibleToken.sol +++ b/tests/src/eth/api/UniqueRefungibleToken.sol @@ -25,13 +25,13 @@ /// @dev the ERC-165 identifier for this interface is 0xe17a7d2b 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 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 burns an amount of the token of a given account, /// deducting from the sender's allowance for said account. --- a/tests/src/eth/base.test.ts +++ b/tests/src/eth/base.test.ts @@ -108,10 +108,6 @@ await checkInterface(helper, '0x5b5e139f', false, true); }); - itEth('ERC721UniqueMintable - 0x476ff149 - support', async ({helper}) => { - await checkInterface(helper, '0x476ff149', true, true); - }); - itEth('ERC721Enumerable - 0x780e9d63 - support', async ({helper}) => { await checkInterface(helper, '0x780e9d63', true, true); });