Skip to main content
Call frame context mappings describe how assertions can use matched call context and call-scoped snapshots to validate state around a specific function call.

Status

  • Supported
  • Partially Supported
  • Not Supported Yet

Implementation Details

Required Cheatcodes

  • getCallInputs(address aa, bytes4 signature) - Gets call inputs with unique IDs
  • context() - Gets the currently matched onFnCall trigger context
  • loadStateAt(address target, bytes32 slot, ForkId fork) - Reads storage at a call-scoped snapshot

Example Implementation

Protocol:
Assertion:

Implementation Notes

  • Call frame isolation:
    • Use registerFnCallTrigger() to execute once for each matched call
    • Use ph.context() to read the matched call’s callStart and callEnd
    • Construct PhEvm.ForkId({forkType: 2, callIndex: ctx.callStart}) and PhEvm.ForkId({forkType: 3, callIndex: ctx.callEnd}) for call-scoped snapshots
    • This allows validation at the individual function call level, not just transaction level
  • Benefits over transaction-level assertions:
    • Provides more precise state validation at the individual function call level
    • Allows validation of intermediate states within a transaction
    • Makes complex, multi-function transactions easier to validate
    • Can catch issues that would be masked by transaction-level checks
  • When to use call frame context vs transaction context:
    • Use call-scoped ForkId values when you need to validate individual calls within a transaction
    • Use transaction-scoped ForkId values when you only need to compare overall transaction state
    • Call frame context is especially useful for batch operations, multi-step protocols, or when validating intermediate states

Example Use Cases

  • Batch operations: Validate each individual operation within a batch transaction
  • Multi-step protocols: Check state at each step of a complex transaction
  • Oracle price updates: Verify each price update doesn’t exceed deviation limits (see Intra-TX Oracle Deviation)
  • Rate provider validation: Check rate changes before and after swaps (see Balancer V2 Stable Rate Exploit)

Implementation Considerations

  • Recursive function calls: Recursive calls compound state changes similar to transaction-level execution. Account for recursive call paths when precise call frame tracking is required.