solidity:理解库函数

208 阅读2分钟

库函数定义

  1. 使用 library关键字定义库合约
  2. 不能继承别的合约,只能实现接口
  3. 不能有构造函数、成员变量、修饰器

总的来说,库合约就是纯粹的方法集。使用using for将方法附加在一个数据类型上。

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

// 定义一个库
library SafeMath {
    function add(uint x, uint y) internal pure returns (uint) {
        uint z = x + y;
        require(z >= x, "uint overflow");
        return z;
    }
}

// 使用库的合约
contract TestSafeMath {
    using SafeMath for uint;

    uint public result;

    function add(uint x, uint y) public {
        result = x.add(y);
    }
}

库合约中的public与internal

public或external库合约是通常通过delegatecall调用的,但是调用的参数约束和内部调用相同

对于 internal 库函数:它们会被编译器内联到调用它们的合约的字节码中。这意味着没有单独的函数调用,而是直接在合约代码内执行。

如果有public就需要单独部署

无论技术的实现方式如何,库函数调用时合约内部调用,上下文不变化

更新知识

b-->up:东风草绿

  1. 库的internal是inline到调用者代码中了
  2. 库的public方法是library单独部署为合约,然后用delegatecall调用。所以,如果library有public方法,则必然是要单独部署的(Linked Library)。如果全是internal方法,则可以不部署(Embedded Library)
  3. 当library因为有public而单独部署时,与proxy pattern相比照,都是利用另一个合约承载逻辑,但方式不用,一个利用存储布局,一个直接传递storage引用,上下文变量都保持在调用者一边。(调用者以delegatecall调用,由于library没有成员,被调用者只操作传入的参数,因此delegatecall不是像proxy pattern中的那样通过兼容存储布局利用另一合约逻辑的作用,而是通过操作storage属性的参数利用另一合约的逻辑)。
  4. library的public,external函数传入storage参数,从这一点来看,说它是普通合约并不准确。
  5. 调用者对单独部署的library的引用是在编译时完成,不是运行时,无法实现动态升级(是要故意为升级制造困难吗?)
  6. internal: 对调用者可见,并且内联编译;private:library内部用,对library使用者不可见(仅从可见性解释上,library类似超类)。public:对library使用者可见,但是合约要单独部署
  7. 交易属性:解释为对storage类型参数的操作,而不是成员;或者解释为对调用者成员变量的操作;两者等价