sherlock-audit / 2024-05-napier-update-judging

8 stars 7 forks source link

karsar - PufETHAdapter fails when trying to stake stETH #52

Closed sherlock-admin3 closed 4 months ago

sherlock-admin3 commented 5 months ago

karsar

high

PufETHAdapter fails when trying to stake stETH

Summary

When calling the depositSTETH function through PUFFER_DEPOSITOR it will fail in PufETHAdapter contract because of usage of different versions.

Vulnerability Detail

The main cause of this issue is depositSTETH function doesnt have a recipient so the function will revert because napier PufETHAdapter is using v1 of puffethdepositor instead of v2 which has been updated recently which adds a recipent address parameter. As we can see the pufETH has been upgraded to v2 https://github.com/PufferFinance/pufETH/releases/tag/v2.0.0

function _stake(uint256 stakeAmount) internal override returns (uint256) {
        if (stakeAmount == 0) return 0;

        uint256 stakeLimit = STETH.getCurrentStakeLimit();
        if (stakeAmount > stakeLimit) {
            // Cap stake amount
            stakeAmount = stakeLimit;
        }

        IWETH9(Constants.WETH).withdraw(stakeAmount);
        uint256 _stETHAmt = STETH.balanceOf(address(this));
        STETH.submit{value: stakeAmount}(address(this));
        _stETHAmt = STETH.balanceOf(address(this)) - _stETHAmt;
        if (_stETHAmt == 0) revert InvariantViolation();

        // Stake stETH to PufferDepositor
        uint256 _pufETHAmt = PUFFER_DEPOSITOR.depositStETH(Permit(block.timestamp, _stETHAmt, 0, 0, 0)); // no recepient

        if (_pufETHAmt == 0) revert InvariantViolation();

        return stakeAmount;
    }

here is the v2 version

   /**
     * @inheritdoc IPufferDepositorV2
     */
    function depositStETH(Permit calldata permitData, address recipient)
        external
        restricted
        returns (uint256 pufETHAmount)
    {
        try ERC20Permit(address(_ST_ETH)).permit({
            owner: msg.sender,
            spender: address(this),
            value: permitData.amount,
            deadline: permitData.deadline,
            v: permitData.v,
            s: permitData.s,
            r: permitData.r
        }) { } catch { }

        // Transfer stETH from user to this contract. The amount received here can be 1-2 wei lower than the actual permitData.amount
        SafeERC20.safeTransferFrom(IERC20(address(_ST_ETH)), msg.sender, address(this), permitData.amount);

        // The PufferDepositor is not supposed to hold any stETH, so we sharesOf(PufferDepositor) to the PufferVault immediately
        return PUFFER_VAULT.depositStETH(_ST_ETH.sharesOf(address(this)), recipient);
    }

Impact

Dos of users

Code Snippet

[https://github.com/sherlock-audit/2024-05-napier-update/blob/main/napier-uups-adapters/src/adapters/puffer/PufETHAdapter.sol#L66-L87]()

Tool used

Manual Review

Recommendation


        // Stake stETH to PufferDepositor
        uint256 _pufETHAmt = PUFFER_DEPOSITOR.depositStETH(Permit(block.timestamp, _stETHAmt, 0, 0, 0),msg.sender); 

Duplicate of #21