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: 43/103
Findings: 2
Award: $86.20
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Jeiwan
Also found by: 0xxm, 9svR6w, BAHOZ, Bobface, CRYP70, Chom, HE1M, Junnon, RaymondFam, UNCHAIN, __141345__, bytehat, carlitox477, caventa, cccz, chaduke, hansfriese, hihen, koxuan, mauricio1802, minhquanym, minhtrng, nicobevi, obront, shung, unforgiven, wait
40.2564 USDC - $40.26
https://github.com/code-423n4/2022-12-caviar/blob/0212f9dc3b6a418803dbfacda0e340e059b8aae2/src/Pair.sol#L85 https://github.com/code-423n4/2022-12-caviar/blob/0212f9dc3b6a418803dbfacda0e340e059b8aae2/src/Pair.sol#L93-L96
Users calling Pair.sol#add() will cost more tokens than needed. It also makes Pair.sol#add() and Pair.sol#nftAdd() vulnerable to sandwich attacks.
It is incorrect that the token amounts transferred in function Pair.sol#add is derived from input parameters (baseTokenAmount
, fractionalTokenAmount
) rather than recalculate the amounts from the lpTokenAmount
to mint:
function add(uint256 baseTokenAmount, uint256 fractionalTokenAmount, uint256 minLpTokenAmount) returns (uint256 lpTokenAmount) { // -- omit -- lpTokenAmount = addQuote(baseTokenAmount, fractionalTokenAmount); // -- omit -- _transferFrom(msg.sender, address(this), fractionalTokenAmount); // -- omit -- lpToken.mint(msg.sender, lpTokenAmount); // -- omit -- if (baseToken != address(0)) { ERC20(baseToken).safeTransferFrom(msg.sender, address(this), baseTokenAmount); } // -- omit -- }
For example, if a pair contains 10 ETH and 1000 FT(fractional token), the following three users will get the same amount of lp tokens:
All of them will get the same number of lp tokens, which means user2 costs 100 FT more and user3 costs 10 ETH more.
Manual
transferFrom
based on the lpTokenAmount
transferFrom
based on the lpTokenAmount
lpTokenAmount
and return the excess ETH to user.#0 - Shungy
2022-12-21T19:48:04Z
Dup #90
#1 - c4-judge
2022-12-28T11:04:25Z
berndartmueller marked the issue as duplicate of #376
#2 - c4-judge
2023-01-10T09:01:33Z
berndartmueller marked the issue as satisfactory
🌟 Selected for report: Zarf
Also found by: 0xDave, Apocalypto, CRYP70, Franfran, Jeiwan, UNCHAIN, adriro, bytehat, chaduke, hansfriese, hihen, kiki_dev, koxuan, minhtrng, rajatbeladiya, unforgiven, wait, yixxas
45.9386 USDC - $45.94
Users might sell NFT or fractional tokens for 0 base token.
The return value of function Pair.sol#sellQuote may be 0.
function sellQuote(uint256 inputAmount) public view returns (uint256) { uint256 inputAmountWithFee = inputAmount * 997; return (inputAmountWithFee * baseTokenReserves()) / ((fractionalTokenReserves() * 1000) + inputAmountWithFee); }
This will result in the user calling Pair.sol#sell
lose the inputAmount
of fractional tokens, because 0 base token will send to the user if minOutputAmount = 0
.
Manual
I recommend to revert the Pair.sol#sell
if outputAmount is 0
#0 - Shungy
2022-12-21T08:08:38Z
Technically the dup of #424 . However the actual issue is described in #436
#1 - c4-judge
2022-12-23T13:51:13Z
berndartmueller marked the issue as duplicate of #243
#2 - c4-judge
2023-01-10T09:44:10Z
berndartmueller marked the issue as satisfactory