Skip to content

Commit

Permalink
feat: resolve issues and add test cases per comment
Browse files Browse the repository at this point in the history
  • Loading branch information
chefburger committed Nov 28, 2024
1 parent 2bbabf3 commit c0dd734
Showing 1 changed file with 89 additions and 2 deletions.
91 changes: 89 additions & 2 deletions test/ProtocolFeeController.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,16 @@ import {IProtocolFees} from "../src/interfaces/IProtocolFees.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {CLPoolManagerRouter} from "../test/pool-cl/helpers/CLPoolManagerRouter.sol";
import {ICLPoolManager} from "../src/pool-cl/interfaces/ICLPoolManager.sol";
import {IBinPoolManager} from "../src/pool-bin/interfaces/IBinPoolManager.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {Currency} from "../src/types/Currency.sol";
import {TickMath} from "../src/pool-cl/libraries/TickMath.sol";
import {BalanceDelta} from "../src/types/BalanceDelta.sol";
import {BinTestHelper} from "./pool-bin/helpers/BinTestHelper.sol";
import {BinSwapHelper} from "./pool-bin/helpers/BinSwapHelper.sol";
import {BinLiquidityHelper} from "./pool-bin/helpers/BinLiquidityHelper.sol";

contract ProtocolFeeControllerTest is TokenFixture, Test {
contract ProtocolFeeControllerTest is Test, BinTestHelper, TokenFixture {
using CLPoolParametersHelper for bytes32;
using BinPoolParametersHelper for bytes32;
using ProtocolFeeLibrary for *;
Expand All @@ -33,14 +37,24 @@ contract ProtocolFeeControllerTest is TokenFixture, Test {
CLPoolManager clPoolManager;
BinPoolManager binPoolManager;

BinSwapHelper public binSwapHelper;
BinLiquidityHelper public binLiquidityHelper;

function setUp() public {
initializeTokens();

vault = new Vault();
clPoolManager = new CLPoolManager(vault);
binPoolManager = new BinPoolManager(vault);
vault.registerApp(address(clPoolManager));
vault.registerApp(address(binPoolManager));

initializeTokens();
binSwapHelper = new BinSwapHelper(binPoolManager, vault);
binLiquidityHelper = new BinLiquidityHelper(binPoolManager, vault);
IERC20(Currency.unwrap(currency0)).approve(address(binSwapHelper), 1000 ether);
IERC20(Currency.unwrap(currency1)).approve(address(binSwapHelper), 1000 ether);
IERC20(Currency.unwrap(currency0)).approve(address(binLiquidityHelper), 1000 ether);
IERC20(Currency.unwrap(currency1)).approve(address(binLiquidityHelper), 1000 ether);
}

function testOwnerTransfer() public {
Expand Down Expand Up @@ -241,6 +255,9 @@ contract ProtocolFeeControllerTest is TokenFixture, Test {
100 ether * uint256(actualProtocolFee >> 12) / controller.ONE_HUNDRED_PERCENT_RATIO()
);

// lp fee should be roughly 0.1 ether, allow 2% error
assertApproxEqAbs(clPoolManager.protocolFeesAccrued(currency0), 0.1 ether, 0.1 ether / 50);

// check lp fee is twice the protocol fee
(, BalanceDelta accumulatedLPFee) = router.modifyPosition(
key,
Expand Down Expand Up @@ -280,6 +297,76 @@ contract ProtocolFeeControllerTest is TokenFixture, Test {
assertEq(IERC20(Currency.unwrap(currency0)).balanceOf(makeAddr("recipient")), protocolFeeAmount);
}

function testCollectProtocolFeeForBinPool() public {
// init protocol fee controller and bind it to binPoolManager
ProtocolFeeController controller = new ProtocolFeeController(address(binPoolManager));
binPoolManager.setProtocolFeeController(controller);
// make protocol fee half of the total fee
controller.setProtocolFeeSplitRatio(500000);

// init pool with protocol fee controller
PoolKey memory key = PoolKey({
currency0: currency0,
currency1: currency1,
hooks: IHooks(address(0)),
poolManager: binPoolManager,
fee: 2000,
parameters: bytes32(0).setBinStep(1)
});
binPoolManager.initialize(key, ID_ONE);

(, uint24 actualProtocolFee,) = binPoolManager.getSlot0(key.toId());

// add some liquidity
IBinPoolManager.MintParams memory mintParams = _getSingleBinMintParams(ID_ONE, 500 ether, 500 ether);
binLiquidityHelper.mint(key, mintParams, abi.encode(0));

// swap to generate protocol fee
// splitRatio=50% so that protcol fee should be half of the total fee
binSwapHelper.swap(key, true, -int128(100 ether), BinSwapHelper.TestSettings(true, true), "");

assertEq(
binPoolManager.protocolFeesAccrued(currency0),
100 ether * uint256(actualProtocolFee >> 12) / controller.ONE_HUNDRED_PERCENT_RATIO()
);

// lp fee should be roughly 0.2 ether
assertApproxEqAbs(binPoolManager.protocolFeesAccrued(currency0), 0.2 ether, 0.2 ether / 100);

// check lp fee equals to the protocol fee
IBinPoolManager.BurnParams memory burnParams =
_getSingleBinBurnLiquidityParams(key, binPoolManager, ID_ONE, address(binLiquidityHelper), 100);
BalanceDelta delta = binLiquidityHelper.burn(key, burnParams, "");

assertApproxEqAbs(
binPoolManager.protocolFeesAccrued(currency0) * 2,
// amt1 out roughly 100 ether, but the actual output amount is less due to fee and init liquidity lock
// since no slippage within a given bin, we can calculate the total fee as follows:
uint256(int256(delta.amount1() - 400 ether)),
// we know total fee is roughly 0.4 ether, let's say error caused by init liqudity lock is less than 1%
0.4 ether / 100
);

// collect protocol fee
{
vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, makeAddr("someone")));
vm.prank(makeAddr("someone"));
controller.collectProtocolFee(makeAddr("recipient"), currency0, 0);
}

// collect half
uint256 protocolFeeAmount = binPoolManager.protocolFeesAccrued(currency0);
controller.collectProtocolFee(makeAddr("recipient"), currency0, protocolFeeAmount / 2);

assertEq(binPoolManager.protocolFeesAccrued(currency0), protocolFeeAmount / 2);
assertEq(IERC20(Currency.unwrap(currency0)).balanceOf(makeAddr("recipient")), protocolFeeAmount / 2);

// collect the rest
controller.collectProtocolFee(makeAddr("recipient"), currency0, 0);
assertEq(binPoolManager.protocolFeesAccrued(currency0), 0);
assertEq(IERC20(Currency.unwrap(currency0)).balanceOf(makeAddr("recipient")), protocolFeeAmount);
}

function _calculateLPFeeThreshold(ProtocolFeeController controller) internal view returns (uint24) {
return uint24(
(
Expand Down

0 comments on commit c0dd734

Please sign in to comment.