Skip to content

Commit

Permalink
add earning to Karura & Acala (#2558)
Browse files Browse the repository at this point in the history
* add earning to Karura & Acala

* fix

* remove earn booster

* fix

* make instant unstake optional
  • Loading branch information
xlc authored Jul 3, 2023
1 parent 34b1d74 commit a35964e
Show file tree
Hide file tree
Showing 15 changed files with 100 additions and 88 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions modules/earning/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ pub mod module {
#[pallet::constant]
type UnbondingPeriod: Get<Self::BlockNumber>;
#[pallet::constant]
type InstantUnstakeFee: Get<Permill>;
type InstantUnstakeFee: Get<Option<Permill>>;
#[pallet::constant]
type MaxUnbondingChunks: Get<u32>;
#[pallet::constant]
Expand All @@ -80,6 +80,7 @@ pub mod module {
BelowMinBondThreshold,
MaxUnlockChunksExceeded,
NotBonded,
NotAllowed,
}

#[pallet::event]
Expand Down Expand Up @@ -177,11 +178,13 @@ pub mod module {
pub fn unbond_instant(origin: OriginFor<T>, #[pallet::compact] amount: Balance) -> DispatchResult {
let who = ensure_signed(origin)?;

let fee_ratio = T::InstantUnstakeFee::get().ok_or(Error::<T>::NotAllowed)?;

let change = <Self as BondingController>::unbond_instant(&who, amount)?;

if let Some(change) = change {
let amount = change.change;
let fee = T::InstantUnstakeFee::get().mul_ceil(amount);
let fee = fee_ratio.mul_ceil(amount);
let final_amount = amount.saturating_sub(fee);

let unbalance =
Expand Down
2 changes: 1 addition & 1 deletion modules/earning/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ impl pallet_balances::Config for Runtime {
}

parameter_types! {
pub const InstantUnstakeFee: Permill = Permill::from_percent(10);
pub const InstantUnstakeFee: Option<Permill> = Some(Permill::from_percent(10));
pub const EarningLockIdentifier: LockIdentifier = *b"12345678";
}

Expand Down
12 changes: 3 additions & 9 deletions modules/incentives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ use orml_traits::{Happened, MultiCurrency, RewardHandler};
use primitives::{Amount, Balance, CurrencyId};
use sp_runtime::{
traits::{AccountIdConversion, UniqueSaturatedInto, Zero},
DispatchResult, FixedPointNumber, Permill,
DispatchResult, FixedPointNumber,
};
use sp_std::{collections::btree_map::BTreeMap, prelude::*};
use support::{DEXIncentives, EmergencyShutdown, FractionalRate, IncentivesManager, PoolId, Rate};
Expand Down Expand Up @@ -80,10 +80,6 @@ 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::RuntimeOrigin>;

Expand Down Expand Up @@ -574,15 +570,13 @@ 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);
<orml_rewards::Pallet<T>>::add_share(who, &PoolId::Earning(T::NativeCurrencyId::get()), *amount);
}
}

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);
<orml_rewards::Pallet<T>>::remove_share(who, &PoolId::Earning(T::NativeCurrencyId::get()), *amount);
}
}
2 changes: 0 additions & 2 deletions modules/incentives/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,15 +140,13 @@ parameter_types! {

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

impl Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type RewardsSource = RewardsSource;
type AccumulatePeriod = ConstU64<10>;
type NativeCurrencyId = GetNativeCurrencyId;
type EarnShareBooster = EarnShareBooster;
type UpdateOrigin = EnsureSignedBy<ROOT, AccountId>;
type Currency = TokensModule;
type EmergencyShutdown = MockEmergencyShutdown;
Expand Down
48 changes: 11 additions & 37 deletions modules/incentives/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1072,67 +1072,41 @@ fn on_initialize_should_work() {
}

#[test]
fn earning_booster_should_work() {
fn earning_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)),
RewardsModule::pool_infos(PoolId::Earning(ACA)),
PoolInfo {
total_shares: 100 + 80 + 40,
total_shares: 80,
..Default::default()
}
);
assert_eq!(
RewardsModule::shares_and_withdrawn_rewards(PoolId::Loans(ACA), ALICE::get()),
(100 + 80 + 40, Default::default())
RewardsModule::shares_and_withdrawn_rewards(PoolId::Earning(ACA), ALICE::get()),
(80, 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)),
RewardsModule::pool_infos(PoolId::Earning(ACA)),
PoolInfo {
total_shares: 60 + 30,
total_shares: 60,
..Default::default()
}
);
assert_eq!(
RewardsModule::shares_and_withdrawn_rewards(PoolId::Loans(ACA), ALICE::get()),
(60 + 30, Default::default())
RewardsModule::shares_and_withdrawn_rewards(PoolId::Earning(ACA), ALICE::get()),
(60, Default::default())
);

OnEarningUnbonded::<Runtime>::happened(&(ALICE::get(), 60));
assert_eq!(
RewardsModule::pool_infos(PoolId::Loans(ACA)),
RewardsModule::pool_infos(PoolId::Earning(ACA)),
PoolInfo { ..Default::default() }
);
assert_eq!(
RewardsModule::shares_and_withdrawn_rewards(PoolId::Loans(ACA), ALICE::get()),
RewardsModule::shares_and_withdrawn_rewards(PoolId::Earning(ACA), ALICE::get()),
(0, Default::default())
);
});
Expand Down
3 changes: 3 additions & 0 deletions modules/support/src/incentives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ pub enum PoolId {

/// Rewards and shares pool for DEX makers who stake LP token(LPCurrencyId)
Dex(CurrencyId),

/// Rewards and shares pool for earning module
Earning(CurrencyId),
}

pub trait IncentivesManager<AccountId, Balance, CurrencyId, PoolId> {
Expand Down
2 changes: 1 addition & 1 deletion predeploy-contracts
26 changes: 15 additions & 11 deletions runtime/acala/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,7 @@ orml-xcm = { path = "../../orml/xcm", default-features = false }
orml-utilities = { path = "../../orml/utilities", default-features = false }

# modules
module-transaction-pause = { path = "../../modules/transaction-pause", default-features = false }
module-transaction-payment = { path = "../../modules/transaction-payment", default-features = false }
module-aggregated-dex = { path = "../../modules/aggregated-dex", default-features = false }
module-asset-registry = { path = "../../modules/asset-registry", default-features = false }
module-auction-manager = { path = "../../modules/auction-manager", default-features = false }
module-cdp-engine = { path = "../../modules/cdp-engine", default-features = false }
Expand All @@ -100,24 +99,26 @@ module-collator-selection = { path = "../../modules/collator-selection", default
module-currencies = { path = "../../modules/currencies", default-features = false }
module-dex = { path = "../../modules/dex", default-features = false }
module-dex-oracle = { path = "../../modules/dex-oracle", default-features = false }
module-earning = { path = "../../modules/earning", default-features = false }
module-emergency-shutdown = { path = "../../modules/emergency-shutdown", default-features = false }
module-evm = { path = "../../modules/evm", default-features = false }
module-evm-accounts = { path = "../../modules/evm-accounts", default-features = false }
module-evm-bridge = { path = "../../modules/evm-bridge", default-features = false }
module-evm-rpc-runtime-api = { path = "../../modules/evm/rpc/runtime_api", default-features = false }
module-homa = { path = "../../modules/homa", default-features = false }
module-honzon = { path = "../../modules/honzon", default-features = false }
module-idle-scheduler = { path = "../../modules/idle-scheduler", default-features = false }
module-incentives = { path = "../../modules/incentives", default-features = false }
module-liquid-crowdloan = { path = "../../modules/liquid-crowdloan", default-features = false }
module-loans = { path = "../../modules/loans", default-features = false }
module-nft = { path = "../../modules/nft", default-features = false }
module-prices = { path = "../../modules/prices", default-features = false }
module-incentives = { path = "../../modules/incentives", default-features = false }
module-relaychain = { path = "../../modules/relaychain", default-features = false, features = ["polkadot"] }
module-session-manager = { path = "../../modules/session-manager", default-features = false }
module-support = { path = "../../modules/support", default-features = false }
module-homa = { path = "../../modules/homa", default-features = false }
module-transaction-pause = { path = "../../modules/transaction-pause", default-features = false }
module-transaction-payment = { path = "../../modules/transaction-payment", default-features = false }
module-xcm-interface = { path = "../../modules/xcm-interface", default-features = false }
module-session-manager = { path = "../../modules/session-manager", default-features = false }
module-relaychain = { path = "../../modules/relaychain", default-features = false, features = ["polkadot"] }
module-idle-scheduler = { path = "../../modules/idle-scheduler", default-features = false }
module-aggregated-dex = { path = "../../modules/aggregated-dex", default-features = false }
module-liquid-crowdloan = { path = "../../modules/liquid-crowdloan", default-features = false }

primitives = { package = "acala-primitives", path = "../../primitives", default-features = false }
runtime-common = { path = "../common", default-features = false }
Expand Down Expand Up @@ -231,6 +232,7 @@ std = [
"module-currencies/std",
"module-dex-oracle/std",
"module-dex/std",
"module-earning/std",
"module-emergency-shutdown/std",
"module-evm-accounts/std",
"module-evm-bridge/std",
Expand All @@ -240,6 +242,7 @@ std = [
"module-honzon/std",
"module-idle-scheduler/std",
"module-incentives/std",
"module-liquid-crowdloan/std",
"module-loans/std",
"module-nft/std",
"module-prices/std",
Expand All @@ -249,7 +252,7 @@ std = [
"module-transaction-pause/std",
"module-transaction-payment/std",
"module-xcm-interface/std",
"module-liquid-crowdloan/std",

"primitives/std",
"runtime-common/std",

Expand Down Expand Up @@ -369,6 +372,7 @@ try-runtime = [
"module-currencies/try-runtime",
"module-dex-oracle/try-runtime",
"module-dex/try-runtime",
"module-earning/try-runtime",
"module-emergency-shutdown/try-runtime",
"module-evm-accounts/try-runtime",
"module-evm-bridge/try-runtime",
Expand All @@ -377,14 +381,14 @@ try-runtime = [
"module-honzon/try-runtime",
"module-idle-scheduler/try-runtime",
"module-incentives/try-runtime",
"module-liquid-crowdloan/try-runtime",
"module-loans/try-runtime",
"module-nft/try-runtime",
"module-prices/try-runtime",
"module-session-manager/try-runtime",
"module-transaction-pause/try-runtime",
"module-transaction-payment/try-runtime",
"module-xcm-interface/try-runtime",
"module-liquid-crowdloan/try-runtime",

"primitives/try-runtime",

Expand Down
30 changes: 22 additions & 8 deletions runtime/acala/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1243,20 +1243,12 @@ impl orml_rewards::Config for Runtime {

parameter_types! {
pub const AccumulatePeriod: BlockNumber = MINUTES;
pub const EarnShareBooster: Permill = Permill::from_percent(30);
pub const GetAusdIbtcPoolId: PoolId = PoolId::Dex(
CurrencyId::DexShare(
DexShare::Token(TokenSymbol::AUSD),
DexShare::ForeignAsset(3)
)
);
}

impl module_incentives::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type RewardsSource = UnreleasedNativeVaultAccountId;
type NativeCurrencyId = GetNativeCurrencyId;
type EarnShareBooster = EarnShareBooster;
type AccumulatePeriod = AccumulatePeriod;
type UpdateOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
type Currency = Currencies;
Expand Down Expand Up @@ -1672,6 +1664,27 @@ impl module_liquid_crowdloan::Config for Runtime {
type WeightInfo = weights::module_liquid_crowdloan::WeightInfo<Runtime>;
}

parameter_types! {
pub const InstantUnstakeFee: Option<Permill> = None;
pub MinBond: Balance = 100 * dollar(ACA);
pub const UnbondingPeriod: BlockNumber = 28 * DAYS;
pub const EarningLockIdentifier: LockIdentifier = *b"aca/earn";
}

impl module_earning::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Currency = Balances;
type OnBonded = module_incentives::OnEarningBonded<Runtime>;
type OnUnbonded = module_incentives::OnEarningUnbonded<Runtime>;
type OnUnstakeFee = Treasury; // fee goes to treasury
type MinBond = MinBond;
type UnbondingPeriod = UnbondingPeriod;
type InstantUnstakeFee = InstantUnstakeFee;
type MaxUnbondingChunks = ConstU32<10>;
type LockIdentifier = EarningLockIdentifier;
type WeightInfo = ();
}

construct_runtime!(
pub enum Runtime where
Block = Block,
Expand Down Expand Up @@ -1750,6 +1763,7 @@ construct_runtime!(
Dex: module_dex = 91,
DexOracle: module_dex_oracle = 92,
AggregatedDex: module_aggregated_dex = 93,
Earning: module_earning = 94,

// Honzon
AuctionManager: module_auction_manager = 100,
Expand Down
4 changes: 1 addition & 3 deletions runtime/common/src/precompile/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ use scale_info::TypeInfo;
use sp_core::{H160, H256};
use sp_runtime::{
traits::{AccountIdConversion, BlakeTwo256, BlockNumberProvider, Convert, IdentityLookup, One as OneT, Zero},
AccountId32, DispatchResult, FixedPointNumber, FixedU128, Perbill, Percent, Permill,
AccountId32, DispatchResult, FixedPointNumber, FixedU128, Perbill, Percent,
};
use sp_std::prelude::*;
use xcm::{prelude::*, v3::Xcm};
Expand Down Expand Up @@ -740,7 +740,6 @@ parameter_types! {
}

ord_parameter_types! {
pub const EarnShareBooster: Permill = Permill::from_percent(50);
pub const RewardsSource: AccountId = REWARDS_SOURCE;
}

Expand All @@ -749,7 +748,6 @@ impl module_incentives::Config for Test {
type RewardsSource = RewardsSource;
type AccumulatePeriod = ConstU32<10>;
type NativeCurrencyId = GetNativeCurrencyId;
type EarnShareBooster = EarnShareBooster;
type UpdateOrigin = EnsureSignedBy<One, AccountId>;
type Currency = Tokens;
type EmergencyShutdown = MockEmergencyShutdown;
Expand Down
2 changes: 1 addition & 1 deletion runtime/common/src/precompile/schedule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ mod tests {
run_to_block(5);
#[cfg(not(feature = "with-ethereum-compatibility"))]
{
assert_eq!(Balances::free_balance(from_account.clone()), 999999944068);
assert_eq!(Balances::free_balance(from_account.clone()), 999999944095);
assert_eq!(Balances::reserved_balance(from_account), 0);
assert_eq!(Balances::free_balance(to_account), 1000000001000);
}
Expand Down
Loading

0 comments on commit a35964e

Please sign in to comment.