Skip to content

Commit

Permalink
tidy up
Browse files Browse the repository at this point in the history
  • Loading branch information
akildemir committed Nov 27, 2023
1 parent 42b3fe4 commit ddb957b
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 20 deletions.
8 changes: 4 additions & 4 deletions substrate/coins/pallet/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
#![cfg_attr(not(feature = "std"), no_std)]

use serai_primitives::{Coin, SubstrateAmount};
use serai_primitives::{Coin, SubstrateAmount, Balance};

pub trait AllowMint {
fn allow(coin: Coin, supply: SubstrateAmount) -> bool;
fn allow(balance: &Balance) -> bool;
}

impl AllowMint for () {
fn allow(_: Coin, _: SubstrateAmount) -> bool {
fn allow(_: &Balance) -> bool {
true
}
}
Expand Down Expand Up @@ -163,7 +163,7 @@ pub mod pallet {

// skip the economics check for lp tokens.
if TypeId::of::<I>() != TypeId::of::<LiquidityTokensInstance>() &&
!T::AllowMint::allow(balance.coin, new_supply)
!T::AllowMint::allow(&balance)
{
Err(Error::<T, I>::NotEnoughStake)?;
}
Expand Down
1 change: 1 addition & 0 deletions substrate/dex/pallet/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ pub mod pallet {
*v = None;
}
});
// TODO: delete old LastQuoteForBlock keys as well?
}

// update the oracle value
Expand Down
61 changes: 45 additions & 16 deletions substrate/validator-sets/pallet/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,8 @@ pub mod pallet {
BadSignature,
/// Validator wasn't registered or active.
NonExistentValidator,
/// Deallocation would take the stake below what is required.
NotEnoughStake,
}

#[pallet::hooks]
Expand Down Expand Up @@ -528,7 +530,16 @@ pub mod pallet {
account: T::AccountId,
amount: Amount,
) -> Result<bool, DispatchError> {
// TODO: Check it's safe to decrease this set's stake by this amount
// Check it's safe to decrease this set's stake by this amount
let new_total_staked = Self::total_allocated_stake(network)
.unwrap()
.0
.checked_sub(amount.0)
.ok_or(Error::<T>::NotEnoughAllocated)?;
let required_stake = Self::required_stake_for_network(network);
if new_total_staked < required_stake {
Err(Error::<T>::NotEnoughStake)?;
}

let old_allocation =
Self::allocation((network, account)).ok_or(Error::<T>::NonExistentValidator)?.0;
Expand Down Expand Up @@ -707,6 +718,31 @@ pub mod pallet {
validators.into_iter().map(|(id, w)| (GrandpaAuthorityId::from(id), w)).collect(),
);
}

/// Returns the required stake in terms SRI for a given `Balance`.
pub fn required_stake(balance: &Balance) -> SubstrateAmount {
// TODO: unwrap_or? We will always have an oracle value except the first block
// of each session since we have to wait for that block to end to update the window and
// the oracle value accordingly.
let price = Dex::<T>::oracle_value(balance.coin).unwrap_or(Amount(0));
let total_coin_value = balance.amount.0.saturating_mul(price.0);

// required stake formula (COIN_VALUE * 1.5) + margin(20%)
total_coin_value.saturating_mul(3).saturating_div(2).saturating_div(5)
}

/// Returns the current total required stake for a given `network`.
pub fn required_stake_for_network(network: NetworkId) -> SubstrateAmount {
let mut total_required: SubstrateAmount = 0;
// TODO: have network.coins() instead of this?
let coins = COINS.iter().filter(|c| c.network() == network).collect::<Vec<&Coin>>();
for coin in coins {
let supply = Coins::<T>::supply(coin);
total_required = total_required
.saturating_add(Self::required_stake(&Balance { coin: *coin, amount: Amount(supply) }));
}
total_required
}
}

#[pallet::call]
Expand Down Expand Up @@ -820,6 +856,7 @@ pub mod pallet {
Err(Error::DeallocationWouldRemoveFaultTolerance) |
Err(Error::NonExistentDeallocation) |
Err(Error::NonExistentValidator) |
Err(Error::NotEnoughStake) |
Err(Error::BadSignature) => Err(InvalidTransaction::BadProof)?,
Err(Error::__Ignore(_, _)) => unreachable!(),
Ok(()) => (),
Expand All @@ -840,26 +877,18 @@ pub mod pallet {
}

impl<T: Config> AllowMint for Pallet<T> {
fn allow(coin: Coin, supply: SubstrateAmount) -> bool {
let price = Dex::<T>::oracle_value(coin);
if price.is_none() {
return false;
}

let total_coin_value = supply.saturating_mul(price.unwrap().0);
let margin = total_coin_value.saturating_div(5);

// required stake formula (COIN_VALUE * 1.5) + margin
let required = total_coin_value.saturating_mul(3).saturating_div(2).saturating_add(margin);
fn allow(balance: &Balance) -> bool {
// get the required stake
let current_required = Self::required_stake_for_network(balance.coin.network());
let new_required = current_required.saturating_add(Self::required_stake(balance));

let staked = Self::total_allocated_stake(coin.network());
// get the total stake for the network
let staked = Self::total_allocated_stake(balance.coin.network());
if staked.is_none() {
return false;
}

// TODO: ETH & DAI belongs to the same network. If the coin is ETH or DAI stake should cover
// value of the both supply. Required has to take into account the other coin in that case?
staked.unwrap().0 >= required
staked.unwrap().0 >= new_required
}
}

Expand Down

0 comments on commit ddb957b

Please sign in to comment.