Most smart-contract exploits fall into a small set of well-known vulnerability classes. This checklist lets a developer self-audit a Solidity contract against those classes — reentrancy, access control, oracle manipulation, overflow, front-running, and more — before commissioning a formal audit. Items map to the SWC Registry and common Trail of Bits and ConsenSys Diligence findings.
How it works
Each control is marked OK, Issue, or N/A and carries a severity. The score counts only the applicable controls, and flagged issues are grouped so the most dangerous classes surface first:
applicable = total controls − (controls marked N/A)
score = OK controls / applicable × 100
issues → grouped by severity: critical → high → medium → low
A critical issue (reentrancy, broken access control, unprotected selfdestruct, delegatecall, or proxy init) triggers an explicit do-not-deploy warning regardless of the overall percentage.
The critical vulnerability classes in depth
Reentrancy
Reentrancy lets an external contract call back into your function before the first execution completes. The classic pattern: you send ETH before updating balances, so a malicious receiver’s fallback function calls back and drains additional funds. The fix is always to update state before making external calls (checks-effects-interactions pattern) or use a nonReentrant modifier. Mark all call, transfer, and send sites and verify that storage writes happen first.
Access control
Missing or incorrect access control is behind a large share of real DeFi incidents. Check every privileged function for an explicit role guard. Watch especially for:
- Functions that anyone can call to upgrade proxies or drain funds.
tx.originused instead ofmsg.senderfor authentication (allows a phishing contract to relay calls from a legitimate user).- Initializer functions on proxy implementations that can be called by anyone after deployment.
Oracle and price manipulation
If your contract reads a price from a DEX pool’s reserve0 / reserve1 ratio, an attacker can take a flash loan, move the price dramatically within a single transaction, trigger your logic, and repay the loan — all in one block. A time-weighted average price (TWAP) over many blocks, or an external feed with circuit breakers, defeats single-block manipulation.
Integer arithmetic
Solidity 0.8.x reverts on overflow and underflow by default. If you are auditing a contract written before 0.8 or one that uses unchecked blocks, verify each arithmetic operation manually. Division before multiplication is a common precision bug even in safe-math code.
Notes and example
For example, a lending contract that reads its collateral price from a DEX pool’s spot reserves will pass most controls but flags a high-severity oracle issue, because a flash loan can warp that price within one transaction and trigger bad liquidations. The fix is a time-weighted average or a Chainlink feed.
After the self-audit
Treat the checklist as the floor. Even a fully green self-audit should be followed by:
- Slither (Trail of Bits static analyzer) — run
slither .to catch common patterns automatically. - Echidna or Foundry fuzzing — property-based tests probe state space that unit tests miss.
- Formal verification — for high-value contracts, tools like Certora Prover or Halmos can prove invariants hold across all inputs.
- Professional audit — an independent firm reviews economic and composability bugs that no automated tool fully catches.
Everything is computed locally in your browser.