tx · HJv9n1UH3Ze4U5aFXaq9FZvu7M241UMABdnrkvNKgyBP

3P3Yh7H5wLGty1ykyk9uG9TqG4a1AYpE4mw:  -0.05000000 Waves

2023.04.26 13:18 [3616978] smart account 3P3Yh7H5wLGty1ykyk9uG9TqG4a1AYpE4mw > SELF 0.00000000 Waves

{ "type": 13, "id": "HJv9n1UH3Ze4U5aFXaq9FZvu7M241UMABdnrkvNKgyBP", "fee": 5000000, "feeAssetId": null, "timestamp": 1682504351033, "version": 2, "chainId": 87, "sender": "3P3Yh7H5wLGty1ykyk9uG9TqG4a1AYpE4mw", "senderPublicKey": "4KPHtDDQdyCKhwF8swguQW8jgozBAswuP6wneqWd9yhG", "proofs": [ "2jsjWyHZLVV8V7QcRspmUmzWVyrAiwS36ZKURwqHJjMrKiZAbsQGnYjR7tPTURGiit9qPoS6Vm5ArauRGdDpsjgJ" ], "script": "base64:BgIzCAISAwoBCBIECgIICBIDCgEIEgMKAQgSABIAEgASAwoBARIFCgMIAQESAwoBCBIDCgEIgAEAA1NFUAICX18ABUVNUFRZAgAACVBSRUNJU0lPTgCAoJSljR0ACERFQ0lNQUxTAIDC1y8AFERFRkFVTFRfTUFYX1NMSVBQQUdFCQBoAgkAaQIFCVBSRUNJU0lPTgAUABMAA0RBWQkAaAIJAGgCADwAPAAYAARZRUFSCQBoAgUDREFZAO0CAA9PUkFDTEVfREVDSU1BTFMAwIQ9AAhJTkZJTklUWQD//////////38AEE1JTl9BTU9VTlRfREVMVEEA6AcAFU1BWF9SQVRFX0hFSUdIVF9ERUxUQQAFABFMSVFVSURBVElPTl9CT05VUwkAaAIJAGkCBQlQUkVDSVNJT04AZAAFABhMSVFVSURBVElPTl9QUk9UT0NPTF9GRUUJAGgCCQBpAgUJUFJFQ0lTSU9OAGQAAgAUTUFYX0xJUVVJREFUSU9OX1BBUlQJAGgCCQBpAgUJUFJFQ0lTSU9OAGQAMgANU1RBQklMSVRZX0ZFRQkAaQIFCVBSRUNJU0lPTgBkAAdFTkFCTEVEAgdFTkFCTEVEAAhESVNBQkxFRAIIRElTQUJMRUQAEklkeFZhdWx0QXNzZXRDb3VudAABABNJZHhWYXVsdEFzc2V0QW1vdW50AAIAEUlkeFZhdWx0QXNzZXRSYXRlAAMADUlkeFZhdWx0Q291bnQAAQASSWR4VmF1bHRFYXN0QW1vdW50AAIAEUlkeFZhdWx0VGltZXN0YW1wAAMAD0lkeFN0YWJpbGl0eUZlZQAEAA9JZHhMYXN0RnJhY3Rpb24ABQAPaW52b2NhdGlvbkVycm9yAhBJbnZvY2F0aW9uIGVycm9yAQRkaXZkAgJfeAJfeQkAbgQFAl94BQhERUNJTUFMUwUCX3kFCEhBTEZFVkVOAQRtdWxkAgJfeAJfeQkAbgQFAl94BQJfeQUIREVDSU1BTFMFCEhBTEZFVkVOAQRkaXZwAgJfeAJfeQkAbgQFAl94BQlQUkVDSVNJT04FAl95BQhIQUxGRVZFTgEEbXVscAICX3gCX3kJAG4EBQJfeAUCX3kFCVBSRUNJU0lPTgUISEFMRkVWRU4BBGpvaW4BAmFyCQC5CQIFAmFyBQNTRVABDmtleUluaXRpYWxpemVkAAkBBGpvaW4BCQDMCAICAiVzCQDMCAICC2luaXRpYWxpemVkBQNuaWwBFWtleUNvb3JkaW5hdG9yQWRkcmVzcwAJAQRqb2luAQkAzAgCAgIlcwkAzAgCAhJjb29yZGluYXRvckFkZHJlc3MFA25pbAESa2V5VmVyaWZpZXJBZGRyZXNzAAkBBGpvaW4BCQDMCAICAiVzCQDMCAICD3ZlcmlmaWVyQWRkcmVzcwUDbmlsARFrZXlTZXJ2aWNlQWRkcmVzcwAJAQRqb2luAQkAzAgCAgIlcwkAzAgCAg5zZXJ2aWNlQWRkcmVzcwUDbmlsARJrZXlGcm9udGVuZEFkZHJlc3MACQEEam9pbgEJAMwIAgICJXMJAMwIAgIPZnJvbnRlbmRBZGRyZXNzBQNuaWwBEGtleU1pbnRlckFkZHJlc3MACQEEam9pbgEJAMwIAgICJXMJAMwIAgINbWludGVyQWRkcmVzcwUDbmlsARJrZXlUcmVhc3VyeUFkZHJlc3MACQEEam9pbgEJAMwIAgICJXMJAMwIAgIPdHJlYXN1cnlBZGRyZXNzBQNuaWwBEWtleUJhY2tlbmRBZGRyZXNzAAkBBGpvaW4BCQDMCAICAiVzCQDMCAICDmJhY2tlbmRBZGRyZXNzBQNuaWwBFWtleUVhc3RTdGFraW5nQWRkcmVzcwAJAQRqb2luAQkAzAgCAgIlcwkAzAgCAhJlYXN0U3Rha2luZ0FkZHJlc3MFA25pbAEQa2V5T3JhY2xlQWRkcmVzcwAJAQRqb2luAQkAzAgCAgIlcwkAzAgCAg1vcmFjbGVBZGRyZXNzBQNuaWwBEmtleUV4Y2hhbmdlQWRkcmVzcwAJAQRqb2luAQkAzAgCAgIlcwkAzAgCAg9leGNoYW5nZUFkZHJlc3MFA25pbAEMa2V5RWFzdEFzc2V0AAkBBGpvaW4BCQDMCAICAiVzCQDMCAICCWVhc3RBc3NldAUDbmlsAQ5rZXlTdEVhc3RBc3NldAAJAQRqb2luAQkAzAgCAgIlcwkAzAgCAgtzdEVhc3RBc3NldAUDbmlsARBrZXlBQXNzZXRCYWxhbmNlAAIPQV9hc3NldF9iYWxhbmNlARBrZXlCQXNzZXRCYWxhbmNlAAIPQl9hc3NldF9iYWxhbmNlAQ1rZXlWYXVsdEFzc2V0AgdhZGRyZXNzBWFzc2V0CQEEam9pbgEJAMwIAgIGJXMlcyVzCQDMCAICBXZhdWx0CQDMCAIFB2FkZHJlc3MJAMwIAgUFYXNzZXQFA25pbAEMa2V5VmF1bHREYXRhAQdhZGRyZXNzCQEEam9pbgEJAMwIAgIEJXMlcwkAzAgCAgV2YXVsdAkAzAgCBQdhZGRyZXNzBQNuaWwBDGtleVByZWNpc2lvbgAJAQRqb2luAQkAzAgCAgIlcwkAzAgCAglwcmVjaXNpb24FA25pbAEPa2V5QmFja2luZ1JhdGlvAAkBBGpvaW4BCQDMCAICAiVzCQDMCAICDGJhY2tpbmdSYXRpbwUDbmlsARNrZXlMaXF1aWRhdGlvblJhdGlvAAkBBGpvaW4BCQDMCAICAiVzCQDMCAICEGxpcXVpZGF0aW9uUmF0aW8FA25pbAETa2V5TGlxdWlkYXRpb25Cb251cwAJAQRqb2luAQkAzAgCAgIlcwkAzAgCAhBsaXF1aWRhdGlvbkJvbnVzBQNuaWwBGWtleUxpcXVpZGF0aW9uUHJvdG9jb2xGZWUACQEEam9pbgEJAMwIAgICJXMJAMwIAgIWbGlxdWlkYXRpb25Qcm90b2NvbEZlZQUDbmlsAQ9rZXlTdGFiaWxpdHlGZWUACQEEam9pbgEJAMwIAgICJXMJAMwIAgIMc3RhYmlsaXR5RmVlBQNuaWwBEWtleU1pbkFtb3VudERlbHRhAAkBBGpvaW4BCQDMCAICAiVzCQDMCAICDm1pbkFtb3VudERlbHRhBQNuaWwBCWtleVRpY2tlcgAJAQRqb2luAQkAzAgCAgIlcwkAzAgCAgZ0aWNrZXIFA25pbAEVa2V5TWF4UmF0ZUhlaWdodERlbHRhAAkBBGpvaW4BCQDMCAICAiVzCQDMCAICEm1heFJhdGVIZWlnaHREZWx0YQUDbmlsARJrZXlDb250cmFjdEFzc2V0SWQACQEEam9pbgEJAMwIAgICJXMJAMwIAgIPY29udHJhY3RBc3NldElkBQNuaWwBFGtleU9yYWNsZVRpY2tlclByaWNlAQZ0aWNrZXIJAQRqb2luAQkAzAgCAgQlcyVzCQDMCAICBXByaWNlCQDMCAIFBnRpY2tlcgUDbmlsARprZXlPcmFjbGVUaWNrZXJQcmljZUhlaWdodAEGdGlja2VyCQEEam9pbgEJAMwIAgIEJXMlcwkAzAgCAgpsYXN0SGVpZ2h0CQDMCAIFBnRpY2tlcgUDbmlsAQlrZXlTaWduZWQCCF9hZGRyZXNzBV90eElkCQEEam9pbgEJAMwIAgIGJXMlcyVzCQDMCAICBnNpZ25lZAkAzAgCBQhfYWRkcmVzcwkAzAgCBQVfdHhJZAUDbmlsARFrZXlQcm90b2NvbEFjdGl2ZQAJAQRqb2luAQkAzAgCAgIlcwkAzAgCAg5wcm90b2NvbEFjdGl2ZQUDbmlsAQ1pc0luaXRpYWxpemVkAAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzCQEOa2V5SW5pdGlhbGl6ZWQABwEPbXVzdEluaXRpYWxpemVkAAMJAQEhAQkBDWlzSW5pdGlhbGl6ZWQACQACAQIPTm90IGluaXRpYWxpemVkBQR1bml0ARJtdXN0Tm90SW5pdGlhbGl6ZWQAAwkBDWlzSW5pdGlhbGl6ZWQACQACAQITQWxyZWFkeSBpbml0aWFsaXplZAUEdW5pdAEIbXVzdFNlbGYBAWkDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAh1Pbmx5IHNlbGYgaW52b2NhdGlvbiBhbGxvd2VkLgUEdW5pdAELY29vcmRpbmF0b3IACQERQGV4dHJOYXRpdmUoMTA2MikBCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFWtleUNvb3JkaW5hdG9yQWRkcmVzcwACFkNvb3JkaW5hdG9yIGlzIG5vdCBzZXQBCHZlcmlmaWVyAAQHJG1hdGNoMAkAoggBCQEVa2V5Q29vcmRpbmF0b3JBZGRyZXNzAAMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAXMFByRtYXRjaDAJAJ0IAgkBEUBleHRyTmF0aXZlKDEwNjIpAQUBcwkBEmtleVZlcmlmaWVyQWRkcmVzcwADCQABAgUHJG1hdGNoMAIEVW5pdAUEdW5pdAkAAgECC01hdGNoIGVycm9yAQpnZXRBZGRyZXNzAgNrZXkDZXJyCQERQGV4dHJOYXRpdmUoMTA2MikBCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgkBC2Nvb3JkaW5hdG9yAAUDa2V5BQNlcnIBEGdldE1pbnRlckFkZHJlc3MACQEKZ2V0QWRkcmVzcwIJARBrZXlNaW50ZXJBZGRyZXNzAAIRTWludGVyIGlzIG5vdCBzZXQBEmdldEZyb250ZW5kQWRkcmVzcwAJAQpnZXRBZGRyZXNzAgkBEmtleUZyb250ZW5kQWRkcmVzcwACE0Zyb250ZW5kIGlzIG5vdCBzZXQBEmdldFRyZWFzdXJ5QWRkcmVzcwAJAQpnZXRBZGRyZXNzAgkBEmtleVRyZWFzdXJ5QWRkcmVzcwACE1RyZWFzdXJ5IGlzIG5vdCBzZXQBEWdldEJhY2tlbmRBZGRyZXNzAAkBCmdldEFkZHJlc3MCCQERa2V5QmFja2VuZEFkZHJlc3MAAhJCYWNrZW5kIGlzIG5vdCBzZXQBEGdldE9yYWNsZUFkZHJlc3MACQEKZ2V0QWRkcmVzcwIJARBrZXlPcmFjbGVBZGRyZXNzAAIRT3JhY2xlIGlzIG5vdCBzZXQBFWdldEVhc3RTdGFraW5nQWRkcmVzcwAJAQpnZXRBZGRyZXNzAgkBFWtleUVhc3RTdGFraW5nQWRkcmVzcwACF0Vhc3Qgc3Rha2luZyBpcyBub3Qgc2V0AQ1pc05vdFRyZWFzdXJ5AQFpCQECIT0CCAUBaQZjYWxsZXIJARJnZXRUcmVhc3VyeUFkZHJlc3MAARFnZXRNaW5BbW91bnREZWx0YQAJAQt2YWx1ZU9yRWxzZQIJAJoIAgkBC2Nvb3JkaW5hdG9yAAkBEWtleU1pbkFtb3VudERlbHRhAAUQTUlOX0FNT1VOVF9ERUxUQQEVZ2V0TWF4UmF0ZUhlaWdodERlbHRhAAkBC3ZhbHVlT3JFbHNlAgkAmggCCQELY29vcmRpbmF0b3IACQEVa2V5TWF4UmF0ZUhlaWdodERlbHRhAAUVTUFYX1JBVEVfSEVJR0hUX0RFTFRBARNnZXRMaXF1aWRhdGlvbkJvbnVzAAkBC3ZhbHVlT3JFbHNlAgkAmggCCQELY29vcmRpbmF0b3IACQETa2V5TGlxdWlkYXRpb25Cb251cwAFEUxJUVVJREFUSU9OX0JPTlVTARlnZXRMaXF1aWRhdGlvblByb3RvY29sRmVlAAkBC3ZhbHVlT3JFbHNlAgkAmggCCQELY29vcmRpbmF0b3IACQEZa2V5TGlxdWlkYXRpb25Qcm90b2NvbEZlZQAFGExJUVVJREFUSU9OX1BST1RPQ09MX0ZFRQEPZ2V0U3RhYmlsaXR5RmVlAAkBC3ZhbHVlT3JFbHNlAgkAmggCCQELY29vcmRpbmF0b3IACQEPa2V5U3RhYmlsaXR5RmVlAAUNU1RBQklMSVRZX0ZFRQEKZ2V0QXNzZXRJZAAJARFAZXh0ck5hdGl2ZSgxMDU4KQEJARJrZXlDb250cmFjdEFzc2V0SWQAAQ9nZXRFYXN0QXNzZXRTdHIACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgkBC2Nvb3JkaW5hdG9yAAkBDGtleUVhc3RBc3NldAACFUVhc3QgYXNzZXQgaXMgbm90IHNldAEMZ2V0RWFzdEFzc2V0AAkA2QQBCQEPZ2V0RWFzdEFzc2V0U3RyAAEIaXNBY3RpdmUACQELdmFsdWVPckVsc2UCCQCbCAIJAQtjb29yZGluYXRvcgAJARFrZXlQcm90b2NvbEFjdGl2ZQAHAQptdXN0QWN0aXZlAAMDCQEBIQEJAQhpc0FjdGl2ZQAGCQEBIQEJAQ1pc0luaXRpYWxpemVkAAkAAgECLVByb3RvY29sIGlzIGRpc2FibGVkLiBQbGVhc2UgY29udGFjdCBzdXBwb3J0LgUEdW5pdAEMbXVzdEZyb250ZW5kAQFpAwkBAiE9AggFAWkGY2FsbGVyCQESZ2V0RnJvbnRlbmRBZGRyZXNzAAkAAgECC05vdCBhbGxvd2VkBQR1bml0AQttdXN0QmFja2VuZAEBaQMJAQIhPQIIBQFpBmNhbGxlcgkBEWdldEJhY2tlbmRBZGRyZXNzAAkAAgECC05vdCBhbGxvd2VkBQR1bml0ARFtdXN0Tm90VmF1bHRPd25lcgIBaQdhZGRyZXNzAwkAAAIJANgEAQgIBQFpBmNhbGxlcgVieXRlcwUHYWRkcmVzcwkAAgECHFNlbGYgaW52b2NhdGlvbiBub3QgYWxsb3dlZC4FBHVuaXQBEm11c3RIYXZlT25lUGF5bWVudAEBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECGU9ubHkgb25lIHBheW1lbnQgYWxsb3dlZC4FBHVuaXQBEW11c3RIYXZlTm9QYXltZW50AQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQITTm8gcGF5bWVudCBhbGxvd2VkLgUEdW5pdAENaGFzT25lUGF5bWVudAEBaQkAAAIJAJADAQgFAWkIcGF5bWVudHMAAQEKaXNQb3NpdGl2ZQEGbnVtYmVyAwkAZwIAAAUGbnVtYmVyCQACAQIlQXR0cmlidXRlIHNob3VsZCBiZSBwb3NpdGl2ZSBvciB6ZXJvLgUEdW5pdAENaXNOb3ROZWdhdGl2ZQEGbnVtYmVyAwkAZgIAAAUGbnVtYmVyCQACAQIdQXR0cmlidXRlIHNob3VsZCBiZSBwb3NpdGl2ZS4FBHVuaXQBC2dldFN1YnZhdWx0AgdhZGRyZXNzBWFzc2V0CQCiCAEJAQ1rZXlWYXVsdEFzc2V0AgUHYWRkcmVzcwUFYXNzZXQBEGlzU3VidmF1bHRFeGlzdHMCB2FkZHJlc3MFYXNzZXQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkBC2dldFN1YnZhdWx0AgUHYWRkcmVzcwUFYXNzZXQCEFZhdWx0IG5vdCBleGlzdHMBDmdldEFzc2V0U3RyaW5nAQFwBAckbWF0Y2gwCAUBcAdhc3NldElkAwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEB2Fzc2V0SWQFByRtYXRjaDAJANgEAQUHYXNzZXRJZAMJAAECBQckbWF0Y2gwAgRVbml0AgVXQVZFUwkAAgECC01hdGNoIGVycm9yARRnZXRBc3NldElkRnJvbVN0cmluZwEHYXNzZXRJZAMJAAACBQdhc3NldElkAgVXQVZFUwUEdW5pdAkA2QQBBQdhc3NldElkAQdpc0Fzc2V0AgFwDWNoZWNraW5nQXNzZXQEB2Fzc2V0SWQEByRtYXRjaDAFDWNoZWNraW5nQXNzZXQDCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQCYnYFByRtYXRjaDAFAmJ2AwkAAQIFByRtYXRjaDACBlN0cmluZwQBcwUHJG1hdGNoMAkBFGdldEFzc2V0SWRGcm9tU3RyaW5nAQUBcwMJAAECBQckbWF0Y2gwAgRVbml0BQR1bml0CQACAQILTWF0Y2ggZXJyb3IEByRtYXRjaDAFB2Fzc2V0SWQDCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQCYnYFByRtYXRjaDAEBG5hbWUEByRtYXRjaDEJAOwHAQUCYnYDCQABAgUHJG1hdGNoMQIFQXNzZXQEBWFzc2V0BQckbWF0Y2gxCAUFYXNzZXQEbmFtZQMJAAECBQckbWF0Y2gxAgRVbml0CQACAQkArAICAhFDYW4ndCBmaW5kIGFzc2V0IAkA2AQBBQJidgkAAgECC01hdGNoIGVycm9yBANlcnIJAAIBCQCsAgICHkF0dGFjaGVkIHBheW1lbnQgYXNzZXQgaXMgbm90IAUEbmFtZQQHJG1hdGNoMQgFAXAHYXNzZXRJZAMJAAECBQckbWF0Y2gxAgpCeXRlVmVjdG9yBAxwYXltZW50QXNzZXQFByRtYXRjaDEDCQECIT0CBQxwYXltZW50QXNzZXQFB2Fzc2V0SWQFA2VycgUEdW5pdAMJAAECBQckbWF0Y2gxAgRVbml0BQNlcnIJAAIBAgtNYXRjaCBlcnJvcgMJAAECBQckbWF0Y2gwAgRVbml0AwkBAiE9AggFAXAHYXNzZXRJZAUEdW5pdAkAAgECI0F0dGFjaGVkIHBheW1lbnQgYXNzZXQgaXMgbm90IFdBVkVTBQR1bml0CQACAQILTWF0Y2ggZXJyb3IBD2dldEJhY2tpbmdSYXRpbwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnwgBCQEPa2V5QmFja2luZ1JhdGlvAAIYQmFja2luZyByYXRpbyBpcyBub3Qgc2V0ARNnZXRMaXF1aWRhdGlvblJhdGlvAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCfCAEJARNrZXlMaXF1aWRhdGlvblJhdGlvAAIcTGlxdWlkYXRpb24gcmF0aW8gaXMgbm90IHNldAEMY2hlY2tBZGRyZXNzAQhfYWRkcmVzcwQHJG1hdGNoMAkApggBBQhfYWRkcmVzcwMJAAECBQckbWF0Y2gwAgdBZGRyZXNzBAdhZGRyZXNzBQckbWF0Y2gwBgMJAAECBQckbWF0Y2gwAgRVbml0CQACAQIPSW52YWxpZCBhZGRyZXNzCQACAQILTWF0Y2ggZXJyb3IBCWNoZWNrVHhJZAEDX2lkCQAAAgkAyAEBCQDZBAEFA19pZAAgARZnZXRDdXJyZW50VGltZXN0YW1wU2VjAAkAaQIIBQlsYXN0QmxvY2sJdGltZXN0YW1wAOgHARBtdXN0V2F2ZXNQYXltZW50AQFpBAVjaGVjawkBEm11c3RIYXZlT25lUGF5bWVudAEFAWkDCQAAAgUFY2hlY2sFBWNoZWNrBApwbXRBc3NldElkCAkAkQMCCAUBaQhwYXltZW50cwAAB2Fzc2V0SWQEByRtYXRjaDAFCnBtdEFzc2V0SWQDCQABAgUHJG1hdGNoMAIEVW5pdAQBYQUHJG1hdGNoMAUEdW5pdAkAAgECE09ubHkgV0FWRVMgYWNjZXB0ZWQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BDGdldEFzc2V0SW5mbwEHYXNzZXRJZAQHJG1hdGNoMAUHYXNzZXRJZAMJAAECBQckbWF0Y2gwAgpCeXRlVmVjdG9yBAJpZAUHJG1hdGNoMAQIc3RyaW5nSWQJANgEAQUCaWQEBGluZm8JARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkA7AcBBQJpZAkArAICCQCsAgICBkFzc2V0IAUIc3RyaW5nSWQCDiBkb2Vzbid0IGV4aXN0CQCVCgMFCHN0cmluZ0lkCAUEaW5mbwRuYW1lCAUEaW5mbwhkZWNpbWFscwMJAAECBQckbWF0Y2gwAgRVbml0BAV3YXZlcwUHJG1hdGNoMAkAlQoDAgVXQVZFUwIFV0FWRVMACAkAAgECC01hdGNoIGVycm9yARBjaGVja0hlaWdodERlbHRhAQtwcmljZUhlaWdodAQObWF4SGVpZ2h0RGVsdGEJARVnZXRNYXhSYXRlSGVpZ2h0RGVsdGEABAtjdXJyZW50RGlmZgkAZQIIBQlsYXN0QmxvY2sGaGVpZ2h0BQtwcmljZUhlaWdodAMJAGcCBQ5tYXhIZWlnaHREZWx0YQULY3VycmVudERpZmYFBHVuaXQJAAIBAhJMYXJnZSBwcmljZSBkZWx0YS4BEGdldEFzc2V0VXNkUHJpY2UABAZ0aWNrZXIJARFAZXh0ck5hdGl2ZSgxMDUzKQIFBHRoaXMJAQlrZXlUaWNrZXIABA1vcmFjbGVBZGRyZXNzCQEQZ2V0T3JhY2xlQWRkcmVzcwAEC3ByaWNlSGVpZ2h0CQERQGV4dHJOYXRpdmUoMTA1MCkCBQ1vcmFjbGVBZGRyZXNzCQEaa2V5T3JhY2xlVGlja2VyUHJpY2VIZWlnaHQBBQZ0aWNrZXIEC2NoZWNrSGVpZ2h0CQEQY2hlY2tIZWlnaHREZWx0YQEFC3ByaWNlSGVpZ2h0AwkAAAIFC2NoZWNrSGVpZ2h0BQtjaGVja0hlaWdodAQFcHJpY2UJARFAZXh0ck5hdGl2ZSgxMDUwKQIFDW9yYWNsZUFkZHJlc3MJARRrZXlPcmFjbGVUaWNrZXJQcmljZQEFBnRpY2tlcgkAawMFBXByaWNlBQlQUkVDSVNJT04FD09SQUNMRV9ERUNJTUFMUwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgAOSWR4QXNzZXRTdGF0dXMAAQASSWR4QXNzZXRDb250cmFjdElkAAIBCGtleUFzc2V0AQlfYXNzZXRTdHIJAQRqb2luAQkAzAgCAgQlcyVzCQDMCAICBWFzc2V0CQDMCAIFCV9hc3NldFN0cgUDbmlsAQ5rZXlWYXVsdEFzc2V0cwEIX2FkZHJlc3MJAQRqb2luAQkAzAgCAgQlcyVzCQDMCAICC3ZhdWx0QXNzZXRzCQDMCAIFCF9hZGRyZXNzBQNuaWwBGGtleUN1bXVsYXRpdmVGZWVGcmFjdGlvbgAJAQRqb2luAQkAzAgCAgIlcwkAzAgCAhVjdW11bGF0aXZlRmVlRnJhY3Rpb24FA25pbAEWa2V5RnJhY3Rpb25MYXN0VXBkYXRlZAAJAQRqb2luAQkAzAgCAgIlcwkAzAgCAhNmcmFjdGlvbkxhc3RVcGRhdGVkBQNuaWwBE2dldEFzc2V0Q29udHJhY3RTdHIBBl9hc3NldAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJAQhrZXlBc3NldAEFBl9hc3NldAINVW5rbm93biBhc3NldAEQZ2V0QXNzZXRDb250cmFjdAEGX2Fzc2V0BAtjb250cmFjdFN0cgkBE2dldEFzc2V0Q29udHJhY3RTdHIBBQZfYXNzZXQEC2NvbnRyYWN0QXJyCQC1CQIFC2NvbnRyYWN0U3RyBQNTRVAECmNvbnRyYWN0SWQJAJEDAgULY29udHJhY3RBcnIFEklkeEFzc2V0Q29udHJhY3RJZAkBEUBleHRyTmF0aXZlKDEwNjIpAQUKY29udHJhY3RJZAEOZ2V0VmF1bHRBc3NldHMBCF9hZGRyZXNzBAckbWF0Y2gwCQCiCAEJAQ5rZXlWYXVsdEFzc2V0cwEFCF9hZGRyZXNzAwkAAQIFByRtYXRjaDACBlN0cmluZwQBcwUHJG1hdGNoMAkAtQkCBQFzBQNTRVADCQABAgUHJG1hdGNoMAIEVW5pdAUDbmlsCQACAQILTWF0Y2ggZXJyb3IBDGdldFZhdWx0RGF0YQEIX2FkZHJlc3MEByRtYXRjaDAJAKIIAQkBDGtleVZhdWx0RGF0YQEFCF9hZGRyZXNzAwkAAQIFByRtYXRjaDACBlN0cmluZwQBcwUHJG1hdGNoMAkAtQkCBQFzBQNTRVADCQABAgUHJG1hdGNoMAIEVW5pdAkAzAgCAgolZCVkJWQlZCVkCQDMCAICATAJAMwIAgIBMAkAzAgCCQCkAwEJARZnZXRDdXJyZW50VGltZXN0YW1wU2VjAAkAzAgCAgEwCQDMCAICATAFA25pbAkAAgECC01hdGNoIGVycm9yAQphc3NldEV4aXN0AQlfYXNzZXRTdHIEByRtYXRjaDAJAKIIAQkBCGtleUFzc2V0AQUJX2Fzc2V0U3RyAwkAAQIFByRtYXRjaDACBlN0cmluZwQBcwUHJG1hdGNoMAYDCQABAgUHJG1hdGNoMAIEVW5pdAcJAAIBAgtNYXRjaCBlcnJvcgEYZ2V0Q3VtdWxhdGl2ZUZlZUZyYWN0aW9uAAkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEYa2V5Q3VtdWxhdGl2ZUZlZUZyYWN0aW9uAAAAARZnZXRGcmFjdGlvbkxhc3RVcGRhdGVkAAkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEWa2V5RnJhY3Rpb25MYXN0VXBkYXRlZAAJARZnZXRDdXJyZW50VGltZXN0YW1wU2VjAAEJaXNFbmFibGVkAQlfYXNzZXRTdHIECGFzc2V0Q2ZnCQERQGV4dHJOYXRpdmUoMTA1OCkBCQEIa2V5QXNzZXQBBQlfYXNzZXRTdHIECGFzc2V0QXJyCQC1CQIFCGFzc2V0Q2ZnBQNTRVADCQECIT0CCQCRAwIFCGFzc2V0QXJyBQ5JZHhBc3NldFN0YXR1cwUHRU5BQkxFRAkAAgEJAKwCAgkArAICAgZBc3NldCAFCV9hc3NldFN0cgIPIGlzIG5vdCBlbmFibGVkBQR1bml0AQ1pc1ZhdWx0RXhpc3RzAQhfYWRkcmVzcwMJAAACCQCQAwEJAQ5nZXRWYXVsdEFzc2V0cwEFCF9hZGRyZXNzAAAJAAIBAhJWYXVsdCBpcyBub3QgZXhpc3QFBHVuaXQBFmdldEN1cnJlbnRTdGFiaWxpdHlGZWUDC19lYXN0QW1vdW50EV9sYXN0U3RhYmlsaXR5RmVlDV9sYXN0RnJhY3Rpb24JAGQCBRFfbGFzdFN0YWJpbGl0eUZlZQkBBG11bHACBQtfZWFzdEFtb3VudAkAZQIJARhnZXRDdW11bGF0aXZlRmVlRnJhY3Rpb24ABQ1fbGFzdEZyYWN0aW9uAQlkYXRhQXNzZXQCB19zdGF0dXMIX2FkZHJlc3MJALkJAgkAzAgCAgQlcyVzCQDMCAIFB19zdGF0dXMJAMwIAgUIX2FkZHJlc3MFA25pbAUDU0VQAQt1cGRhdGVWYXVsdAMIX2FkZHJlc3MLX2Vhc3RBbW91bnQIX3BhaWRGZWUEBXZhdWx0CQEMZ2V0VmF1bHREYXRhAQUIX2FkZHJlc3MECmVhc3RBbW91bnQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQV2YXVsdAUSSWR4VmF1bHRFYXN0QW1vdW50BAVjb3VudAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBXZhdWx0BQ1JZHhWYXVsdENvdW50BAl0aW1lc3RhbXAJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQV2YXVsdAURSWR4VmF1bHRUaW1lc3RhbXAEEGxhc3RTdGFiaWxpdHlGZWUJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQV2YXVsdAUPSWR4U3RhYmlsaXR5RmVlBAxsYXN0RnJhY3Rpb24JAQ1wYXJzZUludFZhbHVlAQkAkQMCBQV2YXVsdAUPSWR4TGFzdEZyYWN0aW9uBA1uZXdFYXN0QW1vdW50CQBkAgUKZWFzdEFtb3VudAULX2Vhc3RBbW91bnQECG5ld0NvdW50CQBkAgUFY291bnQAAQMJAGYCAAAFDW5ld0Vhc3RBbW91bnQJAAIBAiVTb21ldGhpbmcgd2VudCB3cm9uZy4gQ29udGFjdCBzdXBwb3J0BA9uZXdTdGFiaWxpdHlGZWUJAGUCCQEWZ2V0Q3VycmVudFN0YWJpbGl0eUZlZQMFCmVhc3RBbW91bnQFEGxhc3RTdGFiaWxpdHlGZWUFDGxhc3RGcmFjdGlvbgUIX3BhaWRGZWUJALkJAgkAzAgCAgolZCVkJWQlZCVkCQDMCAIJAKQDAQUIbmV3Q291bnQJAMwIAgkApAMBBQ1uZXdFYXN0QW1vdW50CQDMCAIJAKQDAQkBFmdldEN1cnJlbnRUaW1lc3RhbXBTZWMACQDMCAIJAKQDAQUPbmV3U3RhYmlsaXR5RmVlCQDMCAIJAKQDAQkBGGdldEN1bXVsYXRpdmVGZWVGcmFjdGlvbgAFA25pbAUDU0VQAQ1hZGRWYXVsdEFzc2V0AghfYWRkcmVzcwlfYXNzZXRTdHIEBmFzc2V0cwkBDmdldFZhdWx0QXNzZXRzAQUIX2FkZHJlc3MDCQEPY29udGFpbnNFbGVtZW50AgUGYXNzZXRzBQlfYXNzZXRTdHIJAAIBAhRBc3NldCBhbHJlYWR5IGV4aXN0cwkAuQkCCQDNCAIFBmFzc2V0cwUJX2Fzc2V0U3RyBQNTRVABEHJlbW92ZVZhdWx0QXNzZXQCCF9hZGRyZXNzCV9hc3NldFN0cgQGYXNzZXRzCQEOZ2V0VmF1bHRBc3NldHMBBQhfYWRkcmVzcwMJAQEhAQkBD2NvbnRhaW5zRWxlbWVudAIFBmFzc2V0cwUJX2Fzc2V0U3RyCQACAQINVW5rbm93biBhc3NldAQDaWR4CgABQAkAzwgCBQZhc3NldHMFCV9hc3NldFN0cgMJAAECBQFAAgNJbnQFAUAJAAIBCQCsAgIJAAMBBQFAAhggY291bGRuJ3QgYmUgY2FzdCB0byBJbnQJALkJAgkA0QgCBQZhc3NldHMFA2lkeAUDU0VQCwFpAQppbml0aWFsaXplARNfY29vcmRpbmF0b3JBZGRyZXNzBAZjaGVja3MJAMwIAgkBEm11c3ROb3RJbml0aWFsaXplZAAJAMwIAgkBDGNoZWNrQWRkcmVzcwEFE19jb29yZGluYXRvckFkZHJlc3MFA25pbAMJAAACBQZjaGVja3MFBmNoZWNrcwkAzAgCCQELU3RyaW5nRW50cnkCCQEVa2V5Q29vcmRpbmF0b3JBZGRyZXNzAAUTX2Nvb3JkaW5hdG9yQWRkcmVzcwkAzAgCCQEMQm9vbGVhbkVudHJ5AgkBDmtleUluaXRpYWxpemVkAAYFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQhhZGRBc3NldAIJX2Fzc2V0U3RyDF9jb250cmFjdFN0cgQGY2hlY2tzCQDMCAIJAQ9tdXN0SW5pdGlhbGl6ZWQACQDMCAIJAQhtdXN0U2VsZgEFAWkFA25pbAMJAAACBQZjaGVja3MFBmNoZWNrcwMJAQEhAQkBDGNoZWNrQWRkcmVzcwEFDF9jb250cmFjdFN0cgkAAgECFEFkZHJlc3MgaXMgbm90IHZhbGlkAwkBCmFzc2V0RXhpc3QBBQlfYXNzZXRTdHIJAAIBAhRBc3NldCBpcyBhbHJlYWR5IHNldAkAzAgCCQELU3RyaW5nRW50cnkCCQEIa2V5QXNzZXQBBQlfYXNzZXRTdHIJAQlkYXRhQXNzZXQCBQdFTkFCTEVEBQxfY29udHJhY3RTdHIFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQxkaXNhYmxlQXNzZXQBCV9hc3NldFN0cgQGY2hlY2tzCQDMCAIJAQ9tdXN0SW5pdGlhbGl6ZWQACQDMCAIJAQhtdXN0U2VsZgEFAWkFA25pbAMJAAACBQZjaGVja3MFBmNoZWNrcwQIYXNzZXRBcnIJALUJAgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJAQhrZXlBc3NldAEFCV9hc3NldFN0cgINVW5rbm93biBhc3NldAUDU0VQCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQhrZXlBc3NldAEFCV9hc3NldFN0cgkBCWRhdGFBc3NldAIFCERJU0FCTEVECQCRAwIFCGFzc2V0QXJyBRJJZHhBc3NldENvbnRyYWN0SWQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQtlbmFibGVBc3NldAEJX2Fzc2V0U3RyBAZjaGVja3MJAMwIAgkBD211c3RJbml0aWFsaXplZAAJAMwIAgkBCG11c3RTZWxmAQUBaQUDbmlsAwkAAAIFBmNoZWNrcwUGY2hlY2tzBAhhc3NldEFycgkAtQkCCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBCGtleUFzc2V0AQUJX2Fzc2V0U3RyAg1Vbmtub3duIGFzc2V0BQNTRVAJAMwIAgkBC1N0cmluZ0VudHJ5AgkBCGtleUFzc2V0AQUJX2Fzc2V0U3RyCQEJZGF0YUFzc2V0AgUHRU5BQkxFRAkAkQMCBQhhc3NldEFycgUSSWR4QXNzZXRDb250cmFjdElkBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEOdXBkYXRlRnJhY3Rpb24ABAVkZWx0YQkAZQIJARZnZXRDdXJyZW50VGltZXN0YW1wU2VjAAkBFmdldEZyYWN0aW9uTGFzdFVwZGF0ZWQABA1mcmFjdGlvbkRlbHRhCQEEbXVscAIJAQRkaXZwAgUFZGVsdGEFBFlFQVIJAQ9nZXRTdGFiaWxpdHlGZWUABBVjdW11bGF0aXZlRmVlRnJhY3Rpb24JAGQCCQEYZ2V0Q3VtdWxhdGl2ZUZlZUZyYWN0aW9uAAUNZnJhY3Rpb25EZWx0YQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBGGtleUN1bXVsYXRpdmVGZWVGcmFjdGlvbgAFFWN1bXVsYXRpdmVGZWVGcmFjdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBFmtleUZyYWN0aW9uTGFzdFVwZGF0ZWQACQEWZ2V0Q3VycmVudFRpbWVzdGFtcFNlYwAFA25pbAFpAQRtaW50AAQHcGF5bWVudAkAkQMCCAUBaQhwYXltZW50cwAABAhhc3NldFN0cgkBDmdldEFzc2V0U3RyaW5nAQUHcGF5bWVudAQHYWRkcmVzcwkA2AQBCAgFAWkGY2FsbGVyBWJ5dGVzBAZjaGVja3MJAMwIAgkBCm11c3RBY3RpdmUACQDMCAIJARJtdXN0SGF2ZU9uZVBheW1lbnQBBQFpCQDMCAIJAQlpc0VuYWJsZWQBBQhhc3NldFN0cgUDbmlsAwkAAAIFBmNoZWNrcwUGY2hlY2tzBBBkb1VwZGF0ZUZyYWN0aW9uCQD8BwQFBHRoaXMCDnVwZGF0ZUZyYWN0aW9uBQNuaWwFA25pbAMJAAACBRBkb1VwZGF0ZUZyYWN0aW9uBRBkb1VwZGF0ZUZyYWN0aW9uBARlcnIxCQACAQIpVW5hYmxlIHRvIHByb2NlZWQuIFRvbyBmZXcgYXNzZXRzIHRvIG1pbnQDCQBmAgkBEWdldE1pbkFtb3VudERlbHRhAAgFB3BheW1lbnQGYW1vdW50BQRlcnIxBAhjb250cmFjdAkBEGdldEFzc2V0Q29udHJhY3QBBQhhc3NldFN0cgQNJHQwMTU1MzkxNTY0MwoAAUAJAPwHBAUIY29udHJhY3QCBG1pbnQJAMwIAgUHYWRkcmVzcwUDbmlsCAUBaQhwYXltZW50cwMJAAECBQFAAg0oU3RyaW5nLCBJbnQpBQFACQACAQkArAICCQADAQUBQAIiIGNvdWxkbid0IGJlIGNhc3QgdG8gKFN0cmluZywgSW50KQMJAAACBQ0kdDAxNTUzOTE1NjQzBQ0kdDAxNTUzOTE1NjQzBAplYXN0QW1vdW50CAUNJHQwMTU1MzkxNTY0MwJfMgQKYXNzZXRWYXVsdAgFDSR0MDE1NTM5MTU2NDMCXzEECWVhc3RBc3NldAkBDGdldEVhc3RBc3NldAAEDHVwZGF0ZWRWYXVsdAkBC3VwZGF0ZVZhdWx0AwUHYWRkcmVzcwUKZWFzdEFtb3VudAAABAZtaW50ZXIJARBnZXRNaW50ZXJBZGRyZXNzAAQLZG9Jc3N1ZUVhc3QJAPwHBAUGbWludGVyAgVpc3N1ZQkAzAgCBQplYXN0QW1vdW50BQNuaWwFA25pbAMJAAACBQtkb0lzc3VlRWFzdAULZG9Jc3N1ZUVhc3QEBmFzc2V0cwkBDmdldFZhdWx0QXNzZXRzAQUHYWRkcmVzcwQRdmF1bHRBc3NldEFjdGlvbnMDCQEBIQEJAQ9jb250YWluc0VsZW1lbnQCBQZhc3NldHMFCGFzc2V0U3RyCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQ5rZXlWYXVsdEFzc2V0cwEFB2FkZHJlc3MJAQ1hZGRWYXVsdEFzc2V0AgUHYWRkcmVzcwUIYXNzZXRTdHIFA25pbAUDbmlsCQDOCAIJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDGtleVZhdWx0RGF0YQEFB2FkZHJlc3MFDHVwZGF0ZWRWYXVsdAkAzAgCCQELU3RyaW5nRW50cnkCCQENa2V5VmF1bHRBc3NldAIFB2FkZHJlc3MFCGFzc2V0U3RyBQphc3NldFZhdWx0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgUKZWFzdEFtb3VudAUJZWFzdEFzc2V0BQNuaWwFEXZhdWx0QXNzZXRBY3Rpb25zCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBBnN1cHBseQAEB3BheW1lbnQJAJEDAggFAWkIcGF5bWVudHMAAAQHYWRkcmVzcwkA2AQBCAgFAWkGY2FsbGVyBWJ5dGVzBAVhc3NldAkBDmdldEFzc2V0U3RyaW5nAQkAkQMCCAUBaQhwYXltZW50cwAABAZjaGVja3MJAMwIAgkBCm11c3RBY3RpdmUACQDMCAIJARJtdXN0SGF2ZU9uZVBheW1lbnQBBQFpCQDMCAIJARBpc1N1YnZhdWx0RXhpc3RzAgUHYWRkcmVzcwUFYXNzZXQJAMwIAgkBCWlzRW5hYmxlZAEFBWFzc2V0BQNuaWwDCQAAAgUGY2hlY2tzBQZjaGVja3MEEGRvVXBkYXRlRnJhY3Rpb24JAPwHBAUEdGhpcwIOdXBkYXRlRnJhY3Rpb24FA25pbAUDbmlsAwkAAAIFEGRvVXBkYXRlRnJhY3Rpb24FEGRvVXBkYXRlRnJhY3Rpb24EBGVycjEJAAIBAitVbmFibGUgdG8gcHJvY2VlZC4gVG9vIGZldyBhc3NldHMgdG8gc3VwcGx5AwkAZgIJARFnZXRNaW5BbW91bnREZWx0YQAIBQdwYXltZW50BmFtb3VudAUEZXJyMQQIY29udHJhY3QJARBnZXRBc3NldENvbnRyYWN0AQUFYXNzZXQEEXVwZGF0ZWRWYXVsdEFzc2V0CgABQAkA/AcEBQhjb250cmFjdAIGc3VwcGx5CQDMCAIFB2FkZHJlc3MFA25pbAgFAWkIcGF5bWVudHMDCQABAgUBQAIGU3RyaW5nBQFACQACAQkArAICCQADAQUBQAIbIGNvdWxkbid0IGJlIGNhc3QgdG8gU3RyaW5nAwkAAAIFEXVwZGF0ZWRWYXVsdEFzc2V0BRF1cGRhdGVkVmF1bHRBc3NldAkAzAgCCQELU3RyaW5nRW50cnkCCQENa2V5VmF1bHRBc3NldAIFB2FkZHJlc3MFBWFzc2V0BRF1cGRhdGVkVmF1bHRBc3NldAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBB3JlaXNzdWUBB19hbW91bnQEB2FkZHJlc3MJANgEAQgIBQFpBmNhbGxlcgVieXRlcwQGY2hlY2tzCQDMCAIJAQptdXN0QWN0aXZlAAkAzAgCCQERbXVzdEhhdmVOb1BheW1lbnQBBQFpCQDMCAIJAQ1pc1ZhdWx0RXhpc3RzAQUHYWRkcmVzcwUDbmlsAwkAAAIFBmNoZWNrcwUGY2hlY2tzBBBkb1VwZGF0ZUZyYWN0aW9uCQD8BwQFBHRoaXMCDnVwZGF0ZUZyYWN0aW9uBQNuaWwFA25pbAMJAAACBRBkb1VwZGF0ZUZyYWN0aW9uBRBkb1VwZGF0ZUZyYWN0aW9uBARlcnIxCQACAQIqVW5hYmxlIHRvIHByb2NlZWQuIFRvbyBmZXcgZWFzdCB0byByZWlzc3VlAwkAZgIJARFnZXRNaW5BbW91bnREZWx0YQAFB19hbW91bnQFBGVycjEEDHZhdWx0RGF0YUFycgkBDGdldFZhdWx0RGF0YQEFB2FkZHJlc3MECmVhc3RBbW91bnQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQx2YXVsdERhdGFBcnIFEklkeFZhdWx0RWFzdEFtb3VudAQNJHQwMTc0MzExNzU0NwoAAUAJAPwHBAUEdGhpcwIMZ2V0VmF1bHRJbmZvCQDMCAIFB2FkZHJlc3MFA25pbAUDbmlsAwkAAQIFAUACGShJbnQsIEludCwgSW50LCBJbnQsIEludCkFAUAJAAIBCQCsAgIJAAMBBQFAAi4gY291bGRuJ3QgYmUgY2FzdCB0byAoSW50LCBJbnQsIEludCwgSW50LCBJbnQpAwkAAAIFDSR0MDE3NDMxMTc1NDcFDSR0MDE3NDMxMTc1NDcEA2ZlZQgFDSR0MDE3NDMxMTc1NDcCXzUEAmxyCAUNJHQwMTc0MzExNzU0NwJfNAQCYnIIBQ0kdDAxNzQzMTE3NTQ3Al8zBAZlYXN0RXEIBQ0kdDAxNzQzMTE3NTQ3Al8yBAV1c2RFcQgFDSR0MDE3NDMxMTc1NDcCXzEEDWVhc3RBdmFpbGFibGUJAGUCBQZlYXN0RXEFCmVhc3RBbW91bnQEBGVycjIJAAIBCQCsAgIJAKwCAgIYVW5hYmxlIHRvIHJlaXNzdWUuIE9ubHkgCQCkAwEFDWVhc3RBdmFpbGFibGUCECBFQVNUIGF2YWlsYWJsZS4DCQBmAgUHX2Ftb3VudAUNZWFzdEF2YWlsYWJsZQUEZXJyMgQMdXBkYXRlZFZhdWx0CQELdXBkYXRlVmF1bHQDBQdhZGRyZXNzBQdfYW1vdW50AAAEBm1pbnRlcgkBEGdldE1pbnRlckFkZHJlc3MABAtkb0lzc3VlRWFzdAkA/AcEBQZtaW50ZXICBWlzc3VlCQDMCAIFB19hbW91bnQFA25pbAUDbmlsAwkAAAIFC2RvSXNzdWVFYXN0BQtkb0lzc3VlRWFzdAQJZWFzdEFzc2V0CQEMZ2V0RWFzdEFzc2V0AAkAzAgCCQELU3RyaW5nRW50cnkCCQEMa2V5VmF1bHREYXRhAQUHYWRkcmVzcwUMdXBkYXRlZFZhdWx0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgUHX2Ftb3VudAUJZWFzdEFzc2V0BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEFY2xvc2UDBl9hc3NldAdfYW1vdW50C19lYXN0VG9CdXJuBAdhZGRyZXNzCQDYBAEICAUBaQZjYWxsZXIFYnl0ZXMECWVhc3RBc3NldAkBDGdldEVhc3RBc3NldAAEBmNoZWNrcwkAzAgCCQEKbXVzdEFjdGl2ZQAJAMwIAgkBDWlzTm90TmVnYXRpdmUBBQdfYW1vdW50CQDMCAIJAQ1pc1ZhdWx0RXhpc3RzAQUHYWRkcmVzcwkAzAgCAwkBDWhhc09uZVBheW1lbnQBBQFpCQEHaXNBc3NldAIJAJEDAggFAWkIcGF5bWVudHMAAAUJZWFzdEFzc2V0CQERbXVzdEhhdmVOb1BheW1lbnQBBQFpCQDMCAIDCQBmAgUHX2Ftb3VudAAACQDMCAIJARBpc1N1YnZhdWx0RXhpc3RzAgUHYWRkcmVzcwUGX2Fzc2V0BQNuaWwFBHVuaXQFA25pbAMJAAACBQZjaGVja3MFBmNoZWNrcwQQZG9VcGRhdGVGcmFjdGlvbgkA/AcEBQR0aGlzAg51cGRhdGVGcmFjdGlvbgUDbmlsBQNuaWwDCQAAAgUQZG9VcGRhdGVGcmFjdGlvbgUQZG9VcGRhdGVGcmFjdGlvbgQMdmF1bHREYXRhQXJyCQEMZ2V0VmF1bHREYXRhAQUHYWRkcmVzcwQKZWFzdEFtb3VudAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFDHZhdWx0RGF0YUFycgUSSWR4VmF1bHRFYXN0QW1vdW50BA0kdDAxODY0ODE4NzY0CgABQAkA/AcEBQR0aGlzAgxnZXRWYXVsdEluZm8JAMwIAgUHYWRkcmVzcwUDbmlsBQNuaWwDCQABAgUBQAIZKEludCwgSW50LCBJbnQsIEludCwgSW50KQUBQAkAAgEJAKwCAgkAAwEFAUACLiBjb3VsZG4ndCBiZSBjYXN0IHRvIChJbnQsIEludCwgSW50LCBJbnQsIEludCkDCQAAAgUNJHQwMTg2NDgxODc2NAUNJHQwMTg2NDgxODc2NAQDZmVlCAUNJHQwMTg2NDgxODc2NAJfNQQCbHIIBQ0kdDAxODY0ODE4NzY0Al80BAJicggFDSR0MDE4NjQ4MTg3NjQCXzMEBmVhc3RFcQgFDSR0MDE4NjQ4MTg3NjQCXzIEBXVzZEVxCAUNJHQwMTg2NDgxODc2NAJfMQQQb3ZlcmNvbGxhdGVyaXplZAkAZgIFBmVhc3RFcQUKZWFzdEFtb3VudAQLZWFzdEFjdGlvbnMDCQENaGFzT25lUGF5bWVudAEFAWkEB3BheW1lbnQJAJEDAggFAWkIcGF5bWVudHMAAAQNdG90YWxFYXN0T3dlZAkAZAIFCmVhc3RBbW91bnQFA2ZlZQQMZWFzdFRvUGF5RmVlCQBlAggFB3BheW1lbnQGYW1vdW50BQtfZWFzdFRvQnVybgQMbWluRmVlQW1vdW50CQEEbXVscAIFA2ZlZQkBBGRpdnACBQtfZWFzdFRvQnVybgUNdG90YWxFYXN0T3dlZAQEZXJyMQkAAgEJAKwCAgkArAICCQCsAgICOFVuYWJsZSB0byBwcm9jZWVkLiBOb3QgZW5vdWdoIGVhc3QgdG8gcGF5IHN0YWJpbGl0eSBmZWUuCQCkAwEFDGVhc3RUb1BheUZlZQIBIAkApAMBBQxtaW5GZWVBbW91bnQDCQBmAgUMbWluRmVlQW1vdW50BQxlYXN0VG9QYXlGZWUFBGVycjEDCQBmAggFB3BheW1lbnQGYW1vdW50CQBkAgULX2Vhc3RUb0J1cm4FDGVhc3RUb1BheUZlZQUEZXJyMQQEZXJyMgkAAgECPlVuYWJsZSB0byBwcm9jZWVkLiBQYXltZW50IGlzIGJpZ2dlciB0aGFuIG93ZWQgYW1vdW50IG9mIGVhc3QuAwkAZgIIBQdwYXltZW50BmFtb3VudAUNdG90YWxFYXN0T3dlZAUEZXJyMgQEZXJyMwkAAgECJ1VuYWJsZSB0byBwcm9jZWVkLiBUb28gZmV3IGVhc3QgdG8gYnVybgMJAGYCCQERZ2V0TWluQW1vdW50RGVsdGEABQtfZWFzdFRvQnVybgUEZXJyMwQEZXJyNAkAAgECKVVuYWJsZSB0byBwcm9jZWVkLiBUb28gbXVjaCBlYXN0IHRvIGJ1cm4uAwkAZgIFC19lYXN0VG9CdXJuBQplYXN0QW1vdW50BQRlcnI0BAx1cGRhdGVkVmF1bHQJAQt1cGRhdGVWYXVsdAMFB2FkZHJlc3MJAQEtAQULX2Vhc3RUb0J1cm4FDGVhc3RUb1BheUZlZQQPdHJlYXN1cnlBZGRyZXNzCQESZ2V0VHJlYXN1cnlBZGRyZXNzAAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQ90cmVhc3VyeUFkZHJlc3MFDGVhc3RUb1BheUZlZQUJZWFzdEFzc2V0CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQxrZXlWYXVsdERhdGEBBQdhZGRyZXNzBQx1cGRhdGVkVmF1bHQJAMwIAgkBBEJ1cm4CBQllYXN0QXNzZXQFC19lYXN0VG9CdXJuBQNuaWwFA25pbAQMYXNzZXRBY3Rpb25zAwkAZgIFB19hbW91bnQAAAQIY29udHJhY3QJARBnZXRBc3NldENvbnRyYWN0AQUGX2Fzc2V0BA0kdDAyMDEwMzIwMjUwCgABQAkA/AcEBQhjb250cmFjdAIFY2xvc2UJAMwIAgUHYWRkcmVzcwkAzAgCBQdfYW1vdW50BQNuaWwFA25pbAMJAAECBQFAAhIoU3RyaW5nLCBJbnQsIEludCkFAUAJAAIBCQCsAgIJAAMBBQFAAicgY291bGRuJ3QgYmUgY2FzdCB0byAoU3RyaW5nLCBJbnQsIEludCkDCQAAAgUNJHQwMjAxMDMyMDI1MAUNJHQwMjAxMDMyMDI1MAQRY2xvc2VkQW1vdW50SW5Vc2QIBQ0kdDAyMDEwMzIwMjUwAl8zBBRjbG9zZWRFYXN0RXF1aXZhbGVudAgFDSR0MDIwMTAzMjAyNTACXzIEEXVwZGF0ZWRWYXVsdEFzc2V0CAUNJHQwMjAxMDMyMDI1MAJfMQQEZXJyMQkAAgECKlVuYWJsZSB0byBwcm9jZWVkLiBUb28gZmV3IGFzc2V0cyB0byBjbG9zZQMJAGYCCQERZ2V0TWluQW1vdW50RGVsdGEABQdfYW1vdW50BQRlcnIxBARlcnIyCQACAQJEVW5hYmxlIHRvIHByb2NlZWQuIFRvbyBtdWNoIGFzc2V0cyB0byBjbG9zZSBmb3IgdGhhdCBhbW91bnQgb2YgZWFzdC4DAwUQb3ZlcmNvbGxhdGVyaXplZAkAZgIJAGUCBQplYXN0QW1vdW50BQtfZWFzdFRvQnVybgkAZQIFBmVhc3RFcQUUY2xvc2VkRWFzdEVxdWl2YWxlbnQHBQRlcnIyBAhuZXdVc2RFcQkAZQIFBXVzZEVxBRFjbG9zZWRBbW91bnRJblVzZAQNbmV3RWFzdEFtb3VudAkAZQIFCmVhc3RBbW91bnQFC19lYXN0VG9CdXJuBARlcnIzCQACAQI7VW5hYmxlIHRvIHByb2NlZWQuIEJSIGFmdGVyIGNsb3NlIG11c3QgYmUgbW9yZSB0aGFuIGJlZm9yZS4EBHUxZTIJALkCAgkAtgIBBQV1c2RFcQkAtgIBBQ1uZXdFYXN0QW1vdW50BAR1MmUxCQC5AgIJALYCAQUIbmV3VXNkRXEJALYCAQUKZWFzdEFtb3VudAMDCQEBIQEFEG92ZXJjb2xsYXRlcml6ZWQJAL8CAgUEdTFlMgUEdTJlMQcFBGVycjMJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDWtleVZhdWx0QXNzZXQCBQdhZGRyZXNzBQZfYXNzZXQFEXVwZGF0ZWRWYXVsdEFzc2V0BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAkAzggCBQtlYXN0QWN0aW9ucwUMYXNzZXRBY3Rpb25zCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCWxpcXVpZGF0ZQEIX2FkZHJlc3MEB3BheW1lbnQJAJEDAggFAWkIcGF5bWVudHMAAAQJZWFzdEFzc2V0CQEMZ2V0RWFzdEFzc2V0AAQGY2hlY2tzCQDMCAIJAQptdXN0QWN0aXZlAAkAzAgCCQESbXVzdEhhdmVPbmVQYXltZW50AQUBaQkAzAgCCQERbXVzdE5vdFZhdWx0T3duZXICBQFpBQhfYWRkcmVzcwkAzAgCCQEHaXNBc3NldAIFB3BheW1lbnQFCWVhc3RBc3NldAkAzAgCCQENaXNWYXVsdEV4aXN0cwEFCF9hZGRyZXNzBQNuaWwDCQAAAgUGY2hlY2tzBQZjaGVja3MEEGRvVXBkYXRlRnJhY3Rpb24JAPwHBAUEdGhpcwIOdXBkYXRlRnJhY3Rpb24FA25pbAUDbmlsAwkAAAIFEGRvVXBkYXRlRnJhY3Rpb24FEGRvVXBkYXRlRnJhY3Rpb24EDHZhdWx0RGF0YUFycgkBDGdldFZhdWx0RGF0YQEFCF9hZGRyZXNzBAplYXN0QW1vdW50CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUMdmF1bHREYXRhQXJyBRJJZHhWYXVsdEVhc3RBbW91bnQEGW1heExpcXVpZGF0ZUFtb3VudEFsbG93ZWQJAQRtdWxwAgUKZWFzdEFtb3VudAUUTUFYX0xJUVVJREFUSU9OX1BBUlQEBGVycjEJAAIBAkJVbmFibGUgdG8gcHJvY2VlZC4gUGF5bWVudCBhbW91bnQgaXMgYmlnZ2VyIHRoYW4gNTAlIG9mIHRoZSB2YXVsdC4DCQBmAggFB3BheW1lbnQGYW1vdW50BRltYXhMaXF1aWRhdGVBbW91bnRBbGxvd2VkBQRlcnIxBA0kdDAyMTc0OTIxOTAwCgABQAkA/AcEBQR0aGlzAgxnZXRWYXVsdEluZm8JAMwIAgUIX2FkZHJlc3MFA25pbAUDbmlsAwkAAQIFAUACGShJbnQsIEludCwgSW50LCBJbnQsIEludCkFAUAJAAIBCQCsAgIJAAMBBQFAAi4gY291bGRuJ3QgYmUgY2FzdCB0byAoSW50LCBJbnQsIEludCwgSW50LCBJbnQpAwkAAAIFDSR0MDIxNzQ5MjE5MDAFDSR0MDIxNzQ5MjE5MDAEA2ZlZQgFDSR0MDIxNzQ5MjE5MDACXzUEE2F2Z0xpcXVpZGF0aW9uUmF0aW8IBQ0kdDAyMTc0OTIxOTAwAl80BBNjdXJyZW50QmFja2luZ1JhdGlvCAUNJHQwMjE3NDkyMTkwMAJfMwQGZWFzdEVxCAUNJHQwMjE3NDkyMTkwMAJfMgQFdXNkRXEIBQ0kdDAyMTc0OTIxOTAwAl8xBARlcnIyCQACAQIqVW5hYmxlIHRvIHByb2NlZWQuIFZhdWx0IGhlYWx0aCBpcyBub3JtYWwuAwkAZgIFE2N1cnJlbnRCYWNraW5nUmF0aW8FE2F2Z0xpcXVpZGF0aW9uUmF0aW8FBGVycjIEEGxpcXVpZGF0aW9uQm9udXMJAQRtdWxwAggFB3BheW1lbnQGYW1vdW50CQETZ2V0TGlxdWlkYXRpb25Cb251cwAEF2xpcXVpZGF0aW9uQW1vdW50SW5FYXN0CQBkAggFB3BheW1lbnQGYW1vdW50BRBsaXF1aWRhdGlvbkJvbnVzBBBsaXF1aWRhdGlvblJhdGlvCQEEZGl2cAIFF2xpcXVpZGF0aW9uQW1vdW50SW5FYXN0BQV1c2RFcQQPdHJlYXN1cnlBZGRyZXNzCQESZ2V0VHJlYXN1cnlBZGRyZXNzAAQRbGlxdWlkYXRvckFkZHJlc3MJANgEAQgIBQFpBmNhbGxlcgVieXRlcwoBD2xpcXVpZGF0ZUFzc2V0cwIDYWNjBG5leHQEByRtYXRjaDAFBG5leHQDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAVhc3NldAUHJG1hdGNoMAQFY2hlY2sJAQlpc0VuYWJsZWQBBQVhc3NldAMJAAACBQVjaGVjawUFY2hlY2sEBXZhdWx0CQELZ2V0U3VidmF1bHQCBQhfYWRkcmVzcwUFYXNzZXQEByRtYXRjaDEFBXZhdWx0AwkAAQIFByRtYXRjaDECBlN0cmluZwQBdgUHJG1hdGNoMQQIY29udHJhY3QJARBnZXRBc3NldENvbnRyYWN0AQUFYXNzZXQEDSR0MDIyNjcxMjI4MzEKAAFACQD8BwQFCGNvbnRyYWN0AglsaXF1aWRhdGUJAMwIAgURbGlxdWlkYXRvckFkZHJlc3MJAMwIAgUIX2FkZHJlc3MJAMwIAgUQbGlxdWlkYXRpb25SYXRpbwUDbmlsBQNuaWwDCQABAgUBQAINKFN0cmluZywgSW50KQUBQAkAAgEJAKwCAgkAAwEFAUACIiBjb3VsZG4ndCBiZSBjYXN0IHRvIChTdHJpbmcsIEludCkDCQAAAgUNJHQwMjI2NzEyMjgzMQUNJHQwMjI2NzEyMjgzMQQYbGlxdWlkYXRlZEVhc3RFcXVpdmFsZW50CAUNJHQwMjI2NzEyMjgzMQJfMgQRdXBkYXRlZFZhdWx0QXNzZXQIBQ0kdDAyMjY3MTIyODMxAl8xBAdhc3NldElkCQEUZ2V0QXNzZXRJZEZyb21TdHJpbmcBBQVhc3NldAQHYWN0aW9ucwkAzAgCCQELU3RyaW5nRW50cnkCCQENa2V5VmF1bHRBc3NldAIFCF9hZGRyZXNzBQVhc3NldAURdXBkYXRlZFZhdWx0QXNzZXQFA25pbAkAlAoCCQDOCAIIBQNhY2MCXzEFB2FjdGlvbnMJAGQCCAUDYWNjAl8yBRhsaXF1aWRhdGVkRWFzdEVxdWl2YWxlbnQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4DCQABAgUHJG1hdGNoMQIEVW5pdAUDYWNjCQACAQILTWF0Y2ggZXJyb3IJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4DCQABAgUHJG1hdGNoMAIEVW5pdAUDYWNjCQACAQILTWF0Y2ggZXJyb3IEBmFzc2V0cwkBDmdldFZhdWx0QXNzZXRzAQUIX2FkZHJlc3MEDSR0MDIzMTg3MjMyODEKAAIkbAUGYXNzZXRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlAoCBQNuaWwAAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEPbGlxdWlkYXRlQXNzZXRzAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKBBJ2YXVsdEFzc2V0c0FjdGlvbnMIBQ0kdDAyMzE4NzIzMjgxAl8xBBdsaXF1aWRhdGVkRWFzdEVxaXZhbGVudAgFDSR0MDIzMTg3MjMyODECXzIEDHVwZGF0ZWRWYXVsdAkBC3VwZGF0ZVZhdWx0AwUIX2FkZHJlc3MJAQEtAQgFB3BheW1lbnQGYW1vdW50AAAECXBvc3RDaGVjawMJAQ1pc05vdFRyZWFzdXJ5AQUBaQQIbmV3VXNkRXEJAGUCBQV1c2RFcQUXbGlxdWlkYXRpb25BbW91bnRJbkVhc3QECW5ld0Vhc3RFcQkAZQIFBmVhc3RFcQUXbGlxdWlkYXRlZEVhc3RFcWl2YWxlbnQEDW5ld0Vhc3RBbW91bnQJAGUCBQplYXN0QW1vdW50CAUHcGF5bWVudAZhbW91bnQEBGVycjMJAAIBAkFVbmFibGUgdG8gcHJvY2VlZC4gQlIgYWZ0ZXIgbGlxdWlkYXRpb24gbXVzdCBiZSBtb3JlIHRoYW4gYmVmb3JlLgQEdTFlMgkAuQICCQC2AgEFBXVzZEVxCQC2AgEFDW5ld0Vhc3RBbW91bnQEBHUyZTEJALkCAgkAtgIBBQhuZXdVc2RFcQkAtgIBBQplYXN0QW1vdW50AwkAvwICBQR1MWUyBQR1MmUxBQRlcnIzBARlcnI0CQACAQJAVW5hYmxlIHRvIHByb2NlZWQuIFZhdWx0IGhlYWx0aCBpcyBhYm92ZSAxMDAlIGFmdGVyIGxpcXVpZGF0aW9uLgMJAGYCBQluZXdFYXN0RXEFDW5ld0Vhc3RBbW91bnQFBGVycjQFBHVuaXQFBHVuaXQDCQAAAgUJcG9zdENoZWNrBQlwb3N0Q2hlY2sEDHZhdWx0QWN0aW9ucwkAzAgCCQEEQnVybgIFCWVhc3RBc3NldAgFB3BheW1lbnQGYW1vdW50CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQxrZXlWYXVsdERhdGEBBQhfYWRkcmVzcwUMdXBkYXRlZFZhdWx0BQNuaWwJAM4IAgUMdmF1bHRBY3Rpb25zBRJ2YXVsdEFzc2V0c0FjdGlvbnMJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEMZ2V0VmF1bHRJbmZvAQhfYWRkcmVzcwQGZXhpc3RzCQENaXNWYXVsdEV4aXN0cwEFCF9hZGRyZXNzAwkAAAIFBmV4aXN0cwUGZXhpc3RzBBBkb1VwZGF0ZUZyYWN0aW9uCQD8BwQFBHRoaXMCDnVwZGF0ZUZyYWN0aW9uBQNuaWwFA25pbAMJAAACBRBkb1VwZGF0ZUZyYWN0aW9uBRBkb1VwZGF0ZUZyYWN0aW9uBAZhc3NldHMJAQ5nZXRWYXVsdEFzc2V0cwEFCF9hZGRyZXNzCgEFY291bnQCA2FjYwRuZXh0BAckbWF0Y2gwBQRuZXh0AwkAAQIFByRtYXRjaDACBlN0cmluZwQFYXNzZXQFByRtYXRjaDAECGNvbnRyYWN0CQEQZ2V0QXNzZXRDb250cmFjdAEFBWFzc2V0BA0kdDAyNDQ5NTI0NjA3CgABQAkA/AcEBQhjb250cmFjdAIPZ2V0U3VidmF1bHRJbmZvCQDMCAIFCF9hZGRyZXNzBQNuaWwFA25pbAMJAAECBQFAAg8oSW50LCBJbnQsIEludCkFAUAJAAIBCQCsAgIJAAMBBQFAAiQgY291bGRuJ3QgYmUgY2FzdCB0byAoSW50LCBJbnQsIEludCkDCQAAAgUNJHQwMjQ0OTUyNDYwNwUNJHQwMjQ0OTUyNDYwNwQJdGhyZXNob2xkCAUNJHQwMjQ0OTUyNDYwNwJfMwQGZWFzdEVxCAUNJHQwMjQ0OTUyNDYwNwJfMgQFdXNkRXEIBQ0kdDAyNDQ5NTI0NjA3Al8xCQCVCgMJAGQCCAUDYWNjAl8xBQV1c2RFcQkAZAIIBQNhY2MCXzIFBmVhc3RFcQkAZAIIBQNhY2MCXzMFCXRocmVzaG9sZAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgMJAAECBQckbWF0Y2gwAgRVbml0BQNhY2MJAAIBAgtNYXRjaCBlcnJvcgQMdmF1bHREYXRhQXJyCQEMZ2V0VmF1bHREYXRhAQUIX2FkZHJlc3MECmVhc3RBbW91bnQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQx2YXVsdERhdGFBcnIFEklkeFZhdWx0RWFzdEFtb3VudAQQbGFzdFN0YWJpbGl0eUZlZQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFDHZhdWx0RGF0YUFycgUPSWR4U3RhYmlsaXR5RmVlBAxsYXN0RnJhY3Rpb24JAQ1wYXJzZUludFZhbHVlAQkAkQMCBQx2YXVsdERhdGFBcnIFD0lkeExhc3RGcmFjdGlvbgQNJHQwMjQ5NjgyNTAzNQoAAiRsBQZhc3NldHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCVCgMAAAAAAAAKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBBWNvdW50AgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKBAV1c2RFcQgFDSR0MDI0OTY4MjUwMzUCXzEEBmVhc3RFcQgFDSR0MDI0OTY4MjUwMzUCXzIECXRocmVzaG9sZAgFDSR0MDI0OTY4MjUwMzUCXzMEE2F2Z0xpcXVpZGF0aW9uUmF0aW8JAQRkaXZwAgUJdGhyZXNob2xkBQV1c2RFcQQTY3VycmVudEJhY2tpbmdSYXRpbwMJAGYCBQplYXN0QW1vdW50AAAJAQRkaXZwAgUFdXNkRXEFCmVhc3RBbW91bnQFCElORklOSVRZBAxzdGFiaWxpdHlGZWUJARZnZXRDdXJyZW50U3RhYmlsaXR5RmVlAwUKZWFzdEFtb3VudAUQbGFzdFN0YWJpbGl0eUZlZQUMbGFzdEZyYWN0aW9uCQCUCgIFA25pbAkAlwoFBQV1c2RFcQUGZWFzdEVxBRNjdXJyZW50QmFja2luZ1JhdGlvBRNhdmdMaXF1aWRhdGlvblJhdGlvBQxzdGFiaWxpdHlGZWUJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BAnR4AQZ2ZXJpZnkABAckbWF0Y2gwCQEIdmVyaWZpZXIAAwkAAQIFByRtYXRjaDACBlN0cmluZwQHYWRkcmVzcwUHJG1hdGNoMAkBC3ZhbHVlT3JFbHNlAgkAmwgCCQERQGV4dHJOYXRpdmUoMTA2MikBBQdhZGRyZXNzCQEJa2V5U2lnbmVkAgkApQgBBQR0aGlzCQDYBAEIBQJ0eAJpZAcJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAAIBQJ0eA9zZW5kZXJQdWJsaWNLZXlfY2hT", "height": 3616978, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: none Next: none Full:
OldNewDifferences
1-# no script
1+{-# STDLIB_VERSION 6 #-}
2+{-# SCRIPT_TYPE ACCOUNT #-}
3+{-# CONTENT_TYPE DAPP #-}
4+let SEP = "__"
5+
6+let EMPTY = ""
7+
8+let PRECISION = 1000000000000
9+
10+let DECIMALS = 100000000
11+
12+let DEFAULT_MAX_SLIPPAGE = ((PRECISION / 20) * 19)
13+
14+let DAY = ((60 * 60) * 24)
15+
16+let YEAR = (DAY * 365)
17+
18+let ORACLE_DECIMALS = 1000000
19+
20+let INFINITY = 9223372036854775807
21+
22+let MIN_AMOUNT_DELTA = 1000
23+
24+let MAX_RATE_HEIGHT_DELTA = 5
25+
26+let LIQUIDATION_BONUS = ((PRECISION / 100) * 5)
27+
28+let LIQUIDATION_PROTOCOL_FEE = ((PRECISION / 100) * 2)
29+
30+let MAX_LIQUIDATION_PART = ((PRECISION / 100) * 50)
31+
32+let STABILITY_FEE = (PRECISION / 100)
33+
34+let ENABLED = "ENABLED"
35+
36+let DISABLED = "DISABLED"
37+
38+let IdxVaultAssetCount = 1
39+
40+let IdxVaultAssetAmount = 2
41+
42+let IdxVaultAssetRate = 3
43+
44+let IdxVaultCount = 1
45+
46+let IdxVaultEastAmount = 2
47+
48+let IdxVaultTimestamp = 3
49+
50+let IdxStabilityFee = 4
51+
52+let IdxLastFraction = 5
53+
54+let invocationError = "Invocation error"
55+
56+func divd (_x,_y) = fraction(_x, DECIMALS, _y, HALFEVEN)
57+
58+
59+func muld (_x,_y) = fraction(_x, _y, DECIMALS, HALFEVEN)
60+
61+
62+func divp (_x,_y) = fraction(_x, PRECISION, _y, HALFEVEN)
63+
64+
65+func mulp (_x,_y) = fraction(_x, _y, PRECISION, HALFEVEN)
66+
67+
68+func join (ar) = makeString(ar, SEP)
69+
70+
71+func keyInitialized () = join(["%s", "initialized"])
72+
73+
74+func keyCoordinatorAddress () = join(["%s", "coordinatorAddress"])
75+
76+
77+func keyVerifierAddress () = join(["%s", "verifierAddress"])
78+
79+
80+func keyServiceAddress () = join(["%s", "serviceAddress"])
81+
82+
83+func keyFrontendAddress () = join(["%s", "frontendAddress"])
84+
85+
86+func keyMinterAddress () = join(["%s", "minterAddress"])
87+
88+
89+func keyTreasuryAddress () = join(["%s", "treasuryAddress"])
90+
91+
92+func keyBackendAddress () = join(["%s", "backendAddress"])
93+
94+
95+func keyEastStakingAddress () = join(["%s", "eastStakingAddress"])
96+
97+
98+func keyOracleAddress () = join(["%s", "oracleAddress"])
99+
100+
101+func keyExchangeAddress () = join(["%s", "exchangeAddress"])
102+
103+
104+func keyEastAsset () = join(["%s", "eastAsset"])
105+
106+
107+func keyStEastAsset () = join(["%s", "stEastAsset"])
108+
109+
110+func keyAAssetBalance () = "A_asset_balance"
111+
112+
113+func keyBAssetBalance () = "B_asset_balance"
114+
115+
116+func keyVaultAsset (address,asset) = join(["%s%s%s", "vault", address, asset])
117+
118+
119+func keyVaultData (address) = join(["%s%s", "vault", address])
120+
121+
122+func keyPrecision () = join(["%s", "precision"])
123+
124+
125+func keyBackingRatio () = join(["%s", "backingRatio"])
126+
127+
128+func keyLiquidationRatio () = join(["%s", "liquidationRatio"])
129+
130+
131+func keyLiquidationBonus () = join(["%s", "liquidationBonus"])
132+
133+
134+func keyLiquidationProtocolFee () = join(["%s", "liquidationProtocolFee"])
135+
136+
137+func keyStabilityFee () = join(["%s", "stabilityFee"])
138+
139+
140+func keyMinAmountDelta () = join(["%s", "minAmountDelta"])
141+
142+
143+func keyTicker () = join(["%s", "ticker"])
144+
145+
146+func keyMaxRateHeightDelta () = join(["%s", "maxRateHeightDelta"])
147+
148+
149+func keyContractAssetId () = join(["%s", "contractAssetId"])
150+
151+
152+func keyOracleTickerPrice (ticker) = join(["%s%s", "price", ticker])
153+
154+
155+func keyOracleTickerPriceHeight (ticker) = join(["%s%s", "lastHeight", ticker])
156+
157+
158+func keySigned (_address,_txId) = join(["%s%s%s", "signed", _address, _txId])
159+
160+
161+func keyProtocolActive () = join(["%s", "protocolActive"])
162+
163+
164+func isInitialized () = valueOrElse(getBoolean(this, keyInitialized()), false)
165+
166+
167+func mustInitialized () = if (!(isInitialized()))
168+ then throw("Not initialized")
169+ else unit
170+
171+
172+func mustNotInitialized () = if (isInitialized())
173+ then throw("Already initialized")
174+ else unit
175+
176+
177+func mustSelf (i) = if ((i.caller != this))
178+ then throw("Only self invocation allowed.")
179+ else unit
180+
181+
182+func coordinator () = addressFromStringValue(valueOrErrorMessage(getString(keyCoordinatorAddress()), "Coordinator is not set"))
183+
184+
185+func verifier () = match getString(keyCoordinatorAddress()) {
186+ case s: String =>
187+ getString(addressFromStringValue(s), keyVerifierAddress())
188+ case _: Unit =>
189+ unit
190+ case _ =>
191+ throw("Match error")
192+}
193+
194+
195+func getAddress (key,err) = addressFromStringValue(valueOrErrorMessage(getString(coordinator(), key), err))
196+
197+
198+func getMinterAddress () = getAddress(keyMinterAddress(), "Minter is not set")
199+
200+
201+func getFrontendAddress () = getAddress(keyFrontendAddress(), "Frontend is not set")
202+
203+
204+func getTreasuryAddress () = getAddress(keyTreasuryAddress(), "Treasury is not set")
205+
206+
207+func getBackendAddress () = getAddress(keyBackendAddress(), "Backend is not set")
208+
209+
210+func getOracleAddress () = getAddress(keyOracleAddress(), "Oracle is not set")
211+
212+
213+func getEastStakingAddress () = getAddress(keyEastStakingAddress(), "East staking is not set")
214+
215+
216+func isNotTreasury (i) = (i.caller != getTreasuryAddress())
217+
218+
219+func getMinAmountDelta () = valueOrElse(getInteger(coordinator(), keyMinAmountDelta()), MIN_AMOUNT_DELTA)
220+
221+
222+func getMaxRateHeightDelta () = valueOrElse(getInteger(coordinator(), keyMaxRateHeightDelta()), MAX_RATE_HEIGHT_DELTA)
223+
224+
225+func getLiquidationBonus () = valueOrElse(getInteger(coordinator(), keyLiquidationBonus()), LIQUIDATION_BONUS)
226+
227+
228+func getLiquidationProtocolFee () = valueOrElse(getInteger(coordinator(), keyLiquidationProtocolFee()), LIQUIDATION_PROTOCOL_FEE)
229+
230+
231+func getStabilityFee () = valueOrElse(getInteger(coordinator(), keyStabilityFee()), STABILITY_FEE)
232+
233+
234+func getAssetId () = getStringValue(keyContractAssetId())
235+
236+
237+func getEastAssetStr () = valueOrErrorMessage(getString(coordinator(), keyEastAsset()), "East asset is not set")
238+
239+
240+func getEastAsset () = fromBase58String(getEastAssetStr())
241+
242+
243+func isActive () = valueOrElse(getBoolean(coordinator(), keyProtocolActive()), false)
244+
245+
246+func mustActive () = if (if (!(isActive()))
247+ then true
248+ else !(isInitialized()))
249+ then throw("Protocol is disabled. Please contact support.")
250+ else unit
251+
252+
253+func mustFrontend (i) = if ((i.caller != getFrontendAddress()))
254+ then throw("Not allowed")
255+ else unit
256+
257+
258+func mustBackend (i) = if ((i.caller != getBackendAddress()))
259+ then throw("Not allowed")
260+ else unit
261+
262+
263+func mustNotVaultOwner (i,address) = if ((toBase58String(i.caller.bytes) == address))
264+ then throw("Self invocation not allowed.")
265+ else unit
266+
267+
268+func mustHaveOnePayment (i) = if ((size(i.payments) != 1))
269+ then throw("Only one payment allowed.")
270+ else unit
271+
272+
273+func mustHaveNoPayment (i) = if ((size(i.payments) != 0))
274+ then throw("No payment allowed.")
275+ else unit
276+
277+
278+func hasOnePayment (i) = (size(i.payments) == 1)
279+
280+
281+func isPositive (number) = if ((0 >= number))
282+ then throw("Attribute should be positive or zero.")
283+ else unit
284+
285+
286+func isNotNegative (number) = if ((0 > number))
287+ then throw("Attribute should be positive.")
288+ else unit
289+
290+
291+func getSubvault (address,asset) = getString(keyVaultAsset(address, asset))
292+
293+
294+func isSubvaultExists (address,asset) = valueOrErrorMessage(getSubvault(address, asset), "Vault not exists")
295+
296+
297+func getAssetString (p) = match p.assetId {
298+ case assetId: ByteVector =>
299+ toBase58String(assetId)
300+ case _: Unit =>
301+ "WAVES"
302+ case _ =>
303+ throw("Match error")
304+}
305+
306+
307+func getAssetIdFromString (assetId) = if ((assetId == "WAVES"))
308+ then unit
309+ else fromBase58String(assetId)
310+
311+
312+func isAsset (p,checkingAsset) = {
313+ let assetId = match checkingAsset {
314+ case bv: ByteVector =>
315+ bv
316+ case s: String =>
317+ getAssetIdFromString(s)
318+ case _: Unit =>
319+ unit
320+ case _ =>
321+ throw("Match error")
322+ }
323+ match assetId {
324+ case bv: ByteVector =>
325+ let name = match assetInfo(bv) {
326+ case asset: Asset =>
327+ asset.name
328+ case _: Unit =>
329+ throw(("Can't find asset " + toBase58String(bv)))
330+ case _ =>
331+ throw("Match error")
332+ }
333+ let err = throw(("Attached payment asset is not " + name))
334+ match p.assetId {
335+ case paymentAsset: ByteVector =>
336+ if ((paymentAsset != assetId))
337+ then err
338+ else unit
339+ case _: Unit =>
340+ err
341+ case _ =>
342+ throw("Match error")
343+ }
344+ case _: Unit =>
345+ if ((p.assetId != unit))
346+ then throw("Attached payment asset is not WAVES")
347+ else unit
348+ case _ =>
349+ throw("Match error")
350+ }
351+ }
352+
353+
354+func getBackingRatio () = valueOrErrorMessage(getInteger(keyBackingRatio()), "Backing ratio is not set")
355+
356+
357+func getLiquidationRatio () = valueOrErrorMessage(getInteger(keyLiquidationRatio()), "Liquidation ratio is not set")
358+
359+
360+func checkAddress (_address) = match addressFromString(_address) {
361+ case address: Address =>
362+ true
363+ case _: Unit =>
364+ throw("Invalid address")
365+ case _ =>
366+ throw("Match error")
367+}
368+
369+
370+func checkTxId (_id) = (size(fromBase58String(_id)) == 32)
371+
372+
373+func getCurrentTimestampSec () = (lastBlock.timestamp / 1000)
374+
375+
376+func mustWavesPayment (i) = {
377+ let check = mustHaveOnePayment(i)
378+ if ((check == check))
379+ then {
380+ let pmtAssetId = i.payments[0].assetId
381+ match pmtAssetId {
382+ case a: Unit =>
383+ unit
384+ case _ =>
385+ throw("Only WAVES accepted")
386+ }
387+ }
388+ else throw("Strict value is not equal to itself.")
389+ }
390+
391+
392+func getAssetInfo (assetId) = match assetId {
393+ case id: ByteVector =>
394+ let stringId = toBase58String(id)
395+ let info = valueOrErrorMessage(assetInfo(id), (("Asset " + stringId) + " doesn't exist"))
396+ $Tuple3(stringId, info.name, info.decimals)
397+ case waves: Unit =>
398+ $Tuple3("WAVES", "WAVES", 8)
399+ case _ =>
400+ throw("Match error")
401+}
402+
403+
404+func checkHeightDelta (priceHeight) = {
405+ let maxHeightDelta = getMaxRateHeightDelta()
406+ let currentDiff = (lastBlock.height - priceHeight)
407+ if ((maxHeightDelta >= currentDiff))
408+ then unit
409+ else throw("Large price delta.")
410+ }
411+
412+
413+func getAssetUsdPrice () = {
414+ let ticker = getStringValue(this, keyTicker())
415+ let oracleAddress = getOracleAddress()
416+ let priceHeight = getIntegerValue(oracleAddress, keyOracleTickerPriceHeight(ticker))
417+ let checkHeight = checkHeightDelta(priceHeight)
418+ if ((checkHeight == checkHeight))
419+ then {
420+ let price = getIntegerValue(oracleAddress, keyOracleTickerPrice(ticker))
421+ fraction(price, PRECISION, ORACLE_DECIMALS)
422+ }
423+ else throw("Strict value is not equal to itself.")
424+ }
425+
426+
427+let IdxAssetStatus = 1
428+
429+let IdxAssetContractId = 2
430+
431+func keyAsset (_assetStr) = join(["%s%s", "asset", _assetStr])
432+
433+
434+func keyVaultAssets (_address) = join(["%s%s", "vaultAssets", _address])
435+
436+
437+func keyCumulativeFeeFraction () = join(["%s", "cumulativeFeeFraction"])
438+
439+
440+func keyFractionLastUpdated () = join(["%s", "fractionLastUpdated"])
441+
442+
443+func getAssetContractStr (_asset) = valueOrErrorMessage(getString(keyAsset(_asset)), "Unknown asset")
444+
445+
446+func getAssetContract (_asset) = {
447+ let contractStr = getAssetContractStr(_asset)
448+ let contractArr = split(contractStr, SEP)
449+ let contractId = contractArr[IdxAssetContractId]
450+ addressFromStringValue(contractId)
451+ }
452+
453+
454+func getVaultAssets (_address) = match getString(keyVaultAssets(_address)) {
455+ case s: String =>
456+ split(s, SEP)
457+ case _: Unit =>
458+ nil
459+ case _ =>
460+ throw("Match error")
461+}
462+
463+
464+func getVaultData (_address) = match getString(keyVaultData(_address)) {
465+ case s: String =>
466+ split(s, SEP)
467+ case _: Unit =>
468+["%d%d%d%d%d", "0", "0", toString(getCurrentTimestampSec()), "0", "0"]
469+ case _ =>
470+ throw("Match error")
471+}
472+
473+
474+func assetExist (_assetStr) = match getString(keyAsset(_assetStr)) {
475+ case s: String =>
476+ true
477+ case _: Unit =>
478+ false
479+ case _ =>
480+ throw("Match error")
481+}
482+
483+
484+func getCumulativeFeeFraction () = valueOrElse(getInteger(keyCumulativeFeeFraction()), 0)
485+
486+
487+func getFractionLastUpdated () = valueOrElse(getInteger(keyFractionLastUpdated()), getCurrentTimestampSec())
488+
489+
490+func isEnabled (_assetStr) = {
491+ let assetCfg = getStringValue(keyAsset(_assetStr))
492+ let assetArr = split(assetCfg, SEP)
493+ if ((assetArr[IdxAssetStatus] != ENABLED))
494+ then throw((("Asset " + _assetStr) + " is not enabled"))
495+ else unit
496+ }
497+
498+
499+func isVaultExists (_address) = if ((size(getVaultAssets(_address)) == 0))
500+ then throw("Vault is not exist")
501+ else unit
502+
503+
504+func getCurrentStabilityFee (_eastAmount,_lastStabilityFee,_lastFraction) = (_lastStabilityFee + mulp(_eastAmount, (getCumulativeFeeFraction() - _lastFraction)))
505+
506+
507+func dataAsset (_status,_address) = makeString(["%s%s", _status, _address], SEP)
508+
509+
510+func updateVault (_address,_eastAmount,_paidFee) = {
511+ let vault = getVaultData(_address)
512+ let eastAmount = parseIntValue(vault[IdxVaultEastAmount])
513+ let count = parseIntValue(vault[IdxVaultCount])
514+ let timestamp = parseIntValue(vault[IdxVaultTimestamp])
515+ let lastStabilityFee = parseIntValue(vault[IdxStabilityFee])
516+ let lastFraction = parseIntValue(vault[IdxLastFraction])
517+ let newEastAmount = (eastAmount + _eastAmount)
518+ let newCount = (count + 1)
519+ if ((0 > newEastAmount))
520+ then throw("Something went wrong. Contact support")
521+ else {
522+ let newStabilityFee = (getCurrentStabilityFee(eastAmount, lastStabilityFee, lastFraction) - _paidFee)
523+ makeString(["%d%d%d%d%d", toString(newCount), toString(newEastAmount), toString(getCurrentTimestampSec()), toString(newStabilityFee), toString(getCumulativeFeeFraction())], SEP)
524+ }
525+ }
526+
527+
528+func addVaultAsset (_address,_assetStr) = {
529+ let assets = getVaultAssets(_address)
530+ if (containsElement(assets, _assetStr))
531+ then throw("Asset already exists")
532+ else makeString((assets :+ _assetStr), SEP)
533+ }
534+
535+
536+func removeVaultAsset (_address,_assetStr) = {
537+ let assets = getVaultAssets(_address)
538+ if (!(containsElement(assets, _assetStr)))
539+ then throw("Unknown asset")
540+ else {
541+ let idx = {
542+ let @ = indexOf(assets, _assetStr)
543+ if ($isInstanceOf(@, "Int"))
544+ then @
545+ else throw(($getType(@) + " couldn't be cast to Int"))
546+ }
547+ makeString(removeByIndex(assets, idx), SEP)
548+ }
549+ }
550+
551+
552+@Callable(i)
553+func initialize (_coordinatorAddress) = {
554+ let checks = [mustNotInitialized(), checkAddress(_coordinatorAddress)]
555+ if ((checks == checks))
556+ then [StringEntry(keyCoordinatorAddress(), _coordinatorAddress), BooleanEntry(keyInitialized(), true)]
557+ else throw("Strict value is not equal to itself.")
558+ }
559+
560+
561+
562+@Callable(i)
563+func addAsset (_assetStr,_contractStr) = {
564+ let checks = [mustInitialized(), mustSelf(i)]
565+ if ((checks == checks))
566+ then if (!(checkAddress(_contractStr)))
567+ then throw("Address is not valid")
568+ else if (assetExist(_assetStr))
569+ then throw("Asset is already set")
570+ else [StringEntry(keyAsset(_assetStr), dataAsset(ENABLED, _contractStr))]
571+ else throw("Strict value is not equal to itself.")
572+ }
573+
574+
575+
576+@Callable(i)
577+func disableAsset (_assetStr) = {
578+ let checks = [mustInitialized(), mustSelf(i)]
579+ if ((checks == checks))
580+ then {
581+ let assetArr = split(valueOrErrorMessage(getString(keyAsset(_assetStr)), "Unknown asset"), SEP)
582+[StringEntry(keyAsset(_assetStr), dataAsset(DISABLED, assetArr[IdxAssetContractId]))]
583+ }
584+ else throw("Strict value is not equal to itself.")
585+ }
586+
587+
588+
589+@Callable(i)
590+func enableAsset (_assetStr) = {
591+ let checks = [mustInitialized(), mustSelf(i)]
592+ if ((checks == checks))
593+ then {
594+ let assetArr = split(valueOrErrorMessage(getString(keyAsset(_assetStr)), "Unknown asset"), SEP)
595+[StringEntry(keyAsset(_assetStr), dataAsset(ENABLED, assetArr[IdxAssetContractId]))]
596+ }
597+ else throw("Strict value is not equal to itself.")
598+ }
599+
600+
601+
602+@Callable(i)
603+func updateFraction () = {
604+ let delta = (getCurrentTimestampSec() - getFractionLastUpdated())
605+ let fractionDelta = mulp(divp(delta, YEAR), getStabilityFee())
606+ let cumulativeFeeFraction = (getCumulativeFeeFraction() + fractionDelta)
607+[IntegerEntry(keyCumulativeFeeFraction(), cumulativeFeeFraction), IntegerEntry(keyFractionLastUpdated(), getCurrentTimestampSec())]
608+ }
609+
610+
611+
612+@Callable(i)
613+func mint () = {
614+ let payment = i.payments[0]
615+ let assetStr = getAssetString(payment)
616+ let address = toBase58String(i.caller.bytes)
617+ let checks = [mustActive(), mustHaveOnePayment(i), isEnabled(assetStr)]
618+ if ((checks == checks))
619+ then {
620+ let doUpdateFraction = invoke(this, "updateFraction", nil, nil)
621+ if ((doUpdateFraction == doUpdateFraction))
622+ then {
623+ let err1 = throw("Unable to proceed. Too few assets to mint")
624+ if ((getMinAmountDelta() > payment.amount))
625+ then err1
626+ else {
627+ let contract = getAssetContract(assetStr)
628+ let $t01553915643 = {
629+ let @ = invoke(contract, "mint", [address], i.payments)
630+ if ($isInstanceOf(@, "(String, Int)"))
631+ then @
632+ else throw(($getType(@) + " couldn't be cast to (String, Int)"))
633+ }
634+ if (($t01553915643 == $t01553915643))
635+ then {
636+ let eastAmount = $t01553915643._2
637+ let assetVault = $t01553915643._1
638+ let eastAsset = getEastAsset()
639+ let updatedVault = updateVault(address, eastAmount, 0)
640+ let minter = getMinterAddress()
641+ let doIssueEast = invoke(minter, "issue", [eastAmount], nil)
642+ if ((doIssueEast == doIssueEast))
643+ then {
644+ let assets = getVaultAssets(address)
645+ let vaultAssetActions = if (!(containsElement(assets, assetStr)))
646+ then [StringEntry(keyVaultAssets(address), addVaultAsset(address, assetStr))]
647+ else nil
648+ ([StringEntry(keyVaultData(address), updatedVault), StringEntry(keyVaultAsset(address, assetStr), assetVault), ScriptTransfer(i.caller, eastAmount, eastAsset)] ++ vaultAssetActions)
649+ }
650+ else throw("Strict value is not equal to itself.")
651+ }
652+ else throw("Strict value is not equal to itself.")
653+ }
654+ }
655+ else throw("Strict value is not equal to itself.")
656+ }
657+ else throw("Strict value is not equal to itself.")
658+ }
659+
660+
661+
662+@Callable(i)
663+func supply () = {
664+ let payment = i.payments[0]
665+ let address = toBase58String(i.caller.bytes)
666+ let asset = getAssetString(i.payments[0])
667+ let checks = [mustActive(), mustHaveOnePayment(i), isSubvaultExists(address, asset), isEnabled(asset)]
668+ if ((checks == checks))
669+ then {
670+ let doUpdateFraction = invoke(this, "updateFraction", nil, nil)
671+ if ((doUpdateFraction == doUpdateFraction))
672+ then {
673+ let err1 = throw("Unable to proceed. Too few assets to supply")
674+ if ((getMinAmountDelta() > payment.amount))
675+ then err1
676+ else {
677+ let contract = getAssetContract(asset)
678+ let updatedVaultAsset = {
679+ let @ = invoke(contract, "supply", [address], i.payments)
680+ if ($isInstanceOf(@, "String"))
681+ then @
682+ else throw(($getType(@) + " couldn't be cast to String"))
683+ }
684+ if ((updatedVaultAsset == updatedVaultAsset))
685+ then [StringEntry(keyVaultAsset(address, asset), updatedVaultAsset)]
686+ else throw("Strict value is not equal to itself.")
687+ }
688+ }
689+ else throw("Strict value is not equal to itself.")
690+ }
691+ else throw("Strict value is not equal to itself.")
692+ }
693+
694+
695+
696+@Callable(i)
697+func reissue (_amount) = {
698+ let address = toBase58String(i.caller.bytes)
699+ let checks = [mustActive(), mustHaveNoPayment(i), isVaultExists(address)]
700+ if ((checks == checks))
701+ then {
702+ let doUpdateFraction = invoke(this, "updateFraction", nil, nil)
703+ if ((doUpdateFraction == doUpdateFraction))
704+ then {
705+ let err1 = throw("Unable to proceed. Too few east to reissue")
706+ if ((getMinAmountDelta() > _amount))
707+ then err1
708+ else {
709+ let vaultDataArr = getVaultData(address)
710+ let eastAmount = parseIntValue(vaultDataArr[IdxVaultEastAmount])
711+ let $t01743117547 = {
712+ let @ = invoke(this, "getVaultInfo", [address], nil)
713+ if ($isInstanceOf(@, "(Int, Int, Int, Int, Int)"))
714+ then @
715+ else throw(($getType(@) + " couldn't be cast to (Int, Int, Int, Int, Int)"))
716+ }
717+ if (($t01743117547 == $t01743117547))
718+ then {
719+ let fee = $t01743117547._5
720+ let lr = $t01743117547._4
721+ let br = $t01743117547._3
722+ let eastEq = $t01743117547._2
723+ let usdEq = $t01743117547._1
724+ let eastAvailable = (eastEq - eastAmount)
725+ let err2 = throw((("Unable to reissue. Only " + toString(eastAvailable)) + " EAST available."))
726+ if ((_amount > eastAvailable))
727+ then err2
728+ else {
729+ let updatedVault = updateVault(address, _amount, 0)
730+ let minter = getMinterAddress()
731+ let doIssueEast = invoke(minter, "issue", [_amount], nil)
732+ if ((doIssueEast == doIssueEast))
733+ then {
734+ let eastAsset = getEastAsset()
735+[StringEntry(keyVaultData(address), updatedVault), ScriptTransfer(i.caller, _amount, eastAsset)]
736+ }
737+ else throw("Strict value is not equal to itself.")
738+ }
739+ }
740+ else throw("Strict value is not equal to itself.")
741+ }
742+ }
743+ else throw("Strict value is not equal to itself.")
744+ }
745+ else throw("Strict value is not equal to itself.")
746+ }
747+
748+
749+
750+@Callable(i)
751+func close (_asset,_amount,_eastToBurn) = {
752+ let address = toBase58String(i.caller.bytes)
753+ let eastAsset = getEastAsset()
754+ let checks = [mustActive(), isNotNegative(_amount), isVaultExists(address), if (hasOnePayment(i))
755+ then isAsset(i.payments[0], eastAsset)
756+ else mustHaveNoPayment(i), if ((_amount > 0))
757+ then [isSubvaultExists(address, _asset)]
758+ else unit]
759+ if ((checks == checks))
760+ then {
761+ let doUpdateFraction = invoke(this, "updateFraction", nil, nil)
762+ if ((doUpdateFraction == doUpdateFraction))
763+ then {
764+ let vaultDataArr = getVaultData(address)
765+ let eastAmount = parseIntValue(vaultDataArr[IdxVaultEastAmount])
766+ let $t01864818764 = {
767+ let @ = invoke(this, "getVaultInfo", [address], nil)
768+ if ($isInstanceOf(@, "(Int, Int, Int, Int, Int)"))
769+ then @
770+ else throw(($getType(@) + " couldn't be cast to (Int, Int, Int, Int, Int)"))
771+ }
772+ if (($t01864818764 == $t01864818764))
773+ then {
774+ let fee = $t01864818764._5
775+ let lr = $t01864818764._4
776+ let br = $t01864818764._3
777+ let eastEq = $t01864818764._2
778+ let usdEq = $t01864818764._1
779+ let overcollaterized = (eastEq > eastAmount)
780+ let eastActions = if (hasOnePayment(i))
781+ then {
782+ let payment = i.payments[0]
783+ let totalEastOwed = (eastAmount + fee)
784+ let eastToPayFee = (payment.amount - _eastToBurn)
785+ let minFeeAmount = mulp(fee, divp(_eastToBurn, totalEastOwed))
786+ let err1 = throw(((("Unable to proceed. Not enough east to pay stability fee." + toString(eastToPayFee)) + " ") + toString(minFeeAmount)))
787+ if ((minFeeAmount > eastToPayFee))
788+ then err1
789+ else if ((payment.amount > (_eastToBurn + eastToPayFee)))
790+ then err1
791+ else {
792+ let err2 = throw("Unable to proceed. Payment is bigger than owed amount of east.")
793+ if ((payment.amount > totalEastOwed))
794+ then err2
795+ else {
796+ let err3 = throw("Unable to proceed. Too few east to burn")
797+ if ((getMinAmountDelta() > _eastToBurn))
798+ then err3
799+ else {
800+ let err4 = throw("Unable to proceed. Too much east to burn.")
801+ if ((_eastToBurn > eastAmount))
802+ then err4
803+ else {
804+ let updatedVault = updateVault(address, -(_eastToBurn), eastToPayFee)
805+ let treasuryAddress = getTreasuryAddress()
806+[ScriptTransfer(treasuryAddress, eastToPayFee, eastAsset), StringEntry(keyVaultData(address), updatedVault), Burn(eastAsset, _eastToBurn)]
807+ }
808+ }
809+ }
810+ }
811+ }
812+ else nil
813+ let assetActions = if ((_amount > 0))
814+ then {
815+ let contract = getAssetContract(_asset)
816+ let $t02010320250 = {
817+ let @ = invoke(contract, "close", [address, _amount], nil)
818+ if ($isInstanceOf(@, "(String, Int, Int)"))
819+ then @
820+ else throw(($getType(@) + " couldn't be cast to (String, Int, Int)"))
821+ }
822+ if (($t02010320250 == $t02010320250))
823+ then {
824+ let closedAmountInUsd = $t02010320250._3
825+ let closedEastEquivalent = $t02010320250._2
826+ let updatedVaultAsset = $t02010320250._1
827+ let err1 = throw("Unable to proceed. Too few assets to close")
828+ if ((getMinAmountDelta() > _amount))
829+ then err1
830+ else {
831+ let err2 = throw("Unable to proceed. Too much assets to close for that amount of east.")
832+ if (if (overcollaterized)
833+ then ((eastAmount - _eastToBurn) > (eastEq - closedEastEquivalent))
834+ else false)
835+ then err2
836+ else {
837+ let newUsdEq = (usdEq - closedAmountInUsd)
838+ let newEastAmount = (eastAmount - _eastToBurn)
839+ let err3 = throw("Unable to proceed. BR after close must be more than before.")
840+ let u1e2 = (toBigInt(usdEq) * toBigInt(newEastAmount))
841+ let u2e1 = (toBigInt(newUsdEq) * toBigInt(eastAmount))
842+ if (if (!(overcollaterized))
843+ then (u1e2 > u2e1)
844+ else false)
845+ then err3
846+ else [StringEntry(keyVaultAsset(address, _asset), updatedVaultAsset)]
847+ }
848+ }
849+ }
850+ else throw("Strict value is not equal to itself.")
851+ }
852+ else nil
853+ (eastActions ++ assetActions)
854+ }
855+ else throw("Strict value is not equal to itself.")
856+ }
857+ else throw("Strict value is not equal to itself.")
858+ }
859+ else throw("Strict value is not equal to itself.")
860+ }
861+
862+
863+
864+@Callable(i)
865+func liquidate (_address) = {
866+ let payment = i.payments[0]
867+ let eastAsset = getEastAsset()
868+ let checks = [mustActive(), mustHaveOnePayment(i), mustNotVaultOwner(i, _address), isAsset(payment, eastAsset), isVaultExists(_address)]
869+ if ((checks == checks))
870+ then {
871+ let doUpdateFraction = invoke(this, "updateFraction", nil, nil)
872+ if ((doUpdateFraction == doUpdateFraction))
873+ then {
874+ let vaultDataArr = getVaultData(_address)
875+ let eastAmount = parseIntValue(vaultDataArr[IdxVaultEastAmount])
876+ let maxLiquidateAmountAllowed = mulp(eastAmount, MAX_LIQUIDATION_PART)
877+ let err1 = throw("Unable to proceed. Payment amount is bigger than 50% of the vault.")
878+ if ((payment.amount > maxLiquidateAmountAllowed))
879+ then err1
880+ else {
881+ let $t02174921900 = {
882+ let @ = invoke(this, "getVaultInfo", [_address], nil)
883+ if ($isInstanceOf(@, "(Int, Int, Int, Int, Int)"))
884+ then @
885+ else throw(($getType(@) + " couldn't be cast to (Int, Int, Int, Int, Int)"))
886+ }
887+ if (($t02174921900 == $t02174921900))
888+ then {
889+ let fee = $t02174921900._5
890+ let avgLiquidationRatio = $t02174921900._4
891+ let currentBackingRatio = $t02174921900._3
892+ let eastEq = $t02174921900._2
893+ let usdEq = $t02174921900._1
894+ let err2 = throw("Unable to proceed. Vault health is normal.")
895+ if ((currentBackingRatio > avgLiquidationRatio))
896+ then err2
897+ else {
898+ let liquidationBonus = mulp(payment.amount, getLiquidationBonus())
899+ let liquidationAmountInEast = (payment.amount + liquidationBonus)
900+ let liquidationRatio = divp(liquidationAmountInEast, usdEq)
901+ let treasuryAddress = getTreasuryAddress()
902+ let liquidatorAddress = toBase58String(i.caller.bytes)
903+ func liquidateAssets (acc,next) = match next {
904+ case asset: String =>
905+ let check = isEnabled(asset)
906+ if ((check == check))
907+ then {
908+ let vault = getSubvault(_address, asset)
909+ match vault {
910+ case v: String =>
911+ let contract = getAssetContract(asset)
912+ let $t02267122831 = {
913+ let @ = invoke(contract, "liquidate", [liquidatorAddress, _address, liquidationRatio], nil)
914+ if ($isInstanceOf(@, "(String, Int)"))
915+ then @
916+ else throw(($getType(@) + " couldn't be cast to (String, Int)"))
917+ }
918+ if (($t02267122831 == $t02267122831))
919+ then {
920+ let liquidatedEastEquivalent = $t02267122831._2
921+ let updatedVaultAsset = $t02267122831._1
922+ let assetId = getAssetIdFromString(asset)
923+ let actions = [StringEntry(keyVaultAsset(_address, asset), updatedVaultAsset)]
924+ $Tuple2((acc._1 ++ actions), (acc._2 + liquidatedEastEquivalent))
925+ }
926+ else throw("Strict value is not equal to itself.")
927+ case _: Unit =>
928+ acc
929+ case _ =>
930+ throw("Match error")
931+ }
932+ }
933+ else throw("Strict value is not equal to itself.")
934+ case _: Unit =>
935+ acc
936+ case _ =>
937+ throw("Match error")
938+ }
939+
940+ let assets = getVaultAssets(_address)
941+ let $t02318723281 = {
942+ let $l = assets
943+ let $s = size($l)
944+ let $acc0 = $Tuple2(nil, 0)
945+ func $f0_1 ($a,$i) = if (($i >= $s))
946+ then $a
947+ else liquidateAssets($a, $l[$i])
948+
949+ func $f0_2 ($a,$i) = if (($i >= $s))
950+ then $a
951+ else throw("List size exceeds 10")
952+
953+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
954+ }
955+ let vaultAssetsActions = $t02318723281._1
956+ let liquidatedEastEqivalent = $t02318723281._2
957+ let updatedVault = updateVault(_address, -(payment.amount), 0)
958+ let postCheck = if (isNotTreasury(i))
959+ then {
960+ let newUsdEq = (usdEq - liquidationAmountInEast)
961+ let newEastEq = (eastEq - liquidatedEastEqivalent)
962+ let newEastAmount = (eastAmount - payment.amount)
963+ let err3 = throw("Unable to proceed. BR after liquidation must be more than before.")
964+ let u1e2 = (toBigInt(usdEq) * toBigInt(newEastAmount))
965+ let u2e1 = (toBigInt(newUsdEq) * toBigInt(eastAmount))
966+ if ((u1e2 > u2e1))
967+ then err3
968+ else {
969+ let err4 = throw("Unable to proceed. Vault health is above 100% after liquidation.")
970+ if ((newEastEq > newEastAmount))
971+ then err4
972+ else unit
973+ }
974+ }
975+ else unit
976+ if ((postCheck == postCheck))
977+ then {
978+ let vaultActions = [Burn(eastAsset, payment.amount), StringEntry(keyVaultData(_address), updatedVault)]
979+ (vaultActions ++ vaultAssetsActions)
980+ }
981+ else throw("Strict value is not equal to itself.")
982+ }
983+ }
984+ else throw("Strict value is not equal to itself.")
985+ }
986+ }
987+ else throw("Strict value is not equal to itself.")
988+ }
989+ else throw("Strict value is not equal to itself.")
990+ }
991+
992+
993+
994+@Callable(i)
995+func getVaultInfo (_address) = {
996+ let exists = isVaultExists(_address)
997+ if ((exists == exists))
998+ then {
999+ let doUpdateFraction = invoke(this, "updateFraction", nil, nil)
1000+ if ((doUpdateFraction == doUpdateFraction))
1001+ then {
1002+ let assets = getVaultAssets(_address)
1003+ func count (acc,next) = match next {
1004+ case asset: String =>
1005+ let contract = getAssetContract(asset)
1006+ let $t02449524607 = {
1007+ let @ = invoke(contract, "getSubvaultInfo", [_address], nil)
1008+ if ($isInstanceOf(@, "(Int, Int, Int)"))
1009+ then @
1010+ else throw(($getType(@) + " couldn't be cast to (Int, Int, Int)"))
1011+ }
1012+ if (($t02449524607 == $t02449524607))
1013+ then {
1014+ let threshold = $t02449524607._3
1015+ let eastEq = $t02449524607._2
1016+ let usdEq = $t02449524607._1
1017+ $Tuple3((acc._1 + usdEq), (acc._2 + eastEq), (acc._3 + threshold))
1018+ }
1019+ else throw("Strict value is not equal to itself.")
1020+ case _: Unit =>
1021+ acc
1022+ case _ =>
1023+ throw("Match error")
1024+ }
1025+
1026+ let vaultDataArr = getVaultData(_address)
1027+ let eastAmount = parseIntValue(vaultDataArr[IdxVaultEastAmount])
1028+ let lastStabilityFee = parseIntValue(vaultDataArr[IdxStabilityFee])
1029+ let lastFraction = parseIntValue(vaultDataArr[IdxLastFraction])
1030+ let $t02496825035 = {
1031+ let $l = assets
1032+ let $s = size($l)
1033+ let $acc0 = $Tuple3(0, 0, 0)
1034+ func $f0_1 ($a,$i) = if (($i >= $s))
1035+ then $a
1036+ else count($a, $l[$i])
1037+
1038+ func $f0_2 ($a,$i) = if (($i >= $s))
1039+ then $a
1040+ else throw("List size exceeds 10")
1041+
1042+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1043+ }
1044+ let usdEq = $t02496825035._1
1045+ let eastEq = $t02496825035._2
1046+ let threshold = $t02496825035._3
1047+ let avgLiquidationRatio = divp(threshold, usdEq)
1048+ let currentBackingRatio = if ((eastAmount > 0))
1049+ then divp(usdEq, eastAmount)
1050+ else INFINITY
1051+ let stabilityFee = getCurrentStabilityFee(eastAmount, lastStabilityFee, lastFraction)
1052+ $Tuple2(nil, $Tuple5(usdEq, eastEq, currentBackingRatio, avgLiquidationRatio, stabilityFee))
1053+ }
1054+ else throw("Strict value is not equal to itself.")
1055+ }
1056+ else throw("Strict value is not equal to itself.")
1057+ }
1058+
1059+
1060+@Verifier(tx)
1061+func verify () = match verifier() {
1062+ case address: String =>
1063+ valueOrElse(getBoolean(addressFromStringValue(address), keySigned(toString(this), toBase58String(tx.id))), false)
1064+ case _ =>
1065+ sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
1066+}
1067+

github/deemru/w8io/3ef1775 
65.31 ms