difftreelog
Merge branch 'develop' into feature/CORE-386_1
in: master
54 files changed
Makefilediffbeforeafterboth--- a/Makefile
+++ b/Makefile
@@ -93,5 +93,9 @@
bench-structure:
make _bench PALLET=structure
+.PHONY: bench-rmrk-core
+bench-rmrk-core:
+ make _bench PALLET=proxy-rmrk-core
+
.PHONY: bench
-bench: bench-evm-migration bench-unique bench-structure bench-fungible bench-refungible bench-nonfungible
+bench: bench-evm-migration bench-unique bench-structure bench-fungible bench-refungible bench-nonfungible bench-rmrk-core
pallets/common/src/benchmarking.rsdiffbeforeafterboth--- a/pallets/common/src/benchmarking.rs
+++ b/pallets/common/src/benchmarking.rs
@@ -109,7 +109,7 @@
create_collection_raw(
owner,
CollectionMode::NFT,
- |owner, data| <Pallet<T>>::init_collection(owner, data),
+ |owner, data| <Pallet<T>>::init_collection(owner, data, true),
|h| h,
)
}
pallets/common/src/dispatch.rsdiffbeforeafterboth--- a/pallets/common/src/dispatch.rs
+++ b/pallets/common/src/dispatch.rs
@@ -11,7 +11,7 @@
use crate::{pallet::Config, CommonCollectionOperations, CollectionHandle};
// TODO: move to benchmarking
-/// Price of [`dispatch_call`] call with noop `call` argument
+/// Price of [`dispatch_tx`] call with noop `call` argument
pub fn dispatch_weight<T: Config>() -> Weight {
// Read collection
<T as frame_system::Config>::DbWeight::get().reads(1)
@@ -21,7 +21,7 @@
}
/// Helper function to implement substrate calls for common collection methods
-pub fn dispatch_call<
+pub fn dispatch_tx<
T: Config,
C: FnOnce(&dyn CommonCollectionOperations<T>) -> DispatchResultWithPostInfo,
>(
pallets/common/src/lib.rsdiffbeforeafterboth--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -427,7 +427,7 @@
/// Target collection doesn't supports this operation
UnsupportedOperation,
- /// Not sufficient founds to perform action
+ /// Not sufficient funds to perform action
NotSufficientFounds,
/// Collection has nesting disabled
pallets/nonfungible/src/benchmarking.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/benchmarking.rs
+++ b/pallets/nonfungible/src/benchmarking.rs
@@ -51,7 +51,7 @@
create_collection_raw(
owner,
CollectionMode::NFT,
- <Pallet<T>>::init_collection,
+ |owner, data| <Pallet<T>>::init_collection(owner, data, true),
NonfungibleHandle::cast,
)
}
@@ -99,7 +99,7 @@
sender: cross_from_sub(owner); burner: cross_sub;
};
let item = create_max_item(&collection, &sender, burner.clone())?;
- }: {<Pallet<T>>::burn_recursively(&collection, &burner, item, &Unlimited, &Unlimited)}
+ }: {<Pallet<T>>::burn_recursively(&collection, &burner, item, &Unlimited, &Unlimited)?}
burn_recursively_breadth_plus_self_plus_self_per_each_raw {
let b in 0..200;
@@ -111,7 +111,7 @@
for i in 0..b {
create_max_item(&collection, &sender, T::CrossTokenAddressMapping::token_to_address(collection.id, item))?;
}
- }: {<Pallet<T>>::burn_recursively(&collection, &burner, item, &Unlimited, &Unlimited)}
+ }: {<Pallet<T>>::burn_recursively(&collection, &burner, item, &Unlimited, &Unlimited)?}
transfer {
bench_init!{
@@ -183,7 +183,7 @@
value: property_value(),
}).collect::<Vec<_>>();
let item = create_max_item(&collection, &owner, owner.clone())?;
- }: {<Pallet<T>>::set_token_properties(&collection, &owner, item, props)?}
+ }: {<Pallet<T>>::set_token_properties(&collection, &owner, item, props, false)?}
delete_token_properties {
let b in 0..MAX_PROPERTIES_PER_ITEM;
@@ -205,7 +205,7 @@
value: property_value(),
}).collect::<Vec<_>>();
let item = create_max_item(&collection, &owner, owner.clone())?;
- <Pallet<T>>::set_token_properties(&collection, &owner, item, props)?;
+ <Pallet<T>>::set_token_properties(&collection, &owner, item, props, false)?;
let to_delete = (0..b).map(|k| property_key(k as usize)).collect::<Vec<_>>();
}: {<Pallet<T>>::delete_token_properties(&collection, &owner, item, to_delete)?}
}
pallets/proxy-rmrk-core/src/benchmarking.rsdiffbeforeafterboth--- /dev/null
+++ b/pallets/proxy-rmrk-core/src/benchmarking.rs
@@ -0,0 +1,26 @@
+use sp_std::vec;
+
+use frame_benchmarking::{benchmarks, account};
+use frame_system::RawOrigin;
+use frame_support::{
+ traits::{Currency, Get},
+ BoundedVec,
+};
+
+use crate::{Config, Pallet, Call};
+
+const SEED: u32 = 1;
+
+fn create_data<S: Get<u32>>() -> BoundedVec<u8, S> {
+ vec![0; S::get() as usize].try_into().expect("size == S")
+}
+
+benchmarks! {
+ create_collection {
+ let caller = account("caller", 0, SEED);
+ <T as pallet_common::Config>::Currency::deposit_creating(&caller, T::CollectionCreationPrice::get());
+ let metadata = create_data();
+ // TODO: Fix CollectionTokenPrefixLimitExceeded with create_data
+ let symbol = vec![].try_into().expect("0 <= x");
+ }: _(RawOrigin::Signed(caller), metadata, None, symbol)
+}
pallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-core/src/lib.rs
+++ b/pallets/proxy-rmrk-core/src/lib.rs
@@ -31,9 +31,15 @@
pub use pallet::*;
+#[cfg(feature = "runtime-benchmarks")]
+pub mod benchmarking;
pub mod misc;
pub mod property;
+pub mod weights;
+
+pub type SelfWeightOf<T> = <T as Config>::WeightInfo;
+use weights::WeightInfo;
use misc::*;
pub use property::*;
@@ -51,6 +57,7 @@
frame_system::Config + pallet_common::Config + pallet_nonfungible::Config + account::Config
{
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
+ type WeightInfo: WeightInfo;
}
#[pallet::storage]
@@ -169,8 +176,9 @@
#[pallet::call]
impl<T: Config> Pallet<T> {
- #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
+ /// Create a collection
#[transactional]
+ #[pallet::weight(<SelfWeightOf<T>>::create_collection())]
pub fn create_collection(
origin: OriginFor<T>,
metadata: RmrkString,
@@ -222,6 +230,7 @@
Ok(())
}
+ /// destroy collection
#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn destroy_collection(
@@ -248,6 +257,12 @@
Ok(())
}
+ /// Change the issuer of a collection
+ ///
+ /// Parameters:
+ /// - `origin`: sender of the transaction
+ /// - `collection_id`: collection id of the nft to change issuer of
+ /// - `new_issuer`: Collection's new issuer
#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn change_collection_issuer(
@@ -278,6 +293,7 @@
Ok(())
}
+ /// lock collection
#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn lock_collection(
@@ -309,6 +325,16 @@
Ok(())
}
+ /// Mints an NFT in the specified collection
+ /// Sets metadata and the royalty attribute
+ ///
+ /// Parameters:
+ /// - `collection_id`: The class of the asset to be minted.
+ /// - `nft_id`: The nft value of the asset to be minted.
+ /// - `recipient`: Receiver of the royalty
+ /// - `royalty`: Permillage reward from each trade for the Recipient
+ /// - `metadata`: Arbitrary data about an nft, e.g. IPFS hash
+ /// - `transferable`: Ability to transfer this NFT
#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn mint_nft(
@@ -378,6 +404,7 @@
Ok(())
}
+ /// burn nft
#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn burn_nft(
@@ -409,6 +436,13 @@
Ok(())
}
+ /// Transfers a NFT from an Account or NFT A to another Account or NFT B
+ ///
+ /// Parameters:
+ /// - `origin`: sender of the transaction
+ /// - `rmrk_collection_id`: collection id of the nft to be transferred
+ /// - `rmrk_nft_id`: nft id of the nft to be transferred
+ /// - `new_owner`: new owner of the nft which can be either an account or a NFT
#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn send(
@@ -462,7 +496,7 @@
let target_nft_budget = budget::Value::new(NESTING_BUDGET);
- let target_nft_owner = <PalletStructure<T>>::get_checked_indirect_owner(
+ let target_nft_owner = <PalletStructure<T>>::get_checked_topmost_owner(
target_collection_id,
target_nft_id.into(),
Some((collection_id, nft_id)),
@@ -513,6 +547,14 @@
Ok(())
}
+ /// Accepts an NFT sent from another account to self or owned NFT
+ ///
+ /// Parameters:
+ /// - `origin`: sender of the transaction
+ /// - `rmrk_collection_id`: collection id of the nft to be accepted
+ /// - `rmrk_nft_id`: nft id of the nft to be accepted
+ /// - `new_owner`: either origin's account ID or origin-owned NFT, whichever the NFT was
+ /// sent to
#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn accept_nft(
@@ -582,6 +624,12 @@
Ok(())
}
+ /// Rejects an NFT sent from another account to self or owned NFT
+ ///
+ /// Parameters:
+ /// - `origin`: sender of the transaction
+ /// - `rmrk_collection_id`: collection id of the nft to be accepted
+ /// - `rmrk_nft_id`: nft id of the nft to be accepted
#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn reject_nft(
@@ -618,6 +666,7 @@
Ok(())
}
+ /// accept the addition of a new resource to an existing NFT
#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn accept_resource(
@@ -674,6 +723,7 @@
Ok(())
}
+ /// accept the removal of a resource of an existing NFT
#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn accept_resource_removal(
@@ -731,6 +781,7 @@
Ok(())
}
+ /// set a custom value on an NFT
#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn set_property(
@@ -790,6 +841,7 @@
Ok(())
}
+ /// set a different order of resource priority
#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn set_priority(
@@ -828,6 +880,7 @@
Ok(())
}
+ /// Create basic resource
#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn add_basic_resource(
@@ -865,6 +918,7 @@
Ok(())
}
+ /// Create composable resource
#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn add_composable_resource(
@@ -905,6 +959,7 @@
Ok(())
}
+ /// Create slot resource
#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn add_slot_resource(
@@ -944,6 +999,7 @@
Ok(())
}
+ /// remove resource
#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn remove_resource(
pallets/proxy-rmrk-core/src/misc.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-core/src/misc.rs
+++ b/pallets/proxy-rmrk-core/src/misc.rs
@@ -1,3 +1,19 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
use super::*;
use codec::{Encode, Decode, Error};
pallets/proxy-rmrk-core/src/property.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-core/src/property.rs
+++ b/pallets/proxy-rmrk-core/src/property.rs
@@ -1,3 +1,19 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
use super::*;
use core::convert::AsRef;
pallets/proxy-rmrk-core/src/weights.rsdiffbeforeafterboth--- /dev/null
+++ b/pallets/proxy-rmrk-core/src/weights.rs
@@ -0,0 +1,74 @@
+// Template adopted from https://github.com/paritytech/substrate/blob/master/.maintain/frame-weight-template.hbs
+
+//! Autogenerated weights for pallet_proxy_rmrk_core
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
+//! DATE: 2022-06-09, STEPS: `50`, REPEAT: 200, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024
+
+// Executed Command:
+// target/release/unique-collator
+// benchmark
+// pallet
+// --pallet
+// pallet-proxy-rmrk-core
+// --wasm-execution
+// compiled
+// --extrinsic
+// *
+// --template
+// .maintain/frame-weight-template.hbs
+// --steps=50
+// --repeat=200
+// --heap-pages=4096
+// --output=./pallets/proxy-rmrk-core/src/weights.rs
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+#![allow(clippy::unnecessary_cast)]
+
+use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
+use sp_std::marker::PhantomData;
+
+/// Weight functions needed for pallet_proxy_rmrk_core.
+pub trait WeightInfo {
+ fn create_collection() -> Weight;
+}
+
+/// Weights for pallet_proxy_rmrk_core using the Substrate node and recommended hardware.
+pub struct SubstrateWeight<T>(PhantomData<T>);
+impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
+ // Storage: Common CreatedCollectionCount (r:1 w:1)
+ // Storage: Common DestroyedCollectionCount (r:1 w:0)
+ // Storage: System Account (r:2 w:2)
+ // Storage: RmrkCore CollectionIndex (r:1 w:1)
+ // Storage: Common CollectionPropertyPermissions (r:0 w:1)
+ // Storage: Common CollectionProperties (r:0 w:1)
+ // Storage: Common CollectionById (r:0 w:1)
+ // Storage: RmrkCore UniqueCollectionId (r:0 w:1)
+ // Storage: RmrkCore RmrkInernalCollectionId (r:0 w:1)
+ fn create_collection() -> Weight {
+ (76_647_000 as Weight)
+ .saturating_add(T::DbWeight::get().reads(5 as Weight))
+ .saturating_add(T::DbWeight::get().writes(9 as Weight))
+ }
+}
+
+// For backwards compatibility and tests
+impl WeightInfo for () {
+ // Storage: Common CreatedCollectionCount (r:1 w:1)
+ // Storage: Common DestroyedCollectionCount (r:1 w:0)
+ // Storage: System Account (r:2 w:2)
+ // Storage: RmrkCore CollectionIndex (r:1 w:1)
+ // Storage: Common CollectionPropertyPermissions (r:0 w:1)
+ // Storage: Common CollectionProperties (r:0 w:1)
+ // Storage: Common CollectionById (r:0 w:1)
+ // Storage: RmrkCore UniqueCollectionId (r:0 w:1)
+ // Storage: RmrkCore RmrkInernalCollectionId (r:0 w:1)
+ fn create_collection() -> Weight {
+ (76_647_000 as Weight)
+ .saturating_add(RocksDbWeight::get().reads(5 as Weight))
+ .saturating_add(RocksDbWeight::get().writes(9 as Weight))
+ }
+}
pallets/proxy-rmrk-equip/src/lib.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-equip/src/lib.rs
+++ b/pallets/proxy-rmrk-equip/src/lib.rs
@@ -74,6 +74,15 @@
#[pallet::call]
impl<T: Config> Pallet<T> {
+ /// Creates a new Base.
+ /// Modeled after [base interaction](https://github.com/rmrk-team/rmrk-spec/blob/master/standards/rmrk2.0.0/interactions/base.md)
+ ///
+ /// Parameters:
+ /// - origin: Caller, will be assigned as the issuer of the Base
+ /// - base_type: media type, e.g. "svg"
+ /// - symbol: arbitrary client-chosen symbol
+ /// - parts: array of Fixed and Slot parts composing the base, confined in length by
+ /// RmrkPartsLimit
#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn create_base(
@@ -137,6 +146,19 @@
Ok(())
}
+ /// Adds a Theme to a Base.
+ /// Modeled after [themeadd interaction](https://github.com/rmrk-team/rmrk-spec/blob/master/standards/rmrk2.0.0/interactions/themeadd.md)
+ /// Themes are stored in the Themes storage
+ /// A Theme named "default" is required prior to adding other Themes.
+ ///
+ /// Parameters:
+ /// - origin: The caller of the function, must be issuer of the base
+ /// - base_id: The Base containing the Theme to be updated
+ /// - theme: The Theme to add to the Base. A Theme has a name and properties, which are an
+ /// array of [key, value, inherit].
+ /// - key: arbitrary BoundedString, defined by client
+ /// - value: arbitrary BoundedString, defined by client
+ /// - inherit: optional bool
#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn theme_add(
pallets/structure/src/lib.rsdiffbeforeafterboth--- a/pallets/structure/src/lib.rs
+++ b/pallets/structure/src/lib.rs
@@ -149,7 +149,7 @@
})
}
- pub fn get_checked_indirect_owner(
+ pub fn get_checked_topmost_owner(
collection: CollectionId,
token: TokenId,
for_nest: Option<(CollectionId, TokenId)>,
@@ -203,7 +203,7 @@
None => user,
};
- Self::get_checked_indirect_owner(collection, token, for_nest, budget)
+ Self::get_checked_topmost_owner(collection, token, for_nest, budget)
.map(|indirect_owner| indirect_owner == target_parent)
}
pallets/unique/src/lib.rsdiffbeforeafterboth--- a/pallets/unique/src/lib.rs
+++ b/pallets/unique/src/lib.rs
@@ -44,7 +44,7 @@
};
use pallet_evm::account::CrossAccountId;
use pallet_common::{
- CollectionHandle, Pallet as PalletCommon, CommonWeightInfo, dispatch::dispatch_call,
+ CollectionHandle, Pallet as PalletCommon, CommonWeightInfo, dispatch::dispatch_tx,
dispatch::CollectionDispatch,
};
pub mod eth;
@@ -581,7 +581,7 @@
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
let budget = budget::Value::new(NESTING_BUDGET);
- dispatch_call::<T, _>(collection_id, |d| d.create_item(sender, owner, data, &budget))
+ dispatch_tx::<T, _>(collection_id, |d| d.create_item(sender, owner, data, &budget))
}
/// This method creates multiple items in a collection created with CreateCollection method.
@@ -609,7 +609,7 @@
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
let budget = budget::Value::new(NESTING_BUDGET);
- dispatch_call::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data, &budget))
+ dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data, &budget))
}
#[weight = T::CommonWeightInfo::set_collection_properties(properties.len() as u32)]
@@ -623,7 +623,7 @@
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
- dispatch_call::<T, _>(collection_id, |d| d.set_collection_properties(sender, properties))
+ dispatch_tx::<T, _>(collection_id, |d| d.set_collection_properties(sender, properties))
}
#[weight = T::CommonWeightInfo::delete_collection_properties(property_keys.len() as u32)]
@@ -637,7 +637,7 @@
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
- dispatch_call::<T, _>(collection_id, |d| d.delete_collection_properties(&sender, property_keys))
+ dispatch_tx::<T, _>(collection_id, |d| d.delete_collection_properties(&sender, property_keys))
}
#[weight = T::CommonWeightInfo::set_token_properties(properties.len() as u32)]
@@ -652,7 +652,7 @@
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
- dispatch_call::<T, _>(collection_id, |d| d.set_token_properties(sender, token_id, properties))
+ dispatch_tx::<T, _>(collection_id, |d| d.set_token_properties(sender, token_id, properties))
}
#[weight = T::CommonWeightInfo::delete_token_properties(property_keys.len() as u32)]
@@ -667,7 +667,7 @@
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
- dispatch_call::<T, _>(collection_id, |d| d.delete_token_properties(sender, token_id, property_keys))
+ dispatch_tx::<T, _>(collection_id, |d| d.delete_token_properties(sender, token_id, property_keys))
}
#[weight = T::CommonWeightInfo::set_property_permissions(property_permissions.len() as u32)]
@@ -681,7 +681,7 @@
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
- dispatch_call::<T, _>(collection_id, |d| d.set_property_permissions(&sender, property_permissions))
+ dispatch_tx::<T, _>(collection_id, |d| d.set_property_permissions(&sender, property_permissions))
}
#[weight = T::CommonWeightInfo::create_multiple_items_ex(&data)]
@@ -690,7 +690,7 @@
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
let budget = budget::Value::new(NESTING_BUDGET);
- dispatch_call::<T, _>(collection_id, |d| d.create_multiple_items_ex(sender, data, &budget))
+ dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items_ex(sender, data, &budget))
}
// TODO! transaction weight
@@ -738,7 +738,7 @@
pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
- let post_info = dispatch_call::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))?;
+ let post_info = dispatch_tx::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))?;
if value == 1 {
<NftTransferBasket<T>>::remove(collection_id, item_id);
<NftApproveBasket<T>>::remove(collection_id, item_id);
@@ -771,7 +771,7 @@
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
let budget = budget::Value::new(NESTING_BUDGET);
- dispatch_call::<T, _>(collection_id, |d| d.burn_from(sender, from, item_id, value, &budget))
+ dispatch_tx::<T, _>(collection_id, |d| d.burn_from(sender, from, item_id, value, &budget))
}
/// Change ownership of the token.
@@ -803,7 +803,7 @@
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
let budget = budget::Value::new(NESTING_BUDGET);
- dispatch_call::<T, _>(collection_id, |d| d.transfer(sender, recipient, item_id, value, &budget))
+ dispatch_tx::<T, _>(collection_id, |d| d.transfer(sender, recipient, item_id, value, &budget))
}
/// Set, change, or remove approved address to transfer the ownership of the NFT.
@@ -826,7 +826,7 @@
pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
- dispatch_call::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))
+ dispatch_tx::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))
}
/// Change ownership of a NFT on behalf of the owner. See Approve method for additional information. After this method executes, the approval is removed so that the approved address will not be able to transfer this NFT again from this owner.
@@ -854,7 +854,7 @@
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
let budget = budget::Value::new(NESTING_BUDGET);
- dispatch_call::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value, &budget))
+ dispatch_tx::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value, &budget))
}
#[weight = <SelfWeightOf<T>>::set_collection_limits()]
primitives/rmrk-rpc/src/lib.rsdiffbeforeafterboth--- a/primitives/rmrk-rpc/src/lib.rs
+++ b/primitives/rmrk-rpc/src/lib.rs
@@ -1,3 +1,19 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
#![cfg_attr(not(feature = "std"), no_std)]
use sp_api::{Encode, Decode};
primitives/rmrk-traits/src/base.rsdiffbeforeafterboth--- a/primitives/rmrk-traits/src/base.rs
+++ b/primitives/rmrk-traits/src/base.rs
@@ -1,3 +1,7 @@
+// Copyright (C) 2021-2022 RMRK
+// This file is part of rmrk-substrate.
+// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
+
use codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
primitives/rmrk-traits/src/collection.rsdiffbeforeafterboth--- a/primitives/rmrk-traits/src/collection.rs
+++ b/primitives/rmrk-traits/src/collection.rs
@@ -1,3 +1,7 @@
+// Copyright (C) 2021-2022 RMRK
+// This file is part of rmrk-substrate.
+// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
+
use codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
primitives/rmrk-traits/src/lib.rsdiffbeforeafterboth--- a/primitives/rmrk-traits/src/lib.rs
+++ b/primitives/rmrk-traits/src/lib.rs
@@ -1,3 +1,7 @@
+// Copyright (C) 2021-2022 RMRK
+// This file is part of rmrk-substrate.
+// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
+
#![cfg_attr(not(feature = "std"), no_std)]
pub mod base;
primitives/rmrk-traits/src/nft.rsdiffbeforeafterboth--- a/primitives/rmrk-traits/src/nft.rs
+++ b/primitives/rmrk-traits/src/nft.rs
@@ -1,3 +1,7 @@
+// Copyright (C) 2021-2022 RMRK
+// This file is part of rmrk-substrate.
+// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
+
use codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
primitives/rmrk-traits/src/part.rsdiffbeforeafterboth--- a/primitives/rmrk-traits/src/part.rs
+++ b/primitives/rmrk-traits/src/part.rs
@@ -1,3 +1,7 @@
+// Copyright (C) 2021-2022 RMRK
+// This file is part of rmrk-substrate.
+// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
+
use codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
primitives/rmrk-traits/src/property.rsdiffbeforeafterboth--- a/primitives/rmrk-traits/src/property.rs
+++ b/primitives/rmrk-traits/src/property.rs
@@ -1,3 +1,7 @@
+// Copyright (C) 2021-2022 RMRK
+// This file is part of rmrk-substrate.
+// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
+
use codec::{Decode, Encode};
use scale_info::TypeInfo;
primitives/rmrk-traits/src/resource.rsdiffbeforeafterboth--- a/primitives/rmrk-traits/src/resource.rs
+++ b/primitives/rmrk-traits/src/resource.rs
@@ -1,3 +1,7 @@
+// Copyright (C) 2021-2022 RMRK
+// This file is part of rmrk-substrate.
+// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
+
use codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
primitives/rmrk-traits/src/serialize.rsdiffbeforeafterboth--- a/primitives/rmrk-traits/src/serialize.rs
+++ b/primitives/rmrk-traits/src/serialize.rs
@@ -1,3 +1,7 @@
+// Copyright (C) 2021-2022 RMRK
+// This file is part of rmrk-substrate.
+// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
+
use core::convert::AsRef;
use serde::ser::{self, Serialize};
primitives/rmrk-traits/src/theme.rsdiffbeforeafterboth--- a/primitives/rmrk-traits/src/theme.rs
+++ b/primitives/rmrk-traits/src/theme.rs
@@ -1,3 +1,7 @@
+// Copyright (C) 2021-2022 RMRK
+// This file is part of rmrk-substrate.
+// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
+
use codec::{Decode, Encode};
use scale_info::TypeInfo;
runtime/common/src/constants.rsdiffbeforeafterboth--- a/runtime/common/src/constants.rs
+++ b/runtime/common/src/constants.rs
@@ -1,3 +1,19 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
use sp_runtime::Perbill;
use frame_support::{
parameter_types,
runtime/common/src/dispatch.rsdiffbeforeafterboth--- a/runtime/common/src/dispatch.rs
+++ b/runtime/common/src/dispatch.rs
@@ -1,3 +1,19 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
use frame_support::{dispatch::DispatchResult, ensure};
use pallet_evm::{PrecompileHandle, PrecompileResult};
use sp_core::H160;
runtime/common/src/lib.rsdiffbeforeafterboth--- a/runtime/common/src/lib.rs
+++ b/runtime/common/src/lib.rs
@@ -1,3 +1,19 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
#![cfg_attr(not(feature = "std"), no_std)]
pub mod constants;
runtime/common/src/runtime_apis.rsdiffbeforeafterboth--- a/runtime/common/src/runtime_apis.rs
+++ b/runtime/common/src/runtime_apis.rs
@@ -1,3 +1,19 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
#[macro_export]
macro_rules! impl_common_runtime_apis {
(
@@ -331,30 +347,30 @@
.iter()
.filter_map(|(res_id)| Some(RmrkResourceInfo {
id: res_id.0,
- pending: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceAccept).unwrap(),
- pending_removal: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceRemoval).unwrap(),
- resource: match RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::ResourceType).unwrap() {
+ pending: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceAccept).ok()?,
+ pending_removal: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceRemoval).ok()?,
+ resource: match RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::ResourceType).ok()? {
ResourceType::Basic => RmrkResourceTypes::Basic(RmrkBasicResource {
- src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),
- metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),
- license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),
- thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),
+ src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).ok()?,
+ metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).ok()?,
+ license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).ok()?,
+ thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).ok()?,
}),
ResourceType::Composable => RmrkResourceTypes::Composable(RmrkComposableResource {
- parts: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Parts).unwrap(),
- base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).unwrap(),
- src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),
- metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),
- license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),
- thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),
+ parts: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Parts).ok()?,
+ base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).ok()?,
+ src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).ok()?,
+ metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).ok()?,
+ license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).ok()?,
+ thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).ok()?,
}),
ResourceType::Slot => RmrkResourceTypes::Slot(RmrkSlotResource {
- base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).unwrap(),
- src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),
- metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),
- slot: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Slot).unwrap(),
- license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),
- thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),
+ base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).ok()?,
+ src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).ok()?,
+ metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).ok()?,
+ slot: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Slot).ok()?,
+ license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).ok()?,
+ thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).ok()?,
}),
},
}))
@@ -447,12 +463,10 @@
let theme_names = collection.collection_tokens()
.iter()
.filter_map(|token_id| {
- let nft_type = RmrkCore::get_nft_type(collection_id, *token_id).unwrap();
+ let nft_type = RmrkCore::get_nft_type(collection_id, *token_id).ok()?;
match nft_type {
- Theme => Some(
- RmrkCore::get_nft_property_decoded(collection_id, *token_id, RmrkProperty::ThemeName).unwrap()
- ),
+ Theme => RmrkCore::get_nft_property_decoded(collection_id, *token_id, RmrkProperty::ThemeName).ok(),
_ => None
}
})
@@ -829,6 +843,7 @@
list_benchmark!(list, extra, pallet_fungible, Fungible);
list_benchmark!(list, extra, pallet_refungible, Refungible);
list_benchmark!(list, extra, pallet_nonfungible, Nonfungible);
+ list_benchmark!(list, extra, pallet_proxy_rmrk_core, RmrkCore);
// list_benchmark!(list, extra, pallet_evm_coder_substrate, EvmCoderSubstrate);
let storage_info = AllPalletsReversedWithSystemFirst::storage_info();
@@ -872,6 +887,7 @@
add_benchmark!(params, batches, pallet_fungible, Fungible);
add_benchmark!(params, batches, pallet_refungible, Refungible);
add_benchmark!(params, batches, pallet_nonfungible, Nonfungible);
+ add_benchmark!(params, batches, pallet_proxy_rmrk_core, RmrkCore);
// add_benchmark!(params, batches, pallet_evm_coder_substrate, EvmCoderSubstrate);
if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }
runtime/common/src/types.rsdiffbeforeafterboth--- a/runtime/common/src/types.rs
+++ b/runtime/common/src/types.rs
@@ -1,3 +1,19 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
use sp_runtime::{
traits::{Verify, IdentifyAccount, BlakeTwo256},
generic, MultiSignature,
runtime/opal/src/lib.rsdiffbeforeafterboth--- a/runtime/opal/src/lib.rs
+++ b/runtime/opal/src/lib.rs
@@ -919,6 +919,7 @@
}
impl pallet_proxy_rmrk_core::Config for Runtime {
+ type WeightInfo = pallet_proxy_rmrk_core::weights::SubstrateWeight<Self>;
type Event = Event;
}
runtime/quartz/src/lib.rsdiffbeforeafterboth--- a/runtime/quartz/src/lib.rs
+++ b/runtime/quartz/src/lib.rs
@@ -918,6 +918,7 @@
}
impl pallet_proxy_rmrk_core::Config for Runtime {
+ type WeightInfo = pallet_proxy_rmrk_core::weights::SubstrateWeight<Self>;
type Event = Event;
}
runtime/unique/src/lib.rsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! The Substrate Node Template runtime. This can be compiled with `#[no_std]`, ready for Wasm.1819#![cfg_attr(not(feature = "std"), no_std)]20// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.21#![recursion_limit = "1024"]22#![allow(clippy::from_over_into, clippy::identity_op)]23#![allow(clippy::fn_to_numeric_cast_with_truncation)]24// Make the WASM binary available.25#[cfg(feature = "std")]26include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));2728use sp_api::impl_runtime_apis;29use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H256, U256, H160};30use sp_runtime::DispatchError;31use fp_self_contained::*;32// #[cfg(any(feature = "std", test))]33// pub use sp_runtime::BuildStorage;3435use sp_runtime::{36 Permill, Perbill, Percent, create_runtime_str, generic, impl_opaque_keys,37 traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, AccountIdConversion, Zero, Member},38 transaction_validity::{TransactionSource, TransactionValidity},39 ApplyExtrinsicResult, RuntimeAppPublic,40};4142use sp_std::prelude::*;4344#[cfg(feature = "std")]45use sp_version::NativeVersion;46use sp_version::RuntimeVersion;47pub use pallet_transaction_payment::{48 Multiplier, TargetedFeeAdjustment, FeeDetails, RuntimeDispatchInfo,49};50// A few exports that help ease life for downstream crates.51pub use pallet_balances::Call as BalancesCall;52pub use pallet_evm::{53 EnsureAddressTruncated, HashedAddressMapping, Runner, account::CrossAccountId as _,54 OnMethodCall, Account as EVMAccount, FeeCalculator, GasWeightMapping,55};56pub use frame_support::{57 construct_runtime, match_types,58 dispatch::DispatchResult,59 PalletId, parameter_types, StorageValue, ConsensusEngineId,60 traits::{61 tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT, Everything,62 Currency, ExistenceRequirement, Get, IsInVec, KeyOwnerProofSystem, LockIdentifier,63 OnUnbalanced, Randomness, FindAuthor, ConstU32, Imbalance, PrivilegeCmp,64 },65 weights::{66 constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},67 DispatchClass, DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,68 WeightToFeePolynomial, WeightToFeeCoefficient, WeightToFeeCoefficients, ConstantMultiplier,69 },70};71use pallet_unq_scheduler::DispatchCall;72use up_data_structs::{73 CollectionId, TokenId, TokenData, Property, PropertyKeyPermission, CollectionLimits,74 CollectionStats, RpcCollection,75 mapping::{EvmTokenAddressMapping, CrossTokenAddressMapping},76 TokenChild, RmrkCollectionInfo, RmrkInstanceInfo, RmrkResourceInfo, RmrkPropertyInfo,77 RmrkBaseInfo, RmrkPartType, RmrkTheme, RmrkThemeName, RmrkThemeProperty, RmrkCollectionId,78 RmrkNftId, RmrkAccountIdOrCollectionNftTuple, RmrkNftChild, RmrkPropertyKey, RmrkResourceTypes,79 RmrkBasicResource, RmrkComposableResource, RmrkSlotResource, RmrkResourceId, RmrkBaseId,80 RmrkFixedPart, RmrkSlotPart, RmrkString,81};8283// use pallet_contracts::weights::WeightInfo;84// #[cfg(any(feature = "std", test))]85use frame_system::{86 self as frame_system, EnsureRoot, EnsureSigned,87 limits::{BlockWeights, BlockLength},88};89use sp_arithmetic::{90 traits::{BaseArithmetic, Unsigned},91};92use smallvec::smallvec;93use codec::{Encode, Decode};94use fp_rpc::TransactionStatus;95use sp_runtime::{96 traits::{97 Applyable, BlockNumberProvider, Dispatchable, PostDispatchInfoOf, DispatchInfoOf,98 Saturating, CheckedConversion,99 },100 generic::Era,101 transaction_validity::TransactionValidityError,102 DispatchErrorWithPostInfo, SaturatedConversion,103};104105// pub use pallet_timestamp::Call as TimestampCall;106pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;107108// Polkadot imports109use pallet_xcm::XcmPassthrough;110use polkadot_parachain::primitives::Sibling;111use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*};112use xcm_builder::{113 AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter,114 EnsureXcmOrigin, FixedWeightBounds, LocationInverter, NativeAsset, ParentAsSuperuser,115 RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,116 SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,117 ParentIsPreset,118};119use xcm_executor::{Config, XcmExecutor, Assets};120use sp_std::{cmp::Ordering, marker::PhantomData};121122use xcm::latest::{123 // Xcm,124 AssetId::{Concrete},125 Fungibility::Fungible as XcmFungible,126 MultiAsset,127 Error as XcmError,128};129use xcm_executor::traits::{MatchesFungible, WeightTrader};130131use unique_runtime_common::{132 impl_common_runtime_apis,133 types::*,134 constants::*,135 dispatch::{CollectionDispatchT, CollectionDispatch},136 sponsoring::UniqueSponsorshipHandler,137 eth_sponsoring::UniqueEthSponsorshipHandler,138 weights::CommonWeights,139};140141pub const RUNTIME_NAME: &str = "unique";142pub const TOKEN_SYMBOL: &str = "UNQ";143144type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Runtime>;145146impl RuntimeInstance for Runtime {147 type CrossAccountId = self::CrossAccountId;148 type TransactionConverter = self::TransactionConverter;149150 fn get_transaction_converter() -> TransactionConverter {151 TransactionConverter152 }153}154155/// The type for looking up accounts. We don't expect more than 4 billion of them, but you156/// never know...157pub type AccountIndex = u32;158159/// Balance of an account.160pub type Balance = u128;161162/// Index of a transaction in the chain.163pub type Index = u32;164165/// A hash of some data used by the chain.166pub type Hash = sp_core::H256;167168/// Digest item type.169pub type DigestItem = generic::DigestItem;170171/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know172/// the specifics of the runtime. They can then be made to be agnostic over specific formats173/// of data like extrinsics, allowing for them to continue syncing the network through upgrades174/// to even the core data structures.175pub mod opaque {176 use sp_std::prelude::*;177 use sp_runtime::impl_opaque_keys;178 use super::Aura;179180 pub use unique_runtime_common::types::*;181182 impl_opaque_keys! {183 pub struct SessionKeys {184 pub aura: Aura,185 }186 }187}188189/// This runtime version.190pub const VERSION: RuntimeVersion = RuntimeVersion {191 spec_name: create_runtime_str!(RUNTIME_NAME),192 impl_name: create_runtime_str!(RUNTIME_NAME),193 authoring_version: 1,194 spec_version: 922000,195 impl_version: 0,196 apis: RUNTIME_API_VERSIONS,197 transaction_version: 1,198 state_version: 0,199};200201#[derive(codec::Encode, codec::Decode)]202pub enum XCMPMessage<XAccountId, XBalance> {203 /// Transfer tokens to the given account from the Parachain account.204 TransferToken(XAccountId, XBalance),205}206207/// The version information used to identify this runtime when compiled natively.208#[cfg(feature = "std")]209pub fn native_version() -> NativeVersion {210 NativeVersion {211 runtime_version: VERSION,212 can_author_with: Default::default(),213 }214}215216type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;217218pub struct DealWithFees;219impl OnUnbalanced<NegativeImbalance> for DealWithFees {220 fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance>) {221 if let Some(fees) = fees_then_tips.next() {222 // for fees, 100% to treasury223 let mut split = fees.ration(100, 0);224 if let Some(tips) = fees_then_tips.next() {225 // for tips, if any, 100% to treasury226 tips.ration_merge_into(100, 0, &mut split);227 }228 Treasury::on_unbalanced(split.0);229 // Author::on_unbalanced(split.1);230 }231 }232}233234parameter_types! {235 pub const BlockHashCount: BlockNumber = 2400;236 pub RuntimeBlockLength: BlockLength =237 BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);238 pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);239 pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;240 pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()241 .base_block(BlockExecutionWeight::get())242 .for_class(DispatchClass::all(), |weights| {243 weights.base_extrinsic = ExtrinsicBaseWeight::get();244 })245 .for_class(DispatchClass::Normal, |weights| {246 weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);247 })248 .for_class(DispatchClass::Operational, |weights| {249 weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);250 // Operational transactions have some extra reserved space, so that they251 // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.252 weights.reserved = Some(253 MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT254 );255 })256 .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)257 .build_or_panic();258 pub const Version: RuntimeVersion = VERSION;259 pub const SS58Prefix: u16 = 7391;260}261262parameter_types! {263 pub const ChainId: u64 = 8880;264}265266pub struct FixedFee;267impl FeeCalculator for FixedFee {268 fn min_gas_price() -> (U256, u64) {269 (MIN_GAS_PRICE.into(), 0)270 }271}272273// Assuming slowest ethereum opcode is SSTORE, with gas price of 20000 as our worst case274// (contract, which only writes a lot of data),275// approximating on top of our real store write weight276parameter_types! {277 pub const WritesPerSecond: u64 = WEIGHT_PER_SECOND / <Runtime as frame_system::Config>::DbWeight::get().write;278 pub const GasPerSecond: u64 = WritesPerSecond::get() * 20000;279 pub const WeightPerGas: u64 = WEIGHT_PER_SECOND / GasPerSecond::get();280}281282/// Limiting EVM execution to 50% of block for substrate users and management tasks283/// EVM transaction consumes more weight than substrate's, so we can't rely on them being284/// scheduled fairly285const EVM_DISPATCH_RATIO: Perbill = Perbill::from_percent(50);286parameter_types! {287 pub BlockGasLimit: U256 = U256::from(NORMAL_DISPATCH_RATIO * EVM_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT / WeightPerGas::get());288}289290pub enum FixedGasWeightMapping {}291impl GasWeightMapping for FixedGasWeightMapping {292 fn gas_to_weight(gas: u64) -> Weight {293 gas.saturating_mul(WeightPerGas::get())294 }295 fn weight_to_gas(weight: Weight) -> u64 {296 weight / WeightPerGas::get()297 }298}299300impl pallet_evm::account::Config for Runtime {301 type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Self>;302 type EvmAddressMapping = pallet_evm::HashedAddressMapping<Self::Hashing>;303 type EvmBackwardsAddressMapping = fp_evm_mapping::MapBackwardsAddressTruncated;304}305306impl pallet_evm::Config for Runtime {307 type BlockGasLimit = BlockGasLimit;308 type FeeCalculator = FixedFee;309 type GasWeightMapping = FixedGasWeightMapping;310 type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;311 type CallOrigin = EnsureAddressTruncated<Self>;312 type WithdrawOrigin = EnsureAddressTruncated<Self>;313 type AddressMapping = HashedAddressMapping<Self::Hashing>;314 type PrecompilesType = ();315 type PrecompilesValue = ();316 type Currency = Balances;317 type Event = Event;318 type OnMethodCall = (319 pallet_evm_migration::OnMethodCall<Self>,320 pallet_evm_contract_helpers::HelpersOnMethodCall<Self>,321 CollectionDispatchT<Self>,322 pallet_unique::eth::CollectionHelpersOnMethodCall<Self>,323 );324 type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;325 type ChainId = ChainId;326 type Runner = pallet_evm::runner::stack::Runner<Self>;327 type OnChargeTransaction = pallet_evm::EVMCurrencyAdapter<Balances, DealWithFees>;328 type TransactionValidityHack = pallet_evm_transaction_payment::TransactionValidityHack<Self>;329 type FindAuthor = EthereumFindAuthor<Aura>;330}331332impl pallet_evm_migration::Config for Runtime {333 type WeightInfo = pallet_evm_migration::weights::SubstrateWeight<Self>;334}335336pub struct EthereumFindAuthor<F>(core::marker::PhantomData<F>);337impl<F: FindAuthor<u32>> FindAuthor<H160> for EthereumFindAuthor<F> {338 fn find_author<'a, I>(digests: I) -> Option<H160>339 where340 I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,341 {342 if let Some(author_index) = F::find_author(digests) {343 let authority_id = Aura::authorities()[author_index as usize].clone();344 return Some(H160::from_slice(&authority_id.to_raw_vec()[4..24]));345 }346 None347 }348}349350impl pallet_ethereum::Config for Runtime {351 type Event = Event;352 type StateRoot = pallet_ethereum::IntermediateStateRoot<Self>;353}354355impl pallet_randomness_collective_flip::Config for Runtime {}356357impl frame_system::Config for Runtime {358 /// The data to be stored in an account.359 type AccountData = pallet_balances::AccountData<Balance>;360 /// The identifier used to distinguish between accounts.361 type AccountId = AccountId;362 /// The basic call filter to use in dispatchable.363 type BaseCallFilter = Everything;364 /// Maximum number of block number to block hash mappings to keep (oldest pruned first).365 type BlockHashCount = BlockHashCount;366 /// The maximum length of a block (in bytes).367 type BlockLength = RuntimeBlockLength;368 /// The index type for blocks.369 type BlockNumber = BlockNumber;370 /// The weight of the overhead invoked on the block import process, independent of the extrinsics included in that block.371 type BlockWeights = RuntimeBlockWeights;372 /// The aggregated dispatch type that is available for extrinsics.373 type Call = Call;374 /// The weight of database operations that the runtime can invoke.375 type DbWeight = RocksDbWeight;376 /// The ubiquitous event type.377 type Event = Event;378 /// The type for hashing blocks and tries.379 type Hash = Hash;380 /// The hashing algorithm used.381 type Hashing = BlakeTwo256;382 /// The header type.383 type Header = generic::Header<BlockNumber, BlakeTwo256>;384 /// The index type for storing how many extrinsics an account has signed.385 type Index = Index;386 /// The lookup mechanism to get account ID from whatever is passed in dispatchers.387 type Lookup = AccountIdLookup<AccountId, ()>;388 /// What to do if an account is fully reaped from the system.389 type OnKilledAccount = ();390 /// What to do if a new account is created.391 type OnNewAccount = ();392 type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;393 /// The ubiquitous origin type.394 type Origin = Origin;395 /// This type is being generated by `construct_runtime!`.396 type PalletInfo = PalletInfo;397 /// This is used as an identifier of the chain. 42 is the generic substrate prefix.398 type SS58Prefix = SS58Prefix;399 /// Weight information for the extrinsics of this pallet.400 type SystemWeightInfo = frame_system::weights::SubstrateWeight<Self>;401 /// Version of the runtime.402 type Version = Version;403 type MaxConsumers = ConstU32<16>;404}405406parameter_types! {407 pub const MinimumPeriod: u64 = SLOT_DURATION / 2;408}409410impl pallet_timestamp::Config for Runtime {411 /// A timestamp: milliseconds since the unix epoch.412 type Moment = u64;413 type OnTimestampSet = ();414 type MinimumPeriod = MinimumPeriod;415 type WeightInfo = ();416}417418parameter_types! {419 // pub const ExistentialDeposit: u128 = 500;420 pub const ExistentialDeposit: u128 = 0;421 pub const MaxLocks: u32 = 50;422 pub const MaxReserves: u32 = 50;423}424425impl pallet_balances::Config for Runtime {426 type MaxLocks = MaxLocks;427 type MaxReserves = MaxReserves;428 type ReserveIdentifier = [u8; 16];429 /// The type for recording an account's balance.430 type Balance = Balance;431 /// The ubiquitous event type.432 type Event = Event;433 type DustRemoval = Treasury;434 type ExistentialDeposit = ExistentialDeposit;435 type AccountStore = System;436 type WeightInfo = pallet_balances::weights::SubstrateWeight<Self>;437}438439pub const fn deposit(items: u32, bytes: u32) -> Balance {440 items as Balance * 15 * CENTIUNIQUE + (bytes as Balance) * 6 * CENTIUNIQUE441}442443/*444parameter_types! {445 pub TombstoneDeposit: Balance = deposit(446 1,447 sp_std::mem::size_of::<pallet_contracts::Pallet<Runtime>> as u32,448 );449 pub DepositPerContract: Balance = TombstoneDeposit::get();450 pub const DepositPerStorageByte: Balance = deposit(0, 1);451 pub const DepositPerStorageItem: Balance = deposit(1, 0);452 pub RentFraction: Perbill = Perbill::from_rational(1u32, 30 * DAYS);453 pub const SurchargeReward: Balance = 150 * MILLIUNIQUE;454 pub const SignedClaimHandicap: u32 = 2;455 pub const MaxDepth: u32 = 32;456 pub const MaxValueSize: u32 = 16 * 1024;457 pub const MaxCodeSize: u32 = 1024 * 1024 * 25; // 25 Mb458 // The lazy deletion runs inside on_initialize.459 pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO *460 RuntimeBlockWeights::get().max_block;461 // The weight needed for decoding the queue should be less or equal than a fifth462 // of the overall weight dedicated to the lazy deletion.463 pub DeletionQueueDepth: u32 = ((DeletionWeightLimit::get() / (464 <Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(1) -465 <Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(0)466 )) / 5) as u32;467 pub Schedule: pallet_contracts::Schedule<Runtime> = Default::default();468}469470impl pallet_contracts::Config for Runtime {471 type Time = Timestamp;472 type Randomness = RandomnessCollectiveFlip;473 type Currency = Balances;474 type Event = Event;475 type RentPayment = ();476 type SignedClaimHandicap = SignedClaimHandicap;477 type TombstoneDeposit = TombstoneDeposit;478 type DepositPerContract = DepositPerContract;479 type DepositPerStorageByte = DepositPerStorageByte;480 type DepositPerStorageItem = DepositPerStorageItem;481 type RentFraction = RentFraction;482 type SurchargeReward = SurchargeReward;483 type WeightPrice = pallet_transaction_payment::Pallet<Self>;484 type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;485 type ChainExtension = NFTExtension;486 type DeletionQueueDepth = DeletionQueueDepth;487 type DeletionWeightLimit = DeletionWeightLimit;488 type Schedule = Schedule;489 type CallStack = [pallet_contracts::Frame<Self>; 31];490}491*/492493parameter_types! {494 /// This value increases the priority of `Operational` transactions by adding495 /// a "virtual tip" that's equal to the `OperationalFeeMultiplier * final_fee`.496 pub const OperationalFeeMultiplier: u8 = 5;497}498499/// Linear implementor of `WeightToFeePolynomial`500pub struct LinearFee<T>(sp_std::marker::PhantomData<T>);501502impl<T> WeightToFeePolynomial for LinearFee<T>503where504 T: BaseArithmetic + From<u32> + Copy + Unsigned,505{506 type Balance = T;507508 fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {509 smallvec!(WeightToFeeCoefficient {510 // Targeting 0.1 Unique per NFT transfer511 coeff_integer: WEIGHT_TO_FEE_COEFF.into(),512 coeff_frac: Perbill::zero(),513 negative: false,514 degree: 1,515 })516 }517}518519impl pallet_transaction_payment::Config for Runtime {520 type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, DealWithFees>;521 type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;522 type OperationalFeeMultiplier = OperationalFeeMultiplier;523 type WeightToFee = LinearFee<Balance>;524 type FeeMultiplierUpdate = ();525}526527parameter_types! {528 pub const ProposalBond: Permill = Permill::from_percent(5);529 pub const ProposalBondMinimum: Balance = 1 * UNIQUE;530 pub const ProposalBondMaximum: Balance = 1000 * UNIQUE;531 pub const SpendPeriod: BlockNumber = 5 * MINUTES;532 pub const Burn: Permill = Permill::from_percent(0);533 pub const TipCountdown: BlockNumber = 1 * DAYS;534 pub const TipFindersFee: Percent = Percent::from_percent(20);535 pub const TipReportDepositBase: Balance = 1 * UNIQUE;536 pub const DataDepositPerByte: Balance = 1 * CENTIUNIQUE;537 pub const BountyDepositBase: Balance = 1 * UNIQUE;538 pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS;539 pub const TreasuryModuleId: PalletId = PalletId(*b"py/trsry");540 pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS;541 pub const MaximumReasonLength: u32 = 16384;542 pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);543 pub const BountyValueMinimum: Balance = 5 * UNIQUE;544 pub const MaxApprovals: u32 = 100;545}546547impl pallet_treasury::Config for Runtime {548 type PalletId = TreasuryModuleId;549 type Currency = Balances;550 type ApproveOrigin = EnsureRoot<AccountId>;551 type RejectOrigin = EnsureRoot<AccountId>;552 type Event = Event;553 type OnSlash = ();554 type ProposalBond = ProposalBond;555 type ProposalBondMinimum = ProposalBondMinimum;556 type ProposalBondMaximum = ProposalBondMaximum;557 type SpendPeriod = SpendPeriod;558 type Burn = Burn;559 type BurnDestination = ();560 type SpendFunds = ();561 type WeightInfo = pallet_treasury::weights::SubstrateWeight<Self>;562 type MaxApprovals = MaxApprovals;563}564565impl pallet_sudo::Config for Runtime {566 type Event = Event;567 type Call = Call;568}569570pub struct RelayChainBlockNumberProvider<T>(sp_std::marker::PhantomData<T>);571572impl<T: cumulus_pallet_parachain_system::Config> BlockNumberProvider573 for RelayChainBlockNumberProvider<T>574{575 type BlockNumber = BlockNumber;576577 fn current_block_number() -> Self::BlockNumber {578 cumulus_pallet_parachain_system::Pallet::<T>::validation_data()579 .map(|d| d.relay_parent_number)580 .unwrap_or_default()581 }582}583584parameter_types! {585 pub const MinVestedTransfer: Balance = 10 * UNIQUE;586 pub const MaxVestingSchedules: u32 = 28;587}588589impl orml_vesting::Config for Runtime {590 type Event = Event;591 type Currency = pallet_balances::Pallet<Runtime>;592 type MinVestedTransfer = MinVestedTransfer;593 type VestedTransferOrigin = EnsureSigned<AccountId>;594 type WeightInfo = ();595 type MaxVestingSchedules = MaxVestingSchedules;596 type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;597}598599parameter_types! {600 pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;601 pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;602}603604impl cumulus_pallet_parachain_system::Config for Runtime {605 type Event = Event;606 type SelfParaId = parachain_info::Pallet<Self>;607 type OnSystemEvent = ();608 // type DownwardMessageHandlers = cumulus_primitives_utility::UnqueuedDmpAsParent<609 // MaxDownwardMessageWeight,610 // XcmExecutor<XcmConfig>,611 // Call,612 // >;613 type OutboundXcmpMessageSource = XcmpQueue;614 type DmpMessageHandler = DmpQueue;615 type ReservedDmpWeight = ReservedDmpWeight;616 type ReservedXcmpWeight = ReservedXcmpWeight;617 type XcmpMessageHandler = XcmpQueue;618}619620impl parachain_info::Config for Runtime {}621622impl cumulus_pallet_aura_ext::Config for Runtime {}623624parameter_types! {625 pub const RelayLocation: MultiLocation = MultiLocation::parent();626 pub const RelayNetwork: NetworkId = NetworkId::Polkadot;627 pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();628 pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();629}630631/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used632/// when determining ownership of accounts for asset transacting and when attempting to use XCM633/// `Transact` in order to determine the dispatch Origin.634pub type LocationToAccountId = (635 // The parent (Relay-chain) origin converts to the default `AccountId`.636 ParentIsPreset<AccountId>,637 // Sibling parachain origins convert to AccountId via the `ParaId::into`.638 SiblingParachainConvertsVia<Sibling, AccountId>,639 // Straight up local `AccountId32` origins just alias directly to `AccountId`.640 AccountId32Aliases<RelayNetwork, AccountId>,641);642643pub struct OnlySelfCurrency;644impl<B: TryFrom<u128>> MatchesFungible<B> for OnlySelfCurrency {645 fn matches_fungible(a: &MultiAsset) -> Option<B> {646 match (&a.id, &a.fun) {647 (Concrete(_), XcmFungible(ref amount)) => CheckedConversion::checked_from(*amount),648 _ => None,649 }650 }651}652653/// Means for transacting assets on this chain.654pub type LocalAssetTransactor = CurrencyAdapter<655 // Use this currency:656 Balances,657 // Use this currency when it is a fungible asset matching the given location or name:658 OnlySelfCurrency,659 // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:660 LocationToAccountId,661 // Our chain's account ID type (we can't get away without mentioning it explicitly):662 AccountId,663 // We don't track any teleports.664 (),665>;666667/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,668/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can669/// biases the kind of local `Origin` it will become.670pub type XcmOriginToTransactDispatchOrigin = (671 // Sovereign account converter; this attempts to derive an `AccountId` from the origin location672 // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for673 // foreign chains who want to have a local sovereign account on this chain which they control.674 SovereignSignedViaLocation<LocationToAccountId, Origin>,675 // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when676 // recognised.677 RelayChainAsNative<RelayOrigin, Origin>,678 // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when679 // recognised.680 SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,681 // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a682 // transaction from the Root origin.683 ParentAsSuperuser<Origin>,684 // Native signed account converter; this just converts an `AccountId32` origin into a normal685 // `Origin::Signed` origin of the same 32-byte value.686 SignedAccountId32AsNative<RelayNetwork, Origin>,687 // Xcm origins can be represented natively under the Xcm pallet's Xcm origin.688 XcmPassthrough<Origin>,689);690691parameter_types! {692 // One XCM operation is 1_000_000 weight - almost certainly a conservative estimate.693 pub UnitWeightCost: Weight = 1_000_000;694 // 1200 UNIQUEs buy 1 second of weight.695 pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), 1_200 * UNIQUE);696 pub const MaxInstructions: u32 = 100;697 pub const MaxAuthorities: u32 = 100_000;698}699700match_types! {701 pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {702 MultiLocation { parents: 1, interior: Here } |703 MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }704 };705}706707pub type Barrier = (708 TakeWeightCredit,709 AllowTopLevelPaidExecutionFrom<Everything>,710 AllowUnpaidExecutionFrom<ParentOrParentsUnitPlurality>,711 // ^^^ Parent & its unit plurality gets free execution712);713714pub struct UsingOnlySelfCurrencyComponents<715 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,716 AssetId: Get<MultiLocation>,717 AccountId,718 Currency: CurrencyT<AccountId>,719 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,720>(721 Weight,722 Currency::Balance,723 PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>,724);725impl<726 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,727 AssetId: Get<MultiLocation>,728 AccountId,729 Currency: CurrencyT<AccountId>,730 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,731 > WeightTrader732 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>733{734 fn new() -> Self {735 Self(0, Zero::zero(), PhantomData)736 }737738 fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, XcmError> {739 let amount = WeightToFee::calc(&weight);740 let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?;741742 // location to this parachain through relay chain743 let option1: xcm::v1::AssetId = Concrete(MultiLocation {744 parents: 1,745 interior: X1(Parachain(ParachainInfo::parachain_id().into())),746 });747 // direct location748 let option2: xcm::v1::AssetId = Concrete(MultiLocation {749 parents: 0,750 interior: Here,751 });752753 let required = if payment.fungible.contains_key(&option1) {754 (option1, u128_amount).into()755 } else if payment.fungible.contains_key(&option2) {756 (option2, u128_amount).into()757 } else {758 (Concrete(MultiLocation::default()), u128_amount).into()759 };760761 let unused = payment762 .checked_sub(required)763 .map_err(|_| XcmError::TooExpensive)?;764 self.0 = self.0.saturating_add(weight);765 self.1 = self.1.saturating_add(amount);766 Ok(unused)767 }768769 fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {770 let weight = weight.min(self.0);771 let amount = WeightToFee::calc(&weight);772 self.0 -= weight;773 self.1 = self.1.saturating_sub(amount);774 let amount: u128 = amount.saturated_into();775 if amount > 0 {776 Some((AssetId::get(), amount).into())777 } else {778 None779 }780 }781}782impl<783 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,784 AssetId: Get<MultiLocation>,785 AccountId,786 Currency: CurrencyT<AccountId>,787 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,788 > Drop789 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>790{791 fn drop(&mut self) {792 OnUnbalanced::on_unbalanced(Currency::issue(self.1));793 }794}795796pub struct XcmConfig;797impl Config for XcmConfig {798 type Call = Call;799 type XcmSender = XcmRouter;800 // How to withdraw and deposit an asset.801 type AssetTransactor = LocalAssetTransactor;802 type OriginConverter = XcmOriginToTransactDispatchOrigin;803 type IsReserve = NativeAsset;804 type IsTeleporter = (); // Teleportation is disabled805 type LocationInverter = LocationInverter<Ancestry>;806 type Barrier = Barrier;807 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;808 type Trader = UsingOnlySelfCurrencyComponents<809 IdentityFee<Balance>,810 RelayLocation,811 AccountId,812 Balances,813 (),814 >;815 type ResponseHandler = (); // Don't handle responses for now.816 type SubscriptionService = PolkadotXcm;817818 type AssetTrap = PolkadotXcm;819 type AssetClaims = PolkadotXcm;820}821822// parameter_types! {823// pub const MaxDownwardMessageWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 10;824// }825826/// No local origins on this chain are allowed to dispatch XCM sends/executions.827pub type LocalOriginToLocation = (SignedToAccountId32<Origin, AccountId, RelayNetwork>,);828829/// The means for routing XCM messages which are not for local execution into the right message830/// queues.831pub type XcmRouter = (832 // Two routers - use UMP to communicate with the relay chain:833 cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,834 // ..and XCMP to communicate with the sibling chains.835 XcmpQueue,836);837838impl pallet_evm_coder_substrate::Config for Runtime {}839840impl pallet_xcm::Config for Runtime {841 type Event = Event;842 type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;843 type XcmRouter = XcmRouter;844 type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;845 type XcmExecuteFilter = Everything;846 type XcmExecutor = XcmExecutor<XcmConfig>;847 type XcmTeleportFilter = Everything;848 type XcmReserveTransferFilter = Everything;849 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;850 type LocationInverter = LocationInverter<Ancestry>;851 type Origin = Origin;852 type Call = Call;853 const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;854 type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;855}856857impl cumulus_pallet_xcm::Config for Runtime {858 type Event = Event;859 type XcmExecutor = XcmExecutor<XcmConfig>;860}861862impl cumulus_pallet_xcmp_queue::Config for Runtime {863 type WeightInfo = ();864 type Event = Event;865 type XcmExecutor = XcmExecutor<XcmConfig>;866 type ChannelInfo = ParachainSystem;867 type VersionWrapper = ();868 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;869 type ControllerOrigin = EnsureRoot<AccountId>;870 type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;871}872873impl cumulus_pallet_dmp_queue::Config for Runtime {874 type Event = Event;875 type XcmExecutor = XcmExecutor<XcmConfig>;876 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;877}878879impl pallet_aura::Config for Runtime {880 type AuthorityId = AuraId;881 type DisabledValidators = ();882 type MaxAuthorities = MaxAuthorities;883}884885parameter_types! {886 pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account();887 pub const CollectionCreationPrice: Balance = 2 * UNIQUE;888}889890impl pallet_common::Config for Runtime {891 type WeightInfo = pallet_common::weights::SubstrateWeight<Self>;892 type Event = Event;893 type Currency = Balances;894 type CollectionCreationPrice = CollectionCreationPrice;895 type TreasuryAccountId = TreasuryAccountId;896 type CollectionDispatch = CollectionDispatchT<Self>;897898 type EvmTokenAddressMapping = EvmTokenAddressMapping;899 type CrossTokenAddressMapping = CrossTokenAddressMapping<Self::AccountId>;900 type ContractAddress = EvmCollectionHelpersAddress;901}902903impl pallet_structure::Config for Runtime {904 type Event = Event;905 type Call = Call;906 type WeightInfo = pallet_structure::weights::SubstrateWeight<Self>;907}908909impl pallet_fungible::Config for Runtime {910 type WeightInfo = pallet_fungible::weights::SubstrateWeight<Self>;911}912impl pallet_refungible::Config for Runtime {913 type WeightInfo = pallet_refungible::weights::SubstrateWeight<Self>;914}915impl pallet_nonfungible::Config for Runtime {916 type WeightInfo = pallet_nonfungible::weights::SubstrateWeight<Self>;917}918919impl pallet_proxy_rmrk_core::Config for Runtime {920 type Event = Event;921}922923impl pallet_proxy_rmrk_equip::Config for Runtime {924 type Event = Event;925}926927impl pallet_unique::Config for Runtime {928 type Event = Event;929 type WeightInfo = pallet_unique::weights::SubstrateWeight<Self>;930 type CommonWeightInfo = CommonWeights<Self>;931}932933parameter_types! {934 pub const InflationBlockInterval: BlockNumber = 100; // every time per how many blocks inflation is applied935}936937/// Used for the pallet inflation938impl pallet_inflation::Config for Runtime {939 type Currency = Balances;940 type TreasuryAccountId = TreasuryAccountId;941 type InflationBlockInterval = InflationBlockInterval;942 type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;943}944945parameter_types! {946 pub MaximumSchedulerWeight: Weight = Perbill::from_percent(50) *947 RuntimeBlockWeights::get().max_block;948 pub const MaxScheduledPerBlock: u32 = 50;949}950951type ChargeTransactionPayment = pallet_charge_transaction::ChargeTransactionPayment<Runtime>;952use frame_support::traits::NamedReservableCurrency;953954fn get_signed_extras(from: <Runtime as frame_system::Config>::AccountId) -> SignedExtraScheduler {955 (956 frame_system::CheckSpecVersion::<Runtime>::new(),957 frame_system::CheckGenesis::<Runtime>::new(),958 frame_system::CheckEra::<Runtime>::from(Era::Immortal),959 frame_system::CheckNonce::<Runtime>::from(frame_system::Pallet::<Runtime>::account_nonce(960 from,961 )),962 frame_system::CheckWeight::<Runtime>::new(),963 // sponsoring transaction logic964 // pallet_charge_transaction::ChargeTransactionPayment::<Runtime>::new(0),965 )966}967968pub struct SchedulerPaymentExecutor;969impl<T: frame_system::Config + pallet_unq_scheduler::Config, SelfContainedSignedInfo>970 DispatchCall<T, SelfContainedSignedInfo> for SchedulerPaymentExecutor971where972 <T as frame_system::Config>::Call: Member973 + Dispatchable<Origin = Origin, Info = DispatchInfo>974 + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>975 + GetDispatchInfo976 + From<frame_system::Call<Runtime>>,977 SelfContainedSignedInfo: Send + Sync + 'static,978 Call: From<<T as frame_system::Config>::Call>979 + From<<T as pallet_unq_scheduler::Config>::Call>980 + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>,981 sp_runtime::AccountId32: From<<T as frame_system::Config>::AccountId>,982{983 fn dispatch_call(984 signer: <T as frame_system::Config>::AccountId,985 call: <T as pallet_unq_scheduler::Config>::Call,986 ) -> Result<987 Result<PostDispatchInfo, DispatchErrorWithPostInfo<PostDispatchInfo>>,988 TransactionValidityError,989 > {990 let dispatch_info = call.get_dispatch_info();991 let extrinsic = fp_self_contained::CheckedExtrinsic::<992 AccountId,993 Call,994 SignedExtraScheduler,995 SelfContainedSignedInfo,996 > {997 signed:998 CheckedSignature::<AccountId, SignedExtraScheduler, SelfContainedSignedInfo>::Signed(999 signer.clone().into(),1000 get_signed_extras(signer.into()),1001 ),1002 function: call.into(),1003 };10041005 extrinsic.apply::<Runtime>(&dispatch_info, 0)1006 }10071008 fn reserve_balance(1009 id: [u8; 16],1010 sponsor: <T as frame_system::Config>::AccountId,1011 call: <T as pallet_unq_scheduler::Config>::Call,1012 count: u32,1013 ) -> Result<(), DispatchError> {1014 let dispatch_info = call.get_dispatch_info();1015 let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0)1016 .saturating_mul(count.into());10171018 <Balances as NamedReservableCurrency<AccountId>>::reserve_named(1019 &id,1020 &(sponsor.into()),1021 weight,1022 )1023 }10241025 fn pay_for_call(1026 id: [u8; 16],1027 sponsor: <T as frame_system::Config>::AccountId,1028 call: <T as pallet_unq_scheduler::Config>::Call,1029 ) -> Result<u128, DispatchError> {1030 let dispatch_info = call.get_dispatch_info();1031 let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0);1032 Ok(1033 <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(1034 &id,1035 &(sponsor.into()),1036 weight,1037 ),1038 )1039 }10401041 fn cancel_reserve(1042 id: [u8; 16],1043 sponsor: <T as frame_system::Config>::AccountId,1044 ) -> Result<u128, DispatchError> {1045 Ok(1046 <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(1047 &id,1048 &(sponsor.into()),1049 u128::MAX,1050 ),1051 )1052 }1053}10541055parameter_types! {1056 pub const NoPreimagePostponement: Option<u32> = Some(10);1057 pub const Preimage: Option<u32> = Some(10);1058}10591060/// Used the compare the privilege of an origin inside the scheduler.1061pub struct OriginPrivilegeCmp;10621063impl PrivilegeCmp<OriginCaller> for OriginPrivilegeCmp {1064 fn cmp_privilege(_left: &OriginCaller, _right: &OriginCaller) -> Option<Ordering> {1065 Some(Ordering::Equal)1066 }1067}10681069impl pallet_unq_scheduler::Config for Runtime {1070 type Event = Event;1071 type Origin = Origin;1072 type Currency = Balances;1073 type PalletsOrigin = OriginCaller;1074 type Call = Call;1075 type MaximumWeight = MaximumSchedulerWeight;1076 type ScheduleOrigin = EnsureSigned<AccountId>;1077 type MaxScheduledPerBlock = MaxScheduledPerBlock;1078 type WeightInfo = ();1079 type CallExecutor = SchedulerPaymentExecutor;1080 type OriginPrivilegeCmp = OriginPrivilegeCmp;1081 type PreimageProvider = ();1082 type NoPreimagePostponement = NoPreimagePostponement;1083}10841085type EvmSponsorshipHandler = (1086 UniqueEthSponsorshipHandler<Runtime>,1087 pallet_evm_contract_helpers::HelpersContractSponsoring<Runtime>,1088);1089type SponsorshipHandler = (1090 UniqueSponsorshipHandler<Runtime>,1091 //pallet_contract_helpers::ContractSponsorshipHandler<Runtime>,1092 pallet_evm_transaction_payment::BridgeSponsorshipHandler<Runtime>,1093);10941095impl pallet_evm_transaction_payment::Config for Runtime {1096 type EvmSponsorshipHandler = EvmSponsorshipHandler;1097 type Currency = Balances;1098}10991100impl pallet_charge_transaction::Config for Runtime {1101 type SponsorshipHandler = SponsorshipHandler;1102}11031104// impl pallet_contract_helpers::Config for Runtime {1105// type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;1106// }11071108parameter_types! {1109 // 0x842899ECF380553E8a4de75bF534cdf6fBF640491110 pub const HelpersContractAddress: H160 = H160([1111 0x84, 0x28, 0x99, 0xec, 0xf3, 0x80, 0x55, 0x3e, 0x8a, 0x4d, 0xe7, 0x5b, 0xf5, 0x34, 0xcd, 0xf6, 0xfb, 0xf6, 0x40, 0x49,1112 ]);11131114 // 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f1115 pub const EvmCollectionHelpersAddress: H160 = H160([1116 0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f,1117 ]);1118}11191120impl pallet_evm_contract_helpers::Config for Runtime {1121 type ContractAddress = HelpersContractAddress;1122 type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;1123}11241125construct_runtime!(1126 pub enum Runtime where1127 Block = Block,1128 NodeBlock = opaque::Block,1129 UncheckedExtrinsic = UncheckedExtrinsic1130 {1131 ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Config, Storage, Inherent, Event<T>, ValidateUnsigned} = 20,1132 ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21,11331134 Aura: pallet_aura::{Pallet, Config<T>} = 22,1135 AuraExt: cumulus_pallet_aura_ext::{Pallet, Config} = 23,11361137 Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 30,1138 RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage} = 31,1139 Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 32,1140 TransactionPayment: pallet_transaction_payment::{Pallet, Storage} = 33,1141 Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event<T>} = 34,1142 Sudo: pallet_sudo::{Pallet, Call, Storage, Config<T>, Event<T>} = 35,1143 System: frame_system::{Pallet, Call, Storage, Config, Event<T>} = 36,1144 Vesting: orml_vesting::{Pallet, Storage, Call, Event<T>, Config<T>} = 37,1145 // Vesting: pallet_vesting::{Pallet, Call, Config<T>, Storage, Event<T>} = 37,1146 // Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>} = 38,11471148 // XCM helpers.1149 XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 50,1150 PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin} = 51,1151 CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event<T>, Origin} = 52,1152 DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 53,11531154 // Unique Pallets1155 Inflation: pallet_inflation::{Pallet, Call, Storage} = 60,1156 Unique: pallet_unique::{Pallet, Call, Storage, Event<T>} = 61,1157 Scheduler: pallet_unq_scheduler::{Pallet, Call, Storage, Event<T>} = 62,1158 // free = 631159 Charging: pallet_charge_transaction::{Pallet, Call, Storage } = 64,1160 // ContractHelpers: pallet_contract_helpers::{Pallet, Call, Storage} = 65,1161 Common: pallet_common::{Pallet, Storage, Event<T>} = 66,1162 Fungible: pallet_fungible::{Pallet, Storage} = 67,1163 Refungible: pallet_refungible::{Pallet, Storage} = 68,1164 Nonfungible: pallet_nonfungible::{Pallet, Storage} = 69,1165 Structure: pallet_structure::{Pallet, Call, Storage, Event<T>} = 70,1166 RmrkCore: pallet_proxy_rmrk_core::{Pallet, Call, Storage, Event<T>} = 71,1167 RmrkEquip: pallet_proxy_rmrk_equip::{Pallet, Call, Storage, Event<T>} = 72,11681169 // Frontier1170 EVM: pallet_evm::{Pallet, Config, Call, Storage, Event<T>} = 100,1171 Ethereum: pallet_ethereum::{Pallet, Config, Call, Storage, Event, Origin} = 101,11721173 EvmCoderSubstrate: pallet_evm_coder_substrate::{Pallet, Storage} = 150,1174 EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage} = 151,1175 EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152,1176 EvmMigration: pallet_evm_migration::{Pallet, Call, Storage} = 153,1177 }1178);11791180pub struct TransactionConverter;11811182impl fp_rpc::ConvertTransaction<UncheckedExtrinsic> for TransactionConverter {1183 fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> UncheckedExtrinsic {1184 UncheckedExtrinsic::new_unsigned(1185 pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),1186 )1187 }1188}11891190impl fp_rpc::ConvertTransaction<opaque::UncheckedExtrinsic> for TransactionConverter {1191 fn convert_transaction(1192 &self,1193 transaction: pallet_ethereum::Transaction,1194 ) -> opaque::UncheckedExtrinsic {1195 let extrinsic = UncheckedExtrinsic::new_unsigned(1196 pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),1197 );1198 let encoded = extrinsic.encode();1199 opaque::UncheckedExtrinsic::decode(&mut &encoded[..])1200 .expect("Encoded extrinsic is always valid")1201 }1202}12031204/// The address format for describing accounts.1205pub type Address = sp_runtime::MultiAddress<AccountId, ()>;1206/// Block header type as expected by this runtime.1207pub type Header = generic::Header<BlockNumber, BlakeTwo256>;1208/// Block type as expected by this runtime.1209pub type Block = generic::Block<Header, UncheckedExtrinsic>;1210/// A Block signed with a Justification1211pub type SignedBlock = generic::SignedBlock<Block>;1212/// BlockId type as expected by this runtime.1213pub type BlockId = generic::BlockId<Block>;1214/// The SignedExtension to the basic transaction logic.1215pub type SignedExtra = (1216 frame_system::CheckSpecVersion<Runtime>,1217 // system::CheckTxVersion<Runtime>,1218 frame_system::CheckGenesis<Runtime>,1219 frame_system::CheckEra<Runtime>,1220 frame_system::CheckNonce<Runtime>,1221 frame_system::CheckWeight<Runtime>,1222 pallet_charge_transaction::ChargeTransactionPayment<Runtime>,1223 //pallet_contract_helpers::ContractHelpersExtension<Runtime>,1224 pallet_ethereum::FakeTransactionFinalizer<Runtime>,1225);1226pub type SignedExtraScheduler = (1227 frame_system::CheckSpecVersion<Runtime>,1228 frame_system::CheckGenesis<Runtime>,1229 frame_system::CheckEra<Runtime>,1230 frame_system::CheckNonce<Runtime>,1231 frame_system::CheckWeight<Runtime>,1232 // pallet_charge_transaction::ChargeTransactionPayment<Runtime>,1233);1234/// Unchecked extrinsic type as expected by this runtime.1235pub type UncheckedExtrinsic =1236 fp_self_contained::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;1237/// Extrinsic type that has already been checked.1238pub type CheckedExtrinsic = fp_self_contained::CheckedExtrinsic<AccountId, Call, SignedExtra, H160>;1239/// Executive: handles dispatch to the various modules.1240pub type Executive = frame_executive::Executive<1241 Runtime,1242 Block,1243 frame_system::ChainContext<Runtime>,1244 Runtime,1245 AllPalletsReversedWithSystemFirst,1246>;12471248impl_opaque_keys! {1249 pub struct SessionKeys {1250 pub aura: Aura,1251 }1252}12531254impl fp_self_contained::SelfContainedCall for Call {1255 type SignedInfo = H160;12561257 fn is_self_contained(&self) -> bool {1258 match self {1259 Call::Ethereum(call) => call.is_self_contained(),1260 _ => false,1261 }1262 }12631264 fn check_self_contained(&self) -> Option<Result<Self::SignedInfo, TransactionValidityError>> {1265 match self {1266 Call::Ethereum(call) => call.check_self_contained(),1267 _ => None,1268 }1269 }12701271 fn validate_self_contained(1272 &self,1273 info: &Self::SignedInfo,1274 dispatch_info: &DispatchInfoOf<Call>,1275 len: usize,1276 ) -> Option<TransactionValidity> {1277 match self {1278 Call::Ethereum(call) => call.validate_self_contained(info, dispatch_info, len),1279 _ => None,1280 }1281 }12821283 fn pre_dispatch_self_contained(1284 &self,1285 info: &Self::SignedInfo,1286 ) -> Option<Result<(), TransactionValidityError>> {1287 match self {1288 Call::Ethereum(call) => call.pre_dispatch_self_contained(info),1289 _ => None,1290 }1291 }12921293 fn apply_self_contained(1294 self,1295 info: Self::SignedInfo,1296 ) -> Option<sp_runtime::DispatchResultWithInfo<PostDispatchInfoOf<Self>>> {1297 match self {1298 call @ Call::Ethereum(pallet_ethereum::Call::transact { .. }) => Some(call.dispatch(1299 Origin::from(pallet_ethereum::RawOrigin::EthereumTransaction(info)),1300 )),1301 _ => None,1302 }1303 }1304}13051306macro_rules! dispatch_unique_runtime {1307 ($collection:ident.$method:ident($($name:ident),*)) => {{1308 let collection = <Runtime as pallet_common::Config>::CollectionDispatch::dispatch(<pallet_common::CollectionHandle<Runtime>>::try_get($collection)?);1309 let dispatch = collection.as_dyn();13101311 Ok::<_, DispatchError>(dispatch.$method($($name),*))1312 }};1313}13141315impl_common_runtime_apis!();13161317struct CheckInherents;13181319impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {1320 fn check_inherents(1321 block: &Block,1322 relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof,1323 ) -> sp_inherents::CheckInherentsResult {1324 let relay_chain_slot = relay_state_proof1325 .read_slot()1326 .expect("Could not read the relay chain slot from the proof");13271328 let inherent_data =1329 cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration(1330 relay_chain_slot,1331 sp_std::time::Duration::from_secs(6),1332 )1333 .create_inherent_data()1334 .expect("Could not create the timestamp inherent data");13351336 inherent_data.check_extrinsics(block)1337 }1338}13391340cumulus_pallet_parachain_system::register_validate_block!(1341 Runtime = Runtime,1342 BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,1343 CheckInherents = CheckInherents,1344);1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! The Substrate Node Template runtime. This can be compiled with `#[no_std]`, ready for Wasm.1819#![cfg_attr(not(feature = "std"), no_std)]20// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.21#![recursion_limit = "1024"]22#![allow(clippy::from_over_into, clippy::identity_op)]23#![allow(clippy::fn_to_numeric_cast_with_truncation)]24// Make the WASM binary available.25#[cfg(feature = "std")]26include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));2728use sp_api::impl_runtime_apis;29use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H256, U256, H160};30use sp_runtime::DispatchError;31use fp_self_contained::*;32// #[cfg(any(feature = "std", test))]33// pub use sp_runtime::BuildStorage;3435use sp_runtime::{36 Permill, Perbill, Percent, create_runtime_str, generic, impl_opaque_keys,37 traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, AccountIdConversion, Zero, Member},38 transaction_validity::{TransactionSource, TransactionValidity},39 ApplyExtrinsicResult, RuntimeAppPublic,40};4142use sp_std::prelude::*;4344#[cfg(feature = "std")]45use sp_version::NativeVersion;46use sp_version::RuntimeVersion;47pub use pallet_transaction_payment::{48 Multiplier, TargetedFeeAdjustment, FeeDetails, RuntimeDispatchInfo,49};50// A few exports that help ease life for downstream crates.51pub use pallet_balances::Call as BalancesCall;52pub use pallet_evm::{53 EnsureAddressTruncated, HashedAddressMapping, Runner, account::CrossAccountId as _,54 OnMethodCall, Account as EVMAccount, FeeCalculator, GasWeightMapping,55};56pub use frame_support::{57 construct_runtime, match_types,58 dispatch::DispatchResult,59 PalletId, parameter_types, StorageValue, ConsensusEngineId,60 traits::{61 tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT, Everything,62 Currency, ExistenceRequirement, Get, IsInVec, KeyOwnerProofSystem, LockIdentifier,63 OnUnbalanced, Randomness, FindAuthor, ConstU32, Imbalance, PrivilegeCmp,64 },65 weights::{66 constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},67 DispatchClass, DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,68 WeightToFeePolynomial, WeightToFeeCoefficient, WeightToFeeCoefficients, ConstantMultiplier,69 },70};71use pallet_unq_scheduler::DispatchCall;72use up_data_structs::{73 CollectionId, TokenId, TokenData, Property, PropertyKeyPermission, CollectionLimits,74 CollectionStats, RpcCollection,75 mapping::{EvmTokenAddressMapping, CrossTokenAddressMapping},76 TokenChild, RmrkCollectionInfo, RmrkInstanceInfo, RmrkResourceInfo, RmrkPropertyInfo,77 RmrkBaseInfo, RmrkPartType, RmrkTheme, RmrkThemeName, RmrkThemeProperty, RmrkCollectionId,78 RmrkNftId, RmrkAccountIdOrCollectionNftTuple, RmrkNftChild, RmrkPropertyKey, RmrkResourceTypes,79 RmrkBasicResource, RmrkComposableResource, RmrkSlotResource, RmrkResourceId, RmrkBaseId,80 RmrkFixedPart, RmrkSlotPart, RmrkString,81};8283// use pallet_contracts::weights::WeightInfo;84// #[cfg(any(feature = "std", test))]85use frame_system::{86 self as frame_system, EnsureRoot, EnsureSigned,87 limits::{BlockWeights, BlockLength},88};89use sp_arithmetic::{90 traits::{BaseArithmetic, Unsigned},91};92use smallvec::smallvec;93use codec::{Encode, Decode};94use fp_rpc::TransactionStatus;95use sp_runtime::{96 traits::{97 Applyable, BlockNumberProvider, Dispatchable, PostDispatchInfoOf, DispatchInfoOf,98 Saturating, CheckedConversion,99 },100 generic::Era,101 transaction_validity::TransactionValidityError,102 DispatchErrorWithPostInfo, SaturatedConversion,103};104105// pub use pallet_timestamp::Call as TimestampCall;106pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;107108// Polkadot imports109use pallet_xcm::XcmPassthrough;110use polkadot_parachain::primitives::Sibling;111use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*};112use xcm_builder::{113 AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter,114 EnsureXcmOrigin, FixedWeightBounds, LocationInverter, NativeAsset, ParentAsSuperuser,115 RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,116 SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,117 ParentIsPreset,118};119use xcm_executor::{Config, XcmExecutor, Assets};120use sp_std::{cmp::Ordering, marker::PhantomData};121122use xcm::latest::{123 // Xcm,124 AssetId::{Concrete},125 Fungibility::Fungible as XcmFungible,126 MultiAsset,127 Error as XcmError,128};129use xcm_executor::traits::{MatchesFungible, WeightTrader};130131use unique_runtime_common::{132 impl_common_runtime_apis,133 types::*,134 constants::*,135 dispatch::{CollectionDispatchT, CollectionDispatch},136 sponsoring::UniqueSponsorshipHandler,137 eth_sponsoring::UniqueEthSponsorshipHandler,138 weights::CommonWeights,139};140141pub const RUNTIME_NAME: &str = "unique";142pub const TOKEN_SYMBOL: &str = "UNQ";143144type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Runtime>;145146impl RuntimeInstance for Runtime {147 type CrossAccountId = self::CrossAccountId;148 type TransactionConverter = self::TransactionConverter;149150 fn get_transaction_converter() -> TransactionConverter {151 TransactionConverter152 }153}154155/// The type for looking up accounts. We don't expect more than 4 billion of them, but you156/// never know...157pub type AccountIndex = u32;158159/// Balance of an account.160pub type Balance = u128;161162/// Index of a transaction in the chain.163pub type Index = u32;164165/// A hash of some data used by the chain.166pub type Hash = sp_core::H256;167168/// Digest item type.169pub type DigestItem = generic::DigestItem;170171/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know172/// the specifics of the runtime. They can then be made to be agnostic over specific formats173/// of data like extrinsics, allowing for them to continue syncing the network through upgrades174/// to even the core data structures.175pub mod opaque {176 use sp_std::prelude::*;177 use sp_runtime::impl_opaque_keys;178 use super::Aura;179180 pub use unique_runtime_common::types::*;181182 impl_opaque_keys! {183 pub struct SessionKeys {184 pub aura: Aura,185 }186 }187}188189/// This runtime version.190pub const VERSION: RuntimeVersion = RuntimeVersion {191 spec_name: create_runtime_str!(RUNTIME_NAME),192 impl_name: create_runtime_str!(RUNTIME_NAME),193 authoring_version: 1,194 spec_version: 922000,195 impl_version: 0,196 apis: RUNTIME_API_VERSIONS,197 transaction_version: 1,198 state_version: 0,199};200201#[derive(codec::Encode, codec::Decode)]202pub enum XCMPMessage<XAccountId, XBalance> {203 /// Transfer tokens to the given account from the Parachain account.204 TransferToken(XAccountId, XBalance),205}206207/// The version information used to identify this runtime when compiled natively.208#[cfg(feature = "std")]209pub fn native_version() -> NativeVersion {210 NativeVersion {211 runtime_version: VERSION,212 can_author_with: Default::default(),213 }214}215216type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;217218pub struct DealWithFees;219impl OnUnbalanced<NegativeImbalance> for DealWithFees {220 fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance>) {221 if let Some(fees) = fees_then_tips.next() {222 // for fees, 100% to treasury223 let mut split = fees.ration(100, 0);224 if let Some(tips) = fees_then_tips.next() {225 // for tips, if any, 100% to treasury226 tips.ration_merge_into(100, 0, &mut split);227 }228 Treasury::on_unbalanced(split.0);229 // Author::on_unbalanced(split.1);230 }231 }232}233234parameter_types! {235 pub const BlockHashCount: BlockNumber = 2400;236 pub RuntimeBlockLength: BlockLength =237 BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);238 pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);239 pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;240 pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()241 .base_block(BlockExecutionWeight::get())242 .for_class(DispatchClass::all(), |weights| {243 weights.base_extrinsic = ExtrinsicBaseWeight::get();244 })245 .for_class(DispatchClass::Normal, |weights| {246 weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);247 })248 .for_class(DispatchClass::Operational, |weights| {249 weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);250 // Operational transactions have some extra reserved space, so that they251 // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.252 weights.reserved = Some(253 MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT254 );255 })256 .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)257 .build_or_panic();258 pub const Version: RuntimeVersion = VERSION;259 pub const SS58Prefix: u16 = 7391;260}261262parameter_types! {263 pub const ChainId: u64 = 8880;264}265266pub struct FixedFee;267impl FeeCalculator for FixedFee {268 fn min_gas_price() -> (U256, u64) {269 (MIN_GAS_PRICE.into(), 0)270 }271}272273// Assuming slowest ethereum opcode is SSTORE, with gas price of 20000 as our worst case274// (contract, which only writes a lot of data),275// approximating on top of our real store write weight276parameter_types! {277 pub const WritesPerSecond: u64 = WEIGHT_PER_SECOND / <Runtime as frame_system::Config>::DbWeight::get().write;278 pub const GasPerSecond: u64 = WritesPerSecond::get() * 20000;279 pub const WeightPerGas: u64 = WEIGHT_PER_SECOND / GasPerSecond::get();280}281282/// Limiting EVM execution to 50% of block for substrate users and management tasks283/// EVM transaction consumes more weight than substrate's, so we can't rely on them being284/// scheduled fairly285const EVM_DISPATCH_RATIO: Perbill = Perbill::from_percent(50);286parameter_types! {287 pub BlockGasLimit: U256 = U256::from(NORMAL_DISPATCH_RATIO * EVM_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT / WeightPerGas::get());288}289290pub enum FixedGasWeightMapping {}291impl GasWeightMapping for FixedGasWeightMapping {292 fn gas_to_weight(gas: u64) -> Weight {293 gas.saturating_mul(WeightPerGas::get())294 }295 fn weight_to_gas(weight: Weight) -> u64 {296 weight / WeightPerGas::get()297 }298}299300impl pallet_evm::account::Config for Runtime {301 type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Self>;302 type EvmAddressMapping = pallet_evm::HashedAddressMapping<Self::Hashing>;303 type EvmBackwardsAddressMapping = fp_evm_mapping::MapBackwardsAddressTruncated;304}305306impl pallet_evm::Config for Runtime {307 type BlockGasLimit = BlockGasLimit;308 type FeeCalculator = FixedFee;309 type GasWeightMapping = FixedGasWeightMapping;310 type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;311 type CallOrigin = EnsureAddressTruncated<Self>;312 type WithdrawOrigin = EnsureAddressTruncated<Self>;313 type AddressMapping = HashedAddressMapping<Self::Hashing>;314 type PrecompilesType = ();315 type PrecompilesValue = ();316 type Currency = Balances;317 type Event = Event;318 type OnMethodCall = (319 pallet_evm_migration::OnMethodCall<Self>,320 pallet_evm_contract_helpers::HelpersOnMethodCall<Self>,321 CollectionDispatchT<Self>,322 pallet_unique::eth::CollectionHelpersOnMethodCall<Self>,323 );324 type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;325 type ChainId = ChainId;326 type Runner = pallet_evm::runner::stack::Runner<Self>;327 type OnChargeTransaction = pallet_evm::EVMCurrencyAdapter<Balances, DealWithFees>;328 type TransactionValidityHack = pallet_evm_transaction_payment::TransactionValidityHack<Self>;329 type FindAuthor = EthereumFindAuthor<Aura>;330}331332impl pallet_evm_migration::Config for Runtime {333 type WeightInfo = pallet_evm_migration::weights::SubstrateWeight<Self>;334}335336pub struct EthereumFindAuthor<F>(core::marker::PhantomData<F>);337impl<F: FindAuthor<u32>> FindAuthor<H160> for EthereumFindAuthor<F> {338 fn find_author<'a, I>(digests: I) -> Option<H160>339 where340 I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,341 {342 if let Some(author_index) = F::find_author(digests) {343 let authority_id = Aura::authorities()[author_index as usize].clone();344 return Some(H160::from_slice(&authority_id.to_raw_vec()[4..24]));345 }346 None347 }348}349350impl pallet_ethereum::Config for Runtime {351 type Event = Event;352 type StateRoot = pallet_ethereum::IntermediateStateRoot<Self>;353}354355impl pallet_randomness_collective_flip::Config for Runtime {}356357impl frame_system::Config for Runtime {358 /// The data to be stored in an account.359 type AccountData = pallet_balances::AccountData<Balance>;360 /// The identifier used to distinguish between accounts.361 type AccountId = AccountId;362 /// The basic call filter to use in dispatchable.363 type BaseCallFilter = Everything;364 /// Maximum number of block number to block hash mappings to keep (oldest pruned first).365 type BlockHashCount = BlockHashCount;366 /// The maximum length of a block (in bytes).367 type BlockLength = RuntimeBlockLength;368 /// The index type for blocks.369 type BlockNumber = BlockNumber;370 /// The weight of the overhead invoked on the block import process, independent of the extrinsics included in that block.371 type BlockWeights = RuntimeBlockWeights;372 /// The aggregated dispatch type that is available for extrinsics.373 type Call = Call;374 /// The weight of database operations that the runtime can invoke.375 type DbWeight = RocksDbWeight;376 /// The ubiquitous event type.377 type Event = Event;378 /// The type for hashing blocks and tries.379 type Hash = Hash;380 /// The hashing algorithm used.381 type Hashing = BlakeTwo256;382 /// The header type.383 type Header = generic::Header<BlockNumber, BlakeTwo256>;384 /// The index type for storing how many extrinsics an account has signed.385 type Index = Index;386 /// The lookup mechanism to get account ID from whatever is passed in dispatchers.387 type Lookup = AccountIdLookup<AccountId, ()>;388 /// What to do if an account is fully reaped from the system.389 type OnKilledAccount = ();390 /// What to do if a new account is created.391 type OnNewAccount = ();392 type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;393 /// The ubiquitous origin type.394 type Origin = Origin;395 /// This type is being generated by `construct_runtime!`.396 type PalletInfo = PalletInfo;397 /// This is used as an identifier of the chain. 42 is the generic substrate prefix.398 type SS58Prefix = SS58Prefix;399 /// Weight information for the extrinsics of this pallet.400 type SystemWeightInfo = frame_system::weights::SubstrateWeight<Self>;401 /// Version of the runtime.402 type Version = Version;403 type MaxConsumers = ConstU32<16>;404}405406parameter_types! {407 pub const MinimumPeriod: u64 = SLOT_DURATION / 2;408}409410impl pallet_timestamp::Config for Runtime {411 /// A timestamp: milliseconds since the unix epoch.412 type Moment = u64;413 type OnTimestampSet = ();414 type MinimumPeriod = MinimumPeriod;415 type WeightInfo = ();416}417418parameter_types! {419 // pub const ExistentialDeposit: u128 = 500;420 pub const ExistentialDeposit: u128 = 0;421 pub const MaxLocks: u32 = 50;422 pub const MaxReserves: u32 = 50;423}424425impl pallet_balances::Config for Runtime {426 type MaxLocks = MaxLocks;427 type MaxReserves = MaxReserves;428 type ReserveIdentifier = [u8; 16];429 /// The type for recording an account's balance.430 type Balance = Balance;431 /// The ubiquitous event type.432 type Event = Event;433 type DustRemoval = Treasury;434 type ExistentialDeposit = ExistentialDeposit;435 type AccountStore = System;436 type WeightInfo = pallet_balances::weights::SubstrateWeight<Self>;437}438439pub const fn deposit(items: u32, bytes: u32) -> Balance {440 items as Balance * 15 * CENTIUNIQUE + (bytes as Balance) * 6 * CENTIUNIQUE441}442443/*444parameter_types! {445 pub TombstoneDeposit: Balance = deposit(446 1,447 sp_std::mem::size_of::<pallet_contracts::Pallet<Runtime>> as u32,448 );449 pub DepositPerContract: Balance = TombstoneDeposit::get();450 pub const DepositPerStorageByte: Balance = deposit(0, 1);451 pub const DepositPerStorageItem: Balance = deposit(1, 0);452 pub RentFraction: Perbill = Perbill::from_rational(1u32, 30 * DAYS);453 pub const SurchargeReward: Balance = 150 * MILLIUNIQUE;454 pub const SignedClaimHandicap: u32 = 2;455 pub const MaxDepth: u32 = 32;456 pub const MaxValueSize: u32 = 16 * 1024;457 pub const MaxCodeSize: u32 = 1024 * 1024 * 25; // 25 Mb458 // The lazy deletion runs inside on_initialize.459 pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO *460 RuntimeBlockWeights::get().max_block;461 // The weight needed for decoding the queue should be less or equal than a fifth462 // of the overall weight dedicated to the lazy deletion.463 pub DeletionQueueDepth: u32 = ((DeletionWeightLimit::get() / (464 <Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(1) -465 <Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(0)466 )) / 5) as u32;467 pub Schedule: pallet_contracts::Schedule<Runtime> = Default::default();468}469470impl pallet_contracts::Config for Runtime {471 type Time = Timestamp;472 type Randomness = RandomnessCollectiveFlip;473 type Currency = Balances;474 type Event = Event;475 type RentPayment = ();476 type SignedClaimHandicap = SignedClaimHandicap;477 type TombstoneDeposit = TombstoneDeposit;478 type DepositPerContract = DepositPerContract;479 type DepositPerStorageByte = DepositPerStorageByte;480 type DepositPerStorageItem = DepositPerStorageItem;481 type RentFraction = RentFraction;482 type SurchargeReward = SurchargeReward;483 type WeightPrice = pallet_transaction_payment::Pallet<Self>;484 type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;485 type ChainExtension = NFTExtension;486 type DeletionQueueDepth = DeletionQueueDepth;487 type DeletionWeightLimit = DeletionWeightLimit;488 type Schedule = Schedule;489 type CallStack = [pallet_contracts::Frame<Self>; 31];490}491*/492493parameter_types! {494 /// This value increases the priority of `Operational` transactions by adding495 /// a "virtual tip" that's equal to the `OperationalFeeMultiplier * final_fee`.496 pub const OperationalFeeMultiplier: u8 = 5;497}498499/// Linear implementor of `WeightToFeePolynomial`500pub struct LinearFee<T>(sp_std::marker::PhantomData<T>);501502impl<T> WeightToFeePolynomial for LinearFee<T>503where504 T: BaseArithmetic + From<u32> + Copy + Unsigned,505{506 type Balance = T;507508 fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {509 smallvec!(WeightToFeeCoefficient {510 // Targeting 0.1 Unique per NFT transfer511 coeff_integer: WEIGHT_TO_FEE_COEFF.into(),512 coeff_frac: Perbill::zero(),513 negative: false,514 degree: 1,515 })516 }517}518519impl pallet_transaction_payment::Config for Runtime {520 type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, DealWithFees>;521 type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;522 type OperationalFeeMultiplier = OperationalFeeMultiplier;523 type WeightToFee = LinearFee<Balance>;524 type FeeMultiplierUpdate = ();525}526527parameter_types! {528 pub const ProposalBond: Permill = Permill::from_percent(5);529 pub const ProposalBondMinimum: Balance = 1 * UNIQUE;530 pub const ProposalBondMaximum: Balance = 1000 * UNIQUE;531 pub const SpendPeriod: BlockNumber = 5 * MINUTES;532 pub const Burn: Permill = Permill::from_percent(0);533 pub const TipCountdown: BlockNumber = 1 * DAYS;534 pub const TipFindersFee: Percent = Percent::from_percent(20);535 pub const TipReportDepositBase: Balance = 1 * UNIQUE;536 pub const DataDepositPerByte: Balance = 1 * CENTIUNIQUE;537 pub const BountyDepositBase: Balance = 1 * UNIQUE;538 pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS;539 pub const TreasuryModuleId: PalletId = PalletId(*b"py/trsry");540 pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS;541 pub const MaximumReasonLength: u32 = 16384;542 pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);543 pub const BountyValueMinimum: Balance = 5 * UNIQUE;544 pub const MaxApprovals: u32 = 100;545}546547impl pallet_treasury::Config for Runtime {548 type PalletId = TreasuryModuleId;549 type Currency = Balances;550 type ApproveOrigin = EnsureRoot<AccountId>;551 type RejectOrigin = EnsureRoot<AccountId>;552 type Event = Event;553 type OnSlash = ();554 type ProposalBond = ProposalBond;555 type ProposalBondMinimum = ProposalBondMinimum;556 type ProposalBondMaximum = ProposalBondMaximum;557 type SpendPeriod = SpendPeriod;558 type Burn = Burn;559 type BurnDestination = ();560 type SpendFunds = ();561 type WeightInfo = pallet_treasury::weights::SubstrateWeight<Self>;562 type MaxApprovals = MaxApprovals;563}564565impl pallet_sudo::Config for Runtime {566 type Event = Event;567 type Call = Call;568}569570pub struct RelayChainBlockNumberProvider<T>(sp_std::marker::PhantomData<T>);571572impl<T: cumulus_pallet_parachain_system::Config> BlockNumberProvider573 for RelayChainBlockNumberProvider<T>574{575 type BlockNumber = BlockNumber;576577 fn current_block_number() -> Self::BlockNumber {578 cumulus_pallet_parachain_system::Pallet::<T>::validation_data()579 .map(|d| d.relay_parent_number)580 .unwrap_or_default()581 }582}583584parameter_types! {585 pub const MinVestedTransfer: Balance = 10 * UNIQUE;586 pub const MaxVestingSchedules: u32 = 28;587}588589impl orml_vesting::Config for Runtime {590 type Event = Event;591 type Currency = pallet_balances::Pallet<Runtime>;592 type MinVestedTransfer = MinVestedTransfer;593 type VestedTransferOrigin = EnsureSigned<AccountId>;594 type WeightInfo = ();595 type MaxVestingSchedules = MaxVestingSchedules;596 type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;597}598599parameter_types! {600 pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;601 pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;602}603604impl cumulus_pallet_parachain_system::Config for Runtime {605 type Event = Event;606 type SelfParaId = parachain_info::Pallet<Self>;607 type OnSystemEvent = ();608 // type DownwardMessageHandlers = cumulus_primitives_utility::UnqueuedDmpAsParent<609 // MaxDownwardMessageWeight,610 // XcmExecutor<XcmConfig>,611 // Call,612 // >;613 type OutboundXcmpMessageSource = XcmpQueue;614 type DmpMessageHandler = DmpQueue;615 type ReservedDmpWeight = ReservedDmpWeight;616 type ReservedXcmpWeight = ReservedXcmpWeight;617 type XcmpMessageHandler = XcmpQueue;618}619620impl parachain_info::Config for Runtime {}621622impl cumulus_pallet_aura_ext::Config for Runtime {}623624parameter_types! {625 pub const RelayLocation: MultiLocation = MultiLocation::parent();626 pub const RelayNetwork: NetworkId = NetworkId::Polkadot;627 pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();628 pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();629}630631/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used632/// when determining ownership of accounts for asset transacting and when attempting to use XCM633/// `Transact` in order to determine the dispatch Origin.634pub type LocationToAccountId = (635 // The parent (Relay-chain) origin converts to the default `AccountId`.636 ParentIsPreset<AccountId>,637 // Sibling parachain origins convert to AccountId via the `ParaId::into`.638 SiblingParachainConvertsVia<Sibling, AccountId>,639 // Straight up local `AccountId32` origins just alias directly to `AccountId`.640 AccountId32Aliases<RelayNetwork, AccountId>,641);642643pub struct OnlySelfCurrency;644impl<B: TryFrom<u128>> MatchesFungible<B> for OnlySelfCurrency {645 fn matches_fungible(a: &MultiAsset) -> Option<B> {646 match (&a.id, &a.fun) {647 (Concrete(_), XcmFungible(ref amount)) => CheckedConversion::checked_from(*amount),648 _ => None,649 }650 }651}652653/// Means for transacting assets on this chain.654pub type LocalAssetTransactor = CurrencyAdapter<655 // Use this currency:656 Balances,657 // Use this currency when it is a fungible asset matching the given location or name:658 OnlySelfCurrency,659 // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:660 LocationToAccountId,661 // Our chain's account ID type (we can't get away without mentioning it explicitly):662 AccountId,663 // We don't track any teleports.664 (),665>;666667/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,668/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can669/// biases the kind of local `Origin` it will become.670pub type XcmOriginToTransactDispatchOrigin = (671 // Sovereign account converter; this attempts to derive an `AccountId` from the origin location672 // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for673 // foreign chains who want to have a local sovereign account on this chain which they control.674 SovereignSignedViaLocation<LocationToAccountId, Origin>,675 // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when676 // recognised.677 RelayChainAsNative<RelayOrigin, Origin>,678 // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when679 // recognised.680 SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,681 // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a682 // transaction from the Root origin.683 ParentAsSuperuser<Origin>,684 // Native signed account converter; this just converts an `AccountId32` origin into a normal685 // `Origin::Signed` origin of the same 32-byte value.686 SignedAccountId32AsNative<RelayNetwork, Origin>,687 // Xcm origins can be represented natively under the Xcm pallet's Xcm origin.688 XcmPassthrough<Origin>,689);690691parameter_types! {692 // One XCM operation is 1_000_000 weight - almost certainly a conservative estimate.693 pub UnitWeightCost: Weight = 1_000_000;694 // 1200 UNIQUEs buy 1 second of weight.695 pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), 1_200 * UNIQUE);696 pub const MaxInstructions: u32 = 100;697 pub const MaxAuthorities: u32 = 100_000;698}699700match_types! {701 pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {702 MultiLocation { parents: 1, interior: Here } |703 MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }704 };705}706707pub type Barrier = (708 TakeWeightCredit,709 AllowTopLevelPaidExecutionFrom<Everything>,710 AllowUnpaidExecutionFrom<ParentOrParentsUnitPlurality>,711 // ^^^ Parent & its unit plurality gets free execution712);713714pub struct UsingOnlySelfCurrencyComponents<715 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,716 AssetId: Get<MultiLocation>,717 AccountId,718 Currency: CurrencyT<AccountId>,719 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,720>(721 Weight,722 Currency::Balance,723 PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>,724);725impl<726 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,727 AssetId: Get<MultiLocation>,728 AccountId,729 Currency: CurrencyT<AccountId>,730 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,731 > WeightTrader732 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>733{734 fn new() -> Self {735 Self(0, Zero::zero(), PhantomData)736 }737738 fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, XcmError> {739 let amount = WeightToFee::calc(&weight);740 let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?;741742 // location to this parachain through relay chain743 let option1: xcm::v1::AssetId = Concrete(MultiLocation {744 parents: 1,745 interior: X1(Parachain(ParachainInfo::parachain_id().into())),746 });747 // direct location748 let option2: xcm::v1::AssetId = Concrete(MultiLocation {749 parents: 0,750 interior: Here,751 });752753 let required = if payment.fungible.contains_key(&option1) {754 (option1, u128_amount).into()755 } else if payment.fungible.contains_key(&option2) {756 (option2, u128_amount).into()757 } else {758 (Concrete(MultiLocation::default()), u128_amount).into()759 };760761 let unused = payment762 .checked_sub(required)763 .map_err(|_| XcmError::TooExpensive)?;764 self.0 = self.0.saturating_add(weight);765 self.1 = self.1.saturating_add(amount);766 Ok(unused)767 }768769 fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {770 let weight = weight.min(self.0);771 let amount = WeightToFee::calc(&weight);772 self.0 -= weight;773 self.1 = self.1.saturating_sub(amount);774 let amount: u128 = amount.saturated_into();775 if amount > 0 {776 Some((AssetId::get(), amount).into())777 } else {778 None779 }780 }781}782impl<783 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,784 AssetId: Get<MultiLocation>,785 AccountId,786 Currency: CurrencyT<AccountId>,787 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,788 > Drop789 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>790{791 fn drop(&mut self) {792 OnUnbalanced::on_unbalanced(Currency::issue(self.1));793 }794}795796pub struct XcmConfig;797impl Config for XcmConfig {798 type Call = Call;799 type XcmSender = XcmRouter;800 // How to withdraw and deposit an asset.801 type AssetTransactor = LocalAssetTransactor;802 type OriginConverter = XcmOriginToTransactDispatchOrigin;803 type IsReserve = NativeAsset;804 type IsTeleporter = (); // Teleportation is disabled805 type LocationInverter = LocationInverter<Ancestry>;806 type Barrier = Barrier;807 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;808 type Trader = UsingOnlySelfCurrencyComponents<809 IdentityFee<Balance>,810 RelayLocation,811 AccountId,812 Balances,813 (),814 >;815 type ResponseHandler = (); // Don't handle responses for now.816 type SubscriptionService = PolkadotXcm;817818 type AssetTrap = PolkadotXcm;819 type AssetClaims = PolkadotXcm;820}821822// parameter_types! {823// pub const MaxDownwardMessageWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 10;824// }825826/// No local origins on this chain are allowed to dispatch XCM sends/executions.827pub type LocalOriginToLocation = (SignedToAccountId32<Origin, AccountId, RelayNetwork>,);828829/// The means for routing XCM messages which are not for local execution into the right message830/// queues.831pub type XcmRouter = (832 // Two routers - use UMP to communicate with the relay chain:833 cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,834 // ..and XCMP to communicate with the sibling chains.835 XcmpQueue,836);837838impl pallet_evm_coder_substrate::Config for Runtime {}839840impl pallet_xcm::Config for Runtime {841 type Event = Event;842 type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;843 type XcmRouter = XcmRouter;844 type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;845 type XcmExecuteFilter = Everything;846 type XcmExecutor = XcmExecutor<XcmConfig>;847 type XcmTeleportFilter = Everything;848 type XcmReserveTransferFilter = Everything;849 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;850 type LocationInverter = LocationInverter<Ancestry>;851 type Origin = Origin;852 type Call = Call;853 const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;854 type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;855}856857impl cumulus_pallet_xcm::Config for Runtime {858 type Event = Event;859 type XcmExecutor = XcmExecutor<XcmConfig>;860}861862impl cumulus_pallet_xcmp_queue::Config for Runtime {863 type WeightInfo = ();864 type Event = Event;865 type XcmExecutor = XcmExecutor<XcmConfig>;866 type ChannelInfo = ParachainSystem;867 type VersionWrapper = ();868 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;869 type ControllerOrigin = EnsureRoot<AccountId>;870 type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;871}872873impl cumulus_pallet_dmp_queue::Config for Runtime {874 type Event = Event;875 type XcmExecutor = XcmExecutor<XcmConfig>;876 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;877}878879impl pallet_aura::Config for Runtime {880 type AuthorityId = AuraId;881 type DisabledValidators = ();882 type MaxAuthorities = MaxAuthorities;883}884885parameter_types! {886 pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account();887 pub const CollectionCreationPrice: Balance = 2 * UNIQUE;888}889890impl pallet_common::Config for Runtime {891 type WeightInfo = pallet_common::weights::SubstrateWeight<Self>;892 type Event = Event;893 type Currency = Balances;894 type CollectionCreationPrice = CollectionCreationPrice;895 type TreasuryAccountId = TreasuryAccountId;896 type CollectionDispatch = CollectionDispatchT<Self>;897898 type EvmTokenAddressMapping = EvmTokenAddressMapping;899 type CrossTokenAddressMapping = CrossTokenAddressMapping<Self::AccountId>;900 type ContractAddress = EvmCollectionHelpersAddress;901}902903impl pallet_structure::Config for Runtime {904 type Event = Event;905 type Call = Call;906 type WeightInfo = pallet_structure::weights::SubstrateWeight<Self>;907}908909impl pallet_fungible::Config for Runtime {910 type WeightInfo = pallet_fungible::weights::SubstrateWeight<Self>;911}912impl pallet_refungible::Config for Runtime {913 type WeightInfo = pallet_refungible::weights::SubstrateWeight<Self>;914}915impl pallet_nonfungible::Config for Runtime {916 type WeightInfo = pallet_nonfungible::weights::SubstrateWeight<Self>;917}918919impl pallet_proxy_rmrk_core::Config for Runtime {920 type WeightInfo = pallet_proxy_rmrk_core::weights::SubstrateWeight<Self>;921 type Event = Event;922}923924impl pallet_proxy_rmrk_equip::Config for Runtime {925 type Event = Event;926}927928impl pallet_unique::Config for Runtime {929 type Event = Event;930 type WeightInfo = pallet_unique::weights::SubstrateWeight<Self>;931 type CommonWeightInfo = CommonWeights<Self>;932}933934parameter_types! {935 pub const InflationBlockInterval: BlockNumber = 100; // every time per how many blocks inflation is applied936}937938/// Used for the pallet inflation939impl pallet_inflation::Config for Runtime {940 type Currency = Balances;941 type TreasuryAccountId = TreasuryAccountId;942 type InflationBlockInterval = InflationBlockInterval;943 type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;944}945946parameter_types! {947 pub MaximumSchedulerWeight: Weight = Perbill::from_percent(50) *948 RuntimeBlockWeights::get().max_block;949 pub const MaxScheduledPerBlock: u32 = 50;950}951952type ChargeTransactionPayment = pallet_charge_transaction::ChargeTransactionPayment<Runtime>;953use frame_support::traits::NamedReservableCurrency;954955fn get_signed_extras(from: <Runtime as frame_system::Config>::AccountId) -> SignedExtraScheduler {956 (957 frame_system::CheckSpecVersion::<Runtime>::new(),958 frame_system::CheckGenesis::<Runtime>::new(),959 frame_system::CheckEra::<Runtime>::from(Era::Immortal),960 frame_system::CheckNonce::<Runtime>::from(frame_system::Pallet::<Runtime>::account_nonce(961 from,962 )),963 frame_system::CheckWeight::<Runtime>::new(),964 // sponsoring transaction logic965 // pallet_charge_transaction::ChargeTransactionPayment::<Runtime>::new(0),966 )967}968969pub struct SchedulerPaymentExecutor;970impl<T: frame_system::Config + pallet_unq_scheduler::Config, SelfContainedSignedInfo>971 DispatchCall<T, SelfContainedSignedInfo> for SchedulerPaymentExecutor972where973 <T as frame_system::Config>::Call: Member974 + Dispatchable<Origin = Origin, Info = DispatchInfo>975 + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>976 + GetDispatchInfo977 + From<frame_system::Call<Runtime>>,978 SelfContainedSignedInfo: Send + Sync + 'static,979 Call: From<<T as frame_system::Config>::Call>980 + From<<T as pallet_unq_scheduler::Config>::Call>981 + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>,982 sp_runtime::AccountId32: From<<T as frame_system::Config>::AccountId>,983{984 fn dispatch_call(985 signer: <T as frame_system::Config>::AccountId,986 call: <T as pallet_unq_scheduler::Config>::Call,987 ) -> Result<988 Result<PostDispatchInfo, DispatchErrorWithPostInfo<PostDispatchInfo>>,989 TransactionValidityError,990 > {991 let dispatch_info = call.get_dispatch_info();992 let extrinsic = fp_self_contained::CheckedExtrinsic::<993 AccountId,994 Call,995 SignedExtraScheduler,996 SelfContainedSignedInfo,997 > {998 signed:999 CheckedSignature::<AccountId, SignedExtraScheduler, SelfContainedSignedInfo>::Signed(1000 signer.clone().into(),1001 get_signed_extras(signer.into()),1002 ),1003 function: call.into(),1004 };10051006 extrinsic.apply::<Runtime>(&dispatch_info, 0)1007 }10081009 fn reserve_balance(1010 id: [u8; 16],1011 sponsor: <T as frame_system::Config>::AccountId,1012 call: <T as pallet_unq_scheduler::Config>::Call,1013 count: u32,1014 ) -> Result<(), DispatchError> {1015 let dispatch_info = call.get_dispatch_info();1016 let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0)1017 .saturating_mul(count.into());10181019 <Balances as NamedReservableCurrency<AccountId>>::reserve_named(1020 &id,1021 &(sponsor.into()),1022 weight,1023 )1024 }10251026 fn pay_for_call(1027 id: [u8; 16],1028 sponsor: <T as frame_system::Config>::AccountId,1029 call: <T as pallet_unq_scheduler::Config>::Call,1030 ) -> Result<u128, DispatchError> {1031 let dispatch_info = call.get_dispatch_info();1032 let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0);1033 Ok(1034 <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(1035 &id,1036 &(sponsor.into()),1037 weight,1038 ),1039 )1040 }10411042 fn cancel_reserve(1043 id: [u8; 16],1044 sponsor: <T as frame_system::Config>::AccountId,1045 ) -> Result<u128, DispatchError> {1046 Ok(1047 <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(1048 &id,1049 &(sponsor.into()),1050 u128::MAX,1051 ),1052 )1053 }1054}10551056parameter_types! {1057 pub const NoPreimagePostponement: Option<u32> = Some(10);1058 pub const Preimage: Option<u32> = Some(10);1059}10601061/// Used the compare the privilege of an origin inside the scheduler.1062pub struct OriginPrivilegeCmp;10631064impl PrivilegeCmp<OriginCaller> for OriginPrivilegeCmp {1065 fn cmp_privilege(_left: &OriginCaller, _right: &OriginCaller) -> Option<Ordering> {1066 Some(Ordering::Equal)1067 }1068}10691070impl pallet_unq_scheduler::Config for Runtime {1071 type Event = Event;1072 type Origin = Origin;1073 type Currency = Balances;1074 type PalletsOrigin = OriginCaller;1075 type Call = Call;1076 type MaximumWeight = MaximumSchedulerWeight;1077 type ScheduleOrigin = EnsureSigned<AccountId>;1078 type MaxScheduledPerBlock = MaxScheduledPerBlock;1079 type WeightInfo = ();1080 type CallExecutor = SchedulerPaymentExecutor;1081 type OriginPrivilegeCmp = OriginPrivilegeCmp;1082 type PreimageProvider = ();1083 type NoPreimagePostponement = NoPreimagePostponement;1084}10851086type EvmSponsorshipHandler = (1087 UniqueEthSponsorshipHandler<Runtime>,1088 pallet_evm_contract_helpers::HelpersContractSponsoring<Runtime>,1089);1090type SponsorshipHandler = (1091 UniqueSponsorshipHandler<Runtime>,1092 //pallet_contract_helpers::ContractSponsorshipHandler<Runtime>,1093 pallet_evm_transaction_payment::BridgeSponsorshipHandler<Runtime>,1094);10951096impl pallet_evm_transaction_payment::Config for Runtime {1097 type EvmSponsorshipHandler = EvmSponsorshipHandler;1098 type Currency = Balances;1099}11001101impl pallet_charge_transaction::Config for Runtime {1102 type SponsorshipHandler = SponsorshipHandler;1103}11041105// impl pallet_contract_helpers::Config for Runtime {1106// type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;1107// }11081109parameter_types! {1110 // 0x842899ECF380553E8a4de75bF534cdf6fBF640491111 pub const HelpersContractAddress: H160 = H160([1112 0x84, 0x28, 0x99, 0xec, 0xf3, 0x80, 0x55, 0x3e, 0x8a, 0x4d, 0xe7, 0x5b, 0xf5, 0x34, 0xcd, 0xf6, 0xfb, 0xf6, 0x40, 0x49,1113 ]);11141115 // 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f1116 pub const EvmCollectionHelpersAddress: H160 = H160([1117 0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f,1118 ]);1119}11201121impl pallet_evm_contract_helpers::Config for Runtime {1122 type ContractAddress = HelpersContractAddress;1123 type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;1124}11251126construct_runtime!(1127 pub enum Runtime where1128 Block = Block,1129 NodeBlock = opaque::Block,1130 UncheckedExtrinsic = UncheckedExtrinsic1131 {1132 ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Config, Storage, Inherent, Event<T>, ValidateUnsigned} = 20,1133 ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21,11341135 Aura: pallet_aura::{Pallet, Config<T>} = 22,1136 AuraExt: cumulus_pallet_aura_ext::{Pallet, Config} = 23,11371138 Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 30,1139 RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage} = 31,1140 Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 32,1141 TransactionPayment: pallet_transaction_payment::{Pallet, Storage} = 33,1142 Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event<T>} = 34,1143 Sudo: pallet_sudo::{Pallet, Call, Storage, Config<T>, Event<T>} = 35,1144 System: frame_system::{Pallet, Call, Storage, Config, Event<T>} = 36,1145 Vesting: orml_vesting::{Pallet, Storage, Call, Event<T>, Config<T>} = 37,1146 // Vesting: pallet_vesting::{Pallet, Call, Config<T>, Storage, Event<T>} = 37,1147 // Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>} = 38,11481149 // XCM helpers.1150 XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 50,1151 PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin} = 51,1152 CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event<T>, Origin} = 52,1153 DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 53,11541155 // Unique Pallets1156 Inflation: pallet_inflation::{Pallet, Call, Storage} = 60,1157 Unique: pallet_unique::{Pallet, Call, Storage, Event<T>} = 61,1158 Scheduler: pallet_unq_scheduler::{Pallet, Call, Storage, Event<T>} = 62,1159 // free = 631160 Charging: pallet_charge_transaction::{Pallet, Call, Storage } = 64,1161 // ContractHelpers: pallet_contract_helpers::{Pallet, Call, Storage} = 65,1162 Common: pallet_common::{Pallet, Storage, Event<T>} = 66,1163 Fungible: pallet_fungible::{Pallet, Storage} = 67,1164 Refungible: pallet_refungible::{Pallet, Storage} = 68,1165 Nonfungible: pallet_nonfungible::{Pallet, Storage} = 69,1166 Structure: pallet_structure::{Pallet, Call, Storage, Event<T>} = 70,1167 RmrkCore: pallet_proxy_rmrk_core::{Pallet, Call, Storage, Event<T>} = 71,1168 RmrkEquip: pallet_proxy_rmrk_equip::{Pallet, Call, Storage, Event<T>} = 72,11691170 // Frontier1171 EVM: pallet_evm::{Pallet, Config, Call, Storage, Event<T>} = 100,1172 Ethereum: pallet_ethereum::{Pallet, Config, Call, Storage, Event, Origin} = 101,11731174 EvmCoderSubstrate: pallet_evm_coder_substrate::{Pallet, Storage} = 150,1175 EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage} = 151,1176 EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152,1177 EvmMigration: pallet_evm_migration::{Pallet, Call, Storage} = 153,1178 }1179);11801181pub struct TransactionConverter;11821183impl fp_rpc::ConvertTransaction<UncheckedExtrinsic> for TransactionConverter {1184 fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> UncheckedExtrinsic {1185 UncheckedExtrinsic::new_unsigned(1186 pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),1187 )1188 }1189}11901191impl fp_rpc::ConvertTransaction<opaque::UncheckedExtrinsic> for TransactionConverter {1192 fn convert_transaction(1193 &self,1194 transaction: pallet_ethereum::Transaction,1195 ) -> opaque::UncheckedExtrinsic {1196 let extrinsic = UncheckedExtrinsic::new_unsigned(1197 pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),1198 );1199 let encoded = extrinsic.encode();1200 opaque::UncheckedExtrinsic::decode(&mut &encoded[..])1201 .expect("Encoded extrinsic is always valid")1202 }1203}12041205/// The address format for describing accounts.1206pub type Address = sp_runtime::MultiAddress<AccountId, ()>;1207/// Block header type as expected by this runtime.1208pub type Header = generic::Header<BlockNumber, BlakeTwo256>;1209/// Block type as expected by this runtime.1210pub type Block = generic::Block<Header, UncheckedExtrinsic>;1211/// A Block signed with a Justification1212pub type SignedBlock = generic::SignedBlock<Block>;1213/// BlockId type as expected by this runtime.1214pub type BlockId = generic::BlockId<Block>;1215/// The SignedExtension to the basic transaction logic.1216pub type SignedExtra = (1217 frame_system::CheckSpecVersion<Runtime>,1218 // system::CheckTxVersion<Runtime>,1219 frame_system::CheckGenesis<Runtime>,1220 frame_system::CheckEra<Runtime>,1221 frame_system::CheckNonce<Runtime>,1222 frame_system::CheckWeight<Runtime>,1223 pallet_charge_transaction::ChargeTransactionPayment<Runtime>,1224 //pallet_contract_helpers::ContractHelpersExtension<Runtime>,1225 pallet_ethereum::FakeTransactionFinalizer<Runtime>,1226);1227pub type SignedExtraScheduler = (1228 frame_system::CheckSpecVersion<Runtime>,1229 frame_system::CheckGenesis<Runtime>,1230 frame_system::CheckEra<Runtime>,1231 frame_system::CheckNonce<Runtime>,1232 frame_system::CheckWeight<Runtime>,1233 // pallet_charge_transaction::ChargeTransactionPayment<Runtime>,1234);1235/// Unchecked extrinsic type as expected by this runtime.1236pub type UncheckedExtrinsic =1237 fp_self_contained::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;1238/// Extrinsic type that has already been checked.1239pub type CheckedExtrinsic = fp_self_contained::CheckedExtrinsic<AccountId, Call, SignedExtra, H160>;1240/// Executive: handles dispatch to the various modules.1241pub type Executive = frame_executive::Executive<1242 Runtime,1243 Block,1244 frame_system::ChainContext<Runtime>,1245 Runtime,1246 AllPalletsReversedWithSystemFirst,1247>;12481249impl_opaque_keys! {1250 pub struct SessionKeys {1251 pub aura: Aura,1252 }1253}12541255impl fp_self_contained::SelfContainedCall for Call {1256 type SignedInfo = H160;12571258 fn is_self_contained(&self) -> bool {1259 match self {1260 Call::Ethereum(call) => call.is_self_contained(),1261 _ => false,1262 }1263 }12641265 fn check_self_contained(&self) -> Option<Result<Self::SignedInfo, TransactionValidityError>> {1266 match self {1267 Call::Ethereum(call) => call.check_self_contained(),1268 _ => None,1269 }1270 }12711272 fn validate_self_contained(1273 &self,1274 info: &Self::SignedInfo,1275 dispatch_info: &DispatchInfoOf<Call>,1276 len: usize,1277 ) -> Option<TransactionValidity> {1278 match self {1279 Call::Ethereum(call) => call.validate_self_contained(info, dispatch_info, len),1280 _ => None,1281 }1282 }12831284 fn pre_dispatch_self_contained(1285 &self,1286 info: &Self::SignedInfo,1287 ) -> Option<Result<(), TransactionValidityError>> {1288 match self {1289 Call::Ethereum(call) => call.pre_dispatch_self_contained(info),1290 _ => None,1291 }1292 }12931294 fn apply_self_contained(1295 self,1296 info: Self::SignedInfo,1297 ) -> Option<sp_runtime::DispatchResultWithInfo<PostDispatchInfoOf<Self>>> {1298 match self {1299 call @ Call::Ethereum(pallet_ethereum::Call::transact { .. }) => Some(call.dispatch(1300 Origin::from(pallet_ethereum::RawOrigin::EthereumTransaction(info)),1301 )),1302 _ => None,1303 }1304 }1305}13061307macro_rules! dispatch_unique_runtime {1308 ($collection:ident.$method:ident($($name:ident),*)) => {{1309 let collection = <Runtime as pallet_common::Config>::CollectionDispatch::dispatch(<pallet_common::CollectionHandle<Runtime>>::try_get($collection)?);1310 let dispatch = collection.as_dyn();13111312 Ok::<_, DispatchError>(dispatch.$method($($name),*))1313 }};1314}13151316impl_common_runtime_apis!();13171318struct CheckInherents;13191320impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {1321 fn check_inherents(1322 block: &Block,1323 relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof,1324 ) -> sp_inherents::CheckInherentsResult {1325 let relay_chain_slot = relay_state_proof1326 .read_slot()1327 .expect("Could not read the relay chain slot from the proof");13281329 let inherent_data =1330 cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration(1331 relay_chain_slot,1332 sp_std::time::Duration::from_secs(6),1333 )1334 .create_inherent_data()1335 .expect("Could not create the timestamp inherent data");13361337 inherent_data.check_extrinsics(block)1338 }1339}13401341cumulus_pallet_parachain_system::register_validate_block!(1342 Runtime = Runtime,1343 BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,1344 CheckInherents = CheckInherents,1345);tests/src/addCollectionAdmin.test.tsdiffbeforeafterboth--- a/tests/src/addCollectionAdmin.test.ts
+++ b/tests/src/addCollectionAdmin.test.ts
@@ -40,8 +40,10 @@
expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
});
});
+});
- it('Add admin using added collection admin.', async () => {
+describe('Negative Integration Test addCollectionAdmin(collection_id, new_admin_id):', () => {
+ it("Not owner can't add collection admin.", async () => {
await usingApi(async (api, privateKeyWrapper) => {
const collectionId = await createCollectionExpectSuccess();
const alice = privateKeyWrapper('//Alice');
@@ -51,38 +53,43 @@
const collection = await queryCollectionExpectSuccess(api, collectionId);
expect(collection.owner.toString()).to.be.equal(alice.address);
- const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
- await submitTransactionAsync(alice, changeAdminTx);
-
const adminListAfterAddAdmin = await getAdminList(api, collectionId);
- expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
+ expect(adminListAfterAddAdmin).to.be.not.deep.contains(normalizeAccountId(bob.address));
const changeAdminTxCharlie = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(charlie.address));
- await submitTransactionAsync(bob, changeAdminTxCharlie);
+ await expect(submitTransactionAsync(bob, changeAdminTxCharlie)).to.be.rejected;
+
const adminListAfterAddNewAdmin = await getAdminList(api, collectionId);
- expect(adminListAfterAddNewAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
- expect(adminListAfterAddNewAdmin).to.be.deep.contains(normalizeAccountId(charlie.address));
+ expect(adminListAfterAddNewAdmin).to.be.not.deep.contains(normalizeAccountId(bob.address));
+ expect(adminListAfterAddNewAdmin).to.be.not.deep.contains(normalizeAccountId(charlie.address));
});
});
-});
-describe('Negative Integration Test addCollectionAdmin(collection_id, new_admin_id):', () => {
- it("Not owner can't add collection admin.", async () => {
+ it("Admin can't add collection admin.", async () => {
await usingApi(async (api, privateKeyWrapper) => {
const collectionId = await createCollectionExpectSuccess();
const alice = privateKeyWrapper('//Alice');
- const nonOwner = privateKeyWrapper('//Bob_stash');
+ const bob = privateKeyWrapper('//Bob');
+ const charlie = privateKeyWrapper('//CHARLIE');
+
+ const collection = await queryCollectionExpectSuccess(api, collectionId);
+ expect(collection.owner.toString()).to.be.equal(alice.address);
- const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(alice.address));
- await expect(submitTransactionExpectFailAsync(nonOwner, changeAdminTx)).to.be.rejected;
+ const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
+ await submitTransactionAsync(alice, changeAdminTx);
const adminListAfterAddAdmin = await getAdminList(api, collectionId);
- expect(adminListAfterAddAdmin).not.to.be.deep.contains(normalizeAccountId(alice.address));
+ expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
- // Verifying that nothing bad happened (network is live, new collections can be created, etc.)
- await createCollectionExpectSuccess();
+ const changeAdminTxCharlie = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(charlie.address));
+ await expect(submitTransactionAsync(bob, changeAdminTxCharlie)).to.be.rejected;
+
+ const adminListAfterAddNewAdmin = await getAdminList(api, collectionId);
+ expect(adminListAfterAddNewAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
+ expect(adminListAfterAddNewAdmin).to.be.not.deep.contains(normalizeAccountId(charlie.address));
});
});
+
it("Can't add collection admin of not existing collection.", async () => {
await usingApi(async (api, privateKeyWrapper) => {
// tslint:disable-next-line: no-bitwise
tests/src/eth/allowlist.test.tsdiffbeforeafterboth--- a/tests/src/eth/allowlist.test.ts
+++ b/tests/src/eth/allowlist.test.ts
@@ -18,8 +18,8 @@
import {contractHelpers, createEthAccountWithBalance, deployFlipper, itWeb3} from './util/helpers';
describe('EVM allowlist', () => {
- itWeb3('Contract allowlist can be toggled', async ({api, web3}) => {
- const owner = await createEthAccountWithBalance(api, web3);
+ itWeb3('Contract allowlist can be toggled', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const flipper = await deployFlipper(web3, owner);
const helpers = contractHelpers(web3, owner);
@@ -36,10 +36,10 @@
expect(await helpers.methods.allowlistEnabled(flipper.options.address).call()).to.be.false;
});
- itWeb3('Non-allowlisted user can\'t call contract with allowlist enabled', async ({api, web3}) => {
- const owner = await createEthAccountWithBalance(api, web3);
+ itWeb3('Non-allowlisted user can\'t call contract with allowlist enabled', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const flipper = await deployFlipper(web3, owner);
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const helpers = contractHelpers(web3, owner);
tests/src/eth/base.test.tsdiffbeforeafterboth--- a/tests/src/eth/base.test.ts
+++ b/tests/src/eth/base.test.ts
@@ -32,16 +32,16 @@
import Web3 from 'web3';
describe('Contract calls', () => {
- itWeb3('Call of simple contract fee is less than 0.2 UNQ', async ({web3, api}) => {
- const deployer = await createEthAccountWithBalance(api, web3);
+ itWeb3('Call of simple contract fee is less than 0.2 UNQ', async ({web3, api, privateKeyWrapper}) => {
+ const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const flipper = await deployFlipper(web3, deployer);
const cost = await recordEthFee(api, deployer, () => flipper.methods.flip().send({from: deployer}));
expect(cost < BigInt(0.2 * Number(UNIQUE))).to.be.true;
});
- itWeb3('Balance transfer fee is less than 0.2 UNQ', async ({web3, api}) => {
- const userA = await createEthAccountWithBalance(api, web3);
+ itWeb3('Balance transfer fee is less than 0.2 UNQ', async ({web3, api, privateKeyWrapper}) => {
+ const userA = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const userB = createEthAccount(web3);
const cost = await recordEthFee(api, userA, () => web3.eth.sendTransaction({from: userA, to: userB, value: '1000000', ...GAS_ARGS}));
@@ -50,7 +50,7 @@
});
itWeb3('NFT transfer is close to 0.15 UNQ', async ({web3, api, privateKeyWrapper}) => {
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const receiver = createEthAccount(web3);
const alice = privateKeyWrapper('//Alice');
tests/src/eth/collectionProperties.test.tsdiffbeforeafterboth--- a/tests/src/eth/collectionProperties.test.ts
+++ b/tests/src/eth/collectionProperties.test.ts
@@ -7,7 +7,7 @@
describe('EVM collection properties', () => {
itWeb3('Can be set', async({web3, api, privateKeyWrapper}) => {
const alice = privateKeyWrapper('//Alice');
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
await addCollectionAdminExpectSuccess(alice, collection, {Ethereum: caller});
@@ -22,7 +22,7 @@
});
itWeb3('Can be deleted', async({web3, api, privateKeyWrapper}) => {
const alice = privateKeyWrapper('//Alice');
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
await executeTransaction(api, alice, api.tx.unique.setCollectionProperties(collection, [{key: 'testKey', value: 'testValue'}]));
tests/src/eth/contractSponsoring.test.tsdiffbeforeafterboth--- a/tests/src/eth/contractSponsoring.test.ts
+++ b/tests/src/eth/contractSponsoring.test.ts
@@ -44,8 +44,8 @@
import {evmToAddress} from '@polkadot/util-crypto';
describe('Sponsoring EVM contracts', () => {
- itWeb3('Sponsoring can be set by the address that has deployed the contract', async ({api, web3}) => {
- const owner = await createEthAccountWithBalance(api, web3);
+ itWeb3('Sponsoring can be set by the address that has deployed the contract', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const flipper = await deployFlipper(web3, owner);
const helpers = contractHelpers(web3, owner);
expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;
@@ -53,9 +53,9 @@
expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;
});
- itWeb3('Sponsoring cannot be set by the address that did not deployed the contract', async ({api, web3}) => {
- const owner = await createEthAccountWithBalance(api, web3);
- const notOwner = await createEthAccountWithBalance(api, web3);
+ itWeb3('Sponsoring cannot be set by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const notOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const flipper = await deployFlipper(web3, owner);
const helpers = contractHelpers(web3, owner);
expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;
@@ -66,8 +66,8 @@
itWeb3('In generous mode, non-allowlisted user transaction will be sponsored', async ({api, web3, privateKeyWrapper}) => {
const alice = privateKeyWrapper('//Alice');
- const owner = await createEthAccountWithBalance(api, web3);
- const caller = await createEthAccountWithBalance(api, web3);
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const flipper = await deployFlipper(web3, owner);
@@ -94,7 +94,7 @@
itWeb3('Sponsoring is set, an address that has no UNQ can send a transaction and it works. Sponsor balance should decrease (allowlisted)', async ({api, web3, privateKeyWrapper}) => {
const alice = privateKeyWrapper('//Alice');
- const owner = await createEthAccountWithBalance(api, web3);
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const caller = createEthAccount(web3);
const flipper = await deployFlipper(web3, owner);
@@ -124,7 +124,7 @@
itWeb3('Sponsoring is set, an address that has no UNQ can send a transaction and it works. Sponsor balance should not decrease (non-allowlisted)', async ({api, web3, privateKeyWrapper}) => {
const alice = privateKeyWrapper('//Alice');
- const owner = await createEthAccountWithBalance(api, web3);
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const caller = createEthAccount(web3);
const flipper = await deployFlipper(web3, owner);
@@ -152,8 +152,8 @@
itWeb3('Sponsoring is set, an address that has UNQ can send a transaction and it works. User balance should not change', async ({api, web3, privateKeyWrapper}) => {
const alice = privateKeyWrapper('//Alice');
- const owner = await createEthAccountWithBalance(api, web3);
- const caller = await createEthAccountWithBalance(api, web3);
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const originalCallerBalance = await web3.eth.getBalance(caller);
const flipper = await deployFlipper(web3, owner);
@@ -181,8 +181,8 @@
itWeb3('Sponsoring is limited, with setContractRateLimit. The limitation is working if transactions are sent more often, the sender pays the commission.', async ({api, web3, privateKeyWrapper}) => {
const alice = privateKeyWrapper('//Alice');
- const owner = await createEthAccountWithBalance(api, web3);
- const caller = await createEthAccountWithBalance(api, web3);
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const originalCallerBalance = await web3.eth.getBalance(caller);
const flipper = await deployFlipper(web3, owner);
@@ -214,30 +214,31 @@
});
// TODO: Find a way to calculate default rate limit
- itWeb3('Default rate limit equals 7200', async ({api, web3}) => {
- const owner = await createEthAccountWithBalance(api, web3);
+ itWeb3('Default rate limit equals 7200', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const flipper = await deployFlipper(web3, owner);
const helpers = contractHelpers(web3, owner);
expect(await helpers.methods.getSponsoringRateLimit(flipper.options.address).call()).to.be.equals('7200');
});
- itWeb3('Sponsoring collection from evm address via access list', async ({api, web3}) => {
- const owner = await createEthAccountWithBalance(api, web3);
+ itWeb3('Sponsoring collection from evm address via access list', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const collectionHelpers = evmCollectionHelpers(web3, owner);
let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send();
const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
- const sponsor = await createEthAccountWithBalance(api, web3);
+ const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
result = await collectionEvm.methods.setCollectionSponsor(sponsor).send({from: owner});
let collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
+ const ss58Format = (api.registry.getChainProperties())!.toJSON().ss58Format;
expect(collectionSub.sponsorship.isUnconfirmed).to.be.true;
- expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor));
+ expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('Caller is not set as sponsor');
await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});
collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
expect(collectionSub.sponsorship.isConfirmed).to.be.true;
- expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor));
+ expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
const user = createEthAccount(web3);
const nextTokenId = await collectionEvm.methods.nextTokenId().call();
@@ -289,23 +290,24 @@
}
});
- itWeb3('Check that transaction via EVM spend money from sponsor address', async ({api, web3}) => {
- const owner = await createEthAccountWithBalance(api, web3);
+ itWeb3('Check that transaction via EVM spend money from sponsor address', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const collectionHelpers = evmCollectionHelpers(web3, owner);
let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send();
const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
- const sponsor = await createEthAccountWithBalance(api, web3);
+ const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
result = await collectionEvm.methods.setCollectionSponsor(sponsor).send();
let collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
+ const ss58Format = (api.registry.getChainProperties())!.toJSON().ss58Format;
expect(collectionSub.sponsorship.isUnconfirmed).to.be.true;
- expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor));
+ expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('Caller is not set as sponsor');
const sponsorCollection = evmCollection(web3, sponsor, collectionIdAddress);
await sponsorCollection.methods.confirmCollectionSponsorship().send();
collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
expect(collectionSub.sponsorship.isConfirmed).to.be.true;
- expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor));
+ expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
const user = createEthAccount(web3);
await collectionEvm.methods.addCollectionAdmin(user).send();
tests/src/eth/createCollection.test.tsdiffbeforeafterboth--- a/tests/src/eth/createCollection.test.ts
+++ b/tests/src/eth/createCollection.test.ts
@@ -28,67 +28,68 @@
} from './util/helpers';
describe('Create collection from EVM', () => {
- itWeb3('Create collection', async ({api, web3}) => {
- const owner = await createEthAccountWithBalance(api, web3);
- const collectionHelper = evmCollectionHelpers(web3, owner);
- const collectionName = 'CollectionEVM';
- const description = 'Some description';
- const tokenPrefix = 'token prefix';
+ // itWeb3('Create collection', async ({api, web3, privateKeyWrapper}) => {
+ // const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ // const collectionHelper = evmCollectionHelpers(web3, owner);
+ // const collectionName = 'CollectionEVM';
+ // const description = 'Some description';
+ // const tokenPrefix = 'token prefix';
- const collectionCountBefore = await getCreatedCollectionCount(api);
- const result = await collectionHelper.methods
- .createNonfungibleCollection(collectionName, description, tokenPrefix)
- .send();
- const collectionCountAfter = await getCreatedCollectionCount(api);
+ // const collectionCountBefore = await getCreatedCollectionCount(api);
+ // const result = await collectionHelper.methods
+ // .createNonfungibleCollection(collectionName, description, tokenPrefix)
+ // .send();
+ // const collectionCountAfter = await getCreatedCollectionCount(api);
- const {collectionId, collection} = await getCollectionAddressFromResult(api, result);
- expect(collectionCountAfter - collectionCountBefore).to.be.eq(1);
- expect(collectionId).to.be.eq(collectionCountAfter);
- expect(collection.name.map(v => String.fromCharCode(v.toNumber())).join('')).to.be.eq(collectionName);
- expect(collection.description.map(v => String.fromCharCode(v.toNumber())).join('')).to.be.eq(description);
- expect(collection.tokenPrefix.toHuman()).to.be.eq(tokenPrefix);
- });
+ // const {collectionId, collection} = await getCollectionAddressFromResult(api, result);
+ // expect(collectionCountAfter - collectionCountBefore).to.be.eq(1);
+ // expect(collectionId).to.be.eq(collectionCountAfter);
+ // expect(collection.name.map(v => String.fromCharCode(v.toNumber())).join('')).to.be.eq(collectionName);
+ // expect(collection.description.map(v => String.fromCharCode(v.toNumber())).join('')).to.be.eq(description);
+ // expect(collection.tokenPrefix.toHuman()).to.be.eq(tokenPrefix);
+ // });
- itWeb3('Check collection address exist', async ({api, web3}) => {
- const owner = await createEthAccountWithBalance(api, web3);
- const collectionHelpers = evmCollectionHelpers(web3, owner);
+ // itWeb3('Check collection address exist', async ({api, web3, privateKeyWrapper}) => {
+ // const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ // const collectionHelpers = evmCollectionHelpers(web3, owner);
- const expectedCollectionId = await getCreatedCollectionCount(api) + 1;
- const expectedCollectionAddress = collectionIdToAddress(expectedCollectionId);
- expect(await collectionHelpers.methods
- .isCollectionExist(expectedCollectionAddress)
- .call()).to.be.false;
+ // const expectedCollectionId = await getCreatedCollectionCount(api) + 1;
+ // const expectedCollectionAddress = collectionIdToAddress(expectedCollectionId);
+ // expect(await collectionHelpers.methods
+ // .isCollectionExist(expectedCollectionAddress)
+ // .call()).to.be.false;
- await collectionHelpers.methods
- .createNonfungibleCollection('A', 'A', 'A')
- .send();
+ // await collectionHelpers.methods
+ // .createNonfungibleCollection('A', 'A', 'A')
+ // .send();
- expect(await collectionHelpers.methods
- .isCollectionExist(expectedCollectionAddress)
- .call()).to.be.true;
- });
+ // expect(await collectionHelpers.methods
+ // .isCollectionExist(expectedCollectionAddress)
+ // .call()).to.be.true;
+ // });
- itWeb3('Set sponsorship', async ({api, web3}) => {
- const owner = await createEthAccountWithBalance(api, web3);
+ itWeb3('Set sponsorship', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const collectionHelpers = evmCollectionHelpers(web3, owner);
let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send();
const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
- const sponsor = await createEthAccountWithBalance(api, web3);
+ const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
result = await collectionEvm.methods.setCollectionSponsor(sponsor).send();
let collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
expect(collectionSub.sponsorship.isUnconfirmed).to.be.true;
- expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor));
+ const ss58Format = (api.registry.getChainProperties())!.toJSON().ss58Format;
+ expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('Caller is not set as sponsor');
const sponsorCollection = evmCollection(web3, sponsor, collectionIdAddress);
await sponsorCollection.methods.confirmCollectionSponsorship().send();
collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
expect(collectionSub.sponsorship.isConfirmed).to.be.true;
- expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor));
+ expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
});
- itWeb3('Set limits', async ({api, web3}) => {
- const owner = await createEthAccountWithBalance(api, web3);
+ itWeb3('Set limits', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const collectionHelpers = evmCollectionHelpers(web3, owner);
const result = await collectionHelpers.methods.createNonfungibleCollection('Const collection', '5', '5').send();
const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
@@ -127,8 +128,8 @@
expect(collectionSub.limits.transfersEnabled.toHuman()).to.be.eq(limits.transfersEnabled);
});
- itWeb3('Collection address exist', async ({api, web3}) => {
- const owner = await createEthAccountWithBalance(api, web3);
+ itWeb3('Collection address exist', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233';
const collectionHelpers = evmCollectionHelpers(web3, owner);
expect(await collectionHelpers.methods
@@ -144,8 +145,8 @@
});
describe('(!negative tests!) Create collection from EVM', () => {
- itWeb3('(!negative test!) Create collection (bad lengths)', async ({api, web3}) => {
- const owner = await createEthAccountWithBalance(api, web3);
+ itWeb3('(!negative test!) Create collection (bad lengths)', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const helper = evmCollectionHelpers(web3, owner);
{
const MAX_NAME_LENGHT = 64;
@@ -190,8 +191,8 @@
.call()).to.be.rejectedWith('NotSufficientFounds');
});
- itWeb3('(!negative test!) Check owner', async ({api, web3}) => {
- const owner = await createEthAccountWithBalance(api, web3);
+ itWeb3('(!negative test!) Check owner', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const notOwner = await createEthAccount(web3);
const collectionHelpers = evmCollectionHelpers(web3, owner);
const result = await collectionHelpers.methods.createNonfungibleCollection('A', 'A', 'A').send();
@@ -199,7 +200,7 @@
const contractEvmFromNotOwner = evmCollection(web3, notOwner, collectionIdAddress);
const EXPECTED_ERROR = 'NoPermission';
{
- const sponsor = await createEthAccountWithBalance(api, web3);
+ const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
await expect(contractEvmFromNotOwner.methods
.setCollectionSponsor(sponsor)
.call()).to.be.rejectedWith(EXPECTED_ERROR);
@@ -216,8 +217,8 @@
}
});
- itWeb3('(!negative test!) Set limits', async ({api, web3}) => {
- const owner = await createEthAccountWithBalance(api, web3);
+ itWeb3('(!negative test!) Set limits', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const collectionHelpers = evmCollectionHelpers(web3, owner);
const result = await collectionHelpers.methods.createNonfungibleCollection('Schema collection', 'A', 'A').send();
const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
tests/src/eth/crossTransfer.test.tsdiffbeforeafterboth--- a/tests/src/eth/crossTransfer.test.ts
+++ b/tests/src/eth/crossTransfer.test.ts
@@ -48,8 +48,8 @@
});
const alice = privateKeyWrapper('//Alice');
const bob = privateKeyWrapper('//Bob');
- const bobProxy = await createEthAccountWithBalance(api, web3);
- const aliceProxy = await createEthAccountWithBalance(api, web3);
+ const bobProxy = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const aliceProxy = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, alice.address);
await transferExpectSuccess(collection, 0, alice, {Ethereum: aliceProxy} , 200, 'Fungible');
@@ -85,8 +85,8 @@
const alice = privateKeyWrapper('//Alice');
const bob = privateKeyWrapper('//Bob');
const charlie = privateKeyWrapper('//Charlie');
- const bobProxy = await createEthAccountWithBalance(api, web3);
- const aliceProxy = await createEthAccountWithBalance(api, web3);
+ const bobProxy = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const aliceProxy = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Substrate: alice.address});
await transferExpectSuccess(collection, tokenId, alice, {Ethereum: aliceProxy} , 1, 'NFT');
const address = collectionIdToAddress(collection);
tests/src/eth/fungible.test.tsdiffbeforeafterboth--- a/tests/src/eth/fungible.test.ts
+++ b/tests/src/eth/fungible.test.ts
@@ -27,7 +27,7 @@
});
const alice = privateKeyWrapper('//Alice');
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Substrate: alice.address});
@@ -45,7 +45,7 @@
});
const alice = privateKeyWrapper('//Alice');
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: caller});
@@ -65,7 +65,7 @@
});
const alice = privateKeyWrapper('//Alice');
- const owner = await createEthAccountWithBalance(api, web3);
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});
@@ -208,7 +208,7 @@
});
const alice = privateKeyWrapper('//Alice');
- const owner = await createEthAccountWithBalance(api, web3);
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const spender = createEthAccount(web3);
await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});
@@ -226,8 +226,8 @@
});
const alice = privateKeyWrapper('//Alice');
- const owner = await createEthAccountWithBalance(api, web3);
- const spender = await createEthAccountWithBalance(api, web3);
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const spender = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});
@@ -246,7 +246,7 @@
});
const alice = privateKeyWrapper('//Alice');
- const owner = await createEthAccountWithBalance(api, web3);
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const receiver = createEthAccount(web3);
await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});
tests/src/eth/helpersSmoke.test.tsdiffbeforeafterboth--- a/tests/src/eth/helpersSmoke.test.ts
+++ b/tests/src/eth/helpersSmoke.test.ts
@@ -18,16 +18,16 @@
import {createEthAccountWithBalance, deployFlipper, itWeb3, contractHelpers} from './util/helpers';
describe('Helpers sanity check', () => {
- itWeb3('Contract owner is recorded', async ({api, web3}) => {
- const owner = await createEthAccountWithBalance(api, web3);
+ itWeb3('Contract owner is recorded', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const flipper = await deployFlipper(web3, owner);
expect(await contractHelpers(web3, owner).methods.contractOwner(flipper.options.address).call()).to.be.equal(owner);
});
- itWeb3('Flipper is working', async ({api, web3}) => {
- const owner = await createEthAccountWithBalance(api, web3);
+ itWeb3('Flipper is working', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const flipper = await deployFlipper(web3, owner);
expect(await flipper.methods.getValue().call()).to.be.false;
tests/src/eth/marketplace/marketplace.test.tsdiffbeforeafterboth--- a/tests/src/eth/marketplace/marketplace.test.ts
+++ b/tests/src/eth/marketplace/marketplace.test.ts
@@ -39,7 +39,7 @@
describe('Matcher contract usage', () => {
itWeb3('With UNQ', async ({api, web3, privateKeyWrapper}) => {
const alice = privateKeyWrapper('//Alice');
- const matcherOwner = await createEthAccountWithBalance(api, web3);
+ const matcherOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlace.abi`)).toString()), undefined, {
from: matcherOwner,
...GAS_ARGS,
@@ -100,8 +100,8 @@
itWeb3('With escrow', async ({api, web3, privateKeyWrapper}) => {
const alice = privateKeyWrapper('//Alice');
- const matcherOwner = await createEthAccountWithBalance(api, web3);
- const escrow = await createEthAccountWithBalance(api, web3);
+ const matcherOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const escrow = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlace.abi`)).toString()), undefined, {
from: matcherOwner,
...GAS_ARGS,
@@ -171,7 +171,7 @@
itWeb3('Sell tokens from substrate user via EVM contract', async ({api, web3, privateKeyWrapper}) => {
const alice = privateKeyWrapper('//Alice');
- const matcherOwner = await createEthAccountWithBalance(api, web3);
+ const matcherOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlace.abi`)).toString()), undefined, {
from: matcherOwner,
...GAS_ARGS,
tests/src/eth/migration.test.tsdiffbeforeafterboth--- a/tests/src/eth/migration.test.ts
+++ b/tests/src/eth/migration.test.ts
@@ -54,7 +54,7 @@
];
const alice = privateKeyWrapper('//Alice');
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
await submitTransactionAsync(alice, api.tx.sudo.sudo(api.tx.evmMigration.begin(ADDRESS) as any));
await submitTransactionAsync(alice, api.tx.sudo.sudo(api.tx.evmMigration.setData(ADDRESS, DATA as any) as any));
tests/src/eth/nonFungible.test.tsdiffbeforeafterboth--- a/tests/src/eth/nonFungible.test.ts
+++ b/tests/src/eth/nonFungible.test.ts
@@ -26,7 +26,7 @@
mode: {type: 'NFT'},
});
const alice = privateKeyWrapper('//Alice');
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
await createItemExpectSuccess(alice, collection, 'NFT', {Substrate: alice.address});
@@ -43,7 +43,7 @@
});
const alice = privateKeyWrapper('//Alice');
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum:caller});
await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});
await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});
@@ -61,7 +61,7 @@
});
const alice = privateKeyWrapper('//Alice');
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});
const address = collectionIdToAddress(collection);
@@ -73,8 +73,8 @@
});
describe('NFT: Plain calls', () => {
- itWeb3('Can perform mint()', async ({web3, api}) => {
- const owner = await createEthAccountWithBalance(api, web3);
+ itWeb3('Can perform mint()', async ({web3, api, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const helper = evmCollectionHelpers(web3, owner);
let result = await helper.methods.createNonfungibleCollection('Mint collection', '6', '6').send();
const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
@@ -119,7 +119,7 @@
});
const alice = privateKeyWrapper('//Alice');
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const changeAdminTx = api.tx.unique.addCollectionAdmin(collection, {Ethereum: caller});
await submitTransactionAsync(alice, changeAdminTx);
const receiver = createEthAccount(web3);
@@ -182,7 +182,7 @@
});
const alice = privateKeyWrapper('//Alice');
- const owner = await createEthAccountWithBalance(api, web3);
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
@@ -341,7 +341,7 @@
});
const alice = privateKeyWrapper('//Alice');
- const owner = await createEthAccountWithBalance(api, web3);
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const spender = createEthAccount(web3);
const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
@@ -359,8 +359,8 @@
});
const alice = privateKeyWrapper('//Alice');
- const owner = await createEthAccountWithBalance(api, web3);
- const spender = await createEthAccountWithBalance(api, web3);
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const spender = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
@@ -379,7 +379,7 @@
});
const alice = privateKeyWrapper('//Alice');
- const owner = await createEthAccountWithBalance(api, web3);
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const receiver = createEthAccount(web3);
const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
@@ -541,12 +541,12 @@
});
describe('Common metadata', () => {
- itWeb3('Returns collection name', async ({api, web3}) => {
+ itWeb3('Returns collection name', async ({api, web3, privateKeyWrapper}) => {
const collection = await createCollectionExpectSuccess({
name: 'token name',
mode: {type: 'NFT'},
});
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const address = collectionIdToAddress(collection);
const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
@@ -555,12 +555,12 @@
expect(name).to.equal('token name');
});
- itWeb3('Returns symbol name', async ({api, web3}) => {
+ itWeb3('Returns symbol name', async ({api, web3, privateKeyWrapper}) => {
const collection = await createCollectionExpectSuccess({
tokenPrefix: 'TOK',
mode: {type: 'NFT'},
});
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const address = collectionIdToAddress(collection);
const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
tests/src/eth/payable.test.tsdiffbeforeafterboth--- a/tests/src/eth/payable.test.ts
+++ b/tests/src/eth/payable.test.ts
@@ -22,8 +22,8 @@
import {getBalanceSingle, transferBalanceExpectSuccess} from '../substrate/get-balance';
describe('EVM payable contracts', () => {
- itWeb3('Evm contract can receive wei from eth account', async ({api, web3}) => {
- const deployer = await createEthAccountWithBalance(api, web3);
+ itWeb3('Evm contract can receive wei from eth account', async ({api, web3, privateKeyWrapper}) => {
+ const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const contract = await deployCollector(web3, deployer);
await web3.eth.sendTransaction({from: deployer, to: contract.options.address, value: '10000', ...GAS_ARGS});
@@ -32,7 +32,7 @@
});
itWeb3('Evm contract can receive wei from substrate account', async ({api, web3, privateKeyWrapper}) => {
- const deployer = await createEthAccountWithBalance(api, web3);
+ const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const contract = await deployCollector(web3, deployer);
const alice = privateKeyWrapper('//Alice');
@@ -62,7 +62,7 @@
// We can't handle sending balance to backing storage of evm balance, because evmToAddress operation is irreversible
itWeb3('Wei sent directly to backing storage of evm contract balance is unaccounted', async({api, web3, privateKeyWrapper}) => {
- const deployer = await createEthAccountWithBalance(api, web3);
+ const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const contract = await deployCollector(web3, deployer);
const alice = privateKeyWrapper('//Alice');
@@ -75,7 +75,7 @@
const FEE_BALANCE = 1000n * UNIQUE;
const CONTRACT_BALANCE = 1n * UNIQUE;
- const deployer = await createEthAccountWithBalance(api, web3);
+ const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const contract = await deployCollector(web3, deployer);
const alice = privateKeyWrapper('//Alice');
tests/src/eth/proxy/fungibleProxy.test.tsdiffbeforeafterboth--- a/tests/src/eth/proxy/fungibleProxy.test.ts
+++ b/tests/src/eth/proxy/fungibleProxy.test.ts
@@ -21,10 +21,11 @@
import {ApiPromise} from '@polkadot/api';
import Web3 from 'web3';
import {readFile} from 'fs/promises';
+import {IKeyringPair} from '@polkadot/types/types';
-async function proxyWrap(api: ApiPromise, web3: Web3, wrapped: any) {
+async function proxyWrap(api: ApiPromise, web3: Web3, wrapped: any, privateKeyWrapper: (account: string) => IKeyringPair) {
// Proxy owner has no special privilegies, we don't need to reuse them
- const owner = await createEthAccountWithBalance(api, web3);
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const proxyContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/UniqueFungibleProxy.abi`)).toString()), undefined, {
from: owner,
...GAS_ARGS,
@@ -40,12 +41,12 @@
mode: {type: 'Fungible', decimalPoints: 0},
});
const alice = privateKeyWrapper('//Alice');
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Substrate: alice.address});
const address = collectionIdToAddress(collection);
- const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+ const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
const totalSupply = await contract.methods.totalSupply().call();
expect(totalSupply).to.equal('200');
@@ -57,12 +58,12 @@
mode: {type: 'Fungible', decimalPoints: 0},
});
const alice = privateKeyWrapper('//Alice');
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: caller});
const address = collectionIdToAddress(collection);
- const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+ const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
const balance = await contract.methods.balanceOf(caller).call();
expect(balance).to.equal('200');
@@ -76,11 +77,11 @@
mode: {type: 'Fungible', decimalPoints: 0},
});
const alice = privateKeyWrapper('//Alice');
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const spender = createEthAccount(web3);
const address = collectionIdToAddress(collection);
- const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+ const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: contract.options.address});
{
@@ -112,8 +113,8 @@
mode: {type: 'Fungible', decimalPoints: 0},
});
const alice = privateKeyWrapper('//Alice');
- const caller = await createEthAccountWithBalance(api, web3);
- const owner = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});
@@ -121,7 +122,7 @@
const address = collectionIdToAddress(collection);
const evmCollection = new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS});
- const contract = await proxyWrap(api, web3, evmCollection);
+ const contract = await proxyWrap(api, web3, evmCollection, privateKeyWrapper);
await evmCollection.methods.approve(contract.options.address, 100).send({from: owner});
@@ -167,11 +168,11 @@
mode: {type: 'Fungible', decimalPoints: 0},
});
const alice = privateKeyWrapper('//Alice');
- const caller = await createEthAccountWithBalance(api, web3);
- const receiver = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const receiver = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const address = collectionIdToAddress(collection);
- const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+ const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: contract.options.address});
{
tests/src/eth/proxy/nonFungibleProxy.test.tsdiffbeforeafterboth--- a/tests/src/eth/proxy/nonFungibleProxy.test.ts
+++ b/tests/src/eth/proxy/nonFungibleProxy.test.ts
@@ -22,10 +22,11 @@
import Web3 from 'web3';
import {readFile} from 'fs/promises';
import {ApiPromise} from '@polkadot/api';
+import {IKeyringPair} from '@polkadot/types/types';
-async function proxyWrap(api: ApiPromise, web3: Web3, wrapped: any) {
+async function proxyWrap(api: ApiPromise, web3: Web3, wrapped: any, privateKeyWrapper: (account: string) => IKeyringPair) {
// Proxy owner has no special privilegies, we don't need to reuse them
- const owner = await createEthAccountWithBalance(api, web3);
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const proxyContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/UniqueNFTProxy.abi`)).toString()), undefined, {
from: owner,
...GAS_ARGS,
@@ -40,12 +41,12 @@
mode: {type: 'NFT'},
});
const alice = privateKeyWrapper('//Alice');
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
await createItemExpectSuccess(alice, collection, 'NFT', {Substrate: alice.address});
const address = collectionIdToAddress(collection);
- const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+ const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
const totalSupply = await contract.methods.totalSupply().call();
expect(totalSupply).to.equal('1');
@@ -57,13 +58,13 @@
});
const alice = privateKeyWrapper('//Alice');
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});
await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});
await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});
const address = collectionIdToAddress(collection);
- const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+ const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
const balance = await contract.methods.balanceOf(caller).call();
expect(balance).to.equal('3');
@@ -75,11 +76,11 @@
});
const alice = privateKeyWrapper('//Alice');
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});
const address = collectionIdToAddress(collection);
- const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+ const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
const owner = await contract.methods.ownerOf(tokenId).call();
expect(owner).to.equal(caller);
@@ -87,18 +88,18 @@
});
describe('NFT (Via EVM proxy): Plain calls', () => {
- itWeb3('Can perform mint()', async ({web3, api}) => {
- const owner = await createEthAccountWithBalance(api, web3);
+ itWeb3('Can perform mint()', async ({web3, api, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const collectionHelper = evmCollectionHelpers(web3, owner);
const result = await collectionHelper.methods
.createNonfungibleCollection('A', 'A', 'A')
.send();
const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const receiver = createEthAccount(web3);
const collectionEvmOwned = evmCollection(web3, owner, collectionIdAddress);
const collectionEvm = evmCollection(web3, caller, collectionIdAddress);
- const contract = await proxyWrap(api, web3, collectionEvm);
+ const contract = await proxyWrap(api, web3, collectionEvm, privateKeyWrapper);
await collectionEvmOwned.methods.addCollectionAdmin(contract.options.address).send();
{
@@ -135,11 +136,11 @@
});
const alice = privateKeyWrapper('//Alice');
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const receiver = createEthAccount(web3);
const address = collectionIdToAddress(collection);
- const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+ const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
const changeAdminTx = api.tx.unique.addCollectionAdmin(collection, {Ethereum: contract.options.address});
await submitTransactionAsync(alice, changeAdminTx);
@@ -197,10 +198,10 @@
mode: {type: 'NFT'},
});
const alice = privateKeyWrapper('//Alice');
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const address = collectionIdToAddress(collection);
- const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+ const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: contract.options.address});
const changeAdminTx = api.tx.unique.addCollectionAdmin(collection, {Ethereum: contract.options.address});
@@ -229,11 +230,11 @@
mode: {type: 'NFT'},
});
const alice = privateKeyWrapper('//Alice');
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const spender = createEthAccount(web3);
const address = collectionIdToAddress(collection);
- const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address));
+ const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address), privateKeyWrapper);
const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: contract.options.address});
{
@@ -259,14 +260,14 @@
mode: {type: 'NFT'},
});
const alice = privateKeyWrapper('//Alice');
- const caller = await createEthAccountWithBalance(api, web3);
- const owner = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const receiver = createEthAccount(web3);
const address = collectionIdToAddress(collection);
const evmCollection = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
- const contract = await proxyWrap(api, web3, evmCollection);
+ const contract = await proxyWrap(api, web3, evmCollection, privateKeyWrapper);
const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
await evmCollection.methods.approve(contract.options.address, tokenId).send({from: owner});
@@ -303,11 +304,11 @@
mode: {type: 'NFT'},
});
const alice = privateKeyWrapper('//Alice');
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const receiver = createEthAccount(web3);
const address = collectionIdToAddress(collection);
- const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+ const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: contract.options.address});
{
tests/src/eth/scheduling.test.tsdiffbeforeafterboth--- a/tests/src/eth/scheduling.test.ts
+++ b/tests/src/eth/scheduling.test.ts
@@ -17,14 +17,13 @@
import {expect} from 'chai';
import {createEthAccountWithBalance, deployFlipper, GAS_ARGS, itWeb3, subToEth, transferBalanceToEth} from './util/helpers';
import {scheduleExpectSuccess, waitNewBlocks} from '../util/helpers';
-import privateKey from '../substrate/privateKey';
describe('Scheduing EVM smart contracts', () => {
- itWeb3('Successfully schedules and periodically executes an EVM contract', async ({api, web3}) => {
- const deployer = await createEthAccountWithBalance(api, web3);
+ itWeb3('Successfully schedules and periodically executes an EVM contract', async ({api, web3, privateKeyWrapper}) => {
+ const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const flipper = await deployFlipper(web3, deployer);
const initialValue = await flipper.methods.getValue().call();
- const alice = privateKey('//Alice');
+ const alice = privateKeyWrapper('//Alice');
await transferBalanceToEth(api, alice, subToEth(alice.address));
{
tests/src/eth/sponsoring.test.tsdiffbeforeafterboth--- a/tests/src/eth/sponsoring.test.ts
+++ b/tests/src/eth/sponsoring.test.ts
@@ -21,7 +21,7 @@
itWeb3('Fee is deducted from contract if sponsoring is enabled', async ({api, web3, privateKeyWrapper}) => {
const alice = privateKeyWrapper('//Alice');
- const owner = await createEthAccountWithBalance(api, web3);
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const caller = createEthAccount(web3);
const originalCallerBalance = await web3.eth.getBalance(caller);
expect(originalCallerBalance).to.be.equal('0');
@@ -52,8 +52,8 @@
itWeb3('...but this doesn\'t applies to payable value', async ({api, web3, privateKeyWrapper}) => {
const alice = privateKeyWrapper('//Alice');
- const owner = await createEthAccountWithBalance(api, web3);
- const caller = await createEthAccountWithBalance(api, web3);
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const originalCallerBalance = await web3.eth.getBalance(caller);
expect(originalCallerBalance).to.be.not.equal('0');
tests/src/eth/tokenProperties.test.tsdiffbeforeafterboth--- a/tests/src/eth/tokenProperties.test.ts
+++ b/tests/src/eth/tokenProperties.test.ts
@@ -7,7 +7,7 @@
describe('EVM token properties', () => {
itWeb3('Can be reconfigured', async({web3, api, privateKeyWrapper}) => {
const alice = privateKeyWrapper('//Alice');
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
for(const [mutable,collectionAdmin, tokenOwner] of cartesian([], [false, true], [false, true], [false, true])) {
const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
await addCollectionAdminExpectSuccess(alice, collection, {Ethereum: caller});
@@ -25,7 +25,7 @@
});
itWeb3('Can be set', async({web3, api, privateKeyWrapper}) => {
const alice = privateKeyWrapper('//Alice');
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
const token = await createItemExpectSuccess(alice, collection, 'NFT');
@@ -48,7 +48,7 @@
});
itWeb3('Can be deleted', async({web3, api, privateKeyWrapper}) => {
const alice = privateKeyWrapper('//Alice');
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
const token = await createItemExpectSuccess(alice, collection, 'NFT');
tests/src/eth/util/helpers.tsdiffbeforeafterboth--- a/tests/src/eth/util/helpers.ts
+++ b/tests/src/eth/util/helpers.ts
@@ -112,8 +112,8 @@
return account.address;
}
-export async function createEthAccountWithBalance(api: ApiPromise, web3: Web3) {
- const alice = privateKey('//Alice');
+export async function createEthAccountWithBalance(api: ApiPromise, web3: Web3, privateKeyWrapper: (account: string) => IKeyringPair) {
+ const alice = privateKeyWrapper('//Alice');
const account = createEthAccount(web3);
await transferBalanceToEth(api, alice, account);
tests/src/removeCollectionAdmin.test.tsdiffbeforeafterboth--- a/tests/src/removeCollectionAdmin.test.ts
+++ b/tests/src/removeCollectionAdmin.test.ts
@@ -46,33 +46,6 @@
});
});
- it('Remove collection admin by admin.', async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- const collectionId = await createCollectionExpectSuccess();
- const alice = privateKeyWrapper('//Alice');
- const bob = privateKeyWrapper('//Bob');
- const charlie = privateKeyWrapper('//Charlie');
- const collection = await queryCollectionExpectSuccess(api, collectionId);
- expect(collection.owner.toString()).to.be.eq(alice.address);
- // first - add collection admin Bob
- const addAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
- await submitTransactionAsync(alice, addAdminTx);
-
- const addAdminTx2 = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(charlie.address));
- await submitTransactionAsync(alice, addAdminTx2);
-
- const adminListAfterAddAdmin = await getAdminList(api, collectionId);
- expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
-
- // then remove bob from admins of collection
- const removeAdminTx = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));
- await submitTransactionAsync(charlie, removeAdminTx);
-
- const adminListAfterRemoveAdmin = await getAdminList(api, collectionId);
- expect(adminListAfterRemoveAdmin).not.to.be.deep.contains(normalizeAccountId(bob.address));
- });
- });
-
it('Remove admin from collection that has no admins', async () => {
await usingApi(async (api, privateKeyWrapper) => {
const alice = privateKeyWrapper('//Alice');
@@ -120,7 +93,7 @@
});
});
- it('Regular user Can\'t remove collection admin', async () => {
+ it('Regular user can\'t remove collection admin', async () => {
await usingApi(async (api, privateKeyWrapper) => {
const collectionId = await createCollectionExpectSuccess();
const alice = privateKeyWrapper('//Alice');
@@ -137,4 +110,23 @@
await createCollectionExpectSuccess();
});
});
+
+ it('Admin can\'t remove collection admin.', async () => {
+ await usingApi(async (api, privateKeyWrapper) => {
+ const collectionId = await createCollectionExpectSuccess();
+ const alice = privateKeyWrapper('//Alice');
+ const bob = privateKeyWrapper('//Bob');
+ const charlie = privateKeyWrapper('//Charlie');
+
+ const adminListAfterAddAdmin = await getAdminList(api, collectionId);
+ expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
+
+ const removeAdminTx = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));
+ await expect(submitTransactionAsync(charlie, removeAdminTx)).to.be.rejected;
+
+ const adminListAfterRemoveAdmin = await getAdminList(api, collectionId);
+ expect(adminListAfterRemoveAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
+ expect(adminListAfterRemoveAdmin).to.be.deep.contains(normalizeAccountId(charlie.address));
+ });
+ });
});
tests/src/rmrk/rmrk.test.tsdiffbeforeafterboth--- a/tests/src/rmrk/rmrk.test.ts
+++ b/tests/src/rmrk/rmrk.test.ts
@@ -49,8 +49,8 @@
describe('RMRK External Integration Test', () => {
before(async () => {
- await usingApi(async () => {
- alice = privateKey('//Alice');
+ await usingApi(async (api, privateKeyWrapper) => {
+ alice = privateKeyWrapper('//Alice');
});
});
@@ -75,9 +75,9 @@
let rmrkNftId: number;
before(async () => {
- await usingApi(async api => {
- alice = privateKey('//Alice');
- bob = privateKey('//Bob');
+ await usingApi(async (api, privateKeyWrapper) => {
+ alice = privateKeyWrapper('//Alice');
+ bob = privateKeyWrapper('//Bob');
const collectionIds = await createRmrkCollection(api, alice);
uniqueCollectionId = collectionIds.uniqueId;
@@ -210,9 +210,9 @@
let nftId: number;
before(async () => {
- await usingApi(async () => {
- alice = privateKey('//Alice');
- bob = privateKey('//Bob');
+ await usingApi(async (api, privateKeyWrapper) => {
+ alice = privateKeyWrapper('//Alice');
+ bob = privateKeyWrapper('//Bob');
collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
nftId = await createItemExpectSuccess(alice, collectionId, 'NFT');
tests/src/rpc.load.tsdiffbeforeafterboth--- a/tests/src/rpc.load.ts
+++ b/tests/src/rpc.load.ts
@@ -59,8 +59,7 @@
const deployer = await findUnusedAddress(api, privateKeyWrapper);
// Transfer balance to it
- const keyring = new Keyring({type: 'sr25519'});
- const alice = keyring.addFromUri('//Alice');
+ const alice = privateKeyWrapper('//Alice');
const amount = BigInt(endowment) + 10n**15n;
const tx = api.tx.balances.transfer(deployer.address, amount);
await submitTransactionAsync(alice, tx);
tests/src/scheduler.test.tsdiffbeforeafterboth--- a/tests/src/scheduler.test.ts
+++ b/tests/src/scheduler.test.ts
@@ -16,7 +16,6 @@
import chai, {expect} from 'chai';
import chaiAsPromised from 'chai-as-promised';
-import privateKey from './substrate/privateKey';
import {
default as usingApi,
submitTransactionAsync,
@@ -52,9 +51,9 @@
let scheduledIdSlider: number;
before(async() => {
- await usingApi(async () => {
- alice = privateKey('//Alice');
- bob = privateKey('//Bob');
+ await usingApi(async (api, privateKeyWrapper) => {
+ alice = privateKeyWrapper('//Alice');
+ bob = privateKeyWrapper('//Bob');
});
scheduledIdBase = '0x' + '0'.repeat(31);