Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

measure global fee growth and fees collected after fuzzing... #736

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1 +1 @@
146557
146650
2 changes: 1 addition & 1 deletion .forge-snapshots/addLiquidity CA fee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
172605
172698
2 changes: 1 addition & 1 deletion .forge-snapshots/addLiquidity with empty hook.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
275714
275807
2 changes: 1 addition & 1 deletion .forge-snapshots/addLiquidity with native token.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
136837
136931
Original file line number Diff line number Diff line change
@@ -1 +1 @@
294762
294855
2 changes: 1 addition & 1 deletion .forge-snapshots/removeLiquidity CA fee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
142125
142218
2 changes: 1 addition & 1 deletion .forge-snapshots/removeLiquidity with empty hook.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
131597
131690
2 changes: 1 addition & 1 deletion .forge-snapshots/removeLiquidity with native token.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
113398
113473
4 changes: 2 additions & 2 deletions src/test/Fuzzers.sol
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ contract Fuzzers is StdUtils {
bytes memory hookData
) internal returns (IPoolManager.ModifyLiquidityParams memory result, BalanceDelta delta) {
result = createFuzzyLiquidityParams(key, params, sqrtPriceX96);
delta = modifyLiquidityRouter.modifyLiquidity(key, result, hookData);
(delta,) = modifyLiquidityRouter.modifyLiquidity(key, result, hookData);
}

// There exists possible positions in the pool, so we tighten the boundaries of liquidity.
Expand All @@ -178,6 +178,6 @@ contract Fuzzers is StdUtils {
uint256 maxPositions
) internal returns (IPoolManager.ModifyLiquidityParams memory result, BalanceDelta delta) {
result = createFuzzyLiquidityParamsWithTightBound(key, params, sqrtPriceX96, maxPositions);
delta = modifyLiquidityRouter.modifyLiquidity(key, result, hookData);
(delta,) = modifyLiquidityRouter.modifyLiquidity(key, result, hookData);
}
}
14 changes: 7 additions & 7 deletions src/test/PoolModifyLiquidityTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ contract PoolModifyLiquidityTest is PoolTestBase {
PoolKey memory key,
IPoolManager.ModifyLiquidityParams memory params,
bytes memory hookData
) external payable returns (BalanceDelta delta) {
delta = modifyLiquidity(key, params, hookData, false, false);
) external payable returns (BalanceDelta delta, BalanceDelta feesAccrued) {
(delta, feesAccrued) = modifyLiquidity(key, params, hookData, false, false);
}

function modifyLiquidity(
Expand All @@ -45,10 +45,10 @@ contract PoolModifyLiquidityTest is PoolTestBase {
bytes memory hookData,
bool settleUsingBurn,
bool takeClaims
) public payable returns (BalanceDelta delta) {
delta = abi.decode(
) public payable returns (BalanceDelta delta, BalanceDelta feesAccrued) {
(delta, feesAccrued) = abi.decode(
manager.unlock(abi.encode(CallbackData(msg.sender, key, params, hookData, settleUsingBurn, takeClaims))),
(BalanceDelta)
(BalanceDelta, BalanceDelta)
);

uint256 ethBalance = address(this).balance;
Expand All @@ -66,7 +66,7 @@ contract PoolModifyLiquidityTest is PoolTestBase {
data.key.toId(), address(this), data.params.tickLower, data.params.tickUpper, data.params.salt
).liquidity;

(BalanceDelta delta,) = manager.modifyLiquidity(data.key, data.params, data.hookData);
(BalanceDelta delta, BalanceDelta feesAccrued) = manager.modifyLiquidity(data.key, data.params, data.hookData);

uint128 liquidityAfter = manager.getPosition(
data.key.toId(), address(this), data.params.tickLower, data.params.tickUpper, data.params.salt
Expand All @@ -92,6 +92,6 @@ contract PoolModifyLiquidityTest is PoolTestBase {
if (delta0 > 0) data.key.currency0.take(manager, data.sender, uint256(delta0), data.takeClaims);
if (delta1 > 0) data.key.currency1.take(manager, data.sender, uint256(delta1), data.takeClaims);

return abi.encode(delta);
return abi.encode(delta, feesAccrued);
}
}
6 changes: 3 additions & 3 deletions test/ModifyLiquidity.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ contract ModifyLiquidityTest is Test, Logger, Deployers, JavascriptFfi, Fuzzers,

logParams(params);

(BalanceDelta delta) = modifyLiquidityRouter.modifyLiquidity(simpleKey, params, ZERO_BYTES);
(BalanceDelta delta,) = modifyLiquidityRouter.modifyLiquidity(simpleKey, params, ZERO_BYTES);

(int128 jsDelta0, int128 jsDelta1) = _modifyLiquidityJS(simplePoolId, params);

Expand All @@ -85,7 +85,7 @@ contract ModifyLiquidityTest is Test, Logger, Deployers, JavascriptFfi, Fuzzers,
salt: 0
});

(BalanceDelta delta) = modifyLiquidityRouter.modifyLiquidity(wp0, params, ZERO_BYTES);
(BalanceDelta delta,) = modifyLiquidityRouter.modifyLiquidity(wp0, params, ZERO_BYTES);

(int128 jsDelta0, int128 jsDelta1) = _modifyLiquidityJS(wpId0, params);

Expand All @@ -112,7 +112,7 @@ contract ModifyLiquidityTest is Test, Logger, Deployers, JavascriptFfi, Fuzzers,

params.tickLower = 10;

(BalanceDelta delta) = modifyLiquidityRouter.modifyLiquidity(wp0, params, ZERO_BYTES);
(BalanceDelta delta,) = modifyLiquidityRouter.modifyLiquidity(wp0, params, ZERO_BYTES);

(int128 jsDelta0, int128 jsDelta1) = _modifyLiquidityJS(wpId0, params);

Expand Down
52 changes: 43 additions & 9 deletions test/PoolManager.swap.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,15 @@ import {SqrtPriceMath} from "../src/libraries/SqrtPriceMath.sol";
import {TickMath} from "../src/libraries/TickMath.sol";
import {SafeCast} from "../src/libraries/SafeCast.sol";
import {LiquidityAmounts} from "./utils/LiquidityAmounts.sol";
import {StateLibrary} from "../src/libraries/StateLibrary.sol";
import {PoolIdLibrary} from "../src/types/PoolId.sol";

abstract contract V3Fuzzer is V3Helper, Deployers, Fuzzers, IUniswapV3MintCallback, IUniswapV3SwapCallback {
using CurrencyLibrary for Currency;
using StateLibrary for IPoolManager;
using PoolIdLibrary for PoolKey;

IPoolManager.ModifyLiquidityParams[] liquidityParams;

function setUp() public virtual override {
super.setUp();
Expand Down Expand Up @@ -75,11 +81,12 @@ abstract contract V3Fuzzer is V3Helper, Deployers, Fuzzers, IUniswapV3MintCallba
);

modifyLiquidityRouter.modifyLiquidity(key_, v4LiquidityParams, "");
liquidityParams.push(v4LiquidityParams);
}

function swap(IUniswapV3Pool pool, PoolKey memory key_, bool zeroForOne, int128 amountSpecified)
internal
returns (int256 amount0Diff, int256 amount1Diff)
returns (int256 amount0Diff, int256 amount1Diff, bool overflows)
{
if (amountSpecified == 0) amountSpecified = 1;
if (amountSpecified == type(int128).min) amountSpecified = type(int128).min + 1;
Expand All @@ -93,7 +100,6 @@ abstract contract V3Fuzzer is V3Helper, Deployers, Fuzzers, IUniswapV3MintCallba
""
);
// v3 can handle bigger numbers than v4, so if we exceed int128, check that the next call reverts
bool overflows = false;
if (
amount0Delta > type(int128).max || amount1Delta > type(int128).max || amount0Delta < type(int128).min
|| amount1Delta < type(int128).min
Expand Down Expand Up @@ -134,6 +140,30 @@ abstract contract V3Fuzzer is V3Helper, Deployers, Fuzzers, IUniswapV3MintCallba
if (amount0Delta > 0) currency0.transfer(msg.sender, uint256(amount0Delta));
if (amount1Delta > 0) currency1.transfer(msg.sender, uint256(amount1Delta));
}

function verifyFees(IUniswapV3Pool pool, PoolKey memory key_) internal {
(uint256 v4FeeGrowth0, uint256 v4FeeGrowth1) = manager.getFeeGrowthGlobals(key_.toId());
uint256 v3FeeGrowth0 = pool.feeGrowthGlobal0X128();
uint256 v3FeeGrowth1 = pool.feeGrowthGlobal1X128();
assertEq(v4FeeGrowth0, v3FeeGrowth0);
assertEq(v4FeeGrowth1, v3FeeGrowth1);

BalanceDelta v3FeesTotal = toBalanceDelta(0, 0);
BalanceDelta v4FeesTotal = toBalanceDelta(0, 0);
uint256 len = liquidityParams.length;
for (uint256 i = 0; i < len; ++i) {
IPoolManager.ModifyLiquidityParams memory params = liquidityParams[i];
pool.burn(params.tickLower, params.tickUpper, 0);
(uint128 v3Amount0, uint128 v3Amount1) =
pool.collect(address(this), params.tickLower, params.tickUpper, type(uint128).max, type(uint128).max);
v3FeesTotal = v3FeesTotal + toBalanceDelta(int128(v3Amount0), int128(v3Amount1));
params.liquidityDelta = 0;
(, BalanceDelta feesAccrued) = modifyLiquidityRouter.modifyLiquidity(key_, params, "");

v4FeesTotal = v4FeesTotal + feesAccrued;
}
assertTrue(v3FeesTotal == v4FeesTotal);
}
}

contract V3SwapTests is V3Fuzzer {
Expand All @@ -150,9 +180,11 @@ contract V3SwapTests is V3Fuzzer {
(IUniswapV3Pool pool, PoolKey memory key_, uint160 sqrtPriceX96) =
initPools(feeSeed, tickSpacingSeed, sqrtPriceX96seed);
addLiquidity(pool, key_, sqrtPriceX96, lowerTickUnsanitized, upperTickUnsanitized, liquidityDeltaUnbound, false);
(int256 amount0Diff, int256 amount1Diff) = swap(pool, key_, zeroForOne, swapAmount);
(int256 amount0Diff, int256 amount1Diff, bool overflows) = swap(pool, key_, zeroForOne, swapAmount);
if (overflows) return;
assertEq(amount0Diff, 0);
assertEq(amount1Diff, 0);
verifyFees(pool, key_);
}

struct TightLiquidityParams {
Expand All @@ -164,28 +196,30 @@ contract V3SwapTests is V3Fuzzer {
function test_shouldSwapEqualMultipleLP(
uint24 feeSeed,
int24 tickSpacingSeed,
TightLiquidityParams[] memory liquidityParams,
TightLiquidityParams[] memory liquidityParams_,
int256 sqrtPriceX96seed,
int128 swapAmount,
bool zeroForOne
) public {
(IUniswapV3Pool pool, PoolKey memory key_, uint160 sqrtPriceX96) =
initPools(feeSeed, tickSpacingSeed, sqrtPriceX96seed);
for (uint256 i = 0; i < liquidityParams.length; ++i) {
for (uint256 i = 0; i < liquidityParams_.length; ++i) {
if (i == 20) break;
addLiquidity(
pool,
key_,
sqrtPriceX96,
liquidityParams[i].lowerTickUnsanitized,
liquidityParams[i].upperTickUnsanitized,
liquidityParams[i].liquidityDeltaUnbound,
liquidityParams_[i].lowerTickUnsanitized,
liquidityParams_[i].upperTickUnsanitized,
liquidityParams_[i].liquidityDeltaUnbound,
true
);
}

(int256 amount0Diff, int256 amount1Diff) = swap(pool, key_, zeroForOne, swapAmount);
(int256 amount0Diff, int256 amount1Diff, bool overflows) = swap(pool, key_, zeroForOne, swapAmount);
if (overflows) return;
assertEq(amount0Diff, 0);
assertEq(amount1Diff, 0);
verifyFees(pool, key_);
}
}
4 changes: 2 additions & 2 deletions test/PoolManager.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {

(key,) = initPool(currency0, currency1, IHooks(mockAddr), 3000, sqrtPriceX96, ZERO_BYTES);

BalanceDelta balanceDelta = modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES);
(BalanceDelta balanceDelta,) = modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES);

bytes32 beforeSelector = MockHooks.beforeAddLiquidity.selector;
bytes memory beforeParams = abi.encode(address(modifyLiquidityRouter), key, LIQUIDITY_PARAMS, ZERO_BYTES);
Expand Down Expand Up @@ -200,7 +200,7 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {

(key,) = initPool(currency0, currency1, IHooks(mockAddr), 3000, sqrtPriceX96, ZERO_BYTES);
modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES);
BalanceDelta balanceDelta = modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES);
(BalanceDelta balanceDelta,) = modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES);

bytes32 beforeSelector = MockHooks.beforeRemoveLiquidity.selector;
bytes memory beforeParams = abi.encode(address(modifyLiquidityRouter), key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES);
Expand Down
9 changes: 9 additions & 0 deletions test/utils/V3Helper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ interface IUniswapV3Pool {
uint160 sqrtPriceLimitX96,
bytes calldata data
) external returns (int256 amount0, int256 amount1);
function collect(
address recipient,
int24 tickLower,
int24 tickUpper,
uint128 amount0Requested,
uint128 amount1Requested
) external returns (uint128 amount0, uint128 amount1);
function feeGrowthGlobal0X128() external view returns (uint256);
function feeGrowthGlobal1X128() external view returns (uint256);
}

interface IUniswapV3MintCallback {
Expand Down
Loading