Open In App

Solidity – Assembly

Improve
Improve
Like Article
Like
Save
Share
Report

Assembly or Assembler language indicates a low-level programming language that can be converted to machine code by using assembler. Assembly language is tied to either physical or a virtual machine as their implementation is an instruction set, and these instructions tell the CPU to do that fundamental task like adding two numbers.

Solidity has an option to write an assembly language code inside the smart contract’s source code. With the help of Solidity assembly, we can directly interact with the EVM using the opcodes. Assembly provides more control over some logic which cannot be possible using only solidity, like pointing to the specific memory block. One of the main advantages is that it reduces the cost of the gas used to deploy the contract. Solidity has two ways to implement the assembly language: 

Inline Assembly: Inline assembly code can be written inside solidity code for more fine-grain control and especially used for enhancing the language via creating new libraries. Inline assembly can be inserted in between solidity statements in a way that EVM can understand. It can also be used when the optimizer is not able to produce efficient code. Solidity becomes easier when features like assembly local variables, functions calls, switch statements, if statements, loops, etc are used.
Syntax:

assembly{
     // assembly language statements
}

Example: In the below example, a contract with a function is created, where the inline assembly code is located inside the function.

Solidity




// SPDX-License-Identifier: GPL-3.0
pragma solidity >= 0.4.16 < 0.9.0;
/// @title A contract for demonstrate Inline Assembly
/// @author Jitendra Kumar
/// @notice For now, this contract just show the function execution using inline assembly
 
contract InlineAssembly {
 
    // Defining function
    function add(uint a) public view returns (uint b) {
 
        // Inline assembly code
        assembly {
 
            // Creating a new variable 'c'
            // Calculate the sum of 'a+16'
            // with the 'add' opcode
            // assign the value to the 'c'
            let c := add(a, 16)
 
            // Use 'mstore' opcode to
            // store 'c' in memory
            // at memory address 0x80
            mstore(0x80, c)
            {
 
                // Creating a new variable'
                // Calculate the sum of 'sload(c)+12'
                // means values in variable 'c'
               // with the 'add' opcode
               // assign the value to 'd'
                let d := add(sload(c), 12)
  
                 // assign the value of 'd' to 'b'
                b := d
  
            // 'd' is deallocated now
            }
     
            // Calculate the sum of 'b+c' with the 'add' opcode
            // assign the value to 'b'
            b := add(b, c)
 
        // 'c' is deallocated here
        }
    }
}


             

Output : 

Inline Assembly

Sometimes writing assembly code is more difficult because will not perform checks, that’s why it is better to use only when things are complex and you have an idea about what you are doing.

Standalone Assembly: Standalone assembly is planned for making an intermediate language for the solidity compiler. It was supported for recent compatibility but it is no more documented in the solidity documentation. Programs written in a standalone assembly are readable even if the code is been generated by a solidity compiler. The control flow should be easy, for optimization and formal verification.

Example: In the below example, the contract and a function are created to demonstrate the concept of Standalone assembly. 

Solidity




// SPDX-License-Identifier: GPL-3.0
pragma solidity >= 0.4.16 < 0.9.0;
/// @title A contract for demonstrate Standalone Assembly
/// @author Jitendra Kumar
/// @notice For now, this contract just show the flow of for loop
 
contract StandaloneAssembly {
 
  // Defining a function
  function add(uint a) public pure returns (uint b) {
 
    // Initializing the variable b
    b = 10;
 
    // Executing for loop till the condition is met
    for (uint n = 0; n < a; n++)
      b = b + a;
  }
}


    

The assembly level code for the above example is :  

mstore(0x40, 0x60) // this line will store the “free memory pointer” 
// dispatch function 
switch div(calldataload(0), exp(2, 226)) 
case 0xb3de649b { 
let (retData) = func(calldataload(4)) 
let retVal := $memAllocate(0x20) 
mstore(retVal, retData) 
return(retVal, 0x20) 

default { revert(0, 0) } 
// allocate memory 
function $memAllocate(size) -> pos { 
pos := mload(0x40) 
mstore(0x40, add(pos, size)) 

// function of the contract 
function addition(a) -> b { 
b := 10 
for { let n := 0 } lt(n, a) { n := add(n, 1) } { 
b := add(a, b) 


Output : 

Standalone Assembly



Last Updated : 02 Mar, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads