@@ -47,8 +47,43 @@ impl<const N_ARGS: usize> Opcode for CallOpcode<N_ARGS> {
47
47
state. call_expand_memory ( args_offset, args_length, ret_offset, ret_length) ?;
48
48
49
49
let tx_id = state. tx_ctx . id ( ) ;
50
- let callee_call = state . parse_call ( geth_step) ?;
50
+ let callee_kind = CallKind :: try_from ( geth_step. op ) ?;
51
51
let caller_call = state. call ( ) ?. clone ( ) ;
52
+ // we need those information but we haven't parse callee's call yet
53
+ let caller_address = match callee_kind {
54
+ CallKind :: Call | CallKind :: CallCode | CallKind :: StaticCall => caller_call. address ,
55
+ CallKind :: DelegateCall => caller_call. caller_address ,
56
+ CallKind :: Create | CallKind :: Create2 => {
57
+ unreachable ! ( "CREATE opcode handled in create.rs" )
58
+ }
59
+ } ;
60
+ let ( found, sender_account) = state. sdb . get_account ( & caller_address) ;
61
+ debug_assert ! ( found) ;
62
+ let caller_balance = sender_account. balance ;
63
+ let call_value = match callee_kind {
64
+ CallKind :: Call | CallKind :: CallCode => geth_step. stack . nth_last ( 2 ) ?,
65
+ CallKind :: DelegateCall => caller_call. value ,
66
+ CallKind :: StaticCall => Word :: zero ( ) ,
67
+ CallKind :: Create | CallKind :: Create2 => {
68
+ unreachable ! ( "CREATE opcode handled in create.rs" )
69
+ }
70
+ } ;
71
+ // Precheck is OK when depth is in range and caller balance is sufficient.
72
+ let is_call_or_callcode = matches ! ( callee_kind, CallKind :: Call | CallKind :: CallCode ) ;
73
+ let is_precheck_ok =
74
+ geth_step. depth < 1025 && ( !is_call_or_callcode || caller_balance >= call_value) ;
75
+
76
+ let callee_call = if is_precheck_ok {
77
+ state. parse_call ( geth_step) ?
78
+ } else {
79
+ // if precheck not ok, the call won't appear in call trace since it never happens
80
+ // we need to increase the offset and mannually set the is_success
81
+ state. tx_ctx . call_is_success_offset += 1 ;
82
+ let mut call = state. parse_call_partial ( geth_step) ?;
83
+ call. is_success = false ;
84
+ call. is_persistent = false ;
85
+ call
86
+ } ;
52
87
53
88
// For both CALLCODE and DELEGATECALL opcodes, `call.address` is caller
54
89
// address which is different from callee_address (code address).
@@ -146,17 +181,6 @@ impl<const N_ARGS: usize> Opcode for CallOpcode<N_ARGS> {
146
181
state. call_context_write ( & mut exec_step, callee_call. call_id , field, value) ?;
147
182
}
148
183
149
- let ( found, sender_account) = state. sdb . get_account ( & callee_call. caller_address ) ;
150
- debug_assert ! ( found) ;
151
-
152
- let caller_balance = sender_account. balance ;
153
- let is_call_or_callcode =
154
- callee_call. kind == CallKind :: Call || callee_call. kind == CallKind :: CallCode ;
155
-
156
- // Precheck is OK when depth is in range and caller balance is sufficient.
157
- let is_precheck_ok =
158
- geth_step. depth < 1025 && ( !is_call_or_callcode || caller_balance >= callee_call. value ) ;
159
-
160
184
// read balance of caller to compare to value for insufficient_balance checking
161
185
// in circuit, also use for callcode successful case check balance is
162
186
// indeed larger than transfer value. for call opcode, it does in
@@ -465,11 +489,8 @@ impl<const N_ARGS: usize> Opcode for CallOpcode<N_ARGS> {
465
489
callee_gas_left_with_stipend,
466
490
) ;
467
491
468
- let mut oog_step = ErrorOOGPrecompile :: gen_associated_ops (
469
- state,
470
- & geth_steps[ 1 ] ,
471
- callee_call. clone ( ) ,
472
- ) ?;
492
+ let mut oog_step =
493
+ ErrorOOGPrecompile :: gen_associated_ops ( state, & geth_steps[ 1 ] , callee_call) ?;
473
494
474
495
oog_step. gas_left = Gas ( callee_gas_left_with_stipend) ;
475
496
oog_step. gas_cost = GasCost ( precompile_call_gas_cost) ;
@@ -482,7 +503,7 @@ impl<const N_ARGS: usize> Opcode for CallOpcode<N_ARGS> {
482
503
let mut precompile_step = precompile_associated_ops (
483
504
state,
484
505
geth_steps[ 1 ] . clone ( ) ,
485
- callee_call. clone ( ) ,
506
+ callee_call,
486
507
precompile_call,
487
508
& input_bytes. unwrap_or_default ( ) ,
488
509
& output_bytes. unwrap_or_default ( ) ,
0 commit comments