Skip to content

Commit

Permalink
feat: forge test, fix liquidity provider
Browse files Browse the repository at this point in the history
  • Loading branch information
ts0yu authored Aug 4, 2024
1 parent 438fd63 commit 6f41aad
Show file tree
Hide file tree
Showing 7 changed files with 1,976 additions and 590 deletions.
1 change: 1 addition & 0 deletions contracts/utils/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
src = "src"
out = "out"
libs = ["lib"]
evm-version = "cancun"

# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
112 changes: 88 additions & 24 deletions contracts/utils/src/LiquidityProvider.sol
Original file line number Diff line number Diff line change
@@ -1,34 +1,98 @@
// SPDX-License-Identifier: MIT
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;

import {IPoolManager} from "v4-core/interfaces/IPoolManager.sol";
import {PoolManager} from "v4-core/PoolManager.sol";
import {PoolKey} from "v4-core/types/PoolKey.sol";
import {PoolModifyLiquidityTestNoChecks} from "v4-core/test/PoolModifyLiquidityTestNoChecks.sol";
import {BalanceDelta} from "v4-core/types/BalanceDelta.sol";
import {CurrencyLibrary, Currency} from "v4-core/types/Currency.sol";
import {PoolIdLibrary} from "v4-core/types/PoolId.sol";
import {IHooks} from "v4-core/interfaces/IHooks.sol";
import {Hooks} from "v4-core/libraries/Hooks.sol";
import {LPFeeLibrary} from "v4-core/libraries/LPFeeLibrary.sol";
import {StateLibrary} from "v4-core/libraries/StateLibrary.sol";
import {PoolTestBase} from "v4-core/test/PoolTestBase.sol";
import {CurrencySettler} from "../lib/v4-core/test/utils/CurrencySettler.sol";

contract LiquidityProvider {
PoolModifyLiquidityTestNoChecks immutable lpRouter;
contract LiquidityProvider is PoolTestBase {
using CurrencySettler for Currency;
using Hooks for IHooks;
using LPFeeLibrary for uint24;
using PoolIdLibrary for PoolKey;
using StateLibrary for IPoolManager;

constructor(IPoolManager _manager) {
lpRouter = new PoolModifyLiquidityTestNoChecks(_manager);
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 createLiquidity(
PoolKey memory poolKey,
int24 tickLower,
int24 tickUpper,
int256 liquidity,
bytes calldata hookData
) external {
// if 0 < liquidity: add liquidity -- otherwise remove liquidity
lpRouter.modifyLiquidity(
poolKey,
IPoolManager.ModifyLiquidityParams({
tickLower: tickLower,
tickUpper: tickUpper,
liquidityDelta: liquidity,
salt: ""
}),
hookData
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));

(uint128 liquidityBefore,,) = manager.getPositionInfo(
data.key.toId(), address(this), data.params.tickLower, data.params.tickUpper, data.params.salt
);

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

(uint128 liquidityAfter,,) = manager.getPositionInfo(
data.key.toId(), address(this), data.params.tickLower, data.params.tickUpper, data.params.salt
);

(,, int256 delta0) = _fetchBalances(data.key.currency0, data.sender, address(this));
(,, int256 delta1) = _fetchBalances(data.key.currency1, data.sender, address(this));

require(
int128(liquidityBefore) + data.params.liquidityDelta == int128(liquidityAfter), "liquidity change incorrect"
);

if (data.params.liquidityDelta < 0) {
assert(delta0 > 0 || delta1 > 0);
assert(!(delta0 < 0 || delta1 < 0));
} else if (data.params.liquidityDelta > 0) {
assert(delta0 < 0 || delta1 < 0);
assert(!(delta0 > 0 || delta1 > 0));
}

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);
}
}
}
Loading

0 comments on commit 6f41aad

Please sign in to comment.