tx · 5iTiPMMEZXVpDpsZB8WjiqeMDHAcqn8QxwQAAnsBYBHY 3MwFEMuNTRTZhZMw4WiGEtSfYiWqDMmrK7D: -0.01000000 Waves 2022.03.17 12:53 [1967783] smart account 3MwFEMuNTRTZhZMw4WiGEtSfYiWqDMmrK7D > SELF 0.00000000 Waves
{ "type": 13, "id": "5iTiPMMEZXVpDpsZB8WjiqeMDHAcqn8QxwQAAnsBYBHY", "fee": 1000000, "feeAssetId": null, "timestamp": 1647510845744, "version": 1, "sender": "3MwFEMuNTRTZhZMw4WiGEtSfYiWqDMmrK7D", "senderPublicKey": "BqyHrfDTfAgrmYrQ1WpsawT3NyagsKDi6KTuDTMLfCGL", "proofs": [ "22tjypSu1XKcqZds1JtqBVaNzteZFPynu83Sk3A5mrgMLg5em1mGbWGEBtqfsuco8dzn8fg4kibKZ2KVDva1WyD4" ], "script": "base64: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c2V0SWQJAAJZAAAAAQkBAAAAD2dldFN0cmluZ09yRmFpbAAAAAEFAAAADGtleVd4QXNzZXRJZAAAAAAPdm90aW5nVGhyZXNob2xkCQEAAAAQZ2V0SW50ZWdlck9yRmFpbAAAAAEFAAAAEmtleVZvdGluZ1RocmVzaG9sZAAAAAAOdm90aW5nRHVyYXRpb24JAQAAABBnZXRJbnRlZ2VyT3JGYWlsAAAAAQUAAAARa2V5Vm90aW5nRHVyYXRpb24AAAAAFXZvdGVCZWZvcmVFbGltaW5hdGlvbgkBAAAAEGdldEludGVnZXJPckZhaWwAAAABBQAAABhrZXlWb3RlQmVmb3JlRWxpbWluYXRpb24AAAAAC3N0YXJ0SGVpZ2h0CQEAAAAQZ2V0SW50ZWdlck9yRmFpbAAAAAEFAAAADmtleVN0YXJ0SGVpZ2h0AAAAAA1jdXJyZW50UGVyaW9kCQEAAAAQZ2V0SW50ZWdlck9yRmFpbAAAAAEFAAAAEGtleUN1cnJlbnRQZXJpb2QAAAAAEGJvb3N0aW5nQ29udHJhY3QJAQAAABFAZXh0ck5hdGl2ZSgxMDYyKQAAAAEJAQAAAA9nZXRTdHJpbmdPckZhaWwAAAABBQAAABNrZXlCb29zdGluZ0NvbnRyYWN0AAAAABBlbWlzc2lvbkNvbnRyYWN0CQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABCQEAAAAPZ2V0U3RyaW5nT3JGYWlsAAAAAQUAAAATa2V5RW1pc3Npb25Db250cmFjdAEAAAAYZ2V0VXNlckd3eEFtb3VudEF0SGVpZ2h0AAAAAgAAAAt1c2VyQWRkcmVzcwAAAAx0YXJnZXRIZWlnaHQEAAAACWd3eEFtb3VudAkAA/wAAAAEBQAAABBib29zdGluZ0NvbnRyYWN0AgAAACBnZXRVc2VyR3d4QW1vdW50QXRIZWlnaHRSRUFET05MWQkABEwAAAACBQAAAAt1c2VyQWRkcmVzcwkABEwAAAACBQAAAAx0YXJnZXRIZWlnaHQFAAAAA25pbAUAAAADbmlsCQEAAAAFYXNJbnQAAAABBQAAAAlnd3hBbW91bnQBAAAADGNvbnRhaW5zTm9kZQAAAAIAAAAIbGlzdE5hbWUAAAACaWQEAAAABGhlYWQJAAQdAAAAAgUAAAAEdGhpcwkBAAAA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AAtEZWxldGVFbnRyeQAAAAEFAAAAFmtleUxhdGVzdFByb2Nlc3NlZFVzZXIDCQAAAAAAAAIFAAAAEXVzZXJBZGRyZXNzT3JVbml0BQAAAAR1bml0CQAETAAAAAIFAAAAIHVwZGF0ZUxhdGVzdFByb2Nlc3NlZEFzc2V0QWN0aW9uCQAETAAAAAIFAAAAH2RlbGV0ZUxhdGVzdFByb2Nlc3NlZFVzZXJBY3Rpb24FAAAAA25pbAQAAAAJZW5kSGVpZ2h0CQAAZAAAAAIFAAAAC3N0YXJ0SGVpZ2h0BQAAAA52b3RpbmdEdXJhdGlvbgQAAAALdXNlckFkZHJlc3MJAQAAAAV2YWx1ZQAAAAEFAAAAEXVzZXJBZGRyZXNzT3JVbml0BAAAAB91cGRhdGVMYXRlc3RQcm9jZXNzZWRVc2VyQWN0aW9uCQEAAAALU3RyaW5nRW50cnkAAAACBQAAABZrZXlMYXRlc3RQcm9jZXNzZWRVc2VyBQAAAAt1c2VyQWRkcmVzcwQAAAALdXNlclZvdGVLZXkJAQAAABNrZXlVc2VyVm90ZUJ5UGVyaW9kAAAAAwUAAAALdXNlckFkZHJlc3MFAAAAB2Fzc2V0SWQFAAAADWN1cnJlbnRQZXJpb2QEAAAADnVzZXJWb3RlT3JVbml0CQAEIgAAAAEFAAAAC3VzZXJWb3RlS2V5BAAAABh1c2VyR3d4QW1vdW50QXRFbmRIZWlnaHQJAQAAABhnZXRVc2VyR3d4QW1vdW50QXRIZWlnaHQAAAACBQAAAAt1c2VyQWRkcmVzcwUAAAAJZW5kSGVpZ2h0BAAAAAt2b3RlQWN0aW9ucwMJAAAAAAAAAgUAAAAYdXNlckd3eEFtb3VudEF0RW5kSGVpZ2h0AAAAAAAAAAAABAAAAA12b3Rlc0xpc3ROYW1lCQEAAAAQZ2V0Vm90ZXNMaXN0TmFtZQAAAAEFAAAAB2Fzc2V0SWQJAQAAAApkZWxldGVOb2RlAAAAAgUAAAANdm90ZXNMaXN0TmFtZQUAAAALdXNlckFkZHJlc3MEAAAAGWludGVybWVkaWF0ZVZvdGVSZXN1bHRLZXkJAQAAACFrZXlJbnRlcm1lZGlhdGVWb3RlUmVzdWx0QnlQZXJpb2QAAAACBQAAAAdhc3NldElkBQAAAA1jdXJyZW50UGVyaW9kBAAAAAskdDA3NzY0NzkzMgQAAAAHJG1hdGNoMAkABCIAAAABBQAAABlpbnRlcm1lZGlhdGVWb3RlUmVzdWx0S2V5AwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAAZTdHJpbmcEAAAAAXMFAAAAByRtYXRjaDAJAQAAABtwYXJzZUludGVybWVkaWF0ZVZvdGVSZXN1bHQAAAABBQAAAAFzAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAARVbml0CQAFFAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAJAAACAAAAAQIAAAALTWF0Y2ggZXJyb3IEAAAACHRvdGFsWWVzCAUAAAALJHQwNzc2NDc5MzIAAAACXzEEAAAAB3RvdGFsTm8IBQAAAAskdDA3NzY0NzkzMgAAAAJfMgoBAAAAH2dldEludGVybWVkaWF0ZVZvdGVSZXN1bHRBY3Rpb24AAAAEAAAACHRvdGFsWWVzAAAAB3RvdGFsTm8AAAAFdG90YWwAAAAHaW5GYXZvcgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAAZaW50ZXJtZWRpYXRlVm90ZVJlc3VsdEtleQkBAAAAHGZvcm1hdEludGVybWVkaWF0ZVZvdGVSZXN1bHQAAAACCQAAZAAAAAIFAAAACHRvdGFsWWVzAwUAAAAHaW5GYXZvcgUAAAAFdG90YWwAAAAAAAAAAAAJAABkAAAAAgUAAAAHdG90YWxObwMFAAAAB2luRmF2b3IAAAAAAAAAAAAFAAAABXRvdGFsAwkAAAAAAAACBQAAAA51c2VyVm90ZU9yVW5pdAUAAAAEdW5pdAQAAAAWdXNlclByZXZpb3VzVm90ZU9yVW5pdAkABCIAAAABCQEAAAATa2V5VXNlclZvdGVCeVBlcmlvZAAAAAMFAAAAC3VzZXJBZGRyZXNzBQAAAAdhc3NldElkCQAAZQAAAAIFAAAADWN1cnJlbnRQZXJpb2QAAAAAAAAAAAEDCQAAAAAAAAIFAAAAFnVzZXJQcmV2aW91c1ZvdGVPclVuaXQFAAAABHVuaXQFAAAAA25pbAQAAAALJHQwODU3NTg2NDgJAQAAAA1wYXJzZVVzZXJWb3RlAAAAAQkBAAAABXZhbHVlAAAAAQUAAAAWdXNlclByZXZpb3VzVm90ZU9yVW5pdAQAAAAJcHJldlRvdGFsCAUAAAALJHQwODU3NTg2NDgAAAACXzEEAAAAB2luRmF2b3IIBQAAAAskdDA4NTc1ODY0OAAAAAJfMgQAAAAFdG90YWwJAAGXAAAAAQkABEwAAAACBQAAAAlwcmV2VG90YWwJAARMAAAAAgUAAAAYdXNlckd3eEFtb3VudEF0RW5kSGVpZ2h0BQAAAANuaWwJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAALdXNlclZvdGVLZXkJAQAAAA5mb3JtYXRVc2VyVm90ZQAAAAIFAAAABXRvdGFsBQAAAAdpbkZhdm9yCQAETAAAAAIJAQAAAB9nZXRJbnRlcm1lZGlhdGVWb3RlUmVzdWx0QWN0aW9uAAAABAUAAAAIdG90YWxZZXMFAAAAB3RvdGFsTm8FAAAABXRvdGFsBQAAAAdpbkZhdm9yBQAAAANuaWwEAAAACyR0MDg5MTk4OTgwCQEAAAANcGFyc2VVc2VyVm90ZQAAAAEJAQAAAAV2YWx1ZQAAAAEFAAAADnVzZXJWb3RlT3JVbml0BAAAAAV0b3RhbAgFAAAACyR0MDg5MTk4OTgwAAAAAl8xBAAAAAdpbkZhdm9yCAUAAAALJHQwODkxOTg5ODAAAAACXzIJAARMAAAAAgkBAAAAH2dldEludGVybWVkaWF0ZVZvdGVSZXN1bHRBY3Rpb24AAAAEBQAAAAh0b3RhbFllcwUAAAAHdG90YWxObwUAAAAFdG90YWwFAAAAB2luRmF2b3IFAAAAA25pbAkABE0AAAACCQAETQAAAAIFAAAAC3ZvdGVBY3Rpb25zBQAAACB1cGRhdGVMYXRlc3RQcm9jZXNzZWRBc3NldEFjdGlvbgUAAAAfdXBkYXRlTGF0ZXN0UHJvY2Vzc2VkVXNlckFjdGlvbgAAAAoAAAABaQEAAAALY29uc3RydWN0b3IAAAAIAAAAE2Jvb3N0aW5nQ29udHJhY3RQcm0AAAATZW1pc3Npb25Db250cmFjdFBybQAAAAxmZWVBbW91bnRQcm0AAAAMd3hBc3NldElkUHJtAAAAEnZvdGluZ1RocmVzaG9sZFBybQAAABF2b3RpbmdEdXJhdGlvblBybQAAABh2b3RlQmVmb3JlRWxpbWluYXRpb25Qcm0AAAAOc3RhcnRIZWlnaHRQcm0EAAAABmNoZWNrcwkABEwAAAACCQEAAAAIdGhpc09ubHkAAAABBQAAAAFpCQAETAAAAAIDCQEAAAAJaXNEZWZpbmVkAAAAAQkABCYAAAABBQAAABNib29zdGluZ0NvbnRyYWN0UHJtBgkAAAIAAAABAgAAACFJbnZhbGlkIGJvb3N0aW5nIGNvbnRyYWN0IGFkZHJlc3MJAARMAAAAAgMJAQAAAAlpc0RlZmluZWQAAAABCQAEJgAAAAEFAAAAE2VtaXNzaW9uQ29udHJhY3RQcm0GCQAAAgAAAAECAAAAIUludmFsaWQgZW1pc3Npb24gY29udHJhY3QgYWRkcmVzcwkABEwAAAACAwkAAGcAAAACBQAAAAxmZWVBbW91bnRQcm0AAAAAAAAAAAAGCQAAAgAAAAECAAAAEkludmFsaWQgZmVlIGFtb3VudAkABEwAAAACAwkBAAAACWlzRGVmaW5lZAAAAAEJAAPsAAAAAQkAAlkAAAABBQAAAAx3eEFzc2V0SWRQcm0GCQAAAgAAAAECAAAAE0ludmFsaWQgV1ggYXNzZXQgSUQJAARMAAAAAgMJAABnAAAAAgUAAAASdm90aW5nVGhyZXNob2xkUHJtAAAAAAAAAAAABgkAAAIAAAABAgAAABhJbnZhbGlkIHZvdGluZyB0aHJlc2hvbGQJAARMAAAAAgMJAABmAAAAAgUAAAARdm90aW5nRHVyYXRpb25Qcm0AAAAAAAAAAAAGCQAAAgAAAAECAAAAF0ludmFsaWQgdm90aW5nIGR1cmF0aW9uCQAETAAAAAIDCQAAZgAAAAIJAABkAAAAAgUAAAAOc3RhcnRIZWlnaHRQcm0FAAAAEXZvdGluZ0R1cmF0aW9uUHJtBQAAAAZoZWlnaHQGCQAAAgAAAAECAAAAFEludmFsaWQgc3RhcnQgaGVpZ2h0BQAAAANuaWwDCQAAAAAAAAIFAAAABmNoZWNrcwUAAAAGY2hlY2tzCQAFFAAAAAIJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAATa2V5Qm9vc3RpbmdDb250cmFjdAUAAAATYm9vc3RpbmdDb250cmFjdFBybQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAABNrZXlFbWlzc2lvbkNvbnRyYWN0BQAAABNlbWlzc2lvbkNvbnRyYWN0UHJtCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAxrZXlGZWVBbW91bnQFAAAADGZlZUFtb3VudFBybQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAAAxrZXlXeEFzc2V0SWQFAAAADHd4QXNzZXRJZFBybQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAASa2V5Vm90aW5nVGhyZXNob2xkBQAAABJ2b3RpbmdUaHJlc2hvbGRQcm0JAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAEWtleVZvdGluZ0R1cmF0aW9uBQAAABF2b3RpbmdEdXJhdGlvblBybQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAYa2V5Vm90ZUJlZm9yZUVsaW1pbmF0aW9uBQAAABh2b3RlQmVmb3JlRWxpbWluYXRpb25Qcm0JAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAADmtleVN0YXJ0SGVpZ2h0BQAAAA5zdGFydEhlaWdodFBybQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAQa2V5Q3VycmVudFBlcmlvZAAAAAAAAAAAAAUAAAADbmlsBQAAAAR1bml0CQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgAAAAFpAQAAAAdzdWdnZXN0AAAAAgAAAAdhc3NldElkAAAACmFzc2V0SW1hZ2UEAAAABGluZm8JAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkAA+wAAAABCQACWQAAAAEFAAAAB2Fzc2V0SWQCAAAAEEludmFsaWQgYXNzZXQgSUQEAAAAB3BheW1lbnQJAQAAAAV2YWx1ZQAAAAEJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAEAAAABmNoZWNrcwkABEwAAAACAwkAAAAAAAACCAUAAAAEaW5mbwAAAAZpc3N1ZXIIBQAAAAFpAAAABmNhbGxlcgYJAAACAAAAAQIAAAApQXNzZXQgY2FuIG9ubHkgYmUgc3VnZ2VzdGVkIGJ5IGl0cyBpc3N1ZXIJAARMAAAAAgMJAAAAAAAAAgkBAAAABXZhbHVlAAAAAQgFAAAAB3BheW1lbnQAAAAHYXNzZXRJZAUAAAAJd3hBc3NldElkBgkAAAIAAAABAgAAABFJbnZhbGlkIGZlZSBhc3NldAkABEwAAAACAwkAAAAAAAACCAUAAAAHcGF5bWVudAAAAAZhbW91bnQFAAAACWZlZUFtb3VudAYJAAACAAAAAQIAAAASSW52YWxpZCBmZWUgYW1vdW50BQAAAANuaWwDCQAAAAAAAAIFAAAABmNoZWNrcwUAAAAGY2hlY2tzBAAAAApidXJuRmVlSW52CQAD/AAAAAQFAAAAEGVtaXNzaW9uQ29udHJhY3QCAAAABGJ1cm4FAAAAA25pbAkABEwAAAACCQEAAAAPQXR0YWNoZWRQYXltZW50AAAAAggFAAAAB3BheW1lbnQAAAAHYXNzZXRJZAgFAAAAB3BheW1lbnQAAAAGYW1vdW50BQAAAANuaWwDCQAAAAAAAAIFAAAACmJ1cm5GZWVJbnYFAAAACmJ1cm5GZWVJbnYEAAAAD2FkZEFzc2V0QWN0aW9ucwkBAAAACmluc2VydE5vZGUAAAACBQAAAA5hc3NldHNMaXN0TmFtZQUAAAAHYXNzZXRJZAkABRQAAAACCQAETQAAAAIFAAAAD2FkZEFzc2V0QWN0aW9ucwkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAADWtleUFzc2V0SW1hZ2UAAAABBQAAAAdhc3NldElkBQAAAAphc3NldEltYWdlBQAAAAR1bml0CQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAABaQEAAAAEdm90ZQAAAAIAAAAHYXNzZXRJZAAAAAdpbkZhdm9yBAAAAAllbmRIZWlnaHQJAABkAAAAAgUAAAALc3RhcnRIZWlnaHQFAAAADnZvdGluZ0R1cmF0aW9uBAAAAApjaGVja0Fzc2V0AwkBAAAADGNvbnRhaW5zTm9kZQAAAAIFAAAADmFzc2V0c0xpc3ROYW1lBQAAAAdhc3NldElkBgkAAAIAAAABAgAAAA1JbnZhbGlkIGFzc2V0AwkAAAAAAAACBQAAAApjaGVja0Fzc2V0BQAAAApjaGVja0Fzc2V0BAAAAAtjaGVja0hlaWdodAMJAABmAAAAAgUAAAAJZW5kSGVpZ2h0BQAAAAZoZWlnaHQGCQAAAgAAAAECAAAANEN1cnJlbnQgdm90aW5nIGlzIG92ZXIgYnV0IHJlc3VsdHMgYXJlIG5vdCBmaW5hbGl6ZWQDCQAAAAAAAAIFAAAAC2NoZWNrSGVpZ2h0BQAAAAtjaGVja0hlaWdodAQAAAALdXNlckFkZHJlc3MJAAQlAAAAAQgFAAAAAWkAAAAGY2FsbGVyBAAAAA5nd3hBbW91bnRBdEVuZAkBAAAAGGdldFVzZXJHd3hBbW91bnRBdEhlaWdodAAAAAIFAAAAC3VzZXJBZGRyZXNzBQAAAAllbmRIZWlnaHQEAAAAE2NoZWNrR3d4QW1vdW50QXRFbmQDCQAAZgAAAAIFAAAADmd3eEFtb3VudEF0RW5kAAAAAAAAAAAABgkAAAIAAAABAgAAAChZb3UnbGwgbm90IGhhdmUgZ1dYIGF0IHRoZSBlbmQgb2Ygdm90aW5nAwkAAAAAAAACBQAAABNjaGVja0d3eEFtb3VudEF0RW5kBQAAABNjaGVja0d3eEFtb3VudEF0RW5kBAAAAA12b3Rlc0xpc3ROYW1lCQEAAAAQZ2V0Vm90ZXNMaXN0TmFtZQAAAAEFAAAAB2Fzc2V0SWQEAAAAC3VzZXJWb3RlS2V5CQEAAAATa2V5VXNlclZvdGVCeVBlcmlvZAAAAAMFAAAAC3VzZXJBZGRyZXNzBQAAAAdhc3NldElkBQAAAA1jdXJyZW50UGVyaW9kBAAAAA91c2VyVm90ZUFjdGlvbnMJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAALdXNlclZvdGVLZXkJAQAAAA5mb3JtYXRVc2VyVm90ZQAAAAIFAAAADmd3eEFtb3VudEF0RW5kBQAAAAdpbkZhdm9yBQAAAANuaWwEAAAAEHZvdGVzTGlzdEFjdGlvbnMDCQEAAAAMY29udGFpbnNOb2RlAAAAAgUAAAANdm90ZXNMaXN0TmFtZQUAAAALdXNlckFkZHJlc3MFAAAAA25pbAkBAAAACmluc2VydE5vZGUAAAACBQAAAA12b3Rlc0xpc3ROYW1lBQAAAAt1c2VyQWRkcmVzcwkABRQAAAACCQAETgAAAAIFAAAAEHZvdGVzTGlzdEFjdGlvbnMFAAAAD3VzZXJWb3RlQWN0aW9ucwUAAAAEdW5pdAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgAAAAFpAQAAAApjYW5jZWxWb3RlAAAAAQAAAAdhc3NldElkBAAAAAt1c2VyQWRkcmVzcwkABCUAAAABCAUAAAABaQAAAAZjYWxsZXIEAAAADXZvdGVzTGlzdE5hbWUJAQAAABBnZXRWb3Rlc0xpc3ROYW1lAAAAAQUAAAAHYXNzZXRJZAQAAAALdXNlclZvdGVLZXkJAQAAABNrZXlVc2VyVm90ZUJ5UGVyaW9kAAAAAwUAAAALdXNlckFkZHJlc3MFAAAAB2Fzc2V0SWQFAAAADWN1cnJlbnRQZXJpb2QEAAAADnVzZXJWb3RlT3JVbml0CQAEIgAAAAEFAAAAC3VzZXJWb3RlS2V5BAAAAAljaGVja1ZvdGUJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQiAAAAAQUAAAALdXNlclZvdGVLZXkCAAAAEU5vdGhpbmcgdG8gY2FuY2VsAwkAAAAAAAACBQAAAAljaGVja1ZvdGUFAAAACWNoZWNrVm90ZQQAAAAQdm90ZXNMaXN0QWN0aW9ucwkBAAAACmRlbGV0ZU5vZGUAAAACBQAAAA12b3Rlc0xpc3ROYW1lBQAAAAt1c2VyQWRkcmVzcwQAAAAPdXNlclZvdGVBY3Rpb25zCQAETAAAAAIJAQAAAAtEZWxldGVFbnRyeQAAAAEFAAAAC3VzZXJWb3RlS2V5BQAAAANuaWwJAAUUAAAAAgkABE4AAAACBQAAABB2b3Rlc0xpc3RBY3Rpb25zBQAAAA91c2VyVm90ZUFjdGlvbnMFAAAABHVuaXQJAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAAAAAWkBAAAAFGZpbmFsaXplVm90aW5nSGVscGVyAAAAAAQAAAAJZW5kSGVpZ2h0CQAAZAAAAAIFAAAAC3N0YXJ0SGVpZ2h0BQAAAA52b3RpbmdEdXJhdGlvbgMJAABmAAAAAgUAAAAJZW5kSGVpZ2h0BQAAAAZoZWlnaHQJAAUUAAAAAgUAAAADbmlsBwQAAAAabGF0ZXN0UHJvY2Vzc2VkQXNzZXRPclVuaXQJAAQiAAAAAQUAAAAXa2V5TGF0ZXN0UHJvY2Vzc2VkQXNzZXQEAAAAGWxhdGVzdFByb2Nlc3NlZFVzZXJPclVuaXQJAAQiAAAAAQUAAAAWa2V5TGF0ZXN0UHJvY2Vzc2VkVXNlcgQAAAAPbmV4dFBlcmlvZERlbGF5AAAAAAAAAAABBAAAAAZmaW5pc2gJAAUUAAAAAgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAOa2V5U3RhcnRIZWlnaHQJAABkAAAAAgUAAAAGaGVpZ2h0BQAAAA9uZXh0UGVyaW9kRGVsYXkJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAEGtleUN1cnJlbnRQZXJpb2QJAABkAAAAAgUAAAANY3VycmVudFBlcmlvZAAAAAAAAAAAAQkABEwAAAACCQEAAAALRGVsZXRlRW50cnkAAAABBQAAABdrZXlMYXRlc3RQcm9jZXNzZWRBc3NldAkABEwAAAACCQEAAAALRGVsZXRlRW50cnkAAAABBQAAABZrZXlMYXRlc3RQcm9jZXNzZWRVc2VyBQAAAANuaWwGAwkAAAAAAAACBQAAABpsYXRlc3RQcm9jZXNzZWRBc3NldE9yVW5pdAUAAAAEdW5pdAQAAAAQYXNzZXRzSGVhZE9yVW5pdAkABCIAAAABCQEAAAALa2V5TGlzdEhlYWQAAAABBQAAAA5hc3NldHNMaXN0TmFtZQMJAAAAAAAAAgUAAAAQYXNzZXRzSGVhZE9yVW5pdAUAAAAEdW5pdAUAAAAGZmluaXNoBAAAAAVhc3NldAkBAAAABXZhbHVlAAAAAQUAAAAQYXNzZXRzSGVhZE9yVW5pdAQAAAARdXNlckFkZHJlc3NPclVuaXQJAAQiAAAAAQkBAAAAC2tleUxpc3RIZWFkAAAAAQkBAAAAEGdldFZvdGVzTGlzdE5hbWUAAAABBQAAAAVhc3NldAQAAAAScHJvY2Vzc1ZvdGVBY3Rpb25zCQEAAAALcHJvY2Vzc1ZvdGUAAAACBQAAAAVhc3NldAUAAAARdXNlckFkZHJlc3NPclVuaXQJAAUUAAAAAgUAAAAScHJvY2Vzc1ZvdGVBY3Rpb25zBgQAAAAUbGF0ZXN0UHJvY2Vzc2VkQXNzZXQJAQAAAAV2YWx1ZQAAAAEFAAAAGmxhdGVzdFByb2Nlc3NlZEFzc2V0T3JVbml0AwkAAAAAAAACBQAAABlsYXRlc3RQcm9jZXNzZWRVc2VyT3JVbml0BQAAAAR1bml0BAAAAAthc3NldE9yVW5pdAkABCIAAAABCQEAAAALa2V5TGlzdE5leHQAAAACBQAAAA5hc3NldHNMaXN0TmFtZQUAAAAUbGF0ZXN0UHJvY2Vzc2VkQXNzZXQDCQAAAAAAAAIFAAAAC2Fzc2V0T3JVbml0BQAAAAR1bml0BQAAAAZmaW5pc2gEAAAABWFzc2V0CQEAAAAFdmFsdWUAAAABBQAAAAthc3NldE9yVW5pdAQAAAARdXNlckFkZHJlc3NPclVuaXQJAAQiAAAAAQkBAAAAC2tleUxpc3RIZWFkAAAAAQkBAAAAEGdldFZvdGVzTGlzdE5hbWUAAAABBQAAAAVhc3NldAQAAAAScHJvY2Vzc1ZvdGVBY3Rpb25zCQEAAAALcHJvY2Vzc1ZvdGUAAAACBQAAAAVhc3NldAUAAAARdXNlckFkZHJlc3NPclVuaXQJAAUUAAAAAgUAAAAScHJvY2Vzc1ZvdGVBY3Rpb25zBgQAAAATbGF0ZXN0UHJvY2Vzc2VkVXNlcgkBAAAABXZhbHVlAAAAAQUAAAAZbGF0ZXN0UHJvY2Vzc2VkVXNlck9yVW5pdAQAAAARdXNlckFkZHJlc3NPclVuaXQJAAQiAAAAAQkBAAAAC2tleUxpc3ROZXh0AAAAAgkBAAAAEGdldFZvdGVzTGlzdE5hbWUAAAABBQAAABRsYXRlc3RQcm9jZXNzZWRBc3NldAUAAAATbGF0ZXN0UHJvY2Vzc2VkVXNlcgQAAAAScHJvY2Vzc1ZvdGVBY3Rpb25zCQEAAAALcHJvY2Vzc1ZvdGUAAAACBQAAABRsYXRlc3RQcm9jZXNzZWRBc3NldAUAAAARdXNlckFkZHJlc3NPclVuaXQJAAUUAAAAAgUAAAAScHJvY2Vzc1ZvdGVBY3Rpb25zBgAAAAFpAQAAABVmaW5hbGl6ZVZvdGluZ1dyYXBwZXIAAAABAAAAB2NvdW50ZXIEAAAABnJlc3VsdAkBAAAABmFzQm9vbAAAAAEJAAP8AAAABAUAAAAEdGhpcwIAAAAUZmluYWxpemVWb3RpbmdIZWxwZXIFAAAAA25pbAUAAAADbmlsAwkAAAAAAAACBQAAAAZyZXN1bHQFAAAABnJlc3VsdAMJAQAAAAEhAAAAAQUAAAAGcmVzdWx0AwkAAAAAAAACBQAAAAdjb3VudGVyAAAAAAAAAAAACQAAAgAAAAECAAAAHkN1cnJlbnQgdm90aW5nIGlzIG5vdCBvdmVyIHlldAkABRQAAAACBQAAAANuaWwFAAAABHVuaXQDCQAAZgAAAAIFAAAACG1heERlcHRoBQAAAAdjb3VudGVyBAAAAANpbnYJAAP8AAAABAUAAAAEdGhpcwIAAAAVZmluYWxpemVWb3RpbmdXcmFwcGVyCQAETAAAAAIJAABkAAAAAgUAAAAHY291bnRlcgAAAAAAAAAAAQUAAAADbmlsBQAAAANuaWwDCQAAAAAAAAIFAAAAA2ludgUAAAADaW52CQAFFAAAAAIFAAAAA25pbAUAAAAEdW5pdAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAUUAAAAAgUAAAADbmlsBQAAAAR1bml0CQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgAAAAFpAQAAAA5maW5hbGl6ZVZvdGluZwAAAAAEAAAAA2ludgkAA/wAAAAEBQAAAAR0aGlzAgAAABVmaW5hbGl6ZVZvdGluZ1dyYXBwZXIJAARMAAAAAgAAAAAAAAAAAAUAAAADbmlsBQAAAANuaWwDCQAAAAAAAAIFAAAAA2ludgUAAAADaW52CQAFFAAAAAIFAAAAA25pbAUAAAAEdW5pdAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAABaQEAAAASc2V0Vm90aW5nVGhyZXNob2xkAAAAAQAAAAxuZXdUaHJlc2hvbGQEAAAAC2NoZWNrQ2FsbGVyCQEAAAAIdGhpc09ubHkAAAABBQAAAAFpAwkAAAAAAAACBQAAAAtjaGVja0NhbGxlcgUAAAALY2hlY2tDYWxsZXIJAAUUAAAAAgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAASa2V5Vm90aW5nVGhyZXNob2xkBQAAAAxuZXdUaHJlc2hvbGQFAAAAA25pbAUAAAAEdW5pdAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAABaQEAAAAGc2V0RmVlAAAAAQAAAAZuZXdGZWUEAAAAC2NoZWNrQ2FsbGVyCQEAAAAIdGhpc09ubHkAAAABBQAAAAFpAwkAAAAAAAACBQAAAAtjaGVja0NhbGxlcgUAAAALY2hlY2tDYWxsZXIJAAUUAAAAAgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAMa2V5RmVlQW1vdW50BQAAAAZuZXdGZWUFAAAAA25pbAUAAAAEdW5pdAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAABaQEAAAAbZ3d4QXZhaWxhYmxlRm9yVm90ZVJFQURPTkxZAAAAAQAAAAt1c2VyQWRkcmVzcwQAAAAJZW5kSGVpZ2h0CQAAZAAAAAIFAAAAC3N0YXJ0SGVpZ2h0BQAAAA52b3RpbmdEdXJhdGlvbgQAAAAOZ3d4QW1vdW50QXRFbmQJAQAAABhnZXRVc2VyR3d4QW1vdW50QXRIZWlnaHQAAAACBQAAAAt1c2VyQWRkcmVzcwUAAAAJZW5kSGVpZ2h0CQAFFAAAAAIFAAAAA25pbAUAAAAOZ3d4QW1vdW50QXRFbmQAAAAA0oS56w==", "chainId": 84, "height": 1967783, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: none Next: BiMcxpkBxj32odU7ZDcrbhGejP69LWiLp9iX8FHS1JGE Full:
Old | New | Differences | |
---|---|---|---|
1 | - | # no script | |
1 | + | {-# STDLIB_VERSION 5 #-} | |
2 | + | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | + | {-# CONTENT_TYPE DAPP #-} | |
4 | + | let separator = "__" | |
5 | + | ||
6 | + | let maxDepth = 10 | |
7 | + | ||
8 | + | func asInt (val) = match val { | |
9 | + | case valInt: Int => | |
10 | + | valInt | |
11 | + | case _ => | |
12 | + | throw("Failed to cast into Integer") | |
13 | + | } | |
14 | + | ||
15 | + | ||
16 | + | func asBool (val) = match val { | |
17 | + | case valBool: Boolean => | |
18 | + | valBool | |
19 | + | case _ => | |
20 | + | throw("Failed to cast into Boolean") | |
21 | + | } | |
22 | + | ||
23 | + | ||
24 | + | let keyFeeAmount = makeString(["%s", "fee"], separator) | |
25 | + | ||
26 | + | let keyWxAssetId = makeString(["%s", "wxAssetId"], separator) | |
27 | + | ||
28 | + | let keyVotingThreshold = makeString(["%s", "votingThreshold"], separator) | |
29 | + | ||
30 | + | let keyVotingDuration = makeString(["%s", "epochLength"], separator) | |
31 | + | ||
32 | + | let keyVoteBeforeElimination = makeString(["%s", "voteBeforeElimination"], separator) | |
33 | + | ||
34 | + | let keyStartHeight = makeString(["%s", "currentVotingHeightStart"], separator) | |
35 | + | ||
36 | + | let keyCurrentPeriod = makeString(["%s", "currentEpoch"], separator) | |
37 | + | ||
38 | + | let keyBoostingContract = makeString(["%s", "boostingContract"], separator) | |
39 | + | ||
40 | + | let keyEmissionContract = makeString(["%s", "emissionContract"], separator) | |
41 | + | ||
42 | + | let keyLatestProcessedAsset = makeString(["%s", "latestProcessedAsset"], separator) | |
43 | + | ||
44 | + | let keyLatestProcessedUser = makeString(["%s", "latestProcessedUser"], separator) | |
45 | + | ||
46 | + | func keyAssetImage (assetId) = makeString(["%s", "assetImage"], separator) | |
47 | + | ||
48 | + | ||
49 | + | let assetsListName = "__assets" | |
50 | + | ||
51 | + | func getVotesListName (assetId) = ("%s__votes__" + assetId) | |
52 | + | ||
53 | + | ||
54 | + | func keyListHead (listName) = makeString([("%s%s" + listName), "head"], separator) | |
55 | + | ||
56 | + | ||
57 | + | func keyListSize (listName) = makeString([("%s%s" + listName), "size"], separator) | |
58 | + | ||
59 | + | ||
60 | + | func keyListPrev (listName,id) = makeString([("%s%s%s" + listName), id, "prev"], separator) | |
61 | + | ||
62 | + | ||
63 | + | func keyListNext (listName,id) = makeString([("%s%s%s" + listName), id, "next"], separator) | |
64 | + | ||
65 | + | ||
66 | + | func keyIntermediateVoteResultByPeriod (assetId,period) = makeString(["%s%d%s%s", "votingResultAt", toString(period), assetId], separator) | |
67 | + | ||
68 | + | ||
69 | + | func formatIntermediateVoteResult (totalYes,totalNo) = makeString(["%d%d", toString(totalYes), toString(totalNo)], separator) | |
70 | + | ||
71 | + | ||
72 | + | func parseIntermediateVoteResult (input) = { | |
73 | + | let parts = split(input, separator) | |
74 | + | let totalYesIdx = 1 | |
75 | + | let totalNoIdx = 2 | |
76 | + | let totalYes = parseIntValue(parts[totalYesIdx]) | |
77 | + | let totalNo = parseIntValue(parts[totalNoIdx]) | |
78 | + | $Tuple2(totalYes, totalNo) | |
79 | + | } | |
80 | + | ||
81 | + | ||
82 | + | func keyUserVoteByPeriod (userAddress,assetId,period) = makeString(["%s%d%s%s", "vru", toString(period), assetId, userAddress], separator) | |
83 | + | ||
84 | + | ||
85 | + | func formatUserVote (total,inFavor) = { | |
86 | + | let totalYes = if (inFavor) | |
87 | + | then total | |
88 | + | else 0 | |
89 | + | let totalNo = if (inFavor) | |
90 | + | then 0 | |
91 | + | else total | |
92 | + | makeString(["%d%d", toString(totalYes), toString(totalNo)], separator) | |
93 | + | } | |
94 | + | ||
95 | + | ||
96 | + | func parseUserVote (input) = { | |
97 | + | let parts = split(input, separator) | |
98 | + | let totalYesIdx = 1 | |
99 | + | let totalNoIdx = 2 | |
100 | + | let totalYes = parseIntValue(parts[totalYesIdx]) | |
101 | + | let totalNo = parseIntValue(parts[totalNoIdx]) | |
102 | + | let inFavor = if ((totalYes > 0)) | |
103 | + | then (totalNo == 0) | |
104 | + | else false | |
105 | + | let against = if ((totalYes == 0)) | |
106 | + | then (totalNo > 0) | |
107 | + | else false | |
108 | + | let checkTotals = if (if (inFavor) | |
109 | + | then true | |
110 | + | else against) | |
111 | + | then true | |
112 | + | else throw("Invalid user vote value") | |
113 | + | if ((checkTotals == checkTotals)) | |
114 | + | then { | |
115 | + | let total = if (inFavor) | |
116 | + | then totalYes | |
117 | + | else totalNo | |
118 | + | $Tuple2(total, inFavor) | |
119 | + | } | |
120 | + | else throw("Strict value is not equal to itself.") | |
121 | + | } | |
122 | + | ||
123 | + | ||
124 | + | func thisOnly (i) = if ((i.caller == this)) | |
125 | + | then true | |
126 | + | else throw("Permission denied") | |
127 | + | ||
128 | + | ||
129 | + | func getIntegerOrZero (key) = valueOrElse(getInteger(this, key), 0) | |
130 | + | ||
131 | + | ||
132 | + | func getIntegerOrFail (key) = valueOrErrorMessage(getInteger(this, key), (key + " is not defined")) | |
133 | + | ||
134 | + | ||
135 | + | func getStringOrEmpty (key) = valueOrElse(getString(this, key), "") | |
136 | + | ||
137 | + | ||
138 | + | func getStringOrFail (key) = valueOrErrorMessage(getString(this, key), (key + " is not defined")) | |
139 | + | ||
140 | + | ||
141 | + | let feeAmount = getIntegerOrFail(keyFeeAmount) | |
142 | + | ||
143 | + | let wxAssetId = fromBase58String(getStringOrFail(keyWxAssetId)) | |
144 | + | ||
145 | + | let votingThreshold = getIntegerOrFail(keyVotingThreshold) | |
146 | + | ||
147 | + | let votingDuration = getIntegerOrFail(keyVotingDuration) | |
148 | + | ||
149 | + | let voteBeforeElimination = getIntegerOrFail(keyVoteBeforeElimination) | |
150 | + | ||
151 | + | let startHeight = getIntegerOrFail(keyStartHeight) | |
152 | + | ||
153 | + | let currentPeriod = getIntegerOrFail(keyCurrentPeriod) | |
154 | + | ||
155 | + | let boostingContract = addressFromStringValue(getStringOrFail(keyBoostingContract)) | |
156 | + | ||
157 | + | let emissionContract = addressFromStringValue(getStringOrFail(keyEmissionContract)) | |
158 | + | ||
159 | + | func getUserGwxAmountAtHeight (userAddress,targetHeight) = { | |
160 | + | let gwxAmount = invoke(boostingContract, "getUserGwxAmountAtHeightREADONLY", [userAddress, targetHeight], nil) | |
161 | + | asInt(gwxAmount) | |
162 | + | } | |
163 | + | ||
164 | + | ||
165 | + | func containsNode (listName,id) = { | |
166 | + | let head = getString(this, keyListHead(listName)) | |
167 | + | let prev = getString(this, keyListPrev(listName, id)) | |
168 | + | let next = getString(this, keyListNext(listName, id)) | |
169 | + | if (if ((id == head)) | |
170 | + | then true | |
171 | + | else (prev != unit)) | |
172 | + | then true | |
173 | + | else (next != unit) | |
174 | + | } | |
175 | + | ||
176 | + | ||
177 | + | func insertNode (listName,id) = { | |
178 | + | let head = getString(this, keyListHead(listName)) | |
179 | + | let listSize = valueOrElse(getInteger(this, keyListSize(listName)), 0) | |
180 | + | let checkNode = if (!(containsNode(listName, id))) | |
181 | + | then true | |
182 | + | else throw("Node exists") | |
183 | + | if ((checkNode == checkNode)) | |
184 | + | then (([IntegerEntry(keyListSize(listName), (listSize + 1))] ++ (if (isDefined(head)) | |
185 | + | then [StringEntry(keyListNext(listName, id), value(head)), StringEntry(keyListPrev(listName, value(head)), id)] | |
186 | + | else nil)) ++ [StringEntry(keyListHead(listName), id)]) | |
187 | + | else throw("Strict value is not equal to itself.") | |
188 | + | } | |
189 | + | ||
190 | + | ||
191 | + | func deleteNode (listName,id) = { | |
192 | + | let head = getString(this, keyListHead(listName)) | |
193 | + | let listSize = valueOrElse(getInteger(this, keyListSize(listName)), 0) | |
194 | + | let prev = getString(this, keyListPrev(listName, id)) | |
195 | + | let next = getString(this, keyListNext(listName, id)) | |
196 | + | ([IntegerEntry(keyListSize(listName), (listSize - 1))] ++ (if (if (isDefined(prev)) | |
197 | + | then isDefined(next) | |
198 | + | else false) | |
199 | + | then [StringEntry(keyListNext(listName, value(prev)), value(next)), StringEntry(keyListPrev(listName, value(next)), value(prev)), DeleteEntry(keyListPrev(listName, id)), DeleteEntry(keyListNext(listName, id))] | |
200 | + | else if (isDefined(next)) | |
201 | + | then [StringEntry(keyListHead(listName), value(next)), DeleteEntry(keyListNext(listName, id)), DeleteEntry(keyListPrev(listName, value(next)))] | |
202 | + | else if (isDefined(prev)) | |
203 | + | then [DeleteEntry(keyListPrev(listName, id)), DeleteEntry(keyListNext(listName, value(prev)))] | |
204 | + | else if ((id == head)) | |
205 | + | then [DeleteEntry(keyListHead(listName))] | |
206 | + | else throw("Invalid node"))) | |
207 | + | } | |
208 | + | ||
209 | + | ||
210 | + | func processVote (assetId,userAddressOrUnit) = { | |
211 | + | let updateLatestProcessedAssetAction = StringEntry(keyLatestProcessedAsset, assetId) | |
212 | + | let deleteLatestProcessedUserAction = DeleteEntry(keyLatestProcessedUser) | |
213 | + | if ((userAddressOrUnit == unit)) | |
214 | + | then [updateLatestProcessedAssetAction, deleteLatestProcessedUserAction] | |
215 | + | else { | |
216 | + | let endHeight = (startHeight + votingDuration) | |
217 | + | let userAddress = value(userAddressOrUnit) | |
218 | + | let updateLatestProcessedUserAction = StringEntry(keyLatestProcessedUser, userAddress) | |
219 | + | let userVoteKey = keyUserVoteByPeriod(userAddress, assetId, currentPeriod) | |
220 | + | let userVoteOrUnit = getString(userVoteKey) | |
221 | + | let userGwxAmountAtEndHeight = getUserGwxAmountAtHeight(userAddress, endHeight) | |
222 | + | let voteActions = if ((userGwxAmountAtEndHeight == 0)) | |
223 | + | then { | |
224 | + | let votesListName = getVotesListName(assetId) | |
225 | + | deleteNode(votesListName, userAddress) | |
226 | + | } | |
227 | + | else { | |
228 | + | let intermediateVoteResultKey = keyIntermediateVoteResultByPeriod(assetId, currentPeriod) | |
229 | + | let $t077647932 = match getString(intermediateVoteResultKey) { | |
230 | + | case s: String => | |
231 | + | parseIntermediateVoteResult(s) | |
232 | + | case _: Unit => | |
233 | + | $Tuple2(0, 0) | |
234 | + | case _ => | |
235 | + | throw("Match error") | |
236 | + | } | |
237 | + | let totalYes = $t077647932._1 | |
238 | + | let totalNo = $t077647932._2 | |
239 | + | func getIntermediateVoteResultAction (totalYes,totalNo,total,inFavor) = StringEntry(intermediateVoteResultKey, formatIntermediateVoteResult((totalYes + (if (inFavor) | |
240 | + | then total | |
241 | + | else 0)), (totalNo + (if (inFavor) | |
242 | + | then 0 | |
243 | + | else total)))) | |
244 | + | ||
245 | + | if ((userVoteOrUnit == unit)) | |
246 | + | then { | |
247 | + | let userPreviousVoteOrUnit = getString(keyUserVoteByPeriod(userAddress, assetId, (currentPeriod - 1))) | |
248 | + | if ((userPreviousVoteOrUnit == unit)) | |
249 | + | then nil | |
250 | + | else { | |
251 | + | let $t085758648 = parseUserVote(value(userPreviousVoteOrUnit)) | |
252 | + | let prevTotal = $t085758648._1 | |
253 | + | let inFavor = $t085758648._2 | |
254 | + | let total = min([prevTotal, userGwxAmountAtEndHeight]) | |
255 | + | [StringEntry(userVoteKey, formatUserVote(total, inFavor)), getIntermediateVoteResultAction(totalYes, totalNo, total, inFavor)] | |
256 | + | } | |
257 | + | } | |
258 | + | else { | |
259 | + | let $t089198980 = parseUserVote(value(userVoteOrUnit)) | |
260 | + | let total = $t089198980._1 | |
261 | + | let inFavor = $t089198980._2 | |
262 | + | [getIntermediateVoteResultAction(totalYes, totalNo, total, inFavor)] | |
263 | + | } | |
264 | + | } | |
265 | + | ((voteActions :+ updateLatestProcessedAssetAction) :+ updateLatestProcessedUserAction) | |
266 | + | } | |
267 | + | } | |
268 | + | ||
269 | + | ||
270 | + | @Callable(i) | |
271 | + | func constructor (boostingContractPrm,emissionContractPrm,feeAmountPrm,wxAssetIdPrm,votingThresholdPrm,votingDurationPrm,voteBeforeEliminationPrm,startHeightPrm) = { | |
272 | + | let checks = [thisOnly(i), if (isDefined(addressFromString(boostingContractPrm))) | |
273 | + | then true | |
274 | + | else throw("Invalid boosting contract address"), if (isDefined(addressFromString(emissionContractPrm))) | |
275 | + | then true | |
276 | + | else throw("Invalid emission contract address"), if ((feeAmountPrm >= 0)) | |
277 | + | then true | |
278 | + | else throw("Invalid fee amount"), if (isDefined(assetInfo(fromBase58String(wxAssetIdPrm)))) | |
279 | + | then true | |
280 | + | else throw("Invalid WX asset ID"), if ((votingThresholdPrm >= 0)) | |
281 | + | then true | |
282 | + | else throw("Invalid voting threshold"), if ((votingDurationPrm > 0)) | |
283 | + | then true | |
284 | + | else throw("Invalid voting duration"), if (((startHeightPrm + votingDurationPrm) > height)) | |
285 | + | then true | |
286 | + | else throw("Invalid start height")] | |
287 | + | if ((checks == checks)) | |
288 | + | then $Tuple2([StringEntry(keyBoostingContract, boostingContractPrm), StringEntry(keyEmissionContract, emissionContractPrm), IntegerEntry(keyFeeAmount, feeAmountPrm), StringEntry(keyWxAssetId, wxAssetIdPrm), IntegerEntry(keyVotingThreshold, votingThresholdPrm), IntegerEntry(keyVotingDuration, votingDurationPrm), IntegerEntry(keyVoteBeforeElimination, voteBeforeEliminationPrm), IntegerEntry(keyStartHeight, startHeightPrm), IntegerEntry(keyCurrentPeriod, 0)], unit) | |
289 | + | else throw("Strict value is not equal to itself.") | |
290 | + | } | |
291 | + | ||
292 | + | ||
293 | + | ||
294 | + | @Callable(i) | |
295 | + | func suggest (assetId,assetImage) = { | |
296 | + | let info = valueOrErrorMessage(assetInfo(fromBase58String(assetId)), "Invalid asset ID") | |
297 | + | let payment = value(i.payments[0]) | |
298 | + | let checks = [if ((info.issuer == i.caller)) | |
299 | + | then true | |
300 | + | else throw("Asset can only be suggested by its issuer"), if ((value(payment.assetId) == wxAssetId)) | |
301 | + | then true | |
302 | + | else throw("Invalid fee asset"), if ((payment.amount == feeAmount)) | |
303 | + | then true | |
304 | + | else throw("Invalid fee amount")] | |
305 | + | if ((checks == checks)) | |
306 | + | then { | |
307 | + | let burnFeeInv = invoke(emissionContract, "burn", nil, [AttachedPayment(payment.assetId, payment.amount)]) | |
308 | + | if ((burnFeeInv == burnFeeInv)) | |
309 | + | then { | |
310 | + | let addAssetActions = insertNode(assetsListName, assetId) | |
311 | + | $Tuple2((addAssetActions :+ StringEntry(keyAssetImage(assetId), assetImage)), unit) | |
312 | + | } | |
313 | + | else throw("Strict value is not equal to itself.") | |
314 | + | } | |
315 | + | else throw("Strict value is not equal to itself.") | |
316 | + | } | |
317 | + | ||
318 | + | ||
319 | + | ||
320 | + | @Callable(i) | |
321 | + | func vote (assetId,inFavor) = { | |
322 | + | let endHeight = (startHeight + votingDuration) | |
323 | + | let checkAsset = if (containsNode(assetsListName, assetId)) | |
324 | + | then true | |
325 | + | else throw("Invalid asset") | |
326 | + | if ((checkAsset == checkAsset)) | |
327 | + | then { | |
328 | + | let checkHeight = if ((endHeight > height)) | |
329 | + | then true | |
330 | + | else throw("Current voting is over but results are not finalized") | |
331 | + | if ((checkHeight == checkHeight)) | |
332 | + | then { | |
333 | + | let userAddress = toString(i.caller) | |
334 | + | let gwxAmountAtEnd = getUserGwxAmountAtHeight(userAddress, endHeight) | |
335 | + | let checkGwxAmountAtEnd = if ((gwxAmountAtEnd > 0)) | |
336 | + | then true | |
337 | + | else throw("You'll not have gWX at the end of voting") | |
338 | + | if ((checkGwxAmountAtEnd == checkGwxAmountAtEnd)) | |
339 | + | then { | |
340 | + | let votesListName = getVotesListName(assetId) | |
341 | + | let userVoteKey = keyUserVoteByPeriod(userAddress, assetId, currentPeriod) | |
342 | + | let userVoteActions = [StringEntry(userVoteKey, formatUserVote(gwxAmountAtEnd, inFavor))] | |
343 | + | let votesListActions = if (containsNode(votesListName, userAddress)) | |
344 | + | then nil | |
345 | + | else insertNode(votesListName, userAddress) | |
346 | + | $Tuple2((votesListActions ++ userVoteActions), unit) | |
347 | + | } | |
348 | + | else throw("Strict value is not equal to itself.") | |
349 | + | } | |
350 | + | else throw("Strict value is not equal to itself.") | |
351 | + | } | |
352 | + | else throw("Strict value is not equal to itself.") | |
353 | + | } | |
354 | + | ||
355 | + | ||
356 | + | ||
357 | + | @Callable(i) | |
358 | + | func cancelVote (assetId) = { | |
359 | + | let userAddress = toString(i.caller) | |
360 | + | let votesListName = getVotesListName(assetId) | |
361 | + | let userVoteKey = keyUserVoteByPeriod(userAddress, assetId, currentPeriod) | |
362 | + | let userVoteOrUnit = getString(userVoteKey) | |
363 | + | let checkVote = valueOrElse(getString(userVoteKey), "Nothing to cancel") | |
364 | + | if ((checkVote == checkVote)) | |
365 | + | then { | |
366 | + | let votesListActions = deleteNode(votesListName, userAddress) | |
367 | + | let userVoteActions = [DeleteEntry(userVoteKey)] | |
368 | + | $Tuple2((votesListActions ++ userVoteActions), unit) | |
369 | + | } | |
370 | + | else throw("Strict value is not equal to itself.") | |
371 | + | } | |
372 | + | ||
373 | + | ||
374 | + | ||
375 | + | @Callable(i) | |
376 | + | func finalizeVotingHelper () = { | |
377 | + | let endHeight = (startHeight + votingDuration) | |
378 | + | if ((endHeight > height)) | |
379 | + | then $Tuple2(nil, false) | |
380 | + | else { | |
381 | + | let latestProcessedAssetOrUnit = getString(keyLatestProcessedAsset) | |
382 | + | let latestProcessedUserOrUnit = getString(keyLatestProcessedUser) | |
383 | + | let nextPeriodDelay = 1 | |
384 | + | let finish = $Tuple2([IntegerEntry(keyStartHeight, (height + nextPeriodDelay)), IntegerEntry(keyCurrentPeriod, (currentPeriod + 1)), DeleteEntry(keyLatestProcessedAsset), DeleteEntry(keyLatestProcessedUser)], true) | |
385 | + | if ((latestProcessedAssetOrUnit == unit)) | |
386 | + | then { | |
387 | + | let assetsHeadOrUnit = getString(keyListHead(assetsListName)) | |
388 | + | if ((assetsHeadOrUnit == unit)) | |
389 | + | then finish | |
390 | + | else { | |
391 | + | let asset = value(assetsHeadOrUnit) | |
392 | + | let userAddressOrUnit = getString(keyListHead(getVotesListName(asset))) | |
393 | + | let processVoteActions = processVote(asset, userAddressOrUnit) | |
394 | + | $Tuple2(processVoteActions, true) | |
395 | + | } | |
396 | + | } | |
397 | + | else { | |
398 | + | let latestProcessedAsset = value(latestProcessedAssetOrUnit) | |
399 | + | if ((latestProcessedUserOrUnit == unit)) | |
400 | + | then { | |
401 | + | let assetOrUnit = getString(keyListNext(assetsListName, latestProcessedAsset)) | |
402 | + | if ((assetOrUnit == unit)) | |
403 | + | then finish | |
404 | + | else { | |
405 | + | let asset = value(assetOrUnit) | |
406 | + | let userAddressOrUnit = getString(keyListHead(getVotesListName(asset))) | |
407 | + | let processVoteActions = processVote(asset, userAddressOrUnit) | |
408 | + | $Tuple2(processVoteActions, true) | |
409 | + | } | |
410 | + | } | |
411 | + | else { | |
412 | + | let latestProcessedUser = value(latestProcessedUserOrUnit) | |
413 | + | let userAddressOrUnit = getString(keyListNext(getVotesListName(latestProcessedAsset), latestProcessedUser)) | |
414 | + | let processVoteActions = processVote(latestProcessedAsset, userAddressOrUnit) | |
415 | + | $Tuple2(processVoteActions, true) | |
416 | + | } | |
417 | + | } | |
418 | + | } | |
419 | + | } | |
420 | + | ||
421 | + | ||
422 | + | ||
423 | + | @Callable(i) | |
424 | + | func finalizeVotingWrapper (counter) = { | |
425 | + | let result = asBool(invoke(this, "finalizeVotingHelper", nil, nil)) | |
426 | + | if ((result == result)) | |
427 | + | then if (!(result)) | |
428 | + | then if ((counter == 0)) | |
429 | + | then throw("Current voting is not over yet") | |
430 | + | else $Tuple2(nil, unit) | |
431 | + | else if ((maxDepth > counter)) | |
432 | + | then { | |
433 | + | let inv = invoke(this, "finalizeVotingWrapper", [(counter + 1)], nil) | |
434 | + | if ((inv == inv)) | |
435 | + | then $Tuple2(nil, unit) | |
436 | + | else throw("Strict value is not equal to itself.") | |
437 | + | } | |
438 | + | else $Tuple2(nil, unit) | |
439 | + | else throw("Strict value is not equal to itself.") | |
440 | + | } | |
441 | + | ||
442 | + | ||
443 | + | ||
444 | + | @Callable(i) | |
445 | + | func finalizeVoting () = { | |
446 | + | let inv = invoke(this, "finalizeVotingWrapper", [0], nil) | |
447 | + | if ((inv == inv)) | |
448 | + | then $Tuple2(nil, unit) | |
449 | + | else throw("Strict value is not equal to itself.") | |
450 | + | } | |
451 | + | ||
452 | + | ||
453 | + | ||
454 | + | @Callable(i) | |
455 | + | func setVotingThreshold (newThreshold) = { | |
456 | + | let checkCaller = thisOnly(i) | |
457 | + | if ((checkCaller == checkCaller)) | |
458 | + | then $Tuple2([IntegerEntry(keyVotingThreshold, newThreshold)], unit) | |
459 | + | else throw("Strict value is not equal to itself.") | |
460 | + | } | |
461 | + | ||
462 | + | ||
463 | + | ||
464 | + | @Callable(i) | |
465 | + | func setFee (newFee) = { | |
466 | + | let checkCaller = thisOnly(i) | |
467 | + | if ((checkCaller == checkCaller)) | |
468 | + | then $Tuple2([IntegerEntry(keyFeeAmount, newFee)], unit) | |
469 | + | else throw("Strict value is not equal to itself.") | |
470 | + | } | |
471 | + | ||
472 | + | ||
473 | + | ||
474 | + | @Callable(i) | |
475 | + | func gwxAvailableForVoteREADONLY (userAddress) = { | |
476 | + | let endHeight = (startHeight + votingDuration) | |
477 | + | let gwxAmountAtEnd = getUserGwxAmountAtHeight(userAddress, endHeight) | |
478 | + | $Tuple2(nil, gwxAmountAtEnd) | |
479 | + | } | |
480 | + | ||
481 | + |
github/deemru/w8io/c3f4982 28.28 ms ◑