Matador Docs
Guides

Integration Guide

Architecture for integrating Matador into smart accounts and protocols.

Matador is designed to be the "permission engine" for modular smart accounts. This guide explains how to integrate the interpreter into your account implementation or use it with popular frameworks like Kernel and Safe.

Integration Lifecycle

The integration of Matador generally follows three stages:

graph LR
    Deploy[1. Deployment] --> Grant[2. Provisioning]
    Grant --> Enforce[3. Enforcement]
  1. Deployment: Deploy the PermissionInterpreter and register modules. (One-time setup per network).
  2. Provisioning: The account owner grants a permission by storing the compiled bytecode on the account.
  3. Enforcement: Before executing a user transaction, the account calls interpreter.enforce() to validate the action against the stored policy.

Base Implementation

The simplest integration is to inherit from BasePermissionAccount. This provides the storage layout and internal functions needed to manage permissions.

Inherit Base Contract

MyAccount.sol
import { BasePermissionAccount } from "@matador/core/accounts/BasePermissionAccount.sol";

contract MyAccount is BasePermissionAccount {
    // ...
}

Implement Execution Logic

In your execution function, construct the ExecutionContext and call _enforcePermission.

function execute(
    bytes32 permissionId,
    address target,
    uint256 value,
    bytes calldata data
) external {
    // 1. Build Context
    IPermissionInterpreter.ExecutionContext memory exec = IPermissionInterpreter.ExecutionContext({
        caller: msg.sender,
        target: target,
        value: value,
        data: data,
        gasLimit: gasleft(),
        gasPrice: tx.gasprice,
        nonce: 0,
        blobBaseFee: block.blobbasefee,
        blobGasPrice: 0
    });

    // 2. Enforce (Reverts on failure)
    _enforcePermission(permissionId, exec);

    // 3. Execute
    (bool success, ) = target.call{value: value}(data);
    require(success, "Execution failed");
}

Modular Accounts (ERC-7579)

For modular accounts like Kernel or Safe, Matador acts as a Validation Module or Guard.

Kernel Integration

Matador can serve as a Validator or an Executor plugin.

As a Validator: The kernel calls validateUserOp on the plugin. The plugin uses Matador to verify the session key signature and policy constraints.

As an Executor: The kernel delegates execution to the plugin. The plugin enforces the policy before performing the call.

ERC-4337 Session Keys

Matador is the ideal engine for ERC-4337 Session Keys.

The Flow

  1. UserOp Creation: The user signs a UserOp with a temporary session key.
  2. Validation: The validateUserOp function checks that the session key is authorized and active.
  3. Execution: The execute function enforces the Matador policy to ensure the session key is only performing allowed actions (e.g., swapping specific tokens).

Storage Restrictions

During validateUserOp, access to external storage is restricted by the bundler. If your policy uses stateful checks (like RATE_LIMIT_CHECK), you must enforce them during the execution phase, not the validation phase.

function validateUserOp(PackedUserOperation calldata userOp, ...) returns (uint256) {
    // 1. Recover signer from userOp.signature
    // 2. Verify signer corresponds to a valid permissionId
    // 3. Return validation success (pay prefund)
}

function execute(bytes32 permissionId, ...) external {
    // 1. Enforce Matador Policy (Full access to storage/opcodes)
    interpreter.enforce(bytecode, address(this), execContext);
    
    // 2. Perform Action
}

Best Practices

  • Fail Closed: Ensure that if a permissionId does not exist, the transaction reverts immediately.
  • Gas Overhead: Complex policies add overhead. Profile your gas usage using the Matador benchmarks.
  • Context Integrity: Ensure that the caller, target, and value passed to the interpreter accurately reflect the transaction about to be executed.

On this page