Skip to content

Commit

Permalink
earning precompile (#2776)
Browse files Browse the repository at this point in the history
* earning precompile

* update EarningManager

* fix tests

* update predeploy-contracts

* fix fmt

* fix tests
  • Loading branch information
wangjj9219 authored Aug 16, 2024
1 parent 3802117 commit 71a8898
Show file tree
Hide file tree
Showing 13 changed files with 1,074 additions and 63 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions modules/earning/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ sp-std = { workspace = true }

orml-traits = { workspace = true }
primitives = { workspace = true }
module-support = { workspace = true }

[dev-dependencies]
sp-io = { workspace = true, features = ["std"] }
Expand All @@ -32,6 +33,7 @@ std = [
"sp-core/std",
"sp-runtime/std",
"sp-std/std",
"module-support/std",
]
try-runtime = [
"frame-support/try-runtime",
Expand Down
196 changes: 137 additions & 59 deletions modules/earning/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,16 @@ use frame_support::{
traits::{Currency, ExistenceRequirement, LockIdentifier, LockableCurrency, OnUnbalanced, WithdrawReasons},
};
use frame_system::pallet_prelude::*;
use module_support::EarningManager;
use orml_traits::{define_parameters, parameters::ParameterStore, Handler};
use primitives::{
bonding::{self, BondingController},
Balance,
};
use sp_runtime::{traits::Saturating, Permill};
use sp_runtime::{
traits::{Saturating, Zero},
DispatchError, Permill,
};

pub use module::*;

Expand Down Expand Up @@ -138,15 +142,8 @@ pub mod module {
pub fn bond(origin: OriginFor<T>, #[pallet::compact] amount: Balance) -> DispatchResult {
let who = ensure_signed(origin)?;

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

if let Some(change) = change {
T::OnBonded::handle(&(who.clone(), change.change))?;
Self::deposit_event(Event::Bonded {
who,
amount: change.change,
});
}
Ok(())
}

Expand All @@ -158,16 +155,7 @@ pub mod module {
pub fn unbond(origin: OriginFor<T>, #[pallet::compact] amount: Balance) -> DispatchResult {
let who = ensure_signed(origin)?;

let unbond_at = frame_system::Pallet::<T>::block_number().saturating_add(T::UnbondingPeriod::get());
let change = <Self as BondingController>::unbond(&who, amount, unbond_at)?;

if let Some(change) = change {
T::OnUnbonded::handle(&(who.clone(), change.change))?;
Self::deposit_event(Event::Unbonded {
who,
amount: change.change,
});
}
let _ = Self::do_unbond(&who, amount)?;

Ok(())
}
Expand All @@ -180,27 +168,7 @@ pub mod module {
pub fn unbond_instant(origin: OriginFor<T>, #[pallet::compact] amount: Balance) -> DispatchResult {
let who = ensure_signed(origin)?;

let fee_ratio = T::ParameterStore::get(InstantUnstakeFee).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 = fee_ratio.mul_ceil(amount);
let final_amount = amount.saturating_sub(fee);

let unbalance =
T::Currency::withdraw(&who, fee, WithdrawReasons::TRANSFER, ExistenceRequirement::KeepAlive)?;
T::OnUnstakeFee::on_unbalanced(unbalance);

// remove all shares of the change amount.
T::OnUnbonded::handle(&(who.clone(), amount))?;
Self::deposit_event(Event::InstantUnbonded {
who,
amount: final_amount,
fee,
});
}
let _ = Self::do_unbond_instant(&who, amount)?;

Ok(())
}
Expand All @@ -213,15 +181,7 @@ pub mod module {
pub fn rebond(origin: OriginFor<T>, #[pallet::compact] amount: Balance) -> DispatchResult {
let who = ensure_signed(origin)?;

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

if let Some(change) = change {
T::OnBonded::handle(&(who.clone(), change.change))?;
Self::deposit_event(Event::Rebonded {
who,
amount: change.change,
});
}
let _ = Self::do_rebond(&who, amount)?;

Ok(())
}
Expand All @@ -232,22 +192,95 @@ pub mod module {
pub fn withdraw_unbonded(origin: OriginFor<T>) -> DispatchResult {
let who = ensure_signed(origin)?;

let change =
<Self as BondingController>::withdraw_unbonded(&who, frame_system::Pallet::<T>::block_number())?;

if let Some(change) = change {
Self::deposit_event(Event::Withdrawn {
who,
amount: change.change,
});
}
let _ = Self::do_withdraw_unbonded(&who)?;

Ok(())
}
}
}

impl<T: Config> Pallet<T> {}
impl<T: Config> Pallet<T> {
fn do_bond(who: &T::AccountId, amount: Balance) -> Result<Balance, DispatchError> {
let change = <Self as BondingController>::bond(who, amount)?;

if let Some(ref change) = change {
T::OnBonded::handle(&(who.clone(), change.change))?;
Self::deposit_event(Event::Bonded {
who: who.clone(),
amount: change.change,
});
}
Ok(change.map_or(Zero::zero(), |c| c.change))
}

fn do_unbond(who: &T::AccountId, amount: Balance) -> Result<Balance, DispatchError> {
let unbond_at = frame_system::Pallet::<T>::block_number().saturating_add(T::UnbondingPeriod::get());
let change = <Self as BondingController>::unbond(who, amount, unbond_at)?;

if let Some(ref change) = change {
T::OnUnbonded::handle(&(who.clone(), change.change))?;
Self::deposit_event(Event::Unbonded {
who: who.clone(),
amount: change.change,
});
}

Ok(change.map_or(Zero::zero(), |c| c.change))
}

fn do_unbond_instant(who: &T::AccountId, amount: Balance) -> Result<Balance, DispatchError> {
let fee_ratio = T::ParameterStore::get(InstantUnstakeFee).ok_or(Error::<T>::NotAllowed)?;

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

if let Some(ref change) = change {
let amount = change.change;
let fee = fee_ratio.mul_ceil(amount);
let final_amount = amount.saturating_sub(fee);

let unbalance =
T::Currency::withdraw(who, fee, WithdrawReasons::TRANSFER, ExistenceRequirement::KeepAlive)?;
T::OnUnstakeFee::on_unbalanced(unbalance);

// remove all shares of the change amount.
T::OnUnbonded::handle(&(who.clone(), amount))?;
Self::deposit_event(Event::InstantUnbonded {
who: who.clone(),
amount: final_amount,
fee,
});
}

Ok(change.map_or(Zero::zero(), |c| c.change))
}

fn do_rebond(who: &T::AccountId, amount: Balance) -> Result<Balance, DispatchError> {
let change = <Self as BondingController>::rebond(who, amount)?;

if let Some(ref change) = change {
T::OnBonded::handle(&(who.clone(), change.change))?;
Self::deposit_event(Event::Rebonded {
who: who.clone(),
amount: change.change,
});
}

Ok(change.map_or(Zero::zero(), |c| c.change))
}

fn do_withdraw_unbonded(who: &T::AccountId) -> Result<Balance, DispatchError> {
let change = <Self as BondingController>::withdraw_unbonded(who, frame_system::Pallet::<T>::block_number())?;

if let Some(ref change) = change {
Self::deposit_event(Event::Withdrawn {
who: who.clone(),
amount: change.change,
});
}

Ok(change.map_or(Zero::zero(), |c| c.change))
}
}

impl<T: Config> BondingController for Pallet<T> {
type MinBond = T::MinBond;
Expand Down Expand Up @@ -279,3 +312,48 @@ impl<T: Config> BondingController for Pallet<T> {
}
}
}

impl<T: Config> EarningManager<T::AccountId, Balance, BondingLedgerOf<T>> for Pallet<T> {
type Moment = BlockNumberFor<T>;
type FeeRatio = Permill;

fn bond(who: T::AccountId, amount: Balance) -> Result<Balance, DispatchError> {
Self::do_bond(&who, amount)
}

fn unbond(who: T::AccountId, amount: Balance) -> Result<Balance, DispatchError> {
Self::do_unbond(&who, amount)
}

fn unbond_instant(who: T::AccountId, amount: Balance) -> Result<Balance, DispatchError> {
Self::do_unbond_instant(&who, amount)
}

fn rebond(who: T::AccountId, amount: Balance) -> Result<Balance, DispatchError> {
Self::do_rebond(&who, amount)
}

fn withdraw_unbonded(who: T::AccountId) -> Result<Balance, DispatchError> {
Self::do_withdraw_unbonded(&who)
}

fn get_bonding_ledger(who: T::AccountId) -> BondingLedgerOf<T> {
Self::ledger(who).unwrap_or_default()
}

fn get_instant_unstake_fee() -> Option<Permill> {
T::ParameterStore::get(InstantUnstakeFee)
}

fn get_min_bond() -> Balance {
T::MinBond::get()
}

fn get_unbonding_period() -> BlockNumberFor<T> {
T::UnbondingPeriod::get()
}

fn get_max_unbonding_chunks() -> u32 {
T::MaxUnbondingChunks::get()
}
}
Loading

0 comments on commit 71a8898

Please sign in to comment.