Meow Gateway
Crypto fund payouts
Stablecoin transfers with per-chain rail binding and dual-control over $10k.
Fund payouts move USDC across chains. The rail router picks the right chain from the address; the counterparty lock prevents address-substitution attacks.
Pack
Bundled crypto_fund_v1. Key rules:
rails.allowed: [usdc.eth, usdc.base, usdc.arb, usdc.sol]rails.denied: [ach, wire, international_wire]dual_control_threshold_usd: 10000
Address normalization matters
The protocol hashes EVM addresses after EIP-55 checksum normalization and Solana addresses after base58 canonicalization. That means:
0xAb58...and0xab58...produce the same beneficiary hash (checksum-case-insensitive)- An attacker cannot create a "visually similar" zero-width-char copy of a known address and have it hash differently — the normalizer strips them
Flow
// 1. Rail pick:
const route = await veto.routing.suggest({
destination: "crypto_base",
amount_usd: "5000",
rail_allowlist: ["usdc.base", "usdc.arb"]
});
// → { suggested_rail: "usdc.base", reason: "beneficiary is on base" }
// 2. Counterparty:
const payee = await veto.counterparties.upsert({
type: "crypto",
display_name: "Portfolio LP #7",
chain: "base",
address: "0xAb58...",
});
// 3. Mint — $5k is under dual-control, so mints straight through:
const mint = await veto.capsules.mint({
entity_id: "ent_fund_operations",
agent_id: "agent_payouts",
tool: "meow.pay",
rail_allowlist: [route.suggested_rail],
counterparty_hash: payee.beneficiary_hash,
amount_ceiling: { currency: "USD", amount: "5000.00" },
invoice_hash: "sha256:...",
workflow_id: newWorkflowId(),
});
// 4. For a $15k payment, the mint returns 409 with approval_id
// and dual_control_required. Two distinct approvers must resolve
// the approval before re-minting with the approval_ref attached.Replayed webhook?
Meow may deliver the payment.settled webhook twice. The gateway deduplicates via claimMeowWebhookDelivery — second delivery returns 200 without re-transitioning the workflow. Your chain stays honest.