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

Lend market #1022

Merged
merged 32 commits into from
Sep 12, 2023
Merged
Changes from 1 commit
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
185d3ac
feat: 🎸 add lend-market
yooml Aug 21, 2023
075a720
fix: 🐛 check
yooml Aug 24, 2023
8c85fc7
feat: 🎸 add oracle
yooml Aug 25, 2023
429128c
feat: 🎸 add oracle
yooml Aug 25, 2023
e5b102e
fix: 🐛 test
yooml Aug 28, 2023
24dfd91
fix: 🐛 test
yooml Aug 28, 2023
0d4bf3a
fix: 🐛 clippy
yooml Aug 29, 2023
db8a9cc
fix: 🐛 conflict
yooml Aug 29, 2023
09b9e99
fix: 🐛 test
yooml Aug 29, 2023
386c822
fix: 🐛 clippy
yooml Aug 29, 2023
82d97be
feat: 🎸 add bifrost-currencies
yooml Aug 30, 2023
8cbc235
feat: 🎸 add fungibles
yooml Aug 30, 2023
fa247d1
feat: 🎸 bifrost-currencies for lend-market
yooml Aug 30, 2023
45628df
fix: 🐛 test
yooml Aug 31, 2023
0cad5ad
refactor: 💡 merge develop
yooml Sep 4, 2023
b5c4f84
refactor: 💡 ptoken to lend_token
yooml Sep 4, 2023
1801c60
fix: 🐛 lend_token test
yooml Sep 5, 2023
f797650
Merge branch 'develop' into lend-market
yooml Sep 5, 2023
7026941
feat: 🎸 add pallet-prices
yooml Sep 5, 2023
2141ad6
fix: 🐛 prices test
yooml Sep 6, 2023
ddfaef4
fix: 🐛 clippy
yooml Sep 6, 2023
31fc265
fix: 🐛 format lend-market
yooml Sep 6, 2023
8ef04e8
feat: 🎸 rm oracle
yooml Sep 6, 2023
ac47879
fix: 🐛 rm migration
yooml Sep 6, 2023
c7bec8b
fix: 🐛 modify currency name used for testing
yooml Sep 6, 2023
045a683
fix: 🐛 format
yooml Sep 7, 2023
2fa28ad
fix: 🐛 pallet-traits
yooml Sep 7, 2023
bb872fd
fix: 🐛 rpc
yooml Sep 8, 2023
7f52a8f
fix: 🐛 lend-market-rpc
yooml Sep 8, 2023
a3c63f5
fix: 🐛 format
yooml Sep 8, 2023
e5513d7
Merge branch 'v0.9.82' into lend-market
yooml Sep 11, 2023
b8fc700
fix: 🐛 check-all
yooml Sep 11, 2023
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
Prev Previous commit
Next Next commit
fix: 🐛 format lend-market
yooml committed Sep 6, 2023
commit 31fc265ccf0eeccda958485c8062077d5e43e9dd
13 changes: 6 additions & 7 deletions pallets/lend-market/src/benchmarking.rs
Original file line number Diff line number Diff line change
@@ -56,7 +56,7 @@ const INITIAL_AMOUNT: u32 = 500_000_000;
fn transfer_initial_balance<
T: Config
+ pallet_assets::Config<AssetId = CurrencyId, Balance = Balance>
// + pallet_prices::Config
+ pallet_prices::Config
+ pallet_balances::Config<Balance = Balance>,
>(
caller: T::AccountId,
@@ -159,12 +159,11 @@ fn transfer_initial_balance<
<T as pallet::Config>::Assets::mint_into(SKSM, &caller, INITIAL_AMOUNT.into()).unwrap();
<T as pallet::Config>::Assets::mint_into(DOT, &caller, INITIAL_AMOUNT.into()).unwrap();
<T as pallet::Config>::Assets::mint_into(CDOT_6_13, &caller, INITIAL_AMOUNT.into()).unwrap();
// pallet_prices::Pallet::<T>::set_price(SystemOrigin::Root.into(), USDT, 1.into()).unwrap();
// pallet_prices::Pallet::<T>::set_price(SystemOrigin::Root.into(), KSM, 1.into()).unwrap();
// pallet_prices::Pallet::<T>::set_price(SystemOrigin::Root.into(), SKSM, 1.into()).unwrap();
// pallet_prices::Pallet::<T>::set_price(SystemOrigin::Root.into(), DOT, 1.into()).unwrap();
// pallet_prices::Pallet::<T>::set_price(SystemOrigin::Root.into(), CDOT_6_13,
// 1.into()).unwrap();
pallet_prices::Pallet::<T>::set_price(SystemOrigin::Root.into(), USDT, 1.into()).unwrap();
pallet_prices::Pallet::<T>::set_price(SystemOrigin::Root.into(), KSM, 1.into()).unwrap();
pallet_prices::Pallet::<T>::set_price(SystemOrigin::Root.into(), SKSM, 1.into()).unwrap();
pallet_prices::Pallet::<T>::set_price(SystemOrigin::Root.into(), DOT, 1.into()).unwrap();
pallet_prices::Pallet::<T>::set_price(SystemOrigin::Root.into(), CDOT_6_13, 1.into()).unwrap();
}

fn set_account_borrows<T: Config>(
22 changes: 0 additions & 22 deletions pallets/lend-market/src/lend_token.rs
Original file line number Diff line number Diff line change
@@ -130,28 +130,6 @@ impl<T: Config> Inspect<T::AccountId> for Pallet<T> {
}
}

// impl<T: Config> Transfer<T::AccountId> for Pallet<T> {
// /// Returns `Err` if the reducible lend token of `who` is insufficient
// ///
// /// For lend token, We don't care if keep_alive is enabled
// #[transactional]
// fn transfer(
// lend_token_id: Self::AssetId,
// source: &T::AccountId,
// dest: &T::AccountId,
// amount: Self::Balance,
// _keep_alive: bool,
// ) -> Result<BalanceOf<T>, DispatchError> {
// ensure!(
// amount <= Self::reducible_balance(lend_token_id, source, false),
// Error::<T>::InsufficientCollateral
// );

// Self::do_transfer_lend_tokens(lend_token_id, source, dest, amount)?;
// Ok(amount)
// }
// }

impl<T: Config> Pallet<T> {
/// Returns `Err` if the reducible lend token of `who` is insufficient
///
9 changes: 4 additions & 5 deletions pallets/lend-market/src/lib.rs
Original file line number Diff line number Diff line change
@@ -980,11 +980,10 @@ pub mod pallet {
collateral_asset_id: AssetIdOf<T>,
) -> DispatchResultWithPostInfo {
let who = ensure_signed(origin)?;
// ensure!(
// !Self::liquidation_free_collaterals().contains(&collateral_asset_id) &&
// !is_auxiliary_token(collateral_asset_id),
// Error::<T>::CollateralReserved
// );
ensure!(
!Self::liquidation_free_collaterals().contains(&collateral_asset_id),
Error::<T>::CollateralReserved
);
Self::accrue_interest(liquidation_asset_id)?;
Self::accrue_interest(collateral_asset_id)?;
Self::do_liquidate_borrow(
22 changes: 2 additions & 20 deletions pallets/lend-market/src/mock.rs
Original file line number Diff line number Diff line change
@@ -56,7 +56,6 @@ construct_runtime!(
Currencies: bifrost_currencies::{Pallet, Call},
AssetRegistry: bifrost_asset_registry,
Loans: crate::{Pallet, Storage, Call, Event<T>},
// Prices: pallet_prices::{Pallet, Storage, Call, Event<T>},
TimestampPallet: pallet_timestamp::{Pallet, Call, Storage, Inherent},
Assets: pallet_assets::{Pallet, Call, Storage, Event<T>},
}
@@ -101,6 +100,7 @@ pub const ALICE: AccountId = AccountId32::new([1u8; 32]);
pub const BOB: AccountId = AccountId32::new([2u8; 32]);
pub const CHARLIE: AccountId = AccountId32::new([3u8; 32]);
pub const DAVE: AccountId = AccountId32::new([4u8; 32]);
pub const EVE: AccountId = AccountId32::new([5u8; 32]);

parameter_types! {
pub const MinimumPeriod: u64 = 5;
@@ -119,11 +119,7 @@ parameter_types! {
}

parameter_types! {
// pub const ExistentialDeposit: Balance = 1;
// pub const NativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::BNC);
// pub const RelayCurrencyId: CurrencyId = CurrencyId::Token(TokenSymbol::KSM);
pub const StableCurrencyId: CurrencyId = CurrencyId::Stable(TokenSymbol::KUSD);
// pub SelfParaId: u32 = ParachainInfo::parachain_id().into();
pub const PolkadotCurrencyId: CurrencyId = CurrencyId::Token(TokenSymbol::DOT);
}

@@ -143,9 +139,6 @@ impl pallet_balances::Config for Test {
type MaxFreezes = ConstU32<0>;
}

// ord_parameter_types! {
// pub const One: u128 = 1;
// }
impl bifrost_asset_registry::Config for Test {
type RuntimeEvent = RuntimeEvent;
type Currency = Balances;
@@ -297,17 +290,6 @@ parameter_types! {
pub const RelayCurrency: CurrencyId = KSM;
}

// AMM instance initialization
parameter_types! {
pub const AMMPalletId: PalletId = PalletId(*b"par/ammp");
// pub const DefaultLpFee: Ratio = Ratio::from_rational(25u32, 10000u32); // 0.25%
// pub const DefaultProtocolFee: Ratio = Ratio::from_rational(5u32, 10000u32);
pub DefaultLpFee: Ratio = Ratio::from_rational(25u32, 10000u32); // 0.3%
pub const MinimumLiquidity: u128 = 1_000u128;
pub const LockAccountId: AccountId = ALICE;
pub const MaxLengthRoute: u8 = 10;
}

pub struct AliceCreatePoolOrigin;
impl SortedMembers<AccountId> for AliceCreatePoolOrigin {
fn sorted_members() -> Vec<AccountId> {
@@ -379,7 +361,7 @@ impl pallet_assets::Config for Test {
type RuntimeEvent = RuntimeEvent;
type Balance = Balance;
type AssetId = CurrencyId;
type AssetIdParameter = CurrencyId; // codec::Compact<CurrencyId>;
type AssetIdParameter = CurrencyId;
type Currency = Balances;
type CreateOrigin = AsEnsureOriginWithArg<EnsureSigned<AccountId>>;
type ForceOrigin = EnsureRoot<AccountId>;
7 changes: 0 additions & 7 deletions pallets/lend-market/src/tests.rs
Original file line number Diff line number Diff line change
@@ -296,13 +296,6 @@ fn redeem_must_return_err_when_overflows_occur() {
Loans::redeem(RuntimeOrigin::signed(ALICE), DOT, u128::MAX),
ArithmeticError::Underflow,
);

// Exchange rate must ge greater than zero
// ExchangeRate::<Test>::insert(DOT, Rate::zero());
// assert_noop!(
// Loans::redeem(RuntimeOrigin::signed(ALICE), DOT, 100),
// ArithmeticError::Underflow
// );
})
}

80 changes: 42 additions & 38 deletions pallets/lend-market/src/tests/edge_cases.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{mock::*, tests::Loans, Error};
use frame_support::{assert_err, assert_ok};
use frame_support::{assert_err, assert_noop, assert_ok};
use sp_runtime::FixedPointNumber;

#[test]
@@ -83,40 +83,44 @@ fn redeem_all_should_be_accurate() {
})
}

// #[test]
// fn prevent_the_exchange_rate_attack() {
// new_test_ext().execute_with(|| {
// // Initialize Eve's balance
// assert_ok!(<Test as Config>::Assets::transfer(DOT.into(), &ALICE, &EVE, unit(200), false));
// // Eve deposits a small amount
// assert_ok!(Loans::mint(RuntimeOrigin::signed(EVE), DOT, 1));
// // !!! Eve transfer a big amount to Loans::account_id
// assert_ok!(<Test as Config>::Assets::transfer(
// DOT.into(),
// &EVE,
// &Loans::account_id(),
// unit(100),
// false
// ));
// assert_eq!(<Test as Config>::<Test as Config>::Assets::balance(DOT, &EVE), 99999999999999);
// assert_eq!(<Test as Config>::<Test as Config>::Assets::balance(DOT, &Loans::account_id()),
// 100000000000001); assert_eq!(
// Loans::total_supply(DOT),
// 1 * 50, // 1 / 0.02
// );
// TimestampPallet::set_timestamp(12000);
// // Eve can not let the exchange rate greater than 1
// assert!(Loans::accrue_interest(DOT).is_err());

// // Mock a BIG exchange_rate: 100000000000.02
// ExchangeRate::<Test>::insert(
// DOT,
// Rate::saturating_from_rational(100000000000020u128, 20 * 50),
// );
// // Bob can not deposit 0.1 DOT because the voucher_balance can not be 0.
// assert_noop!(
// Loans::mint(RuntimeOrigin::signed(BOB), DOT, 100000000000),
// Error::<Test>::InvalidExchangeRate
// );
// })
// }
#[test]
fn prevent_the_exchange_rate_attack() {
new_test_ext().execute_with(|| {
// Initialize Eve's balance
assert_ok!(<Test as Config>::Assets::transfer(
RuntimeOrigin::signed(ALICE),
EVE,
DOT.into(),
unit(200)
));
// Eve deposits a small amount
assert_ok!(Loans::mint(RuntimeOrigin::signed(EVE), DOT, 1));
// !!! Eve transfer a big amount to Loans::account_id
assert_ok!(<Test as Config>::Assets::transfer(
RuntimeOrigin::signed(EVE),
Loans::account_id(),
DOT.into(),
unit(100),
));
assert_eq!(<Test as Config>::Assets::balance(DOT, &EVE), 99999999999999);
assert_eq!(<Test as Config>::Assets::balance(DOT, &Loans::account_id()), 100000000000001);
assert_eq!(
Loans::total_supply(DOT),
1 * 50, // 1 / 0.02
);
TimestampPallet::set_timestamp(12000);
// Eve can not let the exchange rate greater than 1
assert!(Loans::accrue_interest(DOT).is_err());

// Mock a BIG exchange_rate: 100000000000.02
ExchangeRate::<Test>::insert(
DOT,
Rate::saturating_from_rational(100000000000020u128, 20 * 50),
);
// Bob can not deposit 0.1 DOT because the voucher_balance can not be 0.
assert_noop!(
Loans::mint(RuntimeOrigin::signed(BOB), DOT, 100000000000),
Error::<Test>::InvalidExchangeRate
);
})
}
30 changes: 15 additions & 15 deletions pallets/lend-market/src/tests/liquidate_borrow.rs
Original file line number Diff line number Diff line change
@@ -33,21 +33,21 @@ fn liquidate_borrow_allowed_works() {
})
}

// #[test]
// fn lf_liquidate_borrow_fails_due_to_lf_collateral() {
// new_test_ext().execute_with(|| {
// Loans::update_liquidation_free_collateral(RuntimeOrigin::root(), vec![CDOT_6_13]).unwrap();

// assert_err!(
// Loans::liquidate_borrow(RuntimeOrigin::signed(ALICE), BOB, DOT, unit(100), CDOT_6_13),
// Error::<Test>::CollateralReserved
// );
// assert_err!(
// Loans::liquidate_borrow(RuntimeOrigin::signed(ALICE), BOB, DOT, unit(100), DOT_U),
// Error::<Test>::CollateralReserved
// );
// })
// }
#[test]
fn lf_liquidate_borrow_fails_due_to_lf_collateral() {
new_test_ext().execute_with(|| {
Loans::update_liquidation_free_collateral(RuntimeOrigin::root(), vec![CDOT_6_13]).unwrap();

assert_err!(
Loans::liquidate_borrow(RuntimeOrigin::signed(ALICE), BOB, DOT, unit(100), CDOT_6_13),
Error::<Test>::CollateralReserved
);
assert_err!(
Loans::liquidate_borrow(RuntimeOrigin::signed(ALICE), BOB, DOT, unit(100), DOT_U),
Error::<Test>::InsufficientShortfall
);
})
}

#[test]
fn lf_liquidate_borrow_allowed_works() {