--- a/Cargo.lock +++ b/Cargo.lock @@ -5912,6 +5912,7 @@ name = "pallet-common" version = "0.1.0" dependencies = [ + "ethereum", "evm-coder", "fp-evm-mapping", "frame-benchmarking", --- a/Makefile +++ b/Makefile @@ -16,12 +16,12 @@ CONTRACT_HELPERS_ABI=./tests/src/eth/util/contractHelpersAbi.json COLLECTION_HELPER_STUBS=./pallets/unique/src/eth/stubs/ -COLLECTION_HELPER_ABI=./tests/src/eth/collectionHelperAbi.json +COLLECTION_HELPER_ABI=./tests/src/eth/collectionHelpersAbi.json TESTS_API=./tests/src/eth/api/ .PHONY: regenerate_solidity -regenerate_solidity: UniqueFungible.sol UniqueNFT.sol ContractHelpers.sol CollectionHelper.sol +regenerate_solidity: UniqueFungible.sol UniqueNFT.sol ContractHelpers.sol CollectionHelpers.sol UniqueFungible.sol: PACKAGE=pallet-fungible NAME=erc::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh @@ -35,7 +35,7 @@ PACKAGE=pallet-evm-contract-helpers NAME=eth::contract_helpers_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh PACKAGE=pallet-evm-contract-helpers NAME=eth::contract_helpers_impl OUTPUT=$(CONTRACT_HELPERS_STUBS)/$@ ./.maintain/scripts/generate_sol.sh -CollectionHelper.sol: +CollectionHelpers.sol: PACKAGE=pallet-unique NAME=eth::collection_helper_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh PACKAGE=pallet-unique NAME=eth::collection_helper_impl OUTPUT=$(COLLECTION_HELPER_STUBS)/$@ ./.maintain/scripts/generate_sol.sh @@ -51,11 +51,11 @@ INPUT=$(CONTRACT_HELPERS_STUBS)/$< OUTPUT=$(CONTRACT_HELPERS_STUBS)/ContractHelpers.raw ./.maintain/scripts/compile_stub.sh INPUT=$(CONTRACT_HELPERS_STUBS)/$< OUTPUT=$(CONTRACT_HELPERS_ABI) ./.maintain/scripts/generate_abi.sh -CollectionHelper: CollectionHelper.sol - INPUT=$(COLLECTION_HELPER_STUBS)/$< OUTPUT=$(COLLECTION_HELPER_STUBS)/CollectionHelper.raw ./.maintain/scripts/compile_stub.sh +CollectionHelpers: CollectionHelpers.sol + INPUT=$(COLLECTION_HELPER_STUBS)/$< OUTPUT=$(COLLECTION_HELPER_STUBS)/CollectionHelpers.raw ./.maintain/scripts/compile_stub.sh INPUT=$(COLLECTION_HELPER_STUBS)/$< OUTPUT=$(COLLECTION_HELPER_ABI) ./.maintain/scripts/generate_abi.sh -evm_stubs: UniqueFungible UniqueNFT ContractHelpers CollectionHelper +evm_stubs: UniqueFungible UniqueNFT ContractHelpers CollectionHelpers .PHONY: _bench _bench: --- a/pallets/common/Cargo.toml +++ b/pallets/common/Cargo.toml @@ -21,6 +21,7 @@ up-data-structs = { default-features = false, path = '../../primitives/data-structs' } pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' } evm-coder = { default-features = false, path = '../../crates/evm-coder' } +ethereum = { version = "0.12.0", default-features = false } pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.21-logs" } serde = { version = "1.0.130", default-features = false } --- a/pallets/common/src/dispatch.rs +++ b/pallets/common/src/dispatch.rs @@ -56,7 +56,10 @@ } pub trait CollectionDispatch { - fn create(sender: T::AccountId, data: CreateCollectionData) -> DispatchResult; + fn create( + sender: T::CrossAccountId, + data: CreateCollectionData, + ) -> DispatchResult; fn destroy(sender: T::CrossAccountId, handle: CollectionHandle) -> DispatchResult; fn dispatch(handle: CollectionHandle) -> Self; --- a/pallets/common/src/erc.rs +++ b/pallets/common/src/erc.rs @@ -15,7 +15,7 @@ // along with Unique Network. If not, see . use evm_coder::{ - solidity_interface, solidity, + solidity_interface, solidity, ToLog, types::*, execution::{Result, Error}, }; @@ -28,6 +28,16 @@ use crate::{Pallet, CollectionHandle, Config, CollectionProperties}; +#[derive(ToLog)] +pub enum CollectionHelpersEvents { + CollectionCreated { + #[indexed] + owner: address, + #[indexed] + collection_id: address, + }, +} + /// Does not always represent a full collection, for RFT it is either /// collection (Implementing ERC721), or specific collection token (Implementing ERC20) pub trait CommonEvmHandler { --- a/pallets/common/src/lib.rs +++ b/pallets/common/src/lib.rs @@ -21,12 +21,12 @@ use core::ops::{Deref, DerefMut}; use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder}; use sp_std::vec::Vec; -use pallet_evm::account::CrossAccountId; +use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm}; +use evm_coder::ToLog; use frame_support::{ dispatch::{DispatchErrorWithPostInfo, DispatchResultWithPostInfo, Weight, PostDispatchInfo}, ensure, traits::{Imbalance, Get, Currency, WithdrawReasons, ExistenceRequirement}, - BoundedVec, weights::Pays, transactional, }; @@ -54,7 +54,6 @@ CreateItemExData, SponsoringRateLimit, budget::Budget, - COLLECTION_FIELD_LIMIT, PhantomType, Property, Properties, @@ -218,7 +217,11 @@ #[pallet::config] pub trait Config: - frame_system::Config + pallet_evm_coder_substrate::Config + TypeInfo + account::Config + frame_system::Config + + pallet_evm_coder_substrate::Config + + pallet_evm::Config + + TypeInfo + + account::Config { type WeightInfo: WeightInfo; type Event: IsType<::Event> + From>; @@ -232,6 +235,7 @@ type CollectionDispatch: CollectionDispatch; type TreasuryAccountId: Get; + type ContractAddress: Get; type EvmTokenAddressMapping: TokenAddressMapping; type CrossTokenAddressMapping: TokenAddressMapping; @@ -722,7 +726,7 @@ impl Pallet { pub fn init_collection( - owner: T::AccountId, + owner: T::CrossAccountId, data: CreateCollectionData, ) -> Result { { @@ -748,7 +752,7 @@ // ========= let collection = Collection { - owner: owner.clone(), + owner: owner.as_sub().clone(), name: data.name, mode: data.mode.clone(), description: data.description, @@ -794,7 +798,7 @@ ), ); ::Currency::settle( - &owner, + &owner.as_sub(), imbalance, WithdrawReasons::TRANSFER, ExistenceRequirement::KeepAlive, @@ -803,7 +807,18 @@ } >::put(created_count); - >::deposit_event(Event::CollectionCreated(id, data.mode.id(), owner.clone())); + >::deposit_event(Event::CollectionCreated( + id, + data.mode.id(), + owner.as_sub().clone(), + )); + >::deposit_log( + erc::CollectionHelpersEvents::CollectionCreated { + owner: *owner.as_eth(), + collection_id: eth::collection_id_to_address(id), + } + .to_log(T::ContractAddress::get()), + ); >::insert(id, collection); Ok(id) } --- a/pallets/evm-coder-substrate/src/lib.rs +++ b/pallets/evm-coder-substrate/src/lib.rs @@ -66,9 +66,7 @@ } #[pallet::config] - pub trait Config: frame_system::Config { - type GasWeightMapping: pallet_evm::GasWeightMapping; - } + pub trait Config: frame_system::Config + pallet_evm::Config {} #[pallet::pallet] pub struct Pallet(_); --- a/pallets/fungible/src/lib.rs +++ b/pallets/fungible/src/lib.rs @@ -134,7 +134,7 @@ impl Pallet { pub fn init_collection( - owner: T::AccountId, + owner: T::CrossAccountId, data: CreateCollectionData, ) -> Result { >::init_collection(owner, data) --- a/pallets/fungible/src/stubs/UniqueFungible.sol +++ b/pallets/fungible/src/stubs/UniqueFungible.sol @@ -127,7 +127,7 @@ } } -// Selector: f5652829 +// Selector: c894dc35 contract Collection is Dummy, ERC165 { // Selector: setCollectionProperty(string,bytes) 2f073f66 function setCollectionProperty(string memory key, bytes memory value) @@ -173,8 +173,16 @@ dummy = 0; } - // Selector: setLimit(string,string) bf4d2014 - function setLimit(string memory limit, string memory value) public { + // Selector: setLimit(string,uint32) 68db30ca + function setLimit(string memory limit, uint32 value) public { + require(false, stub_error); + limit; + value; + dummy = 0; + } + + // Selector: setLimit(string,bool) ea67e4c2 + function setLimit(string memory limit, bool value) public { require(false, stub_error); limit; value; --- a/pallets/nonfungible/src/lib.rs +++ b/pallets/nonfungible/src/lib.rs @@ -295,7 +295,7 @@ // unchecked calls skips any permission checks impl Pallet { pub fn init_collection( - owner: T::AccountId, + owner: T::CrossAccountId, data: CreateCollectionData, ) -> Result { >::init_collection(owner, data) --- a/pallets/nonfungible/src/stubs/UniqueNFT.sol +++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol @@ -330,57 +330,7 @@ } } -// Selector: d74d154f -contract ERC721UniqueExtensions is Dummy, ERC165 { - // Selector: transfer(address,uint256) a9059cbb - function transfer(address to, uint256 tokenId) public { - require(false, stub_error); - to; - tokenId; - dummy = 0; - } - - // Selector: burnFrom(address,uint256) 79cc6790 - function burnFrom(address from, uint256 tokenId) public { - require(false, stub_error); - from; - tokenId; - dummy = 0; - } - - // Selector: nextTokenId() 75794a3c - function nextTokenId() public view returns (uint256) { - require(false, stub_error); - dummy; - return 0; - } - - // Selector: mintBulk(address,uint256[]) 44a9945e - function mintBulk(address to, uint256[] memory tokenIds) - public - returns (bool) - { - require(false, stub_error); - to; - tokenIds; - dummy = 0; - return false; - } - - // Selector: mintBulkWithTokenURI(address,(uint256,string)[]) 36543006 - function mintBulkWithTokenURI(address to, Tuple0[] memory tokens) - public - returns (bool) - { - require(false, stub_error); - to; - tokens; - dummy = 0; - return false; - } -} - -// Selector: f5652829 +// Selector: c894dc35 contract Collection is Dummy, ERC165 { // Selector: setCollectionProperty(string,bytes) 2f073f66 function setCollectionProperty(string memory key, bytes memory value) @@ -426,8 +376,16 @@ dummy = 0; } - // Selector: setLimit(string,string) bf4d2014 - function setLimit(string memory limit, string memory value) public { + // Selector: setLimit(string,uint32) 68db30ca + function setLimit(string memory limit, uint32 value) public { + require(false, stub_error); + limit; + value; + dummy = 0; + } + + // Selector: setLimit(string,bool) ea67e4c2 + function setLimit(string memory limit, bool value) public { require(false, stub_error); limit; value; @@ -442,6 +400,56 @@ } } +// Selector: d74d154f +contract ERC721UniqueExtensions is Dummy, ERC165 { + // Selector: transfer(address,uint256) a9059cbb + function transfer(address to, uint256 tokenId) public { + require(false, stub_error); + to; + tokenId; + dummy = 0; + } + + // Selector: burnFrom(address,uint256) 79cc6790 + function burnFrom(address from, uint256 tokenId) public { + require(false, stub_error); + from; + tokenId; + dummy = 0; + } + + // Selector: nextTokenId() 75794a3c + function nextTokenId() public view returns (uint256) { + require(false, stub_error); + dummy; + return 0; + } + + // Selector: mintBulk(address,uint256[]) 44a9945e + function mintBulk(address to, uint256[] memory tokenIds) + public + returns (bool) + { + require(false, stub_error); + to; + tokenIds; + dummy = 0; + return false; + } + + // Selector: mintBulkWithTokenURI(address,(uint256,string)[]) 36543006 + function mintBulkWithTokenURI(address to, Tuple0[] memory tokens) + public + returns (bool) + { + require(false, stub_error); + to; + tokens; + dummy = 0; + return false; + } +} + contract UniqueNFT is Dummy, ERC165, --- a/pallets/proxy-rmrk-core/src/lib.rs +++ b/pallets/proxy-rmrk-core/src/lib.rs @@ -139,7 +139,8 @@ ..Default::default() }; - let collection_id_res = >::init_collection(sender.clone(), data); + let collection_id_res = + >::init_collection(T::CrossAccountId::from_sub(sender.clone()), data); if let Err(DispatchError::Arithmetic(_)) = &collection_id_res { return Err(>::NoAvailableCollectionId.into()); --- a/pallets/proxy-rmrk-equip/src/lib.rs +++ b/pallets/proxy-rmrk-equip/src/lib.rs @@ -94,7 +94,7 @@ ..Default::default() }; - let collection_id_res = >::init_collection(sender.clone(), data); + let collection_id_res = >::init_collection(cross_sender.clone(), data); if let Err(DispatchError::Arithmetic(_)) = &collection_id_res { return Err(>::NoAvailableBaseId.into()); --- a/pallets/refungible/src/lib.rs +++ b/pallets/refungible/src/lib.rs @@ -197,7 +197,7 @@ // unchecked calls skips any permission checks impl Pallet { pub fn init_collection( - owner: T::AccountId, + owner: T::CrossAccountId, data: CreateCollectionData, ) -> Result { >::init_collection(owner, data) --- a/pallets/unique/src/eth/mod.rs +++ b/pallets/unique/src/eth/mod.rs @@ -24,14 +24,17 @@ MAX_COLLECTION_NAME_LENGTH, }; use frame_support::traits::Get; -use pallet_common::{CollectionById, erc::token_uri_key}; +use pallet_common::{ + CollectionById, + erc::{token_uri_key, CollectionHelpersEvents}, +}; use crate::{SelfWeightOf, Config, weights::WeightInfo}; use sp_std::vec::Vec; use alloc::format; -struct EvmCollectionHelper(SubstrateRecorder); -impl WithRecorder for EvmCollectionHelper { +struct EvmCollectionHelpers(SubstrateRecorder); +impl WithRecorder for EvmCollectionHelpers { fn recorder(&self) -> &SubstrateRecorder { &self.0 } @@ -41,8 +44,8 @@ } } -#[solidity_interface(name = "CollectionHelper")] -impl EvmCollectionHelper { +#[solidity_interface(name = "CollectionHelpers", events(CollectionHelpersEvents))] +impl EvmCollectionHelpers { #[weight(>::create_collection())] fn create_nonfungible_collection( &self, @@ -89,9 +92,8 @@ ..Default::default() }; - let collection_id = - >::init_collection(caller.as_sub().clone(), data) - .map_err(pallet_evm_coder_substrate::dispatch_to_evm::)?; + let collection_id = >::init_collection(caller.clone(), data) + .map_err(pallet_evm_coder_substrate::dispatch_to_evm::)?; let address = pallet_common::eth::collection_id_to_address(collection_id); Ok(address) @@ -107,8 +109,8 @@ } } -pub struct CollectionHelperOnMethodCall(PhantomData<*const T>); -impl OnMethodCall for CollectionHelperOnMethodCall { +pub struct CollectionHelpersOnMethodCall(PhantomData<*const T>); +impl OnMethodCall for CollectionHelpersOnMethodCall { fn is_reserved(contract: &sp_core::H160) -> bool { contract == &T::ContractAddress::get() } @@ -128,18 +130,18 @@ return None; } - let helpers = EvmCollectionHelper::(SubstrateRecorder::::new(gas_left)); + let helpers = EvmCollectionHelpers::(SubstrateRecorder::::new(gas_left)); pallet_evm_coder_substrate::call(*source, helpers, value, input) } fn get_code(contract: &sp_core::H160) -> Option> { (contract == &T::ContractAddress::get()) - .then(|| include_bytes!("./stubs/CollectionHelper.raw").to_vec()) + .then(|| include_bytes!("./stubs/CollectionHelpers.raw").to_vec()) } } -generate_stubgen!(collection_helper_impl, CollectionHelperCall<()>, true); -generate_stubgen!(collection_helper_iface, CollectionHelperCall<()>, false); +generate_stubgen!(collection_helper_impl, CollectionHelpersCall<()>, true); +generate_stubgen!(collection_helper_iface, CollectionHelpersCall<()>, false); fn error_feild_too_long(feild: &str, bound: u32) -> Error { Error::Revert(format!("{} is too long. Max length is {}.", feild, bound)) --- a/pallets/unique/src/eth/stubs/CollectionHelper.sol +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: OTHER -// This code is automatically generated - -pragma solidity >=0.8.0 <0.9.0; - -// Common stubs holder -contract Dummy { - uint8 dummy; - string stub_error = "this contract is implemented in native"; -} - -contract ERC165 is Dummy { - function supportsInterface(bytes4 interfaceID) - external - view - returns (bool) - { - require(false, stub_error); - interfaceID; - return true; - } -} - -// Selector: 56c215c5 -contract CollectionHelper is Dummy, ERC165 { - // Selector: create721Collection(string,string,string) 951c0151 - function create721Collection( - string memory name, - string memory description, - string memory tokenPrefix - ) public view returns (address) { - require(false, stub_error); - name; - description; - tokenPrefix; - dummy; - return 0x0000000000000000000000000000000000000000; - } - - // Selector: isCollectionExist(address) c3de1494 - function isCollectionExist(address collectionAddress) - public - view - returns (bool) - { - require(false, stub_error); - collectionAddress; - dummy; - return false; - } -} --- /dev/null +++ b/pallets/unique/src/eth/stubs/CollectionHelpers.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: OTHER +// This code is automatically generated + +pragma solidity >=0.8.0 <0.9.0; + +// Common stubs holder +contract Dummy { + uint8 dummy; + string stub_error = "this contract is implemented in native"; +} + +contract ERC165 is Dummy { + function supportsInterface(bytes4 interfaceID) + external + view + returns (bool) + { + require(false, stub_error); + interfaceID; + return true; + } +} + +// Inline +contract CollectionHelpersEvents { + event CollectionCreated( + address indexed owner, + address indexed collectionId + ); +} + +// Selector: 20947cd0 +contract CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents { + // Selector: createNonfungibleCollection(string,string,string) e34a6844 + function createNonfungibleCollection( + string memory name, + string memory description, + string memory tokenPrefix + ) public view returns (address) { + require(false, stub_error); + name; + description; + tokenPrefix; + dummy; + return 0x0000000000000000000000000000000000000000; + } + + // Selector: isCollectionExist(address) c3de1494 + function isCollectionExist(address collectionAddress) + public + view + returns (bool) + { + require(false, stub_error); + collectionAddress; + dummy; + return false; + } +} --- a/pallets/unique/src/lib.rs +++ b/pallets/unique/src/lib.rs @@ -30,10 +30,9 @@ ensure, weights::{Weight}, transactional, - pallet_prelude::{DispatchResultWithPostInfo, ConstU32, Get}, + pallet_prelude::{DispatchResultWithPostInfo, ConstU32}, BoundedVec, }; -use sp_core::H160; use scale_info::TypeInfo; use frame_system::{self as system, ensure_signed}; use sp_runtime::{sp_std::prelude::Vec}; @@ -75,7 +74,6 @@ /// Weight information for extrinsics in this pallet. type WeightInfo: WeightInfo; type CommonWeightInfo: CommonWeightInfo; - type ContractAddress: Get; } decl_event! { @@ -287,7 +285,7 @@ // ========= - T::CollectionDispatch::create(sender, data)?; + T::CollectionDispatch::create(T::CrossAccountId::from_sub(sender), data)?; Ok(()) } --- a/runtime/common/src/dispatch.rs +++ b/runtime/common/src/dispatch.rs @@ -30,7 +30,10 @@ + pallet_nonfungible::Config + pallet_refungible::Config, { - fn create(sender: T::AccountId, data: CreateCollectionData) -> DispatchResult { + fn create( + sender: T::CrossAccountId, + data: CreateCollectionData, + ) -> DispatchResult { let _id = match data.mode { CollectionMode::NFT => >::init_collection(sender, data)?, CollectionMode::Fungible(decimal_points) => { --- a/runtime/opal/src/lib.rs +++ b/runtime/opal/src/lib.rs @@ -306,7 +306,7 @@ pallet_evm_migration::OnMethodCall, pallet_evm_contract_helpers::HelpersOnMethodCall, CollectionDispatchT, - pallet_unique::eth::CollectionHelperOnMethodCall, + pallet_unique::eth::CollectionHelpersOnMethodCall, ); type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate; type ChainId = ChainId; @@ -821,9 +821,7 @@ XcmpQueue, ); -impl pallet_evm_coder_substrate::Config for Runtime { - type GasWeightMapping = FixedGasWeightMapping; -} +impl pallet_evm_coder_substrate::Config for Runtime {} impl pallet_xcm::Config for Runtime { type Event = Event; @@ -885,6 +883,7 @@ type EvmTokenAddressMapping = EvmTokenAddressMapping; type CrossTokenAddressMapping = CrossTokenAddressMapping; + type ContractAddress = EvmCollectionHelpersAddress; } impl pallet_structure::Config for Runtime { @@ -917,7 +916,6 @@ type Event = Event; type WeightInfo = pallet_unique::weights::SubstrateWeight; type CommonWeightInfo = CommonWeights; - type ContractAddress = EvmCollectionHelperAddress; } parameter_types! { @@ -980,7 +978,7 @@ ]); // 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f - pub const EvmCollectionHelperAddress: H160 = H160([ + pub const EvmCollectionHelpersAddress: H160 = H160([ 0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f, ]); } --- a/runtime/quartz/src/lib.rs +++ b/runtime/quartz/src/lib.rs @@ -285,7 +285,7 @@ pallet_evm_migration::OnMethodCall, pallet_evm_contract_helpers::HelpersOnMethodCall, CollectionDispatchT, - pallet_unique::eth::CollectionHelperOnMethodCall, + pallet_unique::eth::CollectionHelpersOnMethodCall, ); type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate; type ChainId = ChainId; @@ -800,9 +800,7 @@ XcmpQueue, ); -impl pallet_evm_coder_substrate::Config for Runtime { - type GasWeightMapping = FixedGasWeightMapping; -} +impl pallet_evm_coder_substrate::Config for Runtime {} impl pallet_xcm::Config for Runtime { type Event = Event; @@ -864,6 +862,7 @@ type EvmTokenAddressMapping = EvmTokenAddressMapping; type CrossTokenAddressMapping = CrossTokenAddressMapping; + type ContractAddress = EvmCollectionHelpersAddress; } impl pallet_structure::Config for Runtime { @@ -900,7 +899,6 @@ type Event = Event; type WeightInfo = pallet_unique::weights::SubstrateWeight; type CommonWeightInfo = CommonWeights; - type ContractAddress = EvmCollectionHelperAddress; } parameter_types! { @@ -963,7 +961,7 @@ ]); // 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f - pub const EvmCollectionHelperAddress: H160 = H160([ + pub const EvmCollectionHelpersAddress: H160 = H160([ 0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f, ]); } --- a/runtime/tests/src/lib.rs +++ b/runtime/tests/src/lib.rs @@ -208,9 +208,7 @@ type BlockHashMapping = SubstrateBlockHashMapping; type TransactionValidityHack = (); } -impl pallet_evm_coder_substrate::Config for Test { - type GasWeightMapping = (); -} +impl pallet_evm_coder_substrate::Config for Test {} impl pallet_common::Config for Test { type WeightInfo = (); @@ -222,6 +220,7 @@ type CollectionDispatch = CollectionDispatchT; type EvmTokenAddressMapping = EvmTokenAddressMapping; type CrossTokenAddressMapping = CrossTokenAddressMapping; + type ContractAddress = EvmCollectionHelpersAddress; } impl pallet_evm::account::Config for Test { @@ -247,7 +246,7 @@ parameter_types! { // 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f - pub const EvmCollectionHelperAddress: H160 = H160([ + pub const EvmCollectionHelpersAddress: H160 = H160([ 0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f, ]); } @@ -256,7 +255,6 @@ type Event = (); type WeightInfo = (); type CommonWeightInfo = CommonWeights; - type ContractAddress = EvmCollectionHelperAddress; } // Build genesis storage according to the mock runtime. --- a/runtime/unique/src/lib.rs +++ b/runtime/unique/src/lib.rs @@ -290,7 +290,7 @@ pallet_evm_migration::OnMethodCall, pallet_evm_contract_helpers::HelpersOnMethodCall, CollectionDispatchT, - pallet_unique::eth::CollectionHelperOnMethodCall, + pallet_unique::eth::CollectionHelpersOnMethodCall, ); type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate; type ChainId = ChainId; @@ -805,9 +805,7 @@ XcmpQueue, ); -impl pallet_evm_coder_substrate::Config for Runtime { - type GasWeightMapping = FixedGasWeightMapping; -} +impl pallet_evm_coder_substrate::Config for Runtime {} impl pallet_xcm::Config for Runtime { type Event = Event; @@ -869,6 +867,7 @@ type EvmTokenAddressMapping = EvmTokenAddressMapping; type CrossTokenAddressMapping = CrossTokenAddressMapping; + type ContractAddress = EvmCollectionHelpersAddress; } impl pallet_structure::Config for Runtime { @@ -905,7 +904,6 @@ type Event = Event; type WeightInfo = pallet_unique::weights::SubstrateWeight; type CommonWeightInfo = CommonWeights; - type ContractAddress = EvmCollectionHelperAddress; } parameter_types! { @@ -968,7 +966,7 @@ ]); // 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f - pub const EvmCollectionHelperAddress: H160 = H160([ + pub const EvmCollectionHelpersAddress: H160 = H160([ 0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f, ]); } --- a/tests/src/eth/api/CollectionHelper.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: OTHER -// This code is automatically generated - -pragma solidity >=0.8.0 <0.9.0; - -// Common stubs holder -interface Dummy { - -} - -interface ERC165 is Dummy { - function supportsInterface(bytes4 interfaceID) external view returns (bool); -} - -// Selector: 56c215c5 -interface CollectionHelper is Dummy, ERC165 { - // Selector: create721Collection(string,string,string) 951c0151 - function create721Collection( - string memory name, - string memory description, - string memory tokenPrefix - ) external view returns (address); - - // Selector: isCollectionExist(address) c3de1494 - function isCollectionExist(address collectionAddress) - external - view - returns (bool); -} --- /dev/null +++ b/tests/src/eth/api/CollectionHelpers.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: OTHER +// This code is automatically generated + +pragma solidity >=0.8.0 <0.9.0; + +// Common stubs holder +interface Dummy { + +} + +interface ERC165 is Dummy { + function supportsInterface(bytes4 interfaceID) external view returns (bool); +} + +// Inline +interface CollectionHelpersEvents { + event CollectionCreated( + address indexed owner, + address indexed collectionId + ); +} + +// Selector: 20947cd0 +interface CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents { + // Selector: createNonfungibleCollection(string,string,string) e34a6844 + function createNonfungibleCollection( + string memory name, + string memory description, + string memory tokenPrefix + ) external view returns (address); + + // Selector: isCollectionExist(address) c3de1494 + function isCollectionExist(address collectionAddress) + external + view + returns (bool); +} --- a/tests/src/eth/api/UniqueFungible.sol +++ b/tests/src/eth/api/UniqueFungible.sol @@ -65,7 +65,7 @@ returns (uint256); } -// Selector: f5652829 +// Selector: c894dc35 interface Collection is Dummy, ERC165 { // Selector: setCollectionProperty(string,bytes) 2f073f66 function setCollectionProperty(string memory key, bytes memory value) @@ -88,8 +88,11 @@ // Selector: ethConfirmSponsorship() a8580d1a function ethConfirmSponsorship() external; - // Selector: setLimit(string,string) bf4d2014 - function setLimit(string memory limit, string memory value) external; + // Selector: setLimit(string,uint32) 68db30ca + function setLimit(string memory limit, uint32 value) external; + + // Selector: setLimit(string,bool) ea67e4c2 + function setLimit(string memory limit, bool value) external; // Selector: contractAddress() f6b4dfb4 function contractAddress() external view returns (address); --- a/tests/src/eth/api/UniqueNFT.sol +++ b/tests/src/eth/api/UniqueNFT.sol @@ -191,29 +191,7 @@ function totalSupply() external view returns (uint256); } -// Selector: d74d154f -interface ERC721UniqueExtensions is Dummy, ERC165 { - // Selector: transfer(address,uint256) a9059cbb - function transfer(address to, uint256 tokenId) external; - - // Selector: burnFrom(address,uint256) 79cc6790 - function burnFrom(address from, uint256 tokenId) external; - - // Selector: nextTokenId() 75794a3c - function nextTokenId() external view returns (uint256); - - // Selector: mintBulk(address,uint256[]) 44a9945e - function mintBulk(address to, uint256[] memory tokenIds) - external - returns (bool); - - // Selector: mintBulkWithTokenURI(address,(uint256,string)[]) 36543006 - function mintBulkWithTokenURI(address to, Tuple0[] memory tokens) - external - returns (bool); -} - -// Selector: f5652829 +// Selector: c894dc35 interface Collection is Dummy, ERC165 { // Selector: setCollectionProperty(string,bytes) 2f073f66 function setCollectionProperty(string memory key, bytes memory value) @@ -236,13 +214,38 @@ // Selector: ethConfirmSponsorship() a8580d1a function ethConfirmSponsorship() external; - // Selector: setLimit(string,string) bf4d2014 - function setLimit(string memory limit, string memory value) external; + // Selector: setLimit(string,uint32) 68db30ca + function setLimit(string memory limit, uint32 value) external; + + // Selector: setLimit(string,bool) ea67e4c2 + function setLimit(string memory limit, bool value) external; // Selector: contractAddress() f6b4dfb4 function contractAddress() external view returns (address); } +// Selector: d74d154f +interface ERC721UniqueExtensions is Dummy, ERC165 { + // Selector: transfer(address,uint256) a9059cbb + function transfer(address to, uint256 tokenId) external; + + // Selector: burnFrom(address,uint256) 79cc6790 + function burnFrom(address from, uint256 tokenId) external; + + // Selector: nextTokenId() 75794a3c + function nextTokenId() external view returns (uint256); + + // Selector: mintBulk(address,uint256[]) 44a9945e + function mintBulk(address to, uint256[] memory tokenIds) + external + returns (bool); + + // Selector: mintBulkWithTokenURI(address,(uint256,string)[]) 36543006 + function mintBulkWithTokenURI(address to, Tuple0[] memory tokens) + external + returns (bool); +} + interface UniqueNFT is Dummy, ERC165, --- a/tests/src/eth/collectionHelperAbi.json +++ /dev/null @@ -1,35 +0,0 @@ -[ - { - "inputs": [ - { "internalType": "string", "name": "name", "type": "string" }, - { "internalType": "string", "name": "description", "type": "string" }, - { "internalType": "string", "name": "tokenPrefix", "type": "string" } - ], - "name": "create721Collection", - "outputs": [{ "internalType": "address", "name": "", "type": "address" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "collectionAddress", - "type": "address" - } - ], - "name": "isCollectionExist", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" } - ], - "name": "supportsInterface", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], - "stateMutability": "view", - "type": "function" - } -] --- /dev/null +++ b/tests/src/eth/collectionHelpersAbi.json @@ -0,0 +1,54 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "collectionId", + "type": "address" + } + ], + "name": "CollectionCreated", + "type": "event" + }, + { + "inputs": [ + { "internalType": "string", "name": "name", "type": "string" }, + { "internalType": "string", "name": "description", "type": "string" }, + { "internalType": "string", "name": "tokenPrefix", "type": "string" } + ], + "name": "createNonfungibleCollection", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "collectionAddress", + "type": "address" + } + ], + "name": "isCollectionExist", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" } + ], + "name": "supportsInterface", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + } +] --- a/tests/src/eth/contractSponsoring.test.ts +++ b/tests/src/eth/contractSponsoring.test.ts @@ -29,7 +29,7 @@ normalizeEvents, subToEth, executeEthTxOnSub, - evmCollectionHelper, + evmCollectionHelpers, getCollectionAddressFromResult, evmCollection, } from './util/helpers'; @@ -224,8 +224,8 @@ //TODO: CORE-302 add eth methods itWeb3.skip('Sponsoring evm address from substrate collection', async ({api, web3}) => { const owner = await createEthAccountWithBalance(api, web3); - const collectionHelper = evmCollectionHelper(web3, owner); - let result = await collectionHelper.methods.create721Collection('Sponsor collection', '1', '1').send(); + const collectionHelpers = evmCollectionHelpers(web3, owner); + let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send(); const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result); const sponsor = await createEthAccountWithBalance(api, web3); const collectionEvm = evmCollection(web3, owner, collectionIdAddress); --- a/tests/src/eth/createCollection.test.ts +++ b/tests/src/eth/createCollection.test.ts @@ -18,7 +18,7 @@ import {expect} from 'chai'; import {getCreatedCollectionCount, getDetailedCollectionInfo} from '../util/helpers'; import { - evmCollectionHelper, + evmCollectionHelpers, collectionIdToAddress, createEthAccount, createEthAccountWithBalance, @@ -30,14 +30,14 @@ describe('Create collection from EVM', () => { itWeb3('Create collection', async ({api, web3}) => { const owner = await createEthAccountWithBalance(api, web3); - const helper = evmCollectionHelper(web3, owner); + const helper = evmCollectionHelpers(web3, owner); const collectionName = 'CollectionEVM'; const description = 'Some description'; const tokenPrefix = 'token prefix'; const collectionCountBefore = await getCreatedCollectionCount(api); const result = await helper.methods - .create721Collection(collectionName, description, tokenPrefix) + .createNonfungibleCollection(collectionName, description, tokenPrefix) .send(); const collectionCountAfter = await getCreatedCollectionCount(api); @@ -51,27 +51,27 @@ itWeb3('Check collection address exist', async ({api, web3}) => { const owner = await createEthAccountWithBalance(api, web3); - const collectionHelper = evmCollectionHelper(web3, owner); + const collectionHelpers = evmCollectionHelpers(web3, owner); const expectedCollectionId = await getCreatedCollectionCount(api) + 1; const expectedCollectionAddress = collectionIdToAddress(expectedCollectionId); - expect(await collectionHelper.methods + expect(await collectionHelpers.methods .isCollectionExist(expectedCollectionAddress) .call()).to.be.false; - await collectionHelper.methods - .create721Collection('A', 'A', 'A') + await collectionHelpers.methods + .createNonfungibleCollection('A', 'A', 'A') .send(); - expect(await collectionHelper.methods + expect(await collectionHelpers.methods .isCollectionExist(expectedCollectionAddress) .call()).to.be.true; }); itWeb3('Set sponsorship', async ({api, web3}) => { const owner = await createEthAccountWithBalance(api, web3); - const collectionHelper = evmCollectionHelper(web3, owner); - let result = await collectionHelper.methods.create721Collection('Sponsor collection', '1', '1').send(); + const collectionHelpers = evmCollectionHelpers(web3, owner); + let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send(); const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result); const sponsor = await createEthAccountWithBalance(api, web3); const collectionEvm = evmCollection(web3, owner, collectionIdAddress); @@ -89,8 +89,8 @@ itWeb3('Set limits', async ({api, web3}) => { const owner = await createEthAccountWithBalance(api, web3); - const collectionHelper = evmCollectionHelper(web3, owner); - const result = await collectionHelper.methods.create721Collection('Const collection', '5', '5').send(); + const collectionHelpers = evmCollectionHelpers(web3, owner); + const result = await collectionHelpers.methods.createNonfungibleCollection('Const collection', '5', '5').send(); const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result); const limits = { accountTokenOwnershipLimit: 1000, @@ -105,15 +105,15 @@ }; const collectionEvm = evmCollection(web3, owner, collectionIdAddress); - await collectionEvm.methods.setLimit('accountTokenOwnershipLimit', limits.accountTokenOwnershipLimit.toString()).send(); - await collectionEvm.methods.setLimit('sponsoredDataSize', limits.sponsoredDataSize.toString()).send(); - await collectionEvm.methods.setLimit('sponsoredDataRateLimit', limits.sponsoredDataRateLimit.toString()).send(); - await collectionEvm.methods.setLimit('tokenLimit', limits.tokenLimit.toString()).send(); - await collectionEvm.methods.setLimit('sponsorTransferTimeout', limits.sponsorTransferTimeout.toString()).send(); - await collectionEvm.methods.setLimit('sponsorApproveTimeout', limits.sponsorApproveTimeout.toString()).send(); - await collectionEvm.methods.setLimit('ownerCanTransfer', limits.ownerCanTransfer.toString()).send(); - await collectionEvm.methods.setLimit('ownerCanDestroy', limits.ownerCanDestroy.toString()).send(); - await collectionEvm.methods.setLimit('transfersEnabled', limits.transfersEnabled.toString()).send(); + await collectionEvm.methods['setLimit(string,uint32)']('accountTokenOwnershipLimit', limits.accountTokenOwnershipLimit).send(); + await collectionEvm.methods['setLimit(string,uint32)']('sponsoredDataSize', limits.sponsoredDataSize).send(); + await collectionEvm.methods['setLimit(string,uint32)']('sponsoredDataRateLimit', limits.sponsoredDataRateLimit).send(); + await collectionEvm.methods['setLimit(string,uint32)']('tokenLimit', limits.tokenLimit).send(); + await collectionEvm.methods['setLimit(string,uint32)']('sponsorTransferTimeout', limits.sponsorTransferTimeout).send(); + await collectionEvm.methods['setLimit(string,uint32)']('sponsorApproveTimeout', limits.sponsorApproveTimeout).send(); + await collectionEvm.methods['setLimit(string,bool)']('ownerCanTransfer', limits.ownerCanTransfer).send(); + await collectionEvm.methods['setLimit(string,bool)']('ownerCanDestroy', limits.ownerCanDestroy).send(); + await collectionEvm.methods['setLimit(string,bool)']('transfersEnabled', limits.transfersEnabled).send(); const collectionSub = (await getDetailedCollectionInfo(api, collectionId))!; expect(collectionSub.limits.accountTokenOwnershipLimit.unwrap().toNumber()).to.be.eq(limits.accountTokenOwnershipLimit); @@ -130,14 +130,14 @@ itWeb3('Collection address exist', async ({api, web3}) => { const owner = await createEthAccountWithBalance(api, web3); const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233'; - const collectionHelper = evmCollectionHelper(web3, owner); - expect(await collectionHelper.methods + const collectionHelpers = evmCollectionHelpers(web3, owner); + expect(await collectionHelpers.methods .isCollectionExist(collectionAddressForNonexistentCollection).call()) .to.be.false; - const result = await collectionHelper.methods.create721Collection('Collection address exist', '7', '7').send(); + const result = await collectionHelpers.methods.createNonfungibleCollection('Collection address exist', '7', '7').send(); const {collectionIdAddress} = await getCollectionAddressFromResult(api, result); - expect(await collectionHelper.methods + expect(await collectionHelpers.methods .isCollectionExist(collectionIdAddress).call()) .to.be.true; }); @@ -146,7 +146,7 @@ describe('(!negative tests!) Create collection from EVM', () => { itWeb3('(!negative test!) Create collection (bad lengths)', async ({api, web3}) => { const owner = await createEthAccountWithBalance(api, web3); - const helper = evmCollectionHelper(web3, owner); + const helper = evmCollectionHelpers(web3, owner); { const MAX_NAME_LENGHT = 64; const collectionName = 'A'.repeat(MAX_NAME_LENGHT + 1); @@ -154,7 +154,7 @@ const tokenPrefix = 'A'; await expect(helper.methods - .create721Collection(collectionName, description, tokenPrefix) + .createNonfungibleCollection(collectionName, description, tokenPrefix) .call()).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGHT); } @@ -164,7 +164,7 @@ const description = 'A'.repeat(MAX_DESCRIPTION_LENGHT + 1); const tokenPrefix = 'A'; await expect(helper.methods - .create721Collection(collectionName, description, tokenPrefix) + .createNonfungibleCollection(collectionName, description, tokenPrefix) .call()).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGHT); } { @@ -173,28 +173,28 @@ const description = 'A'; const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGHT + 1); await expect(helper.methods - .create721Collection(collectionName, description, tokenPrefix) + .createNonfungibleCollection(collectionName, description, tokenPrefix) .call()).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGHT); } }); itWeb3('(!negative test!) Create collection (no funds)', async ({web3}) => { const owner = await createEthAccount(web3); - const helper = evmCollectionHelper(web3, owner); + const helper = evmCollectionHelpers(web3, owner); const collectionName = 'A'; const description = 'A'; const tokenPrefix = 'A'; await expect(helper.methods - .create721Collection(collectionName, description, tokenPrefix) + .createNonfungibleCollection(collectionName, description, tokenPrefix) .call()).to.be.rejectedWith('NotSufficientFounds'); }); itWeb3('(!negative test!) Check owner', async ({api, web3}) => { const owner = await createEthAccountWithBalance(api, web3); const notOwner = await createEthAccount(web3); - const collectionHelper = evmCollectionHelper(web3, owner); - const result = await collectionHelper.methods.create721Collection('A', 'A', 'A').send(); + const collectionHelpers = evmCollectionHelpers(web3, owner); + const result = await collectionHelpers.methods.createNonfungibleCollection('A', 'A', 'A').send(); const {collectionIdAddress} = await getCollectionAddressFromResult(api, result); const contractEvmFromNotOwner = evmCollection(web3, notOwner, collectionIdAddress); const EXPECTED_ERROR = 'NoPermission'; @@ -218,18 +218,12 @@ itWeb3('(!negative test!) Set limits', async ({api, web3}) => { const owner = await createEthAccountWithBalance(api, web3); - const collectionHelper = evmCollectionHelper(web3, owner); - const result = await collectionHelper.methods.create721Collection('Schema collection', 'A', 'A').send(); + const collectionHelpers = evmCollectionHelpers(web3, owner); + const result = await collectionHelpers.methods.createNonfungibleCollection('Schema collection', 'A', 'A').send(); const {collectionIdAddress} = await getCollectionAddressFromResult(api, result); const collectionEvm = evmCollection(web3, owner, collectionIdAddress); await expect(collectionEvm.methods .setLimit('badLimit', 'true') - .call()).to.be.rejectedWith('Unknown limit "badLimit"'); - await expect(collectionEvm.methods - .setLimit('sponsoredDataSize', 'badValue') - .call()).to.be.rejectedWith('Int value "badValue" parse error:'); - await expect(collectionEvm.methods - .setLimit('ownerCanTransfer', 'badValue') - .call()).to.be.rejectedWith('Bool value "badValue" parse error:'); + .call()).to.be.rejectedWith('Unknown boolean limit "badLimit"'); }); }); \ No newline at end of file --- a/tests/src/eth/fungibleAbi.json +++ b/tests/src/eth/fungibleAbi.json @@ -152,7 +152,17 @@ { "inputs": [ { "internalType": "string", "name": "limit", "type": "string" }, - { "internalType": "string", "name": "value", "type": "string" } + { "internalType": "uint32", "name": "value", "type": "uint32" } + ], + "name": "setLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "string", "name": "limit", "type": "string" }, + { "internalType": "bool", "name": "value", "type": "bool" } ], "name": "setLimit", "outputs": [], --- a/tests/src/eth/nonFungible.test.ts +++ b/tests/src/eth/nonFungible.test.ts @@ -16,7 +16,7 @@ import privateKey from '../substrate/privateKey'; import {approveExpectSuccess, burnItemExpectSuccess, createCollectionExpectSuccess, createItemExpectSuccess, transferExpectSuccess, transferFromExpectSuccess, UNIQUE} from '../util/helpers'; -import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, evmCollectionHelper, GAS_ARGS, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, transferBalanceToEth} from './util/helpers'; +import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, evmCollectionHelpers, GAS_ARGS, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, transferBalanceToEth} from './util/helpers'; import nonFungibleAbi from './nonFungibleAbi.json'; import {expect} from 'chai'; import {submitTransactionAsync} from '../substrate/substrate-api'; @@ -76,8 +76,8 @@ describe('NFT: Plain calls', () => { itWeb3('Can perform mint()', async ({web3, api}) => { const owner = await createEthAccountWithBalance(api, web3); - const helper = evmCollectionHelper(web3, owner); - let result = await helper.methods.create721Collection('Mint collection', '6', '6').send(); + const helper = evmCollectionHelpers(web3, owner); + let result = await helper.methods.createNonfungibleCollection('Mint collection', '6', '6').send(); const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result); const receiver = createEthAccount(web3); const contract = evmCollection(web3, owner, collectionIdAddress); --- a/tests/src/eth/nonFungibleAbi.json +++ b/tests/src/eth/nonFungibleAbi.json @@ -326,7 +326,17 @@ { "inputs": [ { "internalType": "string", "name": "limit", "type": "string" }, - { "internalType": "string", "name": "value", "type": "string" } + { "internalType": "uint32", "name": "value", "type": "uint32" } + ], + "name": "setLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "string", "name": "limit", "type": "string" }, + { "internalType": "bool", "name": "value", "type": "bool" } ], "name": "setLimit", "outputs": [], --- a/tests/src/eth/util/helpers.ts +++ b/tests/src/eth/util/helpers.ts @@ -29,7 +29,7 @@ import privateKey from '../../substrate/privateKey'; import contractHelpersAbi from './contractHelpersAbi.json'; import nonFungibleAbi from '../nonFungibleAbi.json'; -import collectionHelperAbi from '../collectionHelperAbi.json'; +import collectionHelpersAbi from '../collectionHelpersAbi.json'; import getBalance from '../../substrate/get-balance'; import waitNewBlocks from '../../substrate/wait-new-blocks'; @@ -69,7 +69,7 @@ } export async function getCollectionAddressFromResult(api: ApiPromise, result: any) { - const collectionIdAddress = normalizeAddress(result.events[0].raw.topics[2]); + const collectionIdAddress = normalizeAddress(result.events.CollectionCreated.returnValues.collectionId); const collectionId = collectionIdFromAddress(collectionIdAddress); const collection = (await getDetailedCollectionInfo(api, collectionId))!; return {collectionIdAddress, collectionId, collection}; @@ -297,8 +297,8 @@ * @param caller - eth address * @returns */ -export function evmCollectionHelper(web3: Web3, caller: string) { - return new web3.eth.Contract(collectionHelperAbi as any, '0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f', {from: caller, ...GAS_ARGS}); +export function evmCollectionHelpers(web3: Web3, caller: string) { + return new web3.eth.Contract(collectionHelpersAbi as any, '0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f', {from: caller, ...GAS_ARGS}); } /**