Skip to content

Commit

Permalink
allow specify incentives reward dudection currency (#2625)
Browse files Browse the repository at this point in the history
* allow specify incentives reward dudection currency

* fix

* fix

* fix
  • Loading branch information
xlc authored Oct 2, 2023
1 parent f828e76 commit 5fed183
Show file tree
Hide file tree
Showing 8 changed files with 187 additions and 8 deletions.
40 changes: 40 additions & 0 deletions modules/incentives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ pub mod module {
},
/// Payout deduction rate updated.
ClaimRewardDeductionRateUpdated { pool: PoolId, deduction_rate: Rate },
/// Payout deduction currency updated.
ClaimRewardDeductionCurrencyUpdated { pool: PoolId, currency: Option<CurrencyId> },
}

/// Mapping from pool to its fixed incentive amounts of multi currencies per period.
Expand All @@ -156,6 +158,12 @@ pub mod module {
#[pallet::storage]
pub type ClaimRewardDeductionRates<T: Config> = StorageMap<_, Twox64Concat, PoolId, FractionalRate, ValueQuery>;

/// If specified, ClaimRewardDeductionRates only apply to this currency.
///
/// ClaimRewardDeductionCurrency: map Pool => Option<RewardCurrencyId>
#[pallet::storage]
pub type ClaimRewardDeductionCurrency<T: Config> = StorageMap<_, Twox64Concat, PoolId, CurrencyId, OptionQuery>;

/// The pending rewards amount, actual available rewards amount may be deducted
///
/// PendingMultiRewards: double_map PoolId, AccountId => BTreeMap<CurrencyId, Balance>
Expand Down Expand Up @@ -338,6 +346,25 @@ pub mod module {
}
Ok(())
}

/// Update claim rewards deduction rates currency
///
/// The dispatch origin of this call must be `UpdateOrigin`.
#[pallet::call_index(5)]
#[pallet::weight(<T as Config>::WeightInfo::update_claim_reward_deduction_currency())]
pub fn update_claim_reward_deduction_currency(
origin: OriginFor<T>,
pool_id: PoolId,
currency_id: Option<CurrencyId>,
) -> DispatchResult {
T::UpdateOrigin::ensure_origin(origin)?;
ClaimRewardDeductionCurrency::<T>::mutate_exists(pool_id, |c| *c = currency_id);
Self::deposit_event(Event::ClaimRewardDeductionCurrencyUpdated {
pool: pool_id,
currency: currency_id,
});
Ok(())
}
}
}

Expand Down Expand Up @@ -393,12 +420,25 @@ impl<T: Config> Pallet<T> {
PendingMultiRewards::<T>::mutate_exists(pool_id, &who, |maybe_pending_multi_rewards| {
if let Some(pending_multi_rewards) = maybe_pending_multi_rewards {
let deduction_rate = Self::claim_reward_deduction_rates(&pool_id);
let deduction_currency = ClaimRewardDeductionCurrency::<T>::get(pool_id);

for (currency_id, pending_reward) in pending_multi_rewards.iter_mut() {
if pending_reward.is_zero() {
continue;
}

let deduction_rate = if let Some(deduction_currency) = deduction_currency {
// only apply deduction rate to specified currency
if deduction_currency == *currency_id {
deduction_rate
} else {
Zero::zero()
}
} else {
// apply deduction rate to all currencies
deduction_rate
};

let (payout_amount, deduction_amount) = {
let should_deduction_amount = deduction_rate.saturating_mul_int(*pending_reward);
(
Expand Down
5 changes: 4 additions & 1 deletion modules/incentives/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ impl ExtBuilder {
}
.assimilate_storage(&mut t)
.unwrap();
t.into()

let mut ext = sp_io::TestExternalities::new(t);
ext.execute_with(|| System::set_block_number(1));
ext
}
}
132 changes: 126 additions & 6 deletions modules/incentives/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ use sp_runtime::{traits::BadOrigin, FixedPointNumber};
#[test]
fn deposit_dex_share_works() {
ExtBuilder::default().build().execute_with(|| {
System::set_block_number(1);
assert_ok!(TokensModule::deposit(BTC_AUSD_LP, &ALICE::get(), 10000));
assert_eq!(TokensModule::free_balance(BTC_AUSD_LP, &ALICE::get()), 10000);
assert_eq!(
Expand Down Expand Up @@ -76,7 +75,6 @@ fn deposit_dex_share_works() {
#[test]
fn withdraw_dex_share_works() {
ExtBuilder::default().build().execute_with(|| {
System::set_block_number(1);
assert_ok!(TokensModule::deposit(BTC_AUSD_LP, &ALICE::get(), 10000));

assert_noop!(
Expand Down Expand Up @@ -138,7 +136,6 @@ fn withdraw_dex_share_works() {
#[test]
fn update_incentive_rewards_works() {
ExtBuilder::default().build().execute_with(|| {
System::set_block_number(1);
assert_noop!(
IncentivesModule::update_incentive_rewards(RuntimeOrigin::signed(ALICE::get()), vec![]),
BadOrigin
Expand Down Expand Up @@ -239,7 +236,6 @@ fn update_incentive_rewards_works() {
#[test]
fn update_claim_reward_deduction_rates_works() {
ExtBuilder::default().build().execute_with(|| {
System::set_block_number(1);
assert_noop!(
IncentivesModule::update_claim_reward_deduction_rates(RuntimeOrigin::signed(ALICE::get()), vec![]),
BadOrigin
Expand Down Expand Up @@ -439,7 +435,6 @@ fn payout_works() {
#[test]
fn transfer_failed_when_claim_rewards() {
ExtBuilder::default().build().execute_with(|| {
System::set_block_number(1);
assert_ok!(TokensModule::deposit(AUSD, &VAULT::get(), 27));
assert_ok!(TokensModule::deposit(DOT, &VAULT::get(), 30));
RewardsModule::add_share(&ALICE::get(), &PoolId::Loans(BTC), 100);
Expand Down Expand Up @@ -633,7 +628,6 @@ fn transfer_failed_when_claim_rewards() {
#[test]
fn claim_rewards_works() {
ExtBuilder::default().build().execute_with(|| {
System::set_block_number(1);
assert_ok!(TokensModule::deposit(ACA, &VAULT::get(), 10000));
assert_ok!(TokensModule::deposit(AUSD, &VAULT::get(), 10000));
assert_ok!(TokensModule::deposit(LDOT, &VAULT::get(), 10000));
Expand Down Expand Up @@ -1214,3 +1208,129 @@ fn transfer_reward_and_update_rewards_storage_atomically_when_accumulate_incenti
);
});
}

#[test]
fn update_claim_reward_deduction_currency() {
ExtBuilder::default().build().execute_with(|| {
assert_noop!(
IncentivesModule::update_claim_reward_deduction_currency(
RuntimeOrigin::signed(ALICE::get()),
PoolId::Dex(DOT_AUSD_LP),
Some(ACA)
),
BadOrigin
);

assert_ok!(IncentivesModule::update_claim_reward_deduction_rates(
RuntimeOrigin::signed(ROOT::get()),
vec![(PoolId::Dex(DOT_AUSD_LP), Rate::saturating_from_rational(10, 100)),]
));
assert_ok!(IncentivesModule::update_claim_reward_deduction_currency(
RuntimeOrigin::signed(ROOT::get()),
PoolId::Dex(DOT_AUSD_LP),
Some(ACA)
),);
System::assert_has_event(RuntimeEvent::IncentivesModule(
crate::Event::ClaimRewardDeductionCurrencyUpdated {
pool: PoolId::Dex(DOT_AUSD_LP),
currency: Some(ACA),
},
));

assert_eq!(
ClaimRewardDeductionCurrency::<Runtime>::get(PoolId::Dex(DOT_AUSD_LP)),
Some(ACA)
);
});
}

#[test]
fn claim_reward_deduction_currency_works() {
ExtBuilder::default().build().execute_with(|| {
let pool_id = PoolId::Dex(DOT_AUSD_LP);

assert_ok!(IncentivesModule::update_claim_reward_deduction_rates(
RuntimeOrigin::signed(ROOT::get()),
vec![(pool_id, Rate::saturating_from_rational(10, 100)),]
));
assert_ok!(IncentivesModule::update_claim_reward_deduction_currency(
RuntimeOrigin::signed(ROOT::get()),
pool_id,
Some(ACA)
));

assert_ok!(TokensModule::deposit(ACA, &VAULT::get(), 10000));
assert_ok!(TokensModule::deposit(AUSD, &VAULT::get(), 10000));

// alice add shares before accumulate rewards
RewardsModule::add_share(&ALICE::get(), &pool_id, 100);

// bob add shares before accumulate rewards
RewardsModule::add_share(&BOB::get(), &pool_id, 100);

// accumulate rewards
assert_ok!(RewardsModule::accumulate_reward(&pool_id, ACA, 1000));
assert_ok!(RewardsModule::accumulate_reward(&pool_id, AUSD, 2000));

// alice claim rewards
assert_ok!(IncentivesModule::claim_rewards(
RuntimeOrigin::signed(ALICE::get()),
pool_id
));

System::assert_has_event(RuntimeEvent::IncentivesModule(crate::Event::ClaimRewards {
who: ALICE::get(),
pool: pool_id,
reward_currency_id: ACA,
actual_amount: 450,
deduction_amount: 50,
}));
System::assert_has_event(RuntimeEvent::IncentivesModule(crate::Event::ClaimRewards {
who: ALICE::get(),
pool: pool_id,
reward_currency_id: AUSD,
actual_amount: 1000,
deduction_amount: 0,
}));

System::reset_events();

assert_eq!(TokensModule::free_balance(ACA, &ALICE::get()), 450);
assert_eq!(TokensModule::free_balance(AUSD, &ALICE::get()), 1000);

// apply deduction currency to all rewards
assert_ok!(IncentivesModule::update_claim_reward_deduction_currency(
RuntimeOrigin::signed(ROOT::get()),
pool_id,
None
));

// accumulate rewards
assert_ok!(RewardsModule::accumulate_reward(&pool_id, ACA, 1000));
assert_ok!(RewardsModule::accumulate_reward(&pool_id, AUSD, 2000));

// alice claim rewards
assert_ok!(IncentivesModule::claim_rewards(
RuntimeOrigin::signed(ALICE::get()),
pool_id
));

System::assert_has_event(RuntimeEvent::IncentivesModule(crate::Event::ClaimRewards {
who: ALICE::get(),
pool: pool_id,
reward_currency_id: ACA,
actual_amount: 473,
deduction_amount: 52,
}));
System::assert_has_event(RuntimeEvent::IncentivesModule(crate::Event::ClaimRewards {
who: ALICE::get(),
pool: pool_id,
reward_currency_id: AUSD,
actual_amount: 900,
deduction_amount: 100,
}));

assert_eq!(TokensModule::free_balance(ACA, &ALICE::get()), 923);
assert_eq!(TokensModule::free_balance(AUSD, &ALICE::get()), 1900);
});
}
7 changes: 7 additions & 0 deletions modules/incentives/src/weights.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ pub trait WeightInfo {
fn claim_rewards() -> Weight;
fn update_incentive_rewards(c: u32, ) -> Weight;
fn update_claim_reward_deduction_rates(c: u32, ) -> Weight;
fn update_claim_reward_deduction_currency() -> Weight;
}

/// Weights for module_incentives using the Acala node and recommended hardware.
Expand Down Expand Up @@ -92,6 +93,9 @@ impl<T: frame_system::Config> WeightInfo for AcalaWeight<T> {
.saturating_add(Weight::from_parts(1_829_000, 0).saturating_mul(c as u64))
.saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(c as u64)))
}
fn update_claim_reward_deduction_currency() -> Weight {
Weight::from_parts(914_000, 0)
}
}

// For backwards compatibility and tests
Expand Down Expand Up @@ -129,4 +133,7 @@ impl WeightInfo for () {
.saturating_add(Weight::from_parts(1_829_000, 0).saturating_mul(c as u64))
.saturating_add(RocksDbWeight::get().writes((1 as u64).saturating_mul(c as u64)))
}
fn update_claim_reward_deduction_currency() -> Weight {
Weight::from_parts(914_000, 0)
}
}
3 changes: 3 additions & 0 deletions runtime/acala/src/weights/module_incentives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,4 +155,7 @@ impl<T: frame_system::Config> module_incentives::WeightInfo for WeightInfo<T> {
.saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(c.into())))
.saturating_add(Weight::from_parts(0, 2475).saturating_mul(c.into()))
}
fn update_claim_reward_deduction_currency() -> Weight {
Weight::from_parts(914_000, 0)
}
}
3 changes: 3 additions & 0 deletions runtime/karura/src/weights/module_incentives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,4 +155,7 @@ impl<T: frame_system::Config> module_incentives::WeightInfo for WeightInfo<T> {
.saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(c.into())))
.saturating_add(Weight::from_parts(0, 2475).saturating_mul(c.into()))
}
fn update_claim_reward_deduction_currency() -> Weight {
Weight::from_parts(914_000, 0)
}
}
3 changes: 3 additions & 0 deletions runtime/mandala/src/weights/module_incentives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,4 +156,7 @@ impl<T: frame_system::Config> module_incentives::WeightInfo for WeightInfo<T> {
.saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(c.into())))
.saturating_add(Weight::from_parts(0, 2475).saturating_mul(c.into()))
}
fn update_claim_reward_deduction_currency() -> Weight {
Weight::from_parts(914_000, 0)
}
}
2 changes: 1 addition & 1 deletion ts-tests/tests/test-precompiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,6 @@ describeWithAcala("Acala RPC (Precompile)", (context) => {
// Passes system contract filter
from: '0x0000000000000000000100000000000000000001',
data: input,
})).to.be.rejectedWith('VM Exception while processing transaction: execution revert: invalid currencies size');
})).to.be.rejectedWith('execution reverted: invalid currencies size');
});
});

0 comments on commit 5fed183

Please sign in to comment.