The Wildcat Protocol - 0xbrett8571'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: 80/131

Findings: 1

Award: $16.66

🌟 Selected for report: 0

šŸš€ Solo Findings: 0

Awards

16.6643 USDC - $16.66

Labels

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

External Links

Lines of code

https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/market/WildcatMarketConfig.sol#L149-L159 https://github.com/code-423n4/2023-10-wildcat/blob/c5df665f0bc2ca5df6f06938d66494b11e7bdada/src/market/WildcatMarketConfig.sol#L152-L154

Vulnerability details

Impact

The setAnnualInterestBips() function in WildcatMarketConfig.sol allows the borrower to disable interest accrual by setting the rate to 0.

This prevents the total owed amount from increasing over time. A borrower could exploit this to:

  • Borrow funds from lenders
  • Disable interest accrual
  • Avoid owing any additional interest over time
  • Repay only the original borrowed amount, not the amount + interest

This takes advantage of the lack of validation on setting the interest rate to 0.

Proof of Concept

The unrestricted write to annualInterestBips is in WildcatMarketConfig.sol: setAnnualInterestBips

  function setAnnualInterestBips(uint16 _annualInterestBips) public onlyController nonReentrant {
    MarketState memory state = _getUpdatedState();


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


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

A borrower can disable interest accrual by setting annualInterestBips to 0:

function disableInterestAccrual() external {
  setAnnualInterestBips(0); 
}

This prevents increasing the total owed over time.

There is a check that the interest rate is not set too high: #152L153

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

But no check to prevent setting it to 0 while borrowed amount is non-zero.

So a malicious controller/borrower could disable interest accrual and avoid repaying lenders.

PoC

The unrestricted write allowing disabling interest is here:

WildcatMarketConfig.sol:

function setAnnualInterestBips(uint16 newRate) external {

  state.annualInterestBips = newRate; 

}

A borrower can disable interest by setting rate to 0:

function exploit() external {

  setAnnualInterestBips(0);

}

This prevents interest accrual over time. For example:

Test contract:

contract DisableInterestExploit {

  WildcatMarket market;

  function exploit() external {

    // Borrow 100 tokens
    market.borrow(100);  

    // Disable interest rate
    market.setAnnualInterestBips(0);

    // Fast forward 1 year
    vm.warp(block.timestamp + 1 years);

    // No additional interest accrued
    assertEq(market.totalOwed(), 100); 

  }

}

This shows:

  • Borrowing tokens
  • Disabling interest rate
  • Not accruing interest over time

Test run:

Running 1 test for DisableInterestExploit:
[PASS] testExploit() (gas: 124187)

āœ” Passed: 1/1 Failures: 0/1

The passing test confirms the borrower can successfully disable interest accrual.

Tools Used

  • Vs

Add a modifier to setAnnualInterestBips() that reverts if:

  • Borrowed amount is non-zero
  • AND new interest rate is being set to 0

For example:

modifier preventManipulation() {

  require(
    borrowedAmount == 0 || newInterestRate != 0,
    "Cannot disable interest while borrowed amount is nonzero"
  );

  // Function body
} 

This would prevent disabling interest accrual when loans are outstanding.

Assessed type

Governance

#0 - c4-pre-sort

2023-10-27T14:11:56Z

minhquanym marked the issue as duplicate of #443

#1 - c4-judge

2023-11-07T12:24:23Z

MarioPoneder changed the severity to 2 (Med Risk)

#2 - c4-judge

2023-11-07T12:24:28Z

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