Created
August 6, 2018 05:02
-
-
Save devender-yadav/1ad3c18b11861f8f90ce912b94e6c671 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^ 0.4 .24; | |
pragma experimental ABIEncoderV2; | |
contract DecentGov { | |
address public admin; | |
uint public proposalSubmissionStart; | |
uint public proposalSubmissionEnd; | |
uint public votingStart; | |
uint public votingEnd; | |
uint public resultDeclare; | |
uint public projectsStart; | |
uint public projectsEnd; | |
bool private hasResultDeclared; | |
uint public funds; | |
struct Member { | |
address addr; | |
string name; | |
// can be Aadhaar card for Indians | |
string uniqueId; | |
} | |
struct Vote { | |
address votedBy; | |
uint32 proposalId; | |
bool isUpvote; | |
} | |
struct Proposal { | |
uint proposalId; | |
string title; | |
string description; | |
bytes docs; | |
bool selected; | |
uint64 expectedBudget; | |
address submitter; | |
// points are upvotes - downvotes | |
int64 points; | |
} | |
uint[] public selectedProjectsId; | |
Proposal[] public proposals; | |
mapping(address => Member) public members; | |
//proposal id to votes map | |
mapping(uint32 => Vote[]) public proposalVotes; | |
mapping(address => Vote[]) memberVotes; | |
constructor( | |
uint _proposalSubmissionStart, | |
uint _proposalSubmissionEnd, | |
uint _votingStart, | |
uint _votingEnd, | |
uint _resultDeclare, | |
uint _projectsStart, | |
uint _projectsEnd, | |
uint _funds | |
) public { | |
require(_funds != 0 && _proposalSubmissionStart != 0 && (_proposalSubmissionEnd > _proposalSubmissionStart) && (_votingStart > _proposalSubmissionEnd) && (_votingEnd > _votingStart) && (_resultDeclare > _votingEnd) && (_projectsStart > _resultDeclare) && (_projectsEnd > _projectsStart), "invalid inputs"); | |
proposalSubmissionStart = now + _proposalSubmissionStart; | |
proposalSubmissionEnd = now + _proposalSubmissionEnd; | |
votingStart = now + _votingStart; | |
votingEnd = now + _votingEnd; | |
resultDeclare = now + _resultDeclare; | |
projectsStart = now + _projectsStart; | |
projectsEnd = now + _projectsEnd; | |
hasResultDeclared = false; | |
funds = _funds; | |
admin = msg.sender; | |
} | |
function addMember(address _address, string _name, string _uniqueId) public { | |
require(msg.sender == admin, "only admin can add members!"); | |
require(bytes(members[_address].name).length == 0, "member already added!"); | |
require(votingStart > now, "Can't register now; voting has already started!"); | |
members[_address] = Member(_address, _name, _uniqueId); | |
} | |
function addMembers(address[] _addresses, string[] _names, string[] _uniqueIds) public { | |
require(msg.sender == admin, "only admin can add members!"); | |
for (uint i = 0; i < _addresses.length; i++) { | |
require(votingStart > now, "Can't register now; voting has already started!"); | |
require(bytes(members[_addresses[i]].name).length == 0, "member already added!"); | |
require(bytes( _names[i]).length == 0, "Name can't be empty!"); | |
require(bytes(_uniqueIds[i]).length == 0, "Unique ID can't be empty!"); | |
members[_addresses[i]] = Member(_addresses[i], _names[i], _uniqueIds[i]); | |
} | |
} | |
function getMemeberDetails() public view returns(string _uniqueId, string _name) { | |
Member memory member = members[msg.sender]; | |
_uniqueId = member.uniqueId; | |
_name = member.name; | |
} | |
function getProposalsWithPoints() public view returns(string[] _proposalNames, int64[] _points) { | |
for (uint i = 0; i < proposals.length; i++) { | |
_proposalNames[i] = proposals[i].title; | |
_points[i] = getPoints(proposals[i].proposalId); | |
} | |
} | |
function saveProposal(string _title, string _description, uint64 _expectedBudget) public returns(uint _proposalId) { | |
// proposal submission must be started and not ended. | |
require(bytes(members[msg.sender].name).length != 0, "Not a registered member!"); | |
require(proposalSubmissionStart < now, "Proposal submission hasn't started!"); | |
require(proposalSubmissionEnd > now, "Proposal submission has ended!"); | |
require(bytes(_title).length != 0 && bytes(_description).length != 0 && _expectedBudget != 0, "Invalid title/description/expectedBudget"); | |
_proposalId = proposals.length; | |
proposals.push(Proposal(_proposalId, _title, _description, "", false, _expectedBudget, msg.sender, 0)); | |
} | |
function updateProposal(uint32 _proposalId, string _title, string _description, uint64 _expectedBudget) public { | |
// proposal submission must be started and not ended. | |
require(bytes(members[msg.sender].name).length != 0, "Not a registered member!"); | |
require(proposalSubmissionStart < now, "proposal submission hasn't started!"); | |
require(proposalSubmissionEnd > now, "proposal submission has ended!"); | |
require(bytes(_title).length != 0 && bytes(_description).length != 0 && _expectedBudget != 0, "invalid title/description/expectedBudget"); | |
require(_proposalId <= proposals.length && bytes(proposals[_proposalId].title).length != 0, "No proposal exist for this Proposal Id"); | |
// check if same user (who created proposal) is updating it. | |
require(proposals[_proposalId].submitter == msg.sender, "Can't update this proposal because it's created by another user"); | |
proposals.push(Proposal(_proposalId, _title, _description, "", false, _expectedBudget, msg.sender, 0)); | |
} | |
function castVote(bool _isUpvote, uint32 _proposalId) public { | |
require(bytes(members[msg.sender].name).length != 0, "Not a registered member!"); | |
require(votingStart < now, "Proposal Voting hasn't started!"); | |
require(votingEnd > now, "Proposal Voting has ended!"); | |
require(_proposalId <= proposals.length && bytes(proposals[_proposalId].title).length != 0, "No Proposal exists for this Id!"); | |
Vote[] memory votes = memberVotes[msg.sender]; | |
if (votes.length > 0) { | |
for (uint i = 0; i < votes.length; i++) { | |
require(votes[i].proposalId != _proposalId, "Already voted for this proposal"); | |
} | |
} | |
proposalVotes[_proposalId].push(Vote(msg.sender, _proposalId, _isUpvote)); | |
memberVotes[msg.sender].push(Vote(msg.sender, _proposalId, _isUpvote)); | |
// upvote will get +1 and downvote will get -1 point | |
_isUpvote ? proposals[_proposalId].points++ : proposals[_proposalId].points--; | |
} | |
function getPoints(uint _proposalId) public view returns(int64 count) { | |
require(_proposalId <= proposals.length && bytes(proposals[_proposalId].title).length != 0, "No Proposal exists for this Id!"); | |
count = proposals[_proposalId].points; | |
} | |
function calculateResults() public { | |
require(resultDeclare < now, "results has't declared!"); | |
if (!hasResultDeclared) { | |
sortProposals(); | |
for (uint i = 0; i < proposals.length; i++) { | |
if (proposals[i].expectedBudget < funds) { | |
proposals[i].selected = true; | |
selectedProjectsId.push(proposals[i].proposalId); | |
funds -= proposals[i].expectedBudget; | |
} | |
break; | |
} | |
hasResultDeclared = true; | |
} | |
} | |
function addDocuments(uint _proposalId, bytes _docs) public { | |
require(proposals[_proposalId].submitter == msg.sender, "Only proposal owner can add documents!"); | |
require(projectsStart < now, "projects has't started!"); | |
require(projectsEnd > now, "projects has ended!"); | |
require(_proposalId <= proposals.length && bytes(proposals[_proposalId].title).length != 0, "No Proposal exists for this Id!"); | |
require(proposals[_proposalId].selected == true, "This project is not selected!"); | |
require(_docs.length > 0, "Add document(s)"); | |
for (uint i = 0; i < _docs.length; i++) { | |
proposals[i].docs.push(_docs[i]); | |
} | |
} | |
//bubble sort as of now. | |
function sortProposals() private { | |
uint len = proposals.length; | |
for (uint i = 0; i < (len - 1); i++) { | |
for (uint j = 0; j < len - i - 1; j++) { | |
if (proposals[j].points < proposals[j + 1].points) { | |
Proposal memory temp = proposals[j]; | |
proposals[j] = proposals[j + 1]; | |
proposals[j + 1] = temp; | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment