Skip to content

Commit

Permalink
Liquidation penalty now goes to OnFeeDeposit, and the same amount of …
Browse files Browse the repository at this point in the history
…debit is added to the Treasury. When liquidation is complete, the debit should be fully paid off.

Updated tests accordingly.
  • Loading branch information
Roy Yang committed Jun 21, 2022
1 parent 117f791 commit d0e6454
Show file tree
Hide file tree
Showing 10 changed files with 203 additions and 36 deletions.
8 changes: 7 additions & 1 deletion modules/cdp-engine/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1155,6 +1155,13 @@ impl<T: Config> Pallet<T> {
let liquidation_penalty = Self::get_liquidation_penalty(currency_id)?;
let target_stable_amount = liquidation_penalty.saturating_mul_acc_int(bad_debt_value);

let debt_penalty = liquidation_penalty.saturating_mul_int(bad_debt_value);
let stable_currency_id = T::GetStableCurrencyId::get();

// Deposit penalty to OnFeeDeposit and add the debt to the treasury.
T::OnFeeDeposit::on_fee_deposit(IncomeSource::HonzonLiquidationFee, stable_currency_id, debt_penalty)?;
<T as Config>::CDPTreasury::on_system_debit(debt_penalty)?;

match currency_id {
CurrencyId::DexShare(dex_share_0, dex_share_1) => {
let token_0: CurrencyId = dex_share_0.into();
Expand All @@ -1165,7 +1172,6 @@ impl<T: Config> Pallet<T> {
<T as Config>::CDPTreasury::remove_liquidity_for_lp_collateral(currency_id, collateral)?;

// if these's stable
let stable_currency_id = T::GetStableCurrencyId::get();
if token_0 == stable_currency_id || token_1 == stable_currency_id {
let (existing_stable, need_handle_currency, handle_amount) = if token_0 == stable_currency_id {
(amount_0, token_1, amount_1)
Expand Down
89 changes: 81 additions & 8 deletions modules/cdp-engine/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
use super::*;
use frame_support::{assert_noop, assert_ok};
use mock::{Call as MockCall, Event, *};
use module_fees::PoolPercent;
use orml_traits::MultiCurrency;
use primitives::PoolPercent;
use sp_core::offchain::{testing, OffchainDbExt, OffchainWorkerExt, TransactionPoolExt};
use sp_io::offchain;
use sp_runtime::{
Expand Down Expand Up @@ -68,6 +68,14 @@ fn setup_fees_distribution() {
rate: Rate::one(),
}],
));
assert_ok!(Fees::set_income_fee(
Origin::root(),
IncomeSource::HonzonLiquidationFee,
vec![PoolPercent {
pool: BOB,
rate: Rate::one(),
}],
));
}

#[test]
Expand Down Expand Up @@ -819,6 +827,7 @@ fn remain_debit_value_too_small_check() {
#[test]
fn liquidate_unsafe_cdp_by_collateral_auction() {
ExtBuilder::default().build().execute_with(|| {
setup_fees_distribution();
System::set_block_number(1);
assert_ok!(CDPEngineModule::set_collateral_params(
Origin::signed(1),
Expand All @@ -831,6 +840,7 @@ fn liquidate_unsafe_cdp_by_collateral_auction() {
));
setup_default_collateral(AUSD);
assert_ok!(CDPEngineModule::adjust_position(&ALICE, BTC, 100, 500));

assert_eq!(Currencies::free_balance(BTC, &ALICE), 900);
assert_eq!(Currencies::free_balance(AUSD, &ALICE), 50);
assert_eq!(LoansModule::positions(BTC, ALICE).debit, 500);
Expand All @@ -848,16 +858,21 @@ fn liquidate_unsafe_cdp_by_collateral_auction() {
Change::NoChange,
Change::NoChange,
));
assert_ok!(CDPEngineModule::liquidate_unsafe_cdp(ALICE, BTC));

assert_eq!(CDPTreasuryModule::debit_pool(), 0);
assert_eq!(Currencies::free_balance(AUSD, &ALICE), 50);
assert_ok!(CDPEngineModule::liquidate_unsafe_cdp(ALICE, BTC));
System::assert_last_event(Event::CDPEngineModule(crate::Event::LiquidateUnsafeCDP {
collateral_type: BTC,
owner: ALICE,
collateral_amount: 100,
bad_debt_value: 50,
target_amount: 60,
}));
assert_eq!(CDPTreasuryModule::debit_pool(), 50);
// 50 debt + 10 penalty
assert_eq!(CDPTreasuryModule::debit_pool(), 60);
assert_eq!(Currencies::free_balance(AUSD, &BOB), 10);

assert_eq!(Currencies::free_balance(BTC, &ALICE), 900);
assert_eq!(Currencies::free_balance(AUSD, &ALICE), 50);
assert_eq!(LoansModule::positions(BTC, ALICE).debit, 0);
Expand All @@ -874,6 +889,7 @@ fn liquidate_unsafe_cdp_by_collateral_auction() {
#[test]
fn liquidate_unsafe_cdp_by_collateral_auction_when_limited_by_slippage() {
ExtBuilder::default().build().execute_with(|| {
setup_fees_distribution();
System::set_block_number(1);
assert_ok!(CDPEngineModule::set_collateral_params(
Origin::signed(1),
Expand Down Expand Up @@ -932,7 +948,7 @@ fn liquidate_unsafe_cdp_by_collateral_auction_when_limited_by_slippage() {
}));

assert_eq!(DEXModule::get_liquidity_pool(BTC, AUSD), (100, 121));
assert_eq!(CDPTreasuryModule::debit_pool(), 50);
assert_eq!(CDPTreasuryModule::debit_pool(), 60);
assert_eq!(Currencies::free_balance(BTC, &ALICE), 900);
assert_eq!(Currencies::free_balance(AUSD, &ALICE), 50);
assert_eq!(LoansModule::positions(BTC, ALICE).debit, 0);
Expand All @@ -943,6 +959,7 @@ fn liquidate_unsafe_cdp_by_collateral_auction_when_limited_by_slippage() {
#[test]
fn liquidate_unsafe_cdp_by_swap() {
ExtBuilder::default().build().execute_with(|| {
setup_fees_distribution();
System::set_block_number(1);
assert_ok!(CDPEngineModule::set_collateral_params(
Origin::signed(1),
Expand Down Expand Up @@ -992,7 +1009,7 @@ fn liquidate_unsafe_cdp_by_swap() {
}));

assert_eq!(DEXModule::get_liquidity_pool(BTC, AUSD), (199, 61));
assert_eq!(CDPTreasuryModule::debit_pool(), 50);
assert_eq!(CDPTreasuryModule::debit_pool(), 60);
assert_eq!(Currencies::free_balance(BTC, &ALICE), 901);
assert_eq!(Currencies::free_balance(AUSD, &ALICE), 50);
assert_eq!(LoansModule::positions(BTC, ALICE).debit, 0);
Expand All @@ -1003,6 +1020,7 @@ fn liquidate_unsafe_cdp_by_swap() {
#[test]
fn liquidate_unsafe_cdp_of_lp_ausd_dot_and_swap_dot() {
ExtBuilder::default().build().execute_with(|| {
setup_fees_distribution();
System::set_block_number(1);
assert_ok!(CDPEngineModule::set_collateral_params(
Origin::signed(1),
Expand Down Expand Up @@ -1082,7 +1100,7 @@ fn liquidate_unsafe_cdp_of_lp_ausd_dot_and_swap_dot() {
assert_eq!(LoansModule::positions(LP_AUSD_DOT, ALICE).debit, 0);
assert_eq!(LoansModule::positions(LP_AUSD_DOT, ALICE).collateral, 0);
assert_eq!(Currencies::free_balance(LP_AUSD_DOT, &LoansModule::account_id()), 0);
assert_eq!(CDPTreasuryModule::debit_pool(), 500);
assert_eq!(CDPTreasuryModule::debit_pool(), 600);
assert_eq!(Currencies::free_balance(AUSD, &CDPTreasuryModule::account_id()), 600);
assert_eq!(Currencies::free_balance(DOT, &CDPTreasuryModule::account_id()), 0);
assert_eq!(
Expand All @@ -1096,6 +1114,7 @@ fn liquidate_unsafe_cdp_of_lp_ausd_dot_and_swap_dot() {
#[test]
fn liquidate_unsafe_cdp_of_lp_ausd_dot_and_ausd_take_whole_target() {
ExtBuilder::default().build().execute_with(|| {
setup_fees_distribution();
System::set_block_number(1);
assert_ok!(CDPEngineModule::set_collateral_params(
Origin::signed(1),
Expand Down Expand Up @@ -1175,7 +1194,7 @@ fn liquidate_unsafe_cdp_of_lp_ausd_dot_and_ausd_take_whole_target() {
assert_eq!(LoansModule::positions(LP_AUSD_DOT, ALICE).debit, 0);
assert_eq!(LoansModule::positions(LP_AUSD_DOT, ALICE).collateral, 0);
assert_eq!(Currencies::free_balance(LP_AUSD_DOT, &LoansModule::account_id()), 0);
assert_eq!(CDPTreasuryModule::debit_pool(), 200);
assert_eq!(CDPTreasuryModule::debit_pool(), 240);
assert_eq!(Currencies::free_balance(AUSD, &CDPTreasuryModule::account_id()), 240);
assert_eq!(Currencies::free_balance(DOT, &CDPTreasuryModule::account_id()), 0);
assert_eq!(
Expand All @@ -1189,6 +1208,7 @@ fn liquidate_unsafe_cdp_of_lp_ausd_dot_and_ausd_take_whole_target() {
#[test]
fn liquidate_unsafe_cdp_of_lp_ausd_dot_and_create_dot_auction() {
ExtBuilder::default().build().execute_with(|| {
setup_fees_distribution();
System::set_block_number(1);
assert_ok!(CDPEngineModule::set_collateral_params(
Origin::signed(1),
Expand Down Expand Up @@ -1268,7 +1288,7 @@ fn liquidate_unsafe_cdp_of_lp_ausd_dot_and_create_dot_auction() {
assert_eq!(LoansModule::positions(LP_AUSD_DOT, ALICE).debit, 0);
assert_eq!(LoansModule::positions(LP_AUSD_DOT, ALICE).collateral, 0);
assert_eq!(Currencies::free_balance(LP_AUSD_DOT, &LoansModule::account_id()), 0);
assert_eq!(CDPTreasuryModule::debit_pool(), 500);
assert_eq!(CDPTreasuryModule::debit_pool(), 600);
assert_eq!(Currencies::free_balance(AUSD, &CDPTreasuryModule::account_id()), 500);
assert_eq!(Currencies::free_balance(DOT, &CDPTreasuryModule::account_id()), 25);
assert_eq!(
Expand Down Expand Up @@ -1644,6 +1664,7 @@ fn offchain_worker_works_cdp() {
ext.register_extension(OffchainDbExt::new(offchain));

ext.execute_with(|| {
setup_fees_distribution();
// number of currencies allowed as collateral (cycles through all of them)
setup_default_collateral(BTC);
setup_default_collateral(LP_AUSD_DOT);
Expand Down Expand Up @@ -1729,6 +1750,7 @@ fn offchain_worker_iteration_limit_works() {
ext.register_extension(OffchainDbExt::new(offchain.clone()));

ext.execute_with(|| {
setup_fees_distribution();
System::set_block_number(1);
// sets max iterations value to 1
offchain.local_storage_set(StorageKind::PERSISTENT, OFFCHAIN_WORKER_MAX_ITERATIONS, &1u32.encode());
Expand Down Expand Up @@ -1950,3 +1972,54 @@ fn accumulated_interest_goes_to_on_fee_deposit() {
);
});
}

#[test]
fn liquidation_fee_goes_to_on_fee_deposit() {
ExtBuilder::default().build().execute_with(|| {
setup_fees_distribution();

assert_ok!(CDPEngineModule::set_collateral_params(
Origin::signed(1),
BTC,
Change::NewValue(Some(Rate::zero())),
Change::NewValue(Some(Ratio::saturating_from_rational(2, 1))),
Change::NewValue(Some(Rate::one())),
Change::NewValue(Some(Ratio::saturating_from_rational(2, 1))),
Change::NewValue(10000),
));
assert_ok!(CDPEngineModule::adjust_position(&ALICE, BTC, 100, 500));

// Alice: -100 collateral. +50 from debit
assert_eq!(Currencies::free_balance(BTC, &ALICE), 900);
assert_eq!(Currencies::free_balance(AUSD, &ALICE), 50);
// Bob's initial balance
assert_eq!(Currencies::free_balance(BTC, &BOB), 1000);
assert_eq!(Currencies::free_balance(AUSD, &BOB), 0);
// Treasury had no debt from before
assert_eq!(CDPTreasuryModule::get_debit_pool(), 0);
assert_eq!(
LoansModule::positions(BTC, &ALICE),
Position {
collateral: 100,
debit: 500,
}
);
MockPriceSource::set_price(BTC, Some(Price::saturating_from_rational(1, 10)));
assert_ok!(CDPEngineModule::liquidate_unsafe_cdp(ALICE, BTC));

// Treasury Debit: 50 from confiscation and +50 from penalty
assert_eq!(CDPTreasuryModule::get_debit_pool(), 100);

assert_eq!(Currencies::free_balance(BTC, &ALICE), 900);
assert_eq!(Currencies::free_balance(AUSD, &ALICE), 50);
assert_eq!(
LoansModule::positions(BTC, &ALICE),
Position {
collateral: 0,
debit: 0,
}
);
assert_eq!(Currencies::free_balance(BTC, &BOB), 1000);
assert_eq!(Currencies::free_balance(AUSD, &BOB), 50);
});
}
14 changes: 2 additions & 12 deletions modules/fees/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use frame_support::{
};
use frame_system::pallet_prelude::*;
use orml_traits::MultiCurrency;
use primitives::{Balance, CurrencyId, IncomeSource};
use primitives::{Balance, CurrencyId, IncomeSource, PoolPercent};
use sp_runtime::{
traits::{One, Saturating, Zero},
FixedPointNumber, FixedU128,
Expand All @@ -40,11 +40,8 @@ use support::{DEXManager, OnFeeDeposit, SwapLimit};
mod mock;
mod tests;
pub mod weights;
pub use weights::WeightInfo;

#[cfg(feature = "std")]
use serde::{Deserialize, Serialize};
use sp_runtime::traits::UniqueSaturatedInto;
pub use weights::WeightInfo;

pub type NegativeImbalanceOf<T> =
<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::NegativeImbalance;
Expand All @@ -55,13 +52,6 @@ pub type Treasuries<T> = Vec<(
Vec<(<T as frame_system::Config>::AccountId, u32)>,
)>;

#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct PoolPercent<AccountId> {
pub pool: AccountId,
pub rate: FixedU128,
}

/// helper method to create `PoolPercent` list by tuple.
pub fn build_pool_percents<AccountId: Clone>(list: Vec<(AccountId, u32)>) -> Vec<PoolPercent<AccountId>> {
list.iter()
Expand Down
2 changes: 2 additions & 0 deletions modules/fees/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ use sp_runtime::traits::AccountIdConversion;
use support::mocks::MockAddressMapping;

pub const ALICE: AccountId = AccountId::new([1u8; 32]);
pub const BOB: AccountId = AccountId::new([2u8; 32]);
pub const CHARLIE: AccountId = AccountId::new([3u8; 32]);
pub const AUSD: CurrencyId = CurrencyId::Token(TokenSymbol::AUSD);
pub const ACA: CurrencyId = CurrencyId::Token(TokenSymbol::ACA);
pub const DOT: CurrencyId = CurrencyId::Token(TokenSymbol::DOT);
Expand Down
63 changes: 62 additions & 1 deletion modules/fees/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ use crate::mock::*;
use frame_support::traits::{ExistenceRequirement, WithdrawReasons};
use frame_support::{assert_noop, assert_ok};
use mock::{Event, ExtBuilder, Origin, Runtime, System};
use primitives::AccountId;
use primitives::{AccountId, PoolPercent};
use support::Rate;

#[test]
fn set_income_fee_works() {
Expand Down Expand Up @@ -215,6 +216,19 @@ fn on_fee_deposit_works() {
.balances(vec![(ALICE, ACA, 10000), (ALICE, DOT, 10000)])
.build()
.execute_with(|| {
assert_ok!(Fees::do_set_treasury_rate(
IncomeSource::TxFee,
vec![
PoolPercent {
pool: NetworkTreasuryPool::get(),
rate: Rate::saturating_from_rational(8, 10)
},
PoolPercent {
pool: CollatorsRewardPool::get(),
rate: Rate::saturating_from_rational(2, 10)
},
]
));
// Native token tests
// FeeToTreasuryPool based on pre-configured treasury pool percentage.
assert_ok!(Pallet::<Runtime>::on_fee_deposit(IncomeSource::TxFee, ACA, 10000));
Expand Down Expand Up @@ -406,3 +420,50 @@ fn distribution_incentive_threshold_works() {
}));
});
}

#[test]
fn independent_pools_on_fee_deposit_works() {
ExtBuilder::default().build().execute_with(|| {
// Register payout destination for multiple pools
assert_ok!(Fees::do_set_treasury_rate(
IncomeSource::TxFee,
vec![PoolPercent {
pool: ALICE,
rate: Rate::one()
},]
));
assert_ok!(Fees::do_set_treasury_rate(
IncomeSource::XcmFee,
vec![PoolPercent {
pool: BOB,
rate: Rate::one()
},]
));
assert_ok!(Fees::do_set_treasury_rate(
IncomeSource::HonzonStabilityFee,
vec![PoolPercent {
pool: CHARLIE,
rate: Rate::one()
},]
));

assert_ok!(Pallet::<Runtime>::on_fee_deposit(IncomeSource::TxFee, ACA, 1000));
assert_eq!(Currencies::free_balance(ACA, &ALICE), 1000);
assert_eq!(Currencies::free_balance(ACA, &BOB), 0);
assert_eq!(Currencies::free_balance(ACA, &CHARLIE), 0);

assert_ok!(Pallet::<Runtime>::on_fee_deposit(IncomeSource::XcmFee, ACA, 1000));
assert_eq!(Currencies::free_balance(ACA, &ALICE), 1000);
assert_eq!(Currencies::free_balance(ACA, &BOB), 1000);
assert_eq!(Currencies::free_balance(ACA, &CHARLIE), 0);

assert_ok!(Pallet::<Runtime>::on_fee_deposit(
IncomeSource::HonzonStabilityFee,
ACA,
1000
));
assert_eq!(Currencies::free_balance(ACA, &ALICE), 1000);
assert_eq!(Currencies::free_balance(ACA, &BOB), 1000);
assert_eq!(Currencies::free_balance(ACA, &CHARLIE), 1000);
});
}
2 changes: 1 addition & 1 deletion modules/homa/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
use super::*;
use frame_support::{assert_noop, assert_ok};
use mock::{Event, *};
use module_fees::PoolPercent;
use orml_traits::MultiCurrency;
use primitives::PoolPercent;
use sp_runtime::{traits::BadOrigin, FixedPointNumber};

fn setup_fees_distribution() {
Expand Down
Loading

0 comments on commit d0e6454

Please sign in to comment.