difftreelog
Merge branch 'feature/multi-assets-redone' of https://github.com/UniqueNetwork/unique-chain into feature/multi-assets-redone
in: master
72 files changed
.maintain/scripts/generate_sol.shdiffbeforeafterboth1#!/bin/sh1#!/bin/sh2set -eu2set -eu34PRETTIER_CONFIG="$(pwd)""/.prettierrc"354tmp=$(mktemp)6tmp=$(mktemp)5cargo test --package $PACKAGE -- $NAME --exact --nocapture --ignored | tee $tmp7cargo test --package $PACKAGE -- $NAME --exact --nocapture --ignored | tee $tmp6raw=$(mktemp --suffix .sol)8raw=$(mktemp --suffix .sol)7sed -n '/=== SNIP START ===/, /=== SNIP END ===/{ /=== SNIP START ===/! { /=== SNIP END ===/! p } }' $tmp > $raw9sed -n '/=== SNIP START ===/, /=== SNIP END ===/{ /=== SNIP START ===/! { /=== SNIP END ===/! p } }' $tmp > $raw108formatted=$(mktemp)11formatted=$(mktemp)9prettier --use-tabs $raw > $formatted12prettier --config $PRETTIER_CONFIG $raw > $formatted101311mv $formatted $OUTPUT14mv $formatted $OUTPUT1215.prettierignorediffbeforeafterbothno changes
.prettierrcdiffbeforeafterbothno changes
Cargo.lockdiffbeforeafterboth2324[[package]]2324[[package]]2325name = "fc-consensus"2325name = "fc-consensus"2326version = "2.0.0-dev"2326version = "2.0.0-dev"2327source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"2327source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"2328dependencies = [2328dependencies = [2329 "async-trait",2329 "async-trait",2330 "fc-db",2330 "fc-db",2343[[package]]2343[[package]]2344name = "fc-db"2344name = "fc-db"2345version = "2.0.0-dev"2345version = "2.0.0-dev"2346source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"2346source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"2347dependencies = [2347dependencies = [2348 "fp-storage",2348 "fp-storage",2349 "kvdb-rocksdb",2349 "kvdb-rocksdb",2359[[package]]2359[[package]]2360name = "fc-mapping-sync"2360name = "fc-mapping-sync"2361version = "2.0.0-dev"2361version = "2.0.0-dev"2362source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"2362source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"2363dependencies = [2363dependencies = [2364 "fc-db",2364 "fc-db",2365 "fp-consensus",2365 "fp-consensus",2376[[package]]2376[[package]]2377name = "fc-rpc"2377name = "fc-rpc"2378version = "2.0.0-dev"2378version = "2.0.0-dev"2379source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"2379source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"2380dependencies = [2380dependencies = [2381 "ethereum",2381 "ethereum",2382 "ethereum-types",2382 "ethereum-types",2416[[package]]2416[[package]]2417name = "fc-rpc-core"2417name = "fc-rpc-core"2418version = "1.1.0-dev"2418version = "1.1.0-dev"2419source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"2419source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"2420dependencies = [2420dependencies = [2421 "ethereum",2421 "ethereum",2422 "ethereum-types",2422 "ethereum-types",2557[[package]]2557[[package]]2558name = "fp-consensus"2558name = "fp-consensus"2559version = "2.0.0-dev"2559version = "2.0.0-dev"2560source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"2560source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"2561dependencies = [2561dependencies = [2562 "ethereum",2562 "ethereum",2563 "parity-scale-codec 3.1.5",2563 "parity-scale-codec 3.1.5",2569[[package]]2569[[package]]2570name = "fp-evm"2570name = "fp-evm"2571version = "3.0.0-dev"2571version = "3.0.0-dev"2572source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"2572source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"2573dependencies = [2573dependencies = [2574 "evm",2574 "evm",2575 "frame-support",2575 "frame-support",2583[[package]]2583[[package]]2584name = "fp-evm-mapping"2584name = "fp-evm-mapping"2585version = "0.1.0"2585version = "0.1.0"2586source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"2586source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"2587dependencies = [2587dependencies = [2588 "frame-support",2588 "frame-support",2589 "sp-core",2589 "sp-core",2592[[package]]2592[[package]]2593name = "fp-rpc"2593name = "fp-rpc"2594version = "3.0.0-dev"2594version = "3.0.0-dev"2595source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"2595source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"2596dependencies = [2596dependencies = [2597 "ethereum",2597 "ethereum",2598 "ethereum-types",2598 "ethereum-types",2609[[package]]2609[[package]]2610name = "fp-self-contained"2610name = "fp-self-contained"2611version = "1.0.0-dev"2611version = "1.0.0-dev"2612source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"2612source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"2613dependencies = [2613dependencies = [2614 "ethereum",2614 "ethereum",2615 "frame-support",2615 "frame-support",2625[[package]]2625[[package]]2626name = "fp-storage"2626name = "fp-storage"2627version = "2.0.0"2627version = "2.0.0"2628source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"2628source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"2629dependencies = [2629dependencies = [2630 "parity-scale-codec 3.1.5",2630 "parity-scale-codec 3.1.5",2631]2631]5543[[package]]5543[[package]]5544name = "pallet-base-fee"5544name = "pallet-base-fee"5545version = "1.0.0"5545version = "1.0.0"5546source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"5546source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"5547dependencies = [5547dependencies = [5548 "fp-evm",5548 "fp-evm",5549 "frame-support",5549 "frame-support",5758[[package]]5758[[package]]5759name = "pallet-ethereum"5759name = "pallet-ethereum"5760version = "4.0.0-dev"5760version = "4.0.0-dev"5761source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"5761source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"5762dependencies = [5762dependencies = [5763 "ethereum",5763 "ethereum",5764 "ethereum-types",5764 "ethereum-types",5787[[package]]5787[[package]]5788name = "pallet-evm"5788name = "pallet-evm"5789version = "6.0.0-dev"5789version = "6.0.0-dev"5790source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"5790source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"5791dependencies = [5791dependencies = [5792 "evm",5792 "evm",5793 "fp-evm",5793 "fp-evm",5842 "pallet-common",5842 "pallet-common",5843 "pallet-evm",5843 "pallet-evm",5844 "pallet-evm-coder-substrate",5844 "pallet-evm-coder-substrate",5845 "pallet-evm-transaction-payment",5845 "parity-scale-codec 3.1.5",5846 "parity-scale-codec 3.1.5",5846 "scale-info",5847 "scale-info",5847 "sp-core",5848 "sp-core",client/rpc/Cargo.tomldiffbeforeafterboth19sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }19sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }20sp-rpc = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }20sp-rpc = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }21sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }21sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }22pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }22pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }2323client/rpc/src/lib.rsdiffbeforeafterboth577 BlockNumber: Decode + Member + AtLeast32BitUnsigned,577 BlockNumber: Decode + Member + AtLeast32BitUnsigned,578 AccountId: Decode,578 AccountId: Decode,579 C: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,579 C: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,580 C::Api: AppPromotionRuntimeApi<Block, BlockNumber, CrossAccountId, AccountId>,581 CrossAccountId: pallet_evm::account::CrossAccountId<AccountId>,580 CrossAccountId: pallet_evm::account::CrossAccountId<AccountId>,581 C::Api: AppPromotionRuntimeApi<Block, BlockNumber, CrossAccountId, AccountId>,582{582{583 pass_method!(total_staked(staker: Option<CrossAccountId>) -> String => |v| v.to_string(), app_promotion_api);583 pass_method!(total_staked(staker: Option<CrossAccountId>) -> String => |v| v.to_string(), app_promotion_api);584 pass_method!(total_staked_per_block(staker: CrossAccountId) -> Vec<(BlockNumber, String)> =>584 pass_method!(total_staked_per_block(staker: CrossAccountId) -> Vec<(BlockNumber, String)> =>doc/sponsoring-flow.drawio.svgdiffbeforeafterbothno changes
doc/sponsoring.mddiffbeforeafterbothno changes
node/cli/Cargo.tomldiffbeforeafterboth309jsonrpsee = { version = "0.14.0", features = ["server", "macros"] }309jsonrpsee = { version = "0.14.0", features = ["server", "macros"] }310tokio = { version = "1.19.2", features = ["time"] }310tokio = { version = "1.19.2", features = ["time"] }311311312fc-rpc-core = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }312fc-rpc-core = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }313fc-consensus = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }313fc-consensus = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }314fc-mapping-sync = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }314fc-mapping-sync = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }315fc-rpc = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }315fc-rpc = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }316fc-db = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }316fc-db = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }317fp-rpc = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }317fp-rpc = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }318pallet-ethereum = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }318pallet-ethereum = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }319319320unique-rpc = { default-features = false, path = "../rpc" }320unique-rpc = { default-features = false, path = "../rpc" }321app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false}321app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false}node/rpc/Cargo.tomldiffbeforeafterboth40substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }40substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }41tokio = { version = "1.19.2", features = ["macros", "sync"] }41tokio = { version = "1.19.2", features = ["macros", "sync"] }424243pallet-ethereum = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }43pallet-ethereum = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }44fc-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }44fc-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }45fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }45fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }46fp-storage = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }46fp-storage = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }47fc-rpc-core = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }47fc-rpc-core = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }48fc-db = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }48fc-db = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }49fc-mapping-sync = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }49fc-mapping-sync = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }505051pallet-common = { default-features = false, path = "../../pallets/common" }51pallet-common = { default-features = false, path = "../../pallets/common" }52up-common = { path = "../../primitives/common" }52up-common = { path = "../../primitives/common" }pallets/app-promotion/Cargo.tomldiffbeforeafterboth52pallet-balances ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }52pallet-balances ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }53pallet-timestamp ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }53pallet-timestamp ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }54pallet-randomness-collective-flip ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }54pallet-randomness-collective-flip ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }55pallet-evm ={ default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }55pallet-evm ={ default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }56sp-std ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }56sp-std ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }57sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }57sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }58sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }58sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }pallets/common/Cargo.tomldiffbeforeafterboth17sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }17sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }18sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }18sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }19frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }19frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }20fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }20fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }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 }24ethereum = { version = "0.12.0", default-features = false }25pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }25pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }262627serde = { version = "1.0.130", default-features = false }27serde = { version = "1.0.130", default-features = false }28scale-info = { version = "2.0.1", default-features = false, features = [28scale-info = { version = "2.0.1", default-features = false, features = [pallets/common/src/erc.rsdiffbeforeafterboth20 solidity_interface, solidity, ToLog,20 solidity_interface, solidity, ToLog,21 types::*,21 types::*,22 execution::{Result, Error},22 execution::{Result, Error},23 weight,23};24};24pub use pallet_evm::{PrecompileOutput, PrecompileResult, PrecompileHandle, account::CrossAccountId};25pub use pallet_evm::{PrecompileOutput, PrecompileResult, PrecompileHandle, account::CrossAccountId};25use pallet_evm_coder_substrate::dispatch_to_evm;26use pallet_evm_coder_substrate::dispatch_to_evm;31use alloc::format;32use alloc::format;323333use crate::{34use crate::{34 Pallet, CollectionHandle, Config, CollectionProperties,35 Pallet, CollectionHandle, Config, CollectionProperties, SelfWeightOf,35 eth::{convert_cross_account_to_uint256, convert_uint256_to_cross_account},36 eth::{37 convert_cross_account_to_uint256, convert_uint256_to_cross_account,38 convert_cross_account_to_tuple,39 },40 weights::WeightInfo,36};41};374238/// Events for ethereum collection helper.43/// Events for ethereum collection helper.69 ///74 ///70 /// @param key Property key.75 /// @param key Property key.71 /// @param value Propery value.76 /// @param value Propery value.77 #[weight(<SelfWeightOf<T>>::set_collection_properties(1))]72 fn set_collection_property(78 fn set_collection_property(73 &mut self,79 &mut self,74 caller: caller,80 caller: caller,88 /// Delete collection property.94 /// Delete collection property.89 ///95 ///90 /// @param key Property key.96 /// @param key Property key.97 #[weight(<SelfWeightOf<T>>::delete_collection_properties(1))]91 fn delete_collection_property(&mut self, caller: caller, key: string) -> Result<()> {98 fn delete_collection_property(&mut self, caller: caller, key: string) -> Result<()> {99 self.consume_store_reads_and_writes(1, 1)?;10092 let caller = T::CrossAccountId::from_eth(caller);101 let caller = T::CrossAccountId::from_eth(caller);93 let key = <Vec<u8>>::from(key)102 let key = <Vec<u8>>::from(key)94 .try_into()103 .try_into()120 ///129 ///121 /// @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.130 /// @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.122 fn set_collection_sponsor(&mut self, caller: caller, sponsor: address) -> Result<void> {131 fn set_collection_sponsor(&mut self, caller: caller, sponsor: address) -> Result<void> {132 self.consume_store_reads_and_writes(1, 1)?;133123 check_is_owner_or_admin(caller, self)?;134 check_is_owner_or_admin(caller, self)?;124135125 let sponsor = T::CrossAccountId::from_eth(sponsor);136 let sponsor = T::CrossAccountId::from_eth(sponsor);138 caller: caller,149 caller: caller,139 sponsor: uint256,150 sponsor: uint256,140 ) -> Result<void> {151 ) -> Result<void> {152 self.consume_store_reads_and_writes(1, 1)?;153141 check_is_owner_or_admin(caller, self)?;154 check_is_owner_or_admin(caller, self)?;142155143 let sponsor = convert_uint256_to_cross_account::<T>(sponsor);156 let sponsor = convert_uint256_to_cross_account::<T>(sponsor);146 save(self)159 save(self)147 }160 }148161149 // /// Whether there is a pending sponsor.162 /// Whether there is a pending sponsor.150 fn has_collection_pending_sponsor(&self) -> Result<bool> {163 fn has_collection_pending_sponsor(&self) -> Result<bool> {151 Ok(matches!(164 Ok(matches!(152 self.collection.sponsorship,165 self.collection.sponsorship,158 ///171 ///159 /// @dev After setting the sponsor for the collection, it must be confirmed with this function.172 /// @dev After setting the sponsor for the collection, it must be confirmed with this function.160 fn confirm_collection_sponsorship(&mut self, caller: caller) -> Result<void> {173 fn confirm_collection_sponsorship(&mut self, caller: caller) -> Result<void> {174 self.consume_store_writes(1)?;175161 let caller = T::CrossAccountId::from_eth(caller);176 let caller = T::CrossAccountId::from_eth(caller);162 if !self177 if !self163 .confirm_sponsorship(caller.as_sub())178 .confirm_sponsorship(caller.as_sub())170185171 /// Remove collection sponsor.186 /// Remove collection sponsor.172 fn remove_collection_sponsor(&mut self, caller: caller) -> Result<void> {187 fn remove_collection_sponsor(&mut self, caller: caller) -> Result<void> {188 self.consume_store_reads_and_writes(1, 1)?;173 check_is_owner_or_admin(caller, self)?;189 check_is_owner_or_admin(caller, self)?;174 self.remove_sponsor().map_err(dispatch_to_evm::<T>)?;190 self.remove_sponsor().map_err(dispatch_to_evm::<T>)?;175 save(self)191 save(self)206 /// @param value Value of the limit.222 /// @param value Value of the limit.207 #[solidity(rename_selector = "setCollectionLimit")]223 #[solidity(rename_selector = "setCollectionLimit")]208 fn set_int_limit(&mut self, caller: caller, limit: string, value: uint32) -> Result<void> {224 fn set_int_limit(&mut self, caller: caller, limit: string, value: uint32) -> Result<void> {225 self.consume_store_reads_and_writes(1, 1)?;226209 check_is_owner_or_admin(caller, self)?;227 check_is_owner_or_admin(caller, self)?;210 let mut limits = self.limits.clone();228 let mut limits = self.limits.clone();211229249 /// @param value Value of the limit.267 /// @param value Value of the limit.250 #[solidity(rename_selector = "setCollectionLimit")]268 #[solidity(rename_selector = "setCollectionLimit")]251 fn set_bool_limit(&mut self, caller: caller, limit: string, value: bool) -> Result<void> {269 fn set_bool_limit(&mut self, caller: caller, limit: string, value: bool) -> Result<void> {270 self.consume_store_reads_and_writes(1, 1)?;271252 check_is_owner_or_admin(caller, self)?;272 check_is_owner_or_admin(caller, self)?;253 let mut limits = self.limits.clone();273 let mut limits = self.limits.clone();254274275 }295 }276296277 /// Get contract address.297 /// Get contract address.278 fn contract_address(&self, _caller: caller) -> Result<address> {298 fn contract_address(&self) -> Result<address> {279 Ok(crate::eth::collection_id_to_address(self.id))299 Ok(crate::eth::collection_id_to_address(self.id))280 }300 }281301286 caller: caller,306 caller: caller,287 new_admin: uint256,307 new_admin: uint256,288 ) -> Result<void> {308 ) -> Result<void> {309 self.consume_store_writes(2)?;310289 let caller = T::CrossAccountId::from_eth(caller);311 let caller = T::CrossAccountId::from_eth(caller);290 let new_admin = convert_uint256_to_cross_account::<T>(new_admin);312 let new_admin = convert_uint256_to_cross_account::<T>(new_admin);291 <Pallet<T>>::toggle_admin(self, &caller, &new_admin, true).map_err(dispatch_to_evm::<T>)?;313 <Pallet<T>>::toggle_admin(self, &caller, &new_admin, true).map_err(dispatch_to_evm::<T>)?;299 caller: caller,321 caller: caller,300 admin: uint256,322 admin: uint256,301 ) -> Result<void> {323 ) -> Result<void> {324 self.consume_store_writes(2)?;325302 let caller = T::CrossAccountId::from_eth(caller);326 let caller = T::CrossAccountId::from_eth(caller);303 let admin = convert_uint256_to_cross_account::<T>(admin);327 let admin = convert_uint256_to_cross_account::<T>(admin);304 <Pallet<T>>::toggle_admin(self, &caller, &admin, false).map_err(dispatch_to_evm::<T>)?;328 <Pallet<T>>::toggle_admin(self, &caller, &admin, false).map_err(dispatch_to_evm::<T>)?;308 /// Add collection admin.332 /// Add collection admin.309 /// @param newAdmin Address of the added administrator.333 /// @param newAdmin Address of the added administrator.310 fn add_collection_admin(&mut self, caller: caller, new_admin: address) -> Result<void> {334 fn add_collection_admin(&mut self, caller: caller, new_admin: address) -> Result<void> {335 self.consume_store_writes(2)?;336311 let caller = T::CrossAccountId::from_eth(caller);337 let caller = T::CrossAccountId::from_eth(caller);312 let new_admin = T::CrossAccountId::from_eth(new_admin);338 let new_admin = T::CrossAccountId::from_eth(new_admin);313 <Pallet<T>>::toggle_admin(self, &caller, &new_admin, true).map_err(dispatch_to_evm::<T>)?;339 <Pallet<T>>::toggle_admin(self, &caller, &new_admin, true).map_err(dispatch_to_evm::<T>)?;318 ///344 ///319 /// @param admin Address of the removed administrator.345 /// @param admin Address of the removed administrator.320 fn remove_collection_admin(&mut self, caller: caller, admin: address) -> Result<void> {346 fn remove_collection_admin(&mut self, caller: caller, admin: address) -> Result<void> {347 self.consume_store_writes(2)?;348321 let caller = T::CrossAccountId::from_eth(caller);349 let caller = T::CrossAccountId::from_eth(caller);322 let admin = T::CrossAccountId::from_eth(admin);350 let admin = T::CrossAccountId::from_eth(admin);323 <Pallet<T>>::toggle_admin(self, &caller, &admin, false).map_err(dispatch_to_evm::<T>)?;351 <Pallet<T>>::toggle_admin(self, &caller, &admin, false).map_err(dispatch_to_evm::<T>)?;329 /// @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'357 /// @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'330 #[solidity(rename_selector = "setCollectionNesting")]358 #[solidity(rename_selector = "setCollectionNesting")]331 fn set_nesting_bool(&mut self, caller: caller, enable: bool) -> Result<void> {359 fn set_nesting_bool(&mut self, caller: caller, enable: bool) -> Result<void> {360 self.consume_store_reads_and_writes(1, 1)?;361332 check_is_owner_or_admin(caller, self)?;362 check_is_owner_or_admin(caller, self)?;333363334 let mut permissions = self.collection.permissions.clone();364 let mut permissions = self.collection.permissions.clone();358 enable: bool,388 enable: bool,359 collections: Vec<address>,389 collections: Vec<address>,360 ) -> Result<void> {390 ) -> Result<void> {391 self.consume_store_reads_and_writes(1, 1)?;392361 if collections.is_empty() {393 if collections.is_empty() {362 return Err("no addresses provided".into());394 return Err("no addresses provided".into());363 }395 }401 /// 0 for Normal433 /// 0 for Normal402 /// 1 for AllowList434 /// 1 for AllowList403 fn set_collection_access(&mut self, caller: caller, mode: uint8) -> Result<void> {435 fn set_collection_access(&mut self, caller: caller, mode: uint8) -> Result<void> {436 self.consume_store_reads_and_writes(1, 1)?;437404 check_is_owner_or_admin(caller, self)?;438 check_is_owner_or_admin(caller, self)?;405 let permissions = CollectionPermissions {439 let permissions = CollectionPermissions {406 access: Some(match mode {440 access: Some(match mode {420 save(self)454 save(self)421 }455 }422456457 /// Checks that user allowed to operate with collection.458 ///459 /// @param user User address to check.460 fn allowed(&self, user: address) -> Result<bool> {461 Ok(Pallet::<T>::allowed(462 self.id,463 T::CrossAccountId::from_eth(user),464 ))465 }466423 /// Add the user to the allowed list.467 /// Add the user to the allowed list.424 ///468 ///425 /// @param user Address of a trusted user.469 /// @param user Address of a trusted user.426 fn add_to_collection_allow_list(&mut self, caller: caller, user: address) -> Result<void> {470 fn add_to_collection_allow_list(&mut self, caller: caller, user: address) -> Result<void> {471 self.consume_store_writes(1)?;472427 let caller = T::CrossAccountId::from_eth(caller);473 let caller = T::CrossAccountId::from_eth(caller);428 let user = T::CrossAccountId::from_eth(user);474 let user = T::CrossAccountId::from_eth(user);429 <Pallet<T>>::toggle_allowlist(self, &caller, &user, true).map_err(dispatch_to_evm::<T>)?;475 <Pallet<T>>::toggle_allowlist(self, &caller, &user, true).map_err(dispatch_to_evm::<T>)?;430 Ok(())476 Ok(())431 }477 }432478479 /// Add substrate user to allowed list.480 ///481 /// @param user User substrate address.482 fn add_to_collection_allow_list_substrate(483 &mut self,484 caller: caller,485 user: uint256,486 ) -> Result<void> {487 self.consume_store_writes(1)?;488489 let caller = T::CrossAccountId::from_eth(caller);490 let user = convert_uint256_to_cross_account::<T>(user);491 Pallet::<T>::toggle_allowlist(self, &caller, &user, true).map_err(dispatch_to_evm::<T>)?;492 Ok(())493 }494433 /// Remove the user from the allowed list.495 /// Remove the user from the allowed list.434 ///496 ///435 /// @param user Address of a removed user.497 /// @param user Address of a removed user.436 fn remove_from_collection_allow_list(&mut self, caller: caller, user: address) -> Result<void> {498 fn remove_from_collection_allow_list(&mut self, caller: caller, user: address) -> Result<void> {499 self.consume_store_writes(1)?;500437 let caller = T::CrossAccountId::from_eth(caller);501 let caller = T::CrossAccountId::from_eth(caller);438 let user = T::CrossAccountId::from_eth(user);502 let user = T::CrossAccountId::from_eth(user);439 <Pallet<T>>::toggle_allowlist(self, &caller, &user, false).map_err(dispatch_to_evm::<T>)?;503 <Pallet<T>>::toggle_allowlist(self, &caller, &user, false).map_err(dispatch_to_evm::<T>)?;440 Ok(())504 Ok(())441 }505 }442506507 /// Remove substrate user from allowed list.508 ///509 /// @param user User substrate address.510 fn remove_from_collection_allow_list_substrate(511 &mut self,512 caller: caller,513 user: uint256,514 ) -> Result<void> {515 self.consume_store_writes(1)?;516517 let caller = T::CrossAccountId::from_eth(caller);518 let user = convert_uint256_to_cross_account::<T>(user);519 Pallet::<T>::toggle_allowlist(self, &caller, &user, false).map_err(dispatch_to_evm::<T>)?;520 Ok(())521 }522443 /// Switch permission for minting.523 /// Switch permission for minting.444 ///524 ///445 /// @param mode Enable if "true".525 /// @param mode Enable if "true".446 fn set_collection_mint_mode(&mut self, caller: caller, mode: bool) -> Result<void> {526 fn set_collection_mint_mode(&mut self, caller: caller, mode: bool) -> Result<void> {527 self.consume_store_reads_and_writes(1, 1)?;528447 check_is_owner_or_admin(caller, self)?;529 check_is_owner_or_admin(caller, self)?;448 let permissions = CollectionPermissions {530 let permissions = CollectionPermissions {449 mint_mode: Some(mode),531 mint_mode: Some(mode),481 /// Returns collection type563 /// Returns collection type482 ///564 ///483 /// @return `Fungible` or `NFT` or `ReFungible`565 /// @return `Fungible` or `NFT` or `ReFungible`484 fn unique_collection_type(&mut self) -> Result<string> {566 fn unique_collection_type(&self) -> Result<string> {485 let mode = match self.collection.mode {567 let mode = match self.collection.mode {486 CollectionMode::Fungible(_) => "Fungible",568 CollectionMode::Fungible(_) => "Fungible",487 CollectionMode::NFT => "NFT",569 CollectionMode::NFT => "NFT",490 Ok(mode.into())572 Ok(mode.into())491 }573 }492574575 /// Get collection owner.576 ///577 /// @return Tuble with sponsor address and his substrate mirror.578 /// If address is canonical then substrate mirror is zero and vice versa.579 fn collection_owner(&self) -> Result<(address, uint256)> {580 Ok(convert_cross_account_to_tuple::<T>(581 &T::CrossAccountId::from_sub(self.owner.clone()),582 ))583 }584493 /// Changes collection owner to another account585 /// Changes collection owner to another account494 ///586 ///495 /// @dev Owner can be changed only by current owner587 /// @dev Owner can be changed only by current owner496 /// @param newOwner new owner account588 /// @param newOwner new owner account497 fn set_owner(&mut self, caller: caller, new_owner: address) -> Result<void> {589 fn set_owner(&mut self, caller: caller, new_owner: address) -> Result<void> {590 self.consume_store_writes(1)?;591498 let caller = T::CrossAccountId::from_eth(caller);592 let caller = T::CrossAccountId::from_eth(caller);499 let new_owner = T::CrossAccountId::from_eth(new_owner);593 let new_owner = T::CrossAccountId::from_eth(new_owner);500 self.set_owner_internal(caller, new_owner)594 self.set_owner_internal(caller, new_owner)506 /// @dev Owner can be changed only by current owner600 /// @dev Owner can be changed only by current owner507 /// @param newOwner new owner substrate account601 /// @param newOwner new owner substrate account508 fn set_owner_substrate(&mut self, caller: caller, new_owner: uint256) -> Result<void> {602 fn set_owner_substrate(&mut self, caller: caller, new_owner: uint256) -> Result<void> {603 self.consume_store_writes(1)?;604509 let caller = T::CrossAccountId::from_eth(caller);605 let caller = T::CrossAccountId::from_eth(caller);510 let new_owner = convert_uint256_to_cross_account::<T>(new_owner);606 let new_owner = convert_uint256_to_cross_account::<T>(new_owner);511 self.set_owner_internal(caller, new_owner)607 self.set_owner_internal(caller, new_owner)512 .map_err(dispatch_to_evm::<T>)608 .map_err(dispatch_to_evm::<T>)513 }609 }610611 // TODO: need implement AbiWriter for &Vec<T>612 // fn collection_admins(&self) -> Result<Vec<(address, uint256)>> {613 // let result = pallet_common::IsAdmin::<T>::iter_prefix((self.id,))614 // .map(|(admin, _)| pallet_common::eth::convert_cross_account_to_tuple::<T>(&admin))615 // .collect();616 // Ok(result)617 // }514}618}515619620/// ### Note621/// Do not forget to add: `self.consume_store_reads(1)?;`516fn check_is_owner_or_admin<T: Config>(622fn check_is_owner_or_admin<T: Config>(517 caller: caller,623 caller: caller,518 collection: &CollectionHandle<T>,624 collection: &CollectionHandle<T>,524 Ok(caller)630 Ok(caller)525}631}526632633/// ### Note634/// Do not forget to add: `self.consume_store_writes(1)?;`527fn save<T: Config>(collection: &CollectionHandle<T>) -> Result<void> {635fn save<T: Config>(collection: &CollectionHandle<T>) -> Result<void> {528 // TODO possibly delete for the lack of transaction529 collection.consume_store_writes(1)?;530 collection636 collection531 .check_is_internal()637 .check_is_internal()532 .map_err(dispatch_to_evm::<T>)?;638 .map_err(dispatch_to_evm::<T>)?;pallets/common/src/eth.rsdiffbeforeafterboth161617//! The module contains a number of functions for converting and checking ethereum identifiers.17//! The module contains a number of functions for converting and checking ethereum identifiers.181819use evm_coder::types::uint256;19use evm_coder::types::{uint256, address};20pub use pallet_evm::account::{Config, CrossAccountId};20pub use pallet_evm::account::{Config, CrossAccountId};21use sp_core::H160;21use sp_core::H160;22use up_data_structs::CollectionId;22use up_data_structs::CollectionId;70 T::CrossAccountId::from_sub(account_id)70 T::CrossAccountId::from_sub(account_id)71}71}7273/// Convert `CrossAccountId` to `(address, uint256)`.74pub fn convert_cross_account_to_tuple<T: Config>(75 cross_account_id: &T::CrossAccountId,76) -> (address, uint256)77where78 T::AccountId: AsRef<[u8; 32]>,79{80 if cross_account_id.is_canonical_substrate() {81 let sub = convert_cross_account_to_uint256::<T>(cross_account_id);82 (Default::default(), sub)83 } else {84 let eth = *cross_account_id.as_eth();85 (eth, Default::default())86 }87}7288pallets/common/src/lib.rsdiffbeforeafterboth112 RmrkBoundedTheme,112 RmrkBoundedTheme,113 RmrkNftChild,113 RmrkNftChild,114 CollectionPermissions,114 CollectionPermissions,115 SchemaVersion,116};115};117116118pub use pallet::*;117pub use pallet::*;202 ))201 ))203 }202 }203204 /// Consume gas for reading and writing.205 pub fn consume_store_reads_and_writes(206 &self,207 reads: u64,208 writes: u64,209 ) -> evm_coder::execution::Result<()> {210 let weight = <T as frame_system::Config>::DbWeight::get();211 let reads = weight.read.saturating_mul(reads);212 let writes = weight.read.saturating_mul(writes);213 self.recorder214 .consume_gas(T::GasWeightMapping::weight_to_gas(215 reads.saturating_add(writes),216 ))217 }204218205 /// Save collection to storage.219 /// Save collection to storage.206 pub fn save(&self) -> DispatchResult {220 pub fn save(&self) -> DispatchResult {310 }324 }311325312 /// Changes collection owner to another account326 /// Changes collection owner to another account327 /// #### Store read/writes328 /// 1 writes313 fn set_owner_internal(329 fn set_owner_internal(314 &mut self,330 &mut self,315 caller: T::CrossAccountId,331 caller: T::CrossAccountId,1292 }1308 }129313091294 /// Toggle `user` participation in the `collection`'s allow list.1310 /// Toggle `user` participation in the `collection`'s allow list.1311 /// #### Store read/writes1312 /// 1 writes1295 pub fn toggle_allowlist(1313 pub fn toggle_allowlist(1296 collection: &CollectionHandle<T>,1314 collection: &CollectionHandle<T>,1297 sender: &T::CrossAccountId,1315 sender: &T::CrossAccountId,1312 }1330 }131313311314 /// Toggle `user` participation in the `collection`'s admin list.1332 /// Toggle `user` participation in the `collection`'s admin list.1333 /// #### Store read/writes1334 /// 2 writes1315 pub fn toggle_admin(1335 pub fn toggle_admin(1316 collection: &CollectionHandle<T>,1336 collection: &CollectionHandle<T>,1317 sender: &T::CrossAccountId,1337 sender: &T::CrossAccountId,pallets/configuration/Cargo.tomldiffbeforeafterboth16sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }16sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }17sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }17sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }18sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }18sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }19fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }19fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }20smallvec = "1.6.1"20smallvec = "1.6.1"212122[features]22[features]pallets/evm-coder-substrate/Cargo.tomldiffbeforeafterboth12sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }12sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }13ethereum = { version = "0.12.0", default-features = false }13ethereum = { version = "0.12.0", default-features = false }14evm-coder = { default-features = false, path = "../../crates/evm-coder" }14evm-coder = { default-features = false, path = "../../crates/evm-coder" }15pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }15pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }16pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }16pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }17frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }17frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }18frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }18frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }19frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }19frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }pallets/evm-contract-helpers/Cargo.tomldiffbeforeafterboth19sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }19sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }202021# Unique21# Unique22pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }22pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }23fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }23fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }24up-sponsorship = { version = "0.1.0", default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.27" }24up-sponsorship = { version = "0.1.0", default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.27" }252526# Locals26# Locals27evm-coder = { default-features = false, path = '../../crates/evm-coder' }27evm-coder = { default-features = false, path = '../../crates/evm-coder' }28pallet-common = { default-features = false, path = '../../pallets/common' }28pallet-common = { default-features = false, path = '../../pallets/common' }29pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }29pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }30pallet-evm-transaction-payment = { default-features = false, path = '../../pallets/evm-transaction-payment' }30up-data-structs = { default-features = false, path = '../../primitives/data-structs', features = [31up-data-structs = { default-features = false, path = '../../primitives/data-structs', features = [31 'serde1',32 'serde1',32] }33] }pallets/evm-contract-helpers/src/eth.rsdiffbeforeafterboth20use evm_coder::{20use evm_coder::{21 abi::AbiWriter, execution::Result, generate_stubgen, solidity_interface, types::*, ToLog,21 abi::AbiWriter, execution::Result, generate_stubgen, solidity_interface, types::*, ToLog,22};22};23use pallet_evm::{24 ExitRevert, OnCreate, OnMethodCall, PrecompileResult, PrecompileFailure, PrecompileHandle,25 account::CrossAccountId,26};23use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder, dispatch_to_evm};27use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder, dispatch_to_evm};24use pallet_evm::{28use pallet_evm_transaction_payment::CallContext;25 ExitRevert, OnCreate, OnMethodCall, PrecompileResult, PrecompileFailure, PrecompileHandle,26 account::CrossAccountId,27};28use sp_core::H160;29use sp_core::{H160, U256};29use up_data_structs::SponsorshipState;30use up_data_structs::SponsorshipState;30use crate::{31use crate::{31 AllowlistEnabled, Config, Owner, Pallet, SponsorBasket, SponsoringRateLimit, SponsoringModeT,32 AllowlistEnabled, Config, Owner, Pallet, SponsorBasket, SponsoringFeeLimit,32 Sponsoring,33 SponsoringRateLimit, SponsoringModeT, Sponsoring,33};34};34use frame_support::traits::Get;35use frame_support::traits::Get;171 fn get_sponsor(&self, contract_address: address) -> Result<(address, uint256)> {172 fn get_sponsor(&self, contract_address: address) -> Result<(address, uint256)> {172 let sponsor =173 let sponsor =173 Pallet::<T>::get_sponsor(contract_address).ok_or("Contract has no sponsor")?;174 Pallet::<T>::get_sponsor(contract_address).ok_or("Contract has no sponsor")?;174 let result: (address, uint256) = if sponsor.is_canonical_substrate() {175 let sponsor = pallet_common::eth::convert_cross_account_to_uint256::<T>(&sponsor);175 Ok(pallet_common::eth::convert_cross_account_to_tuple::<T>(176 (Default::default(), sponsor)176 &sponsor,177 } else {177 ))178 let sponsor = *sponsor.as_eth();179 (sponsor, Default::default())180 };181 Ok(result)182 }178 }183179184 /// Check tat contract has confirmed sponsor.180 /// Check tat contract has confirmed sponsor.222 }218 }223219224 /// Get current contract sponsoring rate limit220 /// Get current contract sponsoring rate limit225 /// @param contractAddress Contract to get sponsoring mode of221 /// @param contractAddress Contract to get sponsoring rate limit of226 /// @return uint32 Amount of blocks between two sponsored transactions222 /// @return uint32 Amount of blocks between two sponsored transactions227 fn get_sponsoring_rate_limit(&self, contract_address: address) -> Result<uint32> {223 fn get_sponsoring_rate_limit(&self, contract_address: address) -> Result<uint32> {224 self.recorder().consume_sload()?;225228 Ok(<SponsoringRateLimit<T>>::get(contract_address)226 Ok(<SponsoringRateLimit<T>>::get(contract_address)229 .try_into()227 .try_into()250 Ok(())248 Ok(())251 }249 }250251 /// Set contract sponsoring fee limit252 /// @dev Sponsoring fee limit - is maximum fee that could be spent by253 /// single transaction254 /// @param contractAddress Contract to change sponsoring fee limit of255 /// @param feeLimit Fee limit256 /// @dev Only contract owner can change this setting257 fn set_sponsoring_fee_limit(258 &mut self,259 caller: caller,260 contract_address: address,261 fee_limit: uint256,262 ) -> Result<void> {263 self.recorder().consume_sload()?;264 self.recorder().consume_sstore()?;265266 <Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;267 <Pallet<T>>::set_sponsoring_fee_limit(contract_address, fee_limit.into())268 .map_err(dispatch_to_evm::<T>)?;269 Ok(())270 }271272 /// Get current contract sponsoring fee limit273 /// @param contractAddress Contract to get sponsoring fee limit of274 /// @return uint256 Maximum amount of fee that could be spent by single275 /// transaction276 fn get_sponsoring_fee_limit(&self, contract_address: address) -> Result<uint256> {277 self.recorder().consume_sload()?;278279 Ok(get_sponsoring_fee_limit::<T>(contract_address))280 }252281253 /// Is specified user present in contract allow list282 /// Is specified user present in contract allow list254 /// @dev Contract owner always implicitly included283 /// @dev Contract owner always implicitly included363392364/// Bridge to pallet-sponsoring393/// Bridge to pallet-sponsoring365pub struct HelpersContractSponsoring<T: Config>(PhantomData<*const T>);394pub struct HelpersContractSponsoring<T: Config>(PhantomData<*const T>);366impl<T: Config> SponsorshipHandler<T::CrossAccountId, (H160, Vec<u8>)>395impl<T: Config> SponsorshipHandler<T::CrossAccountId, CallContext>367 for HelpersContractSponsoring<T>396 for HelpersContractSponsoring<T>368{397{369 fn get_sponsor(who: &T::CrossAccountId, call: &(H160, Vec<u8>)) -> Option<T::CrossAccountId> {398 fn get_sponsor(399 who: &T::CrossAccountId,400 call_context: &CallContext,401 ) -> Option<T::CrossAccountId> {370 let (contract_address, _) = call;402 let contract_address = call_context.contract_address;371 let mode = <Pallet<T>>::sponsoring_mode(*contract_address);403 let mode = <Pallet<T>>::sponsoring_mode(contract_address);372 if mode == SponsoringModeT::Disabled {404 if mode == SponsoringModeT::Disabled {373 return None;405 return None;374 }406 }375407376 let sponsor = match <Pallet<T>>::get_sponsor(*contract_address) {408 let sponsor = match <Pallet<T>>::get_sponsor(contract_address) {377 Some(sponsor) => sponsor,409 Some(sponsor) => sponsor,378 None => return None,410 None => return None,379 };411 };380412381 if mode == SponsoringModeT::Allowlisted413 if mode == SponsoringModeT::Allowlisted382 && !<Pallet<T>>::allowed(*contract_address, *who.as_eth())414 && !<Pallet<T>>::allowed(contract_address, *who.as_eth())383 {415 {384 return None;416 return None;385 }417 }394 }426 }395 }427 }428429 let sponsored_fee_limit = get_sponsoring_fee_limit::<T>(contract_address);430431 if call_context.max_fee > sponsored_fee_limit {432 return None;433 }396434397 <SponsorBasket<T>>::insert(contract_address, who.as_eth(), block_number);435 <SponsorBasket<T>>::insert(contract_address, who.as_eth(), block_number);398436399 Some(sponsor)437 Some(sponsor)400 }438 }401}439}440441fn get_sponsoring_fee_limit<T: Config>(contract_address: address) -> uint256 {442 <SponsoringFeeLimit<T>>::get(contract_address)443 .get(&0xffffffff)444 .cloned()445 .unwrap_or(U256::MAX)446}402447403generate_stubgen!(contract_helpers_impl, ContractHelpersCall<()>, true);448generate_stubgen!(contract_helpers_impl, ContractHelpersCall<()>, true);404generate_stubgen!(contract_helpers_iface, ContractHelpersCall<()>, false);449generate_stubgen!(contract_helpers_iface, ContractHelpersCall<()>, false);pallets/evm-contract-helpers/src/lib.rsdiffbeforeafterboth22pub use pallet::*;22pub use pallet::*;23pub use eth::*;23pub use eth::*;24use scale_info::TypeInfo;24use scale_info::TypeInfo;25use frame_support::storage::bounded_btree_map::BoundedBTreeMap;25pub mod eth;26pub mod eth;2728/// Maximum number of methods per contract that could have fee limit29pub const MAX_FEE_LIMITED_METHODS: u32 = 5;263027#[frame_support::pallet]31#[frame_support::pallet]28pub mod pallet {32pub mod pallet {29 pub use super::*;33 pub use super::*;30 use crate::eth::ContractHelpersEvents;34 use crate::eth::ContractHelpersEvents;31 use frame_support::pallet_prelude::*;35 use frame_support::pallet_prelude::*;32 use pallet_evm_coder_substrate::DispatchResult;36 use pallet_evm_coder_substrate::DispatchResult;33 use sp_core::H160;37 use sp_core::{H160, U256};34 use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};38 use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};35 use up_data_structs::SponsorshipState;39 use up_data_structs::SponsorshipState;36 use evm_coder::ToLog;40 use evm_coder::ToLog;58 /// No pending sponsor for contract.62 /// No pending sponsor for contract.59 NoPendingSponsor,63 NoPendingSponsor,6465 /// Number of methods that sponsored limit is defined for exceeds maximum.66 TooManyMethodsHaveSponsoredLimit,60 }67 }616862 #[pallet::pallet]69 #[pallet::pallet]118 /// * **Key2** - sponsored user address.125 /// * **Key2** - sponsored user address.119 /// * **Value** - last sponsored block number.126 /// * **Value** - last sponsored block number.120 #[pallet::storage]127 #[pallet::storage]121 pub(super) type SponsorBasket<T: Config> = StorageDoubleMap<128 pub(super) type SponsoringFeeLimit<T: Config> = StorageMap<129 Hasher = Twox128,130 Key = H160,131 Value = BoundedBTreeMap<u32, U256, ConstU32<MAX_FEE_LIMITED_METHODS>>,132 QueryKind = ValueQuery,133 >;134135 #[pallet::storage]136 pub(super) type SponsorBasket<T: Config> = StorageDoubleMap<122 Hasher1 = Twox128,137 Hasher1 = Twox128,123 Key1 = H160,138 Key1 = H160,124 Hasher2 = Twox128,139 Hasher2 = Twox128,355 <SponsoringRateLimit<T>>::insert(contract, rate_limit);370 <SponsoringRateLimit<T>>::insert(contract, rate_limit);356 }371 }372373 /// Set maximum for gas limit of transaction374 pub fn set_sponsoring_fee_limit(contract: H160, fee_limit: U256) -> DispatchResult {375 <SponsoringFeeLimit<T>>::try_mutate(contract, |limits_map| {376 limits_map377 .try_insert(0xffffffff, fee_limit)378 .map_err(|_| <Error<T>>::TooManyMethodsHaveSponsoredLimit)379 })?;380 Ok(())381 }357382358 /// Is user added to allowlist, or he is owner of specified contract383 /// Is user added to allowlist, or he is owner of specified contract359 pub fn allowed(contract: H160, user: H160) -> bool {384 pub fn allowed(contract: H160, user: H160) -> bool {pallets/evm-contract-helpers/src/stubs/ContractHelpers.rawdiffbeforeafterbothbinary blob — no preview
pallets/evm-contract-helpers/src/stubs/ContractHelpers.soldiffbeforeafterboth32}32}333334/// @title Magic contract, which allows users to reconfigure other contracts34/// @title Magic contract, which allows users to reconfigure other contracts35/// @dev the ERC-165 identifier for this interface is 0xd77fab7035/// @dev the ERC-165 identifier for this interface is 0x172cb4fb36contract ContractHelpers is Dummy, ERC165, ContractHelpersEvents {36contract ContractHelpers is Dummy, ERC165, ContractHelpersEvents {37 /// Get user, which deployed specified contract37 /// Get user, which deployed specified contract38 /// @dev May return zero address in case if contract is deployed38 /// @dev May return zero address in case if contract is deployed171 }171 }172172173 /// Get current contract sponsoring rate limit173 /// Get current contract sponsoring rate limit174 /// @param contractAddress Contract to get sponsoring mode of174 /// @param contractAddress Contract to get sponsoring rate limit of175 /// @return uint32 Amount of blocks between two sponsored transactions175 /// @return uint32 Amount of blocks between two sponsored transactions176 /// @dev EVM selector for this function is: 0x610cfabd,176 /// @dev EVM selector for this function is: 0x610cfabd,177 /// or in textual repr: getSponsoringRateLimit(address)177 /// or in textual repr: getSponsoringRateLimit(address)203 dummy = 0;203 dummy = 0;204 }204 }205206 /// Set contract sponsoring fee limit207 /// @dev Sponsoring fee limit - is maximum fee that could be spent by208 /// single transaction209 /// @param contractAddress Contract to change sponsoring fee limit of210 /// @param feeLimit Fee limit211 /// @dev Only contract owner can change this setting212 /// @dev EVM selector for this function is: 0x03aed665,213 /// or in textual repr: setSponsoringFeeLimit(address,uint256)214 function setSponsoringFeeLimit(address contractAddress, uint256 feeLimit)215 public216 {217 require(false, stub_error);218 contractAddress;219 feeLimit;220 dummy = 0;221 }222223 /// Get current contract sponsoring fee limit224 /// @param contractAddress Contract to get sponsoring fee limit of225 /// @return uint256 Maximum amount of fee that could be spent by single226 /// transaction227 /// @dev EVM selector for this function is: 0xc3fdc9ee,228 /// or in textual repr: getSponsoringFeeLimit(address)229 function getSponsoringFeeLimit(address contractAddress)230 public231 view232 returns (uint256)233 {234 require(false, stub_error);235 contractAddress;236 dummy;237 return 0;238 }205239206 /// Is specified user present in contract allow list240 /// Is specified user present in contract allow list207 /// @dev Contract owner always implicitly included241 /// @dev Contract owner always implicitly includedpallets/evm-migration/Cargo.tomldiffbeforeafterboth15sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }15sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }16sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }16sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }17sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }17sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }18pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }18pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }19fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }19fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }202021[dependencies.codec]21[dependencies.codec]22default-features = false22default-features = falsepallets/evm-transaction-payment/Cargo.tomldiffbeforeafterboth14sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }14sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }15sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }15sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }16sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }16sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }17pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }17pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }18fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }18fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }19pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }19pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }20up-sponsorship = { version = "0.1.0", default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.27" }20up-sponsorship = { version = "0.1.0", default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.27" }21fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }21fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }222223[dependencies.codec]23[dependencies.codec]24default-features = false24default-features = falsepallets/evm-transaction-payment/src/lib.rsdiffbeforeafterboth22use fp_evm::WithdrawReason;22use fp_evm::WithdrawReason;23use frame_support::traits::IsSubType;23use frame_support::traits::IsSubType;24pub use pallet::*;24pub use pallet::*;25use pallet_evm::{EnsureAddressOrigin, account::CrossAccountId};25use pallet_evm::{account::CrossAccountId, EnsureAddressOrigin};26use sp_core::H160;26use sp_core::{H160, U256};27use sp_runtime::{TransactionOutcome, DispatchError};27use sp_runtime::{TransactionOutcome, DispatchError};28use up_sponsorship::SponsorshipHandler;28use up_sponsorship::SponsorshipHandler;2929333334 use sp_std::vec::Vec;34 use sp_std::vec::Vec;3536 /// Contains call data37 pub struct CallContext {38 /// Contract address39 pub contract_address: H160,40 /// Transaction data41 pub input: Vec<u8>,42 /// Max fee for transaction - gasLimit * gasPrice43 pub max_fee: U256,44 }354536 #[pallet::config]46 #[pallet::config]37 pub trait Config: frame_system::Config + pallet_evm::account::Config {47 pub trait Config: frame_system::Config + pallet_evm::account::Config {38 /// Loosly-coupled handlers for evm call sponsoring48 /// Loosly-coupled handlers for evm call sponsoring39 type EvmSponsorshipHandler: SponsorshipHandler<Self::CrossAccountId, (H160, Vec<u8>)>;49 type EvmSponsorshipHandler: SponsorshipHandler<Self::CrossAccountId, CallContext>;40 }50 }415142 #[pallet::pallet]52 #[pallet::pallet]49impl<T: Config> fp_evm::TransactionValidityHack<T::CrossAccountId> for TransactionValidityHack<T> {59impl<T: Config> fp_evm::TransactionValidityHack<T::CrossAccountId> for TransactionValidityHack<T> {50 fn who_pays_fee(origin: H160, reason: &WithdrawReason) -> Option<T::CrossAccountId> {60 fn who_pays_fee(61 origin: H160,62 max_fee: U256,63 reason: &WithdrawReason,64 ) -> Option<T::CrossAccountId> {51 match reason {65 match reason {52 WithdrawReason::Call { target, input } => {66 WithdrawReason::Call { target, input } => {53 let origin_sub = T::CrossAccountId::from_eth(origin);67 let origin_sub = T::CrossAccountId::from_eth(origin);68 let call_context = CallContext {69 contract_address: *target,70 input: input.clone(),71 max_fee,72 };54 T::EvmSponsorshipHandler::get_sponsor(&origin_sub, &(*target, input.clone()))73 T::EvmSponsorshipHandler::get_sponsor(&origin_sub, &call_context)55 }74 }56 _ => None,75 _ => None,57 }76 }71 source,90 source,72 target,91 target,73 input,92 input,93 gas_limit,94 max_fee_per_gas,74 ..95 ..75 } => {96 } => {76 let _ = T::CallOrigin::ensure_address_origin(97 let _ = T::CallOrigin::ensure_address_origin(79 )100 )80 .ok()?;101 .ok()?;81 let who = T::CrossAccountId::from_sub(who.clone());102 let who = T::CrossAccountId::from_sub(who.clone());103 let max_fee = max_fee_per_gas.saturating_mul((*gas_limit).into());104 let call_context = CallContext {105 contract_address: *target,106 input: input.clone(),107 max_fee,108 };82 // Effects from EvmSponsorshipHandler are applied by pallet_evm::runner109 // Effects from EvmSponsorshipHandler are applied by pallet_evm::runner83 // TODO: Should we implement simulation mode (test, but do not apply effects) in `up-sponsorship`?110 // TODO: Should we implement simulation mode (test, but do not apply effects) in `up-sponsorship`?84 let sponsor = frame_support::storage::with_transaction(|| {111 let sponsor = frame_support::storage::with_transaction(|| {85 TransactionOutcome::Rollback(Ok::<_, DispatchError>(112 TransactionOutcome::Rollback(Ok::<_, DispatchError>(86 T::EvmSponsorshipHandler::get_sponsor(&who, &(*target, input.clone())),113 T::EvmSponsorshipHandler::get_sponsor(&who, &call_context),87 ))114 ))88 })115 })89 // FIXME: it may fail with DispatchError in case of depth limit116 // FIXME: it may fail with DispatchError in case of depth limitpallets/fungible/Cargo.tomldiffbeforeafterboth23pallet-evm-coder-substrate = { default-features = false, path = '../evm-coder-substrate' }23pallet-evm-coder-substrate = { default-features = false, path = '../evm-coder-substrate' }24ethereum = { version = "0.12.0", default-features = false }24ethereum = { version = "0.12.0", default-features = false }25frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }25frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }26pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }26pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }27scale-info = { version = "2.0.1", default-features = false, features = [27scale-info = { version = "2.0.1", default-features = false, features = [28 "derive",28 "derive",29] }29] }pallets/fungible/src/stubs/UniqueFungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth22}22}232324/// @title A contract that allows you to work with collections.24/// @title A contract that allows you to work with collections.25/// @dev the ERC-165 identifier for this interface is 0xe54be64025/// @dev the ERC-165 identifier for this interface is 0x9f70d4e026contract Collection is Dummy, ERC165 {26contract Collection is Dummy, ERC165 {27 /// Set collection property.27 /// Set collection property.28 ///28 ///255 dummy = 0;255 dummy = 0;256 }256 }257258 /// Checks that user allowed to operate with collection.259 ///260 /// @param user User address to check.261 /// @dev EVM selector for this function is: 0xd63a8e11,262 /// or in textual repr: allowed(address)263 function allowed(address user) public view returns (bool) {264 require(false, stub_error);265 user;266 dummy;267 return false;268 }257269258 /// Add the user to the allowed list.270 /// Add the user to the allowed list.259 ///271 ///266 dummy = 0;278 dummy = 0;267 }279 }280281 /// Add substrate user to allowed list.282 ///283 /// @param user User substrate address.284 /// @dev EVM selector for this function is: 0xd06ad267,285 /// or in textual repr: addToCollectionAllowListSubstrate(uint256)286 function addToCollectionAllowListSubstrate(uint256 user) public {287 require(false, stub_error);288 user;289 dummy = 0;290 }268291269 /// Remove the user from the allowed list.292 /// Remove the user from the allowed list.270 ///293 ///277 dummy = 0;300 dummy = 0;278 }301 }302303 /// Remove substrate user from allowed list.304 ///305 /// @param user User substrate address.306 /// @dev EVM selector for this function is: 0xa31913ed,307 /// or in textual repr: removeFromCollectionAllowListSubstrate(uint256)308 function removeFromCollectionAllowListSubstrate(uint256 user) public {309 require(false, stub_error);310 user;311 dummy = 0;312 }279313280 /// Switch permission for minting.314 /// Switch permission for minting.281 ///315 ///325 return "";359 return "";326 }360 }361362 /// Get collection owner.363 ///364 /// @return Tuble with sponsor address and his substrate mirror.365 /// If address is canonical then substrate mirror is zero and vice versa.366 /// @dev EVM selector for this function is: 0xdf727d3b,367 /// or in textual repr: collectionOwner()368 function collectionOwner() public view returns (Tuple6 memory) {369 require(false, stub_error);370 dummy;371 return Tuple6(0x0000000000000000000000000000000000000000, 0);372 }327373328 /// Changes collection owner to another account374 /// Changes collection owner to another account329 ///375 ///pallets/nonfungible/Cargo.tomldiffbeforeafterboth16sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }16sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }17sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }17sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }18sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }18sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }19pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }19pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }20pallet-common = { default-features = false, path = '../common' }20pallet-common = { default-features = false, path = '../common' }21pallet-structure = { default-features = false, path = '../structure' }21pallet-structure = { default-features = false, path = '../structure' }22up-data-structs = { default-features = false, path = '../../primitives/data-structs' }22up-data-structs = { default-features = false, path = '../../primitives/data-structs' }pallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterbothbinary blob — no preview
pallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth99}99}100100101/// @title A contract that allows you to work with collections.101/// @title A contract that allows you to work with collections.102/// @dev the ERC-165 identifier for this interface is 0xe54be640102/// @dev the ERC-165 identifier for this interface is 0x9f70d4e0103contract Collection is Dummy, ERC165 {103contract Collection is Dummy, ERC165 {104 /// Set collection property.104 /// Set collection property.105 ///105 ///332 dummy = 0;332 dummy = 0;333 }333 }334335 /// Checks that user allowed to operate with collection.336 ///337 /// @param user User address to check.338 /// @dev EVM selector for this function is: 0xd63a8e11,339 /// or in textual repr: allowed(address)340 function allowed(address user) public view returns (bool) {341 require(false, stub_error);342 user;343 dummy;344 return false;345 }334346335 /// Add the user to the allowed list.347 /// Add the user to the allowed list.336 ///348 ///343 dummy = 0;355 dummy = 0;344 }356 }357358 /// Add substrate user to allowed list.359 ///360 /// @param user User substrate address.361 /// @dev EVM selector for this function is: 0xd06ad267,362 /// or in textual repr: addToCollectionAllowListSubstrate(uint256)363 function addToCollectionAllowListSubstrate(uint256 user) public {364 require(false, stub_error);365 user;366 dummy = 0;367 }345368346 /// Remove the user from the allowed list.369 /// Remove the user from the allowed list.347 ///370 ///354 dummy = 0;377 dummy = 0;355 }378 }379380 /// Remove substrate user from allowed list.381 ///382 /// @param user User substrate address.383 /// @dev EVM selector for this function is: 0xa31913ed,384 /// or in textual repr: removeFromCollectionAllowListSubstrate(uint256)385 function removeFromCollectionAllowListSubstrate(uint256 user) public {386 require(false, stub_error);387 user;388 dummy = 0;389 }356390357 /// Switch permission for minting.391 /// Switch permission for minting.358 ///392 ///402 return "";436 return "";403 }437 }438439 /// Get collection owner.440 ///441 /// @return Tuble with sponsor address and his substrate mirror.442 /// If address is canonical then substrate mirror is zero and vice versa.443 /// @dev EVM selector for this function is: 0xdf727d3b,444 /// or in textual repr: collectionOwner()445 function collectionOwner() public view returns (Tuple17 memory) {446 require(false, stub_error);447 dummy;448 return Tuple17(0x0000000000000000000000000000000000000000, 0);449 }404450405 /// Changes collection owner to another account451 /// Changes collection owner to another account406 ///452 ///pallets/proxy-rmrk-core/Cargo.tomldiffbeforeafterboth20pallet-nonfungible = { default-features = false, path = "../../pallets/nonfungible" }20pallet-nonfungible = { default-features = false, path = "../../pallets/nonfungible" }21pallet-structure = { default-features = false, path = "../../pallets/structure" }21pallet-structure = { default-features = false, path = "../../pallets/structure" }22up-data-structs = { default-features = false, path = '../../primitives/data-structs' }22up-data-structs = { default-features = false, path = '../../primitives/data-structs' }23pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }23pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }24frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }24frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }25rmrk-traits = { default-features = false, path = "../../primitives/rmrk-traits" }25rmrk-traits = { default-features = false, path = "../../primitives/rmrk-traits" }26scale-info = { version = "2.0.1", default-features = false, features = [26scale-info = { version = "2.0.1", default-features = false, features = [pallets/proxy-rmrk-equip/Cargo.tomldiffbeforeafterboth19pallet-common = { default-features = false, path = '../common' }19pallet-common = { default-features = false, path = '../common' }20pallet-nonfungible = { default-features = false, path = "../../pallets/nonfungible" }20pallet-nonfungible = { default-features = false, path = "../../pallets/nonfungible" }21up-data-structs = { default-features = false, path = '../../primitives/data-structs' }21up-data-structs = { default-features = false, path = '../../primitives/data-structs' }22pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }22pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }23frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }23frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }24rmrk-traits = { default-features = false, path = "../../primitives/rmrk-traits" }24rmrk-traits = { default-features = false, path = "../../primitives/rmrk-traits" }25scale-info = { version = "2.0.1", default-features = false, features = [25scale-info = { version = "2.0.1", default-features = false, features = [pallets/refungible/Cargo.tomldiffbeforeafterboth16sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }16sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }17sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }17sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }18sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }18sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }19pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }19pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }20evm-coder = { default-features = false, path = '../../crates/evm-coder' }20evm-coder = { default-features = false, path = '../../crates/evm-coder' }21pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }21pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }22pallet-common = { default-features = false, path = '../common' }22pallet-common = { default-features = false, path = '../common' }pallets/refungible/src/stubs/UniqueRefungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth99}99}100100101/// @title A contract that allows you to work with collections.101/// @title A contract that allows you to work with collections.102/// @dev the ERC-165 identifier for this interface is 0xe54be640102/// @dev the ERC-165 identifier for this interface is 0x9f70d4e0103contract Collection is Dummy, ERC165 {103contract Collection is Dummy, ERC165 {104 /// Set collection property.104 /// Set collection property.105 ///105 ///332 dummy = 0;332 dummy = 0;333 }333 }334335 /// Checks that user allowed to operate with collection.336 ///337 /// @param user User address to check.338 /// @dev EVM selector for this function is: 0xd63a8e11,339 /// or in textual repr: allowed(address)340 function allowed(address user) public view returns (bool) {341 require(false, stub_error);342 user;343 dummy;344 return false;345 }334346335 /// Add the user to the allowed list.347 /// Add the user to the allowed list.336 ///348 ///343 dummy = 0;355 dummy = 0;344 }356 }357358 /// Add substrate user to allowed list.359 ///360 /// @param user User substrate address.361 /// @dev EVM selector for this function is: 0xd06ad267,362 /// or in textual repr: addToCollectionAllowListSubstrate(uint256)363 function addToCollectionAllowListSubstrate(uint256 user) public {364 require(false, stub_error);365 user;366 dummy = 0;367 }345368346 /// Remove the user from the allowed list.369 /// Remove the user from the allowed list.347 ///370 ///354 dummy = 0;377 dummy = 0;355 }378 }379380 /// Remove substrate user from allowed list.381 ///382 /// @param user User substrate address.383 /// @dev EVM selector for this function is: 0xa31913ed,384 /// or in textual repr: removeFromCollectionAllowListSubstrate(uint256)385 function removeFromCollectionAllowListSubstrate(uint256 user) public {386 require(false, stub_error);387 user;388 dummy = 0;389 }356390357 /// Switch permission for minting.391 /// Switch permission for minting.358 ///392 ///402 return "";436 return "";403 }437 }438439 /// Get collection owner.440 ///441 /// @return Tuble with sponsor address and his substrate mirror.442 /// If address is canonical then substrate mirror is zero and vice versa.443 /// @dev EVM selector for this function is: 0xdf727d3b,444 /// or in textual repr: collectionOwner()445 function collectionOwner() public view returns (Tuple17 memory) {446 require(false, stub_error);447 dummy;448 return Tuple17(0x0000000000000000000000000000000000000000, 0);449 }404450405 /// Changes collection owner to another account451 /// Changes collection owner to another account406 ///452 ///pallets/structure/Cargo.tomldiffbeforeafterboth16 "derive",16 "derive",17] }17] }18up-data-structs = { path = "../../primitives/data-structs", default-features = false }18up-data-structs = { path = "../../primitives/data-structs", default-features = false }19pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }19pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }202021[features]21[features]22default = ["std"]22default = ["std"]pallets/unique/CHANGELOG.mddiffbeforeafterboth445<!-- bureaucrate goes here -->5<!-- bureaucrate goes here -->667## [v0.2.0] 2022-09-1389### Changes10- Change **collectionHelper** method `createRefungibleCollection` to `createRFTCollection`,117## [v0.1.4] 2022-09-0512## [v0.1.4] 2022-09-058139### Added14### Addedpallets/unique/Cargo.tomldiffbeforeafterboth9license = 'GPLv3'9license = 'GPLv3'10name = 'pallet-unique'10name = 'pallet-unique'11repository = 'https://github.com/UniqueNetwork/unique-chain'11repository = 'https://github.com/UniqueNetwork/unique-chain'12version = "0.1.4"12version = "0.2.0"131314[package.metadata.docs.rs]14[package.metadata.docs.rs]15targets = ['x86_64-unknown-linux-gnu']15targets = ['x86_64-unknown-linux-gnu']98scale-info = { version = "2.0.1", default-features = false, features = [98scale-info = { version = "2.0.1", default-features = false, features = [99 "derive",99 "derive",100] }100] }101pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }101pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }102pallet-common = { default-features = false, path = "../common" }102pallet-common = { default-features = false, path = "../common" }103evm-coder = { default-features = false, path = '../../crates/evm-coder' }103evm-coder = { default-features = false, path = '../../crates/evm-coder' }104pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }104pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }pallets/unique/src/eth/mod.rsdiffbeforeafterboth21use evm_coder::{execution::*, generate_stubgen, solidity_interface, solidity, weight, types::*};21use evm_coder::{execution::*, generate_stubgen, solidity_interface, solidity, weight, types::*};22use frame_support::traits::Get;22use frame_support::traits::Get;23use pallet_common::{23use pallet_common::{24 CollectionById, CollectionHandle,24 CollectionById,25 dispatch::CollectionDispatch,25 dispatch::CollectionDispatch,26 erc::{26 erc::{27 CollectionHelpersEvents,27 CollectionHelpersEvents,28 static_property::{key, value as property_value},28 static_property::{key, value as property_value},29 },29 },30 Pallet as PalletCommon,31};30};32use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};31use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};33use pallet_evm::{account::CrossAccountId, OnMethodCall, PrecompileHandle, PrecompileResult};32use pallet_evm::{account::CrossAccountId, OnMethodCall, PrecompileHandle, PrecompileResult};34use pallet_evm_coder_substrate::dispatch_to_evm;35use up_data_structs::{33use up_data_structs::{36 CollectionName, CollectionDescription, CollectionTokenPrefix, CreateCollectionData,34 CollectionName, CollectionDescription, CollectionTokenPrefix, CreateCollectionData,37 CollectionMode, PropertyKeyPermission, PropertyPermission, PropertyScope, PropertyValue,35 CollectionMode, PropertyValue,38};36};393740use crate::{Config, SelfWeightOf, weights::WeightInfo};38use crate::{Config, SelfWeightOf, weights::WeightInfo};413942use sp_std::{vec, vec::Vec};40use sp_std::vec::Vec;43use alloc::format;41use alloc::format;444245/// See [`CollectionHelpersCall`]43/// See [`CollectionHelpersCall`]245 }243 }246244247 #[weight(<SelfWeightOf<T>>::create_collection())]245 #[weight(<SelfWeightOf<T>>::create_collection())]246 #[solidity(rename_selector = "createRFTCollection")]248 fn create_refungible_collection(247 fn create_refungible_collection(249 &mut self,248 &mut self,250 caller: caller,249 caller: caller,pallets/unique/src/eth/stubs/CollectionHelpers.rawdiffbeforeafterbothbinary blob — no preview
pallets/unique/src/eth/stubs/CollectionHelpers.soldiffbeforeafterboth30}23}312432/// @title Contract, which allows users to operate with collections25/// @title Contract, which allows users to operate with collections33/// @dev the ERC-165 identifier for this interface is 0x675f307426/// @dev the ERC-165 identifier for this interface is 0x88ee8ef134contract CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents {27contract CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents {35 /// Create an NFT collection28 /// Create an NFT collection36 /// @param name Name of the collection29 /// @param name Name of the collection69 return 0x0000000000000000000000000000000000000000;62 return 0x0000000000000000000000000000000000000000;70 }63 }716472 /// @dev EVM selector for this function is: 0x44a68ad5,65 /// @dev EVM selector for this function is: 0xab173450,73 /// or in textual repr: createRefungibleCollection(string,string,string)66 /// or in textual repr: createRFTCollection(string,string,string)74 function createRefungibleCollection(67 function createRFTCollection(75 string memory name,68 string memory name,76 string memory description,69 string memory description,77 string memory tokenPrefix70 string memory tokenPrefixprimitives/app_promotion_rpc/Cargo.tomldiffbeforeafterboth14sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }14sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }15sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }15sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }16sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }16sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }17pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }17pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }181819[features]19[features]20default = ["std"]20default = ["std"]primitives/common/Cargo.tomldiffbeforeafterboth48[dependencies.fp-rpc]48[dependencies.fp-rpc]49default-features = false49default-features = false50git = "https://github.com/uniquenetwork/frontier"50git = "https://github.com/uniquenetwork/frontier"51branch = "unique-polkadot-v0.9.27"51branch = "unique-polkadot-v0.9.27-fee-limit"525253[dependencies.pallet-evm]53[dependencies.pallet-evm]54default-features = false54default-features = false55git = "https://github.com/uniquenetwork/frontier"55git = "https://github.com/uniquenetwork/frontier"56branch = "unique-polkadot-v0.9.27"56branch = "unique-polkadot-v0.9.27-fee-limit"5757primitives/data-structs/Cargo.tomldiffbeforeafterboth25sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }25sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }26derivative = { version = "2.2.0", features = ["use_core"] }26derivative = { version = "2.2.0", features = ["use_core"] }27struct-versioning = { path = "../../crates/struct-versioning" }27struct-versioning = { path = "../../crates/struct-versioning" }28pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }28pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }29rmrk-traits = { default-features = false, path = "../rmrk-traits" }29rmrk-traits = { default-features = false, path = "../rmrk-traits" }303031[features]31[features]primitives/rpc/Cargo.tomldiffbeforeafterboth14sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }14sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }15sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }15sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }16sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }16sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }17pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }17pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }181819[features]19[features]20default = ["std"]20default = ["std"]runtime/common/config/sponsoring.rsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// 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/>.161617use frame_support::parameter_types;18use crate::{17use crate::{19 runtime_common::{sponsoring::UniqueSponsorshipHandler},18 runtime_common::{sponsoring::UniqueSponsorshipHandler},20 Runtime,19 Runtime,21};20};21use frame_support::parameter_types;22use sp_core::U256;22use up_common::{types::BlockNumber, constants::*};23use up_common::{constants::*, types::BlockNumber};232424parameter_types! {25parameter_types! {25 pub const DefaultSponsoringRateLimit: BlockNumber = 1 * DAYS;26 pub const DefaultSponsoringRateLimit: BlockNumber = 1 * DAYS;27 pub const DefaultSponsoringFeeLimit: U256 = U256::MAX;26}28}272928type SponsorshipHandler = (30type SponsorshipHandler = (runtime/common/ethereum/sponsoring.rsdiffbeforeafterboth161617//! Implements EVM sponsoring logic via TransactionValidityHack17//! Implements EVM sponsoring logic via TransactionValidityHack181819use core::{convert::TryInto, marker::PhantomData};19use evm_coder::{Call, abi::AbiReader};20use evm_coder::{Call, abi::AbiReader};20use pallet_common::{CollectionHandle, eth::map_eth_to_id};21use pallet_common::{CollectionHandle, eth::map_eth_to_id};21use sp_core::H160;22use pallet_evm::account::CrossAccountId;23use pallet_evm_transaction_payment::CallContext;22use sp_std::prelude::*;24use pallet_nonfungible::{25 Config as NonfungibleConfig,26 erc::{27 UniqueNFTCall, ERC721UniqueExtensionsCall, ERC721MintableCall, ERC721Call,28 TokenPropertiesCall,29 },30};23use up_sponsorship::SponsorshipHandler;31use pallet_fungible::{32 Config as FungibleConfig,33 erc::{UniqueFungibleCall, ERC20Call},34};24use core::marker::PhantomData;35use pallet_refungible::Config as RefungibleConfig;25use core::convert::TryInto;36use pallet_unique::Config as UniqueConfig;26use pallet_evm::account::CrossAccountId;37use sp_std::prelude::*;27use up_data_structs::{TokenId, CreateItemData, CreateNftData, CollectionMode};38use up_data_structs::{CollectionMode, CreateItemData, CreateNftData, TokenId};28use pallet_unique::Config as UniqueConfig;39use up_sponsorship::SponsorshipHandler;294030use crate::{Runtime, runtime_common::sponsoring::*};41use crate::{Runtime, runtime_common::sponsoring::*};3132use pallet_nonfungible::erc::{33 UniqueNFTCall, ERC721UniqueExtensionsCall, ERC721MintableCall, ERC721Call, TokenPropertiesCall,34};35use pallet_fungible::erc::{UniqueFungibleCall, ERC20Call};36use pallet_fungible::Config as FungibleConfig;37use pallet_nonfungible::Config as NonfungibleConfig;38use pallet_refungible::Config as RefungibleConfig;394240pub type EvmSponsorshipHandler = (43pub type EvmSponsorshipHandler = (41 UniqueEthSponsorshipHandler<Runtime>,44 UniqueEthSponsorshipHandler<Runtime>,444745pub struct UniqueEthSponsorshipHandler<T: UniqueConfig>(PhantomData<*const T>);48pub struct UniqueEthSponsorshipHandler<T: UniqueConfig>(PhantomData<*const T>);46impl<T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig>49impl<T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig>47 SponsorshipHandler<T::CrossAccountId, (H160, Vec<u8>)> for UniqueEthSponsorshipHandler<T>50 SponsorshipHandler<T::CrossAccountId, CallContext> for UniqueEthSponsorshipHandler<T>48{51{49 fn get_sponsor(who: &T::CrossAccountId, call: &(H160, Vec<u8>)) -> Option<T::CrossAccountId> {52 fn get_sponsor(53 who: &T::CrossAccountId,54 call_context: &CallContext,55 ) -> Option<T::CrossAccountId> {50 let collection_id = map_eth_to_id(&call.0)?;56 let collection_id = map_eth_to_id(&call_context.contract_address)?;51 let collection = <CollectionHandle<T>>::new(collection_id)?;57 let collection = <CollectionHandle<T>>::new(collection_id)?;52 let sponsor = collection.sponsorship.sponsor()?.clone();58 let sponsor = collection.sponsorship.sponsor()?.clone();53 let (method_id, mut reader) = AbiReader::new_call(&call.1).ok()?;59 let (method_id, mut reader) = AbiReader::new_call(&call_context.input).ok()?;54 Some(T::CrossAccountId::from_sub(match &collection.mode {60 Some(T::CrossAccountId::from_sub(match &collection.mode {55 CollectionMode::NFT => {61 CollectionMode::NFT => {56 let call = <UniqueNFTCall<T>>::parse(method_id, &mut reader).ok()??;62 let call = <UniqueNFTCall<T>>::parse(method_id, &mut reader).ok()??;runtime/opal/Cargo.tomldiffbeforeafterboth441up-rpc = { path = "../../primitives/rpc", default-features = false }441up-rpc = { path = "../../primitives/rpc", default-features = false }442app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false}442app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false}443rmrk-rpc = { path = "../../primitives/rmrk-rpc", default-features = false }443rmrk-rpc = { path = "../../primitives/rmrk-rpc", default-features = false }444fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }444fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }445pallet-inflation = { path = '../../pallets/inflation', default-features = false }445pallet-inflation = { path = '../../pallets/inflation', default-features = false }446pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false }446pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false }447up-data-structs = { path = '../../primitives/data-structs', default-features = false }447up-data-structs = { path = '../../primitives/data-structs', default-features = false }460pallet-evm-contract-helpers = { path = '../../pallets/evm-contract-helpers', default-features = false }460pallet-evm-contract-helpers = { path = '../../pallets/evm-contract-helpers', default-features = false }461pallet-evm-transaction-payment = { path = '../../pallets/evm-transaction-payment', default-features = false }461pallet-evm-transaction-payment = { path = '../../pallets/evm-transaction-payment', default-features = false }462pallet-evm-coder-substrate = { default-features = false, path = "../../pallets/evm-coder-substrate" }462pallet-evm-coder-substrate = { default-features = false, path = "../../pallets/evm-coder-substrate" }463pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }463pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }464pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }464pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }465pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }465pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }466fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }466fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }467fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }467fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }468evm-coder = { default-features = false, path = '../../crates/evm-coder' }468evm-coder = { default-features = false, path = '../../crates/evm-coder' }469up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.27' }469up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.27' }470pallet-foreign-assets = { default-features = false, path = "../../pallets/foreign-assets" }470pallet-foreign-assets = { default-features = false, path = "../../pallets/foreign-assets" }runtime/quartz/Cargo.tomldiffbeforeafterboth446pallet-unique = { path = '../../pallets/unique', default-features = false }446pallet-unique = { path = '../../pallets/unique', default-features = false }447up-rpc = { path = "../../primitives/rpc", default-features = false }447up-rpc = { path = "../../primitives/rpc", default-features = false }448app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false}448app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false}449fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }449fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }450pallet-inflation = { path = '../../pallets/inflation', default-features = false }450pallet-inflation = { path = '../../pallets/inflation', default-features = false }451pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false }451pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false }452up-data-structs = { path = '../../primitives/data-structs', default-features = false }452up-data-structs = { path = '../../primitives/data-structs', default-features = false }465pallet-evm-contract-helpers = { path = '../../pallets/evm-contract-helpers', default-features = false }465pallet-evm-contract-helpers = { path = '../../pallets/evm-contract-helpers', default-features = false }466pallet-evm-transaction-payment = { path = '../../pallets/evm-transaction-payment', default-features = false }466pallet-evm-transaction-payment = { path = '../../pallets/evm-transaction-payment', default-features = false }467pallet-evm-coder-substrate = { default-features = false, path = "../../pallets/evm-coder-substrate" }467pallet-evm-coder-substrate = { default-features = false, path = "../../pallets/evm-coder-substrate" }468pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }468pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }469pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }469pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }470pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }470pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }471fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }471fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }472fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }472fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }473evm-coder = { default-features = false, path = '../../crates/evm-coder' }473evm-coder = { default-features = false, path = '../../crates/evm-coder' }474up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.27' }474up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.27' }475pallet-foreign-assets = { default-features = false, path = "../../pallets/foreign-assets" }475pallet-foreign-assets = { default-features = false, path = "../../pallets/foreign-assets" }runtime/tests/Cargo.tomldiffbeforeafterboth16sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }16sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }17sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }17sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }181819fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }19fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }202021frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }21frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }22frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }22frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }25pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }25pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }26pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }26pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }272728pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }28pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }29pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }29pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }303031pallet-common = { path = '../../pallets/common' }31pallet-common = { path = '../../pallets/common' }32pallet-structure = { path = '../../pallets/structure' }32pallet-structure = { path = '../../pallets/structure' }43scale-info = "*"43scale-info = "*"444445evm-coder = { default-features = false, path = '../../crates/evm-coder' }45evm-coder = { default-features = false, path = '../../crates/evm-coder' }46up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.27' }46up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.27" }4747runtime/unique/Cargo.tomldiffbeforeafterboth456pallet-evm-contract-helpers = { path = '../../pallets/evm-contract-helpers', default-features = false }456pallet-evm-contract-helpers = { path = '../../pallets/evm-contract-helpers', default-features = false }457pallet-evm-transaction-payment = { path = '../../pallets/evm-transaction-payment', default-features = false }457pallet-evm-transaction-payment = { path = '../../pallets/evm-transaction-payment', default-features = false }458pallet-evm-coder-substrate = { default-features = false, path = "../../pallets/evm-coder-substrate" }458pallet-evm-coder-substrate = { default-features = false, path = "../../pallets/evm-coder-substrate" }459pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }459pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }460pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }460pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }461pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }461pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }462fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }462fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }463fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }463fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }464fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }464fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }465evm-coder = { default-features = false, path = '../../crates/evm-coder' }465evm-coder = { default-features = false, path = '../../crates/evm-coder' }466up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.27' }466up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.27' }467pallet-foreign-assets = { default-features = false, path = "../../pallets/foreign-assets" }467pallet-foreign-assets = { default-features = false, path = "../../pallets/foreign-assets" }tests/src/eth/allowlist.test.tsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// 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/>.161617import {IKeyringPair} from '@polkadot/types/types';17import {expect} from 'chai';18import {expect} from 'chai';19import {isAllowlisted, normalizeAccountId} from '../util/helpers';18import {contractHelpers, createEthAccountWithBalance, deployFlipper, itWeb3} from './util/helpers';20import {21 contractHelpers,22 createEthAccount,23 createEthAccountWithBalance,24 deployFlipper,25 evmCollection,26 evmCollectionHelpers,27 getCollectionAddressFromResult,28 itWeb3,29} from './util/helpers';30import {itEth, usingEthPlaygrounds} from './util/playgrounds';193120describe('EVM allowlist', () => {32describe('EVM contract allowlist', () => {21 itWeb3('Contract allowlist can be toggled', async ({api, web3, privateKeyWrapper}) => {33 itWeb3('Contract allowlist can be toggled', async ({api, web3, privateKeyWrapper}) => {22 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);34 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);23 const flipper = await deployFlipper(web3, owner);35 const flipper = await deployFlipper(web3, owner);59 });71 });60});72});7374describe('EVM collection allowlist', () => {75 let donor: IKeyringPair;7677 before(async function() {78 await usingEthPlaygrounds(async (_helper, privateKey) => {79 donor = privateKey('//Alice');80 });81 });82 83 itEth('Collection allowlist can be added and removed by [eth] address', async ({helper}) => {84 const owner = await helper.eth.createAccountWithBalance(donor);85 const user = helper.eth.createAccount();86 87 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');88 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);89 90 expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false;91 await collectionEvm.methods.addToCollectionAllowList(user).send({from: owner});92 expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.true;93 94 await collectionEvm.methods.removeFromCollectionAllowList(user).send({from: owner});95 expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false;96 });9798 itEth('Collection allowlist can be added and removed by [sub] address', async ({helper}) => {99 const owner = await helper.eth.createAccountWithBalance(donor);100 const user = donor;101 102 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');103 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);104 105 expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;106 await collectionEvm.methods.addToCollectionAllowListSubstrate(user.addressRaw).send({from: owner});107 expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.true;108 109 await collectionEvm.methods.removeFromCollectionAllowListSubstrate(user.addressRaw).send({from: owner});110 expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;111 });112113 itEth('Collection allowlist can not be add and remove [eth] address by not owner', async ({helper}) => {114 const owner = await helper.eth.createAccountWithBalance(donor);115 const notOwner = await helper.eth.createAccountWithBalance(donor);116 const user = helper.eth.createAccount();117 118 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');119 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);120 121 expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false;122 await expect(collectionEvm.methods.addToCollectionAllowList(user).call({from: notOwner})).to.be.rejectedWith('NoPermission');123 expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false;124 await collectionEvm.methods.addToCollectionAllowList(user).send({from: owner});125 126 expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.true;127 await expect(collectionEvm.methods.removeFromCollectionAllowList(user).call({from: notOwner})).to.be.rejectedWith('NoPermission');128 expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.true;129 });130131 itEth('Collection allowlist can not be add and remove [sub] address by not owner', async ({helper}) => {132 const owner = await helper.eth.createAccountWithBalance(donor);133 const notOwner = await helper.eth.createAccountWithBalance(donor);134 const user = donor;135 136 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');137 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);138 139 expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;140 await expect(collectionEvm.methods.addToCollectionAllowListSubstrate(user.addressRaw).call({from: notOwner})).to.be.rejectedWith('NoPermission');141 expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;142 await collectionEvm.methods.addToCollectionAllowListSubstrate(user.addressRaw).send({from: owner});143 144 expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.true;145 await expect(collectionEvm.methods.removeFromCollectionAllowListSubstrate(user.addressRaw).call({from: notOwner})).to.be.rejectedWith('NoPermission');146 expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.true;147 });148});61149tests/src/eth/api/CollectionHelpers.soldiffbeforeafterboth21}18}221923/// @title Contract, which allows users to operate with collections20/// @title Contract, which allows users to operate with collections24/// @dev the ERC-165 identifier for this interface is 0x675f307421/// @dev the ERC-165 identifier for this interface is 0x88ee8ef125interface CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents {22interface CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents {26 /// Create an NFT collection23 /// Create an NFT collection27 /// @param name Name of the collection24 /// @param name Name of the collection45 string memory baseUri42 string memory baseUri46 ) external returns (address);43 ) external returns (address);474448 /// @dev EVM selector for this function is: 0x44a68ad5,45 /// @dev EVM selector for this function is: 0xab173450,49 /// or in textual repr: createRefungibleCollection(string,string,string)46 /// or in textual repr: createRFTCollection(string,string,string)50 function createRefungibleCollection(47 function createRFTCollection(51 string memory name,48 string memory name,52 string memory description,49 string memory description,53 string memory tokenPrefix50 string memory tokenPrefixtests/src/eth/api/ContractHelpers.soldiffbeforeafterboth23}23}242425/// @title Magic contract, which allows users to reconfigure other contracts25/// @title Magic contract, which allows users to reconfigure other contracts26/// @dev the ERC-165 identifier for this interface is 0xd77fab7026/// @dev the ERC-165 identifier for this interface is 0x172cb4fb27interface ContractHelpers is Dummy, ERC165, ContractHelpersEvents {27interface ContractHelpers is Dummy, ERC165, ContractHelpersEvents {28 /// Get user, which deployed specified contract28 /// Get user, which deployed specified contract29 /// @dev May return zero address in case if contract is deployed29 /// @dev May return zero address in case if contract is deployed111 function setSponsoringMode(address contractAddress, uint8 mode) external;111 function setSponsoringMode(address contractAddress, uint8 mode) external;112112113 /// Get current contract sponsoring rate limit113 /// Get current contract sponsoring rate limit114 /// @param contractAddress Contract to get sponsoring mode of114 /// @param contractAddress Contract to get sponsoring rate limit of115 /// @return uint32 Amount of blocks between two sponsored transactions115 /// @return uint32 Amount of blocks between two sponsored transactions116 /// @dev EVM selector for this function is: 0x610cfabd,116 /// @dev EVM selector for this function is: 0x610cfabd,117 /// or in textual repr: getSponsoringRateLimit(address)117 /// or in textual repr: getSponsoringRateLimit(address)131 function setSponsoringRateLimit(address contractAddress, uint32 rateLimit)131 function setSponsoringRateLimit(address contractAddress, uint32 rateLimit)132 external;132 external;133134 /// Set contract sponsoring fee limit135 /// @dev Sponsoring fee limit - is maximum fee that could be spent by136 /// single transaction137 /// @param contractAddress Contract to change sponsoring fee limit of138 /// @param feeLimit Fee limit139 /// @dev Only contract owner can change this setting140 /// @dev EVM selector for this function is: 0x03aed665,141 /// or in textual repr: setSponsoringFeeLimit(address,uint256)142 function setSponsoringFeeLimit(address contractAddress, uint256 feeLimit)143 external;144145 /// Get current contract sponsoring fee limit146 /// @param contractAddress Contract to get sponsoring fee limit of147 /// @return uint256 Maximum amount of fee that could be spent by single148 /// transaction149 /// @dev EVM selector for this function is: 0xc3fdc9ee,150 /// or in textual repr: getSponsoringFeeLimit(address)151 function getSponsoringFeeLimit(address contractAddress)152 external153 view154 returns (uint256);133155134 /// Is specified user present in contract allow list156 /// Is specified user present in contract allow list135 /// @dev Contract owner always implicitly included157 /// @dev Contract owner always implicitly includedtests/src/eth/api/UniqueFungible.soldiffbeforeafterboth13}13}141415/// @title A contract that allows you to work with collections.15/// @title A contract that allows you to work with collections.16/// @dev the ERC-165 identifier for this interface is 0xe54be64016/// @dev the ERC-165 identifier for this interface is 0x9f70d4e017interface Collection is Dummy, ERC165 {17interface Collection is Dummy, ERC165 {18 /// Set collection property.18 /// Set collection property.19 ///19 ///164 /// or in textual repr: setCollectionAccess(uint8)164 /// or in textual repr: setCollectionAccess(uint8)165 function setCollectionAccess(uint8 mode) external;165 function setCollectionAccess(uint8 mode) external;166167 /// Checks that user allowed to operate with collection.168 ///169 /// @param user User address to check.170 /// @dev EVM selector for this function is: 0xd63a8e11,171 /// or in textual repr: allowed(address)172 function allowed(address user) external view returns (bool);166173167 /// Add the user to the allowed list.174 /// Add the user to the allowed list.168 ///175 ///171 /// or in textual repr: addToCollectionAllowList(address)178 /// or in textual repr: addToCollectionAllowList(address)172 function addToCollectionAllowList(address user) external;179 function addToCollectionAllowList(address user) external;180181 /// Add substrate user to allowed list.182 ///183 /// @param user User substrate address.184 /// @dev EVM selector for this function is: 0xd06ad267,185 /// or in textual repr: addToCollectionAllowListSubstrate(uint256)186 function addToCollectionAllowListSubstrate(uint256 user) external;173187174 /// Remove the user from the allowed list.188 /// Remove the user from the allowed list.175 ///189 ///178 /// or in textual repr: removeFromCollectionAllowList(address)192 /// or in textual repr: removeFromCollectionAllowList(address)179 function removeFromCollectionAllowList(address user) external;193 function removeFromCollectionAllowList(address user) external;194195 /// Remove substrate user from allowed list.196 ///197 /// @param user User substrate address.198 /// @dev EVM selector for this function is: 0xa31913ed,199 /// or in textual repr: removeFromCollectionAllowListSubstrate(uint256)200 function removeFromCollectionAllowListSubstrate(uint256 user) external;180201181 /// Switch permission for minting.202 /// Switch permission for minting.182 ///203 ///208 /// or in textual repr: uniqueCollectionType()229 /// or in textual repr: uniqueCollectionType()209 function uniqueCollectionType() external returns (string memory);230 function uniqueCollectionType() external returns (string memory);231232 /// Get collection owner.233 ///234 /// @return Tuble with sponsor address and his substrate mirror.235 /// If address is canonical then substrate mirror is zero and vice versa.236 /// @dev EVM selector for this function is: 0xdf727d3b,237 /// or in textual repr: collectionOwner()238 function collectionOwner() external view returns (Tuple6 memory);210239211 /// Changes collection owner to another account240 /// Changes collection owner to another account212 ///241 ///tests/src/eth/api/UniqueNFT.soldiffbeforeafterboth65}65}666667/// @title A contract that allows you to work with collections.67/// @title A contract that allows you to work with collections.68/// @dev the ERC-165 identifier for this interface is 0xe54be64068/// @dev the ERC-165 identifier for this interface is 0x9f70d4e069interface Collection is Dummy, ERC165 {69interface Collection is Dummy, ERC165 {70 /// Set collection property.70 /// Set collection property.71 ///71 ///216 /// or in textual repr: setCollectionAccess(uint8)216 /// or in textual repr: setCollectionAccess(uint8)217 function setCollectionAccess(uint8 mode) external;217 function setCollectionAccess(uint8 mode) external;218219 /// Checks that user allowed to operate with collection.220 ///221 /// @param user User address to check.222 /// @dev EVM selector for this function is: 0xd63a8e11,223 /// or in textual repr: allowed(address)224 function allowed(address user) external view returns (bool);218225219 /// Add the user to the allowed list.226 /// Add the user to the allowed list.220 ///227 ///223 /// or in textual repr: addToCollectionAllowList(address)230 /// or in textual repr: addToCollectionAllowList(address)224 function addToCollectionAllowList(address user) external;231 function addToCollectionAllowList(address user) external;232233 /// Add substrate user to allowed list.234 ///235 /// @param user User substrate address.236 /// @dev EVM selector for this function is: 0xd06ad267,237 /// or in textual repr: addToCollectionAllowListSubstrate(uint256)238 function addToCollectionAllowListSubstrate(uint256 user) external;225239226 /// Remove the user from the allowed list.240 /// Remove the user from the allowed list.227 ///241 ///230 /// or in textual repr: removeFromCollectionAllowList(address)244 /// or in textual repr: removeFromCollectionAllowList(address)231 function removeFromCollectionAllowList(address user) external;245 function removeFromCollectionAllowList(address user) external;246247 /// Remove substrate user from allowed list.248 ///249 /// @param user User substrate address.250 /// @dev EVM selector for this function is: 0xa31913ed,251 /// or in textual repr: removeFromCollectionAllowListSubstrate(uint256)252 function removeFromCollectionAllowListSubstrate(uint256 user) external;232253233 /// Switch permission for minting.254 /// Switch permission for minting.234 ///255 ///260 /// or in textual repr: uniqueCollectionType()281 /// or in textual repr: uniqueCollectionType()261 function uniqueCollectionType() external returns (string memory);282 function uniqueCollectionType() external returns (string memory);283284 /// Get collection owner.285 ///286 /// @return Tuble with sponsor address and his substrate mirror.287 /// If address is canonical then substrate mirror is zero and vice versa.288 /// @dev EVM selector for this function is: 0xdf727d3b,289 /// or in textual repr: collectionOwner()290 function collectionOwner() external view returns (Tuple17 memory);262291263 /// Changes collection owner to another account292 /// Changes collection owner to another account264 ///293 ///tests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth65}65}666667/// @title A contract that allows you to work with collections.67/// @title A contract that allows you to work with collections.68/// @dev the ERC-165 identifier for this interface is 0xe54be64068/// @dev the ERC-165 identifier for this interface is 0x9f70d4e069interface Collection is Dummy, ERC165 {69interface Collection is Dummy, ERC165 {70 /// Set collection property.70 /// Set collection property.71 ///71 ///216 /// or in textual repr: setCollectionAccess(uint8)216 /// or in textual repr: setCollectionAccess(uint8)217 function setCollectionAccess(uint8 mode) external;217 function setCollectionAccess(uint8 mode) external;218219 /// Checks that user allowed to operate with collection.220 ///221 /// @param user User address to check.222 /// @dev EVM selector for this function is: 0xd63a8e11,223 /// or in textual repr: allowed(address)224 function allowed(address user) external view returns (bool);218225219 /// Add the user to the allowed list.226 /// Add the user to the allowed list.220 ///227 ///223 /// or in textual repr: addToCollectionAllowList(address)230 /// or in textual repr: addToCollectionAllowList(address)224 function addToCollectionAllowList(address user) external;231 function addToCollectionAllowList(address user) external;232233 /// Add substrate user to allowed list.234 ///235 /// @param user User substrate address.236 /// @dev EVM selector for this function is: 0xd06ad267,237 /// or in textual repr: addToCollectionAllowListSubstrate(uint256)238 function addToCollectionAllowListSubstrate(uint256 user) external;225239226 /// Remove the user from the allowed list.240 /// Remove the user from the allowed list.227 ///241 ///230 /// or in textual repr: removeFromCollectionAllowList(address)244 /// or in textual repr: removeFromCollectionAllowList(address)231 function removeFromCollectionAllowList(address user) external;245 function removeFromCollectionAllowList(address user) external;246247 /// Remove substrate user from allowed list.248 ///249 /// @param user User substrate address.250 /// @dev EVM selector for this function is: 0xa31913ed,251 /// or in textual repr: removeFromCollectionAllowListSubstrate(uint256)252 function removeFromCollectionAllowListSubstrate(uint256 user) external;232253233 /// Switch permission for minting.254 /// Switch permission for minting.234 ///255 ///260 /// or in textual repr: uniqueCollectionType()281 /// or in textual repr: uniqueCollectionType()261 function uniqueCollectionType() external returns (string memory);282 function uniqueCollectionType() external returns (string memory);283284 /// Get collection owner.285 ///286 /// @return Tuble with sponsor address and his substrate mirror.287 /// If address is canonical then substrate mirror is zero and vice versa.288 /// @dev EVM selector for this function is: 0xdf727d3b,289 /// or in textual repr: collectionOwner()290 function collectionOwner() external view returns (Tuple17 memory);262291263 /// Changes collection owner to another account292 /// Changes collection owner to another account264 ///293 ///tests/src/eth/collectionHelpersAbi.jsondiffbeforeafterboth59 { "internalType": "string", "name": "description", "type": "string" },59 { "internalType": "string", "name": "description", "type": "string" },60 { "internalType": "string", "name": "tokenPrefix", "type": "string" }60 { "internalType": "string", "name": "tokenPrefix", "type": "string" }61 ],61 ],62 "name": "createRefungibleCollection",62 "name": "createRFTCollection",63 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],63 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],64 "stateMutability": "nonpayable",64 "stateMutability": "nonpayable",65 "type": "function"65 "type": "function"tests/src/eth/contractSponsoring.test.tsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// 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/>.161617import * as solc from 'solc';17import {expect} from 'chai';18import {expect} from 'chai';18import {expectSubstrateEventsAtBlock} from '../util/helpers';19import {expectSubstrateEventsAtBlock} from '../util/helpers';20import Web3 from 'web3';2119import {22import {20 contractHelpers,23 contractHelpers,26 createEthAccount,29 createEthAccount,27 ethBalanceViaSub,30 ethBalanceViaSub,28 normalizeEvents,31 normalizeEvents,32 CompiledContract,33 GAS_ARGS,34 subToEth,29} from './util/helpers';35} from './util/helpers';36import {submitTransactionAsync} from '../substrate/substrate-api';303731describe('Sponsoring EVM contracts', () => {38describe('Sponsoring EVM contracts', () => {32 itWeb3('Self sponsored can be set by the address that deployed the contract', async ({api, web3, privateKeyWrapper}) => {39 itWeb3('Self sponsored can be set by the address that deployed the contract', async ({api, web3, privateKeyWrapper}) => {479 });486 });480});487});488489describe('Sponsoring Fee Limit', () => {490491 let testContract: CompiledContract;492 493 function compileTestContract() {494 if (!testContract) {495 const input = {496 language: 'Solidity',497 sources: {498 ['TestContract.sol']: {499 content:500 `501 // SPDX-License-Identifier: MIT502 pragma solidity ^0.8.0;503 504 contract TestContract {505 event Result(bool);506507 function test(uint32 cycles) public {508 uint256 counter = 0;509 while(true) {510 counter ++;511 if (counter > cycles){512 break;513 }514 }515 emit Result(true);516 }517 }518 `,519 },520 },521 settings: {522 outputSelection: {523 '*': {524 '*': ['*'],525 },526 },527 },528 };529 const json = JSON.parse(solc.compile(JSON.stringify(input)));530 const out = json.contracts['TestContract.sol']['TestContract'];531 532 testContract = {533 abi: out.abi,534 object: '0x' + out.evm.bytecode.object,535 };536 }537 return testContract;538 }539 540 async function deployTestContract(web3: Web3, owner: string) {541 const compiled = compileTestContract();542 const testContract = new web3.eth.Contract(compiled.abi, undefined, {543 data: compiled.object,544 from: owner,545 ...GAS_ARGS,546 });547 return await testContract.deploy({data: compiled.object}).send({from: owner});548 }549550 itWeb3('Default fee limit', async ({api, web3, privateKeyWrapper}) => {551 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);552 const flipper = await deployFlipper(web3, owner);553 const helpers = contractHelpers(web3, owner);554 expect(await helpers.methods.getSponsoringFeeLimit(flipper.options.address).call()).to.be.equals('115792089237316195423570985008687907853269984665640564039457584007913129639935');555 });556557 itWeb3('Set fee limit', async ({api, web3, privateKeyWrapper}) => {558 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);559 const flipper = await deployFlipper(web3, owner);560 const helpers = contractHelpers(web3, owner);561 await helpers.methods.setSponsoringFeeLimit(flipper.options.address, 100).send();562 expect(await helpers.methods.getSponsoringFeeLimit(flipper.options.address).call()).to.be.equals('100');563 });564565 itWeb3('Negative test - set fee limit by non-owner', async ({api, web3, privateKeyWrapper}) => {566 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);567 const stranger = await createEthAccountWithBalance(api, web3, privateKeyWrapper);568 const flipper = await deployFlipper(web3, owner);569 const helpers = contractHelpers(web3, owner);570 await expect(helpers.methods.setSponsoringFeeLimit(flipper.options.address, 100).send({from: stranger})).to.be.rejected;571 });572573 itWeb3('Negative test - check that eth transactions exceeding fee limit are not executed', async ({api, web3, privateKeyWrapper}) => {574 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);575 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);576 const user = await createEthAccountWithBalance(api, web3, privateKeyWrapper);577578 const testContract = await deployTestContract(web3, owner);579 const helpers = contractHelpers(web3, owner);580 581 await helpers.methods.setSponsoringMode(testContract.options.address, SponsoringMode.Generous).send({from: owner});582 await helpers.methods.setSponsoringRateLimit(testContract.options.address, 0).send({from: owner});583 584 await helpers.methods.setSponsor(testContract.options.address, sponsor).send();585 await helpers.methods.confirmSponsorship(testContract.options.address).send({from: sponsor});586587 const gasPrice = BigInt(await web3.eth.getGasPrice());588589 await helpers.methods.setSponsoringFeeLimit(testContract.options.address, 2_000_000n * gasPrice).send();590591 const originalUserBalance = await web3.eth.getBalance(user);592 await testContract.methods.test(100).send({from: user, gas: 2_000_000});593 expect(await web3.eth.getBalance(user)).to.be.equal(originalUserBalance);594595 await testContract.methods.test(100).send({from: user, gas: 2_100_000});596 expect(await web3.eth.getBalance(user)).to.not.be.equal(originalUserBalance);597 });598599 itWeb3('Negative test - check that evm.call transactions exceeding fee limit are not executed', async ({api, web3, privateKeyWrapper}) => {600 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);601 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);602603 const testContract = await deployTestContract(web3, owner);604 const helpers = contractHelpers(web3, owner);605 606 await helpers.methods.setSponsoringMode(testContract.options.address, SponsoringMode.Generous).send({from: owner});607 await helpers.methods.setSponsoringRateLimit(testContract.options.address, 0).send({from: owner});608 609 await helpers.methods.setSponsor(testContract.options.address, sponsor).send();610 await helpers.methods.confirmSponsorship(testContract.options.address).send({from: sponsor});611612 const gasPrice = BigInt(await web3.eth.getGasPrice());613614 await helpers.methods.setSponsoringFeeLimit(testContract.options.address, 2_000_000n * gasPrice).send();615616 const alice = privateKeyWrapper('//Alice');617 const originalAliceBalance = (await api.query.system.account(alice.address)).data.free.toBigInt();618 619 await submitTransactionAsync(620 alice,621 api.tx.evm.call(622 subToEth(alice.address),623 testContract.options.address,624 testContract.methods.test(100).encodeABI(),625 Uint8Array.from([]),626 2_000_000n,627 gasPrice,628 null,629 null,630 [],631 ),632 );633 expect((await api.query.system.account(alice.address)).data.free.toBigInt()).to.be.equal(originalAliceBalance);634 635 await submitTransactionAsync(636 alice,637 api.tx.evm.call(638 subToEth(alice.address),639 testContract.options.address,640 testContract.methods.test(100).encodeABI(),641 Uint8Array.from([]),642 2_100_000n,643 gasPrice,644 null,645 null,646 [],647 ),648 );649 expect((await api.query.system.account(alice.address)).data.free.toBigInt()).to.not.be.equal(originalAliceBalance);650 });651});481652tests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth41 41 42 const collectionCountBefore = await getCreatedCollectionCount(api);42 const collectionCountBefore = await getCreatedCollectionCount(api);43 const result = await collectionHelper.methods43 const result = await collectionHelper.methods44 .createRefungibleCollection(collectionName, description, tokenPrefix)44 .createRFTCollection(collectionName, description, tokenPrefix)45 .send();45 .send();46 const collectionCountAfter = await getCreatedCollectionCount(api);46 const collectionCountAfter = await getCreatedCollectionCount(api);47 47 65 .call()).to.be.false;65 .call()).to.be.false;666667 await collectionHelpers.methods67 await collectionHelpers.methods68 .createRefungibleCollection('A', 'A', 'A')68 .createRFTCollection('A', 'A', 'A')69 .send();69 .send();70 70 71 expect(await collectionHelpers.methods71 expect(await collectionHelpers.methods76 itWeb3('Set sponsorship', async ({api, web3, privateKeyWrapper}) => {76 itWeb3('Set sponsorship', async ({api, web3, privateKeyWrapper}) => {77 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);77 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);78 const collectionHelpers = evmCollectionHelpers(web3, owner);78 const collectionHelpers = evmCollectionHelpers(web3, owner);79 let result = await collectionHelpers.methods.createRefungibleCollection('Sponsor collection', '1', '1').send();79 let result = await collectionHelpers.methods.createRFTCollection('Sponsor collection', '1', '1').send();80 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);80 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);81 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);81 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);82 const collectionEvm = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});82 const collectionEvm = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});96 itWeb3('Set limits', async ({api, web3, privateKeyWrapper}) => {96 itWeb3('Set limits', async ({api, web3, privateKeyWrapper}) => {97 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);97 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);98 const collectionHelpers = evmCollectionHelpers(web3, owner);98 const collectionHelpers = evmCollectionHelpers(web3, owner);99 const result = await collectionHelpers.methods.createRefungibleCollection('Const collection', '5', '5').send();99 const result = await collectionHelpers.methods.createRFTCollection('Const collection', '5', '5').send();100 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);100 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);101 const limits = {101 const limits = {102 accountTokenOwnershipLimit: 1000,102 accountTokenOwnershipLimit: 1000,141 .isCollectionExist(collectionAddressForNonexistentCollection).call())141 .isCollectionExist(collectionAddressForNonexistentCollection).call())142 .to.be.false;142 .to.be.false;143 143 144 const result = await collectionHelpers.methods.createRefungibleCollection('Collection address exist', '7', '7').send();144 const result = await collectionHelpers.methods.createRFTCollection('Collection address exist', '7', '7').send();145 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);145 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);146 expect(await collectionHelpers.methods146 expect(await collectionHelpers.methods147 .isCollectionExist(collectionIdAddress).call())147 .isCollectionExist(collectionIdAddress).call())164 const tokenPrefix = 'A';164 const tokenPrefix = 'A';165 165 166 await expect(helper.methods166 await expect(helper.methods167 .createRefungibleCollection(collectionName, description, tokenPrefix)167 .createRFTCollection(collectionName, description, tokenPrefix)168 .call()).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGHT);168 .call()).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGHT);169 169 170 }170 }174 const description = 'A'.repeat(MAX_DESCRIPTION_LENGHT + 1);174 const description = 'A'.repeat(MAX_DESCRIPTION_LENGHT + 1);175 const tokenPrefix = 'A';175 const tokenPrefix = 'A';176 await expect(helper.methods176 await expect(helper.methods177 .createRefungibleCollection(collectionName, description, tokenPrefix)177 .createRFTCollection(collectionName, description, tokenPrefix)178 .call()).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGHT);178 .call()).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGHT);179 }179 }180 { 180 { 183 const description = 'A';183 const description = 'A';184 const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGHT + 1);184 const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGHT + 1);185 await expect(helper.methods185 await expect(helper.methods186 .createRefungibleCollection(collectionName, description, tokenPrefix)186 .createRFTCollection(collectionName, description, tokenPrefix)187 .call()).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGHT);187 .call()).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGHT);188 }188 }189 });189 });196 const tokenPrefix = 'A';196 const tokenPrefix = 'A';197 197 198 await expect(helper.methods198 await expect(helper.methods199 .createRefungibleCollection(collectionName, description, tokenPrefix)199 .createRFTCollection(collectionName, description, tokenPrefix)200 .call()).to.be.rejectedWith('NotSufficientFounds');200 .call()).to.be.rejectedWith('NotSufficientFounds');201 });201 });202202203 itWeb3('(!negative test!) Check owner', async ({api, web3, privateKeyWrapper}) => {203 itWeb3('(!negative test!) Check owner', async ({api, web3, privateKeyWrapper}) => {204 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);204 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);205 const notOwner = createEthAccount(web3);205 const notOwner = createEthAccount(web3);206 const collectionHelpers = evmCollectionHelpers(web3, owner);206 const collectionHelpers = evmCollectionHelpers(web3, owner);207 const result = await collectionHelpers.methods.createRefungibleCollection('A', 'A', 'A').send();207 const result = await collectionHelpers.methods.createRFTCollection('A', 'A', 'A').send();208 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);208 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);209 const contractEvmFromNotOwner = evmCollection(web3, notOwner, collectionIdAddress, {type: 'ReFungible'});209 const contractEvmFromNotOwner = evmCollection(web3, notOwner, collectionIdAddress, {type: 'ReFungible'});210 const EXPECTED_ERROR = 'NoPermission';210 const EXPECTED_ERROR = 'NoPermission';229 itWeb3('(!negative test!) Set limits', async ({api, web3, privateKeyWrapper}) => {229 itWeb3('(!negative test!) Set limits', async ({api, web3, privateKeyWrapper}) => {230 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);230 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);231 const collectionHelpers = evmCollectionHelpers(web3, owner);231 const collectionHelpers = evmCollectionHelpers(web3, owner);232 const result = await collectionHelpers.methods.createRefungibleCollection('Schema collection', 'A', 'A').send();232 const result = await collectionHelpers.methods.createRFTCollection('Schema collection', 'A', 'A').send();233 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);233 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);234 const collectionEvm = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});234 const collectionEvm = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});235 await expect(collectionEvm.methods235 await expect(collectionEvm.methodstests/src/eth/fractionalizer/Fractionalizer.soldiffbeforeafterboth84 "RFT collection is already set"85 );86 address collectionHelpers = 0x6C4E9fE1AE37a41E93CEE429e8E1881aBdcbb54F;84 address collectionHelpers = 0x6C4E9fE1AE37a41E93CEE429e8E1881aBdcbb54F;87 rftCollection = CollectionHelpers(collectionHelpers).createRefungibleCollection(_name, _description, _tokenPrefix);85 rftCollection = CollectionHelpers(collectionHelpers).createRFTCollection(_name, _description, _tokenPrefix);88 emit RFTCollectionSet(rftCollection);86 emit RFTCollectionSet(rftCollection);89 }87 }9088tests/src/eth/fractionalizer/fractionalizer.test.tsdiffbeforeafterboth21import {readFile} from 'fs/promises';21import {readFile} from 'fs/promises';22import {executeTransaction, submitTransactionAsync} from '../../substrate/substrate-api';22import {executeTransaction, submitTransactionAsync} from '../../substrate/substrate-api';23import {getCreateCollectionResult, getCreateItemResult, UNIQUE, requirePallets, Pallets} from '../../util/helpers';23import {getCreateCollectionResult, getCreateItemResult, UNIQUE, requirePallets, Pallets} from '../../util/helpers';24import {collectionIdToAddress, CompiledContract, createEthAccountWithBalance, createNonfungibleCollection, createRefungibleCollection, GAS_ARGS, itWeb3, tokenIdFromAddress, uniqueNFT, uniqueRefungible, uniqueRefungibleToken} from '../util/helpers';24import {collectionIdToAddress, CompiledContract, createEthAccountWithBalance, createNonfungibleCollection, createRFTCollection, GAS_ARGS, itWeb3, tokenIdFromAddress, uniqueNFT, uniqueRefungible, uniqueRefungibleToken} from '../util/helpers';25import {Contract} from 'web3-eth-contract';25import {Contract} from 'web3-eth-contract';26import * as solc from 'solc';26import * as solc from 'solc';2727123 itWeb3('Set RFT collection', async ({api, web3, privateKeyWrapper}) => {123 itWeb3('Set RFT collection', async ({api, web3, privateKeyWrapper}) => {124 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);124 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);125 const fractionalizer = await deployFractionalizer(web3, owner);125 const fractionalizer = await deployFractionalizer(web3, owner);126 const {collectionIdAddress} = await createRefungibleCollection(api, web3, owner);126 const {collectionIdAddress} = await createRFTCollection(api, web3, owner);127 const refungibleContract = uniqueRefungible(web3, collectionIdAddress, owner);127 const refungibleContract = uniqueRefungible(web3, collectionIdAddress, owner);128 await refungibleContract.methods.addCollectionAdmin(fractionalizer.options.address).send();128 await refungibleContract.methods.addCollectionAdmin(fractionalizer.options.address).send();129 const result = await fractionalizer.methods.setRFTCollection(collectionIdAddress).send();129 const result = await fractionalizer.methods.setRFTCollection(collectionIdAddress).send();256256257 itWeb3('call setRFTCollection twice', async ({api, web3, privateKeyWrapper}) => {257 itWeb3('call setRFTCollection twice', async ({api, web3, privateKeyWrapper}) => {258 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);258 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);259 const {collectionIdAddress} = await createRefungibleCollection(api, web3, owner);259 const {collectionIdAddress} = await createRFTCollection(api, web3, owner);260 const refungibleContract = uniqueRefungible(web3, collectionIdAddress, owner);260 const refungibleContract = uniqueRefungible(web3, collectionIdAddress, owner);261261262 const fractionalizer = await deployFractionalizer(web3, owner);262 const fractionalizer = await deployFractionalizer(web3, owner);282 itWeb3('call setRFTCollection while not collection admin', async ({api, web3, privateKeyWrapper}) => {282 itWeb3('call setRFTCollection while not collection admin', async ({api, web3, privateKeyWrapper}) => {283 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);283 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);284 const fractionalizer = await deployFractionalizer(web3, owner);284 const fractionalizer = await deployFractionalizer(web3, owner);285 const {collectionIdAddress} = await createRefungibleCollection(api, web3, owner);285 const {collectionIdAddress} = await createRFTCollection(api, web3, owner);286286287 await expect(fractionalizer.methods.setRFTCollection(collectionIdAddress).call())287 await expect(fractionalizer.methods.setRFTCollection(collectionIdAddress).call())288 .to.be.rejectedWith(/Fractionalizer contract should be an admin of the collection$/g);288 .to.be.rejectedWith(/Fractionalizer contract should be an admin of the collection$/g);368 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);368 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);369369370 const fractionalizer = await deployFractionalizer(web3, owner);370 const fractionalizer = await deployFractionalizer(web3, owner);371 const {collectionIdAddress: rftCollectionAddress} = await createRefungibleCollection(api, web3, owner);371 const {collectionIdAddress: rftCollectionAddress} = await createRFTCollection(api, web3, owner);372 const refungibleContract = uniqueRefungible(web3, rftCollectionAddress, owner);372 const refungibleContract = uniqueRefungible(web3, rftCollectionAddress, owner);373 const rftTokenId = await refungibleContract.methods.nextTokenId().call();373 const rftTokenId = await refungibleContract.methods.nextTokenId().call();374 await refungibleContract.methods.mint(owner, rftTokenId).send();374 await refungibleContract.methods.mint(owner, rftTokenId).send();381 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);381 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);382382383 const {fractionalizer} = await initFractionalizer(api, web3, privateKeyWrapper, owner);383 const {fractionalizer} = await initFractionalizer(api, web3, privateKeyWrapper, owner);384 const {collectionIdAddress: rftCollectionAddress} = await createRefungibleCollection(api, web3, owner);384 const {collectionIdAddress: rftCollectionAddress} = await createRFTCollection(api, web3, owner);385 const refungibleContract = uniqueRefungible(web3, rftCollectionAddress, owner);385 const refungibleContract = uniqueRefungible(web3, rftCollectionAddress, owner);386 const rftTokenId = await refungibleContract.methods.nextTokenId().call();386 const rftTokenId = await refungibleContract.methods.nextTokenId().call();387 await refungibleContract.methods.mint(owner, rftTokenId).send();387 await refungibleContract.methods.mint(owner, rftTokenId).send();392392393 itWeb3('call rft2nft for RFT token that was not minted by fractionalizer contract', async ({api, web3, privateKeyWrapper}) => {393 itWeb3('call rft2nft for RFT token that was not minted by fractionalizer contract', async ({api, web3, privateKeyWrapper}) => {394 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);394 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);395 const {collectionIdAddress: rftCollectionAddress} = await createRefungibleCollection(api, web3, owner);395 const {collectionIdAddress: rftCollectionAddress} = await createRFTCollection(api, web3, owner);396396397 const fractionalizer = await deployFractionalizer(web3, owner);397 const fractionalizer = await deployFractionalizer(web3, owner);398 const refungibleContract = uniqueRefungible(web3, rftCollectionAddress, owner);398 const refungibleContract = uniqueRefungible(web3, rftCollectionAddress, owner);tests/src/eth/fungibleAbi.jsondiffbeforeafterboth76 "stateMutability": "nonpayable",76 "stateMutability": "nonpayable",77 "type": "function"77 "type": "function"78 },78 },79 {80 "inputs": [81 { "internalType": "uint256", "name": "user", "type": "uint256" }82 ],83 "name": "addToCollectionAllowListSubstrate",84 "outputs": [],85 "stateMutability": "nonpayable",86 "type": "function"87 },79 {88 {80 "inputs": [89 "inputs": [81 { "internalType": "address", "name": "owner", "type": "address" },90 { "internalType": "address", "name": "owner", "type": "address" },86 "stateMutability": "view",95 "stateMutability": "view",87 "type": "function"96 "type": "function"88 },97 },98 {99 "inputs": [100 { "internalType": "address", "name": "user", "type": "address" }101 ],102 "name": "allowed",103 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],104 "stateMutability": "view",105 "type": "function"106 },89 {107 {90 "inputs": [108 "inputs": [91 { "internalType": "address", "name": "spender", "type": "address" },109 { "internalType": "address", "name": "spender", "type": "address" },115 "stateMutability": "nonpayable",133 "stateMutability": "nonpayable",116 "type": "function"134 "type": "function"117 },135 },136 {137 "inputs": [],138 "name": "collectionOwner",139 "outputs": [140 {141 "components": [142 { "internalType": "address", "name": "field_0", "type": "address" },143 { "internalType": "uint256", "name": "field_1", "type": "uint256" }144 ],145 "internalType": "struct Tuple6",146 "name": "",147 "type": "tuple"148 }149 ],150 "stateMutability": "view",151 "type": "function"152 },118 {153 {119 "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],154 "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],120 "name": "collectionProperty",155 "name": "collectionProperty",260 "stateMutability": "nonpayable",295 "stateMutability": "nonpayable",261 "type": "function"296 "type": "function"262 },297 },298 {299 "inputs": [300 { "internalType": "uint256", "name": "user", "type": "uint256" }301 ],302 "name": "removeFromCollectionAllowListSubstrate",303 "outputs": [],304 "stateMutability": "nonpayable",305 "type": "function"306 },263 {307 {264 "inputs": [{ "internalType": "uint8", "name": "mode", "type": "uint8" }],308 "inputs": [{ "internalType": "uint8", "name": "mode", "type": "uint8" }],265 "name": "setCollectionAccess",309 "name": "setCollectionAccess",tests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth107 "stateMutability": "nonpayable",107 "stateMutability": "nonpayable",108 "type": "function"108 "type": "function"109 },109 },110 {111 "inputs": [112 { "internalType": "uint256", "name": "user", "type": "uint256" }113 ],114 "name": "addToCollectionAllowListSubstrate",115 "outputs": [],116 "stateMutability": "nonpayable",117 "type": "function"118 },119 {120 "inputs": [121 { "internalType": "address", "name": "user", "type": "address" }122 ],123 "name": "allowed",124 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],125 "stateMutability": "view",126 "type": "function"127 },110 {128 {111 "inputs": [129 "inputs": [112 { "internalType": "address", "name": "approved", "type": "address" },130 { "internalType": "address", "name": "approved", "type": "address" },145 "stateMutability": "nonpayable",163 "stateMutability": "nonpayable",146 "type": "function"164 "type": "function"147 },165 },166 {167 "inputs": [],168 "name": "collectionOwner",169 "outputs": [170 {171 "components": [172 { "internalType": "address", "name": "field_0", "type": "address" },173 { "internalType": "uint256", "name": "field_1", "type": "uint256" }174 ],175 "internalType": "struct Tuple17",176 "name": "",177 "type": "tuple"178 }179 ],180 "stateMutability": "view",181 "type": "function"182 },148 {183 {149 "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],184 "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],150 "name": "collectionProperty",185 "name": "collectionProperty",374 "stateMutability": "nonpayable",409 "stateMutability": "nonpayable",375 "type": "function"410 "type": "function"376 },411 },412 {413 "inputs": [414 { "internalType": "uint256", "name": "user", "type": "uint256" }415 ],416 "name": "removeFromCollectionAllowListSubstrate",417 "outputs": [],418 "stateMutability": "nonpayable",419 "type": "function"420 },377 {421 {378 "inputs": [422 "inputs": [379 { "internalType": "address", "name": "from", "type": "address" },423 { "internalType": "address", "name": "from", "type": "address" },tests/src/eth/reFungible.test.tsdiffbeforeafterboth26 itWeb3('totalSupply', async ({api, web3, privateKeyWrapper}) => {26 itWeb3('totalSupply', async ({api, web3, privateKeyWrapper}) => {27 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);27 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);28 const helper = evmCollectionHelpers(web3, caller);28 const helper = evmCollectionHelpers(web3, caller);29 const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();29 const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();30 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);30 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);31 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});31 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});32 const nextTokenId = await contract.methods.nextTokenId().call();32 const nextTokenId = await contract.methods.nextTokenId().call();38 itWeb3('balanceOf', async ({api, web3, privateKeyWrapper}) => {38 itWeb3('balanceOf', async ({api, web3, privateKeyWrapper}) => {39 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);39 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);40 const helper = evmCollectionHelpers(web3, caller);40 const helper = evmCollectionHelpers(web3, caller);41 const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();41 const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();42 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);42 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);43 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});43 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});444463 itWeb3('ownerOf', async ({api, web3, privateKeyWrapper}) => {63 itWeb3('ownerOf', async ({api, web3, privateKeyWrapper}) => {64 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);64 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);65 const helper = evmCollectionHelpers(web3, caller);65 const helper = evmCollectionHelpers(web3, caller);66 const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();66 const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();67 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);67 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);68 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});68 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});696979 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);79 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);80 const receiver = createEthAccount(web3);80 const receiver = createEthAccount(web3);81 const helper = evmCollectionHelpers(web3, caller);81 const helper = evmCollectionHelpers(web3, caller);82 const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();82 const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();83 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);83 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);84 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});84 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});8585103 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);103 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);104 const receiver = createEthAccount(web3);104 const receiver = createEthAccount(web3);105 const helper = evmCollectionHelpers(web3, caller);105 const helper = evmCollectionHelpers(web3, caller);106 const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();106 const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();107 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);107 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);108 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});108 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});109109130 itWeb3('Can perform mint()', async ({web3, api, privateKeyWrapper}) => {130 itWeb3('Can perform mint()', async ({web3, api, privateKeyWrapper}) => {131 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);131 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);132 const helper = evmCollectionHelpers(web3, owner);132 const helper = evmCollectionHelpers(web3, owner);133 let result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();133 let result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();134 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);134 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);135 const receiver = createEthAccount(web3);135 const receiver = createEthAccount(web3);136 const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});136 const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});163 itWeb3('Can perform mintBulk()', async ({web3, api, privateKeyWrapper}) => {163 itWeb3('Can perform mintBulk()', async ({web3, api, privateKeyWrapper}) => {164 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);164 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);165 const helper = evmCollectionHelpers(web3, caller);165 const helper = evmCollectionHelpers(web3, caller);166 const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();166 const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();167 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);167 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);168 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});168 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});169169221 itWeb3('Can perform burn()', async ({web3, api, privateKeyWrapper}) => {221 itWeb3('Can perform burn()', async ({web3, api, privateKeyWrapper}) => {222 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);222 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);223 const helper = evmCollectionHelpers(web3, caller);223 const helper = evmCollectionHelpers(web3, caller);224 const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();224 const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();225 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);225 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);226 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});226 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});227227247 itWeb3('Can perform transferFrom()', async ({web3, api, privateKeyWrapper}) => {247 itWeb3('Can perform transferFrom()', async ({web3, api, privateKeyWrapper}) => {248 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);248 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);249 const helper = evmCollectionHelpers(web3, caller);249 const helper = evmCollectionHelpers(web3, caller);250 const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();250 const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();251 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);251 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);252 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});252 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});253253304 itWeb3('Can perform transfer()', async ({web3, api, privateKeyWrapper}) => {304 itWeb3('Can perform transfer()', async ({web3, api, privateKeyWrapper}) => {305 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);305 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);306 const helper = evmCollectionHelpers(web3, caller);306 const helper = evmCollectionHelpers(web3, caller);307 const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();307 const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();308 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);308 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);309 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});309 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});310310344 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);344 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);345 const receiver = createEthAccount(web3);345 const receiver = createEthAccount(web3);346 const helper = evmCollectionHelpers(web3, caller);346 const helper = evmCollectionHelpers(web3, caller);347 const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();347 const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();348 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);348 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);349 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});349 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});350350376 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);376 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);377 const receiver = createEthAccount(web3);377 const receiver = createEthAccount(web3);378 const helper = evmCollectionHelpers(web3, caller);378 const helper = evmCollectionHelpers(web3, caller);379 const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();379 const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();380 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);380 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);381 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});381 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});382382413 itWeb3('transferFrom() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {413 itWeb3('transferFrom() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {414 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);414 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);415 const helper = evmCollectionHelpers(web3, caller);415 const helper = evmCollectionHelpers(web3, caller);416 const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();416 const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();417 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);417 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);418 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});418 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});419419430 itWeb3('transfer() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {430 itWeb3('transfer() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {431 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);431 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);432 const helper = evmCollectionHelpers(web3, caller);432 const helper = evmCollectionHelpers(web3, caller);433 const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();433 const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();434 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);434 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);435 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});435 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});436436tests/src/eth/reFungibleAbi.jsondiffbeforeafterboth107 "stateMutability": "nonpayable",107 "stateMutability": "nonpayable",108 "type": "function"108 "type": "function"109 },109 },110 {111 "inputs": [112 { "internalType": "uint256", "name": "user", "type": "uint256" }113 ],114 "name": "addToCollectionAllowListSubstrate",115 "outputs": [],116 "stateMutability": "nonpayable",117 "type": "function"118 },119 {120 "inputs": [121 { "internalType": "address", "name": "user", "type": "address" }122 ],123 "name": "allowed",124 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],125 "stateMutability": "view",126 "type": "function"127 },110 {128 {111 "inputs": [129 "inputs": [112 { "internalType": "address", "name": "approved", "type": "address" },130 { "internalType": "address", "name": "approved", "type": "address" },145 "stateMutability": "nonpayable",163 "stateMutability": "nonpayable",146 "type": "function"164 "type": "function"147 },165 },166 {167 "inputs": [],168 "name": "collectionOwner",169 "outputs": [170 {171 "components": [172 { "internalType": "address", "name": "field_0", "type": "address" },173 { "internalType": "uint256", "name": "field_1", "type": "uint256" }174 ],175 "internalType": "struct Tuple17",176 "name": "",177 "type": "tuple"178 }179 ],180 "stateMutability": "view",181 "type": "function"182 },148 {183 {149 "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],184 "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],150 "name": "collectionProperty",185 "name": "collectionProperty",374 "stateMutability": "nonpayable",409 "stateMutability": "nonpayable",375 "type": "function"410 "type": "function"376 },411 },412 {413 "inputs": [414 { "internalType": "uint256", "name": "user", "type": "uint256" }415 ],416 "name": "removeFromCollectionAllowListSubstrate",417 "outputs": [],418 "stateMutability": "nonpayable",419 "type": "function"420 },377 {421 {378 "inputs": [422 "inputs": [379 { "internalType": "address", "name": "from", "type": "address" },423 { "internalType": "address", "name": "from", "type": "address" },tests/src/eth/reFungibleToken.test.tsdiffbeforeafterboth15// 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/>.161617import {approve, createCollection, createRefungibleToken, transfer, transferFrom, UNIQUE, requirePallets, Pallets} from '../util/helpers';17import {approve, createCollection, createRefungibleToken, transfer, transferFrom, UNIQUE, requirePallets, Pallets} from '../util/helpers';18import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, createRefungibleCollection, evmCollection, evmCollectionHelpers, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, tokenIdToAddress, transferBalanceToEth, uniqueRefungible, uniqueRefungibleToken} from './util/helpers';18import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, createRFTCollection, evmCollection, evmCollectionHelpers, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, tokenIdToAddress, transferBalanceToEth, uniqueRefungible, uniqueRefungibleToken} from './util/helpers';191920import chai from 'chai';20import chai from 'chai';21import chaiAsPromised from 'chai-as-promised';21import chaiAsPromised from 'chai-as-promised';458 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);458 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);459 const receiver = await createEthAccountWithBalance(api, web3, privateKeyWrapper);459 const receiver = await createEthAccountWithBalance(api, web3, privateKeyWrapper);460 const helper = evmCollectionHelpers(web3, caller);460 const helper = evmCollectionHelpers(web3, caller);461 const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();461 const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();462 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);462 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);463 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});463 const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});464464658 itWeb3('Default parent token address and id', async ({api, web3, privateKeyWrapper}) => {658 itWeb3('Default parent token address and id', async ({api, web3, privateKeyWrapper}) => {659 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);659 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);660660661 const {collectionIdAddress, collectionId} = await createRefungibleCollection(api, web3, owner);661 const {collectionIdAddress, collectionId} = await createRFTCollection(api, web3, owner);662 const refungibleContract = uniqueRefungible(web3, collectionIdAddress, owner);662 const refungibleContract = uniqueRefungible(web3, collectionIdAddress, owner);663 const refungibleTokenId = await refungibleContract.methods.nextTokenId().call();663 const refungibleTokenId = await refungibleContract.methods.nextTokenId().call();664 await refungibleContract.methods.mint(owner, refungibleTokenId).send();664 await refungibleContract.methods.mint(owner, refungibleTokenId).send();tests/src/eth/util/contractHelpersAbi.jsondiffbeforeafterboth126 "stateMutability": "view",126 "stateMutability": "view",127 "type": "function"127 "type": "function"128 },128 },129 {130 "inputs": [131 {132 "internalType": "address",133 "name": "contractAddress",134 "type": "address"135 }136 ],137 "name": "getSponsoringFeeLimit",138 "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],139 "stateMutability": "view",140 "type": "function"141 },129 {142 {130 "inputs": [143 "inputs": [131 {144 {205 "stateMutability": "nonpayable",218 "stateMutability": "nonpayable",206 "type": "function"219 "type": "function"207 },220 },221 {222 "inputs": [223 {224 "internalType": "address",225 "name": "contractAddress",226 "type": "address"227 },228 { "internalType": "uint256", "name": "feeLimit", "type": "uint256" }229 ],230 "name": "setSponsoringFeeLimit",231 "outputs": [],232 "stateMutability": "nonpayable",233 "type": "function"234 },208 {235 {209 "inputs": [236 "inputs": [210 {237 {tests/src/eth/util/helpers.tsdiffbeforeafterboth141 expect(result.success).to.be.true;141 expect(result.success).to.be.true;142}142}143143144export async function createRefungibleCollection(api: ApiPromise, web3: Web3, owner: string) {144export async function createRFTCollection(api: ApiPromise, web3: Web3, owner: string) {145 const collectionHelper = evmCollectionHelpers(web3, owner);145 const collectionHelper = evmCollectionHelpers(web3, owner);146 const result = await collectionHelper.methods146 const result = await collectionHelper.methods147 .createRefungibleCollection('A', 'B', 'C')147 .createRFTCollection('A', 'B', 'C')148 .send();148 .send();149 return await getCollectionAddressFromResult(api, result);149 return await getCollectionAddressFromResult(api, result);150}150}tests/src/util/helpers.tsdiffbeforeafterboth1677 });1677 });1678}1678}167916791680export async function isAllowlisted(api: ApiPromise, collectionId: number, address: string | CrossAccountId) {1680export async function isAllowlisted(api: ApiPromise, collectionId: number, address: string | CrossAccountId | IKeyringPair) {1681 return (await api.rpc.unique.allowed(collectionId, normalizeAccountId(address))).toJSON();1681 return (await api.rpc.unique.allowed(collectionId, normalizeAccountId(address))).toJSON();1682}1682}16831683tests/src/util/playgrounds/unique.tsdiffbeforeafterboth729 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionAdminRemoved');729 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionAdminRemoved');730 }730 }731732 /**733 * Check if user is in allow list.734 * 735 * @param collectionId ID of collection736 * @param user Account to check737 * @example await getAdmins(1)738 * @returns is user in allow list739 */740 async allowed(collectionId: number, user: ICrossAccountId): Promise<boolean> {741 return (await this.helper.callRpc('api.rpc.unique.allowed', [collectionId, user])).toJSON();742 }731743732 /**744 /**733 * Adds an address to allow list745 * Adds an address to allow list