Skip to content

Commit 3c45a89

Browse files
committed
Merge branch 'devnet-ready' of https://github.com/opentensor/subtensor into devnet-ready
2 parents 54f1d33 + 7c67ab5 commit 3c45a89

File tree

5 files changed

+130
-34
lines changed

5 files changed

+130
-34
lines changed

pallets/subtensor/src/macros/genesis.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ mod genesis {
4949
let hotkey = DefaultAccount::<T>::get();
5050
SubnetMechanism::<T>::insert(netuid, 1); // Make dynamic.
5151
Owner::<T>::insert(hotkey.clone(), hotkey.clone());
52-
SubnetAlphaIn::<T>::insert(netuid, 1);
52+
SubnetAlphaIn::<T>::insert(netuid, 10_000_000_000);
5353
SubnetTAO::<T>::insert(netuid, 10_000_000_000);
5454
NetworksAdded::<T>::insert(netuid, true);
5555
TotalNetworks::<T>::mutate(|n| *n = n.saturating_add(1));

runtime/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
220220
// `spec_version`, and `authoring_version` are the same between Wasm and native.
221221
// This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use
222222
// the compatible custom types.
223-
spec_version: 221,
223+
spec_version: 222,
224224
impl_version: 1,
225225
apis: RUNTIME_API_VERSIONS,
226226
transaction_version: 1,

runtime/src/precompiles/solidity/staking.abi

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,45 @@
77
"type": "bytes32"
88
},
99
{
10-
"internalType": "uint16",
10+
"internalType": "uint256",
1111
"name": "netuid",
12-
"type": "uint16"
12+
"type": "uint256"
1313
}
1414
],
1515
"name": "addStake",
1616
"outputs": [],
1717
"stateMutability": "payable",
1818
"type": "function"
1919
},
20+
{
21+
"inputs": [
22+
{
23+
"internalType": "bytes32",
24+
"name": "hotkey",
25+
"type": "bytes32"
26+
},
27+
{
28+
"internalType": "bytes32",
29+
"name": "coldkey",
30+
"type": "bytes32"
31+
},
32+
{
33+
"internalType": "uint256",
34+
"name": "netuid",
35+
"type": "uint256"
36+
}
37+
],
38+
"name": "getStake",
39+
"outputs": [
40+
{
41+
"internalType": "uint256",
42+
"name": "",
43+
"type": "uint256"
44+
}
45+
],
46+
"stateMutability": "view",
47+
"type": "function"
48+
},
2049
{
2150
"inputs": [
2251
{
@@ -30,14 +59,14 @@
3059
"type": "uint256"
3160
},
3261
{
33-
"internalType": "uint16",
62+
"internalType": "uint256",
3463
"name": "netuid",
35-
"type": "uint16"
64+
"type": "uint256"
3665
}
3766
],
3867
"name": "removeStake",
3968
"outputs": [],
40-
"stateMutability": "payable",
69+
"stateMutability": "nonpayable",
4170
"type": "function"
4271
},
4372
{
@@ -59,4 +88,4 @@
5988
"stateMutability": "view",
6089
"type": "function"
6190
}
62-
]
91+
]

runtime/src/precompiles/solidity/staking.sol

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ interface IStaking {
1414
* https://github.com/polkadot-evm/frontier/blob/2e219e17a526125da003e64ef22ec037917083fa/frame/evm/src/lib.rs#L739
1515
*
1616
* @param hotkey The hotkey public key (32 bytes).
17-
* @param netuid The subnet to stake to (uint16). Currently a noop, functionality will be enabled with RAO.
17+
* @param netuid The subnet to stake to (uint256).
1818
*
1919
* Requirements:
2020
* - `hotkey` must be a valid hotkey registered on the network, ensuring that the stake is
2121
* correctly attributed.
2222
*/
23-
function addStake(bytes32 hotkey, uint16 netuid) external payable;
23+
function addStake(bytes32 hotkey, uint256 netuid) external payable;
2424

2525
/**
2626
* @dev Removes a subtensor stake `amount` from the specified `hotkey`.
@@ -33,8 +33,7 @@ interface IStaking {
3333
*
3434
* @param hotkey The hotkey public key (32 bytes).
3535
* @param amount The amount to unstake in rao.
36-
* @param netuid The subnet to stake to (uint16). Currently a noop, functionality will be enabled with RAO.
37-
36+
* @param netuid The subnet to stake to (uint256).
3837
*
3938
* Requirements:
4039
* - `hotkey` must be a valid hotkey registered on the network, ensuring that the stake is
@@ -44,14 +43,27 @@ interface IStaking {
4443
function removeStake(bytes32 hotkey, uint256 amount, uint16 netuid) external;
4544

4645
/**
47-
* @dev Returns the amount of RAO staked by the coldkey associated with the hotkey.
46+
* @dev Returns the amount of RAO staked by the coldkey.
4847
*
4948
* This function allows external accounts and contracts to query the amount of RAO staked by the coldkey
50-
* associated with the coldkey, which effectively calls `get_coldkey_stake` on the subtensor pallet with
49+
* which effectively calls `get_coldkey_stake` on the subtensor pallet with
5150
* specified coldkey as a parameter.
5251
*
5352
* @param coldkey The coldkey public key (32 bytes).
54-
* @return The amount of RAO staked by the coldkey associated with the hotkey.
53+
* @return The amount of RAO staked by the coldkey.
5554
*/
5655
function getStakeColdkey(bytes32 coldkey) external view returns (uint256);
56+
57+
/**
58+
* @dev Returns the stake amount associated with the specified `hotkey` and `coldkey`.
59+
*
60+
* This function retrieves the current stake amount linked to a specific hotkey and coldkey pair.
61+
* It is a view function, meaning it does not modify the state of the contract and is free to call.
62+
*
63+
* @param hotkey The hotkey public key (32 bytes).
64+
* @param coldkey The coldkey public key (32 bytes).
65+
* @param netuid The subnet the stake is on (uint256).
66+
* @return The current stake amount in uint256 format.
67+
*/
68+
function getStake(bytes32 hotkey, bytes32 coldkey, uint256 netuid) external view returns (uint256);
5769
}

runtime/src/precompiles/staking.rs

Lines changed: 74 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -53,27 +53,28 @@ impl StakingPrecompile {
5353
.map_or_else(vec::Vec::new, |slice| slice.to_vec()); // Avoiding borrowing conflicts
5454

5555
match method_id {
56-
id if id == get_method_id("addStake(bytes32,uint16)") => {
56+
id if id == get_method_id("addStake(bytes32,uint256)") => {
5757
Self::add_stake(handle, &method_input)
5858
}
59-
id if id == get_method_id("removeStake(bytes32,uint256,uint16)") => {
59+
id if id == get_method_id("removeStake(bytes32,uint256,uint256)") => {
6060
Self::remove_stake(handle, &method_input)
6161
}
6262
id if id == get_method_id("getStakeColdkey(bytes32)") => {
6363
Self::get_stake_coldkey(&method_input)
6464
}
65+
id if id == get_method_id("getStake(bytes32,bytes32,uint256)") => {
66+
Self::get_stake(&method_input)
67+
}
6568
_ => Err(PrecompileFailure::Error {
6669
exit_status: ExitError::InvalidRange,
6770
}),
6871
}
6972
}
7073

7174
fn add_stake(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult {
72-
let hotkey = Self::parse_ss58(data)?.into();
75+
let hotkey = Self::parse_key(data)?.into();
7376
let amount: U256 = handle.context().apparent_value;
74-
75-
// TODO: Use netuid method parameter here
76-
let netuid: u16 = 0;
77+
let netuid = Self::parse_netuid(data, 0x3E)?;
7778

7879
let amount_sub =
7980
<Runtime as pallet_evm::Config>::BalanceConverter::into_substrate_balance(amount)
@@ -88,11 +89,10 @@ impl StakingPrecompile {
8889
// Dispatch the add_stake call
8990
Self::dispatch(handle, call)
9091
}
91-
fn remove_stake(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult {
92-
let hotkey = Self::parse_ss58(data)?.into();
9392

94-
// TODO: Use netuid method parameter here
95-
let netuid: u16 = 0;
93+
fn remove_stake(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult {
94+
let hotkey = Self::parse_key(data)?.into();
95+
let netuid = Self::parse_netuid(data, 0x5E)?;
9696

9797
// We have to treat this as uint256 (because of Solidity ABI encoding rules, it pads uint64),
9898
// but this will never exceed 8 bytes, se we will ignore higher bytes and will only use lower
@@ -114,11 +114,10 @@ impl StakingPrecompile {
114114
}
115115

116116
fn get_stake_coldkey(data: &[u8]) -> PrecompileResult {
117-
// TODO: rename parse_ss58 to parse_key or something?
118-
let coldkey: AccountId32 = Self::parse_ss58(data)?.into();
117+
let coldkey: AccountId32 = Self::parse_key(data)?.into();
119118

120119
// get total stake of coldkey
121-
let total_stake = pallet_subtensor::TotalColdkeyStake::<Runtime>::get(coldkey);
120+
let total_stake = pallet_subtensor::Pallet::<Runtime>::get_total_stake_for_coldkey(&coldkey);
122121
let result_u256 = U256::from(total_stake);
123122
let mut result = [0_u8; 32];
124123
U256::to_big_endian(&result_u256, &mut result);
@@ -129,15 +128,68 @@ impl StakingPrecompile {
129128
})
130129
}
131130

132-
fn parse_ss58(data: &[u8]) -> Result<[u8; 32], PrecompileFailure> {
133-
if data.len() < 32 {
131+
fn get_stake(data: &[u8]) -> PrecompileResult {
132+
let (hotkey, coldkey) = Self::parse_hotkey_coldkey(data)?;
133+
let netuid: u16 = Self::parse_netuid(data, 0x5E)?;
134+
135+
let stake = pallet_subtensor::Pallet::<Runtime>::get_stake_for_hotkey_and_coldkey_on_subnet(
136+
&hotkey.into(),
137+
&coldkey.into(),
138+
netuid,
139+
);
140+
141+
// Convert to EVM decimals
142+
let stake_u256 = U256::from(stake);
143+
let stake_eth =
144+
<Runtime as pallet_evm::Config>::BalanceConverter::into_evm_balance(stake_u256)
145+
.ok_or(ExitError::InvalidRange)?;
146+
147+
// Format output
148+
let mut result = [0_u8; 32];
149+
U256::to_big_endian(&stake_eth, &mut result);
150+
151+
Ok(PrecompileOutput {
152+
exit_status: ExitSucceed::Returned,
153+
output: result.into(),
154+
})
155+
}
156+
157+
fn parse_hotkey_coldkey(data: &[u8]) -> Result<([u8; 32], [u8; 32]), PrecompileFailure> {
158+
if data.len() < 64 {
134159
return Err(PrecompileFailure::Error {
135160
exit_status: ExitError::InvalidRange,
136161
});
137162
}
138163
let mut hotkey = [0u8; 32];
139164
hotkey.copy_from_slice(get_slice(data, 0, 32)?);
140-
Ok(hotkey)
165+
let mut coldkey = [0u8; 32];
166+
coldkey.copy_from_slice(get_slice(data, 32, 64)?);
167+
Ok((hotkey, coldkey))
168+
}
169+
170+
fn parse_key(data: &[u8]) -> Result<[u8; 32], PrecompileFailure> {
171+
if data.len() < 32 {
172+
return Err(PrecompileFailure::Error {
173+
exit_status: ExitError::InvalidRange,
174+
});
175+
}
176+
let mut key = [0u8; 32];
177+
key.copy_from_slice(get_slice(data, 0, 32)?);
178+
Ok(key)
179+
}
180+
181+
fn parse_netuid(data: &[u8], offset: usize) -> Result<u16, PrecompileFailure> {
182+
if data.len() < offset + 2 {
183+
return Err(PrecompileFailure::Error {
184+
exit_status: ExitError::InvalidRange,
185+
});
186+
}
187+
188+
let mut netuid_bytes = [0u8; 2];
189+
netuid_bytes.copy_from_slice(get_slice(data, offset, offset + 2)?);
190+
let netuid: u16 = netuid_bytes[1] as u16 | ((netuid_bytes[0] as u16) << 8u16);
191+
192+
Ok(netuid)
141193
}
142194

143195
fn dispatch(handle: &mut impl PrecompileHandle, call: RuntimeCall) -> PrecompileResult {
@@ -164,9 +216,12 @@ impl StakingPrecompile {
164216
exit_status: ExitSucceed::Returned,
165217
output: vec![],
166218
}),
167-
Err(_) => Err(PrecompileFailure::Error {
168-
exit_status: ExitError::Other("Subtensor call failed".into()),
169-
}),
219+
Err(_) => {
220+
log::warn!("Returning error PrecompileFailure::Error");
221+
Err(PrecompileFailure::Error {
222+
exit_status: ExitError::Other("Subtensor call failed".into()),
223+
})
224+
}
170225
}
171226
}
172227

0 commit comments

Comments
 (0)