debpf
pump.fun / instructions

Instruction

buy_v2

Decompiled

buy_v2 buys exactly `amount` tokens from a pump.fun bonding curve. It works for SOL-priced curves (native lamports, quote_mint must be wSOL) and for curves priced in another SPL token (payment by transfer_checked from your quote token account). Anyone can call it. You pay the constant-product price plus 1 lamport, a 0.95% protocol fee and a 0.30% creator fee (both rounded up; the rates come from a CPI to pump's fee program). Half of the protocol fee goes to a buyback recipient, except on mayhem curves. The creator fee goes to the creator vault, or back to you as cashback on cashback curves. One wallet stored in Global pays no fees. It fails if the curve is complete (6005), amount is 0 (6020), too few tokens remain (6021, unless the hidden cap flag byte is set), the quote mint is wrong (6063), or the total exceeds max_sol_cost (6002).

Discriminator
0xb817ee6167c5d33d
Calls in the sample
3
Reproduced, seen by the agent
0 / 1
Reproduced, never shown to the agent
0 / 2

0 of 3 real mainnet calls reproduced exactly. Every SOL and token movement the model predicted matched the chain to the last unit. Unseen calls were never shown to the agent.

Bytecodefn_2425a
2425amov64 r6, r5
2425bmov64 r8, r4
2425cmov64 r9, r3
2425dmov64 r7, r2
2425estxdw [r10-952], r1
2425flddw r1, 0x1ae3aa ; "Instruction: BuyV2"
24261mov64 r2, 0x12
24262call sol_log_
24263ldxdw r1, [r6-4088]
24264jlt r1, 0x8, +109 ; -> 242d2
24265mov64 r2, r1
24266and64 r2, -0x8
24267jeq r2, 0x8, +106 ; -> 242d2
24268ldxdw r2, [r6-4096]
24269ldxdw r3, [r2+0]
2426amov64 r5, 0x0
2426bldxdw r4, [r2+8]
2426cjeq r1, 0x10, +4 ; -> 24271
2426dldxb r1, [r2+16]
2426ejeq r1, 0x0, +2 ; -> 24271
2426fjne r1, 0x1, +153 ; -> 24309
24270mov64 r5, 0x1
24271stxdw [r10-976], r5
24272stxdw [r10-968], r4
24273stxdw [r10-960], r3
24274stdw [r10-891], -0x1
24275stdw [r10-896], -0x1
24276stxdw [r10-8], r8
24277stxdw [r10-16], r9
24278mov64 r1, r10
24279add64 r1, -0x380
2427astxdw [r10-4088], r1
2427bmov64 r1, r10
2427cadd64 r1, -0x1c0
2427dmov64 r3, r10
2427eadd64 r3, -0x10
2427fmov64 r5, r10
24280mov64 r2, r7
24281call fn_13be6
24282ldxdw r8, [r10-432]
24283ldxdw r6, [r10-440]
24284ldxdw r9, [r10-448]
24285lddw r1, 0x8000000000000000
24287jeq r9, r1, +93 ; -> 242e5
24288mov64 r1, r10
24289add64 r1, -0x358
2428amov64 r2, r10
2428badd64 r2, -0x1a8
2428cmov64 r3, 0x198
2428dcall fn_35367
2428estxdw [r10-864], r8
2428fstxdw [r10-872], r6
24290stxdw [r10-880], r9
24291ldxdw r1, [r10-896]
24292stxdw [r10-416], r1
24293ldxdw r1, [r10-891]
24294stxdw [r10-411], r1
24295ldxdw r1, [r10-8]
24296stxdw [r10-424], r1
24297ldxdw r1, [r10-16]
24298stxdw [r10-432], r1
24299mov64 r1, r10
2429aadd64 r1, -0x370
2429bstxdw [r10-440], r1
2429cstxdw [r10-448], r7
2429dmov64 r1, r10
2429eadd64 r1, -0x390
2429fmov64 r2, r10
242a0add64 r2, -0x1c0
242a1ldxdw r3, [r10-960]
242a2ldxdw r4, [r10-968]
242a3ldxdw r5, [r10-976]
242a4call fn_26aef
242a5ldxdw r6, [r10-912]
242a6jeq r6, 0x2, +1 ; -> 242a8
242a7ja +65 ; -> 242e9
242a8mov64 r1, r10
242a9add64 r1, -0x3a0
242aamov64 r2, r10
242abadd64 r2, -0x370
242acmov64 r3, r7
242adcall fn_14b46
242aeldxdw r1, [r10-720]
242afldxdw r2, [r10-728]
242b0ldxdw r3, [r2+0]
242b1add64 r3, -0x1
242b2ldxdw r8, [r10-920]
242b3ldxdw r6, [r10-928]
242b4stxdw [r2+0], r3
242b5jne r3, 0x0, +3 ; -> 242b9
242b6ldxdw r3, [r2+8]
242b7add64 r3, -0x1
242b8stxdw [r2+8], r3
242b9ldxdw r2, [r1+0]
242baadd64 r2, -0x1
242bbstxdw [r1+0], r2
242bcldxdw r4, [r10-952]
242bdjne r2, 0x0, +3 ; -> 242c1
242beldxdw r2, [r1+8]
242bfadd64 r2, -0x1
242c0stxdw [r1+8], r2
242c1ldxdw r1, [r10-672]
242c2ldxdw r2, [r10-680]
242c3ldxdw r3, [r2+0]
242c4add64 r3, -0x1
242c5stxdw [r2+0], r3
242c6jne r3, 0x0, +3 ; -> 242ca
242c7ldxdw r3, [r2+8]
242c8add64 r3, -0x1
242c9stxdw [r2+8], r3
242caldxdw r2, [r1+0]
242cbadd64 r2, -0x1
242ccstxdw [r1+0], r2
242cdjne r2, 0x0, +24 ; -> 242e6
242celdxdw r2, [r1+8]
242cfadd64 r2, -0x1
242d0stxdw [r1+8], r2
242d1ja +20 ; -> 242e6
242d2lddw r1, 0x1b3c60
242d4call fn_33e71
242d5mov64 r1, r0
242d6and64 r1, 0x3
242d7mov64 r2, r1
242d8add64 r2, -0x2
242d9jlt r2, 0x2, +5 ; -> 242df
242dajeq r1, 0x0, +4 ; -> 242df
242dbldxdw r1, [r0-1]
242dcldxdw r2, [r0+7]
242ddldxdw r2, [r2+0]
242decallx r2
242dfmov64 r1, r10
242e0add64 r1, -0x3b0
242e1mov64 r2, 0x66
242e2call fn_32b09
242e3ldxdw r8, [r10-936]
242e4ldxdw r6, [r10-944]
242e5ldxdw r4, [r10-952]
242e6stxdw [r4+8], r8
242e7stxdw [r4+0], r6
242e8exit
242e9ldxdw r8, [r10-904]
242ealdxdw r1, [r10-720]
242ebldxdw r2, [r10-728]
242ecldxdw r3, [r2+0]
242edadd64 r3, -0x1
242eestxdw [r2+0], r3
242efjne r3, 0x0, +3 ; -> 242f3
242f0ldxdw r3, [r2+8]
242f1add64 r3, -0x1
242f2stxdw [r2+8], r3
242f3ldxdw r2, [r1+0]
242f4add64 r2, -0x1
242f5stxdw [r1+0], r2
242f6ldxdw r4, [r10-952]
242f7jne r2, 0x0, +3 ; -> 242fb
242f8ldxdw r2, [r1+8]
242f9add64 r2, -0x1
242fastxdw [r1+8], r2
242fbldxdw r1, [r10-672]
242fcldxdw r2, [r10-680]
242fdldxdw r3, [r2+0]
242feadd64 r3, -0x1
242ffstxdw [r2+0], r3
24300jne r3, 0x0, +3 ; -> 24304
24301ldxdw r3, [r2+8]
24302add64 r3, -0x1
24303stxdw [r2+8], r3
24304ldxdw r2, [r1+0]
24305add64 r2, -0x1
24306stxdw [r1+0], r2
24307jne r2, 0x0, -34 ; -> 242e6
24308ja -59 ; -> 242ce
24309stxb [r10-896], r1
2430alddw r1, 0x1b3d30
2430cstxdw [r10-448], r1
2430dmov64 r1, r10
2430eadd64 r1, -0x10
2430fstxdw [r10-432], r1
24310lddw r1, 0x1a96e0
24312stxdw [r10-8], r1
24313mov64 r1, r10
24314add64 r1, -0x380
24315stxdw [r10-16], r1
24316stdw [r10-416], 0x0
24317stdw [r10-440], 0x1
24318stdw [r10-424], 0x1
24319mov64 r6, r10
2431aadd64 r6, -0x370
2431bmov64 r2, r10
2431cadd64 r2, -0x1c0
2431dmov64 r1, r6
2431ecall fn_342ee
2431fmov64 r1, 0x15
24320mov64 r2, r6
24321call fn_01495
24322ja -78 ; -> 242d5
Reconstructedbuy_v2
// discriminator b817ee6167c5d33d handler fn_2425a -> buy_v2_logic fn_26aef
// args: amount: u64, max_sol_cost: u64, [optional u8 cap_to_remaining: 0|1] (3rd byte not in IDL)
pub fn buy_v2(ctx, amount: u64, max_sol_cost: u64, cap_to_remaining: Option<bool>) -> Result<()> {
msg!("Instruction: BuyV2");
BuyV2Accounts::try_accounts(ctx)?; // fn_13be6 (shared with buy_exact_quote_in_v2): PDAs, ATAs, mints, programs
let curve = &mut ctx.bonding_curve;
require!(!curve.complete, BondingCurveComplete /*6005*/); // pc 26afb
let mut amount = amount;
if cap_to_remaining == Some(true) { amount = min(amount, curve.real_token_reserves); } // pc 26afe
require!(amount != 0, 6020); // pc 26b01
require!(curve.real_token_reserves >= amount, 6021 /*not enough tokens*/); // pc 26b04
check_global_state(global)?; // fn_078ef
check_mints(global, base_mint, ...)?; // fn_123fe
let token_quoted = curve.quote_mint != Pubkey::default(); // pc 26bc1
if token_quoted {
// create-idempotent the quote ATAs as needed (fn_029be / fn_02cb6):
// associated_quote_bonding_curve, associated_quote_user, associated_creator_vault,
// associated_user_volume_accumulator, associated_quote_fee_recipient, associated_quote_buyback_fee_recipient
} else {
require!(quote_mint.key == WSOL_MINT, 6063 /*wrong quote mint*/); // pc 26d42
}
// constant-product price, rounded up by one unit (fn_13385)
require!(curve.virtual_token_reserves > amount, 6024/6026);
let cost = (amount as u128 * curve.virtual_quote_reserves as u128
/ (curve.virtual_token_reserves - amount) as u128) as u64 + 1;
let whitelisted = user.key == global.whitelist; // Global data @451, pc 26d84
let (protocol_fee, creator_fee) = if whitelisted { (0, 0) } else {
// CPI fee_program::GetFeesWithQuoteMint(fee_config, curve, market cap) -> bps (fn_10820)
// currently protocol 95 bps, creator 30 bps
(ceil_div(cost * protocol_bps, 10_000), ceil_div(cost * creator_bps, 10_000))
};
let total = cost.checked_add(protocol_fee)?.checked_add(creator_fee)?; // overflow -> panic helpers
require!(total <= max_sol_cost, TooMuchSolRequired /*6002*/); // pc 26dc6
curve_apply_buy(curve, amount, cost); // fn_134f5: vtok-=amt, rtok-=amt, vquote+=cost, rquote+=cost
// base tokens out: transfer_checked(associated_base_bonding_curve -> associated_base_user, amount),
// signed by PDA ["bonding-curve", base_mint, bump] // fn_1148a
transfer_base_from_curve_signed(amount)?;
if whitelisted { // pc 26e37 -> 26f34
// re-read both token accounts and sync curve via fn_137f5; no fees charged
} else {
if global_volume_accumulator.field_8 == default { /* copied from accounts struct (unclear) */ }
if creator_fee != 0 { // pc 26e56 -> 26ef9
if curve.cashback_enabled { // curve byte 163
quote_xfer(user -> user_volume_accumulator (or its quote ATA), creator_fee); // fn_1234d
record_cashback(user_volume_accumulator, creator_fee); // fn_0f055
} else {
quote_xfer(user -> creator_vault (or associated_creator_vault), creator_fee); // fn_1234d
}
}
// SOL curve: system_program::transfer; token curve: transfer_checked from associated_quote_user
quote_xfer(user -> bonding_curve | associated_quote_bonding_curve, cost); // fn_1229d
let buyback = if curve.mayhem_mode /*byte 162*/ { 0 }
else { protocol_fee * global.buyback_bps(5000) / 10_000 }; // fn_12780, floor
quote_xfer(user -> fee_recipient | associated_quote_fee_recipient, protocol_fee - buyback); // fn_122f5
quote_xfer(user -> buyback_fee_recipient | associated_quote_buyback_fee_recipient, buyback); // fn_122f5
}
// volume tracking (user_volume_accumulator), completion flag when real_token_reserves hits 0,
// TradeEvent emitted via CPI to self through event_authority ("__event_authority")
Ok(())
}

Replay model

The executable model the agent wrote. Every tally above comes from running it against mainnet.

const B58='123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
function b58(hex){let n=BigInt('0x'+hex);let s='';while(n>0n){s=B58[Number(n%58n)]+s;n/=58n;}for(let i=0;i<hex.length&&hex.substr(i,2)==='00';i+=2)s='1'+s;return s;}
// Global (4wTV1Ymi...) @451: whitelisted trader (pays no fees)
const WHITELIST=b58('a28b5fd26ab479a6a9cc6cbf6b0b23eb61885a371e0120aca913beef3d138a78');
// Global @483.. reserved (mayhem) fee recipients
const RESERVED=['e893141fb18e9f1574d810e178e19e30604e3175aa2e4a32dfc8600727d10709',
'3584536256094f912819127efa4e446b4333721793d13876f9aadbf3dc7d0b5f','6e75018220f942677003237b4d6b453759b4a5c690b59c35d9bb187a090cbd2a',
'33987a9ebb136799ab59925b13e5dc8b3081df005db427c1478fa46ff8c347a0','74e9543f3e37a2d046227addcb4e9c774c44258c43edf24aa8aae1f00214665b',
'da4c38cd6db7438f59b408bb9ec3b4ca9e8ad1f1f24653c499b5796c20dbf9b3','2ddd9eea3f39b372115c71847c1845cfa536c685074e030e44d021de3ef9e35c',
'4cb780f08ee2fee84bec446a577825da68d439fa8a5da3b0c5cff50f63f4546b'].map(b58);
const WSOL='So11111111111111111111111111111111111111112';
function u64(d,o){let v=0n;for(let i=7;i>=0;i--)v=(v<<8n)|BigInt(d[o+i]);return v;}
const ceilDiv=(a,b)=>(a+b-1n)/b;
function model(ctx){
const d=ctx.data; let amount=u64(d,8); const maxCost=u64(d,16);
const capFlag = d.length>24 && d[24]===1;
const A=ctx.accounts;
const curveTokens=A[11].token.amount;
// virtual token reserves = curve ATA balance + 73e12 (1073e12 initial virtual - 1e15 supply)
const vtr=curveTokens+73000000000000n;
const K=1073000000000000n*30000000000n;
const vsr=ceilDiv(K,vtr);
const realTok = vtr - 279900000000000n; // real token reserves (793.1e12 initial)
if(capFlag && amount>realTok) amount=realTok;
const whitelisted = A[13].pubkey===WHITELIST;
let cost = whitelisted ? maxCost : amount*vsr/(vtr-amount)+1n;
let pf=0n,cf=0n;
if(!whitelisted){ pf=ceilDiv(cost*95n,10000n); cf=ceilDiv(cost*30n,10000n); }
const mayhem=RESERVED.includes(A[6].pubkey);
const buyback = mayhem?0n: pf*5000n/10000n;
const sol = A[2].pubkey===WSOL;
const lam={}, tok={11:-amount,14:amount};
if(sol){
lam[10]=cost; lam[6]=pf-buyback; lam[8]=buyback; lam[16]=cf;
lam[7]=0n; lam[9]=0n; lam[11]=0n; lam[20]=0n;
tok[7]=0n; tok[9]=0n;
} else {
tok[12]=cost; tok[7]=pf-buyback; tok[9]=buyback; tok[17]=cf; tok[15]=-(cost+pf+cf);
}
return {lamports:lam,tokens:tok};
}

Accounts

  1. 0global
  2. 1base_mint
  3. 2quote_mint
  4. 3base_token_program
  5. 4quote_token_program
  6. 5associated_token_program
  7. 6fee_recipientwritten
  8. 7associated_quote_fee_recipientwritten
  9. 8buyback_fee_recipientwritten
  10. 9associated_quote_buyback_fee_recipientwritten
  11. 10bonding_curvewritten
  12. 11associated_base_bonding_curvewritten
  13. 12associated_quote_bonding_curvewritten
  14. 13usersigns, written
  15. 14associated_base_userwritten
  16. 15associated_quote_userwritten
  17. 16creator_vaultwritten
  18. 17associated_creator_vaultwritten
  19. 18sharing_config
  20. 19global_volume_accumulator
  21. 20user_volume_accumulatorwritten
  22. 21associated_user_volume_accumulatorwritten
  23. 22fee_config
  24. 23fee_program
  25. 24system_program
  26. 25event_authority
  27. 26program

args: amount: u64, max_sol_cost: u64

program 6EF8rr…BEwF6P