tx · DTXYtkHHqmtmF56TrmDc6vXrDTXh8v5YJyZFDF36Dchk

3Myu2fd7qjgM3kBm1YGjCWAB6RF8STyv9Gs:  -0.01000000 Waves

2021.11.25 16:22 [1806623] smart account 3Myu2fd7qjgM3kBm1YGjCWAB6RF8STyv9Gs > SELF 0.00000000 Waves

{ "type": 13, "id": "DTXYtkHHqmtmF56TrmDc6vXrDTXh8v5YJyZFDF36Dchk", "fee": 1000000, "feeAssetId": null, "timestamp": 1637846590614, "version": 1, "sender": "3Myu2fd7qjgM3kBm1YGjCWAB6RF8STyv9Gs", "senderPublicKey": "6MNRhMJWPQC5kYFZNsYg1y1bAEh5cHEwVenZHXaBKLTz", "proofs": [ "3ud8xDi9hRE4pBQuAQEtV2HkF8rvrGd2gzCp59UJ699Y5GrQy1rg4tCmCLUWwXJ7iQNneV4E5tuPXhuWBiLhgAW1" ], "script": "base64:AAIFAAAAAAAAACoIAhIICgYICAEBAQgSAwoBARIDCgEBEgMKAQgSAwoBCBIDCgEIEgMKAQgAAABSAAAAAANTRVACAAAAAl9fAAAAAAZTQ0FMRTgAAAAAAAAAAAgAAAAABU1VTFQ4AAAAAAAF9eEAAQAAAA9nZXRTdHJpbmdPckZhaWwAAAACAAAAB2FkZHJlc3MAAAADa2V5CQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQdAAAAAgUAAAAHYWRkcmVzcwUAAAADa2V5CQABLAAAAAIJAAEsAAAAAgIAAAAPbWFuZGF0b3J5IHRoaXMuBQAAAANrZXkCAAAADyBpcyBub3QgZGVmaW5lZAEAAAAMZ2V0SW50T3JaZXJvAAAAAgAAAAdhZGRyZXNzAAAAA2tleQkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAdhZGRyZXNzBQAAAANrZXkAAAAAAAAAAAABAAAAD2dldEludE9yRGVmYXVsdAAAAAMAAAAHYWRkcmVzcwAAAANrZXkAAAAKZGVmYXVsdFZhbAkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAdhZGRyZXNzBQAAAANrZXkFAAAACmRlZmF1bHRWYWwBAAAADGdldEludE9yRmFpbAAAAAIAAAAHYWRkcmVzcwAAAANrZXkJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABBoAAAACBQAAAAdhZGRyZXNzBQAAAANrZXkJAAEsAAAAAgkAASwAAAACAgAAAA9tYW5kYXRvcnkgdGhpcy4FAAAAA2tleQIAAAAPIGlzIG5vdCBkZWZpbmVkAQAAAAlhc0FueUxpc3QAAAABAAAAA3ZhbAQAAAAHJG1hdGNoMAUAAAADdmFsAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAAlMaXN0W0FueV0EAAAACnZhbEFueUx5c3QFAAAAByRtYXRjaDAFAAAACnZhbEFueUx5c3QJAAACAAAAAQIAAAAbZmFpbCB0byBjYXN0IGludG8gTGlzdFtBbnldAQAAAAVhc0ludAAAAAEAAAADdmFsBAAAAAckbWF0Y2gwBQAAAAN2YWwDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAA0ludAQAAAAGdmFsSW50BQAAAAckbWF0Y2gwBQAAAAZ2YWxJbnQJAAACAAAAAQIAAAAVZmFpbCB0byBjYXN0IGludG8gSW50AQAAABFrZXlGYWN0b3J5QWRkcmVzcwAAAAACAAAAHCVzJXNfX2NvbmZpZ19fZmFjdG9yeUFkZHJlc3MAAAAAGElkeEZhY3RvcnlDZmdTdGFraW5nRGFwcAAAAAAAAAAAAQAAAAAZSWR4RmFjdG9yeUNmZ0Jvb3N0aW5nRGFwcAAAAAAAAAAAAgAAAAAUSWR4RmFjdG9yeUNmZ0lkb0RhcHAAAAAAAAAAAAMAAAAAFUlkeEZhY3RvcnlDZmdUZWFtRGFwcAAAAAAAAAAABAAAAAAZSWR4RmFjdG9yeUNmZ0VtaXNzaW9uRGFwcAAAAAAAAAAABQAAAAAVSWR4RmFjdG9yeUNmZ1Jlc3REYXBwAAAAAAAAAAAGAAAAABlJZHhGYWN0b3J5Q2ZnU2xpcHBhZ2VEYXBwAAAAAAAAAAAHAQAAAA1rZXlGYWN0b3J5Q2ZnAAAAAAIAAAARJXNfX2ZhY3RvcnlDb25maWcBAAAAGmtleUZhY3RvcnlMcDJBc3NldHNNYXBwaW5nAAAAAQAAAApscEFzc2V0U3RyCQAEuQAAAAIJAARMAAAAAgIAAAAGJXMlcyVzCQAETAAAAAIFAAAACmxwQXNzZXRTdHIJAARMAAAAAgIAAAAebWFwcGluZ3NfX2xwQXNzZXQyUG9vbENvbnRyYWN0BQAAAANuaWwFAAAAA1NFUAEAAAAQa2V5RmFjdG9yeUxwTGlzdAAAAAACAAAAECVzX19scFRva2Vuc0xpc3QBAAAAJmtleUZhY3RvcnlMcEFzc2V0VG9Qb29sQ29udHJhY3RBZGRyZXNzAAAAAQAAAApscEFzc2V0U3RyCQAEuQAAAAIJAARMAAAAAgIAAAAGJXMlcyVzCQAETAAAAAIFAAAACmxwQXNzZXRTdHIJAARMAAAAAgIAAAAebWFwcGluZ3NfX2xwQXNzZXQyUG9vbENvbnRyYWN0BQAAAANuaWwFAAAAA1NFUAEAAAAUa2V5RmFjdG9yeVBvb2xXZWlnaHQAAAABAAAAD2NvbnRyYWN0QWRkcmVzcwkABLkAAAACCQAETAAAAAICAAAABCVzJXMJAARMAAAAAgIAAAAKcG9vbFdlaWdodAkABEwAAAACBQAAAA9jb250cmFjdEFkZHJlc3MFAAAAA25pbAUAAAADU0VQAQAAABhyZWFkRmFjdG9yeUFkZHJlc3NPckZhaWwAAAAACQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABCQEAAAAPZ2V0U3RyaW5nT3JGYWlsAAAAAgUAAAAEdGhpcwkBAAAAEWtleUZhY3RvcnlBZGRyZXNzAAAAAAEAAAAKcmVhZExwTGlzdAAAAAAJAAS1AAAAAgkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABB0AAAACCQEAAAAYcmVhZEZhY3RvcnlBZGRyZXNzT3JGYWlsAAAAAAkBAAAAEGtleUZhY3RvcnlMcExpc3QAAAAAAgAAAAAFAAAAA1NFUAEAAAAUcmVhZEZhY3RvcnlDZmdPckZhaWwAAAABAAAAB2ZhY3RvcnkJAAS1AAAAAgkBAAAAD2dldFN0cmluZ09yRmFpbAAAAAIFAAAAB2ZhY3RvcnkJAQAAAA1rZXlGYWN0b3J5Q2ZnAAAAAAUAAAADU0VQAQAAABhnZXRCb29zdGluZ0FkZHJlc3NPckZhaWwAAAABAAAACmZhY3RvcnlDZmcJAQAAABFAZXh0ck5hdGl2ZSgxMDYyKQAAAAEJAAGRAAAAAgUAAAAKZmFjdG9yeUNmZwUAAAAZSWR4RmFjdG9yeUNmZ0Jvb3N0aW5nRGFwcAEAAAAYZ2V0RW1pc3Npb25BZGRyZXNzT3JGYWlsAAAAAQAAAApmYWN0b3J5Q2ZnCQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABCQABkQAAAAIFAAAACmZhY3RvcnlDZmcFAAAAGUlkeEZhY3RvcnlDZmdFbWlzc2lvbkRhcHABAAAAF2dldFN0YWtpbmdBZGRyZXNzT3JGYWlsAAAAAQAAAApmYWN0b3J5Q2ZnCQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABCQABkQAAAAIFAAAACmZhY3RvcnlDZmcFAAAAGElkeEZhY3RvcnlDZmdTdGFraW5nRGFwcAEAAAAea2V5RW1pc3Npb25SYXRlUGVyQmxvY2tDdXJyZW50AAAAAAIAAAAbJXMlc19fcmF0ZVBlckJsb2NrX19jdXJyZW50AQAAACFrZXlFbWlzc2lvblJhdGVQZXJCbG9ja01heEN1cnJlbnQAAAAAAgAAAB4lcyVzX19yYXRlUGVyQmxvY2tNYXhfX2N1cnJlbnQBAAAAFWtleUVtaXNzaW9uU3RhcnRCbG9jawAAAAACAAAAGiVzJXNfX2VtaXNzaW9uX19zdGFydEJsb2NrAQAAABtrZXlFbWlzc2lvbkR1cmF0aW9uSW5CbG9ja3MAAAAAAgAAABglcyVzX19lbWlzc2lvbl9fZHVyYXRpb24BAAAAE2tleUVtaXNzaW9uRW5kQmxvY2sAAAAAAgAAABglcyVzX19lbWlzc2lvbl9fZW5kQmxvY2sAAAAADUlkeENmZ0Fzc2V0SWQAAAAAAAAAAAEAAAAAE0lkeENmZ01pbkxvY2tBbW91bnQAAAAAAAAAAAIAAAAAFUlkeENmZ01pbkxvY2tEdXJhdGlvbgAAAAAAAAAAAwAAAAAVSWR4Q2ZnTWF4TG9ja0R1cmF0aW9uAAAAAAAAAAAEAAAAABJJZHhDZmdNYXRoQ29udHJhY3QAAAAAAAAAAAUBAAAACWtleUNvbmZpZwAAAAACAAAACiVzX19jb25maWcBAAAAFXJlYWRDb25maWdBcnJheU9yRmFpbAAAAAAJAAS1AAAAAgkBAAAAD2dldFN0cmluZ09yRmFpbAAAAAIFAAAABHRoaXMJAQAAAAlrZXlDb25maWcAAAAABQAAAANTRVABAAAADWZvcm1hdENvbmZpZ1MAAAAFAAAAB2Fzc2V0SWQAAAANbWluTG9ja0Ftb3VudAAAAA9taW5Mb2NrRHVyYXRpb24AAAAPbWF4TG9ja0R1cmF0aW9uAAAADG1hdGhDb250cmFjdAkABLkAAAACCQAETAAAAAICAAAACCVzJWQlZCVkCQAETAAAAAIFAAAAB2Fzc2V0SWQJAARMAAAAAgUAAAANbWluTG9ja0Ftb3VudAkABEwAAAACBQAAAA9taW5Mb2NrRHVyYXRpb24JAARMAAAAAgUAAAAPbWF4TG9ja0R1cmF0aW9uCQAETAAAAAIFAAAADG1hdGhDb250cmFjdAUAAAADbmlsBQAAAANTRVABAAAADGZvcm1hdENvbmZpZwAAAAUAAAAHYXNzZXRJZAAAAA1taW5Mb2NrQW1vdW50AAAAD21pbkxvY2tEdXJhdGlvbgAAAA9tYXhMb2NrRHVyYXRpb24AAAAMbWF0aENvbnRyYWN0CQEAAAANZm9ybWF0Q29uZmlnUwAAAAUF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AAAAHSVzJXNfX3N0YXRzX19hY3RpdmVVc2Vyc0NvdW50AQAAACBrZXlVc2VyQm9vc3RFbWlzc2lvbkxhc3RJTlRFR1JBTAAAAAEAAAAHdXNlck51bQkABLkAAAACCQAETAAAAAICAAAAHiVzJWRfX3VzZXJCb29zdEVtaXNzaW9uTGFzdEludAkABEwAAAACBQAAAAd1c2VyTnVtBQAAAANuaWwFAAAAA1NFUAEAAAAXa2V5VXNlck1heEJvb3N0SU5URUdSQUwAAAABAAAAB3VzZXJOdW0JAAS5AAAAAgkABEwAAAACAgAAABElcyVkX19tYXhCb29zdEludAkABEwAAAACBQAAAAd1c2VyTnVtBQAAAANuaWwFAAAAA1NFUAEAAAAYa2V5VG90YWxNYXhCb29zdElOVEVHUkFMAAAAAAIAAAAYJXMlc19fbWF4Qm9vc3RJbnRfX3RvdGFsAQAAACFrZXlVc2VyQm9vc3RBdmFsYWlibGVUb0NsYWltVG90YWwAAAABAAAAB3VzZXJOdW0JAAS5AAAAAgkABEwAAAACAgAAACQlcyVkX191c2VyQm9vc3RBdmFsaWFibGVUb0NsYWltVG90YWwJAARMAAAAAgUAAAAHdXNlck51bQUAAAADbmlsBQAAAANTRVABAAAAE2tleVVzZXJCb29zdENsYWltZWQAAAABAAAAB3VzZXJOdW0JAAS5AAAAAgkABEwAAAACAgAAABYlcyVkX191c2VyQm9vc3RDbGFpbWVkCQAETAAAAAIFAAAAB3VzZXJOdW0FAAAAA25pbAUAAAADU0VQAAAAAA9mYWN0b3J5Q29udHJhY3QJAQAAABhyZWFkRmFjdG9yeUFkZHJlc3NPckZhaWwAAAAAAAAAAApmYWN0b3J5Q2ZnCQEAAAAUcmVhZEZhY3RvcnlDZmdPckZhaWwAAAABBQAAAA9mYWN0b3J5Q29udHJhY3QAAAAAEGVtaXNzaW9uQ29udHJhY3QJAQAAABhnZXRFbWlzc2lvbkFkZHJlc3NPckZhaWwAAAABBQAAAApmYWN0b3J5Q2ZnAAAAAA9zdGFraW5nQ29udHJhY3QJAQAAABdnZXRTdGFraW5nQWRkcmVzc09yRmFpbAAAAAEFAAAACmZhY3RvcnlDZmcBAAAADEhpc3RvcnlFbnRyeQAAAAgAAAAEdHlwZQAAAAR1c2VyAAAABmFtb3VudAAAAAlsb2NrU3RhcnQAAAAIZHVyYXRpb24AAAABawAAAAFiAAAAAWkEAAAACmhpc3RvcnlLRVkJAAS5AAAAAgkABEwAAAACAgAAABElcyVzJXMlc19faGlzdG9yeQkABEwAAAACBQAAAAR0eXBlCQAETAAAAAIFAAAABHVzZXIJAARMAAAAAgkAAlgAAAABCAUAAAABaQAAAA10cmFuc2FjdGlvbklkBQAAAANuaWwFAAAAA1NFUAQAAAALaGlzdG9yeURBVEEJAAS5AAAAAgkABEwAAAACAgAAAA4lZCVkJWQlZCVkJWQlZAkABEwAAAACCQABpAAAAAEIBQAAAAlsYXN0QmxvY2sAAAAGaGVpZ2h0CQAETAAAAAIJAAGkAAAAAQgFAAAACWxhc3RCbG9jawAAAAl0aW1lc3RhbXAJAARMAAAAAgkAAaQAAAABBQAAAAZhbW91bnQJAARMAAAAAgkAAaQAAAABBQAAAAlsb2NrU3RhcnQJAARMAAAAAgkAAaQAAAABBQAAAAhkdXJhdGlvbgkABEwAAAACCQABpAAAAAEFAAAAAWsJAARMAAAAAgkAAaQAAAABBQAAAAFiBQAAAANuaWwFAAAAA1NFUAkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAAKaGlzdG9yeUtFWQUAAAALaGlzdG9yeURBVEEBAAAAClN0YXRzRW50cnkAAAAEAAAADnRvdGFsTG9ja2VkSW5jAAAAC2R1cmF0aW9uSW5jAAAADGxvY2tDb3VudEluYwAAAA11c2Vyc0NvdW50SW5jBAAAABtsb2Nrc0R1cmF0aW9uU3VtSW5CbG9ja3NLRVkJAQAAACBrZXlTdGF0c0xvY2tzRHVyYXRpb25TdW1JbkJsb2NrcwAAAAAEAAAADWxvY2tzQ291bnRLRVkJAQAAABJrZXlTdGF0c0xvY2tzQ291bnQAAAAABAAAAA11c2Vyc0NvdW50S0VZCQEAAAASa2V5U3RhdHNVc2Vyc0NvdW50AAAAAAQAAAAOdG90YWxBbW91bnRLRVkJAQAAABdrZXlMb2NrUGFyYW1Ub3RhbEFtb3VudAAAAAAEAAAAGGxvY2tzRHVyYXRpb25TdW1JbkJsb2NrcwkBAAAADGdldEludE9yWmVybwAAAAIFAAAABHRoaXMFAAAAG2xvY2tzRHVyYXRpb25TdW1JbkJsb2Nrc0tFWQQAAAAKbG9ja3NDb3VudAkBAAAADGdldEludE9yWmVybwAAAAIFAAAABHRoaXMFAAAADWxvY2tzQ291bnRLRVkEAAAACnVzZXJzQ291bnQJAQAAAAxnZXRJbnRPclplcm8AAAACBQAAAAR0aGlzBQAAAA11c2Vyc0NvdW50S0VZBAAAAAt0b3RhbEFtb3VudAkBAAAADGdldEludE9yWmVybwAAAAIFAAAABHRoaXMFAAAADnRvdGFsQW1vdW50S0VZCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABtsb2Nrc0R1cmF0aW9uU3VtSW5CbG9ja3NLRVkJAABkAAAAAgUAAAAYbG9ja3NEdXJhdGlvblN1bUluQmxvY2tzBQAAAAtkdXJhdGlvbkluYwkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAANbG9ja3NDb3VudEtFWQkAAGQAAAACBQAAAApsb2Nrc0NvdW50BQAAAAxsb2NrQ291bnRJbmMJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAADXVzZXJzQ291bnRLRVkJAABkAAAAAgUAAAAKdXNlcnNDb3VudAUAAAANdXNlcnNDb3VudEluYwkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAOdG90YWxBbW91bnRLRVkJAABkAAAAAgUAAAALdG90YWxBbW91bnQFAAAADnRvdGFsTG9ja2VkSW5jBQAAAANuaWwBAAAADWNhbGNHd3hBbW91bnQAAAADAAAABGtSYXcAAAAEYlJhdwAAAAFoBAAAAAVTQ0FMRQAAAAAAAAAD6AkAAGkAAAACCQAAZAAAAAIJAABoAAAAAgUAAAAEa1JhdwUAAAABaAUAAAAEYlJhdwUAAAAFU0NBTEUBAAAAD0xvY2tQYXJhbXNFbnRyeQAAAAgAAAALdXNlckFkZHJlc3MAAAAHdXNlck51bQAAAAZhbW91bnQAAAAFc3RhcnQAAAAIZHVyYXRpb24AAAABawAAAAFiAAAABnBlcmlvZAQAAAANdXNlckFtb3VudEtFWQkBAAAAFmtleUxvY2tQYXJhbVVzZXJBbW91bnQAAAABBQAAAAd1c2VyTnVtBAAAAA1zdGFydEJsb2NrS0VZCQEAAAAWa2V5TG9ja1BhcmFtU3RhcnRCbG9jawAAAAEFAAAAB3VzZXJOdW0EAAAAC2R1cmF0aW9uS0VZCQEAAAAUa2V5TG9ja1BhcmFtRHVyYXRpb24AAAABBQAAAAd1c2VyTnVtBAAAAARrS0VZCQEAAAANa2V5TG9ja1BhcmFtSwAAAAEFAAAAB3VzZXJOdW0EAAAABGJLRVkJAQAAAA1rZXlMb2NrUGFyYW1CAAAAAQUAAAAHdXNlck51bQQAAAALa0J5UGVyaW9LRVkJAQAAABVrZXlMb2NrUGFyYW1CeVBlcmlvZEsAAAACBQAAAAd1c2VyTnVtBQAAAAZwZXJpb2QEAAAADGJCeVBlcmlvZEtFWQkBAAAAFWtleUxvY2tQYXJhbUJ5UGVyaW9kQgAAAAIFAAAAB3VzZXJOdW0FAAAABnBlcmlvZAQAAAAJZ3d4QW1vdW50CQEAAAANY2FsY0d3eEFtb3VudAAAAAMFAAAAAWsFAAAAAWIFAAAABmhlaWdodAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAANdXNlckFtb3VudEtFWQUAAAAGYW1vdW50CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAA1zdGFydEJsb2NrS0VZBQAAAAVzdGFydAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAALZHVyYXRpb25LRVkFAAAACGR1cmF0aW9uCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAARrS0VZBQAAAAFrCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAARiS0VZBQAAAAFiCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAtrQnlQZXJpb0tFWQUAAAABawkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAMYkJ5UGVyaW9kS0VZBQAAAAFiCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAABNrZXlMb2NrUGFyYW1zUmVjb3JkAAAAAQUAAAALdXNlckFkZHJlc3MJAQAAABZmb3JtYXRMb2NrUGFyYW1zUmVjb3JkAAAABwUAAAAHdXNlck51bQUAAAAGYW1vdW50BQAAAAVzdGFydAUAAAAIZHVyYXRpb24FAAAAAWsFAAAAAWIFAAAACWd3eEFtb3VudAUAAAADbmlsAQAAACJleHRyYWN0T3B0aW9uYWxQYXltZW50QW1vdW50T3JGYWlsAAAAAgAAAAFpAAAAD2V4cGVjdGVkQXNzZXRJZAMJAABmAAAAAgkAAZAAAAABCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAQkAAAIAAAABAgAAABtvbmx5IG9uZSBwYXltZW50IGlzIGFsbG93ZWQDCQAAAAAAAAIJAAGQAAAAAQgFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAAAAAAAAAAAAAEAAAAA3BtdAkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAMJAQAAAAIhPQAAAAIJAQAAAAV2YWx1ZQAAAAEIBQAAAANwbXQAAAAHYXNzZXRJZAUAAAAPZXhwZWN0ZWRBc3NldElkCQAAAgAAAAECAAAAG2ludmFsaWQgYXNzZXQgaWQgaW4gcGF5bWVudAgFAAAAA3BtdAAAAAZhbW91bnQBAAAAFGNhbGNDdXJyZW50R3d4QW1vdW50AAAAAQAAAAt1c2VyQWRkcmVzcwQAAAAFRU1QVFkCAAAABWVtcHR5BAAAABJ1c2VyMk51bU1hcHBpbmdLRVkJAQAAABJrZXlVc2VyMk51bU1hcHBpbmcAAAABBQAAAAt1c2VyQWRkcmVzcwQAAAAHdXNlck51bQkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABCIAAAABBQAAABJ1c2VyMk51bU1hcHBpbmdLRVkFAAAABUVNUFRZBAAAAAFrCQEAAAALdmFsdWVPckVsc2UAAAACCQAEHwAAAAEJAQAAAA1rZXlMb2NrUGFyYW1LAAAAAQUAAAAHdXNlck51bQAAAAAAAAAAAAQAAAABYgkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABB8AAAABCQEAAAANa2V5TG9ja1BhcmFtQgAAAAEFAAAAB3VzZXJOdW0AAAAAAAAAAAAEAAAADWd3eEFtb3VudENhbGMJAQAAAA1jYWxjR3d4QW1vdW50AAAAAwUAAAABawUAAAABYgUAAAAGaGVpZ2h0BAAAAAlnd3hBbW91bnQDCQAAZgAAAAIAAAAAAAAAAAAFAAAADWd3eEFtb3VudENhbGMAAAAAAAAAAAAFAAAADWd3eEFtb3VudENhbGMFAAAACWd3eEFtb3VudAEAAAAUaW50ZXJuYWxDbGFpbVd4Qm9vc3QAAAABAAAADnVzZXJBZGRyZXNzU3RyBAAAAA91c2VyUmVjb3JkQXJyYXkJAQAAABpyZWFkTG9ja1BhcmFtc1JlY29yZE9yRmFpbAAAAAEFAAAADnVzZXJBZGRyZXNzU3RyBAAAAAp1c2VyTnVtU3RyCQABkQAAAAIFAAAAD3VzZXJSZWNvcmRBcnJheQUAAAAOSWR4TG9ja1VzZXJOdW0EAAAAEnd4RW1pc3Npb25QZXJCbG9jawkBAAAADGdldEludE9yRmFpbAAAAAIFAAAAEGVtaXNzaW9uQ29udHJhY3QJAQAAAB5rZXlFbWlzc2lvblJhdGVQZXJCbG9ja0N1cnJlbnQAAAAABAAAAA1lbWlzc2lvblN0YXJ0CQEAAAAMZ2V0SW50T3JGYWlsAAAAAgUAAAAQZW1pc3Npb25Db250cmFjdAkBAAAAFWtleUVtaXNzaW9uU3RhcnRCbG9jawAAAAAEAAAAC2VtaXNzaW9uRW5kCQEAAAAMZ2V0SW50T3JGYWlsAAAAAgUAAAAQZW1pc3Npb25Db250cmFjdAkBAAAAE2tleUVtaXNzaW9uRW5kQmxvY2sAAAAABAAAAAFoAwkAAGYAAAACBQAAAAZoZWlnaHQFAAAAC2VtaXNzaW9uRW5kBQAAAAtlbWlzc2lvbkVuZAUAAAAGaGVpZ2h0BAAAAAJkaAkAAZYAAAABCQAETAAAAAIJAABlAAAAAgUAAAABaAUAAAANZW1pc3Npb25TdGFydAkABEwAAAACAAAAAAAAAAAABQAAAANuaWwEAAAAIHVzZXJCb29zdEVtaXNzaW9uTGFzdEludGVncmFsS0VZCQEAAAAga2V5VXNlckJvb3N0RW1pc3Npb25MYXN0SU5URUdSQUwAAAABBQAAAAp1c2VyTnVtU3RyBAAAAB11c2VyQm9vc3RFbWlzc2lvbkxhc3RJbnRlZ3JhbAkBAAAADGdldEludE9yWmVybwAAAAIFAAAABHRoaXMFAAAAIHVzZXJCb29zdEVtaXNzaW9uTGFzdEludGVncmFsS0VZBAAAABVib29zdEVtaXNzaW9uSW50ZWdyYWwJAABpAAAAAgkAAGgAAAACCQAAaAAAAAIFAAAAEnd4RW1pc3Npb25QZXJCbG9jawUAAAACZGgAAAAAAAAAAAIAAAAAAAAAAAMEAAAAGXVzZXJCb29zdEVtaXNzaW9uSW50ZWdyYWwJAABlAAAAAgUAAAAVYm9vc3RFbWlzc2lvbkludGVncmFsBQAAAB11c2VyQm9vc3RFbWlzc2lvbkxhc3RJbnRlZ3JhbAMJAABnAAAAAgAAAAAAAAAAAAUAAAAZdXNlckJvb3N0RW1pc3Npb25JbnRlZ3JhbAkAAAIAAAABAgAAABJ3cm9uZyBjYWxjdWxhdGlvbnMEAAAAF3VzZXJNYXhCb29zdEludGVncmFsS0VZCQEAAAAXa2V5VXNlck1heEJvb3N0SU5URUdSQUwAAAABBQAAAAp1c2VyTnVtU3RyBAAAABh0b3RhbE1heEJvb3N0SW50ZWdyYWxLRVkJAQAAABhrZXlUb3RhbE1heEJvb3N0SU5URUdSQUwAAAAABAAAACF1c2VyQm9vc3RBdmFsYWlibGVUb0NsYWltVG90YWxLRVkJAQAAACFrZXlVc2VyQm9vc3RBdmFsYWlibGVUb0NsYWltVG90YWwAAAABBQAAAAp1c2VyTnVtU3RyBAAAAA91c2VyTWF4Qm9vc3RJbnQJAQAAAAxnZXRJbnRPclplcm8AAAACBQAAAAR0aGlzBQAAABd1c2VyTWF4Qm9vc3RJbnRlZ3JhbEtFWQQAAAAQdG90YWxNYXhCb29zdEludAkBAAAADGdldEludE9yWmVybwAAAAIFAAAABHRoaXMFAAAAGHRvdGFsTWF4Qm9vc3RJbnRlZ3JhbEtFWQQAAAAedXNlckJvb3N0QXZhbGlhYmxlVG9DbGFpbVRvdGFsCQEAAAAMZ2V0SW50T3JaZXJvAAAAAgUAAAAEdGhpcwUAAAAhdXNlckJvb3N0QXZhbGFpYmxlVG9DbGFpbVRvdGFsS0VZBAAAACF1c2VyQm9vc3RBdmFsaWFibGVUb0NsYWltVG90YWxOZXcJAABkAAAAAgUAAAAedXNlckJvb3N0QXZhbGlhYmxlVG9DbGFpbVRvdGFsCQAAawAAAAMFAAAAGXVzZXJCb29zdEVtaXNzaW9uSW50ZWdyYWwFAAAAD3VzZXJNYXhCb29zdEludAUAAAAQdG90YWxNYXhCb29zdEludAQAAAATdXNlckJvb3N0Q2xhaW1lZEtFWQkBAAAAE2tleVVzZXJCb29zdENsYWltZWQAAAABBQAAAAp1c2VyTnVtU3RyBAAAABB1c2VyQm9vc3RDbGFpbWVkCQEAAAAMZ2V0SW50T3JaZXJvAAAAAgUAAAAEdGhpcwUAAAATdXNlckJvb3N0Q2xhaW1lZEtFWQQAAAASdXNlckJvb3N0QXZhaWxhYmxlCQAAZQAAAAIFAAAAIXVzZXJCb29zdEF2YWxpYWJsZVRvQ2xhaW1Ub3RhbE5ldwUAAAAQdXNlckJvb3N0Q2xhaW1lZAQAAAAJZGF0YVN0YXRlCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAACF1c2VyQm9vc3RBdmFsYWlibGVUb0NsYWltVG90YWxLRVkFAAAAIXVzZXJCb29zdEF2YWxpYWJsZVRvQ2xhaW1Ub3RhbE5ldwkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAgdXNlckJvb3N0RW1pc3Npb25MYXN0SW50ZWdyYWxLRVkFAAAAFWJvb3N0RW1pc3Npb25JbnRlZ3JhbAUAAAADbmlsCQAFFAAAAAIFAAAAEnVzZXJCb29zdEF2YWlsYWJsZQUAAAAJZGF0YVN0YXRlAAAABwAAAAFpAQAAAAtjb25zdHJ1Y3RvcgAAAAYAAAARZmFjdG9yeUFkZHJlc3NTdHIAAAAObG9ja0Fzc2V0SWRTdHIAAAANbWluTG9ja0Ftb3VudAAAAAttaW5EdXJhdGlvbgAAAAttYXhEdXJhdGlvbgAAAAxtYXRoQ29udHJhY3QDCQEAAAACIT0AAAACBQAAAAR0aGlzCAUAAAABaQAAAAZjYWxsZXIJAAACAAAAAQIAAAAObm90IGF1dGhvcml6ZWQJAAROAAAAAgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAADmtleU5leHRVc2VyTnVtAAAAAAAAAAAAAAAAAAkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAAJa2V5Q29uZmlnAAAAAAkBAAAADGZvcm1hdENvbmZpZwAAAAUFAAAADmxvY2tBc3NldElkU3RyBQAAAA1taW5Mb2NrQW1vdW50BQAAAAttaW5EdXJhdGlvbgUAAAALbWF4RHVyYXRpb24FAAAADG1hdGhDb250cmFjdAkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAARa2V5RmFjdG9yeUFkZHJlc3MAAAAABQAAABFmYWN0b3J5QWRkcmVzc1N0cgUAAAADbmlsCQEAAAAKU3RhdHNFbnRyeQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABaQEAAAAEbG9jawAAAAEAAAAIZHVyYXRpb24EAAAACGNmZ0FycmF5CQEAAAAVcmVhZENvbmZpZ0FycmF5T3JGYWlsAAAAAAQAAAAKYXNzZXRJZFN0cgkAAZEAAAACBQAAAAhjZmdBcnJheQUAAAANSWR4Q2ZnQXNzZXRJZAQAAAAHYXNzZXRJZAkAAlkAAAABBQAAAAphc3NldElkU3RyBAAAAA1taW5Mb2NrQW1vdW50CQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAIY2ZnQXJyYXkFAAAAE0lkeENmZ01pbkxvY2tBbW91bnQEAAAAD21pbkxvY2tEdXJhdGlvbgkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAACGNmZ0FycmF5BQAAABVJZHhDZmdNaW5Mb2NrRHVyYXRpb24EAAAAD21heExvY2tEdXJhdGlvbgkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAACGNmZ0FycmF5BQAAABVJZHhDZmdNYXhMb2NrRHVyYXRpb24EAAAADG1hdGhDb250cmFjdAkBAAAAEUBleHRyTmF0aXZlKDEwNjIpAAAAAQkAAZEAAAACBQAAAAhjZmdBcnJheQUAAAASSWR4Q2ZnTWF0aENvbnRyYWN0AwkBAAAAAiE9AAAAAgkAAZAAAAABCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAQkAAAIAAAABAgAAADRpbnZhbGlkIHBheW1lbnQgLSBleGFjdCBvbmUgcGF5bWVudCBtdXN0IGJlIGF0dGFjaGVkBAAAAANwbXQJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAEAAAACXBtdEFtb3VudAgFAAAAA3BtdAAAAAZhbW91bnQDCQEAAAACIT0AAAACBQAAAAdhc3NldElkCQEAAAAFdmFsdWUAAAABCAUAAAADcG10AAAAB2Fzc2V0SWQJAAACAAAAAQkAASwAAAACCQABLAAAAAICAAAAHmludmFsaWQgYXNzZXQgaXMgaW4gcGF5bWVudCAtIAUAAAAKYXNzZXRJZFN0cgIAAAAMIGlzIGV4cGVjdGVkBAAAAA5uZXh0VXNlck51bUtFWQkBAAAADmtleU5leHRVc2VyTnVtAAAAAAQAAAAOdXNlckFkZHJlc3NTdHIJAAQlAAAAAQgFAAAAAWkAAAAGY2FsbGVyBAAAAA51c2VySXNFeGlzdGluZwkBAAAACWlzRGVmaW5lZAAAAAEJAAQiAAAAAQkBAAAAEmtleVVzZXIyTnVtTWFwcGluZwAAAAEFAAAADnVzZXJBZGRyZXNzU3RyBAAAAAp1c2VyTnVtU3RyAwUAAAAOdXNlcklzRXhpc3RpbmcJAQAAAAV2YWx1ZQAAAAEJAAQiAAAAAQkBAAAAEmtleVVzZXIyTnVtTWFwcGluZwAAAAEFAAAADnVzZXJBZGRyZXNzU3RyCQABpAAAAAEJAQAAAAxnZXRJbnRPckZhaWwAAAACBQAAAAR0aGlzBQAAAA5uZXh0VXNlck51bUtFWQQAAAAHdXNlck51bQkBAAAADXBhcnNlSW50VmFsdWUAAAABBQAAAAp1c2VyTnVtU3RyBAAAAAlsb2NrU3RhcnQFAAAABmhlaWdodAQAAAANc3RhcnRCbG9ja0tFWQkBAAAAFmtleUxvY2tQYXJhbVN0YXJ0QmxvY2sAAAABBQAAAAp1c2VyTnVtU3RyBAAAAAtkdXJhdGlvbktFWQkBAAAAFGtleUxvY2tQYXJhbUR1cmF0aW9uAAAAAQUAAAAKdXNlck51bVN0cgQAAAANdXNlckFtb3VudEtFWQkBAAAAFmtleUxvY2tQYXJhbVVzZXJBbW91bnQAAAABBQAAAAp1c2VyTnVtU3RyAwkAAGYAAAACBQAAAA1taW5Mb2NrQW1vdW50BQAAAAlwbXRBbW91bnQJAAACAAAAAQkAASwAAAACAgAAACJhbW91bnQgaXMgbGVzcyB0aGVuIG1pbkxvY2tBbW91bnQ9CQABpAAAAAEFAAAADW1pbkxvY2tBbW91bnQDCQAAZgAAAAIFAAAAD21pbkxvY2tEdXJhdGlvbgUAAAAIZHVyYXRpb24JAAACAAAAAQkAASwAAAACAgAAAC1wYXNzZWQgZHVyYXRpb24gaXMgbGVzcyB0aGVuIG1pbkxvY2tEdXJhdGlvbj0JAAGkAAAAAQUAAAAPbWluTG9ja0R1cmF0aW9uAwkAAGYAAAACBQAAAAhkdXJhdGlvbgUAAAAPbWF4TG9ja0R1cmF0aW9uCQAAAgAAAAEJAAEsAAAAAgIAAAAwcGFzc2VkIGR1cmF0aW9uIGlzIGdyZWF0ZXIgdGhlbiBtYXhMb2NrRHVyYXRpb249CQABpAAAAAEFAAAAD21heExvY2tEdXJhdGlvbgMDBQAAAA51c2VySXNFeGlzdGluZwkAAGcAAAACCQAAZAAAAAIJAQAAAAxnZXRJbnRPckZhaWwAAAACBQAAAAR0aGlzBQAAAA1zdGFydEJsb2NrS0VZCQEAAAAMZ2V0SW50T3JGYWlsAAAAAgUAAAAEdGhpcwUAAAALZHVyYXRpb25LRVkFAAAACWxvY2tTdGFydAcJAAACAAAAAQIAAAA2dGhlcmUgaXMgYW4gYWN0aXZlIGxvY2sgLSBjb25zaWRlciB0byB1c2UgaW5jcmVhc2VMb2NrBAAAAAdjb2VmZlg4CQAAawAAAAMFAAAACGR1cmF0aW9uBQAAAAVNVUxUOAUAAAAPbWF4TG9ja0R1cmF0aW9uBAAAAA5nV3hBbW91bnRTdGFydAkAAGsAAAADBQAAAAlwbXRBbW91bnQFAAAAB2NvZWZmWDgFAAAABU1VTFQ4BAAAABNnV3hQYXJhbXNSZXN1bHRMaXN0CQEAAAAJYXNBbnlMaXN0AAAAAQkAA/wAAAAEBQAAAAxtYXRoQ29udHJhY3QCAAAAFWNhbGNHd3hQYXJhbXNSRUFET05MWQkABEwAAAACBQAAAA5nV3hBbW91bnRTdGFydAkABEwAAAACBQAAAAlsb2NrU3RhcnQJAARMAAAAAgUAAAAIZHVyYXRpb24FAAAAA25pbAUAAAADbmlsBAAAAAFrCQEAAAAFYXNJbnQAAAABCQABkQAAAAIFAAAAE2dXeFBhcmFtc1Jlc3VsdExpc3QAAAAAAAAAAAAEAAAAAWIJAQAAAAVhc0ludAAAAAEJAAGRAAAAAgUAAAATZ1d4UGFyYW1zUmVzdWx0TGlzdAAAAAAAAAAAAQQAAAAGcGVyaW9kCQABpAAAAAEJAQAAAAVhc0ludAAAAAEJAAGRAAAAAgUAAAATZ1d4UGFyYW1zUmVzdWx0TGlzdAAAAAAAAAAAAgQAAAASd3hFbWlzc2lvblBlckJsb2NrCQEAAAAMZ2V0SW50T3JGYWlsAAAAAgUAAAAQZW1pc3Npb25Db250cmFjdAkBAAAAHmtleUVtaXNzaW9uUmF0ZVBlckJsb2NrQ3VycmVudAAAAAAEAAAADWVtaXNzaW9uU3RhcnQJAQAAAAxnZXRJbnRPckZhaWwAAAACBQAAABBlbWlzc2lvbkNvbnRyYWN0CQEAAAAVa2V5RW1pc3Npb25TdGFydEJsb2NrAAAAAAQAAAALZW1pc3Npb25FbmQJAQAAAAxnZXRJbnRPckZhaWwAAAACBQAAABBlbWlzc2lvbkNvbnRyYWN0CQEAAAATa2V5RW1pc3Npb25FbmRCbG9jawAAAAAEAAAAAWgDCQAAZgAAAAIFAAAABmhlaWdodAUAAAALZW1pc3Npb25FbmQFAAAAC2VtaXNzaW9uRW5kBQAAAAZoZWlnaHQEAAAAAmRoCQABlgAAAAEJAARMAAAAAgkAAGUAAAACBQAAAAFoBQAAAA1lbWlzc2lvblN0YXJ0CQAETAAAAAIAAAAAAAAAAAAFAAAAA25pbAQAAAAgdXNlckJvb3N0RW1pc3Npb25MYXN0SW50ZWdyYWxLRVkJAQAAACBrZXlVc2VyQm9vc3RFbWlzc2lvbkxhc3RJTlRFR1JBTAAAAAEFAAAACnVzZXJOdW1TdHIEAAAAFWJvb3N0RW1pc3Npb25JbnRlZ3JhbAkAAGkAAAACCQAAaAAAAAIJAABoAAAAAgUAAAASd3hFbWlzc2lvblBlckJsb2NrBQAAAAJkaAAAAAAAAAAAAgAAAAAAAAAAAwQAAAAXdXNlck1heEJvb3N0SW50ZWdyYWxLRVkJAQAAABdrZXlVc2VyTWF4Qm9vc3RJTlRFR1JBTAAAAAEFAAAACnVzZXJOdW1TdHIEAAAAGHRvdGFsTWF4Qm9vc3RJbnRlZ3JhbEtFWQkBAAAAGGtleVRvdGFsTWF4Qm9vc3RJTlRFR1JBTAAAAAAEAAAAD3VzZXJNYXhCb29zdEludAkAAGkAAAACCQAAaAAAAAIFAAAADmdXeEFtb3VudFN0YXJ0BQAAAAhkdXJhdGlvbgAAAAAAAAAAAgQAAAAQdG90YWxNYXhCb29zdEludAkBAAAADGdldEludE9yWmVybwAAAAIFAAAABHRoaXMFAAAAGHRvdGFsTWF4Qm9vc3RJbnRlZ3JhbEtFWQQAAAADYXJyAwUAAAAOdXNlcklzRXhpc3RpbmcFAAAAA25pbAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAObmV4dFVzZXJOdW1LRVkJAABkAAAAAgUAAAAHdXNlck51bQAAAAAAAAAAAQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAASa2V5VXNlcjJOdW1NYXBwaW5nAAAAAQUAAAAOdXNlckFkZHJlc3NTdHIFAAAACnVzZXJOdW1TdHIJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAEmtleU51bTJVc2VyTWFwcGluZwAAAAEFAAAACnVzZXJOdW1TdHIFAAAADnVzZXJBZGRyZXNzU3RyBQAAAANuaWwJAAROAAAAAgkABE0AAAACCQAETgAAAAIJAAROAAAAAgUAAAADYXJyCQEAAAAPTG9ja1BhcmFtc0VudHJ5AAAACAUAAAAOdXNlckFkZHJlc3NTdHIFAAAACnVzZXJOdW1TdHIFAAAACXBtdEFtb3VudAUAAAAJbG9ja1N0YXJ0BQAAAAhkdXJhdGlvbgUAAAABawUAAAABYgUAAAAGcGVyaW9kCQEAAAAKU3RhdHNFbnRyeQAAAAQFAAAACXBtdEFtb3VudAUAAAAIZHVyYXRpb24AAAAAAAAAAAEDBQAAAA51c2VySXNFeGlzdGluZwAAAAAAAAAAAAAAAAAAAAAAAQkBAAAADEhpc3RvcnlFbnRyeQAAAAgCAAAABGxvY2sFAAAADnVzZXJBZGRyZXNzU3RyBQAAAAlwbXRBbW91bnQFAAAACWxvY2tTdGFydAUAAAAIZHVyYXRpb24FAAAAAWsFAAAAAWIFAAAAAWkJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAIHVzZXJCb29zdEVtaXNzaW9uTGFzdEludGVncmFsS0VZBQAAABVib29zdEVtaXNzaW9uSW50ZWdyYWwJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAF3VzZXJNYXhCb29zdEludGVncmFsS0VZBQAAAA91c2VyTWF4Qm9vc3RJbnQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAGHRvdGFsTWF4Qm9vc3RJbnRlZ3JhbEtFWQkAAGQAAAACBQAAABB0b3RhbE1heEJvb3N0SW50BQAAAA91c2VyTWF4Qm9vc3RJbnQFAAAAA25pbAAAAAFpAQAAAAxpbmNyZWFzZUxvY2sAAAABAAAADWRlbHRhRHVyYXRpb24EAAAACGNmZ0FycmF5CQEAAAAVcmVhZENvbmZpZ0FycmF5T3JGYWlsAAAAAAQAAAAKYXNzZXRJZFN0cgkAAZEAAAACBQAAAAhjZmdBcnJheQUAAAANSWR4Q2ZnQXNzZXRJZAQAAAAHYXNzZXRJZAkAAlkAAAABBQAAAAphc3NldElkU3RyBAAAAA9taW5Mb2NrRHVyYXRpb24JAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAAAhjZmdBcnJheQUAAAAVSWR4Q2ZnTWluTG9ja0R1cmF0aW9uBAAAAA9tYXhMb2NrRHVyYXRpb24JAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAAAhjZmdBcnJheQUAAAAVSWR4Q2ZnTWF4TG9ja0R1cmF0aW9uBAAAAAxtYXRoQ29udHJhY3QJAQAAABFAZXh0ck5hdGl2ZSgxMDYyKQAAAAEJAAGRAAAAAgUAAAAIY2ZnQXJyYXkFAAAAEklkeENmZ01hdGhDb250cmFjdAQAAAAJcG10QW1vdW50CQEAAAAiZXh0cmFjdE9wdGlvbmFsUGF5bWVudEFtb3VudE9yRmFpbAAAAAIFAAAAAWkFAAAAB2Fzc2V0SWQEAAAADnVzZXJBZGRyZXNzU3RyCQAEJQAAAAEIBQAAAAFpAAAABmNhbGxlcgQAAAAPdXNlclJlY29yZEFycmF5CQEAAAAacmVhZExvY2tQYXJhbXNSZWNvcmRPckZhaWwAAAABBQAAAA51c2VyQWRkcmVzc1N0cgQAAAAKdXNlck51bVN0cgkAAZEAAAACBQAAAA91c2VyUmVjb3JkQXJyYXkFAAAADklkeExvY2tVc2VyTnVtBAAAAAp1c2VyQW1vdW50CQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAPdXNlclJlY29yZEFycmF5BQAAAA1JZHhMb2NrQW1vdW50BAAAAAlsb2NrU3RhcnQJAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAAA91c2VyUmVjb3JkQXJyYXkFAAAADElkeExvY2tTdGFydAQAAAAMbG9ja0R1cmF0aW9uCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAPdXNlclJlY29yZEFycmF5BQAAAA9JZHhMb2NrRHVyYXRpb24EAAAAB2xvY2tFbmQJAABkAAAAAgUAAAAJbG9ja1N0YXJ0BQAAAAxsb2NrRHVyYXRpb24EAAAAEXJlbWFpbmluZ0R1cmF0aW9uCQABlgAAAAEJAARMAAAAAgkAAGUAAAACBQAAAAdsb2NrRW5kBQAAAAZoZWlnaHQJAARMAAAAAgAAAAAAAAAAAAUAAAADbmlsBAAAAA11c2VyQW1vdW50TmV3CQAAZAAAAAIFAAAACnVzZXJBbW91bnQFAAAACXBtdEFtb3VudAQAAAAPbG9ja0R1cmF0aW9uTmV3CQAAZAAAAAIFAAAAEXJlbWFpbmluZ0R1cmF0aW9uBQAAAA1kZWx0YUR1cmF0aW9uAwkAAGYAAAACAAAAAAAAAAAABQAAAA1kZWx0YUR1cmF0aW9uCQAAAgAAAAECAAAAGmR1cmF0aW9uIGlzIGxlc3MgdGhlbiB6ZXJvAwkAAGYAAAACBQAAAA9taW5Mb2NrRHVyYXRpb24FAAAAD2xvY2tEdXJhdGlvbk5ldwkAAAIAAAABCQABLAAAAAICAAAALWxvY2tEdXJhdGlvbk5ldyBpcyBsZXNzIHRoZW4gbWluTG9ja0R1cmF0aW9uPQkAAaQAAAABBQAAAA9taW5Mb2NrRHVyYXRpb24DCQAAZgAAAAIFAAAAD2xvY2tEdXJhdGlvbk5ldwUAAAAPbWF4TG9ja0R1cmF0aW9uCQAAAgAAAAEJAAEsAAAAAgIAAABEZGVsdGFEdXJhdGlvbiArIGV4aXN0ZWRMb2NrRHVyYXRpb24gaXMgZ3JlYXRlciB0aGVuIG1heExvY2tEdXJhdGlvbj0JAAGkAAAAAQUAAAAPbWF4TG9ja0R1cmF0aW9uAwMJAABnAAAAAgUAAAAGaGVpZ2h0BQAAAAdsb2NrRW5kCQAAZgAAAAIFAAAACnVzZXJBbW91bnQAAAAAAAAAAAAHCQAAAgAAAAECAAAAOXRoZXJlIGlzIGFuIGV4cGlyZWQgbG9jayAtIG5lZWQgdG8gdW5sb2NrIGJlZm9yZSBuZXcgbG9jawQAAAAHY29lZmZYOAkAAGsAAAADBQAAAA9sb2NrRHVyYXRpb25OZXcFAAAABU1VTFQ4BQAAAA9tYXhMb2NrRHVyYXRpb24EAAAADmdXeEFtb3VudFN0YXJ0CQAAawAAAAMFAAAADXVzZXJBbW91bnROZXcFAAAAB2NvZWZmWDgFAAAABU1VTFQ4BAAAABNnV3hQYXJhbXNSZXN1bHRMaXN0CQEAAAAJYXNBbnlMaXN0AAAAAQkAA/wAAAAEBQAAAAxtYXRoQ29udHJhY3QCAAAAFWNhbGNHd3hQYXJhbXNSRUFET05MWQkABEwAAAACBQAAAA5nV3hBbW91bnRTdGFydAkABEwAAAACBQAAAAZoZWlnaHQJAARMAAAAAgUAAAAPbG9ja0R1cmF0aW9uTmV3BQAAAANuaWwFAAAAA25pbAQAAAABawkBAAAABWFzSW50AAAAAQkAAZEAAAACBQAAABNnV3hQYXJhbXNSZXN1bHRMaXN0AAAAAAAAAAAABAAAAAFiCQEAAAAFYXNJbnQAAAABCQABkQAAAAIFAAAAE2dXeFBhcmFtc1Jlc3VsdExpc3QAAAAAAAAAAAEEAAAABnBlcmlvZAkAAaQAAAABCQEAAAAFYXNJbnQAAAABCQABkQAAAAIFAAAAE2dXeFBhcmFtc1Jlc3VsdExpc3QAAAAAAAAAAAIEAAAAEnd4RW1pc3Npb25QZXJCbG9jawkBAAAADGdldEludE9yRmFpbAAAAAIFAAAAEGVtaXNzaW9uQ29udHJhY3QJAQAAAB5rZXlFbWlzc2lvblJhdGVQZXJCbG9ja0N1cnJlbnQAAAAABAAAAA1lbWlzc2lvblN0YXJ0CQEAAAAMZ2V0SW50T3JGYWlsAAAAAgUAAAAQZW1pc3Npb25Db250cmFjdAkBAAAAFWtleUVtaXNzaW9uU3RhcnRCbG9jawAAAAAEAAAAC2VtaXNzaW9uRW5kCQEAAAAMZ2V0SW50T3JGYWlsAAAAAgUAAAAQZW1pc3Npb25Db250cmFjdAkBAAAAE2tleUVtaXNzaW9uRW5kQmxvY2sAAAAABAAAAAFoAwkAAGYAAAACBQAAAAZoZWlnaHQFAAAAC2VtaXNzaW9uRW5kBQAAAAtlbWlzc2lvbkVuZAUAAAAGaGVpZ2h0BAAAAAJkaAkAAZYAAAABCQAETAAAAAIJAABlAAAAAgUAAAABaAUAAAANZW1pc3Npb25TdGFydAkABEwAAAACAAAAAAAAAAAABQAAAANuaWwEAAAAIHVzZXJCb29zdEVtaXNzaW9uTGFzdEludGVncmFsS0VZCQEAAAAga2V5VXNlckJvb3N0RW1pc3Npb25MYXN0SU5URUdSQUwAAAABBQAAAAp1c2VyTnVtU3RyBAAAAB11c2VyQm9vc3RFbWlzc2lvbkxhc3RJbnRlZ3JhbAkBAAAADGdldEludE9yWmVybwAAAAIFAAAABHRoaXMFAAAAIHVzZXJCb29zdEVtaXNzaW9uTGFzdEludGVncmFsS0VZBAAAABVib29zdEVtaXNzaW9uSW50ZWdyYWwJAABpAAAAAgkAAGgAAAACCQAAaAAAAAIFAAAAEnd4RW1pc3Npb25QZXJCbG9jawUAAAACZGgAAAAAAAAAAAIAAAAAAAAAAAMEAAAAGXVzZXJCb29zdEVtaXNzaW9uSW50ZWdyYWwJAABlAAAAAgUAAAAVYm9vc3RFbWlzc2lvbkludGVncmFsBQAAAB11c2VyQm9vc3RFbWlzc2lvbkxhc3RJbnRlZ3JhbAMJAABnAAAAAgAAAAAAAAAAAAUAAAAZdXNlckJvb3N0RW1pc3Npb25JbnRlZ3JhbAkAAAIAAAABAgAAABJ3cm9uZyBjYWxjdWxhdGlvbnMEAAAAF3VzZXJNYXhCb29zdEludGVncmFsS0VZCQEAAAAXa2V5VXNlck1heEJvb3N0SU5URUdSQUwAAAABBQAAAAp1c2VyTnVtU3RyBAAAABh0b3RhbE1heEJvb3N0SW50ZWdyYWxLRVkJAQAAABhrZXlUb3RhbE1heEJvb3N0SU5URUdSQUwAAAAABAAAACF1c2VyQm9vc3RBdmFsYWlibGVUb0NsYWltVG90YWxLRVkJAQAAACFrZXlVc2VyQm9vc3RBdmFsYWlibGVUb0NsYWltVG90YWwAAAABBQAAAAp1c2VyTnVtU3RyBAAAAA91c2VyTWF4Qm9vc3RJbnQJAQAAAAxnZXRJbnRPclplcm8AAAACBQAAAAR0aGlzBQAAABd1c2VyTWF4Qm9vc3RJbnRlZ3JhbEtFWQQAAAAQdG90YWxNYXhCb29zdEludAkBAAAADGdldEludE9yWmVybwAAAAIFAAAABHRoaXMFAAAAGHRvdGFsTWF4Qm9vc3RJbnRlZ3JhbEtFWQQAAAAedXNlckJvb3N0QXZhbGlhYmxlVG9DbGFpbVRvdGFsCQEAAAAMZ2V0SW50T3JaZXJvAAAAAgUAAAAEdGhpcwUAAAAhdXNlckJvb3N0QXZhbGFpYmxlVG9DbGFpbVRvdGFsS0VZBAAAACF1c2VyQm9vc3RBdmFsaWFibGVUb0NsYWltVG90YWxOZXcJAABkAAAAAgUAAAAedXNlckJvb3N0QXZhbGlhYmxlVG9DbGFpbVRvdGFsCQAAawAAAAMFAAAAGXVzZXJCb29zdEVtaXNzaW9uSW50ZWdyYWwFAAAAD3VzZXJNYXhCb29zdEludAUAAAAQdG90YWxNYXhCb29zdEludAQAAAASdXNlck1heEJvb3N0SW50TmV3CQAAaQAAAAIJAABoAAAAAgUAAAAOZ1d4QW1vdW50U3RhcnQFAAAAD2xvY2tEdXJhdGlvbk5ldwAAAAAAAAAAAgQAAAALY3VyclVzZXJHd3gJAQAAABRjYWxjQ3VycmVudEd3eEFtb3VudAAAAAEFAAAADnVzZXJBZGRyZXNzU3RyBAAAABhyZW1haW5pbmdVc2VyTWF4Qm9vc3RJbnQJAABpAAAAAgkAAGgAAAACBQAAAAtjdXJyVXNlckd3eAUAAAARcmVtYWluaW5nRHVyYXRpb24AAAAAAAAAAAIEAAAAE3VzZXJNYXhCb29zdEludERpZmYJAABlAAAAAgUAAAASdXNlck1heEJvb3N0SW50TmV3BQAAABhyZW1haW5pbmdVc2VyTWF4Qm9vc3RJbnQDCQAAZwAAAAIAAAAAAAAAAAAFAAAAE3VzZXJNYXhCb29zdEludERpZmYJAAACAAAAAQIAAAASd3JvbmcgY2FsY3VsYXRpb25zCQAETgAAAAIJAARNAAAAAgkABE4AAAACCQEAAAAPTG9ja1BhcmFtc0VudHJ5AAAACAUAAAAOdXNlckFkZHJlc3NTdHIFAAAACnVzZXJOdW1TdHIFAAAADXVzZXJBbW91bnROZXcFAAAACWxvY2tTdGFydAUAAAAPbG9ja0R1cmF0aW9uTmV3BQAAAAFrBQAAAAFiBQAAAAZwZXJpb2QJAQAAAApTdGF0c0VudHJ5AAAABAUAAAAJcG10QW1vdW50BQAAAA1kZWx0YUR1cmF0aW9uAAAAAAAAAAAAAAAAAAAAAAAACQEAAAAMSGlzdG9yeUVudHJ5AAAACAIAAAAEbG9jawUAAAAOdXNlckFkZHJlc3NTdHIFAAAACXBtdEFtb3VudAUAAAAJbG9ja1N0YXJ0BQAAAA9sb2NrRHVyYXRpb25OZXcFAAAAAWsFAAAAAWIFAAAAAWkJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAF3VzZXJNYXhCb29zdEludGVncmFsS0VZBQAAABN1c2VyTWF4Qm9vc3RJbnREaWZmCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABh0b3RhbE1heEJvb3N0SW50ZWdyYWxLRVkJAABkAAAAAgUAAAAQdG90YWxNYXhCb29zdEludAUAAAATdXNlck1heEJvb3N0SW50RGlmZgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAhdXNlckJvb3N0QXZhbGFpYmxlVG9DbGFpbVRvdGFsS0VZBQAAACF1c2VyQm9vc3RBdmFsaWFibGVUb0NsYWltVG90YWxOZXcJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAIHVzZXJCb29zdEVtaXNzaW9uTGFzdEludGVncmFsS0VZBQAAABVib29zdEVtaXNzaW9uSW50ZWdyYWwFAAAAA25pbAAAAAFpAQAAAAxjbGFpbVd4Qm9vc3QAAAABAAAADnVzZXJBZGRyZXNzU3RyBAAAAA0kdDAyMTY4MDIxNzkyCQEAAAAUaW50ZXJuYWxDbGFpbVd4Qm9vc3QAAAABBQAAAA51c2VyQWRkcmVzc1N0cgQAAAASdXNlckJvb3N0QXZhaWxhYmxlCAUAAAANJHQwMjE2ODAyMTc5MgAAAAJfMQQAAAAJZGF0YVN0YXRlCAUAAAANJHQwMjE2ODAyMTc5MgAAAAJfMgUAAAADbmlsAAAAAWkBAAAAFGNsYWltV3hCb29zdFJFQURPTkxZAAAAAQAAAA51c2VyQWRkcmVzc1N0cgQAAAANJHQwMjE4NzAyMTk0NAkBAAAAFGludGVybmFsQ2xhaW1XeEJvb3N0AAAAAQUAAAAOdXNlckFkZHJlc3NTdHIEAAAAEnVzZXJCb29zdEF2YWlsYWJsZQgFAAAADSR0MDIxODcwMjE5NDQAAAACXzEEAAAACWRhdGFTdGF0ZQgFAAAADSR0MDIxODcwMjE5NDQAAAACXzIJAAUUAAAAAgUAAAADbmlsCQAETAAAAAIFAAAAEnVzZXJCb29zdEF2YWlsYWJsZQUAAAADbmlsAAAAAWkBAAAABnVubG9jawAAAAEAAAALdXNlckFkZHJlc3MEAAAAD3VzZXJSZWNvcmRBcnJheQkBAAAAGnJlYWRMb2NrUGFyYW1zUmVjb3JkT3JGYWlsAAAAAQUAAAALdXNlckFkZHJlc3MEAAAACnVzZXJOdW1TdHIJAAGRAAAAAgUAAAAPdXNlclJlY29yZEFycmF5BQAAAA5JZHhMb2NrVXNlck51bQQAAAAKdXNlckFtb3VudAkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAAD3VzZXJSZWNvcmRBcnJheQUAAAANSWR4TG9ja0Ftb3VudAQAAAAJbG9ja1N0YXJ0CQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAPdXNlclJlY29yZEFycmF5BQAAAAxJZHhMb2NrU3RhcnQEAAAADGxvY2tEdXJhdGlvbgkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAAD3VzZXJSZWNvcmRBcnJheQUAAAAPSWR4TG9ja0R1cmF0aW9uBAAAAAdsb2NrRW5kCQAAZAAAAAIFAAAACWxvY2tTdGFydAUAAAAMbG9ja0R1cmF0aW9uBAAAAAhjZmdBcnJheQkBAAAAFXJlYWRDb25maWdBcnJheU9yRmFpbAAAAAAEAAAAB2Fzc2V0SWQJAAJZAAAAAQkAAZEAAAACBQAAAAhjZmdBcnJheQUAAAANSWR4Q2ZnQXNzZXRJZAMJAABnAAAAAgUAAAAHbG9ja0VuZAUAAAAGaGVpZ2h0CQAAAgAAAAEJAAEsAAAAAgkAASwAAAACAgAAAAV3YWl0IAkAAaQAAAABBQAAAAdsb2NrRW5kAgAAAAogdG8gdW5sb2NrAwkAAGcAAAACAAAAAAAAAAAABQAAAAp1c2VyQW1vdW50CQAAAgAAAAECAAAAEW5vdGhpbmcgdG8gdW5sb2NrBAAAAAZwZXJpb2QCAAAAATAJAARNAAAAAgkABE0AAAACCQAETgAAAAIJAQAAAA9Mb2NrUGFyYW1zRW50cnkAAAAIBQAAAAt1c2VyQWRkcmVzcwUAAAAKdXNlck51bVN0cgAAAAAAAAAAAAUAAAAJbG9ja1N0YXJ0BQAAAAxsb2NrRHVyYXRpb24AAAAAAAAAAAAAAAAAAAAAAAAFAAAABnBlcmlvZAkBAAAAClN0YXRzRW50cnkAAAAECQEAAAABLQAAAAEFAAAACnVzZXJBbW91bnQAAAAAAAAAAAAAAAAAAAAAAAAA//////////8JAQAAAAxIaXN0b3J5RW50cnkAAAAIAgAAAAZ1bmxvY2sFAAAAC3VzZXJBZGRyZXNzBQAAAAp1c2VyQW1vdW50BQAAAAlsb2NrU3RhcnQFAAAADGxvY2tEdXJhdGlvbgAAAAAAAAAAAAAAAAAAAAAAAAUAAAABaQkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwkBAAAAEUBleHRyTmF0aXZlKDEwNjIpAAAAAQUAAAALdXNlckFkZHJlc3MFAAAACnVzZXJBbW91bnQFAAAAB2Fzc2V0SWQAAAABaQEAAAATZ3d4VXNlckluZm9SRUFET05MWQAAAAEAAAALdXNlckFkZHJlc3MEAAAACWd3eEFtb3VudAkBAAAAFGNhbGNDdXJyZW50R3d4QW1vdW50AAAAAQUAAAALdXNlckFkZHJlc3MJAAUUAAAAAgUAAAADbmlsCQAETAAAAAIFAAAACWd3eEFtb3VudAUAAAADbmlsAAAAAPcL5gQ=", "chainId": 84, "height": 1806623, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: EHAowXCmHoatCXdVz9P6xU47WqbJ53STCJnQNVHvaw98 Next: GZUviw5gAezdToEWnDMAifKnj4RtdRg1HRi8bSJvNjFz Diff:
OldNewDifferences
1010 func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), (("mandatory this." + key) + " is not defined"))
1111
1212
13-func getIntOrZero (key) = valueOrElse(getInteger(this, key), 0)
13+func getIntOrZero (address,key) = valueOrElse(getInteger(address, key), 0)
1414
1515
16-func getIntOrFail (key) = valueOrErrorMessage(getInteger(key), (("mandatory this." + key) + " is not defined"))
16+func getIntOrDefault (address,key,defaultVal) = valueOrElse(getInteger(address, key), defaultVal)
17+
18+
19+func getIntOrFail (address,key) = valueOrErrorMessage(getInteger(address, key), (("mandatory this." + key) + " is not defined"))
1720
1821
1922 func asAnyList (val) = match val {
8083
8184
8285 func getStakingAddressOrFail (factoryCfg) = addressFromStringValue(factoryCfg[IdxFactoryCfgStakingDapp])
86+
87+
88+func keyEmissionRatePerBlockCurrent () = "%s%s__ratePerBlock__current"
89+
90+
91+func keyEmissionRatePerBlockMaxCurrent () = "%s%s__ratePerBlockMax__current"
92+
93+
94+func keyEmissionStartBlock () = "%s%s__emission__startBlock"
95+
96+
97+func keyEmissionDurationInBlocks () = "%s%s__emission__duration"
98+
99+
100+func keyEmissionEndBlock () = "%s%s__emission__endBlock"
83101
84102
85103 let IdxCfgAssetId = 1
170188 func keyStatsUsersCount () = "%s%s__stats__activeUsersCount"
171189
172190
191+func keyUserBoostEmissionLastINTEGRAL (userNum) = makeString(["%s%d__userBoostEmissionLastInt", userNum], SEP)
192+
193+
194+func keyUserMaxBoostINTEGRAL (userNum) = makeString(["%s%d__maxBoostInt", userNum], SEP)
195+
196+
197+func keyTotalMaxBoostINTEGRAL () = "%s%s__maxBoostInt__total"
198+
199+
200+func keyUserBoostAvalaibleToClaimTotal (userNum) = makeString(["%s%d__userBoostAvaliableToClaimTotal", userNum], SEP)
201+
202+
203+func keyUserBoostClaimed (userNum) = makeString(["%s%d__userBoostClaimed", userNum], SEP)
204+
205+
206+let factoryContract = readFactoryAddressOrFail()
207+
208+let factoryCfg = readFactoryCfgOrFail(factoryContract)
209+
210+let emissionContract = getEmissionAddressOrFail(factoryCfg)
211+
212+let stakingContract = getStakingAddressOrFail(factoryCfg)
213+
173214 func HistoryEntry (type,user,amount,lockStart,duration,k,b,i) = {
174215 let historyKEY = makeString(["%s%s%s%s__history", type, user, toBase58String(i.transactionId)], SEP)
175216 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)
182223 let locksCountKEY = keyStatsLocksCount()
183224 let usersCountKEY = keyStatsUsersCount()
184225 let totalAmountKEY = keyLockParamTotalAmount()
185- let locksDurationSumInBlocks = getIntOrZero(locksDurationSumInBlocksKEY)
186- let locksCount = getIntOrZero(locksCountKEY)
187- let usersCount = getIntOrZero(usersCountKEY)
188- let totalAmount = getIntOrZero(totalAmountKEY)
226+ let locksDurationSumInBlocks = getIntOrZero(this, locksDurationSumInBlocksKEY)
227+ let locksCount = getIntOrZero(this, locksCountKEY)
228+ let usersCount = getIntOrZero(this, usersCountKEY)
229+ let totalAmount = getIntOrZero(this, totalAmountKEY)
189230 [IntegerEntry(locksDurationSumInBlocksKEY, (locksDurationSumInBlocks + durationInc)), IntegerEntry(locksCountKEY, (locksCount + lockCountInc)), IntegerEntry(usersCountKEY, (usersCount + usersCountInc)), IntegerEntry(totalAmountKEY, (totalAmount + totalLockedInc))]
190231 }
191232
221262 }
222263
223264
265+func calcCurrentGwxAmount (userAddress) = {
266+ let EMPTY = "empty"
267+ let user2NumMappingKEY = keyUser2NumMapping(userAddress)
268+ let userNum = valueOrElse(getString(user2NumMappingKEY), EMPTY)
269+ let k = valueOrElse(getInteger(keyLockParamK(userNum)), 0)
270+ let b = valueOrElse(getInteger(keyLockParamB(userNum)), 0)
271+ let gwxAmountCalc = calcGwxAmount(k, b, height)
272+ let gwxAmount = if ((0 > gwxAmountCalc))
273+ then 0
274+ else gwxAmountCalc
275+ gwxAmount
276+ }
277+
278+
279+func internalClaimWxBoost (userAddressStr) = {
280+ let userRecordArray = readLockParamsRecordOrFail(userAddressStr)
281+ let userNumStr = userRecordArray[IdxLockUserNum]
282+ let wxEmissionPerBlock = getIntOrFail(emissionContract, keyEmissionRatePerBlockCurrent())
283+ let emissionStart = getIntOrFail(emissionContract, keyEmissionStartBlock())
284+ let emissionEnd = getIntOrFail(emissionContract, keyEmissionEndBlock())
285+ let h = if ((height > emissionEnd))
286+ then emissionEnd
287+ else height
288+ let dh = max([(h - emissionStart), 0])
289+ let userBoostEmissionLastIntegralKEY = keyUserBoostEmissionLastINTEGRAL(userNumStr)
290+ let userBoostEmissionLastIntegral = getIntOrZero(this, userBoostEmissionLastIntegralKEY)
291+ let boostEmissionIntegral = (((wxEmissionPerBlock * dh) * 2) / 3)
292+ let userBoostEmissionIntegral = (boostEmissionIntegral - userBoostEmissionLastIntegral)
293+ if ((0 >= userBoostEmissionIntegral))
294+ then throw("wrong calculations")
295+ else {
296+ let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
297+ let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
298+ let userBoostAvalaibleToClaimTotalKEY = keyUserBoostAvalaibleToClaimTotal(userNumStr)
299+ let userMaxBoostInt = getIntOrZero(this, userMaxBoostIntegralKEY)
300+ let totalMaxBoostInt = getIntOrZero(this, totalMaxBoostIntegralKEY)
301+ let userBoostAvaliableToClaimTotal = getIntOrZero(this, userBoostAvalaibleToClaimTotalKEY)
302+ let userBoostAvaliableToClaimTotalNew = (userBoostAvaliableToClaimTotal + fraction(userBoostEmissionIntegral, userMaxBoostInt, totalMaxBoostInt))
303+ let userBoostClaimedKEY = keyUserBoostClaimed(userNumStr)
304+ let userBoostClaimed = getIntOrZero(this, userBoostClaimedKEY)
305+ let userBoostAvailable = (userBoostAvaliableToClaimTotalNew - userBoostClaimed)
306+ let dataState = [IntegerEntry(userBoostAvalaibleToClaimTotalKEY, userBoostAvaliableToClaimTotalNew), IntegerEntry(userBoostEmissionLastIntegralKEY, boostEmissionIntegral)]
307+ $Tuple2(userBoostAvailable, dataState)
308+ }
309+ }
310+
311+
224312 @Callable(i)
225313 func constructor (factoryAddressStr,lockAssetIdStr,minLockAmount,minDuration,maxDuration,mathContract) = if ((this != i.caller))
226314 then throw("not authorized")
250338 let userIsExisting = isDefined(getString(keyUser2NumMapping(userAddressStr)))
251339 let userNumStr = if (userIsExisting)
252340 then value(getString(keyUser2NumMapping(userAddressStr)))
253- else toString(getIntOrFail(nextUserNumKEY))
341+ else toString(getIntOrFail(this, nextUserNumKEY))
254342 let userNum = parseIntValue(userNumStr)
255343 let lockStart = height
256344 let startBlockKEY = keyLockParamStartBlock(userNumStr)
263351 else if ((duration > maxLockDuration))
264352 then throw(("passed duration is greater then maxLockDuration=" + toString(maxLockDuration)))
265353 else if (if (userIsExisting)
266- then ((getIntOrFail(startBlockKEY) + getIntOrFail(durationKEY)) >= lockStart)
354+ then ((getIntOrFail(this, startBlockKEY) + getIntOrFail(this, durationKEY)) >= lockStart)
267355 else false)
268356 then throw("there is an active lock - consider to use increaseLock")
269357 else {
270358 let coeffX8 = fraction(duration, MULT8, maxLockDuration)
271- let wxAmountStart = fraction(pmtAmount, coeffX8, MULT8)
272- let gWxParamsResultList = asAnyList(invoke(mathContract, "calcGwxParamsREADONLY", [wxAmountStart, lockStart, duration], nil))
359+ let gWxAmountStart = fraction(pmtAmount, coeffX8, MULT8)
360+ let gWxParamsResultList = asAnyList(invoke(mathContract, "calcGwxParamsREADONLY", [gWxAmountStart, lockStart, duration], nil))
273361 let k = asInt(gWxParamsResultList[0])
274362 let b = asInt(gWxParamsResultList[1])
275363 let period = toString(asInt(gWxParamsResultList[2]))
364+ let wxEmissionPerBlock = getIntOrFail(emissionContract, keyEmissionRatePerBlockCurrent())
365+ let emissionStart = getIntOrFail(emissionContract, keyEmissionStartBlock())
366+ let emissionEnd = getIntOrFail(emissionContract, keyEmissionEndBlock())
367+ let h = if ((height > emissionEnd))
368+ then emissionEnd
369+ else height
370+ let dh = max([(h - emissionStart), 0])
371+ let userBoostEmissionLastIntegralKEY = keyUserBoostEmissionLastINTEGRAL(userNumStr)
372+ let boostEmissionIntegral = (((wxEmissionPerBlock * dh) * 2) / 3)
373+ let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
374+ let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
375+ let userMaxBoostInt = ((gWxAmountStart * duration) / 2)
376+ let totalMaxBoostInt = getIntOrZero(this, totalMaxBoostIntegralKEY)
276377 let arr = if (userIsExisting)
277378 then nil
278379 else [IntegerEntry(nextUserNumKEY, (userNum + 1)), StringEntry(keyUser2NumMapping(userAddressStr), userNumStr), StringEntry(keyNum2UserMapping(userNumStr), userAddressStr)]
279- (((arr ++ LockParamsEntry(userAddressStr, userNumStr, pmtAmount, lockStart, duration, k, b, period)) ++ StatsEntry(pmtAmount, duration, 1, if (userIsExisting)
380+ ((((arr ++ LockParamsEntry(userAddressStr, userNumStr, pmtAmount, lockStart, duration, k, b, period)) ++ StatsEntry(pmtAmount, duration, 1, if (userIsExisting)
280381 then 0
281- else 1)) :+ HistoryEntry("lock", userAddressStr, pmtAmount, lockStart, duration, k, b, i))
382+ else 1)) :+ HistoryEntry("lock", userAddressStr, pmtAmount, lockStart, duration, k, b, i)) ++ [IntegerEntry(userBoostEmissionLastIntegralKEY, boostEmissionIntegral), IntegerEntry(userMaxBoostIntegralKEY, userMaxBoostInt), IntegerEntry(totalMaxBoostIntegralKEY, (totalMaxBoostInt + userMaxBoostInt))])
282383 }
283384 }
284385 }
317418 then throw("there is an expired lock - need to unlock before new lock")
318419 else {
319420 let coeffX8 = fraction(lockDurationNew, MULT8, maxLockDuration)
320- let wxAmountStart = fraction(userAmountNew, coeffX8, MULT8)
321- let gWxParamsResultList = asAnyList(invoke(mathContract, "calcGwxParamsREADONLY", [wxAmountStart, height, lockDurationNew], nil))
421+ let gWxAmountStart = fraction(userAmountNew, coeffX8, MULT8)
422+ let gWxParamsResultList = asAnyList(invoke(mathContract, "calcGwxParamsREADONLY", [gWxAmountStart, height, lockDurationNew], nil))
322423 let k = asInt(gWxParamsResultList[0])
323424 let b = asInt(gWxParamsResultList[1])
324425 let period = toString(asInt(gWxParamsResultList[2]))
325- ((LockParamsEntry(userAddressStr, userNumStr, userAmountNew, lockStart, lockDurationNew, k, b, period) ++ StatsEntry(pmtAmount, deltaDuration, 0, 0)) :+ HistoryEntry("lock", userAddressStr, pmtAmount, lockStart, lockDurationNew, k, b, i))
426+ let wxEmissionPerBlock = getIntOrFail(emissionContract, keyEmissionRatePerBlockCurrent())
427+ let emissionStart = getIntOrFail(emissionContract, keyEmissionStartBlock())
428+ let emissionEnd = getIntOrFail(emissionContract, keyEmissionEndBlock())
429+ let h = if ((height > emissionEnd))
430+ then emissionEnd
431+ else height
432+ let dh = max([(h - emissionStart), 0])
433+ let userBoostEmissionLastIntegralKEY = keyUserBoostEmissionLastINTEGRAL(userNumStr)
434+ let userBoostEmissionLastIntegral = getIntOrZero(this, userBoostEmissionLastIntegralKEY)
435+ let boostEmissionIntegral = (((wxEmissionPerBlock * dh) * 2) / 3)
436+ let userBoostEmissionIntegral = (boostEmissionIntegral - userBoostEmissionLastIntegral)
437+ if ((0 >= userBoostEmissionIntegral))
438+ then throw("wrong calculations")
439+ else {
440+ let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
441+ let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
442+ let userBoostAvalaibleToClaimTotalKEY = keyUserBoostAvalaibleToClaimTotal(userNumStr)
443+ let userMaxBoostInt = getIntOrZero(this, userMaxBoostIntegralKEY)
444+ let totalMaxBoostInt = getIntOrZero(this, totalMaxBoostIntegralKEY)
445+ let userBoostAvaliableToClaimTotal = getIntOrZero(this, userBoostAvalaibleToClaimTotalKEY)
446+ let userBoostAvaliableToClaimTotalNew = (userBoostAvaliableToClaimTotal + fraction(userBoostEmissionIntegral, userMaxBoostInt, totalMaxBoostInt))
447+ let userMaxBoostIntNew = ((gWxAmountStart * lockDurationNew) / 2)
448+ let currUserGwx = calcCurrentGwxAmount(userAddressStr)
449+ let remainingUserMaxBoostInt = ((currUserGwx * remainingDuration) / 2)
450+ let userMaxBoostIntDiff = (userMaxBoostIntNew - remainingUserMaxBoostInt)
451+ if ((0 >= userMaxBoostIntDiff))
452+ then throw("wrong calculations")
453+ else (((LockParamsEntry(userAddressStr, userNumStr, userAmountNew, lockStart, lockDurationNew, k, b, period) ++ StatsEntry(pmtAmount, deltaDuration, 0, 0)) :+ HistoryEntry("lock", userAddressStr, pmtAmount, lockStart, lockDurationNew, k, b, i)) ++ [IntegerEntry(userMaxBoostIntegralKEY, userMaxBoostIntDiff), IntegerEntry(totalMaxBoostIntegralKEY, (totalMaxBoostInt + userMaxBoostIntDiff)), IntegerEntry(userBoostAvalaibleToClaimTotalKEY, userBoostAvaliableToClaimTotalNew), IntegerEntry(userBoostEmissionLastIntegralKEY, boostEmissionIntegral)])
454+ }
326455 }
456+ }
457+
458+
459+
460+@Callable(i)
461+func claimWxBoost (userAddressStr) = {
462+ let $t02168021792 = internalClaimWxBoost(userAddressStr)
463+ let userBoostAvailable = $t02168021792._1
464+ let dataState = $t02168021792._2
465+ nil
466+ }
467+
468+
469+
470+@Callable(i)
471+func claimWxBoostREADONLY (userAddressStr) = {
472+ let $t02187021944 = internalClaimWxBoost(userAddressStr)
473+ let userBoostAvailable = $t02187021944._1
474+ let dataState = $t02187021944._2
475+ $Tuple2(nil, [userBoostAvailable])
327476 }
328477
329478
352501
353502 @Callable(i)
354503 func gwxUserInfoREADONLY (userAddress) = {
355- let EMPTY = "empty"
356- let user2NumMappingKEY = keyUser2NumMapping(userAddress)
357- let userNum = valueOrElse(getString(user2NumMappingKEY), EMPTY)
358- let k = valueOrElse(getInteger(keyLockParamK(userNum)), 0)
359- let b = valueOrElse(getInteger(keyLockParamB(userNum)), 0)
360- let gwxAmountCalc = calcGwxAmount(k, b, height)
361- let gwxAmount = if ((0 > gwxAmountCalc))
362- then 0
363- else gwxAmountCalc
504+ let gwxAmount = calcCurrentGwxAmount(userAddress)
364505 $Tuple2(nil, [gwxAmount])
365506 }
366507
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 func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), (("mandatory this." + key) + " is not defined"))
1111
1212
13-func getIntOrZero (key) = valueOrElse(getInteger(this, key), 0)
13+func getIntOrZero (address,key) = valueOrElse(getInteger(address, key), 0)
1414
1515
16-func getIntOrFail (key) = valueOrErrorMessage(getInteger(key), (("mandatory this." + key) + " is not defined"))
16+func getIntOrDefault (address,key,defaultVal) = valueOrElse(getInteger(address, key), defaultVal)
17+
18+
19+func getIntOrFail (address,key) = valueOrErrorMessage(getInteger(address, key), (("mandatory this." + key) + " is not defined"))
1720
1821
1922 func asAnyList (val) = match val {
2023 case valAnyLyst: List[Any] =>
2124 valAnyLyst
2225 case _ =>
2326 throw("fail to cast into List[Any]")
2427 }
2528
2629
2730 func asInt (val) = match val {
2831 case valInt: Int =>
2932 valInt
3033 case _ =>
3134 throw("fail to cast into Int")
3235 }
3336
3437
3538 func keyFactoryAddress () = "%s%s__config__factoryAddress"
3639
3740
3841 let IdxFactoryCfgStakingDapp = 1
3942
4043 let IdxFactoryCfgBoostingDapp = 2
4144
4245 let IdxFactoryCfgIdoDapp = 3
4346
4447 let IdxFactoryCfgTeamDapp = 4
4548
4649 let IdxFactoryCfgEmissionDapp = 5
4750
4851 let IdxFactoryCfgRestDapp = 6
4952
5053 let IdxFactoryCfgSlippageDapp = 7
5154
5255 func keyFactoryCfg () = "%s__factoryConfig"
5356
5457
5558 func keyFactoryLp2AssetsMapping (lpAssetStr) = makeString(["%s%s%s", lpAssetStr, "mappings__lpAsset2PoolContract"], SEP)
5659
5760
5861 func keyFactoryLpList () = "%s__lpTokensList"
5962
6063
6164 func keyFactoryLpAssetToPoolContractAddress (lpAssetStr) = makeString(["%s%s%s", lpAssetStr, "mappings__lpAsset2PoolContract"], SEP)
6265
6366
6467 func keyFactoryPoolWeight (contractAddress) = makeString(["%s%s", "poolWeight", contractAddress], SEP)
6568
6669
6770 func readFactoryAddressOrFail () = addressFromStringValue(getStringOrFail(this, keyFactoryAddress()))
6871
6972
7073 func readLpList () = split(valueOrElse(getString(readFactoryAddressOrFail(), keyFactoryLpList()), ""), SEP)
7174
7275
7376 func readFactoryCfgOrFail (factory) = split(getStringOrFail(factory, keyFactoryCfg()), SEP)
7477
7578
7679 func getBoostingAddressOrFail (factoryCfg) = addressFromStringValue(factoryCfg[IdxFactoryCfgBoostingDapp])
7780
7881
7982 func getEmissionAddressOrFail (factoryCfg) = addressFromStringValue(factoryCfg[IdxFactoryCfgEmissionDapp])
8083
8184
8285 func getStakingAddressOrFail (factoryCfg) = addressFromStringValue(factoryCfg[IdxFactoryCfgStakingDapp])
86+
87+
88+func keyEmissionRatePerBlockCurrent () = "%s%s__ratePerBlock__current"
89+
90+
91+func keyEmissionRatePerBlockMaxCurrent () = "%s%s__ratePerBlockMax__current"
92+
93+
94+func keyEmissionStartBlock () = "%s%s__emission__startBlock"
95+
96+
97+func keyEmissionDurationInBlocks () = "%s%s__emission__duration"
98+
99+
100+func keyEmissionEndBlock () = "%s%s__emission__endBlock"
83101
84102
85103 let IdxCfgAssetId = 1
86104
87105 let IdxCfgMinLockAmount = 2
88106
89107 let IdxCfgMinLockDuration = 3
90108
91109 let IdxCfgMaxLockDuration = 4
92110
93111 let IdxCfgMathContract = 5
94112
95113 func keyConfig () = "%s__config"
96114
97115
98116 func readConfigArrayOrFail () = split(getStringOrFail(this, keyConfig()), SEP)
99117
100118
101119 func formatConfigS (assetId,minLockAmount,minLockDuration,maxLockDuration,mathContract) = makeString(["%s%d%d%d", assetId, minLockAmount, minLockDuration, maxLockDuration, mathContract], SEP)
102120
103121
104122 func formatConfig (assetId,minLockAmount,minLockDuration,maxLockDuration,mathContract) = formatConfigS(assetId, toString(minLockAmount), toString(minLockDuration), toString(maxLockDuration), mathContract)
105123
106124
107125 let IdxLockUserNum = 1
108126
109127 let IdxLockAmount = 2
110128
111129 let IdxLockStart = 3
112130
113131 let IdxLockDuration = 4
114132
115133 let IdxLockParamK = 5
116134
117135 let IdxLockParamB = 6
118136
119137 func keyLockParamsRecord (userAddress) = makeString(["%s%s__lock", userAddress], SEP)
120138
121139
122140 func readLockParamsRecordOrFail (userAddress) = split(getStringOrFail(this, keyLockParamsRecord(userAddress)), SEP)
123141
124142
125143 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)
126144
127145
128146 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))
129147
130148
131149 func keyNextUserNum () = "%s__nextUserNum"
132150
133151
134152 func keyUser2NumMapping (userAddress) = makeString(["%s%s%s__mapping__user2num", userAddress], SEP)
135153
136154
137155 func keyNum2UserMapping (num) = makeString(["%s%s%s__mapping__num2user", num], SEP)
138156
139157
140158 func keyLockParamUserAmount (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "amount"], SEP)
141159
142160
143161 func keyLockParamStartBlock (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "start"], SEP)
144162
145163
146164 func keyLockParamDuration (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "duration"], SEP)
147165
148166
149167 func keyLockParamK (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "k"], SEP)
150168
151169
152170 func keyLockParamB (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "b"], SEP)
153171
154172
155173 func keyLockParamByPeriodK (userNum,period) = makeString(["%s%d%s%d__paramByPeriod", userNum, "k", period], SEP)
156174
157175
158176 func keyLockParamByPeriodB (userNum,period) = makeString(["%s%d%s%d__paramByPeriod", userNum, "b", period], SEP)
159177
160178
161179 func keyLockParamTotalAmount () = "%s%s__stats__activeTotalLocked"
162180
163181
164182 func keyStatsLocksDurationSumInBlocks () = "%s%s__stats__locksDurationSumInBlocks"
165183
166184
167185 func keyStatsLocksCount () = "%s%s__stats__locksCount"
168186
169187
170188 func keyStatsUsersCount () = "%s%s__stats__activeUsersCount"
171189
172190
191+func keyUserBoostEmissionLastINTEGRAL (userNum) = makeString(["%s%d__userBoostEmissionLastInt", userNum], SEP)
192+
193+
194+func keyUserMaxBoostINTEGRAL (userNum) = makeString(["%s%d__maxBoostInt", userNum], SEP)
195+
196+
197+func keyTotalMaxBoostINTEGRAL () = "%s%s__maxBoostInt__total"
198+
199+
200+func keyUserBoostAvalaibleToClaimTotal (userNum) = makeString(["%s%d__userBoostAvaliableToClaimTotal", userNum], SEP)
201+
202+
203+func keyUserBoostClaimed (userNum) = makeString(["%s%d__userBoostClaimed", userNum], SEP)
204+
205+
206+let factoryContract = readFactoryAddressOrFail()
207+
208+let factoryCfg = readFactoryCfgOrFail(factoryContract)
209+
210+let emissionContract = getEmissionAddressOrFail(factoryCfg)
211+
212+let stakingContract = getStakingAddressOrFail(factoryCfg)
213+
173214 func HistoryEntry (type,user,amount,lockStart,duration,k,b,i) = {
174215 let historyKEY = makeString(["%s%s%s%s__history", type, user, toBase58String(i.transactionId)], SEP)
175216 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)
176217 StringEntry(historyKEY, historyDATA)
177218 }
178219
179220
180221 func StatsEntry (totalLockedInc,durationInc,lockCountInc,usersCountInc) = {
181222 let locksDurationSumInBlocksKEY = keyStatsLocksDurationSumInBlocks()
182223 let locksCountKEY = keyStatsLocksCount()
183224 let usersCountKEY = keyStatsUsersCount()
184225 let totalAmountKEY = keyLockParamTotalAmount()
185- let locksDurationSumInBlocks = getIntOrZero(locksDurationSumInBlocksKEY)
186- let locksCount = getIntOrZero(locksCountKEY)
187- let usersCount = getIntOrZero(usersCountKEY)
188- let totalAmount = getIntOrZero(totalAmountKEY)
226+ let locksDurationSumInBlocks = getIntOrZero(this, locksDurationSumInBlocksKEY)
227+ let locksCount = getIntOrZero(this, locksCountKEY)
228+ let usersCount = getIntOrZero(this, usersCountKEY)
229+ let totalAmount = getIntOrZero(this, totalAmountKEY)
189230 [IntegerEntry(locksDurationSumInBlocksKEY, (locksDurationSumInBlocks + durationInc)), IntegerEntry(locksCountKEY, (locksCount + lockCountInc)), IntegerEntry(usersCountKEY, (usersCount + usersCountInc)), IntegerEntry(totalAmountKEY, (totalAmount + totalLockedInc))]
190231 }
191232
192233
193234 func calcGwxAmount (kRaw,bRaw,h) = {
194235 let SCALE = 1000
195236 (((kRaw * h) + bRaw) / SCALE)
196237 }
197238
198239
199240 func LockParamsEntry (userAddress,userNum,amount,start,duration,k,b,period) = {
200241 let userAmountKEY = keyLockParamUserAmount(userNum)
201242 let startBlockKEY = keyLockParamStartBlock(userNum)
202243 let durationKEY = keyLockParamDuration(userNum)
203244 let kKEY = keyLockParamK(userNum)
204245 let bKEY = keyLockParamB(userNum)
205246 let kByPerioKEY = keyLockParamByPeriodK(userNum, period)
206247 let bByPeriodKEY = keyLockParamByPeriodB(userNum, period)
207248 let gwxAmount = calcGwxAmount(k, b, height)
208249 [IntegerEntry(userAmountKEY, amount), IntegerEntry(startBlockKEY, start), IntegerEntry(durationKEY, duration), IntegerEntry(kKEY, k), IntegerEntry(bKEY, b), IntegerEntry(kByPerioKEY, k), IntegerEntry(bByPeriodKEY, b), StringEntry(keyLockParamsRecord(userAddress), formatLockParamsRecord(userNum, amount, start, duration, k, b, gwxAmount))]
209250 }
210251
211252
212253 func extractOptionalPaymentAmountOrFail (i,expectedAssetId) = if ((size(i.payments) > 1))
213254 then throw("only one payment is allowed")
214255 else if ((size(i.payments) == 0))
215256 then 0
216257 else {
217258 let pmt = i.payments[0]
218259 if ((value(pmt.assetId) != expectedAssetId))
219260 then throw("invalid asset id in payment")
220261 else pmt.amount
221262 }
222263
223264
265+func calcCurrentGwxAmount (userAddress) = {
266+ let EMPTY = "empty"
267+ let user2NumMappingKEY = keyUser2NumMapping(userAddress)
268+ let userNum = valueOrElse(getString(user2NumMappingKEY), EMPTY)
269+ let k = valueOrElse(getInteger(keyLockParamK(userNum)), 0)
270+ let b = valueOrElse(getInteger(keyLockParamB(userNum)), 0)
271+ let gwxAmountCalc = calcGwxAmount(k, b, height)
272+ let gwxAmount = if ((0 > gwxAmountCalc))
273+ then 0
274+ else gwxAmountCalc
275+ gwxAmount
276+ }
277+
278+
279+func internalClaimWxBoost (userAddressStr) = {
280+ let userRecordArray = readLockParamsRecordOrFail(userAddressStr)
281+ let userNumStr = userRecordArray[IdxLockUserNum]
282+ let wxEmissionPerBlock = getIntOrFail(emissionContract, keyEmissionRatePerBlockCurrent())
283+ let emissionStart = getIntOrFail(emissionContract, keyEmissionStartBlock())
284+ let emissionEnd = getIntOrFail(emissionContract, keyEmissionEndBlock())
285+ let h = if ((height > emissionEnd))
286+ then emissionEnd
287+ else height
288+ let dh = max([(h - emissionStart), 0])
289+ let userBoostEmissionLastIntegralKEY = keyUserBoostEmissionLastINTEGRAL(userNumStr)
290+ let userBoostEmissionLastIntegral = getIntOrZero(this, userBoostEmissionLastIntegralKEY)
291+ let boostEmissionIntegral = (((wxEmissionPerBlock * dh) * 2) / 3)
292+ let userBoostEmissionIntegral = (boostEmissionIntegral - userBoostEmissionLastIntegral)
293+ if ((0 >= userBoostEmissionIntegral))
294+ then throw("wrong calculations")
295+ else {
296+ let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
297+ let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
298+ let userBoostAvalaibleToClaimTotalKEY = keyUserBoostAvalaibleToClaimTotal(userNumStr)
299+ let userMaxBoostInt = getIntOrZero(this, userMaxBoostIntegralKEY)
300+ let totalMaxBoostInt = getIntOrZero(this, totalMaxBoostIntegralKEY)
301+ let userBoostAvaliableToClaimTotal = getIntOrZero(this, userBoostAvalaibleToClaimTotalKEY)
302+ let userBoostAvaliableToClaimTotalNew = (userBoostAvaliableToClaimTotal + fraction(userBoostEmissionIntegral, userMaxBoostInt, totalMaxBoostInt))
303+ let userBoostClaimedKEY = keyUserBoostClaimed(userNumStr)
304+ let userBoostClaimed = getIntOrZero(this, userBoostClaimedKEY)
305+ let userBoostAvailable = (userBoostAvaliableToClaimTotalNew - userBoostClaimed)
306+ let dataState = [IntegerEntry(userBoostAvalaibleToClaimTotalKEY, userBoostAvaliableToClaimTotalNew), IntegerEntry(userBoostEmissionLastIntegralKEY, boostEmissionIntegral)]
307+ $Tuple2(userBoostAvailable, dataState)
308+ }
309+ }
310+
311+
224312 @Callable(i)
225313 func constructor (factoryAddressStr,lockAssetIdStr,minLockAmount,minDuration,maxDuration,mathContract) = if ((this != i.caller))
226314 then throw("not authorized")
227315 else ([IntegerEntry(keyNextUserNum(), 0), StringEntry(keyConfig(), formatConfig(lockAssetIdStr, minLockAmount, minDuration, maxDuration, mathContract)), StringEntry(keyFactoryAddress(), factoryAddressStr)] ++ StatsEntry(0, 0, 0, 0))
228316
229317
230318
231319 @Callable(i)
232320 func lock (duration) = {
233321 let cfgArray = readConfigArrayOrFail()
234322 let assetIdStr = cfgArray[IdxCfgAssetId]
235323 let assetId = fromBase58String(assetIdStr)
236324 let minLockAmount = parseIntValue(cfgArray[IdxCfgMinLockAmount])
237325 let minLockDuration = parseIntValue(cfgArray[IdxCfgMinLockDuration])
238326 let maxLockDuration = parseIntValue(cfgArray[IdxCfgMaxLockDuration])
239327 let mathContract = addressFromStringValue(cfgArray[IdxCfgMathContract])
240328 if ((size(i.payments) != 1))
241329 then throw("invalid payment - exact one payment must be attached")
242330 else {
243331 let pmt = i.payments[0]
244332 let pmtAmount = pmt.amount
245333 if ((assetId != value(pmt.assetId)))
246334 then throw((("invalid asset is in payment - " + assetIdStr) + " is expected"))
247335 else {
248336 let nextUserNumKEY = keyNextUserNum()
249337 let userAddressStr = toString(i.caller)
250338 let userIsExisting = isDefined(getString(keyUser2NumMapping(userAddressStr)))
251339 let userNumStr = if (userIsExisting)
252340 then value(getString(keyUser2NumMapping(userAddressStr)))
253- else toString(getIntOrFail(nextUserNumKEY))
341+ else toString(getIntOrFail(this, nextUserNumKEY))
254342 let userNum = parseIntValue(userNumStr)
255343 let lockStart = height
256344 let startBlockKEY = keyLockParamStartBlock(userNumStr)
257345 let durationKEY = keyLockParamDuration(userNumStr)
258346 let userAmountKEY = keyLockParamUserAmount(userNumStr)
259347 if ((minLockAmount > pmtAmount))
260348 then throw(("amount is less then minLockAmount=" + toString(minLockAmount)))
261349 else if ((minLockDuration > duration))
262350 then throw(("passed duration is less then minLockDuration=" + toString(minLockDuration)))
263351 else if ((duration > maxLockDuration))
264352 then throw(("passed duration is greater then maxLockDuration=" + toString(maxLockDuration)))
265353 else if (if (userIsExisting)
266- then ((getIntOrFail(startBlockKEY) + getIntOrFail(durationKEY)) >= lockStart)
354+ then ((getIntOrFail(this, startBlockKEY) + getIntOrFail(this, durationKEY)) >= lockStart)
267355 else false)
268356 then throw("there is an active lock - consider to use increaseLock")
269357 else {
270358 let coeffX8 = fraction(duration, MULT8, maxLockDuration)
271- let wxAmountStart = fraction(pmtAmount, coeffX8, MULT8)
272- let gWxParamsResultList = asAnyList(invoke(mathContract, "calcGwxParamsREADONLY", [wxAmountStart, lockStart, duration], nil))
359+ let gWxAmountStart = fraction(pmtAmount, coeffX8, MULT8)
360+ let gWxParamsResultList = asAnyList(invoke(mathContract, "calcGwxParamsREADONLY", [gWxAmountStart, lockStart, duration], nil))
273361 let k = asInt(gWxParamsResultList[0])
274362 let b = asInt(gWxParamsResultList[1])
275363 let period = toString(asInt(gWxParamsResultList[2]))
364+ let wxEmissionPerBlock = getIntOrFail(emissionContract, keyEmissionRatePerBlockCurrent())
365+ let emissionStart = getIntOrFail(emissionContract, keyEmissionStartBlock())
366+ let emissionEnd = getIntOrFail(emissionContract, keyEmissionEndBlock())
367+ let h = if ((height > emissionEnd))
368+ then emissionEnd
369+ else height
370+ let dh = max([(h - emissionStart), 0])
371+ let userBoostEmissionLastIntegralKEY = keyUserBoostEmissionLastINTEGRAL(userNumStr)
372+ let boostEmissionIntegral = (((wxEmissionPerBlock * dh) * 2) / 3)
373+ let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
374+ let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
375+ let userMaxBoostInt = ((gWxAmountStart * duration) / 2)
376+ let totalMaxBoostInt = getIntOrZero(this, totalMaxBoostIntegralKEY)
276377 let arr = if (userIsExisting)
277378 then nil
278379 else [IntegerEntry(nextUserNumKEY, (userNum + 1)), StringEntry(keyUser2NumMapping(userAddressStr), userNumStr), StringEntry(keyNum2UserMapping(userNumStr), userAddressStr)]
279- (((arr ++ LockParamsEntry(userAddressStr, userNumStr, pmtAmount, lockStart, duration, k, b, period)) ++ StatsEntry(pmtAmount, duration, 1, if (userIsExisting)
380+ ((((arr ++ LockParamsEntry(userAddressStr, userNumStr, pmtAmount, lockStart, duration, k, b, period)) ++ StatsEntry(pmtAmount, duration, 1, if (userIsExisting)
280381 then 0
281- else 1)) :+ HistoryEntry("lock", userAddressStr, pmtAmount, lockStart, duration, k, b, i))
382+ else 1)) :+ HistoryEntry("lock", userAddressStr, pmtAmount, lockStart, duration, k, b, i)) ++ [IntegerEntry(userBoostEmissionLastIntegralKEY, boostEmissionIntegral), IntegerEntry(userMaxBoostIntegralKEY, userMaxBoostInt), IntegerEntry(totalMaxBoostIntegralKEY, (totalMaxBoostInt + userMaxBoostInt))])
282383 }
283384 }
284385 }
285386 }
286387
287388
288389
289390 @Callable(i)
290391 func increaseLock (deltaDuration) = {
291392 let cfgArray = readConfigArrayOrFail()
292393 let assetIdStr = cfgArray[IdxCfgAssetId]
293394 let assetId = fromBase58String(assetIdStr)
294395 let minLockDuration = parseIntValue(cfgArray[IdxCfgMinLockDuration])
295396 let maxLockDuration = parseIntValue(cfgArray[IdxCfgMaxLockDuration])
296397 let mathContract = addressFromStringValue(cfgArray[IdxCfgMathContract])
297398 let pmtAmount = extractOptionalPaymentAmountOrFail(i, assetId)
298399 let userAddressStr = toString(i.caller)
299400 let userRecordArray = readLockParamsRecordOrFail(userAddressStr)
300401 let userNumStr = userRecordArray[IdxLockUserNum]
301402 let userAmount = parseIntValue(userRecordArray[IdxLockAmount])
302403 let lockStart = parseIntValue(userRecordArray[IdxLockStart])
303404 let lockDuration = parseIntValue(userRecordArray[IdxLockDuration])
304405 let lockEnd = (lockStart + lockDuration)
305406 let remainingDuration = max([(lockEnd - height), 0])
306407 let userAmountNew = (userAmount + pmtAmount)
307408 let lockDurationNew = (remainingDuration + deltaDuration)
308409 if ((0 > deltaDuration))
309410 then throw("duration is less then zero")
310411 else if ((minLockDuration > lockDurationNew))
311412 then throw(("lockDurationNew is less then minLockDuration=" + toString(minLockDuration)))
312413 else if ((lockDurationNew > maxLockDuration))
313414 then throw(("deltaDuration + existedLockDuration is greater then maxLockDuration=" + toString(maxLockDuration)))
314415 else if (if ((height >= lockEnd))
315416 then (userAmount > 0)
316417 else false)
317418 then throw("there is an expired lock - need to unlock before new lock")
318419 else {
319420 let coeffX8 = fraction(lockDurationNew, MULT8, maxLockDuration)
320- let wxAmountStart = fraction(userAmountNew, coeffX8, MULT8)
321- let gWxParamsResultList = asAnyList(invoke(mathContract, "calcGwxParamsREADONLY", [wxAmountStart, height, lockDurationNew], nil))
421+ let gWxAmountStart = fraction(userAmountNew, coeffX8, MULT8)
422+ let gWxParamsResultList = asAnyList(invoke(mathContract, "calcGwxParamsREADONLY", [gWxAmountStart, height, lockDurationNew], nil))
322423 let k = asInt(gWxParamsResultList[0])
323424 let b = asInt(gWxParamsResultList[1])
324425 let period = toString(asInt(gWxParamsResultList[2]))
325- ((LockParamsEntry(userAddressStr, userNumStr, userAmountNew, lockStart, lockDurationNew, k, b, period) ++ StatsEntry(pmtAmount, deltaDuration, 0, 0)) :+ HistoryEntry("lock", userAddressStr, pmtAmount, lockStart, lockDurationNew, k, b, i))
426+ let wxEmissionPerBlock = getIntOrFail(emissionContract, keyEmissionRatePerBlockCurrent())
427+ let emissionStart = getIntOrFail(emissionContract, keyEmissionStartBlock())
428+ let emissionEnd = getIntOrFail(emissionContract, keyEmissionEndBlock())
429+ let h = if ((height > emissionEnd))
430+ then emissionEnd
431+ else height
432+ let dh = max([(h - emissionStart), 0])
433+ let userBoostEmissionLastIntegralKEY = keyUserBoostEmissionLastINTEGRAL(userNumStr)
434+ let userBoostEmissionLastIntegral = getIntOrZero(this, userBoostEmissionLastIntegralKEY)
435+ let boostEmissionIntegral = (((wxEmissionPerBlock * dh) * 2) / 3)
436+ let userBoostEmissionIntegral = (boostEmissionIntegral - userBoostEmissionLastIntegral)
437+ if ((0 >= userBoostEmissionIntegral))
438+ then throw("wrong calculations")
439+ else {
440+ let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
441+ let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
442+ let userBoostAvalaibleToClaimTotalKEY = keyUserBoostAvalaibleToClaimTotal(userNumStr)
443+ let userMaxBoostInt = getIntOrZero(this, userMaxBoostIntegralKEY)
444+ let totalMaxBoostInt = getIntOrZero(this, totalMaxBoostIntegralKEY)
445+ let userBoostAvaliableToClaimTotal = getIntOrZero(this, userBoostAvalaibleToClaimTotalKEY)
446+ let userBoostAvaliableToClaimTotalNew = (userBoostAvaliableToClaimTotal + fraction(userBoostEmissionIntegral, userMaxBoostInt, totalMaxBoostInt))
447+ let userMaxBoostIntNew = ((gWxAmountStart * lockDurationNew) / 2)
448+ let currUserGwx = calcCurrentGwxAmount(userAddressStr)
449+ let remainingUserMaxBoostInt = ((currUserGwx * remainingDuration) / 2)
450+ let userMaxBoostIntDiff = (userMaxBoostIntNew - remainingUserMaxBoostInt)
451+ if ((0 >= userMaxBoostIntDiff))
452+ then throw("wrong calculations")
453+ else (((LockParamsEntry(userAddressStr, userNumStr, userAmountNew, lockStart, lockDurationNew, k, b, period) ++ StatsEntry(pmtAmount, deltaDuration, 0, 0)) :+ HistoryEntry("lock", userAddressStr, pmtAmount, lockStart, lockDurationNew, k, b, i)) ++ [IntegerEntry(userMaxBoostIntegralKEY, userMaxBoostIntDiff), IntegerEntry(totalMaxBoostIntegralKEY, (totalMaxBoostInt + userMaxBoostIntDiff)), IntegerEntry(userBoostAvalaibleToClaimTotalKEY, userBoostAvaliableToClaimTotalNew), IntegerEntry(userBoostEmissionLastIntegralKEY, boostEmissionIntegral)])
454+ }
326455 }
456+ }
457+
458+
459+
460+@Callable(i)
461+func claimWxBoost (userAddressStr) = {
462+ let $t02168021792 = internalClaimWxBoost(userAddressStr)
463+ let userBoostAvailable = $t02168021792._1
464+ let dataState = $t02168021792._2
465+ nil
466+ }
467+
468+
469+
470+@Callable(i)
471+func claimWxBoostREADONLY (userAddressStr) = {
472+ let $t02187021944 = internalClaimWxBoost(userAddressStr)
473+ let userBoostAvailable = $t02187021944._1
474+ let dataState = $t02187021944._2
475+ $Tuple2(nil, [userBoostAvailable])
327476 }
328477
329478
330479
331480 @Callable(i)
332481 func unlock (userAddress) = {
333482 let userRecordArray = readLockParamsRecordOrFail(userAddress)
334483 let userNumStr = userRecordArray[IdxLockUserNum]
335484 let userAmount = parseIntValue(userRecordArray[IdxLockAmount])
336485 let lockStart = parseIntValue(userRecordArray[IdxLockStart])
337486 let lockDuration = parseIntValue(userRecordArray[IdxLockDuration])
338487 let lockEnd = (lockStart + lockDuration)
339488 let cfgArray = readConfigArrayOrFail()
340489 let assetId = fromBase58String(cfgArray[IdxCfgAssetId])
341490 if ((lockEnd >= height))
342491 then throw((("wait " + toString(lockEnd)) + " to unlock"))
343492 else if ((0 >= userAmount))
344493 then throw("nothing to unlock")
345494 else {
346495 let period = "0"
347496 (((LockParamsEntry(userAddress, userNumStr, 0, lockStart, lockDuration, 0, 0, period) ++ StatsEntry(-(userAmount), 0, 0, -1)) :+ HistoryEntry("unlock", userAddress, userAmount, lockStart, lockDuration, 0, 0, i)) :+ ScriptTransfer(addressFromStringValue(userAddress), userAmount, assetId))
348497 }
349498 }
350499
351500
352501
353502 @Callable(i)
354503 func gwxUserInfoREADONLY (userAddress) = {
355- let EMPTY = "empty"
356- let user2NumMappingKEY = keyUser2NumMapping(userAddress)
357- let userNum = valueOrElse(getString(user2NumMappingKEY), EMPTY)
358- let k = valueOrElse(getInteger(keyLockParamK(userNum)), 0)
359- let b = valueOrElse(getInteger(keyLockParamB(userNum)), 0)
360- let gwxAmountCalc = calcGwxAmount(k, b, height)
361- let gwxAmount = if ((0 > gwxAmountCalc))
362- then 0
363- else gwxAmountCalc
504+ let gwxAmount = calcCurrentGwxAmount(userAddress)
364505 $Tuple2(nil, [gwxAmount])
365506 }
366507
367508

github/deemru/w8io/169f3d6 
72.20 ms