千家信息网

以太坊DAO时间锁定Multisig怎么运用

发表于:2025-01-26 作者:千家信息网编辑
千家信息网最后更新 2025年01月26日,本文小编为大家详细介绍"以太坊DAO时间锁定Multisig怎么运用",内容详细,步骤清晰,细节处理妥当,希望这篇"以太坊DAO时间锁定Multisig怎么运用"文章能帮助大家解决疑惑,下面跟着小编的
千家信息网最后更新 2025年01月26日以太坊DAO时间锁定Multisig怎么运用

本文小编为大家详细介绍"以太坊DAO时间锁定Multisig怎么运用",内容详细,步骤清晰,细节处理妥当,希望这篇"以太坊DAO时间锁定Multisig怎么运用"文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

Decentralized Autonomous Organization,简称DAO,以太坊中重要的概念。一般翻译为去中心化的自治组织。

有时候,时间也可以用作一种很好的安全机制。以下代码基于DAO区块链大会,但有不同的变化。不是每个操作需要X个成员批准,而是任何交易都可以由单个成员发起,但它们在执行之前都需要最少的延迟,这取决于交易的支持。提案的批准越多,就越早执行。会员可以对交易进行投票,这意味着它将取消其他一个已批准的签名。

时间锁定Multisig

这意味着如果你没有紧急程度,则执行任何交易可能只需要一个或两个签名。但是,如果单个密钥被泄露,其他密钥可以将该交易延迟数月或数年,甚至可以阻止其执行。

这个怎么运作

所有密钥都已批准的交易可以在十分钟后执行(此金额是可配置的),并且每5%未投票的成员每次需要的时间加倍(如果他们主动投票,则为四倍)反对)。如果它是一个简单的ether交易,只要支持投票将其置于所需的时间内,就会执行交易,但更复杂的交易将要求使用正确的字节码手动执行交易。这些是默认值,但在创建合约时可以设置不同的值:

批准交易的成员数量:近似时间延迟

  • 100%批准:10分钟(最低默认值)

  • 90%批准:40分钟

  • 80%:2小时40分钟

  • 50%:大约一周

  • 40%:1个月

  • 30%:4个月

  • 20%:超过一年

  • 10%或更少:5年或从不 一旦最短的时间过去,任何人都可以执行交易(参见"国会"以获得更完整的步行)。这是故意的,因为它允许某人安排交易或雇用其他人来执行交易。

代码:

pragma solidity >=0.4.22 <0.6.0;contract owned {    address public owner;    constructor() public {        owner = msg.sender;    }    modifier onlyOwner {        require(msg.sender == owner);        _;    }    function transferOwnership(address newOwner) onlyOwner public {        owner = newOwner;    }}contract tokenRecipient {    event receivedEther(address sender, uint amount);    event receivedTokens(address _from, uint256 _value, address _token, bytes _extraData);    function receiveApproval(address _from, uint256 _value, address _token, bytes memory _extraData) public {        Token t = Token(_token);        require(t.transferFrom(_from, address(this), _value));        emit receivedTokens(_from, _value, _token, _extraData);    }    function () payable external {        emit receivedEther(msg.sender, msg.value);    }}interface Token {    function transferFrom(address _from, address _to, uint256 _value) external returns (bool success);}contract TimeLockMultisig is owned, tokenRecipient {    Proposal[] public proposals;    uint public numProposals;    mapping (address => uint) public memberId;    Member[] public members;    uint minimumTime = 10;    event ProposalAdded(uint proposalID, address recipient, uint amount, string description);    event Voted(uint proposalID, bool position, address voter, string justification);    event ProposalExecuted(uint proposalID, int result, uint deadline);    event MembershipChanged(address member, bool isMember);    struct Proposal {        address recipient;        uint amount;        string description;        bool executed;        int currentResult;        bytes32 proposalHash;        uint creationDate;        Vote[] votes;        mapping (address => bool) voted;    }    struct Member {        address member;        string name;        uint memberSince;    }    struct Vote {        bool inSupport;        address voter;        string justification;    }    // Modifier that allows only shareholders to vote and create new proposals    modifier onlyMembers {        require(memberId[msg.sender] != 0);        _;    }    /**     * Constructor     *     * First time setup     */    constructor(        address founder,         address[] memory initialMembers,         uint minimumAmountOfMinutes    ) payable public {        if (founder != address(0)) owner = founder;        if (minimumAmountOfMinutes !=0) minimumTime = minimumAmountOfMinutes;        // It's necessary to add an empty first member        addMember(address(0), '');        // and let's add the founder, to save a step later        addMember(owner, 'founder');        changeMembers(initialMembers, true);    }    /**     * Add member     *     * @param targetMember address to add as a member     * @param memberName label to give this member address     */    function addMember(address targetMember, string memory memberName) onlyOwner public    {        uint id;        if (memberId[targetMember] == 0) {            memberId[targetMember] = members.length;            id = members.length++;        } else {            id = memberId[targetMember];        }        members[id] = Member({member: targetMember, memberSince: now, name: memberName});        emit MembershipChanged(targetMember, true);    }    /**     * Remove member     *     * @param targetMember the member to remove     */    function removeMember(address targetMember) onlyOwner public {        require(memberId[targetMember] != 0);        for (uint i = memberId[targetMember]; i proposalDeadline(proposalNumber)            && p.currentResult > 0            && p.proposalHash == keccak256(abi.encodePacked(p.recipient, p.amount, ''))            && supportsProposal) {            executeProposal(proposalNumber, '');        }    }    function proposalDeadline(uint proposalNumber) public view returns(uint deadline) {        Proposal storage p = proposals[proposalNumber];        uint factor = calculateFactor(uint(p.currentResult), (members.length - 1));        return p.creationDate + uint(factor * minimumTime *  1 minutes);    }    function calculateFactor(uint a, uint b) public pure returns (uint factor) {        return 2**(20 - (20 * a)/b);    }    /**     * Finish vote     *     * Count the votes proposal #`proposalNumber` and execute it if approved     *     * @param proposalNumber proposal number     * @param transactionBytecode optional: if the transaction contained a bytecode, you need to send it     */    function executeProposal(uint proposalNumber, bytes memory transactionBytecode) public {        Proposal storage p = proposals[proposalNumber];        require(now >= proposalDeadline(proposalNumber)                                         // If it is past the voting deadline            && p.currentResult > 0                                                              // and a minimum quorum has been reached            && !p.executed                                                                      // and it is not currently being executed            && checkProposalCode(proposalNumber, p.recipient, p.amount, transactionBytecode));  // and the supplied code matches the proposal...        p.executed = true;        (bool success, ) = p.recipient.call.value(p.amount)(transactionBytecode);        require(success);        // Fire Events        emit ProposalExecuted(proposalNumber, p.currentResult, proposalDeadline(proposalNumber));    }}
部署和使用

像以前一样在这些教程上部署该代码。在部署参数上,将最小时间留空将默认为30分钟,如果你想要更快的锁定时间,则放1分钟。上传后,执行"添加成员"功能以添加组的新成员,他们可以是你认识的其他人,也可以是不同计算机上的帐户或离线存储。

设置为所有者owner的帐户非常强大,因为它可以随意添加或删除成员。因此,在添加主成员后,我们建议你通过执行Transfer Membership功能将owner设置为另一个帐户。如果你希望对所有成员的添加或删除进行投票,则将其设置为multisig本身,就像任何其他交易一样。另一种方法是将其设置为另一个受信任的multisig钱包,如果你希望永久修复成员数,则可以设置为0x000。请记住,此合约上的资金仅与"所有者"帐户一样安全。

与上述任何DAO一样,此合约可以持有以太币,任何基于以太坊的代币并执行任何合约。为此,请检查如何在国会DAO上执行复杂的提案。

警告和改进

为简单起见,对提案的投票仅仅算得少一点支持。如果你愿意,你可以玩弄负面投票更重要的想法,但这意味着少数成员可以对任何提议的交易拥有有效的否决权!

读到这里,这篇"以太坊DAO时间锁定Multisig怎么运用"文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注行业资讯频道。

0