mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 20:29:23 +00:00
Add event emissions to the DEX pallet
This commit is contained in:
@@ -79,41 +79,43 @@ impl Call {
|
|||||||
#[derive(Clone, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)]
|
#[derive(Clone, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
/// Liquidity was added to a pool.
|
/// Liquidity was added to a pool.
|
||||||
LiquidityAdded {
|
LiquidityAddition {
|
||||||
/// The account which added the liquidity.
|
/// The account which received the minted liquidity tokens.
|
||||||
origin: SeraiAddress,
|
|
||||||
/// The account which received the liquidity tokens.
|
|
||||||
recipient: SeraiAddress,
|
recipient: SeraiAddress,
|
||||||
/// The pool liquidity was added to.
|
/// The liquidity tokens which were minted.
|
||||||
pool: ExternalCoin,
|
liquidity_tokens: ExternalBalance,
|
||||||
/// The amount of liquidity tokens which were minted.
|
|
||||||
liquidity_tokens_minted: Amount,
|
|
||||||
/// The amount of the coin which was added to the pool's liquidity.
|
|
||||||
external_coin_amount: Amount,
|
|
||||||
/// The amount of SRI which was added to the pool's liquidity.
|
/// The amount of SRI which was added to the pool's liquidity.
|
||||||
sri_amount: Amount,
|
sri_amount: Amount,
|
||||||
|
/// The amount of the coin which was added to the pool's liquidity.
|
||||||
|
external_coin_amount: Amount,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// The specified liquidity tokens were transferred.
|
||||||
|
LiquidityTransfer {
|
||||||
|
/// The address transferred from.
|
||||||
|
from: SeraiAddress,
|
||||||
|
/// The address transferred to.
|
||||||
|
to: SeraiAddress,
|
||||||
|
/// The liquidity tokens transferred.
|
||||||
|
liquidity_tokens: ExternalBalance,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Liquidity was removed from a pool.
|
/// Liquidity was removed from a pool.
|
||||||
LiquidityRemoved {
|
LiquidityRemoval {
|
||||||
/// The account which removed the liquidity.
|
/// The account which removed the liquidity.
|
||||||
origin: SeraiAddress,
|
from: SeraiAddress,
|
||||||
/// The pool liquidity was removed from.
|
/// The liquidity tokens which were burnt.
|
||||||
pool: ExternalCoin,
|
liquidity_tokens: ExternalBalance,
|
||||||
/// The mount of liquidity tokens which were burnt.
|
|
||||||
liquidity_tokens_burnt: Amount,
|
|
||||||
/// The amount of the coin which was removed from the pool's liquidity.
|
|
||||||
external_coin_amount: Amount,
|
|
||||||
/// The amount of SRI which was removed from the pool's liquidity.
|
/// The amount of SRI which was removed from the pool's liquidity.
|
||||||
sri_amount: Amount,
|
sri_amount: Amount,
|
||||||
|
/// The amount of the coin which was removed from the pool's liquidity.
|
||||||
|
external_coin_amount: Amount,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// A swap through the liquidity pools occurred.
|
/// A swap through the liquidity pools occurred.
|
||||||
Swap {
|
Swap {
|
||||||
/// The account which made the swap.
|
/// The account which made the swap.
|
||||||
origin: SeraiAddress,
|
from: SeraiAddress,
|
||||||
/// The recipient for the output of the swap.
|
|
||||||
recipient: SeraiAddress,
|
|
||||||
/// The deltas incurred by the pools.
|
/// The deltas incurred by the pools.
|
||||||
///
|
///
|
||||||
/// For a swap of sriABC to sriDEF, this would be
|
/// For a swap of sriABC to sriDEF, this would be
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ mod mock;
|
|||||||
#[expect(clippy::cast_possible_truncation)]
|
#[expect(clippy::cast_possible_truncation)]
|
||||||
#[frame_support::pallet]
|
#[frame_support::pallet]
|
||||||
mod pallet {
|
mod pallet {
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
use frame_system::pallet_prelude::*;
|
use frame_system::pallet_prelude::*;
|
||||||
use frame_support::pallet_prelude::*;
|
use frame_support::pallet_prelude::*;
|
||||||
|
|
||||||
@@ -18,7 +20,7 @@ mod pallet {
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
dex::{Error as PrimitivesError, Reserves, Premise},
|
dex::{Error as PrimitivesError, Reserves, Premise},
|
||||||
},
|
},
|
||||||
Event,
|
dex::Event,
|
||||||
};
|
};
|
||||||
|
|
||||||
use serai_core_pallet::Pallet as Core;
|
use serai_core_pallet::Pallet as Core;
|
||||||
@@ -99,10 +101,20 @@ mod pallet {
|
|||||||
let (sri_actual, external_coin_actual, liquidity) = if supply == 0 {
|
let (sri_actual, external_coin_actual, liquidity) = if supply == 0 {
|
||||||
let sri_actual = sri_intended;
|
let sri_actual = sri_intended;
|
||||||
let external_coin_actual = external_coin_intended;
|
let external_coin_actual = external_coin_intended;
|
||||||
let liquidity = Amount(
|
/*
|
||||||
u64::try_from((u128::from(sri_actual.0) * u128::from(external_coin_actual.0)).isqrt())
|
The best way to explain this is to first consider how would one would write shares of a
|
||||||
.map_err(|_| Error::<T>::Overflow)?,
|
liquidity pool with only a single coin (however purposeless that may be). The immediate
|
||||||
);
|
suggestion would simply be to use the amount of the singular coin initially added as the
|
||||||
|
initial amount of shares, with further shares being distributed pro-rata as further
|
||||||
|
liquidity is added. This inherently has the amount of liquidity tokens approximate the
|
||||||
|
magnitude and scale of the underlying coin.
|
||||||
|
|
||||||
|
When we scale the two-coin case, this methodology no longer immediately applies. The
|
||||||
|
solution here is to take the product, and then the square root, of the two values. This
|
||||||
|
provides a magnitude/scale of the liquidity tokens approximately in-between both coins.
|
||||||
|
*/
|
||||||
|
let liquidity = (u128::from(sri_actual.0) * u128::from(external_coin_actual.0)).isqrt();
|
||||||
|
let liquidity = Amount(u64::try_from(liquidity).map_err(|_| Error::<T>::Overflow)?);
|
||||||
if liquidity.0 < MINIMUM_LIQUIDITY {
|
if liquidity.0 < MINIMUM_LIQUIDITY {
|
||||||
Err(Error::<T>::InvalidLiquidity)?;
|
Err(Error::<T>::InvalidLiquidity)?;
|
||||||
}
|
}
|
||||||
@@ -149,6 +161,10 @@ mod pallet {
|
|||||||
Amount(sri_liquidity.min(external_coin_liquidity))
|
Amount(sri_liquidity.min(external_coin_liquidity))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if liquidity == Amount(0) {
|
||||||
|
Err(Error::<T>::Unsatisfied)?;
|
||||||
|
}
|
||||||
|
|
||||||
(sri_actual, external_coin_actual, liquidity)
|
(sri_actual, external_coin_actual, liquidity)
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -162,12 +178,15 @@ mod pallet {
|
|||||||
pool.into(),
|
pool.into(),
|
||||||
Balance { coin: Coin::from(external_coin), amount: external_coin_actual },
|
Balance { coin: Coin::from(external_coin), amount: external_coin_actual },
|
||||||
)?;
|
)?;
|
||||||
LiquidityTokens::<T>::mint(
|
let liquidity_tokens = ExternalBalance { coin: external_coin, amount: liquidity };
|
||||||
from,
|
LiquidityTokens::<T>::mint(from, liquidity_tokens.into())?;
|
||||||
Balance { coin: Coin::from(external_coin), amount: liquidity },
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// TODO: Event
|
Self::emit_event(Event::LiquidityAddition {
|
||||||
|
recipient: from.into(),
|
||||||
|
liquidity_tokens,
|
||||||
|
sri_amount: sri_actual,
|
||||||
|
external_coin_amount: external_coin_actual,
|
||||||
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -183,7 +202,7 @@ mod pallet {
|
|||||||
let from = ensure_signed(origin)?;
|
let from = ensure_signed(origin)?;
|
||||||
LiquidityTokens::<T>::transfer_fn(from, to.into(), liquidity_tokens.into())?;
|
LiquidityTokens::<T>::transfer_fn(from, to.into(), liquidity_tokens.into())?;
|
||||||
|
|
||||||
// TODO: Event
|
Self::emit_event(Event::LiquidityTransfer { from: from.into(), to, liquidity_tokens });
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -234,7 +253,12 @@ mod pallet {
|
|||||||
Balance { coin: Coin::from(external_coin), amount: external_coin_amount },
|
Balance { coin: Coin::from(external_coin), amount: external_coin_amount },
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// TODO: Event
|
Self::emit_event(Event::LiquidityRemoval {
|
||||||
|
from: from.into(),
|
||||||
|
liquidity_tokens,
|
||||||
|
sri_amount,
|
||||||
|
external_coin_amount,
|
||||||
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -254,6 +278,7 @@ mod pallet {
|
|||||||
|
|
||||||
let swaps = Premise::route(coins_to_swap.coin, minimum_to_receive.coin)
|
let swaps = Premise::route(coins_to_swap.coin, minimum_to_receive.coin)
|
||||||
.ok_or(Error::<T>::FromToSelf)?;
|
.ok_or(Error::<T>::FromToSelf)?;
|
||||||
|
let mut deltas = Vec::with_capacity(swaps.len() + 1);
|
||||||
for swap in &swaps {
|
for swap in &swaps {
|
||||||
let external_coin = swap.external_coin();
|
let external_coin = swap.external_coin();
|
||||||
let pool = serai_abi::dex::address(external_coin);
|
let pool = serai_abi::dex::address(external_coin);
|
||||||
@@ -273,11 +298,9 @@ mod pallet {
|
|||||||
be credited both as part of the reserves _and_ the amount in if violated.
|
be credited both as part of the reserves _and_ the amount in if violated.
|
||||||
*/
|
*/
|
||||||
assert!(transfer_from != pool, "swap routed from a coin to itself");
|
assert!(transfer_from != pool, "swap routed from a coin to itself");
|
||||||
Coins::<T>::transfer_fn(
|
let delta = Balance { coin: swap.r#in(), amount: next_amount };
|
||||||
transfer_from.into(),
|
Coins::<T>::transfer_fn(transfer_from.into(), pool.into(), delta)?;
|
||||||
pool.into(),
|
deltas.push(delta);
|
||||||
Balance { coin: swap.r#in(), amount: next_amount },
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// Update the current status
|
// Update the current status
|
||||||
transfer_from = pool;
|
transfer_from = pool;
|
||||||
@@ -290,13 +313,11 @@ mod pallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Transfer the resulting coins to the origin
|
// Transfer the resulting coins to the origin
|
||||||
Coins::<T>::transfer_fn(
|
let delta = Balance { coin: minimum_to_receive.coin, amount: next_amount };
|
||||||
transfer_from.into(),
|
Coins::<T>::transfer_fn(transfer_from.into(), origin.into(), delta)?;
|
||||||
origin.into(),
|
deltas.push(delta);
|
||||||
Balance { coin: minimum_to_receive.coin, amount: next_amount },
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// TODO: Event
|
Self::emit_event(Event::Swap { from: origin, deltas });
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -316,6 +337,7 @@ mod pallet {
|
|||||||
|
|
||||||
let swaps = Premise::route(maximum_to_swap.coin, coins_to_receive.coin)
|
let swaps = Premise::route(maximum_to_swap.coin, coins_to_receive.coin)
|
||||||
.ok_or(Error::<T>::FromToSelf)?;
|
.ok_or(Error::<T>::FromToSelf)?;
|
||||||
|
let mut deltas = Vec::with_capacity(swaps.len() + 1);
|
||||||
let mut i = swaps.len();
|
let mut i = swaps.len();
|
||||||
while {
|
while {
|
||||||
i -= 1;
|
i -= 1;
|
||||||
@@ -342,11 +364,9 @@ mod pallet {
|
|||||||
excluded when determining the reserves on the next iteration.
|
excluded when determining the reserves on the next iteration.
|
||||||
*/
|
*/
|
||||||
assert!(transfer_to != pool, "swap routed to a coin from itself");
|
assert!(transfer_to != pool, "swap routed to a coin from itself");
|
||||||
Coins::<T>::transfer_fn(
|
let delta = Balance { coin: swap.out(), amount: next_amount };
|
||||||
pool.into(),
|
Coins::<T>::transfer_fn(pool.into(), transfer_to.into(), delta)?;
|
||||||
transfer_to.into(),
|
deltas.push(delta);
|
||||||
Balance { coin: swap.out(), amount: next_amount },
|
|
||||||
)?;
|
|
||||||
|
|
||||||
transfer_to = pool;
|
transfer_to = pool;
|
||||||
next_amount = swap.quote_for_out(reserves, next_amount).map_err(Error::<T>::from)?;
|
next_amount = swap.quote_for_out(reserves, next_amount).map_err(Error::<T>::from)?;
|
||||||
@@ -360,13 +380,12 @@ mod pallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Transfer the necessary coins from the origin
|
// Transfer the necessary coins from the origin
|
||||||
Coins::<T>::transfer_fn(
|
let delta = Balance { coin: maximum_to_swap.coin, amount: next_amount };
|
||||||
origin.into(),
|
Coins::<T>::transfer_fn(origin.into(), transfer_to.into(), delta)?;
|
||||||
transfer_to.into(),
|
deltas.push(delta);
|
||||||
Balance { coin: maximum_to_swap.coin, amount: next_amount },
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// TODO: Event
|
deltas.reverse();
|
||||||
|
Self::emit_event(Event::Swap { from: origin, deltas });
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user