intent.escrow

How it works

A three-step flow where the beneficiary never has to send a transaction. They just sign a message; anyone can carry that signature on-chain to release funds.

1 · Depositor
Depositor locks funds
The depositor calls createEscrow, picking a beneficiary, an asset (ETH or any ERC-20), an amount, and an expiry. Funds move into the contract and an escrow ID is minted.
2 · Beneficiary
Beneficiary signs an intent
Off-chain, the beneficiary signs an EIP-712 SettleIntent: { escrowId, amount, deadline, nonce }. No gas, no transaction — it's just a signed message.
3 · Anyone
Anyone settles on-chain
A relayer (or the depositor, or the beneficiary themselves) submits the signature to settleWithSignature. The contract verifies it, pays out, and bumps the nonce so the same signature can't be replayed.

Why sign instead of just sending funds?

A signature is a portable, verifiable promise. The beneficiary can authorise a release from a phone with no ETH for gas; the depositor (or any relayer) pays the gas to execute it. That's the "intent" pattern: users express what they want, and anyone competes to make it happen.

EIP-712 makes the signed payload human-readable in the wallet ("Release 10 USDC from escrow #4 before Nov 1") instead of an opaque hex blob, which is what makes this safe to use in practice.

Safety rails

Replay protection
Each escrow has its own nonce. After every successful settlement the nonce increments, invalidating any previously-signed intent.
Deadlines
Every intent has a deadline. Sign once, and if it isn't submitted in time, it's automatically dead.
Partial releases
A signed intent can authorise part of the locked amount. The remainder stays escrowed and can be released (or refunded) later.
Refund after expiry
If nothing is settled by the expiry, the depositor can pull the remaining balance back out — no counterparty signature needed.
Cancel by beneficiary
The beneficiary can also walk away and return the funds before expiry. Both sides have an exit.
Smart-wallet friendly
Signatures are verified via ERC-1271, so the beneficiary can be a Safe, a 4337 account, or any contract wallet — not just an EOA.

The key idea

Off-chain
Beneficiary signs

A typed EIP-712 message — escrowId, amount, deadline, nonce. Takes about a second in their wallet. No gas, no transaction, no on-chain footprint.

signTypedData
signature
On-chain
Anyone submits

Depositor, relayer, beneficiary — whoever. The contract verifies the signature, pays out the amount, and bumps the nonce, all atomically.

settleWithSignature

The signature is the bridge. Cheap to produce (one wallet click), trivial to pass around (just bytes), cryptographically binding when submitted.

Try it: create an escrowBrowse existing escrows