🌱
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
  3. Memory

Tuples, revert, keccak256

  • memory allows us to deal with data types that are larger than 32 bytes

  • if we want to return a struct or an array within one function, this would not be possible with a single variable, if that struct/array is larger than 32 bytes

  • we can do this in Yul by simply denoting the boundaries/area of memory whose values we wish to return (this is what Solidity does under the hood)

function return2and4() external pure returns (uint256, uint256) {
        assembly {
            mstore(0x00, 2)
            mstore(0x20, 4)
            return(0x00, 0x40) // beginning and end location in memory of items we want to return 
        }
    }
  • when we want to revert a statement, we also have to specify an area in memory to store the revert values, just like return

  • Solidity obscures the fact that in a revert case, data can still be sent so caller can debug it

  • Most of the time, we want to revert just so that execution stops, and not return a value. we can do this with: revert(0, 0)

  • values in abi.encode are stored in memory in solidity:

// Solidity example 

function hashV1() external pure returns (bytes32) {
        bytes memory toBeHashed = abi.encode(1, 2, 3);
        return keccak256(toBeHashed);
    }

// Yul equivalent version

function hashV2() external pure returns (bytes32) {
        assembly {
            let freeMemoryPointer := mload(0x40)

            // store 1, 2, 3 in memory
            mstore(freeMemoryPointer, 1)
            mstore(add(freeMemoryPointer, 0x20), 2)
            mstore(add(freeMemoryPointer, 0x40), 3)

            // update memory pointer to account for 3 32-byte variables 
            mstore(0x40, add(freeMemoryPointer, 0x60)) // increase memory pointer by 96 bytes

            mstore(0x00, keccak256(freeMemoryPointer, 0x60))
            return(0x00, 0x60)
        }
    }
  • in Yul, keccak256 takes in the start location in memory of the variables to be hashed, and how many bytes of data (0x60 in this case)

PreviousStructsNextLogs and Events

Last updated 1 year ago