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

Big update #25

Merged
merged 15 commits into from
May 31, 2024
2 changes: 1 addition & 1 deletion .forge-snapshots/autodynamic fee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
242952
141494
2 changes: 1 addition & 1 deletion .forge-snapshots/hookFee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
265804
150527
2 changes: 1 addition & 1 deletion .forge-snapshots/manual dynamic fee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
219217
122293
2 changes: 1 addition & 1 deletion forge-lib/v4-core
Submodule v4-core updated 236 files
20 changes: 12 additions & 8 deletions forge-test/Counter.sol
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
pragma solidity ^0.8.24;

// import {BaseHook} from "v4-periphery/BaseHook.sol";
import {BaseHook} from "@v4-by-example/utils/BaseHook.sol";
import {BaseHook} from "v4-periphery/BaseHook.sol";

import {Hooks} from "v4-core/src/libraries/Hooks.sol";
import {IPoolManager} from "v4-core/src/interfaces/IPoolManager.sol";
import {PoolKey} from "v4-core/src/types/PoolKey.sol";
import {PoolId, PoolIdLibrary} from "v4-core/src/types/PoolId.sol";
import {BalanceDelta} from "v4-core/src/types/BalanceDelta.sol";
import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "v4-core/src/types/BeforeSwapDelta.sol";

contract Counter is BaseHook {
using PoolIdLibrary for PoolKey;
Expand Down Expand Up @@ -37,7 +37,11 @@ contract Counter is BaseHook {
beforeSwap: true,
afterSwap: true,
beforeDonate: false,
afterDonate: false
afterDonate: false,
beforeSwapReturnDelta: false,
afterSwapReturnDelta: false,
afterAddLiquidityReturnDelta: false,
afterRemoveLiquidityReturnDelta: false
});
}

Expand All @@ -48,19 +52,19 @@ contract Counter is BaseHook {
function beforeSwap(address, PoolKey calldata key, IPoolManager.SwapParams calldata, bytes calldata)
external
override
returns (bytes4)
returns (bytes4, BeforeSwapDelta, uint24)
{
beforeSwapCount[key.toId()]++;
return BaseHook.beforeSwap.selector;
return (BaseHook.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, 0);
}

function afterSwap(address, PoolKey calldata key, IPoolManager.SwapParams calldata, BalanceDelta, bytes calldata)
external
override
returns (bytes4)
returns (bytes4, int128)
{
afterSwapCount[key.toId()]++;
return BaseHook.afterSwap.selector;
return (BaseHook.afterSwap.selector, 0);
}

function beforeAddLiquidity(
Expand Down
56 changes: 25 additions & 31 deletions forge-test/Counter.t.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
pragma solidity ^0.8.24;

import "forge-std/Test.sol";
import {IHooks} from "v4-core/src/interfaces/IHooks.sol";
Expand All @@ -10,22 +10,20 @@ import {PoolKey} from "v4-core/src/types/PoolKey.sol";
import {BalanceDelta} from "v4-core/src/types/BalanceDelta.sol";
import {PoolId, PoolIdLibrary} from "v4-core/src/types/PoolId.sol";
import {CurrencyLibrary, Currency} from "v4-core/src/types/Currency.sol";
import {PoolSwapTest} from "v4-core/src/test/PoolSwapTest.sol";
import {Deployers} from "v4-core/test/utils/Deployers.sol";
import {Counter} from "./Counter.sol";
import {HookMiner} from "./utils/HookMiner.sol";
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
import {PoolSwapTest} from "v4-core/src/test/PoolSwapTest.sol";

contract CounterTest is Test, Deployers, GasSnapshot {
contract CounterTest is Test, Deployers {
using PoolIdLibrary for PoolKey;
using CurrencyLibrary for Currency;

Counter counter;
PoolKey poolKey;
PoolId poolId;

function setUp() public {
// creates the pool manager, test tokens, and other utility routers
// creates the pool manager, utility routers, and test tokens
Deployers.deployFreshManagerAndRouters();
Deployers.deployMintAndApprove2Currencies();

Expand All @@ -40,20 +38,18 @@ contract CounterTest is Test, Deployers, GasSnapshot {
require(address(counter) == hookAddress, "CounterTest: hook address mismatch");

// Create the pool
poolKey = PoolKey(currency0, currency1, 3000, 60, IHooks(address(counter)));
poolId = poolKey.toId();
manager.initialize(poolKey, SQRT_RATIO_1_1, ZERO_BYTES);
key = PoolKey(currency0, currency1, 3000, 60, IHooks(address(counter)));
poolId = key.toId();
manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES);

// Provide liquidity to the pool
modifyLiquidityRouter.modifyLiquidity(key, IPoolManager.ModifyLiquidityParams(-60, 60, 10 ether, 0), ZERO_BYTES);
modifyLiquidityRouter.modifyLiquidity(
poolKey, IPoolManager.ModifyLiquidityParams(-60, 60, 10 ether), ZERO_BYTES
);
modifyLiquidityRouter.modifyLiquidity(
poolKey, IPoolManager.ModifyLiquidityParams(-120, 120, 10 ether), ZERO_BYTES
key, IPoolManager.ModifyLiquidityParams(-120, 120, 10 ether, 0), ZERO_BYTES
);
modifyLiquidityRouter.modifyLiquidity(
poolKey,
IPoolManager.ModifyLiquidityParams(TickMath.minUsableTick(60), TickMath.maxUsableTick(60), 10 ether),
key,
IPoolManager.ModifyLiquidityParams(TickMath.minUsableTick(60), TickMath.maxUsableTick(60), 10 ether, 0),
ZERO_BYTES
);
}
Expand All @@ -67,31 +63,29 @@ contract CounterTest is Test, Deployers, GasSnapshot {
assertEq(counter.afterSwapCount(poolId), 0);

// Perform a test swap //
int256 amount = -100;
bool zeroForOne = true;
BalanceDelta swapDelta = swap(poolKey, zeroForOne, amount, ZERO_BYTES);
int256 amountSpecified = -1e18; // negative number indicates exact input swap!
BalanceDelta swapDelta = swap(key, zeroForOne, amountSpecified, ZERO_BYTES);
// ------------------- //

assertEq(int256(swapDelta.amount0()), amount);
assertEq(int256(swapDelta.amount0()), amountSpecified);

assertEq(counter.beforeSwapCount(poolId), 1);
assertEq(counter.afterSwapCount(poolId), 1);
}

function test_counter_snapshot() public {
int256 amount = 1e18;
bool zeroForOne = true;
IPoolManager.SwapParams memory params = IPoolManager.SwapParams({
zeroForOne: zeroForOne,
amountSpecified: amount,
sqrtPriceLimitX96: zeroForOne ? MIN_PRICE_LIMIT : MAX_PRICE_LIMIT // unlimited impact
});
function testLiquidityHooks() public {
// positions were created in setup()
assertEq(counter.beforeAddLiquidityCount(poolId), 3);
assertEq(counter.beforeRemoveLiquidityCount(poolId), 0);

PoolSwapTest.TestSettings memory testSettings =
PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true, currencyAlreadySent: false});
// remove liquidity
int256 liquidityDelta = -1e18;
modifyLiquidityRouter.modifyLiquidity(
key, IPoolManager.ModifyLiquidityParams(-60, 60, liquidityDelta, 0), ZERO_BYTES
);

snapStart("counter");
swapRouter.swap(poolKey, params, testSettings, ZERO_BYTES);
snapEnd();
assertEq(counter.beforeAddLiquidityCount(poolId), 3);
assertEq(counter.beforeRemoveLiquidityCount(poolId), 1);
}
}
53 changes: 27 additions & 26 deletions forge-test/CustomCurve.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ import {BalanceDelta} from "v4-core/src/types/BalanceDelta.sol";
import {PoolId, PoolIdLibrary} from "v4-core/src/types/PoolId.sol";
import {CurrencyLibrary, Currency} from "v4-core/src/types/Currency.sol";
import {Deployers} from "v4-core/test/utils/Deployers.sol";
import {CustomCurve} from "@v4-by-example/pages/hooks/custom-curve/CustomCurve.sol";
import {ConstantSumCurve} from "@v4-by-example/pages/hooks/custom-curve/CustomCurve.sol";
import {HookMiner} from "./utils/HookMiner.sol";
import {IERC20} from "forge-std/interfaces/IERC20.sol";

contract CustomCurveTest is Test, Deployers {
using PoolIdLibrary for PoolKey;
using CurrencyLibrary for Currency;

CustomCurve hook;
ConstantSumCurve hook;
PoolKey poolKey;
PoolId poolId;

Expand All @@ -29,41 +29,42 @@ contract CustomCurveTest is Test, Deployers {
Deployers.deployMintAndApprove2Currencies();

// Deploy the hook to an address with the correct flags
uint160 flags = uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_ADD_LIQUIDITY_FLAG);
uint160 flags =
uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_ADD_LIQUIDITY_FLAG | Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG);
(address hookAddress, bytes32 salt) =
HookMiner.find(address(this), flags, type(CustomCurve).creationCode, abi.encode(address(manager)));
hook = new CustomCurve{salt: salt}(IPoolManager(address(manager)));
HookMiner.find(address(this), flags, type(ConstantSumCurve).creationCode, abi.encode(address(manager)));
hook = new ConstantSumCurve{salt: salt}(IPoolManager(address(manager)));
require(address(hook) == hookAddress, "CustomCurveTest: hook address mismatch");

// Create the pool
poolKey = PoolKey(currency0, currency1, 3000, 60, IHooks(hook));
poolId = poolKey.toId();
manager.initialize(poolKey, SQRT_RATIO_1_1, ZERO_BYTES);
manager.initialize(poolKey, SQRT_PRICE_1_1, ZERO_BYTES);

PoolKey memory hookless = PoolKey(currency0, currency1, 3000, 60, IHooks(address(0x0)));
manager.initialize(hookless, SQRT_RATIO_1_1, ZERO_BYTES);

// add liquidity so theres tokens to take
modifyLiquidityRouter.modifyLiquidity(
hookless, IPoolManager.ModifyLiquidityParams(-60, 60, 10000 ether), ZERO_BYTES
);

// Provide liquidity to the pool
IERC20(Currency.unwrap(currency0)).transfer(address(hook), 10_000 ether);
IERC20(Currency.unwrap(currency1)).transfer(address(hook), 10_000 ether);
// Add liquidity
IERC20(Currency.unwrap(currency0)).approve(address(hook), type(uint256).max);
IERC20(Currency.unwrap(currency1)).approve(address(hook), type(uint256).max);
hook.addLiquidity(poolKey, 100 ether, 100 ether);
}

function test_swap() public {
uint256 token1Before = currency1.balanceOfSelf();

// Perform a test swap //
int256 amount = 10e18;
bool zeroForOne = true;
swap(poolKey, zeroForOne, amount, ZERO_BYTES);
// ------------------- //
function test_swap(bool zeroForOne, int256 amountSpecified) public {
amountSpecified = bound(amountSpecified, -100 ether, 100 ether);
vm.assume(amountSpecified != 0);

uint256 token0Before = currency0.balanceOfSelf();
uint256 token1Before = currency1.balanceOfSelf();
swap(poolKey, zeroForOne, amountSpecified, ZERO_BYTES);
uint256 token0After = currency0.balanceOfSelf();
uint256 token1After = currency1.balanceOfSelf();

assertEq(token1After - token1Before, 1e18);
bool exactInput = amountSpecified < 0;
uint256 amountSwapped = exactInput ? uint256(-amountSpecified) : uint256(amountSpecified);
if (zeroForOne) {
assertEq(token0Before - token0After, amountSwapped);
assertEq(token1After - token1Before, amountSwapped);
} else {
assertEq(token0After - token0Before, amountSwapped);
assertEq(token1Before - token1After, amountSwapped);
}
}
}
Loading
Loading