Skip to content

Commit 41fed5a

Browse files
Merge pull request #51 from bnb-party/curve
curve tests
2 parents 39398cd + a772945 commit 41fed5a

File tree

3 files changed

+162
-9
lines changed

3 files changed

+162
-9
lines changed

package-lock.json

+9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+11-9
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,26 @@
1919
"@nomicfoundation/hardhat-network-helpers": "^1.0.10",
2020
"@nomicfoundation/hardhat-verify": "^2.0.6",
2121
"@truffle/dashboard-hardhat-plugin": "^0.2.15",
22-
"ethers": "^6.12.0",
23-
"hardhat-gas-reporter": "^2.1.1",
24-
"hardhat": "^2.22.3",
25-
"solidity-coverage": "^0.8.12",
26-
"ts-node": ">=8.0.0",
27-
"typechain": "^8.3.2",
28-
"typescript": "^5.4.5",
2922
"@typechain/ethers-v6": "^0.5.1",
3023
"@typechain/hardhat": "^9.1.0",
3124
"@types/chai": "^4.2.0",
3225
"@types/mocha": ">=9.1.0",
3326
"@types/node": "^20.12.7",
34-
"chai": "^4.2.0"
27+
"bignumber.js": "^9.1.2",
28+
"chai": "^4.2.0",
29+
"csv-writer": "^1.6.0",
30+
"ethers": "^6.12.0",
31+
"hardhat": "^2.22.3",
32+
"hardhat-gas-reporter": "^2.1.1",
33+
"solidity-coverage": "^0.8.12",
34+
"ts-node": ">=8.0.0",
35+
"typechain": "^8.3.2",
36+
"typescript": "^5.4.5"
3537
},
3638
"dependencies": {
37-
"@openzeppelin/contracts": "^5.0.2",
3839
"@bnb-party/v3-core": "^1.0.4",
3940
"@bnb-party/v3-periphery": "^1.0.5",
41+
"@openzeppelin/contracts": "^5.0.2",
4042
"@uniswap/lib": "^4.0.1-alpha",
4143
"@uniswap/v3-core": "^1.0.0",
4244
"@uniswap/v3-periphery": "^1.4.4"

scripts/curve.ts

+142
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import { ethers } from "hardhat"
2+
import { FeeAmount, v3PartyFactory, deployContracts, weth9, bnbPartyFactory, BNBPositionManager, v3Factory, positionManager } from "../test/helper"
3+
import { IUniswapV3Pool } from "../typechain-types"
4+
import BigNumber from "bignumber.js"
5+
import * as csvWriter from "csv-writer"
6+
7+
const BNB_PRICE = 600 // BNB price in USD
8+
let lpContract: IUniswapV3Pool
9+
10+
const createCsvWriter = csvWriter.createObjectCsvWriter
11+
const csv = createCsvWriter({
12+
path: "liquidity_pool_data.csv",
13+
header: [
14+
{ id: "iteration", title: "Iteration" },
15+
{ id: "MEMEAmount", title: "MEME Amount" },
16+
{ id: "WBNBAmount", title: "WBNB Amount" },
17+
{ id: "SqrtPriceX96", title: "sqrtPriceX96" },
18+
{ id: "priceMemeInWbnb", title: "Price of MEME in WBNB" },
19+
{ id: "priceWbnbInMeme", title: "Price of WBNB in MEME" },
20+
{ id: "wbnbValueInLp", title: "WBNB Value in USD" },
21+
{ id: "memeValueInLp", title: "MEME Value in USD" },
22+
{ id: "marketCap", title: "Market Cap in USD" },
23+
{ id: "memeMarketCapInBnb", title: "Market Cap in BNB" },
24+
{ id: "remainingMEMEPercentage", title: "Remaining MEME %" },
25+
],
26+
})
27+
28+
async function createLiquidityPool() {
29+
const tokenCreationFee = ethers.parseUnits("1", 16)
30+
await bnbPartyFactory.createParty("MEME", "MEME", { value: tokenCreationFee })
31+
const tokenId = await BNBPositionManager.totalSupply()
32+
const position = await BNBPositionManager.positions(tokenId)
33+
34+
const wethAddress = await weth9.getAddress()
35+
const MEME = position.token1 === wethAddress ? position.token0 : position.token1
36+
return { MEME, position }
37+
}
38+
39+
function calculatePrices(sqrtPriceX96: BigNumber, token0: string, token1: string, meme: string) {
40+
const priceX96 = sqrtPriceX96.pow(2)
41+
const priceToken0InToken1 = priceX96.dividedBy(new BigNumber(2).pow(192))
42+
const priceToken1InToken0 = new BigNumber(1).div(priceToken0InToken1)
43+
return token0 === meme
44+
? { priceMemeInWbnb: priceToken0InToken1, priceWbnbInMeme: priceToken1InToken0 }
45+
: { priceMemeInWbnb: priceToken1InToken0, priceWbnbInMeme: priceToken0InToken1 }
46+
}
47+
48+
async function getTokenBalances(lpAddress: string, token: any) {
49+
const [MEMEAmount, WBNBAmount, wethAddress] = await Promise.all([
50+
token.balanceOf(lpAddress),
51+
weth9.balanceOf(lpAddress),
52+
weth9.getAddress(),
53+
])
54+
55+
const lpPool = await ethers.getContractAt("UniswapV3Pool", lpAddress)
56+
const token0 = await lpPool.token0()
57+
const isPartyPool = await bnbPartyFactory.isTokenOnPartyLP(token0 === wethAddress ? await token.getAddress() : token0)
58+
const [feeGrowthGlobal0X128, feeGrowthGlobal1X128, liquidity, getFeeGlobal] = await Promise.all([
59+
lpPool.feeGrowthGlobal0X128(),
60+
lpPool.feeGrowthGlobal1X128(),
61+
lpPool.liquidity(),
62+
bnbPartyFactory.getFeeGrowthInsideLastX128(lpAddress, isPartyPool ? BNBPositionManager : positionManager),
63+
])
64+
let wbnbFee, memeFee
65+
if (token0 === wethAddress) {
66+
wbnbFee = await bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobal0X128 - getFeeGlobal.feeGrowthInside0LastX128)
67+
memeFee = await bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobal1X128 - getFeeGlobal.feeGrowthInside1LastX128)
68+
} else {
69+
memeFee = await bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobal0X128 - getFeeGlobal.feeGrowthInside0LastX128)
70+
wbnbFee = await bnbPartyFactory.calculateFees(liquidity, feeGrowthGlobal1X128 - getFeeGlobal.feeGrowthInside1LastX128)
71+
}
72+
73+
return { WBNBAmount: new BigNumber((WBNBAmount - wbnbFee).toString()), MEMEAmount: new BigNumber((MEMEAmount - memeFee).toString()) }
74+
}
75+
76+
async function logData(
77+
iteration: number,
78+
MEMEAmount: BigNumber,
79+
WBNBAmount: BigNumber,
80+
sqrtPriceX96: BigNumber,
81+
priceMemeInWbnb: BigNumber,
82+
priceWbnbInMeme: BigNumber,
83+
initialMEMEAmount: BigNumber
84+
) {
85+
const wbnbValueUSD = WBNBAmount.div(new BigNumber(10).pow(18)).multipliedBy(BNB_PRICE)
86+
const memeValueUSD = MEMEAmount.div(new BigNumber(10).pow(18)).multipliedBy(priceMemeInWbnb).multipliedBy(BNB_PRICE)
87+
const marketCap = initialMEMEAmount.div(new BigNumber(10).pow(18)).multipliedBy(priceMemeInWbnb).multipliedBy(BNB_PRICE)
88+
const remainingMEMEPercentage = MEMEAmount.div(initialMEMEAmount).multipliedBy(100).toFixed(2)
89+
const memeMarketCapInBnb = initialMEMEAmount.div(new BigNumber(10).pow(18)).multipliedBy(priceMemeInWbnb)
90+
91+
const data = {
92+
iteration,
93+
MEMEAmount: MEMEAmount.toString(),
94+
WBNBAmount: WBNBAmount.toString(),
95+
SqrtPriceX96: sqrtPriceX96.toString(),
96+
priceMemeInWbnb: priceMemeInWbnb.toString(),
97+
priceWbnbInMeme: priceWbnbInMeme.toString(),
98+
wbnbValueInLp: wbnbValueUSD.toString(),
99+
memeValueInLp: memeValueUSD.toString(),
100+
marketCap: marketCap.toString(),
101+
memeMarketCapInBnb: memeMarketCapInBnb.toString(),
102+
remainingMEMEPercentage,
103+
}
104+
105+
console.log(data)
106+
await csv.writeRecords([data])
107+
}
108+
109+
async function test() {
110+
const target = ethers.parseEther("13")
111+
await deployContracts(target)
112+
const { MEME, position } = await createLiquidityPool()
113+
const token = await ethers.getContractAt("ERC20Token", MEME)
114+
const lpAddress = await v3PartyFactory.getPool(position.token0, position.token1, FeeAmount.HIGH)
115+
lpContract = (await ethers.getContractAt("UniswapV3Pool", lpAddress)) as any as IUniswapV3Pool
116+
117+
const { MEMEAmount: initialMEMEAmount, } = await getTokenBalances(lpAddress, token)
118+
const segments = 26
119+
for (let i = 0; i <= segments; ++i) {
120+
const swapAmount = ethers.parseUnits("5.06", 17)
121+
if( i !== 0) await bnbPartyFactory.joinParty(MEME, 0, { value: swapAmount })
122+
const isParty = await bnbPartyFactory.isTokenOnPartyLP(MEME)
123+
if (isParty) {
124+
const { MEMEAmount, WBNBAmount } = await getTokenBalances(lpAddress, token)
125+
const slot0 = await lpContract.slot0()
126+
const sqrtPriceX96 = new BigNumber(slot0.sqrtPriceX96.toString())
127+
const { priceMemeInWbnb, priceWbnbInMeme } = calculatePrices(sqrtPriceX96, await lpContract.token0(), await lpContract.token1(), MEME)
128+
await logData(i, MEMEAmount, WBNBAmount, sqrtPriceX96, priceMemeInWbnb, priceWbnbInMeme, initialMEMEAmount)
129+
}
130+
else {
131+
const newLPPool = await v3Factory.getPool(await weth9.getAddress(), MEME, FeeAmount.HIGH)
132+
const lpContract = (await ethers.getContractAt("UniswapV3Pool", newLPPool)) as any as IUniswapV3Pool
133+
const slot0 = await lpContract.slot0()
134+
const sqrtPriceX96 = new BigNumber(slot0.sqrtPriceX96.toString())
135+
const { priceMemeInWbnb, priceWbnbInMeme } = calculatePrices(sqrtPriceX96, await lpContract.token0(), await lpContract.token1(), MEME)
136+
const { MEMEAmount, WBNBAmount } = await getTokenBalances(newLPPool, token)
137+
await logData(i, MEMEAmount, WBNBAmount, sqrtPriceX96, priceMemeInWbnb, priceWbnbInMeme, initialMEMEAmount)
138+
}
139+
}
140+
}
141+
142+
test().catch(console.error)

0 commit comments

Comments
 (0)