-
Notifications
You must be signed in to change notification settings - Fork 1
/
PLTMProposal.sol
232 lines (198 loc) · 6.43 KB
/
PLTMProposal.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
//Sources:
//https://github.com/dappuniversity/nft/blob/master/src/contracts/Color.sol
//https://coursetro.com/posts/code/102/Solidity-Mappings-&-Structs-Tutorial
pragma solidity ^0.6.0;
//Not sure if I have to change this
import "@openzeppelin-solidity/contracts/token/ERC721/ERC721Full.sol";
contract PLTMProposal is ERC721Full{
//hard coded, because it doesn't sound like this would change
uint total = 100000000;
struct ProposalData {
string message;
//false until 10k votes have been received
bool deposit;
uint depositVotes;
uint yesVotes;
uint noVotes;
uint abstains;
//Shows how many votes one account has used
mapping(address => uint) votesSpent;
//Shows if the user voted yes (1) or no (2) or abstain (0)
mapping(address => uint) decsion;
//true until deactivated after a week of deposit being true
bool active;
uint endTime;
}
//PLTMToken stored here:
PLTMToken public tokens;
//Array of IDs;
uint[] private IDs;
//mapping of IDs to strings
mapping(uint => proposalData) _proposals;
//constructor defines name, symbol
constructor() ERC721Full("PLTMProposal", "PLTM Proposal") public {
}
//Can be created by anyone
//Create new proposal
function mint(string memory _proposal, PLTMToken _PLTM) public {
//add a new ID;
uint _id = IDs.length;
IDs.push(_id);
//Creates the new token
_mint(msg.sender, _id);
//Defines proposal for said id
var proposal = _proposals[_id];
proposal.message = _proposal;
proposal.deposit = false;
proposal.depositVotes = 0;
proposal.yesVotes = 0;
proposal.noVotes = 0;
proposal.active = true;
proposal.endTime = 0;
}
function addDepositVotes(uint _numVotes, uint _id) public returns (bool success) {
//Grabs proposal of said ID
var proposal = _proposals[_id];
//Requires the the proposal is on deposit mode
require(!proposal.deposit);
//Requires that the user can spend enough votes.
require(_numVotes <= tokens.balanceOfVote(msg.sender) - proposal.votesSpent[msg.sender]);
proposal.depositVotes += _numVotes;
proposal.votesSpent[msg.sender] += _numVotes;
proposal.yesOrNo[msg.sender] = true;
//Add in the countdown start I guess
if(proposal.depositVotes >= 10000) {
deposit = true;
proposal.yesVotes = proposal.depositVotes;
proposal.depositVotes = 0;
//THere are 604800 seconds in a week
endTime = now + 604800;
}
return true;
}
//If decision is 0, its abstain, if 1, its yes, if 2, its no
function vote(uint _numVotes, uint _id, uint _decision) public returns (bool success) {
//Grabs proposal of said ID
var proposal = _proposals[_id];
//Requires proposal to be active;
require(proposal.active);
//Requires that the user can spend enough votes.
require(_numVotes <= tokens.balanceOfVote(msg.sender) - proposal.votesSpent[msg.sender]);
//Require that the address is voting for the same decision (i.e. they're still voting yes/no/abstain)
require(getAddressDecision(msg.sender, _id) == 4 || getAddressDecision(msg.sender, _id) == _decision)
if(getAddressDecision(msg.sender, _id) == 4) {
proposal.decision = _decision;
}
if(_decision == 1){
proposal.yesVotes += _numVotes;
} else if (_decision == 2) {
proposal.noVotes += _numVotes;
} else {
proposal.abstains += _numVotes;
}
proposal.votesSpent[msg.sender] += _numVotes;
return true;
}
//Call this function when a user's amount of available votes goes down
function reduceVotes(address _address, uint _id) public {
var proposal = _proposals[_id];
require(proposal.active);
if(proposal.votesSpent[address] > tokens.balanceOf(address)) {
uint difference = proposal.votesSpent[address] - tokens.balanceOf(address);
if(!proposal.deposit) {
proposal.depositVotes -= difference;
} else {
if(proposal.yesOrNo == 1){
proposal.yesVotes -= difference;
} else if (proposal.yesOrNo == 2){
proposal.noVotes -= difference;
} else {
proposal.abstains -= difference;
}
}
}
}
//Call this function when a user's amount of available votes goes up
function addVotes(address _address, uint _id) public {
var proposal = _proposals[_id];
require(proposal.active);
if(proposal.votesSpent[address] < tokens.balanceOf(address)) {
uint difference = tokens.balanceOf(address) - proposal.votesSpent[address];
if(!proposal.deposit) {
proposal.depositVotes += difference;
} else {
if(proposal.yesOrNo == 1){
proposal.yesVotes += difference;
} else if (proposal.yesOrNo == 2){
proposal.noVotes -= difference;
} else {
proposal.abstains += difference;
}
}
}
}
function close(uint _id) public returns (bool success) {
var proposal = _proposals[_id];
proposal.active = false;
if(yesVotes >= 0.2 * (total - abstains) && yesVotes > noVotes) {
return true;
} else {
return false;
}
}
//return 0 is abstain, 1 is yes, 2 is no, 3 is no vote yet
function getAddressDecision(address _address, uint _id) public returns (uint success) {
var proposal = _proposals[_id];
if(proposal.votesSpent[_address] > 0) {
return proposal.decision[_address];
} else {
return 3;
}
}
function getAddressVotes(address _address, uint _id) public returns (uint success) {
var proposal = _proposals[_id];
return proposal.votesSpent[_address];
}
function getYesVotes(uint _id) public returns (uint success) {
var proposal = _proposals[_id];
return proposal.yesVotes;
}
function getNoVotes(uint _id) public returns (uint success) {
var proposal = _proposals[_id];
return proposal.noVotes;
}
function getAbstains(uint _id) public returns (uint success) {
var proposal = _proposals[_id];
return proposal.abstains;
}
function getMessage(uint _id) public returns (uint success) {
var proposal = _proposals[_id];
return proposal.message;
}
//Just remove all of your votes
function revokeVotes(uint _numVotes, uint _id) public returns (bool success) {
var proposal = _proposals[_id];
require(proposal.active);
require(_numVotes == proposal.spentVotes[msg.sender]);
if(proposal.decision == 1){
proposal.yesVotes -= _numVotes;
} else if (proposal.decision == 2) {
proposal.noVotes -= _numVotes;
} else {
proposal.abstains -= _numVotes;
}
proposal.spentVotes[msg.sender] = 0;
return true;
}
function getTotalIDs() public returns (uint success) {
return IDs.length;
}
function getTimeLeft(uint _id) public view returns (uint success) {
var proposal = _proposals[_id];
if(now <= end){
return proposal.endTime - now;
} else {
return 0;
}
}
}