Bundle Building
This document describes how a node is expected to derive certain parameters for the payload which is then structured and formatted via the payload types and PADE encoding format.
Note that a lot of these things cannot or are not enforced at the contract level and rely on the economic security & sufficiently staked assumptions.
Asset list
The asset list of a given bundle must encompass any asset referenced in the bundle.
The save
, take
& settle
fields must be set according to the orders contained within the
bundle.
save
The save
amount determines the total in gas, exchange & referral fees to be committed to for later
collection. Exchange fees are computed by the pair's fee_in_e6
. Note that save
only includes the
amount to be distributed to nodes, LP fees are attributed within the bundle via pool updates.
take
The take
amount is the total in liquid tokens to be drawn in from Uniswap at the start of the
bundle. This serves to:
- Settle the total output from the swaps in the respective asset.
- Borrow an amount such that contract has sufficient liquid tokens to pay order outputs as orders are processed and settled 1-by-1.
settle
The settle
amount is the total in liquid tokens to be paid to Uniswap to repay borrows as well as
pay for the input side of pool swaps.
Example
Imagine a bundle with:
- AMM Swap A -> B, pool receives 300 A, angstrom receives 1200 B
- User order A -> B, user pays 1100 A, receives 4000 B (fee: 100 A)
- User order B -> A, user pays 2800 B, receives 650 A (fee: 50 A)
Asset list (assuming contract's A balance is already 1200):
- asset: A
save: 150
take: 0
settle: 300
- asset: B
save: 0
take: 2800
settle: 1600
Explanation:
For A: Extra fees are always charged in asset0
of the pair which is assigned to A's take
(50 + 100 =
150). The first order we process gives us all the A
liquidity we need so we don't need to take
anything. Due to the AMM Swap we owe Uniswap 300 A so we set settle
to 300.
For B: We need 4000 B to pay the first order but we already have 1200 in the contract so we only
need to borrow 2800. Due to the AMM swap we virtually receive 1200 B so we only owe Uniswap 1600
(2800 - 1200) requiring us to set settle
to 1600.
Pair list
For each pair the node needs to look up the store_index
for the (asset0, asset1)
pair as well as
determine a uniform clearing price (price_1over0
) for that pair. This should be the output of the
order matching algorithm.
Pool Updates
The pool updates contain information about swaps to perform against the underlying Uniswap pool and what rewards to distribute to that pool.
Note: It is a requirement that no one else, except for the Angstrom contract should be able to swap against the pools. This is to protect the LPs from outside searchers who may seek to extract the arbitrage value for themselves (with the exception of the post-bundle unlock that charges a higher fee).
Per pair it is expected that one swap will be executed based on the winning ToB order. The order specifies the total quantity that the bidder expects to pay and receive in return.
It also implies the swap & bid based on zero_for_one
:
if order.zero_for_one:
swap_input = pool.compute_input_for_exact_out(order.quantity_out)
bid_in_asset0 = order.quantity_in - swap_input
else:
swap_output = pool.compute_output_for_exact_in(order.quantity_in)
bid_in_asset0 = swap_output - order.quantity_out
assert bid_in_asset0 >= 0, f'Requesting more out than simple AMMs swap'
On top of the bid_in_asset0
any fees collected from normal user orders shall be distributed to
LPs.
The ticks that were used to complete the swap should be the ones to receive the reward, how and in
what proportions is to be specified elsewhere. The reward distribution is then specified via the
RewardsUpdate
.
User orders can also be matched against the pool's liquidity based on the post-ToB swap price. In
that case the total user order swap + ToB swap can be netted out into a single swap in the
PoolUpdate
.
If for some reason ticks on both sides of the final tick need to be rewarded two PoolUpdate
may be
added for a single pool. For the sake of gas the number of pool updates per pair is not enforced.
Orders
ToB Orders
Only 1 ToB order should be supplied per pair but this also is not checked as it would not give any additional guarantees.
Gas / Extra fee
The node should attribute each order's share of the gas cost via the gas_used_asset0
&
extra_fee_aset0
fields. Additionally extra_fee_asset0
may include referral fees for user orders.