昨天我們成功發行了標準的 ERC20 代幣。但代幣如果只能在朋友之間互轉,就無法形成真正的金融市場。在 Web3 的世界裡,要讓代幣具有流動性並能互相兌換,我們需要一個去中心化交易所(DEX)。
傳統交易所採用的是「訂單簿(Order Book)」模型,需要買家與賣家掛單搓合。然而,在以太坊上每一筆掛單與取消都要消耗高昂的 Gas 費,且物聯網設備頻繁呼叫合約的成本極大,訂單簿模型在此完全行不通。因此,DeFi 領域誕生了一個天才般的發明:自動做市商 (Automated Market Maker, AMM)。今天,我們將實作 AMM 最經典的核心邏輯。
恆定乘積公式 (Constant Product Formula)引領 DeFi 風騷的核心,就是一條極度簡潔的數學公式:
x x y = k
x 代表資金池中 Token 1 的數量。
y 代表資金池中 Token 2 的數量。
k 是一個常數(在交易發生的瞬間必須保持不變)。
交易運作邏輯:
假設池子裡有 100 顆代幣 A (x) 和 1000 顆代幣 B (y),k = 100000。
今天你想用 10 顆代幣 A 兌換代幣 B。當你把代幣 A 丟進池子後,池子的代幣 A 變成 110 顆 (x + ▵x)。
為了讓 k 依然保持 100000,池子裡的代幣 B 數量必須變成 100000 / 110 ≈ 909.09$ 顆 (y -▵y)。
因此,你可以拿走 1000 - 909.09 = 90.91 顆代幣 B。這就是 DEX 定價與交易的底層數學機制!
實戰:撰寫簡易版 DEX 智慧合約
我們延續 Foundry 的開發環境,建立一個 SimpleDEX.sol。為了聚焦在 AMM 邏輯,這裡省略了手續費機制與初始流動性提供的複雜細節。
'''
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
contract SimpleDEX {
IERC20 public token1;
IERC20 public token2;
uint256 public reserve1;
uint256 public reserve2;
constructor(address _token1, address _token2) {
token1 = IERC20(_token1);
token2 = IERC20(_token2);
}
// 核心交易函數:用 token1 兌換 token2
function swapToken1ForToken2(uint256 amountIn) public {
require(amountIn > 0, "Amount must be greater than 0");
// 1. 將用戶的 token1 轉入 DEX 合約 (用戶必須先對此 DEX 合約執行 approve)
token1.transferFrom(msg.sender, address(this), amountIn);
// 2. 計算恆定乘積 x * y = k
// 推導公式:(reserve1 + amountIn) * (reserve2 - amountOut) = reserve1 * reserve2
// 解出 amountOut = (amountIn * reserve2) / (reserve1 + amountIn)
uint256 amountOut = (amountIn * reserve2) / (reserve1 + amountIn);
require(amountOut > 0, "Insufficient output amount");
// 3. 更新合約內的儲備量紀錄
reserve1 += amountIn;
reserve2 -= amountOut;
// 4. 將 token2 轉給用戶
token2.transfer(msg.sender, amountOut);
}
}
'''
潛藏的資安危機 (駭客視角)
這段程式碼雖然完美展現了 AMM 的數學邏輯,但從資安稽核的角度來看,它充滿了實務上的破綻:
滑點保護缺失 (Slippage):如果交易執行前,有另一個駭客使用機器人搶先交易 (Front-running) 改變了 reserve1 與 reserve2 的比例,用戶拿到的 amountOut 可能會遠低於預期。實務上必須加入 minAmountOut 參數來保護用戶。
狀態更新與外部呼叫的順序:在程式碼中,我們在第 3 步先更新了內部變數,才在第 4 步呼叫外部合約 token2.transfer。這個順序非常關鍵!如果順序反過來(先轉帳再更新紀錄),就會引發我們後續將探討的毀滅性漏洞——重入攻擊 (Reentrancy Attack)。
今天我們實作了 Web3 應用層最重要的基礎設施——去中心化交易所。雖然程式碼極度精簡,但它已經具備了真實 DeFi 協議的骨架。合約寫完之後,我們不能直接部署到主網上去盲測。