Polynomial Protocol contest - Josiah's results

The DeFi Derivatives Powerhouse.

General Information

Platform: Code4rena

Start Date: 13/03/2023

Pot Size: $72,500 USDC

Total HM: 33

Participants: 35

Period: 7 days

Judge: Dravee

Total Solo HM: 16

Id: 222

League: ETH

Polynomial Protocol

Findings Distribution

Researcher Performance

Rank: 11/35

Findings: 1

Award: $1,201.95

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: RaymondFam

Also found by: Josiah

Labels

bug
3 (High Risk)
satisfactory
upgraded by judge
duplicate-70

Awards

1201.9527 USDC - $1,201.95

External Links

Lines of code

https://github.com/code-423n4/2023-03-polynomial/blob/main/src/ShortCollateral.sol#L235-L239

Vulnerability details

Impact

A specific position can be liquidated if canLiquidate() returns true. However, the function logic of maxLiquidatableDebt() is going to make it fully liquidatable even if safetyRatio == 1e18.

Proof of Concept

Let's assume the following setup:

collRatio = 1.5e18 liqRatio = 1.2e18

According to the code logic involved, a position is deemed one half liquidatable the moment its collateral ratio is equal to 1.2e18.

Let's assume:

liqBonus = 0.55e17 (5.5 %)

Following the first round of liquidation, the position will have its collateral ratio turn to (1.2 * 0.5 * 0.945) / 0.5) * 1e18 = 1.134e18, which is immediately liquidatable again.

The position will in fact be fully liquidatable this time because 1.134e18 is less than 1.2e18 * 0.95 = 1.14e18.

ShortCollateral.sol#L230-L239

function maxLiquidatableDebt(uint256 positionId) public view override returns (uint256 maxDebt) { [... SNIPPED ...] uint256 safetyRatioNumerator = position.collateralAmount.mulWadDown(collateralPrice); uint256 safetyRatioDenominator = position.shortAmount.mulWadDown(markPrice); safetyRatioDenominator = safetyRatioDenominator.mulWadDown(collateral.liqRatio); uint256 safetyRatio = safetyRatioNumerator.divWadDown(safetyRatioDenominator); if (safetyRatio > 1e18) return maxDebt; maxDebt = position.shortAmount / 2; if (safetyRatio < WIPEOUT_CUTOFF) maxDebt = position.shortAmount; }

It is recommended the code logic of maxLiquidatableDebt() be reasonably revised so that a normal liquidation will only make the underwater position become healthy again rather than worsening the collateral ratio.

#0 - c4-judge

2023-03-23T11:14:14Z

JustDravee marked the issue as duplicate of #146

#1 - JustDravee

2023-05-03T01:03:37Z

Smallest partial credits due to low quality of submission compared to any other and blurry mitigation (also blurry explanation, this one is shorter https://github.com/code-423n4/2023-03-polynomial-findings/issues/102 but a lot clearer).

#2 - c4-judge

2023-05-03T01:04:22Z

JustDravee marked the issue as partial-25

#3 - c4-judge

2023-05-09T16:11:30Z

JustDravee marked the issue as not a duplicate

#4 - c4-judge

2023-05-09T16:12:38Z

JustDravee marked the issue as duplicate of #70

#5 - c4-judge

2023-05-09T16:12:42Z

JustDravee marked the issue as partial-25

#6 - c4-judge

2023-05-09T16:15:20Z

JustDravee marked the issue as full credit

#7 - c4-judge

2023-05-15T23:47:14Z

JustDravee marked the issue as satisfactory

#8 - c4-judge

2023-05-16T00:09:07Z

JustDravee 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