Unable to deposit to Tranche/Adaptor under certain conditions
Minting of PT and YT is the core feature of the protocol. Without the ability to mint PT and YT, the protocol would not operate.\\nThe user cannot deposit into the Tranche to issue new PT + YT under certain conditions.\\nThe comment in Line 133 below mentioned that the `stakeAmount` can be zero.\\nThe reason is that when `targetBufferEth < (availableEth + queueEthCache)`, it is possible that there is a pending withdrawal request (queueEthCache) and no available ETH left in the buffer (availableEth = 0). Refer to the comment in Line 123 below.\\nAs a result, the code at Line 127 below will restrict the amount of ETH to be staked and set the `stakeAmount` to zero.\\n```\\nFile: BaseLSTAdapter.sol\\n    function prefundedDeposit() external nonReentrant returns (uint256, uint256) {\\n..SNIP..\\n        uint256 stakeAmount;\\n        unchecked {\\n            stakeAmount = availableEth + queueEthCache - targetBufferEth; // non-zero, no underflow\\n        }\\n        // If the stake amount exceeds 95% of the available ETH, cap the stake amount.\\n        // This is to prevent the buffer from being completely drained. This is not a complete solution.\\n        //\\n        // The condition: stakeAmount > availableEth, is equivalent to: queueEthCache > targetBufferEth\\n        // Possible scenarios:\\n        // - Target buffer percentage was changed to a lower value and there is a large withdrawal request pending.\\n        // - There is a pending withdrawal request and the available ETH are not left in the buffer.\\n        // - There is no pending withdrawal request and the available ETH are not left in the buffer.\\n        uint256 maxStakeAmount = (availableEth * 95) / 100;\\n        if (stakeAmount > maxStakeAmount) {\\n            stakeAmount = maxStakeAmount; // max 95% of the available ETH\\n        }\\n\\n        /// INTERACT ///\\n        // Deposit into the yield source\\n        // Actual amount of ETH spent may be less than the requested amount.\\n        stakeAmount = _stake(stakeAmount); // stake amount can be 0\\n```\\n\\nHowever, the issue is that when `_stake` function is called with `stakeAmount` set to zero, it will result in zero ETH being staked and Line 77 below will revert.\\n```\\nFile: StEtherAdapter.sol\\n    /// @inheritdoc BaseLSTAdapter\\n    /// @dev Lido has a limit on the amount of ETH that can be staked.\\n    /// @dev Need to check the current staking limit before staking to prevent DoS.\\n    function _stake(uint256 stakeAmount) internal override returns (uint256) {\\n        uint256 stakeLimit = STETH.getCurrentStakeLimit();\\n        if (stakeAmount > stakeLimit) {\\n            // Cap stake amount\\n            stakeAmount = stakeLimit;\\n        }\\n\\n        IWETH9(Constants.WETH).withdraw(stakeAmount);\\n        uint256 _stETHAmt = STETH.submit{value: stakeAmount}(address(this));\\n\\n        if (_stETHAmt == 0) revert InvariantViolation();\\n        return stakeAmount;\\n    }\\n```\\n\\nA similar issue also occurs for the sFRXETH adaptor. If `FRXETH_MINTER.submit` function is called with `stakeAmount == 0`, it will revert.\\n```\\nFile: SFrxETHAdapter.sol\\n    /// @notice Mint sfrxETH using WETH\\n    function _stake(uint256 stakeAmount) internal override returns (uint256) {\\n        IWETH9(Constants.WETH).withdraw(stakeAmount);\\n        FRXETH_MINTER.submit{value: stakeAmount}();\\n        uint256 received = STAKED_FRXETH.deposit(stakeAmount, address(this));\\n        if (received == 0) revert InvariantViolation();\\n\\n        return stakeAmount;\\n    }\\n```\\n\\nThe following shows that the `FRXETH_MINTER.submit` function will revert if submitted ETH is zero below.\\n```\\n/// @notice Mint frxETH to the recipient using sender's funds. Internal portion\\nfunction _submit(address recipient) internal nonReentrant {\\n    // Initial pause and value checks\\n    require(!submitPaused, "Submit is paused");\\n    require(msg.value != 0, "Cannot submit 0");\\n```\\n
Short-circuit the `_stake` function by returning zero value immediately if the `stakeAmount` is zero.\\nFile: StEtherAdapter.sol\\n```\\nfunction _stake(uint256 stakeAmount) internal override returns (uint256) {\\n// Add the line below\\n if (stakeAmount == 0) return 0; \\n uint256 stakeLimit = STETH.getCurrentStakeLimit();\\n if (stakeAmount > stakeLimit) {\\n  // Cap stake amount\\n  stakeAmount = stakeLimit;\\n }\\n\\n IWETH9(Constants.WETH).withdraw(stakeAmount);\\n uint256 _stETHAmt = STETH.submit{value: stakeAmount}(address(this));\\n\\n if (_stETHAmt == 0) revert InvariantViolation();\\n return stakeAmount;\\n}\\n```\\n\\nFile: SFrxETHAdapter.sol\\n```\\nfunction _stake(uint256 stakeAmount) internal override returns (uint256) {\\n// Add the line below\\n if (stakeAmount == 0) return 0; \\n IWETH9(Constants.WETH).withdraw(stakeAmount);\\n FRXETH_MINTER.submit{value: stakeAmount}();\\n uint256 received = STAKED_FRXETH.deposit(stakeAmount, address(this));\\n if (received == 0) revert InvariantViolation();\\n\\n return stakeAmount;\\n}\\n```\\n
Minting of PT and YT is the core feature of the protocol. Without the ability to mint PT and YT, the protocol would not operate. The user cannot deposit into the Tranche to issue new PT + YT under certain conditions. Breaking of core protocol/contract functionality.
```\\nFile: BaseLSTAdapter.sol\\n    function prefundedDeposit() external nonReentrant returns (uint256, uint256) {\\n..SNIP..\\n        uint256 stakeAmount;\\n        unchecked {\\n            stakeAmount = availableEth + queueEthCache - targetBufferEth; // non-zero, no underflow\\n        }\\n        // If the stake amount exceeds 95% of the available ETH, cap the stake amount.\\n        // This is to prevent the buffer from being completely drained. This is not a complete solution.\\n        //\\n        // The condition: stakeAmount > availableEth, is equivalent to: queueEthCache > targetBufferEth\\n        // Possible scenarios:\\n        // - Target buffer percentage was changed to a lower value and there is a large withdrawal request pending.\\n        // - There is a pending withdrawal request and the available ETH are not left in the buffer.\\n        // - There is no pending withdrawal request and the available ETH are not left in the buffer.\\n        uint256 maxStakeAmount = (availableEth * 95) / 100;\\n        if (stakeAmount > maxStakeAmount) {\\n            stakeAmount = maxStakeAmount; // max 95% of the available ETH\\n        }\\n\\n        /// INTERACT ///\\n        // Deposit into the yield source\\n        // Actual amount of ETH spent may be less than the requested amount.\\n        stakeAmount = _stake(stakeAmount); // stake amount can be 0\\n```\\n