1
- use anyhow:: Context as _ ;
1
+ use anyhow:: Context ;
2
2
use derive_more:: { Deref , DerefMut } ;
3
3
use fvm_ipld_encoding:: { RawBytes , DAG_CBOR } ;
4
4
use fvm_shared:: actor:: builtin:: Type ;
5
5
use fvm_shared:: address:: { Address , Protocol } ;
6
6
use fvm_shared:: econ:: TokenAmount ;
7
7
use fvm_shared:: error:: ExitCode ;
8
+ use fvm_shared:: version:: NetworkVersion ;
8
9
use fvm_shared:: { ActorID , MethodNum , METHOD_SEND } ;
9
10
use num_traits:: Zero ;
10
11
@@ -294,7 +295,19 @@ where
294
295
} ;
295
296
296
297
// Make a store.
298
+ let gas_available = kernel. gas_available ( ) ;
299
+ let exec_units_to_add = match kernel. network_version ( ) {
300
+ NetworkVersion :: V14 | NetworkVersion :: V15 => i64:: MAX ,
301
+ _ => kernel. price_list ( ) . gas_to_exec_units ( gas_available, false ) ,
302
+ } ;
303
+
297
304
let mut store = engine. new_store ( kernel) ;
305
+ if let Err ( err) = store. add_fuel ( u64:: try_from ( exec_units_to_add) . unwrap_or ( 0 ) ) {
306
+ return (
307
+ Err ( ExecutionError :: Fatal ( err) ) ,
308
+ store. into_data ( ) . kernel . take ( ) ,
309
+ ) ;
310
+ }
298
311
299
312
// Instantiate the module.
300
313
let instance = match engine
@@ -315,12 +328,30 @@ where
315
328
. map_err ( Abort :: Fatal ) ?;
316
329
317
330
// Invoke it.
318
- let return_block_id = invoke. call ( & mut store, ( param_id, ) ) ?;
331
+ let res = invoke. call ( & mut store, ( param_id, ) ) ;
332
+
333
+ // Charge gas for the "latest" use of execution units (all the exec units used since the most recent syscall)
334
+ // We do this by first loading the _total_ execution units consumed
335
+ let exec_units_consumed = store
336
+ . fuel_consumed ( )
337
+ . context ( "expected to find fuel consumed" )
338
+ . map_err ( Abort :: Fatal ) ?;
339
+ // Then, pass the _total_ exec_units_consumed to the InvocationData,
340
+ // which knows how many execution units had been consumed at the most recent snapshot
341
+ // It will charge gas for the delta between the total units (the number we provide) and its snapshot
342
+ store
343
+ . data_mut ( )
344
+ . charge_gas_for_exec_units ( exec_units_consumed)
345
+ . map_err ( |e| Abort :: from_error ( ExitCode :: SYS_ASSERTION_FAILED , e) ) ?;
346
+
347
+ // If the invocation failed due to running out of exec_units, we have already detected it and returned OutOfGas above.
348
+ // Any other invocation failure is returned here as an Abort
349
+ let return_block_id = res?;
319
350
320
351
// Extract the return value, if there is one.
321
352
let return_value: RawBytes = if return_block_id > NO_DATA_BLOCK_ID {
322
353
let ( code, ret) = store
323
- . data ( )
354
+ . data_mut ( )
324
355
. kernel
325
356
. block_get ( return_block_id)
326
357
. map_err ( |e| Abort :: from_error ( ExitCode :: SYS_MISSING_RETURN , e) ) ?;
0 commit comments