Yield Witch v2 contest - csanuragjain's results

Fixed-rate borrowing and lending on Ethereum

General Information

Platform: Code4rena

Start Date: 14/07/2022

Pot Size: $25,000 USDC

Total HM: 2

Participants: 63

Period: 3 days

Judge: PierrickGT

Total Solo HM: 1

Id: 147

League: ETH

Yield

Findings Distribution

Researcher Performance

Rank: 1/63

Findings: 3

Award: $11,252.55

🌟 Selected for report: 1

🚀 Solo Findings: 1

Findings Information

🌟 Selected for report: csanuragjain

Labels

bug
3 (High Risk)
sponsor confirmed

Awards

11184.2105 USDC - $11,184.21

External Links

Lines of code

https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L232

Vulnerability details

Impact

It was observed that the debt and collateral which moves for Auction is calculated incorrectly. In case where line.proportion is set to small value, chances are art will become lower than min debt. This causes whole collateral to go for auction, which was not expected


Proof of Concept

  1. Assume line.proportion is set to 10% which is a valid value

  2. Auction is started on Vault associated with collateral & base representing line from Step 1

  3. Now debt and collateral to be sold are calculated in _calcAuction

uint128 art = uint256(balances.art).wmul(line.proportion).u128(); if (art < debt.min * (10**debt.dec)) art = balances.art; uint128 ink = (art == balances.art) ? balances.ink : uint256(balances.ink).wmul(line.proportion).u128();
  1. Now lets say debt (art) on this vault was amount 10, collateral (ink) was amount 9, debt.min * (10**debt.dec) was amount 2

  2. Below calculation occurs

uint128 art = uint256(balances.art).wmul(line.proportion).u128(); // which makes art = 10*10% =1 if (art < debt.min * (10**debt.dec)) art = balances.art; // since 1<2 so art=10 uint128 ink = (art == balances.art) // Since art is 10 so ink=9 ? balances.ink : uint256(balances.ink).wmul(line.proportion).u128();
  1. So full collateral and full debt are placed for Auction even though only 10% was meant for Auction. Even if it was lower than min debt, auction amount should have only increased upto the point where minimum debt limit is reached

Revise the calculation like below

uint128 art = uint256(balances.art).wmul(line.proportion).u128(); uint128 ink=0; if (art < debt.min * (10**debt.dec)) { art = debt.min * (10**debt.dec); (balances.ink<art) ? (ink=balances.ink) : (ink=art) } else { ink=uint256(balances.ink).wmul(line.proportion).u128(); }

#0 - HickupHH3

2022-07-18T14:11:37Z

debt.min * (10**debt.dec) was amount 2

Only way for this to happen is for the token's decimals to be 0, which is an edge case.

Anyway, the issue is invalid because it is intended for the full collateral to be offered if it is below the minimum debt amount, ie. vault proportion is to be disregarded: // We store the proportion of the vault to auction, which is the whole vault if the debt would be below dust.

#1 - alcueca

2022-07-21T11:06:13Z

The finding is valid, but it is a bit complicated.

The behaviour should be:

  1. If the part of the vault for auction is below dust, increase to dust.
  2. If the remaining part of the vault is below dust, increase to 100%.

#2 - PierrickGT

2022-08-03T16:33:11Z

This is the second most critical vulnerability found during the audit. This issue is less critical than #116 since the protocol would not take on bad debts but users may lose their entire collateral when only part of their collateral should have been put to auction.

Awards

39.3794 USDC - $39.38

Labels

bug
QA (Quality Assurance)

External Links

Zero address checks

Contract: https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L176

Issue: Check that auctioneer address is not 0. This mean the funds would be lost while paying the auctioneer cut once someone pay the debt

Recommendation: Add below check in auction function

require(to!=address(0), "Invalid address");

Add pause feature if under attack

Contract: https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol

Issue: If contract is under attack and Auctioned Vault interaction for buying collateral need to be stopped, then currently there is no way.

Recommendation: Add a pause modifier which allows Admin to stop interaction with Auctioned Vault function like payBase in case of emergency

Ignore pair on ongoing auction has no impact

Contract: https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L150

Issue: If setIgnoredPair function is called to ignore a pair on which a auction is already live then it has no impact on live auction

Recommendation: Display an error to Admin mentioning that pair is already running live auction in a vault. If still required then have a boolean param which can forcefully ignore this pair

#0 - alcueca

2022-07-22T14:42:35Z

One useful

Check non existing vault to save gas

Contract: https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L180

Issue: auction function will fail at later stage even if vault id provided by user does not exist. This waste gas

Recommendation: Add below check:

DataTypes.Vault memory vault = cauldron.vaults(vaultId); require(vault.owner!=address(0), "Vault not found");

maxBaseIn cannot be 0

Contract: https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L286

Issue: If maxBaseIn is provided 0 value while calling payBase function, it means user is paying for 0 debt which does not make sense and should be reverted immediately to prevent gas. Same applies for payFYToken function

Recommendation: Add below check

require(maxBaseIn!=0,"Incorrect value");
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