tx · BkHd8EfLoabZ6orf7VCraMbdRkLcFyLVSAgE35Me34UD

3Myn55vLkduxbX3ZXfiDCZhaQsLxYp1kmCy:  -0.02600000 Waves

2023.08.31 14:12 [2734786] smart account 3Myn55vLkduxbX3ZXfiDCZhaQsLxYp1kmCy > SELF 0.00000000 Waves

{ "type": 13, "id": "BkHd8EfLoabZ6orf7VCraMbdRkLcFyLVSAgE35Me34UD", "fee": 2600000, "feeAssetId": null, "timestamp": 1693480348129, "version": 2, "chainId": 84, "sender": "3Myn55vLkduxbX3ZXfiDCZhaQsLxYp1kmCy", "senderPublicKey": "9W33iCCNfmFxUbiC6XZcH5x7f6xfwC7Jb3BoExT5q2PV", "proofs": [ "2VzdpSc2nPbDeKicngT6sjA2LUZW8obegTCLeZAHkxjsZBBW71C3HENiMJk65KvmRty8mVY75ewVHwgDRn5nhtze" ], "script": "base64:BgK2LQgCEgUKAwEIAhIDCgEBEgQKAggIEgQKAggIEgMKAQgSAwoBCBIDCgEIEgQKAggBEgMKAQgSABIAEgUKAwgIBBIDCgEIEgMKAQgSBAoCCAgSBAoCCAgSAwoBBCIDU0VQIgZTQ0FMRTgiBU1VTFQ4Ig5QT09MV0VJR0hUTVVMVCIQY29udHJhY3RGaWxlbmFtZSIHU0NBTEUxOCIGTVVMVDE4IghNVUxUMThCSSIOREVDQVlfQ09OU1RBTlQiB3dyYXBFcnIiA21zZyIIdGhyb3dFcnIiD2dldFN0cmluZ09yRmFpbCIHYWRkcmVzcyIDa2V5IgxnZXRJbnRPclplcm8iD2dldEludE9yRGVmYXVsdCIKZGVmYXVsdFZhbCIMZ2V0SW50T3JGYWlsIgNhYnMiA3ZhbCIOZW5zdXJlUG9zaXRpdmUiAXYiAW0iG2tleVJlZmVycmFsc0NvbnRyYWN0QWRkcmVzcyIecmVmZXJyYWxzQ29udHJhY3RBZGRyZXNzT3JGYWlsIhZrZXlSZWZlcnJhbFByb2dyYW1OYW1lIhpyZWZlcnJhbFByb2dyYW1OYW1lRGVmYXVsdCITcmVmZXJyYWxQcm9ncmFtTmFtZSIRa2V5RmFjdG9yeUFkZHJlc3MiGElkeEZhY3RvcnlDZmdTdGFraW5nRGFwcCIZSWR4RmFjdG9yeUNmZ0Jvb3N0aW5nRGFwcCIUSWR4RmFjdG9yeUNmZ0lkb0RhcHAiFUlkeEZhY3RvcnlDZmdUZWFtRGFwcCIZSWR4RmFjdG9yeUNmZ0VtaXNzaW9uRGFwcCIVSWR4RmFjdG9yeUNmZ1Jlc3REYXBwIhlJZHhGYWN0b3J5Q2ZnU2xpcHBhZ2VEYXBwIhRJZHhGYWN0b3J5Q2ZnRGFvRGFwcCIaSWR4RmFjdG9yeUNmZ01hcmtldGluZ0RhcHAiGklkeEZhY3RvcnlDZmdHd3hSZXdhcmREYXBwIhZJZHhGYWN0b3J5Q2ZnQmlyZHNEYXBwIg1rZXlGYWN0b3J5Q2ZnIiZrZXlGYWN0b3J5THBBc3NldFRvUG9vbENvbnRyYWN0QWRkcmVzcyIKbHBBc3NldFN0ciIUa2V5RmFjdG9yeVBvb2xXZWlnaHQiD2NvbnRyYWN0QWRkcmVzcyIba2V5RmFjdG9yeVBvb2xXZWlnaHRIaXN0b3J5Igtwb29sQWRkcmVzcyIDbnVtIhhyZWFkRmFjdG9yeUFkZHJlc3NPckZhaWwiFHJlYWRGYWN0b3J5Q2ZnT3JGYWlsIgdmYWN0b3J5IhhnZXRCb29zdGluZ0FkZHJlc3NPckZhaWwiCmZhY3RvcnlDZmciGGdldEVtaXNzaW9uQWRkcmVzc09yRmFpbCIXZ2V0U3Rha2luZ0FkZHJlc3NPckZhaWwiGWdldEd3eFJld2FyZEFkZHJlc3NPckZhaWwiE2tleU1hbmFnZXJQdWJsaWNLZXkiFmtleU1hbmFnZXJWYXVsdEFkZHJlc3MiHmtleUVtaXNzaW9uUmF0ZVBlckJsb2NrQ3VycmVudCIha2V5RW1pc3Npb25SYXRlUGVyQmxvY2tNYXhDdXJyZW50IhVrZXlFbWlzc2lvblN0YXJ0QmxvY2siHWtleUJvb3N0aW5nVjJMYXN0VXBkYXRlSGVpZ2h0IhVrZXlCb29zdGluZ1YySW50ZWdyYWwiG2tleUVtaXNzaW9uRHVyYXRpb25JbkJsb2NrcyITa2V5RW1pc3Npb25FbmRCbG9jayINSWR4Q2ZnQXNzZXRJZCITSWR4Q2ZnTWluTG9ja0Ftb3VudCIVSWR4Q2ZnTWluTG9ja0R1cmF0aW9uIhVJZHhDZmdNYXhMb2NrRHVyYXRpb24iEklkeENmZ01hdGhDb250cmFjdCIUSWR4Q2ZnQmxvY2tzSW5QZXJpb2QiFElkeENmZ0xvY2tTdGVwQmxvY2tzIglrZXlDb25maWciFXJlYWRDb25maWdBcnJheU9yRmFpbCIIY2ZnQXJyYXkiB2Fzc2V0SWQiDW1pbkxvY2tBbW91bnQiD21pbkxvY2tEdXJhdGlvbiIPbWF4TG9ja0R1cmF0aW9uIgxtYXRoQ29udHJhY3QiDmJsb2Nrc0luUGVyaW9kIg5sb2NrU3RlcEJsb2NrcyINa2V5U3VzcGVuc2lvbiILaXNTdXNwZW5kZWQiEHRocm93SWZTdXNwZW5kZWQiHGdldE1hbmFnZXJWYXVsdEFkZHJlc3NPclRoaXMiByRtYXRjaDAiAXMiFm1hbmFnZXJQdWJsaWNLZXlPclVuaXQiE21hbmFnZXJWYXVsdEFkZHJlc3MiC211c3RNYW5hZ2VyIgFpIgJwZCICcGsiDUlkeExvY2tBbW91bnQiDElkeExvY2tTdGFydCIPSWR4TG9ja0R1cmF0aW9uIhpJZHhMb2NrTGFzdFVwZGF0ZVRpbWVzdGFtcCIQSWR4TG9ja0d3eEFtb3VudCIQSWR4TG9ja1d4Q2xhaW1lZCITa2V5TG9ja1BhcmFtc1JlY29yZCILdXNlckFkZHJlc3MiBHR4SWQiAWIiGnJlYWRMb2NrUGFyYW1zUmVjb3JkT3JGYWlsIhVrZXlVc2VyR3d4QW1vdW50VG90YWwiFmZvcm1hdExvY2tQYXJhbXNSZWNvcmQiBmFtb3VudCIFc3RhcnQiCGR1cmF0aW9uIglnd3hBbW91bnQiCXd4Q2xhaW1lZCIOa2V5TmV4dFVzZXJOdW0iEmtleVVzZXIyTnVtTWFwcGluZyISa2V5TnVtMlVzZXJNYXBwaW5nIhdrZXlMb2NrUGFyYW1Ub3RhbEFtb3VudCIga2V5U3RhdHNMb2Nrc0R1cmF0aW9uU3VtSW5CbG9ja3MiEmtleVN0YXRzTG9ja3NDb3VudCISa2V5U3RhdHNVc2Vyc0NvdW50IiBrZXlVc2VyQm9vc3RFbWlzc2lvbkxhc3RJTlRFR1JBTCIHdXNlck51bSIia2V5VXNlckxwQm9vc3RFbWlzc2lvbkxhc3RJTlRFR1JBTCIJbHBBc3NldElkIhdrZXlVc2VyTWF4Qm9vc3RJTlRFR1JBTCIYa2V5VG90YWxNYXhCb29zdElOVEVHUkFMIiFrZXlVc2VyQm9vc3RBdmFsYWlibGVUb0NsYWltVG90YWwiE2tleVVzZXJCb29zdENsYWltZWQiC2tleUd3eFRvdGFsIgdrZXlWb3RlIg1hbW91bnRBc3NldElkIgxwcmljZUFzc2V0SWQiBWVwb2NoIhVrZXlTdGFydEhlaWdodEJ5RXBvY2giEWtleUN1cnJlbnRFcG9jaFVpIhVrZXlWb3RpbmdSZXN1bHRTdGFrZWQiDGxwQXNzZXRJZFN0ciIda2V5Vm90aW5nUmVzdWx0U3Rha2VkSW50ZWdyYWwiJWtleVZvdGluZ1Jlc3VsdFN0YWtlZExhc3RVcGRhdGVIZWlnaHQiIWtleVZvdGluZ1Jlc3VsdFN0YWtlZEludGVncmFsTGFzdCIVa2V5Vm90ZVN0YWtlZEludGVncmFsIh1rZXlWb3RlU3Rha2VkTGFzdFVwZGF0ZUhlaWdodCIZa2V5Vm90ZVN0YWtlZEludGVncmFsTGFzdCIPa2V5U3Rha2VkQnlVc2VyIg51c2VyQWRkcmVzc1N0ciIPZmFjdG9yeUNvbnRyYWN0IhBlbWlzc2lvbkNvbnRyYWN0Ig9zdGFraW5nQ29udHJhY3QiEWd3eFJld2FyZENvbnRyYWN0IhZscFN0YWtpbmdQb29sc0NvbnRyYWN0IhlrZXlWb3RpbmdFbWlzc2lvbkNvbnRyYWN0IhZ2b3RpbmdFbWlzc2lvbkNvbnRyYWN0Ih1rZXlWb3RpbmdFbWlzc2lvblJhdGVDb250cmFjdCIKYm9vc3RDb2VmZiIBQCIZdXNlck51bWJlckJ5QWRkcmVzc09yRmFpbCIRZ2V0R3d4QW1vdW50VG90YWwiEmdldExvY2tlZEd3eEFtb3VudCIMZnVuY3Rpb25OYW1lIhp2b3RpbmdFbWlzc2lvblJhdGVDb250cmFjdCIYbG9ja2VkVm90aW5nRW1pc3Npb25SYXRlIhRsb2NrZWRWb3RpbmdFbWlzc2lvbiIGbG9ja2VkIgxIaXN0b3J5RW50cnkiBHR5cGUiBHVzZXIiCWxvY2tTdGFydCIKaGlzdG9yeUtFWSILaGlzdG9yeURBVEEiClN0YXRzRW50cnkiDnRvdGFsTG9ja2VkSW5jIgtkdXJhdGlvbkluYyIMbG9ja0NvdW50SW5jIg11c2Vyc0NvdW50SW5jIhtsb2Nrc0R1cmF0aW9uU3VtSW5CbG9ja3NLRVkiDWxvY2tzQ291bnRLRVkiDXVzZXJzQ291bnRLRVkiDnRvdGFsQW1vdW50S0VZIhhsb2Nrc0R1cmF0aW9uU3VtSW5CbG9ja3MiCmxvY2tzQ291bnQiCnVzZXJzQ291bnQiC3RvdGFsQW1vdW50Ig9Mb2NrUGFyYW1zRW50cnkiImV4dHJhY3RPcHRpb25hbFBheW1lbnRBbW91bnRPckZhaWwiD2V4cGVjdGVkQXNzZXRJZCIDcG10IhVnZXRVc2VyR3d4QW1vdW50VG90YWwiGmdldFZvdGluZ0VtaXNzaW9uRXBvY2hJbmZvIg0kdDAxNDY4NjE0OTc2Ig5jdXJyZW50RXBvY2hVaSISbGFzdEZpbmFsaXplZEVwb2NoIhdjdXJyZW50RXBvY2hTdGFydEhlaWdodCIYZ2V0UG9vbEFzc2V0c0J5THBBc3NldElkIhBpZHhBbW91bnRBc3NldElkIg9pZHhQcmljZUFzc2V0SWQiB3Bvb2xDZmciFGdldFVzZXJWb3RlRmluYWxpemVkIg0kdDAxNTY2NzE1NzQ3Ig0kdDAxNTc1MDE1ODI1Igt1c2VyVm90ZUtleSIIdXNlclZvdGUiEWdldFVzZXJWb3RlU3Rha2VkIgxzdGFrZWRCeVVzZXIiFWdldFZvdGluZ1Jlc3VsdFN0YWtlZCINJHQwMTYzNjkxNjQ0OSIXdm90aW5nUmVzdWx0U3Rha2VkU3RhcnQiEnZvdGluZ1Jlc3VsdFN0YWtlZCIdZ2V0Vm90aW5nUmVzdWx0U3Rha2VkSW50ZWdyYWwiDSR0MDE2ODExMTY4OTEiHnZvdGluZ1Jlc3VsdFN0YWtlZEludGVncmFsUHJldiIidm90aW5nUmVzdWx0U3Rha2VkTGFzdFVwZGF0ZUhlaWdodCIcdm90aW5nUmVzdWx0U3Rha2VkSW50ZWdyYWxEaCIadm90aW5nUmVzdWx0U3Rha2VkSW50ZWdyYWwiIXJlZnJlc2hWb3RpbmdSZXN1bHRTdGFrZWRJbnRlZ3JhbCIPc3Rha2VkVm90ZURlbHRhIg0kdDAxNzcyODE3ODA4IhV2b3RpbmdSZXN1bHRTdGFrZWROZXciGWdldFVzZXJWb3RlU3Rha2VkSW50ZWdyYWwiDSR0MDE4NDE5MTg0OTkiDnVzZXJWb3RlU3Rha2VkIhp1c2VyVm90ZVN0YWtlZEludGVncmFsUHJldiIedXNlclZvdGVTdGFrZWRMYXN0VXBkYXRlSGVpZ2h0Ihh1c2VyVm90ZVN0YWtlZEludGVncmFsRGgiFnVzZXJWb3RlU3Rha2VkSW50ZWdyYWwiGXJlZnJlc2hWb3RlU3Rha2VkSW50ZWdyYWwiBGVkZ2UiDSR0MDE5Mjg3MTkzNjciEXVzZXJWb3RlRmluYWxpemVkIgdhY3Rpb25zIhN2b3RpbmdSZXN1bHRBY3Rpb25zIgt2b3RlQWN0aW9ucyIbZ2V0U3Rha2VkVm90ZXNJbnRlZ3JhbHNEaWZmIg0kdDAyMDIyMTIwMzAxIh11c2VyVm90ZVN0YWtlZEludGVncmFsTGFzdEtleSIadXNlclZvdGVTdGFrZWRJbnRlZ3JhbExhc3QiIXZvdGluZ1Jlc3VsdFN0YWtlZEludGVncmFsTGFzdEtleSIedm90aW5nUmVzdWx0U3Rha2VkSW50ZWdyYWxMYXN0Ihp1c2VyVm90ZVN0YWtlZEludGVncmFsRGlmZiIedm90aW5nUmVzdWx0U3Rha2VkSW50ZWdyYWxEaWZmIhxyZWZyZXNoQm9vc3RFbWlzc2lvbkludGVncmFsIhJ3eEVtaXNzaW9uUGVyQmxvY2siIGJvb3N0aW5nVjJMYXN0VXBkYXRlSGVpZ2h0T3B0aW9uIhhib29zdGluZ1YySW5nZXJnYWxPcHRpb24iC2VtaXNzaW9uRW5kIgFoIgJkaCIQbGFzdFVwZGF0ZUhlaWdodCIVYm9vc3RFbWlzc2lvblBlckJsb2NrIhlib29zdEVtaXNzaW9uSW50ZWdyYWxQcmV2IhVib29zdEVtaXNzaW9uSW50ZWdyYWwiFGludGVybmFsQ2xhaW1XeEJvb3N0IghyZWFkT25seSIIRU1QVFlTVFIiCnBvb2xXZWlnaHQiDnBvb2xBZGRyZXNzU3RyIiJ1c2VyTHBCb29zdEVtaXNzaW9uTGFzdEludGVncmFsS0VZIiB1c2VyQm9vc3RFbWlzc2lvbkxhc3RJbnRlZ3JhbEtFWSIddXNlckJvb3N0RW1pc3Npb25MYXN0SW50ZWdyYWwiGXVzZXJCb29zdEVtaXNzaW9uSW50ZWdyYWwiDSR0MDIzODQzMjM5ODIiG3N0YWtlZFZvdGVzSW50ZWdyYWxzQWN0aW9ucyIUdXNlclZvdGVJbnRlZ3JhbERpZmYiFnRvdGFsVm90ZXNJbnRlZ3JhbERpZmYiHXBvb2xVc2VyQm9vc3RFbWlzc2lvbkludGVncmFsIiF1c2VyQm9vc3RBdmFsaWFibGVUb0NsYWltVG90YWxOZXciCWRhdGFTdGF0ZSIFZGVidWciC2xvY2tBY3Rpb25zIgphc3NldElkU3RyIglwbXRBbW91bnQiDm5leHRVc2VyTnVtS0VZIg51c2VySXNFeGlzdGluZyIKdXNlck51bVN0ciIOZ1d4QW1vdW50U3RhcnQiDmd3eEFtb3VudFRvdGFsIhJ1c2VyR3d4QW1vdW50VG90YWwiDGd3eFJld2FyZEludiIDYXJyIhFnZXRXeFdpdGhkcmF3YWJsZSIKdHhJZE9wdGlvbiIPdXNlclJlY29yZEFycmF5Igp1c2VyQW1vdW50Igxsb2NrRHVyYXRpb24iB2xvY2tFbmQiAXQiCGV4cG9uZW50IhN3eFdpdGhkcmF3YWJsZVRvdGFsIg53eFdpdGhkcmF3YWJsZSIPcmVmZXJyZXJBZGRyZXNzIglzaWduYXR1cmUiD3N1c3BlbnNpb25DaGVjayINJHQwMjg0MDAyODQ2NSIRbG9ja0FjdGlvbnNSZXN1bHQiD3JlZmVycmFsQWRkcmVzcyIGcmVmSW52IhF1cGRhdGVSZWZBY3Rpdml0eSINJHQwMjg5NjkyOTAzNCINJHQwMjkzOTAyOTQ5MiISdXNlckJvb3N0QXZhaWxhYmxlIg0kdDAyOTYyNDI5NzI1Igd0eElkU3RyIglnd3hCdXJuZWQiDGd3eFJlbWFpbmluZyIPbG9ja2VkR3d4QW1vdW50IhV1c2VyR3d4QW1vdW50VG90YWxOZXciDHRhcmdldEhlaWdodCILY2hlY2tDYWxsZXIiAnR4IgZ2ZXJpZnkiD3RhcmdldFB1YmxpY0tleY8BAAFhAgJfXwABYgAIAAFjAIDC1y8AAWQFAWMAAWUCDWJvb3N0aW5nLnJpZGUAAWYAEgABZwCAgJC7utat8A0AAWgJALYCAQUBZwABaQAIAQFqAQFrCQC5CQIJAMwIAgUBZQkAzAgCAgI6IAkAzAgCBQFrBQNuaWwCAAEBbAEBawkAAgEJAQFqAQUBawEBbQIBbgFvCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUBbgUBbwkBAWoBCQCsAgIJAKwCAgIPbWFuZGF0b3J5IHRoaXMuBQFvAg8gaXMgbm90IGRlZmluZWQBAXACAW4BbwkBC3ZhbHVlT3JFbHNlAgkAmggCBQFuBQFvAAABAXEDAW4BbwFyCQELdmFsdWVPckVsc2UCCQCaCAIFAW4FAW8FAXIBAXMCAW4BbwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFAW4FAW8JAQFqAQkArAICCQCsAgICD21hbmRhdG9yeSB0aGlzLgUBbwIPIGlzIG5vdCBkZWZpbmVkAQF0AQF1AwkAZgIAAAUBdQkBAS0BBQF1BQF1AQF2AgF3AXgDCQBnAgUBdwAABQF3CQEBbAEJAKwCAgkBC3ZhbHVlT3JFbHNlAgUBeAIFdmFsdWUCEyBzaG91bGQgYmUgcG9zaXRpdmUBAXkACQC5CQIJAMwIAgIEJXMlcwkAzAgCAgZjb25maWcJAMwIAgIYcmVmZXJyYWxzQ29udHJhY3RBZGRyZXNzBQNuaWwFAWEAAXoJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQFtAgUEdGhpcwkBAXkAAAFBCQC5CQIJAMwIAgIEJXMlcwkAzAgCAghyZWZlcnJhbAkAzAgCAgtwcm9ncmFtTmFtZQUDbmlsBQFhAAFCAgZ3eGxvY2sAAUMJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwUBQQUBQgEBRAACHCVzJXNfX2NvbmZpZ19fZmFjdG9yeUFkZHJlc3MAAUUAAQABRgACAAFHAAMAAUgABAABSQAFAAFKAAYAAUsABwABTAAIAAFNAAkAAU4ACgABTwALAQFQAAIRJXNfX2ZhY3RvcnlDb25maWcBAVEBAVIJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgUBUgkAzAgCAh5tYXBwaW5nc19fbHBBc3NldDJQb29sQ29udHJhY3QFA25pbAUBYQEBUwEBVAkAuQkCCQDMCAICBCVzJXMJAMwIAgIKcG9vbFdlaWdodAkAzAgCBQFUBQNuaWwFAWEBAVUCAVYBVwkArAICCQCsAgIJAKwCAgISJXMlc19fcG9vbFdlaWdodF9fBQFWAgJfXwkApAMBBQFXAQFYAAkBEUBleHRyTmF0aXZlKDEwNjIpAQkBAW0CBQR0aGlzCQEBRAABAVkBAVoJALUJAgkBAW0CBQFaCQEBUAAFAWEBAmFhAQJhYgkBEUBleHRyTmF0aXZlKDEwNjIpAQkAkQMCBQJhYgUBRgECYWMBAmFiCQERQGV4dHJOYXRpdmUoMTA2MikBCQCRAwIFAmFiBQFJAQJhZAECYWIJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAJEDAgUCYWIFAUUBAmFlAQJhYgkBEUBleHRyTmF0aXZlKDEwNjIpAQkAkQMCBQJhYgUBTgECYWYAAhQlc19fbWFuYWdlclB1YmxpY0tleQECYWcAAhclc19fbWFuYWdlclZhdWx0QWRkcmVzcwECYWgAAhslcyVzX19yYXRlUGVyQmxvY2tfX2N1cnJlbnQBAmFpAAIeJXMlc19fcmF0ZVBlckJsb2NrTWF4X19jdXJyZW50AQJhagACGiVzJXNfX2VtaXNzaW9uX19zdGFydEJsb2NrAQJhawACHCVzJXNfX2Jvb3N0aW5nVjJfX3N0YXJ0QmxvY2sBAmFsAAIaJXMlc19fYm9vc3RpbmdWMl9faW50ZWdyYWwBAmFtAAIYJXMlc19fZW1pc3Npb25fX2R1cmF0aW9uAQJhbgACGCVzJXNfX2VtaXNzaW9uX19lbmRCbG9jawACYW8AAQACYXAAAgACYXEAAwACYXIABAACYXMABQACYXQABgACYXUABwECYXYAAgolc19fY29uZmlnAQJhdwAJALUJAgkBAW0CBQR0aGlzCQECYXYABQFhAAJheAkBAmF3AAACYXkJANkEAQkAkQMCBQJheAUCYW8AAmF6CQETdmFsdWVPckVycm9yTWVzc2FnZQIJALYJAQkAkQMCBQJheAUCYXAJAQFqAQIXaW52YWxpZCBtaW4gbG9jayBhbW91bnQAAmFBCQETdmFsdWVPckVycm9yTWVzc2FnZQIJALYJAQkAkQMCBQJheAUCYXEJAQFqAQIZaW52YWxpZCBtaW4gbG9jayBkdXJhdGlvbgACYUIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAtgkBCQCRAwIFAmF4BQJhcgkBAWoBAhlpbnZhbGlkIG1heCBsb2NrIGR1cmF0aW9uAAJhQwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJAJEDAgUCYXgFAmFzCQEBagECHWludmFsaWQgbWF0aCBjb250cmFjdCBhZGRyZXNzAAJhRAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQC2CQEJAJEDAgUCYXgFAmF0CQEBagECGGludmFsaWQgYmxvY2tzIGluIHBlcmlvZAACYUUJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAtgkBCQCRAwIFAmF4BQJhdQkBAWoBAhhpbnZhbGlkIGxvY2sgc3RlcCBibG9ja3MAAmFGAg4lc19fc3VzcGVuc2lvbgACYUcJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhpcwUCYUYHAQJhSAADCQEBIQEFAmFHBgkBAWwBAglzdXNwZW5kZWQBAmFJAAQCYUoJAKIIAQkBAmFnAAMJAAECBQJhSgIGU3RyaW5nBAJhSwUCYUoJARFAZXh0ck5hdGl2ZSgxMDYyKQEFAmFLBQR0aGlzAQJhTAAEAmFNCQECYUkABAJhSgkAnQgCBQJhTQkBAmFmAAMJAAECBQJhSgIGU3RyaW5nBAJhSwUCYUoJANkEAQUCYUsDCQABAgUCYUoCBFVuaXQFBHVuaXQJAAIBAgtNYXRjaCBlcnJvcgECYU4BAmFPBAJhUAkBAWwBAhFQZXJtaXNzaW9uIGRlbmllZAQCYUoJAQJhTAADCQABAgUCYUoCCkJ5dGVWZWN0b3IEAmFRBQJhSgMJAAACCAUCYU8PY2FsbGVyUHVibGljS2V5BQJhUQYFAmFQAwkAAQIFAmFKAgRVbml0AwkAAAIIBQJhTwZjYWxsZXIFBHRoaXMGBQJhUAkAAgECC01hdGNoIGVycm9yAAJhUgABAAJhUwACAAJhVAADAAJhVQAEAAJhVgAFAAJhVwAGAQJhWAICYVkCYVoJALkJAgkAzAgCAgwlcyVzJXNfX2xvY2sJAMwIAgkApQgBBQJhWQkAzAgCBAJhSgUCYVoDCQABAgUCYUoCCkJ5dGVWZWN0b3IEAmJhBQJhSgkA2AQBBQJiYQMJAAECBQJhSgIEVW5pdAIGbGVnYWN5CQACAQILTWF0Y2ggZXJyb3IFA25pbAUBYQECYmICAmFZAmFaCQC1CQIJAQFtAgUEdGhpcwkBAmFYAgUCYVkFAmFaBQFhAQJiYwECYVkJALkJAgkAzAgCAhQlcyVzX19nd3hBbW91bnRUb3RhbAkAzAgCCQClCAEFAmFZBQNuaWwFAWEBAmJkBQJiZQJiZgJiZwJiaAJiaQkAuQkCCQDMCAICDCVkJWQlZCVkJWQlZAkAzAgCCQCkAwEFAmJlCQDMCAIJAKQDAQUCYmYJAMwIAgkApAMBBQJiZwkAzAgCCQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wCQDMCAIJAKQDAQUCYmgJAMwIAgkApAMBBQJiaQUDbmlsBQFhAQJiagACDyVzX19uZXh0VXNlck51bQECYmsBAmFZCQC5CQIJAMwIAgIZJXMlcyVzX19tYXBwaW5nX191c2VyMm51bQkAzAgCBQJhWQUDbmlsBQFhAQJibAEBVwkAuQkCCQDMCAICGSVzJXMlc19fbWFwcGluZ19fbnVtMnVzZXIJAMwIAgUBVwUDbmlsBQFhAQJibQACHiVzJXNfX3N0YXRzX19hY3RpdmVUb3RhbExvY2tlZAECYm4AAiUlcyVzX19zdGF0c19fbG9ja3NEdXJhdGlvblN1bUluQmxvY2tzAQJibwACFyVzJXNfX3N0YXRzX19sb2Nrc0NvdW50AQJicAACHSVzJXNfX3N0YXRzX19hY3RpdmVVc2Vyc0NvdW50AQJicQECYnIJALkJAgkAzAgCAiAlcyVkX191c2VyQm9vc3RFbWlzc2lvbkxhc3RJbnRWMgkAzAgCCQCkAwEFAmJyBQNuaWwFAWEBAmJzAgJicgJidAkAuQkCCQDMCAICICVzJWRfX3VzZXJCb29zdEVtaXNzaW9uTGFzdEludFYyCQDMCAIJAKQDAQUCYnIJAMwIAgUCYnQFA25pbAUBYQECYnUBAmJyCQC5CQIJAMwIAgIRJXMlZF9fbWF4Qm9vc3RJbnQJAMwIAgkApAMBBQJicgUDbmlsBQFhAQJidgACGCVzJXNfX21heEJvb3N0SW50X190b3RhbAECYncBAmJyCQC5CQIJAMwIAgIkJXMlZF9fdXNlckJvb3N0QXZhbGlhYmxlVG9DbGFpbVRvdGFsCQDMCAIJAKQDAQUCYnIFA25pbAUBYQECYngBAmJyCQC5CQIJAMwIAgIWJXMlZF9fdXNlckJvb3N0Q2xhaW1lZAkAzAgCCQCkAwEFAmJyBQNuaWwFAWEBAmJ5AAIQJXMlc19fZ3d4X190b3RhbAECYnoEAmJBAmJCAW4CYkMJALkJAgkAzAgCAgolcyVzJXMlcyVkCQDMCAICBHZvdGUJAMwIAgUCYkEJAMwIAgUCYkIJAMwIAgkApQgBBQFuCQDMCAIJAKQDAQUCYkMFA25pbAUBYQECYkQBAmJDCQC5CQIJAMwIAgIEJXMlZAkAzAgCAgtzdGFydEhlaWdodAkAzAgCCQCkAwEFAmJDBQNuaWwFAWEBAmJFAAkAuQkCCQDMCAICAiVzCQDMCAICDmN1cnJlbnRFcG9jaFVpBQNuaWwFAWEBAmJGAgJiRwJiQwkAuQkCCQDMCAICBiVzJXMlZAkAzAgCAhJ2b3RpbmdSZXN1bHRTdGFrZWQJAMwIAgUCYkcJAMwIAgkApAMBBQJiQwUDbmlsBQFhAQJiSAICYkcCYkMJALkJAgkAzAgCAgYlcyVzJWQJAMwIAgIadm90aW5nUmVzdWx0U3Rha2VkSW50ZWdyYWwJAMwIAgUCYkcJAMwIAgkApAMBBQJiQwUDbmlsBQFhAQJiSQICYkcCYkMJALkJAgkAzAgCAgYlcyVzJWQJAMwIAgIqdm90aW5nUmVzdWx0U3Rha2VkSW50ZWdyYWxMYXN0VXBkYXRlSGVpZ2h0CQDMCAIFAmJHCQDMCAIJAKQDAQUCYkMFA25pbAUBYQECYkoDAmJHAW4CYkMJALkJAgkAzAgCAgglcyVzJXMlZAkAzAgCAh52b3RpbmdSZXN1bHRTdGFrZWRJbnRlZ3JhbExhc3QJAMwIAgUCYkcJAMwIAgkApQgBBQFuCQDMCAIJAKQDAQUCYkMFA25pbAUBYQECYksDAmJHAW4CYkMJALkJAgkAzAgCAgglcyVzJXMlZAkAzAgCAhJ2b3RlU3Rha2VkSW50ZWdyYWwJAMwIAgUCYkcJAMwIAgkApQgBBQFuCQDMCAIJAKQDAQUCYkMFA25pbAUBYQECYkwDAmJHAW4CYkMJALkJAgkAzAgCAgglcyVzJXMlZAkAzAgCAiJ2b3RlU3Rha2VkSW50ZWdyYWxMYXN0VXBkYXRlSGVpZ2h0CQDMCAIFAmJHCQDMCAIJAKUIAQUBbgkAzAgCCQCkAwEFAmJDBQNuaWwFAWEBAmJNAwJiRwFuAmJDCQC5CQIJAMwIAgIIJXMlcyVzJWQJAMwIAgIWdm90ZVN0YWtlZEludGVncmFsTGFzdAkAzAgCBQJiRwkAzAgCCQClCAEFAW4JAMwIAgkApAMBBQJiQwUDbmlsBQFhAQJiTgICYk8CYkcJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgIGc3Rha2VkCQDMCAIFAmJPCQDMCAIFAmJHBQNuaWwFAWEAAmJQCQEBWAAAAmFiCQEBWQEFAmJQAAJiUQkBAmFjAQUCYWIAAmJSCQECYWQBBQJhYgACYlMJAQJhZQEFAmFiAAJiVAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQC5CQIJAMwIAgICJXMJAMwIAgIWbHBTdGFraW5nUG9vbHNDb250cmFjdAUDbmlsBQFhCQEBagECLmxwX3N0YWtpbmdfcG9vbHMgY29udHJhY3QgYWRkcmVzcyBpcyB1bmRlZmluZWQJAQFqAQIpaW52YWxpZCBscF9zdGFraW5nX3Bvb2xzIGNvbnRyYWN0IGFkZHJlc3MAAmJVCQC5CQIJAMwIAgICJXMJAMwIAgIWdm90aW5nRW1pc3Npb25Db250cmFjdAUDbmlsBQFhAAJiVgkBEUBleHRyTmF0aXZlKDEwNjIpAQkBEUBleHRyTmF0aXZlKDEwNTMpAgUCYlAFAmJVAAJiVwkAuQkCCQDMCAICAiVzCQDMCAICGnZvdGluZ0VtaXNzaW9uUmF0ZUNvbnRyYWN0BQNuaWwFAWEAAmJYCgACYlkJAPwHBAUCYlECFWdldEJvb3N0Q29lZmZSRUFET05MWQUDbmlsBQNuaWwDCQABAgUCYlkCA0ludAUCYlkJAAIBCQCsAgIJAAMBBQJiWQIYIGNvdWxkbid0IGJlIGNhc3QgdG8gSW50AQJiWgECYVkEAmFKCQCdCAIFBHRoaXMJAQJiawEJAKUIAQUCYVkDCQABAgUCYUoCBlN0cmluZwQCYUsFAmFKCQETdmFsdWVPckVycm9yTWVzc2FnZQIJALYJAQUCYUsJAQFqAQITaW52YWxpZCB1c2VyIG51bWJlcgMJAAECBQJhSgIEVW5pdAkBAWwBAgxpbnZhbGlkIHVzZXIJAAIBAgtNYXRjaCBlcnJvcgECY2EACQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQJieQAAAAECY2IBAmFZBAJjYwISZ2V0TG9ja2VkR3d4QW1vdW50BAJjZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCBAJhSgkAnQgCBQJiVgUCYlcDCQABAgUCYUoCBFVuaXQFBHVuaXQDCQABAgUCYUoCBlN0cmluZwQCYUsFAmFKCQCmCAEFAmFLCQACAQILTWF0Y2ggZXJyb3IJAQFqAQIkaW52YWxpZCB2b3RpbmcgZW1pc3Npb24gcmF0ZSBhZGRyZXNzBAJjZQoAAmJZCQD8BwQFAmJWBQJjYwkAzAgCCQClCAEFAmFZBQNuaWwFA25pbAMJAAECBQJiWQIDSW50BQJiWQkAAgEJAKwCAgkAAwEFAmJZAhggY291bGRuJ3QgYmUgY2FzdCB0byBJbnQEAmNmCgACYlkJAPwHBAUCY2QFAmNjCQDMCAIJAKUIAQUCYVkFA25pbAUDbmlsAwkAAQIFAmJZAgNJbnQFAmJZCQACAQkArAICCQADAQUCYlkCGCBjb3VsZG4ndCBiZSBjYXN0IHRvIEludAQCY2cJAJYDAQkAzAgCBQJjZQkAzAgCBQJjZgUDbmlsBQJjZwECY2gHAmNpAmNqAmJlAmNrAmJnAmJoAmFPBAJjbAkAuQkCCQDMCAICESVzJXMlcyVzX19oaXN0b3J5CQDMCAIFAmNpCQDMCAIFAmNqCQDMCAIJANgEAQgFAmFPDXRyYW5zYWN0aW9uSWQFA25pbAUBYQQCY20JALkJAgkAzAgCAg4lZCVkJWQlZCVkJWQlZAkAzAgCCQCkAwEIBQlsYXN0QmxvY2sGaGVpZ2h0CQDMCAIJAKQDAQgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAMwIAgkApAMBBQJiZQkAzAgCCQCkAwEFAmNrCQDMCAIJAKQDAQUCYmcJAMwIAgkApAMBBQJiaAUDbmlsBQFhCQELU3RyaW5nRW50cnkCBQJjbAUCY20BAmNuBAJjbwJjcAJjcQJjcgQCY3MJAQJibgAEAmN0CQECYm8ABAJjdQkBAmJwAAQCY3YJAQJibQAEAmN3CQEBcAIFBHRoaXMFAmNzBAJjeAkBAXACBQR0aGlzBQJjdAQCY3kJAQFwAgUEdGhpcwUCY3UEAmN6CQEBcAIFBHRoaXMFAmN2CQDMCAIJAQxJbnRlZ2VyRW50cnkCBQJjcwkAZAIFAmN3BQJjcAkAzAgCCQEMSW50ZWdlckVudHJ5AgUCY3QJAGQCBQJjeAUCY3EJAMwIAgkBDEludGVnZXJFbnRyeQIFAmN1CQBkAgUCY3kFAmNyCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQJjdgkAZAIFAmN6BQJjbwUDbmlsAQJjQQcCYVkCYVoCYmUCYmYCYmcCYmgCYmkJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAmFYAgUCYVkFAmFaCQECYmQFBQJiZQUCYmYFAmJnBQJiaAUCYmkFA25pbAECY0ICAmFPAmNDAwkAZgIJAJADAQgFAmFPCHBheW1lbnRzAAEJAQFsAQIbb25seSBvbmUgcGF5bWVudCBpcyBhbGxvd2VkAwkAAAIJAJADAQgFAmFPCHBheW1lbnRzAAAAAAQCY0QJAJEDAggFAmFPCHBheW1lbnRzAAADCQECIT0CCQEFdmFsdWUBCAUCY0QHYXNzZXRJZAUCY0MJAQFsAQIbaW52YWxpZCBhc3NldCBpZCBpbiBwYXltZW50CAUCY0QGYW1vdW50AQJjRQECYVkJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBAmJjAQUCYVkAAAECY0YABAJjRwQCY0gJAQV2YWx1ZQEJAJoIAgUCYlYJAQJiRQAEAmNJCQBlAgUCY0gAAQMJAGYCAAAFAmNJCQEBbAECDWludmFsaWQgZXBvY2gJAJQKAgUCY0gFAmNJBAJjSAgFAmNHAl8xBAJjSQgFAmNHAl8yBAJjSgkBBXZhbHVlAQkAmggCBQJiVgkBAmJEAQUCY0gJAJQKAgUCY0kFAmNKAQJjSwECYkcEAmNMAAQEAmNNAAUEAmNOCgACYlkJAPwHBAUCYlACIGdldFBvb2xDb25maWdCeUxwQXNzZXRJZFJFQURPTkxZCQDMCAIFAmJHBQNuaWwFA25pbAMJAAECBQJiWQIJTGlzdFtBbnldBQJiWQkAAgEJAKwCAgkAAwEFAmJZAh4gY291bGRuJ3QgYmUgY2FzdCB0byBMaXN0W0FueV0EAmJBCgACYlkJAJEDAgUCY04FAmNMAwkAAQIFAmJZAgZTdHJpbmcFAmJZCQACAQkArAICCQADAQUCYlkCGyBjb3VsZG4ndCBiZSBjYXN0IHRvIFN0cmluZwQCYkIKAAJiWQkAkQMCBQJjTgUCY00DCQABAgUCYlkCBlN0cmluZwUCYlkJAAIBCQCsAgIJAAMBBQJiWQIbIGNvdWxkbid0IGJlIGNhc3QgdG8gU3RyaW5nCQCUCgIFAmJBBQJiQgECY08CAmJHAmJPBAJhWQkBEUBleHRyTmF0aXZlKDEwNjIpAQUCYk8EAmNQCQECY0YABAJjSQgFAmNQAl8xBAJjSggFAmNQAl8yBAJjUQkBAmNLAQUCYkcEAmJBCAUCY1ECXzEEAmJCCAUCY1ECXzIEAmNSCQECYnoEBQJiQQUCYkIFAmFZBQJjSQQCY1MJAQt2YWx1ZU9yRWxzZQIJAJoIAgUCYlYFAmNSAAAFAmNTAQJjVAICYkcCYk8EAmNVCQELdmFsdWVPckVsc2UCCQCaCAIFAmJSCQECYk4CBQJiTwUCYkcAAAQCY1MJAQJjTwIFAmJHBQJiTwMJAAACBQJjVQAAAAAFAmNTAQJjVgECYkcEAmNXCQECY0YABAJjSQgFAmNXAl8xBAJjSggFAmNXAl8yBAJjWAkBC3ZhbHVlT3JFbHNlAgkAmggCBQJiVgkBAmJGAgUCYkcFAmNJAAAEAmNZCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQJiRgIFAmJHBQJjSQUCY1gFAmNZAQJjWgECYkcEAmRhCQECY0YABAJjSQgFAmRhAl8xBAJjSggFAmRhAl8yBAJjWQkBAmNWAQUCYkcEAmRiCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQJiSAIFAmJHBQJjSQAABAJkYwkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQECYkkCBQJiRwUCY0kFAmNKBAJkZAkAZQIFBmhlaWdodAUCZGMEAmRlCQBkAgkAaAIFAmRkBQJjWQUCZGIFAmRlAQJkZgICYkcCZGcEAmRoCQECY0YABAJjSQgFAmRoAl8xBAJjSggFAmRoAl8yBAJjWQkBAmNWAQUCYkcEAmRpCQBkAgUCY1kFAmRnBAJkZQkBAmNaAQUCYkcJAMwIAgkBDEludGVnZXJFbnRyeQIJAQJiRgIFAmJHBQJjSQUCZGkJAMwIAgkBDEludGVnZXJFbnRyeQIJAQJiSQIFAmJHBQJjSQUGaGVpZ2h0CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQECYkgCBQJiRwUCY0kFAmRlBQNuaWwBAmRqAgJiRwJiTwQCZGsJAQJjRgAEAmNJCAUCZGsCXzEEAmNKCAUCZGsCXzIEAmFZCQERQGV4dHJOYXRpdmUoMTA2MikBBQJiTwQCZGwJAQJjVAIFAmJHBQJiTwQCZG0JAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBAmJLAwUCYkcFAmFZBQJjSQAABAJkbgkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQECYkwDBQJiRwUCYVkFAmNJBQJjSgQCZG8JAGUCBQZoZWlnaHQFAmRuBAJkcAkAZAIJAGgCBQJkbwUCZGwFAmRtBQJkcAECZHEDAmJHAmJPAmRyBAJkcwkBAmNGAAQCY0kIBQJkcwJfMQQCY0oIBQJkcwJfMgQCYVkJARFAZXh0ck5hdGl2ZSgxMDYyKQEFAmJPBAJkdAkBAmNPAgUCYkcFAmJPBAJkdQMJAAACBQJkdAAABQNuaWwEAmRnAwUCZHIFAmR0CQEBLQEFAmR0BAJkdgkBAmRmAgUCYkcFAmRnBAJkcAkBAmRqAgUCYkcFAmJPBAJkdwkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAmJMAwUCYkcFAmFZBQJjSQUGaGVpZ2h0CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQECYksDBQJiRwUCYVkFAmNJBQJkcAUDbmlsCQDOCAIFAmR2BQJkdwUCZHUBAmR4AgJiRwJiTwQCZHkJAQJjRgAEAmNJCAUCZHkCXzEEAmNKCAUCZHkCXzIEAmFZCQERQGV4dHJOYXRpdmUoMTA2MikBBQJiTwQCZHoJAQJiTQMFAmJHBQJhWQUCY0kEAmRBCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFAmR6AAAEAmRCCQECYkoDBQJiRwUCYVkFAmNJBAJkQwkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQJkQgAABAJkcAkBAmRqAgUCYkcFAmJPBAJkZQkBAmNaAQUCYkcEAmRECQBlAgUCZHAFAmRBBAJkRQkAZQIFAmRlBQJkQwkAlQoDCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQJkegUCZHAJAMwIAgkBDEludGVnZXJFbnRyeQIFAmRCBQJkZQUDbmlsBQJkRAUCZEUBAmRGAAQCZEcJAQFzAgUCYlEJAQJhaAAEAmRICQCaCAIFBHRoaXMJAQJhawAEAmRJCQCaCAIFBHRoaXMJAQJhbAAEAmRKCQEBcwIFAmJRCQECYW4ABAJkSwMJAGYCBQZoZWlnaHQFAmRKBQJkSgUGaGVpZ2h0BAJkTAQCYUoFAmRIAwkAAQIFAmFKAgNJbnQEAmRNBQJhSgkAlgMBCQDMCAIJAGUCBQJkSwUCZE0JAMwIAgAABQNuaWwDCQABAgUCYUoCBFVuaXQAAAkAAgECC01hdGNoIGVycm9yBAJkTgkAaQIJAGgCBQJkRwkAZQIFAmJYAAEFAmJYBAJkTwkBC3ZhbHVlT3JFbHNlAgUCZEkAAAQCZFAJAGQCCQBoAgUCZE4FAmRMBQJkTwkAlAoCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQECYWwABQJkUAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAmFrAAUGaGVpZ2h0BQNuaWwFAmRQAQJkUQMCYkcCYk8CZFIEAmFZCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQUCYk8JAQFqAQIUaW52YWxpZCB1c2VyIGFkZHJlc3MEAmJyCQECYloBBQJhWQMJAAACBQJicgUCYnIEAmRTAgVlbXB0eQQCZFQDCQECIT0CBQJiRwUCZFMEAmRVCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUCYlAJAQFRAQUCYkcJAQFqAQkArAICAhV1bnN1cHBvcnRlZCBscCBhc3NldCAFAmJHCQERQGV4dHJOYXRpdmUoMTA1MCkCBQJiUAkBAVMBBQJkVQMFAmRSAAAJAQFsAQkArAICAihub3QgcmVhZG9ubHkgbW9kZTogdW5zdXBwb3J0ZWQgbHAgYXNzZXQgBQJiRwQCZFYJAQJicwIFAmJyBQJiRwQCZFcJAQJicQEFAmJyBAJkWAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQJkVgkBAXACBQR0aGlzBQJkVwQCZFAICQECZEYAAl8yBAJkWQkAZQIFAmRQBQJkWAMJAGYCAAAFAmRZCQEBbAECEndyb25nIGNhbGN1bGF0aW9ucwQCZFoJAQJkeAIFAmJHBQJiTwQCZWEIBQJkWgJfMQQCZWIIBQJkWgJfMgQCZWMIBQJkWgJfMwQCZWQJAGsDBQJkWQUCZFQFAWQEAmVlAwkAAAIFAmVjAAAAAAkAawMFAmVkBQJlYgUCZWMEAmVmCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIFAmRWBQJkUAUDbmlsBQJlYQQCZWcJALkJAgkAzAgCCQCkAwEFAmRYCQDMCAIJAKQDAQUCZFkJAMwIAgkApAMBBQJkVAkAzAgCCQCkAwEFAmViCQDMCAIJAKQDAQUCZWMFA25pbAIBOgkAlQoDBQJlZQUCZWYFAmVnCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQJlaAICYU8CYmcEAmVpCQDYBAEFAmF5AwkBAiE9AgkAkAMBCAUCYU8IcGF5bWVudHMAAQkBAWwBAjRpbnZhbGlkIHBheW1lbnQgLSBleGFjdCBvbmUgcGF5bWVudCBtdXN0IGJlIGF0dGFjaGVkBAJjRAkAkQMCCAUCYU8IcGF5bWVudHMAAAQCZWoIBQJjRAZhbW91bnQDCQECIT0CBQJheQkBBXZhbHVlAQgFAmNEB2Fzc2V0SWQJAQFsAQkArAICCQCsAgICHmludmFsaWQgYXNzZXQgaXMgaW4gcGF5bWVudCAtIAUCZWkCDCBpcyBleHBlY3RlZAQCZWsJAQJiagAEAmFZCAUCYU8GY2FsbGVyBAJiTwkApQgBBQJhWQQCZWwJAQlpc0RlZmluZWQBCQCiCAEJAQJiawEFAmJPBAJlbQMFAmVsCQEFdmFsdWUBCQCiCAEJAQJiawEFAmJPCQCkAwEJAQFzAgUEdGhpcwUCZWsEAmJyCQENcGFyc2VJbnRWYWx1ZQEFAmVtBAJjawUGaGVpZ2h0AwMJAGYCBQJhegUCZWoJAQIhPQIFAmFZBQJiVAcJAQFsAQkArAICAiJhbW91bnQgaXMgbGVzcyB0aGVuIG1pbkxvY2tBbW91bnQ9CQCkAwEFAmF6AwkAZgIFAmFBBQJiZwkBAWwBCQCsAgICLXBhc3NlZCBkdXJhdGlvbiBpcyBsZXNzIHRoYW4gbWluTG9ja0R1cmF0aW9uPQkApAMBBQJhQQMJAGYCBQJiZwUCYUIJAQFsAQkArAICAjBwYXNzZWQgZHVyYXRpb24gaXMgZ3JlYXRlciB0aGFuIG1heExvY2tEdXJhdGlvbj0JAKQDAQUCYUIDCQECIT0CCQBqAgUCYmcFAmFFAAAJAQFsAQkArAICAixkdXJhdGlvbiBtdXN0IGJlIG11bHRpcGxlIG9mIGxvY2tTdGVwQmxvY2tzPQkApAMBBQJhRQQCZW4JAGsDBQJlagUCYmcFAmFCBAJlbwkBAmNhAAQCZFcJAQJicQEFAmJyBAJkUAgJAQJkRgACXzIEAmVwCQECY0UBBQJhWQQCZXEJAPwHBAUCYlMCEXJlZnJlc2hVc2VyUmV3YXJkCQDMCAIIBQJhWQVieXRlcwkAzAgCBQJicgUDbmlsBQNuaWwDCQAAAgUCZXEFAmVxBAJlcgMFAmVsBQNuaWwJAMwIAgkBDEludGVnZXJFbnRyeQIFAmVrCQBkAgUCYnIAAQkAzAgCCQELU3RyaW5nRW50cnkCCQECYmsBBQJiTwUCZW0JAMwIAgkBC1N0cmluZ0VudHJ5AgkBAmJsAQUCZW0FAmJPBQNuaWwJAJQKAgkAzggCCQDNCAIJAM4IAgkAzggCBQJlcgkBAmNBBwUCYVkIBQJhTw10cmFuc2FjdGlvbklkBQJlagUCY2sFAmJnBQJlbgAACQECY24EBQJlagUCYmcAAQMFAmVsAAAAAQkBAmNoBwIEbG9jawUCYk8FAmVqBQJjawUCYmcFAmVuBQJhTwkAzAgCCQEMSW50ZWdlckVudHJ5AgUCZFcFAmRQCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQECYnkACQBkAgUCZW8FAmVuCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQECYmMBBQJhWQkAZAIFAmVwBQJlbgUDbmlsBQJlbgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgECZXMCAmFZAmV0BAJldQkBAmJiAgUCYVkFAmV0BAJldgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmV1BQJhUgQCY2sJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJldQUCYVMEAmV3CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCZXUFAmFUBAJleAkAZAIFAmNrBQJldwQCYmkJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJldQUCYVcEAmV5CQBpAgkAZQIFBmhlaWdodAUCY2sFAmFEBAJlegkAvAIDCQC2AgEFAmV5CQC5AgIJALYCAQkAaAIFAWkFAmFEBQFoCQC2AgEFAmV3BAJlQQMJAGYCBQZoZWlnaHQFAmV4BQJldgkAoAMBCQC8AgMJALYCAQUCZXYJALgCAgUBaAkAdgYJALYCAQAFAAEFAmV6BQFmBQFmBQRET1dOBQFoBAJlQgkAZQIFAmVBBQJiaQUCZUIRAmFPAQdsb2NrUmVmAwJiZwJlQwJlRAQCZUUJAQJhSAADCQAAAgUCZUUFAmVFBAJlRgkBAmVoAgUCYU8FAmJnBAJlRwgFAmVGAl8xBAJlbggFAmVGAl8yBAJlSAkApQgBCAUCYU8GY2FsbGVyBAJlSQMDCQAAAgUCZUMCAAYJAAACBQJlRAEABQR1bml0CQD8BwQFAXoCCmNyZWF0ZVBhaXIJAMwIAgUBQwkAzAgCBQJlQwkAzAgCBQJlSAkAzAgCBQJlRAUDbmlsBQNuaWwDCQAAAgUCZUkFAmVJBAJlSgkA/AcEBQJhQwIWdXBkYXRlUmVmZXJyYWxBY3Rpdml0eQkAzAgCCQClCAEIBQJhTwZjYWxsZXIJAMwIAgUCZW4FA25pbAUDbmlsAwkAAAIFAmVKBQJlSgkAlAoCBQJlRwUEdW5pdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJhTwEEbG9jawECYmcEAmVFCQECYUgAAwkAAAIFAmVFBQJlRQQCZUsJAQJlaAIFAmFPBQJiZwQCZUcIBQJlSwJfMQQCZW4IBQJlSwJfMgQCZUoJAPwHBAUCYUMCFnVwZGF0ZVJlZmVycmFsQWN0aXZpdHkJAMwIAgkApQgBCAUCYU8GY2FsbGVyCQDMCAIFAmVuBQNuaWwFA25pbAMJAAACBQJlSgUCZUoJAJQKAgUCZUcFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CYU8BDGNsYWltV3hCb29zdAICYkcCYk8EAmVFCQECYUgAAwkAAAIFAmVFBQJlRQMJAQIhPQIFAmJSCAUCYU8GY2FsbGVyCQEBbAECEnBlcm1pc3Npb25zIGRlbmllZAQCZUwJAQJkUQMFAmJHBQJiTwcEAmVNCAUCZUwCXzEEAmVmCAUCZUwCXzIEAmVnCAUCZUwCXzMJAJQKAgUCZWYJAMwIAgUCZU0FA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJhTwEUY2xhaW1XeEJvb3N0UkVBRE9OTFkCAmJHAmJPBAJlTgkBAmRRAwUCYkcFAmJPBgQCZU0IBQJlTgJfMQQCZWYIBQJlTgJfMgQCZWcIBQJlTgJfMwkAlAoCBQNuaWwJAMwIAgUCZU0JAMwIAgUCZWcFA25pbAJhTwEGdW5sb2NrAQJlTwQCZUUJAQJhSAADCQAAAgUCZUUFAmVFBAJhWQgFAmFPBmNhbGxlcgQCYk8JAKUIAQUCYVkEAmV0AwkAAAIFAmVPAgAFBHVuaXQJANkEAQUCZU8EAmV1CQECYmICBQJhWQUCZXQEAmV2CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCZXUFAmFSBAJjawkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmV1BQJhUwQCZXcJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJldQUCYVQEAmJpCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCZXUFAmFXBAJiaAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmV1BQJhVgQCZXkJAGkCCQBlAgUGaGVpZ2h0BQJjawUCYUQEAmVCCQECZXMCBQJhWQUCZXQEAmVQCQCXAwEJAMwIAgkAawMFAmVCBQJldwUCYUIJAMwIAgUCYmgFA25pbAQCZVEJAQF2AgkAZQIFAmJoBQJlUAIMZ3d4UmVtYWluaW5nBAJlUgkBAmNiAQUCYVkDCQBnAgAABQJlQgkBAWwBAhFub3RoaW5nIHRvIHVubG9jawQCZW8JAQJjYQAEAmVwCQECY0UBBQJhWQQCZVMJAQF2AgkAZQIFAmVwBQJlUAIVdXNlckd3eEFtb3VudFRvdGFsTmV3AwkAZgIFAmVSBQJlUwkBAWwBCQCsAgICE2xvY2tlZCBnd3ggYW1vdW50OiAJAKQDAQUCZVIEAmJyCQENcGFyc2VJbnRWYWx1ZQEJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQECYmsBBQJiTwkBAWoBAhNpbnZhbGlkIHVzZXIgbnVtYmVyBAJlcQkA/AcEBQJiUwIRcmVmcmVzaFVzZXJSZXdhcmQJAMwIAggFAmFZBWJ5dGVzCQDMCAIFAmJyBQNuaWwFA25pbAMJAAACBQJlcQUCZXEJAM4IAgkAzQgCCQDNCAIJAM4IAgkBAmNBBwUCYVkFAmV0BQJldgUCY2sFAmV3BQJlUQkAZAIFAmJpBQJlQgkBAmNuBAkBAS0BBQJlQgAAAAAAAAkBAmNoBwIGdW5sb2NrBQJiTwUCZUIFAmNrBQJldwUCZVAFAmFPCQEOU2NyaXB0VHJhbnNmZXIDBQJhWQUCZUIFAmF5CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQECYnkACQEBdgIJAGUCBQJlbwUCZVACCGd3eFRvdGFsCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQECYmMBBQJhWQUCZVMFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJhTwETZ3d4VXNlckluZm9SRUFET05MWQECYk8EAmFZCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQUCYk8JAQFqAQIUaW52YWxpZCB1c2VyIGFkZHJlc3MEAmJoCQECY0UBBQJhWQkAlAoCBQNuaWwJAMwIAgUCYmgFA25pbAJhTwEXdXNlck1heER1cmF0aW9uUkVBRE9OTFkBAmJPCQCUCgIFA25pbAkAlAoCAgRsb2NrBQJhQgJhTwEgZ2V0VXNlckd3eEFtb3VudEF0SGVpZ2h0UkVBRE9OTFkCAmJPAmVUBAJhWQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEFAmJPCQEBagECFGludmFsaWQgdXNlciBhZGRyZXNzBAJiaAkBAmNFAQUCYVkJAJQKAgUDbmlsBQJiaAJhTwEQZ2V0VXNlckd3eEFtb3VudAECYk8EAmFZCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQUCYk8JAQFqAQIUaW52YWxpZCB1c2VyIGFkZHJlc3MEAmJoCQECY0UBBQJhWQkAlAoCBQNuaWwFAmJoAmFPARNnZXRHd3hUb3RhbFJFQURPTkxZAAkAlAoCBQNuaWwJAQJjYQACYU8BFW9uQm9vc3RFbWlzc2lvblVwZGF0ZQAEAmVFCQECYUgAAwkAAAIFAmVFBQJlRQQCZVUDCQAAAggFAmFPBmNhbGxlcgUCYlEGCQECYU4BBQJhTwMJAAACBQJlVQUCZVUJAQJkRgAJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CYU8BEm9uU3Rha2VkVm90ZVVwZGF0ZQMCYkcCYk8CZHIEAmVFCQECYUgAAwkAAAIFAmVFBQJlRQQCZVUDCQAAAggFAmFPBmNhbGxlcgUCYlIGCQECYU4BBQJhTwMJAAACBQJlVQUCZVUEAmR1CQECZHEDBQJiRwUCYk8FAmRyCQCUCgIFAmR1BQR1bml0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmFPAR1nZXRWb3RpbmdSZXN1bHRTdGFrZWRSRUFET05MWQECYkcJAJQKAgUDbmlsCQECY1YBBQJiRwJhTwElZ2V0Vm90aW5nUmVzdWx0U3Rha2VkSW50ZWdyYWxSRUFET05MWQECYkcJAJQKAgUDbmlsCQECY1oBBQJiRwJhTwEcZ2V0VXNlclZvdGVGaW5hbGl6ZWRSRUFET05MWQICYkcCYk8JAJQKAgUDbmlsCQECY08CBQJiRwUCYk8CYU8BIWdldFVzZXJWb3RlU3Rha2VkSW50ZWdyYWxSRUFET05MWQICYkcCYk8JAJQKAgUDbmlsCQECZGoCBQJiRwUCYk8CYU8BB3N1c3BlbmQBAXcEAmVVCQECYU4BBQJhTwMJAAACBQJlVQUCZVUJAJQKAgkAzAgCCQEMQm9vbGVhbkVudHJ5AgUCYUYFAXcFA25pbAUBdwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgECZVYBAmVXAAQCZVgEAmFKCQECYUwAAwkAAQIFAmFKAgpCeXRlVmVjdG9yBAJhUQUCYUoFAmFRAwkAAQIFAmFKAgRVbml0CAUCZVYPc2VuZGVyUHVibGljS2V5CQACAQILTWF0Y2ggZXJyb3IJAPQDAwgFAmVWCWJvZHlCeXRlcwkAkQMCCAUCZVYGcHJvb2ZzAAAFAmVYVftOcw==", "height": 2734786, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: AJfoLY7Sbk8L34gs3UYKCYV3n36smMVUkSitSTmtmLfC Next: BE7P4d1VrWjaXjVwVjZhZvHBSuLE16cAiF9H8fsC8HEq Diff:
OldNewDifferences
805805 let gwxAmount = parseIntValue(userRecordArray[IdxLockGwxAmount])
806806 let t = ((height - lockStart) / blocksInPeriod)
807807 let wxWithdrawable = getWxWithdrawable(userAddress, txIdOption)
808- let gWxAmountStart = fraction(userAmount, lockDuration, maxLockDuration)
809- let gwxBurned = min([fraction((t * blocksInPeriod), gWxAmountStart, maxLockDuration), gwxAmount])
808+ let gwxBurned = min([fraction(wxWithdrawable, lockDuration, maxLockDuration), gwxAmount])
810809 let gwxRemaining = ensurePositive((gwxAmount - gwxBurned), "gwxRemaining")
811810 let lockedGwxAmount = getLockedGwxAmount(userAddress)
812811 if ((0 >= wxWithdrawable))
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
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 let contractFilename = "boosting.ride"
1313
1414 let SCALE18 = 18
1515
1616 let MULT18 = 1000000000000000000
1717
1818 let MULT18BI = toBigInt(MULT18)
1919
2020 let DECAY_CONSTANT = 8
2121
2222 func wrapErr (msg) = makeString([contractFilename, ": ", msg], "")
2323
2424
2525 func throwErr (msg) = throw(wrapErr(msg))
2626
2727
2828 func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), wrapErr((("mandatory this." + key) + " is not defined")))
2929
3030
3131 func getIntOrZero (address,key) = valueOrElse(getInteger(address, key), 0)
3232
3333
3434 func getIntOrDefault (address,key,defaultVal) = valueOrElse(getInteger(address, key), defaultVal)
3535
3636
3737 func getIntOrFail (address,key) = valueOrErrorMessage(getInteger(address, key), wrapErr((("mandatory this." + key) + " is not defined")))
3838
3939
4040 func abs (val) = if ((0 > val))
4141 then -(val)
4242 else val
4343
4444
4545 func ensurePositive (v,m) = if ((v >= 0))
4646 then v
4747 else throwErr((valueOrElse(m, "value") + " should be positive"))
4848
4949
5050 func keyReferralsContractAddress () = makeString(["%s%s", "config", "referralsContractAddress"], SEP)
5151
5252
5353 let referralsContractAddressOrFail = addressFromStringValue(getStringOrFail(this, keyReferralsContractAddress()))
5454
5555 let keyReferralProgramName = makeString(["%s%s", "referral", "programName"], SEP)
5656
5757 let referralProgramNameDefault = "wxlock"
5858
5959 let referralProgramName = valueOrElse(getString(this, keyReferralProgramName), referralProgramNameDefault)
6060
6161 func keyFactoryAddress () = "%s%s__config__factoryAddress"
6262
6363
6464 let IdxFactoryCfgStakingDapp = 1
6565
6666 let IdxFactoryCfgBoostingDapp = 2
6767
6868 let IdxFactoryCfgIdoDapp = 3
6969
7070 let IdxFactoryCfgTeamDapp = 4
7171
7272 let IdxFactoryCfgEmissionDapp = 5
7373
7474 let IdxFactoryCfgRestDapp = 6
7575
7676 let IdxFactoryCfgSlippageDapp = 7
7777
7878 let IdxFactoryCfgDaoDapp = 8
7979
8080 let IdxFactoryCfgMarketingDapp = 9
8181
8282 let IdxFactoryCfgGwxRewardDapp = 10
8383
8484 let IdxFactoryCfgBirdsDapp = 11
8585
8686 func keyFactoryCfg () = "%s__factoryConfig"
8787
8888
8989 func keyFactoryLpAssetToPoolContractAddress (lpAssetStr) = makeString(["%s%s%s", lpAssetStr, "mappings__lpAsset2PoolContract"], SEP)
9090
9191
9292 func keyFactoryPoolWeight (contractAddress) = makeString(["%s%s", "poolWeight", contractAddress], SEP)
9393
9494
9595 func keyFactoryPoolWeightHistory (poolAddress,num) = ((("%s%s__poolWeight__" + poolAddress) + "__") + toString(num))
9696
9797
9898 func readFactoryAddressOrFail () = addressFromStringValue(getStringOrFail(this, keyFactoryAddress()))
9999
100100
101101 func readFactoryCfgOrFail (factory) = split(getStringOrFail(factory, keyFactoryCfg()), SEP)
102102
103103
104104 func getBoostingAddressOrFail (factoryCfg) = addressFromStringValue(factoryCfg[IdxFactoryCfgBoostingDapp])
105105
106106
107107 func getEmissionAddressOrFail (factoryCfg) = addressFromStringValue(factoryCfg[IdxFactoryCfgEmissionDapp])
108108
109109
110110 func getStakingAddressOrFail (factoryCfg) = addressFromStringValue(factoryCfg[IdxFactoryCfgStakingDapp])
111111
112112
113113 func getGwxRewardAddressOrFail (factoryCfg) = addressFromStringValue(factoryCfg[IdxFactoryCfgGwxRewardDapp])
114114
115115
116116 func keyManagerPublicKey () = "%s__managerPublicKey"
117117
118118
119119 func keyManagerVaultAddress () = "%s__managerVaultAddress"
120120
121121
122122 func keyEmissionRatePerBlockCurrent () = "%s%s__ratePerBlock__current"
123123
124124
125125 func keyEmissionRatePerBlockMaxCurrent () = "%s%s__ratePerBlockMax__current"
126126
127127
128128 func keyEmissionStartBlock () = "%s%s__emission__startBlock"
129129
130130
131131 func keyBoostingV2LastUpdateHeight () = "%s%s__boostingV2__startBlock"
132132
133133
134134 func keyBoostingV2Integral () = "%s%s__boostingV2__integral"
135135
136136
137137 func keyEmissionDurationInBlocks () = "%s%s__emission__duration"
138138
139139
140140 func keyEmissionEndBlock () = "%s%s__emission__endBlock"
141141
142142
143143 let IdxCfgAssetId = 1
144144
145145 let IdxCfgMinLockAmount = 2
146146
147147 let IdxCfgMinLockDuration = 3
148148
149149 let IdxCfgMaxLockDuration = 4
150150
151151 let IdxCfgMathContract = 5
152152
153153 let IdxCfgBlocksInPeriod = 6
154154
155155 let IdxCfgLockStepBlocks = 7
156156
157157 func keyConfig () = "%s__config"
158158
159159
160160 func readConfigArrayOrFail () = split(getStringOrFail(this, keyConfig()), SEP)
161161
162162
163163 let cfgArray = readConfigArrayOrFail()
164164
165165 let assetId = fromBase58String(cfgArray[IdxCfgAssetId])
166166
167167 let minLockAmount = valueOrErrorMessage(parseInt(cfgArray[IdxCfgMinLockAmount]), wrapErr("invalid min lock amount"))
168168
169169 let minLockDuration = valueOrErrorMessage(parseInt(cfgArray[IdxCfgMinLockDuration]), wrapErr("invalid min lock duration"))
170170
171171 let maxLockDuration = valueOrErrorMessage(parseInt(cfgArray[IdxCfgMaxLockDuration]), wrapErr("invalid max lock duration"))
172172
173173 let mathContract = valueOrErrorMessage(addressFromString(cfgArray[IdxCfgMathContract]), wrapErr("invalid math contract address"))
174174
175175 let blocksInPeriod = valueOrErrorMessage(parseInt(cfgArray[IdxCfgBlocksInPeriod]), wrapErr("invalid blocks in period"))
176176
177177 let lockStepBlocks = valueOrErrorMessage(parseInt(cfgArray[IdxCfgLockStepBlocks]), wrapErr("invalid lock step blocks"))
178178
179179 let keySuspension = "%s__suspension"
180180
181181 let isSuspended = valueOrElse(getBoolean(this, keySuspension), false)
182182
183183 func throwIfSuspended () = if (!(isSuspended))
184184 then true
185185 else throwErr("suspended")
186186
187187
188188 func getManagerVaultAddressOrThis () = match getString(keyManagerVaultAddress()) {
189189 case s: String =>
190190 addressFromStringValue(s)
191191 case _ =>
192192 this
193193 }
194194
195195
196196 func managerPublicKeyOrUnit () = {
197197 let managerVaultAddress = getManagerVaultAddressOrThis()
198198 match getString(managerVaultAddress, keyManagerPublicKey()) {
199199 case s: String =>
200200 fromBase58String(s)
201201 case _: Unit =>
202202 unit
203203 case _ =>
204204 throw("Match error")
205205 }
206206 }
207207
208208
209209 func mustManager (i) = {
210210 let pd = throwErr("Permission denied")
211211 match managerPublicKeyOrUnit() {
212212 case pk: ByteVector =>
213213 if ((i.callerPublicKey == pk))
214214 then true
215215 else pd
216216 case _: Unit =>
217217 if ((i.caller == this))
218218 then true
219219 else pd
220220 case _ =>
221221 throw("Match error")
222222 }
223223 }
224224
225225
226226 let IdxLockAmount = 1
227227
228228 let IdxLockStart = 2
229229
230230 let IdxLockDuration = 3
231231
232232 let IdxLockLastUpdateTimestamp = 4
233233
234234 let IdxLockGwxAmount = 5
235235
236236 let IdxLockWxClaimed = 6
237237
238238 func keyLockParamsRecord (userAddress,txId) = makeString(["%s%s%s__lock", toString(userAddress), match txId {
239239 case b: ByteVector =>
240240 toBase58String(b)
241241 case _: Unit =>
242242 "legacy"
243243 case _ =>
244244 throw("Match error")
245245 }], SEP)
246246
247247
248248 func readLockParamsRecordOrFail (userAddress,txId) = split(getStringOrFail(this, keyLockParamsRecord(userAddress, txId)), SEP)
249249
250250
251251 func keyUserGwxAmountTotal (userAddress) = makeString(["%s%s__gwxAmountTotal", toString(userAddress)], SEP)
252252
253253
254254 func formatLockParamsRecord (amount,start,duration,gwxAmount,wxClaimed) = makeString(["%d%d%d%d%d%d", toString(amount), toString(start), toString(duration), toString(lastBlock.timestamp), toString(gwxAmount), toString(wxClaimed)], SEP)
255255
256256
257257 func keyNextUserNum () = "%s__nextUserNum"
258258
259259
260260 func keyUser2NumMapping (userAddress) = makeString(["%s%s%s__mapping__user2num", userAddress], SEP)
261261
262262
263263 func keyNum2UserMapping (num) = makeString(["%s%s%s__mapping__num2user", num], SEP)
264264
265265
266266 func keyLockParamTotalAmount () = "%s%s__stats__activeTotalLocked"
267267
268268
269269 func keyStatsLocksDurationSumInBlocks () = "%s%s__stats__locksDurationSumInBlocks"
270270
271271
272272 func keyStatsLocksCount () = "%s%s__stats__locksCount"
273273
274274
275275 func keyStatsUsersCount () = "%s%s__stats__activeUsersCount"
276276
277277
278278 func keyUserBoostEmissionLastINTEGRAL (userNum) = makeString(["%s%d__userBoostEmissionLastIntV2", toString(userNum)], SEP)
279279
280280
281281 func keyUserLpBoostEmissionLastINTEGRAL (userNum,lpAssetId) = makeString(["%s%d__userBoostEmissionLastIntV2", toString(userNum), lpAssetId], SEP)
282282
283283
284284 func keyUserMaxBoostINTEGRAL (userNum) = makeString(["%s%d__maxBoostInt", toString(userNum)], SEP)
285285
286286
287287 func keyTotalMaxBoostINTEGRAL () = "%s%s__maxBoostInt__total"
288288
289289
290290 func keyUserBoostAvalaibleToClaimTotal (userNum) = makeString(["%s%d__userBoostAvaliableToClaimTotal", toString(userNum)], SEP)
291291
292292
293293 func keyUserBoostClaimed (userNum) = makeString(["%s%d__userBoostClaimed", toString(userNum)], SEP)
294294
295295
296296 func keyGwxTotal () = "%s%s__gwx__total"
297297
298298
299299 func keyVote (amountAssetId,priceAssetId,address,epoch) = makeString(["%s%s%s%s%d", "vote", amountAssetId, priceAssetId, toString(address), toString(epoch)], SEP)
300300
301301
302302 func keyStartHeightByEpoch (epoch) = makeString(["%s%d", "startHeight", toString(epoch)], SEP)
303303
304304
305305 func keyCurrentEpochUi () = makeString(["%s", "currentEpochUi"], SEP)
306306
307307
308308 func keyVotingResultStaked (lpAssetIdStr,epoch) = makeString(["%s%s%d", "votingResultStaked", lpAssetIdStr, toString(epoch)], SEP)
309309
310310
311311 func keyVotingResultStakedIntegral (lpAssetIdStr,epoch) = makeString(["%s%s%d", "votingResultStakedIntegral", lpAssetIdStr, toString(epoch)], SEP)
312312
313313
314314 func keyVotingResultStakedLastUpdateHeight (lpAssetIdStr,epoch) = makeString(["%s%s%d", "votingResultStakedIntegralLastUpdateHeight", lpAssetIdStr, toString(epoch)], SEP)
315315
316316
317317 func keyVotingResultStakedIntegralLast (lpAssetIdStr,address,epoch) = makeString(["%s%s%s%d", "votingResultStakedIntegralLast", lpAssetIdStr, toString(address), toString(epoch)], SEP)
318318
319319
320320 func keyVoteStakedIntegral (lpAssetIdStr,address,epoch) = makeString(["%s%s%s%d", "voteStakedIntegral", lpAssetIdStr, toString(address), toString(epoch)], SEP)
321321
322322
323323 func keyVoteStakedLastUpdateHeight (lpAssetIdStr,address,epoch) = makeString(["%s%s%s%d", "voteStakedIntegralLastUpdateHeight", lpAssetIdStr, toString(address), toString(epoch)], SEP)
324324
325325
326326 func keyVoteStakedIntegralLast (lpAssetIdStr,address,epoch) = makeString(["%s%s%s%d", "voteStakedIntegralLast", lpAssetIdStr, toString(address), toString(epoch)], SEP)
327327
328328
329329 func keyStakedByUser (userAddressStr,lpAssetIdStr) = makeString(["%s%s%s", "staked", userAddressStr, lpAssetIdStr], SEP)
330330
331331
332332 let factoryContract = readFactoryAddressOrFail()
333333
334334 let factoryCfg = readFactoryCfgOrFail(factoryContract)
335335
336336 let emissionContract = getEmissionAddressOrFail(factoryCfg)
337337
338338 let stakingContract = getStakingAddressOrFail(factoryCfg)
339339
340340 let gwxRewardContract = getGwxRewardAddressOrFail(factoryCfg)
341341
342342 let lpStakingPoolsContract = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(makeString(["%s", "lpStakingPoolsContract"], SEP)), wrapErr("lp_staking_pools contract address is undefined"))), wrapErr("invalid lp_staking_pools contract address"))
343343
344344 let keyVotingEmissionContract = makeString(["%s", "votingEmissionContract"], SEP)
345345
346346 let votingEmissionContract = addressFromStringValue(getStringValue(factoryContract, keyVotingEmissionContract))
347347
348348 let keyVotingEmissionRateContract = makeString(["%s", "votingEmissionRateContract"], SEP)
349349
350350 let boostCoeff = {
351351 let @ = invoke(emissionContract, "getBoostCoeffREADONLY", nil, nil)
352352 if ($isInstanceOf(@, "Int"))
353353 then @
354354 else throw(($getType(@) + " couldn't be cast to Int"))
355355 }
356356
357357 func userNumberByAddressOrFail (userAddress) = match getString(this, keyUser2NumMapping(toString(userAddress))) {
358358 case s: String =>
359359 valueOrErrorMessage(parseInt(s), wrapErr("invalid user number"))
360360 case _: Unit =>
361361 throwErr("invalid user")
362362 case _ =>
363363 throw("Match error")
364364 }
365365
366366
367367 func getGwxAmountTotal () = valueOrElse(getInteger(this, keyGwxTotal()), 0)
368368
369369
370370 func getLockedGwxAmount (userAddress) = {
371371 let functionName = "getLockedGwxAmount"
372372 let votingEmissionRateContract = valueOrErrorMessage( match getString(votingEmissionContract, keyVotingEmissionRateContract) {
373373 case _: Unit =>
374374 unit
375375 case s: String =>
376376 addressFromString(s)
377377 case _ =>
378378 throw("Match error")
379379 }, wrapErr("invalid voting emission rate address"))
380380 let lockedVotingEmissionRate = {
381381 let @ = invoke(votingEmissionContract, functionName, [toString(userAddress)], nil)
382382 if ($isInstanceOf(@, "Int"))
383383 then @
384384 else throw(($getType(@) + " couldn't be cast to Int"))
385385 }
386386 let lockedVotingEmission = {
387387 let @ = invoke(votingEmissionRateContract, functionName, [toString(userAddress)], nil)
388388 if ($isInstanceOf(@, "Int"))
389389 then @
390390 else throw(($getType(@) + " couldn't be cast to Int"))
391391 }
392392 let locked = max([lockedVotingEmissionRate, lockedVotingEmission])
393393 locked
394394 }
395395
396396
397397 func HistoryEntry (type,user,amount,lockStart,duration,gwxAmount,i) = {
398398 let historyKEY = makeString(["%s%s%s%s__history", type, user, toBase58String(i.transactionId)], SEP)
399399 let historyDATA = makeString(["%d%d%d%d%d%d%d", toString(lastBlock.height), toString(lastBlock.timestamp), toString(amount), toString(lockStart), toString(duration), toString(gwxAmount)], SEP)
400400 StringEntry(historyKEY, historyDATA)
401401 }
402402
403403
404404 func StatsEntry (totalLockedInc,durationInc,lockCountInc,usersCountInc) = {
405405 let locksDurationSumInBlocksKEY = keyStatsLocksDurationSumInBlocks()
406406 let locksCountKEY = keyStatsLocksCount()
407407 let usersCountKEY = keyStatsUsersCount()
408408 let totalAmountKEY = keyLockParamTotalAmount()
409409 let locksDurationSumInBlocks = getIntOrZero(this, locksDurationSumInBlocksKEY)
410410 let locksCount = getIntOrZero(this, locksCountKEY)
411411 let usersCount = getIntOrZero(this, usersCountKEY)
412412 let totalAmount = getIntOrZero(this, totalAmountKEY)
413413 [IntegerEntry(locksDurationSumInBlocksKEY, (locksDurationSumInBlocks + durationInc)), IntegerEntry(locksCountKEY, (locksCount + lockCountInc)), IntegerEntry(usersCountKEY, (usersCount + usersCountInc)), IntegerEntry(totalAmountKEY, (totalAmount + totalLockedInc))]
414414 }
415415
416416
417417 func LockParamsEntry (userAddress,txId,amount,start,duration,gwxAmount,wxClaimed) = [StringEntry(keyLockParamsRecord(userAddress, txId), formatLockParamsRecord(amount, start, duration, gwxAmount, wxClaimed))]
418418
419419
420420 func extractOptionalPaymentAmountOrFail (i,expectedAssetId) = if ((size(i.payments) > 1))
421421 then throwErr("only one payment is allowed")
422422 else if ((size(i.payments) == 0))
423423 then 0
424424 else {
425425 let pmt = i.payments[0]
426426 if ((value(pmt.assetId) != expectedAssetId))
427427 then throwErr("invalid asset id in payment")
428428 else pmt.amount
429429 }
430430
431431
432432 func getUserGwxAmountTotal (userAddress) = valueOrElse(getInteger(this, keyUserGwxAmountTotal(userAddress)), 0)
433433
434434
435435 func getVotingEmissionEpochInfo () = {
436436 let $t01468614976 = {
437437 let currentEpochUi = value(getInteger(votingEmissionContract, keyCurrentEpochUi()))
438438 let lastFinalizedEpoch = (currentEpochUi - 1)
439439 if ((0 > lastFinalizedEpoch))
440440 then throwErr("invalid epoch")
441441 else $Tuple2(currentEpochUi, lastFinalizedEpoch)
442442 }
443443 let currentEpochUi = $t01468614976._1
444444 let lastFinalizedEpoch = $t01468614976._2
445445 let currentEpochStartHeight = value(getInteger(votingEmissionContract, keyStartHeightByEpoch(currentEpochUi)))
446446 $Tuple2(lastFinalizedEpoch, currentEpochStartHeight)
447447 }
448448
449449
450450 func getPoolAssetsByLpAssetId (lpAssetIdStr) = {
451451 let idxAmountAssetId = 4
452452 let idxPriceAssetId = 5
453453 let poolCfg = {
454454 let @ = invoke(factoryContract, "getPoolConfigByLpAssetIdREADONLY", [lpAssetIdStr], nil)
455455 if ($isInstanceOf(@, "List[Any]"))
456456 then @
457457 else throw(($getType(@) + " couldn't be cast to List[Any]"))
458458 }
459459 let amountAssetId = {
460460 let @ = poolCfg[idxAmountAssetId]
461461 if ($isInstanceOf(@, "String"))
462462 then @
463463 else throw(($getType(@) + " couldn't be cast to String"))
464464 }
465465 let priceAssetId = {
466466 let @ = poolCfg[idxPriceAssetId]
467467 if ($isInstanceOf(@, "String"))
468468 then @
469469 else throw(($getType(@) + " couldn't be cast to String"))
470470 }
471471 $Tuple2(amountAssetId, priceAssetId)
472472 }
473473
474474
475475 func getUserVoteFinalized (lpAssetIdStr,userAddressStr) = {
476476 let userAddress = addressFromStringValue(userAddressStr)
477477 let $t01566715747 = getVotingEmissionEpochInfo()
478478 let lastFinalizedEpoch = $t01566715747._1
479479 let currentEpochStartHeight = $t01566715747._2
480480 let $t01575015825 = getPoolAssetsByLpAssetId(lpAssetIdStr)
481481 let amountAssetId = $t01575015825._1
482482 let priceAssetId = $t01575015825._2
483483 let userVoteKey = keyVote(amountAssetId, priceAssetId, userAddress, lastFinalizedEpoch)
484484 let userVote = valueOrElse(getInteger(votingEmissionContract, userVoteKey), 0)
485485 userVote
486486 }
487487
488488
489489 func getUserVoteStaked (lpAssetIdStr,userAddressStr) = {
490490 let stakedByUser = valueOrElse(getInteger(stakingContract, keyStakedByUser(userAddressStr, lpAssetIdStr)), 0)
491491 let userVote = getUserVoteFinalized(lpAssetIdStr, userAddressStr)
492492 if ((stakedByUser == 0))
493493 then 0
494494 else userVote
495495 }
496496
497497
498498 func getVotingResultStaked (lpAssetIdStr) = {
499499 let $t01636916449 = getVotingEmissionEpochInfo()
500500 let lastFinalizedEpoch = $t01636916449._1
501501 let currentEpochStartHeight = $t01636916449._2
502502 let votingResultStakedStart = valueOrElse(getInteger(votingEmissionContract, keyVotingResultStaked(lpAssetIdStr, lastFinalizedEpoch)), 0)
503503 let votingResultStaked = valueOrElse(getInteger(this, keyVotingResultStaked(lpAssetIdStr, lastFinalizedEpoch)), votingResultStakedStart)
504504 votingResultStaked
505505 }
506506
507507
508508 func getVotingResultStakedIntegral (lpAssetIdStr) = {
509509 let $t01681116891 = getVotingEmissionEpochInfo()
510510 let lastFinalizedEpoch = $t01681116891._1
511511 let currentEpochStartHeight = $t01681116891._2
512512 let votingResultStaked = getVotingResultStaked(lpAssetIdStr)
513513 let votingResultStakedIntegralPrev = valueOrElse(getInteger(this, keyVotingResultStakedIntegral(lpAssetIdStr, lastFinalizedEpoch)), 0)
514514 let votingResultStakedLastUpdateHeight = valueOrElse(getInteger(this, keyVotingResultStakedLastUpdateHeight(lpAssetIdStr, lastFinalizedEpoch)), currentEpochStartHeight)
515515 let votingResultStakedIntegralDh = (height - votingResultStakedLastUpdateHeight)
516516 let votingResultStakedIntegral = ((votingResultStakedIntegralDh * votingResultStaked) + votingResultStakedIntegralPrev)
517517 votingResultStakedIntegral
518518 }
519519
520520
521521 func refreshVotingResultStakedIntegral (lpAssetIdStr,stakedVoteDelta) = {
522522 let $t01772817808 = getVotingEmissionEpochInfo()
523523 let lastFinalizedEpoch = $t01772817808._1
524524 let currentEpochStartHeight = $t01772817808._2
525525 let votingResultStaked = getVotingResultStaked(lpAssetIdStr)
526526 let votingResultStakedNew = (votingResultStaked + stakedVoteDelta)
527527 let votingResultStakedIntegral = getVotingResultStakedIntegral(lpAssetIdStr)
528528 [IntegerEntry(keyVotingResultStaked(lpAssetIdStr, lastFinalizedEpoch), votingResultStakedNew), IntegerEntry(keyVotingResultStakedLastUpdateHeight(lpAssetIdStr, lastFinalizedEpoch), height), IntegerEntry(keyVotingResultStakedIntegral(lpAssetIdStr, lastFinalizedEpoch), votingResultStakedIntegral)]
529529 }
530530
531531
532532 func getUserVoteStakedIntegral (lpAssetIdStr,userAddressStr) = {
533533 let $t01841918499 = getVotingEmissionEpochInfo()
534534 let lastFinalizedEpoch = $t01841918499._1
535535 let currentEpochStartHeight = $t01841918499._2
536536 let userAddress = addressFromStringValue(userAddressStr)
537537 let userVoteStaked = getUserVoteStaked(lpAssetIdStr, userAddressStr)
538538 let userVoteStakedIntegralPrev = valueOrElse(getInteger(this, keyVoteStakedIntegral(lpAssetIdStr, userAddress, lastFinalizedEpoch)), 0)
539539 let userVoteStakedLastUpdateHeight = valueOrElse(getInteger(this, keyVoteStakedLastUpdateHeight(lpAssetIdStr, userAddress, lastFinalizedEpoch)), currentEpochStartHeight)
540540 let userVoteStakedIntegralDh = (height - userVoteStakedLastUpdateHeight)
541541 let userVoteStakedIntegral = ((userVoteStakedIntegralDh * userVoteStaked) + userVoteStakedIntegralPrev)
542542 userVoteStakedIntegral
543543 }
544544
545545
546546 func refreshVoteStakedIntegral (lpAssetIdStr,userAddressStr,edge) = {
547547 let $t01928719367 = getVotingEmissionEpochInfo()
548548 let lastFinalizedEpoch = $t01928719367._1
549549 let currentEpochStartHeight = $t01928719367._2
550550 let userAddress = addressFromStringValue(userAddressStr)
551551 let userVoteFinalized = getUserVoteFinalized(lpAssetIdStr, userAddressStr)
552552 let actions = if ((userVoteFinalized == 0))
553553 then nil
554554 else {
555555 let stakedVoteDelta = if (edge)
556556 then userVoteFinalized
557557 else -(userVoteFinalized)
558558 let votingResultActions = refreshVotingResultStakedIntegral(lpAssetIdStr, stakedVoteDelta)
559559 let userVoteStakedIntegral = getUserVoteStakedIntegral(lpAssetIdStr, userAddressStr)
560560 let voteActions = [IntegerEntry(keyVoteStakedLastUpdateHeight(lpAssetIdStr, userAddress, lastFinalizedEpoch), height), IntegerEntry(keyVoteStakedIntegral(lpAssetIdStr, userAddress, lastFinalizedEpoch), userVoteStakedIntegral)]
561561 (votingResultActions ++ voteActions)
562562 }
563563 actions
564564 }
565565
566566
567567 func getStakedVotesIntegralsDiff (lpAssetIdStr,userAddressStr) = {
568568 let $t02022120301 = getVotingEmissionEpochInfo()
569569 let lastFinalizedEpoch = $t02022120301._1
570570 let currentEpochStartHeight = $t02022120301._2
571571 let userAddress = addressFromStringValue(userAddressStr)
572572 let userVoteStakedIntegralLastKey = keyVoteStakedIntegralLast(lpAssetIdStr, userAddress, lastFinalizedEpoch)
573573 let userVoteStakedIntegralLast = valueOrElse(getInteger(this, userVoteStakedIntegralLastKey), 0)
574574 let votingResultStakedIntegralLastKey = keyVotingResultStakedIntegralLast(lpAssetIdStr, userAddress, lastFinalizedEpoch)
575575 let votingResultStakedIntegralLast = valueOrElse(getInteger(this, votingResultStakedIntegralLastKey), 0)
576576 let userVoteStakedIntegral = getUserVoteStakedIntegral(lpAssetIdStr, userAddressStr)
577577 let votingResultStakedIntegral = getVotingResultStakedIntegral(lpAssetIdStr)
578578 let userVoteStakedIntegralDiff = (userVoteStakedIntegral - userVoteStakedIntegralLast)
579579 let votingResultStakedIntegralDiff = (votingResultStakedIntegral - votingResultStakedIntegralLast)
580580 $Tuple3([IntegerEntry(userVoteStakedIntegralLastKey, userVoteStakedIntegral), IntegerEntry(votingResultStakedIntegralLastKey, votingResultStakedIntegral)], userVoteStakedIntegralDiff, votingResultStakedIntegralDiff)
581581 }
582582
583583
584584 func refreshBoostEmissionIntegral () = {
585585 let wxEmissionPerBlock = getIntOrFail(emissionContract, keyEmissionRatePerBlockCurrent())
586586 let boostingV2LastUpdateHeightOption = getInteger(this, keyBoostingV2LastUpdateHeight())
587587 let boostingV2IngergalOption = getInteger(this, keyBoostingV2Integral())
588588 let emissionEnd = getIntOrFail(emissionContract, keyEmissionEndBlock())
589589 let h = if ((height > emissionEnd))
590590 then emissionEnd
591591 else height
592592 let dh = match boostingV2LastUpdateHeightOption {
593593 case lastUpdateHeight: Int =>
594594 max([(h - lastUpdateHeight), 0])
595595 case _: Unit =>
596596 0
597597 case _ =>
598598 throw("Match error")
599599 }
600600 let boostEmissionPerBlock = ((wxEmissionPerBlock * (boostCoeff - 1)) / boostCoeff)
601601 let boostEmissionIntegralPrev = valueOrElse(boostingV2IngergalOption, 0)
602602 let boostEmissionIntegral = ((boostEmissionPerBlock * dh) + boostEmissionIntegralPrev)
603603 $Tuple2([IntegerEntry(keyBoostingV2Integral(), boostEmissionIntegral), IntegerEntry(keyBoostingV2LastUpdateHeight(), height)], boostEmissionIntegral)
604604 }
605605
606606
607607 func internalClaimWxBoost (lpAssetIdStr,userAddressStr,readOnly) = {
608608 let userAddress = valueOrErrorMessage(addressFromString(userAddressStr), wrapErr("invalid user address"))
609609 let userNum = userNumberByAddressOrFail(userAddress)
610610 if ((userNum == userNum))
611611 then {
612612 let EMPTYSTR = "empty"
613613 let poolWeight = if ((lpAssetIdStr != EMPTYSTR))
614614 then {
615615 let poolAddressStr = valueOrErrorMessage(getString(factoryContract, keyFactoryLpAssetToPoolContractAddress(lpAssetIdStr)), wrapErr(("unsupported lp asset " + lpAssetIdStr)))
616616 getIntegerValue(factoryContract, keyFactoryPoolWeight(poolAddressStr))
617617 }
618618 else if (readOnly)
619619 then 0
620620 else throwErr(("not readonly mode: unsupported lp asset " + lpAssetIdStr))
621621 let userLpBoostEmissionLastIntegralKEY = keyUserLpBoostEmissionLastINTEGRAL(userNum, lpAssetIdStr)
622622 let userBoostEmissionLastIntegralKEY = keyUserBoostEmissionLastINTEGRAL(userNum)
623623 let userBoostEmissionLastIntegral = valueOrElse(getInteger(this, userLpBoostEmissionLastIntegralKEY), getIntOrZero(this, userBoostEmissionLastIntegralKEY))
624624 let boostEmissionIntegral = refreshBoostEmissionIntegral()._2
625625 let userBoostEmissionIntegral = (boostEmissionIntegral - userBoostEmissionLastIntegral)
626626 if ((0 > userBoostEmissionIntegral))
627627 then throwErr("wrong calculations")
628628 else {
629629 let $t02384323982 = getStakedVotesIntegralsDiff(lpAssetIdStr, userAddressStr)
630630 let stakedVotesIntegralsActions = $t02384323982._1
631631 let userVoteIntegralDiff = $t02384323982._2
632632 let totalVotesIntegralDiff = $t02384323982._3
633633 let poolUserBoostEmissionIntegral = fraction(userBoostEmissionIntegral, poolWeight, POOLWEIGHTMULT)
634634 let userBoostAvaliableToClaimTotalNew = if ((totalVotesIntegralDiff == 0))
635635 then 0
636636 else fraction(poolUserBoostEmissionIntegral, userVoteIntegralDiff, totalVotesIntegralDiff)
637637 let dataState = ([IntegerEntry(userLpBoostEmissionLastIntegralKEY, boostEmissionIntegral)] ++ stakedVotesIntegralsActions)
638638 let debug = makeString([toString(userBoostEmissionLastIntegral), toString(userBoostEmissionIntegral), toString(poolWeight), toString(userVoteIntegralDiff), toString(totalVotesIntegralDiff)], ":")
639639 $Tuple3(userBoostAvaliableToClaimTotalNew, dataState, debug)
640640 }
641641 }
642642 else throw("Strict value is not equal to itself.")
643643 }
644644
645645
646646 func lockActions (i,duration) = {
647647 let assetIdStr = toBase58String(assetId)
648648 if ((size(i.payments) != 1))
649649 then throwErr("invalid payment - exact one payment must be attached")
650650 else {
651651 let pmt = i.payments[0]
652652 let pmtAmount = pmt.amount
653653 if ((assetId != value(pmt.assetId)))
654654 then throwErr((("invalid asset is in payment - " + assetIdStr) + " is expected"))
655655 else {
656656 let nextUserNumKEY = keyNextUserNum()
657657 let userAddress = i.caller
658658 let userAddressStr = toString(userAddress)
659659 let userIsExisting = isDefined(getString(keyUser2NumMapping(userAddressStr)))
660660 let userNumStr = if (userIsExisting)
661661 then value(getString(keyUser2NumMapping(userAddressStr)))
662662 else toString(getIntOrFail(this, nextUserNumKEY))
663663 let userNum = parseIntValue(userNumStr)
664664 let lockStart = height
665665 if (if ((minLockAmount > pmtAmount))
666666 then (userAddress != lpStakingPoolsContract)
667667 else false)
668668 then throwErr(("amount is less then minLockAmount=" + toString(minLockAmount)))
669669 else if ((minLockDuration > duration))
670670 then throwErr(("passed duration is less than minLockDuration=" + toString(minLockDuration)))
671671 else if ((duration > maxLockDuration))
672672 then throwErr(("passed duration is greater than maxLockDuration=" + toString(maxLockDuration)))
673673 else if (((duration % lockStepBlocks) != 0))
674674 then throwErr(("duration must be multiple of lockStepBlocks=" + toString(lockStepBlocks)))
675675 else {
676676 let gWxAmountStart = fraction(pmtAmount, duration, maxLockDuration)
677677 let gwxAmountTotal = getGwxAmountTotal()
678678 let userBoostEmissionLastIntegralKEY = keyUserBoostEmissionLastINTEGRAL(userNum)
679679 let boostEmissionIntegral = refreshBoostEmissionIntegral()._2
680680 let userGwxAmountTotal = getUserGwxAmountTotal(userAddress)
681681 let gwxRewardInv = invoke(gwxRewardContract, "refreshUserReward", [userAddress.bytes, userNum], nil)
682682 if ((gwxRewardInv == gwxRewardInv))
683683 then {
684684 let arr = if (userIsExisting)
685685 then nil
686686 else [IntegerEntry(nextUserNumKEY, (userNum + 1)), StringEntry(keyUser2NumMapping(userAddressStr), userNumStr), StringEntry(keyNum2UserMapping(userNumStr), userAddressStr)]
687687 $Tuple2(((((arr ++ LockParamsEntry(userAddress, i.transactionId, pmtAmount, lockStart, duration, gWxAmountStart, 0)) ++ StatsEntry(pmtAmount, duration, 1, if (userIsExisting)
688688 then 0
689689 else 1)) :+ HistoryEntry("lock", userAddressStr, pmtAmount, lockStart, duration, gWxAmountStart, i)) ++ [IntegerEntry(userBoostEmissionLastIntegralKEY, boostEmissionIntegral), IntegerEntry(keyGwxTotal(), (gwxAmountTotal + gWxAmountStart)), IntegerEntry(keyUserGwxAmountTotal(userAddress), (userGwxAmountTotal + gWxAmountStart))]), gWxAmountStart)
690690 }
691691 else throw("Strict value is not equal to itself.")
692692 }
693693 }
694694 }
695695 }
696696
697697
698698 func getWxWithdrawable (userAddress,txIdOption) = {
699699 let userRecordArray = readLockParamsRecordOrFail(userAddress, txIdOption)
700700 let userAmount = parseIntValue(userRecordArray[IdxLockAmount])
701701 let lockStart = parseIntValue(userRecordArray[IdxLockStart])
702702 let lockDuration = parseIntValue(userRecordArray[IdxLockDuration])
703703 let lockEnd = (lockStart + lockDuration)
704704 let wxClaimed = parseIntValue(userRecordArray[IdxLockWxClaimed])
705705 let t = ((height - lockStart) / blocksInPeriod)
706706 let exponent = fraction(toBigInt(t), (toBigInt((DECAY_CONSTANT * blocksInPeriod)) * MULT18BI), toBigInt(lockDuration))
707707 let wxWithdrawableTotal = if ((height > lockEnd))
708708 then userAmount
709709 else toInt(fraction(toBigInt(userAmount), (MULT18BI - pow(toBigInt(5), 1, exponent, SCALE18, SCALE18, DOWN)), MULT18BI))
710710 let wxWithdrawable = (wxWithdrawableTotal - wxClaimed)
711711 wxWithdrawable
712712 }
713713
714714
715715 @Callable(i)
716716 func lockRef (duration,referrerAddress,signature) = {
717717 let suspensionCheck = throwIfSuspended()
718718 if ((suspensionCheck == suspensionCheck))
719719 then {
720720 let $t02840028465 = lockActions(i, duration)
721721 let lockActionsResult = $t02840028465._1
722722 let gWxAmountStart = $t02840028465._2
723723 let referralAddress = toString(i.caller)
724724 let refInv = if (if ((referrerAddress == ""))
725725 then true
726726 else (signature == base58''))
727727 then unit
728728 else invoke(referralsContractAddressOrFail, "createPair", [referralProgramName, referrerAddress, referralAddress, signature], nil)
729729 if ((refInv == refInv))
730730 then {
731731 let updateRefActivity = invoke(mathContract, "updateReferralActivity", [toString(i.caller), gWxAmountStart], nil)
732732 if ((updateRefActivity == updateRefActivity))
733733 then $Tuple2(lockActionsResult, unit)
734734 else throw("Strict value is not equal to itself.")
735735 }
736736 else throw("Strict value is not equal to itself.")
737737 }
738738 else throw("Strict value is not equal to itself.")
739739 }
740740
741741
742742
743743 @Callable(i)
744744 func lock (duration) = {
745745 let suspensionCheck = throwIfSuspended()
746746 if ((suspensionCheck == suspensionCheck))
747747 then {
748748 let $t02896929034 = lockActions(i, duration)
749749 let lockActionsResult = $t02896929034._1
750750 let gWxAmountStart = $t02896929034._2
751751 let updateRefActivity = invoke(mathContract, "updateReferralActivity", [toString(i.caller), gWxAmountStart], nil)
752752 if ((updateRefActivity == updateRefActivity))
753753 then $Tuple2(lockActionsResult, unit)
754754 else throw("Strict value is not equal to itself.")
755755 }
756756 else throw("Strict value is not equal to itself.")
757757 }
758758
759759
760760
761761 @Callable(i)
762762 func claimWxBoost (lpAssetIdStr,userAddressStr) = {
763763 let suspensionCheck = throwIfSuspended()
764764 if ((suspensionCheck == suspensionCheck))
765765 then if ((stakingContract != i.caller))
766766 then throwErr("permissions denied")
767767 else {
768768 let $t02939029492 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, false)
769769 let userBoostAvailable = $t02939029492._1
770770 let dataState = $t02939029492._2
771771 let debug = $t02939029492._3
772772 $Tuple2(dataState, [userBoostAvailable])
773773 }
774774 else throw("Strict value is not equal to itself.")
775775 }
776776
777777
778778
779779 @Callable(i)
780780 func claimWxBoostREADONLY (lpAssetIdStr,userAddressStr) = {
781781 let $t02962429725 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, true)
782782 let userBoostAvailable = $t02962429725._1
783783 let dataState = $t02962429725._2
784784 let debug = $t02962429725._3
785785 $Tuple2(nil, [userBoostAvailable, debug])
786786 }
787787
788788
789789
790790 @Callable(i)
791791 func unlock (txIdStr) = {
792792 let suspensionCheck = throwIfSuspended()
793793 if ((suspensionCheck == suspensionCheck))
794794 then {
795795 let userAddress = i.caller
796796 let userAddressStr = toString(userAddress)
797797 let txIdOption = if ((txIdStr == ""))
798798 then unit
799799 else fromBase58String(txIdStr)
800800 let userRecordArray = readLockParamsRecordOrFail(userAddress, txIdOption)
801801 let userAmount = parseIntValue(userRecordArray[IdxLockAmount])
802802 let lockStart = parseIntValue(userRecordArray[IdxLockStart])
803803 let lockDuration = parseIntValue(userRecordArray[IdxLockDuration])
804804 let wxClaimed = parseIntValue(userRecordArray[IdxLockWxClaimed])
805805 let gwxAmount = parseIntValue(userRecordArray[IdxLockGwxAmount])
806806 let t = ((height - lockStart) / blocksInPeriod)
807807 let wxWithdrawable = getWxWithdrawable(userAddress, txIdOption)
808- let gWxAmountStart = fraction(userAmount, lockDuration, maxLockDuration)
809- let gwxBurned = min([fraction((t * blocksInPeriod), gWxAmountStart, maxLockDuration), gwxAmount])
808+ let gwxBurned = min([fraction(wxWithdrawable, lockDuration, maxLockDuration), gwxAmount])
810809 let gwxRemaining = ensurePositive((gwxAmount - gwxBurned), "gwxRemaining")
811810 let lockedGwxAmount = getLockedGwxAmount(userAddress)
812811 if ((0 >= wxWithdrawable))
813812 then throwErr("nothing to unlock")
814813 else {
815814 let gwxAmountTotal = getGwxAmountTotal()
816815 let userGwxAmountTotal = getUserGwxAmountTotal(userAddress)
817816 let userGwxAmountTotalNew = ensurePositive((userGwxAmountTotal - gwxBurned), "userGwxAmountTotalNew")
818817 if ((lockedGwxAmount > userGwxAmountTotalNew))
819818 then throwErr(("locked gwx amount: " + toString(lockedGwxAmount)))
820819 else {
821820 let userNum = parseIntValue(valueOrErrorMessage(getString(keyUser2NumMapping(userAddressStr)), wrapErr("invalid user number")))
822821 let gwxRewardInv = invoke(gwxRewardContract, "refreshUserReward", [userAddress.bytes, userNum], nil)
823822 if ((gwxRewardInv == gwxRewardInv))
824823 then ((((LockParamsEntry(userAddress, txIdOption, userAmount, lockStart, lockDuration, gwxRemaining, (wxClaimed + wxWithdrawable)) ++ StatsEntry(-(wxWithdrawable), 0, 0, 0)) :+ HistoryEntry("unlock", userAddressStr, wxWithdrawable, lockStart, lockDuration, gwxBurned, i)) :+ ScriptTransfer(userAddress, wxWithdrawable, assetId)) ++ [IntegerEntry(keyGwxTotal(), ensurePositive((gwxAmountTotal - gwxBurned), "gwxTotal")), IntegerEntry(keyUserGwxAmountTotal(userAddress), userGwxAmountTotalNew)])
825824 else throw("Strict value is not equal to itself.")
826825 }
827826 }
828827 }
829828 else throw("Strict value is not equal to itself.")
830829 }
831830
832831
833832
834833 @Callable(i)
835834 func gwxUserInfoREADONLY (userAddressStr) = {
836835 let userAddress = valueOrErrorMessage(addressFromString(userAddressStr), wrapErr("invalid user address"))
837836 let gwxAmount = getUserGwxAmountTotal(userAddress)
838837 $Tuple2(nil, [gwxAmount])
839838 }
840839
841840
842841
843842 @Callable(i)
844843 func userMaxDurationREADONLY (userAddressStr) = $Tuple2(nil, $Tuple2("lock", maxLockDuration))
845844
846845
847846
848847 @Callable(i)
849848 func getUserGwxAmountAtHeightREADONLY (userAddressStr,targetHeight) = {
850849 let userAddress = valueOrErrorMessage(addressFromString(userAddressStr), wrapErr("invalid user address"))
851850 let gwxAmount = getUserGwxAmountTotal(userAddress)
852851 $Tuple2(nil, gwxAmount)
853852 }
854853
855854
856855
857856 @Callable(i)
858857 func getUserGwxAmount (userAddressStr) = {
859858 let userAddress = valueOrErrorMessage(addressFromString(userAddressStr), wrapErr("invalid user address"))
860859 let gwxAmount = getUserGwxAmountTotal(userAddress)
861860 $Tuple2(nil, gwxAmount)
862861 }
863862
864863
865864
866865 @Callable(i)
867866 func getGwxTotalREADONLY () = $Tuple2(nil, getGwxAmountTotal())
868867
869868
870869
871870 @Callable(i)
872871 func onBoostEmissionUpdate () = {
873872 let suspensionCheck = throwIfSuspended()
874873 if ((suspensionCheck == suspensionCheck))
875874 then {
876875 let checkCaller = if ((i.caller == emissionContract))
877876 then true
878877 else mustManager(i)
879878 if ((checkCaller == checkCaller))
880879 then refreshBoostEmissionIntegral()
881880 else throw("Strict value is not equal to itself.")
882881 }
883882 else throw("Strict value is not equal to itself.")
884883 }
885884
886885
887886
888887 @Callable(i)
889888 func onStakedVoteUpdate (lpAssetIdStr,userAddressStr,edge) = {
890889 let suspensionCheck = throwIfSuspended()
891890 if ((suspensionCheck == suspensionCheck))
892891 then {
893892 let checkCaller = if ((i.caller == stakingContract))
894893 then true
895894 else mustManager(i)
896895 if ((checkCaller == checkCaller))
897896 then {
898897 let actions = refreshVoteStakedIntegral(lpAssetIdStr, userAddressStr, edge)
899898 $Tuple2(actions, unit)
900899 }
901900 else throw("Strict value is not equal to itself.")
902901 }
903902 else throw("Strict value is not equal to itself.")
904903 }
905904
906905
907906
908907 @Callable(i)
909908 func getVotingResultStakedREADONLY (lpAssetIdStr) = $Tuple2(nil, getVotingResultStaked(lpAssetIdStr))
910909
911910
912911
913912 @Callable(i)
914913 func getVotingResultStakedIntegralREADONLY (lpAssetIdStr) = $Tuple2(nil, getVotingResultStakedIntegral(lpAssetIdStr))
915914
916915
917916
918917 @Callable(i)
919918 func getUserVoteFinalizedREADONLY (lpAssetIdStr,userAddressStr) = $Tuple2(nil, getUserVoteFinalized(lpAssetIdStr, userAddressStr))
920919
921920
922921
923922 @Callable(i)
924923 func getUserVoteStakedIntegralREADONLY (lpAssetIdStr,userAddressStr) = $Tuple2(nil, getUserVoteStakedIntegral(lpAssetIdStr, userAddressStr))
925924
926925
927926
928927 @Callable(i)
929928 func suspend (v) = {
930929 let checkCaller = mustManager(i)
931930 if ((checkCaller == checkCaller))
932931 then $Tuple2([BooleanEntry(keySuspension, v)], v)
933932 else throw("Strict value is not equal to itself.")
934933 }
935934
936935
937936 @Verifier(tx)
938937 func verify () = {
939938 let targetPublicKey = match managerPublicKeyOrUnit() {
940939 case pk: ByteVector =>
941940 pk
942941 case _: Unit =>
943942 tx.senderPublicKey
944943 case _ =>
945944 throw("Match error")
946945 }
947946 sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey)
948947 }
949948

github/deemru/w8io/3ef1775 
138.54 ms