25
25
// - Precompile checks the result of do_remove_stake and, in case of a failure, reverts the transaction.
26
26
//
27
27
28
- use crate :: precompiles:: {
29
- get_method_id, get_pubkey, get_slice, parse_netuid, try_dispatch_runtime_call,
30
- } ;
31
- use crate :: { ProxyType , Runtime , RuntimeCall } ;
32
28
use frame_system:: RawOrigin ;
33
29
use pallet_evm:: {
34
30
AddressMapping , BalanceConverter , ExitError , ExitSucceed , HashedAddressMapping ,
35
31
PrecompileFailure , PrecompileHandle , PrecompileOutput , PrecompileResult ,
36
32
} ;
37
- use sp_core:: U256 ;
33
+ use precompile_utils:: EvmResult ;
34
+ use sp_core:: { H256 , U256 } ;
38
35
use sp_runtime:: traits:: { BlakeTwo256 , Dispatchable , StaticLookup , UniqueSaturatedInto } ;
39
36
use sp_runtime:: AccountId32 ;
40
37
use sp_std:: vec;
41
38
39
+ use crate :: precompiles:: {
40
+ get_method_id, get_pubkey, get_slice, parse_netuid, try_dispatch_runtime_call,
41
+ try_u16_from_u256,
42
+ } ;
43
+ use crate :: { ProxyType , Runtime , RuntimeCall } ;
44
+
42
45
pub const STAKING_PRECOMPILE_INDEX : u64 = 2049 ;
43
46
44
47
// ss58 public key i.e., the contract sends funds it received to the destination address from the
@@ -50,40 +53,17 @@ const CONTRACT_ADDRESS_SS58: [u8; 32] = [
50
53
51
54
pub struct StakingPrecompile ;
52
55
56
+ #[ precompile_utils:: precompile]
53
57
impl StakingPrecompile {
54
- pub fn execute ( handle : & mut impl PrecompileHandle ) -> PrecompileResult {
55
- let txdata = handle. input ( ) ;
56
- let method_id = get_slice ( txdata, 0 , 4 ) ?;
57
- let method_input = txdata
58
- . get ( 4 ..)
59
- . map_or_else ( vec:: Vec :: new, |slice| slice. to_vec ( ) ) ; // Avoiding borrowing conflicts
60
-
61
- if method_id == get_method_id ( "addStake(bytes32,uint256)" ) {
62
- Self :: add_stake ( handle, & method_input)
63
- } else if method_id == get_method_id ( "removeStake(bytes32,uint256,uint256)" ) {
64
- Self :: remove_stake ( handle, & method_input)
65
- } else if method_id == get_method_id ( "getStake(bytes32,bytes32,uint256)" ) {
66
- Self :: get_stake ( & method_input)
67
- } else if method_id == get_method_id ( "addProxy(bytes32)" ) {
68
- Self :: add_proxy ( handle, & method_input)
69
- } else if method_id == get_method_id ( "removeProxy(bytes32)" ) {
70
- Self :: remove_proxy ( handle, & method_input)
71
- } else {
72
- Err ( PrecompileFailure :: Error {
73
- exit_status : ExitError :: InvalidRange ,
74
- } )
75
- }
76
- }
77
-
78
- fn add_stake ( handle : & mut impl PrecompileHandle , data : & [ u8 ] ) -> PrecompileResult {
58
+ #[ precompile:: public( "addStake(bytes32,uint256)" ) ]
59
+ #[ precompile:: payable]
60
+ fn add_stake ( handle : & mut impl PrecompileHandle , address : H256 , netuid : U256 ) -> EvmResult < ( ) > {
79
61
let account_id =
80
62
<HashedAddressMapping < BlakeTwo256 > as AddressMapping < AccountId32 > >:: into_account_id (
81
63
handle. context ( ) . caller ,
82
64
) ;
83
65
84
- let ( hotkey, _) = get_pubkey ( data) ?;
85
- let amount: U256 = handle. context ( ) . apparent_value ;
86
- let netuid = parse_netuid ( data, 0x3E ) ?;
66
+ let amount = handle. context ( ) . apparent_value ;
87
67
88
68
if !amount. is_zero ( ) {
89
69
Self :: transfer_back_to_caller ( & account_id, amount) ?;
@@ -93,6 +73,8 @@ impl StakingPrecompile {
93
73
<Runtime as pallet_evm:: Config >:: BalanceConverter :: into_substrate_balance ( amount)
94
74
. ok_or ( ExitError :: OutOfFund ) ?;
95
75
76
+ let ( hotkey, _) = get_pubkey ( address. as_bytes ( ) ) ?;
77
+ let netuid = try_u16_from_u256 ( netuid) ?;
96
78
let call = RuntimeCall :: SubtensorModule ( pallet_subtensor:: Call :: < Runtime > :: add_stake {
97
79
hotkey,
98
80
netuid,
@@ -102,39 +84,40 @@ impl StakingPrecompile {
102
84
try_dispatch_runtime_call ( handle, call, RawOrigin :: Signed ( account_id) )
103
85
}
104
86
105
- fn remove_stake ( handle : & mut impl PrecompileHandle , data : & [ u8 ] ) -> PrecompileResult {
87
+ #[ precompile:: public( "removeStake(bytes32,uint256,uint256)" ) ]
88
+ fn remove_stake (
89
+ handle : & mut impl PrecompileHandle ,
90
+ address : H256 ,
91
+ amount : U256 ,
92
+ netuid : U256 ,
93
+ ) -> EvmResult < ( ) > {
106
94
let account_id =
107
95
<HashedAddressMapping < BlakeTwo256 > as AddressMapping < AccountId32 > >:: into_account_id (
108
96
handle. context ( ) . caller ,
109
97
) ;
110
- let ( hotkey, _) = get_pubkey ( data) ?;
111
- let netuid = parse_netuid ( data, 0x5E ) ?;
112
-
113
- // We have to treat this as uint256 (because of Solidity ABI encoding rules, it pads uint64),
114
- // but this will never exceed 8 bytes, se we will ignore higher bytes and will only use lower
115
- // 8 bytes.
116
- let amount = data
117
- . get ( 56 ..64 )
118
- . map ( U256 :: from_big_endian)
119
- . ok_or ( ExitError :: OutOfFund ) ?;
98
+
120
99
let amount_sub =
121
100
<Runtime as pallet_evm:: Config >:: BalanceConverter :: into_substrate_balance ( amount)
122
101
. ok_or ( ExitError :: OutOfFund ) ?;
123
102
103
+ let ( hotkey, _) = get_pubkey ( address. as_bytes ( ) ) ?;
104
+ let netuid = try_u16_from_u256 ( netuid) ?;
124
105
let call = RuntimeCall :: SubtensorModule ( pallet_subtensor:: Call :: < Runtime > :: remove_stake {
125
106
hotkey,
126
107
netuid,
127
108
amount_unstaked : amount_sub. unique_saturated_into ( ) ,
128
109
} ) ;
110
+
129
111
try_dispatch_runtime_call ( handle, call, RawOrigin :: Signed ( account_id) )
130
112
}
131
113
132
- fn add_proxy ( handle : & mut impl PrecompileHandle , data : & [ u8 ] ) -> PrecompileResult {
114
+ #[ precompile:: public( "addProxy(bytes32)" ) ]
115
+ fn add_proxy ( handle : & mut impl PrecompileHandle , delegate : H256 ) -> EvmResult < ( ) > {
133
116
let account_id =
134
117
<HashedAddressMapping < BlakeTwo256 > as AddressMapping < AccountId32 > >:: into_account_id (
135
118
handle. context ( ) . caller ,
136
119
) ;
137
- let ( delegate, _) = get_pubkey ( data ) ?;
120
+ let ( delegate, _) = get_pubkey ( delegate . as_bytes ( ) ) ?;
138
121
let delegate = <Runtime as frame_system:: Config >:: Lookup :: unlookup ( delegate) ;
139
122
let call = RuntimeCall :: Proxy ( pallet_proxy:: Call :: < Runtime > :: add_proxy {
140
123
delegate,
@@ -145,12 +128,13 @@ impl StakingPrecompile {
145
128
try_dispatch_runtime_call ( handle, call, RawOrigin :: Signed ( account_id) )
146
129
}
147
130
148
- fn remove_proxy ( handle : & mut impl PrecompileHandle , data : & [ u8 ] ) -> PrecompileResult {
131
+ #[ precompile:: public( "removeProxy(bytes32)" ) ]
132
+ fn remove_proxy ( handle : & mut impl PrecompileHandle , delegate : H256 ) -> EvmResult < ( ) > {
149
133
let account_id =
150
134
<HashedAddressMapping < BlakeTwo256 > as AddressMapping < AccountId32 > >:: into_account_id (
151
135
handle. context ( ) . caller ,
152
136
) ;
153
- let ( delegate, _) = get_pubkey ( data ) ?;
137
+ let ( delegate, _) = get_pubkey ( delegate . as_bytes ( ) ) ?;
154
138
let delegate = <Runtime as frame_system:: Config >:: Lookup :: unlookup ( delegate) ;
155
139
let call = RuntimeCall :: Proxy ( pallet_proxy:: Call :: < Runtime > :: remove_proxy {
156
140
delegate,
@@ -161,29 +145,25 @@ impl StakingPrecompile {
161
145
try_dispatch_runtime_call ( handle, call, RawOrigin :: Signed ( account_id) )
162
146
}
163
147
164
- fn get_stake ( data : & [ u8 ] ) -> PrecompileResult {
165
- let ( hotkey, left_data) = get_pubkey ( data) ?;
166
- let ( coldkey, _) = get_pubkey ( & left_data) ?;
167
- let netuid = parse_netuid ( data, 0x5E ) ?;
148
+ #[ precompile:: public( "getStake(bytes32,bytes32,uint256)" ) ]
149
+ #[ precompile:: view]
150
+ fn get_stake (
151
+ _: & mut impl PrecompileHandle ,
152
+ hotkey : H256 ,
153
+ coldkey : H256 ,
154
+ netuid : U256 ,
155
+ ) -> EvmResult < U256 > {
156
+ let ( hotkey, _) = get_pubkey ( hotkey. as_bytes ( ) ) ?;
157
+ let ( coldkey, _) = get_pubkey ( coldkey. as_bytes ( ) ) ?;
158
+ let netuid = try_u16_from_u256 ( netuid) ?;
168
159
169
160
let stake = pallet_subtensor:: Pallet :: < Runtime > :: get_stake_for_hotkey_and_coldkey_on_subnet (
170
161
& hotkey, & coldkey, netuid,
171
162
) ;
172
163
173
164
// Convert to EVM decimals
174
- let stake_u256 = U256 :: from ( stake) ;
175
- let stake_eth =
176
- <Runtime as pallet_evm:: Config >:: BalanceConverter :: into_evm_balance ( stake_u256)
177
- . ok_or ( ExitError :: InvalidRange ) ?;
178
-
179
- // Format output
180
- let mut result = [ 0_u8 ; 32 ] ;
181
- U256 :: to_big_endian ( & stake_eth, & mut result) ;
182
-
183
- Ok ( PrecompileOutput {
184
- exit_status : ExitSucceed :: Returned ,
185
- output : result. into ( ) ,
186
- } )
165
+ <Runtime as pallet_evm:: Config >:: BalanceConverter :: into_evm_balance ( stake. into ( ) )
166
+ . ok_or ( ExitError :: InvalidRange . into ( ) )
187
167
}
188
168
189
169
fn transfer_back_to_caller (
0 commit comments