Skip to content

Commit 3a1d030

Browse files
ilariaeIlaria Enache0xlukemdawnkelly09eshaben
authored
Ilariae/wormhole settlements (#254)
* overview page * protocols architecture * added todo comments * Integrate Wormhole Settlement Routes using the SDK * liquidity layer * solver * Apply suggestions from code review Co-authored-by: Lucas Malizia <131050418+0xlukem@users.noreply.github.com> * meta descriptions * index pages * llms * adds index page card for WH liquidity layer page, edits to same page * typo fix * fix conflict * fix conflict * llms * messaging index page * tutorials index page * llms * more updates to index pages, etc plus solver build page * update architecture and overview pages * tutorial edits * output element * llms * update pictures * remove comments * update llms * replace contact link * update llms * Apply suggestions from code review Co-authored-by: Erin Shaben <eshaben@icloud.com> * update llms * remove page * update llms --------- Co-authored-by: Ilaria Enache <ilaria@Host-009.homenet.telecomitalia.it> Co-authored-by: Lucas Malizia <131050418+0xlukem@users.noreply.github.com> Co-authored-by: DAWN KELLY <dawnkelly09@gmail.com> Co-authored-by: Erin Shaben <eshaben@icloud.com>
1 parent f126cac commit 3a1d030

File tree

20 files changed

+1524
-0
lines changed

20 files changed

+1524
-0
lines changed

build/contract-integrations/.pages

+1
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ nav:
77
- 'CCTP': 'cctp.md'
88
- native-token-transfers
99
- multigov
10+
- settlements
1011
- 'Development Environment': 'dev-env.md'
1112
- 'FAQs': 'faqs.md'

build/contract-integrations/index.md

+8
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,14 @@ The content in this section will teach you how to create smart contracts that in
5959

6060
[:custom-arrow: Get started with MultiGov](/docs/build/contract-integrations/multigov/)
6161

62+
- :octicons-code-16:{ .lg .middle } **Wormhole Settlements**
63+
64+
---
65+
66+
Build with Wormhole Settlements, including integrating the Liquidity Layer into your application and running a Solver for efficient cross-chain asset transfers.
67+
68+
[:custom-arrow: Get started with Settlements](/docs/build/contract-integrations/settlements/)
69+
6270
- :octicons-terminal-16:{ .lg .middle } **Development Environment**
6371

6472
---
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
title: Wormhole Settlements
2+
nav:
3+
- index.md
4+
- 'Build on the Wormhole Liquidity Layer': 'liquidity-layer.md'
5+
- 'Run a Wormhole Settlement Solver': 'solver.md'
6+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
title: Wormhole Settlements
3+
description: Start building with Wormhole Settlements; integrate with the Liquidity Layer and set up Solvers to enable seamless cross-chain asset transfers.
4+
---
5+
6+
# Wormhole Settlements
7+
8+
## Get Started
9+
10+
This section provides resources to build with Wormhole Settlements, including integrating the Liquidity Layer into your application and running a Solver for efficient cross-chain asset transfers.
11+
12+
<div class="grid cards" markdown>
13+
14+
- :octicons-code-16:{ .lg .middle } **Build on the Liquidity Layer**
15+
16+
---
17+
18+
Integrate seamlessly with Wormhole's Liquidity Layer, learn key EVM contract functions for fast and secure cross-chain transfers.
19+
20+
[:custom-arrow: Build on the Liquidity layer](/docs/build/contract-integrations/settlements/liquidity-layer/)
21+
22+
- :octicons-code-16:{ .lg .middle } **Run a Settlement Solver**
23+
24+
---
25+
26+
Set up, configure, and run a Wormhole Settlement Solver on Solana's Matching Engine to fulfill cross-chain transfers efficiently and securely.
27+
28+
[:custom-arrow: Run a Solver](/docs/build/contract-integrations/settlements/solver/)
29+
30+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
---
2+
title: Wormhole Settlements
3+
description: Learn how to build on the Wormhole Liquidity Layer, the underlying chain abstraction infrastructure layer for protocols across Wormhole-connected ecosystems.
4+
---
5+
6+
# Build on the Wormhole Liquidity Layer
7+
8+
## Introduction
9+
10+
The Wormhole Liquidity Layer is the underlying chain abstraction infrastructure layer for protocols across Wormhole-connected ecosystems. It allows these protocols to bundle call data containing arbitrary actions that can be executed atomically alongside each transfer. This feature enables developers to create fully chain-abstracted user experiences, including constructing natively cross-chain decentralized exchanges (DEXs), borrow-lend protocols, payment protocols, and other applications atop this layer. The following section describes the key smart contract components for teams seeking to build atop Wormhole Settlement.
11+
12+
## EVM Functions
13+
14+
The EVM Token Router is a simple interface against which to integrate. For an integrator, the contracts have two main entry points: `placeMarketOrder` and `placeFastMarketOrder`.
15+
16+
### Fast Market Order
17+
18+
The `placeFastMarketOrder` function allows the caller to elect for a _faster-than-finality_ transfer of USDC (with an arbitrary message payload) to the destination chain by setting the `maxFee` and `deadline` parameters. Using this interface does not guarantee that the caller's transfer will be delivered faster than finality; however, any willing market participants can compete for the specified `maxFee` by participating in an auction on the Solana `MatchingEngine`
19+
20+
```solidity title="`placeFastMarketOrder` interface"
21+
function placeFastMarketOrder(
22+
uint128 amountIn,
23+
uint16 targetChain,
24+
bytes32 redeemer,
25+
bytes calldata redeemerMessage,
26+
uint128 maxFee,
27+
uint32 deadline
28+
) external payable returns (uint64 sequence, uint64 fastSequence);
29+
```
30+
31+
??? interface "Parameters `placeFastMarketOrder()`"
32+
33+
`amountIn` ++"uint128"++
34+
35+
The amount to transfer.
36+
37+
---
38+
39+
`targetChain` ++"uint16"++
40+
41+
Target chain ID.
42+
43+
---
44+
45+
`redeemer` ++"bytes32"++
46+
47+
Redeemer contract address.
48+
49+
---
50+
51+
`redeemerMessage` ++"bytes"++
52+
53+
An arbitrary payload for the redeemer.
54+
55+
---
56+
57+
`maxFee` ++"uint128"++
58+
59+
The maximum fee the user wants to pay to execute a fast transfer.
60+
61+
---
62+
63+
`deadline` ++"uint32"++
64+
65+
The deadline for the fast transfer auction to start. Note: This timestamp should be for the `MatchingEngine` chain (such as Solana) to avoid any clock drift issues between different blockchains. Integrators can set this value to `0` if they don't want to use a deadline.
66+
67+
The `placeFastMarketOrder` function returns a sequence number for the Wormhole Fill message. This function requires the caller to provide a `msg.value` equal to the amount returned by the `messageFee()` function on the `IWormhole.sol` interface.
68+
69+
### Market Order
70+
71+
The `placeMarketOrder` function is a _wait-for-full-finality_ USDC transfer with an arbitrary message payload. The Swap Layer, built on top of the Wormhole Settlement, uses this function if the auction on the matching engine for `placeFastMarketOrder` doesn't start within a specific deadline.
72+
73+
```solidity title="`placeMarketOrder` interface"
74+
function placeMarketOrder(
75+
uint128 amountIn,
76+
uint16 targetChain,
77+
bytes32 redeemer,
78+
bytes calldata redeemerMessage,
79+
) external payable returns (uint64 sequence, uint64 protocolSequence);
80+
```
81+
82+
??? interface "Parameters `placeMarketOrder()`"
83+
84+
`amountIn` ++"uint128"++
85+
86+
The amount to transfer.
87+
88+
---
89+
90+
`targetChain` ++"uint16"++
91+
92+
Target chain ID.
93+
94+
---
95+
96+
`redeemer` ++"bytes32"++
97+
98+
Redeemer contract address.
99+
100+
---
101+
102+
`redeemerMessage` ++"bytes"++
103+
104+
An arbitrary payload for the redeemer.
105+
106+
The `placeMarketOrder` function returns a sequence number for the Wormhole Fill message. This function requires the caller to provide a `msg.value` equal to the amount returned by the `messageFee()` function on the `IWormhole.sol` interface.
107+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
---
2+
title: Wormhole Settlement Solver
3+
description: Set up, configure, and run a Wormhole Settlement Solver on Solana's Matching Engine to fulfill cross-chain transfers efficiently and securely.
4+
---
5+
6+
# Run a Wormhole Settlement Solver
7+
8+
## Introduction
9+
10+
This page provides instructions on how to set up, configure, and run a Solver for Wormhole Settlement using the [example solver](https://github.com/wormholelabs-xyz/example-liquidity-layer/tree/update-solver-example/solver){target=\_blank}.
11+
12+
A Solver is an off-chain agent responsible for:
13+
14+
- Listening to cross-chain transfer requests sent over Wormhole
15+
- Bidding in auctions (on Solana) to fulfill each request
16+
- Facilitating the actual cross-chain transfer by locking/burning assets on Solana and minting/unlocking them on the destination chain
17+
- Rebalancing once the origin chain transaction finalizes and is redeemed back on Solana
18+
19+
For information on how the protocol functions and its core features, please visit the [Wormhole Settlement](/docs/learn/messaging/wormhole-settlements/overview/){target=\_blank} page.
20+
21+
## Background
22+
23+
The Solana Matching Engine's permissionless English auction is a central component of Wormhole Settlements protocol architecture. The Matching Engine contract allows any third-party solver to interact with the matching engine to place bids or improve existing ones. The contract includes four key instructions:
24+
25+
1. `initialize_auction` - creates a new auction account on-chain and sets basic parameters like the auction's token mint, the amount required, and the bidding period details
26+
2. `bid` - allows a solver to place or update a bid on the active auction
27+
3. `finalize_auction` - following the conclusion of the auction, this instruction completes the fast transfer by sending funds to the recipient on the target chain. This instruction may call the Circle CCTP contract or release an NTT contract in the future, depending on the shuttle asset in question. Failure to execute this message within a predefined grace period may result in a penalty for the winning bidder.
28+
4. `cancel_auction` - cancels an open auction when the auction is no longer valid or was created by mistake. The program returns all locked funds to their respective owners
29+
30+
These instructions work together to carry out the auction as follows:
31+
32+
- The solver transfers the bid amount to the program escrow account, which ensures they have liquidity
33+
- With each successful call of `bid`, the program updates the auction to the new highest bidder, and the prior bid is atomically sent back to the originating solver
34+
- The originating solver can repurpose the returned funds and use them to improve their bid
35+
- Following the auction, the winning solver has to call an instruction on the matching engine to execute the intent
36+
37+
When placing a bid, whether initial or improved, the solver must deposit the required funds plus a security deposit into the matching engine contract. In this permissionless auction, the requirement of this principal amount plus the security deposit ensures a solver's credible commitment to fulfill the transfer. Malicious actors could place hollow bids without this safeguard, undermining the auction's credibility and hindering true price discovery.
38+
39+
If the winning solver fails to call the `finalize_auction` instruction, other competing solvers may permissionlessly 'slash' the solver by executing the instruction on their behalf and collecting a portion of the original security deposit as a reward. The remaining portion is routed to the user as compensation for the unanticipated delay. This mechanism properly incentivizes timely execution through solver redundancy and competition.
40+
41+
## Testnet Example Solver
42+
43+
You can clone the Wormhole [`example-liquidity-layer`](https://github.com/wormholelabs-xyz/example-liquidity-layer){target=\_blank} repository to use the included [`solver`](https://github.com/wormholelabs-xyz/example-liquidity-layer/tree/main/solver){target=\_blank} directory as an example solver to fulfill fast orders by interacting with the Matching Engine on Solana.
44+
45+
!!!warning
46+
This example is not optimized for performance, has only been tested on Solana devnet, and is not intended for production use. Any assumptions made in this example may not translate to mainnet.
47+
48+
### Prerequisites
49+
50+
In order to build and install dependencies locally in this repo, you will need:
51+
52+
- node v20.18.1
53+
- npmv - get started by installing `nvm` using this [installation guide](https://github.com/nvm-sh/nvm?tab=readme-ov-file#installing-and-updating){target=\_blank}
54+
55+
Navigate into the `solver` directory, then run the command below to set up your environment and install the node dependencies and Matching Engine package:
56+
57+
```sh
58+
make dependencies
59+
```
60+
61+
### Set up Config
62+
63+
The following is an example of a `config.json` file for Solana devnet. The keys here are required for both the publisher and example solver processes.
64+
65+
```json
66+
{
67+
"environment": "Testnet",
68+
"zmqChannels": {
69+
"fastVaa": "tcp://localhost:6001",
70+
"finalizedVaa": "tcp://localhost:6002"
71+
},
72+
"publisher": {
73+
"log": {
74+
"level": "info"
75+
},
76+
"vaaSpy": {
77+
"host": "localhost:7073",
78+
"enableObservationCleanup": true,
79+
"observationSeenThresholdMs": 1500000,
80+
"observationCleanupIntervalMs": 500,
81+
"observationsToRemovePerInterval": 5,
82+
"delayedThresholdMs": 60000
83+
}
84+
},
85+
"solver": {
86+
"log": {
87+
"level": "info",
88+
"filename": "logs/solver.log"
89+
},
90+
"connection": {
91+
"rpc": "<https://your-devnet-rpc-here/>",
92+
"maxTransactionsPerSecond": 5,
93+
"commitment": "processed",
94+
"addressLookupTable": "YourAddressLookupTab1eHere11111111111111111",
95+
"matchingEngine": "mPydpGUWxzERTNpyvTKdvS7v8kvw5sgwfiP8WQFrXVS",
96+
"mint": "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU",
97+
"knownAtaOwners": [
98+
"Payer11111111111111111111111111111111111111",
99+
"Payer11111111111111111111111111111111111112",
100+
"Payer11111111111111111111111111111111111113"
101+
]
102+
}
103+
},
104+
"routerEndpoints": [
105+
{
106+
"chain": "Sepolia",
107+
"endpoint": "0xE57D917bf955FedE2888AAbD056202a6497F1882",
108+
"rollbackRisk": 0.0069,
109+
"offerEdge": 0.042
110+
},
111+
{
112+
"chain": "Avalanche",
113+
"endpoint": "0x8Cd7D7C980cd72eBD16737dC3fa04469dcFcf07A",
114+
"rollbackRisk": 0.0069,
115+
"offerEdge": 0.042
116+
},
117+
{
118+
"chain": "OptimismSepolia",
119+
"endpoint": "0x6BAa7397c18abe6221b4f6C3Ac91C88a9faE00D8",
120+
"rollbackRisk": 0.0069,
121+
"offerEdge": 0.042
122+
},
123+
{
124+
"chain": "ArbitrumSepolia",
125+
"endpoint": "0xe0418C44F06B0b0D7D1706E01706316DBB0B210E",
126+
"rollbackRisk": 0.0069,
127+
"offerEdge": 0.042
128+
},
129+
{
130+
"chain": "BaseSepolia",
131+
"endpoint": "0x824Ea687CD1CC2f2446235D33Ae764CbCd08e18C",
132+
"rollbackRisk": 0.0069,
133+
"offerEdge": 0.042
134+
},
135+
{
136+
"chain": "Polygon",
137+
"endpoint": "0xa098368AaaDc0FdF3e309cda710D7A5f8BDEeCD9",
138+
"rollbackRisk": 0.0069,
139+
"offerEdge": 0.042
140+
}
141+
]
142+
}
143+
```
144+
145+
The rollback risks and offer edges configured in the sample config are arbitrary placeholders. You should use historical data and your risk tolerance, to determine appropriate values for your project.
146+
147+
### Listen to Activity
148+
149+
The example solver listens to attested Wormhole messages (VAAs) published on the Wormhole Guardian gossip network. To listen to this gossip network and run the VAA publisher, run the command below. Docker compose is used to listen to the Pyth Beacon and start the [`publishActivity`](https://github.com/wormholelabs-xyz/example-liquidity-layer/blob/update-solver-example/solver/app/publishActivity.ts){target=\_blank} process.
150+
151+
```sh
152+
NETWORK=testnet CONFIG=path/to/config.json make run-publisher
153+
```
154+
155+
You should see output resembling:
156+
157+
<div id="termynal" data-termynal>
158+
<span data-ty> Start logging with info level.</span>
159+
<span data-ty> 2025-01-21 16:38:28.145 [publisher] info: Environment: Testnet</span>
160+
<span data-ty> 2025-01-21 16:38:36.631 [publisher] info: Fast VAA. chain=OptimismSepolia, sequence=33635, vaaTime=1737499116</span>
161+
<span data-ty> 2025-01-21 16:38:51.044 [publisher] info: Fast VAA. chain=OptimismSepolia, sequence=33637, vaaTime=1737499130</span>
162+
<span data-ty> 2025-01-21 16:40:24.890 [publisher] info: Fast VAA. chain=OptimismSepolia, sequence=33639, vaaTime=1737499224</span>
163+
</div>
164+
165+
To set up the Pyth Beacon (which is run using make `run-publisher`), you may need to increase the UDP buffer size for the OS:
166+
167+
=== "Linux"
168+
169+
```sh
170+
sudo sysctl -w net.core.rmem_max=2097152
171+
sudo sysctl -w net.core.rmem_default=2097152
172+
```
173+
174+
=== "MacOS"
175+
176+
```sh
177+
sudo sysctl -w net.inet.udp.recvspace=2097152
178+
```
179+
180+
### Running the Example Solver
181+
182+
Using the same config for your publisher, run the example solver with the command below.
183+
184+
```sh
185+
CONFIG=path/to/config.json make run-solver
186+
```
187+
188+
It is recommended you write log output to a file so errors can be tracked. The example config above specifies an example log filename.
189+
190+
This process reads the following environment variables:
191+
192+
```sh
193+
SOLANA_PRIVATE_KEY_1=
194+
SOLANA_PRIVATE_KEY_2=
195+
SOLANA_PRIVATE_KEY_3=
196+
SOLANA_PRIVATE_KEY_4=
197+
SOLANA_PRIVATE_KEY_5=
198+
```
199+
200+
At least one of these environment variables must be defined as a keypair encoded in base64 format. These payers must have SOL to send transactions on Solana devnet. If they need funds, they can request them from the [Solana devnet faucet](https://faucet.solana.com/){target=\_blank}.
201+
202+
The example solver assumes that these payers own USDC Associated Token Accounts(ATAs), which will be used to fulfill fast transfers. These ATAs must be funded with Solana Devnet USDC. If your ATAs need funds, request some at the [Circle testnet faucet](https://faucet.circle.com/){target=\_blank}.
203+
204+
Wallets and their corresponding ATA will be disabled if there are insufficient funds to pay for transactions or fulfill fast transfers. These constraints can be modified using the `updatePayerMinimumLamports` and `updateTokenMinimumBalance` methods.
205+
206+
An address lookup table is required to execute some transactions. Use the command below to create one.
207+
208+
```sh
209+
CONFIG=path/to/config.json make create-lut
210+
```
211+
212+
`SOLANA_PRIVATE_KEY_1` must be defined for this script to work.
213+
214+
The example solver has the following toggles depending on which orders you want to fulfill:
215+
216+
- `enableCctpOrderPipeline()`
217+
- `enableLocalOrderPipeline()`
218+
- `enablePlaceInitialOffer()`
219+
- `enableImproveOffer()`
220+
221+
See the comments in [runExampleSolver](https://github.com/wormholelabs-xyz/example-liquidity-layer/blob/update-solver-example/solver/app/runExampleSolver.ts){target=\_blank} for more information.
222+
223+
This example solver does NOT do the following:
224+
225+
- Discriminate between the CCTP source networks. You must add logic to determine whether you want to constrain fulfilling orders from specific networks. This solver will try to fulfill all orders as long as `enableCctpOrderPipeline()` is called
226+
- Discriminate among fulfillment sizes. No logic determines how small or large fast order transfer sizes should be. This solver will try to fulfill anything as long as your balance can handle it
227+
- Add auctions to auction history. We recommend that after settling a complete auction (one that you have won), you write the auction pubkey to a database and have a separate process to add auction history entries to reclaim rent from these auction accounts. The auction history time delay is two hours after the VAA timestamp. This example does not prescribe any specific database, so add whichever you want
228+
229+
230+
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)