库合约 #

一、库合约概述 #

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