xanoutas/solidity-security-findings huggingface dataset:
Lender can cause unintended behavior for the borrower's transaction
Audit: 2023-10-wildcat-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

This vulnerability comes in the form of when a borrower wants to remove a lender as a both deposit and withdraw and set them as a withdraw only, to avoid paying more interest on their funds in the market, this plan may not go as planned, based on the nature of the lender you might be dealing with, 
A lender that wants to make the borrower pay absolute fee for their funds can simply frontrun this transaction to make them an only deposit lender, and deposit a large amount if the market is not in full capacity yet and refuse to withdraw has some sort of punishment or payback, it is really based on the lender behavior, malicious or non-malicious

## Proof of Concept

Let's Explore how this will be carried out in practice 

The borrower discovers that they don't want this Lender again in the market, as maybe they don't need the funds from them or they just cant pay that high interest rate based on the amount they put in the market, any reason the borrower does this is up to them.

They call the updateLenderAuthorization function to limit the actions of the lender, and make them only a withdrawal lender.

```solidity
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));
    }
  }
```

This calls the updateAccountAutorization function, The updateAccountAuthorization function, which is called from the first function, actually updates the authorization status based on the boolean value _isAuthorized. If the lender is authorized, they're given permission to deposit and withdraw; otherwise, they can only withdraw.

```solidity
function updateAccountAuthorization(
    address _account,
    bool _isAuthorized
  ) external onlyController nonReentrant {
    MarketState memory state = _getUpdatedState();
    Account memory account = _getAccount(_account);
    if (_isAuthorized) {
      account.approval = AuthRole.DepositAndWithdraw;
    } else {
      account.approval = AuthRole.WithdrawOnly;
    }
    _accounts[_account] = account;
    _writeState(state);
    emit AuthorizationStatusUpdated(_account, account.approval);
  }
```

Monitoring the transactions taking place in the market on the mempool and seeing what their beloved borrower is about to do

The lender is not happy about this which means they cant put more money in the market and get paid the fees from it, they decide to frontrun the transaction and deposit a large sum into the account
Deploying a market with a non-ERC20 asset can cause incorrect interaction with asset
Audit: 2023-10-wildcat-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact
The market contract may expect certain ERC20 functions to be present and behave in a specific way. If the asset contract does not adhere to the ERC20 standard, the market may behave unexpectedly, resulting in incorrect token balances, pricing, or other critical parameters.

Example using a `safeTransferFrom` function to transfer assets, If the asset is not an ERC20 token, this call will fail, potentially resulting in a loss of funds or locking of funds in the contract.
Users interacting with the market could also lose funds if they attempt to deposit or withdraw the invalid asset.

## Tools Used
Vscode

## Recommended Mitigation Steps
Implement a validation function that checks if the asset contract adheres to the ERC20 standard. This function should verify that the asset contract has the necessary functions and that they behave as expected.

```
function isValidAsset(address asset) internal view returns (bool) {
    try IERC20(asset).decimals() returns (uint8) {
        // Further checks can be added here as necessary
        return true;
    } catch {
        return false;
    }
}
```



## Assessed type

ERC20
Missing check to avoid zero transfer revert
Audit: 2023-10-wildcat-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details



## Impact
Cannot deploy market with `originationFeeAmount == 0` for ERC20 asset which reverts on zero amount transfers.

## Proof of concept
In `deployMarket()` [the following](https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/WildcatMarketController.sol#L345-L347) is executed:
```solidity
if (originationFeeAsset != address(0)) {
    originationFeeAsset.safeTransferFrom(borrower, parameters.feeRecipient, originationFeeAmount);
}
```
If `originationFeeAmount == 0` then `safeTransferFrom()` reverts](https://github.com/Vectorized/solady/blob/6cce088e69d6e46671f2f622318102bd5db77a65/src/utils/SafeTransferLib.sol#L174) if `originationFeeAsset` is an ERC20 which reverts on zero amount transfers.

## Recommended mitigation
`if (originationFeeAsset != address(0) && originationFeeAmount > 0)`


## Assessed type

ERC20
Uninitialized State Variables
Audit: 2023-10-wildcat-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact
in The _resetTmpMarketParameters function is an internal function, which means it can only be called from within the WildcatMarketController contract itself. If a child contract inherits from WildcatMarketController and calls _resetTmpMarketParameters before _tmpMarketParameters is initialized, it could indeed lead to unexpected behavior.
The _resetTmpMarketParameters() function resets the _tmpMarketParameters struct to its default state. If a child contract calls this function before _tmpMarketParameters is initialized, it will overwrite the _tmpMarketParameters struct with the default values, which could disrupt the logic of the parent contract.
## Proof of Concept
Attack Vector:
- A child contract inherits from the WildcatMarketController contract.
- The child contract calls the _resetTmpMarketParameters() function before the _tmpMarketParameters state variable is initialized.
- This call to _resetTmpMarketParameters() overwrites the _tmpMarketParameters struct with the default values.
- The parent contract then uses the _tmpMarketParameters struct in its operations, leading to unexpected behavior

## Tools Used
manual review
## Recommended Mitigation Steps
ensure that _tmpMarketParameters is always properly initialized before it's used. 


## Assessed type

Other
No Create2 Contract Deployment Check can prevent a borrower from deploying contracts from a factory if deployment fails
Audit: 2023-10-wildcat-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/libraries/LibStoredInitCode.sol#L106-L117


# Vulnerability details

## Descripion
When a contract is deployed using Create2 the deployment can fail without causing a revert. The following conditions can cause it to not revert:

1. A contract already exists at the destination address.
2. Insufficient value to transfer.
3. Sub context reverted.
4. Insufficient gas to execute the initialisation code.
5. Call depth limit reached.

When any of the conditions above occur the CREATE2 opcode completes execution without reverting but the contract will not be deployed.

The `create2WithStoredInitCode` in [LibStoredInitCode](https://github.com/code-423n4/2023-10-wildcat/blob/main/src/libraries/LibStoredInitCode.sol) and `createEscrow` in [WildcatSanctionsSentinel](https://github.com/code-423n4/2023-10-wildcat/blob/main/src/WildcatSanctionsSentinel.sol) don't have these checks.

## Impact 
`create2WithStoredInitCode` is used to deploy controllers and markets. If a controller deployment fails it is still recorded in the archController as a valid controller. The borrower won't be able to deploy a controller again and the initial one won't exist.

`createEscrow` is used to deploy escrows. If an escrow deployment fails. It will have to be deployed again.


## Tools Used
Manual Analysis

## Recommended Mitigation Steps
Add a check that checks the code deployed at the contract address and reverts if it is empty. The codehash or codesize can be checked.


## Assessed type

Other
wrong implementation of rayDiv.
Audit: 2023-10-wildcat-findings
Severity: MEDIUM

# Lines of code

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


# 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 rayDiv(uint256 a, uint256 b) internal pure returns (uint256 c) {
    assembly {
      // equivalent to `require(b != 0 && a <= (type(uint256).max - halfB) / RAY)`
      if or(iszero(b), gt(a, div(sub(not(0), div(b, 2)), RAY))) {
        mstore(0, Panic_ErrorSelector)
        mstore(Panic_ErrorCodePointer, Panic_Arithmetic)
        revert(Error_SelectorPointer, Panic_ErrorLength)
      }

      c := div(add(mul(a, RAY), div(b, 2)), b)
    }
  }

i think its wrong implementation.


## Assessed type

Other
Underflow can be occurred in codebase
Audit: 2023-10-wildcat-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-wildcat/blob/main/src/WildcatArchController.sol#L85-L96
https://github.com/code-423n4/2023-10-wildcat/blob/main/src/WildcatArchController.sol#L128-L139
https://github.com/code-423n4/2023-10-wildcat/blob/main/src/WildcatArchController.sol#L171-L182
https://github.com/code-423n4/2023-10-wildcat/blob/main/src/WildcatArchController.sol#L214-L225


# Vulnerability details

## Impact
Because of the lack of the input validation, underflow can be occurred in the code.

## Proof of Concept

https://github.com/code-423n4/2023-10-wildcat/blob/main/src/WildcatArchController.sol#L85C1-L96C4
```
  function getRegisteredBorrowers(
    uint256 start,
    uint256 end
  ) external view returns (address[] memory arr) {
    uint256 len = _borrowers.length();
    end = MathUtils.min(end, len);
    uint256 count = end - start;
    arr = new address[](count);
    for (uint256 i = 0; i < count; i++) {
      arr[i] = _borrowers.at(start + i);
    }
  }
```
In this code, there is no input validation for the variables start and `end," which could potentially lead to underflow issues.

For instance, the following line of code:
`uint256 count = end - start;`
This lack of input validation is a recurring issue in multiple functions throughout the codebase.
## Tools Used
Manual Review
## Recommended Mitigation Steps
Add the input validation code.
```
function getRegisteredBorrowers(
    uint256 start,
    uint256 end
) external view returns (address[] memory arr) {
    require(end >= start, "End must be greater than or equal to start");
    uint256 len = _borrowers.length();
    end = MathUtils.min(end, len);
    uint256 count = end - start;
    arr = new address[](count);
    for (uint256 i = 0; i < count; i++) {
        arr[i] = _borrowers.at(start + i);
    }
}
```


## Assessed type

Under/Overflow
Early market adopters can force delinquency to game borrowers
Audit: 2023-10-wildcat-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/market/WildcatMarketBase.sol#L449


# Vulnerability details

## Impact
When new markets are created, a lender can call `WildcatMarket.updateState()`. This will trigger a call to `WildcatMarketBase._writeState()`, the check on line 449 `state.liquidityRequired() > totalAssets()` will return false since totalAssets starts as 0. 

This will instantly set the `state.isDelinquent == true` and require the borrower to deposit funds of their own. If the delinquency grace period expires before the borrower has a chance to deposit funds, they will begin getting penalised prior to any lending taking place.

This allows lenders to game markets by triggering updates on markets that are slower to get the required funding they need.

## Proof of Concept
1. Borrower deploys a market using `WildcatMarketController.deployMarket()`
2. Anyone can instantly call `WildcatMarket.updateState()` which will perform a state check then update the state. 
3. Since the check on line 449 `state.liquidityRequired() > totalAssets()` returns false as both sides of the condition return 0, the account will instantly be considered delinquent.
4. Once the `delinquencyGracePeriod` has expired fees will begin acruing at a faster rate.

Further details: `state.LiquidityRequired == 0` as lines 95-97 in `MarketState.sol` all are initially set to 0. `totalAssets() == 0` since no deposits of the base asset has been made.

* note after an account is flagged as delinquent, it will not immediately start acruing fees, a borrower could fund his own market to ensure there is no delinquency fees. The requirement is they do this before the delinquency grace period has been finalised.

## Tools Used
Manual Review

## Recommended Mitigation Steps

The protocol team could prevent users from updating state until borrowing has commenced or adjust the conditional check to `state.liquidityRequired() >= totalAssets()`


## Assessed type

Context
wrong implementation of  bipDiv.
Audit: 2023-10-wildcat-findings
Severity: MEDIUM

# Lines of code

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


# 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 bipDiv(uint256 a, uint256 b) internal pure returns (uint256 c) {
    assembly {
      // equivalent to `require(b != 0 && a <= (type(uint256).max - b/2) / BIP)`
      if or(iszero(b), gt(a, div(sub(not(0), div(b, 2)), BIP))) {
        mstore(0, Panic_ErrorSelector)
        mstore(Panic_ErrorCodePointer, Panic_Arithmetic)
        revert(Error_SelectorPointer, Panic_ErrorLength)
      }

      c := div(add(mul(a, BIP), div(b, 2)), b)
    }
  }

here we have a problem as they have define require(b != 0 && a <= (type(uint256).max - b/2) / BIP)





## Assessed type

Other
Invalid asset address can result to malicious Market Address and loss of fund
Audit: 2023-10-wildcat-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact
The `computeMarketAddress` function is used to calculate the address where a market contract for a specific asset would be deployed. If an invalid asset address is passed, it could potentially lead to a collision with a valid market contract address, causing confusion and potential loss of funds. An invalid asset could lead to corrupted data within the protocol. This could affect calculations, reporting, and other critical functions of the protocol.


## Recommended Mitigation Steps
To mitigate these risks, it is essential to have proper validation checks in place to ensure that the asset passed to this function is valid, supported by the protocol, and not malicious. 

```solidity
function computeMarketAddress(
    address asset,
    string memory namePrefix,
    string memory symbolPrefix
) external view returns (address) {
    require(isValidAsset(asset), "Invalid asset");
    bytes32 salt = _deriveSalt(asset, namePrefix, symbolPrefix);
    return LibStoredInitCode.calculateCreate2Address(ownCreate2Prefix, salt, marketInitCodeHash);
}

function isValidAsset(address asset) internal view returns (bool) {
    // Implement validation logic here, such as checking against a whitelist,
    // verifying adherence to specific token standards, etc.
    return true; // Placeholder return value
}
```


## Tools Used
Vscode


## Assessed type

Invalid Validation
safeTransferFrom Does Not Check for Code at the Token Address
Audit: 2023-10-wildcat-findings
Severity: MEDIUM

# Lines of code

https://github.com/Vectorized/solady/blob/6cce088e69d6e46671f2f622318102bd5db77a65/src/utils/SafeTransferLib.sol#L178


# Vulnerability details

## Impact
The solady safeTransferFrom does not check for code at a token address before transferring. This can result in a deposit being made in a selfdestructed token or an embryonic token (such as one that can be created from another chain's bridge) without the user actually having any tokens.

This attack is currently viable if a token is created then selfdestructed, but is only hypothetical for embryonic tokens because it looks like market creation will fail if the token doesn't exist yet when it checks for decimals. An adjustment in the constructor code could make this viable.

If market creation succeeds but the token does not exist (whether through selfdestruct or not yet created), someone can lend a large amount of it (because deposit trusts safeTransferFrom https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/market/WildcatMarket.sol#L60), and gain a huge supply of the market token without depositing anything.

## Proof of Concept
https://code4rena.com/reports/2023-01-astaria#11-solmate-safetransfer-and-safetransferfrom-does-not-check-the-codesize-of-the-token-address-which-may-lead-to-fund-loss

https://community.thecreed.xyz/c/warez/embryonic-token-attack-the-danger-of-erc20-safetransfers

## Tools Used
Manual

## Recommended Mitigation Steps
Use OpenZeppelin safeTransferFrom


## Assessed type

Invalid Validation
Malicious initial reserve ratio can be used to rug lenders collateral
Audit: 2023-10-wildcat-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact
Wildcat protocol provides borrowers the ability to adjust annual interest BIPs after market deployment. In order to protect lenders the protocol increases the reserve ratio of ratio of the market to 90% for two weeks. The increased reserve ratio allows borrowers to exit if they chose for up to 2 weeks before the reserve ratio is reset back to baseline. This calculation assumes initial reserve ratio starts lower than 90%. If the initial reserve ratio is set higher, the borrower can instantly lower the reserve ratio to 90% by lowering the annual interest BIPs.

This allows the borrower the ability to withdraw up to an additional 10% of the market total supply which previously a lender would have considered part of the reserve ratio (something which under normal conditions can't be lowered below the initial baseline level).

## Proof of Concept
Consider the following scenario;

1. A borrower deploys a market, sets the reserve ratio to 98%, a seemingly extremely safe market where the lenders have a greater chance than others at being repaid. The lenders accept this market under those conditions.
2. Once the borrower has maxed out the expected totalSupply of marketTokens they can then call `WildcatMarketController.setAnnualInterestBips()` where the annual interest rate value is lower than expected. This will instantly give them access to an additional 8% of user funds. 

Further notes: it is important to note that setting reserve ratios of 98% is allowed by the system currently and it is important to consider that the market lenders and borrowers though agreeing to a system perhaps not run as intended by Wildcat, can only agree to how they believe the system to behave. Without strictly inspecting the code a lender would have no idea that despite having a reserve ratio of 98%, the borrower has access to 10%, not 2% of lender funds.

I have set the rating for this as medium due to the setup requirements of this attack. Though it could be argued that 8% of user funds could attribute to a significant portion. The file is both in scope and no notes have been included in the audit about any out of scope aspects of invariant testing.

## Tools Used
Manual Review

## Recommended Mitigation Steps

Lenders should have sanction status checked when transferring.


## Assessed type

Rug-Pull
Incorrect Order of Operations in nukeFromOrbit Function
Audit: 2023-10-wildcat-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact
 the nukeFromOrbit function, the nonReentrant modifier is correctly applied. This means that the function cannot be reentered while it is already being executed the problem is that  The _blockAccount(state, accountAddress) function is called before _writeState(state). If the _blockAccount function modifies the state in a way that affects the _writeState function, then it could potentially be exploited allow an attacker to steal funds from the market, or to prevent sanctioned accounts from being blocked. It also undermines the trust and integrity of the market as it allows unauthorized control over the market's funds.
## Proof of Concept
here is a scenario !
 -    The attacker deposits funds into the market associated with their address.

 -    The attacker calls the nukeFromOrbit() function, passing in their own address.

 -    Before the escrow contract is called, the attacker reenters the nukeFromOrbit() function due to the nonReentrant modifier being incorrectly implemented.

 -    In the second call to the nukeFromOrbit() function, the attacker manipulates the state such that the funds are transferred to their own address.

 -    The attacker withdraws the funds from their own address, effectively stealing the funds from the market.
## Tools Used
manual review 
## Recommended Mitigation Steps
the _blockAccount function should be called after _writeState(state). This would ensure that the funds are transferred to the escrow contract before they could be manipulated.


## Assessed type

Other