banner
zach

zach

github
twitter
medium

從零開始UniswapV2 | Part-2 預言機

什麼是價格#

Uniswap 作為鏈上的去中心化交易所,承載著價值發現的功能,即用戶或其他鏈上合約可以通過 Uniswap 來獲取代幣的價格,Uniswap 在這其中承擔鏈上預言機的功能。

假設當前交易池中有 1 Ether 和 2000 USDC,那麼以太幣的價格就是 2000/1=2000 USDC,反之就是 USDC 的價格,因此價格就是一個比率,由於智能合約尚不支持小數,所以在 Uniswap 的代碼中拓展了新的數據類型來存儲價格,關於新的數據類型後面會專門做介紹。

TWAP 價格機制#

然而僅僅使用瞬時的代幣數目之比作為價格是不安全的,存在人為操縱價格預言機的風險,由於 Uniswap 提供了閃電貸功能,因此在某個閃電貸交易的瞬間,交易對內的代幣餘額會產生劇烈波動。在 UniswapV2 中為了解決這個問題,採用了 TWAP(Time Weighted Average Price)即時間加權的價格預言機機制。

具體工作原理如下:

  • 假設過去一天,資產在前 20 個小時的價格為 20$,最近 4 小時的價格為 10$,那麼 TWAP=($20*20+10$*4)/24 = 18.33$
  • 假設過去一天,資產在第一個小時的價格為 10$,最近 23 小時的價格為 15$,那麼 TWAP=($10*1+15$*23)/24 = 14.79$

總結下來,TWAP 的公式如下,這裡的 T 是時間段,P 是對應時間段的價格

在 UniswapV2 的合約中,只會記錄分子部分,即記錄每個時間段乘以單價的求和,而分母部分則需要使用方自行維護,交易對內有兩個代幣,所有有兩個值來記錄

通常我們只需關心某一時間區間內的代幣價格,這是 TWAP 公式的歷史價格公式:

假設我們的計價從 T4 開始,那麼實際的計價公式應該如下:

前面已經提到,在合約內有一個變量會追蹤分子的求和值,以 token0 的追蹤計價變量 price0Cumulativelast 為例:

這個變量是記錄了歷史以來所有時間段的求和,那麼我們只需要從 T4 開始的部分即可,計算方式也很簡單,在 T3 時間點我們獲取一個 price0Cumulativelast 變量的快照,在最新即 T6 時間點再獲取一次,兩次的差值即是 T4 - 最新時間段內 token0 的計價和

我們自己也維護了最近的窗口持續時間和,即:T4+T5+T6

那麼這段時間內的 TWAP 價格即可計算得出:(price0Cumulativelast-UpToTime3)/(T4+T5+T6)

UniswapV2 的實現#

具體到 Uniswap 的實現中,對於每個交易對都維護了兩個變量 price0Cumulativelast 和 price1Cumulativelast,在之前提到的_update 方法中進行求和,具體的代碼如下:

  • 首先獲取當前的區塊時間戳blockTimestamp
  • 通過與 blockTimestampLast 相減,計算出距離上次更新過去了多少時間timeElapsed
  • 只有在timeElapsed >0 時,即進入下一個區塊時,才會累加價格 * 時間段
  • 注意這裡的價格計算用到了UQ112x112 的特殊格式,了解它是為了記錄小數即可,後面會專門講解這裡的優化
  • 在處理完累加後,才會更新blockTimestampLast 到最新的區塊時間戳
function _update(uint balance0, uint balance1, uint112 _reserve0, uint112 _reserve1) private {
    ...
    uint32 blockTimestamp = uint32(block.timestamp % 2**32);
    uint32 timeElapsed = blockTimestamp - blockTimestampLast;
    if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {
      // * never overflows, and + overflow is desired
      price0CumulativeLast += uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * timeElapsed;
      price1CumulativeLast += uint(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * timeElapsed;
    }
    blockTimestampLast = blockTimestamp;
    ...
  }

TWAP 的潛在問題#

  • 基於時間加權的價格計算,會提高攻擊者的操縱成本,因為需要連續控制多個區塊,這樣的攻擊成本是很高的。
    當價格產生劇烈波動時,由於有時間作為加權因素,預言機的價格無法在較短時間內反映出價格的波動,反而提供出過時的價格,尤其是在市場發生劇烈動盪時,這樣的情況會導致 Uniswap 中的價格與外部市場產生較大的差異。

  • 使用 TWAP 預言機仍然依賴鏈下的定時觸發,存在維護成本與中心化問題。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。