From 6b4f591a1933dc454cf938c5980eea9eb90bf236 Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Mon, 2 Sep 2024 15:03:03 +0300 Subject: [PATCH 1/7] add more tests --- test/BNBPartyFactory.ts | 99 +++++++++++++++++++++++++++++++++++++++++ test/WithdrawFee.ts | 23 +++++----- test/helper.ts | 43 ++++++++++++++++-- 3 files changed, 151 insertions(+), 14 deletions(-) diff --git a/test/BNBPartyFactory.ts b/test/BNBPartyFactory.ts index 3d21235..f75cc1e 100644 --- a/test/BNBPartyFactory.ts +++ b/test/BNBPartyFactory.ts @@ -13,6 +13,7 @@ import { BNBSwapRouter, weth9, deployContracts, + deployBNBPartyFactory, } from "./helper" const POOL_BYTECODE_HASH = keccak256(bytecode) @@ -79,6 +80,104 @@ describe("BNBPartyFactory", function () { expect(balanceAfter).to.be.equal(balanceBefore + tokenCreationFee) }) + it("should revert WBNB zero address", async function () { + const sqrtAddress = "0x0000000000000000000000000000000000000001" + await expect( + deployBNBPartyFactory( + partyTarget, + tokenCreationFee, + returnFeeAmount, + bonusFee, + targetReachFee, + initialTokenAmount, + sqrtPriceX96, + ethers.ZeroAddress, + sqrtAddress + ) + ).to.be.revertedWithCustomError(bnbPartyFactory, "ZeroAddress") + }) + + it("should revert sqrtPriceCalculator zero address", async function () { + const WBNB = "0x0000000000000000000000000000000000000001" + await expect( + deployBNBPartyFactory( + partyTarget, + tokenCreationFee, + returnFeeAmount, + bonusFee, + targetReachFee, + initialTokenAmount, + sqrtPriceX96, + WBNB, + ethers.ZeroAddress + ) + ).to.be.revertedWithCustomError(bnbPartyFactory, "ZeroAddress") + }) + + it("should revert zero target", async function () { + await expect( + deployBNBPartyFactory( + 0n, + tokenCreationFee, + returnFeeAmount, + bonusFee, + targetReachFee, + initialTokenAmount, + sqrtPriceX96, + await weth9.getAddress(), + await v3Factory.getAddress() + ) + ).to.be.revertedWithCustomError(bnbPartyFactory, "ZeroAmount") + }) + + it("should revert zero initialTokenAmount", async function () { + await expect( + deployBNBPartyFactory( + partyTarget, + tokenCreationFee, + returnFeeAmount, + bonusFee, + targetReachFee, + "0", + sqrtPriceX96, + await weth9.getAddress(), + await v3Factory.getAddress() + ) + ).to.be.revertedWithCustomError(bnbPartyFactory, "ZeroAmount") + }) + + it("should revert zero sqrtPriceX96", async function () { + await expect( + deployBNBPartyFactory( + partyTarget, + tokenCreationFee, + returnFeeAmount, + bonusFee, + targetReachFee, + initialTokenAmount, + "0", + await weth9.getAddress(), + await v3Factory.getAddress() + ) + ).to.be.revertedWithCustomError(bnbPartyFactory, "ZeroAmount") + }) + + it("should revert if target is less than fees", async function () { + await expect( + deployBNBPartyFactory( + bonusFee, + tokenCreationFee, + returnFeeAmount, + bonusFee, + targetReachFee, + initialTokenAmount, + sqrtPriceX96, + await weth9.getAddress(), + await v3Factory.getAddress() + ) + ).to.be.revertedWithCustomError(bnbPartyFactory, "BonusGreaterThanTarget") + }) + it("should revert if not enough BNB is sent", async function () { await expect( bnbPartyFactory.createParty(name, symbol, { value: tokenCreationFee - 1n }) diff --git a/test/WithdrawFee.ts b/test/WithdrawFee.ts index bcd96c5..13b48e9 100644 --- a/test/WithdrawFee.ts +++ b/test/WithdrawFee.ts @@ -2,14 +2,7 @@ import { expect } from "chai" import { ethers } from "hardhat" import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" import { IUniswapV3Pool, MockContract } from "../typechain-types" -import { - FeeAmount, - bnbPartyFactory, - v3PartyFactory, - BNBPositionManager, - weth9, - deployContracts, -} from "./helper" +import { FeeAmount, bnbPartyFactory, v3PartyFactory, BNBPositionManager, weth9, deployContracts } from "./helper" describe("Withdraw fees", function () { let MEME: string @@ -63,7 +56,15 @@ describe("Withdraw fees", function () { const partyLP = await v3PartyFactory.getPool(await weth9.getAddress(), MEME, FeeAmount.HIGH) await bnbPartyFactory.withdrawPartyLPFee([partyLP]) const balanceAfter = await weth9.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 () => { + expect(await bnbPartyFactory.getFeeGrowthInsideLastX128(ethers.ZeroAddress, BNBPositionManager)).to.be.deep.equal([ 0n, 0n ]) + }) + + it("should return zero if position manager is zero address", async () => { + expect(await bnbPartyFactory.getFeeGrowthInsideLastX128(lpAddress, ethers.ZeroAddress)).to.be.deep.equal([0n, 0n]) }) it("should revert LPNotAtParty", async () => { @@ -102,8 +103,8 @@ describe("Withdraw fees", function () { expect(await bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobalX128)).to.be.equal(amountIn / 20n - 1n) // 1 % fee }) - it("isToken0WBNB should return false if token0 is not WBNB", async () => { - expect(await bnbPartyFactory.isToken0WBNB(lpAddress)).to.be.false + it("isToken0WBNB should return true if token0 is WBNB", async () => { + expect(await bnbPartyFactory.isToken0WBNB(lpAddress)).to.be.true }) it("isToken0WBNB should revert if set zero address", async () => { diff --git a/test/helper.ts b/test/helper.ts index f54fd60..22822db 100644 --- a/test/helper.ts +++ b/test/helper.ts @@ -63,7 +63,7 @@ export async function deployContracts(partyTarget = ethers.parseEther("90")) { bonusPartyCreator: bonusFee, targetReachFee: targetReachFee, partyTicks: { tickLower: "-214200", tickUpper: "195600" }, - lpTicks: { tickLower: "-214200", tickUpper: "201400" } + lpTicks: { tickLower: "-214200", tickUpper: "201400" }, }, await weth9.getAddress(), await sqrtPriceCalculator.getAddress() @@ -71,7 +71,10 @@ export async function deployContracts(partyTarget = ethers.parseEther("90")) { // Deploy Uniswap V3 Factory const v3PartyFactoryContract = await ethers.getContractFactory(FactoryArtifact.abi, FactoryArtifact.bytecode) - const v3FactoryContract = await ethers.getContractFactory(ClassicFactoryArtifact.abi, ClassicFactoryArtifact.bytecode) + const v3FactoryContract = await ethers.getContractFactory( + ClassicFactoryArtifact.abi, + ClassicFactoryArtifact.bytecode + ) v3Factory = (await v3FactoryContract.deploy()) as UniswapV3Factory v3PartyFactory = (await v3PartyFactoryContract.deploy(await bnbPartyFactory.getAddress())) as UniswapV3Factory @@ -81,7 +84,10 @@ export async function deployContracts(partyTarget = ethers.parseEther("90")) { tokenPositionDescriptor = (await TokenPositionDescriptor.deploy()) as MockNonfungibleTokenPositionDescriptor // Deploy Position Manager - const ManagerContract = await ethers.getContractFactory(ClassicNonfungiblePositionManager.abi, ClassicNonfungiblePositionManager.bytecode) + const ManagerContract = await ethers.getContractFactory( + ClassicNonfungiblePositionManager.abi, + ClassicNonfungiblePositionManager.bytecode + ) positionManager = (await ManagerContract.deploy( await v3Factory.getAddress(), await weth9.getAddress(), @@ -114,3 +120,34 @@ export async function deployContracts(partyTarget = ethers.parseEther("90")) { await bnbPartyFactory.setBNBPartySwapRouter(await BNBSwapRouter.getAddress()) await bnbPartyFactory.setSwapRouter(await swapRouter.getAddress()) } + +export async function deployBNBPartyFactory( + partyTarget: bigint, + tokenCreationFee: bigint, + returnFeeAmount: bigint, + bonusFee: bigint, + targetReachFee: bigint, + initialTokenAmount: string, + sqrtPriceX96: string, + WBNB: string, + sqrtPriceCalculator: string +) { + const BNBPartyFactoryContract = await ethers.getContractFactory("BNBPartyFactory") + return BNBPartyFactoryContract.deploy( + { + partyTarget: partyTarget, + createTokenFee: tokenCreationFee, + partyLpFee: FeeAmount.HIGH, + lpFee: FeeAmount.HIGH, + initialTokenAmount: initialTokenAmount, + sqrtPriceX96: sqrtPriceX96, + bonusTargetReach: returnFeeAmount, + bonusPartyCreator: bonusFee, + targetReachFee: targetReachFee, + partyTicks: { tickLower: "-214200", tickUpper: "195600" }, + lpTicks: { tickLower: "-214200", tickUpper: "201400" }, + }, + WBNB, + sqrtPriceCalculator + ) +} From 22962b0a0da100888d4f3078be2e491b1a782239 Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Mon, 2 Sep 2024 15:41:15 +0300 Subject: [PATCH 2/7] update revert tests, add solcover --- .solcover.js | 3 + test/BNBPartyFactory.ts | 164 +--------------------------- test/WithdrawFee.ts | 9 +- test/reverts.ts | 235 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 240 insertions(+), 171 deletions(-) create mode 100644 .solcover.js create mode 100644 test/reverts.ts diff --git a/.solcover.js b/.solcover.js new file mode 100644 index 0000000..c5897f6 --- /dev/null +++ b/.solcover.js @@ -0,0 +1,3 @@ +module.exports = { + skipFiles: ['./mock'], +} \ No newline at end of file diff --git a/test/BNBPartyFactory.ts b/test/BNBPartyFactory.ts index f75cc1e..391aa76 100644 --- a/test/BNBPartyFactory.ts +++ b/test/BNBPartyFactory.ts @@ -80,131 +80,6 @@ describe("BNBPartyFactory", function () { expect(balanceAfter).to.be.equal(balanceBefore + tokenCreationFee) }) - it("should revert WBNB zero address", async function () { - const sqrtAddress = "0x0000000000000000000000000000000000000001" - await expect( - deployBNBPartyFactory( - partyTarget, - tokenCreationFee, - returnFeeAmount, - bonusFee, - targetReachFee, - initialTokenAmount, - sqrtPriceX96, - ethers.ZeroAddress, - sqrtAddress - ) - ).to.be.revertedWithCustomError(bnbPartyFactory, "ZeroAddress") - }) - - it("should revert sqrtPriceCalculator zero address", async function () { - const WBNB = "0x0000000000000000000000000000000000000001" - await expect( - deployBNBPartyFactory( - partyTarget, - tokenCreationFee, - returnFeeAmount, - bonusFee, - targetReachFee, - initialTokenAmount, - sqrtPriceX96, - WBNB, - ethers.ZeroAddress - ) - ).to.be.revertedWithCustomError(bnbPartyFactory, "ZeroAddress") - }) - - it("should revert zero target", async function () { - await expect( - deployBNBPartyFactory( - 0n, - tokenCreationFee, - returnFeeAmount, - bonusFee, - targetReachFee, - initialTokenAmount, - sqrtPriceX96, - await weth9.getAddress(), - await v3Factory.getAddress() - ) - ).to.be.revertedWithCustomError(bnbPartyFactory, "ZeroAmount") - }) - - it("should revert zero initialTokenAmount", async function () { - await expect( - deployBNBPartyFactory( - partyTarget, - tokenCreationFee, - returnFeeAmount, - bonusFee, - targetReachFee, - "0", - sqrtPriceX96, - await weth9.getAddress(), - await v3Factory.getAddress() - ) - ).to.be.revertedWithCustomError(bnbPartyFactory, "ZeroAmount") - }) - - it("should revert zero sqrtPriceX96", async function () { - await expect( - deployBNBPartyFactory( - partyTarget, - tokenCreationFee, - returnFeeAmount, - bonusFee, - targetReachFee, - initialTokenAmount, - "0", - await weth9.getAddress(), - await v3Factory.getAddress() - ) - ).to.be.revertedWithCustomError(bnbPartyFactory, "ZeroAmount") - }) - - it("should revert if target is less than fees", async function () { - await expect( - deployBNBPartyFactory( - bonusFee, - tokenCreationFee, - returnFeeAmount, - bonusFee, - targetReachFee, - initialTokenAmount, - sqrtPriceX96, - await weth9.getAddress(), - await v3Factory.getAddress() - ) - ).to.be.revertedWithCustomError(bnbPartyFactory, "BonusGreaterThanTarget") - }) - - it("should revert if not enough BNB is sent", async function () { - await expect( - bnbPartyFactory.createParty(name, symbol, { value: tokenCreationFee - 1n }) - ).to.be.revertedWithCustomError(bnbPartyFactory, "InsufficientBNB") - }) - - it("should revert to Create Party if position manager is not set", async function () { - await bnbPartyFactory.setNonfungiblePositionManager(ethers.ZeroAddress, ethers.ZeroAddress) - await expect( - bnbPartyFactory.createParty(name, symbol, { value: tokenCreationFee }) - ).to.be.revertedWithCustomError(bnbPartyFactory, "ZeroAddress") - await bnbPartyFactory.setNonfungiblePositionManager( - await BNBPositionManager.getAddress(), - await positionManager.getAddress() - ) - }) - - it("should revert if swap router is not set", async function () { - const amountIn = ethers.parseUnits("1", 18) - await bnbPartyFactory.setBNBPartySwapRouter(ethers.ZeroAddress) - await expect(bnbPartyFactory.createParty(name, symbol, { value: amountIn })).to.be.revertedWithCustomError( - bnbPartyFactory, - "ZeroAddress" - ) - await bnbPartyFactory.setBNBPartySwapRouter(await BNBSwapRouter.getAddress()) - }) - it("should set pause", async function () { await bnbPartyFactory.pause() expect(await bnbPartyFactory.paused()).to.be.true @@ -217,43 +92,6 @@ describe("BNBPartyFactory", function () { expect(await bnbPartyFactory.paused()).to.be.false }) - it("should revert party creation if paused", async function () { - await bnbPartyFactory.pause() - await expect( - bnbPartyFactory.createParty(name, symbol, { value: tokenCreationFee }) - ).to.be.revertedWithCustomError(bnbPartyFactory, "EnforcedPause") - await bnbPartyFactory.unpause() - }) - - it("should revert join party if paused", async function () { - await bnbPartyFactory.createParty(name, symbol, { value: tokenCreationFee }) - await bnbPartyFactory.pause() - const tokenId = (await BNBPositionManager.totalSupply()) - 1n - const position = await BNBPositionManager.positions(tokenId) - const MEME = position.token1 == (await weth9.getAddress()) ? position.token0 : position.token1 - await expect(bnbPartyFactory.joinParty(MEME, 0, { value: BNBToTarget })).to.be.revertedWithCustomError( - bnbPartyFactory, - "EnforcedPause" - ) - await bnbPartyFactory.unpause() - }) - - it("should revert leave party if paused", async function () { - await bnbPartyFactory.createParty(name, symbol, { value: tokenCreationFee }) - const tokenId = (await BNBPositionManager.totalSupply()) - 1n - const position = await BNBPositionManager.positions(tokenId) - const MEME = position.token1 == (await weth9.getAddress()) ? position.token0 : position.token1 - const MEMEToken = await ethers.getContractAt("ERC20Token", MEME) - await MEMEToken.approve(await bnbPartyFactory.getAddress(), ethers.parseEther("1000000")) - await bnbPartyFactory.joinParty(MEME, 0, { value: tokenCreationFee }) - await bnbPartyFactory.pause() - await expect(bnbPartyFactory.leaveParty(MEME, tokenCreationFee, 0)).to.be.revertedWithCustomError( - bnbPartyFactory, - "EnforcedPause" - ) - await bnbPartyFactory.unpause() - }) - describe("Second Liquidity Pool", function () { let MEME: string let tokenId: string @@ -296,7 +134,7 @@ describe("BNBPartyFactory", function () { const lpAddress = await v3Factory.getPool(await weth9.getAddress(), MEME, FeeAmount.HIGH) const balance = await weth9.balanceOf(lpAddress) const percentFee = ethers.parseEther("0.14") // target 13 + 1 BNB - 1% fee - expect(balance).to.be.equal(BNBToTarget - returnFeeAmount - bonusFee - targetReachFee - percentFee - 2n) + expect(balance).to.be.equal(BNBToTarget - returnFeeAmount - bonusFee - targetReachFee - percentFee - 1n) }) it("should send MEME to new LP", async () => { diff --git a/test/WithdrawFee.ts b/test/WithdrawFee.ts index 13b48e9..6c279af 100644 --- a/test/WithdrawFee.ts +++ b/test/WithdrawFee.ts @@ -56,7 +56,7 @@ describe("Withdraw fees", function () { const partyLP = await v3PartyFactory.getPool(await weth9.getAddress(), MEME, FeeAmount.HIGH) await bnbPartyFactory.withdrawPartyLPFee([partyLP]) const balanceAfter = await weth9.balanceOf(await signers[0].getAddress()) - expect(balanceAfter).to.be.equal(balanceBefore + expectedFee - 1n) + expect(balanceAfter).to.be.equal(balanceBefore + expectedFee) }) it("should return zero if pool is zero address", async () => { @@ -107,13 +107,6 @@ describe("Withdraw fees", function () { expect(await bnbPartyFactory.isToken0WBNB(lpAddress)).to.be.true }) - it("isToken0WBNB should revert if set zero address", async () => { - await expect(bnbPartyFactory.isToken0WBNB(ethers.ZeroAddress)).to.be.revertedWithCustomError( - bnbPartyFactory, - "ZeroAddress" - ) - }) - it("should deacrease fee after withdraw", async () => { for (let i = 0; i < 5; i++) { await bnbPartyFactory.joinParty(MEME, 0, { value: amountIn }) diff --git a/test/reverts.ts b/test/reverts.ts new file mode 100644 index 0000000..cfc6c3b --- /dev/null +++ b/test/reverts.ts @@ -0,0 +1,235 @@ +import { expect } from "chai" +import { ethers } from "hardhat" +import { + bnbPartyFactory, + v3Factory, + positionManager, + BNBPositionManager, + BNBSwapRouter, + swapRouter, + weth9, + deployContracts, + deployBNBPartyFactory, +} from "./helper" + +describe("BNBPartyFactory reverts", function () { + const partyTarget = ethers.parseEther("13") // 13 BNB target + const tokenCreationFee = ethers.parseUnits("1", 16) // 0.01 BNB token creation fee + const returnFeeAmount = ethers.parseUnits("5", 16) // 0.05 BNB return fee (bonusTargetReach) + const bonusFee = ethers.parseUnits("1", 17) // 0.01 BNB bonus fee (bonusPartyCreator) + const targetReachFee = ethers.parseUnits("8.5", 17) // 0.85 BNB target reach fee + const initialTokenAmount = "1000000000000000000000000000" + const name = "Party" + const symbol = "Token" + const sqrtPriceX96 = "1252685732681638336686364" + const BNBToTarget: bigint = partyTarget + ethers.parseEther("1") + + before(async () => { + await deployContracts(partyTarget) + }) + + it("should revert WBNB zero address", async function () { + const sqrtAddress = "0x0000000000000000000000000000000000000001" + await expect( + deployBNBPartyFactory( + partyTarget, + tokenCreationFee, + returnFeeAmount, + bonusFee, + targetReachFee, + initialTokenAmount, + sqrtPriceX96, + ethers.ZeroAddress, + sqrtAddress + ) + ).to.be.revertedWithCustomError(bnbPartyFactory, "ZeroAddress") + }) + + it("should revert sqrtPriceCalculator zero address", async function () { + const WBNB = "0x0000000000000000000000000000000000000001" + await expect( + deployBNBPartyFactory( + partyTarget, + tokenCreationFee, + returnFeeAmount, + bonusFee, + targetReachFee, + initialTokenAmount, + sqrtPriceX96, + WBNB, + ethers.ZeroAddress + ) + ).to.be.revertedWithCustomError(bnbPartyFactory, "ZeroAddress") + }) + + it("should revert zero target", async function () { + await expect( + deployBNBPartyFactory( + 0n, + tokenCreationFee, + returnFeeAmount, + bonusFee, + targetReachFee, + initialTokenAmount, + sqrtPriceX96, + await weth9.getAddress(), + await v3Factory.getAddress() + ) + ).to.be.revertedWithCustomError(bnbPartyFactory, "ZeroAmount") + }) + + it("should revert zero initialTokenAmount", async function () { + await expect( + deployBNBPartyFactory( + partyTarget, + tokenCreationFee, + returnFeeAmount, + bonusFee, + targetReachFee, + "0", + sqrtPriceX96, + await weth9.getAddress(), + await v3Factory.getAddress() + ) + ).to.be.revertedWithCustomError(bnbPartyFactory, "ZeroAmount") + }) + + it("should revert zero sqrtPriceX96", async function () { + await expect( + deployBNBPartyFactory( + partyTarget, + tokenCreationFee, + returnFeeAmount, + bonusFee, + targetReachFee, + initialTokenAmount, + "0", + await weth9.getAddress(), + await v3Factory.getAddress() + ) + ).to.be.revertedWithCustomError(bnbPartyFactory, "ZeroAmount") + }) + + it("should revert if target is less than fees", async function () { + await expect( + deployBNBPartyFactory( + bonusFee, + tokenCreationFee, + returnFeeAmount, + bonusFee, + targetReachFee, + initialTokenAmount, + sqrtPriceX96, + await weth9.getAddress(), + await v3Factory.getAddress() + ) + ).to.be.revertedWithCustomError(bnbPartyFactory, "BonusGreaterThanTarget") + }) + + it("should revert if not enough BNB is sent", async function () { + await expect( + bnbPartyFactory.createParty(name, symbol, { value: tokenCreationFee - 1n }) + ).to.be.revertedWithCustomError(bnbPartyFactory, "InsufficientBNB") + }) + + it("should revert to Create Party if position manager is not set", async function () { + await bnbPartyFactory.setNonfungiblePositionManager(ethers.ZeroAddress, ethers.ZeroAddress) + await expect( + bnbPartyFactory.createParty(name, symbol, { value: tokenCreationFee }) + ).to.be.revertedWithCustomError(bnbPartyFactory, "ZeroAddress") + await bnbPartyFactory.setNonfungiblePositionManager( + await BNBPositionManager.getAddress(), + await positionManager.getAddress() + ) + }) + + it("should revert setNonfungiblePositionManager if set same address", async function () { + await expect( + bnbPartyFactory.setNonfungiblePositionManager( + await BNBPositionManager.getAddress(), + await positionManager.getAddress() + ) + ).to.be.revertedWithCustomError(bnbPartyFactory, "PositionManagerAlreadySet") + }) + + it("should revert if swap router is not set", async function () { + const amountIn = ethers.parseUnits("1", 18) + await bnbPartyFactory.setBNBPartySwapRouter(ethers.ZeroAddress) + await expect(bnbPartyFactory.createParty(name, symbol, { value: amountIn })).to.be.revertedWithCustomError( + bnbPartyFactory, + "ZeroAddress" + ) + await bnbPartyFactory.setBNBPartySwapRouter(await BNBSwapRouter.getAddress()) + }) + + it("should revert party creation if paused", async function () { + await bnbPartyFactory.pause() + await expect( + bnbPartyFactory.createParty(name, symbol, { value: tokenCreationFee }) + ).to.be.revertedWithCustomError(bnbPartyFactory, "EnforcedPause") + await bnbPartyFactory.unpause() + }) + + it("should revert double swap router set", async function () { + await expect(bnbPartyFactory.setSwapRouter(await swapRouter.getAddress())).to.be.revertedWithCustomError( + bnbPartyFactory, + "AlreadySet" + ) + }) + + it("should revert if liquidity pool is zero address on withdrawPartyLPFee", async function () { + await expect(bnbPartyFactory.withdrawPartyLPFee([ethers.ZeroAddress])).to.be.revertedWithCustomError( + bnbPartyFactory, + "ZeroAddress" + ) + }) + + it("should revert if liquidity pool is zero address on withdrawLPFee", async function () { + await expect(bnbPartyFactory.withdrawLPFee([ethers.ZeroAddress])).to.be.revertedWithCustomError( + bnbPartyFactory, + "ZeroAddress" + ) + }) + + it("should revert double bnb party swap router set", async function () { + await expect( + bnbPartyFactory.setBNBPartySwapRouter(await BNBSwapRouter.getAddress()) + ).to.be.revertedWithCustomError(bnbPartyFactory, "AlreadySet") + }) + + it("should revert join party if paused", async function () { + await bnbPartyFactory.createParty(name, symbol, { value: tokenCreationFee }) + await bnbPartyFactory.pause() + const tokenId = await BNBPositionManager.totalSupply() + const position = await BNBPositionManager.positions(tokenId) + const MEME = position.token1 == (await weth9.getAddress()) ? position.token0 : position.token1 + await expect(bnbPartyFactory.joinParty(MEME, 0, { value: BNBToTarget })).to.be.revertedWithCustomError( + bnbPartyFactory, + "EnforcedPause" + ) + await bnbPartyFactory.unpause() + }) + + it("should revert leave party if paused", async function () { + await bnbPartyFactory.createParty(name, symbol, { value: tokenCreationFee }) + const tokenId = await BNBPositionManager.totalSupply() + const position = await BNBPositionManager.positions(tokenId) + const MEME = position.token1 == (await weth9.getAddress()) ? position.token0 : position.token1 + const MEMEToken = await ethers.getContractAt("ERC20Token", MEME) + await MEMEToken.approve(await bnbPartyFactory.getAddress(), ethers.parseEther("1000000")) + await bnbPartyFactory.joinParty(MEME, 0, { value: tokenCreationFee }) + await bnbPartyFactory.pause() + await expect(bnbPartyFactory.leaveParty(MEME, tokenCreationFee, 0)).to.be.revertedWithCustomError( + bnbPartyFactory, + "EnforcedPause" + ) + await bnbPartyFactory.unpause() + }) + + it("isToken0WBNB should revert if set zero address", async () => { + await expect(bnbPartyFactory.isToken0WBNB(ethers.ZeroAddress)).to.be.revertedWithCustomError( + bnbPartyFactory, + "ZeroAddress" + ) + }) +}) From 81abd0362744db2cb47dd0043b71d41698a9a85e Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Mon, 2 Sep 2024 15:43:16 +0300 Subject: [PATCH 3/7] fix build --- test/WithdrawFee.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/WithdrawFee.ts b/test/WithdrawFee.ts index 6c279af..23a6f53 100644 --- a/test/WithdrawFee.ts +++ b/test/WithdrawFee.ts @@ -103,8 +103,8 @@ describe("Withdraw fees", function () { expect(await bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobalX128)).to.be.equal(amountIn / 20n - 1n) // 1 % fee }) - it("isToken0WBNB should return true if token0 is WBNB", async () => { - expect(await bnbPartyFactory.isToken0WBNB(lpAddress)).to.be.true + it("isToken0WBNB should return false if token0 is not WBNB", async () => { + expect(await bnbPartyFactory.isToken0WBNB(lpAddress)).to.be.false }) it("should deacrease fee after withdraw", async () => { From b8b3b4f92b1c656265f6a4ed64937464583eb23c Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Mon, 2 Sep 2024 16:22:45 +0300 Subject: [PATCH 4/7] update fee tests --- contracts/BNBPartyFee.sol | 1 + test/WithdrawFee.ts | 34 ++++++++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/contracts/BNBPartyFee.sol b/contracts/BNBPartyFee.sol index e40782d..44d138f 100644 --- a/contracts/BNBPartyFee.sol +++ b/contracts/BNBPartyFee.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.0; import "./BNBPartyModifiers.sol"; import "./interfaces/IUniswapV3Pool.sol"; +import "hardhat/console.sol"; /// @title BNBPartyFee /// @notice This abstract contract provides internal functions for calculating fees in the BNB Party system. diff --git a/test/WithdrawFee.ts b/test/WithdrawFee.ts index 23a6f53..189cd04 100644 --- a/test/WithdrawFee.ts +++ b/test/WithdrawFee.ts @@ -1,8 +1,8 @@ import { expect } from "chai" import { ethers } from "hardhat" import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" -import { IUniswapV3Pool, MockContract } from "../typechain-types" -import { FeeAmount, bnbPartyFactory, v3PartyFactory, BNBPositionManager, weth9, deployContracts } from "./helper" +import { IUniswapV3Pool } from "../typechain-types" +import { FeeAmount, bnbPartyFactory, v3PartyFactory, BNBPositionManager, weth9, deployContracts, v3Factory, positionManager } from "./helper" describe("Withdraw fees", function () { let MEME: string @@ -16,8 +16,6 @@ describe("Withdraw fees", function () { const name = "Party" const symbol = "Token" const BNBToTarget: bigint = partyTarget + ethers.parseEther("1") - const tickLower = -214200 - const tickUpper = 201400 beforeEach(async () => { signers = await ethers.getSigners() @@ -64,7 +62,24 @@ describe("Withdraw fees", function () { }) it("should return zero if position manager is zero address", async () => { - expect(await bnbPartyFactory.getFeeGrowthInsideLastX128(lpAddress, ethers.ZeroAddress)).to.be.deep.equal([0n, 0n]) + expect(await bnbPartyFactory.getFeeGrowthInsideLastX128(lpAddress, ethers.ZeroAddress)).to.be.deep.equal([0n, 0n,]) + }) + + 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 weth9.getAddress(), FeeAmount.HIGH) + const lpPool = (await ethers.getContractAt("UniswapV3Pool", secondLP)) as any as IUniswapV3Pool + const token0 = await lpPool.token0() + await bnbPartyFactory.withdrawLPFee([secondLP]) + const liquidity = await lpPool.liquidity() + if (token0 == (await weth9.getAddress())) { + const feeGrowthGlobalX128 = await lpPool.feeGrowthGlobal0X128() + expect(await bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobalX128)).to.be.deep.equal(ethers.parseEther("1") / 100n - 1n) + } else { + const feeGrowthGlobalX128 = await lpPool.feeGrowthGlobal1X128() + expect(await bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobalX128)).to.be.deep.equal(ethers.parseEther("1") / 100n - 1n) + } }) it("should revert LPNotAtParty", async () => { @@ -99,12 +114,15 @@ describe("Withdraw fees", function () { } const lpPool = (await ethers.getContractAt("UniswapV3Pool", lpAddress)) as any as IUniswapV3Pool const liquidity = await lpPool.liquidity() - const feeGrowthGlobalX128 = await lpPool.feeGrowthGlobal0X128() > 0 ? await lpPool.feeGrowthGlobal0X128() : await lpPool.feeGrowthGlobal1X128() + const feeGrowthGlobalX128 = + (await lpPool.feeGrowthGlobal0X128()) > 0 + ? await lpPool.feeGrowthGlobal0X128() + : await lpPool.feeGrowthGlobal1X128() expect(await bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobalX128)).to.be.equal(amountIn / 20n - 1n) // 1 % fee }) - it("isToken0WBNB should return false if token0 is not WBNB", async () => { - expect(await bnbPartyFactory.isToken0WBNB(lpAddress)).to.be.false + it("isToken0WBNB should return true if token0 is WBNB", async () => { + expect(await bnbPartyFactory.isToken0WBNB(lpAddress)).to.be.true }) it("should deacrease fee after withdraw", async () => { From e2b709a68dfb04132a60d50d4180370135271db1 Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Mon, 2 Sep 2024 16:26:43 +0300 Subject: [PATCH 5/7] delete console --- contracts/BNBPartyFee.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/BNBPartyFee.sol b/contracts/BNBPartyFee.sol index 44d138f..e40782d 100644 --- a/contracts/BNBPartyFee.sol +++ b/contracts/BNBPartyFee.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.0; import "./BNBPartyModifiers.sol"; import "./interfaces/IUniswapV3Pool.sol"; -import "hardhat/console.sol"; /// @title BNBPartyFee /// @notice This abstract contract provides internal functions for calculating fees in the BNB Party system. From d896de84743277c940e35ec327f4f88a1b7993f8 Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Mon, 2 Sep 2024 16:28:28 +0300 Subject: [PATCH 6/7] fix build --- test/WithdrawFee.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/WithdrawFee.ts b/test/WithdrawFee.ts index 189cd04..56dbb4a 100644 --- a/test/WithdrawFee.ts +++ b/test/WithdrawFee.ts @@ -105,7 +105,7 @@ describe("Withdraw fees", function () { const lpPool = (await ethers.getContractAt("UniswapV3Pool", lpAddress)) as any as IUniswapV3Pool const liquidity = await lpPool.liquidity() const feeGrowthGlobalX128 = await lpPool.feeGrowthGlobal1X128() > 0 ? await lpPool.feeGrowthGlobal1X128() : await lpPool.feeGrowthGlobal0X128() - expect(await bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobalX128)).to.be.equal(amountIn / 100n) // 1 % fee + expect(await bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobalX128)).to.be.equal(amountIn / 100n - 1n) // 1 % fee }) it("calculateFees should return fee from 5 swaps", async () => { @@ -118,7 +118,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 - 1n) // 1 % fee + expect(await bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobalX128)).to.be.equal(amountIn / 20n) // 1 % fee }) it("isToken0WBNB should return true if token0 is WBNB", async () => { From fc5a885c31c2a5b8e10884d7b92999c0fc4f5414 Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Mon, 2 Sep 2024 16:35:53 +0300 Subject: [PATCH 7/7] update getFeeGrowthInsideLastX128 test --- test/WithdrawFee.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/WithdrawFee.ts b/test/WithdrawFee.ts index 56dbb4a..58b3bed 100644 --- a/test/WithdrawFee.ts +++ b/test/WithdrawFee.ts @@ -72,13 +72,14 @@ describe("Withdraw fees", function () { const lpPool = (await ethers.getContractAt("UniswapV3Pool", secondLP)) as any as IUniswapV3Pool const token0 = await lpPool.token0() await bnbPartyFactory.withdrawLPFee([secondLP]) - const liquidity = await lpPool.liquidity() + const collectedFee = await bnbPartyFactory.getFeeGrowthInsideLastX128(secondLP, positionManager) + const fee = collectedFee.feeGrowthInside0LastX128 == 0n ? collectedFee.feeGrowthInside1LastX128 : collectedFee.feeGrowthInside0LastX128 if (token0 == (await weth9.getAddress())) { const feeGrowthGlobalX128 = await lpPool.feeGrowthGlobal0X128() - expect(await bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobalX128)).to.be.deep.equal(ethers.parseEther("1") / 100n - 1n) + expect(feeGrowthGlobalX128).to.be.deep.equal(fee) } else { const feeGrowthGlobalX128 = await lpPool.feeGrowthGlobal1X128() - expect(await bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobalX128)).to.be.deep.equal(ethers.parseEther("1") / 100n - 1n) + expect(feeGrowthGlobalX128).to.be.deep.equal(fee) } })