Skip to content

Commit

Permalink
Merge pull request moonbeam-foundation#2 from mangata-finance/feature…
Browse files Browse the repository at this point in the history
…/staking-add-remove-using-paired-token

MultiTokenParachainStaking - Use PairedOrLiquidityToken to add or rem…
  • Loading branch information
gleb-urvanov authored Dec 17, 2021
2 parents 9fa4e52 + c970830 commit b9218b1
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 85 deletions.
48 changes: 24 additions & 24 deletions Cargo.lock

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

4 changes: 2 additions & 2 deletions pallets/parachain-staking/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ substrate-fixed = { git = "https://github.com/encointer/substrate-fixed", defaul

pallet-xyk = { default-features = false, git = "https://github.com/mangata-finance/mangata-node", branch = "mangata-dev-v4" }
mangata-primitives = { git = "https://github.com/mangata-finance/mangata-node", branch = "mangata-dev-v4", default-features = false }
orml-tokens = { default-features = false, version = '0.4.1-dev', git = "https://github.com/mangata-finance/open-runtime-module-library", branch = "mangata-dev" }
orml-tokens = { default-features = false, version = '0.4.1-dev', git = "https://github.com/mangata-finance/open-runtime-module-library", branch = "mangata-dev-v4" }


[dev-dependencies]
similar-asserts = "1.1.0"

orml-traits = { default-features = false, version = "0.4.1-dev", git = "https://github.com/mangata-finance/open-runtime-module-library", branch = "mangata-dev" }
orml-traits = { default-features = false, version = "0.4.1-dev", git = "https://github.com/mangata-finance/open-runtime-module-library", branch = "mangata-dev-v4" }
pallet-assets-info = { default-features = false, git = "https://github.com/mangata-finance/mangata-node", branch = "mangata-dev-v4" }
sp-core = { git = "https://github.com/mangata-finance/substrate", branch = "mangata-dev-v4" }
sp-io = { git = "https://github.com/mangata-finance/substrate", branch = "mangata-dev-v4" }
Expand Down
3 changes: 1 addition & 2 deletions pallets/parachain-staking/src/inflation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
// along with Moonbeam. If not, see <http://www.gnu.org/licenses/>.

//! Helper methods for computing issuance based on inflation
use crate::pallet::{Balance, Config, Pallet, TokenId, Get, MultiTokenCurrency};
use frame_support::traits::Currency;
use crate::pallet::{Balance, Config, Pallet, Get, MultiTokenCurrency};
use parity_scale_codec::{Decode, Encode};
use scale_info::TypeInfo;
#[cfg(feature = "std")]
Expand Down
91 changes: 50 additions & 41 deletions pallets/parachain-staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,20 +58,19 @@ pub mod weights;
use frame_support::pallet;
pub use inflation::{InflationInfo, Range};
use weights::WeightInfo;
use sp_runtime::FixedU128;
pub use mangata_primitives::{Balance, TokenId};
use orml_tokens::{MultiTokenCurrency, MultiTokenReservableCurrency};
use pallet_xyk::Valuate;

use crate::{set::OrderedSet};
use frame_support::pallet_prelude::*;
use frame_support::traits::{Currency, Get, Imbalance, ReservableCurrency, EstimateNextSessionRotation};
use frame_support::traits::{Get, Imbalance, EstimateNextSessionRotation};
use frame_system::pallet_prelude::*;
use frame_system::RawOrigin;
use parity_scale_codec::{Decode, Encode};
use scale_info::TypeInfo;
use sp_runtime::{
traits::{AtLeast32BitUnsigned, Saturating, Zero, One},
traits::{Saturating, Zero, One},
Perbill, Permill, Percent, RuntimeDebug,
helpers_128bit::multiply_by_rational,
};
Expand All @@ -89,6 +88,12 @@ pub mod pallet {
#[pallet::pallet]
pub struct Pallet<T>(PhantomData<T>);

#[derive(Eq, PartialEq, Clone, Encode, Decode, RuntimeDebug, TypeInfo,)]
pub enum PairedOrLiquidityToken{
Paired(TokenId),
Liquidity(TokenId),
}

#[derive(Default, Clone, Encode, Decode, RuntimeDebug, TypeInfo,)]
pub struct Bond<AccountId> {
pub owner: AccountId,
Expand Down Expand Up @@ -688,8 +693,6 @@ pub mod pallet {
self.status = DelegatorStatus::Active
}
pub fn add_delegation(&mut self, bond: Bond<A>) -> bool {
let amt = bond.amount;
let liquidity_token = bond.liquidity_token;
if self.delegations.insert(bond) {
true
} else {
Expand All @@ -700,22 +703,20 @@ pub mod pallet {
// Return None if delegation not found
pub fn rm_delegation(&mut self, collator: A) -> Option<usize> {
let mut amt: Option<Balance> = None;
let mut liquidity_token_option: Option<TokenId> = None;
let delegations = self
.delegations
.0
.iter()
.filter_map(|x| {
if x.owner == collator {
amt = Some(x.amount);
liquidity_token_option = Some(x.liquidity_token);
None
} else {
Some(x.clone())
}
})
.collect();
if let ( Some(liquidity_token), Some(balance)) = (liquidity_token_option, amt) {
if let Some(_) = amt {
self.delegations = OrderedSet::from(delegations);
Some(self.delegations.0.len())
} else {
Expand All @@ -731,7 +732,7 @@ pub mod pallet {
where
T::AccountId: From<A>,
{
let Bond { liquidity_token: liquidity_token, .. } = self
let Bond { liquidity_token, .. } = self
.delegations
.0
.iter()
Expand All @@ -743,7 +744,7 @@ pub mod pallet {
Error::<T>::InsufficientBalance
);
let when = <Round<T>>::get().current + T::DelegationBondDelay::get();
self.requests.bond_more::<T>(collator, more, when, *liquidity_token)?;
self.requests.bond_more::<T>(collator, more, when)?;
Ok(when)
}
/// Schedule decrease delegation
Expand All @@ -756,7 +757,7 @@ pub mod pallet {
Balance: Into<Balance> + From<Balance>,
{
// get delegation amount
let Bond { amount: amount, liquidity_token: liquidity_token, owner: _ } = self
let Bond { amount, .. } = self
.delegations
.0
.iter()
Expand All @@ -767,7 +768,7 @@ pub mod pallet {
Error::<T>::DelegationBelowMin
);
let when = <Round<T>>::get().current + T::DelegationBondDelay::get();
self.requests.bond_less::<T>(collator, less, when, *liquidity_token)?;
self.requests.bond_less::<T>(collator, less, when)?;
Ok(when)
}
/// Schedule revocation for the given collator
Expand All @@ -779,7 +780,7 @@ pub mod pallet {
Balance: Into<Balance>,
{
// get delegation amount
let Bond { amount: amount, liquidity_token: liquidity_token, owner: _ } = self
let Bond { amount, .. } = self
.delegations
.0
.iter()
Expand All @@ -788,7 +789,7 @@ pub mod pallet {
let now = <Round<T>>::get().current;
let when = now + T::RevokeDelegationDelay::get();
// add revocation to pending requests
self.requests.revoke::<T>(collator, *amount, when, *liquidity_token)?;
self.requests.revoke::<T>(collator, *amount, when)?;
Ok((now, when))
}
/// Execute pending delegation change request
Expand Down Expand Up @@ -984,8 +985,7 @@ pub mod pallet {
&mut self,
collator: A,
amount: Balance,
when_executable: RoundIndex,
liquidity_token: TokenId,
when_executable: RoundIndex
) -> DispatchResult {
ensure!(
self.requests.get(&collator).is_none(),
Expand All @@ -1009,8 +1009,7 @@ pub mod pallet {
&mut self,
collator: A,
amount: Balance,
when_executable: RoundIndex,
liquidity_token: TokenId,
when_executable: RoundIndex
) -> DispatchResult {
ensure!(
self.requests.get(&collator).is_none(),
Expand All @@ -1034,8 +1033,7 @@ pub mod pallet {
&mut self,
collator: A,
amount: Balance,
when_executable: RoundIndex,
liquidity_token: TokenId,
when_executable: RoundIndex
) -> DispatchResult {
ensure!(
self.requests.get(&collator).is_none(),
Expand Down Expand Up @@ -1474,7 +1472,7 @@ pub mod pallet {
for (i, liquidity_token) in liquidity_token_list.iter().enumerate(){
if let Err(error) = <Pallet<T>>::add_staking_liquidity_token(
RawOrigin::Root.into(),
*liquidity_token,
PairedOrLiquidityToken::Liquidity(*liquidity_token),
i as u32,
) {
log::warn!("Adding staking liquidity token failed in genesis with error {:?}", error);
Expand Down Expand Up @@ -2148,11 +2146,17 @@ pub mod pallet {
#[pallet::weight(100_000)]
pub fn add_staking_liquidity_token(
origin: OriginFor<T>,
added_liquidity_token: TokenId,
paired_or_liquidity_token: PairedOrLiquidityToken,
current_liquidity_tokens: u32,
) -> DispatchResultWithPostInfo {
ensure_root(origin)?;
<StakingLiquidityTokens<T>>::try_mutate(|staking_liquidity_tokens| -> DispatchResult {

let added_liquidity_token:TokenId = match paired_or_liquidity_token {
PairedOrLiquidityToken::Paired(x) => T::StakingLiquidityTokenValuator::get_liquidity_asset(x.into(), T::NativeTokenId::get().into())?,
PairedOrLiquidityToken::Liquidity(x) => x,
};

StakingLiquidityTokens::<T>::try_mutate(|staking_liquidity_tokens| -> DispatchResult {
ensure!(
current_liquidity_tokens as usize >= staking_liquidity_tokens.len(),
Error::<T>::TooLowCurrentStakingLiquidityTokensCount
Expand All @@ -2170,11 +2174,17 @@ pub mod pallet {
#[pallet::weight(100_000)]
pub fn remove_staking_liquidity_token(
origin: OriginFor<T>,
removed_liquidity_token: TokenId,
paired_or_liquidity_token: PairedOrLiquidityToken,
current_liquidity_tokens: u32,
) -> DispatchResultWithPostInfo {
ensure_root(origin)?;
<StakingLiquidityTokens<T>>::try_mutate(|staking_liquidity_tokens| -> DispatchResult {

let removed_liquidity_token: TokenId = match paired_or_liquidity_token {
PairedOrLiquidityToken::Paired(x) => T::StakingLiquidityTokenValuator::get_liquidity_asset(x.into(), T::NativeTokenId::get().into())?,
PairedOrLiquidityToken::Liquidity(x) => x,
};

StakingLiquidityTokens::<T>::try_mutate(|staking_liquidity_tokens| -> DispatchResult {
ensure!(
current_liquidity_tokens as usize >= staking_liquidity_tokens.len(),
Error::<T>::TooLowCurrentStakingLiquidityTokensCount
Expand Down Expand Up @@ -2265,20 +2275,19 @@ pub mod pallet {
// reserve portion of issuance for parachain bond account
let bond_config = <ParachainBondInfo<T>>::get();
let parachain_bond_reserve = bond_config.percent * total_issuance;
if let imb =
T::Currency::deposit_creating(T::NativeTokenId::get().into(), &bond_config.account, parachain_bond_reserve.into())
{
// update round issuance iff transfer succeeds
left_issuance -= imb.peek().into();
Self::deposit_event(Event::ReservedForParachainBond(
bond_config.account,
imb.peek().into(),
));
}
let imb =
T::Currency::deposit_creating(T::NativeTokenId::get().into(), &bond_config.account, parachain_bond_reserve.into());
// update round issuance iff transfer succeeds
left_issuance -= imb.peek().into();
Self::deposit_event(Event::ReservedForParachainBond(
bond_config.account,
imb.peek().into(),
));
let mint = |amt: Balance, to: T::AccountId| {
if let amount_transferred = T::Currency::deposit_creating(T::NativeTokenId::get().into(), &to, amt.into()) {
Self::deposit_event(Event::Rewarded(to.clone(), amount_transferred.peek().into()));
}
let amount_transferred = T::Currency::deposit_creating(T::NativeTokenId::get().into(), &to, amt.into());
Self::deposit_event(Event::Rewarded(to.clone(), amount_transferred.peek().into()));
};
// only pay out rewards at the end to transfer only total amount due
let mut due_rewards: BTreeMap<T::AccountId, Balance> = BTreeMap::new();
Expand Down Expand Up @@ -2329,7 +2338,7 @@ pub mod pallet {
/// Compute the top `TotalSelected` candidates in the CandidatePool and return
/// a vec of their AccountIds (in the order of selection)
pub fn compute_top_candidates() -> (Vec<(T::AccountId, Balance)>, Balance) {
let mut candidates = <CandidatePool<T>>::get().0;
let candidates = <CandidatePool<T>>::get().0;
let staking_liquidity_tokens = <StakingLiquidityTokens<T>>::get();

// morph amount in candidates to exposure in mga
Expand Down Expand Up @@ -2417,7 +2426,7 @@ pub mod pallet {
}

impl<T: Config> pallet_session::SessionManager<T::AccountId> for Pallet<T> {
fn new_session(index: SessionIndex) -> Option<Vec<T::AccountId>> {
fn new_session(_: SessionIndex) -> Option<Vec<T::AccountId>> {
Some(Self::selected_candidates())
}
fn start_session(_: SessionIndex) {
Expand All @@ -2428,7 +2437,7 @@ pub mod pallet {
// pay all stakers for T::RewardPaymentDelay rounds ago
Self::pay_stakers(round.current);
// select top collator candidates for next round
let (collator_count, delegation_count, total_relevant_exposure, total_round_exposure) =
let (collator_count, _delegation_count, total_relevant_exposure, total_round_exposure) =
Self::select_top_candidates(round.current.saturating_add(One::one()));
// start next round
<Round<T>>::put(round);
Expand Down
19 changes: 13 additions & 6 deletions pallets/parachain-staking/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,23 +178,30 @@ impl Valuate for TestTokenValuator {

type CurrencyId = TokenId;

fn get_liquidity_asset(
first_asset_id: Self::CurrencyId,
_second_asset_id: Self::CurrencyId,
) -> Result<TokenId, DispatchError> {
Ok(first_asset_id/100)
}

fn get_liquidity_token_mga_pool(
liquidity_token_id: Self::CurrencyId,
_liquidity_token_id: Self::CurrencyId,
) -> Result<(Self::CurrencyId, Self::CurrencyId), DispatchError> {
unimplemented!("Not required in tests!")
}

fn valuate_liquidity_token(
liquidity_token_id: Self::CurrencyId,
liquidity_token_amount: Self::Balance,
_liquidity_token_id: Self::CurrencyId,
_liquidity_token_amount: Self::Balance,
) -> Self::Balance {
unimplemented!("Not required in tests!")
}

fn scale_liquidity_by_mga_valuation(
mga_valuation: Self::Balance,
liquidity_token_amount: Self::Balance,
mga_token_amount: Self::Balance,
_mga_valuation: Self::Balance,
_liquidity_token_amount: Self::Balance,
_mga_token_amount: Self::Balance,
) -> Self::Balance {
unimplemented!("Not required in tests!")
}
Expand Down
Loading

0 comments on commit b9218b1

Please sign in to comment.