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

fix ticks #64

Merged
merged 11 commits into from
Sep 12, 2024
4 changes: 2 additions & 2 deletions arguments.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ module.exports = [
bonusTargetReach: "50000000000000000n",
bonusPartyCreator: "100000000000000000",
targetReachFee: "850000000000000000",
partyTicks: { tickLower: "-214200", tickUpper: "195600" },
lpTicks: { tickLower: "-214200", tickUpper: "201400" }
partyTicks: { tickLower: "-195600", tickUpper: "214200" },
lpTicks: { tickLower: "-201400", tickUpper: "214200" }
},
"0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd",
"0xFe3355feD445709971277BC3842E0f581Bf4146b"
Expand Down
4 changes: 2 additions & 2 deletions contracts/BNBPartyCreation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ abstract contract BNBPartyCreation is BNBPartySwaps {
/// @return liquidityPool Address of the newly created liquidity pool
/// @dev Sets the token amounts based on the balance and initializes the pool
function _createFLP(address _token) internal returns (address liquidityPool) {
(address token0, address token1, uint160 sqrtPrice) = _getTokenPairAndPrice(_token);
(address token0, address token1, uint160 sqrtPrice, Ticks memory ticks) = _getTokenPairAndPrice(_token);
// Determine the token amounts
(uint256 amount0, uint256 amount1) = _calculateAmounts(token0);
IERC20(_token).safeIncreaseAllowance(address(BNBPositionManager), party.initialTokenAmount);
Expand All @@ -26,7 +26,7 @@ abstract contract BNBPartyCreation is BNBPartySwaps {
amount1,
sqrtPrice,
party.partyLpFee,
party.partyTicks
ticks
);
isParty[liquidityPool] = true; // Mark the liquidity pool as a party pool
isTokenOnPartyLP[_token] = true; // Mark the token as part of the party LP
Expand Down
51 changes: 43 additions & 8 deletions contracts/BNBPartyFee.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ abstract contract BNBPartyFee is BNBPartyModifiers {
uint256 feeGrowthInside1LastX128
)
{
Ticks memory ticks = _getTicks(pool.token0(), party.lpTicks);
(
feeGrowthInside0LastX128,
feeGrowthInside1LastX128
Expand All @@ -29,8 +30,8 @@ abstract contract BNBPartyFee is BNBPartyModifiers {
keccak256(
abi.encodePacked(
address(positionManager),
party.lpTicks.tickLower,
party.lpTicks.tickUpper
ticks.tickLower,
ticks.tickUpper
)
)
);
Expand All @@ -48,6 +49,7 @@ abstract contract BNBPartyFee is BNBPartyModifiers {
uint256 feeGrowthInside1LastX128
)
{
Ticks memory ticks = _getTicks(pool.token0(), party.partyTicks);
(
feeGrowthInside0LastX128,
feeGrowthInside1LastX128
Expand All @@ -56,8 +58,8 @@ abstract contract BNBPartyFee is BNBPartyModifiers {
keccak256(
abi.encodePacked(
address(BNBPositionManager),
party.partyTicks.tickLower,
party.partyTicks.tickUpper
ticks.tickLower,
ticks.tickUpper
)
)
);
Expand All @@ -81,13 +83,46 @@ abstract contract BNBPartyFee is BNBPartyModifiers {

/// @notice Internal function to calculate the global fee growth
/// @param pool Address of the Uniswap V3 pool
function _calculateFeeGrowthGlobal(IUniswapV3Pool pool) internal view returns (uint256 feeGrowthGlobal) {
function _calculateFeeGrowthGlobal(
IUniswapV3Pool pool
) internal view returns (uint256 feeGrowthGlobal) {
if (pool.token0() == address(WBNB)) {
(uint256 feeGrowthInside0LastX128,) = _getPartyFeeGrowthInsideLastX128(pool);
feeGrowthGlobal = pool.feeGrowthGlobal0X128() - feeGrowthInside0LastX128;
(uint256 feeGrowthInside0LastX128 , ) = _getPartyFeeGrowthInsideLastX128(pool);
feeGrowthGlobal = pool.feeGrowthGlobal0X128() -feeGrowthInside0LastX128;
} else {
(,uint256 feeGrowthInside1LastX128) = _getPartyFeeGrowthInsideLastX128(pool);
( , uint256 feeGrowthInside1LastX128) = _getPartyFeeGrowthInsideLastX128(pool);
feeGrowthGlobal = pool.feeGrowthGlobal1X128() - feeGrowthInside1LastX128;
}
}

/// @notice Invert the ticks
/// @param tickLower Lower tick
/// @param tickUpper Upper tick
/// @return ticks struct with inverted ticks
function _invertTicks(
int24 tickLower,
int24 tickUpper
) internal pure returns (Ticks memory ticks) {
ticks.tickLower = -tickUpper;
ticks.tickUpper = -tickLower;
}

/// @notice Internal function to retrieve the Ticks based on the token address
/// @param token0 Address of the token0
/// @param ticks The Ticks struct with lower and upper ticks
/// @return adjustedTicks The Ticks struct adjusted based on token address
function _getTicks(
address token0,
Ticks memory ticks
)
internal
view
returns (Ticks memory adjustedTicks)
{
if (address(WBNB) == token0) {
adjustedTicks = _invertTicks(ticks.tickLower, ticks.tickUpper);
} else {
adjustedTicks = ticks;
}
}
}
4 changes: 2 additions & 2 deletions contracts/BNBPartyLiquidity.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ abstract contract BNBPartyLiquidity is BNBPartyLiquidityHelper {
newSqrtPriceX96 = sqrtPriceCalculator.getNextSqrtPriceFromAmount1RoundingDown(
sqrtPriceX96,
liquidity,
unwrapAmount / 2,
unwrapAmount,
false
);
}
Expand All @@ -47,7 +47,7 @@ abstract contract BNBPartyLiquidity is BNBPartyLiquidityHelper {
IERC20(token0).safeIncreaseAllowance(address(positionManager), amount0);
IERC20(token1).safeIncreaseAllowance(address(positionManager), amount1);
// Create new Liquidity Pool
_createLP(positionManager, token0, token1, amount0, amount1, newSqrtPriceX96, party.lpFee, party.lpTicks);
_createLP(positionManager, token0, token1, amount0, amount1, newSqrtPriceX96, party.lpFee, _getTicks(token0, party.lpTicks));

// Send bonuses
_unwrapAndSendBNB(recipient, unwrapAmount);
Expand Down
7 changes: 4 additions & 3 deletions contracts/BNBPartySwaps.sol
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,14 @@ abstract contract BNBPartySwaps is BNBPartyView {
/// @return token0 Address of the first token in the pair
/// @return token1 Address of the second token in the pair
/// @return sqrtPriceX96 The sqrt price of the token pair
/// @return ticks The ticks for the token pair
function _getTokenPairAndPrice(
address _token
) internal view returns (address token0, address token1, uint160 sqrtPriceX96) {
) internal view returns (address token0, address token1, uint160 sqrtPriceX96, Ticks memory ticks) {
if (_token < address(WBNB)) {
return (_token, address(WBNB), party.sqrtPriceX96);
return (_token, address(WBNB), party.sqrtPriceX96, Ticks(party.partyTicks.tickLower, party.partyTicks.tickUpper));
} else {
return (address(WBNB), _token, _reverseSqrtPrice(party.sqrtPriceX96));
return (address(WBNB), _token, _reverseSqrtPrice(party.sqrtPriceX96), _invertTicks(party.partyTicks.tickLower, party.partyTicks.tickUpper));
}
}

Expand Down
2 changes: 1 addition & 1 deletion hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const LOW_OPTIMIZER_COMPILER_SETTINGS = {
}

const BNB_FACTORY_COMPILER_SETTINGS = {
version: "0.8.24",
version: "0.8.25",
settings: {
evmVersion: "istanbul",
optimizer: {
Expand Down
4 changes: 2 additions & 2 deletions scripts/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ async function main() {
bonusTargetReach: returnFeeAmount,
bonusPartyCreator: bonusFee,
targetReachFee: targetReachFee,
partyTicks: { tickLower: "-214200", tickUpper: "195600" },
lpTicks: { tickLower: "-214200", tickUpper: "201400" }
partyTicks: { tickLower: "-195600", tickUpper: "214200" },
lpTicks: { tickLower: "-201400", tickUpper: "214200" }
},
tWBNB,
await sqrtPriceCalculator.getAddress()
Expand Down
4 changes: 2 additions & 2 deletions test/BNBPartyFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ describe("BNBPartyFactory", function () {
expect((await bnbPartyFactory.party()).lpFee).to.equal(FeeAmount.HIGH)
expect((await bnbPartyFactory.party()).partyLpFee).to.equal(FeeAmount.HIGH)
expect((await bnbPartyFactory.party()).createTokenFee).to.equal(tokenCreationFee)
expect((await bnbPartyFactory.party()).partyTicks.tickUpper).to.equal("195600")
expect((await bnbPartyFactory.party()).partyTicks.tickLower).to.equal("-214200")
expect((await bnbPartyFactory.party()).partyTicks.tickUpper).to.equal("214200")
expect((await bnbPartyFactory.party()).partyTicks.tickLower).to.equal("-195600")
})

it("should create party LP", async function () {
Expand Down
8 changes: 4 additions & 4 deletions test/WithdrawFee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ describe("Withdraw fees", function () {
const partyLP = await v3PartyFactory.getPool(await wbnb.getAddress(), MEME, FeeAmount.HIGH)
await bnbPartyFactory.withdrawPartyLPFee([partyLP])
const balanceAfter = await wbnb.balanceOf(await signers[0].getAddress())
expect(balanceAfter).to.be.equal(balanceBefore + expectedFee)
expect(balanceAfter).to.be.equal(balanceBefore + expectedFee - 1n)
})

it("should return zero if pool is zero address", async () => {
Expand All @@ -68,11 +68,11 @@ describe("Withdraw fees", function () {
it("should return fee from second lp", async () => {
await bnbPartyFactory.joinParty(MEME, 0, { value: BNBToTarget }) // create second lp
await bnbPartyFactory.joinParty(MEME, 0, { value: ethers.parseEther("1") }) // make swap for fee
const secondLP = await v3Factory.getPool(MEME, await wbnb.getAddress(), FeeAmount.HIGH)
const secondLP = await v3Factory.getPool(await wbnb.getAddress(), MEME, FeeAmount.HIGH)
const lpPool = (await ethers.getContractAt("UniswapV3Pool", secondLP)) as any as IUniswapV3Pool
const token0 = await lpPool.token0()
await bnbPartyFactory.withdrawLPFee([secondLP])
const collectedFee = await bnbPartyFactory.getFeeGrowthInsideLastX128(secondLP, positionManager)
const collectedFee = await bnbPartyFactory.getFeeGrowthInsideLastX128(secondLP, await positionManager.getAddress())
const fee = collectedFee.feeGrowthInside0LastX128 == 0n ? collectedFee.feeGrowthInside1LastX128 : collectedFee.feeGrowthInside0LastX128
if (token0 == (await wbnb.getAddress())) {
const feeGrowthGlobalX128 = await lpPool.feeGrowthGlobal0X128()
Expand Down Expand Up @@ -119,7 +119,7 @@ describe("Withdraw fees", function () {
(await lpPool.feeGrowthGlobal0X128()) > 0
? await lpPool.feeGrowthGlobal0X128()
: await lpPool.feeGrowthGlobal1X128()
expect(await bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobalX128)).to.be.equal(amountIn / 20n) // 1 % fee
expect(await bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobalX128)).to.be.equal(amountIn / 20n - 1n) // 1 % fee
})

it("isToken0WBNB should return true if token0 is WBNB", async () => {
Expand Down
8 changes: 4 additions & 4 deletions test/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ export async function deployContracts(partyTarget = ethers.parseEther("90"), wbn
bonusTargetReach: returnFeeAmount,
bonusPartyCreator: bonusFee,
targetReachFee: targetReachFee,
partyTicks: { tickLower: "-214200", tickUpper: "195600" },
lpTicks: { tickLower: "-214200", tickUpper: "201400" },
partyTicks: { tickLower: "-195600", tickUpper: "214200" },
lpTicks: { tickLower: "-201400", tickUpper: "214200" }
},
wbnbAddress,
await sqrtPriceCalculator.getAddress()
Expand Down Expand Up @@ -145,8 +145,8 @@ export async function deployBNBPartyFactory(
bonusTargetReach: returnFeeAmount,
bonusPartyCreator: bonusFee,
targetReachFee: targetReachFee,
partyTicks: { tickLower: "-214200", tickUpper: "195600" },
lpTicks: { tickLower: "-214200", tickUpper: "201400" },
partyTicks: { tickLower: "-195600", tickUpper: "214200" },
lpTicks: { tickLower: "-201400", tickUpper: "214200" }
},
WBNB,
sqrtPriceCalculator
Expand Down