Skip to content

Commit 3ad54bb

Browse files
committed
Extend staking contract with proxy setting
1 parent d261f67 commit 3ad54bb

File tree

3 files changed

+85
-17
lines changed

3 files changed

+85
-17
lines changed

runtime/src/precompiles/solidity/staking.abi

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,17 @@
11
[
2+
{
3+
"inputs": [
4+
{
5+
"internalType": "bytes32",
6+
"name": "delegate",
7+
"type": "bytes32"
8+
}
9+
],
10+
"name": "addProxy",
11+
"outputs": [],
12+
"stateMutability": "nonpayable",
13+
"type": "function"
14+
},
215
{
316
"inputs": [
417
{
@@ -17,6 +30,19 @@
1730
"stateMutability": "payable",
1831
"type": "function"
1932
},
33+
{
34+
"inputs": [
35+
{
36+
"internalType": "bytes32",
37+
"name": "delegate",
38+
"type": "bytes32"
39+
}
40+
],
41+
"name": "removeProxy",
42+
"outputs": [],
43+
"stateMutability": "nonpayable",
44+
"type": "function"
45+
},
2046
{
2147
"inputs": [
2248
{
@@ -37,7 +63,7 @@
3763
],
3864
"name": "removeStake",
3965
"outputs": [],
40-
"stateMutability": "payable",
66+
"stateMutability": "nonpayable",
4167
"type": "function"
4268
}
4369
]

runtime/src/precompiles/solidity/staking.sol

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,18 @@ interface IStaking {
4242
* - The existing stake amount must be not lower than specified amount
4343
*/
4444
function removeStake(bytes32 hotkey, uint256 amount, uint16 netuid) external;
45+
46+
/**
47+
* @dev Delegates staking to a proxy account.
48+
*
49+
* @param delegate The public key (32 bytes) of the delegate.
50+
*/
51+
function addProxy(bytes32 delegate) external;
52+
53+
/**
54+
* @dev Removes staking proxy account.
55+
*
56+
* @param delegate The public key (32 bytes) of the delegate.
57+
*/
58+
function removeProxy(bytes32 delegate) external;
4559
}

runtime/src/precompiles/staking.rs

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ use sp_runtime::traits::Dispatchable;
3636
use sp_runtime::traits::{BlakeTwo256, UniqueSaturatedInto};
3737
use sp_runtime::AccountId32;
3838

39-
use crate::precompiles::{get_method_id, get_slice};
39+
use crate::{
40+
precompiles::{get_method_id, get_slice},
41+
ProxyType,
42+
};
4043
use sp_std::vec;
4144

4245
use crate::{Runtime, RuntimeCall};
@@ -52,21 +55,23 @@ impl StakingPrecompile {
5255
.get(4..)
5356
.map_or_else(vec::Vec::new, |slice| slice.to_vec()); // Avoiding borrowing conflicts
5457

55-
match method_id {
56-
id if id == get_method_id("addStake(bytes32,uint16)") => {
57-
Self::add_stake(handle, &method_input)
58-
}
59-
id if id == get_method_id("removeStake(bytes32,uint256,uint16)") => {
60-
Self::remove_stake(handle, &method_input)
61-
}
62-
_ => Err(PrecompileFailure::Error {
58+
if method_id == get_method_id("addStake(bytes32,uint16)") {
59+
Self::add_stake(handle, &method_input)
60+
} else if method_id == get_method_id("removeStake(bytes32,uint256,uint16)") {
61+
Self::remove_stake(handle, &method_input)
62+
} else if method_id == get_method_id("addProxy(bytes32)") {
63+
Self::add_proxy(handle, &method_input)
64+
} else if method_id == get_method_id("removeProxy(bytes32)") {
65+
Self::remove_proxy(handle, &method_input)
66+
} else {
67+
Err(PrecompileFailure::Error {
6368
exit_status: ExitError::InvalidRange,
64-
}),
69+
})
6570
}
6671
}
6772

6873
fn add_stake(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult {
69-
let hotkey = Self::parse_hotkey(data)?.into();
74+
let hotkey = Self::parse_pub_key(data)?.into();
7075
let amount: U256 = handle.context().apparent_value;
7176
let amount_sub =
7277
<Runtime as pallet_evm::Config>::BalanceConverter::into_substrate_balance(amount)
@@ -80,8 +85,9 @@ impl StakingPrecompile {
8085
// Dispatch the add_stake call
8186
Self::dispatch(handle, call)
8287
}
88+
8389
fn remove_stake(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult {
84-
let hotkey = Self::parse_hotkey(data)?.into();
90+
let hotkey = Self::parse_pub_key(data)?.into();
8591

8692
// We have to treat this as uint256 (because of Solidity ABI encoding rules, it pads uint64),
8793
// but this will never exceed 8 bytes, se we will ignore higher bytes and will only use lower
@@ -101,15 +107,37 @@ impl StakingPrecompile {
101107
Self::dispatch(handle, call)
102108
}
103109

104-
fn parse_hotkey(data: &[u8]) -> Result<[u8; 32], PrecompileFailure> {
110+
fn add_proxy(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult {
111+
let delegate = Self::parse_pub_key(data)?;
112+
let call = RuntimeCall::Proxy(pallet_proxy::Call::<Runtime>::add_proxy {
113+
delegate,
114+
proxy_type: ProxyType::Staking,
115+
delay: 0,
116+
});
117+
118+
Self::dispatch(handle, call)
119+
}
120+
121+
fn remove_proxy(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult {
122+
let delegate = Self::parse_pub_key(data)?;
123+
let call = RuntimeCall::Proxy(pallet_proxy::Call::<Runtime>::remove_proxy {
124+
delegate,
125+
proxy_type: ProxyType::Staking,
126+
delay: 0,
127+
});
128+
129+
Self::dispatch(handle, call)
130+
}
131+
132+
fn parse_pub_key(data: &[u8]) -> Result<[u8; 32], PrecompileFailure> {
105133
if data.len() < 32 {
106134
return Err(PrecompileFailure::Error {
107135
exit_status: ExitError::InvalidRange,
108136
});
109137
}
110-
let mut hotkey = [0u8; 32];
111-
hotkey.copy_from_slice(get_slice(data, 0, 32)?);
112-
Ok(hotkey)
138+
let mut pubkey = [0u8; 32];
139+
pubkey.copy_from_slice(get_slice(data, 0, 32)?);
140+
Ok(pubkey)
113141
}
114142

115143
fn dispatch(handle: &mut impl PrecompileHandle, call: RuntimeCall) -> PrecompileResult {

0 commit comments

Comments
 (0)