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

optimize lend-market pallet #1468

Merged
merged 2 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 2 additions & 0 deletions pallets/lend-market/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pallet-traits = { workspace = true }
parity-scale-codec = { workspace = true, features = ["derive"] }
scale-info = { workspace = true, features = ["derive"] }
serde = { workspace = true, features = ['derive'], optional = true }
sp-core = { workspace = true }
sp-io = { workspace = true }
sp-runtime = { workspace = true }
sp-std = { workspace = true }
Expand All @@ -49,6 +50,7 @@ std = [
'frame-benchmarking/std',
'orml-traits/std',
'bifrost-primitives/std',
'sp-core/std',
'sp-runtime/std',
'sp-std/std',
'sp-io/std',
Expand Down
52 changes: 27 additions & 25 deletions pallets/lend-market/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ use pallet_traits::{
ConvertToBigUint, LendMarket as LendMarketTrait, LendMarketMarketDataProvider,
LendMarketPositionDataProvider, MarketInfo, MarketStatus,
};
use sp_core::bounded::BoundedVec;
use sp_runtime::{
traits::{
AccountIdConversion, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, One,
Expand All @@ -62,6 +63,7 @@ pub use weights::WeightInfo;
#[cfg(feature = "runtime-benchmarks")]
mod benchmarking;

pub mod migrations;
#[cfg(test)]
pub mod mock;
#[cfg(test)]
Expand All @@ -75,9 +77,6 @@ mod types;

pub mod weights;

pub const MAX_INTEREST_CALCULATING_INTERVAL: u64 = 5 * 24 * 3600; // 5 days
pub const MIN_INTEREST_CALCULATING_INTERVAL: u64 = 100; // 100 seconds

pub const MAX_EXCHANGE_RATE: u128 = 1_000_000_000_000_000_000; // 1
pub const MIN_EXCHANGE_RATE: u128 = 20_000_000_000_000_000; // 0.02

Expand All @@ -87,12 +86,6 @@ pub type AssetIdOf<T> =
pub type BalanceOf<T> =
<<T as Config>::Assets as Inspect<<T as frame_system::Config>::AccountId>>::Balance;

/// Utility type for managing upgrades/migrations.
#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)]
pub enum Versions {
V0,
}

#[frame_support::pallet]
pub mod pallet {

Expand Down Expand Up @@ -132,6 +125,9 @@ pub mod pallet {

#[pallet::constant]
type LiquidationFreeAssetId: Get<AssetIdOf<Self>>;

#[pallet::constant]
type MaxLengthLimit: Get<u32>;
}

#[pallet::error]
Expand Down Expand Up @@ -196,6 +192,8 @@ pub mod pallet {
CollateralReserved,
/// Market bond does not exist
MarketBondDoesNotExist,
/// Error converting Vec to BoundedVec.
ConversionError,
}

#[pallet::event]
Expand Down Expand Up @@ -275,7 +273,8 @@ pub mod pallet {

/// Liquidation free collateral.
#[pallet::storage]
pub type LiquidationFreeCollaterals<T: Config> = StorageValue<_, Vec<AssetIdOf<T>>, ValueQuery>;
pub type LiquidationFreeCollaterals<T: Config> =
StorageValue<_, BoundedVec<AssetIdOf<T>, T::MaxLengthLimit>, ValueQuery>;

/// Total number of collateral tokens in circulation
/// CollateralType -> Balance
Expand Down Expand Up @@ -434,21 +433,13 @@ pub mod pallet {

#[pallet::storage]
pub type MarketBond<T: Config> =
StorageMap<_, Blake2_128Concat, AssetIdOf<T>, Vec<AssetIdOf<T>>>;

/// DefaultVersion is using for initialize the StorageVersion
#[pallet::type_value]
pub(super) fn DefaultVersion() -> Versions {
Versions::V0
}
StorageMap<_, Blake2_128Concat, AssetIdOf<T>, BoundedVec<AssetIdOf<T>, T::MaxLengthLimit>>;

/// Storage version of the pallet.
#[pallet::storage]
pub(crate) type StorageVersion<T: Config> =
StorageValue<_, Versions, ValueQuery, DefaultVersion>;
const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);

#[pallet::pallet]
#[pallet::without_storage_info]
#[pallet::storage_version(STORAGE_VERSION)]
pub struct Pallet<T>(PhantomData<T>);

#[pallet::call]
Expand Down Expand Up @@ -1110,9 +1101,16 @@ pub mod pallet {
collaterals: Vec<AssetIdOf<T>>,
) -> DispatchResultWithPostInfo {
T::UpdateOrigin::ensure_origin(origin)?;
LiquidationFreeCollaterals::<T>::mutate(|liquidation_free_collaterals| {
*liquidation_free_collaterals = collaterals.clone()
});
LiquidationFreeCollaterals::<T>::try_mutate(
|liquidation_free_collaterals| -> DispatchResultWithPostInfo {
// Attempt to convert `collaterals` into a `BoundedVec` and handle potential
// conversion error
*liquidation_free_collaterals = BoundedVec::try_from(collaterals.clone())
.map_err(|_| Error::<T>::ConversionError)?;
Ok(().into())
},
)?;

Self::deposit_event(Event::<T>::LiquidationFreeCollateralsUpdated(collaterals));
Ok(().into())
}
Expand All @@ -1126,7 +1124,11 @@ pub mod pallet {
market_bond: Vec<AssetIdOf<T>>,
) -> DispatchResultWithPostInfo {
T::UpdateOrigin::ensure_origin(origin)?;
MarketBond::<T>::insert(asset_id, market_bond.clone());
MarketBond::<T>::insert(
asset_id,
BoundedVec::try_from(market_bond.clone())
.map_err(|_| Error::<T>::ConversionError)?,
);

Self::deposit_event(Event::<T>::MarketBonded { asset_id, market_bond });
Ok(().into())
Expand Down
19 changes: 19 additions & 0 deletions pallets/lend-market/src/migrations/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// This file is part of Bifrost.

// Copyright (C) Liebi Technologies PTE. 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 <https://www.gnu.org/licenses/>.

pub mod v1;
136 changes: 136 additions & 0 deletions pallets/lend-market/src/migrations/v1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// This file is part of Bifrost.

// Copyright (C) Liebi Technologies PTE. 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 <https://www.gnu.org/licenses/>.

use crate::*;
use frame_support::{
ensure,
pallet_prelude::StorageVersion,
traits::{GetStorageVersion, Len, OnRuntimeUpgrade},
};
use parity_scale_codec::{Decode, Encode};
#[cfg(feature = "try-runtime")]
use sp_runtime::TryRuntimeError;

const LOG_TARGET: &str = "lend-market::migration";

pub struct MigrateToV1<T>(sp_std::marker::PhantomData<T>);
impl<T: Config> OnRuntimeUpgrade for MigrateToV1<T> {
fn on_runtime_upgrade() -> frame_support::weights::Weight {
// Check the storage version
let onchain_version = Pallet::<T>::on_chain_storage_version();
if onchain_version < 1 {
// Transform storage values
// We transform the storage values from the old into the new format.
log::info!(target: LOG_TARGET, "Start to migrate LiquidationFreeCollateralsstorage...");
LiquidationFreeCollaterals::<T>::translate::<Vec<AssetIdOf<T>>, _>(
|maybe_value: Option<Vec<AssetIdOf<T>>>| {
let target_bounded_vec: BoundedVec<AssetIdOf<T>, T::MaxLengthLimit>;
if let Some(value) = maybe_value {
// If there's a value, try to convert Vec to BoundedVec
target_bounded_vec = BoundedVec::try_from(value).unwrap();
} else {
// If there's no value (None), set the BoundedVec to default (empty)
target_bounded_vec =
BoundedVec::<AssetIdOf<T>, T::MaxLengthLimit>::default();
}
// Return the new BoundedVec as the migrated value
Some(target_bounded_vec)
},
)
.unwrap();

log::info!(target: LOG_TARGET, "Start to migrate MarketBond storage...");
MarketBond::<T>::translate::<Vec<AssetIdOf<T>>, _>(
|k: AssetIdOf<T>, value: Vec<AssetIdOf<T>>| {
log::info!(target: LOG_TARGET, "Migrated to boundedvec for {:?}...", k);

let target_bounded_vec: BoundedVec<AssetIdOf<T>, T::MaxLengthLimit>;
if value.len() != 0 {
target_bounded_vec = BoundedVec::try_from(value).unwrap();
} else {
target_bounded_vec =
BoundedVec::<AssetIdOf<T>, T::MaxLengthLimit>::default();
}

Some(target_bounded_vec)
},
);

// Update the storage version
StorageVersion::new(1).put::<Pallet<T>>();

// Return the consumed weight
let liquidation_free_collaterals_count = 1u64;
let market_bond_count = MarketBond::<T>::iter().count();
Weight::from(T::DbWeight::get().reads_writes(
liquidation_free_collaterals_count + market_bond_count as u64 + 1,
liquidation_free_collaterals_count as u64 + market_bond_count as u64 + 1,
))
} else {
// We don't do anything here.
Weight::zero()
}
}

#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
let liquidation_free_collaterals_count = LiquidationFreeCollaterals::<T>::get().len();
let market_bond_count = MarketBond::<T>::iter().count();

// print out the pre-migrate storage count
log::info!(target: LOG_TARGET, "LiquidationFreeCollaterals pre-migrate storage count: {:?}", liquidation_free_collaterals_count);
log::info!(target: LOG_TARGET, "MarketBond pre-migrate storage count: {:?}", market_bond_count);
Ok((liquidation_free_collaterals_count as u64, market_bond_count as u64).encode())
}

#[cfg(feature = "try-runtime")]
fn post_upgrade(cnt: Vec<u8>) -> Result<(), TryRuntimeError> {
let new_liquidation_free_collaterals_count = LiquidationFreeCollaterals::<T>::get().len();
let new_market_bond_count = MarketBond::<T>::iter().count();

let (old_liquidation_free_collaterals_count, old_market_bond_count): (u64, u64) =
Decode::decode(&mut cnt.as_slice()).expect(
"the state parameter should be something that was generated by pre_upgrade",
);

// print out the post-migrate storage count
log::info!(
target: LOG_TARGET,
"LiquidationFreeCollaterals post-migrate storage count: {:?}",
new_liquidation_free_collaterals_count
);

log::info!(
target: LOG_TARGET,
"MarketBond post-migrate storage count: {:?}",
new_market_bond_count
);

ensure!(
new_liquidation_free_collaterals_count as u64 == old_liquidation_free_collaterals_count,
"LiquidationFreeCollaterals Post-migration storage count does not match pre-migration count"
);

ensure!(
new_market_bond_count as u64 == old_market_bond_count,
"MarketBond Post-migration storage count does not match pre-migration count"
);

Ok(())
}
}
2 changes: 2 additions & 0 deletions pallets/lend-market/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ impl pallet_prices::Config for Test {
parameter_types! {
pub const RewardAssetId: CurrencyId = BNC;
pub const LiquidationFreeAssetId: CurrencyId = DOT;
pub const MaxLengthLimit: u32 = 500;
}

impl Config for Test {
Expand All @@ -321,6 +322,7 @@ impl Config for Test {
type Assets = Currencies;
type RewardAssetId = RewardAssetId;
type LiquidationFreeAssetId = LiquidationFreeAssetId;
type MaxLengthLimit = MaxLengthLimit;
}

pub(crate) fn new_test_ext() -> sp_io::TestExternalities {
Expand Down
2 changes: 2 additions & 0 deletions pallets/leverage-staking/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,7 @@ impl OraclePriceProvider for MockOraclePriceProvider {
parameter_types! {
pub const RewardAssetId: CurrencyId = BNC;
pub const LiquidationFreeAssetId: CurrencyId = DOT;
pub const MaxLengthLimit: u32 = 500;
}

impl lend_market::Config for Test {
Expand All @@ -450,6 +451,7 @@ impl lend_market::Config for Test {
type Assets = Currencies;
type RewardAssetId = RewardAssetId;
type LiquidationFreeAssetId = LiquidationFreeAssetId;
type MaxLengthLimit = MaxLengthLimit;
}

impl pallet_prices::Config for Test {
Expand Down
2 changes: 2 additions & 0 deletions runtime/bifrost-kusama/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1592,6 +1592,7 @@ impl lend_market::Config for Runtime {
type Assets = Currencies;
type RewardAssetId = NativeCurrencyId;
type LiquidationFreeAssetId = RelayCurrencyId;
type MaxLengthLimit = MaxLengthLimit;
}

parameter_types! {
Expand Down Expand Up @@ -1906,6 +1907,7 @@ pub mod migrations {
frame_support::migrations::RemovePallet<SystemMakerName, RocksDbWeight>,
frame_support::migrations::RemovePallet<VSBondAuctionName, RocksDbWeight>,
bifrost_system_staking::migrations::v1::MigrateToV1<Runtime>,
lend_market::migrations::v1::MigrateToV1<Runtime>,
);
}

Expand Down
2 changes: 2 additions & 0 deletions runtime/bifrost-polkadot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1455,6 +1455,7 @@ impl lend_market::Config for Runtime {
type Assets = Currencies;
type RewardAssetId = NativeCurrencyId;
type LiquidationFreeAssetId = RelayCurrencyId;
type MaxLengthLimit = MaxLengthLimit;
}

parameter_types! {
Expand Down Expand Up @@ -1836,6 +1837,7 @@ pub mod migrations {
bifrost_slpx::migration::v2::MigrateToV2<Runtime>,
frame_support::migrations::RemovePallet<SystemMakerName, RocksDbWeight>,
bifrost_system_staking::migrations::v1::MigrateToV1<Runtime>,
lend_market::migrations::v1::MigrateToV1<Runtime>,
);
}

Expand Down