Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add documentation for solvers #24

Merged
merged 5 commits into from
Feb 19, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions docs/amm.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,78 @@ referencePair=0x1111111111111111111111111111111111111111
cast abi-encode 'f((address))' "($referencePair)"
```

## I'm a solver. How do I use CoW AMM liquidity?

CoW AMM orders already appear in the CoW Protocol orderbook, so you're already using its liquidity.
However, CoW AMMs allow solvers to specify custom buy and sell amounts, as long as the order preserves or increase the constant product invariant of the token reserves.

CoW AMMs can be treated as a liquidity source akin to Uniswap or Balancer weighted pools with uniform weights.
Each CoW AMM is a pair that trades two tokens.

Importantly, surplus for a CoW AMM order is measured differently when computing the solver reward payout.

### Indexing CoW AMMs

CoW AMM pairs can be detected by listening to the [`ConditionalOrderCreated` events](https://docs.cow.fi/cow-protocol/reference/contracts/periphery/composable-cow#indexing) emitted by the `ComposableCoW` instance for the current chain (see the [official docs](https://docs.cow.fi/cow-protocol/reference/contracts/periphery) for the current deployment addresses).

The order owner is a CoW AMM if its [handler](https://docs.cow.fi/cow-protocol/reference/contracts/periphery/composable-cow#conditionalorderparams) is the contract `ConstantProduct`. Official deployment addresses for the contracts in this repo can be found in the file [`networks.json`](../networks.json).

The field `staticInput` represents the parameters of the AMM, as for example the traded tokens. A description of each parameter can be found in the [instructions on how to create an order](#constantproduct-static-input).

The AMM reserves are the owner's balance of the two tokens traded by the AMM.

There are a few caveats to listening to these events:
- CoW AMM orders can be cancelled at any time with a call to [`ComposableCoW.remove`](https://docs.cow.fi/cow-protocol/reference/contracts/periphery/composable-cow#remove).
There is no corresponding event onchain, but the current validity state can be tracked with [`ComposableCoW.singleOrders`](https://docs.cow.fi/cow-protocol/reference/contracts/periphery/composable-cow#singleorders).
- While it's strongly discuraged behavior, there's nothing stopping the same CoW AMM from trading multiple pairs.
A batch can include only a single custom order per AMM address (this is because a solver can `commit` to only a single order per AMM address).
Moreover, if the AMM trades two overlapping pairs, settling one order may affect the reserve balance of an unrelated pair after the order is executed.
- Even if an event is emitted, the order may be impossible to settle.
This can happen for example if the encoding of `staticInput` is invalid.

### Settling a custom order

You need to choose a valid CoW Swap order with the following restrictions:

- `sellToken`: any token in the pair.
- `buyToken`: the other token in the pair.
- `receiver`: must be `RECEIVER_SAME_AS_OWNER` (zero address).
- `sellAmount`: any value.
- `buyAmount`: any value such that, after trading these exact amounts, the product of the token reserves is no smaller than before trading.
- `validTo`: at most 5 minutes after the block timestamp at execution time.
- `appData`: must be the value specified in `staticInput`.
- `feeAmount`: must be zero.
- `kind`: any value.
- `partiallyFillable`: any value.
- `sellTokenBalance`: must be `BALANCE_ERC20`.
- `buyTokenBalance`: must be `BALANCE_ERC20`.

You also need to compute:
- the order hash `hash` as defined in the library `GPv2Order`, and
- the order signature (example code that generates a valid signature is [the `getTradeableOrderWithSignature` function in the ComposableCoW repo](https://github.com/cowprotocol/composable-cow/blob/main/src/ComposableCoW.sol)).

This order can be included in a batch as any other CoW Protocol orders with three extra conditions:
- One of the pre-interaction must set the commitment by calling `ConstantProduct.commit(hash)`.
- Must contain at most one order from the AMM in the same batch.
- One of the post-interactions must reset the commitment by calling `ConstantProduct.commit(EMPTY_COMMITMENT)`.

The last step (clearing the commit) is technically not required for the batch to settle successfully, however it makes the settlement overall cheaper, since it resets the storage slot.
However, leaving the commit set means that no AMM orders will appear in the orderbook until the commit is reset.
Not clearing the commit at the end of the batch is considered slashable behavior.

### Surplus

The surplus for a CoW AMM order is measured differently depending on which AMM order is executed.

If picking the default CoW AMM order (that is, it's settled with the empty commitment), then the surplus is computed exactly like any other CoW Swap order.

Otherwise, if we call `X` (resp. `Y`) the reserves of sell (resp. buy) token, and `x` (resp. `y`) the sell (resp. buy) amount, then the order surplus is computed as:
```
x (Y + y)
surplus = y - --------- .
X
```
Comment on lines +166 to +170
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See Slack.


## Risk profile

The risks for the funds on the AMM are comparable to the risks of depositing the same reserves on a constant-product curve like Uniswap v2.
Expand Down