# Solidity极简入门: 17. 库合约 站在巨人的肩膀上


By [0xAA](https://paragraph.com/@wtfacademy) · 2022-04-20

---

我最近在重新学solidity，巩固一下细节，也写一个“Solidity极简入门”，供小白们使用（编程大佬可以另找教程），每周更新1-3讲。

欢迎关注我的推特：[@0xAA\_Science](https://twitter.com/0xAA_Science)

WTF技术社群discord，内有加微信群方法：[链接](https://discord.gg/5akcruXrsk)

所有代码和教程开源在github（1024个star发课程认证，2048个star发社群NFT）: [github.com/AmazingAng/WTFSolidity](https://github.com/AmazingAng/WTFSolidity)

* * *

这一讲，我们用`ERC721`的引用的库合约`String`为例介绍solidity中的库合约（`library`），并总结了常用的库函数。

库函数
---

库函数是一种特殊的合约，主要是为了提升solidity代码的复用性和减少gas fee而存在。库合约一般都是一些好用的函数合集（库函数），由大神或者项目方创作，咱们站在巨人的肩膀上，会用就行了。

![库合约：站在巨人的肩膀上](https://storage.googleapis.com/papyrus_images/dce2c3b857a2ac6998a36cca241c70d4416c8ecdf960b1039a0f4460182dfba6.jpg)

库合约：站在巨人的肩膀上

他和普通合约主要有以下几点不同：

*   不能存在状态变量
    
*   不能够继承或被继承
    
*   不能接收以太币
    
*   不可以被销毁
    

### String库合约

`String`库合约是将uint256类型转换为相应的string类型的代码库，样例代码如下：

    library Strings {
        bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
    
        /**
         * @dev Converts a `uint256` to its ASCII `string` decimal representation.
         */
        function toString(uint256 value) public pure returns (string memory) {
            // Inspired by OraclizeAPI's implementation - MIT licence
            // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
    
            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);
        }
    
        /**
         * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
         */
        function toHexString(uint256 value) public pure returns (string memory) {
            if (value == 0) {
                return "0x00";
            }
            uint256 temp = value;
            uint256 length = 0;
            while (temp != 0) {
                length++;
                temp >>= 8;
            }
            return toHexString(value, length);
        }
    
        /**
         * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
         */
        function toHexString(uint256 value, uint256 length) public pure returns (string memory) {
            bytes memory buffer = new bytes(2 * length + 2);
            buffer[0] = "0";
            buffer[1] = "x";
            for (uint256 i = 2 * length + 1; i > 1; --i) {
                buffer[i] = _HEX_SYMBOLS[value & 0xf];
                value >>= 4;
            }
            require(value == 0, "Strings: hex length insufficient");
            return string(buffer);
        }
    }
    

他主要包含两个函数，`toString()`将`uint256`转为`string`，`toHexString()`将`uint256`转换为`16进制`，在转换为`string`。

### 如何使用库合约

我们用`String`库函数的`toHexString()`来演示两种使用库合约中函数的办法。

**1\. 利用using for指令**：

指令 `using A for B;` 可用于附加库函数（从库 `A`）到任何类型（`B`）。添加完指令后，库`A`中的函数会自动添加为`B`类型变量的成员，可以直接调用。`注意`：在调用的时候，这个变量会被当作第一个参数传递给函数：

        // 利用using for指令
        using Strings for uint256;
        function getString1(uint256 _number) public pure returns(string memory){
            // 库函数会自动添加为uint256型变量的成员
            return _number.toHexString();
        }
    

**2\. 通过库合约名称调用库函数：**

        // 直接通过库合约名调用
        function getString2(uint256 _number) public pure returns(string memory){
            return Strings.toHexString(_number);
        }
    

我们部署合约并输入`170`测试一下，两种方法均能返回正确的16进制string `“0xaa”`。证明我们调用库函数成功！

![成功调用库函数](https://storage.googleapis.com/papyrus_images/5af8811d5da956bd98f2f0e14af729b6719ac588de2f01c42c16e7f52abb6148.png)

成功调用库函数

### 总结

这一讲，我们用`ERC721`的引用的库函数`String`为例介绍solidity中的库函数（`Library`）。99%的开发者都不需要自己去写库合约，会用大神写的就可以了。我们只需要知道什么情况该用什么库合约。常用的有：

1.  [String](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/4a9cc8b4918ef3736229a5cc5a310bdc17bf759f/contracts/utils/String.sol)：将uint256转换为String
    
2.  [Address](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/4a9cc8b4918ef3736229a5cc5a310bdc17bf759f/contracts/utils/Address.sol)：判断某个地址是否为合约地址
    
3.  [Create2](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/4a9cc8b4918ef3736229a5cc5a310bdc17bf759f/contracts/utils/Create2.sol)：更安全的使用Create2 EVM opcode
    
4.  [Arrays](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/4a9cc8b4918ef3736229a5cc5a310bdc17bf759f/contracts/utils/Arrays.sol)：跟数组相关的库函数

---

*Originally published on [0xAA](https://paragraph.com/@wtfacademy/solidity-17)*
