跳至主要內容

公開測試版,運行在 Base Sepolia 測試網。 付款使用沒有實際價值的測試 USDC,請勿轉入真實資金。擔保合約尚未完成外部安全稽核,條款仍是待律師審閱的草稿。 測試版代表什麼

OpenVPT

2-of-3 多簽如何保護你的錢:OpenVPT 託管合約逐項拆解

買家、賣家、平台三把鑰匙,任兩方簽名才能放款。本文用白話解釋 EIP-712 簽名、合約檢查項目、每種簽名組合,以及平台能做與不能做的事。

作者
OpenVPT 團隊
發布於
閱讀
14 分鐘閱讀
標籤
  • 多簽
  • 託管
  • EIP-712
  • USDC
  • 智能合約
  • 資金安全
目錄

TL;DR 在 OpenVPT 下單付款後,你的 USDC 不會進入平台帳戶,而是鎖在 Base 鏈上的託管合約 VPTEscrow 裡。要把錢領出來,必須有「買家、賣家、平台」三方中任意兩個不同的人對同一份分配方案簽名。平台單獨一方永遠動不了這筆錢;合約擁有者可以暫停新訂單、更換平台簽名地址、管理可用代幣,但沒有任何函式能讓它結算或提款。代價是:如果沒有任何兩方願意簽名,資金會一直鎖在合約裡——下文會坦白說明這一點,以及我們的改進規劃。

先講結論:你的錢在哪裡?

很多交易平台的「擔保交易」,其實是把錢轉進平台自己的帳戶,由平台決定何時轉給賣家。這種模式下,你必須完全信任平台:信任它不挪用、不被駭、不倒閉。

OpenVPT 的做法不同。買家付款時,是自己的錢包直接呼叫託管合約的 fund(),把 USDC(6 位小數的美元穩定幣)轉進合約。從這一刻起:

  • 錢在合約裡,不在平台的錢包裡。
  • 合約只有一個出口:settle() 結算函式。
  • settle() 需要兩個不同身分的 EIP-712 簽名,缺一不可。

換句話說,OpenVPT 設計上是「對平台非託管」(non-custodial for the platform):平台沒有任何單方面移動資金的路徑。

三把鑰匙:誰是「三方」?

每一筆訂單在合約裡都記錄了三個角色的地址:

角色地址從哪裡來簽名代表什麼
買家呼叫 fund() 付款的那個錢包(必須是下單時指定、已用 SIWE 驗證的錢包,因為平台的 CreateOrder 簽名綁定了這個地址)「我同意這樣分配我付的錢」
賣家賣家在 OpenVPT 以 SIWE(Sign-In with Ethereum)驗證過的錢包「我同意這樣分配貨款」
平台合約裡設定的 platformSigner 地址「平台依規則(確認收貨、逾時、仲裁結果)認可這個分配」

這裡的「鑰匙」就是各自錢包的私鑰。買家與賣家的私鑰在你們自己手上,OpenVPT 看不到也拿不到;平台只持有自己那一把。

補充兩點背景:

  • 賣家門檻:在 OpenVPT 上架販售,需要完成 KYC(狀態為 VERIFIED),並用 SIWE 證明自己控制收款錢包。這確保合約裡的「賣家地址」確實屬於那位賣家。
  • 下單時就綁定:買家付款時,平台會用自己的鑰匙簽一份 CreateOrder,把訂單編號、買家、賣家、代幣、金額、手續費、到期時間全部綁在一起。合約會驗證這份簽名,所以沒有人能在付款時偷偷把賣家地址或手續費改掉。

EIP-712 是什麼?用白話說

你可能在錢包裡看過「簽名請求」:有的是一串看不懂的十六進位亂碼,有的則清楚列出欄位與數值。後者就是 EIP-712 型別化結構簽名(typed structured data signing)。

白話來說,EIP-712 讓你簽的不是「一段神秘資料」,而是一張有格式的單據。OpenVPT 的結算單據長這樣:

text
Settle(
  bytes32 orderId,     // 哪一筆訂單
  uint256 toSeller,    // 給賣家多少
  uint256 toBuyer,     // 退給買家多少
  uint256 toPlatform   // 平台手續費多少
)

此外,每張單據都帶著一個「網域」(domain):名稱 VPTEscrow、版本 1、鏈 ID(Base 主網為 8453)、以及合約地址。這有三個實際好處:

  1. 看得懂:支援 EIP-712 的錢包會把 toSeller、toBuyer、toPlatform 逐欄顯示給你看。
  2. 不能挪用:因為網域綁定了鏈與合約地址,這張簽名拿到別條鏈或別的合約上都無效。
  3. 不能竄改:金額只要差 1 個最小單位,簽名就對不上,合約會拒絕。

小提醒:USDC 有 6 位小數,所以合約裡的 1200000000 代表 1,200 USDC。錢包若顯示原始整數,請記得往左移 6 位再核對。

合約放款前,到底檢查了什麼?

以下是 VPTEscrow.settle() 實際執行的檢查,依順序列出:

  1. 訂單存在:這個 orderId 必須真的被付款過,否則回傳 OrderNotFound。
  2. 只能結算一次:訂單若已結算,直接拒絕(OrderAlreadySettled)。合約在轉帳之前就先把訂單標記為已結算,並有防重入保護。
  3. 金額加總必須剛好等於託管金額:toSeller + toBuyer + toPlatform == amount,多一分少一分都不行(AmountMismatch)。沒有「剩下的錢留在合約」這種情況,也沒有憑空多出來的錢。
  4. 平台手續費有下限,而且按比例計算:toPlatform 必須大於或等於 fee × toSeller ÷ amount(整數除法,無條件捨去)。意思是:賣家拿到多少比例,平台手續費最少就按那個比例收;全額退款時,手續費下限為 0。
  5. 兩個簽名都要有效:簽名無法解析就拒絕(InvalidSignature)。
  6. 簽名者必須是這筆訂單的三方之一:只接受該訂單的買家、賣家,或目前的 platformSigner,其他任何地址都會被拒絕(UnauthorizedSigner)。
  7. 兩個簽名者必須不同:同一個人簽兩次不算數(DuplicateSigner)。

通過全部檢查後,合約才會把錢分別轉給賣家、買家,以及平台的手續費收款地址。任何人都可以把兩份簽名送上鏈(實務上由平台代為送出並支付 gas),因為權限來自簽名本身,而不是送交易的人。

實際算一次:1,200 USDC 的訂單

假設商品售價 1,200 USDC,手續費率為預設的 5%(feeBps = 500):

  • 手續費 fee = 1,200 × 500 ÷ 10,000 = 60 USDC

OpenVPT 的分配公式(splitSettlement)是先算出賣家的「毛額」,再從毛額中按比例扣手續費:

  • 賣家毛額 = 金額 × 判給賣家的比例
  • 平台 = 手續費 × 賣家毛額 ÷ 金額(捨去)
  • 賣家實收 = 賣家毛額 − 平台
  • 買家退款 = 金額 − 賣家毛額
情境賣家實收買家退款平台手續費合約的手續費下限
正常完成(100% 給賣家)1,14006060 × 1,140 ÷ 1,200 = 57
全額退款(0% 給賣家)01,20000
仲裁判賣家 30%3428401860 × 342 ÷ 1,200 = 17.1

30% 的計算過程:賣家毛額 = 1,200 × 30% = 360;平台 = 60 × 360 ÷ 1,200 = 18;賣家實收 = 360 − 18 = 342;買家退款 = 1,200 − 360 = 840。三者加總 342 + 840 + 18 = 1,200,剛好等於託管金額。平台拿 18,高於合約要求的下限 17.1,所以能通過檢查。

重點是:平台手續費只跟著賣家實際拿到的部分走。全額退款時,平台一毛都不收。

每一種簽名組合,分別在什麼時候用?

三方取二,共有三種組合。以下是它們在 OpenVPT 流程中的實際用途:

簽名組合典型情境誰先簽結果
買家 + 平台買家按下「確認收貨」平台自動簽,買家在錢包簽放款給賣家(扣手續費)
買家 + 平台賣家超過交付期限未交付平台簽退款方案,買家簽名後送出全額退回買家
賣家 + 平台驗收期(預設交付後 3 天)屆滿,買家未確認也未提出爭議平台簽,賣家簽名後送出放款給賣家(扣手續費)
平台 + 買家或賣家爭議經仲裁裁決(例如 30/70)仲裁員裁決後平台簽,再由買家或賣家其中一方共同簽名依裁決比例分配
買家 + 賣家雙方直接對同一份方案達成共識雙方各自簽名依雙方簽署的方案分配,平台簽名不是必要條件

幾個細節值得說明:

  • 確認收貨:買家確認時,平台會自動簽上同一份放款方案,所以買家的那一個簽名就湊齊了 2-of-3,平台隨即代為送出交易。賣家此時不需要再簽。
  • 逾時退款與逾時放款:這兩種情況都由系統排程觸發,平台先簽,另一個簽名通常由「會拿到錢的那一方」補上——退款由買家簽、放款由賣家簽,因為拿錢的人最有動機完成簽名。技術上,買家或賣家任一方對同一份方案的有效簽名都能湊齊兩票。
  • 仲裁:買家在驗收期內可提出爭議,由指派的仲裁員審閱雙方證據,以「給賣家多少比例」的方式裁決。平台依裁決簽名,再由買家或賣家其中一方(通常是獲得款項的一方)共同簽署後送出。目前沒有上訴機制,裁決即為最終方案。
  • 平台只簽一次:因為 Settle 簽名本身沒有到期時間、也無法撤銷,OpenVPT 目前的政策是每筆訂單平台最多只簽一份結算方案。若之後有人要求平台再簽另一個不同的方案,系統會拒絕並留下稽核紀錄,改由人工處理。這避免了「兩份不同方案都帶有平台簽名」的風險。

平台能做什麼?不能做什麼?

VPTEscrow 合約有一個「擁有者」(owner),也就是營運方的管理地址。它的權限清單很短,而且全部寫在合約裡,任何人都可以在鏈上查證:

擁有者可以擁有者不可以
暫停與恢復新的 fund() 付款呼叫 settle() 替任何訂單結算
更換平台簽名地址 platformSigner(例如定期輪換金鑰)從合約提款或轉走任何託管資金
設定可用代幣白名單修改已付款訂單的買家、賣家、金額或手續費
更換手續費收款地址放棄擁有權(renounceOwnership 被刻意停用,避免暫停與金鑰輪換功能永久失效)

特別注意「暫停」只影響新的付款,settle() 並不受暫停影響。也就是說,即使平台暫停了合約,已經在託管中的訂單仍然可以依照兩方簽名正常結算。

擁有權的轉移採用兩步驟(Ownable2Step):新擁有者必須主動接受,降低因為打錯地址而失去管理權的風險。

坦白說:2-of-3 防不了什麼

多簽大幅降低風險,但不是萬能。以下是我們認為你應該知道的限制:

  • 兩方串通:2-of-3 的前提是三方中至少有兩方誠實。如果任意兩方聯手,他們就能簽出任何加總正確的方案。平台端以「只簽一次」、仲裁流程與稽核紀錄來降低這類風險,但合約本身無法判斷誰在說謊。
  • 你簽了什麼,就是什麼:簽名一旦送出便無法撤回。請務必在錢包畫面核對訂單編號與三個金額,不要在不明網站或聊天中別人丟來的連結上簽名。
  • 平台金鑰的安全:平台簽名金鑰若外洩,攻擊者等同取得「平台」這一票,但仍需要買家或賣家其中一方的簽名才能動用資金。擁有者也可以立即輪換 platformSigner。
  • 合約審計:上線前的第三方合約審計目前為計劃中,完成前請依自身風險承受度決定交易金額。

如果平台消失了,我的錢怎麼辦?

這是最常被問到的問題,我們直接回答。

在目前的設計下,託管中的資金會一直留在合約裡,直到有兩個不同的當事方對同一份方案簽名為止。

這代表:

  • 買家和賣家若能達成共識,他們可以不經過平台,自行對同一份 Settle 方案簽名,再由任何人把交易送上鏈。合約只看簽名,不在乎是誰送出的。不過,這需要一定的技術能力(自行產生 EIP-712 簽名、自行支付 gas),目前 OpenVPT 沒有提供「平台停止運作時」的專用介面。
  • 買家和賣家若談不攏,而平台又無法簽名,合約裡沒有「逾時後自動退款」或「單方提款」的機制,資金會保持鎖定。
  • 任何人(包括平台)都無法把錢挪作他用,因為沒有任何函式能繞過兩方簽名。

我們認為誠實說明比粉飾更重要。改善這個情境(例如為結算簽名加入期限、提供不依賴平台的退出路徑)已列入後續合約版本的規劃,屬計劃中,尚未實作。實作前,建議你把單筆交易控制在自己能承受的範圍。

付款環節的兩道保險

多簽保護的是「錢進了合約之後」。在「錢還沒進合約」的那一刻,也有一個容易被忽略的風險:你按下取消,但付款交易其實已經送出、還在排隊上鏈。OpenVPT 為此設計了兩道保險。

第一道:短效的 CreateOrder 簽名

每次付款都需要平台簽發的 CreateOrder 簽名,而它的到期時間是「付款期限(下單後 24 小時)」與「現在起 15 分鐘」兩者中較早的那一個。合約會拒絕已過期的簽名。付款頁面每次讀取訂單時都會重新簽發一份新的,所以正常操作不會被影響;但一張舊簽名最多只有 15 分鐘的有效期。

第二道:延後生效的取消

當你在付款前按下「取消」,訂單不會立刻變成已取消,而是進入「取消中」:

  1. 系統記錄取消請求的時間,從此不再簽發新的付款簽名。
  2. 等待至少 15 分鐘加上一段緩衝時間,讓你手上可能還有的舊簽名全部過期、且已送出的交易有時間上鏈。
  3. 最終取消前,系統會再檢查鏈上是否已有這筆訂單的付款紀錄。
  4. 若付款先一步完成,付款優先:訂單正常進入「已付款」,取消請求作廢。
  5. 萬一付款在取消之後才確認(安全網),系統會自動走「只能退款」的路徑:平台簽署全額退款方案,由你共同簽名後送出,錢原路退回,平台不收手續費。

交易前後的自我檢查清單

  • 付款前,確認錢包顯示的網路是 Base、代幣是 USDC、金額與訂單一致。
  • 付款前,確認你在 OpenVPT 官方網站的訂單頁操作,而不是聊天中別人給的連結。
  • 簽署 Settle 前,逐欄核對 orderId、toSeller、toBuyer、toPlatform(記得 6 位小數)。
  • 賣家要求你「先在站外付款」或「加通訊軟體私下交易」時,停止操作——站外付款不受合約保護,OpenVPT 聊天也會對分享聯絡方式的訊息提出提醒。
  • 收到商品後在驗收期內檢查;有問題就在期限內提出爭議,並保留證據。交付的檔案會記錄 SHA-256 雜湊值,有助於在爭議時確認實際交付的內容;授權碼則以加密方式儲存。
  • 只在確認沒問題後才按「確認收貨」,因為確認後即放款,無法撤回。

常見問題

平台可以凍結我的錢嗎? 平台可以暫停新的付款,但無法阻止已具備兩方有效簽名的結算;同時,平台也無法單方面把錢轉走。不過,如前所述,若沒有兩方簽名,資金會維持鎖定。

被停權的使用者怎麼辦? 停權不會取消或改變進行中的訂單,排程與仲裁照常運作。但若結算需要被停權者本人的簽名(例如退款給他),該筆結算會停在「結算中」,需由管理員個別處理。

為什麼不讓平台一個人就能退款給我,這樣不是更快? 因為「平台一個人就能動錢」正是我們想消除的風險。要求買家或賣家其中一方也對同一份方案簽名,可以確保沒有人能在你不知情的情況下改變去向。

免責聲明:本文僅說明 OpenVPT 託管合約的技術設計,不構成法律、稅務或投資建議。區塊鏈交易具有不可逆等風險,請依自身情況審慎評估。

下一步

延伸閱讀