Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
36 changes: 29 additions & 7 deletions modules/incentives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ use primitives::{Amount, Balance, CurrencyId};
use scale_info::TypeInfo;
use sp_runtime::{
traits::{AccountIdConversion, One, UniqueSaturatedInto, Zero},
DispatchResult, FixedPointNumber, RuntimeDebug,
DispatchResult, FixedPointNumber, Permill, RuntimeDebug,
};
use sp_std::{collections::btree_map::BTreeMap, prelude::*};
use support::{CDPTreasury, DEXIncentives, DEXManager, EmergencyShutdown, Rate};
Expand Down Expand Up @@ -86,6 +86,10 @@ pub mod module {
#[pallet::constant]
type AccumulatePeriod: Get<Self::BlockNumber>;

/// The native currency for earning staking
#[pallet::constant]
type NativeCurrencyId: Get<CurrencyId>;

/// The reward type for dex saving.
#[pallet::constant]
type StableCurrencyId: Get<CurrencyId>;
Expand All @@ -94,6 +98,10 @@ pub mod module {
#[pallet::constant]
type RewardsSource: Get<Self::AccountId>;

/// Additional share amount from earning
#[pallet::constant]
type EarnShareBooster: Get<Permill>;

/// The origin which may update incentive related params
type UpdateOrigin: EnsureOrigin<Self::Origin>;

Expand Down Expand Up @@ -576,16 +584,14 @@ impl<T: Config> DEXIncentives<T::AccountId, CurrencyId, Balance> for Pallet<T> {
pub struct OnUpdateLoan<T>(sp_std::marker::PhantomData<T>);
impl<T: Config> Happened<(T::AccountId, CurrencyId, Amount, Balance)> for OnUpdateLoan<T> {
fn happened(info: &(T::AccountId, CurrencyId, Amount, Balance)) {
let (who, currency_id, adjustment, previous_amount) = info;
let (who, currency_id, adjustment, _previous_amount) = info;
let adjustment_abs = TryInto::<Balance>::try_into(adjustment.saturating_abs()).unwrap_or_default();

let new_share_amount = if adjustment.is_positive() {
previous_amount.saturating_add(adjustment_abs)
if adjustment.is_positive() {
<orml_rewards::Pallet<T>>::add_share(who, &PoolId::Loans(*currency_id), adjustment_abs);
} else {
previous_amount.saturating_sub(adjustment_abs)
<orml_rewards::Pallet<T>>::remove_share(who, &PoolId::Loans(*currency_id), adjustment_abs);
};

<orml_rewards::Pallet<T>>::set_share(who, &PoolId::Loans(*currency_id), new_share_amount);
}
}

Expand All @@ -605,3 +611,19 @@ impl<T: Config> RewardHandler<T::AccountId, CurrencyId> for Pallet<T> {
});
}
}

pub struct OnEarningBonded<T>(sp_std::marker::PhantomData<T>);
impl<T: Config> Happened<(T::AccountId, Balance)> for OnEarningBonded<T> {
fn happened((who, amount): &(T::AccountId, Balance)) {
let share = amount.saturating_add(T::EarnShareBooster::get() * *amount);
<orml_rewards::Pallet<T>>::add_share(who, &PoolId::Loans(T::NativeCurrencyId::get()), share);
}
}

pub struct OnEarningUnbonded<T>(sp_std::marker::PhantomData<T>);
impl<T: Config> Happened<(T::AccountId, Balance)> for OnEarningUnbonded<T> {
fn happened((who, amount): &(T::AccountId, Balance)) {
let share = amount.saturating_add(T::EarnShareBooster::get() * *amount);
<orml_rewards::Pallet<T>>::remove_share(who, &PoolId::Loans(T::NativeCurrencyId::get()), share);
}
}
4 changes: 4 additions & 0 deletions modules/incentives/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,18 +248,22 @@ impl orml_rewards::Config for Runtime {
parameter_types! {
pub const AccumulatePeriod: BlockNumber = 10;
pub const StableCurrencyId: CurrencyId = AUSD;
pub const GetNativeCurrencyId: CurrencyId = ACA;
pub const IncentivesPalletId: PalletId = PalletId(*b"aca/inct");
}

ord_parameter_types! {
pub const Root: AccountId = ROOT::get();
pub const EarnShareBooster: Permill = Permill::from_percent(50);
}

impl Config for Runtime {
type Event = Event;
type RewardsSource = RewardsSource;
type AccumulatePeriod = AccumulatePeriod;
type StableCurrencyId = StableCurrencyId;
type NativeCurrencyId = GetNativeCurrencyId;
type EarnShareBooster = EarnShareBooster;
type UpdateOrigin = EnsureSignedBy<ROOT, AccountId>;
type CDPTreasury = MockCDPTreasury;
type Currency = TokensModule;
Expand Down
74 changes: 70 additions & 4 deletions modules/incentives/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,8 +436,7 @@ fn on_update_loan_works() {
(100, Default::default())
);

// share will be updated even if the adjustment is zero
OnUpdateLoan::<Runtime>::happened(&(ALICE::get(), BTC, 0, 200));
OnUpdateLoan::<Runtime>::happened(&(ALICE::get(), BTC, 100, 100));
assert_eq!(
RewardsModule::pool_infos(PoolId::Loans(BTC)),
PoolInfo {
Expand All @@ -450,7 +449,7 @@ fn on_update_loan_works() {
(200, Default::default())
);

OnUpdateLoan::<Runtime>::happened(&(BOB::get(), BTC, 100, 500));
OnUpdateLoan::<Runtime>::happened(&(BOB::get(), BTC, 600, 0));
assert_eq!(
RewardsModule::pool_infos(PoolId::Loans(BTC)),
PoolInfo {
Expand All @@ -476,7 +475,7 @@ fn on_update_loan_works() {
(150, Default::default())
);

OnUpdateLoan::<Runtime>::happened(&(BOB::get(), BTC, -650, 600));
OnUpdateLoan::<Runtime>::happened(&(BOB::get(), BTC, -600, 600));
assert_eq!(
RewardsModule::pool_infos(PoolId::Loans(BTC)),
PoolInfo {
Expand Down Expand Up @@ -938,3 +937,70 @@ fn on_initialize_should_work() {
);
});
}

#[test]
fn earning_booster_should_work() {
ExtBuilder::default().build().execute_with(|| {
OnUpdateLoan::<Runtime>::happened(&(ALICE::get(), ACA, 100, 0));
assert_eq!(
RewardsModule::pool_infos(PoolId::Loans(ACA)),
PoolInfo {
total_shares: 100,
..Default::default()
}
);
assert_eq!(
RewardsModule::shares_and_withdrawn_rewards(PoolId::Loans(ACA), ALICE::get()),
(100, Default::default())
);

OnEarningBonded::<Runtime>::happened(&(ALICE::get(), 80));
assert_eq!(
RewardsModule::pool_infos(PoolId::Loans(ACA)),
PoolInfo {
total_shares: 100 + 80 + 40,
..Default::default()
}
);
assert_eq!(
RewardsModule::shares_and_withdrawn_rewards(PoolId::Loans(ACA), ALICE::get()),
(100 + 80 + 40, Default::default())
);

OnEarningUnbonded::<Runtime>::happened(&(ALICE::get(), 20));
assert_eq!(
RewardsModule::pool_infos(PoolId::Loans(ACA)),
PoolInfo {
total_shares: 100 + 60 + 30,
..Default::default()
}
);
assert_eq!(
RewardsModule::shares_and_withdrawn_rewards(PoolId::Loans(ACA), ALICE::get()),
(100 + 60 + 30, Default::default())
);

OnUpdateLoan::<Runtime>::happened(&(ALICE::get(), ACA, -100, 100));
assert_eq!(
RewardsModule::pool_infos(PoolId::Loans(ACA)),
PoolInfo {
total_shares: 60 + 30,
..Default::default()
}
);
assert_eq!(
RewardsModule::shares_and_withdrawn_rewards(PoolId::Loans(ACA), ALICE::get()),
(60 + 30, Default::default())
);

OnEarningUnbonded::<Runtime>::happened(&(ALICE::get(), 60));
assert_eq!(
RewardsModule::pool_infos(PoolId::Loans(ACA)),
PoolInfo { ..Default::default() }
);
assert_eq!(
RewardsModule::shares_and_withdrawn_rewards(PoolId::Loans(ACA), ALICE::get()),
(0, Default::default())
);
});
}
3 changes: 3 additions & 0 deletions runtime/acala/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1229,12 +1229,15 @@ impl orml_rewards::Config for Runtime {

parameter_types! {
pub const AccumulatePeriod: BlockNumber = MINUTES;
pub const EarnShareBooster: Permill = Permill::from_percent(30);
}

impl module_incentives::Config for Runtime {
type Event = Event;
type RewardsSource = UnreleasedNativeVaultAccountId;
type StableCurrencyId = GetStableCurrencyId;
type NativeCurrencyId = GetNativeCurrencyId;
type EarnShareBooster = EarnShareBooster;
type AccumulatePeriod = AccumulatePeriod;
type UpdateOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
type CDPTreasury = CdpTreasury;
Expand Down
3 changes: 3 additions & 0 deletions runtime/karura/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1245,12 +1245,15 @@ impl orml_rewards::Config for Runtime {

parameter_types! {
pub const AccumulatePeriod: BlockNumber = MINUTES;
pub const EarnShareBooster: Permill = Permill::from_percent(30);
}

impl module_incentives::Config for Runtime {
type Event = Event;
type RewardsSource = UnreleasedNativeVaultAccountId;
type StableCurrencyId = GetStableCurrencyId;
type NativeCurrencyId = GetNativeCurrencyId;
type EarnShareBooster = EarnShareBooster;
type AccumulatePeriod = AccumulatePeriod;
type UpdateOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
type CDPTreasury = CdpTreasury;
Expand Down
9 changes: 6 additions & 3 deletions runtime/mandala/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1226,9 +1226,9 @@ parameter_types! {
impl module_earning::Config for Runtime {
type Event = Event;
type Currency = Balances;
type OnBonded = ();
type OnUnbonded = ();
type OnUnstakeFee = ();
type OnBonded = module_incentives::OnEarningBonded<Runtime>;
type OnUnbonded = module_incentives::OnEarningUnbonded<Runtime>;
type OnUnstakeFee = Treasury; // fee goes to treasury
type MinBond = ConstU128<100>;
type UnbondingPeriod = ConstU32<3>;
type InstantUnstakeFee = InstantUnstakeFee;
Expand Down Expand Up @@ -1265,12 +1265,15 @@ impl orml_rewards::Config for Runtime {

parameter_types! {
pub const AccumulatePeriod: BlockNumber = MINUTES;
pub const EarnShareBooster: Permill = Permill::from_percent(30);
}

impl module_incentives::Config for Runtime {
type Event = Event;
type RewardsSource = UnreleasedNativeVaultAccountId;
type StableCurrencyId = GetStableCurrencyId;
type NativeCurrencyId = GetNativeCurrencyId;
type EarnShareBooster = EarnShareBooster;
type AccumulatePeriod = AccumulatePeriod;
type UpdateOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
type CDPTreasury = CdpTreasury;
Expand Down