Caviar contest - adriro's results

A fully on-chain NFT AMM that allows you to trade every NFT in a collection.

General Information

Platform: Code4rena

Start Date: 12/12/2022

Pot Size: $36,500 USDC

Total HM: 8

Participants: 103

Period: 7 days

Judge: berndartmueller

Id: 193

League: ETH

Caviar

Findings Distribution

Researcher Performance

Rank: 62/103

Findings: 1

Award: $45.94

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

Awards

45.9386 USDC - $45.94

Labels

bug
2 (Med Risk)
satisfactory
duplicate-243

External Links

Lines of code

https://github.com/code-423n4/2022-12-caviar/blob/main/src/Pair.sol#L398-L400

Vulnerability details

The function buyQuote present in the Pair contract is used to calculate the amount of base tokens required to buy a given amount of fractional tokens.

https://github.com/code-423n4/2022-12-caviar/blob/main/src/Pair.sol#L398-L400

function buyQuote(uint256 outputAmount) public view returns (uint256) {
    return (outputAmount * 1000 * baseTokenReserves()) / ((fractionalTokenReserves() - outputAmount) * 997);
}

The integer division will round down the return value, while the correct behavior should be to round up in favor of the protocol.

Impact

The buyQuote function will round down the division, which means that the required amount of base tokens that the user needs to input to take a given amount of fractional tokens will be rounded down.

The result amount will then be rounded down in favor of the user calling the buy instead of favoring the LPs.

Proof of Concept

If the numerator outputAmount * 1000 * baseTokenReserves() isn't a multiple of the denominator (fractionalTokenReserves() - outputAmount) * 997, then the integer division will round the result down.

Following UniswapV2 getAmountIn implementation, a +1 can be added to the calculation to force the rounding to be up:

function buyQuote(uint256 outputAmount) public view returns (uint256) {
    return ((outputAmount * 1000 * baseTokenReserves()) / ((fractionalTokenReserves() - outputAmount) * 997)) + 1;
}

As a more technically correct alternative, it is also possible to use solmate's FixedPointMathLib.mulDivUp to calculate the buyQuote formula (this library is already used and imported in the project).

#0 - Shungy

2022-12-21T07:35:19Z

Seems valid.

#1 - c4-judge

2022-12-23T13:42:01Z

berndartmueller marked the issue as primary issue

#2 - c4-judge

2022-12-23T13:49:52Z

berndartmueller marked the issue as duplicate of #243

#3 - c4-judge

2023-01-10T09:43:19Z

berndartmueller 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