Skip to main content
A Vault is a per-intent escrow contract that holds reward tokens until execution is proven. Every intent gets its own vault, deployed deterministically via CREATE2. There is no shared protocol account. There are no admin keys.

Why per-intent vaults

Two consequences make the design useful: Funding is just a transfer. The vault address can be computed offchain from the intent hash. Cold wallets, hardware devices, multisigs, exchanges, and PSPs can fund an intent with a standard ERC-20 transfer to the vault — no EIP-712 signature, no permit, no contract interaction. Funds release only on proof. No private key controls withdrawal. The source-chain Portal will only release funds after a registered prover confirms fulfillment. If the deadline passes without fulfillment, a permissionless refund service returns the funds to the depositor.

Resource locks vs escrow

The vault model is sometimes called a resource lock: instead of escrowing funds in a shared protocol account, each operation reserves its own resource container. This eliminates protocol-level risk concentration and lets the funding flow look exactly like a payment.
Pooled escrowPer-intent vault
One contract holds all reward tokensOne vault per intent
Trust the protocol’s accountingTrust the proof
Funding requires interaction with the protocolFunding is a vanilla ERC-20 transfer
Bug in escrow contract → all users affectedBug in vault → bounded to one intent

Determinism in practice

vaultAddress = CREATE2(
  portalAddress,
  intentHash,           // salt
  keccak256(initCode)
)
Because the vault address is a deterministic function of the intent hash, an application can:
  • Display “Send USDC to 0xVaultAddr” before the intent is even published
  • Pre-fund a vault, then publish the intent later when ready
  • Verify funding by checking onchain balance, with no protocol coupling

Vault contract reference

The full Solidity surface.

Intents

How the intent hash is built.

Provers

What releases funds from the vault.