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 的結算單據長這樣:
Settle(
bytes32 orderId, // 哪一筆訂單
uint256 toSeller, // 給賣家多少
uint256 toBuyer, // 退給買家多少
uint256 toPlatform // 平台手續費多少
)此外,每張單據都帶著一個「網域」(domain):名稱 VPTEscrow、版本 1、鏈 ID(Base 主網為 8453)、以及合約地址。這有三個實際好處:
- 看得懂:支援 EIP-712 的錢包會把
toSeller、toBuyer、toPlatform逐欄顯示給你看。 - 不能挪用:因為網域綁定了鏈與合約地址,這張簽名拿到別條鏈或別的合約上都無效。
- 不能竄改:金額只要差 1 個最小單位,簽名就對不上,合約會拒絕。
小提醒:USDC 有 6 位小數,所以合約裡的
1200000000代表 1,200 USDC。錢包若顯示原始整數,請記得往左移 6 位再核對。
合約放款前,到底檢查了什麼?
以下是 VPTEscrow.settle() 實際執行的檢查,依順序列出:
- 訂單存在:這個
orderId必須真的被付款過,否則回傳OrderNotFound。 - 只能結算一次:訂單若已結算,直接拒絕(
OrderAlreadySettled)。合約在轉帳之前就先把訂單標記為已結算,並有防重入保護。 - 金額加總必須剛好等於託管金額:
toSeller + toBuyer + toPlatform == amount,多一分少一分都不行(AmountMismatch)。沒有「剩下的錢留在合約」這種情況,也沒有憑空多出來的錢。 - 平台手續費有下限,而且按比例計算:
toPlatform必須大於或等於fee × toSeller ÷ amount(整數除法,無條件捨去)。意思是:賣家拿到多少比例,平台手續費最少就按那個比例收;全額退款時,手續費下限為 0。 - 兩個簽名都要有效:簽名無法解析就拒絕(
InvalidSignature)。 - 簽名者必須是這筆訂單的三方之一:只接受該訂單的買家、賣家,或目前的
platformSigner,其他任何地址都會被拒絕(UnauthorizedSigner)。 - 兩個簽名者必須不同:同一個人簽兩次不算數(
DuplicateSigner)。
通過全部檢查後,合約才會把錢分別轉給賣家、買家,以及平台的手續費收款地址。任何人都可以把兩份簽名送上鏈(實務上由平台代為送出並支付 gas),因為權限來自簽名本身,而不是送交易的人。
實際算一次:1,200 USDC 的訂單
假設商品售價 1,200 USDC,手續費率為預設的 5%(feeBps = 500):
- 手續費
fee = 1,200 × 500 ÷ 10,000 = 60 USDC
OpenVPT 的分配公式(splitSettlement)是先算出賣家的「毛額」,再從毛額中按比例扣手續費:
- 賣家毛額 = 金額 × 判給賣家的比例
- 平台 = 手續費 × 賣家毛額 ÷ 金額(捨去)
- 賣家實收 = 賣家毛額 − 平台
- 買家退款 = 金額 − 賣家毛額
| 情境 | 賣家實收 | 買家退款 | 平台手續費 | 合約的手續費下限 |
|---|---|---|---|---|
| 正常完成(100% 給賣家) | 1,140 | 0 | 60 | 60 × 1,140 ÷ 1,200 = 57 |
| 全額退款(0% 給賣家) | 0 | 1,200 | 0 | 0 |
| 仲裁判賣家 30% | 342 | 840 | 18 | 60 × 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 分鐘的有效期。
第二道:延後生效的取消
當你在付款前按下「取消」,訂單不會立刻變成已取消,而是進入「取消中」:
- 系統記錄取消請求的時間,從此不再簽發新的付款簽名。
- 等待至少 15 分鐘加上一段緩衝時間,讓你手上可能還有的舊簽名全部過期、且已送出的交易有時間上鏈。
- 最終取消前,系統會再檢查鏈上是否已有這筆訂單的付款紀錄。
- 若付款先一步完成,付款優先:訂單正常進入「已付款」,取消請求作廢。
- 萬一付款在取消之後才確認(安全網),系統會自動走「只能退款」的路徑:平台簽署全額退款方案,由你共同簽名後送出,錢原路退回,平台不收手續費。
交易前後的自我檢查清單
- 付款前,確認錢包顯示的網路是 Base、代幣是 USDC、金額與訂單一致。
- 付款前,確認你在 OpenVPT 官方網站的訂單頁操作,而不是聊天中別人給的連結。
- 簽署
Settle前,逐欄核對orderId、toSeller、toBuyer、toPlatform(記得 6 位小數)。 - 賣家要求你「先在站外付款」或「加通訊軟體私下交易」時,停止操作——站外付款不受合約保護,OpenVPT 聊天也會對分享聯絡方式的訊息提出提醒。
- 收到商品後在驗收期內檢查;有問題就在期限內提出爭議,並保留證據。交付的檔案會記錄 SHA-256 雜湊值,有助於在爭議時確認實際交付的內容;授權碼則以加密方式儲存。
- 只在確認沒問題後才按「確認收貨」,因為確認後即放款,無法撤回。
常見問題
平台可以凍結我的錢嗎? 平台可以暫停新的付款,但無法阻止已具備兩方有效簽名的結算;同時,平台也無法單方面把錢轉走。不過,如前所述,若沒有兩方簽名,資金會維持鎖定。
被停權的使用者怎麼辦? 停權不會取消或改變進行中的訂單,排程與仲裁照常運作。但若結算需要被停權者本人的簽名(例如退款給他),該筆結算會停在「結算中」,需由管理員個別處理。
為什麼不讓平台一個人就能退款給我,這樣不是更快? 因為「平台一個人就能動錢」正是我們想消除的風險。要求買家或賣家其中一方也對同一份方案簽名,可以確保沒有人能在你不知情的情況下改變去向。
免責聲明:本文僅說明 OpenVPT 託管合約的技術設計,不構成法律、稅務或投資建議。區塊鏈交易具有不可逆等風險,請依自身情況審慎評估。
下一步
- 延伸閱讀:爭議與仲裁:OpenVPT 如何處理交易糾紛
- 延伸閱讀:為什麼 OpenVPT 用 USDC 在 Base 上結算
- 了解完整交易流程:運作方式
- 查看手續費說明:收費說明
- 開始瀏覽商品:商品列表
- 還有疑問?請看幫助中心或聯絡我們