Cover photo

The Ethereum Bytecode Lifecyle

filosofiacodigo.eth and Cooldev1337

We reject abstraction
We believe in bytecode
Bytecode is the only true form
Let’s code with bytes now

In the last article we explored opcodes, the individual instructions the EVM executes. Today we’re tracing the two distinct journeys your contract takes: one when you deploy it, and another each time it’s called.

1. Writing and Compiling

You start with a .sol or .vy file in Solidity or Vyper, defining functions, state variables and control flow in human-readable form. When you invoke solc or vyper, the compiler outputs EVM bytecode, a linear stream of one-byte opcodes plus any immediate data. That bytecode is split into a header segment, which runs once to set up constructor logic and write initial values into storage slots, and a runtime segment, the permanent code that lives at your contract’s address.

post image
On Remix, you can retrieve the compiled result by clicking the “Bytecode” button on the compiler tab. This will copy both the header and runtime segments to your clipboard. The same result can be obtained with Foundry and Hardhat.

2. Deploying a Contract

Deployment is its own transaction with to = 0x0 and data = <contract-bytecode>. That transaction enters the network’s mempool, where nodes check nonce, gas limit and signature. When a block proposer includes it in a block, the EVM executes the header segment: it manipulates the stack, uses transient memory (a temporary byte array that persists only during each transaction) for intermediate data, and writes to persistent storage slots (32-byte keys in the global state). If init succeeds within the gas budget, the runtime segment is returned and stored at the new contract address. For this point forward your contract is now live on the blockchain.

post image
Bytecode deployment using the cast command

3. Executing Contract Bytecode

Each call to your contract is another transaction with to = <contract-address> and data = <calldata>. Again it joins the mempool for basic validation. After mempool validation, the EVM loads the stored runtime bytecode and runs it with three data regions:

  • Stack for last-in, first-out temporary values,

  • Memory for intra-transaction data (a byte array that resets every call), and

  • Storage slots for persistent state (a mapping of 32-byte keys to 32-byte values).

post image
In Etherscan, you can see the bytecode passed calldata on every transaction. The calldata are the parameters passed to the runtime code.

Storage in Ethereum is organized using a data structure called the Merkle Patricia Trie, which is a specialized form of a Merkle tree. This trie efficiently encodes key-value pairs (such as storage slots or account data) into a compact structure where the root hash represents the entire global state. Every time a storage slot is updated, the corresponding MPT changes, resulting in a new root hash that reflects the updated state.

post image
Ethereum rely on Merkle-based trees where the root hash represents the entire global state. Currently the Merkle Patricia Trie is being used, although there are ongoing discussions about transitioning to more efficient structures like Verkle trees in the future.

During contract execution, each opcode consumes a certain amount of gas. If the transaction runs out of gas, all changes made during the call are reverted, this includes the stack, the memory and the storage. But when execution succeeds, the changes to storage and the emitted logs are emitted. The state of Ethereum then updates in the following flow: the old state root and the calldata (which you can think of as input parameters) are processed by the contract’s runtime bytecode. This produces an execution trace, which results in a new state root. The updated root reflects the global state after the transaction and is used in the block’s final state commitment.

post image
Ethereum steps during execution.

4. Consensus and Finality

Upon successful execution, the node calculates a new state root, a Merkle Patricia commitment covering every account balance and storage slot. That root is embedded in the block header. Under Proof-of-Stake, validators propose and attest to blocks; peers re-execute the same bytecode to confirm the state root matches, then follow the fork-choice rule and finalized checkpoints to agree on one canonical chain. Once finalized, your deployment or function call is irreversible.

post image
After execution is computed, validators reach consensus on what is the new state root. The new root is attached to the next block header.

Now that you have a clear, step-by-step view of deployment versus execution and how each leads to a consensus-backed state, you’re ready to dive deeper into how contracts are constructed at the bytecode level. Subscribe here on paragraph and join us next Tuesday for more bytecode.

ethereum
protocol

Collect this post as an NFT.

Subscribe to Bytecode Tuesday to receive new posts directly to your inbox.