{"id":24054315,"url":"https://github.com/adnpark/solidity-cheatsheet","last_synced_at":"2025-10-26T14:37:22.042Z","repository":{"id":270145594,"uuid":"908899356","full_name":"adnpark/solidity-cheatsheet","owner":"adnpark","description":"master cheatsheet for solidity developers","archived":false,"fork":false,"pushed_at":"2025-01-28T07:01:17.000Z","size":1496,"stargazers_count":10,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-29T17:51:11.277Z","etag":null,"topics":["cheatsheet","contract-solidity","ethereum","resources","solidity","solidity-cheatsheet","solidity-codes","solidity-compiler","solidity-contract","solidity-contracts","solidity-coverage","solidity-dapps","solidity-language","solidity-security","web3","web3-dapp","web3-solidity"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/adnpark.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"security.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-12-27T08:39:57.000Z","updated_at":"2025-03-17T16:47:16.000Z","dependencies_parsed_at":null,"dependency_job_id":"ec03b538-e4ba-4f35-8b6e-410b4e649495","html_url":"https://github.com/adnpark/solidity-cheatsheet","commit_stats":null,"previous_names":["adnpark/solidity-cheatsheet"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adnpark%2Fsolidity-cheatsheet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adnpark%2Fsolidity-cheatsheet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adnpark%2Fsolidity-cheatsheet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adnpark%2Fsolidity-cheatsheet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/adnpark","download_url":"https://codeload.github.com/adnpark/solidity-cheatsheet/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250306607,"owners_count":21408925,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cheatsheet","contract-solidity","ethereum","resources","solidity","solidity-cheatsheet","solidity-codes","solidity-compiler","solidity-contract","solidity-contracts","solidity-coverage","solidity-dapps","solidity-language","solidity-security","web3","web3-dapp","web3-solidity"],"created_at":"2025-01-09T03:03:50.418Z","updated_at":"2025-10-26T14:37:21.962Z","avatar_url":"https://github.com/adnpark.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Solidity Master Cheatsheet\n\nWelcome to the Solidity Master Cheatsheet—created especially for new Solidity developers! Whether you’re just starting to explore the fundamentals of smart contract programming or need a convenient reference while building your DApps, this guide has you covered.\n\n_This cheatsheet is based on version 0.8.29_\n\n# Table of Contents\n\n-   [Solidity Master Cheatsheet](#solidity-master-cheatsheet)\n-   [Table of Contents](#table-of-contents)\n-   [Getting Started](#getting-started)\n-   [Specifying compiler version](#specifying-compiler-version)\n-   [Basic Data Types](#basic-data-types)\n    -   [Summary](#summary)\n    -   [`bool`](#bool)\n    -   [Integers: `uint` and `int`](#integers-uint-and-int)\n    -   [`address` and `address payable`](#address-and-address-payable)\n    -   [`bytes` and `bytesN`](#bytes-and-bytesn)\n    -   [`string`](#string)\n-   [Variables \\\u0026 Visibility](#variables--visibility)\n    -   [State Variables](#state-variables)\n        -   [Constants](#constants)\n        -   [Immutable Variables](#immutable-variables)\n    -   [Local Variables](#local-variables)\n    -   [Global (Built-in) Variables](#global-built-in-variables)\n    -   [Visibility Keywords](#visibility-keywords)\n        -   [Visibility Accessible By Common Use Cases](#visibility-accessible-by-common-use-cases)\n        -   [`public`](#public)\n        -   [`external`](#external)\n        -   [`internal`](#internal)\n        -   [`private`](#private)\n    -   [Best Practices for Visibility](#best-practices-for-visibility)\n-   [Functions](#functions)\n    -   [Basic Syntax](#basic-syntax)\n    -   [Visibility](#visibility)\n-   [State Mutability: view, pure, and payable](#state-mutability-view-pure-and-payable)\n    -   [Return Values](#return-values)\n    -   [Function Parameters and Data Location](#function-parameters-and-data-location)\n    -   [Overloading and Overriding](#overloading-and-overriding)\n    -   [Internal vs External Calls](#internal-vs-external-calls)\n    -   [Gas Considerations](#gas-considerations)\n    -   [Best Practices for Functions](#best-practices-for-functions)\n-   [Control Flow](#control-flow)\n    -   [If / Else Statements](#if--else-statements)\n    -   [`require`](#require)\n    -   [For Loops](#for-loops)\n    -   [While Loops](#while-loops)\n    -   [Do-While Loops](#do-while-loops)\n    -   [Break and Continue](#break-and-continue)\n    -   [Best Practices for Loops](#best-practices-for-loops)\n        -   [Vanila Loop](#vanila-loop)\n        -   [Array Loop](#array-loop)\n-   [Error Handling](#error-handling)\n    -   [`require` vs `revert` vs `assert`](#require-vs-revert-vs-assert)\n        -   [`require(condition, \"Error Message\")`](#requirecondition-error-message)\n        -   [`revert(\"Error Message\")`](#reverterror-message)\n        -   [`assert(condition)`](#assertcondition)\n        -   [Key Points:](#key-points)\n    -   [Custom Errors (\\\u003e=0.8.4)](#custom-errors-084)\n        -   [Benefits:](#benefits)\n    -   [`try/catch` for External Calls](#trycatch-for-external-calls)\n    -   [Best Practices for Error Handling](#best-practices-for-error-handling)\n-   [Arrays, Mappings, Structs, Enums](#arrays-mappings-structs-enums)\n    -   [Arrays](#arrays)\n        -   [Fixed-size Arrays](#fixed-size-arrays)\n        -   [Dynamic Arrays](#dynamic-arrays)\n        -   [Declaring and Using Arrays](#declaring-and-using-arrays)\n            -   [Storage vs. Memory](#storage-vs-memory)\n            -   [Accessing Elements](#accessing-elements)\n            -   [Length](#length)\n            -   [Push and Pop (Dynamic Arrays in Storage)](#push-and-pop-dynamic-arrays-in-storage)\n            -   [Gas Considerations:](#gas-considerations-1)\n    -   [Mappings](#mappings)\n    -   [Structs](#structs)\n    -   [User Defined Value Types](#user-defined-value-types)\n        -   [Motivation](#motivation)\n        -   [Syntax](#syntax)\n        -   [Wrapping and Unwrapping](#wrapping-and-unwrapping)\n        -   [Operations and Conversions](#operations-and-conversions)\n    -   [Enums](#enums)\n        -   [Enum Advantages:](#enum-advantages)\n    -   [Best Practices and Tips](#best-practices-and-tips)\n-   [Modifiers](#modifiers)\n    -   [Syntax](#syntax-1)\n    -   [Anatomy of a Modifier](#anatomy-of-a-modifier)\n    -   [Multiple Modifiers on One Function](#multiple-modifiers-on-one-function)\n-   [Events](#events)\n    -   [Key Characteristics](#key-characteristics)\n    -   [Declaring Events](#declaring-events)\n    -   [Emitting Events](#emitting-events)\n    -   [Viewing Events Off-Chain](#viewing-events-off-chain)\n    -   [Indexed vs. Non-Indexed Parameters](#indexed-vs-non-indexed-parameters)\n    -   [Common Use Cases](#common-use-cases)\n    -   [Simple Example](#simple-example)\n    -   [Best Practices](#best-practices)\n-   [Contract Inheritance \\\u0026 Interfaces](#contract-inheritance--interfaces)\n    -   [Contract Inheritance](#contract-inheritance)\n        -   [Single Inheritance](#single-inheritance)\n        -   [Multiple Inheritance](#multiple-inheritance)\n        -   [Overriding Functions](#overriding-functions)\n        -   [Constructors in Inheritance](#constructors-in-inheritance)\n    -   [Interfaces](#interfaces)\n        -   [Implementing an Interface](#implementing-an-interface)\n        -   [Using Interfaces](#using-interfaces)\n        -   [Combining Inheritance and Interfaces](#combining-inheritance-and-interfaces)\n        -   [Abstract Contracts](#abstract-contracts)\n        -   [Diamond Inheritance and the “Linearization of Base Contracts”](#diamond-inheritance-and-the-linearization-of-base-contracts)\n    -   [Best Practices](#best-practices-1)\n-   [Libraries](#libraries)\n    -   [Key Characteristics of Libraries](#key-characteristics-of-libraries)\n    -   [Library Function Types](#library-function-types)\n        -   [Example: Internal Library](#example-internal-library)\n        -   [Example: External Library](#example-external-library)\n    -   [Library for Struct Extensions](#library-for-struct-extensions)\n    -   [Best Practices](#best-practices-2)\n-   [Payable, Fallback, and Receive](#payable-fallback-and-receive)\n    -   [`payable` Keyword](#payable-keyword)\n    -   [`receive()` Function](#receive-function)\n    -   [`fallback()` Function](#fallback-function)\n    -   [Best Practices](#best-practices-3)\n-   [Data Locations: `storage`, `memory`, `calldata`](#data-locations-storage-memory-calldata)\n    -   [`storage`: Persistent, On-Chain Data](#storage-persistent-on-chain-data)\n    -   [`memory`: Temporary, In-Function Workspace](#memory-temporary-in-function-workspace)\n    -   [`calldata`: Read-Only External Input](#calldata-read-only-external-input)\n    -   [Best Practices](#best-practices-4)\n-   [Transient Storage](#transient-storage)\n-   [Sending Ether](#sending-ether)\n    -   [Overview](#overview)\n        -   [transfer](#transfer)\n        -   [send](#send)\n        -   [call](#call)\n        -   [Best Practices](#best-practices-5)\n-   [Function Selector](#function-selector)\n    -   [How is the Function Selector Computed?](#how-is-the-function-selector-computed)\n    -   [Layout of Calldata](#layout-of-calldata)\n    -   [Function Overloading and Selectors](#function-overloading-and-selectors)\n    -   [Collision Issues](#collision-issues)\n-   [Call \\\u0026 Delegatecall](#call--delegatecall)\n    -   [Introduction to Low-Level Calls](#introduction-to-low-level-calls)\n        -   [Why Use Low-Level Calls?](#why-use-low-level-calls)\n    -   [`call`](#call-1)\n        -   [Behavior](#behavior)\n    -   [`delegatecall`](#delegatecall)\n        -   [Behavior](#behavior-1)\n    -   [`staticcall`](#staticcall)\n    -   [Comparison](#comparison)\n    -   [Security \\\u0026 Best Practices](#security--best-practices)\n-   [CREATE, CREATE2, Create3, and CreateX](#create-create2-create3-and-createx)\n    -   [CREATE](#create)\n    -   [CREATE2](#create2)\n    -   [Create3](#create3)\n    -   [Comparison](#comparison-1)\n    -   [CreateX](#createx)\n-   [ABI Encode \\\u0026 Decode](#abi-encode--decode)\n-   [References](#references)\n\n# Getting Started\n\n```solidity\n// SPDX-License-Identifier: MIT\n// Filename: HelloWorld.sol\n// The function `greet()` will return the message \"Hello, Solidity!\"\npragma solidity ^0.8.29;\n\ncontract HelloWorld {\n    string public message = \"Hello, Solidity!\";\n\n    function greet() external view returns (string memory) {\n        return message;\n    }\n}\n```\n\n# Specifying compiler version\n\n```solidity\npragma solidity 0.8.29; // The contract must be compiled with exactly version 0.8.29\n\npragma solidity ^0.8.29; // Any version greater than or equal to 0.8.29, but strictly less than 0.9.0\n\npragma solidity \u003e=0.8.0 \u003c0.9.0; // Any version greater than or equal to 0.8.0, but strictly less than 0.9.0\n```\n\n**Best Practice**\n\n-   When releasing production contracts, you may want to pin to a narrower range or exact version for complete determinism.\n-   During development, using ^0.8.x can be more convenient.\n\n# Basic Data Types\n\n## Summary\n\n| Type                | Description                                                | Example                                         |\n| ------------------- | ---------------------------------------------------------- | ----------------------------------------------- |\n| **bool**            | Boolean type, true or false                                | `bool isReady = true;`                          |\n| **uint**            | Unsigned integer (by default 256 bits, i.e. `uint256`)     | `uint256 count = 10;`                           |\n| **int**             | Signed integer (by default 256 bits, i.e. `int256`)        | `int256 temperature = -5;`                      |\n| **address**         | 20-byte Ethereum address (e.g. `0xABC123...`), non-payable | `address owner = msg.sender;`                   |\n| **address payable** | Same as address, but can receive Ether                     | `address payable wallet = payable(msg.sender);` |\n| **bytes**           | Dynamically sized byte array                               | `bytes data = hex\"001122\";`                     |\n| **bytesN**          | Fixed-size byte array of length N (1 ≤ N ≤ 32)             | `bytes32 hash = keccak256(...);`                |\n| **string**          | Dynamically sized UTF-8 data                               | `string name = \"Alice\";`                        |\n\n## `bool`\n\n-   Stores a single bit of information (true or false).\n-   Default value is false if not initialized.\n\n## Integers: `uint` and `int`\n\n-   uint stands for unsigned integer and does not allow negative values.\n    -   Range for uint256 is 0 to 2^256 - 1.\n    -   You can also specify smaller sizes like uint8, uint16, ..., uint256 (increments of 8 bits).\n-   int stands for signed integer and allows negative values.\n    -   Range for int256 is -(2^255) to (2^255 - 1).\n    -   Similarly, you can specify int8, int16, ..., int256.\n-   Default value for both uint256 and int256 is 0.\n\n```solidity\n// Unsigned integer\nuint256 public totalSupply = 10000;\n// Signed integer\nint256 public temperature = -25;\n```\n\n**Best Practice**\n\n-   Use uint256 unless you have a specific reason to use a smaller size (like uint128, etc.).\n    -   Smaller types can save storage (gas) if you can tightly pack multiple variables in a struct or the same storage slot.\n-   Avoid using signed integers if you only deal with non-negative values.\n\n## `address` and `address payable`\n\n-   An address type holds a 20-byte value.\n-   address has built-in attributes like:\n    -   balance (returns the account’s balance in wei),\n    -   code and codehash (get contract code or its hash),\n    -   and methods like call, delegatecall, staticcall (low-level).\n-   address payable is a special variant that allows sending Ether via methods like transfer or send.\n\n**Important**\n\nIn Solidity ^0.8.0, you must explicitly convert an address to address payable if you want to send Ether:\n\n```solidity\naddress payable receiver = payable(someAddress);\n```\n\n## `bytes` and `bytesN`\n\nbytes: dynamically sized array of bytes.\n\n-   Good for arbitrary-length binary data.\n-   More expensive to store than fixed-size arrays due to dynamic nature.\n\nbytesN: fixed-size array of length N (where 1 \u003c= N \u003c= 32).\n\n-   Commonly used for storing hashes (bytes32) or other fixed-length data (e.g., signatures).\n-   bytes32 is a popular choice for storing keccak256 hashes.\n\n```solidity\n// Dynamically sized\nbytes public data = hex\"DEADBEEF\";\n\n// Fixed-size, exactly 32 bytes\nbytes32 public myHash = keccak256(abi.encodePacked(\"Solidity\"));\n```\n\n## `string`\n\n-   A dynamically sized UTF-8 encoded data type typically used for text.\n-   In practice, string is very similar to bytes (both are dynamically sized), but string is meant for text, while bytes is better for raw binary data.\n-   Default value is an empty string \"\".\n\n```solidity\nstring public greeting = \"Hello, World!\";\n```\n\n# Variables \u0026 Visibility\n\nIn Solidity, variables are categorized based on **where** they are declared and **how** they can be accessed:\n\n1. State Variables\n2. Local Variables\n3. Global (Built-in) Variables\n4. Visibility Keywords\n\n## State Variables\n\n-   **Declared inside** a contract but **outside** of any function.\n-   **Stored permanently** on the blockchain as part of the contract’s state (in storage).\n-   **Gas cost**: Writing and updating state variables costs gas. Reading is cheaper but not free.\n-   **Initialization**: If not explicitly initialized, they are given default values (e.g., 0 for integers, false for booleans, address(0) for addresses).\n\n```solidity\npragma solidity ^0.8.29;\n\ncontract MyContract {\n    // State variables\n    uint256 public count;         // defaults to 0\n    bool public isActive = true;\n\n    // ...\n}\n```\n\n### Constants\n\n-   Constants are declared using the `constant` keyword.\n\n```solidity\nuint256 public constant constantVariable = 10;\n```\n\n### Immutable Variables\n\n-   Immutable variables are declared using the `immutable` keyword.\n-   They are initialized once and cannot be changed after that.\n\n```solidity\nuint256 public immutable immutableVariable = 10;\n```\n\n**Best Practice**\n\n-   Mark state variables as `public` only if you need external read access.\n-   Use `private` or `internal` for variables that should not be directly accessible outside the contract.\n-   Use `immutable` for variables that should not be changed after initialization.\n\n## Local Variables\n\n-   **Declared and used within function scope** (including function parameters).\n-   **Stored in memory or stack**, not in contract storage (unless explicitly specified otherwise).\n-   **Cheaper than state variables** because they’re only used temporarily during function execution.\n\n```solidity\nfunction multiplyByTwo(uint256 _x) public pure returns (uint256) {\n    // Local variable\n    uint256 result = _x * 2;\n    return result; // This value is not saved on-chain\n}\n```\n\n**Note**\n\n-   Local variables are destroyed after the function call ends.\n-   For arrays, structs, or strings passed as function parameters, you often must specify memory or calldata (in external functions) to define the data location.\n\n## Global (Built-in) Variables\n\nThese are pre-defined variables and functions that give information about the blockchain, transaction, or message context. Examples include:\n\n-   `msg.sender` — the address that called the function.\n-   `msg.value` — how much Ether (in wei) was sent with the call.\n-   `msg.data` — the data sent with the call.\n-   `block.timestamp` — the current block timestamp (a.k.a. Unix epoch time).\n-   `block.number` — the current block number.\n-   `block.chainid` — the chain ID of the blockchain.\n-   `tx.gasprice` — the gas price of the transaction.\n\nThese variables are read from the environment and cannot be directly overwritten. They do not require a declaration like normal variables.\n\nFor more global variables, see [here](https://docs.soliditylang.org/en/v0.8.29/units-and-global-variables.html#units-and-globally-available-variables).\n\nExample:\n\n```solidity\nfunction whoCalledMe() public view returns (address) {\n    // msg.sender is a global variable\n    return msg.sender;\n}\n```\n\n## Visibility Keywords\n\nIn Solidity, visibility determines which parts of the contract or external entities can access a function or state variable.\n\n### Visibility Accessible By Common Use Cases\n\n| Visibility   | Accessible By                                                                                    | Common Use Cases                                                                      |\n| ------------ | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------- |\n| **public**   | - Externally (via transactions or other contracts) \u003cbr/\u003e - Internally within the contract itself | Functions/variables that need to be read or called externally                         |\n| **external** | - Externally only (cannot be called internally without `this.`)                                  | Functions intended solely for external interaction (e.g., an API for Dapp users)      |\n| **internal** | - Only within this contract or inheriting contracts                                              | Helper functions and state variables used by derived contracts                        |\n| **private**  | - Only within this specific contract                                                             | Sensitive logic or state variables that shouldn't be accessed even by child contracts |\n\n**Note**\n\n-   `public` and `private` keywords are used to define the visibility of state variables and functions.\n-   `external` and `internal` keywords are used to define the visibility of functions only.\n\n### `public`\n\n-   A `public` state variable automatically generates a getter function. For example:\n\n```solidity\nuint256 public count;\n```\n\nThis allows reading `count` externally. The contract ABI will have a function `count()` that returns the variable’s value.\n\n```solidity\nfunction getCount() public view returns (uint256) {\n    return count;\n}\n```\n\n-   A `public` function can be called from:\n    -   Outside via a transaction or another contract\n    -   Inside by other functions within the same contract\n\n### `external`\n\n-   Functions only callable from outside the contract (or via `this.functionName(...)`).\n-   Typically used to indicate a function is part of the contract’s external interface.\n-   Slightly more gas-efficient if you don’t plan to call that function from within the contract.\n\n```solidity\nfunction externalFunction() external view returns (uint256) {\n    return address(this).balance;\n}\n\n// Inside another function in the same contract, you'd have to call: (but not recommended)\nthis.externalFunction();\n```\n\n### `internal`\n\n-   Accessible **only** within the contract and child contracts that inherit from it.\n-   Not part of the public ABI, so cannot be called externally.\n-   Useful for shared logic across parent-child relationships.\n\n```solidity\nfunction internalHelper() internal pure returns (uint256) {\n    return 42;\n}\n```\n\n### `private`\n\n-   **Only** accessible within the same contract.\n-   Not accessible in derived contracts.\n-   Typically used for sensitive or low-level logic that you don’t want child contracts to override or manipulate directly.\n\n```solidity\nbool private privateVariable = true;\n\nfunction privateHelper() private pure returns (uint256) {\n    return 123;\n}\n```\n\n## Best Practices for Visibility\n\n1. Explicitly Specify Visibility\n\n    - In Solidity, the default function visibility is internal if not specified.\n    - Always define visibility (public, external, internal, private) for every function and state variable to avoid confusion and ensure clarity in your code.\n\n2. Use external for Functions Called Externally Only\n\n    - If a function is never intended to be called internally, mark it external.\n    - external functions can be slightly more gas-efficient than public because Solidity handles arguments differently for external calls.\n\n3. Restrict Access Whenever Possible\n\n    - Follow the principle of least privilege.\n    - Use private or internal whenever you don’t need external or inherited access.\n    - This minimizes the contract’s attack surface and reduces the likelihood of unintended behavior.\n\n# Functions\n\nSolidity functions define the behavior of your smart contract. They can be used to read or modify the contract’s state, interact with other contracts, or perform computations.\n\n## Basic Syntax\n\n```solidity\nfunction functionName(Type param1, Type param2) [visibility] [stateMutability] returns (ReturnType) {\n    // function body\n}\n```\n\nWhere:\n\n-   `functionName` is the identifier (name) of the function.\n-   `param1, param2` are parameters with specified types.\n-   `visibility` can be `public`, `external`, `internal`, or `private`.\n-   `stateMutability` includes `view`, `pure`, `payable`, or can be omitted if the function modifies state.\n-   `returns (ReturnType)` specifies the output type(s) (can be multiple).\n\n## Visibility\n\nAs covered in [Visibility Keywords](#visibility-keywords), a function’s visibility determines who can call it. The most common visibilities for functions are:\n\n-   `public`: callable from outside and inside the contract\n-   `external`: callable from outside only (or via `this.functionName()` inside)\n-   `internal`: callable only inside this contract and derived contracts\n-   `private`: callable only inside this contract\n\n# State Mutability: view, pure, and payable\n\n1. `view`\n\n-   The function can read state variables but cannot modify them.\n\n```solidity\nfunction getCount() public view returns (uint256) {\n    return count;  // reading a state variable\n}\n```\n\n2. `pure`\n\n-   The function cannot read or modify state variables (nor use `this.balance` or `block.number` etc.).\n-   Ideal for pure math or utility functions.\n\n```solidity\nfunction addNumbers(uint256 a, uint256 b) public pure returns (uint256) {\n    return a + b;\n}\n```\n\n3. `payable`\n\n-   The function can accept Ether sent to it.\n-   Without `payable`, the function will reject any Ether transfer.\n\n```solidity\nfunction deposit() public payable {}\n```\n\n## Return Values\n\nYou can return one or more values from a function. There are multiple ways to do so:\n\n1. Return Single Value\n\n```solidity\nfunction getNumber() public pure returns (uint256) {\n    return 42;\n}\n```\n\n2. Return Multiple Values\n\n```solidity\nfunction getValues() public pure returns (uint256, bool) {\n    return (100, true);\n}\n```\n\n3. Named Returns\n\n-   You can name your return variables for clarity.\n\n```solidity\nfunction namedReturn() public pure returns (uint256 count, bool status) {\n    count = 10;\n    status = true;\n}\n```\n\n-   This can sometimes make the code more readable but is optional.\n\n## Function Parameters and Data Location\n\nFor parameters of reference types (e.g., `string`, `bytes`, `arrays`, `structs`), you must specify the data location (memory, storage, or calldata):\n\n-   `memory`: non-persistent, used for local copies within a function.\n-   `calldata`: non-persistent, immutable/read-only, only used in **external** function parameters. It’s more gas-efficient than memory for external calls because it doesn’t copy the data.\n-   `storage`: persists in the contract’s state storage (rarely used as a parameter location, mostly used for state variables). Can be used for internal or private function if you want to pass a reference to an existing storage variable.\n\nExample using calldata:\n\n```solidity\nfunction concatStrings(\n    string calldata str1,\n    string calldata str2\n) external pure returns (string memory) {\n    return string(abi.encodePacked(str1, str2));\n}\n```\n\n## Overloading and Overriding\n\n-   **Overloading**: Defining multiple functions with the same name but different parameters.\n\n```solidity\nfunction setValue(uint256 _value) public {\n    // ...\n}\n\nfunction setValue(uint256 _value, bool _flag) public {\n    // ...\n}\n```\n\n-   **Overriding**: When a function in a child contract overrides a function from a parent contract.\n    -   The parent function must be marked as `virtual`.\n    -   The child function must use `override`.\n\n```solidity\ncontract Parent {\n    function greet() public virtual pure returns (string memory) {\n        return \"Hello from Parent\";\n    }\n}\n\ncontract Child is Parent {\n    function greet() public pure override returns (string memory) {\n        return \"Hello from Child\";\n    }\n}\n```\n\n## Internal vs External Calls\n\n-   When you call a function internally in Solidity, it uses jump instructions without creating a new message call. This is more gas-efficient.\n-   When you call an external function from within the same contract (e.g., this.myExternalFunction()), it triggers a new contract call. This is less gas-efficient and changes msg.sender to the contract itself.\n\n## Gas Considerations\n\n1. Function Complexity:\n\n    - Avoid excessive loops or large data copy operations within a single function.\n    - If possible, break down large operations into smaller functions or use off-chain solutions for heavy computations.\n\n2. Function Parameters:\n\n    - For external functions, using calldata for parameters instead of memory is cheaper in many cases.\n    - Passing large arrays around increases gas due to data copy overhead.\n\n## Best Practices for Functions\n\n-   Use public or external only if the function needs to be called from outside. Otherwise, consider internal or private.\n-   Separate reading (view/pure) and state-changing functions for clarity and potential performance benefits.\n-   Overloading can be handy, but use it sparingly; it can cause confusion if the parameter differences are subtle.\n-   Overriding is essential for inheritance hierarchies. Make sure to mark parent functions as virtual and child overrides as override.\n\n# Control Flow\n\nControl flow in Solidity is largely similar to other languages like JavaScript, C, or Python. You can use if/else, for, while, and do-while loops to direct program execution.\n\n## If / Else Statements\n\nSyntax:\n\n```solidity\nfunction checkValue(uint256 _x) public pure returns (string memory) {\n    if (_x \u003e 100) {\n        return \"Greater than 100\";\n    } else if (_x == 100) {\n        return \"Exactly 100\";\n    } else {\n        return \"Less than 100\";\n    }\n}\n```\n\n## `require`\n\n`require` statements revert the transaction immediately if a condition is not met:\n\n```solidity\nrequire(condition, \"Error message\");\n```\n\nThis is often used for input validation or access control checks.\n\n## For Loops\n\n```solidity\nfunction sumArray(uint256[] memory _arr) public pure returns (uint256) {\n    uint256 total = 0;\n    for (uint256 i = 0; i \u003c _arr.length; i++) {\n        total += _arr[i];\n    }\n    return total;\n}\n```\n\n## While Loops\n\n```solidity\nfunction decrement(uint256 _x) public pure returns (uint256) {\n    while (_x \u003e 0) {\n        _x--;\n    }\n    return _x; // returns 0\n}\n```\n\n## Do-While Loops\n\nSolidity also supports do-while loops, which execute the loop body at least once before checking the condition:\n\n```solidity\nfunction doWhileExample(uint256 _x) public pure returns (uint256) {\n    uint256 counter = _x;\n\n    do {\n        counter--;\n    } while (counter \u003e 0);\n\n    return counter;\n}\n```\n\n## Break and Continue\n\nLike many languages, Solidity provides `break` and `continue` statements for early termination or skipping an iteration in loops.\n\n-   `break`: Exits the loop immediately.\n-   `continue`: Skips the remaining statements in the current iteration and moves to the next iteration.\n\n```solidity\nfunction loopWithBreak(uint256 _x) public pure returns (uint256) {\n    for (uint256 i = 0; i \u003c _x; i++) {\n        if (i == 5) break; // exits loop when i equals 5\n        if (i == 3) continue; // skips remaining statements when i equals 3\n        // ...\n    }\n}\n```\n\n## Best Practices for Loops\n\n### Vanila Loop\n\n**Don't use \u003e= and \u003c= in the condition**\n\n```solidity\n// 37975 gas (+347)\nfunction loop_lte() public returns (uint256 sum) {\n    for(uint256 n = 0; n \u003c= 99; n++) {\n        sum += n;\n    }\n}\n```\n\n-   The EVM has the opcodes LT, GT and EQ for comparison, but there are no convenient LTE or GTE opcodes for the operation we are doing.\n-   Therefore each time the condition n \u003c= 99 is checked, 3 instructions must be executed: LT n 99,EQ n 99 and OR to check if either one of those returned true, which leads to extra gas cost.\n\n**Increment the variable in an unchecked block**\n\n```solidity\n// 32343 gas (-5285)\nfunction loop_unchecked_plusplus() public returns (uint256 sum) {\n    for(uint256 n = 0; n \u003c 100;) {\n        sum += n;\n        unchecked {\n            n++;\n        }\n    }\n}\n```\n\n-   Since version 0.8 Solidity implements safety checks for all integer arithmetic, including overflow and underflow guards\n-   `n++` Solidity will insert extra code to handle the case if `n` would overflow after incrementing it\n-   We can skip the overflow check by using `unchecked` block\n-   Use only if you are sure the variables will never overflow\n\n**Just write it in assembly**\n\n```solidity\n// 26450 gas (-11178)\nfunction loop_assembly() public returns (uint256) {\n    assembly {\n        let sum := 0\n        for {let n := 0} lt(n, 100) {n := add(n, 1)} {\n            sum := add(sum, n)\n        }\n        mstore(0, sum)\n        return(0, 32)\n    }\n}\n```\n\n-   Removed the declaration uint256 sum from the function header in order to escape Solidity's type system as much as possible\n-   Using assembly is the most gas-efficient way to write a loop, but it's also the most complex and harder to read and maintain. So make sure to use it only when necessary.\n\n### Array Loop\n\n**\"Cache\" the array's length for the loop condition**\n\n```solidity\n// 25182 gas (-230)\nfunction loopArray_cached(uint256[] calldata ns) public returns (uint256 sum) {\n    uint256 length = ns.length;\n    for(uint256 i = 0; i \u003c length;) {\n        sum += ns[i];\n        unchecked {\n            i++;\n        }\n    }\n}\n```\n\n-   We know the length won't change during execution and we can reduce the number of ns.length calls to just 1 for a modest reduction in gas.\n\n# Error Handling\n\n## `require` vs `revert` vs `assert`\n\n### `require(condition, \"Error Message\")`\n\n-   Verifies **input conditions** or **other external conditions**.\n-   Commonly used at the start of a function to validate function inputs, access control, or other preconditions (e.g., ensuring msg.value is sufficient).\n\n```solidity\nrequire(msg.sender == owner, \"Not the owner\");\nrequire(amount \u003e 0, \"Amount must be greater than 0\");\n```\n\n-   If the condition fails, it reverts with the provided error message.\n-\n\n### `revert(\"Error Message\")`\n\n-   **Explicitly** trigger a revert from any part of the code.\n-   Often used to handle more complex logic or custom flows.\n\n```solidity\nif (balance \u003c amount) {\n    revert(\"Insufficient balance to withdraw\");\n}\n```\n\n### `assert(condition)`\n\n-   Used to check for internal errors and invariants that should never fail.\n-   If an assert fails, it indicates a bug in your code (e.g., an invariant has been violated).\n-   From Solidity 0.8.x onwards, failing assert also reverts the transaction but uses a different kind of error—often highlighting a critical code issue.\n\n```solidity\nassert(totalSupply == sumOfAllBalances);\n```\n\n### Key Points:\n\n-   `require` is for **invalid user inputs** or **external conditions**.\n-   `revert` is a **manual** revert trigger.\n-   `assert` is for **internal invariants**—if it fails, something is fundamentally wrong.\n\n## Custom Errors (\u003e=0.8.4)\n\n-   Custom errors allow you to define error types with optional parameters.\n-   They are more **gas-efficient** than revert strings because the encoded error data is smaller.\n\n```solidity\nerror Unauthorized(address caller);\nerror InvalidAmount(uint256 requested, uint256 available);\n\nfunction restrictedAction() public view {\n    if (msg.sender != owner) {\n        revert Unauthorized(msg.sender);\n    }\n    // ...\n}\n\nfunction withdraw(uint256 amount) public {\n    if (amount \u003e balances[msg.sender]) {\n        revert InvalidAmount(amount, balances[msg.sender]);\n    }\n    // ...\n}\n```\n\n### Benefits:\n\n-   Saves gas compared to long string messages.\n-   Provides typed parameters, making debugging easier off-chain.\n-   Especially useful in large or complex contracts.\n\n## `try/catch` for External Calls\n\n-   When calling **external** functions or doing contract creations, you can use `try/catch` to handle failures without reverting your entire function:\n\n```solidity\ninterface DataFeed { function getData(address token) external returns (uint value); }\n\ncontract FeedConsumer {\n    DataFeed feed;\n    uint errorCount;\n    function rate(address token) public returns (uint value, bool success) {\n        // Permanently disable the mechanism if there are\n        // more than 10 errors.\n        require(errorCount \u003c 10);\n        try feed.getData(token) returns (uint v) {\n            return (v, true);\n        } catch Error(string memory /*reason*/) {\n            // This is executed in case\n            // revert was called inside getData\n            // and a reason string was provided.\n            errorCount++;\n            return (0, false);\n        } catch Panic(uint /*errorCode*/) {\n            // This is executed in case of a panic,\n            // i.e. a serious error like division by zero\n            // or overflow. The error code can be used\n            // to determine the kind of error.\n            errorCount++;\n            return (0, false);\n        } catch (bytes memory /*lowLevelData*/) {\n            // This is executed in case revert() was used.\n            errorCount++;\n            return (0, false);\n        }\n    }\n}\n```\n\n-   You can choose to handle or re-revert. This can be used to do partial rollbacks or alternate logic.\n\n## Best Practices for Error Handling\n\n-   **Use require for Input Validation**\n    -   Validate function arguments, check `msg.value`, verify permissions, etc.\n-   **Keep Revert Messages Short**\n    -   Revert strings add to the bytecode size and runtime cost.\n    -   If you need to pass detailed data, consider custom errors.\n-   **Use custom errors for More Complex Logic**\n    -   Save gas and convey structured data (like addresses, amounts) in the revert reason.\n-   **Fail Fast**\n    -   Place `require` checks at the top of your functions to prevent unnecessary computations.\n\n# Arrays, Mappings, Structs, Enums\n\n-   Arrays: Sequential lists of elements of the same type.\n-   Mappings: Key-value data structure that does not store keys (only values).\n-   Structs: Custom types that group different data fields together.\n-   Enums: Defines a finite set of possible states.\n\n## Arrays\n\n### Fixed-size Arrays\n\n-   Their size must be known at compile time.\n-   You cannot change their length afterward.\n\n```solidity\nuint256[3] public fixedArray = [1, 2, 3];\n```\n\n### Dynamic Arrays\n\n-   Size can be modified at runtime using built-in methods like push and pop.\n-   Declared with empty brackets: `uint256[]`.\n\n```solidity\nuint256[] public dynamicArray;\n```\n\n### Declaring and Using Arrays\n\n#### Storage vs. Memory\n\n-   State arrays (declared at the contract level) live in **storage** (on-chain).\n-   Function parameters and local arrays can be declared in **memory** or **calldata** (for external functions).\n-   `calldata` is read-only and more gas-efficient for external function parameters.\n\n#### Accessing Elements\n\n```solidity\nuint256[] public numbers;\n\nfunction addNumber(uint256 num) external {\n    numbers.push(num); // dynamic array\n}\n\nfunction getNumber(uint256 index) external view returns (uint256) {\n    return numbers[index];\n}\n```\n\n#### Length\n\n-   For a dynamic array, `arrayName.length` gives the current length.\n-   You can also set a new length (in storage arrays) by assigning: `numbers.length = newLength;` (this can truncate or extend the array).\n\n#### Push and Pop (Dynamic Arrays in Storage)\n\n-   `push(value)` appends a new element at the end.\n-   `pop()` removes the last element (reducing the array length by one).\n-   Time complexity of `push` and `pop` is O(1).\n\n```solidity\nfunction removeLast() external {\n    numbers.pop();\n}\n```\n\n#### Gas Considerations:\n\n-   Each push, pop, and indexing operation in storage arrays incurs gas costs.\n-   Minimizing on-chain array size or using more efficient data structures can be crucial for large data sets.\n\n## Mappings\n\n-   A mapping is a reference type that stores key-value pairs.\n-   Mappings in Solidity:\n    -   **Do not allow iteration** over keys.\n    -   **Do not store** or keep track of the keys themselves—only the values and their hashed keys.\n    -   Are often used for **fast lookups** (constant time access).\n\n```solidity\nmapping(address =\u003e uint256) public balances;\n\nfunction deposit() external payable {\n    balances[msg.sender] += msg.value;\n}\n```\n\n-   **KeyType**: Usually a built-in type like `address`, `uint256`, or `bytes32`. (Structs, mappings, or dynamically-sized arrays cannot be used as keys.)\n-   **ValueType**: Can be any type, including another mapping or a struct.\n\n```solidity\n// Nested mapping\nmapping(address =\u003e mapping(address =\u003e uint256)) public allowance;\n\nfunction approve(address spender, uint256 amount) external {\n    allowance[msg.sender][spender] = amount;\n}\n```\n\n## Structs\n\n-   **Structs** let you define custom data types that group multiple variables (of possibly different types).\n-   They help in making code more readable and organizing complex data.\n\n```solidity\nstruct User {\n    string name;\n    uint256 age;\n    address wallet;\n}\n\nUser[] public users; // dynamic array of User structs\n\nfunction createUser(string memory _name, uint256 _age) external {\n    // Option 1: Direct struct creation\n    User memory newUser = User(_name, _age, msg.sender);\n    users.push(newUser);\n\n    // Option 2: Struct with named fields\n    users.push(User({name: _name, age: _age, wallet: msg.sender}));\n}\n```\n\n## User Defined Value Types\n\n-   User-Defined Value Types allow you to create a custom type name that wraps an existing built-in value type (like `uint256`, `int128`, `bytes32`, etc.).\n-   This feature was introduced in Solidity 0.8.8 and provides a way to give **semantic meaning** to a primitive type, helping catch logic errors and improving code readability.\n\n### Motivation\n\n-   **Type Safety \u0026 Readability**: By assigning a descriptive name to a built-in type, you can differentiate between, say, a `UserId` and a `Balance`, even if they’re both `uint256` under the hood.\n-   **Compile-Time Checks**: Conversions between different user-defined value types (and between the user-defined type and its underlying type) require **explicit** wrapping/unwrapping. This helps avoid mixing up incompatible values in your code.\n\n### Syntax\n\n```solidity\ntype TypeName is UnderlyingType;\n```\n\n-   `TypeName`: The name of your new type (PascalCase by convention).\n-   `UnderlyingType`: Any built-in value type (e.g., `uint256`, `int128`, `bool`, `bytes32`, etc.).\n\n```solidity\ntype UserId is uint256;\ntype Price is uint128;\ntype Flag is bool;\n```\n\n### Wrapping and Unwrapping\n\n-   Wrapping: Converting an underlying type to a user-defined type.\n-   Unwrapping: Converting a user-defined type back to its underlying type.\n\n```solidity\nuint256 rawId = 123;\n// Wrap a uint256 into a UserId\nUserId userId = UserId.wrap(rawId);\n\n// Unwrap a UserId to a uint256\nuint256 unwrappedId = UserId.unwrap(userId);\n\n// ❌ This will fail: Type uint256 is not implicitly convertible to UserId\nUserId invalidConversion = 123;\n```\n\n### Operations and Conversions\n\nBy default, **no** arithmetic or comparison operations are defined for user-defined value types. If you need to perform operations on your custom type, you can:\n\n1. **Unwrap** your custom type, perform the operations on the underlying type, then **re-wrap** the result.\n2. Define **inline** or **library** functions that handle the logic for your custom type.\n\n```solidity\npragma solidity ^0.8.29;\n\ntype Distance is uint256;\n\nlibrary DistanceLib {\n    function add(Distance a, Distance b) internal pure returns (Distance) {\n        // unwrap, add, then re-wrap\n        return Distance.wrap(Distance.unwrap(a) + Distance.unwrap(b));\n    }\n\n    function greaterThan(Distance a, Distance b) internal pure returns (bool) {\n        return Distance.unwrap(a) \u003e Distance.unwrap(b);\n    }\n}\n\ncontract Road {\n    using DistanceLib for Distance;\n\n    // store total length of roads\n    Distance public totalDistance;\n\n    function addDistance(Distance d) external {\n        totalDistance = totalDistance.add(d);\n        // internally uses DistanceLib.add\n    }\n\n    function compareDistances(Distance a, Distance b) external pure returns (bool) {\n        return a.greaterThan(b);\n    }\n}\n\n```\n\n## Enums\n\n-   Enums define a finite list of constant values, improving code clarity when dealing with limited states.\n-   Internally, enums map to uint8 by default (or the smallest fitting unsigned integer, though conceptually it can occupy a full storage slot). Each value corresponds to an index, starting at `0`.\n\n```solidity\nenum Status {\n    Pending,    // 0\n    Shipped,    // 1\n    Delivered,  // 2\n    Canceled    // 3\n}\n\nStatus public currentStatus;\n\nfunction setStatusShipped() external {\n    currentStatus = Status.Shipped;\n}\n\nfunction cancelOrder() external {\n    currentStatus = Status.Canceled;\n}\n\nfunction getStatus() external view returns (Status) {\n    return currentStatus;\n}\n```\n\n-   **Converting Enums**:\n    -   You can cast an integer to an enum if it’s a valid index.\n    -   Example: `Status s = Status(1); // s == Status.Shipped`\n    -   Be careful with casting, as invalid casts can lead to out-of-range enum values, which can corrupt state.\n\n### Enum Advantages:\n\n-   Makes state transitions self-documenting.\n-   Avoids using magic numbers (`0, 1, 2, 3`) or strings for statuses.\n-   Typically used for order states, workflow stages, or roles with limited states.\n\n## Best Practices and Tips\n\n1. **Use Arrays for Ordered Collections**\n\n-   Great for sequential data like lists of user IDs.\n-   Remember that iterating over large arrays on-chain is costly.\n\n2. **Use Mappings for Fast Lookups**\n\n-   Ideal for key-value pairs like balances or allowances.\n-   You cannot iterate over a mapping, so maintain auxiliary data if you need a list of keys.\n\n3. **Structs for Grouped Data**\n\n-   Keep related data fields together.\n-   This improves readability and can reduce storage slot usage if packed correctly (e.g., storing small-size types in one slot).\n\n4. **Guard Against Invalid Enum Values**\n\n-   If you do type-casting from integers to enums, ensure you handle out-of-range values.\n-   In Solidity 0.8.x, you get a revert on overflow, but be explicit about checking valid indices if you do custom casting.\n\n5. **Avoid Large Arrays in Storage**\n\n-   If you expect an unbounded number of elements, consider a more efficient approach like indexing or partial off-chain storage.\n-   Or provide a mechanism to paginate through array elements or handle them in batches.\n\n6. **Be Aware of Storage Collisions**\n\n-   When dealing with nested data structures or inherited contracts, be sure you understand how Solidity’s storage layout works.\n-   Typically, using the standard approach (top-level declarations) avoids collisions.\n\n# Modifiers\n\n-   Modifiers are a powerful feature in Solidity that allow you to augment or condition the execution of functions.\n-   Think of them as wrappers around your functions that can run additional code (e.g., access checks, state validations) before (and/or after) the function body is executed.\n\n## Syntax\n\n```solidity\nmodifier onlyOwner() {\n    require(msg.sender == owner, \"Caller is not owner\");\n    _;\n}\n\nfunction sensitiveAction() public onlyOwner {\n    // This code runs after the `onlyOwner` checks\n    // ...\n}\n```\n\n1. When `sensitiveAction()` is called, Solidity first executes the code in the `onlyOwner` modifier.\n2. If all checks (e.g., `require`) pass, it proceeds to execute the body of `sensitiveAction()`.\n3. If any check fails, it reverts and never calls the function body.\n\n## Anatomy of a Modifier\n\n-   A modifier can contain code before and after the special `_` (underscore):\n\n```solidity\nmodifier checkValue(uint256 _value) {\n    // Code executed before the function body\n    require(_value \u003e 0, \"Value must be greater than zero\");\n\n    _; // The function body is inserted here\n\n    // Code executed after the function body\n    emit ValueChecked(_value);\n}\n\nfunction doSomething(uint256 amount) public checkValue(amount) {\n    // function body\n}\n```\n\nthe compiled code effectively looks like:\n\n```solidity\nfunction doSomething(uint256 amount) public {\n    require(amount \u003e 0, \"Value must be greater than zero\");\n\n    // function body (original code of doSomething)\n\n    emit ValueChecked(amount);\n}\n```\n\n## Multiple Modifiers on One Function\n\n-   You can apply multiple modifiers to a single function. The modifiers will execute in order, left to right:\n\n```solidity\nmodifier onlyOwner() { /* ... */ _; }\nmodifier whenNotPaused() { /* ... */ _; }\n\nfunction specialAction() public onlyOwner whenNotPaused {\n    // function body\n}\n```\n\n-   Be mindful of the order, especially if the modifiers change state.\n-   Also ensure your modifiers don’t conflict or replicate the same checks unnecessarily.\n\n# Events\n\n-   Events in Solidity are mechanisms that allow smart contracts to emit logs during execution.\n-   These logs are stored on the blockchain as part of the transaction receipt, but do not directly consume contract storage.\n-   Off-chain applications (like DApps, block explorers, etc.) can listen for these events to react or update their interfaces.\n\n## Key Characteristics\n\n-   **Logs vs. Storage**: Events produce logs that are cheaper than storing data in contract state, because they’re kept in the transaction receipt.\n-   **Indexed Parameters**: You can mark up to **3 parameters** as indexed, enabling more efficient filtering on the client side.\n-   **Not Accessible On-Chain**: Event data (logs) are **not** accessible to other contracts. You can’t read events from within Solidity; they’re purely for off-chain usage.\n\n## Declaring Events\n\n```solidity\nevent Transfer(address indexed from, address indexed to, uint256 value);\n```\n\n-   Up to three parameters can be labeled as `indexed`.\n-   `indexed` parameters are **indexed** in the event log, which makes them searchable by off-chain tools.\n\n## Emitting Events\n\n```solidity\nfunction transfer(address _to, uint256 _amount) external {\n    // ... perform transfer logic ...\n    emit Transfer(msg.sender, _to, _amount);\n}\n```\n\n## Viewing Events Off-Chain\n\n-   Web3 Libraries (Viem, ethers.js) allow you to listen for these events or query past events by searching transaction logs.\n\nExample(in Viem):\n\n```typescript\nimport { parseAbiItem } from \"viem\"\nimport { publicClient } from \"./client\"\n\npublicClient.watchEvent({\n    address: \"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48\",\n    event: parseAbiItem(\n        \"event Transfer(address indexed from, address indexed to, uint256 value)\"\n    ),\n    args: {\n        from: \"0xd8da6bf26964af9d7eed9e03e53415d37aa96045\",\n        to: \"0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac\"\n    },\n    onLogs: (logs) =\u003e console.log(logs)\n})\n```\n\n## Indexed vs. Non-Indexed Parameters\n\n-   Indexed parameters are **searchable** in the logs and stored as topics.\n-   Non-indexed parameters are stored in the log’s data section, which is not easily searchable but can be read once you retrieve the log.\n\nFor example, in `event Transfer(address indexed from, address indexed to, uint256 value)`;:\n\n-   `from` =\u003e topic[1]\n-   `to` =\u003e topic[2]\n-   `value` =\u003e part of the data payload\n\n-   You can filter logs by indexed topics like `from = 0x1234...abcd`, but you cannot directly filter by `value` because it’s not indexed.\n\n```typescript\nconst filter = await publicClient.createContractEventFilter({\n    abi: wagmiAbi,\n    address: \"0xfba3912ca04dd458c843e2ee08967fc04f3579c2\",\n    eventName: \"Transfer\",\n    args: {\n        from: \"0xd8da6bf26964af9d7eed9e03e53415d37aa96045\",\n        to: \"0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac\"\n    }\n})\n```\n\n## Common Use Cases\n\n1. Token Transfers\n    - ERC20 tokens emit a `Transfer` event whenever tokens move from one address to another.\n2. State Changes\n    - Logging changes of ownership, updates to config variables, or changes in contract status.\n3. Debugging\n    - Emitting certain events during testing can help you trace contract execution.\n4. Off-Chain Processing\n    - Subgraphs (e.g., The Graph) or other indexing services use events to build databases of contract activity, enabling complex queries and analytics.\n\n## Simple Example\n\n```solidity\npragma solidity ^0.8.21;\n\ncontract Payment {\n    event Deposit(address indexed sender, uint256 amount);\n    event Withdraw(address indexed recipient, uint256 amount);\n\n    function deposit() external payable {\n        require(msg.value \u003e 0, \"No ether sent\");\n        emit Deposit(msg.sender, msg.value);\n    }\n\n    function withdraw(uint256 amount) external {\n        require(amount \u003e 0, \"Zero withdrawal\");\n        require(address(this).balance \u003e= amount, \"Insufficient contract balance\");\n\n        (bool success, ) = payable(msg.sender).call{value: amount}(\"\");\n        require(success, \"Withdraw failed\");\n\n        emit Withdraw(msg.sender, amount);\n    }\n}\n```\n\n## Best Practices\n\n-   Emit Events for Important State Changes\n\n    -   Especially for actions that off-chain services or UIs need to track: token transfers, ownership changes, auctions ending, etc.\n\n-   Index Only What’s Needed\n\n    -   Up to three indexed parameters can be used. Indexing more variables doesn’t exist (the rest must be unindexed).\n    -   Too many indexed parameters or large data can increase log size and gas cost.\n\n-   Avoid Emitting Too Many Events in a Single Transaction\n\n    -   Each event adds to the gas cost. If you’re in a loop, consider alternative approaches or batch events if possible.\n\n-   Be Aware of Event Ordering\n\n    -   The order in which you emit events is the order they appear in the logs. Off-chain listeners often rely on log order to interpret data.\n\n# Contract Inheritance \u0026 Interfaces\n\n-   Solidity supports an **object-oriented programming** model where **contracts** can **inherit** from one or more base contracts.\n-   This allows for code reuse and hierarchical organization of functionality.\n-   **Interfaces** in Solidity define the required function signatures (and optionally events) without providing an implementation, allowing for standardized interaction between different contracts.\n\n## Contract Inheritance\n\nInheritance is achieved using the `is` keyword. A derived (child) contract can access and override the functions and state variables of its parent (base) contract(s).\n\n### Single Inheritance\n\n```solidity\ncontract Parent {\n    string public parentName = \"Parent\";\n\n    function greet() public pure returns (string memory) {\n        return \"Hello from Parent\";\n    }\n}\n\ncontract Child is Parent {\n    function sayHello() public view returns (string memory) {\n        // Access parent's state variable\n        return parentName;\n    }\n}\n```\n\n-   `Child` inherits everything from `Parent` except **constructor**, **private** state variables/functions, and **internal** data can only be accessed within `Child`.\n\n### Multiple Inheritance\n\nA contract can inherit from multiple base contracts using comma separation:\n\n```solidity\ncontract A {\n    function foo() public pure returns (string memory) {\n        return \"A\";\n    }\n}\n\ncontract B {\n    function bar() public pure returns (string memory) {\n        return \"B\";\n    }\n}\n\n// Child inherits both A and B\ncontract C is A, B {\n    // C now has both foo() from A and bar() from B\n}\n```\n\n### Overriding Functions\n\n-   Parent functions must be marked `virtual` to allow them to be overridden.\n-   Child overrides must use `override`.\n\n```solidity\ncontract Parent {\n    function greet() public pure virtual returns (string memory) {\n        return \"Hello from Parent\";\n    }\n}\n\ncontract Child is Parent {\n    // Overriding greet()\n    function greet() public pure override returns (string memory) {\n        return \"Hello from Child\";\n    }\n}\n```\n\n-   If you have multiple levels (e.g., `Grandparent -\u003e Parent -\u003e Child`), and `Child` wants to override a function from `Grandparent`, you typically chain `override(Base, Grandparent)` if needed.\n\n```solidity\ncontract Child is Parent, Grandparent {\n    function greet() public pure override(Parent, Grandparent) returns (string memory) {\n        return \"Hello from Child\";\n    }\n}\n```\n\n### Constructors in Inheritance\n\n-   If a parent contract has a **constructor**, the child must **explicitly** call it (unless it has a parameterless constructor).\n-   If multiple parents have constructors, each must be called with the needed arguments in the child’s constructor.\n\n```solidity\ncontract Parent1 {\n    uint256 public x;\n\n    constructor(uint256 _x) {\n        x = _x;\n    }\n}\n\ncontract Parent2 {\n    uint256 public y;\n\n    constructor(uint256 _y) {\n        y = _y;\n    }\n}\n\ncontract Child is Parent1, Parent2 {\n    // Must call Parent1,2 constructor\n    constructor(uint256 _childValue) Parent1(_childValue) Parent2(_childValue) {\n        // additional child init\n    }\n}\n```\n\n## Interfaces\n\nAn **interface** in Solidity is like a contract but with these restrictions:\n\n1. **No** state variables or constructor definitions.\n2. **All functions must be `external`** (or public in older versions of Solidity, but typically we use `external`).\n3. **No** function implementations—**only signatures**.\n4. Usually includes events that implementing contracts should emit.\n\nPurpose: They define a **standard** for other contracts to implement, ensuring compatibility without forcing an implementation approach.\n\n```solidity\ninterface ICounter {\n    function increment() external;\n    function getCount() external view returns (uint256);\n    event Counted(address indexed caller, uint256 newCount);\n}\n```\n\n### Implementing an Interface\n\n-   A contract **implements** an interface by providing **all** the functions declared in the interface and matching their signatures exactly.\n\n```solidity\ncontract Counter is ICounter {\n    uint256 private count;\n\n    function increment() external override {\n        count++;\n        emit Counted(msg.sender, count);\n    }\n\n    function getCount() external view override returns (uint256) {\n        return count;\n    }\n}\n```\n\n### Using Interfaces\n\nContracts can call interface functions to interact with external contracts that implement them:\n\n```solidity\ncontract Caller {\n    function doIncrement(ICounter _counter) external {\n        _counter.increment();\n    }\n\n    function readCount(ICounter _counter) external view returns (uint256) {\n        return _counter.getCount();\n    }\n}\n```\n\n### Combining Inheritance and Interfaces\n\nYou can mix inheritance and interfaces. For example, you could have a base abstract contract that implements some parts of an interface and leaves others for child contracts.\n\n```solidity\ninterface IVault {\n    function deposit(uint256 amount) external;\n    function withdraw(uint256 amount) external;\n}\n\nabstract contract VaultBase is IVault {\n    // partially implement deposit logic\n    // but keep withdraw abstract or add some logic\n\n    function deposit(uint256 amount) external virtual override {\n        // partial logic\n    }\n}\n\ncontract MyVault is VaultBase {\n    // Must override deposit if not fully implemented\n    // Must implement withdraw\n    function deposit(uint256 amount) external override {\n        // full deposit logic\n    }\n\n    function withdraw(uint256 amount) external override {\n        // implement withdraw logic\n    }\n}\n```\n\n-   `VaultBase` is an abstract contract because it might not fully implement all methods of `IVault`.\n-   `MyVault` completes the implementation.\n\n### Abstract Contracts\n\n**Abstract contracts** are those that cannot be deployed directly because they have at least one function without an implementation (`virtual` function). They serve as base contracts.\n\n-   Typically contain shared logic and placeholders for functions to be defined in child contracts.\n-   Marked with `abstract` keyword in Solidity 0.6.x+.\n\n```solidity\nabstract contract Animal {\n    function speak() public virtual returns (string memory);\n}\n\ncontract Dog is Animal {\n    function speak() public pure override returns (string memory) {\n        return \"Woof!\";\n    }\n}\n```\n\n-   `Animal` is abstract because `speak()` has no implementation.\n-   `Dog` provides an implementation for `speak()`.\n\n### Diamond Inheritance and the “Linearization of Base Contracts”\n\n-   Solidity uses the **C3 linearization** algorithm to resolve conflicts in multiple inheritance.\n-   If multiple parent contracts have the **same function** name, you must explicitly **override** and specify which base contract’s implementation to use.\n\n```solidity\ncontract A {\n    function foo() public pure virtual returns (string memory) {\n        return \"A\";\n    }\n}\n\ncontract B is A {\n    function foo() public pure virtual override returns (string memory) {\n        return \"B\";\n    }\n}\n\ncontract C is A {\n    function foo() public pure virtual override returns (string memory) {\n        return \"C\";\n    }\n}\n\n// D inherits from both B and C\ncontract D is B, C {\n    // Must override foo() again\n    function foo() public pure override(B, C) returns (string memory) {\n        // decide which parent's implementation to call, or write new logic\n        // it will return \"C\"\n        return super.foo(); // picks the rightmost parent's override by default (C) in linearization\n    }\n}\n```\n\n-   The `override(B, C)` explicitly states you are overriding `foo()` from both `B` and `C`.\n-   `super.foo()` calls the next-most derived override in the linearization.\n\n## Best Practices\n\n-   **Use Inheritance for Shared Logic**\n\n    -   Common functionality (e.g., access control, utility functions) can be placed in base contracts for easy reuse.\n\n-   **Favor Composition over Deep Inheritance**\n\n    -   Avoid extremely deep inheritance chains—they can become confusing and error-prone.\n    -   Sometimes, libraries or composition patterns are clearer.\n\n-   **Mark Functions as `virtual` and `override`**\n\n    -   Always use `virtual` in the base contract to signal it can be overridden.\n    -   Always use `override` in child contracts to signal you’re overriding a parent function.\n\n-   **Use Interfaces for Inter-Contract Communication**\n\n    -   Define an interface that external contracts must implement.\n    -   This reduces dependencies, as your contract does not rely on the internal details of the other contract.\n\n-   **Separate Interfaces into Their Own Files**\n\n    -   This aids clarity and reusability.\n    -   Keep your interface definitions minimal—only the required function signatures and events.\n\n-   **Avoid Conflicting State in Multiple Inheritance**\n\n    -   Overlapping storage layouts from multiple parents can cause confusion or even storage collisions.\n    -   Ensure each parent contract uses distinct state variable slots (this usually happens naturally if you’re just inheriting standard contracts without complicated overrides).\n\n# Libraries\n\n-   In Solidity, **libraries** are special types of contracts intended to provide reusable code.\n-   They can be thought of as utility or helper modules that other contracts can call without needing to implement the same logic repeatedly.\n-   Libraries help keep code DRY (Don’t Repeat Yourself), save gas, and improve readability.\n\n## Key Characteristics of Libraries\n\n-   **No Ether**\n\n    -   Libraries **cannot** hold Ether (i.e., they cannot have a balance).\n    -   Any attempt to send Ether to a library will fail.\n\n-   **No State Variables**\n\n    -   Libraries cannot store or modify their own state; they are stateless.\n\n-   **No Inheritance**\n\n    -   Libraries cannot be inherited or extend other contracts (nor can you inherit from a library).\n\n-   **Linked at Compile Time or Deployment Time**\n    -   **Internal library functions** are typically inlined or statically called.\n    -   **External library functions** can be deployed and then “linked” to your contract.\n\n## Library Function Types\n\nSolidity libraries support **two** ways of using their functions:\n\n-   **Internal Functions**\n\n    -   If a library function is declared `internal`, it is inlined into the calling contract’s bytecode at compile time (similar to macros).\n    -   This reduces overhead since no external call is made.\n\n-   **External Functions**\n\n    -   If a library function is declared `public` or `external`, the calling contract will **delegatecall** into the library at runtime.\n    -   This can save bytecode size in the calling contract but introduces a small overhead for each external call.\n    -   You must **deploy** the library contract first and link it before deploying the final contract.\n\n### Example: Internal Library\n\nMost libraries are used as **internal** because it’s more gas-efficient (no external call) and simpler to manage.\n\n```solidity\n// MathLib.sol\npragma solidity ^0.8.29;\n\nlibrary MathLib {\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a + b;\n    }\n\n    function multiply(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a * b;\n    }\n}\n\n// TestMath.sol\npragma solidity ^0.8.21;\n\nimport \"./MathLib.sol\";\n\ncontract TestMath {\n    function testAdd(uint256 x, uint256 y) public pure returns (uint256) {\n        return MathLib.add(x, y);\n    }\n\n    function testMultiply(uint256 x, uint256 y) public pure returns (uint256) {\n        return MathLib.multiply(x, y);\n    }\n}\n```\n\n-   `MathLib.add` and `MathLib.multiply` are called from `TestMath` without an external call because they’re `internal` functions in a library.\n-   The compiler will inline or statically link these calls, increasing `TestMath`’s bytecode size, but saving on runtime gas costs.\n\n### Example: External Library\n\nYou can define a library with public or external functions. In that case, your contract calls the library via delegatecall at runtime.\n\n```solidity\n// ExternalLib.sol\npragma solidity ^0.8.29;\n\nlibrary ExternalLib {\n    function externalAdd(uint256 a, uint256 b) external pure returns (uint256) {\n        return a + b;\n    }\n}\n```\n\nTo use this library in another contract:\n\n```solidity\npragma solidity ^0.8.29;\n\nimport \"./ExternalLib.sol\";\n\ncontract UseExternalLib {\n    // The compiler inserts a reference that must be linked to the ExternalLib deployed address\n    function compute(uint256 x, uint256 y) public pure returns (uint256) {\n        return ExternalLib.externalAdd(x, y);\n    }\n}\n```\n\n-   **Deployment**: You must first deploy `ExternalLib` and then link its address into `UseExternalLib`’s bytecode.\n-   At runtime, calls to `ExternalLib.externalAdd` happen via DELEGATECALL.\n\n## Library for Struct Extensions\n\n-   A popular pattern is to write libraries that extend built-in types or custom structs with `using for`.\n-   This adds **library functions** as if they were member functions of the type.\n\n```solidity\npragma solidity ^0.8.29;\n\nlibrary ArrayUtils {\n    function findIndex(uint256[] storage arr, uint256 value) internal view returns (int256) {\n        for (uint256 i = 0; i \u003c arr.length; i++) {\n            if (arr[i] == value) {\n                return int256(i);\n            }\n        }\n        return -1; // Not found\n    }\n}\n\ncontract MyArray {\n    using ArrayUtils for uint256[];  // \"using for\" directive\n\n    uint256[] private data;\n\n    function addValue(uint256 value) external {\n        data.push(value);\n    }\n\n    function findValue(uint256 value) external view returns (int256) {\n        // We can now call findIndex() as if it's a member of data\n        return data.findIndex(value);\n    }\n}\n```\n\n-   The `using ArrayUtils for uint256[];` directive allows you to call `data.findIndex(value)` directly.\n-   This improves readability and encapsulates utility logic for arrays.\n\n## Best Practices\n\n-   **Keep Libraries Focused**\n\n    -   A library should do **one thing** well—e.g., math operations, array helpers, address utilities, etc.\n\n-   **Avoid Large External Libraries for Single Contracts**\n\n    -   If you’re only using a library for a single contract and that library has few functions, it might be simpler and cheaper to make them internal.\n\n-   **Mark Functions `pure` or `view` Where Possible**\n\n    -   Avoid unintentional state modifications in libraries unless that’s the library’s explicit purpose.\n    -   This also ensures your library is safer and can be reasoned about more easily.\n\n-   **`using for` Pattern**\n\n    -   Great for readability and a more object-oriented feel.\n    -   Clarifies which types are extended by the library.\n\n-   **Security**\n\n    -   Libraries can mutate the caller’s storage if called with `delegatecall`. Ensure your library code is trusted and thoroughly reviewed.\n\n-   **Solady, OpenZeppelin and Other Standard Libraries**\n\n    -   Before writing your own, check if established libraries (e.g., Solady, OpenZeppelin) cover your needs. This reduces risk and leverages well-audited code.\n\n# Payable, Fallback, and Receive\n\n-   Smart contracts in Solidity can receive Ether if they have specific functions set up.\n-   Before Solidity `0.6.x`, there was only a single fallback function.\n-   From `0.6.x` onward, Solidity introduced a split: a dedicated `receive()` function to handle plain Ether transfers, and a `fallback()` function to handle non-matching function calls (and optionally Ether if `receive()` is not found).\n\n## `payable` Keyword\n\n1. `payable` is required for functions to receive Ether.\n2. It can apply to constructors and functions.\n3. If a function or constructor is not marked `payable`, it will reject any incoming Ether with a revert.\n\n```solidity\npragma solidity ^0.8.21;\n\ncontract PayableExample {\n    // A payable constructor allows you to deploy the contract with initial Ether\n    constructor() payable {\n        // Contract can receive Ether on deployment\n    }\n\n    // A payable function can receive Ether\n    function deposit() external payable {\n        // Funds are added to contract balance\n    }\n\n    // This function is NOT payable, so it cannot receive Ether\n    function nonPayableFunction() external {\n        // ...\n    }\n}\n```\n\n-   Attempting to send Ether (e.g., via `msg.value`) to `nonPayableFunction()` will revert.\n-   Conversely, calling `deposit()` without sending Ether is valid (but `msg.value` would be `0`).\n\n## `receive()` Function\n\n-   **Introduced** in Solidity `0.6.x` as a **special** function to receive plain Ether with no data (i.e., calls with an empty calldata).\n-   It can be declared `external payable` with **no** arguments and **no** return value.\n\n```solidity\nreceive() external payable {\n    // custom logic or leave it empty\n}\n```\n\n-   If someone sends Ether to your contract without calling a specific function (like a simple `transfer()` or `send()` from an external account), the `receive()` function is triggered if it is defined.\n-   If you want your contract to accept plain Ether transfers, define a `receive()` function (or a fallback that is payable).\n\n**Behavior:**\n\n-   If a contract **does not** define `receive() external payable` but does define a `fallback() external payable`, then sending Ether with no data triggers the `fallback()` function.\n-   If neither function is payable, the contract cannot receive Ether outside of a payable function call and will revert.\n\n## `fallback()` Function\n\n-   The `fallback()` function is a special function in Solidity, called when:\n    -   A function that doesn’t exist in the contract is called.\n    -   No function signature matches the calldata.\n    -   If the call has data but there is no matching function.\n\n```solidity\nfallback() external [payable] {\n    // custom logic\n}\n```\n\n-   `fallback()` is **not** required to be `payable` by default. If you want it to receive Ether when no function matches, mark it `payable`. Otherwise, calls sending Ether will revert.\n\n**Use Cases:**\n\n-   **Proxy/Forwarding**: This is common in proxy contracts where all unknown calls are forwarded to another contract.\n-   **Emergency catch-all**: If a user or contract calls a function that does not exist, you can handle or revert gracefully.\n-   **Receiving Ether + Data**: If you need to handle Ether transfers that include data, you can do so in `fallback()` if `receive()` is not suitable or is absent.\n\n## Best Practices\n\n-   **Decide if you want to accept Ether**:\n    -   If yes, define a `receive()` function (or a `payable fallback()`).\n    -   If no, either omit them or revert in `fallback()`.\n-   **Keep Fallback/Receive Minimal**:\n    -   They can be triggered frequently, and often with limited gas (2,300).\n    -   Complex logic can lead to out-of-gas errors.\n    -   For reentrancy safety, minimize state changes or use reentrancy guards.\n-   **Test for Edge Cases**:\n    -   Test calls with valid function signatures, invalid ones, random data, zero-length data, and with Ether attached.\n    -   Make sure you get the intended behavior (especially for proxies or other fallback patterns).\n-   **Event Logging**:\n    -   If your contract receives Ether, consider emitting an event to easily track inbound transfers.\n\n# Data Locations: `storage`, `memory`, `calldata`\n\n-   In Solidity, **complex data types**—like arrays, structs, and mappings—require specifying a **data location**.\n-   This tells the compiler where the data physically resides. The three main data locations are:\n\n1. `storage`: Persistent on-chain storage (the contract’s state).\n2. `memory`: Temporary, in-memory area used within function execution. Not persisted on-chain.\n3. `calldata`: Read-only area for function arguments in external functions. It directly references call data without copying it into memory.\n\n## `storage`: Persistent, On-Chain Data\n\n-   **Location**: The contract’s long-term memory on the Ethereum blockchain.\n-   **Persistence**: Any changes to data in storage are permanent and cost **significant gas**.\n-   **State Variables**: By default, state variables declared at the contract level (e.g., `uint256 public count;`) reside in `storage`.\n\n```solidity\ncontract MyContract {\n    // This array is in storage (part of contract state).\n    uint256[] public numbers;\n\n    function storeValue(uint256 value) external {\n        numbers.push(value); // Modifying storage costs gas\n    }\n}\n```\n\n**Key Points:**\n\n-   **Expensive to Modify**: Writing to `storage` is the costliest operation because you’re permanently updating the blockchain state.\n-   **Reference Types in Storage**: Arrays, structs, and mappings can be stored in `storage`. Modifying their contents is also costly.\n-   **Assignments in Storage**: When you do `storageRef = someStateVar;`, you create a reference pointing to the same data. Changes to one reflect in the other.\n\n## `memory`: Temporary, In-Function Workspace\n\n-   **Location**: A transient area used for the duration of a function call.\n-   **Lifecycle**: Data in `memory` is wiped after the function executes.\n-   **Cost**: Reading/writing `memory` is cheaper than `storage` (though not free), but the data does not persist.\n\n```solidity\nfunction incrementValuesMemory(uint256[] memory arr)\n    public\n    pure\n    returns (uint256[] memory)\n{\n    // We can mutate the array elements because 'arr' is a mutable copy in memory.\n    for (uint256 i = 0; i \u003c arr.length; ++i) {\n        arr[i] += 10;\n    }\n    // Returning the changed array\n    return arr;\n}\n```\n\n## `calldata`: Read-Only External Input\n\n-   **Location**: A special data location for external function parameters.\n-   **Read-Only**: You cannot modify data in calldata; it’s immutable.\n-   **Gas Optimization**: Using calldata for external function parameters (instead of memory) can save gas, because Solidity can read directly from the transaction call data instead of making a full copy in memory.\n\n```solidity\nfunction sumArray(uint256[] calldata arr) external pure returns (uint256) {\n    uint256 sum = 0;\n    for (uint256 i = 0; i \u003c arr.length; i++) {\n        sum += arr[i];\n    }\n    return sum;\n}\n```\n\n-   Any attempt to modify arr (e.g., `arr[i] = ...`) will fail to compile.\n\n## Best Practices\n\n-   **Use `calldata` for External Read-Only Params**:\n    -   If you only need to read from parameters, mark them as `calldata` to save gas (no copying into memory).\n-   **Avoid Large Copies**:\n    -   Copying large arrays from `storage` to `memory` can be expensive. Consider streaming or chunking if you need partial data.\n-   **Use `storage` Wisely**:\n    -   Minimize writes to `storage`. If possible, only store essential data. Reading from and especially writing to `storage` is the biggest cost in Solidity.\n\n# Transient Storage\n\n-   Transient storage is a new feature introduced to Ethereum through EIP-1153.\n-   It provides a special type of storage for Ethereum smart contracts that:\n\n    -   Exists only **during a single transaction**.\n    -   Automatically resets at the end of the transaction.\n    -   Does not incur persistent storage costs (unlike regular storage, which is expensive because it remains on-chain indefinitely).\n\n-   Transient storage is implemented through two new opcodes:\n\n    -   `TSTORE`: Temporarily stores a value in transient storage.\n    -   `TLOAD`: Retrieves a value from transient storage.\n\n```solidity\ncontract ReentrancyGuard {\n    bytes32 constant SLOT = 0;\n\n    modifier nonreentrant() {\n        assembly {\n            if tload(SLOT) { revert(0, 0) }\n            tstore(SLOT, 1)\n        }\n        _;\n        assembly {\n            tstore(SLOT, 0)\n        }\n    }\n}\n```\n\n-   One practical example of transient storage is using it for a reentrancy guard.\n-   Normally, you’d store a boolean flag in contract storage to indicate that a function is currently being executed.\n-   With transient storage, you can use the `TSTORE` and `TLOAD` opcodes instead, which let you store and read this flag during the transaction without writing to storage.\n-   This not only makes the guard cheaper to implement, but also avoids cluttering your contract’s persistent state.\n\n**Differences from Existing Data Locations**\n| Data Location | Persistence | Cost | Typical Usage |\n| --------------------- | ---------------------------- | ------------------ | ------------------------------------------------------------ |\n| **storage** | Persists across transactions | High | State variables, permanent contract data |\n| **memory** | Temporary (function scope) | Medium | Local variables, function operations |\n| **calldata** | Read-only, external inputs | Low | External function parameters |\n| **Transient Storage** | Only within one transaction | Lower than storage | Ephemeral data used across calls within the same transaction |\n\n# Sending Ether\n\n## Overview\n\n| **Method**   | **Gas Forwarded**                        | **On Failure**             | **Return Type**                | **Recommended Usage**             |\n| ------------ | ---------------------------------------- | -------------------------- | ------------------------------ | --------------------------------- |\n| **transfer** | 2,300 gas (fixed)                        | Auto-reverts               | No return (reverts)            | Not recommended                   |\n| **send**     | 2,300 gas (fixed)                        | Does not revert            | bool (success/fail)            | Not recommended                   |\n| **call**     | All remaining gas (or a specified value) | Does not revert by default | (bool, bytes) (success + data) | Recommended with reentrancy guard |\n\n### transfer\n\n-   Forwards a **fixed 2,300 gas** to the recipient’s fallback/receive function.\n-   If the call fails (e.g., the fallback function uses more than 2,300 gas or reverts), `transfer` will automatically revert the entire transaction.\n-   If future Ethereum upgrades raise the fallback gas cost or the logic changes, `transfer` might break.\n\n```solidity\nfunction transfer(address payable _to, uint256 _amount) external {\n    _to.transfer(_amount);\n    // If it fails, entire function reverts automatically\n}\n```\n\n### send\n\n-   Also forwards 2,300 gas to the recipient’s fallback function.\n-   Does not revert on failure by default. Instead, it returns false if the call fails.\n-   Generally considered obsolete in favor of `transfer`, or `call`.\n\n```solidity\nfunction send(address payable _to, uint256 _amount) external {\n    bool success = _to.send(_amount);\n    require(success, \"Send failed\");\n}\n```\n\n### call\n\n```solidity\n(bool success, bytes memory data) = recipient.call{value: amount, gas: gasAmount}(\"\");\n\n```\n\n-   Forwards all remaining gas by default, or a specified amount if you use `gas: gasAmount`.\n-   Does not automatically revert; you must handle the success boolean.\n-   `call` is more future-proof and flexible. Recommended for most use cases with reentrancy guards or checks-effects-interactions pattern.\n\nSimple Ether send:\n\n```solidity\nfunction flexibleCall(address payable _to, uint256 _amount) external {\n    (bool success, ) = _to.call{value: _amount}(\"\");\n    require(success, \"Call failed\");\n}\n```\n\nCalling a function with data:\n\n```solidity\nfunction callFunction(address _contract, bytes memory _data, uint256 _amount) external {\n    (bool success, bytes memory returnedData) = _contract.call{value: _amount}(_data);\n    require(success, \"Low-level call failed\");\n    // returnedData may contain a return value\n}\n```\n\n### Best Practices\n\n-   `transfer` and `send` are no longer recommended in most modern Solidity patterns because of their 2,300 gas limit and potential for breakage if fallback logic changes.\n-   `call` with proper error handling (checking the return boolean) and reentrancy protections is the current best practice for sending Ether.\n\n# Function Selector\n\nA **function selector** is a **4-byte (8-hex-digit)** identifier for a function. When a contract is called, **the first 4 bytes** of the calldata are used to determine which function should be invoked within the contract.\n\n1. **Location**: The function selector resides at the **start** of the transaction’s data (calldata).\n2. **Purpose**: It **selects** which function in the contract to call. If a contract doesn’t have a matching selector, it triggers the fallback or receive function (if defined).\n\n## How is the Function Selector Computed?\n\nThe function selector for a given function is computed as the **first 4 bytes** of the **Keccak-256 hash** of the function’s **signature string**.\n\n```solidity\nbytes32 hash = keccak256(\"transfer(address,uint256)\");\nbytes4 selector = bytes4(hash);  // first 4 bytes\n```\n\n## Layout of Calldata\n\nWhen you call a function on a contract via a low-level call or transaction, the calldata typically follows this format:\n\n| **Bytes Range** | **Purpose**                      |\n| --------------- | -------------------------------- |\n| 0x00 - 0x03     | Function selector (4 bytes)      |\n| 0x04 - end      | Encoded function arguments (ABI) |\n\nFor instance, a call to `transfer(address to, uint256 amount)` might have:\n\n-   **First 4 bytes**: `0xa9059cbb` (the selector).\n-   **Next 32 bytes**: Encoded `to` address (padded to 32 bytes).\n-   **Next 32 bytes**: Encoded `amount` (256-bit integer).\n\n## Function Overloading and Selectors\n\nSolidity supports function overloading: multiple functions can share the same name but have different parameter types.\n\n-   Each overloaded function has a unique signature string (because the parameter types differ).\n-   This results in different keccak-256 hashes and thus different 4-byte selectors.\n\n```solidity\nfunction foo(uint256 x) external { /* ... */ }\nfunction foo(uint256 x, uint256 y) external { /* ... */ }\n```\n\n## Collision Issues\n\n-   The function selector is derived from: `bytes4(keccak256(functionSignatureString))`.\n-   Because it’s only 4 bytes, there are `2^32` possible selectors, which is about 4.29 billion unique values.\n-   In theory (and sometimes in practice), **two different function signatures** can **hash** to the same 4-byte prefix. This is called a **collision**.\n-   In most modern Solidity compilers, the compiler **fails** or warns at compile time if it detects a collision among the function signatures in your contract.\n\n```solidity\ncontract WontCompile {\n    // function selector of collate_propagate_storage: 0x42966c68\n    function collate_propagate_storage(bytes16 x) external {}\n    // function selector of burn: 0x42966c68\n    function burn(uint256 amount) external {}\n}\n```\n\n# Call \u0026 Delegatecall\n\n## Introduction to Low-Level Calls\n\nIn Solidity, you can interact with other contracts or addresses at a low level using:\n\n-   `call`\n-   `delegatecall`\n-   (less common) `staticcall` (for read-only calls)\n\nThese are lower-level functions than the usual contract function calls because they bypass the Solidity function name → selector → ABI encoding process (unless you manually encode/decode arguments and return data). They return success/failure booleans and raw byte data rather than automatically reverting on failure or decoding data.\n\n### Why Use Low-Level Calls?\n\n1. **Dynamic function calls**: If you only know at runtime which contract or function signature you’re calling.\n2. **Proxies**: Common pattern for upgradeable contracts or decoupling logic from storage.\n3. **Manual gas management**: You can specify the exact gas or handle reverts manually.\n\n## `call`\n\n`call` allows you to call a specified address (contract or EOA) with custom calldata, value (Ether), and an optional gas parameter.\n\n```solidity\n(bool success, bytes memory returnedData) = targetAddress.call{value: etherAmount, gas: gasAmount}(calldata);\n```\n\n### Behavior\n\n-   **Does Not Auto-Revert**: If the call fails (e.g., the target reverts), `success` will be `false`. The state changes in your contract up to that point remain unless you manually revert.\n-   **Returns Raw Data**: `returnedData` is the raw bytes the target contract returned. You must decode it if you expect a specific type (e.g., an integer or a boolean).\n-   **Forwards Gas**: By default, `call` will forward all remaining gas. You can specify a `gas: someAmount` to limit it.\n-   **Potential Reentrancy**: Because you may be forwarding a lot of gas, be mindful of reentrancy vulnerabilities if your contract’s state is updated before calling out.\n\n```solidity\nfunction callTransfer(address _token, address _to, uint256 _amount) external {\n    // Encode the function selector and arguments for an ERC20 transfer\n    bytes memory data = abi.encodeWithSelector(\n        bytes4(keccak256(\"transfer(address,uint256)\")),\n        _to,\n        _amount\n    );\n\n    // Low-level call\n    (bool success, bytes memory returnData) = _token.call(data);\n\n    require(success, \"call to transfer failed\");\n\n    // Optionally decode the returned data (many ERC20s return bool, but not all)\n    // bool transferSuccess = abi.decode(returnData, (bool));\n}\n```\n\n## `delegatecall`\n\n`delegatecall` is similar to `call` but crucially **executes the code of the target contract in the context of the caller’s state**. This is the foundation for **proxy** contracts or **upgradeable** contract patterns.\n\n```solidity\n(bool success, bytes memory returnedData) = targetAddress.delegatecall(calldata);\n```\n\n### Behavior\n\n-   **Executes in Caller’s Context**:\n    -   `msg.sender` and `msg.value` remain the same as in the original call that reached the caller.\n    -   Any storage changes (writes) made by the executed code affect the caller contract’s storage layout.\n-   **No Ether Transfer**:\n    -   Unlike `call`, you can’t directly send Ether with `delegatecall`. It only executes code with the current call’s context.\n-   **State \u0026 Storage Layout**:\n    -   You must ensure the storage layout of the caller and the target match if the target code writes to storage. Mismatched layouts lead to corruption or undefined behavior.\n-   **Returns**:\n    -   Similar to `call`, you get `(bool success, bytes memory returnData)`. You must handle them manually.\n\n```solidity\ncontract Proxy {\n    address public implementation; // Points to logic contract\n\n    constructor(address _impl) {\n        implementation = _impl;\n    }\n\n    fallback() external payable {\n        // Forward all calls to 'implementation' using delegatecall\n        (bool success, bytes memory data) = implementation.delegatecall(msg.data);\n        if (!success) {\n            assembly {\n                revert(add(data, 32), mload(data))\n            }\n        }\n        assembly {\n            return(add(data, 32), mload(data))\n        }\n    }\n}\n```\n\n## `staticcall`\n\n`staticcall` is another low-level function used for read-only calls. It reverts if the called code attempts to modify state (like writing to storage or emitting events).\n\n```solidity\n(bool success, bytes memory returnData) = targetAddress.staticcall(calldata);\n```\n\n## Comparison\n\n| Aspect                     | call                                                                  | delegatecall                                                                                            |\n| -------------------------- | --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |\n| **State Context**          | Runs in the **target’s** context. Writes in the **target’s** storage. | Runs in the **caller’s** context. Writes in the **caller’s** storage.                                   |\n| **msg.sender / msg.value** | **msg.sender** is the caller (the contract executing `call`).         | **msg.sender** remains the original external address or higher-level caller.                            |\n| **Ether Transfer**         | You can send Ether along with it (`value: X`).                        | No direct Ether transfer is possible.                                                                   |\n| **Common Use Case**        | Directly calling external contracts, optionally sending Ether.        | Proxy patterns, libraries, or upgradeable contracts (code is borrowed but state remains in the caller). |\n| **Gas Forwarding**         | Forwards all remaining gas unless specified otherwise.                | Same, but in the caller’s context (no Ether).                                                           |\n\n## Security \u0026 Best Practices\n\n1. **Check Return Values**\n\n-   Both `call` and `delegatecall` return a boolean indicating success/failure. Always check it.\n\n2. **Handle returnData**\n\n-   If the called function returns data, decode it if you care about it.\n-   If the call reverts with a reason string, that’s included in `returnData`. You can bubble it up using inline assembly or revert with your own error.\n\n3. **Protect Against Reentrancy**\n\n-   If you use `call` to forward large amounts of gas, your contract can be reentered. Use patterns like **Checks-Effects-Interactions** or **ReentrancyGuard**.\n\n4. **Proxy Storage Layout**\n\n-   With `delegatecall`, ensure the **implementation** contract’s storage layout is compatible with the proxy contract’s layout. If you add new variables in the implementation or reorder them, you can break or corrupt the proxy’s storage.\n\n5. **Avoid Arbitrary Delegatecalls**\n\n-   Letting users choose any target for `delegatecall` is a critical security hole. Restrict target addresses or function signatures if you want safe upgrade patterns.\n\n6. **Gas Estimation**\n\n-   Low-level calls might confuse the Solidity gas estimator. You sometimes need to manually specify gas or test thoroughly to avoid out-of-gas issues.\n\n# CREATE, CREATE2, Create3, and CreateX\n\n## CREATE\n\n`CREATE` is the most basic and commonly used opcode for contract deployment. It works as follows:\n\n-   Deploys contracts dynamically within other contracts\n-   More cost-effective for deploying multiple contracts\n-   The resulting contract address is determined by the deployer's address and nonce\n-   Doesn't provide address predictability\n\nUsing `CREATE`, the address of the newly deployed contract is determined by:\n\n-   `address = rightmost 160 bits of keccak256(rlp(sender, nonce))`\n\n1. `sender`: The address that deploys the contract (an EOA or another contract).\n2. `nonce`: The internal transaction count (nonce) of the sender at the time of creation.\n\n```solidity\nfunction deployWithCREATE() external returns (address childAddress) {\n    // Simple CREATE deployment\n    Child child = new Child();\n    childAddress = address(child);\n\n    emit Deployed(childAddress, 0);\n}\n```\n\n## CREATE2\n\n`CREATE2` was designed to let you compute a contract’s address in advance, based on a salt and the contract’s init code, enabling so-called “counterfactual deployments.”\n\n`address = rightmost 160 bits of keccak256(0xff | sender | salt | keccak256(init_code))`\n\nWhere:\n\n-   `0xff`: A constant single byte to avoid collisions with regular `CREATE`.\n-   `sender`: The address that issues the `CREATE2`.\n-   `salt`: A 32-byte value supplied by the deployer.\n-   `keccak256(init_code)`: The hash of the contract’s creation bytecode.\n\nNormally, CREATE2 is used with the [Deterministic Deployment Proxy contract](https://github.com/Arachnid/deterministic-deployment-proxy) to ensure a fixed `msg.sender` address.\n\n```solidity\ncontract Child {\n    uint public x;\n    constructor(uint a) {\n        x = a;\n    }\n}\n\ncontract Parent {\n    function deployWithCREATE2(bytes32 salt, uint arg) public {\n        // This complicated expression just tells you how the address\n        // can be pre-computed. It is just there for illustration.\n        // You actually only need ``new Child{salt: salt}(arg)``.\n        address predictedAddress = address(uint160(uint(keccak256(abi.encodePacked(\n            bytes1(0xff),\n            address(this),\n            salt,\n            keccak256(abi.encodePacked(\n                type(Child).creationCode,\n                abi.encode(arg)\n            ))\n        )))));\n\n        Child child = new Child{salt: salt}(arg);\n        require(address(child) == predictedAddress);\n    }\n}\n```\n\n## Create3\n\n`Create3` is not an opcode but a method combining `CREATE` and `CREATE2`:\n\n-   Generates deterministic contract addresses without depending on the contract's bytecode\n-   Address is based **only on `msg.sender` and `salt`**\n-   You can use **different constructor arguments** on multiple chains\n-   More expensive than `CREATE` or `CREATE2` (extra ~55k gas)\n-   Allows deploying contracts to the same address across multiple EVM-compatible blockchains\n\nUsually, Create3 is used with [Create3 Factory](https://github.com/ZeframLou/create3-factory)\n\n```solidity\n  /**\n    @notice Creates a new contract with given `_creationCode` and `_salt`\n    @param _salt Salt of the contract creation, resulting address will be derivated from this value only\n    @param _creationCode Creation code (constructor) of the contract to be deployed, this value doesn't affect the resulting address\n    @param _value In WEI of ETH to be forwarded to child contract\n    @return addr of the deployed contract, reverts on error\n  */\n  function create3(bytes32 _salt, bytes memory _creationCode, uint256 _value) internal returns (address addr) {\n    // Creation code\n    bytes memory creationCode = PROXY_CHILD_BYTECODE;\n\n    // Get target final address\n    addr = addressOf(_salt);\n    if (codeSize(addr) != 0) revert TargetAlreadyExists();\n\n    // Create CREATE2 proxy\n    address proxy; assembly { proxy := create2(0, add(creationCode, 32), mload(creationCode), _salt)}\n    if (proxy == address(0)) revert ErrorCreatingProxy();\n\n    // Call proxy with final init code\n    (bool success,) = proxy.call{ value: _value }(_creationCode);\n    if (!success || codeSize(addr) == 0) revert ErrorCreatingContract();\n  }\n```\n\n## Comparison\n\n| Feature             | CREATE  | CREATE2  | Create3   |\n| ------------------- | ------- | -------- | --------- |\n| Address Determinism | No      | Yes      | Yes       |\n| Bytecode Dependency | Yes     | Yes      | No        |\n| Multi-chain Support | Limited | Possible | Excellent |\n| Gas Cost            | Lowest  | Medium   | Highest   |\n\n## CreateX\n\n[CreateX](https://github.com/pcaversaccio/createx) is a factory smart contract designed to simplify and enhance the usage of CREATE, CREATE2, and Create3:\n\n-   Provides a unified interface for different contract creation methods\n-   Offers additional features and optimizations\n\n# ABI Encode \u0026 Decode\n\n# References\n\n-   [Solidity Docs](https://docs.soliditylang.org/en/latest/)\n-   [Solidity by Example](https://solidity-by-example.org/)\n-   [Solidity Cheatsheet and Best practices](https://github.com/manojpramesh/solidity-cheatsheet/)\n-   [Solidity Gas Optimization Techniques: Loops](https://hackmd.io/@totomanov/gas-optimization-loops#Solidity-Gas-Optimization-Techniques-Loops)\n-   [Gas Optimization In Solidity: Strategies For Cost-Effective Smart Contracts](https://hacken.io/discover/solidity-gas-optimization/)\n-   [Understanding the Function Selector in Solidity](https://www.rareskills.io/post/function-selector)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadnpark%2Fsolidity-cheatsheet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadnpark%2Fsolidity-cheatsheet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadnpark%2Fsolidity-cheatsheet/lists"}