Closed howlbot-integration[bot] closed 3 months ago
koolexcrypto marked the issue as primary issue
Point calculation is done offchain and controlled via events that cannot be manipulated this way
Points are calculated off-chain based on Claimed events emitted, claimedAmount
is address(this).balance
, so the user won't get more points.
// Convert swapped ETH to lpETH (1 to 1 conversion)
claimedAmount = address(this).balance;
lpETH.deposit{value: claimedAmount}(_receiver);
}
emit Claimed(msg.sender, _token, claimedAmount);
koolexcrypto marked the issue as unsatisfactory: Invalid
Lines of code
https://github.com/code-423n4/2024-05-loop/blob/0dc8467ccff27230e7c0530b619524cc8401e22a/src/PrelaunchPoints.sol#L252-L262
Vulnerability details
Impact
Users can farm points without participating in the protocol.
Proof of Concept
When users that deposited LRTs call
claim()
, the function will route through 0x, convert their LRT tokens to ETH, send ETH to the contract, and swap lpETH to ETH at a 1:1 conversion rate.This means that users who deposited LRT will get lpETH back when
claim()
. However, there is a way that users can get back ETH and bypass the conversion to lpETH.The reason for doing so could be to farm points through
lock()
without participating in getting lpETH. Also, there may be instances where lpETH breaks the 1:1 peg to ETH because of market volatility or a manipulation in thetotalLpETH
variable, which results in users wanting ETH back and not lpETH.In 0x, there is a request for
feeRecipient
andfeeRecipientPercentage
.If the
feeRecipient
andfeeRecipientPercentage
is set, the percentage of buyToken will be sent to thefeeRecipient
. This means that the LRT will be converted to ETH, and the percentage of ETH will be sent to thefeeRecipient
. Note that the fee can be up to 0.99 (apparently 1.0 gets internal server error)If a user locks 1 rETH for example, and the exchange rate to ETH is 1.1:1, he can get back 1.1 ETH and not 1.1 lpETH.
Send this request to the CLI, get the API-KEY by creating an account on 0x. Note that this is selling 1 USDC for x USDT on polygon.
This should return the data:
When sent to Metamask, the
feeRecipient
will get 99% of thebuyToken
, which is USDT.Tools Used
Manual Review
Recommended Mitigation Steps
If this bypass is not intended, set the priceFeePercentage to zero and check zero value when validating the data.
Assessed type
Context