The Wildcat Protocol - ayden'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: 81/131

Findings: 2

Award: $13.18

🌟 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

market cannot be closed

Proof of Concept

external function closeMarket use an onlyController modifier which is defined in WildcatMarketBase.sol:

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

to ensure that only controller can invoke this function.

and controller is an immutable variable which is set in wildcatMarketBase constructor:


MarketParameters memory parameters = IWildcatMarketController(msg.sender).getMarketParameters();
sentinel = parameters.sentinel;
borrower = parameters.borrower;
controller = parameters.controller;  <------------------------------get from IWildcatMarketController.
feeRecipient = parameters.feeRecipient;
protocolFeeBips = parameters.protocolFeeBips;
delinquencyFeeBips = parameters.delinquencyFeeBips;
delinquencyGracePeriod = parameters.delinquencyGracePeriod;
withdrawalBatchDuration = parameters.withdrawalBatchDuration;

let's have a look at getMarketParameters in WildcatMarketController.sol

  function getMarketParameters() external view returns (MarketParameters memory parameters) {
    parameters.asset = _tmpMarketParameters.asset;
    parameters.namePrefix = _tmpMarketParameters.namePrefix;
    parameters.symbolPrefix = _tmpMarketParameters.symbolPrefix;
    parameters.borrower = borrower;
    parameters.controller = address(this);<-------------------------controller address.
    parameters.feeRecipient = _tmpMarketParameters.feeRecipient;
    parameters.sentinel = sentinel;
    parameters.maxTotalSupply = _tmpMarketParameters.maxTotalSupply;
    parameters.protocolFeeBips = _tmpMarketParameters.protocolFeeBips;
    parameters.annualInterestBips = _tmpMarketParameters.annualInterestBips;
    parameters.delinquencyFeeBips = _tmpMarketParameters.delinquencyFeeBips;
    parameters.withdrawalBatchDuration = _tmpMarketParameters.withdrawalBatchDuration;
    parameters.reserveRatioBips = _tmpMarketParameters.reserveRatioBips;
    parameters.delinquencyGracePeriod = _tmpMarketParameters.delinquencyGracePeriod;
  }

thus , the contract address of WildcatMarketController.sol will be the value of controller. However we can't find any function which invoke closeMarket in WildcatMarketController.sol.

Tools Used

manury

should use onlyBorrower instead of onlyController or add closeMarket in controller

Assessed type

Access Control

#0 - c4-pre-sort

2023-10-27T07:31:30Z

minhquanym marked the issue as duplicate of #147

#1 - c4-judge

2023-11-07T14:08:33Z

MarioPoneder marked the issue as partial-50

#2 - c4-judge

2023-11-07T14:16:53Z

MarioPoneder changed the severity to 3 (High Risk)

Awards

13.1205 USDC - $13.12

Labels

bug
3 (High Risk)
satisfactory
edited-by-warden
duplicate-266

External Links

Lines of code

https://github.com/code-423n4/2023-10-wildcat/blob/main/src/market/WildcatMarketConfig.sol#L74#L81

Vulnerability details

Impact

Once a lender is flagged or sanctioned by Chainalysis, anyone can trigger the nukeFromOrbit function to freeze that account. Subsequently, they can create an Escrow contract to reduce the scaledBalance of the blocked account and transfer the assets to the Escrow contract. However, the lender has the option to monitor the mempool and, upon detecting that their account has been blocked and someone intends to execute a nukeFromOrbit to transfer their tokens to a target contract, they can initiate a transfer transaction and outbid with a higher gas fee to preempt the action.

Proof of Concept

Assume Alice is added to chainalysis block list . And then before someone invoke nukeFromOrbit to freeze his account .Alice can transfer all market ERC20 token to one of his accounts even if the account not interact with this protocol before. 1.transfer token to address attacker 2.use attacker account to get withdrawOnly role 3.invoke market queueWithdrawal

add test case to WildcatMarketConfig.t.sol:

  function test_nukeFromOrbit_WithBalance_FrontRun() external {
    address attacker = vm.addr(1001);

    _deposit(alice, 1e18);

    assert(market.scaledBalanceOf(alice) == 1e18);

    //alice is added to block list.
    address escrow = sanctionsSentinel.getEscrowAddress(alice, borrower, address(market));
    sanctionsSentinel.sanction(alice);

    //front-run to avoid token being transfer to contract.
    vm.prank(alice);
    market.transfer(attacker,1e18);

    //alice is blocked.
    market.nukeFromOrbit(alice);

    assert(market.scaledBalanceOf(alice) == 0);

    //attacker get alice's token.
    assert(market.scaledBalanceOf(attacker) == 1e18);

    assertEq(
      uint(market.getAccountRole(alice)),
      uint(AuthRole.Blocked),
      'account role should be Blocked'
    );

    //get withdraw role.
    address[] memory markets = new address[](1);
    markets[0] = address(market);
    controller.updateLenderAuthorization(attacker,markets);

    assertEq(
      uint(market.getAccountRole(attacker)),
      uint(AuthRole.WithdrawOnly),
      'account role should be WithdrawOnly'
    );

    vm.prank(attacker);
    market.queueWithdrawal(1e18);

    AccountWithdrawalStatus memory accountStatus =  market.getAccountWithdrawalStatus(attacker,86401);
    assert(uint256(accountStatus.scaledAmount) == 1e18);
  }


## Tools Used
vscode
## Recommended Mitigation Steps
It is necessary to check whether a user has been blacklisted when processing user transfers.
However, at the moment, only a check for whether the user has been set to a "Blocked" status has been implemented, and changing this status requires invoking "nukeFromOrbit."





## Assessed type

Access Control

#0 - c4-pre-sort

2023-10-27T03:21:15Z

minhquanym marked the issue as duplicate of #54

#1 - c4-judge

2023-11-07T14:39:54Z

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