git.delta.rocks / unique-network / refs/commits / d2735a42ddb8

difftreelog

feat evm collection creation event

Yaroslav Bolyukin2022-05-30parent: #7523de2.patch.diff
in: master

39 files changed

modifiedCargo.lockdiffbeforeafterboth
5912name = "pallet-common"5912name = "pallet-common"
5913version = "0.1.0"5913version = "0.1.0"
5914dependencies = [5914dependencies = [
5915 "ethereum",
5915 "evm-coder",5916 "evm-coder",
5916 "fp-evm-mapping",5917 "fp-evm-mapping",
5917 "frame-benchmarking",5918 "frame-benchmarking",
modifiedMakefilediffbeforeafterboth
16CONTRACT_HELPERS_ABI=./tests/src/eth/util/contractHelpersAbi.json16CONTRACT_HELPERS_ABI=./tests/src/eth/util/contractHelpersAbi.json
1717
18COLLECTION_HELPER_STUBS=./pallets/unique/src/eth/stubs/18COLLECTION_HELPER_STUBS=./pallets/unique/src/eth/stubs/
19COLLECTION_HELPER_ABI=./tests/src/eth/collectionHelperAbi.json19COLLECTION_HELPER_ABI=./tests/src/eth/collectionHelpersAbi.json
2020
21TESTS_API=./tests/src/eth/api/21TESTS_API=./tests/src/eth/api/
2222
23.PHONY: regenerate_solidity23.PHONY: regenerate_solidity
24regenerate_solidity: UniqueFungible.sol UniqueNFT.sol ContractHelpers.sol CollectionHelper.sol24regenerate_solidity: UniqueFungible.sol UniqueNFT.sol ContractHelpers.sol CollectionHelpers.sol
2525
26UniqueFungible.sol:26UniqueFungible.sol:
27 PACKAGE=pallet-fungible NAME=erc::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh27 PACKAGE=pallet-fungible NAME=erc::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh
35 PACKAGE=pallet-evm-contract-helpers NAME=eth::contract_helpers_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh35 PACKAGE=pallet-evm-contract-helpers NAME=eth::contract_helpers_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh
36 PACKAGE=pallet-evm-contract-helpers NAME=eth::contract_helpers_impl OUTPUT=$(CONTRACT_HELPERS_STUBS)/$@ ./.maintain/scripts/generate_sol.sh36 PACKAGE=pallet-evm-contract-helpers NAME=eth::contract_helpers_impl OUTPUT=$(CONTRACT_HELPERS_STUBS)/$@ ./.maintain/scripts/generate_sol.sh
3737
38CollectionHelper.sol:38CollectionHelpers.sol:
39 PACKAGE=pallet-unique NAME=eth::collection_helper_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh39 PACKAGE=pallet-unique NAME=eth::collection_helper_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh
40 PACKAGE=pallet-unique NAME=eth::collection_helper_impl OUTPUT=$(COLLECTION_HELPER_STUBS)/$@ ./.maintain/scripts/generate_sol.sh40 PACKAGE=pallet-unique NAME=eth::collection_helper_impl OUTPUT=$(COLLECTION_HELPER_STUBS)/$@ ./.maintain/scripts/generate_sol.sh
4141
51 INPUT=$(CONTRACT_HELPERS_STUBS)/$< OUTPUT=$(CONTRACT_HELPERS_STUBS)/ContractHelpers.raw ./.maintain/scripts/compile_stub.sh51 INPUT=$(CONTRACT_HELPERS_STUBS)/$< OUTPUT=$(CONTRACT_HELPERS_STUBS)/ContractHelpers.raw ./.maintain/scripts/compile_stub.sh
52 INPUT=$(CONTRACT_HELPERS_STUBS)/$< OUTPUT=$(CONTRACT_HELPERS_ABI) ./.maintain/scripts/generate_abi.sh52 INPUT=$(CONTRACT_HELPERS_STUBS)/$< OUTPUT=$(CONTRACT_HELPERS_ABI) ./.maintain/scripts/generate_abi.sh
5353
54CollectionHelper: CollectionHelper.sol54CollectionHelpers: CollectionHelpers.sol
55 INPUT=$(COLLECTION_HELPER_STUBS)/$< OUTPUT=$(COLLECTION_HELPER_STUBS)/CollectionHelper.raw ./.maintain/scripts/compile_stub.sh55 INPUT=$(COLLECTION_HELPER_STUBS)/$< OUTPUT=$(COLLECTION_HELPER_STUBS)/CollectionHelpers.raw ./.maintain/scripts/compile_stub.sh
56 INPUT=$(COLLECTION_HELPER_STUBS)/$< OUTPUT=$(COLLECTION_HELPER_ABI) ./.maintain/scripts/generate_abi.sh56 INPUT=$(COLLECTION_HELPER_STUBS)/$< OUTPUT=$(COLLECTION_HELPER_ABI) ./.maintain/scripts/generate_abi.sh
5757
58evm_stubs: UniqueFungible UniqueNFT ContractHelpers CollectionHelper58evm_stubs: UniqueFungible UniqueNFT ContractHelpers CollectionHelpers
5959
60.PHONY: _bench60.PHONY: _bench
61_bench:61_bench:
modifiedpallets/common/Cargo.tomldiffbeforeafterboth
21up-data-structs = { default-features = false, path = '../../primitives/data-structs' }21up-data-structs = { default-features = false, path = '../../primitives/data-structs' }
22pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }22pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }
23evm-coder = { default-features = false, path = '../../crates/evm-coder' }23evm-coder = { default-features = false, path = '../../crates/evm-coder' }
24ethereum = { version = "0.12.0", default-features = false }
24pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.21-logs" }25pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.21-logs" }
2526
26serde = { version = "1.0.130", default-features = false }27serde = { version = "1.0.130", default-features = false }
modifiedpallets/common/src/dispatch.rsdiffbeforeafterboth
56}56}
5757
58pub trait CollectionDispatch<T: Config> {58pub trait CollectionDispatch<T: Config> {
59 fn create(sender: T::AccountId, data: CreateCollectionData<T::AccountId>) -> DispatchResult;59 fn create(
60 sender: T::CrossAccountId,
61 data: CreateCollectionData<T::AccountId>,
62 ) -> DispatchResult;
60 fn destroy(sender: T::CrossAccountId, handle: CollectionHandle<T>) -> DispatchResult;63 fn destroy(sender: T::CrossAccountId, handle: CollectionHandle<T>) -> DispatchResult;
6164
modifiedpallets/common/src/erc.rsdiffbeforeafterboth
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
1616
17use evm_coder::{17use evm_coder::{
18 solidity_interface, solidity,18 solidity_interface, solidity, ToLog,
19 types::*,19 types::*,
20 execution::{Result, Error},20 execution::{Result, Error},
21};21};
2828
29use crate::{Pallet, CollectionHandle, Config, CollectionProperties};29use crate::{Pallet, CollectionHandle, Config, CollectionProperties};
30
31#[derive(ToLog)]
32pub enum CollectionHelpersEvents {
33 CollectionCreated {
34 #[indexed]
35 owner: address,
36 #[indexed]
37 collection_id: address,
38 },
39}
3040
31/// Does not always represent a full collection, for RFT it is either41/// Does not always represent a full collection, for RFT it is either
32/// collection (Implementing ERC721), or specific collection token (Implementing ERC20)42/// collection (Implementing ERC721), or specific collection token (Implementing ERC20)
modifiedpallets/common/src/lib.rsdiffbeforeafterboth
21use core::ops::{Deref, DerefMut};21use core::ops::{Deref, DerefMut};
22use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};22use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};
23use sp_std::vec::Vec;23use sp_std::vec::Vec;
24use pallet_evm::account::CrossAccountId;24use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};
25use evm_coder::ToLog;
25use frame_support::{26use frame_support::{
26 dispatch::{DispatchErrorWithPostInfo, DispatchResultWithPostInfo, Weight, PostDispatchInfo},27 dispatch::{DispatchErrorWithPostInfo, DispatchResultWithPostInfo, Weight, PostDispatchInfo},
27 ensure,28 ensure,
28 traits::{Imbalance, Get, Currency, WithdrawReasons, ExistenceRequirement},29 traits::{Imbalance, Get, Currency, WithdrawReasons, ExistenceRequirement},
29 BoundedVec,
30 weights::Pays,30 weights::Pays,
31 transactional,31 transactional,
32};32};
54 CreateItemExData,54 CreateItemExData,
55 SponsoringRateLimit,55 SponsoringRateLimit,
56 budget::Budget,56 budget::Budget,
57 COLLECTION_FIELD_LIMIT,
58 PhantomType,57 PhantomType,
59 Property,58 Property,
60 Properties,59 Properties,
220 pub trait Config:219 pub trait Config:
221 frame_system::Config + pallet_evm_coder_substrate::Config + TypeInfo + account::Config220 frame_system::Config
221 + pallet_evm_coder_substrate::Config
222 + pallet_evm::Config
223 + TypeInfo
224 + account::Config
222 {225 {
232 type CollectionDispatch: CollectionDispatch<Self>;235 type CollectionDispatch: CollectionDispatch<Self>;
233236
234 type TreasuryAccountId: Get<Self::AccountId>;237 type TreasuryAccountId: Get<Self::AccountId>;
238 type ContractAddress: Get<H160>;
235239
236 type EvmTokenAddressMapping: TokenAddressMapping<H160>;240 type EvmTokenAddressMapping: TokenAddressMapping<H160>;
237 type CrossTokenAddressMapping: TokenAddressMapping<Self::CrossAccountId>;241 type CrossTokenAddressMapping: TokenAddressMapping<Self::CrossAccountId>;
722726
723impl<T: Config> Pallet<T> {727impl<T: Config> Pallet<T> {
724 pub fn init_collection(728 pub fn init_collection(
725 owner: T::AccountId,729 owner: T::CrossAccountId,
726 data: CreateCollectionData<T::AccountId>,730 data: CreateCollectionData<T::AccountId>,
727 ) -> Result<CollectionId, DispatchError> {731 ) -> Result<CollectionId, DispatchError> {
728 {732 {
748 // =========752 // =========
749753
750 let collection = Collection {754 let collection = Collection {
751 owner: owner.clone(),755 owner: owner.as_sub().clone(),
752 name: data.name,756 name: data.name,
753 mode: data.mode.clone(),757 mode: data.mode.clone(),
754 description: data.description,758 description: data.description,
794 ),798 ),
795 );799 );
796 <T as Config>::Currency::settle(800 <T as Config>::Currency::settle(
797 &owner,801 &owner.as_sub(),
798 imbalance,802 imbalance,
799 WithdrawReasons::TRANSFER,803 WithdrawReasons::TRANSFER,
800 ExistenceRequirement::KeepAlive,804 ExistenceRequirement::KeepAlive,
806 <Pallet<T>>::deposit_event(Event::CollectionCreated(id, data.mode.id(), owner.clone()));810 <Pallet<T>>::deposit_event(Event::CollectionCreated(
811 id,
812 data.mode.id(),
813 owner.as_sub().clone(),
814 ));
815 <PalletEvm<T>>::deposit_log(
816 erc::CollectionHelpersEvents::CollectionCreated {
817 owner: *owner.as_eth(),
818 collection_id: eth::collection_id_to_address(id),
819 }
820 .to_log(T::ContractAddress::get()),
821 );
807 <CollectionById<T>>::insert(id, collection);822 <CollectionById<T>>::insert(id, collection);
808 Ok(id)823 Ok(id)
809 }824 }
modifiedpallets/evm-coder-substrate/src/lib.rsdiffbeforeafterboth
66 }66 }
6767
68 #[pallet::config]68 #[pallet::config]
69 pub trait Config: frame_system::Config {69 pub trait Config: frame_system::Config + pallet_evm::Config {}
70 type GasWeightMapping: pallet_evm::GasWeightMapping;
71 }
7270
73 #[pallet::pallet]71 #[pallet::pallet]
74 pub struct Pallet<T>(_);72 pub struct Pallet<T>(_);
modifiedpallets/fungible/src/lib.rsdiffbeforeafterboth
134134
135impl<T: Config> Pallet<T> {135impl<T: Config> Pallet<T> {
136 pub fn init_collection(136 pub fn init_collection(
137 owner: T::AccountId,137 owner: T::CrossAccountId,
138 data: CreateCollectionData<T::AccountId>,138 data: CreateCollectionData<T::AccountId>,
139 ) -> Result<CollectionId, DispatchError> {139 ) -> Result<CollectionId, DispatchError> {
140 <PalletCommon<T>>::init_collection(owner, data)140 <PalletCommon<T>>::init_collection(owner, data)
modifiedpallets/fungible/src/stubs/UniqueFungible.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth
127 }127 }
128}128}
129129
130// Selector: f5652829130// Selector: c894dc35
131contract Collection is Dummy, ERC165 {131contract Collection is Dummy, ERC165 {
132 // Selector: setCollectionProperty(string,bytes) 2f073f66132 // Selector: setCollectionProperty(string,bytes) 2f073f66
133 function setCollectionProperty(string memory key, bytes memory value)133 function setCollectionProperty(string memory key, bytes memory value)
173 dummy = 0;173 dummy = 0;
174 }174 }
175175
176 // Selector: setLimit(string,string) bf4d2014176 // Selector: setLimit(string,uint32) 68db30ca
177 function setLimit(string memory limit, string memory value) public {177 function setLimit(string memory limit, uint32 value) public {
178 require(false, stub_error);178 require(false, stub_error);
179 limit;179 limit;
180 value;180 value;
181 dummy = 0;181 dummy = 0;
182 }182 }
183
184 // Selector: setLimit(string,bool) ea67e4c2
185 function setLimit(string memory limit, bool value) public {
186 require(false, stub_error);
187 limit;
188 value;
189 dummy = 0;
190 }
183191
184 // Selector: contractAddress() f6b4dfb4192 // Selector: contractAddress() f6b4dfb4
185 function contractAddress() public view returns (address) {193 function contractAddress() public view returns (address) {
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
295// unchecked calls skips any permission checks295// unchecked calls skips any permission checks
296impl<T: Config> Pallet<T> {296impl<T: Config> Pallet<T> {
297 pub fn init_collection(297 pub fn init_collection(
298 owner: T::AccountId,298 owner: T::CrossAccountId,
299 data: CreateCollectionData<T::AccountId>,299 data: CreateCollectionData<T::AccountId>,
300 ) -> Result<CollectionId, DispatchError> {300 ) -> Result<CollectionId, DispatchError> {
301 <PalletCommon<T>>::init_collection(owner, data)301 <PalletCommon<T>>::init_collection(owner, data)
modifiedpallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth
330 }330 }
331}331}
332
333// Selector: c894dc35
334contract Collection is Dummy, ERC165 {
335 // Selector: setCollectionProperty(string,bytes) 2f073f66
336 function setCollectionProperty(string memory key, bytes memory value)
337 public
338 {
339 require(false, stub_error);
340 key;
341 value;
342 dummy = 0;
343 }
344
345 // Selector: deleteCollectionProperty(string) 7b7debce
346 function deleteCollectionProperty(string memory key) public {
347 require(false, stub_error);
348 key;
349 dummy = 0;
350 }
351
352 // Throws error if key not found
353 //
354 // Selector: collectionProperty(string) cf24fd6d
355 function collectionProperty(string memory key)
356 public
357 view
358 returns (bytes memory)
359 {
360 require(false, stub_error);
361 key;
362 dummy;
363 return hex"";
364 }
365
366 // Selector: ethSetSponsor(address) 8f9af356
367 function ethSetSponsor(address sponsor) public {
368 require(false, stub_error);
369 sponsor;
370 dummy = 0;
371 }
372
373 // Selector: ethConfirmSponsorship() a8580d1a
374 function ethConfirmSponsorship() public {
375 require(false, stub_error);
376 dummy = 0;
377 }
378
379 // Selector: setLimit(string,uint32) 68db30ca
380 function setLimit(string memory limit, uint32 value) public {
381 require(false, stub_error);
382 limit;
383 value;
384 dummy = 0;
385 }
386
387 // Selector: setLimit(string,bool) ea67e4c2
388 function setLimit(string memory limit, bool value) public {
389 require(false, stub_error);
390 limit;
391 value;
392 dummy = 0;
393 }
394
395 // Selector: contractAddress() f6b4dfb4
396 function contractAddress() public view returns (address) {
397 require(false, stub_error);
398 dummy;
399 return 0x0000000000000000000000000000000000000000;
400 }
401}
332402
333// Selector: d74d154f403// Selector: d74d154f
334contract ERC721UniqueExtensions is Dummy, ERC165 {404contract ERC721UniqueExtensions is Dummy, ERC165 {
380 }450 }
381}451}
382
383// Selector: f5652829
384contract Collection is Dummy, ERC165 {
385 // Selector: setCollectionProperty(string,bytes) 2f073f66
386 function setCollectionProperty(string memory key, bytes memory value)
387 public
388 {
389 require(false, stub_error);
390 key;
391 value;
392 dummy = 0;
393 }
394
395 // Selector: deleteCollectionProperty(string) 7b7debce
396 function deleteCollectionProperty(string memory key) public {
397 require(false, stub_error);
398 key;
399 dummy = 0;
400 }
401
402 // Throws error if key not found
403 //
404 // Selector: collectionProperty(string) cf24fd6d
405 function collectionProperty(string memory key)
406 public
407 view
408 returns (bytes memory)
409 {
410 require(false, stub_error);
411 key;
412 dummy;
413 return hex"";
414 }
415
416 // Selector: ethSetSponsor(address) 8f9af356
417 function ethSetSponsor(address sponsor) public {
418 require(false, stub_error);
419 sponsor;
420 dummy = 0;
421 }
422
423 // Selector: ethConfirmSponsorship() a8580d1a
424 function ethConfirmSponsorship() public {
425 require(false, stub_error);
426 dummy = 0;
427 }
428
429 // Selector: setLimit(string,string) bf4d2014
430 function setLimit(string memory limit, string memory value) public {
431 require(false, stub_error);
432 limit;
433 value;
434 dummy = 0;
435 }
436
437 // Selector: contractAddress() f6b4dfb4
438 function contractAddress() public view returns (address) {
439 require(false, stub_error);
440 dummy;
441 return 0x0000000000000000000000000000000000000000;
442 }
443}
444452
445contract UniqueNFT is453contract UniqueNFT is
446 Dummy,454 Dummy,
modifiedpallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth
140 };140 };
141141
142 let collection_id_res = <PalletNft<T>>::init_collection(sender.clone(), data);142 let collection_id_res =
143 <PalletNft<T>>::init_collection(T::CrossAccountId::from_sub(sender.clone()), data);
143144
144 if let Err(DispatchError::Arithmetic(_)) = &collection_id_res {145 if let Err(DispatchError::Arithmetic(_)) = &collection_id_res {
145 return Err(<Error<T>>::NoAvailableCollectionId.into());146 return Err(<Error<T>>::NoAvailableCollectionId.into());
modifiedpallets/proxy-rmrk-equip/src/lib.rsdiffbeforeafterboth
94 ..Default::default()94 ..Default::default()
95 };95 };
9696
97 let collection_id_res = <PalletNft<T>>::init_collection(sender.clone(), data);97 let collection_id_res = <PalletNft<T>>::init_collection(cross_sender.clone(), data);
9898
99 if let Err(DispatchError::Arithmetic(_)) = &collection_id_res {99 if let Err(DispatchError::Arithmetic(_)) = &collection_id_res {
100 return Err(<Error<T>>::NoAvailableBaseId.into());100 return Err(<Error<T>>::NoAvailableBaseId.into());
modifiedpallets/refungible/src/lib.rsdiffbeforeafterboth
197// unchecked calls skips any permission checks197// unchecked calls skips any permission checks
198impl<T: Config> Pallet<T> {198impl<T: Config> Pallet<T> {
199 pub fn init_collection(199 pub fn init_collection(
200 owner: T::AccountId,200 owner: T::CrossAccountId,
201 data: CreateCollectionData<T::AccountId>,201 data: CreateCollectionData<T::AccountId>,
202 ) -> Result<CollectionId, DispatchError> {202 ) -> Result<CollectionId, DispatchError> {
203 <PalletCommon<T>>::init_collection(owner, data)203 <PalletCommon<T>>::init_collection(owner, data)
modifiedpallets/unique/src/eth/mod.rsdiffbeforeafterboth
26use frame_support::traits::Get;26use frame_support::traits::Get;
27use pallet_common::{CollectionById, erc::token_uri_key};27use pallet_common::{
28 CollectionById,
29 erc::{token_uri_key, CollectionHelpersEvents},
30};
28use crate::{SelfWeightOf, Config, weights::WeightInfo};31use crate::{SelfWeightOf, Config, weights::WeightInfo};
2932
30use sp_std::vec::Vec;33use sp_std::vec::Vec;
31use alloc::format;34use alloc::format;
3235
33struct EvmCollectionHelper<T: Config>(SubstrateRecorder<T>);36struct EvmCollectionHelpers<T: Config>(SubstrateRecorder<T>);
34impl<T: Config> WithRecorder<T> for EvmCollectionHelper<T> {37impl<T: Config> WithRecorder<T> for EvmCollectionHelpers<T> {
35 fn recorder(&self) -> &SubstrateRecorder<T> {38 fn recorder(&self) -> &SubstrateRecorder<T> {
36 &self.039 &self.0
37 }40 }
41 }44 }
42}45}
4346
44#[solidity_interface(name = "CollectionHelper")]47#[solidity_interface(name = "CollectionHelpers", events(CollectionHelpersEvents))]
45impl<T: Config + pallet_nonfungible::Config> EvmCollectionHelper<T> {48impl<T: Config + pallet_nonfungible::Config> EvmCollectionHelpers<T> {
46 #[weight(<SelfWeightOf<T>>::create_collection())]49 #[weight(<SelfWeightOf<T>>::create_collection())]
47 fn create_nonfungible_collection(50 fn create_nonfungible_collection(
48 &self,51 &self,
90 };93 };
9194
92 let collection_id =95 let collection_id = <pallet_nonfungible::Pallet<T>>::init_collection(caller.clone(), data)
93 <pallet_nonfungible::Pallet<T>>::init_collection(caller.as_sub().clone(), data)
94 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;96 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;
9597
96 let address = pallet_common::eth::collection_id_to_address(collection_id);98 let address = pallet_common::eth::collection_id_to_address(collection_id);
107 }109 }
108}110}
109111
110pub struct CollectionHelperOnMethodCall<T: Config>(PhantomData<*const T>);112pub struct CollectionHelpersOnMethodCall<T: Config>(PhantomData<*const T>);
111impl<T: Config + pallet_nonfungible::Config> OnMethodCall<T> for CollectionHelperOnMethodCall<T> {113impl<T: Config + pallet_nonfungible::Config> OnMethodCall<T> for CollectionHelpersOnMethodCall<T> {
112 fn is_reserved(contract: &sp_core::H160) -> bool {114 fn is_reserved(contract: &sp_core::H160) -> bool {
113 contract == &T::ContractAddress::get()115 contract == &T::ContractAddress::get()
114 }116 }
128 return None;130 return None;
129 }131 }
130132
131 let helpers = EvmCollectionHelper::<T>(SubstrateRecorder::<T>::new(gas_left));133 let helpers = EvmCollectionHelpers::<T>(SubstrateRecorder::<T>::new(gas_left));
132 pallet_evm_coder_substrate::call(*source, helpers, value, input)134 pallet_evm_coder_substrate::call(*source, helpers, value, input)
133 }135 }
134136
135 fn get_code(contract: &sp_core::H160) -> Option<Vec<u8>> {137 fn get_code(contract: &sp_core::H160) -> Option<Vec<u8>> {
136 (contract == &T::ContractAddress::get())138 (contract == &T::ContractAddress::get())
137 .then(|| include_bytes!("./stubs/CollectionHelper.raw").to_vec())139 .then(|| include_bytes!("./stubs/CollectionHelpers.raw").to_vec())
138 }140 }
139}141}
140142
141generate_stubgen!(collection_helper_impl, CollectionHelperCall<()>, true);143generate_stubgen!(collection_helper_impl, CollectionHelpersCall<()>, true);
142generate_stubgen!(collection_helper_iface, CollectionHelperCall<()>, false);144generate_stubgen!(collection_helper_iface, CollectionHelpersCall<()>, false);
143145
144fn error_feild_too_long(feild: &str, bound: u32) -> Error {146fn error_feild_too_long(feild: &str, bound: u32) -> Error {
145 Error::Revert(format!("{} is too long. Max length is {}.", feild, bound))147 Error::Revert(format!("{} is too long. Max length is {}.", feild, bound))
deletedpallets/unique/src/eth/stubs/CollectionHelper.rawdiffbeforeafterboth

binary blob — no preview

deletedpallets/unique/src/eth/stubs/CollectionHelper.soldiffbeforeafterboth

no changes

addedpallets/unique/src/eth/stubs/CollectionHelpers.rawdiffbeforeafterboth

binary blob — no preview

addedpallets/unique/src/eth/stubs/CollectionHelpers.soldiffbeforeafterboth

no changes

modifiedpallets/unique/src/lib.rsdiffbeforeafterboth
30 ensure,30 ensure,
31 weights::{Weight},31 weights::{Weight},
32 transactional,32 transactional,
33 pallet_prelude::{DispatchResultWithPostInfo, ConstU32, Get},33 pallet_prelude::{DispatchResultWithPostInfo, ConstU32},
34 BoundedVec,34 BoundedVec,
35};35};
36use sp_core::H160;
37use scale_info::TypeInfo;36use scale_info::TypeInfo;
38use frame_system::{self as system, ensure_signed};37use frame_system::{self as system, ensure_signed};
39use sp_runtime::{sp_std::prelude::Vec};38use sp_runtime::{sp_std::prelude::Vec};
75 /// Weight information for extrinsics in this pallet.74 /// Weight information for extrinsics in this pallet.
76 type WeightInfo: WeightInfo;75 type WeightInfo: WeightInfo;
77 type CommonWeightInfo: CommonWeightInfo<Self::CrossAccountId>;76 type CommonWeightInfo: CommonWeightInfo<Self::CrossAccountId>;
78 type ContractAddress: Get<H160>;
79}77}
8078
81decl_event! {79decl_event! {
287285
288 // =========286 // =========
289287
290 T::CollectionDispatch::create(sender, data)?;288 T::CollectionDispatch::create(T::CrossAccountId::from_sub(sender), data)?;
291289
292 Ok(())290 Ok(())
293 }291 }
modifiedruntime/common/src/dispatch.rsdiffbeforeafterboth
30 + pallet_nonfungible::Config30 + pallet_nonfungible::Config
31 + pallet_refungible::Config,31 + pallet_refungible::Config,
32{32{
33 fn create(sender: T::AccountId, data: CreateCollectionData<T::AccountId>) -> DispatchResult {33 fn create(
34 sender: T::CrossAccountId,
35 data: CreateCollectionData<T::AccountId>,
36 ) -> DispatchResult {
34 let _id = match data.mode {37 let _id = match data.mode {
35 CollectionMode::NFT => <PalletNonfungible<T>>::init_collection(sender, data)?,38 CollectionMode::NFT => <PalletNonfungible<T>>::init_collection(sender, data)?,
modifiedruntime/opal/src/lib.rsdiffbeforeafterboth
306 pallet_evm_migration::OnMethodCall<Self>,306 pallet_evm_migration::OnMethodCall<Self>,
307 pallet_evm_contract_helpers::HelpersOnMethodCall<Self>,307 pallet_evm_contract_helpers::HelpersOnMethodCall<Self>,
308 CollectionDispatchT<Self>,308 CollectionDispatchT<Self>,
309 pallet_unique::eth::CollectionHelperOnMethodCall<Self>,309 pallet_unique::eth::CollectionHelpersOnMethodCall<Self>,
310 );310 );
311 type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;311 type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;
312 type ChainId = ChainId;312 type ChainId = ChainId;
822);822);
823823
824impl pallet_evm_coder_substrate::Config for Runtime {824impl pallet_evm_coder_substrate::Config for Runtime {}
825 type GasWeightMapping = FixedGasWeightMapping;
826}
827825
828impl pallet_xcm::Config for Runtime {826impl pallet_xcm::Config for Runtime {
885883
886 type EvmTokenAddressMapping = EvmTokenAddressMapping;884 type EvmTokenAddressMapping = EvmTokenAddressMapping;
887 type CrossTokenAddressMapping = CrossTokenAddressMapping<Self::AccountId>;885 type CrossTokenAddressMapping = CrossTokenAddressMapping<Self::AccountId>;
886 type ContractAddress = EvmCollectionHelpersAddress;
888}887}
889888
890impl pallet_structure::Config for Runtime {889impl pallet_structure::Config for Runtime {
917 type Event = Event;916 type Event = Event;
918 type WeightInfo = pallet_unique::weights::SubstrateWeight<Self>;917 type WeightInfo = pallet_unique::weights::SubstrateWeight<Self>;
919 type CommonWeightInfo = CommonWeights<Self>;918 type CommonWeightInfo = CommonWeights<Self>;
920 type ContractAddress = EvmCollectionHelperAddress;
921}919}
922920
923parameter_types! {921parameter_types! {
980 ]);978 ]);
981979
982 // 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f980 // 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f
983 pub const EvmCollectionHelperAddress: H160 = H160([981 pub const EvmCollectionHelpersAddress: H160 = H160([
984 0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f,982 0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f,
985 ]);983 ]);
986}984}
modifiedruntime/quartz/src/lib.rsdiffbeforeafterboth
285 pallet_evm_migration::OnMethodCall<Self>,285 pallet_evm_migration::OnMethodCall<Self>,
286 pallet_evm_contract_helpers::HelpersOnMethodCall<Self>,286 pallet_evm_contract_helpers::HelpersOnMethodCall<Self>,
287 CollectionDispatchT<Self>,287 CollectionDispatchT<Self>,
288 pallet_unique::eth::CollectionHelperOnMethodCall<Self>,288 pallet_unique::eth::CollectionHelpersOnMethodCall<Self>,
289 );289 );
290 type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;290 type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;
291 type ChainId = ChainId;291 type ChainId = ChainId;
801);801);
802802
803impl pallet_evm_coder_substrate::Config for Runtime {803impl pallet_evm_coder_substrate::Config for Runtime {}
804 type GasWeightMapping = FixedGasWeightMapping;
805}
806804
807impl pallet_xcm::Config for Runtime {805impl pallet_xcm::Config for Runtime {
864862
865 type EvmTokenAddressMapping = EvmTokenAddressMapping;863 type EvmTokenAddressMapping = EvmTokenAddressMapping;
866 type CrossTokenAddressMapping = CrossTokenAddressMapping<Self::AccountId>;864 type CrossTokenAddressMapping = CrossTokenAddressMapping<Self::AccountId>;
865 type ContractAddress = EvmCollectionHelpersAddress;
867}866}
868867
869impl pallet_structure::Config for Runtime {868impl pallet_structure::Config for Runtime {
900 type Event = Event;899 type Event = Event;
901 type WeightInfo = pallet_unique::weights::SubstrateWeight<Self>;900 type WeightInfo = pallet_unique::weights::SubstrateWeight<Self>;
902 type CommonWeightInfo = CommonWeights<Self>;901 type CommonWeightInfo = CommonWeights<Self>;
903 type ContractAddress = EvmCollectionHelperAddress;
904}902}
905903
906parameter_types! {904parameter_types! {
963 ]);961 ]);
964 962
965 // 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f963 // 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f
966 pub const EvmCollectionHelperAddress: H160 = H160([964 pub const EvmCollectionHelpersAddress: H160 = H160([
967 0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f,965 0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f,
968 ]);966 ]);
969}967}
modifiedruntime/tests/src/lib.rsdiffbeforeafterboth
209 type TransactionValidityHack = ();209 type TransactionValidityHack = ();
210}210}
211impl pallet_evm_coder_substrate::Config for Test {211impl pallet_evm_coder_substrate::Config for Test {}
212 type GasWeightMapping = ();
213}
214212
215impl pallet_common::Config for Test {213impl pallet_common::Config for Test {
222 type CollectionDispatch = CollectionDispatchT<Self>;220 type CollectionDispatch = CollectionDispatchT<Self>;
223 type EvmTokenAddressMapping = EvmTokenAddressMapping;221 type EvmTokenAddressMapping = EvmTokenAddressMapping;
224 type CrossTokenAddressMapping = CrossTokenAddressMapping<Self::AccountId>;222 type CrossTokenAddressMapping = CrossTokenAddressMapping<Self::AccountId>;
223 type ContractAddress = EvmCollectionHelpersAddress;
225}224}
226225
227impl pallet_evm::account::Config for Test {226impl pallet_evm::account::Config for Test {
247246
248parameter_types! {247parameter_types! {
249 // 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f248 // 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f
250 pub const EvmCollectionHelperAddress: H160 = H160([249 pub const EvmCollectionHelpersAddress: H160 = H160([
251 0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f,250 0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f,
252 ]);251 ]);
253}252}
256 type Event = ();255 type Event = ();
257 type WeightInfo = ();256 type WeightInfo = ();
258 type CommonWeightInfo = CommonWeights<Self>;257 type CommonWeightInfo = CommonWeights<Self>;
259 type ContractAddress = EvmCollectionHelperAddress;
260}258}
261259
262// Build genesis storage according to the mock runtime.260// Build genesis storage according to the mock runtime.
modifiedruntime/unique/src/lib.rsdiffbeforeafterboth
290 pallet_evm_migration::OnMethodCall<Self>,290 pallet_evm_migration::OnMethodCall<Self>,
291 pallet_evm_contract_helpers::HelpersOnMethodCall<Self>,291 pallet_evm_contract_helpers::HelpersOnMethodCall<Self>,
292 CollectionDispatchT<Self>,292 CollectionDispatchT<Self>,
293 pallet_unique::eth::CollectionHelperOnMethodCall<Self>,293 pallet_unique::eth::CollectionHelpersOnMethodCall<Self>,
294 );294 );
295 type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;295 type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;
296 type ChainId = ChainId;296 type ChainId = ChainId;
806);806);
807807
808impl pallet_evm_coder_substrate::Config for Runtime {808impl pallet_evm_coder_substrate::Config for Runtime {}
809 type GasWeightMapping = FixedGasWeightMapping;
810}
811809
812impl pallet_xcm::Config for Runtime {810impl pallet_xcm::Config for Runtime {
869867
870 type EvmTokenAddressMapping = EvmTokenAddressMapping;868 type EvmTokenAddressMapping = EvmTokenAddressMapping;
871 type CrossTokenAddressMapping = CrossTokenAddressMapping<Self::AccountId>;869 type CrossTokenAddressMapping = CrossTokenAddressMapping<Self::AccountId>;
870 type ContractAddress = EvmCollectionHelpersAddress;
872}871}
873872
874impl pallet_structure::Config for Runtime {873impl pallet_structure::Config for Runtime {
905 type Event = Event;904 type Event = Event;
906 type WeightInfo = pallet_unique::weights::SubstrateWeight<Self>;905 type WeightInfo = pallet_unique::weights::SubstrateWeight<Self>;
907 type CommonWeightInfo = CommonWeights<Self>;906 type CommonWeightInfo = CommonWeights<Self>;
908 type ContractAddress = EvmCollectionHelperAddress;
909}907}
910908
911parameter_types! {909parameter_types! {
968 ]);966 ]);
969 967
970 // 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f968 // 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f
971 pub const EvmCollectionHelperAddress: H160 = H160([969 pub const EvmCollectionHelpersAddress: H160 = H160([
972 0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f,970 0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f,
973 ]);971 ]);
974}972}
deletedtests/src/eth/api/CollectionHelper.soldiffbeforeafterboth

no changes

addedtests/src/eth/api/CollectionHelpers.soldiffbeforeafterboth

no changes

modifiedtests/src/eth/api/UniqueFungible.soldiffbeforeafterboth
65 returns (uint256);65 returns (uint256);
66}66}
6767
68// Selector: f565282968// Selector: c894dc35
69interface Collection is Dummy, ERC165 {69interface Collection is Dummy, ERC165 {
70 // Selector: setCollectionProperty(string,bytes) 2f073f6670 // Selector: setCollectionProperty(string,bytes) 2f073f66
71 function setCollectionProperty(string memory key, bytes memory value)71 function setCollectionProperty(string memory key, bytes memory value)
88 // Selector: ethConfirmSponsorship() a8580d1a88 // Selector: ethConfirmSponsorship() a8580d1a
89 function ethConfirmSponsorship() external;89 function ethConfirmSponsorship() external;
9090
91 // Selector: setLimit(string,string) bf4d201491 // Selector: setLimit(string,uint32) 68db30ca
92 function setLimit(string memory limit, string memory value) external;92 function setLimit(string memory limit, uint32 value) external;
93
94 // Selector: setLimit(string,bool) ea67e4c2
95 function setLimit(string memory limit, bool value) external;
9396
94 // Selector: contractAddress() f6b4dfb497 // Selector: contractAddress() f6b4dfb4
95 function contractAddress() external view returns (address);98 function contractAddress() external view returns (address);
modifiedtests/src/eth/api/UniqueNFT.soldiffbeforeafterboth
191 function totalSupply() external view returns (uint256);191 function totalSupply() external view returns (uint256);
192}192}
193
194// Selector: c894dc35
195interface Collection is Dummy, ERC165 {
196 // Selector: setCollectionProperty(string,bytes) 2f073f66
197 function setCollectionProperty(string memory key, bytes memory value)
198 external;
199
200 // Selector: deleteCollectionProperty(string) 7b7debce
201 function deleteCollectionProperty(string memory key) external;
202
203 // Throws error if key not found
204 //
205 // Selector: collectionProperty(string) cf24fd6d
206 function collectionProperty(string memory key)
207 external
208 view
209 returns (bytes memory);
210
211 // Selector: ethSetSponsor(address) 8f9af356
212 function ethSetSponsor(address sponsor) external;
213
214 // Selector: ethConfirmSponsorship() a8580d1a
215 function ethConfirmSponsorship() external;
216
217 // Selector: setLimit(string,uint32) 68db30ca
218 function setLimit(string memory limit, uint32 value) external;
219
220 // Selector: setLimit(string,bool) ea67e4c2
221 function setLimit(string memory limit, bool value) external;
222
223 // Selector: contractAddress() f6b4dfb4
224 function contractAddress() external view returns (address);
225}
193226
194// Selector: d74d154f227// Selector: d74d154f
195interface ERC721UniqueExtensions is Dummy, ERC165 {228interface ERC721UniqueExtensions is Dummy, ERC165 {
213 returns (bool);246 returns (bool);
214}247}
215
216// Selector: f5652829
217interface Collection is Dummy, ERC165 {
218 // Selector: setCollectionProperty(string,bytes) 2f073f66
219 function setCollectionProperty(string memory key, bytes memory value)
220 external;
221
222 // Selector: deleteCollectionProperty(string) 7b7debce
223 function deleteCollectionProperty(string memory key) external;
224
225 // Throws error if key not found
226 //
227 // Selector: collectionProperty(string) cf24fd6d
228 function collectionProperty(string memory key)
229 external
230 view
231 returns (bytes memory);
232
233 // Selector: ethSetSponsor(address) 8f9af356
234 function ethSetSponsor(address sponsor) external;
235
236 // Selector: ethConfirmSponsorship() a8580d1a
237 function ethConfirmSponsorship() external;
238
239 // Selector: setLimit(string,string) bf4d2014
240 function setLimit(string memory limit, string memory value) external;
241
242 // Selector: contractAddress() f6b4dfb4
243 function contractAddress() external view returns (address);
244}
245248
246interface UniqueNFT is249interface UniqueNFT is
247 Dummy,250 Dummy,
deletedtests/src/eth/collectionHelperAbi.jsondiffbeforeafterboth

no changes

addedtests/src/eth/collectionHelpersAbi.jsondiffbeforeafterboth

no changes

modifiedtests/src/eth/contractSponsoring.test.tsdiffbeforeafterboth
29 normalizeEvents,29 normalizeEvents,
30 subToEth,30 subToEth,
31 executeEthTxOnSub,31 executeEthTxOnSub,
32 evmCollectionHelper,32 evmCollectionHelpers,
33 getCollectionAddressFromResult,33 getCollectionAddressFromResult,
34 evmCollection,34 evmCollection,
35} from './util/helpers';35} from './util/helpers';
224 //TODO: CORE-302 add eth methods224 //TODO: CORE-302 add eth methods
225 itWeb3.skip('Sponsoring evm address from substrate collection', async ({api, web3}) => {225 itWeb3.skip('Sponsoring evm address from substrate collection', async ({api, web3}) => {
226 const owner = await createEthAccountWithBalance(api, web3);226 const owner = await createEthAccountWithBalance(api, web3);
227 const collectionHelper = evmCollectionHelper(web3, owner);227 const collectionHelpers = evmCollectionHelpers(web3, owner);
228 let result = await collectionHelper.methods.create721Collection('Sponsor collection', '1', '1').send();228 let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send();
229 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);229 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
230 const sponsor = await createEthAccountWithBalance(api, web3);230 const sponsor = await createEthAccountWithBalance(api, web3);
231 const collectionEvm = evmCollection(web3, owner, collectionIdAddress);231 const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
modifiedtests/src/eth/createCollection.test.tsdiffbeforeafterboth
18import {expect} from 'chai';18import {expect} from 'chai';
19import {getCreatedCollectionCount, getDetailedCollectionInfo} from '../util/helpers';19import {getCreatedCollectionCount, getDetailedCollectionInfo} from '../util/helpers';
20import {20import {
21 evmCollectionHelper,21 evmCollectionHelpers,
22 collectionIdToAddress,22 collectionIdToAddress,
23 createEthAccount,23 createEthAccount,
24 createEthAccountWithBalance,24 createEthAccountWithBalance,
30describe('Create collection from EVM', () => {30describe('Create collection from EVM', () => {
31 itWeb3('Create collection', async ({api, web3}) => {31 itWeb3('Create collection', async ({api, web3}) => {
32 const owner = await createEthAccountWithBalance(api, web3);32 const owner = await createEthAccountWithBalance(api, web3);
33 const helper = evmCollectionHelper(web3, owner);33 const helper = evmCollectionHelpers(web3, owner);
34 const collectionName = 'CollectionEVM';34 const collectionName = 'CollectionEVM';
35 const description = 'Some description';35 const description = 'Some description';
36 const tokenPrefix = 'token prefix';36 const tokenPrefix = 'token prefix';
37 37
38 const collectionCountBefore = await getCreatedCollectionCount(api);38 const collectionCountBefore = await getCreatedCollectionCount(api);
39 const result = await helper.methods39 const result = await helper.methods
40 .create721Collection(collectionName, description, tokenPrefix)40 .createNonfungibleCollection(collectionName, description, tokenPrefix)
41 .send();41 .send();
42 const collectionCountAfter = await getCreatedCollectionCount(api);42 const collectionCountAfter = await getCreatedCollectionCount(api);
43 43
5151
52 itWeb3('Check collection address exist', async ({api, web3}) => {52 itWeb3('Check collection address exist', async ({api, web3}) => {
53 const owner = await createEthAccountWithBalance(api, web3);53 const owner = await createEthAccountWithBalance(api, web3);
54 const collectionHelper = evmCollectionHelper(web3, owner);54 const collectionHelpers = evmCollectionHelpers(web3, owner);
55 55
56 const expectedCollectionId = await getCreatedCollectionCount(api) + 1;56 const expectedCollectionId = await getCreatedCollectionCount(api) + 1;
57 const expectedCollectionAddress = collectionIdToAddress(expectedCollectionId);57 const expectedCollectionAddress = collectionIdToAddress(expectedCollectionId);
58 expect(await collectionHelper.methods58 expect(await collectionHelpers.methods
59 .isCollectionExist(expectedCollectionAddress)59 .isCollectionExist(expectedCollectionAddress)
60 .call()).to.be.false;60 .call()).to.be.false;
6161
62 await collectionHelper.methods62 await collectionHelpers.methods
63 .create721Collection('A', 'A', 'A')63 .createNonfungibleCollection('A', 'A', 'A')
64 .send();64 .send();
65 65
66 expect(await collectionHelper.methods66 expect(await collectionHelpers.methods
67 .isCollectionExist(expectedCollectionAddress)67 .isCollectionExist(expectedCollectionAddress)
68 .call()).to.be.true;68 .call()).to.be.true;
69 });69 });
70 70
71 itWeb3('Set sponsorship', async ({api, web3}) => {71 itWeb3('Set sponsorship', async ({api, web3}) => {
72 const owner = await createEthAccountWithBalance(api, web3);72 const owner = await createEthAccountWithBalance(api, web3);
73 const collectionHelper = evmCollectionHelper(web3, owner);73 const collectionHelpers = evmCollectionHelpers(web3, owner);
74 let result = await collectionHelper.methods.create721Collection('Sponsor collection', '1', '1').send();74 let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send();
75 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);75 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
76 const sponsor = await createEthAccountWithBalance(api, web3);76 const sponsor = await createEthAccountWithBalance(api, web3);
77 const collectionEvm = evmCollection(web3, owner, collectionIdAddress);77 const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
8989
90 itWeb3('Set limits', async ({api, web3}) => {90 itWeb3('Set limits', async ({api, web3}) => {
91 const owner = await createEthAccountWithBalance(api, web3);91 const owner = await createEthAccountWithBalance(api, web3);
92 const collectionHelper = evmCollectionHelper(web3, owner);92 const collectionHelpers = evmCollectionHelpers(web3, owner);
93 const result = await collectionHelper.methods.create721Collection('Const collection', '5', '5').send();93 const result = await collectionHelpers.methods.createNonfungibleCollection('Const collection', '5', '5').send();
94 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);94 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
95 const limits = {95 const limits = {
96 accountTokenOwnershipLimit: 1000,96 accountTokenOwnershipLimit: 1000,
105 };105 };
106106
107 const collectionEvm = evmCollection(web3, owner, collectionIdAddress);107 const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
108 await collectionEvm.methods.setLimit('accountTokenOwnershipLimit', limits.accountTokenOwnershipLimit.toString()).send();108 await collectionEvm.methods['setLimit(string,uint32)']('accountTokenOwnershipLimit', limits.accountTokenOwnershipLimit).send();
109 await collectionEvm.methods.setLimit('sponsoredDataSize', limits.sponsoredDataSize.toString()).send();109 await collectionEvm.methods['setLimit(string,uint32)']('sponsoredDataSize', limits.sponsoredDataSize).send();
110 await collectionEvm.methods.setLimit('sponsoredDataRateLimit', limits.sponsoredDataRateLimit.toString()).send();110 await collectionEvm.methods['setLimit(string,uint32)']('sponsoredDataRateLimit', limits.sponsoredDataRateLimit).send();
111 await collectionEvm.methods.setLimit('tokenLimit', limits.tokenLimit.toString()).send();111 await collectionEvm.methods['setLimit(string,uint32)']('tokenLimit', limits.tokenLimit).send();
112 await collectionEvm.methods.setLimit('sponsorTransferTimeout', limits.sponsorTransferTimeout.toString()).send();112 await collectionEvm.methods['setLimit(string,uint32)']('sponsorTransferTimeout', limits.sponsorTransferTimeout).send();
113 await collectionEvm.methods.setLimit('sponsorApproveTimeout', limits.sponsorApproveTimeout.toString()).send();113 await collectionEvm.methods['setLimit(string,uint32)']('sponsorApproveTimeout', limits.sponsorApproveTimeout).send();
114 await collectionEvm.methods.setLimit('ownerCanTransfer', limits.ownerCanTransfer.toString()).send();114 await collectionEvm.methods['setLimit(string,bool)']('ownerCanTransfer', limits.ownerCanTransfer).send();
115 await collectionEvm.methods.setLimit('ownerCanDestroy', limits.ownerCanDestroy.toString()).send();115 await collectionEvm.methods['setLimit(string,bool)']('ownerCanDestroy', limits.ownerCanDestroy).send();
116 await collectionEvm.methods.setLimit('transfersEnabled', limits.transfersEnabled.toString()).send();116 await collectionEvm.methods['setLimit(string,bool)']('transfersEnabled', limits.transfersEnabled).send();
117 117
118 const collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;118 const collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
119 expect(collectionSub.limits.accountTokenOwnershipLimit.unwrap().toNumber()).to.be.eq(limits.accountTokenOwnershipLimit);119 expect(collectionSub.limits.accountTokenOwnershipLimit.unwrap().toNumber()).to.be.eq(limits.accountTokenOwnershipLimit);
130 itWeb3('Collection address exist', async ({api, web3}) => {130 itWeb3('Collection address exist', async ({api, web3}) => {
131 const owner = await createEthAccountWithBalance(api, web3);131 const owner = await createEthAccountWithBalance(api, web3);
132 const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233';132 const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233';
133 const collectionHelper = evmCollectionHelper(web3, owner);133 const collectionHelpers = evmCollectionHelpers(web3, owner);
134 expect(await collectionHelper.methods134 expect(await collectionHelpers.methods
135 .isCollectionExist(collectionAddressForNonexistentCollection).call())135 .isCollectionExist(collectionAddressForNonexistentCollection).call())
136 .to.be.false;136 .to.be.false;
137 137
138 const result = await collectionHelper.methods.create721Collection('Collection address exist', '7', '7').send();138 const result = await collectionHelpers.methods.createNonfungibleCollection('Collection address exist', '7', '7').send();
139 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);139 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
140 expect(await collectionHelper.methods140 expect(await collectionHelpers.methods
141 .isCollectionExist(collectionIdAddress).call())141 .isCollectionExist(collectionIdAddress).call())
142 .to.be.true;142 .to.be.true;
143 });143 });
146describe('(!negative tests!) Create collection from EVM', () => {146describe('(!negative tests!) Create collection from EVM', () => {
147 itWeb3('(!negative test!) Create collection (bad lengths)', async ({api, web3}) => {147 itWeb3('(!negative test!) Create collection (bad lengths)', async ({api, web3}) => {
148 const owner = await createEthAccountWithBalance(api, web3);148 const owner = await createEthAccountWithBalance(api, web3);
149 const helper = evmCollectionHelper(web3, owner);149 const helper = evmCollectionHelpers(web3, owner);
150 {150 {
151 const MAX_NAME_LENGHT = 64;151 const MAX_NAME_LENGHT = 64;
152 const collectionName = 'A'.repeat(MAX_NAME_LENGHT + 1);152 const collectionName = 'A'.repeat(MAX_NAME_LENGHT + 1);
153 const description = 'A';153 const description = 'A';
154 const tokenPrefix = 'A';154 const tokenPrefix = 'A';
155 155
156 await expect(helper.methods156 await expect(helper.methods
157 .create721Collection(collectionName, description, tokenPrefix)157 .createNonfungibleCollection(collectionName, description, tokenPrefix)
158 .call()).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGHT);158 .call()).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGHT);
159 159
160 }160 }
164 const description = 'A'.repeat(MAX_DESCRIPTION_LENGHT + 1);164 const description = 'A'.repeat(MAX_DESCRIPTION_LENGHT + 1);
165 const tokenPrefix = 'A';165 const tokenPrefix = 'A';
166 await expect(helper.methods166 await expect(helper.methods
167 .create721Collection(collectionName, description, tokenPrefix)167 .createNonfungibleCollection(collectionName, description, tokenPrefix)
168 .call()).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGHT);168 .call()).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGHT);
169 }169 }
170 { 170 {
173 const description = 'A';173 const description = 'A';
174 const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGHT + 1);174 const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGHT + 1);
175 await expect(helper.methods175 await expect(helper.methods
176 .create721Collection(collectionName, description, tokenPrefix)176 .createNonfungibleCollection(collectionName, description, tokenPrefix)
177 .call()).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGHT);177 .call()).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGHT);
178 }178 }
179 });179 });
180 180
181 itWeb3('(!negative test!) Create collection (no funds)', async ({web3}) => {181 itWeb3('(!negative test!) Create collection (no funds)', async ({web3}) => {
182 const owner = await createEthAccount(web3);182 const owner = await createEthAccount(web3);
183 const helper = evmCollectionHelper(web3, owner);183 const helper = evmCollectionHelpers(web3, owner);
184 const collectionName = 'A';184 const collectionName = 'A';
185 const description = 'A';185 const description = 'A';
186 const tokenPrefix = 'A';186 const tokenPrefix = 'A';
187 187
188 await expect(helper.methods188 await expect(helper.methods
189 .create721Collection(collectionName, description, tokenPrefix)189 .createNonfungibleCollection(collectionName, description, tokenPrefix)
190 .call()).to.be.rejectedWith('NotSufficientFounds');190 .call()).to.be.rejectedWith('NotSufficientFounds');
191 });191 });
192192
193 itWeb3('(!negative test!) Check owner', async ({api, web3}) => {193 itWeb3('(!negative test!) Check owner', async ({api, web3}) => {
194 const owner = await createEthAccountWithBalance(api, web3);194 const owner = await createEthAccountWithBalance(api, web3);
195 const notOwner = await createEthAccount(web3);195 const notOwner = await createEthAccount(web3);
196 const collectionHelper = evmCollectionHelper(web3, owner);196 const collectionHelpers = evmCollectionHelpers(web3, owner);
197 const result = await collectionHelper.methods.create721Collection('A', 'A', 'A').send();197 const result = await collectionHelpers.methods.createNonfungibleCollection('A', 'A', 'A').send();
198 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);198 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
199 const contractEvmFromNotOwner = evmCollection(web3, notOwner, collectionIdAddress);199 const contractEvmFromNotOwner = evmCollection(web3, notOwner, collectionIdAddress);
200 const EXPECTED_ERROR = 'NoPermission';200 const EXPECTED_ERROR = 'NoPermission';
218218
219 itWeb3('(!negative test!) Set limits', async ({api, web3}) => {219 itWeb3('(!negative test!) Set limits', async ({api, web3}) => {
220 const owner = await createEthAccountWithBalance(api, web3);220 const owner = await createEthAccountWithBalance(api, web3);
221 const collectionHelper = evmCollectionHelper(web3, owner);221 const collectionHelpers = evmCollectionHelpers(web3, owner);
222 const result = await collectionHelper.methods.create721Collection('Schema collection', 'A', 'A').send();222 const result = await collectionHelpers.methods.createNonfungibleCollection('Schema collection', 'A', 'A').send();
223 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);223 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
224 const collectionEvm = evmCollection(web3, owner, collectionIdAddress);224 const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
225 await expect(collectionEvm.methods225 await expect(collectionEvm.methods
226 .setLimit('badLimit', 'true')226 .setLimit('badLimit', 'true')
227 .call()).to.be.rejectedWith('Unknown limit "badLimit"');227 .call()).to.be.rejectedWith('Unknown boolean limit "badLimit"');
228 await expect(collectionEvm.methods
229 .setLimit('sponsoredDataSize', 'badValue')
230 .call()).to.be.rejectedWith('Int value "badValue" parse error:');
231 await expect(collectionEvm.methods
232 .setLimit('ownerCanTransfer', 'badValue')
233 .call()).to.be.rejectedWith('Bool value "badValue" parse error:');
234 });228 });
235});229});
modifiedtests/src/eth/fungibleAbi.jsondiffbeforeafterboth
152 {152 {
153 "inputs": [153 "inputs": [
154 { "internalType": "string", "name": "limit", "type": "string" },154 { "internalType": "string", "name": "limit", "type": "string" },
155 { "internalType": "string", "name": "value", "type": "string" }155 { "internalType": "uint32", "name": "value", "type": "uint32" }
156 ],156 ],
157 "name": "setLimit",157 "name": "setLimit",
158 "outputs": [],158 "outputs": [],
159 "stateMutability": "nonpayable",159 "stateMutability": "nonpayable",
160 "type": "function"160 "type": "function"
161 },161 },
162 {
163 "inputs": [
164 { "internalType": "string", "name": "limit", "type": "string" },
165 { "internalType": "bool", "name": "value", "type": "bool" }
166 ],
167 "name": "setLimit",
168 "outputs": [],
169 "stateMutability": "nonpayable",
170 "type": "function"
171 },
162 {172 {
163 "inputs": [173 "inputs": [
164 { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }174 { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }
modifiedtests/src/eth/nonFungible.test.tsdiffbeforeafterboth
1616
17import privateKey from '../substrate/privateKey';17import privateKey from '../substrate/privateKey';
18import {approveExpectSuccess, burnItemExpectSuccess, createCollectionExpectSuccess, createItemExpectSuccess, transferExpectSuccess, transferFromExpectSuccess, UNIQUE} from '../util/helpers';18import {approveExpectSuccess, burnItemExpectSuccess, createCollectionExpectSuccess, createItemExpectSuccess, transferExpectSuccess, transferFromExpectSuccess, UNIQUE} from '../util/helpers';
19import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, evmCollectionHelper, GAS_ARGS, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, transferBalanceToEth} from './util/helpers';19import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, evmCollectionHelpers, GAS_ARGS, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, transferBalanceToEth} from './util/helpers';
20import nonFungibleAbi from './nonFungibleAbi.json';20import nonFungibleAbi from './nonFungibleAbi.json';
21import {expect} from 'chai';21import {expect} from 'chai';
22import {submitTransactionAsync} from '../substrate/substrate-api';22import {submitTransactionAsync} from '../substrate/substrate-api';
76describe('NFT: Plain calls', () => {76describe('NFT: Plain calls', () => {
77 itWeb3('Can perform mint()', async ({web3, api}) => {77 itWeb3('Can perform mint()', async ({web3, api}) => {
78 const owner = await createEthAccountWithBalance(api, web3);78 const owner = await createEthAccountWithBalance(api, web3);
79 const helper = evmCollectionHelper(web3, owner);79 const helper = evmCollectionHelpers(web3, owner);
80 let result = await helper.methods.create721Collection('Mint collection', '6', '6').send();80 let result = await helper.methods.createNonfungibleCollection('Mint collection', '6', '6').send();
81 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);81 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
82 const receiver = createEthAccount(web3);82 const receiver = createEthAccount(web3);
83 const contract = evmCollection(web3, owner, collectionIdAddress);83 const contract = evmCollection(web3, owner, collectionIdAddress);
modifiedtests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth
326 {326 {
327 "inputs": [327 "inputs": [
328 { "internalType": "string", "name": "limit", "type": "string" },328 { "internalType": "string", "name": "limit", "type": "string" },
329 { "internalType": "string", "name": "value", "type": "string" }329 { "internalType": "uint32", "name": "value", "type": "uint32" }
330 ],330 ],
331 "name": "setLimit",331 "name": "setLimit",
332 "outputs": [],332 "outputs": [],
333 "stateMutability": "nonpayable",333 "stateMutability": "nonpayable",
334 "type": "function"334 "type": "function"
335 },335 },
336 {
337 "inputs": [
338 { "internalType": "string", "name": "limit", "type": "string" },
339 { "internalType": "bool", "name": "value", "type": "bool" }
340 ],
341 "name": "setLimit",
342 "outputs": [],
343 "stateMutability": "nonpayable",
344 "type": "function"
345 },
336 {346 {
337 "inputs": [347 "inputs": [
338 { "internalType": "uint256", "name": "tokenId", "type": "uint256" },348 { "internalType": "uint256", "name": "tokenId", "type": "uint256" },
modifiedtests/src/eth/util/helpers.tsdiffbeforeafterboth
29import privateKey from '../../substrate/privateKey';29import privateKey from '../../substrate/privateKey';
30import contractHelpersAbi from './contractHelpersAbi.json';30import contractHelpersAbi from './contractHelpersAbi.json';
31import nonFungibleAbi from '../nonFungibleAbi.json';31import nonFungibleAbi from '../nonFungibleAbi.json';
32import collectionHelperAbi from '../collectionHelperAbi.json';32import collectionHelpersAbi from '../collectionHelpersAbi.json';
33import getBalance from '../../substrate/get-balance';33import getBalance from '../../substrate/get-balance';
34import waitNewBlocks from '../../substrate/wait-new-blocks';34import waitNewBlocks from '../../substrate/wait-new-blocks';
3535
69}69}
7070
71export async function getCollectionAddressFromResult(api: ApiPromise, result: any) {71export async function getCollectionAddressFromResult(api: ApiPromise, result: any) {
72 const collectionIdAddress = normalizeAddress(result.events[0].raw.topics[2]);72 const collectionIdAddress = normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);
73 const collectionId = collectionIdFromAddress(collectionIdAddress); 73 const collectionId = collectionIdFromAddress(collectionIdAddress);
74 const collection = (await getDetailedCollectionInfo(api, collectionId))!;74 const collection = (await getDetailedCollectionInfo(api, collectionId))!;
75 return {collectionIdAddress, collectionId, collection};75 return {collectionIdAddress, collectionId, collection};
297 * @param caller - eth address297 * @param caller - eth address
298 * @returns 298 * @returns
299 */299 */
300export function evmCollectionHelper(web3: Web3, caller: string) {300export function evmCollectionHelpers(web3: Web3, caller: string) {
301 return new web3.eth.Contract(collectionHelperAbi as any, '0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f', {from: caller, ...GAS_ARGS});301 return new web3.eth.Contract(collectionHelpersAbi as any, '0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f', {from: caller, ...GAS_ARGS});
302}302}
303303
304/** 304/**