What is an Intent?
An intent is a signed message that says: “I want to swap X tokens for at least Y tokens, by this deadline.” It’s not an on-chain transaction — it’s a gasless signature that authorizes a settler to execute the trade on your behalf during batch settlement.Key difference from a swap: A swap executes immediately against the AMM. An intent is collected, batched with others, and settled at a uniform clearing price. You trade against the batch, not against the pool.
The GeodeIntent Struct
Every intent contains these fields:Implicit Limit Price
The intent doesn’t have an explicit price field. Instead, the limit price is derived fromamountIn and minAmountOut:
- Buy limit price =
amountIn × Q128 / minAmountOut(maximum price willing to pay) - Sell limit price =
minAmountOut × Q128 / amountIn(minimum price willing to accept)
Permit2 Integration
Geode uses Permit2 for gasless token approvals and transfers. This is the mechanism that lets users sign intents off-chain while settlers execute them on-chain.How It Works
One-Time Approval
The user approves the Permit2 contract to spend their tokens (standard ERC20
approve). This is a one-time transaction per token — Permit2 is shared across all protocols.Sign the Intent
The user signs a Permit2
PermitWitnessTransferFrom message that includes:- Permitted: token address, amount, nonce, deadline (standard Permit2 fields)
- Witness: poolId, tokenOut, minAmountOut (Geode-specific fields)
Witness Type
The Geode-specific witness contains only the fields NOT already in the Permit2PermitTransferFrom:
Replay Protection
Intents are protected against replay attacks at multiple levels:Permit2 Nonce
Each intent uses a unique Permit2 nonce. Once used, the nonce is consumed and the signature becomes invalid. The same intent can never be executed twice.
Pool Binding
The
poolId is part of the signed witness. An intent signed for Pool A cannot be replayed on Pool B — the signature verification will fail.Deadline
Every intent has an expiry timestamp. After the deadline, the Permit2 signature is invalid and the tokens cannot be moved, regardless of whether the nonce was used.
Chain ID
Permit2’s EIP-712 domain separator includes the chain ID. Signatures from Ethereum mainnet cannot be replayed on other chains.
Intent Lifecycle
Created
User configures the trade in the UI (or programmatically) and signs the Permit2 message in their wallet. The signature is produced locally — no on-chain transaction.
Submitted
The signed intent is sent to a settler (or a public mempool of intents). The settler collects intents for the current batch window.
Evaluated
When the settler is ready to settle, the clearing price algorithm evaluates each intent:
- Fills if the intent’s limit price is compatible with the clearing price
- Skipped if the limit price is not met (user keeps their tokens)
What Happens If My Intent Doesn’t Fill?
If the clearing price doesn’t meet yourminAmountOut, your intent is simply skipped. Your tokens are never moved and your Permit2 nonce is NOT consumed — you can reuse the same signed intent in a future batch.
If your intent isn’t included in any batch before its deadline, the signature expires naturally and becomes unusable.
Settler Competition
Settlement is permissionless — anyone can callgeodeSettleBatch(). Settlers compete to submit the most complete batches because:
- More filled intents = more settlement fees earned
- Omitting valid intents leaves money on the table for a competing settler
- The first valid batch for a given window wins
Security Model
Permit2 has two modes — Geode deliberately uses the safer one.SignatureTransfer, Not AllowanceTransfer
Permit2 provides two token transfer mechanisms:| AllowanceTransfer | SignatureTransfer | |
|---|---|---|
| Approval type | Standing allowance (amount + expiry) | Single-use permit per signature |
| Reuse | Can be spent multiple times up to the allowance | Each nonce is consumed on first use |
| Risk surface | A compromised spender can drain up to the approved amount | A compromised signature can only move exactly amountIn once |
| Used by | Uniswap frontend (swap router) | Geode intents |
permitWitnessTransferFrom from the SignatureTransfer interface. Every intent signature is a single-use authorization — once the Permit2 nonce is consumed, that signature is permanently dead.
Bounded Exposure
Every intent signature is scoped to exactly five constraints:| Constraint | Field | Effect |
|---|---|---|
| Amount | amountIn | Maximum tokens that can be moved |
| Time | deadline | Signature expires and becomes unusable |
| Destination | spender (hook address) | Only the Geode hook contract can use this signature |
| Pool | poolId (witness) | Cannot be replayed on a different pool |
| One-shot | nonce | Consumed on first use, permanently invalidated |
amountIn tokens, for at most deadline - now seconds, usable only by the specific hook contract, on the specific pool, exactly once.
If the intent fills, you receive at least minAmountOut tokens in return. If it doesn’t fill, your tokens are never touched and the nonce remains available for reuse.
What a Settler Cannot Do
The settler submits your signed intent to the hook, but the hook enforces all safety checks on-chain:- Cannot change the amount — Permit2 verifies
amountInmatches the signature - Cannot change the recipient — output tokens are sent to
intent.owner, hardcoded in the settlement logic - Cannot underpay you — if the clearing price doesn’t meet
minAmountOut, the intent is skipped entirely - Cannot replay the signature — Permit2 nonces are consumed atomically
- Cannot front-run — all intents in a batch get the same uniform clearing price
No Residual Risk
Unlike protocols that hold standing Permit2 allowances, Geode intents leave no persistent authorization:- Before signing: Permit2 has your ERC20 approval, but no signature exists to use it
- After signing: A time-limited, single-use, amount-capped signature exists
- After settlement: The nonce is consumed — the signature is dead
- After deadline: Even if never settled, the signature expires and becomes cryptographically unusable
For integrators: The intent can be constructed and signed using any EIP-712 compatible library. The witness type string and typehash are defined in
GeodeTypes.sol. See the production fork tests for complete signing examples with real Permit2.