Login
欢迎来到未来世界

您现在的位置是: 首页 > 计算机 > 区块链

区块链

如何在Solidity中设计模块化智能合约(solidity开发文档)

区块链 加入收藏
下面由小编针对如何在Solidity中设计模块化智能合约为您答疑解惑,希望能给您带来有一些有效参考。在本文中,我将描述如何使用称为目标模式的东西来模块化智能合约。使用标准的solidity,您将学习如何使用abi.encodeSelector和target.call(data)重写脆弱、耦合的调用,以清除模块和分离关注点。为此,

下面由小编针对如何在Solidity中设计模块化智能合约为您答疑解惑,希望能给您带来有一些有效参考。

在本文中,我将描述如何使用称为目标模式的东西来模块化智能合约。

使用标准的solidity,您将学习如何使用abi.encodeSelector和target.call(data)重写脆弱、耦合的调用,以清除模块和分离关注点。

为此,我们将以HumanityDAO为例 - 以及他们如何使用目标模式将治理与注册表分开。

HumanityDAO:介绍HumanityDAO是一个DAO,其目的是人类验证。

维护一个说“你是真的”的注册表。

它既能让人安心,又在对抗Sybil攻击方面也非常有用。

在我目前的工作中,我正在使用注册表构建像分散式reddit这样的东西,你可以捎带其他DAO所做的工作来打击垃圾邮件(作为一个基本的例子)。

一旦我们开始采用这些模式,您就可以看到整个生态系统如何蓬勃发展。

但除了HumanityDAO是一个伟大的dapp,它也是我看到的模块化Solidity设计的第一个例子。

但是在这种情况下模块化指的是什么?我们如何实现它?HumanityDAO中的模块HumanityDAO维护一个您添加和查询的人的注册表,称为HumanityRegology。

注册表本身仅对单个映射(address=>bool)公共人员上操作。

以下是添加条目的主要功能:functionadd(addresswho)public{require(msg.sender==governance,"HumanityRegistry::add:Onlygovernancecanaddanidentity");require(humans[who]==false, "HumanityRegistry::add:Addressisalreadyontheregistry");_reward(who);humans[who]=true;}治理是我们将要研究的下一个模块,它涉及提案和投票。

这是基本流程:Propose(address target, bytes memory data)开始一个新的提议。

它会创建一个Proposal,将其添加到列表中,然后发出一个事件。

用户调用voteyes(uint proposalid)和voteno(uint proposalid)在通过/失败提案时使用其令牌。

投票期过后,可以调用finalize(uint proposalId)。

如果proposal.yesCount> proposal.noCount,则使用数据调用target为了简单起见,最后一步我将在本指南中引用为目标模式。

这不是一种新的编程模式.EVM:调用合同,发送消息简要说明 - 以太坊合约在EVM中执行,这是一个消息传递执行环境。

因此,当您向地址发送10个wei时,您发送的消息显示{from:me,to:0x123456789,value:10}。

当我们在合同上执行调用时,除了附加数据之外我们也是这样做的 - 所以现在消息看起来像{from:me,to:0x123456789,data:“0xcafebabe”,value:10}。

这是什么数据?嗯,这是根据Solidity应用程序二进制接口(或简称ABI)编码的调用。

消息构造很好,因为它意味着发送以太和调用智能合约没有什么不同。

将钱汇入用户的钱包地址,并将钱汇入合同,看起来一样。

唯一的区别是,合同的地址不是从公钥生成的(而是从nonce生成)。

因为我们在区块链中,而且我们更愿意以不变的方式进行引用,所以智能合约中的方法由它们的选择器引用。

选择器只是函数签名哈希的一部分。

target模式目标模式非常简单,但尚未被广泛使用,因为Solidity具有这些特殊名称。

它也可以称为动态调度(Ruby,Obj-C),回调(JS),无论你想要什么;它基本上包括:你正在构建的模块,例如治理你正在实施的事情,例如注册表目标整合点- 即传递提案将添加到注册表我们将从HumanityDAO的例子中学习如何实现这一目标。

综上所述,我们的目标是:在通过治理投票之后,在注册表中添加一个条目。

在我们将它们组合在一起之前,下面是两个难题,治理和注册模块:contractRegistry{mapping(address=>bool)publichumansfunctionadd(addresswho)public{require(msg.sender==governance,"HumanityRegistry::add:Onlygovernancecanaddanidentity");humans[who]=true;}}contractGovernance{functionpropose(addresstarget,bytesmemorydata) publicreturns(uint){uintproposalId=proposals.length;Proposalmemoryproposal;proposal.target=target;proposal.data=data;proposals.push(proposal);}functionvote()public{/*...*/}functionfinalize(uintproposalId)public{Proposalstorageproposal=proposals[proposalId];require(proposal.result==Result.Pending,"Governance::finalize:Proposalisalreadyfinalized");if(proposal.yesCount>proposal.noCount){//Callthetargetcontractwiththedataproposal.target.call(proposal.data);}}}我们可以使用Registry.add添加到注册表中。

治理的基础是提交一份提案,对提案进行投票,然后调用finalize并通过/失败。

如果提案通过,我们将数据中的calldata调用target合同。

那么我们如何构建这个calldata呢? 你会认为这是非常复杂的,即Solidity不! 我们可以通过一个名为abi.encodeWithSelector的东西来做到这一点:bytesmemorydata=abi.encodeWithSelector(registry.add.selector,who);governance.propose(address(registry),data)就像那样,目标被设置为注册表合同,并且看起来像Registry.add(who)的调用被编码并存储在提议中。

这真的很简单。

使用wrapper还有一件事 - 因为我们已经在谈论良好的设计和可组合性 - 我建议在一个单独的合同中用一种方法wrapper这个调用。

这个wrapper智能合约是一个可以在前端调用的简单方法。

我们将建议的代码流命名为什么,并可能将某人添加到注册表中? HumanityDAO称之为HumanityApplicant:contractHumanityApplicant{Governancegovernance;Registryregistry;constructor(Governance_Governance,Registry_Registry){governance=Governance(_Governance);registry=Registry(_Registry);}functionaddToRegistry(addresswho){bytesmemorydata=abi.encodeWithSelector(registry.add.selector,who);returngovernance.propose(msg.sender,address(registry),data);}}结论就是这样! 使用此功能,您可以轻松获取治理合同并在您自己的设计中使用它。

如何在Solidity中设计模块化智能合约就为大家介绍到这里了。如果你也感兴趣的话,不妨试试网站搜索,相信可能会有不一样的惊喜!

图集详情底部广告位