Caviar contest - supernova'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: 93/103

Findings: 1

Award: $6.99

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

6.9881 USDC - $6.99

Labels

bug
3 (High Risk)
satisfactory
duplicate-442

External Links

Lines of code

https://github.com/code-423n4/2022-12-caviar/blob/0212f9dc3b6a418803dbfacda0e340e059b8aae2/src/Pair.sol#L417-L428 https://github.com/code-423n4/2022-12-caviar/blob/0212f9dc3b6a418803dbfacda0e340e059b8aae2/src/Pair.sol#L63-L99

Vulnerability details

Impact

The first LP can impact the pricing formula used in addQuote function . It will make the pricing of baseTokenShare and fractionalTokenShare favourable to the second LP.

Proof of Concept

Example:

The add function of Pair takes baseTokenAmount and fractionalTokenAmount as parameter. The first LP front runs the Pair and sets baseTokenAmount = 1; fractionalTokenAmount =1;

Now see the addQuote function

function addQuote(uint256 baseTokenAmount, uint256 fractionalTokenAmount) public view returns (uint256) {
        uint256 lpTokenSupply = lpToken.totalSupply();
        if (lpTokenSupply > 0) {
            // calculate amount of lp tokens as a fraction of existing reserves
            uint256 baseTokenShare = (baseTokenAmount * lpTokenSupply) / baseTokenReserves();
            uint256 fractionalTokenShare = (fractionalTokenAmount * lpTokenSupply) / fractionalTokenReserves();
            return Math.min(baseTokenShare, fractionalTokenShare);
        } else {
            // if there is no liquidity then init
            return Math.sqrt(baseTokenAmount * fractionalTokenAmount);
        }
    }

Here, as lpTokenSupply ==0 , it will return 1 ; Now lpTokenSupply will return 1 for second LP.

Second LP calls the add function again , In the addQuote function ,

baseTokenShare will be equal to the baseTokenAmount and similarly , fractionalTokenShare = fractionalTokenAmount

This phenomenon , ignores the other 2 variables in the formula( lpTokenSupply and baseTokenReserves ,fractionalTokenReserves ) , as they are 1 in value . Thus, it will be more advantageous for the second LP to mint the tokens, which will put , the rest of the future LPs at a disadvantage.

Tools Used

Manual

  • Mint some initial LP tokens to the Zero address in the constructor .
  • In the addQuote function, when lpTokenSupply ==0 , enforce a require statement , to make the user deposit a minimum amount of baseTokenAmount that will make the calculation more robust to manipulation.

#0 - c4-judge

2022-12-20T14:35:00Z

berndartmueller marked the issue as duplicate of #442

#1 - c4-judge

2023-01-10T09:13:57Z

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