mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-06 03:18:01 +00:00
Freeze Assets and Asset Metadata (#7346)
* Features needed for reserve-backed stablecoins * Builds & tests. * Double map for an efficient destroy. * Update frame/assets/src/lib.rs Co-authored-by: Nikolay Volf <nikvolf@gmail.com> * ED/zombie-count/refs Feature: ED/minimum balance enforcement Feature: enforce zombie count Feature: allow system-alive accounts to exist, but add reference * Update frame/assets/src/lib.rs Co-authored-by: Nikolay Volf <nikvolf@gmail.com> * Update frame/assets/Cargo.toml Co-authored-by: Niklas Adolfsson <niklasadolfsson1@gmail.com> * Docs * Some tests * More tests * Allow for max_zombies to be adjusted * Test for set_max_zombies * Tests and a couple of fixes * First few benchmarks * Benchmarks. * Fix error message in test * Fixes * Fixes * Fixes * cargo run --release --features runtime-benchmarks --manifest-path bin/node/cli/Cargo.toml -- benchmark --chain dev --steps 50 --repeat 20 --extrinsic * --execution=wasm --wasm-execution=compiled --output ./bin/node/runtime/src/weights --header ./HEADER --pallet pallet_assets * Update frame/assets/src/lib.rs Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com> * Fixes * Fixes * Fixes * cargo run --release --features runtime-benchmarks --manifest-path bin/node/cli/Cargo.toml -- benchmark --chain dev --steps 50 --repeat 20 --extrinsic * --execution=wasm --wasm-execution=compiled --output ./bin/node/runtime/src/weights --header ./HEADER --pallet pallet_assets * Fixes * Update default weight * Add proper verification to benchmarks * minor improvements to tests * Add `freeze_asset` and `thaw_asset` * Add metadata * fix build * Update benchmarks * fix line width * cargo run --release --features runtime-benchmarks --manifest-path bin/node/cli/Cargo.toml -- benchmark --chain dev --steps 50 --repeat 20 --extrinsic * --execution=wasm --wasm-execution=compiled --output ./bin/node/runtime/src/weights --header ./HEADER --pallet pallet_assets * update default weights * destroy cleans up metadata * more comprehensive lifecycle test * update docs * Update frame/assets/src/benchmarking.rs Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Fix * New weights system * fix compile * cargo run --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_assets --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/assets/src/weights.rs --template=./.maintain/frame-weight-template.hbs * fix compile * fix up * cargo run --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_assets --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/assets/src/weights.rs --template=./.maintain/frame-weight-template.hbs * fixes to pallet compile * fix node build * remote diff artifacts * less diff * cargo run --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_assets --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/assets/src/weights.rs --template=./.maintain/frame-weight-template.hbs * Update frame/assets/src/lib.rs * Update frame/assets/src/lib.rs * usize to u32 * missed some usize * cargo run --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_assets --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/assets/src/weights.rs --template=./.maintain/frame-weight-template.hbs Co-authored-by: Gav Wood <gavin@parity.io> Co-authored-by: Nikolay Volf <nikvolf@gmail.com> Co-authored-by: Niklas Adolfsson <niklasadolfsson1@gmail.com> Co-authored-by: Parity Benchmarking Bot <admin@parity.io> Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com> Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
This commit is contained in:
@@ -979,6 +979,9 @@ impl pallet_lottery::Config for Runtime {
|
||||
parameter_types! {
|
||||
pub const AssetDepositBase: Balance = 100 * DOLLARS;
|
||||
pub const AssetDepositPerZombie: Balance = 1 * DOLLARS;
|
||||
pub const StringLimit: u32 = 50;
|
||||
pub const MetadataDepositBase: Balance = 10 * DOLLARS;
|
||||
pub const MetadataDepositPerByte: Balance = 1 * DOLLARS;
|
||||
}
|
||||
|
||||
impl pallet_assets::Config for Runtime {
|
||||
@@ -989,6 +992,9 @@ impl pallet_assets::Config for Runtime {
|
||||
type ForceOrigin = EnsureRoot<AccountId>;
|
||||
type AssetDepositBase = AssetDepositBase;
|
||||
type AssetDepositPerZombie = AssetDepositPerZombie;
|
||||
type StringLimit = StringLimit;
|
||||
type MetadataDepositBase = MetadataDepositBase;
|
||||
type MetadataDepositPerByte = MetadataDepositPerByte;
|
||||
type WeightInfo = pallet_assets::weights::SubstrateWeight<Runtime>;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
//! Assets pallet benchmarking.
|
||||
|
||||
use super::*;
|
||||
use sp_std::prelude::*;
|
||||
use sp_runtime::traits::Bounded;
|
||||
use frame_system::RawOrigin as SystemOrigin;
|
||||
use frame_benchmarking::{benchmarks, account, whitelisted_caller};
|
||||
@@ -154,16 +153,34 @@ benchmarks! {
|
||||
|
||||
thaw {
|
||||
let (caller, caller_lookup) = create_default_minted_asset::<T>(10, 100u32.into());
|
||||
assert!(Assets::<T>::freeze(
|
||||
Assets::<T>::freeze(
|
||||
SystemOrigin::Signed(caller.clone()).into(),
|
||||
Default::default(),
|
||||
caller_lookup.clone()
|
||||
).is_ok());
|
||||
caller_lookup.clone(),
|
||||
)?;
|
||||
}: _(SystemOrigin::Signed(caller.clone()), Default::default(), caller_lookup)
|
||||
verify {
|
||||
assert_last_event::<T>(RawEvent::Thawed(Default::default(), caller).into());
|
||||
}
|
||||
|
||||
freeze_asset {
|
||||
let (caller, caller_lookup) = create_default_minted_asset::<T>(10, 100u32.into());
|
||||
}: _(SystemOrigin::Signed(caller.clone()), Default::default())
|
||||
verify {
|
||||
assert_last_event::<T>(RawEvent::AssetFrozen(Default::default()).into());
|
||||
}
|
||||
|
||||
thaw_asset {
|
||||
let (caller, caller_lookup) = create_default_minted_asset::<T>(10, 100u32.into());
|
||||
Assets::<T>::freeze_asset(
|
||||
SystemOrigin::Signed(caller.clone()).into(),
|
||||
Default::default(),
|
||||
)?;
|
||||
}: _(SystemOrigin::Signed(caller.clone()), Default::default())
|
||||
verify {
|
||||
assert_last_event::<T>(RawEvent::AssetThawed(Default::default()).into());
|
||||
}
|
||||
|
||||
transfer_ownership {
|
||||
let (caller, _) = create_default_asset::<T>(10);
|
||||
let target: T::AccountId = account("target", 0, SEED);
|
||||
@@ -196,6 +213,21 @@ benchmarks! {
|
||||
verify {
|
||||
assert_last_event::<T>(RawEvent::MaxZombiesChanged(Default::default(), max_zombies).into());
|
||||
}
|
||||
|
||||
set_metadata {
|
||||
let n in 0 .. T::StringLimit::get();
|
||||
let s in 0 .. T::StringLimit::get();
|
||||
|
||||
let name = vec![0u8; n as usize];
|
||||
let symbol = vec![0u8; s as usize];
|
||||
let decimals = 12;
|
||||
|
||||
let (caller, _) = create_default_asset::<T>(10);
|
||||
T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
|
||||
}: _(SystemOrigin::Signed(caller), Default::default(), name.clone(), symbol.clone(), decimals)
|
||||
verify {
|
||||
assert_last_event::<T>(RawEvent::MetadataSet(Default::default(), name, symbol, decimals).into());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -273,6 +305,20 @@ mod tests {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn freeze_asset() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert!(test_benchmark_freeze_asset::<Test>().is_ok());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn thaw_asset() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert!(test_benchmark_thaw_asset::<Test>().is_ok());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transfer_ownership() {
|
||||
new_test_ext().execute_with(|| {
|
||||
@@ -293,4 +339,11 @@ mod tests {
|
||||
assert!(test_benchmark_set_max_zombies::<Test>().is_ok());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_metadata() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert!(test_benchmark_set_metadata::<Test>().is_ok());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
mod benchmarking;
|
||||
pub mod weights;
|
||||
|
||||
use sp_std::{fmt::Debug};
|
||||
use sp_std::{fmt::Debug, prelude::*};
|
||||
use sp_runtime::{RuntimeDebug, traits::{
|
||||
Member, AtLeast32BitUnsigned, Zero, StaticLookup, Saturating, CheckedSub, CheckedAdd
|
||||
}};
|
||||
@@ -151,6 +151,16 @@ pub trait Config: frame_system::Config {
|
||||
/// supports.
|
||||
type AssetDepositPerZombie: Get<BalanceOf<Self>>;
|
||||
|
||||
/// The maximum length of a name or symbol stored on-chain.
|
||||
type StringLimit: Get<u32>;
|
||||
|
||||
/// The basic amount of funds that must be reserved when adding metadata to your asset.
|
||||
type MetadataDepositBase: Get<BalanceOf<Self>>;
|
||||
|
||||
/// The additional funds that must be reserved for the number of bytes you store in your
|
||||
/// metadata.
|
||||
type MetadataDepositPerByte: Get<BalanceOf<Self>>;
|
||||
|
||||
/// Weight information for extrinsics in this pallet.
|
||||
type WeightInfo: WeightInfo;
|
||||
}
|
||||
@@ -184,6 +194,8 @@ pub struct AssetDetails<
|
||||
zombies: u32,
|
||||
/// The total number of accounts.
|
||||
accounts: u32,
|
||||
/// Whether the asset is frozen for permissionless transfers.
|
||||
is_frozen: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default)]
|
||||
@@ -198,6 +210,20 @@ pub struct AssetBalance<
|
||||
is_zombie: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default)]
|
||||
pub struct AssetMetadata<DepositBalance> {
|
||||
/// The balance deposited for this metadata.
|
||||
///
|
||||
/// This pays for the data stored in this struct.
|
||||
deposit: DepositBalance,
|
||||
/// The user friendly name of this asset. Limited in length by `StringLimit`.
|
||||
name: Vec<u8>,
|
||||
/// The ticker symbol for this asset. Limited in length by `StringLimit`.
|
||||
symbol: Vec<u8>,
|
||||
/// The number of decimals this asset uses to represent one unit.
|
||||
decimals: u8,
|
||||
}
|
||||
|
||||
decl_storage! {
|
||||
trait Store for Module<T: Config> as Assets {
|
||||
/// Details of an asset.
|
||||
@@ -212,6 +238,9 @@ decl_storage! {
|
||||
hasher(blake2_128_concat) T::AssetId,
|
||||
hasher(blake2_128_concat) T::AccountId
|
||||
=> AssetBalance<T::Balance>;
|
||||
|
||||
/// Metadata of an asset.
|
||||
Metadata: map hasher(blake2_128_concat) T::AssetId => AssetMetadata<BalanceOf<T>>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,12 +268,18 @@ decl_event! {
|
||||
Frozen(AssetId, AccountId),
|
||||
/// Some account `who` was thawed. \[asset_id, who\]
|
||||
Thawed(AssetId, AccountId),
|
||||
/// Some asset `asset_id` was frozen. \[asset_id\]
|
||||
AssetFrozen(AssetId),
|
||||
/// Some asset `asset_id` was thawed. \[asset_id\]
|
||||
AssetThawed(AssetId),
|
||||
/// An asset class was destroyed.
|
||||
Destroyed(AssetId),
|
||||
/// Some asset class was force-created. \[asset_id, owner\]
|
||||
ForceCreated(AssetId, AccountId),
|
||||
/// The maximum amount of zombies allowed has changed. \[asset_id, max_zombies\]
|
||||
MaxZombiesChanged(AssetId, u32),
|
||||
/// New metadata has been set for an asset. \[asset_id, name, symbol, decimals\]
|
||||
MetadataSet(AssetId, Vec<u8>, Vec<u8>, u8),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,6 +311,8 @@ decl_error! {
|
||||
Overflow,
|
||||
/// Some internal state is broken.
|
||||
BadState,
|
||||
/// Invalid metadata given.
|
||||
BadMetadata,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,6 +374,7 @@ decl_module! {
|
||||
min_balance,
|
||||
zombies: Zero::zero(),
|
||||
accounts: Zero::zero(),
|
||||
is_frozen: false,
|
||||
});
|
||||
Self::deposit_event(RawEvent::Created(id, owner, admin));
|
||||
}
|
||||
@@ -386,6 +424,7 @@ decl_module! {
|
||||
min_balance,
|
||||
zombies: Zero::zero(),
|
||||
accounts: Zero::zero(),
|
||||
is_frozen: false,
|
||||
});
|
||||
Self::deposit_event(RawEvent::ForceCreated(id, owner));
|
||||
}
|
||||
@@ -412,7 +451,9 @@ decl_module! {
|
||||
ensure!(details.owner == origin, Error::<T>::NoPermission);
|
||||
ensure!(details.accounts == details.zombies, Error::<T>::RefsLeft);
|
||||
ensure!(details.zombies <= zombies_witness, Error::<T>::BadWitness);
|
||||
T::Currency::unreserve(&details.owner, details.deposit);
|
||||
|
||||
let metadata = Metadata::<T>::take(&id);
|
||||
T::Currency::unreserve(&details.owner, details.deposit.saturating_add(metadata.deposit));
|
||||
|
||||
*maybe_details = None;
|
||||
Account::<T>::remove_prefix(&id);
|
||||
@@ -442,7 +483,9 @@ decl_module! {
|
||||
let details = maybe_details.take().ok_or(Error::<T>::Unknown)?;
|
||||
ensure!(details.accounts == details.zombies, Error::<T>::RefsLeft);
|
||||
ensure!(details.zombies <= zombies_witness, Error::<T>::BadWitness);
|
||||
T::Currency::unreserve(&details.owner, details.deposit);
|
||||
|
||||
let metadata = Metadata::<T>::take(&id);
|
||||
T::Currency::unreserve(&details.owner, details.deposit.saturating_add(metadata.deposit));
|
||||
|
||||
*maybe_details = None;
|
||||
Account::<T>::remove_prefix(&id);
|
||||
@@ -580,6 +623,7 @@ decl_module! {
|
||||
let dest = T::Lookup::lookup(target)?;
|
||||
Asset::<T>::try_mutate(id, |maybe_details| {
|
||||
let details = maybe_details.as_mut().ok_or(Error::<T>::Unknown)?;
|
||||
ensure!(!details.is_frozen, Error::<T>::Frozen);
|
||||
|
||||
if dest == origin {
|
||||
return Ok(())
|
||||
@@ -739,6 +783,54 @@ decl_module! {
|
||||
Self::deposit_event(Event::<T>::Thawed(id, who));
|
||||
}
|
||||
|
||||
/// Disallow further unprivileged transfers for the asset class.
|
||||
///
|
||||
/// Origin must be Signed and the sender should be the Freezer of the asset `id`.
|
||||
///
|
||||
/// - `id`: The identifier of the asset to be frozen.
|
||||
///
|
||||
/// Emits `Frozen`.
|
||||
///
|
||||
/// Weight: `O(1)`
|
||||
#[weight = T::WeightInfo::freeze_asset()]
|
||||
fn freeze_asset(origin, #[compact] id: T::AssetId) -> DispatchResult {
|
||||
let origin = ensure_signed(origin)?;
|
||||
|
||||
Asset::<T>::try_mutate(id, |maybe_details| {
|
||||
let d = maybe_details.as_mut().ok_or(Error::<T>::Unknown)?;
|
||||
ensure!(&origin == &d.freezer, Error::<T>::NoPermission);
|
||||
|
||||
d.is_frozen = true;
|
||||
|
||||
Self::deposit_event(Event::<T>::AssetFrozen(id));
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
/// Allow unprivileged transfers for the asset again.
|
||||
///
|
||||
/// Origin must be Signed and the sender should be the Admin of the asset `id`.
|
||||
///
|
||||
/// - `id`: The identifier of the asset to be frozen.
|
||||
///
|
||||
/// Emits `Thawed`.
|
||||
///
|
||||
/// Weight: `O(1)`
|
||||
#[weight = T::WeightInfo::thaw_asset()]
|
||||
fn thaw_asset(origin, #[compact] id: T::AssetId) -> DispatchResult {
|
||||
let origin = ensure_signed(origin)?;
|
||||
|
||||
Asset::<T>::try_mutate(id, |maybe_details| {
|
||||
let d = maybe_details.as_mut().ok_or(Error::<T>::Unknown)?;
|
||||
ensure!(&origin == &d.admin, Error::<T>::NoPermission);
|
||||
|
||||
d.is_frozen = false;
|
||||
|
||||
Self::deposit_event(Event::<T>::AssetThawed(id));
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
/// Change the Owner of an asset.
|
||||
///
|
||||
/// Origin must be Signed and the sender should be the Owner of the asset `id`.
|
||||
@@ -809,6 +901,20 @@ decl_module! {
|
||||
})
|
||||
}
|
||||
|
||||
/// Set the maximum number of zombie accounts for an asset.
|
||||
///
|
||||
/// Origin must be Signed and the sender should be the Owner of the asset `id`.
|
||||
///
|
||||
/// Funds of sender are reserved according to the formula:
|
||||
/// `AssetDepositBase + AssetDepositPerZombie * max_zombies` taking into account
|
||||
/// any already reserved funds.
|
||||
///
|
||||
/// - `id`: The identifier of the asset to update zombie count.
|
||||
/// - `max_zombies`: The new number of zombies allowed for this asset.
|
||||
///
|
||||
/// Emits `MaxZombiesChanged`.
|
||||
///
|
||||
/// Weight: `O(1)`
|
||||
#[weight = T::WeightInfo::set_max_zombies()]
|
||||
fn set_max_zombies(origin,
|
||||
#[compact] id: T::AssetId,
|
||||
@@ -837,6 +943,76 @@ decl_module! {
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
/// Set the metadata for an asset.
|
||||
///
|
||||
/// NOTE: There is no `unset_metadata` call. Simply pass an empty name, symbol,
|
||||
/// and 0 decimals to this function to remove the metadata of an asset and
|
||||
/// return your deposit.
|
||||
///
|
||||
/// Origin must be Signed and the sender should be the Owner of the asset `id`.
|
||||
///
|
||||
/// Funds of sender are reserved according to the formula:
|
||||
/// `MetadataDepositBase + MetadataDepositPerByte * (name.len + symbol.len)` taking into
|
||||
/// account any already reserved funds.
|
||||
///
|
||||
/// - `id`: The identifier of the asset to update.
|
||||
/// - `name`: The user friendly name of this asset. Limited in length by `StringLimit`.
|
||||
/// - `symbol`: The exchange symbol for this asset. Limited in length by `StringLimit`.
|
||||
/// - `decimals`: The number of decimals this asset uses to represent one unit.
|
||||
///
|
||||
/// Emits `MaxZombiesChanged`.
|
||||
///
|
||||
/// Weight: `O(1)`
|
||||
#[weight = T::WeightInfo::set_metadata(name.len() as u32, symbol.len() as u32)]
|
||||
fn set_metadata(origin,
|
||||
#[compact] id: T::AssetId,
|
||||
name: Vec<u8>,
|
||||
symbol: Vec<u8>,
|
||||
decimals: u8,
|
||||
) -> DispatchResult {
|
||||
let origin = ensure_signed(origin)?;
|
||||
|
||||
ensure!(name.len() <= T::StringLimit::get() as usize, Error::<T>::BadMetadata);
|
||||
ensure!(symbol.len() <= T::StringLimit::get() as usize, Error::<T>::BadMetadata);
|
||||
|
||||
let d = Asset::<T>::get(id).ok_or(Error::<T>::Unknown)?;
|
||||
ensure!(&origin == &d.owner, Error::<T>::NoPermission);
|
||||
|
||||
Metadata::<T>::try_mutate_exists(id, |metadata| {
|
||||
let bytes_used = name.len() + symbol.len();
|
||||
let old_deposit = match metadata {
|
||||
Some(m) => m.deposit,
|
||||
None => Default::default()
|
||||
};
|
||||
|
||||
// Metadata is being removed
|
||||
if bytes_used.is_zero() && decimals.is_zero() {
|
||||
T::Currency::unreserve(&origin, old_deposit);
|
||||
*metadata = None;
|
||||
} else {
|
||||
let new_deposit = T::MetadataDepositPerByte::get()
|
||||
.saturating_mul(((name.len() + symbol.len()) as u32).into())
|
||||
.saturating_add(T::MetadataDepositBase::get());
|
||||
|
||||
if new_deposit > old_deposit {
|
||||
T::Currency::reserve(&origin, new_deposit - old_deposit)?;
|
||||
} else {
|
||||
T::Currency::unreserve(&origin, old_deposit - new_deposit);
|
||||
}
|
||||
|
||||
*metadata = Some(AssetMetadata {
|
||||
deposit: new_deposit,
|
||||
name: name.clone(),
|
||||
symbol: symbol.clone(),
|
||||
decimals,
|
||||
})
|
||||
}
|
||||
|
||||
Self::deposit_event(RawEvent::MetadataSet(id, name, symbol, decimals));
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -912,6 +1088,7 @@ mod tests {
|
||||
use frame_support::{impl_outer_origin, assert_ok, assert_noop, parameter_types, impl_outer_event};
|
||||
use sp_core::H256;
|
||||
use sp_runtime::{traits::{BlakeTwo256, IdentityLookup}, testing::Header};
|
||||
use pallet_balances::Error as BalancesError;
|
||||
|
||||
mod pallet_assets {
|
||||
pub use crate::Event;
|
||||
@@ -976,6 +1153,9 @@ mod tests {
|
||||
parameter_types! {
|
||||
pub const AssetDepositBase: u64 = 1;
|
||||
pub const AssetDepositPerZombie: u64 = 1;
|
||||
pub const StringLimit: u32 = 50;
|
||||
pub const MetadataDepositBase: u64 = 1;
|
||||
pub const MetadataDepositPerByte: u64 = 1;
|
||||
}
|
||||
|
||||
impl Config for Test {
|
||||
@@ -986,6 +1166,9 @@ mod tests {
|
||||
type ForceOrigin = frame_system::EnsureRoot<u64>;
|
||||
type AssetDepositBase = AssetDepositBase;
|
||||
type AssetDepositPerZombie = AssetDepositPerZombie;
|
||||
type StringLimit = StringLimit;
|
||||
type MetadataDepositBase = MetadataDepositBase;
|
||||
type MetadataDepositPerByte = MetadataDepositPerByte;
|
||||
type WeightInfo = ();
|
||||
}
|
||||
type System = frame_system::Module<Test>;
|
||||
@@ -1013,15 +1196,41 @@ mod tests {
|
||||
Balances::make_free_balance_be(&1, 100);
|
||||
assert_ok!(Assets::create(Origin::signed(1), 0, 1, 10, 1));
|
||||
assert_eq!(Balances::reserved_balance(&1), 11);
|
||||
assert!(Asset::<Test>::contains_key(0));
|
||||
|
||||
assert_ok!(Assets::set_metadata(Origin::signed(1), 0, vec![0], vec![0], 12));
|
||||
assert_eq!(Balances::reserved_balance(&1), 14);
|
||||
assert!(Metadata::<Test>::contains_key(0));
|
||||
|
||||
assert_ok!(Assets::mint(Origin::signed(1), 0, 10, 100));
|
||||
assert_ok!(Assets::mint(Origin::signed(1), 0, 20, 100));
|
||||
assert_eq!(Account::<Test>::iter_prefix(0).count(), 2);
|
||||
|
||||
assert_ok!(Assets::destroy(Origin::signed(1), 0, 100));
|
||||
assert_eq!(Balances::reserved_balance(&1), 0);
|
||||
|
||||
assert!(!Asset::<Test>::contains_key(0));
|
||||
assert!(!Metadata::<Test>::contains_key(0));
|
||||
assert_eq!(Account::<Test>::iter_prefix(0).count(), 0);
|
||||
|
||||
assert_ok!(Assets::create(Origin::signed(1), 0, 1, 10, 1));
|
||||
assert_eq!(Balances::reserved_balance(&1), 11);
|
||||
assert!(Asset::<Test>::contains_key(0));
|
||||
|
||||
assert_ok!(Assets::set_metadata(Origin::signed(1), 0, vec![0], vec![0], 12));
|
||||
assert_eq!(Balances::reserved_balance(&1), 14);
|
||||
assert!(Metadata::<Test>::contains_key(0));
|
||||
|
||||
assert_ok!(Assets::mint(Origin::signed(1), 0, 10, 100));
|
||||
assert_ok!(Assets::mint(Origin::signed(1), 0, 20, 100));
|
||||
assert_eq!(Account::<Test>::iter_prefix(0).count(), 2);
|
||||
|
||||
assert_ok!(Assets::force_destroy(Origin::root(), 0, 100));
|
||||
assert_eq!(Balances::reserved_balance(&1), 0);
|
||||
|
||||
assert!(!Asset::<Test>::contains_key(0));
|
||||
assert!(!Metadata::<Test>::contains_key(0));
|
||||
assert_eq!(Account::<Test>::iter_prefix(0).count(), 0);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1172,7 +1381,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transferring_frozen_balance_should_not_work() {
|
||||
fn transferring_frozen_user_should_not_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(Assets::force_create(Origin::root(), 0, 1, 10, 1));
|
||||
assert_ok!(Assets::mint(Origin::signed(1), 0, 1, 100));
|
||||
@@ -1184,6 +1393,19 @@ mod tests {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transferring_frozen_asset_should_not_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(Assets::force_create(Origin::root(), 0, 1, 10, 1));
|
||||
assert_ok!(Assets::mint(Origin::signed(1), 0, 1, 100));
|
||||
assert_eq!(Assets::balance(0, 1), 100);
|
||||
assert_ok!(Assets::freeze_asset(Origin::signed(1), 0));
|
||||
assert_noop!(Assets::transfer(Origin::signed(1), 0, 2, 50), Error::<Test>::Frozen);
|
||||
assert_ok!(Assets::thaw_asset(Origin::signed(1), 0));
|
||||
assert_ok!(Assets::transfer(Origin::signed(1), 0, 2, 50));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn origin_guards_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
@@ -1306,4 +1528,53 @@ mod tests {
|
||||
assert_noop!(Assets::burn(Origin::signed(1), 0, 2, u64::max_value()), Error::<Test>::BalanceZero);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_metadata_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// Cannot add metadata to unknown asset
|
||||
assert_noop!(
|
||||
Assets::set_metadata(Origin::signed(1), 0, vec![0u8; 10], vec![0u8; 10], 12),
|
||||
Error::<Test>::Unknown,
|
||||
);
|
||||
assert_ok!(Assets::force_create(Origin::root(), 0, 1, 10, 1));
|
||||
// Cannot add metadata to unowned asset
|
||||
assert_noop!(
|
||||
Assets::set_metadata(Origin::signed(2), 0, vec![0u8; 10], vec![0u8; 10], 12),
|
||||
Error::<Test>::NoPermission,
|
||||
);
|
||||
|
||||
// Cannot add oversized metadata
|
||||
assert_noop!(
|
||||
Assets::set_metadata(Origin::signed(1), 0, vec![0u8; 100], vec![0u8; 10], 12),
|
||||
Error::<Test>::BadMetadata,
|
||||
);
|
||||
assert_noop!(
|
||||
Assets::set_metadata(Origin::signed(1), 0, vec![0u8; 10], vec![0u8; 100], 12),
|
||||
Error::<Test>::BadMetadata,
|
||||
);
|
||||
|
||||
// Successfully add metadata and take deposit
|
||||
Balances::make_free_balance_be(&1, 30);
|
||||
assert_ok!(Assets::set_metadata(Origin::signed(1), 0, vec![0u8; 10], vec![0u8; 10], 12));
|
||||
assert_eq!(Balances::free_balance(&1), 9);
|
||||
|
||||
// Update deposit
|
||||
assert_ok!(Assets::set_metadata(Origin::signed(1), 0, vec![0u8; 10], vec![0u8; 5], 12));
|
||||
assert_eq!(Balances::free_balance(&1), 14);
|
||||
assert_ok!(Assets::set_metadata(Origin::signed(1), 0, vec![0u8; 10], vec![0u8; 15], 12));
|
||||
assert_eq!(Balances::free_balance(&1), 4);
|
||||
|
||||
// Cannot over-reserve
|
||||
assert_noop!(
|
||||
Assets::set_metadata(Origin::signed(1), 0, vec![0u8; 20], vec![0u8; 20], 12),
|
||||
BalancesError::<Test, _>::InsufficientBalance,
|
||||
);
|
||||
|
||||
// Clear Metadata
|
||||
assert!(Metadata::<Test>::contains_key(0));
|
||||
assert_ok!(Assets::set_metadata(Origin::signed(1), 0, vec![], vec![], 0));
|
||||
assert!(!Metadata::<Test>::contains_key(0));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd.
|
||||
// Copyright (C) 2021 Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
//! Autogenerated weights for pallet_assets
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 2.0.0
|
||||
//! DATE: 2020-12-03, STEPS: [50, ], REPEAT: 20, LOW RANGE: [], HIGH RANGE: []
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 2.0.1
|
||||
//! DATE: 2021-01-18, STEPS: [50, ], REPEAT: 20, LOW RANGE: [], HIGH RANGE: []
|
||||
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128
|
||||
|
||||
// Executed Command:
|
||||
@@ -54,154 +54,199 @@ pub trait WeightInfo {
|
||||
fn force_transfer() -> Weight;
|
||||
fn freeze() -> Weight;
|
||||
fn thaw() -> Weight;
|
||||
fn freeze_asset() -> Weight;
|
||||
fn thaw_asset() -> Weight;
|
||||
fn transfer_ownership() -> Weight;
|
||||
fn set_team() -> Weight;
|
||||
fn set_max_zombies() -> Weight;
|
||||
fn set_metadata(n: u32, s: u32, ) -> Weight;
|
||||
}
|
||||
|
||||
/// Weights for pallet_assets using the Substrate node and recommended hardware.
|
||||
pub struct SubstrateWeight<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
fn create() -> Weight {
|
||||
(58_077_000 as Weight)
|
||||
(44_459_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn force_create() -> Weight {
|
||||
(30_497_000 as Weight)
|
||||
(21_480_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn destroy(z: u32, ) -> Weight {
|
||||
(0 as Weight)
|
||||
.saturating_add((1_153_000 as Weight).saturating_mul(z as Weight))
|
||||
.saturating_add(T::DbWeight::get().reads(1 as Weight))
|
||||
// Standard Error: 2_000
|
||||
.saturating_add((1_149_000 as Weight).saturating_mul(z as Weight))
|
||||
.saturating_add(T::DbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(z as Weight)))
|
||||
}
|
||||
fn force_destroy(z: u32, ) -> Weight {
|
||||
(0 as Weight)
|
||||
.saturating_add((1_153_000 as Weight).saturating_mul(z as Weight))
|
||||
.saturating_add(T::DbWeight::get().reads(1 as Weight))
|
||||
// Standard Error: 2_000
|
||||
.saturating_add((1_146_000 as Weight).saturating_mul(z as Weight))
|
||||
.saturating_add(T::DbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(z as Weight)))
|
||||
}
|
||||
fn mint() -> Weight {
|
||||
(45_600_000 as Weight)
|
||||
(32_995_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
fn burn() -> Weight {
|
||||
(40_143_000 as Weight)
|
||||
(29_245_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
fn transfer() -> Weight {
|
||||
(58_903_000 as Weight)
|
||||
(42_211_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(4 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
||||
}
|
||||
fn force_transfer() -> Weight {
|
||||
(59_025_000 as Weight)
|
||||
(42_218_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(4 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
||||
}
|
||||
fn freeze() -> Weight {
|
||||
(43_308_000 as Weight)
|
||||
(31_079_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn thaw() -> Weight {
|
||||
(43_383_000 as Weight)
|
||||
(30_853_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn freeze_asset() -> Weight {
|
||||
(22_383_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn thaw_asset() -> Weight {
|
||||
(22_341_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn transfer_ownership() -> Weight {
|
||||
(31_380_000 as Weight)
|
||||
(22_782_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn set_team() -> Weight {
|
||||
(32_049_000 as Weight)
|
||||
(23_293_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn set_max_zombies() -> Weight {
|
||||
(57_745_000 as Weight)
|
||||
(44_525_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn set_metadata(n: u32, s: u32, ) -> Weight {
|
||||
(49_456_000 as Weight)
|
||||
// Standard Error: 0
|
||||
.saturating_add((1_000 as Weight).saturating_mul(n as Weight))
|
||||
// Standard Error: 0
|
||||
.saturating_add((6_000 as Weight).saturating_mul(s as Weight))
|
||||
.saturating_add(T::DbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
}
|
||||
|
||||
// For backwards compatibility and tests
|
||||
impl WeightInfo for () {
|
||||
fn create() -> Weight {
|
||||
(58_077_000 as Weight)
|
||||
(44_459_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn force_create() -> Weight {
|
||||
(30_497_000 as Weight)
|
||||
(21_480_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn destroy(z: u32, ) -> Weight {
|
||||
(0 as Weight)
|
||||
.saturating_add((1_153_000 as Weight).saturating_mul(z as Weight))
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
|
||||
// Standard Error: 2_000
|
||||
.saturating_add((1_149_000 as Weight).saturating_mul(z as Weight))
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(z as Weight)))
|
||||
}
|
||||
fn force_destroy(z: u32, ) -> Weight {
|
||||
(0 as Weight)
|
||||
.saturating_add((1_153_000 as Weight).saturating_mul(z as Weight))
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
|
||||
// Standard Error: 2_000
|
||||
.saturating_add((1_146_000 as Weight).saturating_mul(z as Weight))
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(z as Weight)))
|
||||
}
|
||||
fn mint() -> Weight {
|
||||
(45_600_000 as Weight)
|
||||
(32_995_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
fn burn() -> Weight {
|
||||
(40_143_000 as Weight)
|
||||
(29_245_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
fn transfer() -> Weight {
|
||||
(58_903_000 as Weight)
|
||||
(42_211_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
||||
}
|
||||
fn force_transfer() -> Weight {
|
||||
(59_025_000 as Weight)
|
||||
(42_218_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
||||
}
|
||||
fn freeze() -> Weight {
|
||||
(43_308_000 as Weight)
|
||||
(31_079_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn thaw() -> Weight {
|
||||
(43_383_000 as Weight)
|
||||
(30_853_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn freeze_asset() -> Weight {
|
||||
(22_383_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn thaw_asset() -> Weight {
|
||||
(22_341_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn transfer_ownership() -> Weight {
|
||||
(31_380_000 as Weight)
|
||||
(22_782_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn set_team() -> Weight {
|
||||
(32_049_000 as Weight)
|
||||
(23_293_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn set_max_zombies() -> Weight {
|
||||
(57_745_000 as Weight)
|
||||
(44_525_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn set_metadata(n: u32, s: u32, ) -> Weight {
|
||||
(49_456_000 as Weight)
|
||||
// Standard Error: 0
|
||||
.saturating_add((1_000 as Weight).saturating_mul(n as Weight))
|
||||
// Standard Error: 0
|
||||
.saturating_add((6_000 as Weight).saturating_mul(s as Weight))
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user