SIP-264: Update Atomic Pricing


Simple Summary

This SIP proposes improvements to the atomic pricing methodology incorporating an in-block spot price (i.e. the live price).


Update the atomic price methodology as to incorporate the in-block live price into the computation of atomic price (specified in the specification below).


The current implementation of atomic swaps uses the spot price at the previous block. This exposes the debt pool to latency attacks, as the spot price at the previous block does not incorporate the latest updated information. Hence using the live spot helps reduce the latency considerably as shown in the scatter plot. The scatter plot shows the delta between centralized exchange prices and uniswap prices when considering same block price (orange) versus previous block pricing (blue). It is important to mention that the updated computation would use the worse between live price, price at the previous block, twap and chainlink.

Latency arbitrageurs can still push their transactions at the head of the block via flashbots or high gas prices, as to front-run a uniswap pool arbitrage and updated oracle pricing. The protocol would need to lean against this by increasing fees and incorporating slippage (using uniswapInputAmount). uniswapInputAmount is the amount used as an input to measure the price obtained by trading on uniswap.

It is also worth pointing out out that this does expose the protocol to the ability of arbitrageurs to manipulate the uniswap price as to sandwish users or take advantage of latency. Therefore the minReturn is necessary to protect users and fees need to be high enough as lean against such oracle manipulation, the damage however is constrained to the use of the worse price with previous block price, twap and chainlink.

The live price usage would add around 100k units of gas to the transaction per trade.


Technical Specification

Update to the atomic price methodology

Computation Methodology in Atomic Pricing Updated

Atomic exchanges leads to combinations that involve the usage of chainlink in certain situations and the usage of uniswap in others or a combination of the two sources of prices. This sip updates the computation laid out in SIP-258, incorporating a UniLive price which is the in-block price from uniswap.

  1. PureChainlink Vs Not Pure Chainlink:
  • When a pure chainlink price is assigned to a currency, the chainlink price is used.
  • Otherwise the worse price between chainlink and uniswap-spot and uniswap-twap is used in the combination. Worse price, means the price that would result in the lowest DEST_Amount.
  1. Naming Convention:
  • UniLive(SRC/USD) and UniLive(DEST/USD) refers to the price obtained from uniswap V3 spot in the current block, reflecting arbitrages on uniswap pool that had taken place within the same block. Few implementation details:

    a) As implemented in SIP-120, in case the 5 bp pool is specified, the implementation should determine the price of the synthEquivalent/wETH price by hoping over the wETH/synthEquivalent & wETH/USDC uniswap pools in case no native synthEquivalent/USDC exists. Therefore the implementation will need to hop over the wETH/USDC and wBTC/wETH pools in order to arrive at the price of wBTC on the 5 bp pool.

    b) In order to arrive at the live uniswap price quoteExactInput function could be utilized on chain, despite these function not being gas efficient. The live price is the rate obtained by converting a uniswapInputAmount worth of the inputCurrency into the outputCurrency. Hence, a user that swaps sUSD to sBTC, the live price (excluding fees) is the computed by outputAmount / [inputAmount * (1-uniswapFee)]

      - `inputAmount` is specified via sccp and allows us to incorporate a form slippage into the fill amount.
      - `uniswapFee` is dependent on the specified pool being used, we'll assume for the sake of simplification that uniswap admin fees will remain at zero.
  • UniSpot(SRC/USD) and UniSpot(DEST/USD) refers to the price obtained from uniswap V3 spot in the previous block.

  • UniTwap(SRC/USD) and UniTwap(DEST/USD) refers to the price obtained from uniswap V3 twap.

  • Chainlink(SRC/USD) and Chainlink(DEST/USD) refers to the price obtained from chainlink price feed

  1. Below are the different scenarios that could arise for trading currencies that have or don't have the Pure Chainlink tag:
  • SRC and DEST are both set to trade at the PureChainlinkPrice, in such a case, both Chainlink(SRC/USD) and Chainlink(DEST/USD) are used to compute SRC/DEST by dividing Chainlink(SRC/USD) by Chainlink(DEST/USD).
  • SRC is NOT set to PureChainlinkPrice and DEST is set to PureChainlinkPrice. Therefore, SRC/DEST is obtained by dividing min(UniSpot(SRC/USD),UniLive(SRC/USD),UniTwap(SRC/USD),Chainlink(SRC/USD)) by Chainlink(DEST/USD).
  • SRC is set to PureChainlinkPrice and DEST is NOT set to PureChainlinkPrice. Therefore, SRC/DEST is obtained by dividing Chainlink(SRC/USD) by max(Chainlink(DEST/USD),UniLive(DEST/USD),UniSpot(DEST/USD),UniTwap(DEST/USD)).
  • Both SRC and DEST are NOT set to PureChainlinkPrice, in such a case, SRC/DEST is obtained by dividing min(UniSpot(SRC/USD),UniLive(SRC/USD),UniTwap(SRC/USD),Chainlink(SRC/USD)) by max(Chainlink(DEST/USD),UniLive(DEST/USD),UniSpot(DEST/USD),UniTwap(DEST/USD)).

Test Cases

Configurable Values (Via SCCP)

The same configurable values as those set out in SIP-120, SIP-198 and SIP-258. uniswap.

uniswapInputAmount is an amount that should be specified per atomicEquivalent that allows for the calculation of the live uniswap price. In case uniswapInputAmount is not specified on the atomicEquivalent being traded, then the amount being traded is used to fetch the uniswap live price (i.e. using the same amount of slippage one would obtain by trading on uniswap).

Copyright and related rights waived via CC0.