./resources / blog

Smart Contract & Web3 Security

In most software, a bug means a patch. In a smart contract, a bug can mean an irreversible, eight-figure loss — because the code is public, immutable once deployed, and holds real value that anyone on earth can try to take. Web3 security is application security with the safety nets removed.

A smart contract is a program deployed to a blockchain that executes exactly as written, autonomously, whenever its conditions are met. That determinism is the whole point — and the whole problem. The code is visible to every attacker, it usually cannot be changed after deployment, and it frequently custodies significant funds. There is no firewall to hide behind, no WAF to buffer a mistake, and no "roll back the database" after an exploit clears the vault. Understanding the attack surface, and the pipeline that hardens against it, is therefore non-negotiable before any contract touches mainnet.

Attack surface & hardening pipeline Smart Contract immutable · holds value Reentrancy via external call Oracle price manipulation Access Control missing / weak Integer over/underflow Hardening pipeline Develop Test Audit Deploy Monitor Preemptive Cyber Security
Figure 1. Four dominant threat classes ring the contract; a develop → test → audit → deploy → monitor pipeline hardens against them.

Reentrancy: the classic that keeps returning

Reentrancy remains the most infamous smart-contract flaw, and variants still drain funds years after the pattern was first understood. It occurs when a contract makes an external call — sending value to another address — before it has updated its own internal state. A malicious recipient contract can use that moment to call back into the original function repeatedly, each time seeing the stale, un-updated balance, and withdraw far more than it was owed. The defence is a discipline, not a library: follow the checks-effects-interactions pattern — validate conditions, update state, and only then make external calls — and add a reentrancy guard for functions that cannot avoid an external interaction.

Oracle manipulation: garbage in, exploit out

Contracts that need real-world data — the price of an asset, most commonly — rely on oracles. If a contract naively reads a price from a single on-chain source, such as the spot ratio of a liquidity pool, an attacker can distort that source for the length of a single transaction. Using a flash loan to momentarily skew a pool's balance, they make the contract value collateral or mint tokens at a fabricated price, then extract the difference — all atomically. The mitigation is to never trust a single, manipulable spot price: use time-weighted averages, aggregate across independent, well-secured oracle networks, and add sanity bounds that reject implausible movements.

Immutability is the double edge of Web3: it is what makes contracts trustworthy, and what makes their bugs permanent. You cannot patch your way out — you have to be right before you deploy.

Access control: who is allowed to do this?

Some of the largest losses trace not to exotic cryptography but to a missing modifier. A privileged function — one that withdraws funds, upgrades the contract, or changes ownership — left without a proper authorisation check is an open door. Related failures include uninitialised ownership after deployment, over-broad admin roles, and upgrade mechanisms that a single compromised key can abuse. Apply least privilege rigorously: use well-reviewed role-based access-control libraries, gate every state-changing privileged function, protect upgrade and ownership functions behind multi-signature control, and confirm initialisation happens atomically with deployment.

Integer overflow and arithmetic edge cases

Older contracts were plagued by integer overflow and underflow, where a value wrapping past its maximum or below zero produced absurd balances an attacker could exploit. Modern Solidity reverts on overflow by default, which closes the classic case — but arithmetic risk did not disappear. Unchecked blocks, casts between integer sizes, precision loss in division, and rounding that favours the wrong party remain live hazards. Reason carefully about every calculation that touches value, and test the boundaries explicitly.

The wider Web3 surface

The contract itself is only part of the picture. Real losses also come from the surrounding ecosystem: front-end interfaces that can be hijacked to trick users into signing malicious transactions, wallet approvals granted too broadly and never revoked, and cross-chain bridges — among the most catastrophic targets, since they concentrate value and combine complex logic with off-chain relayers. Composability is Web3's superpower and its systemic risk: because contracts freely call one another, a flaw in one protocol can cascade into every protocol that integrates it, and an economic assumption that holds in isolation can break when combined with a lending market or a flash-loan facility. Threat modelling has to extend past your own code to the dependencies and the humans who sign transactions.

The audit and testing pipeline

Because you cannot patch after the fact, assurance must be front-loaded into a layered pipeline. During development, use battle-tested libraries such as those from OpenZeppelin rather than hand-rolling primitives. In testing, aim for exhaustive unit coverage, then go further: fuzzing throws vast randomised inputs at the contract to surface edge cases, invariant testing asserts properties that must always hold ("total supply never exceeds the cap"), and static analysis flags known dangerous patterns automatically. The audit stage brings independent expert human review — the irreplaceable step where specialists reason about economic and cross-contract logic that tools miss. Ahead of or after audit, a bug bounty invites the wider security community to probe under incentive.

Deploy and monitor

Security does not end at deployment. Stage releases through testnets, consider a phased rollout with value caps, and keep tested emergency controls — a pause mechanism, an incident runbook — ready. Then monitor continuously: watch on-chain activity for anomalous transactions, sudden outflows, and oracle deviations, so that if something does go wrong, you detect and respond in minutes rather than reading about it on social media.

Key takeaways

  • Smart-contract code is public and immutable — bugs are permanent and directly monetisable, so assurance must be front-loaded.
  • Reentrancy is defeated by checks-effects-interactions plus a guard, not by luck.
  • Oracle manipulation beats naive spot prices — use TWAPs, aggregated feeds, and sanity bounds.
  • Many of the biggest losses are simple access-control gaps — gate every privileged function and protect upgrades with multi-sig.
  • Layer the pipeline: trusted libraries, fuzzing and invariant tests, independent audit, and continuous on-chain monitoring.
#web3 #smart-contracts #solidity #audit
All articles Audit your smart contracts