Settlement Flows#
TetraFi settles trades across chains using ERC-7683 intents. Three lock types, four settlement paths, and a cross-chain oracle network ensure atomic DvP regardless of the chains involved.
Settlement Lifecycle#
RFQ & Auction
Solvers compete with sealed bids
Escrow Lock
Taker's funds locked on origin chain
Solver Fill
Solver delivers output on destination chain
Oracle Proof
Cross-chain attestation of fill
Claim / Refund
Solver claims escrow or taker refunds
WORM Audit
Hash-chained evidence record
RFQ & Auction
Solvers compete with sealed bids
Escrow Lock
Taker's funds locked on origin chain
Solver Fill
Solver delivers output on destination chain
Oracle Proof
Cross-chain attestation of fill
Claim / Refund
Solver claims escrow or taker refunds
WORM Audit
Hash-chained evidence record
End-to-end settlement: under 3 minutes
End-to-End Settlement
DvP Settlement Sequence
Cross-Chain Settlement Walkthrough
Lock Types#
Lock Type Comparison
| Feature | ResourceLock | Permit2Escrow | EIP-3009Escrow |
|---|---|---|---|
Settlement Model4 features | |||
Direction | Output-first | Input-first | Input-first |
Byte Code | 0xff | 0x00 | 0x01 |
Taker deposits first? | |||
Solver fills first? | |||
Properties4 features | |||
Capital efficiency | |||
Broad token support | |||
Gasless approval | |||
Non-revocable commitment | |||
Best For3 features | |||
Default choice | |||
USDC/EURC corridors | |||
Exotic tokens | |||
- Taker pre-deposits into The Compact
- Allocator co-signs the commitment (prevents double-spend)
- Solver fills on destination chain with own capital
- Oracle attests fill → Arbiter processes
batchClaim() - Taker's allocation released to solver
Escape hatch: If the allocator is unresponsive, taker calls enableForcedWithdrawal() → waits the reset period → forcedWithdrawal(). Deterministic exit, no permission needed.
- Taker calls
open()→ funds locked → state =Deposited - Solver fills on destination → oracle attests
- Solver calls
finalise()with oracle proof → state =Claimed - OR: deadline expires → taker calls
refund()→ state =Refunded
Equivocation Protection#
Without ResourceLock, a user can revoke token approval after the solver fills - leaving the solver with an unfillable claim.
ResourceLock solves this by converting token approval into a non-revocable credible commitment. Solvers can act on a signature (milliseconds) rather than waiting for source-chain finality (minutes). This is the primary reason ResourceLock is the default settlement mode.
Settlement Path Routing#
The system selects one of four paths based on compliance status and lock type:
Default path for regulated corridors. Both counterparties have valid ComplianceRegistry attestations. ResourceLock provides output-first settlement with maximum capital efficiency.
Pre-trade: 7 compliance checks (jurisdiction, tier, expiry, sanctions, PEP, Travel Rule, counterparty). Post-trade: evidence logged to WORM ledger.
Fill Deadlines#
Every StandardOrder has two deadlines:
| Deadline | Purpose |
|---|---|
fillDeadline | Solver must fill on destination chain before this time |
expires | After this time, taker can call refund() to reclaim escrowed funds |
expires is always after fillDeadline. Between the two, the oracle proof may still be in transit.
Order Types & Context Byte#
The context field in MandateOutput encodes the order type. The OutputSettler reads this to determine how to resolve the final output amount.
| Value | Type | Length | Description |
|---|---|---|---|
0x00 | Limit | 1 byte | Static output amount, no decay |
0x01 | Dutch Auction | 41 bytes | startTime + stopTime + slope (time-decaying price) |
0xe0 | Exclusive Limit | 37 bytes | exclusiveFor solver + startTime (single-solver window, then open) |
0xe1 | Exclusive Dutch | 73 bytes | Exclusive window with Dutch decay (exclusiveFor + startTime + stopTime + slope) |
Constants live in FulfilmentLib.sol (LIMIT_ORDER = 0x00, DUTCH_AUCTION = 0x01, EXCLUSIVE_LIMIT_ORDER = 0xe0, EXCLUSIVE_DUTCH_AUCTION = 0xe1).
For Dutch auction types (0x01, 0xe1), price decays linearly from startTime to stopTime according to slope. Typical corridor defaults: 1 bps → 3 bps over 2–10 minutes, though concrete timing is encoded per-order.
Order State Machine#
Off-Chain Order Lifecycle
Path Selection Logic#
- Compliant? - Valid ComplianceRegistry attestation → Compliant path. None → Direct only
- ResourceLock? - Token/chain supports Compact → ResourceLock. Otherwise → Permit2Escrow fallback
- Corridor gated? - Compliance-required corridor + no attestation → rejected
Path Defaults by Persona#
| Persona | Default Path | Reason |
|---|---|---|
| Direct User | Compliant + ResourceLock | Full on-chain compliance |
| Company | Compliant + ResourceLock | Workspace-level, per-member |
| Broker | Direct + ResourceLock | KYC delegated to integrator |
| LP/Maker | Direct + ResourceLock | Compliance at fill time |
See Personas & Workspaces for the full persona model - including data-visibility rules and onboarding requirements per role.
Error Cases#
| Scenario | Error | Recovery |
|---|---|---|
| Missing attestation | 403 COMPLIANCE_FAILED | Complete KYC, wait for sync |
| Expired attestation | 403 ATTESTATION_EXPIRED | Renew verification |
| Lock unavailable | Auto fallback | Engine uses Permit2Escrow |
| Corridor not configured | 400 CORRIDOR_UNAVAILABLE | Contact TetraFi ops |