Main Capabilities
Cheatcodes enable functionality that would be impossible or impractical with standard Solidity:- Forking blockchain state: Access the state of the blockchain before and after a transaction, enabling pre/post comparisons
 - Callstack introspection: Inspect call traces and execution flow in ways not possible with standard EVM tools
 - State change tracking: Monitor specific storage slots and track how they change during transaction execution
 - Triggering assertions: Define precise conditions for when assertions should execute (specific function calls, storage changes, or balance changes)
 
Why Cheatcodes Exist
Standard Solidity doesn’t provide access to transaction execution history, call traces, or the ability to compare pre and post-transaction states. Cheatcodes fill this gap by providing native functions that can:- Compare values before and after a transaction
 - Track how storage slots change during execution
 - Identify which functions were called and in what order
 - Access logs and events from the transaction
 
You may notice the terms “precompiles” and “cheatcodes” used interchangeably in some contexts. We use the term “cheatcodes” as it’s more familiar to Solidity developers who are already using testing frameworks like Foundry or Hardhat. Both terms refer to native functions that extend the EVM’s capabilities, but “cheatcodes” better reflects their role in the developer experience.
When to Use Cheatcodes
Use cheatcodes when you need to:- Compare state changes: Check if values changed correctly (e.g., “balance decreased by exactly the withdrawal amount”)
 - Validate call patterns: Ensure functions were called in the correct order or with expected parameters
 - Monitor storage: Track changes to specific storage slots that represent critical protocol state
 - Optimize performance: Use triggers to run assertions only when relevant state changes occur
 
New to assertions? Check out What are Assertions? to understand how cheatcodes fit into the bigger picture of writing security rules.
State Forking Guidance
Not all assertions require checking both pre- and post-state. Understanding when to use each makes assertions more efficient. Default behavior: If neitherph.forkPreState() nor ph.forkPostState() are called, assertions execute against post-transaction state by default.
When to Use Pre-State
- Comparing values before and after a transaction
 - Building on top of specific state to verify invariants hold
 - Verifying that certain values remain constant
 
When to Skip Pre-State
- Only final values matter
 - Checking conditions that only matter after execution
 - Pre-state is irrelevant to your invariant
 

