Closed howlbot-integration[bot] closed 4 months ago
This is indeed a problem on the test implementations, however TransformERC20
always give ETH as an outputToken
and Uniswap_V3
always give WETH as outputToken
so the validations in the contract are correct and not a vulnerability in the contract itself
From 0x => UniswapV3Feature contract, encodedPath expects the last token to be WETH.
/// @dev Sell a token for ETH directly against uniswap v3.
/// @param encodedPath Uniswap-encoded path, where the last token is WETH.
/// @param sellAmount amount of the first token in the path to sell.
/// @param minBuyAmount Minimum amount of ETH to buy.
/// @param recipient The recipient of the bought tokens. Can be zero for sender.
/// @return buyAmount Amount of ETH bought.
function sellTokenForEthToUniswapV3(
bytes memory encodedPath,
uint256 sellAmount,
uint256 minBuyAmount,
address payable recipient
) public override returns (uint256 buyAmount) {
UniswapV3Feature:sellTokenForEthToUniswapV3
In this case, this validation is correct.
if (outputToken != address(WETH)) {
revert WrongDataTokens(inputToken, outputToken);
}
koolexcrypto marked the issue as primary issue
koolexcrypto marked the issue as unsatisfactory: Invalid
Lines of code
https://github.com/code-423n4/2024-05-loop/blob/main/src/PrelaunchPoints.sol#L412-L413 https://github.com/code-423n4/2024-05-loop/blob/main/src/PrelaunchPoints.sol#L448-L464
Vulnerability details
Severity Medium (Likelihood: High Impact: Low)
Description
claim / claimAndStake
doesn't seem to be working as expected. When non-ETH are claimed and Uniswap_V3 is used by 0x API,_decodeUniswapV3Data
will be used to decode the 0x response, but it doesn't decode properly and willalways revert
which seems to warrant Medium severity (but border line, as change in the loop's back-end could resolve the issue without having to change the smart contract - see recommendation section).Impact
claim / claimAndStake
function callwill revert
when 0x API usesUniswap_V3
todo the swap from LRT token to ETH.PoC
Use the following in Remix, which is the decoding code used by the smart contract.
1. Create a smart contract in Remix with the following code
2. Hit the 0x API to simulate a swap of 1 ether from pufETH to ETH.
curl --location --request GET 'https://api.0x.org/swap/v1/quote?buyToken=0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee&sellToken=0xD9A442856C234a39a81a089C06451EBAa4306a72&sellAmount=1000000000000000000' --header '0x-api-key: 89798b75-e786-4a46-bd22-d6cf8b8dd3d5'
3. Extract the data, in run it against both function in Remix created in step 1.
That returned the following response at the time of writing. We can see that
quote.orders[0].source == Uniswap_V3
._decodeUniswapV3Data
result:_decodeTransformERC20Data
result:Result
The assumption is that
_decodeUniswapV3Data
would be called in _validateData in such case based on the following logic seen inPrelaunchPoints0x.test.ts
, so when the user would want toclaim
throught the loop's front-end, the loop's back-end would provide_exchange == 0
based on the test currently written.Consequently this scenario will always revert, and will be occuring very often as 0x API seems to select almost always Uniswap_V3 for the swap. Somehow, seems like
_decodeTransformERC20Data
should always be called, but I didn't dig the reasoning further. I guess an easy way for the team to fix it (even without changing the smart contract) would be to force_exchange == 1
in the loop's back-end even for Uniswap_V3.Tools Used
Manual inspection, Remix, Foundry
Recommended Mitigation Steps
Use
_decodeTransformERC20Data
even for Uniswap_V3. In my humble opinion I think this report still warrant a Medium severity for the fact of having exposed the problematic situation in details, even if this can probably be resolved without changing the smart contract.Assessed type
Error