You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
-[Library for Struct Extensions](#library-for-struct-extensions)
110
+
-[Best Practices](#best-practices-2)
104
111
-[References](#references)
105
112
106
113
# Getting Started
@@ -1566,6 +1573,182 @@ contract D is B, C {
1566
1573
- Overlapping storage layouts from multiple parents can cause confusion or even storage collisions.
1567
1574
- Ensure each parent contract uses distinct state variable slots (this usually happens naturally if you’re just inheriting standard contracts without complicated overrides).
1568
1575
1576
+
# Libraries
1577
+
1578
+
- In Solidity, **libraries** are special types of contracts intended to provide reusable code.
1579
+
- They can be thought of as utility or helper modules that other contracts can call without needing to implement the same logic repeatedly.
1580
+
- Libraries help keep code DRY (Don’t Repeat Yourself), save gas, and improve readability.
1581
+
1582
+
## Key Characteristics of Libraries
1583
+
1584
+
-**No Ether**
1585
+
1586
+
- Libraries **cannot** hold Ether (i.e., they cannot have a balance).
1587
+
- Any attempt to send Ether to a library will fail.
1588
+
1589
+
-**No State Variables**
1590
+
1591
+
- Libraries cannot store or modify their own state; they are stateless.
1592
+
1593
+
-**No Inheritance**
1594
+
1595
+
- Libraries cannot be inherited or extend other contracts (nor can you inherit from a library).
1596
+
1597
+
-**Linked at Compile Time or Deployment Time**
1598
+
-**Internal library functions** are typically inlined or statically called.
1599
+
-**External library functions** can be deployed and then “linked” to your contract.
1600
+
1601
+
## Library Function Types
1602
+
1603
+
Solidity libraries support **two** ways of using their functions:
1604
+
1605
+
-**Internal Functions**
1606
+
1607
+
- If a library function is declared `internal`, it is inlined into the calling contract’s bytecode at compile time (similar to macros).
1608
+
- This reduces overhead since no external call is made.
1609
+
1610
+
-**External Functions**
1611
+
1612
+
- If a library function is declared `public` or `external`, the calling contract will **delegatecall** into the library at runtime.
1613
+
- This can save bytecode size in the calling contract but introduces a small overhead for each external call.
1614
+
- You must **deploy** the library contract first and link it before deploying the final contract.
1615
+
1616
+
### Example: Internal Library
1617
+
1618
+
Most libraries are used as **internal** because it’s more gas-efficient (no external call) and simpler to manage.
1619
+
1620
+
```solidity
1621
+
// MathLib.sol
1622
+
pragma solidity ^0.8.29;
1623
+
1624
+
library MathLib {
1625
+
function add(uint256 a, uint256 b) internal pure returns (uint256) {
1626
+
return a + b;
1627
+
}
1628
+
1629
+
function multiply(uint256 a, uint256 b) internal pure returns (uint256) {
1630
+
return a * b;
1631
+
}
1632
+
}
1633
+
1634
+
// TestMath.sol
1635
+
pragma solidity ^0.8.21;
1636
+
1637
+
import "./MathLib.sol";
1638
+
1639
+
contract TestMath {
1640
+
function testAdd(uint256 x, uint256 y) public pure returns (uint256) {
1641
+
return MathLib.add(x, y);
1642
+
}
1643
+
1644
+
function testMultiply(uint256 x, uint256 y) public pure returns (uint256) {
1645
+
return MathLib.multiply(x, y);
1646
+
}
1647
+
}
1648
+
```
1649
+
1650
+
-`MathLib.add` and `MathLib.multiply` are called from `TestMath` without an external call because they’re `internal` functions in a library.
1651
+
- The compiler will inline or statically link these calls, increasing `TestMath`’s bytecode size, but saving on runtime gas costs.
1652
+
1653
+
### Example: External Library
1654
+
1655
+
You can define a library with public or external functions. In that case, your contract calls the library via delegatecall at runtime.
1656
+
1657
+
```solidity
1658
+
// ExternalLib.sol
1659
+
pragma solidity ^0.8.29;
1660
+
1661
+
library ExternalLib {
1662
+
function externalAdd(uint256 a, uint256 b) external pure returns (uint256) {
1663
+
return a + b;
1664
+
}
1665
+
}
1666
+
```
1667
+
1668
+
To use this library in another contract:
1669
+
1670
+
```solidity
1671
+
pragma solidity ^0.8.29;
1672
+
1673
+
import "./ExternalLib.sol";
1674
+
1675
+
contract UseExternalLib {
1676
+
// The compiler inserts a reference that must be linked to the ExternalLib deployed address
1677
+
function compute(uint256 x, uint256 y) public pure returns (uint256) {
1678
+
return ExternalLib.externalAdd(x, y);
1679
+
}
1680
+
}
1681
+
```
1682
+
1683
+
-**Deployment**: You must first deploy `ExternalLib` and then link its address into `UseExternalLib`’s bytecode.
1684
+
- At runtime, calls to `ExternalLib.externalAdd` happen via DELEGATECALL.
1685
+
1686
+
## Library for Struct Extensions
1687
+
1688
+
- A popular pattern is to write libraries that extend built-in types or custom structs with `using for`.
1689
+
- This adds **library functions** as if they were member functions of the type.
using ArrayUtils for uint256[]; // "using for" directive
1707
+
1708
+
uint256[] private data;
1709
+
1710
+
function addValue(uint256 value) external {
1711
+
data.push(value);
1712
+
}
1713
+
1714
+
function findValue(uint256 value) external view returns (int256) {
1715
+
// We can now call findIndex() as if it's a member of data
1716
+
return data.findIndex(value);
1717
+
}
1718
+
}
1719
+
```
1720
+
1721
+
- The `using ArrayUtils for uint256[];` directive allows you to call `data.findIndex(value)` directly.
1722
+
- This improves readability and encapsulates utility logic for arrays.
1723
+
1724
+
## Best Practices
1725
+
1726
+
-**Keep Libraries Focused**
1727
+
1728
+
- A library should do **one thing** well—e.g., math operations, array helpers, address utilities, etc.
1729
+
1730
+
-**Avoid Large External Libraries for Single Contracts**
1731
+
1732
+
- 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.
1733
+
1734
+
-**Mark Functions `pure` or `view` Where Possible**
1735
+
1736
+
- Avoid unintentional state modifications in libraries unless that’s the library’s explicit purpose.
1737
+
- This also ensures your library is safer and can be reasoned about more easily.
1738
+
1739
+
-**`using for` Pattern**
1740
+
1741
+
- Great for readability and a more object-oriented feel.
1742
+
- Clarifies which types are extended by the library.
1743
+
1744
+
-**Security**
1745
+
1746
+
- Libraries can mutate the caller’s storage if called with `delegatecall`. Ensure your library code is trusted and thoroughly reviewed.
1747
+
1748
+
-**Solady, OpenZeppelin and Other Standard Libraries**
1749
+
1750
+
- Before writing your own, check if established libraries (e.g., Solady, OpenZeppelin) cover your needs. This reduces risk and leverages well-audited code.
0 commit comments