Skip to content

Latest commit

 

History

History
38 lines (26 loc) · 2.53 KB

M-04.md

File metadata and controls

38 lines (26 loc) · 2.53 KB

Type casting can potentially change semantics of swap operation

A type casting while executing the token swap can potentially change the semantics of the swap action in the UniswapV3 pool.

Impact

While executing the swap, the implementation of the JBXBuybackDelegate needs to cast the amount parameter from uint256 to int256, as the swap() function from UniswapV3 takes an int256 as the type of the amount to be swapped.

https://github.com/code-423n4/2023-05-juicebox/blob/main/juice-buyback/contracts/JBXBuybackDelegate.sol#L263-L275

263:         try pool.swap({
264:             recipient: address(this),
265:             zeroForOne: !_projectTokenIsZero,
266:             amountSpecified: int256(_data.amount.value),
267:             sqrtPriceLimitX96: _projectTokenIsZero ? TickMath.MAX_SQRT_RATIO - 1 : TickMath.MIN_SQRT_RATIO + 1,
268:             data: abi.encode(_minimumReceivedFromSwap)
269:         }) returns (int256 amount0, int256 amount1) {
270:             // Swap succeded, take note of the amount of projectToken received (negative as it is an exact input)
271:             _amountReceived = uint256(-(_projectTokenIsZero ? amount0 : amount1));
272:         } catch {
273:             // implies _amountReceived = 0 -> will later mint when back in didPay
274:             return _amountReceived;
275:         }

Line 266 casts the variable _data.amount.value to int256 to pass it as the amountSpecified member of swap parameters. This casting can potentially turn the value into a negative one. If the leading bit is 1 (i.e. any value greater or equal to 0x8000000000000000000000000000000000000000000000000000000000000000), then the resulting amount will be interpreted as a negative value.

This creates a potential conflict with the swap() function of UniswapV3, which interprets negative values differently:

/// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)

This means that if the value is negative, Uniswap will interpret the value as an "exact output", changing the semantics of the swap operation.

Recommendation

Use a library to implement the type casting from uint256 to int256, such as SafeCast.toInt256() from the OpenZeppelin contracts library, which correctly checks that the given value does not overflow into a negative one while being converted.