Skip to content

Commit

Permalink
Update lib.rs
Browse files Browse the repository at this point in the history
  • Loading branch information
JuaniRios committed Sep 20, 2024
1 parent 7675e65 commit 70655e3
Show file tree
Hide file tree
Showing 12 changed files with 124 additions and 83 deletions.
3 changes: 1 addition & 2 deletions integration-tests/src/tests/defaults.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ use pallet_funding::{
use sp_arithmetic::{FixedPointNumber, Percent};

use macros::generate_accounts;
use pallet_funding::traits::ProvideAssetPrice;
use polimec_common::{USD_DECIMALS, USD_UNIT};
use polimec_common::{ProvideAssetPrice, USD_DECIMALS, USD_UNIT};
use polimec_runtime::{AccountId, PLMC};
use sp_runtime::{traits::ConstU32, Perquintill};

Expand Down
5 changes: 2 additions & 3 deletions integration-tests/src/tests/e2e.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,11 @@ use frame_support::{
};
use itertools::Itertools;
use macros::generate_accounts;
use pallet_funding::{traits::ProvideAssetPrice, *};
use polimec_common::{USD_DECIMALS, USD_UNIT};
use pallet_funding::*;
use polimec_common::{ProvideAssetPrice, USD_DECIMALS, USD_UNIT};
use sp_arithmetic::{traits::Zero, Percent, Perquintill};
use sp_runtime::{FixedPointNumber, FixedU128};
use xcm_emulator::log;

type UserToCTBalance = Vec<(AccountId, FixedU128, ProjectId)>;

generate_accounts!(
Expand Down
1 change: 0 additions & 1 deletion pallets/funding/src/functions/misc.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#[allow(clippy::wildcard_imports)]
use super::*;
use polimec_common::ProvideAssetPrice;
use sp_runtime::traits::CheckedAdd;

// Helper functions
// ATTENTION: if this is called directly, it will not be transactional
Expand Down
2 changes: 1 addition & 1 deletion pallets/funding/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ pub use pallet::*;
use pallet_xcm::ensure_response;
use polimec_common::{
credentials::{Cid, Did, EnsureOriginWithCredentials, InvestorType, UntrustedToken},
migration_types::{Migration, MigrationStatusd},
migration_types::{Migration, MigrationStatus},
};
use polkadot_parachain_primitives::primitives::Id as ParaId;
use sp_arithmetic::traits::{One, Saturating};
Expand Down
1 change: 0 additions & 1 deletion pallets/funding/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ pub const PLMC: Balance = 10u128.pow(PLMC_DECIMALS as u32);
pub const MILLI_PLMC: Balance = PLMC / 10u128.pow(3);
pub const MICRO_PLMC: Balance = PLMC / 10u128.pow(6);
pub const EXISTENTIAL_DEPOSIT: Balance = 10 * MILLI_PLMC;

pub type Block = frame_system::mocking::MockBlock<TestRuntime>;
pub type AccountId = u32;
pub type BlockNumber = u64;
Expand Down
2 changes: 1 addition & 1 deletion pallets/funding/src/runtime_api.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#[allow(clippy::wildcard_imports)]
use crate::{traits::*, *};
use crate::*;
use alloc::collections::BTreeMap;
use frame_support::traits::fungibles::{metadata::Inspect as MetadataInspect, Inspect, InspectEnumerable};
use itertools::Itertools;
Expand Down
4 changes: 0 additions & 4 deletions pallets/funding/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@
use crate::{Balance, Config, ProjectId};
use frame_support::weights::Weight;
use frame_system::pallet_prelude::BlockNumberFor;
use sp_arithmetic::{
traits::{CheckedDiv, CheckedMul},
FixedPointNumber,
};
use sp_runtime::DispatchError;

pub trait BondingRequirementCalculation {
Expand Down
34 changes: 18 additions & 16 deletions pallets/proxy-bonding/src/functions.rs
Original file line number Diff line number Diff line change
@@ -1,40 +1,42 @@
use frame_support::ensure;
use crate::{AccountIdOf, AssetId, BalanceOf, Config, Pallet, ReleaseType, Releases};
use frame_support::traits::{
fungible,
fungible::{Inspect, Mutate, MutateHold},
fungibles,
fungibles::Mutate as FungiblesMutate,
tokens::{Fortitude, Precision, Preservation},
use crate::{AccountIdOf, AssetId, BalanceOf, Config, Error, Pallet, ReleaseType, Releases};
use frame_support::{
ensure,
traits::{
fungible,
fungible::{Inspect, Mutate, MutateHold},
fungibles,
fungibles::Mutate as FungiblesMutate,
tokens::{Fortitude, Precision, Preservation},
},
};
use frame_system::pallet_prelude::BlockNumberFor;
use polimec_common::ProvideAssetPrice;
use sp_runtime::{
traits::{AccountIdConversion, Get},
FixedPointNumber,
DispatchError, FixedPointNumber,
};

impl<T: Config> Pallet<T> {
/// Calculate the USD fee in `fee_asset` for bonding `bond_amount` of the native token.
/// e.g. if the fee is 1%, native token PLMC, fee_asset USDT, bond_amount 1000 PLMC, PLMC price 0.5USD, USDT price 1USD,
/// Then the calculated fee would be 1% * 1000 * 0.5 = 5USD, which is 5 USDT at a price of 1USD.
pub fn calculate_fee(bond_amount: BalanceOf<T>, fee_asset: AssetId) -> Result<BalanceOf<T>, &'static str> {
pub fn calculate_fee(bond_amount: BalanceOf<T>, fee_asset: AssetId) -> Result<BalanceOf<T>, DispatchError> {
let bonding_token_price = T::PriceProvider::get_decimals_aware_price(
T::BondingTokenId::get(),
T::UsdDecimals::get(),
T::BondingTokenDecimals::get(),
)
.ok_or("Price not available")?;
.ok_or(Error::<T>::PriceNotAvailable)?;

let fee_asset_decimals = <T::FeeToken as fungibles::metadata::Inspect<AccountIdOf<T>>>::decimals(fee_asset);
let fee_token_price =
T::PriceProvider::get_decimals_aware_price(fee_asset, T::UsdDecimals::get(), fee_asset_decimals)
.ok_or("Price not available")?;
.ok_or(Error::<T>::PriceNotAvailable)?;

let bonded_in_usd = bonding_token_price.saturating_mul_int(bond_amount);
let fee_in_usd = T::FeePercentage::get() * bonded_in_usd;
let fee_in_fee_asset =
fee_token_price.reciprocal().ok_or("Price not available")?.saturating_mul_int(fee_in_usd);
fee_token_price.reciprocal().ok_or(Error::<T>::PriceNotAvailable)?.saturating_mul_int(fee_in_usd);

Ok(fee_in_fee_asset)
}
Expand All @@ -47,7 +49,7 @@ impl<T: Config> Pallet<T> {
bond_amount: BalanceOf<T>,
fee_asset: AssetId,
hold_reason: T::RuntimeHoldReason,
) -> Result<(), &'static str> {
) -> Result<(), DispatchError> {
let treasury = T::Treasury::get();
let bonding_account: AccountIdOf<T> = T::RootId::get().into_sub_account_truncating(derivation_path);
let existential_deposit = <T::BondingToken as fungible::Inspect<T::AccountId>>::minimum_balance();
Expand Down Expand Up @@ -99,9 +101,9 @@ impl<T: Config> Pallet<T> {
) -> Result<(), DispatchError> {
let bonding_account: AccountIdOf<T> = T::RootId::get().into_sub_account_truncating(derivation_path);
let fee_in_fee_asset = Self::calculate_fee(bond_amount, fee_asset)?;
let release_type = Releases::<T>::get(derivation_path, hold_reason).ok_or("Release type not found")?;
let release_type = Releases::<T>::get(derivation_path, hold_reason).ok_or(Error::<T>::ReleaseTypeNotSet)?;

ensure!(release_type == ReleaseType::Refunded, "Need to set this derivation path / hold reason as `Refunded`");
ensure!(release_type == ReleaseType::Refunded, Error::<T>::FeeRefundDisallowed);

// We know this fee token account is existing thanks to the provider reference of the ED of the native asset, so we can fully move all the funds.
// FYI same cannot be said of the `account`. We assume they only hold the fee token so their fee asset balance must not go below the min_balance.
Expand Down
25 changes: 19 additions & 6 deletions pallets/proxy-bonding/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,7 @@ pub mod pallet {
};
use frame_system::pallet_prelude::*;
use polimec_common::ProvideAssetPrice;
use sp_runtime::{
traits::{AccountIdConversion},
Perbill, TypeId,
};
use sp_runtime::{traits::AccountIdConversion, Perbill, TypeId};

pub type AssetId = u32;
pub type BalanceOf<T> = <<T as Config>::BondingToken as fungible::Inspect<AccountIdOf<T>>>::Balance;
Expand All @@ -56,31 +53,44 @@ pub mod pallet {
/// Because this pallet emits events, it depends on the runtime's definition of an event.
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;

/// The overarching hold reason generated by `construct_runtime`. This is used for the bonding.
type RuntimeHoldReason: IsType<HoldReasonOf<Self>> + Parameter + MaxEncodedLen;

/// The pallet giving access to the bonding token
type BondingToken: fungible::Inspect<Self::AccountId>
+ fungible::Mutate<Self::AccountId>
+ fungible::MutateHold<Self::AccountId>;

/// The number of decimals one unit of the bonding token has. Used to calculate decimal aware prices.
#[pallet::constant]
type BondingTokenDecimals: Get<u8>;

/// The number of decimals one unit of USD has. Used to calculate decimal aware prices. USD is not a real asset, but a reference point.
#[pallet::constant]
type UsdDecimals: Get<u8>;

/// The id of the bonding token. Used to get the price of the bonding token.
#[pallet::constant]
type BondingTokenId: Get<AssetId>;

/// The pallet giving access to fee-paying assets, like USDT
type FeeToken: fungibles::Inspect<Self::AccountId, Balance = BalanceOf<Self>, AssetId = AssetId>
+ fungibles::Mutate<Self::AccountId, Balance = BalanceOf<Self>, AssetId = AssetId>
+ fungibles::metadata::Inspect<Self::AccountId, Balance = BalanceOf<Self>, AssetId = AssetId>;

/// The percentage of the bonded amount in USD that will be taken as a fee in the fee asset.
#[pallet::constant]
type FeePercentage: Get<Perbill>;

/// Method to get the price of an asset like USDT or PLMC. Likely to come from an oracle
type PriceProvider: ProvideAssetPrice<AssetId = u32>;

/// The account holding the tokens to be bonded. Normally the treasury
#[pallet::constant]
type Treasury: Get<Self::AccountId>;

/// The account receiving the fees
#[pallet::constant]
type FeeRecipient: Get<Self::AccountId>;

/// The id type that can generate sub-accounts
Expand Down Expand Up @@ -125,9 +135,12 @@ pub mod pallet {
ReleaseTypeNotSet,
/// Tried to unlock the native tokens and send them back to the treasury, but the release type configured a later unlock block.
TooEarlyToUnlock,
/// The release type for the given derivation path / hold reason is set to refunded, which disallows sending fees to the recipient
/// The release type for the given derivation path / hold reason is set to `Refunded`, which disallows sending fees to the recipient
FeeToRecipientDisallowed,

/// The release type for the given derivation path / hold reason is set to `Locked`, which disallows refunding fees
FeeRefundDisallowed,
/// The price of a fee asset or the native token could not be retrieved
PriceNotAvailable,
}

#[pallet::hooks]
Expand Down
28 changes: 24 additions & 4 deletions pallets/proxy-bonding/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@ use sp_runtime::{
};
use std::{cell::RefCell, collections::BTreeMap};
pub const NATIVE_DECIMALS: u8 = 10;
pub const FEE_ASSET_DECIMALS: u8 = 6;
pub const NATIVE_UNIT: u64 = 1 * 10u64.pow(NATIVE_DECIMALS as u32);
pub const MILLI_NATIVE_UNIT: u64 = NATIVE_UNIT / 1_000;
pub const FEE_ASSET_UNIT: u64 = 1 * 10u64.pow(FEE_ASSET_DECIMALS as u32);

pub const MOCK_FEE_ASSET_ID: u32 = 1337;
pub const MOCK_FEE_ASSET_DECIMALS: u8 = 6;
pub const MOCK_FEE_ASSET_UNIT: u64 = 1 * 10u64.pow(MOCK_FEE_ASSET_DECIMALS as u32);

// Configure a mock runtime to test the pallet.
#[frame_support::runtime]
mod test_runtime {
Expand Down Expand Up @@ -165,10 +168,27 @@ impl crate::Config for TestRuntime {
type RuntimeEvent = RuntimeEvent;
type RuntimeHoldReason = MockRuntimeHoldReason;
type Treasury = Treasury;
type UsdDecimals = ConstU8<FEE_ASSET_DECIMALS>;
type UsdDecimals = ConstU8<MOCK_FEE_ASSET_DECIMALS>;
}

// Build genesis storage according to the mock runtime.
pub fn new_test_ext() -> sp_io::TestExternalities {
GenesisConfig::<TestRuntime>::default().build_storage().unwrap().into()
let mut storage = GenesisConfig::<TestRuntime>::default().build_storage().unwrap();
RuntimeGenesisConfig {
assets: AssetsConfig {
assets: vec![(MOCK_FEE_ASSET_ID, 1, true, 100)],
metadata: vec![(
MOCK_FEE_ASSET_ID,
"Tether USD".to_string().into_bytes(),
"USDT".to_string().into_bytes(),
MOCK_FEE_ASSET_DECIMALS,
)],
accounts: vec![],
},
..Default::default()
}
.assimilate_storage(&mut storage)
.unwrap();

sp_io::TestExternalities::new(storage)
}
Loading

0 comments on commit 70655e3

Please sign in to comment.