xanoutas/solidity-security-findings huggingface dataset:
wrong written code for "error selector and argument"
Audit: 2023-10-wildcat-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-wildcat/blob/main/src/libraries/Errors.sol#L60


# Vulnerability details

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

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

## Tools Used

## Recommended Mitigation Steps

function revertWithSelectorAndArgument(uint256 errorSelector, uint256 argument) pure {
  assembly {
    mstore(0, errorSelector)
    mstore(0x20, argument)
    revert(Error_SelectorPointer, 0x24)
  }
}
we should store argument as address 4.

Recommended Mitigation Steps:
function revertWithSelectorAndArgument(uint256 errorSelector, uint256 argument) pure {
  assembly {
    mstore(0, errorSelector)
    mstore(4, argument)
    revert(Error_SelectorPointer, 0x24)
  }
}



## Assessed type

Other
Attacker can front-running the borrower calls to the `dauthorizeLenders` function by blocking themself
Audit: 2023-10-wildcat-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/WildcatMarketController.sol#L162-L177
https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/WildcatMarketController.sol#L182-L190
https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/market/WildcatMarketConfig.sol#L112-L126
https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/market/WildcatMarketConfig.sol#L117
https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/market/WildcatMarketBase.sol#L150-L155
https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/market/WildcatMarketConfig.sol#L74-L81
https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/market/WildcatMarketConfig.sol#L88-L102


# Vulnerability details

## Impact
borrowers can call the `deauthorizeLenders` function to set an address to unAutorized or remove it from the lender address list, in the comment of this function it mentioned that the borrower should call the `updateLenderAuthorization` seperatly to update the changed state,however a malicous lender address can front run the borrower call to the `dauthorizeLenders` to prevent the borrower to remove him by blocking himself by calling the `nukeFromOrbit` function and in this case the call to `updateLenderAuthorization` function reverts due to the call to the `getAccount` which check if the address is blocked or not, if blocked then the whole transaction revert.

## Proof of Concept
the `deauthorizeLenders` function:

```solidity 
 /**
     * @dev Revoke authorization for a set of lenders.
     *
     *      Note: Only updates the internal set of approved lenders.
     *      Must call `updateLenderAuthorization` to apply changes
     *      to existing market accounts
     */
    function deauthorizeLenders(
        address[] memory lenders
    ) external onlyBorrower {
        for (uint256 i = 0; i < lenders.length; i++) {
            address lender = lenders[i];
            if (_authorizedLenders.remove(lender)) {
                emit LenderDeauthorized(lender);
            }
        }
    }
```
As indicated in the comment, changes to the market addresses should be applied by calling the `updateLenderAuthorization` function, which is implemented as follows:

```solidity 
/**
     * @dev Update lender authorization for a set of markets to the current
     *      status.
     */
    function updateLenderAuthorization(
        address lender,
        address[] memory markets
    ) external {
        for (uint256 i; i < markets.length; i++) {
            address market = markets[i];
            if (!_controlledMarkets.contains(market)) {
                revert NotControlledMarket();
            }
            //@audit its imposible to remove blocked address !
            Wil
Sanctioned account get Funds stuck if market is removed from the ``WildcatArchController``
Audit: 2023-10-wildcat-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/WildcatSanctionsSentinel.sol#L100-L102
https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/market/WildcatMarketWithdrawals.sol#L164-L170


# Vulnerability details

## Impact
Markets can be added and removed from the ``ArchController`` by the controller and owner respectively.
Removal of a market from the ArchController is expected, however this creates an issue for sanctioned acccount.
## Proof of Concept
Sanctioned accounts are unable to make a withdrawal because the function ``createEscrow`` checks if the market is registered.
```solidity
  function createEscrow(
    address borrower,
    address account,
    address asset
  ) public override returns (address escrowContract) {
     if (!IWildcatArchController(archController).isRegisteredMarket(msg.sender)) {
      revert NotRegisteredMarket();
    }
```
This causes a DOS for addresses with a sanction as the transaction would always revert and users will not get their funds. 
After a discussion with the sponsor, it was said that the check will be removed from the sanctions sentinel to keep it from affecting withdrawal.
## Tools Used
Manual Review
## Recommended Mitigation Steps

As said by the sponsor, the check would be removed to allow santioned users access their funds.


## Assessed type

Error
removes a lender with a single function call
Audit: 2023-10-wildcat-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/WildcatMarketController.sol#L169-L190


# Vulnerability details

## Impact
Suppose, A lender has lent "A borrower" some amount of eth or token. Now, after borrowing, the borrower
can remove the lender with these 2 simple function calls. As there is no restriction to remove the lender and there is no kind of check if the lender has lent any money; before he was removed,this functions can create unwanted situations.

## Proof of Concept
    *      Note: Only updates the internal set of approved lenders.
   *      Must call `updateLenderAuthorization` to apply changes
   *      to existing market accounts
   
  function deauthorizeLenders(address[] memory lenders) external onlyBorrower {
    for (uint256 i = 0; i < lenders.length; i++) {
      address lender = lenders[i];
      if (_authorizedLenders.remove(lender)) {
        emit LenderDeauthorized(lender);
      }
    }
  }


  
   * @dev Update lender authorization for a set of markets to the current status.
 
  function updateLenderAuthorization(address lender, address[] memory markets) external {
    for (uint256 i; i < markets.length; i++) {
      address market = markets[i];
      if (!_controlledMarkets.contains(market)) {
        revert NotControlledMarket();
      }
      WildcatMarket(market).updateAccountAuthorization(lender, _authorizedLenders.contains(lender));
    }
  }

## Tools Used
Manual Review

## Recommended Mitigation Steps
Highly recommend to add a check to see if the lender has lent any kind of valuables, before this function can fully execute.


## Assessed type

Invalid Validation
Fee-On-Transfer Issue
Audit: 2023-10-wildcat-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/market/WildcatMarket.sol#L60
https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/market/WildcatMarket.sol#L154


# Vulnerability details

## Impact
`WildcatMarket` contract transfers funds from `msg.sender` using function call `safeTransferFrom(msg.sender, address(this), amount);`, but do not verify that the actual number of tokens received matches the `amount`. This could lead to accounting issues if the token involves a fee on transfer. An attacker might exploit latent funds to get a free credit. To prevent this, consider checking the balance before and after the transfer and use the difference as the actual amount received.

## Proof of Concept
In `WildcatMarket` contract, [`depositUpTo`](https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/market/WildcatMarket.sol#L42-L77) function (Line 60) and [`closeMarket`](https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/market/WildcatMarket.sol#L142-L162) function (Line 154) do not check actual amount of tokens received after `safeTransferFrom(`... and are vulnerable to Fee-On-Transfer Issue.

https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/market/WildcatMarket.sol#L42-L77

https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/market/WildcatMarket.sol#L142-L162


## Tools Used
Manual Review

## Recommended Mitigation Steps
Check balance before and after the transfer and use the difference as the actual amount received.

## Links
https://github.com/code-423n4/2023-10-ethena/blob/main/bot-report.md#m-02-possible-vulnerability-to-fee-on-transfer-accounting-issues
https://solodit.xyz/issues/m-25-consistently-check-account-balance-before-and-after-transfers-for-fee-on-transfer-discrepancies-code4rena-vetoken-finance-vetoken-finance-contest-git
https://solodit.xyz/issues/m-06-consistently-check-account-balance-before-and-after-transfers-for-fee-on-transfer-discrepencies-code4rena-behodler-behodler-contest-git






## Assessed type

ERC20
Unsafe uint32 conversion during queueWithdrawal can brick the market
Audit: 2023-10-wildcat-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-wildcat/blob/main/src/market/WildcatMarketWithdrawals.sol#L95
https://github.com/code-423n4/2023-10-wildcat/blob/main/src/libraries/FeeMath.sol#L30-L38


# Vulnerability details

## Impact
In `queueWithdrawal`, there is an unsafe uint32 conversion
```
        // If there is no pending withdrawal batch, create a new one.
        if (state.pendingWithdrawalExpiry == 0) {
            state.pendingWithdrawalExpiry = uint32(
                block.timestamp + withdrawalBatchDuration
            );
            emit WithdrawalBatchCreated(state.pendingWithdrawalExpiry);
        }
```
Which will cause `pendingWithdrawalExpiry` to overflow back to the past. Any interaction with market contract after the last `queueWithdrawal` will revert due to subtraction overflow in `calculateBaseInterest`. Before any interaction, `_getUpdatedState` is called. It tries to update scale factor with the past expiry
```
uint256 expiry = state.pendingWithdrawalExpiry;
      // Only accrue interest if time has passed since last update.
      // This will only be false if withdrawalBatchDuration is 0.
      if (expiry != state.lastInterestAccruedTimestamp) {
        (uint256 baseInterestRay, uint256 delinquencyFeeRay, uint256 protocolFee) = state
          .updateScaleFactorAndFees(
            protocolFeeBips,
            delinquencyFeeBips,
            delinquencyGracePeriod,
            expiry
          );
```
The expiry is then passed down to this code block in `calculateBaseInterest`
```
    baseInterestRay = MathUtils.calculateLinearInterestFromBips(
      state.annualInterestBips,
      timestamp - state.lastInterestAccruedTimestamp
    );
```
Causing revert due to overflow.

This scenario could happen in 2 cases
1. block timestamp reach `2 ** 32 - withdrawalBatchDuration + 1`
2. `MaximumWithdrawalBatchDuration` is misconfigured and allow high value that could cause overflow
## Proof of Concept
The test extends `BaseMarketTest`
```
    function test_ExpiryOverflow() public {
        vm.warp(2 ** 32 - parameters.withdrawalBatchDuration + 1);
        // Prepare some deposit
        uint256 depositAmount = 1e18;
        vm.startPrank(alice);
        asset.mint(alice, depositAmount);
        asset.approve(address(market), depositAmount);
        market.depositUpTo(depositAmount);
        // Queue withdrawal
        market.queueWithdrawal(depositAmount);
        uint32 expiry = uint32(
            block.timestamp + parameters.withdrawalBatchDuration
        );
        // Any interaction afterward will revert
        vm.expectRevert(stdError.arithmeticError);
        market.executeWithdrawal(alice, expiry);
        vm.expectRevert(stdError.arithmeticError);
        market.updateState();
    }
```

## Tools Used
- Manual review
- Foundry

## Recommended Mitigation Steps
Use safe cast or make sure that `MaximumWithdrawalBatchDuration` is properly configured


## Assessed type

Under/Overflow
potential griefing attack on setReserveRatioBips
Audit: 2023-10-wildcat-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/market/WildcatMarketConfig.sol#L171-L194


# Vulnerability details

## Impact
griefing attack can happen at setReserveRationBips by lenders  .
 

## Proof of Concept
here is how liquidity work 
   

             function liquidityRequired(
       MarketState memory state
     ) internal pure returns (uint256 _liquidityRequired) {
      uint256 scaledWithdrawals = state.scaledPendingWithdrawals;
      uint256 scaledRequiredReserves = (state.scaledTotalSupply - scaledWithdrawals).bipMul(
      state.reserveRatioBips
     ) + scaledWithdrawals;
    return
      state.normalizeAmount(scaledRequiredReserves) +
      state.accruedProtocolFees +
      state.normalizedUnclaimedWithdrawals;
  }

by front running, lenders call queueWithdrawal with certain amount while controller try to setReserveRationBips .Transaction will be revert 
## Tools Used
manual view
## Recommended Mitigation Steps
add pause function , 
then pause when protocol call is being executed


## Assessed type

DoS
Use of `transfer()` Might Render asset Impossible to Withdraw
Audit: 2023-10-wildcat-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-wildcat/blob/main/src/WildcatSanctionsEscrow.sol#L38


# Vulnerability details

## Impact
The protocol uses Solidity’s `transfer()` when transferring asset. This has some notable shortcomings when the recipient is a smart contract, which can render asset impossible to transfer. Specifically, the transfer will inevitably fail when the smart contract:
- does not implement a payable fallback function, or
- implements a payable fallback function which would incur more than 2300 gas units, or
- implements a payable fallback function incurring less than 2300 gas units but is called through a proxy that raises the call’s gas usage above 2300.

## Proof of Concept
```solidity
File: src/WildcatSanctionsEscrow.sol

38:     IERC20(asset).transfer(account, amount);

```

## Tools Used
VS Code, Manual Review

## Recommended Mitigation Steps
Using `call` with its returned boolean checked in combination with re-entrancy guard is highly recommended.


## Assessed type

ETH-Transfer
Borrower can abuse `setAnnualInterestBips` to set an interest rate lower than the minimum allowable (`minimumAnnualInterestBips`)
Audit: 2023-10-wildcat-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-wildcat/blob/main/src/WildcatMarketController.sol#L468-L488


# Vulnerability details

## Impact

Any market which is created is tied to a specific controller, which has specific allowable ranges for core market parameters, such as `minimumAnnualInterestBips`. There is currently an issue where when the borrower calls the `setAnnualInterestBips` function of the WildcatMarketController, they can effectively circumvent the `minimumAnnualInterestBips` and set a new interest rate to any value, including 0. This effectively breaks the constraints of the WildcatMarketController and is invalid.

## Proof of Concept

When the borrower wants to change the interest rate for a given market, they call `WildcatMarketController:setAnnualInterestBips` which is defined as follows:
```solidity
function setAnnualInterestBips(
  address market,
  uint16 annualInterestBips
) external virtual onlyBorrower onlyControlledMarket(market) {
  // If borrower is reducing the interest rate, increase the reserve
  // ratio for the next two weeks.
  if (annualInterestBips < WildcatMarket(market).annualInterestBips()) {
    TemporaryReserveRatio storage tmp = temporaryExcessReserveRatio[market];

    if (tmp.expiry == 0) {
      tmp.reserveRatioBips = uint128(WildcatMarket(market).reserveRatioBips());

      // Require 90% liquidity coverage for the next 2 weeks
      WildcatMarket(market).setReserveRatioBips(9000);
    }

    tmp.expiry = uint128(block.timestamp + 2 weeks);
  }

  WildcatMarket(market).setAnnualInterestBips(annualInterestBips);
}
```

This then makes a call to `WildcatMarketConfig:setAnnualInterestBips`:
```solidity
function setAnnualInterestBips(uint16 _annualInterestBips) public onlyController nonReentrant {
  MarketState memory state = _getUpdatedState();

  if (_annualInterestBips > BIP) {
    revert InterestRateTooHigh();
  }

  state.annualInterestBips = _annualInterestBips;
  _writeState(state);
  emit AnnualInterestBipsUpdated(_annualInterestBips);
}
```

As can be seen in this flow, there is never any check as to whether the new interest rate is >= `minimumAnnualInterestBips` (or <= `maximumAnnualInterestBips`). This means the borrower can circumvent the controls of the WildcatMarketController.

## Tools Used

Manual review

## Recommended Mitigation Steps

Ensure that all changes to market parameters still result in those parameters being within the constraints specified by the WildcatMarketController.


## Assessed type

Other
Insecure Access Control: Unauthorized Removal of Entities
Audit: 2023-10-wildcat-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-wildcat/blob/main/src/WildcatArchController.sol#L70
https://github.com/code-423n4/2023-10-wildcat/blob/main/src/WildcatArchController.sol#L113
https://github.com/code-423n4/2023-10-wildcat/blob/main/src/WildcatArchController.sol#L156
https://github.com/code-423n4/2023-10-wildcat/blob/main/src/WildcatArchController.sol#L199


# Vulnerability details

## Impact
The contract allows only the owner to perform critical functions such as removing borrowers, controller factories, controllers, and markets. This centralized control contradicts the fundamental principles of blockchain technology, as it undermines decentralization and opens doors for potential abuse. Unauthorized removal of these entities can lead to market disruptions, loss of user funds, and loss of trust in the protocol's integrity.

## Proof of Concept
```solidity
File: src/WildcatArchController.sol

70:   function removeBorrower(address borrower) external onlyOwner {

113:   function removeControllerFactory(address factory) external onlyOwner {

156:   function removeController(address controller) external onlyOwner {

199:   function removeMarket(address market) external onlyOwner {

```

## Tools Used
VS Code, Manual Review

## Recommended Mitigation Steps
Implement a robust and decentralized access control mechanism. Consider utilizing access control libraries like OpenZeppelin's `Ownable` to manage ownership and permissions. Use a multi-signature or governance-based approach to decision-making, ensuring that critical actions require consensus among multiple stakeholders. Regularly audit and update access control policies to adapt to evolving security standards and user requirements.


## Assessed type

Access Control
In certain cases the delinquency time for a borrower will not be decremented, even if they are no longer delinquent
Audit: 2023-10-wildcat-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-wildcat/blob/main/src/libraries/FeeMath.sol#L159-L165
https://github.com/code-423n4/2023-10-wildcat/blob/main/src/libraries/FeeMath.sol#L61-L65
https://github.com/code-423n4/2023-10-wildcat/blob/main/src/libraries/FeeMath.sol#L115
https://github.com/code-423n4/2023-10-wildcat/blob/main/src/libraries/MathUtils.sol#L59-L65


# Vulnerability details

## Impact

In certain cases the delinquency time for a borrower will not be decremented, even if they are no longer delinquent. Considering that it is in the best interest of the lenders that the delinquency time for a borrower not be decremented, as it increases the likelihood that they receive the delinquency fee, they can game updates to the system to increase this likelihood. Ultimately the borrower is unfairly impacted, as their delinquency time in certain cases will not be properly decremented.

## Proof of Concept

When the state is being updated to accrue for fees, the `updateScaleFactorAndFees` function of FeeMath is called, which the following logic relevant to updating the delinquency:
```solidity
  function updateScaleFactorAndFees(
    MarketState memory state,
    uint256 protocolFeeBips,
    uint256 delinquencyFeeBips,
    uint256 delinquencyGracePeriod,
    uint256 timestamp
  )
    internal
    pure
    returns (uint256 baseInterestRay, uint256 delinquencyFeeRay, uint256 protocolFee)
  {
    ...
    if (delinquencyFeeBips > 0) {
      delinquencyFeeRay = state.updateDelinquency(
        timestamp,
        delinquencyFeeBips,
        delinquencyGracePeriod
      );
    }
    ...
  }
```

The `updateDelinquency` function is called, which is implemented as follows:
```solidity
  function updateDelinquency(
    MarketState memory state,
    uint256 timestamp,
    uint256 delinquencyFeeBips,
    uint256 delinquencyGracePeriod
  ) internal pure returns (uint256 delinquencyFeeRay) {
    ...
    uint256 timeWithPenalty = updateTimeDelinquentAndGetPenaltyTime(
      state,
      delinquencyGracePeriod,
      timestamp - state.lastInterestAccruedTimestamp
    );
    ...
  }
```

Here notice that they are passing `timestamp - state.lastInterestAccruedTimestamp`, which is the difference between the current block.timestamp and the last interest accrual, as `timeDelta` to the `updateTimeDelinquentAndGetPenaltyTime` function. This is implemented as follows:
```solidity
  function updateTimeDelinquentAndGetPenaltyTime(
    MarketState memory state,
    uint256 delinquencyGracePeriod,
    uint256 timeDelta
  ) internal pure returns (uint256 /* timeWithPenalty */) {
    // Seconds in delinquency at last update
    uint256 previousTimeDelinquent = state.timeDelinquent;

    if (state.isDelinquent) {
      ...
    }

    // Reduce the total time in delinquency by the time elapsed, stopping
    // when it reaches zero.
    state.timeDelinquent = previousTimeDelinquent.satSub(timeDelta).toUint32();
    ...
  }
```

Here we are assuming that the borrower