背景介紹
2025年7⽉28⽇,我們監控到 Ethereum上針對RareStaking的攻擊事件https://etherscan.io/tx/0xd813751bfb98a51912b8394b5856ae4515be6a9c6e5583e06b41d9255ba6e3c1,
攻擊共造成25.8kUSD 的損失。
攻擊及事件分析
⾸先,攻擊者創建了⼀個攻擊合約,並在攻擊合約中取得了RareStaking對應的Staking Token。

隨後,攻擊者透過調⽤updateMerkleRoot更新了Merkle Tree Root。

讓我們看⼀下 updateMerkleRoot 的程式碼:
function updateMerkleRoot(bytes32 newRoot) external override {
require((msg.sender != owner() || msg.sender !=
address(0xc2F394a45e994bc81EfF678bDE9172e10f7c8ddc)), "Not authorized to update merkle root");
if (newRoot == bytes32(0)) revert EmptyMerkleRoot();
currentClaimRoot = newRoot;
currentRound++;
emit NewClaimRootAdded(newRoot, currentRound, block.timestamp);
}
⼀般來說,更新 Merkle Tree Root 是敏感操作,通常需要管理員或營運⼈員才可能更改。但是程式碼中的邏輯,不是 owner 且不是項⽬⽅位址的⼈才可以更改,顯然,開發者把 require 的功能理解錯了。在攻擊者 updateMerkleRoot 後,便發動了 claim ,提取了項⽬中的所有 Token 。

由於MerkleRoot已經被攻擊者修改,所以claim可以通過驗證。在被攻擊後,項⽬⽅在交易
https://etherscan.io/tx/0x65f37e4b1ec995adadd3f264a77f67b6bcbb52f16f29cf3302c9bf90396aa67e
中升級了實現合約,將 updateMerkleRoot 的程式碼修改為下⾯的程式碼:
function updateMerkleRoot(bytes32 newRoot) external override {
if (
(msg.sender != owner() &&
msg.sender !=
address(0xc2F394a45e994bc81EfF678bDE9172e10f7c8ddc))
) revert NotAuthorized();
if (newRoot == bytes32(0)) revert EmptyMerkleRoot();
currentClaimRoot = newRoot;
currentRound++;
emit NewClaimRootAdded(newRoot, currentRound, block.timestamp);
}
可以看到,修改後的邏輯才能正確驗證調⽤者的權限。
總結
這次漏洞的成因是函數 updateMerkleRoot 函數在校驗調⽤者權限時,沒有正確理解 require 的作⽤,導致權限驗證失效。最終,導致攻擊者透過權限校驗修改了 MerkleTreeRoot 後透過驗證提取了項⽬所有資⾦。建議項⽬⽅在設計經濟模型及程式碼運⾏邏輯時要多⽅驗證,合約上線前審計時盡量選擇多個審計公司交叉審計。
