1 | | - | {-# STDLIB_VERSION 5 #-} |
---|
2 | | - | {-# SCRIPT_TYPE ACCOUNT #-} |
---|
3 | | - | {-# CONTENT_TYPE DAPP #-} |
---|
4 | | - | let separator = "__" |
---|
5 | | - | |
---|
6 | | - | let maxDepthDefault = 10 |
---|
7 | | - | |
---|
8 | | - | func asInt (val) = match val { |
---|
9 | | - | case valInt: Int => |
---|
10 | | - | valInt |
---|
11 | | - | case _ => |
---|
12 | | - | throw("Failed to cast into Integer") |
---|
13 | | - | } |
---|
14 | | - | |
---|
15 | | - | |
---|
16 | | - | func asBool (val) = match val { |
---|
17 | | - | case valBool: Boolean => |
---|
18 | | - | valBool |
---|
19 | | - | case _ => |
---|
20 | | - | throw("Failed to cast into Boolean") |
---|
21 | | - | } |
---|
22 | | - | |
---|
23 | | - | |
---|
24 | | - | let keyFeeAmount = makeString(["%s", "fee"], separator) |
---|
25 | | - | |
---|
26 | | - | let keyWxAssetId = makeString(["%s", "wxAssetId"], separator) |
---|
27 | | - | |
---|
28 | | - | let keyVotingThreshold = makeString(["%s", "votingThreshold"], separator) |
---|
29 | | - | |
---|
30 | | - | let keyVotingDuration = makeString(["%s", "epochLength"], separator) |
---|
31 | | - | |
---|
32 | | - | let keyVoteBeforeElimination = makeString(["%s", "voteBeforeElimination"], separator) |
---|
33 | | - | |
---|
34 | | - | let keyStartHeight = makeString(["%s", "currentVotingHeightStart"], separator) |
---|
35 | | - | |
---|
36 | | - | let keyCurrentPeriod = makeString(["%s", "currentEpoch"], separator) |
---|
37 | | - | |
---|
38 | | - | let keyBoostingContract = makeString(["%s", "boostingContract"], separator) |
---|
39 | | - | |
---|
40 | | - | let keyEmissionContract = makeString(["%s", "emissionContract"], separator) |
---|
41 | | - | |
---|
42 | | - | let keyAssetsStoreContract = makeString(["%s", "assetsStoreContract"], separator) |
---|
43 | | - | |
---|
44 | | - | let keyLatestProcessedAsset = makeString(["%s", "latestProcessedAsset"], separator) |
---|
45 | | - | |
---|
46 | | - | let keyLatestProcessedUser = makeString(["%s", "latestProcessedUser"], separator) |
---|
47 | | - | |
---|
48 | | - | let keyLatestProcessedUserRemove = makeString(["%s", "latestProcessedUserRemove"], separator) |
---|
49 | | - | |
---|
50 | | - | let keyLatestProcessedAssetTransfer = makeString(["%s", "latestProcessedAssetTransfer"], separator) |
---|
51 | | - | |
---|
52 | | - | let keyLatestProcessedUserTransfer = makeString(["%s", "latestProcessedUserTransfer"], separator) |
---|
53 | | - | |
---|
54 | | - | let keyLatestProcessedUserRemoveTransfer = makeString(["%s", "latestProcessedUserRemoveTransfer"], separator) |
---|
55 | | - | |
---|
56 | | - | let keyMaxDepth = makeString(["%s", "maxDepth"], separator) |
---|
57 | | - | |
---|
58 | | - | func keyVotesTransferFinishedByPeriod (period) = makeString(["%s", "votesTransferFinished", toString(period)], separator) |
---|
59 | | - | |
---|
60 | | - | |
---|
61 | | - | let assetsListName = "__assets" |
---|
62 | | - | |
---|
63 | | - | func getVotesListName (assetId) = ("%s__votes__" + assetId) |
---|
64 | | - | |
---|
65 | | - | |
---|
66 | | - | func keyListHead (listName) = makeString([("%s%s" + listName), "head"], separator) |
---|
67 | | - | |
---|
68 | | - | |
---|
69 | | - | func keyListSize (listName) = makeString([("%s%s" + listName), "size"], separator) |
---|
70 | | - | |
---|
71 | | - | |
---|
72 | | - | func keyListPrev (listName,id) = makeString([("%s%s%s" + listName), id, "prev"], separator) |
---|
73 | | - | |
---|
74 | | - | |
---|
75 | | - | func keyListNext (listName,id) = makeString([("%s%s%s" + listName), id, "next"], separator) |
---|
76 | | - | |
---|
77 | | - | |
---|
78 | | - | func keyAssetVerifiedByPeriod (assetId,period) = makeString(["%s%d%s", "verifiedAt", toString(period), assetId], separator) |
---|
79 | | - | |
---|
80 | | - | |
---|
81 | | - | func keyAssetVerified (assetId) = makeString(["%s%s", "verified", assetId], separator) |
---|
82 | | - | |
---|
83 | | - | |
---|
84 | | - | func keyAssetWasEliminated (assetId,period) = makeString(["%s%s%d", "eliminated", assetId, toString(period)], separator) |
---|
85 | | - | |
---|
86 | | - | |
---|
87 | | - | func keyVoteResultByPeriod (assetId,period) = makeString(["%s%d%s", "votingResultAtAsset", toString(period), assetId], separator) |
---|
88 | | - | |
---|
89 | | - | |
---|
90 | | - | func formatVoteResult (totalYes,totalNo,verified) = makeString(["%d%d%s", toString(totalYes), toString(totalNo), toString(verified)], separator) |
---|
91 | | - | |
---|
92 | | - | |
---|
93 | | - | func parseVoteResult (input) = { |
---|
94 | | - | let parts = split(input, separator) |
---|
95 | | - | let totalYesIdx = 1 |
---|
96 | | - | let totalNoIdx = 2 |
---|
97 | | - | let verifiedIdx = 3 |
---|
98 | | - | let totalYes = parseIntValue(parts[totalYesIdx]) |
---|
99 | | - | let totalNo = parseIntValue(parts[totalNoIdx]) |
---|
100 | | - | let verified = if ((size(parts) == 4)) |
---|
101 | | - | then (parts[verifiedIdx] == "true") |
---|
102 | | - | else false |
---|
103 | | - | $Tuple3(totalYes, totalNo, verified) |
---|
104 | | - | } |
---|
105 | | - | |
---|
106 | | - | |
---|
107 | | - | func keyUserVoteByPeriod (userAddress,assetId,period) = makeString(["%s%d%s%s", "vru", toString(period), assetId, userAddress], separator) |
---|
108 | | - | |
---|
109 | | - | |
---|
110 | | - | func formatUserVote (total,inFavor) = { |
---|
111 | | - | let totalYes = if (inFavor) |
---|
112 | | - | then total |
---|
113 | | - | else 0 |
---|
114 | | - | let totalNo = if (inFavor) |
---|
115 | | - | then 0 |
---|
116 | | - | else total |
---|
117 | | - | makeString(["%d%d", toString(totalYes), toString(totalNo)], separator) |
---|
118 | | - | } |
---|
119 | | - | |
---|
120 | | - | |
---|
121 | | - | func parseUserVote (input) = { |
---|
122 | | - | let parts = split(input, separator) |
---|
123 | | - | let totalYesIdx = 1 |
---|
124 | | - | let totalNoIdx = 2 |
---|
125 | | - | let totalYes = parseIntValue(parts[totalYesIdx]) |
---|
126 | | - | let totalNo = parseIntValue(parts[totalNoIdx]) |
---|
127 | | - | let inFavor = if ((totalYes > 0)) |
---|
128 | | - | then (totalNo == 0) |
---|
129 | | - | else false |
---|
130 | | - | let against = if ((totalYes == 0)) |
---|
131 | | - | then (totalNo > 0) |
---|
132 | | - | else false |
---|
133 | | - | let checkTotals = if (if (inFavor) |
---|
134 | | - | then true |
---|
135 | | - | else against) |
---|
136 | | - | then true |
---|
137 | | - | else throw("Invalid user vote value") |
---|
138 | | - | if ((checkTotals == checkTotals)) |
---|
139 | | - | then { |
---|
140 | | - | let total = if (inFavor) |
---|
141 | | - | then totalYes |
---|
142 | | - | else totalNo |
---|
143 | | - | $Tuple2(total, inFavor) |
---|
144 | | - | } |
---|
145 | | - | else throw("Strict value is not equal to itself.") |
---|
146 | | - | } |
---|
147 | | - | |
---|
148 | | - | |
---|
149 | | - | func keyUserVoteHistory (type,userAddress,assetId,txId,period) = makeString(["%s%s%s%s%s%d", "history", type, assetId, userAddress, txId, toString(period)], separator) |
---|
150 | | - | |
---|
151 | | - | |
---|
152 | | - | func thisOnly (i) = if ((i.caller == this)) |
---|
153 | | - | then true |
---|
154 | | - | else throw("Permission denied") |
---|
155 | | - | |
---|
156 | | - | |
---|
157 | | - | func getIntegerOrZero (key) = valueOrElse(getInteger(this, key), 0) |
---|
158 | | - | |
---|
159 | | - | |
---|
160 | | - | func getIntegerOrFail (key) = valueOrErrorMessage(getInteger(this, key), (key + " is not defined")) |
---|
161 | | - | |
---|
162 | | - | |
---|
163 | | - | func getStringOrEmpty (key) = valueOrElse(getString(this, key), "") |
---|
164 | | - | |
---|
165 | | - | |
---|
166 | | - | func getStringOrFail (key) = valueOrErrorMessage(getString(this, key), (key + " is not defined")) |
---|
167 | | - | |
---|
168 | | - | |
---|
169 | | - | let feeAmount = getIntegerOrFail(keyFeeAmount) |
---|
170 | | - | |
---|
171 | | - | let wxAssetId = fromBase58String(getStringOrFail(keyWxAssetId)) |
---|
172 | | - | |
---|
173 | | - | let votingThreshold = getIntegerOrFail(keyVotingThreshold) |
---|
174 | | - | |
---|
175 | | - | let votingDuration = getIntegerOrFail(keyVotingDuration) |
---|
176 | | - | |
---|
177 | | - | let voteBeforeElimination = getIntegerOrFail(keyVoteBeforeElimination) |
---|
178 | | - | |
---|
179 | | - | let startHeight = getIntegerOrFail(keyStartHeight) |
---|
180 | | - | |
---|
181 | | - | let currentPeriod = getIntegerOrFail(keyCurrentPeriod) |
---|
182 | | - | |
---|
183 | | - | let boostingContract = addressFromStringValue(getStringOrFail(keyBoostingContract)) |
---|
184 | | - | |
---|
185 | | - | let emissionContract = addressFromStringValue(getStringOrFail(keyEmissionContract)) |
---|
186 | | - | |
---|
187 | | - | let assetsStoreContract = addressFromStringValue(getStringOrFail(keyAssetsStoreContract)) |
---|
188 | | - | |
---|
189 | | - | let maxDepth = valueOrElse(getInteger(keyMaxDepth), maxDepthDefault) |
---|
190 | | - | |
---|
191 | | - | let endHeight = (startHeight + votingDuration) |
---|
192 | | - | |
---|
193 | | - | func getUserGwxAmountAtHeight (userAddress,targetHeight) = { |
---|
194 | | - | let gwxAmount = invoke(boostingContract, "getUserGwxAmountAtHeightREADONLY", [userAddress, targetHeight], nil) |
---|
195 | | - | asInt(gwxAmount) |
---|
196 | | - | } |
---|
197 | | - | |
---|
198 | | - | |
---|
199 | | - | func getVoteResultAction (assetId,total,inFavor,period,verified) = { |
---|
200 | | - | let voteResultKey = keyVoteResultByPeriod(assetId, period) |
---|
201 | | - | let $t062886597 = match getString(voteResultKey) { |
---|
202 | | - | case s: String => |
---|
203 | | - | parseVoteResult(s) |
---|
204 | | - | case _: Unit => |
---|
205 | | - | match getString(keyVoteResultByPeriod(assetId, (period - 1))) { |
---|
206 | | - | case s: String => |
---|
207 | | - | $Tuple3(0, 0, parseVoteResult(s)._3) |
---|
208 | | - | case _: Unit => |
---|
209 | | - | $Tuple3(0, 0, false) |
---|
210 | | - | case _ => |
---|
211 | | - | throw("Match error") |
---|
212 | | - | } |
---|
213 | | - | case _ => |
---|
214 | | - | throw("Match error") |
---|
215 | | - | } |
---|
216 | | - | let oldTotalYes = $t062886597._1 |
---|
217 | | - | let oldTotalNo = $t062886597._2 |
---|
218 | | - | let oldVerified = $t062886597._3 |
---|
219 | | - | StringEntry(voteResultKey, formatVoteResult((oldTotalYes + (if (inFavor) |
---|
220 | | - | then total |
---|
221 | | - | else 0)), (oldTotalNo + (if (inFavor) |
---|
222 | | - | then 0 |
---|
223 | | - | else total)), if ((verified == unit)) |
---|
224 | | - | then oldVerified |
---|
225 | | - | else value(verified))) |
---|
226 | | - | } |
---|
227 | | - | |
---|
228 | | - | |
---|
229 | | - | func containsNode (listName,id) = { |
---|
230 | | - | let head = getString(this, keyListHead(listName)) |
---|
231 | | - | let prev = getString(this, keyListPrev(listName, id)) |
---|
232 | | - | let next = getString(this, keyListNext(listName, id)) |
---|
233 | | - | if (if ((id == head)) |
---|
234 | | - | then true |
---|
235 | | - | else (prev != unit)) |
---|
236 | | - | then true |
---|
237 | | - | else (next != unit) |
---|
238 | | - | } |
---|
239 | | - | |
---|
240 | | - | |
---|
241 | | - | func insertNode (listName,id) = { |
---|
242 | | - | let head = getString(this, keyListHead(listName)) |
---|
243 | | - | let listSize = valueOrElse(getInteger(this, keyListSize(listName)), 0) |
---|
244 | | - | let checkNode = if (!(containsNode(listName, id))) |
---|
245 | | - | then true |
---|
246 | | - | else throw("Node exists") |
---|
247 | | - | if ((checkNode == checkNode)) |
---|
248 | | - | then (([IntegerEntry(keyListSize(listName), (listSize + 1))] ++ (if (isDefined(head)) |
---|
249 | | - | then [StringEntry(keyListNext(listName, id), value(head)), StringEntry(keyListPrev(listName, value(head)), id)] |
---|
250 | | - | else nil)) ++ [StringEntry(keyListHead(listName), id)]) |
---|
251 | | - | else throw("Strict value is not equal to itself.") |
---|
252 | | - | } |
---|
253 | | - | |
---|
254 | | - | |
---|
255 | | - | func deleteNode (listName,id) = { |
---|
256 | | - | let head = getString(this, keyListHead(listName)) |
---|
257 | | - | let listSize = valueOrElse(getInteger(this, keyListSize(listName)), 0) |
---|
258 | | - | let prev = getString(this, keyListPrev(listName, id)) |
---|
259 | | - | let next = getString(this, keyListNext(listName, id)) |
---|
260 | | - | ([IntegerEntry(keyListSize(listName), (listSize - 1))] ++ (if (if (isDefined(prev)) |
---|
261 | | - | then isDefined(next) |
---|
262 | | - | else false) |
---|
263 | | - | then [StringEntry(keyListNext(listName, value(prev)), value(next)), StringEntry(keyListPrev(listName, value(next)), value(prev)), DeleteEntry(keyListPrev(listName, id)), DeleteEntry(keyListNext(listName, id))] |
---|
264 | | - | else if (isDefined(next)) |
---|
265 | | - | then [StringEntry(keyListHead(listName), value(next)), DeleteEntry(keyListNext(listName, id)), DeleteEntry(keyListPrev(listName, value(next)))] |
---|
266 | | - | else if (isDefined(prev)) |
---|
267 | | - | then [DeleteEntry(keyListPrev(listName, id)), DeleteEntry(keyListNext(listName, value(prev)))] |
---|
268 | | - | else if ((id == head)) |
---|
269 | | - | then [DeleteEntry(keyListHead(listName))] |
---|
270 | | - | else throw("Invalid node"))) |
---|
271 | | - | } |
---|
272 | | - | |
---|
273 | | - | |
---|
274 | | - | func processVote (assetId,userAddressOrUnit,latestProcessedAssetKey,latestProcessedUserKey,latestProcessedUserRemoveKey) = { |
---|
275 | | - | let updateLatestProcessedAssetAction = StringEntry(latestProcessedAssetKey, assetId) |
---|
276 | | - | let deleteLatestProcessedUserAction = DeleteEntry(latestProcessedUserKey) |
---|
277 | | - | if ((userAddressOrUnit == unit)) |
---|
278 | | - | then [updateLatestProcessedAssetAction, deleteLatestProcessedUserAction] |
---|
279 | | - | else { |
---|
280 | | - | let userAddress = value(userAddressOrUnit) |
---|
281 | | - | let updateLatestProcessedUserAction = StringEntry(latestProcessedUserKey, userAddress) |
---|
282 | | - | let userVoteKey = keyUserVoteByPeriod(userAddress, assetId, currentPeriod) |
---|
283 | | - | let userVoteOrUnit = getString(userVoteKey) |
---|
284 | | - | let voteActions = if ((userVoteOrUnit == unit)) |
---|
285 | | - | then { |
---|
286 | | - | let userGwxAmountAtEndHeight = getUserGwxAmountAtHeight(userAddress, endHeight) |
---|
287 | | - | if ((userGwxAmountAtEndHeight == 0)) |
---|
288 | | - | then [BooleanEntry(latestProcessedUserRemoveKey, true)] |
---|
289 | | - | else { |
---|
290 | | - | let previousPeriod = (currentPeriod - 1) |
---|
291 | | - | let assetWasEliminated = valueOrElse(getBoolean(keyAssetWasEliminated(assetId, previousPeriod)), false) |
---|
292 | | - | let userPreviousVoteOrUnit = if (assetWasEliminated) |
---|
293 | | - | then unit |
---|
294 | | - | else getString(keyUserVoteByPeriod(userAddress, assetId, previousPeriod)) |
---|
295 | | - | if ((userPreviousVoteOrUnit == unit)) |
---|
296 | | - | then nil |
---|
297 | | - | else { |
---|
298 | | - | let $t01080110874 = parseUserVote(value(userPreviousVoteOrUnit)) |
---|
299 | | - | let prevTotal = $t01080110874._1 |
---|
300 | | - | let inFavor = $t01080110874._2 |
---|
301 | | - | let total = min([prevTotal, userGwxAmountAtEndHeight]) |
---|
302 | | - | [StringEntry(userVoteKey, formatUserVote(total, inFavor)), getVoteResultAction(assetId, total, inFavor, currentPeriod, unit)] |
---|
303 | | - | } |
---|
304 | | - | } |
---|
305 | | - | } |
---|
306 | | - | else nil |
---|
307 | | - | ((voteActions :+ updateLatestProcessedAssetAction) :+ updateLatestProcessedUserAction) |
---|
308 | | - | } |
---|
309 | | - | } |
---|
310 | | - | |
---|
311 | | - | |
---|
312 | | - | func assetShouldBeEliminated (assetId,period) = !(valueOrElse(getBoolean(keyAssetVerifiedByPeriod(assetId, period)), true)) |
---|
313 | | - | |
---|
314 | | - | |
---|
315 | | - | func eliminationCheck (assetId) = if (if (assetShouldBeEliminated(assetId, (currentPeriod - 1))) |
---|
316 | | - | then assetShouldBeEliminated(assetId, (currentPeriod - 2)) |
---|
317 | | - | else false) |
---|
318 | | - | then assetShouldBeEliminated(assetId, (currentPeriod - 3)) |
---|
319 | | - | else false |
---|
320 | | - | |
---|
321 | | - | |
---|
322 | | - | @Callable(i) |
---|
323 | | - | func constructor (boostingContractPrm,emissionContractPrm,assetsStoreContractPrm,feeAmountPrm,wxAssetIdPrm,votingThresholdPrm,votingDurationPrm,voteBeforeEliminationPrm,startHeightPrm,maxDepthPrm) = { |
---|
324 | | - | let checks = [thisOnly(i), if (isDefined(addressFromString(boostingContractPrm))) |
---|
325 | | - | then true |
---|
326 | | - | else throw("Invalid boosting contract address"), if (isDefined(addressFromString(emissionContractPrm))) |
---|
327 | | - | then true |
---|
328 | | - | else throw("Invalid emission contract address"), if (isDefined(addressFromString(assetsStoreContractPrm))) |
---|
329 | | - | then true |
---|
330 | | - | else throw("Invalid asset_store contract address"), if ((feeAmountPrm >= 0)) |
---|
331 | | - | then true |
---|
332 | | - | else throw("Invalid fee amount"), if (isDefined(assetInfo(fromBase58String(wxAssetIdPrm)))) |
---|
333 | | - | then true |
---|
334 | | - | else throw("Invalid WX asset ID"), if ((votingThresholdPrm >= 0)) |
---|
335 | | - | then true |
---|
336 | | - | else throw("Invalid voting threshold"), if ((votingDurationPrm > 0)) |
---|
337 | | - | then true |
---|
338 | | - | else throw("Invalid voting duration"), if (((startHeightPrm + votingDurationPrm) > height)) |
---|
339 | | - | then true |
---|
340 | | - | else throw("Invalid start height")] |
---|
341 | | - | if ((checks == checks)) |
---|
342 | | - | then $Tuple2([StringEntry(keyBoostingContract, boostingContractPrm), StringEntry(keyEmissionContract, emissionContractPrm), StringEntry(keyAssetsStoreContract, assetsStoreContractPrm), IntegerEntry(keyFeeAmount, feeAmountPrm), StringEntry(keyWxAssetId, wxAssetIdPrm), IntegerEntry(keyVotingThreshold, votingThresholdPrm), IntegerEntry(keyVotingDuration, votingDurationPrm), IntegerEntry(keyVoteBeforeElimination, voteBeforeEliminationPrm), IntegerEntry(keyStartHeight, startHeightPrm), IntegerEntry(keyCurrentPeriod, 0), IntegerEntry(keyMaxDepth, maxDepthPrm)], unit) |
---|
343 | | - | else throw("Strict value is not equal to itself.") |
---|
344 | | - | } |
---|
345 | | - | |
---|
346 | | - | |
---|
347 | | - | |
---|
348 | | - | @Callable(i) |
---|
349 | | - | func suggest (assetId,assetImage) = { |
---|
350 | | - | let info = valueOrErrorMessage(assetInfo(fromBase58String(assetId)), "Invalid asset ID") |
---|
351 | | - | let payment = value(i.payments[0]) |
---|
352 | | - | let checks = [if ((info.issuer == i.caller)) |
---|
353 | | - | then true |
---|
354 | | - | else throw("Asset can only be suggested by its issuer"), if ((value(payment.assetId) == wxAssetId)) |
---|
355 | | - | then true |
---|
356 | | - | else throw("Invalid fee asset"), if ((payment.amount == feeAmount)) |
---|
357 | | - | then true |
---|
358 | | - | else throw("Invalid fee amount")] |
---|
359 | | - | if ((checks == checks)) |
---|
360 | | - | then { |
---|
361 | | - | let assetsStoreCreateOrUpdateInv = invoke(assetsStoreContract, "createOrUpdate", [assetId, assetImage, false], nil) |
---|
362 | | - | if ((assetsStoreCreateOrUpdateInv == assetsStoreCreateOrUpdateInv)) |
---|
363 | | - | then { |
---|
364 | | - | let burnFeeInv = invoke(emissionContract, "burn", nil, [AttachedPayment(payment.assetId, payment.amount)]) |
---|
365 | | - | if ((burnFeeInv == burnFeeInv)) |
---|
366 | | - | then { |
---|
367 | | - | let addAssetActions = insertNode(assetsListName, assetId) |
---|
368 | | - | let nextPeriod = (currentPeriod + 1) |
---|
369 | | - | let targetPeriod = if ((endHeight > height)) |
---|
370 | | - | then currentPeriod |
---|
371 | | - | else nextPeriod |
---|
372 | | - | $Tuple2((addAssetActions :+ getVoteResultAction(assetId, 0, true, targetPeriod, false)), unit) |
---|
373 | | - | } |
---|
374 | | - | else throw("Strict value is not equal to itself.") |
---|
375 | | - | } |
---|
376 | | - | else throw("Strict value is not equal to itself.") |
---|
377 | | - | } |
---|
378 | | - | else throw("Strict value is not equal to itself.") |
---|
379 | | - | } |
---|
380 | | - | |
---|
381 | | - | |
---|
382 | | - | |
---|
383 | | - | @Callable(i) |
---|
384 | | - | func vote (assetId,inFavor) = { |
---|
385 | | - | let checkAsset = if (containsNode(assetsListName, assetId)) |
---|
386 | | - | then true |
---|
387 | | - | else throw("Invalid asset") |
---|
388 | | - | if ((checkAsset == checkAsset)) |
---|
389 | | - | then { |
---|
390 | | - | let checkHeight = if ((endHeight > height)) |
---|
391 | | - | then true |
---|
392 | | - | else throw("Current voting is over but results are not finalized") |
---|
393 | | - | if ((checkHeight == checkHeight)) |
---|
394 | | - | then { |
---|
395 | | - | let userAddress = toString(i.caller) |
---|
396 | | - | let gwxAmountAtEnd = getUserGwxAmountAtHeight(userAddress, endHeight) |
---|
397 | | - | let checkGwxAmountAtEnd = if ((gwxAmountAtEnd > 0)) |
---|
398 | | - | then true |
---|
399 | | - | else throw("You'll not have gWX at the end of voting") |
---|
400 | | - | if ((checkGwxAmountAtEnd == checkGwxAmountAtEnd)) |
---|
401 | | - | then { |
---|
402 | | - | let votesListName = getVotesListName(assetId) |
---|
403 | | - | let userVoteKey = keyUserVoteByPeriod(userAddress, assetId, currentPeriod) |
---|
404 | | - | let userVoteOrUnit = getString(userVoteKey) |
---|
405 | | - | let cancelVoteInv = if ((userVoteOrUnit == unit)) |
---|
406 | | - | then unit |
---|
407 | | - | else invoke(this, "cancelVote", [assetId], nil) |
---|
408 | | - | if ((cancelVoteInv == cancelVoteInv)) |
---|
409 | | - | then { |
---|
410 | | - | let userVoteActions = [StringEntry(userVoteKey, formatUserVote(gwxAmountAtEnd, inFavor)), StringEntry(keyUserVoteHistory("vote", userAddress, assetId, toBase58String(i.transactionId), currentPeriod), formatUserVote(gwxAmountAtEnd, inFavor)), getVoteResultAction(assetId, gwxAmountAtEnd, inFavor, currentPeriod, unit)] |
---|
411 | | - | let votesListActions = if (containsNode(votesListName, userAddress)) |
---|
412 | | - | then nil |
---|
413 | | - | else insertNode(votesListName, userAddress) |
---|
414 | | - | $Tuple2((votesListActions ++ userVoteActions), unit) |
---|
415 | | - | } |
---|
416 | | - | else throw("Strict value is not equal to itself.") |
---|
417 | | - | } |
---|
418 | | - | else throw("Strict value is not equal to itself.") |
---|
419 | | - | } |
---|
420 | | - | else throw("Strict value is not equal to itself.") |
---|
421 | | - | } |
---|
422 | | - | else throw("Strict value is not equal to itself.") |
---|
423 | | - | } |
---|
424 | | - | |
---|
425 | | - | |
---|
426 | | - | |
---|
427 | | - | @Callable(i) |
---|
428 | | - | func cancelVote (assetId) = { |
---|
429 | | - | let userAddress = if ((i.caller == this)) |
---|
430 | | - | then toString(i.originCaller) |
---|
431 | | - | else toString(i.caller) |
---|
432 | | - | let votesListName = getVotesListName(assetId) |
---|
433 | | - | let userVoteKey = keyUserVoteByPeriod(userAddress, assetId, currentPeriod) |
---|
434 | | - | let userVoteOrUnit = getString(userVoteKey) |
---|
435 | | - | let $t01631416408 = parseUserVote(valueOrErrorMessage(userVoteOrUnit, "Nothing to cancel")) |
---|
436 | | - | let total = $t01631416408._1 |
---|
437 | | - | let inFavor = $t01631416408._2 |
---|
438 | | - | let votesListActions = deleteNode(votesListName, userAddress) |
---|
439 | | - | let userVoteActions = [DeleteEntry(userVoteKey), StringEntry(keyUserVoteHistory("cancelVote", userAddress, assetId, toBase58String(i.transactionId), currentPeriod), formatUserVote(0, true)), getVoteResultAction(assetId, -(total), inFavor, currentPeriod, unit)] |
---|
440 | | - | $Tuple2((votesListActions ++ userVoteActions), unit) |
---|
441 | | - | } |
---|
442 | | - | |
---|
443 | | - | |
---|
444 | | - | |
---|
445 | | - | @Callable(i) |
---|
446 | | - | func finalizeAssetINTERNAL (assetId,period) = { |
---|
447 | | - | let checkCaller = thisOnly(i) |
---|
448 | | - | if ((checkCaller == checkCaller)) |
---|
449 | | - | then { |
---|
450 | | - | let voteResultKey = keyVoteResultByPeriod(assetId, period) |
---|
451 | | - | let $t01706317242 = match getString(voteResultKey) { |
---|
452 | | - | case s: String => |
---|
453 | | - | let r = parseVoteResult(s) |
---|
454 | | - | $Tuple2(r._1, r._2) |
---|
455 | | - | case _: Unit => |
---|
456 | | - | $Tuple2(0, 0) |
---|
457 | | - | case _ => |
---|
458 | | - | throw("Match error") |
---|
459 | | - | } |
---|
460 | | - | let totalYes = $t01706317242._1 |
---|
461 | | - | let totalNo = $t01706317242._2 |
---|
462 | | - | let total = (totalYes + totalNo) |
---|
463 | | - | let verified = if ((total >= votingThreshold)) |
---|
464 | | - | then (totalYes > totalNo) |
---|
465 | | - | else false |
---|
466 | | - | let assetVerifiedActions = [BooleanEntry(keyAssetVerifiedByPeriod(assetId, period), verified), if (verified) |
---|
467 | | - | then BooleanEntry(keyAssetVerified(assetId), true) |
---|
468 | | - | else DeleteEntry(keyAssetVerified(assetId))] |
---|
469 | | - | let assetsStoreSetVerifiedInv = invoke(assetsStoreContract, "setVerified", [assetId, verified], nil) |
---|
470 | | - | if ((assetsStoreSetVerifiedInv == assetsStoreSetVerifiedInv)) |
---|
471 | | - | then { |
---|
472 | | - | let eliminate = if (verified) |
---|
473 | | - | then false |
---|
474 | | - | else eliminationCheck(assetId) |
---|
475 | | - | let assetWasEliminatedActions = if (eliminate) |
---|
476 | | - | then [BooleanEntry(keyAssetWasEliminated(assetId, currentPeriod), true)] |
---|
477 | | - | else nil |
---|
478 | | - | let voteResultActions = if (eliminate) |
---|
479 | | - | then nil |
---|
480 | | - | else [getVoteResultAction(assetId, 0, true, (currentPeriod + 1), verified)] |
---|
481 | | - | let votesListActions = if (eliminate) |
---|
482 | | - | then deleteNode(assetsListName, assetId) |
---|
483 | | - | else nil |
---|
484 | | - | let onEliminationInv = if (eliminate) |
---|
485 | | - | then invoke(assetsStoreContract, "onEliminate", [assetId], nil) |
---|
486 | | - | else unit |
---|
487 | | - | if ((onEliminationInv == onEliminationInv)) |
---|
488 | | - | then $Tuple2(((votesListActions ++ voteResultActions) ++ assetVerifiedActions), unit) |
---|
489 | | - | else throw("Strict value is not equal to itself.") |
---|
490 | | - | } |
---|
491 | | - | else throw("Strict value is not equal to itself.") |
---|
492 | | - | } |
---|
493 | | - | else throw("Strict value is not equal to itself.") |
---|
494 | | - | } |
---|
495 | | - | |
---|
496 | | - | |
---|
497 | | - | |
---|
498 | | - | @Callable(i) |
---|
499 | | - | func deleteUserNodeINTERNAL (assetId,userAddress,latestProcessedUserRemoveKey) = { |
---|
500 | | - | let checkCaller = thisOnly(i) |
---|
501 | | - | if ((checkCaller == checkCaller)) |
---|
502 | | - | then $Tuple2((deleteNode(getVotesListName(assetId), userAddress) :+ DeleteEntry(latestProcessedUserRemoveKey)), unit) |
---|
503 | | - | else throw("Strict value is not equal to itself.") |
---|
504 | | - | } |
---|
505 | | - | |
---|
506 | | - | |
---|
507 | | - | |
---|
508 | | - | @Callable(i) |
---|
509 | | - | func finalizeVotingHelper () = if ((endHeight > height)) |
---|
510 | | - | then $Tuple2(nil, false) |
---|
511 | | - | else { |
---|
512 | | - | let latestProcessedAssetOrUnit = getString(keyLatestProcessedAsset) |
---|
513 | | - | let latestProcessedUserOrUnit = getString(keyLatestProcessedUser) |
---|
514 | | - | let nextPeriodDelay = 0 |
---|
515 | | - | let finish = $Tuple2([IntegerEntry(keyStartHeight, (height + nextPeriodDelay)), IntegerEntry(keyCurrentPeriod, (currentPeriod + 1)), DeleteEntry(keyLatestProcessedAsset), DeleteEntry(keyLatestProcessedUser), DeleteEntry(keyLatestProcessedAssetTransfer), DeleteEntry(keyLatestProcessedUserTransfer)], true) |
---|
516 | | - | if ((latestProcessedAssetOrUnit == unit)) |
---|
517 | | - | then { |
---|
518 | | - | let assetsHeadOrUnit = getString(keyListHead(assetsListName)) |
---|
519 | | - | if ((assetsHeadOrUnit == unit)) |
---|
520 | | - | then finish |
---|
521 | | - | else { |
---|
522 | | - | let asset = value(assetsHeadOrUnit) |
---|
523 | | - | let userAddressOrUnit = getString(keyListHead(getVotesListName(asset))) |
---|
524 | | - | let processVoteActions = processVote(asset, userAddressOrUnit, keyLatestProcessedAsset, keyLatestProcessedUser, keyLatestProcessedUserRemove) |
---|
525 | | - | $Tuple2(processVoteActions, true) |
---|
526 | | - | } |
---|
527 | | - | } |
---|
528 | | - | else { |
---|
529 | | - | let latestProcessedAsset = value(latestProcessedAssetOrUnit) |
---|
530 | | - | if ((latestProcessedUserOrUnit == unit)) |
---|
531 | | - | then { |
---|
532 | | - | let assetOrUnit = getString(keyListNext(assetsListName, latestProcessedAsset)) |
---|
533 | | - | if ((assetOrUnit == assetOrUnit)) |
---|
534 | | - | then { |
---|
535 | | - | let finalizeAssetInv = invoke(this, "finalizeAssetINTERNAL", [latestProcessedAsset, currentPeriod], nil) |
---|
536 | | - | if ((finalizeAssetInv == finalizeAssetInv)) |
---|
537 | | - | then if ((assetOrUnit == unit)) |
---|
538 | | - | then finish |
---|
539 | | - | else { |
---|
540 | | - | let asset = value(assetOrUnit) |
---|
541 | | - | let userAddressOrUnit = getString(keyListHead(getVotesListName(asset))) |
---|
542 | | - | let processVoteActions = processVote(asset, userAddressOrUnit, keyLatestProcessedAsset, keyLatestProcessedUser, keyLatestProcessedUserRemove) |
---|
543 | | - | $Tuple2(processVoteActions, true) |
---|
544 | | - | } |
---|
545 | | - | else throw("Strict value is not equal to itself.") |
---|
546 | | - | } |
---|
547 | | - | else throw("Strict value is not equal to itself.") |
---|
548 | | - | } |
---|
549 | | - | else { |
---|
550 | | - | let latestProcessedUser = value(latestProcessedUserOrUnit) |
---|
551 | | - | let userAddressOrUnit = getString(keyListNext(getVotesListName(latestProcessedAsset), latestProcessedUser)) |
---|
552 | | - | if ((userAddressOrUnit == userAddressOrUnit)) |
---|
553 | | - | then { |
---|
554 | | - | let removeLatestUser = valueOrElse(getBoolean(keyLatestProcessedUserRemove), false) |
---|
555 | | - | let deleteUserInv = if (removeLatestUser) |
---|
556 | | - | then invoke(this, "deleteUserNodeINTERNAL", [latestProcessedAsset, latestProcessedUser, keyLatestProcessedUserRemove], nil) |
---|
557 | | - | else unit |
---|
558 | | - | if ((deleteUserInv == deleteUserInv)) |
---|
559 | | - | then { |
---|
560 | | - | let processVoteActions = processVote(latestProcessedAsset, userAddressOrUnit, keyLatestProcessedAsset, keyLatestProcessedUser, keyLatestProcessedUserRemove) |
---|
561 | | - | $Tuple2(processVoteActions, true) |
---|
562 | | - | } |
---|
563 | | - | else throw("Strict value is not equal to itself.") |
---|
564 | | - | } |
---|
565 | | - | else throw("Strict value is not equal to itself.") |
---|
566 | | - | } |
---|
567 | | - | } |
---|
568 | | - | } |
---|
569 | | - | |
---|
570 | | - | |
---|
571 | | - | |
---|
572 | | - | @Callable(i) |
---|
573 | | - | func finalizeVotingWrapper (counter) = { |
---|
574 | | - | let result = asBool(invoke(this, "finalizeVotingHelper", nil, nil)) |
---|
575 | | - | if ((result == result)) |
---|
576 | | - | then if (!(result)) |
---|
577 | | - | then if ((counter == 0)) |
---|
578 | | - | then throw("Current voting is not over yet") |
---|
579 | | - | else $Tuple2(nil, unit) |
---|
580 | | - | else if ((maxDepth > counter)) |
---|
581 | | - | then { |
---|
582 | | - | let inv = invoke(this, "finalizeVotingWrapper", [(counter + 1)], nil) |
---|
583 | | - | if ((inv == inv)) |
---|
584 | | - | then $Tuple2(nil, unit) |
---|
585 | | - | else throw("Strict value is not equal to itself.") |
---|
586 | | - | } |
---|
587 | | - | else $Tuple2(nil, unit) |
---|
588 | | - | else throw("Strict value is not equal to itself.") |
---|
589 | | - | } |
---|
590 | | - | |
---|
591 | | - | |
---|
592 | | - | |
---|
593 | | - | @Callable(i) |
---|
594 | | - | func finalizeVoting () = { |
---|
595 | | - | let inv = invoke(this, "finalizeVotingWrapper", [0], nil) |
---|
596 | | - | if ((inv == inv)) |
---|
597 | | - | then $Tuple2(nil, unit) |
---|
598 | | - | else throw("Strict value is not equal to itself.") |
---|
599 | | - | } |
---|
600 | | - | |
---|
601 | | - | |
---|
602 | | - | |
---|
603 | | - | @Callable(i) |
---|
604 | | - | func transferVotesHelper () = { |
---|
605 | | - | let votesTransferFinishedKey = keyVotesTransferFinishedByPeriod(currentPeriod) |
---|
606 | | - | let votesTransferFinished = valueOrElse(getBoolean(votesTransferFinishedKey), false) |
---|
607 | | - | if (if (if ((startHeight > height)) |
---|
608 | | - | then true |
---|
609 | | - | else (height >= endHeight)) |
---|
610 | | - | then true |
---|
611 | | - | else votesTransferFinished) |
---|
612 | | - | then $Tuple2(nil, false) |
---|
613 | | - | else { |
---|
614 | | - | let latestProcessedAssetOrUnit = getString(keyLatestProcessedAssetTransfer) |
---|
615 | | - | let latestProcessedUserOrUnit = getString(keyLatestProcessedUserTransfer) |
---|
616 | | - | let finish = $Tuple2([BooleanEntry(votesTransferFinishedKey, true), DeleteEntry(keyLatestProcessedAssetTransfer), DeleteEntry(keyLatestProcessedUserTransfer)], true) |
---|
617 | | - | if ((latestProcessedAssetOrUnit == unit)) |
---|
618 | | - | then { |
---|
619 | | - | let assetsHeadOrUnit = getString(keyListHead(assetsListName)) |
---|
620 | | - | if ((assetsHeadOrUnit == unit)) |
---|
621 | | - | then finish |
---|
622 | | - | else { |
---|
623 | | - | let asset = value(assetsHeadOrUnit) |
---|
624 | | - | let userAddressOrUnit = getString(keyListHead(getVotesListName(asset))) |
---|
625 | | - | let processVoteActions = processVote(asset, userAddressOrUnit, keyLatestProcessedAssetTransfer, keyLatestProcessedUserTransfer, keyLatestProcessedUserRemoveTransfer) |
---|
626 | | - | $Tuple2(processVoteActions, true) |
---|
627 | | - | } |
---|
628 | | - | } |
---|
629 | | - | else { |
---|
630 | | - | let latestProcessedAsset = value(latestProcessedAssetOrUnit) |
---|
631 | | - | if ((latestProcessedUserOrUnit == unit)) |
---|
632 | | - | then { |
---|
633 | | - | let assetOrUnit = getString(keyListNext(assetsListName, latestProcessedAsset)) |
---|
634 | | - | if ((assetOrUnit == unit)) |
---|
635 | | - | then finish |
---|
636 | | - | else { |
---|
637 | | - | let asset = value(assetOrUnit) |
---|
638 | | - | let userAddressOrUnit = getString(keyListHead(getVotesListName(asset))) |
---|
639 | | - | let processVoteActions = processVote(asset, userAddressOrUnit, keyLatestProcessedAssetTransfer, keyLatestProcessedUserTransfer, keyLatestProcessedUserRemoveTransfer) |
---|
640 | | - | $Tuple2(processVoteActions, true) |
---|
641 | | - | } |
---|
642 | | - | } |
---|
643 | | - | else { |
---|
644 | | - | let latestProcessedUser = value(latestProcessedUserOrUnit) |
---|
645 | | - | let userAddressOrUnit = getString(keyListNext(getVotesListName(latestProcessedAsset), latestProcessedUser)) |
---|
646 | | - | if ((userAddressOrUnit == userAddressOrUnit)) |
---|
647 | | - | then { |
---|
648 | | - | let removeLatestUser = valueOrElse(getBoolean(keyLatestProcessedUserRemoveTransfer), false) |
---|
649 | | - | let deleteUserInv = if (removeLatestUser) |
---|
650 | | - | then invoke(this, "deleteUserNodeINTERNAL", [latestProcessedAsset, latestProcessedUser, keyLatestProcessedUserRemoveTransfer], nil) |
---|
651 | | - | else unit |
---|
652 | | - | if ((deleteUserInv == deleteUserInv)) |
---|
653 | | - | then { |
---|
654 | | - | let processVoteActions = processVote(latestProcessedAsset, userAddressOrUnit, keyLatestProcessedAssetTransfer, keyLatestProcessedUserTransfer, keyLatestProcessedUserRemoveTransfer) |
---|
655 | | - | $Tuple2(processVoteActions, true) |
---|
656 | | - | } |
---|
657 | | - | else throw("Strict value is not equal to itself.") |
---|
658 | | - | } |
---|
659 | | - | else throw("Strict value is not equal to itself.") |
---|
660 | | - | } |
---|
661 | | - | } |
---|
662 | | - | } |
---|
663 | | - | } |
---|
664 | | - | |
---|
665 | | - | |
---|
666 | | - | |
---|
667 | | - | @Callable(i) |
---|
668 | | - | func transferVotesWrapper (counter) = { |
---|
669 | | - | let result = asBool(invoke(this, "transferVotesHelper", nil, nil)) |
---|
670 | | - | if ((result == result)) |
---|
671 | | - | then if (!(result)) |
---|
672 | | - | then if ((counter == 0)) |
---|
673 | | - | then throw("Voting is not started yet") |
---|
674 | | - | else $Tuple2(nil, unit) |
---|
675 | | - | else if ((maxDepth > counter)) |
---|
676 | | - | then { |
---|
677 | | - | let inv = invoke(this, "transferVotesWrapper", [(counter + 1)], nil) |
---|
678 | | - | if ((inv == inv)) |
---|
679 | | - | then $Tuple2(nil, unit) |
---|
680 | | - | else throw("Strict value is not equal to itself.") |
---|
681 | | - | } |
---|
682 | | - | else $Tuple2(nil, unit) |
---|
683 | | - | else throw("Strict value is not equal to itself.") |
---|
684 | | - | } |
---|
685 | | - | |
---|
686 | | - | |
---|
687 | | - | |
---|
688 | | - | @Callable(i) |
---|
689 | | - | func transferVotes () = { |
---|
690 | | - | let inv = invoke(this, "transferVotesWrapper", [0], nil) |
---|
691 | | - | if ((inv == inv)) |
---|
692 | | - | then $Tuple2(nil, unit) |
---|
693 | | - | else throw("Strict value is not equal to itself.") |
---|
694 | | - | } |
---|
695 | | - | |
---|
696 | | - | |
---|
697 | | - | |
---|
698 | | - | @Callable(i) |
---|
699 | | - | func setVotingThreshold (newThreshold) = { |
---|
700 | | - | let checkCaller = thisOnly(i) |
---|
701 | | - | if ((checkCaller == checkCaller)) |
---|
702 | | - | then $Tuple2([IntegerEntry(keyVotingThreshold, newThreshold)], unit) |
---|
703 | | - | else throw("Strict value is not equal to itself.") |
---|
704 | | - | } |
---|
705 | | - | |
---|
706 | | - | |
---|
707 | | - | |
---|
708 | | - | @Callable(i) |
---|
709 | | - | func setFee (newFee) = { |
---|
710 | | - | let checkCaller = thisOnly(i) |
---|
711 | | - | if ((checkCaller == checkCaller)) |
---|
712 | | - | then $Tuple2([IntegerEntry(keyFeeAmount, newFee)], unit) |
---|
713 | | - | else throw("Strict value is not equal to itself.") |
---|
714 | | - | } |
---|
715 | | - | |
---|
716 | | - | |
---|
717 | | - | |
---|
718 | | - | @Callable(i) |
---|
719 | | - | func gwxAvailableForVoteREADONLY (userAddress) = { |
---|
720 | | - | let gwxAmountAtEnd = getUserGwxAmountAtHeight(userAddress, endHeight) |
---|
721 | | - | $Tuple2(nil, gwxAmountAtEnd) |
---|
722 | | - | } |
---|
723 | | - | |
---|
724 | | - | |
---|
| 1 | + | # no script |
---|