Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Dmarket and modified Migration pallet to testnet #212

Merged
merged 16 commits into from
Aug 21, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Dmarket pallet for mythical review and testing
valentinfernandez1 committed Aug 1, 2024

Verified

This commit was signed with the committer’s verified signature.
valentinfernandez1 Valentin Fernandez
commit bac8dc3a3803d2c0efa0ccadfab972401143b0d5
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -43,6 +43,7 @@ enumflags2 = { version = "0.7.7" }
# Local dependencies
testnet-runtime = { path = "runtime/testnet" }
mainnet-runtime = { path = "runtime/mainnet" }
pallet-dmarket = { path = "pallets/dmarket", default-features = false }
pallet-marketplace = { path = "pallets/marketplace", default-features = false }
pallet-multibatching = { path = "pallets/multibatching", default-features = false }
runtime-common = { path = "runtime/common", default-features = false }
59 changes: 59 additions & 0 deletions pallets/dmarket/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
[package]
name = "pallet-dmarket"
version = "0.0.1"
description = "DMarket FRAME pallet to provide Nft trading"
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",
] }

# Primitives
account = { workspace = true }

frame-benchmarking = { workspace = true, default-features = false, optional = true }
frame-support = { workspace = true }
frame-system = { workspace = true }
sp-std = { workspace = true }
sp-api = { workspace = true, default-features = false }
sp-io = { workspace = true }
sp-runtime = { workspace = true, default-features = false }
pallet-nfts = { workspace = true, default-features = false }
sp-core = { workspace = true, default-features = false }
sp-keystore = { workspace = true, default-features = false }
pallet-balances = { workspace = true, default-features = false }
pallet-timestamp = { workspace = true, default-features = false }

[dev-dependencies]
sp-io = { workspace = true }

[features]
default = ["std"]
std = [
"account/std",
"parity-scale-codec/std",
"frame-benchmarking?/std",
"frame-support/std",
"frame-system/std",
"scale-info/std",
"sp-io/std",
"sp-api/std",
"sp-std/std",
"pallet-balances/std",
"pallet-nfts/std",
"pallet-timestamp/std",
]
runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"]
try-runtime = ["frame-support/try-runtime"]
3 changes: 3 additions & 0 deletions pallets/dmarket/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Dmarket Pallet

The Dmarket pallet provides a market to buy and sell Nfts from pallet-nft, based on the dmarket Smart contracts from Mythical.
179 changes: 179 additions & 0 deletions pallets/dmarket/src/benchmarking.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
#![cfg(feature = "runtime-benchmarks")]
use super::*;
use crate::Pallet as Dmarket;
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_nfts::ItemId;
use pallet_nfts::{CollectionConfig, CollectionSettings, ItemConfig, MintSettings, Pallet as Nfts};
use sp_core::ecdsa::Public;
use sp_io::{
crypto::{ecdsa_generate, ecdsa_sign_prehashed},
hashing::keccak_256,
};

use crate::BenchmarkHelper;

const SEED: u32 = 0;

type BalanceOf<T> =
<<T as Config>::Currency as InspectFungible<<T as frame_system::Config>::AccountId>>::Balance;

impl<CollectionId, Moment> BenchmarkHelper<CollectionId, Moment> for ()
where
CollectionId: From<u16>,
ItemId: From<u16>,
Moment: From<u64>,
{
fn collection(id: u16) -> CollectionId {
id.into()
}
fn timestamp(value: u64) -> Moment {
value.into()
}
}

fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
frame_system::Pallet::<T>::assert_last_event(generic_event.into());
}

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.
// Otherwise some transfers will fail with an overflow error.
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: ItemId, caller: T::AccountId) {
let default_config = CollectionConfig {
settings: CollectionSettings::all_enabled(),
max_supply: Some(u128::MAX),
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));
}

#[benchmarks(where T::AccountId: From<AccountId20>, T::Signature: From<EthereumSignature>)]
pub mod benchmarks {
use super::*;
use account::{AccountId20, EthereumSignature, EthereumSigner};
use pallet_timestamp::Pallet as Timestamp;

use sp_runtime::traits::IdentifyAccount;

fn sign_trade<T: Config>(
sender: &T::AccountId,
fee_address: &T::AccountId,
trade: &TradeParamsOf<T>,
seller_signer: Public,
buyer_signer: Public,
) -> TradeSignatures<T::Signature>
where
T::Signature: From<EthereumSignature>,
{
let ask_message: Vec<u8> = Dmarket::<T>::get_ask_message(sender, fee_address, trade);
let ask_hashed = keccak_256(&ask_message);

let bid_message: Vec<u8> = Dmarket::<T>::get_bid_message(sender, fee_address, trade);
let bid_hashed = keccak_256(&bid_message);

TradeSignatures {
ask_signature: EthereumSignature::from(
ecdsa_sign_prehashed(0.into(), &seller_signer, &ask_hashed).unwrap(),
)
.into(),
bid_signature: EthereumSignature::from(
ecdsa_sign_prehashed(1.into(), &buyer_signer, &bid_hashed).unwrap(),
)
.into(),
}
}

fn trade_participants<T: Config>() -> (T::AccountId, Public, T::AccountId, Public)
where
T::AccountId: From<AccountId20>,
{
let ed = <T as Config>::Currency::minimum_balance();
let multiplier = BalanceOf::<T>::from(10000u16);

let seller_public = ecdsa_generate(0.into(), None);
let seller_signer: EthereumSigner = seller_public.into();
let seller: T::AccountId = seller_signer.clone().into_account().into();
whitelist_account!(seller);

let buyer_public = ecdsa_generate(1.into(), None);
let buyer_signer: EthereumSigner = buyer_public.into();
let buyer: T::AccountId = buyer_signer.clone().into_account().into();
whitelist_account!(buyer);

<T as Config>::Currency::set_balance(&seller, ed * multiplier);
<T as Config>::Currency::set_balance(&buyer, ed * multiplier);

(seller, seller_public, buyer, buyer_public)
}

#[benchmark]
fn force_set_collection() {
let collection_id = T::BenchmarkHelper::collection(0);
let caller: T::AccountId = funded_and_whitelisted_account::<T>("caller", 0);
let _ = mint_nft::<T>(1, caller);

#[extrinsic_call]
_(RawOrigin::Root, collection_id);

assert_last_event::<T>(Event::CollectionUpdated { collection_id }.into());
}

#[benchmark]
fn execute_trade() {
let sender: T::AccountId = funded_and_whitelisted_account::<T>("sender", 0);
let (seller, seller_public, buyer, buyer_public) = trade_participants::<T>();
let fee_address: T::AccountId = funded_and_whitelisted_account::<T>("fee_address", 0);

let collection_id = T::BenchmarkHelper::collection(0);
let item = 1;
mint_nft::<T>(item, seller.clone());
assert_ok!(Dmarket::<T>::force_set_collection(RawOrigin::Root.into(), collection_id));

let expiration = Timestamp::<T>::get() + T::BenchmarkHelper::timestamp(1000);
let trade = TradeParams {
price: BalanceOf::<T>::from(100u16),
fee: BalanceOf::<T>::from(1u8),
ask_expiration: expiration,
bid_expiration: expiration,
item,
};
let signatures =
sign_trade::<T>(&sender, &fee_address, &trade, seller_public, buyer_public);

#[extrinsic_call]
_(
RawOrigin::Signed(sender),
seller.clone(),
buyer.clone(),
trade.clone(),
signatures,
fee_address,
);

assert_last_event::<T>(
Event::Trade { seller, buyer, item, price: trade.price, fee: trade.fee }.into(),
);
}

impl_benchmark_test_suite!(Dmarket, crate::mock::new_test_ext(), crate::mock::Test);
}
311 changes: 311 additions & 0 deletions pallets/dmarket/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,311 @@
//! # Marketplace Module
//!
//! A module that facilitates trading of non-fungible items (NFTs) through the creation and management of orders.
//!
//! ## Related Modules
//! - NFTs: Provides functionalities for managing non-fungible tokens.
#![cfg_attr(not(feature = "std"), no_std)]

#[cfg(test)]
mod mock;
#[cfg(test)]
mod tests;

#[cfg(feature = "runtime-benchmarks")]
mod benchmarking;

mod types;
use parity_scale_codec::Codec;
pub use types::*;

pub mod weights;
pub use weights::*;

pub use pallet::*;

#[frame_support::pallet]
pub mod pallet {
use core::usize;

use crate::Item;

use super::*;
use frame_support::{
ensure,
pallet_prelude::*,
traits::{
fungible::{Inspect, Mutate},
nonfungibles_v2::{Inspect as NftInspect, Transfer},
tokens::Preservation::Preserve,
},
};
use frame_system::{ensure_signed, pallet_prelude::*};

use frame_support::{dispatch::GetDispatchInfo, traits::UnfilteredDispatchable};

use sp_runtime::traits::Hash;
use sp_runtime::{
traits::{IdentifyAccount, Verify},
DispatchError,
};
use sp_std::vec::Vec;

#[pallet::pallet]
pub struct Pallet<T>(_);

#[pallet::config]
pub trait Config:
frame_system::Config + pallet_nfts::Config + pallet_timestamp::Config
{
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;

type RuntimeCall: Parameter
+ UnfilteredDispatchable<RuntimeOrigin = Self::RuntimeOrigin>
+ GetDispatchInfo;

/// The currency trait.
type Currency: Inspect<Self::AccountId> + Mutate<Self::AccountId>;

/// Off-Chain signature type.
///
/// Can verify whether a `Self::Signer` created a signature.
type Signature: Verify<Signer = Self::Signer> + Parameter;

/// Off-Chain public key.
///
/// Must identify as an on-chain `Self::AccountId`.
type Signer: IdentifyAccount<AccountId = Self::AccountId>;

///Chain Domain
#[pallet::constant]
type Domain: Get<Domain>;

#[cfg(feature = "runtime-benchmarks")]
/// A set of helper functions for benchmarking.
type BenchmarkHelper: BenchmarkHelper<Self::CollectionId, Self::Moment>;
}

#[pallet::storage]
pub type ClosedAsks<T: Config> = StorageMap<_, Blake2_128Concat, T::Hash, OrderDataOf<T>>;

#[pallet::storage]
pub type ClosedBids<T: Config> = StorageMap<_, Blake2_128Concat, T::Hash, OrderDataOf<T>>;

#[pallet::storage]
pub type DmarketCollection<T: Config> = StorageValue<_, T::CollectionId, OptionQuery>;

#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
/// The fee signer account was updated.
CollectionUpdated { collection_id: T::CollectionId },
///
Trade {
buyer: T::AccountId,
seller: T::AccountId,
item: Item,
price: BalanceOf<T>,
fee: BalanceOf<T>,
},
}

#[pallet::error]
pub enum Error<T> {
/// The item was not found.
ItemNotFound,
/// Item can only be operated by the Item owner.
SellerNotItemOwner,
///
BidAlreadyExecuted,
///
AskAlreadyExecuted,
///
BuyerBalanceTooLow,
///
BidExpired,
///
AskExpired,
///
InvalidBuyerSignature,
///
InvalidSellerSignature,
/// Same buyer and seller not allowed.
BuyerIsSeller,
///
BadSignedMessage,
///
CollectionAlreadyInUse,
///
CollectionNotSet,
///
CollectionNotFound,
}

#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::call_index(0)]
#[pallet::weight({0})]
pub fn force_set_collection(
origin: OriginFor<T>,
collection_id: T::CollectionId,
) -> DispatchResult {
ensure_root(origin)?;

<pallet_nfts::Pallet<T> as NftInspect<T::AccountId>>::collection_owner(&collection_id)
.ok_or(Error::<T>::CollectionNotFound)?;

ensure!(
DmarketCollection::<T>::get().as_ref() != Some(&collection_id),
Error::<T>::CollectionAlreadyInUse
);

DmarketCollection::<T>::put(collection_id.clone());
Self::deposit_event(Event::CollectionUpdated { collection_id });
Ok(())
}

#[pallet::call_index(1)]
#[pallet::weight({0})]
pub fn execute_trade(
origin: OriginFor<T>,
seller: T::AccountId,
buyer: T::AccountId,
trade: TradeParamsOf<T>,
signatures: TradeSignatures<<T as Config>::Signature>,
fee_address: T::AccountId,
) -> DispatchResult {
let who = ensure_signed(origin)?;

ensure!(seller != buyer, Error::<T>::BuyerIsSeller);

let timestamp = pallet_timestamp::Pallet::<T>::get();
ensure!(trade.ask_expiration > timestamp, Error::<T>::AskExpired);
ensure!(trade.bid_expiration > timestamp, Error::<T>::BidExpired);

// Pay fees to FeeAddress
let collection = DmarketCollection::<T>::get().ok_or(Error::<T>::CollectionNotSet)?;

let item_owner = pallet_nfts::Pallet::<T>::owner(collection, trade.item)
.ok_or(Error::<T>::ItemNotFound)?;
ensure!(seller == item_owner, Error::<T>::SellerNotItemOwner);

let (ask_hash, bid_hash) = Self::hash_ask_bid_data(&trade);
ensure!(!ClosedAsks::<T>::contains_key(ask_hash), Error::<T>::AskAlreadyExecuted);
ensure!(!ClosedBids::<T>::contains_key(bid_hash), Error::<T>::BidAlreadyExecuted);

Self::verify_signature(
&seller,
&Self::get_ask_message(&who, &fee_address, &trade),
signatures.ask_signature,
)
.map_err(|_| Error::<T>::InvalidSellerSignature)?;

Self::verify_signature(
&buyer,
&Self::get_bid_message(&who, &fee_address, &trade),
signatures.bid_signature,
)
.map_err(|_| Error::<T>::InvalidBuyerSignature)?;

<pallet_nfts::Pallet<T> as Transfer<T::AccountId>>::transfer(
&collection,
&trade.item,
&buyer,
)?;
<T as crate::Config>::Currency::transfer(&buyer, &seller, trade.price, Preserve)
.map_err(|_| Error::<T>::BuyerBalanceTooLow)?;
<T as crate::Config>::Currency::transfer(&seller, &fee_address, trade.fee, Preserve)?;

let order_data: OrderDataOf<T> = OrderData { caller: who, fee_address };

//Store closed trades
ClosedAsks::<T>::insert(ask_hash, order_data.clone());
ClosedBids::<T>::insert(bid_hash, order_data);

Self::deposit_event(Event::Trade {
seller,
buyer,
item: trade.item,
price: trade.price,
fee: trade.fee,
});

Ok(())
}
}

impl<T: Config> Pallet<T> {
fn verify_signature(
who: &T::AccountId,
message: &Vec<u8>,
signature: T::Signature,
) -> Result<(), DispatchError> {
if !signature.verify(message.as_ref(), &who) {
return Err(Error::<T>::BadSignedMessage.into());
}

Ok(())
}

pub fn hash_ask_bid_data(trade: &TradeParamsOf<T>) -> (T::Hash, T::Hash) {
let ask_hash =
T::Hashing::hash(&(trade.item, trade.price, trade.ask_expiration).encode());
let bid_hash = T::Hashing::hash(
&(trade.item, trade.price, trade.fee, trade.bid_expiration).encode(),
);

(ask_hash, bid_hash)
}

pub fn get_ask_message(
caller: &T::AccountId,
fee_address: &T::AccountId,
trade: &TradeParamsOf<T>,
) -> Vec<u8> {
AskMessage {
domain: T::Domain::get(),
sender: caller.clone(),
fee_address: fee_address.clone(),
item: trade.item,
price: trade.price,
expiration: trade.ask_expiration,
}
.encode()
}

pub fn get_bid_message(
caller: &T::AccountId,
fee_address: &T::AccountId,
trade: &TradeParamsOf<T>,
) -> Vec<u8> {
BidMessage {
domain: T::Domain::get(),
sender: caller.clone(),
fee_address: fee_address.clone(),
item: trade.item,
price: trade.price,
fee: trade.fee,
expiration: trade.bid_expiration,
}
.encode()
}
}
}

sp_core::generate_feature_enabled_macro!(runtime_benchmarks_enabled, feature = "runtime-benchmarks", $);

use sp_std::vec::Vec;
sp_api::decl_runtime_apis! {
pub trait DmarketApi<AccountId, Balance, Moment, Hash>
where
AccountId: Codec,
Balance: Codec,
Moment: Codec,
Hash: Codec,
{
fn hash_ask_bid_data(trade: TradeParams<Balance, Item, Moment>)-> (Hash, Hash);
fn get_ask_message(caller: AccountId, fee_address: AccountId, trade: TradeParams<Balance, Item, Moment>) -> Vec<u8>;
fn get_bid_message(caller: AccountId, fee_address: AccountId, trade: TradeParams<Balance, Item, Moment>) -> Vec<u8>;
}
}
144 changes: 144 additions & 0 deletions pallets/dmarket/src/mock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
use frame_support::{
derive_impl, parameter_types,
traits::{AsEnsureOriginWithArg, ConstU128, ConstU32, ConstU64},
};
use frame_system as system;
use sp_core::H256;
use sp_keystore::{testing::MemoryKeystore, KeystoreExt};
use sp_runtime::{
traits::{BlakeTwo256, IdentifyAccount, IdentityLookup, Verify},
BuildStorage,
};

use account::EthereumSignature;

use crate::{self as pallet_dmarket};
use pallet_nfts::PalletFeatures;

type Signature = EthereumSignature;
pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
type Block = frame_system::mocking::MockBlock<Test>;

// Configure a mock runtime to test the pallet.
frame_support::construct_runtime!(
pub enum Test
{
System: frame_system,
Dmarket: pallet_dmarket,
Balances: pallet_balances,
Timestamp: pallet_timestamp,
Nfts: pallet_nfts,
}
);

parameter_types! {
pub const BlockHashCount: u64 = 250;
pub const SS58Prefix: u8 = 42;
}

#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)]
impl frame_system::Config for Test {
type BaseCallFilter = frame_support::traits::Everything;
type BlockWeights = ();
type BlockLength = ();
type RuntimeOrigin = RuntimeOrigin;
type RuntimeCall = RuntimeCall;
type Nonce = u64;
type Hash = H256;
type Hashing = BlakeTwo256;
type AccountId = AccountId;
type Lookup = IdentityLookup<Self::AccountId>;
type Block = Block;
type RuntimeEvent = RuntimeEvent;
type BlockHashCount = ConstU64<250>;
type DbWeight = ();
type Version = ();
type PalletInfo = PalletInfo;
type AccountData = pallet_balances::AccountData<u128>;
type OnNewAccount = ();
type OnKilledAccount = ();
type SystemWeightInfo = ();
type SS58Prefix = ();
type OnSetCode = ();
type MaxConsumers = ConstU32<16>;
}

parameter_types! {
pub storage Features: PalletFeatures = PalletFeatures::all_enabled();
}

impl pallet_nfts::Config for Test {
type RuntimeEvent = RuntimeEvent;
type CollectionId = u32;
type Currency = Balances;
type CreateOrigin = AsEnsureOriginWithArg<frame_system::EnsureSigned<Self::AccountId>>;
type ForceOrigin = frame_system::EnsureRoot<Self::AccountId>;
type Locker = ();
type CollectionDeposit = ConstU128<0>;
type ItemDeposit = ConstU128<0>;
type MetadataDepositBase = ConstU128<1>;
type AttributeDepositBase = ConstU128<1>;
type DepositPerByte = ConstU128<1>;
type StringLimit = ConstU32<50>;
type KeyLimit = ConstU32<50>;
type ValueLimit = ConstU32<50>;
type ApprovalsLimit = ConstU32<10>;
type ItemAttributesApprovalsLimit = ConstU32<2>;
type MaxTips = ConstU32<10>;
type MaxDeadlineDuration = ConstU64<10000>;
type MaxAttributesPerCall = ConstU32<2>;
type Features = Features;
type OffchainSignature = Signature;
type OffchainPublic = <Signature as Verify>::Signer;
type WeightInfo = ();
pallet_nfts::runtime_benchmarks_enabled! {
type Helper = ();
}
}

impl pallet_balances::Config for Test {
type MaxLocks = ();
type MaxReserves = ConstU32<2>;
type ReserveIdentifier = [u8; 8];
type Balance = u128;
type DustRemoval = ();
type RuntimeEvent = RuntimeEvent;
type ExistentialDeposit = ConstU128<1>;
type AccountStore = System;
type WeightInfo = ();
type RuntimeHoldReason = RuntimeHoldReason;
type RuntimeFreezeReason = ();
type FreezeIdentifier = ();
type MaxFreezes = ();
}

impl pallet_timestamp::Config for Test {
type Moment = u64;
type OnTimestampSet = ();
type MinimumPeriod = ConstU64<3>;
type WeightInfo = ();
}

parameter_types! {
pub const DOMAIN: [u8;8] = *b"MYTH_NET";
}

impl crate::Config for Test {
type RuntimeEvent = RuntimeEvent;
type RuntimeCall = RuntimeCall;
type Currency = Balances;
type Signature = Signature;
type Signer = <Signature as Verify>::Signer;
type Domain = DOMAIN;
#[cfg(feature = "runtime-benchmarks")]
type BenchmarkHelper = ();
}

// Build genesis storage according to the mock runtime.
pub fn new_test_ext() -> sp_io::TestExternalities {
let t = system::GenesisConfig::<Test>::default().build_storage().unwrap();
let mut ext = sp_io::TestExternalities::new(t);
ext.register_extension(KeystoreExt::new(MemoryKeystore::new()));
ext.execute_with(|| System::set_block_number(1));
ext
}
547 changes: 547 additions & 0 deletions pallets/dmarket/src/tests.rs

Large diffs are not rendered by default.

84 changes: 84 additions & 0 deletions pallets/dmarket/src/types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
use crate::Config;
use frame_support::traits::fungible::Inspect;
use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;

pub type BalanceOf<T> =
<<T as Config>::Currency as Inspect<<T as frame_system::Config>::AccountId>>::Balance;

pub type Item = u128;
pub type Domain = [u8; 8];

#[derive(Clone, Encode, Decode, Debug, Eq, PartialEq, TypeInfo)]
pub struct TradeParams<Amount, ItemId, Expiration> {
pub price: Amount,
pub fee: Amount,
pub item: ItemId,
pub ask_expiration: Expiration,
pub bid_expiration: Expiration,
}

pub type TradeParamsOf<T> = TradeParams<
<<T as Config>::Currency as Inspect<<T as frame_system::Config>::AccountId>>::Balance,
Item,
<T as pallet_timestamp::Config>::Moment,
>;

#[derive(Clone, Encode, Decode, Debug, Eq, PartialEq, TypeInfo)]
pub struct TradeSignatures<OffchainSignature> {
pub ask_signature: OffchainSignature,
pub bid_signature: OffchainSignature,
}

pub type TradeSignaturesOf<T> = TradeSignatures<<T as pallet_nfts::Config>::OffchainSignature>;

#[derive(Clone, Encode, Decode, Debug, Eq, PartialEq, TypeInfo)]
pub struct AskMessage<Account, Amount, ItemId, Expiration> {
pub domain: Domain,
pub sender: Account,
pub fee_address: Account,
pub item: ItemId,
pub price: Amount,
pub expiration: Expiration,
}

pub type AskMessageOf<T> = AskMessage<
<T as frame_system::Config>::AccountId,
<<T as Config>::Currency as Inspect<<T as frame_system::Config>::AccountId>>::Balance,
Item,
<T as pallet_timestamp::Config>::Moment,
>;

#[derive(Clone, Encode, Decode, Debug, Eq, PartialEq, TypeInfo, MaxEncodedLen)]
pub struct OrderData<Account> {
pub caller: Account,
pub fee_address: Account,
}

pub type OrderDataOf<T> = OrderData<<T as frame_system::Config>::AccountId>;

#[derive(Clone, Encode, Decode, Debug, Eq, PartialEq, TypeInfo)]
pub struct BidMessage<Account, Amount, ItemId, Expiration> {
pub domain: Domain,
pub sender: Account,
pub fee_address: Account,
pub item: ItemId,
pub price: Amount,
pub fee: Amount,
pub expiration: Expiration,
}

pub type BidMessageOf<T> = BidMessage<
<T as frame_system::Config>::AccountId,
<<T as Config>::Currency as Inspect<<T as frame_system::Config>::AccountId>>::Balance,
Item,
<T as pallet_timestamp::Config>::Moment,
>;

#[cfg(feature = "runtime-benchmarks")]
pub trait BenchmarkHelper<CollectionId, Moment> {
/// Returns a collection id from a given integer.
fn collection(id: u16) -> CollectionId;
/// Returns an nft id from a given integer.
fn timestamp(value: u64) -> Moment;
}
202 changes: 202 additions & 0 deletions pallets/dmarket/src/weights.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@

//! Autogenerated weights for `pallet_dmarket`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
//! DATE: 2024-06-05, STEPS: `10`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `pop-os`, CPU: `AMD Ryzen 9 7900X 12-Core Processor`
//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024`
// Executed Command:
// ./target/release/mythos-node
// benchmark
// pallet
// --steps
// 10
// --template
// ./.maintain/template.hbs
// --repeat
// 20
// --extrinsic
// *
// --wasm-execution
// compiled
// --heap-pages
// 4096
// --pallet
// pallet_dmarket
// --output
// ./pallets/dmarket/src/weights.rs

#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
#![allow(missing_docs)]

use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
use core::marker::PhantomData;

/// Weight functions needed for `pallet_dmarket`.
pub trait WeightInfo {
fn force_set_balance_manager() -> Weight;
fn force_set_collection() -> Weight;
fn set_fee_address() -> Weight;
fn execute_trade() -> Weight;
}

/// Weights for `pallet_dmarket` using the Substrate node and recommended hardware.
pub struct SubstrateWeight<T>(PhantomData<T>);
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
/// Storage: `Dmarket::BalanceManager` (r:1 w:1)
/// Proof: `Dmarket::BalanceManager` (`max_values`: Some(1), `max_size`: Some(20), added: 515, mode: `MaxEncodedLen`)
fn force_set_balance_manager() -> Weight {
// Proof Size summary in bytes:
// Measured: `76`
// Estimated: `1505`
// Minimum execution time: 4_650_000 picoseconds.
Weight::from_parts(4_920_000, 1505)
.saturating_add(T::DbWeight::get().reads(1_u64))
.saturating_add(T::DbWeight::get().writes(1_u64))
}
/// Storage: `Nfts::Collection` (r:1 w:0)
/// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`)
/// Storage: `Dmarket::DmarketCollection` (r:1 w:1)
/// Proof: `Dmarket::DmarketCollection` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
fn force_set_collection() -> Weight {
// Proof Size summary in bytes:
// Measured: `420`
// Estimated: `3610`
// Minimum execution time: 10_150_000 picoseconds.
Weight::from_parts(10_390_000, 3610)
.saturating_add(T::DbWeight::get().reads(2_u64))
.saturating_add(T::DbWeight::get().writes(1_u64))
}
/// Storage: `Dmarket::BalanceManager` (r:1 w:0)
/// Proof: `Dmarket::BalanceManager` (`max_values`: Some(1), `max_size`: Some(20), added: 515, mode: `MaxEncodedLen`)
/// Storage: `Dmarket::FeeAddress` (r:1 w:1)
/// Proof: `Dmarket::FeeAddress` (`max_values`: Some(1), `max_size`: Some(20), added: 515, mode: `MaxEncodedLen`)
fn set_fee_address() -> Weight {
// Proof Size summary in bytes:
// Measured: `120`
// Estimated: `1505`
// Minimum execution time: 6_770_000 picoseconds.
Weight::from_parts(7_020_000, 1505)
.saturating_add(T::DbWeight::get().reads(2_u64))
.saturating_add(T::DbWeight::get().writes(1_u64))
}
/// Storage: `Dmarket::BalanceManager` (r:1 w:0)
/// Proof: `Dmarket::BalanceManager` (`max_values`: Some(1), `max_size`: Some(20), added: 515, mode: `MaxEncodedLen`)
/// Storage: `Timestamp::Now` (r:1 w:0)
/// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
/// Storage: `Dmarket::FeeAddress` (r:1 w:0)
/// Proof: `Dmarket::FeeAddress` (`max_values`: Some(1), `max_size`: Some(20), added: 515, mode: `MaxEncodedLen`)
/// Storage: `Dmarket::DmarketCollection` (r:1 w:0)
/// Proof: `Dmarket::DmarketCollection` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
/// Storage: `Nfts::Item` (r:1 w:1)
/// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(637), added: 3112, mode: `MaxEncodedLen`)
/// Storage: `Dmarket::ClosedAsks` (r:1 w:1)
/// Proof: `Dmarket::ClosedAsks` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
/// Storage: `Dmarket::ClosedBids` (r:1 w:1)
/// Proof: `Dmarket::ClosedBids` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
/// Storage: `Nfts::Collection` (r:1 w:0)
/// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`)
/// Storage: `Nfts::Attribute` (r:1 w:0)
/// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(495), added: 2970, mode: `MaxEncodedLen`)
/// Storage: `Nfts::CollectionConfigOf` (r:1 w:0)
/// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(142), added: 2617, mode: `MaxEncodedLen`)
/// Storage: `Nfts::ItemConfigOf` (r:1 w:0)
/// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`)
/// Storage: `Nfts::Account` (r:0 w:2)
/// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`)
/// Storage: `Nfts::ItemPriceOf` (r:0 w:1)
/// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(117), added: 2592, mode: `MaxEncodedLen`)
/// Storage: `Nfts::PendingSwapOf` (r:0 w:1)
/// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(151), added: 2626, mode: `MaxEncodedLen`)
fn execute_trade() -> Weight {
// Proof Size summary in bytes:
// Measured: `1228`
// Estimated: `4102`
// Minimum execution time: 172_460_000 picoseconds.
Weight::from_parts(174_840_000, 4102)
.saturating_add(T::DbWeight::get().reads(11_u64))
.saturating_add(T::DbWeight::get().writes(7_u64))
}
}

// For backwards compatibility and tests.
impl WeightInfo for () {
/// Storage: `Dmarket::BalanceManager` (r:1 w:1)
/// Proof: `Dmarket::BalanceManager` (`max_values`: Some(1), `max_size`: Some(20), added: 515, mode: `MaxEncodedLen`)
fn force_set_balance_manager() -> Weight {
// Proof Size summary in bytes:
// Measured: `76`
// Estimated: `1505`
// Minimum execution time: 4_650_000 picoseconds.
Weight::from_parts(4_920_000, 1505)
.saturating_add(RocksDbWeight::get().reads(1_u64))
.saturating_add(RocksDbWeight::get().writes(1_u64))
}
/// Storage: `Nfts::Collection` (r:1 w:0)
/// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`)
/// Storage: `Dmarket::DmarketCollection` (r:1 w:1)
/// Proof: `Dmarket::DmarketCollection` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
fn force_set_collection() -> Weight {
// Proof Size summary in bytes:
// Measured: `420`
// Estimated: `3610`
// Minimum execution time: 10_150_000 picoseconds.
Weight::from_parts(10_390_000, 3610)
.saturating_add(RocksDbWeight::get().reads(2_u64))
.saturating_add(RocksDbWeight::get().writes(1_u64))
}
/// Storage: `Dmarket::BalanceManager` (r:1 w:0)
/// Proof: `Dmarket::BalanceManager` (`max_values`: Some(1), `max_size`: Some(20), added: 515, mode: `MaxEncodedLen`)
/// Storage: `Dmarket::FeeAddress` (r:1 w:1)
/// Proof: `Dmarket::FeeAddress` (`max_values`: Some(1), `max_size`: Some(20), added: 515, mode: `MaxEncodedLen`)
fn set_fee_address() -> Weight {
// Proof Size summary in bytes:
// Measured: `120`
// Estimated: `1505`
// Minimum execution time: 6_770_000 picoseconds.
Weight::from_parts(7_020_000, 1505)
.saturating_add(RocksDbWeight::get().reads(2_u64))
.saturating_add(RocksDbWeight::get().writes(1_u64))
}
/// Storage: `Dmarket::BalanceManager` (r:1 w:0)
/// Proof: `Dmarket::BalanceManager` (`max_values`: Some(1), `max_size`: Some(20), added: 515, mode: `MaxEncodedLen`)
/// Storage: `Timestamp::Now` (r:1 w:0)
/// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
/// Storage: `Dmarket::FeeAddress` (r:1 w:0)
/// Proof: `Dmarket::FeeAddress` (`max_values`: Some(1), `max_size`: Some(20), added: 515, mode: `MaxEncodedLen`)
/// Storage: `Dmarket::DmarketCollection` (r:1 w:0)
/// Proof: `Dmarket::DmarketCollection` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
/// Storage: `Nfts::Item` (r:1 w:1)
/// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(637), added: 3112, mode: `MaxEncodedLen`)
/// Storage: `Dmarket::ClosedAsks` (r:1 w:1)
/// Proof: `Dmarket::ClosedAsks` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
/// Storage: `Dmarket::ClosedBids` (r:1 w:1)
/// Proof: `Dmarket::ClosedBids` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
/// Storage: `Nfts::Collection` (r:1 w:0)
/// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`)
/// Storage: `Nfts::Attribute` (r:1 w:0)
/// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(495), added: 2970, mode: `MaxEncodedLen`)
/// Storage: `Nfts::CollectionConfigOf` (r:1 w:0)
/// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(142), added: 2617, mode: `MaxEncodedLen`)
/// Storage: `Nfts::ItemConfigOf` (r:1 w:0)
/// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`)
/// Storage: `Nfts::Account` (r:0 w:2)
/// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`)
/// Storage: `Nfts::ItemPriceOf` (r:0 w:1)
/// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(117), added: 2592, mode: `MaxEncodedLen`)
/// Storage: `Nfts::PendingSwapOf` (r:0 w:1)
/// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(151), added: 2626, mode: `MaxEncodedLen`)
fn execute_trade() -> Weight {
// Proof Size summary in bytes:
// Measured: `1228`
// Estimated: `4102`
// Minimum execution time: 172_460_000 picoseconds.
Weight::from_parts(174_840_000, 4102)
.saturating_add(RocksDbWeight::get().reads(11_u64))
.saturating_add(RocksDbWeight::get().writes(7_u64))
}
}