Skip to content
Open
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
2 changes: 1 addition & 1 deletion pallets/admin-utils/src/tests/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ parameter_types! {
pub const SwapProtocolId: PalletId = PalletId(*b"ten/swap");
pub const SwapMaxFeeRate: u16 = 10000; // 15.26%
pub const SwapMaxPositions: u32 = 100;
pub const SwapMinimumLiquidity: u64 = 1_000;
pub const SwapMinimumLiquidity: u128 = 1_000;
pub const SwapMinimumReserve: NonZeroU64 = NonZeroU64::new(1_000_000).unwrap();
}

Expand Down
4 changes: 3 additions & 1 deletion pallets/subtensor/src/macros/hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,9 @@ mod hooks {
// Cleanup child/parent keys
.saturating_add(migrations::migrate_fix_childkeys::migrate_fix_childkeys::<T>())
// Migrate AutoStakeDestinationColdkeys
.saturating_add(migrations::migrate_auto_stake_destination::migrate_auto_stake_destination::<T>());
.saturating_add(migrations::migrate_auto_stake_destination::migrate_auto_stake_destination::<T>())
// Migrate and fix LP ticks that saturated
.saturating_add(migrations::migrate_fix_liquidity_ticks::migrate_fix_liquidity_ticks::<T>());
weight
}

Expand Down
56 changes: 56 additions & 0 deletions pallets/subtensor/src/migrations/migrate_fix_liquidity_ticks.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use super::*;
use alloc::string::String;
use subtensor_swap_interface::SwapHandler;

/// Migrate and fix LP ticks that saturated
pub fn migrate_fix_liquidity_ticks<T: Config>() -> Weight {
let migration_name = b"migrate_fix_liquidity_ticks".to_vec();
let mut weight = T::DbWeight::get().reads(1);

if HasMigrationRun::<T>::get(&migration_name) {
log::info!(
"Migration '{:?}' has already run. Skipping.",
String::from_utf8_lossy(&migration_name)
);
return weight;
}

log::info!(
"Running migration '{}'",
String::from_utf8_lossy(&migration_name)
);

////////////////////////////////////////////////////////
// Actual migration

T::SwapInterface::migrate_fix_liquidity_ticks(&mut weight);
T::SwapInterface::migrate_fix_current_liquidity(&mut weight);

// Fix reserves for all subnets
let netuids: Vec<NetUid> = NetworksAdded::<T>::iter()
.map(|(netuid, _)| netuid)
.collect();
weight = weight.saturating_add(T::DbWeight::get().reads_writes(netuids.len() as u64, 0));

for netuid in netuids.into_iter() {
let (tao_reserve, alpha_reserve) =
T::SwapInterface::migrate_get_implied_reserves(netuid, &mut weight);
SubnetTaoProvided::<T>::insert(netuid, TaoCurrency::from(0));
SubnetTAO::<T>::insert(netuid, tao_reserve);
SubnetAlphaInProvided::<T>::insert(netuid, AlphaCurrency::from(0));
SubnetAlphaIn::<T>::insert(netuid, alpha_reserve);
weight = weight.saturating_add(T::DbWeight::get().writes(4));
}

////////////////////////////////////////////////////////

HasMigrationRun::<T>::insert(&migration_name, true);
weight = weight.saturating_add(T::DbWeight::get().writes(1));

log::info!(
target: "runtime",
"Migration '{}' completed successfully.",
String::from_utf8_lossy(&migration_name)
);
weight
}
1 change: 1 addition & 0 deletions pallets/subtensor/src/migrations/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub mod migrate_delete_subnet_3;
pub mod migrate_disable_commit_reveal;
pub mod migrate_fix_childkeys;
pub mod migrate_fix_is_network_member;
pub mod migrate_fix_liquidity_ticks;
pub mod migrate_fix_root_subnet_tao;
pub mod migrate_fix_root_tao_and_alpha_in;
pub mod migrate_identities_v2;
Expand Down
69 changes: 69 additions & 0 deletions pallets/subtensor/src/tests/coinbase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2876,3 +2876,72 @@ fn test_incentive_goes_to_hotkey_when_no_autostake_destination() {
);
});
}

// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_coinbase_liquidity_reserves --exact --show-output
#[test]
fn test_coinbase_liquidity_reserves() {
new_test_ext(1).execute_with(|| {
let owner_hotkey = U256::from(1001);
let owner_coldkey = U256::from(1002);
let coldkey = U256::from(1);

// add network
let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey);

// Setup reserves that will make amount push the liquidity limits
// let tao_reserve_before = TaoCurrency::from(2_000_000_000_000_000);
// let alpha_reserve_before = AlphaCurrency::from(1_700_000_000_000_000);
let tao_reserve_before = TaoCurrency::from(1_000_000_000_000_000);
let alpha_reserve_before = AlphaCurrency::from(1_000_000_000_000_000);
mock::setup_reserves(netuid, tao_reserve_before, alpha_reserve_before);

// Force the swap to initialize
SubtensorModule::swap_tao_for_alpha(
netuid,
TaoCurrency::ZERO,
1_000_000_000_000.into(),
false,
)
.unwrap();

// Calculate implied reserves before
let protocol_account_id = pallet_subtensor_swap::Pallet::<Test>::protocol_account_id();
let position_before = pallet_subtensor_swap::Positions::<Test>::get((
netuid,
protocol_account_id,
PositionId::from(1),
))
.unwrap();
let price_sqrt_before = pallet_subtensor_swap::AlphaSqrtPrice::<Test>::get(netuid);
let (tao_implied_before, _alpha_implied_before) =
position_before.to_token_amounts(price_sqrt_before).unwrap();

////////////////////////////////////////////
// Do emissions

// Set subnet ema price
SubnetMovingPrice::<Test>::insert(netuid, I96F32::from_num(1.0));

// Run the coinbase with the emission amount.
SubtensorModule::run_coinbase(U96F32::from_num(1_000_000_000));

// Calculate implied reserves after
let position_after = pallet_subtensor_swap::Positions::<Test>::get((
netuid,
protocol_account_id,
PositionId::from(1),
))
.unwrap();
let price_sqrt_after = pallet_subtensor_swap::AlphaSqrtPrice::<Test>::get(netuid);
let (tao_implied_after, _alpha_implied_after) =
position_after.to_token_amounts(price_sqrt_after).unwrap();

// Verify implied and realized reserve diffs match
let tao_reserve_after = SubnetTAO::<Test>::get(netuid);
assert_abs_diff_eq!(
tao_reserve_after - tao_reserve_before,
(tao_implied_after - tao_implied_before).into(),
epsilon = 1.into()
);
});
}
2 changes: 1 addition & 1 deletion pallets/subtensor/src/tests/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ parameter_types! {
pub const SwapProtocolId: PalletId = PalletId(*b"ten/swap");
pub const SwapMaxFeeRate: u16 = 10000; // 15.26%
pub const SwapMaxPositions: u32 = 100;
pub const SwapMinimumLiquidity: u64 = 1_000;
pub const SwapMinimumLiquidity: u128 = 1_000;
pub const SwapMinimumReserve: NonZeroU64 = NonZeroU64::new(100).unwrap();
}

Expand Down
4 changes: 2 additions & 2 deletions pallets/subtensor/src/tests/networks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2067,7 +2067,7 @@ fn massive_dissolve_refund_and_reregistration_flow_is_lossless_and_cleans_state(
"subnet {net:?} still exists"
);
assert!(
pallet_subtensor_swap::Ticks::<Test>::iter_prefix(net)
pallet_subtensor_swap::Ticks128::<Test>::iter_prefix(net)
.next()
.is_none(),
"ticks not cleared for net {net:?}"
Expand All @@ -2088,7 +2088,7 @@ fn massive_dissolve_refund_and_reregistration_flow_is_lossless_and_cleans_state(
"FeeGlobalAlpha nonzero for net {net:?}"
);
assert_eq!(
pallet_subtensor_swap::CurrentLiquidity::<Test>::get(net),
pallet_subtensor_swap::CurrentLiquidity128::<Test>::get(net),
0,
"CurrentLiquidity not zero for net {net:?}"
);
Expand Down
82 changes: 82 additions & 0 deletions pallets/subtensor/src/tests/staking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use frame_support::sp_runtime::DispatchError;
use frame_support::{assert_err, assert_noop, assert_ok, traits::Currency};
use frame_system::RawOrigin;
use pallet_subtensor_swap::Call as SwapCall;
use pallet_subtensor_swap::position::PositionId;
use pallet_subtensor_swap::tick::TickIndex;
use safe_math::FixedExt;
use sp_core::{Get, H256, U256};
Expand Down Expand Up @@ -5576,3 +5577,84 @@ fn test_remove_root_updates_counters() {
);
});
}

// cargo test --package pallet-subtensor --lib -- tests::staking::test_add_stake_liquidity_reserves --exact --show-output
#[test]
fn test_add_stake_liquidity_reserves() {
new_test_ext(1).execute_with(|| {
let owner_hotkey = U256::from(1001);
let owner_coldkey = U256::from(1002);
let coldkey = U256::from(1);
let amount = TaoCurrency::from(10_000_000_000_000_000);

// add network
let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey);

// Give it some $$$ in his coldkey balance
SubtensorModule::add_balance_to_coldkey_account(&coldkey, amount.into());

// Setup reserves that will make amount push the liquidity limits
let tao_reserve_before = TaoCurrency::from(20_000_000_000_000);
let alpha_reserve_before = AlphaCurrency::from(1_700_000_000_000_000);
mock::setup_reserves(netuid, tao_reserve_before, alpha_reserve_before);

// Force the swap to initialize
SubtensorModule::swap_tao_for_alpha(
netuid,
TaoCurrency::ZERO,
1_000_000_000_000.into(),
false,
)
.unwrap();

// Calculate implied reserves before
let protocol_account_id = pallet_subtensor_swap::Pallet::<Test>::protocol_account_id();
let position_before = pallet_subtensor_swap::Positions::<Test>::get((
netuid,
protocol_account_id,
PositionId::from(1),
))
.unwrap();
let price_sqrt_before = pallet_subtensor_swap::AlphaSqrtPrice::<Test>::get(netuid);
let (tao_implied_before, _alpha_implied_before) =
position_before.to_token_amounts(price_sqrt_before).unwrap();

////////////////////////////////////////////
// Call add_stake extrinsic
assert_ok!(SubtensorModule::add_stake(
RuntimeOrigin::signed(coldkey),
owner_hotkey,
netuid,
amount
));

////////////////////////////////////////////
// Call remove_stake extrinsic for a small alpha amount
let unstake_amount = AlphaCurrency::from(100_000_000);
remove_stake_rate_limit_for_tests(&owner_hotkey, &coldkey, netuid);
assert_ok!(SubtensorModule::remove_stake(
RuntimeOrigin::signed(coldkey),
owner_hotkey,
netuid,
unstake_amount
));

// Calculate implied reserves after
let position_after = pallet_subtensor_swap::Positions::<Test>::get((
netuid,
protocol_account_id,
PositionId::from(1),
))
.unwrap();
let price_sqrt_after = pallet_subtensor_swap::AlphaSqrtPrice::<Test>::get(netuid);
let (tao_implied_after, _alpha_implied_after) =
position_after.to_token_amounts(price_sqrt_after).unwrap();

// Verify implied and realized reserve diffs match
let tao_reserve_after = SubnetTAO::<Test>::get(netuid);
assert_eq!(
tao_reserve_after - tao_reserve_before,
(tao_implied_after - tao_implied_before).into(),
);
});
}
8 changes: 8 additions & 0 deletions pallets/swap-interface/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ pub trait SwapHandler {
fn dissolve_all_liquidity_providers(netuid: NetUid) -> DispatchResult;
fn toggle_user_liquidity(netuid: NetUid, enabled: bool);
fn clear_protocol_liquidity(netuid: NetUid) -> DispatchResult;

// Migrations
fn migrate_fix_liquidity_ticks(weight: &mut Weight);
fn migrate_fix_current_liquidity(weight: &mut Weight);
fn migrate_get_implied_reserves(
netuid: NetUid,
weight: &mut Weight,
) -> (TaoCurrency, AlphaCurrency);
}

pub trait DefaultPriceLimit<PaidIn, PaidOut>
Expand Down
10 changes: 5 additions & 5 deletions pallets/swap/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ use subtensor_runtime_common::NetUid;

use crate::{
pallet::{
AlphaSqrtPrice, Call, Config, CurrentLiquidity, CurrentTick, EnabledUserLiquidity, Pallet,
Positions, SwapV3Initialized,
AlphaSqrtPrice, Call, Config, CurrentLiquidity128, CurrentTick, EnabledUserLiquidity,
Pallet, Positions, SwapV3Initialized,
},
position::{Position, PositionId},
tick::TickIndex,
Expand All @@ -40,7 +40,7 @@ mod benchmarks {
SwapV3Initialized::<T>::insert(netuid, true);
AlphaSqrtPrice::<T>::insert(netuid, U64F64::from_num(1));
CurrentTick::<T>::insert(netuid, TickIndex::new(0).unwrap());
CurrentLiquidity::<T>::insert(netuid, T::MinimumLiquidity::get());
CurrentLiquidity128::<T>::insert(netuid, T::MinimumLiquidity::get());
}

let caller: T::AccountId = whitelisted_caller();
Expand All @@ -67,7 +67,7 @@ mod benchmarks {
SwapV3Initialized::<T>::insert(netuid, true);
AlphaSqrtPrice::<T>::insert(netuid, U64F64::from_num(1));
CurrentTick::<T>::insert(netuid, TickIndex::new(0).unwrap());
CurrentLiquidity::<T>::insert(netuid, T::MinimumLiquidity::get());
CurrentLiquidity128::<T>::insert(netuid, T::MinimumLiquidity::get());
}

let caller: T::AccountId = whitelisted_caller();
Expand Down Expand Up @@ -100,7 +100,7 @@ mod benchmarks {
SwapV3Initialized::<T>::insert(netuid, true);
AlphaSqrtPrice::<T>::insert(netuid, U64F64::from_num(1));
CurrentTick::<T>::insert(netuid, TickIndex::new(0).unwrap());
CurrentLiquidity::<T>::insert(netuid, T::MinimumLiquidity::get());
CurrentLiquidity128::<T>::insert(netuid, T::MinimumLiquidity::get());
}

let caller: T::AccountId = whitelisted_caller();
Expand Down
2 changes: 1 addition & 1 deletion pallets/swap/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ parameter_types! {
pub const SwapProtocolId: PalletId = PalletId(*b"ten/swap");
pub const MaxFeeRate: u16 = 10000; // 15.26%
pub const MaxPositions: u32 = 100;
pub const MinimumLiquidity: u64 = 1_000;
pub const MinimumLiquidity: u128 = 1_000;
pub const MinimumReserves: NonZeroU64 = NonZeroU64::new(1).unwrap();
}

Expand Down
Loading
Loading