xanoutas/solidity-security-findings huggingface dataset:
Frontrunners can steal a users choice of name and symbol
Audit: 2024-01-curves-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact

Since Curves tokens must have unique symbols, it is possible to DOS a user's attempt to create a Curves token by front running their mint transaction with the same name and symbol. This will permanently take their choice of name and symbol.

## Proof of Concept

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

`symbolToSubject` is checked to ensure Curves tokens have unique symbols

## Tools Used

Manual Review

## Recommended Mitigation Steps

None


## Assessed type

DoS
any one can change the manger due to broken check in the modifier
Audit: 2024-01-curves-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact
change status of the manger

## Proof of Concept
```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Test, console2} from "forge-std/Test.sol";
import {Security} from "../src/Security.sol";

contract CounterTest is Test {
    Security public security;
    address user = makeAddr("user");
    address owner = makeAddr("owner");

    function setUp() public {
        vm.startPrank(owner);
        security = new Security();
        vm.stopPrank();
    }
    
    
    function test_owner() public{
        vm.startPrank(user);
        security.setManager(user,true);
    }

}

```
## Tools Used
Manual Review , forge
## Recommended Mitigation Steps
diff --git a/Security.sol b/aSecurity.sol
index 80158e4..10a2688 100644
--- a/Security.sol
+++ b/aSecurity.sol
@@ -6,12 +6,12 @@ contract Security {

     modifier onlyManager() {
-        managers[msg.sender] == true;
+        require(managers[msg.sender] == true, "Only managers can call this function");
         _;
```


## Assessed type

Access Control
Missing slippage checks
Audit: 2024-01-curves-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact
Missing slippage check when a user try to buy or sell curves tokens. Functions `buyCurvesToken` and `sellCurvesToken` does not implement any slippage checks with comparing the buy/sell price result with a minimum buy/sell value.

Users can be frontrun and receive a worse price than expected when they initially submitted the transaction. There's no protection at all, no minimum return amount for the buy/sell transaction to be valid which means the buy/sell can be delayed by miners or users congesting the network, as well as being sandwich attacked - ultimately leading to loss of user funds.

## Tools Used
Manual Review

## Recommended Mitigation Steps
Add some sort of protection for the user such that they receive their desired amounts. 


## Assessed type

MEV
Potential Price Slippage Due to Gaps in Consecutive Ranges
Audit: 2023-09-ondo-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-09-ondo/blob/47d34d6d4a5303af5f46e907ac2292e6a7745f6c/contracts/rwaOracles/RWADynamicOracle.sol#L45


# Vulnerability details

**The method allows appending new Range instances without restrictions on the gap between the end of the last range and the start of the new one. Significant gaps between these ranges can result in considerable price slippages, introducing volatility in price calculation and potentially disrupting the ecosystem.**

## Impact
Price Volatility: Sudden and unintended price movements can harm users and destabilize the system.

Economic Exploits: Malicious actors or informed traders might exploit these price shocks to gain undue profit.

Loss of Trust: Continuous volatility or significant price corrections can erode users' confidence in the platform.

## Proof of Concept
Alice, an administrator, sets a new Range where the endTimestamp of the last range is 2023-12-15, but the new range's starting time is 2023-12-30, creating a 15-day gap.

Bob, an uninformed trader, makes a transaction based on the derived price on 2023-12-16. He is caught off guard by the price derived from the huge gap, resulting in an unexpected loss.

Carol, who was aware of the gap, leverages this information to make profitable trades at the expense of less informed users like Bob.

Over time, users like Bob become wary of the platform due to the frequent price shocks and consider moving to a more stable platform.

## Tools Used

## Recommended Mitigation Steps
Implement a mechanism to limit the allowable gap between consecutive ranges, ensuring smooth transitions.

Provide administrators with tools to modify or remove incorrect or harmful ranges. While it introduces a degree of centralization, it can be crucial for maintaining system stability.

Introduce an optional alert mechanism for users, notifying them of potential significant price changes due to large gaps.

Extend test cases to simulate scenarios with different gap lengths between ranges, ensuring that price derivations are smooth and within acceptable limits.


## Assessed type

Other
Precision Error in getPrice due to Omission of Last Day's Interest
Audit: 2023-09-ondo-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-09-ondo/blob/47d34d6d4a5303af5f46e907ac2292e6a7745f6c/contracts/rwaOracles/RWADynamicOracle.sol#L81


# Vulnerability details

**The code attempts to calculate the price based on the interest from the previous day by using range.end - 1. However, if the last day represented by range.end has fully passed, the interest for this day is never taken into account. Over time, these slight omissions can compound, leading to incorrect price information.**

## Impact
-  Accumulative loss of precision: Though the error might appear negligible in isolated instances, over an 
   extended period, the cumulative effect can result in significant discrepancies in the price.
-  Any functionalities or contracts relying on the precise price data from this function might behave 
   differently than expected due to the precision error.
-  Users or contract participants might be misled by the wrong price information, which can affect their 
  decisions and interactions with the contract.

## Proof of Concept
1. Alice sets the range.end to a specific timestamp representing the end of a month.
2. Bob interacts with the contract the day after the month ends, calling the getPrice function.
   The contract returns a price derived from range.end - 1, thereby excluding the interest of the last day 
   of the month.
3. Over several months, these omissions compound, and when Carol checks the price much later, she receives 
   a value that's off from the expected accurate price due to these accumulated precision errors.

## Tools Used

## Recommended Mitigation Steps
Introduce a condition to check if range.end is greater than block.timestamp. If so, the function should account for the interest of the full last day instead of subtracting one.


## Assessed type

Other
Discrepancy in Token Allowance After Rebase Events
Audit: 2023-09-ondo-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-09-ondo/blob/47d34d6d4a5303af5f46e907ac2292e6a7745f6c/contracts/usdy/rUSDY.sol#L260


# Vulnerability details

**The function returns the number of tokens that _spender is allowed to spend on behalf of _owner. However, in the context of tokens with rebase mechanisms, the owner's balance can dynamically change without explicit transactions. The described behavior might lead to scenarios where the allowance is greater than the owner's actual balance post-rebase.**

## Impact
In a situation where a user (Alice) has approved another user (Bob) to spend 100 tokens on her behalf, and a rebase event then reduces Alice's holdings from 200 to 100 tokens, Bob's allowance remains at 100 tokens. This means Bob could potentially spend all of Alice's tokens, even though the original intention might have been for him to spend only up to half.

## Proof of Concept
Consider Alice and Bob. Alice holds 200 tokens and allows Bob to spend 100 tokens on her behalf. A rebase event occurs, reducing Alice's holdings by 50% to 100 tokens. However, when Bob checks his allowance using the allowance function, it still returns 100 tokens. Bob can now spend all of Alice's 100 tokens, despite the original intention possibly being that he can only spend half of what Alice holds.

## Tools Used

## Recommended Mitigation Steps
Rebase-capable tokens should implement a mechanism to adjust allowances proportionally during a rebase event or explicitly warn users about the possible discrepancy post-rebase and recommend setting allowances again.


## Assessed type

Other
Lack of Post-Allowance Verification Before Token Minting
Audit: 2023-09-ondo-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-09-ondo/blob/47d34d6d4a5303af5f46e907ac2292e6a7745f6c/contracts/bridge/DestinationBridge.sol#L349


# Vulnerability details

**The code checks if the user (txn.sender) is allowed via the ALLOWLIST. If not, it sets the user's status to "allowed". However, after this step, there's no subsequent verification to ensure the user has indeed been added to the ALLOWLIST before minting tokens to them.**

## Impact
An unauthorized user might get tokens minted if there's a discrepancy in the setAccountStatus function or if there are other conditions that prevent the user from being added to the ALLOWLIST. This can lead to unauthorized minting, potentially diluting the token supply or allowing malicious actors to exploit the system.

## Proof of Concept
Imagine Alice initiates a token minting process. The contract checks if Alice is on the ALLOWLIST. Let's assume she's not. The contract then tries to add Alice to the ALLOWLIST.

However, due to some unforeseen condition or a bug in setAccountStatus, Alice isn't successfully added to the ALLOWLIST. Despite this, the contract proceeds to mint tokens for Alice.

Now, Alice, who was initially not authorized and somehow failed to be added to the ALLOWLIST, still receives tokens. This scenario can be exploited by potential attackers to mint tokens without proper authorization.

## Tools Used

## Recommended Mitigation Steps
After setting the account status to allowed, a subsequent verification should be added to ensure the user is indeed allowed before minting the tokens to them.


## Assessed type

Access Control
Wrong calculation of elapsed days
Audit: 2023-09-ondo-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-09-ondo/blob/main/contracts/rwaOracles/RWADynamicOracle.sol#L266


# Vulnerability details

## Impact
For a certain period of time, the dailyIr is compounded every day. However, when calculating `prevClosePrice`, the last day's addition is missed.

The formula for calculating the current price is as follows: `(Range.dailyInterestRate ** (Days Elapsed + 1)) * Range.lastSetPrice.` Here, "Days Elapsed" refers to all the days that have passed during this time period.

For example, if the period starts on July 31 at 8:00:00 PM UTC (timestamp = 1690833600) and ends on August 31 at 8:00:00 PM UTC (timestamp = 1693512000), a total of 31 days have passed.

In the `getPrice` function, when `range.end <= block.timestamp` is true, the calculation of `prevClosePrice` calls `derivePrice(range, range.end - 1);`. Subtracting 1 from range.end (for your example periodEnd = 1693512000), the elapsed days will be 30 due to precision errors in:

`uint256 elapsedDays = (currentTime - currentRange.start) / DAY;`

A precision error causes the elapsed days to be 30 and the last `dailyIr` will not be compounded because the elapsed days will be one day less.

## PoC
```solidity
  function test_diffPrices() public {
    /*
      uint256 periodStart = 1690833600; // JUL 31 8:00:00PM UTC
      uint256 periodEnd = 1693512000; // AUG 31  8:00:00PM UTC
      uint256 dailyIR = 1.00013368 * 1e27; // (1 + Daily IR, scaled to 1e27),
      uint256 dailyIR_oct = 1.00018538 * 1e27;
      uint256 rangeStartPrice = 1e18; // Range Initial price
   */

    oracleUSDY = new RWADynamicOracle(
      address(this),
      address(this),
      address(this),
      periodStart,
      periodEnd, // range.end
      dailyIR,
      rangeStartPrice
    );

    uint256 price1 = oracleUSDY.simulateRange(
        periodStart,
        dailyIR,
        periodEnd - 1, // simulating block.timestamp
                       // if (range.end <= block.timestamp) -> false
                       // return derivePrice(range, block.timestamp);
        periodStart,
        rangeStartPrice
      );
      uint256 price2 = oracleUSDY.simulateRange(
        periodStart,
        dailyIR,
        periodEnd + 110, // simulating block.timestamp 
                         // if (range.end <= block.timestamp) -> true
                         // return derivePrice(range, range.end - 1); 
        periodStart,
        rangeStartPrice
      );

      console.log("The derived price is: ", price2);

      assertEq(price1, price2); // prices should not be equal, elapsedDays1 == elapsedDays2
  }
```
## Tools Used
Manual Review

## Recommended Mitigation Steps
Do not substract 1 from `range.end`


## Assessed type

Math
User will loss his funds forever if Threshold are not met . 
Audit: 2023-09-ondo-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-09-ondo/blob/main/contracts/bridge/DestinationBridge.sol#L337


# Vulnerability details

## Impact
`_mintIfThresholdMet` function is called from `_execute` function while executing a bridging transaction . This function checks if thresholds are met and only mints token in the destination chain to the user if thresholds are met properly .  However , the problem is it doesnot revert if threshold is not met . Which will get really problematic if an user tries to bridge assets but couldnot met the threshold . He will loss his funds forever and assets will be stuck in the destination chain forever .  

## Proof of Concept
`_mintIfThresholdMet` function is called from `_execute` function through axelar  while executing a bridge transaction  : 
```solidity 
   _attachThreshold(amt, txnHash, srcChain);
    _approve(txnHash);
    _mintIfThresholdMet(txnHash);
```
`_mintIfThresholdMet`  function checks if thresholds are met
```solidity 
  function _mintIfThresholdMet(bytes32 txnHash) internal {
    bool thresholdMet = _checkThresholdMet(txnHash); //<-------Here 
    Transaction memory txn = txnHashToTransaction[txnHash];
    if (thresholdMet) { //<------- only mints token in the destination chain to the user if thresholds are met but skips reverting or minting if thresholds are  not met 
      _checkAndUpdateInstantMintLimit(txn.amount);
      if (!ALLOWLIST.isAllowed(txn.sender)) {
        ALLOWLIST.setAccountStatus(
          txn.sender,
          ALLOWLIST.getValidTermIndexes()[0],
          true
        );
      }
      TOKEN.mint(txn.sender, txn.amount);
      delete txnHashToTransaction[txnHash];
      emit BridgeCompleted(txn.sender, txn.amount);
    }
  }
```
 This is  really problematic cause  if an user tries to bridge assets but couldnot met the threshold . He will loss his funds forever and assets will be stuck in the destination chain forever .  


## Tools Used
Manual review
## Recommended Mitigation Steps
Revert if the ` bool thresholdMet = _checkThresholdMet(txnHash);` returns false 


## Assessed type

Error
In case of accrual of additional income for holding rUSDY tokens, the protocol is subject to a flashloan attack
Audit: 2023-09-ondo-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-09-ondo/blob/main/contracts/usdy/rUSDY.sol#L449-L456
https://github.com/code-423n4/2023-09-ondo/blob/main/contracts/usdy/rUSDY.sol#L434-L440


# Vulnerability details

## Impact
rUSDY is the rebasing variant of USDY token, and is heavily based on other rebasing tokens such as stETH. Users are able to acquire rUSDY tokens by calling the wrap(uint256) function on the contract. Where as the price of a single USDY token varies over time, the price of a single rUSDY token is fixed at a price of 1 Dollar.

The description of the competition on the code4rena website says:
"Where as the price of a single USDY token varies over time, the price of a single rUSDY token is fixed at a price of 1 Dollar, with yield being accrued in the form of additional rUSDY tokens."

At the same time, there is no time in the contract for which rUSDY tokens are held. If additional income is credited to the user's rUSDY balance, the contract is subject to a flashloan attack.

## Proof of Concept
1. The service intends to accrue additional income based on the user's balance.
2. The user calculates a transaction through the mempool to accrue additional income and takes a flashloan, ahead of the service transaction.
3. The service calculates more tokens per user address.
4. User returns flashloan.

## Tools Used
Manual review

## Recommended Mitigation Steps
Enter a minimum wrap() time for tokens or accrue additional income based on the holding time


## Assessed type

Context
The USDT.sol contract does not accrue additional income in the form of rUSDY tokens
Audit: 2023-09-ondo-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-09-ondo/blob/main/contracts/usdy/rUSDY.sol#L449-L456
https://github.com/code-423n4/2023-09-ondo/blob/main/contracts/usdy/rUSDY.sol#L434-L440


# Vulnerability details

## Impact
rUSDY is the rebasing variant of USDY token, and is heavily based on other rebasing tokens such as stETH. Users are able to acquire rUSDY tokens by calling the wrap(uint256) function on the contract. Where as the price of a single USDY token varies over time, the price of a single rUSDY token is fixed at a price of 1 Dollar.

The description of the competition on the code4rena website says:
"Where as the price of a single USDY token varies over time, the price of a single rUSDY token is fixed at a price of 1 Dollar, with yield being accrued in the form of additional rUSDY tokens."

However, in the functions wrap(https://github.com/code-423n4/2023-09-ondo/blob/main/contracts/usdy/rUSDY.sol#L434-L440) and unwrap() (https://github. com/code-423n4/2023-09-ondo/blob/main/contracts/usdy/rUSDY.sol#L449-L456) no income is accrued when converting back from the rUSDY token. I couldn't find it anywhere else to pay. The contract does not work in accordance with the description of the tender.

## Tools Used
Manual review

## Recommended Mitigation Steps
https://code4rena.com/contests/2023-09-ondo-finance#top


## Assessed type

Context
Lack of an option in DestinationBridge.sol to cancel a transaction can lead to unwanted transactions
Audit: 2023-09-ondo-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-09-ondo/blob/main/contracts/bridge/DestinationBridge.sol#L85-L114


# Vulnerability details

## Impact
DestinationBridge.sol is for handling calls from Axelar Gateway and must be deployed in the destination chain. DestinationBridge.sol requires that the address from which Axelar messages are sent must be registered in the recipient's contract. Once a message has been received through the Axelar gateway, it will be queued and processed once it has received the required number of approvals. The number of assertions corresponding to a transaction can vary depending on the original chain and the amount to be traversed.

This contract also implements a rate limit that places a ceiling on the number of tokens that the Recipient's contract can mint within a certain fixed period of time.

## Proof of Concept
The lack of an option in DestinationBridge.sol to cancel a transaction can result in unwanted transactions being executed.
Assume that a transaction has arrived with a certain approval threshold. The transaction will be in the array until it is executed. It may take at least a year, and the transaction will not be canceled.

Suppose the approval thresholds have changed. And all the old transactions that were in the array can be executed. This may lead to undesirable consequences. It is necessary to enter either the time during which a transaction can be performed or to enter the possibility of forced cancellation of transactions.

## Tools Used
Manual review

## Recommended Mitigation Steps
It is necessary to enter either the time during which a transaction can be performed or to enter the possibility of forced cancellation of transactions.


## Assessed type

Timing
In the event of a fall in the price of USDY, the withdrawal of funds for the user may be blocked
Audit: 2023-09-ondo-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-09-ondo/blob/main/contracts/usdy/rUSDY.sol#L449-L456


# Vulnerability details

## Impact
There is a wrap() function (https://github.com/code-423n4/2023-09-ondo/blob/main/contracts/usdy/rUSDY.sol#L434-L440) called by users to wrap their USDY tokens . In the future, to withdraw tokens, the user calls the unwrap() function (https://github.com/code-423n4/2023-09-ondo/blob/main/contracts/usdy/rUSDY.sol#L449-L456). However, in the unwrap() function, the user can have more funds in case the price of USDY falls. Based on the case with the UST, this may well happen.

## Proof of Concept
1. Suppose the user has called the wrap(uint256 _USDYAmount) function with the input parameter _USDYAmount = 9000
2. User got shares = _USDYAmount * BPS_DENOMINATOR = 9000 * 10000 = 9000 * 1e4

In RUSDY this is (_shares * oracle.getPrice()) / (1e18 * BPS_DENOMINATOR) = (9 * 1e7 * 1 * 1e18) / (1e18 * 10000) = 9 * 1e3

3. Then the user called the unwrap(uint256 _rUSDYAmount) function with the input parameter _rUSDYAmount = 6000
4. In https://github.com/code-423n4/2023-09-ondo/blob/main/contracts/usdy/rUSDY.sol#L451 usdyAmount = getSharesByRUSDY(_rUSDYAmount) is calculated:

usdyAmount = (_rUSDYAmount * 1e18 * BPS_DENOMINATOR) / oracle.getPrice()

Let's say the price of USDY went down and became oracle.getPrice() = 1e17

usdyAmount = (6000 * 1e18 * 10000) / 1e17 = 6000 * 1e5

The verification at https://github.com/code-423n4/2023-09-ondo/blob/main/contracts/usdy/rUSDY.sol#L452 will pass.
if (usdyAmount < BPS_DENOMINATOR) revert UnwrapTooSmall();

5. In https://github.com/code-423n4/2023-09-ondo/blob/main/contracts/usdy/rUSDY.sol#L453, the _burnShares() function is called, where the number of user shares is reduced.

In this case, decrementing shares will cause an error:
shares = 9000 * 1e4 - 6000 * 1e5 < 0

Thus, the output for the user will be blocked.

## Tools Used
Manual review

## Recommended Mitigation Steps
Pick up parameters in (_rUSDYAmount * 1e18 * BPS_DENOMINATOR) / oracle.getPrice() depending on USDY price


## Assessed type

Context