
کتابخانه ها (Library) در سالیدیتی شباهت زیادی به قرارداد ها دارند اما در عین حال قرارداد به حساب نمی آیند.
بیشتر بخوانید: کتابخانه ها در سالیدیتی و نکات مربوط به آنهاکتابخانه ها از یک سری توابع فقط خوابل خواندن تشکیل شدند و در واقع هدف از ایجاد آنها جلوگیری از تکرار توابع در قرارداد های مختلف است.
البته در مورد سالیدیتی مورد دیگری نیز اهمیت زیادی دارد آن هم مقدار مصرف گس هست، که با استفاده از کتابخانه ها میتوان مقدار مصرف گس را نیز کاهش داد. در واقع با یک بار نوشتن کد ها در کتابخانه و یک بار دیپلوی، از دیپلوی چند باره کد های تکراری جلوگیری می شود.
در مورد کتابخانه ها باید یک سری قوانین را رعایت کنیم. مهمترین آنها عبارتند از:
Stateless اند: یعنی امکان تعریف متغیر های state در آنها وجود ندارد. به بیانی دیگر کتابخانه ها امکان تغییر وضعیت قرارداد ها را ندارند.
توابع فقط خواندنی: صدا زدن یک تابع هیچ هزینه گسی ندارد. در واقع در کتابخانه ها تنها امکان تعریف توابع pure و view وجود دارد.
توابع داخلی: در واقع توابع در کتابخانه ها امکان صدا زده شدن از بیرون را ندارند. البته قرارداد هایی که از کتابخانه استفاده میکنند میتوانند توابع را صدا بزنند اما نمیوان آنها را مستقیم از خارج از قرارداد صدا زد.
امکان ارث بری ندارند: از آنجایی که قرارداد ها مستقل هستند، امکان ارث بری از کتابخانه یا قرارداد های دیگر را ندارند.
امکان به ارث برده شدن ندارند: به همان دلیلی مستقل بودن، امکان به ارث برده شدن توسط قرارداد، کتابخانه یا هر موجودیت دیگری ندارند.
توابع بازگشتی یا پرداختی ندارند: در یک کتابخانه امکان پیاده سازی توابع بازگشتی یا توابع پرداختی وجود ندارد. یعنی قابلیت جابجایی اتر هم ندارند.
مثالی از کتابخانه ها:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
library Math {
function sqrt(uint y) internal pure returns (uint z) {
if (y > 3) {
z = y;
uint x = y / 2 + 1;
while (x < z) {
z = x;
x = (y / x + x) / 2;
}
} else if (y != 0) {
z = 1;
}
// else z = 0 (default value)
}
}
contract TestMath {
function testSquareRoot(uint x) public pure returns (uint) {
return Math.sqrt(x);
}
}
// Array function to delete element at index and re-organize the array
// so that there are no gaps between the elements.
library Array {
function remove(uint[] storage arr, uint index) public {
// Move the last element into the place to delete
require(arr.length > 0, "Can't remove from empty array");
arr[index] = arr[arr.length - 1];
arr.pop();
}
}
contract TestArray {
using Array for uint[];
uint[] public arr;
function testArrayRemove() public {
for (uint i = 0; i < 3; i++) {
arr.push(i);
}
arr.remove(1);
assert(arr.length == 2);
assert(arr[0] == 0);
assert(arr[1] == 2);
}
}