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

[Reference ]Feat/dynamic fee hook #11

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
30 changes: 30 additions & 0 deletions script/04_DeploySampleCLDynamicFeeHook.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;

import "forge-std/Script.sol";
import {BaseScript} from "./BaseScript.sol";

import {SampleCLDynamicFeeHook} from "../src/pool-cl/dynamic-fee/SampleCLDynamicFeeHook.sol";
import {ICLPoolManager} from "pancake-v4-core/src/pool-cl/interfaces/ICLPoolManager.sol";

/**
* forge script script/04_DeploySampleCLDynamicFeeHook.s.sol:DeploySampleCLDynamicFeeHookScript -vvv \
* --rpc-url $RPC_URL \
* --broadcast \
* --slow \
* --verify
*/
contract DeploySampleCLDynamicFeeHookScript is BaseScript {
function run() public {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(deployerPrivateKey);

address clPoolManager = getAddressFromConfig("clPoolManager");
emit log_named_address("CLPoolManager", clPoolManager);

SampleCLDynamicFeeHook hookAddr = new SampleCLDynamicFeeHook(ICLPoolManager(clPoolManager));
emit log_named_address("SampleCLDynamicFeeHook", address(hookAddr));

vm.stopBroadcast();
}
}
30 changes: 30 additions & 0 deletions script/05_DeploySampleBinDynamicFeeHook.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;

import "forge-std/Script.sol";
import {BaseScript} from "./BaseScript.sol";

import {SampleBinDynamicFeeHook} from "../src/pool-bin/dynamic-fee/SampleBinDynamicFeeHook.sol";
import {IBinPoolManager} from "pancake-v4-core/src/pool-bin/interfaces/IBinPoolManager.sol";

/**
* forge script script/05_DeploySampleBinDynamicFeeHook.s.sol:DeploySampleBinDynamicFeeHookScript -vvv \
* --rpc-url $RPC_URL \
* --broadcast \
* --slow \
* --verify
*/
contract DeploySampleBinDynamicFeeHookScript is BaseScript {
function run() public {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(deployerPrivateKey);

address binPoolManager = getAddressFromConfig("binPoolManager");
emit log_named_address("BinPoolManager", binPoolManager);

SampleBinDynamicFeeHook feeHook = new SampleBinDynamicFeeHook(IBinPoolManager(binPoolManager));
emit log_named_address("SampleBinDynamicFeeHook", address(feeHook));

vm.stopBroadcast();
}
}
4 changes: 3 additions & 1 deletion script/config/bsc-testnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"binPositionManager": "0x26008c91a2D47147d6739db3fFd3598A27da859d",
"mockVeCake": "0x86668337a40CaAd59F463E89550c6Aa59C056988",
"clVeCakeExclusiveHook": "0x3290880eB5b48Ee5CF1E8e381DDe932F7D696B27",
"binVeCakeExclusiveHook": "0x6203377AE3B7e1592806909836F6DC6b39026a60"
"binVeCakeExclusiveHook": "0x6203377AE3B7e1592806909836F6DC6b39026a60",
"sampleCLDynamicFeeHook": "0x9D596b40A6C9eAcCd90B3556500e93A489BB8Ba7",
"sampleBinDynamicFeeHook": "0x07728d3e6CD6aE8010F8F07D132E28e4e32c55E3"
}

4 changes: 3 additions & 1 deletion script/config/ethereum-sepolia.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"binPositionManager": "0x21015eF9927e06b7Fc19D986A214e449Aa22FF7d",
"mockVeCake": "0xA25ECd559680c77185a00a00e33BD9df14a5133e",
"clVeCakeExclusiveHook": "0x549D196225706804c0A0fa9296c7a32fE6963850",
"binVeCakeExclusiveHook": "0xCc22705eA9433c8C35a1C93778bbFF76A19F3d55"
"binVeCakeExclusiveHook": "0xCc22705eA9433c8C35a1C93778bbFF76A19F3d55",
"sampleCLDynamicFeeHook": "0x6B1fdFc5dFB10DC5735bB242D014B4d4F1fb2c7A",
"sampleBinDynamicFeeHook": "0x470a9995c3bf588eE90A7F8e1b5372da1643Bca1"
}

91 changes: 91 additions & 0 deletions src/pool-bin/dynamic-fee/SampleBinDynamicFeeHook.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
pragma solidity ^0.8.19;

import "pancake-v4-core/src/pool-cl/interfaces/ICLHooks.sol";
import {PoolKey} from "pancake-v4-core/src/types/PoolKey.sol";
import {PoolId, PoolIdLibrary} from "pancake-v4-core/src/types/PoolId.sol";
import {Currency} from "pancake-v4-core/src/types/Currency.sol";
import {IBinPoolManager} from "pancake-v4-core/src/pool-bin/interfaces/IBinPoolManager.sol";
import {BinPoolManager} from "pancake-v4-core/src/pool-bin/BinPoolManager.sol";
import {LPFeeLibrary} from "pancake-v4-core/src/libraries/LPFeeLibrary.sol";
import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "pancake-v4-core/src/types/BeforeSwapDelta.sol";
import {BinBaseHook} from "../BinBaseHook.sol";

contract SampleBinDynamicFeeHook is BinBaseHook {
using PoolIdLibrary for PoolKey;

uint24 DEFAULT_LP_FEE = 3000;
uint24 FREE_LP_FEE = 0;

bool enableLPFeeOverride = false;

constructor(IBinPoolManager poolManager) BinBaseHook(poolManager) {}

function toggleLPFeeOverride() external {
enableLPFeeOverride = !enableLPFeeOverride;
}

function setDynamicLpFee(PoolKey memory key, uint24 fee) public {
poolManager.updateDynamicLPFee(key, fee);
}

function getHooksRegistrationBitmap() external pure override returns (uint16) {
return _hooksRegistrationBitmapFrom(
Permissions({
beforeInitialize: false,
afterInitialize: true,
beforeMint: true,
afterMint: false,
beforeBurn: false,
afterBurn: false,
beforeSwap: true,
afterSwap: false,
beforeDonate: false,
afterDonate: false,
beforeSwapReturnDelta: false,
afterSwapReturnDelta: false,
afterMintReturnDelta: false,
afterBurnReturnDelta: false
})
);
}

function afterInitialize(address, PoolKey calldata key, uint24, bytes calldata)
external
override
returns (bytes4)
{
setDynamicLpFee(key, DEFAULT_LP_FEE);
return this.beforeInitialize.selector;
}

function beforeMint(address, PoolKey calldata, IBinPoolManager.MintParams calldata, bytes calldata)
external
override
returns (bytes4, uint24)
{
// if enableLPFeeOverride, the lp fee for the ongoing inner swap will be 0
if (enableLPFeeOverride) {
return (this.beforeMint.selector, LPFeeLibrary.OVERRIDE_FEE_FLAG & FREE_LP_FEE);
}

// otherwise, the lp fee will just be the default value
return (this.beforeMint.selector, 0);
}

function beforeSwap(address, PoolKey calldata, bool, int128, bytes calldata)
external
override
returns (bytes4, BeforeSwapDelta, uint24)
{
// if enableLPFeeOverride, the lp fee for the ongoing swap will be 0
if (enableLPFeeOverride) {
return (
this.beforeSwap.selector,
BeforeSwapDeltaLibrary.ZERO_DELTA,
LPFeeLibrary.OVERRIDE_FEE_FLAG & FREE_LP_FEE
);
}

return (this.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, 0);
}
}
80 changes: 80 additions & 0 deletions src/pool-cl/dynamic-fee/SampleCLDynamicFeeHook.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
pragma solidity ^0.8.19;

import "pancake-v4-core/src/pool-cl/interfaces/ICLHooks.sol";
import {PoolKey} from "pancake-v4-core/src/types/PoolKey.sol";
import {PoolId, PoolIdLibrary} from "pancake-v4-core/src/types/PoolId.sol";
import {Currency} from "pancake-v4-core/src/types/Currency.sol";
import {ICLPoolManager} from "pancake-v4-core/src/pool-cl/interfaces/ICLPoolManager.sol";
import {CLPoolManager} from "pancake-v4-core/src/pool-cl/CLPoolManager.sol";
import {LPFeeLibrary} from "pancake-v4-core/src/libraries/LPFeeLibrary.sol";
import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "pancake-v4-core/src/types/BeforeSwapDelta.sol";
import {CLBaseHook} from "../CLBaseHook.sol";

contract SampleCLDynamicFeeHook is CLBaseHook {
using PoolIdLibrary for PoolKey;

uint24 DEFAULT_LP_FEE = 3000;
uint24 FREE_LP_FEE = 0;

bool enableLPFeeOverride = false;

constructor(ICLPoolManager poolManager) CLBaseHook(poolManager) {}

function toggleLPFeeOverride() external {
enableLPFeeOverride = !enableLPFeeOverride;
}

function setDynamicLpFee(PoolKey memory key, uint24 fee) public {
poolManager.updateDynamicLPFee(key, fee);
}

function getHooksRegistrationBitmap() external pure override returns (uint16) {
return _hooksRegistrationBitmapFrom(
Permissions({
beforeInitialize: false,
afterInitialize: true,
beforeAddLiquidity: false,
afterAddLiquidity: false,
beforeRemoveLiquidity: false,
afterRemoveLiquidity: false,
beforeSwap: true,
afterSwap: false,
beforeDonate: false,
afterDonate: false,
beforeSwapReturnsDelta: false,
afterSwapReturnsDelta: false,
afterAddLiquidiyReturnsDelta: false,
afterRemoveLiquidiyReturnsDelta: false
})
);
}

function afterInitialize(
address sender,
PoolKey calldata key,
uint160 sqrtPriceX96,
int24 tick,
bytes calldata hookData
) external override returns (bytes4) {
setDynamicLpFee(key, DEFAULT_LP_FEE);
return this.beforeInitialize.selector;
}

function beforeSwap(
address sender,
PoolKey calldata key,
ICLPoolManager.SwapParams calldata params,
bytes calldata hookData
) external override returns (bytes4, BeforeSwapDelta, uint24) {
// if enableLPFeeOverride, the lp fee for the ongoing swap will be 0
if (enableLPFeeOverride) {
return (
this.beforeSwap.selector,
BeforeSwapDeltaLibrary.ZERO_DELTA,
LPFeeLibrary.OVERRIDE_FEE_FLAG & FREE_LP_FEE
);
}

return (this.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, 0);
}
}