当前位置:   article > 正文

Paraluni合约攻击学习_fist.balanceof(address(this))

fist.balanceof(address(this))

2022年3月13日,Paraluni合约遭受攻击,损失约170万美元
攻击交易:https://bscscan.com/tx/0xd0b4a1d4964cec578516bd3a2fcb6d46cadefe1fea5a2f18eec4c0a496e696f9
合约代码:
MasterChef:https://bscscan.com/address/0xa386f30853a7eb7e6a25ec8389337a5c6973421d#code
ParaRouter:https://bscscan.com/address/0x48bb5f07e78f32ac7039366533d620c72c389797#code


MasterChef合约中函数depositByAddLiquidity 允许将池pid,与任意token(2ge)地址传递,并在收取token后记录当前pid对应lptoken数量后调用paraRouter.addLiquidity将用户传入token(2个)加入池中,计算lptoken的数量差值后记录用户对应的lptoken数量,但合约并没有设置防重入.

 function depositByAddLiquidity(uint256 _pid, address[2] memory _tokens, uint256[2] memory _amounts) external{
        require(_amounts[0] > 0 && _amounts[1] > 0, "!0");
        address[2] memory tokens;
        uint256[2] memory amounts;
        (tokens[0], amounts[0]) = _doTransferIn(msg.sender, _tokens[0], _amounts[0]);
        (tokens[1], amounts[1]) = _doTransferIn(msg.sender, _tokens[1], _amounts[1]);
        depositByAddLiquidityInternal(msg.sender, _pid, tokens,amounts);
    }
 function depositByAddLiquidityInternal(address _user, uint256 _pid, address[2] memory _tokens, uint256[2] memory _amounts) internal {
        PoolInfo memory pool = poolInfo[_pid];
        require(address(pool.ticket) == address(0), "T:E");
        uint liquidity = addLiquidityInternal(address(pool.lpToken), _user, _tokens, _amounts);
        _deposit(_pid, liquidity, _user);
    }

    function addLiquidityInternal(address _lpAddress, address _user, address[2] memory _tokens, uint256[2] memory _amounts) internal returns (uint){
        //Stack too deep, try removing local variables
        DepositVars memory vars;
        approveIfNeeded(_tokens[0], address(paraRouter), _amounts[0]);
        approveIfNeeded(_tokens[1], address(paraRouter), _amounts[1]);
        vars.oldBalance = IERC20(_lpAddress).balanceOf(address(this));
        (vars.amountA, vars.amountB, vars.liquidity) = paraRouter.addLiquidity(_tokens[0], _tokens[1], _amounts[0], _amounts[1], 1, 1, address(this), block.timestamp + 600);
        vars.newBalance = IERC20(_lpAddress).balanceOf(address(this));
        require(vars.newBalance > vars.oldBalance, "B:E");
        vars.liquidity = vars.newBalance.sub(vars.oldBalance);
        addChange(_user, _tokens[0], _amounts[0].sub(vars.amountA));
        addChange(_user, _tokens[1], _amounts[1].sub(vars.amountB));
        return vars.liquidity;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

而且token地址由用户传入,所以如果传入用户自己生成的合约,并且再transfer函数中重入调用影响IERC20(_lpAddress).balanceOf(address(this))的功能(如deposit,depositByAddLiquidity)就能使用户对应的lptoken数量加多倍,最后通过提取lptoken,移除流动性完成攻击.

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/654149
推荐阅读
相关标签
  

闽ICP备14008679号