Swapping via Catalyst
Catalyst is an entirely componentized and permissionless system with no inherent trust elements. It is up to integrators to mix and match components as needed. We will provide baselines for generally available components.
A Catalyst order generally follows the structure of the CatalystCompactOrder
:
struct CatalystCompactOrder { address user; uint256 nonce; uint256 originChainId; uint32 fillDeadline; address localOracle; uint256[2][] inputs; OutputDescription[] outputs;}
Where uint256[2][] inputs
is equivalent to [uint256 tokenId, uint256 amount][]
and OutputDescription
is:
struct OutputDescription { bytes32 remoteOracle; bytes32 remoteFiller; uint256 chainId; bytes32 token; uint256 amount; bytes32 recipient; bytes remoteCall; bytes fulfillmentContext;}
The CatalystCompactOrder
needs to be appropriately signed. For TheCompact
settlement interface, use the following transformation:
struct BatchCompact { address arbiter; // Associated settlement contract address sponsor; // CatalystCompactOrder.user uint256 nonce; // CatalystCompactOrder.nonce uint256 expires; // CatalystCompactOrder.fillDeadline uint256[2][] idsAndAmounts; // CatalystCompactOrder.inputs CatalystWitness witness;}
struct CatalystWitness { uint32 fillDeadline; // CatalystCompactOrder.fillDeadline address localOracle; // CatalystCompactOrder.localOracle OutputDescription[] outputs; // CatalystCompactOrder.outputs}
The sponsor (user) shall then sign it as an EIP-712 signed structure.
Order Parameters
Inputs
For TheCompact
, the inputs need to be provided as an array of [uint256 tokenId, uint256 amount]
. The tokenId
refers to the TheCompact
encoded tokenId, which contains relevant lock details. See IdLib.sol::toIdIfRegistered.
Output
struct OutputDescription { bytes32 remoteOracle; bytes32 remoteFiller; uint256 chainId; bytes32 token; uint256 amount; bytes32 recipient; bytes remoteCall; bytes fulfillmentContext;}
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.
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.
Specify the token as the bytes32
identifier. For EVM, the address is left-padded, e.g., 0x000...00abcdef
.
RemoteCall
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 can be used.
Structure
Then configure the relevant order structure:
address user
: Pays for the inputs of the order. If the order fails, will be recipient of the refund.uint256 nonce
: Unique order identifier to redeem locks with. If two orders share the same nonce and user, only one can be redeemed.uint256 originChainId
: The chainId (canonical) of the input chain.uint32 fillDeadline
: The expiry of the lock. Enough time for the fill and validation needs to be provided.address localOracle
: Address of the validation layer on the origin chain.
Broadcasting Order
There are two ways to manage orders:
- On-chain deposits.
- Off-chain relay.
Catalyst recommends that you use off-chain relay for a cheaper and more seamless experience. Though, for a fully decentralised system the on-chain deposit may provide advantages for you.
On-chain deposits
For non-wallet integrators, on-chain deposits is the easiest integration. It uses more gas but abstracts the resource lock complexity away:
function depositFor(CatalystCompactOrder calldata order, ResetPeriod resetPeriod) external;
resetPeriod
should exceed the expiry window.
Off-chain relaying
For other integrators, off-chain relaying is both the easiest and cheapest integration. Simply use the associated integration endpoint of your wallet of choice and then broadcast the order through the order-server.
TODO: endpoint