tx · BiMcxpkBxj32odU7ZDcrbhGejP69LWiLp9iX8FHS1JGE

3MwFEMuNTRTZhZMw4WiGEtSfYiWqDMmrK7D:  -0.01400000 Waves

2022.03.21 15:03 [1973672] smart account 3MwFEMuNTRTZhZMw4WiGEtSfYiWqDMmrK7D > SELF 0.00000000 Waves

{ "type": 13, "id": "BiMcxpkBxj32odU7ZDcrbhGejP69LWiLp9iX8FHS1JGE", "fee": 1400000, "feeAssetId": null, "timestamp": 1647864192090, "version": 1, "sender": "3MwFEMuNTRTZhZMw4WiGEtSfYiWqDMmrK7D", "senderPublicKey": "BqyHrfDTfAgrmYrQ1WpsawT3NyagsKDi6KTuDTMLfCGL", "proofs": [ "3PfRb3uJ8uahHN2H9Gv7syDbV8TRcShP7nFEwDW1PpHTNot6NWSjxZ5zmhVsjVj63zfNyKjxrJ6N6dcGzYhrsX3w" ], "script": "base64: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cwYJAAACAAAAAQIAAAARUGVybWlzc2lvbiBkZW5pZWQBAAAAEGdldEludGVnZXJPclplcm8AAAABAAAAA2tleQkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAR0aGlzBQAAAANrZXkAAAAAAAAAAAABAAAAEGdldEludGVnZXJPckZhaWwAAAABAAAAA2tleQkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEGgAAAAIFAAAABHRoaXMFAAAAA2tleQkAASwAAAACBQAAAANrZXkCAAAADyBpcyBub3QgZGVmaW5lZAEAAAAQZ2V0U3RyaW5nT3JFbXB0eQAAAAEAAAADa2V5CQEAAAALdmFsdWVPckVsc2UAAAACCQAEHQAAAAIFAAAABHRoaXMFAAAAA2tleQIAAAAAAQAAAA9nZXRTdHJpbmdPckZhaWwAAAABAAAAA2tleQkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEHQAAAAIFAAAABHRoaXMFAAAAA2tleQkAASwAAAACBQAAAANrZXkCAAAADyBpcyBub3QgZGVmaW5lZAAAAAAJZmVlQW1vdW50CQEAAAAQZ2V0SW50ZWdlck9yRmFpbAAAAAEFAAAADGtleUZlZUFtb3VudAAAAAAJd3hBc3NldElkCQACWQAAAAEJAQAAAA9nZXRTdHJpbmdPckZhaWwAAAABBQAAAAxrZXlXeEFzc2V0SWQAAAAAD3ZvdGluZ1RocmVzaG9sZAkBAAAAEGdldEludGVnZXJPckZhaWwAAAABBQAAABJrZXlWb3RpbmdUaHJlc2hvbGQAAAAADnZvdGluZ0R1cmF0aW9uCQEAAAAQZ2V0SW50ZWdlck9yRmFpbAAAAAEFAAAAEWtleVZvdGluZ0R1cmF0aW9uAAAAABV2b3RlQmVmb3JlRWxpbWluYXRpb24JAQAAABBnZXRJbnRlZ2VyT3JGYWlsAAAAAQUAAAAYa2V5Vm90ZUJlZm9yZUVsaW1pbmF0aW9uAAAAAAtzdGFydEhlaWdodAkBAAAAEGdldEludGVnZXJPckZhaWwAAAABBQAAAA5rZXlTdGFydEhlaWdodAAAAAANY3VycmVudFBlcmlvZAkBAAAAEGdldEludGVnZXJPckZhaWwAAAABBQAAABBrZXlDdXJyZW50UGVyaW9kAAAAABBib29zdGluZ0NvbnRyYWN0CQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABCQEAAAAPZ2V0U3RyaW5nT3JGYWlsAAAAAQUAAAATa2V5Qm9vc3RpbmdDb250cmFjdAAAAAAQZW1pc3Npb25Db250cmFjdAkBAAAAEUBleHRyTmF0aXZlKDEwNjIpAAAAAQkBAAAAD2dldFN0cmluZ09yRmFpbAAAAAEFAAAAE2tleUVtaXNzaW9uQ29udHJhY3QAAAAAE2Fzc2V0c1N0b3JlQ29udHJhY3QJAQAAABFAZXh0ck5hdGl2ZSgxMDYyKQAAAAEJAQAAAA9nZXRTdHJpbmdPckZhaWwAAAABBQAAABZrZXlBc3NldHNTdG9yZUNvbnRyYWN0AQAAABhnZXRVc2VyR3d4QW1vdW50QXRIZWlnaHQAAAACAAAAC3VzZXJBZGRyZXNzAAAADHRhcmdldEhlaWdodAQAAAAJZ3d4QW1vdW50CQAD/AAAAAQFAAAAEGJvb3N0aW5nQ29udHJhY3QCAAAAIGdldFVzZXJHd3hBbW91bnRBdEhlaWdodFJFQURPTkxZCQAETAAAAAIFAAAAC3VzZXJBZGRyZXNzCQAETAAAAAIFAAAADHRhcmdldEhlaWdodAUAAAADbmlsBQAAAANuaWwJAQAAAAVhc0ludAAAAAEFAAAACWd3eEFtb3VudAEAAAAMY29udGFpbnNOb2RlAAAAAgAAAAhsaXN0TmFtZQAAAAJpZAQAAAAEaGVhZAkABB0AAAACBQAAAAR0aGlzCQEAAAALa2V5TGlzdEhlYWQAAAABBQAAAAhsaXN0TmFtZQQAAAAEcHJldgkABB0AAAACBQAAAAR0aGlzCQEAAAALa2V5TGlzdFByZXYAAAACBQAAAAhsaXN0TmFtZQUAAAACaWQEAAAABG5leHQJAAQdAAAAAgUAAAAEdGhpcwkBAAAAC2tleUxpc3ROZXh0AAAAAgUAAAAIbGlzdE5hbWUFAAAAAmlkAwMJAAAAAAAAAgUAAAACaWQFAAAABGhlYWQGCQEAAAACIT0AAAACBQAAAARwcmV2BQAAAAR1bml0BgkBAAAAAiE9AAAAAgUAAAAEbmV4dAUAAAAEdW5pdAEAAAAKaW5zZXJ0Tm9kZQAAAAIAAAAIbGlzdE5hbWUAAAAC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aXN0TmFtZQUAAAACaWQJAARMAAAAAgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQkBAAAAC2tleUxpc3RQcmV2AAAAAgUAAAAIbGlzdE5hbWUJAQAAAAV2YWx1ZQAAAAEFAAAABG5leHQFAAAAA25pbAMJAQAAAAlpc0RlZmluZWQAAAABBQAAAARwcmV2CQAETAAAAAIJAQAAAAtEZWxldGVFbnRyeQAAAAEJAQAAAAtrZXlMaXN0UHJldgAAAAIFAAAACGxpc3ROYW1lBQAAAAJpZAkABEwAAAACCQEAAAALRGVsZXRlRW50cnkAAAABCQEAAAALa2V5TGlzdE5leHQAAAACBQAAAAhsaXN0TmFtZQkBAAAABXZhbHVlAAAAAQUAAAAEcHJldgUAAAADbmlsAwkAAAAAAAACBQAAAAJpZAUAAAAEaGVhZAkABEwAAAACCQEAAAALRGVsZXRlRW50cnkAAAABCQEAAAALa2V5TGlzdEhlYWQAAAABBQAAAAhsaXN0TmFtZQUAAAADbmlsCQAAAgAAAAECAAAADEludmFsaWQgbm9kZQEAAAALcHJvY2Vzc1ZvdGUAAAACAAAAB2Fzc2V0SWQAAAARdXNlckFkZHJlc3NPclVuaXQEAAAAIHVwZGF0ZUxhdGVzdFByb2Nlc3NlZEFzc2V0QWN0aW9uCQEAAAALU3RyaW5nRW50cnkAAAACBQAAABdrZXlMYXRlc3RQcm9jZXNzZWRBc3NldAUAAAAHYXNzZXRJZAQAAAAfZGVsZXRlTGF0ZXN0UHJvY2Vzc2VkVXNlckFjdGlvbgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQUAAAAWa2V5TGF0ZXN0UHJvY2Vzc2VkVXNlcgMJAAAAAAAAAgUAAAARdXNlckFkZHJlc3NPclVuaXQFAAAABHVuaXQJAARMAAAAAgUAAAAgdXBkYXRlTGF0ZXN0UHJvY2Vzc2VkQXNzZXRBY3Rpb24JAARMAAAAAgUAAAAfZGVsZXRlTGF0ZXN0UHJvY2Vzc2VkVXNlckFjdGlvbgUAAAADbmlsBAAAAAllbmRIZWlnaHQJAABkAAAAAgUAAAALc3RhcnRIZWlnaHQFAAAADnZvdGluZ0R1cmF0aW9uBAAAAAt1c2VyQWRkcmVzcwkBAAAABXZhbHVlAAAAAQUAAAARdXNlckFkZHJlc3NPclVuaXQEAAAAH3VwZGF0ZUxhdGVzdFByb2Nlc3NlZFVzZXJBY3Rpb24JAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAAFmtleUxhdGVzdFByb2Nlc3NlZFVzZXIFAAAAC3VzZXJBZGRyZXNzBAAAAAt1c2VyVm90ZUtleQkBAAAAE2tleVVzZXJWb3RlQnlQZXJpb2QAAAADBQAAAAt1c2VyQWRkcmVzcwUAAAAHYXNzZXRJZAUAAAANY3VycmVudFBlcmlvZAQAAAAOdXNlclZvdGVPclVuaXQJAAQiAAAAAQUAAAALdXNlclZvdGVLZXkEAAAAGHVzZXJHd3hBbW91bnRBdEVuZEhlaWdodAkBAAAAGGdldFVzZXJHd3hBbW91bnRBdEhlaWdodAAAAAIFAAAAC3VzZXJBZGRyZXNzBQAAAAllbmRIZWlnaHQEAAAAC3ZvdGVBY3Rpb25zAwkAAAAAAAACBQAAABh1c2VyR3d4QW1vdW50QXRFbmRIZWlnaHQAAAAAAAAAAAAEAAAADXZvdGVzTGlzdE5hbWUJAQAAABBnZXRWb3Rlc0xpc3ROYW1lAAAAAQUAAAAHYXNzZXRJZAkBAAAACmRlbGV0ZU5vZGUAAAACBQAAAA12b3Rlc0xpc3ROYW1lBQAAAAt1c2VyQWRkcmVzcwQAAAANdm90ZVJlc3VsdEtleQkBAAAAFWtleVZvdGVSZXN1bHRCeVBlcmlvZAAAAAIFAAAAB2Fzc2V0SWQFAAAADWN1cnJlbnRQZXJpb2QEAAAACyR0MDgyNTQ4Mzk4BAAAAAckbWF0Y2gwCQAEIgAAAAEFAAAADXZvdGVSZXN1bHRLZXkDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAABlN0cmluZwQAAAABcwUAAAAHJG1hdGNoMAkBAAAAD3BhcnNlVm90ZVJlc3VsdAAAAAEFAAAAAXMDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAABFVuaXQJAAUUAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAkAAAIAAAABAgAAAAtNYXRjaCBlcnJvcgQAAAAIdG90YWxZZXMIBQAAAAskdDA4MjU0ODM5OAAAAAJfMQQAAAAHdG90YWxObwgFAAAACyR0MDgyNTQ4Mzk4AAAAAl8yCgEAAAATZ2V0Vm90ZVJlc3VsdEFjdGlvbgAAAAQAAAAIdG90YWxZZXMAAAAHdG90YWxObwAAAAV0b3RhbAAAAAdpbkZhdm9yCQEAAAALU3RyaW5nRW50cnkAAAACBQAAAA12b3RlUmVzdWx0S2V5CQEAAAAQZm9ybWF0Vm90ZVJlc3VsdAAAAAIJAABkAAAAAgUAAAAIdG90YWxZZXMDBQAAAAdpbkZhdm9yBQAAAAV0b3RhbAAAAAAAAAAAAAkAAGQAAAACBQAAAAd0b3RhbE5vAwUAAAAHaW5GYXZvcgAAAAAAAAAAAAUAAAAFdG90YWwDCQAAAAAAAAIFAAAADnVzZXJWb3RlT3JVbml0BQAAAAR1bml0BAAAABZ1c2VyUHJldmlvdXNWb3RlT3JVbml0CQAEIgAAAAEJAQAAABNrZXlVc2VyVm90ZUJ5UGVyaW9kAAAAAwUAAAALdXNlckFkZHJlc3MFAAAAB2Fzc2V0SWQJAABlAAAAAgUAAAANY3VycmVudFBlcmlvZAAAAAAAAAAAAQMJAAAAAAAAAgUAAAAWdXNlclByZXZpb3VzVm90ZU9yVW5pdAUAAAAEdW5pdAUAAAADbmlsBAAAAAskdDA5MDA1OTA3OAkBAAAADXBhcnNlVXNlclZvdGUAAAABCQEAAAAFdmFsdWUAAAABBQAAABZ1c2VyUHJldmlvdXNWb3RlT3JVbml0BAAAAAlwcmV2VG90YWwIBQAAAAskdDA5MDA1OTA3OAAAAAJfMQQAAAAHaW5GYXZvcggFAAAACyR0MDkwMDU5MDc4AAAAAl8yBAAAAAV0b3RhbAkAAZcAAAABCQAETAAAAAIFAAAACXByZXZUb3RhbAkABEwAAAACBQAAABh1c2VyR3d4QW1vdW50QXRFbmRIZWlnaHQFAAAAA25pbAkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAAAt1c2VyVm90ZUtleQkBAAAADmZvcm1hdFVzZXJWb3RlAAAAAgUAAAAFdG90YWwFAAAAB2luRmF2b3IJAARMAAAAAgkBAAAAE2dldFZvdGVSZXN1bHRBY3Rpb24AAAAEBQAAAAh0b3RhbFllcwUAAAAHdG90YWxObwUAAAAFdG90YWwFAAAAB2luRmF2b3IFAAAAA25pbAQAAAALJHQwOTMzNzkzOTgJAQAAAA1wYXJzZVVzZXJWb3RlAAAAAQkBAAAABXZhbHVlAAAAAQUAAAAOdXNlclZvdGVPclVuaXQEAAAABXRvdGFsCAUAAAALJHQwOTMzNzkzOTgAAAACXzEEAAAAB2luRmF2b3IIBQAAAAskdDA5MzM3OTM5OAAAAAJfMgkABEwAAAACCQEAAAATZ2V0Vm90ZVJlc3VsdEFjdGlvbgAAAAQFAAAACHRvdGFsWWVzBQAAAAd0b3RhbE5vBQAAAAV0b3RhbAUAAAAHaW5GYXZvcgUAAAADbmlsCQAETQAAAAIJAARNAAAAAgUAAAALdm90ZUFjdGlvbnMFAAAAIHVwZGF0ZUxhdGVzdFByb2Nlc3NlZEFzc2V0QWN0aW9uBQAAAB91cGRhdGVMYXRlc3RQcm9jZXNzZWRVc2VyQWN0aW9uAAAACwAAAAFpAQAAAAtjb25zdHJ1Y3RvcgAAAAkAAAATYm9vc3RpbmdDb250cmFjdFBybQAAABNlbWlzc2lvbkNvbnRyYWN0UHJtAAAAFmFzc2V0c1N0b3JlQ29udHJhY3RQcm0AAAAMZmVlQW1vdW50UHJtAAAADHd4QXNzZXRJZFBybQAAABJ2b3RpbmdUaHJlc2hvbGRQcm0AAAARdm90aW5nRHVyYXRpb25Qcm0AAAAYdm90ZUJlZm9yZUVsaW1pbmF0aW9uUHJtAAAADnN0YXJ0SGVpZ2h0UHJtBAAAAAZjaGVja3MJAARMAAAAAgkBAAAACHRoaXNPbmx5AAAAAQUAAAABaQkABEwAAAACAwkBAAAACWlzRGVmaW5lZAAAAAEJAAQmAAAAAQUAAAATYm9vc3RpbmdDb250cmFjdFBybQYJAAACAAAAAQIAAAAhSW52YWxpZCBib29zdGluZyBjb250cmFjdCBhZGRyZXNzCQAETAAAAAIDCQEAAAAJaXNEZWZpbmVkAAAAAQkABCYAAAABBQAAABNlbWlzc2lvbkNvbnRyYWN0UHJtBgkAAAIAAAABAgAAACFJbnZhbGlkIGVtaXNzaW9uIGNvbnRyYWN0IGFkZHJlc3MJAARMAAAAAgMJAQAAAAlpc0RlZmluZWQAAAABCQAEJgAAAAEFAAAAFmFzc2V0c1N0b3JlQ29udHJhY3RQcm0GCQAAAgAAAAECAAAAJEludmFsaWQgYXNzZXRfc3RvcmUgY29udHJhY3QgYWRkcmVzcwkABEwAAAACAwkAAGcAAAACBQAAAAxmZWVBbW91bnRQcm0AAAAAAAAAAAAGCQAAAgAAAAECAAAAEkludmFsaWQgZmVlIGFtb3VudAkABEwAAAACAwkBAAAACWlzRGVmaW5lZAAAAAEJAAPsAAAAAQkAAlkAAAABBQAAAAx3eEFzc2V0SWRQcm0GCQAAAgAAAAECAAAAE0ludmFsaWQgV1ggYXNzZXQgSUQJAARMAAAAAgMJAABnAAAAAgUAAAASdm90aW5nVGhyZXNob2xkUHJtAAAAAAAAAAAABgkAAAIAAAABAgAAABhJbnZhbGlkIHZvdGluZyB0aHJlc2hvbGQJAARMAAAAAgMJAABmAAAAAgUAAAARdm90aW5nRHVyYXRpb25Qcm0AAAAAAAAAAAAGCQAAAgAAAAECAAAAF0ludmFsaWQgdm90aW5nIGR1cmF0aW9uCQAETAAAAAIDCQAAZgAAAAIJAABkAAAAAgUAAAAOc3RhcnRIZWlnaHRQcm0FAAAAEXZvdGluZ0R1cmF0aW9uUHJtBQAAAAZoZWlnaHQGCQAAAgAAAAECAAAAFEludmFsaWQgc3RhcnQgaGVpZ2h0BQAAAANuaWwDCQAAAAAAAAIFAAAABmNoZWNrcwUAAAAGY2hlY2tzCQAFFAAAAAIJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAATa2V5Qm9vc3RpbmdDb250cmFjdAUAAAATYm9vc3RpbmdDb250cmFjdFBybQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAABNrZXlFbWlzc2lvbkNvbnRyYWN0BQAAABNlbWlzc2lvbkNvbnRyYWN0UHJtCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAAFmtleUFzc2V0c1N0b3JlQ29udHJhY3QFAAAAFmFzc2V0c1N0b3JlQ29udHJhY3RQcm0JAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAADGtleUZlZUFtb3VudAUAAAAMZmVlQW1vdW50UHJtCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAADGtleVd4QXNzZXRJZAUAAAAMd3hBc3NldElkUHJtCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABJrZXlWb3RpbmdUaHJlc2hvbGQFAAAAEnZvdGluZ1RocmVzaG9sZFBybQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAARa2V5Vm90aW5nRHVyYXRpb24FAAAAEXZvdGluZ0R1cmF0aW9uUHJtCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABhrZXlWb3RlQmVmb3JlRWxpbWluYXRpb24FAAAAGHZvdGVCZWZvcmVFbGltaW5hdGlvblBybQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAOa2V5U3RhcnRIZWlnaHQFAAAADnN0YXJ0SGVpZ2h0UHJtCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABBrZXlDdXJyZW50UGVyaW9kAAAAAAAAAAAABQAAAANuaWwFAAAABHVuaXQJAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAAAAAWkBAAAAB3N1Z2dlc3QAAAADAAAAB2Fzc2V0SWQAAAAGdGlja2VyAAAACmFzc2V0SW1hZ2UEAAAABGluZm8JAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkAA+wAAAABCQACWQAAAAEFAAAAB2Fzc2V0SWQCAAAAEEludmFsaWQgYXNzZXQgSUQEAAAAB3BheW1lbnQJAQAAAAV2YWx1ZQAAAAEJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAEAAAABmNoZWNrcwkABEwAAAACAwkAAAAAAAACCAUAAAAEaW5mbwAAAAZpc3N1ZXIIBQAAAAFpAAAABmNhbGxlcgYJAAACAAAAAQIAAAApQXNzZXQgY2FuIG9ubHkgYmUgc3VnZ2VzdGVkIGJ5IGl0cyBpc3N1ZXIJAARMAAAAAgMJAAAAAAAAAgkBAAAABXZhbHVlAAAAAQgFAAAAB3BheW1lbnQAAAAHYXNzZXRJZAUAAAAJd3hBc3NldElkBgkAAAIAAAABAgAAABFJbnZhbGlkIGZlZSBhc3NldAkABEwAAAACAwkAAAAAAAACCAUAAAAHcGF5bWVudAAAAAZhbW91bnQFAAAACWZlZUFtb3VudAYJAAACAAAAAQIAAAASSW52YWxpZCBmZWUgYW1vdW50BQAAAANuaWwDCQAAAAAAAAIFAAAABmNoZWNrcwUAAAAGY2hlY2tzBAAAABxhc3NldHNTdG9yZUNyZWF0ZU9yVXBkYXRlSW52CQAD/AAAAAQFAAAAE2Fzc2V0c1N0b3JlQ29udHJhY3QCAAAADmNyZWF0ZU9yVXBkYXRlCQAETAAAAAIFAAAAB2Fzc2V0SWQJAARMAAAAAgUAAAAGdGlja2VyCQAETAAAAAIFAAAACmFzc2V0SW1hZ2UJAARMAAAAAgcFAAAAA25pbAUAAAADbmlsAwkAAAAAAAACBQAAABxhc3NldHNTdG9yZUNyZWF0ZU9yVXBkYXRlSW52BQAAABxhc3NldHNTdG9yZUNyZWF0ZU9yVXBkYXRlSW52BAAAAApidXJuRmVlSW52CQAD/AAAAAQFAAAAEGVtaXNzaW9uQ29udHJhY3QCAAAABGJ1cm4FAAAAA25pbAkABEwAAAACCQEAAAAPQXR0YWNoZWRQYXltZW50AAAAAggFAAAAB3BheW1lbnQAAAAHYXNzZXRJZAgFAAAAB3BheW1lbnQAAAAGYW1vdW50BQAAAANuaWwDCQAAAAAAAAIFAAAACmJ1cm5GZWVJbnYFAAAACmJ1cm5GZWVJbnYEAAAAD2FkZEFzc2V0QWN0aW9ucwkBAAAACmluc2VydE5vZGUAAAACBQAAAA5hc3NldHNMaXN0TmFtZQUAAAAHYXNzZXRJZAkABRQAAAACCQAETQAAAAIFAAAAD2FkZEFzc2V0QWN0aW9ucwkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAADWtleUFzc2V0SW1hZ2UAAAABBQAAAAdhc3NldElkBQAAAAphc3NldEltYWdlBQAAAAR1bml0CQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAAAAAWkBAAAABHZvdGUAAAACAAAAB2Fzc2V0SWQAAAAHaW5GYXZvcgQAAAAJZW5kSGVpZ2h0CQAAZAAAAAIFAAAAC3N0YXJ0SGVpZ2h0BQAAAA52b3RpbmdEdXJhdGlvbgQAAAAKY2hlY2tBc3NldAMJAQAAAAxjb250YWluc05vZGUAAAACBQAAAA5hc3NldHNMaXN0TmFtZQUAAAAHYXNzZXRJZAYJAAACAAAAAQIAAAANSW52YWxpZCBhc3NldAMJAAAAAAAAAgUAAAAKY2hlY2tBc3NldAUAAAAKY2hlY2tBc3NldAQAAAALY2hlY2tIZWlnaHQDCQAAZgAAAAIFAAAACWVuZEhlaWdodAUAAAAGaGVpZ2h0BgkAAAIAAAABAgAAADRDdXJyZW50IHZvdGluZyBpcyBvdmVyIGJ1dCByZXN1bHRzIGFyZSBub3QgZmluYWxpemVkAwkAAAAAAAACBQAAAAtjaGVja0hlaWdodAUAAAALY2hlY2tIZWlnaHQEAAAAC3VzZXJBZGRyZXNzCQAEJQAAAAEIBQAAAAFpAAAABmNhbGxlcgQAAAAOZ3d4QW1vdW50QXRFbmQJAQAAABhnZXRVc2VyR3d4QW1vdW50QXRIZWlnaHQAAAACBQAAAAt1c2VyQWRkcmVzcwUAAAAJZW5kSGVpZ2h0BAAAABNjaGVja0d3eEFtb3VudEF0RW5kAwkAAGYAAAACBQAAAA5nd3hBbW91bnRBdEVuZAAAAAAAAAAAAAYJAAACAAAAAQIAAAAoWW91J2xsIG5vdCBoYXZlIGdXWCBhdCB0aGUgZW5kIG9mIHZvdGluZwMJAAAAAAAAAgUAAAATY2hlY2tHd3hBbW91bnRBdEVuZAUAAAATY2hlY2tHd3hBbW91bnRBdEVuZAQAAAANdm90ZXNMaXN0TmFtZQkBAAAAEGdldFZvdGVzTGlzdE5hbWUAAAABBQAAAAdhc3NldElkBAAAAAt1c2VyVm90ZUtleQkBAAAAE2tleVVzZXJWb3RlQnlQZXJpb2QAAAADBQAAAAt1c2VyQWRkcmVzcwUAAAAHYXNzZXRJZAUAAAANY3VycmVudFBlcmlvZAQAAAAPdXNlclZvdGVBY3Rpb25zCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAAC3VzZXJWb3RlS2V5CQEAAAAOZm9ybWF0VXNlclZvdGUAAAACBQAAAA5nd3hBbW91bnRBdEVuZAUAAAAHaW5GYXZvcgkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAASa2V5VXNlclZvdGVIaXN0b3J5AAAABQIAAAAEdm90ZQUAAAALdXNlckFkZHJlc3MFAAAAB2Fzc2V0SWQJAAJYAAAAAQgFAAAAAWkAAAANdHJhbnNhY3Rpb25JZAUAAAANY3VycmVudFBlcmlvZAkBAAAADmZvcm1hdFVzZXJWb3RlAAAAAgUAAAAOZ3d4QW1vdW50QXRFbmQFAAAAB2luRmF2b3IFAAAAA25pbAQAAAAQdm90ZXNMaXN0QWN0aW9ucwMJAQAAAAxjb250YWluc05vZGUAAAACBQAAAA12b3Rlc0xpc3ROYW1lBQAAAAt1c2VyQWRkcmVzcwUAAAADbmlsCQEAAAAKaW5zZXJ0Tm9kZQAAAAIFAAAADXZvdGVzTGlzdE5hbWUFAAAAC3VzZXJBZGRyZXNzCQAFFAAAAAIJAAROAAAAAgUAAAAQdm90ZXNMaXN0QWN0aW9ucwUAAAAPdXNlclZvdGVBY3Rpb25zBQAAAAR1bml0CQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAAAAAWkBAAAACmNhbmNlbFZvdGUAAAABAAAAB2Fzc2V0SWQEAAAAC3VzZXJBZGRyZXNzCQAEJQAAAAEIBQAAAAFpAAAABmNhbGxlcgQAAAANdm90ZXNMaXN0TmFtZQkBAAAAEGdldFZvdGVzTGlzdE5hbWUAAAABBQAAAAdhc3NldElkBAAAAAt1c2VyVm90ZUtleQkBAAAAE2tleVVzZXJWb3RlQnlQZXJpb2QAAAADBQAAAAt1c2VyQWRkcmVzcwUAAAAHYXNzZXRJZAUAAAANY3VycmVudFBlcmlvZAQAAAAOdXNlclZvdGVPclVuaXQJAAQiAAAAAQUAAAALdXNlclZvdGVLZXkEAAAACWNoZWNrVm90ZQkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABCIAAAABBQAAAAt1c2VyVm90ZUtleQIAAAARTm90aGluZyB0byBjYW5jZWwDCQAAAAAAAAIFAAAACWNoZWNrVm90ZQUAAAAJY2hlY2tWb3RlBAAAABB2b3Rlc0xpc3RBY3Rpb25zCQEAAAAKZGVsZXRlTm9kZQAAAAIFAAAADXZvdGVzTGlzdE5hbWUFAAAAC3VzZXJBZGRyZXNzBAAAAA91c2VyVm90ZUFjdGlvbnMJAARMAAAAAgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQUAAAALdXNlclZvdGVLZXkJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAEmtleVVzZXJWb3RlSGlzdG9yeQAAAAUCAAAACmNhbmNlbFZvdGUFAAAAC3VzZXJBZGRyZXNzBQAAAAdhc3NldElkCQACWAAAAAEIBQAAAAFpAAAADXRyYW5zYWN0aW9uSWQFAAAADWN1cnJlbnRQZXJpb2QJAQAAAA5mb3JtYXRVc2VyVm90ZQAAAAIAAAAAAAAAAAAGBQAAAANuaWwJAAUUAAAAAgkABE4AAAACBQAAABB2b3Rlc0xpc3RBY3Rpb25zBQAAAA91c2VyVm90ZUFjdGlvbnMFAAAABHVuaXQJAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAAAAAWkBAAAAFWZpbmFsaXplQXNzZXRJTlRFUk5BTAAAAAIAAAAHYXNzZXRJZAAAAAZwZXJpb2QEAAAAC2NoZWNrQ2FsbGVyCQEAAAAIdGhpc09ubHkAAAABBQAAAAFpAwkAAAAAAAACBQAAAAtjaGVja0NhbGxlcgUAAAALY2hlY2tDYWxsZXIEAAAADXZvdGVSZXN1bHRLZXkJAQAAABVrZXlWb3RlUmVzdWx0QnlQZXJpb2QAAAACBQAAAAdhc3NldElkBQAAAAZwZXJpb2QEAAAADSR0MDE0NDM1MTQ1NjcEAAAAByRtYXRjaDAJAAQiAAAAAQUAAAANdm90ZVJlc3VsdEtleQMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAGU3RyaW5nBAAAAAFzBQAAAAckbWF0Y2gwCQEAAAAPcGFyc2VWb3RlUmVzdWx0AAAAAQUAAAABcwMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAEVW5pdAkABRQAAAACAAAAAAAAAAAAAAAAAAAAAAAACQAAAgAAAAECAAAAC01hdGNoIGVycm9yBAAAAAh0b3RhbFllcwgFAAAADSR0MDE0NDM1MTQ1NjcAAAACXzEEAAAAB3RvdGFsTm8IBQAAAA0kdDAxNDQzNTE0NTY3AAAAAl8yBAAAAAV0b3RhbAkAAGQAAAACBQAAAAh0b3RhbFllcwUAAAAHdG90YWxObwQAAAAIdmVyaWZpZWQDCQAAZwAAAAIFAAAABXRvdGFsBQAAAA92b3RpbmdUaHJlc2hvbGQJAABmAAAAAgUAAAAIdG90YWxZZXMFAAAAB3RvdGFsTm8HBAAAABNhc3NldFZlcmlmaWVkQWN0aW9uCQEAAAAMQm9vbGVhbkVudHJ5AAAAAgkBAAAAGGtleUFzc2V0VmVyaWZpZWRCeVBlcmlvZAAAAAIFAAAAB2Fzc2V0SWQFAAAABnBlcmlvZAUAAAAIdmVyaWZpZWQEAAAAGWFzc2V0c1N0b3JlU2V0VmVyaWZpZWRJbnYJAAP8AAAABAUAAAATYXNzZXRzU3RvcmVDb250cmFjdAIAAAALc2V0VmVyaWZpZWQJAARMAAAAAgUAAAAHYXNzZXRJZAkABEwAAAACBQAAAAh2ZXJpZmllZAUAAAADbmlsBQAAAANuaWwDCQAAAAAAAAIFAAAAGWFzc2V0c1N0b3JlU2V0VmVyaWZpZWRJbnYFAAAAGWFzc2V0c1N0b3JlU2V0VmVyaWZpZWRJbnYJAAUUAAAAAgkABEwAAAACBQAAABNhc3NldFZlcmlmaWVkQWN0aW9uBQAAAANuaWwFAAAABHVuaXQJAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgAAAAFpAQAAABRmaW5hbGl6ZVZvdGluZ0hlbHBlcgAAAAAEAAAACWVuZEhlaWdodAkAAGQAAAACBQAAAAtzdGFydEhlaWdodAUAAAAOdm90aW5nRHVyYXRpb24DCQAAZgAAAAIFAAAACWVuZEhlaWdodAUAAAAGaGVpZ2h0CQAFFAAAAAIFAAAAA25pbAcEAAAAGmxhdGVzdFByb2Nlc3NlZEFzc2V0T3JVbml0CQAEIgAAAAEFAAAAF2tleUxhdGVzdFByb2Nlc3NlZEFzc2V0BAAAABlsYXRlc3RQcm9jZXNzZWRVc2VyT3JVbml0CQAEIgAAAAEFAAAAFmtleUxhdGVzdFByb2Nlc3NlZFVzZXIEAAAAD25leHRQZXJpb2REZWxheQAAAAAAAAAAAQQAAAAGZmluaXNoCQAFFAAAAAIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAADmtleVN0YXJ0SGVpZ2h0CQAAZAAAAAIFAAAABmhlaWdodAUAAAAPbmV4dFBlcmlvZERlbGF5CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABBrZXlDdXJyZW50UGVyaW9kCQAAZAAAAAIFAAAADWN1cnJlbnRQZXJpb2QAAAAAAAAAAAEJAARMAAAAAgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQUAAAAXa2V5TGF0ZXN0UHJvY2Vzc2VkQXNzZXQJAARMAAAAAgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQUAAAAWa2V5TGF0ZXN0UHJvY2Vzc2VkVXNlcgUAAAADbmlsBgMJAAAAAAAAAgUAAAAabGF0ZXN0UHJvY2Vzc2VkQXNzZXRPclVuaXQFAAAABHVuaXQEAAAAEGFzc2V0c0hlYWRPclVuaXQJAAQiAAAAAQkBAAAAC2tleUxpc3RIZWFkAAAAAQUAAAAOYXNzZXRzTGlzdE5hbWUDCQAAAAAAAAIFAAAAEGFzc2V0c0hlYWRPclVuaXQFAAAABHVuaXQFAAAABmZpbmlzaAQAAAAFYXNzZXQJAQAAAAV2YWx1ZQAAAAEFAAAAEGFzc2V0c0hlYWRPclVuaXQEAAAAEXVzZXJBZGRyZXNzT3JVbml0CQAEIgAAAAEJAQAAAAtrZXlMaXN0SGVhZAAAAAEJAQAAABBnZXRWb3Rlc0xpc3ROYW1lAAAAAQUAAAAFYXNzZXQEAAAAEnByb2Nlc3NWb3RlQWN0aW9ucwkBAAAAC3Byb2Nlc3NWb3RlAAAAAgUAAAAFYXNzZXQFAAAAEXVzZXJBZGRyZXNzT3JVbml0CQAFFAAAAAIFAAAAEnByb2Nlc3NWb3RlQWN0aW9ucwYEAAAAFGxhdGVzdFByb2Nlc3NlZEFzc2V0CQEAAAAFdmFsdWUAAAABBQAAABpsYXRlc3RQcm9jZXNzZWRBc3NldE9yVW5pdAMJAAAAAAAAAgUAAAAZbGF0ZXN0UHJvY2Vzc2VkVXNlck9yVW5pdAUAAAAEdW5pdAQAAAAQZmluYWxpemVBc3NldEludgkAA/wAAAAEBQAAAAR0aGlzAgAAABVmaW5hbGl6ZUFzc2V0SU5URVJOQUwJAARMAAAAAgUAAAAUbGF0ZXN0UHJvY2Vzc2VkQXNzZXQJAARMAAAAAgUAAAANY3VycmVudFBlcmlvZAUAAAADbmlsBQAAAANuaWwDCQAAAAAAAAIFAAAAEGZpbmFsaXplQXNzZXRJbnYFAAAAEGZpbmFsaXplQXNzZXRJbnYEAAAAC2Fzc2V0T3JVbml0CQAEIgAAAAEJAQAAAAtrZXlMaXN0TmV4dAAAAAIFAAAADmFzc2V0c0xpc3ROYW1lBQAAABRsYXRlc3RQcm9jZXNzZWRBc3NldAMJAAAAAAAAAgUAAAALYXNzZXRPclVuaXQFAAAABHVuaXQFAAAABmZpbmlzaAQAAAAFYXNzZXQJAQAAAAV2YWx1ZQAAAAEFAAAAC2Fzc2V0T3JVbml0BAAAABF1c2VyQWRkcmVzc09yVW5pdAkABCIAAAABCQEAAAALa2V5TGlzdEhlYWQAAAABCQEAAAAQZ2V0Vm90ZXNMaXN0TmFtZQAAAAEFAAAABWFzc2V0BAAAABJwcm9jZXNzVm90ZUFjdGlvbnMJAQAAAAtwcm9jZXNzVm90ZQAAAAIFAAAABWFzc2V0BQAAABF1c2VyQWRkcmVzc09yVW5pdAkABRQAAAACBQAAABJwcm9jZXNzVm90ZUFjdGlvbnMGCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgQAAAATbGF0ZXN0UHJvY2Vzc2VkVXNlcgkBAAAABXZhbHVlAAAAAQUAAAAZbGF0ZXN0UHJvY2Vzc2VkVXNlck9yVW5pdAQAAAARdXNlckFkZHJlc3NPclVuaXQJAAQiAAAAAQkBAAAAC2tleUxpc3ROZXh0AAAAAgkBAAAAEGdldFZvdGVzTGlzdE5hbWUAAAABBQAAABRsYXRlc3RQcm9jZXNzZWRBc3NldAUAAAATbGF0ZXN0UHJvY2Vzc2VkVXNlcgQAAAAScHJvY2Vzc1ZvdGVBY3Rpb25zCQEAAAALcHJvY2Vzc1ZvdGUAAAACBQAAABRsYXRlc3RQcm9jZXNzZWRBc3NldAUAAAARdXNlckFkZHJlc3NPclVuaXQJAAUUAAAAAgUAAAAScHJvY2Vzc1ZvdGVBY3Rpb25zBgAAAAFpAQAAABVmaW5hbGl6ZVZvdGluZ1dyYXBwZXIAAAABAAAAB2NvdW50ZXIEAAAABnJlc3VsdAkBAAAABmFzQm9vbAAAAAEJAAP8AAAABAUAAAAEdGhpcwIAAAAUZmluYWxpemVWb3RpbmdIZWxwZXIFAAAAA25pbAUAAAADbmlsAwkAAAAAAAACBQAAAAZyZXN1bHQFAAAABnJlc3VsdAMJAQAAAAEhAAAAAQUAAAAGcmVzdWx0AwkAAAAAAAACBQAAAAdjb3VudGVyAAAAAAAAAAAACQAAAgAAAAECAAAAHkN1cnJlbnQgdm90aW5nIGlzIG5vdCBvdmVyIHlldAkABRQAAAACBQAAAANuaWwFAAAABHVuaXQDCQAAZgAAAAIFAAAACG1heERlcHRoBQAAAAdjb3VudGVyBAAAAANpbnYJAAP8AAAABAUAAAAEdGhpcwIAAAAVZmluYWxpemVWb3RpbmdXcmFwcGVyCQAETAAAAAIJAABkAAAAAgUAAAAHY291bnRlcgAAAAAAAAAAAQUAAAADbmlsBQAAAANuaWwDCQAAAAAAAAIFAAAAA2ludgUAAAADaW52CQAFFAAAAAIFAAAAA25pbAUAAAAEdW5pdAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAUUAAAAAgUAAAADbmlsBQAAAAR1bml0CQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgAAAAFpAQAAAA5maW5hbGl6ZVZvdGluZwAAAAAEAAAAA2ludgkAA/wAAAAEBQAAAAR0aGlzAgAAABVmaW5hbGl6ZVZvdGluZ1dyYXBwZXIJAARMAAAAAgAAAAAAAAAAAAUAAAADbmlsBQAAAANuaWwDCQAAAAAAAAIFAAAAA2ludgUAAAADaW52CQAFFAAAAAIFAAAAA25pbAUAAAAEdW5pdAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAABaQEAAAASc2V0Vm90aW5nVGhyZXNob2xkAAAAAQAAAAxuZXdUaHJlc2hvbGQEAAAAC2NoZWNrQ2FsbGVyCQEAAAAIdGhpc09ubHkAAAABBQAAAAFpAwkAAAAAAAACBQAAAAtjaGVja0NhbGxlcgUAAAALY2hlY2tDYWxsZXIJAAUUAAAAAgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAASa2V5Vm90aW5nVGhyZXNob2xkBQAAAAxuZXdUaHJlc2hvbGQFAAAAA25pbAUAAAAEdW5pdAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAABaQEAAAAGc2V0RmVlAAAAAQAAAAZuZXdGZWUEAAAAC2NoZWNrQ2FsbGVyCQEAAAAIdGhpc09ubHkAAAABBQAAAAFpAwkAAAAAAAACBQAAAAtjaGVja0NhbGxlcgUAAAALY2hlY2tDYWxsZXIJAAUUAAAAAgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAMa2V5RmVlQW1vdW50BQAAAAZuZXdGZWUFAAAAA25pbAUAAAAEdW5pdAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAABaQEAAAAbZ3d4QXZhaWxhYmxlRm9yVm90ZVJFQURPTkxZAAAAAQAAAAt1c2VyQWRkcmVzcwQAAAAJZW5kSGVpZ2h0CQAAZAAAAAIFAAAAC3N0YXJ0SGVpZ2h0BQAAAA52b3RpbmdEdXJhdGlvbgQAAAAOZ3d4QW1vdW50QXRFbmQJAQAAABhnZXRVc2VyR3d4QW1vdW50QXRIZWlnaHQAAAACBQAAAAt1c2VyQWRkcmVzcwUAAAAJZW5kSGVpZ2h0CQAFFAAAAAIFAAAAA25pbAUAAAAOZ3d4QW1vdW50QXRFbmQAAAAAx6oIWg==", "chainId": 84, "height": 1973672, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 5iTiPMMEZXVpDpsZB8WjiqeMDHAcqn8QxwQAAnsBYBHY Next: none Diff:
OldNewDifferences
3939
4040 let keyEmissionContract = makeString(["%s", "emissionContract"], separator)
4141
42+let keyAssetsStoreContract = makeString(["%s", "assetsStoreContract"], separator)
43+
4244 let keyLatestProcessedAsset = makeString(["%s", "latestProcessedAsset"], separator)
4345
4446 let keyLatestProcessedUser = makeString(["%s", "latestProcessedUser"], separator)
6365 func keyListNext (listName,id) = makeString([("%s%s%s" + listName), id, "next"], separator)
6466
6567
66-func keyIntermediateVoteResultByPeriod (assetId,period) = makeString(["%s%d%s%s", "votingResultAt", toString(period), assetId], separator)
68+func keyAssetVerifiedByPeriod (assetId,period) = makeString(["%s%d%s", "verifiedAt", toString(period), assetId], separator)
6769
6870
69-func formatIntermediateVoteResult (totalYes,totalNo) = makeString(["%d%d", toString(totalYes), toString(totalNo)], separator)
71+func keyVoteResultByPeriod (assetId,period) = makeString(["%s%d%s", "votingResultAtAsset", toString(period), assetId], separator)
7072
7173
72-func parseIntermediateVoteResult (input) = {
74+func formatVoteResult (totalYes,totalNo) = makeString(["%d%d", toString(totalYes), toString(totalNo)], separator)
75+
76+
77+func parseVoteResult (input) = {
7378 let parts = split(input, separator)
7479 let totalYesIdx = 1
7580 let totalNoIdx = 2
121126 }
122127
123128
129+func keyUserVoteHistory (type,userAddress,assetId,txId,period) = makeString(["%s%s%s%s%s%d", "history", type, assetId, userAddress, txId, toString(period)], separator)
130+
131+
124132 func thisOnly (i) = if ((i.caller == this))
125133 then true
126134 else throw("Permission denied")
155163 let boostingContract = addressFromStringValue(getStringOrFail(keyBoostingContract))
156164
157165 let emissionContract = addressFromStringValue(getStringOrFail(keyEmissionContract))
166+
167+let assetsStoreContract = addressFromStringValue(getStringOrFail(keyAssetsStoreContract))
158168
159169 func getUserGwxAmountAtHeight (userAddress,targetHeight) = {
160170 let gwxAmount = invoke(boostingContract, "getUserGwxAmountAtHeightREADONLY", [userAddress, targetHeight], nil)
225235 deleteNode(votesListName, userAddress)
226236 }
227237 else {
228- let intermediateVoteResultKey = keyIntermediateVoteResultByPeriod(assetId, currentPeriod)
229- let $t077647932 = match getString(intermediateVoteResultKey) {
238+ let voteResultKey = keyVoteResultByPeriod(assetId, currentPeriod)
239+ let $t082548398 = match getString(voteResultKey) {
230240 case s: String =>
231- parseIntermediateVoteResult(s)
241+ parseVoteResult(s)
232242 case _: Unit =>
233243 $Tuple2(0, 0)
234244 case _ =>
235245 throw("Match error")
236246 }
237- let totalYes = $t077647932._1
238- let totalNo = $t077647932._2
239- func getIntermediateVoteResultAction (totalYes,totalNo,total,inFavor) = StringEntry(intermediateVoteResultKey, formatIntermediateVoteResult((totalYes + (if (inFavor)
247+ let totalYes = $t082548398._1
248+ let totalNo = $t082548398._2
249+ func getVoteResultAction (totalYes,totalNo,total,inFavor) = StringEntry(voteResultKey, formatVoteResult((totalYes + (if (inFavor)
240250 then total
241251 else 0)), (totalNo + (if (inFavor)
242252 then 0
248258 if ((userPreviousVoteOrUnit == unit))
249259 then nil
250260 else {
251- let $t085758648 = parseUserVote(value(userPreviousVoteOrUnit))
252- let prevTotal = $t085758648._1
253- let inFavor = $t085758648._2
261+ let $t090059078 = parseUserVote(value(userPreviousVoteOrUnit))
262+ let prevTotal = $t090059078._1
263+ let inFavor = $t090059078._2
254264 let total = min([prevTotal, userGwxAmountAtEndHeight])
255-[StringEntry(userVoteKey, formatUserVote(total, inFavor)), getIntermediateVoteResultAction(totalYes, totalNo, total, inFavor)]
265+[StringEntry(userVoteKey, formatUserVote(total, inFavor)), getVoteResultAction(totalYes, totalNo, total, inFavor)]
256266 }
257267 }
258268 else {
259- let $t089198980 = parseUserVote(value(userVoteOrUnit))
260- let total = $t089198980._1
261- let inFavor = $t089198980._2
262-[getIntermediateVoteResultAction(totalYes, totalNo, total, inFavor)]
269+ let $t093379398 = parseUserVote(value(userVoteOrUnit))
270+ let total = $t093379398._1
271+ let inFavor = $t093379398._2
272+[getVoteResultAction(totalYes, totalNo, total, inFavor)]
263273 }
264274 }
265275 ((voteActions :+ updateLatestProcessedAssetAction) :+ updateLatestProcessedUserAction)
268278
269279
270280 @Callable(i)
271-func constructor (boostingContractPrm,emissionContractPrm,feeAmountPrm,wxAssetIdPrm,votingThresholdPrm,votingDurationPrm,voteBeforeEliminationPrm,startHeightPrm) = {
281+func constructor (boostingContractPrm,emissionContractPrm,assetsStoreContractPrm,feeAmountPrm,wxAssetIdPrm,votingThresholdPrm,votingDurationPrm,voteBeforeEliminationPrm,startHeightPrm) = {
272282 let checks = [thisOnly(i), if (isDefined(addressFromString(boostingContractPrm)))
273283 then true
274284 else throw("Invalid boosting contract address"), if (isDefined(addressFromString(emissionContractPrm)))
275285 then true
276- else throw("Invalid emission contract address"), if ((feeAmountPrm >= 0))
286+ else throw("Invalid emission contract address"), if (isDefined(addressFromString(assetsStoreContractPrm)))
287+ then true
288+ else throw("Invalid asset_store contract address"), if ((feeAmountPrm >= 0))
277289 then true
278290 else throw("Invalid fee amount"), if (isDefined(assetInfo(fromBase58String(wxAssetIdPrm))))
279291 then true
285297 then true
286298 else throw("Invalid start height")]
287299 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)
300+ then $Tuple2([StringEntry(keyBoostingContract, boostingContractPrm), StringEntry(keyEmissionContract, emissionContractPrm), StringEntry(keyAssetsStoreContract, assetsStoreContractPrm), IntegerEntry(keyFeeAmount, feeAmountPrm), StringEntry(keyWxAssetId, wxAssetIdPrm), IntegerEntry(keyVotingThreshold, votingThresholdPrm), IntegerEntry(keyVotingDuration, votingDurationPrm), IntegerEntry(keyVoteBeforeElimination, voteBeforeEliminationPrm), IntegerEntry(keyStartHeight, startHeightPrm), IntegerEntry(keyCurrentPeriod, 0)], unit)
289301 else throw("Strict value is not equal to itself.")
290302 }
291303
292304
293305
294306 @Callable(i)
295-func suggest (assetId,assetImage) = {
307+func suggest (assetId,ticker,assetImage) = {
296308 let info = valueOrErrorMessage(assetInfo(fromBase58String(assetId)), "Invalid asset ID")
297309 let payment = value(i.payments[0])
298310 let checks = [if ((info.issuer == i.caller))
304316 else throw("Invalid fee amount")]
305317 if ((checks == checks))
306318 then {
307- let burnFeeInv = invoke(emissionContract, "burn", nil, [AttachedPayment(payment.assetId, payment.amount)])
308- if ((burnFeeInv == burnFeeInv))
319+ let assetsStoreCreateOrUpdateInv = invoke(assetsStoreContract, "createOrUpdate", [assetId, ticker, assetImage, false], nil)
320+ if ((assetsStoreCreateOrUpdateInv == assetsStoreCreateOrUpdateInv))
309321 then {
310- let addAssetActions = insertNode(assetsListName, assetId)
311- $Tuple2((addAssetActions :+ StringEntry(keyAssetImage(assetId), assetImage)), unit)
322+ let burnFeeInv = invoke(emissionContract, "burn", nil, [AttachedPayment(payment.assetId, payment.amount)])
323+ if ((burnFeeInv == burnFeeInv))
324+ then {
325+ let addAssetActions = insertNode(assetsListName, assetId)
326+ $Tuple2((addAssetActions :+ StringEntry(keyAssetImage(assetId), assetImage)), unit)
327+ }
328+ else throw("Strict value is not equal to itself.")
312329 }
313330 else throw("Strict value is not equal to itself.")
314331 }
339356 then {
340357 let votesListName = getVotesListName(assetId)
341358 let userVoteKey = keyUserVoteByPeriod(userAddress, assetId, currentPeriod)
342- let userVoteActions = [StringEntry(userVoteKey, formatUserVote(gwxAmountAtEnd, inFavor))]
359+ let userVoteActions = [StringEntry(userVoteKey, formatUserVote(gwxAmountAtEnd, inFavor)), StringEntry(keyUserVoteHistory("vote", userAddress, assetId, toBase58String(i.transactionId), currentPeriod), formatUserVote(gwxAmountAtEnd, inFavor))]
343360 let votesListActions = if (containsNode(votesListName, userAddress))
344361 then nil
345362 else insertNode(votesListName, userAddress)
364381 if ((checkVote == checkVote))
365382 then {
366383 let votesListActions = deleteNode(votesListName, userAddress)
367- let userVoteActions = [DeleteEntry(userVoteKey)]
384+ let userVoteActions = [DeleteEntry(userVoteKey), StringEntry(keyUserVoteHistory("cancelVote", userAddress, assetId, toBase58String(i.transactionId), currentPeriod), formatUserVote(0, true))]
368385 $Tuple2((votesListActions ++ userVoteActions), unit)
386+ }
387+ else throw("Strict value is not equal to itself.")
388+ }
389+
390+
391+
392+@Callable(i)
393+func finalizeAssetINTERNAL (assetId,period) = {
394+ let checkCaller = thisOnly(i)
395+ if ((checkCaller == checkCaller))
396+ then {
397+ let voteResultKey = keyVoteResultByPeriod(assetId, period)
398+ let $t01443514567 = match getString(voteResultKey) {
399+ case s: String =>
400+ parseVoteResult(s)
401+ case _: Unit =>
402+ $Tuple2(0, 0)
403+ case _ =>
404+ throw("Match error")
405+ }
406+ let totalYes = $t01443514567._1
407+ let totalNo = $t01443514567._2
408+ let total = (totalYes + totalNo)
409+ let verified = if ((total >= votingThreshold))
410+ then (totalYes > totalNo)
411+ else false
412+ let assetVerifiedAction = BooleanEntry(keyAssetVerifiedByPeriod(assetId, period), verified)
413+ let assetsStoreSetVerifiedInv = invoke(assetsStoreContract, "setVerified", [assetId, verified], nil)
414+ if ((assetsStoreSetVerifiedInv == assetsStoreSetVerifiedInv))
415+ then $Tuple2([assetVerifiedAction], unit)
416+ else throw("Strict value is not equal to itself.")
369417 }
370418 else throw("Strict value is not equal to itself.")
371419 }
398446 let latestProcessedAsset = value(latestProcessedAssetOrUnit)
399447 if ((latestProcessedUserOrUnit == unit))
400448 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)
449+ let finalizeAssetInv = invoke(this, "finalizeAssetINTERNAL", [latestProcessedAsset, currentPeriod], nil)
450+ if ((finalizeAssetInv == finalizeAssetInv))
451+ then {
452+ let assetOrUnit = getString(keyListNext(assetsListName, latestProcessedAsset))
453+ if ((assetOrUnit == unit))
454+ then finish
455+ else {
456+ let asset = value(assetOrUnit)
457+ let userAddressOrUnit = getString(keyListHead(getVotesListName(asset)))
458+ let processVoteActions = processVote(asset, userAddressOrUnit)
459+ $Tuple2(processVoteActions, true)
460+ }
409461 }
462+ else throw("Strict value is not equal to itself.")
410463 }
411464 else {
412465 let latestProcessedUser = value(latestProcessedUserOrUnit)
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let separator = "__"
55
66 let maxDepth = 10
77
88 func asInt (val) = match val {
99 case valInt: Int =>
1010 valInt
1111 case _ =>
1212 throw("Failed to cast into Integer")
1313 }
1414
1515
1616 func asBool (val) = match val {
1717 case valBool: Boolean =>
1818 valBool
1919 case _ =>
2020 throw("Failed to cast into Boolean")
2121 }
2222
2323
2424 let keyFeeAmount = makeString(["%s", "fee"], separator)
2525
2626 let keyWxAssetId = makeString(["%s", "wxAssetId"], separator)
2727
2828 let keyVotingThreshold = makeString(["%s", "votingThreshold"], separator)
2929
3030 let keyVotingDuration = makeString(["%s", "epochLength"], separator)
3131
3232 let keyVoteBeforeElimination = makeString(["%s", "voteBeforeElimination"], separator)
3333
3434 let keyStartHeight = makeString(["%s", "currentVotingHeightStart"], separator)
3535
3636 let keyCurrentPeriod = makeString(["%s", "currentEpoch"], separator)
3737
3838 let keyBoostingContract = makeString(["%s", "boostingContract"], separator)
3939
4040 let keyEmissionContract = makeString(["%s", "emissionContract"], separator)
4141
42+let keyAssetsStoreContract = makeString(["%s", "assetsStoreContract"], separator)
43+
4244 let keyLatestProcessedAsset = makeString(["%s", "latestProcessedAsset"], separator)
4345
4446 let keyLatestProcessedUser = makeString(["%s", "latestProcessedUser"], separator)
4547
4648 func keyAssetImage (assetId) = makeString(["%s", "assetImage"], separator)
4749
4850
4951 let assetsListName = "__assets"
5052
5153 func getVotesListName (assetId) = ("%s__votes__" + assetId)
5254
5355
5456 func keyListHead (listName) = makeString([("%s%s" + listName), "head"], separator)
5557
5658
5759 func keyListSize (listName) = makeString([("%s%s" + listName), "size"], separator)
5860
5961
6062 func keyListPrev (listName,id) = makeString([("%s%s%s" + listName), id, "prev"], separator)
6163
6264
6365 func keyListNext (listName,id) = makeString([("%s%s%s" + listName), id, "next"], separator)
6466
6567
66-func keyIntermediateVoteResultByPeriod (assetId,period) = makeString(["%s%d%s%s", "votingResultAt", toString(period), assetId], separator)
68+func keyAssetVerifiedByPeriod (assetId,period) = makeString(["%s%d%s", "verifiedAt", toString(period), assetId], separator)
6769
6870
69-func formatIntermediateVoteResult (totalYes,totalNo) = makeString(["%d%d", toString(totalYes), toString(totalNo)], separator)
71+func keyVoteResultByPeriod (assetId,period) = makeString(["%s%d%s", "votingResultAtAsset", toString(period), assetId], separator)
7072
7173
72-func parseIntermediateVoteResult (input) = {
74+func formatVoteResult (totalYes,totalNo) = makeString(["%d%d", toString(totalYes), toString(totalNo)], separator)
75+
76+
77+func parseVoteResult (input) = {
7378 let parts = split(input, separator)
7479 let totalYesIdx = 1
7580 let totalNoIdx = 2
7681 let totalYes = parseIntValue(parts[totalYesIdx])
7782 let totalNo = parseIntValue(parts[totalNoIdx])
7883 $Tuple2(totalYes, totalNo)
7984 }
8085
8186
8287 func keyUserVoteByPeriod (userAddress,assetId,period) = makeString(["%s%d%s%s", "vru", toString(period), assetId, userAddress], separator)
8388
8489
8590 func formatUserVote (total,inFavor) = {
8691 let totalYes = if (inFavor)
8792 then total
8893 else 0
8994 let totalNo = if (inFavor)
9095 then 0
9196 else total
9297 makeString(["%d%d", toString(totalYes), toString(totalNo)], separator)
9398 }
9499
95100
96101 func parseUserVote (input) = {
97102 let parts = split(input, separator)
98103 let totalYesIdx = 1
99104 let totalNoIdx = 2
100105 let totalYes = parseIntValue(parts[totalYesIdx])
101106 let totalNo = parseIntValue(parts[totalNoIdx])
102107 let inFavor = if ((totalYes > 0))
103108 then (totalNo == 0)
104109 else false
105110 let against = if ((totalYes == 0))
106111 then (totalNo > 0)
107112 else false
108113 let checkTotals = if (if (inFavor)
109114 then true
110115 else against)
111116 then true
112117 else throw("Invalid user vote value")
113118 if ((checkTotals == checkTotals))
114119 then {
115120 let total = if (inFavor)
116121 then totalYes
117122 else totalNo
118123 $Tuple2(total, inFavor)
119124 }
120125 else throw("Strict value is not equal to itself.")
121126 }
122127
123128
129+func keyUserVoteHistory (type,userAddress,assetId,txId,period) = makeString(["%s%s%s%s%s%d", "history", type, assetId, userAddress, txId, toString(period)], separator)
130+
131+
124132 func thisOnly (i) = if ((i.caller == this))
125133 then true
126134 else throw("Permission denied")
127135
128136
129137 func getIntegerOrZero (key) = valueOrElse(getInteger(this, key), 0)
130138
131139
132140 func getIntegerOrFail (key) = valueOrErrorMessage(getInteger(this, key), (key + " is not defined"))
133141
134142
135143 func getStringOrEmpty (key) = valueOrElse(getString(this, key), "")
136144
137145
138146 func getStringOrFail (key) = valueOrErrorMessage(getString(this, key), (key + " is not defined"))
139147
140148
141149 let feeAmount = getIntegerOrFail(keyFeeAmount)
142150
143151 let wxAssetId = fromBase58String(getStringOrFail(keyWxAssetId))
144152
145153 let votingThreshold = getIntegerOrFail(keyVotingThreshold)
146154
147155 let votingDuration = getIntegerOrFail(keyVotingDuration)
148156
149157 let voteBeforeElimination = getIntegerOrFail(keyVoteBeforeElimination)
150158
151159 let startHeight = getIntegerOrFail(keyStartHeight)
152160
153161 let currentPeriod = getIntegerOrFail(keyCurrentPeriod)
154162
155163 let boostingContract = addressFromStringValue(getStringOrFail(keyBoostingContract))
156164
157165 let emissionContract = addressFromStringValue(getStringOrFail(keyEmissionContract))
166+
167+let assetsStoreContract = addressFromStringValue(getStringOrFail(keyAssetsStoreContract))
158168
159169 func getUserGwxAmountAtHeight (userAddress,targetHeight) = {
160170 let gwxAmount = invoke(boostingContract, "getUserGwxAmountAtHeightREADONLY", [userAddress, targetHeight], nil)
161171 asInt(gwxAmount)
162172 }
163173
164174
165175 func containsNode (listName,id) = {
166176 let head = getString(this, keyListHead(listName))
167177 let prev = getString(this, keyListPrev(listName, id))
168178 let next = getString(this, keyListNext(listName, id))
169179 if (if ((id == head))
170180 then true
171181 else (prev != unit))
172182 then true
173183 else (next != unit)
174184 }
175185
176186
177187 func insertNode (listName,id) = {
178188 let head = getString(this, keyListHead(listName))
179189 let listSize = valueOrElse(getInteger(this, keyListSize(listName)), 0)
180190 let checkNode = if (!(containsNode(listName, id)))
181191 then true
182192 else throw("Node exists")
183193 if ((checkNode == checkNode))
184194 then (([IntegerEntry(keyListSize(listName), (listSize + 1))] ++ (if (isDefined(head))
185195 then [StringEntry(keyListNext(listName, id), value(head)), StringEntry(keyListPrev(listName, value(head)), id)]
186196 else nil)) ++ [StringEntry(keyListHead(listName), id)])
187197 else throw("Strict value is not equal to itself.")
188198 }
189199
190200
191201 func deleteNode (listName,id) = {
192202 let head = getString(this, keyListHead(listName))
193203 let listSize = valueOrElse(getInteger(this, keyListSize(listName)), 0)
194204 let prev = getString(this, keyListPrev(listName, id))
195205 let next = getString(this, keyListNext(listName, id))
196206 ([IntegerEntry(keyListSize(listName), (listSize - 1))] ++ (if (if (isDefined(prev))
197207 then isDefined(next)
198208 else false)
199209 then [StringEntry(keyListNext(listName, value(prev)), value(next)), StringEntry(keyListPrev(listName, value(next)), value(prev)), DeleteEntry(keyListPrev(listName, id)), DeleteEntry(keyListNext(listName, id))]
200210 else if (isDefined(next))
201211 then [StringEntry(keyListHead(listName), value(next)), DeleteEntry(keyListNext(listName, id)), DeleteEntry(keyListPrev(listName, value(next)))]
202212 else if (isDefined(prev))
203213 then [DeleteEntry(keyListPrev(listName, id)), DeleteEntry(keyListNext(listName, value(prev)))]
204214 else if ((id == head))
205215 then [DeleteEntry(keyListHead(listName))]
206216 else throw("Invalid node")))
207217 }
208218
209219
210220 func processVote (assetId,userAddressOrUnit) = {
211221 let updateLatestProcessedAssetAction = StringEntry(keyLatestProcessedAsset, assetId)
212222 let deleteLatestProcessedUserAction = DeleteEntry(keyLatestProcessedUser)
213223 if ((userAddressOrUnit == unit))
214224 then [updateLatestProcessedAssetAction, deleteLatestProcessedUserAction]
215225 else {
216226 let endHeight = (startHeight + votingDuration)
217227 let userAddress = value(userAddressOrUnit)
218228 let updateLatestProcessedUserAction = StringEntry(keyLatestProcessedUser, userAddress)
219229 let userVoteKey = keyUserVoteByPeriod(userAddress, assetId, currentPeriod)
220230 let userVoteOrUnit = getString(userVoteKey)
221231 let userGwxAmountAtEndHeight = getUserGwxAmountAtHeight(userAddress, endHeight)
222232 let voteActions = if ((userGwxAmountAtEndHeight == 0))
223233 then {
224234 let votesListName = getVotesListName(assetId)
225235 deleteNode(votesListName, userAddress)
226236 }
227237 else {
228- let intermediateVoteResultKey = keyIntermediateVoteResultByPeriod(assetId, currentPeriod)
229- let $t077647932 = match getString(intermediateVoteResultKey) {
238+ let voteResultKey = keyVoteResultByPeriod(assetId, currentPeriod)
239+ let $t082548398 = match getString(voteResultKey) {
230240 case s: String =>
231- parseIntermediateVoteResult(s)
241+ parseVoteResult(s)
232242 case _: Unit =>
233243 $Tuple2(0, 0)
234244 case _ =>
235245 throw("Match error")
236246 }
237- let totalYes = $t077647932._1
238- let totalNo = $t077647932._2
239- func getIntermediateVoteResultAction (totalYes,totalNo,total,inFavor) = StringEntry(intermediateVoteResultKey, formatIntermediateVoteResult((totalYes + (if (inFavor)
247+ let totalYes = $t082548398._1
248+ let totalNo = $t082548398._2
249+ func getVoteResultAction (totalYes,totalNo,total,inFavor) = StringEntry(voteResultKey, formatVoteResult((totalYes + (if (inFavor)
240250 then total
241251 else 0)), (totalNo + (if (inFavor)
242252 then 0
243253 else total))))
244254
245255 if ((userVoteOrUnit == unit))
246256 then {
247257 let userPreviousVoteOrUnit = getString(keyUserVoteByPeriod(userAddress, assetId, (currentPeriod - 1)))
248258 if ((userPreviousVoteOrUnit == unit))
249259 then nil
250260 else {
251- let $t085758648 = parseUserVote(value(userPreviousVoteOrUnit))
252- let prevTotal = $t085758648._1
253- let inFavor = $t085758648._2
261+ let $t090059078 = parseUserVote(value(userPreviousVoteOrUnit))
262+ let prevTotal = $t090059078._1
263+ let inFavor = $t090059078._2
254264 let total = min([prevTotal, userGwxAmountAtEndHeight])
255-[StringEntry(userVoteKey, formatUserVote(total, inFavor)), getIntermediateVoteResultAction(totalYes, totalNo, total, inFavor)]
265+[StringEntry(userVoteKey, formatUserVote(total, inFavor)), getVoteResultAction(totalYes, totalNo, total, inFavor)]
256266 }
257267 }
258268 else {
259- let $t089198980 = parseUserVote(value(userVoteOrUnit))
260- let total = $t089198980._1
261- let inFavor = $t089198980._2
262-[getIntermediateVoteResultAction(totalYes, totalNo, total, inFavor)]
269+ let $t093379398 = parseUserVote(value(userVoteOrUnit))
270+ let total = $t093379398._1
271+ let inFavor = $t093379398._2
272+[getVoteResultAction(totalYes, totalNo, total, inFavor)]
263273 }
264274 }
265275 ((voteActions :+ updateLatestProcessedAssetAction) :+ updateLatestProcessedUserAction)
266276 }
267277 }
268278
269279
270280 @Callable(i)
271-func constructor (boostingContractPrm,emissionContractPrm,feeAmountPrm,wxAssetIdPrm,votingThresholdPrm,votingDurationPrm,voteBeforeEliminationPrm,startHeightPrm) = {
281+func constructor (boostingContractPrm,emissionContractPrm,assetsStoreContractPrm,feeAmountPrm,wxAssetIdPrm,votingThresholdPrm,votingDurationPrm,voteBeforeEliminationPrm,startHeightPrm) = {
272282 let checks = [thisOnly(i), if (isDefined(addressFromString(boostingContractPrm)))
273283 then true
274284 else throw("Invalid boosting contract address"), if (isDefined(addressFromString(emissionContractPrm)))
275285 then true
276- else throw("Invalid emission contract address"), if ((feeAmountPrm >= 0))
286+ else throw("Invalid emission contract address"), if (isDefined(addressFromString(assetsStoreContractPrm)))
287+ then true
288+ else throw("Invalid asset_store contract address"), if ((feeAmountPrm >= 0))
277289 then true
278290 else throw("Invalid fee amount"), if (isDefined(assetInfo(fromBase58String(wxAssetIdPrm))))
279291 then true
280292 else throw("Invalid WX asset ID"), if ((votingThresholdPrm >= 0))
281293 then true
282294 else throw("Invalid voting threshold"), if ((votingDurationPrm > 0))
283295 then true
284296 else throw("Invalid voting duration"), if (((startHeightPrm + votingDurationPrm) > height))
285297 then true
286298 else throw("Invalid start height")]
287299 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)
300+ then $Tuple2([StringEntry(keyBoostingContract, boostingContractPrm), StringEntry(keyEmissionContract, emissionContractPrm), StringEntry(keyAssetsStoreContract, assetsStoreContractPrm), IntegerEntry(keyFeeAmount, feeAmountPrm), StringEntry(keyWxAssetId, wxAssetIdPrm), IntegerEntry(keyVotingThreshold, votingThresholdPrm), IntegerEntry(keyVotingDuration, votingDurationPrm), IntegerEntry(keyVoteBeforeElimination, voteBeforeEliminationPrm), IntegerEntry(keyStartHeight, startHeightPrm), IntegerEntry(keyCurrentPeriod, 0)], unit)
289301 else throw("Strict value is not equal to itself.")
290302 }
291303
292304
293305
294306 @Callable(i)
295-func suggest (assetId,assetImage) = {
307+func suggest (assetId,ticker,assetImage) = {
296308 let info = valueOrErrorMessage(assetInfo(fromBase58String(assetId)), "Invalid asset ID")
297309 let payment = value(i.payments[0])
298310 let checks = [if ((info.issuer == i.caller))
299311 then true
300312 else throw("Asset can only be suggested by its issuer"), if ((value(payment.assetId) == wxAssetId))
301313 then true
302314 else throw("Invalid fee asset"), if ((payment.amount == feeAmount))
303315 then true
304316 else throw("Invalid fee amount")]
305317 if ((checks == checks))
306318 then {
307- let burnFeeInv = invoke(emissionContract, "burn", nil, [AttachedPayment(payment.assetId, payment.amount)])
308- if ((burnFeeInv == burnFeeInv))
319+ let assetsStoreCreateOrUpdateInv = invoke(assetsStoreContract, "createOrUpdate", [assetId, ticker, assetImage, false], nil)
320+ if ((assetsStoreCreateOrUpdateInv == assetsStoreCreateOrUpdateInv))
309321 then {
310- let addAssetActions = insertNode(assetsListName, assetId)
311- $Tuple2((addAssetActions :+ StringEntry(keyAssetImage(assetId), assetImage)), unit)
322+ let burnFeeInv = invoke(emissionContract, "burn", nil, [AttachedPayment(payment.assetId, payment.amount)])
323+ if ((burnFeeInv == burnFeeInv))
324+ then {
325+ let addAssetActions = insertNode(assetsListName, assetId)
326+ $Tuple2((addAssetActions :+ StringEntry(keyAssetImage(assetId), assetImage)), unit)
327+ }
328+ else throw("Strict value is not equal to itself.")
312329 }
313330 else throw("Strict value is not equal to itself.")
314331 }
315332 else throw("Strict value is not equal to itself.")
316333 }
317334
318335
319336
320337 @Callable(i)
321338 func vote (assetId,inFavor) = {
322339 let endHeight = (startHeight + votingDuration)
323340 let checkAsset = if (containsNode(assetsListName, assetId))
324341 then true
325342 else throw("Invalid asset")
326343 if ((checkAsset == checkAsset))
327344 then {
328345 let checkHeight = if ((endHeight > height))
329346 then true
330347 else throw("Current voting is over but results are not finalized")
331348 if ((checkHeight == checkHeight))
332349 then {
333350 let userAddress = toString(i.caller)
334351 let gwxAmountAtEnd = getUserGwxAmountAtHeight(userAddress, endHeight)
335352 let checkGwxAmountAtEnd = if ((gwxAmountAtEnd > 0))
336353 then true
337354 else throw("You'll not have gWX at the end of voting")
338355 if ((checkGwxAmountAtEnd == checkGwxAmountAtEnd))
339356 then {
340357 let votesListName = getVotesListName(assetId)
341358 let userVoteKey = keyUserVoteByPeriod(userAddress, assetId, currentPeriod)
342- let userVoteActions = [StringEntry(userVoteKey, formatUserVote(gwxAmountAtEnd, inFavor))]
359+ let userVoteActions = [StringEntry(userVoteKey, formatUserVote(gwxAmountAtEnd, inFavor)), StringEntry(keyUserVoteHistory("vote", userAddress, assetId, toBase58String(i.transactionId), currentPeriod), formatUserVote(gwxAmountAtEnd, inFavor))]
343360 let votesListActions = if (containsNode(votesListName, userAddress))
344361 then nil
345362 else insertNode(votesListName, userAddress)
346363 $Tuple2((votesListActions ++ userVoteActions), unit)
347364 }
348365 else throw("Strict value is not equal to itself.")
349366 }
350367 else throw("Strict value is not equal to itself.")
351368 }
352369 else throw("Strict value is not equal to itself.")
353370 }
354371
355372
356373
357374 @Callable(i)
358375 func cancelVote (assetId) = {
359376 let userAddress = toString(i.caller)
360377 let votesListName = getVotesListName(assetId)
361378 let userVoteKey = keyUserVoteByPeriod(userAddress, assetId, currentPeriod)
362379 let userVoteOrUnit = getString(userVoteKey)
363380 let checkVote = valueOrElse(getString(userVoteKey), "Nothing to cancel")
364381 if ((checkVote == checkVote))
365382 then {
366383 let votesListActions = deleteNode(votesListName, userAddress)
367- let userVoteActions = [DeleteEntry(userVoteKey)]
384+ let userVoteActions = [DeleteEntry(userVoteKey), StringEntry(keyUserVoteHistory("cancelVote", userAddress, assetId, toBase58String(i.transactionId), currentPeriod), formatUserVote(0, true))]
368385 $Tuple2((votesListActions ++ userVoteActions), unit)
386+ }
387+ else throw("Strict value is not equal to itself.")
388+ }
389+
390+
391+
392+@Callable(i)
393+func finalizeAssetINTERNAL (assetId,period) = {
394+ let checkCaller = thisOnly(i)
395+ if ((checkCaller == checkCaller))
396+ then {
397+ let voteResultKey = keyVoteResultByPeriod(assetId, period)
398+ let $t01443514567 = match getString(voteResultKey) {
399+ case s: String =>
400+ parseVoteResult(s)
401+ case _: Unit =>
402+ $Tuple2(0, 0)
403+ case _ =>
404+ throw("Match error")
405+ }
406+ let totalYes = $t01443514567._1
407+ let totalNo = $t01443514567._2
408+ let total = (totalYes + totalNo)
409+ let verified = if ((total >= votingThreshold))
410+ then (totalYes > totalNo)
411+ else false
412+ let assetVerifiedAction = BooleanEntry(keyAssetVerifiedByPeriod(assetId, period), verified)
413+ let assetsStoreSetVerifiedInv = invoke(assetsStoreContract, "setVerified", [assetId, verified], nil)
414+ if ((assetsStoreSetVerifiedInv == assetsStoreSetVerifiedInv))
415+ then $Tuple2([assetVerifiedAction], unit)
416+ else throw("Strict value is not equal to itself.")
369417 }
370418 else throw("Strict value is not equal to itself.")
371419 }
372420
373421
374422
375423 @Callable(i)
376424 func finalizeVotingHelper () = {
377425 let endHeight = (startHeight + votingDuration)
378426 if ((endHeight > height))
379427 then $Tuple2(nil, false)
380428 else {
381429 let latestProcessedAssetOrUnit = getString(keyLatestProcessedAsset)
382430 let latestProcessedUserOrUnit = getString(keyLatestProcessedUser)
383431 let nextPeriodDelay = 1
384432 let finish = $Tuple2([IntegerEntry(keyStartHeight, (height + nextPeriodDelay)), IntegerEntry(keyCurrentPeriod, (currentPeriod + 1)), DeleteEntry(keyLatestProcessedAsset), DeleteEntry(keyLatestProcessedUser)], true)
385433 if ((latestProcessedAssetOrUnit == unit))
386434 then {
387435 let assetsHeadOrUnit = getString(keyListHead(assetsListName))
388436 if ((assetsHeadOrUnit == unit))
389437 then finish
390438 else {
391439 let asset = value(assetsHeadOrUnit)
392440 let userAddressOrUnit = getString(keyListHead(getVotesListName(asset)))
393441 let processVoteActions = processVote(asset, userAddressOrUnit)
394442 $Tuple2(processVoteActions, true)
395443 }
396444 }
397445 else {
398446 let latestProcessedAsset = value(latestProcessedAssetOrUnit)
399447 if ((latestProcessedUserOrUnit == unit))
400448 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)
449+ let finalizeAssetInv = invoke(this, "finalizeAssetINTERNAL", [latestProcessedAsset, currentPeriod], nil)
450+ if ((finalizeAssetInv == finalizeAssetInv))
451+ then {
452+ let assetOrUnit = getString(keyListNext(assetsListName, latestProcessedAsset))
453+ if ((assetOrUnit == unit))
454+ then finish
455+ else {
456+ let asset = value(assetOrUnit)
457+ let userAddressOrUnit = getString(keyListHead(getVotesListName(asset)))
458+ let processVoteActions = processVote(asset, userAddressOrUnit)
459+ $Tuple2(processVoteActions, true)
460+ }
409461 }
462+ else throw("Strict value is not equal to itself.")
410463 }
411464 else {
412465 let latestProcessedUser = value(latestProcessedUserOrUnit)
413466 let userAddressOrUnit = getString(keyListNext(getVotesListName(latestProcessedAsset), latestProcessedUser))
414467 let processVoteActions = processVote(latestProcessedAsset, userAddressOrUnit)
415468 $Tuple2(processVoteActions, true)
416469 }
417470 }
418471 }
419472 }
420473
421474
422475
423476 @Callable(i)
424477 func finalizeVotingWrapper (counter) = {
425478 let result = asBool(invoke(this, "finalizeVotingHelper", nil, nil))
426479 if ((result == result))
427480 then if (!(result))
428481 then if ((counter == 0))
429482 then throw("Current voting is not over yet")
430483 else $Tuple2(nil, unit)
431484 else if ((maxDepth > counter))
432485 then {
433486 let inv = invoke(this, "finalizeVotingWrapper", [(counter + 1)], nil)
434487 if ((inv == inv))
435488 then $Tuple2(nil, unit)
436489 else throw("Strict value is not equal to itself.")
437490 }
438491 else $Tuple2(nil, unit)
439492 else throw("Strict value is not equal to itself.")
440493 }
441494
442495
443496
444497 @Callable(i)
445498 func finalizeVoting () = {
446499 let inv = invoke(this, "finalizeVotingWrapper", [0], nil)
447500 if ((inv == inv))
448501 then $Tuple2(nil, unit)
449502 else throw("Strict value is not equal to itself.")
450503 }
451504
452505
453506
454507 @Callable(i)
455508 func setVotingThreshold (newThreshold) = {
456509 let checkCaller = thisOnly(i)
457510 if ((checkCaller == checkCaller))
458511 then $Tuple2([IntegerEntry(keyVotingThreshold, newThreshold)], unit)
459512 else throw("Strict value is not equal to itself.")
460513 }
461514
462515
463516
464517 @Callable(i)
465518 func setFee (newFee) = {
466519 let checkCaller = thisOnly(i)
467520 if ((checkCaller == checkCaller))
468521 then $Tuple2([IntegerEntry(keyFeeAmount, newFee)], unit)
469522 else throw("Strict value is not equal to itself.")
470523 }
471524
472525
473526
474527 @Callable(i)
475528 func gwxAvailableForVoteREADONLY (userAddress) = {
476529 let endHeight = (startHeight + votingDuration)
477530 let gwxAmountAtEnd = getUserGwxAmountAtHeight(userAddress, endHeight)
478531 $Tuple2(nil, gwxAmountAtEnd)
479532 }
480533
481534

github/deemru/w8io/c3f4982 
70.71 ms