Limitless CTF Exchange 智能合約分析:基於 Polymarket 的 Safe 4337 擴展架構

Limitless CTF Exchange 智能合約分析:基於 Polymarket 的 Safe 4337 擴展架構


生成提示詞

請深入分析 Limitless Labs CTF Exchange 智能合約:
1. Clone limitless-ctf-exchange 源代碼
2. 與 Polymarket CTF Exchange 進行差異比較
3. 分析 Safe 4337 賬戶抽象整合方式
4. 研究雙工廠架構(Proxy + Safe)設計
5. 解析自定義 SignatureType 擴展
6. 繪製 Mermaid 對比圖說明架構差異
7. 以繁體中文撰寫工程級深度文章

執行摘要

Limitless Labs CTF Exchange 是基於 Polymarket CTF Exchange 的分叉版本,新增了重要的 Safe 4337 賬戶抽象支援。本文將深入分析其與原版的差異:

  • Safe 4337 整合:原生支援 ERC-4337 賬戶抽象錢包
  • 雙工廠架構:同時管理 Polymarket Proxy 和 Limitless Safe
  • 三種簽名類型:EOA、POLY_PROXY、LIMITLESS_SAFE
  • CREATE2 地址推導:確定性錢包地址計算
  • 域名分離:獨立的 EIP712 簽名域

目錄

  1. Limitless vs Polymarket 架構對比
  2. 簽名類型擴展
  3. Safe 4337 整合
  4. 雙工廠架構設計
  5. 關鍵差異總結

1. Limitless vs Polymarket 架構對比

1.1 整體架構差異

flowchart TB
    subgraph Limitless["Limitless CTF Exchange"]
        LCTF[CTFExchange]
        LSig[Signatures Mixin]
        LFactory[PolyFactoryHelper]

        LSigTypes["簽名類型"]
        LEOA[EOA]
        LProxy[POLY_PROXY]
        LSafe[LIMITLESS_SAFE]

        LLibs["地址推導庫"]
        LPolyProxy[PolyProxyLib]
        LPolySafe[PolySafeLib]
        LSafeLib[SafeLib ⭐新增]

        LCTF --> LSig
        LSig --> LSigTypes
        LSigTypes --> LEOA
        LSigTypes --> LProxy
        LSigTypes --> LSafe

        LSig --> LFactory
        LFactory --> LLibs
        LLibs --> LPolyProxy
        LLibs --> LPolySafe
        LLibs --> LSafeLib
    end

    subgraph Polymarket["Polymarket CTF Exchange"]
        PCTF[CTFExchange]
        PSig[Signatures Mixin]

        PSigTypes["簽名類型"]
        PEOA[EOA]
        PProxy[POLY_PROXY]
        PGnosis[POLY_GNOSIS_SAFE]
        P1271[POLY_1271]

        PLibs["地址推導庫"]
        PPolyProxy[PolyProxyLib]
        PPolySafe[PolySafeLib]

        PCTF --> PSig
        PSig --> PSigTypes
        PSigTypes --> PEOA
        PSigTypes --> PProxy
        PSigTypes --> PGnosis
        PSigTypes --> P1271

        PSig --> PLibs
        PLibs --> PPolyProxy
        PLibs --> PPolySafe
    end

1.2 關鍵差異表

特性PolymarketLimitless影響
EIP712 域名Polymarket CTF ExchangeLimitless CTF Exchange訂單不可跨平台使用
簽名類型4 種 (EOA, POLY_PROXY, POLY_GNOSIS_SAFE, POLY_1271)3 種 (EOA, POLY_PROXY, LIMITLESS_SAFE)不同錢包支援策略
Safe 實作Gnosis Safe (標準)Safe 4337 (賬戶抽象)支援 Gas 代付
工廠數量2 個 (Proxy + Safe)2 個 (Proxy + Safe)相同架構
Safe 地址傳入 implementation硬編碼地址不同部署模式

1.3 主合約對比

Polymarket CTFExchange.sol:

contract CTFExchange is
    BaseExchange,
    Auth,
    Assets,
    Fees,
    Pausable,
    AssetOperations,
    Hashing("Polymarket CTF Exchange", "1"),  // 原版域名
    NonceManager,
    Registry,
    Signatures,
    Trading
{ }

Limitless CTFExchange.sol:

contract CTFExchange is
    BaseExchange,
    Auth,
    Assets,
    Fees,
    Pausable,
    AssetOperations,
    Hashing("Limitless CTF Exchange", "1"),   // ⭐ 修改域名
    NonceManager,
    Registry,
    Signatures,
    Trading
{ }

2. 簽名類型擴展

2.1 SignatureType 枚舉變更

Polymarket 版本:

enum SignatureType {
    EOA,               // 普通外部帳戶
    POLY_PROXY,        // Polymarket Proxy 錢包
    POLY_GNOSIS_SAFE,  // Gnosis Safe 多簽
    POLY_1271          // EIP1271 合約錢包
}

Limitless 版本:

enum SignatureType {
    EOA,               // 普通外部帳戶
    POLY_PROXY,        // Polymarket Proxy 錢包(保持兼容)
    LIMITLESS_SAFE     // ⭐ 新增:Limitless Safe 4337
}

2.2 簽名驗證實作

Limitless Signatures.sol:

function isValidSignature(
    address signer,
    address associated,
    bytes32 structHash,
    bytes memory signature,
    SignatureType signatureType
) internal view returns (bool) {
    if (signatureType == SignatureType.EOA) {
        return verifyEOASignature(signer, associated, structHash, signature);
    }
    else if (signatureType == SignatureType.LIMITLESS_SAFE) {
        // ⭐ 新增的 Safe 4337 驗證
        return verifySafeSignature(signer, associated, structHash, signature);
    }
    else {
        // POLY_PROXY - 保持與 Polymarket 兼容
        return verifyPolyProxySignature(signer, associated, structHash, signature);
    }
}

/// @notice Safe 4337 簽名驗證
function verifySafeSignature(
    address signer,
    address safeAddress,
    bytes32 hash,
    bytes memory signature
) internal view returns (bool) {
    // 1. 驗證 ECDSA 簽名
    // 2. 驗證計算出的 Safe 地址匹配
    return verifyECDSASignature(signer, hash, signature) &&
           getSafeAddress(signer) == safeAddress;
}

2.3 為何移除 POLY_1271?

Limitless 移除了 POLY_1271 類型,原因可能是:

  1. Safe 4337 涵蓋用例:賬戶抽象錢包已支援合約簽名
  2. 簡化驗證邏輯:減少攻擊面
  3. 專注核心場景:EOA、Proxy、Safe 覆蓋大部分用戶

3. Safe 4337 整合

3.1 SafeLib 核心實作

檔案路徑: src/exchange/libraries/SafeLib.sol

Limitless 新增了專門的 Safe 4337 地址推導庫:

library SafeLib {
    // ⭐ 硬編碼的 Safe 4337 合約地址
    address public constant addModuleLibAddress =
        0x8EcD4ec46D4D2a6B64fE960B3D64e8B94B2234eb;

    address public constant safe4337ModuleAddress =
        0xa581c4A4DB7175302464fF3C06380BC3270b4037;

    address public constant safeProxyFactoryAddress =
        0x4e1DCf7AD4e460CfD30791CCC4F9c8a4f820ec67;

    address public constant safeSingletonAddress =
        0x41675C099F32341bf84BFc5382aF534df5C7461a;

    address public constant multiSendAddress =
        0x38869bf66a61cF6bDB996A6aE40D5853Fd43B526;

    address internal constant ZERO_ADDRESS = address(0);
}

3.2 CREATE2 地址推導

/// @notice 計算用戶的 Safe 4337 錢包地址
function getSafeAddress(address signer, address deployer)
    internal
    pure
    returns (address safe)
{
    uint256 saltNonce = 0;

    // 計算 Proxy 合約的 bytecode hash
    bytes32 bytecodeHash = keccak256(
        getContractBytecode(safeSingletonAddress)
    );

    // 獲取初始化代碼
    bytes memory initializer = _getInitializerCode(
        signer,
        ZERO_ADDRESS,  // 無額外 token 授權
        ZERO_ADDRESS
    );

    // 計算 salt
    bytes32 salt = keccak256(
        abi.encodePacked(keccak256(initializer), saltNonce)
    );

    // CREATE2 地址計算
    safe = _computeCreate2Address(deployer, bytecodeHash, salt);
}

3.3 Safe 初始化代碼

/// @notice 生成 Safe 初始化調用數據
function _getInitializerCode(
    address owner,
    address token,       // 可選的 token 授權
    address spender      // 可選的授權接收者
) internal pure returns (bytes memory) {
    // 設定 owners 和閾值
    address[] memory owners = new address[](1);
    owners[0] = owner;

    // 多交易設置:啟用 4337 模組
    bytes memory multiSendData = _getMultiSendData(owner, token, spender);

    return abi.encodeWithSelector(
        ISafe.setup.selector,
        owners,                    // _owners
        1,                         // _threshold
        multiSendAddress,          // to (MultiSend)
        multiSendData,             // data (啟用模組)
        safe4337ModuleAddress,     // fallbackHandler
        ZERO_ADDRESS,              // paymentToken
        0,                         // payment
        ZERO_ADDRESS               // paymentReceiver
    );
}

3.4 4337 模組啟用

/// @notice 構建多交易數據以啟用 4337 模組
function _getMultiSendData(
    address owner,
    address token,
    address spender
) internal pure returns (bytes memory) {
    bytes memory transactions;

    // 交易 1: 啟用 4337 模組
    bytes memory enableModuleData = abi.encodeWithSelector(
        ISafe.enableModule.selector,
        safe4337ModuleAddress
    );

    transactions = abi.encodePacked(
        uint8(0),              // operation (Call)
        addModuleLibAddress,   // to
        uint256(0),            // value
        uint256(enableModuleData.length),
        enableModuleData
    );

    // 可選交易 2: Token 授權
    if (token != ZERO_ADDRESS && spender != ZERO_ADDRESS) {
        bytes memory approveData = abi.encodeWithSelector(
            IERC20.approve.selector,
            spender,
            type(uint256).max
        );

        transactions = abi.encodePacked(
            transactions,
            uint8(0),
            token,
            uint256(0),
            uint256(approveData.length),
            approveData
        );
    }

    return abi.encodeWithSelector(
        IMultiSend.multiSend.selector,
        transactions
    );
}

3.5 Safe 4337 vs Gnosis Safe 對比

flowchart TB
    subgraph Safe4337["Safe 4337 (Limitless)"]
        S4User[用戶]
        S4Bundler[Bundler]
        S4EntryPoint[EntryPoint]
        S4Module[4337 Module]
        S4Safe[Safe 合約]
        S4Exchange[CTFExchange]

        S4User -->|簽署 UserOp| S4Bundler
        S4Bundler -->|提交| S4EntryPoint
        S4EntryPoint -->|驗證| S4Module
        S4Module -->|執行| S4Safe
        S4Safe -->|交易| S4Exchange
    end

    subgraph GnosisSafe["Gnosis Safe (Polymarket)"]
        GSUser[用戶]
        GSRelayer[Relayer]
        GSSafe[Safe 合約]
        GSExchange[CTFExchange]

        GSUser -->|簽署交易| GSRelayer
        GSRelayer -->|執行| GSSafe
        GSSafe -->|交易| GSExchange
    end

Safe 4337 優勢:

  • 標準化的 Gas 代付機制
  • 更好的跨鏈兼容性
  • 內建的批量交易支援

4. 雙工廠架構設計

4.1 PolyFactoryHelper

檔案路徑: src/exchange/mixins/PolyFactoryHelper.sol

Limitless 維護兩套工廠基礎設施:

abstract contract PolyFactoryHelper {
    // Polymarket Proxy 工廠
    address public proxyFactory;

    // Limitless Safe 工廠
    address public safeFactory;

    /// @notice 獲取用戶的 Polymarket Proxy 錢包地址
    function getPolyProxyWalletAddress(address _addr)
        public view returns (address)
    {
        return PolyProxyLib.getProxyWalletAddress(
            _addr,
            getPolyProxyFactoryImplementation(),
            proxyFactory
        );
    }

    /// @notice 獲取用戶的 Safe 4337 錢包地址
    function getSafeAddress(address _addr)
        public view returns (address)
    {
        return SafeLib.getSafeAddress(_addr, safeFactory);
    }

    /// @notice 管理員設置 Proxy 工廠
    function setProxyFactory(address _proxyFactory) external onlyAdmin {
        proxyFactory = _proxyFactory;
        emit ProxyFactorySet(_proxyFactory);
    }

    /// @notice 管理員設置 Safe 工廠
    function setSafeFactory(address _safeFactory) external onlyAdmin {
        safeFactory = _safeFactory;
        emit SafeFactorySet(_safeFactory);
    }
}

4.2 地址推導庫對比

flowchart LR
    subgraph PolyProxyLib["PolyProxyLib"]
        PP1[輸入: signer, implementation, deployer]
        PP2[Salt: keccak256(signer)]
        PP3[Bytecode: Proxy 合約]
        PP4[CREATE2 計算]
        PP1 --> PP2 --> PP4
        PP1 --> PP3 --> PP4
    end

    subgraph PolySafeLib["PolySafeLib (Polymarket)"]
        PS1[輸入: signer, implementation, deployer]
        PS2[Salt: keccak256(encode(signer))]
        PS3[Bytecode: 傳入 implementation]
        PS4[CREATE2 計算]
        PS1 --> PS2 --> PS4
        PS1 --> PS3 --> PS4
    end

    subgraph SafeLib["SafeLib (Limitless)"]
        SL1[輸入: signer, deployer]
        SL2[Salt: keccak256(initializer, nonce)]
        SL3[Bytecode: 硬編碼 singleton]
        SL4[CREATE2 計算]
        SL1 --> SL2 --> SL4
        SL3 --> SL4
    end

4.3 關鍵差異

PolySafeLib (Polymarket):

function getSafeAddress(
    address signer,
    address implementation,  // ⭐ 傳入 implementation
    address deployer
) internal pure returns (address safe) {
    bytes32 bytecodeHash = keccak256(
        getContractBytecode(implementation)
    );
    bytes32 salt = keccak256(abi.encode(signer));
    safe = _computeCreate2Address(deployer, bytecodeHash, salt);
}

SafeLib (Limitless):

function getSafeAddress(
    address signer,
    address deployer
) internal pure returns (address safe) {
    // ⭐ 使用硬編碼 singleton
    bytes32 bytecodeHash = keccak256(
        getContractBytecode(safeSingletonAddress)
    );

    // ⭐ 使用 initializer + nonce 作為 salt
    bytes memory initializer = _getInitializerCode(signer, ...);
    bytes32 salt = keccak256(
        abi.encodePacked(keccak256(initializer), saltNonce)
    );

    safe = _computeCreate2Address(deployer, bytecodeHash, salt);
}

設計權衡:

  • Polymarket: 靈活(可更換 implementation)
  • Limitless: 簡單(固定使用 Safe 4337)

5. 關鍵差異總結

5.1 功能對比表

功能PolymarketLimitless說明
域名Polymarket CTF ExchangeLimitless CTF Exchange訂單不互通
EOA 簽名✅✅相同實作
Proxy 錢包✅✅保持兼容
Gnosis Safe✅❌移除
Safe 4337❌✅新增
EIP1271✅❌移除
Gas 代付依賴 Relayer原生支援更好的 UX

5.2 用戶體驗影響

flowchart TB
    subgraph Polymarket["Polymarket 用戶流程"]
        PU1[創建錢包]
        PU2[存入 Gas]
        PU3[簽署訂單]
        PU4[等待 Relayer]
        PU5[訂單執行]

        PU1 --> PU2 --> PU3 --> PU4 --> PU5
    end

    subgraph Limitless["Limitless 用戶流程 (Safe 4337)"]
        LU1[創建 Safe]
        LU2[簽署 UserOp]
        LU3[Bundler 代付 Gas]
        LU4[訂單執行]

        LU1 --> LU2 --> LU3 --> LU4
    end

Limitless 優勢:

  • 無需預存 Gas(Bundler 代付)
  • 更好的隱私保護(UserOp 批處理)
  • 標準化的賬戶抽象介面

5.3 技術決策權衡

決策Polymarket 方案Limitless 方案權衡分析
Safe 版本Gnosis Safe 1.xSafe 4337新版本需更多測試
地址推導動態 implementation硬編碼簡單但較不靈活
簽名類型4 種3 種更聚焦但較少選擇
兼容性廣泛支援專注 4337未來導向

5.4 源碼文件對比

Polymarket                      Limitless
─────────────────────────────────────────────────────
libraries/
├── PolyProxyLib.sol           ├── PolyProxyLib.sol     (相同)
├── PolySafeLib.sol            ├── PolySafeLib.sol      (相同)
│                              └── SafeLib.sol ⭐        (新增)
└── CalculatorHelper.sol       └── CalculatorHelper.sol (相同)

mixins/
├── Signatures.sol             ├── Signatures.sol       (修改)
│   └── 4種簽名類型             │   └── 3種簽名類型
│                              ├── PolyFactoryHelper.sol (修改)
│                              │   └── 新增 safeFactory
└── ...                        └── ...                  (相同)

5.5 訂單結構對比

兩者使用相同的 Order 結構,但 SignatureType 枚舉不同:

// 相同的訂單結構
struct Order {
    uint256 salt;
    address maker;
    address signer;
    address taker;
    uint256 tokenId;
    uint256 makerAmount;
    uint256 takerAmount;
    uint256 expiration;
    uint256 nonce;
    uint256 feeRateBps;
    Side side;
    SignatureType signatureType;  // ⭐ 枚舉值不同
    bytes signature;
}

重要:由於 SignatureType 枚舉不同,訂單無法在兩個平台間通用。


總結

Limitless Labs 的創新

  1. Safe 4337 原生整合

    • 首個整合 ERC-4337 的預測市場
    • 支援 Bundler 代付 Gas
    • 更好的用戶體驗
  2. 簡化的簽名類型

    • 聚焦三種核心類型
    • 移除 EIP1271 複雜性
    • 更清晰的驗證邏輯
  3. 硬編碼 Safe 地址

    • 簡化部署流程
    • 確保一致的地址推導
    • 犧牲靈活性換取簡單性

適用場景

場景推薦平台
傳統 EOA 用戶兩者皆可
需要多簽Polymarket (Gnosis Safe)
需要 Gas 代付Limitless (Safe 4337)
合約錢包 (EIP1271)Polymarket
未來賬戶抽象生態Limitless

關鍵文件路徑

Limitless 新增/修改:
├── src/exchange/libraries/SafeLib.sol          # Safe 4337 地址推導
├── src/exchange/mixins/Signatures.sol          # 3種簽名類型
├── src/exchange/mixins/PolyFactoryHelper.sol   # 雙工廠管理
└── src/exchange/CTFExchange.sol                # 域名修改

保持不變:
├── src/exchange/mixins/Trading.sol             # 核心交易邏輯
├── src/exchange/libraries/CalculatorHelper.sol # 費用計算
└── src/exchange/libraries/PolyProxyLib.sol     # Proxy 地址推導

Limitless Labs CTF Exchange 展示了如何在保持 Polymarket 核心架構的同時,整合 ERC-4337 賬戶抽象標準,為預測市場帶來更好的用戶體驗。