Solidity / Library

Library

Library нь дахин ашиглагдах функцүүдийн цуглуулга юм. Өөрийн гэсэн state хадгалдаггүй, зөвхөн логик агуулна. Gas хэмнэж, кодыг модульчилахад хэрэглэнэ.

Library тодорхойлох

library түлхүүр үгээр тодорхойлно.

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

library MathLib {
    function square(uint256 x) internal pure returns (uint256) {
        return x * x;
    }

    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a <= b ? a : b;
    }
}

Library-н функцүүд ихэвчлэн internal байдаг — ингэснээр compile хийх үед contract-д шууд оруулагдана (байрлуулах шаардлагагүй).

Library хэрэглэх

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./MathLib.sol"; // Тусдаа файлаас оруулах

contract Calculator {
    function computeSquare(uint256 x) public pure returns (uint256) {
        return MathLib.square(x);
    }

    function findMax(uint256 a, uint256 b) public pure returns (uint256) {
        return MathLib.max(a, b);
    }
}

using X for Y — тохиромжтой синтакс

using түлхүүр үгээр library-н функцийг тухайн өгөгдлийн төрөлд шууд дуудах боломжтой болно.

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

library StringLib {
    function isEmpty(string memory s) internal pure returns (bool) {
        return bytes(s).length == 0;
    }

    function length(string memory s) internal pure returns (uint256) {
        return bytes(s).length;
    }
}

contract Profile {
    using StringLib for string; // string төрөлд StringLib-г ашиглана

    mapping(address => string) public usernames;

    function setUsername(string memory name) public {
        require(!name.isEmpty(), "Нэр хоосон байж болохгүй"); // name.isEmpty() хэлбэрээр дуудна
        require(name.length() <= 32, "Нэр хэтэрхий урт байна");
        usernames[msg.sender] = name;
    }
}

using StringLib for string тохируулсны дараа name.isEmpty() нь StringLib.isEmpty(name)-тай яг адилхан ажиллана.

Практик жишээ — SafeMath хэв маяг

Хуучин Solidity (0.8 хүртэл) дугаарын overflow-г шалгаддаггүй байсан тул SafeMath library алдартай байсан. 0.8-аас эхлэн автоматаар шалгадаг болсон ч жишээ болгон:

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

library SafeArithmetic {
    function safeAdd(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 result = a + b;
        require(result >= a, "Overflow гарлаа");
        return result;
    }

    function safeSubtract(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "Underflow гарлаа");
        return a - b;
    }

    function safeMultiply(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) return 0;
        uint256 result = a * b;
        require(result / a == b, "Overflow гарлаа");
        return result;
    }
}

contract Token {
    using SafeArithmetic for uint256;

    mapping(address => uint256) public balances;

    function transfer(address to, uint256 amount) public {
        balances[msg.sender] = balances[msg.sender].safeSubtract(amount);
        balances[to] = balances[to].safeAdd(amount);
    }
}

Deployed library vs Embedded library

| Төрөл | Байрлуулах | Gas | Хэрэглэх үе | | ------------------------- | ----------------- | ------------------- | -------------------------------- | | Embedded (internal) | Contract-тай хамт | Нэмэлт gas үгүй | Ихэнх тохиолдолд | | Deployed (external) | Тусдаа байрлуулна | Бага gas (нэг удаа) | Том, олон contract хуваалцах үед |

external функцтэй library тусдаа байрлуулагдаж, олон contract нэг library-г хуваалцаж болно.

OpenZeppelin library

Дэлхийд хамгийн өргөн хэрэглэгддэг Solidity library бол OpenZeppelin. Аюулгүй, audit хийгдсэн кодыг агуулна.

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// OpenZeppelin-ийн Strings library
import "@openzeppelin/contracts/utils/Strings.sol";

contract NFT {
    using Strings for uint256;

    function tokenURI(uint256 tokenId) public pure returns (string memory) {
        // uint256-г string болгон хөрвүүлнэ
        return string(abi.encodePacked("https://api.example.com/token/", tokenId.toString()));
    }
}

OpenZeppelin-ийн алдартай library-нууд: Strings, Address, Arrays, Math, EnumerableSet.

Дараагийн хичээлд:

payable функц ба ETH хүлээн авах аргыг судална.