库合约 library
本章讲解在 Solidity
中,库合约 library
的定义和使用方法。
Solidity
中的库合约 library
是一种特殊的合约,它能够提高代码的重用性和可维护性。
库合约,也称为库函数、函数库,它是一个函数合集,里面包含了一些常用函数,并把它们封装在一个单独的文件中,可以被其它合约引用。
库函数在其它编程语言中也普遍存在,作用也基本相同,都是为了提高代码的可复用性。
1. 库合约的好处
Solidity
中使用库合约有两个用处:
1.1 代码重用和模块化
库合约允许你将一组相关的功能封装到一个地方,并在多个合约中重复使用。这种模块化设计提高了代码的可复用性、可维护性和可读性。
1.2 减少部署成本和 gas 消耗
库合约的字节码在合约中保持一份,这样可以在使用它的代码中共享,因此不需要每次都在链上部署相同的代码。这可以减少部署成本,也有助于减少 gas
消耗。
2. 库合约的定义
定义一个库合约与定义普通合约类似,但需要使用 library
关键字:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library Maths { function add(uint a, uint b) external pure returns (uint) { return a + b; } }
在上面的示例中,Maths
是一个库合约,它里面包含了一个简单的加法函数。
我们把上面的合约保存在一个单独文件 Maths.sol
中。
2. 库合约的定义使用
一个合约要使用库合约中的函数,首先需要将库合约文件,通过 import
关键字引入到合约中。
import "./Maths.sol";
然后就可以使用库合约中的函数了。使用方法有两种:
2.1 通过库合约名称调用
第一种方法是使用库合约名称。比如,使用 Maths
库合约的函数 add
,计算 1 + 2:
function calculate() public pure returns(uint){ return Maths.add(1, 2); }
前面是库合约名称 Maths
,后面跟着一个点,然后跟着函数名称 add
。
2.2 通过 using for 指令
第二种方法是使用 using for
指令。比如,使用这样一条指令:
using A for B;
这条指令表示,将库合约 A 中的所有函数附加到数据类型 B 上。这条指令之后,库库合约 A 中的函数会自动成为 B 类型变量的成员,可以直接调用。
下面是一个使用 using for
指令的智能合约:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./Maths.sol"; contract UsingMaths { using Maths for uint; function calculate(uint x, uint y) external pure returns (uint) { return x.add(y); } }
其中,x.add(y)
就等同于 add(x, y)
。x.add(y)
在调用的时候,x 变量会被当作第一个参数传递给函数。
我们把这个合约复制到 Remix
上,对其进行编译和部署,并调用 calculate
函数:
3. 库合约的编译
库合约在部署时,并没有自己的单独地址,它的字节码被包含在使用该库的合约中,而不是在链上以独立的合约地址进行部署。
当你使用 Solidity
中的库合约时,库合约的代码会被复制并嵌入到使用它的合约中。这样,使用库的合约在部署时会包含库合约的代码,并且在合约中会有一份对应合约函数的跳转表。这种方式可以节省 gas
费用并提高代码的重用性。
当你调用库函数时,实际上是在使用库合约的合约内部执行了库函数的代码,而不是通过在链上调用一个独立的合约地址。