Skip to main content
New to cheatcodes? Start with What are Cheatcodes? to understand what they are and why they exist.
This reference lists the Credible Layer cheatcodes exposed through credible-std. Cheatcodes are grouped by API status:
  • Legacy precompiles: launch-era APIs that remain part of the legacy assertion surface.
  • Reshiram precompiles: newer APIs based on explicit ForkId snapshot reads, call context, richer log and call inspection, and protection-suite helpers.
  • Deprecated cheatcodes: legacy fork-switching APIs. Do not use them in new assertions.
As of May 6, 2026, the v2 Reshiram spec is not live on Linea mainnet. Do not assume Reshiram-only precompiles or onFnCall and onTxEnd triggers are available on Linea mainnet until that rollout is live.

Assertion Specs

credible-std defines assertion specs in SpecRecorder.sol.
enum AssertionSpec {
    Legacy,
    Reshiram,
    Experimental
}
SpecAvailability
LegacyStandard launch precompile set. Reshiram-only precompiles are unavailable.
ReshiramReshiram precompiles plus the non-deprecated shared surface. Legacy-only fork-switching selectors are unavailable.
ExperimentalUnrestricted access to all available precompiles. May include untested or dangerous behavior.
Register the spec in the assertion constructor:
import {AssertionSpec} from "credible-std/SpecRecorder.sol";

constructor() {
    registerAssertionSpec(AssertionSpec.Reshiram);
}

Common Types

ForkId

Identifies an immutable transaction snapshot.
struct ForkId {
    uint8 forkType;
    uint256 callIndex;
}
forkTypeSnapshot
0PreTx
1PostTx
2PreCall(callIndex)
3PostCall(callIndex)
Construct ForkId values explicitly:
PhEvm.ForkId memory preTx = _preTx();
PhEvm.ForkId memory postTx = _postTx();
PhEvm.ForkId memory preCall = PhEvm.ForkId({forkType: 2, callIndex: callId});
PhEvm.ForkId memory postCall = PhEvm.ForkId({forkType: 3, callIndex: callId});

Log

Represents an Ethereum log emitted during transaction execution.
struct Log {
    bytes32[] topics;
    bytes data;
    address emitter;
}

LogQuery

Filters logs by emitter and signature.
struct LogQuery {
    address emitter;
    bytes32 signature;
}
address(0) matches any emitter. bytes32(0) matches any topic0 signature.

CallInputs

Represents call input data recorded during transaction execution.
struct CallInputs {
    bytes input;
    uint64 gas_limit;
    address bytecode_address;
    address target_address;
    address caller;
    uint256 value;
    uint256 id;
}
Use id with call-scoped APIs such as PhEvm.ForkId({forkType: 2, callIndex: id}), PhEvm.ForkId({forkType: 3, callIndex: id}), callinputAt(id), callOutputAt(id), and getLogsForCall(query, id).

Legacy Precompiles

Legacy precompiles are the standard launch-era cheatcodes. Some are still useful, but prefer the Reshiram equivalents when you need explicit snapshot selection or call-scoped behavior.

getLogs

Returns all logs emitted during the assertion-triggering transaction.
function getLogs() external returns (Log[] memory logs);
Use getLogsQuery(query, fork) when you need emitter or signature filtering, or getLogsForCall(query, callId) when you need call-scoped logs.

getAllCallInputs

Gets call inputs for a target and selector across CALL, STATICCALL, DELEGATECALL, and CALLCODE.
function getAllCallInputs(
    address target,
    bytes4 selector
) external view returns (CallInputs[] memory calls);
Prefer the opcode-specific functions below when you need to avoid double counting through proxies.

getCallInputs

Gets call inputs for CALL opcodes only.
function getCallInputs(
    address target,
    bytes4 selector
) external view returns (CallInputs[] memory calls);

getStaticCallInputs

Gets call inputs for STATICCALL opcodes only.
function getStaticCallInputs(
    address target,
    bytes4 selector
) external view returns (CallInputs[] memory calls);

getDelegateCallInputs

Gets call inputs for DELEGATECALL opcodes only.
function getDelegateCallInputs(
    address target,
    bytes4 selector
) external view returns (CallInputs[] memory calls);

getCallCodeInputs

Gets call inputs for CALLCODE opcodes only.
function getCallCodeInputs(
    address target,
    bytes4 selector
) external view returns (CallInputs[] memory calls);
Internal Solidity calls are not EVM calls and are not recorded by the call tracer. Calls made through this.someFunction() are external calls and can be recorded.

getStateChanges

Returns the sequence of values for a storage slot during transaction execution.
function getStateChanges(
    address contractAddress,
    bytes32 slot
) external view returns (bytes32[] memory stateChanges);
The returned array includes the initial value as the first element. The length is either 0 or at least 2.

State Change Helpers

StateChanges.sol provides typed helpers for reading slot changes as common Solidity types.
function getStateChangesUint(
    address target,
    bytes32 slot
) internal view returns (uint256[] memory);

function getStateChangesAddress(
    address target,
    bytes32 slot
) internal view returns (address[] memory);

function getStateChangesBool(
    address target,
    bytes32 slot
) internal view returns (bool[] memory);

function getStateChangesBytes32(
    address target,
    bytes32 slot
) internal view returns (bytes32[] memory);
The helper family also includes mapping-key and mapping-key-with-offset variants.

getAssertionAdopter

Returns the assertion adopter contract address associated with the current transaction.
function getAssertionAdopter() external view returns (address);
This cheatcode is available in triggers() and assertion functions. It is not available in the constructor because assertion contracts have no state during deployment.

console.log

Prints debug information during local assertion testing.
function console.log(string memory message) external;
Import it from credible-std/Console.sol.

Legacy Trigger Registration

Legacy trigger registration functions are internal helpers on Assertion.

registerCallTrigger

Registers an assertion function to run when the adopter receives a call.
function registerCallTrigger(
    bytes4 assertionFnSelector
) internal view;

function registerCallTrigger(
    bytes4 assertionFnSelector,
    bytes4 triggerSelector
) internal view;
The one-argument overload triggers on any call to the adopter. The two-argument overload triggers on calls matching triggerSelector.

registerStorageChangeTrigger

Registers an assertion function to run when adopter storage changes.
function registerStorageChangeTrigger(
    bytes4 assertionFnSelector
) internal view;

function registerStorageChangeTrigger(
    bytes4 assertionFnSelector,
    bytes32 slot
) internal view;
The one-argument overload triggers on any storage slot change. The two-argument overload triggers on a specific slot.

registerBalanceChangeTrigger

Registers an assertion function to run when the adopter’s ETH balance changes.
function registerBalanceChangeTrigger(
    bytes4 assertionFnSelector
) internal view;

Reshiram Precompiles

Reshiram precompiles use explicit snapshot reads instead of global fork switching. In credible-sdk, these live under crates/assertion-executor/src/inspectors/precompiles/reshiram/.

State Access

loadStateAt

Reads a storage slot from a snapshot fork.
function loadStateAt(
    bytes32 slot,
    ForkId calldata fork
) external view returns (bytes32 value);

function loadStateAt(
    address target,
    bytes32 slot,
    ForkId calldata fork
) external view returns (bytes32 value);
The first overload reads from the current assertion adopter. The second overload reads from any target account.

staticcallAt

Executes a read-only call against a snapshot fork.
struct StaticCallResult {
    bool ok;
    bytes data;
}

function staticcallAt(
    address target,
    bytes calldata data,
    uint64 gas_limit,
    ForkId calldata fork
) external view returns (StaticCallResult memory result);
data contains return data when ok is true and revert data when ok is false.

Logs

getLogsQuery

Returns logs matching an emitter/signature query from a snapshot fork.
function getLogsQuery(
    LogQuery calldata query,
    ForkId calldata fork
) external view returns (Log[] memory logs);

getLogsForCall

Returns logs matching a query from one recorded call frame.
function getLogsForCall(
    LogQuery calldata query,
    uint256 callId
) external view returns (Log[] memory logs);

Call Inspection

callinputAt

Returns the raw calldata for a traced call.
function callinputAt(
    uint256 callId
) external view returns (bytes memory input);

callOutputAt

Returns the raw return or revert bytes for a traced call.
function callOutputAt(
    uint256 callId
) external view returns (bytes memory output);

matchingCalls

Returns recorded calls matching target, selector, and filter criteria.
struct CallFilter {
    uint8 callType;
    uint32 minDepth;
    uint32 maxDepth;
    bool topLevelOnly;
    bool successOnly;
}

struct TriggerCall {
    uint256 callId;
    uint256 parentCallId;
    address caller;
    address target;
    address codeAddress;
    bytes4 selector;
    uint32 depth;
    uint8 callType;
    bool success;
    uint256 value;
    bytes input;
}

function matchingCalls(
    address target,
    bytes4 selector,
    CallFilter calldata filter,
    uint256 limit
) external view returns (TriggerCall[] memory calls);
callType uses 0 for any, 1 for CALL, 2 for STATICCALL, 3 for DELEGATECALL, and 4 for CALLCODE.

Trigger Context

context

Returns context for the current registerFnCallTrigger invocation.
struct TriggerContext {
    bytes4 selector;
    uint256 callStart;
    uint256 callEnd;
}

function context() external view returns (TriggerContext memory);
This reverts outside an assertion function triggered by registerFnCallTrigger.

ERC20 Introspection

Erc20TransferData

Decoded ERC20 Transfer event data.
struct Erc20TransferData {
    address token_addr;
    address from;
    address to;
    uint256 value;
}

getErc20Transfers

Returns decoded ERC20 transfers for one token in a snapshot fork.
function getErc20Transfers(
    address token,
    ForkId calldata fork
) external view returns (Erc20TransferData[] memory transfers);

getErc20TransfersForTokens

Returns decoded ERC20 transfers across multiple tokens in a snapshot fork.
function getErc20TransfersForTokens(
    address[] calldata tokens,
    ForkId calldata fork
) external view returns (Erc20TransferData[] memory transfers);

changedErc20BalanceDeltas

Returns all transfer records involving a token in a snapshot fork.
function changedErc20BalanceDeltas(
    address token,
    ForkId calldata fork
) external view returns (Erc20TransferData[] memory deltas);

reduceErc20BalanceDeltas

Aggregates transfers into net balance deltas per unique (from, to) pair.
function reduceErc20BalanceDeltas(
    address token,
    ForkId calldata fork
) external view returns (Erc20TransferData[] memory deltas);

Mapping Tracing

changedMappingKeys

Returns canonical Solidity key encodings for mapping entries written during the transaction.
function changedMappingKeys(
    address target,
    bytes32 baseSlot
) external view returns (bytes[] memory keys);
This is a best-effort trace heuristic. Custom assembly or precomputed hashed slots can produce false negatives.

mappingValueDiff

Returns pre-transaction and post-transaction values for one mapping entry.
function mappingValueDiff(
    address target,
    bytes32 baseSlot,
    bytes calldata key,
    uint256 fieldOffset
) external view returns (bytes32 pre, bytes32 post, bool changed);

Transaction Object

getTxObject

Returns data from the original assertion-triggering transaction.
struct TxObject {
    address from;
    address to;
    uint256 value;
    uint64 chain_id;
    uint64 gas_limit;
    uint128 gas_price;
    bytes input;
}

function getTxObject() external view returns (TxObject memory txObject);

Protection Suite Helpers

forbidChangeForSlot

Checks that one adopter storage slot was not modified.
function forbidChangeForSlot(
    bytes32 slot
) external returns (bool ok);

forbidChangeForSlots

Checks that none of the listed adopter storage slots were modified.
function forbidChangeForSlots(
    bytes32[] calldata slots
) external returns (bool ok);

conserveBalance

Checks that an account’s ERC20 balance is unchanged between two forks.
function conserveBalance(
    ForkId calldata fork0,
    ForkId calldata fork1,
    address token,
    address account
) external returns (bool);

oracleSanity

Checks oracle price consistency across all fork points.
function oracleSanity(
    address target,
    bytes calldata data,
    uint256 bpsDeviation
) external returns (bool);

oracleSanityAt

Checks oracle price consistency between two specific forks.
function oracleSanityAt(
    address target,
    bytes calldata data,
    uint256 bpsDeviation,
    ForkId calldata initialFork,
    ForkId calldata currentFork
) external returns (bool);

assetsMatchSharePrice

Checks ERC4626 share price consistency across all fork points.
function assetsMatchSharePrice(
    address vault,
    uint256 toleranceBps
) external returns (bool);

assetsMatchSharePriceAt

Checks ERC4626 share price consistency between two forks.
function assetsMatchSharePriceAt(
    address vault,
    uint256 toleranceBps,
    ForkId calldata fork0,
    ForkId calldata fork1
) external returns (bool);

Circuit Breaker Context

outflowContext

Returns context for an assertion triggered by watchCumulativeOutflow.
struct OutflowContext {
    address token;
    uint256 cumulativeOutflow;
    uint256 absoluteOutflow;
    uint256 currentBps;
    uint256 tvlSnapshot;
    uint256 windowStart;
    uint256 windowEnd;
}

function outflowContext() external view returns (OutflowContext memory ctx);

inflowContext

Returns context for an assertion triggered by watchCumulativeInflow.
struct InflowContext {
    address token;
    uint256 cumulativeInflow;
    uint256 absoluteInflow;
    uint256 currentBps;
    uint256 tvlSnapshot;
    uint256 windowStart;
    uint256 windowEnd;
}

function inflowContext() external view returns (InflowContext memory ctx);

Math Helpers

mulDivDown

Computes (x * y) / denominator, rounded down, using 512-bit intermediates.
function mulDivDown(
    uint256 x,
    uint256 y,
    uint256 denominator
) external pure returns (uint256 result);

mulDivUp

Computes (x * y) / denominator, rounded up, using 512-bit intermediates.
function mulDivUp(
    uint256 x,
    uint256 y,
    uint256 denominator
) external pure returns (uint256 result);

normalizeDecimals

Scales an amount from one decimal base to another.
function normalizeDecimals(
    uint256 amount,
    uint8 fromDecimals,
    uint8 toDecimals
) external pure returns (uint256 result);

ratioGe

Compares two ratios with basis-point tolerance.
function ratioGe(
    uint256 num1,
    uint256 den1,
    uint256 num2,
    uint256 den2,
    uint256 toleranceBps
) external pure returns (bool);

Reshiram Trigger Registration

Reshiram trigger registration functions are internal helpers on Assertion.

registerFnCallTrigger

Registers an assertion that fires once per matching adopter call. Use ph.context() inside the assertion to inspect the matched call context.
function registerFnCallTrigger(
    bytes4 fnSelector,
    bytes4 triggerSelector
) internal view;

registerTxEndTrigger

Registers an assertion that fires once after the transaction completes.
function registerTxEndTrigger(
    bytes4 fnSelector
) internal view;

registerErc20ChangeTrigger

Registers an assertion that fires when a token’s balances change.
function registerErc20ChangeTrigger(
    bytes4 fnSelector,
    address token
) internal view;

watchCumulativeOutflow

Registers a circuit breaker trigger for cumulative ERC20 outflow from the assertion adopter.
function watchCumulativeOutflow(
    address token,
    uint256 thresholdBps,
    uint256 windowDuration,
    bytes4 fnSelector
) internal view;
thresholdBps is measured against the TVL snapshot taken at the start of the rolling window. 1000 is 10%.

watchCumulativeInflow

Registers a circuit breaker trigger for cumulative ERC20 inflow into the assertion adopter.
function watchCumulativeInflow(
    address token,
    uint256 thresholdBps,
    uint256 windowDuration,
    bytes4 fnSelector
) internal view;
thresholdBps is measured against the TVL snapshot taken at the start of the rolling window. 1000 is 10%.

Deprecated Cheatcodes

Do not use these cheatcodes in new assertions. They mutate the active fork globally and are replaced by Reshiram’s explicit ForkId-based loadStateAt API.

forkPreTx

Switches the active fork to the state before the assertion-triggering transaction.
function forkPreTx() external;
Use loadStateAt(..., _preTx()) instead.

forkPostTx

Switches the active fork to the state after the assertion-triggering transaction.
function forkPostTx() external;
Use loadStateAt(..., _postTx()) instead.

forkPreCall

Switches the active fork to the state before a specific call execution.
function forkPreCall(uint256 id) external;
Use loadStateAt(..., PhEvm.ForkId({forkType: 2, callIndex: id})) instead.

forkPostCall

Switches the active fork to the state after a specific call execution.
function forkPostCall(uint256 id) external;
Use loadStateAt(..., PhEvm.ForkId({forkType: 3, callIndex: id})) instead.

load(address, bytes32)

Loads a storage slot from an address on the current active fork.
function load(
    address target,
    bytes32 slot
) external view returns (bytes32 data);
Use loadStateAt(target, slot, fork) instead.

Cheatcodes Overview

Conceptual overview of cheatcodes

Write Your First Assertion

Tutorial for writing an assertion

Use Case Mappings

Examples of assertion capabilities

Testing Assertions

How to test assertions locally