Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions specs/error_state/ErrorOutOfGasCall.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
# ErrorOutOfGasCall state

## Procedure

Handle the corresponding out of gas errors for `CALL`, `CALLCODE`, `DELEGATECALL` and `STATICCALL` opcodes.

### EVM behavior

For this gadget, the core is to calculate gas required, there are multiple kinds of gas
consumes in call:
consumes in above call related opcodes:
1. memory expansion gas cost
2. gas cost if new account creates
3. transfer fee if has value
4. account access list costwarm/cold
4. account access list cost (warm/cold)

below is the total gas cost calculation which from [`Call` Spec](../opcode/F1CALL_F4DELEGATECALL_FASTATICCALL.md).
below is the total gas cost calculation which from [Spec of call related opcodes](../opcode/F1CALL_F4DELEGATECALL_FASTATICCALL.md).
```
GAS_COST_WARM_ACCESS := 100
GAS_COST_ACCOUNT_COLD_ACCESS := 2600
Expand All @@ -23,6 +27,7 @@ gas_cost = (
```

### Constraints

1. `gas_left < gas_cost`.
2. Current call must be failed.
3. If it's a root call, it transits to `EndTx`.
Expand Down
2 changes: 1 addition & 1 deletion src/zkevm_specs/evm/execution/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@
ExecutionState.RETURN: return_revert,
ExecutionState.ErrorOutOfGasConstant: oog_constant,
ExecutionState.ErrorInvalidJump: invalid_jump,
ExecutionState.ErrorOutOfGasCALL: oog_call,
ExecutionState.ErrorOutOfGasCall: oog_call,
ExecutionState.ErrorStack: stack_error,
# ExecutionState.ECRECOVER: ,
# ExecutionState.SHA256: ,
Expand Down
20 changes: 15 additions & 5 deletions src/zkevm_specs/evm/execution/oog_call.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,22 @@
from ..opcode import Opcode


# Handle the corresponding out of gas errors for CALL, CALLCODE, DELEGATECALL
# and STATICCALL opcodes.
def oog_call(instruction: Instruction):
# retrieve op code associated to oog call error
opcode = instruction.opcode_lookup(True)
# TODO: add CallCode etc.when handle ErrorOutOfGasCALLCODE in future implementation
instruction.constrain_equal(opcode, Opcode.CALL)
is_call, is_callcode, is_delegatecall, is_staticcall = instruction.multiple_select(
opcode, (Opcode.CALL, Opcode.CALLCODE, Opcode.DELEGATECALL, Opcode.STATICCALL)
)

# Constrain opcode must be CALL, CALLCODE, DELEGATECALL or STATICCALL.
instruction.constrain_equal(is_call + is_callcode + is_delegatecall + is_staticcall, FQ(1))

tx_id = instruction.call_context_lookup(CallContextFieldTag.TxId)

# init CallGadget to handle stack vars.
call = CallGadget(instruction, FQ(0), FQ(1), FQ(0), FQ(0))
call = CallGadget(instruction, FQ(0), is_call, is_callcode, is_delegatecall)

# TODO: handle PrecompiledContract oog cases

Expand All @@ -39,18 +45,22 @@ def oog_call(instruction: Instruction):
is_to_end_tx = instruction.is_equal(instruction.next.execution_state, ExecutionState.EndTx)
instruction.constrain_equal(FQ(instruction.curr.is_root), is_to_end_tx)

# Both CALL and CALLCODE opcodes have an extra stack pop `value` relative to
# DELEGATECALL and STATICCALL.
rw_counter_delta = 11 + is_call + is_callcode

# state transition.
if instruction.curr.is_root:
# Do step state transition
instruction.constrain_step_state_transition(
rw_counter=Transition.delta(12),
rw_counter=Transition.delta(rw_counter_delta),
call_id=Transition.same(),
)
else:
# when it is internal call, need to restore caller's state as finishing this call.
# Restore caller state to next StepState
instruction.step_state_transition_to_restored_context(
rw_counter_delta=12,
rw_counter_delta=rw_counter_delta.n,
return_data_offset=FQ(0),
return_data_length=FQ(0),
gas_left=instruction.curr.gas_left,
Expand Down
11 changes: 3 additions & 8 deletions src/zkevm_specs/evm/execution_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,9 @@ class ExecutionState(IntEnum):
ErrorOutOfGasEXTCODECOPY = auto()
ErrorOutOfGasSLOAD = auto()
ErrorOutOfGasSSTORE = auto()
ErrorOutOfGasCALL = auto()
ErrorOutOfGasCALLCODE = auto()
ErrorOutOfGasDELEGATECALL = auto()
# For CALL, CALLCODE, DELEGATECALL and STATICCALL opcodes which may run out of gas.
ErrorOutOfGasCall = auto()
ErrorOutOfGasCREATE2 = auto()
ErrorOutOfGasSTATICCALL = auto()
ErrorOutOfGasSELFDESTRUCT = auto()

# Precompile's successful cases
Expand Down Expand Up @@ -393,11 +391,8 @@ def halts_in_exception(self) -> bool:
ExecutionState.ErrorOutOfGasEXTCODECOPY,
ExecutionState.ErrorOutOfGasSLOAD,
ExecutionState.ErrorOutOfGasSSTORE,
ExecutionState.ErrorOutOfGasCALL,
ExecutionState.ErrorOutOfGasCALLCODE,
ExecutionState.ErrorOutOfGasDELEGATECALL,
ExecutionState.ErrorOutOfGasCall,
ExecutionState.ErrorOutOfGasCREATE2,
ExecutionState.ErrorOutOfGasSTATICCALL,
ExecutionState.ErrorOutOfGasSELFDESTRUCT,
]

Expand Down
Loading