Technical guide. Updated February 15, 2026.
Smart contracts lost users over $5 billion between 2020 and 2025. Not because the technology is inherently insecure, but because writing correct code that handles value is difficult and the consequences of errors are irreversible. Understanding how key bugs work, what an audit covers, and how to verify a contract before interacting allows you to reduce risk in a practical way.
The most common bugs in smart contracts
Reentrancy: the vulnerability that affected The DAO
Reentrancy is the most well-known class of bug in the history of smart contracts. The mechanism: a contract A calls a contract B to transfer ETH; contract B, in its receiving function, calls A before A has updated its internal state. The result is that A is fooled into believing that the attacker’s balance is still high, and can be drained multiple times in the same transaction.
The DAO hack of 2016 exploited exactly that: $60 million in stolen ETH. The standard solution is the “checks-effects-interactions” pattern: always update the internal state (effects) before interacting with external contracts (interactions). OpenZeppelin’s ReentrancyGuard is the standard defense tool today.
Oracle price manipulation
Many DeFi protocols read the price of an asset from an on-chain spot price (e.g. an AMM pool). An attacker with enough capital โ often via flash loans โ can temporarily manipulate that price and use it to artificially liquidate positions or extract value from lending protocols. The defense is to use TWAP (Time-Weighted Average Price) prices instead of spot prices: the average over time is much more expensive to manipulate. Chainlink and other off-chain oracles solve the problem differently, but introduce an external dependency.
Flash loan attack
Flash loans allow you to borrow any amount without collateral, as long as it is repaid in the same transaction. They are not inherently dangerous โ they are a useful tool for arbitrage and liquidations. They become an attack vector when a protocol is not designed to handle large operations in a single block. Beanstalk (2022, $182M), Cream Finance (2021, $130M) and dozens of other protocols were flushed with flash loans that amplified vulnerabilities in contract design.
Integer overflow and underflow
Before Solidity 0.8.x, arithmetic operations could overcome the bounds of the integer type without reverting. A counter that was supposed to go to 100 could “wind up” to 0 if manipulated correctly. Since Solidity 0.8.x the default behavior is revert on overflow, but legacy contracts (or contracts compiled with old versions) remain vulnerable. OpenZeppelin’s SafeMath was the pre-0.8.x solution.
How a security audit works
A smart contract audit is a systematic review of code by security experts. It’s not a guarantee of no bugs โ it’s a significant reduction in the likelihood of common, known bugs.
What an audit covers
A good audit covers: business logic (does the code do what the whitepaper says?), known vulnerabilities (reentrancy, overflow, oracle manipulation, unauthorized access), external dependencies (oracle, tokens used as collateral, called contracts), and centralization (who can pause the contract, who can update it, by what mechanism).
What an audit does not cover: market risk, the quality of the team, the sustainability of the business model, zero-day vulnerabilities unknown at the date of the audit. An audit on old code does not cover subsequent changes, unless there is a re-audit.
How to find and read audits
Public audits are available on the project’s GitHub, in their Docs, or on platforms like Solodit.xyz that aggregate them. When you read an audit, look for: How many “critical” and “high” issues were found? Have they been resolved? Does the post-fix report confirm the resolution? A report that finds only “low” and “informational” can be a sign that the audit wasn’t thorough, or that the code is really clean โ you need to have the context to understand which.
Auditors recognized in 2026: Trail of Bits, Spearbit, OpenZeppelin, Halborn, Code4rena (contest model), Cantina. An audit by an unknown, unverifiable auditor is worth almost nothing as a security signal.
Upgradeability: proxy patterns and risks
Most major DeFi contracts are upgradeable: the code can be changed after deployment. This seems to contradict the premise of blockchain “immutability”, but it is a practical necessity for fixing bugs or adding features.
How the proxy pattern works
The standard mechanism is the proxy pattern: users interact with a proxy contract that delegates execution to an implementation contract. To upgrade, the implementation contract is replaced. The storage remains in the proxy, the code changes in the implementation.
The main risk is that a poorly designed upgrade can cause “storage collision”: if the new implementation uses variables in different storage locations than the previous one, it can corrupt existing data. The UUPS (Universal Upgradeable Proxy Standard) pattern and OpenZeppelin’s Transparent Proxy are the most used and audited.
Who can upgrade?
The critical question is not technical but one of governance: who holds the keys to authorize an upgrade? If it is a multisig with 3 anonymous people, the contract can be maliciously changed with the compromise of 2 keys. If it’s DAO governance with 48 hour timelock, you at least have time to exit before a malicious change takes effect.
Timelock: The security mechanism for governance
A timelock is a contract that imposes a delay between the proposal of a change and its execution. It is to give users time to check what is about to happen and to exit if they don’t approve.
Market standard: 24-48 hours for smaller protocols, 72 hours or more for high TVL protocols. Aave v3 uses a timelock of 24 hours for minor parameters and 7 days for critical changes. Compound uses 48 hours. A protocol without timelocks โ where upgrades can be performed instantly โ is structurally unsafe for users.
Check the timelock on chain: look for the Timelock contract in the explorer, check the value of minDelay and what address has the PROPOSER role. If the minDelay is 0 or the executor is a single EOA (Externally Owned Account), the timelock is effectively useless.
How to verify a contract before interacting
Etherscan: Verified vs. Unverified
On Etherscan, a contract is “verified” if the source code has been published and matches the deployed bytecode. This doesn’t mean the code is safe โ it means you can read it. An unverified contract doesn’t let you know what it does: avoid it for any relevant interactions.
Also check the deployment date and number of transactions. A contract deployed yesterday with zero transactions is a different signal than one deployed 2 years ago with millions of interactions.
Allowance: the risk that silently accumulates
Every time you approve a contract to spend your tokens (via ERC-20 approve), you are giving a permanent signature until you revoke it. Over time, you accumulate dozens of allowances on contracts that you may no longer use. If one of those contracts becomes compromised, it can drain you of approved tokens even if you no longer interact with it.
Verify and revoke allowances periodically with tools like Revoke.cash or Etherscan Token Approvals. Set allowance to the minimum required instead of โapprove maxโ โ many wallets and dApps offer this option. The gas cost of a revocation is minimal compared to the risk it eliminates.
Security checklist before interacting with a new contract
- Is the contract verified on Etherscan/Basescan/etc.?
- Is there a recent audit (no older than 12 months for an active codebase) from a recognized auditor?
- Who can upgrade the contract and with what timelock?
- Which oracle does he use for pricing โ spot price or TWAP?
- What is the allowance I’m giving โ is it limited or unlimited?
- Is there an active bug bounty on Immunefi or similar?
- What is the security history of the protocol over the last 12 months?
Access control: owners, roles and permissions
Most governance exploits โ not pure code bugs, but intentional manipulations โ exploit access control misconfigurations. Who can call which function on a contract is just as important as the correctness of the internal logic.
The Ownable pattern
The simplest contract has an “owner” who can perform administrative functions. OpenZeppelin Ownable is the standard pattern: an owner variable, an onlyOwner modifier, and ownership transfer functions. The main risk is that if the owner’s private key is compromised, the attacker has complete control. For contracts with high TVL, an EOA as owner is insufficient โ at least one multisig is needed.
Role-based access control (RBAC)
OpenZeppelin’s AccessControl introduces granular roles: ADMIN_ROLE, PAUSER_ROLE, UPGRADER_ROLE, etc. Each role can be assigned to different addresses โ a multisig for upgrades, a separate address for emergency pause, a third for operational parameters. Granularity reduces risk: compromising the PAUSER role does not give access to contract upgrades.
How to check: On Etherscan, in the “Read Contract” section, look for the hasRole, getRoleAdmin functions, and read which addresses have which roles. Then check those addresses: are they EOA or multisig? If they are multisig, how many signatories and with what threshold?
How to read and interpret an audit report
An audit report is a technical document that describes the vulnerabilities found, their severity and the status of resolution. Understanding how to read it allows you to use it as an evaluation tool, not as a simple certificate to display in marketing.
Structure of a typical report
Most audit reports are structured into: executive summary, scope (which code was reviewed, at which commit), findings (vulnerabilities), and technical appendix. The most important section for a non-technician is the findings with their resolution status.
Severity levels
| Severity | Meaning | Response expected |
|---|---|---|
| Critical | Direct and immediate loss of funds possible | Mandatory fix before deployment |
| High | Loss of funds possible under specific conditions | Strongly recommended fix |
| Medium | Misbehavior, loss of funds unlikely | Recommended fix |
| Low | Design problem, best practice not followed | Fix at discretion |
| Informational | Observation, no direct risk | Consider for future improvements |
A report with Critical or High issues not resolved before deployment is a serious red flag. A report with only Low and Informational may indicate a well-written codebase โ or an audit that isn’t thorough enough. Context and the auditor’s reputation are key to correct interpretation.
What to do if the audit is old
An audit that is valid at the time of deployment may become obsolete if the contract is changed. Always look for: Is the report dated? Have there been any upgrades or changes since the audit? If so, is there a re-audit that covers the changes? A protocol that boasts of 2021 audits on code that has been changed 10 times since then doesn’t offer the guarantees it seems.
Bug bounty: the security market continues
A bug bounty is a program that rewards those who find and responsibly report vulnerabilities instead of exploiting them. On Immunefi, the leading crypto bug bounty aggregator, rewards range from a few thousand to millions of dollars for critical vulnerabilities. MakerDAO, Compound, Aave, Uniswap all have bug bounties with maximum rewards above $1 million.
The existence of an active and well-funded bug bounty is a positive sign: it indicates that the team has an economic interest in finding bugs before attackers, and that the security researcher community has an incentive to look at the code. A protocol with $500 million TVL and no bug bounties is betting that its audits have been perfect โ a bet that historically has a poor track record.
Continuous monitoring: the initial audit is not enough
The security of a protocol is not static. New blocks are mined every few seconds; new transactions interact with contracts in ways that no audit could fully predict; Governance updates change the parameters. Continuous monitoring is an integral part of security.
Tools like Tenderly and Forta allow you to set alerts on specific events: an unusual large transaction to a contract you use, a change in owner, the activation of an emergency function. OpenZeppelin Defender offers a more comprehensive suite for teams managing contracts in production.
For users (not development teams), practical monitoring is simpler: follow the alert channels of the protocols you use (many have Telegram or Discord bots for security alerts), set up Etherscan alerts via email for major contracts, and use security aggregators like DeFi Safety or DefiWatch that report exploits as soon as they are detected.
Reaction speed is critical in the event of an exploit: serious protocols have incident response procedures that include emergency pauses (circuit breakers). But as a user, having an alert within 30 minutes of an exploit gives you time to exit before the situation deteriorates further โ often the difference between recovering 90% and 20% of the value.
Bug bounty: the preventative security market
Bug bounty programs represent one of the most effective mechanisms for preventative security of smart contracts. Platforms like Immunefi have distributed over $100 million in rewards to independent researchers who identified critical vulnerabilities before they were exploited. The cost of a bug bounty is almost always less than the cost of an unmitigated exploit.
Conclusion
Smart contract security is not a solved problem, but it is a manageable problem. The costliest bugs in history โ reentrancy, oracle manipulation, malicious upgrades โ are all preventable with known design patterns, quality audits, and transparent governance mechanisms. As a user, your role is to verify that these elements exist before trusting a contract with your capital.
Related reading: Bitcoin Market Cycles: The Complete Guide to Every Phase ยท On-chain analysis: a guide to understanding the crypto market.
