ESCAPE HATCH for arbitrary EVM contract calls — Timelock proposals, governance hooks, DAO ops, anything not covered by a protocol-specific prepare_*. BYPASSES the canonical-dispatch allowlist by design; the schema's acknowledgeNonProtocolTarget: true literal is the user's affirmative gate. ABI so...
AI agents invoke prepare_custom_call to trigger actions in VaultPilot MCP. What it does depends on the arguments the agent supplies, and its effects often reach beyond the immediate call — builds kicked off, notifications sent, workflows started.
| Parameter | Type | Required | Description |
|---|---|---|---|
fn | string | Yes | Function name to call (e.g. "schedule"). Pass the FULL signature ("schedule(address,uint256,bytes,bytes32,bytes32,uint256)") to disambiguate when the ABI has ov |
abi | array | — | Inline ABI array. When omitted, the tool fetches it via Etherscan V2. Pass it to override the Etherscan ABI, to call a contract whose source isn't yet verified, |
args | array | — | Array of args matching the function's inputs in order. Decimal strings for uint256 (e.g. "1000000000000000000" for 1 ETH-as-wei), hex strings for bytes32/bytes, |
chain | string | — | |
value | string | — | Native-coin value in WEI (decimal string). Use "0" for non-payable functions. For payable functions, pass the wei amount (e.g. "1000000000000000000" for 1 ETH). |
wallet | string | Yes | EVM wallet that will sign + broadcast the call. Must be paired via `pair_ledger_live`. |
contract | string | Yes | Target contract address. Must be Etherscan-verified OR the `abi` arg must be passed inline. NOT canonical-dispatch-allowlist gated — this is the explicit escape |
acknowledgeBurnApproval | boolean | — | Override flag for the BURN_ADDRESS_UNLIMITED_APPROVAL refusal. Required only when `fn` is `approve` and the encoded call grants unlimited (2^256-1) allowance to |
acknowledgeRawApproveBypass | boolean | — | Override flag for the APPROVE_ROUTE_VIA_DEDICATED_TOOL refusal. By default any `approve(address,uint256)` calldata routed through this escape hatch refuses and |
acknowledgeKnownExfilPattern | boolean | — | Override flag for the CUSTOM_CALL_REFUSED selector classifier (issue #652). The classifier hard-refuses obvious ERC-20 value-exfil selectors routed through this |
acknowledgeNonProtocolTarget | boolean | Yes | AFFIRMATIVE GATE — must be true. The tool BYPASSES the canonical-dispatch allowlist by design (used for arbitrary contract calls like Timelock proposals, govern |
Parameters from the server's own tool schema.
prepare_custom_call triggers real processes with real consequences. An agent gone sideways doesn't fire it once — it starts dozens of builds, sends mass notifications, or burns through compute before anyone looks up.
Risk signalsHigh parameter count (11 properties)
Attacks that exploit this kind of access
ESCAPE HATCH for arbitrary EVM contract calls — Timelock proposals, governance hooks, DAO ops, anything not covered by a protocol-specific prepare_*. BYPASSES the canonical-dispatch allowlist by design; the schema's acknowledgeNonProtocolTarget: true literal is the user's affirmative gate. ABI source: pass abi: [...] inline (preferred when you have the project's published artifact), OR omit it and the tool fetches via Etherscan V2 — refuses on unverified contracts with NO raw-bytecode fallback. Proxies are followed once to the implementation when Etherscan exposes the link; deeper proxy chains require an inline ABI. Pass fn as a name ("schedule") when unambiguous or as the full signature ("schedule(address,uint256,bytes,bytes32,bytes32,uint256)") to disambiguate overloads. args types are validated by viem's encoder at build time — uint256 expects a decimal string, address expects a 0x-prefixed lowercase hex, bytes/bytes32 expect 0x-prefixed hex, structs are objects with their named fields. value is RAW WEI (decimal string), not human-readable. The standard prepare-receipt + verification envelope (payloadHash, decoderUrl, humanDecode) applies; on-device verification is blind-sign by definition (no Ledger plugin decodes arbitrary calldata) — the swiss-knife decoder URL surfaced in chat is the user-side anchor. Use a protocol-specific prepare_* whenever one fits — this tool exists for the long tail. It is categorised as a Execute tool in the VaultPilot MCP MCP Server, which means it can trigger actions or run processes. Use rate limits and argument validation.
prepare_custom_call accepts 11 parameters: fn, abi, args, chain, value, wallet, contract, acknowledgeBurnApproval, acknowledgeRawApproveBypass, acknowledgeKnownExfilPattern, acknowledgeNonProtocolTarget. Required: fn, wallet, contract, acknowledgeNonProtocolTarget. The full parameter table on this page comes from the server's own tool schema.
Register the VaultPilot MCP server in PolicyLayer and add a rule for prepare_custom_call: allow, deny, rate-limit, or require approval. Point your MCP client at the PolicyLayer proxy URL and the rule is enforced on every call, before it reaches VaultPilot MCP. Nothing to install.
prepare_custom_call is a Execute tool with high risk. Execute tools should be rate-limited and have argument validation enabled.
Yes. Add a rate_limit block to the prepare_custom_call rule in your PolicyLayer policy. For example, setting max: 10 and window: 60 limits the tool to 10 calls per minute. Rate limits are tracked per agent session and reset automatically.
Set action: deny in the PolicyLayer policy for prepare_custom_call. The AI agent will receive a policy violation error and cannot call the tool. You can also include a reason field to explain why the tool is blocked.
prepare_custom_call is provided by the VaultPilot MCP server (vaultpilot-mcp). PolicyLayer sits as a proxy in front of this server to enforce policies before tool calls reach the server.