在可升级智能合约的背景下,什么时候应该使用接口,什么时候应该使用库?我阅读了几个类似的问题和博客文章,但都没有给出直截了当的答案:
我知道在设计可升级性时要考虑的主要标准(除了安全性之外)是:
这篇Medium文章建议使用库来封装逻辑(例如,在与“存储合约”交互时),并使用接口来解耦合约间通信。其他帖子建议使用不同的技术。据我所知,库在部署之前链接到合约,所以一旦合约发生变化,就需要重新部署库。为什么使用接口与存储协定交互不是更好?
下面我给出了目前为止我看到的两个解决方案——一个是用库,一个是用接口。(我想避免使用内嵌汇编的解决方案...)
StorageWithLib.sol:
contract StorageWithLib {
uint public data;
function getData() public returns(uint) {
return data;
}
}
StorageLib.sol:
import './StorageWithLib.sol';
library StorageLib {
function getData(address _storageContract) public view returns(uint) {
return StorageWithLib(_storageContract).getData();
}
}
ActionWithLib.sol:
import './StorageLib.sol';
contract ActionWithLib {
using StorageLib for address;
address public storageContract;
function ActionWithLib(address _storageContract) public {
storageContract = _storageContract;
}
function doSomething() public {
uint data = storageContract.getData();
// do something with data ...
}
}
IStorage.sol:
contract IStorage {
function getData() public returns(uint);
}
storagewithininterface . sol:
import './IStorage.sol';
contract StorageWithInterface is IStorage {
uint public data;
function getData() public returns(uint) {
return data;
}
}
Action WiththInterface.sol:
import './IStorage.sol';
contract ActionWithInterface {
IStorage public storageContract;
function ActionWithInterface(address _storageContract) public {
storageContract = IStorage(_storageContract);
}
function doSomething() public {
uint data = storageContract.getData();
// do something with data ...
}
}
考虑到上述标准,哪种解决方案更适合分离存储和逻辑,为什么?在哪些其他情况下,另一种解决方案更好?
我希望有人能给出一个更好的答案,但这是一个好问题,我想给出我的意见。
简而言之,由于它专门与可升级合同有关,因此我认为这两种方法之间没有真正的区别。无论使用哪种实现,您仍然具有单独的存储协定,并且仍在发出对存储协定的调用
(一个通过接口从操作协定发出调用,另一个通过库间接地从操作协定发出调用)。
唯一的具体区别在于气体消耗。通过该界面,您正在发出单个呼叫
操作。通过一个库,您正在添加一个抽象层,最终得到一个委托调用
,然后是一个调用
。不过,头顶上的天然气并不是很大,所以归根结底,我认为这两种方法非常相似。您采取的方法是个人喜好。
这并不意味着库通常没有用处。我经常使用它们来重用常见数据结构或操作的代码(例如,由于在Solidity中迭代很痛苦,我有一个库可以用作基本的可迭代集合)。我只是看不出将它们用于我的存储合同集成有多大价值。我很好奇,看看那里的Solidity专家是否有不同的看法。
库和接口确实不同,用在不同的情况下。我个人不认为它们在合同设计中可以互换。下面我试图概述两者的主要特征。注意,我所说的< code >接口指的是一个抽象契约(也就是上面例子中的契约)。我之前在这里强调的接口在可靠性方面仍然存在问题https://medium . com/@ Elena _ di/hi-there-answers-below-6378 b 08 cfcef
图书馆:
> < li>
可以包含逻辑,用于从合同中提取代码,以实现可维护性和重用目的
部署一次,然后在合同中引用。它们的字节码是单独部署的,不是引用它们的契约的一部分。这在我上面的文章(“在Solidity中编写可升级的契约”)中被定义为单例,我在文章中解释了它的好处,比如更低的部署成本。
抽象契约/接口
>
Cannon包含逻辑和接口定义
主要用于导入其他合约,提供与合约实现的交互。接口的部署/导入大小比实施者合约小得多
为可升级性提供抽象,我在“使用‘接口’解耦合同间通信”一节中也描述了这一点
我能想到的上述两者之间唯一的相似之处是它们都不能包含存储变量。
版本申明 pragma solidity ^0.4.0; 说明: 1 版本要高于0.4才可以编译 2 号表示高于0.5的版本则不可编译,第三位的版本号但可以变,留出来用做bug可以修复(如0.4.1的编译器有bug,可在0.4.2修复,现有合约不用改代码)。 引用其它源文件 全局引入 * import “filename”; 自定义命名空间引入 * import * as symbolN
假设双方之间有一份合同,允许根据某些业务逻辑将一些资金(最初与我一起)转移给双方,例如80%的资金转移给a,20%的资金转让给B。现在,对于不同的一方对X,这些百分比是不同的
指导编写一个EOSIO的智能合约 模块 Account API 查询账户数据的API. Chain API 查询链内部状态的API. Database API 存储和检索EOS.IO区块链的数据API根据以下广泛结构来组织数据. Math API 定义常用的数学函数. Action API 定义用于查询操作属性的API. Memory API 定义常用的记忆功能. Console API 使应用程
编程语言 使用golang作为编程语言(对部分关键字限制,以保证处理的有序性),而不是重新创造编程语言。 golang是一个简单、易用的编程语言,它有完善的帮助文档和开发工具。 它是强类型校验,编译阶段就能够校验发现很多bug。 它是模块化的,本系统能够简单屏蔽外部功能,使智能合约处在简单可预期的环境中。 已经有大量的golang开发人员,他们如果要开发智能合约,非常容易上手。 智能合约的分类 公
智能合约有效性 使用此方法,可能希望确定所加载的合约地址是你所期望的智能合约。为此,你可以使用isValid合约方法,只有在合约地址中部署的字节码与智能合约封装包中的字节码匹配时才会返回true。 contract.isValid(); // returns false if the contract bytecode does not match what's deployed
介绍 EOSIO 智能合约 编写智能合约需要的必备技能 C / C++ 相关 基于 EOSIO 的块链使用的是 WebAssembly(http://webassembly.org/) (WASM) 来执行用户编写的智能合约。WASM 是一种新兴的 Web 标准,广泛支持于谷歌、微软、苹果等。对编写 WASM 标准的智能合约来说使用 clang/llvm(https://clang.llvm.or