eye Q

# Summary

The **setCollateralParams** function in the **CollateralConfig** contract in the **Ethos-Core** repository lacks input validation, which could allow an attacker to manipulate collateral parameters for a given asset.

# Description

The **CollateralConfig** contract in the **Ethos-Core** repository is used to manage **collateral** parameters for different assets in the protocol. The **setCollateralParams** function in this contract is responsible for setting the collateral parameters for a given asset, including the **liquidationDiscount**, **liquidationRatio**, and **borrowingEnabled** parameters.
However, the **setCollateralParams** function does not perform any input validation on the values passed as parameters. This means that an attacker could potentially pass in invalid or unexpected values for these parameters, which could allow them to manipulate the market for a given asset and potentially profit from their actions.

# Snippet

```
function setCollateralParams(
    address collateralType,
    uint256 liquidationDiscount,
    uint256 liquidationRatio,
    bool borrowingEnabled
) external onlyOwner {
    require(collateralType != address(0), "CollateralConfig: invalid collateral type");

    collateralTypes[collateralType].liquidationDiscount = liquidationDiscount;
    collateralTypes[collateralType].liquidationRatio = liquidationRatio;
    collateralTypes[collateralType].borrowingEnabled = borrowingEnabled;
}

```

# Fix

To address this issue, input validation should be added to the setCollateralParams function to ensure that the values passed as parameters are valid and within acceptable ranges. This could include range checks, type checks, and other forms of input validation to ensure that the values passed as parameters are safe and secure.

In this example, a check has been added to ensure that the **liquidationDiscount** value is not greater than 100, which is the maximum value that this parameter can have. This check ensures that the in

function setCollateralParams(
    address collateralType,
    uint256 liquidationDiscount,
    uint256 liquidationRatio,
    bool borrowingEnabled
) external onlyOwner {
    require(collateralType != address(0), "CollateralConfig: invalid collateral type");

    // Validate the liquidation discount value
    require(liquidationDiscount <= 100, "CollateralConfig: liquidation discount cannot exceed 100");

    collateralTypes[collateralType].liquidationDiscount = liquidationDiscount;
    collateralTypes[collateralType].liquidationRatio = liquidationRatio;
    collateralTypes[collateralType].borrowingEnabled = borrowingEnabled;
}

// Code block 1 (unknown):
function setCollateralParams(
    address collateralType,
    uint256 liquidationDiscount,
    uint256 liquidationRatio,
    bool borrowingEnabled
) external onlyOwner {
    require(collateralType != address(0), "CollateralConfig: invalid collateral type");

    collateralTypes[collateralType].liquidationDiscount = liquidationDiscount;
    collateralTypes[collateralType].liquidationRatio = liquidationRatio;
    collateralTypes[collateralType].borrowingEnabled = borrowingEnabled;
}


peanuts Analysis

### 1. Any comments for the judge to contextualize your findings
- Focused on the rUSDY and Destination Bridge contract, and followed through with all the test files for those contracts

### 2. Approach taken in evaluating the codebase
- Understood the relation between USDY,rUSDY and shares first, then check all the functions in rUSDY to make sure that they are working as intended and cannot be exploited easily
- Run the test files of rUSDY and run some fuzz testing to make sure that wrap() and unwrap() works as intended with different time stamp and oracle price
- Moved on to the source and destination bridge and ran the tests
- Made sure that the test are properly written and focused on the setThresholds() function in Destination contract
- Zoomed out and looked at all the contracts as a whole to check whether all contracts and imports are written correctly, and all contracts have the pause function as well as being protected by the modifier.

### 3. Mechanism review
- I don't think that rUSDY can be called a rebasing token because it is not pegged to USDY but rather to the dollar. Also, the price of rUSDY is taken from the oracle of USDY, so it's more like a vault token than a rebasing token
- There is a part in the rUSDY contract that has a truncation to zero issue. If the shares passed into getRUSDYByShares() is less than 10,000 and the oracle returns the price of 1e18, then the price of RUSDYByShares will be zero. Minimal loss as only dust amounts will be lost

```
  function getRUSDYByShares(uint256 _shares) public view returns (uint256) {
    return (_shares * oracle.getPrice()) / (1e18 * BPS_DENOMINATOR);
  }
```
- In the Destination contract, there is a heavy emphasis on restricting users from minting the token on the destination chain. The restriction includes having the need to have approvals and having a rate limiter with a maxTokenlimit
```
      _checkAndUpdateInstantMintLimit(txn.amount);
```

### 4. Centralization Risk

- The owner can burn the r

// Code block 1 (unknown):
function getRUSDYByShares(uint256 _shares) public view returns (uint256) {
    return (_shares * oracle.getPrice()) / (1e18 * BPS_DENOMINATOR);
  }

// Code block 2 (unknown):
_checkAndUpdateInstantMintLimit(txn.amount);


Rolezn G

## Summary<a name="Summary">

### Gas Optimizations
| |Issue|Contexts|Estimated Gas Saved|
|-|:-|:-|:-:|
| [GAS‑1](#GAS‑1) | `abi.encode()` is less efficient than `abi.encodepacked()` | 2 | 200 |
| [GAS‑2](#GAS‑2) | Setting the `constructor` to `payable` | 4 | 52 |
| [GAS‑3](#GAS‑3) | Do not calculate constants | 2 | - |
| [GAS‑4](#GAS‑4) | Duplicated `require()`/`revert()` Checks Should Be Refactored To A Modifier Or Function | 6 | 168 |
| [GAS‑5](#GAS‑5) | Using fixed bytes is cheaper than using `string` | 9 | - |
| [GAS‑6](#GAS‑6) | Using `delete` statement can save gas | 19 | - |
| [GAS‑7](#GAS‑7) | Use `assembly` to write address storage values | 2 | - |
| [GAS‑8](#GAS‑8) | Use hardcoded address instead `address(this)` | 34 | - |
| [GAS‑9](#GAS‑9) | `internal` functions only called once can be inlined to save gas | 4 | 88 |
| [GAS‑10](#GAS‑10) | Optimize names to save gas | 11 | 242 |
| [GAS‑11](#GAS‑11) | `<x> += <y>` Costs More Gas Than `<x> = <x> + <y>` For State Variables | 21 | - |
| [GAS‑12](#GAS‑12) | Structs can be packed into fewer storage slots by editing time variables and uint variables | 1 | 8000 |
| [GAS‑13](#GAS‑13) | Public Functions To External | 28 | - |
| [GAS‑14](#GAS‑14) | `require()` Should Be Used Instead Of `assert()` | 20 | - |
| [GAS‑15](#GAS‑15) | Save gas with the use of specific import statements | 96 | - |
| [GAS‑16](#GAS‑16) | Shorten the array rather than copying to a new one | 4 | - |
| [GAS‑17](#GAS‑17) | State variables can be packed into fewer storage slots | 1 | 2000 |
| [GAS‑18](#GAS‑18) | Help The Optimizer By Saving A Storage Variable’s Reference Instead Of Repeatedly Fetching It | 9 | - |
| [GAS‑19](#GAS‑19) | Superfluous event fields | 1 | - |
| [GAS‑2

305: return keccak256(abi.encode(typeHash, name, version, _chainID(), address(this)));


ABA Q

# QA Report for Caviar Private Pools contest

## Overview
During the audit, 3 low, 6 refactoring and 1 non-critical issues were found.

### Low Risk Issues

Total: 10 instances over 3 issues

|#|Issue|Instances|
|-|:-|:-:|
| [L-01] | Input is not checked when setting sensitive addresses across protocol | 4 |
| [L-02] | Any leftover ETH on `EthRouter` can be taken with empty buy/change orders | 2 |
| [L-03] | Precision loss on royalties payments | 4 |

### Refactoring Issues

Total: 10 instances over 6 issues

|#|Issue|Instances|
|-|:-|:-:|
| [R-01]| Events missing key information | 3 |
| [R-02]| Inconsistent checks for `royaltyRecipient` | 2 |
| [R-03]| Reuse `getRoyalty` implementation | 2 |
| [R-04]| Use a constant for the flashLoan callback keccak256 | 1 |
| [R-05]| Combine royalty transfer logic and ERC721 transfer logic in `PrivatePool`'s `buy` function | 1 |
| [R-06]| `buyQuote` reverts with arithmetic underflow instead of meaningful message | 1 |

### Non-critical Issues

Total: 2 instances over 1 issues

|#|Issue|Instances|
|-|:-|:-:|
| [NC-01]| misleading or incorrect documentation | 2 |

#
## Low Risk Issues (3)
#

### [L-01] Input is not checked when setting sensitive addresses across protocol
##### Description

- in `Factory`, when setting the `privatePoolMetadata` or `privatePoolImplementation` addresses, there is no check if the new address is 0 or that it is actually a contract.
- in `EthRouter` when deploying the contract, the `royaltyRegistry` variable is set, but not checked if the provided address is 0 or that it is actually a contract.
- in `PrivatePool` when deploying the contract, the factory, royaltyRegistry and stolenNftOracle are set but not checked if the provided address is 0 or that it is actually a contract.

##### Instances (4)

https://github.com/code-423n4/2023-04-caviar/blob/main/src/Factory.sol#L127-L137
```Solidity
    /// @notice Sets private pool metadata contract.
    /// @param _privatePoolMetadata The private pool metadata con

    /// @notice Sets private pool metadata contract.
    /// @param _privatePoolMetadata The private pool metadata contract.
    function setPrivatePoolMetadata(address _privatePoolMetadata) public onlyOwner {
        privatePoolMetadata = _privatePoolMetadata;
    }

    function buy(Buy[] calldata buys, uint256 deadline, bool payRoyalties) public payable {
        // check that the deadline has not passed (if any)
        if (block.timestamp > deadline && deadline != 0) {
            revert DeadlinePassed();
        }

        // loop through and execute the the buys
        for (uint256 i = 0; i < buys.length; i++) {
            // as buys ca be empty this code block is skipped
        }

        // refund any surplus ETH to the caller
        if (address(this).balance > 0) {
            msg.sender.safeTransferETH(address(this).balance);
        }
    }


Rickard Q

# [L-01] Use `safeTransferOwnership` instead of `_transferOwnership` function
## Lines of code
[https://github.com/code-423n4/2023-03-asymmetry/blob/main/contracts/SafEth/derivatives/WstEth.sol#L34](https://github.com/code-423n4/2023-03-asymmetry/blob/main/contracts/SafEth/derivatives/WstEth.sol#L34)
[https://github.com/code-423n4/2023-03-asymmetry/blob/main/contracts/SafEth/SafEth.sol#L53](https://github.com/code-423n4/2023-03-asymmetry/blob/main/contracts/SafEth/SafEth.sol#L53)
[https://github.com/code-423n4/2023-03-asymmetry/blob/main/contracts/SafEth/derivatives/Reth.sol#L43](https://github.com/code-423n4/2023-03-asymmetry/blob/main/contracts/SafEth/derivatives/Reth.sol#L43)
[https://github.com/code-423n4/2023-03-asymmetry/blob/main/contracts/SafEth/derivatives/SfrxEth.sol#L37](https://github.com/code-423n4/2023-03-asymmetry/blob/main/contracts/SafEth/derivatives/SfrxEth.sol#L37)
## Vulnerability details
`_transferOwnership` function is used to change Ownership from `OwnableUpgradeable.sol`.

Use a 2 structure `_transferOwnership` which is safer. `safeTransferOwnership`, use is more secure due to 2-stage ownership transfer.
### Recommended Mitigation Steps
Use [Ownable2Step.sol](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable2Step.sol).

# [L-02] Lack of checks `address(0)`
## Lines of code
[https://github.com/code-423n4/2023-03-asymmetry/blob/main/contracts/SafEth/derivatives/Reth.sol#L93-L94](https://github.com/code-423n4/2023-03-asymmetry/blob/main/contracts/SafEth/derivatives/Reth.sol#L93-L94)
## Vulnerability details
The following methods have a lack of checks if the received argument is an address, it’s good practice in order to reduce human error to check that the address specified in the constructor or initialize is different than `address(0)`.

# [L-03] Missing ReEntrancy Guard to withdraw function
## Lines of code
[https://github.com/code-423n4/2023-03-asymmetry/blob/main/contracts

contracts/SafEth/derivatives/Reth.sol
    function withdraw(uint256 amount) external onlyOwner {
        RocketTokenRETHInterface(rethAddress()).burn(amount);
        // solhint-disable-next-line
        (bool sent, ) = address(msg.sender).call{value: address(this).balance}(
            ""
        );
        require(sent, "Failed to send Ether");
    }

contracts/SafEth/derivatives/SfrxEth.sol
    function withdraw(uint256 _amount) external onlyOwner {
        IsFrxEth(SFRX_ETH_ADDRESS).redeem(
            _amount,
            address(this),
            address(this)
        );
        uint256 frxEthBalance = IERC20(FRX_ETH_ADDRESS).balanceOf(
            address(this)
        );
        IsFrxEth(FRX_ETH_ADDRESS).approve(
            FRX_ETH_CRV_POOL_ADDRESS,
            frxEthBalance
        );

        uint256 minOut = (((ethPerDerivative(_amount) * _amount) / 10 ** 18) *
            (10 ** 18 - maxSlippage)) / 10 ** 18;

        IFrxEthEthPool(FRX_ETH_CRV_POOL_ADDRESS).exchange(
            1,
            0,
            frxEthBalance,
            minOut
        );
        // solhint-disable-next-line
        (bool sent, ) = address(msg.sender).call{value: address(this).balance}(
            ""
        );
        require(sent, "Failed to send Ether");
    }

contracts/SafEth/derivatives/WstEth.sol
    function withdraw(uint256 _amount) external onlyOwner {
        IWStETH(WST_ETH).unwrap(_amount);
        uint256 stEthBal = IERC20(STETH_TOKEN).balanceOf(address(this));
        IERC20(STETH_TOKEN).approve(LIDO_CRV_POOL, stEthBal);
        uint256 minOut = (stEthBal * (10 ** 18 - maxSlippage)) / 10 ** 18;
        IStEthEthPool(LIDO_CRV_POOL).exchange(1, 0, stEthBal, minOut);
        // solhint-disable-next-line
        (bool sent, ) = address(msg.sender).call{value: address(this).balance}(
            ""
        );
        require(sent, "Failed to send Ether");
    }

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
contract ReEntrancyGuard {
    bool internal locked;
    modifier noReentrant() {
        require(!locked, "No re-entrancy");
        locked = true;
        _;
        locked = false;
    }
}

WstEth.sol#L34, SafEth.sol#L53, Reth.sol#L43, SfrxEth.sol#L37, Ownable2Step.sol, Reth.sol#L93-L94

SfrxEth.sol, Reth.sol, WstEth.sol, SafEth.sol, Ownable2Step.sol


2997ms G

## [G-01] Remove the `initializer` modifier

If we can just ensure that the `initialize()` function could only be called from within the constructor, we shouldn’t need to worry about it getting called again.

https://github.com/code-423n4/2023-02-ethos/blob/34ba1e7dd2d259f06f9d5fa13f5d96be7829ff34/Ethos-Vault/contracts/ReaperStrategyGranarySupplyOnly.sol#L63

In the EVM, the constructor’s job is actually to return the bytecode that will live at the contract’s address. So, while inside a constructor, your address `(address(this))` will be the deployment address, but there will be no bytecode at that address. So if we check `address(this).code.length` before the constructor has finished, even from within a delegatecall, we will get 0. So now let’s update our `initialize()` function to only run if we are inside a constructor:

```
 function initialize(
        address _vault,
        address[] memory _strategists,
        address[] memory _multisigRoles,
        IAToken _gWant
    ) public initializer {
+ require(address(this).code.length == 0, 'not in constructor');
```

Now the Proxy contract’s constructor can still delegatecall initialize(), but if anyone attempts to call it again (after deployment) through the Proxy instance, or tries to call it directly on the above instance, it will revert because address(this).code.length will be nonzero.

Also, because we no longer need to write to any state to track whether initialize() has been called, we can avoid the 20k storage gas cost. In fact, the cost for checking our own code size is only 2 gas, which means we have a 10,000x gas savings over the standard version. Pretty neat.

## [G-02] Reduce the size of error messages (Long revert Strings)

Shortening revert strings to fit in 32 bytes will decrease deployment time gas and will decrease runtime gas when the revert condition is met.

Revert strings that are longer than 32 bytes require at least one additional mstore, along with additional overhead for com

// Code block 1 (unknown):
function initialize(
        address _vault,
        address[] memory _strategists,
        address[] memory _multisigRoles,
        IAToken _gWant
    ) public initializer {
+ require(address(this).code.length == 0, 'not in constructor');


favelanky G

## Summary

### Gas Optimizations
|               | Issue                                                                                | Instances | Total Gas Saved |
| ------------- |:-------------------------------------------------------------------------------------------- |:---------:|:---------------:|
| [G-01] | `require()`  statements that check input arguments should be at the top of the function      |     11     |      >2100       |
| [G-02] | Use  `require` instead of `assert`                                                           |    20     |        -      |
| [G-03] | `internal` functions only called once can be inlined to save gas                        |     28    |       560       |
| [G-04] |  Structs can be packed into fewer storage slots                                               |     6     |       12000       |
| [G-05] | Using fixed `bytes` is cheaper than using `string` |    6       |  -    |
| [G-06] |   State variables should be cached in stack variables rather than re-reading them from storage |    12     |        ~1200        |
| [G-07] | Splitting require() statements that use && saves gas                                         |     7     |       21       |
| [G-08] |  Multiple address mappings can be combined into a single mapping of an address to a struct, where appropriate     |     3     |        -        |

Total: 93 instances over 8 issues with >15881 **gas** saved.

## Gas Optimizations:

### [G-01] `require()`  statements that check input arguments should be at the top of the function

Checks that involve constants should come before checks that involve state variables, function calls, and calculations. By doing these checks first, the function is able to revert before wasting a Gcoldsload (**2100 gas**) in a function that may ultimately revert in the unhappy case.

_There are 11 instance of this issue:_

```Solidity
File: contracts/CollateralConfig.sol

66:             require(_MCRs[i] >= MIN_ALLOWED_MCR, "MCR

File: contracts/CollateralConfig.sol

66:             require(_MCRs[i] >= MIN_ALLOWED_MCR, "MCR below allowed minimum");

69:             require(_CCRs[i] >= MIN_ALLOWED_CCR, "CCR below allowed minimum");

94:             require(_MCR >= MIN_ALLOWED_MCR, "MCR below allowed minimum");

97:             require(_CCR >= MIN_ALLOWED_CCR, "CCR below allowed minimum");

File: contracts/ActivePool.sol

93:     require(_treasuryAddress != address(0), "Treasury cannot be 0 address");

107:    require(numCollaterals == _erc4626vaults.length, "Vaults array length must match number of collaterals");

111:    require(IERC4626(vault).asset() == collateral, "Vault asset must be collateral");

127:    require(_bps <= 10_000, "Invalid BPS value");


debo Q

## [L-01]
SWC-115 Authorization through tx.origin

File
```
/contracts/smart-contract-wallet/SmartAccount.sol
```

URL
```
https://github.com/code-423n4/2023-01-biconomy/blob/53c8c3823175aeb26dee5529eeefa81240a406ba/scw-contracts/contracts/smart-contract-wallet/SmartAccount.sol#L257
```

Transaction origin
```
Use of tx.origin: "tx.origin" is useful only in very exceptional cases.
If you use it for authentication, you usually want to replace it by "msg.sender", because otherwise any contract you call can act on your behalf.
Using "tx.origin" as a security control can lead to authorization bypass vulnerabilities. Consider using "msg.sender" unless you really know what you are doing.
```

PoC
Current code
```
address payable receiver = refundReceiver == address(0) ? payable(tx.origin) : refundReceiver;
```

Remediation
tx.origin should not be used for authorization. Use msg.sender instead.
```
address payable receiver = refundReceiver == address(0) ? payable(msg.sender) : refundReceiver;
```

## [L-02]
SWC-115 Authorization through tx.origin

File
```
/contracts/smart-contract-wallet/SmartAccount.sol
```

URL
```
https://github.com/code-423n4/2023-01-biconomy/blob/53c8c3823175aeb26dee5529eeefa81240a406ba/scw-contracts/contracts/smart-contract-wallet/SmartAccount.sol#L281
```

Transaction origin
```
Use of tx.origin: "tx.origin" is useful only in very exceptional cases.
If you use it for authentication, you usually want to replace it by "msg.sender", because otherwise any contract you call can act on your behalf.
Using "tx.origin" as a security control can lead to authorization bypass vulnerabilities. Consider using "msg.sender" unless you really know what you are doing.
```

PoC
Current code
```
address payable receiver = refundReceiver == address(0) ? payable(tx.origin) : refundReceiver;
```

Remediation
tx.origin should not be used for authorization. Use msg.sender instead.
```
address payable receiver = refundReceiver == address(0) ? payable(msg.sender) : refu

// Code block 1 (unknown):
/contracts/smart-contract-wallet/SmartAccount.sol

// Code block 2 (unknown):
https://github.com/code-423n4/2023-01-biconomy/blob/53c8c3823175aeb26dee5529eeefa81240a406ba/scw-contracts/contracts/smart-contract-wallet/SmartAccount.sol#L257

// Code block 3 (unknown):
Use of tx.origin: "tx.origin" is useful only in very exceptional cases.
If you use it for authentication, you usually want to replace it by "msg.sender", because otherwise any contract you call can act on your behalf.
Using "tx.origin" as a security control can lead to authorization bypass vulnerabilities. Consider using "msg.sender" unless you really know what you are doing.

// Code block 4 (unknown):
address payable receiver = refundReceiver == address(0) ? payable(tx.origin) : refundReceiver;

// Code block 5 (unknown):
address payable receiver = refundReceiver == address(0) ? payable(msg.sender) : refundReceiver;

// Code block 6 (unknown):
/contracts/smart-contract-wallet/SmartAccount.sol

// Code block 7 (unknown):
https://github.com/code-423n4/2023-01-biconomy/blob/53c8c3823175aeb26dee5529eeefa81240a406ba/scw-contracts/contracts/smart-contract-wallet/SmartAccount.sol#L281

// Code block 8 (unknown):
Use of tx.origin: "tx.origin" is useful only in very exceptional cases.
If you use it for authentication, you usually want to replace it by "msg.sender", because otherwise any contract you call can act on your behalf.
Using "tx.origin" as a security control can lead to authorization bypass vulnerabilities. Consider using "msg.sender" unless you really know what you are doing.

// Code block 9 (unknown):
address payable receiver = refundReceiver == address(0) ? payable(tx.origin) : refundReceiver;


MatricksDeCoder G

#### Gas-1 Make constructor payable to save on deployment costs

Gas savings can be achieved by making constructors payable can cut out about 10 opcodes which allow for the check if(msg.value != 0) revert();

https://github.com/code-423n4/2023-04-caviar/blob/cd8a92667bcb6657f70657183769c244d04c015c/src/EthRouter.sol#L90

https://github.com/code-423n4/2023-04-caviar/blob/cd8a92667bcb6657f70657183769c244d04c015c/src/Factory.sol#L53

https://github.com/code-423n4/2023-04-caviar/blob/cd8a92667bcb6657f70657183769c244d04c015c/src/PrivatePool.sol#L143

#### Gas-2 Use private for constants or immutable variables

Making such variables avoids the overhead cost of compiler creating getter functions for these variables

https://github.com/code-423n4/2023-04-caviar/blob/cd8a92667bcb6657f70657183769c244d04c015c/src/EthRouter.sol#L86

https://github.com/code-423n4/2023-04-caviar/blob/cd8a92667bcb6657f70657183769c244d04c015c/src/PrivatePool.sol#L119

https://github.com/code-423n4/2023-04-caviar/blob/cd8a92667bcb6657f70657183769c244d04c015c/src/PrivatePool.sol#L122

https://github.com/code-423n4/2023-04-caviar/blob/cd8a92667bcb6657f70657183769c244d04c015c/src/PrivatePool.sol#L125

#### Gas-3 Public functions not called in contract should be declared as external

External functions can read directly from calldata avoiding copying arguments from memory

https://github.com/code-423n4/2023-04-caviar/blob/cd8a92667bcb6657f70657183769c244d04c015c/src/EthRouter.sol#L99

https://github.com/code-423n4/2023-04-caviar/blob/cd8a92667bcb6657f70657183769c244d04c015c/src/EthRouter.sol#L152

https://github.com/code-423n4/2023-04-caviar/blob/cd8a92667bcb6657f70657183769c244d04c015c/src/EthRouter.sol#L219

https://github.com/code-423n4/2023-04-caviar/blob/cd8a92667bcb6657f70657183769c244d04c015c/src/EthRouter.sol#L254

https://github.com/code-423n4/2023-04-caviar/blob/cd8a92667bcb6657f70657183769c244d04c015c/src/EthRouter.sol#L301

#### Gas-4 Use more efficient abi.encodePacked vs abi.encode

virtualBaseTokenReserves = virtualBaseTokenReserves + uint128(netInputAmount - feeAmount - protocolFeeAmount);
virtualNftReserves = virtualNftReserves - uint128(weightSum);

EthRouter.sol#L90, Factory.sol#L53, PrivatePool.sol#L143, EthRouter.sol#L86, PrivatePool.sol#L119, PrivatePool.sol#L122, PrivatePool.sol#L125, EthRouter.sol#L99, EthRouter.sol#L152, EthRouter.sol#L219, EthRouter.sol#L254, EthRouter.sol#L301


debo Q

## [L-01] Block values as a proxy for time
Description
Contracts often need access to time values to perform certain types of functionality. Values such as block.timestamp, and block.number can give you a sense of the current time or a time delta, however, they are not safe to use for most purposes.

In the case of block.timestamp, developers often attempt to use it to trigger time-dependent events. As Ethereum is decentralized, nodes can synchronize time only to some degree. Moreover, malicious miners can alter the timestamp of their blocks, especially if they can gain advantages by doing so. However, miners can't set a timestamp smaller than the previous one (otherwise the block will be rejected), nor can they set the timestamp too far ahead in the future. Taking all of the above into consideration, developers can't rely on the preciseness of the provided timestamp.

```txt
https://github.com/code-423n4/2023-09-ondo/blob/47d34d6d4a5303af5f46e907ac2292e6a7745f6c/contracts/rwaOracles/RWADynamicOracle.sol#L64
    timestamp = block.timestamp;

https://github.com/code-423n4/2023-09-ondo/blob/47d34d6d4a5303af5f46e907ac2292e6a7745f6c/contracts/rwaOracles/RWADynamicOracle.sol#L79-L83
      if (range.start <= block.timestamp) {
        if (range.end <= block.timestamp) {
          return derivePrice(range, range.end - 1);
        } else {
          return derivePrice(range, block.timestamp);
```

Remediation
Developers should write smart contracts with the notion that block values are not precise, and the use of them can lead to unexpected effects. Alternatively, they may make use oracles.

## [L-02] Unsafe erc20 operations
Description
ERC20 operations can be unsafe due to different implementations and vulnerabilities in the standard.

It is therefore recommended to always either use OpenZeppelin's SafeERC20 library or at least to wrap each operation in a require statement.

To circumvent ERC20's approve functions race-condition vulnerability use OpenZeppelin's SafeERC20 l

Remediation
Developers should write smart contracts with the notion that block values are not precise, and the use of them can lead to unexpected effects. Alternatively, they may make use oracles.

## [L-02] Unsafe erc20 operations
Description
ERC20 operations can be unsafe due to different implementations and vulnerabilities in the standard.

It is therefore recommended to always either use OpenZeppelin's SafeERC20 library or at least to wrap each operation in a require statement.

To circumvent ERC20's approve functions race-condition vulnerability use OpenZeppelin's SafeERC20 library's safe{Increase|Decrease}Allowance functions.

In case the vulnerability is of no danger for your implementation, provide enough documentation explaining the reasonings.

// Code block 1 (txt):
https://github.com/code-423n4/2023-09-ondo/blob/47d34d6d4a5303af5f46e907ac2292e6a7745f6c/contracts/rwaOracles/RWADynamicOracle.sol#L64
    timestamp = block.timestamp;

https://github.com/code-423n4/2023-09-ondo/blob/47d34d6d4a5303af5f46e907ac2292e6a7745f6c/contracts/rwaOracles/RWADynamicOracle.sol#L79-L83
      if (range.start <= block.timestamp) {
        if (range.end <= block.timestamp) {
          return derivePrice(range, range.end - 1);
        } else {
          return derivePrice(range, block.timestamp);


zhaojie Q

## DestinationBridge.approve without checking txnHash exists

DestinationBridge.approve without checking txnHash exists leads to skip _checkThresholdMet permission check.

This does not cause any problems at present, but errors may be introduced during the subsequent upgrade. Therefore, advised to check whether txnHash exists.

```
  function _approve(bytes32 txnHash) internal {
    // Check that the approver has not already approved
    TxnThreshold storage t = txnToThresholdSet[txnHash];
    if (t.approvers.length > 0) {
      for (uint256 i = 0; i < t.approvers.length; ++i) {
        if (t.approvers[i] == msg.sender) {
          revert AlreadyApproved();
        }
      }
    }
    //@audit when txnHash not exists t.approvers was added
    t.approvers.push(msg.sender);
  }
```
```

  function _checkThresholdMet(bytes32 txnHash) internal view returns (bool) {
    TxnThreshold memory t = txnToThresholdSet[txnHash];
    //@audit t.numberOfApprovalsNeeded = 0 _checkThresholdMet return true
    if (t.numberOfApprovalsNeeded <= t.approvers.length) {
      return true;
    } else {
      return false;
    }
  }

  ```

  But the approver does not mint the token when it approves a non-existent txnHash because _checkAndUpdateInstantMintLimit will check whether the amount is greater than zero, but it is still has risk, suggest check whether txnHash exist when the approve.

  ```

  function approve(bytes32 txnHash) external {
    if (!approvers[msg.sender]) {
      revert NotApprover();
    }
    _approve(txnHash);
    _mintIfThresholdMet(txnHash);
  }

  function _mintIfThresholdMet(bytes32 txnHash) internal {
    bool thresholdMet = _checkThresholdMet(txnHash);
    Transaction memory txn = txnHashToTransaction[txnHash];
    if (thresholdMet) {
      _checkAndUpdateInstantMintLimit(txn.amount);
      if (!ALLOWLIST.isAllowed(txn.sender)) {
        ALLOWLIST.setAccountStatus(
          txn.sender,
          ALLOWLIST.getValidTermIndexes()[0],
          true
        );

// Code block 1 (unknown):
function _approve(bytes32 txnHash) internal {
    // Check that the approver has not already approved
    TxnThreshold storage t = txnToThresholdSet[txnHash];
    if (t.approvers.length > 0) {
      for (uint256 i = 0; i < t.approvers.length; ++i) {
        if (t.approvers[i] == msg.sender) {
          revert AlreadyApproved();
        }
      }
    }
    //@audit when txnHash not exists t.approvers was added
    t.approvers.push(msg.sender);
  }

// Code block 2 (unknown):
function _checkThresholdMet(bytes32 txnHash) internal view returns (bool) {
    TxnThreshold memory t = txnToThresholdSet[txnHash];
    //@audit t.numberOfApprovalsNeeded = 0 _checkThresholdMet return true
    if (t.numberOfApprovalsNeeded <= t.approvers.length) {
      return true;
    } else {
      return false;
    }
  }


befree3x Q

# QA reports

## Low

### [L-1] Missing checks on `V3Vault::setEmergencyAdmin` allowing owner to set the emergency admin as himself

**Vulnerability Details**

An emergency is defined by the protocol to be able to execute certain critical operations without timelock, for example:
- Set an oracle mode
- Set different protocol limit factors, e.g. the global limit of lent or deb amounts

However, it's possible for the owner to accidentally (or not) make himself as an emergency admin.

```javascript

function setEmergencyAdmin(address admin) external onlyOwner {
@>      emergencyAdmin = admin; // missing check here
       emit SetEmergencyAdmin(admin);
   }

```

**Impact**

If the emergency admin is also the owner, the protocol becomes entirely centralized. Although the current implementation allows all administrative actions to be done by the owner, an emergency admin can help to execute certain administrative actions in the absence of the owner.

**Tools Used**

Manual review.

**Recommended Mitigation Steps**

The following change can be used to update the `setEmergencyAdmin` function in both files `V3Vault.sol` and `V3Oracle.sol`

```diff

function setEmergencyAdmin(address admin) external onlyOwner {
+       if(admin == owner()) {
+           revert Unauthorized();
+       }
       emergencyAdmin = admin;
       emit SetEmergencyAdmin(admin);
}

```

The following test case can be added to the files `V3Vault.t.sol` and `V3Oracle.t.sol` as well:

- On `V3Vault.t.sol`, add this test:

```javascript

function testEmergencyAdminCanNotBeOwner() external {
       vm.expectRevert(IErrors.Unauthorized.selector);
       vault.setEmergencyAdmin(address(this));
}

```

- On `V3Oracle.t.sol`, add this test:

```javascript

function testEmergencyAdminCanNotBeOwner() external {
       vm.expectRevert(IErrors.Unauthorized.selector);
       oracle.setEmergencyAdmin(address(this));
}

```

// Code block 1 (javascript):
function setEmergencyAdmin(address admin) external onlyOwner {
@>      emergencyAdmin = admin; // missing check here
       emit SetEmergencyAdmin(admin);
   }

// Code block 2 (diff):
function setEmergencyAdmin(address admin) external onlyOwner {
+       if(admin == owner()) {
+           revert Unauthorized();
+       }
       emergencyAdmin = admin;
       emit SetEmergencyAdmin(admin);
}

// Code block 3 (javascript):
function testEmergencyAdminCanNotBeOwner() external {
       vm.expectRevert(IErrors.Unauthorized.selector);
       vault.setEmergencyAdmin(address(this));
}

// Code block 4 (javascript):
function testEmergencyAdminCanNotBeOwner() external {
       vm.expectRevert(IErrors.Unauthorized.selector);
       oracle.setEmergencyAdmin(address(this));
}


matrix_0wl G

## Gas Optimizations

|        | Issue                                                                                |
| ------ | :--------------------------------------------------------------------------------------------------------------------- |
| GAS-1  | `ABI.ENCODE()` IS LESS EFFICIENT THAN `ABI.ENCODEPACKED()`                                                             |
| GAS-2  | Use assembly to check for `address(0)`                                                                                |
| GAS-3  | Setting the constructor to payable                                                                                |
| GAS-4  | DUPLICATED REQUIRE()/REVERT() CHECKS SHOULD BE REFACTORED TO A MODIFIER OR FUNCTION                                    |
| GAS-5  | USE FUNCTION INSTEAD OF MODIFIERS                                                                                |
| GAS-6  | CONSTANT VALUES SUCH AS A CALL TO KECCAK256(), SHOULD USE IMMUTABLE RATHER THAN CONSTANT                               |
| GAS-7  | KECCAK256() SHOULD ONLY NEED TO BE CALLED ON A SPECIFIC STRING LITERAL ONCE                                            |
| GAS-8  | MAKING CONSTANT VARIABLES PRIVATE WILL SAVE GAS DURING DEPLOYMENT                                                      |
| GAS-9  | Functions guaranteed to revert when called by normal users can be marked payable                                       |
| GAS-10 | `++i` costs less gas than `i++`, especially when it's used in `for`-loops (`--i`/`i--` too) = for-loop and while-loops |
| GAS-11 | The increment in for loop postcondition can be made unchecked                                                          |
| GAS-12 | Using `private` rather than `public` for constants, saves gas                                                          |
| GAS-13 | TERNARY OPERATION IS CHEAPER THAN IF-ELSE STATEMENT

File: contracts/bridge/DestinationBridge.sol

99:     if (chainToApprovedSender[srcChain] != keccak256(abi.encode(srcAddr))) {

238:     chainToApprovedSender[srcChain] = keccak256(abi.encode(srcContractAddress));

File: contracts/bridge/SourceBridge.sol

79:     bytes memory payload = abi.encode(VERSION, msg.sender, amount, nonce++);


mahdirostami G

1. COMPOUND ASSIGNMENT OPERATOR COSTS EXTRA GAS FOR STATE VARIABLES

<X += Y> uses more gas than <X = X + Y>
<X -= Y>  uses more gas than <X = X - Y>

Affected source code:
- [CashManager.sol#L221](https://github.com/code-423n4/2023-01-ondo/blob/f3426e5b6b4561e09460b2e6471eb694efdd6c70/contracts/cash/CashManager.sol#L221)
- [CashManager.sol#L582](https://github.com/code-423n4/2023-01-ondo/blob/f3426e5b6b4561e09460b2e6471eb694efdd6c70/contracts/cash/CashManager.sol#L582)
- [CashManager.sol#L630](https://github.com/code-423n4/2023-01-ondo/blob/f3426e5b6b4561e09460b2e6471eb694efdd6c70/contracts/cash/CashManager.sol#L630)
- [CashManager.sol#L649](https://github.com/code-423n4/2023-01-ondo/blob/f3426e5b6b4561e09460b2e6471eb694efdd6c70/contracts/cash/CashManager.sol#L649)
- [CashManager.sol#L792](https://github.com/code-423n4/2023-01-ondo/blob/f3426e5b6b4561e09460b2e6471eb694efdd6c70/contracts/cash/CashManager.sol#L792)

2. IN SOLIDITY 0.8+ <I++> AND <++I>  SHOULD BE UNCHECKED{I++} AND UNCHECKED{++I}

Because, there’s a default overflow check on unsigned integers.
It’s possible to uncheck this in for-loops and save some gas at each iteration.

Affected source code:
- [CashManager.sol#L750](https://github.com/code-423n4/2023-01-ondo/blob/f3426e5b6b4561e09460b2e6471eb694efdd6c70/contracts/cash/CashManager.sol#L750)
- [CashManager.sol#L786](https://github.com/code-423n4/2023-01-ondo/blob/f3426e5b6b4561e09460b2e6471eb694efdd6c70/contracts/cash/CashManager.sol#L786)
- [CashManager.sol#L933](https://github.com/code-423n4/2023-01-ondo/blob/f3426e5b6b4561e09460b2e6471eb694efdd6c70/contracts/cash/CashManager.sol#L933)
- [CashManager.sol#L961](https://github.com/code-423n4/2023-01-ondo/blob/f3426e5b6b4561e09460b2e6471eb694efdd6c70/contracts/cash/CashManager.sol#L961)
- [CashFactory.sol#L127](https://github.com/code-423n4/2023-01-ondo/blob/f3426e5b6b4561e09460b2e6471eb694efdd6c70/contracts/cash/factory/CashFactory.sol#L127)
- [KYCRegistry.sol#L180](https://github.com/code-423n4/202

    modifier onlyGuardian() {
        require(msg.sender == guardian, "CashFactory: You are not the Guardian");
        _;
      }

CashManager.sol#L221, CashManager.sol#L582, CashManager.sol#L630, CashManager.sol#L649, CashManager.sol#L792, CashManager.sol#L750, CashManager.sol#L786, CashManager.sol#L933, CashManager.sol#L961, CashFactory.sol#L127


ernestognw G

## Reorder `SafEthStorage` variables for lesser storage accesses

Considering that `stake()` is reasonably expected to be the most-called function, it currently accesses 5 storage slots while reading the following variables:

* `pauseStaking`
* `derivativeCount`
* `totalWeight`
* `minAmount`
* `maxAmount`

However, both `derivativeCount` and `totalWeight` are not expected to grow much, so they can be packed along with `pauseStaking`, and for the case of `minAmount` and `maxAmount` both current values hardcoded in the contract can fit in `uin128` to be packed together.

Concretely, the arrangement proposed is the following:

```solidity
contract SafEthStorage {
    bool public pauseStaking; // true if staking is paused
    bool public pauseUnstaking; // true if unstaking is pause
    uint120 public derivativeCount; // amount of derivatives added to contract
    uint120 public totalWeight; // total weight of all derivatives (used to calculate percentage of derivative)
    uint128 public minAmount; // minimum amount to stake
    uint128 public maxAmount; // maximum amount to stake
    ...
}
```

// Code block 1 (solidity):
contract SafEthStorage {
    bool public pauseStaking; // true if staking is paused
    bool public pauseUnstaking; // true if unstaking is pause
    uint120 public derivativeCount; // amount of derivatives added to contract
    uint120 public totalWeight; // total weight of all derivatives (used to calculate percentage of derivative)
    uint128 public minAmount; // minimum amount to stake
    uint128 public maxAmount; // maximum amount to stake
    ...
}


matrix_0wl G

# Summary

## Gas Optimizations

|        | Issue                                                                                |
| ------ | :-------------------------------------------------------------------------------------------------------------------------------------------------- |
| GAS-1  | `ABI.ENCODE()` IS LESS EFFICIENT THAN `ABI.ENCODEPACKED()`                                                                                |
| GAS-2  | MAKING CONSTANT VARIABLES PRIVATE WILL SAVE GAS DURING DEPLOYMENT                                                                                |
| GAS-3  | `<X> += <Y>`/`<X> -= <Y>` COSTS MORE GAS THAN `<X> = <X> + <Y>`/`<X> = <X> - <Y>` FOR STATE VARIABLES                                               |
| GAS-4  | AVOID CONTRACT EXISTENCE CHECKS BY USING LOW LEVEL CALLS                                                                                |
| GAS-6  | SETTING THE CONSTRUCTOR TO PAYABLE                                                                                |
| GAS-7  | DUPLICATED REQUIRE()/REVERT() CHECKS SHOULD BE REFACTORED TO A MODIFIER OR FUNCTION (INSTANCES)                                                     |
| GAS-8  | DOS WITH BLOCK GAS LIMIT                                                                                |
| GAS-9  | INSTEAD OF CALCULATING A STATEVAR WITH KECCAK256() EVERY TIME THE CONTRACT IS MADE PRE CALCULATE THEM BEFORE AND ONLY GIVE THE RESULT TO A CONSTANT |
| GAS-10 | CONSTANT VALUES SUCH AS A CALL TO KECCAK256(), SHOULD USE IMMUTABLE RATHER THAN CONSTANT                                                            |
| GAS-11 | KECCAK256() SHOULD ONLY NEED TO BE CALLED ON A SPECIFIC STRING LITERAL ONCE                                                                         |
| GAS-12 | MAKING CONSTANT VARIABLE

File: Ethos-Core/contracts/LUSDToken.sol

305:         return keccak256(abi.encode(typeHash, name, version, _chainID(), address(this)));

File: Ethos-Core/contracts/StabilityPool.sol

197:     uint public constant SCALE_FACTOR = 1e9;


BClabs Q

1. **Function duplicate**:

There are 2 functions that implmenet the same logic- They both accept batchId and return nonces[batchId].

https://github.com/code-423n4/2023-01-biconomy/blob/53c8c3823175aeb26dee5529eeefa81240a406ba/scw-contracts/contracts/smart-contract-wallet/SmartAccount.sol#L155-L159
https://github.com/code-423n4/2023-01-biconomy/blob/53c8c3823175aeb26dee5529eeefa81240a406ba/scw-contracts/contracts/smart-contract-wallet/SmartAccount.sol#L97-L99

2. **Wrong error message**:

Should be invalid _handler not Invalid Entrypoint.

https://github.com/code-423n4/2023-01-biconomy/blob/53c8c3823175aeb26dee5529eeefa81240a406ba/scw-contracts/contracts/smart-contract-wallet/SmartAccount.sol#L171

3. **Address.isContract does not work as expected when called from constructor**:

Address.isContract(paymasterId) can be fooled when calling a function from the contract's constructor. Since isContract checks contract size, which is at the time of constructor 0, it will return that the address is not contract.

```
contract Attack {
    constructor(address contractAddress) {
        VerifyingSingletonPaymaster(contractAddress).depositFor{value: 1}(address(this));
    }
}
```

To be sure paymasterId is not a contract add require tx.origin == msg.sender.
https://github.com/code-423n4/2023-01-biconomy/blob/53c8c3823175aeb26dee5529eeefa81240a406ba/scw-contracts/contracts/smart-contract-wallet/paymasters/verifying/singleton/VerifyingSingletonPaymaster.sol#L49

4. **Abstract contracts should have some functions unimplemented**

Since StakeManager is a complete contract, it should not be marked as abstract.

https://github.com/code-423n4/2023-01-biconomy/blob/53c8c3823175aeb26dee5529eeefa81240a406ba/scw-contracts/contracts/smart-contract-wallet/aa-4337/core/StakeManager.sol#L13

// Code block 1 (unknown):
contract Attack {
    constructor(address contractAddress) {
        VerifyingSingletonPaymaster(contractAddress).depositFor{value: 1}(address(this));
    }
}

SmartAccount.sol#L155-L159, SmartAccount.sol#L97-L99, SmartAccount.sol#L171, VerifyingSingletonPaymaster.sol#L49, StakeManager.sol#L13


Bason Q

## QA Findings
| Number  | Issues Details                                                                                |
|:-------:|:---------------------------------------------------------------------------------------------------|
| [QA-01] | Emit event after proposal is executed and not before                                               |
| [QA-02] | Create a more specific custom error in StandardFunding.sol in the executeStandard function         |
| [QA-03] | Rename function findMechanismOfProposal to getProposalMechanism                                    |
| [QA-04] | Remove the underscore from the name of the parameter in GrantFund.sol in the fundTreasury function |
| [L-01]  | Not verifying that params_.pool is valid pool address                                              |
| [L-02]  | Creating two variables when we need only one                                                       |

***

## |[QA-01]| Emit event after proposal is executed and not before

Funding.sol function _execute

```solidity
 function _execute(
        uint256 proposalId_,
        address[] memory targets_,
        uint256[] memory values_,
        bytes[] memory calldatas_
    ) internal {
        // use common event name to maintain consistency with tally
        emit ProposalExecuted(proposalId_);

        string memory errorMessage = "Governor: call reverted without message";
        for (uint256 i = 0; i < targets_.length; ++i) {
            (bool success, bytes memory returndata) = targets_[i].call{value: values_[i]}(calldatas_[i]);
            Address.verifyCallResult(success, returndata, errorMessage);
        }
    }
```
The ProposalExecuted event should be emitted after the for loop and all call results have been verified.
Otherwise we might emit the event and then revert which is misleading.
***

## |[QA-02]| Create a more specific custom error in StandardFunding.sol in the executeStandard function

StandardFunding.sol function executeStandard

```solidity
fun

function executeStandard(
        address[] memory targets_,
        uint256[] memory values_,
        bytes[] memory calldatas_,
        bytes32 descriptionHash_
    ) external nonReentrant override returns (uint256 proposalId_) {
        //Hash proposal generates a uint256 based on the values
        ...
        if (block.number <= _getChallengeStageEndBlock(_distributions[distributionId].endBlock)) revert ExecuteProposalInvalid();

// Code block 1 (solidity):
function _execute(
        uint256 proposalId_,
        address[] memory targets_,
        uint256[] memory values_,
        bytes[] memory calldatas_
    ) internal {
        // use common event name to maintain consistency with tally
        emit ProposalExecuted(proposalId_);

        string memory errorMessage = "Governor: call reverted without message";
        for (uint256 i = 0; i < targets_.length; ++i) {
            (bool success, bytes memory returndata) = targets_[i].call{value: values_[i]}(calldatas_[i]);
            Address.verifyCallResult(success, returndata, errorMessage);
        }
    }


Go Langer G

## Consider optimizing sendCollateral for batch operations in ActivePool.sol

```solidity
    function sendCollateral(address _collateral, address _account, uint _amount) external override {
        _requireValidCollateralAddress(_collateral);
        _requireCallerIsBOorTroveMorSP();
        _rebalance(_collateral, _amount);
        collAmount[_collateral] = collAmount[_collateral].sub(_amount);
        emit ActivePoolCollateralBalanceUpdated(_collateral, collAmount[_collateral]);
        emit CollateralSent(_collateral, _account, _amount);

        if (_account == defaultPoolAddress) {
            IERC20(_collateral).safeIncreaseAllowance(defaultPoolAddress, _amount);
            IDefaultPool(defaultPoolAddress).pullCollateralFromActivePool(_collateral, _amount);
        } else if (_account == collSurplusPoolAddress) {
            IERC20(_collateral).safeIncreaseAllowance(collSurplusPoolAddress, _amount);
            ICollSurplusPool(collSurplusPoolAddress).pullCollateralFromActivePool(_collateral, _amount);
        } else {
            IERC20(_collateral).safeTransfer(_account, _amount);
        }
    }

```

Refactored code:

```
    function batchSendCollateral(address[] calldata _collateral, address[] calldata _account, uint[] calldata _amount) external override {
        _requireCallerIsBOorTroveMorSP();
        uint256 length = _collateral.length;
        for (uint256 i = 0; i < length; i++) {
        _requireValidCollateralAddress(_collateral[i]);
            _rebalance(_collateral[i], _amount[i]);
         collAmount[_collateral[i]] = collAmount[_collateral[i]].sub(_amount[i]);
             emit ActivePoolCollateralBalanceUpdated(_collateral[i], collAmount[_collateral[i]]);
           emit CollateralSent(_collateral[i], _account[i], _amount[i]);
        }
     }
```

### There are 65 instances of this:

171: Ethos-Core/contracts/ActivePool.sol function sendCollaterall

172: Ethos-Core/contracts/BorrowerOperations.sol function openTrove

242: Ethos-Core/co

// Code block 1 (unknown):
Refactored code:


Dinesh11G G

### 1st BUG
Don't Initialize Variables with Default Value

#### Impact
Issue Information:
Uninitialized variables are assigned with the types default value.

Explicitly initializing a variable with it's default value costs unnecessary gas.

Example
🤦 Bad:

uint256 x = 0;
bool y = false;
🚀 Good:

uint256 x;
bool y;

#### Findings:
```
2023-01-ondo/contracts/cash/external/openzeppelin/contracts/utils/Strings.sol::45 => uint256 length = 0;
2023-01-ondo/contracts/cash/external/openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol::46 => uint256 length = 0;
2023-01-ondo/contracts/lending/CompoundLens.sol::85 => for (uint i = 0; i < cTokenCount; i++) {
2023-01-ondo/contracts/lending/CompoundLens.sol::135 => for (uint i = 0; i < cTokenCount; i++) {
2023-01-ondo/contracts/lending/CompoundLens.sol::167 => for (uint i = 0; i < cTokenCount; i++) {
2023-01-ondo/contracts/lending/compound/Comptroller.sol::168 => for (uint i = 0; i < len; i++) {
2023-01-ondo/contracts/lending/compound/Comptroller.sol::258 => for (uint i = 0; i < len; i++) {
2023-01-ondo/contracts/lending/compound/Comptroller.sol::873 => for (uint i = 0; i < assets.length; i++) {
2023-01-ondo/contracts/lending/compound/Comptroller.sol::1183 => for (uint i = 0; i < allMarkets.length; i++) {
2023-01-ondo/contracts/lending/compound/Comptroller.sol::1237 => for (uint i = 0; i < numMarkets; i++) {
2023-01-ondo/contracts/lending/compound/Comptroller.sol::1363 => for (uint i = 0; i < affectedUsers.length; ++i) {
2023-01-ondo/contracts/lending/compound/Comptroller.sol::1656 => for (uint i = 0; i < cTokens.length; i++) {
2023-01-ondo/contracts/lending/compound/Comptroller.sol::1662 => for (uint j = 0; j < holders.length; j++) {
2023-01-ondo/contracts/lending/compound/Comptroller.sol::1668 => for (uint j = 0; j < holders.length; j++) {
2023-01-ondo/contracts/lending/compound/Comptroller.sol::1673 => for (uint j = 0; j < holders.length; j++) {
2023-01-ondo/contracts/lending/compound/Comptroller.sol::1735 => for (u

2023-01-ondo/contracts/cash/external/openzeppelin/contracts/utils/Strings.sol::45 => uint256 length = 0;
2023-01-ondo/contracts/cash/external/openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol::46 => uint256 length = 0;
2023-01-ondo/contracts/lending/CompoundLens.sol::85 => for (uint i = 0; i < cTokenCount; i++) {
2023-01-ondo/contracts/lending/CompoundLens.sol::135 => for (uint i = 0; i < cTokenCount; i++) {
2023-01-ondo/contracts/lending/CompoundLens.sol::167 => for (uint i = 0; i < cTokenCount; i++) {
2023-01-ondo/contracts/lending/compound/Comptroller.sol::168 => for (uint i = 0; i < len; i++) {
2023-01-ondo/contracts/lending/compound/Comptroller.sol::258 => for (uint i = 0; i < len; i++) {
2023-01-ondo/contracts/lending/compound/Comptroller.sol::873 => for (uint i = 0; i < assets.length; i++) {
2023-01-ondo/contracts/lending/compound/Comptroller.sol::1183 => for (uint i = 0; i < allMarkets.length; i++) {
2023-01-ondo/contracts/lending/compound/Comptroller.sol::1237 => for (uint i = 0; i < numMarkets; i++) {
2023-01-ondo/contracts/lending/compound/Comptroller.sol::1363 => for (uint i = 0; i < affectedUsers.length; ++i) {
2023-01-ondo/contracts/lending/compound/Comptroller.sol::1656 => for (uint i = 0; i < cTokens.length; i++) {
2023-01-ondo/contracts/lending/compound/Comptroller.sol::1662 => for (uint j = 0; j < holders.length; j++) {
2023-01-ondo/contracts/lending/compound/Comptroller.sol::1668 => for (uint j = 0; j < holders.length; j++) {
2023-01-ondo/contracts/lending/compound/Comptroller.sol::1673 => for (uint j = 0; j < holders.length; j++) {
2023-01-ondo/contracts/lending/compound/Comptroller.sol::1735 => for (uint i = 0; i < numTokens; ++i) {
2023-01-ondo/contracts/lending/compound/governance/Comp.sol::258 => uint32 lower = 0;
2023-01-ondo/contracts/lending/compound/governance/GovernorBravoDelegate.sol::201 => for (uint i = 0; i < proposal.targets.length; i++) {
2023-01-ondo/contracts/lending/compound/governance/GovernorBravoDelegate.sol::24

2023-01-ondo/contracts/cash/CashManager.sol::749 => uint256 size = redeemers.length;
2023-01-ondo/contracts/cash/CashManager.sol::785 => uint256 size = refundees.length;
2023-01-ondo/contracts/cash/CashManager.sol::932 => uint256 size = accounts.length;
2023-01-ondo/contracts/cash/CashManager.sol::960 => results = new bytes[](exCallData.length);
2023-01-ondo/contracts/cash/external/openzeppelin/contracts/access/AccessControlEnumerable.sol::69 => return _roleMembers[role].length();
2023-01-ondo/contracts/cash/external/openzeppelin/contracts/proxy/ERC1967Upgrade.sol::76 => if (data.length > 0 || forceCall) {
2023-01-ondo/contracts/cash/external/openzeppelin/contracts/proxy/ERC1967Upgrade.sol::196 => if (data.length > 0 || forceCall) {
2023-01-ondo/contracts/cash/external/openzeppelin/contracts/token/SafeERC20.sol::113 => if (returndata.length > 0) {
2023-01-ondo/contracts/cash/external/openzeppelin/contracts/utils/Address.sol::41 => return account.code.length > 0;
2023-01-ondo/contracts/cash/external/openzeppelin/contracts/utils/Address.sol::238 => if (returndata.length > 0) {
2023-01-ondo/contracts/cash/external/openzeppelin/contracts/utils/EnumerableSet.sol::59 => set._indexes[value] = set._values.length;
2023-01-ondo/contracts/cash/external/openzeppelin/contracts/utils/EnumerableSet.sol::83 => uint256 lastIndex = set._values.length - 1;
2023-01-ondo/contracts/cash/external/openzeppelin/contracts/utils/EnumerableSet.sol::120 => function _length(Set storage set) private view returns (uint256) {
2023-01-ondo/contracts/cash/external/openzeppelin/contracts/utils/EnumerableSet.sol::121 => return set._values.length;
2023-01-ondo/contracts/cash/external/openzeppelin/contracts/utils/EnumerableSet.sol::193 => function length(Bytes32Set storage set) internal view returns (uint256) {
2023-01-ondo/contracts/cash/external/openzeppelin/contracts/utils/EnumerableSet.sol::194 => return _length(set._inner);
2023-01-ondo/contracts/cash/external/openzeppelin/contracts/utils/Enumerable


descharre G

## Summary
|ID     | Syntax      |  Gas saved| Instances |
|:----: | :---           |              :----:    |  :----:         |
|1       | Make nonces private|   22   | 1 |
| 2      | refundInfo.gasPrice is redundant| 18| 1 |
| 3      |Unchecked for loop| 611 | 1 |

## Details
### 1 Make nonces private
Saves on average 22 gas

`mapping(uint256 => uint256) public nonces;`

[SmartAccount.sol#L55](https://github.com/code-423n4/2023-01-biconomy/blob/main/scw-contracts/contracts/smart-contract-wallet/SmartAccount.sol#L55)

### 2 refundInfo.gasPrice is redundant
Saves on average 18 gas

remove the !=0 in the require statement because it's also checked in the if statement below

additionally you can put the variable initialization of payment inside the if statement so it only initializes when the statement true. This is an extra 5 gas saving

- [SmartAccount.sol#L232](https://github.com/code-423n4/2023-01-biconomy/blob/main/scw-contracts/contracts/smart-contract-wallet/SmartAccount.sol#L232)
- [SmartAccount.sol#L234](https://github.com/code-423n4/2023-01-biconomy/blob/main/scw-contracts/contracts/smart-contract-wallet/SmartAccount.sol#L234)

### 3  Unchecked for loop
[EntryPoint.sol](https://github.com/code-423n4/2023-01-biconomy/blob/main/scw-contracts/contracts/smart-contract-wallet/aa-4337/core/EntryPoint.sol)
- [EntryPoint.sol#L93-L142](https://github.com/code-423n4/2023-01-biconomy/blob/main/scw-contracts/contracts/smart-contract-wallet/aa-4337/core/EntryPoint.sol#L93-L142) handleAggregatedOps: make all for loops unchecked: on average 611 gas saved
```
function increment_unchecked(uint256 x) private pure returns (uint256) {
        unchecked {
            return x + 1;
        }
    }

for (uint256 i = 0; i < opasLen; i =increment_unchecked(i++) ) {
            totalOps += opsPerAggregator[i].userOps.length;
        }
```

// Code block 1 (unknown):
function increment_unchecked(uint256 x) private pure returns (uint256) {
        unchecked {
            return x + 1;
        }
    }

for (uint256 i = 0; i < opasLen; i =increment_unchecked(i++) ) {
            totalOps += opsPerAggregator[i].userOps.length;
        }

SmartAccount.sol#L55, SmartAccount.sol#L232, SmartAccount.sol#L234, EntryPoint.sol, EntryPoint.sol#L93-L142


alymurtazamemon G

# Amphora Protocol - Gas Optimization Report

## Table Of Content

| Number                                                                                | Issue                                                                            | Instances |
| :----------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------- | --------: |
| [G-01](#g-01---functions-guaranteed-to-revert-when-called-by-normal-users-can-be-marked-payable) | Functions guaranteed to revert when called by normal users can be marked payable |        50 |
| [G-02](#g-02---multiple-reads-of-storage-variable-which-can-be-cached-to-save-users-gas-cost)    | Multiple reads of `storage` variable which can be cached to save users gas cost  |         4 |
| [G-03](#g-03---variables-contains-keccak256-expression-should-be-immutable)                      | variables contains `keccak256` expression should be `immutable`                  |         1 |
| [G-04](#g-04---variables-only-write-on-deployment-should-be-immutable-to-save-users-gas)         | Variables only write on deployment should be `immutable` to save users gas       |         1 |
| [G-05](#g-05---re-order-the-modifiers-to-save-users-gas-cost)                                    | Re-order the modifiers to save users gas cost                                    |         5 |
| [G-06](#g-06---check-conditions-should-be-at-the-top-of-the-functions)                           | `check` conditions should be at the top of the functions                         |         1 |
| [G-07](#g-07---use-unchecked-where-possible-to-save-users-gas)                                   | Use unchecked where possible to save users gas                                   |         1 |

### [G-01] - Functions guaranteed to revert when called by normal users can be marked payable.

**Details**

It is advisable to always use payable keyword with function

Similarly for all these functions, users will save 24 gas per call just adding `payable` keyword.

[AMPHClaimer.sol - Line 128](https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/AMPHClaimer.sol#L128)

[AMPHClaimer.sol - Line 136](https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/AMPHClaimer.sol#L136)

[AMPHClaimer.sol - Line 144](https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/AMPHClaimer.sol#L144)

[USDA.sol - Line 63](https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/USDA.sol#L63)

[USDA.sol - Line 161](https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/USDA.sol#L161)

[USDA.sol - Line 182](https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/USDA.sol#L182)

[USDA.sol - Line 212](https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/USDA.sol#L212)

[USDA.sol - Line 224](https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/USDA.sol#L224)

[USDA.sol - Line 231](https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/USDA.sol#L231)

[USDA.sol - Line 239](https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/USDA.sol#L239)

[USDA.sol - Line 253](https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/USDA.sol#L253)

[USDA.sol - Line 278](https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/USDA.sol#L278)

[USDA.sol - Line 287](https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/USDA.sol#L287)

[USDA.sol - Line 297](https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/USDA.sol#L297)

[Vault.sol - Line 89](https://github.com/code-423n4/2023-07-amphora/blob/main/core/solidity/contracts/core/Vault.sol#L89)

[Vault.sol - Lin

AMPHClaimer.sol#L128, AMPHClaimer.sol#L136, AMPHClaimer.sol#L144, USDA.sol#L63, USDA.sol#L161, USDA.sol#L182, USDA.sol#L212, USDA.sol#L224, USDA.sol#L231, USDA.sol#L239, USDA.sol#L253, USDA.sol#L278, USDA.sol#L287, USDA.sol#L297, Vault.sol#L89, USDA.sol#L132


peanuts Q

### [L-01] Supported Assets cannot be removed in LRTConfig.sol

The asset and deposit limit can be added to the `isSupportedAsset` mapping and is pushed to the `supportedAssetList` address array, but cannot be popped nor set to false. It would be great if the asset can be popped from the array if the supported token is not in use, or simply set to false. A way to make sure that the supported asset is not in use is to set the deposit limit to zero.

```
    /// @dev Adds a new supported asset
    /// @param asset Asset address
    /// @param depositLimit Deposit limit for the asset
    function _addNewSupportedAsset(address asset, uint256 depositLimit) private {
        UtilLib.checkNonZeroAddress(asset);
        if (isSupportedAsset[asset]) {
            revert AssetAlreadySupported();
        }
        isSupportedAsset[asset] = true;
        supportedAssetList.push(asset);
        depositLimitByAsset[asset] = depositLimit;
        emit AddedNewSupportedAsset(asset, depositLimit);
```

https://github.com/code-423n4/2023-11-kelp/blob/main/src/LRTConfig.sol

### [L-02] NodeDelegator cannot be removed from the nodeDelegatorQueue array

There is a `maxNodeDelegatorCount` of 10 set in the initializer, and this number can be changed. Node delegators are added to the `nodeDelegatorQueue`, but they cannot be removed. Consider allowing the removal of node delegators. This is quite important as the `nodeDelegatorQueue` is used in a loop, and if every node delegator has some assets present, the `getAssetDistributionData()` might run into a out of gas error when calculating the amount of assets in the NDCs

```
    function addNodeDelegatorContractToQueue(address[] calldata nodeDelegatorContracts) external onlyLRTAdmin {
        uint256 length = nodeDelegatorContracts.length;
        if (nodeDelegatorQueue.length + length > maxNodeDelegatorCount) {
            revert MaximumNodeDelegatorCountReached();
        }

        for (uint256 i; i < length;) {
            UtilLib.checkN

    function addNodeDelegatorContractToQueue(address[] calldata nodeDelegatorContracts) external onlyLRTAdmin {
        uint256 length = nodeDelegatorContracts.length;
        if (nodeDelegatorQueue.length + length > maxNodeDelegatorCount) {
            revert MaximumNodeDelegatorCountReached();
        }

        for (uint256 i; i < length;) {
            UtilLib.checkNonZeroAddress(nodeDelegatorContracts[i]);
            nodeDelegatorQueue.push(nodeDelegatorContracts[i]);
            emit NodeDelegatorAddedinQueue(nodeDelegatorContracts[i]);
            unchecked {
                ++i;
            }
        }
    }

// Code block 1 (unknown):
/// @dev Adds a new supported asset
    /// @param asset Asset address
    /// @param depositLimit Deposit limit for the asset
    function _addNewSupportedAsset(address asset, uint256 depositLimit) private {
        UtilLib.checkNonZeroAddress(asset);
        if (isSupportedAsset[asset]) {
            revert AssetAlreadySupported();
        }
        isSupportedAsset[asset] = true;
        supportedAssetList.push(asset);
        depositLimitByAsset[asset] = depositLimit;
        emit AddedNewSupportedAsset(asset, depositLimit);


Rickard G

## [G-01] Use named imports instead of plain `import file.sol
## Summary
Using import declarations of the form `import {<identifier_name>} from 'some/file.sol'` avoids polluting the symbol namespace making flattened files smaller, and speeds up compilation.
## Vulnerability Details

## Impact
Instances (95):
````solidity
packages\contracts\contracts\Dependencies\EbtcBase.sol

5: import "./BaseMath.sol";
6: import "./EbtcMath.sol";
7: import "../Interfaces/IActivePool.sol";
8: import "../Interfaces/IPriceFeed.sol";
9: import "../Interfaces/IEbtcBase.sol";
10: import "../Dependencies/ICollateralToken.sol";
````
````solidity
packages\contracts\contracts\Dependencies\ERC3156FlashLender.sol

5: import "../Interfaces/IERC3156FlashLender.sol";
6: import "../Interfaces/IWETH.sol";
````
````solidity
packages\contracts\contracts\Dependencies\RolesAuthority.sol

6: import "./EnumerableSet.sol";
````
````solidity
packages\contracts\contracts\Interfaces\IActivePool.sol

5: import "./IPool.sol";
````
````solidity
packages\contracts\contracts\Interfaces\IBorrowerOperations.sol

4: import "./IPositionManagers.sol";
````
````solidity
packages\contracts\contracts\Interfaces\ICdpManager.sol

5: import "./IEbtcBase.sol";
6: import "./ICdpManagerData.sol";
````
````solidity
packages\contracts\contracts\Interfaces\ICdpManagerData.sol

5: import "./ICollSurplusPool.sol";
6: import "./IEBTCToken.sol";
7: import "./ISortedCdps.sol";
8: import "./IActivePool.sol";
9: import "./IRecoveryModeGracePeriod.sol";
10: import "../Dependencies/ICollateralTokenOracle.sol";
````
````solidity
packages\contracts\contracts\Interfaces\IEbtcBase.sol

5: import "./IPriceFeed.sol";
````
````solidity
packages\contracts\contracts\Interfaces\IEBTCToken.sol

5: import "../Dependencies/IERC20.sol";
6: import "../Dependencies/IERC2612.sol";
````
````solidity
packages\contracts\contracts\Interfaces\IERC3156FlashLender.sol

5: import "./IERC3156FlashBorrower.sol";
````
````solidity
packages\contracts\contracts\Active

// Code block 1 (solidity):
packages\contracts\contracts\Dependencies\EbtcBase.sol

5: import "./BaseMath.sol";
6: import "./EbtcMath.sol";
7: import "../Interfaces/IActivePool.sol";
8: import "../Interfaces/IPriceFeed.sol";
9: import "../Interfaces/IEbtcBase.sol";
10: import "../Dependencies/ICollateralToken.sol";

// Code block 2 (solidity):
packages\contracts\contracts\Dependencies\ERC3156FlashLender.sol

5: import "../Interfaces/IERC3156FlashLender.sol";
6: import "../Interfaces/IWETH.sol";

// Code block 3 (solidity):
packages\contracts\contracts\Dependencies\RolesAuthority.sol

6: import "./EnumerableSet.sol";

// Code block 4 (solidity):
packages\contracts\contracts\Interfaces\IActivePool.sol

5: import "./IPool.sol";

// Code block 5 (solidity):
packages\contracts\contracts\Interfaces\IBorrowerOperations.sol

4: import "./IPositionManagers.sol";

// Code block 6 (solidity):
packages\contracts\contracts\Interfaces\ICdpManager.sol

5: import "./IEbtcBase.sol";
6: import "./ICdpManagerData.sol";

// Code block 7 (solidity):
packages\contracts\contracts\Interfaces\ICdpManagerData.sol

5: import "./ICollSurplusPool.sol";
6: import "./IEBTCToken.sol";
7: import "./ISortedCdps.sol";
8: import "./IActivePool.sol";
9: import "./IRecoveryModeGracePeriod.sol";
10: import "../Dependencies/ICollateralTokenOracle.sol";

// Code block 8 (solidity):
packages\contracts\contracts\Interfaces\IEbtcBase.sol

5: import "./IPriceFeed.sol";

// Code block 9 (solidity):
packages\contracts\contracts\Interfaces\IEBTCToken.sol

5: import "../Dependencies/IERC20.sol";
6: import "../Dependencies/IERC2612.sol";

// Code block 10 (solidity):
packages\contracts\contracts\Interfaces\IERC3156FlashLender.sol

5: import "./IERC3156FlashBorrower.sol";

packages\contracts\contracts\Dependencies\EbtcBase.sol

5: import "./BaseMath.sol";
6: import "./EbtcMath.sol";
7: import "../Interfaces/IActivePool.sol";
8: import "../Interfaces/IPriceFeed.sol";
9: import "../Interfaces/IEbtcBase.sol";
10: import "../Dependencies/ICollateralToken.sol";

packages\contracts\contracts\Dependencies\ERC3156FlashLender.sol

5: import "../Interfaces/IERC3156FlashLender.sol";
6: import "../Interfaces/IWETH.sol";

packages\contracts\contracts\Dependencies\RolesAuthority.sol

6: import "./EnumerableSet.sol";

packages\contracts\contracts\Interfaces\IActivePool.sol

5: import "./IPool.sol";

packages\contracts\contracts\Interfaces\IBorrowerOperations.sol

4: import "./IPositionManagers.sol";

packages\contracts\contracts\Interfaces\ICdpManager.sol

5: import "./IEbtcBase.sol";
6: import "./ICdpManagerData.sol";

packages\contracts\contracts\Interfaces\ICdpManagerData.sol

5: import "./ICollSurplusPool.sol";
6: import "./IEBTCToken.sol";
7: import "./ISortedCdps.sol";
8: import "./IActivePool.sol";
9: import "./IRecoveryModeGracePeriod.sol";
10: import "../Dependencies/ICollateralTokenOracle.sol";

packages\contracts\contracts\Interfaces\IEbtcBase.sol

5: import "./IPriceFeed.sol";

packages\contracts\contracts\Interfaces\IEBTCToken.sol

5: import "../Dependencies/IERC20.sol";
6: import "../Dependencies/IERC2612.sol";

packages\contracts\contracts\Interfaces\IERC3156FlashLender.sol

5: import "./IERC3156FlashBorrower.sol";


0xRobocop Q

The following criteria are used for suggested severity:

- L - Low Severity -> Some risk

- NC - Non-Critical / Informational -> Minor suggestions

# L-01 Normal liquidations at the EUSD and PeUSD vaults do not take into account providers preferences over their funds.

The `liquidation` function in the EUSD and PeUSD vault contracts only validates that the provider has granted an allowance to the vault greater than zero, which may impact the liquidation provider's preferences since they cannot specify how much eUSD they are willing to spend to participate as liquidations providers. This behavior is also inconsistent with super liquidations, which validate that the provider has approved at least the amount of eUSD that will be repaid with their funds.

# L-02 setvaultMintPaused at the configurator cannot be called by the TIMELOCK

The comments above `setvaultMintPaused` says:

```solidity
@dev This function can only be called by accounts with ADMIN or higher privilege.
```

The function is implemented as:

```solidity
function setvaultMintPaused(address pool, bool isActive) external checkRole(ADMIN) {
    vaultMintPaused[pool] = isActive;
}
```

The `checkRole` modifier is implemented as:

```solidity
modifier checkRole(bytes32 role) {
   GovernanceTimelock.checkRole(role, msg.sender);
   _;
}
```

The `checkRole` at the governance timelock is implemented as:

```solidity
function checkRole(bytes32 role, address _sender) public view  returns(bool){
        return hasRole(role, _sender) || hasRole(DAO, _sender);
}
```

It means that only admin or dao can call it, althoug timelock is a role greater than admin.

# L-03 getClaimableUSD view function at the ProtocolRewardsPool contract returns an incorrect value.

The function is coded as follows:

```solidity
function getClaimAbleUSD(address user) external view returns (uint256 amount) {
   amount = IEUSD(configurator.getEUSDAddress()).getMintedEUSDByShares(earned(user));
}
```

The function treats all the tokens a user

// Code block 1 (solidity):
@dev This function can only be called by accounts with ADMIN or higher privilege.

// Code block 2 (solidity):
function setvaultMintPaused(address pool, bool isActive) external checkRole(ADMIN) {
    vaultMintPaused[pool] = isActive;
}

// Code block 3 (solidity):
modifier checkRole(bytes32 role) {
   GovernanceTimelock.checkRole(role, msg.sender);
   _;
}

// Code block 4 (solidity):
function checkRole(bytes32 role, address _sender) public view  returns(bool){
        return hasRole(role, _sender) || hasRole(DAO, _sender);
}

// Code block 5 (solidity):
function getClaimAbleUSD(address user) external view returns (uint256 amount) {
   amount = IEUSD(configurator.getEUSDAddress()).getMintedEUSDByShares(earned(user));
}

@dev This function can only be called by accounts with ADMIN or higher privilege.

function setvaultMintPaused(address pool, bool isActive) external checkRole(ADMIN) {
    vaultMintPaused[pool] = isActive;
}

modifier checkRole(bytes32 role) {
   GovernanceTimelock.checkRole(role, msg.sender);
   _;
}

function checkRole(bytes32 role, address _sender) public view  returns(bool){
        return hasRole(role, _sender) || hasRole(DAO, _sender);
}

function getClaimAbleUSD(address user) external view returns (uint256 amount) {
   amount = IEUSD(configurator.getEUSDAddress()).getMintedEUSDByShares(earned(user));
}


JP_Courses G

0. RdpxV2Core::settle() - Gas optimization possible in `for loop`.

https://github.com/code-423n4/2023-08-dopex/blob/e96aaa5ea21f11b29d828dbe2d0745974cd046ed/contracts/core/RdpxV2Core.sol#L775-L777

Current code:
```solidity
    for (uint256 i = 0; i < optionIds.length; i++) {  /// @audit-issue GAS
      optionsOwned[optionIds[i]] = false;
    }
```

Recommended gas optimizations:
```solidity
 ++ uint256 optionIdsLength = optionIds.length;
 ++ for (uint256 i; i < optionIdsLength;) {
      optionsOwned[optionIds[i]] = false;

 ++   unchecked {
 ++   	i++;
 ++   }
    }
```

1. RdpxV2Core::bondWithDelegate() - Gas optimization possible in `for loop`.

https://github.com/code-423n4/2023-08-dopex/blob/e96aaa5ea21f11b29d828dbe2d0745974cd046ed/contracts/core/RdpxV2Core.sol#L836-L867

Recommendation:

```solidity
 ++ uint256 _amountsLength = _amounts.length;
 ++ for (uint256 i; i < _amountsLength;) {

        /// `for loop` logic

 ++     unchecked {
 ++         i++;
 ++     }
    }
```

2.

https://github.com/code-423n4/2023-08-dopex/blob/e96aaa5ea21f11b29d828dbe2d0745974cd046ed/contracts/core/RdpxV2Core.sol#L167-L170

Existing code/`for loop`:
```solidity
    for (uint256 i = 0; i < tokens.length; i++) {
      token = IERC20WithBurn(tokens[i]);
      token.safeTransfer(msg.sender, token.balanceOf(address(this)));
    }
```

Recommendation:
```solidity
 ++ uint256 tokensLength = tokens.length;
 ++ for (uint256 i; i < tokensLength;) {
      token = IERC20WithBurn(tokens[i]);
      token.safeTransfer(msg.sender, token.balanceOf(address(this)));
 ++   unchecked {
 ++       i++;
 ++   }
    }
```

// Code block 1 (solidity):
for (uint256 i = 0; i < optionIds.length; i++) {  /// @audit-issue GAS
      optionsOwned[optionIds[i]] = false;
    }

// Code block 2 (solidity):
++ uint256 optionIdsLength = optionIds.length;
 ++ for (uint256 i; i < optionIdsLength;) {
      optionsOwned[optionIds[i]] = false;

 ++   unchecked {
 ++   	i++;
 ++   }
    }

// Code block 3 (solidity):
++ uint256 _amountsLength = _amounts.length;
 ++ for (uint256 i; i < _amountsLength;) {

        /// `for loop` logic

 ++     unchecked {
 ++         i++;
 ++     }
    }

// Code block 4 (solidity):
for (uint256 i = 0; i < tokens.length; i++) {
      token = IERC20WithBurn(tokens[i]);
      token.safeTransfer(msg.sender, token.balanceOf(address(this)));
    }

// Code block 5 (solidity):
++ uint256 tokensLength = tokens.length;
 ++ for (uint256 i; i < tokensLength;) {
      token = IERC20WithBurn(tokens[i]);
      token.safeTransfer(msg.sender, token.balanceOf(address(this)));
 ++   unchecked {
 ++       i++;
 ++   }
    }

for (uint256 i = 0; i < optionIds.length; i++) {  /// @audit-issue GAS
      optionsOwned[optionIds[i]] = false;
    }

++ uint256 optionIdsLength = optionIds.length;
 ++ for (uint256 i; i < optionIdsLength;) {
      optionsOwned[optionIds[i]] = false;

 ++   unchecked {
 ++   	i++;
 ++   }
    }

++ uint256 _amountsLength = _amounts.length;
 ++ for (uint256 i; i < _amountsLength;) {

        /// `for loop` logic

 ++     unchecked {
 ++         i++;
 ++     }
    }

for (uint256 i = 0; i < tokens.length; i++) {
      token = IERC20WithBurn(tokens[i]);
      token.safeTransfer(msg.sender, token.balanceOf(address(this)));
    }

++ uint256 tokensLength = tokens.length;
 ++ for (uint256 i; i < tokensLength;) {
      token = IERC20WithBurn(tokens[i]);
      token.safeTransfer(msg.sender, token.balanceOf(address(this)));
 ++   unchecked {
 ++       i++;
 ++   }
    }


RaymondFam Q

## Impractical upper bound limit in `_requireValidMaxFeePercentage()`
In `_requireValidMaxFeePercentage()` of BorrowerOperations.sol, the upper bound of `_maxFeePercentage` is `DECIMAL_PRECISION`, i.e. 1e18 (or 100%). However, when [`getBorrowingFee()`](https://github.com/code-423n4/2023-02-ethos/blob/main/Ethos-Core/contracts/TroveManager.sol#L1471-L1473) is eventually invoked by [`_triggerBorrowingFee()`](https://github.com/code-423n4/2023-02-ethos/blob/main/Ethos-Core/contracts/BorrowerOperations.sol#L421), the output returned will at most be equal to [`MAX_BORROWING_FEE`](https://github.com/code-423n4/2023-02-ethos/blob/main/Ethos-Core/contracts/TroveManager.sol#L1467), which is [5%](https://github.com/code-423n4/2023-02-ethos/blob/main/Ethos-Core/contracts/TroveManager.sol#L55). As such, `_requireValidMaxFeePercentage()` should be refactored as follows, regardless of the minimal impact this has on [`_requireUserAcceptsFee()`](https://github.com/code-423n4/2023-02-ethos/blob/main/Ethos-Core/contracts/Dependencies/LiquityBase.sol#L90), to be more expediently in line with the logic flow entailed:

[File: BorrowerOperations.sol#L648-L656](https://github.com/code-423n4/2023-02-ethos/blob/main/Ethos-Core/contracts/BorrowerOperations.sol#L648-L656)

```diff
    function _requireValidMaxFeePercentage(uint _maxFeePercentage, bool _isRecoveryMode) internal pure {
        if (_isRecoveryMode) {
-            require(_maxFeePercentage <= DECIMAL_PRECISION,
                "Max fee percentage must less than or equal to 100%");
+            require(_maxFeePercentage <= 5e15,
                "Max fee percentage must less than or equal to 5%");
        } else {
-            require(_maxFeePercentage >= BORROWING_FEE_FLOOR && _maxFeePercentage <= DECIMAL_PRECISION,
                "Max fee percentage must be between 0.5% and 100%");
+            require(_maxFeePercentage >= BORROWING_FEE_FLOOR && _maxFeePercentage <= 5e15,
                "Max fee percentage must be betwe

## Uninitialized `baseRate` till the first call on `redeemCollateral()`
The impact, though low, is twofold. First off, the output of `getBorrowingFee()` is always going to be `BORROWING_FEE_FLOOR`, i.e. [0.5%](https://github.com/code-423n4/2023-02-ethos/blob/main/Ethos-Core/contracts/Dependencies/LiquityBase.sol#L30) because `_baseRate == 0`:

[File: TroveManager.sol#L1464-L1469](https://github.com/code-423n4/2023-02-ethos/blob/main/Ethos-Core/contracts/TroveManager.sol#L1464-L1469)

Next, when `baseRate` finally gets assigned via [`updateBaseRateFromRedemption()`](https://github.com/code-423n4/2023-02-ethos/blob/main/Ethos-Core/contracts/TroveManager.sol#L1408-L1417), increasing the `baseRate` based on the amount redeemed, as a proportion of total supply, is going to be minimally negligible unless the redemption amount is significantly sizable. And, if subsequently LUSD borrowing operations exceed redemptions, `baseRate` is as good as zero comparatively in [5e15, 5e16].

In another words, this makes the complexity of introducing a decaying factor pegged to a half-life of 720 minutes pretty much obsolete considering the borrowing rate stays always at 0.5%.

Consider having `_calcDecayedBaseRate()` refactored as follows if it is going to take a while before the first redemption is made. Better yet, return `0` if `baseRate` falls below a reasonable dust value:

[File: TroveManager.sol#L1509-L1514](https://github.com/code-423n4/2023-02-ethos/blob/main/Ethos-Core/contracts/TroveManager.sol#L1509-L1514)

TroveManager.sol#L1471-L1473, BorrowerOperations.sol#L421, TroveManager.sol#L1467, TroveManager.sol#L55, LiquityBase.sol#L90, BorrowerOperations.sol#L648-L656, LiquityBase.sol#L30, TroveManager.sol#L1464-L1469, TroveManager.sol#L1408-L1417, TroveManager.sol#L1509-L1514


Breeje Q

## QA Report

| |Issue|Instances|
|-|:-|:-:|
| [L-1](#L-1) | USE OF FLOATING PRAGMA | 13 |
| [L-2](#L-2) | MISSING CONTRACT-EXISTENCE CHECKS BEFORE LOW-LEVEL CALLS | 6 |
| [L-3](#L-3) | CONSIDER USING A TWO-STEP-TRANSFER OF OWNERSHIP | 2 |
| [L-4](#L-4) | POSSIBLE REENTRACY ATTACK | 2 |
| [NC-1](#NC-1) | USE REQUIRE INSTEAD OF ASSERT | 2 |
| [NC-2](#NC-2) | UNUSED FUNCTIONAL PARAMETER | 1 |
| [NC-3](#NC-3) | INSTEAD OF JUST REVERTING, FUNCTION CAN BE OMITTED | 1 |

###  [L-1] USE OF FLOATING PRAGMA

Impact: [swcregistry](https://swcregistry.io/docs/SWC-103)

*Instances (13)*:
* [BasePaymaster.sol](https://github.com/code-423n4/2023-01-biconomy/blob/main/scw-contracts/contracts/smart-contract-wallet/paymasters/BasePaymaster.sol#L2)
* [BaseAccount.sol](https://github.com/code-423n4/2023-01-biconomy/blob/main/scw-contracts/contracts/smart-contract-wallet/aa-4337/core/BaseAccount.sol#L2)
* [BasePaymaster.sol](https://github.com/code-423n4/2023-01-biconomy/blob/main/scw-contracts/contracts/smart-contract-wallet/aa-4337/core/BasePaymaster.sol#L2)
* [EntryPoint.sol](https://github.com/code-423n4/2023-01-biconomy/blob/main/scw-contracts/contracts/smart-contract-wallet/aa-4337/core/EntryPoint.sol#L6)
* [SenderCreator.sol](https://github.com/code-423n4/2023-01-biconomy/blob/main/scw-contracts/contracts/smart-contract-wallet/aa-4337/core/SenderCreator.sol#L2)
* [StakeManager.sol](https://github.com/code-423n4/2023-01-biconomy/blob/main/scw-contracts/contracts/smart-contract-wallet/aa-4337/core/StakeManager.sol#L2)
* [IAccount.sol](https://github.com/code-423n4/2023-01-biconomy/blob/main/scw-contracts/contracts/smart-contract-wallet/aa-4337/interfaces/IAccount.sol#L2)
* [IAggregatedAccount.sol](https://github.com/code-423n4/2023-01-biconomy/blob/main/scw-contracts/contracts/smart-contract-wallet/aa-4337/interfaces/IAggregatedAccount.sol#L2)
* [IEntryPoint.sol](https://github.com/code-423n4/2023-01-biconomy/blob/main/scw-contracts/contracts/smart-contract-wallet/aa-4337/inter

File: Proxy.sol

28:        let result := delegatecall(gas(), target, 0, calldatasize(), 0, 0)

File: aa-4337/utils/Exec.sol

35:        success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0)

BasePaymaster.sol#L2, BaseAccount.sol#L2, EntryPoint.sol#L6, SenderCreator.sol#L2, StakeManager.sol#L2, IAccount.sol#L2, IAggregatedAccount.sol#L2

SenderCreator.sol, IAggregatedAccount.sol, BasePaymaster.sol, BaseAccount.sol, IAccount.sol, EntryPoint.sol, StakeManager.sol


Sathish9098 G

# GAS OPTIMIZATIONS

|             | Issues| Instances|
|:--------:|-------|----------|
| [G-1]   | Use a more recent version of solidity      |4 |
| [G-2]   | Setting the constructor to payable      |4 |
| [G-3]   | OPTIMIZE NAMES TO SAVE GAS      | 37|
| [G-4]   | Don't declare the variables inside the loops costs more gas       |11 |
| [G-5]   | Avoid contract existence checks by using low level calls     | 19|
| [G-6]   |  ADD UNCHECKED {} FOR SUBTRACTIONS WHERE THE OPERANDS CANNOT UNDERFLOW BECAUSE OF A PREVIOUS REQUIRE() OR IF-STATEMENT       |1 |
| [G-7]   | Public function not called by contract declare external to save gas     | 2|
| [G-8]   | With assembly, .call (bool success) transfer can be done gas-optimized      |3 |
| [G-9]   | Empty blocks should be removed or emit something      | 4|
| [G-10]   | Usage of uints/ints smaller than 32 bytes (256 bits) incurs overhead      | 2|
| [G-11]   |  Private functions only called once can be inlined to save gas      |1 |
| [G-12]   | Make 3 event parameters indexed when possible      | 5|
| [G-13]   | Save gas with address(0) checks before transfer ownership      | 4|
| [G-14]   | Gas overflow during iteration (DoS)      | 4|
| [G-15]   | Sort Solidity operations using short-circuit mode      | 1|
| [G-16]   | Save gas with the use of the specific import statement      | 4|
| [G-17]   | Instead of calculating the value with keccak256() every time the contract is made pre calculate them before and only give the result to a constant      | 3|

### [G-1] Use a more recent version of solidity

INSTANCES (4):

In 0.8.15 the conditions necessary for inlining are relaxed. Benchmarks show that the change significantly decreases the bytecode size (which impacts the deployment cost) while the effect on the runtime gas usage is smaller.

In 0.8.17 prevent the incorrect removal of storage writes before calls to Yul functions that conditionally terminate the external EVM call; Simplify the starting offset of zero-length ope


niki Q

### Unsafe ERC20 Operation(s)

#### Findings:
```
anja\RewardsManager.sol::250 => IERC721(address(positionManager)).transferFrom(msg.sender, address(this), tokenId_);
anja\RewardsManager.sol::302 => IERC721(address(positionManager)).transferFrom(address(this), msg.sender, tokenId_);
```

// Code block 1 (unknown):
anja\RewardsManager.sol::250 => IERC721(address(positionManager)).transferFrom(msg.sender, address(this), tokenId_);
anja\RewardsManager.sol::302 => IERC721(address(positionManager)).transferFrom(address(this), msg.sender, tokenId_);


Silvermist Q

## Emitting event before it happens
```
function setFlashloanFee(uint256 fee) external checkRole(TIMELOCK) {
        if (fee > 10_000) revert('EL');
        emit FlashloanFeeUpdated(fee);
        flashloanFee = fee;
    }
```
https://github.com/code-423n4/2023-06-lybra/blob/7b73ef2fbb542b569e182d9abf79be643ca883ee/contracts/lybra/configuration/LybraConfigurator.sol#L253-L257

## Not implemented function logic
```
     /**
     * @notice Update user's claimable reward data and record the timestamp.
     */
    function refreshReward(address _account) external updateReward(_account) {}
```
https://github.com/code-423n4/2023-06-lybra/blob/7b73ef2fbb542b569e182d9abf79be643ca883ee/contracts/lybra/miner/EUSDMiningIncentives.sol#L171-L174

## Isn't check if _contracts and _bools arrays are equal
It is assumed that the two arrays will be equal and this is not checked. But if the _contracts array has more values than _bools, the pools that have no corresponding values from _bools will be set as default to false.

```
    function setTokenMiner(address[] calldata _contracts, bool[] calldata _bools) external checkRole(TIMELOCK) {
        for (uint256 i = 0; i < _contracts.length; i++) {
            tokenMiner[_contracts[i]] = _bools[i];
            emit tokenMinerChanges(_contracts[i], _bools[i]);
        }
    }
```

https://github.com/code-423n4/2023-06-lybra/blob/7b73ef2fbb542b569e182d9abf79be643ca883ee/contracts/lybra/configuration/LybraConfigurator.sol#L235-L240

## Missing require check
It is written in the comments that 'amount' must me higher than 0 but that isn't checked.
Add require(amount > 0, "ZERO_MINT");
```
     * Requirements:
     * - `onBehalfOf` cannot be the zero address.
     * - `amount` Must be higher than 0.
     * @dev Calling the internal`_repay`function.
     */
    function burn(address onBehalfOf, uint256 amount) external {
        require(onBehalfOf != address(0), "BURN_TO_THE_ZERO_ADDRESS");
        _repay(msg.sender, onBehalfOf, amount);
    }

// Code block 1 (unknown):
function setFlashloanFee(uint256 fee) external checkRole(TIMELOCK) {
        if (fee > 10_000) revert('EL');
        emit FlashloanFeeUpdated(fee);
        flashloanFee = fee;
    }

// Code block 2 (unknown):
/**
     * @notice Update user's claimable reward data and record the timestamp.
     */
    function refreshReward(address _account) external updateReward(_account) {}

// Code block 3 (unknown):
function setTokenMiner(address[] calldata _contracts, bool[] calldata _bools) external checkRole(TIMELOCK) {
        for (uint256 i = 0; i < _contracts.length; i++) {
            tokenMiner[_contracts[i]] = _bools[i];
            emit tokenMinerChanges(_contracts[i], _bools[i]);
        }
    }


0x6980 G

# 1. Use assembly to write address storage values
- [EthRouter.sol#L91](https://github.com/code-423n4/2023-04-caviar/blob/cd8a92667bcb6657f70657183769c244d04c015c/src/EthRouter.sol#L91)
```js
File: src/EthRouter.sol

90:    constructor(address _royaltyRegistry) {
91:        royaltyRegistry = _royaltyRegistry;
90:    }
```
- [Factory.sol#L130](https://github.com/code-423n4/2023-04-caviar/blob/cd8a92667bcb6657f70657183769c244d04c015c/src/Factory.sol#L130)
- [Factory.sol#L136](https://github.com/code-423n4/2023-04-caviar/blob/cd8a92667bcb6657f70657183769c244d04c015c/src/Factory.sol#L136)
```js
File: src/Factory.sol

129:    function setPrivatePoolMetadata(address _privatePoolMetadata) public onlyOwner {
130:        privatePoolMetadata = _privatePoolMetadata;
131:    }

135:    function setPrivatePoolImplementation(address _privatePoolImplementation) public onlyOwner {
136:        privatePoolImplementation = _privatePoolImplementation;
137:    }
```
Recommendation Code:
```js
+                  assembly {
+                      sstore(owner.slot, _owner)
+                  }
```
# 2. Use nested ```if``` and, avoid multiple check combinations
Using nested is cheaper than using && multiple check combinations. There are more advantages, such as easier to read code and better coverage reports.
- [EthRouter.sol#L101](https://github.com/code-423n4/2023-04-caviar/blob/cd8a92667bcb6657f70657183769c244d04c015c/src/EthRouter.sol#L101)
- [EthRouter.sol#L154](https://github.com/code-423n4/2023-04-caviar/blob/cd8a92667bcb6657f70657183769c244d04c015c/src/EthRouter.sol#L154)
- [EthRouter.sol#L228](https://github.com/code-423n4/2023-04-caviar/blob/cd8a92667bcb6657f70657183769c244d04c015c/src/EthRouter.sol#L228)
- [EthRouter.sol#L256](https://github.com/code-423n4/2023-04-caviar/blob/cd8a92667bcb6657f70657183769c244d04c015c/src/EthRouter.sol#L256)
```js
File: src/EthRouter.sol

101:         if (block.timestamp > deadline && deadline != 0) {
102:             rever

// Code block 1 (js):
File: src/EthRouter.sol

90:    constructor(address _royaltyRegistry) {
91:        royaltyRegistry = _royaltyRegistry;
90:    }

// Code block 2 (js):
File: src/Factory.sol

129:    function setPrivatePoolMetadata(address _privatePoolMetadata) public onlyOwner {
130:        privatePoolMetadata = _privatePoolMetadata;
131:    }

135:    function setPrivatePoolImplementation(address _privatePoolImplementation) public onlyOwner {
136:        privatePoolImplementation = _privatePoolImplementation;
137:    }

// Code block 3 (js):
+                  assembly {
+                      sstore(owner.slot, _owner)
+                  }

EthRouter.sol#L91, Factory.sol#L130, Factory.sol#L136, EthRouter.sol#L101, EthRouter.sol#L154, EthRouter.sol#L228, EthRouter.sol#L256


nzm_ G

### <a> += <b> costs more gas than <a> = <a> + <b> for state variables

Using the addition (or subtraction) operator instead of plus-equals (minus-equals) saves 13 gas for state variables and 7 gas for `mapping` to `struct` per iteration.

9 Instances found:
https://github.com/code-423n4/2023-05-ajna/blob/main/ajna-grants/src/grants/GrantFund.sol#L62
https://github.com/code-423n4/2023-05-ajna/blob/main/ajna-grants/src/grants/base/ExtraordinaryFunding.sol#L78
https://github.com/code-423n4/2023-05-ajna/blob/main/ajna-grants/src/grants/base/ExtraordinaryFunding.sol#L145
https://github.com/code-423n4/2023-05-ajna/blob/main/ajna-grants/src/grants/base/StandardFunding.sol#L217
https://github.com/code-423n4/2023-05-ajna/blob/main/ajna-grants/src/grants/base/StandardFunding.sol#L648
https://github.com/code-423n4/2023-05-ajna/blob/main/ajna-grants/src/grants/base/StandardFunding.sol#L673
https://github.com/code-423n4/2023-05-ajna/blob/main/ajna-grants/src/grants/base/StandardFunding.sol#L676
https://github.com/code-423n4/2023-05-ajna/blob/main/ajna-core/src/PositionManager.sol#L320
https://github.com/code-423n4/2023-05-ajna/blob/main/ajna-core/src/PositionManager.sol#L321

### Some of `memory` input arguments can be changed to `calldata`

If function's dynamic arguments are not modified it is cheaper to use `calldata` than `memory`.

9 Instances found:
https://github.com/code-423n4/2023-05-ajna/blob/main/ajna-grants/src/grants/base/Funding.sol#L54-L56
https://github.com/code-423n4/2023-05-ajna/blob/main/ajna-grants/src/grants/base/Funding.sol#L153-L155
https://github.com/code-423n4/2023-05-ajna/blob/main/ajna-grants/src/grants/base/ExtraordinaryFunding.sol#L57-L59
https://github.com/code-423n4/2023-05-ajna/blob/main/ajna-grants/src/grants/base/ExtraordinaryFunding.sol#L87-L89
https://github.com/code-423n4/2023-05-ajna/blob/main/ajna-grants/src/grants/base/StandardFunding.sol#L344-L346
https://github.com/code-423n4/2023-05-ajna/blob/main/ajna-grants/src/grants/base/StandardFu

 // check that the voter has enough voting power remaining to cast the vote
 if (cumulativeVotePowerUsed > votingPower) revert InsufficientVotingPower();

 // update voter voting power accumulator
 voter_.remainingVotingPower = votingPower - cumulativeVotePowerUsed;

GrantFund.sol#L62, ExtraordinaryFunding.sol#L78, ExtraordinaryFunding.sol#L145, StandardFunding.sol#L217, StandardFunding.sol#L648, StandardFunding.sol#L673, StandardFunding.sol#L676, PositionManager.sol#L320, PositionManager.sol#L321, Funding.sol#L54-L56, Funding.sol#L153-L155, ExtraordinaryFunding.sol#L57-L59, ExtraordinaryFunding.sol#L87-L89, StandardFunding.sol#L344-L346

GrantFund.sol, PositionManager.sol, StandardFunding.sol, Funding.sol, ExtraordinaryFunding.sol


0xAgro G

# Gas Report
## Finding Summary
||Issue|Instances|
|-|-|-|
|[G-01]|Bit Shift(s) Not Used For MUL/DIV/MOD of Powers of 2|9|
|[G-02]|`uint256` Iterator Checked Each Iteration|7|
|[G-03]|&& In If Statement(s)|5|
|[G-04]|`i++`/`i+=1` Used Over `++i`|[+4](https://gist.github.com/Picodes/0a53b4abfc71e0b9998e8b09aa283fb3)|
|[G-05]|`unchecked` Not Used on Overflow / Underflow Proof Arithmetic|4|
|[G-06]|&& In Require Statement(s)|3|

### [G-01] Bit Shift(s) Not Used For MUL/DIV/MOD of Powers of 2

Bitwise operations usually save on gas. Expressions that deal with unsigned integers, a power of 2 and the operations MUL/DIV/MOD can often be re-written with bitwise shifts.

#### Findings:

*/scw-contracts/contracts/smart-contract-wallet/SmartAccount.sol*
Links: [200](https://github.com/code-423n4/2023-01-biconomy/blob/main/scw-contracts/contracts/smart-contract-wallet/SmartAccount.sol#L200), [224](https://github.com/code-423n4/2023-01-biconomy/blob/main/scw-contracts/contracts/smart-contract-wallet/SmartAccount.sol#L224).
```solidity
200:	uint256 startGas = gasleft() + 21000 + msg.data.length * 8;
224:	require(gasleft() >= max((_tx.targetTxGas * 64) / 63,_tx.targetTxGas + 2500) + 500, "BSA010");
```

*/scw-contracts/contracts/smart-contract-wallet/libs/Math.sol*
Links: [36](https://github.com/code-423n4/2023-01-biconomy/blob/main/scw-contracts/contracts/smart-contract-wallet/libs/Math.sol#L36).
```solidity
36:	return (a & b) + (a ^ b) / 2;
```

### [G-02] `uint256` Iterator Checked Each Iteration

A `uint256` iterator will not overflow before the check variable overflows. Unchecking the iterator increment saves gas.
**Example**
```solidity
//From
for (uint256 i; i < len; ++i) {
	//Do Something
}
//To
for (uint256 i; i < len;) {
	//Do Something
	unchecked { ++i; }
}
```

#### Findings:

*/scw-contracts/contracts/smart-contract-wallet/aa-4337/core/EntryPoint.sol*
Links: [74](https://github.com/code-423n4/2023-01-biconomy/blob/main/scw-contracts/contracts/smart-contract-wallet/aa-

// Code block 1 (solidity):
200:	uint256 startGas = gasleft() + 21000 + msg.data.length * 8;
224:	require(gasleft() >= max((_tx.targetTxGas * 64) / 63,_tx.targetTxGas + 2500) + 500, "BSA010");

// Code block 2 (solidity):
36:	return (a & b) + (a ^ b) / 2;

// Code block 3 (solidity):
//From
for (uint256 i; i < len; ++i) {
	//Do Something
}
//To
for (uint256 i; i < len;) {
	//Do Something
	unchecked { ++i; }
}

200:	uint256 startGas = gasleft() + 21000 + msg.data.length * 8;
224:	require(gasleft() >= max((_tx.targetTxGas * 64) / 63,_tx.targetTxGas + 2500) + 500, "BSA010");

36:	return (a & b) + (a ^ b) / 2;

//From
for (uint256 i; i < len; ++i) {
	//Do Something
}
//To
for (uint256 i; i < len;) {
	//Do Something
	unchecked { ++i; }
}