- 部署
部署參考只能合約的簡(jiǎn)單編程。 - 智能合約代碼
// title 授權(quán)投票 contract Ballot { // 這里聲明了復(fù)雜類型 // 將會(huì)在被后面的參數(shù)使用 // 代表一個(gè)獨(dú)立的投票人。 struct Voter { uint weight; // 累積的權(quán)重,也就是具有的投票數(shù) bool voted; // 如果為真,則表示該投票人已經(jīng)投票。 address delegate; // 委托的投票代表(如果自己不投,委托給別人,這個(gè)別人的地址) uint vote; // 投票選擇的提案索引號(hào)(投的提案) } // 這是一個(gè)獨(dú)立提案的類型 struct Proposal { string name; // 提案的短名稱 uint voteCount; // 提案累計(jì)獲得的票數(shù) } // 提案創(chuàng)建者地址 address public chairperson; // 這里聲明一個(gè)狀態(tài)變量,保存每個(gè)獨(dú)立地址的`Voter` 結(jié)構(gòu) mapping(address => Voter) public voters; // 一個(gè)存儲(chǔ)`Proposal`結(jié)構(gòu)的動(dòng)態(tài)數(shù)組 Proposal[] public proposals; // 提案名字?jǐn)?shù)組 string[] public myProposalNames; // 創(chuàng)建一個(gè)新的投票用于選出一個(gè)提案名`proposalNames` // 這個(gè)構(gòu)造函數(shù),會(huì)在合約執(zhí)行的第一次直接調(diào)用 function Ballot() public { // 提案創(chuàng)建者 chairperson = msg.sender; // 這個(gè)地址的投票數(shù)為1,只有一票 voters[chairperson].weight = 1; // 數(shù)組元素 myProposalNames = ['tom', 'david', 'Bob']; // 對(duì)提供的每一個(gè)提案名稱,創(chuàng)建一個(gè)新的提案 // 對(duì)象添加到數(shù)組末尾 for (uint i = 0; i < myProposalNames.length; i++) // 添加到了提案數(shù)組`proposals`末尾 proposals.push( // 創(chuàng)建了一個(gè)臨時(shí)的提案對(duì)象 Proposal({ name: myProposalNames[i], voteCount: 0 }) ); } // 給投票人`voter`參加投票的投票權(quán), // 只能由投票主持人`chairperson`調(diào)用。 function giveRightToVote(address voter) { // 添加可以投票的人,這個(gè)人不可以是投票創(chuàng)建者,不能已經(jīng)投過票 if (msg.sender != chairperson || voters[voter].voted) // `throw`會(huì)終止和撤銷所有的狀態(tài)和以太改變。 // 如果函數(shù)調(diào)用無效,這通常是一個(gè)好的選擇。 // 但是需要注意,這會(huì)消耗提供的所有g(shù)as。 throw; // 這個(gè)新的可以投票的人,擁有一票 voters[voter].weight = 1; } // 委托你的投票權(quán)到一個(gè)投票代表,自己不投,權(quán)利給別人 function delegate(address to) { // 首先確定這個(gè)更改投票權(quán)的人,本身自投票人列表中 Voter sender = voters[msg.sender]; // 確定他是否已經(jīng)投票 if (sender.voted) throw; // 當(dāng)投票代表`to`也委托給別人時(shí),尋找到最終的投票代表 while (voters[to].delegate != address(0) && voters[to].delegate != msg.sender) to = voters[to].delegate; // 當(dāng)最終投票代表等于調(diào)用者,是不被允許的。 if (to == msg.sender) throw; // 因?yàn)閌sender`是一個(gè)引用, // 當(dāng)你把投票權(quán)給別人時(shí),你本身是已投票狀態(tài)。 sender.voted = true; // 你的投票代理 sender.delegate = to; // 代理者 Voter delegate = voters[to]; // 如果你委托的投票者,已經(jīng)投票 if (delegate.voted) // 那么你的票,直接累加在委托者投票的提案上 proposals[delegate.vote].voteCount += sender.weight; else // 如果投票代表還沒有投票,則修改委托者擁有的投票數(shù)量。 delegate.weight += sender.weight; } // 投出你的選票(包括委托給你的選票) // 給 `proposals[proposal].name`。 function vote(uint proposal) { // 獲得要投票的對(duì)象 Voter sender = voters[msg.sender]; // 判斷是否投票 if (sender.voted) throw; // 修改為已投 sender.voted = true; // 記錄投票者的選擇 sender.vote = proposal; // 如果`proposal`索引超出了給定的提案數(shù)組范圍 // 將會(huì)自動(dòng)拋出異常,并撤銷所有的改變。 proposals[proposal].voteCount += sender.weight; } // 根據(jù)當(dāng)前所有的投票計(jì)算出當(dāng)前的勝出提案 function winningProposal() constant returns (uint winningProposal) { // 獲得投票數(shù),最多的提案編號(hào) uint winningVoteCount = 0; for (uint p = 0; p < proposals.length; p++) { // 記錄投票最多的提案編號(hào) if (proposals[p].voteCount > winningVoteCount) { winningVoteCount = proposals[p].voteCount; winningProposal = p; } } } } - 調(diào)用
- 部署之后的立刻調(diào)用和之前沒啥區(qū)別
- 部署之后其他節(jié)點(diǎn)的調(diào)用或者重新打開配置環(huán)境再次調(diào)用
// 部署之后的再次調(diào)用,需要記住abi abi = [{"constant":false,"inputs":[{"name":"proposal","type":"uint256"}],"name":"vote","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"proposals","outputs":[{"name":"name","type":"string"},{"name":"voteCount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"chairperson","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"}],"name":"delegate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"winningProposal","outputs":[{"name":"winningProposal","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"myProposalNames","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"voter","type":"address"}],"name":"giveRightToVote","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"voters","outputs":[{"name":"weight","type":"uint256"},{"name":"voted","type":"bool"},{"name":"delegate","type":"address"},{"name":"vote","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"}] // 需要記住部署成功后的Contract mined! address contractMinedAddress = '0xcd4dc04ce4452ed24d76b04a80fe4094b178dc22' // 獲得bytecode // bytecode = eth.getCode(adress); // 合約 contract = web3.eth.contract(abi) // 合約實(shí)例對(duì)象 myContractInstance = contract.at(contractMinedAddress) - 合約函數(shù)或者數(shù)組,變量的調(diào)用
1. 一個(gè)公開的變量可以如此 > myContractInstance.chairperson() "0x4079a3f5ffeeb7a84a4a582e9fc5f25579c3bba0" 2. 一個(gè)公開的數(shù)組 > myContractInstance.myProposalNames(0) "tom" // 不可以,需要后綴第幾個(gè)元素,這個(gè)被eth.accounts誤導(dǎo),這個(gè)命令直接輸出數(shù)組,而下面函數(shù)必須輸入index > myContractInstance.myProposalNames() 3. 一個(gè)復(fù)雜的調(diào)用,即如果這個(gè)調(diào)用需要得到礦工去確認(rèn)的 // 先解鎖 > personal.unlockAccount(user,'abc123') // 然后如此調(diào)用投票給第一個(gè)元素即index為0的元素 > myContractInstance.vote.sendTransaction(0, {from:user, gas:4700000}) // 需要去挖礦,才能得到確認(rèn) > miner.start()
參考資料
Solidity 官方文檔中文版
Solidity 官方文檔
Solidity瀏覽器編譯
智能合約調(diào)用示例