tx · EishfpvG6BJojn83BtsqmZmoAXfYpSVs6Kf8CuV7P6PJ 3MvsqDUjgwou6Q8kxvUE4Rydq3aTAoGM4ez: -0.01800000 Waves 2024.09.24 00:26 [3296771] smart account 3MvsqDUjgwou6Q8kxvUE4Rydq3aTAoGM4ez > SELF 0.00000000 Waves
{ "type": 13, "id": "EishfpvG6BJojn83BtsqmZmoAXfYpSVs6Kf8CuV7P6PJ", "fee": 1800000, "feeAssetId": null, "timestamp": 1727126859523, "version": 2, "chainId": 84, "sender": "3MvsqDUjgwou6Q8kxvUE4Rydq3aTAoGM4ez", "senderPublicKey": "G6Zojn5ShR3qnxHQU6Q8bQm9RCojVPtMWH2j2i6dUbmi", "proofs": [ "2oRQcGgfkhYEDCuaDAr8sCji4bEHxWnW6JQyAURn1i6ScC4KFm7BSSGa5PRze5rC47Z31bapTr7dKBshLpSWMWrG" ], "script": "base64:AAIFAAAAAAAAACsIAhIHCgUICAgICBIFCgMICAgSAwoBCBIDCgEIEgMKAQgSAwoBCBIDCgEIAAAANwEAAAAHdGhyb3dJZgAAAAIAAAAJY29uZGl0aW9uAAAABWVycm9yAwUAAAAJY29uZGl0aW9uCQAAAgAAAAEFAAAABWVycm9yBgEAAAAObm9uRW1wdHlTdHJpbmcAAAACAAAAAXMAAAADa2V5AwkAAGcAAAACAAAAAAAAAAAACQABMQAAAAEFAAAAAXMJAAACAAAAAQkAASwAAAACAgAAAA5lbXB0eSBzdHJpbmc6IAUAAAADa2V5BgEAAAALd3JpdGVTdHJpbmcAAAACAAAAA2tleQAAAAV2YWx1ZQMJAABnAAAAAgAAAAAAAAAAAAkAATEAAAABBQAAAAV2YWx1ZQkAAAIAAAABCQABLAAAAAICAAAADmVtcHR5IHN0cmluZzogBQAAAANrZXkJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAAA2tleQUAAAAFdmFsdWUBAAAACHdyaXRlSW50AAAAAgAAAANrZXkAAAAFdmFsdWUDCQAAZgAAAAIAAAAAAAAAAAAFAAAABXZhbHVlCQAAAgAAAAEJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAF3dyaXRpbmcgbmVnYXRpdmUgdmFsdWUgCQABpAAAAAEFAAAABXZhbHVlAgAAAAkgZm9yIGtleSAFAAAAA2tleQkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAA2tleQUAAAAFdmFsdWUBAAAAEHdyaXRlQ29uc3RTdHJpbmcAAAACAAAAA2tleQAAAAV2YWx1ZQMDCQEAAAABIQAAAAEJAQAAAAlpc0RlZmluZWQAAAABCQAEHQAAAAIFAAAABHRoaXMFAAAAA2tleQkBAAAADm5vbkVtcHR5U3RyaW5nAAAAAgUAAAAFdmFsdWUFAAAAA2tleQcJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAAA2tleQUAAAAFdmFsdWUJAAACAAAAAQkAASwAAAACAgAAABVhbHJlYWR5IGluaXRpYWxpemVkOiAFAAAAA2tleQEAAAANd3JpdGVDb25zdEludAAAAAIAAAADa2V5AAAABXZhbHVlAwkBAAAAASEAAAABCQEAAAAJaXNEZWZpbmVkAAAAAQkABBoAAAACBQAAAAR0aGlzBQAAAANrZXkJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAANrZXkFAAAABXZhbHVlCQAAAgAAAAEJAAEsAAAAAgIAAAAQYWxyZWFkeSBleGlzdHM6IAUAAAADa2V5AQAAAAhjaGFuZ2VCeQAAAAIAAAADa2V5AAAABXZhbHVlCQEAAAAId3JpdGVJbnQAAAACBQAAAANrZXkJAABkAAAAAgkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAR0aGlzBQAAAANrZXkAAAAAAAAAAAAFAAAABXZhbHVlAQAAAAVhc0ludAAAAAEAAAAFdmFsdWUEAAAAByRtYXRjaDAFAAAABXZhbHVlAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAANJbnQEAAAAA2ludAUAAAAHJG1hdGNoMAUAAAADaW50CQAAAgAAAAECAAAAGXdyb25nIHR5cGUsIGV4cGVjdGVkOiBJbnQAAAAAEmNvbmZpZ0FkZHJlc3NTdG9yZQIAAAAGY29uZmlnAAAAAA1jb25maWdBZGRyZXNzCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQmAAAAAQkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEHQAAAAIFAAAABHRoaXMFAAAAEmNvbmZpZ0FkZHJlc3NTdG9yZQIAAAAJbm8gY29uZmlnAgAAABZpbnZhbGlkIGNvbmZpZyBhZGRyZXNzAAAAAAZ2b3RpbmcJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABCYAAAABCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQdAAAAAgUAAAANY29uZmlnQWRkcmVzcwIAAAAWY29udHJhY3Rfdm90aW5nX3Jlc3VsdAIAAAAZbm8gY29udHJhY3Rfdm90aW5nX3Jlc3VsdAIAAAAeaW52YWxpZCBjb250cmFjdF92b3RpbmdfcmVzdWx0AAAAAAdzdGFraW5nCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQmAAAAAQkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEHQAAAAIFAAAADWNvbmZpZ0FkZHJlc3MCAAAAEGNvbnRyYWN0X3N0YWtpbmcCAAAA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dXNlcmRhdGEJAQAAABp1c2VyTGFzdFByb3Bvc2VIZWlnaHRTdG9yZQAAAAEFAAAABHVzZXIA//////////8AAAAAC3RoaXNBZGRyZXNzCQAEJQAAAAEFAAAABHRoaXMAAAAAEHVzZXJQcm9wb3NlRGVsYXkJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABBoAAAACBQAAAA1jb25maWdBZGRyZXNzCQABLAAAAAIFAAAAC3RoaXNBZGRyZXNzAgAAABNfdXNlcl9wcm9wb3NlX2RlbGF5AgAAACJfdXNlcl9wcm9wb3NlX2RlbGF5IGlzIG5vdCBkZWZpbmVkAAAAAAtxdW9ydW1SYXRpbwkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEGgAAAAIFAAAADWNvbmZpZ0FkZHJlc3MJAAEsAAAAAgUAAAALdGhpc0FkZHJlc3MCAAAAFl9wcm9wb3NhbF9xdW9ydW1fcmF0aW8CAAAAJV9wcm9wb3NhbF9xdW9ydW1fcmF0aW8gaXMgbm90IGRlZmluZWQBAAAAE3Byb3Bvc2FsUXVvcnVtU3RvcmUAAAABAAAABHR4aWQJAAEsAAAAAgIAAAAWcHJvcG9zYWxfcXVvcnVtX3JhdGlvXwUAAAAEdHhpZAAAAAALcGFzc2VkUmF0aW8JAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABBoAAAACBQAAAA1jb25maWdBZGRyZXNzCQABLAAAAAIFAAAAC3RoaXNBZGRyZXNzAgAAABZfcHJvcG9zYWxfcGFzc2VkX3JhdGlvAgAAACVfcHJvcG9zYWxfcGFzc2VkX3JhdGlvIGlzIG5vdCBkZWZpbmVkAAAAABNwcm9wb3NhbE1pblJlcXVpcmVkCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAANY29uZmlnQWRkcmVzcwkAASwAAAACBQAAAAt0aGlzQWRkcmVzcwIAAAAWX3Byb3Bvc2FsX21pbl9yZXF1aXJlZAIAAAAlX3Byb3Bvc2FsX21pbl9yZXF1aXJlZCBpcyBub3QgZGVmaW5lZAAAAAARdm90aW5nU3RhcnRPZmZzZXQJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABBoAAAACBQAAAA1jb25maWdBZGRyZXNzCQABLAAAAAIFAAAAC3RoaXNBZGRyZXNzAgAAABxfcHJvcG9zYWxfdm90aW5nc3RhcnRfb2Zmc2V0AgAAACtfcHJvcG9zYWxfdm90aW5nc3RhcnRfb2Zmc2V0IGlzIG5vdCBkZWZpbmVkAAAAAA92b3RpbmdFbmRPZmZzZXQJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABBoAAAACBQAAAA1jb25maWdBZGRyZXNzCQABLAAAAAIFAAAAC3RoaXNBZGRyZXNzAgAAABpfcHJvcG9zYWxfdm90aW5nZW5kX29mZnNldAIAAAApX3Byb3Bvc2FsX3ZvdGluZ2VuZF9vZmZzZXQgaXMgbm90IGRlZmluZWQBAAAACXVzZXJTdGFrZQAAAAEAAAAEdXNlcgkBAAAABWFzSW50AAAAAQkAA/wAAAAEBQAAAAdzdGFraW5nAgAAAAl1c2VyU3Rha2UJAARMAAAAAgUAAAAEdXNlcgUAAAADbmlsBQAAAANuaWwBAAAADnByb3Bvc2FsRXhpc3RzAAAAAQAAAAR0eElkBAAAAAckbWF0Y2gwCQAEGgAAAAIFAAAABHRoaXMJAQAAAAtoZWlnaHRTdG9yZQAAAAEFAAAABHR4SWQDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAA0ludAQAAAAFc3RhcnQFAAAAByRtYXRjaDAGBwEAAAAQcHJvcG9zYWxPblZvdGluZwAAAAEAAAAEdHhJZAQAAAALbm9uRXhpc3RFcnICAAAAFnByb3Bvc2FsIGRvZXNuJ3QgZXhpc3QDCQEAAAABIQAAAAEJAQAAAA5wcm9wb3NhbEV4aXN0cwAAAAEFAAAABHR4SWQJAAACAAAAAQUAAAALbm9uRXhpc3RFcnIEAAAAC3ZvdGluZ1N0YXJ0CQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAAEdGhpcwkBAAAAEHZvdGluZ1N0YXJ0U3RvcmUAAAABBQAAAAR0eElkBQAAAAtub25FeGlzdEVycgQAAAAJdm90aW5nRW5kCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAAEdGhpcwkBAAAADnZvdGluZ0VuZFN0b3JlAAAAAQUAAAAEdHhJZAUA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", "height": 3296771, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: none Next: none Full:
Old | New | Differences | |
---|---|---|---|
1 | - | # no script | |
1 | + | {-# STDLIB_VERSION 5 #-} | |
2 | + | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | + | {-# CONTENT_TYPE DAPP #-} | |
4 | + | func throwIf (condition,error) = if (condition) | |
5 | + | then throw(error) | |
6 | + | else true | |
7 | + | ||
8 | + | ||
9 | + | func nonEmptyString (s,key) = if ((0 >= size(s))) | |
10 | + | then throw(("empty string: " + key)) | |
11 | + | else true | |
12 | + | ||
13 | + | ||
14 | + | func writeString (key,value) = if ((0 >= size(value))) | |
15 | + | then throw(("empty string: " + key)) | |
16 | + | else StringEntry(key, value) | |
17 | + | ||
18 | + | ||
19 | + | func writeInt (key,value) = if ((0 > value)) | |
20 | + | then throw(((("writing negative value " + toString(value)) + " for key ") + key)) | |
21 | + | else IntegerEntry(key, value) | |
22 | + | ||
23 | + | ||
24 | + | func writeConstString (key,value) = if (if (!(isDefined(getString(this, key)))) | |
25 | + | then nonEmptyString(value, key) | |
26 | + | else false) | |
27 | + | then StringEntry(key, value) | |
28 | + | else throw(("already initialized: " + key)) | |
29 | + | ||
30 | + | ||
31 | + | func writeConstInt (key,value) = if (!(isDefined(getInteger(this, key)))) | |
32 | + | then IntegerEntry(key, value) | |
33 | + | else throw(("already exists: " + key)) | |
34 | + | ||
35 | + | ||
36 | + | func changeBy (key,value) = writeInt(key, (valueOrElse(getInteger(this, key), 0) + value)) | |
37 | + | ||
38 | + | ||
39 | + | func asInt (value) = match value { | |
40 | + | case int: Int => | |
41 | + | int | |
42 | + | case _ => | |
43 | + | throw("wrong type, expected: Int") | |
44 | + | } | |
45 | + | ||
46 | + | ||
47 | + | let configAddressStore = "config" | |
48 | + | ||
49 | + | let configAddress = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(this, configAddressStore), "no config")), "invalid config address") | |
50 | + | ||
51 | + | let voting = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(configAddress, "contract_voting_result"), "no contract_voting_result")), "invalid contract_voting_result") | |
52 | + | ||
53 | + | let staking = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(configAddress, "contract_staking"), "no contract_staking")), "invalid contract_staking") | |
54 | + | ||
55 | + | let userdata = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(configAddress, "contract_user_data"), "no contract_user_data")), "invalid contract_user_data") | |
56 | + | ||
57 | + | let HEIGHT = height | |
58 | + | ||
59 | + | func advise () = ("height: " + toString(HEIGHT)) | |
60 | + | ||
61 | + | ||
62 | + | let BASE = 1000 | |
63 | + | ||
64 | + | func opAllowed (op) = { | |
65 | + | let s = invoke(configAddress, "opAllowed", [op], nil) | |
66 | + | if ((s == s)) | |
67 | + | then true | |
68 | + | else throw("Strict value is not equal to itself.") | |
69 | + | } | |
70 | + | ||
71 | + | ||
72 | + | func addressStore (id) = ("proposal_address_" + id) | |
73 | + | ||
74 | + | ||
75 | + | func heightStore (id) = ("proposal_height_" + id) | |
76 | + | ||
77 | + | ||
78 | + | func votingStartStore (id) = ("proposal_votingstart_" + id) | |
79 | + | ||
80 | + | ||
81 | + | func votingEndStore (id) = ("proposal_votingend_" + id) | |
82 | + | ||
83 | + | ||
84 | + | func byStore (id) = ("proposal_by_" + id) | |
85 | + | ||
86 | + | ||
87 | + | func descriptionStore (id) = ("proposal_description_" + id) | |
88 | + | ||
89 | + | ||
90 | + | func titleStore (id) = ("proposal_title_" + id) | |
91 | + | ||
92 | + | ||
93 | + | func payloadStore (id) = ("proposal_payload_" + id) | |
94 | + | ||
95 | + | ||
96 | + | func maxSnapStore (id) = ("proposal_max_snap_" + id) | |
97 | + | ||
98 | + | ||
99 | + | func totalYesStore (id) = ("proposal_yes_" + id) | |
100 | + | ||
101 | + | ||
102 | + | func totalNoStore (id) = ("proposal_no_" + id) | |
103 | + | ||
104 | + | ||
105 | + | func userYesStore (user,id) = ((("proposal_yes_user_" + id) + "_") + user) | |
106 | + | ||
107 | + | ||
108 | + | func userNoStore (user,id) = ((("proposal_no_user_" + id) + "_") + user) | |
109 | + | ||
110 | + | ||
111 | + | func userLastProposeHeightStore (user) = ("propose_lastheight_" + user) | |
112 | + | ||
113 | + | ||
114 | + | func userYes (user,id) = valueOrElse(getInteger(userdata, userYesStore(user, id)), 0) | |
115 | + | ||
116 | + | ||
117 | + | func userNo (user,id) = valueOrElse(getInteger(userdata, userNoStore(user, id)), 0) | |
118 | + | ||
119 | + | ||
120 | + | func userLastProposeHeight (user) = valueOrElse(getInteger(userdata, userLastProposeHeightStore(user)), -1) | |
121 | + | ||
122 | + | ||
123 | + | let thisAddress = toString(this) | |
124 | + | ||
125 | + | let userProposeDelay = valueOrErrorMessage(getInteger(configAddress, (thisAddress + "_user_propose_delay")), "_user_propose_delay is not defined") | |
126 | + | ||
127 | + | let quorumRatio = valueOrErrorMessage(getInteger(configAddress, (thisAddress + "_proposal_quorum_ratio")), "_proposal_quorum_ratio is not defined") | |
128 | + | ||
129 | + | func proposalQuorumStore (txid) = ("proposal_quorum_ratio_" + txid) | |
130 | + | ||
131 | + | ||
132 | + | let passedRatio = valueOrErrorMessage(getInteger(configAddress, (thisAddress + "_proposal_passed_ratio")), "_proposal_passed_ratio is not defined") | |
133 | + | ||
134 | + | let proposalMinRequired = valueOrErrorMessage(getInteger(configAddress, (thisAddress + "_proposal_min_required")), "_proposal_min_required is not defined") | |
135 | + | ||
136 | + | let votingStartOffset = valueOrErrorMessage(getInteger(configAddress, (thisAddress + "_proposal_votingstart_offset")), "_proposal_votingstart_offset is not defined") | |
137 | + | ||
138 | + | let votingEndOffset = valueOrErrorMessage(getInteger(configAddress, (thisAddress + "_proposal_votingend_offset")), "_proposal_votingend_offset is not defined") | |
139 | + | ||
140 | + | func userStake (user) = asInt(invoke(staking, "userStake", [user], nil)) | |
141 | + | ||
142 | + | ||
143 | + | func proposalExists (txId) = match getInteger(this, heightStore(txId)) { | |
144 | + | case start: Int => | |
145 | + | true | |
146 | + | case _ => | |
147 | + | false | |
148 | + | } | |
149 | + | ||
150 | + | ||
151 | + | func proposalOnVoting (txId) = { | |
152 | + | let nonExistErr = "proposal doesn't exist" | |
153 | + | if (!(proposalExists(txId))) | |
154 | + | then throw(nonExistErr) | |
155 | + | else { | |
156 | + | let votingStart = valueOrErrorMessage(getInteger(this, votingStartStore(txId)), nonExistErr) | |
157 | + | let votingEnd = valueOrErrorMessage(getInteger(this, votingEndStore(txId)), nonExistErr) | |
158 | + | if ((votingStart > HEIGHT)) | |
159 | + | then throw(((("voting not started yet, discussion is in progress, voting will start at block " + toString(votingStart)) + ", now it's ") + toString(HEIGHT))) | |
160 | + | else if ((HEIGHT > votingEnd)) | |
161 | + | then throw(((("voting ended at block " + toString(votingEnd)) + ", now it's ") + toString(HEIGHT))) | |
162 | + | else true | |
163 | + | } | |
164 | + | } | |
165 | + | ||
166 | + | ||
167 | + | func proposalBeforeVoting (txId) = { | |
168 | + | let nonExistErr = "proposal doesn't exist" | |
169 | + | if (!(proposalExists(txId))) | |
170 | + | then throw(nonExistErr) | |
171 | + | else { | |
172 | + | let votingStart = valueOrErrorMessage(getInteger(this, votingStartStore(txId)), nonExistErr) | |
173 | + | if ((HEIGHT >= votingStart)) | |
174 | + | then throw("voting start is already happened") | |
175 | + | else true | |
176 | + | } | |
177 | + | } | |
178 | + | ||
179 | + | ||
180 | + | func totalStake () = asInt(invoke(staking, "totalStake", nil, nil)) | |
181 | + | ||
182 | + | ||
183 | + | func quorum (txId) = valueOrElse(getInteger(proposalQuorumStore(txId)), quorumRatio) | |
184 | + | ||
185 | + | ||
186 | + | func canBroadcast (id,yesInc,noInc) = { | |
187 | + | let votesYes = (valueOrElse(getInteger(("proposal_yes_" + id)), 0) + yesInc) | |
188 | + | let votesNo = (valueOrElse(getInteger(("proposal_no_" + id)), 0) + noInc) | |
189 | + | let total = totalStake() | |
190 | + | let totalVotes = (votesYes + votesNo) | |
191 | + | let hasQuorum = (((totalVotes * BASE) / total) >= quorum(id)) | |
192 | + | let hasPassed = (((votesYes * BASE) / totalVotes) >= passedRatio) | |
193 | + | if (hasQuorum) | |
194 | + | then hasPassed | |
195 | + | else false | |
196 | + | } | |
197 | + | ||
198 | + | ||
199 | + | func adviseProposalUserVotes (txId,user) = { | |
200 | + | let yes = userYes(user, txId) | |
201 | + | let no = userNo(user, txId) | |
202 | + | let txAddress = valueOrErrorMessage(getString(addressStore(txId)), "proposal address not found") | |
203 | + | ((((("height: " + toString(HEIGHT)) + ", vote_yes: ") + toString(yes)) + ", vote_no: ") + toString(no)) | |
204 | + | } | |
205 | + | ||
206 | + | ||
207 | + | func adviseProposal (txId) = { | |
208 | + | let proposalHeight = valueOrErrorMessage(getInteger(heightStore(txId)), "no proposal") | |
209 | + | let votingStart = valueOrErrorMessage(getInteger(votingStartStore(txId)), "no proposal") | |
210 | + | let votingEnd = valueOrErrorMessage(getInteger(votingEndStore(txId)), "no proposal") | |
211 | + | let votesYes = valueOrElse(getInteger(totalYesStore(txId)), 0) | |
212 | + | let votesNo = valueOrElse(getInteger(totalNoStore(txId)), 0) | |
213 | + | let maxSnap = valueOrElse(getInteger(maxSnapStore(txId)), 0) | |
214 | + | let totalVotes = (votesYes + votesNo) | |
215 | + | let q = quorum(txId) | |
216 | + | let hasQuorum = if ((totalVotes > 0)) | |
217 | + | then (((totalVotes * BASE) / maxSnap) >= q) | |
218 | + | else false | |
219 | + | let hasPassed = if ((totalVotes > 0)) | |
220 | + | then (((votesYes * BASE) / totalVotes) >= passedRatio) | |
221 | + | else false | |
222 | + | let inBlockchainHeight = valueOrElse(transactionHeightById(fromBase58String(txId)), 0) | |
223 | + | let status = if ((votingStart > HEIGHT)) | |
224 | + | then "discussion" | |
225 | + | else if ((votingEnd >= HEIGHT)) | |
226 | + | then "voting" | |
227 | + | else if (!(hasQuorum)) | |
228 | + | then "noQuorum" | |
229 | + | else if (!(hasPassed)) | |
230 | + | then "votingFailed" | |
231 | + | else if ((inBlockchainHeight > 0)) | |
232 | + | then "inBlockchain" | |
233 | + | else "waitingForTx" | |
234 | + | ((((((((((((((((((((((((((((((("height: " + toString(HEIGHT)) + ", proposal_id: ") + txId) + ", proposal_title: ") + getStringValue(titleStore(txId))) + ", proposal_address: ") + valueOrErrorMessage(addressStore(txId), "no address")) + ", proposal_status: ") + status) + ", proposal_by: ") + valueOrErrorMessage(getString(this, byStore(txId)), "no proposal")) + ", proposal_height: ") + toString(proposalHeight)) + ", proposal_txheight: ") + toString(inBlockchainHeight)) + ", proposal_votingstart: ") + toString(votingStart)) + ", proposal_votingend: ") + toString(votingEnd)) + ", proposal_max: ") + toString(maxSnap)) + ", vote_yes: ") + toString(votesYes)) + ", vote_no: ") + toString(votesNo)) + ", proposal_quorum: ") + toString(q)) + ", proposal_description: ") + getStringValue(descriptionStore(txId))) + ", proposal_payload: ") + getStringValue(payloadStore(txId))) | |
235 | + | } | |
236 | + | ||
237 | + | ||
238 | + | func broadcastHeight (txId) = (getIntegerValue(votingEndStore(txId)) + 1) | |
239 | + | ||
240 | + | ||
241 | + | func setResult (txAddress,txId,result) = invoke(voting, "setResult", [txAddress, txId, result, broadcastHeight(txId)], nil) | |
242 | + | ||
243 | + | ||
244 | + | func setMaxSnap (txId) = IntegerEntry(maxSnapStore(txId), totalStake()) | |
245 | + | ||
246 | + | ||
247 | + | func lock (user,txId) = { | |
248 | + | let votingEnd = getIntegerValue(votingEndStore(txId)) | |
249 | + | let unlock = (votingEnd + 1) | |
250 | + | invoke(staking, "lockFor", [user, unlock], nil) | |
251 | + | } | |
252 | + | ||
253 | + | ||
254 | + | @Callable(i) | |
255 | + | func propose (address,txId,title,description,payload) = { | |
256 | + | let checks = opAllowed("governance_propose_tx") | |
257 | + | if ((checks == checks)) | |
258 | + | then { | |
259 | + | let user = toString(i.caller) | |
260 | + | let gv = userStake(user) | |
261 | + | if ((proposalMinRequired > gv)) | |
262 | + | then throw((((("not enough staked units to make proposal." + " Minimum required = ") + toString(proposalMinRequired)) + ", actual: = ") + toString(gv))) | |
263 | + | else { | |
264 | + | let last = userLastProposeHeight(user) | |
265 | + | if (if ((last > -1)) | |
266 | + | then ((last + userProposeDelay) > HEIGHT) | |
267 | + | else false) | |
268 | + | then throw(((("can't propose too often, last proroposal height: " + toString(last)) + ", blocks to wait: ") + toString(((last + userProposeDelay) - HEIGHT)))) | |
269 | + | else { | |
270 | + | let votingEnds = (HEIGHT + votingEndOffset) | |
271 | + | let l = invoke(userdata, "write", [userLastProposeHeightStore(user), HEIGHT], nil) | |
272 | + | if ((l == l)) | |
273 | + | then [writeConstInt(heightStore(txId), HEIGHT), setMaxSnap(txId), writeConstInt(votingStartStore(txId), (HEIGHT + votingStartOffset)), writeConstInt(votingEndStore(txId), votingEnds), writeConstString(byStore(txId), toString(i.caller)), writeConstString(addressStore(txId), address), IntegerEntry(proposalQuorumStore(txId), quorumRatio), writeString(descriptionStore(txId), description), writeString(payloadStore(txId), payload), writeConstString(titleStore(txId), title)] | |
274 | + | else throw("Strict value is not equal to itself.") | |
275 | + | } | |
276 | + | } | |
277 | + | } | |
278 | + | else throw("Strict value is not equal to itself.") | |
279 | + | } | |
280 | + | ||
281 | + | ||
282 | + | ||
283 | + | @Callable(i) | |
284 | + | func edit (txId,title,description) = { | |
285 | + | let checks = if (opAllowed("governance_edit_attachments")) | |
286 | + | then proposalBeforeVoting(txId) | |
287 | + | else false | |
288 | + | if ((checks == checks)) | |
289 | + | then { | |
290 | + | let user = toString(i.caller) | |
291 | + | let by = valueOrErrorMessage(getString(this, byStore(txId)), "proposal doesn't exist") | |
292 | + | if ((by != user)) | |
293 | + | then throw("only owner can edit proposal attachments e.g. title, description") | |
294 | + | else [writeString(titleStore(txId), title), writeString(descriptionStore(txId), description)] | |
295 | + | } | |
296 | + | else throw("Strict value is not equal to itself.") | |
297 | + | } | |
298 | + | ||
299 | + | ||
300 | + | ||
301 | + | @Callable(i) | |
302 | + | func voteYes (txId) = { | |
303 | + | let checks = if (opAllowed("governance_vote_tx")) | |
304 | + | then proposalOnVoting(txId) | |
305 | + | else false | |
306 | + | if ((checks == checks)) | |
307 | + | then { | |
308 | + | let user = toString(i.caller) | |
309 | + | if ((userNo(user, txId) > 0)) | |
310 | + | then throw("already voted against, please retract your vote first") | |
311 | + | else { | |
312 | + | let yesDelta = (userStake(user) - userYes(user, txId)) | |
313 | + | let l = lock(user, txId) | |
314 | + | if ((l == l)) | |
315 | + | then { | |
316 | + | let txAddress = valueOrErrorMessage(getString(addressStore(txId)), "proposal address not found") | |
317 | + | let result = canBroadcast(txId, yesDelta, 0) | |
318 | + | let s = setResult(txAddress, txId, result) | |
319 | + | if ((s == s)) | |
320 | + | then { | |
321 | + | let y = invoke(userdata, "changeBy", [userYesStore(user, txId), yesDelta], nil) | |
322 | + | if ((y == y)) | |
323 | + | then [setMaxSnap(txId), changeBy(totalYesStore(txId), yesDelta)] | |
324 | + | else throw("Strict value is not equal to itself.") | |
325 | + | } | |
326 | + | else throw("Strict value is not equal to itself.") | |
327 | + | } | |
328 | + | else throw("Strict value is not equal to itself.") | |
329 | + | } | |
330 | + | } | |
331 | + | else throw("Strict value is not equal to itself.") | |
332 | + | } | |
333 | + | ||
334 | + | ||
335 | + | ||
336 | + | @Callable(i) | |
337 | + | func voteNo (txId) = { | |
338 | + | let checks = if (opAllowed("governance_vote_tx")) | |
339 | + | then proposalOnVoting(txId) | |
340 | + | else false | |
341 | + | if ((checks == checks)) | |
342 | + | then { | |
343 | + | let user = toString(i.caller) | |
344 | + | if ((userYes(user, txId) > 0)) | |
345 | + | then throw("already voted for, please retract your vote first") | |
346 | + | else { | |
347 | + | let noDelta = (userStake(user) - userNo(user, txId)) | |
348 | + | let l = lock(user, txId) | |
349 | + | if ((l == l)) | |
350 | + | then { | |
351 | + | let txAddress = valueOrErrorMessage(getString(addressStore(txId)), "proposal address not found") | |
352 | + | let result = canBroadcast(txId, 0, noDelta) | |
353 | + | let s = setResult(txAddress, txId, result) | |
354 | + | if ((s == s)) | |
355 | + | then { | |
356 | + | let n = invoke(userdata, "changeBy", [userNoStore(user, txId), noDelta], nil) | |
357 | + | if ((n == n)) | |
358 | + | then [setMaxSnap(txId), changeBy(totalNoStore(txId), noDelta)] | |
359 | + | else throw("Strict value is not equal to itself.") | |
360 | + | } | |
361 | + | else throw("Strict value is not equal to itself.") | |
362 | + | } | |
363 | + | else throw("Strict value is not equal to itself.") | |
364 | + | } | |
365 | + | } | |
366 | + | else throw("Strict value is not equal to itself.") | |
367 | + | } | |
368 | + | ||
369 | + | ||
370 | + | ||
371 | + | @Callable(i) | |
372 | + | func retract (txId) = { | |
373 | + | let checks = if (opAllowed("governance_retract_vote")) | |
374 | + | then proposalOnVoting(txId) | |
375 | + | else false | |
376 | + | if ((checks == checks)) | |
377 | + | then { | |
378 | + | let user = toString(i.caller) | |
379 | + | let yes = userYes(user, txId) | |
380 | + | let no = userNo(user, txId) | |
381 | + | let txAddress = valueOrErrorMessage(getString(addressStore(txId)), "proposal address not found") | |
382 | + | let result = canBroadcast(txId, -(yes), -(no)) | |
383 | + | let s = setResult(txAddress, txId, result) | |
384 | + | if ((s == s)) | |
385 | + | then { | |
386 | + | let y = invoke(userdata, "delete", [userYesStore(user, txId)], nil) | |
387 | + | if ((y == y)) | |
388 | + | then { | |
389 | + | let n = invoke(userdata, "delete", [userNoStore(user, txId)], nil) | |
390 | + | if ((n == n)) | |
391 | + | then [changeBy(totalYesStore(txId), -(yes)), changeBy(totalNoStore(txId), -(no))] | |
392 | + | else throw("Strict value is not equal to itself.") | |
393 | + | } | |
394 | + | else throw("Strict value is not equal to itself.") | |
395 | + | } | |
396 | + | else throw("Strict value is not equal to itself.") | |
397 | + | } | |
398 | + | else throw("Strict value is not equal to itself.") | |
399 | + | } | |
400 | + | ||
401 | + | ||
402 | + | ||
403 | + | @Callable(i) | |
404 | + | func retractProposal (txId) = { | |
405 | + | let checks = if (opAllowed("governance_retract_proposal_tx")) | |
406 | + | then proposalBeforeVoting(txId) | |
407 | + | else false | |
408 | + | if ((checks == checks)) | |
409 | + | then { | |
410 | + | let by = valueOrErrorMessage(getString(this, byStore(txId)), "proposal doesn't exist") | |
411 | + | let user = toString(i.caller) | |
412 | + | if ((by != user)) | |
413 | + | then throw("only owner can retract proposal") | |
414 | + | else { | |
415 | + | let l = invoke(userdata, "delete", [userLastProposeHeightStore(user)], nil) | |
416 | + | if ((l == l)) | |
417 | + | then [DeleteEntry(heightStore(txId)), DeleteEntry(votingStartStore(txId)), DeleteEntry(votingEndStore(txId)), DeleteEntry(byStore(txId)), DeleteEntry(maxSnapStore(txId)), DeleteEntry(totalYesStore(txId)), DeleteEntry(totalNoStore(txId)), DeleteEntry(addressStore(txId)), DeleteEntry(titleStore(txId)), DeleteEntry(payloadStore(txId))] | |
418 | + | else throw("Strict value is not equal to itself.") | |
419 | + | } | |
420 | + | } | |
421 | + | else throw("Strict value is not equal to itself.") | |
422 | + | } | |
423 | + | ||
424 | + | ||
425 | + | ||
426 | + | @Callable(i) | |
427 | + | func init (config) = [writeConstString(configAddressStore, config)] | |
428 | + | ||
429 | + |
github/deemru/w8io/169f3d6 35.81 ms ◑![]()