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
Rank: 95/103
Findings: 1
Award: $6.99
๐ Selected for report: 0
๐ Solo Findings: 0
๐ Selected for report: minhquanym
Also found by: 0x52, 0xDecorativePineapple, Apocalypto, BAHOZ, ElKu, Franfran, HE1M, Jeiwan, KingNFT, Koolex, SamGMK, Tointer, Tricko, UNCHAIN, __141345__, ak1, aviggiano, bytehat, carrotsmuggler, cccz, chaduke, cozzetti, dipp, eyexploit, fs0c, haku, hansfriese, hihen, immeas, izhelyazkov, koxuan, ladboy233, lumoswiz, rajatbeladiya, rjs, rvierdiiev, seyni, supernova, unforgiven, yixxas
6.9881 USDC - $6.99
The attack vector is the same as TOB-YEARN-003
, where users may not receive liquidity tokens in exchange for their baseTokenAmount
and fractionalTokenAmount
deposited if the total baseTokenAmount
has been manipulated through a large โdonationโ.
In the addQuote
function, the calculation of LP Tokens is as follows:
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); }
A malicious early user/first depositor of the Pair contract can deposit with wrap his/her NFT in the contract, receive 1e18 of fractional tokens in return, and then deposit the 1e18 of fractional tokens and 1e18
of baseToken
to the contract. Since they are the first depositor, they will receive 1e18
of LP tokens.
Then, the attacker can send 1000e18
of baseTokens tokens to the contract, thereby inflating the price of the LP tokens. As a result, the next user who tries to add liquidity to the pool will receive 0 LP tokens, unless they set the minimum amount of LP tokens to mint. This causes the legitimate user to lose a significant portion of the amount deposited when trying to add liquidity to the pair.
Manual Code Review
Uniswapv2
pair implemented the following measures to mitigate this issue:
MINIMUM_LIQUIDITY
tokens to the zero address.#0 - Shungy
2022-12-20T06:04:05Z
Seems technically valid, but of lower severity. I submitted this as QA: https://github.com/code-423n4/2022-12-caviar-findings/blob/main/data/shung-Q.md#low-6-initial-1000-liquidity-is-not-burned
Then, the attacker can send 1000e18 of baseTokens tokens to the contract, thereby inflating the price of the LP tokens. As a result, the next user who tries to add liquidity to the pool will receive 0 LP tokens, unless they set the minimum amount of LP tokens to mint. This causes the legitimate user to lose a significant portion of the amount deposited when trying to add liquidity to the pair.
So this hinges on user not setting proper slippage, hence it is dependent on user mistake. It has been more or less established that these are not Medium risk: https://github.com/code-423n4/org/issues/53
Users can also rebalance the pair by wrapping and dumping their fractional shares, making the first depositor lose their baseTokens, so there is also no sense in this attack. And the minting is not broken permanently.
#1 - c4-judge
2022-12-20T14:36:21Z
berndartmueller marked the issue as duplicate of #442
#2 - c4-judge
2023-01-10T09:15:31Z
berndartmueller changed the severity to 3 (High Risk)
#3 - c4-judge
2023-01-10T09:15:36Z
berndartmueller marked the issue as satisfactory