Tornado Cash再次遭遇DAO治理攻击,如何识别恶意提案
币圈去中心化治理听起来挺美好,谁拿了代币谁就有投票权,大家一起决定协议怎么走,可现实是治理这套机制本身就是个攻击入口,只要有人能在提案环节做点手脚,整个协议的控制权就可能被人拿走,最近隐私协议Tornado Cash又出事了,一份提案差点把价值2300万美元的治理资产送进攻击者口袋。

这次提案到底藏了什么
2026年6月25日安全研究机构L2BEAT的人发现了一份提交给Tornado Cash DAO的提案,表面上写的是要建立新的费用标准,外加一套动态通缩销毁方案,听上去就是常规的协议优化,没什么敏感字眼。
问题是这份提案指向的合约压根没有在Etherscan上验证,这一点在Tornado的治理历史里非常罕见,正常提案基本都是开源可查的,没验证本身就是个大问号。
研究员Sergey Shemyakov在X上喊了一声,把这事公开出来,说这份提案的逻辑绕得很复杂。
随后另一位安全研究者Pascal Caversaccio介入分析,反编译合约之后确认,这份提案的真实目的是把合法的治理地址,换成一个攻击者控制的山寨地址,两个地址开头字符高度相似,肉眼基本分不出来。
一旦提案通过,攻击者就能随意清空relayer的余额,控制的资产规模高达2300万美元。
这不是第一次了
Tornado Cash在治理这块栽过跟头不是一次两次,2023年5月就发生过一次更严重的事件。
攻击者复制了一份之前已经通过的正常提案,几乎一字不改,只在执行逻辑里偷偷加了一个函数,提案通过之后,攻击者用这个函数直接给自己加了120万票。
当时整个DAO合法的票数加起来才大概70万,攻击者就这样拿到了对治理系统的完全控制权,治理系统在那一刻基本等于失效了。
拿到控制权之后,攻击者卷走了一部分代币,换成以太坊,又通过Tornado Cash自己把这笔钱洗了一遍,价格那段时间也跌得不轻,TORN从7点3美元一路跌到3点75美元。
后来攻击者把一部分资金又还了回去,社区也重新拿回了控制权,但这件事在行业里留下的影响一直没消,类似的剧本在2026年6月又差点重演了一次。
恶意提案常见的几种伪装手法
攻击者很少会从头写一份全新的提案,这样太容易被盯上,常用的招数其实就那么几种,摸清楚套路再去看提案,能省不少功夫。
复制历史提案
攻击者把以前已经通过的提案直接拿来Fork一份,保持百分之九十五以上的代码完全一致,只在最后几行执行逻辑上做手脚。
这样做让审查的人产生一种"以前就是这样写的"的错觉,正常提案可能写的是升级到一个新的实现合约地址,恶意提案表面上结构一模一样,只是把目标地址换成了攻击者自己控制的合约,代码差异可能就两三行,开发者审查的时候很容易一扫而过。
隐藏delegatecall
delegatecall这个调用方式是攻击者特别喜欢用的一招,它执行的是外部合约里的代码,但修改的却是当前合约自己的状态变量。
提案合约表面上看不出有权限去改Owner这种关键变量,但只要执行了delegatecall,调用进去的外部合约代码一跑完,Owner实际上已经悄悄变成了攻击者的地址,这种攻击方式不会留下特别明显的痕迹,单看提案的权限声明根本发现不了问题,必须把整条调用链路扒出来才能看清楚。
利用代理合约做文章
现在主流的DAO架构基本都离不开Proxy、可升级合约,加上Timelock这套组合。
如果一份提案拿到了升级权限,攻击者根本不需要直接去偷代币,只要把Proxy指向的Implementation地址换成自己部署的恶意版本,从那一刻起,所有调用这个合约的交易都会进入攻击者写的逻辑里去。
很多恶意提案真正改动的其实不是资产相关的变量,而是这个Implementation地址,这一点恰恰是最容易被忽略的地方,因为表面上看提案根本没碰任何跟钱有关的字段。
为什么这么多人没发现异常
标题写得太正常
常见的标题就是"优化治理流程"或者"小版本升级",没有任何敏感词汇会让人多想一步。
代码差异小到可以忽略
拉一下Git Diff可能就显示加了两行减了一行,开发者审查的时候注意力很容易被分散,扫一眼觉得没问题就过去了。
大多数投票人根本不读代码
现实情况是DAO里参与投票的人,绝大多数依赖的是社交媒体上的介绍,或者某个意见领袖的看法,真正打开合约逐行去看的人少之又少。
社区天然信任历史提案
攻击者正是吃准了这一点,复制一份老提案,只改最后一小段,社区看到大体框架熟悉,下意识就会觉得安全,等真正出问题的时候,控制权早就已经转移了。
普通持币人怎么判断一份提案靠不靠谱
1、先看提案有没有动Owner、Governor、Timelock、Admin这类权限相关的变量,这些东西决定的是整个协议的控制权,一旦改动要格外小心。
2、检查代码里是否出现delegatecall,出现了就说明这份提案可能能执行任意逻辑,风险等级直接拉高。
3、留意有没有新增的外部合约地址,比如setImplementation、upgrade、execute这类函数,去查一下这个新地址是谁部署的,有没有开源,有没有经过审计。
4、看是否绕开了Timelock,正常流程应该是提案、投票、排队、Timelock等待、再执行,如果提案想跳过等待期或者缩短时间,风险很高。
5、查一下提案发起人的地址,是不是长期参与治理的老地址,有没有提案历史,如果是刚建的新钱包突然提出重大升级,这种情况值得多看几眼。
6、合约是否在Etherscan上验证过,没验证的合约本身就是个高危信号,需要拿去反编译看看里面到底写了什么。
能用上的工具和具体操作
① 查合约状态可以直接上Etherscan看验证情况、字节码和交易记录,这是最基础也最直接的一步。
② 遇到没验证的合约,可以借助在线反编译工具或者Foundry去扒一下里面的逻辑,看看跟提案描述的内容是不是对得上。
③ 平时也可以多关注像L2BEAT、Pascal Caversaccio这类安全研究员在社交媒体上的动态,他们往往是最先发现异常的人,等于是给整个社区提前预警。
④ PFS链接里的提案详情也可以直接打开看一眼,很多关键信息会比简单的摘要描述更完整。
怎么把风险降到最低
1、不要盲目跟着投票走,意见领袖说的话也不能直接当依据,他们同样可能没去看代码细节。
2、至少把提案的摘要内容读一遍,弄清楚这次升级到底想干什么,目标是改进效率还是别的什么。
3、代码Diff一定要看,重点盯紧权限变量和地址变化这两块,其他无关的格式调整可以略过。
4、不着急投票的话,可以多等等安全社区那边的分析结果出来,专业的审计团队反应速度通常很快。
5、投票通过之后也不是完全没机会,Timelock执行前这段等待期里,如果发现异常,社区还有机会发起紧急提案去撤回或者应对。
6、可以考虑加一层代码哈希校验,保证投票时看到的代码和最终执行的代码完全是同一份,再配合最小锁仓门槛和更长的Timelock等待期,能把这类攻击的成功概率压下去不少。
这次2026年6月的提案算是被及时拦下来了,没造成实际损失,但回头看这两次事件会发现一个共同点,治理系统一旦失守,后面所有的升级、所有的资金调动都跟着失控,持币人手里的投票权看起来是权利,操作不当也可能变成被攻击的入口,多看一眼代码,多查一下提案发起人的背景,花的时间不多,但能避开的坑可能很大。






