ZK-Permit is a permissionless execution firewall for wallets and agents on Base. Users sign intents (EIP-712) bound to their current on-chain policy. The protocol enforces the constraints on-chain, then executes the target call.
policyHash.policyHash, nonce, deadline, dataHash, and actionType.executeWithUserSig (in v1.1 the user pays gas). The Checkpoint contract verifies signature + policyHash, enforces policy/allowlists, then executes the target call.maxDeadlineSeconds: keep tight (e.g. 600–1800 seconds)maxCallDataBytes: cap calldata (e.g. 2–8 KB)maxSwapsPerDay: optional rate limit for swapsThe user signs an intent including dataHash=keccak256(calldata), a replay protection nonce, a deadline, and the current policyHash. Execution requires the same on-chain policy hash (prevents “sign once, then policy changes silently”).
actionType=0: ETH transfer (requires empty calldata)actionType=1: ERC-20 approve(spender, amount)actionType=2: router swap call (router + selector allowlist + deadline check)Integrations typically follow the same pattern as the console, but in your own UI:
dataHash and build EIP-712 typed data.executeWithUserSig.This repo includes an SDK with helpers for typed data and calldata builders.
getZKPermitTypedData(): domain + types + message (EIP-712)buildApproveIntent, buildUniswapV2SwapIntent, buildUniswapV3ExactInputSingleIntent, buildAerodromeSwapIntentvalidateIntentAgainstPolicy(): client-side sanity checksConnect an AI agent to the live ZK-Permit deployment on Base. The MCP server reads policy + nonce, builds intents, generates EIP-712 typed data, checks allowlists, and (optionally) submits executeWithUserSig.
Package: zkpermit-mcp on npm. Paste this JSON — npx downloads and runs the server automatically.
{
"mcpServers": {
"zkpermit": {
"command": "npx",
"args": ["-y", "zkpermit-mcp"],
"env": {
"ZKPERMIT_RPC_URL": "https://mainnet.base.org",
"ZKPERMIT_CHECKPOINT_ADDRESS": "0x6209C1d46832726bb95B344F33ea643343fDD55A"
}
}
}
}Optional — add inside env only if your agent should broadcast txs (never share real keys): "ZKPERMIT_SUBMITTER_PRIVATE_KEY": "0x..."
~/.cursor/mcp.jsonmcpServers in ~/.claude.json (all projects), or .mcp.json in a project root. Restart the session, then run /mcp to confirm it is connected.~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or the equivalent config file on your OS. Restart the app.zkpermit_get_policy + zkpermit_get_nonce for the user walletzkpermit_check_allowlist before building a swap/approvezkpermit_build_intent → zkpermit_get_typed_data (with auto: true)zkpermit_submit_execute if a submitter key is configuredzkpermit_get_policy — read on-chain policy + policyHashzkpermit_get_nonce — current replay-protection noncezkpermit_build_intent — ETH / approve / UniV2 / UniV3 / Aerodromezkpermit_get_typed_data — EIP-712 typed data (auto=true fetches nonce + policyHash)zkpermit_check_allowlist — router / selector / token / spender checkszkpermit_submit_execute — optional, requires ZKPERMIT_SUBMITTER_PRIVATE_KEYEvery execution emits a structured Executed event including the policyHash, selector, and dataHash. Dashboards can index these events for pagination and analytics.
allowArbitraryCalldata disabled for production wallets.maxDeadlineSeconds (e.g. 10–30 minutes).maxCallDataBytes to a safe cap to prevent griefing.maxApproveAmount.