Skip to content
This repository was archived by the owner on Apr 14, 2026. It is now read-only.

Commit 1527d86

Browse files
authored
Merge pull request #21 from catalystsystem/escrow
Input Settler Escrow documentation
2 parents c9e43db + 8cf6ca8 commit 1527d86

11 files changed

Lines changed: 150 additions & 93 deletions

File tree

src/components/solver/QuoteCommon.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ export type DutchAuctionData = {
55
collateralToken: string;
66
fillerCollateralAmount: string;
77
challengerCollateralAmount: string;
8-
localOracle: string;
9-
remoteOracle: string;
8+
inputOracle: string;
9+
oracle: string;
1010
slopeStartingTime: number;
1111
inputSlope: string;
1212
outputSlope: string;
@@ -21,8 +21,8 @@ export type LimitOrderData = {
2121
collateralToken: string;
2222
fillerCollateralAmount: string;
2323
challengerCollateralAmount: string;
24-
localOracle: string;
25-
remoteOracle: string;
24+
inputOracle: string;
25+
oracle: string;
2626
inputs: {}[];
2727
outputs: {}[];
2828
};

src/content/docs/1-system-architecture/100-overview.mdx

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,10 @@ Historically, these components have been intertwined, which presented scaling ch
2121

2222
### Input Settlement
2323

24-
The input settlement scheme manages user deposits and releases funds to solvers once intents are fulfilled. LI.FI intent currently implements one input settlement scheme:
24+
The input settlement scheme manages user deposits and releases funds to solvers once intents are fulfilled. The Open Intents Framework currently implements two input settlement scheme:
2525

26-
- [**TheCompact**](https://github.com/Uniswap/the-compact) via [`InputSettlerCompact.sol`](https://github.com/openintentsframework/oif-contracts/blob/d238f87d01552986b66d392d0f2ea77bd6e25f2f/src/input/compact/InputSettlerCompact.sol)
27-
28-
Resource locks support both fill-first flows and ordinary flows.
26+
- **Escrow** via [`InputSettlerEscrow.sol`](https://github.com/openintentsframework/oif-contracts/blob/main/src/input/escrow/InputSettlerEscrow.sol)
27+
- [**TheCompact**](https://github.com/Uniswap/the-compact) via [`InputSettlerCompact.sol`](https://github.com/openintentsframework/oif-contracts/blob/main/src/input/compact/InputSettlerCompact.sol). The Compact supports both fill-first flows and ordinary flows.
2928

3029
The intent system imposes no restrictions on the implementation of input settlements. Input settlements can access proven outputs through validation layers by calling [`efficientRequireProven`](https://github.com/openintentsframework/oif-contracts/blob/main/src/interfaces/IOracle.sol#L19-L27). If an order contains multiple outputs and the outputs are filled by different solvers, **the filler of the first output** in the order specification is considered the canonical solver.
3130

@@ -83,7 +82,7 @@ interface IValidationLayer {
8382
* @notice Check if a series of data has been attested to.
8483
* @dev Does not return a boolean; instead, it reverts if false.
8584
* This function returns true if proofSeries is empty.
86-
* @param proofSeries remoteOracle, remoteChainId, and dataHash encoded in chunks of 32*4=128 bytes.
85+
* @param proofSeries oracle, remoteChainId, and dataHash encoded in chunks of 32*4=128 bytes.
8786
*/
8887
function efficientRequireProven(
8988
bytes calldata proofSeries
@@ -128,14 +127,14 @@ Assuming the output description can be represented as:
128127

129128
```solidity
130129
struct OutputDescription {
131-
bytes32 remoteOracle;
132-
bytes32 remoteFiller;
130+
bytes32 oracle;
131+
bytes32 settler;
133132
uint256 chainId;
134133
bytes32 token;
135134
uint256 amount;
136135
bytes32 recipient;
137-
bytes remoteCall;
138-
bytes fulfillmentContext;
136+
bytes call;
137+
bytes context;
139138
}
140139
```
141140

src/content/docs/1-system-architecture/101-input-settlement.md

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@ sidebar:
66
order: 1
77
---
88

9-
Currently, only one Input Settler is supported:
9+
Two Single Chain Input Settlers are supported:
10+
- [**InputSettlerEscrow**](https://github.com/openintentsframework/oif-contracts/blob/main/src/input/escrow/InputSettlerEscrow.sol)
1011
- [**InputSettlerCompact**](https://github.com/openintentsframework/oif-contracts/blob/main/src/input/compact/InputSettlerCompact.sol)
1112

12-
The Compact uses resource locks and supports first-fill flows. However, LI.FI intents also support escrow-like flows.
13+
[Work is in progress](https://github.com/openintentsframework/oif-contracts/pull/49) to support multi chain inpurts settlers.
14+
15+
The Compact uses resource locks and supports fill-first flows. For traditional flows without resource locks, the escrow settler can be used. Escrow flows are not safe in fill-first flows and have to be opened before fills.
1316

1417
#### Default Output
1518
The default output for settlement schemes is [`MandateOutput`](https://github.com/openintentsframework/oif-contracts/blob/main/src/input/types/MandateOutputType.sol#L4-L18):
@@ -27,31 +30,29 @@ struct MandateOutput {
2730
```
2831
To verify if the encoded output description has been validated, send the hashed encoded payload to the appropriate local oracle along with relevant resolution details, such as the solver's identity.
2932

30-
## InputSettlerCompact
33+
## Single Chain Inputs
3134

32-
The Compact Settler uses the [`StandardOrder`](https://github.com/openintentsframework/oif-contracts/blob/main/src/input/types/StandardOrderType.sol#L6-L15):
35+
Single Chain Input Settlers uses [`StandardOrder`](https://github.com/openintentsframework/oif-contracts/blob/main/src/input/types/StandardOrderType.sol#L6-L15):
3336
```solidity
3437
struct StandardOrder {
3538
address user;
3639
uint256 nonce;
3740
uint256 originChainId;
3841
uint32 expires;
3942
uint32 fillDeadline;
40-
address localOracle;
43+
address inputOracle;
4144
uint256[2][] inputs;
4245
MandateOutput[] outputs;
4346
}
4447
```
4548

46-
The CompactSettler supports two ways to resolve locks once outputs are available for verification by the validation layer:
47-
48-
There are two ways to finalize an intent:
49-
1. [`finalise`](https://github.com/openintentsframework/oif-contracts/blob/main/src/input/compact/InputSettlerCompact.sol#L177-L184): Can only be called by the solver. The caller can designate where to send assets and whether to make an external call.
50-
2. [`finaliseWithSignature`](https://github.com/openintentsframework/oif-contracts/blob/main/src/input/compact/InputSettlerCompact.sol#L213-L221): Can be called by anyone with an [`AllowOpen`](https://github.com/openintentsframework/oif-contracts/blob/main/src/input/types/AllowOpenType.sol#L5-L9l) signature from the solver, containing the destination and call details.
49+
To finalise orders to get paid their inputs, the relevant finalise functions have to be called. 2 endpoints are available:
50+
1. `finalise`: To be called by the solver, the caller can designate where to send assets and whether to make an external call. Note that the Escrow & Compact interfaces are different to optimise for gas.
51+
2. `finaliseWithSignature`: Can be called by anyone with an [`AllowOpen`](https://github.com/openintentsframework/oif-contracts/blob/main/src/input/types/AllowOpenType.sol#L5-L9l) signature from the solver, containing the destination and call details.
5152

52-
### Intent Registration
53+
### Compact Intent Registration
5354

54-
While intents are transferred as `StandardOrder` structures, they are signed as a `BatchClaim` with the following structure:
55+
Intents are transferred as `StandardOrder`, within the Compact they are signed as a `BatchClaim` with the following structure:
5556

5657
```solidity
5758
struct BatchCompact {
@@ -62,12 +63,10 @@ struct BatchCompact {
6263
uint256[2][] idsAndAmounts;
6364
Mandate mandate;
6465
}
65-
```
66-
With the Mandate defined as:
67-
```solidity
66+
// With the Mandate defined as:
6867
struct Mandate {
6968
uint32 fillDeadline;
70-
address localOracle;
69+
address inputOracle;
7170
MandateOutput[] outputs;
7271
}
7372
```
@@ -76,6 +75,34 @@ Intents are EIP712-signed `BatchClaim`s using The Compact's domain separator.
7675

7776
Alternatively, intents can be registered on-chain. There are two ways to do this: either the sponsor (user) registers it, or someone pays for the entire claim and registers it on their behalf.
7877

78+
### Escrow Compact Registration
79+
80+
Intents are transferred as `StandardOrder` but can be registered in several ways:
81+
1. Registered by their owner through ERC-7683 `function open(bytes)`. This emits a ERC-7683 `event Open(bytes32 indexed orderId, bytes order)` and also sets its `function orderStatus(bytes)` to 1.
82+
2. Registered through ERC-3009 with the orderId as the nonce.. For each input a signature has to be provided and then `0x01, abi.encode(bytes[])`.
83+
3. Registered through Permit2 with the signature provided as `0x00, bytes` from the EIP-712 signed object `PermitBatchWitnessTransferFrom`:
84+
85+
```solidity
86+
struct PermitBatchWitnessTransferFrom {
87+
TokenPermissions[] permitted;
88+
address spender;
89+
uint256 nonce;
90+
uint256 deadline;
91+
Permit2Witness witness;
92+
}
93+
// With TokenPermissions as
94+
TokenPermissions(
95+
address token;
96+
uint256 amount;
97+
)
98+
// With Permit2Witness as
99+
Permit2Witness(
100+
uint32 expires;
101+
address inputOracle;
102+
MandateOutput[] outputs;
103+
)
104+
```
105+
79106
#### Integration Examples
80107
81108
- For a smart contract example of registering intents on behalf of someone else, see [`RegisterIntentLib.sol`](https://github.com/catalystsystem/catalyst-intent/blob/27ce0972c150ed113f66ae91069eb953f23d920b/src/libs/RegisterIntentLib.sol#L100-L131).

src/content/docs/1-system-architecture/102-output-settlement.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ uint256 slope;
3030
uint256 stopTime;
3131
string orderType; // "limit" or "dutch"
3232
33-
if (orderType == "limit") fulfillmentContext = "0x" || fulfillmentContext = "0x00";
34-
if (orderType == "dutch") fulfillmentContext = abi.encodePacked(0x01, slope, stopTime);
33+
if (orderType == "limit") context = "0x" || context = "0x00";
34+
if (orderType == "dutch") context = abi.encodePacked(0x01, slope, stopTime);
3535
```
3636

3737
Specifically for Dutch auctions, if the order contains multiple outputs, only the first one will function as an auction. The rest will resolve to the worst price. This is because solvers are only incentivized to compete on the first output in an order, since the winner of that output is the winner of the entire order once anyone fills the remaining outputs.

src/content/docs/2-devs/200-dev-overview.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ By integrating with Catalyst, you gain access to our network of solvers who comp
2424

2525
### Simple Integration
2626

27-
Catalyst is designed to work with common resource lock standards like [The Compact](/architecture/input#inputsettlercompact). No custom development is required, significantly reducing the engineering effort needed to support cross-chain functionality.
27+
Catalyst is designed to work with common resource lock standards like [The Compact](/architecture/input#compact-intent-registration). No custom development is required, significantly reducing the engineering effort needed to support cross-chain functionality.
2828

2929
### Flexibility to Expand
3030

@@ -54,6 +54,6 @@ Our full integration guide provides detailed instructions, code examples, and be
5454

5555
By default, Catalyst supports calls on delivery. This allows you to schedule calldata to be executed after the delivery of assets, enabling more complex cross-chain operations.
5656

57-
The default output type of Catalyst, called `OutputDescription`, supports secondary calls through its `remoteCall` field, allowing for additional execution logic upon delivery.
57+
The default output type of Catalyst, called `OutputDescription`, supports secondary calls through its `call` field, allowing for additional execution logic upon delivery.
5858

5959
[Learn more about Sub-Calls →](/devs/calls)

src/content/docs/2-devs/201-simple-swaps.mdx

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ struct CatalystCompactOrder {
7777
/** @dev The expiry of the lock. Enough time for the fill and validation needs to be provided. */
7878
uint32 fillDeadline;
7979
/** @dev Address of the validation layer on the origin chain. */
80-
address localOracle;
80+
address inputOracle;
8181
uint256[2][] inputs;
8282
OutputDescription[] outputs;
8383
}
@@ -97,7 +97,7 @@ struct BatchCompact {
9797
9898
struct CatalystWitness {
9999
uint32 fillDeadline; // CatalystCompactOrder.fillDeadline
100-
address localOracle; // CatalystCompactOrder.localOracle
100+
address inputOracle; // CatalystCompactOrder.inputOracle
101101
OutputDescription[] outputs; // CatalystCompactOrder.outputs
102102
}
103103
```
@@ -112,32 +112,32 @@ For `TheCompact`, the inputs need to be provided as an array of `[uint256 tokenI
112112

113113
```solidity
114114
struct OutputDescription {
115-
bytes32 remoteOracle;
116-
bytes32 remoteFiller;
115+
bytes32 oracle;
116+
bytes32 settler;
117117
uint256 chainId;
118118
bytes32 token;
119119
uint256 amount;
120120
bytes32 recipient;
121-
bytes remoteCall;
122-
bytes fulfillmentContext;
121+
bytes call;
122+
bytes context;
123123
}
124124
```
125125

126-
Note that `OutputDescription.remoteOracle` and `CatalystCompactOrder.localOracle` need to match. Together, they define the validation layer used. Each order should only use one validation layer, which can be an aggregation of AMBs.
126+
Note that `OutputDescription.oracle` and `CatalystCompactOrder.inputOracle` need to match. Together, they define the validation layer used. Each order should only use one validation layer, which can be an aggregation of AMBs.
127127

128-
`remoteFiller` specifies the output type. For limit orders, use the `CoinFiller` and set `fulfillmentContext` as empty (`0x`). For Dutch auctions, use the `CoinFiller` and set `fulfillmentContext` [appropriately](/solver/auctions#dutch-auction).
128+
`settler` specifies the output type. For limit orders, use the `CoinFiller` and set `context` as empty (`0x`). For Dutch auctions, use the `CoinFiller` and set `context` [appropriately](/solver/auctions#dutch-auction).
129129

130130
Specify the token as the `bytes32` identifier. For EVM, the address is left-padded, e.g., `0x000...00abcdef`.
131131

132-
#### RemoteCall
132+
#### Call
133133

134-
You can schedule additional calls to happen after token delivery. Note that if you have configured multiple outputs, the order of execution is not guaranteed (it may happen over multiple blocks). If `remoteCall` is provided, the `recipient` is called using the Catalyst interfaces. For arbitrary calls, the [Catalyst Multicaller](https://github.com/catalystsystem/catalyst-intent/blob/main/src/integrations/CatsMulticallHandler.sol) can be used.
134+
You can schedule additional calls to happen after token delivery. Note that if you have configured multiple outputs, the order of execution is not guaranteed (it may happen over multiple blocks). If `call` is provided, the `recipient` is called using the Catalyst interfaces. For arbitrary calls, the [Catalyst Multicaller](https://github.com/catalystsystem/catalyst-intent/blob/main/src/integrations/CatsMulticallHandler.sol) can be used.
135135

136136
[Learn more about Sub-Calls →](/devs/calls)
137137

138138
## Off-chain relay via resource locks
139139

140-
Off-chain relaying of swaps assumes that you have an existing [resource lock](/glossary#resource-lock) somewhere. This guide we assumes you use [TheCompact](/architecture/input#inputsettlercompact). When using pure resource lock flow, ensure funds are already deposited into the lock. For alternative integrations, refer to the [on-chain flow](#on-chain-relay).
140+
Off-chain relaying of swaps assumes that you have an existing [resource lock](/glossary#resource-lock) somewhere. This guide we assumes you use [TheCompact](/architecture/input#compact-intent-registration). When using pure resource lock flow, ensure funds are already deposited into the lock. For alternative integrations, refer to the [on-chain flow](#on-chain-relay).
141141

142142
```typescript
143143
// Submit an order to the order server
@@ -169,7 +169,7 @@ const submitOrder = async () => {
169169
nonce: 1005,
170170
originChainId: 84532,
171171
fillDeadline: 1744884642,
172-
localOracle: "0xada1de62bE4F386346453A5b6F005BCdBE4515A1",
172+
inputOracle: "0xada1de62bE4F386346453A5b6F005BCdBE4515A1",
173173
inputs: [
174174
[
175175
"36286452483532273188258183071097127586156282419649613466036116694645176389502",
@@ -178,18 +178,18 @@ const submitOrder = async () => {
178178
],
179179
outputs: [
180180
{
181-
remoteOracle:
181+
oracle:
182182
"0x0000000000000000000000007bc921c858c5390d9fd74c337dd009ec9a1b6b8f",
183-
remoteFiller:
183+
settler:
184184
"0x0000000000000000000000005d14806127d7caafcb8028c7736ae6b8aec583d9",
185185
chainId: 11155111,
186186
token:
187187
"0x0000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c7238",
188188
amount: 1000000,
189189
recipient:
190190
"0x0000000000000000000000009773dacbc46cafb4e055060565e319922b48607d",
191-
remoteCall: "0x",
192-
fulfillmentContext: "0x",
191+
call: "0x",
192+
context: "0x",
193193
},
194194
],
195195
},

src/content/docs/2-devs/210-calls.mdx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,22 +62,22 @@ struct Instructions {
6262
}
6363
```
6464

65-
When used: set `remoteCall = abi.encode(Instructions)`.
65+
When used: set `call = abi.encode(Instructions)`.
6666

6767
For the default Catalyst `OutputDescription`:
6868

6969
import { Code } from '@astrojs/starlight/components';
7070

7171
export const outputDescription = `
7272
struct OutputDescription {
73-
bytes32 remoteOracle;
74-
bytes32 remoteFiller;
73+
bytes32 oracle;
74+
bytes32 settler;
7575
uint256 chainId;
7676
bytes32 token;
7777
uint256 amount;
7878
bytes32 recipient; // = addressOf(CatsMulticallHandler)
79-
bytes remoteCall; // = abi.encode(Instructions)
80-
bytes fulfillmentContext;
79+
bytes call; // = abi.encode(Instructions)
80+
bytes context;
8181
}`;
8282

83-
<Code code={outputDescription} lang="solidity" mark={['bytes32 recipient; // = addressOf(CatsMulticallHandler)', 'bytes remoteCall; // = abi.encode(Instructions)']} />
83+
<Code code={outputDescription} lang="solidity" mark={['bytes32 recipient; // = addressOf(CatsMulticallHandler)', 'bytes call; // = abi.encode(Instructions)']} />

src/content/docs/3-solver/300-introduction.mdx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import { Steps } from '@astrojs/starlight/components';
4040
4. The proof is delivered to the input chain through the validation layer.
4141

4242
:::note[[Oracle system](/architecture/oracle)]
43-
is denoted as the `localOracle` and `output.oracle` in the order struct.
43+
is denoted as the `inputOracle` and `output.oracle` in the order struct.
4444
:::
4545

4646
5. The solver submits the order to the input settlement contract, verifying the delivery and unlocking the associated input tokens.
@@ -73,7 +73,7 @@ struct StandardOrder {
7373
uint256 originChainId;
7474
uint32 expires;
7575
uint32 fillDeadline;
76-
address localOracle;
76+
address inputOracle;
7777
uint256[2][] inputs;
7878
MandateOutput[] outputs;
7979
}
@@ -123,13 +123,14 @@ For more information about filling intents [View EVM Order Filling Guide →](/s
123123

124124
## Validating Fills
125125

126-
After filling intents, the proof of fill has to be sent to the input chain. The oracle system used for the order is specified through `localOracle` and `output.oracle`. These should match. However, validating filled outputs is highly oracle specific. For more, [View Oracle System Architecture ->](/architecture/oracle/#implemented-validation-interfaces) ->
126+
After filling intents, the proof of fill has to be sent to the input chain. The oracle system used for the order is specified through `inputOracle` and `output.oracle`. These should match. However, validating filled outputs is highly oracle specific. For more, [View Oracle System Architecture ->](/architecture/oracle/#implemented-validation-interfaces) ->
127127

128128
## Settling Orders
129129

130130
Lastly, intents have to be settled before their expiry. This is achieved by calling `finalise[withSignature]` on the designated InputSettler. The caller has to be the designated solver set on fill.
131131

132132
```solidity
133+
// For the Compact Input Settler
133134
function finalise(
134135
StandardOrder calldata order,
135136
bytes calldata signatures,
@@ -138,6 +139,14 @@ function finalise(
138139
bytes32 destination,
139140
bytes calldata call
140141
) external;
142+
// Or for the Escrow Input Settler
143+
function finalise(
144+
StandardOrder calldata order,
145+
uint32[] calldata timestamps,
146+
bytes32[] memory solvers,
147+
bytes32 destination,
148+
bytes calldata call
149+
) external;
141150
```
142151

143152
For more information about settling orders [View Order Settlement Guide →](/solver/settlement)

0 commit comments

Comments
 (0)