智能案例详解:第一个投票智能合约

1.结构解析

一个简单的投票合约

2.结构解析图解

3.整体结构

pragma solidity ^0.4.4;
// 授权投票
contract Ballot{
   struct Voter{
        uint weight;//累积的权重
        bool voted;//如果为真,则表示该投票人已经投票
        address delegate;//委托的投票代表
        uint vote;//投票选择的提案索引号
   }
  //这是一个独立提案的类型
  struct Proposal{
        bytes32 name; //短名称(32字节)
        uint voteCount;//累积获得的票数
  }
  address public chairperson;
  //这里声明一个状态变量,保存每个独立地址的Voter的结构
  mapping (address => Voter) public voters;
  //一个储存 Proposal结构的动态数组
  Proposal[] public  proposals;
  
  
  
  
  
  
  // 创建一个新的投票用于选出一个提案名称 proposalsNames
  function Ballot(bytes32[] proposalNames) {
        chairperson = msg.sender;
        voters[chairperson].weight = 1;
  //对提供的每一个提案名称,创建一个新的提案
  //对象添加到数据末尾
  for (uint i= 0;i<proposalNames.length;i++){
  //创建一个临时的提案对象
  //添加到一个提案数组proposals末尾
  proposals.push(Proposal({
            name:proposalNames[i],
            voteCount:0
    }));
    }
  }



  //给投票人voter参加投票的投票权
  //只能由投票主持人chairperson调用
  function giveRightToVote(address voter) public{
    if(msg.sender !=chairperson || voters[voter].voted)
    //如果函数调用无效,这通常是一个
    //但是要注意,这会消耗所有的gas
    throw;
    voters[voter].weight = 1;
  }
  
  
  
  //委托你的投票权到一个投票代表 to
  function delegate(address to){
    // 指定引用
    Voter  storage sender = voters[msg.sender];
    if (sender.voted)
    throw;
    //当投票代表to 也委托给别人时候,虚招到最终的投票代表
    while (voters[to].delegate !=address(0)&& voters[to].delegate !=msg.sender)
    to = voters[to].delegate;
    //当最终投票代表等于调用者,这是不予许的
    if (to ==msg.sender)
     throw;
    //因为sender是一个引用
    //这里实际修改了voters[msg.sender].voted
         sender.voted = true;
         sender.delegate = to;
         Voter delegate =voters[to];
     if(delegate.voted){
    //如果委托的投票代表已经投票,直接修改票数
        proposals[delegate.vote].voteCount +=sender.weight;
    }else{
    //如果投票代表还没有投票,则修改其投票的权重
        delegate.weight += sender.weight;
     }
  }
 

 
 //投出你的选票(包括委托给你的选票)
 //给  proposals[proposal].proposalNames
function vote(uint proposal){
    Voter  storage sender = voters[msg.sender];
    if (sender.voted)throw;
    sender.voted = true;
    sender.vote = proposal;
//如果proposal 索引超出了给定的提案数据范围
// 将会自动抛出异常,并撤销所有改变
    proposals[proposal].voteCount +=sender.weight;
 }
 
 
 
 //根据当前的所有投票计算出当前的胜出提案
 function winningProposal() constant returns (uint winningProposal){
    uint winningVoteCount = 0;
    for(uint p =0; p<proposals.length;p++){
        if(proposals[p].voteCount >winningVoteCount){
            winningVoteCount = proposals[p].voteCount;
            winningProposal = p;  
    }
  }
 }
}

4.重要函数解析

01.授权投票结构体

struct Voter{
        uint weight;//累积的权重
        bool voted;//如果为真,则表示该投票人已经投票
        address delegate;//委托的投票代表
        uint vote;//投票选择的提案索引号
   }

02.独立提案结构

  struct Proposal{
        bytes32 name; //短名称(32字节)
        uint voteCount;//累积获得的票数
  }

03.状态变量以及其他参数声明

address public chairperson;
  //这里声明一个状态变量,保存每个独立地址的Voter的结构
  mapping (address => Voter) public voters;
  //一个储存 Proposal结构的动态数组
  Proposal[] public  proposals;

04.创建一个新的投票用于选出一个提案名称 proposalsNames

  function Ballot(bytes32[] proposalNames) {
        chairperson = msg.sender;
        voters[chairperson].weight = 1;
  //对提供的每一个提案名称,创建一个新的提案
  //对象添加到数据末尾
  for (uint i= 0;i<proposalNames.length;i++){
  //创建一个临时的提案对象
  //添加到一个提案数组proposals末尾
  proposals.push(Proposal({
            name:proposalNames[i],
            voteCount:0
    }));
    }
  }

05.给投票人voter参加投票的投票权

//给投票人voter参加投票的投票权
  //只能由投票主持人chairperson调用
  function giveRightToVote(address voter) public{
    if(msg.sender !=chairperson || voters[voter].voted)
    //如果函数调用无效,这通常是一个
    //但是要注意,这会消耗所有的gas
    throw;
    voters[voter].weight = 1;
  }

06.委托你的投票到一个投票代表 to

  //委托你的投票权到一个投票代表 to
  function delegate(address to){
    // 指定引用
    Voter  storage sender = voters[msg.sender];
    if (sender.voted)
    throw;
    //当投票代表to 也委托给别人时候,虚招到最终的投票代表
    while (voters[to].delegate !=address(0)&& voters[to].delegate !=msg.sender)
    to = voters[to].delegate;
    //当最终投票代表等于调用者,这是不予许的
    if (to ==msg.sender)
     throw;
    //因为sender是一个引用
    //这里实际修改了voters[msg.sender].voted
         sender.voted = true;
         sender.delegate = to;
         Voter delegate =voters[to];
     if(delegate.voted){
    //如果委托的投票代表已经投票,直接修改票数
        proposals[delegate.vote].voteCount +=sender.weight;
    }else{
    //如果投票代表还没有投票,则修改其投票的权重
        delegate.weight += sender.weight;
     }
  }
 

07.投出你的选票(包括委托给你的选票)

 //投出你的选票(包括委托给你的选票)
 //给  proposals[proposal].proposalNames
function vote(uint proposal){
    Voter  storage sender = voters[msg.sender];
    if (sender.voted)throw;
    sender.voted = true;
    sender.vote = proposal;
//如果proposal 索引超出了给定的提案数据范围
// 将会自动抛出异常,并撤销所有改变
    proposals[proposal].voteCount +=sender.weight;
 }

08.根据当前的所有投票计算出当前的胜出提案

 //根据当前的所有投票计算出当前的胜出提案
 function winningProposal() constant returns (uint winningProposal){
    uint winningVoteCount = 0;
    for(uint p =0; p<proposals.length;p++){
        if(proposals[p].voteCount >winningVoteCount){
            winningVoteCount = proposals[p].voteCount;
            winningProposal = p;  
    }
  }
 }

你可能感兴趣的:(solidity合约解析)