跳轉至

SeraSOR.sol

智慧訂單路由器可實現多段原子兌換。使用者簽署單一 Intent,執行者將其路由至多筆訂單撮合。

主網: 0xa7A0cf7cd6f043fCA23f29d8ae5aae6b46e11c18 原始碼: src/SeraSOR.sol

常數

uint256 public constant MAX_ROUTE_LEGS = 20;

資料結構

IntentParams

struct IntentParams {
    address inputToken;            // Initial wallet funding token
    address outputToken;           // Final output token
    uint256 maxInputAmount;        // Max total spend across all legs
    uint256 minOutputAmount;       // Min total output
    address recipient;             // Final output recipient
    uint256 initialDepositAmount;  // Amount to pull from wallet
    uint256 uuid;                  // Replay protection
    uint48 deadline;               // Signature deadline
}

函式

executeIntent

根據 Taker 簽署的 Intent 執行多段原子路由。

function executeIntent(
    MatchData[] calldata matches,
    bytes calldata intentSignature,
    IntentParams calldata intent,
    uint8 uniqueTokenCount,
    uint256 permitDeadline,
    bytes calldata permitSignature
) external
參數 類型 說明
matches MatchData[] 訂單撮合對陣列(每段路由一對)
intentSignature bytes Taker 的 EIP-712 Intent 簽名
intent IntentParams 已簽署的路由參數
uniqueTokenCount uint8 瞬態餘額追蹤的最佳化提示
permitDeadline uint256 ERC-2612 permit 截止時間(不使用 permit 時為 0)
permitSignature bytes ERC-2612 permit 簽名(不使用 permit 時為空)

流程:

  1. 驗證 Intent 簽名並檢查 UUID 是否已使用
  2. 從 Taker 錢包提取 initialDepositAmount(可選用 permit)
  3. 對每一段路由:
    • 透過 Sera.settleRoutedLeg() 將 Taker 訂單與 Maker 訂單撮合
    • 將中間輸出保存在瞬態餘額中
  4. 驗證封套約束:
    • 總輸入 ≤ maxInputAmount
    • 總輸出 ≥ minOutputAmount
    • 所有中間餘額已消耗(無殘餘)

範例路由:GBP → SGD 透過 USD

Leg 1: GBP → USD (taker sells GBP, receives USD)
Leg 2: USD → SGD (taker sells USD, receives SGD)

USD 在段與段之間以瞬態方式持有,永遠不會進入 Taker 的 Vault。

要求:

  • ≥1 且 ≤20 段路由
  • 截止時間未過期
  • UUID 未曾使用
  • 所有段路由屬於同一 Taker
  • 最後一段路由交付至已簽署的收件人
  • 所有瞬態餘額完全消耗

事件:

event IntentMatched(bytes32 indexed intentHash, address indexed taker, uint256 legCount);
event IntentLegMatched(bytes32 indexed intentHash, uint256 indexed legIndex, bytes32 takerOrderHash, bytes32 makerOrderHash);

EIP-712 類型雜湊

bytes32 constant INTENT_TYPEHASH = keccak256(
    "Intent(address inputToken,address outputToken,uint256 maxInputAmount,uint256 minOutputAmount,address recipient,uint256 initialDepositAmount,uint256 uuid,uint48 deadline)"
);

狀態變數

mapping(address => mapping(uint256 => bool)) public isIntentUuidUsed;

錯誤

錯誤 原因
EmptyRoute 未提供路由段
TooManyLegs 超過 20 段路由
InvalidRoute 路由驗證失敗(代幣不匹配、收件人錯誤等)
TransientBalanceNotZero 中間代幣未完全消耗
InsufficientOutput 最終輸出低於 minOutputAmount
ExcessiveInput 總輸入超過 maxInputAmount

重放保護集中在 Sera 中:executeIntent 呼叫 sera.consumeIntentUuid(taker, uuid),若 UUID 已被消費,將以 UuidAlreadyUsed 回滾。