debpf
pump.fun / instructions

Instruction

sell_v2

Partly proven

Sells `amount` base tokens back into a pump.fun bonding curve. The curve can be priced in SOL or in an SPL quote token (e.g. PUMP). Anyone holding the token can call it. Payout = floor(vQuote·amount/(vToken+amount)), minus a protocol fee (95 bps) and a creator fee (30 bps by default; a per-curve override can raise it, e.g. 100 bps was seen on a PUMP-quoted curve). Both fees come from a CPI to pump's fee program and are rounded up. Unlike sell_v3, all fees are paid out right away: on normal curves Global.buyback_bps (5000) of the protocol fee goes to the buyback recipient and the rest to fee_recipient. On mayhem-mode curves (fee recipient must be one of Global's reserved recipients) all of it goes to fee_recipient. The creator fee goes to creator_vault (or its quote ATA). Fails if the curve is complete (6005), amount is 0 (6022), the seller holds fewer tokens than amount (6023), or the net payout is below min_sol_output (6003).

Discriminator
0x5df6823ce7e940b2
Calls in the sample
63
Reproduced, seen by the agent
9 / 37
Reproduced, never shown to the agent
4 / 25

13 of 62 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_243ec
243ecmov64 r6, r5
243edmov64 r9, r4
243eemov64 r8, r3
243efmov64 r7, r2
243f0stxdw [r10-936], r1
243f1lddw r1, 0x1ae3da ; "Instruction: SellV2"
243f3mov64 r2, 0x13
243f4call sol_log_
243f5ldxdw r1, [r6-4088]
243f6jlt r1, 0x8, +97 ; -> 24458
243f7and64 r1, -0x8
243f8jeq r1, 0x8, +95 ; -> 24458
243f9ldxdw r1, [r6-4096]
243faldxdw r2, [r1+0]
243fbstxdw [r10-944], r2
243fcldxdw r1, [r1+8]
243fdstxdw [r10-952], r1
243femov64 r1, -0x1
243ffstxw [r10-872], r1
24400stdw [r10-880], -0x1
24401stxdw [r10-856], r9
24402stxdw [r10-864], r8
24403mov64 r1, r10
24404add64 r1, -0x370
24405stxdw [r10-4088], r1
24406mov64 r1, r10
24407add64 r1, -0x1a8
24408mov64 r3, r10
24409add64 r3, -0x360
2440amov64 r5, r10
2440bmov64 r2, r7
2440ccall fn_1bfcc
2440dldxdw r8, [r10-408]
2440eldxdw r6, [r10-416]
2440fldxdw r9, [r10-424]
24410lddw r1, 0x8000000000000000
24412jeq r9, r1, +88 ; -> 2446b
24413mov64 r1, r10
24414add64 r1, -0x338
24415mov64 r2, r10
24416add64 r2, -0x190
24417mov64 r3, 0x190
24418call fn_35367
24419stxdw [r10-832], r8
2441astxdw [r10-840], r6
2441bstxdw [r10-848], r9
2441cldxdw r1, [r10-880]
2441dstxdw [r10-392], r1
2441eldxw r1, [r10-872]
2441fstxw [r10-384], r1
24420ldxdw r1, [r10-856]
24421stxdw [r10-400], r1
24422ldxdw r1, [r10-864]
24423stxdw [r10-408], r1
24424mov64 r1, r10
24425add64 r1, -0x350
24426stxdw [r10-416], r1
24427stxdw [r10-424], r7
24428mov64 r1, r10
24429add64 r1, -0x380
2442amov64 r2, r10
2442badd64 r2, -0x1a8
2442cldxdw r3, [r10-944]
2442dldxdw r4, [r10-952]
2442ecall fn_27b25
2442fldxdw r6, [r10-896]
24430jeq r6, 0x2, +1 ; -> 24432
24431ja +61 ; -> 2446f
24432mov64 r1, r10
24433add64 r1, -0x390
24434mov64 r2, r10
24435add64 r2, -0x350
24436mov64 r3, r7
24437call fn_1cec3
24438ldxdw r1, [r10-688]
24439ldxdw r2, [r10-696]
2443aldxdw r3, [r2+0]
2443badd64 r3, -0x1
2443cldxdw r8, [r10-904]
2443dldxdw r6, [r10-912]
2443estxdw [r2+0], r3
2443fjne r3, 0x0, +3 ; -> 24443
24440ldxdw r3, [r2+8]
24441add64 r3, -0x1
24442stxdw [r2+8], r3
24443ldxdw r2, [r1+0]
24444add64 r2, -0x1
24445stxdw [r1+0], r2
24446jne r2, 0x0, +3 ; -> 2444a
24447ldxdw r2, [r1+8]
24448add64 r2, -0x1
24449stxdw [r1+8], r2
2444aldxdw r1, [r10-640]
2444bldxdw r2, [r10-648]
2444cldxdw r3, [r2+0]
2444dadd64 r3, -0x1
2444estxdw [r2+0], r3
2444fjne r3, 0x0, +3 ; -> 24453
24450ldxdw r3, [r2+8]
24451add64 r3, -0x1
24452stxdw [r2+8], r3
24453ldxdw r2, [r1+0]
24454add64 r2, -0x1
24455stxdw [r1+0], r2
24456jne r2, 0x0, +20 ; -> 2446b
24457ja +53 ; -> 2448d
24458lddw r1, 0x1b3c60
2445acall fn_33e71
2445bmov64 r1, r0
2445cand64 r1, 0x3
2445dmov64 r2, r1
2445eadd64 r2, -0x2
2445fjlt r2, 0x2, +5 ; -> 24465
24460jeq r1, 0x0, +4 ; -> 24465
24461ldxdw r1, [r0-1]
24462ldxdw r2, [r0+7]
24463ldxdw r2, [r2+0]
24464callx r2
24465mov64 r1, r10
24466add64 r1, -0x3a0
24467mov64 r2, 0x66
24468call fn_32b09
24469ldxdw r8, [r10-920]
2446aldxdw r6, [r10-928]
2446bldxdw r1, [r10-936]
2446cstxdw [r1+8], r8
2446dstxdw [r1+0], r6
2446eexit
2446fldxdw r8, [r10-888]
24470ldxdw r1, [r10-688]
24471ldxdw r2, [r10-696]
24472ldxdw r3, [r2+0]
24473add64 r3, -0x1
24474stxdw [r2+0], r3
24475jne r3, 0x0, +3 ; -> 24479
24476ldxdw r3, [r2+8]
24477add64 r3, -0x1
24478stxdw [r2+8], r3
24479ldxdw r2, [r1+0]
2447aadd64 r2, -0x1
2447bstxdw [r1+0], r2
2447cjne r2, 0x0, +3 ; -> 24480
2447dldxdw r2, [r1+8]
2447eadd64 r2, -0x1
2447fstxdw [r1+8], r2
24480ldxdw r1, [r10-640]
24481ldxdw r2, [r10-648]
24482ldxdw r3, [r2+0]
24483add64 r3, -0x1
24484stxdw [r2+0], r3
24485jne r3, 0x0, +3 ; -> 24489
24486ldxdw r3, [r2+8]
24487add64 r3, -0x1
24488stxdw [r2+8], r3
24489ldxdw r2, [r1+0]
2448aadd64 r2, -0x1
2448bstxdw [r1+0], r2
2448cjne r2, 0x0, -34 ; -> 2446b
2448dldxdw r2, [r1+8]
2448eadd64 r2, -0x1
2448fstxdw [r1+8], r2
24490ja -38 ; -> 2446b
Reconstructedsell_v2
// Instruction: sell_v2(amount: u64, min_sol_output: u64) disc 5df6823ce7e940b2
// handler fn_243ec -> validate accounts (fn_1bfcc) -> sell_v2_logic fn_27b25
pub fn sell_v2(ctx: Context<SellV2>, amount: u64, min_sol_output: u64) -> Result<()> {
msg!("Instruction: SellV2");
let curve = &mut ctx.accounts.bonding_curve; // PDA ["bonding-curve", base_mint]
// fn_076ea: curve/global sanity + migration-state check
require!(!curve.complete, BondingCurveComplete /*6005*/); // pc 27b3d
require!(amount > 0, ZeroAmount /*6022 0x1786*/); // pc 27b83
require!(ctx.accounts.associated_base_user.amount >= amount,
InsufficientTokens /*6023 0x1787*/); // pc 27b86
// fn_078ef / fn_123fe / fn_029be x4: create-idempotent quote ATAs
// (fee recipient, curve, user, creator vault, volume accumulator), payer = user
// quote mint must be the curve's quote mint, else error 6063 (0x17af) // pc 27d92
// ---- price (fn_1341e, u128) ----
let gross = (curve.virtual_quote_reserves as u128 * amount as u128
/ (curve.virtual_token_reserves as u128 + amount as u128)) as u64; // floor
// ---- fees (fn_10820): CPI pump_fees::GetFeesWithQuoteMint(fee_config, quote_mint, ...) ----
let (protocol_bps, mut creator_bps) = fee_program::get_fees_with_quote_mint(...);
if global.creator_fee_override_enabled /*byte 1086*/ && curve.creator_fee_bps_override != 0 {
creator_bps = curve.creator_fee_bps_override; // e.g. 100 bps seen
}
let protocol_fee = ceil_div(gross * protocol_bps, 10_000); // fn_107c7 (95 bps observed)
let creator_fee = if curve.creator != Pubkey::default() { ceil_div(gross * creator_bps, 10_000) } else { 0 };
require!(gross >= protocol_fee + creator_fee, ...); // pc 27df3 / 27e02
let net = gross - protocol_fee - creator_fee;
require!(net >= min_sol_output, TooLittleSolReceived /*6003 0x1773*/); // pc 27e0f
// ---- move base tokens user -> curve (fn_135f3: transfer_checked, user signs) ----
token::transfer_checked(associated_base_user -> associated_base_bonding_curve, amount);
// ---- reserves update (fn_11594) ----
curve.virtual_token_reserves += amount; curve.real_token_reserves += amount;
curve.virtual_quote_reserves -= gross; curve.real_quote_reserves -= gross;
// ---- payouts ----
// quote == native SOL (wSOL mint): lamports debited directly from bonding_curve
// other quote mint: transfer_checked from associated_quote_bonding_curve, curve PDA signs (fn_137f5)
pay(user, net); // fn_12780
if protocol_fee > 0 { // pc 27e61
if !curve.is_mayhem_mode /* curve byte 163 */ {
let buyback = protocol_fee * global.buyback_bps /*5000*/ / 10_000; // floor, fn_073f3
pay(buyback_fee_recipient /*or its quote ATA*/, buyback); // fn_12196
pay(fee_recipient /*or quote ATA*/, protocol_fee - buyback);
} else {
// mayhem: fee_recipient must be a Global reserved fee recipient; no buyback split
pay(fee_recipient, protocol_fee); // fn_12196 + fn_0f055
}
}
pay(creator_vault /*or associated_creator_vault*/, creator_fee); // fn_12120 / fn_12227
// volume tracking: user_volume_accumulator updated if track_volume (fn_10d03)
emit!(TradeEvent { mint, sol_amount: gross, token_amount: amount, is_buy: false, user, timestamp,
virtual_sol_reserves, virtual_token_reserves, real_sol_reserves, real_token_reserves,
fee_recipient, fee_basis_points: protocol_bps, fee: protocol_fee, creator, creator_fee_basis_points,
creator_fee, ix_name: "sell", mayhem_mode, buyback_fee_basis_points, buyback_fee, .. });
Ok(())
}

Replay model

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

const ALPH='123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
function b58hex(s){let n=0n;for(const c of s){n=n*58n+BigInt(ALPH.indexOf(c));}let h=n.toString(16);while(h.length<64)h='0'+h;return h;}
const RESERVED=new Set(['e893141fb18e9f1574d810e178e19e30604e3175aa2e4a32dfc8600727d10709',
'3584536256094f912819127efa4e446b4333721793d13876f9aadbf3dc7d0b5f','6e75018220f942677003237b4d6b453759b4a5c690b59c35d9bb187a090cbd2a',
'33987a9ebb136799ab59925b13e5dc8b3081df005db427c1478fa46ff8c347a0','74e9543f3e37a2d046227addcb4e9c774c44258c43edf24aa8aae1f00214665b',
'da4c38cd6db7438f59b408bb9ec3b4ca9e8ad1f1f24653c499b5796c20dbf9b3','2ddd9eea3f39b372115c71847c1845cfa536c685074e030e44d021de3ef9e35c',
'4cb780f08ee2fee84bec446a577825da68d439fa8a5da3b0c5cff50f63f4546b']);
const WSOL='So11111111111111111111111111111111111111112';
const RENT=1493520n, VSOL0=30000000000n, VTOK0=1073000000000000n, TOKOFF=73000000000000n;
const K0=VSOL0*VTOK0;
function cdiv(a,b){return (a+b-1n)/b;}
function model(ctx){
const by={}; for(const a of ctx.accounts) by[a.name]=a;
const amount=BigInt(ctx.args.amount);
const vtok=by.associated_base_bonding_curve.token.amount+TOKOFF;
const isSol=by.quote_mint.pubkey===WSOL;
const mayhem=RESERVED.has(b58hex(by.fee_recipient.pubkey));
let vsol;
if(isSol){
const vA=by.bonding_curve.lamports-RENT+VSOL0; // exact if no fees accrued in curve
const vB=cdiv(K0,vtok); // k only grows -> lower bound
const band=vB/20000000n; // ~5e-8 drift allowance
if(mayhem || (vA>=vB && vA-vB<=band)) vsol=vA; else vsol=vB+vB/100000000n;
} else {
vsol=by.associated_quote_bonding_curve.token.amount+VSOL0;
}
const gross=vsol*amount/(vtok+amount);
const cbps = 30n;
const prot=cdiv(gross*95n,10000n), cre=cdiv(gross*cbps,10000n);
const bb = mayhem?0n:prot*5000n/10000n;
const fr=prot-bb;
const L={},T={};
T.associated_base_bonding_curve=amount; T.associated_base_user=-amount;
if(isSol){ L.bonding_curve=-gross; L.fee_recipient=fr; L.buyback_fee_recipient=bb; L.creator_vault=cre; }
else { T.associated_quote_bonding_curve=-gross; T.associated_quote_fee_recipient=fr; T.associated_quote_buyback_fee_recipient=bb; T.associated_creator_vault=cre; T.associated_quote_user=gross-prot-cre; }
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. 19user_volume_accumulatorwritten
  21. 20associated_user_volume_accumulatorwritten
  22. 21fee_config
  23. 22fee_program
  24. 23system_program
  25. 24event_authority
  26. 25program

args: amount: u64, min_sol_output: u64

program 6EF8rr…BEwF6P