tx · 56DAP4Xm6j9Mcqpyodv2E3K8oUTqCrWJcs1sN5k1wtJv 3MsKbBRn4MNQTvLknJgkwjcDf3eFYCRqCKC: -0.03500000 Waves 2023.02.21 09:30 [2459040] smart account 3MsKbBRn4MNQTvLknJgkwjcDf3eFYCRqCKC > SELF 0.00000000 Waves
{ "type": 13, "id": "56DAP4Xm6j9Mcqpyodv2E3K8oUTqCrWJcs1sN5k1wtJv", "fee": 3500000, "feeAssetId": null, "timestamp": 1676961052999, "version": 1, "sender": "3MsKbBRn4MNQTvLknJgkwjcDf3eFYCRqCKC", "senderPublicKey": "6e6PYNUYUtXRU2QBTGRM5u5pifkCkr1MVU7E5fNHpd6e", "proofs": [ "45BWjEnjqP5AWA6jxNYfv6WCkPHJAKwPkvgyLeRJED4c8ae4VXEZPgiaTPQDEA8oAJmxoFCogzjaLfLPStTRrYXs" ], "script": "base64:BgItCAISCQoHAQEBAQEIARIAEgQKAggIEgMKAQgSBAoCCAgSBAoCCAgSAwoBCBIAQwEPZ2V0U3RyaW5nT3JGYWlsAQNrZXkJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBBQNrZXkJAKwCAgkArAICAg9tYW5kYXRvcnkgdGhpcy4FA2tleQIPIGlzIG5vdCBkZWZpbmVkAANTRVACAl9fAAhCVUZTQ0FMRQkAtgIBAICAkLu61q3wDQAGc2NhbGU4AIDC1y8BCHRocm93RXJyAQNtc2cJAAIBCQC5CQIJAMwIAgIJaWRvLnJpZGU6CQDMCAIFA21zZwUDbmlsAgEgAQhhc1N0cmluZwEDdmFsBAckbWF0Y2gwBQN2YWwDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAZ2YWxTdHIFByRtYXRjaDAFBnZhbFN0cgkAAgECGGZhaWwgdG8gY2FzdCBpbnRvIFN0cmluZwEdY29udmVydFByaWNlQXNzZXRJbnRvSWRvQXNzZXQFEHByaWNlQXNzZXRBbW91bnQOcHJpY2VBc3NldE1VTFQFcHJpY2UJcHJpY2VNVUxUDGlkb0Fzc2V0TVVMVAQPYlByaWNlQXNzZXRNVUxUCQC2AgEFDnByaWNlQXNzZXRNVUxUBA1iSWRvQXNzZXRNVUxUCQC2AgEFDGlkb0Fzc2V0TVVMVAQOYlByaWNlQXNzZXRCVUYJALwCAwkAtgIBBRBwcmljZUFzc2V0QW1vdW50BQhCVUZTQ0FMRQUPYlByaWNlQXNzZXRNVUxUBA9iQW1vdW50QXNzZXRCVUYJALwCAwUOYlByaWNlQXNzZXRCVUYJALYCAQUJcHJpY2VNVUxUCQC2AgEFBXByaWNlCQCgAwEJALwCAwUPYkFtb3VudEFzc2V0QlVGCQC2AgEFDGlkb0Fzc2V0TVVMVAUIQlVGU0NBTEUADklkeENmZ0lkb1N0YXJ0AAEAEUlkeENmZ0lkb0R1cmF0aW9uAAIAEElkeENmZ0NsYWltU3RhcnQAAwATSWR4Q2ZnQ2xhaW1EdXJhdGlvbgAEAAtJZHhDZmdQcmljZQAFAA9JZHhDZmdQcmljZU11bHQABgAQSWR4Q2ZnSWRvQXNzZXRJZAAHABJJZHhDZmdJZG9Bc3NldE11bHQACAASSWR4Q2ZnUHJpY2VBc3NldElkAAkAFElkeENmZ1ByaWNlQXNzZXRNdWx0AAoAFUlkeENmZ01pbkludmVzdEFtb3VudAALAQ1mcm9tYXRDb25maWdTDAhpZG9TdGFydAtpZG9EdXJhdGlvbgpjbGFpbVN0YXJ0DWNsYWltRHVyYXRpb24FcHJpY2UJcHJpY2VNdWx0DGlkb0Fzc2V0SWQ1OAxpZG9Bc3NldE11bHQOcHJpY2VBc3NldElkNTgOcHJpY2VBc3NldE11bHQPbWluSW52ZXN0QW1vdW50E3RvdGFsSWRvQXNzZXRUb1NlbGwJALkJAgkAzAgCAhglZCVkJWQlZCVkJWQlcyVkJXMlZCVkJWQJAMwIAgUIaWRvU3RhcnQJAMwIAgULaWRvRHVyYXRpb24JAMwIAgUKY2xhaW1TdGFydAkAzAgCBQ1jbGFpbUR1cmF0aW9uCQDMCAIFBXByaWNlCQDMCAIFCXByaWNlTXVsdAkAzAgCBQxpZG9Bc3NldElkNTgJAMwIAgUMaWRvQXNzZXRNdWx0CQDMCAIFDnByaWNlQXNzZXRJZDU4CQDMCAIFDnByaWNlQXNzZXRNdWx0CQDMCAIFD21pbkludmVzdEFtb3VudAkAzAgCBRN0b3RhbElkb0Fzc2V0VG9TZWxsBQNuaWwFA1NFUAEMZnJvbWF0Q29uZmlnDAhpZG9TdGFydAtpZG9EdXJhdGlvbgpjbGFpbVN0YXJ0DWNsYWltRHVyYXRpb24FcHJpY2UJcHJpY2VNdWx0DGlkb0Fzc2V0SWQ1OAxpZG9Bc3NldE11bHQOcHJpY2VBc3NldElkNTgOcHJpY2VBc3NldE11bHQPbWluSW52ZXN0QW1vdW50E3RvdGFsSWRvQXNzZXRUb1NlbGwJAQ1mcm9tYXRDb25maWdTDAkApAMBBQhpZG9TdGFydAkApAMBBQtpZG9EdXJhdGlvbgkApAMBBQpjbGFpbVN0YXJ0CQCkAwEFDWNsYWltRHVyYXRpb24JAKQDAQUFcHJpY2UJAKQDAQUJcHJpY2VNdWx0BQxpZG9Bc3NldElkNTgJAKQDAQUMaWRvQXNzZXRNdWx0BQ5wcmljZUFzc2V0SWQ1OAkApAMBBQ5wcmljZUFzc2V0TXVsdAkApAMBBQ9taW5JbnZlc3RBbW91bnQJAKQDAQUTdG90YWxJZG9Bc3NldFRvU2VsbAARSWR4SW52VG90YWxBbW91bnQAAQAVSWR4SW52UmVtYWluaW5nQW1vdW50AAIAHUlkeEludkNsYWltZWRQcmljZUFzc2V0QW1vdW50AAMAG0lkeEludkNsYWltZWRJZG9Bc3NldEFtb3VudAAEABdJZHhJbnZMYXN0Q2xhaW1lZEhlaWdodAAFAQ9mb3JtYXRJbnZlc3RvclMFC3RvdGFsQW1vdW50D3JlbWFpbmluZ0Ftb3VudBdjbGFpbWVkUHJpY2VBc3NldEFtb3VudBVjbGFpbWVkSWRvQXNzZXRBbW91bnQRbGFzdENsYWltZWRIZWlnaHQJALkJAgkAzAgCAgolZCVkJWQlZCVkCQDMCAIFC3RvdGFsQW1vdW50CQDMCAIFD3JlbWFpbmluZ0Ftb3VudAkAzAgCBRdjbGFpbWVkUHJpY2VBc3NldEFtb3VudAkAzAgCBRVjbGFpbWVkSWRvQXNzZXRBbW91bnQJAMwIAgURbGFzdENsYWltZWRIZWlnaHQFA25pbAUDU0VQAQ5mb3JtYXRJbnZlc3RvcgULdG90YWxBbW91bnQPcmVtYWluaW5nQW1vdW50F2NsYWltZWRQcmljZUFzc2V0QW1vdW50FWNsYWltZWRJZG9Bc3NldEFtb3VudBFsYXN0Q2xhaW1lZEhlaWdodAkBD2Zvcm1hdEludmVzdG9yUwUJAKQDAQULdG90YWxBbW91bnQJAKQDAQUPcmVtYWluaW5nQW1vdW50CQCkAwEFF2NsYWltZWRQcmljZUFzc2V0QW1vdW50CQCkAwEFFWNsYWltZWRJZG9Bc3NldEFtb3VudAkApAMBBRFsYXN0Q2xhaW1lZEhlaWdodAETZm9ybWF0SGlzdG9yeVJlY29yZAIQcHJpY2VBc3NldEFtb3VudA5pZG9Bc3NldEFtb3VudAkAuQkCCQDMCAICCCVkJWQlZCVkCQDMCAIJAKQDAQUGaGVpZ2h0CQDMCAIJAKQDAQgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAMwIAgkApAMBBRBwcmljZUFzc2V0QW1vdW50CQDMCAIJAKQDAQUOaWRvQXNzZXRBbW91bnQFA25pbAUDU0VQAQlrZXlDb25maWcAAgolc19fY29uZmlnAQtrZXlJbnZlc3RvcgELdXNlckFkZHJlc3MJAKwCAgIEJXNfXwULdXNlckFkZHJlc3MBCWtleVRvdGFscwACCiVzX190b3RhbHMBGWtleU9wZXJhdGlvbkhpc3RvcnlSZWNvcmQDBHR5cGULdXNlckFkZHJlc3MGdHhJZDU4CQC5CQIJAMwIAgIRJXMlcyVzJXNfX2hpc3RvcnkJAMwIAgUEdHlwZQkAzAgCBQt1c2VyQWRkcmVzcwkAzAgCBQZ0eElkNTgFA25pbAUDU0VQARRrZXlVU0ROQ2xhaW1EaXNhYmxlZAACFSVzX191c2RuQ2xhaW1EaXNhYmxlZAEVa2V5VVNETkNsYWltRW5kSGVpZ2h0AAIWJXNfX3VzZG5DbGFpbUVuZEhlaWdodAEPa2V5UGVyaW9kTGVuZ3RoAAkAuQkCCQDMCAICAiVzCQDMCAICDHBlcmlvZExlbmd0aAUDbmlsBQNTRVABEGtleUN1cnJlbnRQZXJpb2QACQC5CQIJAMwIAgICJXMJAMwIAgINY3VycmVudFBlcmlvZAUDbmlsBQNTRVABFGtleVBlcmlvZFN0YXJ0SGVpZ2h0AQlwZXJpb2ROdW0JALkJAgkAzAgCAgQlcyVzCQDMCAICEXBlcmlvZFN0YXJ0SGVpZ2h0CQDMCAIJAKQDAQUJcGVyaW9kTnVtBQNuaWwFA1NFUAESa2V5UGVyaW9kRW5kSGVpZ2h0AQlwZXJpb2ROdW0JALkJAgkAzAgCAgQlcyVzCQDMCAICD3BlcmlvZEVuZEhlaWdodAkAzAgCCQCkAwEFCXBlcmlvZE51bQUDbmlsBQNTRVABH2tleVVzZHRQcmljZUFzc2V0QWxsb3dhYmxlUmF0aW8ACQC5CQIJAMwIAgICJXMJAMwIAgIcdXNkdFByaWNlQXNzZXRBbGxvd2FibGVSYXRpbwUDbmlsBQNTRVABF2tleVRvdGFsUGVyaW9kQWxsb3dhbmNlAQdhc3NldElkCQC5CQIJAMwIAgIEJXMlcwkAzAgCAhR0b3RhbFBlcmlvZEFsbG93YW5jZQkAzAgCBQdhc3NldElkBQNuaWwFA1NFUAEWa2V5VXNlclBlcmlvZEFsbG93YW5jZQEHYXNzZXRJZAkAuQkCCQDMCAICBCVzJXMJAMwIAgITdXNlclBlcmlvZEFsbG93YW5jZQkAzAgCBQdhc3NldElkBQNuaWwFA1NFUAEea2V5UGVyaW9kVG90YWxBdmFpbGFibGVUb0NsYWltAgdhc3NldElkCXBlcmlvZE51bQkAuQkCCQDMCAICBiVzJXMlcwkAzAgCAhtwZXJpb2RUb3RhbEF2YWlsYWJsZVRvQ2xhaW0JAMwIAgUHYXNzZXRJZAkAzAgCCQCkAwEFCXBlcmlvZE51bQUDbmlsBQNTRVABHWtleVBlcmlvZFVzZXJBdmFpbGFibGVUb0NsYWltAwdhc3NldElkCXBlcmlvZE51bQt1c2VyQWRkcmVzcwkAuQkCCQDMCAICCCVzJXMlcyVzCQDMCAICGnBlcmlvZFVzZXJBdmFpbGFibGVUb0NsYWltCQDMCAIFB2Fzc2V0SWQJAMwIAgkApAMBBQlwZXJpb2ROdW0JAMwIAgULdXNlckFkZHJlc3MFA25pbAUDU0VQARtrZXlVc2R0UHJpY2VBc3NldFN0YWJsZVBvb2wACQC5CQIJAMwIAgICJXMJAMwIAgIYdXNkdFByaWNlQXNzZXRTdGFibGVQb29sBQNuaWwFA1NFUAEOa2V5VXNkdEFzc2V0SWQACQC5CQIJAMwIAgICJXMJAMwIAgILdXNkdEFzc2V0SWQFA25pbAUDU0VQARRrZXlQcmljZUFzc2V0QmFsYW5jZQEHYWRkcmVzcwkAuQkCCQDMCAICBCVzJXMJAMwIAgIRcHJpY2VBc3NldEJhbGFuY2UJAMwIAgUHYWRkcmVzcwUDbmlsBQNTRVABGmtleUludmVzdG9yUmVtYWluaW5nQW1vdW50AQdhZGRyZXNzCQC5CQIJAMwIAgIEJXMlcwkAzAgCAhdpbnZlc3RvclJlbWFpbmluZ0Ftb3VudAkAzAgCBQdhZGRyZXNzBQNuaWwFA1NFUAEXa2V5VG90YWxSZW1haW5pbmdBbW91bnQACQC5CQIJAMwIAgICJXMJAMwIAgIUdG90YWxSZW1haW5pbmdBbW91bnQFA25pbAUDU0VQARNrZXlNYW5hZ2VyUHVibGljS2V5AAIUJXNfX21hbmFnZXJQdWJsaWNLZXkBGmtleVBlbmRpbmdNYW5hZ2VyUHVibGljS2V5AAIbJXNfX3BlbmRpbmdNYW5hZ2VyUHVibGljS2V5AQ9yZWFkQ29uZmlnQXJyYXkACQC1CQIJAQ9nZXRTdHJpbmdPckZhaWwBCQEJa2V5Q29uZmlnAAUDU0VQASNyZWFkVG90YWxzQXJyYXlPckRlZmF1bHRCeUN1c3RvbUtleQEJY3VzdG9tS2V5CQC1CQIJAQt2YWx1ZU9yRWxzZQIJAKIIAQUJY3VzdG9tS2V5CQEPZm9ybWF0SW52ZXN0b3JTBQIBMAIBMAIBMAIBMAIBMAUDU0VQARhyZWFkVG90YWxzQXJyYXlPckRlZmF1bHQACQEjcmVhZFRvdGFsc0FycmF5T3JEZWZhdWx0QnlDdXN0b21LZXkBCQEJa2V5VG90YWxzAAEacmVhZEludmVzdG9yQXJyYXlPckRlZmF1bHQBC3VzZXJBZGRyZXNzCQEjcmVhZFRvdGFsc0FycmF5T3JEZWZhdWx0QnlDdXN0b21LZXkBCQELa2V5SW52ZXN0b3IBBQt1c2VyQWRkcmVzcwEXcmVhZEludmVzdG9yQXJyYXlPckZhaWwBC3VzZXJBZGRyZXNzCQC1CQIJAQ9nZXRTdHJpbmdPckZhaWwBCQELa2V5SW52ZXN0b3IBBQt1c2VyQWRkcmVzcwUDU0VQABVJZHhEaWZmVG90YWxJbmNyZW1lbnQAAAAkSWR4RGlmZlJlbWFpbmluZ1ByaWNlQW1vdW50SW5jcmVtZW50AAEAIklkeERpZmZDbGFpbWVkUHJpY2VBbW91bnRJbmNyZW1lbnQAAgAlSWR4RGlmZkNsYWltZWRJZG9Bc3NldEFtb3VudEluY3JlbWVudAADAQtUb3RhbHNFbnRyeQUDa2V5CW9yaWdBcnJheQ1pbmNyZW1lbnREaWZmFG5ld0xhc3RDbGFpbWVkSGVpZ2h0EXByaWNlQXNzZXRCYWxhbmNlBAt0b3RhbEFtb3VudAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCW9yaWdBcnJheQURSWR4SW52VG90YWxBbW91bnQED3JlbWFpbmluZ0Ftb3VudAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCW9yaWdBcnJheQUVSWR4SW52UmVtYWluaW5nQW1vdW50BBdjbGFpbWVkUHJpY2VBc3NldEFtb3VudAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCW9yaWdBcnJheQUdSWR4SW52Q2xhaW1lZFByaWNlQXNzZXRBbW91bnQEFWNsYWltZWRJZG9Bc3NldEFtb3VudAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCW9yaWdBcnJheQUbSWR4SW52Q2xhaW1lZElkb0Fzc2V0QW1vdW50BBFsYXN0Q2xhaW1lZEhlaWdodAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCW9yaWdBcnJheQUXSWR4SW52TGFzdENsYWltZWRIZWlnaHQEDm5ld1RvdGFsQW1vdW50CQBkAgULdG90YWxBbW91bnQJAJEDAgUNaW5jcmVtZW50RGlmZgUVSWR4RGlmZlRvdGFsSW5jcmVtZW50BBJuZXdSZW1haW5pbmdBbW91bnQJAGQCBQ9yZW1haW5pbmdBbW91bnQJAJEDAgUNaW5jcmVtZW50RGlmZgUkSWR4RGlmZlJlbWFpbmluZ1ByaWNlQW1vdW50SW5jcmVtZW50BAhjZmdBcnJheQkBD3JlYWRDb25maWdBcnJheQAEDnByaWNlQXNzZXRJZDU4CQCRAwIFCGNmZ0FycmF5BRJJZHhDZmdQcmljZUFzc2V0SWQEEnByaWNlQXNzZXREZWNpbWFscwgJAQV2YWx1ZQEJAOwHAQkA2QQBBQ5wcmljZUFzc2V0SWQ1OAhkZWNpbWFscwQjcHJpY2VBc3NldEJhbGFuY2VQcmljZUFzc2V0RGVjaW1hbHMJAGsDBRFwcmljZUFzc2V0QmFsYW5jZQUGc2NhbGU4CQBsBgAKAAAFEnByaWNlQXNzZXREZWNpbWFscwAAAAAFBERPV04EGm5ld0NsYWltZWRQcmljZUFzc2V0QW1vdW50CQBlAgkAZAIFF2NsYWltZWRQcmljZUFzc2V0QW1vdW50CQCRAwIFDWluY3JlbWVudERpZmYFIklkeERpZmZDbGFpbWVkUHJpY2VBbW91bnRJbmNyZW1lbnQFEXByaWNlQXNzZXRCYWxhbmNlBBhuZXdDbGFpbWVkSWRvQXNzZXRBbW91bnQJAGQCCQBkAgUVY2xhaW1lZElkb0Fzc2V0QW1vdW50CQCRAwIFDWluY3JlbWVudERpZmYFJUlkeERpZmZDbGFpbWVkSWRvQXNzZXRBbW91bnRJbmNyZW1lbnQFI3ByaWNlQXNzZXRCYWxhbmNlUHJpY2VBc3NldERlY2ltYWxzBAdlbnRyaWVzAwkAZgIAAAUSbmV3UmVtYWluaW5nQW1vdW50BARkaWZmCQBlAgkAZQIFDm5ld1RvdGFsQW1vdW50BRpuZXdDbGFpbWVkUHJpY2VBc3NldEFtb3VudAUYbmV3Q2xhaW1lZElkb0Fzc2V0QW1vdW50BBduZXdMb2dpY1JlbWFpbmluZ0Ftb3VudAMJAGYCAAAFBGRpZmYAAAUEZGlmZgkBC1N0cmluZ0VudHJ5AgUDa2V5CQEOZm9ybWF0SW52ZXN0b3IFBQ5uZXdUb3RhbEFtb3VudAUXbmV3TG9naWNSZW1haW5pbmdBbW91bnQFGm5ld0NsYWltZWRQcmljZUFzc2V0QW1vdW50BRhuZXdDbGFpbWVkSWRvQXNzZXRBbW91bnQFFG5ld0xhc3RDbGFpbWVkSGVpZ2h0CQELU3RyaW5nRW50cnkCBQNrZXkJAQ5mb3JtYXRJbnZlc3RvcgUFDm5ld1RvdGFsQW1vdW50BRJuZXdSZW1haW5pbmdBbW91bnQFGm5ld0NsYWltZWRQcmljZUFzc2V0QW1vdW50BRhuZXdDbGFpbWVkSWRvQXNzZXRBbW91bnQFFG5ld0xhc3RDbGFpbWVkSGVpZ2h0BQdlbnRyaWVzARtJbnZlc3RPcGVyYXRpb25IaXN0b3J5RW50cnkEC3VzZXJBZGRyZXNzEHByaWNlQXNzZXRBbW91bnQOaWRvQXNzZXRBbW91bnQEdHhJZAkBC1N0cmluZ0VudHJ5AgkBGWtleU9wZXJhdGlvbkhpc3RvcnlSZWNvcmQDAgZpbnZlc3QFC3VzZXJBZGRyZXNzCQDYBAEFBHR4SWQJARNmb3JtYXRIaXN0b3J5UmVjb3JkAgUQcHJpY2VBc3NldEFtb3VudAUOaWRvQXNzZXRBbW91bnQBGkNsYWltT3BlcmF0aW9uSGlzdG9yeUVudHJ5BAt1c2VyQWRkcmVzcxBwcmljZUFzc2V0QW1vdW50Dmlkb0Fzc2V0QW1vdW50BHR4SWQJAQtTdHJpbmdFbnRyeQIJARlrZXlPcGVyYXRpb25IaXN0b3J5UmVjb3JkAwIFY2xhaW0FC3VzZXJBZGRyZXNzCQDYBAEFBHR4SWQJARNmb3JtYXRIaXN0b3J5UmVjb3JkAgUQcHJpY2VBc3NldEFtb3VudAUOaWRvQXNzZXRBbW91bnQBDWludGVybmFsQ2xhaW0DEGNsYWltZWRBc3NldElkNTgLdXNlckFkZHJlc3MEdHhJZAQIY2ZnQXJyYXkJAQ9yZWFkQ29uZmlnQXJyYXkABApjbGFpbVN0YXJ0CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUIY2ZnQXJyYXkFEElkeENmZ0NsYWltU3RhcnQEDWNsYWltRHVyYXRpb24JAQ1wYXJzZUludFZhbHVlAQkAkQMCBQhjZmdBcnJheQUTSWR4Q2ZnQ2xhaW1EdXJhdGlvbgQIY2xhaW1FbmQJAGQCBQpjbGFpbVN0YXJ0BQ1jbGFpbUR1cmF0aW9uBAVwcmljZQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCGNmZ0FycmF5BQtJZHhDZmdQcmljZQQJcHJpY2VNdWx0CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUIY2ZnQXJyYXkFD0lkeENmZ1ByaWNlTXVsdAQMaWRvQXNzZXRJZDU4CQCRAwIFCGNmZ0FycmF5BRBJZHhDZmdJZG9Bc3NldElkBAppZG9Bc3NldElkCQDZBAEFDGlkb0Fzc2V0SWQ1OAQMaWRvQXNzZXRNdWx0CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUIY2ZnQXJyYXkFEklkeENmZ0lkb0Fzc2V0TXVsdAQOcHJpY2VBc3NldElkNTgJAJEDAgUIY2ZnQXJyYXkFEklkeENmZ1ByaWNlQXNzZXRJZAQMcHJpY2VBc3NldElkCQDZBAEFDnByaWNlQXNzZXRJZDU4BA5wcmljZUFzc2V0TXVsdAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCGNmZ0FycmF5BRRJZHhDZmdQcmljZUFzc2V0TXVsdAQNdXNlckFkZHJlc3M1OAkApQgBBQt1c2VyQWRkcmVzcwQPb3JpZ0ludmVzdEFycmF5CQEXcmVhZEludmVzdG9yQXJyYXlPckZhaWwBBQ11c2VyQWRkcmVzczU4BBFpbnZlc3RUb3RhbEFtb3VudAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFD29yaWdJbnZlc3RBcnJheQURSWR4SW52VG90YWxBbW91bnQEGmludmVzdExhc3RDbGFpbWVkSGVpZ2h0VE1QCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUPb3JpZ0ludmVzdEFycmF5BRdJZHhJbnZMYXN0Q2xhaW1lZEhlaWdodAQXaW52ZXN0TGFzdENsYWltZWRIZWlnaHQDCQBnAgUKY2xhaW1TdGFydAUaaW52ZXN0TGFzdENsYWltZWRIZWlnaHRUTVAFCmNsYWltU3RhcnQFGmludmVzdExhc3RDbGFpbWVkSGVpZ2h0VE1QBBRuZXdDbGFpbVBlcmlvZEhlaWdodAMJAGYCBQZoZWlnaHQFCGNsYWltRW5kBQhjbGFpbUVuZAMJAGYCBQpjbGFpbVN0YXJ0BQZoZWlnaHQFCmNsYWltU3RhcnQFBmhlaWdodAQOY2xhaW1pbmdCbG9ja3MJAGUCBRRuZXdDbGFpbVBlcmlvZEhlaWdodAUXaW52ZXN0TGFzdENsYWltZWRIZWlnaHQEGGNsYWltaW5nUHJpY2VBc3NldEFtb3VudAkAawMFEWludmVzdFRvdGFsQW1vdW50BQ5jbGFpbWluZ0Jsb2NrcwUNY2xhaW1EdXJhdGlvbgQWY2xhaW1pbmdJZG9Bc3NldEFtb3VudAkBHWNvbnZlcnRQcmljZUFzc2V0SW50b0lkb0Fzc2V0BQUYY2xhaW1pbmdQcmljZUFzc2V0QW1vdW50BQ5wcmljZUFzc2V0TXVsdAUFcHJpY2UFCXByaWNlTXVsdAUMaWRvQXNzZXRNdWx0BAZpc1VTRE4JAAACBRBjbGFpbWVkQXNzZXRJZDU4BQ5wcmljZUFzc2V0SWQ1OAQTaXNVU0ROQ2xhaW1EaXNhYmxlZAkBC3ZhbHVlT3JFbHNlAgkAoAgBCQEUa2V5VVNETkNsYWltRGlzYWJsZWQABwQGY2hlY2tzCQDMCAIDCQEBIQEDBQZpc1VTRE4FE2lzVVNETkNsYWltRGlzYWJsZWQHBgkAAgECFlVTRE4gY2xhaW0gaXMgZGlzYWJsZWQFA25pbAMJAAACBQZjaGVja3MFBmNoZWNrcwMJAAACBRBjbGFpbWVkQXNzZXRJZDU4BQ5wcmljZUFzc2V0SWQ1OAkAmAoGCQDMCAIAAAkAzAgCCQEBLQEFGGNsYWltaW5nUHJpY2VBc3NldEFtb3VudAkAzAgCBRhjbGFpbWluZ1ByaWNlQXNzZXRBbW91bnQJAMwIAgAABQNuaWwFGGNsYWltaW5nUHJpY2VBc3NldEFtb3VudAUMcHJpY2VBc3NldElkBQ9vcmlnSW52ZXN0QXJyYXkFFG5ld0NsYWltUGVyaW9kSGVpZ2h0CQDMCAIFGGNsYWltaW5nUHJpY2VBc3NldEFtb3VudAkAzAgCBRZjbGFpbWluZ0lkb0Fzc2V0QW1vdW50BQNuaWwDCQAAAgUQY2xhaW1lZEFzc2V0SWQ1OAUMaWRvQXNzZXRJZDU4CQCYCgYJAMwIAgAACQDMCAIJAQEtAQUYY2xhaW1pbmdQcmljZUFzc2V0QW1vdW50CQDMCAIAAAkAzAgCBRZjbGFpbWluZ0lkb0Fzc2V0QW1vdW50BQNuaWwFFmNsYWltaW5nSWRvQXNzZXRBbW91bnQFCmlkb0Fzc2V0SWQFD29yaWdJbnZlc3RBcnJheQUUbmV3Q2xhaW1QZXJpb2RIZWlnaHQJAMwIAgUYY2xhaW1pbmdQcmljZUFzc2V0QW1vdW50CQDMCAIFFmNsYWltaW5nSWRvQXNzZXRBbW91bnQFA25pbAkAAgEJAKwCAgIVdW5zdXBwb3J0ZWQgYXNzZXRJZDogBRBjbGFpbWVkQXNzZXRJZDU4CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQ9pbnRlcm5hbENsYWltVjIEDnByaWNlQXNzZXRJZDU4DXVzZXJBZGRyZXNzNTgJb3V0QW1vdW50GXRvdGFsVXNlckF2YWlsYWJsZVRvQ2xhaW0EHnRvdGFsUGVyaW9kUHJpY2VBc3NldEFsbG93YW5jZQkBBXZhbHVlAQkAnwgBCQEXa2V5VG90YWxQZXJpb2RBbGxvd2FuY2UBBQ5wcmljZUFzc2V0SWQ1OAQddXNlclBlcmlvZFByaWNlQXNzZXRBbGxvd2FuY2UJAQV2YWx1ZQEJAJ8IAQkBFmtleVVzZXJQZXJpb2RBbGxvd2FuY2UBBQ5wcmljZUFzc2V0SWQ1OAQMcGVyaW9kTGVuZ3RoCQEFdmFsdWUBCQCfCAEJAQ9rZXlQZXJpb2RMZW5ndGgABA1jdXJyZW50UGVyaW9kCQELdmFsdWVPckVsc2UCCQCfCAEJARBrZXlDdXJyZW50UGVyaW9kAAAABBt6ZXJvUGVyaW9kRW5kSGVpZ2hJc0RlZmluZWQJAQlpc0RlZmluZWQBCQCfCAEJARJrZXlQZXJpb2RFbmRIZWlnaHQBAAAEDSR0MDEzMzAwMTUyMTYDCQBmAgUNY3VycmVudFBlcmlvZAAABBVsYXN0UGVyaW9kU3RhcnRIZWlnaHQJAQV2YWx1ZQEJAJ8IAQkBFGtleVBlcmlvZFN0YXJ0SGVpZ2h0AQUNY3VycmVudFBlcmlvZAQTbGFzdFBlcmlvZEVuZEhlaWdodAkBBXZhbHVlAQkAnwgBCQESa2V5UGVyaW9kRW5kSGVpZ2h0AQUNY3VycmVudFBlcmlvZAQNJHQwMTM1NjQxNDI4NwMJAGYCBQZoZWlnaHQFE2xhc3RQZXJpb2RFbmRIZWlnaHQEFHVwZGF0ZWRDdXJyZW50UGVyaW9kCQBkAgUNY3VycmVudFBlcmlvZAABBAtwZXJpb2RTdGFydAMJAGYCBQZoZWlnaHQJAGQCBRNsYXN0UGVyaW9kRW5kSGVpZ2h0BQxwZXJpb2RMZW5ndGgEF2Jsb2Nrc1RvTGFzdFBlcmlvZFN0YXJ0CQBqAgkAZQIFBmhlaWdodAUTbGFzdFBlcmlvZEVuZEhlaWdodAUMcGVyaW9kTGVuZ3RoAwkAAAIFF2Jsb2Nrc1RvTGFzdFBlcmlvZFN0YXJ0AAAJAGQCCQBlAgUGaGVpZ2h0BQxwZXJpb2RMZW5ndGgAAQkAZQIFBmhlaWdodAUXYmxvY2tzVG9MYXN0UGVyaW9kU3RhcnQJAGQCBRNsYXN0UGVyaW9kRW5kSGVpZ2h0AAEECXBlcmlvZEVuZAkAZQIJAGQCBQtwZXJpb2RTdGFydAUMcGVyaW9kTGVuZ3RoAAEJAJUKAwUUdXBkYXRlZEN1cnJlbnRQZXJpb2QFC3BlcmlvZFN0YXJ0BQlwZXJpb2RFbmQJAJUKAwUNY3VycmVudFBlcmlvZAUVbGFzdFBlcmlvZFN0YXJ0SGVpZ2h0BRNsYXN0UGVyaW9kRW5kSGVpZ2h0BBR1cGRhdGVkQ3VycmVudFBlcmlvZAgFDSR0MDEzNTY0MTQyODcCXzEEC3BlcmlvZFN0YXJ0CAUNJHQwMTM1NjQxNDI4NwJfMgQJcGVyaW9kRW5kCAUNJHQwMTM1NjQxNDI4NwJfMwkAlQoDBRR1cGRhdGVkQ3VycmVudFBlcmlvZAULcGVyaW9kU3RhcnQFCXBlcmlvZEVuZAMFG3plcm9QZXJpb2RFbmRIZWlnaElzRGVmaW5lZAQVemVyb1BlcmlvZFN0YXJ0SGVpZ2h0CQEFdmFsdWUBCQCfCAEJARRrZXlQZXJpb2RTdGFydEhlaWdodAEAAAQTemVyb1BlcmlvZEVuZEhlaWdodAkBBXZhbHVlAQkAnwgBCQESa2V5UGVyaW9kRW5kSGVpZ2h0AQAABA0kdDAxNDU0OTE0OTM5AwkAZgIFBmhlaWdodAUTemVyb1BlcmlvZEVuZEhlaWdodAQUdXBkYXRlZEN1cnJlbnRQZXJpb2QJAGQCBQ1jdXJyZW50UGVyaW9kAAEEC3BlcmlvZFN0YXJ0CQBkAgUTemVyb1BlcmlvZEVuZEhlaWdodAABBAlwZXJpb2RFbmQJAGUCCQBkAgULcGVyaW9kU3RhcnQFDHBlcmlvZExlbmd0aAABCQCVCgMFFHVwZGF0ZWRDdXJyZW50UGVyaW9kBQtwZXJpb2RTdGFydAUJcGVyaW9kRW5kCQCVCgMFDWN1cnJlbnRQZXJpb2QFFXplcm9QZXJpb2RTdGFydEhlaWdodAUTemVyb1BlcmlvZEVuZEhlaWdodAQUdXBkYXRlZEN1cnJlbnRQZXJpb2QIBQ0kdDAxNDU0OTE0OTM5Al8xBAtwZXJpb2RTdGFydAgFDSR0MDE0NTQ5MTQ5MzkCXzIECXBlcmlvZEVuZAgFDSR0MDE0NTQ5MTQ5MzkCXzMJAJUKAwUUdXBkYXRlZEN1cnJlbnRQZXJpb2QFC3BlcmlvZFN0YXJ0BQlwZXJpb2RFbmQJAJUKAwUNY3VycmVudFBlcmlvZAkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEUa2V5UGVyaW9kU3RhcnRIZWlnaHQBBQ1jdXJyZW50UGVyaW9kBQZoZWlnaHQJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBEmtleVBlcmlvZEVuZEhlaWdodAEFDWN1cnJlbnRQZXJpb2QJAGUCCQBkAgUGaGVpZ2h0BQxwZXJpb2RMZW5ndGgAAQQUdXBkYXRlZEN1cnJlbnRQZXJpb2QIBQ0kdDAxMzMwMDE1MjE2Al8xBAtwZXJpb2RTdGFydAgFDSR0MDEzMzAwMTUyMTYCXzIECXBlcmlvZEVuZAgFDSR0MDEzMzAwMTUyMTYCXzMEG3BlcmlvZFRvdGFsQXZhaWxhYmxlVG9DbGFpbQkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEea2V5UGVyaW9kVG90YWxBdmFpbGFibGVUb0NsYWltAgUOcHJpY2VBc3NldElkNTgFFHVwZGF0ZWRDdXJyZW50UGVyaW9kBR50b3RhbFBlcmlvZFByaWNlQXNzZXRBbGxvd2FuY2UEGnBlcmlvZFVzZXJBdmFpbGFibGVUb0NsYWltCQELdmFsdWVPckVsc2UCCQCfCAEJAR1rZXlQZXJpb2RVc2VyQXZhaWxhYmxlVG9DbGFpbQMFDnByaWNlQXNzZXRJZDU4BRR1cGRhdGVkQ3VycmVudFBlcmlvZAUNdXNlckFkZHJlc3M1OAUddXNlclBlcmlvZFByaWNlQXNzZXRBbGxvd2FuY2UEEXByaWNlQXNzZXRCYWxhbmNlCQELdmFsdWVPckVsc2UCCQCfCAEJARRrZXlQcmljZUFzc2V0QmFsYW5jZQEFDXVzZXJBZGRyZXNzNTgAAAQZcGVyaW9kTWluQXZhaWxhYmxlVG9DbGFpbQkAlwMBCQDMCAIJAGQCBQlvdXRBbW91bnQFEXByaWNlQXNzZXRCYWxhbmNlCQDMCAIFG3BlcmlvZFRvdGFsQXZhaWxhYmxlVG9DbGFpbQkAzAgCBRpwZXJpb2RVc2VyQXZhaWxhYmxlVG9DbGFpbQUDbmlsBBx1c2R0UHJpY2VBc3NldEFsbG93YWJsZVJhdGlvCQEFdmFsdWUBCQCfCAEJAR9rZXlVc2R0UHJpY2VBc3NldEFsbG93YWJsZVJhdGlvAAQbcHV0T25lVGtuVjJQcmljZUFzc2V0QW1vdW50BQZzY2FsZTgEDSR0MDE1OTk0MTYyNTIKAAFACQD8BwQJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQV2YWx1ZQEJAKIIAQkBG2tleVVzZHRQcmljZUFzc2V0U3RhYmxlUG9vbAACIXB1dE9uZVRrblYyV2l0aG91dFRha2VGZWVSRUFET05MWQkAzAgCBRtwdXRPbmVUa25WMlByaWNlQXNzZXRBbW91bnQJAMwIAgUOcHJpY2VBc3NldElkNTgFA25pbAUDbmlsAwkAAQIFAUACDyhJbnQsIEludCwgSW50KQUBQAkAAgEJAKwCAgkAAwEFAUACJCBjb3VsZG4ndCBiZSBjYXN0IHRvIChJbnQsIEludCwgSW50KQMJAAACBQ0kdDAxNTk5NDE2MjUyBQ0kdDAxNTk5NDE2MjUyBAVib251cwgFDSR0MDE1OTk0MTYyNTICXzMECWZlZUFtb3VudAgFDSR0MDE1OTk0MTYyNTICXzIECGxwQW1vdW50CAUNJHQwMTU5OTQxNjI1MgJfMQQLdXNkdEFzc2V0SWQJAQV2YWx1ZQEJAKIIAQkBDmtleVVzZHRBc3NldElkAAQNJHQwMTYzMTgxNjU0MQoAAUAJAPwHBAkBEUBleHRyTmF0aXZlKDEwNjIpAQkBBXZhbHVlAQkAoggBCQEba2V5VXNkdFByaWNlQXNzZXRTdGFibGVQb29sAAITZ2V0T25lVGtuVjJSRUFET05MWQkAzAgCBQt1c2R0QXNzZXRJZAkAzAgCBQhscEFtb3VudAUDbmlsBQNuaWwDCQABAgUBQAIKKEludCwgSW50KQUBQAkAAgEJAKwCAgkAAwEFAUACHyBjb3VsZG4ndCBiZSBjYXN0IHRvIChJbnQsIEludCkDCQAAAgUNJHQwMTYzMTgxNjU0MQUNJHQwMTYzMTgxNjU0MQQUZ2V0T25lVGtuVjJGZWVBbW91bnQIBQ0kdDAxNjMxODE2NTQxAl8yBAp1c2R0QW1vdW50CAUNJHQwMTYzMTgxNjU0MQJfMQQaY3VycmVudFVzZHRQcmljZUFzc2V0UmF0aW8JAGsDBRtwdXRPbmVUa25WMlByaWNlQXNzZXRBbW91bnQFBnNjYWxlOAUKdXNkdEFtb3VudAQTZW5kUGVyaW9kQmxvY2tzTGVmdAkAZQIFCXBlcmlvZEVuZAUGaGVpZ2h0CQCcCgoFGXBlcmlvZE1pbkF2YWlsYWJsZVRvQ2xhaW0FG3BlcmlvZFRvdGFsQXZhaWxhYmxlVG9DbGFpbQUacGVyaW9kVXNlckF2YWlsYWJsZVRvQ2xhaW0FGXRvdGFsVXNlckF2YWlsYWJsZVRvQ2xhaW0FHHVzZHRQcmljZUFzc2V0QWxsb3dhYmxlUmF0aW8FGmN1cnJlbnRVc2R0UHJpY2VBc3NldFJhdGlvBRNlbmRQZXJpb2RCbG9ja3NMZWZ0BRR1cGRhdGVkQ3VycmVudFBlcmlvZAULcGVyaW9kU3RhcnQFCXBlcmlvZEVuZAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgEWbWFuYWdlclB1YmxpY0tleU9yVW5pdAAEByRtYXRjaDAJAKIIAQkBE2tleU1hbmFnZXJQdWJsaWNLZXkAAwkAAQIFByRtYXRjaDACBlN0cmluZwQBcwUHJG1hdGNoMAkA2QQBBQFzAwkAAQIFByRtYXRjaDACBFVuaXQFBHVuaXQJAAIBAgtNYXRjaCBlcnJvcgEdcGVuZGluZ01hbmFnZXJQdWJsaWNLZXlPclVuaXQABAckbWF0Y2gwCQCiCAEJARprZXlQZW5kaW5nTWFuYWdlclB1YmxpY0tleQADCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFzBQckbWF0Y2gwCQDZBAEFAXMDCQABAgUHJG1hdGNoMAIEVW5pdAUEdW5pdAkAAgECC01hdGNoIGVycm9yAQttdXN0TWFuYWdlcgEBaQQCcGQJAAIBAhFQZXJtaXNzaW9uIGRlbmllZAQHJG1hdGNoMAkBFm1hbmFnZXJQdWJsaWNLZXlPclVuaXQAAwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEAnBrBQckbWF0Y2gwAwkAAAIIBQFpD2NhbGxlclB1YmxpY0tleQUCcGsGBQJwZAMJAAECBQckbWF0Y2gwAgRVbml0AwkAAAIIBQFpBmNhbGxlcgUEdGhpcwYFAnBkCQACAQILTWF0Y2ggZXJyb3IIAWkBC2NvbnN0cnVjdG9yBwhpZG9TdGFydAtpZG9EdXJhdGlvbgpjbGFpbVN0YXJ0DWNsYWltRHVyYXRpb24FcHJpY2UOcHJpY2VBc3NldElkNTgPbWluSW52ZXN0QW1vdW50BAlwcmljZU11bHQJAGgCCQBoAgBkAOgHAOgHBAZpZG9FbmQJAGQCBQhpZG9TdGFydAULaWRvRHVyYXRpb24DCQEJaXNEZWZpbmVkAQkAoggBCQEJa2V5Q29uZmlnAAkAAgECE2FscmVhZHkgaW5pdGlhbGl6ZWQDCQECIT0CAiMzUE1FSEx4MWo2emVyYXJaVFlmc0dxRGVlWnFRb01weHE1UwkApQgBCAUBaQZjYWxsZXIJAAIBAg5ub3QgYXV0aG9yaXplZAMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECImV4YWN0bHkgMSBwYXltZW50IG11c3QgYmUgYXR0YWNoZWQDCQBnAgUGaWRvRW5kBQpjbGFpbVN0YXJ0CQACAQImY2xhaW1TdGFydCBtdXN0IGJlIGdyZWF0ZXIgdGhhbiBpZG9FbmQEA3BtdAkBBXZhbHVlAQkAkQMCCAUBaQhwYXltZW50cwAABAppZG9Bc3NldElkCQEFdmFsdWUBCAUDcG10B2Fzc2V0SWQEDGlkb0Fzc2V0SW5mbwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQDsBwEFCmlkb0Fzc2V0SWQCG2ZhaWwgdG8gbG9hZCBpZG8gYXNzZXQgaW5mbwQMaWRvQXNzZXRJZDU4CQDYBAEFCmlkb0Fzc2V0SWQEDGlkb0Fzc2V0TXVsdAkAbAYACgAACAUMaWRvQXNzZXRJbmZvCGRlY2ltYWxzAAAAAAUERE9XTgQMcHJpY2VBc3NldElkCQDZBAEFDnByaWNlQXNzZXRJZDU4BA5wcmljZUFzc2V0SW5mbwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQDsBwEFDHByaWNlQXNzZXRJZAIdZmFpbCB0byBsb2FkIHByaWNlIGFzc2V0IGluZm8EDnByaWNlQXNzZXRNdWx0CQBsBgAKAAAIBQ5wcmljZUFzc2V0SW5mbwhkZWNpbWFscwAAAAAFBERPV04ED29yaWdUb3RhbHNBcnJheQkBGHJlYWRUb3RhbHNBcnJheU9yRGVmYXVsdAAECnRvdGFsc0RpZmYJAMwIAgAACQDMCAIAAAkAzAgCAAAJAMwIAgAABQNuaWwJAMwIAgkBC1N0cmluZ0VudHJ5AgkBCWtleUNvbmZpZwAJAQxmcm9tYXRDb25maWcMBQhpZG9TdGFydAULaWRvRHVyYXRpb24FCmNsYWltU3RhcnQFDWNsYWltRHVyYXRpb24FBXByaWNlBQlwcmljZU11bHQFDGlkb0Fzc2V0SWQ1OAUMaWRvQXNzZXRNdWx0BQ5wcmljZUFzc2V0SWQ1OAUOcHJpY2VBc3NldE11bHQFD21pbkludmVzdEFtb3VudAgFA3BtdAZhbW91bnQJAMwIAgkBC1RvdGFsc0VudHJ5BQkBCWtleVRvdGFscwAFD29yaWdUb3RhbHNBcnJheQUKdG90YWxzRGlmZgUKY2xhaW1TdGFydAAABQNuaWwBaQEGaW52ZXN0AAQIY2ZnQXJyYXkJAQ9yZWFkQ29uZmlnQXJyYXkABAhpZG9TdGFydAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCGNmZ0FycmF5BQ5JZHhDZmdJZG9TdGFydAQLaWRvRHVyYXRpb24JAQ1wYXJzZUludFZhbHVlAQkAkQMCBQhjZmdBcnJheQURSWR4Q2ZnSWRvRHVyYXRpb24EBmlkb0VuZAkAZAIFCGlkb1N0YXJ0BQtpZG9EdXJhdGlvbgQKY2xhaW1TdGFydAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCGNmZ0FycmF5BRBJZHhDZmdDbGFpbVN0YXJ0BA1jbGFpbUR1cmF0aW9uCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUIY2ZnQXJyYXkFE0lkeENmZ0NsYWltRHVyYXRpb24EBXByaWNlCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUIY2ZnQXJyYXkFC0lkeENmZ1ByaWNlBAlwcmljZU11bHQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQhjZmdBcnJheQUPSWR4Q2ZnUHJpY2VNdWx0BAxpZG9Bc3NldElkNTgJAJEDAgUIY2ZnQXJyYXkFEElkeENmZ0lkb0Fzc2V0SWQECmlkb0Fzc2V0SWQJANkEAQUMaWRvQXNzZXRJZDU4BAxpZG9Bc3NldE11bHQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQhjZmdBcnJheQUSSWR4Q2ZnSWRvQXNzZXRNdWx0BA5wcmljZUFzc2V0SWQ1OAkAkQMCBQhjZmdBcnJheQUSSWR4Q2ZnUHJpY2VBc3NldElkBAxwcmljZUFzc2V0SWQJANkEAQUOcHJpY2VBc3NldElkNTgEDnByaWNlQXNzZXRNdWx0CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUIY2ZnQXJyYXkFFElkeENmZ1ByaWNlQXNzZXRNdWx0BA5taW5JdmVzdEFtb3VudAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCGNmZ0FycmF5BRVJZHhDZmdNaW5JbnZlc3RBbW91bnQEC3VzZXJBZGRyZXNzCQClCAEIBQFpBmNhbGxlcgMJAGYCBQhpZG9TdGFydAUGaGVpZ2h0CQACAQIcaWRvIGhhcyBub3QgYmVlbiBzdGFydGVkIHlldAMJAGYCBQZoZWlnaHQFBmlkb0VuZAkAAgECGmlkbyBoYXMgYmVlbiBhbHJlYWR5IGVuZGVkAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQACAQIdZXhhY3RseSAxIHBheW1lbnQgaXMgZXhwZWN0ZWQEA3BtdAkBBXZhbHVlAQkAkQMCCAUBaQhwYXltZW50cwAABApwbXRBc3NldElkCQEFdmFsdWUBCAUDcG10B2Fzc2V0SWQECXBtdEFtb3VudAgFA3BtdAZhbW91bnQDCQECIT0CBQpwbXRBc3NldElkBQxwcmljZUFzc2V0SWQJAAIBCQCsAgIJAKwCAgIaaW52YWxpZCBwYXltZW50IGFzc2V0IGlkOiAJANgEAQUKcG10QXNzZXRJZAIMIGlzIGV4cGVjdGVkBBFvcmlnSW52ZXN0b3JBcnJheQkBGnJlYWRJbnZlc3RvckFycmF5T3JEZWZhdWx0AQULdXNlckFkZHJlc3MED29yaWdUb3RhbHNBcnJheQkBGHJlYWRUb3RhbHNBcnJheU9yRGVmYXVsdAAEE25ld1ByaWNlVG90YWxBbW91bnQJAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUPb3JpZ1RvdGFsc0FycmF5BRFJZHhJbnZUb3RhbEFtb3VudAUJcG10QW1vdW50BBZyZXF1aXJlZElkb0Fzc2V0QW1vdW50CQBoAgUTbmV3UHJpY2VUb3RhbEFtb3VudABkAwkAZgIFFnJlcXVpcmVkSWRvQXNzZXRBbW91bnQJAPAHAgUEdGhpcwUKaWRvQXNzZXRJZAkAAgECOUlETyBhc3NldCBoYXMgYmVlbiAtIHNvbGQgY29uc2lkZXIgdG8gdXNlIHNtYWxsZXIgcGF5bWVudAQKdG90YWxzRGlmZgkAzAgCBQlwbXRBbW91bnQJAMwIAgUJcG10QW1vdW50CQDMCAIAAAkAzAgCAAAFA25pbAkAzAgCCQELVG90YWxzRW50cnkFCQELa2V5SW52ZXN0b3IBBQt1c2VyQWRkcmVzcwURb3JpZ0ludmVzdG9yQXJyYXkFCnRvdGFsc0RpZmYFCmNsYWltU3RhcnQAAAkAzAgCCQELVG90YWxzRW50cnkFCQEJa2V5VG90YWxzAAUPb3JpZ1RvdGFsc0FycmF5BQp0b3RhbHNEaWZmBQpjbGFpbVN0YXJ0AAAJAMwIAgkBG0ludmVzdE9wZXJhdGlvbkhpc3RvcnlFbnRyeQQFC3VzZXJBZGRyZXNzBQlwbXRBbW91bnQAAAgFAWkNdHJhbnNhY3Rpb25JZAUDbmlsAWkBBWNsYWltAhBjbGFpbWVkQXNzZXRJZDU4DXVzZXJBZGRyZXNzNTgED2NhbGxlckFkZHJlc3M1OAkApQgBCAUBaQZjYWxsZXIDCQECIT0CBQ11c2VyQWRkcmVzczU4BQ9jYWxsZXJBZGRyZXNzNTgJAAIBAg5ub3QgYXV0aG9yaXplZAQIY2ZnQXJyYXkJAQ9yZWFkQ29uZmlnQXJyYXkABA5wcmljZUFzc2V0SWQ1OAkAkQMCBQhjZmdBcnJheQUSSWR4Q2ZnUHJpY2VBc3NldElkBBBjbGFpbVJlc3VsdFR1cGxlCQENaW50ZXJuYWxDbGFpbQMFEGNsYWltZWRBc3NldElkNTgIBQFpBmNhbGxlcggFAWkNdHJhbnNhY3Rpb25JZAQKdG90YWxzRGlmZggFEGNsYWltUmVzdWx0VHVwbGUCXzEECW91dEFtb3VudAgFEGNsYWltUmVzdWx0VHVwbGUCXzIECm91dEFzc2V0SWQIBRBjbGFpbVJlc3VsdFR1cGxlAl8zBA9vcmlnSW52ZXN0QXJyYXkIBRBjbGFpbVJlc3VsdFR1cGxlAl80BBRuZXdDbGFpbVBlcmlvZEhlaWdodAgFEGNsYWltUmVzdWx0VHVwbGUCXzUEGmNsYWltZWRQcmljZUFtb3VudEZyb21EaWZmCQCRAwIFCnRvdGFsc0RpZmYFIklkeERpZmZDbGFpbWVkUHJpY2VBbW91bnRJbmNyZW1lbnQEHWNsYWltZWRJZG9Bc3NldEFtb3VudEZyb21EaWZmCQCRAwIFCnRvdGFsc0RpZmYFJUlkeERpZmZDbGFpbWVkSWRvQXNzZXRBbW91bnRJbmNyZW1lbnQEEXByaWNlQXNzZXRCYWxhbmNlCQELdmFsdWVPckVsc2UCCQCfCAEJARRrZXlQcmljZUFzc2V0QmFsYW5jZQEFDXVzZXJBZGRyZXNzNTgAAAQScHJpY2VBc3NldERlY2ltYWxzCAkBBXZhbHVlAQkA7AcBCQDZBAEFDnByaWNlQXNzZXRJZDU4CGRlY2ltYWxzBAdlbnRyaWVzAwkAAAIFEGNsYWltZWRBc3NldElkNTgFDnByaWNlQXNzZXRJZDU4BA0kdDAyMjU4ODIzMDQ4CQEPaW50ZXJuYWxDbGFpbVYyBAUOcHJpY2VBc3NldElkNTgFDXVzZXJBZGRyZXNzNTgFCW91dEFtb3VudAkAkQMCBQp0b3RhbHNEaWZmBSJJZHhEaWZmQ2xhaW1lZFByaWNlQW1vdW50SW5jcmVtZW50BBlwZXJpb2RNaW5BdmFpbGFibGVUb0NsYWltCAUNJHQwMjI1ODgyMzA0OAJfMQQbcGVyaW9kVG90YWxBdmFpbGFibGVUb0NsYWltCAUNJHQwMjI1ODgyMzA0OAJfMgQacGVyaW9kVXNlckF2YWlsYWJsZVRvQ2xhaW0IBQ0kdDAyMjU4ODIzMDQ4Al8zBBl0b3RhbFVzZXJBdmFpbGFibGVUb0NsYWltCAUNJHQwMjI1ODgyMzA0OAJfNAQcdXNkdFByaWNlQXNzZXRBbGxvd2FibGVSYXRpbwgFDSR0MDIyNTg4MjMwNDgCXzUEGmN1cnJlbnRVc2R0UHJpY2VBc3NldFJhdGlvCAUNJHQwMjI1ODgyMzA0OAJfNgQTZW5kUGVyaW9kQmxvY2tzTGVmdAgFDSR0MDIyNTg4MjMwNDgCXzcEFHVwZGF0ZWRDdXJyZW50UGVyaW9kCAUNJHQwMjI1ODgyMzA0OAJfOAQLcGVyaW9kU3RhcnQIBQ0kdDAyMjU4ODIzMDQ4Al85BAlwZXJpb2RFbmQIBQ0kdDAyMjU4ODIzMDQ4A18xMAQGY2hlY2tzCQDMCAIDCQBmAgUacGVyaW9kVXNlckF2YWlsYWJsZVRvQ2xhaW0AAAYJAQh0aHJvd0VycgECOnVuYXZhaWxhYmxlIHRvIGNsYWltIGJlY2F1c2UgdXNlciBwZXJpb2QgYWxsb3dhbmNlIHJlYWNoZWQJAMwIAgMJAGYCBRtwZXJpb2RUb3RhbEF2YWlsYWJsZVRvQ2xhaW0AAAYJAQh0aHJvd0VycgECO3VuYXZhaWxhYmxlIHRvIGNsYWltIGJlY2F1c2UgdG90YWwgcGVyaW9kIGFsbG93YW5jZSByZWFjaGVkCQDMCAIDCQBmAgUZcGVyaW9kTWluQXZhaWxhYmxlVG9DbGFpbQAABgkBCHRocm93RXJyAQIQbm90aGluZyB0byBjbGFpbQkAzAgCAwkAZgIFHHVzZHRQcmljZUFzc2V0QWxsb3dhYmxlUmF0aW8FGmN1cnJlbnRVc2R0UHJpY2VBc3NldFJhdGlvBgkBCHRocm93RXJyAQJPdW5hdmFpbGFibGUgdG8gY2xhaW0gYmVjYXVzZSB1c2RuIHByaWNlIGxvd2VyIHRoYW4gdXNkdFByaWNlQXNzZXRBbGxvd2FibGVSYXRpbwUDbmlsAwkAAAIFBmNoZWNrcwUGY2hlY2tzBCJ1cGRhdGVkUGVyaW9kVG90YWxBdmFpbGFibGVUb0NsYWltCQBlAgUbcGVyaW9kVG90YWxBdmFpbGFibGVUb0NsYWltBRlwZXJpb2RNaW5BdmFpbGFibGVUb0NsYWltBCF1cGRhdGVkUGVyaW9kVXNlckF2YWlsYWJsZVRvQ2xhaW0JAGUCBRpwZXJpb2RVc2VyQXZhaWxhYmxlVG9DbGFpbQUZcGVyaW9kTWluQXZhaWxhYmxlVG9DbGFpbQQHZW50cmllcwMJAGYCBRFwcmljZUFzc2V0QmFsYW5jZQUZcGVyaW9kTWluQXZhaWxhYmxlVG9DbGFpbQkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIFGXBlcmlvZE1pbkF2YWlsYWJsZVRvQ2xhaW0FCm91dEFzc2V0SWQJAMwIAgkBDEludGVnZXJFbnRyeQIJARRrZXlQcmljZUFzc2V0QmFsYW5jZQEFDXVzZXJBZGRyZXNzNTgJAGUCBRFwcmljZUFzc2V0QmFsYW5jZQUZcGVyaW9kTWluQXZhaWxhYmxlVG9DbGFpbQUDbmlsBA5ldmFsdWF0ZVJlc3VsdAkAtQkCCQEIYXNTdHJpbmcBCQD8BwQFBHRoaXMCDWNsYWltUkVBRE9OTFkJAMwIAgUOcHJpY2VBc3NldElkNTgJAMwIAgUNdXNlckFkZHJlc3M1OAUDbmlsBQNuaWwFA1NFUAMJAAACBQ5ldmFsdWF0ZVJlc3VsdAUOZXZhbHVhdGVSZXN1bHQEG2F2YWlsYWJsZVByaWNlQW1vdW50VG9DbGFpbQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFDmV2YWx1YXRlUmVzdWx0AAMEEGxhc3RDbGFpbUVudHJpZXMDCQAAAgUbYXZhaWxhYmxlUHJpY2VBbW91bnRUb0NsYWltBRlwZXJpb2RNaW5BdmFpbGFibGVUb0NsYWltBBNpbnZlc3RvclRvdGFsQW1vdW50CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUPb3JpZ0ludmVzdEFycmF5BRFJZHhJbnZUb3RhbEFtb3VudAQXaW52ZXN0b3JSZW1haW5pbmdBbW91bnQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQ9vcmlnSW52ZXN0QXJyYXkFFUlkeEludlJlbWFpbmluZ0Ftb3VudAQZaW52ZXN0b3JQcmljZUFzc2V0QmFsYW5jZQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFD29yaWdJbnZlc3RBcnJheQUdSWR4SW52Q2xhaW1lZFByaWNlQXNzZXRBbW91bnQEF2ludmVzdG9ySWRvQXNzZXRCYWxhbmNlCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUPb3JpZ0ludmVzdEFycmF5BRtJZHhJbnZDbGFpbWVkSWRvQXNzZXRBbW91bnQEGWludmVzdG9yTGFzdENsYWltZWRIZWlnaHQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQ9vcmlnSW52ZXN0QXJyYXkFF0lkeEludkxhc3RDbGFpbWVkSGVpZ2h0BA5uZXdJbnZlc3RBcnJheQkAzAgCCQCkAwEFE2ludmVzdG9yVG90YWxBbW91bnQJAMwIAgIBMAkAzAgCCQCkAwEFGWludmVzdG9yUHJpY2VBc3NldEJhbGFuY2UJAMwIAgkApAMBBRdpbnZlc3Rvcklkb0Fzc2V0QmFsYW5jZQkAzAgCCQCkAwEFGWludmVzdG9yTGFzdENsYWltZWRIZWlnaHQFA25pbAQGdG90YWxzCQEYcmVhZFRvdGFsc0FycmF5T3JEZWZhdWx0AAQRdG90YWxzVG90YWxBbW91bnQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQZ0b3RhbHMFEUlkeEludlRvdGFsQW1vdW50BBV0b3RhbHNSZW1haW5pbmdBbW91bnQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQZ0b3RhbHMFFUlkeEludlJlbWFpbmluZ0Ftb3VudAQddG90YWxzQ2xhaW1lZFByaWNlQXNzZXRBbW91bnQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQZ0b3RhbHMFHUlkeEludkNsYWltZWRQcmljZUFzc2V0QW1vdW50BBt0b3RhbHNDbGFpbWVkSWRvQXNzZXRBbW91bnQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQZ0b3RhbHMFG0lkeEludkNsYWltZWRJZG9Bc3NldEFtb3VudAQXdG90YWxzTGFzdENsYWltZWRIZWlnaHQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQZ0b3RhbHMFF0lkeEludkxhc3RDbGFpbWVkSGVpZ2h0BBhuZXdUb3RhbHNSZW1haW5pbmdBbW91bnQJAGUCBRV0b3RhbHNSZW1haW5pbmdBbW91bnQFF2ludmVzdG9yUmVtYWluaW5nQW1vdW50BA1uZXdUb3RhbEFycmF5CQDMCAIJAKQDAQURdG90YWxzVG90YWxBbW91bnQJAMwIAgkApAMBBRhuZXdUb3RhbHNSZW1haW5pbmdBbW91bnQJAMwIAgkApAMBBR10b3RhbHNDbGFpbWVkUHJpY2VBc3NldEFtb3VudAkAzAgCCQCkAwEFG3RvdGFsc0NsYWltZWRJZG9Bc3NldEFtb3VudAkAzAgCCQCkAwEFF3RvdGFsc0xhc3RDbGFpbWVkSGVpZ2h0BQNuaWwEF25ld1RvdGFsUmVtYWluaW5nQW1vdW50CQBkAgkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEXa2V5VG90YWxSZW1haW5pbmdBbW91bnQAAAAFF2ludmVzdG9yUmVtYWluaW5nQW1vdW50CQDMCAIJAQtTdHJpbmdFbnRyeQIJARprZXlJbnZlc3RvclJlbWFpbmluZ0Ftb3VudAEFDXVzZXJBZGRyZXNzNTgJAKQDAQUXaW52ZXN0b3JSZW1haW5pbmdBbW91bnQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBF2tleVRvdGFsUmVtYWluaW5nQW1vdW50AAkApAMBBRduZXdUb3RhbFJlbWFpbmluZ0Ftb3VudAkAzAgCCQELVG90YWxzRW50cnkFCQELa2V5SW52ZXN0b3IBBQ11c2VyQWRkcmVzczU4BQ5uZXdJbnZlc3RBcnJheQUKdG90YWxzRGlmZgUUbmV3Q2xhaW1QZXJpb2RIZWlnaHQAAAkAzAgCCQELVG90YWxzRW50cnkFCQEJa2V5VG90YWxzAAUNbmV3VG90YWxBcnJheQUKdG90YWxzRGlmZgUUbmV3Q2xhaW1QZXJpb2RIZWlnaHQAAAUDbmlsCQDMCAIJAQtUb3RhbHNFbnRyeQUJAQtrZXlJbnZlc3RvcgEFDXVzZXJBZGRyZXNzNTgFD29yaWdJbnZlc3RBcnJheQUKdG90YWxzRGlmZgUUbmV3Q2xhaW1QZXJpb2RIZWlnaHQAAAkAzAgCCQELVG90YWxzRW50cnkFCQEJa2V5VG90YWxzAAkBGHJlYWRUb3RhbHNBcnJheU9yRGVmYXVsdAAFCnRvdGFsc0RpZmYFFG5ld0NsYWltUGVyaW9kSGVpZ2h0AAAFA25pbAQYdXBkYXRlZFByaWNlQXNzZXRCYWxhbmNlCQBlAgkAZAIFEXByaWNlQXNzZXRCYWxhbmNlBQlvdXRBbW91bnQFGXBlcmlvZE1pbkF2YWlsYWJsZVRvQ2xhaW0JAM4IAgkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIFGXBlcmlvZE1pbkF2YWlsYWJsZVRvQ2xhaW0FCm91dEFzc2V0SWQJAMwIAgkBDEludGVnZXJFbnRyeQIJARRrZXlQcmljZUFzc2V0QmFsYW5jZQEFDXVzZXJBZGRyZXNzNTgFGHVwZGF0ZWRQcmljZUFzc2V0QmFsYW5jZQUDbmlsBRBsYXN0Q2xhaW1FbnRyaWVzCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQCUCgIJAM4IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEGtleUN1cnJlbnRQZXJpb2QABRR1cGRhdGVkQ3VycmVudFBlcmlvZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBFGtleVBlcmlvZFN0YXJ0SGVpZ2h0AQUUdXBkYXRlZEN1cnJlbnRQZXJpb2QFC3BlcmlvZFN0YXJ0CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQESa2V5UGVyaW9kRW5kSGVpZ2h0AQUUdXBkYXRlZEN1cnJlbnRQZXJpb2QFCXBlcmlvZEVuZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBHmtleVBlcmlvZFRvdGFsQXZhaWxhYmxlVG9DbGFpbQIFDnByaWNlQXNzZXRJZDU4BRR1cGRhdGVkQ3VycmVudFBlcmlvZAUidXBkYXRlZFBlcmlvZFRvdGFsQXZhaWxhYmxlVG9DbGFpbQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBHWtleVBlcmlvZFVzZXJBdmFpbGFibGVUb0NsYWltAwUOcHJpY2VBc3NldElkNTgFFHVwZGF0ZWRDdXJyZW50UGVyaW9kBQ11c2VyQWRkcmVzczU4BSF1cGRhdGVkUGVyaW9kVXNlckF2YWlsYWJsZVRvQ2xhaW0JAMwIAgkBGkNsYWltT3BlcmF0aW9uSGlzdG9yeUVudHJ5BAUNdXNlckFkZHJlc3M1OAUZcGVyaW9kTWluQXZhaWxhYmxlVG9DbGFpbQUdY2xhaW1lZElkb0Fzc2V0QW1vdW50RnJvbURpZmYIBQFpDXRyYW5zYWN0aW9uSWQFA25pbAUHZW50cmllcwUEdW5pdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgQccHJpY2VBc3NldEJhbGFuY2VJZG9EZWNpbWFscwkAawMFEXByaWNlQXNzZXRCYWxhbmNlBQZzY2FsZTgJAGwGAAoAAAUScHJpY2VBc3NldERlY2ltYWxzAAAAAAUERE9XTgkAlAoCCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgkAZAIFCW91dEFtb3VudAUccHJpY2VBc3NldEJhbGFuY2VJZG9EZWNpbWFscwUKb3V0QXNzZXRJZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBFGtleVByaWNlQXNzZXRCYWxhbmNlAQUNdXNlckFkZHJlc3M1OAAACQDMCAIJAQtUb3RhbHNFbnRyeQUJAQtrZXlJbnZlc3RvcgEFDXVzZXJBZGRyZXNzNTgFD29yaWdJbnZlc3RBcnJheQUKdG90YWxzRGlmZgUUbmV3Q2xhaW1QZXJpb2RIZWlnaHQFEXByaWNlQXNzZXRCYWxhbmNlCQDMCAIJAQtUb3RhbHNFbnRyeQUJAQlrZXlUb3RhbHMACQEYcmVhZFRvdGFsc0FycmF5T3JEZWZhdWx0AAUKdG90YWxzRGlmZgUUbmV3Q2xhaW1QZXJpb2RIZWlnaHQFEXByaWNlQXNzZXRCYWxhbmNlCQDMCAIJARpDbGFpbU9wZXJhdGlvbkhpc3RvcnlFbnRyeQQFDXVzZXJBZGRyZXNzNTgFGmNsYWltZWRQcmljZUFtb3VudEZyb21EaWZmCQBkAgUdY2xhaW1lZElkb0Fzc2V0QW1vdW50RnJvbURpZmYFHHByaWNlQXNzZXRCYWxhbmNlSWRvRGVjaW1hbHMIBQFpDXRyYW5zYWN0aW9uSWQFA25pbAUEdW5pdAUHZW50cmllcwFpARJjbGVhblJlbWFpbmdBbW91bnQBDXVzZXJBZGRyZXNzNTgEDnByaWNlQXNzZXRJZDU4CQCRAwIJAQ9yZWFkQ29uZmlnQXJyYXkABRJJZHhDZmdQcmljZUFzc2V0SWQEDmV2YWx1YXRlUmVzdWx0CQC1CQIJAQhhc1N0cmluZwEJAPwHBAUEdGhpcwINY2xhaW1SRUFET05MWQkAzAgCBQ5wcmljZUFzc2V0SWQ1OAkAzAgCBQ11c2VyQWRkcmVzczU4BQNuaWwFA25pbAUDU0VQAwkAAAIFDmV2YWx1YXRlUmVzdWx0BQ5ldmFsdWF0ZVJlc3VsdAQbYXZhaWxhYmxlUHJpY2VBbW91bnRUb0NsYWltCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUOZXZhbHVhdGVSZXN1bHQAAgQUY2hlY2tVbmNsYWltZWRBc3NldHMDCQAAAgUbYXZhaWxhYmxlUHJpY2VBbW91bnRUb0NsYWltAAAGCQEIdGhyb3dFcnIBAhp1c2VyIGhhdmUgdW5jbGFpbWVkIGFzc2V0cwMJAAACBRRjaGVja1VuY2xhaW1lZEFzc2V0cwUUY2hlY2tVbmNsYWltZWRBc3NldHMECGludmVzdG9yCQC1CQIJAQV2YWx1ZQEJAKIIAQkBC2tleUludmVzdG9yAQUNdXNlckFkZHJlc3M1OAUDU0VQBBNpbnZlc3RvclRvdGFsQW1vdW50CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUIaW52ZXN0b3IFEUlkeEludlRvdGFsQW1vdW50BBdpbnZlc3RvclJlbWFpbmluZ0Ftb3VudAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCGludmVzdG9yBRVJZHhJbnZSZW1haW5pbmdBbW91bnQEGWludmVzdG9yUHJpY2VBc3NldEJhbGFuY2UJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQhpbnZlc3RvcgUdSWR4SW52Q2xhaW1lZFByaWNlQXNzZXRBbW91bnQEF2ludmVzdG9ySWRvQXNzZXRCYWxhbmNlCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUIaW52ZXN0b3IFG0lkeEludkNsYWltZWRJZG9Bc3NldEFtb3VudAQZaW52ZXN0b3JMYXN0Q2xhaW1lZEhlaWdodAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCGludmVzdG9yBRdJZHhJbnZMYXN0Q2xhaW1lZEhlaWdodAQcaW52ZXN0b3JSZW1haW5pbmdBbW91bnRDaGVjawMJAQIhPQIFF2ludmVzdG9yUmVtYWluaW5nQW1vdW50AAAGCQEIdGhyb3dFcnIBAiRpbnZlc3RvclJlbWFpbmluZ0Ftb3VudCBhbHJlYWR5IHplcm8DCQAAAgUcaW52ZXN0b3JSZW1haW5pbmdBbW91bnRDaGVjawUcaW52ZXN0b3JSZW1haW5pbmdBbW91bnRDaGVjawQLbmV3SW52ZXN0b3IJALkJAgkAzAgCAgolZCVkJWQlZCVkCQDMCAIJAKQDAQUTaW52ZXN0b3JUb3RhbEFtb3VudAkAzAgCAgEwCQDMCAIJAKQDAQUZaW52ZXN0b3JQcmljZUFzc2V0QmFsYW5jZQkAzAgCCQCkAwEFF2ludmVzdG9ySWRvQXNzZXRCYWxhbmNlCQDMCAIJAKQDAQUZaW52ZXN0b3JMYXN0Q2xhaW1lZEhlaWdodAUDbmlsBQNTRVAEBnRvdGFscwkAtQkCCQEFdmFsdWUBCQCiCAEJAQlrZXlUb3RhbHMABQNTRVAEEXRvdGFsc1RvdGFsQW1vdW50CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUGdG90YWxzBRFJZHhJbnZUb3RhbEFtb3VudAQVdG90YWxzUmVtYWluaW5nQW1vdW50CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUGdG90YWxzBRVJZHhJbnZSZW1haW5pbmdBbW91bnQEHXRvdGFsc0NsYWltZWRQcmljZUFzc2V0QW1vdW50CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUGdG90YWxzBR1JZHhJbnZDbGFpbWVkUHJpY2VBc3NldEFtb3VudAQbdG90YWxzQ2xhaW1lZElkb0Fzc2V0QW1vdW50CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUGdG90YWxzBRtJZHhJbnZDbGFpbWVkSWRvQXNzZXRBbW91bnQEF3RvdGFsc0xhc3RDbGFpbWVkSGVpZ2h0CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUGdG90YWxzBRdJZHhJbnZMYXN0Q2xhaW1lZEhlaWdodAQJbmV3VG90YWxzCQC5CQIJAMwIAgIKJWQlZCVkJWQlZAkAzAgCCQCkAwEFEXRvdGFsc1RvdGFsQW1vdW50CQDMCAIJAKQDAQkAZQIFFXRvdGFsc1JlbWFpbmluZ0Ftb3VudAUXaW52ZXN0b3JSZW1haW5pbmdBbW91bnQJAMwIAgkApAMBBR10b3RhbHNDbGFpbWVkUHJpY2VBc3NldEFtb3VudAkAzAgCCQCkAwEFG3RvdGFsc0NsYWltZWRJZG9Bc3NldEFtb3VudAkAzAgCCQCkAwEFF3RvdGFsc0xhc3RDbGFpbWVkSGVpZ2h0BQNuaWwFA1NFUAQXbmV3VG90YWxSZW1haW5pbmdBbW91bnQJAGQCCQELdmFsdWVPckVsc2UCCQCfCAEJARdrZXlUb3RhbFJlbWFpbmluZ0Ftb3VudAAAAAUXaW52ZXN0b3JSZW1haW5pbmdBbW91bnQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBGmtleUludmVzdG9yUmVtYWluaW5nQW1vdW50AQUNdXNlckFkZHJlc3M1OAkApAMBBRdpbnZlc3RvclJlbWFpbmluZ0Ftb3VudAkAzAgCCQELU3RyaW5nRW50cnkCCQEXa2V5VG90YWxSZW1haW5pbmdBbW91bnQACQCkAwEFF25ld1RvdGFsUmVtYWluaW5nQW1vdW50CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQtrZXlJbnZlc3RvcgEFDXVzZXJBZGRyZXNzNTgFC25ld0ludmVzdG9yCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQlrZXlUb3RhbHMABQluZXdUb3RhbHMFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ1jbGFpbVJFQURPTkxZAhBjbGFpbWVkQXNzZXRJZDU4DXVzZXJBZGRyZXNzNTgEEGNsYWltUmVzdWx0VHVwbGUJAQ1pbnRlcm5hbENsYWltAwUQY2xhaW1lZEFzc2V0SWQ1OAkBEUBleHRyTmF0aXZlKDEwNjIpAQUNdXNlckFkZHJlc3M1OAkA2QQBAgAECnRvdGFsc0RpZmYIBRBjbGFpbVJlc3VsdFR1cGxlAl8xBAlvdXRBbW91bnQIBRBjbGFpbVJlc3VsdFR1cGxlAl8yBApvdXRBc3NldElkCAUQY2xhaW1SZXN1bHRUdXBsZQJfMwQPb3JpZ0ludmVzdEFycmF5CAUQY2xhaW1SZXN1bHRUdXBsZQJfNAQUbmV3Q2xhaW1QZXJpb2RIZWlnaHQIBRBjbGFpbVJlc3VsdFR1cGxlAl81BBVhdmFpbGFibGVUb0NsYWltQXJyYXkIBRBjbGFpbVJlc3VsdFR1cGxlAl82BBthdmFpbGFibGVQcmljZUFtb3VudFRvQ2xhaW0JAJEDAgUVYXZhaWxhYmxlVG9DbGFpbUFycmF5AAAEGWF2YWlsYWJsZUlkb0Ftb3VudFRvQ2xhaW0JAJEDAgUVYXZhaWxhYmxlVG9DbGFpbUFycmF5AAEJAJQKAgUDbmlsCQC5CQIJAMwIAgIGJXMlZCVkCQDMCAIFDXVzZXJBZGRyZXNzNTgJAMwIAgkApAMBBRthdmFpbGFibGVQcmljZUFtb3VudFRvQ2xhaW0JAMwIAgkApAMBBRlhdmFpbGFibGVJZG9BbW91bnRUb0NsYWltBQNuaWwFA1NFUAFpAQ9jbGFpbVYyUkVBRE9OTFkCEGNsYWltZWRBc3NldElkNTgNdXNlckFkZHJlc3M1OAQQY2xhaW1SZXN1bHRUdXBsZQkBDWludGVybmFsQ2xhaW0DBRBjbGFpbWVkQXNzZXRJZDU4CQERQGV4dHJOYXRpdmUoMTA2MikBBQ11c2VyQWRkcmVzczU4CQDZBAECAAQKdG90YWxzRGlmZggFEGNsYWltUmVzdWx0VHVwbGUCXzEECW91dEFtb3VudAgFEGNsYWltUmVzdWx0VHVwbGUCXzIECm91dEFzc2V0SWQIBRBjbGFpbVJlc3VsdFR1cGxlAl8zBA9vcmlnSW52ZXN0QXJyYXkIBRBjbGFpbVJlc3VsdFR1cGxlAl80BBRuZXdDbGFpbVBlcmlvZEhlaWdodAgFEGNsYWltUmVzdWx0VHVwbGUCXzUEFWF2YWlsYWJsZVRvQ2xhaW1BcnJheQgFEGNsYWltUmVzdWx0VHVwbGUCXzYEG2F2YWlsYWJsZVByaWNlQW1vdW50VG9DbGFpbQkAkQMCBRVhdmFpbGFibGVUb0NsYWltQXJyYXkAAAQZYXZhaWxhYmxlSWRvQW1vdW50VG9DbGFpbQkAkQMCBRVhdmFpbGFibGVUb0NsYWltQXJyYXkAAQQIY2ZnQXJyYXkJAQ9yZWFkQ29uZmlnQXJyYXkABA5wcmljZUFzc2V0SWQ1OAkAkQMCBQhjZmdBcnJheQUSSWR4Q2ZnUHJpY2VBc3NldElkBBFwcmljZUFzc2V0QmFsYW5jZQkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEUa2V5UHJpY2VBc3NldEJhbGFuY2UBBQ11c2VyQWRkcmVzczU4AAAEHHByaWNlQXNzZXRCYWxhbmNlSWRvRGVjaW1hbHMJAGgCBRFwcmljZUFzc2V0QmFsYW5jZQBkBC5hdmFpbGFibGVJZG9BbW91bnRUb0NsYWltV2l0aFByaWNlQXNzZXRCYWxhbmNlCQBkAgUZYXZhaWxhYmxlSWRvQW1vdW50VG9DbGFpbQUccHJpY2VBc3NldEJhbGFuY2VJZG9EZWNpbWFscwQNJHQwMzQ1NzIzNTAwMAkBD2ludGVybmFsQ2xhaW1WMgQFDnByaWNlQXNzZXRJZDU4BQ11c2VyQWRkcmVzczU4BQlvdXRBbW91bnQJAJEDAgUKdG90YWxzRGlmZgUiSWR4RGlmZkNsYWltZWRQcmljZUFtb3VudEluY3JlbWVudAQZcGVyaW9kTWluQXZhaWxhYmxlVG9DbGFpbQgFDSR0MDM0NTcyMzUwMDACXzEEG3BlcmlvZFRvdGFsQXZhaWxhYmxlVG9DbGFpbQgFDSR0MDM0NTcyMzUwMDACXzIEGnBlcmlvZFVzZXJBdmFpbGFibGVUb0NsYWltCAUNJHQwMzQ1NzIzNTAwMAJfMwQZdG90YWxVc2VyQXZhaWxhYmxlVG9DbGFpbQgFDSR0MDM0NTcyMzUwMDACXzQEHHVzZHRQcmljZUFzc2V0QWxsb3dhYmxlUmF0aW8IBQ0kdDAzNDU3MjM1MDAwAl81BBpjdXJyZW50VXNkdFByaWNlQXNzZXRSYXRpbwgFDSR0MDM0NTcyMzUwMDACXzYEE2VuZFBlcmlvZEJsb2Nrc0xlZnQIBQ0kdDAzNDU3MjM1MDAwAl83BBR1cGRhdGVkQ3VycmVudFBlcmlvZAgFDSR0MDM0NTcyMzUwMDACXzgEC3BlcmlvZFN0YXJ0CAUNJHQwMzQ1NzIzNTAwMAJfOQQJcGVyaW9kRW5kCAUNJHQwMzQ1NzIzNTAwMANfMTAEFmN1cnJlbnRQZXJpb2RFbmRIZWlnaHQJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBEmtleVBlcmlvZEVuZEhlaWdodAEFFHVwZGF0ZWRDdXJyZW50UGVyaW9kAAAEGnVzZXJUb3RhbFByaWNlQXNzZXRDbGFpbWVkCQBlAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIJARdyZWFkSW52ZXN0b3JBcnJheU9yRmFpbAEFDXVzZXJBZGRyZXNzNTgFHUlkeEludkNsYWltZWRQcmljZUFzc2V0QW1vdW50BRFwcmljZUFzc2V0QmFsYW5jZQQMcmVzdWx0U3RyaW5nAwkAZgIFBmhlaWdodAUWY3VycmVudFBlcmlvZEVuZEhlaWdodAQMcGVyaW9kTGVuZ2h0CQEFdmFsdWUBCQCfCAEJAQ9rZXlQZXJpb2RMZW5ndGgABBN1c2VyUGVyaW9kQWxsb3dhbmNlCQEFdmFsdWUBCQCfCAEJARZrZXlVc2VyUGVyaW9kQWxsb3dhbmNlAQUOcHJpY2VBc3NldElkNTgEFHRvdGFsUGVyaW9kQWxsb3dhbmNlCQEFdmFsdWUBCQCfCAEJARdrZXlUb3RhbFBlcmlvZEFsbG93YW5jZQEFDnByaWNlQXNzZXRJZDU4CQC5CQIJAMwIAgIMJWQlZCVkJWQlZCVkCQDMCAIJAKQDAQUuYXZhaWxhYmxlSWRvQW1vdW50VG9DbGFpbVdpdGhQcmljZUFzc2V0QmFsYW5jZQkAzAgCCQCkAwEFE3VzZXJQZXJpb2RBbGxvd2FuY2UJAMwIAgkApAMBBRR0b3RhbFBlcmlvZEFsbG93YW5jZQkAzAgCCQCkAwEFHHVzZHRQcmljZUFzc2V0QWxsb3dhYmxlUmF0aW8JAMwIAgkApAMBBRpjdXJyZW50VXNkdFByaWNlQXNzZXRSYXRpbwkAzAgCCQCkAwEFDHBlcmlvZExlbmdodAkAzAgCCQCkAwEFGnVzZXJUb3RhbFByaWNlQXNzZXRDbGFpbWVkBQNuaWwFA1NFUAkAuQkCCQDMCAICDCVkJWQlZCVkJWQlZAkAzAgCCQCkAwEFLmF2YWlsYWJsZUlkb0Ftb3VudFRvQ2xhaW1XaXRoUHJpY2VBc3NldEJhbGFuY2UJAMwIAgkApAMBBRlwZXJpb2RNaW5BdmFpbGFibGVUb0NsYWltCQDMCAIJAKQDAQUbcGVyaW9kVG90YWxBdmFpbGFibGVUb0NsYWltCQDMCAIJAKQDAQUcdXNkdFByaWNlQXNzZXRBbGxvd2FibGVSYXRpbwkAzAgCCQCkAwEFGmN1cnJlbnRVc2R0UHJpY2VBc3NldFJhdGlvCQDMCAIJAKQDAQUTZW5kUGVyaW9kQmxvY2tzTGVmdAkAzAgCCQCkAwEFGnVzZXJUb3RhbFByaWNlQXNzZXRDbGFpbWVkBQNuaWwFA1NFUAkAlAoCBQNuaWwFDHJlc3VsdFN0cmluZwFpAQpzZXRNYW5hZ2VyARdwZW5kaW5nTWFuYWdlclB1YmxpY0tleQQLY2hlY2tDYWxsZXIJAQttdXN0TWFuYWdlcgEFAWkDCQAAAgULY2hlY2tDYWxsZXIFC2NoZWNrQ2FsbGVyBBVjaGVja01hbmFnZXJQdWJsaWNLZXkJANkEAQUXcGVuZGluZ01hbmFnZXJQdWJsaWNLZXkDCQAAAgUVY2hlY2tNYW5hZ2VyUHVibGljS2V5BRVjaGVja01hbmFnZXJQdWJsaWNLZXkJAMwIAgkBC1N0cmluZ0VudHJ5AgkBGmtleVBlbmRpbmdNYW5hZ2VyUHVibGljS2V5AAUXcGVuZGluZ01hbmFnZXJQdWJsaWNLZXkFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ5jb25maXJtTWFuYWdlcgAEAnBtCQEdcGVuZGluZ01hbmFnZXJQdWJsaWNLZXlPclVuaXQABAVoYXNQTQMJAQlpc0RlZmluZWQBBQJwbQYJAAIBAhJObyBwZW5kaW5nIG1hbmFnZXIDCQAAAgUFaGFzUE0FBWhhc1BNBAdjaGVja1BNAwkAAAIIBQFpD2NhbGxlclB1YmxpY0tleQkBBXZhbHVlAQUCcG0GCQACAQIbWW91IGFyZSBub3QgcGVuZGluZyBtYW5hZ2VyAwkAAAIFB2NoZWNrUE0FB2NoZWNrUE0JAMwIAgkBC1N0cmluZ0VudHJ5AgkBE2tleU1hbmFnZXJQdWJsaWNLZXkACQDYBAEJAQV2YWx1ZQEFAnBtCQDMCAIJAQtEZWxldGVFbnRyeQEJARprZXlQZW5kaW5nTWFuYWdlclB1YmxpY0tleQAFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgECdHgBBnZlcmlmeQAED3RhcmdldFB1YmxpY0tleQQHJG1hdGNoMAkBFm1hbmFnZXJQdWJsaWNLZXlPclVuaXQAAwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEAnBrBQckbWF0Y2gwBQJwawMJAAECBQckbWF0Y2gwAgRVbml0CAUCdHgPc2VuZGVyUHVibGljS2V5CQACAQILTWF0Y2ggZXJyb3IJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAAFD3RhcmdldFB1YmxpY0tleY/Hcj0=", "chainId": 84, "height": 2459040, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: none Next: 2RBaUrzXVy27U1osHzi1umyZTXFhytwmyREBtPMcs4iK Full:
Old | New | Differences | |
---|---|---|---|
1 | - | # no script | |
1 | + | {-# STDLIB_VERSION 6 #-} | |
2 | + | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | + | {-# CONTENT_TYPE DAPP #-} | |
4 | + | func getStringOrFail (key) = valueOrErrorMessage(getString(key), (("mandatory this." + key) + " is not defined")) | |
5 | + | ||
6 | + | ||
7 | + | let SEP = "__" | |
8 | + | ||
9 | + | let BUFSCALE = toBigInt(1000000000000000000) | |
10 | + | ||
11 | + | let scale8 = 100000000 | |
12 | + | ||
13 | + | func throwErr (msg) = throw(makeString(["ido.ride:", msg], " ")) | |
14 | + | ||
15 | + | ||
16 | + | func asString (val) = match val { | |
17 | + | case valStr: String => | |
18 | + | valStr | |
19 | + | case _ => | |
20 | + | throw("fail to cast into String") | |
21 | + | } | |
22 | + | ||
23 | + | ||
24 | + | func convertPriceAssetIntoIdoAsset (priceAssetAmount,priceAssetMULT,price,priceMULT,idoAssetMULT) = { | |
25 | + | let bPriceAssetMULT = toBigInt(priceAssetMULT) | |
26 | + | let bIdoAssetMULT = toBigInt(idoAssetMULT) | |
27 | + | let bPriceAssetBUF = fraction(toBigInt(priceAssetAmount), BUFSCALE, bPriceAssetMULT) | |
28 | + | let bAmountAssetBUF = fraction(bPriceAssetBUF, toBigInt(priceMULT), toBigInt(price)) | |
29 | + | toInt(fraction(bAmountAssetBUF, toBigInt(idoAssetMULT), BUFSCALE)) | |
30 | + | } | |
31 | + | ||
32 | + | ||
33 | + | let IdxCfgIdoStart = 1 | |
34 | + | ||
35 | + | let IdxCfgIdoDuration = 2 | |
36 | + | ||
37 | + | let IdxCfgClaimStart = 3 | |
38 | + | ||
39 | + | let IdxCfgClaimDuration = 4 | |
40 | + | ||
41 | + | let IdxCfgPrice = 5 | |
42 | + | ||
43 | + | let IdxCfgPriceMult = 6 | |
44 | + | ||
45 | + | let IdxCfgIdoAssetId = 7 | |
46 | + | ||
47 | + | let IdxCfgIdoAssetMult = 8 | |
48 | + | ||
49 | + | let IdxCfgPriceAssetId = 9 | |
50 | + | ||
51 | + | let IdxCfgPriceAssetMult = 10 | |
52 | + | ||
53 | + | let IdxCfgMinInvestAmount = 11 | |
54 | + | ||
55 | + | func fromatConfigS (idoStart,idoDuration,claimStart,claimDuration,price,priceMult,idoAssetId58,idoAssetMult,priceAssetId58,priceAssetMult,minInvestAmount,totalIdoAssetToSell) = makeString(["%d%d%d%d%d%d%s%d%s%d%d%d", idoStart, idoDuration, claimStart, claimDuration, price, priceMult, idoAssetId58, idoAssetMult, priceAssetId58, priceAssetMult, minInvestAmount, totalIdoAssetToSell], SEP) | |
56 | + | ||
57 | + | ||
58 | + | func fromatConfig (idoStart,idoDuration,claimStart,claimDuration,price,priceMult,idoAssetId58,idoAssetMult,priceAssetId58,priceAssetMult,minInvestAmount,totalIdoAssetToSell) = fromatConfigS(toString(idoStart), toString(idoDuration), toString(claimStart), toString(claimDuration), toString(price), toString(priceMult), idoAssetId58, toString(idoAssetMult), priceAssetId58, toString(priceAssetMult), toString(minInvestAmount), toString(totalIdoAssetToSell)) | |
59 | + | ||
60 | + | ||
61 | + | let IdxInvTotalAmount = 1 | |
62 | + | ||
63 | + | let IdxInvRemainingAmount = 2 | |
64 | + | ||
65 | + | let IdxInvClaimedPriceAssetAmount = 3 | |
66 | + | ||
67 | + | let IdxInvClaimedIdoAssetAmount = 4 | |
68 | + | ||
69 | + | let IdxInvLastClaimedHeight = 5 | |
70 | + | ||
71 | + | func formatInvestorS (totalAmount,remainingAmount,claimedPriceAssetAmount,claimedIdoAssetAmount,lastClaimedHeight) = makeString(["%d%d%d%d%d", totalAmount, remainingAmount, claimedPriceAssetAmount, claimedIdoAssetAmount, lastClaimedHeight], SEP) | |
72 | + | ||
73 | + | ||
74 | + | func formatInvestor (totalAmount,remainingAmount,claimedPriceAssetAmount,claimedIdoAssetAmount,lastClaimedHeight) = formatInvestorS(toString(totalAmount), toString(remainingAmount), toString(claimedPriceAssetAmount), toString(claimedIdoAssetAmount), toString(lastClaimedHeight)) | |
75 | + | ||
76 | + | ||
77 | + | func formatHistoryRecord (priceAssetAmount,idoAssetAmount) = makeString(["%d%d%d%d", toString(height), toString(lastBlock.timestamp), toString(priceAssetAmount), toString(idoAssetAmount)], SEP) | |
78 | + | ||
79 | + | ||
80 | + | func keyConfig () = "%s__config" | |
81 | + | ||
82 | + | ||
83 | + | func keyInvestor (userAddress) = ("%s__" + userAddress) | |
84 | + | ||
85 | + | ||
86 | + | func keyTotals () = "%s__totals" | |
87 | + | ||
88 | + | ||
89 | + | func keyOperationHistoryRecord (type,userAddress,txId58) = makeString(["%s%s%s%s__history", type, userAddress, txId58], SEP) | |
90 | + | ||
91 | + | ||
92 | + | func keyUSDNClaimDisabled () = "%s__usdnClaimDisabled" | |
93 | + | ||
94 | + | ||
95 | + | func keyUSDNClaimEndHeight () = "%s__usdnClaimEndHeight" | |
96 | + | ||
97 | + | ||
98 | + | func keyPeriodLength () = makeString(["%s", "periodLength"], SEP) | |
99 | + | ||
100 | + | ||
101 | + | func keyCurrentPeriod () = makeString(["%s", "currentPeriod"], SEP) | |
102 | + | ||
103 | + | ||
104 | + | func keyPeriodStartHeight (periodNum) = makeString(["%s%s", "periodStartHeight", toString(periodNum)], SEP) | |
105 | + | ||
106 | + | ||
107 | + | func keyPeriodEndHeight (periodNum) = makeString(["%s%s", "periodEndHeight", toString(periodNum)], SEP) | |
108 | + | ||
109 | + | ||
110 | + | func keyUsdtPriceAssetAllowableRatio () = makeString(["%s", "usdtPriceAssetAllowableRatio"], SEP) | |
111 | + | ||
112 | + | ||
113 | + | func keyTotalPeriodAllowance (assetId) = makeString(["%s%s", "totalPeriodAllowance", assetId], SEP) | |
114 | + | ||
115 | + | ||
116 | + | func keyUserPeriodAllowance (assetId) = makeString(["%s%s", "userPeriodAllowance", assetId], SEP) | |
117 | + | ||
118 | + | ||
119 | + | func keyPeriodTotalAvailableToClaim (assetId,periodNum) = makeString(["%s%s%s", "periodTotalAvailableToClaim", assetId, toString(periodNum)], SEP) | |
120 | + | ||
121 | + | ||
122 | + | func keyPeriodUserAvailableToClaim (assetId,periodNum,userAddress) = makeString(["%s%s%s%s", "periodUserAvailableToClaim", assetId, toString(periodNum), userAddress], SEP) | |
123 | + | ||
124 | + | ||
125 | + | func keyUsdtPriceAssetStablePool () = makeString(["%s", "usdtPriceAssetStablePool"], SEP) | |
126 | + | ||
127 | + | ||
128 | + | func keyUsdtAssetId () = makeString(["%s", "usdtAssetId"], SEP) | |
129 | + | ||
130 | + | ||
131 | + | func keyPriceAssetBalance (address) = makeString(["%s%s", "priceAssetBalance", address], SEP) | |
132 | + | ||
133 | + | ||
134 | + | func keyInvestorRemainingAmount (address) = makeString(["%s%s", "investorRemainingAmount", address], SEP) | |
135 | + | ||
136 | + | ||
137 | + | func keyTotalRemainingAmount () = makeString(["%s", "totalRemainingAmount"], SEP) | |
138 | + | ||
139 | + | ||
140 | + | func keyManagerPublicKey () = "%s__managerPublicKey" | |
141 | + | ||
142 | + | ||
143 | + | func keyPendingManagerPublicKey () = "%s__pendingManagerPublicKey" | |
144 | + | ||
145 | + | ||
146 | + | func readConfigArray () = split(getStringOrFail(keyConfig()), SEP) | |
147 | + | ||
148 | + | ||
149 | + | func readTotalsArrayOrDefaultByCustomKey (customKey) = split(valueOrElse(getString(customKey), formatInvestorS("0", "0", "0", "0", "0")), SEP) | |
150 | + | ||
151 | + | ||
152 | + | func readTotalsArrayOrDefault () = readTotalsArrayOrDefaultByCustomKey(keyTotals()) | |
153 | + | ||
154 | + | ||
155 | + | func readInvestorArrayOrDefault (userAddress) = readTotalsArrayOrDefaultByCustomKey(keyInvestor(userAddress)) | |
156 | + | ||
157 | + | ||
158 | + | func readInvestorArrayOrFail (userAddress) = split(getStringOrFail(keyInvestor(userAddress)), SEP) | |
159 | + | ||
160 | + | ||
161 | + | let IdxDiffTotalIncrement = 0 | |
162 | + | ||
163 | + | let IdxDiffRemainingPriceAmountIncrement = 1 | |
164 | + | ||
165 | + | let IdxDiffClaimedPriceAmountIncrement = 2 | |
166 | + | ||
167 | + | let IdxDiffClaimedIdoAssetAmountIncrement = 3 | |
168 | + | ||
169 | + | func TotalsEntry (key,origArray,incrementDiff,newLastClaimedHeight,priceAssetBalance) = { | |
170 | + | let totalAmount = parseIntValue(origArray[IdxInvTotalAmount]) | |
171 | + | let remainingAmount = parseIntValue(origArray[IdxInvRemainingAmount]) | |
172 | + | let claimedPriceAssetAmount = parseIntValue(origArray[IdxInvClaimedPriceAssetAmount]) | |
173 | + | let claimedIdoAssetAmount = parseIntValue(origArray[IdxInvClaimedIdoAssetAmount]) | |
174 | + | let lastClaimedHeight = parseIntValue(origArray[IdxInvLastClaimedHeight]) | |
175 | + | let newTotalAmount = (totalAmount + incrementDiff[IdxDiffTotalIncrement]) | |
176 | + | let newRemainingAmount = (remainingAmount + incrementDiff[IdxDiffRemainingPriceAmountIncrement]) | |
177 | + | let cfgArray = readConfigArray() | |
178 | + | let priceAssetId58 = cfgArray[IdxCfgPriceAssetId] | |
179 | + | let priceAssetDecimals = value(assetInfo(fromBase58String(priceAssetId58))).decimals | |
180 | + | let priceAssetBalancePriceAssetDecimals = fraction(priceAssetBalance, scale8, pow(10, 0, priceAssetDecimals, 0, 0, DOWN)) | |
181 | + | let newClaimedPriceAssetAmount = ((claimedPriceAssetAmount + incrementDiff[IdxDiffClaimedPriceAmountIncrement]) - priceAssetBalance) | |
182 | + | let newClaimedIdoAssetAmount = ((claimedIdoAssetAmount + incrementDiff[IdxDiffClaimedIdoAssetAmountIncrement]) + priceAssetBalancePriceAssetDecimals) | |
183 | + | let entries = if ((0 > newRemainingAmount)) | |
184 | + | then { | |
185 | + | let diff = ((newTotalAmount - newClaimedPriceAssetAmount) - newClaimedIdoAssetAmount) | |
186 | + | let newLogicRemainingAmount = if ((0 > diff)) | |
187 | + | then 0 | |
188 | + | else diff | |
189 | + | StringEntry(key, formatInvestor(newTotalAmount, newLogicRemainingAmount, newClaimedPriceAssetAmount, newClaimedIdoAssetAmount, newLastClaimedHeight)) | |
190 | + | } | |
191 | + | else StringEntry(key, formatInvestor(newTotalAmount, newRemainingAmount, newClaimedPriceAssetAmount, newClaimedIdoAssetAmount, newLastClaimedHeight)) | |
192 | + | entries | |
193 | + | } | |
194 | + | ||
195 | + | ||
196 | + | func InvestOperationHistoryEntry (userAddress,priceAssetAmount,idoAssetAmount,txId) = StringEntry(keyOperationHistoryRecord("invest", userAddress, toBase58String(txId)), formatHistoryRecord(priceAssetAmount, idoAssetAmount)) | |
197 | + | ||
198 | + | ||
199 | + | func ClaimOperationHistoryEntry (userAddress,priceAssetAmount,idoAssetAmount,txId) = StringEntry(keyOperationHistoryRecord("claim", userAddress, toBase58String(txId)), formatHistoryRecord(priceAssetAmount, idoAssetAmount)) | |
200 | + | ||
201 | + | ||
202 | + | func internalClaim (claimedAssetId58,userAddress,txId) = { | |
203 | + | let cfgArray = readConfigArray() | |
204 | + | let claimStart = parseIntValue(cfgArray[IdxCfgClaimStart]) | |
205 | + | let claimDuration = parseIntValue(cfgArray[IdxCfgClaimDuration]) | |
206 | + | let claimEnd = (claimStart + claimDuration) | |
207 | + | let price = parseIntValue(cfgArray[IdxCfgPrice]) | |
208 | + | let priceMult = parseIntValue(cfgArray[IdxCfgPriceMult]) | |
209 | + | let idoAssetId58 = cfgArray[IdxCfgIdoAssetId] | |
210 | + | let idoAssetId = fromBase58String(idoAssetId58) | |
211 | + | let idoAssetMult = parseIntValue(cfgArray[IdxCfgIdoAssetMult]) | |
212 | + | let priceAssetId58 = cfgArray[IdxCfgPriceAssetId] | |
213 | + | let priceAssetId = fromBase58String(priceAssetId58) | |
214 | + | let priceAssetMult = parseIntValue(cfgArray[IdxCfgPriceAssetMult]) | |
215 | + | let userAddress58 = toString(userAddress) | |
216 | + | let origInvestArray = readInvestorArrayOrFail(userAddress58) | |
217 | + | let investTotalAmount = parseIntValue(origInvestArray[IdxInvTotalAmount]) | |
218 | + | let investLastClaimedHeightTMP = parseIntValue(origInvestArray[IdxInvLastClaimedHeight]) | |
219 | + | let investLastClaimedHeight = if ((claimStart >= investLastClaimedHeightTMP)) | |
220 | + | then claimStart | |
221 | + | else investLastClaimedHeightTMP | |
222 | + | let newClaimPeriodHeight = if ((height > claimEnd)) | |
223 | + | then claimEnd | |
224 | + | else if ((claimStart > height)) | |
225 | + | then claimStart | |
226 | + | else height | |
227 | + | let claimingBlocks = (newClaimPeriodHeight - investLastClaimedHeight) | |
228 | + | let claimingPriceAssetAmount = fraction(investTotalAmount, claimingBlocks, claimDuration) | |
229 | + | let claimingIdoAssetAmount = convertPriceAssetIntoIdoAsset(claimingPriceAssetAmount, priceAssetMult, price, priceMult, idoAssetMult) | |
230 | + | let isUSDN = (claimedAssetId58 == priceAssetId58) | |
231 | + | let isUSDNClaimDisabled = valueOrElse(getBoolean(keyUSDNClaimDisabled()), false) | |
232 | + | let checks = [if (!(if (isUSDN) | |
233 | + | then isUSDNClaimDisabled | |
234 | + | else false)) | |
235 | + | then true | |
236 | + | else throw("USDN claim is disabled")] | |
237 | + | if ((checks == checks)) | |
238 | + | then if ((claimedAssetId58 == priceAssetId58)) | |
239 | + | then $Tuple6([0, -(claimingPriceAssetAmount), claimingPriceAssetAmount, 0], claimingPriceAssetAmount, priceAssetId, origInvestArray, newClaimPeriodHeight, [claimingPriceAssetAmount, claimingIdoAssetAmount]) | |
240 | + | else if ((claimedAssetId58 == idoAssetId58)) | |
241 | + | then $Tuple6([0, -(claimingPriceAssetAmount), 0, claimingIdoAssetAmount], claimingIdoAssetAmount, idoAssetId, origInvestArray, newClaimPeriodHeight, [claimingPriceAssetAmount, claimingIdoAssetAmount]) | |
242 | + | else throw(("unsupported assetId: " + claimedAssetId58)) | |
243 | + | else throw("Strict value is not equal to itself.") | |
244 | + | } | |
245 | + | ||
246 | + | ||
247 | + | func internalClaimV2 (priceAssetId58,userAddress58,outAmount,totalUserAvailableToClaim) = { | |
248 | + | let totalPeriodPriceAssetAllowance = value(getInteger(keyTotalPeriodAllowance(priceAssetId58))) | |
249 | + | let userPeriodPriceAssetAllowance = value(getInteger(keyUserPeriodAllowance(priceAssetId58))) | |
250 | + | let periodLength = value(getInteger(keyPeriodLength())) | |
251 | + | let currentPeriod = valueOrElse(getInteger(keyCurrentPeriod()), 0) | |
252 | + | let zeroPeriodEndHeighIsDefined = isDefined(getInteger(keyPeriodEndHeight(0))) | |
253 | + | let $t01330015216 = if ((currentPeriod > 0)) | |
254 | + | then { | |
255 | + | let lastPeriodStartHeight = value(getInteger(keyPeriodStartHeight(currentPeriod))) | |
256 | + | let lastPeriodEndHeight = value(getInteger(keyPeriodEndHeight(currentPeriod))) | |
257 | + | let $t01356414287 = if ((height > lastPeriodEndHeight)) | |
258 | + | then { | |
259 | + | let updatedCurrentPeriod = (currentPeriod + 1) | |
260 | + | let periodStart = if ((height > (lastPeriodEndHeight + periodLength))) | |
261 | + | then { | |
262 | + | let blocksToLastPeriodStart = ((height - lastPeriodEndHeight) % periodLength) | |
263 | + | if ((blocksToLastPeriodStart == 0)) | |
264 | + | then ((height - periodLength) + 1) | |
265 | + | else (height - blocksToLastPeriodStart) | |
266 | + | } | |
267 | + | else (lastPeriodEndHeight + 1) | |
268 | + | let periodEnd = ((periodStart + periodLength) - 1) | |
269 | + | $Tuple3(updatedCurrentPeriod, periodStart, periodEnd) | |
270 | + | } | |
271 | + | else $Tuple3(currentPeriod, lastPeriodStartHeight, lastPeriodEndHeight) | |
272 | + | let updatedCurrentPeriod = $t01356414287._1 | |
273 | + | let periodStart = $t01356414287._2 | |
274 | + | let periodEnd = $t01356414287._3 | |
275 | + | $Tuple3(updatedCurrentPeriod, periodStart, periodEnd) | |
276 | + | } | |
277 | + | else if (zeroPeriodEndHeighIsDefined) | |
278 | + | then { | |
279 | + | let zeroPeriodStartHeight = value(getInteger(keyPeriodStartHeight(0))) | |
280 | + | let zeroPeriodEndHeight = value(getInteger(keyPeriodEndHeight(0))) | |
281 | + | let $t01454914939 = if ((height > zeroPeriodEndHeight)) | |
282 | + | then { | |
283 | + | let updatedCurrentPeriod = (currentPeriod + 1) | |
284 | + | let periodStart = (zeroPeriodEndHeight + 1) | |
285 | + | let periodEnd = ((periodStart + periodLength) - 1) | |
286 | + | $Tuple3(updatedCurrentPeriod, periodStart, periodEnd) | |
287 | + | } | |
288 | + | else $Tuple3(currentPeriod, zeroPeriodStartHeight, zeroPeriodEndHeight) | |
289 | + | let updatedCurrentPeriod = $t01454914939._1 | |
290 | + | let periodStart = $t01454914939._2 | |
291 | + | let periodEnd = $t01454914939._3 | |
292 | + | $Tuple3(updatedCurrentPeriod, periodStart, periodEnd) | |
293 | + | } | |
294 | + | else $Tuple3(currentPeriod, valueOrElse(getInteger(keyPeriodStartHeight(currentPeriod)), height), valueOrElse(getInteger(keyPeriodEndHeight(currentPeriod)), ((height + periodLength) - 1))) | |
295 | + | let updatedCurrentPeriod = $t01330015216._1 | |
296 | + | let periodStart = $t01330015216._2 | |
297 | + | let periodEnd = $t01330015216._3 | |
298 | + | let periodTotalAvailableToClaim = valueOrElse(getInteger(keyPeriodTotalAvailableToClaim(priceAssetId58, updatedCurrentPeriod)), totalPeriodPriceAssetAllowance) | |
299 | + | let periodUserAvailableToClaim = valueOrElse(getInteger(keyPeriodUserAvailableToClaim(priceAssetId58, updatedCurrentPeriod, userAddress58)), userPeriodPriceAssetAllowance) | |
300 | + | let priceAssetBalance = valueOrElse(getInteger(keyPriceAssetBalance(userAddress58)), 0) | |
301 | + | let periodMinAvailableToClaim = min([(outAmount + priceAssetBalance), periodTotalAvailableToClaim, periodUserAvailableToClaim]) | |
302 | + | let usdtPriceAssetAllowableRatio = value(getInteger(keyUsdtPriceAssetAllowableRatio())) | |
303 | + | let putOneTknV2PriceAssetAmount = scale8 | |
304 | + | let $t01599416252 = { | |
305 | + | let @ = invoke(addressFromStringValue(value(getString(keyUsdtPriceAssetStablePool()))), "putOneTknV2WithoutTakeFeeREADONLY", [putOneTknV2PriceAssetAmount, priceAssetId58], nil) | |
306 | + | if ($isInstanceOf(@, "(Int, Int, Int)")) | |
307 | + | then @ | |
308 | + | else throw(($getType(@) + " couldn't be cast to (Int, Int, Int)")) | |
309 | + | } | |
310 | + | if (($t01599416252 == $t01599416252)) | |
311 | + | then { | |
312 | + | let bonus = $t01599416252._3 | |
313 | + | let feeAmount = $t01599416252._2 | |
314 | + | let lpAmount = $t01599416252._1 | |
315 | + | let usdtAssetId = value(getString(keyUsdtAssetId())) | |
316 | + | let $t01631816541 = { | |
317 | + | let @ = invoke(addressFromStringValue(value(getString(keyUsdtPriceAssetStablePool()))), "getOneTknV2READONLY", [usdtAssetId, lpAmount], nil) | |
318 | + | if ($isInstanceOf(@, "(Int, Int)")) | |
319 | + | then @ | |
320 | + | else throw(($getType(@) + " couldn't be cast to (Int, Int)")) | |
321 | + | } | |
322 | + | if (($t01631816541 == $t01631816541)) | |
323 | + | then { | |
324 | + | let getOneTknV2FeeAmount = $t01631816541._2 | |
325 | + | let usdtAmount = $t01631816541._1 | |
326 | + | let currentUsdtPriceAssetRatio = fraction(putOneTknV2PriceAssetAmount, scale8, usdtAmount) | |
327 | + | let endPeriodBlocksLeft = (periodEnd - height) | |
328 | + | $Tuple10(periodMinAvailableToClaim, periodTotalAvailableToClaim, periodUserAvailableToClaim, totalUserAvailableToClaim, usdtPriceAssetAllowableRatio, currentUsdtPriceAssetRatio, endPeriodBlocksLeft, updatedCurrentPeriod, periodStart, periodEnd) | |
329 | + | } | |
330 | + | else throw("Strict value is not equal to itself.") | |
331 | + | } | |
332 | + | else throw("Strict value is not equal to itself.") | |
333 | + | } | |
334 | + | ||
335 | + | ||
336 | + | func managerPublicKeyOrUnit () = match getString(keyManagerPublicKey()) { | |
337 | + | case s: String => | |
338 | + | fromBase58String(s) | |
339 | + | case _: Unit => | |
340 | + | unit | |
341 | + | case _ => | |
342 | + | throw("Match error") | |
343 | + | } | |
344 | + | ||
345 | + | ||
346 | + | func pendingManagerPublicKeyOrUnit () = match getString(keyPendingManagerPublicKey()) { | |
347 | + | case s: String => | |
348 | + | fromBase58String(s) | |
349 | + | case _: Unit => | |
350 | + | unit | |
351 | + | case _ => | |
352 | + | throw("Match error") | |
353 | + | } | |
354 | + | ||
355 | + | ||
356 | + | func mustManager (i) = { | |
357 | + | let pd = throw("Permission denied") | |
358 | + | match managerPublicKeyOrUnit() { | |
359 | + | case pk: ByteVector => | |
360 | + | if ((i.callerPublicKey == pk)) | |
361 | + | then true | |
362 | + | else pd | |
363 | + | case _: Unit => | |
364 | + | if ((i.caller == this)) | |
365 | + | then true | |
366 | + | else pd | |
367 | + | case _ => | |
368 | + | throw("Match error") | |
369 | + | } | |
370 | + | } | |
371 | + | ||
372 | + | ||
373 | + | @Callable(i) | |
374 | + | func constructor (idoStart,idoDuration,claimStart,claimDuration,price,priceAssetId58,minInvestAmount) = { | |
375 | + | let priceMult = ((100 * 1000) * 1000) | |
376 | + | let idoEnd = (idoStart + idoDuration) | |
377 | + | if (isDefined(getString(keyConfig()))) | |
378 | + | then throw("already initialized") | |
379 | + | else if (("3PMEHLx1j6zerarZTYfsGqDeeZqQoMpxq5S" != toString(i.caller))) | |
380 | + | then throw("not authorized") | |
381 | + | else if ((size(i.payments) != 1)) | |
382 | + | then throw("exactly 1 payment must be attached") | |
383 | + | else if ((idoEnd >= claimStart)) | |
384 | + | then throw("claimStart must be greater than idoEnd") | |
385 | + | else { | |
386 | + | let pmt = value(i.payments[0]) | |
387 | + | let idoAssetId = value(pmt.assetId) | |
388 | + | let idoAssetInfo = valueOrErrorMessage(assetInfo(idoAssetId), "fail to load ido asset info") | |
389 | + | let idoAssetId58 = toBase58String(idoAssetId) | |
390 | + | let idoAssetMult = pow(10, 0, idoAssetInfo.decimals, 0, 0, DOWN) | |
391 | + | let priceAssetId = fromBase58String(priceAssetId58) | |
392 | + | let priceAssetInfo = valueOrErrorMessage(assetInfo(priceAssetId), "fail to load price asset info") | |
393 | + | let priceAssetMult = pow(10, 0, priceAssetInfo.decimals, 0, 0, DOWN) | |
394 | + | let origTotalsArray = readTotalsArrayOrDefault() | |
395 | + | let totalsDiff = [0, 0, 0, 0] | |
396 | + | [StringEntry(keyConfig(), fromatConfig(idoStart, idoDuration, claimStart, claimDuration, price, priceMult, idoAssetId58, idoAssetMult, priceAssetId58, priceAssetMult, minInvestAmount, pmt.amount)), TotalsEntry(keyTotals(), origTotalsArray, totalsDiff, claimStart, 0)] | |
397 | + | } | |
398 | + | } | |
399 | + | ||
400 | + | ||
401 | + | ||
402 | + | @Callable(i) | |
403 | + | func invest () = { | |
404 | + | let cfgArray = readConfigArray() | |
405 | + | let idoStart = parseIntValue(cfgArray[IdxCfgIdoStart]) | |
406 | + | let idoDuration = parseIntValue(cfgArray[IdxCfgIdoDuration]) | |
407 | + | let idoEnd = (idoStart + idoDuration) | |
408 | + | let claimStart = parseIntValue(cfgArray[IdxCfgClaimStart]) | |
409 | + | let claimDuration = parseIntValue(cfgArray[IdxCfgClaimDuration]) | |
410 | + | let price = parseIntValue(cfgArray[IdxCfgPrice]) | |
411 | + | let priceMult = parseIntValue(cfgArray[IdxCfgPriceMult]) | |
412 | + | let idoAssetId58 = cfgArray[IdxCfgIdoAssetId] | |
413 | + | let idoAssetId = fromBase58String(idoAssetId58) | |
414 | + | let idoAssetMult = parseIntValue(cfgArray[IdxCfgIdoAssetMult]) | |
415 | + | let priceAssetId58 = cfgArray[IdxCfgPriceAssetId] | |
416 | + | let priceAssetId = fromBase58String(priceAssetId58) | |
417 | + | let priceAssetMult = parseIntValue(cfgArray[IdxCfgPriceAssetMult]) | |
418 | + | let minIvestAmount = parseIntValue(cfgArray[IdxCfgMinInvestAmount]) | |
419 | + | let userAddress = toString(i.caller) | |
420 | + | if ((idoStart > height)) | |
421 | + | then throw("ido has not been started yet") | |
422 | + | else if ((height > idoEnd)) | |
423 | + | then throw("ido has been already ended") | |
424 | + | else if ((size(i.payments) != 1)) | |
425 | + | then throw("exactly 1 payment is expected") | |
426 | + | else { | |
427 | + | let pmt = value(i.payments[0]) | |
428 | + | let pmtAssetId = value(pmt.assetId) | |
429 | + | let pmtAmount = pmt.amount | |
430 | + | if ((pmtAssetId != priceAssetId)) | |
431 | + | then throw((("invalid payment asset id: " + toBase58String(pmtAssetId)) + " is expected")) | |
432 | + | else { | |
433 | + | let origInvestorArray = readInvestorArrayOrDefault(userAddress) | |
434 | + | let origTotalsArray = readTotalsArrayOrDefault() | |
435 | + | let newPriceTotalAmount = (parseIntValue(origTotalsArray[IdxInvTotalAmount]) + pmtAmount) | |
436 | + | let requiredIdoAssetAmount = (newPriceTotalAmount * 100) | |
437 | + | if ((requiredIdoAssetAmount > assetBalance(this, idoAssetId))) | |
438 | + | then throw("IDO asset has been - sold consider to use smaller payment") | |
439 | + | else { | |
440 | + | let totalsDiff = [pmtAmount, pmtAmount, 0, 0] | |
441 | + | [TotalsEntry(keyInvestor(userAddress), origInvestorArray, totalsDiff, claimStart, 0), TotalsEntry(keyTotals(), origTotalsArray, totalsDiff, claimStart, 0), InvestOperationHistoryEntry(userAddress, pmtAmount, 0, i.transactionId)] | |
442 | + | } | |
443 | + | } | |
444 | + | } | |
445 | + | } | |
446 | + | ||
447 | + | ||
448 | + | ||
449 | + | @Callable(i) | |
450 | + | func claim (claimedAssetId58,userAddress58) = { | |
451 | + | let callerAddress58 = toString(i.caller) | |
452 | + | if ((userAddress58 != callerAddress58)) | |
453 | + | then throw("not authorized") | |
454 | + | else { | |
455 | + | let cfgArray = readConfigArray() | |
456 | + | let priceAssetId58 = cfgArray[IdxCfgPriceAssetId] | |
457 | + | let claimResultTuple = internalClaim(claimedAssetId58, i.caller, i.transactionId) | |
458 | + | let totalsDiff = claimResultTuple._1 | |
459 | + | let outAmount = claimResultTuple._2 | |
460 | + | let outAssetId = claimResultTuple._3 | |
461 | + | let origInvestArray = claimResultTuple._4 | |
462 | + | let newClaimPeriodHeight = claimResultTuple._5 | |
463 | + | let claimedPriceAmountFromDiff = totalsDiff[IdxDiffClaimedPriceAmountIncrement] | |
464 | + | let claimedIdoAssetAmountFromDiff = totalsDiff[IdxDiffClaimedIdoAssetAmountIncrement] | |
465 | + | let priceAssetBalance = valueOrElse(getInteger(keyPriceAssetBalance(userAddress58)), 0) | |
466 | + | let priceAssetDecimals = value(assetInfo(fromBase58String(priceAssetId58))).decimals | |
467 | + | let entries = if ((claimedAssetId58 == priceAssetId58)) | |
468 | + | then { | |
469 | + | let $t02258823048 = internalClaimV2(priceAssetId58, userAddress58, outAmount, totalsDiff[IdxDiffClaimedPriceAmountIncrement]) | |
470 | + | let periodMinAvailableToClaim = $t02258823048._1 | |
471 | + | let periodTotalAvailableToClaim = $t02258823048._2 | |
472 | + | let periodUserAvailableToClaim = $t02258823048._3 | |
473 | + | let totalUserAvailableToClaim = $t02258823048._4 | |
474 | + | let usdtPriceAssetAllowableRatio = $t02258823048._5 | |
475 | + | let currentUsdtPriceAssetRatio = $t02258823048._6 | |
476 | + | let endPeriodBlocksLeft = $t02258823048._7 | |
477 | + | let updatedCurrentPeriod = $t02258823048._8 | |
478 | + | let periodStart = $t02258823048._9 | |
479 | + | let periodEnd = $t02258823048._10 | |
480 | + | let checks = [if ((periodUserAvailableToClaim > 0)) | |
481 | + | then true | |
482 | + | else throwErr("unavailable to claim because user period allowance reached"), if ((periodTotalAvailableToClaim > 0)) | |
483 | + | then true | |
484 | + | else throwErr("unavailable to claim because total period allowance reached"), if ((periodMinAvailableToClaim > 0)) | |
485 | + | then true | |
486 | + | else throwErr("nothing to claim"), if ((usdtPriceAssetAllowableRatio > currentUsdtPriceAssetRatio)) | |
487 | + | then true | |
488 | + | else throwErr("unavailable to claim because usdn price lower than usdtPriceAssetAllowableRatio")] | |
489 | + | if ((checks == checks)) | |
490 | + | then { | |
491 | + | let updatedPeriodTotalAvailableToClaim = (periodTotalAvailableToClaim - periodMinAvailableToClaim) | |
492 | + | let updatedPeriodUserAvailableToClaim = (periodUserAvailableToClaim - periodMinAvailableToClaim) | |
493 | + | let entries = if ((priceAssetBalance > periodMinAvailableToClaim)) | |
494 | + | then [ScriptTransfer(i.caller, periodMinAvailableToClaim, outAssetId), IntegerEntry(keyPriceAssetBalance(userAddress58), (priceAssetBalance - periodMinAvailableToClaim))] | |
495 | + | else { | |
496 | + | let evaluateResult = split(asString(invoke(this, "claimREADONLY", [priceAssetId58, userAddress58], nil)), SEP) | |
497 | + | if ((evaluateResult == evaluateResult)) | |
498 | + | then { | |
499 | + | let availablePriceAmountToClaim = parseIntValue(evaluateResult[3]) | |
500 | + | let lastClaimEntries = if ((availablePriceAmountToClaim == periodMinAvailableToClaim)) | |
501 | + | then { | |
502 | + | let investorTotalAmount = parseIntValue(origInvestArray[IdxInvTotalAmount]) | |
503 | + | let investorRemainingAmount = parseIntValue(origInvestArray[IdxInvRemainingAmount]) | |
504 | + | let investorPriceAssetBalance = parseIntValue(origInvestArray[IdxInvClaimedPriceAssetAmount]) | |
505 | + | let investorIdoAssetBalance = parseIntValue(origInvestArray[IdxInvClaimedIdoAssetAmount]) | |
506 | + | let investorLastClaimedHeight = parseIntValue(origInvestArray[IdxInvLastClaimedHeight]) | |
507 | + | let newInvestArray = [toString(investorTotalAmount), "0", toString(investorPriceAssetBalance), toString(investorIdoAssetBalance), toString(investorLastClaimedHeight)] | |
508 | + | let totals = readTotalsArrayOrDefault() | |
509 | + | let totalsTotalAmount = parseIntValue(totals[IdxInvTotalAmount]) | |
510 | + | let totalsRemainingAmount = parseIntValue(totals[IdxInvRemainingAmount]) | |
511 | + | let totalsClaimedPriceAssetAmount = parseIntValue(totals[IdxInvClaimedPriceAssetAmount]) | |
512 | + | let totalsClaimedIdoAssetAmount = parseIntValue(totals[IdxInvClaimedIdoAssetAmount]) | |
513 | + | let totalsLastClaimedHeight = parseIntValue(totals[IdxInvLastClaimedHeight]) | |
514 | + | let newTotalsRemainingAmount = (totalsRemainingAmount - investorRemainingAmount) | |
515 | + | let newTotalArray = [toString(totalsTotalAmount), toString(newTotalsRemainingAmount), toString(totalsClaimedPriceAssetAmount), toString(totalsClaimedIdoAssetAmount), toString(totalsLastClaimedHeight)] | |
516 | + | let newTotalRemainingAmount = (valueOrElse(getInteger(keyTotalRemainingAmount()), 0) + investorRemainingAmount) | |
517 | + | [StringEntry(keyInvestorRemainingAmount(userAddress58), toString(investorRemainingAmount)), StringEntry(keyTotalRemainingAmount(), toString(newTotalRemainingAmount)), TotalsEntry(keyInvestor(userAddress58), newInvestArray, totalsDiff, newClaimPeriodHeight, 0), TotalsEntry(keyTotals(), newTotalArray, totalsDiff, newClaimPeriodHeight, 0)] | |
518 | + | } | |
519 | + | else [TotalsEntry(keyInvestor(userAddress58), origInvestArray, totalsDiff, newClaimPeriodHeight, 0), TotalsEntry(keyTotals(), readTotalsArrayOrDefault(), totalsDiff, newClaimPeriodHeight, 0)] | |
520 | + | let updatedPriceAssetBalance = ((priceAssetBalance + outAmount) - periodMinAvailableToClaim) | |
521 | + | ([ScriptTransfer(i.caller, periodMinAvailableToClaim, outAssetId), IntegerEntry(keyPriceAssetBalance(userAddress58), updatedPriceAssetBalance)] ++ lastClaimEntries) | |
522 | + | } | |
523 | + | else throw("Strict value is not equal to itself.") | |
524 | + | } | |
525 | + | $Tuple2(([IntegerEntry(keyCurrentPeriod(), updatedCurrentPeriod), IntegerEntry(keyPeriodStartHeight(updatedCurrentPeriod), periodStart), IntegerEntry(keyPeriodEndHeight(updatedCurrentPeriod), periodEnd), IntegerEntry(keyPeriodTotalAvailableToClaim(priceAssetId58, updatedCurrentPeriod), updatedPeriodTotalAvailableToClaim), IntegerEntry(keyPeriodUserAvailableToClaim(priceAssetId58, updatedCurrentPeriod, userAddress58), updatedPeriodUserAvailableToClaim), ClaimOperationHistoryEntry(userAddress58, periodMinAvailableToClaim, claimedIdoAssetAmountFromDiff, i.transactionId)] ++ entries), unit) | |
526 | + | } | |
527 | + | else throw("Strict value is not equal to itself.") | |
528 | + | } | |
529 | + | else { | |
530 | + | let priceAssetBalanceIdoDecimals = fraction(priceAssetBalance, scale8, pow(10, 0, priceAssetDecimals, 0, 0, DOWN)) | |
531 | + | $Tuple2([ScriptTransfer(i.caller, (outAmount + priceAssetBalanceIdoDecimals), outAssetId), IntegerEntry(keyPriceAssetBalance(userAddress58), 0), TotalsEntry(keyInvestor(userAddress58), origInvestArray, totalsDiff, newClaimPeriodHeight, priceAssetBalance), TotalsEntry(keyTotals(), readTotalsArrayOrDefault(), totalsDiff, newClaimPeriodHeight, priceAssetBalance), ClaimOperationHistoryEntry(userAddress58, claimedPriceAmountFromDiff, (claimedIdoAssetAmountFromDiff + priceAssetBalanceIdoDecimals), i.transactionId)], unit) | |
532 | + | } | |
533 | + | entries | |
534 | + | } | |
535 | + | } | |
536 | + | ||
537 | + | ||
538 | + | ||
539 | + | @Callable(i) | |
540 | + | func cleanRemaingAmount (userAddress58) = { | |
541 | + | let priceAssetId58 = readConfigArray()[IdxCfgPriceAssetId] | |
542 | + | let evaluateResult = split(asString(invoke(this, "claimREADONLY", [priceAssetId58, userAddress58], nil)), SEP) | |
543 | + | if ((evaluateResult == evaluateResult)) | |
544 | + | then { | |
545 | + | let availablePriceAmountToClaim = parseIntValue(evaluateResult[2]) | |
546 | + | let checkUnclaimedAssets = if ((availablePriceAmountToClaim == 0)) | |
547 | + | then true | |
548 | + | else throwErr("user have unclaimed assets") | |
549 | + | if ((checkUnclaimedAssets == checkUnclaimedAssets)) | |
550 | + | then { | |
551 | + | let investor = split(value(getString(keyInvestor(userAddress58))), SEP) | |
552 | + | let investorTotalAmount = parseIntValue(investor[IdxInvTotalAmount]) | |
553 | + | let investorRemainingAmount = parseIntValue(investor[IdxInvRemainingAmount]) | |
554 | + | let investorPriceAssetBalance = parseIntValue(investor[IdxInvClaimedPriceAssetAmount]) | |
555 | + | let investorIdoAssetBalance = parseIntValue(investor[IdxInvClaimedIdoAssetAmount]) | |
556 | + | let investorLastClaimedHeight = parseIntValue(investor[IdxInvLastClaimedHeight]) | |
557 | + | let investorRemainingAmountCheck = if ((investorRemainingAmount != 0)) | |
558 | + | then true | |
559 | + | else throwErr("investorRemainingAmount already zero") | |
560 | + | if ((investorRemainingAmountCheck == investorRemainingAmountCheck)) | |
561 | + | then { | |
562 | + | let newInvestor = makeString(["%d%d%d%d%d", toString(investorTotalAmount), "0", toString(investorPriceAssetBalance), toString(investorIdoAssetBalance), toString(investorLastClaimedHeight)], SEP) | |
563 | + | let totals = split(value(getString(keyTotals())), SEP) | |
564 | + | let totalsTotalAmount = parseIntValue(totals[IdxInvTotalAmount]) | |
565 | + | let totalsRemainingAmount = parseIntValue(totals[IdxInvRemainingAmount]) | |
566 | + | let totalsClaimedPriceAssetAmount = parseIntValue(totals[IdxInvClaimedPriceAssetAmount]) | |
567 | + | let totalsClaimedIdoAssetAmount = parseIntValue(totals[IdxInvClaimedIdoAssetAmount]) | |
568 | + | let totalsLastClaimedHeight = parseIntValue(totals[IdxInvLastClaimedHeight]) | |
569 | + | let newTotals = makeString(["%d%d%d%d%d", toString(totalsTotalAmount), toString((totalsRemainingAmount - investorRemainingAmount)), toString(totalsClaimedPriceAssetAmount), toString(totalsClaimedIdoAssetAmount), toString(totalsLastClaimedHeight)], SEP) | |
570 | + | let newTotalRemainingAmount = (valueOrElse(getInteger(keyTotalRemainingAmount()), 0) + investorRemainingAmount) | |
571 | + | [StringEntry(keyInvestorRemainingAmount(userAddress58), toString(investorRemainingAmount)), StringEntry(keyTotalRemainingAmount(), toString(newTotalRemainingAmount)), StringEntry(keyInvestor(userAddress58), newInvestor), StringEntry(keyTotals(), newTotals)] | |
572 | + | } | |
573 | + | else throw("Strict value is not equal to itself.") | |
574 | + | } | |
575 | + | else throw("Strict value is not equal to itself.") | |
576 | + | } | |
577 | + | else throw("Strict value is not equal to itself.") | |
578 | + | } | |
579 | + | ||
580 | + | ||
581 | + | ||
582 | + | @Callable(i) | |
583 | + | func claimREADONLY (claimedAssetId58,userAddress58) = { | |
584 | + | let claimResultTuple = internalClaim(claimedAssetId58, addressFromStringValue(userAddress58), fromBase58String("")) | |
585 | + | let totalsDiff = claimResultTuple._1 | |
586 | + | let outAmount = claimResultTuple._2 | |
587 | + | let outAssetId = claimResultTuple._3 | |
588 | + | let origInvestArray = claimResultTuple._4 | |
589 | + | let newClaimPeriodHeight = claimResultTuple._5 | |
590 | + | let availableToClaimArray = claimResultTuple._6 | |
591 | + | let availablePriceAmountToClaim = availableToClaimArray[0] | |
592 | + | let availableIdoAmountToClaim = availableToClaimArray[1] | |
593 | + | $Tuple2(nil, makeString(["%s%d%d", userAddress58, toString(availablePriceAmountToClaim), toString(availableIdoAmountToClaim)], SEP)) | |
594 | + | } | |
595 | + | ||
596 | + | ||
597 | + | ||
598 | + | @Callable(i) | |
599 | + | func claimV2READONLY (claimedAssetId58,userAddress58) = { | |
600 | + | let claimResultTuple = internalClaim(claimedAssetId58, addressFromStringValue(userAddress58), fromBase58String("")) | |
601 | + | let totalsDiff = claimResultTuple._1 | |
602 | + | let outAmount = claimResultTuple._2 | |
603 | + | let outAssetId = claimResultTuple._3 | |
604 | + | let origInvestArray = claimResultTuple._4 | |
605 | + | let newClaimPeriodHeight = claimResultTuple._5 | |
606 | + | let availableToClaimArray = claimResultTuple._6 | |
607 | + | let availablePriceAmountToClaim = availableToClaimArray[0] | |
608 | + | let availableIdoAmountToClaim = availableToClaimArray[1] | |
609 | + | let cfgArray = readConfigArray() | |
610 | + | let priceAssetId58 = cfgArray[IdxCfgPriceAssetId] | |
611 | + | let priceAssetBalance = valueOrElse(getInteger(keyPriceAssetBalance(userAddress58)), 0) | |
612 | + | let priceAssetBalanceIdoDecimals = (priceAssetBalance * 100) | |
613 | + | let availableIdoAmountToClaimWithPriceAssetBalance = (availableIdoAmountToClaim + priceAssetBalanceIdoDecimals) | |
614 | + | let $t03457235000 = internalClaimV2(priceAssetId58, userAddress58, outAmount, totalsDiff[IdxDiffClaimedPriceAmountIncrement]) | |
615 | + | let periodMinAvailableToClaim = $t03457235000._1 | |
616 | + | let periodTotalAvailableToClaim = $t03457235000._2 | |
617 | + | let periodUserAvailableToClaim = $t03457235000._3 | |
618 | + | let totalUserAvailableToClaim = $t03457235000._4 | |
619 | + | let usdtPriceAssetAllowableRatio = $t03457235000._5 | |
620 | + | let currentUsdtPriceAssetRatio = $t03457235000._6 | |
621 | + | let endPeriodBlocksLeft = $t03457235000._7 | |
622 | + | let updatedCurrentPeriod = $t03457235000._8 | |
623 | + | let periodStart = $t03457235000._9 | |
624 | + | let periodEnd = $t03457235000._10 | |
625 | + | let currentPeriodEndHeight = valueOrElse(getInteger(keyPeriodEndHeight(updatedCurrentPeriod)), 0) | |
626 | + | let userTotalPriceAssetClaimed = (parseIntValue(readInvestorArrayOrFail(userAddress58)[IdxInvClaimedPriceAssetAmount]) - priceAssetBalance) | |
627 | + | let resultString = if ((height > currentPeriodEndHeight)) | |
628 | + | then { | |
629 | + | let periodLenght = value(getInteger(keyPeriodLength())) | |
630 | + | let userPeriodAllowance = value(getInteger(keyUserPeriodAllowance(priceAssetId58))) | |
631 | + | let totalPeriodAllowance = value(getInteger(keyTotalPeriodAllowance(priceAssetId58))) | |
632 | + | makeString(["%d%d%d%d%d%d", toString(availableIdoAmountToClaimWithPriceAssetBalance), toString(userPeriodAllowance), toString(totalPeriodAllowance), toString(usdtPriceAssetAllowableRatio), toString(currentUsdtPriceAssetRatio), toString(periodLenght), toString(userTotalPriceAssetClaimed)], SEP) | |
633 | + | } | |
634 | + | else makeString(["%d%d%d%d%d%d", toString(availableIdoAmountToClaimWithPriceAssetBalance), toString(periodMinAvailableToClaim), toString(periodTotalAvailableToClaim), toString(usdtPriceAssetAllowableRatio), toString(currentUsdtPriceAssetRatio), toString(endPeriodBlocksLeft), toString(userTotalPriceAssetClaimed)], SEP) | |
635 | + | $Tuple2(nil, resultString) | |
636 | + | } | |
637 | + | ||
638 | + | ||
639 | + | ||
640 | + | @Callable(i) | |
641 | + | func setManager (pendingManagerPublicKey) = { | |
642 | + | let checkCaller = mustManager(i) | |
643 | + | if ((checkCaller == checkCaller)) | |
644 | + | then { | |
645 | + | let checkManagerPublicKey = fromBase58String(pendingManagerPublicKey) | |
646 | + | if ((checkManagerPublicKey == checkManagerPublicKey)) | |
647 | + | then [StringEntry(keyPendingManagerPublicKey(), pendingManagerPublicKey)] | |
648 | + | else throw("Strict value is not equal to itself.") | |
649 | + | } | |
650 | + | else throw("Strict value is not equal to itself.") | |
651 | + | } | |
652 | + | ||
653 | + | ||
654 | + | ||
655 | + | @Callable(i) | |
656 | + | func confirmManager () = { | |
657 | + | let pm = pendingManagerPublicKeyOrUnit() | |
658 | + | let hasPM = if (isDefined(pm)) | |
659 | + | then true | |
660 | + | else throw("No pending manager") | |
661 | + | if ((hasPM == hasPM)) | |
662 | + | then { | |
663 | + | let checkPM = if ((i.callerPublicKey == value(pm))) | |
664 | + | then true | |
665 | + | else throw("You are not pending manager") | |
666 | + | if ((checkPM == checkPM)) | |
667 | + | then [StringEntry(keyManagerPublicKey(), toBase58String(value(pm))), DeleteEntry(keyPendingManagerPublicKey())] | |
668 | + | else throw("Strict value is not equal to itself.") | |
669 | + | } | |
670 | + | else throw("Strict value is not equal to itself.") | |
671 | + | } | |
672 | + | ||
673 | + | ||
674 | + | @Verifier(tx) | |
675 | + | func verify () = { | |
676 | + | let targetPublicKey = match managerPublicKeyOrUnit() { | |
677 | + | case pk: ByteVector => | |
678 | + | pk | |
679 | + | case _: Unit => | |
680 | + | tx.senderPublicKey | |
681 | + | case _ => | |
682 | + | throw("Match error") | |
683 | + | } | |
684 | + | sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey) | |
685 | + | } | |
686 | + |
github/deemru/w8io/169f3d6 43.37 ms ◑