solady

repository·main·Indexed 25 days ago

https://github.com/vectorized/solady

A collection of gas-optimized Solidity smart contract snippets and libraries for high-performance EVM development. Version 0.1.26 provides optimized implementations for account abstractions including ERC4337, ERC6551, and ERC1271, as well as EIP7702Proxy for upgradeable EIP7702 accounts. The library includes tools for ZKsync stack compatibility analysis and supports installation via Foundry or Hardhat.

Tokens
72.9K
Snippets
159
Records
498
Agent score
85%

What's inside solady

  1. Overview of LibClone Proxy Types

    main

    LibClone provides several minimal proxy patterns optimized for different use cases:

    • Minimal Proxy: Uses the 0age pattern. It is optimized for Etherscan verification and has a small bytecode footprint. Saves 4 gas over ERC1167.
    • Minimal Proxy (PUSH0 variant): Uses the PUSH0 opcode (Shanghai upgrade). Optimized for minimal runtime gas, then minimal bytecode. Caution: Use with care as some EVM chains may not support PUSH0 immediately after the Shanghai upgrade. Functions are postfixed with _PUSH0.
    • Clones with Immutable Args (CWIA): An ERC1167 minimal proxy where immutable arguments are appended to the back of the runtime bytecode rather than being appended to the calldata. Uses the identity precompile (0x4) to copy args during deployment.
    • Minimal ERC1967 Proxy: Intended for upgrades via UUPS. This is not a transparent proxy and does not include admin logic.
    • ERC1967I Proxy: A variant of the ERC1967 proxy with a special code path. If calldatasize() == 1, it skips the delegatecall and directly returns the implementation address. This is valid if the proxy's code hash matches ERC1967I_CODE_HASH.
    • Minimal ERC1967 Beacon Proxy: Intended for upgrades via an upgradable beacon.
    • ERC1967I Beacon Proxy: A variant of the beacon proxy with the same calldatasize() == 1 optimization as the standard ERC1967I proxy.
  2. Implement EIP-712 typed structured data hashing

    main

    Use the EIP-712 contract to handle typed structured data hashing and signing.

    Important Implementation Details:

    • The contract automatically uses address(this) for the verifyingContract field.
    • It does NOT support the optional EIP-712 salt.
    • It does NOT support EIP-712 extensions.

    This implementation is optimized for gas efficiency and simplicity. If you require salt or extensions, you must modify or fork the contract.

  3. Understand EnumerableSetLib core concepts

    main

    EnumerableSetLib is a library for managing enumerable sets in storage.

    Key Characteristics:

    • Optimization: For sets with up to 3 elements, the implementation avoids storing length and indices to save gas. Once the length exceeds 3, length and indices are initialized. The amortized cost of adding elements is $O(1)$.
    • AddressSet Packing: The AddressSet implementation packs the length with the 0th entry.
    • Iteration Order: All sets except Uint8Set use a pop-and-swap mechanism for removals. This means the iteration order of elements may change when an element is removed.
    • Gas Warning: Calling values() on large sets can consume more gas than the block gas limit.
  4. Use the Receiver mixin for ETH and token safety

    main
    The Receiver mixin is designed to handle ETH transfers and safety callbacks for ERC721 and ERC1155 tokens. It optimizes gas overhead and code size by collapsing the function table and utilizing a fallback mechanism to ensure unknown calldata is processed correctly.
  5. Use MerkleTreeLib for Merkle tree generation

    main

    MerkleTreeLib is a Solidity library for generating Merkle trees.

    Important Usage Notes:

    • No Auto-Hashing: Leaves are NOT automatically hashed. If your leaves are 64 bytes long, you should hash them first to prevent second-preimage attacks.
    • No Auto-Sorting: Leaves are NOT automatically sorted.
    • Pair Hashing: The library uses pair-sorted-keccak256, making it compatible with MerkleProofLib out-of-the-box.
    • Compatibility: This library is not equivalent to OpenZeppelin or Murky implementations.
  6. Use CallContextChecker to validate call contexts

    main
    The CallContextChecker mixin provides tools to verify whether a contract is being executed via a proxy (e.g., delegatecall to an implementation) or via an EIP-7702 authority (an externally owned account pointing to a delegation). This is useful for enforcing security constraints based on how a contract is being called.
  7. SafeCastLib Overview

    main
    SafeCastLib is a Solidity library designed for safe integer casting. It provides optimized functions to cast larger integer types to smaller ones, ensuring that the operation reverts if an overflow occurs. It is specifically optimized for runtime gas efficiency in scenarios with a very high number of optimizer runs.
  8. Use EnumerableRoles mixin for multirole authorization

    main

    The EnumerableRoles mixin provides multirole authorization with the ability to enumerate holders of specific roles.

    Key Characteristics:

    • Agnostic Ownership: It is compatible with any Ownable implementation (including OpenZeppelin and LayerZero's OApp) by performing a self-staticcall to the owner() function.
    • Role Definition: It uses uint256 for roles rather than bitmasks. It performs a self-staticcall to MAX_ROLE() to determine the maximum allowed role; if MAX_ROLE() is not implemented, any uint256 role can be used.
    • Default Permissions: By default, only the owner() is authorized to call setRole. This can be customized by overriding _authorizeSetRole.
    • Compatibility Note: It is NOT compatible with OwnableRoles.
  9. Important considerations for ERC4337Factory

    main

    When using ERC4337Factory, be aware of the following architectural constraints:

    • No Admin Storage: Unlike ERC1967Factory, this factory does not store admin information on itself.
    • No Proxy Upgrading: The proxy bytecode does not contain upgrading logic. Upgrading must be performed via UUPS logic on the accounts themselves.
    • Deterministic Deployment Only: To comply with the ERC4337 standard, this factory only supports deterministic deployment methods and does not include non-deterministic options.
  10. Use MetadataReaderLib for robust contract metadata reading

    main

    The MetadataReaderLib library provides best-effort methods to read contract metadata (like names, symbols, and decimals) from external addresses. These operations are designed to be robust: they should NOT revert as long as sufficient gas is provided.

    If a read fails (due to a revert, no returndata, or an empty return), the library returns a default value (an empty string for strings, or 0 for uints) instead of failing the transaction.

    Reading Logic Order:

    1. Returns an empty string if the call reverts, has no returndata, or returns an empty string.
    2. Attempts to abi.decode the returndata into a string.
    3. Scans the returndata for a null byte \0 to interpret it as a null-terminated string.
  11. Perform low-level uint256 array operations

    main

    DynamicArrayLib provides minimalist, low-level uint256 array operations. These functions are recommended if you do not need syntax sugar. Many of these functions support function chaining (e.g., array.set(0, 1).set(1, 2)).

    Note: Most get and set operations do not perform bounds checking.