Blockchain

Solidity Yul Assembly – Beginner’s Guide

Solidity is the most widely used programming language in the blockchain space. It is a powerful alternative for smart contract scripting and provides a user-friendly development experience. If you want to learn Solidity Yul Assembly, you need to know more deeply about the features of Solidity. By exploring the details of Solidity, you can unlock the true potential of the Ethereum Virtual Machine, or EVM. Assembly is one of the important elements in working with Solidity.

It is a low-level language that helps developers explore the inner working mechanisms of the Ethereum Virtual Machine or EVM in detail. Assembly helps optimize smart contracts to achieve better performance and efficiency. It acts as an add-on to optimize every line of code and get the best results from your smart contracts. Let’s learn more about Solidity Yul Assembly in the following discussion.

Learn the process of creating and deploying smart contracts on the Ethereum blockchain with the Solidity Fundamentals Course.

EVM and Opcode Operations

Before writing assembly code, you need to learn how the EVM works. Exploring the working mechanisms of EVM and opcodes will help you understand Solidity Yul Assembly Guide more clearly. The Ethereum Virtual Machine (EVM) is one of the core components of the Ethereum blockchain. It serves as a general-purpose decentralized computer for smart contract execution while ensuring reliability and consistency across the network. What are the EVM working procedures?

When you compile a contract, you will receive bytecode. Bytecode is a long collection of bytes and serves to represent a small set of instructions. Each instruction contains one byte, which is called an opcode. What is the relationship between Solidity inline assembly and opcodes? Opcodes help perform various tasks such as memory manipulation, storage access, arithmetic calculations, and control flow management.

Do you want to learn basic and advanced concepts of Ethereum? Enroll in the Ethereum Development Fundamentals Course now

What is a Solidity assembly?

The next important aspect to learn to explore Solidity inline assembly examples is the definition of an assembly. Assembly, or ‘inline assembly’, is a low-level language that enables low-level access to the Ethereum virtual machine. You can think of this as a special pass into the basic operating mechanisms of the Ethereum Virtual Machine. Assembly can help you write code to bypass certain safety features and critical checks in Solidity. As a result, developers have more control over their smart contracts.

You can find a better answer to “What is Solidity Yul Assembly?” Identifies the language used to create assemblies in Solidity. The importance of Yul in assembly writing in Solidity substantiates the use of ‘Yul’ as an essential term to describe inline assembly. Yul is an intermediate language and provides the flexibility to compile your code into bytecode for the Ethereum Virtual Machine. When writing code in Solidity, you can always use the ‘assemble ‘ keyword to start writing an inline assembly.

When you insert assembly blocks into your Solidity code, you will find many different levels of control. Solidity comes first and provides a high-level approach to smart contract writing. On the other hand, you may want more control using Yul or assembly language. Yul helps you manipulate the EVM at a more granular level, which can give you the flexibility to fine-tune your code and improve efficiency. If you want to be a bit more adventurous, you can write your own bytecode for the EVM. It doesn’t require a compiler and is similar to gaining full control over the EVM.

Build your identity as a certified blockchain professional with 101 Blockchains’ blockchain certification, designed to provide enhanced career prospects.

How can I write an inline assembly in Solidity?

The next important highlight in learning inline assembly in Solidity using the Yul programming language is the example code. You can use the Solidity inline assembly example for a simple contract called ‘Box’. Contracts help you store, modify, and retrieve values. Below is example code for a Box contract.

pragma solidity ^0.8.14;

contract Box 
    uint256 private _value;

    event NewValue(uint256 newValue);

    function store(uint256 newValue) public 
        _value = newValue;
        emit NewValue(newValue);
    

    function retrieve() public view returns (uint256) 
        return _value;
    

You can now convert the example Solidity code to an inline assembly to see the functionality of calling Solidity assemblies. You can start working with the search function from the first steps. For example, in the original Solidity code, the search function reads the value stored in the ‘_value’ parameter from the contract storage and returns the result.

For assembly, you can achieve similar results by using the ‘sload’ opcode to read the value. The ‘sload’ opcode receives one input, the key of the storage slot, and the ‘_value’ variable is stored in slot #0. In assembly language, you could write the following example:

assembly 
    let v := sload(0) // Read from slot #0

Once you get a value, you need to do something to return that value. For Solidity inline assembly, you can use the ‘return’ opcode to perform functions. The ‘return’ opcode takes two separate inputs: ‘offset’ and ‘size’. The ‘offset’ input indicates where the value starts in memory and the ‘size’ indicates how many bytes should be returned.

On the other hand, ‘sload’ returns the ‘v’ value, which is stored in the call stack rather than memory. Therefore, the value must be moved into memory before retrieving it. Opcode ‘mstore’ can help us store a value in memory by taking two inputs like ‘offset’ and ‘value’. The ‘offset’ parameter indicates the location in the memory array where the value should be stored, and ‘value’ indicates the number of bytes or ‘v’.

The final assembly code for the Solidity inline assembly example is as follows:

assembly 
    let v := sload(0) // Read from slot #0
    mstore(0x80, v) // Store v at position 0x80 in memory
    return(0x80, 32) // Return 32 bytes (uint256)

In particular, you should note a special highlight in the assembly code that selects location 0x80 in memory to store the value. why? Reviewing the Solidity Yul Assembly guide will also help you learn the answer. Solidity blocks the first four 32-byte slots for certain applications. So free memory starts from 0x80. In the simple example described in this discussion, we can use 0x80 to store the new variable. On the other hand, complex tasks require pointer tracking and effective management of free memory.

function retrieve() public view returns (uint256) 
    assembly 
        let v := sload(0)
        mstore(0x80, v)
        return(0x80, 32)
    

Certified Enterprise Blockchain Professional Certification

How do I use the Store function in the given example?

‘What is Solidity Rule Assembly?’ Answer Summary You will also pay attention to the ‘Save’ function. It helps to store variables using the ‘sstore’ opcode which takes two inputs. One of the inputs is ‘key’, which is a 32-byte key in storage, and ‘value’ is the value that needs to be stored. In assembly language, you can write a function like the following example:

assembly 
 sstore(0, newValue) // store value at slot 0 of storage

After saving the value, we can utilize the ‘log1’ opcode to start the event sending process. The ‘log1’ opcode requires three different inputs: ‘offset’, ‘topic’ and ‘size’. The ‘offset’ input indicates the byte offset in memory where the event data should be stored. The ‘Size’ input indicates the size in bytes of data that needs to be copied.

The ‘topic’ input represents a 32-byte value that acts as an identifier or label for the event. Candidates who want to learn Solidity Yul Assembly working knowledge should know that the ‘log1’ opcode requires three inputs to be set to different values. Since we used the ‘mstore’ opcode to store the value, we need to set ‘offset’ to 0x80.

The ‘size’ input of the opcode can be specified as 0x20, which serves to represent 32 bytes. Finally, you need to set the ‘topic’ parameter with an event label, such as the name ‘NewValue’. The argument passed to ‘subject’ is just a hash of the event signature. With these updates, the ‘Save’ feature will look like this:

function store(uint256 newValue) public 
 assembly 
  // store value at slot 0 of storage
  sstore(0, newValue)

  // emit event
  mstore(0x80, newValue)
  log1(0x80, 0x20, 0xac3e966f295f2d5312f973dc6d42f30a6dc1c1f76ab8ee91cc8ca5dad1fa60fd)
 

Finally, the ‘Box’ contract looks like this:

pragma solidity ^0.8.14;

contract Box 
    uint256 public value;

    function retrieve() public view returns(uint256) 
        assembly 
            let v := sload(0) 
            mstore(0x80, v)
            return(0x80, 32) 
        
    

    function store(uint256 newValue) public 
        assembly 
            sstore(0, newValue)
            mstore(0x80, newValue)
            log1(0x80, 0x20, 0xac3e966f295f2d5312f973dc6d42f30a6dc1c1f76ab8ee91cc8ca5dad1fa60fd)
        
    

Certified web3 expert certification

How can I send Ether to an address using Solidity Yul Assembly?

The power and efficiency of Solidity assembly calls also allows us to design another contract to send Ether to a specific address. Below is an example of a contract that can help achieve the same functionality.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.14;

contract MyContract 

    address public owner = payable(0x5B38Da6a701c568545dCfcB03FcB875f56beddC4);

    function sendETH(uint256 _amount) public payable 
        require(msg.value >= _amount,"Not Enough ETH Sent");
        bool success;
        assembly 
            let o := sload(0)
            success := call(gas(), o, _amount, 0, 0, 0, 0)
        
        require(success, "Failed to send ETH");
    

Below is a breakdown of the assembly code for the individual steps:

First, the owner’s address is stored in slot 0, and the owner’s address is assigned to the local variable ‘o’. Also, the ‘sload’ opcode helps in reading values ​​from storage. In the following line of the Solidity inline assembly example, you can see the execution of the ‘call’ opcode: This helps to send Ether to a specific address and the ‘call’ opcode in assembly language takes different arguments.

The ‘gas()’ function works to return the remaining gas for the existing execution context. It can be passed as the first argument to the call, indicating the maximum amount of gas to be provided for the function call.

The ‘call’ opcode also takes an ‘address’ argument, which indicates the address of the contract or user that should be called. Has a value located in slot 0 storage.

The ‘value’ argument represents the amount of Ether that should be sent via the function call. For this example, you must pass the ‘value’ argument as the second argument for the call.

You can understand Solidity inline assembly functionality by pointing to the following four arguments: 0, 0, 0, 0. Arguments help you pass additional data to the function you want to call. In the example code, you can see that it is set to 0 so that no additional data is passed.

The result of the calling opcode can be assigned to the ‘success’ local variable. true if the function call succeeds; false otherwise.

Want to build your Ethereum development skills by leveraging the ethers.js library? Enroll in the Ethers.Js Blockchain Developer Course now

What are the limitations of Solidity assembly language?

The details in the Solidity Yul Assembly guide may help you understand that the low-level language has certain limitations. First of all, it is difficult to understand, and beginners may not immediately understand the logic and flow of the code. This can be an intimidating concept for people unfamiliar with low-level programming. However, it is important to note that these limitations do not affect the value advantage of assemblies in Solidity. Assembly code can help improve Solidity’s competitive advantage and gas efficiency.

Start your journey to becoming a smart contract developer or designer with the Smart Contract Technology Path.

conclusion

Applications of the Yul programming language for generating inline assembly code in Solidity help optimize smart contracts. The main goal of Solidity inline assembly is to coordinate smart contracts to precisely achieve the desired goals of the smart contract. Assembly code is scripted in a low-level language, which can make it look unattractive and difficult.

On the other hand, it can offer a comprehensive range of benefits to help you achieve better cost savings and gas efficiency. Developers must consider all the pros and cons and evaluate whether the complexity of assembly code is a good price to pay for the potential benefits in their particular use case.

Build your career with 101 blockchain learning programs

Related Articles

Back to top button