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: 28/47
Findings: 1
Award: $71.11
🌟 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
71.1111 USDC - $71.11
https://github.com/code-423n4/2024-05-loop/blob/0dc8467ccff27230e7c0530b619524cc8401e22a/src/PrelaunchPoints.sol#L249 https://github.com/code-423n4/2024-05-loop/blob/0dc8467ccff27230e7c0530b619524cc8401e22a/src/PrelaunchPoints.sol#L262
When claimedAmount
is calculated in the (_token == ETH)
branch, the amount of lpETH
received may be greater than the staked ETH
in case there was an accidental direct deposit of ETH
to the contract. The user making this transfer of ETH
rightfully losses it without a way to recover, the issue is that the ETH
can be considered to be lost as much as it would be when sent to a dummy address, as there is no way to recover it from the contract - you can only recover ERC20s or use the withdraw()
function as a user. The excess balance causes totalLpETH
to be greater than totalSupply
because of the following lines in convertAllETH
:
uint256 totalBalance = address(this).balance; lpETH.deposit{value: totalBalance}(address(this)); totalLpETH = lpETH.balanceOf(address(this));
Therefore, it increases the claimedAmount
for each user. This is causing the conversion rate between ETH
and lpETH
to not equal 1. Moreover, considering the (_token != ETH)
branch, a user can _fillQuote
with amount equal to userClaim
, however the claimedAmount
can be increased by simply sending ETH
directly to the contract right before the call to claim()
or claimAndStake()
functions. Again, this makes the conversion to change from 1:1, because ETH
sent directly to the contract is NOT accessible by anyone including the owner.
Both of these situations make the lpETH
inflationary as users essentially get more lpETH
for the same amount of real stake if they do what's explained above for both _claim()
function token branches.
To run a PoC proving how the received lpETH
is indeed increased when the user sends ETH
directly to the contract right before calling claim()
change the code in PrelaunchPoints0x.test.ts
to the code in this gist and run the test with yarn hardhat test ./test/PrelaunchPoints0x.test.ts
.
Manual Review, Hardhat
To mitigate this issue consider changing the approach from push to pull, meaning that in convertAllETH
the owner does not deposit all ETH
to the lpETH
contract. Thanks to this, totalSupply
and totalLpETH
variables can be removed and the user gets the appropriate amount of lpETH
based on their share of the contract's balance.
Token-Transfer
#0 - c4-judge
2024-05-15T14:16:12Z
koolexcrypto marked the issue as duplicate of #18
#1 - c4-judge
2024-06-03T09:03:32Z
koolexcrypto changed the severity to 3 (High Risk)
#2 - c4-judge
2024-06-05T07:29:36Z
koolexcrypto changed the severity to 2 (Med Risk)
#3 - c4-judge
2024-06-05T09:29:29Z
koolexcrypto marked the issue as partial-50
#4 - c4-judge
2024-06-05T09:41:00Z
koolexcrypto changed the severity to 3 (High Risk)
#5 - c4-judge
2024-06-05T09:41:19Z
koolexcrypto marked the issue as duplicate of #33
#6 - c4-judge
2024-06-11T07:24:06Z
koolexcrypto marked the issue as partial-25