一台會自己定價的販賣機
在傳統交易所——股市,或中心化的加密貨幣交易所——價格來自訂單簿:一份買方與賣方的清單,唯有當願意買的人在同一價格遇上願意賣的人,交易才成立。當簿子裡掛單夠厚時,這套機制運作得很漂亮;但在區塊鏈上它既慢又貴,而一個流動性不足的市場根本沒有對手方可以成交。
自動造市商(AMM)把訂單簿整個丟掉。取而代之的是:任何人都可以把一對資產存入一個共享的流動性池——比方說 ETH 與 USDC 一起待在同一份智慧合約裡——再由一條固定的公式決定價格。沒有人在報價,也沒有對手方在等候:資金池本身就是對手方,而且它永遠會跟你成交。這個單一構想,正是 Uniswap 與大多數 DeFi 底下的引擎。
恆定乘積:x · y = k
把資金池的兩項儲備分別記為 x(ETH 的數量)與 y(USDC 的數量)。恆定乘積公式就只是這條規則:每一筆交易,都必須讓它們的乘積維持不變。
x * y = k // k is a constant the pool must preserve Reserves before: x = 10 ETH, y = 20,000 USDC k = 10 * 20,000 = 200,000 Spot price of ETH = y / x = 20,000 / 10 = 2,000 USDC per ETH
從幾何上看,x·y=k 是一條雙曲線:儲備永遠必須落在這條平滑曲線上。要把 ETH 取出資金池,你就得把 USDC 放入,沿著曲線滑到一個乘積仍等於 k 的新位置。曲線的形狀直接帶來兩個結論。第一,即時價格——也就是無限小一筆交易的成交價——恰好等於比值 y/x,這裡是每顆 ETH 2,000 USDC。第二,這條曲線無限逼近卻永遠碰不到座標軸,所以儲備永遠歸不了零:資金池無法被完全抽乾,因為最後一顆 ETH 的價格會貴到無窮大。
實算一筆兌換:從 10 ETH / 20,000 USDC 的池子裡買 1 ETH
一位交易者想要剛好買到 1 ETH。他付出 USDC,資金池給出 ETH。公式唯一要回答的問題是:要付多少 USDC? 我們透過要求「兌換後 k 不變」來解出答案。
- 交易前:x = 10 ETH、y = 20,000 USDC,所以 k = 200,000。即時價格為 y/x = 2,000 USDC/ETH。
- 交易者取走 1 ETH,因此 ETH 儲備必須降為 x' = 10 − 1 = 9 ETH。
- k 必須維持 200,000,所以新的 USDC 儲備為 y' = k / x' = 200,000 / 9 = 22,222.22 USDC。
- 交易者必須存入的 USDC 為 Δy = y' − y = 22,222.22 − 20,000 = 2,222.22 USDC。
- 實際成交價=以 2,222.22 USDC 換得 1 ETH——比一開始的 2,000 即時價格高出約 11.11%。
值得把通則寫下來,因為每一筆 Uniswap v2 式的兌換都只是它的特例。當儲備為 x、y 時,若要付出代幣 Y 來買進數量 b 的代幣 X,你應付的投入量是 `a = y·b / (x − b)`。驗算一下:y·1/(10−1) = 20,000/9 = 2,222.22。交易後資金池握有 9 ETH 與 22,222.22 USDC,而新的即時價格為 22,222.22/9 ≈ 2,469 USDC/ETH——從這個池子取出的下一顆 ETH,會比這一顆更貴。
價格衝擊:曲線為何會懲罰大額交易
價格衝擊是「你看到的即時價格」與「你這筆交易實際支付的有效價格」之間的落差——它完全來自你的交易把儲備沿著曲線推移所致。買 1 ETH 把價格從 2,000 推到有效的 2,222.22,價格衝擊為 (2,222.22 − 2,000)/2,000 = 11.11%。雙曲線最關鍵的性質是:這個衝擊以超線性方式增長——把交易量加倍,傷害遠不只加倍。
Same pool: x = 10 ETH, y = 20,000 USDC, k = 200,000 General rule: pay a = y*b / (x - b) to buy b ETH Buy 1 ETH: a = 20,000*1 / (10-1) = 2,222.22 USDC -> eff. 2,222/ETH -> impact 11.1% Buy 2 ETH: a = 20,000*2 / (10-2) = 5,000.00 USDC -> eff. 2,500/ETH -> impact 25.0% Buy 5 ETH: a = 20,000*5 / (10-5) = 20,000.0 USDC -> eff. 4,000/ETH -> impact 100.0% Buy 9 ETH: a = 20,000*9 / (10-9) = 180,000 USDC -> eff. 20,000/ETH -> impact 900.0%
這不是缺陷,而是 AMM 的防禦。讓你為大額交易付出更多的那份曲率,正是保護資金池不被以舊價格掏空的力量,也正是讓池內價格隨供需變動而移動的機制。實務上的教訓是:相對於池子規模而言,AMM 對小額交易極為友善,對大額交易則十分殘酷。更深的資金池(更大的 k)會在局部把曲線壓平,使同一筆交易的價格衝擊變小——這正是各協定爭奪流動性的原因。
手續費安插在哪裡
目前為止的計算都沒有手續費,這正是 k 能維持恰好不變的原因。現實中,Uniswap v2 的資金池會對投入端收取 0.30% 的兌換手續費,而這正是當初存入 ETH 與 USDC 的人賺取報酬的方式。合約會在套用公式之前,先從你的投入金額中扣下手續費:你送出的金額只有 99.7% 被用來沿曲線移動;另外的 0.3% 留在池子裡,作為給流動性提供者的獎勵。
// Uniswap v2 core: exact-output quote, fee = 0.30% (997/1000)
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut)
internal pure returns (uint amountIn)
{
uint numerator = reserveIn * amountOut * 1000;
uint denominator = (reserveOut - amountOut) * 997;
amountIn = (numerator / denominator) + 1; // +1 rounds in the pool's favour
}
// Buy 1 ETH: reserveIn = 20,000 USDC, reserveOut = 10 ETH, amountOut = 1 ETH
// numerator = 20,000 * 1 * 1000 = 20,000,000
// denominator = (10 - 1) * 997 = 8,973
// amountIn = 20,000,000 / 8,973 + 1 ~= 2,229.91 USDC由於手續費那一部分是留在池子裡而非被取走,每一筆交易都會讓 k 極輕微地往上增加。流動性提供者不會另外收到一筆派發——而是他們持有份額的那個池子緩慢長大,提領時份額更值錢。這份穩定的累積就是把資金停泊於此的報酬;而停泊的資金最後可能比單純持有那兩種資產還更不值錢的風險,叫做無常損失,正是下一篇的主題。
滑價對上價格衝擊:兩個不同的數字
人們常把價格衝擊與滑價混為一談,但兩者其實不同。價格衝擊是確定性的:在當前儲備下,你這筆交易對價格的影響在簽署前就能精確算出。滑價則是額外的意外,來自資金池在你簽署的那一刻與交易實際執行的那一刻之間發生變化——因為別人的交易會排在你前面被打包進區塊,挪動了你原本用來報價的那組儲備。
這正是為什麼每個兌換介面都會詢問你的滑價容忍度(常見為 0.5%)。你的錢包會把它編碼成一個可接受的最低產出量——Uniswap 稱為 `amountOutMin`——只要執行價格比那條底線還差,合約就會把整筆交易回滾。屆時你會為這次失敗付出 gas,但不會收到糟糕的成交。容忍度設得太緊,繁忙時你的交易會不斷被回滾;設得太鬆,則是在邀請三明治攻擊:機器人搶在你前面買進(把你的價格推高),讓你的交易以更差的價格成交,再緊接著賣出——把你留在容忍度裡的那點空間榨走。
x·y=k 換來什麼,又付出什麼代價
恆定乘積 AMM 是簡潔的勝利。僅憑一條方程式,你就得到永遠在線的流動性(資金池從不拒絕交易)、無需許可的造市(任何人都能存入並賺取手續費,不必執照),以及一個完全在鏈上、不需要可信報價者的價格。相較於鏈上訂單簿,它在 gas 上便宜得多,也不需要有人不斷地掛單與撤單。
代價同樣真實,而誠實面對這些代價正是本階的重點。曲線會對較大的交易給出更差的價格,所以大額兌換需要很深的資金池,否則就得拆單。AMM 沒有獨立的價格發現能力——它只知道自己的儲備,因此每當它的價格偏離更廣的市場,就得仰賴套利者把它交易回正軌,而每一次這樣的修正都是由流動性提供者買單(這正是無常損失的種子)。再者,把一個池子的資金攤在整條價格曲線上是資本效率低落的:大部分資金停在可能永遠不會成交的價位。接下來的幾篇正是要對付這些缺口——先是無常損失,再來是修補效率問題的 Uniswap v3 集中流動性,然後是借貸市場,以及這一切所招來的 MEV。