织梦CMS - 轻松建站从此开始!

我的网站

当前位置: 主页 > 比特币 > 比特币资讯

DeFi YAM,一行代码如何蒸发数亿美元?(2)

时间:2020-08-14 08:40来源:未知 作者:admin 点击:
通过分析代码,可以发现 delegateAndReturn 函数最终使用 delegatecall 的方式调用了 implementation 地址中的逻辑,也就是说,这是一个可升级的合约模型。而真正

通过分析代码,可以发现 delegateAndReturn 函数最终使用 delegatecall 的方式调用了 implementation 地址中的逻辑,也就是说,这是一个可升级的合约模型。而真正的 rebase 逻辑位于 YAM.sol 中, 继续跟进 rebase 函数的具体逻辑,如下:

function rebase(    uint256 epoch,    uint256 indexDelta,    bool positive   )    external    onlyRebaser    returns (uint256)   {    if (indexDelta == 0) {     emit Rebase(epoch, yamsScalingFactor, yamsScalingFactor);     return totalSupply;     }    uint256 prevYamsScalingFactor = yamsScalingFactor;    if (!positive) {      yamsScalingFactor = yamsScalingFactor.mul(BASE.sub(indexDelta)).div(BASE);     } else {      uint256 newScalingFactor = yamsScalingFactor.mul(BASE.add(indexDelta)).div(BASE);      if (newScalingFactor < _maxScalingFactor()) {        yamsScalingFactor = newScalingFactor;       } else {       yamsScalingFactor = _maxScalingFactor();       }     }    //SlowMist// 问题代码    totalSupply = initSupply.mul(yamsScalingFactor);    emit Rebase(epoch, prevYamsScalingFactor, yamsScalingFactor);    return totalSupply;   }}

通过分析最终的 rebase 函数的逻辑,不难发现代码中根据 yamsScalingFactor 来对 totalSupply 进行调整,由于 yamsScalingFactor 是一个高精度的值,在调整完成后应当除以 BASE 来去除计算过程中的精度,获得正确的值。但是项目方在对 totalSupply 进行调整时,竟忘记了对计算结果进行调整,导致了 totalSupply 意外变大,计算出错误的结果。

分析到这里还没结束,要将漏洞和社区治理关联起来,需要对代码进行进一步的分析。通过观察 rebase 函数的修饰器,不难发现此处限定了只能是 rebaser 进行调用。而 rebaser 是 YAM 中用与实现供应量相关逻辑的合约,也就是说,是 rebaser 合约最终调用了 YAM.sol 合约中的 rebase 函数。通过跟踪相关代码,发现 rebaser 合约中对应供应量调整的逻辑为 rebase 函数,代码如下:

function rebase()    public   {    // EOA only    require(msg.sender == tx.origin);    // ensure rebasing at correct time    _inRebaseWindow();    // This comparison also ensures there is no reentrancy.    require(lastRebaseTimestampSec.add(minRebaseTimeIntervalSec) < now);    // Snap the rebase time to the start of this window.    lastRebaseTimestampSec = now.sub(      now.mod(minRebaseTimeIntervalSec)).add(rebaseWindowOffsetSec);    epoch = epoch.add(1);    // get twap from uniswap v2;    uint256 exchangeRate = getTWAP();    // calculates % change to supply     (uint256 offPegPerc, bool positive) = computeOffPegPerc(exchangeRate);    uint256 indexDelta = offPegPerc;    // Apply the Dampening factor.    indexDelta = indexDelta.div(rebaseLag);    YAMTokenInterface yam = YAMTokenInterface(yamAddress);    if (positive) {      require(yam.yamsScalingFactor().mul(uint256(10**18).add(indexDelta)).div(10**18) < yam.maxScalingFactor(), "new scaling factor will be too big");     }    //SlowMist// 取当前 YAM 代币的供应量    uint256 currSupply = yam.totalSupply();    uint256 mintAmount;    // reduce indexDelta to account for minting    //SlowMist// 计算要调整的供应量    if (positive) {      uint256 mintPerc = indexDelta.mul(rebaseMintPerc).div(10**18);      indexDelta = indexDelta.sub(mintPerc);      mintAmount = currSupply.mul(mintPerc).div(10**18);     }    // rebase    //SlowMist// 调用 YAM 的rebase 逻辑    uint256 supplyAfterRebase = yam.rebase(epoch, indexDelta, positive);    assert(yam.yamsScalingFactor() <= yam.maxScalingFactor());    // perform actions after rebase    //SlowMist// 进入调整逻辑    afterRebase(mintAmount, offPegPerc);   } (责任编辑:admin)
织梦二维码生成器
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
推荐内容