# 简单的投票合约

这是 Remix 官方案例

// ["0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000003", "0x0000000000000000000000000000000000000000000000000000000000000004", "0x0000000000000000000000000000000000000000000000000000000000000005"]
// SPDX-License-Identifier:  GPL-3.0
pragma solidity >=0.7.0  <0.9.0;
contract Ballot{
  // struct  结构体
  struct Voter {
    uint weight; // 权重  0  1
    bool voted; // 是否投过票
    address delegate;
    uint vote; // 某一个提案 代号 简单化
  }
  struct Proposal {
    bytes32 name;
    uint voteCount; // 记录被投了几票
  }
  address public chairperson; // 主席   合约的创建者
  // 映射 映射到 Voter   key值是地址
  mapping(address => Voter) public voters;
  Proposal[] public proposals; // 长度可变的数组

  constructor(bytes32[] memory proposalNames){
    chairperson = msg.sender;
    voters[chairperson].weight = 1;
    for(uint i=0;i<proposalNames.length;i++){
      proposals.push(Proposal({
        name: proposalNames[i],
        voteCount: 0
      }));
    }
  }
  // 给某些地址投票权
  function giveRightToVote(address voter) public {
    require(
      msg.sender == chairperson,
      "only chairperson can given right to vote."
    );
    require(
      !voters[voter].voted,
      "the voter already voted."
    );
    require(voters[voter].weight ==0);
    voters[voter].weight = 1;
  }
  // 代理   把投票权代理给别人
  function delegate(address to) public {
    // storage 默认存储到storage
    Voter storage sender = voters[msg.sender]; // 调用者
    require(!sender.voted, "you already voted.");
    require(to != msg.sender, "self-delegation is disallowed");
    // 委托人的委托人
    // 0 地址转换为地址类型
    while (voters[to].delegate != address(0)){
      // 委托人有委托人
      to = voters[to].delegate;   // 委托人的地址和被委托人 的地址不能同一个
      require(to != msg.sender, "Found loop in delegation.");
    }
    sender.voted = true;
    sender.delegate = to;
    Voter storage delegate_ = voters[to];
    // 如果委托人已经投了票
    if(delegate_.voted){
      // sender.weight 有可能是1 也有可能是0
      proposals[delegate_.vote].voteCount +=  sender.weight;
    }  else {
      delegate_.weight += sender.weight; // 把其中加上
    }
  }
  // 我要给谁投票 [uint proposal 方案的序号]
  function vote(uint proposal) public {
    Voter storage sender = voters[msg.sender];
    require(sender.weight !=0, "has  no right to vote");
    require(!sender.voted,  "already voted");
    require(proposal<proposals.length);
    sender.voted  = true;
    sender.vote = proposal;
    proposals[proposal].voteCount += sender.weight;
  }
  function winningProposal() public view 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;
      }
    }
  }
  function winnerName() public view returns (bytes32 winnerName_){
    winnerName_ = proposals[winningProposal()].name;
  }
}