A smart contract is a program stored on a blockchain that runs when a transaction calls it, with its result agreed by every node that re-executes it. It is not intelligent and it is not a contract. Nick Szabo named the idea in 1994 as a computerised transaction protocol that executes the terms of an agreement, and he said plainly that no artificial intelligence was implied. What makes it useful is narrower and stranger than the name suggests: the code runs identically for everyone, and nobody gets to decline to run it.
Deployed bytecode does not change, but most serious deployments sit behind a proxy that can be swapped by whoever holds the admin key. When a team calls their contract immutable, the useful follow up is which address can upgrade it, and what stands between that address and one person.
Scroll to see the full diagram
Neither smart nor a contract, and the man who named it agreed
Szabo's 1994 definition is still the cleanest available: a smart contract is a computerised transaction protocol that executes the terms of a contract, with design objectives of satisfying common contractual conditions, minimising exceptions both malicious and accidental, and minimising the need for trusted intermediaries.1 That predates Bitcoin by fourteen years and any working blockchain implementation by about two decades.
He answered the naming complaint himself. He called them smart because they were more functional than their inanimate paper based ancestors, and stated that no use of artificial intelligence is implied.2 The other half of the objection is fairer. A smart contract is not a contract in the legal sense. It has no parties, no consideration, no governing law and no remedy. It is an execution mechanism that a legal agreement can point at, and the two can disagree.
That gap is where the disputes will eventually live. If the code does something the parties did not intend, the code has still done it, and unwinding the result is a legal and social process happening entirely off-chain. Design for that possibility rather than assuming execution settles the question.
The execution model, and why determinism is a hard constraint
On Ethereum, accounts come in two kinds: externally owned accounts controlled by a private key, and contract accounts holding EVM code and storage. A transaction from an externally owned account triggers a message call that may execute a contract account's code, and the whole arrangement is specified as a state transition function over a single global state.3
Every node runs the same code and has to reach the same state, or consensus breaks. That forces a strict constraint on what a contract is allowed to know. The EVM has no network access, no filesystem, no clock beyond block level values, and no source of randomness. A contract cannot call an API. It cannot see the price of anything. It cannot tell the time except by reading a field that a block proposer chose.
Execution is also metered. Each operation carries a gas cost fixed by the protocol's fee schedule, the caller authorises a maximum, and running out reverts the entire transaction while the gas is still consumed.3 Deterministic and metered together are what make a public execution environment safe to expose to anonymous callers, and they are also why every design decision here is simultaneously a cost decision.
Immutable bytecode, upgradeable systems
Once deployed, a contract's code is fixed. The protocol offers no opcode that mutates deployed bytecode, which is why fixing a bug historically meant deploying a new contract and persuading everyone to migrate to it.3
Almost nobody accepts that in practice. The standard workaround is a proxy: a small contract at a permanent address that uses delegatecall to run a separate implementation contract's logic against its own storage. EIP-1967 exists because the pattern became widespread enough to need standardised storage slots for the implementation and admin addresses, so the proxy's bookkeeping does not collide with the implementation's own variables.4 EIP-2535 generalises it further, splitting functionality across multiple facets behind one stable address.5
So the honest description of most deployed systems is this: the bytecode at each address is immutable, and the behaviour of the address is not. That is a defensible engineering choice. It becomes a misleading claim when it is described as immutable code without mentioning the admin key, and it changes the risk assessment completely, because the security of the system now includes the security of whoever can call upgrade.
Scroll to see the full diagram
The DAO, and why reentrancy is still the canonical failure
The reference incident has a primary source. On 17 June 2016 Vitalik Buterin posted that an attack had been found and exploited in the DAO, describing a recursive calling vulnerability in which an attacker called the split function and then called split recursively inside the split, collecting ether many times over in a single transaction.6
The arithmetic is worth walking, because the bug is an ordering bug and nothing more. A contract holds 1,000 ETH and records that the attacker is owed 1. The withdraw function sends that 1 ETH first, then sets the recorded balance to zero. Sending ETH to a contract hands control to that contract's code, so the attacker's fallback function calls withdraw again before the balance write ever happens. The ledger still shows 1 owed, so another 1 ETH goes out. Repeat until gas runs out or the contract is empty. Two lines in the wrong order, and 1,000 ETH leaves through a function that was doing exactly what it was told.
The fix has been known since 2016 and it is one line of discipline: checks, then effects, then interactions. Zero the balance before sending anything. What keeps the class alive is that modern instances are harder to see. Cross function and cross contract reentrancy through a token transfer callback looks nothing like the textbook example, and the vulnerable call is often in a dependency rather than in the contract under review.
Oracles, and the boundary where determinism ends
A contract cannot see outside its own chain. Anything it needs from the world, a price, an interest rate, a shipment confirmation, a random number, has to be written on-chain by someone first, and that someone is an oracle whether or not the design uses the word.
This is the point where a system's security stops being about its code. A lending contract that liquidates against a price feed is exactly as safe as the cheapest way to move that feed, and the cheapest way is usually to move the thin market the feed reads from rather than to attack the oracle itself. Ask three questions of every external input. Who can write it. What does the contract do when it goes stale. What does moving it ten percent for one block earn an attacker.
Our own rule in review is that any input capable of triggering a transfer is treated as adversarial by default, including inputs the team controls. Insiders make mistakes at the same rate as everyone else, and from the contract's point of view a compromised key and a bad decision are identical.
The exploit classes that keep recurring
Reentrancy is the famous one. Access control is the more common one. A privileged function missing its modifier, an initialiser that can be called a second time, an admin role that was never renounced after deployment. These are boring failures and in aggregate they cost more than the exotic ones.
Then price and oracle manipulation, usually against a spot price read from a pool with shallow liquidity. Then upgrade key compromise, where no contract fails at all and the attacker simply becomes the admin. Then the class that involves no code defect whatsoever: economic and parameter attacks, where every function behaves exactly as specified and the specification was wrong. Collateral factors set too generously. A rewards formula paying out more than the protocol earns. A governance threshold reachable with borrowed tokens.
A competent code audit finds the first three reliably. It finds the last one only if the scope covered the economics, and most audit scopes do not. That gap is the entire reason a tokenomics audit is a separate exercise from a code audit rather than a section of one.
What to settle before deployment
Five questions, all answerable before an audit starts. Who can upgrade, and how long is the delay between an upgrade being proposed and taking effect. What happens if the oracle stops updating, written as behaviour rather than intention. What is the invariant, stated as one sentence that must stay true no matter which functions are called in which order. Who can pause, and can the same party unpause. And what did the audit scope exclude, in writing.
The last one is the one founders skip. An audit report is a statement about a specific commit and a specific scope. The difference between what was reviewed and what was deployed is where a surprising share of incidents live, and that difference is usually documented on page two of the report nobody read past the summary of.
None of this is legal advice, and whether a given deployment creates enforceable obligations is a question for counsel in the relevant jurisdiction. The engineering point stands on its own: the code is the mechanism, not the agreement.
Common questions
Are smart contracts legally binding?
Not by themselves. A smart contract executes code; it has no parties, governing law or remedy in the way a legal contract does. Many arrangements pair a legal agreement with on-chain execution, so the agreement supplies enforceability and the contract supplies settlement. When the two disagree, the code has already acted and unwinding it becomes a legal process happening off-chain. Treat enforceability as a question for counsel in the relevant jurisdiction.
Can a smart contract be changed after it is deployed?
The deployed bytecode cannot be modified, but the system's behaviour usually can. The common pattern is a proxy at a fixed address that delegates to a swappable implementation contract, which is why EIP-1967 standardises storage slots for the implementation and admin addresses.4 So the practical question is never whether the code is immutable. It is who holds the upgrade key and what delay applies.
What happens if a smart contract has a bug?
The bug executes. There is no operator who can decline a transaction, so a flawed function runs for anyone who calls it until the contract is paused, drained or migrated away from. Recovery depends on what the team built in advance: a pause function, an upgrade path, a timelock, a monitored invariant. Teams that planned none of those are left negotiating with an attacker in public.
Why are they called smart contracts?
Nick Szabo coined the phrase in 1994 for a computerised transaction protocol that executes the terms of a contract.1 He later explained that he chose smart because such contracts are more functional than paper based ancestors, and stated that no use of artificial intelligence is implied.2 The name has caused confusion ever since, because the code is neither intelligent nor a contract in the legal sense.
Do smart contracts need oracles?
Any contract depending on information from outside its own chain does. The EVM has no network access and must stay deterministic, so external data has to be written on-chain by some party first. That party is a trust assumption and an attack surface. Contracts that only move their own tokens between accounts need no oracle; anything pricing, lending, insuring or settling against real world events does.
See Tokenomics Audit for how this applies in practice.
Sources
- Smart Contracts
Nick Szabo (mirrored, University of Amsterdam), 1994
Original definition of a smart contract as a computerised transaction protocol that executes the terms of a contract. - An Introduction to Smart Contracts and Their Potential and Inherent Limitations
Harvard Law School Forum on Corporate Governance, 2018
Reproduces Szabo's clarification that he called them smart for functionality and that no use of artificial intelligence is implied. - Ethereum: A Secure Decentralised Generalised Transaction Ledger (Yellow Paper)
Gavin Wood, Ethereum Foundation
Account types, message calls, the state transition function, the gas fee schedule, and the absence of any opcode that mutates deployed code. - EIP-1967: Standard Proxy Storage Slots
Ethereum Improvement Proposals, 2019
Standardised slots for a proxy's implementation and admin addresses, motivated by delegating proxies used for upgradeability and gas savings. - EIP-2535: Diamonds, Multi-Facet Proxy
Ethereum Improvement Proposals, 2020
Multi-facet proxy pattern splitting functionality across facet contracts behind one stable address. - CRITICAL UPDATE Re: DAO Vulnerability
Ethereum Foundation Blog, 2016
Contemporaneous announcement by Vitalik Buterin describing the recursive calling vulnerability in the DAO's split function.
Last reviewed 2026-08
More in Blockchain Fundamentals
Know the terms but not sure how they apply to your project? That is what an engagement is for. We design, document, and stress-test the whole token economy inside the Tokenomics Data Room.
80+ projects advised. Complete tokenomics in 4 to 6 weeks.