xanoutas/solidity-security-findings huggingface dataset:
Insufficient Reward Balance Check Leading to Potential Protocol Insolvency
Audit: 2024-02-uniswap-foundation-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L570-L599


# Vulnerability details

## Impact
Detailed description of the impact of this finding.
description: The `notifyRewardAmount` function in the provided smart contract contains a vulnerability where the balance check for the reward token does not account for unclaimed rewards already owed to users. This oversight could lead to a state of protocol insolvency where the contract falsely believes it has the balance to cover new rewards, potentially preventing users from claiming what they are owed. The root cause of this vulnerability is the function's failure to subtract unclaimed rewards from the contract's balance before comparing it to the required balance for new rewards. The maximum impact is that users may be unable to withdraw their earned rewards, damaging trust in the protocol and disrupting its normal operation.
## 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://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L570-L599
## Tools Used
Meta Scan
## Recommended Mitigation Steps
## Finding Recommendation:

To address the vulnerability identified in the `notifyRewardAmount` function, it is recommended to update the balance check to account for the unclaimed rewards that are already part of the contract's balance. This can be achieved by modifying the balance check logic to deduct the amount of unclaimed rewards from the total balance before verifying if the contract has sufficient funds to cover the new rewards to be distributed.

Additionally, it is advisable to implement a mechanism that tracks and deducts unclaimed rewards from the total balance when calculating available funds for new rewards. This will ensure that users are always able to withdraw their earned rewards without the risk of protocol insolvency due to inaccurate balance calculations.

By incorporating these improvements, the contract can mitigate the risk of users being unable to claim their rewards and maintain the solvency of the protocol. It is also recommended to conduct thorough testing and auditing to validate the changes and ensure the overall security and functionality of the reward distribution mechanism.


## Assessed type

Math
Staking Contract Vulnerable to Inaccurate Token Accounting Due to Transfer-on-Fee or Deflationary Token Mechanics
Audit: 2024-02-uniswap-foundation-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L723-L735


# Vulnerability details

## Impact
Detailed description of the impact of this finding.
description: The function _withdraw in the staking contract contains a critical vulnerability due to the lack of validation after calling _stakeTokenSafeTransferFrom to transfer staked tokens. This function assumes that the full amount of tokens specified by _amount will be transferred to the deposit owner. However, if the staked token implements a transfer-on-fee or deflationary mechanism, the actual transferred amount could be less than the _amount due to fees deducted or tokens burned during the transfer. This assumption leads to inconsistent internal accounting, as the deposit balance, totalStaked, depositorTotalStaked, and earningPower are all decremented by _amount regardless of the actual amount transferred. This discrepancy could allow users to withdraw more tokens than they are entitled to, resulting in potential protocol insolvency as the contract may falsely represent more tokens than are actually held or available, leading to a shortfall when users attempt to withdraw their funds.
## 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://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L723-L735
## Tools Used
Meta Scan
## Recommended Mitigation Steps
Finding Recommendation:
To address the vulnerability related to inconsistent balances when dealing with transfer-on-fee or deflationary tokens, it is recommended to implement a check after the `_stakeTokenSafeTransferFrom` operation to verify that the correct amount of tokens has been transferred. This check should compare the expected amount with the actual amount received by the `deposit.owner` and adjust the internal accounting (`deposit.balance`, `totalStaked`, `depositorTotalStaked`, `earningPower`) accordingly. By ensuring that the contract's accounting reflects the actual token balances, the risk of protocol insolvency due to discrepancies in token amounts can be mitigated. Additionally, consider implementing mechanisms to handle transfer fees or token burns to maintain accurate accounting and prevent unexpected outcomes.


## Assessed type

Invalid Validation
Incompatibility with Fee-Charging ERC20 Tokens Resulting in Fund Freezing in Vault Contract
Audit: 2024-02-uniswap-foundation-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L512-L532


# Vulnerability details

## Impact
Detailed description of the impact of this finding.
description: The Vault contract is vulnerable to incompatibility issues with ERC20 tokens that implement transfer fees. The `_transferAndCheckUnderlying()` function is designed to ensure the correct amount of tokens is received by the contract, but fails to account for tokens that deduct a fee upon transfer, causing the function to revert the transaction. This results in permanent or temporary freezing of funds or unclaimed yield when users attempt to deposit or sponsor using such fee-charging tokens, as the contract is unable to operate due to receiving less than the expected amount of tokens.
## 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://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L512-L532
## Tools Used
Meta Scan
## Recommended Mitigation Steps
Finding Recommendation:
To address the vulnerability related to the incompatibility with fee-charging ERC20 tokens when depositing into the Vault contract, it is recommended to update the `_transferAndCheckUnderlying()` function to handle tokens that charge transfer fees. This can be achieved by adjusting the logic to account for the difference in the received amount due to transfer fees. Additionally, consider implementing a mechanism to allow for the successful deposit and sponsorship of fee-charging ERC20 tokens within the Vault contract. Testing with various fee-charging tokens is essential to ensure the compatibility and functionality of the contract. Regularly reviewing and updating the contract code to address potential vulnerabilities is also recommended to maintain the security and integrity of the smart contract system.


## Assessed type

DoS
Inaccurate Stake Accounting Due to Transfer-on-Fee or Deflationary Token Transfers
Audit: 2024-02-uniswap-foundation-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L638-L664


# Vulnerability details

## Impact
The borrowExactAmount function in the contract lacks proper authorization checks, allowing any user to borrow tokens against an NFT collateral. This omission enables unauthorized loans to be initiated against an NFT owner's collateral without restriction. The function first retrieves the NFT's ID and the token index, followed by syncing the lending user instance and obtaining the current ETH value of the collateralized NFT. Subsequently, it calculates the maximum borrowable amount of tokens based on the ETH value. However, it fails to verify whether the caller has the appropriate authorization to borrow against the specified NFT. As a result, any user can call this function and borrow tokens against any NFT without restriction or permission. This vulnerability poses significant risks, as it could lead to unwarranted debt for NFT owners and potential freezing of their NFT as collateral until the debt is resolved. The root cause of this vulnerability lies in the absence of proper access control mechanisms within the borrowExactAmount function, allowing unauthorized users to exploit the borrowing functionality without restriction.
## 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://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L638-L664
## Tools Used
Meta Scan
## Recommended Mitigation Steps
Finding Recommendation:
1. Review the implementation of the `_stakeTokenSafeTransferFrom` function to ensure it properly handles transfer-on-fee or deflationary token transfers, taking into account the possibility of receiving less than the specified `_amount`.
2. Implement checks or mechanisms to verify the actual amount received when transferring tokens that apply fees or have deflationary mechanics.
3. Consider implementing a mechanism to correct internal balances if the actual amount received differs from the specified `_amount`.
4. Conduct thorough testing, including edge cases with transfer-on-fee or deflationary tokens, to ensure the contract's accounting and user balances are accurately maintained.
5. Regularly audit the contract for any potential vulnerabilities related to inconsistent token transfers and update the code accordingly.


## Assessed type

Invalid Validation
users could withdraw more tokens than expected
Audit: 2024-02-uniswap-foundation-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L723-L735


# Vulnerability details

## Impact
users could withdraw more tokens than expected.

## Proof of Concept

While withdrawing, user's deposit is not checked, whether this user has enough balance to be withdrawed. If user A and user B both stake tokens, and delegate to the same surrogate, user A could withdraw (amountA+amountB) tokens, following are the POC steps:
1, user A stake amountA(for example 10) tokens, and deletage to delegateeX.
2, user B stake amountB(for example 20) tokens, and deletage to delegateeX too.
3, user A withdraw 30 tokens, "_stakeTokenSafeTransferFrom" will succeed since delegateeX has 30 tokens, and depositA.balance will underflow to be a very large number.

https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L499-L503
function withdraw(DepositIdentifier _depositId, uint256 _amount) external {
    Deposit storage deposit = deposits[_depositId];
    _revertIfNotDepositOwner(deposit, msg.sender);
    _withdraw(deposit, _depositId, _amount);
  }

https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L723-L735
function _withdraw(Deposit storage deposit, DepositIdentifier _depositId, uint256 _amount)
    internal
  {
    _checkpointGlobalReward();
    _checkpointReward(deposit.beneficiary);

    deposit.balance -= _amount; // overflow prevents withdrawing more than balance
    totalStaked -= _amount;
    depositorTotalStaked[deposit.owner] -= _amount;
    earningPower[deposit.beneficiary] -= _amount;
    _stakeTokenSafeTransferFrom(address(surrogates[deposit.delegatee]), deposit.owner, _amount);
    emit StakeWithdrawn(_depositId, _amount, deposit.balance);
  }

## Tools Used
manually reviewed 

## Recommended Mitigation Steps
add check to deposit.balance when withdraw

if (deposit.balance < _amount) revert balance_notenough();





## Assessed type

Under/Overflow
Rewards accrued before first deposit will remain stuck forever
Audit: 2024-02-uniswap-foundation-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-02-uniswap-foundation/blob/5a2761c8277541a24bc551fbd624413b384bea94/src/UniStaker.sol#L570


# Vulnerability details

## Impact

A vulnerability in the in the `UniStaker` contract can cause rewards to become permanently locked if they are notified before any deposits have been made into the pool. This means that rewards allocated during this period are irretrievable, due to the contract's inability to distribute these early rewards.

As a result, these funds cannot be claimed by any participants or returned, leading to a loss of funds intended as rewards.

## Proof of Concept

Take the following example scenario:

1. Initially, the contract has no staked tokens (`totalStaked = 0`)
2. Rewards notifier calls `UniStaker#notifyRewardAmount(30 WETH)` which results in `scaledRewardRate = 1 WETH`:

```
scaledRewardRate = 30 WETH / 30 days = 1 WETH/day
```

3. 20 days pass without any staking activity.
4. Alice stakes some WETH on day 20.
5. 10 days pass and `rewardEndTime` is reached.
6. Alice claims her share, calculated to be 10 WETH for her 10-day staking period:

```
Alice's Reward = 1 WETH/day * 10 days = 10 WETH
```

However, the 20 WETH of rewards from the first 20 days remain unclaimed and are stuck in the contract forever.

## Tools Used

Manual Review

## Recommended Mitigation Steps

To prevent rewards from becoming locked in the contract before any staking activity, the contract should revert calls to `UniStaker#notifyRewardAmount()` when there are no active stakers.

This approach ensures that rewards cannot be notified prematurely, avoiding the issue of locked rewards.





## Assessed type

Error
Unregulated reward notifications bug  lead to economic imbalance in reward distribution
Audit: 2024-02-uniswap-foundation-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-02-uniswap-foundation/blob/5a2761c8277541a24bc551fbd624413b384bea94/src/UniStaker.sol#L577-L582


# Vulnerability details

## Vulnerability description
there is a the vulenrbaility  arise in the notifyRewardAmount function, this function is allows authorized notifiers to inform the contract about new rewards. the vulnerability is can lead to economic imbalances, and this affecting the fairness and predictability of reward distribution,  here is the vulnerable line :

```
scaledRewardRate = (_remainingReward + _amount * SCALE_FACTOR) / REWARD_DURATION;

```
this line is  does not account for the size and frequency of incoming rewards, and leading to potential imbalances.
## Impact

if an attacker exploit this vulnerability it's can lead  to economic imbalances that i saffecting the fairness and predictability of reward distribution. this is  relate to the size and timing of reward notifications.

## Proof of Concept

i fuzz with two scenario and show this as result :

and in scenario with frequent Small Rewards NotificationsAfter is that the simulation  100 small rewards notifications, the reward rate was approximately 3.81e-05 units per second.

in scenario with large reward notification a single large reward notification close to the end of the reward period, the reward rate increased to approximately 0.00386 units per second.

here is  a scenario exploit this :
- let's say the attackers accumulate a substantial amount of the staking token to be ready to stake a significant amount at an opportune moment
- and over a period, the attackers, assuming control of a rewards notifier contract, notify the UniStaker contract of small rewards frequently, ans this as result that  does not significantly increase the reward rate due to the small size of each notification but extends the reward duration, affecting the overall reward distribution pace and diluting the value of rewards for existing stakers.
- and in late Large Reward Notification in the close to the end of the extended reward distribution period, the attackers notify a large reward.
- as Value for instance, if the reward period was nearing its end, the attackers notify a reward of 10,000 token, as result this increases the reward rate suddenly, creating an bug for the attackers to stake their accumulated tokens and capture a disproportionate share of the high-rate rewards.
-The attackers stake their accumulated tokens right after notifying the large reward, benefiting from the significantly increased reward rate, and this action disadvantages early stakers, who had staked under the premise of a different reward rate and distribution timeline.
## Tools Used
- manual review 
## Recommended Mitigation Steps
need to add a minimum thresholds for reward amounts to prevent the system from being gamed with frequent small notifications.


## Assessed type

Other
Unrestricted Fee Claiming in the function 
Audit: 2024-02-uniswap-foundation-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-02-uniswap-foundation/blob/5a2761c8277541a24bc551fbd624413b384bea94/src/V3FactoryOwner.sol#L181-L205
https://github.com/code-423n4/2024-02-uniswap-foundation/blob/5a2761c8277541a24bc551fbd624413b384bea94/src/V3FactoryOwner.sol#L187


# Vulnerability details

## Vulnerability Details 
there is a vulenrbaility arise in this contract in the  claimFees function, this  function  is allows any caller to claim accumulated protocol fees from any Uniswap v3 pool, and provided they pay a predetermined amount of a specific payout token (WETH, in the given scenario). This mechanism fails to account for the relative value of the fees being claimed versus the payout amount,and this lead to potential economic imbalance.
here is the vulnerable part :
```solidity
  function claimFees(
    IUniswapV3PoolOwnerActions _pool,
    address _recipient,
    uint128 _amount0Requested,
    uint128 _amount1Requested
  ) external returns (uint128, uint128) {
    PAYOUT_TOKEN.safeTransferFrom(msg.sender, address(REWARD_RECEIVER), payoutAmount);
    REWARD_RECEIVER.notifyRewardAmount(payoutAmount);
    (uint128 _amount0, uint128 _amount1) =
      _pool.collectProtocol(_recipient, _amount0Requested, _amount1Requested);

    // Protect the caller from receiving less than requested. See `collectProtocol` for context.
    if (_amount0 < _amount0Requested || _amount1 < _amount1Requested) {
      revert V3FactoryOwner__InsufficientFeesCollected();
    }
    emit FeesClaimed(address(_pool), msg.sender, _recipient, _amount0, _amount1);
    return (_amount0, _amount1);
  }

  /// @notice Ensures the msg.sender is the contract admin and reverts otherwise.
  /// @dev Place inside external methods to make them admin-only.
  function _revertIfNotAdmin() internal view {
    if (msg.sender != admin) revert V3FactoryOwner__Unauthorized();
  }
}
```
## Impact

if an attacker exploit  this vulnerability is gone be able to drain significant value from pools by repeatedly claiming fees for a relatively minimal payout, as  in scenarios where the accumulated fees far exceed the value of the required payout amount. and  This could lead to disproportionate gains for attackers and potential value leakage from the protocol, affecting all stakeholders.

## Proof of Concept
i fuzz with this scenario 
- An attacker observes a pool with accumulated fees significantly higher than the payout amount as that fees worth >$25K in stablecoins versus a 10 WETH payout.
- The attacker calls claimFees, specifying the pool from which to claim fees and the amount requested.
- The payout of 10 WETH (~$25K) is transferred to the reward receiver, and the attacker receives fees from the pool, potentially worth more than the payout.
- Repeating this process allows the attacker to systematically extract value, exploiting the economic imbalance.

- the fuzz test result that :
```python 
{'success': True,
 'total_collected_token0': 8265774,
 'total_collected_token1': 1396489,
Missing zero value will not update rewardPerTokenAccumulatedCheckpoint
Audit: 2024-02-uniswap-foundation-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L570-L582
https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L188


# Vulnerability details

## Impact
When a Reward notifier with intent to renew rewards, calls `UniStaker.notifyRewardAmount()` with zero amount when timestamp is greater than previous rewardEndTime. The [`caledRewardRate`](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L578C7-L578C24) is set to 0

With this, the rewardPerTokenAccumulatedCheckpoint will remain the same during checkpoints until the notifyRewardAmount() function is called again with a valid amount.

## Proof of Concept
https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L570-L582

## Tools Used
Manual

## Recommended Mitigation Steps
Apply zero amount checks


## Assessed type

Other
No max fee amount specified on factory
Audit: 2024-02-uniswap-foundation-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L131


# Vulnerability details

## Impact
There is no max fee amount specified on `enableFeeAmount`

## Proof of Concept
```
  function enableFeeAmount(uint24 _fee, int24 _tickSpacing) external {
    _revertIfNotAdmin();
    FACTORY.enableFeeAmount(_fee, _tickSpacing);
  }
```
## Tools Used
Manual review

## Recommended Mitigation Steps
Implement a max fee amount


## Assessed type

Other
Re-entrancy in V3FactoryOwner.claimFees()
Audit: 2024-02-uniswap-foundation-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L181-L198


# Vulnerability details

## Impact
The `V3FactoryOwner.claimFees()` function makes an external call to a IUniswapV3PoolOwnerActions pool collectProtocol() function which allows a recipient to receive pool protocol fees. 
A user can take advantage of the claimFees() function in an external call from user-controlled contract where the user-controlled contract re-enters `V3FactoryOwner.claimFees()` multiple times to collect fees from multiple pools which have protocol fees accummulated.


## Proof of Concept
https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L181-L198

1. Alice deploys contract A.
2. ContactA has a function that calls `claimFees()` of V3FactoryOwner contract with an arbitrary IUniswapV3PoolOwnerActions _pool where pool is ContractA' address
3. This acts as the re-entry point back to ContractA which then makes a flashloan call to a UniswapV3 Pool
4. ContractA makes a flashloan call to UniswapV3 PoolA, the `IUniswapV3FlashCallback(msg.sender).uniswapV3FlashCallback` calls PoolA, and the flow is controlled to call `claimFees()` of V3FactoryOwner contract.
5. With this, UniStaker.notifyRewardAmount() would be called multiple times in the same transaction and increasing the Unistaker `scaledRewardRate` which the user can take advantage of to claim more rewards.


## Tools Used
Manual

## Recommended Mitigation Steps
A non-reentrant modifier or mutex may be necessary. Alternatively, the check-effect-interact pattern should be implemented.








## Assessed type

Reentrancy