EVM OPCODES
Master the Machine: A Developerās Guide to 20 Essential EVM Opcodes Powering Smart Contract Logic and Gas Efficiency.

You click āConfirmā on MetaMask, and behind the scenes, your transaction turns into raw bytecode.
That bytecode gets broken down into tiny instructions.
The Ethereum Virtual Machine executes these bytecodes one instruction at a time.
These instructions are called opcodes, and as a developer, you do not write opcodes directly when you write Solidity. You write high-level code, the compiler turns it into bytecode, and that bytecode runs one opcode at a time in the EVM.
So if Solidity is the language you speak, opcodes are the machineās actual thoughts.
Understanding them makes debugging, gas reasoning, low-level calls, inline assembly, proxies, calldata decoding, and contract creation much easier.
I will group 20 useful opcodes into practical categories, and for each one, I will explain what it does, why it matters, and how to think about it as a smart contract developer.
But first, what actually happens when a user calls a contract? Transactions enter the EVM. The first thing the EVM does is figure out who sent this transaction (caller), how much ETH they sent (callvalue) and what data they passed (calldatasize) and (calldataload).
CALLER (0x33) returns
msg.sender, meaning the direct caller of the current execution context. This is the opcode behind most access control decisions. In simple calls, it matches your intuition, but it becomes even more important in delegatecall patterns. ļæ¼CALLVALUE (0x34) returns
msg.value, the amount of ETH sent with the call. This is how payable logic sees incoming ETH at the machine level. If nothing is sent, it will be zero. ļæ¼Then it asks, what do they want?
CALLDATALOAD (0x35) reads
32 bytesfrom calldata at a given offset. This is one of the key opcodes behind ABI decoding. Function selectors, arguments, and packed call inputs all eventually get read through calldata instructions like this.CALLDATASIZE (0x36) returns the total length of calldata. This is important when you need to validate input size, parse dynamic arguments, or write low-level dispatch logic.
CALLDATACOPY (0x37) copies a portion of the calldata to memory. While CALLDATALOAD grabs single chunks, this is the heavy lifter for handling large arrays or strings that need to be staged in memory for further processing. Then it asks, "Where is the logic?"
CODESIZE (0x38) returns the size of the code currently executing. In the context of the current contract, this tells the EVM how many bytes of bytecode are available. It is often used in assembly-heavy deployment scripts or to verify that a contract has been properly initialised. Then it asks, " Can I see it?"
CODECOPY (0x39) copies the bytecode of the currently running contract into memory. This is foundational for "proxy" patterns or off-chain verification, where the contract needs to introspect its own logic or pass its bytecode to another operation. Then it asks, " What is the cost of entry?"
GASPRICE (0x3a) returns the price of gas in the current transaction. This allows a contract to know exactly how much the user is paying per unit of gas, which is vital for gas-reimbursement schemes or MEV-resistant logic. Then it asks, " Who else is out there?"
EXTCODESIZE (0x3b) returns the size of the code at a given external address. This is a classic way to check if an address is a contract or an EOA; if the size is greater than zero, there is code sitting at that location. Then it asks, "What are they doing?"
EXTCODECOPY (0x3c) copies the code of an external contract into memory. This allows a contract to pull in the logic of another address for analysis or to perform security checks on a target's bytecode before interacting. Then it asks, "What did they say back?"
RETURNDATASIZE (0x3d) returns the size of the data returned by the last external call. In the modern EVM, this is the first thing checked after a call to determine if the recipient sent back an error message or a return value. Then it asks, " Can I read that?"
RETURNDATACOPY (0x3e) copies the data from the last external callās return buffer into memory. Just like its calldata counterpart, this brings external data into the local workspace so the contract can decode it. Then it asks, " Is this the code I expect?"
EXTCODEHASH (0x3f) returns the Keccak-256 hash of a contract's code at a specific address. This is much cheaper than copying the code if you only need to verify that a contract is a specific, "trusted" implementation. Then it asks, " What is the history?"
BLOCKHASH (0x40) returns the hash of one of the 256 most recent complete blocks. While often used for "randomness," it is predictable by miners, yet remains a staple for simple on-chain games and historical verification. Then it asks, " Who is the builder?"
COINBASE (0x41) returns the address of the miner (or validator) who produced the current block. This is the destination for priority fees and is frequently used in flashbot-style direct payments to the block builder. Then it asks, "What time is it?"
TIMESTAMP (0x42) returns the current blockās arrival time in Unix seconds. This is the heartbeat of DeFi, powering everything from vesting schedules and interest rate accruals to exchange deadline checks. Then it asks, "How far along are we?"
NUMBER (0x43) returns the current block number. This is the primary way contracts track the passage of "on-chain time," serving as a reliable counter for governance voting periods and reward distributions. Then it asks, " Is it random?"
PREVRANDAO (0x44) returns the random output provided by the beacon chain. Since the Merge, this opcode provides a much more robust source of randomness than the old block difficulty, though it still has specific constraints. Then it asks, "What is the ceiling?"
GASLIMIT (0x45) returns the maximum amount of gas that the current block can consume. This provides a ceiling for the entire network's throughput, allowing contracts to adjust their behaviour based on the current capacity of the chain. Then it asks, 'How much is left?"
GAS (0x5a) returns the amount of available gas remaining in the current execution context. This is the ultimate constraint of the EVM, used by contracts to prevent out-of-gas errors during sub-calls or to ensure there is enough fuel left to finish critical cleanup logic before the transaction hits the limit.
Click to read more about EVM OP codes





