The Wildcat Protocol - TuringConsulting'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: 120/131

Findings: 1

Award: $0.06

🌟 Selected for report: 0

🚀 Solo Findings: 0

Lines of code

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

Vulnerability details

Impact

Wildcat Market' closeMarket() function allows the market controller to close the market, setting its APR to 0% and marking it as closed.

In order to only allow the Market's controller to close the market, an onlyController modifier is added, which enforces the msg.sender to only be the controller:

// WilcatMarketBase.sol
modifier onlyController() {
    if (msg.sender != controller) revert NotController();
    _;
}

// WilcatMarket.sol
function closeMarket() external onlyController nonReentrant {
    ...
}

The problem is that the market controller does not have a function to close the market, which effectively renders the closeMarket() not executable. Checking WildcatMarketController.sol, it is not possible to find a function that allows to close the market by calling the closeMarket() function.

Proof of Concept

It is hard to provide a test that proves the vulnerability given that it comes from the lack of code being implemented. To fully understand the issue, it is recommended to:

  1. Check the WildcatMarketController.sol to be aware of the lack of code that allows closing the market

  2. Review the tests that allow the closeMarket() function to be tested. Checking the WildcatMarket.t.sol test file, we can see how ALL the functions that test closing a market use the asAccount modifier to prank the call as a controller, which is used to bypass the onlyController modifier in WildcatMarket.sol. Then, the closeMarket() function is directly called, without executing a function in the controller:

function test_closeMarket_TransferExcessAssets() external asAccount(address(controller)) {
    // Borrow 80% of deposits then request withdrawal of 100% of deposits
    _depositBorrowWithdraw(alice, 1e18, 8e17, 1e18);
    asset.mint(address(market), 1e18);
    vm.expectEmit(address(asset));
    emit Transfer(address(market), borrower, 2e17);
    market.closeMarket();
  }

Tools Used

Manual review, foundry

Add a function in WildcatMarketController.sol that allows the market to be closed.

Assessed type

Other

#0 - c4-pre-sort

2023-10-27T07:11:30Z

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:57Z

MarioPoneder marked the issue as partial-50

#3 - c4-judge

2023-11-07T14:16:53Z

MarioPoneder changed the severity to 3 (High Risk)

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