美文网首页
12. Solidity:库合约(Library)

12. Solidity:库合约(Library)

作者: 泡泡龙吐泡泡 | 来源:发表于2023-10-06 09:18 被阅读0次

    12.1 库合约

    库合约是一种特殊的合约,为了提升solidity代码的复用性和减少gas而存在。库合约一般都是一些好用的函数合集(库函数),由大神或者项目方创作。
    他和普通合约主要有以下几点不同:

    1. 不能存在状态变量
    2. 不能够继承或被继承
    3. 不能接收以太币
    4. 不可以被销毁

    12.2 库合约的使用

    • 一个简单的例子:通过库合约名称调用库函数
    // 库合约的定义
    library Math { // 合约名称大写开头:编码习惯
        function max(uint x, uint y) internal pure returns (uint) {
            return x >= y ? x : y;
        }
    }
    
    contract Test {
        function testMax(uint _x, uint _y) external pure returns (uint) {
            // 库函数的使用
            return Math.max(_x, _y);
        }
    }
    

    定义了一个库合约Math,实现一个返回两个数中较大值的函数。一般库合约中函数使用internal修饰,如果想要外部访问可以使用public修饰,使用external和private修饰是没有意义的。

    测试合约Test中使用Math.max对库合约中的函数进行调用。

    • 另一个简单的例子:利用using for指令
    library ArrayLib {
        function find(uint[] storage arr, uint x) internal view returns (uint) {
            for (uint i = 0; i < arr.length; i++) {
                if (arr[i] == x) {
                    return i;
                }
            }
            revert("not found");
        }
    }
    
    
    contract TestArray {
        // 使用库合约:using for,使库合约应用到库函数的第一个参数uint[],uint[]就拥有了库合约的所有功能
        using ArrayLib for uint[];
        uint[] public arr = [3,2,1,5,8,0];
    
        function testFind(uint _x) external view returns (uint i) {
            // return ArrayLib.find(arr, 2);
            return arr.find(_x);
        }
    }
    

    库合约ArrayLib中,实现了一个查找数组元素索引的函数。

    测试合约TestArray中使用using for语法调用库合约的功能。指令using A for B;可用于附加库函数(从库 A)到任何类型B。添加完指令后,库A中的函数会自动添加为B类型变量的成员,可以直接调用。

    注意:在调用的时候,这个变量会被当作第一个参数传递给函数

    12.3 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);
        }
    }
    

    String库合约主要包含三个函数:

    1. toString(uint256 value):将uint256转为string。
    2. toHexString(uint256 value):将uint256转为16进制,再转为string。
    3. toHexString(uint256 value, uint256 length):将uint256转为固定长度的16进制string类型。
      使用示例:
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.4;
    
    import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/4a9cc8b4918ef3736229a5cc5a310bdc17bf759f/contracts/utils/Strings.sol";
    
    contract Test {
        using Strings for uint256;
    
        function TestToString(uint256 _x) external pure returns (string memory) {
            return _x.toString();
        }
    
        function TestToHexString(uint256 _x) external pure returns (string memory) {
            return _x.toHexString();
        }
    
        function TestToHexString2(uint256 _x, uint256 _y) external pure returns (string memory) {
            return _x.toHexString(_y);
        }
    }
    

    运行结果:


    strings库合约的使用

    常见的库合约举例:

    1. String:将uint256转换为String
    2. Address:判断某个地址是否为合约地址
    3. Create2:更安全的使用Create2 EVM opcode
    4. Arrays:跟数组相关的库函数

    相关文章

      网友评论

          本文标题:12. Solidity:库合约(Library)

          本文链接:https://www.haomeiwen.com/subject/gxkcbdtx.html