Matador Docs
API Reference

ABI Integration

Import and use external ABIs for type-safe contract interactions.

Matador's type system is extensible through standard Ethereum ABI (Application Binary Interface) files. Importing an ABI allows the compiler to validate function calls, decoding paths, and parameter types at compile time.

Importing ABIs

Use the import keyword to load a JSON ABI file and assign it an alias. This alias becomes a namespace for accessing the contract's functions and events.

import "abis/UniswapV3Router.json" as Uniswap;
import "abis/ERC20.json" as Token;

Path Resolution

The compiler supports flexible path resolution strategies to suit different project structures.

Paths starting with ./ or ../ are resolved relative to the location of the .matador policy file.

// Policy is in /policies/swap.matador
// ABI is in /policies/abis/Router.json
import "./abis/Router.json" as Router;

Capabilities

Importing an ABI unlocks three powerful capabilities in your policies.

Calldata Inspection

Validate incoming transaction data against specific function signatures. The compiler automatically handles selector matching and decoding.

// Checks if the transaction is a call to 'transfer'
// AND if the recipient matches the parameter
Token.transfer(recipient: parameters.allowedRecipient)

State Variable Checks

Read public state variables from external contracts. This compiles to a STATE_VARIABLE_CHECK opcode.

// Ensure the pool has enough liquidity
Pool.liquidity() > 1000000

View Functions Only

The referenced function must be marked as view or pure in the ABI. Mutable functions cannot be called during validation.

Type Definitions

Use the ABI alias as a type annotation for parameters. This ensures that the parameter passed at runtime is treated as that specific contract type.

parameters: {
    // 'router' must be an address that adheres to the Uniswap ABI
    router: Uniswap
}

Deep Nested Access

Matador supports accessing deeply nested fields within struct parameters or arrays in calldata.

For example, given a function exactInputSingle that takes a ExactInputSingleParams struct:

struct ExactInputSingleParams {
    address tokenIn;
    address tokenOut;
    uint24 fee;
    address recipient;
    uint256 amountIn;
    uint256 amountOutMinimum;
    uint160 sqrtPriceLimitX96;
}

You can write a policy that enforces rules on specific fields of that struct:

when: {
    all {
        // Check the function selector
        Uniswap.exactInputSingle,

        // Enforce the recipient is the sender (no sweeping to others)
        context.args.params.recipient == context.caller,

        // Enforce a minimum output amount
        context.args.params.amountOutMinimum >= parameters.minOut
    }
}

Best Practices

Maintain a dedicated ABI directory

Keep all your JSON ABIs in a single abis/ or interfaces/ directory at the root of your project. This makes relative imports consistent across multiple policy files.

  1. Strip Unused Artifacts: Use "human-readable" ABIs or minimal JSON files containing only the functions you need. Full Foundry/Hardhat artifacts are supported but can be large.
  2. Version Control: Commit your ABIs to git alongside your policies to ensure reproducible builds.
  3. Use Aliases: Pick short, descriptive aliases (e.g., Aave instead of AavePoolV3Helper) to keep your policy logic readable.

On this page