xanoutas/solidity-security-findings huggingface dataset:
Wrong `Operator` used for `expectedCollateral`
Audit: 2024-06-badger-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-06-badger/blob/9173558ee1ac8a78a7ae0a39b97b50ff0dd9e0f8/ebtc-zap-router/src/LeverageZapRouterBase.sol#L265-L274
https://github.com/code-423n4/2024-06-badger/blob/9173558ee1ac8a78a7ae0a39b97b50ff0dd9e0f8/ebtc-protocol/packages/contracts/contracts/LeverageMacroBase.sol#L211
https://github.com/code-423n4/2024-06-badger/blob/9173558ee1ac8a78a7ae0a39b97b50ff0dd9e0f8/ebtc-protocol/packages/contracts/contracts/LeverageMacroBase.sol#L281-L282


# Vulnerability details

## Impact
In `PostCheckParams`, the `expectedCollateral` is initialized as `_totalCollateral * _collValidationBuffer / BPS` with a `gte` operator. This signifies that the check is `_totalCollateral * _collValidationBuffer / BPS >= cdpInfo.coll` which is inconsistent with the intended design. As a slippage control, the `cdpInfo.coll` is expected to be higher than `_collValidationBuffer` of `_totalCollateral` provided.

## Proof of Concept
In `PostCheckParams`, the `expectedCollateral` is initialized as `_totalCollateral * _collValidationBuffer / BPS` with a `gte` operator.

```solidity
	expectedCollateral: CheckValueAndType({
		value:  _totalCollateral * _collValidationBuffer / BPS,
		operator: Operator.gte
	}),
```

It is later used in the postcheck.

```solidity
	 _doCheckValueType(checkParams.expectedCollateral, cdpInfo.coll);
```

This actually checks that:

```solidity
	check.value = _totalCollateral * _collValidationBuffer / BPS >= cdpInfo.coll
```

According to the sponsor, this is used as a `laxer check post swap`: when you expect after openCdp, the collateral will be 5 stETH, setting it to `100%` will ensure that the collateral is at least 5 stETH.

This is not consistent with what is checking here and thus it is an invalid check which will cause unexpected revert and prevent the protocol from working correctly.


## Tools Used

Manual

## Recommended Mitigation Steps

Change the operator from `gte` to `lte`.


## Assessed type

Invalid Validation
`_depositRawEthIntoLido` doesn't check for after - before balance, can lead to first depositor vulnerability
Audit: 2024-06-badger-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-06-badger/blob/9173558ee1ac8a78a7ae0a39b97b50ff0dd9e0f8/ebtc-zap-router/src/ZapRouterBase.sol#L34-L41


# Vulnerability details

## Summary

_depositRawEthIntoLido doesn't check for after - before balance

## Vulnerability Details

In the function `_depositRawEthIntoLido ` from the comment `// check before-after balances for 1-wei corner case` , we can infer that the function is supposed to check for the balance of token before and after the deposit of raw Eth in Lido. 

Let us consider at this stage we have `10 stEth` as current balance and `_initialETH = 5`, and if we simulate the `_depositRawEthIntoLido ` with the assumed valued we get

```solidity
_initialETH = 5
 _balBefore = 10 //gets current stEth balance of contract
payable(address(stEth)).call{value: 5}("") // transfers 5stEth
//current balance = 10 + 5 = 15 stEth
_deposit= 15-10//gets amount of stEth deposited 
 ```
As we can see the function just checks balance of the contract before the transfer and the amount deposited to the contract. And doesn't checks the balance of contract after and before the transfer.

## Impact

Function can be susceptible to first depositor vulnerability or 1-wei corner case

## Proof of  code

```solidity
    function _depositRawEthIntoLido(uint256 _initialETH) internal returns (uint256) {
        // check before-after balances for 1-wei corner case
        uint256 _balBefore = stEth.balanceOf(address(this));
        // TODO call submit() with a referral?
        payable(address(stEth)).call{value: _initialETH}("");
        uint256 _deposit = stEth.balanceOf(address(this)) - _balBefore;
        return _deposit;
    }

```
https://github.com/code-423n4/2024-06-badger/blob/9173558ee1ac8a78a7ae0a39b97b50ff0dd9e0f8/ebtc-zap-router/src/ZapRouterBase.sol#L34-L41

## Tools Used 

Manual review

## Recommended Mitigation

Check the after and before balance of the contract after transfers.



## Assessed type

Context
`LeverageMacroBase::_doOperation` will revert if `willSweep` is set to true
Audit: 2024-06-badger-findings
Severity: MEDIUM

# Lines of code

https://github.com/ebtc-protocol/ebtc/blob/2da05f2d1354190eacf64ec256d2c5c5358e5fa2/packages/contracts/contracts/LeverageMacroBase.sol#L241-L243
https://github.com/ebtc-protocol/ebtc/blob/2da05f2d1354190eacf64ec256d2c5c5358e5fa2/packages/contracts/contracts/LeverageMacroBase.sol#L248
https://github.com/ebtc-protocol/ebtc/blob/2da05f2d1354190eacf64ec256d2c5c5358e5fa2/packages/contracts/contracts/LeverageMacroBase.sol#L43-L46


# Vulnerability details

`LeverageMacroBase.sol` has an internal function `_doOperation` that handles the execution of the CDP operation requested by an user, which can be opening a CDP, adjusting a CDP or closing a CDP. 

`LeverageMacroBase::_doOperation`

```solidity
function _doOperation(
        FlashLoanType flType,
        uint256 borrowAmount,
        LeverageMacroOperation memory operation,
        PostOperationCheck postCheckType,
        PostCheckParams memory checkParams,
        bytes32 expectedCdpId
    ) internal {
        // Call FL Here, then the stuff below needs to happen inside the FL
        if (operation.amountToTransferIn > 0) {
            IERC20(operation.tokenToTransferIn).safeTransferFrom(
                msg.sender,
                address(this),
                operation.amountToTransferIn
            );
        }

        // Take eBTC or stETH FlashLoan
        if (flType == FlashLoanType.eBTC) {
            IERC3156FlashLender(address(borrowerOperations)).flashLoan(
                IERC3156FlashBorrower(address(this)),
                address(ebtcToken),
                borrowAmount,
                abi.encode(operation)
            );
        } else if (flType == FlashLoanType.stETH) {
            IERC3156FlashLender(address(activePool)).flashLoan(
                IERC3156FlashBorrower(address(this)),
                address(stETH),
                borrowAmount,
                abi.encode(operation)
            );
        } else {
            // No leverage, just do the operation
            _handleOperation(operation);
        }
```

After handling the operation, the `_doOperation` function performs post-operation checks to ensure that the CDP position values, such as debt and collateral, are as expected post-operation execution.

```solidity
				/**
         * POST CALL CHECK FOR CREATION
         */
        if (postCheckType == PostOperationCheck.openCdp) {
            // Check for param details
            ICdpManagerData.Cdp memory cdpInfo = cdpManager.Cdps(expectedCdpId);
            _doCheckValueType(checkParams.expectedDebt, cdpInfo.debt);
            _doCheckValueType(checkParams.expectedCollateral, cdpInfo.coll);
            require(
                cdpInfo.status == checkParams.expectedStatus,
                "!LeverageMacroReference: openCDP status check"
            );
        }

        // Update CDP, Ensure the stats are as intended
        if (postCheckType == PostOperationCheck.cdpStats) {
            ICdpManagerData.Cdp memory cdpInfo = cdpManager.Cdps(checkPa
Staking ETH incorrectly assumes revert bubbling
Audit: 2024-06-badger-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-06-badger/blob/9173558ee1ac8a78a7ae0a39b97b50ff0dd9e0f8/ebtc-zap-router/src/ZapRouterBase.sol#L38-L38


# Vulnerability details

## Impact
When `EbtcLeverageZapRouter::openCdpWithEth` and `EbtcLeverageZapRouter::adjustCdpWithEth` stake ETH with Lido, the underlying function performing the call assumes that any exceptions (from Lido) will be bubbled up, but with call being a low level rather than a Solidity function, it is not the case.

Lido stETH has two cases where a revert on depositing ETH for staking may be encountered, when deposits are paused or when staking limits are enabled and it is exceeded.

If Lido returns a revert it is ignored and the entire CDP flow continues (permits, flash loans, account synching, CDP initialization, eBTC minting), with a revert only being cause only by one of the last step of the flow, moving the collateral to the active pool. 



## Proof of Concept
The two parts to the issue:
1. Any possibility of reverts during staking ETH with Lido 
2. Incorrect assumption that revert would bubble

#### 1. Lido deposit could revert
Lido has pausable staking on [Ethereum stETH]](https://etherscan.io/address/0x17144556fd3424edc8fc8a4c940b2d04936d17eb#code#F1#L324)
```solidity
    /**
     * @notice Stops accepting new Ether to the protocol
     *
     * @dev While accepting new Ether is stopped, calls to the `submit` function,
     * as well as to the default payable function, will revert.
     *
     * Emits `StakingPaused` event.
     */
    function pauseStaking() external {
```

Lido can impose a per block stake limit on [Ethereum stETH](https://etherscan.io/address/0x17144556fd3424edc8fc8a4c940b2d04936d17eb#code#F1#L368)
```solidity
     * @dev Reverts if:
     * - `_maxStakeLimit` == 0
     * - `_maxStakeLimit` >= 2^96
     * - `_maxStakeLimit` < `_stakeLimitIncreasePerBlock`
     * - `_maxStakeLimit` / `_stakeLimitIncreasePerBlock` >= 2^32 (only if `_stakeLimitIncreasePerBlock` != 0)
     *
     * Emits `StakingLimitSet` event
     *
     * @param _maxStakeLimit max stake limit value
     * @param _stakeLimitIncreasePerBlock stake limit increase per single block
     */
    function setStakingLimit(uint256 _maxStakeLimit, uint256 _stakeLimitIncreasePerBlock) external {
```

Both these cause the same effect; a possible revert during the submit of ETH for staking with [Ethereum stETH](https://etherscan.io/address/0x17144556fd3424edc8fc8a4c940b2d04936d17eb#code#F1#L922)
```solidity
    function _submit(address _referral) internal returns (uint256) {
        require(msg.value != 0, "ZERO_DEPOSIT");

        StakeLimitState.Data memory stakeLimitData = STAKING_STATE_POSITION.getStorageStakeLimitStruct();
        // There is an invariant that protocol pause also implies staking pause.
        // Thus, no need to check protocol pause explicitly.
@>      require(!stakeLimitData.isStakingPaused(), "STAKING_PAUSED");

        if (stakeLimitData.isStakingLimitSet()) {
openCdp，adjustCdp Sliding point control may fail
Audit: 2024-06-badger-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-06-badger/blob/9173558ee1ac8a78a7ae0a39b97b50ff0dd9e0f8/ebtc-zap-router/src/LeverageZapRouterBase.sol#L268


# Vulnerability details

## Impact
_The getPostCheckParams function provides a parameter to control the sliding point, _collValidationBuffer.
However, since the coll balance used in the calculation is the balance at the time of the transaction, the sliding point control may become ineffective
## Proof of Concept
_ExpectedCollective in getPostCheckParams for controlling stock slip points

```solidity
    function _getPostCheckParams(
        bytes32 _cdpId,
        uint256 _debt,
        uint256 _totalCollateral,
        ICdpManagerData.Status _status,
        uint256 _collValidationBuffer
    ) internal view returns (PostCheckParams memory) {
        return
            PostCheckParams({
                expectedDebt: CheckValueAndType({value: _debt, operator: Operator.equal}),
                expectedCollateral: CheckValueAndType({
                    value:  _totalCollateral * _collValidationBuffer / BPS,
                    operator: Operator.gte
                }),
                cdpId: _cdpId,
                expectedStatus: _status
            });
    }
```
But in openCdp, the adjustCdp function passes in the number of shares obtained in the transaction instead of pre entered by the user when generating the check parameters. This may lead to sliding point failure.
github:[https://github.com/code-423n4/2024-06-badger/blob/9173558ee1ac8a78a7ae0a39b97b50ff0dd9e0f8/ebtc-zap-router/src/LeverageZapRouterBase.sol#L132](https://github.com/code-423n4/2024-06-badger/blob/9173558ee1ac8a78a7ae0a39b97b50ff0dd9e0f8/ebtc-zap-router/src/LeverageZapRouterBase.sol#L132)
```solidity
    function _adjustCdpOperation(
        bytes32 _cdpId,
        FlashLoanType _flType,
        uint256 _flAmount,
        AdjustCdpOperation memory _cdp,
        uint256 debt,
        uint256 coll,
        TradeData calldata _tradeData
    ) internal {
        uint256 newDebt = _cdp._isDebtIncrease ? debt + _cdp._EBTCChange : debt - _cdp._EBTCChange;
***        uint256 newColl = _cdp._stEthBalanceIncrease > 0 ? 
            coll + stEth.getSharesByPooledEth(_cdp._stEthBalanceIncrease) : 
            coll - stEth.getSharesByPooledEth(_cdp._stEthBalanceDecrease);

        _doOperation(
            _flType,
            _flAmount,
            _getAdjustCdpParams(_cdp, _tradeData),
            PostOperationCheck.cdpStats,
            _getPostCheckParams(
                _cdpId, 
                newDebt, 
***                newColl, 
                ICdpManagerData.Status.active,
                _tradeData.collValidationBufferBPS
            ),
            _cdpId
        );
```
github:[https://github.com/code-423n4/2024-06-badger/blob/9173558ee1ac8a78a7ae0a39b97b50ff0dd9e0f8/ebtc-zap-router/src/LeverageZapRouterBase.sol#L165](https://github.com/code-423n4/2024-06-badger/blob/9173558ee1ac8a78a7ae0a39b97b50ff0dd9e0f8/ebtc-zap-rou
test
Audit: 2024-06-badger-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-06-badger/blob/22de3b03bbb2fc4f04c362d29a2cfb4211235884/ebtc-zap-router/src/EbtcLeverageZapRouter.sol#L34


# Vulnerability details

## Impact
Detailed description of the impact of this finding.

## Proof of Concept
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.

## Tools Used

## Recommended Mitigation Steps


## Assessed type

Access Control
Custom redemption might revert if old assets were unregistered
Audit: 2023-06-reserve-findings
Severity: HIGH

# Lines of code

https://github.com/reserve-protocol/protocol/blob/c4ec2473bbcb4831d62af55d275368e73e16b984/contracts/p1/BasketHandler.sol#L391-L392


# Vulnerability details

`quoteCustomRedemption()` works under the assumption that the maximum size of the `erc20sAll` should be `assetRegistry.size()`, however there can be cases where an asset was unregistered but still exists in an old basket, making the size of the old basket greater than `assetRegistry.size()`. In that case the function will revert with an index out of bounds error.

## Impact
Users might not be able to use `redeemCustom` when needed.

I think this should be considered high severity, since being able to redeem the token at all time is an essential feature for the protocol that's allowed also while frozen.
Not being able to redeem can result in a depeg or in governance becoming malicious and stealing RToken collateral.

## Proof of Concept
Consider the following scenario:
* RToken deployed with 0.9 USDC, 0.05 USDT, 0.05 DAI
* Governance passed a vote to change it to 0.9 DAI and 0.1 USDC and un-register USDT
* Trading is paused before execution, so the basket switch occurs but the re-balance can't be executed. Meaning the actual assets that the backing manager holds are in accordance with the old basket
* A user wants to redeem using the old basket, but custom redemption reverts

As for the revert:
* `erc20sAll` is created [here](https://github.com/reserve-protocol/protocol/blob/c4ec2473bbcb4831d62af55d275368e73e16b984/contracts/p1/BasketHandler.sol#L391-L392) with the length of `assetRegistry.size()`, which is 2 in our case.
* Then in [this loop](https://github.com/reserve-protocol/protocol/blob/c4ec2473bbcb4831d62af55d275368e73e16b984/contracts/p1/BasketHandler.sol#L397-L428) the function tries to push 3 assets into `erc20sAll` which will result in an index-out-of-bonds error

(the function doesn't include in the final results assets that aren't registered, but it does push them too into `erc20sAll`)


## Recommended Mitigation Steps
Allow the user to specify the length of the array `erc20sAll` to avoid this revert


## Assessed type

Other
A new era might be triggered despite a significant value being held in the previous era
Audit: 2023-06-reserve-findings
Severity: HIGH

# Lines of code

https://github.com/reserve-protocol/protocol/blob/c4ec2473bbcb4831d62af55d275368e73e16b984/contracts/p1/StRSR.sol#L441-L444
https://github.com/reserve-protocol/protocol/blob/c4ec2473bbcb4831d62af55d275368e73e16b984/contracts/p1/StRSR.sol#L457-L460


# Vulnerability details



When RSR seizure occurs the staking and drafting rate is adjusted accordingly, if any of those rates is above some threshold then a new era begins (draft or staking era accordingly), wiping out all of the holdings of the current era.
The assumption is that if the rate is above the threshold then there's not much staking or drafts left after the seizure (and therefore it makes sense to begin a new era). 
However, there might be a case where a previous seizure has increased the staking/draft rate close to the threshold, and then even a small seizure would make it cross this threshold. In that case the total value of staking or drafts can be very high, and they will all be wiped out by starting a new era.

## Impact
Stakers will lose their holdings or pending drafts.

## Proof of Concept
Consider the following scenario:
* Max stake rate is 1e9
* A seizure occurs and the new rate is now 91e7
* Not much staking is left after the seizure, but as time passes users keep staking bring back the total stakes to a significant value
* A 10% seizure occurs, this causes the staking rate to cross the threshold (getting to 1.01e9) and start a new era

This means the stakings were wiped out despite holding a significant amount of value, causing a loss for the holders.


## Recommended Mitigation Steps

This one is a bit difficult to mitigate.
One way I can think of is to add a 'migration' feature, where in such cases a new era would be created but users would be able to transfer the funds that they held in the previous era into the new era. But this would require some significant code changes and checking that this doesn't break anything or introduces new bugs.


## Assessed type

Other
A Dutch trade could end up with an unintended lower closing price
Audit: 2023-06-reserve-findings
Severity: MEDIUM

# Lines of code

https://github.com/reserve-protocol/protocol/blob/c4ec2473bbcb4831d62af55d275368e73e16b984/contracts/plugins/trading/DutchTrade.sol#L160
https://github.com/reserve-protocol/protocol/blob/c4ec2473bbcb4831d62af55d275368e73e16b984/contracts/p1/RevenueTrader.sol#L46
https://github.com/reserve-protocol/protocol/blob/c4ec2473bbcb4831d62af55d275368e73e16b984/contracts/p1/BackingManager.sol#L81


# Vulnerability details

## Impact
`notTradingPausedOrFrozen` that is turned on and off during an open Dutch trade could have the auction closed with a lower price depending on the timimg, leading to lesser capability to boost the Rtoken and/or stRSR exchange rates as well as a weakened recollaterization.  

## Proof of Concept
Here's the scenario:

1. A 30 minute Dutch trade is opened by the Revenue trader selling a suplus token for Rtoken.

2. Shortly after the price begins to decrease linearly, Alice calls [`bid()`](https://github.com/reserve-protocol/protocol/blob/c4ec2473bbcb4831d62af55d275368e73e16b984/contracts/plugins/trading/DutchTrade.sol#L146-L164). As can be seen in line 160 of the code block below, `settleTrade()` is externally called on the `origin`, RevenueTrader.sol in this case:

```solidity
    function bid() external returns (uint256 amountIn) {
        require(bidder == address(0), "bid already received");

        // {qBuyTok}
        amountIn = bidAmount(uint48(block.timestamp)); // enforces auction ongoing

        // Transfer in buy tokens
        bidder = msg.sender;
        buy.safeTransferFrom(bidder, address(this), amountIn);

        // status must begin OPEN
        assert(status == TradeStatus.OPEN);

        // settle() via callback
160:        origin.settleTrade(sell);

        // confirm callback succeeded
        assert(status == TradeStatus.CLOSED);
    }
```

3. However, her call is preceded by [`pauseTrading()`](https://github.com/reserve-protocol/protocol/blob/c4ec2473bbcb4831d62af55d275368e73e16b984/contracts/mixins/Auth.sol#L169-L172) invoked by a `PAUSER`, and denied on line 46 of the function below:

https://github.com/reserve-protocol/protocol/blob/c4ec2473bbcb4831d62af55d275368e73e16b984/contracts/p1/RevenueTrader.sol#L43-L52

```solidity
    function settleTrade(IERC20 sell)
        public
        override(ITrading, TradingP1)
46:        notTradingPausedOrFrozen
        returns (ITrade trade)
    {
        trade = super.settleTrade(sell); // nonReentrant
        distributeTokenToBuy();
        // unlike BackingManager, do _not_ chain trades; b2b trades of the same token are unlikely
    }
```
4. As the auction is nearing to `endTime`, the `PAUSER` calls [`unpauseIssuance()`](https://github.com/reserve-protocol/protocol/blob/c4ec2473bbcb4831d62af55d275368e73e16b984/contracts/mixins/Auth.sol#L176-L179).

5. Bob, the late comer, upon seeing this, proceeds to calling `bid()` and gets the sell token for a price much lower than he would initially expect before the trading pause.
 
## Tools Used
Manual

##