主页 > imtoken钱包官网版最新 > 在以太坊上构建去中心化自动化组织 (DAO)

在以太坊上构建去中心化自动化组织 (DAO)

imtoken钱包官网版最新 2023-05-07 07:51:01

sitehqz.com 以太坊和以太坊贸易的关系_众筹是什么?众筹平台哪个好_以太坊众筹平台

这是以太坊应用系列的第四篇文章。

在以太坊上发行自己的代币;

以太坊令牌高级;

在以太坊上创建众筹合约;

在以太坊上建立去中心化自动化组织(DAO)(本文);

以太坊去中心化自动化组织(DAO)先进;

到目前为止,我们所有的合约都由其他可能由人类持有的账户拥有和执行。 在本文中,我们将创建一个基于区块链技术的去中心化组织。 组织有中央管理员,负责制定规则、管理成员等,其行为类似于公司的CEO、国家的总统等,中央管理员可以更换。 组织的任何成员都可以通过发送以太币或执行智能合约的形式发起提案,其他人可以对提案投赞成票或反对票。 一旦达到预定时间并达到一定数量的成员投票,就可以执行提案:合约计算选票,如果有足够的选票,将执行给定的交易。

基于区块链的 DAO

按照惯例,先放代码。

pragma solidity ^0.4.16;
contract owned {
 address public owner;
 function owned() 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 _extraData) public {
 Token t = Token(_token);
 require(t.transferFrom(_from, this, _value));
 receivedTokens(_from, _value, _token, _extraData);
 }
 function () payable public {
 receivedEther(msg.sender, msg.value);
 }
}
interfaceToken {
 function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
}
contract Congress is owned, tokenRecipient {
 // Contract Variables and eventsuintpublic minimumQuorum;
 uintpublic debatingPeriodInMinutes;
 intpublic majorityMargin;

sitehqz.com 以太坊和以太坊贸易的关系_以太坊众筹平台_众筹是什么?众筹平台哪个好

Proposal[] public proposals; uintpublic numProposals; mapping (address => uint) public memberId; Member[] public members; event ProposalAdded(uint proposalID, address recipient, uint amount, string description); event Voted(uint proposalID, bool position, address voter, string justification); event ProposalTallied(uint proposalID, int result, uint quorum, bool active); event MembershipChanged(address member, bool isMember); event ChangeOfRules(uint newMinimumQuorum, uint newDebatingPeriodInMinutes, int newMajorityMargin); struct Proposal { address recipient; uint amount; string description; uint votingDeadline; bool executed; bool proposalPassed; uint numberOfVotes; int currentResult; bytes32 proposalHash; 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 function */function Congress ( uint minimumQuorumForProposals, uint minutesForDebate, int marginOfVotesForMajority) payable public { changeVotingRules(minimumQuorumForProposals, minutesForDebate, marginOfVotesForMajority); // It’s necessary to add an empty first member addMember(0, "");

sitehqz.com 以太坊和以太坊贸易的关系_以太坊众筹平台_众筹是什么?众筹平台哪个好

// and let's add the founder, to save a step later addMember(owner, 'founder'); } /** * Add member * * Make `targetMember` a member named `memberName` * * @param targetMember ethereum address to be added * @param memberName public name for that member */function addMember(address targetMember, string memberName) onlyOwner public { uint id = memberId[targetMember]; if (id == 0) { memberId[targetMember] = members.length; id = members.length++; } members[id] = Member({member: targetMember, memberSince: now, name: memberName}); MembershipChanged(targetMember, true); } /** * Remove member * * @notice Remove membership from `targetMember` * * @param targetMember ethereum address to be removed */function removeMember(address targetMember) onlyOwner public { require(memberId[targetMember] != 0); for (uint i = memberId[targetMember]; i众筹是什么?众筹平台哪个好_sitehqz.com 以太坊和以太坊贸易的关系_以太坊众筹平台

int marginOfVotesForMajority) onlyOwner public { minimumQuorum = minimumQuorumForProposals; debatingPeriodInMinutes = minutesForDebate; majorityMargin = marginOfVotesForMajority; ChangeOfRules(minimumQuorum, debatingPeriodInMinutes, majorityMargin); } /** * Add Proposal * * Propose to send `weiAmount / 1e18` ether to `beneficiary` for `jobDescription`. `transactionBytecode ? Contains : Does not contain` code. * * @param beneficiary who to send the ether to * @param weiAmount amount of ether to send, in wei * @param jobDescription Description of job * @param transactionBytecode bytecode of transaction */function newProposal( address beneficiary, uint weiAmount, string jobDescription, bytes transactionBytecode) onlyMembers publicreturns (uint proposalID){ proposalID = proposals.length++; Proposal storage p = proposals[proposalID]; p.recipient = beneficiary; p.amount = weiAmount; p.description = jobDescription; p.proposalHash = keccak256(beneficiary, weiAmount, transactionBytecode); p.votingDeadline = now + debatingPeriodInMinutes * 1 minutes; p.executed = false; p.proposalPassed = false; p.numberOfVotes = 0; ProposalAdded(proposalID, beneficiary, weiAmount, jobDescription); numProposals = proposalID+1; return proposalID; } /** * Add proposal in Ether * * Propose to send `etherAmount` ether to `beneficiary` for `jobDescription`. `transactionBytecode ? Contains : Does not contain` code. * This is a convenience function to use if the amount to be given is in round number of ether units. * * @param beneficiary who to send the ether to * @param etherAmount amount of ether to send * @param jobDescription Description of job * @param transactionBytecode bytecode of transaction */function newProposalInEther( address beneficiary,

sitehqz.com 以太坊和以太坊贸易的关系_众筹是什么?众筹平台哪个好_以太坊众筹平台

uint etherAmount, string jobDescription, bytes transactionBytecode) onlyMembers public returns (uint proposalID) { return newProposal(beneficiary, etherAmount * 1 ether, jobDescription, transactionBytecode); } /** * Check if a proposal code matches * * @param proposalNumber ID number of the proposal to query * @param beneficiary who to send the ether to * @param weiAmount amount of ether to send * @param transactionBytecode bytecode of transaction */function checkProposalCode( uint proposalNumber, address beneficiary, uint weiAmount, bytes transactionBytecode) constant publicreturns (bool codeChecksOut){ Proposal storage p = proposals[proposalNumber]; return p.proposalHash == keccak256(beneficiary, weiAmount, transactionBytecode); } /** * Log a vote for a proposal * * Vote `supportsProposal? in support of : against` proposal #`proposalNumber` * * @param proposalNumber number of proposal * @param supportsProposal either in favor or against it * @param justificationText optional justification text */function vote( uint proposalNumber, bool supportsProposal, string justificationText) onlyMembers publicreturns (uint voteID){ Proposal storage p = proposals[proposalNumber]; // Get the proposal require(!p.voted[msg.sender]); // If has already voted, cancel p.voted[msg.sender] = true; // Set this voter as having voted p.numberOfVotes++; // Increase the number of votesif (supportsProposal) { // If they support the proposal p.currentResult++; // Increase score } else { // If they don't p.currentResult--; // Decrease the score } // Create a log of this event Voted(proposalNumber, supportsProposal, msg.sender, justificationText); return p.numberOfVotes; } /**

以太坊众筹平台_sitehqz.com 以太坊和以太坊贸易的关系_众筹是什么?众筹平台哪个好

* 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 transactionBytecode) public { Proposal storage p = proposals[proposalNumber]; require(now > p.votingDeadline // If it is past the voting deadline && !p.executed // and it has not already been executed && p.proposalHash == keccak256(p.recipient, p.amount, transactionBytecode) // and the supplied code matches the proposal && p.numberOfVotes >= minimumQuorum); // and a minimum quorum has been reached...// ...then execute resultif (p.currentResult > majorityMargin) { // Proposal passed; execute the transaction p.executed = true; // Avoid recursive calling require(p.recipient.call.value(p.amount)(transactionBytecode)); p.proposalPassed = true; } else { // Proposal failed p.proposalPassed = false; } // Fire Events ProposalTallied(proposalNumber, p.currentResult, p.numberOfVotes, p.proposalPassed); } }

打开以太坊钱包部署合约,输入构造函数需要的参数:

以太坊众筹平台_sitehqz.com 以太坊和以太坊贸易的关系_众筹是什么?众筹平台哪个好

点击Deploy提交部署,等待部署通过。

合约部署成功后,将合约分享给你的朋友,让DAO合约真正运行起来。 复制合约地址和ABI提供给你的朋友,或者通过另一台电脑,打开钱包,点击watch contract,输入地址和ABI即可关注我们的DAO。

sitehqz.com 以太坊和以太坊贸易的关系_众筹是什么?众筹平台哪个好_以太坊众筹平台

与 DAO 交互

“Read from contract”面板上的函数可以自由执行,它们只是从区块链中读取信息。 在这里,可以看到当前DAO的所有者,应该就是合约的创建者。

“Write to contract”面板中的函数会将数据写入区块链,因此也需要消耗以太币。 选择“新建提案”,输入相关参数即可发起提案。

在与合约交互之前,需要添加成员。 在“选择功能”选择器中选择“添加成员”,并输入地址。 需要注意的是,添加成员函数只能由所有者执行,所以你必须确保你的账户是DAO的所有者。 点击Execute,等待交易被打包到下一个区块中。 合约中没有获取所有成员的功能,但是我们可以在Members中输入一个地址来判断是否为组织成员。 同样,我们的 DAO 目前也没有自己的资金。 点击右上角的 Transfer Ether & Tokens 为 DAO 充值。

发起提案

现在我们启动 DAO 合约的第一个提案。 在功能选择器上,选择新提案。

点击确定,输入密码,稍等一会,建议就会出现在左栏中。

sitehqz.com 以太坊和以太坊贸易的关系_以太坊众筹平台_众筹是什么?众筹平台哪个好

对提案进行投票也非常简单。 选择投票功能,输入提案编号以太坊众筹平台,选择是或否,点击运行完成投票。

投票时间结束后,您可以选择“executeProposal”功能。 如果提案只是发送以太币,可以将“transactionBytecode”留空,然后点击运行。

如果出现“预计费用消耗”的提示,说明由于某种原因,该功能将不会执行。 原因有很多。 在我们的合约中,在截止日期之前,或者你发送的字节码与原来的提议不同,你会看到这个提示。 在任何这些情况下,合同将被终止,你将失去你发送的以太币。

如果“executeProposal”正常执行,几秒钟后你会看到executed变为true,预定数量的以太币将从合约转移到接收者的账户。

拥有另一个代币

除了拥有以太币之外,我们的 DAO 还可以拥有代币并可以与任何以太坊资产进行交易。 首先,我们需要先发行代币。 还没有发行代币的同学可以参考之前的文章:进阶以太坊代币。 代币发行后,部分代币可以通过以太坊钱包转移到我们的DAO合约中。 接下来,我们模拟以太坊的行为。 比如你想从DAO转一些token到另一个账户,点击Send,但是先不要输入密码,注意屏幕提示。

sitehqz.com 以太坊和以太坊贸易的关系_以太坊众筹平台_众筹是什么?众筹平台哪个好

点击“SHOW RAW DATA”,复制“RAW DATA”区域的数据并保存。 然后取消交易。 回到我们的 DAO,使用以下参数创建一个新提案:

众筹是什么?众筹平台哪个好_以太坊众筹平台_sitehqz.com 以太坊和以太坊贸易的关系

几秒钟后,您将能够看到提案的详细信息。 请注意,交易字节码不存在,它被交易哈希取代。 因为字节码很长,所以不会保存到区块链中。 调用者需要自己提供字节码。

但这带来了一个安全漏洞:如果没有实际代码,你如何投票? 提案通过后,如何防止用户执行与提案不同的代码?

为了避免这些问题以太坊众筹平台,我们保存哈希值。 我们提供提案校验功能,可以根据提供的参数校验是否与提案一致。 因此,除非交易字节码的哈希值与提案中存储的哈希值相同,否则提案不会被执行。

sitehqz.com 以太坊和以太坊贸易的关系_以太坊众筹平台_众筹是什么?众筹平台哪个好

其余投票过程相同。 邀请朋友加入你的 DAO~