In this chapter, “Learn EVM Opcode in Yul Assembly With Solidity Best Guide,” If you’re diving into the world of Ethereum development, learning EVM (Ethereum Virtual Machine) opcodes is like unlocking the source code of the Ethereum ecosystem. We’ll explore the core concepts, their importance, and how to use them efficiently with Solidity and Yul. This guide is written for beginners with a human-friendly, casual tone, ensuring you’re not only learning but also enjoying the process.
Table of Contents
Learn EVM Opcodes in Yul Assembly With Solidity
What is the EVM?
The Ethereum Virtual Machine (EVM) is the decentralized brain behind Ethereum. It processes and executes smart contracts. Every operation within the EVM is executed using opcodes, which are low-level machine instructions.
Think of opcodes as the building blocks of the EVM. They represent simple operations like adding numbers, storing data, or jumping to another part of the code.
Why Should You Learn EVM Opcodes?
- Optimize Gas Usage: Knowing opcodes allows you to write more gas-efficient smart contracts.
- Debugging Mastery: It helps you debug at the bytecode level when something goes wrong in a deployed contract.
- Deeper Understanding: Learning opcodes bridges the gap between high-level Solidity and the machine-level operations of the EVM.
- Security Awareness: A solid understanding of opcodes enhances your ability to write secure contracts.
What Are Opcodes in Solidity?
Opcodes are single instructions that the EVM understands. While writing smart contracts in Solidity, you’re using a high-level language. However, the compiler converts your Solidity code into EVM bytecode, a sequence of opcodes.
Here’s an example:
- Solidity Code:
uint x = 2 + 3;
- Compiled Opcodes:
PUSH1 02 PUSH1 03 ADD
The Basics of Yul and Its Relation to EVM Opcodes
Yul is an intermediate language designed to write highly optimized EVM bytecode. It acts as a bridge between Solidity and raw bytecode, making it easier to manage low-level details.
Why Use Yul?
- Gas Optimization: You can write leaner code.
- Direct Control: Provides better control over memory and execution flow.
- Debugging: Allows a deeper dive into contract behavior.
Example:
{
let x := add(2, 3) // Adds two numbers
sstore(0x0, x) // Stores the result in storage slot 0x0
}
The corresponding opcodes would look like: PUSH1 02 PUSH1 03 ADD SSTORE
How to Learn EVM Opcodes Using Solidity and Yul
1. Understand the EVM Memory Layout
The EVM uses three main data locations:
- Stack: Temporary memory for calculations (max 1024 slots).
- Memory: Volatile data storage during execution.
- Storage: Persistent, expensive data storage.
2. Common Opcodes and Their Use
Here are some essential opcodes for beginners:
Opcode | Description | Gas Cost |
---|---|---|
ADD | Adds two values on the stack | 3 gas |
MUL | Multiplies two values | 5 gas |
PUSH1 | Pushes 1-byte value to stack | 3 gas |
SSTORE | Stores data in storage | 20,000 gas |
JUMP | Jumps to a specific bytecode | 8 gas |
Writing Your First Yul Code
Let’s write a simple Yul program that performs addition and stores the result.
Example:
{
let a := 5
let b := 7
let sum := add(a, b)
sstore(0x01, sum)
}
Explanation:
let a := 5
initializes a variablea
with value 5.add(a, b)
adds the two variables.sstore(0x01, sum)
stores the result in storage slot0x01
.
Gas Optimization Tips Using Opcodes
- Minimize Storage Operations: Storage operations like
SSTORE
are expensive. Cache frequently used values in memory or stack instead. - Use Assembly Sparingly: Yul and assembly give you more control, but improper use can make your contract error-prone.
- Avoid Dynamic Loops: Loops can become costly if they depend on dynamic input.
EVM Opcode Reference for Beginners
Here’s a cheat sheet for some common EVM opcodes:
Opcode | Operation | Description |
---|---|---|
STOP | Halts execution | Ends execution gracefully. |
PUSH32 | Push 32 bytes to stack | Useful for constants. |
CALL | External function call | Calls another contract or function. |
LOG0-4 | Logging events | Emits events with 0-4 topics. |
RETURN | Returns output data | Ends execution and returns data. |
EVM Bytecode and Its Relation to Yul
How Solidity Converts to Bytecode
When you compile Solidity code, it’s converted into bytecode, which the EVM executes. Yul lets you bypass Solidity and write directly in an intermediate form for optimized bytecode generation.
For example:
- Solidity:
uint x = 10;
- Yul:
{
let x := 10
}
- Opcodes:
PUSH1 0A
Complete EVM Opcode List with Gas Consumption
Understanding the complete list of EVM opcodes and their gas consumption is crucial for writing efficient and optimized smart contracts. Below, we’ve included a detailed table that lists all the EVM opcodes, their descriptions, and corresponding gas costs. Bookmark this section as your go-to reference!
Arithmetic and Logic Opcodes
Opcode | Gas Cost | Description |
---|---|---|
STOP | 0 | Halts execution. |
ADD | 3 | Adds two values. |
MUL | 5 | Multiplies two values. |
SUB | 3 | Subtracts the second value from the first. |
DIV | 5 | Divides the first value by the second. |
SDIV | 5 | Divides two signed integers. |
MOD | 5 | Returns the remainder of division. |
SMOD | 5 | Signed integer modulo operation. |
ADDMOD | 8 | Modular addition. |
MULMOD | 8 | Modular multiplication. |
EXP | 10 + 50 per byte | Exponentiation. |
SIGNEXTEND | 5 | Extends a signed number to a larger byte size. |
Comparison and Bitwise Opcodes
Opcode | Gas Cost | Description |
---|---|---|
LT | 3 | Less-than comparison. |
GT | 3 | Greater-than comparison. |
SLT | 3 | Signed less-than comparison. |
SGT | 3 | Signed greater-than comparison. |
EQ | 3 | Checks equality. |
ISZERO | 3 | Checks if the value is zero. |
AND | 3 | Bitwise AND operation. |
OR | 3 | Bitwise OR operation. |
XOR | 3 | Bitwise XOR operation. |
NOT | 3 | Bitwise NOT operation. |
BYTE | 3 | Retrieves a byte from a 256-bit word. |
Environmental Opcodes
Opcode | Gas Cost | Description |
---|---|---|
SHA3 | 30 + 6 per word | Computes the Keccak-256 hash. |
ADDRESS | 2 | Gets the address of the current contract. |
BALANCE | 400 | Retrieves the balance of an account. |
ORIGIN | 2 | Gets the original sender of the transaction. |
CALLER | 2 | Retrieves the sender of the current call. |
CALLVALUE | 2 | Gets the value (in Wei) sent with the call. |
CALLDATALOAD | 3 | Loads input data to the stack. |
CALLDATASIZE | 2 | Returns the size of the call data. |
CALLDATACOPY | 3 + 3 per word | Copies call data to memory. |
CODESIZE | 2 | Returns the size of the contract’s code. |
CODECOPY | 3 + 3 per word | Copies contract code to memory. |
GASPRICE | 2 | Gets the current gas price. |
EXTCODESIZE | 700 | Returns the size of an external contract’s code. |
EXTCODECOPY | 700 + 3 per word | Copies external contract code. |
RETURNDATASIZE | 2 | Size of returned data from the last external call. |
RETURNDATACOPY | 3 + 3 per word | Copies returned data to memory. |
Block Information Opcodes
Opcode | Gas Cost | Description |
---|---|---|
BLOCKHASH | 20 | Gets the hash of a specific block. |
COINBASE | 2 | Retrieves the current block’s miner address. |
TIMESTAMP | 2 | Gets the current block’s timestamp. |
NUMBER | 2 | Retrieves the current block number. |
DIFFICULTY | 2 | Gets the current block’s difficulty. |
GASLIMIT | 2 | Returns the block’s gas limit. |
Stack, Memory, and Storage Opcodes
Opcode | Gas Cost | Description |
---|---|---|
POP | 2 | Removes the top value from the stack. |
MLOAD | 3 | Loads a word from memory. |
MSTORE | 3 | Stores a word in memory. |
MSTORE8 | 3 | Stores a byte in memory. |
SLOAD | 100 | Loads a word from storage. |
SSTORE | 20,000 or 5,000 | Stores a word in storage. |
MSIZE | 2 | Gets the size of active memory. |
Control Flow Opcodes
Opcode | Gas Cost | Description |
---|---|---|
JUMP | 8 | Jumps to a specified bytecode location. |
JUMPI | 10 | Conditional jump to a specified location. |
PC | 2 | Returns the current program counter. |
JUMPDEST | 1 | Marks a valid jump destination. |
Logging Opcodes
Opcode | Gas Cost | Description |
---|---|---|
LOG0 | 375 + 8 per byte | Logs an event with no topics. |
LOG1 | 375 + 8 per byte | Logs an event with one topic. |
LOG2 | 375 + 8 per byte | Logs an event with two topics. |
LOG3 | 375 + 8 per byte | Logs an event with three topics. |
LOG4 | 375 + 8 per byte | Logs an event with four topics. |
System Opcodes
Opcode | Gas Cost | Description |
---|---|---|
CREATE | 32,000 | Creates a new contract. |
CALL | 700 + dynamic | Calls an external function. |
CALLCODE | 700 + dynamic | Executes code in another contract’s context. |
DELEGATECALL | 700 + dynamic | Executes code in the caller’s context. |
STATICCALL | 700 + dynamic | Executes a static call to another contract. |
RETURN | 0 | Returns data from a function call. |
REVERT | 0 | Reverts state changes and optionally returns data. |
SELFDESTRUCT | Refunds gas | Destroys the contract and sends funds to an address. |
Additional Tips
- Understand Gas Implications: Each opcode has a specific gas cost, which affects the execution cost of your smart contract.
- Combine Opcodes Efficiently: For example, avoid using multiple arithmetic operations in sequence when you can calculate the result in one step.
- Practice with Yul: Use Yul assembly to optimize your opcode usage.
By mastering this complete list of EVM opcodes, you’ll gain deep insights into Ethereum development. Use this reference while coding to create gas-efficient, secure, and optimized smart contracts!
FAQs :
What is the opcode in EVM?
Opcodes are the fundamental instructions the EVM understands. They perform operations like addition, storage, and control flow.
What are opcodes in Solidity?
When you write Solidity code, the compiler converts it into EVM opcodes, which are low-level machine instructions.
How can I learn EVM opcodes for free?
1. Explore resources like GitHub, Reddit communities, and free tutorials.
2. Study Solidity’s compiled bytecode using tools like Remix and Hardhat.
What is the gas cost of an opcode?
Each opcode has a predefined gas cost. For instance, ADD
costs 3 gas, while SSTORE
costs 20,000 gas.
What’s the relation between Yul and EVM bytecode?
Yul serves as a bridge, allowing developers to write optimized code that compiles directly to bytecode.
Conclusion
Learning EVM opcodes in Solidity and Yul assembly opens up a new dimension of Ethereum development. It’s not just about writing smart contracts; it’s about understanding how they work at the lowest level, optimizing for gas, and ensuring security.
Dive deep, experiment with Yul, and make use of tools like Remix, Etherscan, and opcode reference guides to master this skill. The journey might seem challenging at first, but with practice, you’ll unlock the true potential of blockchain programming.
Happy coding! 🚀