| 知乎专栏 | 多维度架构 |
pragma solidity ^0.4.25;
//author: netkiller <netkiller@msn.com>
//homepage: http://www.netkiller.cn
contract Voting {
mapping (bytes32 => uint8) public votesReceived;
// 存储候选人名字的数组
bytes32[] public candidateList;
// 构造函数 初始化候选人名单
function Voting(bytes32[] candidateNames) public {
candidateList = candidateNames;
}
// 查询某个候选人的总票数
function totalVotesFor(bytes32 candidate) public constant returns (uint8) {
require(validCandidate(candidate) == true);
// 或者
// assert(validCandidate(candidate) == true);
return votesReceived[candidate];
}
// 为某个候选人投票
function voteForCandidate(bytes32 candidate) public{
assert(validCandidate(candidate) == true);
votesReceived[candidate] += 1;
}
// 检索投票的姓名是不是候选人的名字
function validCandidate(bytes32 candidate) public constant returns (bool) {
for(uint i = 0; i < candidateList.length; i++) {
if (candidateList[i] == candidate) {
return true;
}
}
return false;
}
}
pragma solidity ^0.4.25;
contract MetaCoin {
mapping (address => uint) balances;
event Transfer(address indexed _from, address indexed _to, uint256 _value);
function MetaCoin() public {
balances[tx.origin] = 10000;
}
function sendCoin(address receiver, uint amount) public returns(bool sufficient) {
if (balances[msg.sender] < amount) return false;
balances[msg.sender] -= amount;
balances[receiver] += amount;
Transfer(msg.sender, receiver, amount);
return true;
}
function getBalance(address addr) public view returns(uint) {
return balances[addr];
}
}
pragma solidity ^0.4.0;
contract Ballot {
struct Voter {
uint weight;
bool voted;
uint8 vote;
address delegate;
}
struct Proposal {
uint voteCount;
}
address chairperson;
mapping(address => Voter) voters;
Proposal[] proposals;
/// Create a new ballot with $(_numProposals) different proposals.
function Ballot(uint8 _numProposals) public {
chairperson = msg.sender;
voters[chairperson].weight = 1;
proposals.length = _numProposals;
}
/// Give $(toVoter) the right to vote on this ballot.
/// May only be called by $(chairperson).
function giveRightToVote(address toVoter) public {
if (msg.sender != chairperson || voters[toVoter].voted) return;
voters[toVoter].weight = 1;
}
/// Delegate your vote to the voter $(to).
function delegate(address to) public {
Voter storage sender = voters[msg.sender]; // assigns reference
if (sender.voted) return;
while (voters[to].delegate != address(0) && voters[to].delegate != msg.sender)
to = voters[to].delegate;
if (to == msg.sender) return;
sender.voted = true;
sender.delegate = to;
Voter storage delegateTo = voters[to];
if (delegateTo.voted)
proposals[delegateTo.vote].voteCount += sender.weight;
else
delegateTo.weight += sender.weight;
}
/// Give a single vote to proposal $(toProposal).
function vote(uint8 toProposal) public {
Voter storage sender = voters[msg.sender];
if (sender.voted || toProposal >= proposals.length) return;
sender.voted = true;
sender.vote = toProposal;
proposals[toProposal].voteCount += sender.weight;
}
function winningProposal() public constant returns (uint8 _winningProposal) {
uint256 winningVoteCount = 0;
for (uint8 prop = 0; prop < proposals.length; prop++)
if (proposals[prop].voteCount > winningVoteCount) {
winningVoteCount = proposals[prop].voteCount;
_winningProposal = prop;
}
}
}
pragma solidity ^0.4.25;
contract Conference {
address public organizer;
mapping (address => uint) public registrantsPaid;
uint public numRegistrants;
uint public quota;
event Deposit(address _from, uint _amount); // so you can log these events
event Refund(address _to, uint _amount);
function Conference() public{ // Constructor
organizer = msg.sender;
quota = 500;
numRegistrants = 0;
}
function buyTicket() public payable returns (bool success) {
if (numRegistrants >= quota) { return false; }
registrantsPaid[msg.sender] = msg.value;
numRegistrants++;
Deposit(msg.sender, msg.value);
return true;
}
function changeQuota(uint newquota) public {
if (msg.sender != organizer) { return; }
quota = newquota;
}
function refundTicket(address recipient, uint amount) public {
if (msg.sender != organizer) { return; }
if (registrantsPaid[recipient] == amount) {
address myAddress = this;
if (myAddress.balance >= amount) {
recipient.transfer(amount);
registrantsPaid[recipient] = 0;
numRegistrants--;
Refund(recipient, amount);
}
}
}
function destroy() public{ // so funds not locked in contract forever
if (msg.sender == organizer) {
selfdestruct(organizer); // send funds to organizer
}
}
}
控制台调试
var contract;
Conference.deployed().then(function(instance){contract=instance;});
contract.buyTicket();
测试程序
neo@MacBook-Pro ~/ethereum/Conference % cat test/conference.js
var Conference = artifacts.require("./Conference.sol");
contract('Conference', function(accounts) {
console.log(accounts);
var owner_account = accounts[0];
var sender_account = accounts[1];
it("Initial conference settings should match", function(done) {
Conference.deployed({from: owner_account}).then(function(conference) {
conference.quota.call().then(function(quota) {
assert.equal(quota, 100, "Quota doesn't match!");
}).then(function() {
return conference.numRegistrants.call();
}).then(function(num) {
assert.equal(num, 0, "Registrants doesn't match!");
return conference.organizer.call();
}).then(function(organizer) {
assert.equal(organizer, owner_account, "Owner doesn't match!");
done();
}).catch(done);
}).catch(done);
});
it("Should update quota", function(done) {
Conference.deployed({from: owner_account}).then(function(conference) {
conference.quota.call().then(
function(quota) {
assert.equal(quota, 100, "Quota doesn't match!");
}).then(
function() {
return conference.changeQuota(300);
}).then(
function() {
return conference.quota.call()
}).then(
function(quota) {
assert.equal(quota, 300, "New quota is not correct!");
done();
}).catch(done);
}).catch(done);
});
it("Should let you buy a ticket", function(done) {
Conference.deployed({ from: accounts[0] }).then(function(conference) {
var ticketPrice = web3.toWei(.05, 'ether');
var initialBalance = web3.eth.getBalance(conference.address).toNumber();
conference.buyTicket({ from: accounts[1], value: ticketPrice }).then(
function() {
var newBalance = web3.eth.getBalance(conference.address).toNumber();
var difference = newBalance - initialBalance;
assert.equal(difference, ticketPrice, "Difference should be what was sent");
return conference.numRegistrants.call();
}).then(
function(num) {
assert.equal(num, 1, "there should be 1 registrant");
return conference.registrantsPaid.call(sender_account);
}).then(
function(amount) {
assert.equal(amount.toNumber(), ticketPrice, "Sender's paid but is not listed as paying");
return web3.eth.getBalance(conference.address);
}).then(
function(bal) {
assert.equal(bal.toNumber(), ticketPrice, "Final balance mismatch");
done();
}).catch(done);
}).catch(done);
});
it("Should issue a refund by owner only", function(done) {
Conference.deployed({ from: accounts[0] }).then(function(conference) {
var ticketPrice = web3.toWei(.05, 'ether');
var initialBalance = web3.eth.getBalance(conference.address).toNumber();
conference.buyTicket({ from: accounts[1], value: ticketPrice }).then(
function() {
var newBalance = web3.eth.getBalance(conference.address).toNumber();
var difference = newBalance - initialBalance;
assert.equal(difference, ticketPrice, "Difference should be what was sent");
// Now try to issue refund as second user - should fail
return conference.refundTicket(accounts[1], ticketPrice, {from: accounts[1]});
}).then(
function() {
var balance = web3.eth.getBalance(conference.address);
assert.equal(balance, ticketPrice, "Balance should be unchanged");
// Now try to issue refund as organizer/owner
return conference.refundTicket(accounts[1], ticketPrice, {from: accounts[0]});
}).then(
function() {
var postRefundBalance = web3.eth.getBalance(conference.address).toNumber();
assert.equal(postRefundBalance, initialBalance, "Balance should be initial balance");
done();
}).catch(done);
}).catch(done);
});
});