HomeGuides › What a smart contract is (and why it is not a contract)

Technology

What a smart contract is (and why it is not a contract)

How code running on the EVM actually works, why almost no contract is truly immutable, and what to check before you sign a transaction.

IC By InfoCrypto Editorial Published 5 March 2026 Updated 28 August 2026 12 min read

Key points

  • A smart contract is not a legal agreement: it is code executed deterministically on a virtual machine replicated across thousands of nodes.
  • Immutability is the exception, not the rule: proxy patterns, admin keys and pause functions make almost every meaningful contract modifiable.
  • Documented failures run into the billions: Ronin $620M, Poly Network $612M, Wormhole $320M, Nomad $190M, KelpDAO $292M, Drift $285M, Cetus $223M.
  • An audit reviews one specific version of the code on one specific date; it does not cover later upgrades, protocol economics, or external oracles.
  • Before signing, check that the code is verified on the explorer, who holds admin permissions, and how long it has been deployed.

A smart contract is neither smart nor a contract. Nick Szabo coined the name in the 1990s and it has caused more confusion than any other term in the sector: people assume there is an agreement, that there are parties, that there is some reasonable interpretation of what was meant. None of that exists.

What exists is a program. A program that lives at an address on a blockchain, runs when someone sends it a transaction, and does exactly what its code says — bugs included. If the code contains a flaw that lets someone drain it, the code is not "in breach" of anything. It is working.

That distinction is not philosophical. It is the reason billions of dollars have been lost through operations that were entirely valid from the protocol's point of view.

The precise definition

A smart contract is code and state stored at an address on the chain, executed deterministically on a virtual machine replicated by every node on the network.

Take that sentence apart:

  • Code and state at an address. The contract has its own balance and its own variables. The address is computed at deployment and never changes.
  • It runs when someone calls it. A contract does nothing by itself. It has no timer and does not wake up at three in the morning. Someone has to send it a transaction and pay the gas. Protocols that appear to act on their own use external bots that call the relevant function.
  • Deterministically. This is the core of it.

The EVM, and why determinism drives everything

The Ethereum Virtual Machine is what executes that code. It is not a machine sitting on a server: every node on the network runs the same instructions against the same state and has to arrive at exactly the same result. If one node got a different answer, the network would split.

Which is why the EVM has no access to anything external. It cannot make an HTTP request. It cannot read the system clock. It has no real random number generator. Everything it uses has to already be on-chain, because only then does every node compute the same thing.

Two consequences follow, and the entire sector wrestles with both.

Oracles. If a lending protocol needs the price of ETH to liquidate positions, someone has to put that price on-chain. That someone is an oracle, and it is an external dependency with its own trust model. A large share of attacks on DeFi protocols do not break the contract at all: they manipulate the price the contract reads.

Randomness. An honest on-chain lottery is a serious engineering problem. The naive attempts — using the block hash, using the timestamp — are either predictable or manipulable by whoever produces the block.

The lifecycle, step by step

Deployment. You send a transaction with no recipient whose data field contains the compiled bytecode. The network runs the constructor and stores the result at a new address. It is one of the most expensive operations that exists, because it writes permanent code into state.

Address. The contract now exists at that address. There is no server, no domain name, and no way to "move" it.

ABI. The Application Binary Interface is the specification of which functions the contract has, with which parameters and which return values. It is what lets your wallet translate "I want to approve 100 USDC" into the correct byte sequence. Without an ABI, a verified contract is still readable; without an ABI and without verified source, you are signing bytes blind.

Calls. There are two kinds and confusing them is common. A read (a call with no state change) is free: your node executes it locally and never touches the chain. A write needs a transaction, gas and a signature.

Events. The contract emits indexed logs that are not part of executable state but stay in transaction receipts. They are what explorers and front ends read to show you your history. A contract that emits no events is technically correct and practically useless.

"Immutable" is, nearly always, a lie

This is the most important point in the whole guide, and the one that shows up least often in introductory explanations.

It is true that the bytecode deployed at an address cannot be modified. But that does not mean the behaviour of the protocol you interact with is immutable, because the industry worked out three ways around it years ago.

The proxy pattern

Two contracts are deployed. The proxy holds the state — balances, positions, everything — plus a variable containing the address of the logic. The implementation holds the code. When you call the proxy, it delegates execution to the implementation but operates on its own state.

You always use the proxy address, which never changes. But whoever holds the admin key can repoint that variable at another implementation. The old code is still there, intact and immutable, and never runs again.

Admin keys

Many contracts have functions restricted to one specific address: changing fees, altering risk parameters, adding or removing accepted assets, withdrawing from the treasury. Who that address belongs to matters enormously. An individual account is not the same as a seven-of-which-four multisig, and an instant change is not the same as one behind a 48-hour timelock that gives you time to get out.

Pause functions

Almost every serious protocol has an emergency switch that freezes withdrawals or deposits. It is a defensible engineering decision: it has saved funds during live attacks. It also means somebody is capable of stopping you withdrawing your money.

When someone tells you "it's immutable, nothing can happen", ask three questions. Is it a proxy? Who controls the upgrade key? Is there a timelock before a change takes effect? If you cannot get a clear answer to all three, you are trusting people rather than code, and you should size your exposure accordingly.

Gas as a physical limit

Every EVM instruction costs gas units. That turns gas into something that does not exist in ordinary programming: a physical ceiling on code complexity.

A loop over a list that grows without bound will eventually exceed a block's gas limit, and the function becomes permanently unexecutable. It is a real failure mode, with documented cases of protocols bricked by a poorly designed data structure.

For a sense of scale: as of August 2026, with gas at 0.151 gwei, a Uniswap swap costs around $0.131. Translated into gas units with ETH at $2,505, that works out at roughly 346,000 units — sixteen times what a plain ETH transfer consumes. That factor of sixteen is the price of executing logic rather than moving a balance.

Composability: the virtue and the risk

Any contract can call any other without asking permission first. A new protocol can be built on top of three existing ones in an afternoon. This is called composability and it is why DeFi moves so fast.

It is also what lets a flaw propagate. If your protocol reads prices from an oracle that in turn depends on the liquidity of a pool, and someone manipulates that pool with a flash loan, your protocol will liquidate healthy positions or accept collateral that is worth nothing. There is no bug in your code. The bug is three layers down, in something you did not even choose.

The corollary is harsh: your risk is not the risk of your contract, it is the risk of the union of every contract it touches, and that surface grows with each new integration.

What has gone wrong, with the technical cause

Incident Date Amount Technical cause
Ronin Network 23 Mar 2022 ~$620M Bridge validator keys compromised. Attributed to Lazarus Group
Poly Network 10 Aug 2021 ~$612M Flaw in the cross-chain logic. Attacker returned ~$578.6M on 12 August
BSC Token Hub 6 Oct 2022 ~$570M Flaw in the native bridge
Wormhole 2 Feb 2022 >$320M Faulty signature verification in the bridge. Jump Crypto replaced 120,000 ETH
KelpDAO 18 Apr 2026 ~$292M DeFi protocol
Drift Protocol 1 Apr 2026 ~$285M DeFi protocol
Cetus Protocol (Sui) 22 May 2025 ~$223M DeFi protocol
Nomad Bridge 1 Aug 2022 >$190M Faulty initialisation: an upgrade left every proof valid. Over $36M was returned

The Nomad case deserves separate reading. A routine upgrade left a default value in place that made the contract accept any message as valid. As soon as the first person spotted it, hundreds of users copied that transaction and swapped in their own destination address. No expertise was required: copy and paste was enough. It is the cleanest example of why public code means public bugs.

The other pattern worth internalising is that bridges account for a wildly disproportionate share of the losses, because they accumulate custody of assets without inheriting the security of the chain that backs them. If you use a Layer 2, the bridge is your most serious point of exposure, not the network itself.

For scale, according to the Chainalysis report published on 8 January 2026, more than $3.4 billion was stolen during 2025, with the three largest incidents accounting for 69% of losses at services.

What an audit is, and what it does not guarantee

An audit is a manual and automated review of the code by a specialist firm, producing a report of the flaws found and their severity. It is useful. It is also systematically oversold.

What an audit does not cover:

  • Code deployed afterwards. The audit covers one specific commit; if the proxy is upgraded the following week, that code is unaudited.
  • Economic design. A contract can be flawless and its incentive model unsustainable. Terra is the canonical example.
  • Oracles and external dependencies. These are usually out of scope.
  • Key management. Whether the multisig is configured sensibly is not something the code can verify.
  • The web front end. The Ledger Connect Kit attack of 14 December 2023 touched no contract at all: attackers compromised a JavaScript library used by thousands of applications and drained roughly $484,000. The contracts were perfect.

An audit lowers the probability of an obvious flaw. It does not make a protocol safe, and several of the incidents in the table above happened in audited code.

How to read a contract before you sign

You do not need to know Solidity to run these checks on a block explorer such as Etherscan.

  • Confirm the source code is verified. If the explorer only shows you bytecode, do not interact: nobody can know what it does.
  • Look at the deployment date and the transaction count. A contract two days old with forty interactions is a different risk from one three years old with millions.
  • In the read tab, find functions like owner or admin and check which address they return. If it is an individual account rather than a multisig, at least you know.
  • Check whether it is a proxy. Explorers flag this and show you the current implementation. If it is, look at when it was last upgraded.
  • Look for pause functions, blacklist functions, or arbitrary mint functions. They exist and are legitimate in many cases, but they change what you are assuming.
  • On the signing screen, read which function you are calling and with what parameters. If the wallet says "unlimited approval" and you thought you were doing a $50 swap, stop.
  • Review your live approvals periodically and revoke the ones you no longer use.

Worked example: what happens when you approve a token and swap

You want to swap $500 of USDC for ETH on a decentralised exchange. Here is what actually happens, as of August 2026.

The starting point. Your 500 USDC is not an object sitting "in your wallet". It is an entry in a table inside the USDC contract: your account address maps to the number 500.000000. Your wallet stores no balances; it stores a private key and queries that table.

Step 1 — The approval. The exchange's router cannot touch your USDC balance, because the USDC contract does not allow it. So you sign a transaction to the USDC contract, not to the exchange, calling approve(router, 500000000). This writes a second entry: "the router address may move up to 500 USDC from this account". An Approval event is emitted. Cost: one storage write, on the order of cents with gas at 0.151 gwei.

This is the point where many front ends offer to approve an unlimited amount instead of 500. It saves one future transaction and leaves a live authorisation over your entire balance of that token, indefinitely.

Step 2 — The swap. Now you sign a second transaction, this one to the router, specifying what you are handing over, what you want back, and a minimum acceptable output. Inside that single transaction, the following happens:

  1. The router calls transferFrom on the USDC contract.
  2. USDC checks the authorisation you wrote in step 1, reduces it by 500, and moves your balance into the pool.
  3. The pool calculates how much ETH you are owed from its formula and current liquidity.
  4. If the result falls below the minimum you specified, the entire transaction reverts: your USDC returns to your account and the gas is lost.
  5. If it clears the threshold, the pool transfers the ETH to you and emits the corresponding events.

All of this is atomic. Either it all happens or none of it does. There is no intermediate state in which you handed over the USDC and did not receive the ETH.

Step 3 — The bill. With gas at 0.151 gwei and ETH at $2,505, the swap runs about $0.131 and the approval considerably less. On $500, the network cost is negligible. What actually costs you money is the pool fee and the slippage, both of which depend on the specific pool and its liquidity at that moment.

What is left afterwards. If you approved exactly 500 USDC, the authorisation is now zero and nothing is outstanding. If you approved unlimited, that router can keep moving your USDC tomorrow, next month, and two years from now, even if its implementation is upgraded to something else entirely. That forgotten authorisation is one of the most common vectors of fund loss, and revoking it costs one transaction of a few cents.

Frequently asked questions

Is a smart contract legally binding?

On its own, no. It is code that executes transfers of value automatically, not an agreement recognised by a legal system. A legal contract can reference a smart contract as its execution mechanism, and several jurisdictions accept it as evidence, but code execution and agreement validity are separate things. If the code does something the parties did not intend, the code wins on-chain.

If the code is immutable, how do protocols ship upgrades?

Through the proxy pattern. Two contracts are deployed: one holding the state and the address to call (the proxy) and another holding the logic (the implementation). The proxy is what you interact with and its address never changes, but whoever holds the admin key can point it at a different implementation. The old code still exists; it simply stops running.

What does it mean for a contract to be verified on Etherscan?

That someone uploaded the source code and the explorer confirmed that compiling it produces exactly the deployed bytecode. It lets you read what the contract does instead of staring at bytes. It does not mean the contract is safe or audited: a perfectly verified malicious contract is still malicious. It is a minimum requirement, not an endorsement.

Why am I asked to approve an unlimited amount of tokens?

Because it saves the protocol from requesting a fresh approval on every operation, and saves you gas. The cost is that the contract stays authorised to move your entire balance of that token, today and in the future. If it is later upgraded to a malicious version, or a flaw is found, the authorisation is still live. Review and revoke approvals you no longer use.

Sources and references

  1. Ethereum.org — Introduction to smart contracts
  2. Ethereum.org — Ethereum Virtual Machine (EVM)
  3. Chainalysis — Crypto hacking and stolen funds 2026
  4. Chainalysis — 2026 Crypto Crime Report
  5. SEC — Clarifies application of federal securities laws to crypto assets (17 Mar 2026)
  6. CoinDesk — Ledger Connect Kit exploit (14 Dec 2023)
  7. Etherscan — Ethereum explorer and source code verification
Important notice. InfoCrypto is an educational site. Nothing here is financial, tax or investment advice. Crypto assets are high risk: you can lose all the capital you invest. Always verify data against the original sources before making any decision, and consult a licensed professional if you need to.

Related guides