Skip to content

Commit

Permalink
Accurate liquidity metering (#655)
Browse files Browse the repository at this point in the history
* add router for more accurate gas metering for adding and removing liquidity

* get amounts from delta directly

* Remove second manager

* remove initPool from no checks router

* move liquidity to a unique range for simple tests

---------

Co-authored-by: Alice Henshaw <henshawalice@gmail.com>
  • Loading branch information
gretzke and hensha256 authored May 15, 2024
1 parent e427108 commit 81a69c6
Show file tree
Hide file tree
Showing 16 changed files with 131 additions and 13 deletions.
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 @@
141237
141249
1 change: 0 additions & 1 deletion .forge-snapshots/addLiquidity.snap

This file was deleted.

2 changes: 1 addition & 1 deletion .forge-snapshots/erc20 collect protocol fees.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
57354
57342
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 @@
117750
117762
1 change: 0 additions & 1 deletion .forge-snapshots/removeLiquidity.snap

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
104916
1 change: 1 addition & 0 deletions .forge-snapshots/simple addLiquidity.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
167758
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
98535
1 change: 1 addition & 0 deletions .forge-snapshots/simple removeLiquidity.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
90901
2 changes: 1 addition & 1 deletion .forge-snapshots/simple swap with native.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
117339
117351
Original file line number Diff line number Diff line change
@@ -1 +1 @@
113800
113812
2 changes: 1 addition & 1 deletion .forge-snapshots/swap burn native 6909 for input.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
126323
126335
2 changes: 1 addition & 1 deletion .forge-snapshots/swap mint native output as 6909.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
148385
148397
77 changes: 77 additions & 0 deletions src/test/PoolModifyLiquidityTestNoChecks.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;

import {CurrencyLibrary, Currency} from "../types/Currency.sol";
import {IPoolManager} from "../interfaces/IPoolManager.sol";
import {BalanceDelta} from "../types/BalanceDelta.sol";
import {PoolKey} from "../types/PoolKey.sol";
import {PoolIdLibrary} from "../types/PoolId.sol";
import {PoolTestBase} from "./PoolTestBase.sol";
import {IHooks} from "../interfaces/IHooks.sol";
import {Hooks} from "../libraries/Hooks.sol";
import {LPFeeLibrary} from "../libraries/LPFeeLibrary.sol";
import {CurrencySettleTake} from "../libraries/CurrencySettleTake.sol";
import {Constants} from "../../test/utils/Constants.sol";

contract PoolModifyLiquidityTestNoChecks is PoolTestBase {
using CurrencyLibrary for Currency;
using CurrencySettleTake for Currency;
using Hooks for IHooks;
using LPFeeLibrary for uint24;
using PoolIdLibrary for PoolKey;

constructor(IPoolManager _manager) PoolTestBase(_manager) {}

struct CallbackData {
address sender;
PoolKey key;
IPoolManager.ModifyLiquidityParams params;
bytes hookData;
bool settleUsingBurn;
bool takeClaims;
}

function modifyLiquidity(
PoolKey memory key,
IPoolManager.ModifyLiquidityParams memory params,
bytes memory hookData
) external payable returns (BalanceDelta delta) {
delta = modifyLiquidity(key, params, hookData, false, false);
}

function modifyLiquidity(
PoolKey memory key,
IPoolManager.ModifyLiquidityParams memory params,
bytes memory hookData,
bool settleUsingBurn,
bool takeClaims
) public payable returns (BalanceDelta delta) {
delta = abi.decode(
manager.unlock(abi.encode(CallbackData(msg.sender, key, params, hookData, settleUsingBurn, takeClaims))),
(BalanceDelta)
);

uint256 ethBalance = address(this).balance;
if (ethBalance > 0) {
CurrencyLibrary.NATIVE.transfer(msg.sender, ethBalance);
}
}

function unlockCallback(bytes calldata rawData) external returns (bytes memory) {
require(msg.sender == address(manager));

CallbackData memory data = abi.decode(rawData, (CallbackData));

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

int256 delta0 = delta.amount0();
int256 delta1 = delta.amount1();

if (delta0 < 0) data.key.currency0.settle(manager, data.sender, uint256(-delta0), data.settleUsingBurn);
if (delta1 < 0) data.key.currency1.settle(manager, data.sender, uint256(-delta1), data.settleUsingBurn);
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);
}
}
41 changes: 38 additions & 3 deletions test/PoolManager.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -451,13 +451,48 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
}

function test_addLiquidity_gas() public {
modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES);
snapLastCall("addLiquidity");
IPoolManager.ModifyLiquidityParams memory uniqueParams =
IPoolManager.ModifyLiquidityParams({tickLower: -300, tickUpper: -180, liquidityDelta: 1e18, salt: 0});
modifyLiquidityNoChecks.modifyLiquidity(key, uniqueParams, ZERO_BYTES);
snapLastCall("simple addLiquidity");
}

function test_addLiquidity_secondAdditionSameRange_gas() public {
IPoolManager.ModifyLiquidityParams memory uniqueParams =
IPoolManager.ModifyLiquidityParams({tickLower: -300, tickUpper: -180, liquidityDelta: 1e18, salt: 0});
modifyLiquidityNoChecks.modifyLiquidity(key, uniqueParams, ZERO_BYTES);
modifyLiquidityNoChecks.modifyLiquidity(key, uniqueParams, ZERO_BYTES);
snapLastCall("simple addLiquidity second addition same range");
}

function test_removeLiquidity_gas() public {
IPoolManager.ModifyLiquidityParams memory uniqueParams =
IPoolManager.ModifyLiquidityParams({tickLower: -300, tickUpper: -180, liquidityDelta: 1e18, salt: 0});
// add some liquidity to remove
modifyLiquidityNoChecks.modifyLiquidity(key, uniqueParams, ZERO_BYTES);

uniqueParams.liquidityDelta *= -1;
modifyLiquidityNoChecks.modifyLiquidity(key, uniqueParams, ZERO_BYTES);
snapLastCall("simple removeLiquidity");
}

function test_removeLiquidity_someLiquidityRemains_gas() public {
// add double the liquidity to remove
IPoolManager.ModifyLiquidityParams memory uniqueParams =
IPoolManager.ModifyLiquidityParams({tickLower: -300, tickUpper: -180, liquidityDelta: 1e18, salt: 0});
modifyLiquidityNoChecks.modifyLiquidity(key, uniqueParams, ZERO_BYTES);

uniqueParams.liquidityDelta /= -2;
modifyLiquidityNoChecks.modifyLiquidity(key, uniqueParams, ZERO_BYTES);
snapLastCall("simple removeLiquidity some liquidity remains");
}

function test_addLiquidity_succeeds() public {
modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES);
}

function test_removeLiquidity_succeeds() public {
modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES);
snapLastCall("removeLiquidity");
}

function test_addLiquidity_withNative_gas() public {
Expand Down
6 changes: 5 additions & 1 deletion test/utils/Deployers.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {TickMath} from "../../src/libraries/TickMath.sol";
import {Constants} from "../utils/Constants.sol";
import {SortTokens} from "./SortTokens.sol";
import {PoolModifyLiquidityTest} from "../../src/test/PoolModifyLiquidityTest.sol";
import {PoolModifyLiquidityTestNoChecks} from "../../src/test/PoolModifyLiquidityTestNoChecks.sol";
import {PoolSwapTest} from "../../src/test/PoolSwapTest.sol";
import {SwapRouterNoChecks} from "../../src/test/SwapRouterNoChecks.sol";
import {PoolDonateTest} from "../../src/test/PoolDonateTest.sol";
Expand Down Expand Up @@ -56,6 +57,7 @@ contract Deployers {
Currency internal currency1;
IPoolManager manager;
PoolModifyLiquidityTest modifyLiquidityRouter;
PoolModifyLiquidityTestNoChecks modifyLiquidityNoChecks;
SwapRouterNoChecks swapRouterNoChecks;
PoolSwapTest swapRouter;
PoolDonateTest donateRouter;
Expand Down Expand Up @@ -97,6 +99,7 @@ contract Deployers {
swapRouter = new PoolSwapTest(manager);
swapRouterNoChecks = new SwapRouterNoChecks(manager);
modifyLiquidityRouter = new PoolModifyLiquidityTest(manager);
modifyLiquidityNoChecks = new PoolModifyLiquidityTestNoChecks(manager);
donateRouter = new PoolDonateTest(manager);
takeRouter = new PoolTakeTest(manager);
settleRouter = new PoolSettleTest(manager);
Expand Down Expand Up @@ -125,10 +128,11 @@ contract Deployers {
function deployMintAndApproveCurrency() internal returns (Currency currency) {
MockERC20 token = deployTokens(1, 2 ** 255)[0];

address[7] memory toApprove = [
address[8] memory toApprove = [
address(swapRouter),
address(swapRouterNoChecks),
address(modifyLiquidityRouter),
address(modifyLiquidityNoChecks),
address(donateRouter),
address(takeRouter),
address(claimsRouter),
Expand Down

0 comments on commit 81a69c6

Please sign in to comment.