iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 20
0
自我挑戰組

區塊鏈報明牌系列 第 20

[區塊鏈報明牌]Day 20 Ethereum(3)-DAO

  • 分享至 

  • xImage
  •  

什麼是DAO

DAO(Distributed Autonomous Organization)翻譯就是去中心化的自治組織。

一樣先來看看wiki的描述:

The DAO had an objective to provide a new decentralized business model for organizing both commercial and non-profit enterprises. It was instantiated on the Ethereum blockchain, and had no conventional management structure or board of directors. The code of the DAO is open-source.

果然是霧裡雲裡的形容,以Lawrence Lessig教授的話"code is law."來形容可能較為貼切。簡單來看在Ethereum中的DAO是這樣的,在智能合約中寫代碼定義一些規則,這些規則就是想要建構的DAO組織的規則,然後對這個組織的運作都是經由智能合約來執行的。

思考順序大概是這樣:

1.區塊鏈上的資料是不可竄改的,所以不需要人維持運作來確保公性力。

2.區塊鏈上執行智能合約來定義規則(其實就是把code放到區塊鏈裡跑)。

3.組織中的人進行決策和討論都要經由Ethereum,自然必須符合智能合約定義的標準才能運作。

此外考慮到乙太幣本身的價值以及上面運作的那些代幣的價值,以這種模式進行金流方面的操作會是一件很可行的事情。

The Blockchain Congress

為了了解DAO的運作模式,我們實際使用ethereum的智能合約範例,今天要做的事是通過這個DAO組織進行投票,以此把day 19的lottery token傳給其他地址。

先來看看今天的操作流程中會用到的程式碼:

提案,其實就是把提案要描述的變數填一填:

/**
 * 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 public
    returns (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;
}

投票,p.currentResult加加減減:

/**
 * 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 public
    returns (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 votes
    if (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;
}

如果得票數高於minimumQuorum就同意:

/**
 * 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 result

    if (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);
}

可以看到其實智能合約執行的code一般邏輯上都不難,更重要的是檢查錯誤,畢竟合約錯誤就好比法律有漏洞,後果是很嚴重的。

現在實際操作:

先自己往Congress裡面塞些lottery token:

接著拿到執行轉移token時使用的binary code,按下交易但不執行就能拿到了,可以看到有趣的地方是transaction交易的address其實是lottery token的智能合約(0x153d...e162是lottery token的智能合約的地址),而不是要轉交token的地址:

然後用這個binary code發起一個proposal:

接著投票表決提案,在我的Congress的設定中是要兩個成員同意才能通過提案(當然兩個成員都是我):

提案通過以後可以去執行提案,然後對方就能從Congress拿到lottery token了:

透過今天的文章我們可以了解到根據智能合約去運作一個組織是怎麼一回事,就如同文章開頭說的"code is law.",下一篇文章讓我們來看看法律被鑽漏洞的情況吧。

相關參考資源:

code is law
https://www.harvardmagazine.com/2000/01/code-is-law-html
The Blockchain Congress
https://www.ethereum.org/dao


上一篇
[區塊鏈報明牌]Day 19 Ethereum(2)-報明牌代幣
下一篇
[區塊鏈報明牌]Day 21 Ethereum(4)-The DAO Attack
系列文
區塊鏈報明牌30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言