Solidity Libraries
A library is a block that groups reusable functions. It holds no state of its own, and its internal functions become part of the caller.
A library groups one reusable computation
DoubleLib holds one function. Calculator calls it by library name.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
library DoubleLib {
function double(uint256 x) internal pure returns (uint256) {
return x * 2;
}
}
contract Calculator {
function doubled(uint256 x) public pure returns (uint256) {
return DoubleLib.double(x);
}
}
An internal function is inlined into the caller
Inlined means the function code is copied into the caller at compile time. The caller stores the result in its own state.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
library BonusLib {
function bonus(uint256 score) internal pure returns (uint256) {
return score + 10;
}
}
contract Player {
uint256 public score;
function setScore(uint256 s) public {
score = s;
}
function addBonus() public {
score = BonusLib.bonus(score);
}
}
A library cannot hold state
A state variable inside a library fails to compile. Libraries compute, they do not store.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
library BadLib {
uint256 public stored;
function one() internal pure returns (uint256) {
return 1;
}
}
Example
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
library PercentLib {
function portion(uint256 amount, uint256 percent) internal pure returns (uint256) {
return amount * percent / 100;
}
function afterDiscount(uint256 price, uint256 percent) internal pure returns (uint256) {
return price - portion(price, percent);
}
}
contract Shop {
uint256 public price;
function setPrice(uint256 p) public {
price = p;
}
function discounted(uint256 percent) public view returns (uint256) {
return PercentLib.afterDiscount(price, percent);
}
}
Key points
- Library: a block of reusable functions with no state of its own.
- Use a library to share one computation across many contracts.
- An internal library function is copied into the caller when the code compiles.
- Call an internal library function by its library name and function name.
- A library with only internal functions needs no separate deployment.
In this example, PercentLib holds two functions, and afterDiscount reuses portion inside the library. Shop stores only the price. Its discounted function asks the library for the price after the discount and returns that value.
Note
a library keeps no balances and no storage, so the caller owns every stored value.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Remix IDE
Exercise
What happens to an internal library function at compile time?