Certora Examples

repository·master·Indexed 42 days ago

https://github.com/certora/examples

A collection of practical examples for the Certora Prover and the Certora Verification Language (CVL), specifically targeting CVL2 compatibility. Includes guides on using the certoraRun CLI, configuring Solidity compiler settings, managing loop unrolling and recursion, implementing contract extensions, and utilizing CVL features like address call functions, contract aliases, and the native ecrecover function.

Tokens
26.5K
Snippets
108
Records
164
Agent score
50%

What's inside Certora Examples

  1. Overview of Summarization in Certora Prover

    master

    Summarization is a core feature of the Certora Prover used to simplify complex verification tasks. It enables:

    1. Reasoning about external calls: Representing the behavior of external contracts or calls without verifying their full implementation.
    2. Modular verification: Splitting a large verification problem into multiple independent subproblems by using symbolic representations of specific parts.
    3. Interface point checking: Verifying properties at the boundaries of contract interfaces.

    For detailed technical specifications, refer to the official Certora documentation on summaries.

  2. Compare Direct vs Wildcard Summarization in CVL

    master

    This example demonstrates two different approaches to function summarization in Certora Verification Language (CVL):

    1. Direct Summary: Provides a contract-level summary for specific base and overloaded functions. In the AllDirect.spec example, every function called from Solidity is given its own direct summarization.
    2. Wildcard Summary: Provides a summary for all library functions using wildcard patterns.

    Key behaviors observed in the AllDirect.spec example:

    • Unresolved Functions: Summaries like function _.calleeOverloadedInInterfaceExternal() external => ALWAYS(true) UNRESOLVED; only apply to functions that are unresolved. If a function is resolved (e.g., TestLibrary.calleeOverloadedInInterfaceExternal()), the summary does not apply, and the function's actual behavior is used instead.
    • CVL Call Limitations: The rule callSummarizedFromCVL fails in this setup because functions called directly from CVL are not covered by these summarizations; summarizations are only applied to functions called from within Solidity code.
  3. Explore CVL Command Examples

    master

    This repository provides a comprehensive collection of examples for the Certora Verification Language (CVL). These examples cover a wide range of CVL commands, from basic assertions to advanced concepts like ghost variables, storage access, and summarization. They are categorized by command type and include real-life code snippets and specifications that have been used to identify critical bugs in smart contracts.

    For a complete guide and full documentation, refer to the official Certora documentation at https://docs.certora.com.

  4. Explore Revert condition examples in CVL

    master

    The RevertConditions directory contains Certora Verification Language (CVL) specification examples demonstrating how different types of reverts behave in Solidity.

    Note on Solidity Versions: Some examples are highly dependent on specific Solidity compiler versions. Behavior may change or fail to replicate if using different compiler versions.

    Available categories of revert examples:

    String Reverts

    Covers scenarios involving string encoding and validation:

    • Revert due to string encoding: String/StrIssueExample.spec
    • Identifying illegally encoded strings: String/StrIssuePersistent.spec
    • Invariant for legal string writes: String/StrIssueInvariant.spec

    Return Size Reverts

    Covers reverts caused by unresolved call return sizes. Detailed documentation can be found in: ReturnSize/README.md.

    Target Call Reverts

    Covers reverts occurring when a contract call targets a non-existent contract. Detailed documentation can be found in: TargetCall/README.md.

  5. TransientStorage Example with transient field syntax

    master

    This example demonstrates how to verify smart contracts using transient storage fields (introduced in recent EVM updates). It uses a contract named TransientTest that implements a simple lock mechanism using a transient boolean field.

    Key verification techniques shown in this example include:

    • Using Tstore and Tload hooks to intercept accesses to transient fields.
    • Performing direct storage access from CVL on transient fields.
  6. Explore Certora Prover and CVL Examples

    master

    This repository serves as a collection of practical examples demonstrating how to use the Certora Verification Language (CVL). The specifications provided in this repository are compatible with CVL2.

    Use these examples to learn how to write formal specifications for smart contracts and how to interact with the Certora Prover.

  7. Use the `address` call function in CVL

    master

    In Certora Verification Language (CVL), you can use address type variables to call methods on contracts. This enables dynamic dispatch, where the specific function call is resolved based on the actual contract implementation associated with the address at runtime. This is useful for specifying properties that must hold true regardless of which contract is being interacted with via an address variable.

    using A as a;
    using B as b;
    
    rule AddressCall {
        env e;
        address x;
        // x.foo(e) calls the 'foo' function on the contract at address x
        assert x.foo(e) >= 1 && x.foo(e) <= 2;
    }
  8. Understand the importance of strengthening invariants in CVL

    master

    In Certora Verification Language (CVL), an invariant must be 'strong' enough to cover all reachable states from the initial state. If an invariant is too weak, the Certora Prover may find a counterexample by starting from an arbitrary state that satisfies the invariant but allows a transition to a state that violates it.

    In the BallGame example:

    • Weak Invariant: playerTwoNeverReceivesBall only assumes player 2 does not have the ball. However, if the ball starts with player 4, a pass call can move the ball to player 2, violating the invariant.
    • Strong Invariant: BallGameCorrect.spec fixes this by explicitly defining the allowed set of states (e.g., the ball must be held by either player 1 or player 3), ensuring the Prover only considers valid starting configurations.
  9. Use Ghost Variables and Functions

    master

    Ghost elements are used to model state or logic that does not exist in the Solidity code but is necessary for verification.

    • Ghost Variables: Can be simple variables or ghost mappings.
    • Ghost Functions: CVL functions used to compute values for verification.
    • init_state: Used to define the initial state of ghost variables.
    • axiom: Used to define truths about ghost variables that the prover can assume.
    • Ghost Summary: Summaries that describe the effects on ghost state.
  10. Use ALWAYS, CONSTANT, and NONDET in CVL

    master

    You can use different keywords to control how the Certora Prover treats function returns:

    1. ALWAYS(x): Forces the function to return exactly x. Any rule asserting a different value will fail.
    2. CONSTANT: Asserts that the function returns the same value every time it is called within a transaction, but the Prover is free to choose any value for that constant.
    3. NONDET: Asserts that the function returns a non-deterministic value. Note that using NONDET to imply no state change can be unsound if the actual implementation could change storage.

    Example of ALWAYS vs CONSTANT behavior:

    • If get1 is ALWAYS(7) and get2 is CONSTANT, get2 will always return the same value, but that value might not be 7.
  11. Understand TransientStorage hooks in CVL

    master

    The TransientStorage example demonstrates how to reason about smart contracts that use the new Ethereum opcodes tstore and tload for reentrancy guards (e.g., using a MockMutexer contract).

    To verify properties involving these opcodes, Certora provides specific CVL hooks:

    • ALL_TSTORE: A hook used to reason about all tstore operations.
    • ALL_TLOAD: A hook used to reason about all tload operations.

    These hooks allow the prover to model the behavior of transient storage, which is essential for verifying guards that rely on this new storage type.

  12. Detect read-only reentrancy with `viewReentrancy`

    master

    The viewReentrancy builtin rule is used to detect vulnerabilities where a contract's state is inconsistent during a view function call due to an ongoing reentrant call.

    In the provided examples, ViewReentrancy.spec demonstrates that even if a contract uses a standard reentrancy guard (like in BankGuardFix.sol), the rule can still be violated if the guard does not protect third parties that rely on view functions during the reentrant window.