Skip to content
Merged
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
10 changes: 10 additions & 0 deletions pallets/subtensor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1569,6 +1569,7 @@ pub enum CustomTransactionError {
NotEnoughStakeToWithdraw,
RateLimitExceeded,
InsufficientLiquidity,
SlippageTooHigh,
BadRequest,
}

Expand All @@ -1583,6 +1584,7 @@ impl From<CustomTransactionError> for u8 {
CustomTransactionError::NotEnoughStakeToWithdraw => 5,
CustomTransactionError::RateLimitExceeded => 6,
CustomTransactionError::InsufficientLiquidity => 7,
CustomTransactionError::SlippageTooHigh => 8,
CustomTransactionError::BadRequest => 255,
}
}
Expand Down Expand Up @@ -1654,6 +1656,10 @@ where
CustomTransactionError::InsufficientLiquidity.into(),
)
.into()),
Error::<T>::SlippageTooHigh => Err(InvalidTransaction::Custom(
CustomTransactionError::SlippageTooHigh.into(),
)
.into()),
_ => Err(
InvalidTransaction::Custom(CustomTransactionError::BadRequest.into()).into(),
),
Expand Down Expand Up @@ -1801,6 +1807,8 @@ where
hotkey,
*netuid,
*amount_staked,
*amount_staked,
false,
))
}
Some(Call::remove_stake {
Expand All @@ -1814,6 +1822,8 @@ where
hotkey,
*netuid,
*amount_unstaked,
*amount_unstaked,
false,
))
}
Some(Call::move_stake {
Expand Down
28 changes: 26 additions & 2 deletions pallets/subtensor/src/macros/dispatches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1710,6 +1710,10 @@ mod dispatches {
/// * 'limit_price' (u64):
/// - The limit price expressed in units of RAO per one Alpha.
///
/// * 'allow_partial' (bool):
/// - Allows partial execution of the amount. If set to false, this becomes
/// fill or kill type or order.
///
/// # Event:
/// * StakeAdded;
/// - On the successfully adding stake to a global account.
Expand All @@ -1734,8 +1738,16 @@ mod dispatches {
netuid: u16,
amount_staked: u64,
limit_price: u64,
allow_partial: bool,
) -> DispatchResult {
Self::do_add_stake_limit(origin, hotkey, netuid, amount_staked, limit_price)
Self::do_add_stake_limit(
origin,
hotkey,
netuid,
amount_staked,
limit_price,
allow_partial,
)
}

/// --- Removes stake from a hotkey on a subnet with a price limit.
Expand All @@ -1759,6 +1771,10 @@ mod dispatches {
/// * 'limit_price' (u64):
/// - The limit price expressed in units of RAO per one Alpha.
///
/// * 'allow_partial' (bool):
/// - Allows partial execution of the amount. If set to false, this becomes
/// fill or kill type or order.
///
/// # Event:
/// * StakeRemoved;
/// - On the successfully removing stake from the hotkey account.
Expand All @@ -1784,8 +1800,16 @@ mod dispatches {
netuid: u16,
amount_unstaked: u64,
limit_price: u64,
allow_partial: bool,
) -> DispatchResult {
Self::do_remove_stake_limit(origin, hotkey, netuid, amount_unstaked, limit_price)
Self::do_remove_stake_limit(
origin,
hotkey,
netuid,
amount_unstaked,
limit_price,
allow_partial,
)
}
}
}
2 changes: 2 additions & 0 deletions pallets/subtensor/src/macros/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,5 +187,7 @@ mod errors {
AmountTooLow,
/// Not enough liquidity.
InsufficientLiquidity,
/// Slippage is too high for the transaction.
SlippageTooHigh,
}
}
29 changes: 24 additions & 5 deletions pallets/subtensor/src/staking/add_stake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,14 @@ impl<T: Config> Pallet<T> {
);

// 2. Validate user input
Self::validate_add_stake(&coldkey, &hotkey, netuid, stake_to_be_added)?;
Self::validate_add_stake(
&coldkey,
&hotkey,
netuid,
stake_to_be_added,
stake_to_be_added,
false,
)?;

// 3. Ensure the remove operation from the coldkey is a success.
let tao_staked: u64 =
Expand Down Expand Up @@ -81,6 +88,10 @@ impl<T: Config> Pallet<T> {
/// * 'limit_price' (u64):
/// - The limit price expressed in units of RAO per one Alpha.
///
/// * 'allow_partial' (bool):
/// - Allows partial execution of the amount. If set to false, this becomes
/// fill or kill type or order.
///
/// # Event:
/// * StakeAdded;
/// - On the successfully adding stake to a global account.
Expand All @@ -104,6 +115,7 @@ impl<T: Config> Pallet<T> {
netuid: u16,
stake_to_be_added: u64,
limit_price: u64,
allow_partial: bool,
) -> dispatch::DispatchResult {
// 1. We check that the transaction is signed by the caller and retrieve the T::AccountId coldkey information.
let coldkey = ensure_signed(origin)?;
Expand All @@ -115,16 +127,23 @@ impl<T: Config> Pallet<T> {
stake_to_be_added
);

// 2. Validate user input
Self::validate_add_stake(&coldkey, &hotkey, netuid, stake_to_be_added)?;

// 3. Calcaulate the maximum amount that can be executed with price limit
// 2. Calcaulate the maximum amount that can be executed with price limit
let max_amount = Self::get_max_amount_add(netuid, limit_price);
let mut possible_stake = stake_to_be_added;
if possible_stake > max_amount {
possible_stake = max_amount;
}

// 3. Validate user input
Self::validate_add_stake(
&coldkey,
&hotkey,
netuid,
stake_to_be_added,
max_amount,
allow_partial,
)?;

// 4. Ensure the remove operation from the coldkey is a success.
let tao_staked: u64 = Self::remove_balance_from_coldkey_account(&coldkey, possible_stake)?;

Expand Down
65 changes: 59 additions & 6 deletions pallets/subtensor/src/staking/remove_stake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,14 @@ impl<T: Config> Pallet<T> {
);

// 2. Validate the user input
Self::validate_remove_stake(&coldkey, &hotkey, netuid, alpha_unstaked)?;
Self::validate_remove_stake(
&coldkey,
&hotkey,
netuid,
alpha_unstaked,
alpha_unstaked,
false,
)?;

// 3. Swap the alpba to tao and update counters for this subnet.
let fee = DefaultStakingFee::<T>::get();
Expand Down Expand Up @@ -223,12 +230,51 @@ impl<T: Config> Pallet<T> {
Ok(())
}

/// ---- The implementation for the extrinsic remove_stake_limit: Removes stake from
/// a hotkey on a subnet with a price limit.
///
/// In case if slippage occurs and the price shall move beyond the limit
/// price, the staking order may execute only partially or not execute
/// at all.
///
/// # Args:
/// * 'origin': (<T as frame_system::Config>Origin):
/// - The signature of the caller's coldkey.
///
/// * 'hotkey' (T::AccountId):
/// - The associated hotkey account.
///
/// * 'amount_unstaked' (u64):
/// - The amount of stake to be added to the hotkey staking account.
///
/// * 'limit_price' (u64):
/// - The limit price expressed in units of RAO per one Alpha.
///
/// * 'allow_partial' (bool):
/// - Allows partial execution of the amount. If set to false, this becomes
/// fill or kill type or order.
///
/// # Event:
/// * StakeRemoved;
/// - On the successfully removing stake from the hotkey account.
///
/// # Raises:
/// * 'NotRegistered':
/// - Thrown if the account we are attempting to unstake from is non existent.
///
/// * 'NonAssociatedColdKey':
/// - Thrown if the coldkey does not own the hotkey we are unstaking from.
///
/// * 'NotEnoughStakeToWithdraw':
/// - Thrown if there is not enough stake on the hotkey to withdwraw this amount.
///
pub fn do_remove_stake_limit(
origin: T::RuntimeOrigin,
hotkey: T::AccountId,
netuid: u16,
alpha_unstaked: u64,
limit_price: u64,
allow_partial: bool,
) -> dispatch::DispatchResult {
// 1. We check the transaction is signed by the caller and retrieve the T::AccountId coldkey information.
let coldkey = ensure_signed(origin)?;
Expand All @@ -240,17 +286,24 @@ impl<T: Config> Pallet<T> {
alpha_unstaked
);

// 2. Validate the user input
Self::validate_remove_stake(&coldkey, &hotkey, netuid, alpha_unstaked)?;

// 3. Calcaulate the maximum amount that can be executed with price limit
// 2. Calcaulate the maximum amount that can be executed with price limit
let max_amount = Self::get_max_amount_remove(netuid, limit_price);
let mut possible_alpha = alpha_unstaked;
if possible_alpha > max_amount {
possible_alpha = max_amount;
}

// 4. Swap the alpba to tao and update counters for this subnet.
// 3. Validate the user input
Self::validate_remove_stake(
&coldkey,
&hotkey,
netuid,
alpha_unstaked,
max_amount,
allow_partial,
)?;

// 4. Swap the alpha to tao and update counters for this subnet.
let fee = DefaultStakingFee::<T>::get();
let tao_unstaked: u64 =
Self::unstake_from_subnet(&hotkey, &coldkey, netuid, possible_alpha, fee);
Expand Down
16 changes: 16 additions & 0 deletions pallets/subtensor/src/staking/stake_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,8 @@ impl<T: Config> Pallet<T> {
hotkey: &T::AccountId,
netuid: u16,
stake_to_be_added: u64,
max_amount: u64,
allow_partial: bool,
) -> Result<(), Error<T>> {
// Ensure that the subnet exists.
ensure!(Self::if_subnet_exist(netuid), Error::<T>::SubnetNotExists);
Expand All @@ -739,6 +741,12 @@ impl<T: Config> Pallet<T> {
// Ensure that the stake_to_be_added is at least the min_amount
ensure!(stake_to_be_added >= min_amount, Error::<T>::AmountTooLow);

// Ensure that if partial execution is not allowed, the amount will not cause
// slippage over desired
if !allow_partial {
ensure!(stake_to_be_added <= max_amount, Error::<T>::SlippageTooHigh);
}

// Ensure the callers coldkey has enough stake to perform the transaction.
ensure!(
Self::can_remove_balance_from_coldkey_account(coldkey, stake_to_be_added),
Expand Down Expand Up @@ -767,6 +775,8 @@ impl<T: Config> Pallet<T> {
hotkey: &T::AccountId,
netuid: u16,
alpha_unstaked: u64,
max_amount: u64,
allow_partial: bool,
) -> Result<(), Error<T>> {
// Ensure that the subnet exists.
ensure!(Self::if_subnet_exist(netuid), Error::<T>::SubnetNotExists);
Expand All @@ -781,6 +791,12 @@ impl<T: Config> Pallet<T> {
return Err(Error::<T>::InsufficientLiquidity);
};

// Ensure that if partial execution is not allowed, the amount will not cause
// slippage over desired
if !allow_partial {
ensure!(alpha_unstaked <= max_amount, Error::<T>::SlippageTooHigh);
}

// Ensure that the hotkey account exists this is only possible through registration.
ensure!(
Self::hotkey_account_exists(hotkey),
Expand Down
Loading
Loading