Smart Contracts Explained: From Ethereum's EVM to Modern Alternatives

What smart contracts actually are, how the EVM executes them, and why gas fees exist — explained for developers and curious readers.

From Human-Readable Code to Unstoppable Execution

Smart contracts are programs that live on a blockchain and execute exactly as written — no intermediaries, no downtime, no possibility of censorship. But what actually happens between the moment a developer writes a function in Solidity and the moment that function runs on thousands of nodes worldwide? The journey involves compilation, bytecode, a purpose-built virtual machine, and a metering system that keeps the whole network honest.

Writing Solidity: The Human Layer

Solidity is a statically typed, contract-oriented language that compiles down to Ethereum Virtual Machine (EVM) bytecode. When a developer writes a smart contract, they define state variables (data stored permanently on-chain), functions (logic that reads or modifies that data), events (logs that external systems can listen to), and modifiers (reusable guards like onlyOwner).

A simple ERC-20 token contract, for instance, tracks a mapping from addresses to balances, exposes transfer and approve functions, and emits Transfer and Approval events. In source form, this is approximately 200 lines of readable Solidity. Before any of it can run on Ethereum, it must be transformed into something the EVM understands.

The Compilation Pipeline

The Solidity compiler (solc) transforms source code through several intermediate representations:

  1. Parsing and semantic analysis — The compiler checks syntax, resolves type mismatches, and verifies that function signatures are internally consistent.
  2. Intermediate Representation (Yul) — Solidity generates an intermediate, lower-level language called Yul (formerly called Julia), which is easier to optimize and target to multiple backends.
  3. Bytecode generation — Yul is compiled into EVM bytecode: a flat sequence of one-byte opcodes and their operands. A PUSH1 0x60 instruction, for example, pushes the value 0x60 onto the EVM's stack.
  4. ABI generation — Alongside bytecode, solc produces the Application Binary Interface (ABI): a JSON description of every public function, its parameter types, and its return types. External callers use the ABI to encode function calls correctly.

The resulting bytecode is split into two parts: the creation code (run once during deployment to set up the contract's initial state) and the runtime code (stored permanently and run on every subsequent call).

The Ethereum Virtual Machine

The EVM is a stack-based virtual machine — it operates on a last-in, first-out stack of 256-bit integers, with no general-purpose registers. Every node in the Ethereum network runs an identical implementation of the EVM, which is what guarantees that the same input always produces the same output everywhere on the network.

Execution Environment

When a transaction calls a smart contract function, the EVM receives:

  • Calldata — the encoded function selector (first 4 bytes of the Keccak-256 hash of the function signature) plus ABI-encoded arguments
  • Caller contextmsg.sender (the calling address), msg.value (ETH sent), and block variables like block.timestamp and block.number
  • Contract storage — the contract's persistent key-value store on-chain
  • Memory — a fresh, temporary byte array that exists only for the duration of the call

The EVM steps through each opcode sequentially. Arithmetic opcodes like ADD and MUL pop values from the stack and push results back. SSTORE and SLOAD read and write the contract's permanent storage. CALL initiates a sub-call to another contract. LOG0 through LOG4 emit events.

Storage Layout

Persistent storage in a smart contract is a mapping from 256-bit keys to 256-bit values — essentially a hash map with 2^256 possible slots, almost all of which are zero by default. The Solidity compiler deterministically assigns storage slots to state variables: the first declared variable goes to slot 0, the second to slot 1, and so on. Mappings and dynamic arrays use hashed keys to avoid collisions.

This layout matters enormously for gas costs. Writing a non-zero value to a previously zero storage slot (SSTORE cold write) costs 22,100 gas. Updating an existing non-zero value costs 5,000 gas. This asymmetry incentivizes developers to initialize storage carefully and to pack multiple small values into a single 32-byte slot where possible.

Gas: The Metering System

Every opcode in the EVM has a fixed gas cost. Simple arithmetic costs 3 gas. A cold storage read costs 2,100 gas. Deploying a new contract costs 32,000 gas plus additional costs per byte of code. Gas transforms an infinite-loop problem — what stops a malicious contract from running forever? — into an economic one: every computation costs real money.

When submitting a transaction, the sender specifies a gas limit (the maximum units of computation they are willing to pay for) and a base fee plus optional priority fee (the price per unit, in gwei, following EIP-1559). If the transaction completes before exhausting its gas limit, unused gas is refunded. If gas runs out mid-execution, the transaction reverts — all state changes are rolled back — but the sender still pays for the computation already performed.

Gas Optimization Techniques

Because gas translates directly to user cost, Solidity developers invest heavily in optimization:

  • Using calldata instead of memory for function parameters reduces gas when data does not need to be modified
  • Packing structs so that multiple small variables share a single 32-byte storage slot halves storage costs
  • Short-circuiting conditionals — placing cheaper checks before expensive ones — avoids unnecessary computation
  • Events instead of storage — emitting an event costs roughly 375 gas plus 8 gas per byte of data, far cheaper than an SSTORE

Events and the Outside World

Smart contracts are deterministic and isolated — they cannot initiate outbound HTTP calls or read external data without an oracle. But they can communicate with the outside world through events. When a contract executes emit Transfer(from, to, amount), the EVM writes a log entry to the transaction receipt. This log is permanently stored in Ethereum's block data and indexed by address and topic.

External applications — wallets, DEX frontends, analytics dashboards — use the JSON-RPC eth_getLogs call or higher-level libraries like ethers.js to filter and decode these events in real time. A DeFi protocol's entire front-end might be built on nothing but event streams: it reconstructs the current state of every position by replaying all historical events from the contract's deployment block to the present.

finality-and-reverting">Execution Finality and Reverting

One of the most important properties of smart contract execution is atomicity. Either every state change in a transaction succeeds, or none of them do. If any opcode triggers a revert — whether through an explicit require check, an out-of-gas condition, or a failed sub-call — the EVM unwinds the entire call stack and restores the pre-transaction state.

This atomicity is what makes complex multi-step DeFi operations possible. A flash loan, for example, borrows millions of dollars of liquidity, uses it across multiple protocols, and repays it — all within a single transaction. If any step fails, the loan is never actually issued. The EVM's atomicity guarantee enforces this with no need for a trusted coordinator.

consensus">From Code to Consensus

Once a transaction is executed, its results must be agreed upon by the entire network. Ethereum nodes each run the EVM independently and arrive at the same new state root — the root hash of the Merkle Patricia Trie that encodes every account balance and every contract's storage. If any node's execution differs, its state root will not match, and the network will reject its blocks.

This combination — deterministic bytecode, metered gas, atomic execution, and consensus on the resulting state root — is what makes smart contracts genuinely "trustless." The code is the contract, and the contract executes itself.

Related Stories