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.