xanoutas/solidity-security-findings huggingface dataset:
Timelock v1 admin can be changed using `executeOnTimelockV1` function
Audit: 2023-07-nounsdao-findings
Severity: HIGH

# Lines of code

https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Proposals.sol#L197-L210
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Proposals.sol#L490-L493


# Vulnerability details

## Impact
Timelock (NounsDAOExecutor) contract admin can be changed by a malicious proposal transaction

## Proof of Concept
The function `proposeOnTimelockV1()` is used to make a proposal on the timelock (executor) contract. Anyone who has voting power above the threshold can create a transaction that can change the admin of the executor contract.

Let's see the details:
With setting a malicious proposal struct in `NounsDAOStorageV3.Proposal` and including the preceding part in the proposal.calldata section:
```
abi.encodeWithSignature("setPendingAdmin(address)", _attackerAddress)
```
Then if this proposal is queued and then executed in the timelock contract, the `_attackerAddress` is set as the pendingAdmin in the timelock contract, and by calling the `acceptAdmin()` function, the attacker becomes the admin of the timelock contract.

Scenario for attack:
Bob creates a proposal with four transactions, one of which is a call to `setPendingAdmin()` with an address controlled by Bob. The admin doesn’t notice this and queues the Proposal. Once the delay is passed Bob executes the Proposal and becomes the pendingAdmin. Bob then calls acceptAdmin and is now the admin of the Timelock.

## Tools Used
Manual Analysis
## Recommended Mitigation Steps
Add a check that prevents `setPendingAdmin()` to be included in a Proposal.


## Assessed type

Governance
An Attacker Can Transfer Entire (ERC20) Balance Because of  ```transferFrom``` ignoring any check or return values While Transferring Tokens
Audit: 2023-07-nounsdao-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact
The return value of an external transfer/transferFrom call is not checked. Because of Ignoring Return Value Even ```transferFrom``` call fail and return ```false``` the code continue to execute and balance is still returned to the caller.

## Proof of Concept
Vulnerable Code Snippet 
``` 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;
    }
```
Here, the ```transferFrom``` is being externally called from IERC20. And the implementation in IERC20 Is look like
``` solidity
function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);
```
A simple ```transferFrom``` function with no check conditions. 
Because Some tokens do not return a bool (e.g. USDT, BNB, OMG) on ERC20 methods. see [here](https://gist.githubusercontent.com/lukas-berlin/f587086f139df93d22987049f3d8ebd2/raw/1f937dc8eb1d6018da59881cbc633e01c0286fb0/Tokens%20missing%20return%20values%20in%20transfer) for a comprehensive (if somewhat outdated) list. Ref [WeirdErc20Tokens](https://github.com/d-xo/weird-erc20).
If the attacker triggers a transferFrom operation that fails, the balance of tokens will still be returned to the attacker, even though no actual transfer occurred.

## Tools Used
Manual Review + Slither (As Always)
## Recommended Mitigation Steps
 it is crucial to check the return value of the transferFrom function. By verifying the return value, you can ensure that the transfer was successful before returning the balance or making any further modifications. If the transfer fails, you should handle the error condition appropriately, such as reverting the transaction or performing other necessary actions based on the requirements of your contract.


## Assessed type

Token-Transfer
An Attacker Can Trick ```_safeTransferETHWithFallback``` Function To Steal Funds 
Audit: 2023-07-nounsdao-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact
If the ```to``` address is a malicious contract, it can invoke a fallback function that calls back into the NounsAuctionHouseFork contract before the WETH tokens are transferred. 

## Proof of Concept
Vulnerable Code Snippet 
``` solidity
function _safeTransferETHWithFallback(address to, uint256 amount) internal {
        if (!_safeTransferETH(to, amount)) {
            IWETH(weth).deposit{ value: amount }();
            IERC20(weth).transfer(to, amount);
        }
    }
```
This above function tries to send Eth to address ```to``` but if it fails to do so then it Wrapped the Eth as ```WETH``` and then try to send the ```WETH``` tokens to ```to``` addresss. 
But, here the potential vulnerability arises when ```to``` address is executed after wrapping ```Eth``` tokens into ```WETH```. If the ```to``` address is an attacker's contract (Reentrancy) address, it will invoke the fallback function that calls back into the contract before the ```WETH``` tokens are transferred. This will lead to the potential reenter ```_safeTransferETHWithFallback``` function and execute the entire login again.

## Tools Used
Solidity Visual Developer + Slither Detection As Well
## Recommended Mitigation Steps
Any external contract or address that can potentially call the ```_safeTransferETHWithFallback``` function is trusted and does not have malicious fallback functions that could exploit reentrancy.


## Assessed type

Reentrancy
In NounsDAOExecutor.sol and NounsDAOExecutorV2.sol, executeTransaction() function is not payable, so value can not be provided along with the call
Audit: 2023-07-nounsdao-findings
Severity: HIGH

# Lines of code

https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOExecutor.sol#L142-L179
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOExecutorV2.sol#L165-L196


# Vulnerability details

## Impact
In NounsDAOExecutor.sol and NounsDAOExecutorV2.sol, executeTransaction() is used to execute the transaction which can be accessed by admin only.

For example see, NounsDAOExecutorV2.executeTransaction(),

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

165    function executeTransaction(
166        address target,
167        uint256 value,
168        string memory signature,
169        bytes memory data,
170        uint256 eta
171    ) public returns (bytes memory) {
172        require(msg.sender == admin, 'NounsDAOExecutor::executeTransaction: Call must come from admin.');



      // Some code


196        (bool success, bytes memory returnData) = target.call{ value: value }(callData);
197        require(success, 'NounsDAOExecutor::executeTransaction: Transaction execution reverted.');
198
199        emit ExecuteTransaction(txHash, target, value, signature, data, eta);
200
201        return returnData;
202    }
```

NounsDAOExecutorV2.executeTransaction() has value param at L-196 which will be sent along with the call to the target address.

**The problem is that this function doesn't have payable modifier, so it is not possible to provide eth with the call. As a result it will be not possible to execute call with eth value.**

Therefore, admin wont be able to provide value while calling executeTransaction() function.

The is same problem with NounsDAOExecutor.executeTransaction() where payable keyword is missing.

## Proof of Concept
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOExecutor.sol#L142-L179

https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOExecutorV2.sol#L165-L196

## Similar Examples
**1) Per the NounsDAOExecutorV2.sol,**
```Solidity
"// NounsDAOExecutor2.sol is a modified version of Compound Lab's Timelock.sol:
```

Therefore, referring the Compound Lab's Timelock.sol executeTransaction(),

```Solidity
File: contracts/Timelock.sol

81    function executeTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public payable returns (bytes memory) {
82        require(msg.sender == admin, "Timelock::executeTransaction: Call must come from admin.");



      // Some code


100        (bool success, bytes memory returnData) = target.call{value: value}(callData);
101        require(success, "Timelock::executeTransaction: Transaction execution reverted.");
102
103        emit ExecuteTransaction(txHash,
Double entry tokens
Audit: 2023-07-nounsdao-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact
The implementation of a 'checkForDuplicates' function has not fully addressed the issue of sending a greater than prorata token share leading to loss of DAO funds. This is because this function does not adequately account for Double Entry Tokens – tokens which have multiple contract addresses representing different versions of the same token, as was the case with [TUSD which famously caused a potential attack on Compound](https://blog.openzeppelin.com/compound-tusd-integration-issue-retrospective). 

In the event of a DAO fork or members quitting, the presence of these Double Entry Tokens in the array could potentially send a greater than prorata share of those tokens to the fork DAO treasury or to the quitting members, which would lead to a loss of funds for the original DAO.

## Proof of Concept
A single token, such as TUSD, could technically have multiple contract addresses if different versions of the token contract were deployed at different times. In such cases, the existing `checkForDuplicates` function may not accurately identify these as duplicate entries, since the contract addresses are different, even though they represent the same underlying asset.

Under this context, an Admin function for setting the list of ERC20 tokens to transfer on `quit` could still have duplicate ERC20 tokens entailed and undetected:

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

```solidity
    /**
     * @notice Admin function for setting the list of ERC20 tokens to transfer on `quit`.
     */
    function _setErc20TokensToIncludeInQuit(address[] calldata erc20tokens) external {
        if (msg.sender != admin) revert AdminOnly();
        checkForDuplicates(erc20tokens);

        emit ERC20TokensToIncludeInQuitSet(erc20TokensToIncludeInQuit, erc20tokens);

        erc20TokensToIncludeInQuit = erc20tokens;
    }
```
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/fork/newdao/governance/NounsDAOLogicV1Fork.sol#L793-L801

```solidity
    function checkForDuplicates(address[] calldata erc20tokens) internal pure {
        if (erc20tokens.length == 0) return;

        for (uint256 i = 0; i < erc20tokens.length - 1; i++) {
            for (uint256 j = i + 1; j < erc20tokens.length; j++) {
                if (erc20tokens[i] == erc20tokens[j]) revert DuplicateTokenAddress();
            }
        }
    }
``
Possible loss of funds as a result of lack of withdraw function
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#L1089C1-L1090C34 #L1089
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOLogicV3.sol#L1035C4-L1035C34 #L1035


# Vulnerability details

## Impact
Both the NounsDAOLogicV3.sol and NounsDAOLogicV3.sol contain the receive function. But they both don't have withdraw function. 

Funds sent to both of these contracts will be locked forever.

## Proof of Concept
 receive() external payable {}
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOLogicV2.sol#L1089C1-L1090C34

 receive() external payable {}
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOLogicV3.sol#L1035C4-L1035C34

## Tools Used
Manual review

## Recommended Mitigation Steps
Remove the receive() if it has no use or include a withdraw function.


## Assessed type

Token-Transfer
sendProRataTreasury() in NounsDAOV3Fork.sol can cause reverts in functions where it is called. 
Audit: 2023-07-nounsdao-findings
Severity: MEDIUM

# Lines of code

https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/fork/NounsDAOV3Fork.sol#L240


# Vulnerability details

## Impact
sendProRataTreasury() calls timelock.sendEth() to send eth, timelock is a NounsDAOExecutorV2 contract. In NounsDAOExecutorV2.sendEth(), it only allows calls from the address set to be admin in the NounsDAOExecutorV2 contract. NounsDAOV3Fork library is used in NounsDAOLogicV3 contract to use the joinFork() function

This means NounsDAOLogicV3 will call NounsDAOExecutorV2.sendEth(), NounsDAOLogicV3 is the msg.sender and it may not be the admin address. 

## Proof of Concept
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/fork/NounsDAOV3Fork.sol#L240-L259
```
    function sendProRataTreasury(
        NounsDAOStorageV3.StorageV3 storage ds,
        address newDAOTreasury,
        uint256 tokenCount,
        uint256 totalSupply
    ) internal {
        INounsDAOExecutorV2 timelock = ds.timelock;
        uint256 ethToSend = (address(timelock).balance * tokenCount) / totalSupply;

        timelock.sendETH(newDAOTreasury, ethToSend);

        uint256 erc20Count = ds.erc20TokensToIncludeInFork.length;
        for (uint256 i = 0; i < erc20Count; ++i) {
            IERC20 erc20token = IERC20(ds.erc20TokensToIncludeInFork[i]);
            uint256 tokensToSend = (erc20token.balanceOf(address(timelock)) * tokenCount) / totalSupply;
            if (tokensToSend > 0) {
                timelock.sendERC20(newDAOTreasury, address(erc20token), tokensToSend);
            }
        }
    }
}
```
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOExecutorV2.sol#L213-L219
```
    function sendETH(address payable recipient, uint256 ethToSend) external {
        require(msg.sender == admin, 'NounsDAOExecutor::sendETH: Call must come from admin.');

        recipient.sendValue(ethToSend);

        emit ETHSent(recipient, ethToSend);
    }
```
## Tools Used
vs code 

## Recommended Mitigation Steps
enforce admin of NounsDAOExecutorV2 to be of type NounsDAOLogicV3 and not address. 







## Assessed type

Access Control
Ex-token holders are still able to cast votes on proposals under certain circumstances
Audit: 2023-07-nounsdao-findings
Severity: MEDIUM

# Lines of code

https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L70-L76
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L184-L200
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L210-L264


# Vulnerability details

When casting a vote, an address is limited to a certain amount of `votes` derived from `ds.nouns.getPriorVotes`.  However, due to the nature of `ds.nouns.getPriorVotes`, the amount of votes available to an address solely depends on the amount of tokens they held when a proposal becomes of Active state.  Consequently, if the token is transferred to another address during this Active state, then the new token holder will not be able to vote on the current proposal, as they were not included in the `ds.nouns.getPriorVotes` snapshot.  However, if the original owner did not vote on the active proposal when they owned the token, they will still be able to vote on the proposal if it is still active, even though they are technically no longer a token holder.

## Impact
The likelihood of this bug occurring is high, as tokens are traded on secondary marketplaces all the time, many of which will probably happen during active proposals.  However, the impact of this bug is low, as the total number of votes remains unchanged throughout the proposal process, all of which result in a medium severity.  The issue with this bug lies in the fact that addresses who are no longer token holders are still able to cast a valid vote, and being as how they are no longer members of the DAO, they could vote against the majority to make the succeeding of the proposal more difficult.

## Proof of Concept
When calling the `castVote` function
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L70-L76

an internal call is made to `castVoteInternal`
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L184-L200

which checks to see if the vote is Active or in the Objection period. If it isn't, then the vote is reverted with `'NounsDAO::castVoteInternal: voting is closed'`.  However, if it is Active, then it makes another internal call to 
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L210-L264

The issue lies with this line:
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol#L222
```
uint96 votes = ds.nouns.getPriorVotes(voter, proposalVoteSna
Unused returns on the ds. _withdraw(), NounsDAOLogicV3._withdraw(), and  ds.executeFork() 
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#L786-#L788
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOLogicV3.sol#L497-#L499
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOLogicV3.sol#L408-#L419


# Vulnerability details

## Impact
The return value of the external calls are not stores in a local variable or a state variable


## Proof of Concept
The return values do not store the results in a store local or state variable. As a result, the computation have no effect.

Code: 

NounsDAOLogicV3.getActions(uint256)
(contracts/governance/NounsDAOLogicV3.sol#408-419) ignores return value by ds.getActions(proposalId) (contracts/governance/NounsDAOLogicV3.sol#418)
NounsDAOLogicV3.executeFork()
(contracts/governance/NounsDAOLogicV3.sol#497-499) ignores return value by ds.executeFork() (contracts/governance/NounsDAOLogicV3.sol#498)
NounsDAOLogicV3._withdraw()
(contracts/governance/NounsDAOLogicV3.sol#786-788) ignores return value by ds._withdraw() (contracts/governance/NounsDAOLogicV3.sol#787)


## Tools Used
Manual Review

## Recommended Mitigation Steps
Ensure that all the return values of the function calls are used.




## Assessed type

Invalid Validation
initializer can be front run
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/token/NounsTokenFork.sol#L119


# Vulnerability details

## Impact
Initialize function have the potential of front running by a malicious actor. An attacker can front-run the deployer and takeover the contract by setting itself as the owner in the NounsTokenFork.sol Contract. Taking ownership will result in passing values favourable to the attacker like claiming all tokens or forking.
Front running the NounsAuctionHouseFork contract an attacker can set the weth address for themself and receiving all the funds.

## Proof of Concept
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/fork/newdao/token/NounsTokenFork.sol#L119
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/fork/newdao/NounsAuctionHouseFork.sol#L76
https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/NounsDAOExecutorV2.sol#L95

## Tools Used
Past relative findings from audit reports. 
https://solodit.xyz/issues/initialization-functions-can-be-front-run-trailofbits-advanced-blockchain-pdf
https://solodit.xyz/issues/possible-front-running-on-initialization-halborn-biconomy-bico-token-pdf


## Recommended Mitigation Steps
Implement use of factory pattern to deploy and initialise contract with enhancing access control to the initialize functions.


## Assessed type

Other