PumpFun - Going deep into the concept of real and virtual liquidity with the migration process.
How does every single newly released coin for just $2 instantly has a market cap of $5,000???!
PS: This is going to be the best guide out there on realTokenReserves, virtualTokenReserves, virtualSolReserves and realSolReserves.
So recently I’ve been trying to automate the token buying and selling mechanism on pumpFun but kinda struggled at figuring out on how it works at the blockchain level and the mathematical aspect of it even though it uses the constant product formula, just wanted to make a quick small guide on explaining the above terms.
Getting the bondingCurve account of a mint address
1
2
3
4
5
6
7
8
9
10
11
12
13
async function getBondingCurveAddress(mint: PublicKey) {
const mintAccount: PublicKey = new PublicKey(mint)
const [bondingCurve, _]: [PublicKey, Number] = PublicKey.findProgramAddressSync(
[
Buffer.from("bonding-curve"),
mintAccount.toBuffer()
],
PUMP_FUN_PROGRAM
)
return bondingCurve
}
To derive the the bonding curve address from the mint account you use use this particular seed.
Parsing the data from the bondingCurve account
If we take a look at the pumpFun idl file , we can see that:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{
"name": "BondingCurve",
"type": {
"kind": "struct",
"fields": [
{
"name": "virtualTokenReserves",
"type": "u64"
},
{
"name": "virtualSolReserves",
"type": "u64"
},
{
"name": "realTokenReserves",
"type": "u64"
},
{
"name": "realSolReserves",
"type": "u64"
},
{
"name": "tokenTotalSupply",
"type": "u64"
},
{
"name": "complete",
"type": "bool"
}
]
}
}
This is the bondingCurve struct and to parse the data we can use:
1
const struct = await program.account.bondingCurve.fetch(bondingCurveAdress);
Okay now here comes’s the real part , So I’ll be taking a few examples from the pumpFun token with different marketCaps to explain how this works, I’ve written a script that prints out these 4 params from the struct.
A new fresh mint
1
2
3
4
Token Virtual Reserves: 1,073,000,000
Token Real Reserves: 793,100,000
Real SOL Reserves: 0
Virtual SOL Reserves: 30
So when a new token is created this is exactly how it’s going to look like.
Virtual Reserves: It represents the total amount of token that can be traded , currently it has 1 billion tokens in supply.
Token real reservers: So the pumpFun mechanism is that out of the 1 billion supply around 800k has to be sold out for SOL before migrating to radyium, the rest 200k will be added to the radiyum pool.
Real sol reserves: This represents the actual or the real amount of SOL that is available in the bonding curve.
Virtual sol reserves: This is exactly where the magical $5k marketCap comes in , by default around 30 SOL with no value is used to calculate the market, consider it like an artifical sol.
virtualSolReserves = realSolReserves + 30
- Since pumpFun uses the constant product formula:
Price (y/x):
- Since we want to get the token price: virtualSolReserves / virtualTokenReserves
- Don’t forget to divide it by the decimals.
This now explains the artificial price when a new token is released.
MarketCap
- price * tokenTotalSupply
Liquidity
- Liquidity is bascially the real sol reserves.
Example 2
Now let’s take a different mint example:
1
2
3
4
5
6
Token Virtual Reserves: 711,127,888
Token Real Reserves: 431,227,888
Real SOL Reserves: 15 sol | USD: $2313
Virtual SOL Reserves: 45
Price: 0.0000000636540
MarketCap: $9644
If we subtract these values from the default values:
Decrease in virtual reserves: 1,073,000,000 - 711,127,888 = 361,872,112
Decrease in real reserves: 793,100,000 - 431,227,888 = 361,872,112
So currently what does the virtual and the real reserves represent?
Virtual Reserves - It represents the total token balance the bonding curve currently holds.
Real reserves - The amount of tokens that should be bought by the users before it gets migrated to pumpFun.
- If we subtract the real reserves from the virtual reserves we can see that around 200k will be available which will be added to the newly created radiyum pool with the real amount of SOL from the bondingCurve(not the whole real SOl amount obv, taking fees and stuffs into consideration).
That basically sums up the whole pumpFun thing…