Deprecated, Not Dead
The code was deprecated. The money wasn't.
Hey, it’s Arsen.
In today’s menu:
• $17M from five contracts teams had already stopped watching
• The rounding bug in Kamino that no manual audit could reach
• What 15 security leaders wish they’d built from the start
• And more…
🏴☠️ Vulnerability
Precision Loss in Kamino Lending’s Exchange Rate
You’re auditing a lending protocol on Solana. Exchange rate math looks clean. The Fraction type handles the division. 68-bit integer, 60-bit fractional representation. Standard fixed-point arithmetic.
You mark it clean and move on.
What happens to the remainder every time that quotient is stored in 60 fractional bits?
It gets discarded. The stored rate comes out slightly lower than the real value. Negligible per operation. Imperceptible in testing. Invisible in a manual review.
Then someone redeems collateral.
pub fn fraction_collateral_to_liquidity(&self, collateral_amount: Fraction) -> Fraction {
collateral_amount / self.rate
}
You divide by a number that’s slightly too low. The quotient comes out slightly too high. The user redeems marginally more liquidity than they deposited. Free money, in principle.
Certora’s Prover ran two solvency rules against every user operation: shares minted must never exceed underlying liquidity, and share value must never decrease. Symbolic execution tests every possible input — not just the ones you thought to test.
It hit a counterexample on redeem_reserve_collateral. Both rules broke.
On Solana today you’d need $216M of BONK to trigger it. No single wallet has that. The invariant was still broken. Kamino patched it anyway — Mul-Div pattern, explicit round-down, gap closed.
The prover found what manual review couldn’t. Not because the reviewers were bad. Because they had to choose which inputs to test.
Symbolic execution doesn’t.
🗞️ News
Deprecated Contracts Drained $17M in 40 Days
Five protocols. Five different bugs. One shared condition.
Each contract had already been replaced or retired at the product level. None had been retired at the security level.
Over 40 days:
TrustedVolumes — May 7, $5.87M. Deprecated RFQ proxy. An authorization boundary bypassed on a path that should never have been reachable.
Huma Finance V1 — May 11, $101K. Deprecated pool proxies on Polygon. Small loss. Clear signal.
DxSale V1 — May 27, $7.3M. Legacy LP locker. Ownership context, monitoring, operational knowledge — all gone.
Raydium legacy AMM V3 — June 10, $1.34M. Stale account-validation on Solana. Dormant liquidity, still reachable.
Aztec Connect — June 14–15, $2.28M. Deprecated rollup exit path. No pause mechanism remaining. Two attackers. Consecutive mornings.
What does a “retired” contract look like from an attacker’s perspective?
Public on-chain. Finite address space. Poorly monitored. Full of stale assumptions. No active team watching for alerts.
That’s not retired. That’s optimal.
The long tail used to be expensive to search. AI-assisted triage is making it cheaper every month. Deprecated contracts are ideal search spaces — attackers don’t need to beat the newest protocol. They just need to find the old one that still holds money.
A contract is retired when value, permissions, and trust assumptions are gone.
Not when development stops.
📚 Education
15 Security Lessons from People Who Built Through It
Fifteen founders, CEOs, and security leads. Interviewed on building, protecting, and surviving Web3 security. This is what they said.
None of these lessons are new. Most teams know them. Few act on them before something breaks.
An audit is a point-in-time snapshot. It doesn’t describe your security posture — that’s a living thing. The teams with clean track records treat it as ongoing, not a completed PDF.
You inherit every integration’s security posture. External protocol, external failure modes. Your security is only as strong as your weakest dependency.
If these principles are common knowledge, why does every post-mortem say the same things?
Specs before code. Formal specifications catch design flaws before they become audit findings. Most teams skip this and pay for it during scope discussions — not before. Precision as a security issue, not a correctness issue: a single misplaced decimal in a financial protocol doesn’t produce wrong outputs. It breaks the system. Irreversibly.
One thread ran through every team that survived a major exploit: they used it as a forcing function. Rebuilt with more rigor. The teams that didn’t often didn’t get a second chance.
Building security in from day one is cheaper than retrofitting it.
Every one of these teams knew that before the incident.
That’s it for this week.
Reply with the Solana bug, tool, or pattern you want me to cover next — I read every one.
If a working Solana auditor in your circle would find this useful, forward it their way.
— Arsen, working Solana auditor




