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

@@ -194,6 +194,11 @@ pub mod pallet {
#[pallet::getter(fn security_oracle_value)]
pub type SecurityOracleValue<T: Config> = StorageMap<_, Identity, Coin, Amount, OptionQuery>;
/// Total swap volume of a given pool in terms of SRI.
#[pallet::storage]
#[pallet::getter(fn swap_volume)]
pub type SwapVolume<T: Config> = StorageMap<_, Identity, PoolId, u64, OptionQuery>;
impl<T: Config> Pallet<T> {
fn restore_median(
coin: Coin,
@@ -373,31 +378,6 @@ pub mod pallet {
},
}
#[pallet::genesis_config]
#[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)]
pub struct GenesisConfig<T: Config> {
/// Pools to create at launch.
pub pools: Vec<Coin>,
/// field just to have T.
pub _ignore: PhantomData<T>,
}
impl<T: Config> Default for GenesisConfig<T> {
fn default() -> Self {
GenesisConfig { pools: Default::default(), _ignore: Default::default() }
}
}
#[pallet::genesis_build]
impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
fn build(&self) {
// create the pools
for coin in &self.pools {
Pallet::<T>::create_pool(*coin).unwrap();
}
}
}
#[pallet::error]
pub enum Error<T> {
/// Provided coins are equal.
@@ -510,19 +490,15 @@ pub mod pallet {
///
/// Once a pool is created, someone may [`Pallet::add_liquidity`] to it.
pub(crate) fn create_pool(coin: Coin) -> DispatchResult {
ensure!(coin != Coin::Serai, Error::<T>::EqualCoins);
// prepare pool_id
let pool_id = Self::get_pool_id(coin, Coin::Serai).unwrap();
// get pool_id
let pool_id = Self::get_pool_id(coin, Coin::Serai)?;
ensure!(!Pools::<T>::contains_key(pool_id), Error::<T>::PoolExists);
let pool_account = Self::get_pool_account(pool_id);
frame_system::Pallet::<T>::inc_providers(&pool_account);
Pools::<T>::insert(pool_id, ());
Self::deposit_event(Event::PoolCreated { pool_id, pool_account });
Ok(())
}
@@ -561,11 +537,14 @@ pub mod pallet {
) -> DispatchResult {
let sender = ensure_signed(origin)?;
ensure!((sri_desired > 0) && (coin_desired > 0), Error::<T>::WrongDesiredAmount);
ensure!(coin != Coin::Serai, Error::<T>::EqualCoins);
let pool_id = Self::get_pool_id(coin, Coin::Serai).unwrap();
let pool_id = Self::get_pool_id(coin, Coin::Serai)?;
Pools::<T>::get(pool_id).as_ref().ok_or(Error::<T>::PoolNotFound)?;
// create the pool if it doesn't exist. We can just attempt to do that because our checks
// far enough to allow that.
if Pools::<T>::get(pool_id).is_none() {
Self::create_pool(coin)?;
}
let pool_account = Self::get_pool_account(pool_id);
let sri_reserve = Self::get_balance(&pool_account, Coin::Serai);
@@ -887,9 +866,20 @@ pub mod pallet {
&to,
Balance { coin: *coin2, amount: Amount(*amount_out) },
)?;
// update the volume
let swap_volume = if *coin1 == Coin::Serai {
amounts.get(i as usize).ok_or(Error::<T>::CorrespondenceError)?
} else {
amount_out
};
let existing = SwapVolume::<T>::get(pool_id).unwrap_or(0);
let new_volume = existing.saturating_add(*swap_volume);
SwapVolume::<T>::set(pool_id, Some(new_volume));
}
i += 1;
}
Self::deposit_event(Event::SwapExecuted {
who: sender,
send_to,

View File

@@ -1155,16 +1155,8 @@ fn can_not_swap_same_coin() {
new_test_ext().execute_with(|| {
let user = system_address(b"user1").into();
let coin1 = Coin::Dai;
assert_ok!(CoinsPallet::<Test>::mint(user, Balance { coin: coin1, amount: Amount(1000) }));
let liquidity1 = 1000;
let liquidity2 = 20;
assert_noop!(
Dex::add_liquidity(RuntimeOrigin::signed(user), coin1, liquidity2, liquidity1, 1, 1, user,),
Error::<Test>::PoolNotFound
);
let exchange_amount = 10;
assert_noop!(
Dex::swap_exact_tokens_for_tokens(