-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #55 from paritytech/feat/migration-pallet
Add pallet migration
- Loading branch information
Showing
13 changed files
with
1,642 additions
and
8 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
[package] | ||
name = "pallet-migration" | ||
version = "0.0.1" | ||
description = "Migration pallet used to recreate the state of marketplace and nfts" | ||
authors = { workspace = true } | ||
homepage = { workspace = true } | ||
edition = { workspace = true } | ||
license = { workspace = true } | ||
publish = false | ||
|
||
[package.metadata.docs.rs] | ||
targets = ["x86_64-unknown-linux-gnu"] | ||
|
||
[dependencies] | ||
parity-scale-codec = { workspace = true, default-features = false, features = [ | ||
"derive", | ||
] } | ||
log = { workspace = true, default-features = false } | ||
scale-info = { workspace = true, default-features = false, features = [ | ||
"derive", | ||
] } | ||
frame-benchmarking = { workspace = true, default-features = false, optional = true } | ||
frame-support = { workspace = true } | ||
frame-system = { workspace = true } | ||
sp-std = { workspace = true } | ||
sp-runtime = { workspace = true, default-features = false } | ||
pallet-nfts = { workspace = true, default-features = false } | ||
pallet-marketplace = { workspace = true, default-features = false } | ||
pallet-timestamp = { workspace = true, default-features = false } | ||
sp-core = { workspace = true, default-features = false } | ||
pallet-balances = { workspace = true, default-features = false } | ||
|
||
# Primitives | ||
account = { workspace = true } | ||
|
||
[dev-dependencies] | ||
sp-io = { workspace = true, default-features = false } | ||
|
||
[features] | ||
default = ["std"] | ||
std = [ | ||
"parity-scale-codec/std", | ||
"frame-benchmarking/std", | ||
"frame-support/std", | ||
"frame-system/std", | ||
"scale-info/std", | ||
"sp-std/std", | ||
"pallet-balances/std", | ||
"pallet-nfts/std", | ||
"pallet-marketplace/std", | ||
"pallet-timestamp/std", | ||
] | ||
runtime-benchmarks = [ | ||
"frame-benchmarking/runtime-benchmarks", | ||
] | ||
try-runtime = ["frame-support/try-runtime"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# Migration Pallet | ||
|
||
The Migration pallet facilitates the transfer of state from the Mythical Hyperledger Besu chain by providing essential functionalities. It enables the migration of collections, items, funds, and marketplace Asks. | ||
|
||
## Overview | ||
|
||
Within this pallet, a designated `Migrator` account is configured in the storage, granting permission to execute calls to pallet-nfts, pallet-marketplace, and pallet-balances to store necessary data: | ||
|
||
- `pallet-nfts`: Enables the creation of collections with specific IDs, configuration of roles for existing collections, setting metadata for collections, and minting items. | ||
- `pallet-marketplace`: Allows for the direct storage of Asks within the pallet's storage, eliminating the need for calling Marketplace::create_order(). | ||
- `pallet-balances`: Facilitates the transfer of funds to a specified account using the balance of a preconfigured Pot account. | ||
|
||
### **Runtime Requirement** | ||
|
||
In order to be able to execute some priviledged operations to `pallet-nfts` the following configuration is required on the runtime: | ||
|
||
```rust | ||
pub type MigratorOrigin = EnsureSignedBy<pallet_migration::MigratorProvider<Runtime>, AccountId>; | ||
|
||
impl pallet_nfts::Config for Runtime { | ||
... | ||
type ForceOrigin = MigratorOrigin; | ||
... | ||
} | ||
``` | ||
|
||
## Dispatchable Functions | ||
|
||
- `force_set_migrator`: Sets the migrator role, granting rights to call this pallet's extrinsics. | ||
- `set_next_collection_id`: Sets the NextCollectionId on pallet-nfts, to be used as the CollectionIdwhen the next collection is created. | ||
- `create_ask`: Creates an Ask inside the Marketplace pallet's storage | ||
- `set_pot_account`: Sets the pot account which will be used as the origin to send funds from on the send_funds_from_pot() extrinsic. | ||
- `send_funds_from_pot`: Transfer funds to a recipient account from the pot account. | ||
- `set_item_owner`: Transfers a given Nft to an AccountId. | ||
- `force_create`: Dispatches a call to pallet-nfts::force_create. | ||
- `set_team`: Dispatches a call to pallet-nfts::set_team. | ||
- `set_collection_metadata`: Dispatches a call to pallet-nfts::set_collection_metadata. | ||
- `force_mint`: Dispatches a call to pallet-nfts::force_mint. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
#![cfg(feature = "runtime-benchmarks")] | ||
use super::*; | ||
use crate::Pallet as Migration; | ||
use frame_benchmarking::v2::*; | ||
use frame_support::{ | ||
assert_ok, | ||
dispatch::RawOrigin, | ||
traits::{ | ||
fungible::{Inspect as InspectFungible, Mutate as MutateFungible}, | ||
tokens::nonfungibles_v2::{Create, Mutate}, | ||
}, | ||
}; | ||
use pallet_marketplace::Ask; | ||
use pallet_marketplace::BenchmarkHelper; | ||
use pallet_nfts::{CollectionConfig, CollectionSettings, ItemConfig, MintSettings, Pallet as Nfts}; | ||
const SEED: u32 = 0; | ||
|
||
fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) { | ||
frame_system::Pallet::<T>::assert_last_event(generic_event.into()); | ||
} | ||
|
||
fn get_migrator<T: Config>() -> T::AccountId { | ||
let migrator: T::AccountId = account("migrator", 10, SEED); | ||
whitelist_account!(migrator); | ||
assert_ok!(Migration::<T>::force_set_migrator(RawOrigin::Root.into(), migrator.clone())); | ||
|
||
migrator | ||
} | ||
|
||
fn funded_and_whitelisted_account<T: Config>(name: &'static str, index: u32) -> T::AccountId { | ||
let caller: T::AccountId = account(name, index, SEED); | ||
// Give the account half of the maximum value of the `Balance` type. | ||
let ed = <T as Config>::Currency::minimum_balance(); | ||
let multiplier = BalanceOf::<T>::from(1000000u32); | ||
|
||
<T as Config>::Currency::set_balance(&caller, ed * multiplier); | ||
whitelist_account!(caller); | ||
caller | ||
} | ||
|
||
fn mint_nft<T: Config>(nft_id: T::ItemId) -> T::AccountId { | ||
let caller: T::AccountId = funded_and_whitelisted_account::<T>("tokenOwner", 0); | ||
|
||
let default_config = CollectionConfig { | ||
settings: CollectionSettings::all_enabled(), | ||
max_supply: None, | ||
mint_settings: MintSettings::default(), | ||
}; | ||
|
||
assert_ok!(Nfts::<T>::create_collection(&caller, &caller, &default_config)); | ||
let collection = T::BenchmarkHelper::collection(0); | ||
assert_ok!(Nfts::<T>::mint_into(&collection, &nft_id, &caller, &ItemConfig::default(), true)); | ||
caller | ||
} | ||
#[benchmarks()] | ||
pub mod benchmarks { | ||
use super::*; | ||
|
||
#[benchmark] | ||
fn force_set_migrator() { | ||
let migrator: T::AccountId = account("migrator", 0, SEED); | ||
|
||
#[extrinsic_call] | ||
_(RawOrigin::Root, migrator.clone()); | ||
|
||
assert_last_event::<T>(Event::MigratorUpdated(migrator).into()); | ||
} | ||
|
||
#[benchmark] | ||
fn set_next_collection_id() { | ||
let next_collection_id = T::BenchmarkHelper::collection(0); | ||
let migrator: T::AccountId = get_migrator::<T>(); | ||
|
||
#[extrinsic_call] | ||
_(RawOrigin::Signed(migrator), next_collection_id.clone()); | ||
|
||
assert_last_event::<T>(Event::NextCollectionIdUpdated(next_collection_id).into()); | ||
} | ||
|
||
#[benchmark] | ||
fn create_ask() { | ||
let migrator: T::AccountId = get_migrator::<T>(); | ||
// Nft Setup | ||
let collection = T::BenchmarkHelper::collection(0); | ||
let item = T::BenchmarkHelper::item(0); | ||
let caller = mint_nft::<T>(item); | ||
let ask = Ask { | ||
seller: caller.clone(), | ||
price: (1000 as u32).into(), | ||
expiration: T::BenchmarkHelper::timestamp(100), | ||
fee: (100 as u32).into(), | ||
}; | ||
|
||
#[extrinsic_call] | ||
_(RawOrigin::Signed(migrator), collection.clone(), item.clone(), ask.clone()); | ||
|
||
assert_last_event::<T>(Event::AskCreated { collection, item, ask }.into()); | ||
} | ||
|
||
#[benchmark] | ||
fn set_pot_account() { | ||
let migrator: T::AccountId = get_migrator::<T>(); | ||
let pot: T::AccountId = account("pot", 0, SEED); | ||
|
||
#[extrinsic_call] | ||
_(RawOrigin::Signed(migrator), pot.clone()); | ||
|
||
assert_last_event::<T>(Event::PotUpdated(pot).into()); | ||
} | ||
|
||
#[benchmark] | ||
fn send_funds_from_pot() { | ||
let migrator: T::AccountId = get_migrator::<T>(); | ||
let pot: T::AccountId = account("pot", 0, SEED); | ||
let receiver: T::AccountId = account("receiver", 0, SEED); | ||
let ed = <T as Config>::Currency::minimum_balance(); | ||
let pot_multi = BalanceOf::<T>::from(1000u32); | ||
let send_multi = BalanceOf::<T>::from(10u32); | ||
let amount_to_send = ed * send_multi; | ||
<T as Config>::Currency::set_balance(&pot, ed * pot_multi); | ||
assert_ok!(Migration::<T>::set_pot_account( | ||
RawOrigin::Signed(migrator.clone()).into(), | ||
pot.clone() | ||
)); | ||
|
||
#[extrinsic_call] | ||
_(RawOrigin::Signed(migrator), receiver.clone(), amount_to_send); | ||
|
||
assert_eq!(<T as Config>::Currency::balance(&receiver), amount_to_send); | ||
} | ||
|
||
#[benchmark] | ||
fn set_item_owner() { | ||
let migrator: T::AccountId = get_migrator::<T>(); | ||
let collection = T::BenchmarkHelper::collection(0); | ||
let item = T::BenchmarkHelper::item(0); | ||
let _ = mint_nft::<T>(item); | ||
let receiver: T::AccountId = account("receiver", 0, SEED); | ||
|
||
#[extrinsic_call] | ||
_(RawOrigin::Signed(migrator), collection.clone(), item.clone(), receiver.clone()); | ||
|
||
assert_eq!(Nfts::<T>::owner(collection, item), Some(receiver)); | ||
} | ||
|
||
impl_benchmark_test_suite!(Migration, crate::mock::new_test_ext(), crate::mock::Test); | ||
} |
Oops, something went wrong.