Skip to main content

APWine AMM

Earlier versions of APWine (Alpha and Beta) featured an order-book based exchange for trading FYTs. While it can prove efficient on off-chain solutions, it is not viable for Ethereum L1. As such, the APWine team has been working on a custom AMM design for the V1 release, that embraces all specifities and unique aspects of the protocol.

Overview#

As explained in the previous sections, the APWine protocol is orchestrated using two tokens. Principal Tokens (PTs) that represent the deposited tokens by a user in the protocol and Future Yield Tokens (FYTs) that represent the generated yield over a specific period. Users can redeem one underlying asset per PT at the end of a period, while burning FYT at the end of the period allows one to redeem the yield generated during the period. Both these tokens will be traded during the duration of the period. PTs and FYTs are both discounted by the same discount rate.

This discount rate is priced by the market and corresponds to the expected APY for the remaining time of the ongoing period.

APWine developed an AMM solution that allows users to trade PTs and FYTs against underlying assets, while reducing their exposure to IL.

Requirements#

PTs and FYTs have their price that increase with time deterministically with the yield generated. They should therefore be less discounted as we move toward the end of the period and yield is progressively generated.

A classic AMM solution working with constant product formula would lead to impermanent losses for the liquidity provider as asset price changes would be induced by swaps. We therefore developed an AMM solution that reduces the arbitrage opportunities that would arise deterministically without any swap by the very nature of the PT and FYT assets.

APWine AMM architecture#

The APWine AMM is composed of two pools for each future that behave like Balancer V1 pools:

  • A PT/Underlying pool with dynamic weights.
  • A PT/FYT pool with constant 50/50 weighs.

Underlying/PT Pool#

This pool is a modified Balancer pool with dynamic weight adjustment. At initialization the weights are 50/50 and adjust to reflect price changes of the principal tokens implied by the generated yield at each block. This mechanism is implied by the nature of the PT asset. The price of the PT at any time during the period reflects the discounted price of the underlying asset. The market price reflects therefore the market discount rate or in other terms the expected APY for the remaining of the period.

If no trade happens, the price of the PT asset should increase taking into account the generated yield at each block. In other words as we get closer to the maturation of the assets (the end of the future period) there should be less discount.

We implemented this scaling mechanism in the _updateWeightsFromYieldAtBlock method. It is called before every liquidity movement within the pool.

PT/FYT Pool#

This second pool allows users to trade FYTs against PTs. The pool is a normal Balancer V1 like pool with constant 50/50 weights. The ratio between the two assets should follow the ratio between the yield generated and the underlying assets. They are both discounted by the same rate induced by the first pool.

Math behind APWine's AMM#

APWine swap and liquidity provisioning methods are based on Balancer V1 maths. The main difference being the behavior of the PT/Underlying pool that acts as the pool that prices the discount rate.

Formal definitions#

tt: The current time of the period. 0t<T0 \leq t <T. tt is abstracted but represents discrete block times.

TT: Period duration

BPTB_{PT} : Balance of principal tokens in the pool

BUB_{U} : Balance of underlying tokens in the pool

Pt(PT)P_t(PT) : Price of a principal token at a time t of the ongoing period. This price is relative to the underlying asset (ex: 1 PT = 0.66 underlying).

PT(PT)=1P_T(PT) = 1 : Price of a principal token at the end of the ongoing period. The PT should be equal to 1 underlying at the end of the period. You should be able to buy 1 PT for 1 underlying (the amount of underlying you need to lock to mint 1 PT).

FVt(A)FV_{t'}(A) The future value of an asset A from the current time tt until time tt'

rtDr^D_t: The discount rate until the end of the period that the market implicitly sets by trading PT and Underlying tokens in the pool

YtY_t: The yield generated by one underlying deposited in the protocol from the beginning (t=0t=0) until time tt of the period.

yty_t: The yield generated at time tt

VtU=1+Yt+ytV^U_t = 1 + Y_t + y_t the value of the system at the previous block time. The value of the underlying asset plus the generated yield so far during the period YtY_t and the new generated yield at current block time yty_t.

Weight scaling function#

The spot price of the principal token Pt(PT)P_t(PT), reflects the discounted price of the underlying asset at current market estimations of the APY during the remaining time of the period. As the PT assets represent one underlying locked in the protocol, we have to take into account the compounding realized until tt.

Pt(PT)=11+rtD    1+rtD=1Pt(PT)P_t(PT) = \frac{1}{1+r^D_t} \implies 1+r^D_t = \frac{1}{P_t(PT)}

We already have a realized yield of YtY_t per underlying deposited in the protocol. We can therefore compute the future value of the underlying asset plus the yield generated so far:

FVT(Vt1U)=(1+rtD)(1+Yt)FV_T(V^U_{t-1}) = (1+r^D_t) \cdot (1+Y_t)

We then compute the ratio of the currently generated value over the future value of the system induced by the current market discount rate. This determines the new price of the PTPT under current market estimations.

Pt+1(PT)=VtUFVT(Vt1U)P_{t+1}(PT) = \frac{V^U_t}{FV_T(V^U_{t-1})}

As this mechanism is only to prevent IL for LPs, we only scale the PTPT price if the new price is higher than the former price and if it is inferior to one. If that ever becomes the case, it means that the market made wrong estimations and there are some arbitrage opportunities.