iT邦幫忙

0

DeFi 應用實作:簡易的去中心化交易所 (DEX) 交易邏輯

  • 分享至 

  • xImage
  •  

昨天我們成功發行了標準的 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 協議的骨架。合約寫完之後,我們不能直接部署到主網上去盲測。


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言