xanoutas/solidity-security-findings huggingface dataset:
One proposal can be vetoed and cancelled  at sametime
Audit: 2023-07-nounsdao-findings
Severity: MEDIUM

# Lines of code

https://github.com/nounsDAO/nouns-monorepo/blob/cf7c6a782353da865977cfaa3eb22773c525cb39/packages/nouns-contracts/contracts/governance/NounsDAOLogicV2.sol#L359-L416
https://github.com/nounsDAO/nouns-monorepo/blob/cf7c6a782353da865977cfaa3eb22773c525cb39/packages/nouns-contracts/contracts/governance/NounsDAOLogicV2.sol#L455-L461


# Vulnerability details

## Impact
One proposal can be vetoed and canceled at the same time, it may cause very inaccurate results when calling `state` to get the proposal state.

## Proof of Concept
```solidity
    function state(uint256 proposalId) public view returns (ProposalState) {
        require(proposalCount >= proposalId, 'NounsDAO::state: invalid proposal id');
        Proposal storage proposal = _proposals[proposalId];
        if (proposal.vetoed) {
            return ProposalState.Vetoed;
        } else if (proposal.canceled) {
            return ProposalState.Canceled;
``` 


It seems that there is no limitation in the function `veto` and function `cancel`; if the proposal is canceled, it can still be vetoed, which make it very confusing when call the function `state` to get the proposal state.

## Tools Used
manual
## Recommended Mitigation Steps
ensure one proposal can only be canceled or vetoed


## Assessed type

Access Control
Type Casting Vulnerability in `safe32` and `safe16` Functions.
Audit: 2023-07-nounsdao-findings
Severity: MEDIUM

# Lines of code

https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3DynamicQuorum.sol#L77-L121
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3DynamicQuorum.sol#L145-L155


# Vulnerability details

## Impact
`safe32` and `safe16` these internal functions are used for type casting and can be vulnerable to attack if the input values are manipulated to exceed the maximum range of the target type.

## Proof of Concept
In the [`getDynamicQuorumParamsAt`](https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3DynamicQuorum.sol#L77-L121) function of the `NounsDAOV3DynamicQuorum` library. These functions aim to ensure that the input values do not exceed the maximum range of the target types (`uint32` and `uint16` respectively). However, a vulnerability exists in these functions, allowing an attacker to manipulate the input values and potentially exceed the maximum range.

```solidity
function getDynamicQuorumParamsAt(NounsDAOStorageV3.StorageV3 storage ds, uint256 blockNumber_)
    internal
    view
    returns (NounsDAOStorageV3.DynamicQuorumParams memory)
{
    uint32 blockNumber = safe32(blockNumber_, 'NounsDAO::getDynamicQuorumParamsAt: block number exceeds 32 bits');
    uint256 len = ds.quorumParamsCheckpoints.length;

    if (len == 0) {
        return
            NounsDAOStorageV3.DynamicQuorumParams({
                minQuorumVotesBPS: safe16(ds.quorumVotesBPS),
                maxQuorumVotesBPS: safe16(ds.quorumVotesBPS),
                quorumCoefficient: 0
            });
    }

    if (ds.quorumParamsCheckpoints[len - 1].fromBlock <= blockNumber) {
        return ds.quorumParamsCheckpoints[len - 1].params;
    }

    if (ds.quorumParamsCheckpoints[0].fromBlock > blockNumber) {
        return
            NounsDAOStorageV3.DynamicQuorumParams({
                minQuorumVotesBPS: safe16(ds.quorumVotesBPS),
                maxQuorumVotesBPS: safe16(ds.quorumVotesBPS),
                quorumCoefficient: 0
            });
    }

    uint256 lower = 0;
    uint256 upper = len - 1;
    while (upper > lower) {
        uint256 center = upper - (upper - lower) / 2;
        NounsDAOStorageV3.DynamicQuorumParamsCheckpoint memory cp = ds.quorumParamsCheckpoints[center];
        if (cp.fromBlock == blockNumber) {
            return cp.params;
        } else if (cp.fromBlock < blockNumber) {
            lower = center;
        } else {
            upper = center - 1;
        }
    }
    return ds.quorumParamsCheckpoints[lower].params;
}
```

The `blockNumber_` parameter is not sufficiently validated for arbitrary values. The `safe32` function is used to convert the `blockNumber_` parameter to a `uint32` value, but it does not enforce any bounds checking on the input value.

By supp
Manipulation of Quorum Parameters Retrieval.
Audit: 2023-07-nounsdao-findings
Severity: MEDIUM

# Lines of code

https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3DynamicQuorum.sol#L82
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3DynamicQuorum.sol#L77-L121


# Vulnerability details

## Impact
If an attacker can manipulate the `blockNumber_` parameter, they can retrieve different quorum parameter values, affecting the quorum calculation for proposal voting. This manipulation could give the attacker an unfair advantage in influencing the outcome of proposals or disrupting the system's intended behavior, and can affect all users of the contract, as it can impact the governance process and the accuracy of the quorum calculation.

## Proof of Concept
[NounsDAOV3DynamicQuorum.sol#L82](https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3DynamicQuorum.sol#L82)
```solidity
        uint32 blockNumber = safe32(blockNumber_, 'NounsDAO::getDynamicQuorumParamsAt: block number exceeds 32 bits');
```
In this line, the `blockNumber_` parameter is cast to a `uint32` value using the `safe32` function. The purpose of this line is to ensure that the `blockNumber_` does not exceed 32 bits. However, the input `blockNumber_` is not validated or sanitized before the cast. If an attacker can manipulate the `blockNumber_` value to exceed the maximum value of a `uint32`, it can lead to unexpected behavior or vulnerabilities.

The [`getDynamicQuorumParamsAt`](https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3DynamicQuorum.sol#L77-L121) function retrieves the dynamic quorum parameters at a specific block number. Let's analyze the function.
```solidity
function getDynamicQuorumParamsAt(NounsDAOStorageV3.StorageV3 storage ds, uint256 blockNumber_)
    internal
    view
    returns (NounsDAOStorageV3.DynamicQuorumParams memory)
{
    // ...

    if (ds.quorumParamsCheckpoints[len - 1].fromBlock <= blockNumber) {
        return ds.quorumParamsCheckpoints[len - 1].params;
    }

    // ...

    uint256 lower = 0;
    uint256 upper = len - 1;
    while (upper > lower) {
        uint256 center = upper - (upper - lower) / 2;
        NounsDAOStorageV3.DynamicQuorumParamsCheckpoint memory cp = ds.quorumParamsCheckpoints[center];
        if (cp.fromBlock == blockNumber) {
            return cp.params;
        } else if (cp.fromBlock < blockNumber) {
            lower = center;
        } else {
            upper = center - 1;
        }
    }
    return ds.quorumParamsCheckpoints[lower].params;
}
```
To exploit this vulnerability, an attacker could try to provide a manipulated `blockNumber_` value that corresponds to a specific checkpoint in the `quorumParamsCheckpoints` array. By doing so, the attacker can
The auction parameters can be changed during ongoing auction
Audit: 2023-07-nounsdao-findings
Severity: MEDIUM

# Lines of code

https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/fork/newdao/NounsAuctionHouseFork.sol#L180
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/fork/newdao/NounsAuctionHouseFork.sol#L190
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/fork/newdao/NounsAuctionHouseFork.sol#L200


# Vulnerability details

## Impact

The auction parameters can be changed anytime, even during ongoing auctions, and take effect immediately. Users may need time to react to the changes. The impacts maybe followings:
- some sudden changes may cause bidder’s transaction fail, such as `setReservePrice()` and `setMinBidIncrementPercentage()`
- some changes may change users expectation about the auction, such as  setTimeBuffer(), with different time parameters, bidders will use different strategy

We can refer to previous audits:
https://code4rena.com/reports/2022-09-nouns-builder#m-16-auction-parameters-can-be-changed-during-ongoing-auction

## Proof of Concept


As we can see ,`NounsAuctionHouseFork.sol`:
```solidity
function setTimeBuffer(uint256 _timeBuffer) external override onlyOwner {
        timeBuffer = _timeBuffer;

        emit AuctionTimeBufferUpdated(_timeBuffer);
    }

    /**
     * @notice Set the auction reserve price.
     * @dev Only callable by the owner.
     */
    function setReservePrice(uint256 _reservePrice) external override onlyOwner {
        reservePrice = _reservePrice;

        emit AuctionReservePriceUpdated(_reservePrice);
    }

    /**
     * @notice Set the auction minimum bid increment percentage.
     * @dev Only callable by the owner.
     */
    function setMinBidIncrementPercentage(uint8 _minBidIncrementPercentage) external override onlyOwner {
        minBidIncrementPercentage = _minBidIncrementPercentage;

        emit AuctionMinBidIncrementPercentageUpdated(_minBidIncrementPercentage);
    }
```

## Tools Used

vs code

## Recommended Mitigation Steps

Do not apply changed parameters on ongoing auctions
Add a timelock for the changes


## Assessed type

Error
Condition will not revert when `block.timestamp` is `==` to the compared variable(supplement)
Audit: 2023-07-nounsdao-findings
Severity: MEDIUM

# Lines of code

https://github.com/nounsDAO/nouns-monorepo/tree/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/nouns-monorepo/packages/nouns-contracts/contracts/governance/NounsDAOV3Proposals.sol#L989
https://github.com/nounsDAO/nouns-monorepo/tree/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/nouns-monorepo/packages/nouns-contracts/contracts/governance/fork/newdao/NounsAuctionHouseFork.sol#L123-L141


# Vulnerability details

Note: This risk has been included in the Automated Findings. At that time, the findings given by [MED-2](https://gist.github.com/CloudEllie/deb7d1c9c91b605555cbe604662e58cf#med2-condition-will-not-revert-when-blocktimestamp-is--to-the-compared-variable) were incomplete. I believe that the following findings should also belong to [MED-2](https://gist.github.com/CloudEllie/deb7d1c9c91b605555cbe604662e58cf#med2-condition-will-not-revert-when-blocktimestamp-is--to-the-compared-variable).

## Impact
The condition does not revert when `block.timestamp` is equal to the compared `>` or `<` variable. For example, if there is a check for `block.timestamp > proposerSignature.expirationTimestamp` then there should be a check for cases where `block.timestamp` is `==` to `proposerSignature.expirationTimestamp`

## Findings
Total: 2

[nouns-monorepo/packages/nouns-contracts/contracts/governance/NounsDAOV3Proposals.sol#L989](https://github.com/nounsDAO/nouns-monorepo/tree/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/nouns-monorepo/packages/nouns-contracts/contracts/governance/NounsDAOV3Proposals.sol#L989)
```solidity
989:         if (block.timestamp > proposerSignature.expirationTimestamp) revert SignatureExpired();
```

[nouns-monorepo/packages/nouns-contracts/contracts/governance/fork/newdao/NounsAuctionHouseFork.sol#L123-L141](https://github.com/nounsDAO/nouns-monorepo/tree/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/nouns-monorepo/packages/nouns-contracts/contracts/governance/fork/newdao/NounsAuctionHouseFork.sol#L123-L141)
```solidity
123:         require(block.timestamp < _auction.endTime, 'Auction expired');
```



## Assessed type

Timing
`NounsAuctionHouseFork.createBid()` does not check if  `msg.sender ` is contract. It may cause user loss fund.
Audit: 2023-07-nounsdao-findings
Severity: MEDIUM

# Lines of code

https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/fork/newdao/NounsAuctionHouseFork.sol#L119


# Vulnerability details

## Impact

`NounsAuctionHouseFork.createBid()` does not check if  `msg.sender ` is contract. It may cause user loss fund.
It is possible for a user to write a contract to call a function, but the user's contract does not have a function to receive funds. So when update the `lastBidder`, and the `_auction.amount` will return for the contract. However, the contract does not have the withdraw function.It will cause use lossing fund and cause bad debt.

I think we should check if  `msg.sender ` is contract or or we can design a protocol(contract) that allows users to create bids directly through the protocol and withdraw money from the protocol

## Proof of Concept

https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/fork/newdao/NounsAuctionHouseFork.sol#L119

## Tools Used

vs code

## Recommended Mitigation Steps

We should check if  `msg.sender ` is contract or we can design a protocol that allows users to create bids directly through the protocol and withdraw money from the protocol


## Assessed type

Error
`NounsAuctionHouseFork._settleAuction()` should use `safeTransferFrom()` instead of `transferFrom()`
Audit: 2023-07-nounsdao-findings
Severity: MEDIUM

# Lines of code

https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/fork/newdao/NounsAuctionHouseFork.sol#L248


# Vulnerability details

## Impact

`NounsAuctionHouseFork._settleAuction()` should use `safeTransferFrom()` instead of `transferFrom()`
Because the `_auction.bidder` maybe not support the ERC721 token. If transfer to the `_auction.bidder`, it will cause lossing fund.

## Proof of Concept

https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/fork/newdao/NounsAuctionHouseFork.sol#L248

## Tools Used

vs code

## Recommended Mitigation Steps

We should use `safeTransferFrom()` instead of `transferFrom()`, and check return value.


## Assessed type

ERC721
`NounsDAOLogicV3.initialize()` does not init the `timelockV1` parameter. It may cause `executeOnTimelockV1()` revert.
Audit: 2023-07-nounsdao-findings
Severity: MEDIUM

# Lines of code

https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOLogicV3.sol#L141


# Vulnerability details

## Impact

`NounsDAOLogicV3.initialize()` does not init the `timelockV1` parameter. When the contract is deployed, and admin forgets to call the `_setTimelocksAndAdmin()`. And then the user propose a new proposal and execute with `executeOnTimelockV1()`. It may cause `executeOnTimelockV1()` revert.

## Proof of Concept

We can check it, the `NounsDAOLogicV3.initialize()` does not init the `timelockV1` parameter. 
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOLogicV3.sol#L141

Even if the `_setTimelocksAndAdmin()` can set the new timelock. but it did not call by `NounsDAOLogicV3.initialize()`.
When the contract is deployed, and admin forgets to call the `_setTimelocksAndAdmin()`. And then the user propose a new proposal and execute with `executeOnTimelockV1()`. It may cause `executeOnTimelockV1()` revert.
```solidity
function executeOnTimelockV1(NounsDAOStorageV3.StorageV3 storage ds, uint256 proposalId) external {
        NounsDAOStorageV3.Proposal storage proposal = ds._proposals[proposalId];
        executeInternal(ds, proposal, ds.timelockV1);//@audit ds.timelockV1 is null
    }
```
## Tools Used

vs code

## Recommended Mitigation Steps

Set the `timelockV1` in init function.


## Assessed type

Error
`block.number` means different things on different L2s(Supplement)
Audit: 2023-07-nounsdao-findings
Severity: MEDIUM

# Lines of code

https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOLogicV2.sol#L211-L1063
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L226
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Proposals.sol#L168-L913
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3DynamicQuorum.sol#L131-L142
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/fork/newdao/governance/NounsDAOLogicV1Fork.sol#L288-L519
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/fork/newdao/token/base/ERC721CheckpointableUpgradeable.sol#L176-L251


# Vulnerability details

Note: This risk has been included in the Automated Findings. At that time, the findings given by [MED-1](https://gist.github.com/CloudEllie/deb7d1c9c91b605555cbe604662e58cf#med1-blocknumber-means-different-things-on-different-l2s) were incomplete. I believe that the following findings should also belong to [MED-1](https://gist.github.com/CloudEllie/deb7d1c9c91b605555cbe604662e58cf#med1-blocknumber-means-different-things-on-different-l2s).

## Impact
On Optimism, `block.number` is the L2 block number, but on Arbitrum, it's the L1 block number, and `ArbSys(address(100)).arbBlockNumber()` must be used. Furthermore, L2 block numbers often occur much more frequently than L1 block numbers (any may even occur on a per-transaction basis), so using block numbers for timing results in inconsistencies, especially when voting is involved across multiple chains. As of version 4.9, OpenZeppelin has [modified](https://blog.openzeppelin.com/introducing-openzeppelin-contracts-v4.9#governor) their governor code to use a clock rather than block numbers, to avoid these sorts of issues, but this still requires that the project [implement](https://docs.openzeppelin.com/contracts/4.x/governance#token_2) a [clock](https://eips.ethereum.org/EIPS/eip-6372) for each L2.

## Findings
Total: 40

[nouns-monorepo/packages/nouns-contracts/contracts/governance/NounsDAOLogicV2.sol#L211-L1063](https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOLogicV2.sol#L211-L1063)
```solidity
211:             nouns.getPriorVotes(msg.sender, block.number - 1) > temp.proposalThreshold,
...
236:         temp.startBlock = block.number + votingDelay;
...
258:         newProposal.creationBlock = block.number;
...
367:                 nouns.getPriorVotes(proposal.proposer, block.number - 1) <= proposal.proposalThreshold,
...
`NounsDAOLogicV1Fork.cancel()`  and `NounsDAOLogicV2.cancel()` do not check if `state(proposalId) == ProposalState.Canceled`
Audit: 2023-07-nounsdao-findings
Severity: MEDIUM

# Lines of code

https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/fork/newdao/governance/NounsDAOLogicV1Fork.sol#L452
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOLogicV2.sol#L359


# Vulnerability details

## Impact

`NounsDAOLogicV1Fork.cancel()` and `NounsDAOLogicV2.cancel()`do not check if `state(proposalId) == ProposalState.Canceled`.
If the user has already performed the cancellation but forgot, it will cause the user to perform the cancellation repeatedly and lose the gas fee

## Proof of Concept

https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/fork/newdao/governance/NounsDAOLogicV1Fork.sol#L452

https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOLogicV2.sol#L359

## Tools Used

vscode

## Recommended Mitigation Steps

We can refer to the code of V3(`NounsDAOV3Proposals.cancel()`). It check such like:
```solidity
function cancel(NounsDAOStorageV3.StorageV3 storage ds, uint256 proposalId) external {
        NounsDAOStorageV3.ProposalState proposalState = stateInternal(ds, proposalId);
        if (
            proposalState == NounsDAOStorageV3.ProposalState.Canceled ||
            proposalState == NounsDAOStorageV3.ProposalState.Defeated ||
            proposalState == NounsDAOStorageV3.ProposalState.Expired ||
            proposalState == NounsDAOStorageV3.ProposalState.Executed ||
            proposalState == NounsDAOStorageV3.ProposalState.Vetoed
        ) {
            revert CantCancelProposalAtFinalState();
        }
```





## Assessed type

Error
`ERC20Transferer.transferEntireBalance` should use `safeTransferFrom()` instead of `transferFrom()`
Audit: 2023-07-nounsdao-findings
Severity: MEDIUM

# Lines of code

https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/utils/ERC20Transferer.sol#L34


# Vulnerability details

## Impact

`ERC20Transferer.transferEntireBalance` should use `safeTransferFrom()` instead of `transferFrom()`
Some ERC20 token does not return true/false such as USDC.

## Proof of Concept

As we can see , the`transferEntireBalance()` call the `transferFrom()`
```solidity
function transferEntireBalance(address token, address to) external returns (uint256) {
        uint256 balance = IERC20(token).balanceOf(msg.sender);
        IERC20(token).transferFrom(msg.sender, to, balance);
        return balance;
    }
```


## Tools Used

vs code 

## Recommended Mitigation Steps

should use `safeTransferFrom()` instead of `transferFrom()`


## Assessed type

ERC20