7High findings
4Medium and trust
~30Protocols reviewed
1Fix shipped
// How I work
The mechanical steps run as scripts so I am not retyping them every hunt. Verification is fork, eth_call, or a local Foundry test. I do not touch live state, and nothing goes public before it is patched.
- 01
Ground truth
Check the RPC answers and the chain id matches before anything else. Dead and spoofed endpoints are common enough to be worth a gate.
- 02
Find the core
Trace tokens and positions back to whatever deployed them. When the explorer is thin, the frontend bundle usually has the addresses labelled by role.
- 03
Map the surface
Balance, code size, Sourcify match, selector dump. This decides whether I am reading source or working from bytecode.
- 04
Triage auth
Call the admin and keeper signatures from an address with no privileges. Missing access control shows up here or not at all.
- 05
Read the value paths
Graduation, migration, settlement, claim accounting, by hand. Most of what I have found came from diffing two contracts that do the same job differently.
- 06
Prove it
Smallest Foundry test that demonstrates the bound, on a fork or against the exact deployed logic. Nothing runs against live state.
- 07
Try to kill it
Look for the reason the bug does not work before writing it up. Severity reflects what I proved, not the worst case I can imagine.
- 08
Report
Plain description first, then the bound, the affected addresses, and the fix. Sent privately and held until it is patched.
// Findings
Audit and bounty work, each linking to the full writeup. Every report says what an attacker gets, what it costs them, and where the impact stops.
High (7)
IMG_PLACEHOLDER
The Index: payout snapshot can be flash loaned
Distribution weights came from a live balanceOf read at a moment anyone could trigger. No checkpoint, no minimum hold. Borrow INDEX, get counted, hand it back, still collect the payout. Reproduced with a local Foundry test built from the deployed snapshot and distribute logic.
Explorearrow_forwardIMG_PLACEHOLDER
Robinlaunch: pool squat on V3 migration
Same shape as the Openfair bug on a different pad. Graduation and Direct Pool both deposit into whatever pool exists, at whatever price it holds. Bound is one launch, about 2.5 ETH. Covered by a Foundry test mirroring the call sequence.
Explorearrow_forwardIMG_PLACEHOLDER
HoodRich: no slippage bounds on V2 migration
addLiquidityETH ran with amountTokenMin and amountETHMin both at 0, so a pre skewed pair takes the raise at whatever ratio it holds. Found by comparison: the same codebase's meme factory already checked slot0, and a competing pad used 95 percent bounds on the identical call.
Explorearrow_forwardIMG_PLACEHOLDER
Openfair: pool squat on V3 graduation
Launches were seeded through createAndInitializePoolIfNecessary with no check on the price that came back. Anyone could open the pool first at a price of their choosing and the raise would land in it. Reported privately. Openfair shipped v2.0 and covered the launches that had already gone out. No funds were lost.
Explorearrow_forwardIMG_PLACEHOLDER
Merry Men: pre initialised V4 pool bricks the factory
initializePool returns rather than reverting when the pool already exists, and the factory never read the return value. Open the pool for the factory's next CREATE address and createToken fails during settlement. The revert rolls the nonce back, so every retry predicts the same address. Confirmed on an Anvil fork.
Explorearrow_forwardIMG_PLACEHOLDER
StockDotFun: pre initialised V4 pool freezes graduation
The locker calls initialize directly, which reverts if the pool key is taken. Claiming that key costs gas and no tokens. Graduation then fails for good, curve trading is already off, and roughly 4.4 ETH of raise has nowhere to go. The verified source has no owner recovery path.
Explorearrow_forwardIMG_PLACEHOLDER
Robinfun: dust on the pair blocks graduation
Curve selling stops once the target is hit and graduate is the only way forward. Around 0.000003 ETH of WETH sitting on the pair trips the pollution check and graduate reverts. Buyers cannot exit until the owner runs a recovery that sends the raise to treasury.
Explorearrow_forwardMedium (3)
IMG_PLACEHOLDER
HoodCash: short claims burn the rest of the accrual
When the pool holds less than a staker has accrued, the claim pays out what is there and still advances the claimed marker. The shortfall is gone, and refilling the pool does not bring it back. Any staker sets this off on their own rewards.
Explorearrow_forwardIMG_PLACEHOLDER
SLVR: claim delegates pick the recipient
approveDelegate lets a delegate choose where the ETH and SLVR go, not just trigger the claim. The official helpers hardcode safe recipients, so this only bites with a hostile or stolen delegate key. The project's own MultiClaim source flags the same problem.
Explorearrow_forwardIMG_PLACEHOLDER
xStocks: borrow fee debt is never minted
The fee is added to a user's debt but no stable is minted against it, so debt drifts past circulating supply. borrowFeeBps reads 0 on every engine I checked, so nothing is broken today. Turning fees on without changing the accounting starts the drift.
Explorearrow_forwardTrust model (1)
IMG_PLACEHOLDER
xStocks: one key sets the oracle price
The engine holding live TVL still reads EquityOracle V1 at quorum 1, and its single reporter is the owner address. That key decides mint limits and liquidation prices. Their own V2 oracle requires quorum 2 and a median, so the fix is already written.
Explorearrow_forwardTooling (1)
IMG_PLACEHOLDER
Bug hunt toolkit
Ten scripts covering the repeatable parts of a hunt: RPC and chain id check, creator trace, frontend bundle grep, surface map with Sourcify and a selector dump, unauthenticated call triage, Foundry fork scaffold, and the report and disclosure templates. Each one exits on a gate so a dead target gets dropped early.
Explorearrow_forwardWork is done on authorized targets, inside bounty or audit scope. Verification is read only or on a local fork. No production state is modified.