wormhole-foundation / example-liquidity-layer

Apache License 2.0
11 stars 11 forks source link

solana: overhaul local fills #122

Closed a5-pickle closed 4 months ago

a5-pickle commented 4 months ago

This change is a significant departure from how local (fast) fills were handled before.

Previous Implementation

In the previous implementation, a Wormhole message with a specific fast fill payload was posted. An integrator would listen to the VAA on the guardian spy network so that he can post it in order to redeem the fill. To prevent replay attacks, a redeemed fast fill account was created. Posting the VAA + creating this replay protection account is a large cost burden to the integrator. The cost to the solver is no different than having to deliver a CCTP transfer to another chain (because that process requires posting a Wormhole message, as well).

What's Different

Instead of a Wormhole message, the matching engine emits an event via Anchor's event CPI technique (which just invokes a privileged instruction, where the program's event authority is a signer). Integrators would listen to this event so that it knows when a fast fill was delivered. This change removes the requirement for the integrator to post a VAA. And the solver has a reduced cost to deliver this fast fill since he does not have to post a Wormhole message, which creates an account.

And instead of the integrator creating a replay protection account, the matching engine creates a fast fill account with a redeemed boolean. When an integrator redeems the fill, this flag gets set to true. The integrator no longer spends lamports to replay protect the fast fill. The solver pays lamports to create this account.

The solver can also get his lamports back by closing a fast fill account only if it is redeemed. Because the auction accounts already act as replay protection against starting new auctions, this operation should be safe.

Side Effects

In order to sequence these fast fills, an additional instruction was added to reserve a fast fill sequence number. Ideally, we would like to seed the fast fill as soon as the order is executed. But because there can be multiple fills delivered at the same time, seeding the fast fill with a sequence number can cause solver's execution to fail.

For these local fast fills, the solver needs to call the reserve_fast_fill_sequence_active_auction instruction prior to calling execute_fast_order_local instruction. He can try to be bold and call them in the same transaction. But if there are other fast fills that need to be sequenced from the same source chain and order sender, his bundled transaction will fail. The sequence reservation instruction should be called in a separate transaction prior to executing the order.

Associated with this change is an addition to the Typescript SDK to listen to these particular fills. Because there is no way to listen to these event CPI instructions like with normal program log Anchor events, we added a convenient way to listen to these fast fills.

Closes #48.

a5-pickle commented 4 months ago

Quick review, will wait for the detailed description to really dig in

Should be good to go. Also finally added the close redeemed fast fill instruction here: https://github.com/wormhole-foundation/example-liquidity-layer/pull/122/commits/507cb405dd2d6a00cd5269adaa15c2d53c8e088e, which the PR description mentioned.