閒聊自動化做市商(Automated Market Maker, AMM)與Uniswap V2 Pair Contract

James Shieh
技術保鮮盒
Published in
Dec 26, 2021

夜深人靜,翻著Uniswap V2 Whitepaper,想認識一下去中心化金融中最務實的一部分是如何設計的,畢竟這市場中投機的水分太高,幸運的是身為工程師,可以很實務地去分析這些東西,所謂的DeFi其實就是用程式去自動化金融服務,這概念很酷,我喜歡自動化繁瑣又重複的事情,只不過對於我這種碼農來說,自動化是降低時間成本來提升工作產能;對於矽谷與華爾街那些天才來說,自動化是權力的轉移,是財富再分配的機會,當然他們才不用自動化這種不sexy的詞呢,要改成去中心化(Decentralize)才夠fancy。無論如何,區塊鏈讓工程師有更多機會參與資本與金融的運作,相當有趣。

中心化交易所

在傳統的交易所中,例如買賣股票,會有一個做市商(Market Maker)的角色,負責鋪買賣單,讓市場中有合理價格的買賣單,以便提供流動性,讓買賣家更容易撮合交易。而像是幣安、ACE這類的加密貨幣交易所也是用類似的方法來做市。這種交易所就是所謂的中心化交易所。

去中心化交易所(Decentralized EXchange, DEX)

而近幾年開始發展起來的去中心化金融(Decentralized Finance, DeFi)主要方向便是藉由把金融服務自動化,進而實現去中心化治理。對於交易所而言,最關鍵的金融服務當然就是剛剛提到的做市(market marking),只要把這個部分自動化,就能實現所謂的去中心化交易所(DEX)。

自動做市商(Automated Market Maker, AMM)

做市怎麼自動化呢?沒有人居中定價要怎麼撮合買賣家?答案是我們可以用智能合約來處理代幣定價、買賣代幣、撮合交易等行為,這就是所謂的自動做市商(AMM),由於智能合約已經把這些操作服務都自動化了,所以自然可以去中心化治理。這就是著名的Uniswap的核心服務與價值。

恆定乘積公式(Constant Product Formula)

但智能合約如何知道什麼是合理的定價?ETH、BTC該賣多少錢合理?一種最簡單的方法就是用供需法則 — — 豬肉變貴時,大家更願意買雞肉;豬肉過剩時,豬肉就會貶值,反之亦然。所以資產x與資產y兩者間的相對價值可以用恆定乘積公式表示:

x * y = k

所以一個市場中,x與y的相對價值可以表示如下:

以下圖為例,因為k固定不變,若x變大,則y變小,反之亦然:

所以一個交易者想用x token來買y token時,只要知道他給了多少x token(也就是dx),用這個公式就可以算出可以買到多少y token(也就是dy):

如此一來,我們只要為各種市場(x & y, y & z, z & n…)設定好合理的k值,那定價可以完成用這個公式自動算出,不需要人為處理,自動做市最關鍵的服務就這樣輕鬆搞定了。

流動性池為基礎的去中心化交易所(Liquidity Pool Based DEX)

剛提到自動乘積公式表達的是兩種資產的相對價值,所以我們必須為各種代幣創造成對的市場,這個市場我們稱之為流動性池(Liquidity Pool),顧名思義,我們就是把兩種資產放在一個池子裡,提供流動性。而理論上任何人都可以創造這種代幣市場,成為所謂的流動性提供者(Liquidity Provider, LP),Uniswap也提供這樣的服務讓項目方或任何想當Liquidity Provider的人用指定的代幣建立各種市場,因為Uniswap V2 Pair Contract已經把這部分的代碼都標準化了。而為了讓大家願意當Liquidity Prodiver,任何交易者在池子中交易都要上繳0.3% 左右的手續費給Liquidity Provider作為獎勵,所以實際上公式為:

我們可以從ETH/DAI的UniswapV2Pair Contract中看到扣除0.3%手續費的程式碼:

uint balance0Adjusted = balance0.mul(1000).sub(amount0In.mul(3));
uint balance1Adjusted = balance1.mul(1000).sub(amount1In.mul(3));

所以像Uniswap、PancakeSwap、TraderJoe這種交易所基本上就是一種以流動性池為基礎的去中心化交易所(Liquidity Pool Based DEX)。

市場機制會讓資產價值維持在行情價

剛提到流動性提供者必須先投入兩種資產來建立流動性池,如果你是Liquidity Provider,你可以透過一開始投入x token與y token的數量來決定k值 — — 你在池子裡放了1顆ETH和100顆USDT,其他人就能用100美元買到一顆1ETH,當然我相信你不會這樣做。理性的Liquidity Provider會根據市價和自己想投入的資產來算出要個別放入多少x, y token。而一旦資金池中的x與y相對價值偏離行情太多,一定會有套利者居中交易,使得資金池中的資產價值能一直維持在行情價。

滑價(Slippage)

雖然自動乘積公式簡單而有效,但卻使得資金使用非常沒效率,在UniswapV2Pair Contract中,基本上池子中有95%的資金是沒被使用的,為什麼呢?

因為自動乘積公式會有滑價(Slippage) 的問題 — — 當y token不斷被交易者買入時,其價格會因為池子裡的y相對於x變少很多,所以價格迅速上漲。所以實際上交易者只願意在某個價格區間內購買資產,當池中的資產價格偏離行情太多,交易者會放棄交易或去其他地方購買y token。

當我們用一顆1ETH來買DAI時,能買到約4,052顆的DAI;當我們用4501顆ETH來買DAI時,卻只能換到18,144,500顆DAI,也就是每顆ETH只值4,031顆DAI,相對市價貶值了-0.52%。

而池子的深度會影響滑價的幅度,我們不妨來看看DAI/ETH與DAI/LINK兩個Pool:

  1. DAI/ETH UniswapV2Pair Contract Addresss: https://etherscan.io/address/0xa478c2975ab1ea89e8196811f51a7b7ade33eb11#readContract
  2. LINK/DAI UniswapV2Pair Contract Addresss: https://etherscan.io/address/0x6d4fd456edeca58cf53a8b586cd50754547dbdb2#readContract

截至2021/12/26日止DAI/ETH Pool中有9,949.65顆ETH與40,261,585.19顆DAI,其k值為400,588,717,232.50;DAI/LINK Pool中有3,354.94顆DAI與151.77顆LINK,其k值為509,171.39。

DAI/LINK Pool相較DAI/ETH Pool淺了許多。

當我們用1顆LINK換DAI時,可以換到約22.39顆得DAI;當我們用4501顆LINK換DAI時,卻只能換到99429.7顆DAI,一顆LINK只值22.09。相對買一顆的價值貶值了-1.39%

小節

實際上這種基於恆定乘積公式的自動做市商,仍有不少改進的空間,所以Uniswap V3做了一些優化,讓資金使用更有效率。如果你在以流動池為基礎的DEX中購買token,注意池子的深度和滑價是相當重要的。如果你想當流動性提供者來賺取手續費獎勵,也要注意太小的資金會讓你的池子過淺,影響交易者購買的意願。

不管是項目方或是對項目方代幣感興趣的投資人,如果有大筆的項目方代幣放在相對淺的池子裡,就表示這代幣的價值有容易被操作的風險。合理的根據代幣供應量建立相對應的流動性池,是相當重要的。

--

--

James Shieh
技術保鮮盒

Find something more important than you are and dedicate your life to it.