Skip to content

Commit 7bbba0a

Browse files
authored
Merge pull request #1123 from opentensor/feat/proxy-precompile-extension
Extend staking contract with proxy setting
2 parents 7c67ab5 + 2874d95 commit 7bbba0a

File tree

3 files changed

+88
-20
lines changed

3 files changed

+88
-20
lines changed

runtime/src/precompiles/solidity/staking.abi

Lines changed: 26 additions & 0 deletions
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
{

runtime/src/precompiles/solidity/staking.sol

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,20 @@ interface IStaking {
4242
*/
4343
function removeStake(bytes32 hotkey, uint256 amount, uint256 netuid) external;
4444

45+
/**
46+
* @dev Delegates staking to a proxy account.
47+
*
48+
* @param delegate The public key (32 bytes) of the delegate.
49+
*/
50+
function addProxy(bytes32 delegate) external;
51+
52+
/**
53+
* @dev Removes staking proxy account.
54+
*
55+
* @param delegate The public key (32 bytes) of the delegate.
56+
*/
57+
function removeProxy(bytes32 delegate) external;
58+
4559
/**
4660
* @dev Returns the stake amount associated with the specified `hotkey` and `coldkey`.
4761
*

runtime/src/precompiles/staking.rs

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,13 @@ use pallet_evm::{
3333
use sp_core::crypto::Ss58Codec;
3434
use sp_core::U256;
3535
use sp_runtime::traits::Dispatchable;
36-
use sp_runtime::traits::{BlakeTwo256, UniqueSaturatedInto};
36+
use sp_runtime::traits::{BlakeTwo256, StaticLookup, 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,24 +55,25 @@ 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,uint256)") => {
57-
Self::add_stake(handle, &method_input)
58-
}
59-
id if id == get_method_id("removeStake(bytes32,uint256,uint256)") => {
60-
Self::remove_stake(handle, &method_input)
61-
}
62-
id if id == get_method_id("getStake(bytes32,bytes32,uint256)") => {
63-
Self::get_stake(&method_input)
64-
}
65-
_ => Err(PrecompileFailure::Error {
58+
if method_id == get_method_id("addStake(bytes32,uint256)") {
59+
Self::add_stake(handle, &method_input)
60+
} else if method_id == get_method_id("removeStake(bytes32,uint256,uint256)") {
61+
Self::remove_stake(handle, &method_input)
62+
} else if method_id == get_method_id("getStake(bytes32,bytes32,uint256)") {
63+
Self::get_stake(&method_input)
64+
} else if method_id == get_method_id("addProxy(bytes32)") {
65+
Self::add_proxy(handle, &method_input)
66+
} else if method_id == get_method_id("removeProxy(bytes32)") {
67+
Self::remove_proxy(handle, &method_input)
68+
} else {
69+
Err(PrecompileFailure::Error {
6670
exit_status: ExitError::InvalidRange,
67-
}),
71+
})
6872
}
6973
}
7074

7175
fn add_stake(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult {
72-
let hotkey = Self::parse_hotkey(data)?.into();
76+
let hotkey = Self::parse_pub_key(data)?.into();
7377
let amount: U256 = handle.context().apparent_value;
7478
let netuid = Self::parse_netuid(data, 0x3E)?;
7579

@@ -88,7 +92,7 @@ impl StakingPrecompile {
8892
}
8993

9094
fn remove_stake(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult {
91-
let hotkey = Self::parse_hotkey(data)?.into();
95+
let hotkey = Self::parse_pub_key(data)?.into();
9296
let netuid = Self::parse_netuid(data, 0x5E)?;
9397

9498
// We have to treat this as uint256 (because of Solidity ABI encoding rules, it pads uint64),
@@ -110,6 +114,30 @@ impl StakingPrecompile {
110114
Self::dispatch(handle, call)
111115
}
112116

117+
fn add_proxy(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult {
118+
let delegate = AccountId32::from(Self::parse_pub_key(data)?);
119+
let delegate = <Runtime as frame_system::Config>::Lookup::unlookup(delegate);
120+
let call = RuntimeCall::Proxy(pallet_proxy::Call::<Runtime>::add_proxy {
121+
delegate,
122+
proxy_type: ProxyType::Staking,
123+
delay: 0,
124+
});
125+
126+
Self::dispatch(handle, call)
127+
}
128+
129+
fn remove_proxy(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult {
130+
let delegate = AccountId32::from(Self::parse_pub_key(data)?);
131+
let delegate = <Runtime as frame_system::Config>::Lookup::unlookup(delegate);
132+
let call = RuntimeCall::Proxy(pallet_proxy::Call::<Runtime>::remove_proxy {
133+
delegate,
134+
proxy_type: ProxyType::Staking,
135+
delay: 0,
136+
});
137+
138+
Self::dispatch(handle, call)
139+
}
140+
113141
fn get_stake(data: &[u8]) -> PrecompileResult {
114142
let (hotkey, coldkey) = Self::parse_hotkey_coldkey(data)?;
115143
let netuid = Self::parse_netuid(data, 0x5E)?;
@@ -149,15 +177,15 @@ impl StakingPrecompile {
149177
Ok((hotkey, coldkey))
150178
}
151179

152-
fn parse_hotkey(data: &[u8]) -> Result<[u8; 32], PrecompileFailure> {
180+
fn parse_pub_key(data: &[u8]) -> Result<[u8; 32], PrecompileFailure> {
153181
if data.len() < 32 {
154182
return Err(PrecompileFailure::Error {
155183
exit_status: ExitError::InvalidRange,
156184
});
157185
}
158-
let mut hotkey = [0u8; 32];
159-
hotkey.copy_from_slice(get_slice(data, 0, 32)?);
160-
Ok(hotkey)
186+
let mut pubkey = [0u8; 32];
187+
pubkey.copy_from_slice(get_slice(data, 0, 32)?);
188+
Ok(pubkey)
161189
}
162190

163191
fn parse_netuid(data: &[u8], offset: usize) -> Result<u16, PrecompileFailure> {

0 commit comments

Comments
 (0)