Smart-contract security findings I submitted to CodeHawks First Flights, published as full write-ups with runnable proof-of-concept exploits.
Profile: profiles.cyfrin.io/u/augustwh11
| Valid findings | 17 — 8 High, 7 Medium, 2 Low |
| Rank | #281 |
| Contests | 3 (Thunder Loan, Snowman Merkle Airdrop, Rust Fund) |
First Flights are CodeHawks' educational contests: small codebases with deliberately seeded vulnerabilities, run so that people can learn the audit workflow. Finding a bug in one is not the same as finding one in a live protocol, and I am not going to present it as if it were.
What this repository is actually for is the other half of audit work: taking a suspicion, proving it with code, measuring what it costs the protocol, and writing it down so a developer can act on it. That part is identical whether the codebase is a training exercise or a mainnet deployment — and it is the part you can judge from the outside.
Six of the twelve High-severity submissions, chosen to cover different vulnerability
classes rather than to pad a count. The two canonical Thunder Loan bugs (settling a loan
via deposit, and deposit inflating the exchange rate) are deliberately left out — they
are the widely published ones and show nothing about how I work.
| Finding | Class | Contest |
|---|---|---|
| Nested flash loans book one fee per level, only one is ever paid | Re-entrancy → accounting inflation | Thunder Loan |
| Storage collision on upgrade charges a 100% flash-loan fee | Upgradeability / proxy storage layout | Thunder Loan |
| Fee is a WETH-denominated value charged in token units | Unit & denomination confusion | Thunder Loan |
| One global earn timer, resettable for free, denies farming to everyone | Griefing / DoS, zero-value edge case | Snowman |
| Claim flag is written but never read, so the proof replays | Replay / unenforced state flag | Snowman |
| Contribution amount is never recorded, so every refund returns zero | State not persisted (Rust / Anchor, Solana) | Rust Fund |
Every finding follows the same structure, because that is what makes a report usable:
- Description — the root cause, with the exact lines annotated, and the mechanism spelled out step by step rather than asserted.
- Risk — likelihood and impact argued separately, in terms of what an attacker needs and what the protocol loses, with numbers.
- Proof of Concept — a complete Foundry (or Anchor) test file that compiles and runs against the project's own fixtures, plus its actual output pasted in.
- Recommended Mitigation — a concrete diff, and where a single fix is not enough, the independent second change that should go with it.
Two habits I hold to: PoCs measure the damage instead of merely triggering the bug (the nested-flash-loan write-up drains a pool to 42 wei and reports the gas it took), and where a number could be read as bigger than it is, the write-up says so explicitly instead of letting it stand.
I direct the research — hypotheses, attack paths, and the call on what is real — and use AI to widen the search and pressure-test my reasoning. Every finding here was validated by writing an exploit that runs, and nothing goes in a report that I could not reproduce and explain line by line.
Related: postmortem-key-compromise-collateral-trust · technique-eth-call-state-override