Instruction
sell
Sells `amount` of a pump.fun token back into its bonding curve for SOL. Anyone holding the token can call it. The SOL comes straight out of the curve account. The price is the constant-product quote floor(vSOL·amount/(vTOKEN+amount)). From that, a 0.95% protocol fee and a 0.30% creator fee are taken, both rounded up; the rates come from a CPI to pump's fee program. Half the protocol fee (Global.buyback_bps = 5000, rounded down) goes to a buyback recipient passed as an extra account. The other half goes to fee_recipient, and the creator fee goes to creator_vault. One exception: when the seller is Global.whitelist_pda (a PDA that pump's admin sets), every fee is skipped and it gets the full gross amount. The sell fails if the curve has already completed or migrated (6005), if amount is 0 (6022), if you hold fewer tokens than amount (6023), or if the net SOL is below min_sol_output (6003).
- Discriminator
- 0x33e685a4017f83ad
- Calls in the sample
- 91
- Reproduced, seen by the agent
- 1 / 64
- Reproduced, never shown to the agent
- 3 / 27
4 of 91 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.
24a0emov64 r6, r524a0fmov64 r9, r424a10mov64 r8, r324a11mov64 r7, r224a12stxdw [r10-2128], r124a13lddw r1, 0x1ae4a1 ; "Instruction: Sell"24a15mov64 r2, 0x1124a16call sol_log_24a17ldxdw r1, [r6-4088]24a18jlt r1, 0x8, +97 ; -> 24a7a24a19and64 r1, -0x824a1ajeq r1, 0x8, +95 ; -> 24a7a24a1bldxdw r1, [r6-4096]24a1cldxdw r2, [r1+0]24a1dstxdw [r10-2136], r224a1eldxdw r1, [r1+8]24a1fstxdw [r10-2144], r124a20mov64 r1, -0x124a21stxb [r10-2068], r124a22stxw [r10-2072], r124a23stxdw [r10-2056], r924a24stxdw [r10-2064], r824a25mov64 r1, r1024a26add64 r1, -0x81824a27stxdw [r10-4088], r124a28mov64 r1, r1024a29add64 r1, -0x40024a2amov64 r3, r1024a2badd64 r3, -0x81024a2cmov64 r5, r1024a2dmov64 r2, r724a2ecall fn_2d92724a2fldxdw r8, [r10-1008]24a30ldxdw r6, [r10-1016]24a31ldxdw r9, [r10-1024]24a32lddw r1, 0x800000000000000024a34jeq r9, r1, +88 ; -> 24a8d24a35mov64 r1, r1024a36add64 r1, -0x7e824a37mov64 r2, r1024a38add64 r2, -0x3e824a39mov64 r3, 0x3e824a3acall fn_3536724a3bstxdw [r10-2032], r824a3cstxdw [r10-2040], r624a3dstxdw [r10-2048], r924a3eldxw r1, [r10-2072]24a3fstxw [r10-992], r124a40ldxb r1, [r10-2068]24a41stxb [r10-988], r124a42ldxdw r1, [r10-2056]24a43stxdw [r10-1000], r124a44ldxdw r1, [r10-2064]24a45stxdw [r10-1008], r124a46mov64 r1, r1024a47add64 r1, -0x80024a48stxdw [r10-1016], r124a49stxdw [r10-1024], r724a4amov64 r1, r1024a4badd64 r1, -0x82824a4cmov64 r2, r1024a4dadd64 r2, -0x40024a4eldxdw r3, [r10-2136]24a4fldxdw r4, [r10-2144]24a50call fn_295ee24a51ldxdw r6, [r10-2088]24a52jeq r6, 0x2, +1 ; -> 24a5424a53ja +61 ; -> 24a9124a54mov64 r1, r1024a55add64 r1, -0x83824a56mov64 r2, r1024a57add64 r2, -0x80024a58mov64 r3, r724a59call fn_2deaa24a5aldxdw r1, [r10-1328]24a5bldxdw r2, [r10-1336]24a5cldxdw r3, [r2+0]24a5dadd64 r3, -0x124a5eldxdw r8, [r10-2096]24a5fldxdw r6, [r10-2104]24a60stxdw [r2+0], r324a61jne r3, 0x0, +3 ; -> 24a6524a62ldxdw r3, [r2+8]24a63add64 r3, -0x124a64stxdw [r2+8], r324a65ldxdw r2, [r1+0]24a66add64 r2, -0x124a67stxdw [r1+0], r224a68jne r2, 0x0, +3 ; -> 24a6c24a69ldxdw r2, [r1+8]24a6aadd64 r2, -0x124a6bstxdw [r1+8], r224a6cldxdw r1, [r10-1280]24a6dldxdw r2, [r10-1288]24a6eldxdw r3, [r2+0]24a6fadd64 r3, -0x124a70stxdw [r2+0], r324a71jne r3, 0x0, +3 ; -> 24a7524a72ldxdw r3, [r2+8]24a73add64 r3, -0x124a74stxdw [r2+8], r324a75ldxdw r2, [r1+0]24a76add64 r2, -0x124a77stxdw [r1+0], r224a78jne r2, 0x0, +20 ; -> 24a8d24a79ja +53 ; -> 24aaf24a7alddw r1, 0x1b3c6024a7ccall fn_33e7124a7dmov64 r1, r024a7eand64 r1, 0x324a7fmov64 r2, r124a80add64 r2, -0x224a81jlt r2, 0x2, +5 ; -> 24a8724a82jeq r1, 0x0, +4 ; -> 24a8724a83ldxdw r1, [r0-1]24a84ldxdw r2, [r0+7]24a85ldxdw r2, [r2+0]24a86callx r224a87mov64 r1, r1024a88add64 r1, -0x84824a89mov64 r2, 0x6624a8acall fn_32b0924a8bldxdw r8, [r10-2112]24a8cldxdw r6, [r10-2120]24a8dldxdw r1, [r10-2128]24a8estxdw [r1+8], r824a8fstxdw [r1+0], r624a90exit24a91ldxdw r8, [r10-2080]24a92ldxdw r1, [r10-1328]24a93ldxdw r2, [r10-1336]24a94ldxdw r3, [r2+0]24a95add64 r3, -0x124a96stxdw [r2+0], r324a97jne r3, 0x0, +3 ; -> 24a9b24a98ldxdw r3, [r2+8]24a99add64 r3, -0x124a9astxdw [r2+8], r324a9bldxdw r2, [r1+0]24a9cadd64 r2, -0x124a9dstxdw [r1+0], r224a9ejne r2, 0x0, +3 ; -> 24aa224a9fldxdw r2, [r1+8]24aa0add64 r2, -0x124aa1stxdw [r1+8], r224aa2ldxdw r1, [r10-1280]24aa3ldxdw r2, [r10-1288]24aa4ldxdw r3, [r2+0]24aa5add64 r3, -0x124aa6stxdw [r2+0], r324aa7jne r3, 0x0, +3 ; -> 24aab24aa8ldxdw r3, [r2+8]24aa9add64 r3, -0x124aaastxdw [r2+8], r324aabldxdw r2, [r1+0]24aacadd64 r2, -0x124aadstxdw [r1+0], r224aaejne r2, 0x0, -34 ; -> 24a8d24aafldxdw r2, [r1+8]24ab0add64 r2, -0x124ab1stxdw [r1+8], r224ab2ja -38 ; -> 24a8d
// discriminator 33e685a4017f83ad — handler fn_24a0e -> sell_logic fn_295eepub fn sell(ctx: Context<Sell>, amount: u64, min_sol_output: u64) -> Result<()> {msg!("Instruction: Sell");// fn_2d927 (Anchor try_accounts): global PDA, bonding_curve PDA ["bonding-curve", mint],// associated_bonding_curve = ATA(bonding_curve, mint), associated_user owned by user,// creator_vault PDA ["creator-vault", bonding_curve.creator], event_authority, fee_config/fee_program.ensure_curve_size_166(&ctx.bonding_curve)?; // fn_076ea: realloc to >=166 bytesvalidate_fee_recipient(&ctx.fee_recipient, &global, &curve)?; // fn_078ef// !curve.is_mayhem_mode -> fee_recipient ∈ {global.fee_recipient} ∪ global.fee_recipients[7]// curve.is_mayhem_mode -> fee_recipient ∈ {global.reserved_fee_recipient} ∪ global.reserved_fee_recipients[7]let curve = &mut ctx.bonding_curve;require!(!curve.complete, BondingCurveComplete /*6005*/); // pc 2960frequire!(amount != 0, SellZeroAmount /*6022*/); // pc 29658require!(ctx.associated_user.amount >= amount, NotEnoughTokensToSell /*6023*/); // pc 29659// fn_1341e: u128 math, floorlet denom = curve.virtual_token_reserves.checked_add(amount)?; // 6026 if 0let gross_sol = (curve.virtual_sol_reserves as u128 * amount as u128 / denom as u128) as u64;// fn_10820: CPI fee_program "GetFeesWithQuoteMint"(fee_config, mint/curve state) -> {lp_bps, protocol_bps, creator_bps}// (current fee_config 8Wf5TiAh…: flat 0 / 95 / 30 bps, single tier)let mut creator_bps = ret.creator_bps;if global.creator_fee_override_enabled /*Global byte @1086*/ && curve.creator_fee_bps_override != 0 {creator_bps = curve.creator_fee_bps_override;}let mut protocol_fee = ceil_div(gross_sol as u128 * ret.protocol_bps, 10_000); // fn_107c7let mut creator_fee = if curve.creator == Pubkey::default() { 0 }else { ceil_div(gross_sol as u128 * creator_bps, 10_000) };// pc 29714: fee exemption for the whitelisted router PDAif ctx.user.key == global.whitelist_pda { // Global borsh offset 451 (BwWK17cb…)protocol_fee = 0; creator_fee = 0; /* bps reported as 0 too */}let after_protocol = gross_sol.checked_sub(protocol_fee)?; // 29a53let net_sol = after_protocol.checked_sub(creator_fee)?; // 29a94require!(net_sol >= min_sol_output, TooLittleSolReceived /*6003*/); // pc 29737// reserve updates (all checked)curve.virtual_token_reserves += amount; // 6024 on overflowcurve.real_token_reserves += amount;curve.virtual_sol_reserves -= gross_sol;curve.real_sol_reserves -= gross_sol; // error if real_sol_reserves < gross_sol// fn_1179d: token CPI transfer_checked(associated_user -> associated_bonding_curve, amount, authority=user)if ctx.user.key != global.whitelist_pda {if creator_fee > 0 {if !curve.fee_sharing_flag /*byte 963*/ {move_lamports(curve -> creator_vault, creator_fee); // fn_11fc7} else {// fn_0d290: creator fee routed through the fee-sharing path (not seen in samples)}}// cashback flag (curve byte 965) only changes the event fields here}move_lamports_from_curve(curve -> user, net_sol); // fn_11ef2if protocol_fee > 0 {// fn_12780let buyback = if curve.is_mayhem_mode { 0 }else { protocol_fee * global.buyback_bps /*5000*/ / 10_000 }; // floorif buyback > 0 {let r = get_buyback_recipient(remaining_accounts)?; // fn_0d75e; 6062 if missing; must be in Global buyback listmove_lamports_from_curve(curve -> r, buyback); // fn_11f5e}move_lamports_from_curve(curve -> fee_recipient, protocol_fee - buyback); // fee_recipient gets the rounding-up half}emit_cpi!(TradeEvent { mint, sol_amount: gross_sol, 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, fee: protocol_fee, creator, creator_fee_basis_points, creator_fee,ix_name: "sell", buyback_fee, ... });Ok(())}
Replay model
The executable model the agent wrote. Every tally above comes from running it against mainnet.
function rd(d,o){let x=0n;for(let i=7;i>=0;i--)x=(x<<8n)|BigInt(d[o+i]);return x;}const WHITELIST="BwWK17cbHxwWBKZkUYvzxLcNQ1YVyaFezduWbtm2de6s"; // Global.whitelist_pdafunction model(ctx){const A=ctx.accounts, d=ctx.data;const amount=rd(d,8);const ata=A[4].token.amount;const vtok=ata+73000000000000n;const k=30000000000n*1073000000000000n;const vsol=(k+vtok-1n)/vtok;const gross=vsol*amount/(vtok+amount);const ceil=(a,b)=>(a+b-1n)/b;const out={lamports:{},tokens:{}};out.tokens[4]=amount; out.tokens[5]=-amount;const user=A[6];if(user.pubkey===WHITELIST){ out.lamports[3]=-gross; out.lamports[6]=gross; out.lamports[1]=0n; out.lamports[8]=0n; return out; }const prot=ceil(gross*95n,10000n), cre=ceil(gross*30n,10000n);const buyback=prot*5000n/10000n;out.lamports[3]=-gross; out.lamports[1]=prot-buyback; out.lamports[8]=cre;if(A.length>15) out.lamports[15]=buyback;if(!user.signer) out.lamports[6]=gross-prot-cre;return out;}
Accounts
- 0global
- 1fee_recipientwritten
- 2mint
- 3bonding_curvewritten
- 4associated_bonding_curvewritten
- 5associated_userwritten
- 6usersigns, written
- 7system_program
- 8creator_vaultwritten
- 9token_program
- 10event_authority
- 11program
- 12fee_config
- 13fee_program
args: amount: u64, min_sol_output: u64
program 6EF8rr…BEwF6P