xanoutas/solidity-security-findings huggingface dataset:
Gas Refund Manipulation in castRefundableVoteInternal function.
Audit: 2023-07-nounsdao-findings
Severity: HIGH

# Lines of code

https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L88-L94
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L123-L135
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L132-L134


# Vulnerability details

## Impact
[`castRefundableVote`](https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L88-L94) and [`castRefundableVoteWithReason`](https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L123-L135) functions allow users to cast a refundable vote, where the DAO is requested to refund the gas costs. Users with a positive number of votes receive gas refunds, but there are limits on the refund amount based on the DAO's balance and the gas priority fee. An attacker could attempt to manipulate the gas refund mechanism by trying to exhaust the DAO's balance to prevent refunds for legitimate voters.

Either of these impacts:

1. Manipulation of gas refunds: The attacker can exploit vulnerabilities in the gas refund calculation to receive higher gas refunds than intended, potentially draining the DAO's balance.
2. Exhaustion of DAO's balance: The attacker can perform actions to exhaust the DAO's balance, preventing refunds for legitimate voters and disrupting the fairness of the voting process.

[NounsDAOV3Votes.sol#L132-L133](https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L132-L134)
```solidity
if (votes > 0) {
    _refundGas(startGas);
}
```
This line is located in the `castRefundableVoteInternal` function, which is called by the `castRefundableVote` and `castRefundableVoteWithReason` functions. It refunds gas costs to users who have cast refundable votes.

The vulnerability in this code is that it blindly refunds gas without considering the DAO's balance or the gas priority fee. An attacker could manipulate the gas refund mechanism by finding vulnerabilities in the gas refund calculation or by trying to exhaust the DAO's balance to prevent refunds for legitimate voters.

## Proof of Concept
[castRefundableVote](https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L88-L94)
```solidity
    function castRefundableVote(
        NounsDAOStorageV3.StorageV3 storage ds,
        uint256 proposalId,
        uint8 support
    ) external {
        castRefundableVoteInternal(ds, proposalId, support, '');
    }
```

[castRefundableVot
Voting Manipulation in `castVoteDuringVotingPeriodInternal`.
Audit: 2023-07-nounsdao-findings
Severity: HIGH

# Lines of code

https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L224-L264
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L210-L264
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L222


# Vulnerability details

## Impact
The [`castVoteDuringVotingPeriodInternal`](https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L224C50-L264) function is responsible for processing votes during the voting period of a proposal. It allows users to cast their votes in favor, against, or abstain from the proposal. However, I can see the function does not properly validate the votes and does not enforce restrictions on the number of votes a user can cast. This can be exploited by an attacker to manipulate the vote counts and influence the outcome of a proposal.

## Proof of Concept
I can see that the [`castVoteDuringVotingPeriodInternal`](https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L210-L264) function handles the voting logic during the voting period, the fact that there is no validation or check for the `votes` value before updating the vote counts for different support types (against, for, abstain). This can lead to a potential overflow or manipulation of vote counts.
```solidity
function castVoteDuringVotingPeriodInternal(
    NounsDAOStorageV3.StorageV3 storage ds,
    uint256 proposalId,
    address voter,
    uint8 support
) internal returns (uint96) {
    require(support <= 2, 'NounsDAO::castVoteDuringVotingPeriodInternal: invalid vote type');
    NounsDAOStorageV3.Proposal storage proposal = ds._proposals[proposalId];
    NounsDAOStorageV3.Receipt storage receipt = proposal.receipts[voter];
    require(receipt.hasVoted == false, 'NounsDAO::castVoteDuringVotingPeriodInternal: voter already voted');

    uint96 votes = ds.nouns.getPriorVotes(voter, proposalVoteSnapshotBlock(ds, proposalId, proposal));

    bool isForVoteInLastMinuteWindow = false;
    if (support == 1) {
        isForVoteInLastMinuteWindow = (proposal.endBlock - block.number < ds.lastMinuteWindowInBlocks);
    }

    bool isDefeatedBefore = false;
    if (isForVoteInLastMinuteWindow) isDefeatedBefore = ds.isDefeated(proposal);

    if (support == 0) {
        proposal.againstVotes = proposal.againstVotes + votes;
    } else if (support == 1) {
        proposal.forVotes = proposal.forVotes + votes;
    } else if (support == 2) {
        proposal.abstainVotes = proposal.abstainVotes + votes;
    }

    // ...
}
```
The `votes` value obtained from [`ds.nouns.getPriorVote
Integer Overflow in variables `proposal.forVotes`, `proposal.againstVotes`, and `proposal.abstainVotes`.
Audit: 2023-07-nounsdao-findings
Severity: HIGH

# Lines of code

https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L232-L238
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L210-L264


# Vulnerability details

## Impact
The variables `proposal.forVotes`, `proposal.againstVotes`, and `proposal.abstainVotes` are incremented without checking for potential overflow, this can lead to integer overflow, If an attacker can exploit the integer overflow vulnerability, they could manipulate the voting results by causing the vote counts to overflow and produce incorrect values. This could lead to the approval of malicious proposals or the rejection of legitimate proposals.

## Proof of Concept
The code lines where the variables [`proposal.forVotes`, `proposal.againstVotes`,](https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L232-L238) and [`proposal.abstainVotes`](https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L232-L238) are incremented without checking for potential overflow are:

```solidity
if (support == 0) {
    proposal.againstVotes = proposal.againstVotes + votes;
} else if (support == 1) {
    proposal.forVotes = proposal.forVotes + votes;
} else if (support == 2) {
    proposal.abstainVotes = proposal.abstainVotes + votes;
}
```

These lines are part of the [`castVoteDuringVotingPeriodInternal`](https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L210-L264) function, It handles voting logic during the voting period of a proposal. The variables `proposal.forVotes`, `proposal.againstVotes`, and `proposal.abstainVotes` are incremented based on the `support` value, which represents the type of vote `(0=against, 1=for, 2=abstain)`. There is no explicit check for potential overflow in these lines of code.

The likelihood of an attacker exploiting this vulnerability is high, as the code is susceptible to a straightforward integer overflow attack. The impact is also high, as the vulnerability can lead to manipulated voting results and compromise the governance process of the Nouns DAO.

Let's consider a scenario where an attacker can exploit.

Suppose there is a governance proposal in the Nouns DAO contract to allocate a large number of tokens to a specific address. The attacker, who possesses a significant number of voting tokens, decides to exploit the vulnerability to manipulate the voting system and pass the proposal in their favor.

Here's how the attacker can exploit the vulnerability:

1. The attacker creates a proposal with the intention of allocating a large number of tokens to
Reentrancy in `castRefundableVoteInternal` Function.
Audit: 2023-07-nounsdao-findings
Severity: HIGH

# Lines of code

https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L133
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L123-L135


# Vulnerability details

## Impact
[`castRefundableVoteInternal`](https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L133) function calls `_refundGas` after emitting the `VoteCast` event.
```solidity
_refundGas(startGas);
```
It may introduce a reentrancy vulnerability. The reentrancy introduced by this bug allows an attacker to exploit the contract and manipulate its state or steal funds. By making an external call within the `_refundGas` function, an attacker can execute malicious code repeatedly before the original transaction completes.

## Proof of Concept
[castRefundableVoteInternal](https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L123-L135)
```solidity
    function castRefundableVoteInternal(
        NounsDAOStorageV3.StorageV3 storage ds,
        uint256 proposalId,
        uint8 support,
        string memory reason
    ) internal {
        uint256 startGas = gasleft();
        uint96 votes = castVoteInternal(ds, msg.sender, proposalId, support);
        emit VoteCast(msg.sender, proposalId, support, votes, reason);
        if (votes > 0) {
            _refundGas(startGas);
        }
    }
```
In the `castRefundableVoteInternal` function, In this function, the `_refundGas` function is called after emitting the `VoteCast` event. If the `_refundGas`, it may introduce a reentrancy vulnerability. 

The `castVoteInternal` function is called to handle the voting logic. After that, the `VoteCast` event is emitted. Finally, the `_refundGas` function is called to refund the gas costs if `votes > 0`.

Let's walk through a scenario where an attacker can exploit the reentrancy vulnerability in the `castRefundableVoteInternal` function.

1. The attacker creates a malicious contract and deploys it on the blockchain.

```solidity
contract MaliciousContract {
    NounsDAOV3Votes daoVotes;

    constructor(address daoVotesAddress) {
        daoVotes = NounsDAOV3Votes(daoVotesAddress);
    }

    function attack(uint256 proposalId, uint8 support) external {
        daoVotes.castRefundableVoteInternal(proposalId, support, "");
    }

    // This fallback function is called when the malicious contract receives funds
    fallback() external payable {
        // Perform the reentrancy attack here
        daoVotes.castRefundableVoteInternal(proposalId, support, "");
    }
}
```

2. The attacker identifies a target address that holds voting power in the Nouns DAO and owns some tokens.

3. The attacker interacts with
Return value of low-level .call() not checked
Audit: 2023-07-nounsdao-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact
In NounsDAOV3Votes.sol, _refundGas() function is given as,

```Solidity
File: nouns-contracts/contracts/governance/NounsDAOV3Votes.sol

295    function _refundGas(uint256 startGas) internal {
296        unchecked {
297            uint256 balance = address(this).balance;
298            if (balance == 0) {
299                return;
300            }
301            uint256 basefee = min(block.basefee, MAX_REFUND_BASE_FEE);
302            uint256 gasPrice = min(tx.gasprice, basefee + MAX_REFUND_PRIORITY_FEE);
303            uint256 gasUsed = min(startGas - gasleft() + REFUND_BASE_GAS, MAX_REFUND_GAS_USED);
304            uint256 refundAmount = min(gasPrice * gasUsed, balance);
305            (bool refundSent, ) = msg.sender.call{ value: refundAmount }('');
306            emit RefundableVote(msg.sender, refundAmount, refundSent);
307        }
308    }
```
and 

In NounsDAOLogicV2.sol, _refundGas() function is given as,

```Solidity
File: nouns-contracts/contracts/governance/NounsDAOLogicV2.sol

1033    function _refundGas(uint256 startGas) internal {
1034        unchecked {
1035            uint256 balance = address(this).balance;
1036            if (balance == 0) {
1037                return;
1038            }
1039            uint256 basefee = min(block.basefee, MAX_REFUND_BASE_FEE);
1040            uint256 gasPrice = min(tx.gasprice, basefee + MAX_REFUND_PRIORITY_FEE);
1041            uint256 gasUsed = min(startGas - gasleft() + REFUND_BASE_GAS, MAX_REFUND_GAS_USED);
1042            uint256 refundAmount = min(gasPrice * gasUsed, balance);
1043            (bool refundSent, ) = tx.origin.call{ value: refundAmount }('');
1044            emit RefundableVote(tx.origin, refundAmount, refundSent);
1045        }
1046    }
```

At above both contracts functions, Low-level primitive .call() doesn't revert in caller's context when the callee reverts. If its return value is not checked, it can lead the caller to falsely believe that the call was successful. NounsDAOLogicV2.sol _refundGas() uses .call() to transfer the refund amount to receiver i.e tx.origin in this case. If receiver reverts, this can lead to locked ETH in the contract.

By adding the require statement the contract will revert and throw an exception with the specified error message if the external call was not successful. This helps to ensure that the contract state remains consistent and avoids potential issues caused by failed executions.

**For example:**
Per solidity documentation,

In order to interface with contracts that do not adhere to the ABI, or to get more direct control over the encoding, the functions call, delegatecall and staticcall are provided. They all take a single bytes memory parameter and return the success condition (as a bool) and the returned data (bytes memor
vetoed proposal can still be executed 
Audit: 2023-07-nounsdao-findings
Severity: HIGH

# Lines of code

https://github.com/nounsDAO/nouns-monorepo/blob/cf7c6a782353da865977cfaa3eb22773c525cb39/packages/nouns-contracts/contracts/governance/NounsDAOLogicV2.sol#L389-L413


# Vulnerability details

## Impact
The vetoed proposal can still be executed; it seems that `the veto` function doesn't prevent the proposal from being executed very well.

## Proof of Concept
The lifecycle of a proposal:
propose -> queue -> execute    
or
propose -> queue -> veto
Notice function inside function veto : 
```solidity
function veto(uint256 proposalId) external {
 ...
  timelock.cancelTransaction(
   ...
} 


# deep into  cancelTransaction:
queuedTransactions[txHash] = true;
```
`veto` only changes the state of `queuedTransactions[txHash],` the state can be modified by function queue,
so if we queue a proposal after the veto, it can still be executed 
propose -> queue —> veto -> queue-> execute    
## Tools Used

manual

## Recommended Mitigation Steps 
add a strict limitation to execute the vetoed proposal 


## Assessed type

Access Control
Vulnerability in Dynamic Quorum Calculation Allows Manipulation of Required Quorum.
Audit: 2023-07-nounsdao-findings
Severity: HIGH

# Lines of code

https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3DynamicQuorum.sol#L58-L68


# Vulnerability details

## Impact
`dynamicQuorumVotes` takes the `againstVotes` and `totalSupply` as input parameters and calculates the required quorum based on these values. The function applies a fixed-point coefficient and adjusts the quorum based on the percentage of against-votes compared to the total supply.

The issue stems from the lack of validation and integrity checks on the input values. An attacker can manipulate the `againstVotes` and `totalSupply` parameters before calling the function. By passing higher values for `againstVotes`, the attacker artificially inflates the percentage of against-votes, resulting in a lower required quorum.

The `dynamicQuorumVotes` function does not validate the input values or cross-reference them with trusted external sources. This lack of validation allows an attacker to bypass the intended quorum requirements and pass proposals with a lower quorum than expected.

## Proof of Concept
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3DynamicQuorum.sol#L58-L68

```solidity
function dynamicQuorumVotes(
    uint256 againstVotes,
    uint256 totalSupply,
    NounsDAOStorageV3.DynamicQuorumParams memory params
) public pure returns (uint256) {
    uint256 againstVotesBPS = (10000 * againstVotes) / totalSupply;
    uint256 quorumAdjustmentBPS = (params.quorumCoefficient * againstVotesBPS) / 1e6;
    uint256 adjustedQuorumBPS = params.minQuorumVotesBPS + quorumAdjustmentBPS;
    uint256 quorumBPS = min(params.maxQuorumVotesBPS, adjustedQuorumBPS);
    return bps2Uint(quorumBPS, totalSupply);
}
```
The `dynamicQuorumVotes` function calculates the required quorum based on the number of against-votes (`againstVotes`), the total supply of Nouns (`totalSupply`), and the dynamic quorum parameters (`params`).

**Scenario**
If the input values (`againstVotes` and `totalSupply`) are manipulated or controlled by an attacker. By providing malicious values, an attacker could potentially influence the calculation of the required quorum.

To exploit this vulnerability, an attacker would need to modify the values of `againstVotes` and `totalSupply` in a way that allows them to bypass the intended quorum requirements and gain control over the contract.


The attacker's goal is to manipulate the quorum calculation in their favor and pass a proposal that would typically require a larger quorum.

This are steps an attacker might take to exploit the vulnerability:

1. The attacker creates multiple accounts and acquires a significant number of Nouns tokens. Let's assume the total supply of Nouns tokens is 1,000,000, and the attacker controls 100,000 tokens (10% of the total supply).

2. The attacker identifies a proposal they want to pass but know
Governance Manipulation in Dynamic Quorum Calculation.
Audit: 2023-07-nounsdao-findings
Severity: HIGH

# Lines of code

https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3DynamicQuorum.sol#L58-L68


# Vulnerability details

## Impact
An attacker exploiting these vulnerabilities can potentially manipulate the quorum calculation, influence the outcome of proposals, and disrupt the governance process. To be specific include:

1. **Integer Overflow/Underflow:** By manipulating the input values (`againstVotes`, `totalSupply`, `quorumCoefficient`, etc.) to cause an integer overflow or underflow, an attacker can cause incorrect quorum calculations. This can result in proposals passing or failing based on manipulated values, undermining the integrity of the governance process.

2. **Division by Zero:** If the `totalSupply` value is set to zero, it will trigger a division by zero error during the quorum calculation. This can lead to the contract failure and potentially disrupt the normal operation of the contract.

3. **Manipulating `quorumCoefficient`:** If an attacker can manipulate the `quorumCoefficient` value, they can influence the quorum calculation to their advantage. By providing a larger or smaller `quorumCoefficient` than the intended value, the attacker can adjust the quorum requirements to favor their desired outcome. This can lead to biased governance decisions and compromise the fairness of the process.

4. **Manipulating `againstVotes`:** An attacker may attempt to manipulate the `againstVotes` value. By providing a higher or lower number of against-votes than the actual count, the attacker can influence the quorum calculation. If they manipulate the `againstVotes` to be significantly higher, they can artificially increase the required quorum, making it harder for proposals to pass. Conversely, if they manipulate the `againstVotes` to be lower, they can decrease the required quorum, making it easier for proposals to pass. This manipulation can disrupt the consensus mechanism and lead to unfair governance outcomes.

## Proof of Concept
The `dynamicQuorumVotes` function calculates the required quorum of "for-votes" based on the amount of "against-votes" and other parameters.

Here are the potential vulnerabilities and relevant code blocks: [NounsDAOV3DynamicQuorum.sol#L58-L68](https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3DynamicQuorum.sol#L58-L68C6)

1. Integer Overflow/Underflow: The `dynamicQuorumVotes` function performs calculations using the `againstVotes`, `totalSupply`, and `quorumCoefficient` values. If these values are manipulated to overflow or underflow, it may result in incorrect quorum calculations. This vulnerability could potentially be exploited by an attacker to manipulate the quorum calculation.
 
```solidity
function dynamicQuorumVotes(
    uint256 againstVotes,
    uint256 totalSupply,
    NounsDAOStorageV3.DynamicQuorumParams memory