Skip to content

Commit

Permalink
Feature/apollo update collateral factor (#1302)
Browse files Browse the repository at this point in the history
* feat: setting up collateral factor and implementing it in borrow and add_collateral extrinsic

* Presto: publish Crop Receipt (#1294)

Signed-off-by: Mikhail Tagirov <[email protected]>

* Presto: fix strings (#1296)

Signed-off-by: Mikhail Tagirov <[email protected]>

* cover with wip new fee events (#1297)

* Presto: fix USA name (#1298)

Signed-off-by: Mikhail Tagirov <[email protected]>

* Prepare release 4.5.2 (#1299)

Co-authored-by: Mikhail Tagirov <[email protected]>

* Presto: benchmarks (#1300)

* benchmarks

Signed-off-by: Mikhail Tagirov <[email protected]>

* weights

Signed-off-by: Mikhail Tagirov <[email protected]>

---------

Signed-off-by: Mikhail Tagirov <[email protected]>

* fix: adjusting the default value for the collateral factor

* Presto: minor fix flag

Signed-off-by: Mikhail Tagirov <[email protected]>

* Change fee to small fee for vesting (#1304)

* change fee to small fee for vesting

* Random xor-fee remint (#1305)

* Random xor-fee remint

* Add benchmark

* Fix clippy

* Fix review issues

* Prepare release 4.5.3 (#1306)

* Prepare release 4.5.3

* Update Cargo.lock

* Benchmark results of benchmarking-4.5.3 from master (#1308)

* Fix benchmarking

* benchmarking results

Signed-off-by: sorabot <[email protected]>

* Fix benchmarks

* Fix xor-fee and demeter benchmarks

* Fix remint without wip

* benchmarking results

Signed-off-by: sorabot <[email protected]>

---------

Signed-off-by: sorabot <[email protected]>
Co-authored-by: Vladimir Stepanenko <[email protected]>

* 1171 xorless fee part 2 (#1290)

* add check for depth

* change assets in migration

* compute fee for order book and vested transfer

* update Carrgo.lock

* add set referrer

---------

Co-authored-by: Vladimir Stepanenko <[email protected]>

* aggregating total collateral amount in separate storage for easier tracking

* migrations for the new approach with total collateral amount

* test coverage of new features

* updating typos in the lib of apollo pallet

* migration update

* Test coverage for updated migration

* minor update to migrations tests in apollo platform

* Moving runtime upgrade to empty struct (MigrateToV1) with OnRuntimeUpgrade implementation

* Presto KYC (#1309)

Signed-off-by: Mikhail Tagirov <[email protected]>

* fix: typo

* fix: changing migration checks for pre and post upgrade

* Update const STORAGE_VERSION from 0 to 1

Co-authored-by: Vladimir Stepanenko <[email protected]>

* Update multiplier for reading the old and new storage

Co-authored-by: Vladimir Stepanenko <[email protected]>

* Fix TBC reserves distribution (#1311)

* Fix TBC reserves distribution

* Update pallets/multicollateral-bonding-curve-pool/src/mock.rs

Co-authored-by: Taras Rusakovich <[email protected]>

---------

Co-authored-by: Taras Rusakovich <[email protected]>

* Prepare release 4.5.4 (#1312)

* feat: added apollo-platform migrations to the runtime migrations

---------

Signed-off-by: Mikhail Tagirov <[email protected]>
Signed-off-by: sorabot <[email protected]>
Co-authored-by: CvijanCBS <[email protected]>
Co-authored-by: Mikhail Tagirov <[email protected]>
Co-authored-by: Taras Rusakovich <[email protected]>
Co-authored-by: Vladimir Stepanenko <[email protected]>
Co-authored-by: sorabot <[email protected]>
Co-authored-by: Cvijan Djukanovic <[email protected]>
  • Loading branch information
7 people authored Jan 24, 2025
1 parent 37be80a commit f2af11d
Show file tree
Hide file tree
Showing 7 changed files with 1,303 additions and 7 deletions.
11 changes: 11 additions & 0 deletions pallets/apollo-platform/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,17 @@ benchmarks! {
assert_last_event::<T>(Event::ChangedRewardsAmount(caller, true, balance!(1)).into());
}

change_collateral_factor {
let caller = pallet::AuthorityAccount::<T>::get();
}: {
ApolloPlatform::<T>::change_collateral_factor(
RawOrigin::Signed(caller.clone()).into(),
balance!(1)
).unwrap()
} verify {
assert_last_event::<T>(Event::ChangedCollateralFactorAmount(caller,balance!(1)).into());
}

change_rewards_per_block {
let caller = pallet::AuthorityAccount::<T>::get();
let asset_id_xor = XOR;
Expand Down
175 changes: 170 additions & 5 deletions pallets/apollo-platform/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,21 @@ pub struct PoolInfo {
}

pub use pallet::*;
pub mod migrations;

#[frame_support::pallet]
pub mod pallet {
use crate::{BorrowingPosition, LendingPosition, PoolInfo, WeightInfo};
use common::prelude::{Balance, FixedWrapper, SwapAmount};
use common::{
balance, AssetIdOf, AssetManager, DEXId, LiquiditySourceFilter, PriceVariant,
CERES_ASSET_ID, DAI,
CERES_ASSET_ID, DAI, KUSD,
};
use common::{LiquidityProxyTrait, PriceToolsProvider, APOLLO_ASSET_ID};
use frame_support::log::{debug, warn};
use frame_support::pallet_prelude::{ValueQuery, *};
use frame_support::sp_runtime::traits::AccountIdConversion;
use frame_support::traits::StorageVersion;
use frame_support::PalletId;
use frame_system::offchain::{SendTransactionTypes, SubmitTransaction};
use frame_system::pallet_prelude::*;
Expand Down Expand Up @@ -108,8 +110,12 @@ pub mod pallet {

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

/// The current storage version.
pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);

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

Expand Down Expand Up @@ -139,6 +145,12 @@ pub mod pallet {
OptionQuery,
>;

/// User AccountId -> Collateral Asset -> Total Collateral Amount
#[pallet::storage]
#[pallet::getter(fn user_total_collateral)]
pub type UserTotalCollateral<T: Config> =
StorageDoubleMap<_, Identity, AccountIdOf<T>, Identity, AssetIdOf<T>, Balance, OptionQuery>;

#[pallet::storage]
#[pallet::getter(fn pool_info)]
pub type PoolData<T: Config> = StorageMap<_, Identity, AssetIdOf<T>, PoolInfo, OptionQuery>;
Expand Down Expand Up @@ -193,6 +205,17 @@ pub mod pallet {
pub type BorrowingRewards<T: Config> =
StorageValue<_, Balance, ValueQuery, FixedBorrowingRewards<T>>;

/// Default collateral factor
#[pallet::type_value]
pub fn DefaultCollateralFactor<T: Config>() -> Balance {
balance!(0.001)
}

#[pallet::storage]
#[pallet::getter(fn collateral_factor)]
pub type CollateralFactor<T: Config> =
StorageValue<_, Balance, ValueQuery, DefaultCollateralFactor<T>>;

#[pallet::type_value]
pub fn FixedLendingRewardsPerBlock<T: Config>() -> Balance {
balance!(0.03805175)
Expand Down Expand Up @@ -236,6 +259,8 @@ pub mod pallet {
ChangedRewardsAmount(AccountIdOf<T>, bool, Balance),
//// ChangedRewardsAmountPerBlock [who, is_lending, amount]
ChangedRewardsAmountPerBlock(AccountIdOf<T>, bool, Balance),
/// Changed Borrowing factor [who, amount]
ChangedCollateralFactorAmount(AccountIdOf<T>, Balance),
/// Liquidated [who, asset_id]
Liquidated(AccountIdOf<T>, AssetIdOf<T>),
/// Pool removed [who, asset_id]
Expand Down Expand Up @@ -542,14 +567,39 @@ pub mod pallet {
.try_into_balance()
.unwrap_or(0);

let mut borrow_info =
<UserBorrowingInfo<T>>::get(borrowing_asset, user.clone()).unwrap_or_default();

if collateral_asset == KUSD.into() {
let factor = <CollateralFactor<T>>::get();

// To get total collateral for a user
let total_existing_collateral =
<UserTotalCollateral<T>>::get(user.clone(), collateral_asset)
.unwrap_or(Zero::zero());

// Calculate the maximum allowed collateral for KUSD
let max_allowed_collateral = Self::calculate_max_allowed_collateral(
user_lending_info
.lending_amount
.saturating_add(total_existing_collateral),
factor,
)?;

let new_total_collateral =
total_existing_collateral.saturating_add(collateral_amount);

ensure!(
new_total_collateral <= max_allowed_collateral,
Error::<T>::InvalidCollateralAmount
);
}

ensure!(
collateral_amount <= user_lending_info.lending_amount,
Error::<T>::InvalidCollateralAmount
);

let mut borrow_info =
<UserBorrowingInfo<T>>::get(borrowing_asset, user.clone()).unwrap_or_default();

// Add borrowing amount, collateral amount and interest to user if exists, otherwise create new user
if let Some(mut user_info) = borrow_info.get_mut(&collateral_asset) {
let block_number = <frame_system::Pallet<T>>::block_number();
Expand Down Expand Up @@ -602,6 +652,9 @@ pub mod pallet {
<PoolData<T>>::insert(collateral_asset, collateral_pool_info);
<PoolData<T>>::insert(borrowing_asset, borrow_pool_info);

// Update the total collateral
Self::update_total_collateral(&user, &collateral_asset, collateral_amount)?;

// Transfer borrowing amount to user
T::AssetManager::transfer_from(
&borrowing_asset,
Expand Down Expand Up @@ -873,6 +926,13 @@ pub mod pallet {
<PoolData<T>>::insert(collateral_asset, collateral_pool_info);
<PoolData<T>>::insert(borrowing_asset, borrow_pool_info);

// Update the total collateral
Self::decrease_total_collateral(
&user,
&collateral_asset,
user_info.collateral_amount,
)?;

// Transfer borrowing amount and borrowing interest to pallet
T::AssetManager::transfer_from(
&borrowing_asset,
Expand Down Expand Up @@ -1011,7 +1071,7 @@ pub mod pallet {
// Calculate total borrow and total collateral in dollars
let mut total_borrowed: Balance = 0;

// Distributing and calculating total borrwed
// Distributing and calculating total borrowed
for (collateral_asset, user_info) in user_infos.iter() {
// Calculate collateral in dollars
let collateral_asset_price = Self::get_price(*collateral_asset);
Expand Down Expand Up @@ -1067,6 +1127,13 @@ pub mod pallet {
.total_collateral
.saturating_sub(user_info.collateral_amount);

// Update the total collateral
Self::decrease_total_collateral(
&user,
collateral_asset,
user_info.collateral_amount,
)?;

<PoolData<T>>::insert(*collateral_asset, collateral_pool_info);
// Add user's borrowed amount tied with this asset to total_borrowed in given asset
total_borrowed += user_info.borrowing_amount;
Expand Down Expand Up @@ -1225,6 +1292,30 @@ pub mod pallet {
let mut borrow_info =
<UserBorrowingInfo<T>>::get(borrowing_asset, user.clone()).unwrap_or_default();

if collateral_asset == KUSD.into() {
let factor = <CollateralFactor<T>>::get();
// To get total collateral for a user
let total_existing_collateral =
<UserTotalCollateral<T>>::get(user.clone(), collateral_asset)
.unwrap_or(Zero::zero());

// Calculate the maximum allowed collateral for KUSD
let max_allowed_collateral = Self::calculate_max_allowed_collateral(
user_lending_info
.lending_amount
.saturating_add(total_existing_collateral),
factor,
)?;

let new_total_collateral =
total_existing_collateral.saturating_add(collateral_amount);

ensure!(
new_total_collateral <= max_allowed_collateral,
Error::<T>::InvalidCollateralAmount
);
}

// Add borrowing amount, collateral amount and interest to user if exists, otherwise return error
if let Some(mut user_info) = borrow_info.get_mut(&collateral_asset) {
let block_number = <frame_system::Pallet<T>>::block_number();
Expand Down Expand Up @@ -1262,6 +1353,9 @@ pub mod pallet {
.saturating_sub(collateral_amount);
collateral_pool_info.total_collateral += collateral_amount;

// Update the total collateral
Self::update_total_collateral(&user, &collateral_asset, collateral_amount)?;

<PoolData<T>>::insert(collateral_asset, collateral_pool_info);

Self::deposit_event(Event::CollateralAdded(
Expand All @@ -1273,6 +1367,25 @@ pub mod pallet {

Ok(().into())
}

/// Change rewards amount
#[pallet::call_index(12)]
#[pallet::weight(<T as Config>::WeightInfo::change_collateral_factor())]
pub fn change_collateral_factor(
origin: OriginFor<T>,
amount: Balance,
) -> DispatchResultWithPostInfo {
let user = ensure_signed(origin)?;

if user != AuthorityAccount::<T>::get() {
return Err(Error::<T>::Unauthorized.into());
}

<CollateralFactor<T>>::put(amount);

Self::deposit_event(Event::ChangedCollateralFactorAmount(user, amount));
Ok(().into())
}
}

/// Validate unsigned call to this pallet.
Expand Down Expand Up @@ -1475,6 +1588,47 @@ pub mod pallet {
)
}

/// Increase total collateral amount for a user and asset
fn update_total_collateral(
user: &AccountIdOf<T>,
collateral_asset: &AssetIdOf<T>,
amount_to_add: Balance,
) -> DispatchResult {
<UserTotalCollateral<T>>::mutate(user, collateral_asset, |current_collateral| {
// If no existing collateral, start with the new amount
// Otherwise, add the new amount
*current_collateral = Some(
current_collateral
.unwrap_or(Zero::zero())
.saturating_add(amount_to_add),
)
});

Ok(())
}

/// Decrease total collateral amount for a user and asset
fn decrease_total_collateral(
user: &AccountIdOf<T>,
collateral_asset: &AssetIdOf<T>,
amount_to_remove: Balance,
) -> DispatchResult {
<UserTotalCollateral<T>>::mutate(user, collateral_asset, |current_collateral| {
if let Some(current) = *current_collateral {
let new_amount = current.saturating_sub(amount_to_remove);

// Remove the entry if it reaches zero, otherwise update
if new_amount == Zero::zero() {
*current_collateral = None;
} else {
*current_collateral = Some(new_amount);
}
}
});

Ok(())
}

pub fn distribute_protocol_interest(
asset_id: AssetIdOf<T>,
amount: Balance,
Expand Down Expand Up @@ -1565,6 +1719,17 @@ pub mod pallet {
Ok(().into())
}

fn calculate_max_allowed_collateral(
lending_amount: Balance,
factor: Balance,
) -> Result<Balance, DispatchError> {
Ok(
(FixedWrapper::from(lending_amount) * FixedWrapper::from(factor))
.try_into_balance()
.unwrap_or(0),
)
}

fn update_interests(block_number: BlockNumberFor<T>) -> Weight {
let mut counter: u64 = 0;
let pool_index = block_number % T::BLOCKS_PER_FIFTEEN_MINUTES;
Expand Down
Loading

0 comments on commit f2af11d

Please sign in to comment.