2022.04.12 16:53 [3070765] smart account 3PKNPHY8VX4XnrrvQ6ery7VqFtmmisD4aUX > SELF 0.00000000 Waves
{ "type": 13, "id": "g1PjQNjoxpnFy7y24ceNJ5QQYFmjegA33ZcsnK452bG", "fee": 1000000, "feeAssetId": null, "timestamp": 1649771652555, "version": 1, "sender": "3PKNPHY8VX4XnrrvQ6ery7VqFtmmisD4aUX", "senderPublicKey": "HAPfoagGYsU8zKTqRhYq6ouE8GZ9TERrtmnCaxdHaf1H", "proofs": [ "5vG256UY3gwhTshEQcuHXgZi8nhD25ZS2DdHFdUxyLbcB1BkZPHZ2NoTHgeLmAoz8p3Z2XzpNPuD41GiZSez6okP" ], "script": "base64:AAIFAAAAAAAAACAIAhIDCgEIEgMKAQgSAwoBCBIDCgEIEgMKAQgSAwoBCAAAACoBAAAAB3Rocm93SWYAAAACAAAACWNvbmRpdGlvbgAAAAVlcnJvcgMFAAAACWNvbmRpdGlvbgkAAAIAAAABBQAAAAVlcnJvcgYBAAAACHdyaXRlSW50AAAAAgAAAANrZXkAAAAFdmFsdWUDCQAAZgAAAAIAAAAAAAAAAAAFAAAABXZhbHVlCQAAAgAAAAEJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAF3dyaXRpbmcgbmVnYXRpdmUgdmFsdWUgCQABpAAAAAEFAAAABXZhbHVlAgAAAAkgZm9yIGtleSAFAAAAA2tleQkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAA2tleQUAAAAFdmFsdWUBAAAAEHdyaXRlQ29uc3RTdHJpbmcAAAACAAAAA2tleQAAAAV2YWx1ZQMJAQAAAAEhAAAAAQkBAAAACWlzRGVmaW5lZAAAAAEJAAQdAAAAAgUAAAAEdGhpcwUAAAADa2V5CQEAAAALU3RyaW5nRW50cnkAAAACBQAAAANrZXkFAAAABXZhbHVlCQAAAgAAAAEJAAEsAAAAAgIAAAAVYWxyZWFkeSBpbml0aWFsaXplZDogBQAAAANrZXkBAAAADXdyaXRlQ29uc3RJbnQAAAACAAAAA2tleQAAAAV2YWx1ZQMJAQAAAAEhAAAAAQkBAAAACWlzRGVmaW5lZAAAAAEJAAQaAAAAAgUAAAAEdGhpcwUAAAADa2V5CQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAADa2V5BQAAAAV2YWx1ZQkAAAIAAAABCQABLAAAAAICAAAAEGFscmVhZHkgZXhpc3RzOiAFAAAAA2tleQEAAAAIY2hhbmdlQnkAAAACAAAAA2tleQAAAAV2YWx1ZQkBAAAACHdyaXRlSW50AAAAAgUAAAADa2V5CQAAZAAAAAIJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQaAAAAAgUAAAAEdGhpcwUAAAADa2V5AAAAAAAAAAAABQAAAAV2YWx1ZQEAAAAFYXNJbnQAAAABAAAABXZhbHVlBAAAAAckbWF0Y2gwBQAAAAV2YWx1ZQMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAADSW50BAAAAANpbnQFAAAAByRtYXRjaDAFAAAAA2ludAkAAAIAAAABAgAAABl3cm9uZyB0eXBlLCBleHBlY3RlZDogSW50AAAAABJjb25maWdBZGRyZXNzU3RvcmUCAAAADWNvbmZpZ0FkZHJlc3MAAAAADWNvbmZpZ0FkZHJlc3MJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABCYAAAABCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQdAAAAAgUAAAAEdGhpcwUAAAASY29uZmlnQWRkcmVzc1N0b3JlAgAAABh2b3Rpbmc6IG5vIGNvbmZpZ0FkZHJlc3MCAAAAFmludmFsaWQgY29uZmlnIGFkZHJlc3MAAAAAEm1heWJlT3JhY2xlQWRkcmVzcwQAAAAHJG1hdGNoMAkABB0AAAACBQAAAA1jb25maWdBZGRyZXNzAgAAAA5vcmFjbGVfYWRkcmVzcwMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAGU3RyaW5nBAAAAAFzBQAAAAckbWF0Y2gwCQAEJgAAAAEFAAAAAXMFAAAABHVuaXQAAAAABkhFSUdIVAUAAAAGaGVpZ2h0AAAAAARCQVNFAAAAAAAAAAPoAQAAAAlvcEFsbG93ZWQAAAABAAAAAm9wBAAAAANhaWQCAAAABnZvdGluZwQAAAAHJG1hdGNoMAkAA/wAAAAEBQAAAA1jb25maWdBZGRyZXNzAgAAAAlvcEFsbG93ZWQJAARMAAAAAgUAAAADYWlkCQAETAAAAAIFAAAAAm9wBQAAAANuaWwFAAAAA25pbAMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAHQm9vbGVhbgQAAAABYgUAAAAHJG1hdGNoMAMFAAAAAWIGCQAAAgAAAAECAAAAC25vdCBhbGxvd2VkCQAAAgAAAAECAAAAIW9wQWxsb3dlZDogdW5leHBlY3RlZCByZXN1bHQgdHlwZQAAAAAOZ1ZpcmVzQ29udHJhY3QJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABCYAAAABCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQdAAAAAgUAAAANY29uZmlnQWRkcmVzcwIAAAASZGl2aWRlbmRzX2NvbnRyYWN0AgAAABVubyBkaXZpZGVuZHNfY29udHJhY3QCAAAAGmludmFsaWQgZGl2aWRlbmRzX2NvbnRyYWN0AQAAABNwcm9wb3NhbEhlaWdodFN0b3JlAAAAAQAAAAJpZAkAASwAAAACAgAAABBwcm9wb3NhbF9oZWlnaHRfBQAAAAJpZAEAAAAYcHJvcG9zYWxWb3RpbmdTdGFydFN0b3JlAAAAAQAAAAJpZAkAASwAAAACAgAAABVwcm9wb3NhbF92b3RpbmdzdGFydF8FAAAAAmlkAQAAABdwcm9wb3NhbEFwcGx5U3RhcnRTdG9yZQAAAAEAAAACaWQJAAEsAAAAAgIAAAAUcHJvcG9zYWxfYXBwbHlzdGFydF8FAAAAAmlkAQAAABZwcm9wb3NhbFZvdGluZ0VuZFN0b3JlAAAAAQAAAAJpZAkAASwAAAACAgAAABNwcm9wb3NhbF92b3RpbmdlbmRfBQAAAAJpZAEAAAAVcHJvcG9zYWxBcHBseUVuZFN0b3JlAAAAAQAAAAJpZAkAASwAAAACAgAAABJwcm9wb3NhbF9hcHBseWVuZF8FAAAAAmlkAQAAAA9wcm9wb3NhbEJ5U3RvcmUAAAABAAAAAmlkCQABLAAAAAICAAAADHByb3Bvc2FsX2J5XwUAAAACaWQBAAAAGHByb3Bvc2FsVG90YWxHVmlyZXNTdG9yZQAAAAEAAAACaWQJAAEsAAAAAgIAAAAQcHJvcG9zYWxfZ3ZpcmVzXwUAAAACaWQBAAAAFXByb3Bvc2FsVG90YWxZZXNTdG9yZQAAAAEAAAACaWQJAAEsAAAAAgIAAAANcHJvcG9zYWxfeWVzXwUAAAACaWQBAAAAFHByb3Bvc2FsVG90YWxOb1N0b3JlAAAAAQAAAAJpZAkAASwAAAACAgAAAAxwcm9wb3NhbF9ub18FAAAAAmlkAQAAABRwcm9wb3NhbFVzZXJZZXNTdG9yZQAAAAIAAAAEdXNlcgAAAAJpZAkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAASdXNlcl9wcm9wb3NhbF95ZXNfBQAAAAR1c2VyAgAAAAFfBQAAAAJpZAEAAAATcHJvcG9zYWxVc2VyTm9TdG9yZQAAAAIAAAAEdXNlcgAAAAJpZAkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAARdXNlcl9wcm9wb3NhbF9ub18FAAAABHVzZXICAAAAAV8FAAAAAmlkAQAAABp1c2VyTGFzdFByb3Bvc2VIZWlnaHRTdG9yZQAAAAEAAAAEdXNlcgkAASwAAAACAgAAABNwcm9wb3NlX2xhc3RoZWlnaHRfBQAAAAR1c2VyAQAAAAd1c2VyWWVzAAAAAgAAAAR1c2VyAAAAAmlkCQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAABHRoaXMJAQAAABRwcm9wb3NhbFVzZXJZZXNTdG9yZQAAAAIFAAAABHVzZXIFAAAAAmlkAAAAAAAAAAAAAQAAAAZ1c2VyTm8AAAACAAAABHVzZXIAAAACaWQJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQaAAAAAgUAAAAEdGhpcwkBAAAAE3Byb3Bvc2FsVXNlck5vU3RvcmUAAAACBQAAAAR1c2VyBQAAAAJpZAAAAAAAAAAAAAEAAAAVdXNlckxhc3RQcm9wb3NlSGVpZ2h0AAAAAQAAAAR1c2VyCQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAABHRoaXMJAQAAABp1c2VyTGFzdFByb3Bvc2VIZWlnaHRTdG9yZQAAAAEFAAAABHVzZXIA//////////8AAAAAEHVzZXJQcm9wb3NlRGVsYXkJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABBoAAAACBQAAAA1jb25maWdBZGRyZXNzAgAAABJ1c2VyX3Byb3Bvc2VfZGVsYXkCAAAAIXVzZXJfcHJvcG9zZV9kZWxheSBpcyBub3QgZGVmaW5lZAAAAAALcXVvcnVtUmF0aW8JAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABBoAAAACBQAAAA1jb25maWdBZGRyZXNzAgAAABVwcm9wb3NhbF9xdW9ydW1fcmF0aW8CAAAAInByb3Bvc2FsUXVvcnVtUmF0aW8gaXMgbm90IGRlZmluZWQAAAAAC3Bhc3NlZFJhdGlvCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAANY29uZmlnQWRkcmVzcwIAAAAVcHJvcG9zYWxfcGFzc2VkX3JhdGlvAgAAACVwcm9wb3NhbFRocmVzaG9sZFJhdGlvIGlzIG5vdCBkZWZpbmVkAAAAABNwcm9wb3NhbE1pblJlcXVpcmVkCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAANY29uZmlnQWRkcmVzcwIAAAAbcHJvcG9zYWxfbWluX3ZpcmVzX3JlcXVpcmVkAgAAABttaW4gcmVxdWlyZWQgaXMgbm90IGRlZmluZWQAAAAAEXZvdGluZ1N0YXJ0T2Zmc2V0CQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAANY29uZmlnQWRkcmVzcwIAAAAbcHJvcG9zYWxfdm90aW5nc3RhcnRfb2Zmc2V0AgAAACpwcm9wb3NhbF92b3RpbmdzdGFydF9vZmZzZXQgaXMgbm90IGRlZmluZWQAAAAAD3ZvdGluZ0VuZE9mZnNldAkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEGgAAAAIFAAAADWNvbmZpZ0FkZHJlc3MCAAAAGXByb3Bvc2FsX3ZvdGluZ2VuZF9vZmZzZXQCAAAAKHByb3Bvc2FsX3ZvdGluZ2VuZF9vZmZzZXQgaXMgbm90IGRlZmluZWQAAAAAEGFwcGx5U3RhcnRPZmZzZXQJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABBoAAAACBQAAAA1jb25maWdBZGRyZXNzAgAAABpwcm9wb3NhbF9hcHBseXN0YXJ0X29mZnNldAIAAAApcHJvcG9zYWxfYXBwbHlzdGFydF9vZmZzZXQgaXMgbm90IGRlZmluZWQAAAAADmFwcGx5RW5kT2Zmc2V0CQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAANY29uZmlnQWRkcmVzcwIAAAAYcHJvcG9zYWxfYXBwbHllbmRfb2Zmc2V0AgAAACdwcm9wb3NhbF9hcHBseWVuZF9vZmZzZXQgaXMgbm90IGRlZmluZWQBAAAACnVzZXJHdmlyZXMAAAABAAAABHVzZXIJAQAAAAVhc0ludAAAAAEJAAP8AAAABAUAAAAOZ1ZpcmVzQ29udHJhY3QCAAAACXVzZXJQb3dlcgkABEwAAAACBQAAAAR1c2VyBQAAAANuaWwFAAAAA25pbAEAAAAOcHJvcG9zYWxFeGlzdHMAAAABAAAABHR4SWQEAAAAByRtYXRjaDAJAAQaAAAAAgUAAAAEdGhpcwkBAAAAE3Byb3Bvc2FsSGVpZ2h0U3RvcmUAAAABBQAAAAR0eElkAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAANJbnQEAAAABXN0YXJ0BQAAAAckbWF0Y2gwBgcBAAAAEHByb3Bvc2FsT25Wb3RpbmcAAAABAAAABHR4SWQEAAAAC25vbkV4aXN0RXJyAgAAABZwcm9wb3NhbCBkb2Vzbid0IGV4aXN0AwkBAAAAASEAAAABCQEAAAAOcHJvcG9zYWxFeGlzdHMAAAABBQAAAAR0eElkCQAAAgAAAAEFAAAAC25vbkV4aXN0RXJyBAAAAAt2b3RpbmdTdGFydAkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEGgAAAAIFAAAABHRoaXMJAQAAABhwcm9wb3NhbFZvdGluZ1N0YXJ0U3RvcmUAAAABBQAAAAR0eElkBQAAAAtub25FeGlzdEVycgQAAAAJdm90aW5nRW5kCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAAEdGhpcwkBAAAAFnByb3Bvc2FsVm90aW5nRW5kU3RvcmUAAAABBQAAAAR0eElkBQAAAAtub25FeGlzdEVycgMJAABmAAAAAgUAAAALdm90aW5nU3RhcnQFAAAABkhFSUdIVAkAAAIAAAABCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAE52b3Rpbmcgbm90IHN0YXJ0ZWQgeWV0LCBkaXNjdXNzaW9uIGlzIGluIHByb2dyZXNzLCB2b3Rpbmcgd2lsbCBzdGFydCBhdCBibG9jayAJAAGkAAAAAQUAAAALdm90aW5nU3RhcnQCAAAACywgbm93IGl0J3MgCQABpAAAAAEFAAAABkhFSUdIVAMJAABmAAAAAgUAAAAGSEVJR0hUBQAAAAl2b3RpbmdFbmQJAAACAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAWdm90aW5nIGVuZGVkIGF0IGJsb2NrIAkAAaQAAAABBQAAAAl2b3RpbmdFbmQCAAAACywgbm93IGl0J3MgCQABpAAAAAEFAAAABkhFSUdIVAYBAAAAFHByb3Bvc2FsQmVmb3JlVm90aW5nAAAAAQAAAAR0eElkBAAAAAtub25FeGlzdEVycgIAAAAWcHJvcG9zYWwgZG9lc24ndCBleGlzdAMJAQAAAAEhAAAAAQkBAAAADnByb3Bvc2FsRXhpc3RzAAAAAQUAAAAEdHhJZAkAAAIAAAABBQAAAAtub25FeGlzdEVycgQAAAALdm90aW5nU3RhcnQJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABBoAAAACBQAAAAR0aGlzCQEAAAAYcHJvcG9zYWxWb3RpbmdTdGFydFN0b3JlAAAAAQUAAAAEdHhJZAUAAAALbm9uRXhpc3RFcnIDCQAAZwAAAAIFAAAABkhFSUdIVAUAAAALdm90aW5nU3RhcnQJAAACAAAAAQIAAAAgdm90aW5nIHN0YXJ0IGlzIGFscmVhZHkgaGFwcGVuZWQGAQAAAAt0b3RhbEdWaXJlcwAAAAAJAQAAAAVhc0ludAAAAAEJAAP8AAAABAUAAAAOZ1ZpcmVzQ29udHJhY3QCAAAAC3RvdGFsR3ZpcmVzBQAAAANuaWwFAAAAA25pbAEAAAAOYWR2aXNlUHJvcG9zYWwAAAABAAAABHR4SWQEAAAADnByb3Bvc2FsSGVpZ2h0CQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAAEdGhpcwkBAAAAE3Byb3Bvc2FsSGVpZ2h0U3RvcmUAAAABBQAAAAR0eElkAgAAAAtubyBwcm9wb3NhbAQAAAALdm90aW5nU3RhcnQJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABBoAAAACBQAAAAR0aGlzCQEAAAAYcHJvcG9zYWxWb3RpbmdTdGFydFN0b3JlAAAAAQUAAAAEdHhJZAIAAAALbm8gcHJvcG9zYWwEAAAACXZvdGluZ0VuZAkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEGgAAAAIFAAAABHRoaXMJAQAAABZwcm9wb3NhbFZvdGluZ0VuZFN0b3JlAAAAAQUAAAAEdHhJZAIAAAALbm8gcHJvcG9zYWwEAAAACmFwcGx5U3RhcnQJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABBoAAAACBQAAAAR0aGlzCQEAAAAXcHJvcG9zYWxBcHBseVN0YXJ0U3RvcmUAAAABBQAAAAR0eElkAgAAAAtubyBwcm9wb3NhbAQAAAAIYXBwbHlF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cnkAAAABCQEAAAAYcHJvcG9zYWxWb3RpbmdTdGFydFN0b3JlAAAAAQUAAAAEdHhJZAkABEwAAAACCQEAAAALRGVsZXRlRW50cnkAAAABCQEAAAAWcHJvcG9zYWxWb3RpbmdFbmRTdG9yZQAAAAEFAAAABHR4SWQJAARMAAAAAgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQkBAAAAF3Byb3Bvc2FsQXBwbHlTdGFydFN0b3JlAAAAAQUAAAAEdHhJZAkABEwAAAACCQEAAAALRGVsZXRlRW50cnkAAAABCQEAAAAVcHJvcG9zYWxBcHBseUVuZFN0b3JlAAAAAQUAAAAEdHhJZAkABEwAAAACCQEAAAALRGVsZXRlRW50cnkAAAABCQEAAAAPcHJvcG9zYWxCeVN0b3JlAAAAAQUAAAAEdHhJZAkABEwAAAACCQEAAAALRGVsZXRlRW50cnkAAAABCQEAAAAYcHJvcG9zYWxUb3RhbEdWaXJlc1N0b3JlAAAAAQUAAAAEdHhJZAkABEwAAAACCQEAAAALRGVsZXRlRW50cnkAAAABCQEAAAAVcHJvcG9zYWxUb3RhbFllc1N0b3JlAAAAAQUAAAAEdHhJZAkABEwAAAACCQEAAAALRGVsZXRlRW50cnkAAAABCQEAAAAUcHJvcG9zYWxUb3RhbE5vU3RvcmUAAAABBQAAAAR0eElkCQAETAAAAAIJAQAAAAtEZWxldGVFbnRyeQAAAAEJAQAAABRwcm9wb3NhbFVzZXJZZXNTdG9yZQAAAAIFAAAABHVzZXIFAAAABHR4SWQJAARMAAAAAgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQkBAAAAE3Byb3Bvc2FsVXNlck5vU3RvcmUAAAACBQAAAAR1c2VyBQAAAAR0eElkCQAETAAAAAIJAQAAAAtEZWxldGVFbnRyeQAAAAEJAQAAABp1c2VyTGFzdFByb3Bvc2VIZWlnaHRTdG9yZQAAAAEFAAAABHVzZXIFAAAAA25pbAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAAATtm88Q==", "chainId": 87, "height": 3070765, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: DBrtTa69NH8c6ovJUXiXKxzgM6Lh4jn4PyHE1wBavGiZ Next: 5EWEVxciYqifAcuXViqRyYJXKebiei7jj27nNazVGyjt Diff:
Old | New | Differences | |
---|---|---|---|
150 | 150 | } | |
151 | 151 | ||
152 | 152 | ||
153 | + | func proposalBeforeVoting (txId) = { | |
154 | + | let nonExistErr = "proposal doesn't exist" | |
155 | + | if (!(proposalExists(txId))) | |
156 | + | then throw(nonExistErr) | |
157 | + | else { | |
158 | + | let votingStart = valueOrErrorMessage(getInteger(this, proposalVotingStartStore(txId)), nonExistErr) | |
159 | + | if ((HEIGHT >= votingStart)) | |
160 | + | then throw("voting start is already happened") | |
161 | + | else true | |
162 | + | } | |
163 | + | } | |
164 | + | ||
165 | + | ||
153 | 166 | func totalGVires () = asInt(invoke(gViresContract, "totalGvires", nil, nil)) | |
154 | 167 | ||
155 | 168 | ||
281 | 294 | } | |
282 | 295 | ||
283 | 296 | ||
297 | + | ||
298 | + | @Callable(i) | |
299 | + | func retractProposal (txId) = { | |
300 | + | let checks = if (opAllowed("governance_retract_proposal_tx")) | |
301 | + | then proposalBeforeVoting(txId) | |
302 | + | else false | |
303 | + | if ((checks == checks)) | |
304 | + | then { | |
305 | + | let by = valueOrErrorMessage(getString(this, proposalByStore(txId)), "proposal doesn't exist") | |
306 | + | let user = toString(i.caller) | |
307 | + | if ((by != user)) | |
308 | + | then throw("only owner can retract proposal") | |
309 | + | else [DeleteEntry(proposalHeightStore(txId)), DeleteEntry(proposalVotingStartStore(txId)), DeleteEntry(proposalVotingEndStore(txId)), DeleteEntry(proposalApplyStartStore(txId)), DeleteEntry(proposalApplyEndStore(txId)), DeleteEntry(proposalByStore(txId)), DeleteEntry(proposalTotalGViresStore(txId)), DeleteEntry(proposalTotalYesStore(txId)), DeleteEntry(proposalTotalNoStore(txId)), DeleteEntry(proposalUserYesStore(user, txId)), DeleteEntry(proposalUserNoStore(user, txId)), DeleteEntry(userLastProposeHeightStore(user))] | |
310 | + | } | |
311 | + | else throw("Strict value is not equal to itself.") | |
312 | + | } | |
313 | + | ||
314 | + |
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 5 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | 4 | func throwIf (condition,error) = if (condition) | |
5 | 5 | then throw(error) | |
6 | 6 | else true | |
7 | 7 | ||
8 | 8 | ||
9 | 9 | func writeInt (key,value) = if ((0 > value)) | |
10 | 10 | then throw(((("writing negative value " + toString(value)) + " for key ") + key)) | |
11 | 11 | else IntegerEntry(key, value) | |
12 | 12 | ||
13 | 13 | ||
14 | 14 | func writeConstString (key,value) = if (!(isDefined(getString(this, key)))) | |
15 | 15 | then StringEntry(key, value) | |
16 | 16 | else throw(("already initialized: " + key)) | |
17 | 17 | ||
18 | 18 | ||
19 | 19 | func writeConstInt (key,value) = if (!(isDefined(getInteger(this, key)))) | |
20 | 20 | then IntegerEntry(key, value) | |
21 | 21 | else throw(("already exists: " + key)) | |
22 | 22 | ||
23 | 23 | ||
24 | 24 | func changeBy (key,value) = writeInt(key, (valueOrElse(getInteger(this, key), 0) + value)) | |
25 | 25 | ||
26 | 26 | ||
27 | 27 | func asInt (value) = match value { | |
28 | 28 | case int: Int => | |
29 | 29 | int | |
30 | 30 | case _ => | |
31 | 31 | throw("wrong type, expected: Int") | |
32 | 32 | } | |
33 | 33 | ||
34 | 34 | ||
35 | 35 | let configAddressStore = "configAddress" | |
36 | 36 | ||
37 | 37 | let configAddress = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(this, configAddressStore), "voting: no configAddress")), "invalid config address") | |
38 | 38 | ||
39 | 39 | let maybeOracleAddress = match getString(configAddress, "oracle_address") { | |
40 | 40 | case s: String => | |
41 | 41 | addressFromString(s) | |
42 | 42 | case _ => | |
43 | 43 | unit | |
44 | 44 | } | |
45 | 45 | ||
46 | 46 | let HEIGHT = height | |
47 | 47 | ||
48 | 48 | let BASE = 1000 | |
49 | 49 | ||
50 | 50 | func opAllowed (op) = { | |
51 | 51 | let aid = "voting" | |
52 | 52 | match invoke(configAddress, "opAllowed", [aid, op], nil) { | |
53 | 53 | case b: Boolean => | |
54 | 54 | if (b) | |
55 | 55 | then true | |
56 | 56 | else throw("not allowed") | |
57 | 57 | case _ => | |
58 | 58 | throw("opAllowed: unexpected result type") | |
59 | 59 | } | |
60 | 60 | } | |
61 | 61 | ||
62 | 62 | ||
63 | 63 | let gViresContract = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(configAddress, "dividends_contract"), "no dividends_contract")), "invalid dividends_contract") | |
64 | 64 | ||
65 | 65 | func proposalHeightStore (id) = ("proposal_height_" + id) | |
66 | 66 | ||
67 | 67 | ||
68 | 68 | func proposalVotingStartStore (id) = ("proposal_votingstart_" + id) | |
69 | 69 | ||
70 | 70 | ||
71 | 71 | func proposalApplyStartStore (id) = ("proposal_applystart_" + id) | |
72 | 72 | ||
73 | 73 | ||
74 | 74 | func proposalVotingEndStore (id) = ("proposal_votingend_" + id) | |
75 | 75 | ||
76 | 76 | ||
77 | 77 | func proposalApplyEndStore (id) = ("proposal_applyend_" + id) | |
78 | 78 | ||
79 | 79 | ||
80 | 80 | func proposalByStore (id) = ("proposal_by_" + id) | |
81 | 81 | ||
82 | 82 | ||
83 | 83 | func proposalTotalGViresStore (id) = ("proposal_gvires_" + id) | |
84 | 84 | ||
85 | 85 | ||
86 | 86 | func proposalTotalYesStore (id) = ("proposal_yes_" + id) | |
87 | 87 | ||
88 | 88 | ||
89 | 89 | func proposalTotalNoStore (id) = ("proposal_no_" + id) | |
90 | 90 | ||
91 | 91 | ||
92 | 92 | func proposalUserYesStore (user,id) = ((("user_proposal_yes_" + user) + "_") + id) | |
93 | 93 | ||
94 | 94 | ||
95 | 95 | func proposalUserNoStore (user,id) = ((("user_proposal_no_" + user) + "_") + id) | |
96 | 96 | ||
97 | 97 | ||
98 | 98 | func userLastProposeHeightStore (user) = ("propose_lastheight_" + user) | |
99 | 99 | ||
100 | 100 | ||
101 | 101 | func userYes (user,id) = valueOrElse(getInteger(this, proposalUserYesStore(user, id)), 0) | |
102 | 102 | ||
103 | 103 | ||
104 | 104 | func userNo (user,id) = valueOrElse(getInteger(this, proposalUserNoStore(user, id)), 0) | |
105 | 105 | ||
106 | 106 | ||
107 | 107 | func userLastProposeHeight (user) = valueOrElse(getInteger(this, userLastProposeHeightStore(user)), -1) | |
108 | 108 | ||
109 | 109 | ||
110 | 110 | let userProposeDelay = valueOrErrorMessage(getInteger(configAddress, "user_propose_delay"), "user_propose_delay is not defined") | |
111 | 111 | ||
112 | 112 | let quorumRatio = valueOrErrorMessage(getInteger(configAddress, "proposal_quorum_ratio"), "proposalQuorumRatio is not defined") | |
113 | 113 | ||
114 | 114 | let passedRatio = valueOrErrorMessage(getInteger(configAddress, "proposal_passed_ratio"), "proposalThresholdRatio is not defined") | |
115 | 115 | ||
116 | 116 | let proposalMinRequired = valueOrErrorMessage(getInteger(configAddress, "proposal_min_vires_required"), "min required is not defined") | |
117 | 117 | ||
118 | 118 | let votingStartOffset = valueOrErrorMessage(getInteger(configAddress, "proposal_votingstart_offset"), "proposal_votingstart_offset is not defined") | |
119 | 119 | ||
120 | 120 | let votingEndOffset = valueOrErrorMessage(getInteger(configAddress, "proposal_votingend_offset"), "proposal_votingend_offset is not defined") | |
121 | 121 | ||
122 | 122 | let applyStartOffset = valueOrErrorMessage(getInteger(configAddress, "proposal_applystart_offset"), "proposal_applystart_offset is not defined") | |
123 | 123 | ||
124 | 124 | let applyEndOffset = valueOrErrorMessage(getInteger(configAddress, "proposal_applyend_offset"), "proposal_applyend_offset is not defined") | |
125 | 125 | ||
126 | 126 | func userGvires (user) = asInt(invoke(gViresContract, "userPower", [user], nil)) | |
127 | 127 | ||
128 | 128 | ||
129 | 129 | func proposalExists (txId) = match getInteger(this, proposalHeightStore(txId)) { | |
130 | 130 | case start: Int => | |
131 | 131 | true | |
132 | 132 | case _ => | |
133 | 133 | false | |
134 | 134 | } | |
135 | 135 | ||
136 | 136 | ||
137 | 137 | func proposalOnVoting (txId) = { | |
138 | 138 | let nonExistErr = "proposal doesn't exist" | |
139 | 139 | if (!(proposalExists(txId))) | |
140 | 140 | then throw(nonExistErr) | |
141 | 141 | else { | |
142 | 142 | let votingStart = valueOrErrorMessage(getInteger(this, proposalVotingStartStore(txId)), nonExistErr) | |
143 | 143 | let votingEnd = valueOrErrorMessage(getInteger(this, proposalVotingEndStore(txId)), nonExistErr) | |
144 | 144 | if ((votingStart > HEIGHT)) | |
145 | 145 | then throw(((("voting not started yet, discussion is in progress, voting will start at block " + toString(votingStart)) + ", now it's ") + toString(HEIGHT))) | |
146 | 146 | else if ((HEIGHT > votingEnd)) | |
147 | 147 | then throw(((("voting ended at block " + toString(votingEnd)) + ", now it's ") + toString(HEIGHT))) | |
148 | 148 | else true | |
149 | 149 | } | |
150 | 150 | } | |
151 | 151 | ||
152 | 152 | ||
153 | + | func proposalBeforeVoting (txId) = { | |
154 | + | let nonExistErr = "proposal doesn't exist" | |
155 | + | if (!(proposalExists(txId))) | |
156 | + | then throw(nonExistErr) | |
157 | + | else { | |
158 | + | let votingStart = valueOrErrorMessage(getInteger(this, proposalVotingStartStore(txId)), nonExistErr) | |
159 | + | if ((HEIGHT >= votingStart)) | |
160 | + | then throw("voting start is already happened") | |
161 | + | else true | |
162 | + | } | |
163 | + | } | |
164 | + | ||
165 | + | ||
153 | 166 | func totalGVires () = asInt(invoke(gViresContract, "totalGvires", nil, nil)) | |
154 | 167 | ||
155 | 168 | ||
156 | 169 | func adviseProposal (txId) = { | |
157 | 170 | let proposalHeight = valueOrErrorMessage(getInteger(this, proposalHeightStore(txId)), "no proposal") | |
158 | 171 | let votingStart = valueOrErrorMessage(getInteger(this, proposalVotingStartStore(txId)), "no proposal") | |
159 | 172 | let votingEnd = valueOrErrorMessage(getInteger(this, proposalVotingEndStore(txId)), "no proposal") | |
160 | 173 | let applyStart = valueOrErrorMessage(getInteger(this, proposalApplyStartStore(txId)), "no proposal") | |
161 | 174 | let applyEnd = valueOrErrorMessage(getInteger(this, proposalApplyEndStore(txId)), "no proposal") | |
162 | 175 | let votesYes = valueOrElse(getInteger(this, proposalTotalYesStore(txId)), 0) | |
163 | 176 | let votesNo = valueOrElse(getInteger(this, proposalTotalNoStore(txId)), 0) | |
164 | 177 | let totalGviresSnap = valueOrElse(getInteger(this, proposalTotalGViresStore(txId)), 0) | |
165 | 178 | let voteYes = votesYes | |
166 | 179 | let voteNo = votesNo | |
167 | 180 | let totalVotes = (voteYes + voteNo) | |
168 | 181 | let hasQuorum = if ((totalVotes > 0)) | |
169 | 182 | then (((totalVotes * BASE) / totalGviresSnap) >= quorumRatio) | |
170 | 183 | else false | |
171 | 184 | let hasPassed = if ((totalVotes > 0)) | |
172 | 185 | then (((voteYes * BASE) / totalVotes) >= passedRatio) | |
173 | 186 | else false | |
174 | 187 | let tooEarly = (applyStart >= HEIGHT) | |
175 | 188 | let tooLate = (HEIGHT >= applyEnd) | |
176 | 189 | let inBlockchainHeight = valueOrElse(transactionHeightById(fromBase58String(txId)), 0) | |
177 | 190 | let status = if ((votingStart > HEIGHT)) | |
178 | 191 | then "discussion" | |
179 | 192 | else if ((votingEnd >= HEIGHT)) | |
180 | 193 | then "voting" | |
181 | 194 | else if (!(hasQuorum)) | |
182 | 195 | then "noQuorum" | |
183 | 196 | else if (!(hasPassed)) | |
184 | 197 | then "votingFailed" | |
185 | 198 | else if (tooEarly) | |
186 | 199 | then "votingPassed" | |
187 | 200 | else if ((inBlockchainHeight > 0)) | |
188 | 201 | then "inBlockchain" | |
189 | 202 | else if (!(tooLate)) | |
190 | 203 | then "waitingForTx" | |
191 | 204 | else "failed" | |
192 | 205 | ((((((((((((((((((((((("proposal_id: " + txId) + ", proposal_status: ") + status) + ", proposal_by: ") + valueOrErrorMessage(getString(this, proposalByStore(txId)), "no proposal")) + ", proposal_height: ") + toString(proposalHeight)) + ", proposal_txheight: ") + toString(inBlockchainHeight)) + ", proposal_votingstart: ") + toString(votingStart)) + ", proposal_votingend: ") + toString(votingEnd)) + ", proposal_applystart: ") + toString(applyStart)) + ", proposal_applyend: ") + toString(applyEnd)) + ", proposal_gvires: ") + toString(totalGviresSnap)) + ", vote_yes: ") + toString(voteYes)) + ", vote_no: ") + toString(voteNo)) | |
193 | 206 | } | |
194 | 207 | ||
195 | 208 | ||
196 | 209 | @Callable(i) | |
197 | 210 | func init (config) = [writeConstString(configAddressStore, config)] | |
198 | 211 | ||
199 | 212 | ||
200 | 213 | ||
201 | 214 | @Callable(i) | |
202 | 215 | func propose (txId) = { | |
203 | 216 | let checks = opAllowed("governance_propose_tx") | |
204 | 217 | if ((checks == checks)) | |
205 | 218 | then { | |
206 | 219 | let user = toString(i.caller) | |
207 | 220 | let gv = userGvires(user) | |
208 | 221 | if ((proposalMinRequired > gv)) | |
209 | 222 | then throw((((("not enough gVires to make proposal." + " Minimum required = ") + toString(proposalMinRequired)) + ", actual: = ") + toString(gv))) | |
210 | 223 | else { | |
211 | 224 | let last = userLastProposeHeight(user) | |
212 | 225 | if (if ((last > -1)) | |
213 | 226 | then ((last + userProposeDelay) > HEIGHT) | |
214 | 227 | else false) | |
215 | 228 | then throw(((("can't propose too often, last proroposal height: " + toString(last)) + ", blocks to wait: ") + toString(((last + userProposeDelay) - HEIGHT)))) | |
216 | 229 | else [writeConstInt(proposalHeightStore(txId), HEIGHT), writeConstInt(proposalVotingStartStore(txId), (HEIGHT + votingStartOffset)), writeConstInt(proposalVotingEndStore(txId), (HEIGHT + votingEndOffset)), writeConstInt(proposalApplyStartStore(txId), (HEIGHT + applyStartOffset)), writeConstInt(proposalApplyEndStore(txId), (HEIGHT + applyEndOffset)), writeConstString(proposalByStore(txId), toString(i.caller)), writeInt(userLastProposeHeightStore(user), HEIGHT)] | |
217 | 230 | } | |
218 | 231 | } | |
219 | 232 | else throw("Strict value is not equal to itself.") | |
220 | 233 | } | |
221 | 234 | ||
222 | 235 | ||
223 | 236 | ||
224 | 237 | @Callable(i) | |
225 | 238 | func voteYes (txId) = { | |
226 | 239 | let checks = if (opAllowed("governance_vote_tx")) | |
227 | 240 | then proposalOnVoting(txId) | |
228 | 241 | else false | |
229 | 242 | if ((checks == checks)) | |
230 | 243 | then { | |
231 | 244 | let user = toString(i.caller) | |
232 | 245 | if ((userNo(user, txId) > 0)) | |
233 | 246 | then throw("already voted against, please retract your vote first") | |
234 | 247 | else { | |
235 | 248 | let delta = (userGvires(user) - userYes(user, txId)) | |
236 | 249 | let setGvires = IntegerEntry(proposalTotalGViresStore(txId), totalGVires()) | |
237 | 250 | if ((0 >= delta)) | |
238 | 251 | then [setGvires] | |
239 | 252 | else [setGvires, changeBy(proposalUserYesStore(user, txId), delta), changeBy(proposalTotalYesStore(txId), delta)] | |
240 | 253 | } | |
241 | 254 | } | |
242 | 255 | else throw("Strict value is not equal to itself.") | |
243 | 256 | } | |
244 | 257 | ||
245 | 258 | ||
246 | 259 | ||
247 | 260 | @Callable(i) | |
248 | 261 | func voteNo (txId) = { | |
249 | 262 | let checks = if (opAllowed("governance_vote_tx")) | |
250 | 263 | then proposalOnVoting(txId) | |
251 | 264 | else false | |
252 | 265 | if ((checks == checks)) | |
253 | 266 | then { | |
254 | 267 | let user = toString(i.caller) | |
255 | 268 | if ((userYes(user, txId) > 0)) | |
256 | 269 | then throw("already voted for, please retract your vote first") | |
257 | 270 | else { | |
258 | 271 | let delta = (userGvires(user) - userNo(user, txId)) | |
259 | 272 | let setGvires = IntegerEntry(proposalTotalGViresStore(txId), totalGVires()) | |
260 | 273 | if ((0 >= delta)) | |
261 | 274 | then [setGvires] | |
262 | 275 | else [setGvires, changeBy(proposalUserNoStore(user, txId), delta), changeBy(proposalTotalNoStore(txId), delta)] | |
263 | 276 | } | |
264 | 277 | } | |
265 | 278 | else throw("Strict value is not equal to itself.") | |
266 | 279 | } | |
267 | 280 | ||
268 | 281 | ||
269 | 282 | ||
270 | 283 | @Callable(i) | |
271 | 284 | func retract (txId) = { | |
272 | 285 | let checks = if (opAllowed("governance_vote_tx")) | |
273 | 286 | then proposalOnVoting(txId) | |
274 | 287 | else false | |
275 | 288 | if ((checks == checks)) | |
276 | 289 | then { | |
277 | 290 | let user = toString(i.caller) | |
278 | 291 | [changeBy(proposalTotalYesStore(txId), -(userYes(user, txId))), changeBy(proposalTotalNoStore(txId), -(userNo(user, txId))), DeleteEntry(proposalUserYesStore(user, txId)), DeleteEntry(proposalUserNoStore(user, txId))] | |
279 | 292 | } | |
280 | 293 | else throw("Strict value is not equal to itself.") | |
281 | 294 | } | |
282 | 295 | ||
283 | 296 | ||
297 | + | ||
298 | + | @Callable(i) | |
299 | + | func retractProposal (txId) = { | |
300 | + | let checks = if (opAllowed("governance_retract_proposal_tx")) | |
301 | + | then proposalBeforeVoting(txId) | |
302 | + | else false | |
303 | + | if ((checks == checks)) | |
304 | + | then { | |
305 | + | let by = valueOrErrorMessage(getString(this, proposalByStore(txId)), "proposal doesn't exist") | |
306 | + | let user = toString(i.caller) | |
307 | + | if ((by != user)) | |
308 | + | then throw("only owner can retract proposal") | |
309 | + | else [DeleteEntry(proposalHeightStore(txId)), DeleteEntry(proposalVotingStartStore(txId)), DeleteEntry(proposalVotingEndStore(txId)), DeleteEntry(proposalApplyStartStore(txId)), DeleteEntry(proposalApplyEndStore(txId)), DeleteEntry(proposalByStore(txId)), DeleteEntry(proposalTotalGViresStore(txId)), DeleteEntry(proposalTotalYesStore(txId)), DeleteEntry(proposalTotalNoStore(txId)), DeleteEntry(proposalUserYesStore(user, txId)), DeleteEntry(proposalUserNoStore(user, txId)), DeleteEntry(userLastProposeHeightStore(user))] | |
310 | + | } | |
311 | + | else throw("Strict value is not equal to itself.") | |
312 | + | } | |
313 | + | ||
314 | + |
github/deemru/w8io/786bc32 43.02 ms ◑