这个例子相对复杂一些,用到了以太坊编程语言Solidity的很多特性。例子实现了一个投票智能合约。电子投票系统的一个主要问题是如何分配合理的权限给正确的人,并且要防止篡改。这个例子不能解决所有问题,但是实现了如何去委托投票,整个投票计数过程是自动且完全透明的。
功能上首先要为投票设立一个简称创建一个合约,发起者作为主席来给每一个独立的地址分配权限。每一个参与者可以自己投票或者委托给信任的人。程序最后会返回得票数最多的那个提议。
// 一个有委托功能的投票系统 contract Ballot { // 定义一个复杂类型,后面作为变量来使用, // 代表一个投票人。 struct Voter { unit weight; // weight在代表投票过程中会累积 bool voted; // 如果值为true,代表这个投票人已经投过票 address delegate; // 投票人地址 unit vote; // 当前投票的索引 } // 代表一份提议的数据结构 struct Posposal { bytes32 name; // 提议的名称 unit voteCount; // 提议接受的投票数 } // 定义投票发起人 address public chairperson; // 这个状态变量存储了所有潜在投票人 mapping(address => Voter) public voters; // 定义动态数组存储所以提议 Posposal[] public proposals; // 传入提议名称来定义一个投票对象 function Ballot(bytes32[] proposalNames){ chairperson = msg.sender; voters[chairperson].weight = 1; // 把传入的提议名称创建一个提议,并加入到前面定义的提议数组 for(unit i = 0; i < proposalNames.length; i++){ // 创建一个临时提议对象,加入提议数组 proposals.push(Proposal({ name: proposalNames[i], voteCount: 0; })); } } // 给投票人分配投票权限,这个操作只有发起人(主席)才可以 function giveRightToVote(address: voter){ if(msg.sender != chairperson || voter.voted) { throw; } voters.weight = 1; } // 委托投票给另外一个投票人 function delegate(address to){ // 找出委托发起人,如果已经投票,终止程序 Voter sender = voters[msg.sender]; if(sender.voted) throw; while(voters[to].delegate != address[0] && voters[to].delegate != msg.sender){ to = voters[to].delegate; } // 发起人、委托人不能是同一个,否则终止程序 if(to == msg.sender){ throw; } // 标识发起人已经投过票 sender.voted = true; sender.delegate = to; Voter delegate = voters[0]; if (delegate.voted) { // 投票成功,投票总数加上相应的weight proposals[delegate.vote].voteCount += sender.weight; } else { // 如果还没投票,发起人weight赋值给委托人 delegate += sender.weight; } } // 投票给某个提议 function vote(unit proposal) { Voter sender = voters[msg.sender]; if (sender.voted) throw; sender.voted = true; sender.voter = proposal; proposals[proposal].voteCount += sender.weight; } // 找出投票数最多的提议 function winningProposal() constant returns (winningProposal) { unit winningVoteCount = 0; for (unit p = 0; p < voteCount; p++) { if (proposals[p].voteCount > winningVoteCount){ winningVoteCount = proposals[p].voteCount; winningProposal = p; } } } }