fix(amm): harden LP reward accounting against transfer-based claims - #3
Merged
Conversation
Fresh wallet + transferred LP claimed the full osola_reward_per_lp accumulator (reward_debt init 0). Confirmed on devnet: 900 oSOLA minted from zero deposit (tx 4RGNQYvmpV37abcrvKUdroQqCgFHVkkkZGbTTH3nuHifwejBPSY32KHiJb6QYVrxYwCj5AqjaRSMp5752VdnBQBe). Reward basis is now min(lp_amount, wallet_lp), lp_amount maintained by add/remove; epoch weight accrues only over time actually deposited (last_change_ts); per-epoch pot capped by osola_claimed. No account realloc (fields carved from spare bytes). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… fixed+deployed, A latent) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two AMM LP-reward defects sharing one root cause: rewards were computed on a freely-transferable SPL LP balance, never on a program-recorded deposit. The same lesson already applied to the founder/team tranches ("restrictions must live in state or escrow, never in a token balance") had never been applied to LP.
Finding B —
claim_lp_rewards: near-unbounded oSOLA mint — Critical (fixed + deployed)LpUserInfoisinit_if_needed→ a fresh wallet readsreward_debt = 0→ claims the fullosola_reward_per_lpaccumulator since pool creation. An attacker deposits, transfers LP to a fresh wallet, claims, withdraws, repeats. Confirmed on devnet (PoC minted ~900 oSOLA from a zero-deposit wallet; unbounded without the cap).Finding A —
checkpoint_lp: epoch-emission over-mint — latentBack-dated weight from
epoch_start+ per-wallet checkpoint PDA let the same LP be walked through N wallets against a denominator counted once, with no cumulative vsosola_allocated. Not exploitable whileosola_emission_initial = 0, but arms at mainnet emission config. Fixed by the same change.Fix
min(lp_amount, wallet_lp), wherelp_amountis a newLpUserInfofield maintained by add/remove.last_change_tsrestarts the epoch-weight window on any position change (no back-dating toepoch_start).claim_lp_emissionscaps the per-epoch pot via a cumulativeosola_claimed <= osola_allocated.LENunchanged, existing accounts deserialize).checkpoint_lpupdated to pass thelp_user_infoaccount.Verification
cargo check(devnet +--no-default-features),clippy -D warnings,cargo fmtclean.NothingToClaim (6007).Migration note
Existing LP positions read
lp_amount = 0and earn nothing until aremove+addre-registers the deposit. Do NOT seedlp_amountfrom the wallet balance — that reopens the hole.Full audit trail (PoC, tx signatures, attack matrix) in
SECURITY_WATCH.md(2026-07-21 entry).🤖 Generated with Claude Code