--- a/Cargo.lock +++ b/Cargo.lock @@ -2653,8 +2653,9 @@ [[package]] name = "evm-coder" -version = "0.3.6" -source = "git+https://github.com/uniquenetwork/evm-coder?tag=v0.3.6#be59ae41a5d2ec9389bae22d54f81122b6ba55a4" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b88ae5a449e7e9dfef59c0dd2df396bc56d81a6f4e297490c0c64aa73f7f7ad4" dependencies = [ "ethereum", "evm-coder-procedural", @@ -2665,8 +2666,9 @@ [[package]] name = "evm-coder-procedural" -version = "0.3.6" -source = "git+https://github.com/uniquenetwork/evm-coder?tag=v0.3.6#be59ae41a5d2ec9389bae22d54f81122b6ba55a4" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6223c1063c1f53380b4b9aaf2e4d82eba4808c661c61265619b804b09b7a6b1a" dependencies = [ "Inflector", "hex", --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ [workspace.dependencies] # Unique app-promotion-rpc = { path = "primitives/app_promotion_rpc", default-features = false } -evm-coder = { git = "https://github.com/uniquenetwork/evm-coder", tag = "v0.3.6", default-features = false, features = [ +evm-coder = { version = "0.4.2", default-features = false, features = [ 'bondrewd', ] } pallet-app-promotion = { path = "pallets/app-promotion", default-features = false } --- a/pallets/common/Cargo.toml +++ b/pallets/common/Cargo.toml @@ -35,7 +35,8 @@ "sp-std/std", "up-data-structs/std", "up-pov-estimate-rpc/std", + "evm-coder/std", ] -stubgen = ["evm-coder/stubgen"] +stubgen = ["evm-coder/stubgen", "up-data-structs/stubgen"] tests = [] try-runtime = ["frame-support/try-runtime"] --- a/pallets/common/src/eth.rs +++ b/pallets/common/src/eth.rs @@ -549,8 +549,6 @@ /// Collection properties #[derive(Debug, Default, AbiCoder)] pub struct CreateCollectionData { - /// Collection sponsor - pub pending_sponsor: CrossAddress, /// Collection name pub name: String, /// Collection description @@ -571,6 +569,8 @@ pub nesting_settings: CollectionNestingAndPermission, /// Collection limits pub limits: Vec, + /// Collection sponsor + pub pending_sponsor: CrossAddress, /// Extra collection flags pub flags: CollectionFlags, } --- a/pallets/evm-coder-substrate/src/lib.rs +++ b/pallets/evm-coder-substrate/src/lib.rs @@ -26,7 +26,7 @@ use frame_support::dispatch::Weight; use core::marker::PhantomData; -use sp_std::cell::RefCell; +use sp_std::{cell::RefCell, vec::Vec}; use codec::Decode; use frame_support::pallet_prelude::DispatchError; @@ -46,8 +46,8 @@ pub use spez::spez; use evm_coder::{ - abi::{AbiReader, AbiWrite, AbiWriter}, types::{Msg, Value}, + AbiEncode, }; pub use pallet::*; @@ -168,7 +168,7 @@ pub fn evm_to_precompile_output( self, handle: &mut impl PrecompileHandle, - result: execution::Result>, + result: execution::Result>>, ) -> Option { use execution::Error; // We ignore error here, as it should not occur, as we have our own bookkeeping of gas @@ -176,18 +176,13 @@ Some(match result { Ok(Some(v)) => Ok(PrecompileOutput { exit_status: ExitSucceed::Returned, - output: v.finish(), + output: v, }), Ok(None) => return None, - Err(Error::Revert(e)) => { - let mut writer = AbiWriter::new_call(evm_coder::fn_selector!(Error(string))); - (&e as &str).abi_write(&mut writer); - - Err(PrecompileFailure::Revert { - exit_status: ExitRevert::Reverted, - output: writer.finish(), - }) - } + Err(Error::Revert(e)) => Err(PrecompileFailure::Revert { + exit_status: ExitRevert::Reverted, + output: (&e as &str,).abi_encode_call(evm_coder::fn_selector!(Error(string))), + }), Err(Error::Fatal(f)) => Err(PrecompileFailure::Fatal { exit_status: f }), Err(Error::Error(e)) => Err(e.into()), }) @@ -266,7 +261,7 @@ C: evm_coder::Call + PreDispatch, E: evm_coder::Callable + WithRecorder, H: PrecompileHandle, - execution::ResultWithPostInfo: From>, + execution::ResultWithPostInfo>: From>>, { let result = call_internal( handle.context().caller, @@ -282,18 +277,16 @@ e: &mut E, value: Value, input: &[u8], -) -> execution::Result> +) -> execution::Result>> where T: Config, C: evm_coder::Call + PreDispatch, E: Contract + evm_coder::Callable + WithRecorder, - execution::ResultWithPostInfo: From>, + execution::ResultWithPostInfo>: From>>, { - let (selector, mut reader) = AbiReader::new_call(input)?; - let call = C::parse(selector, &mut reader)?; + let call = C::parse_full(input)?; if call.is_none() { - let selector = u32::from_be_bytes(selector); - return Err(format!("unrecognized selector: 0x{selector:0<8x}").into()); + return Err("unrecognized selector".into()); } let call = call.unwrap(); --- a/pallets/evm-contract-helpers/src/eth.rs +++ b/pallets/evm-contract-helpers/src/eth.rs @@ -19,7 +19,7 @@ extern crate alloc; use core::marker::PhantomData; use evm_coder::{ - abi::{AbiWriter, AbiType}, + abi::{AbiType, AbiEncode}, generate_stubgen, solidity_interface, types::*, ToLog, @@ -370,11 +370,8 @@ { return Some(Err(PrecompileFailure::Revert { exit_status: ExitRevert::Reverted, - output: { - let mut writer = AbiWriter::new_call(evm_coder::fn_selector!(Error(string))); - writer.string("Target contract is allowlisted"); - writer.finish() - }, + output: ("target contract is allowlisted",) + .abi_encode_call(evm_coder::fn_selector!(Error(string))), })); } --- a/pallets/gov-origins/src/lib.rs +++ b/pallets/gov-origins/src/lib.rs @@ -31,6 +31,7 @@ #[derive(PartialEq, Eq, Clone, MaxEncodedLen, Encode, Decode, TypeInfo, RuntimeDebug)] #[pallet::origin] + #[non_exhaustive] pub enum Origin { /// Origin able to send proposal from fellowship collective to democracy pallet. FellowshipProposition, --- a/pallets/unique/src/eth/mod.rs +++ b/pallets/unique/src/eth/mod.rs @@ -139,116 +139,114 @@ T: Config + pallet_common::Config + pallet_nonfungible::Config + pallet_refungible::Config, T::AccountId: From<[u8; 32]>, { - /* - /// Create a collection - /// @return address Address of the newly created collection - #[weight(>::create_collection())] - #[solidity(rename_selector = "createCollection")] - fn create_collection( - &mut self, - caller: Caller, - value: Value, - data: eth::CreateCollectionData, - ) -> Result
{ - let (caller, name, description, token_prefix) = - convert_data::(caller, data.name, data.description, data.token_prefix)?; - if data.mode != eth::CollectionMode::Fungible && data.decimals != 0 { - return Err("decimals are only supported for NFT and RFT collections".into()); - } - let mode = match data.mode { - eth::CollectionMode::Fungible => CollectionMode::Fungible(data.decimals), - eth::CollectionMode::Nonfungible => CollectionMode::NFT, - eth::CollectionMode::Refungible => CollectionMode::ReFungible, - }; + /// Create a collection + /// @return address Address of the newly created collection + #[weight(>::create_collection())] + #[solidity(rename_selector = "createCollection")] + fn create_collection( + &mut self, + caller: Caller, + value: Value, + data: eth::CreateCollectionData, + ) -> Result
{ + let (caller, name, description, token_prefix) = + convert_data::(caller, data.name, data.description, data.token_prefix)?; + if data.mode != eth::CollectionMode::Fungible && data.decimals != 0 { + return Err("decimals are only supported for NFT and RFT collections".into()); + } + let mode = match data.mode { + eth::CollectionMode::Fungible => CollectionMode::Fungible(data.decimals), + eth::CollectionMode::Nonfungible => CollectionMode::NFT, + eth::CollectionMode::Refungible => CollectionMode::ReFungible, + }; - let properties: BoundedVec<_, _> = data - .properties - .into_iter() - .map(eth::Property::try_into) - .collect::>>()? - .try_into() - .map_err(|_| "too many properties")?; + let properties: BoundedVec<_, _> = data + .properties + .into_iter() + .map(eth::Property::try_into) + .collect::>>()? + .try_into() + .map_err(|_| "too many properties")?; - let token_property_permissions = - eth::TokenPropertyPermission::into_property_key_permissions( - data.token_property_permissions, - )? - .try_into() - .map_err(|_| "too many property permissions")?; + let token_property_permissions = + eth::TokenPropertyPermission::into_property_key_permissions( + data.token_property_permissions, + )? + .try_into() + .map_err(|_| "too many property permissions")?; - let limits = if !data.limits.is_empty() { - Some( - data.limits - .into_iter() - .collect::>()?, - ) - } else { - None - }; + let limits = if !data.limits.is_empty() { + Some( + data.limits + .into_iter() + .collect::>()?, + ) + } else { + None + }; - let pending_sponsor = data.pending_sponsor.into_option_sub_cross_account::()?; + let pending_sponsor = data.pending_sponsor.into_option_sub_cross_account::()?; - let restricted = if !data.nesting_settings.restricted.is_empty() { - Some( - data.nesting_settings - .restricted - .iter() - .map(map_eth_to_id) - .collect::>>() - .ok_or("can't convert address into collection id")? - .try_into() - .map_err(|_| "too many collections")?, - ) - } else { - None - }; + let restricted = if !data.nesting_settings.restricted.is_empty() { + Some( + data.nesting_settings + .restricted + .iter() + .map(map_eth_to_id) + .collect::>>() + .ok_or("can't convert address into collection id")? + .try_into() + .map_err(|_| "too many collections")?, + ) + } else { + None + }; - let admin_list = data - .admin_list - .into_iter() - .map(|admin| admin.into_sub_cross_account::()) - .collect::>>()?; + let admin_list = data + .admin_list + .into_iter() + .map(|admin| admin.into_sub_cross_account::()) + .collect::>>()?; - let flags = data.flags; - if !flags.is_allowed_for_user() { - return Err("internal flags were used".into()); - } + let flags = data.flags; + if !flags.is_allowed_for_user() { + return Err("internal flags were used".into()); + } - let data = CreateCollectionData { - name, - mode, - description, - token_prefix, - properties, - token_property_permissions, - limits, - pending_sponsor, + let data = CreateCollectionData { + name, + mode, + description, + token_prefix, + properties, + token_property_permissions, + limits, + pending_sponsor, + access: None, + permissions: Some(CollectionPermissions { access: None, - permissions: Some(CollectionPermissions { - access: None, - mint_mode: None, - nesting: Some(NestingPermissions { - token_owner: data.nesting_settings.token_owner, - collection_admin: data.nesting_settings.collection_admin, - restricted, - #[cfg(feature = "runtime-benchmarks")] - permissive: true, - }), + mint_mode: None, + nesting: Some(NestingPermissions { + token_owner: data.nesting_settings.token_owner, + collection_admin: data.nesting_settings.collection_admin, + restricted, + #[cfg(feature = "runtime-benchmarks")] + permissive: true, }), - admin_list, - flags, - }; - check_sent_amount_equals_collection_creation_price::(value)?; - let collection_helpers_address = - T::CrossAccountId::from_eth(::ContractAddress::get()); + }), + admin_list, + flags, + }; + check_sent_amount_equals_collection_creation_price::(value)?; + let collection_helpers_address = + T::CrossAccountId::from_eth(::ContractAddress::get()); - let collection_id = T::CollectionDispatch::create(caller, collection_helpers_address, data) - .map_err(dispatch_to_evm::)?; + let collection_id = T::CollectionDispatch::create(caller, collection_helpers_address, data) + .map_err(dispatch_to_evm::)?; - let address = pallet_common::eth::collection_id_to_address(collection_id); - Ok(address) - } - */ + let address = pallet_common::eth::collection_id_to_address(collection_id); + Ok(address) + } /// Create an NFT collection /// @param name Name of the collection --- a/primitives/data-structs/Cargo.toml +++ b/primitives/data-structs/Cargo.toml @@ -39,3 +39,4 @@ "sp-runtime/std", "sp-std/std", ] +stubgen = ["evm-coder/stubgen"] --- a/runtime/common/config/pallets/mod.rs +++ b/runtime/common/config/pallets/mod.rs @@ -24,7 +24,7 @@ weights::CommonWeights, RelayChainBlockNumberProvider, }, - Runtime, RuntimeEvent, RuntimeCall, RuntimeOrigin, RUNTIME_NAME, TOKEN_SYMBOL, DECIMALS, + Runtime, RuntimeEvent, RuntimeCall, RUNTIME_NAME, TOKEN_SYMBOL, DECIMALS, Balances, }; use frame_support::traits::{ConstU32, ConstU64, Currency}; --- a/runtime/common/ethereum/sponsoring.rs +++ b/runtime/common/ethereum/sponsoring.rs @@ -17,7 +17,7 @@ //! Implements EVM sponsoring logic via TransactionValidityHack use core::{convert::TryInto, marker::PhantomData}; -use evm_coder::{Call, abi::AbiReader}; +use evm_coder::{Call}; use pallet_common::{CollectionHandle, eth::map_eth_to_id}; use pallet_evm::account::CrossAccountId; use pallet_evm_transaction_payment::CallContext; @@ -66,11 +66,11 @@ if let Some(collection_id) = map_eth_to_id(&call_context.contract_address) { let collection = >::new(collection_id)?; let sponsor = collection.sponsorship.sponsor()?.clone(); - let (method_id, mut reader) = AbiReader::new_call(&call_context.input).ok()?; + // let (method_id, mut reader) = AbiReader::new_call(&call_context.input).ok()?; Some(T::CrossAccountId::from_sub(match &collection.mode { CollectionMode::NFT => { let collection = NonfungibleHandle::cast(collection); - let call = >::parse(method_id, &mut reader).ok()??; + let call = >::parse_full(&call_context.input).ok()??; match call { UniqueNFTCall::TokenProperties(call) => match call { TokenPropertiesCall::SetProperty { @@ -161,11 +161,11 @@ } } CollectionMode::ReFungible => { - let call = >::parse(method_id, &mut reader).ok()??; + let call = >::parse_full(&call_context.input).ok()??; refungible::call_sponsor(call, collection, who).map(|()| sponsor) } CollectionMode::Fungible(_) => { - let call = >::parse(method_id, &mut reader).ok()??; + let call = >::parse_full(&call_context.input).ok()??; match call { UniqueFungibleCall::ERC20(ERC20Call::Transfer { .. }) => { withdraw_transfer::(&collection, who, &TokenId::default()) @@ -196,8 +196,7 @@ // Token existance isn't checked at this point and should be checked in `withdraw` method. let token = RefungibleTokenHandle(rft_collection, token_id); - let (method_id, mut reader) = AbiReader::new_call(&call_context.input).ok()?; - let call = >::parse(method_id, &mut reader).ok()??; + let call = >::parse_full(&call_context.input).ok()??; Some(T::CrossAccountId::from_sub( refungible::token_call_sponsor(call, token, who).map(|()| sponsor)?, )) --- a/tests/src/eth/abi/collectionHelpers.json +++ b/tests/src/eth/abi/collectionHelpers.json @@ -77,15 +77,6 @@ "inputs": [ { "components": [ - { - "components": [ - { "internalType": "address", "name": "eth", "type": "address" }, - { "internalType": "uint256", "name": "sub", "type": "uint256" } - ], - "internalType": "struct CrossAddress", - "name": "pending_sponsor", - "type": "tuple" - }, { "internalType": "string", "name": "name", "type": "string" }, { "internalType": "string", "name": "description", "type": "string" }, { @@ -170,6 +161,15 @@ "type": "tuple[]" }, { + "components": [ + { "internalType": "address", "name": "eth", "type": "address" }, + { "internalType": "uint256", "name": "sub", "type": "uint256" } + ], + "internalType": "struct CrossAddress", + "name": "pending_sponsor", + "type": "tuple" + }, + { "internalType": "CollectionFlags", "name": "flags", "type": "uint8" --- a/tests/src/eth/util/playgrounds/types.ts +++ b/tests/src/eth/util/playgrounds/types.ts @@ -59,8 +59,8 @@ } export enum CollectionMode { + Nonfungible, Fungible, - Nonfungible, Refungible, } @@ -129,4 +129,4 @@ else this.decimals = 0; } -} \ No newline at end of file +} --- a/tests/src/eth/util/playgrounds/unique.dev.ts +++ b/tests/src/eth/util/playgrounds/unique.dev.ts @@ -216,7 +216,6 @@ } const tx = collectionHelper.methods.createCollection([ - this.data.pendingSponsor, this.data.name, this.data.description, this.data.tokenPrefix, @@ -227,6 +226,7 @@ this.data.adminList, this.data.nestingSettings, this.data.limits, + this.data.pendingSponsor, this.data.flags, ]); return tx;