Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion common/src/currency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,9 @@ macro_rules! impl_approx {
};
}

pub trait Currency: ToFixed + Into<u64> + From<u64> + Clone + Copy {
pub trait Currency:
ToFixed + Into<u64> + From<u64> + Clone + Copy + Eq + Ord + PartialEq + PartialOrd + Display
{
const MAX: Self;
const ZERO: Self;

Expand Down
12 changes: 6 additions & 6 deletions common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,14 +169,18 @@ impl Default for ProxyType {
}

pub trait SubnetInfo<AccountId> {
fn tao_reserve(netuid: NetUid) -> TaoCurrency;
fn alpha_reserve(netuid: NetUid) -> AlphaCurrency;
fn exists(netuid: NetUid) -> bool;
fn mechanism(netuid: NetUid) -> u16;
fn is_owner(account_id: &AccountId, netuid: NetUid) -> bool;
fn is_subtoken_enabled(netuid: NetUid) -> bool;
}

pub trait CurrencyReserve<C: Currency> {
fn reserve(netuid: NetUid) -> C;
fn increase_provided(netuid: NetUid, amount: C);
fn decrease_provided(netuid: NetUid, amount: C);
}

pub trait BalanceOps<AccountId> {
fn tao_balance(account_id: &AccountId) -> TaoCurrency;
fn alpha_balance(netuid: NetUid, coldkey: &AccountId, hotkey: &AccountId) -> AlphaCurrency;
Expand All @@ -197,10 +201,6 @@ pub trait BalanceOps<AccountId> {
netuid: NetUid,
alpha: AlphaCurrency,
) -> Result<AlphaCurrency, DispatchError>;
fn increase_provided_tao_reserve(netuid: NetUid, tao: TaoCurrency);
fn decrease_provided_tao_reserve(netuid: NetUid, tao: TaoCurrency);
fn increase_provided_alpha_reserve(netuid: NetUid, alpha: AlphaCurrency);
fn decrease_provided_alpha_reserve(netuid: NetUid, alpha: AlphaCurrency);
}

pub mod time {
Expand Down
88 changes: 62 additions & 26 deletions pallets/swap-interface/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,36 @@
#![cfg_attr(not(feature = "std"), no_std)]
use core::ops::Neg;

use frame_support::pallet_prelude::*;
use substrate_fixed::types::U96F32;
use subtensor_runtime_common::{AlphaCurrency, NetUid, TaoCurrency};
use subtensor_runtime_common::{AlphaCurrency, Currency, NetUid, TaoCurrency};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OrderType {
Sell,
Buy,
}
pub use order::*;

mod order;

pub trait SwapHandler<AccountId> {
fn swap(
fn swap<OrderT>(
netuid: NetUid,
order_t: OrderType,
amount: u64,
price_limit: u64,
order: OrderT,
price_limit: TaoCurrency,
drop_fees: bool,
should_rollback: bool,
) -> Result<SwapResult, DispatchError>;
fn sim_swap(
) -> Result<SwapResult<OrderT::PaidIn, OrderT::PaidOut>, DispatchError>
where
OrderT: Order,
Self: SwapEngine<OrderT>;
fn sim_swap<OrderT>(
netuid: NetUid,
order_t: OrderType,
amount: u64,
) -> Result<SwapResult, DispatchError>;
fn approx_fee_amount(netuid: NetUid, amount: u64) -> u64;
order: OrderT,
) -> Result<SwapResult<OrderT::PaidIn, OrderT::PaidOut>, DispatchError>
where
OrderT: Order,
Self: DefaultPriceLimit<OrderT::PaidIn, OrderT::PaidOut> + SwapEngine<OrderT>;
fn approx_fee_amount<T: Currency>(netuid: NetUid, amount: T) -> T;
fn current_alpha_price(netuid: NetUid) -> U96F32;
fn max_price() -> u64;
fn min_price() -> u64;
fn max_price<C: Currency>() -> C;
fn min_price<C: Currency>() -> C;
fn adjust_protocol_liquidity(
netuid: NetUid,
tao_delta: TaoCurrency,
Expand All @@ -38,12 +41,45 @@ pub trait SwapHandler<AccountId> {
fn toggle_user_liquidity(netuid: NetUid, enabled: bool);
}

#[derive(Debug, PartialEq)]
pub struct SwapResult {
pub amount_paid_in: u64,
pub amount_paid_out: u64,
pub fee_paid: u64,
// For calculation of new tao/alpha reserves
pub tao_reserve_delta: i64,
pub alpha_reserve_delta: i64,
pub trait DefaultPriceLimit<PaidIn, PaidOut>
where
PaidIn: Currency,
PaidOut: Currency,
{
fn default_price_limit<C: Currency>() -> C;
}

pub trait SwapEngine<OrderT: Order> {
fn swap(
netuid: NetUid,
order: OrderT,
price_limit: TaoCurrency,
drop_fees: bool,
should_rollback: bool,
) -> Result<SwapResult<OrderT::PaidIn, OrderT::PaidOut>, DispatchError>;
}

#[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)]
pub struct SwapResult<PaidIn, PaidOut>
where
PaidIn: Currency,
PaidOut: Currency,
{
pub amount_paid_in: PaidIn,
pub amount_paid_out: PaidOut,
pub fee_paid: PaidIn,
}

impl<PaidIn, PaidOut> SwapResult<PaidIn, PaidOut>
where
PaidIn: Currency,
PaidOut: Currency,
{
pub fn paid_in_reserve_delta(&self) -> i128 {
self.amount_paid_in.to_u64() as i128
}

pub fn paid_out_reserve_delta(&self) -> i128 {
(self.amount_paid_out.to_u64() as i128).neg()
}
}
87 changes: 87 additions & 0 deletions pallets/swap-interface/src/order.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use core::marker::PhantomData;

use substrate_fixed::types::U64F64;
use subtensor_runtime_common::{AlphaCurrency, Currency, CurrencyReserve, TaoCurrency};

pub trait Order: Clone {
type PaidIn: Currency;
type PaidOut: Currency;
type ReserveIn: CurrencyReserve<Self::PaidIn>;
type ReserveOut: CurrencyReserve<Self::PaidOut>;

fn with_amount(amount: impl Into<Self::PaidIn>) -> Self;
fn amount(&self) -> Self::PaidIn;
fn is_beyond_price_limit(&self, alpha_sqrt_price: U64F64, limit_sqrt_price: U64F64) -> bool;
}

#[derive(Clone, Default)]
pub struct AlphaForTao<ReserveIn, ReserveOut>
where
ReserveIn: CurrencyReserve<TaoCurrency>,
ReserveOut: CurrencyReserve<AlphaCurrency>,
{
amount: TaoCurrency,
_phantom: PhantomData<(ReserveIn, ReserveOut)>,
}

impl<ReserveIn, ReserveOut> Order for AlphaForTao<ReserveIn, ReserveOut>
where
ReserveIn: CurrencyReserve<TaoCurrency> + Clone,
ReserveOut: CurrencyReserve<AlphaCurrency> + Clone,
{
type PaidIn = TaoCurrency;
type PaidOut = AlphaCurrency;
type ReserveIn = ReserveIn;
type ReserveOut = ReserveOut;

fn with_amount(amount: impl Into<Self::PaidIn>) -> Self {
Self {
amount: amount.into(),
_phantom: PhantomData,
}
}

fn amount(&self) -> TaoCurrency {
self.amount
}

fn is_beyond_price_limit(&self, alpha_sqrt_price: U64F64, limit_sqrt_price: U64F64) -> bool {
alpha_sqrt_price < limit_sqrt_price
}
}

#[derive(Clone, Default)]
pub struct TaoForAlpha<ReserveIn, ReserveOut>
where
ReserveIn: CurrencyReserve<AlphaCurrency>,
ReserveOut: CurrencyReserve<TaoCurrency>,
{
amount: AlphaCurrency,
_phantom: PhantomData<(ReserveIn, ReserveOut)>,
}

impl<ReserveIn, ReserveOut> Order for TaoForAlpha<ReserveIn, ReserveOut>
where
ReserveIn: CurrencyReserve<AlphaCurrency> + Clone,
ReserveOut: CurrencyReserve<TaoCurrency> + Clone,
{
type PaidIn = AlphaCurrency;
type PaidOut = TaoCurrency;
type ReserveIn = ReserveIn;
type ReserveOut = ReserveOut;

fn with_amount(amount: impl Into<Self::PaidIn>) -> Self {
Self {
amount: amount.into(),
_phantom: PhantomData,
}
}

fn amount(&self) -> AlphaCurrency {
self.amount
}

fn is_beyond_price_limit(&self, alpha_sqrt_price: U64F64, limit_sqrt_price: U64F64) -> bool {
alpha_sqrt_price > limit_sqrt_price
}
}
2 changes: 1 addition & 1 deletion pallets/swap/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ substrate-fixed.workspace = true

pallet-subtensor-swap-runtime-api.workspace = true
subtensor-macros.workspace = true
subtensor-runtime-common.workspace = true
subtensor-runtime-common = { workspace = true, features = ["approx"] }
subtensor-swap-interface.workspace = true

[dev-dependencies]
Expand Down
1 change: 0 additions & 1 deletion pallets/swap/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#![cfg_attr(not(feature = "std"), no_std)]

use substrate_fixed::types::U64F64;
use subtensor_swap_interface::OrderType;

pub mod pallet;
pub mod position;
Expand Down
92 changes: 80 additions & 12 deletions pallets/swap/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@ use sp_runtime::{
BuildStorage, Vec,
traits::{BlakeTwo256, IdentityLookup},
};
use subtensor_runtime_common::{AlphaCurrency, BalanceOps, NetUid, SubnetInfo, TaoCurrency};
use substrate_fixed::types::U64F64;
use subtensor_runtime_common::{
AlphaCurrency, BalanceOps, Currency, CurrencyReserve, NetUid, SubnetInfo, TaoCurrency,
};
use subtensor_swap_interface::Order;

use crate::pallet::EnabledUserLiquidity;
use crate::pallet::{EnabledUserLiquidity, FeeGlobalAlpha, FeeGlobalTao};

construct_runtime!(
pub enum Test {
Expand Down Expand Up @@ -83,11 +87,11 @@ parameter_types! {
pub const MinimumReserves: NonZeroU64 = NonZeroU64::new(1).unwrap();
}

// Mock implementor of SubnetInfo trait
pub struct MockLiquidityProvider;
#[derive(Clone)]
pub struct TaoReserve;

impl SubnetInfo<AccountId> for MockLiquidityProvider {
fn tao_reserve(netuid: NetUid) -> TaoCurrency {
impl CurrencyReserve<TaoCurrency> for TaoReserve {
fn reserve(netuid: NetUid) -> TaoCurrency {
match netuid.into() {
123u16 => 10_000,
WRAPPING_FEES_NETUID => 100_000_000_000,
Expand All @@ -96,14 +100,81 @@ impl SubnetInfo<AccountId> for MockLiquidityProvider {
.into()
}

fn alpha_reserve(netuid: NetUid) -> AlphaCurrency {
fn increase_provided(_: NetUid, _: TaoCurrency) {}
fn decrease_provided(_: NetUid, _: TaoCurrency) {}
}

#[derive(Clone)]
pub struct AlphaReserve;

impl CurrencyReserve<AlphaCurrency> for AlphaReserve {
fn reserve(netuid: NetUid) -> AlphaCurrency {
match netuid.into() {
123u16 => 10_000.into(),
WRAPPING_FEES_NETUID => 400_000_000_000.into(),
_ => 4_000_000_000_000.into(),
}
}

fn increase_provided(_: NetUid, _: AlphaCurrency) {}
fn decrease_provided(_: NetUid, _: AlphaCurrency) {}
}

pub type AlphaForTao = subtensor_swap_interface::AlphaForTao<TaoReserve, AlphaReserve>;
pub type TaoForAlpha = subtensor_swap_interface::TaoForAlpha<AlphaReserve, TaoReserve>;

pub(crate) trait GlobalFeeInfo: Currency {
fn global_fee(&self, netuid: NetUid) -> U64F64;
}

impl GlobalFeeInfo for TaoCurrency {
fn global_fee(&self, netuid: NetUid) -> U64F64 {
FeeGlobalTao::<Test>::get(netuid)
}
}

impl GlobalFeeInfo for AlphaCurrency {
fn global_fee(&self, netuid: NetUid) -> U64F64 {
FeeGlobalAlpha::<Test>::get(netuid)
}
}

pub(crate) trait TestExt<O: Order> {
fn approx_expected_swap_output(
sqrt_current_price: f64,
liquidity_before: f64,
order_liquidity: f64,
) -> f64;
}

impl TestExt<AlphaForTao> for Test {
fn approx_expected_swap_output(
sqrt_current_price: f64,
liquidity_before: f64,
order_liquidity: f64,
) -> f64 {
let denom = sqrt_current_price * (sqrt_current_price * liquidity_before + order_liquidity);
let per_order_liq = liquidity_before / denom;
per_order_liq * order_liquidity
}
}

impl TestExt<TaoForAlpha> for Test {
fn approx_expected_swap_output(
sqrt_current_price: f64,
liquidity_before: f64,
order_liquidity: f64,
) -> f64 {
let denom = liquidity_before / sqrt_current_price + order_liquidity;
let per_order_liq = sqrt_current_price * liquidity_before / denom;
per_order_liq * order_liquidity
}
}

// Mock implementor of SubnetInfo trait
pub struct MockLiquidityProvider;

impl SubnetInfo<AccountId> for MockLiquidityProvider {
fn exists(netuid: NetUid) -> bool {
netuid != NON_EXISTENT_NETUID.into()
}
Expand Down Expand Up @@ -177,16 +248,13 @@ impl BalanceOps<AccountId> for MockBalanceOps {
) -> Result<AlphaCurrency, DispatchError> {
Ok(alpha)
}

fn increase_provided_tao_reserve(_netuid: NetUid, _tao: TaoCurrency) {}
fn decrease_provided_tao_reserve(_netuid: NetUid, _tao: TaoCurrency) {}
fn increase_provided_alpha_reserve(_netuid: NetUid, _alpha: AlphaCurrency) {}
fn decrease_provided_alpha_reserve(_netuid: NetUid, _alpha: AlphaCurrency) {}
}

impl crate::pallet::Config for Test {
type RuntimeEvent = RuntimeEvent;
type SubnetInfo = MockLiquidityProvider;
type TaoReserve = TaoReserve;
type AlphaReserve = AlphaReserve;
type BalanceOps = MockBalanceOps;
type ProtocolId = SwapProtocolId;
type MaxFeeRate = MaxFeeRate;
Expand Down
Loading