Implement block emissions (#551)

* add genesis liquidity implementation

* add missing deposit event

* fix CI issues

* minor fixes

* make math safer

* fix fmt

* implement block emissions

* make remove liquidity an authorized call

* implement setting initial values for coins

* add genesis liquidity test & misc fixes

* updato develop latest

* fix rotation test

* fix licencing

* add fast-epoch feature

* only create the pool when adding liquidity first time

* add initial reward era test

* test whole pre ec security emissions

* fix clippy

* add swap-to-staked-sri feature

* rebase changes

* fix tests

* Remove accidentally commited ETH ABI files

* fix some pr comments

* Finish up fixing pr comments

* exclude SRI from is_allowed check

* Misc changes

---------

Co-authored-by: akildemir <aeg_asd@hotmail.com>
Co-authored-by: Luke Parker <lukeparker5132@gmail.com>
This commit is contained in:
akildemir
2024-08-15 06:12:04 +03:00
committed by GitHub
parent bf1c493d9a
commit cccc1fc7e6
36 changed files with 1279 additions and 302 deletions

View File

@@ -15,6 +15,7 @@ use sp_staking::offence::{ReportOffence, Offence, OffenceError};
use frame_system::{pallet_prelude::*, RawOrigin};
use frame_support::{
pallet_prelude::*,
sp_runtime::SaturatedConversion,
traits::{DisabledValidators, KeyOwnerProofSystem, FindAuthor},
BoundedVec, WeakBoundedVec, StoragePrefixedMap,
};
@@ -262,12 +263,20 @@ pub mod pallet {
_t: PhantomData<T>,
prefix: Vec<u8>,
last: Vec<u8>,
allocation_per_key_share: Amount,
}
impl<T: Config> SortedAllocationsIter<T> {
fn new(network: NetworkId) -> Self {
let mut prefix = SortedAllocations::<T>::final_prefix().to_vec();
prefix.extend(&network.encode());
Self { _t: PhantomData, prefix: prefix.clone(), last: prefix }
Self {
_t: PhantomData,
prefix: prefix.clone(),
last: prefix,
allocation_per_key_share: Pallet::<T>::allocation_per_key_share(network).expect(
"SortedAllocationsIter iterating over a network without a set allocation per key share",
),
}
}
}
impl<T: Config> Iterator for SortedAllocationsIter<T> {
@@ -275,10 +284,17 @@ pub mod pallet {
fn next(&mut self) -> Option<Self::Item> {
let next = sp_io::storage::next_key(&self.last)?;
if !next.starts_with(&self.prefix) {
return None;
None?;
}
let key = Pallet::<T>::recover_key_from_sorted_allocation_key(&next);
let amount = Pallet::<T>::recover_amount_from_sorted_allocation_key(&next);
// We may have validators present, with less than the minimum allocation, due to block
// rewards
if amount.0 < self.allocation_per_key_share.0 {
None?;
}
self.last = next;
Some((key, amount))
}
@@ -309,6 +325,12 @@ pub mod pallet {
#[pallet::storage]
pub type SeraiDisabledIndices<T: Config> = StorageMap<_, Identity, u32, Public, OptionQuery>;
/// Mapping from session to its starting block number.
#[pallet::storage]
#[pallet::getter(fn session_begin_block)]
pub type SessionBeginBlock<T: Config> =
StorageDoubleMap<_, Identity, NetworkId, Identity, Session, u64, ValueQuery>;
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
@@ -391,6 +413,11 @@ pub mod pallet {
Pallet::<T>::deposit_event(Event::NewSet { set });
Participants::<T>::set(network, Some(participants.try_into().unwrap()));
SessionBeginBlock::<T>::set(
network,
session,
<frame_system::Pallet<T>>::block_number().saturated_into::<u64>(),
);
}
}
@@ -490,11 +517,13 @@ pub mod pallet {
network: NetworkId,
account: T::AccountId,
amount: Amount,
block_reward: bool,
) -> DispatchResult {
let old_allocation = Self::allocation((network, account)).unwrap_or(Amount(0)).0;
let new_allocation = old_allocation + amount.0;
let allocation_per_key_share = Self::allocation_per_key_share(network).unwrap().0;
if new_allocation < allocation_per_key_share {
// If this is a block reward, we always allow it to be allocated
if (new_allocation < allocation_per_key_share) && (!block_reward) {
Err(Error::<T>::InsufficientAllocation)?;
}
@@ -819,6 +848,21 @@ pub mod pallet {
total_required
}
pub fn distribute_block_rewards(
network: NetworkId,
account: T::AccountId,
amount: Amount,
) -> DispatchResult {
// TODO: Should this call be part of the `increase_allocation` since we have to have it
// before each call to it?
Coins::<T>::transfer_internal(
account,
Self::account(),
Balance { coin: Coin::Serai, amount },
)?;
Self::increase_allocation(network, account, amount, true)
}
fn can_slash_serai_validator(validator: Public) -> bool {
// Checks if they're active or actively deallocating (letting us still slash them)
// We could check if they're upcoming/still allocating, yet that'd mean the equivocation is
@@ -966,7 +1010,7 @@ pub mod pallet {
Self::account(),
Balance { coin: Coin::Serai, amount },
)?;
Self::increase_allocation(network, validator, amount)
Self::increase_allocation(network, validator, amount, false)
}
#[pallet::call_index(3)]