hats-finance / Convergence---Convex-integration-0xb3df23e155b74ad2b93777f58980d6727e8b40bb

0 stars 1 forks source link

Improper use of Deadline in `_depositEth` function of `StakingServicesBase.sol` using UniswapV2 router #13

Open hats-bug-reporter[bot] opened 6 months ago

hats-bug-reporter[bot] commented 6 months ago

Github username: -- Twitter username: -- Submission hash (on-chain): 0x26c76a511048c54a3920a95a9b36a993381b7dfcf4bccf696a571d4d5581ae4e Severity: medium

Description: Description\ _depositEth function is using a function swapExactETHForTokens from UniswapV2Router but providing deadline as block.timestamp + 1000

Attack Scenario\ Using block.timestamp + 1000 is effectively bypassing the security check. As the block.timestamp will be determined once the transaction gets mined, the check will always pass.

Failing to provide a proper deadline value enables pending transactions to be maliciously executed at a later point. Transactions providing too little gas will have their execution delayed, and can be picked by malicious actors or MEV bots to be executed at a later point when they can profit from it, whilst negatively affecting the transaction sender.

Attachments

  1. Proof of Concept (PoC) File Calls to UniswapV2Router02::swapExactETHForTokens() are protected by a deadline parameter to limit the execution of delayed/ old transactions. Functions that modify liquidity of the pool check this parameter against the current block timestamp in order to discard expired interactions:
  function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        virtual
        override
        payable
        ensure(deadline)
        returns (uint[] memory amounts)
    {
        require(path[0] == WETH, 'UniswapV2Router: INVALID_PATH');
        amounts = UniswapV2Library.getAmountsOut(factory, msg.value, path);
        require(amounts[amounts.length - 1] >= amountOutMin, 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT');
        IWETH(WETH).deposit{value: amounts[0]}();
        assert(IWETH(WETH).transfer(UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0]));
        _swap(amounts, path, to);
    }

The modifier ensure(deadline):

modifier ensure(uint deadline) {
        require(deadline >= block.timestamp, 'UniswapV2Router: EXPIRED');
        _;
    }

The deadline provided by the caller is checked to be larger or equal to the current block timestamp. The implemention of the deadline in _depositEth function is using a function swapExactETHForTokens :

 function _depositEth(uint256 amountIn, uint256 amountOutMin) internal returns (uint256 amountOut) {
        PoolEthInfo memory _poolEthInfo = poolEthInfo;
        require(_poolEthInfo.poolType != PoolType.DEACTIVATED, "DEPOSIT_ETH_PAUSED");
        if (_poolEthInfo.poolType == PoolType.UNIV2) {
            address[] memory path = new address[](2);
            path[0] = WETH;
            path[1] = _poolEthInfo.token;
            uint256[] memory amounts = UNISWAPV2_ROUTER.swapExactETHForTokens{value: amountIn}(
                amountOutMin,
                path,
                address(this),
                block.timestamp + 1000
            );
            amountOut = amounts[1];
        } else if (_poolEthInfo.poolType == PoolType.UNIV3) {
            amountOut = UNISWAPV3_ROUTER.exactInputSingle{value: amountIn}(
                IUniv3Router.ExactInputSingleParams({
                    tokenIn: WETH,
                    tokenOut: _poolEthInfo.token,
                    fee: _poolEthInfo.fee,
                    recipient: address(this),
@>>>                    deadline: block.timestamp + 1000,
                    amountIn: amountIn,
                    amountOutMinimum: amountOutMin,
                    sqrtPriceLimitX96: 0
                })
            );
        } else if (_poolEthInfo.poolType == PoolType.CURVE) {
            (uint256 tokenInIndex, uint256 tokenOutIndex) = _poolEthInfo.indexEth == 0 ? (0, 1) : (1, 0);
            amountOut = _poolEthInfo.poolCurve.exchange{value: amountIn}(
                tokenInIndex,
                tokenOutIndex,
                amountIn,
                amountOutMin,
                true
            );
        }
    }
  1. Revised Code File (Optional)
PlamenTSV commented 6 months ago

Dupe of #1