Skip to content

Commit f2af11d

Browse files
DanijelCBSCvijanCBSwer1stZlayaMordavovac12
authored
Feature/apollo update collateral factor (#1302)
* 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]>
1 parent 37be80a commit f2af11d

File tree

7 files changed

+1303
-7
lines changed

7 files changed

+1303
-7
lines changed

pallets/apollo-platform/src/benchmarking.rs

+11
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,17 @@ benchmarks! {
576576
assert_last_event::<T>(Event::ChangedRewardsAmount(caller, true, balance!(1)).into());
577577
}
578578

579+
change_collateral_factor {
580+
let caller = pallet::AuthorityAccount::<T>::get();
581+
}: {
582+
ApolloPlatform::<T>::change_collateral_factor(
583+
RawOrigin::Signed(caller.clone()).into(),
584+
balance!(1)
585+
).unwrap()
586+
} verify {
587+
assert_last_event::<T>(Event::ChangedCollateralFactorAmount(caller,balance!(1)).into());
588+
}
589+
579590
change_rewards_per_block {
580591
let caller = pallet::AuthorityAccount::<T>::get();
581592
let asset_id_xor = XOR;

pallets/apollo-platform/src/lib.rs

+170-5
Original file line numberDiff line numberDiff line change
@@ -54,19 +54,21 @@ pub struct PoolInfo {
5454
}
5555

5656
pub use pallet::*;
57+
pub mod migrations;
5758

5859
#[frame_support::pallet]
5960
pub mod pallet {
6061
use crate::{BorrowingPosition, LendingPosition, PoolInfo, WeightInfo};
6162
use common::prelude::{Balance, FixedWrapper, SwapAmount};
6263
use common::{
6364
balance, AssetIdOf, AssetManager, DEXId, LiquiditySourceFilter, PriceVariant,
64-
CERES_ASSET_ID, DAI,
65+
CERES_ASSET_ID, DAI, KUSD,
6566
};
6667
use common::{LiquidityProxyTrait, PriceToolsProvider, APOLLO_ASSET_ID};
6768
use frame_support::log::{debug, warn};
6869
use frame_support::pallet_prelude::{ValueQuery, *};
6970
use frame_support::sp_runtime::traits::AccountIdConversion;
71+
use frame_support::traits::StorageVersion;
7072
use frame_support::PalletId;
7173
use frame_system::offchain::{SendTransactionTypes, SubmitTransaction};
7274
use frame_system::pallet_prelude::*;
@@ -108,8 +110,12 @@ pub mod pallet {
108110

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

113+
/// The current storage version.
114+
pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
115+
111116
#[pallet::pallet]
112117
#[pallet::generate_store(pub (super) trait Store)]
118+
#[pallet::storage_version(STORAGE_VERSION)]
113119
#[pallet::without_storage_info]
114120
pub struct Pallet<T>(PhantomData<T>);
115121

@@ -139,6 +145,12 @@ pub mod pallet {
139145
OptionQuery,
140146
>;
141147

148+
/// User AccountId -> Collateral Asset -> Total Collateral Amount
149+
#[pallet::storage]
150+
#[pallet::getter(fn user_total_collateral)]
151+
pub type UserTotalCollateral<T: Config> =
152+
StorageDoubleMap<_, Identity, AccountIdOf<T>, Identity, AssetIdOf<T>, Balance, OptionQuery>;
153+
142154
#[pallet::storage]
143155
#[pallet::getter(fn pool_info)]
144156
pub type PoolData<T: Config> = StorageMap<_, Identity, AssetIdOf<T>, PoolInfo, OptionQuery>;
@@ -193,6 +205,17 @@ pub mod pallet {
193205
pub type BorrowingRewards<T: Config> =
194206
StorageValue<_, Balance, ValueQuery, FixedBorrowingRewards<T>>;
195207

208+
/// Default collateral factor
209+
#[pallet::type_value]
210+
pub fn DefaultCollateralFactor<T: Config>() -> Balance {
211+
balance!(0.001)
212+
}
213+
214+
#[pallet::storage]
215+
#[pallet::getter(fn collateral_factor)]
216+
pub type CollateralFactor<T: Config> =
217+
StorageValue<_, Balance, ValueQuery, DefaultCollateralFactor<T>>;
218+
196219
#[pallet::type_value]
197220
pub fn FixedLendingRewardsPerBlock<T: Config>() -> Balance {
198221
balance!(0.03805175)
@@ -236,6 +259,8 @@ pub mod pallet {
236259
ChangedRewardsAmount(AccountIdOf<T>, bool, Balance),
237260
//// ChangedRewardsAmountPerBlock [who, is_lending, amount]
238261
ChangedRewardsAmountPerBlock(AccountIdOf<T>, bool, Balance),
262+
/// Changed Borrowing factor [who, amount]
263+
ChangedCollateralFactorAmount(AccountIdOf<T>, Balance),
239264
/// Liquidated [who, asset_id]
240265
Liquidated(AccountIdOf<T>, AssetIdOf<T>),
241266
/// Pool removed [who, asset_id]
@@ -542,14 +567,39 @@ pub mod pallet {
542567
.try_into_balance()
543568
.unwrap_or(0);
544569

570+
let mut borrow_info =
571+
<UserBorrowingInfo<T>>::get(borrowing_asset, user.clone()).unwrap_or_default();
572+
573+
if collateral_asset == KUSD.into() {
574+
let factor = <CollateralFactor<T>>::get();
575+
576+
// To get total collateral for a user
577+
let total_existing_collateral =
578+
<UserTotalCollateral<T>>::get(user.clone(), collateral_asset)
579+
.unwrap_or(Zero::zero());
580+
581+
// Calculate the maximum allowed collateral for KUSD
582+
let max_allowed_collateral = Self::calculate_max_allowed_collateral(
583+
user_lending_info
584+
.lending_amount
585+
.saturating_add(total_existing_collateral),
586+
factor,
587+
)?;
588+
589+
let new_total_collateral =
590+
total_existing_collateral.saturating_add(collateral_amount);
591+
592+
ensure!(
593+
new_total_collateral <= max_allowed_collateral,
594+
Error::<T>::InvalidCollateralAmount
595+
);
596+
}
597+
545598
ensure!(
546599
collateral_amount <= user_lending_info.lending_amount,
547600
Error::<T>::InvalidCollateralAmount
548601
);
549602

550-
let mut borrow_info =
551-
<UserBorrowingInfo<T>>::get(borrowing_asset, user.clone()).unwrap_or_default();
552-
553603
// Add borrowing amount, collateral amount and interest to user if exists, otherwise create new user
554604
if let Some(mut user_info) = borrow_info.get_mut(&collateral_asset) {
555605
let block_number = <frame_system::Pallet<T>>::block_number();
@@ -602,6 +652,9 @@ pub mod pallet {
602652
<PoolData<T>>::insert(collateral_asset, collateral_pool_info);
603653
<PoolData<T>>::insert(borrowing_asset, borrow_pool_info);
604654

655+
// Update the total collateral
656+
Self::update_total_collateral(&user, &collateral_asset, collateral_amount)?;
657+
605658
// Transfer borrowing amount to user
606659
T::AssetManager::transfer_from(
607660
&borrowing_asset,
@@ -873,6 +926,13 @@ pub mod pallet {
873926
<PoolData<T>>::insert(collateral_asset, collateral_pool_info);
874927
<PoolData<T>>::insert(borrowing_asset, borrow_pool_info);
875928

929+
// Update the total collateral
930+
Self::decrease_total_collateral(
931+
&user,
932+
&collateral_asset,
933+
user_info.collateral_amount,
934+
)?;
935+
876936
// Transfer borrowing amount and borrowing interest to pallet
877937
T::AssetManager::transfer_from(
878938
&borrowing_asset,
@@ -1011,7 +1071,7 @@ pub mod pallet {
10111071
// Calculate total borrow and total collateral in dollars
10121072
let mut total_borrowed: Balance = 0;
10131073

1014-
// Distributing and calculating total borrwed
1074+
// Distributing and calculating total borrowed
10151075
for (collateral_asset, user_info) in user_infos.iter() {
10161076
// Calculate collateral in dollars
10171077
let collateral_asset_price = Self::get_price(*collateral_asset);
@@ -1067,6 +1127,13 @@ pub mod pallet {
10671127
.total_collateral
10681128
.saturating_sub(user_info.collateral_amount);
10691129

1130+
// Update the total collateral
1131+
Self::decrease_total_collateral(
1132+
&user,
1133+
collateral_asset,
1134+
user_info.collateral_amount,
1135+
)?;
1136+
10701137
<PoolData<T>>::insert(*collateral_asset, collateral_pool_info);
10711138
// Add user's borrowed amount tied with this asset to total_borrowed in given asset
10721139
total_borrowed += user_info.borrowing_amount;
@@ -1225,6 +1292,30 @@ pub mod pallet {
12251292
let mut borrow_info =
12261293
<UserBorrowingInfo<T>>::get(borrowing_asset, user.clone()).unwrap_or_default();
12271294

1295+
if collateral_asset == KUSD.into() {
1296+
let factor = <CollateralFactor<T>>::get();
1297+
// To get total collateral for a user
1298+
let total_existing_collateral =
1299+
<UserTotalCollateral<T>>::get(user.clone(), collateral_asset)
1300+
.unwrap_or(Zero::zero());
1301+
1302+
// Calculate the maximum allowed collateral for KUSD
1303+
let max_allowed_collateral = Self::calculate_max_allowed_collateral(
1304+
user_lending_info
1305+
.lending_amount
1306+
.saturating_add(total_existing_collateral),
1307+
factor,
1308+
)?;
1309+
1310+
let new_total_collateral =
1311+
total_existing_collateral.saturating_add(collateral_amount);
1312+
1313+
ensure!(
1314+
new_total_collateral <= max_allowed_collateral,
1315+
Error::<T>::InvalidCollateralAmount
1316+
);
1317+
}
1318+
12281319
// Add borrowing amount, collateral amount and interest to user if exists, otherwise return error
12291320
if let Some(mut user_info) = borrow_info.get_mut(&collateral_asset) {
12301321
let block_number = <frame_system::Pallet<T>>::block_number();
@@ -1262,6 +1353,9 @@ pub mod pallet {
12621353
.saturating_sub(collateral_amount);
12631354
collateral_pool_info.total_collateral += collateral_amount;
12641355

1356+
// Update the total collateral
1357+
Self::update_total_collateral(&user, &collateral_asset, collateral_amount)?;
1358+
12651359
<PoolData<T>>::insert(collateral_asset, collateral_pool_info);
12661360

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

12741368
Ok(().into())
12751369
}
1370+
1371+
/// Change rewards amount
1372+
#[pallet::call_index(12)]
1373+
#[pallet::weight(<T as Config>::WeightInfo::change_collateral_factor())]
1374+
pub fn change_collateral_factor(
1375+
origin: OriginFor<T>,
1376+
amount: Balance,
1377+
) -> DispatchResultWithPostInfo {
1378+
let user = ensure_signed(origin)?;
1379+
1380+
if user != AuthorityAccount::<T>::get() {
1381+
return Err(Error::<T>::Unauthorized.into());
1382+
}
1383+
1384+
<CollateralFactor<T>>::put(amount);
1385+
1386+
Self::deposit_event(Event::ChangedCollateralFactorAmount(user, amount));
1387+
Ok(().into())
1388+
}
12761389
}
12771390

12781391
/// Validate unsigned call to this pallet.
@@ -1475,6 +1588,47 @@ pub mod pallet {
14751588
)
14761589
}
14771590

1591+
/// Increase total collateral amount for a user and asset
1592+
fn update_total_collateral(
1593+
user: &AccountIdOf<T>,
1594+
collateral_asset: &AssetIdOf<T>,
1595+
amount_to_add: Balance,
1596+
) -> DispatchResult {
1597+
<UserTotalCollateral<T>>::mutate(user, collateral_asset, |current_collateral| {
1598+
// If no existing collateral, start with the new amount
1599+
// Otherwise, add the new amount
1600+
*current_collateral = Some(
1601+
current_collateral
1602+
.unwrap_or(Zero::zero())
1603+
.saturating_add(amount_to_add),
1604+
)
1605+
});
1606+
1607+
Ok(())
1608+
}
1609+
1610+
/// Decrease total collateral amount for a user and asset
1611+
fn decrease_total_collateral(
1612+
user: &AccountIdOf<T>,
1613+
collateral_asset: &AssetIdOf<T>,
1614+
amount_to_remove: Balance,
1615+
) -> DispatchResult {
1616+
<UserTotalCollateral<T>>::mutate(user, collateral_asset, |current_collateral| {
1617+
if let Some(current) = *current_collateral {
1618+
let new_amount = current.saturating_sub(amount_to_remove);
1619+
1620+
// Remove the entry if it reaches zero, otherwise update
1621+
if new_amount == Zero::zero() {
1622+
*current_collateral = None;
1623+
} else {
1624+
*current_collateral = Some(new_amount);
1625+
}
1626+
}
1627+
});
1628+
1629+
Ok(())
1630+
}
1631+
14781632
pub fn distribute_protocol_interest(
14791633
asset_id: AssetIdOf<T>,
14801634
amount: Balance,
@@ -1565,6 +1719,17 @@ pub mod pallet {
15651719
Ok(().into())
15661720
}
15671721

1722+
fn calculate_max_allowed_collateral(
1723+
lending_amount: Balance,
1724+
factor: Balance,
1725+
) -> Result<Balance, DispatchError> {
1726+
Ok(
1727+
(FixedWrapper::from(lending_amount) * FixedWrapper::from(factor))
1728+
.try_into_balance()
1729+
.unwrap_or(0),
1730+
)
1731+
}
1732+
15681733
fn update_interests(block_number: BlockNumberFor<T>) -> Weight {
15691734
let mut counter: u64 = 0;
15701735
let pool_index = block_number % T::BLOCKS_PER_FIFTEEN_MINUTES;

0 commit comments

Comments
 (0)