Solidity assembly is a low-level programming language that is used in the Ethereum Virtual Machine (EVM). It is a set of instructions that can be used to interact directly with the EVM, which is responsible for executing smart contracts on the Ethereum blockchain. Assembly language provides a way to write more optimized and efficient code by directly accessing and manipulating the EVM's memory and registers.
Why use Solidity Assembly ?
While Solidity is a high-level programming language, it has certain limitations when it comes to efficiency and control over the EVM's execution. Solidity assembly allows you to bypass these limitations and write code that can be executed directly on the EVM. This can be particularly useful in situations where you need to optimize gas usage, perform low-level operations, or access specific parts of the EVM that are not accessible through Solidity.
Solidity assembly also provides a way to write more complex logic that cannot be easily expressed in Solidity. For example, you can use assembly to perform bitwise operations, which are not natively supported in Solidity. Additionally, assembly provides a way to implement cryptographic algorithms and perform other complex calculations that require low-level access to the EVM.
EVM (Ethereum Virtual Machine)
The EVM is a stack machine.A stack is a collection of elements or items, and two main operations can be performed on it: push and pop. Pushing an item onto the stack adds it to the top, and popping an item from the stack removes the top item. The stack is typically visualized as a vertical structure, with the top of the stack at the top of the visualization and the bottom of the stack at the bottom.
A stack machine is a type of computer architecture that uses a stack data structure to manage its memory,computation and also store all operands.In assembly language,an operand is a value (an argument) on which the instruction,named by mnemonics operates.
In order to be useful the state machine have to implement some basic functionality like ADD,MUL... Without forgetting instructions usually pop one or more values from the stack to do some computation and push the result .This process is AKA Reverse Polish Notation.
Reverse Polish Notation (RPN), AKA postfix notation, is a mathematical notation where operators come after the operands. In RPN, an expression is evaluated by scanning it from left to right, and pushing operands onto a stack. When an operator is encountered, it is applied to the top two operands on the stack, and the result is pushed back onto the stack.
For example, the infix expression "3 + 4" can be written in RPN as "3 4 +". Here, the operands 3 and 4 are pushed onto the stack, and the operator "+" is applied to them. The result, 7, is pushed back onto the stack.
3 + 4 // Standard notation.
3 4 + // Reverse polish notation.
Different Types of Assembly in Solidity
1- Inline Assembly : Inside the solidity source code.
2- Standalone Assembly : Can use without the solidity.
//Inline Assembly
assembly {
let x:= x
}
How to Use Solidity Assembly ?
Solidity assembly is written using the assembly keyword and is enclosed in curly braces. Inside the braces, you can write a series of assembly instructions that will be executed directly on the EVM. Assembly instructions are written in a specific syntax that is similar to other assembly languages. Here is an example of Solidity assembly that add two values to memory location 0x0 and returns it after:
function add(uint x,uint y) external pure returns(uint) {
assembly {
/*This line is calling the add operation provided by the
assembly language to add x and y, and storing the result
in a variable res.*/
let res := add(x,y)
/*This line is using the mstore operation to store the
value of res at memory location 0x0. mstore takes two
arguments: the memory location to store the data and the
data to store.*/
mstore(0x0,res)
/*This line is returning the result of the addition as a
32-byte value starting at memory location 0x0. The return
statement takes two arguments: the memory location of the
data to return and the size of the data to return.*/
return (0x0,32)
}
}
Variables declarations and Assignments
1- Stack Variables: In assembly language, variables can be declared as stack variables using the mstore operation. Stack variables are used to store values on the stack and are local to the current execution context.
assembly {
mstore(0x0, 5) // Declare stack variable and assign value 5
}
2- Memory Variables: Memory variables are used to store data in memory and are declared using the mload operation. Memory variables can be global or local to a function.
assembly {
let myVariable := mload(0x40) // Declare memory variable
mstore(myVariable, 5) // Assign value 5 to memory variable
}
3- Storage Variables: Storage variables are used to store data in storage and are declared using the sload operation. Storage variables can be global or local to a function.
assembly {
let myVariable := sload(0x0) // Declare storage variable
sstore(0x0, 5) // Assign value 5 to storage variable
}
We use the let keyword.You can then assign it value with the := operator.When declaring a new local variable with let, Solidity will automatically allocate a new memory slot for the variable and initialize it with the default value (which is zero for all types except bool, which is false). The variable's type is determined by the type of the assigned value.Variables declared in let are not visible outside the assembly block.
It's important to note that using assembly language for variable declaration and assignment can be more complex than using Solidity's built-in syntax. Additionally, assembly language can be more difficult to read and write, and can introduce security risks if not used correctly. It is recommended to use assembly language only when necessary and with caution.
Follow me on Twitter !! https://twitter.com/web3_ruud
Iām on @buymeacoffee. If you like my work, you can buy me a and share your thoughts šā https://www.buymeacoffee.com/officialsa4
Top comments (0)