库合约 #
一、库合约概述 #
1.1 什么是库合约 #
库合约是一种特殊的合约,用于封装可复用的代码,不能有状态变量,不能继承或被继承。
solidity
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "Overflow");
return c;
}
}
1.2 库合约的作用 #
| 作用 | 说明 |
|---|---|
| 代码复用 | 封装通用功能 |
| Gas优化 | 内联调用节省Gas |
| 类型安全 | 编译时检查 |
| 命名空间 | 组织代码结构 |
二、库合约定义 #
2.1 基本语法 #
solidity
library LibraryName {
function functionName(parameters) visibility returns (returnTypes) {
// 函数体
}
}
2.2 库合约限制 #
solidity
library MyLibrary {
// ✓ 允许:函数
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
// ✓ 允许:结构体
struct Data {
uint256 value;
}
// ✓ 允许:枚举
enum Status { Active, Inactive }
// ✗ 不允许:状态变量
// uint256 public value;
// ✗ 不允许:继承
// contract Child is Parent {}
// ✗ 不允许:被继承
// contract Child is MyLibrary {}
// ✗ 不允许:接收ETH
// function deposit() public payable {}
}
三、库合约使用 #
3.1 直接调用 #
solidity
library Math {
function square(uint256 x) internal pure returns (uint256) {
return x * x;
}
}
contract UseLibrary {
function calculate(uint256 x) public pure returns (uint256) {
return Math.square(x);
}
}
3.2 using for #
solidity
library Math {
function square(uint256 x) internal pure returns (uint256) {
return x * x;
}
function cube(uint256 x) internal pure returns (uint256) {
return x * x * x;
}
}
contract UsingFor {
using Math for uint256;
function calculate(uint256 x) public pure returns (uint256, uint256) {
return (x.square(), x.cube()); // 等价于 Math.square(x), Math.cube(x)
}
}
3.3 引用类型参数 #
solidity
library ArrayUtils {
function sum(uint256[] memory arr) internal pure returns (uint256) {
uint256 total = 0;
for (uint256 i = 0; i < arr.length; i++) {
total += arr[i];
}
return total;
}
function push(uint256[] storage arr, uint256 value) internal {
arr.push(value);
}
}
contract UseArrayLibrary {
using ArrayUtils for uint256[];
uint256[] public numbers;
function getSum() public view returns (uint256) {
return numbers.sum();
}
function addNumber(uint256 value) public {
numbers.push(value);
}
}
四、常见库合约 #
4.1 SafeMath #
solidity
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
}
4.2 Address库 #
solidity
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value");
}
}
4.3 Strings库 #
solidity
library Strings {
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) return "0";
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
}
五、最佳实践 #
5.1 库函数可见性 #
solidity
library MyLibrary {
// internal:内联调用,节省Gas
function internalFunc(uint256 x) internal pure returns (uint256) {
return x * 2;
}
// public:外部可调用,需要delegatecall
function publicFunc(uint256 x) public pure returns (uint256) {
return x * 2;
}
}
5.2 using for使用 #
solidity
contract BestPractices {
using SafeMath for uint256;
using Address for address;
uint256 public value;
function addValue(uint256 amount) public {
value = value.add(amount); // 使用库函数
}
function checkContract(address addr) public view returns (bool) {
return addr.isContract(); // 使用库函数
}
}
六、总结 #
库合约要点:
| 特性 | 说明 |
|---|---|
| 定义 | library LibraryName { ... } |
| 限制 | 无状态变量,不能继承 |
| 使用 | 直接调用或using for |
| 可见性 | internal/public |
使用建议:
- 使用库封装通用功能
- 使用
using for简化调用 - internal函数节省Gas
- 参考OpenZeppelin库合约
接下来,让我们学习高级特性!
最后更新:2026-03-27