http://www.7klian.com

阐明 | YFValue,一行代码如何锁定上亿资产

通过登岸 YFValue 的官方网站 ,(),可以发此刻 YFValue 的体系中,用户可通过质押相关的代币获取对应的嘉奖,今朝 YFValue 支持的质押代币池有以下几个:

可以看到,今朝由于裂痕的原因,YFV 的抵押池已经在 UI 界面封锁了抵押成果,可是合约上今朝还没封锁代币抵押的成果,我们需要跟踪代码来阐明详细的细节点。

function tokenStakeOnBehalf(address stakeFor, uint256 amount) internal { _totalSupply = _totalSupply.add(amount); _balances[stakeFor] = _balances[stakeFor].add(amount); yfv.safeTransferFrom(msg.sender, address(this), amount); } 可以看到这里只是简朴的把对应的 token 用 transferFrom 的方法转入到合约中,没有什么出格的逻辑点。到这里整个抵押流程就很清晰了,接下来是收益的进程。计较用户收益的是 stakeReward 函数,领取收益的为 withdraw 函数,代码别离如下:


function stakeReward() public updateReward(msg.sender) checkNextEpoch {
        uint256 reward = getReward();
        require(reward > 0, "Earned too little");
        super.tokenStake(reward);
        lastStakeTimes[msg.sender] = block.timestamp;
        emit Staked(msg.sender, reward);
    }

 

修复方案

 

媒介

 

function stakeOnBehalf(address stakeFor, uint256 amount) public updateReward(stakeFor) checkNextEpoch { require(amount > 0, "Cannot stake 0"); super.tokenStakeOnBehalf(stakeFor, amount); lastStakeTimes[stakeFor] = block.timestamp; emit Staked(stakeFor, amount); }

通过代码不难发明,无论是 stake 函数照旧 stakeOnBehalf 函数,逻辑根基是一样的,首先是校验了抵押金额不能为0,接着别离挪用上层的 tokenStake 和 tokenStakeOnBehalf 函数。紧接着更新用户的抵押时间。只不外 stakeOnBehalf 函数可以用于为他人抵押。tokenStake 和 tokenStakeOnBehalf 的代码如下:

function tokenStake(uint256 amount) internal {
        _totalSupply = _totalSupply.add(amount);
        _balances[msg.sender] = _balances[msg.sender].add(amount);
        yfv.safeTransferFrom(msg.sender, address(this), amount);
    }

阐明白一大堆,回到我们最初的问题,恶意的用户是怎么锁定其他用户的 function withdraw(uint256 amount) public updateReward(msg.sender) checkNextEpoch { require(amount > 0, "Cannot withdraw 0"); require(block.timestamp >= unfrozenStakeTime(msg.sender), "Coin is still frozen"); super.tokenWithdraw(amount); emit Withdrawn(msg.sender, amount); }

通过阐明计较收益和领取收益的代码,发明逻辑也很简朴,stake 函数首先是通过 updateReward 修饰器更新了用户的嘉奖,然后利用 getReward 函数计较了用户的嘉奖,并把抵押时间配置成当前区块时间。最后,用户在提取嘉奖的时候,,withdraw 函数会首先计较当前的区块时间,再与 unfrozenStakeTime 函数中计较出的时间举办比拟,只有当前区块时间大于 unfrozenStakeTime 计较出的时间,才答允提现。unfrozenStakeTime 的代码如下:

 function unfrozenStakeTime(address account) public view returns (uint256) {
        return lastStakeTimes[account] + FROZEN_STAKING_TIME;
    }
从代码中得知,unfrozenStakeTime 是利用用户的上次抵押时间加上 FROZEN_STAKING_TIME 常量得出锁按时间,只要高出时间,就能通过 withdraw 函数提现收益。整个抵押和领取收益的简化流程如下:

这是本月呈现的第二个没有颠末审计的 DeFi 项目所袒暴露的风险,按照 YFValue 的官方声明(https://medium.com/@yfv.finance/yfv-bringing-true-value-to-yield-farming-bddc4edf889a),项目代码是由富有履历的开拓者举办开拓的,同时警惕了其他乐成的项目标代码,可是仍无可制止的呈现了风险。术业有专攻,安详审计一方面需要项目方的正向思维,另一方面,照旧需要专业的安详团队的逆向思维,从专业的黑客角度举办模仿反抗,发明问题。

据币世界动静,DeFi 项目 YFValue (YFV)宣布通告称,团队于昨日在 YFV 质押池中发明一个裂痕,恶意参加者借此裂痕对证押中的 YFV 计时器单独重置。今朝已有一个恶意参加者正试图借此打单团队。慢雾安详团队对此举办了深入阐明,以下是相关技能细节。

通过阐明代码和裂痕细节,针对本次裂痕,修复方案也很简朴,只要在抵押的时候查抄用户的抵押状态是否为已经抵押,假如已经抵押,则不答允再次抵押。可能对每次的抵押举办单独的处理惩罚,不能对先前的抵押状态发生影响。

 

细节阐明

 

按照官网提供的 Github 地点,我们溯源到了相关的代码客栈(https://github.com/yfv-finance/audit),关于 YFV 抵押的相关逻辑在YFV_Stake.sol 合约中,合约中关于抵押的函数有 2 个,别离是 stake 函数和 stakeOnBehalf 函数,以下是详细的代码:


 function stake(uint256 amount, address referrer) public updateReward(msg.sender) checkNextEpoch {
        require(amount > 0, "Cannot stake 0");
        require(referrer != msg.sender, "You cannot refer yourself.");
        super.tokenStake(amount);
        lastStakeTimes[msg.sender] = block.timestamp;
        emit Staked(msg.sender, amount);
        if (rewardReferral != address(0) && referrer != address(0)) {
            IYFVReferral(rewardReferral).setReferrer(msg.sender, referrer);
        }
    }

 

前车之鉴

 

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

相关文章阅读