Skip to content

Commit

Permalink
update ticks counter
Browse files Browse the repository at this point in the history
  • Loading branch information
ConjunctiveNormalForm committed Dec 15, 2023
1 parent 7dc6b82 commit 588ffde
Show file tree
Hide file tree
Showing 35 changed files with 83 additions and 77 deletions.
2 changes: 1 addition & 1 deletion .forge-snapshots/FullOracleObserve0After5Seconds.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2771
2687
2 changes: 1 addition & 1 deletion .forge-snapshots/FullOracleObserve200By13.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
23377
22933
2 changes: 1 addition & 1 deletion .forge-snapshots/FullOracleObserve200By13Plus5.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
23624
23180
2 changes: 1 addition & 1 deletion .forge-snapshots/FullOracleObserve5After5Seconds.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2798
2738
2 changes: 1 addition & 1 deletion .forge-snapshots/FullOracleObserveOldest.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
22396
21892
2 changes: 1 addition & 1 deletion .forge-snapshots/FullOracleObserveOldestAfter5Seconds.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
22695
22191
2 changes: 1 addition & 1 deletion .forge-snapshots/FullOracleObserveZero.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2130
2070
2 changes: 1 addition & 1 deletion .forge-snapshots/FullRangeAddInitialLiquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
410761
407968
2 changes: 1 addition & 1 deletion .forge-snapshots/FullRangeAddLiquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
204683
201962
2 changes: 1 addition & 1 deletion .forge-snapshots/FullRangeFirstSwap.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
156432
153306
2 changes: 1 addition & 1 deletion .forge-snapshots/FullRangeInitialize.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
897565
1112212
2 changes: 1 addition & 1 deletion .forge-snapshots/FullRangeRemoveLiquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
200057
197519
2 changes: 1 addition & 1 deletion .forge-snapshots/FullRangeRemoveLiquidityAndRebalance.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
386095
379147
2 changes: 1 addition & 1 deletion .forge-snapshots/FullRangeSecondSwap.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
114700
111940
2 changes: 1 addition & 1 deletion .forge-snapshots/FullRangeSwap.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
154641
151523
2 changes: 1 addition & 1 deletion .forge-snapshots/OracleGrow10Slots.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
254711
254660
2 changes: 1 addition & 1 deletion .forge-snapshots/OracleGrow10SlotsCardinalityGreater.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
245393
245360
2 changes: 1 addition & 1 deletion .forge-snapshots/OracleGrow1Slot.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
54893
54869
2 changes: 1 addition & 1 deletion .forge-snapshots/OracleGrow1SlotCardinalityGreater.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
45575
45569
2 changes: 1 addition & 1 deletion .forge-snapshots/OracleInitialize.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
72361
72316
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6618
6492
2 changes: 1 addition & 1 deletion .forge-snapshots/OracleObserveCurrentTime.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2130
2070
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2130
2070
2 changes: 1 addition & 1 deletion .forge-snapshots/OracleObserveLast20Seconds.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
88543
86878
2 changes: 1 addition & 1 deletion .forge-snapshots/OracleObserveLatestEqual.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2130
2070
2 changes: 1 addition & 1 deletion .forge-snapshots/OracleObserveLatestTransform.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2771
2687
2 changes: 1 addition & 1 deletion .forge-snapshots/OracleObserveMiddle.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6807
6684
2 changes: 1 addition & 1 deletion .forge-snapshots/OracleObserveOldest.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6319
6193
2 changes: 1 addition & 1 deletion .forge-snapshots/OracleObserveSinceMostRecent.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3466
3382
2 changes: 1 addition & 1 deletion .forge-snapshots/TWAMMSubmitOrder.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
146158
145648
5 changes: 3 additions & 2 deletions contracts/interfaces/IQuoter.sol
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.20;

import {PoolKey} from "@uniswap/v4-core/contracts/types/PoolKey.sol";
import {Currency} from "@uniswap/v4-core/contracts/types/Currency.sol";
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
import {Currency} from "@uniswap/v4-core/src/types/Currency.sol";
import {PathKey} from "../libraries/PathKey.sol";

/// @title Quoter Interface
Expand All @@ -12,6 +12,7 @@ import {PathKey} from "../libraries/PathKey.sol";
/// to compute the result. They are also not gas efficient and should not be called on-chain.
interface IQuoter {
error InvalidLockAcquiredSender();
error InvalidLockCaller();
error InvalidQuoteBatchParams();
error LockFailure();
error NotSelf();
Expand Down
39 changes: 21 additions & 18 deletions contracts/lens/Quoter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
pragma solidity ^0.8.20;

import "forge-std/console2.sol";
import {Hooks} from "@uniswap/v4-core/contracts/libraries/Hooks.sol";
import {TickMath} from "@uniswap/v4-core/contracts/libraries/TickMath.sol";
import {IHooks} from "@uniswap/v4-core/contracts/interfaces/IHooks.sol";
import {ILockCallback} from "@uniswap/v4-core/contracts/interfaces/callback/ILockCallback.sol";
import {IPoolManager} from "@uniswap/v4-core/contracts/interfaces/IPoolManager.sol";
import {BalanceDelta} from "@uniswap/v4-core/contracts/types/BalanceDelta.sol";
import {Currency} from "@uniswap/v4-core/contracts/types/Currency.sol";
import {PoolKey} from "@uniswap/v4-core/contracts/types/PoolKey.sol";
import {PoolIdLibrary} from "@uniswap/v4-core/contracts/types/PoolId.sol";
import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol";
import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol";
import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol";
import {ILockCallback} from "@uniswap/v4-core/src/interfaces/callback/ILockCallback.sol";
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol";
import {Currency} from "@uniswap/v4-core/src/types/Currency.sol";
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
import {PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol";
import {IQuoter} from "../interfaces/IQuoter.sol";
import {PoolTicksCounter} from "../libraries/PoolTicksCounter.sol";
import {PathKeyLib} from "../libraries/PathKey.sol";
Expand Down Expand Up @@ -51,7 +51,7 @@ contract Quoter is IQuoter, ILockCallback {
override
returns (int128[] memory deltaAmounts, uint160 sqrtPriceX96After, uint32 initializedTicksLoaded)
{
try manager.lock(abi.encodeWithSelector(this._quoteExactInputSingle.selector, params)) {}
try manager.lock(address(this), abi.encodeWithSelector(this._quoteExactInputSingle.selector, params)) {}
catch (bytes memory reason) {
return _handleRevertSingle(reason, params.poolKey);
}
Expand All @@ -66,7 +66,7 @@ contract Quoter is IQuoter, ILockCallback {
uint32[] memory initializedTicksLoadedList
)
{
try manager.lock(abi.encodeWithSelector(this._quoteExactInput.selector, params)) {}
try manager.lock(address(this), abi.encodeWithSelector(this._quoteExactInput.selector, params)) {}
catch (bytes memory reason) {
return _handleRevert(reason);
}
Expand All @@ -80,7 +80,7 @@ contract Quoter is IQuoter, ILockCallback {
{
if (params.sqrtPriceLimitX96 == 0) amountOutCached = params.amountOut;

try manager.lock(abi.encodeWithSelector(this._quoteExactOutputSingle.selector, params)) {}
try manager.lock(address(this), abi.encodeWithSelector(this._quoteExactOutputSingle.selector, params)) {}
catch (bytes memory reason) {
if (params.sqrtPriceLimitX96 == 0) delete amountOutCached;
return _handleRevertSingle(reason, params.poolKey);
Expand All @@ -97,17 +97,20 @@ contract Quoter is IQuoter, ILockCallback {
uint32[] memory initializedTicksLoadedList
)
{
try manager.lock(abi.encodeWithSelector(this._quoteExactOutput.selector, params)) {}
try manager.lock(address(this), abi.encodeWithSelector(this._quoteExactOutput.selector, params)) {}
catch (bytes memory reason) {
return _handleRevert(reason);
}
}

/// @inheritdoc ILockCallback
function lockAcquired(bytes calldata data) external returns (bytes memory) {
function lockAcquired(address lockCaller, bytes calldata data) external returns (bytes memory) {
if (msg.sender != address(manager)) {
revert InvalidLockAcquiredSender();
}
if (lockCaller != address(this)) {
revert InvalidLockCaller();
}

(bool success, bytes memory returnData) = address(this).call(data);
if (success) return returnData;
Expand Down Expand Up @@ -149,7 +152,7 @@ contract Quoter is IQuoter, ILockCallback {
int24 tickAfter;
BalanceDelta deltas;
deltaAmounts = new int128[](2);
(, tickBefore,,) = manager.getSlot0(poolKey.toId());
(, tickBefore,) = manager.getSlot0(poolKey.toId());
reason = validateRevertReason(reason);
(deltas, sqrtPriceX96After, tickAfter) = abi.decode(reason, (BalanceDelta, uint160, int24));
deltaAmounts[0] = deltas.amount0();
Expand Down Expand Up @@ -186,7 +189,7 @@ contract Quoter is IQuoter, ILockCallback {
for (uint256 i = 0; i < pathLength; i++) {
(PoolKey memory poolKey, bool zeroForOne) =
PathKeyLib.getPoolAndSwapDirection(params.path[i], i == 0 ? params.currencyIn : prevCurrencyOut);
(, int24 tickBefore,,) = manager.getSlot0(poolKey.toId());
(, int24 tickBefore,) = manager.getSlot0(poolKey.toId());

(BalanceDelta curDeltas, uint160 sqrtPriceX96After, int24 tickAfter) = _swap(
poolKey,
Expand Down Expand Up @@ -243,7 +246,7 @@ contract Quoter is IQuoter, ILockCallback {
params.path[i - 1], i == pathLength ? params.currencyOut : prevCurrencyIn
);

(, int24 tickBefore,,) = manager.getSlot0(poolKey.toId());
(, int24 tickBefore,) = manager.getSlot0(poolKey.toId());

(BalanceDelta curDeltas, uint160 sqrtPriceX96After, int24 tickAfter) = _swap(
poolKey,
Expand Down Expand Up @@ -306,7 +309,7 @@ contract Quoter is IQuoter, ILockCallback {
}),
hookData
);
(sqrtPriceX96After, tickAfter,,) = manager.getSlot0(poolKey.toId());
(sqrtPriceX96After, tickAfter,) = manager.getSlot0(poolKey.toId());
}

/// @dev return either the sqrtPriceLimit from user input, or the max/min value possible depending on trade direction
Expand Down
6 changes: 3 additions & 3 deletions contracts/libraries/PathKey.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

pragma solidity ^0.8.20;

import {Currency} from "@uniswap/v4-core/contracts/types/Currency.sol";
import {IHooks} from "@uniswap/v4-core/contracts/interfaces/IHooks.sol";
import {PoolKey} from "@uniswap/v4-core/contracts/types/PoolKey.sol";
import {Currency} from "@uniswap/v4-core/src/types/Currency.sol";
import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol";
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";

struct PathKey {
Currency intermediateCurrency;
Expand Down
15 changes: 9 additions & 6 deletions contracts/libraries/PoolTicksCounter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
pragma solidity >=0.8.20;

import {PoolGetters} from "./PoolGetters.sol";
import {IPoolManager} from "@uniswap/v4-core/contracts/interfaces/IPoolManager.sol";
import {PoolKey} from "@uniswap/v4-core/contracts/types/PoolKey.sol";
import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/contracts/types/PoolId.sol";
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol";

library PoolTicksCounter {
using PoolIdLibrary for PoolKey;
Expand Down Expand Up @@ -37,13 +37,15 @@ library PoolTicksCounter {
// If the initializable tick after the swap is initialized, our original tickAfter is a
// multiple of tick spacing, and we are swapping downwards we know that tickAfter is initialized
// and we shouldn't count it.
uint256 bmAfter = PoolGetters.getTickBitmapAtWord(self, key.toId(), wordPosAfter);
uint256 bmAfter = self.getPoolBitmapInfo(key.toId(), wordPosAfter);
//uint256 bmAfter = PoolGetters.getTickBitmapAtWord(self, key.toId(), wordPosAfter);
tickAfterInitialized =
((bmAfter & (1 << bitPosAfter)) > 0) && ((tickAfter % key.tickSpacing) == 0) && (tickBefore > tickAfter);

// In the case where tickBefore is initialized, we only want to count it if we are swapping upwards.
// Use the same logic as above to decide whether we should count tickBefore or not.
uint256 bmBefore = PoolGetters.getTickBitmapAtWord(self, key.toId(), wordPos);
uint256 bmBefore = self.getPoolBitmapInfo(key.toId(), wordPos);
//uint256 bmBefore = PoolGetters.getTickBitmapAtWord(self, key.toId(), wordPos);
tickBeforeInitialized =
((bmBefore & (1 << bitPos)) > 0) && ((tickBefore % key.tickSpacing) == 0) && (tickBefore < tickAfter);

Expand All @@ -70,7 +72,8 @@ library PoolTicksCounter {
mask = mask & (type(uint256).max >> (255 - bitPosHigher));
}

uint256 bmLower = PoolGetters.getTickBitmapAtWord(self, key.toId(), wordPosLower);
//uint256 bmLower = PoolGetters.getTickBitmapAtWord(self, key.toId(), wordPosLower);
uint256 bmLower = self.getPoolBitmapInfo(key.toId(), wordPosLower);
uint256 masked = bmLower & mask;
initializedTicksLoaded += countOneBits(masked);
wordPosLower++;
Expand Down
35 changes: 17 additions & 18 deletions test/Quoter.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ import {IQuoter} from "../contracts/interfaces/IQuoter.sol";
import {Quoter} from "../contracts/lens/Quoter.sol";
import {LiquidityAmounts} from "../contracts/libraries/LiquidityAmounts.sol";
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
import {BalanceDelta} from "@uniswap/v4-core/contracts/types/BalanceDelta.sol";
import {SafeCast} from "@uniswap/v4-core/contracts/libraries/SafeCast.sol";
import {Deployers} from "@uniswap/v4-core/test/foundry-tests/utils/Deployers.sol";
import {IHooks} from "@uniswap/v4-core/contracts/interfaces/IHooks.sol";
import {PoolModifyPositionTest} from "@uniswap/v4-core/contracts/test/PoolModifyPositionTest.sol";
import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/contracts/types/PoolId.sol";
import {PoolKey} from "@uniswap/v4-core/contracts/types/PoolKey.sol";
import {PoolManager} from "@uniswap/v4-core/contracts/PoolManager.sol";
import {IPoolManager} from "@uniswap/v4-core/contracts/interfaces/IPoolManager.sol";
import {Currency, CurrencyLibrary} from "@uniswap/v4-core/contracts/types/Currency.sol";
import {TickMath} from "@uniswap/v4-core/contracts/libraries/TickMath.sol";
import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol";
import {SafeCast} from "@uniswap/v4-core/src/libraries/SafeCast.sol";
import {Deployers} from "@uniswap/v4-core/test/utils/Deployers.sol";
import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol";
import {PoolModifyPositionTest} from "@uniswap/v4-core/src/test/PoolModifyPositionTest.sol";
import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol";
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
import {PoolManager} from "@uniswap/v4-core/src/PoolManager.sol";
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import {Currency, CurrencyLibrary} from "@uniswap/v4-core/src/types/Currency.sol";
import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol";

contract QuoterTest is Test, Deployers {
using SafeCast for *;
Expand All @@ -36,7 +36,6 @@ contract QuoterTest is Test, Deployers {

Quoter quoter;

PoolManager manager;
PoolModifyPositionTest positionManager;

MockERC20 token0;
Expand All @@ -50,7 +49,7 @@ contract QuoterTest is Test, Deployers {
MockERC20[] tokenPath;

function setUp() public {
manager = new PoolManager(CONTROLLER_GAS_LIMIT);
deployFreshManagerAndRouters();
quoter = new Quoter(address(manager));
positionManager = new PoolModifyPositionTest(manager);

Expand Down Expand Up @@ -120,7 +119,7 @@ contract QuoterTest is Test, Deployers {
function testQuoter_callLockAcquired_reverts() public {
vm.expectRevert(IQuoter.InvalidLockAcquiredSender.selector);
vm.prank(address(manager));
quoter.lockAcquired(abi.encodeWithSelector(quoter.lockAcquired.selector, "0x"));
quoter.lockAcquired(address(this), abi.encodeWithSelector(quoter.lockAcquired.selector, "0x"));
}

function testQuoter_quoteExactInput_0to2_2TicksLoaded() public {
Expand Down Expand Up @@ -539,7 +538,7 @@ contract QuoterTest is Test, Deployers {
}

function setupPool(PoolKey memory poolKey) internal {
manager.initialize(poolKey, SQRT_RATIO_1_1, ZERO_BYTES);
initializeRouter.initialize(poolKey, SQRT_RATIO_1_1, ZERO_BYTES);
MockERC20(Currency.unwrap(poolKey.currency0)).approve(address(positionManager), type(uint256).max);
MockERC20(Currency.unwrap(poolKey.currency1)).approve(address(positionManager), type(uint256).max);
positionManager.modifyPosition(
Expand All @@ -554,7 +553,7 @@ contract QuoterTest is Test, Deployers {
}

function setupPoolMultiplePositions(PoolKey memory poolKey) internal {
manager.initialize(poolKey, SQRT_RATIO_1_1, ZERO_BYTES);
initializeRouter.initialize(poolKey, SQRT_RATIO_1_1, ZERO_BYTES);
MockERC20(Currency.unwrap(poolKey.currency0)).approve(address(positionManager), type(uint256).max);
MockERC20(Currency.unwrap(poolKey.currency1)).approve(address(positionManager), type(uint256).max);
positionManager.modifyPosition(
Expand Down Expand Up @@ -584,9 +583,9 @@ contract QuoterTest is Test, Deployers {

function setupPoolWithZeroTickInitialized(PoolKey memory poolKey) internal {
PoolId poolId = poolKey.toId();
(uint160 sqrtPriceX96,,,) = manager.getSlot0(poolId);
(uint160 sqrtPriceX96,,) = manager.getSlot0(poolId);
if (sqrtPriceX96 == 0) {
manager.initialize(poolKey, SQRT_RATIO_1_1, ZERO_BYTES);
initializeRouter.initialize(poolKey, SQRT_RATIO_1_1, ZERO_BYTES);
}

MockERC20(Currency.unwrap(poolKey.currency0)).approve(address(positionManager), type(uint256).max);
Expand Down

0 comments on commit 588ffde

Please sign in to comment.