mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 01:41:09 +00:00
Pallet Assets: Create new asset classes from genesis config (#9742)
* Pallet Assets: Allow creating asset classes from genesis config * Add accounts and metadata to genesis config * whitespace fixes * Update more chainspecs * Run rustfmt over code * More formatting fixes * Update frame/assets/src/lib.rs Improve error message Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> * Update frame/assets/src/lib.rs Improve error message Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
This commit is contained in:
@@ -361,6 +361,7 @@ pub fn testnet_genesis(
|
|||||||
max_members: 999,
|
max_members: 999,
|
||||||
},
|
},
|
||||||
vesting: Default::default(),
|
vesting: Default::default(),
|
||||||
|
assets: Default::default(),
|
||||||
gilt: Default::default(),
|
gilt: Default::default(),
|
||||||
transaction_storage: Default::default(),
|
transaction_storage: Default::default(),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1280,7 +1280,7 @@ construct_runtime!(
|
|||||||
Multisig: pallet_multisig::{Pallet, Call, Storage, Event<T>},
|
Multisig: pallet_multisig::{Pallet, Call, Storage, Event<T>},
|
||||||
Bounties: pallet_bounties::{Pallet, Call, Storage, Event<T>},
|
Bounties: pallet_bounties::{Pallet, Call, Storage, Event<T>},
|
||||||
Tips: pallet_tips::{Pallet, Call, Storage, Event<T>},
|
Tips: pallet_tips::{Pallet, Call, Storage, Event<T>},
|
||||||
Assets: pallet_assets::{Pallet, Call, Storage, Event<T>},
|
Assets: pallet_assets::{Pallet, Call, Storage, Event<T>, Config<T>},
|
||||||
Mmr: pallet_mmr::{Pallet, Storage},
|
Mmr: pallet_mmr::{Pallet, Storage},
|
||||||
Lottery: pallet_lottery::{Pallet, Call, Storage, Event<T>},
|
Lottery: pallet_lottery::{Pallet, Call, Storage, Event<T>},
|
||||||
Gilt: pallet_gilt::{Pallet, Call, Storage, Event<T>, Config},
|
Gilt: pallet_gilt::{Pallet, Call, Storage, Event<T>, Config},
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ pub fn config_endowed(
|
|||||||
treasury: Default::default(),
|
treasury: Default::default(),
|
||||||
society: SocietyConfig { members: vec![alice(), bob()], pot: 0, max_members: 999 },
|
society: SocietyConfig { members: vec![alice(), bob()], pot: 0, max_members: 999 },
|
||||||
vesting: Default::default(),
|
vesting: Default::default(),
|
||||||
|
assets: Default::default(),
|
||||||
gilt: Default::default(),
|
gilt: Default::default(),
|
||||||
transaction_storage: Default::default(),
|
transaction_storage: Default::default(),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,6 +159,9 @@ use sp_runtime::{
|
|||||||
};
|
};
|
||||||
use sp_std::{borrow::Borrow, convert::TryInto, prelude::*};
|
use sp_std::{borrow::Borrow, convert::TryInto, prelude::*};
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
use frame_support::traits::GenesisBuild;
|
||||||
|
|
||||||
pub use pallet::*;
|
pub use pallet::*;
|
||||||
pub use weights::WeightInfo;
|
pub use weights::WeightInfo;
|
||||||
|
|
||||||
@@ -180,10 +183,22 @@ pub mod pallet {
|
|||||||
type Event: From<Event<Self, I>> + IsType<<Self as frame_system::Config>::Event>;
|
type Event: From<Event<Self, I>> + IsType<<Self as frame_system::Config>::Event>;
|
||||||
|
|
||||||
/// The units in which we record balances.
|
/// The units in which we record balances.
|
||||||
type Balance: Member + Parameter + AtLeast32BitUnsigned + Default + Copy + MaxEncodedLen;
|
type Balance: Member
|
||||||
|
+ Parameter
|
||||||
|
+ AtLeast32BitUnsigned
|
||||||
|
+ Default
|
||||||
|
+ Copy
|
||||||
|
+ MaybeSerializeDeserialize
|
||||||
|
+ MaxEncodedLen;
|
||||||
|
|
||||||
/// Identifier for the class of asset.
|
/// Identifier for the class of asset.
|
||||||
type AssetId: Member + Parameter + Default + Copy + HasCompact + MaxEncodedLen;
|
type AssetId: Member
|
||||||
|
+ Parameter
|
||||||
|
+ Default
|
||||||
|
+ Copy
|
||||||
|
+ HasCompact
|
||||||
|
+ MaybeSerializeDeserialize
|
||||||
|
+ MaxEncodedLen;
|
||||||
|
|
||||||
/// The currency mechanism.
|
/// The currency mechanism.
|
||||||
type Currency: ReservableCurrency<Self::AccountId>;
|
type Currency: ReservableCurrency<Self::AccountId>;
|
||||||
@@ -276,6 +291,89 @@ pub mod pallet {
|
|||||||
ConstU32<300_000>,
|
ConstU32<300_000>,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
#[pallet::genesis_config]
|
||||||
|
pub struct GenesisConfig<T: Config<I>, I: 'static = ()> {
|
||||||
|
/// Genesis assets: id, owner, is_sufficient, min_balance
|
||||||
|
pub assets: Vec<(T::AssetId, T::AccountId, bool, T::Balance)>,
|
||||||
|
/// Genesis metadata: id, name, symbol, decimals
|
||||||
|
pub metadata: Vec<(T::AssetId, Vec<u8>, Vec<u8>, u8)>,
|
||||||
|
/// Genesis accounts: id, account_id, balance
|
||||||
|
pub accounts: Vec<(T::AssetId, T::AccountId, T::Balance)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
impl<T: Config<I>, I: 'static> Default for GenesisConfig<T, I> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
assets: Default::default(),
|
||||||
|
metadata: Default::default(),
|
||||||
|
accounts: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pallet::genesis_build]
|
||||||
|
impl<T: Config<I>, I: 'static> GenesisBuild<T, I> for GenesisConfig<T, I> {
|
||||||
|
fn build(&self) {
|
||||||
|
for (id, owner, is_sufficient, min_balance) in &self.assets {
|
||||||
|
assert!(!Asset::<T, I>::contains_key(id), "Asset id already in use");
|
||||||
|
assert!(!min_balance.is_zero(), "Min balance should not be zero");
|
||||||
|
Asset::<T, I>::insert(
|
||||||
|
id,
|
||||||
|
AssetDetails {
|
||||||
|
owner: owner.clone(),
|
||||||
|
issuer: owner.clone(),
|
||||||
|
admin: owner.clone(),
|
||||||
|
freezer: owner.clone(),
|
||||||
|
supply: Zero::zero(),
|
||||||
|
deposit: Zero::zero(),
|
||||||
|
min_balance: *min_balance,
|
||||||
|
is_sufficient: *is_sufficient,
|
||||||
|
accounts: 0,
|
||||||
|
sufficients: 0,
|
||||||
|
approvals: 0,
|
||||||
|
is_frozen: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (id, name, symbol, decimals) in &self.metadata {
|
||||||
|
assert!(Asset::<T, I>::contains_key(id), "Asset does not exist");
|
||||||
|
|
||||||
|
let bounded_name: BoundedVec<u8, T::StringLimit> =
|
||||||
|
name.clone().try_into().expect("asset name is too long");
|
||||||
|
let bounded_symbol: BoundedVec<u8, T::StringLimit> =
|
||||||
|
symbol.clone().try_into().expect("asset symbol is too long");
|
||||||
|
|
||||||
|
let metadata = AssetMetadata {
|
||||||
|
deposit: Zero::zero(),
|
||||||
|
name: bounded_name,
|
||||||
|
symbol: bounded_symbol,
|
||||||
|
decimals: *decimals,
|
||||||
|
is_frozen: false,
|
||||||
|
};
|
||||||
|
Metadata::<T, I>::insert(id, metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (id, account_id, amount) in &self.accounts {
|
||||||
|
let result = <Pallet<T, I>>::increase_balance(
|
||||||
|
*id,
|
||||||
|
account_id,
|
||||||
|
*amount,
|
||||||
|
|details| -> DispatchResult {
|
||||||
|
debug_assert!(
|
||||||
|
T::Balance::max_value() - details.supply >= *amount,
|
||||||
|
"checked in prep; qed"
|
||||||
|
);
|
||||||
|
details.supply = details.supply.saturating_add(*amount);
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert!(result.is_ok());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[pallet::event]
|
#[pallet::event]
|
||||||
#[pallet::generate_deposit(pub(super) fn deposit_event)]
|
#[pallet::generate_deposit(pub(super) fn deposit_event)]
|
||||||
pub enum Event<T: Config<I>, I: 'static = ()> {
|
pub enum Event<T: Config<I>, I: 'static = ()> {
|
||||||
|
|||||||
@@ -144,9 +144,26 @@ pub(crate) fn hooks() -> Vec<Hook> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn new_test_ext() -> sp_io::TestExternalities {
|
pub(crate) fn new_test_ext() -> sp_io::TestExternalities {
|
||||||
let t = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
|
let mut storage = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
|
||||||
|
|
||||||
let mut ext = sp_io::TestExternalities::new(t);
|
let config: pallet_assets::GenesisConfig<Test> = pallet_assets::GenesisConfig {
|
||||||
|
assets: vec![
|
||||||
|
// id, owner, is_sufficient, min_balance
|
||||||
|
(999, 0, true, 1),
|
||||||
|
],
|
||||||
|
metadata: vec![
|
||||||
|
// id, name, symbol, decimals
|
||||||
|
(999, "Token Name".into(), "TOKEN".into(), 10),
|
||||||
|
],
|
||||||
|
accounts: vec![
|
||||||
|
// id, account_id, balance
|
||||||
|
(999, 1, 100),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
config.assimilate_storage(&mut storage).unwrap();
|
||||||
|
|
||||||
|
let mut ext: sp_io::TestExternalities = storage.into();
|
||||||
ext.execute_with(|| System::set_block_number(1));
|
ext.execute_with(|| System::set_block_number(1));
|
||||||
ext
|
ext
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -784,3 +784,13 @@ fn balance_conversion_should_work() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assets_from_genesis_should_exist() {
|
||||||
|
new_test_ext().execute_with(|| {
|
||||||
|
assert!(Asset::<Test>::contains_key(999));
|
||||||
|
assert!(Metadata::<Test>::contains_key(999));
|
||||||
|
assert_eq!(Assets::balance(999, 1), 100);
|
||||||
|
assert_eq!(Assets::total_supply(999), 100);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user