Polynomial Protocol contest - kaden'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: 26/35

Findings: 1

Award: $175.24

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: peakbolt

Also found by: 0xRobocop, 0xbepresent, auditor0517, kaden

Labels

bug
3 (High Risk)
partial-50
duplicate-153

Awards

175.2447 USDC - $175.24

External Links

Lines of code

https://github.com/code-423n4/2023-03-polynomial/blob/aeecafc8aaceab1ebeb94117459946032ccdff1e/src/LiquidityPool.sol#L494-L521

Vulnerability details

Impact

Fees received by the LiquidityPool contract when a short position is opened are unaccounted for and end up permanently locked in the contract, incurring a loss to liquidity providers.

Proof of Concept

When opening and closing short positions, the LiquidityPool requires either a fee to be transferred in from the user account or withheld in the case that sUSD is being transferred from the contract to the user. Consider for example how fees must be transferred from the user in openLong:

// openLong() - LiquidityPool.sol:L441-444 uint256 fees = orderFee(int256(amount)); totalCost = tradeCost + fees; SUSD.safeTransferFrom(user, address(this), totalCost);

Since the contract is taking a fee, it's necessary to update the corresponding totalFunds state variable to reflect the collected fee:

// openLong() - LiquidityPool.sol:L453 totalFunds += feesCollected - externalFee;

In openShort, however, we deduct a fee from the amount being transferred to the user as expected:

// openShort() - LiquidityPool.sol:L505-508 uint256 fees = orderFee(-int256(amount)); totalCost = tradeCost - fees; SUSD.safeTransfer(user, totalCost);

But there is no corresponding update to totalFunds.

Since we can't withdraw beyond totalFunds (the following will underflow and revert):

// withdraw() - LiquidityPool.sol:255 totalFunds -= susdToReturn;

All fees collected in openShort are not accounted for and permanently locked in the contract. Since these fees would go to the liquidity providers, this is considered a loss of funds for users.

Include the necessary update to totalFunds in openShort:

totalFunds += feesCollected - externalFee;

#0 - c4-judge

2023-03-21T13:35:30Z

JustDravee marked the issue as duplicate of #153

#1 - JustDravee

2023-05-02T22:46:13Z

Partial for lack of coded POC on a high

#2 - c4-judge

2023-05-02T22:46:26Z

JustDravee marked the issue as partial-50

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