The Wildcat Protocol - trachev's results

Banking, but worse - a protocol for fixed-rate, undercollateralised credit facilities.

General Information

Platform: Code4rena

Start Date: 16/10/2023

Pot Size: $60,500 USDC

Total HM: 16

Participants: 131

Period: 10 days

Judge: 0xTheC0der

Total Solo HM: 3

Id: 296

League: ETH

Wildcat Protocol

Findings Distribution

Researcher Performance

Rank: 45/131

Findings: 2

Award: $137.73

🌟 Selected for report: 0

🚀 Solo Findings: 0

Lines of code

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

Vulnerability details

Impact

The closeMarket function in WildcatMarket.sol is used when a borrower has finished utiliizng the funds of a market and wants to stop interest accrual of lenders. The issue comes from the usage of the wrong modifier in the closeMarket function. Currently, the onlyController modifier allows only the controller of a market, which is a WildcatMarketController smart contract, to call the closeMarket function. However, there is no function defined on WildcatMarketController.sol that makes a call to closeMarket, preventing a borrower from ever closing their market. Consequently, the accrual of interest for lenders who do not withdraw their funds would never stop, forcing borrowers to continue to pay interest.

Proof of Concept

function closeMarket() external onlyController nonReentrant { MarketState memory state = _getUpdatedState(); state.annualInterestBips = 0; state.isClosed = true; state.reserveRatioBips = 0; if (_withdrawalData.unpaidBatches.length() > 0) { revert CloseMarketWithUnpaidWithdrawals(); } uint256 currentlyHeld = totalAssets(); uint256 totalDebts = state.totalDebts(); if (currentlyHeld < totalDebts) { // Transfer remaining debts from borrower asset.safeTransferFrom(borrower, address(this), totalDebts - currentlyHeld); } else if (currentlyHeld > totalDebts) { // Transfer excess assets to borrower asset.safeTransfer(borrower, currentlyHeld - totalDebts); } _writeState(state); emit MarketClosed(block.timestamp); }

As it can be seen, the closeMarket function uses the onlyController modifier, which prevents a borrower from closing their markets.

Tools Used

Manual review

Replace onlyController with onlyBorrower in the closeMarket function.

Assessed type

Invalid Validation

#0 - c4-pre-sort

2023-10-27T07:10:46Z

minhquanym marked the issue as duplicate of #147

#1 - c4-judge

2023-11-07T13:53:20Z

MarioPoneder changed the severity to 2 (Med Risk)

#2 - c4-judge

2023-11-07T14:01:10Z

MarioPoneder marked the issue as partial-50

#3 - c4-judge

2023-11-07T14:16:53Z

MarioPoneder changed the severity to 3 (High Risk)

Findings Information

🌟 Selected for report: MiloTruck

Also found by: CaeraDenoir, T1MOH, ast3ros, elprofesor, joaovwfreire, rvierdiiev, t0x1c, trachev

Labels

bug
2 (Med Risk)
downgraded by judge
satisfactory
duplicate-497

Awards

137.6749 USDC - $137.67

External Links

Lines of code

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

Vulnerability details

Impact

Reducing the annual interest rate of a market results in sanctions for the borrower by increasing the reserve ratio to 90% for a span of two weeks. Currently, it is assumed that no borrower would deploy a market with a reserve ratio of such high percentage as it would not be beneficial for them. However, a reserve ratio in the range of 90% would not only attract more lenders to deposit into the protocol but would open the door to a serious vulnerability. A market with a reserve ratio near, equal to or higher than 90% protects the borrower from being sanctioned when decreasing the annual interest rate as it would not bring any impactful changes to the reserve ratio. In fact, decreasing the interest rate is beneficial for the borrower if the market has a reserve ratio equal to or higher than 90%. Consequently, a malicious borrower can exploit this the following way: after deploying the market they decrease the annual interest rate to an insignificant amount without being negatively affected and without being required to return any funds to fill in the reserve ratio(as it was 90% before the decrease of the interest rate and they would not be delinquent). After that, they make use of the funds outside of the reserve ratio, paying an insignificant amount of interest.

Proof of Concept

  1. Malicious borrower needs 1000 USDT for some purpose. Instead of deploying a market with an ordinary reserve ratio of 10% they deploy a market with a reserve ratio of 90% and a max total supply of 10,000 USDT.
  2. A lender gets deceived by the good offer assuming they would be acquiring large interest safely, due to the large sum and low borrowable amount.
  3. Borrower immediately decreases the interest rate to an insignificant amount, escaping from any sanctions and makes use of the 1000 USDT they initially needed without having to pay a large interest.

Tools Used

Manual review

There are no clear mitigations for this issue. Perhaps limiting the maximum reserve ratio to 50%-70% could be an effective fix.

Assessed type

Other

#0 - c4-pre-sort

2023-10-27T17:02:35Z

minhquanym marked the issue as duplicate of #75

#1 - c4-judge

2023-11-07T18:35:10Z

MarioPoneder changed the severity to 2 (Med Risk)

#2 - c4-judge

2023-11-07T18:35:24Z

MarioPoneder marked the issue as satisfactory

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter