2022.03.30 20:14 [3052142] smart account 3PJL8Hn8LACaSBWLQ3UVhctA5cTQLBFwBAP > SELF 0.00000000 Waves

{ "type": 13, "id": "HRvYX7vtRx8kWupgkBuqNoqC3yM8FnVri1rvKqCoFSJP", "fee": 1400000, "feeAssetId": null, "timestamp": 1648660492505, "version": 1, "sender": "3PJL8Hn8LACaSBWLQ3UVhctA5cTQLBFwBAP", "senderPublicKey": "6PdA345SW1zresPEKuWiLPsh9Ku14mFDW6cZtpCQrp3E", "proofs": [ "3aJb5AR3fC74eYseQBYASTBY15UK8rXatPVecwCXtojwDnnT3c5twLs2iy5AsXfuD6YqNRBRrqYwJb3Y6hs7Y9Dq" ], "script": "base64:AAIFAAAAAAAAADkIAhIICgYICAEBAQgSAwoBARIDCgEBEgQKAggIEgQKAggIEgMKAQgSAwoBCBIECgIIARIDCgEIEgAAAABlAAAAAANTRVACAAAAAl9fAAAAAAZTQ0FMRTgAAAAAAAAAAAgAAAAABU1VTFQ4AAAAAAAF9eEAAAAAAA5QT09MV0VJR0hUTVVMVAUAAAAFTVVMVDgBAAAABHN0cmYAAAACAAAAB2FkZHJlc3MAAAADa2V5CQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQdAAAAAgUAAAAHYWRkcmVzcwUAAAADa2V5CQABLAAAAAIJAAEsAAAAAgIAAAAPbWFuZGF0b3J5IHRoaXMuBQAAAANrZXkCAAAADyBpcyBub3QgZGVmaW5lZAEAAAADaW96AAAAAgAAAAdhZGRyZXNzAAAAA2tleQkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAdhZGRyZXNzBQAAAANrZXkAAAAAAAAAAAABAAAAA2lvZAAAAAMAAAAHYWRkcmVzcwAAAANrZXkAAAAKZGVmYXVsdFZhbAkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAdhZGRyZXNzBQAAAANrZXkFAAAACmRlZmF1bHRWYWwBAAAAA2lvZgAAAAIAAAAHYWRkcmVzcwAAAANrZXkJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABBoAAAACBQAAAAdhZGRyZXNzBQAAAANrZXkJAAEsAAAAAgkAASwAAAACAgAAAA9tYW5kYXRvcnkgdGhpcy4FAAAAA2tleQIAAAAPIGlzIG5vdCBkZWZpbmVkAQAAAANhYnMAAAABAAAAA3ZhbAMJAABmAAAAAgAAAAAAAAAAAAUAAAADdmFsCQEAAAABLQAAAAEFAAAAA3ZhbAUAAAADdmFsAQAAAANhYWwAAAABAAAAA3ZhbAQAAAAHJG1hdGNoMAUAAAADdmFsAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAAlMaXN0W0FueV0EAAAACnZhbEFueUx5c3QFAAAAByRtYXRjaDAFAAAACnZhbEFueUx5c3QJAAACAAAAAQIAAAAbZmFpbCB0byBjYXN0IGludG8gTGlzdFtBbnldAQAAAAJhaQAAAAEAAAADdmFsBAAAAAckbWF0Y2gwBQAAAAN2YWwDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAA0ludAQAAAAGdmFsSW50BQAAAAckbWF0Y2gwBQAAAAZ2YWxJbnQJAAACAAAAAQIAAAAVZmFpbCB0byBjYXN0IGludG8gSW50AQAAABFrZXlGYWN0b3J5QWRkcmVzcwAAAAACAAAAHCVzJXNfX2NvbmZpZ19fZmFjdG9yeUFkZHJlc3MAAAAAGElkeEZhY3RvcnlDZmdTdGFraW5nRGFwcAAAAAAAAAAAAQAAAAAZSWR4RmFjdG9yeUNmZ0Jvb3N0aW5nRGFwcAAAAAAAAAAAAgAAAAAUSWR4RmFjdG9yeUNmZ0lkb0RhcHAAAAAAAAAAAAMAAAAAFUlkeEZhY3RvcnlDZmdUZWFtRGFwcAAAAAAAAAAABAAAAAAZSWR4RmFjdG9yeUNmZ0VtaXNzaW9uRGFwcAAAAAAAAAAABQAAAAAVSWR4RmFjdG9yeUNmZ1Jlc3REYXBwAAAAAAAAAAAGAAAAABlJZHhGYWN0b3J5Q2ZnU2xpcHBhZ2VEYXBwAAAAAAAAAAAHAAAAABRJZHhGYWN0b3J5Q2ZnRGFvRGFwcAAAAAAAAAAACAAAAAAaSWR4RmFjdG9yeUNmZ01hcmtldGluZ0RhcHAAAAAAAAAAAAkAAAAAGklkeEZhY3RvcnlDZmdHd3hSZXdhcmREYXBwAAAAAAAAAAAKAAAAABZJZHhGYWN0b3J5Q2ZnQmlyZHNEYXBwAAAAAAAAAAALAQAAAA1rZXlGYWN0b3J5Q2ZnAAAAAAIAAAARJXNfX2ZhY3RvcnlDb25maWcBAAAAGmtleUZhY3RvcnlMcDJBc3NldHNNYXBwaW5nAAAAAQAAAApscEFzc2V0U3RyCQAEuQAAAAIJAARMAAAAAgIAAAAGJXMlcyVzCQAETAAAAAIFAAAACmxwQXNzZXRTdHIJAARMAAAAAgIAAAAebWFwcGluZ3NfX2xwQXNzZXQyUG9vbENvbnRyYWN0BQAAAANuaWwFAAAAA1NFUAEAAAAQa2V5RmFjdG9yeUxwTGlzdAAAAAACAAAAECVzX19scFRva2Vuc0xpc3QBAAAAJmtleUZhY3RvcnlMcEFzc2V0VG9Qb29sQ29udHJhY3RBZGRyZXNzAAAAAQAAAApscEFzc2V0U3RyCQAEuQAAAAIJAARMAAAAAgIAAAAGJXMlcyVzCQAETAAAAAIFAAAACmxwQXNzZXRTdHIJAARMAAAAAgIAAAAebWFwcGluZ3NfX2xwQXNzZXQyUG9vbENvbnRyYWN0BQAAAANuaWwFAAAAA1NFUAEAAAAUa2V5RmFjdG9yeVBvb2xXZWlnaHQAAAABAAAAD2NvbnRyYWN0QWRkcmVzcwkABLkAAAACCQAETAAAAAICAAAABCVzJXMJAARMAAAAAgIAAAAKcG9vbFdlaWdodAkABEwAAAACBQAAAA9jb250cmFjdEFkZHJlc3MFAAAAA25pbAUAAAADU0VQAQAAABtrZXlGYWN0b3J5UG9vbFdlaWdodEhpc3RvcnkAAAACAAAAC3Bvb2xBZGRyZXNzAAAAA251bQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAASJXMlc19fcG9vbFdlaWdodF9fBQAAAAtwb29sQWRkcmVzcwIAAAACX18JAAGkAAAAAQUAAAADbnVtAQAAABhyZWFkRmFjdG9yeUFkZHJlc3NPckZhaWwAAAAACQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABCQEAAAAEc3RyZgAAAAIFAAAABHRoaXMJAQAAABFrZXlGYWN0b3J5QWRkcmVzcwAAAAABAAAACnJlYWRMcExpc3QAAAAACQAEtQAAAAIJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQdAAAAAgkBAAAAGHJlYWRGYWN0b3J5QWRkcmVzc09yRmFpbAAAAAAJAQAAABBrZXlGYWN0b3J5THBMaXN0AAAAAAIAAAAABQAAAANTRVABAAAAFHJlYWRGYWN0b3J5Q2ZnT3JGYWlsAAAAAQAAAAdmYWN0b3J5CQAEtQAAAAIJAQAAAARzdHJmAAAAAgUAAAAHZmFjdG9yeQkBAAAADWtleUZhY3RvcnlDZmcAAAAABQAAAANTRVABAAAAGGdldEJvb3N0aW5nQWRkcmVzc09yRmFpbAAAAAEAAAAKZmFjdG9yeUNmZwkBAAAAEUBleHRyTmF0aXZlKDEwNjIpAAAAAQkAAZEAAAACBQAAAApmYWN0b3J5Q2ZnBQAAABlJZHhGYWN0b3J5Q2ZnQm9vc3RpbmdEYXBwAQAAABhnZXRFbWlzc2lvbkFkZHJlc3NPckZhaWwAAAABAAAACmZhY3RvcnlDZmcJAQAAABFAZXh0ck5hdGl2ZSgxMDYyKQAAAAEJAAGRAAAAAgUAAAAKZmFjdG9yeUNmZwUAAAAZSWR4RmFjdG9yeUNmZ0VtaXNzaW9uRGFwcAEAAAAXZ2V0U3Rha2luZ0FkZHJlc3NPckZhaWwAAAABAAAACmZhY3RvcnlDZmcJAQAAABFAZXh0ck5hdGl2ZSgxMDYyKQAAAAEJAAGRAAAAAgUAAAAKZmFjdG9yeUNmZwUAAAAYSWR4RmFjdG9yeUNmZ1N0YWtpbmdEYXBwAQAAABlnZXRHd3hSZXdhcmRBZGRyZXNzT3JGYWlsAAAAAQAAAApmYWN0b3J5Q2ZnCQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABCQABkQAAAAIFAAAACmZhY3RvcnlDZmcFAAAAGklkeEZhY3RvcnlDZmdHd3hSZXdhcmREYXBwAQAAABNrZXlNYW5hZ2VyUHVibGljS2V5AAAAAAIAAAAUJXNfX21hbmFnZXJQdWJsaWNLZXkBAAAAGmtleVBlbmRpbmdNYW5hZ2VyUHVibGljS2V5AAAAAAIAAAAbJXNfX3BlbmRpbmdNYW5hZ2VyUHVibGljS2V5AQAAAB5rZXlFbWlzc2lvblJhdGVQZXJCbG9ja0N1cnJlbnQAAAAAAgAAABslcyVzX19yYXRlUGVyQmxvY2tfX2N1cnJlbnQBAAAAIWtleUVtaXNzaW9uUmF0ZVBlckJsb2NrTWF4Q3VycmVudAAAAAACAAAAHiVzJXNfX3JhdGVQZXJCbG9ja01heF9fY3VycmVudAEAAAAVa2V5RW1pc3Npb25TdGFydEJsb2NrAAAAAAIAAAAaJXMlc19fZW1pc3Npb25fX3N0YXJ0QmxvY2sBAAAAG2tleUVtaXNzaW9uRHVyYXRpb25JbkJsb2NrcwAAAAACAAAAGCVzJXNfX2VtaXNzaW9uX19kdXJhdGlvbgEAAAATa2V5RW1pc3Npb25FbmRCbG9jawAAAAACAAAAGCVzJXNfX2VtaXNzaW9uX19lbmRCbG9jawEAAAANa2V5TmV4dFBlcmlvZAAAAAACAAAADiVzX19uZXh0UGVyaW9kAQAAAB9rZXlHd3hSZXdhcmRFbWlzc2lvblN0YXJ0SGVpZ2h0AAAAAAIAAAAoJXMlc19fZ3d4UmV3YXJkRW1pc3Npb25QYXJ0X19zdGFydEhlaWdodAAAAAANSWR4Q2ZnQXNzZXRJZAAAAAAAAAAAAQAAAAATSWR4Q2ZnTWluTG9ja0Ftb3VudAAAAAAAAAAAAgAAAAAVSWR4Q2ZnTWluTG9ja0R1cmF0aW9uAAAAAAAAAAADAAAAABVJZHhDZmdNYXhMb2NrRHVyYXRpb24AAAAAAAAAAAQAAAAAEklkeENmZ01hdGhDb250cmFjdAAAAAAAAAAABQEAAAAJa2V5Q29uZmlnAAAAAAIAAAAKJXNfX2NvbmZpZwEAAAAVcmVhZENvbmZpZ0FycmF5T3JGYWlsAAAAAAkABLUAAAACCQEAAAAEc3RyZgAAAAIFAAAABHRoaXMJAQAAAAlrZXlDb25maWcAAAAABQAAAANTRVABAAAADWZvcm1hdENvbmZpZ1MAAAAFAAAAB2Fzc2V0SWQAAAANbWluTG9ja0Ftb3VudAAAAA9taW5Mb2NrRHVyYXRpb24AAAAPbWF4TG9ja0R1cmF0aW9uAAAADG1hdGhDb250cmFjdAkABLkAAAACCQAETAAAAAICAAAACCVzJWQlZCVkCQAETAAAAAIFAAAAB2Fzc2V0SWQJAARMAAAAAgUAAAANbWluTG9ja0Ftb3VudAkABEwAAAACBQAAAA9taW5Mb2NrRHVyYXRpb24JAARMAAAAAgUAAAAPbWF4TG9ja0R1cmF0aW9uCQAETAAAAAIFAAAADG1hdGhDb250cmFjdAUAAAADbmlsBQAAAANTRVABAAAADGZvcm1hdENvbmZpZwAAAAUAAAAHYXNzZXRJZAAAAA1taW5Mb2NrQW1vdW50AAAAD21pbkxvY2tEdXJhdGlvbgAAAA9tYXhMb2NrRHVyYXRpb24AAAAMbWF0aENvbnRyYWN0CQEAAAANZm9ybWF0Q29uZmlnUwAAAAUFAAAAB2Fzc2V0SWQJAAGkAAAAAQUAAAANbWluTG9ja0Ftb3VudAkAAaQAAAABBQAAAA9taW5Mb2NrRHVyYXRpb24JAAGkAAAAAQUAAAAPbWF4TG9ja0R1cmF0aW9uBQAAAAxtYXRoQ29udHJhY3QBAAAAFm1hbmFnZXJQdWJsaWNLZXlPclVuaXQAAAAABAAAAAckbWF0Y2gwCQAEIgAAAAEJAQAAABNrZXlNYW5hZ2VyUHVibGljS2V5AAAAAAMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAGU3RyaW5nBAAAAAFzBQAAAAckbWF0Y2gwCQACWQAAAAEFAAAAAXMDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAABFVuaXQFAAAABHVuaXQJAAACAAAAAQIAAAALTWF0Y2ggZXJyb3IBAAAAHXBlbmRpbmdNYW5hZ2VyUHVibGljS2V5T3JVbml0AAAAAAQAAAAHJG1hdGNoMAkABCIAAAABCQEAAAAaa2V5UGVuZGluZ01hbmFnZXJQdWJsaWNLZXkAAAAAAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAAZTdHJpbmcEAAAAAXMFAAAAByRtYXRjaDAJAAJZAAAAAQUAAAABcwMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAEVW5pdAUAAAAEdW5pdAkAAAIAAAABAgAAAAtNYXRjaCBlcnJvcgEAAAALbXVzdE1hbmFnZXIAAAABAAAAAWkEAAAAAnBkCQAAAgAAAAECAAAAEVBlcm1pc3Npb24gZGVuaWVkBAAAAAckbWF0Y2gwCQEAAAAWbWFuYWdlclB1YmxpY0tleU9yVW5pdAAAAAADCQAAAQAAAAIFAAAAByRtYXRjaDACAAAACkJ5dGVWZWN0b3IEAAAAAnBrBQAAAAckbWF0Y2gwAwkAAAAAAAACCAUAAAABaQAAAA9jYWxsZXJQdWJsaWNLZXkFAAAAAnBrBgUAAAACcGQDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAABFVuaXQDCQAAAAAAAAIIBQAAAAFpAAAABmNhbGxlcgUAAAAEdGhpcwYFAAAAAnBkCQAAAgAAAAECAAAAC01hdGNoIGVycm9yAAAAAA5JZHhMb2NrVXNlck51bQAAAAAAAAAAAQAAAAANSWR4TG9ja0Ftb3VudAAAAAAAAAAAAgAAAAAMSWR4TG9ja1N0YXJ0AAAAAAAAAAADAAAAAA9JZHhMb2NrRHVyYXRpb24AAAAAAAAAAAQAAAAADUlkeExvY2tQYXJhbUsAAAAAAAAAAAUAAAAADUlkeExvY2tQYXJhbUIAAAAAAAAAAAYBAAAAE2tleUxvY2tQYXJhbXNSZWNvcmQAAAABAAAAC3VzZXJBZGRyZXNzCQAEuQAAAAIJAARMAAAAAgIAAAAKJXMlc19fbG9jawkABEwAAAACBQAAAAt1c2VyQWRkcmVzcwUAAAADbmlsBQAAAANTRVABAAAAGnJlYWRMb2NrUGFyYW1zUmVjb3JkT3JGYWlsAAAAAQAAAAt1c2VyQWRkcmVzcwkABLUAAAACCQEAAAAEc3RyZgAAAAIFAAAABHRoaXMJAQAAABNrZXlMb2NrUGFyYW1zUmVjb3JkAAAAAQUAAAALdXNlckFkZHJlc3MFAAAAA1NFUAEAAAAXZm9ybWF0TG9ja1BhcmFtc1JlY29yZFMAAAAIAAAAB3VzZXJOdW0AAAAGYW1vdW50AAAABXN0YXJ0AAAACGR1cmF0aW9uAAAABnBhcmFtSwAAAAZwYXJhbUIAAAAQbGFzdFVwZFRpbWVzdGFtcAAAAAlnd3hBbW91bnQJAAS5AAAAAgkABEwAAAACAgAAABAlZCVkJWQlZCVkJWQlZCVkCQAETAAAAAIFAAAAB3VzZXJOdW0JAARMAAAAAgUAAAAGYW1vdW50CQAETAAAAAIFAAAABXN0YXJ0CQAETAAAAAIFAAAACGR1cmF0aW9uCQAETAAAAAIFAAAABnBhcmFtSwkABEwAAAACBQAAAAZwYXJhbUIJAARMAAAAAgUAAAAQbGFzdFVwZFRpbWVzdGFtcAkABEwAAAACBQAAAAlnd3hBbW91bnQFAAAAA25pbAUAAAADU0VQAQAAABZmb3JtYXRMb2NrUGFyYW1zUmVjb3JkAAAABwAAAAd1c2VyTnVtAAAABmFtb3VudAAAAAVzdGFydAAAAAhkdXJhdGlvbgAAAAZwYXJhbUsAAAAGcGFyYW1CAAAACWd3eEFtb3VudAkBAAAAF2Zvcm1hdExvY2tQYXJhbXNSZWNvcmRTAAAACAUAAAAHdXNlck51bQkAAaQAAAABBQAAAAZhbW91bnQJAAGkAAAAAQUAAAAFc3RhcnQJAAGkAAAAAQUAAAAIZHVyYXRpb24JAAGkAAAAAQUAAAAGcGFyYW1LCQABpAAAAAEFAAAABnBhcmFtQgkAAaQAAAABCAUAAAAJbGFzdEJsb2NrAAAACXRpbWVzdGFtcAkAAaQAAAABBQAAAAlnd3hBbW91bnQBAAAADmtleU5leHRVc2VyTnVtAAAAAAIAAAAPJXNfX25leHRVc2VyTnVtAQAAABJrZXlVc2VyMk51bU1hcHBpbmcAAAABAAAAC3VzZXJBZGRyZXNzCQAEuQAAAAIJAARMAAAAAgIAAAAZJXMlcyVzX19tYXBwaW5nX191c2VyMm51bQkABEwAAAACBQAAAAt1c2VyQWRkcmVzcwUAAAADbmlsBQAAAANTRVABAAAAEmtleU51bTJVc2VyTWFwcGluZwAAAAEAAAADbnVtCQAEuQAAAAIJAARMAAAAAgIAAAAZJXMlcyVzX19tYXBwaW5nX19udW0ydXNlcgkABEwAAAACBQAAAANudW0FAAAAA25pbAUAAAADU0VQAQAAABZrZXlMb2NrUGFyYW1Vc2VyQW1vdW50AAAAAQAAAAd1c2VyTnVtCQAEuQAAAAIJAARMAAAAAgIAAAAWJXMlZCVzX19wYXJhbUJ5VXNlck51bQkABEwAAAACBQAAAAd1c2VyTnVtCQAETAAAAAICAAAABmFtb3VudAUAAAADbmlsBQAAAANTRVABAAAAFmtleUxvY2tQYXJhbVN0YXJ0QmxvY2sAAAABAAAAB3VzZXJOdW0JAAS5AAAAAgkABEwAAAACAgAAABYlcyVkJXNfX3BhcmFtQnlVc2VyTnVtCQAETAAAAAIFAAAAB3VzZXJOdW0JAARMAAAAAgIAAAAFc3RhcnQFAAAAA25pbAUAAAADU0VQAQAAABRrZXlMb2NrUGFyYW1EdXJhdGlvbgAAAAEAAAAHdXNlck51bQkABLkAAAACCQAETAAAAAICAAAAFiVzJWQlc19fcGFyYW1CeVVzZXJOdW0JAARMAAAAAgUAAAAHdXNlck51bQkABEwAAAACAgAAAAhkdXJhdGlvbgUAAAADbmlsBQAAAANTRVABAAAADWtleUxvY2tQYXJhbUsAAAABAAAAB3VzZXJOdW0JAAS5AAAAAgkABEwAAAACAgAAABYlcyVkJXNfX3BhcmFtQnlVc2VyTnVtCQAETAAAAAIFAAAAB3VzZXJOdW0JAARMAAAAAgIAAAABawUAAAADbmlsBQAAAANTRVABAAAADWtleUxvY2tQYXJhbUIAAAABAAAAB3VzZXJOdW0JAAS5AAAAAgkABEwAAAACAgAAABYlcyVkJXNfX3BhcmFtQnlVc2VyTnVtCQAETAAAAAIFAAAAB3VzZXJOdW0JAARMAAAAAgIAAAABYgUAAAADbmlsBQAAAANTRVABAAAAFWtleUxvY2tQYXJhbUJ5UGVyaW9kSwAAAAIAAAAHdXNlck51bQAAAAZwZXJpb2QJAAS5AAAAAgkABEwAAAACAgAAABclcyVkJXMlZF9fcGFyYW1CeVBlcmlvZAkABEwAAAACBQAAAAd1c2VyTnVtCQAETAAAAAICAAAAAWsJAARMAAAAAgUAAAAGcGVyaW9kBQAAAANuaWwFAAAAA1NFUAEAAAAVa2V5TG9ja1BhcmFtQnlQZXJpb2RCAAAAAgAAAAd1c2VyTnVtAAAABnBlcmlvZAkABLkAAAACCQAETAAAAAICAAAAFyVzJWQlcyVkX19wYXJhbUJ5UGVyaW9kCQAETAAAAAIFAAAAB3VzZXJOdW0JAARMAAAAAgIAAAABYgkABEwAAAACBQAAAAZwZXJpb2QFAAAAA25pbAUAAAADU0VQAQAAABdrZXlMb2NrUGFyYW1Ub3RhbEFtb3VudAAAAAACAAAAHiVzJXNfX3N0YXRzX19hY3RpdmVUb3RhbExvY2tlZAEAAAAga2V5U3RhdHNMb2Nrc0R1cmF0aW9uU3VtSW5CbG9ja3MAAAAAAgAAACUlcyVzX19zdGF0c19fbG9ja3NEdXJhdGlvblN1bUluQmxvY2tzAQAAABJrZXlTdGF0c0xvY2tzQ291bnQAAAAAAgAAABclcyVzX19zdGF0c19fbG9ja3NDb3VudAEAAAASa2V5U3RhdHNVc2Vyc0NvdW50AAAAAAIAAAAdJXMlc19fc3RhdHNfX2FjdGl2ZVVzZXJzQ291bnQBAAAAIGtleVVzZXJCb29zdEVtaXNzaW9uTGFzdElOVEVHUkFMAAAAAQAAAAd1c2VyTnVtCQAEuQAAAAIJAARMAAAAAgIAAAAeJXMlZF9fdXNlckJvb3N0RW1pc3Npb25MYXN0SW50CQAETAAAAAIFAAAAB3VzZXJOdW0FAAAAA25pbAUAAAADU0VQAQAAACJrZXlVc2VyTHBCb29zdEVtaXNzaW9uTGFzdElOVEVHUkFMAAAAAgAAAAd1c2VyTnVtAAAACWxwQXNzZXRJZAkABLkAAAACCQAETAAAAAICAAAAHiVzJWRfX3VzZXJCb29zdEVtaXNzaW9uTGFzdEludAkABEwAAAACBQAAAAd1c2VyTnVtCQAETAAAAAIFAAAACWxwQXNzZXRJZAUAAAADbmlsBQAAAANTRVABAAAAF2tleVVzZXJNYXhCb29zdElOVEVHUkFMAAAAAQAAAAd1c2VyTnVtCQAEuQAAAAIJAARMAAAAAgIAAAARJXMlZF9fbWF4Qm9vc3RJbnQJAARMAAAAAgUAAAAHdXNlck51bQUAAAADbmlsBQAAAANTRVABAAAAGGtleVRvdGFsTWF4Qm9vc3RJTlRFR1JBTAAAAAACAAAAGCVzJXNfX21heEJvb3N0SW50X190b3RhbAEAAAAha2V5VXNlckJvb3N0QXZhbGFpYmxlVG9DbGFpbVRvdGFsAAAAAQAAAAd1c2VyTnVtCQAEuQAAAAIJAARMAAAAAgIAAAAkJXMlZF9fdXNlckJvb3N0QXZhbGlhYmxlVG9DbGFpbVRvdGFsCQAETAAAAAIFAAAAB3VzZXJOdW0FAAAAA25pbAUAAAADU0VQAQAAABNrZXlVc2VyQm9vc3RDbGFpbWVkAAAAAQAAAAd1c2VyTnVtCQAEuQAAAAIJAARMAAAAAgIAAAAWJXMlZF9fdXNlckJvb3N0Q2xhaW1lZAkABEwAAAACBQAAAAd1c2VyTnVtBQAAAANuaWwFAAAAA1NFUAEAAAARa2V5VG90YWxDYWNoZWRHd3gAAAAAAgAAABYlcyVzX19nd3hDYWNoZWRfX3RvdGFsAAAAAA9mYWN0b3J5Q29udHJhY3QJAQAAABhyZWFkRmFjdG9yeUFkZHJlc3NPckZhaWwAAAAAAAAAAApmYWN0b3J5Q2ZnCQEAAAAUcmVhZEZhY3RvcnlDZmdPckZhaWwAAAABBQAAAA9mYWN0b3J5Q29udHJhY3QAAAAAEGVtaXNzaW9uQ29udHJhY3QJAQAAABhnZXRFbWlzc2lvbkFkZHJlc3NPckZhaWwAAAABBQAAAApmYWN0b3J5Q2ZnAAAAAA9zdGFraW5nQ29udHJhY3QJAQAAABdnZXRTdGFraW5nQWRkcmVzc09yRmFpbAAAAAEFAAAACmZhY3RvcnlDZmcAAAAAEWd3eFJld2FyZENvbnRyYWN0CQEAAAAZZ2V0R3d4UmV3YXJkQWRkcmVzc09yRmFpbAAAAAEFAAAACmZhY3RvcnlDZmcBAAAADEhpc3RvcnlFbnRyeQAAAAgAAAAEdHlwZQAAAAR1c2VyAAAABmFtb3VudAAAAAlsb2NrU3RhcnQAAAAIZHVyYXRpb24AAAABawAAAAFiAAAAAWkEAAAACmhpc3RvcnlLRVkJAAS5AAAAAgkABEwAAAACAgAAABElcyVzJXMlc19faGlzdG9yeQkABEwAAAACBQAAAAR0eXBlCQAETAAAAAIFAAAABHVzZXIJAARMAAAAAgkAAlgAAAABCAUAAAABaQAAAA10cmFuc2FjdGlvbklkBQAAAANuaWwFAAAAA1NFUAQAAAALaGlzdG9yeURBVEEJAAS5AAAAAgkABEwAAAACAgAAAA4lZCVkJWQlZCVkJWQlZAkABEwAAAACCQABpAAAAAEIBQAAAAlsYXN0QmxvY2sAAAAGaGVpZ2h0CQAETAAAAAIJAAGkAAAAAQgFAAAACWxhc3RCbG9jawAAAAl0aW1lc3RhbXAJAARMAAAAAgkAAaQAAAABBQAAAAZhbW91bnQJAARMAAAAAgkAAaQAAAABBQAAAAlsb2NrU3RhcnQJAARMAAAAAgkAAaQAAAABBQAAAAhkdXJhdGlvbgkABEwAAAACCQABpAAAAAEFAAAAAWsJAARMAAAAAgkAAaQAAAABBQAAAAFiBQAAAANuaWwFAAAAA1NFUAkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAAKaGlzdG9yeUtFWQUAAAALaGlzdG9yeURBVEEBAAAAClN0YXRzRW50cnkAAAAEAAAADnRvdGFsTG9ja2VkSW5jAAAAC2R1cmF0aW9uSW5jAAAADGxvY2tDb3VudEluYwAAAA11c2Vyc0NvdW50SW5jBAAAABtsb2Nrc0R1cmF0aW9uU3VtSW5CbG9ja3NLRVkJAQAAACBrZXlTdGF0c0xvY2tzRHVyYXRpb25TdW1JbkJsb2NrcwAAAAAEAAAADWxvY2tzQ291bnRLRVkJAQAAABJrZXlTdGF0c0xvY2tzQ291bnQAAAAABAAAAA11c2Vyc0NvdW50S0VZCQEAAAASa2V5U3RhdHNVc2Vyc0NvdW50AAAAAAQAAAAOdG90YWxBbW91bnRLRVkJAQAAABdrZXlMb2NrUGFyYW1Ub3RhbEFtb3VudAAAAAAEAAAAGGxvY2tzRHVyYXRpb25TdW1JbkJsb2NrcwkBAAAAA2lvegAAAAIFAAAABHRoaXMFAAAAG2xvY2tzRHVyYXRpb25TdW1JbkJsb2Nrc0tFWQQAAAAKbG9ja3NDb3VudAkBAAAAA2lvegAAAAIFAAAABHRoaXMFAAAADWxvY2tzQ291bnRLRVkEAAAACnVzZXJzQ291bnQJAQAAAANpb3oAAAACBQAAAAR0aGlzBQAAAA11c2Vyc0NvdW50S0VZBAAAAAt0b3RhbEFtb3VudAkBAAAAA2lvegAAAAIFAAAABHRoaXMFAAAADnRvdGFsQW1vdW50S0VZCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABtsb2Nrc0R1cmF0aW9uU3VtSW5CbG9ja3NLRVkJAABkAAAAAgUAAAAYbG9ja3NEdXJhdGlvblN1bUluQmxvY2tzBQAAAAtkdXJhdGlvbkluYwkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAANbG9ja3NDb3VudEtFWQkAAGQAAAACBQAAAApsb2Nrc0NvdW50BQAAAAxsb2NrQ291bnRJbmMJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAADXVzZXJzQ291bnRLRVkJAABkAAAAAgUAAAAKdXNlcnNDb3VudAUAAAANdXNlcnNDb3VudEluYwkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAOdG90YWxBbW91bnRLRVkJAABkAAAAAgUAAAALdG90YWxBbW91bnQFAAAADnRvdGFsTG9ja2VkSW5jBQAAAANuaWwBAAAADWNhbGNHd3hBbW91bnQAAAADAAAABGtSYXcAAAAEYlJhdwAAAAFoBAAAAAVTQ0FMRQAAAAAAAAAD6AkAAGkAAAACCQAAZAAAAAIJAABoAAAAAgUAAAAEa1JhdwUAAAABaAUAAAAEYlJhdwUAAAAFU0NBTEUBAAAAD0xvY2tQYXJhbXNFbnRyeQAAAAgAAAALdXNlckFkZHJlc3MAAAAHdXNlck51bQAAAAZhbW91bnQAAAAFc3RhcnQAAAAIZHVyYXRpb24AAAABawAAAAFiAAAABnBlcmlvZAQAAAANdXNlckFtb3VudEtFWQkBAAAAFmtleUxvY2tQYXJhbVVzZXJBbW91bnQAAAABBQAAAAd1c2VyTnVtBAAAAA1zdGFydEJsb2NrS0VZCQEAAAAWa2V5TG9ja1BhcmFtU3RhcnRCbG9jawAAAAEFAAAAB3VzZXJOdW0EAAAAC2R1cmF0aW9uS0VZCQEAAAAUa2V5TG9ja1BhcmFtRHVyYXRpb24AAAABBQAAAAd1c2VyTnVtBAAAAARrS0VZCQEAAAANa2V5TG9ja1BhcmFtSwAAAAEFAAAAB3VzZXJOdW0EAAAABGJLRVkJAQAAAA1rZXlMb2NrUGFyYW1CAAAAAQUAAAAHdXNlck51bQQAAAAMa0J5UGVyaW9kS0VZCQEAAAAVa2V5TG9ja1BhcmFtQnlQZXJpb2RLAAAAAgUAAAAHdXNlck51bQUAAAAGcGVyaW9kBAAAAAxiQnlQZXJpb2RLRVkJAQAAABVrZXlMb2NrUGFyYW1CeVBlcmlvZEIAAAACBQAAAAd1c2VyTnVtBQAAAAZwZXJpb2QEAAAACWd3eEFtb3VudAkBAAAADWNhbGNHd3hBbW91bnQAAAADBQAAAAFrBQAAAAFiBQAAAAZoZWlnaHQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAADXVzZXJBbW91bnRLRVkFAAAABmFtb3VudAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAANc3RhcnRCbG9ja0tFWQUAAAAFc3RhcnQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAC2R1cmF0aW9uS0VZBQAAAAhkdXJhdGlvbgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAEa0tFWQUAAAABawkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAEYktFWQUAAAABYgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAMa0J5UGVyaW9kS0VZBQAAAAFrCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAxiQnlQZXJpb2RLRVkFAAAAAWIJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAE2tleUxvY2tQYXJhbXNSZWNvcmQAAAABBQAAAAt1c2VyQWRkcmVzcwkBAAAAFmZvcm1hdExvY2tQYXJhbXNSZWNvcmQAAAAHBQAAAAd1c2VyTnVtBQAAAAZhbW91bnQFAAAABXN0YXJ0BQAAAAhkdXJhdGlvbgUAAAABawUAAAABYgUAAAAJZ3d4QW1vdW50BQAAAANuaWwBAAAAImV4dHJhY3RPcHRpb25hbFBheW1lbnRBbW91bnRPckZhaWwAAAACAAAAAWkAAAAPZXhwZWN0ZWRBc3NldElkAwkAAGYAAAACCQABkAAAAAEIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAABCQAAAgAAAAECAAAAG29ubHkgb25lIHBheW1lbnQgaXMgYWxsb3dlZAMJAAAAAAAAAgkAAZAAAAABCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAAAAAAAAAAAAAQAAAADcG10CQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAwkBAAAAAiE9AAAAAgkBAAAABXZhbHVlAAAAAQgFAAAAA3BtdAAAAAdhc3NldElkBQAAAA9leHBlY3RlZEFzc2V0SWQJAAACAAAAAQIAAAAbaW52YWxpZCBhc3NldCBpZCBpbiBwYXltZW50CAUAAAADcG10AAAABmFtb3VudAEAAAAZY2FsY1VzZXJHd3hBbW91bnRBdEhlaWdodAAAAAIAAAALdXNlckFkZHJlc3MAAAAMdGFyZ2V0SGVpZ2h0BAAAAAVFTVBUWQIAAAAFZW1wdHkEAAAAEnVzZXIyTnVtTWFwcGluZ0tFWQkBAAAAEmtleVVzZXIyTnVtTWFwcGluZwAAAAEFAAAAC3VzZXJBZGRyZXNzBAAAAAd1c2VyTnVtCQEAAAALdmFsdWVPckVsc2UAAAACCQAEIgAAAAEFAAAAEnVzZXIyTnVtTWFwcGluZ0tFWQUAAAAFRU1QVFkEAAAAAWsJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQfAAAAAQkBAAAADWtleUxvY2tQYXJhbUsAAAABBQAAAAd1c2VyTnVtAAAAAAAAAAAABAAAAAFiCQEAAAALdmFsdWVPckVsc2UAAAACCQAEHwAAAAEJAQAAAA1rZXlMb2NrUGFyYW1CAAAAAQUAAAAHdXNlck51bQAAAAAAAAAAAAQAAAANZ3d4QW1vdW50Q2FsYwkBAAAADWNhbGNHd3hBbW91bnQAAAADBQAAAAFrBQAAAAFiBQAAAAx0YXJnZXRIZWlnaHQEAAAACWd3eEFtb3VudAMJAABmAAAAAgAAAAAAAAAAAAUAAAANZ3d4QW1vdW50Q2FsYwAAAAAAAAAAAAUAAAANZ3d4QW1vdW50Q2FsYwUAAAAJZ3d4QW1vdW50AQAAABRjYWxjQ3VycmVudEd3eEFtb3VudAAAAAEAAAALdXNlckFkZHJlc3MJAQAAABljYWxjVXNlckd3eEFtb3VudEF0SGVpZ2h0AAAAAgUAAAALdXNlckFkZHJlc3MFAAAABmhlaWdodAEAAAAUaW50ZXJuYWxDbGFpbVd4Qm9vc3QAAAADAAAADGxwQXNzZXRJZFN0cgAAAA51c2VyQWRkcmVzc1N0cgAAAAhyZWFkT25seQQAAAAFRU1QVFkCAAAABUVNUFRZBAAAABF1c2VyUmVjb3JkT3JFbXB0eQkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABB0AAAACBQAAAAR0aGlzCQEAAAATa2V5TG9ja1BhcmFtc1JlY29yZAAAAAEFAAAADnVzZXJBZGRyZXNzU3RyBQAAAAVFTVBUWQMJAAAAAAAAAgUAAAARdXNlclJlY29yZE9yRW1wdHkFAAAABUVNUFRZCQAFFQAAAAMAAAAAAAAAAAAFAAAAA25pbAIAAAAVdXNlclJlY29yZDo6aXM6OmVtcHR5BAAAAA91c2VyUmVjb3JkQXJyYXkJAAS1AAAAAgUAAAARdXNlclJlY29yZE9yRW1wdHkFAAAAA1NFUAQAAAAKdXNlck51bVN0cgkAAZEAAAACBQAAAA91c2VyUmVjb3JkQXJyYXkFAAAADklkeExvY2tVc2VyTnVtBAAAABxnd3hSZXdhcmRFbWlzc2lvblN0YXJ0SGVpZ2h0CQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAAEWd3eFJld2FyZENvbnRyYWN0CQEAAAAfa2V5R3d4UmV3YXJkRW1pc3Npb25TdGFydEhlaWdodAAAAAAAAAAAAAAAAAAEAAAACEVNUFRZU1RSAgAAAAVlbXB0eQQAAAANJHQwMTMxNjcxMzczNQMJAQAAAAIhPQAAAAIFAAAADGxwQXNzZXRJZFN0cgUAAAAIRU1QVFlTVFIEAAAADnBvb2xBZGRyZXNzU3RyCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQdAAAAAgUAAAAPZmFjdG9yeUNvbnRyYWN0CQEAAAAaa2V5RmFjdG9yeUxwMkFzc2V0c01hcHBpbmcAAAABBQAAAAxscEFzc2V0SWRTdHIJAAEsAAAAAgIAAAAVdW5zdXBwb3J0ZWQgbHAgYXNzZXQgBQAAAAxscEFzc2V0SWRTdHIEAAAAA3B3MQkBAAAAEUBleHRyTmF0aXZlKDEwNTApAAAAAgUAAAAPZmFjdG9yeUNvbnRyYWN0CQEAAAAUa2V5RmFjdG9yeVBvb2xXZWlnaHQAAAABBQAAAA5wb29sQWRkcmVzc1N0cgQAAAADcHcwCQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAAD2ZhY3RvcnlDb250cmFjdAkBAAAAG2tleUZhY3RvcnlQb29sV2VpZ2h0SGlzdG9yeQAAAAIFAAAADnBvb2xBZGRyZXNzU3RyAAAAAAAAAAAABQAAAANwdzEJAAUUAAAAAgUAAAADcHcwBQAAAANwdzEDBQAAAAhyZWFkT25seQkABRQAAAACAAAAAAAAAAAAAAAAAAAAAAAACQAAAgAAAAEJAAEsAAAAAgIAAAAobm90IHJlYWRvbmx5IG1vZGU6IHVuc3VwcG9ydGVkIGxwIGFzc2V0IAUAAAAMbHBBc3NldElkU3RyBAAAAAtwb29sV2VpZ2h0MAgFAAAADSR0MDEzMTY3MTM3MzUAAAACXzEEAAAAC3Bvb2xXZWlnaHQxCAUAAAANJHQwMTMxNjcxMzczNQAAAAJfMgQAAAASd3hFbWlzc2lvblBlckJsb2NrCQEAAAADaW9mAAAAAgUAAAAQZW1pc3Npb25Db250cmFjdAkBAAAAHmtleUVtaXNzaW9uUmF0ZVBlckJsb2NrQ3VycmVudAAAAAAEAAAADWVtaXNzaW9uU3RhcnQJAQAAAANpb2YAAAACBQAAABBlbWlzc2lvbkNvbnRyYWN0CQEAAAAVa2V5RW1pc3Npb25TdGFydEJsb2NrAAAAAAQAAAALZW1pc3Npb25FbmQJAQAAAANpb2YAAAACBQAAABBlbWlzc2lvbkNvbnRyYWN0CQEAAAATa2V5RW1pc3Npb25FbmRCbG9jawAAAAAEAAAAAWgDCQAAZgAAAAIFAAAABmhlaWdodAUAAAALZW1pc3Npb25FbmQFAAAAC2VtaXNzaW9uRW5kBQAAAAZoZWlnaHQEAAAAAmRoCQABlgAAAAEJAARMAAAAAgkAAGUAAAACBQAAAAFoBQAAAA1lbWlzc2lvblN0YXJ0CQAETAAAAAIAAAAAAAAAAAAFAAAAA25pbAQAAAAidXNlckxwQm9vc3RFbWlzc2lvbkxhc3RJbnRlZ3JhbEtFWQkBAAAAImtleVVzZXJMcEJvb3N0RW1pc3Npb25MYXN0SU5URUdSQUwAAAACBQAAAAp1c2VyTnVtU3RyBQAAAAxscEFzc2V0SWRTdHIEAAAAIHVzZXJCb29zdEVtaXNzaW9uTGFzdEludGVncmFsS0VZCQEAAAAga2V5VXNlckJvb3N0RW1pc3Npb25MYXN0SU5URUdSQUwAAAABBQAAAAp1c2VyTnVtU3RyBAAAAB11c2VyQm9vc3RFbWlzc2lvbkxhc3RJbnRlZ3JhbAkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAR0aGlzBQAAACJ1c2VyTHBCb29zdEVtaXNzaW9uTGFzdEludGVncmFsS0VZCQEAAAADaW96AAAAAgUAAAAEdGhpcwUAAAAgdXNlckJvb3N0RW1pc3Npb25MYXN0SW50ZWdyYWxLRVkEAAAAFWJvb3N0RW1pc3Npb25JbnRlZ3JhbAkAAGkAAAACCQAAaAAAAAIJAABoAAAAAgUAAAASd3hFbWlzc2lvblBlckJsb2NrBQAAAAJkaAAAAAAAAAAAAgAAAAAAAAAAAwQAAAAZdXNlckJvb3N0RW1pc3Npb25JbnRlZ3JhbAkAAGUAAAACBQAAABVib29zdEVtaXNzaW9uSW50ZWdyYWwFAAAAHXVzZXJCb29zdEVtaXNzaW9uTGFzdEludGVncmFsBAAAAAN1ZGgJAABrAAAAAwUAAAAZdXNlckJvb3N0RW1pc3Npb25JbnRlZ3JhbAAAAAAAAAAAAwkAAGgAAAACAAAAAAAAAAACBQAAABJ3eEVtaXNzaW9uUGVyQmxvY2sEAAAABnVMYXN0SAkAAGUAAAACBQAAAAFoBQAAAAN1ZGgEAAAABHVkaDAJAAGWAAAAAQkABEwAAAACCQAAZQAAAAIFAAAAHGd3eFJld2FyZEVtaXNzaW9uU3RhcnRIZWlnaHQFAAAABnVMYXN0SAkABEwAAAACAAAAAAAAAAAABQAAAANuaWwEAAAABHVkaDEJAABlAAAAAgkAAGUAAAACBQAAAAFoBQAAAAZ1TGFzdEgFAAAABHVkaDADAwMJAABmAAAAAgAAAAAAAAAAAAUAAAAGdUxhc3RIBgkAAGYAAAACAAAAAAAAAAAABQAAAAR1ZGgxBgkAAGcAAAACCQEAAAADYWJzAAAAAQkAAGUAAAACCQAAZAAAAAIFAAAABHVkaDAFAAAABHVkaDEFAAAAA3VkaAAAAAAAAAAAAQkAAAIAAAABCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAFmludmFsaWQgdWRoIGNhbGM6IHVkaD0JAAGkAAAAAQUAAAADdWRoAgAAAAggdUxhc3RIPQkAAaQAAAABBQAAAAZ1TGFzdEgCAAAABiB1ZGgwPQkAAaQAAAABBQAAAAR1ZGgwAgAAAAYgdWRoMT0JAAGkAAAAAQUAAAAEdWRoMQMJAABmAAAAAgAAAAAAAAAAAAUAAAAZdXNlckJvb3N0RW1pc3Npb25JbnRlZ3JhbAkAAAIAAAABAgAAABJ3cm9uZyBjYWxjdWxhdGlvbnMEAAAAF3VzZXJNYXhCb29zdEludGVncmFsS0VZCQEAAAAXa2V5VXNlck1heEJvb3N0SU5URUdSQUwAAAABBQAAAAp1c2VyTnVtU3RyBAAAABh0b3RhbE1heEJvb3N0SW50ZWdyYWxLRVkJAQAAABhrZXlUb3RhbE1heEJvb3N0SU5URUdSQUwAAAAABAAAAA91c2VyTWF4Qm9vc3RJbnQJAQAAAANpb3oAAAACBQAAAAR0aGlzBQAAABd1c2VyTWF4Qm9vc3RJbnRlZ3JhbEtFWQQAAAAQdG90YWxNYXhCb29zdEludAkBAAAAA2lvegAAAAIFAAAABHRoaXMFAAAAGHRvdGFsTWF4Qm9vc3RJbnRlZ3JhbEtFWQQAAAARdG90YWxDYWNoZWRHd3hLRVkJAQAAABFrZXlUb3RhbENhY2hlZEd3eAAAAAAEAAAADnRvdGFsQ2FjaGVkR3d4CQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAABHRoaXMFAAAAEXRvdGFsQ2FjaGVkR3d4S0VZAAAAAAAAAAAABAAAAAt1c2VyQ3Vyckd3eAkBAAAAFGNhbGNDdXJyZW50R3d4QW1vdW50AAAAAQUAAAAOdXNlckFkZHJlc3NTdHIEAAAAIXVzZXJCb29zdEF2YWxhaWJsZVRvQ2xhaW1Ub3RhbEtFWQkBAAAAIWtleVVzZXJCb29zdEF2YWxhaWJsZVRvQ2xhaW1Ub3RhbAAAAAEFAAAACnVzZXJOdW1TdHIEAAAAHnVzZXJCb29zdEF2YWxpYWJsZVRvQ2xhaW1Ub3RhbAkBAAAAA2lvegAAAAIFAAAABHRoaXMFAAAAIXVzZXJCb29zdEF2YWxhaWJsZVRvQ2xhaW1Ub3RhbEtFWQQAAAAadXNlckJvb3N0RW1pc3Npb25JbnRlZ3JhbDAJAABrAAAAAwUAAAAZdXNlckJvb3N0RW1pc3Npb25JbnRlZ3JhbAUAAAAEdWRoMAUAAAADdWRoBAAAABp1c2VyQm9vc3RFbWlzc2lvbkludGVncmFsMQkAAGsAAAADBQAAABl1c2VyQm9vc3RFbWlzc2lvbkludGVncmFsBQAAAAR1ZGgxBQAAAAN1ZGgEAAAAHnBvb2xVc2VyQm9vc3RFbWlzc2lvbkludGVncmFsMAkAAGsAAAADBQAAABp1c2VyQm9vc3RFbWlzc2lvbkludGVncmFsMAUAAAALcG9vbFdlaWdodDAFAAAADlBPT0xXRUlHSFRNVUxUBAAAAB5wb29sVXNlckJvb3N0RW1pc3Npb25JbnRlZ3JhbDEJAABrAAAAAwUAAAAadXNlckJvb3N0RW1pc3Npb25JbnRlZ3JhbDEFAAAAC3Bvb2xXZWlnaHQxBQAAAA5QT09MV0VJR0hUTVVMVAQAAAAidXNlckJvb3N0QXZhbGlhYmxlVG9DbGFpbVRvdGFsTmV3MAMJAAAAAAAAAgUAAAAOdG90YWxDYWNoZWRHd3gAAAAAAAAAAAAAAAAAAAAAAAAJAABrAAAAAwUAAAAecG9vbFVzZXJCb29zdEVtaXNzaW9uSW50ZWdyYWwwBQAAAAt1c2VyQ3Vyckd3eAUAAAAOdG90YWxDYWNoZWRHd3gEAAAAInVzZXJCb29zdEF2YWxpYWJsZVRvQ2xhaW1Ub3RhbE5ldzEDCQAAAAAAAAIFAAAADnRvdGFsQ2FjaGVkR3d4AAAAAAAAAAAAAAAAAAAAAAAACQAAawAAAAMFAAAAHnBvb2xVc2VyQm9vc3RFbWlzc2lvbkludGVncmFsMQUAAAALdXNlckN1cnJHd3gFAAAADnRvdGFsQ2FjaGVkR3d4BAAAACF1c2VyQm9vc3RBdmFsaWFibGVUb0NsYWltVG90YWxOZXcJAABkAAAAAgUAAAAidXNlckJvb3N0QXZhbGlhYmxlVG9DbGFpbVRvdGFsTmV3MAUAAAAidXNlckJvb3N0QXZhbGlhYmxlVG9DbGFpbVRvdGFsTmV3MQQAAAATdXNlckJvb3N0Q2xhaW1lZEtFWQkBAAAAE2tleVVzZXJCb29zdENsYWltZWQAAAABBQAAAAp1c2VyTnVtU3RyBAAAABB1c2VyQm9vc3RDbGFpbWVkCQEAAAADaW96AAAAAgUAAAAEdGhpcwUAAAATdXNlckJvb3N0Q2xhaW1lZEtFWQQAAAASdXNlckJvb3N0QXZhaWxhYmxlCQAAZQAAAAIFAAAAIXVzZXJCb29zdEF2YWxpYWJsZVRvQ2xhaW1Ub3RhbE5ldwUAAAAQdXNlckJvb3N0Q2xhaW1lZAQAAAAJZGF0YVN0YXRlCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAACJ1c2VyTHBCb29zdEVtaXNzaW9uTGFzdEludGVncmFsS0VZBQAAABVib29zdEVtaXNzaW9uSW50ZWdyYWwFAAAAA25pbAQAAAAFZGVidWcJAAS5AAAAAgkABEwAAAACCQABLAAAAAICAAAAHnVzZXJCb29zdEVtaXNzaW9uTGFzdEludGVncmFsPQkAAaQAAAABBQAAAB11c2VyQm9vc3RFbWlzc2lvbkxhc3RJbnRlZ3JhbAkABEwAAAACCQABLAAAAAICAAAAGnVzZXJCb29zdEVtaXNzaW9uSW50ZWdyYWw9CQABpAAAAAEFAAAAGXVzZXJCb29zdEVtaXNzaW9uSW50ZWdyYWwJAARMAAAAAgkAASwAAAACAgAAABB1c2VyTWF4Qm9vc3RJbnQ9CQABpAAAAAEFAAAAD3VzZXJNYXhCb29zdEludAkABEwAAAACCQABLAAAAAICAAAAEXRvdGFsTWF4Qm9vc3RJbnQ9CQABpAAAAAEFAAAAEHRvdGFsTWF4Qm9vc3RJbnQJAARMAAAAAgkAASwAAAACAgAAAB91c2VyQm9vc3RBdmFsaWFibGVUb0NsYWltVG90YWw9CQABpAAAAAEFAAAAHnVzZXJCb29zdEF2YWxpYWJsZVRvQ2xhaW1Ub3RhbAkABEwAAAACCQABLAAAAAICAAAAInVzZXJCb29zdEF2YWxpYWJsZVRvQ2xhaW1Ub3RhbE5ldz0JAAGkAAAAAQUAAAAhdXNlckJvb3N0QXZhbGlhYmxlVG9DbGFpbVRvdGFsTmV3CQAETAAAAAIJAAEsAAAAAgIAAAARdXNlckJvb3N0Q2xhaW1lZD0JAAGkAAAAAQUAAAAQdXNlckJvb3N0Q2xhaW1lZAkABEwAAAACCQABLAAAAAICAAAAE3VzZXJCb29zdEF2YWlsYWJsZT0JAAGkAAAAAQUAAAASdXNlckJvb3N0QXZhaWxhYmxlCQAETAAAAAIJAAEsAAAAAgIAAAAbdXNlckJvb3N0RW1pc3Npb25JbnRlZ3JhbDA9CQABpAAAAAEFAAAAGnVzZXJCb29zdEVtaXNzaW9uSW50ZWdyYWwwCQAETAAAAAIJAAEsAAAAAgIAAAAbdXNlckJvb3N0RW1pc3Npb25JbnRlZ3JhbDE9CQABpAAAAAEFAAAAGnVzZXJCb29zdEVtaXNzaW9uSW50ZWdyYWwxCQAETAAAAAIJAAEsAAAAAgIAAAAfcG9vbFVzZXJCb29zdEVtaXNzaW9uSW50ZWdyYWwwPQkAAaQAAAABBQAAAB5wb29sVXNlckJvb3N0RW1pc3Npb25JbnRlZ3JhbDAJAARMAAAAAgkAASwAAAACAgAAAB9wb29sVXNlckJvb3N0RW1pc3Npb25JbnRlZ3JhbDE9CQABpAAAAAEFAAAAHnBvb2xVc2VyQm9vc3RFbWlzc2lvbkludGVncmFsMQkABEwAAAACCQABLAAAAAICAAAADHBvb2xXZWlnaHQwPQkAAaQAAAABBQAAAAtwb29sV2VpZ2h0MAkABEwAAAACCQABLAAAAAICAAAADHBvb2xXZWlnaHQxPQkAAaQAAAABBQAAAAtwb29sV2VpZ2h0MQkABEwAAAACCQABLAAAAAICAAAAAmg9CQABpAAAAAEFAAAAAWgJAARMAAAAAgkAASwAAAACAgAAAAR1ZGg9CQABpAAAAAEFAAAAA3VkaAkABEwAAAACCQABLAAAAAICAAAAB3VMYXN0SD0JAAGkAAAAAQUAAAAGdUxhc3RICQAETAAAAAIJAAEsAAAAAgIAAAAFdWRoMD0JAAGkAAAAAQUAAAAEdWRoMAkABEwAAAACCQABLAAAAAICAAAABXVkaDE9CQABpAAAAAEFAAAABHVkaDEJAARMAAAAAgkAASwAAAACAgAAAAx1c2VyQ3Vyckd3eD0JAAGkAAAAAQUAAAALdXNlckN1cnJHd3gJAARMAAAAAgkAASwAAAACAgAAAA90b3RhbENhY2hlZEd3eD0JAAGkAAAAAQUAAAAOdG90YWxDYWNoZWRHd3gFAAAAA25pbAIAAAACOjoJAAUVAAAAAwUAAAAhdXNlckJvb3N0QXZhbGlhYmxlVG9DbGFpbVRvdGFsTmV3BQAAAAlkYXRhU3RhdGUFAAAABWRlYnVnAAAACgAAAAFpAQAAAAtjb25zdHJ1Y3RvcgAAAAYAAAARZmFjdG9yeUFkZHJlc3NTdHIAAAAObG9ja0Fzc2V0SWRTdHIAAAANbWluTG9ja0Ftb3VudAAAAAttaW5EdXJhdGlvbgAAAAttYXhEdXJhdGlvbgAAAAxtYXRoQ29udHJhY3QEAAAAC2NoZWNrQ2FsbGVyCQEAAAALbXVzdE1hbmFnZXIAAAABBQAAAAFpAwkAAAAAAAACBQAAAAtjaGVja0NhbGxlcgUAAAALY2hlY2tDYWxsZXIJAAROAAAAAgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAADmtleU5leHRVc2VyTnVtAAAAAAAAAAAAAAAAAAkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAAJa2V5Q29uZmlnAAAAAAkBAAAADGZvcm1hdENvbmZpZwAAAAUFAAAADmxvY2tBc3NldElkU3RyBQAAAA1taW5Mb2NrQW1vdW50BQAAAAttaW5EdXJhdGlvbgUAAAALbWF4RHVyYXRpb24FAAAADG1hdGhDb250cmFjdAkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAARa2V5RmFjdG9yeUFkZHJlc3MAAAAABQAAABFmYWN0b3J5QWRkcmVzc1N0cgUAAAADbmlsCQEAAAAKU3RhdHNFbnRyeQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAAAAAWkBAAAABGxvY2sAAAABAAAACGR1cmF0aW9uBAAAAAhjZmdBcnJheQkBAAAAFXJlYWRDb25maWdBcnJheU9yRmFpbAAAAAAEAAAACmFzc2V0SWRTdHIJAAGRAAAAAgUAAAAIY2ZnQXJyYXkFAAAADUlkeENmZ0Fzc2V0SWQEAAAAB2Fzc2V0SWQJAAJZAAAAAQUAAAAKYXNzZXRJZFN0cgQAAAANbWluTG9ja0Ftb3VudAkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAACGNmZ0FycmF5BQAAABNJZHhDZmdNaW5Mb2NrQW1vdW50BAAAAA9taW5Mb2NrRHVyYXRpb24JAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAAAhjZmdBcnJheQUAAAAVSWR4Q2ZnTWluTG9ja0R1cmF0aW9uBAAAAA9tYXhMb2NrRHVyYXRpb24JAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAAAhjZmdBcnJheQUAAAAVSWR4Q2ZnTWF4TG9ja0R1cmF0aW9uBAAAAAxtYXRoQ29udHJhY3QJAQAAABFAZXh0ck5hdGl2ZSgxMDYyKQAAAAEJAAGRAAAAAgUAAAAIY2ZnQXJyYXkFAAAAEklkeENmZ01hdGhDb250cmFjdAMJAQAAAAIhPQAAAAIJAAGQAAAAAQgFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAEJAAACAAAAAQIAAAA0aW52YWxpZCBwYXltZW50IC0gZXhhY3Qgb25lIHBheW1lbnQgbXVzdCBiZSBhdHRhY2hlZAQAAAADcG10CQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAABAAAAAlwbXRBbW91bnQIBQAAAANwbXQAAAAGYW1vdW50AwkBAAAAAiE9AAAAAgUAAAAHYXNzZXRJZAkBAAAABXZhbHVlAAAAAQgFAAAAA3BtdAAAAAdhc3NldElkCQAAAgAAAAEJAAEsAAAAAgkAASwAAAACAgAAAB5pbnZhbGlkIGFzc2V0IGlzIGluIHBheW1lbnQgLSAFAAAACmFzc2V0SWRTdHICAAAADCBpcyBleHBlY3RlZAQAAAAObmV4dFVzZXJOdW1LRVkJAQAAAA5rZXlOZXh0VXNlck51bQAAAAAEAAAADnVzZXJBZGRyZXNzU3RyCQAEJQAAAAEIBQAAAAFpAAAABmNhbGxlcgQAAAAOdXNlcklzRXhpc3RpbmcJAQAAAAlpc0RlZmluZWQAAAABCQAEIgAAAAEJAQAAABJrZXlVc2VyMk51bU1hcHBpbmcAAAABBQAAAA51c2VyQWRkcmVzc1N0cgQAAAAKdXNlck51bVN0cgMFAAAADnVzZXJJc0V4aXN0aW5nCQEAAAAFdmFsdWUAAAABCQAEIgAAAAEJAQAAABJrZXlVc2VyMk51bU1hcHBpbmcAAAABBQAAAA51c2VyQWRkcmVzc1N0cgkAAaQAAAABCQEAAAADaW9mAAAAAgUAAAAEdGhpcwUAAAAObmV4dFVzZXJOdW1LRVkEAAAAB3VzZXJOdW0JAQAAAA1wYXJzZUludFZhbHVlAAAAAQUAAAAKdXNlck51bVN0cgQAAAAJbG9ja1N0YXJ0BQAAAAZoZWlnaHQEAAAADXN0YXJ0QmxvY2tLRVkJAQAAABZrZXlMb2NrUGFyYW1TdGFydEJsb2NrAAAAAQUAAAAKdXNlck51bVN0cgQAAAALZHVyYXRpb25LRVkJAQAAABRrZXlMb2NrUGFyYW1EdXJhdGlvbgAAAAEFAAAACnVzZXJOdW1TdHIEAAAADXVzZXJBbW91bnRLRVkJAQAAABZrZXlMb2NrUGFyYW1Vc2VyQW1vdW50AAAAAQUAAAAKdXNlck51bVN0cgMJAABmAAAAAgUAAAANbWluTG9ja0Ftb3VudAUAAAAJcG10QW1vdW50CQAAAgAAAAEJAAEsAAAAAgIAAAAiYW1vdW50IGlzIGxlc3MgdGhlbiBtaW5Mb2NrQW1vdW50PQkAAaQAAAABBQAAAA1taW5Mb2NrQW1vdW50AwkAAGYAAAACBQAAAA9taW5Mb2NrRHVyYXRpb24FAAAACGR1cmF0aW9uCQAAAgAAAAEJAAEsAAAAAgIAAAAtcGFzc2VkIGR1cmF0aW9uIGlzIGxlc3MgdGhlbiBtaW5Mb2NrRHVyYXRpb249CQABpAAAAAEFAAAAD21pbkxvY2tEdXJhdGlvbgMJAABmAAAAAgUAAAAIZHVyYXRpb24FAAAAD21heExvY2tEdXJhdGlvbgkAAAIAAAABCQABLAAAAAICAAAAMHBhc3NlZCBkdXJhdGlvbiBpcyBncmVhdGVyIHRoZW4gbWF4TG9ja0R1cmF0aW9uPQkAAaQAAAABBQAAAA9tYXhMb2NrRHVyYXRpb24DAwUAAAAOdXNlcklzRXhpc3RpbmcJAABnAAAAAgkAAGQAAAACCQEAAAADaW9mAAAAAgUAAAAEdGhpcwUAAAANc3RhcnRCbG9ja0tFWQkBAAAAA2lvZgAAAAIFAAAABHRoaXMFAAAAC2R1cmF0aW9uS0VZBQAAAAlsb2NrU3RhcnQHCQAAAgAAAAECAAAANnRoZXJlIGlzIGFuIGFjdGl2ZSBsb2NrIC0gY29uc2lkZXIgdG8gdXNlIGluY3JlYXNlTG9jawMJAABmAAAAAgkBAAAAA2lvegAAAAIFAAAABHRoaXMFAAAADXVzZXJBbW91bnRLRVkAAAAAAAAAAAAJAAACAAAAAQkAASwAAAACAgAAADR0aGVyZSBhcmUgbG9ja2VkIFdYcyAtIGNvbnNpZGVyIHRvIHVzZSBpbmNyZWFzZUxvY2sgBQAAAA11c2VyQW1vdW50S0VZBAAAAAdjb2VmZlg4CQAAawAAAAMFAAAACGR1cmF0aW9uBQAAAAVNVUxUOAUAAAAPbWF4TG9ja0R1cmF0aW9uBAAAAA5nV3hBbW91bnRTdGFydAkAAGsAAAADBQAAAAlwbXRBbW91bnQFAAAAB2NvZWZmWDgFAAAABU1VTFQ4BAAAABNnV3hQYXJhbXNSZXN1bHRMaXN0CQEAAAADYWFsAAAAAQkAA/wAAAAEBQAAAAxtYXRoQ29udHJhY3QCAAAAFWNhbGNHd3hQYXJhbXNSRUFET05MWQkABEwAAAACBQAAAA5nV3hBbW91bnRTdGFydAkABEwAAAACBQAAAAlsb2NrU3RhcnQJAARMAAAAAgUAAAAIZHVyYXRpb24FAAAAA25pbAUAAAADbmlsBAAAAAFrCQEAAAACYWkAAAABCQABkQAAAAIFAAAAE2dXeFBhcmFtc1Jlc3VsdExpc3QAAAAAAAAAAAAEAAAAAWIJAQAAAAJhaQAAAAEJAAGRAAAAAgUAAAATZ1d4UGFyYW1zUmVzdWx0TGlzdAAAAAAAAAAAAQQAAAAGcGVyaW9kCQABpAAAAAEJAQAAAAJhaQAAAAEJAAGRAAAAAgUAAAATZ1d4UGFyYW1zUmVzdWx0TGlzdAAAAAAAAAAAAgQAAAASd3hFbWlzc2lvblBlckJsb2NrCQEAAAADaW9mAAAAAgUAAAAQZW1pc3Npb25Db250cmFjdAkBAAAAHmtleUVtaXNzaW9uUmF0ZVBlckJsb2NrQ3VycmVudAAAAAAEAAAADWVtaXNzaW9uU3RhcnQJAQAAAANpb2YAAAACBQAAABBlbWlzc2lvbkNvbnRyYWN0CQEAAAAVa2V5RW1pc3Npb25TdGFydEJsb2NrAAAAAAQAAAALZW1pc3Npb25FbmQJAQAAAANpb2YAAAACBQAAABBlbWlzc2lvbkNvbnRyYWN0CQEAAAATa2V5RW1pc3Npb25FbmRCbG9jawAAAAAEAAAAAWgDCQAAZgAAAAIFAAAABmhlaWdodAUAAAALZW1pc3Npb25FbmQFAAAAC2VtaXNzaW9uRW5kBQAAAAZoZWlnaHQEAAAAAmRoCQABlgAAAAEJAARMAAAAAgkAAGUAAAACBQAAAAFoBQAAAA1lbWlzc2lvblN0YXJ0CQAETAAAAAIAAAAAAAAAAAAFAAAAA25pbAQAAAAgdXNlckJvb3N0RW1pc3Npb25MYXN0SW50ZWdyYWxLRVkJAQAAACBrZXlVc2VyQm9vc3RFbWlzc2lvbkxhc3RJTlRFR1JBTAAAAAEFAAAACnVzZXJOdW1TdHIEAAAAFWJvb3N0RW1pc3Npb25JbnRlZ3JhbAkAAGkAAAACCQAAaAAAAAIJAABoAAAAAgUAAAASd3hFbWlzc2lvblBlckJsb2NrBQAAAAJkaAAAAAAAAAAAAgAAAAAAAAAAAwQAAAAXdXNlck1heEJvb3N0SW50ZWdyYWxLRVkJAQAAABdrZXlVc2VyTWF4Qm9vc3RJTlRFR1JBTAAAAAEFAAAACnVzZXJOdW1TdHIEAAAAGHRvdGFsTWF4Qm9vc3RJbnRlZ3JhbEtFWQkBAAAAGGtleVRvdGFsTWF4Qm9vc3RJTlRFR1JBTAAAAAAEAAAAD3VzZXJNYXhCb29zdEludAkAAGkAAAACCQAAaAAAAAIFAAAADmdXeEFtb3VudFN0YXJ0BQAAAAhkdXJhdGlvbgAAAAAAAAAAAgQAAAAQdG90YWxNYXhCb29zdEludAkBAAAAA2lvegAAAAIFAAAABHRoaXMFAAAAGHRvdGFsTWF4Qm9vc3RJbnRlZ3JhbEtFWQQAAAARdG90YWxDYWNoZWRHd3hLRVkJAQAAABFrZXlUb3RhbENhY2hlZEd3eAAAAAAEAAAADnRvdGFsQ2FjaGVkR3d4CQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAABHRoaXMFAAAAEXRvdGFsQ2FjaGVkR3d4S0VZAAAAAAAAAAAABAAAAANhcnIDBQAAAA51c2VySXNFeGlzdGluZwUAAAADbmlsCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAA5uZXh0VXNlck51bUtFWQkAAGQAAAACBQAAAAd1c2VyTnVtAAAAAAAAAAABCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAABJrZXlVc2VyMk51bU1hcHBpbmcAAAABBQAAAA51c2VyQWRkcmVzc1N0cgUAAAAKdXNlck51bVN0cgkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAASa2V5TnVtMlVzZXJNYXBwaW5nAAAAAQUAAAAKdXNlck51bVN0cgUAAAAOdXNlckFkZHJlc3NTdHIFAAAAA25pbAkABE4AAAACCQAETQAAAAIJAAROAAAAAgkABE4AAAACBQAAAANhcnIJAQAAAA9Mb2NrUGFyYW1zRW50cnkAAAAIBQAAAA51c2VyQWRkcmVzc1N0cgUAAAAKdXNlck51bVN0cgUAAAAJcG10QW1vdW50BQAAAAlsb2NrU3RhcnQFAAAACGR1cmF0aW9uBQAAAAFrBQAAAAFiBQAAAAZwZXJpb2QJAQAAAApTdGF0c0VudHJ5AAAABAUAAAAJcG10QW1vdW50BQAAAAhkdXJhdGlvbgAAAAAAAAAAAQMFAAAADnVzZXJJc0V4aXN0aW5nAAAAAAAAAAAAAAAAAAAAAAABCQEAAAAMSGlzdG9yeUVudHJ5AAAACAIAAAAEbG9jawUAAAAOdXNlckFkZHJlc3NTdHIFAAAACXBtdEFtb3VudAUAAAAJbG9ja1N0YXJ0BQAAAAhkdXJhdGlvbgUAAAABawUAAAABYgUAAAABaQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAgdXNlckJvb3N0RW1pc3Npb25MYXN0SW50ZWdyYWxLRVkFAAAAFWJvb3N0RW1pc3Npb25JbnRlZ3JhbAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAARdG90YWxDYWNoZWRHd3hLRVkJAABkAAAAAgUAAAAOdG90YWxDYWNoZWRHd3gFAAAADmdXeEFtb3VudFN0YXJ0BQAAAANuaWwAAAABaQEAAAAMaW5jcmVhc2VMb2NrAAAAAQAAAA1kZWx0YUR1cmF0aW9uBAAAAAhjZmdBcnJheQkBAAAAFXJlYWRDb25maWdBcnJheU9yRmFpbAAAAAAEAAAACmFzc2V0SWRTdHIJAAGRAAAAAgUAAAAIY2ZnQXJyYXkFAAAADUlkeENmZ0Fzc2V0SWQEAAAAB2Fzc2V0SWQJAAJZAAAAAQUAAAAKYXNzZXRJZFN0cgQAAAAPbWluTG9ja0R1cmF0aW9uCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAIY2ZnQXJyYXkFAAAAFUlkeENmZ01pbkxvY2tEdXJhdGlvbgQAAAAPbWF4TG9ja0R1cmF0aW9uCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAIY2ZnQXJyYXkFAAAAFUlkeENmZ01heExvY2tEdXJhdGlvbgQAAAAMbWF0aENvbnRyYWN0CQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABCQABkQAAAAIFAAAACGNmZ0FycmF5BQAAABJJZHhDZmdNYXRoQ29udHJhY3QEAAAACXBtdEFtb3VudAkBAAAAImV4dHJhY3RPcHRpb25hbFBheW1lbnRBbW91bnRPckZhaWwAAAACBQAAAAFpBQAAAAdhc3NldElkBAAAAA51c2VyQWRkcmVzc1N0cgkABCUAAAABCAUAAAABaQAAAAZjYWxsZXIEAAAAD3VzZXJSZWNvcmRBcnJheQkBAAAAGnJlYWRMb2NrUGFyYW1zUmVjb3JkT3JGYWlsAAAAAQUAAAAOdXNlckFkZHJlc3NTdHIEAAAACnVzZXJOdW1TdHIJAAGRAAAAAgUAAAAPdXNlclJlY29yZEFycmF5BQAAAA5JZHhMb2NrVXNlck51bQQAAAAKdXNlckFtb3VudAkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAAD3VzZXJSZWNvcmRBcnJheQUAAAANSWR4TG9ja0Ftb3VudAQAAAAJbG9ja1N0YXJ0CQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAPdXNlclJlY29yZEFycmF5BQAAAAxJZHhMb2NrU3RhcnQEAAAADGxvY2tEdXJhdGlvbgkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAAD3VzZXJSZWNvcmRBcnJheQUAAAAPSWR4TG9ja0R1cmF0aW9uBAAAAAdsb2NrRW5kCQAAZAAAAAIFAAAACWxvY2tTdGFydAUAAAAMbG9ja0R1cmF0aW9uBAAAABFyZW1haW5pbmdEdXJhdGlvbgkAAZYAAAABCQAETAAAAAIJAABlAAAAAgUAAAAHbG9ja0VuZAUAAAAGaGVpZ2h0CQAETAAAAAIAAAAAAAAAAAAFAAAAA25pbAQAAAANdXNlckFtb3VudE5ldwkAAGQAAAACBQAAAAp1c2VyQW1vdW50BQAAAAlwbXRBbW91bnQEAAAAD2xvY2tEdXJhdGlvbk5ldwkAAGQAAAACBQAAABFyZW1haW5pbmdEdXJhdGlvbgUAAAANZGVsdGFEdXJhdGlvbgMJAABmAAAAAgAAAAAAAAAAAAUAAAANZGVsdGFEdXJhdGlvbgkAAAIAAAABAgAAABpkdXJhdGlvbiBpcyBsZXNzIHRoZW4gemVybwMJAABmAAAAAgUAAAAPbWluTG9ja0R1cmF0aW9uBQAAAA9sb2NrRHVyYXRpb25OZXcJAAACAAAAAQkAASwAAAACAgAAAC1sb2NrRHVyYXRpb25OZXcgaXMgbGVzcyB0aGVuIG1pbkxvY2tEdXJhdGlvbj0JAAGkAAAAAQUAAAAPbWluTG9ja0R1cmF0aW9uAwkAAGYAAAACBQAAAA9sb2NrRHVyYXRpb25OZXcFAAAAD21heExvY2tEdXJhdGlvbgkAAAIAAAABCQABLAAAAAICAAAARGRlbHRhRHVyYXRpb24gKyBleGlzdGVkTG9ja0R1cmF0aW9uIGlzIGdyZWF0ZXIgdGhlbiBtYXhMb2NrRHVyYXRpb249CQABpAAAAAEFAAAAD21heExvY2tEdXJhdGlvbgQAAAAHY29lZmZYOAkAAGsAAAADBQAAAA9sb2NrRHVyYXRpb25OZXcFAAAABU1VTFQ4BQAAAA9tYXhMb2NrRHVyYXRpb24EAAAADmdXeEFtb3VudFN0YXJ0CQAAawAAAAMFAAAADXVzZXJBbW91bnROZXcFAAAAB2NvZWZmWDgFAAAABU1VTFQ4BAAAAAxsb2NrU3RhcnROZXcFAAAABmhlaWdodAQAAAATZ1d4UGFyYW1zUmVzdWx0TGlzdAkBAAAAA2FhbAAAAAEJAAP8AAAABAUAAAAMbWF0aENvbnRyYWN0AgAAABVjYWxjR3d4UGFyYW1zUkVBRE9OTFkJAARMAAAAAgUAAAAOZ1d4QW1vdW50U3RhcnQJAARMAAAAAgUAAAAMbG9ja1N0YXJ0TmV3CQAETAAAAAIFAAAAD2xvY2tEdXJhdGlvbk5ldwUAAAADbmlsBQAAAANuaWwEAAAAAWsJAQAAAAJhaQAAAAEJAAGRAAAAAgUAAAATZ1d4UGFyYW1zUmVzdWx0TGlzdAAAAAAAAAAAAAQAAAABYgkBAAAAAmFpAAAAAQkAAZEAAAACBQAAABNnV3hQYXJhbXNSZXN1bHRMaXN0AAAAAAAAAAABBAAAAAZwZXJpb2QJAAGkAAAAAQkBAAAAAmFpAAAAAQkAAZEAAAACBQAAABNnV3hQYXJhbXNSZXN1bHRMaXN0AAAAAAAAAAACBAAAABJ3eEVtaXNzaW9uUGVyQmxvY2sJAQAAAANpb2YAAAACBQAAABBlbWlzc2lvbkNvbnRyYWN0CQEAAAAea2V5RW1pc3Npb25SYXRlUGVyQmxvY2tDdXJyZW50AAAAAAQAAAANZW1pc3Npb25TdGFydAkBAAAAA2lvZgAAAAIFAAAAEGVtaXNzaW9uQ29udHJhY3QJAQAAABVrZXlFbWlzc2lvblN0YXJ0QmxvY2sAAAAABAAAAAtlbWlzc2lvbkVuZAkBAAAAA2lvZgAAAAIFAAAAEGVtaXNzaW9uQ29udHJhY3QJAQAAABNrZXlFbWlzc2lvbkVuZEJsb2NrAAAAAAQAAAABaAMJAABmAAAAAgUAAAAGaGVpZ2h0BQAAAAtlbWlzc2lvbkVuZAUAAAALZW1pc3Npb25FbmQFAAAABmhlaWdodAQAAAACZGgJAAGWAAAAAQkABEwAAAACCQAAZQAAAAIFAAAAAWgFAAAADWVtaXNzaW9uU3RhcnQJAARMAAAAAgAAAAAAAAAAAAUAAAADbmlsBAAAACB1c2VyQm9vc3RFbWlzc2lvbkxhc3RJbnRlZ3JhbEtFWQkBAAAAIGtleVVzZXJCb29zdEVtaXNzaW9uTGFzdElOVEVHUkFMAAAAAQUAAAAKdXNlck51bVN0cgQAAAAddXNlckJvb3N0RW1pc3Npb25MYXN0SW50ZWdyYWwJAQAAAANpb3oAAAACBQAAAAR0aGlzBQAAACB1c2VyQm9vc3RFbWlzc2lvbkxhc3RJbnRlZ3JhbEtFWQQAAAAVYm9vc3RFbWlzc2lvbkludGVncmFsCQAAaQAAAAIJAABoAAAAAgkAAGgAAAACBQAAABJ3eEVtaXNzaW9uUGVyQmxvY2sFAAAAAmRoAAAAAAAAAAACAAAAAAAAAAADBAAAABl1c2VyQm9vc3RFbWlzc2lvbkludGVncmFsCQAAZQAAAAIFAAAAFWJvb3N0RW1pc3Npb25JbnRlZ3JhbAUAAAAddXNlckJvb3N0RW1pc3Npb25MYXN0SW50ZWdyYWwDCQAAZgAAAAIAAAAAAAAAAAAFAAAAGXVzZXJCb29zdEVtaXNzaW9uSW50ZWdyYWwJAAACAAAAAQIAAAASd3JvbmcgY2FsY3VsYXRpb25zBAAAABd1c2VyTWF4Qm9vc3RJbnRlZ3JhbEtFWQkBAAAAF2tleVVzZXJNYXhCb29zdElOVEVHUkFMAAAAAQUAAAAKdXNlck51bVN0cgQAAAAYdG90YWxNYXhCb29zdEludGVncmFsS0VZCQEAAAAYa2V5VG90YWxNYXhCb29zdElOVEVHUkFMAAAAAAQAAAAPdXNlck1heEJvb3N0SW50CQEAAAADaW96AAAAAgUAAAAEdGhpcwUAAAAXdXNlck1heEJvb3N0SW50ZWdyYWxLRVkEAAAAEHRvdGFsTWF4Qm9vc3RJbnQJAQAAAANpb3oAAAACBQAAAAR0aGlzBQAAABh0b3RhbE1heEJvb3N0SW50ZWdyYWxLRVkEAAAAC2N1cnJVc2VyR3d4CQEAAAAUY2FsY0N1cnJlbnRHd3hBbW91bnQAAAABBQAAAA51c2VyQWRkcmVzc1N0cgQAAAAHZ3d4RGlmZgkAAGUAAAACBQAAAA5nV3hBbW91bnRTdGFydAUAAAALY3VyclVzZXJHd3gDCQAAZgAAAAIAAAAAAAAAAAAFAAAAB2d3eERpZmYJAAACAAAAAQkAASwAAAACAgAAABhnd3hEaWZmIGlzIGxlc3MgdGhlbiAwOiAJAAGkAAAAAQUAAAAHZ3d4RGlmZgQAAAARdG90YWxDYWNoZWRHd3hLRVkJAQAAABFrZXlUb3RhbENhY2hlZEd3eAAAAAAEAAAADnRvdGFsQ2FjaGVkR3d4CQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAABHRoaXMFAAAAEXRvdGFsQ2FjaGVkR3d4S0VZAAAAAAAAAAAABAAAACF1c2VyQm9vc3RBdmFsYWlibGVUb0NsYWltVG90YWxLRVkJAQAAACFrZXlVc2VyQm9vc3RBdmFsYWlibGVUb0NsYWltVG90YWwAAAABBQAAAAp1c2VyTnVtU3RyBAAAAB51c2VyQm9vc3RBdmFsaWFibGVUb0NsYWltVG90YWwJAQAAAANpb3oAAAACBQAAAAR0aGlzBQAAACF1c2VyQm9vc3RBdmFsYWlibGVUb0NsYWltVG90YWxLRVkEAAAAIXVzZXJCb29zdEF2YWxpYWJsZVRvQ2xhaW1Ub3RhbE5ldwkAAGsAAAADBQAAABl1c2VyQm9vc3RFbWlzc2lvbkludGVncmFsBQAAAAtjdXJyVXNlckd3eAUAAAAOdG90YWxDYWNoZWRHd3gEAAAAEnVzZXJNYXhCb29zdEludE5ldwkAAGkAAAACCQAAaAAAAAIFAAAADmdXeEFtb3VudFN0YXJ0BQAAAA9sb2NrRHVyYXRpb25OZXcAAAAAAAAAAAIEAAAAGHJlbWFpbmluZ1VzZXJNYXhCb29zdEludAkAAGkAAAACCQAAaAAAAAIFAAAAC2N1cnJVc2VyR3d4BQAAABFyZW1haW5pbmdEdXJhdGlvbgAAAAAAAAAAAgQAAAATdXNlck1heEJvb3N0SW50RGlmZgkAAGUAAAACBQAAABJ1c2VyTWF4Qm9vc3RJbnROZXcFAAAAGHJlbWFpbmluZ1VzZXJNYXhCb29zdEludAkABE4AAAACCQAETQAAAAIJAAROAAAAAgkBAAAAD0xvY2tQYXJhbXNFbnRyeQAAAAgFAAAADnVzZXJBZGRyZXNzU3RyBQAAAAp1c2VyTnVtU3RyBQAAAA11c2VyQW1vdW50TmV3BQAAAAxsb2NrU3RhcnROZXcFAAAAD2xvY2tEdXJhdGlvbk5ldwUAAAABawUAAAABYgUAAAAGcGVyaW9kCQEAAAAKU3RhdHNFbnRyeQAAAAQFAAAACXBtdEFtb3VudAUAAAANZGVsdGFEdXJhdGlvbgAAAAAAAAAAAAAAAAAAAAAAAAkBAAAADEhpc3RvcnlFbnRyeQAAAAgCAAAABGxvY2sFAAAADnVzZXJBZGRyZXNzU3RyBQAAAAlwbXRBbW91bnQFAAAACWxvY2tTdGFydAUAAAAPbG9ja0R1cmF0aW9uTmV3BQAAAAFrBQAAAAFiBQAAAAFpCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABF0b3RhbENhY2hlZEd3eEtFWQkAAGQAAAACBQAAAA50b3RhbENhY2hlZEd3eAUAAAAHZ3d4RGlmZgUAAAADbmlsAAAAAWkBAAAADGNsYWltV3hCb29zdAAAAAIAAAAMbHBBc3NldElkU3RyAAAADnVzZXJBZGRyZXNzU3RyAwkBAAAAAiE9AAAAAgUAAAAPc3Rha2luZ0NvbnRyYWN0CAUAAAABaQAAAAZjYWxsZXIJAAACAAAAAQIAAAAScGVybWlzc2lvbnMgZGVuaWVkBAAAAA0kdDAyNzY5ODI3ODAwCQEAAAAUaW50ZXJuYWxDbGFpbVd4Qm9vc3QAAAADBQAAAAxscEFzc2V0SWRTdHIFAAAADnVzZXJBZGRyZXNzU3RyBwQAAAASdXNlckJvb3N0QXZhaWxhYmxlCAUAAAANJHQwMjc2OTgyNzgwMAAAAAJfMQQAAAAJZGF0YVN0YXRlCAUAAAANJHQwMjc2OTgyNzgwMAAAAAJfMgQAAAAFZGVidWcIBQAAAA0kdDAyNzY5ODI3ODAwAAAAAl8zCQAFFAAAAAIFAAAACWRhdGFTdGF0ZQkABEwAAAACBQAAABJ1c2VyQm9vc3RBdmFpbGFibGUFAAAAA25pbAAAAAFpAQAAABRjbGFpbVd4Qm9vc3RSRUFET05MWQAAAAIAAAAMbHBBc3NldElkU3RyAAAADnVzZXJBZGRyZXNzU3RyBAAAAA0kdDAyNzkzMjI4MDMzCQEAAAAUaW50ZXJuYWxDbGFpbVd4Qm9vc3QAAAADBQAAAAxscEFzc2V0SWRTdHIFAAAADnVzZXJBZGRyZXNzU3RyBgQAAAASdXNlckJvb3N0QXZhaWxhYmxlCAUAAAANJHQwMjc5MzIyODAzMwAAAAJfMQQAAAAJZGF0YVN0YXRlCAUAAAANJHQwMjc5MzIyODAzMwAAAAJfMgQAAAAFZGVidWcIBQAAAA0kdDAyNzkzMjI4MDMzAAAAAl8zCQAFFAAAAAIFAAAAA25pbAkABEwAAAACBQAAABJ1c2VyQm9vc3RBdmFpbGFibGUJAARMAAAAAgUAAAAFZGVidWcFAAAAA25pbAAAAAFpAQAAAAZ1bmxvY2sAAAABAAAAC3VzZXJBZGRyZXNzBAAAAA91c2VyUmVjb3JkQXJyYXkJAQAAABpyZWFkTG9ja1BhcmFtc1JlY29yZE9yRmFpbAAAAAEFAAAAC3VzZXJBZGRyZXNzBAAAAAp1c2VyTnVtU3RyCQABkQAAAAIFAAAAD3VzZXJSZWNvcmRBcnJheQUAAAAOSWR4TG9ja1VzZXJOdW0EAAAACnVzZXJBbW91bnQJAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAAA91c2VyUmVjb3JkQXJyYXkFAAAADUlkeExvY2tBbW91bnQEAAAACWxvY2tTdGFydAkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAAD3VzZXJSZWNvcmRBcnJheQUAAAAMSWR4TG9ja1N0YXJ0BAAAAAxsb2NrRHVyYXRpb24JAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAAA91c2VyUmVjb3JkQXJyYXkFAAAAD0lkeExvY2tEdXJhdGlvbgQAAAAHbG9ja0VuZAkAAGQAAAACBQAAAAlsb2NrU3RhcnQFAAAADGxvY2tEdXJhdGlvbgQAAAAIY2ZnQXJyYXkJAQAAABVyZWFkQ29uZmlnQXJyYXlPckZhaWwAAAAABAAAAAdhc3NldElkCQACWQAAAAEJAAGRAAAAAgUAAAAIY2ZnQXJyYXkFAAAADUlkeENmZ0Fzc2V0SWQEAAAADG1hdGhDb250cmFjdAkBAAAAEUBleHRyTmF0aXZlKDEwNjIpAAAAAQkAAZEAAAACBQAAAAhjZmdBcnJheQUAAAASSWR4Q2ZnTWF0aENvbnRyYWN0AwkAAGcAAAACBQAAAAdsb2NrRW5kBQAAAAZoZWlnaHQJAAACAAAAAQkAASwAAAACCQABLAAAAAICAAAABXdhaXQgCQABpAAAAAEFAAAAB2xvY2tFbmQCAAAACiB0byB1bmxvY2sDCQAAZwAAAAIAAAAAAAAAAAAFAAAACnVzZXJBbW91bnQJAAACAAAAAQIAAAARbm90aGluZyB0byB1bmxvY2sEAAAABnBlcmlvZAkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAxtYXRoQ29udHJhY3QJAQAAAA1rZXlOZXh0UGVyaW9kAAAAAAAAAAAAAAAAAAkABE0AAAACCQAETQAAAAIJAAROAAAAAgkBAAAAD0xvY2tQYXJhbXNFbnRyeQAAAAgFAAAAC3VzZXJBZGRyZXNzBQAAAAp1c2VyTnVtU3RyAAAAAAAAAAAABQAAAAlsb2NrU3RhcnQFAAAADGxvY2tEdXJhdGlvbgAAAAAAAAAAAAAAAAAAAAAAAAkAAaQAAAABBQAAAAZwZXJpb2QJAQAAAApTdGF0c0VudHJ5AAAABAkBAAAAAS0AAAABBQAAAAp1c2VyQW1vdW50AAAAAAAAAAAAAAAAAAAAAAAAAP//////////CQEAAAAMSGlzdG9yeUVudHJ5AAAACAIAAAAGdW5sb2NrBQAAAAt1c2VyQWRkcmVzcwUAAAAKdXNlckFtb3VudAUAAAAJbG9ja1N0YXJ0BQAAAAxsb2NrRHVyYXRpb24AAAAAAAAAAAAAAAAAAAAAAAAFAAAAAWkJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAABFAZXh0ck5hdGl2ZSgxMDYyKQAAAAEFAAAAC3VzZXJBZGRyZXNzBQAAAAp1c2VyQW1vdW50BQAAAAdhc3NldElkAAAAAWkBAAAAE2d3eFVzZXJJbmZvUkVBRE9OTFkAAAABAAAAC3VzZXJBZGRyZXNzBAAAAAlnd3hBbW91bnQJAQAAABRjYWxjQ3VycmVudEd3eEFtb3VudAAAAAEFAAAAC3VzZXJBZGRyZXNzCQAFFAAAAAIFAAAAA25pbAkABEwAAAACBQAAAAlnd3hBbW91bnQFAAAAA25pbAAAAAFpAQAAACBnZXRVc2VyR3d4QW1vdW50QXRIZWlnaHRSRUFET05MWQAAAAIAAAALdXNlckFkZHJlc3MAAAAMdGFyZ2V0SGVpZ2h0BAAAAAlnd3hBbW91bnQJAQAAABljYWxjVXNlckd3eEFtb3VudEF0SGVpZ2h0AAAAAgUAAAALdXNlckFkZHJlc3MFAAAADHRhcmdldEhlaWdodAkABRQAAAACBQAAAANuaWwFAAAACWd3eEFtb3VudAAAAAFpAQAAAApzZXRNYW5hZ2VyAAAAAQAAABdwZW5kaW5nTWFuYWdlclB1YmxpY0tleQQAAAALY2hlY2tDYWxsZXIJAQAAAAttdXN0TWFuYWdlcgAAAAEFAAAAAWkDCQAAAAAAAAIFAAAAC2NoZWNrQ2FsbGVyBQAAAAtjaGVja0NhbGxlcgQAAAAVY2hlY2tNYW5hZ2VyUHVibGljS2V5CQACWQAAAAEFAAAAF3BlbmRpbmdNYW5hZ2VyUHVibGljS2V5AwkAAAAAAAACBQAAABVjaGVja01hbmFnZXJQdWJsaWNLZXkFAAAAFWNoZWNrTWFuYWdlclB1YmxpY0tleQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAAaa2V5UGVuZGluZ01hbmFnZXJQdWJsaWNLZXkAAAAABQAAABdwZW5kaW5nTWFuYWdlclB1YmxpY0tleQUAAAADbmlsCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAABaQEAAAAOY29uZmlybU1hbmFnZXIAAAAABAAAAAJwbQkBAAAAHXBlbmRpbmdNYW5hZ2VyUHVibGljS2V5T3JVbml0AAAAAAQAAAAFaGFzUE0DCQEAAAAJaXNEZWZpbmVkAAAAAQUAAAACcG0GCQAAAgAAAAECAAAAEk5vIHBlbmRpbmcgbWFuYWdlcgMJAAAAAAAAAgUAAAAFaGFzUE0FAAAABWhhc1BNBAAAAAdjaGVja1BNAwkAAAAAAAACCAUAAAABaQAAAA9jYWxsZXJQdWJsaWNLZXkJAQAAAAV2YWx1ZQAAAAEFAAAAAnBtBgkAAAIAAAABAgAAABtZb3UgYXJlIG5vdCBwZW5kaW5nIG1hbmFnZXIDCQAAAAAAAAIFAAAAB2NoZWNrUE0FAAAAB2NoZWNrUE0JAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAE2tleU1hbmFnZXJQdWJsaWNLZXkAAAAACQACWAAAAAEJAQAAAAV2YWx1ZQAAAAEFAAAAAnBtCQAETAAAAAIJAQAAAAtEZWxldGVFbnRyeQAAAAEJAQAAABprZXlQZW5kaW5nTWFuYWdlclB1YmxpY0tleQAAAAAFAAAAA25pbAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAAAAAQAAAAJ0eAEAAAAGdmVyaWZ5AAAAAAQAAAAPdGFyZ2V0UHVibGljS2V5BAAAAAckbWF0Y2gwCQEAAAAWbWFuYWdlclB1YmxpY0tleU9yVW5pdAAAAAADCQAAAQAAAAIFAAAAByRtYXRjaDACAAAACkJ5dGVWZWN0b3IEAAAAAnBrBQAAAAckbWF0Y2gwBQAAAAJwawMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAEVW5pdAgFAAAAAnR4AAAAD3NlbmRlclB1YmxpY0tleQkAAAIAAAABAgAAAAtNYXRjaCBlcnJvcgkAAfQAAAADCAUAAAACdHgAAAAJYm9keUJ5dGVzCQABkQAAAAIIBQAAAAJ0eAAAAAZwcm9vZnMAAAAAAAAAAAAFAAAAD3RhcmdldFB1YmxpY0tledCSC0M=", "chainId": 87, "height": 3052142, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: BzJbvMHTmhiGX87GngDCkEa6e5HEd2ZBBsgedABQYVDf Next: 218JccVxYAg3euRNNULaNrUnU1DwhQFagcsiiedsg1yt Diff:
OldNewDifferences
1212 func strf (address,key) = valueOrErrorMessage(getString(address, key), (("mandatory this." + key) + " is not defined"))
1313
1414
15-func getIntOrZero (address,key) = valueOrElse(getInteger(address, key), 0)
15+func ioz (address,key) = valueOrElse(getInteger(address, key), 0)
1616
1717
18-func getIntOrDefault (address,key,defaultVal) = valueOrElse(getInteger(address, key), defaultVal)
18+func iod (address,key,defaultVal) = valueOrElse(getInteger(address, key), defaultVal)
1919
2020
21-func getIntOrFail (address,key) = valueOrErrorMessage(getInteger(address, key), (("mandatory this." + key) + " is not defined"))
21+func iof (address,key) = valueOrErrorMessage(getInteger(address, key), (("mandatory this." + key) + " is not defined"))
2222
2323
2424 func abs (val) = if ((0 > val))
2626 else val
2727
2828
29-func asAnyList (val) = match val {
29+func aal (val) = match val {
3030 case valAnyLyst: List[Any] =>
3131 valAnyLyst
3232 case _ =>
3434 }
3535
3636
37-func asInt (val) = match val {
37+func ai (val) = match val {
3838 case valInt: Int =>
3939 valInt
4040 case _ =>
301301 let locksCountKEY = keyStatsLocksCount()
302302 let usersCountKEY = keyStatsUsersCount()
303303 let totalAmountKEY = keyLockParamTotalAmount()
304- let locksDurationSumInBlocks = getIntOrZero(this, locksDurationSumInBlocksKEY)
305- let locksCount = getIntOrZero(this, locksCountKEY)
306- let usersCount = getIntOrZero(this, usersCountKEY)
307- let totalAmount = getIntOrZero(this, totalAmountKEY)
304+ let locksDurationSumInBlocks = ioz(this, locksDurationSumInBlocksKEY)
305+ let locksCount = ioz(this, locksCountKEY)
306+ let usersCount = ioz(this, usersCountKEY)
307+ let totalAmount = ioz(this, totalAmountKEY)
308308 [IntegerEntry(locksDurationSumInBlocksKEY, (locksDurationSumInBlocks + durationInc)), IntegerEntry(locksCountKEY, (locksCount + lockCountInc)), IntegerEntry(usersCountKEY, (usersCount + usersCountInc)), IntegerEntry(totalAmountKEY, (totalAmount + totalLockedInc))]
309309 }
310310
340340 }
341341
342342
343-func calcCurrentGwxAmount (userAddress) = {
343+func calcUserGwxAmountAtHeight (userAddress,targetHeight) = {
344344 let EMPTY = "empty"
345345 let user2NumMappingKEY = keyUser2NumMapping(userAddress)
346346 let userNum = valueOrElse(getString(user2NumMappingKEY), EMPTY)
347347 let k = valueOrElse(getInteger(keyLockParamK(userNum)), 0)
348348 let b = valueOrElse(getInteger(keyLockParamB(userNum)), 0)
349- let gwxAmountCalc = calcGwxAmount(k, b, height)
349+ let gwxAmountCalc = calcGwxAmount(k, b, targetHeight)
350350 let gwxAmount = if ((0 > gwxAmountCalc))
351351 then 0
352352 else gwxAmountCalc
353353 gwxAmount
354354 }
355+
356+
357+func calcCurrentGwxAmount (userAddress) = calcUserGwxAmountAtHeight(userAddress, height)
355358
356359
357360 func internalClaimWxBoost (lpAssetIdStr,userAddressStr,readOnly) = {
364367 let userNumStr = userRecordArray[IdxLockUserNum]
365368 let gwxRewardEmissionStartHeight = valueOrElse(getInteger(gwxRewardContract, keyGwxRewardEmissionStartHeight()), 0)
366369 let EMPTYSTR = "empty"
367- let $t01304213610 = if ((lpAssetIdStr != EMPTYSTR))
370+ let $t01316713735 = if ((lpAssetIdStr != EMPTYSTR))
368371 then {
369372 let poolAddressStr = valueOrErrorMessage(getString(factoryContract, keyFactoryLp2AssetsMapping(lpAssetIdStr)), ("unsupported lp asset " + lpAssetIdStr))
370373 let pw1 = getIntegerValue(factoryContract, keyFactoryPoolWeight(poolAddressStr))
374377 else if (readOnly)
375378 then $Tuple2(0, 0)
376379 else throw(("not readonly mode: unsupported lp asset " + lpAssetIdStr))
377- let poolWeight0 = $t01304213610._1
378- let poolWeight1 = $t01304213610._2
379- let wxEmissionPerBlock = getIntOrFail(emissionContract, keyEmissionRatePerBlockCurrent())
380- let emissionStart = getIntOrFail(emissionContract, keyEmissionStartBlock())
381- let emissionEnd = getIntOrFail(emissionContract, keyEmissionEndBlock())
380+ let poolWeight0 = $t01316713735._1
381+ let poolWeight1 = $t01316713735._2
382+ let wxEmissionPerBlock = iof(emissionContract, keyEmissionRatePerBlockCurrent())
383+ let emissionStart = iof(emissionContract, keyEmissionStartBlock())
384+ let emissionEnd = iof(emissionContract, keyEmissionEndBlock())
382385 let h = if ((height > emissionEnd))
383386 then emissionEnd
384387 else height
385388 let dh = max([(h - emissionStart), 0])
386389 let userLpBoostEmissionLastIntegralKEY = keyUserLpBoostEmissionLastINTEGRAL(userNumStr, lpAssetIdStr)
387390 let userBoostEmissionLastIntegralKEY = keyUserBoostEmissionLastINTEGRAL(userNumStr)
388- let userBoostEmissionLastIntegral = valueOrElse(getInteger(this, userLpBoostEmissionLastIntegralKEY), getIntOrZero(this, userBoostEmissionLastIntegralKEY))
391+ let userBoostEmissionLastIntegral = valueOrElse(getInteger(this, userLpBoostEmissionLastIntegralKEY), ioz(this, userBoostEmissionLastIntegralKEY))
389392 let boostEmissionIntegral = (((wxEmissionPerBlock * dh) * 2) / 3)
390393 let userBoostEmissionIntegral = (boostEmissionIntegral - userBoostEmissionLastIntegral)
391394 let udh = fraction(userBoostEmissionIntegral, 3, (2 * wxEmissionPerBlock))
403406 else {
404407 let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
405408 let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
406- let userMaxBoostInt = getIntOrZero(this, userMaxBoostIntegralKEY)
407- let totalMaxBoostInt = getIntOrZero(this, totalMaxBoostIntegralKEY)
409+ let userMaxBoostInt = ioz(this, userMaxBoostIntegralKEY)
410+ let totalMaxBoostInt = ioz(this, totalMaxBoostIntegralKEY)
408411 let totalCachedGwxKEY = keyTotalCachedGwx()
409412 let totalCachedGwx = valueOrElse(getInteger(this, totalCachedGwxKEY), 0)
410413 let userCurrGwx = calcCurrentGwxAmount(userAddressStr)
411414 let userBoostAvalaibleToClaimTotalKEY = keyUserBoostAvalaibleToClaimTotal(userNumStr)
412- let userBoostAvaliableToClaimTotal = getIntOrZero(this, userBoostAvalaibleToClaimTotalKEY)
415+ let userBoostAvaliableToClaimTotal = ioz(this, userBoostAvalaibleToClaimTotalKEY)
413416 let userBoostEmissionIntegral0 = fraction(userBoostEmissionIntegral, udh0, udh)
414417 let userBoostEmissionIntegral1 = fraction(userBoostEmissionIntegral, udh1, udh)
415418 let poolUserBoostEmissionIntegral0 = fraction(userBoostEmissionIntegral0, poolWeight0, POOLWEIGHTMULT)
422425 else fraction(poolUserBoostEmissionIntegral1, userCurrGwx, totalCachedGwx)
423426 let userBoostAvaliableToClaimTotalNew = (userBoostAvaliableToClaimTotalNew0 + userBoostAvaliableToClaimTotalNew1)
424427 let userBoostClaimedKEY = keyUserBoostClaimed(userNumStr)
425- let userBoostClaimed = getIntOrZero(this, userBoostClaimedKEY)
428+ let userBoostClaimed = ioz(this, userBoostClaimedKEY)
426429 let userBoostAvailable = (userBoostAvaliableToClaimTotalNew - userBoostClaimed)
427430 let dataState = [IntegerEntry(userLpBoostEmissionLastIntegralKEY, boostEmissionIntegral)]
428431 let debug = makeString([("userBoostEmissionLastIntegral=" + toString(userBoostEmissionLastIntegral)), ("userBoostEmissionIntegral=" + toString(userBoostEmissionIntegral)), ("userMaxBoostInt=" + toString(userMaxBoostInt)), ("totalMaxBoostInt=" + toString(totalMaxBoostInt)), ("userBoostAvaliableToClaimTotal=" + toString(userBoostAvaliableToClaimTotal)), ("userBoostAvaliableToClaimTotalNew=" + toString(userBoostAvaliableToClaimTotalNew)), ("userBoostClaimed=" + toString(userBoostClaimed)), ("userBoostAvailable=" + toString(userBoostAvailable)), ("userBoostEmissionIntegral0=" + toString(userBoostEmissionIntegral0)), ("userBoostEmissionIntegral1=" + toString(userBoostEmissionIntegral1)), ("poolUserBoostEmissionIntegral0=" + toString(poolUserBoostEmissionIntegral0)), ("poolUserBoostEmissionIntegral1=" + toString(poolUserBoostEmissionIntegral1)), ("poolWeight0=" + toString(poolWeight0)), ("poolWeight1=" + toString(poolWeight1)), ("h=" + toString(h)), ("udh=" + toString(udh)), ("uLastH=" + toString(uLastH)), ("udh0=" + toString(udh0)), ("udh1=" + toString(udh1)), ("userCurrGwx=" + toString(userCurrGwx)), ("totalCachedGwx=" + toString(totalCachedGwx))], "::")
464467 let userIsExisting = isDefined(getString(keyUser2NumMapping(userAddressStr)))
465468 let userNumStr = if (userIsExisting)
466469 then value(getString(keyUser2NumMapping(userAddressStr)))
467- else toString(getIntOrFail(this, nextUserNumKEY))
470+ else toString(iof(this, nextUserNumKEY))
468471 let userNum = parseIntValue(userNumStr)
469472 let lockStart = height
470473 let startBlockKEY = keyLockParamStartBlock(userNumStr)
477480 else if ((duration > maxLockDuration))
478481 then throw(("passed duration is greater then maxLockDuration=" + toString(maxLockDuration)))
479482 else if (if (userIsExisting)
480- then ((getIntOrFail(this, startBlockKEY) + getIntOrFail(this, durationKEY)) >= lockStart)
483+ then ((iof(this, startBlockKEY) + iof(this, durationKEY)) >= lockStart)
481484 else false)
482485 then throw("there is an active lock - consider to use increaseLock")
483- else if ((getIntOrZero(this, userAmountKEY) > 0))
486+ else if ((ioz(this, userAmountKEY) > 0))
484487 then throw(("there are locked WXs - consider to use increaseLock " + userAmountKEY))
485488 else {
486489 let coeffX8 = fraction(duration, MULT8, maxLockDuration)
487490 let gWxAmountStart = fraction(pmtAmount, coeffX8, MULT8)
488- let gWxParamsResultList = asAnyList(invoke(mathContract, "calcGwxParamsREADONLY", [gWxAmountStart, lockStart, duration], nil))
489- let k = asInt(gWxParamsResultList[0])
490- let b = asInt(gWxParamsResultList[1])
491- let period = toString(asInt(gWxParamsResultList[2]))
492- let wxEmissionPerBlock = getIntOrFail(emissionContract, keyEmissionRatePerBlockCurrent())
493- let emissionStart = getIntOrFail(emissionContract, keyEmissionStartBlock())
494- let emissionEnd = getIntOrFail(emissionContract, keyEmissionEndBlock())
491+ let gWxParamsResultList = aal(invoke(mathContract, "calcGwxParamsREADONLY", [gWxAmountStart, lockStart, duration], nil))
492+ let k = ai(gWxParamsResultList[0])
493+ let b = ai(gWxParamsResultList[1])
494+ let period = toString(ai(gWxParamsResultList[2]))
495+ let wxEmissionPerBlock = iof(emissionContract, keyEmissionRatePerBlockCurrent())
496+ let emissionStart = iof(emissionContract, keyEmissionStartBlock())
497+ let emissionEnd = iof(emissionContract, keyEmissionEndBlock())
495498 let h = if ((height > emissionEnd))
496499 then emissionEnd
497500 else height
501504 let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
502505 let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
503506 let userMaxBoostInt = ((gWxAmountStart * duration) / 2)
504- let totalMaxBoostInt = getIntOrZero(this, totalMaxBoostIntegralKEY)
507+ let totalMaxBoostInt = ioz(this, totalMaxBoostIntegralKEY)
505508 let totalCachedGwxKEY = keyTotalCachedGwx()
506509 let totalCachedGwx = valueOrElse(getInteger(this, totalCachedGwxKEY), 0)
507510 let arr = if (userIsExisting)
546549 let coeffX8 = fraction(lockDurationNew, MULT8, maxLockDuration)
547550 let gWxAmountStart = fraction(userAmountNew, coeffX8, MULT8)
548551 let lockStartNew = height
549- let gWxParamsResultList = asAnyList(invoke(mathContract, "calcGwxParamsREADONLY", [gWxAmountStart, lockStartNew, lockDurationNew], nil))
550- let k = asInt(gWxParamsResultList[0])
551- let b = asInt(gWxParamsResultList[1])
552- let period = toString(asInt(gWxParamsResultList[2]))
553- let wxEmissionPerBlock = getIntOrFail(emissionContract, keyEmissionRatePerBlockCurrent())
554- let emissionStart = getIntOrFail(emissionContract, keyEmissionStartBlock())
555- let emissionEnd = getIntOrFail(emissionContract, keyEmissionEndBlock())
552+ let gWxParamsResultList = aal(invoke(mathContract, "calcGwxParamsREADONLY", [gWxAmountStart, lockStartNew, lockDurationNew], nil))
553+ let k = ai(gWxParamsResultList[0])
554+ let b = ai(gWxParamsResultList[1])
555+ let period = toString(ai(gWxParamsResultList[2]))
556+ let wxEmissionPerBlock = iof(emissionContract, keyEmissionRatePerBlockCurrent())
557+ let emissionStart = iof(emissionContract, keyEmissionStartBlock())
558+ let emissionEnd = iof(emissionContract, keyEmissionEndBlock())
556559 let h = if ((height > emissionEnd))
557560 then emissionEnd
558561 else height
559562 let dh = max([(h - emissionStart), 0])
560563 let userBoostEmissionLastIntegralKEY = keyUserBoostEmissionLastINTEGRAL(userNumStr)
561- let userBoostEmissionLastIntegral = getIntOrZero(this, userBoostEmissionLastIntegralKEY)
564+ let userBoostEmissionLastIntegral = ioz(this, userBoostEmissionLastIntegralKEY)
562565 let boostEmissionIntegral = (((wxEmissionPerBlock * dh) * 2) / 3)
563566 let userBoostEmissionIntegral = (boostEmissionIntegral - userBoostEmissionLastIntegral)
564567 if ((0 > userBoostEmissionIntegral))
566569 else {
567570 let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
568571 let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
569- let userMaxBoostInt = getIntOrZero(this, userMaxBoostIntegralKEY)
570- let totalMaxBoostInt = getIntOrZero(this, totalMaxBoostIntegralKEY)
572+ let userMaxBoostInt = ioz(this, userMaxBoostIntegralKEY)
573+ let totalMaxBoostInt = ioz(this, totalMaxBoostIntegralKEY)
571574 let currUserGwx = calcCurrentGwxAmount(userAddressStr)
572575 let gwxDiff = (gWxAmountStart - currUserGwx)
573576 if ((0 > gwxDiff))
576579 let totalCachedGwxKEY = keyTotalCachedGwx()
577580 let totalCachedGwx = valueOrElse(getInteger(this, totalCachedGwxKEY), 0)
578581 let userBoostAvalaibleToClaimTotalKEY = keyUserBoostAvalaibleToClaimTotal(userNumStr)
579- let userBoostAvaliableToClaimTotal = getIntOrZero(this, userBoostAvalaibleToClaimTotalKEY)
582+ let userBoostAvaliableToClaimTotal = ioz(this, userBoostAvalaibleToClaimTotalKEY)
580583 let userBoostAvaliableToClaimTotalNew = fraction(userBoostEmissionIntegral, currUserGwx, totalCachedGwx)
581584 let userMaxBoostIntNew = ((gWxAmountStart * lockDurationNew) / 2)
582585 let remainingUserMaxBoostInt = ((currUserGwx * remainingDuration) / 2)
593596 func claimWxBoost (lpAssetIdStr,userAddressStr) = if ((stakingContract != i.caller))
594597 then throw("permissions denied")
595598 else {
596- let $t02781027912 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, false)
597- let userBoostAvailable = $t02781027912._1
598- let dataState = $t02781027912._2
599- let debug = $t02781027912._3
599+ let $t02769827800 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, false)
600+ let userBoostAvailable = $t02769827800._1
601+ let dataState = $t02769827800._2
602+ let debug = $t02769827800._3
600603 $Tuple2(dataState, [userBoostAvailable])
601604 }
602605
604607
605608 @Callable(i)
606609 func claimWxBoostREADONLY (lpAssetIdStr,userAddressStr) = {
607- let $t02804428145 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, true)
608- let userBoostAvailable = $t02804428145._1
609- let dataState = $t02804428145._2
610- let debug = $t02804428145._3
610+ let $t02793228033 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, true)
611+ let userBoostAvailable = $t02793228033._1
612+ let dataState = $t02793228033._2
613+ let debug = $t02793228033._3
611614 $Tuple2(nil, [userBoostAvailable, debug])
612615 }
613616
640643 func gwxUserInfoREADONLY (userAddress) = {
641644 let gwxAmount = calcCurrentGwxAmount(userAddress)
642645 $Tuple2(nil, [gwxAmount])
646+ }
647+
648+
649+
650+@Callable(i)
651+func getUserGwxAmountAtHeightREADONLY (userAddress,targetHeight) = {
652+ let gwxAmount = calcUserGwxAmountAtHeight(userAddress, targetHeight)
653+ $Tuple2(nil, gwxAmount)
643654 }
644655
645656
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let SEP = "__"
55
66 let SCALE8 = 8
77
88 let MULT8 = 100000000
99
1010 let POOLWEIGHTMULT = MULT8
1111
1212 func strf (address,key) = valueOrErrorMessage(getString(address, key), (("mandatory this." + key) + " is not defined"))
1313
1414
15-func getIntOrZero (address,key) = valueOrElse(getInteger(address, key), 0)
15+func ioz (address,key) = valueOrElse(getInteger(address, key), 0)
1616
1717
18-func getIntOrDefault (address,key,defaultVal) = valueOrElse(getInteger(address, key), defaultVal)
18+func iod (address,key,defaultVal) = valueOrElse(getInteger(address, key), defaultVal)
1919
2020
21-func getIntOrFail (address,key) = valueOrErrorMessage(getInteger(address, key), (("mandatory this." + key) + " is not defined"))
21+func iof (address,key) = valueOrErrorMessage(getInteger(address, key), (("mandatory this." + key) + " is not defined"))
2222
2323
2424 func abs (val) = if ((0 > val))
2525 then -(val)
2626 else val
2727
2828
29-func asAnyList (val) = match val {
29+func aal (val) = match val {
3030 case valAnyLyst: List[Any] =>
3131 valAnyLyst
3232 case _ =>
3333 throw("fail to cast into List[Any]")
3434 }
3535
3636
37-func asInt (val) = match val {
37+func ai (val) = match val {
3838 case valInt: Int =>
3939 valInt
4040 case _ =>
4141 throw("fail to cast into Int")
4242 }
4343
4444
4545 func keyFactoryAddress () = "%s%s__config__factoryAddress"
4646
4747
4848 let IdxFactoryCfgStakingDapp = 1
4949
5050 let IdxFactoryCfgBoostingDapp = 2
5151
5252 let IdxFactoryCfgIdoDapp = 3
5353
5454 let IdxFactoryCfgTeamDapp = 4
5555
5656 let IdxFactoryCfgEmissionDapp = 5
5757
5858 let IdxFactoryCfgRestDapp = 6
5959
6060 let IdxFactoryCfgSlippageDapp = 7
6161
6262 let IdxFactoryCfgDaoDapp = 8
6363
6464 let IdxFactoryCfgMarketingDapp = 9
6565
6666 let IdxFactoryCfgGwxRewardDapp = 10
6767
6868 let IdxFactoryCfgBirdsDapp = 11
6969
7070 func keyFactoryCfg () = "%s__factoryConfig"
7171
7272
7373 func keyFactoryLp2AssetsMapping (lpAssetStr) = makeString(["%s%s%s", lpAssetStr, "mappings__lpAsset2PoolContract"], SEP)
7474
7575
7676 func keyFactoryLpList () = "%s__lpTokensList"
7777
7878
7979 func keyFactoryLpAssetToPoolContractAddress (lpAssetStr) = makeString(["%s%s%s", lpAssetStr, "mappings__lpAsset2PoolContract"], SEP)
8080
8181
8282 func keyFactoryPoolWeight (contractAddress) = makeString(["%s%s", "poolWeight", contractAddress], SEP)
8383
8484
8585 func keyFactoryPoolWeightHistory (poolAddress,num) = ((("%s%s__poolWeight__" + poolAddress) + "__") + toString(num))
8686
8787
8888 func readFactoryAddressOrFail () = addressFromStringValue(strf(this, keyFactoryAddress()))
8989
9090
9191 func readLpList () = split(valueOrElse(getString(readFactoryAddressOrFail(), keyFactoryLpList()), ""), SEP)
9292
9393
9494 func readFactoryCfgOrFail (factory) = split(strf(factory, keyFactoryCfg()), SEP)
9595
9696
9797 func getBoostingAddressOrFail (factoryCfg) = addressFromStringValue(factoryCfg[IdxFactoryCfgBoostingDapp])
9898
9999
100100 func getEmissionAddressOrFail (factoryCfg) = addressFromStringValue(factoryCfg[IdxFactoryCfgEmissionDapp])
101101
102102
103103 func getStakingAddressOrFail (factoryCfg) = addressFromStringValue(factoryCfg[IdxFactoryCfgStakingDapp])
104104
105105
106106 func getGwxRewardAddressOrFail (factoryCfg) = addressFromStringValue(factoryCfg[IdxFactoryCfgGwxRewardDapp])
107107
108108
109109 func keyManagerPublicKey () = "%s__managerPublicKey"
110110
111111
112112 func keyPendingManagerPublicKey () = "%s__pendingManagerPublicKey"
113113
114114
115115 func keyEmissionRatePerBlockCurrent () = "%s%s__ratePerBlock__current"
116116
117117
118118 func keyEmissionRatePerBlockMaxCurrent () = "%s%s__ratePerBlockMax__current"
119119
120120
121121 func keyEmissionStartBlock () = "%s%s__emission__startBlock"
122122
123123
124124 func keyEmissionDurationInBlocks () = "%s%s__emission__duration"
125125
126126
127127 func keyEmissionEndBlock () = "%s%s__emission__endBlock"
128128
129129
130130 func keyNextPeriod () = "%s__nextPeriod"
131131
132132
133133 func keyGwxRewardEmissionStartHeight () = "%s%s__gwxRewardEmissionPart__startHeight"
134134
135135
136136 let IdxCfgAssetId = 1
137137
138138 let IdxCfgMinLockAmount = 2
139139
140140 let IdxCfgMinLockDuration = 3
141141
142142 let IdxCfgMaxLockDuration = 4
143143
144144 let IdxCfgMathContract = 5
145145
146146 func keyConfig () = "%s__config"
147147
148148
149149 func readConfigArrayOrFail () = split(strf(this, keyConfig()), SEP)
150150
151151
152152 func formatConfigS (assetId,minLockAmount,minLockDuration,maxLockDuration,mathContract) = makeString(["%s%d%d%d", assetId, minLockAmount, minLockDuration, maxLockDuration, mathContract], SEP)
153153
154154
155155 func formatConfig (assetId,minLockAmount,minLockDuration,maxLockDuration,mathContract) = formatConfigS(assetId, toString(minLockAmount), toString(minLockDuration), toString(maxLockDuration), mathContract)
156156
157157
158158 func managerPublicKeyOrUnit () = match getString(keyManagerPublicKey()) {
159159 case s: String =>
160160 fromBase58String(s)
161161 case _: Unit =>
162162 unit
163163 case _ =>
164164 throw("Match error")
165165 }
166166
167167
168168 func pendingManagerPublicKeyOrUnit () = match getString(keyPendingManagerPublicKey()) {
169169 case s: String =>
170170 fromBase58String(s)
171171 case _: Unit =>
172172 unit
173173 case _ =>
174174 throw("Match error")
175175 }
176176
177177
178178 func mustManager (i) = {
179179 let pd = throw("Permission denied")
180180 match managerPublicKeyOrUnit() {
181181 case pk: ByteVector =>
182182 if ((i.callerPublicKey == pk))
183183 then true
184184 else pd
185185 case _: Unit =>
186186 if ((i.caller == this))
187187 then true
188188 else pd
189189 case _ =>
190190 throw("Match error")
191191 }
192192 }
193193
194194
195195 let IdxLockUserNum = 1
196196
197197 let IdxLockAmount = 2
198198
199199 let IdxLockStart = 3
200200
201201 let IdxLockDuration = 4
202202
203203 let IdxLockParamK = 5
204204
205205 let IdxLockParamB = 6
206206
207207 func keyLockParamsRecord (userAddress) = makeString(["%s%s__lock", userAddress], SEP)
208208
209209
210210 func readLockParamsRecordOrFail (userAddress) = split(strf(this, keyLockParamsRecord(userAddress)), SEP)
211211
212212
213213 func formatLockParamsRecordS (userNum,amount,start,duration,paramK,paramB,lastUpdTimestamp,gwxAmount) = makeString(["%d%d%d%d%d%d%d%d", userNum, amount, start, duration, paramK, paramB, lastUpdTimestamp, gwxAmount], SEP)
214214
215215
216216 func formatLockParamsRecord (userNum,amount,start,duration,paramK,paramB,gwxAmount) = formatLockParamsRecordS(userNum, toString(amount), toString(start), toString(duration), toString(paramK), toString(paramB), toString(lastBlock.timestamp), toString(gwxAmount))
217217
218218
219219 func keyNextUserNum () = "%s__nextUserNum"
220220
221221
222222 func keyUser2NumMapping (userAddress) = makeString(["%s%s%s__mapping__user2num", userAddress], SEP)
223223
224224
225225 func keyNum2UserMapping (num) = makeString(["%s%s%s__mapping__num2user", num], SEP)
226226
227227
228228 func keyLockParamUserAmount (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "amount"], SEP)
229229
230230
231231 func keyLockParamStartBlock (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "start"], SEP)
232232
233233
234234 func keyLockParamDuration (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "duration"], SEP)
235235
236236
237237 func keyLockParamK (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "k"], SEP)
238238
239239
240240 func keyLockParamB (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "b"], SEP)
241241
242242
243243 func keyLockParamByPeriodK (userNum,period) = makeString(["%s%d%s%d__paramByPeriod", userNum, "k", period], SEP)
244244
245245
246246 func keyLockParamByPeriodB (userNum,period) = makeString(["%s%d%s%d__paramByPeriod", userNum, "b", period], SEP)
247247
248248
249249 func keyLockParamTotalAmount () = "%s%s__stats__activeTotalLocked"
250250
251251
252252 func keyStatsLocksDurationSumInBlocks () = "%s%s__stats__locksDurationSumInBlocks"
253253
254254
255255 func keyStatsLocksCount () = "%s%s__stats__locksCount"
256256
257257
258258 func keyStatsUsersCount () = "%s%s__stats__activeUsersCount"
259259
260260
261261 func keyUserBoostEmissionLastINTEGRAL (userNum) = makeString(["%s%d__userBoostEmissionLastInt", userNum], SEP)
262262
263263
264264 func keyUserLpBoostEmissionLastINTEGRAL (userNum,lpAssetId) = makeString(["%s%d__userBoostEmissionLastInt", userNum, lpAssetId], SEP)
265265
266266
267267 func keyUserMaxBoostINTEGRAL (userNum) = makeString(["%s%d__maxBoostInt", userNum], SEP)
268268
269269
270270 func keyTotalMaxBoostINTEGRAL () = "%s%s__maxBoostInt__total"
271271
272272
273273 func keyUserBoostAvalaibleToClaimTotal (userNum) = makeString(["%s%d__userBoostAvaliableToClaimTotal", userNum], SEP)
274274
275275
276276 func keyUserBoostClaimed (userNum) = makeString(["%s%d__userBoostClaimed", userNum], SEP)
277277
278278
279279 func keyTotalCachedGwx () = "%s%s__gwxCached__total"
280280
281281
282282 let factoryContract = readFactoryAddressOrFail()
283283
284284 let factoryCfg = readFactoryCfgOrFail(factoryContract)
285285
286286 let emissionContract = getEmissionAddressOrFail(factoryCfg)
287287
288288 let stakingContract = getStakingAddressOrFail(factoryCfg)
289289
290290 let gwxRewardContract = getGwxRewardAddressOrFail(factoryCfg)
291291
292292 func HistoryEntry (type,user,amount,lockStart,duration,k,b,i) = {
293293 let historyKEY = makeString(["%s%s%s%s__history", type, user, toBase58String(i.transactionId)], SEP)
294294 let historyDATA = makeString(["%d%d%d%d%d%d%d", toString(lastBlock.height), toString(lastBlock.timestamp), toString(amount), toString(lockStart), toString(duration), toString(k), toString(b)], SEP)
295295 StringEntry(historyKEY, historyDATA)
296296 }
297297
298298
299299 func StatsEntry (totalLockedInc,durationInc,lockCountInc,usersCountInc) = {
300300 let locksDurationSumInBlocksKEY = keyStatsLocksDurationSumInBlocks()
301301 let locksCountKEY = keyStatsLocksCount()
302302 let usersCountKEY = keyStatsUsersCount()
303303 let totalAmountKEY = keyLockParamTotalAmount()
304- let locksDurationSumInBlocks = getIntOrZero(this, locksDurationSumInBlocksKEY)
305- let locksCount = getIntOrZero(this, locksCountKEY)
306- let usersCount = getIntOrZero(this, usersCountKEY)
307- let totalAmount = getIntOrZero(this, totalAmountKEY)
304+ let locksDurationSumInBlocks = ioz(this, locksDurationSumInBlocksKEY)
305+ let locksCount = ioz(this, locksCountKEY)
306+ let usersCount = ioz(this, usersCountKEY)
307+ let totalAmount = ioz(this, totalAmountKEY)
308308 [IntegerEntry(locksDurationSumInBlocksKEY, (locksDurationSumInBlocks + durationInc)), IntegerEntry(locksCountKEY, (locksCount + lockCountInc)), IntegerEntry(usersCountKEY, (usersCount + usersCountInc)), IntegerEntry(totalAmountKEY, (totalAmount + totalLockedInc))]
309309 }
310310
311311
312312 func calcGwxAmount (kRaw,bRaw,h) = {
313313 let SCALE = 1000
314314 (((kRaw * h) + bRaw) / SCALE)
315315 }
316316
317317
318318 func LockParamsEntry (userAddress,userNum,amount,start,duration,k,b,period) = {
319319 let userAmountKEY = keyLockParamUserAmount(userNum)
320320 let startBlockKEY = keyLockParamStartBlock(userNum)
321321 let durationKEY = keyLockParamDuration(userNum)
322322 let kKEY = keyLockParamK(userNum)
323323 let bKEY = keyLockParamB(userNum)
324324 let kByPeriodKEY = keyLockParamByPeriodK(userNum, period)
325325 let bByPeriodKEY = keyLockParamByPeriodB(userNum, period)
326326 let gwxAmount = calcGwxAmount(k, b, height)
327327 [IntegerEntry(userAmountKEY, amount), IntegerEntry(startBlockKEY, start), IntegerEntry(durationKEY, duration), IntegerEntry(kKEY, k), IntegerEntry(bKEY, b), IntegerEntry(kByPeriodKEY, k), IntegerEntry(bByPeriodKEY, b), StringEntry(keyLockParamsRecord(userAddress), formatLockParamsRecord(userNum, amount, start, duration, k, b, gwxAmount))]
328328 }
329329
330330
331331 func extractOptionalPaymentAmountOrFail (i,expectedAssetId) = if ((size(i.payments) > 1))
332332 then throw("only one payment is allowed")
333333 else if ((size(i.payments) == 0))
334334 then 0
335335 else {
336336 let pmt = i.payments[0]
337337 if ((value(pmt.assetId) != expectedAssetId))
338338 then throw("invalid asset id in payment")
339339 else pmt.amount
340340 }
341341
342342
343-func calcCurrentGwxAmount (userAddress) = {
343+func calcUserGwxAmountAtHeight (userAddress,targetHeight) = {
344344 let EMPTY = "empty"
345345 let user2NumMappingKEY = keyUser2NumMapping(userAddress)
346346 let userNum = valueOrElse(getString(user2NumMappingKEY), EMPTY)
347347 let k = valueOrElse(getInteger(keyLockParamK(userNum)), 0)
348348 let b = valueOrElse(getInteger(keyLockParamB(userNum)), 0)
349- let gwxAmountCalc = calcGwxAmount(k, b, height)
349+ let gwxAmountCalc = calcGwxAmount(k, b, targetHeight)
350350 let gwxAmount = if ((0 > gwxAmountCalc))
351351 then 0
352352 else gwxAmountCalc
353353 gwxAmount
354354 }
355+
356+
357+func calcCurrentGwxAmount (userAddress) = calcUserGwxAmountAtHeight(userAddress, height)
355358
356359
357360 func internalClaimWxBoost (lpAssetIdStr,userAddressStr,readOnly) = {
358361 let EMPTY = "EMPTY"
359362 let userRecordOrEmpty = valueOrElse(getString(this, keyLockParamsRecord(userAddressStr)), EMPTY)
360363 if ((userRecordOrEmpty == EMPTY))
361364 then $Tuple3(0, nil, "userRecord::is::empty")
362365 else {
363366 let userRecordArray = split(userRecordOrEmpty, SEP)
364367 let userNumStr = userRecordArray[IdxLockUserNum]
365368 let gwxRewardEmissionStartHeight = valueOrElse(getInteger(gwxRewardContract, keyGwxRewardEmissionStartHeight()), 0)
366369 let EMPTYSTR = "empty"
367- let $t01304213610 = if ((lpAssetIdStr != EMPTYSTR))
370+ let $t01316713735 = if ((lpAssetIdStr != EMPTYSTR))
368371 then {
369372 let poolAddressStr = valueOrErrorMessage(getString(factoryContract, keyFactoryLp2AssetsMapping(lpAssetIdStr)), ("unsupported lp asset " + lpAssetIdStr))
370373 let pw1 = getIntegerValue(factoryContract, keyFactoryPoolWeight(poolAddressStr))
371374 let pw0 = valueOrElse(getInteger(factoryContract, keyFactoryPoolWeightHistory(poolAddressStr, 0)), pw1)
372375 $Tuple2(pw0, pw1)
373376 }
374377 else if (readOnly)
375378 then $Tuple2(0, 0)
376379 else throw(("not readonly mode: unsupported lp asset " + lpAssetIdStr))
377- let poolWeight0 = $t01304213610._1
378- let poolWeight1 = $t01304213610._2
379- let wxEmissionPerBlock = getIntOrFail(emissionContract, keyEmissionRatePerBlockCurrent())
380- let emissionStart = getIntOrFail(emissionContract, keyEmissionStartBlock())
381- let emissionEnd = getIntOrFail(emissionContract, keyEmissionEndBlock())
380+ let poolWeight0 = $t01316713735._1
381+ let poolWeight1 = $t01316713735._2
382+ let wxEmissionPerBlock = iof(emissionContract, keyEmissionRatePerBlockCurrent())
383+ let emissionStart = iof(emissionContract, keyEmissionStartBlock())
384+ let emissionEnd = iof(emissionContract, keyEmissionEndBlock())
382385 let h = if ((height > emissionEnd))
383386 then emissionEnd
384387 else height
385388 let dh = max([(h - emissionStart), 0])
386389 let userLpBoostEmissionLastIntegralKEY = keyUserLpBoostEmissionLastINTEGRAL(userNumStr, lpAssetIdStr)
387390 let userBoostEmissionLastIntegralKEY = keyUserBoostEmissionLastINTEGRAL(userNumStr)
388- let userBoostEmissionLastIntegral = valueOrElse(getInteger(this, userLpBoostEmissionLastIntegralKEY), getIntOrZero(this, userBoostEmissionLastIntegralKEY))
391+ let userBoostEmissionLastIntegral = valueOrElse(getInteger(this, userLpBoostEmissionLastIntegralKEY), ioz(this, userBoostEmissionLastIntegralKEY))
389392 let boostEmissionIntegral = (((wxEmissionPerBlock * dh) * 2) / 3)
390393 let userBoostEmissionIntegral = (boostEmissionIntegral - userBoostEmissionLastIntegral)
391394 let udh = fraction(userBoostEmissionIntegral, 3, (2 * wxEmissionPerBlock))
392395 let uLastH = (h - udh)
393396 let udh0 = max([(gwxRewardEmissionStartHeight - uLastH), 0])
394397 let udh1 = ((h - uLastH) - udh0)
395398 if (if (if ((0 > uLastH))
396399 then true
397400 else (0 > udh1))
398401 then true
399402 else (abs(((udh0 + udh1) - udh)) >= 1))
400403 then throw(((((((("invalid udh calc: udh=" + toString(udh)) + " uLastH=") + toString(uLastH)) + " udh0=") + toString(udh0)) + " udh1=") + toString(udh1)))
401404 else if ((0 > userBoostEmissionIntegral))
402405 then throw("wrong calculations")
403406 else {
404407 let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
405408 let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
406- let userMaxBoostInt = getIntOrZero(this, userMaxBoostIntegralKEY)
407- let totalMaxBoostInt = getIntOrZero(this, totalMaxBoostIntegralKEY)
409+ let userMaxBoostInt = ioz(this, userMaxBoostIntegralKEY)
410+ let totalMaxBoostInt = ioz(this, totalMaxBoostIntegralKEY)
408411 let totalCachedGwxKEY = keyTotalCachedGwx()
409412 let totalCachedGwx = valueOrElse(getInteger(this, totalCachedGwxKEY), 0)
410413 let userCurrGwx = calcCurrentGwxAmount(userAddressStr)
411414 let userBoostAvalaibleToClaimTotalKEY = keyUserBoostAvalaibleToClaimTotal(userNumStr)
412- let userBoostAvaliableToClaimTotal = getIntOrZero(this, userBoostAvalaibleToClaimTotalKEY)
415+ let userBoostAvaliableToClaimTotal = ioz(this, userBoostAvalaibleToClaimTotalKEY)
413416 let userBoostEmissionIntegral0 = fraction(userBoostEmissionIntegral, udh0, udh)
414417 let userBoostEmissionIntegral1 = fraction(userBoostEmissionIntegral, udh1, udh)
415418 let poolUserBoostEmissionIntegral0 = fraction(userBoostEmissionIntegral0, poolWeight0, POOLWEIGHTMULT)
416419 let poolUserBoostEmissionIntegral1 = fraction(userBoostEmissionIntegral1, poolWeight1, POOLWEIGHTMULT)
417420 let userBoostAvaliableToClaimTotalNew0 = if ((totalCachedGwx == 0))
418421 then 0
419422 else fraction(poolUserBoostEmissionIntegral0, userCurrGwx, totalCachedGwx)
420423 let userBoostAvaliableToClaimTotalNew1 = if ((totalCachedGwx == 0))
421424 then 0
422425 else fraction(poolUserBoostEmissionIntegral1, userCurrGwx, totalCachedGwx)
423426 let userBoostAvaliableToClaimTotalNew = (userBoostAvaliableToClaimTotalNew0 + userBoostAvaliableToClaimTotalNew1)
424427 let userBoostClaimedKEY = keyUserBoostClaimed(userNumStr)
425- let userBoostClaimed = getIntOrZero(this, userBoostClaimedKEY)
428+ let userBoostClaimed = ioz(this, userBoostClaimedKEY)
426429 let userBoostAvailable = (userBoostAvaliableToClaimTotalNew - userBoostClaimed)
427430 let dataState = [IntegerEntry(userLpBoostEmissionLastIntegralKEY, boostEmissionIntegral)]
428431 let debug = makeString([("userBoostEmissionLastIntegral=" + toString(userBoostEmissionLastIntegral)), ("userBoostEmissionIntegral=" + toString(userBoostEmissionIntegral)), ("userMaxBoostInt=" + toString(userMaxBoostInt)), ("totalMaxBoostInt=" + toString(totalMaxBoostInt)), ("userBoostAvaliableToClaimTotal=" + toString(userBoostAvaliableToClaimTotal)), ("userBoostAvaliableToClaimTotalNew=" + toString(userBoostAvaliableToClaimTotalNew)), ("userBoostClaimed=" + toString(userBoostClaimed)), ("userBoostAvailable=" + toString(userBoostAvailable)), ("userBoostEmissionIntegral0=" + toString(userBoostEmissionIntegral0)), ("userBoostEmissionIntegral1=" + toString(userBoostEmissionIntegral1)), ("poolUserBoostEmissionIntegral0=" + toString(poolUserBoostEmissionIntegral0)), ("poolUserBoostEmissionIntegral1=" + toString(poolUserBoostEmissionIntegral1)), ("poolWeight0=" + toString(poolWeight0)), ("poolWeight1=" + toString(poolWeight1)), ("h=" + toString(h)), ("udh=" + toString(udh)), ("uLastH=" + toString(uLastH)), ("udh0=" + toString(udh0)), ("udh1=" + toString(udh1)), ("userCurrGwx=" + toString(userCurrGwx)), ("totalCachedGwx=" + toString(totalCachedGwx))], "::")
429432 $Tuple3(userBoostAvaliableToClaimTotalNew, dataState, debug)
430433 }
431434 }
432435 }
433436
434437
435438 @Callable(i)
436439 func constructor (factoryAddressStr,lockAssetIdStr,minLockAmount,minDuration,maxDuration,mathContract) = {
437440 let checkCaller = mustManager(i)
438441 if ((checkCaller == checkCaller))
439442 then ([IntegerEntry(keyNextUserNum(), 0), StringEntry(keyConfig(), formatConfig(lockAssetIdStr, minLockAmount, minDuration, maxDuration, mathContract)), StringEntry(keyFactoryAddress(), factoryAddressStr)] ++ StatsEntry(0, 0, 0, 0))
440443 else throw("Strict value is not equal to itself.")
441444 }
442445
443446
444447
445448 @Callable(i)
446449 func lock (duration) = {
447450 let cfgArray = readConfigArrayOrFail()
448451 let assetIdStr = cfgArray[IdxCfgAssetId]
449452 let assetId = fromBase58String(assetIdStr)
450453 let minLockAmount = parseIntValue(cfgArray[IdxCfgMinLockAmount])
451454 let minLockDuration = parseIntValue(cfgArray[IdxCfgMinLockDuration])
452455 let maxLockDuration = parseIntValue(cfgArray[IdxCfgMaxLockDuration])
453456 let mathContract = addressFromStringValue(cfgArray[IdxCfgMathContract])
454457 if ((size(i.payments) != 1))
455458 then throw("invalid payment - exact one payment must be attached")
456459 else {
457460 let pmt = i.payments[0]
458461 let pmtAmount = pmt.amount
459462 if ((assetId != value(pmt.assetId)))
460463 then throw((("invalid asset is in payment - " + assetIdStr) + " is expected"))
461464 else {
462465 let nextUserNumKEY = keyNextUserNum()
463466 let userAddressStr = toString(i.caller)
464467 let userIsExisting = isDefined(getString(keyUser2NumMapping(userAddressStr)))
465468 let userNumStr = if (userIsExisting)
466469 then value(getString(keyUser2NumMapping(userAddressStr)))
467- else toString(getIntOrFail(this, nextUserNumKEY))
470+ else toString(iof(this, nextUserNumKEY))
468471 let userNum = parseIntValue(userNumStr)
469472 let lockStart = height
470473 let startBlockKEY = keyLockParamStartBlock(userNumStr)
471474 let durationKEY = keyLockParamDuration(userNumStr)
472475 let userAmountKEY = keyLockParamUserAmount(userNumStr)
473476 if ((minLockAmount > pmtAmount))
474477 then throw(("amount is less then minLockAmount=" + toString(minLockAmount)))
475478 else if ((minLockDuration > duration))
476479 then throw(("passed duration is less then minLockDuration=" + toString(minLockDuration)))
477480 else if ((duration > maxLockDuration))
478481 then throw(("passed duration is greater then maxLockDuration=" + toString(maxLockDuration)))
479482 else if (if (userIsExisting)
480- then ((getIntOrFail(this, startBlockKEY) + getIntOrFail(this, durationKEY)) >= lockStart)
483+ then ((iof(this, startBlockKEY) + iof(this, durationKEY)) >= lockStart)
481484 else false)
482485 then throw("there is an active lock - consider to use increaseLock")
483- else if ((getIntOrZero(this, userAmountKEY) > 0))
486+ else if ((ioz(this, userAmountKEY) > 0))
484487 then throw(("there are locked WXs - consider to use increaseLock " + userAmountKEY))
485488 else {
486489 let coeffX8 = fraction(duration, MULT8, maxLockDuration)
487490 let gWxAmountStart = fraction(pmtAmount, coeffX8, MULT8)
488- let gWxParamsResultList = asAnyList(invoke(mathContract, "calcGwxParamsREADONLY", [gWxAmountStart, lockStart, duration], nil))
489- let k = asInt(gWxParamsResultList[0])
490- let b = asInt(gWxParamsResultList[1])
491- let period = toString(asInt(gWxParamsResultList[2]))
492- let wxEmissionPerBlock = getIntOrFail(emissionContract, keyEmissionRatePerBlockCurrent())
493- let emissionStart = getIntOrFail(emissionContract, keyEmissionStartBlock())
494- let emissionEnd = getIntOrFail(emissionContract, keyEmissionEndBlock())
491+ let gWxParamsResultList = aal(invoke(mathContract, "calcGwxParamsREADONLY", [gWxAmountStart, lockStart, duration], nil))
492+ let k = ai(gWxParamsResultList[0])
493+ let b = ai(gWxParamsResultList[1])
494+ let period = toString(ai(gWxParamsResultList[2]))
495+ let wxEmissionPerBlock = iof(emissionContract, keyEmissionRatePerBlockCurrent())
496+ let emissionStart = iof(emissionContract, keyEmissionStartBlock())
497+ let emissionEnd = iof(emissionContract, keyEmissionEndBlock())
495498 let h = if ((height > emissionEnd))
496499 then emissionEnd
497500 else height
498501 let dh = max([(h - emissionStart), 0])
499502 let userBoostEmissionLastIntegralKEY = keyUserBoostEmissionLastINTEGRAL(userNumStr)
500503 let boostEmissionIntegral = (((wxEmissionPerBlock * dh) * 2) / 3)
501504 let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
502505 let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
503506 let userMaxBoostInt = ((gWxAmountStart * duration) / 2)
504- let totalMaxBoostInt = getIntOrZero(this, totalMaxBoostIntegralKEY)
507+ let totalMaxBoostInt = ioz(this, totalMaxBoostIntegralKEY)
505508 let totalCachedGwxKEY = keyTotalCachedGwx()
506509 let totalCachedGwx = valueOrElse(getInteger(this, totalCachedGwxKEY), 0)
507510 let arr = if (userIsExisting)
508511 then nil
509512 else [IntegerEntry(nextUserNumKEY, (userNum + 1)), StringEntry(keyUser2NumMapping(userAddressStr), userNumStr), StringEntry(keyNum2UserMapping(userNumStr), userAddressStr)]
510513 ((((arr ++ LockParamsEntry(userAddressStr, userNumStr, pmtAmount, lockStart, duration, k, b, period)) ++ StatsEntry(pmtAmount, duration, 1, if (userIsExisting)
511514 then 0
512515 else 1)) :+ HistoryEntry("lock", userAddressStr, pmtAmount, lockStart, duration, k, b, i)) ++ [IntegerEntry(userBoostEmissionLastIntegralKEY, boostEmissionIntegral), IntegerEntry(totalCachedGwxKEY, (totalCachedGwx + gWxAmountStart))])
513516 }
514517 }
515518 }
516519 }
517520
518521
519522
520523 @Callable(i)
521524 func increaseLock (deltaDuration) = {
522525 let cfgArray = readConfigArrayOrFail()
523526 let assetIdStr = cfgArray[IdxCfgAssetId]
524527 let assetId = fromBase58String(assetIdStr)
525528 let minLockDuration = parseIntValue(cfgArray[IdxCfgMinLockDuration])
526529 let maxLockDuration = parseIntValue(cfgArray[IdxCfgMaxLockDuration])
527530 let mathContract = addressFromStringValue(cfgArray[IdxCfgMathContract])
528531 let pmtAmount = extractOptionalPaymentAmountOrFail(i, assetId)
529532 let userAddressStr = toString(i.caller)
530533 let userRecordArray = readLockParamsRecordOrFail(userAddressStr)
531534 let userNumStr = userRecordArray[IdxLockUserNum]
532535 let userAmount = parseIntValue(userRecordArray[IdxLockAmount])
533536 let lockStart = parseIntValue(userRecordArray[IdxLockStart])
534537 let lockDuration = parseIntValue(userRecordArray[IdxLockDuration])
535538 let lockEnd = (lockStart + lockDuration)
536539 let remainingDuration = max([(lockEnd - height), 0])
537540 let userAmountNew = (userAmount + pmtAmount)
538541 let lockDurationNew = (remainingDuration + deltaDuration)
539542 if ((0 > deltaDuration))
540543 then throw("duration is less then zero")
541544 else if ((minLockDuration > lockDurationNew))
542545 then throw(("lockDurationNew is less then minLockDuration=" + toString(minLockDuration)))
543546 else if ((lockDurationNew > maxLockDuration))
544547 then throw(("deltaDuration + existedLockDuration is greater then maxLockDuration=" + toString(maxLockDuration)))
545548 else {
546549 let coeffX8 = fraction(lockDurationNew, MULT8, maxLockDuration)
547550 let gWxAmountStart = fraction(userAmountNew, coeffX8, MULT8)
548551 let lockStartNew = height
549- let gWxParamsResultList = asAnyList(invoke(mathContract, "calcGwxParamsREADONLY", [gWxAmountStart, lockStartNew, lockDurationNew], nil))
550- let k = asInt(gWxParamsResultList[0])
551- let b = asInt(gWxParamsResultList[1])
552- let period = toString(asInt(gWxParamsResultList[2]))
553- let wxEmissionPerBlock = getIntOrFail(emissionContract, keyEmissionRatePerBlockCurrent())
554- let emissionStart = getIntOrFail(emissionContract, keyEmissionStartBlock())
555- let emissionEnd = getIntOrFail(emissionContract, keyEmissionEndBlock())
552+ let gWxParamsResultList = aal(invoke(mathContract, "calcGwxParamsREADONLY", [gWxAmountStart, lockStartNew, lockDurationNew], nil))
553+ let k = ai(gWxParamsResultList[0])
554+ let b = ai(gWxParamsResultList[1])
555+ let period = toString(ai(gWxParamsResultList[2]))
556+ let wxEmissionPerBlock = iof(emissionContract, keyEmissionRatePerBlockCurrent())
557+ let emissionStart = iof(emissionContract, keyEmissionStartBlock())
558+ let emissionEnd = iof(emissionContract, keyEmissionEndBlock())
556559 let h = if ((height > emissionEnd))
557560 then emissionEnd
558561 else height
559562 let dh = max([(h - emissionStart), 0])
560563 let userBoostEmissionLastIntegralKEY = keyUserBoostEmissionLastINTEGRAL(userNumStr)
561- let userBoostEmissionLastIntegral = getIntOrZero(this, userBoostEmissionLastIntegralKEY)
564+ let userBoostEmissionLastIntegral = ioz(this, userBoostEmissionLastIntegralKEY)
562565 let boostEmissionIntegral = (((wxEmissionPerBlock * dh) * 2) / 3)
563566 let userBoostEmissionIntegral = (boostEmissionIntegral - userBoostEmissionLastIntegral)
564567 if ((0 > userBoostEmissionIntegral))
565568 then throw("wrong calculations")
566569 else {
567570 let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
568571 let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
569- let userMaxBoostInt = getIntOrZero(this, userMaxBoostIntegralKEY)
570- let totalMaxBoostInt = getIntOrZero(this, totalMaxBoostIntegralKEY)
572+ let userMaxBoostInt = ioz(this, userMaxBoostIntegralKEY)
573+ let totalMaxBoostInt = ioz(this, totalMaxBoostIntegralKEY)
571574 let currUserGwx = calcCurrentGwxAmount(userAddressStr)
572575 let gwxDiff = (gWxAmountStart - currUserGwx)
573576 if ((0 > gwxDiff))
574577 then throw(("gwxDiff is less then 0: " + toString(gwxDiff)))
575578 else {
576579 let totalCachedGwxKEY = keyTotalCachedGwx()
577580 let totalCachedGwx = valueOrElse(getInteger(this, totalCachedGwxKEY), 0)
578581 let userBoostAvalaibleToClaimTotalKEY = keyUserBoostAvalaibleToClaimTotal(userNumStr)
579- let userBoostAvaliableToClaimTotal = getIntOrZero(this, userBoostAvalaibleToClaimTotalKEY)
582+ let userBoostAvaliableToClaimTotal = ioz(this, userBoostAvalaibleToClaimTotalKEY)
580583 let userBoostAvaliableToClaimTotalNew = fraction(userBoostEmissionIntegral, currUserGwx, totalCachedGwx)
581584 let userMaxBoostIntNew = ((gWxAmountStart * lockDurationNew) / 2)
582585 let remainingUserMaxBoostInt = ((currUserGwx * remainingDuration) / 2)
583586 let userMaxBoostIntDiff = (userMaxBoostIntNew - remainingUserMaxBoostInt)
584587 (((LockParamsEntry(userAddressStr, userNumStr, userAmountNew, lockStartNew, lockDurationNew, k, b, period) ++ StatsEntry(pmtAmount, deltaDuration, 0, 0)) :+ HistoryEntry("lock", userAddressStr, pmtAmount, lockStart, lockDurationNew, k, b, i)) ++ [IntegerEntry(totalCachedGwxKEY, (totalCachedGwx + gwxDiff))])
585588 }
586589 }
587590 }
588591 }
589592
590593
591594
592595 @Callable(i)
593596 func claimWxBoost (lpAssetIdStr,userAddressStr) = if ((stakingContract != i.caller))
594597 then throw("permissions denied")
595598 else {
596- let $t02781027912 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, false)
597- let userBoostAvailable = $t02781027912._1
598- let dataState = $t02781027912._2
599- let debug = $t02781027912._3
599+ let $t02769827800 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, false)
600+ let userBoostAvailable = $t02769827800._1
601+ let dataState = $t02769827800._2
602+ let debug = $t02769827800._3
600603 $Tuple2(dataState, [userBoostAvailable])
601604 }
602605
603606
604607
605608 @Callable(i)
606609 func claimWxBoostREADONLY (lpAssetIdStr,userAddressStr) = {
607- let $t02804428145 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, true)
608- let userBoostAvailable = $t02804428145._1
609- let dataState = $t02804428145._2
610- let debug = $t02804428145._3
610+ let $t02793228033 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, true)
611+ let userBoostAvailable = $t02793228033._1
612+ let dataState = $t02793228033._2
613+ let debug = $t02793228033._3
611614 $Tuple2(nil, [userBoostAvailable, debug])
612615 }
613616
614617
615618
616619 @Callable(i)
617620 func unlock (userAddress) = {
618621 let userRecordArray = readLockParamsRecordOrFail(userAddress)
619622 let userNumStr = userRecordArray[IdxLockUserNum]
620623 let userAmount = parseIntValue(userRecordArray[IdxLockAmount])
621624 let lockStart = parseIntValue(userRecordArray[IdxLockStart])
622625 let lockDuration = parseIntValue(userRecordArray[IdxLockDuration])
623626 let lockEnd = (lockStart + lockDuration)
624627 let cfgArray = readConfigArrayOrFail()
625628 let assetId = fromBase58String(cfgArray[IdxCfgAssetId])
626629 let mathContract = addressFromStringValue(cfgArray[IdxCfgMathContract])
627630 if ((lockEnd >= height))
628631 then throw((("wait " + toString(lockEnd)) + " to unlock"))
629632 else if ((0 >= userAmount))
630633 then throw("nothing to unlock")
631634 else {
632635 let period = valueOrElse(getInteger(mathContract, keyNextPeriod()), 0)
633636 (((LockParamsEntry(userAddress, userNumStr, 0, lockStart, lockDuration, 0, 0, toString(period)) ++ StatsEntry(-(userAmount), 0, 0, -1)) :+ HistoryEntry("unlock", userAddress, userAmount, lockStart, lockDuration, 0, 0, i)) :+ ScriptTransfer(addressFromStringValue(userAddress), userAmount, assetId))
634637 }
635638 }
636639
637640
638641
639642 @Callable(i)
640643 func gwxUserInfoREADONLY (userAddress) = {
641644 let gwxAmount = calcCurrentGwxAmount(userAddress)
642645 $Tuple2(nil, [gwxAmount])
646+ }
647+
648+
649+
650+@Callable(i)
651+func getUserGwxAmountAtHeightREADONLY (userAddress,targetHeight) = {
652+ let gwxAmount = calcUserGwxAmountAtHeight(userAddress, targetHeight)
653+ $Tuple2(nil, gwxAmount)
643654 }
644655
645656
646657
647658 @Callable(i)
648659 func setManager (pendingManagerPublicKey) = {
649660 let checkCaller = mustManager(i)
650661 if ((checkCaller == checkCaller))
651662 then {
652663 let checkManagerPublicKey = fromBase58String(pendingManagerPublicKey)
653664 if ((checkManagerPublicKey == checkManagerPublicKey))
654665 then [StringEntry(keyPendingManagerPublicKey(), pendingManagerPublicKey)]
655666 else throw("Strict value is not equal to itself.")
656667 }
657668 else throw("Strict value is not equal to itself.")
658669 }
659670
660671
661672
662673 @Callable(i)
663674 func confirmManager () = {
664675 let pm = pendingManagerPublicKeyOrUnit()
665676 let hasPM = if (isDefined(pm))
666677 then true
667678 else throw("No pending manager")
668679 if ((hasPM == hasPM))
669680 then {
670681 let checkPM = if ((i.callerPublicKey == value(pm)))
671682 then true
672683 else throw("You are not pending manager")
673684 if ((checkPM == checkPM))
674685 then [StringEntry(keyManagerPublicKey(), toBase58String(value(pm))), DeleteEntry(keyPendingManagerPublicKey())]
675686 else throw("Strict value is not equal to itself.")
676687 }
677688 else throw("Strict value is not equal to itself.")
678689 }
679690
680691
681692 @Verifier(tx)
682693 func verify () = {
683694 let targetPublicKey = match managerPublicKeyOrUnit() {
684695 case pk: ByteVector =>
685696 pk
686697 case _: Unit =>
687698 tx.senderPublicKey
688699 case _ =>
689700 throw("Match error")
690701 }
691702 sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey)
692703 }
693704

github/deemru/w8io/786bc32 
144.36 ms