diff --git a/README.md b/README.md index f9018a4..3ead9e3 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,9 @@ Lesson 2. Using git (git.hsbp.org, git command, init, add, commit, pull, push, u Lesson 3. Second chapter of CryptoZombies (return, mappings, require, inheritance, import, interfaces, multi return, keccak if str -Lesson 4. TBA +Lesson 4. Voting in solidity + +Lesson 5. Code review and due diligence ## Notes diff --git a/contracts/dummy_voting.sol b/contracts/dummy_voting.sol new file mode 100644 index 0000000..92ff453 --- /dev/null +++ b/contracts/dummy_voting.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.13; + +contract Voting{ + + struct Vote_state { + bool voted; + } + + mapping(address => bool) private Voters; + uint256 nft = 0; + uint256 dao = 0; + uint256 token = 0; + + constructor() { + Voters[0x5B38Da6a701c568545dCfcB03FcB875f56beddC4] = false; + } + + function vote(uint256 option) external returns (bool) { + require(Voters[msg.sender] == false, "Already voted or non-existent."); + if (option == 1) { + Voters[msg.sender] = true; + nft = nft + 1; + return true; + } + if (option == 2) { + Voters[msg.sender] = true; + dao = dao + 1; + return true; + } + if (option == 3) { + Voters[msg.sender] = true; + token = token + 1; + return true; + } + return false; + } + + function result() external view returns (string memory){ + if (nft > dao && nft > token) { + return "nft";} + else if (dao > nft && dao > token){ + return "dao";} + else if (token > nft && token > dao){ + return "token";} + return "couldnt decide"; + } +} diff --git a/contracts/voting_draft.sol b/contracts/voting_draft.sol new file mode 100644 index 0000000..de36a8e --- /dev/null +++ b/contracts/voting_draft.sol @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.13; + +contract BallotDraft { + struct ballotVoter { + uint delegateWeight; + bool voteSpent; + address delegateTo; + uint voteIndex; + } + + struct Proposal { + bytes32 proposalName; + uint voteCount; + } + + address public chairman; + mapping(address => ballotVoter) public ballotVoters; + Proposal[] public proposalsOption; + + function Ballot(bytes32[] proposalNames) external { + chairman = msg.sender; + ballotVoters[chairman].delegateWeight = 1; + for (uint i = 0; i < proposalNames.length; i++) { + proposalsOption.push(Proposal({ + proposalName: proposalNames[i] , + voteCount: 0 + })); + } + } + + function giveVotingRights(address ballotVoter) external { + require((msg.sender == chairman) && !ballotVoters[ballotvoter].voteSpent && (ballotVoters[ballotvoter].delegateWeight == 0)); + ballotVoters[ballotvoter].delegateWeight = 1; + } + + function delegateTo(address to) external { + ballotVoter storage sender = ballotVoters[msg.sender]; + require(!sender.voteSpent); + require(to != msg.sender); + while (ballotVoters[to].delegateTo != address(0)) { + to = ballotVoters[to].delegateTo; + require(to != msg.sender); + } + + sender.voteSpent = true; + sender.delegateTo = to; + ballotVoter storage delegateTo = ballotVoters[to]; + if (delegateTo.voteSpent) { + proposalsOption[delegateTo.voteIndex].voteCount += sender.delegateWeight; + } else { + delegateTo.delegateWeight += sender.delegateWeight; + } + } + + function voteIndex(uint proposal) external { + ballotVoter storage sender = ballotVoters[msg.sender]; + require(!sender.voteSpent); + sender.voteSpent = true; + sender.voteIndex = proposal; + proposalsOption[proposal].voteCount += sender.delegateWeight; + } + + function winnerProposal() external returns (uint winnerProposal) { + uint winnerVoteCount = 0; + for (uint p = 0; p < proposalsOption.length; p++) { + if (proposalsOption[p].voteCount > winnerVoteCount) { + winnerVoteCount = proposalsOption[p].voteCount; + winnerProposal = p; + } + } + } + + function winner() external + returns (bytes32 winner) + { + winner = proposalsOption[winnerProposal()].proposalName; + } +}