Matador Docs
Guides

Production Readiness

A checklist and guide for deploying Matador policies to mainnet.

Deploying permission policies to production is a critical operation. A mistake could lock funds or leave a vulnerability open. This guide outlines the rigorous processes required for a safe deployment.

Deployment Lifecycle

1. Final Compilation

Perform a clean build of your policies. Do not use cached artifacts.

# Clean output
rm -rf ./out

# Compile
npx --package @steerprotocol/matador-cli matador-policy-cli compile ./policies/mainnet/*.matador -d ./out

2. Verification

Verify that the hexData in your output JSON matches the expectations.

  • Instruction Audit: Review the instructions field in the JSON artifact. Does the logic flow match your source code?
  • Checksum: Commit the checksum and specVersion to your deployment log.

3. Provisioning

Submit the transaction to grant the permission.

  • Manual (Safe): Use a transaction builder app to call grantPermission with the bytecode.
  • Automated (Script): Use a hardened script with a hardware wallet.

4. Live Test

Immediately after provisioning, execute a low-value "canary" transaction to verify the policy behaves as expected.

Policy Management

Updating Policies

Policies are immutable by design. To "update" a policy, you must:

  1. Grant the new policy (new permissionId).
  2. Revoke the old policy.

Atomic Updates

If your smart account supports batched transactions (like Safe or Kernel), bundle the revoke and grant calls into a single transaction to ensure zero downtime or security gaps.

Emergency Procedures

Define clear rollback procedures before deployment.

  • Revoke Access: The owner key must be able to call revokePermission instantly if a bug is found.
  • Bypass Mode: Consider having a "Break Glass" policy (e.g., a high-threshold MultiSig) that can bypass specific restrictions in an emergency.

Monitoring & Observability

You cannot debug what you cannot see. Ensure your infrastructure captures interpreter events.

Key Events

EventLogicAction
PermissionEnforcedPolicy PassedLog for audit trail.
PermissionViolationPolicy FailedAlert immediately. Investigate the opcode and subject.
PermissionGrantedNew PolicyVerify against changelog.
PermissionRevokedPolicy RemovedVerify authorization.

Health Checks

Protocols upgrade. Your policies might not.

  • Periodic ABI Check: Automated scripts should verify that the target addresses in your policies still point to the correct implementation contracts.
  • Selector Verification: Ensure function selectors haven't changed (rare, but possible with proxy upgrades).

Coordinated Contract Artifacts

The lean ExecutionContext tuple changes every ABI selector that embeds it. Deploy the interpreter, adapters, account wrappers, and regenerated ABIs as one coordinated artifact set; do not mix components compiled against the old and new tuples. Callable bytecode retains format version 3, but a policy containing BLOCK_TIMESTAMP (0xb5) requires the matching interpreter implementation.

Before deterministic deployment, recompute and record addresses because changed creation bytecode changes CREATE2 results even when salts remain constant. A post-deployment rollback must restore the complete prior component set and must not downgrade an interpreter while an installed policy contains 0xb5.

Pinned Kernel validation evidence

The Kernel validation fixture was exercised in a disposable local environment with Alto commit f8465ad90d0c5f0199960733c178af7cc3c5e6a9, Geth v1.17.3 on a Prague chain with chain id 1337, and canonical EntryPoint v0.9 at 0x433709009b8330fda32311df1c2afa402ed8d009. The final local fixture manifest was 0x4EE6eCAD1c2Dae9f525404De8555724e3c35d07B; it is test evidence, not a production deployment address.

Unmodified Alto at that pinned commit successfully handled eth_estimateUserOperationGas with the explicit 89-byte estimation stub:

ResultValue
preVerificationGas0xc604
verificationGasLimit0x419e9
callGasLimit0x39a11

The pinned checkout's safe-validator send path required one local, disposable v0.9 return-decoder correction. Its tracer expected the final call to be a revert carrying a ValidationResult error, while the v0.9 PimlicoSimulations.simulateValidation path returned a normal function result. The local correction selected that RETURN frame and decoded the simulateValidation function result.

With that correction, the negative TIMESTAMP account was rejected by eth_sendUserOperation with code -32502 and account uses banned opcode: TIMESTAMP. A valid real-signature operation returned UserOperation hash 0x45e576d16b8ea24892b5cbf6c885b027b889ea88fdc6699f8ae9bf546a84d252; debug_bundler_sendBundleNow returned ok, its receipt reported success: true, and the target call count was 1.

Scope of the Alto result

The estimation result above passed on the unmodified pinned Alto commit. The safe-send, banned-opcode, bundle, and receipt results used the disposable return-decoder correction and therefore do not establish unmodified upstream Alto safe-send support.

Alto's executable classifier at this commit is also not byte-for-byte the current normative ERC-7562 snapshot. EntryPoint v0.9 takes Alto's non-v0.8 opcode branch, its associated-slot range ends at offset 127, and its precompile allowlist covers addresses 1 through 9. The retained result proves acceptance by this exact classifier for the documented deployed-account fixture; it is not a general ERC-7562 compliance certificate. Re-run both paths and the complete intended account/policy matrix against the exact bundler revision selected for production.

Production Checklist

  • Source Control: All deployed policies are committed to git with a version tag.
  • Clean Build: Artifacts were generated from a clean CI pipeline, not a local dev machine.
  • Audit: Logic has been reviewed by at least two engineers.
  • Test Coverage: Foundry tests cover >95% of policy logic, including edge cases.
  • Gas Analysis: The policy overhead is acceptable for the intended transaction frequency.
  • Artifact Compatibility: Tuple-bearing ABI selectors and deterministic addresses were regenerated, and all contract components come from one coordinated build.
  • Kernel EntryPoint Pin: The Kernel implementation is configured for the audited canonical EntryPoint v0.9 behavior and its deployed code is verified on the target chain.
  • Kernel Policy Size: Every Kernel policy is at most 24,575 bytes so its SSTORE2 pointer fits under EIP-170 with the leading STOP byte.
  • Bundler Estimation: The exact 89-byte stub and real-signature send were re-tested against the production bundler revision; local decoder patches are not being mistaken for upstream support.
  • Monitoring: Alerts are configured for PermissionViolation events.
  • Recovery: The account owner has access to keys capable of revoking permissions.

On this page