Skip to content

Commit 77a9aab

Browse files
committed
Fix tx validation for staking extrinsics
1 parent 51bb6a3 commit 77a9aab

File tree

13 files changed

+410
-269
lines changed

13 files changed

+410
-269
lines changed

pallets/subtensor/src/lib.rs

Lines changed: 146 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,7 @@ use frame_support::{
1212
dispatch::{self, DispatchInfo, DispatchResult, DispatchResultWithPostInfo, PostDispatchInfo},
1313
ensure,
1414
pallet_macros::import_section,
15-
traits::{
16-
tokens::{fungible, Fortitude, Preservation},
17-
IsSubType,
18-
},
15+
traits::{tokens::fungible, IsSubType},
1916
};
2017

2118
use codec::{Decode, Encode};
@@ -1552,6 +1549,11 @@ pub enum CustomTransactionError {
15521549
ColdkeyInSwapSchedule,
15531550
StakeAmountTooLow,
15541551
BalanceTooLow,
1552+
SubnetDoesntExist,
1553+
HotkeyAccountDoesntExist,
1554+
NotEnoughStakeToWithdraw,
1555+
RateLimitExceeded,
1556+
BadRequest,
15551557
}
15561558

15571559
impl From<CustomTransactionError> for u8 {
@@ -1560,6 +1562,11 @@ impl From<CustomTransactionError> for u8 {
15601562
CustomTransactionError::ColdkeyInSwapSchedule => 0,
15611563
CustomTransactionError::StakeAmountTooLow => 1,
15621564
CustomTransactionError::BalanceTooLow => 2,
1565+
CustomTransactionError::SubnetDoesntExist => 3,
1566+
CustomTransactionError::HotkeyAccountDoesntExist => 4,
1567+
CustomTransactionError::NotEnoughStakeToWithdraw => 5,
1568+
CustomTransactionError::RateLimitExceeded => 6,
1569+
CustomTransactionError::BadRequest => 255,
15631570
}
15641571
}
15651572
}
@@ -1602,6 +1609,41 @@ where
16021609
pub fn check_weights_min_stake(who: &T::AccountId, netuid: u16) -> bool {
16031610
Pallet::<T>::check_weights_min_stake(who, netuid)
16041611
}
1612+
1613+
pub fn result_to_validity(result: Result<(), Error<T>>) -> TransactionValidity {
1614+
if let Err(err) = result {
1615+
match err {
1616+
Error::<T>::AmountTooLow => Err(InvalidTransaction::Custom(
1617+
CustomTransactionError::StakeAmountTooLow.into(),
1618+
)
1619+
.into()),
1620+
Error::<T>::SubnetNotExists => Err(InvalidTransaction::Custom(
1621+
CustomTransactionError::SubnetDoesntExist.into(),
1622+
)
1623+
.into()),
1624+
Error::<T>::NotEnoughBalanceToStake => Err(InvalidTransaction::Custom(
1625+
CustomTransactionError::BalanceTooLow.into(),
1626+
)
1627+
.into()),
1628+
Error::<T>::HotKeyAccountNotExists => Err(InvalidTransaction::Custom(
1629+
CustomTransactionError::HotkeyAccountDoesntExist.into(),
1630+
)
1631+
.into()),
1632+
Error::<T>::NotEnoughStakeToWithdraw => Err(InvalidTransaction::Custom(
1633+
CustomTransactionError::NotEnoughStakeToWithdraw.into(),
1634+
)
1635+
.into()),
1636+
_ => Err(
1637+
InvalidTransaction::Custom(CustomTransactionError::BadRequest.into()).into(),
1638+
),
1639+
}
1640+
} else {
1641+
Ok(ValidTransaction {
1642+
priority: Self::get_priority_vanilla(),
1643+
..Default::default()
1644+
})
1645+
}
1646+
}
16051647
}
16061648

16071649
impl<T: Config + Send + Sync + TypeInfo> sp_std::fmt::Debug for SubtensorSignedExtension<T> {
@@ -1646,7 +1688,10 @@ where
16461688
..Default::default()
16471689
})
16481690
} else {
1649-
Err(InvalidTransaction::Custom(1).into())
1691+
Err(InvalidTransaction::Custom(
1692+
CustomTransactionError::StakeAmountTooLow.into(),
1693+
)
1694+
.into())
16501695
}
16511696
}
16521697
Some(Call::reveal_weights { netuid, .. }) => {
@@ -1658,7 +1703,10 @@ where
16581703
..Default::default()
16591704
})
16601705
} else {
1661-
Err(InvalidTransaction::Custom(2).into())
1706+
Err(InvalidTransaction::Custom(
1707+
CustomTransactionError::StakeAmountTooLow.into(),
1708+
)
1709+
.into())
16621710
}
16631711
}
16641712
Some(Call::batch_reveal_weights { netuid, .. }) => {
@@ -1670,7 +1718,10 @@ where
16701718
..Default::default()
16711719
})
16721720
} else {
1673-
Err(InvalidTransaction::Custom(6).into())
1721+
Err(InvalidTransaction::Custom(
1722+
CustomTransactionError::StakeAmountTooLow.into(),
1723+
)
1724+
.into())
16741725
}
16751726
}
16761727
Some(Call::set_weights { netuid, .. }) => {
@@ -1682,7 +1733,10 @@ where
16821733
..Default::default()
16831734
})
16841735
} else {
1685-
Err(InvalidTransaction::Custom(3).into())
1736+
Err(InvalidTransaction::Custom(
1737+
CustomTransactionError::StakeAmountTooLow.into(),
1738+
)
1739+
.into())
16861740
}
16871741
}
16881742
Some(Call::set_tao_weights { netuid, hotkey, .. }) => {
@@ -1694,7 +1748,10 @@ where
16941748
..Default::default()
16951749
})
16961750
} else {
1697-
Err(InvalidTransaction::Custom(4).into())
1751+
Err(InvalidTransaction::Custom(
1752+
CustomTransactionError::StakeAmountTooLow.into(),
1753+
)
1754+
.into())
16981755
}
16991756
}
17001757
Some(Call::commit_crv3_weights { netuid, .. }) => {
@@ -1706,40 +1763,88 @@ where
17061763
..Default::default()
17071764
})
17081765
} else {
1709-
Err(InvalidTransaction::Custom(7).into())
1766+
Err(InvalidTransaction::Custom(
1767+
CustomTransactionError::StakeAmountTooLow.into(),
1768+
)
1769+
.into())
17101770
}
17111771
}
17121772
Some(Call::add_stake {
1713-
hotkey: _,
1714-
netuid: _,
1773+
hotkey,
1774+
netuid,
17151775
amount,
17161776
}) => {
1717-
// Check that amount parameter is at least the min stake
1718-
// also check the coldkey balance
1719-
let coldkey_balance = <<T as Config>::Currency as fungible::Inspect<
1720-
<T as frame_system::Config>::AccountId,
1721-
>>::reducible_balance(
1722-
who, Preservation::Expendable, Fortitude::Polite
1723-
);
1724-
let min_amount =
1725-
DefaultMinStake::<T>::get().saturating_add(DefaultStakingFee::<T>::get());
1726-
1727-
if *amount < min_amount {
1728-
InvalidTransaction::Custom(CustomTransactionError::StakeAmountTooLow.into())
1729-
.into()
1730-
} else if coldkey_balance < min_amount {
1731-
InvalidTransaction::Custom(CustomTransactionError::BalanceTooLow.into()).into()
1732-
} else {
1733-
Ok(ValidTransaction {
1734-
priority: Self::get_priority_vanilla(),
1735-
..Default::default()
1736-
})
1737-
}
1777+
// Fully validate the user input
1778+
Self::result_to_validity(Pallet::<T>::validate_add_stake(
1779+
who, hotkey, *netuid, *amount,
1780+
))
1781+
}
1782+
Some(Call::remove_stake {
1783+
hotkey,
1784+
netuid,
1785+
amount_unstaked,
1786+
}) => {
1787+
// Fully validate the user input
1788+
Self::result_to_validity(Pallet::<T>::validate_remove_stake(
1789+
who,
1790+
hotkey,
1791+
*netuid,
1792+
*amount_unstaked,
1793+
))
1794+
}
1795+
Some(Call::move_stake {
1796+
origin_hotkey,
1797+
destination_hotkey,
1798+
origin_netuid,
1799+
destination_netuid,
1800+
alpha_amount,
1801+
}) => {
1802+
// Fully validate the user input
1803+
Self::result_to_validity(Pallet::<T>::validate_stake_transition(
1804+
who,
1805+
who,
1806+
origin_hotkey,
1807+
destination_hotkey,
1808+
*origin_netuid,
1809+
*destination_netuid,
1810+
*alpha_amount,
1811+
))
1812+
}
1813+
Some(Call::transfer_stake {
1814+
destination_coldkey,
1815+
hotkey,
1816+
origin_netuid,
1817+
destination_netuid,
1818+
alpha_amount,
1819+
}) => {
1820+
// Fully validate the user input
1821+
Self::result_to_validity(Pallet::<T>::validate_stake_transition(
1822+
who,
1823+
destination_coldkey,
1824+
hotkey,
1825+
hotkey,
1826+
*origin_netuid,
1827+
*destination_netuid,
1828+
*alpha_amount,
1829+
))
1830+
}
1831+
Some(Call::swap_stake {
1832+
hotkey,
1833+
origin_netuid,
1834+
destination_netuid,
1835+
alpha_amount,
1836+
}) => {
1837+
// Fully validate the user input
1838+
Self::result_to_validity(Pallet::<T>::validate_stake_transition(
1839+
who,
1840+
who,
1841+
hotkey,
1842+
hotkey,
1843+
*origin_netuid,
1844+
*destination_netuid,
1845+
*alpha_amount,
1846+
))
17381847
}
1739-
Some(Call::remove_stake { .. }) => Ok(ValidTransaction {
1740-
priority: Self::get_priority_vanilla(),
1741-
..Default::default()
1742-
}),
17431848
Some(Call::register { netuid, .. } | Call::burned_register { netuid, .. }) => {
17441849
let registrations_this_interval =
17451850
Pallet::<T>::get_registrations_this_interval(*netuid);
@@ -1748,7 +1853,10 @@ where
17481853
if registrations_this_interval >= (max_registrations_per_interval.saturating_mul(3))
17491854
{
17501855
// If the registration limit for the interval is exceeded, reject the transaction
1751-
return Err(InvalidTransaction::Custom(5).into());
1856+
return Err(InvalidTransaction::Custom(
1857+
CustomTransactionError::RateLimitExceeded.into(),
1858+
)
1859+
.into());
17521860
}
17531861
Ok(ValidTransaction {
17541862
priority: Self::get_priority_vanilla(),

pallets/subtensor/src/macros/dispatches.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -584,9 +584,9 @@ mod dispatches {
584584
origin: OriginFor<T>,
585585
hotkey: T::AccountId,
586586
netuid: u16,
587-
amount_staked: u64,
587+
amount: u64,
588588
) -> DispatchResult {
589-
Self::do_add_stake(origin, hotkey, netuid, amount_staked)
589+
Self::do_add_stake(origin, hotkey, netuid, amount)
590590
}
591591

592592
/// Remove stake from the staking account. The call must be made

pallets/subtensor/src/macros/errors.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ mod errors {
2525
/// Request to stake, unstake or subscribe is made by a coldkey that is not associated with
2626
/// the hotkey account.
2727
NonAssociatedColdKey,
28-
/// Stake amount to withdraw is zero.
29-
StakeToWithdrawIsZero,
28+
/// DEPRECATED: Stake amount to withdraw is zero.
29+
// StakeToWithdrawIsZero,
3030
/// The caller does not have enought stake to perform this action.
3131
NotEnoughStake,
3232
/// The caller is requesting removing more stake than there exists in the staking account.

pallets/subtensor/src/staking/add_stake.rs

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -47,30 +47,14 @@ impl<T: Config> Pallet<T> {
4747
stake_to_be_added
4848
);
4949

50-
// 2. Ensure that the subnet exists.
51-
ensure!(Self::if_subnet_exist(netuid), Error::<T>::SubnetNotExists);
50+
// 2. Validate user input
51+
Self::validate_add_stake(&coldkey, &hotkey, netuid, stake_to_be_added)?;
5252

53-
// 3. Ensure the callers coldkey has enough stake to perform the transaction.
54-
ensure!(
55-
Self::can_remove_balance_from_coldkey_account(&coldkey, stake_to_be_added),
56-
Error::<T>::NotEnoughBalanceToStake
57-
);
58-
59-
// 4. Ensure that the hotkey account exists this is only possible through registration.
60-
ensure!(
61-
Self::hotkey_account_exists(&hotkey),
62-
Error::<T>::HotKeyAccountNotExists
63-
);
64-
65-
// Ensure stake_to_be_added is at least DefaultMinStake plus fee
66-
let min_amount = DefaultMinStake::<T>::get().saturating_add(DefaultStakingFee::<T>::get());
67-
ensure!(stake_to_be_added >= min_amount, Error::<T>::AmountTooLow);
68-
69-
// 5. Ensure the remove operation from the coldkey is a success.
53+
// 3. Ensure the remove operation from the coldkey is a success.
7054
let tao_staked: u64 =
7155
Self::remove_balance_from_coldkey_account(&coldkey, stake_to_be_added)?;
7256

73-
// 6. Swap the stake into alpha on the subnet and increase counters.
57+
// 4. Swap the stake into alpha on the subnet and increase counters.
7458
// Emit the staking event.
7559
let fee = DefaultStakingFee::<T>::get();
7660
Self::stake_into_subnet(&hotkey, &coldkey, netuid, tao_staked, fee);

0 commit comments

Comments
 (0)