tx · FW3zHnV1ArbfWPUQ9LnpjbYyUtVf98jFotirpxFB9rrv

3N9yMmmL5cJ7LJxr8o6GFbKFUbGz4XcAjeg:  -0.01000000 Waves

2022.03.28 10:02 [1983437] smart account 3N9yMmmL5cJ7LJxr8o6GFbKFUbGz4XcAjeg > SELF 0.00000000 Waves

{ "type": 13, "id": "FW3zHnV1ArbfWPUQ9LnpjbYyUtVf98jFotirpxFB9rrv", "fee": 1000000, "feeAssetId": null, "timestamp": 1648450967608, "version": 2, "chainId": 84, "sender": "3N9yMmmL5cJ7LJxr8o6GFbKFUbGz4XcAjeg", "senderPublicKey": "C2aAS9D6FqfbrkCuCQCtPWAiopjyagvitFLjRuLcRPYt", "proofs": [ "3eszXbE8G9keoHAAHgXnzEndUNwHs4BzLi6yijrbbA2LkmjLt72ECF6BWqZn9WCYFtjsyDXFXDQHXF3d94MDL8Gt" ], "script": "base64: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ABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABB0AAAACBQAAAAR0aGlzBQAAAANrZXkJAAEsAAAAAgUAAAADa2V5AgAAAA8gaXMgbm90IGRlZmluZWQAAAAACWZlZUFtb3VudAkBAAAAEGdldEludGVnZXJPckZhaWwAAAABBQAAAAxrZXlGZWVBbW91bnQAAAAACXd4QXNzZXRJZAkAAlkAAAABCQEAAAAPZ2V0U3RyaW5nT3JGYWlsAAAAAQUAAAAMa2V5V3hBc3NldElkAAAAAA92b3RpbmdUaHJlc2hvbGQJAQAAABBnZXRJbnRlZ2VyT3JGYWlsAAAAAQUAAAASa2V5Vm90aW5nVGhyZXNob2xkAAAAAA52b3RpbmdEdXJhdGlvbgkBAAAAEGdldEludGVnZXJPckZhaWwAAAABBQAAABFrZXlWb3RpbmdEdXJhdGlvbgAAAAAVdm90ZUJlZm9yZUVsaW1pbmF0aW9uCQEAAAAQZ2V0SW50ZWdlck9yRmFpbAAAAAEFAAAAGGtleVZvdGVCZWZvcmVFbGltaW5hdGlvbgAAAAALc3RhcnRIZWlnaHQJAQAAABBnZXRJbnRlZ2VyT3JGYWlsAAAAAQUAAAAOa2V5U3RhcnRIZWlnaHQAAAAADWN1cnJlbnRQZXJpb2QJAQAAABBnZXRJbnRlZ2VyT3JGYWlsAAAAAQUAAAAQa2V5Q3VycmVudFBlcmlvZAAAAAAQYm9vc3RpbmdDb250cmFjdAkBAAAAEUBleHRyTmF0aXZlKDEwNjIpAAAAAQkBAAAAD2dldFN0cmluZ09yRmFpbAAAAAEFAAAAE2tleUJvb3N0aW5nQ29udHJhY3QAAAAAEGVtaXNzaW9uQ29udHJhY3QJAQAAABFAZXh0ck5hdGl2ZSgxMDYyKQAAAAEJAQAAAA9nZXRTdHJpbmdPckZhaWwAAAABBQAAABNrZXlFbWlzc2lvbkNvbnRyYWN0AAAAABNhc3NldHNTdG9yZUNvbnRyYWN0CQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABCQEAAAAPZ2V0U3RyaW5nT3JGYWlsAAAAAQUAAAAWa2V5QXNzZXRzU3RvcmVDb250cmFjdAAAAAAIbWF4RGVwdGgJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQfAAAAAQUAAAALa2V5TWF4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AAIFAAAACGxpc3ROYW1lBQAAAAJpZAkABEwAAAACCQEAAAALRGVsZXRlRW50cnkAAAABCQEAAAALa2V5TGlzdE5leHQAAAACBQAAAAhsaXN0TmFtZQkBAAAABXZhbHVlAAAAAQUAAAAEcHJldgUAAAADbmlsAwkAAAAAAAACBQAAAAJpZAUAAAAEaGVhZAkABEwAAAACCQEAAAALRGVsZXRlRW50cnkAAAABCQEAAAALa2V5TGlzdEhlYWQAAAABBQAAAAhsaXN0TmFtZQUAAAADbmlsCQAAAgAAAAECAAAADEludmFsaWQgbm9kZQEAAAALcHJvY2Vzc1ZvdGUAAAAEAAAAB2Fzc2V0SWQAAAARdXNlckFkZHJlc3NPclVuaXQAAAAXbGF0ZXN0UHJvY2Vzc2VkQXNzZXRLZXkAAAAWbGF0ZXN0UHJvY2Vzc2VkVXNlcktleQQAAAAgdXBkYXRlTGF0ZXN0UHJvY2Vzc2VkQXNzZXRBY3Rpb24JAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAAF2xhdGVzdFByb2Nlc3NlZEFzc2V0S2V5BQAAAAdhc3NldElkBAAAAB9kZWxldGVMYXRlc3RQcm9jZXNzZWRVc2VyQWN0aW9uCQEAAAALRGVsZXRlRW50cnkAAAABBQAAABZsYXRlc3RQcm9jZXNzZWRVc2VyS2V5AwkAAAAAAAACBQAAABF1c2VyQWRkcmVzc09yVW5pdAUAAAAEdW5pdAkABEwAAAACBQAAACB1cGRhdGVMYXRlc3RQcm9jZXNzZWRBc3NldEFjdGlvbgkABEwAAAACBQAAAB9kZWxldGVMYXRlc3RQcm9jZXNzZWRVc2VyQWN0aW9uBQAAAANuaWwEAAAACWVuZEhlaWdodAkAAGQAAAACBQAAAAtzdGFydEhlaWdodAUAAAAOdm90aW5nRHVyYXRpb24EAAAAC3VzZXJBZGRyZXNzCQEAAAAFdmFsdWUAAAABBQAAABF1c2VyQWRkcmVzc09yVW5pdAQAAAAfdXBkYXRlTGF0ZXN0UHJvY2Vzc2VkVXNlckFjdGlvbgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAAWbGF0ZXN0UHJvY2Vzc2VkVXNlcktleQUAAAALdXNlckFkZHJlc3MEAAAAC3VzZXJWb3RlS2V5CQEAAAATa2V5VXNlclZvdGVCeVBlcmlvZAAAAAMFAAAAC3VzZXJBZGRyZXNzBQAAAAdhc3NldElkBQAAAA1jdXJyZW50UGVyaW9kBAAAAA51c2VyVm90ZU9yVW5pdAkABCIAAAABBQAAAAt1c2VyVm90ZUtleQQAAAAYdXNlckd3eEFtb3VudEF0RW5kSGVpZ2h0CQEAAAAYZ2V0VXNlckd3eEFtb3VudEF0SGVpZ2h0AAAAAgUAAAALdXNlckFkZHJlc3MFAAAACWVuZEhlaWdodAQAAAALdm90ZUFjdGlvbnMDCQAAAAAAAAIFAAAAGHVzZXJHd3hBbW91bnRBdEVuZEhlaWdodAAAAAAAAAAAAAQAAAANdm90ZXNMaXN0TmFtZQkBAAAAEGdldFZvdGVzTGlzdE5hbWUAAAABBQAAAAdhc3NldElkCQEAAAAKZGVsZXRlTm9kZQAAAAIFAAAADXZvdGVzTGlzdE5hbWUFAAAAC3VzZXJBZGRyZXNzAwkAAAAAAAACBQAAAA51c2VyVm90ZU9yVW5pdAUAAAAEdW5pdAQAAAAWdXNlclByZXZpb3VzVm90ZU9yVW5pdAkABCIAAAABCQEAAAATa2V5VXNlclZvdGVCeVBlcmlvZAAAAAMFAAAAC3VzZXJBZGRyZXNzBQAAAAdhc3NldElkCQAAZQAAAAIFAAAADWN1cnJlbnRQZXJpb2QAAAAAAAAAAAEDCQAAAAAAAAIFAAAAFnVzZXJQcmV2aW91c1ZvdGVPclVuaXQFAAAABHVuaXQFAAAAA25pbAQAAAALJHQwOTc5Mjk4NjUJAQAAAA1wYXJzZVVzZXJWb3RlAAAAAQkBAAAABXZhbHVlAAAAAQUAAAAWdXNlclByZXZpb3VzVm90ZU9yVW5pdAQAAAAJcHJldlRvdGFsCAUAAAALJHQwOTc5Mjk4NjUAAAACXzEEAAAAB2luRmF2b3IIBQAAAAskdDA5NzkyOTg2NQAAAAJfMgQAAAAFdG90YWwJAAGXAAAAAQkABEwAAAACBQAAAAlwcmV2VG90YWwJAARMAAAAAgUAAAAYdXNlckd3eEFtb3VudEF0RW5kSGVpZ2h0BQAAAANuaWwJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAALdXNlclZvdGVLZXkJAQAAAA5mb3JtYXRVc2VyVm90ZQAAAAIFAAAABXRvdGFsBQAAAAdpbkZhdm9yCQAETAAAAAIJAQAAABNnZXRWb3RlUmVzdWx0QWN0aW9uAAAABQUAAAAHYXNzZXRJZAUAAAAFdG90YWwFAAAAB2luRmF2b3IFAAAADWN1cnJlbnRQZXJpb2QFAAAABHVuaXQFAAAAA25pbAUAAAADbmlsCQAETQAAAAIJAARNAAAAAgUAAAALdm90ZUFjdGlvbnMFAAAAIHVwZGF0ZUxhdGVzdFByb2Nlc3NlZEFzc2V0QWN0aW9uBQAAAB91cGRhdGVMYXRlc3RQcm9jZXNzZWRVc2VyQWN0aW9uAQAAABdhc3NldFNob3VsZEJlRWxpbWluYXRlZAAAAAIAAAAHYXNzZXRJZAAAAAZwZXJpb2QJAQAAAAEhAAAAAQkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABCAAAAABCQEAAAAYa2V5QXNzZXRWZXJpZmllZEJ5UGVyaW9kAAAAAgUAAAAHYXNzZXRJZAUAAAAGcGVyaW9kBgEAAAAQZWxpbWluYXRpb25DaGVjawAAAAEAAAAHYXNzZXRJZAMDCQEAAAAXYXNzZXRTaG91bGRCZUVsaW1pbmF0ZWQAAAACBQAAAAdhc3NldElkCQAAZQAAAAIFAAAADWN1cnJlbnRQZXJpb2QAAAAAAAAAAAEJAQAAABdhc3NldFNob3VsZEJlRWxpbWluYXRlZAAAAAIFAAAAB2Fzc2V0SWQJAABlAAAAAgUAAAANY3VycmVudFBlcmlvZAAAAAAAAAAAAgcJAQAAABdhc3NldFNob3VsZEJlRWxpbWluYXRlZAAAAAIFAAAAB2Fzc2V0SWQJAABlAAAAAgUAAAANY3VycmVudFBlcmlvZAAAAAAAAAAAAwcAAAAOAAAAAWkBAAAAC2NvbnN0cnVjdG9yAAAACgAAABNib29zdGluZ0NvbnRyYWN0UHJtAAAAE2VtaXNzaW9uQ29udHJhY3RQcm0AAAAWYXNzZXRzU3RvcmVDb250cmFjdFBybQAAAAxmZWVBbW91bnRQcm0AAAAMd3hBc3NldElkUHJtAAAAEnZvdGluZ1RocmVzaG9sZFBybQAAABF2b3RpbmdEdXJhdGlvblBybQAAABh2b3RlQmVmb3JlRWxpbWluYXRpb25Qcm0AAAAOc3RhcnRIZWlnaHRQcm0AAAALbWF4RGVwdGhQcm0EAAAABmNoZWNrcwkABEwAAAACCQEAAAAIdGhpc09ubHkAAAABBQAAAAFpCQAETAAAAAIDCQEAAAAJaXNEZWZpbmVkAAAAAQkABCYAAAABBQAAABNib29zdGluZ0NvbnRyYWN0UHJtBgkAAAIAAAABAgAAACFJbnZhbGlkIGJvb3N0aW5nIGNvbnRyYWN0IGFkZHJlc3MJAARMAAAAAgMJAQAAAAlpc0RlZmluZWQAAAABCQAEJgAAAAEFAAAAE2VtaXNzaW9uQ29udHJhY3RQcm0GCQAAAgAAAAECAAAAIUludmFsaWQgZW1pc3Npb24gY29udHJhY3QgYWRkcmVzcwkABEwAAAACAwkBAAAACWlzRGVmaW5lZAAAAAEJAAQmAAAAAQUAAAAWYXNzZXRzU3RvcmVDb250cmFjdFBybQYJAAACAAAAAQIAAAAkSW52YWxpZCBhc3NldF9zdG9yZSBjb250cmFjdCBhZGRyZXNzCQAETAAAAAIDCQAAZwAAAAIFAAAADGZlZUFtb3VudFBybQAAAAAAAAAAAAYJAAACAAAAAQIAAAASSW52YWxpZCBmZWUgYW1vdW50CQAETAAAAAIDCQEAAAAJaXNEZWZpbmVkAAAAAQkAA+wAAAABCQACWQAAAAEFAAAADHd4QXNzZXRJZFBybQYJAAACAAAAAQIAAAATSW52YWxpZCBXWCBhc3NldCBJRAkABEwAAAACAwkAAGcAAAACBQAAABJ2b3RpbmdUaHJlc2hvbGRQcm0AAAAAAAAAAAAGCQAAAgAAAAECAAAAGEludmFsaWQgdm90aW5nIHRocmVzaG9sZAkABEwAAAACAwkAAGYAAAACBQAAABF2b3RpbmdEdXJhdGlvblBybQAAAAAAAAAAAAYJAAACAAAAAQIAAAAXSW52YWxpZCB2b3RpbmcgZHVyYXRpb24JAARMAAAAAgMJAABmAAAAAgkAAGQAAAACBQAAAA5zdGFydEhlaWdodFBybQUAAAARdm90aW5nRHVyYXRpb25Qcm0FAAAABmhlaWdodAYJAAACAAAAAQIAAAAUSW52YWxpZCBzdGFydCBoZWlnaHQFAAAAA25pbAMJAAAAAAAAAgUAAAAGY2hlY2tzBQAAAAZjaGVja3MJAAUUAAAAAgkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAABNrZXlCb29zdGluZ0NvbnRyYWN0BQAAABNib29zdGluZ0NvbnRyYWN0UHJtCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAAE2tleUVtaXNzaW9uQ29udHJhY3QFAAAAE2VtaXNzaW9uQ29udHJhY3RQcm0JAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAAWa2V5QXNzZXRzU3RvcmVDb250cmFjdAUAAAAWYXNzZXRzU3RvcmVDb250cmFjdFBybQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAMa2V5RmVlQW1vdW50BQAAAAxmZWVBbW91bnRQcm0JAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAAMa2V5V3hBc3NldElkBQAAAAx3eEFzc2V0SWRQcm0JAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAEmtleVZvdGluZ1RocmVzaG9sZAUAAAASdm90aW5nVGhyZXNob2xkUHJtCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABFrZXlWb3RpbmdEdXJhdGlvbgUAAAARdm90aW5nRHVyYXRpb25Qcm0JAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAGGtleVZvdGVCZWZvcmVFbGltaW5hdGlvbgUAAAAYdm90ZUJlZm9yZUVsaW1pbmF0aW9uUHJtCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAA5rZXlTdGFydEhlaWdodAUAAAAOc3RhcnRIZWlnaHRQcm0JAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAEGtleUN1cnJlbnRQZXJpb2QAAAAAAAAAAAAJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAC2tleU1heERlcHRoBQAAAAttYXhEZXB0aFBybQUAAAADbmlsBQAAAAR1bml0CQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgAAAAFpAQAAAAdzdWdnZXN0AAAAAgAAAAdhc3NldElkAAAACmFzc2V0SW1hZ2UEAAAABGluZm8JAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkAA+wAAAABCQACWQAAAAEFAAAAB2Fzc2V0SWQCAAAAEEludmFsaWQgYXNzZXQgSUQEAAAAB3BheW1lbnQJAQAAAAV2YWx1ZQAAAAEJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAEAAAABmNoZWNrcwkABEwAAAACAwkAAAAAAAACCAUAAAAEaW5mbwAAAAZpc3N1ZXIIBQAAAAFpAAAABmNhbGxlcgYJAAACAAAAAQIAAAApQXNzZXQgY2FuIG9ubHkgYmUgc3VnZ2VzdGVkIGJ5IGl0cyBpc3N1ZXIJAARMAAAAAgMJAAAAAAAAAgkBAAAABXZhbHVlAAAAAQgFAAAAB3BheW1lbnQAAAAHYXNzZXRJZAUAAAAJd3hBc3NldElkBgkAAAIAAAABAgAAABFJbnZhbGlkIGZlZSBhc3NldAkABEwAAAACAwkAAAAAAAACCAUAAAAHcGF5bWVudAAAAAZhbW91bnQFAAAACWZlZUFtb3VudAYJAAACAAAAAQIAAAASSW52YWxpZCBmZWUgYW1vdW50BQAAAANuaWwDCQAAAAAAAAIFAAAABmNoZWNrcwUAAAAGY2hlY2tzBAAAABxhc3NldHNTdG9yZUNyZWF0ZU9yVXBkYXRlSW52CQAD/AAAAAQFAAAAE2Fzc2V0c1N0b3JlQ29udHJhY3QCAAAADmNyZWF0ZU9yVXBkYXRlCQAETAAAAAIFAAAAB2Fzc2V0SWQJAARMAAAAAgIAAAAACQAETAAAAAIFAAAACmFzc2V0SW1hZ2UJAARMAAAAAgcFAAAAA25pbAUAAAADbmlsAwkAAAAAAAACBQAAABxhc3NldHNTdG9yZUNyZWF0ZU9yVXBkYXRlSW52BQAAABxhc3NldHNTdG9yZUNyZWF0ZU9yVXBkYXRlSW52BAAAAApidXJuRmVlSW52CQAD/AAAAAQFAAAAEGVtaXNzaW9uQ29udHJhY3QCAAAABGJ1cm4FAAAAA25pbAkABEwAAAACCQEAAAAPQXR0YWNoZWRQYXltZW50AAAAAggFAAAAB3BheW1lbnQAAAAHYXNzZXRJZAgFAAAAB3BheW1lbnQAAAAGYW1vdW50BQAAAANuaWwDCQAAAAAAAAIFAAAACmJ1cm5GZWVJbnYFAAAACmJ1cm5GZWVJbnYEAAAAD2FkZEFzc2V0QWN0aW9ucwkBAAAACmluc2VydE5vZGUAAAACBQAAAA5hc3NldHNMaXN0TmFtZQUAAAAHYXNzZXRJZAkABRQAAAACCQAETQAAAAIFAAAAD2FkZEFzc2V0QWN0aW9ucwkBAAAAE2dldFZvdGVSZXN1bHRBY3Rpb24AAAAFBQAAAAdhc3NldElkAAAAAAAAAAAABgUAAAANY3VycmVudFBlcmlvZAcFAAAABHVuaXQJAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAABaQEAAAAEdm90ZQAAAAIAAAAHYXNzZXRJZAAAAAdpbkZhdm9yBAAAAAllbmRIZWlnaHQJAABkAAAAAgUAAAALc3RhcnRIZWlnaHQFAAAADnZvdGluZ0R1cmF0aW9uBAAAAApjaGVja0Fzc2V0AwkBAAAADGNvbnRhaW5zTm9kZQAAAAIFAAAADmFzc2V0c0xpc3ROYW1lBQAAAAdhc3NldElkBgkAAAIAAAABAgAAAA1JbnZhbGlkIGFzc2V0AwkAAAAAAAACBQAAAApjaGVja0Fzc2V0BQAAAApjaGVja0Fzc2V0BAAAAAtjaGVja0hlaWdodAMJAABmAAAAAgUAAAAJZW5kSGVpZ2h0BQAAAAZoZWlnaHQGCQAAAgAAAAECAAAANEN1cnJlbnQgdm90aW5nIGlzIG92ZXIgYnV0IHJlc3VsdHMgYXJlIG5vdCBmaW5hbGl6ZWQDCQAAAAAAAAIFAAAAC2NoZWNrSGVpZ2h0BQAAAAtjaGVja0hlaWdodAQAAAALdXNlckFkZHJlc3MJAAQlAAAAAQgFAAAAAWkAAAAGY2FsbGVyBAAAAA5nd3hBbW91bnRBdEVuZAkBAAAAGGdldFVzZXJHd3hBbW91bnRBdEhlaWdodAAAAAIFAAAAC3VzZXJBZGRyZXNzBQAAAAllbmRIZWlnaHQEAAAAE2NoZWNrR3d4QW1vdW50QXRFbmQDCQAAZgAAAAIFAAAADmd3eEFtb3VudEF0RW5kAAAAAAAAAAAABgkAAAIAAAABAgAAAChZb3UnbGwgbm90IGhhdmUgZ1dYIGF0IHRoZSBlbmQgb2Ygdm90aW5nAwkAAAAAAAACBQAAABNjaGVja0d3eEFtb3VudEF0RW5kBQAAABNjaGVja0d3eEFtb3VudEF0RW5kBAAAAA12b3Rlc0xpc3ROYW1lCQEAAAAQZ2V0Vm90ZXNMaXN0TmFtZQAAAAEFAAAAB2Fzc2V0SWQEAAAAC3VzZXJWb3RlS2V5CQEAAAATa2V5VXNlclZvdGVCeVBlcmlvZAAAAAMFAAAAC3VzZXJBZGRyZXNzBQAAAAdhc3NldElkBQAAAA1jdXJyZW50UGVyaW9kBAAAAA91c2VyVm90ZUFjdGlvbnMJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAALdXNlclZvdGVLZXkJAQAAAA5mb3JtYXRVc2VyVm90ZQAAAAIFAAAADmd3eEFtb3VudEF0RW5kBQAAAAdpbkZhdm9yCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAABJrZXlVc2VyVm90ZUhpc3RvcnkAAAAFAgAAAAR2b3RlBQAAAAt1c2VyQWRkcmVzcwUAAAAHYXNzZXRJZAkAAlgAAAABCAUAAAABaQAAAA10cmFuc2FjdGlvbklkBQAAAA1jdXJyZW50UGVyaW9kCQEAAAAOZm9ybWF0VXNlclZvdGUAAAACBQAAAA5nd3hBbW91bnRBdEVuZAUAAAAHaW5GYXZvcgkABEwAAAACCQEAAAATZ2V0Vm90ZVJlc3VsdEFjdGlvbgAAAAUFAAAAB2Fzc2V0SWQFAAAADmd3eEFtb3VudEF0RW5kBQAAAAdpbkZhdm9yBQAAAA1jdXJyZW50UGVyaW9kBQAAAAR1bml0BQAAAANuaWwEAAAAEHZvdGVzTGlzdEFjdGlvbnMDCQEAAAAMY29udGFpbnNOb2RlAAAAAgUAAAANdm90ZXNMaXN0TmFtZQUAAAALdXNlckFkZHJlc3MFAAAAA25pbAkBAAAACmluc2VydE5vZGUAAAACBQAAAA12b3Rlc0xpc3ROYW1lBQAAAAt1c2VyQWRkcmVzcwkABRQAAAACCQAETgAAAAIFAAAAEHZvdGVzTGlzdEFjdGlvbnMFAAAAD3VzZXJWb3RlQWN0aW9ucwUAAAAEdW5pdAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgAAAAFpAQAAAApjYW5jZWxWb3RlAAAAAQAAAAdhc3NldElkBAAAAAt1c2VyQWRkcmVzcwkABCUAAAABCAUAAAABaQAAAAZjYWxsZXIEAAAADXZvdGVzTGlzdE5hbWUJAQAAABBnZXRWb3Rlc0xpc3ROYW1lAAAAAQUAAAAHYXNzZXRJZAQAAAALdXNlclZvdGVLZXkJAQAAABNrZXlVc2VyVm90ZUJ5UGVyaW9kAAAAAwUAAAALdXNlckFkZHJlc3MFAAAAB2Fzc2V0SWQFAAAADWN1cnJlbnRQZXJpb2QEAAAADnVzZXJWb3RlT3JVbml0CQAEIgAAAAEFAAAAC3VzZXJWb3RlS2V5BAAAAAljaGVja1ZvdGUJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQiAAAAAQUAAAALdXNlclZvdGVLZXkCAAAAEU5vdGhpbmcgdG8gY2FuY2VsAwkAAAAAAAACBQAAAAljaGVja1ZvdGUFAAAACWNoZWNrVm90ZQQAAAANJHQwMTQ5ODExNTA0MgkBAAAADXBhcnNlVXNlclZvdGUAAAABCQEAAAAFdmFsdWUAAAABBQAAAA51c2VyVm90ZU9yVW5pdAQAAAAFdG90YWwIBQAAAA0kdDAxNDk4MTE1MDQyAAAAAl8xBAAAAAdpbkZhdm9yCAUAAAANJHQwMTQ5ODExNTA0MgAAAAJfMgQAAAAQdm90ZXNMaXN0QWN0aW9ucwkBAAAACmRlbGV0ZU5vZGUAAAACBQAAAA12b3Rlc0xpc3ROYW1lBQAAAAt1c2VyQWRkcmVzcwQAAAAPdXNlclZvdGVBY3Rpb25zCQAETAAAAAIJAQAAAAtEZWxldGVFbnRyeQAAAAEFAAAAC3VzZXJWb3RlS2V5CQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAABJrZXlVc2VyVm90ZUhpc3RvcnkAAAAFAgAAAApjYW5jZWxWb3RlBQAAAAt1c2VyQWRkcmVzcwUAAAAHYXNzZXRJZAkAAlgAAAABCAUAAAABaQAAAA10cmFuc2FjdGlvbklkBQAAAA1jdXJyZW50UGVyaW9kCQEAAAAOZm9ybWF0VXNlclZvdGUAAAACAAAAAAAAAAAABgkABEwAAAACCQEAAAATZ2V0Vm90ZVJlc3VsdEFjdGlvbgAAAAUFAAAAB2Fzc2V0SWQJAQAAAAEtAAAAAQUAAAAFdG90YWwFAAAAB2luRmF2b3IFAAAADWN1cnJlbnRQZXJpb2QFAAAABHVuaXQFAAAAA25pbAkABRQAAAACCQAETgAAAAIFAAAAEHZvdGVzTGlzdEFjdGlvbnMFAAAAD3VzZXJWb3RlQWN0aW9ucwUAAAAEdW5pdAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAABaQEAAAAVZmluYWxpemVBc3NldElOVEVSTkFMAAAAAgAAAAdhc3NldElkAAAABnBlcmlvZAQAAAALY2hlY2tDYWxsZXIJAQAAAAh0aGlzT25seQAAAAEFAAAAAWkDCQAAAAAAAAIFAAAAC2NoZWNrQ2FsbGVyBQAAAAtjaGVja0NhbGxlcgQAAAANdm90ZVJlc3VsdEtleQkBAAAAFWtleVZvdGVSZXN1bHRCeVBlcmlvZAAAAAIFAAAAB2Fzc2V0SWQFAAAABnBlcmlvZAQAAAANJHQwMTU3MDIxNTg3NQQAAAAHJG1hdGNoMAkABCIAAAABBQAAAA12b3RlUmVzdWx0S2V5AwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAAZTdHJpbmcEAAAAAXMFAAAAByRtYXRjaDAEAAAAAXIJAQAAAA9wYXJzZVZvdGVSZXN1bHQAAAABBQAAAAFzCQAFFAAAAAIIBQAAAAFyAAAAAl8xCAUAAAABcgAAAAJfMgMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAEVW5pdAkABRQAAAACAAAAAAAAAAAAAAAAAAAAAAAACQAAAgAAAAECAAAAC01hdGNoIGVycm9yBAAAAAh0b3RhbFllcwgFAAAADSR0MDE1NzAyMTU4NzUAAAACXzEEAAAAB3RvdGFsTm8IBQAAAA0kdDAxNTcwMjE1ODc1AAAAAl8yBAAAAAV0b3RhbAkAAGQAAAACBQAAAAh0b3RhbFllcwUAAAAHdG90YWxObwQAAAAIdmVyaWZpZWQDCQAAZwAAAAIFAAAABXRvdGFsBQAAAA92b3RpbmdUaHJlc2hvbGQJAABmAAAAAgUAAAAIdG90YWxZZXMFAAAAB3RvdGFsTm8HBAAAABNhc3NldFZlcmlmaWVkQWN0aW9uCQAETAAAAAIJAQAAAAxCb29sZWFuRW50cnkAAAACCQEAAAAYa2V5QXNzZXRWZXJpZmllZEJ5UGVyaW9kAAAAAgUAAAAHYXNzZXRJZAUAAAAGcGVyaW9kBQAAAAh2ZXJpZmllZAUAAAADbmlsBAAAABlhc3NldHNTdG9yZVNldFZlcmlmaWVkSW52CQAD/AAAAAQFAAAAE2Fzc2V0c1N0b3JlQ29udHJhY3QCAAAAC3NldFZlcmlmaWVkCQAETAAAAAIFAAAAB2Fzc2V0SWQJAARMAAAAAgUAAAAIdmVyaWZpZWQFAAAAA25pbAUAAAADbmlsAwkAAAAAAAACBQAAABlhc3NldHNTdG9yZVNldFZlcmlmaWVkSW52BQAAABlhc3NldHNTdG9yZVNldFZlcmlmaWVkSW52BAAAAAllbGltaW5hdGUDBQAAAAh2ZXJpZmllZAcJAQAAABBlbGltaW5hdGlvbkNoZWNrAAAAAQUAAAAHYXNzZXRJZAQAAAARdm90ZVJlc3VsdEFjdGlvbnMDBQAAAAllbGltaW5hdGUFAAAAA25pbAkABEwAAAACCQEAAAATZ2V0Vm90ZVJlc3VsdEFjdGlvbgAAAAUFAAAAB2Fzc2V0SWQAAAAAAAAAAAAGCQAAZAAAAAIFAAAADWN1cnJlbnRQZXJpb2QAAAAAAAAAAAEFAAAACHZlcmlmaWVkBQAAAANuaWwEAAAAEHZvdGVzTGlzdEFjdGlvbnMDBQAAAAllbGltaW5hdGUJAQAAAApkZWxldGVOb2RlAAAAAgUAAAAOYXNzZXRzTGlzdE5hbWUFAAAAB2Fzc2V0SWQFAAAAA25pbAkABRQAAAACCQAETgAAAAIJAAROAAAAAgUAAAAQdm90ZXNMaXN0QWN0aW9ucwUAAAARdm90ZVJlc3VsdEFjdGlvbnMFAAAAE2Fzc2V0VmVyaWZpZWRBY3Rpb24FAAAABHVuaXQJAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgAAAAFpAQAAABRmaW5hbGl6ZVZvdGluZ0hlbHBlcgAAAAAEAAAACWVuZEhlaWdodAkAAGQAAAACBQAAAAtzdGFydEhlaWdodAUAAAAOdm90aW5nRHVyYXRpb24DCQAAZgAAAAIFAAAACWVuZEhlaWdodAUAAAAGaGVpZ2h0CQAFFAAAAAIFAAAAA25pbAcEAAAAGmxhdGVzdFByb2Nlc3NlZEFzc2V0T3JVbml0CQAEIgAAAAEFAAAAF2tleUxhdGVzdFByb2Nlc3NlZEFzc2V0BAAAABlsYXRlc3RQcm9jZXNzZWRVc2VyT3JVbml0CQAEIgAAAAEFAAAAFmtleUxhdGVzdFByb2Nlc3NlZFVzZXIEAAAAD25leHRQZXJpb2REZWxheQAAAAAAAAAAAAQAAAAGZmluaXNoCQAFFAAAAAIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAADmtleVN0YXJ0SGVpZ2h0CQAAZAAAAAIFAAAABmhlaWdodAUAAAAPbmV4dFBlcmlvZERlbGF5CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABBrZXlDdXJyZW50UGVyaW9kCQAAZAAAAAIFAAAADWN1cnJlbnRQZXJpb2QAAAAAAAAAAAEJAARMAAAAAgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQUAAAAXa2V5TGF0ZXN0UHJvY2Vzc2VkQXNzZXQJAARMAAAAAgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQUAAAAWa2V5TGF0ZXN0UHJvY2Vzc2VkVXNlcgkABEwAAAACCQEAAAALRGVsZXRlRW50cnkAAAABBQAAAB9rZXlMYXRlc3RQcm9jZXNzZWRBc3NldFRyYW5zZmVyCQAETAAAAAIJAQAAAAtEZWxldGVFbnRyeQAAAAEFAAAAHmtleUxhdGVzdFByb2Nlc3NlZFVzZXJUcmFuc2ZlcgUAAAADbmlsBgMJAAAAAAAAAgUAAAAabGF0ZXN0UHJvY2Vzc2VkQXNzZXRPclVuaXQFAAAABHVuaXQEAAAAEGFzc2V0c0hlYWRPclVuaXQJAAQiAAAAAQkBAAAAC2tleUxpc3RIZWFkAAAAAQUAAAAOYXNzZXRzTGlzdE5hbWUDCQAAAAAAAAIFAAAAEGFzc2V0c0hlYWRPclVuaXQFAAAABHVuaXQFAAAABmZpbmlzaAQAAAAFYXNzZXQJAQAAAAV2YWx1ZQAAAAEFAAAAEGFzc2V0c0hlYWRPclVuaXQEAAAAEXVzZXJBZGRyZXNzT3JVbml0CQAEIgAAAAEJAQAAAAtrZXlMaXN0SGVhZAAAAAEJAQAAABBnZXRWb3Rlc0xpc3ROYW1lAAAAAQUAAAAFYXNzZXQEAAAAEnByb2Nlc3NWb3RlQWN0aW9ucwkBAAAAC3Byb2Nlc3NWb3RlAAAABAUAAAAFYXNzZXQFAAAAEXVzZXJBZGRyZXNzT3JVbml0BQAAABdrZXlMYXRlc3RQcm9jZXNzZWRBc3NldAUAAAAWa2V5TGF0ZXN0UHJvY2Vzc2VkVXNlcgkABRQAAAACBQAAABJwcm9jZXNzVm90ZUFjdGlvbnMGBAAAABRsYXRlc3RQcm9jZXNzZWRBc3NldAkBAAAABXZhbHVlAAAAAQUAAAAabGF0ZXN0UHJvY2Vzc2VkQXNzZXRPclVuaXQDCQAAAAAAAAIFAAAAGWxhdGVzdFByb2Nlc3NlZFVzZXJPclVuaXQFAAAABHVuaXQEAAAAC2Fzc2V0T3JVbml0CQAEIgAAAAEJAQAAAAtrZXlMaXN0TmV4dAAAAAIFAAAADmFzc2V0c0xpc3ROYW1lBQAAABRsYXRlc3RQcm9jZXNzZWRBc3NldAMJAAAAAAAAAgUAAAALYXNzZXRPclVuaXQFAAAAC2Fzc2V0T3JVbml0BAAAABBmaW5hbGl6ZUFzc2V0SW52CQAD/AAAAAQFAAAABHRoaXMCAAAAFWZpbmFsaXplQXNzZXRJTlRFUk5BTAkABEwAAAACBQAAABRsYXRlc3RQcm9jZXNzZWRBc3NldAkABEwAAAACBQAAAA1jdXJyZW50UGVyaW9kBQAAAANuaWwFAAAAA25pbAMJAAAAAAAAAgUAAAAQZmluYWxpemVBc3NldEludgUAAAAQZmluYWxpemVBc3NldEludgMJAAAAAAAAAgUAAAALYXNzZXRPclVuaXQFAAAABHVuaXQFAAAABmZpbmlzaAQAAAAFYXNzZXQJAQAAAAV2YWx1ZQAAAAEFAAAAC2Fzc2V0T3JVbml0BAAAABF1c2VyQWRkcmVzc09yVW5pdAkABCIAAAABCQEAAAALa2V5TGlzdEhlYWQAAAABCQEAAAAQZ2V0Vm90ZXNMaXN0TmFtZQAAAAEFAAAABWFzc2V0BAAAABJwcm9jZXNzVm90ZUFjdGlvbnMJAQAAAAtwcm9jZXNzVm90ZQAAAAQFAAAABWFzc2V0BQAAABF1c2VyQWRkcmVzc09yVW5pdAUAAAAXa2V5TGF0ZXN0UHJvY2Vzc2VkQXNzZXQFAAAAFmtleUxhdGVzdFByb2Nlc3NlZFVzZXIJAAUUAAAAAgUAAAAScHJvY2Vzc1ZvdGVBY3Rpb25zBgkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBAAAABNsYXRlc3RQcm9jZXNzZWRVc2VyCQEAAAAFdmFsdWUAAAABBQAAABlsYXRlc3RQcm9jZXNzZWRVc2VyT3JVbml0BAAAABF1c2VyQWRkcmVzc09yVW5pdAkABCIAAAABCQEAAAALa2V5TGlzdE5leHQAAAACCQEAAAAQZ2V0Vm90ZXNMaXN0TmFtZQAAAAEFAAAAFGxhdGVzdFByb2Nlc3NlZEFzc2V0BQAAABNsYXRlc3RQcm9jZXNzZWRVc2VyBAAAABJwcm9jZXNzVm90ZUFjdGlvbnMJAQAAAAtwcm9jZXNzVm90ZQAAAAQFAAAAFGxhdGVzdFByb2Nlc3NlZEFzc2V0BQAAABF1c2VyQWRkcmVzc09yVW5pdAUAAAAXa2V5TGF0ZXN0UHJvY2Vzc2VkQXNzZXQFAAAAFmtleUxhdGVzdFByb2Nlc3NlZFVzZXIJAAUUAAAAAgUAAAAScHJvY2Vzc1ZvdGVBY3Rpb25zBgAAAAFpAQAAABVmaW5hbGl6ZVZvdGluZ1dyYXBwZXIAAAABAAAAB2NvdW50ZXIEAAAABnJlc3VsdAkBAAAABmFzQm9vbAAAAAEJAAP8AAAABAUAAAAEdGhpcwIAAAAUZmluYWxpemVWb3RpbmdIZWxwZXIFAAAAA25pbAUAAAADbmlsAwkAAAAAAAACBQAAAAZyZXN1bHQFAAAABnJlc3VsdAMJAQAAAAEhAAAAAQUAAAAGcmVzdWx0AwkAAAAAAAACBQAAAAdjb3VudGVyAAAAAAAAAAAACQAAAgAAAAECAAAAHkN1cnJlbnQgdm90aW5nIGlzIG5vdCBvdmVyIHlldAkABRQAAAACBQAAAANuaWwFAAAABHVuaXQDCQAAZgAAAAIFAAAACG1heERlcHRoBQAAAAdjb3VudGVyBAAAAANpbnYJAAP8AAAABAUAAAAEdGhpcwIAAAAVZmluYWxpemVWb3RpbmdXcmFwcGVyCQAETAAAAAIJAABkAAAAAgUAAAAHY291bnRlcgAAAAAAAAAAAQUAAAADbmlsBQAAAANuaWwDCQAAAAAAAAIFAAAAA2ludgUAAAADaW52CQAFFAAAAAIFAAAAA25pbAUAAAAEdW5pdAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAUUAAAAAgUAAAADbmlsBQAAAAR1bml0CQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgAAAAFpAQAAAA5maW5hbGl6ZVZvdGluZwAAAAAEAAAAA2ludgkAA/wAAAAEBQAAAAR0aGlzAgAAABVmaW5hbGl6ZVZvdGluZ1dyYXBwZXIJAARMAAAAAgAAAAAAAAAAAAUAAAADbmlsBQAAAANuaWwDCQAAAAAAAAIFAAAAA2ludgUAAAADaW52CQAFFAAAAAIFAAAAA25pbAUAAAAEdW5pdAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAABaQEAAAATdHJhbnNmZXJWb3Rlc0hlbHBlcgAAAAAEAAAAGHZvdGVzVHJhbnNmZXJGaW5pc2hlZEtleQkBAAAAIGtleVZvdGVzVHJhbnNmZXJGaW5pc2hlZEJ5UGVyaW9kAAAAAQUAAAANY3VycmVudFBlcmlvZAQAAAAVdm90ZXNUcmFuc2ZlckZpbmlzaGVkCQEAAAALdmFsdWVPckVsc2UAAAACCQAEIAAAAAEFAAAAGHZvdGVzVHJhbnNmZXJGaW5pc2hlZEtleQcEAAAACWVuZEhlaWdodAkAAGQAAAACBQAAAAtzdGFydEhlaWdodAUAAAAOdm90aW5nRHVyYXRpb24DAwMJAABmAAAAAgUAAAALc3RhcnRIZWlnaHQFAAAABmhlaWdodAYJAABnAAAAAgUAAAAGaGVpZ2h0BQAAAAllbmRIZWlnaHQGBQAAABV2b3Rlc1RyYW5zZmVyRmluaXNoZWQJAAUUAAAAAgUAAAADbmlsBwQAAAAabGF0ZXN0UHJvY2Vzc2VkQXNzZXRPclVuaXQJAAQiAAAAAQUAAAAfa2V5TGF0ZXN0UHJvY2Vzc2VkQXNzZXRUcmFuc2ZlcgQAAAAZbGF0ZXN0UHJvY2Vzc2VkVXNlck9yVW5pdAkABCIAAAABBQAAAB5rZXlMYXRlc3RQcm9jZXNzZWRVc2VyVHJhbnNmZXIEAAAABmZpbmlzaAkABRQAAAACCQAETAAAAAIJAQAAAAxCb29sZWFuRW50cnkAAAACBQAAABh2b3Rlc1RyYW5zZmVyRmluaXNoZWRLZXkGCQAETAAAAAIJAQAAAAtEZWxldGVFbnRyeQAAAAEFAAAAH2tleUxhdGVzdFByb2Nlc3NlZEFzc2V0VHJhbnNmZXIJAARMAAAAAgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQUAAAAea2V5TGF0ZXN0UHJvY2Vzc2VkVXNlclRyYW5zZmVyBQAAAANuaWwGAwkAAAAAAAACBQAAABpsYXRlc3RQcm9jZXNzZWRBc3NldE9yVW5pdAUAAAAEdW5pdAQAAAAQYXNzZXRzSGVhZE9yVW5pdAkABCIAAAABCQEAAAALa2V5TGlzdEhlYWQAAAABBQAAAA5hc3NldHNMaXN0TmFtZQMJAAAAAAAAAgUAAAAQYXNzZXRzSGVhZE9yVW5pdAUAAAAEdW5pdAUAAAAGZmluaXNoBAAAAAVhc3NldAkBAAAABXZhbHVlAAAAAQUAAAAQYXNzZXRzSGVhZE9yVW5pdAQAAAARdXNlckFkZHJlc3NPclVuaXQJAAQiAAAAAQkBAAAAC2tleUxpc3RIZWFkAAAAAQkBAAAAEGdldFZvdGVzTGlzdE5hbWUAAAABBQAAAAVhc3NldAQAAAAScHJvY2Vzc1ZvdGVBY3Rpb25zCQEAAAALcHJvY2Vzc1ZvdGUAAAAEBQAAAAVhc3NldAUAAAARdXNlckFkZHJlc3NPclVuaXQFAAAAH2tleUxhdGVzdFByb2Nlc3NlZEFzc2V0VHJhbnNmZXIFAAAAHmtleUxhdGVzdFByb2Nlc3NlZFVzZXJUcmFuc2ZlcgkABRQAAAACBQAAABJwcm9jZXNzVm90ZUFjdGlvbnMGBAAAABRsYXRlc3RQcm9jZXNzZWRBc3NldAkBAAAABXZhbHVlAAAAAQUAAAAabGF0ZXN0UHJvY2Vzc2VkQXNzZXRPclVuaXQDCQAAAAAAAAIFAAAAGWxhdGVzdFByb2Nlc3NlZFVzZXJPclVuaXQFAAAABHVuaXQEAAAAC2Fzc2V0T3JVbml0CQAEIgAAAAEJAQAAAAtrZXlMaXN0TmV4dAAAAAIFAAAADmFzc2V0c0xpc3ROYW1lBQAAABRsYXRlc3RQcm9jZXNzZWRBc3NldAMJAAAAAAAAAgUAAAALYXNzZXRPclVuaXQFAAAABHVuaXQFAAAABmZpbmlzaAQAAAAFYXNzZXQJAQAAAAV2YWx1ZQAAAAEFAAAAC2Fzc2V0T3JVbml0BAAAABF1c2VyQWRkcmVzc09yVW5pdAkABCIAAAABCQEAAAALa2V5TGlzdEhlYWQAAAABCQEAAAAQZ2V0Vm90ZXNMaXN0TmFtZQAAAAEFAAAABWFzc2V0BAAAABJwcm9jZXNzVm90ZUFjdGlvbnMJAQAAAAtwcm9jZXNzVm90ZQAAAAQFAAAABWFzc2V0BQAAABF1c2VyQWRkcmVzc09yVW5pdAUAAAAfa2V5TGF0ZXN0UHJvY2Vzc2VkQXNzZXRUcmFuc2ZlcgUAAAAea2V5TGF0ZXN0UHJvY2Vzc2VkVXNlclRyYW5zZmVyCQAFFAAAAAIFAAAAEnByb2Nlc3NWb3RlQWN0aW9ucwYEAAAAE2xhdGVzdFByb2Nlc3NlZFVzZXIJAQAAAAV2YWx1ZQAAAAEFAAAAGWxhdGVzdFByb2Nlc3NlZFVzZXJPclVuaXQEAAAAEXVzZXJBZGRyZXNzT3JVbml0CQAEIgAAAAEJAQAAAAtrZXlMaXN0TmV4dAAAAAIJAQAAABBnZXRWb3Rlc0xpc3ROYW1lAAAAAQUAAAAUbGF0ZXN0UHJvY2Vzc2VkQXNzZXQFAAAAE2xhdGVzdFByb2Nlc3NlZFVzZXIEAAAAEnByb2Nlc3NWb3RlQWN0aW9ucwkBAAAAC3Byb2Nlc3NWb3RlAAAABAUAAAAUbGF0ZXN0UHJvY2Vzc2VkQXNzZXQFAAAAEXVzZXJBZGRyZXNzT3JVbml0BQAAAB9rZXlMYXRlc3RQcm9jZXNzZWRBc3NldFRyYW5zZmVyBQAAAB5rZXlMYXRlc3RQcm9jZXNzZWRVc2VyVHJhbnNmZXIJAAUUAAAAAgUAAAAScHJvY2Vzc1ZvdGVBY3Rpb25zBgAAAAFpAQAAABR0cmFuc2ZlclZvdGVzV3JhcHBlcgAAAAEAAAAHY291bnRlcgQAAAAGcmVzdWx0CQEAAAAGYXNCb29sAAAAAQkAA/wAAAAEBQAAAAR0aGlzAgAAABN0cmFuc2ZlclZvdGVzSGVscGVyBQAAAANuaWwFAAAAA25pbAMJAAAAAAAAAgUAAAAGcmVzdWx0BQAAAAZyZXN1bHQDCQEAAAABIQAAAAEFAAAABnJlc3VsdAMJAAAAAAAAAgUAAAAHY291bnRlcgAAAAAAAAAAAAkAAAIAAAABAgAAABlWb3RpbmcgaXMgbm90IHN0YXJ0ZWQgeWV0CQAFFAAAAAIFAAAAA25pbAUAAAAEdW5pdAMJAABmAAAAAgUAAAAIbWF4RGVwdGgFAAAAB2NvdW50ZXIEAAAAA2ludgkAA/wAAAAEBQAAAAR0aGlzAgAAABR0cmFuc2ZlclZvdGVzV3JhcHBlcgkABEwAAAACCQAAZAAAAAIFAAAAB2NvdW50ZXIAAAAAAAAAAAEFAAAAA25pbAUAAAADbmlsAwkAAAAAAAACBQAAAANpbnYFAAAAA2ludgkABRQAAAACBQAAAANuaWwFAAAABHVuaXQJAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQAFFAAAAAIFAAAAA25pbAUAAAAEdW5pdAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAABaQEAAAANdHJhbnNmZXJWb3RlcwAAAAAEAAAAA2ludgkAA/wAAAAEBQAAAAR0aGlzAgAAABR0cmFuc2ZlclZvdGVzV3JhcHBlcgkABEwAAAACAAAAAAAAAAAABQAAAANuaWwFAAAAA25pbAMJAAAAAAAAAgUAAAADaW52BQAAAANpbnYJAAUUAAAAAgUAAAADbmlsBQAAAAR1bml0CQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgAAAAFpAQAAABJzZXRWb3RpbmdUaHJlc2hvbGQAAAABAAAADG5ld1RocmVzaG9sZAQAAAALY2hlY2tDYWxsZXIJAQAAAAh0aGlzT25seQAAAAEFAAAAAWkDCQAAAAAAAAIFAAAAC2NoZWNrQ2FsbGVyBQAAAAtjaGVja0NhbGxlcgkABRQAAAACCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABJrZXlWb3RpbmdUaHJlc2hvbGQFAAAADG5ld1RocmVzaG9sZAUAAAADbmlsBQAAAAR1bml0CQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgAAAAFpAQAAAAZzZXRGZWUAAAABAAAABm5ld0ZlZQQAAAALY2hlY2tDYWxsZXIJAQAAAAh0aGlzT25seQAAAAEFAAAAAWkDCQAAAAAAAAIFAAAAC2NoZWNrQ2FsbGVyBQAAAAtjaGVja0NhbGxlcgkABRQAAAACCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAxrZXlGZWVBbW91bnQFAAAABm5ld0ZlZQUAAAADbmlsBQAAAAR1bml0CQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgAAAAFpAQAAABtnd3hBdmFpbGFibGVGb3JWb3RlUkVBRE9OTFkAAAABAAAAC3VzZXJBZGRyZXNzBAAAAAllbmRIZWlnaHQJAABkAAAAAgUAAAALc3RhcnRIZWlnaHQFAAAADnZvdGluZ0R1cmF0aW9uBAAAAA5nd3hBbW91bnRBdEVuZAkBAAAAGGdldFVzZXJHd3hBbW91bnRBdEhlaWdodAAAAAIFAAAAC3VzZXJBZGRyZXNzBQAAAAllbmRIZWlnaHQJAAUUAAAAAgUAAAADbmlsBQAAAA5nd3hBbW91bnRBdEVuZAAAAABXu9Qv", "height": 1983437, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 4Tyo7A6gixTmMsnS1UfWhxWzvoEUWCEStjinyEjmCkUb Next: 9vUSWcpSF7614QcjHSJnyULRdbCjekxd2Fd8yqYPrGzV Diff:
OldNewDifferences
7777 func keyVoteResultByPeriod (assetId,period) = makeString(["%s%d%s", "votingResultAtAsset", toString(period), assetId], separator)
7878
7979
80-func formatVoteResult (totalYes,totalNo) = makeString(["%d%d", toString(totalYes), toString(totalNo)], separator)
80+func formatVoteResult (totalYes,totalNo,verified) = makeString(["%d%d%s", toString(totalYes), toString(totalNo), toString(verified)], separator)
8181
8282
8383 func parseVoteResult (input) = {
8484 let parts = split(input, separator)
8585 let totalYesIdx = 1
8686 let totalNoIdx = 2
87+ let verifiedIdx = 3
8788 let totalYes = parseIntValue(parts[totalYesIdx])
8889 let totalNo = parseIntValue(parts[totalNoIdx])
89- $Tuple2(totalYes, totalNo)
90+ let verified = (parts[verifiedIdx] == "true")
91+ $Tuple3(totalYes, totalNo, verified)
9092 }
9193
9294
180182 }
181183
182184
183-func getVoteResultAction (assetId,total,inFavor,period) = {
185+func getVoteResultAction (assetId,total,inFavor,period,verified) = {
184186 let voteResultKey = keyVoteResultByPeriod(assetId, period)
185- let $t054515583 = match getString(voteResultKey) {
187+ let $t055955898 = match getString(voteResultKey) {
186188 case s: String =>
187189 parseVoteResult(s)
188190 case _: Unit =>
189- $Tuple2(0, 0)
191+ match getString(keyVoteResultByPeriod(assetId, (period - 1))) {
192+ case s: String =>
193+ $Tuple3(0, 0, parseVoteResult(s)._3)
194+ case _: Unit =>
195+ $Tuple3(0, 0, false)
196+ case _ =>
197+ throw("Match error")
198+ }
190199 case _ =>
191200 throw("Match error")
192201 }
193- let totalYes = $t054515583._1
194- let totalNo = $t054515583._2
195- StringEntry(voteResultKey, formatVoteResult((totalYes + (if (inFavor)
202+ let oldTotalYes = $t055955898._1
203+ let oldTotalNo = $t055955898._2
204+ let oldVerified = $t055955898._3
205+ StringEntry(voteResultKey, formatVoteResult((oldTotalYes + (if (inFavor)
196206 then total
197- else 0)), (totalNo + (if (inFavor)
207+ else 0)), (oldTotalNo + (if (inFavor)
198208 then 0
199- else total))))
209+ else total)), if ((verified == unit))
210+ then oldVerified
211+ else value(verified)))
200212 }
201213
202214
268280 if ((userPreviousVoteOrUnit == unit))
269281 then nil
270282 else {
271- let $t093859458 = parseUserVote(value(userPreviousVoteOrUnit))
272- let prevTotal = $t093859458._1
273- let inFavor = $t093859458._2
283+ let $t097929865 = parseUserVote(value(userPreviousVoteOrUnit))
284+ let prevTotal = $t097929865._1
285+ let inFavor = $t097929865._2
274286 let total = min([prevTotal, userGwxAmountAtEndHeight])
275-[StringEntry(userVoteKey, formatUserVote(total, inFavor)), getVoteResultAction(assetId, total, inFavor, currentPeriod)]
287+[StringEntry(userVoteKey, formatUserVote(total, inFavor)), getVoteResultAction(assetId, total, inFavor, currentPeriod, unit)]
276288 }
277289 }
278290 else nil
337349 if ((burnFeeInv == burnFeeInv))
338350 then {
339351 let addAssetActions = insertNode(assetsListName, assetId)
340- $Tuple2((addAssetActions :+ getVoteResultAction(assetId, 0, true, currentPeriod)), unit)
352+ $Tuple2((addAssetActions :+ getVoteResultAction(assetId, 0, true, currentPeriod, false)), unit)
341353 }
342354 else throw("Strict value is not equal to itself.")
343355 }
370382 then {
371383 let votesListName = getVotesListName(assetId)
372384 let userVoteKey = keyUserVoteByPeriod(userAddress, assetId, currentPeriod)
373- let userVoteActions = [StringEntry(userVoteKey, formatUserVote(gwxAmountAtEnd, inFavor)), StringEntry(keyUserVoteHistory("vote", userAddress, assetId, toBase58String(i.transactionId), currentPeriod), formatUserVote(gwxAmountAtEnd, inFavor)), getVoteResultAction(assetId, gwxAmountAtEnd, inFavor, currentPeriod)]
385+ let userVoteActions = [StringEntry(userVoteKey, formatUserVote(gwxAmountAtEnd, inFavor)), StringEntry(keyUserVoteHistory("vote", userAddress, assetId, toBase58String(i.transactionId), currentPeriod), formatUserVote(gwxAmountAtEnd, inFavor)), getVoteResultAction(assetId, gwxAmountAtEnd, inFavor, currentPeriod, unit)]
374386 let votesListActions = if (containsNode(votesListName, userAddress))
375387 then nil
376388 else insertNode(votesListName, userAddress)
394406 let checkVote = valueOrElse(getString(userVoteKey), "Nothing to cancel")
395407 if ((checkVote == checkVote))
396408 then {
397- let $t01455514616 = parseUserVote(value(userVoteOrUnit))
398- let total = $t01455514616._1
399- let inFavor = $t01455514616._2
409+ let $t01498115042 = parseUserVote(value(userVoteOrUnit))
410+ let total = $t01498115042._1
411+ let inFavor = $t01498115042._2
400412 let votesListActions = deleteNode(votesListName, userAddress)
401- let userVoteActions = [DeleteEntry(userVoteKey), StringEntry(keyUserVoteHistory("cancelVote", userAddress, assetId, toBase58String(i.transactionId), currentPeriod), formatUserVote(0, true)), getVoteResultAction(assetId, -(total), inFavor, currentPeriod)]
413+ let userVoteActions = [DeleteEntry(userVoteKey), StringEntry(keyUserVoteHistory("cancelVote", userAddress, assetId, toBase58String(i.transactionId), currentPeriod), formatUserVote(0, true)), getVoteResultAction(assetId, -(total), inFavor, currentPeriod, unit)]
402414 $Tuple2((votesListActions ++ userVoteActions), unit)
403415 }
404416 else throw("Strict value is not equal to itself.")
412424 if ((checkCaller == checkCaller))
413425 then {
414426 let voteResultKey = keyVoteResultByPeriod(assetId, period)
415- let $t01527015402 = match getString(voteResultKey) {
427+ let $t01570215875 = match getString(voteResultKey) {
416428 case s: String =>
417- parseVoteResult(s)
429+ let r = parseVoteResult(s)
430+ $Tuple2(r._1, r._2)
418431 case _: Unit =>
419432 $Tuple2(0, 0)
420433 case _ =>
421434 throw("Match error")
422435 }
423- let totalYes = $t01527015402._1
424- let totalNo = $t01527015402._2
436+ let totalYes = $t01570215875._1
437+ let totalNo = $t01570215875._2
425438 let total = (totalYes + totalNo)
426439 let verified = if ((total >= votingThreshold))
427440 then (totalYes > totalNo)
435448 else eliminationCheck(assetId)
436449 let voteResultActions = if (eliminate)
437450 then nil
438- else [getVoteResultAction(assetId, 0, true, (currentPeriod + 1))]
451+ else [getVoteResultAction(assetId, 0, true, (currentPeriod + 1), verified)]
439452 let votesListActions = if (eliminate)
440453 then deleteNode(assetsListName, assetId)
441454 else nil
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let separator = "__"
55
66 let maxDepthDefault = 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
4242 let keyAssetsStoreContract = makeString(["%s", "assetsStoreContract"], separator)
4343
4444 let keyLatestProcessedAsset = makeString(["%s", "latestProcessedAsset"], separator)
4545
4646 let keyLatestProcessedUser = makeString(["%s", "latestProcessedUser"], separator)
4747
4848 let keyLatestProcessedAssetTransfer = makeString(["%s", "latestProcessedAssetTransfer"], separator)
4949
5050 let keyLatestProcessedUserTransfer = makeString(["%s", "latestProcessedUserTransfer"], separator)
5151
5252 let keyMaxDepth = makeString(["%s", "maxDepth"], separator)
5353
5454 func keyVotesTransferFinishedByPeriod (period) = makeString(["%s", "votesTransferFinished", toString(period)], separator)
5555
5656
5757 let assetsListName = "__assets"
5858
5959 func getVotesListName (assetId) = ("%s__votes__" + assetId)
6060
6161
6262 func keyListHead (listName) = makeString([("%s%s" + listName), "head"], separator)
6363
6464
6565 func keyListSize (listName) = makeString([("%s%s" + listName), "size"], separator)
6666
6767
6868 func keyListPrev (listName,id) = makeString([("%s%s%s" + listName), id, "prev"], separator)
6969
7070
7171 func keyListNext (listName,id) = makeString([("%s%s%s" + listName), id, "next"], separator)
7272
7373
7474 func keyAssetVerifiedByPeriod (assetId,period) = makeString(["%s%d%s", "verifiedAt", toString(period), assetId], separator)
7575
7676
7777 func keyVoteResultByPeriod (assetId,period) = makeString(["%s%d%s", "votingResultAtAsset", toString(period), assetId], separator)
7878
7979
80-func formatVoteResult (totalYes,totalNo) = makeString(["%d%d", toString(totalYes), toString(totalNo)], separator)
80+func formatVoteResult (totalYes,totalNo,verified) = makeString(["%d%d%s", toString(totalYes), toString(totalNo), toString(verified)], separator)
8181
8282
8383 func parseVoteResult (input) = {
8484 let parts = split(input, separator)
8585 let totalYesIdx = 1
8686 let totalNoIdx = 2
87+ let verifiedIdx = 3
8788 let totalYes = parseIntValue(parts[totalYesIdx])
8889 let totalNo = parseIntValue(parts[totalNoIdx])
89- $Tuple2(totalYes, totalNo)
90+ let verified = (parts[verifiedIdx] == "true")
91+ $Tuple3(totalYes, totalNo, verified)
9092 }
9193
9294
9395 func keyUserVoteByPeriod (userAddress,assetId,period) = makeString(["%s%d%s%s", "vru", toString(period), assetId, userAddress], separator)
9496
9597
9698 func formatUserVote (total,inFavor) = {
9799 let totalYes = if (inFavor)
98100 then total
99101 else 0
100102 let totalNo = if (inFavor)
101103 then 0
102104 else total
103105 makeString(["%d%d", toString(totalYes), toString(totalNo)], separator)
104106 }
105107
106108
107109 func parseUserVote (input) = {
108110 let parts = split(input, separator)
109111 let totalYesIdx = 1
110112 let totalNoIdx = 2
111113 let totalYes = parseIntValue(parts[totalYesIdx])
112114 let totalNo = parseIntValue(parts[totalNoIdx])
113115 let inFavor = if ((totalYes > 0))
114116 then (totalNo == 0)
115117 else false
116118 let against = if ((totalYes == 0))
117119 then (totalNo > 0)
118120 else false
119121 let checkTotals = if (if (inFavor)
120122 then true
121123 else against)
122124 then true
123125 else throw("Invalid user vote value")
124126 if ((checkTotals == checkTotals))
125127 then {
126128 let total = if (inFavor)
127129 then totalYes
128130 else totalNo
129131 $Tuple2(total, inFavor)
130132 }
131133 else throw("Strict value is not equal to itself.")
132134 }
133135
134136
135137 func keyUserVoteHistory (type,userAddress,assetId,txId,period) = makeString(["%s%s%s%s%s%d", "history", type, assetId, userAddress, txId, toString(period)], separator)
136138
137139
138140 func thisOnly (i) = if ((i.caller == this))
139141 then true
140142 else throw("Permission denied")
141143
142144
143145 func getIntegerOrZero (key) = valueOrElse(getInteger(this, key), 0)
144146
145147
146148 func getIntegerOrFail (key) = valueOrErrorMessage(getInteger(this, key), (key + " is not defined"))
147149
148150
149151 func getStringOrEmpty (key) = valueOrElse(getString(this, key), "")
150152
151153
152154 func getStringOrFail (key) = valueOrErrorMessage(getString(this, key), (key + " is not defined"))
153155
154156
155157 let feeAmount = getIntegerOrFail(keyFeeAmount)
156158
157159 let wxAssetId = fromBase58String(getStringOrFail(keyWxAssetId))
158160
159161 let votingThreshold = getIntegerOrFail(keyVotingThreshold)
160162
161163 let votingDuration = getIntegerOrFail(keyVotingDuration)
162164
163165 let voteBeforeElimination = getIntegerOrFail(keyVoteBeforeElimination)
164166
165167 let startHeight = getIntegerOrFail(keyStartHeight)
166168
167169 let currentPeriod = getIntegerOrFail(keyCurrentPeriod)
168170
169171 let boostingContract = addressFromStringValue(getStringOrFail(keyBoostingContract))
170172
171173 let emissionContract = addressFromStringValue(getStringOrFail(keyEmissionContract))
172174
173175 let assetsStoreContract = addressFromStringValue(getStringOrFail(keyAssetsStoreContract))
174176
175177 let maxDepth = valueOrElse(getInteger(keyMaxDepth), maxDepthDefault)
176178
177179 func getUserGwxAmountAtHeight (userAddress,targetHeight) = {
178180 let gwxAmount = invoke(boostingContract, "getUserGwxAmountAtHeightREADONLY", [userAddress, targetHeight], nil)
179181 asInt(gwxAmount)
180182 }
181183
182184
183-func getVoteResultAction (assetId,total,inFavor,period) = {
185+func getVoteResultAction (assetId,total,inFavor,period,verified) = {
184186 let voteResultKey = keyVoteResultByPeriod(assetId, period)
185- let $t054515583 = match getString(voteResultKey) {
187+ let $t055955898 = match getString(voteResultKey) {
186188 case s: String =>
187189 parseVoteResult(s)
188190 case _: Unit =>
189- $Tuple2(0, 0)
191+ match getString(keyVoteResultByPeriod(assetId, (period - 1))) {
192+ case s: String =>
193+ $Tuple3(0, 0, parseVoteResult(s)._3)
194+ case _: Unit =>
195+ $Tuple3(0, 0, false)
196+ case _ =>
197+ throw("Match error")
198+ }
190199 case _ =>
191200 throw("Match error")
192201 }
193- let totalYes = $t054515583._1
194- let totalNo = $t054515583._2
195- StringEntry(voteResultKey, formatVoteResult((totalYes + (if (inFavor)
202+ let oldTotalYes = $t055955898._1
203+ let oldTotalNo = $t055955898._2
204+ let oldVerified = $t055955898._3
205+ StringEntry(voteResultKey, formatVoteResult((oldTotalYes + (if (inFavor)
196206 then total
197- else 0)), (totalNo + (if (inFavor)
207+ else 0)), (oldTotalNo + (if (inFavor)
198208 then 0
199- else total))))
209+ else total)), if ((verified == unit))
210+ then oldVerified
211+ else value(verified)))
200212 }
201213
202214
203215 func containsNode (listName,id) = {
204216 let head = getString(this, keyListHead(listName))
205217 let prev = getString(this, keyListPrev(listName, id))
206218 let next = getString(this, keyListNext(listName, id))
207219 if (if ((id == head))
208220 then true
209221 else (prev != unit))
210222 then true
211223 else (next != unit)
212224 }
213225
214226
215227 func insertNode (listName,id) = {
216228 let head = getString(this, keyListHead(listName))
217229 let listSize = valueOrElse(getInteger(this, keyListSize(listName)), 0)
218230 let checkNode = if (!(containsNode(listName, id)))
219231 then true
220232 else throw("Node exists")
221233 if ((checkNode == checkNode))
222234 then (([IntegerEntry(keyListSize(listName), (listSize + 1))] ++ (if (isDefined(head))
223235 then [StringEntry(keyListNext(listName, id), value(head)), StringEntry(keyListPrev(listName, value(head)), id)]
224236 else nil)) ++ [StringEntry(keyListHead(listName), id)])
225237 else throw("Strict value is not equal to itself.")
226238 }
227239
228240
229241 func deleteNode (listName,id) = {
230242 let head = getString(this, keyListHead(listName))
231243 let listSize = valueOrElse(getInteger(this, keyListSize(listName)), 0)
232244 let prev = getString(this, keyListPrev(listName, id))
233245 let next = getString(this, keyListNext(listName, id))
234246 ([IntegerEntry(keyListSize(listName), (listSize - 1))] ++ (if (if (isDefined(prev))
235247 then isDefined(next)
236248 else false)
237249 then [StringEntry(keyListNext(listName, value(prev)), value(next)), StringEntry(keyListPrev(listName, value(next)), value(prev)), DeleteEntry(keyListPrev(listName, id)), DeleteEntry(keyListNext(listName, id))]
238250 else if (isDefined(next))
239251 then [StringEntry(keyListHead(listName), value(next)), DeleteEntry(keyListNext(listName, id)), DeleteEntry(keyListPrev(listName, value(next)))]
240252 else if (isDefined(prev))
241253 then [DeleteEntry(keyListPrev(listName, id)), DeleteEntry(keyListNext(listName, value(prev)))]
242254 else if ((id == head))
243255 then [DeleteEntry(keyListHead(listName))]
244256 else throw("Invalid node")))
245257 }
246258
247259
248260 func processVote (assetId,userAddressOrUnit,latestProcessedAssetKey,latestProcessedUserKey) = {
249261 let updateLatestProcessedAssetAction = StringEntry(latestProcessedAssetKey, assetId)
250262 let deleteLatestProcessedUserAction = DeleteEntry(latestProcessedUserKey)
251263 if ((userAddressOrUnit == unit))
252264 then [updateLatestProcessedAssetAction, deleteLatestProcessedUserAction]
253265 else {
254266 let endHeight = (startHeight + votingDuration)
255267 let userAddress = value(userAddressOrUnit)
256268 let updateLatestProcessedUserAction = StringEntry(latestProcessedUserKey, userAddress)
257269 let userVoteKey = keyUserVoteByPeriod(userAddress, assetId, currentPeriod)
258270 let userVoteOrUnit = getString(userVoteKey)
259271 let userGwxAmountAtEndHeight = getUserGwxAmountAtHeight(userAddress, endHeight)
260272 let voteActions = if ((userGwxAmountAtEndHeight == 0))
261273 then {
262274 let votesListName = getVotesListName(assetId)
263275 deleteNode(votesListName, userAddress)
264276 }
265277 else if ((userVoteOrUnit == unit))
266278 then {
267279 let userPreviousVoteOrUnit = getString(keyUserVoteByPeriod(userAddress, assetId, (currentPeriod - 1)))
268280 if ((userPreviousVoteOrUnit == unit))
269281 then nil
270282 else {
271- let $t093859458 = parseUserVote(value(userPreviousVoteOrUnit))
272- let prevTotal = $t093859458._1
273- let inFavor = $t093859458._2
283+ let $t097929865 = parseUserVote(value(userPreviousVoteOrUnit))
284+ let prevTotal = $t097929865._1
285+ let inFavor = $t097929865._2
274286 let total = min([prevTotal, userGwxAmountAtEndHeight])
275-[StringEntry(userVoteKey, formatUserVote(total, inFavor)), getVoteResultAction(assetId, total, inFavor, currentPeriod)]
287+[StringEntry(userVoteKey, formatUserVote(total, inFavor)), getVoteResultAction(assetId, total, inFavor, currentPeriod, unit)]
276288 }
277289 }
278290 else nil
279291 ((voteActions :+ updateLatestProcessedAssetAction) :+ updateLatestProcessedUserAction)
280292 }
281293 }
282294
283295
284296 func assetShouldBeEliminated (assetId,period) = !(valueOrElse(getBoolean(keyAssetVerifiedByPeriod(assetId, period)), true))
285297
286298
287299 func eliminationCheck (assetId) = if (if (assetShouldBeEliminated(assetId, (currentPeriod - 1)))
288300 then assetShouldBeEliminated(assetId, (currentPeriod - 2))
289301 else false)
290302 then assetShouldBeEliminated(assetId, (currentPeriod - 3))
291303 else false
292304
293305
294306 @Callable(i)
295307 func constructor (boostingContractPrm,emissionContractPrm,assetsStoreContractPrm,feeAmountPrm,wxAssetIdPrm,votingThresholdPrm,votingDurationPrm,voteBeforeEliminationPrm,startHeightPrm,maxDepthPrm) = {
296308 let checks = [thisOnly(i), if (isDefined(addressFromString(boostingContractPrm)))
297309 then true
298310 else throw("Invalid boosting contract address"), if (isDefined(addressFromString(emissionContractPrm)))
299311 then true
300312 else throw("Invalid emission contract address"), if (isDefined(addressFromString(assetsStoreContractPrm)))
301313 then true
302314 else throw("Invalid asset_store contract address"), if ((feeAmountPrm >= 0))
303315 then true
304316 else throw("Invalid fee amount"), if (isDefined(assetInfo(fromBase58String(wxAssetIdPrm))))
305317 then true
306318 else throw("Invalid WX asset ID"), if ((votingThresholdPrm >= 0))
307319 then true
308320 else throw("Invalid voting threshold"), if ((votingDurationPrm > 0))
309321 then true
310322 else throw("Invalid voting duration"), if (((startHeightPrm + votingDurationPrm) > height))
311323 then true
312324 else throw("Invalid start height")]
313325 if ((checks == checks))
314326 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), IntegerEntry(keyMaxDepth, maxDepthPrm)], unit)
315327 else throw("Strict value is not equal to itself.")
316328 }
317329
318330
319331
320332 @Callable(i)
321333 func suggest (assetId,assetImage) = {
322334 let info = valueOrErrorMessage(assetInfo(fromBase58String(assetId)), "Invalid asset ID")
323335 let payment = value(i.payments[0])
324336 let checks = [if ((info.issuer == i.caller))
325337 then true
326338 else throw("Asset can only be suggested by its issuer"), if ((value(payment.assetId) == wxAssetId))
327339 then true
328340 else throw("Invalid fee asset"), if ((payment.amount == feeAmount))
329341 then true
330342 else throw("Invalid fee amount")]
331343 if ((checks == checks))
332344 then {
333345 let assetsStoreCreateOrUpdateInv = invoke(assetsStoreContract, "createOrUpdate", [assetId, "", assetImage, false], nil)
334346 if ((assetsStoreCreateOrUpdateInv == assetsStoreCreateOrUpdateInv))
335347 then {
336348 let burnFeeInv = invoke(emissionContract, "burn", nil, [AttachedPayment(payment.assetId, payment.amount)])
337349 if ((burnFeeInv == burnFeeInv))
338350 then {
339351 let addAssetActions = insertNode(assetsListName, assetId)
340- $Tuple2((addAssetActions :+ getVoteResultAction(assetId, 0, true, currentPeriod)), unit)
352+ $Tuple2((addAssetActions :+ getVoteResultAction(assetId, 0, true, currentPeriod, false)), unit)
341353 }
342354 else throw("Strict value is not equal to itself.")
343355 }
344356 else throw("Strict value is not equal to itself.")
345357 }
346358 else throw("Strict value is not equal to itself.")
347359 }
348360
349361
350362
351363 @Callable(i)
352364 func vote (assetId,inFavor) = {
353365 let endHeight = (startHeight + votingDuration)
354366 let checkAsset = if (containsNode(assetsListName, assetId))
355367 then true
356368 else throw("Invalid asset")
357369 if ((checkAsset == checkAsset))
358370 then {
359371 let checkHeight = if ((endHeight > height))
360372 then true
361373 else throw("Current voting is over but results are not finalized")
362374 if ((checkHeight == checkHeight))
363375 then {
364376 let userAddress = toString(i.caller)
365377 let gwxAmountAtEnd = getUserGwxAmountAtHeight(userAddress, endHeight)
366378 let checkGwxAmountAtEnd = if ((gwxAmountAtEnd > 0))
367379 then true
368380 else throw("You'll not have gWX at the end of voting")
369381 if ((checkGwxAmountAtEnd == checkGwxAmountAtEnd))
370382 then {
371383 let votesListName = getVotesListName(assetId)
372384 let userVoteKey = keyUserVoteByPeriod(userAddress, assetId, currentPeriod)
373- let userVoteActions = [StringEntry(userVoteKey, formatUserVote(gwxAmountAtEnd, inFavor)), StringEntry(keyUserVoteHistory("vote", userAddress, assetId, toBase58String(i.transactionId), currentPeriod), formatUserVote(gwxAmountAtEnd, inFavor)), getVoteResultAction(assetId, gwxAmountAtEnd, inFavor, currentPeriod)]
385+ let userVoteActions = [StringEntry(userVoteKey, formatUserVote(gwxAmountAtEnd, inFavor)), StringEntry(keyUserVoteHistory("vote", userAddress, assetId, toBase58String(i.transactionId), currentPeriod), formatUserVote(gwxAmountAtEnd, inFavor)), getVoteResultAction(assetId, gwxAmountAtEnd, inFavor, currentPeriod, unit)]
374386 let votesListActions = if (containsNode(votesListName, userAddress))
375387 then nil
376388 else insertNode(votesListName, userAddress)
377389 $Tuple2((votesListActions ++ userVoteActions), unit)
378390 }
379391 else throw("Strict value is not equal to itself.")
380392 }
381393 else throw("Strict value is not equal to itself.")
382394 }
383395 else throw("Strict value is not equal to itself.")
384396 }
385397
386398
387399
388400 @Callable(i)
389401 func cancelVote (assetId) = {
390402 let userAddress = toString(i.caller)
391403 let votesListName = getVotesListName(assetId)
392404 let userVoteKey = keyUserVoteByPeriod(userAddress, assetId, currentPeriod)
393405 let userVoteOrUnit = getString(userVoteKey)
394406 let checkVote = valueOrElse(getString(userVoteKey), "Nothing to cancel")
395407 if ((checkVote == checkVote))
396408 then {
397- let $t01455514616 = parseUserVote(value(userVoteOrUnit))
398- let total = $t01455514616._1
399- let inFavor = $t01455514616._2
409+ let $t01498115042 = parseUserVote(value(userVoteOrUnit))
410+ let total = $t01498115042._1
411+ let inFavor = $t01498115042._2
400412 let votesListActions = deleteNode(votesListName, userAddress)
401- let userVoteActions = [DeleteEntry(userVoteKey), StringEntry(keyUserVoteHistory("cancelVote", userAddress, assetId, toBase58String(i.transactionId), currentPeriod), formatUserVote(0, true)), getVoteResultAction(assetId, -(total), inFavor, currentPeriod)]
413+ let userVoteActions = [DeleteEntry(userVoteKey), StringEntry(keyUserVoteHistory("cancelVote", userAddress, assetId, toBase58String(i.transactionId), currentPeriod), formatUserVote(0, true)), getVoteResultAction(assetId, -(total), inFavor, currentPeriod, unit)]
402414 $Tuple2((votesListActions ++ userVoteActions), unit)
403415 }
404416 else throw("Strict value is not equal to itself.")
405417 }
406418
407419
408420
409421 @Callable(i)
410422 func finalizeAssetINTERNAL (assetId,period) = {
411423 let checkCaller = thisOnly(i)
412424 if ((checkCaller == checkCaller))
413425 then {
414426 let voteResultKey = keyVoteResultByPeriod(assetId, period)
415- let $t01527015402 = match getString(voteResultKey) {
427+ let $t01570215875 = match getString(voteResultKey) {
416428 case s: String =>
417- parseVoteResult(s)
429+ let r = parseVoteResult(s)
430+ $Tuple2(r._1, r._2)
418431 case _: Unit =>
419432 $Tuple2(0, 0)
420433 case _ =>
421434 throw("Match error")
422435 }
423- let totalYes = $t01527015402._1
424- let totalNo = $t01527015402._2
436+ let totalYes = $t01570215875._1
437+ let totalNo = $t01570215875._2
425438 let total = (totalYes + totalNo)
426439 let verified = if ((total >= votingThreshold))
427440 then (totalYes > totalNo)
428441 else false
429442 let assetVerifiedAction = [BooleanEntry(keyAssetVerifiedByPeriod(assetId, period), verified)]
430443 let assetsStoreSetVerifiedInv = invoke(assetsStoreContract, "setVerified", [assetId, verified], nil)
431444 if ((assetsStoreSetVerifiedInv == assetsStoreSetVerifiedInv))
432445 then {
433446 let eliminate = if (verified)
434447 then false
435448 else eliminationCheck(assetId)
436449 let voteResultActions = if (eliminate)
437450 then nil
438- else [getVoteResultAction(assetId, 0, true, (currentPeriod + 1))]
451+ else [getVoteResultAction(assetId, 0, true, (currentPeriod + 1), verified)]
439452 let votesListActions = if (eliminate)
440453 then deleteNode(assetsListName, assetId)
441454 else nil
442455 $Tuple2(((votesListActions ++ voteResultActions) ++ assetVerifiedAction), unit)
443456 }
444457 else throw("Strict value is not equal to itself.")
445458 }
446459 else throw("Strict value is not equal to itself.")
447460 }
448461
449462
450463
451464 @Callable(i)
452465 func finalizeVotingHelper () = {
453466 let endHeight = (startHeight + votingDuration)
454467 if ((endHeight > height))
455468 then $Tuple2(nil, false)
456469 else {
457470 let latestProcessedAssetOrUnit = getString(keyLatestProcessedAsset)
458471 let latestProcessedUserOrUnit = getString(keyLatestProcessedUser)
459472 let nextPeriodDelay = 0
460473 let finish = $Tuple2([IntegerEntry(keyStartHeight, (height + nextPeriodDelay)), IntegerEntry(keyCurrentPeriod, (currentPeriod + 1)), DeleteEntry(keyLatestProcessedAsset), DeleteEntry(keyLatestProcessedUser), DeleteEntry(keyLatestProcessedAssetTransfer), DeleteEntry(keyLatestProcessedUserTransfer)], true)
461474 if ((latestProcessedAssetOrUnit == unit))
462475 then {
463476 let assetsHeadOrUnit = getString(keyListHead(assetsListName))
464477 if ((assetsHeadOrUnit == unit))
465478 then finish
466479 else {
467480 let asset = value(assetsHeadOrUnit)
468481 let userAddressOrUnit = getString(keyListHead(getVotesListName(asset)))
469482 let processVoteActions = processVote(asset, userAddressOrUnit, keyLatestProcessedAsset, keyLatestProcessedUser)
470483 $Tuple2(processVoteActions, true)
471484 }
472485 }
473486 else {
474487 let latestProcessedAsset = value(latestProcessedAssetOrUnit)
475488 if ((latestProcessedUserOrUnit == unit))
476489 then {
477490 let assetOrUnit = getString(keyListNext(assetsListName, latestProcessedAsset))
478491 if ((assetOrUnit == assetOrUnit))
479492 then {
480493 let finalizeAssetInv = invoke(this, "finalizeAssetINTERNAL", [latestProcessedAsset, currentPeriod], nil)
481494 if ((finalizeAssetInv == finalizeAssetInv))
482495 then if ((assetOrUnit == unit))
483496 then finish
484497 else {
485498 let asset = value(assetOrUnit)
486499 let userAddressOrUnit = getString(keyListHead(getVotesListName(asset)))
487500 let processVoteActions = processVote(asset, userAddressOrUnit, keyLatestProcessedAsset, keyLatestProcessedUser)
488501 $Tuple2(processVoteActions, true)
489502 }
490503 else throw("Strict value is not equal to itself.")
491504 }
492505 else throw("Strict value is not equal to itself.")
493506 }
494507 else {
495508 let latestProcessedUser = value(latestProcessedUserOrUnit)
496509 let userAddressOrUnit = getString(keyListNext(getVotesListName(latestProcessedAsset), latestProcessedUser))
497510 let processVoteActions = processVote(latestProcessedAsset, userAddressOrUnit, keyLatestProcessedAsset, keyLatestProcessedUser)
498511 $Tuple2(processVoteActions, true)
499512 }
500513 }
501514 }
502515 }
503516
504517
505518
506519 @Callable(i)
507520 func finalizeVotingWrapper (counter) = {
508521 let result = asBool(invoke(this, "finalizeVotingHelper", nil, nil))
509522 if ((result == result))
510523 then if (!(result))
511524 then if ((counter == 0))
512525 then throw("Current voting is not over yet")
513526 else $Tuple2(nil, unit)
514527 else if ((maxDepth > counter))
515528 then {
516529 let inv = invoke(this, "finalizeVotingWrapper", [(counter + 1)], nil)
517530 if ((inv == inv))
518531 then $Tuple2(nil, unit)
519532 else throw("Strict value is not equal to itself.")
520533 }
521534 else $Tuple2(nil, unit)
522535 else throw("Strict value is not equal to itself.")
523536 }
524537
525538
526539
527540 @Callable(i)
528541 func finalizeVoting () = {
529542 let inv = invoke(this, "finalizeVotingWrapper", [0], nil)
530543 if ((inv == inv))
531544 then $Tuple2(nil, unit)
532545 else throw("Strict value is not equal to itself.")
533546 }
534547
535548
536549
537550 @Callable(i)
538551 func transferVotesHelper () = {
539552 let votesTransferFinishedKey = keyVotesTransferFinishedByPeriod(currentPeriod)
540553 let votesTransferFinished = valueOrElse(getBoolean(votesTransferFinishedKey), false)
541554 let endHeight = (startHeight + votingDuration)
542555 if (if (if ((startHeight > height))
543556 then true
544557 else (height >= endHeight))
545558 then true
546559 else votesTransferFinished)
547560 then $Tuple2(nil, false)
548561 else {
549562 let latestProcessedAssetOrUnit = getString(keyLatestProcessedAssetTransfer)
550563 let latestProcessedUserOrUnit = getString(keyLatestProcessedUserTransfer)
551564 let finish = $Tuple2([BooleanEntry(votesTransferFinishedKey, true), DeleteEntry(keyLatestProcessedAssetTransfer), DeleteEntry(keyLatestProcessedUserTransfer)], true)
552565 if ((latestProcessedAssetOrUnit == unit))
553566 then {
554567 let assetsHeadOrUnit = getString(keyListHead(assetsListName))
555568 if ((assetsHeadOrUnit == unit))
556569 then finish
557570 else {
558571 let asset = value(assetsHeadOrUnit)
559572 let userAddressOrUnit = getString(keyListHead(getVotesListName(asset)))
560573 let processVoteActions = processVote(asset, userAddressOrUnit, keyLatestProcessedAssetTransfer, keyLatestProcessedUserTransfer)
561574 $Tuple2(processVoteActions, true)
562575 }
563576 }
564577 else {
565578 let latestProcessedAsset = value(latestProcessedAssetOrUnit)
566579 if ((latestProcessedUserOrUnit == unit))
567580 then {
568581 let assetOrUnit = getString(keyListNext(assetsListName, latestProcessedAsset))
569582 if ((assetOrUnit == unit))
570583 then finish
571584 else {
572585 let asset = value(assetOrUnit)
573586 let userAddressOrUnit = getString(keyListHead(getVotesListName(asset)))
574587 let processVoteActions = processVote(asset, userAddressOrUnit, keyLatestProcessedAssetTransfer, keyLatestProcessedUserTransfer)
575588 $Tuple2(processVoteActions, true)
576589 }
577590 }
578591 else {
579592 let latestProcessedUser = value(latestProcessedUserOrUnit)
580593 let userAddressOrUnit = getString(keyListNext(getVotesListName(latestProcessedAsset), latestProcessedUser))
581594 let processVoteActions = processVote(latestProcessedAsset, userAddressOrUnit, keyLatestProcessedAssetTransfer, keyLatestProcessedUserTransfer)
582595 $Tuple2(processVoteActions, true)
583596 }
584597 }
585598 }
586599 }
587600
588601
589602
590603 @Callable(i)
591604 func transferVotesWrapper (counter) = {
592605 let result = asBool(invoke(this, "transferVotesHelper", nil, nil))
593606 if ((result == result))
594607 then if (!(result))
595608 then if ((counter == 0))
596609 then throw("Voting is not started yet")
597610 else $Tuple2(nil, unit)
598611 else if ((maxDepth > counter))
599612 then {
600613 let inv = invoke(this, "transferVotesWrapper", [(counter + 1)], nil)
601614 if ((inv == inv))
602615 then $Tuple2(nil, unit)
603616 else throw("Strict value is not equal to itself.")
604617 }
605618 else $Tuple2(nil, unit)
606619 else throw("Strict value is not equal to itself.")
607620 }
608621
609622
610623
611624 @Callable(i)
612625 func transferVotes () = {
613626 let inv = invoke(this, "transferVotesWrapper", [0], nil)
614627 if ((inv == inv))
615628 then $Tuple2(nil, unit)
616629 else throw("Strict value is not equal to itself.")
617630 }
618631
619632
620633
621634 @Callable(i)
622635 func setVotingThreshold (newThreshold) = {
623636 let checkCaller = thisOnly(i)
624637 if ((checkCaller == checkCaller))
625638 then $Tuple2([IntegerEntry(keyVotingThreshold, newThreshold)], unit)
626639 else throw("Strict value is not equal to itself.")
627640 }
628641
629642
630643
631644 @Callable(i)
632645 func setFee (newFee) = {
633646 let checkCaller = thisOnly(i)
634647 if ((checkCaller == checkCaller))
635648 then $Tuple2([IntegerEntry(keyFeeAmount, newFee)], unit)
636649 else throw("Strict value is not equal to itself.")
637650 }
638651
639652
640653
641654 @Callable(i)
642655 func gwxAvailableForVoteREADONLY (userAddress) = {
643656 let endHeight = (startHeight + votingDuration)
644657 let gwxAmountAtEnd = getUserGwxAmountAtHeight(userAddress, endHeight)
645658 $Tuple2(nil, gwxAmountAtEnd)
646659 }
647660
648661

github/deemru/w8io/026f985 
103.19 ms