@@ -27,6 +27,7 @@ import {BalanceDelta} from "../src/types/BalanceDelta.sol";
2727import {BinTestHelper} from "./pool-bin/helpers/BinTestHelper.sol " ;
2828import {BinSwapHelper} from "./pool-bin/helpers/BinSwapHelper.sol " ;
2929import {BinLiquidityHelper} from "./pool-bin/helpers/BinLiquidityHelper.sol " ;
30+ import {HooksContract} from "./libraries/Hooks/HooksContract.sol " ;
3031
3132contract ProtocolFeeControllerTest is Test , BinTestHelper , TokenFixture {
3233 using CLPoolParametersHelper for bytes32 ;
@@ -43,6 +44,8 @@ contract ProtocolFeeControllerTest is Test, BinTestHelper, TokenFixture {
4344 BinSwapHelper public binSwapHelper;
4445 BinLiquidityHelper public binLiquidityHelper;
4546
47+ HooksContract public hooksContract;
48+
4649 function setUp () public {
4750 initializeTokens ();
4851
@@ -58,6 +61,8 @@ contract ProtocolFeeControllerTest is Test, BinTestHelper, TokenFixture {
5861 IERC20 (Currency.unwrap (currency1)).approve (address (binSwapHelper), 1000 ether);
5962 IERC20 (Currency.unwrap (currency0)).approve (address (binLiquidityHelper), 1000 ether);
6063 IERC20 (Currency.unwrap (currency1)).approve (address (binLiquidityHelper), 1000 ether);
64+
65+ hooksContract = new HooksContract (0 );
6166 }
6267
6368 function testOwnerTransfer () public {
@@ -90,6 +95,32 @@ contract ProtocolFeeControllerTest is Test, BinTestHelper, TokenFixture {
9095 assertEq (controller.owner (), makeAddr ("newOwner " ));
9196 }
9297
98+ function testSetDefaultProtocolFeeForDynamicFeePool (uint24 newDefaultProtocolFeeForDynamicFeePool ) public {
99+ ProtocolFeeController controller = new ProtocolFeeController (address (clPoolManager));
100+
101+ // it should start with 0.3% as default
102+ assertEq (controller.defaultProtocolFeeForDynamicFeePool (), 3000 );
103+
104+ {
105+ // must from owner
106+ vm.prank (makeAddr ("someone " ));
107+ vm.expectRevert (abi.encodeWithSelector (Ownable.OwnableUnauthorizedAccount.selector , makeAddr ("someone " )));
108+ controller.setDefaultProtocolFeeForDynamicFeePool (newDefaultProtocolFeeForDynamicFeePool);
109+ }
110+
111+ if (newDefaultProtocolFeeForDynamicFeePool > ProtocolFeeLibrary.MAX_PROTOCOL_FEE) {
112+ vm.expectRevert (ProtocolFeeController.InvalidDefaultProtocolFeeForDynamicFeePool.selector );
113+ controller.setDefaultProtocolFeeForDynamicFeePool (newDefaultProtocolFeeForDynamicFeePool);
114+ } else {
115+ vm.expectEmit (true , true , true , true );
116+ emit ProtocolFeeController.DefaultProtocolFeeForDynamicFeePoolUpdated (
117+ 3000 , newDefaultProtocolFeeForDynamicFeePool
118+ );
119+ controller.setDefaultProtocolFeeForDynamicFeePool (newDefaultProtocolFeeForDynamicFeePool);
120+ assertEq (controller.defaultProtocolFeeForDynamicFeePool (), newDefaultProtocolFeeForDynamicFeePool);
121+ }
122+ }
123+
93124 function testSetProcotolFeeSplitRatio (uint256 newProtocolFeeSplitRatio ) public {
94125 ProtocolFeeController controller = new ProtocolFeeController (address (clPoolManager));
95126
@@ -363,6 +394,104 @@ contract ProtocolFeeControllerTest is Test, BinTestHelper, TokenFixture {
363394 }
364395 }
365396
397+ function testCLDynamicPoolInitWithProtolFeeControllerFuzz (uint24 newDefaultProtocolFeeForDynamicFeePool ) public {
398+ ProtocolFeeController controller = new ProtocolFeeController (address (clPoolManager));
399+ newDefaultProtocolFeeForDynamicFeePool =
400+ uint24 (bound (newDefaultProtocolFeeForDynamicFeePool, 0 , ProtocolFeeLibrary.MAX_PROTOCOL_FEE));
401+
402+ clPoolManager.setProtocolFeeController (controller);
403+
404+ PoolKey memory key = PoolKey ({
405+ currency0: currency0,
406+ currency1: currency1,
407+ hooks: hooksContract,
408+ poolManager: clPoolManager,
409+ fee: LPFeeLibrary.DYNAMIC_FEE_FLAG,
410+ parameters: bytes32 (0 ).setTickSpacing (10 )
411+ });
412+ clPoolManager.initialize (key, Constants.SQRT_RATIO_1_1);
413+
414+ (,, uint24 actualProtocolFee ,) = clPoolManager.getSlot0 (key.toId ());
415+
416+ // under default rule protocol fee must be equal for both directions
417+ uint16 protocolFeeZeroForOne = actualProtocolFee.getZeroForOneFee ();
418+ uint16 protocolFeeOneForZero = actualProtocolFee.getOneForZeroFee ();
419+ assertEq (protocolFeeOneForZero, protocolFeeZeroForOne);
420+ assertEq (protocolFeeOneForZero, 3000 );
421+
422+ controller.setDefaultProtocolFeeForDynamicFeePool (newDefaultProtocolFeeForDynamicFeePool);
423+
424+ key.parameters = bytes32 (0 ).setTickSpacing (30 );
425+ clPoolManager.initialize (key, Constants.SQRT_RATIO_1_1);
426+
427+ (,, actualProtocolFee,) = clPoolManager.getSlot0 (key.toId ());
428+ // under default rule protocol fee must be equal for both directions
429+ protocolFeeZeroForOne = actualProtocolFee.getZeroForOneFee ();
430+ protocolFeeOneForZero = actualProtocolFee.getOneForZeroFee ();
431+ assertEq (protocolFeeOneForZero, protocolFeeZeroForOne);
432+ assertEq (protocolFeeOneForZero, newDefaultProtocolFeeForDynamicFeePool);
433+
434+ // verify the original pool is not affected
435+ {
436+ key.parameters = bytes32 (0 ).setTickSpacing (10 );
437+
438+ (,, actualProtocolFee,) = clPoolManager.getSlot0 (key.toId ());
439+ // under default rule protocol fee must be equal for both directions
440+ protocolFeeZeroForOne = actualProtocolFee.getZeroForOneFee ();
441+ protocolFeeOneForZero = actualProtocolFee.getOneForZeroFee ();
442+ assertEq (protocolFeeOneForZero, protocolFeeZeroForOne);
443+ }
444+ }
445+
446+ function testBinDynamicPoolInitWithProtolFeeControllerFuzz (uint24 newDefaultProtocolFeeForDynamicFeePool ) public {
447+ ProtocolFeeController controller = new ProtocolFeeController (address (binPoolManager));
448+ newDefaultProtocolFeeForDynamicFeePool =
449+ uint24 (bound (newDefaultProtocolFeeForDynamicFeePool, 0 , ProtocolFeeLibrary.MAX_PROTOCOL_FEE));
450+
451+ binPoolManager.setProtocolFeeController (controller);
452+
453+ PoolKey memory key = PoolKey ({
454+ currency0: currency0,
455+ currency1: currency1,
456+ hooks: hooksContract,
457+ poolManager: binPoolManager,
458+ fee: LPFeeLibrary.DYNAMIC_FEE_FLAG,
459+ parameters: bytes32 (0 ).setBinStep (1 )
460+ });
461+ binPoolManager.initialize (key, ID_ONE);
462+
463+ (, uint24 actualProtocolFee ,) = binPoolManager.getSlot0 (key.toId ());
464+
465+ // under default rule protocol fee must be equal for both directions
466+ uint16 protocolFeeZeroForOne = actualProtocolFee.getZeroForOneFee ();
467+ uint16 protocolFeeOneForZero = actualProtocolFee.getOneForZeroFee ();
468+ assertEq (protocolFeeOneForZero, protocolFeeZeroForOne);
469+ assertEq (protocolFeeOneForZero, 3000 );
470+
471+ controller.setDefaultProtocolFeeForDynamicFeePool (newDefaultProtocolFeeForDynamicFeePool);
472+
473+ key.parameters = bytes32 (0 ).setBinStep (5 );
474+ binPoolManager.initialize (key, ID_ONE);
475+
476+ (, actualProtocolFee,) = binPoolManager.getSlot0 (key.toId ());
477+ // under default rule protocol fee must be equal for both directions
478+ protocolFeeZeroForOne = actualProtocolFee.getZeroForOneFee ();
479+ protocolFeeOneForZero = actualProtocolFee.getOneForZeroFee ();
480+ assertEq (protocolFeeOneForZero, protocolFeeZeroForOne);
481+ assertEq (protocolFeeOneForZero, newDefaultProtocolFeeForDynamicFeePool);
482+
483+ // verify the original pool is not affected
484+ {
485+ key.parameters = bytes32 (0 ).setBinStep (1 );
486+
487+ (, actualProtocolFee,) = binPoolManager.getSlot0 (key.toId ());
488+ // under default rule protocol fee must be equal for both directions
489+ protocolFeeZeroForOne = actualProtocolFee.getZeroForOneFee ();
490+ protocolFeeOneForZero = actualProtocolFee.getOneForZeroFee ();
491+ assertEq (protocolFeeOneForZero, protocolFeeZeroForOne);
492+ }
493+ }
494+
366495 function testSetProtocolFeeForCLPool (uint24 newProtocolFee ) public {
367496 ProtocolFeeController controller = new ProtocolFeeController (address (clPoolManager));
368497 clPoolManager.setProtocolFeeController (controller);
0 commit comments