图5. GovernorAlpha::queue() 函数设置eta(生效时间) 又为什么说已经做出的拯救行动,根本无济于事呢? 当触发合约 GovernorAlpha::execute() 时首先会先执行 state 函数来获得当前提案状态。 图6. GovernorAlpha::execute() 检测提案状态 在下面的 state() 函数 第330行,如果 proposal.forVotes <= againstVotes() ,提案状态被设置为失败。 图7. GovernorAlpha::state() 执行返回Defeated错误 从代码中能看出来,项目方在设计系统时,投票数被设计为必须大于 initSupply 总量的4%,此提案才能是合法的状态,如下图所示。然而,当第二次执行 rebase 以后,initSupply 已经被搞成一个极大值。这就导致了,投票票数(forVotes)永远不可能 >= quorumVotes(),从而总是返回 Defeated。 图8. GovernorAlpha::quorumVotes() 返回一个错误的异常值 除了提案状态异常的问题之外,如图9、图10所示,当第二次 rebase 发生以后,由于 GovernorAlpha :: propose() 检查投票数必然小于 proposalThreshold(1%的initSupply),因此新的提案也再也无法被提出,更遑论要投票执行了。 图9. GovernorAlpha::propose() 检测投票数是否大于1% initSupply 图10. GovernorAlpha::proposalThreshold() 返回1% initSupply 总结此次 YAM 漏洞事件,最终造成治理合约中75万枚 yCRV 被永久锁定,而且短时间内的急速暴跌和无力回天的局面,不知道有多少人被埋在了价格高点,其疯狂程度成了如今 DeFi 流动性挖矿的最真实写照,其残酷魔幻程度何尝又不是?倘若项目方在部署合约之前但凡测试过一次 rebase 流程,必定能捕捉到漏洞的存在。足以见得,DeFi 项目做安全审计的重要性。 综上分析,PeckShield(派盾) 想借此劝诫诸君,在区块链世界里,务必要对每一行合约代码保持敬畏,因为任何细微的疏漏都可能造成无法挽回的局面。毕竟,代码是人写的,漏洞也很难被彻底避免,因此需要项目方在合约部署上线前就做好充分的测试和第三方安全审计工作,这会帮助其更早发现并排查合约代码潜在的安全漏洞,不至于等到,漏洞发生后,亡羊补牢,为时已晚。 (责任编辑:admin) |