Farseen0/scar-pairs huggingface dataset:
LOW severity: Rebalance might not work for pools with less than minimum weight assets ratio. **Severity**: Low

**Status**: Resolved

**Description**

In Contract GlmRebalance, the method `getLatestRebalInfo(...)` has one return variable `bool isValidRebalance`.

This value is set as following:

Here, if any pool’s current weight is less than minimum weight then that pool is considered to.....

Vulnerable code:
for (uint256 i; i < manager.getGmPoolLength(); i++) {
          …
           if (currentWeight < minimumWeight) {               isValidRebalance = true;
           }
       }
       isCorePoolLowerThanThreshold(totalAssets) || isCorePoolsRatioInRange(totalAssets)
           ? isValidRebalance = true
           : isValidRebalance = false;
LOW severity: Update in BTC/ETH pools’ target weight can disrupt rebalancing logic. **Severity**: Low

**Status**: Resolved

**Description**

Since pools’ target weight can be updated using `setPoolTargetWeight(...)` method, there exists a threat that can disrupt the current rebalancing logic.

If BTC and ETH pools’ total weight is less than 50%, the following check in the...

Vulnerable code:
function isCorePoolLowerThanThreshold(uint256 totalAssets) public view returns (bool) {
       IGlmManager manager = IGlmManager(glm.manager);
       uint256 corePoolWeight = manager.getCurrentWeight(0, totalAssets) + manager.getCurrentWeight(1, totalAssets);
       return corePoolWeight < corePoolThreshold ? true : false;
   }

require(
           _corePoolThreshold < DECIMAL_PRECISION && _corePoolThreshold > DECIMAL_PRECISION / 2,
           "corePoolThreshold must be greater than 0 and more than 50% "
       );
LOW severity: Possibility of Rebalacing execution fee being unused and stuck in the contract. **Severity**: Low

**Status**: Resolved

**Description**

In the GlmRebalnce contract, the method `_keeperTokenPurchases(...)` checks if sufficient `msg.value` for the execution of all token purchases using the following check:

Here, when the loops start there is one more check:

Meaning that for.....

Vulnerable code:
require(msg.value >= usdcAmounts.length * executionFee, "Invalid input");

for (uint256 i; i < marketTokens.length; i++) {
           if (usdcAmounts[i] == 0) {
               continue;
           }
… }
LOW severity: Missing validation in the `addGmPool()` method. **Severity**: Low

**Status**: Resolved 

**Description**

In the contract GlmManager.sol, the method `addGmPool()` allows the owner to set the pool info but without the following checks:

This means Owner can bypass this checks when adding a pool but this seems to be important as `targetWeight`...

Vulnerable code:
require(_targetWeight <= DECIMAL_PRECISION, "Target weight is too high"); 
       require(_targetWeight >= gmPools[_index].minimumWeight, "Target weight is too low");
       require(_targetWeight >= 1e28 && _minimumWeight >= 1e28, "weight has to be >1%");
LOW severity: Precision loss due to division before multiplication. **Severity**: Low

**Status**: Resolved

**Description**

In Contract GlmManger.sol, the method `getGmTokenValueInUSDC()` has the following logic:

Here `usdcPrice` is divided by 1e18 before multiplication with (`gmTokenPrice * amount`).

Similarly, the method `getGmTokenAmountFromUSDC` has the...

Vulnerable code:
uint256 gmTokenPrice = IGlmPriceReader(glm.priceReader).getMarketTokenPrice(_gmToken);
       uint256 usdcPrice = IGlmPriceReader(glm.priceReader).getTokenPrice(USDC) / 1e18; 
       return ((gmTokenPrice * _amount) * usdcPrice) / 1e30 / 1e18; //return 1e6

uint256 gmTokenPrice = IGlmPriceReader(glm.priceReader).getMarketTokenPrice(_gmToken);


       uint256 usdcPrice = IGlmPriceReader(glm.priceReader).getTokenPrice(USDC) / 1e18; 
       return (_usdcAmount * 1e30 * usdcPrice * 1e6) / gmTokenPrice;

uint256 usdcAmountFor1Year = (totalAssets() * info.managementFeeBpsFor1Year) / DECIMAL_PRECISION;


       uint256 usdcAmount = (usdcAmountFor1Year * info.managementFeeInterval) / (365 days);
HIGH severity: Unauthorized Withdrawal of Staked ETH via `repayWithStakeToken` Function. **Severity**: Critical

**Status**: Resolved

**Affected Function:** repayWithStakeToken

**Description: **

A critical vulnerability allowing attackers to withdraw ETH staked by other users without proper authorization. The function fails to verify the ownership of the stake ID (`stakeId`) before.....

Vulnerable code:
if (staking.user != msg.sender) revert NotStaker(staking.user);
HIGH severity: Incorrect token transfer source in the stake function of `NonLockStakingPools` contract. **Severity**: High

**Status**:  Resolved

**Description**

The stake function in the `NonLockStakingPools` contract is designed to allow users to stake tokens into a specific pool, identified by `poolId`. Due to an incorrect source address used in the token transfer operation within the...

Vulnerable code:
poolInfo[poolId].totalStaked += amount;


   TokenTransfer._depositToken(pool.stakeToken, address(this), amount);
MEDIUM severity: Premature Finalization Vulnerability in `IDOPoolAbstract` Contract. **Severity** : Medium

**Status** : Resolved

**Description** :

The `IDOPoolAbstract` contract suffers from a significant flaw where it allows the contract owner to finalize an Initial DEX Offering (IDO) prematurely without any checks to ensure that predefined conditions, such as reaching an end...

Vulnerable code:
// Define IDO start and end times, and minimum funding goal
uint256 public idoStartTime;
uint256 public idoEndTime;
uint256 public minimumFundingGoal;

// Modifier to check that the current time is after the IDO end time
modifier onlyAfterIDOEnd() {
    require(block.timestamp > idoEndTime, "IDO has not ended yet");
    _;
}

// Modifier to check that the minimum funding goal has been met
modifier fundingGoalMet() {
    require(fundedUSDValue >= minimumFundingGoal, "Funding goal not met");
    _;
}

// Update the finalize function to include the new conditions
function finalize() external onlyOwner notFinalized onlyAfterIDOEnd fundingGoalMet {
    // Finalization logic
}
MEDIUM severity: Misplaced stake limit validation in stake function of `LockedStakingPools` contract. **Severity**: Medium

**Status**:  Resolved

**Description**

The following check inside the stake function from `LockedStakingPools` contract attempts to restrict users from having more than 100 active stakes in any given pool. 

However, the check for `userStakeIds[poolId][msg.sender].length >...

Vulnerable code:
if (userStakeIds[poolId][msg.sender].length == 0) {
     if (userStakeIds[poolId][msg.sender].length > 100) revert TooManyStake();
     noUsersStaked[poolId] += 1;
   }
MEDIUM severity: “isLeverageEnabled” is true by default. **Severity** : Medium

**Status** : Resolved

**Description**

In the Vault.sol contract, there's a boolean called `isLeverageEnabled` that should be (false) to start. This ensures only PositionManager.sol can manage positions. But, the boolean is mistakenly left (true) when the contract is first...

Vulnerable code:
constructor() public {
    gov = msg.sender;
    isLeverageEnabled = false; // Ensure leverage is disabled by default.
}
MEDIUM severity: Unbounded Iteration Leading to Potential Service Blockage. **Severity** : Medium

**Status** : Resolved

**Description**

`Vault.sol:setTokenConfig` due to the absence of a limit on the number of whitelisted tokens. This can lead to scenarios where operations iterating over these tokens consume more gas than the maximum allowed in a block, potentially...

Vulnerable code:
uint256 public constant MAX_WHITELISTED_TOKENS = 100; // Example maximum number
MEDIUM severity: Preventing Unauthorized ZKLP Token Creation. **Severity** : Medium

**Status** : Resolved

**Description**

The `ZkdlpManager.sol:getAum` function, presents two primary issues:

Denial of Service (DoS) Risk: The function iterates over all tokens listed in the `allWhitelistedTokens` array. If the governance role, through...

Vulnerable code:
function clearTokenConfig(address _token) external override {
    _onlyGov();
    require(whitelistedTokens[_token], "Token not whitelisted");
    totalTokenWeights = totalTokenWeights.sub(tokenWeights[_token]);
    
    // Properly removing the token from allWhitelistedTokens array
    for (uint i = 0; i < allWhitelistedTokens.length; i++) {
        if (allWhitelistedTokens[i] == _token) {
            allWhitelistedTokens[i] = allWhitelistedTokens[allWhitelistedTokens.length - 1];
            allWhitelistedTokens.pop();
            break;
        }
    }
    
    // Clearing token configurations
    delete whitelistedTokens[_token];
    delete tokenDecimals[_token];
    delete tokenWeights[_token];
    delete minProfitBasisPoints[_token];
    delete maxZkusdAmounts[_token];
    delete stableTokens[_token];
    delete shortableTokens[_token];
    whitelistedTokenCount = whitelistedTokenCount.sub(1);
}
LOW severity: `_liquidationFeeUsd` and `_fundingRateFactor` Initialization Checks. **Severity** : Low

**Status** : Resolved

**Description**

The initialize function in Vault.sol should include checks to ensure that `_liquidationFeeUsd` and `_fundingRateFactor` are less than or equal to their respective maximum allowed values (`MAX_LIQUIDATION_FEE_USD` and...

Vulnerable code:
require(_liquidationFeeUsd <= MAX_LIQUIDATION_FEE_USD, "Liquidation fee exceeds maximum");
require(_fundingRateFactor <= MAX_FUNDING_RATE_FACTOR, "Funding rate factor exceeds maximum");
LOW severity: Receiver Address Checks for Zero Address. **Severity** : Low

**Status** : Resolved

**Description**

Functions like `sellZKUSD`, `buyZKUSD`, `swap`, `increasePosition`, and `decreasePosition` should include checks to ensure that the `_receiver` address is not the zero address. This is a common practice to prevent funds from being sent to.....

Vulnerable code:
require(_receiver != address(0), "Receiver cannot be the zero address");
HIGH severity: Method `depositRequest(...)` allows the last deposit to be more than the set deposit cap. **Severity**: High

**Status**: Resolved

**Description**

In Contract Branch.sol, the method `depositRequest()` checks if the `depositCap` has been reached before processing any deposit.

However, the deposit cap reached is set as follows:

Here the liquidity is calculated after tokens have been...

Vulnerable code:
if (depositCapReached[id]) revert DepositCapReached(TAG, id);

if (liquidity > capAmount[id]) {
           depositCapReached[id] = true;
       }
HIGH severity: Minted `ceTokens` not added to users list if minted using `Repay()`. **Severity**: High

**Status**: Resolved

**Description**

In Contract Core.sol, the method `repay(...)` allows a user to deposit any extra amount more than the repay amount. This deposit mints `ceTokens` for the user but the same is not added using `_addToken(...)` method to keep a record of all...

Vulnerable code:
function healthFactor(
       address user
   ) public view returns (Data.HealthData memory health) {
       bytes32[] memory ids = users[user];
       if (ids.length > 0) {
           uint256[] memory prices = oracle.getPrices(ids);
           for (uint256 i; i < ids.length; i++) { … }
     … }
 … }
HIGH severity: Liquidation bonus is 0% when `currentLTV > 1e18`. **Severity**: High

**Status**: Acknowledged

**Description**

In Contract LiquidationManager.sol, the method `liquidate(..)` has the following check:

Here discount is 0 if `currentLTV` is more than 1e18. This means there is no liquidation bonus for liquidators and will lead to a pile of bad...

Vulnerable code:
uint256 discount; 
       uint256 liqPercent = 1e18;
       if (currentLTV < 1e18) {
           discount = 1e36 / currentLTV - 999000000000000000;
           console.log("discount", discount);
           if (discount > config.liqMaxDiscount) {
               discount = config.liqMaxDiscount;
           }
…}}
HIGH severity: Repay paused but Liquidation enabled. **Severity**: High

**Status**: Acknowledged

**Description**

The protocol can enter a state where repay is paused for borrowers but liquidation is open. 

Given the volatility of the market, this state will prevent borrowers from repaying their loans leading to the risk of being liquidated. 

If.....

Vulnerable code:
function repayRequest(
       bytes32 id,
       uint256 amount,
       bytes32 route,
       uint256 airdropAmount
   ) external payable nonReentrant {
       if (protocolPause) revert ProtocolPaused(TAG);
       if (repayPause[id]) revert DepositPaused(TAG, id); 
… }
MEDIUM severity: Liquidation fails if the chainId is not configured for `collateralId` or `debtId`. **Severity**: Medium

**Status**: Acknowledged

**Description**

In Contract `LiquidationManager.sol`, the method `liquidate(...)` allows a liquidator to liquidate a borrowers’ default loan.

This method has the following check:

This check can prevent liquidations if the `chainId` not set for...

Vulnerable code:
if (chainId[collateralId] == "" || chainId[debtId] == "")
           revert ChainIdNotConfigured(TAG);
MEDIUM severity: Check effects Interactions Pattern not being followed. **Severity**: Medium

**Status**: Resolved 

**Description**

Checks effects interactions(CEI) is not being followed in the transfer function of CEToken.sol. There is external call being made on line: 165. Not following CEI can result in cross-function reentrancies. 

The variables such as...

Vulnerable code:
super._transfer(from, to, transferCeAmount);
        _handleReward(from,to);
        ICore(core).handleTransfer(from, to, poolId);

_burn(from, burnAmount);
        _handleReward(from,from);
        return burnAmount;

_burn(from, amount);
        _handleReward(from,from);
LOW severity: Underflow issue in `swap()` method. **Severity**: Low

**Status**: Resolved

**Description**

In Contract Core.sol, the `swap()` method has the following logic:

Here if `chainLiquidity[srcChainId][id] < tokenAmountInSrc`, it will lead to underflow panic error.

**Recommendation**: 

It is advised to check if...

Vulnerable code:
function swap(
       bytes32 id,
       bytes32 srcChainId,
       bytes32 destChainId,
       uint256 tokenAmountInSrc,
       uint256 tokenAmountInDest
   ) external onlyRole(IRoleManager(roleManager).POOL()) {
       if (tokenAmountInDest > tokenAmountInSrc) {
           revert ExcessLiquidityInDest(TAG);
       }
       chainLiquidity[srcChainId][id] -= tokenAmountInSrc; 
…}
LOW severity: Chainlink `basePrice` can be non-positive. **Severity**: Low

**Status**: Resolved

**Description**

In Contract Oracle.sol, the method `getPriceFromChainlink(...)` fetches assets prices from chainlink as follows:

Here `basePrice` is of type int256 meaning it can be a negative value as well. Checking it for just equal to 0 can lead to...

Vulnerable code:
(
           uint80 roundID,
           int256 basePrice,
           /*uint256 startedAt*/,
           uint256 timeStamp,
           uint80 answeredInRound
       ) =
        AggregatorV3Interface(
           aggregator[_symbol]
       ).latestRoundData();


       if (basePrice == 0) revert ChainlinkMalfunction(TAG, _symbol);

if (basePrice <= 0) revert ChainlinkMalfunction(TAG, _symbol);
LOW severity: Incorrect Price validation. **Severity**: Low

**Status**: Resolved

**Description**

In Contract Oracle.sol, the following check is done on the prices fetched from chainlink:

Here a price is a valid price even if price is less than `minValue` or price is more the `maxValue`.

**Recommendation**: 

update the above check to.....

Vulnerable code:
function priceCheck(
       bytes32 _symbol,
       uint256 _price
   ) public view returns (bool status) {
       if (
           _price == 0 ||
           _price == minValue[_symbol] || 
           _price == maxValue[_symbol]
       ) {
           return true;
       }
   }

function priceCheck(
       bytes32 _symbol,
       uint256 _price
   ) public view returns (bool status) {
       if (
           _price == 0 ||
           _price <= minValue[_symbol] || 
           _price >= maxValue[_symbol]
       ) {
           return true;
       }
   }
LOW severity: Missing validation in the method `swapRequest()`. **Severity**: Low

**Status**: Resolved

**Description**

In Contract Branch.sol, the method `swapRequest(...)` allows to swap funds between different chains. It also allows ETH but does not check if `msg.value > qty` or not. The transaction will fail if `msg.value < qty`.

Even if it’s equal to...

Vulnerable code:
if (msg.value == 0 && msg.value > qty) revert InsufficientValue(TAG, msg.value, 0);
MEDIUM severity: The latest `Value` is not saved in the `Write()` method. **Severity**: Medium

**Status**: Resolved

**Description**

In Library DynamicFeeHelper, the method `write(...)` is called to write data after each swap.
Since the timepoint for a block can be written only once, this method has the following condition for early return:

Here, `lastPoint.value` is.....

Vulnerable code:
PointHistory memory lastPoint = pointHistories[lastIndex];
       if (lastPoint.pointTimestamp == blockTimestamp) {
           // Early return if we've already written a timepoint this block
           lastPoint.value = value; 
           return lastIndex;
       }
LOW severity: Method `toLogScale` should be internal. **Severity**: Low

**Status**: Acknowledged

**Description**

In Library DynamicFeeHelper, the method `toLogScale(...)` has the following logic:

Here the result is greater than `type(int32).max`, then returned value is `type(int32).max` which incorrect if `toLofScale()` method is used directly....

Vulnerable code:
// bound the result
       if (result > type(int32).max) {
           return type(int32).max;
       } else if (result < type(int32).min) {
           return type(int32).min;
       } else {
           return int32(result);
       }
MEDIUM severity: Nonce Verification Missing in `permit` Function. **Severity**: Medium

**Status**:  Unresolved

**Source**: ./UniswapV2ERC20.sol

**Description**:

The `permit` function does not include a check to verify that the nonce used in the signature is correct and has not been used before. This omission can lead to potential signature replay attacks,...

Vulnerable code:
mapping (address => uint)                      public nonces;
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s, uint nonce) external {
    require(deadline >= block.timestamp, 'UniswapV2: EXPIRED');
    require(nonce == nonces[owner], 'UniswapV2: INVALID_NONCE'); // Nonce verification
    bytes32 digest = keccak256(
        abi.encodePacked(
            '\x19\x01',
            DOMAIN_SEPARATOR,
            keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonce, deadline))
        )
    );
    address recoveredAddress = ecrecover(digest, v, r, s);
    require(recoveredAddress != address(0) && recoveredAddress == owner, 'UniswapV2: INVALID_SIGNATURE');
    _approve(owner, spender, value);
    nonces[owner] += 1; // Increment nonce after successful approval
}
MEDIUM severity: `updateBeneficiary` function lacks critical validation checks. **Severity**: Medium

**Status**:  Unresolved

**Source**: ./libraries/VestingWallet.sol , ./libraries/VestingWallet2.sol

**Description**:

The `updateBeneficiary` function in the `VestingWallet` contract allows the contract owner to update the share of a beneficiary. However, this function lacks.....

Vulnerable code:
function updateBeneficiary(address wallet, uint256 newShare) external onlyOwner {
  
  // Assuming `bootstrapped` is a state variable indicating if the contract has been bootstrapped
  require(!bootstrapped, 'Cannot update beneficiary as contract has been bootstrapped');
  require(beneficiariesShare[wallet] != newShare, 'New share cannot be the same as old share');
  // Assuming there's a way to check if a beneficiary has transferred USD or any similar condition
  require(!hasTransferredUSD[wallet], 'Beneficiary should have not transferred USD');
  require(newShare > 0, 'Share cannot be smaller or equal to 0');
  require(beneficiariesShare[wallet] != 0 || _beneficiariesWallet.contains(wallet), 'Beneficiary has not been added');

  _release();

  totalShare = totalShare.sub(beneficiariesShare[wallet]).add(newShare);
  require(totalShare <= MAX_TOTAL_SHARE, "Allocation too high");
  beneficiariesShare[wallet] = newShare;
  if (newShare == 0) _beneficiariesWallet.remove(wallet);
  else _beneficiariesWallet.add(wallet);
}
MEDIUM severity: Incorrect Implementation of revoke Function in `VestingWallet` Contract. **Severity**: Medium

**Status**:  Unresolved

**Source**: ./libraries/VestingWallet.sol , ./libraries/VestingWallet2.sol

**Description**:

The revoke function in the `VestingWallet` contract is implemented to transfer all remaining tokens in the contract back to the owner upon revocation. This...

Vulnerable code:
bool public revoked = false; // State variable to track revocation status

    event Revoked(); // Event to indicate revocation

    // Modified revoke function
    function revoke() external onlyOwner {
        require(!revoked, "Contract already revoked");
        require(!nonRevocable, "Revoke not allowed");

        uint256 vestedAmount = releasable(); // Calculate the vested amount
        uint256 unvestedAmount = planeToken.balanceOf(address(this)).sub(vestedAmount); // Calculate unvested amount

        planeToken.transfer(owner(), unvestedAmount); // Transfer unvested tokens back to owner

        revoked = true; // Mark contract as revoked
        emit Revoked();
    }
MEDIUM severity: Lack of Epoch End Block Consideration in `pendingRewards` Function. **Severity**: Medium

**Status**:  Unresolved

**Source**: LpNFTPool.sol

**Description**: 

The `pendingRewards` function calculates the pending rewards for a staking position without considering the end of the epoch block `(endOfEpochBlock)`. This omission can lead to the calculation of rewards...

Vulnerable code:
function pendingRewards(uint256 tokenId) external view returns (uint256) {
    StakingPosition storage position = _stakingPositions[tokenId];

    uint256 accRewardsPerShare = _accRewardsPerShare;
    (,,uint256 lastRewardTime, uint256 reserve, uint256 poolEmissionRate) = master.getPoolInfo(address(this));
    uint256 endOfEpochBlock = master.getEndOfEpochBlock(address(this)); // Assume this function exists or a similar mechanism to retrieve endOfEpochBlock

    // Ensure rewards are calculated within the epoch
    uint256 effectiveLastRewardBlock = lastRewardTime < endOfEpochBlock ? lastRewardTime : endOfEpochBlock;

    if ((reserve > 0 || _currentBlockTimestamp() > effectiveLastRewardBlock) && _lpSupplyWithMultiplier > 0) {
        uint256 duration = _currentBlockTimestamp().sub(effectiveLastRewardBlock);
        uint256 tokenRewards = duration.mul(poolEmissionRate).add(reserve);
        accRewardsPerShare = accRewardsPerShare.add(tokenRewards.mul(1e18).div(_lpSupplyWithMultiplier));
    }

    return position.amountWithMultiplier.mul(accRewardsPerShare).div(1e18).sub(position.rewardDebt)
        .add(position.pendingXPlaneRewards).add(position.pendingPlaneRewards);
}
LOW severity: Lack of Minimum Fee Validation in `setDefaultFee` Function. **Severity**: Low

**Status**:  Unresolved

**Source**: ./HyperPoolFactory.sol

**Description**:

The `setDefaultFee` function in the `HyperPoolFactory` contract allows the contract owner to set a default fee for hyper pools. However, the function only checks that the new fee does not exceed the...

Vulnerable code:
uint256 public constant MIN_DEFAULT_FEE = 1; // Example minimum fee (0.01%), adjust as necessary

function setDefaultFee(uint256 newFee) external onlyOwner {
    require(newFee >= MIN_DEFAULT_FEE && newFee <= MAX_DEFAULT_FEE, "Fee must be between min and max");
    defaultFee = newFee;
    emit SetDefaultFee(newFee);
}