Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

credible-std

Standard library for implementing assertions in the Phylax Credible Layer (PCL). Provides the core contracts and interfaces needed to create, test, and validate assertions for smart contract security monitoring.

Documentation

Full API documentation is available at: https://phylaxsystems.github.io/credible-std

Installation

Install the latest stable release:

forge install phylaxsystems/credible-std@0.4.0

Or install from master (latest development version):

forge install phylaxsystems/credible-std

Add the remapping to your remappings.txt:

credible-std/=lib/credible-std/src/

Overview

The Phylax Credible Layer (PCL) is a security framework that enables real-time monitoring and validation of smart contract behavior through assertions. credible-std provides the foundational contracts and utilities needed to implement these assertions.

Key Components

ContractDescription
Assertion.solBase contract for creating assertions with trigger registration
Credible.solProvides access to the PhEvm precompile for transaction state inspection
PhEvm.solInterface for the PhEvm precompile (state forking, logs, call inputs)
StateChanges.solType-safe utilities for tracking contract state changes
TriggerRecorder.solInterface for registering assertion triggers
CredibleTest.solBase contract for testing assertions with Forge
CredibleTestWithBacktesting.solExtended test contract with historical transaction backtesting

Features

  • Trigger System: Register triggers for function calls, storage changes, and balance changes
  • State Inspection: Fork to pre/post transaction state, inspect logs, call inputs, and storage
  • Type-Safe State Changes: Built-in converters for uint256, address, bool, and bytes32 state changes
  • Testing Framework: Test assertions locally with Forge before deployment
  • Backtesting: Validate assertions against historical blockchain transactions
  • Internal Call Detection: Automatically detect transactions that call your contract internally (not just direct calls)

Quick Start

1. Create an Assertion

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {Assertion} from "credible-std/Assertion.sol";

contract MyAssertion is Assertion {
    // Register when this assertion should run
    function triggers() external view override {
        // Run on any call to the adopter contract
        registerCallTrigger(this.checkInvariant.selector);

        // Or run only on specific function calls
        // registerCallTrigger(this.checkInvariant.selector, ITarget.deposit.selector);
    }

    // Implement your invariant check
    function checkInvariant() external {
        address target = ph.getAssertionAdopter();

        ph.forkPreTx();
        uint256 balanceBefore = target.balance;

        ph.forkPostTx();
        uint256 balanceAfter = target.balance;

        require(balanceAfter >= balanceBefore, "Balance decreased unexpectedly");
    }
}

2. Test Your Assertion

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {CredibleTest} from "credible-std/CredibleTest.sol";
import {Test} from "forge-std/Test.sol";
import {MyAssertion} from "./MyAssertion.sol";
import {MyContract} from "./MyContract.sol";

contract TestMyAssertion is CredibleTest, Test {
    MyContract target;

    function setUp() public {
        target = new MyContract();
    }

    function test_assertionPasses() public {
        // Register the assertion
        cl.assertion({
            adopter: address(target),
            createData: type(MyAssertion).creationCode,
            fnSelector: MyAssertion.checkInvariant.selector
        });

        // Execute a transaction - assertion runs automatically
        target.deposit{value: 1 ether}();
    }

    function test_assertionFails() public {
        cl.assertion({
            adopter: address(target),
            createData: type(MyAssertion).creationCode,
            fnSelector: MyAssertion.checkInvariant.selector
        });

        // This should revert because the assertion fails
        vm.expectRevert("Balance decreased unexpectedly");
        target.withdraw(1 ether);
    }
}

Run tests with:

pcl test

PhEvm Cheatcodes

Access these via the ph instance inherited from Credible:

FunctionDescription
forkPreTx()Fork to state before the transaction
forkPostTx()Fork to state after the transaction
forkPreCall(uint256 id)Fork to state before a specific call
forkPostCall(uint256 id)Fork to state after a specific call
load(address, bytes32)Load a storage slot value
getLogs()Get all logs emitted in the transaction
getCallInputs(address, bytes4)Get CALL inputs for target/selector
getStaticCallInputs(address, bytes4)Get STATICCALL inputs
getDelegateCallInputs(address, bytes4)Get DELEGATECALL inputs
getAllCallInputs(address, bytes4)Get all call types
getStateChanges(address, bytes32)Get state changes for a slot
getAssertionAdopter()Get the adopter contract address

Trigger Types

Register triggers in your triggers() function:

function triggers() external view override {
    // Trigger on any call to the adopter
    registerCallTrigger(this.myAssertion.selector);

    // Trigger on specific function call
    registerCallTrigger(this.myAssertion.selector, ITarget.transfer.selector);

    // Trigger on any storage change
    registerStorageChangeTrigger(this.myAssertion.selector);

    // Trigger on specific storage slot change
    registerStorageChangeTrigger(this.myAssertion.selector, bytes32(uint256(0)));

    // Trigger on balance change
    registerBalanceChangeTrigger(this.myAssertion.selector);
}

Backtesting

Test your assertions against historical blockchain transactions to validate correctness before deployment. The backtesting framework automatically detects both direct calls AND internal/nested calls to your target contract.

Setup

Add to your foundry.toml:

[profile.backtesting]
src = "src"
test = "test"
ffi = true
gas_limit = 100000000

Block Range Backtesting

Test all transactions in a block range:

import {CredibleTestWithBacktesting} from "credible-std/CredibleTestWithBacktesting.sol";
import {BacktestingTypes} from "credible-std/utils/BacktestingTypes.sol";

contract MyBacktest is CredibleTestWithBacktesting {
    function testHistoricalTransactions() public {
        BacktestingTypes.BacktestingResults memory results = executeBacktest(
            BacktestingTypes.BacktestingConfig({
                targetContract: 0x1234...,           // Contract to monitor
                endBlock: 1000000,                   // End block
                blockRange: 100,                     // Number of blocks to test
                assertionCreationCode: type(MyAssertion).creationCode,
                assertionSelector: MyAssertion.check.selector,
                rpcUrl: "https://eth.llamarpc.com",
                detailedBlocks: false,               // Verbose block output
                forkByTxHash: true                   // Fork by tx hash for accurate state
            })
        );

        // Check no assertions failed
        assertEq(results.assertionFailures, 0, "Assertions failed on historical data");
    }
}

Single Transaction Backtesting

Test a specific transaction by hash:

contract MyBacktest is CredibleTestWithBacktesting {
    function testSpecificTransaction() public {
        bytes32 txHash = 0xabc123...;

        BacktestingTypes.BacktestingResults memory results = executeBacktestForTransaction(
            txHash,
            0x1234...,                              // Target contract
            type(MyAssertion).creationCode,
            MyAssertion.check.selector,
            "https://eth.llamarpc.com"
        );

        assertEq(results.assertionFailures, 0);
    }
}

Running Backtests

# Run with verbose output
pcl test --ffi -vvvv --match-test testHistoricalTransactions

# Or with the backtesting profile
FOUNDRY_PROFILE=backtesting pcl test -vvvv

Internal Call Detection

The backtesting framework automatically detects transactions that call your target contract internally (e.g., through a router or aggregator). It tries multiple trace APIs with automatic fallback:

  1. trace_filter - Fastest, requires Erigon or archive node with trace API
  2. debug_traceBlockByNumber - Slower but widely supported
  3. debug_traceTransaction - Slowest, per-transaction tracing
  4. Direct calls only - Fallback when no trace APIs available

Example output:

=== TRANSACTION DISCOVERY ===
Target: 0x1234...
Blocks: 1000000 to 1000100

[INFO] Detecting both direct calls AND internal/nested calls to target
[INFO] Trying trace APIs with automatic fallback...

[TRACE] Using trace_filter API (fastest method for internal call detection)
[TRACE] trace_filter not supported by this RPC endpoint
[TRACE] Falling back to debug_traceBlockByNumber (slower but widely supported)

=== DISCOVERY COMPLETE ===
[INFO] Detection method: debug_traceBlockByNumber
[INFO] Internal calls: ENABLED

Understanding Results

The backtesting framework provides detailed categorization:

ResultDescription
SuccessTransaction passed assertion validation
SkippedTransaction didn't trigger the assertion (selector mismatch)
Assertion FailedReal protocol violation detected
Replay FailureTransaction reverted before assertion could run
Unknown ErrorUnexpected failure

When an assertion fails, the framework automatically replays the transaction with full Foundry tracing enabled, showing the complete execution path for debugging.

State Change Helpers

The StateChanges contract provides type-safe helpers for inspecting storage changes:

// Get state changes as specific types
uint256[] memory uintChanges = getStateChangesUint(target, slot);
address[] memory addrChanges = getStateChangesAddress(target, slot);
bool[] memory boolChanges = getStateChangesBool(target, slot);
bytes32[] memory rawChanges = getStateChangesBytes32(target, slot);

// With mapping key support
uint256[] memory balanceChanges = getStateChangesUint(target, balancesSlot, userKey);

// With slot offset for struct fields
uint256[] memory fieldChanges = getStateChangesUint(target, structSlot, key, fieldOffset);

Resources

License

MIT

Contents

Contents

Target

Git Source

State Variables

value

uint256 value = 1

Functions

readStorage

function readStorage() external view returns (uint256);

writeStorage

function writeStorage(uint256 value_) public;

incrementStorage

function incrementStorage() public;

writeStorageAndRevert

function writeStorageAndRevert(uint256 value_) external;

receive

receive() external payable;

fallback

fallback() external;

Events

Log

event Log(uint256 value);

Constants

Git Source

TARGET

Target constant TARGET = Target(payable(0xdCCf1eEB153eF28fdc3CF97d33f60576cF092e9c))

Contents

TestAccessAssertionStorage

Git Source

Inherits: Assertion

State Variables

someAddress

address public someAddress

Functions

accessAssertionStorage

function accessAssertionStorage() external;

triggers

function triggers() external view override;

TriggeringTx

Git Source

Functions

constructor

constructor() payable;

Contents

TestCallInputs

Git Source

Inherits: Assertion

Functions

constructor

constructor() payable;

getCallInputs

function getCallInputs() external view;

callInputsWrongTarget

function callInputsWrongTarget() external view;

callNoSelector

function callNoSelector() external view;

triggers

function triggers() external view override;

TriggeringTx

Git Source

Functions

constructor

constructor() payable;

TestForking

Git Source

Inherits: Assertion

State Variables

sum

uint256 public sum = 0

someInitValue

uint256 public someInitValue = 1

Functions

forkSwitchStorage

function forkSwitchStorage() external;

forkSwitchNewDeployedContract

function forkSwitchNewDeployedContract() external;

forkSwitchBalance

function forkSwitchBalance() external;

persistTargetContracts

function persistTargetContracts() external;

triggers

function triggers() external view override;

TriggeringTx

Git Source

Functions

constructor

constructor() payable;

TestGetAdopter

Git Source

Inherits: Assertion

Functions

constructor

constructor() payable;

getAdopter

function getAdopter() external view;

triggers

function triggers() external view override;

TriggeringTx

Git Source

Functions

constructor

constructor() payable;

TestLoad

Git Source

Inherits: Assertion

Functions

constructor

constructor() payable;

_loadCount

function _loadCount() internal view returns (uint256);

load

function load() external;

loadRandomAccount

function loadRandomAccount() external view;

triggers

function triggers() external view override;

TriggeringTx

Git Source

Functions

constructor

constructor() payable;

TestLogs

Git Source

Inherits: Assertion

Functions

constructor

constructor() payable;

getLogs

function getLogs() external;

triggers

function triggers() external view override;

TriggeringTx

Git Source

Functions

constructor

constructor() payable;

TestStateChanges1

Git Source

Inherits: Assertion

Functions

constructor

constructor() payable;

getStateChanges1

function getStateChanges1() external view;

triggers

function triggers() external view override;

TriggeringTx

Git Source

Functions

constructor

constructor() payable;

TestStateChanges2

Git Source

Inherits: Assertion

Functions

constructor

constructor() payable;

getStateChanges2

function getStateChanges2() external view;

triggers

function triggers() external view override;

TriggeringTx

Git Source

Functions

constructor

constructor() payable;

TestStateChangesNone

Git Source

Inherits: Assertion

Functions

constructor

constructor() payable;

getStateChangesNone

function getStateChangesNone() external view;

triggers

function triggers() external view override;

TriggeringTx

Git Source

Functions

constructor

constructor() payable;

Contents

TestAllCallTrigger

Git Source

Inherits: Assertion

Functions

triggered

function triggered() external pure;

triggers

function triggers() external view override;

TriggeringTx

Git Source

Functions

constructor

constructor() payable;

TestAllStorageChangeTrigger

Git Source

Inherits: Assertion

Functions

triggered

function triggered() external;

triggers

function triggers() external view override;

TriggeringTx

Git Source

Functions

constructor

constructor() payable;

TestBalanceTrigger

Git Source

Inherits: Assertion

Functions

triggered

function triggered() external pure;

triggers

function triggers() external view override;

TriggeringTx

Git Source

Functions

constructor

constructor() payable;

TestSomeCallTrigger

Git Source

Inherits: Assertion

Functions

triggered

function triggered() external pure;

triggers

function triggers() external view override;

TriggeringTx

Git Source

Functions

constructor

constructor() payable;

TestStorageSlotChangeTrigger

Git Source

Inherits: Assertion

Functions

triggered

function triggered() external pure;

triggers

function triggers() external view override;

TriggeringTx

Git Source

Functions

constructor

constructor() payable;

Contents

BacktestingTypes

Git Source

Title: BacktestingTypes

Author: Phylax Systems

Type definitions for the backtesting framework

Contains structs for configuration, transaction data, and results used by CredibleTestWithBacktesting

Structs

TransactionData

Transaction data from blockchain

struct TransactionData {
    bytes32 hash;
    address from;
    address to;
    uint256 value;
    bytes data;
    uint256 blockNumber;
    uint256 transactionIndex;
    uint256 gasPrice;
    uint256 gasLimit;
    uint256 maxFeePerGas;
    uint256 maxPriorityFeePerGas;
}

ValidationDetails

Detailed validation result with error information

struct ValidationDetails {
    ValidationResult result;
    string errorMessage;
    bool isProtocolViolation;
}

BacktestingConfig

Configuration for backtesting runs (block range mode)

Internal call detection is automatic - the system tries trace_filter first, then falls back to debug_traceBlockByNumber, debug_traceTransaction, and finally direct-calls-only if no trace methods are supported.

struct BacktestingConfig {
    address targetContract;
    uint256 endBlock;
    uint256 blockRange;
    bytes assertionCreationCode;
    bytes4 assertionSelector;
    string rpcUrl;
    bool detailedBlocks; // Enable detailed block summaries in output
    bool forkByTxHash; // Fork by transaction hash for correct pre-tx state; block forks are unsafe.
}

BacktestingResults

Enhanced backtesting results with detailed categorization

struct BacktestingResults {
    uint256 totalTransactions;
    uint256 processedTransactions; // Transactions that were actually processed
    uint256 successfulValidations;
    uint256 skippedTransactions; // Transactions where assertion wasn't triggered (selector mismatch)
    uint256 assertionFailures; // Real protocol violations
    uint256 replayFailures; // Transactions that reverted during replay before assertion
    uint256 unknownErrors; // Unexpected failures
}

Enums

ValidationResult

Validation result categories for detailed error analysis

enum ValidationResult {
    Success, // Transaction passed all assertions
    Skipped, // Transaction didn't trigger the assertion (function selector mismatch)
    ReplayFailure, // Transaction reverted during replay before assertion could execute
    AssertionFailed, // Assertion logic failed (actual protocol violation)
    UnknownError // Unexpected error during validation
}

BacktestingUtils

Git Source

Title: BacktestingUtils

Author: Phylax Systems

Utility functions for the backtesting framework

Provides parsing, string manipulation, and error decoding utilities used internally by CredibleTestWithBacktesting

Functions

extractDataLine

Extract transaction data from fetcher output

function extractDataLine(string memory output) internal pure returns (string memory);

_isWhitespace

Check if a character is whitespace

function _isWhitespace(bytes1 char) private pure returns (bool);

splitString

Simple pipe-delimited string splitter

function splitString(string memory str, string memory) internal pure returns (string[] memory);

stringToUint

Parse hex or decimal string to uint256

function stringToUint(string memory str) internal pure returns (uint256);

stringToAddress

Parse hex address string to address

function stringToAddress(string memory str) internal pure returns (address);

stringToBytes32

Parse hex string to bytes32

function stringToBytes32(string memory str) internal pure returns (bytes32);

hexStringToBytes

Parse hex string to bytes

function hexStringToBytes(string memory str) internal pure returns (bytes memory);

bytes32ToHex

Convert bytes32 to hex string

function bytes32ToHex(bytes32 data) internal pure returns (string memory);

extractFunctionSelector

Extract function selector from calldata

function extractFunctionSelector(bytes memory data) internal pure returns (string memory);

parseMultipleTransactions

Parse multiple transactions from a single data line

function parseMultipleTransactions(string memory txDataString)
    internal
    pure
    returns (BacktestingTypes.TransactionData[] memory transactions);

_hexCharToUint8

Convert hex character to uint8

function _hexCharToUint8(bytes1 char) private pure returns (uint8);

substring

Helper to get substring for debugging

function substring(string memory str, uint256 start, uint256 len) private pure returns (string memory);

decodeRevertReason

Decode revert reason from error data

function decodeRevertReason(bytes memory data) internal pure returns (string memory);

Parameters

NameTypeDescription
databytesThe error data from a failed call

Returns

NameTypeDescription
<none>stringThe decoded revert reason string

_panicCodeToString

Convert panic code to human-readable string

function _panicCodeToString(uint256 code) private pure returns (string memory);

bytesToHex

Convert bytes to hex string

function bytesToHex(bytes memory data) internal pure returns (bytes memory);

Parameters

NameTypeDescription
databytesThe bytes to convert

Returns

NameTypeDescription
<none>bytesThe hex string representation

getErrorTypeString

Get human-readable error type string from validation result

function getErrorTypeString(BacktestingTypes.ValidationResult result) internal pure returns (string memory);

Parameters

NameTypeDescription
resultBacktestingTypes.ValidationResultThe validation result enum

Returns

NameTypeDescription
<none>stringThe human-readable string representation

startsWith

Check if a string starts with a prefix

function startsWith(string memory str, string memory prefix) internal pure returns (bool);

Parameters

NameTypeDescription
strstringThe string to check
prefixstringThe prefix to look for

Returns

NameTypeDescription
<none>boolTrue if str starts with prefix

getDefaultScriptSearchPaths

Get the standard search paths for transaction_fetcher.sh

function getDefaultScriptSearchPaths() internal pure returns (string[] memory);

Returns

NameTypeDescription
<none>string[]Array of paths to check, in order of preference

Assertion

Git Source

Inherits: Credible, StateChanges

Title: Assertion

Author: Phylax Systems

Base contract for creating Credible Layer assertions

Inherit from this contract to create custom assertions. Assertions can inspect transaction state via the inherited ph precompile and register triggers to specify when the assertion should be executed. Example:

contract MyAssertion is Assertion {
function triggers() external view override {
registerCallTrigger(this.checkInvariant.selector, ITarget.deposit.selector);
}
function checkInvariant() external {
ph.forkPostTx();
Check invariants...
}
}

State Variables

triggerRecorder

The trigger recorder precompile for registering assertion triggers

Address is derived from a deterministic hash for consistency

TriggerRecorder constant triggerRecorder = TriggerRecorder(address(uint160(uint256(keccak256("TriggerRecorder")))))

Functions

triggers

Used to record fn selectors and their triggers.

function triggers() external view virtual;

registerCallTrigger

Registers a call trigger for the AA without specifying an AA function selector. This will trigger the assertion function on any call to the AA.

function registerCallTrigger(bytes4 fnSelector) internal view;

Parameters

NameTypeDescription
fnSelectorbytes4The function selector of the assertion function.

registerCallTrigger

Registers a call trigger for calls to the AA with a specific AA function selector.

function registerCallTrigger(bytes4 fnSelector, bytes4 triggerSelector) internal view;

Parameters

NameTypeDescription
fnSelectorbytes4The function selector of the assertion function.
triggerSelectorbytes4The function selector upon which the assertion will be triggered.

registerStorageChangeTrigger

Registers storage change trigger for any slot

function registerStorageChangeTrigger(bytes4 fnSelector) internal view;

Parameters

NameTypeDescription
fnSelectorbytes4The function selector of the assertion function.

registerStorageChangeTrigger

Registers storage change trigger for a specific slot

function registerStorageChangeTrigger(bytes4 fnSelector, bytes32 slot) internal view;

Parameters

NameTypeDescription
fnSelectorbytes4The function selector of the assertion function.
slotbytes32The storage slot to trigger on.

registerBalanceChangeTrigger

Registers balance change trigger for the AA

function registerBalanceChangeTrigger(bytes4 fnSelector) internal view;

Parameters

NameTypeDescription
fnSelectorbytes4The function selector of the assertion function.

console

Git Source

Title: console

Author: Phylax Systems

Logging library for Credible Layer assertions

Provides console logging functionality within assertion execution context. Logs are captured by the Credible Layer runtime for debugging purposes.

State Variables

CONSOLE_ADDRESS

The console precompile address

Derived from a deterministic hash to ensure consistency with the runtime

address constant CONSOLE_ADDRESS = address(uint160(uint256(keccak256("Kim Jong Un Sucks"))))

Functions

log

Log a string message

Messages are captured by the Credible Layer runtime

function log(string memory message) internal view;

Parameters

NameTypeDescription
messagestringThe message to log

Credible

Git Source

Title: Credible

Author: Phylax Systems

Base contract providing access to the PhEvm precompile interface

All assertion contracts should inherit from this contract (via Assertion) to access the PhEvm precompile for reading transaction state, logs, and call inputs.

State Variables

ph

The PhEvm precompile instance for accessing transaction state

The address is derived from a deterministic hash to ensure consistency

PhEvm constant ph = PhEvm(address(uint160(uint256(keccak256("Kim Jong Un Sucks")))))

VmEx

Git Source

Inherits: Vm

Title: VmEx

Extended Vm interface with assertion testing capabilities

Extends the standard Forge Vm interface with Credible Layer specific cheatcodes

Functions

assertion

Register an assertion for testing

function assertion(address adopter, bytes calldata createData, bytes4 fnSelector) external;

Parameters

NameTypeDescription
adopteraddressThe address of the contract that adopts the assertion
createDatabytesThe creation bytecode of the assertion contract
fnSelectorbytes4The function selector of the assertion function to test

CredibleTest

Git Source

Title: CredibleTest

Author: Phylax Systems

Base contract for testing Credible Layer assertions with Forge

Inherit from this contract (or CredibleTestWithBacktesting) to test assertions locally

State Variables

cl

The extended Vm cheatcode interface for assertion testing

Provides access to assertion-specific cheatcodes

VmEx public constant cl = VmEx(address(uint160(uint256(keccak256("hevm cheat code")))))

CredibleTestWithBacktesting

Git Source

Inherits: CredibleTest, Test

Title: CredibleTestWithBacktesting

Author: Phylax Systems

Extended CredibleTest with historical transaction backtesting capabilities

Inherit from this contract to test assertions against historical blockchain transactions. Supports two modes:

  • Block range mode: Test all transactions in a block range via executeBacktest(config)
  • Single transaction mode: Test a specific transaction via executeBacktestForTransaction(txHash, ...) Example:
contract MyBacktest is CredibleTestWithBacktesting {
function testHistorical() public {
executeBacktest(BacktestingTypes.BacktestingConfig({
targetContract: 0x...,
endBlock: 1000000,
blockRange: 100,
assertionCreationCode: type(MyAssertion).creationCode,
assertionSelector: MyAssertion.check.selector,
rpcUrl: "https://eth.llamarpc.com",
detailedBlocks: false,
forkByTxHash: true
}));
}
}

State Variables

_cachedScriptPath

Cached script path to avoid repeated filesystem lookups

string private _cachedScriptPath

Functions

executeBacktestForTransaction

Execute backtesting for a single transaction by hash (overload for single tx mode)

function executeBacktestForTransaction(
    bytes32 txHash,
    address targetContract,
    bytes memory assertionCreationCode,
    bytes4 assertionSelector,
    string memory rpcUrl
) public returns (BacktestingTypes.BacktestingResults memory results);

Parameters

NameTypeDescription
txHashbytes32The transaction hash to backtest
targetContractaddressThe target contract address
assertionCreationCodebytesThe assertion contract creation code
assertionSelectorbytes4The assertion function selector
rpcUrlstringThe RPC URL to use

Returns

NameTypeDescription
resultsBacktestingTypes.BacktestingResultsThe backtesting results

executeBacktest

Execute backtesting with config struct (block range mode)

function executeBacktest(BacktestingTypes.BacktestingConfig memory config)
    public
    returns (BacktestingTypes.BacktestingResults memory results);

_getScriptSearchPaths

Get the standard search paths for transaction_fetcher.sh

Override this in your test contract to add custom search paths

function _getScriptSearchPaths() internal view virtual returns (string[] memory);

Returns

NameTypeDescription
<none>string[]Array of paths to check, in order of preference

_findScriptPath

Find the transaction_fetcher.sh script path

Checks environment variable first, then searches common locations, and finally uses find to auto-detect the script location. Override _getScriptSearchPaths() to customize search locations

function _findScriptPath() internal virtual returns (string memory);

Returns

NameTypeDescription
<none>stringThe path to transaction_fetcher.sh

_autoDetectScriptPath

Auto-detect the script path using find command

Searches the project directory for transaction_fetcher.sh

function _autoDetectScriptPath() internal virtual returns (string memory);

Returns

NameTypeDescription
<none>stringThe detected path, or empty string if not found

_fetchTransactions

Fetch transactions using FFI

Automatically detects internal calls using trace APIs with fallback: trace_filter -> debug_traceBlockByNumber -> debug_traceTransaction -> direct calls only

function _fetchTransactions(address targetContract, uint256 startBlock, uint256 endBlock, string memory rpcUrl)
    private
    returns (BacktestingTypes.TransactionData[] memory transactions);

_executeBacktestForSingleTransaction

Execute backtesting for a single transaction specified by hash

function _executeBacktestForSingleTransaction(
    bytes32 txHash,
    address targetContract,
    bytes memory assertionCreationCode,
    bytes4 assertionSelector,
    string memory rpcUrl
) private returns (BacktestingTypes.BacktestingResults memory results);

_fetchTransactionByHash

Fetch a single transaction by hash using FFI

function _fetchTransactionByHash(bytes32 txHash, string memory rpcUrl)
    private
    returns (BacktestingTypes.TransactionData memory txData);

_parseTransactionFromTsv

Parse transaction data from tab-separated output

function _parseTransactionFromTsv(string memory tsvLine)
    private
    pure
    returns (BacktestingTypes.TransactionData memory txData);

_validateTransaction

Validate a single transaction with detailed error categorization

function _validateTransaction(
    address targetContract,
    bytes memory assertionCreationCode,
    bytes4 assertionSelector,
    string memory rpcUrl,
    BacktestingTypes.TransactionData memory txData,
    bool forkByTxHash
) private returns (BacktestingTypes.ValidationDetails memory validation);

_replayTransactionForTrace

Replay a failed transaction to show the full execution trace

Forks to state before the tx and makes a raw call so Foundry prints the full trace

function _replayTransactionForTrace(
    address, // targetContract - unused, kept for interface compatibility
    bytes memory, // assertionCreationCode - unused
    bytes4, // assertionSelector - unused
    string memory rpcUrl,
    BacktestingTypes.TransactionData memory txData
) private;

_categorizeAndLogError

Categorize and log error details

function _categorizeAndLogError(BacktestingTypes.ValidationDetails memory validation) private pure;

_printDetailedResults

Print detailed results with error categorization

function _printDetailedResults(
    uint256 startBlock,
    uint256 endBlock,
    BacktestingTypes.BacktestingResults memory results
) private pure;

PhEvm

Git Source

Title: PhEvm

Author: Phylax Systems

Precompile interface for accessing transaction state within assertions

This interface provides access to the Credible Layer's execution environment, allowing assertions to inspect transaction state, logs, call inputs, and storage changes. The precompile is available at a deterministic address during assertion execution.

Functions

forkPreTx

Fork to the state before the assertion-triggering transaction

Allows inspection of pre-transaction state for comparison

function forkPreTx() external;

forkPostTx

Fork to the state after the assertion-triggering transaction

Allows inspection of post-transaction state for validation

function forkPostTx() external;

forkPreCall

Fork to the state before a specific call execution

Useful for inspecting state at specific points during transaction execution

function forkPreCall(uint256 id) external;

Parameters

NameTypeDescription
iduint256The call identifier from CallInputs.id

forkPostCall

Fork to the state after a specific call execution

Useful for inspecting state changes from specific calls

function forkPostCall(uint256 id) external;

Parameters

NameTypeDescription
iduint256The call identifier from CallInputs.id

load

Load a storage slot value from any address

function load(address target, bytes32 slot) external view returns (bytes32 data);

Parameters

NameTypeDescription
targetaddressThe address to read storage from
slotbytes32The storage slot to read

Returns

NameTypeDescription
databytes32The value stored at the slot

getLogs

Get all logs emitted during the transaction

Returns logs in emission order

function getLogs() external returns (Log[] memory logs);

Returns

NameTypeDescription
logsLog[]Array of Log structs containing all emitted events

getAllCallInputs

Get all call inputs for a target and selector (all call types)

Includes CALL, STATICCALL, DELEGATECALL, and CALLCODE

function getAllCallInputs(address target, bytes4 selector) external view returns (CallInputs[] memory calls);

Parameters

NameTypeDescription
targetaddressThe target contract address
selectorbytes4The function selector to filter by

Returns

NameTypeDescription
callsCallInputs[]Array of CallInputs matching the criteria

getCallInputs

Get call inputs for regular CALL opcode only

function getCallInputs(address target, bytes4 selector) external view returns (CallInputs[] memory calls);

Parameters

NameTypeDescription
targetaddressThe target contract address
selectorbytes4The function selector to filter by

Returns

NameTypeDescription
callsCallInputs[]Array of CallInputs from CALL opcodes

getStaticCallInputs

Get call inputs for STATICCALL opcode only

function getStaticCallInputs(address target, bytes4 selector) external view returns (CallInputs[] memory calls);

Parameters

NameTypeDescription
targetaddressThe target contract address
selectorbytes4The function selector to filter by

Returns

NameTypeDescription
callsCallInputs[]Array of CallInputs from STATICCALL opcodes

getDelegateCallInputs

Get call inputs for DELEGATECALL opcode only

function getDelegateCallInputs(address target, bytes4 selector) external view returns (CallInputs[] memory calls);

Parameters

NameTypeDescription
targetaddressThe target/proxy contract address
selectorbytes4The function selector to filter by

Returns

NameTypeDescription
callsCallInputs[]Array of CallInputs from DELEGATECALL opcodes

getCallCodeInputs

Get call inputs for CALLCODE opcode only

function getCallCodeInputs(address target, bytes4 selector) external view returns (CallInputs[] memory calls);

Parameters

NameTypeDescription
targetaddressThe target contract address
selectorbytes4The function selector to filter by

Returns

NameTypeDescription
callsCallInputs[]Array of CallInputs from CALLCODE opcodes

getStateChanges

Get all state changes for a specific storage slot

Returns the sequence of values the slot held during transaction execution

function getStateChanges(address contractAddress, bytes32 slot)
    external
    view
    returns (bytes32[] memory stateChanges);

Parameters

NameTypeDescription
contractAddressaddressThe contract whose storage to inspect
slotbytes32The storage slot to get changes for

Returns

NameTypeDescription
stateChangesbytes32[]Array of values the slot held (in order of changes)

getAssertionAdopter

Get the assertion adopter address for the current transaction

The adopter is the contract that registered the assertion

function getAssertionAdopter() external view returns (address);

Returns

NameTypeDescription
<none>addressThe address of the assertion adopter contract

Structs

Log

Represents an Ethereum log emitted during transaction execution

Used by getLogs() to return transaction logs for inspection

struct Log {
    /// @notice The topics of the log, including the event signature if any
    bytes32[] topics;
    /// @notice The raw ABI-encoded data of the log
    bytes data;
    /// @notice The address of the contract that emitted the log
    address emitter;
}

CallInputs

Represents the inputs to a call made during transaction execution

Used by getCallInputs() and related functions to inspect call details

struct CallInputs {
    /// @notice The calldata of the call
    bytes input;
    /// @notice The gas limit of the call
    uint64 gas_limit;
    /// @notice The address of the bytecode being executed (code address)
    address bytecode_address;
    /// @notice The target address whose storage may be modified
    address target_address;
    /// @notice The address that initiated this call
    address caller;
    /// @notice The ETH value sent with the call
    uint256 value;
    /// @notice Unique identifier for this call, used with forkPreCall/forkPostCall
    uint256 id;
}

StateChanges

Git Source

Inherits: Credible

Title: StateChanges

Helper contract for converting state changes from bytes32 arrays to typed arrays

Inherits from Credible to access the PhEvm interface

Functions

getStateChangesUint

Converts state changes for a slot to uint256 array

function getStateChangesUint(address contractAddress, bytes32 slot) internal view returns (uint256[] memory);

Parameters

NameTypeDescription
contractAddressaddressThe address of the contract to get state changes from
slotbytes32The storage slot to get state changes for

Returns

NameTypeDescription
<none>uint256[]Array of state changes as uint256 values

getStateChangesAddress

Converts state changes for a slot to address array

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

Parameters

NameTypeDescription
contractAddressaddressThe address of the contract to get state changes from
slotbytes32The storage slot to get state changes for

Returns

NameTypeDescription
<none>address[]Array of state changes as address values

getStateChangesBool

Converts state changes for a slot to boolean array

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

Parameters

NameTypeDescription
contractAddressaddressThe address of the contract to get state changes from
slotbytes32The storage slot to get state changes for

Returns

NameTypeDescription
<none>bool[]Array of state changes as boolean values

getStateChangesBytes32

Gets raw state changes as bytes32 array

function getStateChangesBytes32(address contractAddress, bytes32 slot) internal view returns (bytes32[] memory);

Parameters

NameTypeDescription
contractAddressaddressThe address of the contract to get state changes from
slotbytes32The storage slot to get state changes for

Returns

NameTypeDescription
<none>bytes32[]Array of state changes as bytes32 values

getSlotMapping

Calculates the storage slot for a mapping with a given key and offset

function getSlotMapping(bytes32 slot, uint256 key, uint256 offset) private pure returns (bytes32);

Parameters

NameTypeDescription
slotbytes32The base storage slot of the mapping
keyuint256The key in the mapping
offsetuint256Additional offset to add to the calculated slot

Returns

NameTypeDescription
<none>bytes32The storage slot for the mapping entry

getStateChangesUint

Gets uint256 state changes for a mapping entry

function getStateChangesUint(address contractAddress, bytes32 slot, uint256 key)
    internal
    view
    returns (uint256[] memory);

Parameters

NameTypeDescription
contractAddressaddressThe contract address
slotbytes32The mapping's slot
keyuint256The mapping key

Returns

NameTypeDescription
<none>uint256[]Array of state changes as uint256 values

getStateChangesAddress

Gets address state changes for a mapping entry

function getStateChangesAddress(address contractAddress, bytes32 slot, uint256 key)
    internal
    view
    returns (address[] memory);

Parameters

NameTypeDescription
contractAddressaddressThe contract address
slotbytes32The mapping's slot
keyuint256The mapping key

Returns

NameTypeDescription
<none>address[]Array of state changes as address values

getStateChangesBool

Gets boolean state changes for a mapping entry

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

Parameters

NameTypeDescription
contractAddressaddressThe contract address
slotbytes32The mapping's slot
keyuint256The mapping key

Returns

NameTypeDescription
<none>bool[]Array of state changes as boolean values

getStateChangesBytes32

Gets bytes32 state changes for a mapping entry

function getStateChangesBytes32(address contractAddress, bytes32 slot, uint256 key)
    internal
    view
    returns (bytes32[] memory);

Parameters

NameTypeDescription
contractAddressaddressThe contract address
slotbytes32The mapping's slot
keyuint256The mapping key

Returns

NameTypeDescription
<none>bytes32[]Array of state changes as bytes32 values

getStateChangesUint

Gets uint256 state changes for a mapping entry with offset

function getStateChangesUint(address contractAddress, bytes32 slot, uint256 key, uint256 slotOffset)
    internal
    view
    returns (uint256[] memory);

Parameters

NameTypeDescription
contractAddressaddressThe contract address
slotbytes32The mapping's slot
keyuint256The mapping key
slotOffsetuint256Additional offset to add to the slot

Returns

NameTypeDescription
<none>uint256[]Array of state changes as uint256 values

getStateChangesAddress

Gets address state changes for a mapping entry with offset

function getStateChangesAddress(address contractAddress, bytes32 slot, uint256 key, uint256 slotOffset)
    internal
    view
    returns (address[] memory);

Parameters

NameTypeDescription
contractAddressaddressThe contract address
slotbytes32The mapping's slot
keyuint256The mapping key
slotOffsetuint256Additional offset to add to the slot

Returns

NameTypeDescription
<none>address[]Array of state changes as address values

getStateChangesBool

Gets boolean state changes for a mapping entry with offset

function getStateChangesBool(address contractAddress, bytes32 slot, uint256 key, uint256 slotOffset)
    internal
    view
    returns (bool[] memory);

Parameters

NameTypeDescription
contractAddressaddressThe contract address
slotbytes32The mapping's slot
keyuint256The mapping key
slotOffsetuint256Additional offset to add to the slot

Returns

NameTypeDescription
<none>bool[]Array of state changes as boolean values

getStateChangesBytes32

Gets bytes32 state changes for a mapping entry with offset

function getStateChangesBytes32(address contractAddress, bytes32 slot, uint256 key, uint256 slotOffset)
    internal
    view
    returns (bytes32[] memory);

Parameters

NameTypeDescription
contractAddressaddressThe contract address
slotbytes32The mapping's slot
keyuint256The mapping key
slotOffsetuint256Additional offset to add to the slot

Returns

NameTypeDescription
<none>bytes32[]Array of state changes as bytes32 values

TriggerRecorder

Git Source

Title: TriggerRecorder

Author: Phylax Systems

Precompile interface for registering assertion triggers

Used within the triggers() function of assertion contracts to specify when assertions should be executed. Supports call triggers, storage change triggers, and balance change triggers.

Functions

registerStorageChangeTrigger

Registers storage change trigger for all slots

function registerStorageChangeTrigger(bytes4 fnSelector) external view;

Parameters

NameTypeDescription
fnSelectorbytes4The function selector of the assertion function.

registerStorageChangeTrigger

Registers storage change trigger for a slot

function registerStorageChangeTrigger(bytes4 fnSelector, bytes32 slot) external view;

Parameters

NameTypeDescription
fnSelectorbytes4The function selector of the assertion function.
slotbytes32The storage slot to trigger on.

registerBalanceChangeTrigger

Registers balance change trigger for the AA

function registerBalanceChangeTrigger(bytes4 fnSelector) external view;

Parameters

NameTypeDescription
fnSelectorbytes4The function selector of the assertion function.

registerCallTrigger

Registers a call trigger for calls to the AA.

function registerCallTrigger(bytes4 fnSelector, bytes4 triggerSelector) external view;

Parameters

NameTypeDescription
fnSelectorbytes4The function selector of the assertion function.
triggerSelectorbytes4The function selector of the trigger function.

registerCallTrigger

Records a call trigger for the specified assertion function. A call trigger signifies that the assertion function should be called if the assertion adopter is called.

function registerCallTrigger(bytes4 fnSelector) external view;

Parameters

NameTypeDescription
fnSelectorbytes4The function selector of the assertion function.