tx · 3ZoqCBeUZYJX48kJkpYzt5xueNmu5scqigvAY8dxMsoM 3PJPW1rknfSxCKjUwRp1Upg7Yxhe7VerDqg: -0.01700000 Waves 2024.01.05 11:31 [3983758] smart account 3PJPW1rknfSxCKjUwRp1Upg7Yxhe7VerDqg > SELF 0.00000000 Waves
{ "type": 13, "id": "3ZoqCBeUZYJX48kJkpYzt5xueNmu5scqigvAY8dxMsoM", "fee": 1700000, "feeAssetId": null, "timestamp": 1704443571804, "version": 1, "sender": "3PJPW1rknfSxCKjUwRp1Upg7Yxhe7VerDqg", "senderPublicKey": "7nSWVBfVWDAFZYVVRuNHc1a8vZT9nLbDwm4qn4MaX473", "proofs": [ "3JajFEdh6xNv7DsrsggjJEAeFN3AUGksGgffxroFMuK5UUsH3bsFB9QojFfGQoa9nKckQvYZFLfyPr5fTxyXAnrE" ], "script": "base64:AAIFAAAAAAAAACgIAhIFCgMICAISBAoCCAISAwoBCBIDCgEIEgMKAQgSAwoBCBIDCgEIAAAAMQEAAAAHdGhyb3dJZgAAAAIAAAAJY29uZGl0aW9uAAAABWVycm9yAwUAAAAJY29uZGl0aW9uCQAAAgAAAAEFAAAABWVycm9yBgEAAAALd3JpdGVCaW5hcnkAAAACAAAAA2tleQAAAAV2YWx1ZQkBAAAAC0JpbmFyeUVudHJ5AAAAAgUAAAADa2V5BQAAAAV2YWx1ZQEAAAAId3JpdGVJbnQAAAACAAAAA2tleQAAAAV2YWx1ZQMJAABmAAAAAgAAAAAAAAAAAAUAAAAFdmFsdWUJAAACAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAXd3JpdGluZyBuZWdhdGl2ZSB2YWx1ZSAJAAGkAAAAAQUAAAAFdmFsdWUCAAAACSBmb3Iga2V5IAUAAAADa2V5CQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAADa2V5BQAAAAV2YWx1ZQEAAAAQd3JpdGVDb25zdFN0cmluZwAAAAIAAAADa2V5AAAABXZhbHVlAwkBAAAAASEAAAABCQEAAAAJaXNEZWZpbmVkAAAAAQkABB0AAAACBQAAAAR0aGlzBQAAAANrZXkJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAAA2tleQUAAAAFdmFsdWUJAAACAAAAAQkAASwAAAACAgAAABVhbHJlYWR5IGluaXRpYWxpemVkOiAFAAAAA2tleQEAAAANd3JpdGVDb25zdEludAAAAAIAAAADa2V5AAAABXZhbHVlAwkBAAAAASEAAAABCQEAAAAJaXNEZWZpbmVkAAAAAQkABBoAAAACBQAAAAR0aGlzBQAAAANrZXkJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAANrZXkFAAAABXZhbHVlCQAAAgAAAAEJAAEsAAAAAgIAAAAQYWxyZWFkeSBleGlzdHM6IAUAAAADa2V5AQAAAAhjaGFuZ2VCeQAAAAIAAAADa2V5AAAABXZhbHVlCQEAAAAId3JpdGVJbnQAAAACBQAAAANrZXkJAABkAAAAAgkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAR0aGlzBQAAAANrZXkAAAAAAAAAAAAFAAAABXZhbHVlAQAAAAVhc0ludAAAAAEAAAAFdmFsdWUEAAAAByRtYXRjaDAFAAAABXZhbHVlAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAANJbnQEAAAAA2ludAUAAAAHJG1hdGNoMAUAAAADaW50CQAAAgAAAAECAAAAGXdyb25nIHR5cGUsIGV4cGVjdGVkOiBJbnQAAAAAEmNvbmZpZ0FkZHJlc3NTdG9yZQIAAAAGY29uZmlnAAAAAA1jb25maWdBZGRyZXNzCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQmAAAAAQkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEHQAAAAIFAAAABHRoaXMFAAAAEmNvbmZpZ0FkZHJlc3NTdG9yZQIAAAAaY2hpbGRyZW4udm90aW5nOiBubyBjb25maWcCAAAAFmludmFsaWQgY29uZmlnIGFkZHJlc3MAAAAABkhFSUdIVAUAAAAGaGVpZ2h0AQAAAAZhZHZpc2UAAAAACQABLAAAAAICAAAACGhlaWdodDogCQABpAAAAAEFAAAABkhFSUdIVAAAAAAEQkFTRQAAAAAAAAAD6AEAAAAJb3BBbGxvd2VkAAAAAQAAAAJvcAQAAAABYQkAA/wAAAAEBQAAAA1jb25maWdBZGRyZXNzAgAAAAlvcEFsbG93ZWQJAARMAAAAAgUAAAACb3AFAAAAA25pbAUAAAADbmlsAwkAAAAAAAACBQAAAAFhBQAAAAFhBgkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAAAEGNoaWxkcmVuQ29udHJhY3QJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABCYAAAABCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQdAAAAAgUAAAANY29uZmlnQWRkcmVzcwIAAAARY29udHJhY3RfY2hpbGRyZW4CAAAAFG5vIGNvbnRyYWN0X2NoaWxkcmVuAgAAABlpbnZhbGlkIGNvbnRyYWN0X2NoaWxkcmVuAAAAABR2b3RpbmdSZXN1bHRDb250cmFjdAkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEJgAAAAEJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABB0AAAACBQAAAA1jb25maWdBZGRyZXNzAgAAABZjb250cmFjdF92b3RpbmdfcmVzdWx0AgAAABlubyBjb250cmFjdF92b3RpbmdfcmVzdWx0AgAAAB5pbnZhbGlkIGNvbnRyYWN0X3ZvdGluZ19yZXN1bHQBAAAAEnByb3Bvc2FsQ2hpbGRTdG9yZQAAAAEAAAACaWQJAAEsAAAAAgIAAAAPcHJvcG9zYWxfY2hpbGRfBQAAAAJpZAEAAAAUcHJvcG9zYWxBZGRyZXNzU3RvcmUAAAABAAAAAmlkCQABLAAAAAICAAAAEXByb3Bvc2FsX2FkZHJlc3NfBQAAAAJpZAEAAAATcHJvcG9zYWxIZWlnaHRTdG9yZQAAAAEAAAACaWQJAAEsAAAAAgIAAAAQcHJvcG9zYWxfaGVpZ2h0XwUAAAACaWQBAAAAGHByb3Bvc2FsVm90aW5nU3RhcnRTdG9yZQAAAAEAAAACaWQJAAEsAAAAAgIAAAAVcHJvcG9zYWxfdm90aW5nc3RhcnRfBQAAAAJpZAEAAAAWcHJvcG9zYWxWb3RpbmdFbmRTdG9yZQAAAAEAAAACaWQJAAEsAAAAAgIAAAATcHJvcG9zYWxfdm90aW5nZW5kXwUAAAACaWQBAAAAD3Byb3Bvc2FsQnlTdG9yZQAAAAEAAAACaWQJAAEsAAAAAgIAAAAMcHJvcG9zYWxfYnlfBQAAAAJpZAEAAAAYcHJvcG9zYWxBdHRhY2htZW50c1N0b3JlAAAAAQAAAAJpZAkAASwAAAACAgAAABVwcm9wb3NhbF9hdHRhY2htZW50c18FAAAAAmlkAQAAABVwcm9wb3NhbFRvdGFsWWVzU3RvcmUAAAABAAAAAmlkCQABLAAAAAICAAAADXByb3Bvc2FsX3llc18FAAAAAmlkAQAAABRwcm9wb3NhbFRvdGFsTm9TdG9yZQAAAAEAAAACaWQJAAEsAAAAAgIAAAAMcHJvcG9zYWxfbm9fBQAAAAJpZAEAAAAUcHJvcG9zYWxVc2VyWWVzU3RvcmUAAAACAAAABHVzZXIAAAACaWQJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAEnVzZXJfcHJvcG9zYWxfeWVzXwUAAAAEdXNlcgIAAAABXwUAAAACaWQBAAAAE3Byb3Bvc2FsVXNlck5vU3RvcmUAAAACAAAABHVzZXIAAAACaWQJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAEXVzZXJfcHJvcG9zYWxfbm9fBQAAAAR1c2VyAgAAAAFfBQAAAAJpZAEAAAAadXNlckxhc3RQcm9wb3NlSGVpZ2h0U3RvcmUAAAABAAAABHVzZXIJAAEsAAAAAgIAAAATcHJvcG9zZV9sYXN0aGVpZ2h0XwUAAAAEdXNlcgEAAAAHdXNlclllcwAAAAIAAAAEdXNlcgAAAAJpZAkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAR0aGlzCQEAAAAUcHJvcG9zYWxVc2VyWWVzU3RvcmUAAAACBQAAAAR1c2VyBQAAAAJpZAAAAAAAAAAAAAEAAAAGdXNlck5vAAAAAgAAAAR1c2VyAAAAAmlkCQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAABHRoaXMJAQAAABNwcm9wb3NhbFVzZXJOb1N0b3JlAAAAAgUAAAAEdXNlcgUAAAACaWQAAAAAAAAAAAABAAAAFXVzZXJMYXN0UHJvcG9zZUhlaWdodAAAAAEAAAAEdXNlcgkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAR0aGlzCQEAAAAadXNlckxhc3RQcm9wb3NlSGVpZ2h0U3RvcmUAAAABBQAAAAR1c2VyAP//////////AAAAAAt0aGlzQWRkcmVzcwkABCUAAAABBQAAAAR0aGlzAQAAAAhzZXR0aW5ncwAAAAIAAAADa2V5AAAABWNoaWxkCQEAAAALdmFsdWVPckVsc2UAAAACCQAEHwAAAAEJAAEsAAAAAgkAASwAAAACBQAAAANrZXkCAAAAAV8FAAAABWNoaWxkCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAANY29uZmlnQWRkcmVzcwkAASwAAAACCQABLAAAAAIFAAAAC3RoaXNBZGRyZXNzAgAAAAFfBQAAAANrZXkJAAEsAAAAAgUAAAADa2V5AgAAAA8gaXMgbm90IGRlZmluZWQBAAAAEHVzZXJQcm9wb3NlRGVsYXkAAAABAAAABWNoaWxkCQEAAAAIc2V0dGluZ3MAAAACAgAAABJ1c2VyX3Byb3Bvc2VfZGVsYXkFAAAABWNoaWxkAQAAAAtxdW9ydW1SYXRpbwAAAAEAAAAFY2hpbGQJAQAAAAhzZXR0aW5ncwAAAAICAAAAFXByb3Bvc2FsX3F1b3J1bV9yYXRpbwUAAAAFY2hpbGQBAAAAC3Bhc3NlZFJhdGlvAAAAAQAAAAVjaGlsZAkBAAAACHNldHRpbmdzAAAAAgIAAAAVcHJvcG9zYWxfcGFzc2VkX3JhdGlvBQAAAAVjaGlsZAEAAAATcHJvcG9zYWxNaW5SZXF1aXJlZAAAAAEAAAAFY2hpbGQJAQAAAAhzZXR0aW5ncwAAAAICAAAAG3Byb3Bvc2FsX21pbl9wb3dlcl9yZXF1aXJlZAUAAAAFY2hpbGQBAAAAEXZvdGluZ1N0YXJ0T2Zmc2V0AAAAAQAAAAVjaGlsZAkBAAAACHNldHRpbmdzAAAAAgIAAAAbcHJvcG9zYWxfdm90aW5nc3RhcnRfb2Zmc2V0BQAAAAVjaGlsZAEAAAAPdm90aW5nRW5kT2Zmc2V0AAAAAQAAAAVjaGlsZAkBAAAACHNldHRpbmdzAAAAAgIAAAAZcHJvcG9zYWxfdm90aW5nZW5kX29mZnNldAUAAAAFY2hpbGQBAAAAE3Byb3Bvc2FsUXVvcnVtU3RvcmUAAAABAAAABHR4aWQJAAEsAAAAAgIAAAAWcHJvcG9zYWxfcXVvcnVtX3JhdGlvXwUAAAAEdHhpZAEAAAAGcXVvcnVtAAAAAgAAAAVjaGlsZAAAAAR0eElkCQEAAAALdmFsdWVPckVsc2UAAAACCQAEHwAAAAEJAQAAABNwcm9wb3NhbFF1b3J1bVN0b3JlAAAAAQUAAAAEdHhJZAkBAAAAC3F1b3J1bVJhdGlvAAAAAQUAAAAFY2hpbGQBAAAACXVzZXJQb3dlcgAAAAIAAAAFY2hpbGQAAAAEdXNlcgkBAAAABWFzSW50AAAAAQkAA/wAAAAEBQAAABBjaGlsZHJlbkNvbnRyYWN0AgAAAAl1c2VyUG93ZXIJAARMAAAAAgUAAAAFY2hpbGQJAARMAAAAAgUAAAAEdXNlcgUAAAADbmlsBQAAAANuaWwBAAAADWlzUGFydGljaXBhbnQAAAABAAAABXBvd2VyAwkAAAAAAAACBQAAAAVwb3dlcgAAAAAAAAAAAAkAAAIAAAABAgAAACV5b3UgYXJlIG5vdCBhIHBhcnRpY2lwYW50IG9mIHRoaXMgZGFvBQAAAANuaWwBAAAADnByb3Bvc2FsRXhpc3RzAAAAAQAAAAR0eElkBAAAAAckbWF0Y2gwCQAEGgAAAAIFAAAABHRoaXMJAQAAABNwcm9wb3NhbEhlaWdodFN0b3JlAAAAAQUAAAAEdHhJZAMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAADSW50BAAAAAVzdGFydAUAAAAHJG1hdGNoMAYHAQAAABBwcm9wb3NhbE9uVm90aW5nAAAAAQAAAAR0eElkBAAAAAtub25FeGlzdEVycgIAAAAWcHJvcG9zYWwgZG9lc24ndCBleGlzdAMJAQAAAAEhAAAAAQkBAAAADnByb3Bvc2FsRXhpc3RzAAAAAQUAAAAEdHhJZAkAAAIAAAABBQAAAAtub25FeGlzdEVycgQAAAALdm90aW5nU3RhcnQJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABBoAAAACBQAAAAR0aGlzCQEAAAAYcHJvcG9zYWxWb3RpbmdTdGFydFN0b3JlAAAAAQUAAAAEdHhJZAUAAAALbm9uRXhpc3RFcnIEAAAACXZvdGluZ0VuZAkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEGgAAAAIFAAAABHRoaXMJAQAAABZwcm9wb3NhbFZvdGluZ0VuZFN0b3JlAAAAAQUAAAAEdHhJZAUAAAALbm9uRXhpc3RFcnIDCQAAZgAAAAIFAAAAC3ZvdGluZ1N0YXJ0BQAAAAZIRUlHSFQJAAACAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAABOdm90aW5nIG5vdCBzdGFydGVkIHlldCwgZGlzY3Vzc2lvbiBpcyBpbiBwcm9ncmVzcywgdm90aW5nIHdpbGwgc3RhcnQgYXQgYmxvY2sgCQABpAAAAAEFAAAAC3ZvdGluZ1N0YXJ0AgAAAAssIG5vdyBpdCdzIAkAAaQAAAABBQAAAAZIRUlHSFQDCQAAZgAAAAIFAAAABkhFSUdIVAUAAAAJdm90aW5nRW5kCQAAAgAAAAEJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAFnZvdGluZyBlbmRlZCBhdCBibG9jayAJAAGkAAAAAQUAAAAJdm90aW5nRW5kAgAAAAssIG5vdyBpdCdzIAkAAaQAAAABBQAAAAZIRUlHSFQGAQAAABRwcm9wb3NhbEJlZm9yZVZvdGluZwAAAAEAAAAEdHhJZAQAAAALbm9uRXhpc3RFcnICAAAAFnByb3Bvc2FsIGRvZXNuJ3QgZXhpc3QDCQEAAAABIQAAAAEJAQAAAA5wcm9wb3NhbEV4aXN0cwAAAAEFAAAABHR4SWQJAAACAAAAAQUAAAALbm9uRXhpc3RFcnIEAAAAC3ZvdGluZ1N0YXJ0CQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAAEdGhpcwkBAAAAGHByb3Bvc2FsVm90aW5nU3RhcnRTdG9yZQAAAAEFAAAABHR4SWQFAAAAC25vbkV4aXN0RXJyAwkAAGcAAAACBQAAAAZIRUlHSFQFAAAAC3ZvdGluZ1N0YXJ0CQAAAgAAAAECAAAAIHZvdGluZyBzdGFydCBpcyBhbHJlYWR5IGhhcHBlbmVkBgEAAAAQdG90YWxQb3dlclN0YWtlZAAAAAEAAAAFY2hpbGQJAQAAAAVhc0ludAAAAAEJAAP8AAAABAUAAAAQY2hpbGRyZW5Db250cmFjdAIAAAAKdG90YWxQb3dlcgkABEwAAAACBQAAAAVjaGlsZAUAAAADbmlsBQAAAANuaWwBAAAADGNhbkJyb2FkY2FzdAAAAAQAAAAFY2hpbGQAAAAEdHhJZAAAAAZ5ZXNJbmMAAAAFbm9JbmMEAAAACHZvdGVzWWVzCQAAZAAAAAIJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQfAAAAAQkBAAAAFXByb3Bvc2FsVG90YWxZZXNTdG9yZQAAAAEFAAAABHR4SWQAAAAAAAAAAAAFAAAABnllc0luYwQAAAAHdm90ZXNObwkAAGQAAAACCQEAAAALdmFsdWVPckVsc2UAAAACCQAEHwAAAAEJAQAAABRwcm9wb3NhbFRvdGFsTm9TdG9yZQAAAAEFAAAABHR4SWQAAAAAAAAAAAAFAAAABW5vSW5jBAAAAA5wcm9wb3NhbEhlaWdodAkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEHwAAAAEJAQAAABNwcm9wb3NhbEhlaWdodFN0b3JlAAAAAQUAAAAEdHhJZAIAAAAXcHJvcG9zYWwgbm90IHJlZ2lzdGVyZWQEAAAACnRvdGFsUG93ZXIJAQAAABB0b3RhbFBvd2VyU3Rha2VkAAAAAQUAAAAFY2hpbGQDCQAAAAAAAAIFAAAACnRvdGFsUG93ZXIFAAAACnRvdGFsUG93ZXIEAAAABnBhc3NlZAkBAAAAC3Bhc3NlZFJhdGlvAAAAAQUAAAAFY2hpbGQEAAAACnRvdGFsVm90ZXMJAABkAAAAAgUAAAAIdm90ZXNZZXMFAAAAB3ZvdGVzTm8EAAAACWhhc1F1b3J1bQkAAGcAAAACCQAAaQAAAAIJAABoAAAAAgUAAAAKdG90YWxWb3RlcwUAAAAEQkFTRQUAAAAKdG90YWxQb3dlcgkBAAAABnF1b3J1bQAAAAIFAAAABWNoaWxkBQAAAAR0eElkBAAAAAloYXNQYXNzZWQJAABnAAAAAgkAAGkAAAACCQAAaAAAAAIFAAAACHZvdGVzWWVzBQAAAARCQVNFBQAAAAp0b3RhbFZvdGVzBQAAAAZwYXNzZWQDBQAAAAloYXNRdW9ydW0FAAAACWhhc1Bhc3NlZAcJAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQAAAA5hZHZpc2VQcm9wb3NhbAAAAAEAAAAEdHhJZAQAAAAFY2hpbGQJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABCIAAAABCQEAAAAScHJvcG9zYWxDaGlsZFN0b3JlAAAAAQUAAAAEdHhJZAIAAAAPY2hpbGQgbm90IGZvdW5kBAAAAA5wcm9wb3NhbEhlaWdodAkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEGgAAAAIFAAAABHRoaXMJAQAAABNwcm9wb3NhbEhlaWdodFN0b3JlAAAAAQUAAAAEdHhJZAIAAAALbm8gcHJvcG9zYWwEAAAAC3ZvdGluZ1N0YXJ0CQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAAEdGhpcwkBAAAAGHByb3Bvc2FsVm90aW5nU3RhcnRTdG9yZQAAAAEFAAAABHR4SWQCAAAAC25vIHByb3Bvc2FsBAAAAAl2b3RpbmdFbmQJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABBoAAAACBQAAAAR0aGlzCQEAAAAWcHJvcG9zYWxW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AAEFAAAACXZvdGluZ0VuZAIAAAASLCBwcm9wb3NhbF9wb3dlcjogCQABpAAAAAEFAAAADnRvdGFsUG93ZXJTbmFwAgAAAAwsIHZvdGVfeWVzOiAJAAGkAAAAAQUAAAAIdm90ZXNZZXMCAAAACywgdm90ZV9ubzogCQABpAAAAAEFAAAAB3ZvdGVzTm8CAAAAHCwgcHJvcG9zYWxfYWxsb3dfYnJvYWRjYXN0OiAJAAGlAAAAAQMJAQAAAAIhPQAAAAIFAAAAD2Jyb2FkY2FzdEhlaWdodAD//////////wkAAGcAAAACBQAAAAZIRUlHSFQFAAAAD2Jyb2FkY2FzdEhlaWdodAcCAAAAIywgcHJvcG9zYWxfYWxsb3dfYnJvYWRjYXN0X2hlaWdodDogCQABpAAAAAEFAAAAD2Jyb2FkY2FzdEhlaWdodAIAAAAaLCBwcm9wb3NhbF92b3Rpbmdfc3VjY2VlZDoJAAGlAAAAAQkBAAAAAiE9AAAAAgUAAAAPYnJvYWRjYXN0SGVpZ2h0AP//////////AgAAABIsIHByb3Bvc2FsX3F1b3J1bToJAAGkAAAAAQUAAAABcQIAAAAULCBwcm9wb3NhbF9hZGRyZXNzOiAJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAQAAABRwcm9wb3NhbEFkZHJlc3NTdG9yZQAAAAEFAAAABHR4SWQFAAAABWNoaWxkCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgEAAAAPYnJvYWRjYXN0SGVpZ2h0AAAAAQAAAAR0eElkCQAAZAAAAAIJAQAAABFAZXh0ck5hdGl2ZSgxMDU1KQAAAAEJAQAAABZwcm9wb3NhbFZvdGluZ0VuZFN0b3JlAAAAAQUAAAAEdHhJZAAAAAAAAAAAAQAAAAcAAAABaQEAAAAHcHJvcG9zZQAAAAMAAAAFY2hpbGQAAAAEdHhJZAAAAAthdHRhY2htZW50cwQAAAAGY2hlY2tzCQEAAAAJb3BBbGxvd2VkAAAAAQIAAAAbY2hpbGRfZ292ZXJuYW5jZV9wcm9wb3NlX3R4AwkAAAAAAAACBQAAAAZjaGVja3MFAAAABmNoZWNrcwQAAAAIcmVxdWlyZWQJAQAAABNwcm9wb3NhbE1pblJlcXVpcmVkAAAAAQUAAAAFY2hpbGQEAAAABHVzZXIJAAQlAAAAAQgFAAAAAWkAAAAGY2FsbGVyBAAAAAJndgkBAAAACXVzZXJQb3dlcgAAAAIFAAAABWNoaWxkBQAAAAR1c2VyAwkAAAAAAAACBQAAAAJndgUAAAACZ3YDCQAAZgAAAAIFAAAACHJlcXVpcmVkBQAAAAJndgkAAAIAAAABCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAKW5vdCBlbm91Z2ggc3Rha2VkIHBvd2VyIHRvIG1ha2UgcHJvcG9zYWwuAgAAABQgTWluaW11bSByZXF1aXJlZCA9IAkAAaQAAAABBQAAAAhyZXF1aXJlZAIAAAAMLCBhY3R1YWw6ID0gCQABpAAAAAEFAAAAAmd2BAAAAAVkZWxheQkBAAAAEHVzZXJQcm9wb3NlRGVsYXkAAAABBQAAAAVjaGlsZAQAAAAEbGFzdAkBAAAAFXVzZXJMYXN0UHJvcG9zZUhlaWdodAAAAAEFAAAABHVzZXIDAwkAAGYAAAACBQAAAARsYXN0AP//////////CQAAZgAAAAIJAABkAAAAAgUAAAAEbGFzdAUAAAAFZGVsYXkFAAAABkhFSUdIVAcJAAACAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAxY2FuJ3QgcHJvcG9zZSB0b28gb2Z0ZW4sIGxhc3QgcHJvcm9wb3NhbCBoZWlnaHQ6IAkAAaQAAAABBQAAAARsYXN0AgAAABIsIGJsb2NrcyB0byB3YWl0OiAJAAGkAAAAAQkAAGUAAAACCQAAZAAAAAIFAAAABGxhc3QFAAAABWRlbGF5BQAAAAZIRUlHSFQEAAAAB2FkZHJlc3MJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQdAAAAAgUAAAAQY2hpbGRyZW5Db250cmFjdAkAASwAAAACAgAAAAl0cmVhc3VyeV8FAAAABWNoaWxkBQAAAAVjaGlsZAkABEwAAAACCQEAAAAQd3JpdGVDb25zdFN0cmluZwAAAAIJAQAAABJwcm9wb3NhbENoaWxkU3RvcmUAAAABBQAAAAR0eElkBQAAAAVjaGlsZAkABEwAAAACCQEAAAANd3JpdGVDb25zdEludAAAAAIJAQAAABNwcm9wb3NhbEhlaWdodFN0b3JlAAAAAQUAAAAEdHhJZAUAAAAGSEVJR0hUCQAETAAAAAIJAQAAAA13cml0ZUNvbnN0SW50AAAAAgkBAAAAGHByb3Bvc2FsVm90aW5nU3RhcnRTdG9yZQAAAAEFAAAABHR4SWQJAABkAAAAAgUAAAAGSEVJR0hUCQEAAAARdm90aW5nU3RhcnRPZmZzZXQAAAABBQAAAAVjaGlsZAkABEwAAAACCQEAAAANd3JpdGVDb25zdEludAAAAAIJAQAAABZwcm9wb3NhbFZvdGluZ0VuZFN0b3JlAAAAAQUAAAAEdHhJZAkAAGQAAAACBQAAAAZIRUlHSFQJAQAAAA92b3RpbmdFbmRPZmZzZXQAAAABBQAAAAVjaGlsZAkABEwAAAACCQEAAAAQd3JpdGVDb25zdFN0cmluZwAAAAIJAQAAAA9wcm9wb3NhbEJ5U3RvcmUAAAABBQAAAAR0eElkBQAAAAR1c2VyCQAETAAAAAIJAQAAAAh3cml0ZUludAAAAAIJAQAAABp1c2VyTGFzdFByb3Bvc2VIZWlnaHRTdG9yZQAAAAEFAAAABHVzZXIFAAAABkhFSUdIVAkABEwAAAACCQEAAAALd3JpdGVCaW5hcnkAAAACCQEAAAAYcHJvcG9zYWxBdHRhY2htZW50c1N0b3JlAAAAAQUAAAAEdHhJZAUAAAALYXR0YWNobWVudHMJAARMAAAAAgkBAAAAEHdyaXRlQ29uc3RTdHJpbmcAAAACCQEAAAAUcHJvcG9zYWxBZGRyZXNzU3RvcmUAAAABBQAAAAR0eElkBQAAAAdhZGRyZXNzBQAAAANuaWwJAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgAAAAFpAQAAAA9lZGl0QXR0YWNobWVudHMAAAACAAAABHR4SWQAAAALYXR0YWNobWVudHMEAAAABmNoZWNrcwkBAAAACW9wQWxsb3dlZAAAAAECAAAAIWNoaWxkX2dvdmVybmFuY2VfZWRpdF9hdHRhY2htZW50cwMJAAAAAAAAAgUAAAAGY2hlY2tzBQAAAAZjaGVja3MEAAAABHVzZXIJAAQlAAAAAQgFAAAAAWkAAAAGY2FsbGVy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", "chainId": 87, "height": 3983758, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: D5SqyUfh67paTJzXjsQzmuFCrBaEQ78CbE986QZ2RL87 Next: 9ijVP3qSFNkqxFA5trRYvoZJCjNkZk4ArckaW2Trit9t Diff:
Old | New | Differences | |
---|---|---|---|
59 | 59 | let votingResultContract = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(configAddress, "contract_voting_result"), "no contract_voting_result")), "invalid contract_voting_result") | |
60 | 60 | ||
61 | 61 | func proposalChildStore (id) = ("proposal_child_" + id) | |
62 | + | ||
63 | + | ||
64 | + | func proposalAddressStore (id) = ("proposal_address_" + id) | |
62 | 65 | ||
63 | 66 | ||
64 | 67 | func proposalHeightStore (id) = ("proposal_height_" + id) | |
227 | 230 | then "inBlockchain" | |
228 | 231 | else "waitingForTx" | |
229 | 232 | let broadcastHeight = valueOrElse(getInteger(votingResultContract, ((("proposal_allow_broadcast_" + child) + "_") + txId)), -1) | |
230 | - | ((((((((((((((((((((((((((("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_power: ") + toString(totalPowerSnap)) + ", vote_yes: ") + toString(votesYes)) + ", vote_no: ") + toString(votesNo)) + ", proposal_allow_broadcast: ") + toString(if ((broadcastHeight != -1)) | |
233 | + | ((((((((((((((((((((((((((((("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_power: ") + toString(totalPowerSnap)) + ", vote_yes: ") + toString(votesYes)) + ", vote_no: ") + toString(votesNo)) + ", proposal_allow_broadcast: ") + toString(if ((broadcastHeight != -1)) | |
231 | 234 | then (HEIGHT >= broadcastHeight) | |
232 | - | else false)) + ", proposal_allow_broadcast_height: ") + toString(broadcastHeight)) + ", proposal_voting_succeed:") + toString((broadcastHeight != -1))) + ", proposal_quorum:") + toString(q)) | |
235 | + | else false)) + ", proposal_allow_broadcast_height: ") + toString(broadcastHeight)) + ", proposal_voting_succeed:") + toString((broadcastHeight != -1))) + ", proposal_quorum:") + toString(q)) + ", proposal_address: ") + valueOrElse(proposalAddressStore(txId), child)) | |
233 | 236 | } | |
234 | 237 | else throw("Strict value is not equal to itself.") | |
235 | 238 | } | |
256 | 259 | then ((last + delay) > HEIGHT) | |
257 | 260 | else false) | |
258 | 261 | then throw(((("can't propose too often, last proroposal height: " + toString(last)) + ", blocks to wait: ") + toString(((last + delay) - HEIGHT)))) | |
259 | - | else [writeConstString(proposalChildStore(txId), child), writeConstInt(proposalHeightStore(txId), HEIGHT), writeConstInt(proposalVotingStartStore(txId), (HEIGHT + votingStartOffset(child))), writeConstInt(proposalVotingEndStore(txId), (HEIGHT + votingEndOffset(child))), writeConstString(proposalByStore(txId), user), writeInt(userLastProposeHeightStore(user), HEIGHT), writeBinary(proposalAttachmentsStore(txId), attachments)] | |
262 | + | else { | |
263 | + | let address = valueOrElse(getString(childrenContract, ("treasury_" + child)), child) | |
264 | + | [writeConstString(proposalChildStore(txId), child), writeConstInt(proposalHeightStore(txId), HEIGHT), writeConstInt(proposalVotingStartStore(txId), (HEIGHT + votingStartOffset(child))), writeConstInt(proposalVotingEndStore(txId), (HEIGHT + votingEndOffset(child))), writeConstString(proposalByStore(txId), user), writeInt(userLastProposeHeightStore(user), HEIGHT), writeBinary(proposalAttachmentsStore(txId), attachments), writeConstString(proposalAddressStore(txId), address)] | |
265 | + | } | |
260 | 266 | } | |
261 | 267 | else throw("Strict value is not equal to itself.") | |
262 | 268 | } | |
304 | 310 | if ((p == p)) | |
305 | 311 | then { | |
306 | 312 | let result = canBroadcast(child, txId, power, 0) | |
307 | - | let setResult = invoke(votingResultContract, "setResult", [child, txId, result, broadcastHeight(txId)], nil) | |
313 | + | let txAddress = valueOrElse(getString(proposalAddressStore(txId)), child) | |
314 | + | let setResult = invoke(votingResultContract, "setResult", [txAddress, txId, result, broadcastHeight(txId)], nil) | |
308 | 315 | if ((setResult == setResult)) | |
309 | 316 | then [changeBy(proposalUserYesStore(user, txId), power), changeBy(proposalTotalYesStore(txId), power)] | |
310 | 317 | else throw("Strict value is not equal to itself.") | |
343 | 350 | if ((p == p)) | |
344 | 351 | then { | |
345 | 352 | let result = canBroadcast(child, txId, 0, power) | |
346 | - | let setResult = invoke(votingResultContract, "setResult", [child, txId, result, broadcastHeight(txId)], nil) | |
353 | + | let txAddress = valueOrElse(getString(proposalAddressStore(txId)), child) | |
354 | + | let setResult = invoke(votingResultContract, "setResult", [txAddress, txId, result, broadcastHeight(txId)], nil) | |
347 | 355 | if ((setResult == setResult)) | |
348 | 356 | then [changeBy(proposalUserNoStore(user, txId), power), changeBy(proposalTotalNoStore(txId), power)] | |
349 | 357 | else throw("Strict value is not equal to itself.") | |
371 | 379 | let yes = -(userYes(user, txId)) | |
372 | 380 | let no = -(userNo(user, txId)) | |
373 | 381 | let result = canBroadcast(child, txId, yes, no) | |
374 | - | let setResult = invoke(votingResultContract, "setResult", [child, txId, result, broadcastHeight(txId)], nil) | |
382 | + | let txAddress = valueOrElse(getString(proposalAddressStore(txId)), child) | |
383 | + | let setResult = invoke(votingResultContract, "setResult", [txAddress, txId, result, broadcastHeight(txId)], nil) | |
375 | 384 | if ((setResult == setResult)) | |
376 | 385 | then [changeBy(proposalTotalYesStore(txId), yes), changeBy(proposalTotalNoStore(txId), no), DeleteEntry(proposalUserYesStore(user, txId)), DeleteEntry(proposalUserNoStore(user, txId))] | |
377 | 386 | else throw("Strict value is not equal to itself.") | |
392 | 401 | let user = toString(i.caller) | |
393 | 402 | if ((by != user)) | |
394 | 403 | then throw("only owner can retract proposal") | |
395 | - | else [DeleteEntry(proposalChildStore(txId)), DeleteEntry(proposalHeightStore(txId)), DeleteEntry(proposalVotingStartStore(txId)), DeleteEntry(proposalVotingEndStore(txId)), DeleteEntry(proposalByStore(txId)), DeleteEntry(proposalTotalYesStore(txId)), DeleteEntry(proposalTotalNoStore(txId)), DeleteEntry(proposalUserYesStore(user, txId)), DeleteEntry(proposalUserNoStore(user, txId)), DeleteEntry(userLastProposeHeightStore(user))] | |
404 | + | else [DeleteEntry(proposalChildStore(txId)), DeleteEntry(proposalHeightStore(txId)), DeleteEntry(proposalVotingStartStore(txId)), DeleteEntry(proposalVotingEndStore(txId)), DeleteEntry(proposalByStore(txId)), DeleteEntry(proposalTotalYesStore(txId)), DeleteEntry(proposalTotalNoStore(txId)), DeleteEntry(proposalUserYesStore(user, txId)), DeleteEntry(proposalUserNoStore(user, txId)), DeleteEntry(userLastProposeHeightStore(user)), DeleteEntry(proposalAddressStore(txId))] | |
396 | 405 | } | |
397 | 406 | else throw("Strict value is not equal to itself.") | |
398 | 407 | } |
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 writeBinary (key,value) = BinaryEntry(key, value) | |
10 | 10 | ||
11 | 11 | ||
12 | 12 | func writeInt (key,value) = if ((0 > value)) | |
13 | 13 | then throw(((("writing negative value " + toString(value)) + " for key ") + key)) | |
14 | 14 | else IntegerEntry(key, value) | |
15 | 15 | ||
16 | 16 | ||
17 | 17 | func writeConstString (key,value) = if (!(isDefined(getString(this, key)))) | |
18 | 18 | then StringEntry(key, value) | |
19 | 19 | else throw(("already initialized: " + key)) | |
20 | 20 | ||
21 | 21 | ||
22 | 22 | func writeConstInt (key,value) = if (!(isDefined(getInteger(this, key)))) | |
23 | 23 | then IntegerEntry(key, value) | |
24 | 24 | else throw(("already exists: " + key)) | |
25 | 25 | ||
26 | 26 | ||
27 | 27 | func changeBy (key,value) = writeInt(key, (valueOrElse(getInteger(this, key), 0) + value)) | |
28 | 28 | ||
29 | 29 | ||
30 | 30 | func asInt (value) = match value { | |
31 | 31 | case int: Int => | |
32 | 32 | int | |
33 | 33 | case _ => | |
34 | 34 | throw("wrong type, expected: Int") | |
35 | 35 | } | |
36 | 36 | ||
37 | 37 | ||
38 | 38 | let configAddressStore = "config" | |
39 | 39 | ||
40 | 40 | let configAddress = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(this, configAddressStore), "children.voting: no config")), "invalid config address") | |
41 | 41 | ||
42 | 42 | let HEIGHT = height | |
43 | 43 | ||
44 | 44 | func advise () = ("height: " + toString(HEIGHT)) | |
45 | 45 | ||
46 | 46 | ||
47 | 47 | let BASE = 1000 | |
48 | 48 | ||
49 | 49 | func opAllowed (op) = { | |
50 | 50 | let a = invoke(configAddress, "opAllowed", [op], nil) | |
51 | 51 | if ((a == a)) | |
52 | 52 | then true | |
53 | 53 | else throw("Strict value is not equal to itself.") | |
54 | 54 | } | |
55 | 55 | ||
56 | 56 | ||
57 | 57 | let childrenContract = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(configAddress, "contract_children"), "no contract_children")), "invalid contract_children") | |
58 | 58 | ||
59 | 59 | let votingResultContract = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(configAddress, "contract_voting_result"), "no contract_voting_result")), "invalid contract_voting_result") | |
60 | 60 | ||
61 | 61 | func proposalChildStore (id) = ("proposal_child_" + id) | |
62 | + | ||
63 | + | ||
64 | + | func proposalAddressStore (id) = ("proposal_address_" + id) | |
62 | 65 | ||
63 | 66 | ||
64 | 67 | func proposalHeightStore (id) = ("proposal_height_" + id) | |
65 | 68 | ||
66 | 69 | ||
67 | 70 | func proposalVotingStartStore (id) = ("proposal_votingstart_" + id) | |
68 | 71 | ||
69 | 72 | ||
70 | 73 | func proposalVotingEndStore (id) = ("proposal_votingend_" + id) | |
71 | 74 | ||
72 | 75 | ||
73 | 76 | func proposalByStore (id) = ("proposal_by_" + id) | |
74 | 77 | ||
75 | 78 | ||
76 | 79 | func proposalAttachmentsStore (id) = ("proposal_attachments_" + id) | |
77 | 80 | ||
78 | 81 | ||
79 | 82 | func proposalTotalYesStore (id) = ("proposal_yes_" + id) | |
80 | 83 | ||
81 | 84 | ||
82 | 85 | func proposalTotalNoStore (id) = ("proposal_no_" + id) | |
83 | 86 | ||
84 | 87 | ||
85 | 88 | func proposalUserYesStore (user,id) = ((("user_proposal_yes_" + user) + "_") + id) | |
86 | 89 | ||
87 | 90 | ||
88 | 91 | func proposalUserNoStore (user,id) = ((("user_proposal_no_" + user) + "_") + id) | |
89 | 92 | ||
90 | 93 | ||
91 | 94 | func userLastProposeHeightStore (user) = ("propose_lastheight_" + user) | |
92 | 95 | ||
93 | 96 | ||
94 | 97 | func userYes (user,id) = valueOrElse(getInteger(this, proposalUserYesStore(user, id)), 0) | |
95 | 98 | ||
96 | 99 | ||
97 | 100 | func userNo (user,id) = valueOrElse(getInteger(this, proposalUserNoStore(user, id)), 0) | |
98 | 101 | ||
99 | 102 | ||
100 | 103 | func userLastProposeHeight (user) = valueOrElse(getInteger(this, userLastProposeHeightStore(user)), -1) | |
101 | 104 | ||
102 | 105 | ||
103 | 106 | let thisAddress = toString(this) | |
104 | 107 | ||
105 | 108 | func settings (key,child) = valueOrElse(getInteger(((key + "_") + child)), valueOrErrorMessage(getInteger(configAddress, ((thisAddress + "_") + key)), (key + " is not defined"))) | |
106 | 109 | ||
107 | 110 | ||
108 | 111 | func userProposeDelay (child) = settings("user_propose_delay", child) | |
109 | 112 | ||
110 | 113 | ||
111 | 114 | func quorumRatio (child) = settings("proposal_quorum_ratio", child) | |
112 | 115 | ||
113 | 116 | ||
114 | 117 | func passedRatio (child) = settings("proposal_passed_ratio", child) | |
115 | 118 | ||
116 | 119 | ||
117 | 120 | func proposalMinRequired (child) = settings("proposal_min_power_required", child) | |
118 | 121 | ||
119 | 122 | ||
120 | 123 | func votingStartOffset (child) = settings("proposal_votingstart_offset", child) | |
121 | 124 | ||
122 | 125 | ||
123 | 126 | func votingEndOffset (child) = settings("proposal_votingend_offset", child) | |
124 | 127 | ||
125 | 128 | ||
126 | 129 | func proposalQuorumStore (txid) = ("proposal_quorum_ratio_" + txid) | |
127 | 130 | ||
128 | 131 | ||
129 | 132 | func quorum (child,txId) = valueOrElse(getInteger(proposalQuorumStore(txId)), quorumRatio(child)) | |
130 | 133 | ||
131 | 134 | ||
132 | 135 | func userPower (child,user) = asInt(invoke(childrenContract, "userPower", [child, user], nil)) | |
133 | 136 | ||
134 | 137 | ||
135 | 138 | func isParticipant (power) = if ((power == 0)) | |
136 | 139 | then throw("you are not a participant of this dao") | |
137 | 140 | else nil | |
138 | 141 | ||
139 | 142 | ||
140 | 143 | func proposalExists (txId) = match getInteger(this, proposalHeightStore(txId)) { | |
141 | 144 | case start: Int => | |
142 | 145 | true | |
143 | 146 | case _ => | |
144 | 147 | false | |
145 | 148 | } | |
146 | 149 | ||
147 | 150 | ||
148 | 151 | func proposalOnVoting (txId) = { | |
149 | 152 | let nonExistErr = "proposal doesn't exist" | |
150 | 153 | if (!(proposalExists(txId))) | |
151 | 154 | then throw(nonExistErr) | |
152 | 155 | else { | |
153 | 156 | let votingStart = valueOrErrorMessage(getInteger(this, proposalVotingStartStore(txId)), nonExistErr) | |
154 | 157 | let votingEnd = valueOrErrorMessage(getInteger(this, proposalVotingEndStore(txId)), nonExistErr) | |
155 | 158 | if ((votingStart > HEIGHT)) | |
156 | 159 | then throw(((("voting not started yet, discussion is in progress, voting will start at block " + toString(votingStart)) + ", now it's ") + toString(HEIGHT))) | |
157 | 160 | else if ((HEIGHT > votingEnd)) | |
158 | 161 | then throw(((("voting ended at block " + toString(votingEnd)) + ", now it's ") + toString(HEIGHT))) | |
159 | 162 | else true | |
160 | 163 | } | |
161 | 164 | } | |
162 | 165 | ||
163 | 166 | ||
164 | 167 | func proposalBeforeVoting (txId) = { | |
165 | 168 | let nonExistErr = "proposal doesn't exist" | |
166 | 169 | if (!(proposalExists(txId))) | |
167 | 170 | then throw(nonExistErr) | |
168 | 171 | else { | |
169 | 172 | let votingStart = valueOrErrorMessage(getInteger(this, proposalVotingStartStore(txId)), nonExistErr) | |
170 | 173 | if ((HEIGHT >= votingStart)) | |
171 | 174 | then throw("voting start is already happened") | |
172 | 175 | else true | |
173 | 176 | } | |
174 | 177 | } | |
175 | 178 | ||
176 | 179 | ||
177 | 180 | func totalPowerStaked (child) = asInt(invoke(childrenContract, "totalPower", [child], nil)) | |
178 | 181 | ||
179 | 182 | ||
180 | 183 | func canBroadcast (child,txId,yesInc,noInc) = { | |
181 | 184 | let votesYes = (valueOrElse(getInteger(proposalTotalYesStore(txId)), 0) + yesInc) | |
182 | 185 | let votesNo = (valueOrElse(getInteger(proposalTotalNoStore(txId)), 0) + noInc) | |
183 | 186 | let proposalHeight = valueOrErrorMessage(getInteger(proposalHeightStore(txId)), "proposal not registered") | |
184 | 187 | let totalPower = totalPowerStaked(child) | |
185 | 188 | if ((totalPower == totalPower)) | |
186 | 189 | then { | |
187 | 190 | let passed = passedRatio(child) | |
188 | 191 | let totalVotes = (votesYes + votesNo) | |
189 | 192 | let hasQuorum = (((totalVotes * BASE) / totalPower) >= quorum(child, txId)) | |
190 | 193 | let hasPassed = (((votesYes * BASE) / totalVotes) >= passed) | |
191 | 194 | if (hasQuorum) | |
192 | 195 | then hasPassed | |
193 | 196 | else false | |
194 | 197 | } | |
195 | 198 | else throw("Strict value is not equal to itself.") | |
196 | 199 | } | |
197 | 200 | ||
198 | 201 | ||
199 | 202 | func adviseProposal (txId) = { | |
200 | 203 | let child = valueOrErrorMessage(getString(proposalChildStore(txId)), "child not found") | |
201 | 204 | let proposalHeight = valueOrErrorMessage(getInteger(this, proposalHeightStore(txId)), "no proposal") | |
202 | 205 | let votingStart = valueOrErrorMessage(getInteger(this, proposalVotingStartStore(txId)), "no proposal") | |
203 | 206 | let votingEnd = valueOrErrorMessage(getInteger(this, proposalVotingEndStore(txId)), "no proposal") | |
204 | 207 | let votesYes = valueOrElse(getInteger(this, proposalTotalYesStore(txId)), 0) | |
205 | 208 | let votesNo = valueOrElse(getInteger(this, proposalTotalNoStore(txId)), 0) | |
206 | 209 | let totalPowerSnap = totalPowerStaked(child) | |
207 | 210 | if ((totalPowerSnap == totalPowerSnap)) | |
208 | 211 | then { | |
209 | 212 | let q = quorum(child, txId) | |
210 | 213 | let totalVotes = (votesYes + votesNo) | |
211 | 214 | let hasQuorum = if ((totalVotes > 0)) | |
212 | 215 | then (((totalVotes * BASE) / totalPowerSnap) >= q) | |
213 | 216 | else false | |
214 | 217 | let hasPassed = if ((totalVotes > 0)) | |
215 | 218 | then (((votesYes * BASE) / totalVotes) >= passedRatio(child)) | |
216 | 219 | else false | |
217 | 220 | let inBlockchainHeight = valueOrElse(transactionHeightById(fromBase58String(txId)), 0) | |
218 | 221 | let status = if ((votingStart > HEIGHT)) | |
219 | 222 | then "discussion" | |
220 | 223 | else if ((votingEnd >= HEIGHT)) | |
221 | 224 | then "voting" | |
222 | 225 | else if (!(hasQuorum)) | |
223 | 226 | then "noQuorum" | |
224 | 227 | else if (!(hasPassed)) | |
225 | 228 | then "votingFailed" | |
226 | 229 | else if ((inBlockchainHeight > 0)) | |
227 | 230 | then "inBlockchain" | |
228 | 231 | else "waitingForTx" | |
229 | 232 | let broadcastHeight = valueOrElse(getInteger(votingResultContract, ((("proposal_allow_broadcast_" + child) + "_") + txId)), -1) | |
230 | - | ((((((((((((((((((((((((((("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_power: ") + toString(totalPowerSnap)) + ", vote_yes: ") + toString(votesYes)) + ", vote_no: ") + toString(votesNo)) + ", proposal_allow_broadcast: ") + toString(if ((broadcastHeight != -1)) | |
233 | + | ((((((((((((((((((((((((((((("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_power: ") + toString(totalPowerSnap)) + ", vote_yes: ") + toString(votesYes)) + ", vote_no: ") + toString(votesNo)) + ", proposal_allow_broadcast: ") + toString(if ((broadcastHeight != -1)) | |
231 | 234 | then (HEIGHT >= broadcastHeight) | |
232 | - | else false)) + ", proposal_allow_broadcast_height: ") + toString(broadcastHeight)) + ", proposal_voting_succeed:") + toString((broadcastHeight != -1))) + ", proposal_quorum:") + toString(q)) | |
235 | + | else false)) + ", proposal_allow_broadcast_height: ") + toString(broadcastHeight)) + ", proposal_voting_succeed:") + toString((broadcastHeight != -1))) + ", proposal_quorum:") + toString(q)) + ", proposal_address: ") + valueOrElse(proposalAddressStore(txId), child)) | |
233 | 236 | } | |
234 | 237 | else throw("Strict value is not equal to itself.") | |
235 | 238 | } | |
236 | 239 | ||
237 | 240 | ||
238 | 241 | func broadcastHeight (txId) = (getIntegerValue(proposalVotingEndStore(txId)) + 1) | |
239 | 242 | ||
240 | 243 | ||
241 | 244 | @Callable(i) | |
242 | 245 | func propose (child,txId,attachments) = { | |
243 | 246 | let checks = opAllowed("child_governance_propose_tx") | |
244 | 247 | if ((checks == checks)) | |
245 | 248 | then { | |
246 | 249 | let required = proposalMinRequired(child) | |
247 | 250 | let user = toString(i.caller) | |
248 | 251 | let gv = userPower(child, user) | |
249 | 252 | if ((gv == gv)) | |
250 | 253 | then if ((required > gv)) | |
251 | 254 | then throw((((("not enough staked power to make proposal." + " Minimum required = ") + toString(required)) + ", actual: = ") + toString(gv))) | |
252 | 255 | else { | |
253 | 256 | let delay = userProposeDelay(child) | |
254 | 257 | let last = userLastProposeHeight(user) | |
255 | 258 | if (if ((last > -1)) | |
256 | 259 | then ((last + delay) > HEIGHT) | |
257 | 260 | else false) | |
258 | 261 | then throw(((("can't propose too often, last proroposal height: " + toString(last)) + ", blocks to wait: ") + toString(((last + delay) - HEIGHT)))) | |
259 | - | else [writeConstString(proposalChildStore(txId), child), writeConstInt(proposalHeightStore(txId), HEIGHT), writeConstInt(proposalVotingStartStore(txId), (HEIGHT + votingStartOffset(child))), writeConstInt(proposalVotingEndStore(txId), (HEIGHT + votingEndOffset(child))), writeConstString(proposalByStore(txId), user), writeInt(userLastProposeHeightStore(user), HEIGHT), writeBinary(proposalAttachmentsStore(txId), attachments)] | |
262 | + | else { | |
263 | + | let address = valueOrElse(getString(childrenContract, ("treasury_" + child)), child) | |
264 | + | [writeConstString(proposalChildStore(txId), child), writeConstInt(proposalHeightStore(txId), HEIGHT), writeConstInt(proposalVotingStartStore(txId), (HEIGHT + votingStartOffset(child))), writeConstInt(proposalVotingEndStore(txId), (HEIGHT + votingEndOffset(child))), writeConstString(proposalByStore(txId), user), writeInt(userLastProposeHeightStore(user), HEIGHT), writeBinary(proposalAttachmentsStore(txId), attachments), writeConstString(proposalAddressStore(txId), address)] | |
265 | + | } | |
260 | 266 | } | |
261 | 267 | else throw("Strict value is not equal to itself.") | |
262 | 268 | } | |
263 | 269 | else throw("Strict value is not equal to itself.") | |
264 | 270 | } | |
265 | 271 | ||
266 | 272 | ||
267 | 273 | ||
268 | 274 | @Callable(i) | |
269 | 275 | func editAttachments (txId,attachments) = { | |
270 | 276 | let checks = opAllowed("child_governance_edit_attachments") | |
271 | 277 | if ((checks == checks)) | |
272 | 278 | then { | |
273 | 279 | let user = toString(i.caller) | |
274 | 280 | let by = valueOrErrorMessage(getString(this, proposalByStore(txId)), "proposal doesn't exist") | |
275 | 281 | if ((by != user)) | |
276 | 282 | then throw("only owner can edit proposal attachments") | |
277 | 283 | else [writeBinary(proposalAttachmentsStore(txId), attachments)] | |
278 | 284 | } | |
279 | 285 | else throw("Strict value is not equal to itself.") | |
280 | 286 | } | |
281 | 287 | ||
282 | 288 | ||
283 | 289 | ||
284 | 290 | @Callable(i) | |
285 | 291 | func voteYes (txId) = { | |
286 | 292 | let checks = if (opAllowed("child_governance_vote_tx")) | |
287 | 293 | then proposalOnVoting(txId) | |
288 | 294 | else false | |
289 | 295 | if ((checks == checks)) | |
290 | 296 | then { | |
291 | 297 | let user = toString(i.caller) | |
292 | 298 | if ((userNo(user, txId) > 0)) | |
293 | 299 | then throw("already voted against, please retract your vote first") | |
294 | 300 | else { | |
295 | 301 | let yes = userYes(user, txId) | |
296 | 302 | if ((yes > 0)) | |
297 | 303 | then throw("already voted") | |
298 | 304 | else { | |
299 | 305 | let child = valueOrErrorMessage(getString(proposalChildStore(txId)), "child not found") | |
300 | 306 | let power = userPower(child, user) | |
301 | 307 | if ((power == power)) | |
302 | 308 | then { | |
303 | 309 | let p = isParticipant(power) | |
304 | 310 | if ((p == p)) | |
305 | 311 | then { | |
306 | 312 | let result = canBroadcast(child, txId, power, 0) | |
307 | - | let setResult = invoke(votingResultContract, "setResult", [child, txId, result, broadcastHeight(txId)], nil) | |
313 | + | let txAddress = valueOrElse(getString(proposalAddressStore(txId)), child) | |
314 | + | let setResult = invoke(votingResultContract, "setResult", [txAddress, txId, result, broadcastHeight(txId)], nil) | |
308 | 315 | if ((setResult == setResult)) | |
309 | 316 | then [changeBy(proposalUserYesStore(user, txId), power), changeBy(proposalTotalYesStore(txId), power)] | |
310 | 317 | else throw("Strict value is not equal to itself.") | |
311 | 318 | } | |
312 | 319 | else throw("Strict value is not equal to itself.") | |
313 | 320 | } | |
314 | 321 | else throw("Strict value is not equal to itself.") | |
315 | 322 | } | |
316 | 323 | } | |
317 | 324 | } | |
318 | 325 | else throw("Strict value is not equal to itself.") | |
319 | 326 | } | |
320 | 327 | ||
321 | 328 | ||
322 | 329 | ||
323 | 330 | @Callable(i) | |
324 | 331 | func voteNo (txId) = { | |
325 | 332 | let checks = if (opAllowed("child_governance_vote_tx")) | |
326 | 333 | then proposalOnVoting(txId) | |
327 | 334 | else false | |
328 | 335 | if ((checks == checks)) | |
329 | 336 | then { | |
330 | 337 | let user = toString(i.caller) | |
331 | 338 | if ((userYes(user, txId) > 0)) | |
332 | 339 | then throw("already voted for, please retract your vote first") | |
333 | 340 | else { | |
334 | 341 | let no = userNo(user, txId) | |
335 | 342 | if ((no > 0)) | |
336 | 343 | then throw("already voted") | |
337 | 344 | else { | |
338 | 345 | let child = valueOrErrorMessage(getString(proposalChildStore(txId)), "child not found") | |
339 | 346 | let power = userPower(child, user) | |
340 | 347 | if ((power == power)) | |
341 | 348 | then { | |
342 | 349 | let p = isParticipant(power) | |
343 | 350 | if ((p == p)) | |
344 | 351 | then { | |
345 | 352 | let result = canBroadcast(child, txId, 0, power) | |
346 | - | let setResult = invoke(votingResultContract, "setResult", [child, txId, result, broadcastHeight(txId)], nil) | |
353 | + | let txAddress = valueOrElse(getString(proposalAddressStore(txId)), child) | |
354 | + | let setResult = invoke(votingResultContract, "setResult", [txAddress, txId, result, broadcastHeight(txId)], nil) | |
347 | 355 | if ((setResult == setResult)) | |
348 | 356 | then [changeBy(proposalUserNoStore(user, txId), power), changeBy(proposalTotalNoStore(txId), power)] | |
349 | 357 | else throw("Strict value is not equal to itself.") | |
350 | 358 | } | |
351 | 359 | else throw("Strict value is not equal to itself.") | |
352 | 360 | } | |
353 | 361 | else throw("Strict value is not equal to itself.") | |
354 | 362 | } | |
355 | 363 | } | |
356 | 364 | } | |
357 | 365 | else throw("Strict value is not equal to itself.") | |
358 | 366 | } | |
359 | 367 | ||
360 | 368 | ||
361 | 369 | ||
362 | 370 | @Callable(i) | |
363 | 371 | func retract (txId) = { | |
364 | 372 | let checks = if (opAllowed("child_governance_retract_vote")) | |
365 | 373 | then proposalOnVoting(txId) | |
366 | 374 | else false | |
367 | 375 | if ((checks == checks)) | |
368 | 376 | then { | |
369 | 377 | let user = toString(i.caller) | |
370 | 378 | let child = valueOrErrorMessage(getString(proposalChildStore(txId)), "child not found") | |
371 | 379 | let yes = -(userYes(user, txId)) | |
372 | 380 | let no = -(userNo(user, txId)) | |
373 | 381 | let result = canBroadcast(child, txId, yes, no) | |
374 | - | let setResult = invoke(votingResultContract, "setResult", [child, txId, result, broadcastHeight(txId)], nil) | |
382 | + | let txAddress = valueOrElse(getString(proposalAddressStore(txId)), child) | |
383 | + | let setResult = invoke(votingResultContract, "setResult", [txAddress, txId, result, broadcastHeight(txId)], nil) | |
375 | 384 | if ((setResult == setResult)) | |
376 | 385 | then [changeBy(proposalTotalYesStore(txId), yes), changeBy(proposalTotalNoStore(txId), no), DeleteEntry(proposalUserYesStore(user, txId)), DeleteEntry(proposalUserNoStore(user, txId))] | |
377 | 386 | else throw("Strict value is not equal to itself.") | |
378 | 387 | } | |
379 | 388 | else throw("Strict value is not equal to itself.") | |
380 | 389 | } | |
381 | 390 | ||
382 | 391 | ||
383 | 392 | ||
384 | 393 | @Callable(i) | |
385 | 394 | func retractProposal (txId) = { | |
386 | 395 | let checks = if (opAllowed("child_governance_retract_proposal_tx")) | |
387 | 396 | then proposalBeforeVoting(txId) | |
388 | 397 | else false | |
389 | 398 | if ((checks == checks)) | |
390 | 399 | then { | |
391 | 400 | let by = valueOrErrorMessage(getString(this, proposalByStore(txId)), "proposal doesn't exist") | |
392 | 401 | let user = toString(i.caller) | |
393 | 402 | if ((by != user)) | |
394 | 403 | then throw("only owner can retract proposal") | |
395 | - | else [DeleteEntry(proposalChildStore(txId)), DeleteEntry(proposalHeightStore(txId)), DeleteEntry(proposalVotingStartStore(txId)), DeleteEntry(proposalVotingEndStore(txId)), DeleteEntry(proposalByStore(txId)), DeleteEntry(proposalTotalYesStore(txId)), DeleteEntry(proposalTotalNoStore(txId)), DeleteEntry(proposalUserYesStore(user, txId)), DeleteEntry(proposalUserNoStore(user, txId)), DeleteEntry(userLastProposeHeightStore(user))] | |
404 | + | else [DeleteEntry(proposalChildStore(txId)), DeleteEntry(proposalHeightStore(txId)), DeleteEntry(proposalVotingStartStore(txId)), DeleteEntry(proposalVotingEndStore(txId)), DeleteEntry(proposalByStore(txId)), DeleteEntry(proposalTotalYesStore(txId)), DeleteEntry(proposalTotalNoStore(txId)), DeleteEntry(proposalUserYesStore(user, txId)), DeleteEntry(proposalUserNoStore(user, txId)), DeleteEntry(userLastProposeHeightStore(user)), DeleteEntry(proposalAddressStore(txId))] | |
396 | 405 | } | |
397 | 406 | else throw("Strict value is not equal to itself.") | |
398 | 407 | } | |
399 | 408 | ||
400 | 409 | ||
401 | 410 | ||
402 | 411 | @Callable(i) | |
403 | 412 | func init (config) = [writeConstString(configAddressStore, config)] | |
404 | 413 | ||
405 | 414 |
github/deemru/w8io/3ef1775 76.41 ms ◑