A smart contract audit is an independent security review of your code before attackers get to it. It matters because deployed contracts often hold real money, can't be patched like a web server, and are attacked by people who read the same public code you published.
An audit isn't a certificate of safety. Audited protocols get exploited regularly. But unaudited code that holds value is an open invitation, and a good audit catches the bug classes that have caused most historical losses. This article explains what an audit is, how the process works, how to get value from one, and how needs differ for dApps, DeFi protocols and enterprise ledgers.
Why contracts need a different security bar
Three properties make smart contracts unusually unforgiving:
- Immutability. Deployed bytecode can't be edited. Upgradeable proxies exist, but upgrades themselves are a risk and need governance.
- Public, adversarial execution. Anyone can read your code and call any public function, in any order, with any input, including from contracts built specifically to exploit you.
- Composability. Your contract interacts with tokens, oracles and protocols you didn't write. A flash loan can give an attacker enormous capital for a single transaction.
The history is instructive. The DAO lost a large share of its ETH in 2016 to a reentrancy bug, leading to Ethereum's hard fork. A Parity multisig library was accidentally destroyed in 2017, freezing funds in every wallet that depended on it. In 2022, Nomad's bridge was drained after an upgrade initialized a value that let any message pass verification. In 2023, Euler Finance lost roughly $197 million despite multiple audits, through a flaw in a donation function introduced in a later code change; most funds were later returned. Each of these is a lesson in a specific class of failure.
What auditors look for
| Category | Examples |
|---|---|
| Access control | Missing onlyOwner checks, unprotected initializers, over-powerful admin roles |
| Reentrancy | External calls before state updates, including read-only and cross-function reentrancy |
| Oracle and price manipulation | Using spot AMM prices, stale feeds, missing sequencer-uptime checks on L2s |
| Math and precision | Rounding direction, decimal mismatches, share-inflation attacks on ERC-4626 vaults |
| Business logic | Liquidation edge cases, fee bypasses, incorrect state transitions |
| Signatures | Replay across chains or contracts, malleability, missing EIP-712 domain separation |
| Upgradeability | Storage collisions, uninitialized implementations, unsafe upgrade paths |
| Token integration | Fee-on-transfer and rebasing tokens, missing return values, ERC-777 hooks |
| Denial of service | Unbounded loops, griefing, blocking withdrawals |
| Centralization | Single keys that can pause, mint or drain; documented as trust assumptions |
Business-logic bugs are where human auditors earn their fee. Tools catch known patterns; only someone who understands what the protocol is supposed to do can spot that it does something else.
How an audit works
- Scoping. You share the repository, the exact files in scope and documentation. The auditor estimates effort from lines of code and complexity.
- Code freeze. You pin a commit hash. Auditing a moving target wastes everyone's time and leaves gaps.
- Automated analysis. Static analyzers like Slither, fuzzers like Echidna or Foundry's invariant tests, and sometimes symbolic tools flag common issues quickly.
- Manual review. Two or more reviewers read the code line by line, build a model of how value flows, and try to break invariants. This is most of the work.
- Formal verification (optional). For critical components, tools such as the Certora Prover or the K framework prove that specified properties always hold.
- Report. Findings are classified by severity (critical, high, medium, low, informational) with explanations and recommended fixes.
- Remediation and fix review. You fix the issues, and the auditor checks the fixes. Fixes introduce new bugs surprisingly often.
- Publication. The final report, tied to a commit hash, is usually published so users can verify what was reviewed.
What an audit costs, and why
Pricing is usually based on reviewer-weeks. Rates vary widely by firm reputation and demand, so rather than quoting numbers that go stale, it's more useful to understand the drivers:
- Code size and complexity. A standard ERC-20 with no custom logic may take days; a novel lending protocol can take several reviewers several weeks.
- Novelty. Forked, well-known code is faster to review than new mechanisms.
- External integrations. Each oracle, bridge or protocol you call adds assumptions to verify.
- Quality of tests and docs. Good specs and a high-coverage test suite let auditors spend time on deep issues instead of figuring out intent.
- Timeline. Top firms book well in advance; rush slots cost more.
Competitive audit contests (on platforms like Code4rena, Sherlock and Cantina) take a different approach: many independent researchers review the code in parallel for a prize pool. They often surface more findings, with more noise to triage. Many serious protocols use both a private audit and a contest, then a standing bug bounty.
Why audited code still gets hacked
- Out-of-scope changes. Code deployed differs from what was audited, or a later upgrade wasn't reviewed.
- Composition risk. The audited contract is safe alone but fails when combined with a new token or protocol.
- Economic attacks. The code does exactly what it says, but the incentives can be gamed, for example through governance capture or oracle manipulation with thin liquidity.
- Operational failures. Compromised keys, malicious front ends and social engineering. The February 2025 Bybit theft of roughly $1.5 billion in ETH, attributed by the FBI to North Korea's Lazarus Group, came from attackers manipulating the signing process of a multisig wallet, not from a bug in the wallet's audited contracts.
- Time-boxing. An audit is a fixed number of hours. It reduces risk; it does not eliminate it.
Security after the audit
Launch day is when the real test starts. A mature security program continues long after the report is published.
- Bug bounty. A public bounty, often hosted on a platform such as Immunefi, gives white-hat researchers a legal, paid path to report issues. Size rewards relative to funds at risk; a token reward for a critical bug in a protocol holding large deposits invites researchers to sell the bug elsewhere.
- On-chain monitoring. Watch for unusual events: large withdrawals, admin function calls, oracle deviations, sudden changes in collateral ratios. Alerts should reach someone who can act at any hour.
- Pause and circuit breakers. A guardian role that can pause deposits or borrowing buys time during an incident. Rate limits on withdrawals or bridging cap the maximum loss from an unknown bug.
- Incident response plan. Decide in advance who can trigger a pause, how the team communicates, which security firms and exchanges to contact, and how to coordinate with white-hat rescues. Incidents are not the time to work out who holds which key.
- Timelocked governance. Delays on upgrades and parameter changes give users and monitors time to react to a malicious or mistaken proposal.
- Dependency tracking. Subscribe to security advisories for libraries, oracles and protocols you integrate. A vulnerability in a dependency is a vulnerability in your system.
Different needs for dApps, DeFi and enterprises
Consumer dApps and NFT projects
Contracts are often simpler, built on OpenZeppelin libraries. The main risks are minting logic, access control, signature-based allowlists and payment handling. A focused audit plus careful reuse of standard libraries is usually proportionate. See the smart contract NFT guide for common patterns.
DeFi protocols
The highest bar. Expect multiple independent audits, invariant fuzzing, formal verification of core math, economic modeling of liquidations and oracles, a public bug bounty sized relative to value at risk, and on-chain monitoring with pause mechanisms. The DeFi smart contract guide covers design for auditability.
Enterprises and permissioned ledgers
On Hyperledger Fabric or private EVM networks, participants are known, so the threat model shifts toward insiders, access control, data leakage and integration bugs. Chaincode still needs review for determinism and authorization checks, and the surrounding identity and key management deserves as much attention as the code. The Hyperledger explainer discusses that architecture.
Getting the most from an audit
- Write a short spec: what the system should do, its invariants, its trust assumptions and its admin powers.
- Have strong tests before the audit, including fuzz and invariant tests.
- Run Slither and fix trivial issues yourself so auditors don't spend time on them.
- Keep scope tight and the commit frozen.
- Budget time for remediation and a fix review.
- Verify deployed bytecode matches the audited commit, and publish the report.
- Secure admin keys with a multisig or MPC and timelocks; an audit can't protect a leaked key.
To compare audit providers and understand deliverables, see the smart contract audit buyer's guide.
Frequently asked questions
Does an audit guarantee my contract is secure?
No. It's a time-boxed expert review that significantly reduces risk. Pair it with testing, bug bounties, monitoring and good key management.
When should I schedule the audit?
When the code is feature-complete and tested, but early enough to fix findings before launch. Book ahead; reputable auditors are often busy for weeks.
Do I need an audit if I only use OpenZeppelin contracts?
The libraries are well reviewed, but your configuration and any custom logic aren't. A lighter review is still sensible if the contract holds value.
Private audit or audit contest?
Private audits give consistent depth and a single accountable team; contests bring breadth. High-value protocols often do both.
Do upgrades need a new audit?
Yes. Every change to deployed logic should be reviewed, including the upgrade process itself.
What security references are worth reading?
The ethereum.org smart contract security page and the OpenZeppelin Contracts documentation are good primary starting points.