Platform: Code4rena
Start Date: 01/05/2024
Pot Size: $12,100 USDC
Total HM: 1
Participants: 47
Period: 7 days
Judge: Koolex
Id: 371
League: ETH
Rank: 20/47
Findings: 1
Award: $213.33
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: 0xnev
Also found by: 0x04bytes, 0xBugSlayer, 0xJoyBoy03, 0xSecuri, 0xrex, Bigsam, DMoore, Evo, Greed, Kirkeelee, Krace, Pechenite, Rhaydden, SBSecurity, Sajjad, TheFabled, Topmark, XDZIBECX, ZanyBonzy, _karanel, bbl4de, btk, d3e4, gumgumzum, nfmelendez, novamanbg, petarP1998, samuraii77, sandy, shaflow2, sldtyenj12, web3er, y4y, yovchev_yoan
213.3333 USDC - $213.33
A user that has locked just 1 wei of the allowed tokens can claim an arbitrary amount of the lpETH
token.
This is the _claim()
function:
function _claim(address _token, address _receiver, uint8 _percentage, Exchange _exchange, bytes calldata _data) internal returns (uint256 claimedAmount) { uint256 userStake = balances[msg.sender][_token]; if (userStake == 0) { revert NothingToClaim(); } if (_token == ETH) { claimedAmount = userStake.mulDiv(totalLpETH, totalSupply); balances[msg.sender][_token] = 0; lpETH.safeTransfer(_receiver, claimedAmount); } else { uint256 userClaim = userStake * _percentage / 100; _validateData(_token, userClaim, _exchange, _data); balances[msg.sender][_token] = userStake - userClaim; // At this point there should not be any ETH in the contract // Swap token to ETH _fillQuote(IERC20(_token), userClaim, _data); // Convert swapped ETH to lpETH (1 to 1 conversion) claimedAmount = address(this).balance; lpETH.deposit{value: claimedAmount}(_receiver); } emit Claimed(msg.sender, _token, claimedAmount); }
If a user has locked just 1 wei of any of the allowed tokens, then he can do the following:
claim()
function with the token he has locked for 1 weielse
statement as his token is not ETH
claimedAmount
variable is equal to address(this).balance
which he just increased as he sent Ether directly to the contractWhile the implementation of the lpETH
contract is unclear, such issue can definitely cause a lot of unexpected issues depending on the implementation of lpETH
and other contracts. Furthermore, that makes the event emission wrong and by the contest page in Code4rena, we can see that they are tracking different events on the backend, potentially causing other issues.
Manual Review
Change the _fillQuote()
function to return the boughtETHAmount
variable and use it as the claimedAmount
instead.
Other
#0 - c4-judge
2024-05-15T14:40:54Z
koolexcrypto marked the issue as duplicate of #6
#1 - c4-judge
2024-05-31T09:58:27Z
koolexcrypto marked the issue as duplicate of #33
#2 - c4-judge
2024-06-05T08:48:00Z
koolexcrypto marked the issue as partial-75
#3 - c4-judge
2024-06-05T09:55:53Z
koolexcrypto changed the severity to 3 (High Risk)
#4 - cholakovvv
2024-06-07T06:11:44Z
@koolexcrypto why this issue is marked as partial?
#5 - koolexcrypto
2024-06-10T15:56:45Z
Hi @cholakovvv
All issues that don't mention bypassing the locking duration will have partial credits. still evaluating the percentage
#6 - cholakovvv
2024-06-10T17:21:47Z
@koolexcrypto I believe this report clearly mentions that the user can deposit 1 wei and then call claim(). Since that function can only be called after the start claim date, it is clear what the person behind the report had in mind.
#7 - koolexcrypto
2024-06-10T20:25:13Z
The issue describes a scenario. but didn't clearly mentioned the impact of bypassing locking duration. This got 75% credit unlike others which will get less.
such issue can definitely cause a lot of unexpected issues depending on the implementation of lpETH and other contracts. Furthermore, that makes the event emission wrong and by the contest page in Code4rena, we can see that they are tracking different events on the backend, potentially causing other issues.