Skip to content

Commit

Permalink
Merge pull request #55 from paritytech/feat/migration-pallet
Browse files Browse the repository at this point in the history
Add pallet migration
  • Loading branch information
gautamdhameja authored May 3, 2024
2 parents 141f936 + bb39102 commit afba67d
Show file tree
Hide file tree
Showing 13 changed files with 1,642 additions and 8 deletions.
22 changes: 22 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ hex = { version = "0.4.3", default-features = false }
testnet-runtime = { path = "runtime/testnet" }
mainnet-runtime = { path = "runtime/mainnet" }
pallet-marketplace = { path = "pallets/marketplace", default-features = false }
pallet-migration = { path = "pallets/migration", default-features = false }
pallet-multibatching = { path = "pallets/multibatching", default-features = false }
runtime-common = { path = "runtime/common", default-features = false }

Expand Down
1 change: 0 additions & 1 deletion node/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,6 @@ where
}

#[allow(clippy::too_many_arguments)]

fn start_consensus<RuntimeApi, Executor>(
client: Arc<ParachainClient<RuntimeApi, Executor>>,
backend: Arc<ParachainBackend>,
Expand Down
56 changes: 56 additions & 0 deletions pallets/migration/Cargo.toml
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"]
38 changes: 38 additions & 0 deletions pallets/migration/README.md
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.
147 changes: 147 additions & 0 deletions pallets/migration/src/benchmarking.rs
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);
}
Loading

0 comments on commit afba67d

Please sign in to comment.