diff --git a/Cargo.lock b/Cargo.lock index 31272c721b..70742ae5ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1159,11 +1159,13 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "log", "node-primitives", "orml-tokens 0.4.1-dev (git+https://github.com/open-web3-stack/open-runtime-module-library?rev=17a791edf431d7d7aee1ea3dfaeeb7bc21944301)", "orml-traits 0.4.1-dev (git+https://github.com/open-web3-stack/open-runtime-module-library?rev=17a791edf431d7d7aee1ea3dfaeeb7bc21944301)", "parity-scale-codec", "scale-info", + "sp-arithmetic", "sp-core", "sp-io", "sp-runtime", diff --git a/pallets/vsbond-auction/Cargo.toml b/pallets/vsbond-auction/Cargo.toml index 407c1b70e0..351afcc93b 100644 --- a/pallets/vsbond-auction/Cargo.toml +++ b/pallets/vsbond-auction/Cargo.toml @@ -15,6 +15,8 @@ frame-support = { git = "https://github.com/paritytech/substrate", branch = "pol node-primitives = { path = "../../node/primitives", default-features = false } orml-traits = { version = "0.4.1-dev", default-features = false } frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13", default-features = false, optional = true } +sp-arithmetic = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13", default-features = false } +log = { version = "0.4.14", default-features = false } [dev-dependencies] orml-tokens = { version = "0.4.1-dev" } @@ -32,6 +34,7 @@ std = [ "frame-support/std", "node-primitives/std", "orml-traits/std", + "log/std", ] runtime-benchmarks = [ diff --git a/pallets/vsbond-auction/src/lib.rs b/pallets/vsbond-auction/src/lib.rs index 872e3f3442..4f95d7147a 100644 --- a/pallets/vsbond-auction/src/lib.rs +++ b/pallets/vsbond-auction/src/lib.rs @@ -31,19 +31,23 @@ use core::fmt::Debug; use frame_support::{ pallet_prelude::*, sp_runtime::{ - traits::{AtLeast32BitUnsigned, SaturatedConversion, Saturating, Zero}, + traits::{ + AccountIdConversion, AtLeast32BitUnsigned, SaturatedConversion, Saturating, Zero, + }, FixedPointNumber, FixedU128, }, - transactional, + transactional, PalletId, }; use frame_system::pallet_prelude::*; use node_primitives::{CurrencyId, LeasePeriod, ParaId, TokenSymbol}; use orml_traits::{MultiCurrency, MultiReservableCurrency}; pub use pallet::*; use scale_info::TypeInfo; +use sp_arithmetic::per_things::Permill; use sp_std::cmp::min; pub use weights::WeightInfo; +pub mod migration; #[cfg(test)] mod mock; #[cfg(test)] @@ -69,7 +73,8 @@ where remain: BalanceOf, /// Total price of the order total_price: BalanceOf, - /// Helper to calculate the remain to unreserve + /// Helper to calculate the remain to unreserve. + /// Useful for buy order, it is the amount that has not been spent yet. remain_price: BalanceOf, /// The unique id of the order order_id: OrderId, @@ -135,14 +140,24 @@ pub mod pallet { /// Set default weight. type WeightInfo: WeightInfo; + + /// ModuleID for creating sub account + #[pallet::constant] + type PalletId: Get; + + /// The account that transaction fees go into + #[pallet::constant] + type TreasuryAccount: Get; + + /// The only origin that can modify transaction fee rate + type ControlOrigin: EnsureOrigin; } #[pallet::error] pub enum Error { NotEnoughAmount, NotFindOrderInfo, - NotEnoughBalanceToUnreserve, - NotEnoughBalanceToReserve, + NotEnoughBalanceToCreateOrder, DontHaveEnoughToPay, ForbidRevokeOrderNotInTrade, ForbidRevokeOrderWithoutOwnership, @@ -151,6 +166,7 @@ pub mod pallet { ExceedMaximumOrderInTrade, InvalidVsbond, Unexpected, + InvalidRateInput, } #[pallet::event] @@ -195,6 +211,10 @@ pub mod pallet { BalanceOf, BalanceOf, ), + /// Transaction fee rate has been reset. + /// + /// [buy_fee_rate, sell_fee_rate] + TransactionFeeRateSet(Permill, Permill), } #[pallet::storage] @@ -217,9 +237,21 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn order_info)] - pub(crate) type TotalOrderInfos, I: 'static = ()> = + pub type TotalOrderInfos, I: 'static = ()> = StorageMap<_, Blake2_128Concat, OrderId, OrderInfo, BalanceOf>>; + /// transaction fee rate[sellFee, buyFee] + #[pallet::storage] + #[pallet::getter(fn get_transaction_fee_rate)] + pub type TransactionFee, I: 'static = ()> = + StorageValue<_, (Permill, Permill), ValueQuery, DefaultPrice>; + + // Defult rate for sell and buy transaction fees is 0 + #[pallet::type_value] + pub fn DefaultPrice() -> (Permill, Permill) { + (Permill::zero(), Permill::zero()) + } + #[pallet::pallet] pub struct Pallet(PhantomData<(T, I)>); @@ -254,15 +286,40 @@ pub mod pallet { let (_, vsbond) = CurrencyId::vsAssets(token_symbol, index, first_slot, last_slot); // Check the balance - let (token_reserved, amount_reserved) = match order_type { + let (token_to_transfer, amount_to_transfer) = match order_type { OrderType::Buy => (T::InvoicingCurrency::get(), total_price), OrderType::Sell => (vsbond, amount), }; - ensure!( - T::MultiCurrency::can_reserve(token_reserved, &owner, amount_reserved), - Error::::NotEnoughBalanceToReserve - ); + // Calculate the transaction fee + let maker_fee_rate = Self::get_transaction_fee_rate().0; + let maker_fee = maker_fee_rate.mul_floor(total_price); + + match order_type { + OrderType::Buy => { + T::MultiCurrency::ensure_can_withdraw( + token_to_transfer, + &owner, + amount_to_transfer.saturating_add(maker_fee), + ) + .map_err(|_| Error::::NotEnoughBalanceToCreateOrder)?; + }, + OrderType::Sell => { + T::MultiCurrency::ensure_can_withdraw( + token_to_transfer, + &owner, + amount_to_transfer, + ) + .map_err(|_| Error::::NotEnoughBalanceToCreateOrder)?; + + T::MultiCurrency::ensure_can_withdraw( + T::InvoicingCurrency::get(), + &owner, + maker_fee, + ) + .map_err(|_| Error::::NotEnoughBalanceToCreateOrder)?; + }, + } let order_ids_len = Self::user_order_ids(&owner, order_type).len(); ensure!( @@ -283,8 +340,23 @@ pub mod pallet { order_type, }; - // Reserve the balance. - T::MultiCurrency::reserve(token_reserved, &owner, amount_reserved)?; + let module_account: AccountIdOf = T::PalletId::get().into_account(); + + // Transfer the amount to vsbond-acution module account. + T::MultiCurrency::transfer( + token_to_transfer, + &owner, + &module_account, + amount_to_transfer, + )?; + + // Charge fee + T::MultiCurrency::transfer( + T::InvoicingCurrency::get(), + &owner, + &T::TreasuryAccount::get(), + maker_fee, + )?; // Insert OrderInfo to Storage TotalOrderInfos::::insert(order_id, order_info); @@ -320,33 +392,22 @@ pub mod pallet { // Check OrderOwner ensure!(order_info.owner == from, Error::::ForbidRevokeOrderWithoutOwnership); - let (token_unreserve, amount_unreserve) = match order_info.order_type { - OrderType::Buy => (T::InvoicingCurrency::get(), order_info.remain_price), - OrderType::Sell => (order_info.vsbond, order_info.remain), - }; + Self::do_order_revoke(order_id)?; - // To unreserve - let reserved_balance = - T::MultiCurrency::reserved_balance(token_unreserve, &order_info.owner); - ensure!( - reserved_balance >= amount_unreserve, - Error::::NotEnoughBalanceToUnreserve - ); - T::MultiCurrency::unreserve(token_unreserve, &order_info.owner, amount_unreserve); + Ok(().into()) + } - // Revoke order - TotalOrderInfos::::remove(order_id); - Self::try_to_remove_order_id(order_info.owner.clone(), order_info.order_type, order_id); + /// Revoke a sell or buy order in trade by the order creator. + #[transactional] + #[pallet::weight(T::WeightInfo::revoke_order())] + pub fn force_revoke( + origin: OriginFor, + #[pallet::compact] order_id: OrderId, + ) -> DispatchResultWithPostInfo { + // Check origin + T::ControlOrigin::ensure_origin(origin)?; - Self::deposit_event(Event::OrderRevoked( - order_id, - order_info.order_type, - order_info.owner, - order_info.vsbond, - order_info.amount, - order_info.remain, - order_info.total_price, - )); + Self::do_order_revoke(order_id)?; Ok(().into()) } @@ -379,20 +440,23 @@ pub mod pallet { } // Check origin - let opponent = ensure_signed(origin)?; + let order_taker = ensure_signed(origin)?; // Check OrderInfo let order_info = Self::order_info(order_id).ok_or(Error::::NotFindOrderInfo)?; // Check OrderOwner - ensure!(order_info.owner != opponent, Error::::ForbidClinchOrderWithinOwnership); + ensure!( + order_info.owner != order_taker, + Error::::ForbidClinchOrderWithinOwnership + ); // Calculate the real quantity to clinch let quantity_clinchd = min(order_info.remain, quantity); // Calculate the total price that buyer need to pay let price_to_pay = Self::price_to_pay(quantity_clinchd, order_info.unit_price()); - let (token_owner, amount_owner, token_opponent, amount_opponent) = match order_info + let (token_to_get, amount_to_get, token_to_pay, amount_to_pay) = match order_info .order_type { OrderType::Buy => @@ -401,9 +465,39 @@ pub mod pallet { (order_info.vsbond, quantity_clinchd, T::InvoicingCurrency::get(), price_to_pay), }; - // Check the balance of opponent - T::MultiCurrency::ensure_can_withdraw(token_opponent, &opponent, amount_opponent) - .map_err(|_| Error::::DontHaveEnoughToPay)?; + // Calculate the transaction fee + let taker_fee_rate = Self::get_transaction_fee_rate().1; + let taker_fee = taker_fee_rate.mul_floor(price_to_pay); + + // Check the balance of order taker + match order_info.order_type { + OrderType::Buy => { + // transaction amount + T::MultiCurrency::ensure_can_withdraw( + token_to_pay, + &order_taker, + amount_to_pay, + ) + .map_err(|_| Error::::DontHaveEnoughToPay)?; + + // fee + T::MultiCurrency::ensure_can_withdraw( + T::InvoicingCurrency::get(), + &order_taker, + taker_fee, + ) + .map_err(|_| Error::::DontHaveEnoughToPay)?; + }, + OrderType::Sell => { + // transaction amount + fee + T::MultiCurrency::ensure_can_withdraw( + token_to_pay, + &order_taker, + amount_to_pay.saturating_add(taker_fee), + ) + .map_err(|_| Error::::DontHaveEnoughToPay)?; + }, + }; // Get the new OrderInfo let new_order_info = OrderInfo { @@ -412,28 +506,61 @@ pub mod pallet { ..order_info }; - // Unreserve the balance - let reserved_balance = - T::MultiCurrency::reserved_balance(token_owner, &new_order_info.owner); - ensure!(reserved_balance >= amount_owner, Error::::NotEnoughBalanceToUnreserve); - T::MultiCurrency::unreserve(token_owner, &new_order_info.owner, amount_owner); + let module_account: AccountIdOf = T::PalletId::get().into_account(); + + let mut account_to_send = new_order_info.owner.clone(); + let ed = T::MultiCurrency::minimum_balance(token_to_pay.clone()); + + // deal with account exisitence error we might encounter + if amount_to_pay < ed { + let receiver_balance = + T::MultiCurrency::total_balance(token_to_pay, &new_order_info.owner); + + if receiver_balance.saturating_add(amount_to_pay) < ed { + account_to_send = T::TreasuryAccount::get(); + } + } - // Exchange: Transfer assets to opponent + // Exchange: Transfer corresponding token amount to the order maker from order taker T::MultiCurrency::transfer( - token_owner, - &new_order_info.owner, - &opponent, - amount_owner, + token_to_pay, + &order_taker, + &account_to_send, + amount_to_pay, )?; - // Exchange: Transfer assets to owner + + // Charge fee T::MultiCurrency::transfer( - token_opponent, - &opponent, - &new_order_info.owner, - amount_opponent, + T::InvoicingCurrency::get(), + &order_taker, + &T::TreasuryAccount::get(), + taker_fee, + )?; + + let mut account_to_send = order_taker.clone(); + let ed = T::MultiCurrency::minimum_balance(token_to_get.clone()); + + // deal with account exisitence error we might encounter + if amount_to_get < ed { + let receiver_balance = T::MultiCurrency::total_balance(token_to_get, &order_taker); + + if receiver_balance.saturating_add(amount_to_get) < ed { + account_to_send = T::TreasuryAccount::get(); + } + } + + // Transfer corresponding token amount to the order taker from the module account + T::MultiCurrency::transfer( + token_to_get, + &module_account, + &account_to_send, + amount_to_get, )?; // Change the OrderInfo in Storage + // The seller sells out what he want to sell in the case of sell-order type. + // Or the buyer get all the tokens he wants to buy in the case of buy-order type, + // but the buyer might still have some unspent fund due to small number round-up. if new_order_info.remain == Zero::zero() { TotalOrderInfos::::remove(order_id); Self::try_to_remove_order_id( @@ -443,11 +570,12 @@ pub mod pallet { ); if new_order_info.order_type == OrderType::Buy { - T::MultiCurrency::unreserve( - token_owner, + T::MultiCurrency::transfer( + token_to_get, + &module_account, &new_order_info.owner, new_order_info.remain_price, - ); + )?; } } else { TotalOrderInfos::::insert(order_id, new_order_info.clone()); @@ -457,7 +585,7 @@ pub mod pallet { order_id, new_order_info.order_type, new_order_info.owner, - opponent, + order_taker, new_order_info.vsbond, quantity_clinchd, new_order_info.amount, @@ -467,6 +595,32 @@ pub mod pallet { Ok(().into()) } + + // edit token release start and end block + // input number used as perthousand rate, so it should be less or equal than 1000. + #[transactional] + #[pallet::weight(T::WeightInfo::set_buy_and_sell_transaction_fee_rate())] + pub fn set_buy_and_sell_transaction_fee_rate( + origin: OriginFor, + buy_rate: u32, + sell_rate: u32, + ) -> DispatchResult { + // Check origin + T::ControlOrigin::ensure_origin(origin)?; + + // number input should be less than 10_000, since it is used as x * 1/10_000 + ensure!(buy_rate <= 10_000u32, Error::::InvalidRateInput); + ensure!(sell_rate <= 10_000u32, Error::::InvalidRateInput); + + let buy_fee_rate = Permill::from_parts(buy_rate.saturating_mul(100)); + let sell_fee_rate = Permill::from_parts(sell_rate.saturating_mul(100)); + + TransactionFee::::mutate(|fee| *fee = (buy_fee_rate, sell_fee_rate)); + + Self::deposit_event(Event::TransactionFeeRateSet(buy_fee_rate, sell_fee_rate)); + + Ok(()) + } } impl, I: 'static> Pallet { @@ -500,6 +654,54 @@ pub mod pallet { BalanceOf::::saturated_from(total_price) } + + pub(crate) fn do_order_revoke(order_id: OrderId) -> DispatchResultWithPostInfo { + // Check OrderInfo + let order_info = Self::order_info(order_id).ok_or(Error::::NotFindOrderInfo)?; + + let (token_to_return, amount_to_return) = match order_info.order_type { + OrderType::Buy => (T::InvoicingCurrency::get(), order_info.remain_price), + OrderType::Sell => (order_info.vsbond, order_info.remain), + }; + + let mut account_to_return = order_info.owner.clone(); + let ed = T::MultiCurrency::minimum_balance(token_to_return.clone()); + + // deal with account exisitence error we might encounter + if amount_to_return < ed { + let receiver_balance = + T::MultiCurrency::total_balance(token_to_return, &order_info.owner); + + if receiver_balance.saturating_add(amount_to_return) < ed { + account_to_return = T::TreasuryAccount::get(); + } + } + + // To transfer back the unused amount + let module_account: AccountIdOf = T::PalletId::get().into_account(); + T::MultiCurrency::transfer( + token_to_return, + &module_account, + &account_to_return, + amount_to_return, + )?; + + // Revoke order + TotalOrderInfos::::remove(order_id); + Self::try_to_remove_order_id(order_info.owner.clone(), order_info.order_type, order_id); + + Self::deposit_event(Event::OrderRevoked( + order_id, + order_info.order_type, + order_info.owner, + order_info.vsbond, + order_info.amount, + order_info.remain, + order_info.total_price, + )); + + Ok(().into()) + } } } diff --git a/pallets/vsbond-auction/src/migration.rs b/pallets/vsbond-auction/src/migration.rs new file mode 100644 index 0000000000..b380c2c2f5 --- /dev/null +++ b/pallets/vsbond-auction/src/migration.rs @@ -0,0 +1,88 @@ +// This file is part of Bifrost. + +// Copyright (C) 2019-2021 Liebi Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// Ensure we're `no_std` when compiling for Wasm. +#![cfg_attr(not(feature = "std"), no_std)] + +use super::*; +use crate::{Pallet, TotalOrderInfos}; + +pub fn migrate_orders, I: 'static>() -> Weight { + // get current orders in list + let order_iter = TotalOrderInfos::::iter(); + let mut ok_count = 0; + let mut err_count = 0; + + for (order_id, order_info) in order_iter { + let owner = order_info.owner; + let order_type = order_info.order_type; + let vsbond = order_info.vsbond; + let token = T::InvoicingCurrency::get(); + + let (token_to_transfer, amount_to_transfer) = match order_type { + OrderType::Buy => (token, order_info.remain_price), + OrderType::Sell => (vsbond, order_info.remain), + }; + + let total = T::MultiCurrency::total_balance(token_to_transfer, &owner); + let free = T::MultiCurrency::free_balance(token_to_transfer, &owner); + let reserved = total - free; + + let module_account: AccountIdOf = T::PalletId::get().into_account(); + + if reserved >= amount_to_transfer { + ok_count += 1; + // unreserved and then transfer + T::MultiCurrency::unreserve(token_to_transfer, &owner, amount_to_transfer); + let _ = T::MultiCurrency::transfer( + token_to_transfer, + &owner, + &module_account, + amount_to_transfer, + ); + } else if total >= amount_to_transfer { + ok_count += 1; + // make free all the reserved balance and then transfer + T::MultiCurrency::unreserve(token_to_transfer, &owner, reserved); + let _ = T::MultiCurrency::transfer( + token_to_transfer, + &owner, + &module_account, + amount_to_transfer, + ); + } else { + err_count += 1; + TotalOrderInfos::::remove(order_id); + Pallet::::try_to_remove_order_id(owner, order_type, order_id); + log::info!( + "Order {:?} is removed, transfer amount is: {:?}, account balance is: {:?}", + order_id, + amount_to_transfer, + total + ); + } + } + + // one storage read + two account balance changes + let ok_weight = + ok_count.saturating_mul(T::DbWeight::get().reads(1) + T::DbWeight::get().writes(2)); + let err_weight = + err_count.saturating_mul(T::DbWeight::get().reads(1) + T::WeightInfo::revoke_order()); + + ok_weight + err_weight +} diff --git a/pallets/vsbond-auction/src/mock.rs b/pallets/vsbond-auction/src/mock.rs index d69c0a1d8f..f92449577c 100644 --- a/pallets/vsbond-auction/src/mock.rs +++ b/pallets/vsbond-auction/src/mock.rs @@ -19,14 +19,16 @@ #[cfg(feature = "runtime-benchmarks")] use frame_benchmarking::{account, whitelisted_caller}; use frame_support::{ - construct_runtime, parameter_types, - traits::{GenesisBuild, Nothing}, + construct_runtime, ord_parameter_types, parameter_types, + traits::{Contains, GenesisBuild}, + PalletId, }; +use frame_system::EnsureSignedBy; use node_primitives::{Amount, Balance, CurrencyId, TokenSymbol}; use sp_core::H256; use sp_runtime::{ generic, - traits::{BlakeTwo256, IdentityLookup}, + traits::{AccountIdConversion, BlakeTwo256, IdentityLookup}, }; use crate as vsbond_auction; @@ -82,10 +84,18 @@ impl frame_system::Config for Test { orml_traits::parameter_type_with_key! { pub ExistentialDeposits: |_currency_id: CurrencyId| -> Balance { - 0 + 10 }; } +pub struct DustRemovalWhitelist; +impl Contains for DustRemovalWhitelist { + fn contains(a: &AccountId) -> bool { + BifrostTreasuryAccount::get().eq(a) || + AccountIdConversion::::into_account(&VsbondAuctionPalletId::get()).eq(a) + } +} + parameter_types! { pub const MaxLocks: u32 = 999; } @@ -94,7 +104,7 @@ impl orml_tokens::Config for Test { type Amount = Amount; type Balance = Balance; type CurrencyId = CurrencyId; - type DustRemovalWhitelist = Nothing; + type DustRemovalWhitelist = DustRemovalWhitelist; type Event = Event; type ExistentialDeposits = ExistentialDeposits; type MaxLocks = MaxLocks; @@ -106,6 +116,12 @@ parameter_types! { pub const InvoicingCurrency: CurrencyId = CurrencyId::Token(TokenSymbol::KSM); pub const MaximumOrderInTrade: u32 = 5; pub const MinimumSupply: Balance = 0; + pub const VsbondAuctionPalletId: PalletId = PalletId(*b"bf/vsbnd"); + pub BifrostTreasuryAccount: AccountId = PalletId(*b"bf/trsry").into_account(); +} + +ord_parameter_types! { + pub const One: AccountId = 1; } impl vsbond_auction::Config for Test { @@ -115,6 +131,9 @@ impl vsbond_auction::Config for Test { type MinimumAmount = MinimumSupply; type MultiCurrency = orml_tokens::Pallet; type WeightInfo = (); + type PalletId = VsbondAuctionPalletId; + type TreasuryAccount = BifrostTreasuryAccount; + type ControlOrigin = EnsureSignedBy; } // mockup runtime @@ -131,8 +150,10 @@ pub(crate) fn new_test_ext() -> sp_io::TestExternalities { (ALICE, VSBOND, 100), (BRUCE, TOKEN, 100), (BRUCE, VSBOND, 100), + (CHARLIE, TOKEN, 100), (ALICE, SPECIAL_VSBOND, 100), (BRUCE, SPECIAL_VSBOND, 100), + (DAVE, VSBOND, 100), #[cfg(feature = "runtime-benchmarks")] (whitelist_caller.clone(), TOKEN, 100_000_000_000_000), #[cfg(feature = "runtime-benchmarks")] @@ -151,6 +172,8 @@ pub(crate) fn new_test_ext() -> sp_io::TestExternalities { pub(crate) const ALICE: AccountId = 1; pub(crate) const BRUCE: AccountId = 2; +pub(crate) const CHARLIE: AccountId = 3; +pub(crate) const DAVE: AccountId = 4; pub(crate) const TOKEN: CurrencyId = InvoicingCurrency::get(); pub(crate) const TOKEN_SYMBOL: TokenSymbol = TokenSymbol::KSM; pub(crate) const VSBOND: CurrencyId = CurrencyId::VSBond(TOKEN_SYMBOL, 3000, 13, 20); diff --git a/pallets/vsbond-auction/src/tests.rs b/pallets/vsbond-auction/src/tests.rs index e696a14ec0..3ab7c4fa93 100644 --- a/pallets/vsbond-auction/src/tests.rs +++ b/pallets/vsbond-auction/src/tests.rs @@ -16,7 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use frame_support::{assert_noop, assert_ok, dispatch::DispatchError, traits::BalanceStatus}; +use frame_support::{assert_noop, assert_ok, dispatch::DispatchError}; use orml_traits::{LockIdentifier, MultiLockableCurrency}; use crate::{mock::*, *}; @@ -44,7 +44,9 @@ fn create_sell_order_should_work() { assert_eq!(Tokens::accounts(ALICE, VSBOND).free, 0); assert_eq!(Tokens::accounts(ALICE, VSBOND).frozen, 0); - assert_eq!(Tokens::accounts(ALICE, VSBOND).reserved, 100); + + let module_account: u64 = ::PalletId::get().into_account(); + assert_eq!(Tokens::accounts(module_account, VSBOND).free, 100); }); } @@ -67,11 +69,13 @@ fn create_buy_order_should_work() { let user_order_ids = Auction::user_order_ids(ALICE, OrderType::Buy); assert!(user_order_ids.contains(&0)); + let module_account: u64 = ::PalletId::get().into_account(); + assert!(Auction::order_info(&0).is_some()); assert_eq!(Tokens::accounts(ALICE, TOKEN).free, 0); assert_eq!(Tokens::accounts(ALICE, TOKEN).frozen, 0); - assert_eq!(Tokens::accounts(ALICE, TOKEN).reserved, 100); + assert_eq!(Tokens::accounts(module_account, TOKEN).free, 100); }); } @@ -109,12 +113,14 @@ fn double_create_order_should_work() { assert!(Auction::order_info(&0).is_some()); assert!(Auction::order_info(&1).is_some()); + let module_account: u64 = ::PalletId::get().into_account(); + assert_eq!(Tokens::accounts(ALICE, VSBOND).free, 50); assert_eq!(Tokens::accounts(ALICE, VSBOND).frozen, 0); - assert_eq!(Tokens::accounts(ALICE, VSBOND).reserved, 50); + assert_eq!(Tokens::accounts(module_account, VSBOND).free, 50); assert_eq!(Tokens::accounts(ALICE, TOKEN).free, 50); assert_eq!(Tokens::accounts(ALICE, TOKEN).frozen, 0); - assert_eq!(Tokens::accounts(ALICE, TOKEN).reserved, 50); + assert_eq!(Tokens::accounts(module_account, TOKEN).free, 50); }); } @@ -197,7 +203,7 @@ fn create_order_without_enough_to_reserve_should_fail() { 1000, OrderType::Sell ), - Error::::NotEnoughBalanceToReserve, + Error::::NotEnoughBalanceToCreateOrder, ); const LOCK_ID_SELL: LockIdentifier = 0u64.to_be_bytes(); @@ -213,7 +219,7 @@ fn create_order_without_enough_to_reserve_should_fail() { 51, OrderType::Sell ), - Error::::NotEnoughBalanceToReserve, + Error::::NotEnoughBalanceToCreateOrder, ); assert_noop!( @@ -227,7 +233,7 @@ fn create_order_without_enough_to_reserve_should_fail() { 1000, OrderType::Buy ), - Error::::NotEnoughBalanceToReserve, + Error::::NotEnoughBalanceToCreateOrder, ); const LOCK_ID_BUY: LockIdentifier = 1u64.to_be_bytes(); @@ -243,7 +249,7 @@ fn create_order_without_enough_to_reserve_should_fail() { 51, OrderType::Buy ), - Error::::NotEnoughBalanceToReserve, + Error::::NotEnoughBalanceToCreateOrder, ); }); } @@ -351,6 +357,39 @@ fn revoke_order_should_work() { }); } +#[test] +fn revoke_order_should_work_with_ed_limits() { + new_test_ext().execute_with(|| { + assert_ok!(Auction::create_order( + Some(DAVE).into(), + 3000, + TOKEN_SYMBOL, + 13, + 20, + 100, + 100, + OrderType::Sell + )); + + assert_ok!(Auction::partial_clinch_order(Some(CHARLIE).into(), 0, 96)); + assert_ok!(Auction::revoke_order(Some(DAVE).into(), 0)); + + let module_account: u64 = ::PalletId::get().into_account(); + let treasury_account: u64 = ::TreasuryAccount::get(); + + assert_eq!(Tokens::accounts(DAVE, VSBOND).free, 0); + assert_eq!(Tokens::accounts(CHARLIE, VSBOND).free, 96); + assert_eq!(Tokens::accounts(module_account, VSBOND).free, 0); + assert_eq!(Tokens::accounts(treasury_account, VSBOND).free, 4); + + assert_eq!(Tokens::accounts(DAVE, TOKEN).free, 96); + assert_eq!(Tokens::accounts(module_account, TOKEN).free, 0); + // We didn't config OnDust filed for orml_tokens module, so dust will not be removed. + assert_eq!(Tokens::accounts(CHARLIE, TOKEN).free, 4); + assert_eq!(Tokens::accounts(treasury_account, TOKEN).free, 0); + }); +} + #[test] fn revoke_sell_order_which_be_partial_clinchd_should_work() { new_test_ext().execute_with(|| { @@ -441,7 +480,7 @@ fn revoke_order_not_exist_should_fail() { } #[test] -fn revoke_order_without_enough_reserved_should_fail() { +fn revoke_order_by_origin_illegal_should_fail() { new_test_ext().execute_with(|| { assert_ok!(Auction::create_order( Some(ALICE).into(), @@ -464,64 +503,55 @@ fn revoke_order_without_enough_reserved_should_fail() { OrderType::Buy )); - assert_ok!(Tokens::repatriate_reserved( - VSBOND, - &ALICE, - &BRUCE, - 25, - BalanceStatus::Reserved - )); - assert_ok!(Tokens::repatriate_reserved(TOKEN, &ALICE, &BRUCE, 25, BalanceStatus::Reserved)); - assert_noop!( - Auction::revoke_order(Some(ALICE).into(), 0), - Error::::NotEnoughBalanceToUnreserve + Auction::revoke_order(Some(BRUCE).into(), 0), + Error::::ForbidRevokeOrderWithoutOwnership ); assert_noop!( - Auction::revoke_order(Some(ALICE).into(), 1), - Error::::NotEnoughBalanceToUnreserve + Auction::revoke_order(Some(BRUCE).into(), 1), + Error::::ForbidRevokeOrderWithoutOwnership ); + + assert_noop!(Auction::revoke_order(Origin::root(), 0), DispatchError::BadOrigin); + assert_noop!(Auction::revoke_order(Origin::root(), 1), DispatchError::BadOrigin); + + assert_noop!(Auction::revoke_order(Origin::none(), 0), DispatchError::BadOrigin); + assert_noop!(Auction::revoke_order(Origin::none(), 1), DispatchError::BadOrigin); }); } #[test] -fn revoke_order_by_origin_illegal_should_fail() { +fn partial_clinch_sell_order_should_work_with_ed_limits() { new_test_ext().execute_with(|| { assert_ok!(Auction::create_order( - Some(ALICE).into(), + Some(DAVE).into(), 3000, TOKEN_SYMBOL, 13, 20, - 50, - 50, + 100, + 33, OrderType::Sell )); - assert_ok!(Auction::create_order( - Some(ALICE).into(), - 3000, - TOKEN_SYMBOL, - 13, - 20, - 50, - 50, - OrderType::Buy - )); + assert_ok!(Auction::partial_clinch_order(Some(CHARLIE).into(), 0, 4)); - assert_noop!( - Auction::revoke_order(Some(BRUCE).into(), 0), - Error::::ForbidRevokeOrderWithoutOwnership - ); - assert_noop!( - Auction::revoke_order(Some(BRUCE).into(), 1), - Error::::ForbidRevokeOrderWithoutOwnership - ); + let order_info = Auction::order_info(0).unwrap(); + assert_eq!(order_info.remain, 96); - assert_noop!(Auction::revoke_order(Origin::root(), 0), DispatchError::BadOrigin); - assert_noop!(Auction::revoke_order(Origin::root(), 1), DispatchError::BadOrigin); + let module_account: u64 = ::PalletId::get().into_account(); + let treasury_account: u64 = ::TreasuryAccount::get(); - assert_noop!(Auction::revoke_order(Origin::none(), 0), DispatchError::BadOrigin); - assert_noop!(Auction::revoke_order(Origin::none(), 1), DispatchError::BadOrigin); + assert_eq!(Tokens::accounts(DAVE, VSBOND).free, 0); + assert_eq!(Tokens::accounts(module_account, VSBOND).free, 96); + + assert_eq!(Tokens::accounts(DAVE, TOKEN).free, 0); + assert_eq!(Tokens::accounts(treasury_account, TOKEN).free, 1); + + assert_eq!(Tokens::accounts(CHARLIE, VSBOND).free, 0); + assert_eq!(Tokens::accounts(treasury_account, VSBOND).free, 4); + + assert_eq!(Tokens::accounts(CHARLIE, TOKEN).free, 99); + assert_eq!(Tokens::accounts(module_account, TOKEN).free, 0); }); } @@ -548,21 +578,23 @@ fn partial_clinch_sell_order_should_work() { let order_info = Auction::order_info(0).unwrap(); assert_eq!(order_info.remain, 67); + let module_account: u64 = ::PalletId::get().into_account(); + assert_eq!(Tokens::accounts(ALICE, VSBOND).free, 0); assert_eq!(Tokens::accounts(ALICE, VSBOND).frozen, 0); - assert_eq!(Tokens::accounts(ALICE, VSBOND).reserved, 67); + assert_eq!(Tokens::accounts(module_account, VSBOND).free, 67); assert_eq!(Tokens::accounts(ALICE, TOKEN).free, 110); assert_eq!(Tokens::accounts(ALICE, TOKEN).frozen, 0); - assert_eq!(Tokens::accounts(ALICE, TOKEN).reserved, 0); + assert_eq!(Tokens::accounts(module_account, TOKEN).free, 0); assert_eq!(Tokens::accounts(BRUCE, VSBOND).free, 133); assert_eq!(Tokens::accounts(BRUCE, VSBOND).frozen, 0); - assert_eq!(Tokens::accounts(BRUCE, VSBOND).reserved, 0); + assert_eq!(Tokens::accounts(module_account, VSBOND).free, 67); assert_eq!(Tokens::accounts(BRUCE, TOKEN).free, 90); assert_eq!(Tokens::accounts(BRUCE, TOKEN).frozen, 0); - assert_eq!(Tokens::accounts(BRUCE, TOKEN).reserved, 0); + assert_eq!(Tokens::accounts(module_account, TOKEN).free, 0); assert_ok!(Auction::partial_clinch_order(Some(BRUCE).into(), 0, 9999999)); @@ -612,21 +644,23 @@ fn partial_clinch_buy_order_should_work() { let order_info = Auction::order_info(0).unwrap(); assert_eq!(order_info.remain, 67); + let module_account: u64 = ::PalletId::get().into_account(); + assert_eq!(Tokens::accounts(ALICE, VSBOND).free, 133); assert_eq!(Tokens::accounts(ALICE, VSBOND).frozen, 0); - assert_eq!(Tokens::accounts(ALICE, VSBOND).reserved, 0); + assert_eq!(Tokens::accounts(module_account, VSBOND).free, 0); assert_eq!(Tokens::accounts(ALICE, TOKEN).free, 67); assert_eq!(Tokens::accounts(ALICE, TOKEN).frozen, 0); - assert_eq!(Tokens::accounts(ALICE, TOKEN).reserved, 23); + assert_eq!(Tokens::accounts(module_account, TOKEN).free, 23); assert_eq!(Tokens::accounts(BRUCE, VSBOND).free, 67); assert_eq!(Tokens::accounts(BRUCE, VSBOND).frozen, 0); - assert_eq!(Tokens::accounts(BRUCE, VSBOND).reserved, 0); + assert_eq!(Tokens::accounts(module_account, VSBOND).free, 0); assert_eq!(Tokens::accounts(BRUCE, TOKEN).free, 110); assert_eq!(Tokens::accounts(BRUCE, TOKEN).frozen, 0); - assert_eq!(Tokens::accounts(BRUCE, TOKEN).reserved, 0); + assert_eq!(Tokens::accounts(module_account, TOKEN).free, 23); assert_ok!(Auction::partial_clinch_order(Some(BRUCE).into(), 0, 9999999)); @@ -741,21 +775,23 @@ fn handle_special_vsbond_sell_order_should_work() { let order_info = Auction::order_info(0).unwrap(); assert_eq!(order_info.remain, 67); + let module_account: u64 = ::PalletId::get().into_account(); + assert_eq!(Tokens::accounts(ALICE, SPECIAL_VSBOND).free, 0); assert_eq!(Tokens::accounts(ALICE, SPECIAL_VSBOND).frozen, 0); - assert_eq!(Tokens::accounts(ALICE, SPECIAL_VSBOND).reserved, 67); + assert_eq!(Tokens::accounts(module_account, SPECIAL_VSBOND).free, 67); assert_eq!(Tokens::accounts(ALICE, TOKEN).free, 110); assert_eq!(Tokens::accounts(ALICE, TOKEN).frozen, 0); - assert_eq!(Tokens::accounts(ALICE, TOKEN).reserved, 0); + assert_eq!(Tokens::accounts(module_account, TOKEN).free, 0); assert_eq!(Tokens::accounts(BRUCE, SPECIAL_VSBOND).free, 133); assert_eq!(Tokens::accounts(BRUCE, SPECIAL_VSBOND).frozen, 0); - assert_eq!(Tokens::accounts(BRUCE, SPECIAL_VSBOND).reserved, 0); + assert_eq!(Tokens::accounts(module_account, SPECIAL_VSBOND).free, 67); assert_eq!(Tokens::accounts(BRUCE, TOKEN).free, 90); assert_eq!(Tokens::accounts(BRUCE, TOKEN).frozen, 0); - assert_eq!(Tokens::accounts(BRUCE, TOKEN).reserved, 0); + assert_eq!(Tokens::accounts(module_account, TOKEN).free, 0); assert_ok!(Auction::partial_clinch_order(Some(BRUCE).into(), 0, 9999999)); @@ -766,19 +802,19 @@ fn handle_special_vsbond_sell_order_should_work() { assert_eq!(Tokens::accounts(ALICE, SPECIAL_VSBOND).free, 0); assert_eq!(Tokens::accounts(ALICE, SPECIAL_VSBOND).frozen, 0); - assert_eq!(Tokens::accounts(ALICE, SPECIAL_VSBOND).reserved, 0); + assert_eq!(Tokens::accounts(module_account, SPECIAL_VSBOND).free, 0); assert_eq!(Tokens::accounts(ALICE, TOKEN).free, 132); assert_eq!(Tokens::accounts(ALICE, TOKEN).frozen, 0); - assert_eq!(Tokens::accounts(ALICE, TOKEN).reserved, 0); + assert_eq!(Tokens::accounts(module_account, TOKEN).free, 0); assert_eq!(Tokens::accounts(BRUCE, SPECIAL_VSBOND).free, 200); assert_eq!(Tokens::accounts(BRUCE, SPECIAL_VSBOND).frozen, 0); - assert_eq!(Tokens::accounts(BRUCE, SPECIAL_VSBOND).reserved, 0); + assert_eq!(Tokens::accounts(module_account, SPECIAL_VSBOND).free, 0); assert_eq!(Tokens::accounts(BRUCE, TOKEN).free, 68); assert_eq!(Tokens::accounts(BRUCE, TOKEN).frozen, 0); - assert_eq!(Tokens::accounts(BRUCE, TOKEN).reserved, 0); + assert_eq!(Tokens::accounts(module_account, TOKEN).free, 0); }); } @@ -805,21 +841,23 @@ fn handle_special_vsbond_buy_order_should_work() { let order_info = Auction::order_info(0).unwrap(); assert_eq!(order_info.remain, 67); + let module_account: u64 = ::PalletId::get().into_account(); + assert_eq!(Tokens::accounts(ALICE, SPECIAL_VSBOND).free, 133); assert_eq!(Tokens::accounts(ALICE, SPECIAL_VSBOND).frozen, 0); - assert_eq!(Tokens::accounts(ALICE, SPECIAL_VSBOND).reserved, 0); + assert_eq!(Tokens::accounts(module_account, SPECIAL_VSBOND).free, 0); assert_eq!(Tokens::accounts(ALICE, TOKEN).free, 67); assert_eq!(Tokens::accounts(ALICE, TOKEN).frozen, 0); - assert_eq!(Tokens::accounts(ALICE, TOKEN).reserved, 23); + assert_eq!(Tokens::accounts(module_account, TOKEN).free, 23); assert_eq!(Tokens::accounts(BRUCE, SPECIAL_VSBOND).free, 67); assert_eq!(Tokens::accounts(BRUCE, SPECIAL_VSBOND).frozen, 0); - assert_eq!(Tokens::accounts(BRUCE, SPECIAL_VSBOND).reserved, 0); + assert_eq!(Tokens::accounts(module_account, SPECIAL_VSBOND).free, 0); assert_eq!(Tokens::accounts(BRUCE, TOKEN).free, 110); assert_eq!(Tokens::accounts(BRUCE, TOKEN).frozen, 0); - assert_eq!(Tokens::accounts(BRUCE, TOKEN).reserved, 0); + assert_eq!(Tokens::accounts(module_account, TOKEN).free, 23); assert_ok!(Auction::partial_clinch_order(Some(BRUCE).into(), 0, 9999999)); @@ -846,6 +884,62 @@ fn handle_special_vsbond_buy_order_should_work() { }); } +#[test] +fn set_buy_and_sell_transaction_fee_rate_should_work() { + new_test_ext().execute_with(|| { + // both buy and see rate are 10%. + assert_ok!(Auction::set_buy_and_sell_transaction_fee_rate(Some(ALICE).into(), 1000, 1000)); + + assert_eq!( + Auction::get_transaction_fee_rate(), + (Permill::from_percent(10), Permill::from_percent(10)) + ); + + assert_ok!(Auction::create_order( + Some(ALICE).into(), + 3000, + TOKEN_SYMBOL, + 13, + 20, + 80, + 80, + OrderType::Sell + )); + + assert_eq!(Tokens::accounts(ALICE, VSBOND).free, 20); + // 8 token fee is charged + assert_eq!(Tokens::accounts(ALICE, TOKEN).free, 92); + + let module_account: u64 = ::PalletId::get().into_account(); + assert_eq!(Tokens::accounts(module_account, VSBOND).free, 80); + + let treasury_account: u64 = ::TreasuryAccount::get(); + assert_eq!(Tokens::accounts(treasury_account, TOKEN).free, 8); + + assert_ok!(Auction::create_order( + Some(BRUCE).into(), + 3000, + TOKEN_SYMBOL, + 13, + 20, + 80, + 80, + OrderType::Buy + )); + + assert_eq!(Tokens::accounts(BRUCE, VSBOND).free, 100); + // 8 token fee is charged + 80 total price + assert_eq!(Tokens::accounts(BRUCE, TOKEN).free, 12); + + let module_account: u64 = ::PalletId::get().into_account(); + assert_eq!(Tokens::accounts(module_account, VSBOND).free, 80); + assert_eq!(Tokens::accounts(module_account, TOKEN).free, 80); + + let treasury_account: u64 = ::TreasuryAccount::get(); + assert_eq!(Tokens::accounts(treasury_account, TOKEN).free, 8 + 8); + }); +} + // Test Utilities #[test] fn check_price_to_pay() { diff --git a/pallets/vsbond-auction/src/weights.rs b/pallets/vsbond-auction/src/weights.rs index 28390fc0a5..1f515608cd 100644 --- a/pallets/vsbond-auction/src/weights.rs +++ b/pallets/vsbond-auction/src/weights.rs @@ -31,6 +31,7 @@ pub trait WeightInfo { fn revoke_order() -> Weight; fn clinch_order() -> Weight; fn partial_clinch_order() -> Weight; + fn set_buy_and_sell_transaction_fee_rate() -> Weight; } // For backwards compatibility and tests @@ -50,4 +51,8 @@ impl WeightInfo for () { fn partial_clinch_order() -> Weight { (50_000_000 as Weight) } + + fn set_buy_and_sell_transaction_fee_rate() -> Weight { + (50_000_000 as Weight) + } } diff --git a/runtime/asgard/src/lib.rs b/runtime/asgard/src/lib.rs index 820ecdff2b..582a3de9af 100644 --- a/runtime/asgard/src/lib.rs +++ b/runtime/asgard/src/lib.rs @@ -286,6 +286,7 @@ parameter_types! { pub const LiquidityMiningDOTPalletId: PalletId = PalletId(*b"bf/lmdot"); pub const LighteningRedeemPalletId: PalletId = PalletId(*b"bf/ltnrd"); pub const MerkleDirtributorPalletId: PalletId = PalletId(*b"bf/mklds"); + pub const VsbondAuctionPalletId: PalletId = PalletId(*b"bf/vsbnd"); } pub fn get_all_pallet_accounts() -> Vec { @@ -293,6 +294,7 @@ pub fn get_all_pallet_accounts() -> Vec { TreasuryPalletId::get().into_account(), BifrostCrowdloanId::get().into_account(), LighteningRedeemPalletId::get().into_account(), + VsbondAuctionPalletId::get().into_account(), ] } @@ -1423,6 +1425,10 @@ impl bifrost_vsbond_auction::Config for Runtime { type MinimumAmount = MinimumSupply; type MultiCurrency = Currencies; type WeightInfo = weights::bifrost_vsbond_auction::WeightInfo; + type PalletId = VsbondAuctionPalletId; + type TreasuryAccount = BifrostTreasuryAccount; + type ControlOrigin = + EnsureOneOf; } parameter_types! { diff --git a/runtime/asgard/src/weights/bifrost_vsbond_auction.rs b/runtime/asgard/src/weights/bifrost_vsbond_auction.rs index 9e4dd467e6..54fe29a10f 100644 --- a/runtime/asgard/src/weights/bifrost_vsbond_auction.rs +++ b/runtime/asgard/src/weights/bifrost_vsbond_auction.rs @@ -65,4 +65,9 @@ impl bifrost_vsbond_auction::WeightInfo for WeightInfo< .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } + fn set_buy_and_sell_transaction_fee_rate() -> Weight { + (179_327_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) + .saturating_add(T::DbWeight::get().writes(5 as Weight)) + } } diff --git a/runtime/bifrost/src/lib.rs b/runtime/bifrost/src/lib.rs index 94e8cca553..82bf26f70d 100644 --- a/runtime/bifrost/src/lib.rs +++ b/runtime/bifrost/src/lib.rs @@ -292,6 +292,7 @@ parameter_types! { pub const LiquidityMiningDOTPalletId: PalletId = PalletId(*b"bf/lmdot"); pub const LighteningRedeemPalletId: PalletId = PalletId(*b"bf/ltnrd"); pub const MerkleDirtributorPalletId: PalletId = PalletId(*b"bf/mklds"); + pub const VsbondAuctionPalletId: PalletId = PalletId(*b"bf/vsbnd"); } impl frame_system::Config for Runtime { @@ -1145,6 +1146,7 @@ impl Contains for DustRemovalWhitelist { AccountIdConversion::::into_account(&BifrostCrowdloanId::get()).eq(a) || AccountIdConversion::::into_account(&BifrostSalpLiteCrowdloanId::get()) .eq(a) || AccountIdConversion::::into_account(&LighteningRedeemPalletId::get()) + .eq(a) || AccountIdConversion::::into_account(&VsbondAuctionPalletId::get()) .eq(a) || LiquidityMiningPalletId::get().check_sub_account::(a) || LiquidityMiningDOTPalletId::get().check_sub_account::(a) } @@ -1400,6 +1402,10 @@ impl bifrost_vsbond_auction::Config for Runtime { type MinimumAmount = MinimumSupply; type MultiCurrency = Currencies; type WeightInfo = (); + type PalletId = VsbondAuctionPalletId; + type TreasuryAccount = BifrostTreasuryAccount; + type ControlOrigin = + EnsureOneOf; } parameter_types! { @@ -1704,7 +1710,7 @@ pub type Executive = frame_executive::Executive< frame_system::ChainContext, Runtime, AllPallets, - (), + VsbondAuctionOnRuntimeUpgrade, >; impl_runtime_apis! { @@ -1987,6 +1993,52 @@ impl_runtime_apis! { } } +pub struct VsbondAuctionOnRuntimeUpgrade(PhantomData<(T, I)>); +impl, I: 'static> OnRuntimeUpgrade + for VsbondAuctionOnRuntimeUpgrade +{ + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result<(), &'static str> { + #[allow(unused_imports)] + use frame_support::{migration, Identity}; + log::info!("Bifrost `pre_upgrade`..."); + + // check the on-going order number + let order_iter = bifrost_vsbond_auction::TotalOrderInfos::::iter(); + let order_count = order_iter.count(); + log::info!("Old order count is {:?}", order_count); + + Ok(()) + } + + fn on_runtime_upgrade() -> Weight { + log::info!("Bifrost `on_runtime_upgrade`..."); + + let weight = bifrost_vsbond_auction::migration::migrate_orders::(); + + log::info!("Bifrost `on_runtime_upgrade finished`"); + + weight + + // RocksDbWeight::get().writes(1) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade() -> Result<(), &'static str> { + #[allow(unused_imports)] + use frame_support::{migration, Identity}; + log::info!("Bifrost `post_upgrade`..."); + + // check the post-upgrader remaining order number + let order_iter = bifrost_vsbond_auction::TotalOrderInfos::::iter(); + let order_count = order_iter.count(); + + log::info!("New order count is {:?}", order_count); + + Ok(()) + } +} + struct CheckInherents; impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents { diff --git a/runtime/bifrost/src/weights/bifrost_vsbond_auction.rs b/runtime/bifrost/src/weights/bifrost_vsbond_auction.rs index c86e3cbc7e..a45a120135 100644 --- a/runtime/bifrost/src/weights/bifrost_vsbond_auction.rs +++ b/runtime/bifrost/src/weights/bifrost_vsbond_auction.rs @@ -65,4 +65,9 @@ impl bifrost_vsbond_auction::WeightInfo for WeightInfo< .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } + fn set_buy_and_sell_transaction_fee_rate() -> Weight { + (179_327_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) + .saturating_add(T::DbWeight::get().writes(5 as Weight)) + } }