12. Solidity:庫(kù)合約(Library)

12.1 庫(kù)合約

庫(kù)合約是一種特殊的合約,為了提升solidity代碼的復(fù)用性和減少gas而存在。庫(kù)合約一般都是一些好用的函數(shù)合集(庫(kù)函數(shù)),由大神或者項(xiàng)目方創(chuàng)作。
他和普通合約主要有以下幾點(diǎn)不同:

  1. 不能存在狀態(tài)變量
  2. 不能夠繼承或被繼承
  3. 不能接收以太幣
  4. 不可以被銷毀

12.2 庫(kù)合約的使用

  • 一個(gè)簡(jiǎn)單的例子:通過(guò)庫(kù)合約名稱調(diào)用庫(kù)函數(shù)
// 庫(kù)合約的定義
library Math { // 合約名稱大寫(xiě)開(kāi)頭:編碼習(xí)慣
    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) {
        // 庫(kù)函數(shù)的使用
        return Math.max(_x, _y);
    }
}

定義了一個(gè)庫(kù)合約Math,實(shí)現(xiàn)一個(gè)返回兩個(gè)數(shù)中較大值的函數(shù)。一般庫(kù)合約中函數(shù)使用internal修飾,如果想要外部訪問(wèn)可以使用public修飾,使用external和private修飾是沒(méi)有意義的。

測(cè)試合約Test中使用Math.max對(duì)庫(kù)合約中的函數(shù)進(jìn)行調(diào)用。

  • 另一個(gè)簡(jiǎn)單的例子:利用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 {
    // 使用庫(kù)合約:using for,使庫(kù)合約應(yīng)用到庫(kù)函數(shù)的第一個(gè)參數(shù)uint[],uint[]就擁有了庫(kù)合約的所有功能
    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);
    }
}

庫(kù)合約ArrayLib中,實(shí)現(xiàn)了一個(gè)查找數(shù)組元素索引的函數(shù)。

測(cè)試合約TestArray中使用using for語(yǔ)法調(diào)用庫(kù)合約的功能。指令using A for B;可用于附加庫(kù)函數(shù)(從庫(kù) A)到任何類型B。添加完指令后,庫(kù)A中的函數(shù)會(huì)自動(dòng)添加為B類型變量的成員,可以直接調(diào)用。

注意:在調(diào)用的時(shí)候,這個(gè)變量會(huì)被當(dāng)作第一個(gè)參數(shù)傳遞給函數(shù)

12.3 String庫(kù)合約

String庫(kù)合約是將uint256類型轉(zhuǎn)換為相應(yīng)的string類型的代碼庫(kù),樣例代碼如下:

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庫(kù)合約主要包含三個(gè)函數(shù):

  1. toString(uint256 value):將uint256轉(zhuǎn)為string。
  2. toHexString(uint256 value):將uint256轉(zhuǎn)為16進(jìn)制,再轉(zhuǎn)為string。
  3. toHexString(uint256 value, uint256 length):將uint256轉(zhuǎn)為固定長(zhǎng)度的16進(jìn)制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);
    }
}

運(yùn)行結(jié)果:


strings庫(kù)合約的使用

常見(jiàn)的庫(kù)合約舉例:

  1. String:將uint256轉(zhuǎn)換為String
  2. Address:判斷某個(gè)地址是否為合約地址
  3. Create2:更安全的使用Create2 EVM opcode
  4. Arrays:跟數(shù)組相關(guān)的庫(kù)函數(shù)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容