Libraries & Using For

Libraries are stateless code collections.

21.1 Libraries

Libraries are stateless code collections. They cannot have state variables (except constants), cannot receive Ether, and cannot be inherited.

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

library Math {
    function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; }
    function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; }

    function sqrt(uint256 y) internal pure returns (uint256 z) {   // Babylonian method
        if (y > 3) {
            z = y;
            uint256 x = y / 2 + 1;
            while (x < z) { z = x; x = (y / x + x) / 2; }
        } else if (y != 0) {
            z = 1;
        }
    }
}

library Set {
    struct Data { mapping(uint256 => bool) flags; uint256 size; }

    function insert(Data storage self, uint256 v) internal returns (bool) {   // storage pointer param
        if (self.flags[v]) return false;
        self.flags[v] = true;
        self.size++;
        return true;
    }

    function contains(Data storage self, uint256 v) internal view returns (bool) {
        return self.flags[v];
    }
}

contract UsesLibraries {
    using Set for Set.Data;
    using Math for uint256;

    Set.Data private numbers;

    function add(uint256 v) external returns (bool) { return numbers.insert(v); }   // self = numbers
  
…

21.2 Internal vs external library functions

internal library functions public/external library functions code inlined into the calling contract library deployed separately; contract linked to its address very large shared code (to stay under the 24 KB limit)

21.3 using A for B

using Lib for Type; attaches library functions to a type; the first parameter receives the value.

using Lib for *; attaches to all types.

File-level: using {f, g} for Type; with free functions (0.8.13+); using ... for T global; (for user-defined types in the same file) applies everywhere the type is used.