开发智能合约
按照需求,我们如此开发:
pragma solidity 0.4.4;
contract Vote {
//检查是否为合约创建者
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
//检测汇入的钱是否够 1 ether
modifier checkBail(){
require(msg.value >= bail);
_;
}
//检查是否有该投票者
modifier checkVoter(){
require(voters[msg.sender].delegate != 0x0);
_;
}
//检查投票是否结束
modifier isFinish(){
require(!finishFlag);
_;
}
struct Voter {
uint item;
address delegate;
bool isRefund;
}
struct Proposal {
uint voteCount;
}
address public owner;
Proposal red;
Proposal blue;
uint constant bail = 1 ether;
bool finishFlag = false;
Proposal[] proposals;
mapping(address => Voter) voters;
address[] voterList;
function Vote(uint8 _numProposals) public {
owner = msg.sender;
red = Proposal(0);
blue = Proposal(0);
proposals.push(red);
proposals.push(blue);
}
function delegate(uint item) payable external checkBail isFinish{
if(voters[msg.sender].delegate == 0x0){
var sender = Voter(item, msg.sender, false);
voters[msg.sender] = sender;
voterList.push(msg.sender);
proposals[item].voteCount++;
}
}
function getResult() isFinish external returns(uint result) {
result = red.voteCount > blue.voteCount ? 0 : 1;
}
function finish() onlyOwner{
finishFlag = true;
}
function refundAll() public {
for(uint x; x < voterList.length; x++) {
if(!voterList[x].send(bail)) {
throw;
}
}
}
}
既然是红蓝双方我们就使用Proposal来创建了,它们之间的不同仅是票数。与此同时,在构造方法里把red和blue加进了数组,之后再delegate投票时直接使用数组索引就代表了投的是哪项。
因此在这里,我们约定red标记为0,blue标记为1。相应的使用modifier进行辅助判断,在构造方法里初始化红蓝双方和owner,设定付款即投票的方法delegate,只能由合约创建者确定的finishFlag标志,公共查询投票结果的getResult方法,以及最重要的退款refundAll方法。
注意:
x.transfer(y)和if (!x.send(y)) throw;是等价的,这里只是为了更清楚的解释而已。建议尽可能使用transfer。