@@ -255,3 +255,100 @@ pub fn get_single_u8(data: &[u8], index: usize) -> Result<u8, PrecompileFailure>
255
255
} )
256
256
}
257
257
}
258
+
259
+ pub fn get_pubkey ( data : & [ u8 ] ) -> Result < ( AccountId32 , vec:: Vec < u8 > ) , PrecompileFailure > {
260
+ let mut pubkey = [ 0u8 ; 32 ] ;
261
+ pubkey. copy_from_slice ( get_slice ( data, 0 , 32 ) ?) ;
262
+
263
+ Ok ( (
264
+ pubkey. into ( ) ,
265
+ data. get ( 32 ..)
266
+ . map_or_else ( vec:: Vec :: new, |slice| slice. to_vec ( ) ) ,
267
+ ) )
268
+ }
269
+
270
+ fn parse_netuid ( data : & [ u8 ] , offset : usize ) -> Result < u16 , PrecompileFailure > {
271
+ if data. len ( ) < offset + 2 {
272
+ return Err ( PrecompileFailure :: Error {
273
+ exit_status : ExitError :: InvalidRange ,
274
+ } ) ;
275
+ }
276
+
277
+ let mut netuid_bytes = [ 0u8 ; 2 ] ;
278
+ netuid_bytes. copy_from_slice ( get_slice ( data, offset, offset + 2 ) ?) ;
279
+ let netuid: u16 = netuid_bytes[ 1 ] as u16 | ( ( netuid_bytes[ 0 ] as u16 ) << 8u16 ) ;
280
+
281
+ Ok ( netuid)
282
+ }
283
+
284
+ fn contract_to_origin ( contract : & [ u8 ; 32 ] ) -> Result < RawOrigin < AccountId32 > , PrecompileFailure > {
285
+ let ( account_id, _) = get_pubkey ( contract) ?;
286
+ Ok ( RawOrigin :: Signed ( account_id) )
287
+ }
288
+
289
+ /// Dispatches a runtime call, but also checks and records the gas costs.
290
+ fn try_dispatch_runtime_call (
291
+ handle : & mut impl PrecompileHandle ,
292
+ call : impl Into < RuntimeCall > ,
293
+ origin : RawOrigin < AccountId32 > ,
294
+ ) -> PrecompileResult {
295
+ let call = Into :: < RuntimeCall > :: into ( call) ;
296
+ let info = call. get_dispatch_info ( ) ;
297
+
298
+ let target_gas = handle. gas_limit ( ) ;
299
+ if let Some ( gas) = target_gas {
300
+ let valid_weight =
301
+ <Runtime as pallet_evm:: Config >:: GasWeightMapping :: gas_to_weight ( gas, false ) . ref_time ( ) ;
302
+ if info. weight . ref_time ( ) > valid_weight {
303
+ return Err ( PrecompileFailure :: Error {
304
+ exit_status : ExitError :: OutOfGas ,
305
+ } ) ;
306
+ }
307
+ }
308
+
309
+ handle. record_external_cost (
310
+ Some ( info. weight . ref_time ( ) ) ,
311
+ Some ( info. weight . proof_size ( ) ) ,
312
+ None ,
313
+ ) ?;
314
+
315
+ match call. dispatch ( origin. into ( ) ) {
316
+ Ok ( post_info) => {
317
+ if post_info. pays_fee ( & info) == Pays :: Yes {
318
+ let actual_weight = post_info. actual_weight . unwrap_or ( info. weight ) ;
319
+ let cost =
320
+ <Runtime as pallet_evm:: Config >:: GasWeightMapping :: weight_to_gas ( actual_weight) ;
321
+ handle. record_cost ( cost) ?;
322
+
323
+ handle. refund_external_cost (
324
+ Some (
325
+ info. weight
326
+ . ref_time ( )
327
+ . saturating_sub ( actual_weight. ref_time ( ) ) ,
328
+ ) ,
329
+ Some (
330
+ info. weight
331
+ . proof_size ( )
332
+ . saturating_sub ( actual_weight. proof_size ( ) ) ,
333
+ ) ,
334
+ ) ;
335
+ }
336
+
337
+ log:: info!( "Dispatch succeeded. Post info: {:?}" , post_info) ;
338
+
339
+ Ok ( PrecompileOutput {
340
+ exit_status : ExitSucceed :: Returned ,
341
+ output : Default :: default ( ) ,
342
+ } )
343
+ }
344
+ Err ( e) => {
345
+ log:: error!( "Dispatch failed. Error: {:?}" , e) ;
346
+ log:: warn!( "Returning error PrecompileFailure::Error" ) ;
347
+ Err ( PrecompileFailure :: Error {
348
+ exit_status : ExitError :: Other (
349
+ format ! ( "dispatch execution failed: {}" , <& ' static str >:: from( e) ) . into ( ) ,
350
+ ) ,
351
+ } )
352
+ }
353
+ }
354
+ }
0 commit comments