tx · 3awN8tJzzznenm1XGSb73ms6H8B3jvQV225UoY9b9Aio

3PLDtdSudp3ao5WWU4EzXC6D7TQm7t3dSWC:  -0.03100000 Waves

2023.05.10 15:27 [3637252] smart account 3PLDtdSudp3ao5WWU4EzXC6D7TQm7t3dSWC > SELF 0.00000000 Waves

{ "type": 13, "id": "3awN8tJzzznenm1XGSb73ms6H8B3jvQV225UoY9b9Aio", "fee": 3100000, "feeAssetId": null, "timestamp": 1683721726550, "version": 2, "chainId": 87, "sender": "3PLDtdSudp3ao5WWU4EzXC6D7TQm7t3dSWC", "senderPublicKey": "3g4LaykUG5wGWdSeML6WkuKVnzkREN7uAWEK1UR1uUGB", "proofs": [ "4kEkjAJ75fQxaAhgete6bBkbvBHSKLxZX4rNDBD6yLrhzPPA8jz7Y6nVUCFVNSYttSHQV2L4AiJoTcxbSJW93fv" ], "script": "base64:BgI7CAISEAoOCAgIAQgBAQEIAQEBAQgSAwoBARIAEgASBQoDCAgIEgUKAwgICBIDCgEIEgQKAggBEgMKAQhTAANTRVACAl9fAQ9nZXRTdHJpbmdPckZhaWwBA2tleQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFBHRoaXMFA2tleQkArAICAhVObyBkYXRhIGZvciB0aGlzLmtleT0FA2tleQEQZ2V0Qm9vbGVhbk9yRmFpbAEDa2V5CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJsIAgUEdGhpcwUDa2V5CQCsAgICFU5vIGRhdGEgZm9yIHRoaXMua2V5PQUDa2V5AQxnZXRJbnRPckZhaWwBA2tleQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFBHRoaXMFA2tleQkArAICAhVObyBkYXRhIGZvciB0aGlzLmtleT0FA2tleQEESW50RQIDa2V5A3ZhbAkBDEludGVnZXJFbnRyeQIFA2tleQUDdmFsAQRTdHJFAgNrZXkDdmFsCQELU3RyaW5nRW50cnkCBQNrZXkFA3ZhbAEOZmFpbEV4ZWN1dGVHZXQFA21zZwxiYXNlQXNzZXRTdHIOdXNlckFkZHJlc3NTdHINc3VibWl0VHhJZFN0cg1vcGVyYXRpb25UeXBlCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIFA21zZwIMOiBiYXNlQXNzZXQ9BQxiYXNlQXNzZXRTdHICDSB1c2VyQWRkcmVzcz0FDnVzZXJBZGRyZXNzU3RyAgwgc3VibWl0VHhJZD0FDXN1Ym1pdFR4SWRTdHICCyBvcGVyYXRpb249BQ1vcGVyYXRpb25UeXBlARdmYWlsU3VibWl0TGltaXRzRXhjZWVkcwQNcmVtYWluaW5nQmFzZQ5yZW1haW5pbmdTaGFyZRBuZXdSZW1haW5pbmdCYXNlEW5ld1JlbWFpbmluZ1NoYXJlCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICK3N1Ym1pdCBvcGVyYXRpb24gbGltaXRzIGhhdmUgYmVlbiByZWFjaGVkOiACEiByZW1haW5pbmdCYXNlVmFsPQkApAMBBQ1yZW1haW5pbmdCYXNlAhMgcmVtYWluaW5nU2hhcmVWYWw9CQCkAwEFDnJlbWFpbmluZ1NoYXJlAhUgbmV3UmVtYWluaW5nQmFzZVZhbD0JAKQDAQUQbmV3UmVtYWluaW5nQmFzZQIWIG5ld1JlbWFpbmluZ1NoYXJlVmFsPQkApAMBBRFuZXdSZW1haW5pbmdTaGFyZQEUZmFpbFRvcHVwTWFuYWdlck9ubHkBE3RvcHVwTWFuYWdlckFkZHJlc3MJAAIBCQCsAgIJAKwCAgIjb3BlcnRpb24gZGVuaWVkOiBvbmx5IHRvcFVwTWFuYWdlcj0FE3RvcHVwTWFuYWdlckFkZHJlc3MCGyBjYW4gc2VuZCBzdWNoIHRyYW5zYWN0aW9ucwERY29udmVydFNoYXJlMkJhc2UDC3NoYXJlQW1vdW50BXByaWNlCXByaWNlTXVsdAkAawMFC3NoYXJlQW1vdW50BQVwcmljZQUJcHJpY2VNdWx0ARFjb252ZXJ0QmFzZTJTaGFyZQMKYmFzZUFtb3VudAVwcmljZQlwcmljZU11bHQJAGsDBQpiYXNlQW1vdW50BQlwcmljZU11bHQFBXByaWNlAQtrZXlBc3NldENmZwEMYmFzZUFzc2V0U3RyCQCsAgICFyVzJXMlc19fY29uZmlnX19hc3NldF9fBQxiYXNlQXNzZXRTdHIBFmtleU5leHRJbnRlcm5hbEFzc2V0SWQAAhclc19fbmV4dEludGVybmFsQXNzZXRJZAEMa2V5UHJpY2VMYXN0ARVpbnRlcm5hbEJhc2V0QXNzZXRTdHIJAKwCAgIVJXMlcyVkX19wcmljZV9fbGFzdF9fBRVpbnRlcm5hbEJhc2V0QXNzZXRTdHIBC2tleVByaWNlQVRIARVpbnRlcm5hbEJhc2V0QXNzZXRTdHIJAKwCAgIUJXMlcyVkX19wcmljZV9fYXRoX18FFWludGVybmFsQmFzZXRBc3NldFN0cgESa2V5UHJpY2VCeVRvcFVwSWR4AhRpbnRlcm5hbEJhc2VBc3NldFN0cgh0b3BVcElkeAkAuQkCCQDMCAICGyVzJXMlZCVkX19wcmljZV9fYnlUb3BVcElkeAkAzAgCBRRpbnRlcm5hbEJhc2VBc3NldFN0cgkAzAgCCQCkAwEFCHRvcFVwSWR4BQNuaWwFA1NFUAEPa2V5UHJpY2VIaXN0b3J5AxVpbnRlcm5hbEJhc2V0QXNzZXRTdHIBaAl0aW1lc3RhbXAJALkJAgkAzAgCAholcyVzJWQlZCVkX19wcmljZV9faGlzdG9yeQkAzAgCBRVpbnRlcm5hbEJhc2V0QXNzZXRTdHIJAMwIAgkApAMBBQFoCQDMCAIJAKQDAQUJdGltZXN0YW1wBQNuaWwFA1NFUAEOa2V5VG90YWxMb2NrZWQBFWludGVybmFsQmFzZXRBc3NldFN0cgkArAICAhclcyVzJWRfX3RvdGFsX19sb2NrZWRfXwUVaW50ZXJuYWxCYXNldEFzc2V0U3RyARRrZXlUb3RhbExvY2tlZEJ5VXNlcgIUaW50ZXJuYWxCYXNlQXNzZXRTdHIOdXNlckFkZHJlc3NTdHIJALkJAgkAzAgCAhclcyVzJWQlc19fdG90YWxfX2xvY2tlZAkAzAgCBRRpbnRlcm5hbEJhc2VBc3NldFN0cgkAzAgCBQ51c2VyQWRkcmVzc1N0cgUDbmlsBQNTRVABH2tleU1hcHBpbmdzSW50ZXJuYWwyYmFzZUFzc2V0SWQBEWludGVybmFsQmFzZUFzc2V0CQCsAgICKCVzJXMlZF9fbWFwcGluZ3NfX2ludGVybmFsMmJhc2VBc3NldElkX18JAKQDAQURaW50ZXJuYWxCYXNlQXNzZXQBH2tleU1hcHBpbmdzQmFzZUFzc2V0MmludGVybmFsSWQBDGJhc2VBc3NldFN0cgkArAICAiglcyVzJXNfX21hcHBpbmdzX19iYXNlQXNzZXQyaW50ZXJuYWxJZF9fBQxiYXNlQXNzZXRTdHIBHGtleU1hcHBpbmdzU2hhcmUyYmFzZUFzc2V0SWQBDXNoYXJlQXNzZXRTdHIJAKwCAgIlJXMlcyVzX19tYXBwaW5nc19fc2hhcmUyYmFzZUFzc2V0SWRfXwUNc2hhcmVBc3NldFN0cgEca2V5TWFwcGluZ3NCYXNlQXNzZXQyc2hhcmVJZAEMYmFzZUFzc2V0U3RyCQCsAgICJSVzJXMlc19fbWFwcGluZ3NfX2Jhc2VBc3NldDJzaGFyZUlkX18FDGJhc2VBc3NldFN0cgEaa2V5U2h1dGRvd25TdWJtaXRPcGVyYXRpb24BFGludGVybmFsQmFzZUFzc2V0U3RyCQCsAgICGiVzJXMlZF9fc2h1dGRvd25fX3N1Ym1pdF9fBRRpbnRlcm5hbEJhc2VBc3NldFN0cgESa2V5U2h1dGRvd25NYW5hZ2VyARRpbnRlcm5hbEJhc2VBc3NldFN0cgkArAICAhslcyVzJWRfX3NodXRkb3duX19tYW5hZ2VyX18FFGludGVybmFsQmFzZUFzc2V0U3RyARJrZXlUb3BVcEN1cnJlbnRJZHgBFGludGVybmFsQmFzZUFzc2V0U3RyCQCsAgICGyVzJXMlZF9fdG9wdXBfX2N1cnJlbnRJZHhfXwUUaW50ZXJuYWxCYXNlQXNzZXRTdHIBEmtleVRvcFVwTGFzdEhlaWdodAIVaW50ZXJuYWxCYXNldEFzc2V0U3RyBnNlbmRlcgkAuQkCCQDMCAICHyVzJXMlcyVkJXNfX3RvcHVwX19sYXN0X19oZWlnaHQJAMwIAgUVaW50ZXJuYWxCYXNldEFzc2V0U3RyCQDMCAIFBnNlbmRlcgUDbmlsBQNTRVABDmtleVRvcHVwTXV0ZXh0ARVpbnRlcm5hbEJhc2V0QXNzZXRTdHIJAKwCAgIWJXMlcyVkX190b3B1cF9fbXV0ZXhfXwUVaW50ZXJuYWxCYXNldEFzc2V0U3RyARVrZXlUb3B1cExhc3RUaW1lc3RhbXABFWludGVybmFsQmFzZXRBc3NldFN0cgkArAICAiIlcyVzJXMlZF9fdG9wdXBfX2xhc3RfX3RpbWVzdGFtcF9fBRVpbnRlcm5hbEJhc2V0QXNzZXRTdHIBD2tleVRvcHVwSGlzdG9yeQIVaW50ZXJuYWxCYXNldEFzc2V0U3RyCHRvcHVwSWR4CQC5CQIJAMwIAgIYJXMlcyVkJWRfX3RvcHVwX19oaXN0b3J5CQDMCAIFFWludGVybmFsQmFzZXRBc3NldFN0cgkAzAgCCQCkAwEFCHRvcHVwSWR4BQNuaWwFA1NFUAESa2V5TGltaXRzUmVtYWluaW5nARVpbnRlcm5hbEJhc2V0QXNzZXRTdHIJAKwCAgIbJXMlcyVkX19saW1pdHNfX3JlbWFpbmluZ19fBRVpbnRlcm5hbEJhc2V0QXNzZXRTdHIBFmtleU1hbmFnZXJWYXVsdEFkZHJlc3MAAhclc19fbWFuYWdlclZhdWx0QWRkcmVzcwETa2V5TWFuYWdlclB1YmxpY0tleQACFCVzX19tYW5hZ2VyUHVibGljS2V5ABJJZHhDZmdTaGFyZUFzc2V0SWQAAQAXSWR4Q2ZnSW50ZXJuYWxCYXNlQXNzZXQAAgAcSWR4Q2ZnRGVjaW1hbHNNdWx0Qm90aEFzc2V0cwADABdJZHhDZmdEZWNpbWFsc011bHRQcmljZQAEABRJZHhDZmdHZXREZWxheUJsb2NrcwAFABtJZHhDZmdUb3B1cEludGVydmFsSW5CbG9ja3MABgAaSWR4Q2ZnVG9wdXBNYXhOZWdhdGl2ZVBhcnQABwAZSWR4Q2ZnVG9wdXBNYW5hZ2VyQWRkcmVzcwAIABlJZHhDZmdTdWJtaXRMaW1pdHNCYXNlTWF4AAkAG0lkeENmZ1N1Ym1pdExpbWl0c0Jhc2VSZXNldAAKABpJZHhDZmdTdWJtaXRMaW1pdHNTaGFyZU1heAALABxJZHhDZmdTdWJtaXRMaW1pdHNTaGFyZVJlc2V0AAwAEklkeENmZ0FkbWluQWRkcmVzcwANAQxkYXRhQXNzZXRDZmcNDXNoYXJlQXNzZXRTdHIUaW50ZXJuYWxCYXNlQXNzZXRTdHIWZGVjaW1hbHNNdWx0Qm90aEFzc2V0cxFkZWNpbWFsc011bHRQcmljZRBnZXREZWxheUluQmxvY2tzFXRvcHVwSW50ZXJ2YWxJbkJsb2NrcxR0b3B1cE1heE5lZ2F0aXZlUGFydBN0b3B1cE1hbmFnZXJBZGRyZXNzE3N1Ym1pdExpbWl0c0Jhc2VNYXgVc3VibWl0TGltaXRzQmFzZVJlc2V0FHN1Ym1pdExpbWl0c1NoYXJlTWF4FnN1Ym1pdExpbWl0c1NoYXJlUmVzZXQMYWRtaW5BZGRyZXNzCQC5CQIJAMwIAgIYJXMlZCVkJWQlZCVkJWQlcyVkJWQlZCVkCQDMCAIFDXNoYXJlQXNzZXRTdHIJAMwIAgUUaW50ZXJuYWxCYXNlQXNzZXRTdHIJAMwIAgkApAMBBRZkZWNpbWFsc011bHRCb3RoQXNzZXRzCQDMCAIJAKQDAQURZGVjaW1hbHNNdWx0UHJpY2UJAMwIAgkApAMBBRBnZXREZWxheUluQmxvY2tzCQDMCAIJAKQDAQUVdG9wdXBJbnRlcnZhbEluQmxvY2tzCQDMCAIJAKQDAQUUdG9wdXBNYXhOZWdhdGl2ZVBhcnQJAMwIAgUTdG9wdXBNYW5hZ2VyQWRkcmVzcwkAzAgCCQCkAwEFE3N1Ym1pdExpbWl0c0Jhc2VNYXgJAMwIAgkApAMBBRVzdWJtaXRMaW1pdHNCYXNlUmVzZXQJAMwIAgkApAMBBRRzdWJtaXRMaW1pdHNTaGFyZU1heAkAzAgCCQCkAwEFFnN1Ym1pdExpbWl0c1NoYXJlUmVzZXQJAMwIAgUMYWRtaW5BZGRyZXNzBQNuaWwFA1NFUAAVSWR4VG90YWxMb2NrZWRJblNoYXJlAAEAFUlkeFRvdGFsTG9ja2VkT3V0QmFzZQACABRJZHhUb3RhbExvY2tlZEluQmFzZQADABZJZHhUb3RhbExvY2tlZE91dFNoYXJlAAQBD2RhdGFUb3RhbExvY2tlZAQNaW5TaGFyZUFtb3VudA1vdXRCYXNlQW1vdW50DGluQmFzZUFtb3VudA5vdXRTaGFyZUFtb3VudAkAuQkCCQDMCAICCCVkJWQlZCVkCQDMCAIJAKQDAQUNaW5TaGFyZUFtb3VudAkAzAgCCQCkAwEFDW91dEJhc2VBbW91bnQJAMwIAgkApAMBBQxpbkJhc2VBbW91bnQJAMwIAgkApAMBBQ5vdXRTaGFyZUFtb3VudAUDbmlsBQNTRVABEmRhdGFUb3RhbExvY2tlZEludAQNaW5TaGFyZUFtb3VudA1vdXRCYXNlQW1vdW50DGluQmFzZUFtb3VudA5vdXRTaGFyZUFtb3VudAkAzAgCAP///////////wEJAMwIAgUNaW5TaGFyZUFtb3VudAkAzAgCBQ1vdXRCYXNlQW1vdW50CQDMCAIFDGluQmFzZUFtb3VudAkAzAgCBQ5vdXRTaGFyZUFtb3VudAUDbmlsAQ9yZWFkVG90YWxMb2NrZWQBA2tleQQQdG90YWxMb2NrZWRBcnJheQkAtQkCCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMFA2tleQkBD2RhdGFUb3RhbExvY2tlZAQAAAAAAAAAAAUDU0VQCQESZGF0YVRvdGFsTG9ja2VkSW50BAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFEHRvdGFsTG9ja2VkQXJyYXkFFUlkeFRvdGFsTG9ja2VkSW5TaGFyZQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFEHRvdGFsTG9ja2VkQXJyYXkFFUlkeFRvdGFsTG9ja2VkT3V0QmFzZQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFEHRvdGFsTG9ja2VkQXJyYXkFFElkeFRvdGFsTG9ja2VkSW5CYXNlCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUQdG90YWxMb2NrZWRBcnJheQUWSWR4VG90YWxMb2NrZWRPdXRTaGFyZQETY2FsY1RvdGFsTG9ja2VkRGlmZggJZGlyZWN0aW9uDW9wZXJhdGlvblR5cGUUaW50ZXJuYWxCYXNlQXNzZXRTdHIFcHJpY2UJcHJpY2VNdWx0CGluQW1vdW50C2Jhc2VBc3NldElkDHNoYXJlQXNzZXRJZAQBdAkArAICBQlkaXJlY3Rpb24FDW9wZXJhdGlvblR5cGUDCQAAAgUBdAIHc3VibWl0UAQJdG90YWxEaWZmCQESZGF0YVRvdGFsTG9ja2VkSW50BAAAAAAFCGluQW1vdW50AAAECHVzZXJEaWZmBQl0b3RhbERpZmYJAJYKBAUJdG90YWxEaWZmBQh1c2VyRGlmZgAACQDZBAECAAMJAAACBQF0AgdzdWJtaXRHBAl0b3RhbERpZmYJARJkYXRhVG90YWxMb2NrZWRJbnQEBQhpbkFtb3VudAAAAAAAAAQIdXNlckRpZmYFCXRvdGFsRGlmZgkAlgoEBQl0b3RhbERpZmYFCHVzZXJEaWZmAAAJANkEAQIAAwkAAAIFAXQCCGV4ZWN1dGVQBAlvdXRBbW91bnQJARFjb252ZXJ0QmFzZTJTaGFyZQMFCGluQW1vdW50BQVwcmljZQUJcHJpY2VNdWx0BAl0b3RhbERpZmYJARJkYXRhVG90YWxMb2NrZWRJbnQEAAAAAAAABQlvdXRBbW91bnQECHVzZXJEaWZmCQESZGF0YVRvdGFsTG9ja2VkSW50BAAAAAAFCGluQW1vdW50AAAJAJYKBAUJdG90YWxEaWZmBQh1c2VyRGlmZgUJb3V0QW1vdW50BQxzaGFyZUFzc2V0SWQDCQAAAgUBdAIIZXhlY3V0ZUcECW91dEFtb3VudAkBEWNvbnZlcnRTaGFyZTJCYXNlAwUIaW5BbW91bnQFBXByaWNlBQlwcmljZU11bHQECXRvdGFsRGlmZgkBEmRhdGFUb3RhbExvY2tlZEludAQAAAUJb3V0QW1vdW50AAAAAAQIdXNlckRpZmYJARJkYXRhVG90YWxMb2NrZWRJbnQEBQhpbkFtb3VudAAAAAAAAAkAlgoEBQl0b3RhbERpZmYFCHVzZXJEaWZmBQlvdXRBbW91bnQFC2Jhc2VBc3NldElkAwkAAAIFAXQCBXRvcHVwBBB0b3RhbExvY2tlZEFycmF5CQEPcmVhZFRvdGFsTG9ja2VkAQkBDmtleVRvdGFsTG9ja2VkAQUUaW50ZXJuYWxCYXNlQXNzZXRTdHIEF3RvdGFsTG9ja2VkSW5CYXNlQW1vdW50CQCRAwIFEHRvdGFsTG9ja2VkQXJyYXkFFElkeFRvdGFsTG9ja2VkSW5CYXNlBBh0b3RhbExvY2tlZEluU2hhcmVBbW91bnQJAJEDAgUQdG90YWxMb2NrZWRBcnJheQUVSWR4VG90YWxMb2NrZWRJblNoYXJlBAl0b3RhbERpZmYJARJkYXRhVG90YWxMb2NrZWRJbnQEBRh0b3RhbExvY2tlZEluU2hhcmVBbW91bnQJAGgCAP///////////wEJARFjb252ZXJ0U2hhcmUyQmFzZQMFGHRvdGFsTG9ja2VkSW5TaGFyZUFtb3VudAUFcHJpY2UFCXByaWNlTXVsdAUXdG90YWxMb2NrZWRJbkJhc2VBbW91bnQJAGgCAP///////////wEJARFjb252ZXJ0QmFzZTJTaGFyZQMFF3RvdGFsTG9ja2VkSW5CYXNlQW1vdW50BQVwcmljZQUJcHJpY2VNdWx0CQCWCgQFCXRvdGFsRGlmZgUDbmlsAAAJANkEAQIACQACAQkArAICAhFVbnN1cHBvcnRlZCBUeXBlIAUBdAEWVG90YWxMb2NrZWRTdHJpbmdFbnRyeQMGYWN0aW9uA2tleQRkaWZmCgEGVVBEQVRFAgFhAWIDCQAAAgUGYWN0aW9uAglJTkNSRU1FTlQJAGQCBQFhBQFiAwkAAAIFBmFjdGlvbgIJREVDUkVNRU5UCQBlAgUBYQUBYgkAAgEJAKwCAgITVW5zdXBwb3J0ZWQgYWN0aW9uIAUGYWN0aW9uBAlkYXRhQXJyYXkJAQ9yZWFkVG90YWxMb2NrZWQBBQNrZXkJAQRTdHJFAgUDa2V5CQEPZGF0YVRvdGFsTG9ja2VkBAkBBlVQREFURQIJAJEDAgUJZGF0YUFycmF5BRVJZHhUb3RhbExvY2tlZEluU2hhcmUJAJEDAgUEZGlmZgUVSWR4VG90YWxMb2NrZWRJblNoYXJlCQEGVVBEQVRFAgkAkQMCBQlkYXRhQXJyYXkFFUlkeFRvdGFsTG9ja2VkT3V0QmFzZQkAkQMCBQRkaWZmBRVJZHhUb3RhbExvY2tlZE91dEJhc2UJAQZVUERBVEUCCQCRAwIFCWRhdGFBcnJheQUUSWR4VG90YWxMb2NrZWRJbkJhc2UJAJEDAgUEZGlmZgUUSWR4VG90YWxMb2NrZWRJbkJhc2UJAQZVUERBVEUCCQCRAwIFCWRhdGFBcnJheQUWSWR4VG90YWxMb2NrZWRPdXRTaGFyZQkAkQMCBQRkaWZmBRZJZHhUb3RhbExvY2tlZE91dFNoYXJlAQxrZXlPcGVyYXRpb24EDW9wZXJhdGlvblR5cGUUaW50ZXJuYWxCYXNlQXNzZXRTdHILdXNlckFkZHJlc3MEdHhJZAkAuQkCCQDMCAICCCVzJWQlcyVzCQDMCAIFDW9wZXJhdGlvblR5cGUJAMwIAgUUaW50ZXJuYWxCYXNlQXNzZXRTdHIJAMwIAgULdXNlckFkZHJlc3MJAMwIAgUEdHhJZAUDbmlsBQNTRVAADUlkeE9wZXJTdGF0dXMAAQAPSWR4T3BlckluQW1vdW50AAIADElkeE9wZXJQcmljZQADABBJZHhPcGVyT3V0QW1vdW50AAQAEklkeE9wZXJTdGFydEhlaWdodAAFABVJZHhPcGVyU3RhcnRUaW1lc3RhbXAABgAQSWR4T3BlckVuZEhlaWdodAAHABNJZHhPcGVyRW5kVGltZXN0YW1wAAgAFUlkeE9wZXJUb3B1cFVubG9ja0lkeAAJAR5wcml2YXRlRGF0YU9wZXJhdGlvbkFsbFN0cmluZ3MJBnN0YXR1cw1pbkFzc2V0QW1vdW50BXByaWNlDm91dEFzc2V0QW1vdW50C3N0YXJ0SGVpZ2h0DnN0YXJ0VGltZXN0YW1wCWVuZEhlaWdodAxlbmRUaW1lc3RhbXAEbG9jawkAuQkCCQDMCAICEiVzJWQlZCVkJWQlZCVkJWQlZAkAzAgCBQZzdGF0dXMJAMwIAgUNaW5Bc3NldEFtb3VudAkAzAgCBQVwcmljZQkAzAgCBQ5vdXRBc3NldEFtb3VudAkAzAgCBQtzdGFydEhlaWdodAkAzAgCBQ5zdGFydFRpbWVzdGFtcAkAzAgCBQllbmRIZWlnaHQJAMwIAgUMZW5kVGltZXN0YW1wCQDMCAIFBGxvY2sFA25pbAUDU0VQAQ1kYXRhT3BlcmF0aW9uCQZzdGF0dXMNaW5Bc3NldEFtb3VudAVwcmljZQ5vdXRBc3NldEFtb3VudAtzdGFydEhlaWdodA5zdGFydFRpbWVzdGFtcAllbmRIZWlnaHQMZW5kVGltZXN0YW1wDnRvcHVwVW5sb2NrSWR4CQEecHJpdmF0ZURhdGFPcGVyYXRpb25BbGxTdHJpbmdzCQUGc3RhdHVzCQCkAwEFDWluQXNzZXRBbW91bnQJAKQDAQUFcHJpY2UJAKQDAQUOb3V0QXNzZXRBbW91bnQJAKQDAQULc3RhcnRIZWlnaHQJAKQDAQUOc3RhcnRUaW1lc3RhbXAJAKQDAQUJZW5kSGVpZ2h0CQCkAwEFDGVuZFRpbWVzdGFtcAkApAMBBQ50b3B1cFVubG9ja0lkeAEcZGF0YU9wZXJhdGlvbkV4ZWN1dGlvblVwZGF0ZQQNY3Vyck9wZXJBcnJheQluZXdTdGF0dXMIbmV3UHJpY2UMbmV3T3V0QW1vdW50CQEecHJpdmF0ZURhdGFPcGVyYXRpb25BbGxTdHJpbmdzCQUJbmV3U3RhdHVzCQCRAwIFDWN1cnJPcGVyQXJyYXkFD0lkeE9wZXJJbkFtb3VudAkApAMBBQhuZXdQcmljZQkApAMBBQxuZXdPdXRBbW91bnQJAJEDAgUNY3Vyck9wZXJBcnJheQUSSWR4T3BlclN0YXJ0SGVpZ2h0CQCRAwIFDWN1cnJPcGVyQXJyYXkFFUlkeE9wZXJTdGFydFRpbWVzdGFtcAkApAMBBQZoZWlnaHQJAKQDAQgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAJEDAgUNY3Vyck9wZXJBcnJheQUVSWR4T3BlclRvcHVwVW5sb2NrSWR4ARJyZWFkQXNzZXRDZmdPckZhaWwBDGJhc2VBc3NldFN0cgQDa2V5CQELa2V5QXNzZXRDZmcBBQxiYXNlQXNzZXRTdHIJALUJAgkBD2dldFN0cmluZ09yRmFpbAEFA2tleQUDU0VQABZJZHhMaW1pdHNSZW1haW5pbmdCYXNlAAEAF0lkeExpbWl0c1JlbWFpbmluZ1NoYXJlAAIBGlJlbWFpbmluZ0xpbWl0c1N0cmluZ0VudHJ5AwNrZXkSYmFzZVJlbWFpbmluZ0xpbWl0E3NoYXJlUmVtYWluaW5nTGltaXQJAQRTdHJFAgUDa2V5CQC5CQIJAMwIAgIEJWQlZAkAzAgCCQCkAwEFEmJhc2VSZW1haW5pbmdMaW1pdAkAzAgCCQCkAwEFE3NoYXJlUmVtYWluaW5nTGltaXQFA25pbAUDU0VQARJUb3B1cE11dGV4SW50RW50cnkCFGludGVybmFsQmFzZUFzc2V0U3RyDmFjcXVpcmVkSGVpZ2h0CQEESW50RQIJAQ5rZXlUb3B1cE11dGV4dAEFFGludGVybmFsQmFzZUFzc2V0U3RyBQ5hY3F1aXJlZEhlaWdodAEQZ2VuZXJpY0NhbGNQcmljZQUUaW50ZXJuYWxCYXNlQXNzZXRTdHILYmFzZUFzc2V0SWQPdG9wVXBCYXNlQW1vdW50DHNoYXJlQXNzZXRJZBFkZWNpbWFsc011bHRQcmljZQQQdG90YWxMb2NrZWRBcnJheQkBD3JlYWRUb3RhbExvY2tlZAEJAQ5rZXlUb3RhbExvY2tlZAEFFGludGVybmFsQmFzZUFzc2V0U3RyBBh0b3RhbExvY2tlZE91dEJhc2VBbW91bnQJAJEDAgUQdG90YWxMb2NrZWRBcnJheQUVSWR4VG90YWxMb2NrZWRPdXRCYXNlBBljdXJySXRlclRvdGFsSW5CYXNlQW1vdW50CQCRAwIFEHRvdGFsTG9ja2VkQXJyYXkFFElkeFRvdGFsTG9ja2VkSW5CYXNlBBBiYXNlQXNzZXRCYWxhbmNlCQDwBwIFBHRoaXMFC2Jhc2VBc3NldElkBBNiYXNlQXNzZXRCYWxhbmNlV0NPCQBlAgkAZQIJAGQCBRBiYXNlQXNzZXRCYWxhbmNlBQ90b3BVcEJhc2VBbW91bnQFGWN1cnJJdGVyVG90YWxJbkJhc2VBbW91bnQFGHRvdGFsTG9ja2VkT3V0QmFzZUFtb3VudAQZdG90YWxMb2NrZWRPdXRTaGFyZUFtb3VudAkAkQMCBRB0b3RhbExvY2tlZEFycmF5BRZJZHhUb3RhbExvY2tlZE91dFNoYXJlBBpjdXJySXRlclRvdGFsSW5TaGFyZUFtb3VudAkAkQMCBRB0b3RhbExvY2tlZEFycmF5BRVJZHhUb3RhbExvY2tlZEluU2hhcmUEDXNoYXJlRW1pc3Npb24ICQEFdmFsdWUBCQDsBwEFDHNoYXJlQXNzZXRJZAhxdWFudGl0eQMJAGYCAAAFE2Jhc2VBc3NldEJhbGFuY2VXQ08JAAIBCQCsAgIJAKwCAgkArAICAitiYXNlQXNzZXRCYWxhbmNlV2NvIDwgMDogYmFzZUFzc2V0dEJhbGFuY2U9CQCkAwEFEGJhc2VBc3NldEJhbGFuY2UCFSBiYXNlQXNzZXRCYWxhbmNlV2NvPQkApAMBBRNiYXNlQXNzZXRCYWxhbmNlV0NPBAlsYXN0UHJpY2UJAQxnZXRJbnRPckZhaWwBCQEMa2V5UHJpY2VMYXN0AQUUaW50ZXJuYWxCYXNlQXNzZXRTdHIEBXByaWNlAwkAAAIFDXNoYXJlRW1pc3Npb24AAAUJbGFzdFByaWNlCQBrAwUTYmFzZUFzc2V0QmFsYW5jZVdDTwURZGVjaW1hbHNNdWx0UHJpY2UFDXNoYXJlRW1pc3Npb24JAJsKCQUFcHJpY2UFEGJhc2VBc3NldEJhbGFuY2UA////////////AQUTYmFzZUFzc2V0QmFsYW5jZVdDTwUNc2hhcmVFbWlzc2lvbgUZY3Vyckl0ZXJUb3RhbEluQmFzZUFtb3VudAUaY3Vyckl0ZXJUb3RhbEluU2hhcmVBbW91bnQFGHRvdGFsTG9ja2VkT3V0QmFzZUFtb3VudAUZdG90YWxMb2NrZWRPdXRTaGFyZUFtb3VudAEJY2FsY1ByaWNlBBRpbnRlcm5hbEJhc2VBc3NldFN0cgtiYXNlQXNzZXRJZAxzaGFyZUFzc2V0SWQRZGVjaW1hbHNNdWx0UHJpY2UJARBnZW5lcmljQ2FsY1ByaWNlBQUUaW50ZXJuYWxCYXNlQXNzZXRTdHIFC2Jhc2VBc3NldElkAAAFDHNoYXJlQXNzZXRJZAURZGVjaW1hbHNNdWx0UHJpY2UBHGdldE1hbmFnZXJWYXVsdEFkZHJlc3NPclRoaXMABAckbWF0Y2gwCQCiCAEJARZrZXlNYW5hZ2VyVmF1bHRBZGRyZXNzAAMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAXMFByRtYXRjaDAJARFAZXh0ck5hdGl2ZSgxMDYyKQEFAXMFBHRoaXMBFm1hbmFnZXJQdWJsaWNLZXlPclVuaXQABBNtYW5hZ2VyVmF1bHRBZGRyZXNzCQEcZ2V0TWFuYWdlclZhdWx0QWRkcmVzc09yVGhpcwAEByRtYXRjaDAJAJ0IAgUTbWFuYWdlclZhdWx0QWRkcmVzcwkBE2tleU1hbmFnZXJQdWJsaWNLZXkAAwkAAQIFByRtYXRjaDACBlN0cmluZwQBcwUHJG1hdGNoMAkA2QQBBQFzAwkAAQIFByRtYXRjaDACBFVuaXQFBHVuaXQJAAIBAgtNYXRjaCBlcnJvcgEJaXNNYW5hZ2VyAQFpBAckbWF0Y2gwCQEWbWFuYWdlclB1YmxpY0tleU9yVW5pdAADCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQCcGsFByRtYXRjaDAJAAACCAUBaQ9jYWxsZXJQdWJsaWNLZXkFAnBrAwkAAQIFByRtYXRjaDACBFVuaXQJAAACCAUBaQZjYWxsZXIFBHRoaXMJAAIBAgtNYXRjaCBlcnJvcgELbXVzdE1hbmFnZXIBAWkDCQEJaXNNYW5hZ2VyAQUBaQYJAAIBAhFwZXJtaXNzaW9uIGRlbmllZAEMY29tbW9uU3VibWl0BQ1vcGVyYXRpb25UeXBlAWkIaW5BbW91bnQJaW5Bc3NldElkDGJhc2VBc3NldFN0cgQKaW5Bc3NldFN0cgkA2AQBBQlpbkFzc2V0SWQEDnVzZXJBZGRyZXNzU3RyCQClCAEIBQFpBmNhbGxlcgQLYmFzZUFzc2V0SWQJANkEAQUMYmFzZUFzc2V0U3RyBAhjZmdBcnJheQkBEnJlYWRBc3NldENmZ09yRmFpbAEFDGJhc2VBc3NldFN0cgQNc2hhcmVBc3NldFN0cgkAkQMCBQhjZmdBcnJheQUSSWR4Q2ZnU2hhcmVBc3NldElkBAxzaGFyZUFzc2V0SWQJANkEAQUNc2hhcmVBc3NldFN0cgQWZGVjaW1hbHNNdWx0Qm90aEFzc2V0cwkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCGNmZ0FycmF5BRxJZHhDZmdEZWNpbWFsc011bHRCb3RoQXNzZXRzBBRpbnRlcm5hbEJhc2VBc3NldFN0cgkAkQMCBQhjZmdBcnJheQUXSWR4Q2ZnSW50ZXJuYWxCYXNlQXNzZXQECWxpbWl0c0tFWQkBEmtleUxpbWl0c1JlbWFpbmluZwEFFGludGVybmFsQmFzZUFzc2V0U3RyBA5saW1pdHNDZmdBcnJheQkAtQkCCQEPZ2V0U3RyaW5nT3JGYWlsAQUJbGltaXRzS0VZBQNTRVAEE2xpbWl0c1JlbWFpbmluZ0Jhc2UJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQ5saW1pdHNDZmdBcnJheQUWSWR4TGltaXRzUmVtYWluaW5nQmFzZQQUbGltaXRzUmVtYWluaW5nU2hhcmUJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQ5saW1pdHNDZmdBcnJheQUXSWR4TGltaXRzUmVtYWluaW5nU2hhcmUED2lzU3VibWl0QmxvY2tlZAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzCQEaa2V5U2h1dGRvd25TdWJtaXRPcGVyYXRpb24BBRRpbnRlcm5hbEJhc2VBc3NldFN0cgcDBQ9pc1N1Ym1pdEJsb2NrZWQJAAIBAhtzdWJtaXQgb3BlcmF0aW9uIGlzIGJsb2NrZWQED29wZXJhdGlvbnNNdXRleAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEOa2V5VG9wdXBNdXRleHQBBRRpbnRlcm5hbEJhc2VBc3NldFN0cgAAAwkAZgIJAGQCBQ9vcGVyYXRpb25zTXV0ZXgAPAUGaGVpZ2h0CQACAQIuc3VibWl0IG9wZXJhdGlvbnMgYXJlIGJsb2NrZWQgYnkgdG9wdXAgbWFuYWdlcgQJZGlmZlR1cGxlCQETY2FsY1RvdGFsTG9ja2VkRGlmZggCBnN1Ym1pdAUNb3BlcmF0aW9uVHlwZQUUaW50ZXJuYWxCYXNlQXNzZXRTdHIAAAAABQhpbkFtb3VudAULYmFzZUFzc2V0SWQFDHNoYXJlQXNzZXRJZAQWbGltaXRzUmVtYWluaW5nQmFzZU5ldwkAZQIFE2xpbWl0c1JlbWFpbmluZ0Jhc2UJAJEDAggFCWRpZmZUdXBsZQJfMgUUSWR4VG90YWxMb2NrZWRJbkJhc2UEF2xpbWl0c1JlbWFpbmluZ1NoYXJlTmV3CQBlAgUUbGltaXRzUmVtYWluaW5nU2hhcmUJAJEDAggFCWRpZmZUdXBsZQJfMgUVSWR4VG90YWxMb2NrZWRJblNoYXJlAwMJAGYCAAAFFmxpbWl0c1JlbWFpbmluZ0Jhc2VOZXcGCQBmAgAABRdsaW1pdHNSZW1haW5pbmdTaGFyZU5ldwkBF2ZhaWxTdWJtaXRMaW1pdHNFeGNlZWRzBAUTbGltaXRzUmVtYWluaW5nQmFzZQUUbGltaXRzUmVtYWluaW5nU2hhcmUFFmxpbWl0c1JlbWFpbmluZ0Jhc2VOZXcFF2xpbWl0c1JlbWFpbmluZ1NoYXJlTmV3BA90b3BVcEN1cnJlbnRJZHgJAQxnZXRJbnRPckZhaWwBCQESa2V5VG9wVXBDdXJyZW50SWR4AQUUaW50ZXJuYWxCYXNlQXNzZXRTdHIJAM0IAgkAzQgCCQDNCAIJAMwIAgkBBFN0ckUCCQEMa2V5T3BlcmF0aW9uBAUNb3BlcmF0aW9uVHlwZQUUaW50ZXJuYWxCYXNlQXNzZXRTdHIFDnVzZXJBZGRyZXNzU3RyCQDYBAEIBQFpDXRyYW5zYWN0aW9uSWQJAQ1kYXRhT3BlcmF0aW9uCQIHUEVORElORwUIaW5BbW91bnQAAAAABQZoZWlnaHQIBQlsYXN0QmxvY2sJdGltZXN0YW1wAAAAAAkAZAIFD3RvcFVwQ3VycmVudElkeAABBQNuaWwJARZUb3RhbExvY2tlZFN0cmluZ0VudHJ5AwIJSU5DUkVNRU5UCQEOa2V5VG90YWxMb2NrZWQBBRRpbnRlcm5hbEJhc2VBc3NldFN0cggFCWRpZmZUdXBsZQJfMQkBFlRvdGFsTG9ja2VkU3RyaW5nRW50cnkDAglJTkNSRU1FTlQJARRrZXlUb3RhbExvY2tlZEJ5VXNlcgIFFGludGVybmFsQmFzZUFzc2V0U3RyBQ51c2VyQWRkcmVzc1N0cggFCWRpZmZUdXBsZQJfMgkBGlJlbWFpbmluZ0xpbWl0c1N0cmluZ0VudHJ5AwUJbGltaXRzS0VZBRZsaW1pdHNSZW1haW5pbmdCYXNlTmV3BRdsaW1pdHNSZW1haW5pbmdTaGFyZU5ldwENY29tbW9uRXhlY3V0ZQQNb3BlcmF0aW9uVHlwZQxiYXNlQXNzZXRTdHIOdXNlckFkZHJlc3NTdHINc3VibWl0VHhJZFN0cgQLdXNlckFkZHJlc3MJARFAZXh0ck5hdGl2ZSgxMDYyKQEFDnVzZXJBZGRyZXNzU3RyBA1hc3NldENmZ0FycmF5CQEScmVhZEFzc2V0Q2ZnT3JGYWlsAQUMYmFzZUFzc2V0U3RyBAxzaGFyZUFzc2V0SWQJANkEAQkAkQMCBQ1hc3NldENmZ0FycmF5BRJJZHhDZmdTaGFyZUFzc2V0SWQEFGludGVybmFsQmFzZUFzc2V0U3RyCQCRAwIFDWFzc2V0Q2ZnQXJyYXkFF0lkeENmZ0ludGVybmFsQmFzZUFzc2V0BBFkZWNpbWFsc011bHRQcmljZQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFDWFzc2V0Q2ZnQXJyYXkFF0lkeENmZ0RlY2ltYWxzTXVsdFByaWNlBAtiYXNlQXNzZXRJZAkA2QQBBQxiYXNlQXNzZXRTdHIEBW9wS2V5CQEMa2V5T3BlcmF0aW9uBAUNb3BlcmF0aW9uVHlwZQUUaW50ZXJuYWxCYXNlQXNzZXRTdHIFDnVzZXJBZGRyZXNzU3RyBQ1zdWJtaXRUeElkU3RyBAdvcEFycmF5CQC1CQIJAQ9nZXRTdHJpbmdPckZhaWwBBQVvcEtleQUDU0VQBAZzdGF0dXMJAJEDAgUHb3BBcnJheQUNSWR4T3BlclN0YXR1cwQIaW5BbW91bnQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQdvcEFycmF5BQ9JZHhPcGVySW5BbW91bnQEDnRvcHVwVW5sb2NrSWR4CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUHb3BBcnJheQUVSWR4T3BlclRvcHVwVW5sb2NrSWR4BAxjdXJyVG9wVXBJZHgJAQxnZXRJbnRPckZhaWwBCQESa2V5VG9wVXBDdXJyZW50SWR4AQUUaW50ZXJuYWxCYXNlQXNzZXRTdHIEDnByaWNlQnlUb3BVcElkCQEMZ2V0SW50T3JGYWlsAQkBEmtleVByaWNlQnlUb3BVcElkeAIFFGludGVybmFsQmFzZUFzc2V0U3RyBQ50b3B1cFVubG9ja0lkeAMJAQIhPQIFBnN0YXR1cwIHUEVORElORwkBDmZhaWxFeGVjdXRlR2V0BQIVU3RhdHVzIGlzIG5vdCBQRU5ESU5HBQxiYXNlQXNzZXRTdHIFDnVzZXJBZGRyZXNzU3RyBQ1zdWJtaXRUeElkU3RyBQ1vcGVyYXRpb25UeXBlAwkAZgIFDnRvcHVwVW5sb2NrSWR4BQxjdXJyVG9wVXBJZHgJAQ5mYWlsRXhlY3V0ZUdldAUJAKwCAgkArAICCQCsAgICCU9wZXJMb2NrWwkApAMBBQ50b3B1cFVubG9ja0lkeAIEXSA+IAkApAMBBQxjdXJyVG9wVXBJZHgFDGJhc2VBc3NldFN0cgUOdXNlckFkZHJlc3NTdHIFDXN1Ym1pdFR4SWRTdHIFDW9wZXJhdGlvblR5cGUECWRpZmZUdXBsZQkBE2NhbGNUb3RhbExvY2tlZERpZmYIAgdleGVjdXRlBQ1vcGVyYXRpb25UeXBlBRRpbnRlcm5hbEJhc2VBc3NldFN0cgUOcHJpY2VCeVRvcFVwSWQFEWRlY2ltYWxzTXVsdFByaWNlBQhpbkFtb3VudAULYmFzZUFzc2V0SWQFDHNoYXJlQXNzZXRJZAQJb3V0QW1vdW50CAUJZGlmZlR1cGxlAl8zBA9vdXRUcmFuc2ZlckRhdGEDCQAAAggFCWRpZmZUdXBsZQJfNAULYmFzZUFzc2V0SWQJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwULdXNlckFkZHJlc3MFCW91dEFtb3VudAULYmFzZUFzc2V0SWQFA25pbAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQt1c2VyQWRkcmVzcwUJb3V0QW1vdW50BQxzaGFyZUFzc2V0SWQFA25pbAkAzQgCCQDNCAIJAM0IAgUPb3V0VHJhbnNmZXJEYXRhCQEEU3RyRQIFBW9wS2V5CQEcZGF0YU9wZXJhdGlvbkV4ZWN1dGlvblVwZGF0ZQQFB29wQXJyYXkCCEZJTklTSEVEBQ5wcmljZUJ5VG9wVXBJZAUJb3V0QW1vdW50CQEWVG90YWxMb2NrZWRTdHJpbmdFbnRyeQMCCURFQ1JFTUVOVAkBDmtleVRvdGFsTG9ja2VkAQUUaW50ZXJuYWxCYXNlQXNzZXRTdHIIBQlkaWZmVHVwbGUCXzEJARZUb3RhbExvY2tlZFN0cmluZ0VudHJ5AwIJREVDUkVNRU5UCQEUa2V5VG90YWxMb2NrZWRCeVVzZXICBRRpbnRlcm5hbEJhc2VBc3NldFN0cgUOdXNlckFkZHJlc3NTdHIIBQlkaWZmVHVwbGUCXzIBG3ByaXZhdGVDdXJyZW50U3lzUGFyYW1zUkVTVAEMYmFzZUFzc2V0U3RyBAtiYXNlQXNzZXRJZAkA2QQBBQxiYXNlQXNzZXRTdHIECGNmZ0FycmF5CQEScmVhZEFzc2V0Q2ZnT3JGYWlsAQUMYmFzZUFzc2V0U3RyBA1zaGFyZUFzc2V0U3RyCQCRAwIFCGNmZ0FycmF5BRJJZHhDZmdTaGFyZUFzc2V0SWQEDHNoYXJlQXNzZXRJZAkA2QQBBQ1zaGFyZUFzc2V0U3RyBBlkZWNpbWFsc011bHRCb3RoQXNzZXRzVmFsCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUIY2ZnQXJyYXkFHElkeENmZ0RlY2ltYWxzTXVsdEJvdGhBc3NldHMEFGRlY2ltYWxzTXVsdFByaWNlVmFsCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUIY2ZnQXJyYXkFF0lkeENmZ0RlY2ltYWxzTXVsdFByaWNlBBRpbnRlcm5hbEJhc2VBc3NldFN0cgkAkQMCBQhjZmdBcnJheQUXSWR4Q2ZnSW50ZXJuYWxCYXNlQXNzZXQEC3ByaWNlQXRoS0VZCQELa2V5UHJpY2VBVEgBBRRpbnRlcm5hbEJhc2VBc3NldFN0cgQLcHJpY2VBdGhWYWwJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwULcHJpY2VBdGhLRVkAAAQMcHJpY2VMYXN0S0VZCQEMa2V5UHJpY2VMYXN0AQUUaW50ZXJuYWxCYXNlQXNzZXRTdHIEDHByaWNlTGFzdFZhbAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQxwcmljZUxhc3RLRVkAAAQQdG9wdXBMYXN0VGltZUtFWQkBFWtleVRvcHVwTGFzdFRpbWVzdGFtcAEFFGludGVybmFsQmFzZUFzc2V0U3RyBBB0b3B1cExhc3RUaW1lVmFsCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFEHRvcHVwTGFzdFRpbWVLRVkAAAQIc3lzU3RhdGUJAQljYWxjUHJpY2UEBRRpbnRlcm5hbEJhc2VBc3NldFN0cgULYmFzZUFzc2V0SWQFDHNoYXJlQXNzZXRJZAUUZGVjaW1hbHNNdWx0UHJpY2VWYWwJAKAKDgkBBEludEUCAgVwcmljZQUMcHJpY2VMYXN0VmFsCQEESW50RQICEWRlY2ltYWxzTXVsdFByaWNlBRRkZWNpbWFsc011bHRQcmljZVZhbAkBBEludEUCAhBiYXNlQXNzZXRCYWxhbmNlCAUIc3lzU3RhdGUCXzIJAQRJbnRFAgICLTEIBQhzeXNTdGF0ZQJfMwkBBEludEUCAhNiYXNlQXNzZXRCYWxhbmNlV0NPCAUIc3lzU3RhdGUCXzQJAQRJbnRFAgINc2hhcmVFbWlzc2lvbggFCHN5c1N0YXRlAl81CQEESW50RQICGWN1cnJJdGVyVG90YWxJbkJhc2VBbW91bnQIBQhzeXNTdGF0ZQJfNgkBBEludEUCAhpjdXJySXRlclRvdGFsSW5TaGFyZUFtb3VudAgFCHN5c1N0YXRlAl83CQEESW50RQICGHRvdGFsTG9ja2VkT3V0QmFzZUFtb3VudAgFCHN5c1N0YXRlAl84CQEESW50RQICGXRvdGFsTG9ja2VkT3V0U2hhcmVBbW91bnQIBQhzeXNTdGF0ZQJfOQkBBEludEUCAhZkZWNpbWFsc011bHRCb3RoQXNzZXRzBRlkZWNpbWFsc011bHRCb3RoQXNzZXRzVmFsCQEESW50RQICCHByaWNlQVRIBQtwcmljZUF0aFZhbAkBBEludEUCAhFwcmljZVJlY2FsY3VsYXRlZAgFCHN5c1N0YXRlAl8xCQEESW50RQICEnRvcHVwTGFzdFRpbWVzdGFtcAUQdG9wdXBMYXN0VGltZVZhbAkBaQESYWRtaW5SZWdpc3RlckFzc2V0DgxiYXNlQXNzZXRTdHIOc2hhcmVBc3NldE5hbWUPc2hhcmVBc3NldERlc2NyEGdldERlbGF5aW5CbG9ja3MWc2h1dGRvd25NYW5hZ2VyQWRkcmVzcwpzdGFydFByaWNlFXRvcHVwSW50ZXJ2YWxJbkJsb2NrcxR0b3B1cE1heE5lZ2F0aXZlUGFydBN0b3B1cE1hbmFnZXJBZGRyZXNzE3N1Ym1pdExpbWl0c0Jhc2VNYXgVc3VibWl0TGltaXRzQmFzZVJlc2V0FHN1Ym1pdExpbWl0c1NoYXJlTWF4FnN1Ym1pdExpbWl0c1NoYXJlUmVzZXQMYWRtaW5BZGRyZXNzBAtiYXNlQXNzZXRJZAkA2QQBBQxiYXNlQXNzZXRTdHIEEmJvdGhBc3NldHNEZWNpbWFscwgJAQV2YWx1ZQEJAOwHAQULYmFzZUFzc2V0SWQIZGVjaW1hbHMEFmRlY2ltYWxzTXVsdEJvdGhBc3NldHMJAGwGAAoAAAUSYm90aEFzc2V0c0RlY2ltYWxzAAAAAAUERE9XTgQRZGVjaW1hbHNNdWx0UHJpY2UJAGgCCQBoAgBkAOgHAOgHBBh0b3B1cE1heE5lZ2F0aXZlUGVyY2VudHMJAGsDBRR0b3B1cE1heE5lZ2F0aXZlUGFydABkBRZkZWNpbWFsc011bHRCb3RoQXNzZXRzBBBiYXNlQXNzZXRCYWxhbmNlCQDwBwIFBHRoaXMFC2Jhc2VBc3NldElkBAtjaGVja0NhbGxlcgkBC211c3RNYW5hZ2VyAQUBaQMJAAACBQtjaGVja0NhbGxlcgULY2hlY2tDYWxsZXIDCQAAAgUQYmFzZUFzc2V0QmFsYW5jZQAACQACAQkArAICCQCsAgIJAKUIAQUEdGhpcwIiIG11c3QgaGF2ZSBhbnkgaW5pdGlhbCBiYWxhbmNlIG9mIAUMYmFzZUFzc2V0U3RyAwkBCWlzRGVmaW5lZAEJAJ0IAgUEdGhpcwkBC2tleUFzc2V0Q2ZnAQUMYmFzZUFzc2V0U3RyCQACAQkArAICBQxiYXNlQXNzZXRTdHICHCBoYXMgYmVlbiBhbHJlYWR5IHJlZ2lzdGVyZWQDCQECIT0CCQClCAEJARFAZXh0ck5hdGl2ZSgxMDYyKQEFFnNodXRkb3duTWFuYWdlckFkZHJlc3MFFnNodXRkb3duTWFuYWdlckFkZHJlc3MJAAIBAh5pbnZhbGlkIHNodXRkb3duTWFuYWdlckFkZHJlc3MDCQECIT0CCQClCAEJARFAZXh0ck5hdGl2ZSgxMDYyKQEFE3RvcHVwTWFuYWdlckFkZHJlc3MFE3RvcHVwTWFuYWdlckFkZHJlc3MJAAIBAhtpbnZhbGlkIHRvcHVwTWFuYWdlckFkZHJlc3MDCQBmAgAABRBnZXREZWxheWluQmxvY2tzCQACAQkArAICAhlpbnZhbGlkIGdldERlbGF5aW5CbG9ja3M9CQCkAwEFEGdldERlbGF5aW5CbG9ja3MDAwkAZwIAAAUYdG9wdXBNYXhOZWdhdGl2ZVBlcmNlbnRzBgkAZwIFGHRvcHVwTWF4TmVnYXRpdmVQZXJjZW50cwBjCQACAQImaW52YWxpZCB0b3B1cE1heE5lZ2F0aXZlUGFydCBwYXJhbWV0ZXIED3NoYXJlSW5pdEFtb3VudAkBEWNvbnZlcnRCYXNlMlNoYXJlAwUQYmFzZUFzc2V0QmFsYW5jZQUKc3RhcnRQcmljZQURZGVjaW1hbHNNdWx0UHJpY2UEFXNoYXJlQXNzZXRJc3N1ZUFjdGlvbgkAwggFBQ5zaGFyZUFzc2V0TmFtZQUPc2hhcmVBc3NldERlc2NyBQ9zaGFyZUluaXRBbW91bnQFEmJvdGhBc3NldHNEZWNpbWFscwYEDHNoYXJlQXNzZXRJZAkAuAgBBRVzaGFyZUFzc2V0SXNzdWVBY3Rpb24EDXNoYXJlQXNzZXRTdHIJANgEAQUMc2hhcmVBc3NldElkBBNpbnRlcm5hbEJhc2VBc3NldElkCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJARZrZXlOZXh0SW50ZXJuYWxBc3NldElkAAAABBRpbnRlcm5hbEJhc2VBc3NldFN0cgkApAMBBRNpbnRlcm5hbEJhc2VBc3NldElkCQDMCAIJAQRTdHJFAgkBC2tleUFzc2V0Q2ZnAQUMYmFzZUFzc2V0U3RyCQEMZGF0YUFzc2V0Q2ZnDQUNc2hhcmVBc3NldFN0cgUUaW50ZXJuYWxCYXNlQXNzZXRTdHIFFmRlY2ltYWxzTXVsdEJvdGhBc3NldHMFEWRlY2ltYWxzTXVsdFByaWNlBRBnZXREZWxheWluQmxvY2tzBRV0b3B1cEludGVydmFsSW5CbG9ja3MFFHRvcHVwTWF4TmVnYXRpdmVQYXJ0BRN0b3B1cE1hbmFnZXJBZGRyZXNzBRNzdWJtaXRMaW1pdHNCYXNlTWF4BRVzdWJtaXRMaW1pdHNCYXNlUmVzZXQFFHN1Ym1pdExpbWl0c1NoYXJlTWF4BRZzdWJtaXRMaW1pdHNTaGFyZVJlc2V0BQxhZG1pbkFkZHJlc3MJAMwIAgkBBFN0ckUCCQEfa2V5TWFwcGluZ3NJbnRlcm5hbDJiYXNlQXNzZXRJZAEFE2ludGVybmFsQmFzZUFzc2V0SWQFDGJhc2VBc3NldFN0cgkAzAgCCQEEU3RyRQIJAR9rZXlNYXBwaW5nc0Jhc2VBc3NldDJpbnRlcm5hbElkAQUMYmFzZUFzc2V0U3RyBRRpbnRlcm5hbEJhc2VBc3NldFN0cgkAzAgCCQEEU3RyRQIJARxrZXlNYXBwaW5nc1NoYXJlMmJhc2VBc3NldElkAQUNc2hhcmVBc3NldFN0cgUMYmFzZUFzc2V0U3RyCQDMCAIJAQRTdHJFAgkBHGtleU1hcHBpbmdzQmFzZUFzc2V0MnNoYXJlSWQBBQxiYXNlQXNzZXRTdHIFDXNoYXJlQXNzZXRTdHIJAMwIAgkBDEJvb2xlYW5FbnRyeQIJARprZXlTaHV0ZG93blN1Ym1pdE9wZXJhdGlvbgEFFGludGVybmFsQmFzZUFzc2V0U3RyBwkAzAgCCQEEU3RyRQIJARJrZXlTaHV0ZG93bk1hbmFnZXIBBRRpbnRlcm5hbEJhc2VBc3NldFN0cgUWc2h1dGRvd25NYW5hZ2VyQWRkcmVzcwkAzAgCCQEESW50RQIJARZrZXlOZXh0SW50ZXJuYWxBc3NldElkAAkAZAIFE2ludGVybmFsQmFzZUFzc2V0SWQAAQkAzAgCCQEESW50RQIJAQxrZXlQcmljZUxhc3QBBRRpbnRlcm5hbEJhc2VBc3NldFN0cgUKc3RhcnRQcmljZQkAzAgCCQEESW50RQIJAQ9rZXlQcmljZUhpc3RvcnkDBRRpbnRlcm5hbEJhc2VBc3NldFN0cgUGaGVpZ2h0CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAUKc3RhcnRQcmljZQkAzAgCCQEESW50RQIJARJrZXlUb3BVcEN1cnJlbnRJZHgBBRRpbnRlcm5hbEJhc2VBc3NldFN0cgAACQDMCAIJARpSZW1haW5pbmdMaW1pdHNTdHJpbmdFbnRyeQMJARJrZXlMaW1pdHNSZW1haW5pbmcBBRRpbnRlcm5hbEJhc2VBc3NldFN0cgUTc3VibWl0TGltaXRzQmFzZU1heAUUc3VibWl0TGltaXRzU2hhcmVNYXgJAMwIAgUVc2hhcmVBc3NldElzc3VlQWN0aW9uCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMJARFAZXh0ck5hdGl2ZSgxMDYyKQEFE3RvcHVwTWFuYWdlckFkZHJlc3MFD3NoYXJlSW5pdEFtb3VudAUMc2hhcmVBc3NldElkBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEPc2h1dGRvd25TdWJtaXRzARNpbnRlcm5hbEJhc2VBc3NldElkBAtjaGVja0NhbGxlcgkBC211c3RNYW5hZ2VyAQUBaQMJAAACBQtjaGVja0NhbGxlcgULY2hlY2tDYWxsZXIEFmludGVybmFsQmFzZUFzc2V0SWRTdHIJAKQDAQUTaW50ZXJuYWxCYXNlQXNzZXRJZAQOYmFzZUFzc2V0SWRTdHIJAQ9nZXRTdHJpbmdPckZhaWwBCQEfa2V5TWFwcGluZ3NJbnRlcm5hbDJiYXNlQXNzZXRJZAEFE2ludGVybmFsQmFzZUFzc2V0SWQEFnNodXRkb3duTWFuYWdlckFkZHJlc3MJAQ9nZXRTdHJpbmdPckZhaWwBCQESa2V5U2h1dGRvd25NYW5hZ2VyAQUWaW50ZXJuYWxCYXNlQXNzZXRJZFN0cgMJAGYCAAEJALECAQUOYmFzZUFzc2V0SWRTdHIJAAIBAhtpbnZhbGlkIGludGVybmFsQmFzZUFzc2V0SWQJAMwIAgkBDEJvb2xlYW5FbnRyeQIJARprZXlTaHV0ZG93blN1Ym1pdE9wZXJhdGlvbgEJAKQDAQUTaW50ZXJuYWxCYXNlQXNzZXRJZAYFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQlzdWJtaXRQdXQABANwbXQJAQV2YWx1ZQEJAJEDAggFAWkIcGF5bWVudHMAAAQIaW5BbW91bnQIBQNwbXQGYW1vdW50BAlpbkFzc2V0SWQJAQV2YWx1ZQEIBQNwbXQHYXNzZXRJZAQMYmFzZUFzc2V0U3RyCQDYBAEFCWluQXNzZXRJZAkBDGNvbW1vblN1Ym1pdAUCAVAFAWkFCGluQW1vdW50BQlpbkFzc2V0SWQFDGJhc2VBc3NldFN0cgFpAQlzdWJtaXRHZXQABANwbXQJAQV2YWx1ZQEJAJEDAggFAWkIcGF5bWVudHMAAAQIaW5BbW91bnQIBQNwbXQGYW1vdW50BAlpbkFzc2V0SWQJAQV2YWx1ZQEIBQNwbXQHYXNzZXRJZAQNc2hhcmVBc3NldFN0cgkA2AQBBQlpbkFzc2V0SWQEDGJhc2VBc3NldFN0cgkBD2dldFN0cmluZ09yRmFpbAEJARxrZXlNYXBwaW5nc1NoYXJlMmJhc2VBc3NldElkAQUNc2hhcmVBc3NldFN0cgkBDGNvbW1vblN1Ym1pdAUCAUcFAWkFCGluQW1vdW50BQlpbkFzc2V0SWQFDGJhc2VBc3NldFN0cgFpAQpleGVjdXRlUHV0AwxiYXNlQXNzZXRTdHIOdXNlckFkZHJlc3NTdHINc3VibWl0VHhJZFN0cgkBDWNvbW1vbkV4ZWN1dGUEAgFQBQxiYXNlQXNzZXRTdHIFDnVzZXJBZGRyZXNzU3RyBQ1zdWJtaXRUeElkU3RyAWkBCmV4ZWN1dGVHZXQDDGJhc2VBc3NldFN0cg51c2VyQWRkcmVzc1N0cg1zdWJtaXRUeElkU3RyCQENY29tbW9uRXhlY3V0ZQQCAUcFDGJhc2VBc3NldFN0cgUOdXNlckFkZHJlc3NTdHIFDXN1Ym1pdFR4SWRTdHIBaQEPb3BlcmF0aW9uc011dGV4AQxiYXNlQXNzZXRTdHIEDWFzc2V0Q2ZnQXJyYXkJARJyZWFkQXNzZXRDZmdPckZhaWwBBQxiYXNlQXNzZXRTdHIEFnRvcFVwTWFuYWdlckFkZHJlc3NTdHIJAJEDAgUNYXNzZXRDZmdBcnJheQUZSWR4Q2ZnVG9wdXBNYW5hZ2VyQWRkcmVzcwQUaW50ZXJuYWxCYXNlQXNzZXRTdHIJAJEDAgUNYXNzZXRDZmdBcnJheQUXSWR4Q2ZnSW50ZXJuYWxCYXNlQXNzZXQDCQECIT0CCQClCAEIBQFpBmNhbGxlcgUWdG9wVXBNYW5hZ2VyQWRkcmVzc1N0cgkBFGZhaWxUb3B1cE1hbmFnZXJPbmx5AQUWdG9wVXBNYW5hZ2VyQWRkcmVzc1N0cgkAzAgCCQESVG9wdXBNdXRleEludEVudHJ5AgUUaW50ZXJuYWxCYXNlQXNzZXRTdHIFBmhlaWdodAUDbmlsAWkBDHRvcFVwQmFsYW5jZQIMYmFzZUFzc2V0U3RyBmluY29tZQQLYmFzZUFzc2V0SWQJANkEAQUMYmFzZUFzc2V0U3RyBANjZmcJARJyZWFkQXNzZXRDZmdPckZhaWwBBQxiYXNlQXNzZXRTdHIEDHNoYXJlQXNzZXRJZAkA2QQBCQCRAwIFA2NmZwUSSWR4Q2ZnU2hhcmVBc3NldElkBAlwcmljZU11bHQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQNjZmcFF0lkeENmZ0RlY2ltYWxzTXVsdFByaWNlBA1ib3RoQXNzZXRNdWx0CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUDY2ZnBRxJZHhDZmdEZWNpbWFsc011bHRCb3RoQXNzZXRzBBV0b3B1cEludGVydmFsSW5CbG9ja3MJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQNjZmcFG0lkeENmZ1RvcHVwSW50ZXJ2YWxJbkJsb2NrcwQUdG9wdXBNYXhOZWdhdGl2ZVBhcnQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQNjZmcFGklkeENmZ1RvcHVwTWF4TmVnYXRpdmVQYXJ0BBRpbnRlcm5hbEJhc2VBc3NldFN0cgkAkQMCBQNjZmcFF0lkeENmZ0ludGVybmFsQmFzZUFzc2V0BBZ0b3BVcE1hbmFnZXJBZGRyZXNzU3RyCQCRAwIFA2NmZwUZSWR4Q2ZnVG9wdXBNYW5hZ2VyQWRkcmVzcwQTc3VibWl0TGltaXRzQmFzZU1heAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFA2NmZwUZSWR4Q2ZnU3VibWl0TGltaXRzQmFzZU1heAQUc3VibWl0TGltaXRzU2hhcmVNYXgJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQNjZmcFGklkeENmZ1N1Ym1pdExpbWl0c1NoYXJlTWF4BBJ0b3BVcEN1cnJlbnRJZHhLRVkJARJrZXlUb3BVcEN1cnJlbnRJZHgBBRRpbnRlcm5hbEJhc2VBc3NldFN0cgQMcHJldlRvcFVwSWR4CQEMZ2V0SW50T3JGYWlsAQUSdG9wVXBDdXJyZW50SWR4S0VZBA9jdXJyZW50VG9wVXBJZHgJAGQCBQxwcmV2VG9wVXBJZHgAAQQFdmFsaWQDCQBmAgUGaW5jb21lAAAEA3BtdAkBBXZhbHVlAQkAkQMCCAUBaQhwYXltZW50cwAABApwbXRBc3NldElkCQEFdmFsdWUBCAUDcG10B2Fzc2V0SWQDCQECIT0CBQtiYXNlQXNzZXRJZAUKcG10QXNzZXRJZAkAAgECPmF0dGFjaGVkIHBheW1lbnQncyBhc3NldCBpZCBpcyBOT1QgbWF0Y2hlZCBwYXNzZWQgYmFzZUFzc2V0U3RyAwkAZgIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECIG9ubHkgb25lIHBheW1lbnQgY2FuIGJlIGF0dGFjaGVkAwkBAiE9AggFA3BtdAZhbW91bnQFBmluY29tZQkAAgECPWF0dGFjaGVkIHBheW1lbnQuYW1vdW50IGlzIE5PVCBtYXRjaGVkIHBhc3NlZCBpbmNvbWUgYXJndW1lbnQGAwkAZgIAAAUGaW5jb21lBAtiYXNlQmFsYW5jZQkA8AcCBQR0aGlzBQtiYXNlQXNzZXRJZAQNYWxsb3dlZEFtb3VudAkAawMFFHRvcHVwTWF4TmVnYXRpdmVQYXJ0BQtiYXNlQmFsYW5jZQUNYm90aEFzc2V0TXVsdAMJAGYCCQEBLQEFBmluY29tZQUNYWxsb3dlZEFtb3VudAkAAgEJAKwCAgIvdG9wdXAgbmVnYXRpdmUgaW5jb21lIGNvdWxkbid0IGJlIGdyZWF0ZXIgdGhhbiAJAKQDAQUNYWxsb3dlZEFtb3VudAYJAAIBAhp6ZXJvIGluY29tZSBpcyBub3QgYWxsb3dlZAQSdG9wVXBMYXN0SGVpZ2h0S0VZCQESa2V5VG9wVXBMYXN0SGVpZ2h0AgUUaW50ZXJuYWxCYXNlQXNzZXRTdHIJAKUIAQgFAWkGY2FsbGVyBA90b3BVcExhc3RIZWlnaHQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUSdG9wVXBMYXN0SGVpZ2h0S0VZAAADCQECIT0CCQClCAEIBQFpBmNhbGxlcgUWdG9wVXBNYW5hZ2VyQWRkcmVzc1N0cgkBFGZhaWxUb3B1cE1hbmFnZXJPbmx5AQUWdG9wVXBNYW5hZ2VyQWRkcmVzc1N0cgMJAQEhAQUFdmFsaWQJAAIBAhF2YWxpZGF0aW9uIGZhaWxlZAMJAGYCBRV0b3B1cEludGVydmFsSW5CbG9ja3MJAGUCBQZoZWlnaHQFD3RvcFVwTGFzdEhlaWdodAkAAgEJAKwCAgkArAICAgwxIHRvcHVwIHBlciAJAKQDAQUVdG9wdXBJbnRlcnZhbEluQmxvY2tzAiggYmxvY2tzIGZyb20gdGhlIHNhbWUgYWRkcmVzcyBpcyBhbGxvd2VkBAVwcmljZQgJARBnZW5lcmljQ2FsY1ByaWNlBQUUaW50ZXJuYWxCYXNlQXNzZXRTdHIFC2Jhc2VBc3NldElkBQZpbmNvbWUFDHNoYXJlQXNzZXRJZAUJcHJpY2VNdWx0Al8xBAlkaWZmVHVwbGUJARNjYWxjVG90YWxMb2NrZWREaWZmCAIFdG9wdXACAAUUaW50ZXJuYWxCYXNlQXNzZXRTdHIFBXByaWNlBQlwcmljZU11bHQAAAULYmFzZUFzc2V0SWQFDHNoYXJlQXNzZXRJZAQOdG9wdXBUb3RhbERpZmYIBQlkaWZmVHVwbGUCXzEEC3ByaWNlQXRoS0VZCQELa2V5UHJpY2VBVEgBBRRpbnRlcm5hbEJhc2VBc3NldFN0cgQMcHJldlByaWNlQVRICQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFC3ByaWNlQXRoS0VZAAAJAM4IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzAgCCQEESW50RQIJAQxrZXlQcmljZUxhc3QBBRRpbnRlcm5hbEJhc2VBc3NldFN0cgUFcHJpY2UJAMwIAgkBBEludEUCCQEPa2V5UHJpY2VIaXN0b3J5AwUUaW50ZXJuYWxCYXNlQXNzZXRTdHIFBmhlaWdodAgFCWxhc3RCbG9jawl0aW1lc3RhbXAFBXByaWNlCQDMCAIJAQRJbnRFAgkBEmtleVByaWNlQnlUb3BVcElkeAIFFGludGVybmFsQmFzZUFzc2V0U3RyBQ9jdXJyZW50VG9wVXBJZHgFBXByaWNlCQDMCAIJAQRJbnRFAgUSdG9wVXBDdXJyZW50SWR4S0VZBQ9jdXJyZW50VG9wVXBJZHgJAMwIAgkBBEludEUCBQtwcmljZUF0aEtFWQMJAGYCBQVwcmljZQUMcHJldlByaWNlQVRIBQVwcmljZQUMcHJldlByaWNlQVRICQDMCAIJAQRJbnRFAgUSdG9wVXBMYXN0SGVpZ2h0S0VZBQZoZWlnaHQFA25pbAkBFlRvdGFsTG9ja2VkU3RyaW5nRW50cnkDAglERUNSRU1FTlQJAQ5rZXlUb3RhbExvY2tlZAEFFGludGVybmFsQmFzZUFzc2V0U3RyBQ50b3B1cFRvdGFsRGlmZgkBElRvcHVwTXV0ZXhJbnRFbnRyeQIFFGludGVybmFsQmFzZUFzc2V0U3RyAAAJAQRJbnRFAgkBFWtleVRvcHVwTGFzdFRpbWVzdGFtcAEFFGludGVybmFsQmFzZUFzc2V0U3RyCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkBGlJlbWFpbmluZ0xpbWl0c1N0cmluZ0VudHJ5AwkBEmtleUxpbWl0c1JlbWFpbmluZwEFFGludGVybmFsQmFzZUFzc2V0U3RyBRNzdWJtaXRMaW1pdHNCYXNlTWF4BRRzdWJtaXRMaW1pdHNTaGFyZU1heAkBBEJ1cm4CBQxzaGFyZUFzc2V0SWQJAJEDAgUOdG9wdXBUb3RhbERpZmYFFUlkeFRvdGFsTG9ja2VkSW5TaGFyZQkBB1JlaXNzdWUDBQxzaGFyZUFzc2V0SWQJAQEtAQkAkQMCBQ50b3B1cFRvdGFsRGlmZgUWSWR4VG90YWxMb2NrZWRPdXRTaGFyZQYDCQBmAgAABQZpbmNvbWUJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyCQEBLQEFBmluY29tZQULYmFzZUFzc2V0SWQFA25pbAUDbmlsAWkBFGN1cnJlbnRTeXNQYXJhbXNSRVNUAQxiYXNlQXNzZXRTdHIEDXN5c1N0YXRlVHVwbGUJARtwcml2YXRlQ3VycmVudFN5c1BhcmFtc1JFU1QBBQxiYXNlQXNzZXRTdHIEBXByaWNlCAgFDXN5c1N0YXRlVHVwbGUCXzEFdmFsdWUEEWRlY2ltYWxzTXVsdFByaWNlCAgFDXN5c1N0YXRlVHVwbGUCXzIFdmFsdWUEEGJhc2VBc3NldEJhbGFuY2UICAUNc3lzU3RhdGVUdXBsZQJfMwV2YWx1ZQQVdG90YWxMb2NrZWRCYXNlQW1vdW50CAgFDXN5c1N0YXRlVHVwbGUCXzQFdmFsdWUEE2Jhc2VBc3NldEJhbGFuY2VXQ08ICAUNc3lzU3RhdGVUdXBsZQJfNQV2YWx1ZQQNc2hhcmVFbWlzc2lvbggIBQ1zeXNTdGF0ZVR1cGxlAl82BXZhbHVlBBljdXJySXRlclRvdGFsSW5CYXNlQW1vdW50CAgFDXN5c1N0YXRlVHVwbGUCXzcFdmFsdWUEGmN1cnJJdGVyVG90YWxJblNoYXJlQW1vdW50CAgFDXN5c1N0YXRlVHVwbGUCXzgFdmFsdWUEGHRvdGFsTG9ja2VkT3V0QmFzZUFtb3VudAgIBQ1zeXNTdGF0ZVR1cGxlAl85BXZhbHVlBBl0b3RhbExvY2tlZE91dFNoYXJlQW1vdW50CAgFDXN5c1N0YXRlVHVwbGUDXzEwBXZhbHVlBBZkZWNpbWFsc011bHRCb3RoQXNzZXRzCAgFDXN5c1N0YXRlVHVwbGUDXzExBXZhbHVlBAhwcmljZUFUSAgIBQ1zeXNTdGF0ZVR1cGxlA18xMgV2YWx1ZQQRcHJpY2VSZWNhbGN1bGF0ZWQICAUNc3lzU3RhdGVUdXBsZQNfMTMFdmFsdWUEDXRvcHVwTGFzdFRpbWUICAUNc3lzU3RhdGVUdXBsZQNfMTQFdmFsdWUECHJlc3REYXRhCQC5CQIJAMwIAgIZc3RhcnRDdXJyZW50U3lzUGFyYW1zUkVTVAkAzAgCCQCkAwEFBXByaWNlCQDMCAIJAKQDAQURZGVjaW1hbHNNdWx0UHJpY2UJAMwIAgkApAMBBRBiYXNlQXNzZXRCYWxhbmNlCQDMCAIJAKQDAQUVdG90YWxMb2NrZWRCYXNlQW1vdW50CQDMCAIJAKQDAQUTYmFzZUFzc2V0QmFsYW5jZVdDTwkAzAgCCQCkAwEFDXNoYXJlRW1pc3Npb24JAMwIAgkApAMBBRljdXJySXRlclRvdGFsSW5CYXNlQW1vdW50CQDMCAIJAKQDAQUaY3Vyckl0ZXJUb3RhbEluU2hhcmVBbW91bnQJAMwIAgkApAMBBRh0b3RhbExvY2tlZE91dEJhc2VBbW91bnQJAMwIAgkApAMBBRl0b3RhbExvY2tlZE91dFNoYXJlQW1vdW50CQDMCAIJAKQDAQUWZGVjaW1hbHNNdWx0Qm90aEFzc2V0cwkAzAgCCQCkAwEFCHByaWNlQVRICQDMCAIJAKQDAQURcHJpY2VSZWNhbGN1bGF0ZWQJAMwIAgkApAMBBQ10b3B1cExhc3RUaW1lCQDMCAICF2VuZEN1cnJlbnRTeXNQYXJhbXNSRVNUBQNuaWwFA1NFUAkAAgEFCHJlc3REYXRhAQJ0eAEGdmVyaWZ5AAQPdGFyZ2V0UHVibGljS2V5BAckbWF0Y2gwCQEWbWFuYWdlclB1YmxpY0tleU9yVW5pdAADCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQCcGsFByRtYXRjaDAFAnBrAwkAAQIFByRtYXRjaDACBFVuaXQIBQJ0eA9zZW5kZXJQdWJsaWNLZXkJAAIBAgtNYXRjaCBlcnJvcgkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAUPdGFyZ2V0UHVibGljS2V5SYgFRw==", "height": 3637252, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 6XbwcCnvnKN2fBj4yMc29kzHjdWU9fk8v63T7KUKH592 Next: AmzN6XjXc2SConLKKUxuWQTTqCarLGbJS5D1KaHX5uEw Diff:
OldNewDifferences
1-{-# STDLIB_VERSION 4 #-}
1+{-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let SEP = "__"
9191
9292
9393 func keyLimitsRemaining (internalBasetAssetStr) = ("%s%s%d__limits__remaining__" + internalBasetAssetStr)
94+
95+
96+func keyManagerVaultAddress () = "%s__managerVaultAddress"
97+
98+
99+func keyManagerPublicKey () = "%s__managerPublicKey"
94100
95101
96102 let IdxCfgShareAssetId = 1
264270 func calcPrice (internalBaseAssetStr,baseAssetId,shareAssetId,decimalsMultPrice) = genericCalcPrice(internalBaseAssetStr, baseAssetId, 0, shareAssetId, decimalsMultPrice)
265271
266272
273+func getManagerVaultAddressOrThis () = match getString(keyManagerVaultAddress()) {
274+ case s: String =>
275+ addressFromStringValue(s)
276+ case _ =>
277+ this
278+}
279+
280+
281+func managerPublicKeyOrUnit () = {
282+ let managerVaultAddress = getManagerVaultAddressOrThis()
283+ match getString(managerVaultAddress, keyManagerPublicKey()) {
284+ case s: String =>
285+ fromBase58String(s)
286+ case _: Unit =>
287+ unit
288+ case _ =>
289+ throw("Match error")
290+ }
291+ }
292+
293+
294+func isManager (i) = match managerPublicKeyOrUnit() {
295+ case pk: ByteVector =>
296+ (i.callerPublicKey == pk)
297+ case _: Unit =>
298+ (i.caller == this)
299+ case _ =>
300+ throw("Match error")
301+}
302+
303+
304+func mustManager (i) = if (isManager(i))
305+ then true
306+ else throw("permission denied")
307+
308+
267309 func commonSubmit (operationType,i,inAmount,inAssetId,baseAssetStr) = {
268310 let inAssetStr = toBase58String(inAssetId)
269311 let userAddressStr = toString(i.caller)
357399 let decimalsMultPrice = ((100 * 1000) * 1000)
358400 let topupMaxNegativePercents = fraction(topupMaxNegativePart, 100, decimalsMultBothAssets)
359401 let baseAssetBalance = assetBalance(this, baseAssetId)
360- if ((i.caller != this))
361- then throw("permissions denied")
362- else if ((baseAssetBalance == 0))
402+ let checkCaller = mustManager(i)
403+ if ((checkCaller == checkCaller))
404+ then if ((baseAssetBalance == 0))
363405 then throw(((toString(this) + " must have any initial balance of ") + baseAssetStr))
364406 else if (isDefined(getString(this, keyAssetCfg(baseAssetStr))))
365407 then throw((baseAssetStr + " has been already registered"))
382424 let internalBaseAssetStr = toString(internalBaseAssetId)
383425 [StrE(keyAssetCfg(baseAssetStr), dataAssetCfg(shareAssetStr, internalBaseAssetStr, decimalsMultBothAssets, decimalsMultPrice, getDelayinBlocks, topupIntervalInBlocks, topupMaxNegativePart, topupManagerAddress, submitLimitsBaseMax, submitLimitsBaseReset, submitLimitsShareMax, submitLimitsShareReset, adminAddress)), StrE(keyMappingsInternal2baseAssetId(internalBaseAssetId), baseAssetStr), StrE(keyMappingsBaseAsset2internalId(baseAssetStr), internalBaseAssetStr), StrE(keyMappingsShare2baseAssetId(shareAssetStr), baseAssetStr), StrE(keyMappingsBaseAsset2shareId(baseAssetStr), shareAssetStr), BooleanEntry(keyShutdownSubmitOperation(internalBaseAssetStr), false), StrE(keyShutdownManager(internalBaseAssetStr), shutdownManagerAddress), IntE(keyNextInternalAssetId(), (internalBaseAssetId + 1)), IntE(keyPriceLast(internalBaseAssetStr), startPrice), IntE(keyPriceHistory(internalBaseAssetStr, height, lastBlock.timestamp), startPrice), IntE(keyTopUpCurrentIdx(internalBaseAssetStr), 0), RemainingLimitsStringEntry(keyLimitsRemaining(internalBaseAssetStr), submitLimitsBaseMax, submitLimitsShareMax), shareAssetIssueAction, ScriptTransfer(addressFromStringValue(topupManagerAddress), shareInitAmount, shareAssetId)]
384426 }
427+ else throw("Strict value is not equal to itself.")
385428 }
386429
387430
388431
389432 @Callable(i)
390433 func shutdownSubmits (internalBaseAssetId) = {
391- let internalBaseAssetIdStr = toString(internalBaseAssetId)
392- let baseAssetIdStr = getStringOrFail(keyMappingsInternal2baseAssetId(internalBaseAssetId))
393- let shutdownManagerAddress = getStringOrFail(keyShutdownManager(internalBaseAssetIdStr))
394- if ((1 > size(baseAssetIdStr)))
395- then throw("invalid internalBaseAssetId")
396- else if ((toString(i.caller) != shutdownManagerAddress))
397- then throw("access denied")
398- else [BooleanEntry(keyShutdownSubmitOperation(toString(internalBaseAssetId)), true)]
434+ let checkCaller = mustManager(i)
435+ if ((checkCaller == checkCaller))
436+ then {
437+ let internalBaseAssetIdStr = toString(internalBaseAssetId)
438+ let baseAssetIdStr = getStringOrFail(keyMappingsInternal2baseAssetId(internalBaseAssetId))
439+ let shutdownManagerAddress = getStringOrFail(keyShutdownManager(internalBaseAssetIdStr))
440+ if ((1 > size(baseAssetIdStr)))
441+ then throw("invalid internalBaseAssetId")
442+ else [BooleanEntry(keyShutdownSubmitOperation(toString(internalBaseAssetId)), true)]
443+ }
444+ else throw("Strict value is not equal to itself.")
399445 }
400446
401447
529575
530576
531577 @Verifier(tx)
532-func verify () = sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String("2Cbd8ozG7A1RyRNC3nNnZgHu7Ru4K3JCfpyPkhqr9zxq"))
578+func verify () = {
579+ let targetPublicKey = match managerPublicKeyOrUnit() {
580+ case pk: ByteVector =>
581+ pk
582+ case _: Unit =>
583+ tx.senderPublicKey
584+ case _ =>
585+ throw("Match error")
586+ }
587+ sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey)
588+ }
533589
Full:
OldNewDifferences
1-{-# STDLIB_VERSION 4 #-}
1+{-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let SEP = "__"
55
66 func getStringOrFail (key) = valueOrErrorMessage(getString(this, key), ("No data for this.key=" + key))
77
88
99 func getBooleanOrFail (key) = valueOrErrorMessage(getBoolean(this, key), ("No data for this.key=" + key))
1010
1111
1212 func getIntOrFail (key) = valueOrErrorMessage(getInteger(this, key), ("No data for this.key=" + key))
1313
1414
1515 func IntE (key,val) = IntegerEntry(key, val)
1616
1717
1818 func StrE (key,val) = StringEntry(key, val)
1919
2020
2121 func failExecuteGet (msg,baseAssetStr,userAddressStr,submitTxIdStr,operationType) = throw(((((((((msg + ": baseAsset=") + baseAssetStr) + " userAddress=") + userAddressStr) + " submitTxId=") + submitTxIdStr) + " operation=") + operationType))
2222
2323
2424 func failSubmitLimitsExceeds (remainingBase,remainingShare,newRemainingBase,newRemainingShare) = throw((((((((("submit operation limits have been reached: " + " remainingBaseVal=") + toString(remainingBase)) + " remainingShareVal=") + toString(remainingShare)) + " newRemainingBaseVal=") + toString(newRemainingBase)) + " newRemainingShareVal=") + toString(newRemainingShare)))
2525
2626
2727 func failTopupManagerOnly (topupManagerAddress) = throw((("opertion denied: only topUpManager=" + topupManagerAddress) + " can send such transactions"))
2828
2929
3030 func convertShare2Base (shareAmount,price,priceMult) = fraction(shareAmount, price, priceMult)
3131
3232
3333 func convertBase2Share (baseAmount,price,priceMult) = fraction(baseAmount, priceMult, price)
3434
3535
3636 func keyAssetCfg (baseAssetStr) = ("%s%s%s__config__asset__" + baseAssetStr)
3737
3838
3939 func keyNextInternalAssetId () = "%s__nextInternalAssetId"
4040
4141
4242 func keyPriceLast (internalBasetAssetStr) = ("%s%s%d__price__last__" + internalBasetAssetStr)
4343
4444
4545 func keyPriceATH (internalBasetAssetStr) = ("%s%s%d__price__ath__" + internalBasetAssetStr)
4646
4747
4848 func keyPriceByTopUpIdx (internalBaseAssetStr,topUpIdx) = makeString(["%s%s%d%d__price__byTopUpIdx", internalBaseAssetStr, toString(topUpIdx)], SEP)
4949
5050
5151 func keyPriceHistory (internalBasetAssetStr,h,timestamp) = makeString(["%s%s%d%d%d__price__history", internalBasetAssetStr, toString(h), toString(timestamp)], SEP)
5252
5353
5454 func keyTotalLocked (internalBasetAssetStr) = ("%s%s%d__total__locked__" + internalBasetAssetStr)
5555
5656
5757 func keyTotalLockedByUser (internalBaseAssetStr,userAddressStr) = makeString(["%s%s%d%s__total__locked", internalBaseAssetStr, userAddressStr], SEP)
5858
5959
6060 func keyMappingsInternal2baseAssetId (internalBaseAsset) = ("%s%s%d__mappings__internal2baseAssetId__" + toString(internalBaseAsset))
6161
6262
6363 func keyMappingsBaseAsset2internalId (baseAssetStr) = ("%s%s%s__mappings__baseAsset2internalId__" + baseAssetStr)
6464
6565
6666 func keyMappingsShare2baseAssetId (shareAssetStr) = ("%s%s%s__mappings__share2baseAssetId__" + shareAssetStr)
6767
6868
6969 func keyMappingsBaseAsset2shareId (baseAssetStr) = ("%s%s%s__mappings__baseAsset2shareId__" + baseAssetStr)
7070
7171
7272 func keyShutdownSubmitOperation (internalBaseAssetStr) = ("%s%s%d__shutdown__submit__" + internalBaseAssetStr)
7373
7474
7575 func keyShutdownManager (internalBaseAssetStr) = ("%s%s%d__shutdown__manager__" + internalBaseAssetStr)
7676
7777
7878 func keyTopUpCurrentIdx (internalBaseAssetStr) = ("%s%s%d__topup__currentIdx__" + internalBaseAssetStr)
7979
8080
8181 func keyTopUpLastHeight (internalBasetAssetStr,sender) = makeString(["%s%s%s%d%s__topup__last__height", internalBasetAssetStr, sender], SEP)
8282
8383
8484 func keyTopupMutext (internalBasetAssetStr) = ("%s%s%d__topup__mutex__" + internalBasetAssetStr)
8585
8686
8787 func keyTopupLastTimestamp (internalBasetAssetStr) = ("%s%s%s%d__topup__last__timestamp__" + internalBasetAssetStr)
8888
8989
9090 func keyTopupHistory (internalBasetAssetStr,topupIdx) = makeString(["%s%s%d%d__topup__history", internalBasetAssetStr, toString(topupIdx)], SEP)
9191
9292
9393 func keyLimitsRemaining (internalBasetAssetStr) = ("%s%s%d__limits__remaining__" + internalBasetAssetStr)
94+
95+
96+func keyManagerVaultAddress () = "%s__managerVaultAddress"
97+
98+
99+func keyManagerPublicKey () = "%s__managerPublicKey"
94100
95101
96102 let IdxCfgShareAssetId = 1
97103
98104 let IdxCfgInternalBaseAsset = 2
99105
100106 let IdxCfgDecimalsMultBothAssets = 3
101107
102108 let IdxCfgDecimalsMultPrice = 4
103109
104110 let IdxCfgGetDelayBlocks = 5
105111
106112 let IdxCfgTopupIntervalInBlocks = 6
107113
108114 let IdxCfgTopupMaxNegativePart = 7
109115
110116 let IdxCfgTopupManagerAddress = 8
111117
112118 let IdxCfgSubmitLimitsBaseMax = 9
113119
114120 let IdxCfgSubmitLimitsBaseReset = 10
115121
116122 let IdxCfgSubmitLimitsShareMax = 11
117123
118124 let IdxCfgSubmitLimitsShareReset = 12
119125
120126 let IdxCfgAdminAddress = 13
121127
122128 func dataAssetCfg (shareAssetStr,internalBaseAssetStr,decimalsMultBothAssets,decimalsMultPrice,getDelayInBlocks,topupIntervalInBlocks,topupMaxNegativePart,topupManagerAddress,submitLimitsBaseMax,submitLimitsBaseReset,submitLimitsShareMax,submitLimitsShareReset,adminAddress) = makeString(["%s%d%d%d%d%d%d%s%d%d%d%d", shareAssetStr, internalBaseAssetStr, toString(decimalsMultBothAssets), toString(decimalsMultPrice), toString(getDelayInBlocks), toString(topupIntervalInBlocks), toString(topupMaxNegativePart), topupManagerAddress, toString(submitLimitsBaseMax), toString(submitLimitsBaseReset), toString(submitLimitsShareMax), toString(submitLimitsShareReset), adminAddress], SEP)
123129
124130
125131 let IdxTotalLockedInShare = 1
126132
127133 let IdxTotalLockedOutBase = 2
128134
129135 let IdxTotalLockedInBase = 3
130136
131137 let IdxTotalLockedOutShare = 4
132138
133139 func dataTotalLocked (inShareAmount,outBaseAmount,inBaseAmount,outShareAmount) = makeString(["%d%d%d%d", toString(inShareAmount), toString(outBaseAmount), toString(inBaseAmount), toString(outShareAmount)], SEP)
134140
135141
136142 func dataTotalLockedInt (inShareAmount,outBaseAmount,inBaseAmount,outShareAmount) = [-1, inShareAmount, outBaseAmount, inBaseAmount, outShareAmount]
137143
138144
139145 func readTotalLocked (key) = {
140146 let totalLockedArray = split(valueOrElse(getString(this, key), dataTotalLocked(0, 0, 0, 0)), SEP)
141147 dataTotalLockedInt(parseIntValue(totalLockedArray[IdxTotalLockedInShare]), parseIntValue(totalLockedArray[IdxTotalLockedOutBase]), parseIntValue(totalLockedArray[IdxTotalLockedInBase]), parseIntValue(totalLockedArray[IdxTotalLockedOutShare]))
142148 }
143149
144150
145151 func calcTotalLockedDiff (direction,operationType,internalBaseAssetStr,price,priceMult,inAmount,baseAssetId,shareAssetId) = {
146152 let t = (direction + operationType)
147153 if ((t == "submitP"))
148154 then {
149155 let totalDiff = dataTotalLockedInt(0, 0, inAmount, 0)
150156 let userDiff = totalDiff
151157 $Tuple4(totalDiff, userDiff, 0, fromBase58String(""))
152158 }
153159 else if ((t == "submitG"))
154160 then {
155161 let totalDiff = dataTotalLockedInt(inAmount, 0, 0, 0)
156162 let userDiff = totalDiff
157163 $Tuple4(totalDiff, userDiff, 0, fromBase58String(""))
158164 }
159165 else if ((t == "executeP"))
160166 then {
161167 let outAmount = convertBase2Share(inAmount, price, priceMult)
162168 let totalDiff = dataTotalLockedInt(0, 0, 0, outAmount)
163169 let userDiff = dataTotalLockedInt(0, 0, inAmount, 0)
164170 $Tuple4(totalDiff, userDiff, outAmount, shareAssetId)
165171 }
166172 else if ((t == "executeG"))
167173 then {
168174 let outAmount = convertShare2Base(inAmount, price, priceMult)
169175 let totalDiff = dataTotalLockedInt(0, outAmount, 0, 0)
170176 let userDiff = dataTotalLockedInt(inAmount, 0, 0, 0)
171177 $Tuple4(totalDiff, userDiff, outAmount, baseAssetId)
172178 }
173179 else if ((t == "topup"))
174180 then {
175181 let totalLockedArray = readTotalLocked(keyTotalLocked(internalBaseAssetStr))
176182 let totalLockedInBaseAmount = totalLockedArray[IdxTotalLockedInBase]
177183 let totalLockedInShareAmount = totalLockedArray[IdxTotalLockedInShare]
178184 let totalDiff = dataTotalLockedInt(totalLockedInShareAmount, (-1 * convertShare2Base(totalLockedInShareAmount, price, priceMult)), totalLockedInBaseAmount, (-1 * convertBase2Share(totalLockedInBaseAmount, price, priceMult)))
179185 $Tuple4(totalDiff, nil, 0, fromBase58String(""))
180186 }
181187 else throw(("Unsupported Type " + t))
182188 }
183189
184190
185191 func TotalLockedStringEntry (action,key,diff) = {
186192 func UPDATE (a,b) = if ((action == "INCREMENT"))
187193 then (a + b)
188194 else if ((action == "DECREMENT"))
189195 then (a - b)
190196 else throw(("Unsupported action " + action))
191197
192198 let dataArray = readTotalLocked(key)
193199 StrE(key, dataTotalLocked(UPDATE(dataArray[IdxTotalLockedInShare], diff[IdxTotalLockedInShare]), UPDATE(dataArray[IdxTotalLockedOutBase], diff[IdxTotalLockedOutBase]), UPDATE(dataArray[IdxTotalLockedInBase], diff[IdxTotalLockedInBase]), UPDATE(dataArray[IdxTotalLockedOutShare], diff[IdxTotalLockedOutShare])))
194200 }
195201
196202
197203 func keyOperation (operationType,internalBaseAssetStr,userAddress,txId) = makeString(["%s%d%s%s", operationType, internalBaseAssetStr, userAddress, txId], SEP)
198204
199205
200206 let IdxOperStatus = 1
201207
202208 let IdxOperInAmount = 2
203209
204210 let IdxOperPrice = 3
205211
206212 let IdxOperOutAmount = 4
207213
208214 let IdxOperStartHeight = 5
209215
210216 let IdxOperStartTimestamp = 6
211217
212218 let IdxOperEndHeight = 7
213219
214220 let IdxOperEndTimestamp = 8
215221
216222 let IdxOperTopupUnlockIdx = 9
217223
218224 func privateDataOperationAllStrings (status,inAssetAmount,price,outAssetAmount,startHeight,startTimestamp,endHeight,endTimestamp,lock) = makeString(["%s%d%d%d%d%d%d%d%d", status, inAssetAmount, price, outAssetAmount, startHeight, startTimestamp, endHeight, endTimestamp, lock], SEP)
219225
220226
221227 func dataOperation (status,inAssetAmount,price,outAssetAmount,startHeight,startTimestamp,endHeight,endTimestamp,topupUnlockIdx) = privateDataOperationAllStrings(status, toString(inAssetAmount), toString(price), toString(outAssetAmount), toString(startHeight), toString(startTimestamp), toString(endHeight), toString(endTimestamp), toString(topupUnlockIdx))
222228
223229
224230 func dataOperationExecutionUpdate (currOperArray,newStatus,newPrice,newOutAmount) = privateDataOperationAllStrings(newStatus, currOperArray[IdxOperInAmount], toString(newPrice), toString(newOutAmount), currOperArray[IdxOperStartHeight], currOperArray[IdxOperStartTimestamp], toString(height), toString(lastBlock.timestamp), currOperArray[IdxOperTopupUnlockIdx])
225231
226232
227233 func readAssetCfgOrFail (baseAssetStr) = {
228234 let key = keyAssetCfg(baseAssetStr)
229235 split(getStringOrFail(key), SEP)
230236 }
231237
232238
233239 let IdxLimitsRemainingBase = 1
234240
235241 let IdxLimitsRemainingShare = 2
236242
237243 func RemainingLimitsStringEntry (key,baseRemainingLimit,shareRemainingLimit) = StrE(key, makeString(["%d%d", toString(baseRemainingLimit), toString(shareRemainingLimit)], SEP))
238244
239245
240246 func TopupMutexIntEntry (internalBaseAssetStr,acquiredHeight) = IntE(keyTopupMutext(internalBaseAssetStr), acquiredHeight)
241247
242248
243249 func genericCalcPrice (internalBaseAssetStr,baseAssetId,topUpBaseAmount,shareAssetId,decimalsMultPrice) = {
244250 let totalLockedArray = readTotalLocked(keyTotalLocked(internalBaseAssetStr))
245251 let totalLockedOutBaseAmount = totalLockedArray[IdxTotalLockedOutBase]
246252 let currIterTotalInBaseAmount = totalLockedArray[IdxTotalLockedInBase]
247253 let baseAssetBalance = assetBalance(this, baseAssetId)
248254 let baseAssetBalanceWCO = (((baseAssetBalance + topUpBaseAmount) - currIterTotalInBaseAmount) - totalLockedOutBaseAmount)
249255 let totalLockedOutShareAmount = totalLockedArray[IdxTotalLockedOutShare]
250256 let currIterTotalInShareAmount = totalLockedArray[IdxTotalLockedInShare]
251257 let shareEmission = value(assetInfo(shareAssetId)).quantity
252258 if ((0 > baseAssetBalanceWCO))
253259 then throw(((("baseAssetBalanceWco < 0: baseAssettBalance=" + toString(baseAssetBalance)) + " baseAssetBalanceWco=") + toString(baseAssetBalanceWCO)))
254260 else {
255261 let lastPrice = getIntOrFail(keyPriceLast(internalBaseAssetStr))
256262 let price = if ((shareEmission == 0))
257263 then lastPrice
258264 else fraction(baseAssetBalanceWCO, decimalsMultPrice, shareEmission)
259265 $Tuple9(price, baseAssetBalance, -1, baseAssetBalanceWCO, shareEmission, currIterTotalInBaseAmount, currIterTotalInShareAmount, totalLockedOutBaseAmount, totalLockedOutShareAmount)
260266 }
261267 }
262268
263269
264270 func calcPrice (internalBaseAssetStr,baseAssetId,shareAssetId,decimalsMultPrice) = genericCalcPrice(internalBaseAssetStr, baseAssetId, 0, shareAssetId, decimalsMultPrice)
265271
266272
273+func getManagerVaultAddressOrThis () = match getString(keyManagerVaultAddress()) {
274+ case s: String =>
275+ addressFromStringValue(s)
276+ case _ =>
277+ this
278+}
279+
280+
281+func managerPublicKeyOrUnit () = {
282+ let managerVaultAddress = getManagerVaultAddressOrThis()
283+ match getString(managerVaultAddress, keyManagerPublicKey()) {
284+ case s: String =>
285+ fromBase58String(s)
286+ case _: Unit =>
287+ unit
288+ case _ =>
289+ throw("Match error")
290+ }
291+ }
292+
293+
294+func isManager (i) = match managerPublicKeyOrUnit() {
295+ case pk: ByteVector =>
296+ (i.callerPublicKey == pk)
297+ case _: Unit =>
298+ (i.caller == this)
299+ case _ =>
300+ throw("Match error")
301+}
302+
303+
304+func mustManager (i) = if (isManager(i))
305+ then true
306+ else throw("permission denied")
307+
308+
267309 func commonSubmit (operationType,i,inAmount,inAssetId,baseAssetStr) = {
268310 let inAssetStr = toBase58String(inAssetId)
269311 let userAddressStr = toString(i.caller)
270312 let baseAssetId = fromBase58String(baseAssetStr)
271313 let cfgArray = readAssetCfgOrFail(baseAssetStr)
272314 let shareAssetStr = cfgArray[IdxCfgShareAssetId]
273315 let shareAssetId = fromBase58String(shareAssetStr)
274316 let decimalsMultBothAssets = parseIntValue(cfgArray[IdxCfgDecimalsMultBothAssets])
275317 let internalBaseAssetStr = cfgArray[IdxCfgInternalBaseAsset]
276318 let limitsKEY = keyLimitsRemaining(internalBaseAssetStr)
277319 let limitsCfgArray = split(getStringOrFail(limitsKEY), SEP)
278320 let limitsRemainingBase = parseIntValue(limitsCfgArray[IdxLimitsRemainingBase])
279321 let limitsRemainingShare = parseIntValue(limitsCfgArray[IdxLimitsRemainingShare])
280322 let isSubmitBlocked = valueOrElse(getBoolean(this, keyShutdownSubmitOperation(internalBaseAssetStr)), false)
281323 if (isSubmitBlocked)
282324 then throw("submit operation is blocked")
283325 else {
284326 let operationsMutex = valueOrElse(getInteger(this, keyTopupMutext(internalBaseAssetStr)), 0)
285327 if (((operationsMutex + 60) > height))
286328 then throw("submit operations are blocked by topup manager")
287329 else {
288330 let diffTuple = calcTotalLockedDiff("submit", operationType, internalBaseAssetStr, 0, 0, inAmount, baseAssetId, shareAssetId)
289331 let limitsRemainingBaseNew = (limitsRemainingBase - diffTuple._2[IdxTotalLockedInBase])
290332 let limitsRemainingShareNew = (limitsRemainingShare - diffTuple._2[IdxTotalLockedInShare])
291333 if (if ((0 > limitsRemainingBaseNew))
292334 then true
293335 else (0 > limitsRemainingShareNew))
294336 then failSubmitLimitsExceeds(limitsRemainingBase, limitsRemainingShare, limitsRemainingBaseNew, limitsRemainingShareNew)
295337 else {
296338 let topUpCurrentIdx = getIntOrFail(keyTopUpCurrentIdx(internalBaseAssetStr))
297339 ((([StrE(keyOperation(operationType, internalBaseAssetStr, userAddressStr, toBase58String(i.transactionId)), dataOperation("PENDING", inAmount, 0, 0, height, lastBlock.timestamp, 0, 0, (topUpCurrentIdx + 1)))] :+ TotalLockedStringEntry("INCREMENT", keyTotalLocked(internalBaseAssetStr), diffTuple._1)) :+ TotalLockedStringEntry("INCREMENT", keyTotalLockedByUser(internalBaseAssetStr, userAddressStr), diffTuple._2)) :+ RemainingLimitsStringEntry(limitsKEY, limitsRemainingBaseNew, limitsRemainingShareNew))
298340 }
299341 }
300342 }
301343 }
302344
303345
304346 func commonExecute (operationType,baseAssetStr,userAddressStr,submitTxIdStr) = {
305347 let userAddress = addressFromStringValue(userAddressStr)
306348 let assetCfgArray = readAssetCfgOrFail(baseAssetStr)
307349 let shareAssetId = fromBase58String(assetCfgArray[IdxCfgShareAssetId])
308350 let internalBaseAssetStr = assetCfgArray[IdxCfgInternalBaseAsset]
309351 let decimalsMultPrice = parseIntValue(assetCfgArray[IdxCfgDecimalsMultPrice])
310352 let baseAssetId = fromBase58String(baseAssetStr)
311353 let opKey = keyOperation(operationType, internalBaseAssetStr, userAddressStr, submitTxIdStr)
312354 let opArray = split(getStringOrFail(opKey), SEP)
313355 let status = opArray[IdxOperStatus]
314356 let inAmount = parseIntValue(opArray[IdxOperInAmount])
315357 let topupUnlockIdx = parseIntValue(opArray[IdxOperTopupUnlockIdx])
316358 let currTopUpIdx = getIntOrFail(keyTopUpCurrentIdx(internalBaseAssetStr))
317359 let priceByTopUpId = getIntOrFail(keyPriceByTopUpIdx(internalBaseAssetStr, topupUnlockIdx))
318360 if ((status != "PENDING"))
319361 then failExecuteGet("Status is not PENDING", baseAssetStr, userAddressStr, submitTxIdStr, operationType)
320362 else if ((topupUnlockIdx > currTopUpIdx))
321363 then failExecuteGet(((("OperLock[" + toString(topupUnlockIdx)) + "] > ") + toString(currTopUpIdx)), baseAssetStr, userAddressStr, submitTxIdStr, operationType)
322364 else {
323365 let diffTuple = calcTotalLockedDiff("execute", operationType, internalBaseAssetStr, priceByTopUpId, decimalsMultPrice, inAmount, baseAssetId, shareAssetId)
324366 let outAmount = diffTuple._3
325367 let outTransferData = if ((diffTuple._4 == baseAssetId))
326368 then [ScriptTransfer(userAddress, outAmount, baseAssetId)]
327369 else [ScriptTransfer(userAddress, outAmount, shareAssetId)]
328370 (((outTransferData :+ StrE(opKey, dataOperationExecutionUpdate(opArray, "FINISHED", priceByTopUpId, outAmount))) :+ TotalLockedStringEntry("DECREMENT", keyTotalLocked(internalBaseAssetStr), diffTuple._1)) :+ TotalLockedStringEntry("DECREMENT", keyTotalLockedByUser(internalBaseAssetStr, userAddressStr), diffTuple._2))
329371 }
330372 }
331373
332374
333375 func privateCurrentSysParamsREST (baseAssetStr) = {
334376 let baseAssetId = fromBase58String(baseAssetStr)
335377 let cfgArray = readAssetCfgOrFail(baseAssetStr)
336378 let shareAssetStr = cfgArray[IdxCfgShareAssetId]
337379 let shareAssetId = fromBase58String(shareAssetStr)
338380 let decimalsMultBothAssetsVal = parseIntValue(cfgArray[IdxCfgDecimalsMultBothAssets])
339381 let decimalsMultPriceVal = parseIntValue(cfgArray[IdxCfgDecimalsMultPrice])
340382 let internalBaseAssetStr = cfgArray[IdxCfgInternalBaseAsset]
341383 let priceAthKEY = keyPriceATH(internalBaseAssetStr)
342384 let priceAthVal = valueOrElse(getInteger(this, priceAthKEY), 0)
343385 let priceLastKEY = keyPriceLast(internalBaseAssetStr)
344386 let priceLastVal = valueOrElse(getInteger(this, priceLastKEY), 0)
345387 let topupLastTimeKEY = keyTopupLastTimestamp(internalBaseAssetStr)
346388 let topupLastTimeVal = valueOrElse(getInteger(this, topupLastTimeKEY), 0)
347389 let sysState = calcPrice(internalBaseAssetStr, baseAssetId, shareAssetId, decimalsMultPriceVal)
348390 $Tuple14(IntE("price", priceLastVal), IntE("decimalsMultPrice", decimalsMultPriceVal), IntE("baseAssetBalance", sysState._2), IntE("-1", sysState._3), IntE("baseAssetBalanceWCO", sysState._4), IntE("shareEmission", sysState._5), IntE("currIterTotalInBaseAmount", sysState._6), IntE("currIterTotalInShareAmount", sysState._7), IntE("totalLockedOutBaseAmount", sysState._8), IntE("totalLockedOutShareAmount", sysState._9), IntE("decimalsMultBothAssets", decimalsMultBothAssetsVal), IntE("priceATH", priceAthVal), IntE("priceRecalculated", sysState._1), IntE("topupLastTimestamp", topupLastTimeVal))
349391 }
350392
351393
352394 @Callable(i)
353395 func adminRegisterAsset (baseAssetStr,shareAssetName,shareAssetDescr,getDelayinBlocks,shutdownManagerAddress,startPrice,topupIntervalInBlocks,topupMaxNegativePart,topupManagerAddress,submitLimitsBaseMax,submitLimitsBaseReset,submitLimitsShareMax,submitLimitsShareReset,adminAddress) = {
354396 let baseAssetId = fromBase58String(baseAssetStr)
355397 let bothAssetsDecimals = value(assetInfo(baseAssetId)).decimals
356398 let decimalsMultBothAssets = pow(10, 0, bothAssetsDecimals, 0, 0, DOWN)
357399 let decimalsMultPrice = ((100 * 1000) * 1000)
358400 let topupMaxNegativePercents = fraction(topupMaxNegativePart, 100, decimalsMultBothAssets)
359401 let baseAssetBalance = assetBalance(this, baseAssetId)
360- if ((i.caller != this))
361- then throw("permissions denied")
362- else if ((baseAssetBalance == 0))
402+ let checkCaller = mustManager(i)
403+ if ((checkCaller == checkCaller))
404+ then if ((baseAssetBalance == 0))
363405 then throw(((toString(this) + " must have any initial balance of ") + baseAssetStr))
364406 else if (isDefined(getString(this, keyAssetCfg(baseAssetStr))))
365407 then throw((baseAssetStr + " has been already registered"))
366408 else if ((toString(addressFromStringValue(shutdownManagerAddress)) != shutdownManagerAddress))
367409 then throw("invalid shutdownManagerAddress")
368410 else if ((toString(addressFromStringValue(topupManagerAddress)) != topupManagerAddress))
369411 then throw("invalid topupManagerAddress")
370412 else if ((0 > getDelayinBlocks))
371413 then throw(("invalid getDelayinBlocks=" + toString(getDelayinBlocks)))
372414 else if (if ((0 >= topupMaxNegativePercents))
373415 then true
374416 else (topupMaxNegativePercents >= 99))
375417 then throw("invalid topupMaxNegativePart parameter")
376418 else {
377419 let shareInitAmount = convertBase2Share(baseAssetBalance, startPrice, decimalsMultPrice)
378420 let shareAssetIssueAction = Issue(shareAssetName, shareAssetDescr, shareInitAmount, bothAssetsDecimals, true)
379421 let shareAssetId = calculateAssetId(shareAssetIssueAction)
380422 let shareAssetStr = toBase58String(shareAssetId)
381423 let internalBaseAssetId = valueOrElse(getInteger(this, keyNextInternalAssetId()), 0)
382424 let internalBaseAssetStr = toString(internalBaseAssetId)
383425 [StrE(keyAssetCfg(baseAssetStr), dataAssetCfg(shareAssetStr, internalBaseAssetStr, decimalsMultBothAssets, decimalsMultPrice, getDelayinBlocks, topupIntervalInBlocks, topupMaxNegativePart, topupManagerAddress, submitLimitsBaseMax, submitLimitsBaseReset, submitLimitsShareMax, submitLimitsShareReset, adminAddress)), StrE(keyMappingsInternal2baseAssetId(internalBaseAssetId), baseAssetStr), StrE(keyMappingsBaseAsset2internalId(baseAssetStr), internalBaseAssetStr), StrE(keyMappingsShare2baseAssetId(shareAssetStr), baseAssetStr), StrE(keyMappingsBaseAsset2shareId(baseAssetStr), shareAssetStr), BooleanEntry(keyShutdownSubmitOperation(internalBaseAssetStr), false), StrE(keyShutdownManager(internalBaseAssetStr), shutdownManagerAddress), IntE(keyNextInternalAssetId(), (internalBaseAssetId + 1)), IntE(keyPriceLast(internalBaseAssetStr), startPrice), IntE(keyPriceHistory(internalBaseAssetStr, height, lastBlock.timestamp), startPrice), IntE(keyTopUpCurrentIdx(internalBaseAssetStr), 0), RemainingLimitsStringEntry(keyLimitsRemaining(internalBaseAssetStr), submitLimitsBaseMax, submitLimitsShareMax), shareAssetIssueAction, ScriptTransfer(addressFromStringValue(topupManagerAddress), shareInitAmount, shareAssetId)]
384426 }
427+ else throw("Strict value is not equal to itself.")
385428 }
386429
387430
388431
389432 @Callable(i)
390433 func shutdownSubmits (internalBaseAssetId) = {
391- let internalBaseAssetIdStr = toString(internalBaseAssetId)
392- let baseAssetIdStr = getStringOrFail(keyMappingsInternal2baseAssetId(internalBaseAssetId))
393- let shutdownManagerAddress = getStringOrFail(keyShutdownManager(internalBaseAssetIdStr))
394- if ((1 > size(baseAssetIdStr)))
395- then throw("invalid internalBaseAssetId")
396- else if ((toString(i.caller) != shutdownManagerAddress))
397- then throw("access denied")
398- else [BooleanEntry(keyShutdownSubmitOperation(toString(internalBaseAssetId)), true)]
434+ let checkCaller = mustManager(i)
435+ if ((checkCaller == checkCaller))
436+ then {
437+ let internalBaseAssetIdStr = toString(internalBaseAssetId)
438+ let baseAssetIdStr = getStringOrFail(keyMappingsInternal2baseAssetId(internalBaseAssetId))
439+ let shutdownManagerAddress = getStringOrFail(keyShutdownManager(internalBaseAssetIdStr))
440+ if ((1 > size(baseAssetIdStr)))
441+ then throw("invalid internalBaseAssetId")
442+ else [BooleanEntry(keyShutdownSubmitOperation(toString(internalBaseAssetId)), true)]
443+ }
444+ else throw("Strict value is not equal to itself.")
399445 }
400446
401447
402448
403449 @Callable(i)
404450 func submitPut () = {
405451 let pmt = value(i.payments[0])
406452 let inAmount = pmt.amount
407453 let inAssetId = value(pmt.assetId)
408454 let baseAssetStr = toBase58String(inAssetId)
409455 commonSubmit("P", i, inAmount, inAssetId, baseAssetStr)
410456 }
411457
412458
413459
414460 @Callable(i)
415461 func submitGet () = {
416462 let pmt = value(i.payments[0])
417463 let inAmount = pmt.amount
418464 let inAssetId = value(pmt.assetId)
419465 let shareAssetStr = toBase58String(inAssetId)
420466 let baseAssetStr = getStringOrFail(keyMappingsShare2baseAssetId(shareAssetStr))
421467 commonSubmit("G", i, inAmount, inAssetId, baseAssetStr)
422468 }
423469
424470
425471
426472 @Callable(i)
427473 func executePut (baseAssetStr,userAddressStr,submitTxIdStr) = commonExecute("P", baseAssetStr, userAddressStr, submitTxIdStr)
428474
429475
430476
431477 @Callable(i)
432478 func executeGet (baseAssetStr,userAddressStr,submitTxIdStr) = commonExecute("G", baseAssetStr, userAddressStr, submitTxIdStr)
433479
434480
435481
436482 @Callable(i)
437483 func operationsMutex (baseAssetStr) = {
438484 let assetCfgArray = readAssetCfgOrFail(baseAssetStr)
439485 let topUpManagerAddressStr = assetCfgArray[IdxCfgTopupManagerAddress]
440486 let internalBaseAssetStr = assetCfgArray[IdxCfgInternalBaseAsset]
441487 if ((toString(i.caller) != topUpManagerAddressStr))
442488 then failTopupManagerOnly(topUpManagerAddressStr)
443489 else [TopupMutexIntEntry(internalBaseAssetStr, height)]
444490 }
445491
446492
447493
448494 @Callable(i)
449495 func topUpBalance (baseAssetStr,income) = {
450496 let baseAssetId = fromBase58String(baseAssetStr)
451497 let cfg = readAssetCfgOrFail(baseAssetStr)
452498 let shareAssetId = fromBase58String(cfg[IdxCfgShareAssetId])
453499 let priceMult = parseIntValue(cfg[IdxCfgDecimalsMultPrice])
454500 let bothAssetMult = parseIntValue(cfg[IdxCfgDecimalsMultBothAssets])
455501 let topupIntervalInBlocks = parseIntValue(cfg[IdxCfgTopupIntervalInBlocks])
456502 let topupMaxNegativePart = parseIntValue(cfg[IdxCfgTopupMaxNegativePart])
457503 let internalBaseAssetStr = cfg[IdxCfgInternalBaseAsset]
458504 let topUpManagerAddressStr = cfg[IdxCfgTopupManagerAddress]
459505 let submitLimitsBaseMax = parseIntValue(cfg[IdxCfgSubmitLimitsBaseMax])
460506 let submitLimitsShareMax = parseIntValue(cfg[IdxCfgSubmitLimitsShareMax])
461507 let topUpCurrentIdxKEY = keyTopUpCurrentIdx(internalBaseAssetStr)
462508 let prevTopUpIdx = getIntOrFail(topUpCurrentIdxKEY)
463509 let currentTopUpIdx = (prevTopUpIdx + 1)
464510 let valid = if ((income > 0))
465511 then {
466512 let pmt = value(i.payments[0])
467513 let pmtAssetId = value(pmt.assetId)
468514 if ((baseAssetId != pmtAssetId))
469515 then throw("attached payment's asset id is NOT matched passed baseAssetStr")
470516 else if ((size(i.payments) > 1))
471517 then throw("only one payment can be attached")
472518 else if ((pmt.amount != income))
473519 then throw("attached payment.amount is NOT matched passed income argument")
474520 else true
475521 }
476522 else if ((0 > income))
477523 then {
478524 let baseBalance = assetBalance(this, baseAssetId)
479525 let allowedAmount = fraction(topupMaxNegativePart, baseBalance, bothAssetMult)
480526 if ((-(income) > allowedAmount))
481527 then throw(("topup negative income couldn't be greater than " + toString(allowedAmount)))
482528 else true
483529 }
484530 else throw("zero income is not allowed")
485531 let topUpLastHeightKEY = keyTopUpLastHeight(internalBaseAssetStr, toString(i.caller))
486532 let topUpLastHeight = valueOrElse(getInteger(this, topUpLastHeightKEY), 0)
487533 if ((toString(i.caller) != topUpManagerAddressStr))
488534 then failTopupManagerOnly(topUpManagerAddressStr)
489535 else if (!(valid))
490536 then throw("validation failed")
491537 else if ((topupIntervalInBlocks > (height - topUpLastHeight)))
492538 then throw((("1 topup per " + toString(topupIntervalInBlocks)) + " blocks from the same address is allowed"))
493539 else {
494540 let price = genericCalcPrice(internalBaseAssetStr, baseAssetId, income, shareAssetId, priceMult)._1
495541 let diffTuple = calcTotalLockedDiff("topup", "", internalBaseAssetStr, price, priceMult, 0, baseAssetId, shareAssetId)
496542 let topupTotalDiff = diffTuple._1
497543 let priceAthKEY = keyPriceATH(internalBaseAssetStr)
498544 let prevPriceATH = valueOrElse(getInteger(this, priceAthKEY), 0)
499545 ((((((([IntE(keyPriceLast(internalBaseAssetStr), price), IntE(keyPriceHistory(internalBaseAssetStr, height, lastBlock.timestamp), price), IntE(keyPriceByTopUpIdx(internalBaseAssetStr, currentTopUpIdx), price), IntE(topUpCurrentIdxKEY, currentTopUpIdx), IntE(priceAthKEY, if ((price > prevPriceATH))
500546 then price
501547 else prevPriceATH), IntE(topUpLastHeightKEY, height)] :+ TotalLockedStringEntry("DECREMENT", keyTotalLocked(internalBaseAssetStr), topupTotalDiff)) :+ TopupMutexIntEntry(internalBaseAssetStr, 0)) :+ IntE(keyTopupLastTimestamp(internalBaseAssetStr), lastBlock.timestamp)) :+ RemainingLimitsStringEntry(keyLimitsRemaining(internalBaseAssetStr), submitLimitsBaseMax, submitLimitsShareMax)) :+ Burn(shareAssetId, topupTotalDiff[IdxTotalLockedInShare])) :+ Reissue(shareAssetId, -(topupTotalDiff[IdxTotalLockedOutShare]), true)) ++ (if ((0 > income))
502548 then [ScriptTransfer(i.caller, -(income), baseAssetId)]
503549 else nil))
504550 }
505551 }
506552
507553
508554
509555 @Callable(i)
510556 func currentSysParamsREST (baseAssetStr) = {
511557 let sysStateTuple = privateCurrentSysParamsREST(baseAssetStr)
512558 let price = sysStateTuple._1.value
513559 let decimalsMultPrice = sysStateTuple._2.value
514560 let baseAssetBalance = sysStateTuple._3.value
515561 let totalLockedBaseAmount = sysStateTuple._4.value
516562 let baseAssetBalanceWCO = sysStateTuple._5.value
517563 let shareEmission = sysStateTuple._6.value
518564 let currIterTotalInBaseAmount = sysStateTuple._7.value
519565 let currIterTotalInShareAmount = sysStateTuple._8.value
520566 let totalLockedOutBaseAmount = sysStateTuple._9.value
521567 let totalLockedOutShareAmount = sysStateTuple._10.value
522568 let decimalsMultBothAssets = sysStateTuple._11.value
523569 let priceATH = sysStateTuple._12.value
524570 let priceRecalculated = sysStateTuple._13.value
525571 let topupLastTime = sysStateTuple._14.value
526572 let restData = makeString(["startCurrentSysParamsREST", toString(price), toString(decimalsMultPrice), toString(baseAssetBalance), toString(totalLockedBaseAmount), toString(baseAssetBalanceWCO), toString(shareEmission), toString(currIterTotalInBaseAmount), toString(currIterTotalInShareAmount), toString(totalLockedOutBaseAmount), toString(totalLockedOutShareAmount), toString(decimalsMultBothAssets), toString(priceATH), toString(priceRecalculated), toString(topupLastTime), "endCurrentSysParamsREST"], SEP)
527573 throw(restData)
528574 }
529575
530576
531577 @Verifier(tx)
532-func verify () = sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String("2Cbd8ozG7A1RyRNC3nNnZgHu7Ru4K3JCfpyPkhqr9zxq"))
578+func verify () = {
579+ let targetPublicKey = match managerPublicKeyOrUnit() {
580+ case pk: ByteVector =>
581+ pk
582+ case _: Unit =>
583+ tx.senderPublicKey
584+ case _ =>
585+ throw("Match error")
586+ }
587+ sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey)
588+ }
533589

github/deemru/w8io/3ef1775 
75.32 ms