Skip to content

Commit

Permalink
feat: add sample dynamicFee hook
Browse files Browse the repository at this point in the history
  • Loading branch information
chefburger committed Aug 29, 2024
1 parent 2b85e16 commit 27d7ff6
Show file tree
Hide file tree
Showing 5 changed files with 231 additions and 0 deletions.
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();
}
}
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);
}
}

0 comments on commit 27d7ff6

Please sign in to comment.