• <option id="cacee"><noscript id="cacee"></noscript></option>
  • <table id="cacee"><noscript id="cacee"></noscript></table>
  • <td id="cacee"></td>
  • <option id="cacee"></option>
  • <table id="cacee"></table>
  • <option id="cacee"><option id="cacee"></option></option>
  • <table id="cacee"><source id="cacee"></source></table><td id="cacee"><rt id="cacee"></rt></td>
    <option id="cacee"><option id="cacee"></option></option>
     找回密碼
     立即注冊

    掃一掃,登錄網站

    首頁 自媒體 查看內容
    • 6253
    • 0
    • 分享到

    如何在Solidity中設計模塊化智能合約

    2019-8-30 08:12

    來源: bc-tech-lab


    在本文中,我將描述如何使用稱為目標模式的東西來模塊化智能合約。使用標準的solidity,您將學習如何使用abi.encodeSelector和target.call(data)重寫脆弱、耦合的調用,以清除模塊和分離關注點。為此,我們將以HumanityDAO為例 - 以及他們如何使用目標模式將治理與注冊表分開。

    HumanityDAO:介紹
    HumanityDAO是一個DAO,其目的是人類驗證。維護一個說“你是真的”的注冊表。它既能讓人安心,又在對抗Sybil攻擊方面也非常有用。在我目前的工作中,我正在 使用注冊表構建像分散式reddit這樣的東西,你可以捎帶其他DAO所做的工作來打擊垃圾郵件(作為一個基本的例子)。一旦我們開始采用這些模式,您就可以看到整個生態系統如何蓬勃發展。

    但除了HumanityDAO是一個偉大的dapp,它也是我看到的模塊化Solidity設計的第一個例子。但是在這種情況下模塊化指的是什么?我們如何實現它?

    HumanityDAO中的模塊

    HumanityDAO維護一個您添加和查詢的人的注冊表,稱為HumanityRegology。注冊表本身僅對單個映射(address=>bool)公共人員上操作。以下是添加條目的主要功能:


    function add(address whopublic {
        require(msg.sender == governance, 

       "HumanityRegistry::add: Only governance can add an identity");
        require(humans[who] == false

        "HumanityRegistry::add: Address is already on the registry");

        _reward(who);
        humans[who] = true;
    }


    治理是我們將要研究的下一個模塊,它涉及提案和投票。這是基本流程:


    1. Propose(address target, bytes memory data)開始一個新的提議。它會創建一個Proposal,將其添加到列表中,然后發出一個事件。
    2. 用戶調用voteyes(uint proposalid)和voteno(uint proposalid)在通過/失敗提案時使用其令牌。
    3. 投票期過后,可以調用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的例子中學習如何實現這一目標。


    綜上所述,我們的目標是:在通過治理投票之后,在注冊表中添加一個條目。


    在我們將它們組合在一起之前,下面是兩個難題,治理和注冊模塊:


    contract Registry {
        mapping (address => bool) public humans

        function add(address whopublic {
            require(msg.sender == governance, "HumanityRegistry::add: Only governance can add an identity");
            humans[who] = true;
        }
    }


    contract Governance {
        function propose(address target, bytes memory data

         public returns (uint{

            uint proposalId = proposals.length;
            Proposal memory proposal;
            proposal.target = target;
            proposal.data = data;
            proposals.push(proposal);
        }

        function vote(public /* ... */ }

        function finalize(uint proposalIdpublic {
            Proposal storage proposal = proposals[proposalId];
            require(proposal.result == Result.Pending, 

           "Governance::finalize: Proposal is already finalized");

            if (proposal.yesCount > proposal.noCount) {
                // Call the target contract with the data
                proposal.target.call(proposal.data);
            }
        }
    }



    我們可以使用Registry.add添加到注冊表中。治理的基礎是提交一份提案,對提案進行投票,然后調用finalize并通過/失敗。如果提案通過,我們將數據中的calldata調用target合同。


    那么我們如何構建這個calldata呢? 你會認為這是非常復雜的,即Solidity


    不! 我們可以通過一個名為abi.encodeWithSelector的東西來做到這一點:


    bytes memory data = abi.encodeWithSelector(registry.add.selector, who);
    governance.propose(address(registry), data)


    就像那樣,目標被設置為注冊表合同,并且看起來像Registry.add(who)的調用被編碼并存儲在提議中。 這真的很簡單。

    使用wrapper
    還有一件事 - 因為我們已經在談論良好的設計和可組合性 - 我建議在一個單獨的合同中用一種方法wrapper這個調用。 這個wrapper智能合約是一個可以在前端調用的簡單方法。

    我們將建議的代碼流命名為什么,并可能將某人添加到注冊表中? HumanityDAO稱之為HumanityApplicant:


    contract HumanityApplicant {
        Governance governance;
        Registry registry;

        constructor(Governance _Governance, Registry _Registry) {
            governance = Governance(_Governance);
            registry = Registry(_Registry);
        }

        function addToRegistry(address who{
            bytes memory data = abi.encodeWithSelector(registry.add.selector, who);
            return governance.propose(msg.sender, address(registry), data);
        }
    }


    結論

    就是這樣! 使用此功能,您可以輕松獲取治理合同并在您自己的設計中使用它。


    版權申明:本內容來自于互聯網,屬第三方匯集推薦平臺。本文的版權歸原作者所有,文章言論不代表鏈門戶的觀點,鏈門戶不承擔任何法律責任。如有侵權請聯系QQ:3341927519進行反饋。
    相關新聞
    發表評論

    請先 注冊/登錄 后參與評論

      回頂部
    • <option id="cacee"><noscript id="cacee"></noscript></option>
    • <table id="cacee"><noscript id="cacee"></noscript></table>
    • <td id="cacee"></td>
    • <option id="cacee"></option>
    • <table id="cacee"></table>
    • <option id="cacee"><option id="cacee"></option></option>
    • <table id="cacee"><source id="cacee"></source></table><td id="cacee"><rt id="cacee"></rt></td>
      <option id="cacee"><option id="cacee"></option></option>
      妖精视频