debpf
pump.fun / instructions

Instruction

buy_exact_quote_in_v2

Partly proven

Any wallet can call this to spend an exact amount of quote currency (SOL, or a token such as PUMP) on a pump.fun bonding curve and receive the base token. Fees come out of the amount spent: a protocol fee (95 bps now, read from the pump fee program by market cap) and a creator fee (30 bps by default; a curve can store its own value, e.g. 100 bps, when a Global flag allows it). Both fees are rounded up. Unlike v3, all fees are paid out right away: Global.buyback_bps (5000, so half) of the protocol fee goes to the buyback recipient, unless the curve is in mayhem mode, the rest goes to the fee recipient, and the creator fee goes to the creator vault (or to the buyer's cashback accumulator on cashback curves). One user address stored in Global pays no fees at all. Errors: min_tokens_out = 0 (6020), spend = 0 or too small (6041), curve complete (6005), output below min_tokens_out (6042), not enough tokens left unless the partial-fill flag is set (6021), partial-fill cost above spend (6002), wrong quote mint (6063).

Discriminator
0xc2ab1c46684d5b2f
Calls in the sample
66
Reproduced, seen by the agent
3 / 47
Reproduced, never shown to the agent
0 / 17

3 of 64 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_24323
24323mov64 r6, r5
24324mov64 r8, r4
24325mov64 r9, r3
24326mov64 r7, r2
24327stxdw [r10-952], r1
24328lddw r1, 0x1ae3bc ; "Instruction: BuyExactQuoteInV2"
2432amov64 r2, 0x1e
2432bcall sol_log_
2432cldxdw r1, [r6-4088]
2432djlt r1, 0x8, +109 ; -> 2439b
2432emov64 r2, r1
2432fand64 r2, -0x8
24330jeq r2, 0x8, +106 ; -> 2439b
24331ldxdw r2, [r6-4096]
24332ldxdw r3, [r2+0]
24333mov64 r5, 0x0
24334ldxdw r4, [r2+8]
24335jeq r1, 0x10, +4 ; -> 2433a
24336ldxb r1, [r2+16]
24337jeq r1, 0x0, +2 ; -> 2433a
24338jne r1, 0x1, +153 ; -> 243d2
24339mov64 r5, 0x1
2433astxdw [r10-976], r5
2433bstxdw [r10-968], r4
2433cstxdw [r10-960], r3
2433dstdw [r10-891], -0x1
2433estdw [r10-896], -0x1
2433fstxdw [r10-8], r8
24340stxdw [r10-16], r9
24341mov64 r1, r10
24342add64 r1, -0x380
24343stxdw [r10-4088], r1
24344mov64 r1, r10
24345add64 r1, -0x1c0
24346mov64 r3, r10
24347add64 r3, -0x10
24348mov64 r5, r10
24349mov64 r2, r7
2434acall fn_13be6
2434bldxdw r8, [r10-432]
2434cldxdw r6, [r10-440]
2434dldxdw r9, [r10-448]
2434elddw r1, 0x8000000000000000
24350jeq r9, r1, +93 ; -> 243ae
24351mov64 r1, r10
24352add64 r1, -0x358
24353mov64 r2, r10
24354add64 r2, -0x1a8
24355mov64 r3, 0x198
24356call fn_35367
24357stxdw [r10-864], r8
24358stxdw [r10-872], r6
24359stxdw [r10-880], r9
2435aldxdw r1, [r10-896]
2435bstxdw [r10-416], r1
2435cldxdw r1, [r10-891]
2435dstxdw [r10-411], r1
2435eldxdw r1, [r10-8]
2435fstxdw [r10-424], r1
24360ldxdw r1, [r10-16]
24361stxdw [r10-432], r1
24362mov64 r1, r10
24363add64 r1, -0x370
24364stxdw [r10-440], r1
24365stxdw [r10-448], r7
24366mov64 r1, r10
24367add64 r1, -0x390
24368mov64 r2, r10
24369add64 r2, -0x1c0
2436aldxdw r3, [r10-960]
2436bldxdw r4, [r10-968]
2436cldxdw r5, [r10-976]
2436dcall fn_27215
2436eldxdw r6, [r10-912]
2436fjeq r6, 0x2, +1 ; -> 24371
24370ja +65 ; -> 243b2
24371mov64 r1, r10
24372add64 r1, -0x3a0
24373mov64 r2, r10
24374add64 r2, -0x370
24375mov64 r3, r7
24376call fn_14b46
24377ldxdw r1, [r10-720]
24378ldxdw r2, [r10-728]
24379ldxdw r3, [r2+0]
2437aadd64 r3, -0x1
2437bldxdw r8, [r10-920]
2437cldxdw r6, [r10-928]
2437dstxdw [r2+0], r3
2437ejne r3, 0x0, +3 ; -> 24382
2437fldxdw r3, [r2+8]
24380add64 r3, -0x1
24381stxdw [r2+8], r3
24382ldxdw r2, [r1+0]
24383add64 r2, -0x1
24384stxdw [r1+0], r2
24385ldxdw r4, [r10-952]
24386jne r2, 0x0, +3 ; -> 2438a
24387ldxdw r2, [r1+8]
24388add64 r2, -0x1
24389stxdw [r1+8], r2
2438aldxdw r1, [r10-672]
2438bldxdw r2, [r10-680]
2438cldxdw r3, [r2+0]
2438dadd64 r3, -0x1
2438estxdw [r2+0], r3
2438fjne r3, 0x0, +3 ; -> 24393
24390ldxdw r3, [r2+8]
24391add64 r3, -0x1
24392stxdw [r2+8], r3
24393ldxdw r2, [r1+0]
24394add64 r2, -0x1
24395stxdw [r1+0], r2
24396jne r2, 0x0, +24 ; -> 243af
24397ldxdw r2, [r1+8]
24398add64 r2, -0x1
24399stxdw [r1+8], r2
2439aja +20 ; -> 243af
2439blddw r1, 0x1b3c60
2439dcall fn_33e71
2439emov64 r1, r0
2439fand64 r1, 0x3
243a0mov64 r2, r1
243a1add64 r2, -0x2
243a2jlt r2, 0x2, +5 ; -> 243a8
243a3jeq r1, 0x0, +4 ; -> 243a8
243a4ldxdw r1, [r0-1]
243a5ldxdw r2, [r0+7]
243a6ldxdw r2, [r2+0]
243a7callx r2
243a8mov64 r1, r10
243a9add64 r1, -0x3b0
243aamov64 r2, 0x66
243abcall fn_32b09
243acldxdw r8, [r10-936]
243adldxdw r6, [r10-944]
243aeldxdw r4, [r10-952]
243afstxdw [r4+8], r8
243b0stxdw [r4+0], r6
243b1exit
243b2ldxdw r8, [r10-904]
243b3ldxdw r1, [r10-720]
243b4ldxdw r2, [r10-728]
243b5ldxdw r3, [r2+0]
243b6add64 r3, -0x1
243b7stxdw [r2+0], r3
243b8jne r3, 0x0, +3 ; -> 243bc
243b9ldxdw r3, [r2+8]
243baadd64 r3, -0x1
243bbstxdw [r2+8], r3
243bcldxdw r2, [r1+0]
243bdadd64 r2, -0x1
243bestxdw [r1+0], r2
243bfldxdw r4, [r10-952]
243c0jne r2, 0x0, +3 ; -> 243c4
243c1ldxdw r2, [r1+8]
243c2add64 r2, -0x1
243c3stxdw [r1+8], r2
243c4ldxdw r1, [r10-672]
243c5ldxdw r2, [r10-680]
243c6ldxdw r3, [r2+0]
243c7add64 r3, -0x1
243c8stxdw [r2+0], r3
243c9jne r3, 0x0, +3 ; -> 243cd
243caldxdw r3, [r2+8]
243cbadd64 r3, -0x1
243ccstxdw [r2+8], r3
243cdldxdw r2, [r1+0]
243ceadd64 r2, -0x1
243cfstxdw [r1+0], r2
243d0jne r2, 0x0, -34 ; -> 243af
243d1ja -59 ; -> 24397
243d2stxb [r10-896], r1
243d3lddw r1, 0x1b3d30
243d5stxdw [r10-448], r1
243d6mov64 r1, r10
243d7add64 r1, -0x10
243d8stxdw [r10-432], r1
243d9lddw r1, 0x1a96e0
243dbstxdw [r10-8], r1
243dcmov64 r1, r10
243ddadd64 r1, -0x380
243destxdw [r10-16], r1
243dfstdw [r10-416], 0x0
243e0stdw [r10-440], 0x1
243e1stdw [r10-424], 0x1
243e2mov64 r6, r10
243e3add64 r6, -0x370
243e4mov64 r2, r10
243e5add64 r2, -0x1c0
243e6mov64 r1, r6
243e7call fn_342ee
243e8mov64 r1, 0x15
243e9mov64 r2, r6
243eacall fn_01495
243ebja -78 ; -> 2439e
Reconstructedbuy_exact_quote_in_v2
// discriminator c2ab1c46684d5b2f ; handler fn_24323 -> try_accounts fn_13be6 -> logic fn_27215
pub fn buy_exact_quote_in_v2(ctx, spendable_quote_in: u64, min_tokens_out: u64, allow_partial: Option<bool> /*byte 16, default false*/) -> Result<()> {
msg!("Instruction: BuyExactQuoteInV2");
let curve = &mut ctx.bonding_curve;
require!(!curve.complete, 6005); // pc 27222 (curve struct byte 161)
require!(min_tokens_out != 0, 6020); // pc 27223
require!(spendable_quote_in != 0, 6041); // pc 27224
require_valid_fee_recipient(global, fee_recipient, curve.is_mayhem)?; // fn_078ef (mayhem curves -> reserved_fee_recipients)
if curve.quote_mint != Pubkey::default() {
// token-quoted curve: CreateIdempotent ATAs (fn_029be) for the fee recipient, buyback recipient,
// creator vault and user volume accumulator quote accounts; user pays rent
} else {
require!(quote_mint.key == WSOL, 6063); // pc 27501
}
let (protocol_bps, creator_bps, net, protocol_fee, creator_fee);
if user.key == global.fee_exempt_user /*Global struct +0x288*/ { // pc 274ad
net = spendable_quote_in; protocol_fee = 0; creator_fee = 0; // no-fee path
} else {
// fn_10820: market_cap = curve_market_cap(); CPI pump_fees::GetFeesWithQuoteMint(market_cap, quote_mint)
// (fee_config today: flat lp 0 / protocol 95 / creator 30 at every tier)
(protocol_bps, creator_bps) = fee_program_cpi(...);
if global.creator_fee_override_enabled /*byte 1086*/ && curve.creator_fee_bps != 0 { creator_bps = curve.creator_fee_bps; }
if curve.creator == Pubkey::default() { creator_bps = 0; }
let total_bps = protocol_bps.checked_add(creator_bps)?;
net = if total_bps == 0 { spendable_quote_in }
else { (spendable_quote_in as u128 * 10_000 / (10_000 + total_bps) as u128) as u64 }; // floor
require!(net != 0, 6041);
protocol_fee = ceil_div(net * protocol_bps, 10_000); // fn_107c7
creator_fee = if curve.creator != default { ceil_div(net * creator_bps, 10_000) } else { 0 };
let total = net.saturating_add(protocol_fee).saturating_add(creator_fee);
if total > spendable_quote_in { // rounding overshoot
net -= total - spendable_quote_in; // fees are NOT recomputed
require!(net != 0, 6042);
}
}
// fn_1347e: constant product, one unit of quote held back
let mut tokens_out = ((net - 1) as u128 * curve.virtual_token_reserves as u128
/ (curve.virtual_quote_reserves + net - 1) as u128) as u64;
if tokens_out > curve.real_token_reserves && allow_partial { // pc 2760a
tokens_out = curve.real_token_reserves;
net = quote_needed_for(tokens_out); // fn_13385
protocol_fee = ceil(net*protocol_bps/1e4); creator_fee = ceil(net*creator_bps/1e4);
require!(net + protocol_fee + creator_fee <= spendable_quote_in, 6002);
}
require!(tokens_out >= min_tokens_out, 6042); // pc 2761c
require!(tokens_out <= curve.real_token_reserves, 6021); // pc 27699
// fn_134f5: virtual_token -= tokens_out; real_token -= tokens_out; virtual_quote += net; real_quote += net
apply_buy(curve, tokens_out, net);
// fn_1148a: token transfer_checked associated_base_bonding_curve -> associated_base_user, signed by PDA ["bonding-curve", mint]
transfer_base(tokens_out);
if creator_fee != 0 {
if curve.cashback_enabled /*byte 163*/ {
transfer_quote(user -> user_volume_accumulator (or its quote ATA), creator_fee); fn_0f055: record cashback
} else {
transfer_quote(user -> creator_vault (or associated_creator_vault), creator_fee); // fn_1234d
}
}
transfer_quote(user -> bonding_curve (SOL) | associated_quote_bonding_curve (token), net); // fn_1229d
let buyback = if curve.is_mayhem /*byte 162*/ { 0 } else { protocol_fee * global.buyback_bps /*5000*/ / 10_000 }; // floor, fn_12780
transfer_quote(user -> fee_recipient | associated_quote_fee_recipient, protocol_fee - buyback); // fn_122f5
transfer_quote(user -> buyback_fee_recipient | associated_quote_buyback_fee_recipient, buyback); // fn_122f5
// update global/user volume accumulators, emit TradeEvent (ix_name "buy_exact_quote_in"), check completion
Ok(())
}

Replay model

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

const ALPH='123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
function b58(hex){let n=BigInt('0x'+hex);let s='';while(n>0n){s=ALPH[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.reserved_fee_recipient + reserved_fee_recipients[7] (raw offsets 483, 516..739)
const RESERVED=['e893141fb18e9f1574d810e178e19e30604e3175aa2e4a32dfc8600727d10709','3584536256094f912819127efa4e446b4333721793d13876f9aadbf3dc7d0b5f','6e75018220f942677003237b4d6b453759b4a5c690b59c35d9bb187a090cbd2a','33987a9ebb136799ab59925b13e5dc8b3081df005db427c1478fa46ff8c347a0','74e9543f3e37a2d046227addcb4e9c774c44258c43edf24aa8aae1f00214665b','da4c38cd6db7438f59b408bb9ec3b4ca9e8ad1f1f24653c499b5796c20dbf9b3','2ddd9eea3f39b372115c71847c1845cfa536c685074e030e44d021de3ef9e35c','4cb780f08ee2fee84bec446a577825da68d439fa8a5da3b0c5cff50f63f4546b'].map(b58);
const WSOL='So11111111111111111111111111111111111111112';
function model(ctx){
const A=ctx.accounts;
const spend=BigInt(ctx.args.spendable_quote_in);
const PB=95n, CB=30n, BUYBACK_BPS=5000n;
const tb=PB+CB;
let net=spend*10000n/(10000n+tb);
const ceil=(a,b)=>(a*b+9999n)/10000n;
const pf=ceil(net,PB), cf=ceil(net,CB);
let tot=net+pf+cf; if(tot>spend) net-=tot-spend;
const isSol=A[2].pubkey===WSOL;
const mayhem=RESERVED.includes(A[6].pubkey);
const bb=mayhem?0n:pf*BUYBACK_BPS/10000n;
const fr=pf-bb;
const vtok=A[11].token.amount+73000000000000n;
let vq;
if(isSol){ vq=A[10].lamports-1493520n+30000000000n; }
else { vq=A[12].token.amount+550724007602n; }
const tokens=(net-1n)*vtok/(vq+net-1n);
const L={},T={};
T[11]=-tokens; T[14]=tokens;
if(isSol){L[10]=net;L[6]=fr;L[8]=bb;L[16]=cf;}
else{T[12]=net;T[7]=fr;T[9]=bb;T[17]=cf;}
return {lamports:L,tokens:T};
}

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: spendable_quote_in: u64, min_tokens_out: u64

program 6EF8rr…BEwF6P