Skip to content

Commit

Permalink
feat: switch deposit currency with deposit pallet (#833)
Browse files Browse the repository at this point in the history
Co-authored-by: Adel Golghalyani <[email protected]>
  • Loading branch information
ntn-x2 and Ad96el authored Dec 12, 2024
1 parent 9bf5df3 commit 1ead23b
Show file tree
Hide file tree
Showing 12 changed files with 203 additions and 72 deletions.
26 changes: 12 additions & 14 deletions pallets/pallet-bonded-coins/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ pub trait BenchmarkHelper<T: Config> {

/// Calculate the asset id for the bonded asset.
fn calculate_bonded_asset_id(seed: u32) -> FungiblesAssetIdOf<T>;

fn set_native_balance(account: &T::AccountId, amount: u128);
}

impl<T> BenchmarkHelper<T> for ()
Expand All @@ -57,6 +59,8 @@ where
fn calculate_bonded_asset_id(seed: u32) -> FungiblesAssetIdOf<T> {
seed.into()
}

fn set_native_balance(_account: &<T>::AccountId, _amount: u128) {}
}

fn get_square_root_curve<Float: FixedSigned>() -> Curve<Float> {
Expand Down Expand Up @@ -87,13 +91,12 @@ fn get_lmsr_curve_input<Float: FixedUnsigned>() -> CurveInput<Float> {
FungiblesBalanceOf<T>: Into<U256> + TryFrom<U256>,
T::Collaterals: Create<T::AccountId> ,
T::Fungibles: InspectRoles<T::AccountId> + AccountTouch<FungiblesAssetIdOf<T>, AccountIdOf<T>>,
T::DepositCurrency: Mutate<T::AccountId>,
T::Collaterals: MutateFungibles<T::AccountId>,
AccountIdLookupOf<T>: From<T::AccountId>,
)]
mod benchmarks {
use frame_support::traits::{
fungible::{Inspect, Mutate, MutateHold},
fungible::{Inspect, MutateHold},
fungibles::{Create, Destroy, Inspect as InspectFungibles, Mutate as MutateFungibles},
AccountTouch, EnsureOrigin, Get, OriginTrait,
};
Expand All @@ -104,8 +107,7 @@ mod benchmarks {
curves::Curve,
mock::*,
types::{Locks, PoolManagingTeam, PoolStatus},
AccountIdLookupOf, AccountIdOf, CollateralAssetIdOf, CurveParameterInputOf, HoldReason, PoolDetailsOf, Pools,
TokenMetaOf,
AccountIdLookupOf, AccountIdOf, CollateralAssetIdOf, CurveParameterInputOf, PoolDetailsOf, Pools, TokenMetaOf,
};

use super::*;
Expand Down Expand Up @@ -178,21 +180,15 @@ mod benchmarks {

// native currency

fn make_free_for_deposit<T: Config>(account: &AccountIdOf<T>)
where
T::DepositCurrency: Mutate<T::AccountId>,
{
fn make_free_for_deposit<T: Config>(account: &AccountIdOf<T>) {
let balance = <T::DepositCurrency as Inspect<AccountIdOf<T>>>::minimum_balance()
+ T::BaseDeposit::get().mul(1000u32.into())
+ T::DepositPerCurrency::get().mul(T::MaxCurrenciesPerPool::get().into());
set_native_balance::<T>(account, balance.saturated_into());
}

fn set_native_balance<T: Config>(account: &AccountIdOf<T>, amount: u128)
where
T::DepositCurrency: Mutate<T::AccountId>,
{
<T::DepositCurrency as Mutate<AccountIdOf<T>>>::set_balance(account, amount.saturated_into());
fn set_native_balance<T: Config>(account: &AccountIdOf<T>, amount: u128) {
T::BenchmarkHelper::set_native_balance(account, amount.saturated_into());
let balance = <T::DepositCurrency as Inspect<AccountIdOf<T>>>::balance(account);
assert_eq!(balance, amount.saturated_into());
}
Expand Down Expand Up @@ -795,8 +791,10 @@ mod benchmarks {

make_free_for_deposit::<T>(&owner);

let hold_reason = Pallet::<T>::calculate_hold_reason(&pool_id).expect("Generating HoldReason should not fail");

T::DepositCurrency::hold(
&T::RuntimeHoldReason::from(HoldReason::Deposit),
&hold_reason,
&owner,
Pallet::<T>::calculate_pool_deposit(bonded_currencies.len()),
)
Expand Down
24 changes: 16 additions & 8 deletions pallets/pallet-bonded-coins/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,8 @@ pub mod pallet {
/// The type used for pool ids
type PoolId: Parameter + MaxEncodedLen + From<[u8; 32]> + Into<Self::AccountId>;

type RuntimeHoldReason: From<HoldReason>;
type RuntimeHoldReason: From<Self::HoldReason>;
type HoldReason: TryFrom<Self::PoolId>;

/// The type used for the curve parameters. This is the type used in the
/// calculation steps and stored in the pool details.
Expand Down Expand Up @@ -316,11 +317,6 @@ pub mod pallet {
ZeroCollateral,
}

#[pallet::composite_enum]
pub enum HoldReason {
Deposit,
}

#[pallet::call]
impl<T: Config> Pallet<T>
where
Expand Down Expand Up @@ -399,7 +395,8 @@ pub mod pallet {

let deposit_amount = Self::calculate_pool_deposit(currency_length);

T::DepositCurrency::hold(&T::RuntimeHoldReason::from(HoldReason::Deposit), &who, deposit_amount)?;
let hold_reason = Self::calculate_hold_reason(&pool_id)?;
T::DepositCurrency::hold(&hold_reason, &who, deposit_amount)?;

let pool_account = &pool_id.clone().into();

Expand Down Expand Up @@ -1280,8 +1277,9 @@ pub mod pallet {

Pools::<T>::remove(&pool_id);

let hold_reason = Self::calculate_hold_reason(&pool_id)?;
T::DepositCurrency::release(
&T::RuntimeHoldReason::from(HoldReason::Deposit),
&hold_reason,
&pool_details.owner,
pool_details.deposit,
WithdrawalPrecision::Exact,
Expand Down Expand Up @@ -1562,5 +1560,15 @@ pub mod pallet {
T::BaseDeposit::get()
.saturating_add(T::DepositPerCurrency::get().saturating_mul(n_currencies.saturated_into()))
}

/// Calculates the hold reason for a pool.
pub(crate) fn calculate_hold_reason(pool_id: &T::PoolId) -> Result<T::RuntimeHoldReason, Error<T>> {
let hold_reason = T::HoldReason::try_from(pool_id.to_owned()).map_err(|_| {
log::error!(target: LOG_TARGET, "Failed to convert pool ID into a valid hold reason.");
Error::<T>::Internal
})?;

Ok(T::RuntimeHoldReason::from(hold_reason))
}
}
}
50 changes: 44 additions & 6 deletions pallets/pallet-bonded-coins/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,22 +54,22 @@ pub mod runtime {
use frame_support::{
pallet_prelude::*,
parameter_types, storage_alias,
traits::{fungible::hold::Mutate, ConstU128, ConstU32, PalletInfoAccess},
traits::{fungible::hold::Mutate as MutateHold, ConstU128, ConstU32, PalletInfoAccess, VariantCount},
weights::constants::RocksDbWeight,
};
use frame_system::{EnsureRoot, EnsureSigned};
use sp_core::U256;
use sp_runtime::{
traits::{BlakeTwo256, IdentifyAccount, IdentityLookup, Verify},
ArithmeticError, BoundedVec, BuildStorage, DispatchError, MultiSignature, Permill,
AccountId32, ArithmeticError, BoundedVec, BuildStorage, DispatchError, MultiSignature, Permill,
};
use substrate_fixed::types::{I75F53, U75F53};

use crate::{
self as pallet_bonded_coins,
traits::NextAssetIds,
types::{Locks, PoolStatus},
Config, DepositBalanceOf, FungiblesAssetIdOf, HoldReason, PoolDetailsOf,
Config, DepositBalanceOf, FungiblesAssetIdOf, PoolDetailsOf,
};

pub type Hash = sp_core::H256;
Expand Down Expand Up @@ -200,6 +200,15 @@ pub mod runtime {
}
);

#[derive(Default, Clone, Copy, Encode, Decode, MaxEncodedLen, TypeInfo, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum TestRuntimeHoldReason {
#[default]
Deposit,
}
impl VariantCount for TestRuntimeHoldReason {
const VARIANT_COUNT: u32 = 1;
}

parameter_types! {
pub const SS58Prefix: u8 = 38;
pub const BlockHashCount: u64 = 250;
Expand Down Expand Up @@ -250,7 +259,7 @@ pub mod runtime {
type ReserveIdentifier = [u8; 8];
type RuntimeEvent = RuntimeEvent;
type RuntimeFreezeReason = ();
type RuntimeHoldReason = RuntimeHoldReason;
type RuntimeHoldReason = TestRuntimeHoldReason;
type WeightInfo = ();
}

Expand Down Expand Up @@ -288,6 +297,32 @@ pub mod runtime {
pub const MaxDenomination: u8 = 15;
}

impl From<AccountId32> for TestRuntimeHoldReason {
fn from(_value: AccountId32) -> Self {
Self::Deposit
}
}

#[cfg(feature = "runtime-benchmarks")]
struct BenchmarkHelper;

#[cfg(feature = "runtime-benchmarks")]
impl crate::BenchmarkHelper<Test> for BenchmarkHelper {
fn calculate_bonded_asset_id(seed: u32) -> FungiblesAssetIdOf<Test> {
seed
}

fn calculate_collateral_asset_id(seed: u32) -> crate::CollateralAssetIdOf<Test> {
seed
}

fn set_native_balance(who: &AccountId, amount: DepositBalanceOf<Test>) {
use frame_support::traits::fungible::Mutate;

Balances::set_balance(who, amount);
}
}

impl pallet_bonded_coins::Config for Test {
type BaseDeposit = ExistentialDeposit;
type Collaterals = Assets;
Expand All @@ -298,14 +333,15 @@ pub mod runtime {
type DepositPerCurrency = CurrencyDeposit;
type ForceOrigin = EnsureRoot<AccountId>;
type Fungibles = Assets;
type HoldReason = Self::PoolId;
type MaxCurrenciesPerPool = MaxCurrenciesPerPool;
type MaxDenomination = MaxDenomination;
type MaxStringInputLength = StringLimit;
type NextAssetIds = NextAssetIdGenerator;
type PoolCreateOrigin = EnsureSigned<AccountId>;
type PoolId = AccountId;
type RuntimeEvent = RuntimeEvent;
type RuntimeHoldReason = RuntimeHoldReason;
type RuntimeHoldReason = TestRuntimeHoldReason;
type WeightInfo = ();

#[cfg(feature = "runtime-benchmarks")]
Expand Down Expand Up @@ -400,8 +436,10 @@ pub mod runtime {
System::set_block_number(System::block_number() + 1);

self.pools.into_iter().for_each(|(pool_id, pool)| {
let hold_reason =
BondingPallet::calculate_hold_reason(&pool_id).expect("Creating hold reason should not fail.");
<Test as crate::Config>::DepositCurrency::hold(
&HoldReason::Deposit.into(),
&hold_reason,
&pool.owner,
BondingPallet::calculate_pool_deposit(pool.bonded_currencies.len()),
)
Expand Down
10 changes: 7 additions & 3 deletions pallets/pallet-bonded-coins/src/try_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use frame_support::traits::{
use sp_runtime::{traits::Zero, TryRuntimeError};
use sp_std::vec::Vec;

use crate::{types::PoolDetails, Config, FungiblesAssetIdOf, HoldReason, Pools};
use crate::{types::PoolDetails, Config, FungiblesAssetIdOf, Pools};

pub(crate) fn do_try_state<T: Config>() -> Result<(), TryRuntimeError> {
// checked currency ids. Each Currency should only be associated with one pool.
Expand All @@ -22,10 +22,14 @@ pub(crate) fn do_try_state<T: Config>() -> Result<(), TryRuntimeError> {
..
} = pool_details;

let pool_account = pool_id.into();
let pool_account = pool_id.clone().into();

let hold_reason = T::HoldReason::try_from(pool_id)
.map_err(|_| TryRuntimeError::Other("Failed to convert pool_id to HoldReason"))
.map(T::RuntimeHoldReason::from)?;

// Deposit checks
let balance_on_hold_user = T::DepositCurrency::balance_on_hold(&HoldReason::Deposit.into(), &owner);
let balance_on_hold_user = T::DepositCurrency::balance_on_hold(&hold_reason, &owner);
assert!(balance_on_hold_user >= deposit);

// Collateral checks
Expand Down
6 changes: 6 additions & 0 deletions pallets/pallet-deposit-storage/src/fungible/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ pub struct PalletDepositStorageReason<Namespace, Key> {
pub(crate) key: Key,
}

impl<Namespace, Key> PalletDepositStorageReason<Namespace, Key> {
pub const fn new(namespace: Namespace, key: Key) -> Self {
Self { namespace, key }
}
}

impl<Namespace, Key> From<PalletDepositStorageReason<Namespace, Key>> for HoldReason {
fn from(_value: PalletDepositStorageReason<Namespace, Key>) -> Self {
// All the deposits ever taken like this will count towards the same hold
Expand Down
53 changes: 53 additions & 0 deletions runtimes/common/src/deposits.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// KILT Blockchain – https://botlabs.org
// Copyright (C) 2019-2024 BOTLabs GmbH

// The KILT Blockchain 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.

// The KILT Blockchain 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/>.

// If you feel like getting in touch with us, you can do so at [email protected]

// The `RuntimeDebug` macro uses these internally.
#![allow(clippy::ref_patterns)]

use pallet_dip_provider::IdentityCommitmentVersion;
use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
use sp_core::RuntimeDebug;

use crate::DidIdentifier;

#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Eq, RuntimeDebug)]
pub enum DepositNamespace {
DipProvider,
BondedTokens,
}

#[cfg(feature = "runtime-benchmarks")]
impl Default for DepositNamespace {
fn default() -> Self {
Self::DipProvider
}
}

/// The various different keys that can be stored in the storage-tracking
/// pallet.
/// Although the namespace is used to distinguish between keys, it is useful to
/// group all keys under the same enum to calculate the maximum length that a
/// key can take.
#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Eq, RuntimeDebug)]
pub enum DepositKey {
DipProvider {
identifier: DidIdentifier,
version: IdentityCommitmentVersion,
},
}
Loading

0 comments on commit 1ead23b

Please sign in to comment.