通过分析代码,可以发现在发起提案时,需要提案发起人拥有一定额度的票权利,这个值必须大于 proposalThreshold 计算得来的值,具体代码如下: functionproposalThreshold()publicviewreturns(uint256){ returnSafeMath.div(yam.initSupply(),100);}//1%ofYAM也就是说提案发起人的票权必须大于 initSupply 的 1% 才能发起提案。那 initSupply 受什么影响呢?答案是 YAM 代币的 mint 函数,代码如下: function mint(address to, uint256 amount) external onlyMinter returns (bool) { _mint(to, amount); return true; } function _mint(address to, uint256 amount) internal { // increase totalSupply totalSupply = totalSupply.add(amount); // get underlying value uint256 yamValue = amount.mul(internalDecimals).div(yamsScalingFactor); // increase initSupply initSupply = initSupply.add(yamValue); // make sure the mint didnt push maxScalingFactor too low require(yamsScalingFactor <= _maxScalingFactor(), "max scaling factor too low"); // add balance _yamBalances[to] = _yamBalances[to].add(yamValue); // add delegates to the minter _moveDelegates(address(0), _delegates[to], yamValue); emit Mint(to, amount); }从代码可知,mint 函数在每次铸币时都会更新 initSupply 的值,而这个值是根据 amount 的值来计算的,也就是铸币的数量。 现在,我们已经分析完所有的流程了,剩下的就是把所有的分析串起来,看看这次的漏洞对 YAM 产生了什么影响,对上文的流程图做拓展,变成下面这样: 整个事件的分析如上图,由于 rebase 的时候取的是上一次的 totalSupply 的值,所以计算错误的 totalSupply 的值并不会立即通过 mint 作用到 initSupply 上,所以在下一次 rebase 前,社区仍有机会挽回这个错误,减少损失。但是一旦下一次 rebase 执行,整个失误将会变得无法挽回。 通过查询 Etherscan 上 YAM 代币合约的相关信息,可以看到 totalSupply 已经到了一个非常大的值,而 initSupply 还未受到影响。 (责任编辑:admin) |