Chapter 12 Quiz: The Ethereum Virtual Machine

Multiple Choice

Question 1

What type of architecture does the EVM use?

A) Register-based architecture with 32 general-purpose registers B) Stack-based architecture with a 256-bit word size C) Accumulator-based architecture with a single register D) VLIW (Very Long Instruction Word) architecture

Answer: B

Explanation: The EVM is a stack-based virtual machine where all operands are pushed to and popped from a last-in, first-out (LIFO) stack. Each stack item is exactly 256 bits (32 bytes) wide, chosen to align with the output size of Keccak-256 and the scalar size of the secp256k1 elliptic curve used in Ethereum's cryptography.


Question 2

Which of the following correctly describes the EVM's three data locations in order from cheapest to most expensive gas cost?

A) Storage, Memory, Stack B) Stack, Storage, Memory C) Stack, Memory, Storage D) Memory, Stack, Storage

Answer: C

Explanation: Stack operations are essentially free (their cost is included in the opcode that uses them, typically 3 gas). Memory costs 3 gas per word plus quadratic expansion costs. Storage is by far the most expensive: SSTORE costs 5,000-20,000 gas per operation because data must be permanently stored by every full node in the network.


Question 3

Why does writing to a new storage slot (SSTORE, zero to non-zero) cost 20,000 gas?

A) It is an arbitrary penalty to discourage contract deployment B) It reflects the permanent storage obligation imposed on every full node, including trie updates and disk I/O C) It subsidizes the mining reward D) It costs the same as any other SSTORE operation since EIP-2929

Answer: B

Explanation: A new storage slot creates a permanent entry in the contract's storage trie, which cascades to the account state trie and world state root. Every full node must store this data on disk indefinitely, perform Merkle proof updates, and serve it to other nodes. The 20,000 gas cost approximates the real resource burden this creates across the entire network.


Question 4

What is the maximum depth of the EVM stack?

A) 256 items B) 512 items C) 1,024 items D) Unlimited (bounded only by gas)

Answer: C

Explanation: The EVM stack has a hard limit of 1,024 items. Attempting to push a 1,025th item causes the transaction to revert. Additionally, only the top 16 items can be directly accessed via DUP and SWAP opcodes, which is why Solidity developers sometimes encounter "Stack too deep" errors.


Question 5

What is the difference between CREATE and CREATE2?

A) CREATE deploys contracts; CREATE2 destroys them B) CREATE uses sender + nonce for address derivation; CREATE2 uses sender + salt + bytecode hash C) CREATE is for EOAs; CREATE2 is for contracts D) CREATE2 is a deprecated version of CREATE

Answer: B

Explanation: CREATE computes the new contract address as keccak256(rlp([sender, nonce]))[12:], making the address depend on the sender's current nonce. CREATE2 computes it as keccak256(0xFF ++ sender ++ salt ++ keccak256(init_code))[12:], making the address deterministic based on the deployer, a chosen salt, and the exact bytecode. CREATE2 enables counterfactual deployment and predictable addresses.


Question 6

How does DELEGATECALL differ from CALL?

A) DELEGATECALL sends more gas to the called contract B) DELEGATECALL executes the called contract's code in the caller's storage context C) DELEGATECALL is read-only, like STATICCALL D) DELEGATECALL was removed in the Merge upgrade

Answer: B

Explanation: DELEGATECALL runs the target contract's code but uses the calling contract's storage, msg.sender, and msg.value. This means the called code can read and write the caller's storage. This is the mechanism behind proxy and upgradeable contract patterns, but it is dangerous if the storage layouts of the proxy and implementation do not match.


Question 7

What does a function selector represent in ABI encoding?

A) The full Keccak-256 hash of the function's source code B) The first 4 bytes of the Keccak-256 hash of the function's canonical signature C) A unique integer assigned by the compiler in order of function declaration D) The memory address where the function's bytecode begins

Answer: B

Explanation: A function selector is computed as keccak256("functionName(paramType1,paramType2,...)")[:4] — the first 4 bytes of the Keccak-256 hash of the function's canonical signature. For example, transfer(address,uint256) produces selector 0xa9059cbb. The selector is placed at the beginning of calldata to tell the contract which function to execute.


Question 8

Why does the EVM's memory expansion cost follow a quadratic formula?

A) It is a bug in the specification that has never been fixed B) Quadratic costs make small memory allocations cheap while preventing contracts from consuming unlimited RAM C) Memory is more expensive than storage, requiring higher pricing D) The quadratic formula matches the cost of Merkle trie operations

Answer: B

Explanation: The memory cost formula 3n + floor(n^2/512) is nearly linear for small n (making typical memory usage affordable) but grows quadratically for large n. This deliberately makes it economically impossible for a contract to allocate megabytes of memory, which would slow down or crash nodes. The quadratic cost is a DoS prevention mechanism.


Question 9

What is STATICCALL and when was it introduced?

A) A call that allows state modifications but not ETH transfer; added in Constantinople B) A read-only call that reverts if the called contract attempts any state modification; added in Byzantium (EIP-214) C) A call that bypasses gas metering for pure computation; added in the Merge D) A call to the beacon chain's state; added in Dencun

Answer: B

Explanation: STATICCALL (EIP-214, Byzantium upgrade) is identical to CALL except it enforces a read-only restriction. If the called contract tries to execute SSTORE, CREATE, LOG, or SELFDESTRUCT, the entire call reverts. This provides EVM-level enforcement that view and pure functions in Solidity cannot modify state, which is critical for safely calling untrusted contracts.


Question 10

Which of the following is NOT a reason the EVM sandbox prevents smart contracts from making network requests?

A) Different nodes might receive different responses, breaking consensus B) Network requests would make execution nondeterministic C) Ethereum's bandwidth is too limited for HTTP traffic D) Deterministic execution requires all nodes to produce identical results from identical inputs

Answer: C

Explanation: Bandwidth is not the reason. The EVM forbids network requests because they would introduce nondeterminism. If one node receives a 200 OK from an API and another receives a 503 error, their execution results would differ, making consensus impossible. The sandbox ensures every node, given the same state and transaction, produces the exact same output. This is a fundamental requirement for a decentralized state machine.


Question 11

What happens when a CALL instruction fails (the called contract reverts)?

A) The entire transaction is automatically reverted B) CALL pushes 0 on the caller's stack; the caller decides how to handle it C) The EVM retries the call up to 3 times D) The calling contract is destroyed via SELFDESTRUCT

Answer: B

Explanation: At the EVM level, a failed CALL pushes 0 (failure) onto the caller's stack without automatically reverting the caller. The caller must check this return value and decide what to do. Solidity's high-level call syntax adds automatic revert checks, but low-level address.call() does not — failing to check the return value is a well-known vulnerability pattern.


Question 12

What did EIP-2929 change about gas costs?

A) It doubled all gas costs to reduce network congestion B) It introduced cold/warm pricing: first access to a storage slot costs 2,100 gas (cold), subsequent accesses cost 100 gas (warm) C) It eliminated gas refunds for clearing storage slots D) It reduced SSTORE costs from 20,000 to 5,000 for all operations

Answer: B

Explanation: EIP-2929 (Berlin upgrade, April 2021) introduced the cold/warm distinction for state access. The first access to a storage slot (cold) costs 2,100 gas, reflecting the disk I/O required to read from the trie. Subsequent accesses (warm) cost only 100 gas since the data is cached in memory. This better reflects actual node costs and closed DoS attack vectors where attackers forced many expensive first-reads at below-cost prices.


Question 13

In ABI encoding, how are dynamic types (such as string or bytes) represented in the parameter area?

A) They are encoded inline, taking as many bytes as needed B) An offset is placed in the parameter position, pointing to where the actual data (length + content) begins C) They are stored in a separate calldata segment that the EVM reads with a special opcode D) Dynamic types cannot be passed as function parameters in the EVM

Answer: B

Explanation: ABI encoding uses an offset/data pattern for dynamic types. In the parameter's position, a 32-byte offset (pointer) indicates where the actual data begins relative to the start of the parameters section. At that offset, the data starts with a 32-byte length field followed by the actual content, padded to 32-byte boundaries. This allows the decoder to find fixed-position parameters immediately while handling variable-length data.


Question 14

What prevents the EVM from being used for denial-of-service attacks via infinite loops?

A) The Solidity compiler detects and rejects infinite loops at compile time B) The gas mechanism — every opcode costs gas, and transactions have a gas limit, ensuring execution always terminates C) Miners can detect and reject transactions containing loops D) The EVM does not support loop instructions

Answer: B

Explanation: The gas mechanism is the EVM's fundamental defense against infinite loops. Every opcode consumes gas, and every transaction specifies a gas limit. When gas runs out, execution halts and all state changes revert. This guarantees that no smart contract can execute indefinitely, regardless of its code. The Solidity compiler does not detect infinite loops (this is equivalent to the halting problem, which is undecidable).


Question 15

What is the significance of the JUMPDEST opcode?

A) It marks the end of a function body B) It marks valid destinations for JUMP and JUMPI instructions, preventing jumps into the middle of PUSH data C) It initializes the program counter at the start of execution D) It creates a checkpoint for transaction rollback

Answer: B

Explanation: JUMP and JUMPI can only target addresses containing a JUMPDEST opcode. This prevents "jump-into-data" attacks where an attacker could redirect execution into the middle of a PUSH instruction's data bytes, reinterpreting them as a different opcode sequence. JUMPDEST validation makes the EVM's control flow analyzable and prevents a class of code injection attacks.


Short Answer

Question 16

Explain why the EVM uses a 256-bit word size instead of the more common 32-bit or 64-bit word sizes used by conventional processors.

Model Answer: The 256-bit word size aligns with Ethereum's cryptographic primitives. Keccak-256 produces 256-bit hashes, and the secp256k1 elliptic curve operates on 256-bit scalars. By making the native word size 256 bits, the EVM handles hashes, cryptographic values, and large integers in single stack operations without requiring multi-word arithmetic libraries. This simplifies the implementation of core operations like address derivation, signature verification, and Merkle proof computation. The trade-off is that arithmetic on small values (uint8, uint16) still operates on full 256-bit words internally, with the Solidity compiler adding masking and shifting to enforce smaller type boundaries.


Question 17

A developer asks: "Why should I care about cold vs. warm storage access? I just want my contract to work." Explain, with specific gas costs, why understanding this distinction matters for real-world contract design.

Model Answer: Cold storage access (first read in a transaction) costs 2,100 gas. Warm access (subsequent reads of the same slot) costs only 100 gas — a 21x difference. For a function that reads the same storage variable multiple times, caching the value in a local variable after the first read saves 2,000 gas per additional read. In a function that reads 5 storage slots twice each, the difference between cold+warm (5 x 2,100 + 5 x 100 = 11,000) and all-cold (10 x 2,100 = 21,000) is 10,000 gas. For a high-volume contract processing thousands of transactions per day, this translates to significant ETH savings. Additionally, access lists (EIP-2930) allow prepaying cold costs at a discount, which can optimize gas for transactions that access many slots.


Question 18

Describe the two phases of smart contract bytecode (creation code and runtime code) and explain their relationship.

Model Answer: Creation code (constructor bytecode) is executed once during deployment. It runs the constructor logic (initializing state variables, setting owner addresses, etc.) and then copies the runtime code from its code segment into memory using CODECOPY, finally returning it via RETURN. The EVM takes the returned data and stores it as the contract's permanent code at the newly created address. Runtime code is what lives on-chain after deployment — it contains the function dispatcher, all function implementations, and the metadata hash. Think of creation code as an installer program whose output (the installed program) is the runtime code. After deployment, the creation code is never executed again; only the runtime code is invoked when the contract is called.