1
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
2
pragma solidity ^ 0.8.20 ;
3
3
4
+ import "forge-std/console2.sol " ;
4
5
import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol " ;
5
6
import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol " ;
6
7
import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol " ;
@@ -20,7 +21,7 @@ contract Quoter is IQuoter, ILockCallback {
20
21
using PathKeyLib for PathKey;
21
22
22
23
/// @dev cache used to check a safety condition in exact output swaps.
23
- uint256 private amountOutCached;
24
+ uint128 private amountOutCached;
24
25
25
26
// v4 Singleton contract
26
27
IPoolManager public immutable manager;
@@ -239,22 +240,23 @@ contract Quoter is IQuoter, ILockCallback {
239
240
uint32 [] memory initializedTicksLoadedList = new uint32 [](pathLength);
240
241
Currency prevCurrencyIn;
241
242
uint128 prevAmountIn;
243
+ uint128 curAmountOut;
242
244
243
245
for (uint256 i = pathLength; i > 0 ; i-- ) {
246
+ curAmountOut = i == pathLength ? params.exactAmount : prevAmountIn;
247
+ amountOutCached = curAmountOut;
248
+
244
249
(PoolKey memory poolKey , bool oneForZero ) = PathKeyLib.getPoolAndSwapDirection (
245
250
params.path[i - 1 ], i == pathLength ? params.exactCurrency : prevCurrencyIn
246
251
);
247
252
248
253
(, int24 tickBefore ,) = manager.getSlot0 (poolKey.toId ());
249
254
250
- (BalanceDelta curDeltas , uint160 sqrtPriceX96After , int24 tickAfter ) = _swap (
251
- poolKey,
252
- ! oneForZero,
253
- - int256 (int128 (i == pathLength ? params.exactAmount : prevAmountIn)),
254
- 0 ,
255
- params.path[i - 1 ].hookData
256
- );
255
+ (BalanceDelta curDeltas , uint160 sqrtPriceX96After , int24 tickAfter ) =
256
+ _swap (poolKey, ! oneForZero, - int256 (uint256 (curAmountOut)), 0 , params.path[i - 1 ].hookData);
257
257
258
+ // always clear because sqrtPriceLimitX96 is set to 0 always
259
+ delete amountOutCached;
258
260
(int128 deltaIn , int128 deltaOut ) =
259
261
! oneForZero ? (curDeltas.amount0 (), curDeltas.amount1 ()) : (curDeltas.amount1 (), curDeltas.amount0 ());
260
262
deltaAmounts[i - 1 ] += deltaIn;
@@ -304,7 +306,7 @@ contract Quoter is IQuoter, ILockCallback {
304
306
function _swap (
305
307
PoolKey memory poolKey ,
306
308
bool zeroForOne ,
307
- int256 amountSpecified ,
309
+ int256 amountSpecified , // exactInput = amountSpecified > 0
308
310
uint160 sqrtPriceLimitX96 ,
309
311
bytes memory hookData
310
312
) private returns (BalanceDelta deltas , uint160 sqrtPriceX96After , int24 tickAfter ) {
@@ -318,7 +320,7 @@ contract Quoter is IQuoter, ILockCallback {
318
320
hookData
319
321
);
320
322
// only exactOut case
321
- if (amountOutCached != 0 && amountOutCached != uint256 ( int256 ( - deltas.amount1 ()))) {
323
+ if (amountOutCached != 0 && amountOutCached != uint128 (zeroForOne ? - deltas.amount1 () : - deltas. amount0 ( ))) {
322
324
revert InsufficientAmountOut ();
323
325
}
324
326
(sqrtPriceX96After, tickAfter,) = manager.getSlot0 (poolKey.toId ());
0 commit comments