🌱
Dev Compendium
  • Ethereum
    • Solidity
      • EVM
      • Architecture
      • Execution Context
      • Transactions
      • Gas
      • Calldata, Memory & Storage
      • Gas Optimisation
      • Function Declarations
      • receive() & fallback()
      • CALL vs. DELEGATE CALL
    • Yul
      • Introduction
      • Types
      • Basic Operations
      • Storage
      • Memory
        • Arrays
        • Structs
        • Tuples, revert, keccak256
        • Logs and Events
        • Gotchas
        • abi.encode
      • Calldata
        • External Calls
        • Dynamic Length Inputs
        • Transferring Value
        • Receiving Contract Calls
      • Contracts in Yul
      • Other Yul Functions
    • Foundry
    • Security
      • Common Vulnerabilities
      • Best Practices
      • Development Workflow
      • Contract Migration
    • Auditing Tools
      • Slither
      • Mythril
      • Fuzzing
    • Upgradable Contracts
      • Upgrade Patterns
      • ERC-1967 Implementation
      • Deployment
    • MEV
    • Tooling
      • Chainlink
      • IPFS
      • Radicle
    • Frontend
      • Contract Hooks
      • Wallet Connection
        • wagmi.sh
        • Rainbow Kit
      • thirdweb
    • Protocol Research
      • Uniswap v2
      • Uniswap v3
      • Curve
      • GMX
  • Starkware
    • Fundamentals
    • Account Abstraction
    • Universal Deployer
    • Cairo 1.0
    • starknet.js
    • Security Model
  • Zero Knowledge
    • Group Theory
    • ECDSA
  • Rust
    • Basic Operations
    • Set up
    • Primitives
    • Control Flow
    • Mutability & Shadowing
    • Adding Behavior
    • Lifetimes
    • Std Library
  • SUI
    • Architecture
    • Consensus Mechanism
    • Local Node Setup
    • Sui Client CLI
    • Move Contracts
      • Move
      • Move.toml
      • Move.lock
      • Accessing Time in Sui Move
      • Set up Development Framework
      • Debug & Publish
      • Package Upgrades
      • Sui Move Library
      • Difference from Core Move
    • Object Programming
      • Object Basics
      • Using Objects
      • Immutable Objects
      • Object Wrapping
      • Dynamic Fields
      • Collections
      • Unit Testing
      • Deployment with CLI
  • NEAR
    • Architecture
    • Contract Standards
      • Fungible Token (NEP-141)
      • Non-Fungible Token (NEP-171)
      • Storage Management (NEP-145)
      • Events (NEP-297)
      • Meta-Transactions
    • Rust Contracts
      • Development Workflow
      • Smart Contract Layout
      • Storage Management
      • Events & Meta-transactions
      • Method Types
      • Upgrading Contracts
      • Unit Testing
    • NEAR Libraries
    • Environment Variables
    • Serialisation
    • Security Concepts
    • Collections
    • JS SDK
Powered by GitBook
On this page
  1. Ethereum
  2. Yul

Types

  • Yul has only one type - the 32-bit word, or the 256 bits that we’re used to seeing in Solidity.

// Usual Solidity representation

    function getNumberSol() external pure returns (uint256) {
        return 42;
    }

// Yul representation 

    function getNumberYul() external pure returns (uint256) {
        uint256 x;

        assembly {
            x := 42
        }
        return x;
    }
  • Yul can also take in hex values, but will output them as decimals, since we are casting them as uint256

function getHex() external pure returns (uint256) {
        uint256 x;

        assembly {
            x := 0xa
        }

        return x; // returns decimal 10 
    }
  • Strings are not naturally a bytes32, so we cannot assign values to a string in memory in Yul.

  • Calling this function will return an out of gas error, since you’re essentially trying to assign “hello world” to the pointer storing the location of the string in memory

// wrong example
 
function getString() external pure returns (string memory) {
        string memory myString;

        assembly {
            myString := "hello world"
        }

        return myString;
    }
  • We have to change the string’s data type to bytes32, in order for it to be stored in the stack so that Yul can access it. (bytes32 is always stored on the stack)

  • To make the output a readable string, we have to cast it using: string(abi.encode(myString))

function demoString() external pure returns (string memory) {
        bytes32 myString = "";

        assembly {
            myString := "hello world"
        }
				
        return string(abi.encode(myString));
				// return myString; -> will return a bytes32 representation of hello world 
				// 0x68656c6c6f20776f726c64000000000000000000000000000000000000000000 
    }
  • The max size of the string you can assign to a variable in Yul is 32 bytes, anything larger will return a compiler error

  • 32 bytes is the only type in Yul, and Solidity will just enforce an interpretation based on the value type its being assigned to.

// the following returns true, 
// since a boolean in solidity is essentially 32 bytes where the last bit is 1 
// Example: often seen in calldata 
function representation() external pure returns (bool) {
        bool x;

        assembly {
            x := 1
        }

        return x;
    }
  • If we change the variable to an address, it will return 0x0....001 = address(1)

PreviousIntroductionNextBasic Operations

Last updated 1 year ago