前言

Hi 大家好,我是梅森。今天我想記錄之前我怎麼把一起跨鏈橋盜案,從原始碼一路查到原因的過程。

先從一組對比說起。2026 年 5 月 18 日,一筆跨鏈轉帳在 Verus 網路上送出,成本是大約 10 美元等值的 VRSC 手續費,其來源端鎖定的金額趨近於零。數分鐘後,以太坊側的橋接合約依照這筆訊息的指示,支付了大約 1158 萬美元。

這個過程中沒有任何一個元件失效。沒有重入攻擊,沒有私鑰外洩,沒有簽章繞過,也沒有雜湊碰撞。Verus 的公證人依規簽署,以太坊的合約依規驗證,兩側都正確運作,資產卻仍然流失。

本文要回答的問題是,當每一個環節都正確運作,缺口究竟落在哪裡。我會完整記錄定位這個缺口的過程,包含中途的受阻與轉向,以及我在撰稿階段發現自己報告中有一處事實錯誤的經過。

我最後重建出來的攻擊流程,步驟 4 就是缺陷被觸發的那一刻
我最後重建出來的攻擊流程,步驟 4 就是缺陷被觸發的那一刻

一筆完全合法的交易

先把事件輪廓講清楚。

2026 年 5 月 18 日,長期以信任最小化為訴求的 Verus 與以太坊跨鏈橋遭到攻擊。以太坊側的準備金被抽走大約 1158 萬美元,組成是這樣:

  • 103.6 顆 tBTC v2
  • 1625 顆 ETH
  • 大約 147,659 枚 USDC

這些資產隨即在 DEX 上被換成大約 5402.4 顆 ETH,集中到單一錢包。Verus 官方 Discord 把事件時間記為 5 月 18 日 23:55 UTC,Blockaid 則稱偵測到的時間約為 00:54 GMT,兩者存在報導差異,我在這裡照實列出,不去替他們選一個。

攻擊手法的骨架是這樣。攻擊者在 Verus 側構造了一筆跨鏈轉帳訊息。這筆訊息的結構完整,Merkle 證明有效,雜湊全部正確。所以 Verus 的公證人(15 位中的 8 位)依照規則簽署了狀態根。到這裡為止,Verus 完全沒有做錯任何事,因為這筆訊息確實是一筆結構合法的訊息。

接著攻擊者把這份合法簽署但經濟上不對等的證明,提交給以太坊側的橋接合約。合約驗證了簽名有效,來源身分正確,目的身分正確,然後照著訊息內容把錢付了出去。以太坊側也沒有做錯任何事,因為這份證明確實是被合法簽署的。

問題出在,沒有任何一方負責檢查輸入的價值是否等於輸出的價值

Etherscan 把我擋在門外

我一開始的想法很直覺,就是先把鏈上狀態拉出來看。攻擊者地址跟橋接合約餘額還有逐筆交易,這些應該都是最硬的證據。

結果我卡住了。

我的調查環境沒有區塊鏈 RPC 也沒有瀏覽器 API,Etherscan 直接回我 403,Blockscout 也拉不動。後來我想改用 GitHub API 去交叉比對 commit,未授權的請求又被限流擋下。等於是我最想要的那類證據,一個都拿不到。

這時候有兩條路。一條是乾脆全部引用 PeckShield 跟 Blockaid 這些機構的報導,把報告寫完。另一條是承認鏈上這條路走不通,改找一個我真的能自己驗的東西。

我選了第二條。理由很簡單,如果整份報告的每一句話都是轉述別人講的,那它就只是一篇整理稿,沒有任何我自己的證據價值。我想要至少有一塊是我親手驗出來的。

於是我把問題換了個方向問自己:這個橋是開源的,那為什麼不直接去看它的程式碼?

改用原始碼當第一手證據

Verus 的以太坊合約全部公開在 GitHub 上。既然鏈上狀態拿不到,那原始碼跟版本控制紀錄,就是我能拿到的第一手證據。

git clone https://github.com/VerusCoin/Verus-Ethereum-Contracts
cd Verus-Ethereum-Contracts
ls contracts/

這個決定後來證明是整份報告最關鍵的轉折。因為漏洞本體就在程式碼裡,它不需要鏈上狀態就能被證明。我要回答的問題其實只有一個,就是這個橋在收到一筆跨鏈訊息的時候,到底檢查了什麼。

從這裡開始,我在報告裡嚴格區分兩種證據:

  • A 級,自驗:我親自下載的官方開源合約跟 Git 版本紀錄還有 GitHub release 頁。這些我逐行看過。
  • B 級,第三方:PeckShield 跟 Blockaid 還有 ExVul 與多家媒體所報的金額,地址,逐筆交易。這些我當時沒有辦法在鏈上獨立重驗

這個分級我在文章裡也會一路標下去,因為我覺得誠實揭露自己驗不到什麼,跟秀出自己驗到什麼一樣重要。

Verus-Ethereum-Contracts 的程式碼庫首頁,多數檔案最後提交都在 3 年前
Verus-Ethereum-Contracts 的程式碼庫首頁,多數檔案最後提交都在 3 年前

一路 grep 到 checkCCEValues

拿到程式碼之後,我要找的是匯入的把關點。攻擊者送進來一筆訊息,總得有個函式決定要不要接受它。

先找入口。攻擊面向外的那一層是 contracts/Main/Delegator.solsubmitImports(),它用 delegatecall 把工作轉給 SubmitImports._createImports()

function submitImports(VerusObjects.CReserveTransferImport calldata data) external {

bool success;
bytes memory returnedData;
bytes memory packedData = abi.encode(data);

address SubmitImportsAddress = contracts[uint(VerusConstants.ContractType.SubmitImports)];
(success, returnedData) = SubmitImportsAddress.delegatecall(
abi.encodeWithSignature("_createImports(bytes)", packedData));
require(success);
...
}

再往下追,_createImports 會去呼叫 checkCCEValues。整條呼叫鏈長這樣:

submitImports() → delegatecall → SubmitImports._createImports() → checkCCEValues()
我用 sed 把攻擊呼叫鏈從 Delegator.sol 一路追到 _createImports
我用 sed 把攻擊呼叫鏈從 Delegator.sol 一路追到 _createImports

checkCCEValuescontracts/MMR/VerusProof.sol,從第 200 行開始。這就是整個橋在匯入時最後的把關點。我把它整段讀完,然後找到了關鍵的那六行。

checkCCEValues 函式的起點,位於 VerusProof.sol 第 200 行
checkCCEValues 函式的起點,位於 VerusProof.sol 第 200 行

關鍵在第 258 到 263 行:

if (!(hashedTransfers == hashReserveTransfers &&
systemSourceID == VERUS &&
destSystemID == VETH)) {

revert("CCE information does not checkout");
}

我盯著這段看了很久,因為它比我預期的還要短。這個橋在決定要不要付出上千萬美元之前,只確認了三件事:

  • hashedTransfers == hashReserveTransfers,轉帳雜湊相符,代表結構是真的
  • systemSourceID == VERUS,來源身分是 Verus
  • destSystemID == VETH,目的身分是 vETH

三項全部通過,函式就放行。

這就是最終把關的六行,三項條件裡沒有任何一項碰到金額
這就是最終把關的六行,三項條件裡沒有任何一項碰到金額

我第一個反應是,會不會 VERUS 跟 VETH 其實是某種帶有金額語意的東西?所以我又回頭去確認它們到底是什麼。

address immutable VETH;
address immutable BRIDGE;
address immutable VERUS;

它們是建構子設定的 immutable 系統識別碼,就是身分而已。

VETH 跟 BRIDGE 還有 VERUS 都是建構子設定的 immutable 系統 ID
VETH 跟 BRIDGE 還有 VERUS 都是建構子設定的 immutable 系統 ID

所以結論很清楚,而且是我自己從原始碼讀出來的(A 級):這三項全部是身分與結構的比對,沒有任何一行算術去驗證來源鎖定的價值是否等於目的支付的價值。

在終端機裡把 VerusProof.sol 的 256 到 267 行拉出來看,結論一樣
在終端機裡把 VerusProof.sol 的 256 到 267 行拉出來看,結論一樣

totalamounts:宣告了金額,卻沒有人比對它

看到這裡我還是有點不敢相信。一個跨鏈橋不可能連來源總額都沒有帶過來吧?

於是我去翻 CCE 這個結構。CCE 全名是 CrossChainExport,是價值跨鏈時的封裝物件。我在 VerusObjects.sol 第 112 行找到了它:

CCurrencyValueMap[] totalamounts;

totalamounts 就是來源端宣告的總額。欄位是存在的。所以問題變成,這個欄位到底有沒有被拿去比對?

我直接全庫搜。

grep -rn 'totalamounts' contracts

結果讓我確定缺口是真的。totalamounts 只出現在這幾類地方:

  • 序列化路徑,也就是 VerusSerializer.sol,用來湊出雜湊
  • 匯出端建構 CCE 的時候,也就是 VerusCrossChainExport.sol
  • 結構宣告本身,還有一堆編譯產物的 artifacts

完全沒有出現在匯入路徑的任何一個 require 或 if 裡面

全庫 grep totalamounts,只出現在匯出與序列化路徑,匯入端從未比對
全庫 grep totalamounts,只出現在匯出與序列化路徑,匯入端從未比對

換句話說,這個橋知道來源宣告了多少錢,這個數字一路被序列化,被算進雜湊,被公證人簽名背書。然後在以太坊這一側,它被完整地收下來,然後完全不拿去跟實際要付出去的金額比對

價值守恆這個跨鏈橋最核心的不變量,從來沒有在以太坊側被強制執行過。

這個缺口從 2024 年就躺在那裡

確認缺口存在之後,我馬上想知道兩件事:這是不是最近才寫壞的?以及,攻擊之後補了沒有?

Git 版本紀錄可以同時回答這兩題。

git log -1 --format='%h | %ci | %s' -- contracts/MMR/VerusProof.sol
# c60d685 | 2024-03-18 23:00:12 +0000 | Added Hardening + test

git branch -r
# origin/HEAD -> origin/main
# origin/main

兩個發現,都是 A 級:

第一,checkCCEValues 所在的 VerusProof.sol,最後一次修改是 2024 年 3 月 18 日,提交訊息是 c60d685 Added Hardening + test。也就是說,這不是什麼新引進的 bug,它已經在那裡躺了超過兩年。

第二,遠端只有 main 一支,沒有任何修補分支。我 clone 當下 main 的最新提交是 d633dc4,日期 2026 年 2 月 26 日,也就是攻擊發生之前。公開的 main 到我調查的當下,完全沒有攻擊後的修補。

git log 顯示 VerusProof.sol 最後修改於 2024-03,且遠端沒有修補分支
git log 顯示 VerusProof.sol 最後修改於 2024-03,且遠端沒有修補分支
GitHub 上的提交歷史,最後一筆 Added Hardening + test 停在 2024-03-18
GitHub 上的提交歷史,最後一筆 Added Hardening + test 停在 2024-03-18

一個能直接掏空準備金的缺口,在公開程式碼裡躺了兩年多,而且被打穿之後公開分支還是沒動。這是我整份調查裡最讓我坐立難安的一段。

缺口不在任何一邊,而在兩邊之間

把前面幾段接起來,我想講的核心洞察其實只有一句話。

這不是某個函式寫錯了,而是橋接信任模型的接縫。

Verus 那一側的職責是:這則訊息是不是真的?結構完不完整?雜湊對不對?Merkle 證明有沒有效?只要這些都對,公證人就簽。Verus 從頭到尾沒有承諾過這筆轉帳在經濟上是平衡的,它承諾的只有一件事,就是這則訊息是真的。

以太坊這一側的職責是:這則訊息是不是被合法簽署的?來源身分對不對?目的身分對不對?只要這些都對,合約就付。以太坊從頭到尾也沒有承諾過要檢查經濟平衡,它信任的是被背書過的訊息。

於是就出現了這個荒謬的局面:

  • Verus 背書訊息為真
  • 以太坊信任被背書的訊息
  • 但是沒有任何人背書訊息在經濟上是平衡的

攻擊者鑽的就是這條沒有人負責的接縫。他構造出一筆輸入趨近於零,輸出上千萬的不對等交易,而這筆交易在兩邊的驗證標準下,都是合法的

這也是為什麼我認為這個漏洞的隱蔽性極高。你去稽核 Verus 那一側,會發現簽章邏輯正確。你去稽核以太坊這一側,會發現驗證邏輯正確。只有當你把兩邊擺在一起,去問誰負責確保輸入等於輸出的時候,才會發現答案是沒有人。

Blockaid 跟 PeckShield 還有 ExVul 三家機構都把這個案子歸類為與 Wormhole(2022)跟 Nomad(2022)同一類的來源與目的經濟價值綁定缺口(B 級,我引用他們的分類)。Blockaid 另外判斷,這個缺口大約十行 Solidity 就能補起來(B 級)。

十行程式碼,1158 萬美元。

我用 release 頁修正了媒體的說法

調查到一半,我看到好幾家媒體都寫,Verus 在攻擊前兩天才剛發布緊急更新,修補了另一個漏洞。這個說法如果成立,敘事會很戲劇性。

但我覺得這種東西應該可以直接查。Verus 的 release 頁是公開的,我就自己去翻。

翻完之後我發現媒體的說法對不上,而且真正的事實比那個說法更有意思:

v1.2.14-2(2026 年 2 月 5 日) 的版本說明裡,Verus 自己承認了一件事。原文寫的是 the first Ethereum bridge event we’ve seen in recent memory,也就是說 2 月就已經發生過第一起以太坊橋接事件,他們做了 24 小時的軟分叉緊急封閉。

v1.2.14-2 的版本說明,Verus 自承 2 月已經發生過橋接事件
v1.2.14-2 的版本說明,Verus 自承 2 月已經發生過橋接事件

v1.2.15(2026 年 2 月 27 日) 又是一次以太坊合約升級,官方說明寫著要修補由 AI 與人工稽核所發現的額外問題。

也就是說,Verus 在 2026 年初已經有橋接事故的前科,而且密集做過稽核跟兩次合約升級。checkCCEValues 的金額綁定缺口,還是活著撐到 5 月被打穿。

這才是我覺得真正該講的重點。不是攻擊前兩天有個緊急更新,而是這個系統在同一個風險層面上已經被打過一次,補過兩輪,卻始終沒補到這一刀。

v1.2.16-1 是 Bitcoin Core 的 CVE 修補,跟這次的橋接事件無關
v1.2.16-1 是 Bitcoin Core 的 CVE 修補,跟這次的橋接事件無關

錢去哪了

這一段我要先講清楚,以下的地址跟交易在我當初的報告裡全部是 B 級,因為 Etherscan 擋掉了我的存取,我沒辦法自己在鏈上重驗。我是引用 PeckShield 跟 Blockaid 還有媒體的報導。

資金流的骨架是這樣:

  • 攻擊前大約 14 小時,攻擊者的 EOA 0x5aBb…D5777 從 Tornado Cash 收到 1 顆 ETH 當作 gas,來源被混淆
  • 攻擊者透過 submitImports() 掏空橋接準備金
  • 資產在 DEX 換成大約 5402.4 顆 ETH,集中到 0x65Cb…C25F9
  • 5 月 21 日,Verus 在 X 上公開和解條款,社群同意以 25% 作為白帽賞金
  • 攻擊者歸還 4052.4 顆 ETH(75%)到團隊地址 0xF9AB…C1A74
  • 數分鐘後,把剩下的 1350 顆 ETH(25%)轉進新錢包
  • 5 月 22 日,PeckShield 確認歸還
我當初從報導重建的鏈上資金流向,最後依和解條款做 75% 與 25% 分流
我當初從報導重建的鏈上資金流向,最後依和解條款做 75% 與 25% 分流

這個案子罕見地走向和解回收。直接損失 1158 萬美元,回收大約 850 萬,淨損大約 280 萬。Verus 團隊聲明沒有創投支持,將以去中心化治理承擔殘餘損失。

寫這篇的時候,我重新查了一次

這篇文章是在報告完成大約一週後動筆的。既然要公開發表,我決定把當初被擋掉的部分重新查一次。結果有三個發現,其中一個是我自己報告寫錯了

鏈上數字這次驗到了,而且對得上

這次 Etherscan 可以正常存取,所以我把當初的 B 級資料一筆一筆重新對過:

歸還交易 0xb428dae6… 確認存在,狀態 Success,區塊 25145811,時間 2026 年 5 月 21 日 07:47:11 UTC。轉出方是 0x65Cb8b128Bf6e690761044CCECA422bb239C25F9,Etherscan 直接標記成 Verus Exploiter 2。收款方是 0xF9AB28cB7b72B518e6a351FbdaBe69362cBC1A74,標記為 Verus: Recovery。金額 4052 顆 ETH。

歸還交易在 Etherscan 上的紀錄,Etherscan 自己標記了 Verus Exploiter 2 與 Verus: Recovery
歸還交易在 Etherscan 上的紀錄,Etherscan 自己標記了 Verus Exploiter 2 與 Verus: Recovery

賞金交易 0x84aada67… 也確認存在,區塊 25145825,時間 07:49:59 UTC,金額 1350 顆 ETH。它距離歸還交易只差 2 分 48 秒,印證了報導所說的數分鐘後。

我還補到一個當初報告沒寫到的細節。除了那筆 4052 顆 ETH,同一個錢包另外還送了一筆 0.4 顆 ETH 給 Verus: Recovery。兩筆加起來剛好是 4052.4 顆,正好對上報導的數字。而 4052.4 加上 1350 等於 5402.4,跟集中金額完全吻合,比例是 75.01% 與 24.99%。

另外 Etherscan 顯示那個攻擊者錢包的資金來源就是 Verus: Ethereum Bridge,也就是掏空本身,而且頁面上掛著 Blockaid 的示警橫幅。

攻擊者錢包的 Etherscan 頁面,掛著 Blockaid 的示警橫幅
攻擊者錢包的 Etherscan 頁面,掛著 Blockaid 的示警橫幅

我把橋接合約的位址寫錯了

這一項是我自己的錯,我想誠實寫出來。

我在報告裡把主網橋接合約寫成 0x0200EbbD26467B866120D84A0d37c82CdE0acAEB,說它是 Delegator,位址取自 migrations/setup.js

這次我拿這個位址去 Etherscan 查,發現它沒有任何一筆交易,餘額是 0。這不合理,一個被掏空上千萬美元的橋接合約不可能沒有交易。所以我直接用 RPC 去問這個位址有沒有合約程式碼:

curl -s -X POST https://ethereum-rpc.publicnode.com \
-H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"eth_getCode",
"params":["0x0200EbbD26467B866120D84A0d37c82CdE0acAEB","latest"],"id":1}'
# {"jsonrpc":"2.0","id":1,"result":"0x"}

回傳 0x,代表這個位址上根本沒有程式碼,它不是合約

回頭看 setup.js 我就懂自己錯在哪了。那個區塊的變數名稱寫得很清楚:

const id = {
mainnet: {
VETH: "0x454CB83913D688795E237837d30258d11ea7c752",
VRSC: "0x1Af5b8015C64d39Ab44C60EAd8317f9F5a9B6C4C",
BRIDGE: "0x0200EbbD26467B866120D84A0d37c82CdE0acAEB",
DAIERC20: "0x6B175474E89094C44Da98b954EedeAC495271d0F",
...

變數叫做 id,裡面裝的是 identifier。VETH 跟 VRSC 還有 BRIDGE 這三個都是 Verus 的貨幣與系統識別碼,只是長得像以太坊位址而已。我實際去查,這三個位址全部都沒有合約程式碼。檔案裡真正的以太坊合約是那些標了 ERC20 的,例如 DAIERC20 就是大家熟知的真 DAI 合約。

諷刺的是,我在報告的另一個地方明明就寫對了,我自己確認過 VETH 跟 BRIDGE 跟 VERUS 是 immutable 系統 ID。但我在寫事件摘要的時候,還是把 BRIDGE 這個系統 ID 當成了 Delegator 合約位址。

真正的橋接合約是 0x71518580f36feceffe0721f06ba4703218cd7f63,Etherscan 標記為 Verus: Ethereum Bridge。我驗證它確實有合約程式碼,目前還持有 1122 顆 ETH。而它正是把資產送進攻擊者錢包的那一方。

我用 grep 確認 immutable 系統 ID,也是從 setup.js 取得位址的地方,這裡就是我當初誤讀的來源
我用 grep 確認 immutable 系統 ID,也是從 setup.js 取得位址的地方,這裡就是我當初誤讀的來源

這個錯誤不影響漏洞的分析結論,因為漏洞在程式碼裡,跟部署位址無關。但它確實是一個事實錯誤,而且剛好打中我自己在報告裡強調的那條原則:引用要分級,自己驗過的才算自己驗過。我把 setup.js 裡的一個常數,當成了鏈上的部署事實,而那正是我當時查不到,也就沒有去驗的東西。

兩週過去了,公開 main 還是沒補

這一項我覺得比前兩項都重要。

我在撰稿時直接去抓 GitHub main 上的 VerusProof.sol

curl -s https://raw.githubusercontent.com/VerusCoin/Verus-Ethereum-Contracts/main/contracts/MMR/VerusProof.sol \
| sed -n '256,267p'

拉回來的還是這段:

if (!(hashedTransfers == hashReserveTransfers &&
systemSourceID == VERUS &&
destSystemID == VETH)) {

revert("CCE information does not checkout");
}

一模一樣。三項身分與雜湊比對,依然沒有任何一行金額驗證。main 的最新提交還是停在 d633dc4,2026 年 2 月 26 日,分支也還是只有 main 一支。

距離攻擊已經兩週,公開程式碼庫上這個缺口原封不動。我要說明的是,這不代表 Verus 沒有修。這個橋是可升級的 Delegator 架構,實際部署的合約有可能已經透過鏈上治理升級過,只是沒有同步推送到公開的 main。但站在一個從外部做驗證的人的角度,我能講的就只有一句:在公開可查的範圍內,我看不到修補。

順帶修正一個時序細節

我在報告的早期草稿裡寫過沒有任何 5 月的 release tag,用這點去反駁媒體所說的攻擊前兩天緊急更新。這次我用已認證的 GitHub API 重查,發現這句話不精確。

v1.2.16-1 確實是 5 月的 release,發布於 2026 年 5 月 11 日,也就是攻擊前 7 天。但它的內容是修補 Bitcoin Core 的 CVE-2024-52911,加上網路韌性更新,跟橋接完全無關

所以正確的說法應該是這樣:攻擊前確實有一個 release,但它不是橋接修補,時間也不是兩天前而是 7 天前。媒體的敘事還是站不住腳,只是理由跟我當初寫的不一樣。這個修正我的報告最終版有做到,但早期草稿的說法是錯的,我一併在這裡講明。

心得

這件事對我最大的意義,不是我找到了一個漏洞,而是它逼我想清楚證據到底是什麼。

當 Etherscan 把我擋在門外的時候,我其實可以選擇把三家機構的報導抄一抄就交差。那樣寫出來的東西看起來會很完整,甚至更好看,因為金額跟地址還有時間戳全都有。但那份報告裡不會有任何一個字是我自己驗的。

改走原始碼這條路之後,我反而得到了整份調查裡最硬的一塊。因為漏洞本體不需要鏈上狀態就能證明,它就寫在公開的 Solidity 裡,任何人都可以 clone 下來自己看。而且 Git 版本紀錄還額外給了我兩個第三方報導給不了的東西:這個缺陷有多老,以及它補了沒有。

在拿不到你最想要的證據時,真正該做的不是降低標準去引用別人,而是換一個你能親手驗證的證據面。

第二個體會是關於誠實。我在報告裡花了很大力氣做證據分級,把 A 級跟 B 級標得清清楚楚。結果我還是在事件摘要裡,把一個 setup.js 的常數寫成了鏈上的部署事實。這件事很好地提醒了我,分級不是寫在方法論那一節就算數的,它必須落實到每一個具體句子上。最容易出錯的地方,往往就是那些你以為理所當然,所以沒有特別去驗的東西。

最後回到技術本身。這個案子讓我對跨鏈橋的看法整個變了。

我以前會覺得,橋的安全性等於簽章跟證明的安全性。只要簽名不能偽造,Merkle 證明不能造假,橋就是安全的。這個案子把這個想法打得很碎。Verus 的密碼學一點問題都沒有,公證人的簽名完全有效,Merkle 證明完全正確,然後錢還是走了 1158 萬美元。

因為密碼學能保證的是訊息的真實性,它保證不了訊息的經濟合理性。一則訊息可以百分之百是真的,同時百分之百是搶劫。

所以我現在會這樣看跨鏈橋的設計:價值守恆是橋最核心的不變量,它必須在接收端被強制執行,而不能假設對面已經檢查過了。具體到這個案子,修補其實很單純:在 _createImportscheckCCEValues 裡加上硬性檢查,要求 reserve transfers 的支付總額必須等於 CCE 宣告的 totalamounts,而且 totalamounts 必須對應 Verus 側實際鎖定或銷毀的價值,逐幣別雙向綁定,任一不符就 revert。

大概就是 Blockaid 說的那十行。

這是我第一次做這種規模的取證調查。過程中被擋過,轉過彎,也在事後發現自己寫錯。但我覺得這些不完美的部分,反而比一份看起來滴水不漏的報告更值得寫出來。完整的報告跟所有原始檔案我都放在 GitHub 上,包含我的偵辦紀錄,裡面誠實記著哪幾步成功,哪幾步被擋。

如果你也在學資安,我會很推薦找一個真實案件從頭查一遍。你會很快發現,比起找到答案,知道自己哪裡不知道是更難也更重要的能力。謝謝看到這裡的你。