Library
Library нь дахин ашиглагдах функцүүдийн цуглуулга юм. Өөрийн гэсэн state хадгалдаггүй, зөвхөн логик агуулна. Gas хэмнэж, кодыг модульчилахад хэрэглэнэ.
Library тодорхойлох
library түлхүүр үгээр тодорхойлно.
// 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 хэрэглэх
// 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-н функцийг тухайн өгөгдлийн төрөлд шууд дуудах боломжтой болно.
// 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-аас эхлэн автоматаар шалгадаг болсон ч жишээ болгон:
// 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 хийгдсэн кодыг агуулна.
// 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 хүлээн авах аргыг судална.