Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- pragma solidity ^0.4.22;
- /// @title การลงคะแนนเสียงแบบโอนสิทธิให้ตัวแทนได้
- /// @notice เป็นการสรา้งระบบลงคะแนนเสียง โดยผู้สรา้งการลงคะแนนสามารถกำหนดผู้ลงคะแนนได้ ขณะเดียวกันก็สามารถโอนสิทธิไปให้ผู้อื่นลงคะแนนได้
- /// @dev เริ่มต้นจะต้องระบุข้อเสนอทั้งหมดในการลงคะแนนก่อน(โครงสร้างตาม Proposal)
- contract Ballot {
- // โครงสรา้ง(struct)ของผู้มีสิทธิโหวด
- struct Voter {
- uint weight; // นำ้หนักในาการให้คะแนนรวมถึงการได้รับการโอนสิทธิจากเจ้าของแล้ว
- bool voted; // สถานะการโหวดถ้าเป็น true หมายถึงว่ามีการโหวดแล้ว
- address delegate; // ตำแหน่งของผู้ลงคะแนนที่ให้มอบสิทธิให้
- uint vote; // index ที่ชั้ไปยังข้อเสนอที่เลือกไว้
- }
- // โครงสร้างของข้อเสนอ (Poporsal) ที่ใช้ในการโหวด
- struct Proposal {
- bytes32 name; // หัวข้อของข้อเสนอ (ขนาดสูงสุด 32 bytes)
- uint voteCount; // คะแนนสะสมของผู้โหวดข้อเสนอนี้
- }
- //กำหนดตำแหน่ง(adderess) ประธานการลงคะแนนเสียง
- address public chairperson;
- //กำหนดเก็บผู้ลงคะแนนทั้งหมด(voters) โดยโครงสร้างข้อมูล จะเป็นตาม Voter และทำตารางเทียบกับ address ของผู้ได้รับสิทธิ
- mapping(address => Voter) public voters;
- // ตัวแปรในการเก็บกลุ่มของข้อเสนอ
- Proposal[] public proposals;
- ///@dev contructor ของ smart contract นี้โดยส่งอาร์เรย์ของข้อเสนอทั้งหมด
- constructor(bytes32[] proposalNames) public {
- //เก็บตำแหน่ง(address) ของผู้สรา้ง(ประธาน)การลงคะแนนเสียงนี้
- chairperson = msg.sender;
- //กำหนดประธานให้สามารถเป็นผู้ลงคะแนนได้ และให้กำหนดน้ำหนักเป็น 1
- voters[chairperson].weight = 1;
- //แต่ละครั้งที่ีมีการระบุข้อเสนอเข้าไป จะเป็นการเพิ่มข้อเสนอต่อท้ายอาร์์เรย์ของข้อเสนอที่มีอยู่
- for (uint i = 0; i < proposalNames.length; i++) {
- // สร้าง temporay object ของ Proposal และต่อทั้ง (push) ต่อไปยังอาร์เรย์ของข้อเสนอ proposals
- proposals.push(Proposal({
- name: proposalNames[i],
- voteCount: 0
- }));
- }
- }
- ///@noitce กำหนดผู้ที่มีสิทธิในกระลงคะแนน(ผู้ที่ใช้ได้ต้องเป็นประธานการลงคะแนนเท่านั้น)
- function giveRightToVote(address voter) public {
- //ตรวจสอบว่าผู้เรียกใช้งานเป็นผู้สรา้ง(ประธาน) การลงคะแนนหรือไม่
- require(
- msg.sender == chairperson,
- "Only chairperson can give right to vote."
- );
- //ตรวจสอบว่าผู้ถูกกำหนดให้ลงคะแนนเคยลงคะแนนไปแล้วรึยัง
- require(
- !voters[voter].voted,
- "The voter already voted."
- );
- require(voters[voter].weight == 0);
- voters[voter].weight = 1;
- }
- ///@notice ให้สิทธิในการลงคะแนนไปที่ผู้อื่น
- ///@param to ตำแหน่ง(address) ของผู้ที่ให้สิทธิในการลงคะแนน
- function delegate(address to) public {
- // เรียกหาผู้ลงคะแนนโดยอ้างอิงจากจากตำแหน่งของผู้เรียก smart contract
- Voter storage sender = voters[msg.sender];
- //ตรวจสอบว่าผู้ให้สิทธิเคยลงคะแนนไปแล้วหรือยัง
- require(!sender.voted, "You already voted.");
- //ตรวจสอบว่าผู้ให้สิทธิให้สิทธิตัวเองหรือไม่
- require(to != msg.sender, "Self-delegation is disallowed.");
- // Forward the delegation as long as
- // `to` also delegated.
- // In general, such loops are very dangerous,
- // because if they run too long, they might
- // need more gas than is available in a block.
- // In this case, the delegation will not be executed,
- // but in other situations, such loops might
- // cause a contract to get "stuck" completely.
- while (voters[to].delegate != address(0)) {
- to = voters[to].delegate;
- // We found a loop in the delegation, not allowed.
- require(to != msg.sender, "Found loop in delegation.");
- }
- //กำหนดสถานะผู้ให้สิทธิลงคะแนน เป็นลงคะแนนแล้ว และกำหนดผู้ที่รับสิทธิ
- sender.voted = true;
- sender.delegate = to;
- //เลือกผู้ลงคะแนนโดยอ้างจากผู้ได้รับสิทธิ
- Voter storage delegate_ = voters[to];
- //ตรวจสอบว่าผู้ได้รับสิทธิ ได้ทำการลงคะแนนรึยัง
- if (delegate_.voted) {
- // ถ้าเคยลงคะแนนแล้วให้เพิ่มน้ำหนักไปยังข้อเสนอที่ผู้ได้รับสิทธิเลือกไว้แล้ว
- // directly add to the number of votes
- proposals[delegate_.vote].voteCount += sender.weight;
- } else {
- // ถ้ายังไม่เคยลงคะแนนให้เพิ่มน้ำหนักการลงคะแนน
- delegate_.weight += sender.weight;
- }
- }
- /// @notice ลงคะแนน Give your vote (including votes delegated to you)
- /// @param proposal index ของข้อเสนอที่ต้องการเลือก
- function vote(uint proposal) public {
- //กำหนดผู้ลงคะแนนโดยอ้างจากตำแหน่งผู้เรียก smart contract
- Voter storage sender = voters[msg.sender];
- //ตรวจสอบว่าผู้ลงคะแนนทำการลงคะแนนไปแล้วรึยัง
- require(!sender.voted, "Already voted.");
- //กำหนด index ของข้อเสนอพร้อมกับกำหนดว่าเป็นผู้ลงคะแนนแล้ว
- sender.voted = true;
- sender.vote = proposal;
- //เพิ่มคะแนนสะสมให้กับข้อเสนอนั้นตามน้ำหนักที่ผู้ลงคะแนนได้รับ
- proposals[proposal].voteCount += sender.weight;
- //ในกรณีที่ index ของข้อเสนอที่ป้อนเข้ามาอยู่นอกอาร์เรย์ มันจะออกจาก smart contract นี้โดยอัตโนมัติ พร้อมกับยกเลิกการเปลี่ยนแปลงทั้งหมด
- }
- /// @notice ข้อเสนอที่ชนะการลงคะแนน
- /// @return index ที่ชี้ไปยังข้อเสนอที่มีผู้ลงคะแนนเลือกมากสุด
- /// @dev Computes the winning proposal taking all previous votes into account.
- 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;
- }
- }
- }
- ///@notice แสดงข้อเสนอที่ชนะการลงคะแนน
- ///@return ชื่อของข้อเสนอที่ชนะการลงคะแนน
- function winnerName() public view
- returns (bytes32 winnerName_)
- {
- //เรียกใช้ฟังก์ชัน winningProposal() ในการเรียก index ของข้อเสนอที่มีผู้ลงคะแนนมากสุดจากเรียกชื่อจาก index ในอาร์เรย์
- winnerName_ = proposals[winningProposal()].name;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement