From faa27e9a0856a2825d2aaed987b4bdd532475ff3 Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Thu, 8 Aug 2024 10:45:28 +0300 Subject: [PATCH 01/21] curve draft tests --- package-lock.json | 9 +++ package.json | 20 ++--- scripts/curve.ts | 162 ++++++++++++++++++++++++++++++++++++++++ test/BNBPartyFactory.ts | 12 +-- test/SwapRouter.ts | 2 +- test/helper.ts | 8 +- 6 files changed, 193 insertions(+), 20 deletions(-) create mode 100644 scripts/curve.ts diff --git a/package-lock.json b/package-lock.json index 843d314..a51eeaf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,9 @@ "@types/chai": "^4.2.0", "@types/mocha": ">=9.1.0", "@types/node": "^20.12.7", + "bignumber.js": "^9.1.2", "chai": "^4.2.0", + "csv-writer": "^1.6.0", "ethers": "^6.12.0", "hardhat": "^2.22.3", "hardhat-gas-reporter": "^2.1.1", @@ -3589,6 +3591,13 @@ "node": "*" } }, + "node_modules/csv-writer": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/csv-writer/-/csv-writer-1.6.0.tgz", + "integrity": "sha512-NOx7YDFWEsM/fTRAJjRpPp8t+MKRVvniAg9wQlUKx20MFrPs73WLJhFf5iteqrxNYnsy924K3Iroh3yNHeYd2g==", + "dev": true, + "license": "MIT" + }, "node_modules/d": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", diff --git a/package.json b/package.json index 5413782..20e2c3d 100644 --- a/package.json +++ b/package.json @@ -19,24 +19,26 @@ "@nomicfoundation/hardhat-network-helpers": "^1.0.10", "@nomicfoundation/hardhat-verify": "^2.0.6", "@truffle/dashboard-hardhat-plugin": "^0.2.15", - "ethers": "^6.12.0", - "hardhat-gas-reporter": "^2.1.1", - "hardhat": "^2.22.3", - "solidity-coverage": "^0.8.12", - "ts-node": ">=8.0.0", - "typechain": "^8.3.2", - "typescript": "^5.4.5", "@typechain/ethers-v6": "^0.5.1", "@typechain/hardhat": "^9.1.0", "@types/chai": "^4.2.0", "@types/mocha": ">=9.1.0", "@types/node": "^20.12.7", - "chai": "^4.2.0" + "bignumber.js": "^9.1.2", + "chai": "^4.2.0", + "csv-writer": "^1.6.0", + "ethers": "^6.12.0", + "hardhat": "^2.22.3", + "hardhat-gas-reporter": "^2.1.1", + "solidity-coverage": "^0.8.12", + "ts-node": ">=8.0.0", + "typechain": "^8.3.2", + "typescript": "^5.4.5" }, "dependencies": { - "@openzeppelin/contracts": "^5.0.2", "@bnb-party/v3-core": "^1.0.4", "@bnb-party/v3-periphery": "^1.0.5", + "@openzeppelin/contracts": "^5.0.2", "@uniswap/lib": "^4.0.1-alpha", "@uniswap/v3-core": "^1.0.0", "@uniswap/v3-periphery": "^1.4.4" diff --git a/scripts/curve.ts b/scripts/curve.ts new file mode 100644 index 0000000..81529ff --- /dev/null +++ b/scripts/curve.ts @@ -0,0 +1,162 @@ +import { ethers } from "hardhat" +import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" +import { FeeAmount, v3PartyFactory, deployContracts, weth9, bnbPartyFactory, BNBPositionManager } from "../test/helper" +import { IUniswapV3Pool } from "../typechain-types" +import BigNumber from "bignumber.js" +import * as csvWriter from "csv-writer" + +let signers: SignerWithAddress[] +const BNB_PRICE = 550 // BNB price in USD +let lpContract: IUniswapV3Pool + +// Создаем CSV писатель +const createCsvWriter = csvWriter.createObjectCsvWriter +const csv = createCsvWriter({ + path: "liquidity_pool_data.csv", + header: [ + { id: "iteration", title: "Iteration" }, + { id: "updatedMEMEAmount", title: "Updated MEME Amount" }, + { id: "updatedWBNBAmount", title: "Updated WBNB Amount" }, + { id: "updatedLiquidity", title: "Updated Liquidity" }, + { id: "updatedSqrtPriceX96", title: "Updated sqrtPriceX96" }, + { id: "priceToken0InToken1", title: "Price of MEME in WBNB" }, + { id: "priceToken1InToken0", title: "Price of WBNB in MEME" }, + { id: "wbnbValueUSD", title: "WBNB Value in USD" }, + { id: "memeValueUSD", title: "MEME Value in USD" }, + { id: "marketCap", title: "Market Cap in USD" }, + { id: "remainingMEMEPercentage", title: "Remaining MEME %" }, + ], +}) + +async function before() { + signers = await ethers.getSigners() + await deployContracts() +} + +async function createLiquidityPool() { + const tokenCreationFee = ethers.parseUnits("1", 16) + await bnbPartyFactory.createParty("MEME", "MEME", { value: tokenCreationFee }) + const tokenId = await BNBPositionManager.totalSupply() + const position = await BNBPositionManager.positions(tokenId) + const MEME = position.token1 === (await weth9.getAddress()) ? position.token0 : position.token1 + return { MEME, position } +} + +async function getPoolData(lpContract: IUniswapV3Pool) { + const slot0 = await lpContract.slot0() + const liquidity = await lpContract.liquidity() + console.log("Liquidity: ", liquidity.toString()) + return { slot0, liquidity } +} + +function calculatePrices(sqrtPriceX96: BigNumber) { + const priceX96 = sqrtPriceX96.multipliedBy(sqrtPriceX96) + const priceToken0InToken1 = priceX96.dividedBy(new BigNumber(2).pow(192)) + const priceToken1InToken0 = new BigNumber(1).div(priceToken0InToken1) + return { priceToken0InToken1, priceToken1InToken0 } +} + +async function logPrices(meme: string, priceToken0InToken1: BigNumber, priceToken1InToken0: BigNumber) { + const token0 = await lpContract.token0() + if (token0 === meme) { + console.log(`Price of MEME in terms of WBNB: ${priceToken0InToken1.toString()}`) + console.log(`Price of WBNB in terms of MEME: ${priceToken1InToken0.toString()}`) + } else { + console.log(`Price of WBNB in terms of MEME: ${priceToken0InToken1.toString()}`) + console.log(`Price of MEME in terms of WBNB: ${priceToken1InToken0.toString()}`) + } +} + +// todo: balances minus fee +async function getTokenBalances(lpAddress: string, token: any) { + const fullMEMEAmount = await token.balanceOf(lpAddress) + console.log("Full MEME amount: ", fullMEMEAmount.toString()) + const fullWBNBAmount = await weth9.balanceOf(lpAddress) + console.log("Full WBNB amount: ", fullWBNBAmount.toString()) + return { fullMEMEAmount, fullWBNBAmount } +} + +async function test() { + await before() + const { MEME, position } = await createLiquidityPool() + const token = await ethers.getContractAt("ERC20Token", MEME) + const lpAddress = await v3PartyFactory.getPool(position.token0, position.token1, FeeAmount.HIGH) + + const { fullMEMEAmount, fullWBNBAmount } = await getTokenBalances(lpAddress, token) + const initialMEMEAmount = fullMEMEAmount // Save the initial MEME amount for later comparison + lpContract = (await ethers.getContractAt("UniswapV3Pool", lpAddress)) as any as IUniswapV3Pool + const { slot0, liquidity } = await getPoolData(lpContract) + + const sqrtPriceX96 = new BigNumber(slot0.sqrtPriceX96.toString()) + const { priceToken0InToken1, priceToken1InToken0 } = calculatePrices(sqrtPriceX96) + + await logPrices(MEME, priceToken0InToken1, priceToken1InToken0) + + const target = 12 + for (let i = 0; i < target; i++) { + const swapAmount = ethers.parseUnits("1", 18) + await bnbPartyFactory.joinParty(MEME, 0, { value: swapAmount }) + + const updatedMEMEAmount = await token.balanceOf(lpAddress) + console.log("Updated MEME amount: ", updatedMEMEAmount.toString()) + const updatedWBNBAmount = await weth9.balanceOf(lpAddress) + console.log("Updated WBNB amount: ", updatedWBNBAmount.toString()) + const updatedSlot0 = await lpContract.slot0() + const updatedLiquidity = await lpContract.liquidity() + console.log("Updated liquidity: ", updatedLiquidity.toString()) + + const updatedSqrtPriceX96 = new BigNumber(updatedSlot0.sqrtPriceX96.toString()) + const { priceToken0InToken1: updatedPriceToken0InToken1, priceToken1InToken0: updatedPriceToken1InToken0 } = + calculatePrices(updatedSqrtPriceX96) + + console.log(`Updated sqrtPriceX96: ${updatedSqrtPriceX96.toString()}`) + + if (!(updatedLiquidity == 0n)) { + await logPrices(MEME, updatedPriceToken0InToken1, updatedPriceToken1InToken0) + + // Calculate market cap + const wbnbValueUSD = new BigNumber(updatedWBNBAmount.toString()) + .div(new BigNumber(10).pow(18)) + .multipliedBy(BNB_PRICE) + console.log(`WBNB value in USD: ${wbnbValueUSD.toString()}`) + + const memeValueInWBNB = new BigNumber(updatedMEMEAmount.toString()) + .div(new BigNumber(10).pow(18)) + .multipliedBy(updatedPriceToken1InToken0) + const memeValueUSD = memeValueInWBNB.multipliedBy(BNB_PRICE) + console.log(`MEME value in USD: ${memeValueUSD.toString()}`) + + const marketCap = wbnbValueUSD.plus(memeValueUSD) + console.log(`Market Cap of Liquidity Pool in USD: ${marketCap.toString()}`) + + // Calculate the remaining percentage of MEME tokens + const remainingMEMEPercentage = new BigNumber(updatedMEMEAmount.toString()) + .dividedBy(new BigNumber(initialMEMEAmount.toString())) + .multipliedBy(100) + .toFixed(2) + console.log(`Remaining MEME tokens in the pool: ${remainingMEMEPercentage}%\n`) + + // Write data to CSV + await csv.writeRecords([ + { + iteration: i + 1, + updatedMEMEAmount: updatedMEMEAmount.toString(), + updatedWBNBAmount: updatedWBNBAmount.toString(), + updatedLiquidity: updatedLiquidity.toString(), + updatedSqrtPriceX96: updatedSqrtPriceX96.toString(), + priceToken0InToken1: updatedPriceToken0InToken1.toString(), + priceToken1InToken0: updatedPriceToken1InToken0.toString(), + wbnbValueUSD: wbnbValueUSD.toString(), + memeValueUSD: memeValueUSD.toString(), + marketCap: marketCap.toString(), + remainingMEMEPercentage: remainingMEMEPercentage, + }, + ]) + } else { + console.log("Updated price of token0 in terms of token1: not available (liquidity is zero)") + console.log("Updated price of token1 in terms of token0: not available (liquidity is zero)") + } + } +} + +test().catch(console.error) diff --git a/test/BNBPartyFactory.ts b/test/BNBPartyFactory.ts index e399513..e5eac41 100644 --- a/test/BNBPartyFactory.ts +++ b/test/BNBPartyFactory.ts @@ -25,10 +25,10 @@ describe("BNBPartyFactory", function () { const returnFeeAmount = ethers.parseUnits("5", 17) const bonusFee = ethers.parseUnits("1", 16) const targetReachFee = ethers.parseUnits("1", 17) - const initialTokenAmount = "10000000000000000000000000" + const initialTokenAmount = "1000000000000000000000000000" const name = "Party" const symbol = "Token" - const sqrtPriceX96 = "25052911542910170730777872" + const sqrtPriceX96 = "7922427122162318518285487" const BNBToTarget: bigint = partyTarget + ethers.parseEther("1") before(async () => { @@ -46,8 +46,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()).tickUpper).to.equal("0") - expect((await bnbPartyFactory.party()).tickLower).to.equal("-92200") + expect((await bnbPartyFactory.party()).tickUpper).to.equal("183800") + expect((await bnbPartyFactory.party()).tickLower).to.equal("-183800") }) it("should create party LP", async function () { @@ -146,7 +146,7 @@ describe("BNBPartyFactory", function () { const newBalance = await token.balanceOf(newLPPool) const userBalance = await token.balanceOf(await signers[0].getAddress()) const bnbpartyBalance = await token.balanceOf(await bnbPartyFactory.getAddress()) - expect(newBalance).to.be.equal(oldBalance + rest - userBalance - bnbpartyBalance - 1n) + expect(newBalance).to.be.equal(oldBalance + rest - userBalance - bnbpartyBalance - 2n) }) it("should send WBNB to new LP", async () => { @@ -154,7 +154,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.91") - expect(balance).to.be.equal(BNBToTarget - returnFeeAmount - bonusFee - targetReachFee - percentFee - 1n) + expect(balance).to.be.equal(BNBToTarget - returnFeeAmount - bonusFee - targetReachFee - percentFee - 2n) }) }) }) diff --git a/test/SwapRouter.ts b/test/SwapRouter.ts index f89a833..eeb90ac 100644 --- a/test/SwapRouter.ts +++ b/test/SwapRouter.ts @@ -58,7 +58,7 @@ describe("Smart Router", function () { }) it("user should receive bnb after leave party", async () => { - const amountIn = ethers.parseUnits("5", 16) + const amountIn = ethers.parseUnits("50", 18) const bnbBalanceBefore = await ethers.provider.getBalance(await signers[0].getAddress()) await bnbPartyFactory.leaveParty(MEME, amountIn, 0) const bnbBalanceAfter = await ethers.provider.getBalance(await signers[0].getAddress()) diff --git a/test/helper.ts b/test/helper.ts index fadf50f..ac06b4b 100644 --- a/test/helper.ts +++ b/test/helper.ts @@ -42,8 +42,8 @@ export async function deployContracts() { const returnFeeAmount = ethers.parseUnits("5", 17) const bonusFee = ethers.parseUnits("1", 16) const targetReachFee = ethers.parseUnits("1", 17) - const initialTokenAmount = "10000000000000000000000000" - const sqrtPriceX96 = "25052911542910170730777872" + const initialTokenAmount = "1000000000000000000000000000" + const sqrtPriceX96 = "7922427122162318518285487" // Deploy WETH9 const WETH9 = await ethers.getContractFactory(WETH9Artifact.abi, WETH9Artifact.bytecode) weth9 = (await WETH9.deploy()) as IWBNB @@ -60,8 +60,8 @@ export async function deployContracts() { bonusTargetReach: returnFeeAmount, bonusPartyCreator: bonusFee, targetReachFee: targetReachFee, - tickLower: "-92200", - tickUpper: "0", + tickLower: "-183800", + tickUpper: "183800", }, await weth9.getAddress() )) as BNBPartyFactory From 01358c6409b483efc694bf0a92b53ec5b3115d2a Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Thu, 8 Aug 2024 10:51:26 +0300 Subject: [PATCH 02/21] remove comments --- scripts/curve.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/curve.ts b/scripts/curve.ts index 81529ff..0db2397 100644 --- a/scripts/curve.ts +++ b/scripts/curve.ts @@ -9,7 +9,6 @@ let signers: SignerWithAddress[] const BNB_PRICE = 550 // BNB price in USD let lpContract: IUniswapV3Pool -// Создаем CSV писатель const createCsvWriter = csvWriter.createObjectCsvWriter const csv = createCsvWriter({ path: "liquidity_pool_data.csv", From 04a559f0cd20d32c80987bdb855cff9bf653eb1c Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Fri, 9 Aug 2024 11:12:23 +0300 Subject: [PATCH 03/21] add minus fee calculation --- liquidity_pool_data.csv | 13 +++++++++ scripts/curve.ts | 62 ++++++++++++++++++++++++++++++----------- test/BNBPartyFactory.ts | 4 +-- test/helper.ts | 4 +-- 4 files changed, 63 insertions(+), 20 deletions(-) create mode 100644 liquidity_pool_data.csv diff --git a/liquidity_pool_data.csv b/liquidity_pool_data.csv new file mode 100644 index 0000000..41ec102 --- /dev/null +++ b/liquidity_pool_data.csv @@ -0,0 +1,13 @@ +Iteration,Updated MEME Amount,Updated WBNB Amount,Updated Liquidity,Updated sqrtPriceX96,Price of MEME in WBNB,Price of WBNB in MEME,WBNB Value in USD,MEME Value in USD,Market Cap in USD,Remaining MEME % +1,910049306518703033754838174,990000000000000001,100080116579980480031181,7.20438156095468783116411719870957e+32,82686430.55954322397315714993,1.209388279592e-8,544.50000000000000055,6053.316308350008130201531637381247097544,6597.816308350008130751531637381247097544,91.00 +2,834945389645284344665461943,1980000000000000001,100080116579980480031181,6.60982336749478008988461308594113e+32,69601811.14029477576872155793,1.43674422205e-8,1089.00000000000000055,6597.816303650814996750827527396790437325,7686.816303650814997300827527396790437325,83.49 +3,771292682947645425490924871,2970000000000000001,100080116579980480031181,6.1059183798658855859802320265111e+32,59394033.79653426635640193039,1.683670793308e-8,1633.50000000000000055,7142.316298541148435518514756011586597974,8775.816298541148436068514756011586597974,77.13 +4,716657727499368559455059927,3960000000000000001,100080116579980480031181,5.67340218412820516066151239578073e+32,51277633.69106503939222094387,1.950167993369e-8,2178.00000000000000055,7686.8162930340715659387331448417849323465,9864.8162930340715664887331448417849323465,71.67 +5,669250955742936625147918361,4950000000000000001,100080116579980480031181,5.29810771552178594922798784528074e+32,44718002.90734385938624074953,2.23623582223e-8,2722.50000000000000055,8231.316287117105734488400812610619307665,10953.816287117105735038400812610619307665,66.93 +6,627726938647918356997460460,5940000000000000001,100080116579980480031181,4.96938392031916453803301243374142e+32,39341048.76508812226175317087,2.541874279893e-8,3267.00000000000000055,8775.81628079813175616006527415732291929,12042.81628079813175671006527415732291929,62.77 +7,591054651150815709152209469,6930000000000000001,100080116579980480031181,4.67906871557334294336511926102188e+32,34878650.95707021059536170662,2.867083366357e-8,3811.50000000000000055,9320.3162740734364312644921638671228893815,13131.8162740734364318144921638671228893815,59.11 +8,558430702693671908994965053,7920000000000000001,100080116579980480031181,4.42080208094627959878940159370393e+32,31134577.48935949309979749564,3.211863081623e-8,4356.00000000000000055,9864.8162669462691153323271735587433656045,14220.8162669462691158823271735587433656045,55.84 +9,529219800658797686605556156,8910000000000000001,100080116579980480031181,4.1895547390471779540122261223906e+32,27962536.9340798327025570687,3.57621342569e-8,4900.50000000000000055,10409.31625941337786508766654640035426202,15309.81625941337786563766654640035426202,52.92 +10,502912970716050175600706275,9900000000000000001,100080116579980480031181,3.98129740790453656128343390774867e+32,25251668.23540569610606699665,3.960134398558e-8,5445.00000000000000055,10953.816251474923358124192768889278532975,16398.816251474923358674192768889278532975,50.29 +11,479097647962450678452007300,10890000000000000001,100080116579980480031181,3.79276402825524936215763423790356e+32,22916721.09268568427992006524,4.363626000227e-8,5989.50000000000000055,11498.31624313103583664062310763123111405,17487.81624313103583719062310763123111405,47.91 +12,457435881799001771705479954,11880000000000000001,100080116579980480031181,3.62127922302201618686169015406342e+32,20891270.78690419216945555895,4.786688230698e-8,6534.00000000000000055,12042.816234384337885271091374297415353406,18576.816234384337885821091374297415353406,45.74 diff --git a/scripts/curve.ts b/scripts/curve.ts index 0db2397..4d895d5 100644 --- a/scripts/curve.ts +++ b/scripts/curve.ts @@ -66,13 +66,45 @@ async function logPrices(meme: string, priceToken0InToken1: BigNumber, priceToke } } -// todo: balances minus fee async function getTokenBalances(lpAddress: string, token: any) { const fullMEMEAmount = await token.balanceOf(lpAddress) - console.log("Full MEME amount: ", fullMEMEAmount.toString()) const fullWBNBAmount = await weth9.balanceOf(lpAddress) - console.log("Full WBNB amount: ", fullWBNBAmount.toString()) - return { fullMEMEAmount, fullWBNBAmount } + const lpPool = await ethers.getContractAt("UniswapV3Pool", lpAddress) + let feeGrowthGlobal0X128 = await lpPool.feeGrowthGlobal0X128() + let feeGrowthGlobal1X128 = await lpPool.feeGrowthGlobal1X128() + let liquidity = await lpPool.liquidity() + let getFeeGlobal = await bnbPartyFactory.getFeeGrowthInsideLastX128(lpAddress) + let wbnbFee + let memeFee + if ((await lpPool.token0()) === (await weth9.getAddress())) { + wbnbFee = await bnbPartyFactory.calculateFees( + liquidity, + feeGrowthGlobal0X128 - getFeeGlobal.feeGrowthInside0LastX128 + ) + memeFee = await bnbPartyFactory.calculateFees( + liquidity, + feeGrowthGlobal1X128 - getFeeGlobal.feeGrowthInside1LastX128 + ) + console.log("WBNB fee: ", wbnbFee) + console.log("MEME fee: ", memeFee) + console.log("WBNB amount: ", fullWBNBAmount - wbnbFee) + console.log("MEME amount: ", fullMEMEAmount - memeFee) + } else { + wbnbFee = await bnbPartyFactory.calculateFees( + liquidity, + feeGrowthGlobal1X128 - getFeeGlobal.feeGrowthInside1LastX128 + ) + memeFee = await bnbPartyFactory.calculateFees( + liquidity, + feeGrowthGlobal0X128 - getFeeGlobal.feeGrowthInside0LastX128 + ) + console.log("WBNB fee: ", wbnbFee) + console.log("MEME fee: ", memeFee) + console.log("WBNB amount: ", fullWBNBAmount - wbnbFee) + console.log("MEME amount: ", fullMEMEAmount - memeFee) + } + + return { WBNBAmount: fullWBNBAmount - wbnbFee, MEMEAmount: fullMEMEAmount - memeFee } } async function test() { @@ -81,8 +113,8 @@ async function test() { const token = await ethers.getContractAt("ERC20Token", MEME) const lpAddress = await v3PartyFactory.getPool(position.token0, position.token1, FeeAmount.HIGH) - const { fullMEMEAmount, fullWBNBAmount } = await getTokenBalances(lpAddress, token) - const initialMEMEAmount = fullMEMEAmount // Save the initial MEME amount for later comparison + const { MEMEAmount, WBNBAmount } = await getTokenBalances(lpAddress, token) + const initialMEMEAmount = MEMEAmount // Save the initial MEME amount for later comparison lpContract = (await ethers.getContractAt("UniswapV3Pool", lpAddress)) as any as IUniswapV3Pool const { slot0, liquidity } = await getPoolData(lpContract) @@ -95,11 +127,9 @@ async function test() { for (let i = 0; i < target; i++) { const swapAmount = ethers.parseUnits("1", 18) await bnbPartyFactory.joinParty(MEME, 0, { value: swapAmount }) - - const updatedMEMEAmount = await token.balanceOf(lpAddress) - console.log("Updated MEME amount: ", updatedMEMEAmount.toString()) - const updatedWBNBAmount = await weth9.balanceOf(lpAddress) - console.log("Updated WBNB amount: ", updatedWBNBAmount.toString()) + const { MEMEAmount, WBNBAmount } = await getTokenBalances(lpAddress, token) + console.log("Updated MEME amount: ", MEMEAmount.toString()) + console.log("Updated WBNB amount: ", WBNBAmount.toString()) const updatedSlot0 = await lpContract.slot0() const updatedLiquidity = await lpContract.liquidity() console.log("Updated liquidity: ", updatedLiquidity.toString()) @@ -114,12 +144,12 @@ async function test() { await logPrices(MEME, updatedPriceToken0InToken1, updatedPriceToken1InToken0) // Calculate market cap - const wbnbValueUSD = new BigNumber(updatedWBNBAmount.toString()) + const wbnbValueUSD = new BigNumber(WBNBAmount.toString()) .div(new BigNumber(10).pow(18)) .multipliedBy(BNB_PRICE) console.log(`WBNB value in USD: ${wbnbValueUSD.toString()}`) - const memeValueInWBNB = new BigNumber(updatedMEMEAmount.toString()) + const memeValueInWBNB = new BigNumber(MEMEAmount.toString()) .div(new BigNumber(10).pow(18)) .multipliedBy(updatedPriceToken1InToken0) const memeValueUSD = memeValueInWBNB.multipliedBy(BNB_PRICE) @@ -129,7 +159,7 @@ async function test() { console.log(`Market Cap of Liquidity Pool in USD: ${marketCap.toString()}`) // Calculate the remaining percentage of MEME tokens - const remainingMEMEPercentage = new BigNumber(updatedMEMEAmount.toString()) + const remainingMEMEPercentage = new BigNumber(MEMEAmount.toString()) .dividedBy(new BigNumber(initialMEMEAmount.toString())) .multipliedBy(100) .toFixed(2) @@ -139,8 +169,8 @@ async function test() { await csv.writeRecords([ { iteration: i + 1, - updatedMEMEAmount: updatedMEMEAmount.toString(), - updatedWBNBAmount: updatedWBNBAmount.toString(), + updatedMEMEAmount: MEMEAmount.toString(), + updatedWBNBAmount: WBNBAmount.toString(), updatedLiquidity: updatedLiquidity.toString(), updatedSqrtPriceX96: updatedSqrtPriceX96.toString(), priceToken0InToken1: updatedPriceToken0InToken1.toString(), diff --git a/test/BNBPartyFactory.ts b/test/BNBPartyFactory.ts index e5eac41..3aa0a7a 100644 --- a/test/BNBPartyFactory.ts +++ b/test/BNBPartyFactory.ts @@ -46,8 +46,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()).tickUpper).to.equal("183800") - expect((await bnbPartyFactory.party()).tickLower).to.equal("-183800") + expect((await bnbPartyFactory.party()).tickUpper).to.equal("184200") + expect((await bnbPartyFactory.party()).tickLower).to.equal("-203800") }) it("should create party LP", async function () { diff --git a/test/helper.ts b/test/helper.ts index ac06b4b..10b7d82 100644 --- a/test/helper.ts +++ b/test/helper.ts @@ -60,8 +60,8 @@ export async function deployContracts() { bonusTargetReach: returnFeeAmount, bonusPartyCreator: bonusFee, targetReachFee: targetReachFee, - tickLower: "-183800", - tickUpper: "183800", + tickLower: "-203800", + tickUpper: "184200", }, await weth9.getAddress() )) as BNBPartyFactory From 224e0c70290d779782ad67f9fbe85605fdf55f8e Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Fri, 9 Aug 2024 11:13:07 +0300 Subject: [PATCH 04/21] remove csv --- liquidity_pool_data.csv | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 liquidity_pool_data.csv diff --git a/liquidity_pool_data.csv b/liquidity_pool_data.csv deleted file mode 100644 index 41ec102..0000000 --- a/liquidity_pool_data.csv +++ /dev/null @@ -1,13 +0,0 @@ -Iteration,Updated MEME Amount,Updated WBNB Amount,Updated Liquidity,Updated sqrtPriceX96,Price of MEME in WBNB,Price of WBNB in MEME,WBNB Value in USD,MEME Value in USD,Market Cap in USD,Remaining MEME % -1,910049306518703033754838174,990000000000000001,100080116579980480031181,7.20438156095468783116411719870957e+32,82686430.55954322397315714993,1.209388279592e-8,544.50000000000000055,6053.316308350008130201531637381247097544,6597.816308350008130751531637381247097544,91.00 -2,834945389645284344665461943,1980000000000000001,100080116579980480031181,6.60982336749478008988461308594113e+32,69601811.14029477576872155793,1.43674422205e-8,1089.00000000000000055,6597.816303650814996750827527396790437325,7686.816303650814997300827527396790437325,83.49 -3,771292682947645425490924871,2970000000000000001,100080116579980480031181,6.1059183798658855859802320265111e+32,59394033.79653426635640193039,1.683670793308e-8,1633.50000000000000055,7142.316298541148435518514756011586597974,8775.816298541148436068514756011586597974,77.13 -4,716657727499368559455059927,3960000000000000001,100080116579980480031181,5.67340218412820516066151239578073e+32,51277633.69106503939222094387,1.950167993369e-8,2178.00000000000000055,7686.8162930340715659387331448417849323465,9864.8162930340715664887331448417849323465,71.67 -5,669250955742936625147918361,4950000000000000001,100080116579980480031181,5.29810771552178594922798784528074e+32,44718002.90734385938624074953,2.23623582223e-8,2722.50000000000000055,8231.316287117105734488400812610619307665,10953.816287117105735038400812610619307665,66.93 -6,627726938647918356997460460,5940000000000000001,100080116579980480031181,4.96938392031916453803301243374142e+32,39341048.76508812226175317087,2.541874279893e-8,3267.00000000000000055,8775.81628079813175616006527415732291929,12042.81628079813175671006527415732291929,62.77 -7,591054651150815709152209469,6930000000000000001,100080116579980480031181,4.67906871557334294336511926102188e+32,34878650.95707021059536170662,2.867083366357e-8,3811.50000000000000055,9320.3162740734364312644921638671228893815,13131.8162740734364318144921638671228893815,59.11 -8,558430702693671908994965053,7920000000000000001,100080116579980480031181,4.42080208094627959878940159370393e+32,31134577.48935949309979749564,3.211863081623e-8,4356.00000000000000055,9864.8162669462691153323271735587433656045,14220.8162669462691158823271735587433656045,55.84 -9,529219800658797686605556156,8910000000000000001,100080116579980480031181,4.1895547390471779540122261223906e+32,27962536.9340798327025570687,3.57621342569e-8,4900.50000000000000055,10409.31625941337786508766654640035426202,15309.81625941337786563766654640035426202,52.92 -10,502912970716050175600706275,9900000000000000001,100080116579980480031181,3.98129740790453656128343390774867e+32,25251668.23540569610606699665,3.960134398558e-8,5445.00000000000000055,10953.816251474923358124192768889278532975,16398.816251474923358674192768889278532975,50.29 -11,479097647962450678452007300,10890000000000000001,100080116579980480031181,3.79276402825524936215763423790356e+32,22916721.09268568427992006524,4.363626000227e-8,5989.50000000000000055,11498.31624313103583664062310763123111405,17487.81624313103583719062310763123111405,47.91 -12,457435881799001771705479954,11880000000000000001,100080116579980480031181,3.62127922302201618686169015406342e+32,20891270.78690419216945555895,4.786688230698e-8,6534.00000000000000055,12042.816234384337885271091374297415353406,18576.816234384337885821091374297415353406,45.74 From a8d269a3f94f19d479da871d9d2f8c33933a2c4c Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Tue, 13 Aug 2024 14:49:49 +0300 Subject: [PATCH 05/21] fix market cap, fix tests, refactor script --- liquidity_pool_data.csv | 14 +++++++ scripts/curve.ts | 86 +++++++++++++++++++++-------------------- test/BNBPartyFactory.ts | 6 +-- test/SwapRouter.ts | 2 +- test/WithdrawFee.ts | 2 +- test/helper.ts | 6 +-- 6 files changed, 66 insertions(+), 50 deletions(-) create mode 100644 liquidity_pool_data.csv diff --git a/liquidity_pool_data.csv b/liquidity_pool_data.csv new file mode 100644 index 0000000..c7532ea --- /dev/null +++ b/liquidity_pool_data.csv @@ -0,0 +1,14 @@ +Iteration,Updated MEME Amount,Updated WBNB Amount,Updated Liquidity,Updated sqrtPriceX96,Price of MEME in WBNB,Price of WBNB in MEME,WBNB Value in USD,MEME Value in USD,Market Cap in USD,Remaining MEME % +1,763920318528615997030357345,990000000000000001,56599464646994007045301,1.069338793608067942170073033053952e+33,5.48944606607e-9,182167742.96788060040211602372,109300645780.728360241269614232,0.000003293667639642,3293.667639641999999999979506799946147476,76.39 +2,618018668105026337033216070,1980000000000000001,56599464646994007045301,8.65105065551534620165932366586375e+32,8.3872860986e-9,119228077.86017535494720531542,71536846716.105212968323189252,0.00000503237165916,5032.37165915999999999996868858353670648,61.80 +3,518911428661133039440715651,2970000000000000001,56599464646994007045301,7.26374345712156943258013749010645e+32,1.189701948783e-8,84054666.04664832143727731861,50432799627.988992862366391166,0.000007138211692698,7138.211692697999999999955586046848033044,51.89 +4,447197551497088493517821469,3960000000000000001,56599464646994007045301,6.2598896662920003161687505143937e+32,1.601864623375e-8,62427247.93393113531856176367,37456348760.358681191137058202,0.00000961118774025,9611.1877402499999999999401991898801645,44.72 +5,392898709266936665636785679,4950000000000000001,56599464646994007045301,5.49981224800225909474172460778075e+32,2.075216633635e-8,48187740.19983656594194187607,28912644119.901939565165125642,0.00001245129980181,12451.29980180999999999992252801263313818,39.29 +6,350358134083096714672847995,5940000000000000001,56599464646994007045301,4.90432753359082085502970102286287e+32,2.609757979565e-8,38317729.37682895651801327538,22990637626.097373910807965228,0.00001565854787739,15658.54787738999999999990257251510687942,35.04 +7,316129627177621938378879720,6930000000000000001,56599464646994007045301,4.42519549150504797343401853382721e+32,3.205488661164e-8,31196491.57132912836537458997,18717894942.797477019224753982,0.000019232931966984,19232.931966983999999999880332697301425552,31.61 +8,287993847144385617704728986,7920000000000000001,56599464646994007045301,4.03134968981030868394522357990194e+32,3.862408678432e-8,25890579.77173685735628926882,15534347863.042114413773561292,0.000023174452070592,23174.452070591999999999855808559216776576,28.80 +9,264456973063307692761260695,8910000000000000001,56599464646994007045301,3.70187956206194376744902565503155e+32,4.58051803137e-8,21831591.82327278771949370883,13098955093.963672631696225298,0.00002748310818822,27483.10818821999999999982900010085289516,26.45 +10,244476630659629477660305230,9900000000000000001,56599464646994007045301,3.42219391045334010147146995418172e+32,5.359816719976e-8,18657354.388127468455692945,11194412632.876481073415767,0.000032158900319856,32158.900319855999999999799907322209855968,24.45 +11,227303332613958429940388460,10890000000000000001,56599464646994007045301,3.18180138077937157988527811561997e+32,6.200304744251e-8,16128239.51801996330049202874,9676943710.811977980295217244,0.000037201828465506,37201.828465505999999999768530223287621668,22.73 +12,212384360918002358703766933,11880000000000000001,56599464646994007045301,2.97296500371379918998270540067611e+32,7.101982104196e-8,14080576.17336438029945314627,8448345704.018628179671887762,0.000042611892625176,42611.892625175999999999734868804086154928,21.24 +13,199303169734764664133411686,12870000000000000001,56599464646994007045301,2.78985395356347574140626959762736e+32,8.06484879981e-8,12399488.50651261890021627922,7439693103.907571340129767532,0.00004838909279886,48389.09279885999999999969892306460549308,19.93 diff --git a/scripts/curve.ts b/scripts/curve.ts index 4d895d5..5c228f8 100644 --- a/scripts/curve.ts +++ b/scripts/curve.ts @@ -1,12 +1,10 @@ import { ethers } from "hardhat" -import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" import { FeeAmount, v3PartyFactory, deployContracts, weth9, bnbPartyFactory, BNBPositionManager } from "../test/helper" import { IUniswapV3Pool } from "../typechain-types" import BigNumber from "bignumber.js" import * as csvWriter from "csv-writer" -let signers: SignerWithAddress[] -const BNB_PRICE = 550 // BNB price in USD +const BNB_PRICE = 600 // BNB price in USD let lpContract: IUniswapV3Pool const createCsvWriter = csvWriter.createObjectCsvWriter @@ -18,8 +16,8 @@ const csv = createCsvWriter({ { id: "updatedWBNBAmount", title: "Updated WBNB Amount" }, { id: "updatedLiquidity", title: "Updated Liquidity" }, { id: "updatedSqrtPriceX96", title: "Updated sqrtPriceX96" }, - { id: "priceToken0InToken1", title: "Price of MEME in WBNB" }, - { id: "priceToken1InToken0", title: "Price of WBNB in MEME" }, + { id: "priceMemeInWbnb", title: "Price of MEME in WBNB" }, + { id: "priceWbnbInMeme", title: "Price of WBNB in MEME" }, { id: "wbnbValueUSD", title: "WBNB Value in USD" }, { id: "memeValueUSD", title: "MEME Value in USD" }, { id: "marketCap", title: "Market Cap in USD" }, @@ -28,7 +26,6 @@ const csv = createCsvWriter({ }) async function before() { - signers = await ethers.getSigners() await deployContracts() } @@ -48,24 +45,33 @@ async function getPoolData(lpContract: IUniswapV3Pool) { return { slot0, liquidity } } -function calculatePrices(sqrtPriceX96: BigNumber) { +function calculatePrices(sqrtPriceX96: BigNumber, token0: string, token1: string, meme: string) { const priceX96 = sqrtPriceX96.multipliedBy(sqrtPriceX96) const priceToken0InToken1 = priceX96.dividedBy(new BigNumber(2).pow(192)) const priceToken1InToken0 = new BigNumber(1).div(priceToken0InToken1) - return { priceToken0InToken1, priceToken1InToken0 } -} -async function logPrices(meme: string, priceToken0InToken1: BigNumber, priceToken1InToken0: BigNumber) { - const token0 = await lpContract.token0() + // Determine which token is MEME and which is WBNB if (token0 === meme) { - console.log(`Price of MEME in terms of WBNB: ${priceToken0InToken1.toString()}`) - console.log(`Price of WBNB in terms of MEME: ${priceToken1InToken0.toString()}`) + return { + priceMemeInWbnb: priceToken0InToken1, + priceWbnbInMeme: priceToken1InToken0, + } + } else if (token1 === meme) { + return { + priceMemeInWbnb: priceToken1InToken0, + priceWbnbInMeme: priceToken0InToken1, + } } else { - console.log(`Price of WBNB in terms of MEME: ${priceToken0InToken1.toString()}`) - console.log(`Price of MEME in terms of WBNB: ${priceToken1InToken0.toString()}`) + throw new Error("MEME token address does not match either token0 or token1 in the pool") } } +async function logPrices(meme: string, token0: string, token1: string, sqrtPriceX96: BigNumber) { + const { priceMemeInWbnb, priceWbnbInMeme } = calculatePrices(sqrtPriceX96, token0, token1, meme) + console.log(`Price of MEME in terms of WBNB: ${priceMemeInWbnb.toString()}`) + console.log(`Price of WBNB in terms of MEME: ${priceWbnbInMeme.toString()}`) +} + async function getTokenBalances(lpAddress: string, token: any) { const fullMEMEAmount = await token.balanceOf(lpAddress) const fullWBNBAmount = await weth9.balanceOf(lpAddress) @@ -119,11 +125,12 @@ async function test() { const { slot0, liquidity } = await getPoolData(lpContract) const sqrtPriceX96 = new BigNumber(slot0.sqrtPriceX96.toString()) - const { priceToken0InToken1, priceToken1InToken0 } = calculatePrices(sqrtPriceX96) + const token0 = await lpContract.token0() + const token1 = await lpContract.token1() - await logPrices(MEME, priceToken0InToken1, priceToken1InToken0) + await logPrices(MEME, token0, token1, sqrtPriceX96) - const target = 12 + const target = 13 for (let i = 0; i < target; i++) { const swapAmount = ethers.parseUnits("1", 18) await bnbPartyFactory.joinParty(MEME, 0, { value: swapAmount }) @@ -135,34 +142,29 @@ async function test() { console.log("Updated liquidity: ", updatedLiquidity.toString()) const updatedSqrtPriceX96 = new BigNumber(updatedSlot0.sqrtPriceX96.toString()) - const { priceToken0InToken1: updatedPriceToken0InToken1, priceToken1InToken0: updatedPriceToken1InToken0 } = - calculatePrices(updatedSqrtPriceX96) + const { priceMemeInWbnb: updatedPriceMemeInWbnb, priceWbnbInMeme: updatedPriceWbnbInMeme } = calculatePrices( + updatedSqrtPriceX96, + token0, + token1, + MEME + ) console.log(`Updated sqrtPriceX96: ${updatedSqrtPriceX96.toString()}`) if (!(updatedLiquidity == 0n)) { - await logPrices(MEME, updatedPriceToken0InToken1, updatedPriceToken1InToken0) + await logPrices(MEME, token0, token1, updatedSqrtPriceX96) // Calculate market cap - const wbnbValueUSD = new BigNumber(WBNBAmount.toString()) - .div(new BigNumber(10).pow(18)) - .multipliedBy(BNB_PRICE) - console.log(`WBNB value in USD: ${wbnbValueUSD.toString()}`) + const wbnbValueUSD = new BigNumber(WBNBAmount.toString()).div(new BigNumber(10).pow(18)).multipliedBy(BNB_PRICE) + console.log(`WBNB Value in Liquidity pool: ${wbnbValueUSD.toString()}`) - const memeValueInWBNB = new BigNumber(MEMEAmount.toString()) - .div(new BigNumber(10).pow(18)) - .multipliedBy(updatedPriceToken1InToken0) - const memeValueUSD = memeValueInWBNB.multipliedBy(BNB_PRICE) - console.log(`MEME value in USD: ${memeValueUSD.toString()}`) + const memeAmountInWbnb = new BigNumber(initialMEMEAmount.toString()).dividedBy(new BigNumber(10).pow(18)).multipliedBy(updatedPriceMemeInWbnb) + const marketCap = memeAmountInWbnb.multipliedBy(BNB_PRICE) - const marketCap = wbnbValueUSD.plus(memeValueUSD) - console.log(`Market Cap of Liquidity Pool in USD: ${marketCap.toString()}`) + console.log(`MEME Market Cap: ${marketCap.toString()}`) // Calculate the remaining percentage of MEME tokens - const remainingMEMEPercentage = new BigNumber(MEMEAmount.toString()) - .dividedBy(new BigNumber(initialMEMEAmount.toString())) - .multipliedBy(100) - .toFixed(2) + const remainingMEMEPercentage = new BigNumber(MEMEAmount.toString()).dividedBy(new BigNumber(initialMEMEAmount.toString())).multipliedBy(100).toFixed(2) console.log(`Remaining MEME tokens in the pool: ${remainingMEMEPercentage}%\n`) // Write data to CSV @@ -173,17 +175,17 @@ async function test() { updatedWBNBAmount: WBNBAmount.toString(), updatedLiquidity: updatedLiquidity.toString(), updatedSqrtPriceX96: updatedSqrtPriceX96.toString(), - priceToken0InToken1: updatedPriceToken0InToken1.toString(), - priceToken1InToken0: updatedPriceToken1InToken0.toString(), - wbnbValueUSD: wbnbValueUSD.toString(), - memeValueUSD: memeValueUSD.toString(), + priceMemeInWbnb: updatedPriceMemeInWbnb.toString(), + priceWbnbInMeme: updatedPriceWbnbInMeme.toString(), + wbnbValueUSD: updatedPriceWbnbInMeme.multipliedBy(BNB_PRICE).toString(), + memeValueUSD: updatedPriceMemeInWbnb.multipliedBy(BNB_PRICE).toString(), marketCap: marketCap.toString(), remainingMEMEPercentage: remainingMEMEPercentage, }, ]) } else { - console.log("Updated price of token0 in terms of token1: not available (liquidity is zero)") - console.log("Updated price of token1 in terms of token0: not available (liquidity is zero)") + console.log("Updated price of MEME in terms of WBNB: not available (liquidity is zero)") + console.log("Updated price of WBNB in terms of MEME: not available (liquidity is zero)") } } } diff --git a/test/BNBPartyFactory.ts b/test/BNBPartyFactory.ts index 3aa0a7a..f953474 100644 --- a/test/BNBPartyFactory.ts +++ b/test/BNBPartyFactory.ts @@ -28,7 +28,7 @@ describe("BNBPartyFactory", function () { const initialTokenAmount = "1000000000000000000000000000" const name = "Party" const symbol = "Token" - const sqrtPriceX96 = "7922427122162318518285487" + const sqrtPriceX96 = "1252685732681638336686364" const BNBToTarget: bigint = partyTarget + ethers.parseEther("1") before(async () => { @@ -46,8 +46,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()).tickUpper).to.equal("184200") - expect((await bnbPartyFactory.party()).tickLower).to.equal("-203800") + expect((await bnbPartyFactory.party()).tickUpper).to.equal("195600") + expect((await bnbPartyFactory.party()).tickLower).to.equal("-214200") }) it("should create party LP", async function () { diff --git a/test/SwapRouter.ts b/test/SwapRouter.ts index eeb90ac..02632db 100644 --- a/test/SwapRouter.ts +++ b/test/SwapRouter.ts @@ -49,7 +49,7 @@ describe("Smart Router", function () { }) it("user should receive meme token after join party", async () => { - const amountIn = ethers.parseUnits("5", 17) + const amountIn = ethers.parseUnits("1", 18) const balanceBefore = await MEMEToken.balanceOf(await signers[0].getAddress()) await bnbPartyFactory.joinParty(MEME, 0, { value: amountIn }) diff --git a/test/WithdrawFee.ts b/test/WithdrawFee.ts index 1e9cbe5..569455b 100644 --- a/test/WithdrawFee.ts +++ b/test/WithdrawFee.ts @@ -89,7 +89,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() - expect(await bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobalX128)).to.be.equal(amountIn / 100n - 1n) // 1 % fee + expect(await bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobalX128)).to.be.equal(amountIn / 100n) // 1 % fee }) it("calculateFees should return fee from 5 swaps", async () => { diff --git a/test/helper.ts b/test/helper.ts index 10b7d82..0480c96 100644 --- a/test/helper.ts +++ b/test/helper.ts @@ -43,7 +43,7 @@ export async function deployContracts() { const bonusFee = ethers.parseUnits("1", 16) const targetReachFee = ethers.parseUnits("1", 17) const initialTokenAmount = "1000000000000000000000000000" - const sqrtPriceX96 = "7922427122162318518285487" + const sqrtPriceX96 = "1252685732681638336686364" // Deploy WETH9 const WETH9 = await ethers.getContractFactory(WETH9Artifact.abi, WETH9Artifact.bytecode) weth9 = (await WETH9.deploy()) as IWBNB @@ -60,8 +60,8 @@ export async function deployContracts() { bonusTargetReach: returnFeeAmount, bonusPartyCreator: bonusFee, targetReachFee: targetReachFee, - tickLower: "-203800", - tickUpper: "184200", + tickLower: "-214200", + tickUpper: "195600", }, await weth9.getAddress() )) as BNBPartyFactory From b595631da6bcf70e773242a63432baa49860c367 Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Tue, 13 Aug 2024 14:50:26 +0300 Subject: [PATCH 06/21] remove csv --- liquidity_pool_data.csv | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 liquidity_pool_data.csv diff --git a/liquidity_pool_data.csv b/liquidity_pool_data.csv deleted file mode 100644 index c7532ea..0000000 --- a/liquidity_pool_data.csv +++ /dev/null @@ -1,14 +0,0 @@ -Iteration,Updated MEME Amount,Updated WBNB Amount,Updated Liquidity,Updated sqrtPriceX96,Price of MEME in WBNB,Price of WBNB in MEME,WBNB Value in USD,MEME Value in USD,Market Cap in USD,Remaining MEME % -1,763920318528615997030357345,990000000000000001,56599464646994007045301,1.069338793608067942170073033053952e+33,5.48944606607e-9,182167742.96788060040211602372,109300645780.728360241269614232,0.000003293667639642,3293.667639641999999999979506799946147476,76.39 -2,618018668105026337033216070,1980000000000000001,56599464646994007045301,8.65105065551534620165932366586375e+32,8.3872860986e-9,119228077.86017535494720531542,71536846716.105212968323189252,0.00000503237165916,5032.37165915999999999996868858353670648,61.80 -3,518911428661133039440715651,2970000000000000001,56599464646994007045301,7.26374345712156943258013749010645e+32,1.189701948783e-8,84054666.04664832143727731861,50432799627.988992862366391166,0.000007138211692698,7138.211692697999999999955586046848033044,51.89 -4,447197551497088493517821469,3960000000000000001,56599464646994007045301,6.2598896662920003161687505143937e+32,1.601864623375e-8,62427247.93393113531856176367,37456348760.358681191137058202,0.00000961118774025,9611.1877402499999999999401991898801645,44.72 -5,392898709266936665636785679,4950000000000000001,56599464646994007045301,5.49981224800225909474172460778075e+32,2.075216633635e-8,48187740.19983656594194187607,28912644119.901939565165125642,0.00001245129980181,12451.29980180999999999992252801263313818,39.29 -6,350358134083096714672847995,5940000000000000001,56599464646994007045301,4.90432753359082085502970102286287e+32,2.609757979565e-8,38317729.37682895651801327538,22990637626.097373910807965228,0.00001565854787739,15658.54787738999999999990257251510687942,35.04 -7,316129627177621938378879720,6930000000000000001,56599464646994007045301,4.42519549150504797343401853382721e+32,3.205488661164e-8,31196491.57132912836537458997,18717894942.797477019224753982,0.000019232931966984,19232.931966983999999999880332697301425552,31.61 -8,287993847144385617704728986,7920000000000000001,56599464646994007045301,4.03134968981030868394522357990194e+32,3.862408678432e-8,25890579.77173685735628926882,15534347863.042114413773561292,0.000023174452070592,23174.452070591999999999855808559216776576,28.80 -9,264456973063307692761260695,8910000000000000001,56599464646994007045301,3.70187956206194376744902565503155e+32,4.58051803137e-8,21831591.82327278771949370883,13098955093.963672631696225298,0.00002748310818822,27483.10818821999999999982900010085289516,26.45 -10,244476630659629477660305230,9900000000000000001,56599464646994007045301,3.42219391045334010147146995418172e+32,5.359816719976e-8,18657354.388127468455692945,11194412632.876481073415767,0.000032158900319856,32158.900319855999999999799907322209855968,24.45 -11,227303332613958429940388460,10890000000000000001,56599464646994007045301,3.18180138077937157988527811561997e+32,6.200304744251e-8,16128239.51801996330049202874,9676943710.811977980295217244,0.000037201828465506,37201.828465505999999999768530223287621668,22.73 -12,212384360918002358703766933,11880000000000000001,56599464646994007045301,2.97296500371379918998270540067611e+32,7.101982104196e-8,14080576.17336438029945314627,8448345704.018628179671887762,0.000042611892625176,42611.892625175999999999734868804086154928,21.24 -13,199303169734764664133411686,12870000000000000001,56599464646994007045301,2.78985395356347574140626959762736e+32,8.06484879981e-8,12399488.50651261890021627922,7439693103.907571340129767532,0.00004838909279886,48389.09279885999999999969892306460549308,19.93 From 50aca2a0264bd6348049b89f697970dd973a920e Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Tue, 13 Aug 2024 15:06:21 +0300 Subject: [PATCH 07/21] curve clearing --- scripts/curve.ts | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/scripts/curve.ts b/scripts/curve.ts index 5c228f8..050b817 100644 --- a/scripts/curve.ts +++ b/scripts/curve.ts @@ -38,13 +38,6 @@ async function createLiquidityPool() { return { MEME, position } } -async function getPoolData(lpContract: IUniswapV3Pool) { - const slot0 = await lpContract.slot0() - const liquidity = await lpContract.liquidity() - console.log("Liquidity: ", liquidity.toString()) - return { slot0, liquidity } -} - function calculatePrices(sqrtPriceX96: BigNumber, token0: string, token1: string, meme: string) { const priceX96 = sqrtPriceX96.multipliedBy(sqrtPriceX96) const priceToken0InToken1 = priceX96.dividedBy(new BigNumber(2).pow(192)) @@ -119,10 +112,10 @@ async function test() { const token = await ethers.getContractAt("ERC20Token", MEME) const lpAddress = await v3PartyFactory.getPool(position.token0, position.token1, FeeAmount.HIGH) - const { MEMEAmount, WBNBAmount } = await getTokenBalances(lpAddress, token) + const { MEMEAmount } = await getTokenBalances(lpAddress, token) const initialMEMEAmount = MEMEAmount // Save the initial MEME amount for later comparison lpContract = (await ethers.getContractAt("UniswapV3Pool", lpAddress)) as any as IUniswapV3Pool - const { slot0, liquidity } = await getPoolData(lpContract) + const slot0 = await lpContract.slot0() const sqrtPriceX96 = new BigNumber(slot0.sqrtPriceX96.toString()) const token0 = await lpContract.token0() From e9ed05545b6780ce3aa82c638077f449d98b59a0 Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Tue, 13 Aug 2024 15:35:04 +0300 Subject: [PATCH 08/21] refactor rurve.ts --- scripts/curve.ts | 146 ++++++++++++++++++++++------------------------- 1 file changed, 67 insertions(+), 79 deletions(-) diff --git a/scripts/curve.ts b/scripts/curve.ts index 050b817..65718cc 100644 --- a/scripts/curve.ts +++ b/scripts/curve.ts @@ -25,16 +25,14 @@ const csv = createCsvWriter({ ], }) -async function before() { - await deployContracts() -} - async function createLiquidityPool() { const tokenCreationFee = ethers.parseUnits("1", 16) await bnbPartyFactory.createParty("MEME", "MEME", { 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 wethAddress = await weth9.getAddress() // Await this to get the WETH address string + const MEME = position.token1 === wethAddress ? position.token0 : position.token1 return { MEME, position } } @@ -66,48 +64,44 @@ async function logPrices(meme: string, token0: string, token1: string, sqrtPrice } async function getTokenBalances(lpAddress: string, token: any) { - const fullMEMEAmount = await token.balanceOf(lpAddress) - const fullWBNBAmount = await weth9.balanceOf(lpAddress) + const [fullMEMEAmount, fullWBNBAmount, wethAddress] = await Promise.all([ + token.balanceOf(lpAddress), + weth9.balanceOf(lpAddress), + weth9.getAddress(), + ]) + const lpPool = await ethers.getContractAt("UniswapV3Pool", lpAddress) - let feeGrowthGlobal0X128 = await lpPool.feeGrowthGlobal0X128() - let feeGrowthGlobal1X128 = await lpPool.feeGrowthGlobal1X128() - let liquidity = await lpPool.liquidity() - let getFeeGlobal = await bnbPartyFactory.getFeeGrowthInsideLastX128(lpAddress) - let wbnbFee - let memeFee - if ((await lpPool.token0()) === (await weth9.getAddress())) { - wbnbFee = await bnbPartyFactory.calculateFees( - liquidity, - feeGrowthGlobal0X128 - getFeeGlobal.feeGrowthInside0LastX128 - ) - memeFee = await bnbPartyFactory.calculateFees( - liquidity, - feeGrowthGlobal1X128 - getFeeGlobal.feeGrowthInside1LastX128 - ) - console.log("WBNB fee: ", wbnbFee) - console.log("MEME fee: ", memeFee) - console.log("WBNB amount: ", fullWBNBAmount - wbnbFee) - console.log("MEME amount: ", fullMEMEAmount - memeFee) - } else { - wbnbFee = await bnbPartyFactory.calculateFees( - liquidity, - feeGrowthGlobal1X128 - getFeeGlobal.feeGrowthInside1LastX128 - ) - memeFee = await bnbPartyFactory.calculateFees( - liquidity, - feeGrowthGlobal0X128 - getFeeGlobal.feeGrowthInside0LastX128 - ) - console.log("WBNB fee: ", wbnbFee) - console.log("MEME fee: ", memeFee) - console.log("WBNB amount: ", fullWBNBAmount - wbnbFee) - console.log("MEME amount: ", fullMEMEAmount - memeFee) - } + const [feeGrowthGlobal0X128, feeGrowthGlobal1X128, liquidity, getFeeGlobal] = await Promise.all([ + lpPool.feeGrowthGlobal0X128(), + lpPool.feeGrowthGlobal1X128(), + lpPool.liquidity(), + bnbPartyFactory.getFeeGrowthInsideLastX128(lpAddress), + ]) + const token0 = await lpPool.token0() + const token1 = await lpPool.token1() + + const isToken0WBNB = token0 === wethAddress + const isToken1WBNB = token1 === wethAddress + + const [wbnbFee, memeFee] = await Promise.all([ + isToken0WBNB + ? bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobal0X128 - getFeeGlobal.feeGrowthInside0LastX128) + : bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobal1X128 - getFeeGlobal.feeGrowthInside1LastX128), + isToken1WBNB + ? bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobal0X128 - getFeeGlobal.feeGrowthInside0LastX128) + : bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobal1X128 - getFeeGlobal.feeGrowthInside1LastX128), + ]) + + console.log("WBNB fee: ", wbnbFee) + console.log("MEME fee: ", memeFee) + console.log("WBNB amount: ", fullWBNBAmount - wbnbFee) + console.log("MEME amount: ", fullMEMEAmount - memeFee) return { WBNBAmount: fullWBNBAmount - wbnbFee, MEMEAmount: fullMEMEAmount - memeFee } } async function test() { - await before() + await deployContracts() const { MEME, position } = await createLiquidityPool() const token = await ethers.getContractAt("ERC20Token", MEME) const lpAddress = await v3PartyFactory.getPool(position.token0, position.token1, FeeAmount.HIGH) @@ -118,8 +112,7 @@ async function test() { const slot0 = await lpContract.slot0() const sqrtPriceX96 = new BigNumber(slot0.sqrtPriceX96.toString()) - const token0 = await lpContract.token0() - const token1 = await lpContract.token1() + const [token0, token1] = await Promise.all([lpContract.token0(), lpContract.token1()]) await logPrices(MEME, token0, token1, sqrtPriceX96) @@ -144,42 +137,37 @@ async function test() { console.log(`Updated sqrtPriceX96: ${updatedSqrtPriceX96.toString()}`) - if (!(updatedLiquidity == 0n)) { - await logPrices(MEME, token0, token1, updatedSqrtPriceX96) - - // Calculate market cap - const wbnbValueUSD = new BigNumber(WBNBAmount.toString()).div(new BigNumber(10).pow(18)).multipliedBy(BNB_PRICE) - console.log(`WBNB Value in Liquidity pool: ${wbnbValueUSD.toString()}`) - - const memeAmountInWbnb = new BigNumber(initialMEMEAmount.toString()).dividedBy(new BigNumber(10).pow(18)).multipliedBy(updatedPriceMemeInWbnb) - const marketCap = memeAmountInWbnb.multipliedBy(BNB_PRICE) - - console.log(`MEME Market Cap: ${marketCap.toString()}`) - - // Calculate the remaining percentage of MEME tokens - const remainingMEMEPercentage = new BigNumber(MEMEAmount.toString()).dividedBy(new BigNumber(initialMEMEAmount.toString())).multipliedBy(100).toFixed(2) - console.log(`Remaining MEME tokens in the pool: ${remainingMEMEPercentage}%\n`) - - // Write data to CSV - await csv.writeRecords([ - { - iteration: i + 1, - updatedMEMEAmount: MEMEAmount.toString(), - updatedWBNBAmount: WBNBAmount.toString(), - updatedLiquidity: updatedLiquidity.toString(), - updatedSqrtPriceX96: updatedSqrtPriceX96.toString(), - priceMemeInWbnb: updatedPriceMemeInWbnb.toString(), - priceWbnbInMeme: updatedPriceWbnbInMeme.toString(), - wbnbValueUSD: updatedPriceWbnbInMeme.multipliedBy(BNB_PRICE).toString(), - memeValueUSD: updatedPriceMemeInWbnb.multipliedBy(BNB_PRICE).toString(), - marketCap: marketCap.toString(), - remainingMEMEPercentage: remainingMEMEPercentage, - }, - ]) - } else { - console.log("Updated price of MEME in terms of WBNB: not available (liquidity is zero)") - console.log("Updated price of WBNB in terms of MEME: not available (liquidity is zero)") - } + await logPrices(MEME, token0, token1, updatedSqrtPriceX96) + + // Calculate market cap + const wbnbValueUSD = new BigNumber(WBNBAmount.toString()).div(new BigNumber(10).pow(18)).multipliedBy(BNB_PRICE) + console.log(`WBNB Value in Liquidity pool: ${wbnbValueUSD.toString()}`) + + const memeAmountInWbnb = new BigNumber(initialMEMEAmount.toString()).div(new BigNumber(10).pow(18)).multipliedBy(updatedPriceMemeInWbnb) + const marketCap = memeAmountInWbnb.multipliedBy(BNB_PRICE) + + console.log(`MEME Market Cap: ${marketCap.toString()}`) + + // Calculate the remaining percentage of MEME tokens + const remainingMEMEPercentage = new BigNumber(MEMEAmount.toString()).dividedBy(new BigNumber(initialMEMEAmount.toString())).multipliedBy(100).toFixed(2) + console.log(`Remaining MEME tokens in the pool: ${remainingMEMEPercentage}%\n`) + + // Write data to CSV + await csv.writeRecords([ + { + iteration: i + 1, + updatedMEMEAmount: MEMEAmount.toString(), + updatedWBNBAmount: WBNBAmount.toString(), + updatedLiquidity: updatedLiquidity.toString(), + updatedSqrtPriceX96: updatedSqrtPriceX96.toString(), + priceMemeInWbnb: updatedPriceMemeInWbnb.toString(), + priceWbnbInMeme: updatedPriceWbnbInMeme.toString(), + wbnbValueUSD: wbnbValueUSD.toString(), + memeValueUSD: memeAmountInWbnb.toString(), + marketCap: marketCap.toString(), + remainingMEMEPercentage: remainingMEMEPercentage, + }, + ]) } } From 5f0f336573386fdbd4c8bfa1e6aa6b64fac3df1d Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Tue, 13 Aug 2024 16:02:48 +0300 Subject: [PATCH 09/21] refactor logs --- scripts/curve.ts | 45 ++++++++++++--------------------------------- 1 file changed, 12 insertions(+), 33 deletions(-) diff --git a/scripts/curve.ts b/scripts/curve.ts index 65718cc..63550d1 100644 --- a/scripts/curve.ts +++ b/scripts/curve.ts @@ -18,8 +18,8 @@ const csv = createCsvWriter({ { id: "updatedSqrtPriceX96", title: "Updated sqrtPriceX96" }, { id: "priceMemeInWbnb", title: "Price of MEME in WBNB" }, { id: "priceWbnbInMeme", title: "Price of WBNB in MEME" }, - { id: "wbnbValueUSD", title: "WBNB Value in USD" }, - { id: "memeValueUSD", title: "MEME Value in USD" }, + { id: "wbnb value in lp", title: "WBNB Value in USD" }, + { id: "meme value in lp", title: "MEME Value in USD" }, { id: "marketCap", title: "Market Cap in USD" }, { id: "remainingMEMEPercentage", title: "Remaining MEME %" }, ], @@ -31,7 +31,7 @@ async function createLiquidityPool() { const tokenId = await BNBPositionManager.totalSupply() const position = await BNBPositionManager.positions(tokenId) - const wethAddress = await weth9.getAddress() // Await this to get the WETH address string + const wethAddress = await weth9.getAddress() const MEME = position.token1 === wethAddress ? position.token0 : position.token1 return { MEME, position } } @@ -40,7 +40,6 @@ function calculatePrices(sqrtPriceX96: BigNumber, token0: string, token1: string const priceX96 = sqrtPriceX96.multipliedBy(sqrtPriceX96) const priceToken0InToken1 = priceX96.dividedBy(new BigNumber(2).pow(192)) const priceToken1InToken0 = new BigNumber(1).div(priceToken0InToken1) - // Determine which token is MEME and which is WBNB if (token0 === meme) { return { @@ -57,12 +56,6 @@ function calculatePrices(sqrtPriceX96: BigNumber, token0: string, token1: string } } -async function logPrices(meme: string, token0: string, token1: string, sqrtPriceX96: BigNumber) { - const { priceMemeInWbnb, priceWbnbInMeme } = calculatePrices(sqrtPriceX96, token0, token1, meme) - console.log(`Price of MEME in terms of WBNB: ${priceMemeInWbnb.toString()}`) - console.log(`Price of WBNB in terms of MEME: ${priceWbnbInMeme.toString()}`) -} - async function getTokenBalances(lpAddress: string, token: any) { const [fullMEMEAmount, fullWBNBAmount, wethAddress] = await Promise.all([ token.balanceOf(lpAddress), @@ -92,11 +85,6 @@ async function getTokenBalances(lpAddress: string, token: any) { : bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobal1X128 - getFeeGlobal.feeGrowthInside1LastX128), ]) - console.log("WBNB fee: ", wbnbFee) - console.log("MEME fee: ", memeFee) - console.log("WBNB amount: ", fullWBNBAmount - wbnbFee) - console.log("MEME amount: ", fullMEMEAmount - memeFee) - return { WBNBAmount: fullWBNBAmount - wbnbFee, MEMEAmount: fullMEMEAmount - memeFee } } @@ -114,18 +102,13 @@ async function test() { const sqrtPriceX96 = new BigNumber(slot0.sqrtPriceX96.toString()) const [token0, token1] = await Promise.all([lpContract.token0(), lpContract.token1()]) - await logPrices(MEME, token0, token1, sqrtPriceX96) - const target = 13 for (let i = 0; i < target; i++) { const swapAmount = ethers.parseUnits("1", 18) await bnbPartyFactory.joinParty(MEME, 0, { value: swapAmount }) const { MEMEAmount, WBNBAmount } = await getTokenBalances(lpAddress, token) - console.log("Updated MEME amount: ", MEMEAmount.toString()) - console.log("Updated WBNB amount: ", WBNBAmount.toString()) const updatedSlot0 = await lpContract.slot0() const updatedLiquidity = await lpContract.liquidity() - console.log("Updated liquidity: ", updatedLiquidity.toString()) const updatedSqrtPriceX96 = new BigNumber(updatedSlot0.sqrtPriceX96.toString()) const { priceMemeInWbnb: updatedPriceMemeInWbnb, priceWbnbInMeme: updatedPriceWbnbInMeme } = calculatePrices( @@ -135,25 +118,17 @@ async function test() { MEME ) - console.log(`Updated sqrtPriceX96: ${updatedSqrtPriceX96.toString()}`) - - await logPrices(MEME, token0, token1, updatedSqrtPriceX96) - // Calculate market cap const wbnbValueUSD = new BigNumber(WBNBAmount.toString()).div(new BigNumber(10).pow(18)).multipliedBy(BNB_PRICE) - console.log(`WBNB Value in Liquidity pool: ${wbnbValueUSD.toString()}`) - const memeAmountInWbnb = new BigNumber(initialMEMEAmount.toString()).div(new BigNumber(10).pow(18)).multipliedBy(updatedPriceMemeInWbnb) + const memeValueUSD = new BigNumber(MEMEAmount.toString()).div(new BigNumber(10).pow(18)).multipliedBy(updatedPriceMemeInWbnb).multipliedBy(BNB_PRICE) const marketCap = memeAmountInWbnb.multipliedBy(BNB_PRICE) - console.log(`MEME Market Cap: ${marketCap.toString()}`) - // Calculate the remaining percentage of MEME tokens const remainingMEMEPercentage = new BigNumber(MEMEAmount.toString()).dividedBy(new BigNumber(initialMEMEAmount.toString())).multipliedBy(100).toFixed(2) - console.log(`Remaining MEME tokens in the pool: ${remainingMEMEPercentage}%\n`) - // Write data to CSV - await csv.writeRecords([ + // Prepare data for logging + const data = [ { iteration: i + 1, updatedMEMEAmount: MEMEAmount.toString(), @@ -163,11 +138,15 @@ async function test() { priceMemeInWbnb: updatedPriceMemeInWbnb.toString(), priceWbnbInMeme: updatedPriceWbnbInMeme.toString(), wbnbValueUSD: wbnbValueUSD.toString(), - memeValueUSD: memeAmountInWbnb.toString(), + memeValueUSD: memeValueUSD.toString(), marketCap: marketCap.toString(), remainingMEMEPercentage: remainingMEMEPercentage, }, - ]) + ] + console.log(data) + + // Write data to CSV + await csv.writeRecords(data) } } From e16ecfb695840c774e3b2d124d5254b0ec4a4961 Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Tue, 13 Aug 2024 16:08:09 +0300 Subject: [PATCH 10/21] clean --- scripts/curve.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/scripts/curve.ts b/scripts/curve.ts index 63550d1..4c04e5e 100644 --- a/scripts/curve.ts +++ b/scripts/curve.ts @@ -97,9 +97,6 @@ async function test() { const { MEMEAmount } = await getTokenBalances(lpAddress, token) const initialMEMEAmount = MEMEAmount // Save the initial MEME amount for later comparison lpContract = (await ethers.getContractAt("UniswapV3Pool", lpAddress)) as any as IUniswapV3Pool - const slot0 = await lpContract.slot0() - - const sqrtPriceX96 = new BigNumber(slot0.sqrtPriceX96.toString()) const [token0, token1] = await Promise.all([lpContract.token0(), lpContract.token1()]) const target = 13 From c176c1b00856383345ff4a3a0b7813cb6b6a5d52 Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Tue, 13 Aug 2024 16:26:43 +0300 Subject: [PATCH 11/21] add more iterations, fix csv --- scripts/curve.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/curve.ts b/scripts/curve.ts index 4c04e5e..24e78a9 100644 --- a/scripts/curve.ts +++ b/scripts/curve.ts @@ -18,8 +18,8 @@ const csv = createCsvWriter({ { id: "updatedSqrtPriceX96", title: "Updated sqrtPriceX96" }, { id: "priceMemeInWbnb", title: "Price of MEME in WBNB" }, { id: "priceWbnbInMeme", title: "Price of WBNB in MEME" }, - { id: "wbnb value in lp", title: "WBNB Value in USD" }, - { id: "meme value in lp", title: "MEME Value in USD" }, + { id: "wbnbValueInLp", title: "WBNB Value in USD" }, + { id: "memealueInLp", title: "MEME Value in USD" }, { id: "marketCap", title: "Market Cap in USD" }, { id: "remainingMEMEPercentage", title: "Remaining MEME %" }, ], @@ -99,9 +99,9 @@ async function test() { lpContract = (await ethers.getContractAt("UniswapV3Pool", lpAddress)) as any as IUniswapV3Pool const [token0, token1] = await Promise.all([lpContract.token0(), lpContract.token1()]) - const target = 13 + const target = 26 for (let i = 0; i < target; i++) { - const swapAmount = ethers.parseUnits("1", 18) + const swapAmount = ethers.parseUnits("5", 17) await bnbPartyFactory.joinParty(MEME, 0, { value: swapAmount }) const { MEMEAmount, WBNBAmount } = await getTokenBalances(lpAddress, token) const updatedSlot0 = await lpContract.slot0() @@ -134,8 +134,8 @@ async function test() { updatedSqrtPriceX96: updatedSqrtPriceX96.toString(), priceMemeInWbnb: updatedPriceMemeInWbnb.toString(), priceWbnbInMeme: updatedPriceWbnbInMeme.toString(), - wbnbValueUSD: wbnbValueUSD.toString(), - memeValueUSD: memeValueUSD.toString(), + wbnbValueInLp: wbnbValueUSD.toString(), + memealueInLp: memeValueUSD.toString(), marketCap: marketCap.toString(), remainingMEMEPercentage: remainingMEMEPercentage, }, From df707625be48ec24e092b769b6c6584341ae7e42 Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Wed, 14 Aug 2024 10:21:59 +0300 Subject: [PATCH 12/21] remove liquidity field --- scripts/curve.ts | 3 --- test/BNBPartyFactory.ts | 4 ++-- test/helper.ts | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/scripts/curve.ts b/scripts/curve.ts index 24e78a9..d86c044 100644 --- a/scripts/curve.ts +++ b/scripts/curve.ts @@ -14,7 +14,6 @@ const csv = createCsvWriter({ { id: "iteration", title: "Iteration" }, { id: "updatedMEMEAmount", title: "Updated MEME Amount" }, { id: "updatedWBNBAmount", title: "Updated WBNB Amount" }, - { id: "updatedLiquidity", title: "Updated Liquidity" }, { id: "updatedSqrtPriceX96", title: "Updated sqrtPriceX96" }, { id: "priceMemeInWbnb", title: "Price of MEME in WBNB" }, { id: "priceWbnbInMeme", title: "Price of WBNB in MEME" }, @@ -105,7 +104,6 @@ async function test() { await bnbPartyFactory.joinParty(MEME, 0, { value: swapAmount }) const { MEMEAmount, WBNBAmount } = await getTokenBalances(lpAddress, token) const updatedSlot0 = await lpContract.slot0() - const updatedLiquidity = await lpContract.liquidity() const updatedSqrtPriceX96 = new BigNumber(updatedSlot0.sqrtPriceX96.toString()) const { priceMemeInWbnb: updatedPriceMemeInWbnb, priceWbnbInMeme: updatedPriceWbnbInMeme } = calculatePrices( @@ -130,7 +128,6 @@ async function test() { iteration: i + 1, updatedMEMEAmount: MEMEAmount.toString(), updatedWBNBAmount: WBNBAmount.toString(), - updatedLiquidity: updatedLiquidity.toString(), updatedSqrtPriceX96: updatedSqrtPriceX96.toString(), priceMemeInWbnb: updatedPriceMemeInWbnb.toString(), priceWbnbInMeme: updatedPriceWbnbInMeme.toString(), diff --git a/test/BNBPartyFactory.ts b/test/BNBPartyFactory.ts index f953474..cf2db9b 100644 --- a/test/BNBPartyFactory.ts +++ b/test/BNBPartyFactory.ts @@ -46,7 +46,7 @@ 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()).tickUpper).to.equal("195600") + expect((await bnbPartyFactory.party()).tickUpper).to.equal("195400") expect((await bnbPartyFactory.party()).tickLower).to.equal("-214200") }) @@ -146,7 +146,7 @@ describe("BNBPartyFactory", function () { const newBalance = await token.balanceOf(newLPPool) const userBalance = await token.balanceOf(await signers[0].getAddress()) const bnbpartyBalance = await token.balanceOf(await bnbPartyFactory.getAddress()) - expect(newBalance).to.be.equal(oldBalance + rest - userBalance - bnbpartyBalance - 2n) + expect(newBalance).to.be.equal(oldBalance + rest - userBalance - bnbpartyBalance - 1n) }) it("should send WBNB to new LP", async () => { diff --git a/test/helper.ts b/test/helper.ts index 0480c96..ac67e8e 100644 --- a/test/helper.ts +++ b/test/helper.ts @@ -61,7 +61,7 @@ export async function deployContracts() { bonusPartyCreator: bonusFee, targetReachFee: targetReachFee, tickLower: "-214200", - tickUpper: "195600", + tickUpper: "195400", }, await weth9.getAddress() )) as BNBPartyFactory From 6a2541445302f6ea710771e37bb8d0cbefccdc39 Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Wed, 14 Aug 2024 11:04:39 +0300 Subject: [PATCH 13/21] add zero iteration, refactor --- scripts/curve.ts | 136 ++++++++++++++++++++++------------------------- 1 file changed, 64 insertions(+), 72 deletions(-) diff --git a/scripts/curve.ts b/scripts/curve.ts index d86c044..3b8f1b9 100644 --- a/scripts/curve.ts +++ b/scripts/curve.ts @@ -18,7 +18,7 @@ const csv = createCsvWriter({ { id: "priceMemeInWbnb", title: "Price of MEME in WBNB" }, { id: "priceWbnbInMeme", title: "Price of WBNB in MEME" }, { id: "wbnbValueInLp", title: "WBNB Value in USD" }, - { id: "memealueInLp", title: "MEME Value in USD" }, + { id: "memeValueInLp", title: "MEME Value in USD" }, { id: "marketCap", title: "Market Cap in USD" }, { id: "remainingMEMEPercentage", title: "Remaining MEME %" }, ], @@ -36,27 +36,16 @@ async function createLiquidityPool() { } function calculatePrices(sqrtPriceX96: BigNumber, token0: string, token1: string, meme: string) { - const priceX96 = sqrtPriceX96.multipliedBy(sqrtPriceX96) + const priceX96 = sqrtPriceX96.pow(2) const priceToken0InToken1 = priceX96.dividedBy(new BigNumber(2).pow(192)) const priceToken1InToken0 = new BigNumber(1).div(priceToken0InToken1) - // Determine which token is MEME and which is WBNB - if (token0 === meme) { - return { - priceMemeInWbnb: priceToken0InToken1, - priceWbnbInMeme: priceToken1InToken0, - } - } else if (token1 === meme) { - return { - priceMemeInWbnb: priceToken1InToken0, - priceWbnbInMeme: priceToken0InToken1, - } - } else { - throw new Error("MEME token address does not match either token0 or token1 in the pool") - } + return token0 === meme + ? { priceMemeInWbnb: priceToken0InToken1, priceWbnbInMeme: priceToken1InToken0 } + : { priceMemeInWbnb: priceToken1InToken0, priceWbnbInMeme: priceToken0InToken1 } } async function getTokenBalances(lpAddress: string, token: any) { - const [fullMEMEAmount, fullWBNBAmount, wethAddress] = await Promise.all([ + const [MEMEAmount, WBNBAmount, wethAddress] = await Promise.all([ token.balanceOf(lpAddress), weth9.balanceOf(lpAddress), weth9.getAddress(), @@ -70,21 +59,48 @@ async function getTokenBalances(lpAddress: string, token: any) { bnbPartyFactory.getFeeGrowthInsideLastX128(lpAddress), ]) const token0 = await lpPool.token0() - const token1 = await lpPool.token1() - - const isToken0WBNB = token0 === wethAddress - const isToken1WBNB = token1 === wethAddress - - const [wbnbFee, memeFee] = await Promise.all([ - isToken0WBNB - ? bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobal0X128 - getFeeGlobal.feeGrowthInside0LastX128) - : bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobal1X128 - getFeeGlobal.feeGrowthInside1LastX128), - isToken1WBNB - ? bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobal0X128 - getFeeGlobal.feeGrowthInside0LastX128) - : bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobal1X128 - getFeeGlobal.feeGrowthInside1LastX128), - ]) + let wbnbFee, memeFee + + if (token0 === wethAddress) { + wbnbFee = await bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobal0X128 - getFeeGlobal.feeGrowthInside0LastX128) + memeFee = await bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobal1X128 - getFeeGlobal.feeGrowthInside1LastX128) + } else { + memeFee = await bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobal0X128 - getFeeGlobal.feeGrowthInside0LastX128) + wbnbFee = await bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobal1X128 - getFeeGlobal.feeGrowthInside1LastX128) + } + + return { WBNBAmount: new BigNumber((WBNBAmount - wbnbFee).toString()), MEMEAmount: new BigNumber((MEMEAmount - memeFee).toString()) } +} - return { WBNBAmount: fullWBNBAmount - wbnbFee, MEMEAmount: fullMEMEAmount - memeFee } +async function logData( + iteration: number, + MEMEAmount: BigNumber, + WBNBAmount: BigNumber, + updatedSqrtPriceX96: BigNumber, + updatedPriceMemeInWbnb: BigNumber, + updatedPriceWbnbInMeme: BigNumber, + initialMEMEAmount: BigNumber +) { + const wbnbValueUSD = WBNBAmount.div(new BigNumber(10).pow(18)).multipliedBy(BNB_PRICE) + const memeValueUSD = MEMEAmount.div(new BigNumber(10).pow(18)).multipliedBy(updatedPriceMemeInWbnb).multipliedBy(BNB_PRICE) + const marketCap = initialMEMEAmount.div(new BigNumber(10).pow(18)).multipliedBy(updatedPriceMemeInWbnb).multipliedBy(BNB_PRICE) + const remainingMEMEPercentage = MEMEAmount.div(initialMEMEAmount).multipliedBy(100).toFixed(2) + + const data = { + iteration, + updatedMEMEAmount: MEMEAmount.toString(), + updatedWBNBAmount: WBNBAmount.toString(), + updatedSqrtPriceX96: updatedSqrtPriceX96.toString(), + priceMemeInWbnb: updatedPriceMemeInWbnb.toString(), + priceWbnbInMeme: updatedPriceWbnbInMeme.toString(), + wbnbValueInLp: wbnbValueUSD.toString(), + memeValueInLp: memeValueUSD.toString(), + marketCap: marketCap.toString(), + remainingMEMEPercentage, + } + + console.log(data) + await csv.writeRecords([data]) } async function test() { @@ -92,55 +108,31 @@ async function test() { const { MEME, position } = await createLiquidityPool() const token = await ethers.getContractAt("ERC20Token", MEME) const lpAddress = await v3PartyFactory.getPool(position.token0, position.token1, FeeAmount.HIGH) - - const { MEMEAmount } = await getTokenBalances(lpAddress, token) - const initialMEMEAmount = MEMEAmount // Save the initial MEME amount for later comparison lpContract = (await ethers.getContractAt("UniswapV3Pool", lpAddress)) as any as IUniswapV3Pool - const [token0, token1] = await Promise.all([lpContract.token0(), lpContract.token1()]) + + const { MEMEAmount: initialMEMEAmount, WBNBAmount } = await getTokenBalances(lpAddress, token) + const slot0 = await lpContract.slot0() + const updatedSqrtPriceX96 = new BigNumber(slot0.sqrtPriceX96.toString()) + const { priceMemeInWbnb, priceWbnbInMeme } = calculatePrices( + updatedSqrtPriceX96, + await lpContract.token0(), + await lpContract.token1(), + MEME + ) + + await logData(0, initialMEMEAmount, WBNBAmount, updatedSqrtPriceX96, priceMemeInWbnb, priceWbnbInMeme, initialMEMEAmount) const target = 26 - for (let i = 0; i < target; i++) { + for (let i = 1; i <= target; ++i) { const swapAmount = ethers.parseUnits("5", 17) await bnbPartyFactory.joinParty(MEME, 0, { value: swapAmount }) + const { MEMEAmount, WBNBAmount } = await getTokenBalances(lpAddress, token) const updatedSlot0 = await lpContract.slot0() - const updatedSqrtPriceX96 = new BigNumber(updatedSlot0.sqrtPriceX96.toString()) - const { priceMemeInWbnb: updatedPriceMemeInWbnb, priceWbnbInMeme: updatedPriceWbnbInMeme } = calculatePrices( - updatedSqrtPriceX96, - token0, - token1, - MEME - ) - - // Calculate market cap - const wbnbValueUSD = new BigNumber(WBNBAmount.toString()).div(new BigNumber(10).pow(18)).multipliedBy(BNB_PRICE) - const memeAmountInWbnb = new BigNumber(initialMEMEAmount.toString()).div(new BigNumber(10).pow(18)).multipliedBy(updatedPriceMemeInWbnb) - const memeValueUSD = new BigNumber(MEMEAmount.toString()).div(new BigNumber(10).pow(18)).multipliedBy(updatedPriceMemeInWbnb).multipliedBy(BNB_PRICE) - const marketCap = memeAmountInWbnb.multipliedBy(BNB_PRICE) - - // Calculate the remaining percentage of MEME tokens - const remainingMEMEPercentage = new BigNumber(MEMEAmount.toString()).dividedBy(new BigNumber(initialMEMEAmount.toString())).multipliedBy(100).toFixed(2) - - // Prepare data for logging - const data = [ - { - iteration: i + 1, - updatedMEMEAmount: MEMEAmount.toString(), - updatedWBNBAmount: WBNBAmount.toString(), - updatedSqrtPriceX96: updatedSqrtPriceX96.toString(), - priceMemeInWbnb: updatedPriceMemeInWbnb.toString(), - priceWbnbInMeme: updatedPriceWbnbInMeme.toString(), - wbnbValueInLp: wbnbValueUSD.toString(), - memealueInLp: memeValueUSD.toString(), - marketCap: marketCap.toString(), - remainingMEMEPercentage: remainingMEMEPercentage, - }, - ] - console.log(data) - - // Write data to CSV - await csv.writeRecords(data) + const { priceMemeInWbnb, priceWbnbInMeme } = calculatePrices(updatedSqrtPriceX96, await lpContract.token0(), await lpContract.token1(), MEME) + + await logData(i, MEMEAmount, WBNBAmount, updatedSqrtPriceX96, priceMemeInWbnb, priceWbnbInMeme, initialMEMEAmount) } } From d42fb80bf3d6b3ba3d082d0a20f7d5255bfe92ce Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Wed, 14 Aug 2024 11:18:11 +0300 Subject: [PATCH 14/21] update field names --- scripts/curve.ts | 45 ++++++++++++++++++++------------------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/scripts/curve.ts b/scripts/curve.ts index 3b8f1b9..9b50185 100644 --- a/scripts/curve.ts +++ b/scripts/curve.ts @@ -12,9 +12,9 @@ const csv = createCsvWriter({ path: "liquidity_pool_data.csv", header: [ { id: "iteration", title: "Iteration" }, - { id: "updatedMEMEAmount", title: "Updated MEME Amount" }, - { id: "updatedWBNBAmount", title: "Updated WBNB Amount" }, - { id: "updatedSqrtPriceX96", title: "Updated sqrtPriceX96" }, + { id: "MEMEAmount", title: "MEME Amount" }, + { id: "WBNBAmount", title: "WBNB Amount" }, + { id: "SqrtPriceX96", title: "sqrtPriceX96" }, { id: "priceMemeInWbnb", title: "Price of MEME in WBNB" }, { id: "priceWbnbInMeme", title: "Price of WBNB in MEME" }, { id: "wbnbValueInLp", title: "WBNB Value in USD" }, @@ -76,23 +76,23 @@ async function logData( iteration: number, MEMEAmount: BigNumber, WBNBAmount: BigNumber, - updatedSqrtPriceX96: BigNumber, - updatedPriceMemeInWbnb: BigNumber, - updatedPriceWbnbInMeme: BigNumber, + sqrtPriceX96: BigNumber, + priceMemeInWbnb: BigNumber, + priceWbnbInMeme: BigNumber, initialMEMEAmount: BigNumber ) { const wbnbValueUSD = WBNBAmount.div(new BigNumber(10).pow(18)).multipliedBy(BNB_PRICE) - const memeValueUSD = MEMEAmount.div(new BigNumber(10).pow(18)).multipliedBy(updatedPriceMemeInWbnb).multipliedBy(BNB_PRICE) - const marketCap = initialMEMEAmount.div(new BigNumber(10).pow(18)).multipliedBy(updatedPriceMemeInWbnb).multipliedBy(BNB_PRICE) + const memeValueUSD = MEMEAmount.div(new BigNumber(10).pow(18)).multipliedBy(priceMemeInWbnb).multipliedBy(BNB_PRICE) + const marketCap = initialMEMEAmount.div(new BigNumber(10).pow(18)).multipliedBy(priceMemeInWbnb).multipliedBy(BNB_PRICE) const remainingMEMEPercentage = MEMEAmount.div(initialMEMEAmount).multipliedBy(100).toFixed(2) const data = { iteration, - updatedMEMEAmount: MEMEAmount.toString(), - updatedWBNBAmount: WBNBAmount.toString(), - updatedSqrtPriceX96: updatedSqrtPriceX96.toString(), - priceMemeInWbnb: updatedPriceMemeInWbnb.toString(), - priceWbnbInMeme: updatedPriceWbnbInMeme.toString(), + MEMEAmount: MEMEAmount.toString(), + WBNBAmount: WBNBAmount.toString(), + SqrtPriceX96: sqrtPriceX96.toString(), + priceMemeInWbnb: priceMemeInWbnb.toString(), + priceWbnbInMeme: priceWbnbInMeme.toString(), wbnbValueInLp: wbnbValueUSD.toString(), memeValueInLp: memeValueUSD.toString(), marketCap: marketCap.toString(), @@ -112,15 +112,10 @@ async function test() { const { MEMEAmount: initialMEMEAmount, WBNBAmount } = await getTokenBalances(lpAddress, token) const slot0 = await lpContract.slot0() - const updatedSqrtPriceX96 = new BigNumber(slot0.sqrtPriceX96.toString()) - const { priceMemeInWbnb, priceWbnbInMeme } = calculatePrices( - updatedSqrtPriceX96, - await lpContract.token0(), - await lpContract.token1(), - MEME - ) + const sqrtPriceX96 = new BigNumber(slot0.sqrtPriceX96.toString()) + const { priceMemeInWbnb, priceWbnbInMeme } = calculatePrices(sqrtPriceX96, await lpContract.token0(), await lpContract.token1(), MEME) - await logData(0, initialMEMEAmount, WBNBAmount, updatedSqrtPriceX96, priceMemeInWbnb, priceWbnbInMeme, initialMEMEAmount) + await logData(0, initialMEMEAmount, WBNBAmount, sqrtPriceX96, priceMemeInWbnb, priceWbnbInMeme, initialMEMEAmount) const target = 26 for (let i = 1; i <= target; ++i) { @@ -128,11 +123,11 @@ async function test() { await bnbPartyFactory.joinParty(MEME, 0, { value: swapAmount }) const { MEMEAmount, WBNBAmount } = await getTokenBalances(lpAddress, token) - const updatedSlot0 = await lpContract.slot0() - const updatedSqrtPriceX96 = new BigNumber(updatedSlot0.sqrtPriceX96.toString()) - const { priceMemeInWbnb, priceWbnbInMeme } = calculatePrices(updatedSqrtPriceX96, await lpContract.token0(), await lpContract.token1(), MEME) + const slot0 = await lpContract.slot0() + const sqrtPriceX96 = new BigNumber(slot0.sqrtPriceX96.toString()) + const { priceMemeInWbnb, priceWbnbInMeme } = calculatePrices(sqrtPriceX96, await lpContract.token0(), await lpContract.token1(), MEME) - await logData(i, MEMEAmount, WBNBAmount, updatedSqrtPriceX96, priceMemeInWbnb, priceWbnbInMeme, initialMEMEAmount) + await logData(i, MEMEAmount, WBNBAmount, sqrtPriceX96, priceMemeInWbnb, priceWbnbInMeme, initialMEMEAmount) } } From 51cc9df940a6b3f02d8ba45ca26cccf11ff755cf Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Wed, 14 Aug 2024 11:26:26 +0300 Subject: [PATCH 15/21] add BNB market cap --- scripts/curve.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/curve.ts b/scripts/curve.ts index 9b50185..87be897 100644 --- a/scripts/curve.ts +++ b/scripts/curve.ts @@ -20,6 +20,7 @@ const csv = createCsvWriter({ { id: "wbnbValueInLp", title: "WBNB Value in USD" }, { id: "memeValueInLp", title: "MEME Value in USD" }, { id: "marketCap", title: "Market Cap in USD" }, + { id: "memeMarketCapInBnb", title: "Market Cap in BNB" }, { id: "remainingMEMEPercentage", title: "Remaining MEME %" }, ], }) @@ -85,6 +86,7 @@ async function logData( const memeValueUSD = MEMEAmount.div(new BigNumber(10).pow(18)).multipliedBy(priceMemeInWbnb).multipliedBy(BNB_PRICE) const marketCap = initialMEMEAmount.div(new BigNumber(10).pow(18)).multipliedBy(priceMemeInWbnb).multipliedBy(BNB_PRICE) const remainingMEMEPercentage = MEMEAmount.div(initialMEMEAmount).multipliedBy(100).toFixed(2) + const memeMarketCapInBnb = initialMEMEAmount.div(new BigNumber(10).pow(18)).multipliedBy(priceMemeInWbnb) const data = { iteration, @@ -96,6 +98,7 @@ async function logData( wbnbValueInLp: wbnbValueUSD.toString(), memeValueInLp: memeValueUSD.toString(), marketCap: marketCap.toString(), + memeMarketCapInBnb: memeMarketCapInBnb.toString(), remainingMEMEPercentage, } From 29fce2525620ef5f691e33fc752e72171e7eb787 Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Wed, 14 Aug 2024 14:18:51 +0300 Subject: [PATCH 16/21] add target config --- scripts/curve.ts | 9 +++++---- test/BNBPartyFactory.ts | 4 ++-- test/helper.ts | 5 ++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/scripts/curve.ts b/scripts/curve.ts index 87be897..1c5a469 100644 --- a/scripts/curve.ts +++ b/scripts/curve.ts @@ -107,7 +107,8 @@ async function logData( } async function test() { - await deployContracts() + const target = ethers.parseEther("13") + await deployContracts(target) const { MEME, position } = await createLiquidityPool() const token = await ethers.getContractAt("ERC20Token", MEME) const lpAddress = await v3PartyFactory.getPool(position.token0, position.token1, FeeAmount.HIGH) @@ -120,9 +121,9 @@ async function test() { await logData(0, initialMEMEAmount, WBNBAmount, sqrtPriceX96, priceMemeInWbnb, priceWbnbInMeme, initialMEMEAmount) - const target = 26 - for (let i = 1; i <= target; ++i) { - const swapAmount = ethers.parseUnits("5", 17) + const segments = 26 + for (let i = 1; i <= segments; ++i) { + const swapAmount = ethers.parseUnits("5.05", 17) await bnbPartyFactory.joinParty(MEME, 0, { value: swapAmount }) const { MEMEAmount, WBNBAmount } = await getTokenBalances(lpAddress, token) diff --git a/test/BNBPartyFactory.ts b/test/BNBPartyFactory.ts index cf2db9b..3e7316b 100644 --- a/test/BNBPartyFactory.ts +++ b/test/BNBPartyFactory.ts @@ -46,7 +46,7 @@ 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()).tickUpper).to.equal("195400") + expect((await bnbPartyFactory.party()).tickUpper).to.equal("196200") expect((await bnbPartyFactory.party()).tickLower).to.equal("-214200") }) @@ -146,7 +146,7 @@ describe("BNBPartyFactory", function () { const newBalance = await token.balanceOf(newLPPool) const userBalance = await token.balanceOf(await signers[0].getAddress()) const bnbpartyBalance = await token.balanceOf(await bnbPartyFactory.getAddress()) - expect(newBalance).to.be.equal(oldBalance + rest - userBalance - bnbpartyBalance - 1n) + expect(newBalance).to.be.equal(oldBalance + rest - userBalance - bnbpartyBalance - 2n) }) it("should send WBNB to new LP", async () => { diff --git a/test/helper.ts b/test/helper.ts index ac67e8e..b4901ba 100644 --- a/test/helper.ts +++ b/test/helper.ts @@ -36,8 +36,7 @@ export let BNBSwapRouter: SwapRouter export let swapRouter: SwapRouter export let weth9: IWBNB -export async function deployContracts() { - const partyTarget = ethers.parseEther("90") +export async function deployContracts(partyTarget = ethers.parseEther("90")) { const tokenCreationFee = ethers.parseUnits("1", 16) const returnFeeAmount = ethers.parseUnits("5", 17) const bonusFee = ethers.parseUnits("1", 16) @@ -61,7 +60,7 @@ export async function deployContracts() { bonusPartyCreator: bonusFee, targetReachFee: targetReachFee, tickLower: "-214200", - tickUpper: "195400", + tickUpper: "196200", }, await weth9.getAddress() )) as BNBPartyFactory From e2b6d7bb6c10be29ecc3d07401f3916c281ac520 Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Wed, 14 Aug 2024 15:17:33 +0300 Subject: [PATCH 17/21] added support for second lp on curve --- contracts/BNBPartyState.sol | 2 +- scripts/curve.ts | 18 +++++++++++++++--- test/BNBPartyFactory.ts | 4 ++-- test/helper.ts | 4 ++-- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/contracts/BNBPartyState.sol b/contracts/BNBPartyState.sol index 59d1638..f9c0cd6 100644 --- a/contracts/BNBPartyState.sol +++ b/contracts/BNBPartyState.sol @@ -19,7 +19,7 @@ abstract contract BNBPartyState is IBNBPartyFactory, Ownable { mapping(address => bool) public isParty; // Mapping to track if a LiquidityPool is a party mapping(address => uint256) public lpToTokenId; // Mapping from LiquidityPool to its NFT tokenId mapping(address => address) public lpToCreator; // Mapping from LiquidityPool to its creator - mapping(address => bool) isTokenOnPartyLP; // Mapping to track if a token is part of a party + mapping(address => bool) public isTokenOnPartyLP; // Mapping to track if a token is part of a party Party public party; // store party parameters diff --git a/scripts/curve.ts b/scripts/curve.ts index 1c5a469..058382a 100644 --- a/scripts/curve.ts +++ b/scripts/curve.ts @@ -1,5 +1,5 @@ import { ethers } from "hardhat" -import { FeeAmount, v3PartyFactory, deployContracts, weth9, bnbPartyFactory, BNBPositionManager } from "../test/helper" +import { FeeAmount, v3PartyFactory, deployContracts, weth9, bnbPartyFactory, BNBPositionManager, v3Factory, positionManager } from "../test/helper" import { IUniswapV3Pool } from "../typechain-types" import BigNumber from "bignumber.js" import * as csvWriter from "csv-writer" @@ -123,7 +123,7 @@ async function test() { const segments = 26 for (let i = 1; i <= segments; ++i) { - const swapAmount = ethers.parseUnits("5.05", 17) + const swapAmount = ethers.parseUnits("5.06", 17) await bnbPartyFactory.joinParty(MEME, 0, { value: swapAmount }) const { MEMEAmount, WBNBAmount } = await getTokenBalances(lpAddress, token) @@ -131,7 +131,19 @@ async function test() { const sqrtPriceX96 = new BigNumber(slot0.sqrtPriceX96.toString()) const { priceMemeInWbnb, priceWbnbInMeme } = calculatePrices(sqrtPriceX96, await lpContract.token0(), await lpContract.token1(), MEME) - await logData(i, MEMEAmount, WBNBAmount, sqrtPriceX96, priceMemeInWbnb, priceWbnbInMeme, initialMEMEAmount) + const isParty = await bnbPartyFactory.isTokenOnPartyLP(MEME) + if (isParty) { + await logData(i, MEMEAmount, WBNBAmount, sqrtPriceX96, priceMemeInWbnb, priceWbnbInMeme, initialMEMEAmount) + } + else { + const newLPPool = await v3Factory.getPool(await weth9.getAddress(), MEME, FeeAmount.HIGH) + const lpContract = (await ethers.getContractAt("UniswapV3Pool", newLPPool)) as any as IUniswapV3Pool + const slot0 = await lpContract.slot0() + const sqrtPriceX96 = new BigNumber(slot0.sqrtPriceX96.toString()) + const { priceMemeInWbnb, priceWbnbInMeme } = calculatePrices(sqrtPriceX96, await lpContract.token0(), await lpContract.token1(), MEME) + const { MEMEAmount, WBNBAmount } = await getTokenBalances(newLPPool, token) + await logData(i, MEMEAmount, WBNBAmount, sqrtPriceX96, priceMemeInWbnb, priceWbnbInMeme, initialMEMEAmount) + } } } diff --git a/test/BNBPartyFactory.ts b/test/BNBPartyFactory.ts index 3e7316b..a4ff387 100644 --- a/test/BNBPartyFactory.ts +++ b/test/BNBPartyFactory.ts @@ -24,7 +24,7 @@ describe("BNBPartyFactory", function () { const tokenCreationFee = ethers.parseUnits("1", 16) const returnFeeAmount = ethers.parseUnits("5", 17) const bonusFee = ethers.parseUnits("1", 16) - const targetReachFee = ethers.parseUnits("1", 17) + const targetReachFee = ethers.parseUnits("8.5", 17) const initialTokenAmount = "1000000000000000000000000000" const name = "Party" const symbol = "Token" @@ -46,7 +46,7 @@ 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()).tickUpper).to.equal("196200") + expect((await bnbPartyFactory.party()).tickUpper).to.equal("195600") expect((await bnbPartyFactory.party()).tickLower).to.equal("-214200") }) diff --git a/test/helper.ts b/test/helper.ts index b4901ba..9b5f844 100644 --- a/test/helper.ts +++ b/test/helper.ts @@ -40,7 +40,7 @@ export async function deployContracts(partyTarget = ethers.parseEther("90")) { const tokenCreationFee = ethers.parseUnits("1", 16) const returnFeeAmount = ethers.parseUnits("5", 17) const bonusFee = ethers.parseUnits("1", 16) - const targetReachFee = ethers.parseUnits("1", 17) + const targetReachFee = ethers.parseUnits("8.5", 17) const initialTokenAmount = "1000000000000000000000000000" const sqrtPriceX96 = "1252685732681638336686364" // Deploy WETH9 @@ -60,7 +60,7 @@ export async function deployContracts(partyTarget = ethers.parseEther("90")) { bonusPartyCreator: bonusFee, targetReachFee: targetReachFee, tickLower: "-214200", - tickUpper: "196200", + tickUpper: "195600", }, await weth9.getAddress() )) as BNBPartyFactory From 5562626310eac7c07069d4fdc10afc2565b8e2c9 Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Mon, 2 Sep 2024 12:44:35 +0300 Subject: [PATCH 18/21] refactor curve script --- scripts/curve.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/scripts/curve.ts b/scripts/curve.ts index 058382a..4e0f4c4 100644 --- a/scripts/curve.ts +++ b/scripts/curve.ts @@ -57,7 +57,7 @@ async function getTokenBalances(lpAddress: string, token: any) { lpPool.feeGrowthGlobal0X128(), lpPool.feeGrowthGlobal1X128(), lpPool.liquidity(), - bnbPartyFactory.getFeeGrowthInsideLastX128(lpAddress), + bnbPartyFactory.getFeeGrowthInsideLastX128(lpAddress, BNBPositionManager), ]) const token0 = await lpPool.token0() let wbnbFee, memeFee @@ -125,14 +125,12 @@ async function test() { for (let i = 1; i <= segments; ++i) { const swapAmount = ethers.parseUnits("5.06", 17) await bnbPartyFactory.joinParty(MEME, 0, { value: swapAmount }) - - const { MEMEAmount, WBNBAmount } = await getTokenBalances(lpAddress, token) - const slot0 = await lpContract.slot0() - const sqrtPriceX96 = new BigNumber(slot0.sqrtPriceX96.toString()) - const { priceMemeInWbnb, priceWbnbInMeme } = calculatePrices(sqrtPriceX96, await lpContract.token0(), await lpContract.token1(), MEME) - const isParty = await bnbPartyFactory.isTokenOnPartyLP(MEME) if (isParty) { + const { MEMEAmount, WBNBAmount } = await getTokenBalances(lpAddress, token) + const slot0 = await lpContract.slot0() + const sqrtPriceX96 = new BigNumber(slot0.sqrtPriceX96.toString()) + const { priceMemeInWbnb, priceWbnbInMeme } = calculatePrices(sqrtPriceX96, await lpContract.token0(), await lpContract.token1(), MEME) await logData(i, MEMEAmount, WBNBAmount, sqrtPriceX96, priceMemeInWbnb, priceWbnbInMeme, initialMEMEAmount) } else { From 712360536a55deca6116e5b066440a55dc6d7c56 Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Mon, 2 Sep 2024 12:48:51 +0300 Subject: [PATCH 19/21] optimize curve loop --- scripts/curve.ts | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/scripts/curve.ts b/scripts/curve.ts index 4e0f4c4..c8f1ab0 100644 --- a/scripts/curve.ts +++ b/scripts/curve.ts @@ -114,17 +114,11 @@ async function test() { const lpAddress = await v3PartyFactory.getPool(position.token0, position.token1, FeeAmount.HIGH) lpContract = (await ethers.getContractAt("UniswapV3Pool", lpAddress)) as any as IUniswapV3Pool - const { MEMEAmount: initialMEMEAmount, WBNBAmount } = await getTokenBalances(lpAddress, token) - const slot0 = await lpContract.slot0() - const sqrtPriceX96 = new BigNumber(slot0.sqrtPriceX96.toString()) - const { priceMemeInWbnb, priceWbnbInMeme } = calculatePrices(sqrtPriceX96, await lpContract.token0(), await lpContract.token1(), MEME) - - await logData(0, initialMEMEAmount, WBNBAmount, sqrtPriceX96, priceMemeInWbnb, priceWbnbInMeme, initialMEMEAmount) - + const { MEMEAmount: initialMEMEAmount, } = await getTokenBalances(lpAddress, token) const segments = 26 - for (let i = 1; i <= segments; ++i) { + for (let i = 0; i <= segments; ++i) { const swapAmount = ethers.parseUnits("5.06", 17) - await bnbPartyFactory.joinParty(MEME, 0, { value: swapAmount }) + if( i !== 0) await bnbPartyFactory.joinParty(MEME, 0, { value: swapAmount }) const isParty = await bnbPartyFactory.isTokenOnPartyLP(MEME) if (isParty) { const { MEMEAmount, WBNBAmount } = await getTokenBalances(lpAddress, token) From 780379cf8bc74f3c2576525ec78aaafbd1c6c122 Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Mon, 2 Sep 2024 12:50:13 +0300 Subject: [PATCH 20/21] return test check --- test/SwapRouter.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/SwapRouter.ts b/test/SwapRouter.ts index 35cdb10..491926f 100644 --- a/test/SwapRouter.ts +++ b/test/SwapRouter.ts @@ -49,8 +49,8 @@ describe("Smart Router", function () { }) it("user should receive meme token after join party", async () => { - const amountIn = ethers.parseUnits("1", 18) - + const amountIn = ethers.parseUnits("5", 17) + const balanceBefore = await MEMEToken.balanceOf(await signers[0].getAddress()) await bnbPartyFactory.joinParty(MEME, 0, { value: amountIn }) const balanceAfter = await MEMEToken.balanceOf(await signers[0].getAddress()) From dc249b2454365480b08d1a33fe39e518cea7ffcc Mon Sep 17 00:00:00 2001 From: Andrew Dmytrenko Date: Mon, 2 Sep 2024 12:56:56 +0300 Subject: [PATCH 21/21] calculate both fees --- scripts/curve.ts | 6 +++--- test/SwapRouter.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/curve.ts b/scripts/curve.ts index c8f1ab0..ba2e810 100644 --- a/scripts/curve.ts +++ b/scripts/curve.ts @@ -53,15 +53,15 @@ async function getTokenBalances(lpAddress: string, token: any) { ]) const lpPool = await ethers.getContractAt("UniswapV3Pool", lpAddress) + const token0 = await lpPool.token0() + const isPartyPool = await bnbPartyFactory.isTokenOnPartyLP(token0 === wethAddress ? await token.getAddress() : token0) const [feeGrowthGlobal0X128, feeGrowthGlobal1X128, liquidity, getFeeGlobal] = await Promise.all([ lpPool.feeGrowthGlobal0X128(), lpPool.feeGrowthGlobal1X128(), lpPool.liquidity(), - bnbPartyFactory.getFeeGrowthInsideLastX128(lpAddress, BNBPositionManager), + bnbPartyFactory.getFeeGrowthInsideLastX128(lpAddress, isPartyPool ? BNBPositionManager : positionManager), ]) - const token0 = await lpPool.token0() let wbnbFee, memeFee - if (token0 === wethAddress) { wbnbFee = await bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobal0X128 - getFeeGlobal.feeGrowthInside0LastX128) memeFee = await bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobal1X128 - getFeeGlobal.feeGrowthInside1LastX128) diff --git a/test/SwapRouter.ts b/test/SwapRouter.ts index 491926f..fabdcaa 100644 --- a/test/SwapRouter.ts +++ b/test/SwapRouter.ts @@ -50,7 +50,7 @@ describe("Smart Router", function () { it("user should receive meme token after join party", async () => { const amountIn = ethers.parseUnits("5", 17) - + const balanceBefore = await MEMEToken.balanceOf(await signers[0].getAddress()) await bnbPartyFactory.joinParty(MEME, 0, { value: amountIn }) const balanceAfter = await MEMEToken.balanceOf(await signers[0].getAddress())