tx · 69unUFWTY6stpkjA9rUkqNCJHKKiKxx5ozz1ZAs4jLYv

3NBbSp7yXAeyAmM8uuoenTt3XFfCGQZsHon:  -0.02900000 Waves

2023.07.19 14:41 [2672691] smart account 3NBbSp7yXAeyAmM8uuoenTt3XFfCGQZsHon > SELF 0.00000000 Waves

{ "type": 13, "id": "69unUFWTY6stpkjA9rUkqNCJHKKiKxx5ozz1ZAs4jLYv", "fee": 2900000, "feeAssetId": null, "timestamp": 1689766985963, "version": 2, "chainId": 84, "sender": "3NBbSp7yXAeyAmM8uuoenTt3XFfCGQZsHon", "senderPublicKey": "EdMvX1KG6dSSSsAqgamTtbKQho4ZLojCVgcBU4CDSeix", "proofs": [ "4e7db83qvGN3ZQg3otJnebPwRCexmhdicjCqnwYypRWHLQxxbjXBRwa5sGgHvyfwjfi4BGzK7XzFCqttjy7yGRW3" ], "script": "base64:BgIsCAISBAoCAgESBAoCAgESBwoFCAgICAgSABIECgIICBIAEgQKAggIEgMKAQhBAAlzZXBhcmF0b3ICAl9fABJzaGFyZUFzc2V0RGVjaW1hbHMACAALd2F2ZXNTdHJpbmcCBVdBVkVTAAdzY2FsZTE4AICAkLu61q3wDQANc2NhbGUxOEJpZ0ludAkAtgIBBQdzY2FsZTE4AQd3cmFwRXJyAQNtc2cJALkJAgkAzAgCAhZscF9zdGFraW5nX3Bvb2xzLnJpZGU6CQDMCAIFA21zZwUDbmlsAgEgAQh0aHJvd0VycgEDbXNnCQACAQkBB3dyYXBFcnIBBQNtc2cBEmVycktleUlzTm90RGVmaW5lZAIHYWRkcmVzcwNrZXkJAQd3cmFwRXJyAQkAuQkCCQDMCAICCm1hbmRhdG9yeSAJAMwIAgkApQgBBQdhZGRyZXNzCQDMCAICAS4JAMwIAgUDa2V5CQDMCAICDyBpcyBub3QgZGVmaW5lZAUDbmlsAgABDGdldFN0ck9yRmFpbAIHYWRkcmVzcwNrZXkJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQdhZGRyZXNzBQNrZXkJARJlcnJLZXlJc05vdERlZmluZWQCBQdhZGRyZXNzBQNrZXkBDGdldEludE9yRmFpbAIHYWRkcmVzcwNrZXkJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQdhZGRyZXNzBQNrZXkJARJlcnJLZXlJc05vdERlZmluZWQCBQdhZGRyZXNzBQNrZXkBDHBhcnNlQXNzZXRJZAEFaW5wdXQDCQAAAgUFaW5wdXQFC3dhdmVzU3RyaW5nBQR1bml0CQDZBAEFBWlucHV0AQ9hc3NldElkVG9TdHJpbmcBBWlucHV0AwkAAAIFBWlucHV0BQR1bml0BQt3YXZlc1N0cmluZwkA2AQBCQEFdmFsdWUBBQVpbnB1dAEOZW5zdXJlUG9zaXRpdmUBAXYDCQBnAgUBdgAABQF2CQEIdGhyb3dFcnIBAhh2YWx1ZSBzaG91bGQgYmUgcG9zaXRpdmUBEmtleUZhY3RvcnlDb250cmFjdAAJALkJAgkAzAgCAgIlcwkAzAgCAg9mYWN0b3J5Q29udHJhY3QFA25pbAUJc2VwYXJhdG9yARRrZXlMcFN0YWtpbmdDb250cmFjdAAJALkJAgkAzAgCAgIlcwkAzAgCAhFscFN0YWtpbmdDb250cmFjdAUDbmlsBQlzZXBhcmF0b3IBEmtleVN0YWtpbmdDb250cmFjdAAJALkJAgkAzAgCAgIlcwkAzAgCAg9zdGFraW5nQ29udHJhY3QFA25pbAUJc2VwYXJhdG9yARNrZXlCb29zdGluZ0NvbnRyYWN0AAkAuQkCCQDMCAICAiVzCQDMCAICEGJvb3N0aW5nQ29udHJhY3QFA25pbAUJc2VwYXJhdG9yAQ9rZXlTd2FwQ29udHJhY3QACQC5CQIJAMwIAgICJXMJAMwIAgIMc3dhcENvbnRyYWN0BQNuaWwFCXNlcGFyYXRvcgEWa2V5QXNzZXRzU3RvcmVDb250cmFjdAAJALkJAgkAzAgCAgIlcwkAzAgCAhNhc3NldHNTdG9yZUNvbnRyYWN0BQNuaWwFCXNlcGFyYXRvcgEOa2V5VXNkdEFzc2V0SWQACQC5CQIJAMwIAgICJXMJAMwIAgILdXNkdEFzc2V0SWQFA25pbAUJc2VwYXJhdG9yAQxrZXlXeEFzc2V0SWQACQC5CQIJAMwIAgICJXMJAMwIAgIJd3hBc3NldElkBQNuaWwFCXNlcGFyYXRvcgELa2V5U2h1dGRvd24ACQC5CQIJAMwIAgICJXMJAMwIAgIIc2h1dGRvd24FA25pbAUJc2VwYXJhdG9yAQtrZXlNaW5EZWxheQAJALkJAgkAzAgCAgIlcwkAzAgCAghtaW5EZWxheQUDbmlsBQlzZXBhcmF0b3IBD2tleUxvY2tGcmFjdGlvbgAJALkJAgkAzAgCAgIlcwkAzAgCAgxsb2NrRnJhY3Rpb24FA25pbAUJc2VwYXJhdG9yAQ9rZXlTaGFyZUFzc2V0SWQBC2Jhc2VBc3NldElkCQC5CQIJAMwIAgIEJXMlcwkAzAgCCQEPYXNzZXRJZFRvU3RyaW5nAQULYmFzZUFzc2V0SWQJAMwIAgIMc2hhcmVBc3NldElkBQNuaWwFCXNlcGFyYXRvcgEOa2V5QmFzZUFzc2V0SWQBDHNoYXJlQXNzZXRJZAkAuQkCCQDMCAICBCVzJXMJAMwIAgkBD2Fzc2V0SWRUb1N0cmluZwEFDHNoYXJlQXNzZXRJZAkAzAgCAgtiYXNlQXNzZXRJZAUDbmlsBQlzZXBhcmF0b3IBCWtleVBlcmlvZAELYmFzZUFzc2V0SWQJALkJAgkAzAgCAgQlcyVzCQDMCAIJAQ9hc3NldElkVG9TdHJpbmcBBQtiYXNlQXNzZXRJZAkAzAgCAgZwZXJpb2QFA25pbAUJc2VwYXJhdG9yARRrZXlQZXJpb2RTdGFydEhlaWdodAILYmFzZUFzc2V0SWQGcGVyaW9kCQC5CQIJAMwIAgIGJXMlcyVkCQDMCAIJAQ9hc3NldElkVG9TdHJpbmcBBQtiYXNlQXNzZXRJZAkAzAgCAhFwZXJpb2RTdGFydEhlaWdodAkAzAgCCQCkAwEFBnBlcmlvZAUDbmlsBQlzZXBhcmF0b3IBG2tleUJhc2VBc3NldEFtb3VudFRvQ29udmVydAELYmFzZUFzc2V0SWQJALkJAgkAzAgCAgQlcyVzCQDMCAIJAQ9hc3NldElkVG9TdHJpbmcBBQtiYXNlQXNzZXRJZAkAzAgCAhhiYXNlQXNzZXRBbW91bnRUb0NvbnZlcnQFA25pbAUJc2VwYXJhdG9yARxrZXlTaGFyZUFzc2V0QW1vdW50VG9Db252ZXJ0AQtiYXNlQXNzZXRJZAkAuQkCCQDMCAICBCVzJXMJAMwIAgkBD2Fzc2V0SWRUb1N0cmluZwEFC2Jhc2VBc3NldElkCQDMCAICGXNoYXJlQXNzZXRBbW91bnRUb0NvbnZlcnQFA25pbAUJc2VwYXJhdG9yAR9rZXlVc2VyQmFzZUFzc2V0QW1vdW50VG9Db252ZXJ0AgtiYXNlQXNzZXRJZAt1c2VyQWRkcmVzcwkAuQkCCQDMCAICBiVzJXMlcwkAzAgCCQEPYXNzZXRJZFRvU3RyaW5nAQULYmFzZUFzc2V0SWQJAMwIAgkApQgBBQt1c2VyQWRkcmVzcwkAzAgCAhhiYXNlQXNzZXRBbW91bnRUb0NvbnZlcnQFA25pbAUJc2VwYXJhdG9yASVrZXlVc2VyQmFzZUFzc2V0QW1vdW50VG9Db252ZXJ0UGVyaW9kAgtiYXNlQXNzZXRJZAt1c2VyQWRkcmVzcwkAuQkCCQDMCAICCCVzJXMlcyVzCQDMCAIJAQ9hc3NldElkVG9TdHJpbmcBBQtiYXNlQXNzZXRJZAkAzAgCCQClCAEFC3VzZXJBZGRyZXNzCQDMCAICGGJhc2VBc3NldEFtb3VudFRvQ29udmVydAkAzAgCAgZwZXJpb2QFA25pbAUJc2VwYXJhdG9yASBrZXlVc2VyU2hhcmVBc3NldEFtb3VudFRvQ29udmVydAILYmFzZUFzc2V0SWQLdXNlckFkZHJlc3MJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgkBD2Fzc2V0SWRUb1N0cmluZwEFC2Jhc2VBc3NldElkCQDMCAIJAKUIAQULdXNlckFkZHJlc3MJAMwIAgIZc2hhcmVBc3NldEFtb3VudFRvQ29udmVydAUDbmlsBQlzZXBhcmF0b3IBJmtleVVzZXJTaGFyZUFzc2V0QW1vdW50VG9Db252ZXJ0UGVyaW9kAgtiYXNlQXNzZXRJZAt1c2VyQWRkcmVzcwkAuQkCCQDMCAICCCVzJXMlcyVzCQDMCAIJAQ9hc3NldElkVG9TdHJpbmcBBQtiYXNlQXNzZXRJZAkAzAgCCQClCAEFC3VzZXJBZGRyZXNzCQDMCAICGXNoYXJlQXNzZXRBbW91bnRUb0NvbnZlcnQJAMwIAgIGcGVyaW9kBQNuaWwFCXNlcGFyYXRvcgEOa2V5UHJpY2VQZXJpb2QCC2Jhc2VBc3NldElkBnBlcmlvZAkAuQkCCQDMCAICBiVzJXMlZAkAzAgCCQEPYXNzZXRJZFRvU3RyaW5nAQULYmFzZUFzc2V0SWQJAMwIAgIFcHJpY2UJAMwIAgkApAMBBQZwZXJpb2QFA25pbAUJc2VwYXJhdG9yAQ9rZXlQcmljZUhpc3RvcnkBC2Jhc2VBc3NldElkCQC5CQIJAMwIAgIKJXMlcyVzJWQlZAkAzAgCCQEPYXNzZXRJZFRvU3RyaW5nAQULYmFzZUFzc2V0SWQJAMwIAgIFcHJpY2UJAMwIAgIHaGlzdG9yeQkAzAgCCQCkAwEIBQlsYXN0QmxvY2sGaGVpZ2h0CQDMCAIJAKQDAQgFCWxhc3RCbG9jawl0aW1lc3RhbXAFA25pbAUJc2VwYXJhdG9yARFrZXlQcmljZVBlcmlvZFB1dAILYmFzZUFzc2V0SWQGcGVyaW9kCQC5CQIJAMwIAgIIJXMlcyVkJXMJAMwIAgkBD2Fzc2V0SWRUb1N0cmluZwEFC2Jhc2VBc3NldElkCQDMCAICBXByaWNlCQDMCAIJAKQDAQUGcGVyaW9kCQDMCAICA3B1dAUDbmlsBQlzZXBhcmF0b3IBEmtleVByaWNlUHV0SGlzdG9yeQELYmFzZUFzc2V0SWQJALkJAgkAzAgCAgwlcyVzJXMlcyVkJWQJAMwIAgkBD2Fzc2V0SWRUb1N0cmluZwEFC2Jhc2VBc3NldElkCQDMCAICBXByaWNlCQDMCAICB2hpc3RvcnkJAMwIAgIDcHV0CQDMCAIJAKQDAQgFCWxhc3RCbG9jawZoZWlnaHQJAMwIAgkApAMBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAUDbmlsBQlzZXBhcmF0b3IBEWtleVByaWNlUGVyaW9kR2V0AgtiYXNlQXNzZXRJZAZwZXJpb2QJALkJAgkAzAgCAgglcyVzJWQlcwkAzAgCCQEPYXNzZXRJZFRvU3RyaW5nAQULYmFzZUFzc2V0SWQJAMwIAgIFcHJpY2UJAMwIAgkApAMBBQZwZXJpb2QJAMwIAgIDZ2V0BQNuaWwFCXNlcGFyYXRvcgESa2V5UHJpY2VHZXRIaXN0b3J5AQtiYXNlQXNzZXRJZAkAuQkCCQDMCAICDCVzJXMlcyVzJWQlZAkAzAgCCQEPYXNzZXRJZFRvU3RyaW5nAQULYmFzZUFzc2V0SWQJAMwIAgIFcHJpY2UJAMwIAgIHaGlzdG9yeQkAzAgCAgNnZXQJAMwIAgkApAMBCAUJbGFzdEJsb2NrBmhlaWdodAkAzAgCCQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wBQNuaWwFCXNlcGFyYXRvcgEPa2V5SGlzdG9yeUVudHJ5BQtiYXNlQXNzZXRJZAlvcGVyYXRpb24GcGVyaW9kC3VzZXJBZGRyZXNzBHR4SWQJALkJAgkAzAgCAgglcyVzJXMlcwkAzAgCAgdoaXN0b3J5CQDMCAIJANgEAQkBBXZhbHVlAQULYmFzZUFzc2V0SWQJAMwIAgUJb3BlcmF0aW9uCQDMCAIJAKUIAQULdXNlckFkZHJlc3MJAMwIAgkA2AQBBQR0eElkCQDMCAIJAKQDAQUGaGVpZ2h0BQNuaWwFCXNlcGFyYXRvcgETa2V5TWFuYWdlclB1YmxpY0tleQACFCVzX19tYW5hZ2VyUHVibGljS2V5ARZrZXlNYW5hZ2VyVmF1bHRBZGRyZXNzAAIXJXNfX21hbmFnZXJWYXVsdEFkZHJlc3MBHGdldE1hbmFnZXJWYXVsdEFkZHJlc3NPclRoaXMABAckbWF0Y2gwCQCiCAEJARZrZXlNYW5hZ2VyVmF1bHRBZGRyZXNzAAMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAXMFByRtYXRjaDAJARFAZXh0ck5hdGl2ZSgxMDYyKQEFAXMFBHRoaXMBFm1hbmFnZXJQdWJsaWNLZXlPclVuaXQABBNtYW5hZ2VyVmF1bHRBZGRyZXNzCQEcZ2V0TWFuYWdlclZhdWx0QWRkcmVzc09yVGhpcwAEByRtYXRjaDAJAJ0IAgUTbWFuYWdlclZhdWx0QWRkcmVzcwkBE2tleU1hbmFnZXJQdWJsaWNLZXkAAwkAAQIFByRtYXRjaDACBlN0cmluZwQBcwUHJG1hdGNoMAkA2QQBBQFzAwkAAQIFByRtYXRjaDACBFVuaXQFBHVuaXQJAAIBAgtNYXRjaCBlcnJvcgAVcGVybWlzc2lvbkRlbmllZEVycm9yCQACAQIRUGVybWlzc2lvbiBkZW5pZWQBCG11c3RUaGlzAQFpAwkAAAIIBQFpBmNhbGxlcgUEdGhpcwYFFXBlcm1pc3Npb25EZW5pZWRFcnJvcgELbXVzdE1hbmFnZXIBAWkEByRtYXRjaDAJARZtYW5hZ2VyUHVibGljS2V5T3JVbml0AAMJAAECBQckbWF0Y2gwAgpCeXRlVmVjdG9yBAJwawUHJG1hdGNoMAMJAAACCAUBaQ9jYWxsZXJQdWJsaWNLZXkFAnBrBgUVcGVybWlzc2lvbkRlbmllZEVycm9yAwkAAQIFByRtYXRjaDACBFVuaXQJAQhtdXN0VGhpcwEFAWkJAAIBAgtNYXRjaCBlcnJvcgAIc2h1dGRvd24JAQt2YWx1ZU9yRWxzZQIJAKAIAQkBC2tleVNodXRkb3duAAcBDXNodXRkb3duQ2hlY2sBAWkDAwkBASEBBQhzaHV0ZG93bgYJAQttdXN0TWFuYWdlcgEFAWkGCQACAQIVb3BlcmF0aW9uIGlzIGRpc2FibGVkAA9mYWN0b3J5Q29udHJhY3QJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQxnZXRTdHJPckZhaWwCBQR0aGlzCQESa2V5RmFjdG9yeUNvbnRyYWN0AAARbHBTdGFraW5nQ29udHJhY3QJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQxnZXRTdHJPckZhaWwCBQR0aGlzCQEUa2V5THBTdGFraW5nQ29udHJhY3QAAA9zdGFraW5nQ29udHJhY3QJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQxnZXRTdHJPckZhaWwCBQR0aGlzCQESa2V5U3Rha2luZ0NvbnRyYWN0AAAQYm9vc3RpbmdDb250cmFjdAkBEUBleHRyTmF0aXZlKDEwNjIpAQkBDGdldFN0ck9yRmFpbAIFBHRoaXMJARNrZXlCb29zdGluZ0NvbnRyYWN0AAAMc3dhcENvbnRyYWN0CQERQGV4dHJOYXRpdmUoMTA2MikBCQEMZ2V0U3RyT3JGYWlsAgUEdGhpcwkBD2tleVN3YXBDb250cmFjdAAAE2Fzc2V0c1N0b3JlQ29udHJhY3QJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQxnZXRTdHJPckZhaWwCBQR0aGlzCQEWa2V5QXNzZXRzU3RvcmVDb250cmFjdAAAC3VzZHRBc3NldElkCQEMcGFyc2VBc3NldElkAQkBDGdldFN0ck9yRmFpbAIFBHRoaXMJAQ5rZXlVc2R0QXNzZXRJZAAACXd4QXNzZXRJZAkBDHBhcnNlQXNzZXRJZAEJAQxnZXRTdHJPckZhaWwCBQR0aGlzCQEMa2V5V3hBc3NldElkAAAPbWluRGVsYXlEZWZhdWx0AKALAAhtaW5EZWxheQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQELa2V5TWluRGVsYXkABQ9taW5EZWxheURlZmF1bHQAFmxvY2tGcmFjdGlvbk11bHRpcGxpZXIAgMLXLwATbG9ja0ZyYWN0aW9uRGVmYXVsdAkAawMAAQUWbG9ja0ZyYWN0aW9uTXVsdGlwbGllcgACAAxsb2NrRnJhY3Rpb24JAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBD2tleUxvY2tGcmFjdGlvbgAFE2xvY2tGcmFjdGlvbkRlZmF1bHQBC2dldFBvb2xJbmZvAQ1hbW91bnRBc3NldElkBBBhbW91bnRBc3NldElkU3RyCQEPYXNzZXRJZFRvU3RyaW5nAQUNYW1vdW50QXNzZXRJZAQPcHJpY2VBc3NldElkU3RyCQEPYXNzZXRJZFRvU3RyaW5nAQULdXNkdEFzc2V0SWQEDnBvb2xJbmZvT3B0aW9uCgABQAkA/AcEBQ9mYWN0b3J5Q29udHJhY3QCEHBvb2xJbmZvUkVBRE9OTFkJAMwIAgUQYW1vdW50QXNzZXRJZFN0cgkAzAgCBQ9wcmljZUFzc2V0SWRTdHIFA25pbAUDbmlsAwkAAQIFAUACFShBZGRyZXNzLCBCeXRlVmVjdG9yKQUBQAUEdW5pdAUOcG9vbEluZm9PcHRpb24BCWNhbGNQcmljZQIJbHBBc3NldElkDHNoYXJlQXNzZXRJZAQOc2hhcmVBc3NldEluZm8JARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkA7AcBBQxzaGFyZUFzc2V0SWQCHmZhaWxlZCB0byBnZXQgc2hhcmUgYXNzZXQgaW5mbwQSc2hhcmVBc3NldEVtaXNzaW9uCAUOc2hhcmVBc3NldEluZm8IcXVhbnRpdHkEDHN0YWtlZEFtb3VudAkBDmVuc3VyZVBvc2l0aXZlAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCgABQAkA/AcEBQ9zdGFraW5nQ29udHJhY3QCFHN0YWtlZEJ5VXNlclJFQURPTkxZCQDMCAIJAQ9hc3NldElkVG9TdHJpbmcBBQlscEFzc2V0SWQJAMwIAgkApQgBBQR0aGlzBQNuaWwFA25pbAMJAAECBQFAAgNJbnQFAUAFBHVuaXQJAQd3cmFwRXJyAQIjaW52YWxpZCBzdGFrZWRCeVVzZXJSRUFET05MWSByZXN1bHQEBXByaWNlAwkAAAIFEnNoYXJlQXNzZXRFbWlzc2lvbgAABQ1zY2FsZTE4QmlnSW50CQC9AgQJALYCAQUMc3Rha2VkQW1vdW50BQ1zY2FsZTE4QmlnSW50CQC2AgEFEnNoYXJlQXNzZXRFbWlzc2lvbgUFRkxPT1IFBXByaWNlCAFpAQRlbWl0Agdhc3NldElkBmFtb3VudAQLY2hlY2tDYWxsZXIJAQhtdXN0VGhpcwEFAWkDCQAAAgULY2hlY2tDYWxsZXIFC2NoZWNrQ2FsbGVyBAxpc1JlaXNzdWFibGUGCQCUCgIJAMwIAgkBB1JlaXNzdWUDBQdhc3NldElkBQZhbW91bnQFDGlzUmVpc3N1YWJsZQUDbmlsBQZhbW91bnQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEEYnVybgIHYXNzZXRJZAZhbW91bnQEC2NoZWNrQ2FsbGVyCQEIbXVzdFRoaXMBBQFpAwkAAAIFC2NoZWNrQ2FsbGVyBQtjaGVja0NhbGxlcgkAlAoCCQDMCAIJAQRCdXJuAgUHYXNzZXRJZAUGYW1vdW50BQNuaWwFBmFtb3VudAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQZjcmVhdGUFDmJhc2VBc3NldElkU3RyD3NoYXJlQXNzZXRJZFN0cg5zaGFyZUFzc2V0TmFtZRVzaGFyZUFzc2V0RGVzY3JpcHRpb24Oc2hhcmVBc3NldExvZ28ED3NoYXJlQXNzZXRMYWJlbAIKU1RBS0lOR19MUAQLYmFzZUFzc2V0SWQJAQxwYXJzZUFzc2V0SWQBBQ5iYXNlQXNzZXRJZFN0cgQGY2hlY2tzCQDMCAIJAQttdXN0TWFuYWdlcgEFAWkJAMwIAgMJAQlpc0RlZmluZWQBCQELZ2V0UG9vbEluZm8BBQtiYXNlQXNzZXRJZAYJAQh0aHJvd0VycgECEmludmFsaWQgYmFzZSBhc3NldAUDbmlsAwkAAAIFBmNoZWNrcwUGY2hlY2tzBAtjb21tb25TdGF0ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBCWtleVBlcmlvZAEFC2Jhc2VBc3NldElkAAAFA25pbAMJAAACBQ9zaGFyZUFzc2V0SWRTdHICAAQVc2hhcmVBc3NldElzc3VlQW1vdW50AAEEFXNoYXJlQXNzZXRJc3N1ZUFjdGlvbgkAwggFBQ5zaGFyZUFzc2V0TmFtZQUVc2hhcmVBc3NldERlc2NyaXB0aW9uBRVzaGFyZUFzc2V0SXNzdWVBbW91bnQFEnNoYXJlQXNzZXREZWNpbWFscwYEFmNhbGN1bGF0ZWRTaGFyZUFzc2V0SWQJALgIAQUVc2hhcmVBc3NldElzc3VlQWN0aW9uBBRzaGFyZUFzc2V0QnVybkFjdGlvbgkBBEJ1cm4CBRZjYWxjdWxhdGVkU2hhcmVBc3NldElkBRVzaGFyZUFzc2V0SXNzdWVBbW91bnQEGWNhbGN1bGF0ZWRTaGFyZUFzc2V0SWRTdHIJANgEAQUWY2FsY3VsYXRlZFNoYXJlQXNzZXRJZAQOY3JlYXRlT3JVcGRhdGUJAPwHBAUTYXNzZXRzU3RvcmVDb250cmFjdAIOY3JlYXRlT3JVcGRhdGUJAMwIAgUZY2FsY3VsYXRlZFNoYXJlQXNzZXRJZFN0cgkAzAgCBQ5zaGFyZUFzc2V0TG9nbwkAzAgCBwUDbmlsBQNuaWwDCQAAAgUOY3JlYXRlT3JVcGRhdGUFDmNyZWF0ZU9yVXBkYXRlBAhhZGRMYWJlbAkA/AcEBRNhc3NldHNTdG9yZUNvbnRyYWN0AghhZGRMYWJlbAkAzAgCBRljYWxjdWxhdGVkU2hhcmVBc3NldElkU3RyCQDMCAIFD3NoYXJlQXNzZXRMYWJlbAUDbmlsBQNuaWwDCQAAAgUIYWRkTGFiZWwFCGFkZExhYmVsCQCUCgIJAM4IAgULY29tbW9uU3RhdGUJAMwIAgUVc2hhcmVBc3NldElzc3VlQWN0aW9uCQDMCAIFFHNoYXJlQXNzZXRCdXJuQWN0aW9uCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQ9rZXlTaGFyZUFzc2V0SWQBBQtiYXNlQXNzZXRJZAUZY2FsY3VsYXRlZFNoYXJlQXNzZXRJZFN0cgkAzAgCCQELU3RyaW5nRW50cnkCCQEOa2V5QmFzZUFzc2V0SWQBBRZjYWxjdWxhdGVkU2hhcmVBc3NldElkBQ5iYXNlQXNzZXRJZFN0cgUDbmlsBRljYWxjdWxhdGVkU2hhcmVBc3NldElkU3RyCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBAxzaGFyZUFzc2V0SWQJANkEAQUPc2hhcmVBc3NldElkU3RyBA5zaGFyZUFzc2V0SW5mbwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQDsBwEFDHNoYXJlQXNzZXRJZAkBB3dyYXBFcnIBAhZpbnZhbGlkIHNoYXJlIGFzc2V0IGlkBAtjaGVja0lzc3VlcgMJAAACCAUOc2hhcmVBc3NldEluZm8GaXNzdWVyBRFscFN0YWtpbmdDb250cmFjdAYJAQh0aHJvd0VycgECHWludmFsaWQgc2hhcmUgYXNzZXQgaWQgaXNzdWVyAwkAAAIFC2NoZWNrSXNzdWVyBQtjaGVja0lzc3VlcgkAlAoCCQDOCAIFC2NvbW1vblN0YXRlCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQ9rZXlTaGFyZUFzc2V0SWQBBQtiYXNlQXNzZXRJZAUPc2hhcmVBc3NldElkU3RyCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQ5rZXlCYXNlQXNzZXRJZAEFDHNoYXJlQXNzZXRJZAUOYmFzZUFzc2V0SWRTdHIFA25pbAUPc2hhcmVBc3NldElkU3RyCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBA3B1dAAEA3BtdAMJAAACCQCQAwEIBQFpCHBheW1lbnRzAAEJAJEDAggFAWkIcGF5bWVudHMAAAkBCHRocm93RXJyAQIdZXhhY3RseSAxIHBheW1lbnQgaXMgZXhwZWN0ZWQEC2Jhc2VBc3NldElkCAUDcG10B2Fzc2V0SWQEC3VzZXJBZGRyZXNzCAUBaQZjYWxsZXIEBmNoZWNrcwkAzAgCCQENc2h1dGRvd25DaGVjawEFAWkJAMwIAgMJAQlpc0RlZmluZWQBCQCiCAEJAQ9rZXlTaGFyZUFzc2V0SWQBBQtiYXNlQXNzZXRJZAYJAQh0aHJvd0VycgECDWludmFsaWQgYXNzZXQFA25pbAMJAAACBQZjaGVja3MFBmNoZWNrcwQNJHQwMTExMjkxMTIzMgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQELZ2V0UG9vbEluZm8BBQtiYXNlQXNzZXRJZAkBB3dyYXBFcnIBAg1pbnZhbGlkIGFzc2V0BAtwb29sQWRkcmVzcwgFDSR0MDExMTI5MTEyMzICXzEECWxwQXNzZXRJZAgFDSR0MDExMTI5MTEyMzICXzIEBnBlcmlvZAkBBXZhbHVlAQkAnwgBCQEJa2V5UGVyaW9kAQULYmFzZUFzc2V0SWQEKHVzZXJCYXNlQXNzZXRBbW91bnRUb0NvbnZlcnRQZXJpb2RPcHRpb24JAJ8IAQkBJWtleVVzZXJCYXNlQXNzZXRBbW91bnRUb0NvbnZlcnRQZXJpb2QCBQtiYXNlQXNzZXRJZAULdXNlckFkZHJlc3MEGWNsYWltU2hhcmVBc3NldEludm9jYXRpb24DCQAAAgUodXNlckJhc2VBc3NldEFtb3VudFRvQ29udmVydFBlcmlvZE9wdGlvbgUEdW5pdAUEdW5pdAQidXNlckJhc2VBc3NldEFtb3VudFRvQ29udmVydFBlcmlvZAkBBXZhbHVlAQUodXNlckJhc2VBc3NldEFtb3VudFRvQ29udmVydFBlcmlvZE9wdGlvbgMJAAACBSJ1c2VyQmFzZUFzc2V0QW1vdW50VG9Db252ZXJ0UGVyaW9kBQZwZXJpb2QFBHVuaXQJAPwHBAUEdGhpcwIPY2xhaW1TaGFyZUFzc2V0CQDMCAIJAQ9hc3NldElkVG9TdHJpbmcBBQtiYXNlQXNzZXRJZAkAzAgCCQClCAEFC3VzZXJBZGRyZXNzBQNuaWwFA25pbAMJAAACBRljbGFpbVNoYXJlQXNzZXRJbnZvY2F0aW9uBRljbGFpbVNoYXJlQXNzZXRJbnZvY2F0aW9uBBhiYXNlQXNzZXRBbW91bnRUb0NvbnZlcnQJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBG2tleUJhc2VBc3NldEFtb3VudFRvQ29udmVydAEFC2Jhc2VBc3NldElkAAAEHHVzZXJCYXNlQXNzZXRBbW91bnRUb0NvbnZlcnQJAQV2YWx1ZQEJALYJAQkAkQMCCQC1CQIJAQt2YWx1ZU9yRWxzZQIJAKIIAQkBH2tleVVzZXJCYXNlQXNzZXRBbW91bnRUb0NvbnZlcnQCBQtiYXNlQXNzZXRJZAULdXNlckFkZHJlc3MCDCVkJWQlZF9fMF9fMAUJc2VwYXJhdG9yAAEJAJQKAgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBG2tleUJhc2VBc3NldEFtb3VudFRvQ29udmVydAEFC2Jhc2VBc3NldElkCQBkAgUYYmFzZUFzc2V0QW1vdW50VG9Db252ZXJ0CAUDcG10BmFtb3VudAkAzAgCCQELU3RyaW5nRW50cnkCCQEfa2V5VXNlckJhc2VBc3NldEFtb3VudFRvQ29udmVydAIFC2Jhc2VBc3NldElkBQt1c2VyQWRkcmVzcwkAuQkCCQDMCAICBiVkJWQlZAkAzAgCCQCkAwEJAGQCBRx1c2VyQmFzZUFzc2V0QW1vdW50VG9Db252ZXJ0CAUDcG10BmFtb3VudAkAzAgCCQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wCQDMCAIJAKQDAQUGcGVyaW9kBQNuaWwFCXNlcGFyYXRvcgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBJWtleVVzZXJCYXNlQXNzZXRBbW91bnRUb0NvbnZlcnRQZXJpb2QCBQtiYXNlQXNzZXRJZAULdXNlckFkZHJlc3MFBnBlcmlvZAkAzAgCCQELU3RyaW5nRW50cnkCCQEPa2V5SGlzdG9yeUVudHJ5BQULYmFzZUFzc2V0SWQCA3B1dAUGcGVyaW9kBQt1c2VyQWRkcmVzcwgFAWkNdHJhbnNhY3Rpb25JZAkAuQkCCQDMCAICBiVkJWQlZAkAzAgCCQCkAwEIBQNwbXQGYW1vdW50CQDMCAIJAKQDAQgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAMwIAgkApAMBBRx1c2VyQmFzZUFzc2V0QW1vdW50VG9Db252ZXJ0BQNuaWwFCXNlcGFyYXRvcgUDbmlsBQR1bml0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBD2NsYWltU2hhcmVBc3NldAIOYmFzZUFzc2V0SWRTdHIOdXNlckFkZHJlc3NTdHIEBmNoZWNrcwkAzAgCCQENc2h1dGRvd25DaGVjawEFAWkFA25pbAMJAAACBQZjaGVja3MFBmNoZWNrcwQLdXNlckFkZHJlc3MDCQAAAgUOdXNlckFkZHJlc3NTdHICAAgFAWkGY2FsbGVyBAtjaGVja0NhbGxlcgkBCG11c3RUaGlzAQUBaQMJAAACBQtjaGVja0NhbGxlcgULY2hlY2tDYWxsZXIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBBQ51c2VyQWRkcmVzc1N0cgkBB3dyYXBFcnIBAhRpbnZhbGlkIHVzZXIgYWRkcmVzcwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgMJAAACBQt1c2VyQWRkcmVzcwULdXNlckFkZHJlc3MEC2Jhc2VBc3NldElkCQEMcGFyc2VBc3NldElkAQUOYmFzZUFzc2V0SWRTdHIEDHNoYXJlQXNzZXRJZAkBBXZhbHVlAQkBDHBhcnNlQXNzZXRJZAEJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEPa2V5U2hhcmVBc3NldElkAQULYmFzZUFzc2V0SWQJAQd3cmFwRXJyAQIVaW52YWxpZCBiYXNlIGFzc2V0IGlkAwkAAAIFDHNoYXJlQXNzZXRJZAUMc2hhcmVBc3NldElkBAZwZXJpb2QJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnwgBCQEJa2V5UGVyaW9kAQULYmFzZUFzc2V0SWQJAQd3cmFwRXJyAQIOaW52YWxpZCBwZXJpb2QDCQAAAgUGcGVyaW9kBQZwZXJpb2QEHHVzZXJCYXNlQXNzZXRBbW91bnRUb0NvbnZlcnQJAQV2YWx1ZQEJALYJAQkAkQMCCQC1CQIJAQt2YWx1ZU9yRWxzZQIJAKIIAQkBH2tleVVzZXJCYXNlQXNzZXRBbW91bnRUb0NvbnZlcnQCBQtiYXNlQXNzZXRJZAULdXNlckFkZHJlc3MCDCVkJWQlZF9fMF9fMAUJc2VwYXJhdG9yAAEEFGNoZWNrQW1vdW50VG9Db252ZXJ0AwkAZgIFHHVzZXJCYXNlQXNzZXRBbW91bnRUb0NvbnZlcnQAAAYJAQh0aHJvd0VycgECEG5vdGhpbmcgdG8gY2xhaW0DCQAAAgUUY2hlY2tBbW91bnRUb0NvbnZlcnQFFGNoZWNrQW1vdW50VG9Db252ZXJ0BCJ1c2VyQmFzZUFzc2V0QW1vdW50VG9Db252ZXJ0UGVyaW9kCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ8IAQkBJWtleVVzZXJCYXNlQXNzZXRBbW91bnRUb0NvbnZlcnRQZXJpb2QCBQtiYXNlQXNzZXRJZAULdXNlckFkZHJlc3MJAQd3cmFwRXJyAQIUZmFpbGVkIHRvIGdldCBwZXJpb2QEC2NoZWNrUGVyaW9kAwkAZgIFBnBlcmlvZAUidXNlckJhc2VBc3NldEFtb3VudFRvQ29udmVydFBlcmlvZAYJAQh0aHJvd0VycgECDmludmFsaWQgcGVyaW9kAwkAAAIFC2NoZWNrUGVyaW9kBQtjaGVja1BlcmlvZAQFcHJpY2UJAJ4DAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQChCAEJARFrZXlQcmljZVBlcmlvZFB1dAIFC2Jhc2VBc3NldElkBSJ1c2VyQmFzZUFzc2V0QW1vdW50VG9Db252ZXJ0UGVyaW9kCQEHd3JhcEVycgECE2ZhaWxlZCB0byBnZXQgcHJpY2UEEHNoYXJlQXNzZXRBbW91bnQJAKADAQkAvAIDCQC2AgEFHHVzZXJCYXNlQXNzZXRBbW91bnRUb0NvbnZlcnQFDXNjYWxlMThCaWdJbnQFBXByaWNlCQCUCgIJAMwIAgkBC1N0cmluZ0VudHJ5AgkBH2tleVVzZXJCYXNlQXNzZXRBbW91bnRUb0NvbnZlcnQCBQtiYXNlQXNzZXRJZAULdXNlckFkZHJlc3MJALkJAgkAzAgCAgYlZCVkJWQJAMwIAgkApAMBAAAJAMwIAgkApAMBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAzAgCCQCkAwEFBnBlcmlvZAUDbmlsBQlzZXBhcmF0b3IJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBJWtleVVzZXJCYXNlQXNzZXRBbW91bnRUb0NvbnZlcnRQZXJpb2QCBQtiYXNlQXNzZXRJZAULdXNlckFkZHJlc3MJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwULdXNlckFkZHJlc3MFEHNoYXJlQXNzZXRBbW91bnQFDHNoYXJlQXNzZXRJZAkAzAgCCQELU3RyaW5nRW50cnkCCQEPa2V5SGlzdG9yeUVudHJ5BQULYmFzZUFzc2V0SWQCD2NsYWltU2hhcmVBc3NldAUGcGVyaW9kBQt1c2VyQWRkcmVzcwgFAWkNdHJhbnNhY3Rpb25JZAkAuQkCCQDMCAICCCVkJWQlZCVkCQDMCAIJAKQDAQUQc2hhcmVBc3NldEFtb3VudAkAzAgCCQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wCQDMCAIJAKYDAQUFcHJpY2UJAMwIAgkApAMBBRx1c2VyQmFzZUFzc2V0QW1vdW50VG9Db252ZXJ0BQNuaWwFCXNlcGFyYXRvcgUDbmlsBQR1bml0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBA2dldAAEBmNoZWNrcwkAzAgCCQENc2h1dGRvd25DaGVjawEFAWkFA25pbAMJAAACBQZjaGVja3MFBmNoZWNrcwQDcG10AwkAAAIJAJADAQgFAWkIcGF5bWVudHMAAQkAkQMCCAUBaQhwYXltZW50cwAACQEIdGhyb3dFcnIBAh1leGFjdGx5IDEgcGF5bWVudCBpcyBleHBlY3RlZAQMc2hhcmVBc3NldElkCAUDcG10B2Fzc2V0SWQEC2Jhc2VBc3NldElkCQEFdmFsdWUBCQEMcGFyc2VBc3NldElkAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJAQ5rZXlCYXNlQXNzZXRJZAEFDHNoYXJlQXNzZXRJZAkBB3dyYXBFcnIBAhZpbnZhbGlkIHNoYXJlIGFzc2V0IGlkAwkAAAIFC2Jhc2VBc3NldElkBQtiYXNlQXNzZXRJZAQLdXNlckFkZHJlc3MIBQFpBmNhbGxlcgQNJHQwMTU2NDIxNTgzMQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQELZ2V0UG9vbEluZm8BBQtiYXNlQXNzZXRJZAkBB3dyYXBFcnIBAg1pbnZhbGlkIGFzc2V0BAtwb29sQWRkcmVzcwgFDSR0MDE1NjQyMTU4MzECXzEECWxwQXNzZXRJZAgFDSR0MDE1NjQyMTU4MzECXzIEBnBlcmlvZAkBBXZhbHVlAQkAnwgBCQEJa2V5UGVyaW9kAQULYmFzZUFzc2V0SWQEKXVzZXJTaGFyZUFzc2V0QW1vdW50VG9Db252ZXJ0UGVyaW9kT3B0aW9uCQCfCAEJASZrZXlVc2VyU2hhcmVBc3NldEFtb3VudFRvQ29udmVydFBlcmlvZAIFC2Jhc2VBc3NldElkBQt1c2VyQWRkcmVzcwQYY2xhaW1CYXNlQXNzZXRJbnZvY2F0aW9uAwkAAAIFKXVzZXJTaGFyZUFzc2V0QW1vdW50VG9Db252ZXJ0UGVyaW9kT3B0aW9uBQR1bml0BQR1bml0BCN1c2VyU2hhcmVBc3NldEFtb3VudFRvQ29udmVydFBlcmlvZAkBBXZhbHVlAQUpdXNlclNoYXJlQXNzZXRBbW91bnRUb0NvbnZlcnRQZXJpb2RPcHRpb24DCQAAAgUjdXNlclNoYXJlQXNzZXRBbW91bnRUb0NvbnZlcnRQZXJpb2QFBnBlcmlvZAUEdW5pdAkA/AcEBQR0aGlzAg5jbGFpbUJhc2VBc3NldAkAzAgCCQEPYXNzZXRJZFRvU3RyaW5nAQULYmFzZUFzc2V0SWQJAMwIAgkApQgBBQt1c2VyQWRkcmVzcwUDbmlsBQNuaWwDCQAAAgUYY2xhaW1CYXNlQXNzZXRJbnZvY2F0aW9uBRhjbGFpbUJhc2VBc3NldEludm9jYXRpb24EGXNoYXJlQXNzZXRBbW91bnRUb0NvbnZlcnQJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBHGtleVNoYXJlQXNzZXRBbW91bnRUb0NvbnZlcnQBBQtiYXNlQXNzZXRJZAAABB11c2VyU2hhcmVBc3NldEFtb3VudFRvQ29udmVydAkBBXZhbHVlAQkAtgkBCQCRAwIJALUJAgkBC3ZhbHVlT3JFbHNlAgkAoggBCQEga2V5VXNlclNoYXJlQXNzZXRBbW91bnRUb0NvbnZlcnQCBQtiYXNlQXNzZXRJZAULdXNlckFkZHJlc3MCDCVkJWQlZF9fMF9fMAUJc2VwYXJhdG9yAAEJAJQKAgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBHGtleVNoYXJlQXNzZXRBbW91bnRUb0NvbnZlcnQBBQtiYXNlQXNzZXRJZAkAZAIFGXNoYXJlQXNzZXRBbW91bnRUb0NvbnZlcnQIBQNwbXQGYW1vdW50CQDMCAIJAQtTdHJpbmdFbnRyeQIJASBrZXlVc2VyU2hhcmVBc3NldEFtb3VudFRvQ29udmVydAIFC2Jhc2VBc3NldElkBQt1c2VyQWRkcmVzcwkAuQkCCQDMCAICBiVkJWQlZAkAzAgCCQCkAwEJAGQCBR11c2VyU2hhcmVBc3NldEFtb3VudFRvQ29udmVydAgFA3BtdAZhbW91bnQJAMwIAgkApAMBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAzAgCCQCkAwEFBnBlcmlvZAUDbmlsBQlzZXBhcmF0b3IJAMwIAgkBDEludGVnZXJFbnRyeQIJASZrZXlVc2VyU2hhcmVBc3NldEFtb3VudFRvQ29udmVydFBlcmlvZAIFC2Jhc2VBc3NldElkBQt1c2VyQWRkcmVzcwUGcGVyaW9kCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQ9rZXlIaXN0b3J5RW50cnkFBQtiYXNlQXNzZXRJZAIDZ2V0BQZwZXJpb2QFC3VzZXJBZGRyZXNzCAUBaQ10cmFuc2FjdGlvbklkCQC5CQIJAMwIAgIGJWQlZCVkCQDMCAIJAKQDAQgFA3BtdAZhbW91bnQJAMwIAgkApAMBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAzAgCCQCkAwEFHXVzZXJTaGFyZUFzc2V0QW1vdW50VG9Db252ZXJ0BQNuaWwFCXNlcGFyYXRvcgUDbmlsBQR1bml0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDmNsYWltQmFzZUFzc2V0Ag5iYXNlQXNzZXRJZFN0cg51c2VyQWRkcmVzc1N0cgQGY2hlY2tzCQDMCAIJAQ1zaHV0ZG93bkNoZWNrAQUBaQUDbmlsAwkAAAIFBmNoZWNrcwUGY2hlY2tzBAt1c2VyQWRkcmVzcwMJAAACBQ51c2VyQWRkcmVzc1N0cgIACAUBaQZjYWxsZXIEC2NoZWNrQ2FsbGVyCQEIbXVzdFRoaXMBBQFpAwkAAAIFC2NoZWNrQ2FsbGVyBQtjaGVja0NhbGxlcgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEFDnVzZXJBZGRyZXNzU3RyCQEHd3JhcEVycgECFGludmFsaWQgdXNlciBhZGRyZXNzCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAwkAAAIFC3VzZXJBZGRyZXNzBQt1c2VyQWRkcmVzcwQLYmFzZUFzc2V0SWQJAQxwYXJzZUFzc2V0SWQBBQ5iYXNlQXNzZXRJZFN0cgQMc2hhcmVBc3NldElkCQEFdmFsdWUBCQEMcGFyc2VBc3NldElkAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJAQ9rZXlTaGFyZUFzc2V0SWQBBQtiYXNlQXNzZXRJZAkBB3dyYXBFcnIBAhVpbnZhbGlkIGJhc2UgYXNzZXQgaWQDCQAAAgUMc2hhcmVBc3NldElkBQxzaGFyZUFzc2V0SWQEBnBlcmlvZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCfCAEJAQlrZXlQZXJpb2QBBQtiYXNlQXNzZXRJZAkBB3dyYXBFcnIBAg5pbnZhbGlkIHBlcmlvZAMJAAACBQZwZXJpb2QFBnBlcmlvZAQddXNlclNoYXJlQXNzZXRBbW91bnRUb0NvbnZlcnQJAQV2YWx1ZQEJALYJAQkAkQMCCQC1CQIJAQt2YWx1ZU9yRWxzZQIJAKIIAQkBIGtleVVzZXJTaGFyZUFzc2V0QW1vdW50VG9Db252ZXJ0AgULYmFzZUFzc2V0SWQFC3VzZXJBZGRyZXNzAgwlZCVkJWRfXzBfXzAFCXNlcGFyYXRvcgABBCN1c2VyU2hhcmVBc3NldEFtb3VudFRvQ29udmVydFBlcmlvZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCfCAEJASZrZXlVc2VyU2hhcmVBc3NldEFtb3VudFRvQ29udmVydFBlcmlvZAIFC2Jhc2VBc3NldElkBQt1c2VyQWRkcmVzcwkBB3dyYXBFcnIBAhRmYWlsZWQgdG8gZ2V0IHBlcmlvZAQLY2hlY2tQZXJpb2QDCQBmAgUGcGVyaW9kBSN1c2VyU2hhcmVBc3NldEFtb3VudFRvQ29udmVydFBlcmlvZAYJAQh0aHJvd0VycgECDmludmFsaWQgcGVyaW9kAwkAAAIFC2NoZWNrUGVyaW9kBQtjaGVja1BlcmlvZAQFcHJpY2UJAJ4DAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQChCAEJARFrZXlQcmljZVBlcmlvZEdldAIFC2Jhc2VBc3NldElkBSN1c2VyU2hhcmVBc3NldEFtb3VudFRvQ29udmVydFBlcmlvZAkBB3dyYXBFcnIBAhNmYWlsZWQgdG8gZ2V0IHByaWNlBA9iYXNlQXNzZXRBbW91bnQJAKADAQkAvAIDCQC2AgEFHXVzZXJTaGFyZUFzc2V0QW1vdW50VG9Db252ZXJ0BQVwcmljZQUNc2NhbGUxOEJpZ0ludAkAlAoCCQDMCAIJAQtTdHJpbmdFbnRyeQIJASBrZXlVc2VyU2hhcmVBc3NldEFtb3VudFRvQ29udmVydAIFC2Jhc2VBc3NldElkBQt1c2VyQWRkcmVzcwkAuQkCCQDMCAICBiVkJWQlZAkAzAgCCQCkAwEAAAkAzAgCCQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wCQDMCAIJAKQDAQUGcGVyaW9kBQNuaWwFCXNlcGFyYXRvcgkAzAgCCQELRGVsZXRlRW50cnkBCQEma2V5VXNlclNoYXJlQXNzZXRBbW91bnRUb0NvbnZlcnRQZXJpb2QCBQtiYXNlQXNzZXRJZAULdXNlckFkZHJlc3MJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwULdXNlckFkZHJlc3MFD2Jhc2VBc3NldEFtb3VudAULYmFzZUFzc2V0SWQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBD2tleUhpc3RvcnlFbnRyeQUFC2Jhc2VBc3NldElkAg5jbGFpbUJhc2VBc3NldAUGcGVyaW9kBQt1c2VyQWRkcmVzcwgFAWkNdHJhbnNhY3Rpb25JZAkAuQkCCQDMCAICCCVkJWQlZCVkCQDMCAIJAKQDAQUPYmFzZUFzc2V0QW1vdW50CQDMCAIJAKQDAQgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAMwIAgkApgMBBQVwcmljZQkAzAgCCQCkAwEFI3VzZXJTaGFyZUFzc2V0QW1vdW50VG9Db252ZXJ0UGVyaW9kBQNuaWwFCXNlcGFyYXRvcgUDbmlsBQR1bml0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCGZpbmFsaXplAQ5iYXNlQXNzZXRJZFN0cgQGY2hlY2tzCQDMCAIJAQ1zaHV0ZG93bkNoZWNrAQUBaQUDbmlsAwkAAAIFBmNoZWNrcwUGY2hlY2tzBAtiYXNlQXNzZXRJZAkBDHBhcnNlQXNzZXRJZAEFDmJhc2VBc3NldElkU3RyBAxzaGFyZUFzc2V0SWQJAQV2YWx1ZQEJAQxwYXJzZUFzc2V0SWQBCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBD2tleVNoYXJlQXNzZXRJZAEFC2Jhc2VBc3NldElkCQEHd3JhcEVycgECFWludmFsaWQgYmFzZSBhc3NldCBpZAMJAAACBQxzaGFyZUFzc2V0SWQFDHNoYXJlQXNzZXRJZAQOc2hhcmVBc3NldEluZm8JARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkA7AcBBQxzaGFyZUFzc2V0SWQJAQd3cmFwRXJyAQIWaW52YWxpZCBzaGFyZSBhc3NldCBpZAQGcGVyaW9kCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ8IAQkBCWtleVBlcmlvZAEFC2Jhc2VBc3NldElkCQEHd3JhcEVycgECDmludmFsaWQgcGVyaW9kAwkAAAIFBnBlcmlvZAUGcGVyaW9kBBdwZXJpb2RTdGFydEhlaWdodE9wdGlvbgkAnwgBCQEUa2V5UGVyaW9kU3RhcnRIZWlnaHQCBQtiYXNlQXNzZXRJZAUGcGVyaW9kBApjaGVja0RlbGF5AwkAAAIFF3BlcmlvZFN0YXJ0SGVpZ2h0T3B0aW9uBQR1bml0BQR1bml0BAVkZWxheQkAZQIFBmhlaWdodAkBBXZhbHVlAQUXcGVyaW9kU3RhcnRIZWlnaHRPcHRpb24EDGJsb2Nrc1RvV2FpdAkAlgMBCQDMCAIAAAkAzAgCCQBlAgUIbWluRGVsYXkFBWRlbGF5BQNuaWwDCQAAAgUMYmxvY2tzVG9XYWl0AAAFBHVuaXQJAQh0aHJvd0VycgEJALkJAgkAzAgCAiFmaW5hbGl6YXRpb24gd2lsbCBiZSBwb3NzaWJsZSBpbiAJAMwIAgkApAMBBQxibG9ja3NUb1dhaXQJAMwIAgIHIGJsb2NrcwUDbmlsAgADCQAAAgUKY2hlY2tEZWxheQUKY2hlY2tEZWxheQQNJHQwMjEyNzIyMTQ1MwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQELZ2V0UG9vbEluZm8BBQtiYXNlQXNzZXRJZAkBB3dyYXBFcnIBAg1pbnZhbGlkIGFzc2V0BAtwb29sQWRkcmVzcwgFDSR0MDIxMjcyMjE0NTMCXzEECWxwQXNzZXRJZAgFDSR0MDIxMjcyMjE0NTMCXzIEDXN0YWtpbmdSZXdhcmQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgoAAUAJAPwHBAUPc3Rha2luZ0NvbnRyYWN0AhFjbGFpbVd4RG9Ob3RUaHJvdwkAzAgCCQEPYXNzZXRJZFRvU3RyaW5nAQUJbHBBc3NldElkBQNuaWwFA25pbAMJAAECBQFAAgNJbnQFAUAFBHVuaXQJAQd3cmFwRXJyAQIWaW52YWxpZCBjbGFpbVd4IHJlc3VsdAMJAAACBQ1zdGFraW5nUmV3YXJkBQ1zdGFraW5nUmV3YXJkBBhiYXNlQXNzZXRBbW91bnRUb0NvbnZlcnQJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBG2tleUJhc2VBc3NldEFtb3VudFRvQ29udmVydAEFC2Jhc2VBc3NldElkAAAEGXNoYXJlQXNzZXRBbW91bnRUb0NvbnZlcnQJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBHGtleVNoYXJlQXNzZXRBbW91bnRUb0NvbnZlcnQBBQtiYXNlQXNzZXRJZAAABBtjaGVja0ZpbmFsaXphdGlvbklzUmVxdWlyZWQEFmlzRmluYWxpemF0aW9uUmVxdWlyZWQDAwkAZgIFDXN0YWtpbmdSZXdhcmQAAAYJAGYCBRhiYXNlQXNzZXRBbW91bnRUb0NvbnZlcnQAAAYJAGYCBRlzaGFyZUFzc2V0QW1vdW50VG9Db252ZXJ0AAADBRZpc0ZpbmFsaXphdGlvblJlcXVpcmVkBgkBCHRocm93RXJyAQITbm90aGluZyB0byBmaW5hbGl6ZQMJAAACBRtjaGVja0ZpbmFsaXphdGlvbklzUmVxdWlyZWQFG2NoZWNrRmluYWxpemF0aW9uSXNSZXF1aXJlZAQQdXNlU3Rha2luZ1Jld2FyZAMJAGYCBQ1zdGFraW5nUmV3YXJkAAAECGxvY2tQYXJ0CQBrAwUNc3Rha2luZ1Jld2FyZAUMbG9ja0ZyYWN0aW9uBRZsb2NrRnJhY3Rpb25NdWx0aXBsaWVyBAtjb252ZXJ0UGFydAkAZQIFDXN0YWtpbmdSZXdhcmQFCGxvY2tQYXJ0BAFyCQD8BwQFEGJvb3N0aW5nQ29udHJhY3QCF3VzZXJNYXhEdXJhdGlvblJFQURPTkxZCQDMCAIJAKUIAQUEdGhpcwUDbmlsBQNuaWwEBGxvY2sDCQBmAgUIbG9ja1BhcnQAAAQHJG1hdGNoMAUBcgMDAwkAAQIIBQckbWF0Y2gwAl8xAgZTdHJpbmcJAAECCAUHJG1hdGNoMAJfMgIDSW50BwkAAQIFByRtYXRjaDACDShTdHJpbmcsIEludCkHBAhmdW5jdGlvbggFByRtYXRjaDACXzEECGR1cmF0aW9uCAUHJG1hdGNoMAJfMgMJAGYCBQhsb2NrUGFydAAACQD8BwQFEGJvb3N0aW5nQ29udHJhY3QFCGZ1bmN0aW9uCQDMCAIFCGR1cmF0aW9uBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFCXd4QXNzZXRJZAUIbG9ja1BhcnQFA25pbAUEdW5pdAkBCHRocm93RXJyAQITaW52YWxpZCBsb2NrIHBhcmFtcwUEdW5pdAMJAAACBQRsb2NrBQRsb2NrBA9jb252ZXJ0ZWRBbW91bnQDCQBmAgULY29udmVydFBhcnQAAAQJaW5Bc3NldElkBQl3eEFzc2V0SWQEEG1pbmltdW1Ub1JlY2VpdmUAAAQNb3V0QXNzZXRJZFN0cgkBD2Fzc2V0SWRUb1N0cmluZwEFC3VzZHRBc3NldElkBA10YXJnZXRBZGRyZXNzCQClCAEFBHRoaXMJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgoAAUAJAPwHBAUMc3dhcENvbnRyYWN0AgRzd2FwCQDMCAIFEG1pbmltdW1Ub1JlY2VpdmUJAMwIAgUNb3V0QXNzZXRJZFN0cgkAzAgCBQ10YXJnZXRBZGRyZXNzBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFCWluQXNzZXRJZAULY29udmVydFBhcnQFA25pbAMJAAECBQFAAgNJbnQFAUAFBHVuaXQJAQd3cmFwRXJyAQITaW52YWxpZCBzd2FwIHJlc3VsdAAAAwkAAAIFD2NvbnZlcnRlZEFtb3VudAUPY29udmVydGVkQW1vdW50BA1scEFzc2V0QW1vdW50AwkAZgIFD2NvbnZlcnRlZEFtb3VudAAABAxtaW5PdXRBbW91bnQAAAQJYXV0b1N0YWtlBgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCgABQAkA/AcEBQtwb29sQWRkcmVzcwILcHV0T25lVGtuVjIJAMwIAgUMbWluT3V0QW1vdW50CQDMCAIFCWF1dG9TdGFrZQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQt1c2R0QXNzZXRJZAUPY29udmVydGVkQW1vdW50BQNuaWwDCQABAgUBQAIDSW50BQFABQR1bml0CQEHd3JhcEVycgECGmludmFsaWQgcHV0T25lVGtuVjIgcmVzdWx0AAADCQAAAgUNbHBBc3NldEFtb3VudAUNbHBBc3NldEFtb3VudAUNbHBBc3NldEFtb3VudAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUEdW5pdAMJAAACBRB1c2VTdGFraW5nUmV3YXJkBRB1c2VTdGFraW5nUmV3YXJkBApnZXRBY3Rpb25zAwkAZgIFGXNoYXJlQXNzZXRBbW91bnRUb0NvbnZlcnQAAAQFcHJpY2UJAQljYWxjUHJpY2UCBQlscEFzc2V0SWQFDHNoYXJlQXNzZXRJZAMJAAACBQVwcmljZQUFcHJpY2UEDXVuc3Rha2VBbW91bnQJAKADAQkAvQIECQC2AgEFGXNoYXJlQXNzZXRBbW91bnRUb0NvbnZlcnQFBXByaWNlBQ1zY2FsZTE4QmlnSW50BQVGTE9PUgQPYmFzZUFzc2V0QW1vdW50BApvdXRBc3NldElkBQtiYXNlQXNzZXRJZAQMbWluT3V0QW1vdW50AAAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgoAAUAJAPwHBAULcG9vbEFkZHJlc3MCFXVuc3Rha2VBbmRHZXRPbmVUa25WMgkAzAgCBQ11bnN0YWtlQW1vdW50CQDMCAIJAQ9hc3NldElkVG9TdHJpbmcBBQpvdXRBc3NldElkCQDMCAIFDG1pbk91dEFtb3VudAUDbmlsBQNuaWwDCQABAgUBQAIDSW50BQFABQR1bml0CQEHd3JhcEVycgECJGludmFsaWQgdW5zdGFrZUFuZEdldE9uZVRrblYyIHJlc3VsdAMJAAACBQ9iYXNlQXNzZXRBbW91bnQFD2Jhc2VBc3NldEFtb3VudAQOc2hhcmVBc3NldEJ1cm4DCQAAAggFDnNoYXJlQXNzZXRJbmZvBmlzc3VlcgUEdGhpcwkA/AcEBQR0aGlzAgRidXJuCQDMCAIFDHNoYXJlQXNzZXRJZAkAzAgCBRlzaGFyZUFzc2V0QW1vdW50VG9Db252ZXJ0BQNuaWwFA25pbAkBCHRocm93RXJyAQIaaW52YWxpZCBzaGFyZSBhc3NldCBpc3N1ZXIDCQAAAgUOc2hhcmVBc3NldEJ1cm4FDnNoYXJlQXNzZXRCdXJuBAhwcmljZUdldAkAvQIECQC2AgEFD2Jhc2VBc3NldEFtb3VudAUNc2NhbGUxOEJpZ0ludAkAtgIBBRlzaGFyZUFzc2V0QW1vdW50VG9Db252ZXJ0BQVGTE9PUgQVcHJpY2VHZXRVcGRhdGVBY3Rpb25zCQDMCAIJAQtCaW5hcnlFbnRyeQIJARFrZXlQcmljZVBlcmlvZEdldAIFC2Jhc2VBc3NldElkBQZwZXJpb2QJAJ0DAQUIcHJpY2VHZXQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBEmtleVByaWNlR2V0SGlzdG9yeQEFC2Jhc2VBc3NldElkCQCmAwEFCHByaWNlR2V0BQNuaWwFFXByaWNlR2V0VXBkYXRlQWN0aW9ucwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFCmdldEFjdGlvbnMFCmdldEFjdGlvbnMECnB1dEFjdGlvbnMDCQBmAgUYYmFzZUFzc2V0QW1vdW50VG9Db252ZXJ0AAAEDWxwQXNzZXRBbW91bnQEDG1pbk91dEFtb3VudAAABAlhdXRvU3Rha2UGCQETdmFsdWVPckVycm9yTWVzc2FnZQIKAAFACQD8BwQFC3Bvb2xBZGRyZXNzAgtwdXRPbmVUa25WMgkAzAgCBQxtaW5PdXRBbW91bnQJAMwIAgUJYXV0b1N0YWtlBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFC2Jhc2VBc3NldElkBRhiYXNlQXNzZXRBbW91bnRUb0NvbnZlcnQFA25pbAMJAAECBQFAAgNJbnQFAUAFBHVuaXQJAQd3cmFwRXJyAQIaaW52YWxpZCBwdXRPbmVUa25WMiByZXN1bHQDCQAAAgUNbHBBc3NldEFtb3VudAUNbHBBc3NldEFtb3VudAQFcHJpY2UJAQljYWxjUHJpY2UCBQlscEFzc2V0SWQFDHNoYXJlQXNzZXRJZAMJAAACBQVwcmljZQUFcHJpY2UECmNoZWNrUHJpY2UDCQECIT0CCQEFdmFsdWUBCQCgAwEFBXByaWNlAAAGCQACAQINcHJpY2UgaXMgWkVSTwMJAAACBQpjaGVja1ByaWNlBQpjaGVja1ByaWNlBBBzaGFyZUFzc2V0QW1vdW50CQCgAwEJAL0CBAkAtgIBBQ1scEFzc2V0QW1vdW50BQ1zY2FsZTE4QmlnSW50BQVwcmljZQUFRkxPT1IEFWNoZWNrU2hhcmVBc3NldEFtb3VudAMJAQIhPQIJAQV2YWx1ZQEJAKADAQUFcHJpY2UAAAYJAAIBAhhzaGFyZUFzc2V0QW1vdW50IGlzIFpFUk8DCQAAAgUVY2hlY2tTaGFyZUFzc2V0QW1vdW50BRVjaGVja1NoYXJlQXNzZXRBbW91bnQEEXNoYXJlQXNzZXRSZWlzc3VlAwkAAAIIBQ5zaGFyZUFzc2V0SW5mbwZpc3N1ZXIFBHRoaXMJAPwHBAUEdGhpcwIEZW1pdAkAzAgCBQxzaGFyZUFzc2V0SWQJAMwIAgUQc2hhcmVBc3NldEFtb3VudAUDbmlsBQNuaWwJAQh0aHJvd0VycgECGmludmFsaWQgc2hhcmUgYXNzZXQgaXNzdWVyAwkAAAIFEXNoYXJlQXNzZXRSZWlzc3VlBRFzaGFyZUFzc2V0UmVpc3N1ZQQIcHJpY2VQdXQJALwCAwkAtgIBBRhiYXNlQXNzZXRBbW91bnRUb0NvbnZlcnQFDXNjYWxlMThCaWdJbnQJALYCAQUQc2hhcmVBc3NldEFtb3VudAQVcHJpY2VQdXRVcGRhdGVBY3Rpb25zCQDMCAIJAQtCaW5hcnlFbnRyeQIJARFrZXlQcmljZVBlcmlvZFB1dAIFC2Jhc2VBc3NldElkBQZwZXJpb2QJAJ0DAQUIcHJpY2VQdXQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBEmtleVByaWNlUHV0SGlzdG9yeQEFC2Jhc2VBc3NldElkCQCmAwEFCHByaWNlUHV0BQNuaWwFFXByaWNlUHV0VXBkYXRlQWN0aW9ucwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFCnB1dEFjdGlvbnMFCnB1dEFjdGlvbnMECW5ld1BlcmlvZAkAZAIFBnBlcmlvZAABBAlsYXN0UHJpY2UJAQljYWxjUHJpY2UCBQlscEFzc2V0SWQFDHNoYXJlQXNzZXRJZAQHYWN0aW9ucwkAzggCCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIJAQlrZXlQZXJpb2QBBQtiYXNlQXNzZXRJZAUJbmV3UGVyaW9kCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEUa2V5UGVyaW9kU3RhcnRIZWlnaHQCBQtiYXNlQXNzZXRJZAUJbmV3UGVyaW9kBQZoZWlnaHQJAMwIAgkBDEludGVnZXJFbnRyeQIJARxrZXlTaGFyZUFzc2V0QW1vdW50VG9Db252ZXJ0AQULYmFzZUFzc2V0SWQAAAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBG2tleUJhc2VBc3NldEFtb3VudFRvQ29udmVydAEFC2Jhc2VBc3NldElkAAAJAMwIAgkBC0JpbmFyeUVudHJ5AgkBDmtleVByaWNlUGVyaW9kAgULYmFzZUFzc2V0SWQFBnBlcmlvZAkAnQMBBQlsYXN0UHJpY2UJAMwIAgkBC1N0cmluZ0VudHJ5AgkBD2tleVByaWNlSGlzdG9yeQEFC2Jhc2VBc3NldElkCQCmAwEFCWxhc3RQcmljZQUDbmlsBQpwdXRBY3Rpb25zBQpnZXRBY3Rpb25zCQCUCgIFB2FjdGlvbnMJAJ0DAQUJbGFzdFByaWNlCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQJ0eAEGdmVyaWZ5AAQPdGFyZ2V0UHVibGljS2V5BAckbWF0Y2gwCQEWbWFuYWdlclB1YmxpY0tleU9yVW5pdAADCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQCcGsFByRtYXRjaDAFAnBrAwkAAQIFByRtYXRjaDACBFVuaXQIBQJ0eA9zZW5kZXJQdWJsaWNLZXkJAAIBAgtNYXRjaCBlcnJvcgkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAUPdGFyZ2V0UHVibGljS2V5gLhUNg==", "height": 2672691, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 44QSQ6Sg6oZgzHsCfE4fUs5TizBPBu9auyhe7JdzDdgZ Next: Dwnd5VT42aUjjFR4iRzo8WW5HP4KdF18s8Tb2NbeWpH8 Diff:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let SEP = "__"
4+let separator = "__"
55
6-let feeScale = toBigInt(100000000)
6+let shareAssetDecimals = 8
77
8-func getStringOrFail (key) = valueOrErrorMessage(getString(this, key), ("No data for this.key=" + key))
8+let wavesString = "WAVES"
9+
10+let scale18 = 1000000000000000000
11+
12+let scale18BigInt = toBigInt(scale18)
13+
14+func wrapErr (msg) = makeString(["lp_staking_pools.ride:", msg], " ")
915
1016
11-let poolDisabled = throw("Pool disabled")
17+func throwErr (msg) = throw(wrapErr(msg))
1218
13-let poolNotExist = throw("Pool is not exist")
1419
15-let slippageTooBig = throw("Slippage is too big")
20+func errKeyIsNotDefined (address,key) = wrapErr(makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
21+
22+
23+func getStrOrFail (address,key) = valueOrErrorMessage(getString(address, key), errKeyIsNotDefined(address, key))
24+
25+
26+func getIntOrFail (address,key) = valueOrErrorMessage(getInteger(address, key), errKeyIsNotDefined(address, key))
27+
28+
29+func parseAssetId (input) = if ((input == wavesString))
30+ then unit
31+ else fromBase58String(input)
32+
33+
34+func assetIdToString (input) = if ((input == unit))
35+ then wavesString
36+ else toBase58String(value(input))
37+
38+
39+func ensurePositive (v) = if ((v >= 0))
40+ then v
41+ else throwErr("value should be positive")
42+
43+
44+func keyFactoryContract () = makeString(["%s", "factoryContract"], separator)
45+
46+
47+func keyLpStakingContract () = makeString(["%s", "lpStakingContract"], separator)
48+
49+
50+func keyStakingContract () = makeString(["%s", "stakingContract"], separator)
51+
52+
53+func keyBoostingContract () = makeString(["%s", "boostingContract"], separator)
54+
55+
56+func keySwapContract () = makeString(["%s", "swapContract"], separator)
57+
58+
59+func keyAssetsStoreContract () = makeString(["%s", "assetsStoreContract"], separator)
60+
61+
62+func keyUsdtAssetId () = makeString(["%s", "usdtAssetId"], separator)
63+
64+
65+func keyWxAssetId () = makeString(["%s", "wxAssetId"], separator)
66+
67+
68+func keyShutdown () = makeString(["%s", "shutdown"], separator)
69+
70+
71+func keyMinDelay () = makeString(["%s", "minDelay"], separator)
72+
73+
74+func keyLockFraction () = makeString(["%s", "lockFraction"], separator)
75+
76+
77+func keyShareAssetId (baseAssetId) = makeString(["%s%s", assetIdToString(baseAssetId), "shareAssetId"], separator)
78+
79+
80+func keyBaseAssetId (shareAssetId) = makeString(["%s%s", assetIdToString(shareAssetId), "baseAssetId"], separator)
81+
82+
83+func keyPeriod (baseAssetId) = makeString(["%s%s", assetIdToString(baseAssetId), "period"], separator)
84+
85+
86+func keyPeriodStartHeight (baseAssetId,period) = makeString(["%s%s%d", assetIdToString(baseAssetId), "periodStartHeight", toString(period)], separator)
87+
88+
89+func keyBaseAssetAmountToConvert (baseAssetId) = makeString(["%s%s", assetIdToString(baseAssetId), "baseAssetAmountToConvert"], separator)
90+
91+
92+func keyShareAssetAmountToConvert (baseAssetId) = makeString(["%s%s", assetIdToString(baseAssetId), "shareAssetAmountToConvert"], separator)
93+
94+
95+func keyUserBaseAssetAmountToConvert (baseAssetId,userAddress) = makeString(["%s%s%s", assetIdToString(baseAssetId), toString(userAddress), "baseAssetAmountToConvert"], separator)
96+
97+
98+func keyUserBaseAssetAmountToConvertPeriod (baseAssetId,userAddress) = makeString(["%s%s%s%s", assetIdToString(baseAssetId), toString(userAddress), "baseAssetAmountToConvert", "period"], separator)
99+
100+
101+func keyUserShareAssetAmountToConvert (baseAssetId,userAddress) = makeString(["%s%s%s", assetIdToString(baseAssetId), toString(userAddress), "shareAssetAmountToConvert"], separator)
102+
103+
104+func keyUserShareAssetAmountToConvertPeriod (baseAssetId,userAddress) = makeString(["%s%s%s%s", assetIdToString(baseAssetId), toString(userAddress), "shareAssetAmountToConvert", "period"], separator)
105+
106+
107+func keyPricePeriod (baseAssetId,period) = makeString(["%s%s%d", assetIdToString(baseAssetId), "price", toString(period)], separator)
108+
109+
110+func keyPriceHistory (baseAssetId) = makeString(["%s%s%s%d%d", assetIdToString(baseAssetId), "price", "history", toString(lastBlock.height), toString(lastBlock.timestamp)], separator)
111+
112+
113+func keyPricePeriodPut (baseAssetId,period) = makeString(["%s%s%d%s", assetIdToString(baseAssetId), "price", toString(period), "put"], separator)
114+
115+
116+func keyPricePutHistory (baseAssetId) = makeString(["%s%s%s%s%d%d", assetIdToString(baseAssetId), "price", "history", "put", toString(lastBlock.height), toString(lastBlock.timestamp)], separator)
117+
118+
119+func keyPricePeriodGet (baseAssetId,period) = makeString(["%s%s%d%s", assetIdToString(baseAssetId), "price", toString(period), "get"], separator)
120+
121+
122+func keyPriceGetHistory (baseAssetId) = makeString(["%s%s%s%s%d%d", assetIdToString(baseAssetId), "price", "history", "get", toString(lastBlock.height), toString(lastBlock.timestamp)], separator)
123+
124+
125+func keyHistoryEntry (baseAssetId,operation,period,userAddress,txId) = makeString(["%s%s%s%s", "history", toBase58String(value(baseAssetId)), operation, toString(userAddress), toBase58String(txId), toString(height)], separator)
126+
16127
17128 func keyManagerPublicKey () = "%s__managerPublicKey"
18129
19130
20-func keyPendingManagerPublicKey () = "%s__pendingManagerPublicKey"
131+func keyManagerVaultAddress () = "%s__managerVaultAddress"
21132
22133
23-func fc () = "%s__factoryContract"
24-
25-
26-let factoryContract = addressFromStringValue(getStringOrFail(fc()))
27-
28-func protocolFee () = makeString(["%s", "protocolFee"], SEP)
29-
30-
31-func poolFee () = makeString(["%s", "poolFee"], SEP)
32-
33-
34-func getStringOrFailFromAddress (address,key) = valueOrErrorMessage(getString(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
35-
36-
37-let keyFeeCollectorAddress = "%s__feeCollectorAddress"
38-
39-let feeCollectorAddress = addressFromStringValue(getStringOrFailFromAddress(factoryContract, keyFeeCollectorAddress))
40-
41-func asInt (val) = match val {
42- case valInt: Int =>
43- valInt
134+func getManagerVaultAddressOrThis () = match getString(keyManagerVaultAddress()) {
135+ case s: String =>
136+ addressFromStringValue(s)
44137 case _ =>
45- throw("fail to cast into Int")
138+ this
46139 }
47140
48141
49-func dataMappingPoolAssets (internalAmountAssetStr,internalPriceAssetStr) = makeString(["%d%d", toString(internalAmountAssetStr), toString(internalPriceAssetStr)], SEP)
142+func managerPublicKeyOrUnit () = {
143+ let managerVaultAddress = getManagerVaultAddressOrThis()
144+ match getString(managerVaultAddress, keyManagerPublicKey()) {
145+ case s: String =>
146+ fromBase58String(s)
147+ case _: Unit =>
148+ unit
149+ case _ =>
150+ throw("Match error")
151+ }
152+ }
50153
51154
52-func managerPublicKeyOrUnit () = match getString(keyManagerPublicKey()) {
53- case s: String =>
54- fromBase58String(s)
155+let permissionDeniedError = throw("Permission denied")
156+
157+func mustThis (i) = if ((i.caller == this))
158+ then true
159+ else permissionDeniedError
160+
161+
162+func mustManager (i) = match managerPublicKeyOrUnit() {
163+ case pk: ByteVector =>
164+ if ((i.callerPublicKey == pk))
165+ then true
166+ else permissionDeniedError
55167 case _: Unit =>
56- unit
168+ mustThis(i)
57169 case _ =>
58170 throw("Match error")
59171 }
60172
61173
62-func pendingManagerPublicKeyOrUnit () = match getString(keyPendingManagerPublicKey()) {
63- case s: String =>
64- fromBase58String(s)
65- case _: Unit =>
66- unit
67- case _ =>
68- throw("Match error")
69-}
174+let shutdown = valueOrElse(getBoolean(keyShutdown()), false)
175+
176+func shutdownCheck (i) = if (if (!(shutdown))
177+ then true
178+ else mustManager(i))
179+ then true
180+ else throw("operation is disabled")
70181
71182
72-func isManager (i) = match managerPublicKeyOrUnit() {
73- case pk: ByteVector =>
74- (i.callerPublicKey == pk)
75- case _: Unit =>
76- (i.caller == this)
77- case _ =>
78- throw("Match error")
79-}
183+let factoryContract = addressFromStringValue(getStrOrFail(this, keyFactoryContract()))
80184
185+let lpStakingContract = addressFromStringValue(getStrOrFail(this, keyLpStakingContract()))
81186
82-func mustManager (i) = if (isManager(i))
83- then true
84- else throw("permission denied")
187+let stakingContract = addressFromStringValue(getStrOrFail(this, keyStakingContract()))
85188
189+let boostingContract = addressFromStringValue(getStrOrFail(this, keyBoostingContract()))
86190
87-func getAccBalance (assetId) = if ((assetId == "WAVES"))
88- then wavesBalance(this).available
89- else assetBalance(this, fromBase58String(assetId))
191+let swapContract = addressFromStringValue(getStrOrFail(this, keySwapContract()))
90192
193+let assetsStoreContract = addressFromStringValue(getStrOrFail(this, keyAssetsStoreContract()))
91194
92-func getPoolAddressAndCheckPoolStatus (assetIn,assetOut) = {
93- let lpNonReverse = {
94- let @ = invoke(factoryContract, "getLpAssetFromPoolAssetsREADONLY", [assetIn, assetOut], nil)
95- if ($isInstanceOf(@, "String"))
195+let usdtAssetId = parseAssetId(getStrOrFail(this, keyUsdtAssetId()))
196+
197+let wxAssetId = parseAssetId(getStrOrFail(this, keyWxAssetId()))
198+
199+let minDelayDefault = 1440
200+
201+let minDelay = valueOrElse(getInteger(this, keyMinDelay()), minDelayDefault)
202+
203+let lockFractionMultiplier = 100000000
204+
205+let lockFractionDefault = fraction(1, lockFractionMultiplier, 2)
206+
207+let lockFraction = valueOrElse(getInteger(this, keyLockFraction()), lockFractionDefault)
208+
209+func getPoolInfo (amountAssetId) = {
210+ let amountAssetIdStr = assetIdToString(amountAssetId)
211+ let priceAssetIdStr = assetIdToString(usdtAssetId)
212+ let poolInfoOption = {
213+ let @ = invoke(factoryContract, "poolInfoREADONLY", [amountAssetIdStr, priceAssetIdStr], nil)
214+ if ($isInstanceOf(@, "(Address, ByteVector)"))
96215 then @
97216 else unit
98217 }
99- let lpReverse = {
100- let @ = invoke(factoryContract, "getLpAssetFromPoolAssetsREADONLY", [assetOut, assetIn], nil)
101- if ($isInstanceOf(@, "String"))
218+ poolInfoOption
219+ }
220+
221+
222+func calcPrice (lpAssetId,shareAssetId) = {
223+ let shareAssetInfo = valueOrErrorMessage(assetInfo(shareAssetId), "failed to get share asset info")
224+ let shareAssetEmission = shareAssetInfo.quantity
225+ let stakedAmount = ensurePositive(valueOrErrorMessage({
226+ let @ = invoke(stakingContract, "stakedByUserREADONLY", [assetIdToString(lpAssetId), toString(this)], nil)
227+ if ($isInstanceOf(@, "Int"))
102228 then @
103229 else unit
104- }
105- let $t025332992 = if ((lpNonReverse != unit))
106- then {
107- let pool = {
108- let @ = invoke(factoryContract, "getPoolAddressFromLpAssetREADONLY", [value(lpNonReverse)], nil)
109- if ($isInstanceOf(@, "String"))
110- then @
111- else throw(($getType(@) + " couldn't be cast to String"))
112- }
113- $Tuple2(false, pool)
114- }
115- else if ((lpReverse != unit))
116- then {
117- let pool = {
118- let @ = invoke(factoryContract, "getPoolAddressFromLpAssetREADONLY", [value(lpReverse)], nil)
119- if ($isInstanceOf(@, "String"))
120- then @
121- else throw(($getType(@) + " couldn't be cast to String"))
122- }
123- $Tuple2(true, pool)
124- }
125- else poolNotExist
126- let isReverse = $t025332992._1
127- let pool = $t025332992._2
128- let poolStatus = {
129- let @ = invoke(factoryContract, "getPoolStatusREADONLY", [pool], nil)
130- if ($isInstanceOf(@, "Int"))
131- then @
132- else throw(($getType(@) + " couldn't be cast to Int"))
133- }
134- let check = if ((poolStatus == 1))
135- then true
136- else poolDisabled
137- if ((check == check))
138- then {
139- let poolAdr = addressFromStringValue(valueOrElse(pool, ""))
140- $Tuple2(poolAdr, isReverse)
141- }
142- else throw("Strict value is not equal to itself.")
230+ }, wrapErr("invalid stakedByUserREADONLY result")))
231+ let price = if ((shareAssetEmission == 0))
232+ then scale18BigInt
233+ else fraction(toBigInt(stakedAmount), scale18BigInt, toBigInt(shareAssetEmission), FLOOR)
234+ price
143235 }
144236
145237
146238 @Callable(i)
147-func swapCalculateREADONLY (amountIn,assetIn,assetOut) = {
148- let prFee = value(getInteger(protocolFee()))
149- let feeProtocolAmountCalc = fraction(toBigInt(amountIn), toBigInt(prFee), feeScale)
150- let plFee = value(getInteger(poolFee()))
151- let feePoolAmountCalc = fraction(toBigInt(amountIn), toBigInt(plFee), feeScale)
152- let feeProtocolAmount = if ((toInt(feeProtocolAmountCalc) == 0))
153- then toBigInt(1)
154- else feeProtocolAmountCalc
155- let feePoolAmount = if ((toInt(feePoolAmountCalc) == 0))
156- then toBigInt(1)
157- else feePoolAmountCalc
158- let cleanAmountIn = ((toBigInt(amountIn) - feeProtocolAmount) - feePoolAmount)
159- let $t039804058 = getPoolAddressAndCheckPoolStatus(assetIn, assetOut)
160- let poolAdr = $t039804058._1
161- let isReverse = $t039804058._2
162- let res = {
163- let @ = invoke(poolAdr, "calculateAmountOutForSwapREADONLY", [toInt(cleanAmountIn), isReverse, toInt(feePoolAmount)], nil)
164- if ($isInstanceOf(@, "Int"))
165- then @
166- else throw(($getType(@) + " couldn't be cast to Int"))
167- }
168- $Tuple2(nil, res)
169- }
170-
171-
172-
173-@Callable(i)
174-func swap (amountOutMin,assetOutRaw,addressTo) = {
175- let assetOut = if ((assetOutRaw == ""))
176- then "WAVES"
177- else assetOutRaw
178- let pmt = value(i.payments[0])
179- let assetIn = if ((pmt.assetId == unit))
180- then "WAVES"
181- else toBase58String(value(pmt.assetId))
182- let amountIn = value(pmt.amount)
183- let prFee = value(getInteger(protocolFee()))
184- let feeProtocolAmountCalc = fraction(toBigInt(amountIn), toBigInt(prFee), feeScale)
185- let plFee = value(getInteger(poolFee()))
186- let feePoolAmountCalc = fraction(toBigInt(amountIn), toBigInt(plFee), feeScale)
187- let feeProtocolAmount = if ((toInt(feeProtocolAmountCalc) == 0))
188- then toBigInt(1)
189- else feeProtocolAmountCalc
190- let feePoolAmount = if ((toInt(feePoolAmountCalc) == 0))
191- then toBigInt(1)
192- else feePoolAmountCalc
193- let cleanAmountIn = ((toBigInt(amountIn) - feeProtocolAmount) - feePoolAmount)
194- let checks = [if ((size(i.payments) == 1))
195- then true
196- else throw("exactly 1 payment are expected")]
197- if ((checks == checks))
239+func emit (assetId,amount) = {
240+ let checkCaller = mustThis(i)
241+ if ((checkCaller == checkCaller))
198242 then {
199- let $t052605338 = getPoolAddressAndCheckPoolStatus(assetIn, assetOut)
200- let poolAdr = $t052605338._1
201- let isReverse = $t052605338._2
202- let assetInAttachedPayment = if ((assetIn == "WAVES"))
203- then unit
204- else fromBase58String(assetIn)
205- let totalGetRaw = {
206- let @ = invoke(poolAdr, "calculateAmountOutForSwapAndSendTokens", [toInt(cleanAmountIn), isReverse, amountOutMin, addressTo, toInt(feePoolAmount)], [AttachedPayment(assetInAttachedPayment, toInt(cleanAmountIn))])
207- if ($isInstanceOf(@, "Int"))
208- then @
209- else throw(($getType(@) + " couldn't be cast to Int"))
210- }
211- $Tuple2([ScriptTransfer(feeCollectorAddress, toInt(feeProtocolAmount), assetInAttachedPayment), ScriptTransfer(poolAdr, toInt(feePoolAmount), assetInAttachedPayment)], totalGetRaw)
243+ let isReissuable = true
244+ $Tuple2([Reissue(assetId, amount, isReissuable)], amount)
212245 }
213246 else throw("Strict value is not equal to itself.")
214247 }
216249
217250
218251 @Callable(i)
219-func setManager (pendingManagerPublicKey) = {
220- let checkCaller = mustManager(i)
252+func burn (assetId,amount) = {
253+ let checkCaller = mustThis(i)
221254 if ((checkCaller == checkCaller))
255+ then $Tuple2([Burn(assetId, amount)], amount)
256+ else throw("Strict value is not equal to itself.")
257+ }
258+
259+
260+
261+@Callable(i)
262+func create (baseAssetIdStr,shareAssetIdStr,shareAssetName,shareAssetDescription,shareAssetLogo) = {
263+ let shareAssetLabel = "STAKING_LP"
264+ let baseAssetId = parseAssetId(baseAssetIdStr)
265+ let checks = [mustManager(i), if (isDefined(getPoolInfo(baseAssetId)))
266+ then true
267+ else throwErr("invalid base asset")]
268+ if ((checks == checks))
222269 then {
223- let checkManagerPublicKey = fromBase58String(pendingManagerPublicKey)
224- if ((checkManagerPublicKey == checkManagerPublicKey))
225- then [StringEntry(keyPendingManagerPublicKey(), pendingManagerPublicKey)]
270+ let commonState = [IntegerEntry(keyPeriod(baseAssetId), 0)]
271+ if ((shareAssetIdStr == ""))
272+ then {
273+ let shareAssetIssueAmount = 1
274+ let shareAssetIssueAction = Issue(shareAssetName, shareAssetDescription, shareAssetIssueAmount, shareAssetDecimals, true)
275+ let calculatedShareAssetId = calculateAssetId(shareAssetIssueAction)
276+ let shareAssetBurnAction = Burn(calculatedShareAssetId, shareAssetIssueAmount)
277+ let calculatedShareAssetIdStr = toBase58String(calculatedShareAssetId)
278+ let createOrUpdate = invoke(assetsStoreContract, "createOrUpdate", [calculatedShareAssetIdStr, shareAssetLogo, false], nil)
279+ if ((createOrUpdate == createOrUpdate))
280+ then {
281+ let addLabel = invoke(assetsStoreContract, "addLabel", [calculatedShareAssetIdStr, shareAssetLabel], nil)
282+ if ((addLabel == addLabel))
283+ then $Tuple2((commonState ++ [shareAssetIssueAction, shareAssetBurnAction, StringEntry(keyShareAssetId(baseAssetId), calculatedShareAssetIdStr), StringEntry(keyBaseAssetId(calculatedShareAssetId), baseAssetIdStr)]), calculatedShareAssetIdStr)
284+ else throw("Strict value is not equal to itself.")
285+ }
286+ else throw("Strict value is not equal to itself.")
287+ }
288+ else {
289+ let shareAssetId = fromBase58String(shareAssetIdStr)
290+ let shareAssetInfo = valueOrErrorMessage(assetInfo(shareAssetId), wrapErr("invalid share asset id"))
291+ let checkIssuer = if ((shareAssetInfo.issuer == lpStakingContract))
292+ then true
293+ else throwErr("invalid share asset id issuer")
294+ if ((checkIssuer == checkIssuer))
295+ then $Tuple2((commonState ++ [StringEntry(keyShareAssetId(baseAssetId), shareAssetIdStr), StringEntry(keyBaseAssetId(shareAssetId), baseAssetIdStr)]), shareAssetIdStr)
296+ else throw("Strict value is not equal to itself.")
297+ }
298+ }
299+ else throw("Strict value is not equal to itself.")
300+ }
301+
302+
303+
304+@Callable(i)
305+func put () = {
306+ let pmt = if ((size(i.payments) == 1))
307+ then i.payments[0]
308+ else throwErr("exactly 1 payment is expected")
309+ let baseAssetId = pmt.assetId
310+ let userAddress = i.caller
311+ let checks = [shutdownCheck(i), if (isDefined(getString(keyShareAssetId(baseAssetId))))
312+ then true
313+ else throwErr("invalid asset")]
314+ if ((checks == checks))
315+ then {
316+ let $t01112911232 = valueOrErrorMessage(getPoolInfo(baseAssetId), wrapErr("invalid asset"))
317+ let poolAddress = $t01112911232._1
318+ let lpAssetId = $t01112911232._2
319+ let period = value(getInteger(keyPeriod(baseAssetId)))
320+ let userBaseAssetAmountToConvertPeriodOption = getInteger(keyUserBaseAssetAmountToConvertPeriod(baseAssetId, userAddress))
321+ let claimShareAssetInvocation = if ((userBaseAssetAmountToConvertPeriodOption == unit))
322+ then unit
323+ else {
324+ let userBaseAssetAmountToConvertPeriod = value(userBaseAssetAmountToConvertPeriodOption)
325+ if ((userBaseAssetAmountToConvertPeriod == period))
326+ then unit
327+ else invoke(this, "claimShareAsset", [assetIdToString(baseAssetId), toString(userAddress)], nil)
328+ }
329+ if ((claimShareAssetInvocation == claimShareAssetInvocation))
330+ then {
331+ let baseAssetAmountToConvert = valueOrElse(getInteger(keyBaseAssetAmountToConvert(baseAssetId)), 0)
332+ let userBaseAssetAmountToConvert = value(parseInt(split(valueOrElse(getString(keyUserBaseAssetAmountToConvert(baseAssetId, userAddress)), "%d%d%d__0__0"), separator)[1]))
333+ $Tuple2([IntegerEntry(keyBaseAssetAmountToConvert(baseAssetId), (baseAssetAmountToConvert + pmt.amount)), StringEntry(keyUserBaseAssetAmountToConvert(baseAssetId, userAddress), makeString(["%d%d%d", toString((userBaseAssetAmountToConvert + pmt.amount)), toString(lastBlock.timestamp), toString(period)], separator)), IntegerEntry(keyUserBaseAssetAmountToConvertPeriod(baseAssetId, userAddress), period), StringEntry(keyHistoryEntry(baseAssetId, "put", period, userAddress, i.transactionId), makeString(["%d%d%d", toString(pmt.amount), toString(lastBlock.timestamp), toString(userBaseAssetAmountToConvert)], separator))], unit)
334+ }
226335 else throw("Strict value is not equal to itself.")
227336 }
228337 else throw("Strict value is not equal to itself.")
231340
232341
233342 @Callable(i)
234-func confirmManager () = {
235- let pm = pendingManagerPublicKeyOrUnit()
236- let hasPM = if (isDefined(pm))
237- then true
238- else throw("no pending manager")
239- if ((hasPM == hasPM))
343+func claimShareAsset (baseAssetIdStr,userAddressStr) = {
344+ let checks = [shutdownCheck(i)]
345+ if ((checks == checks))
240346 then {
241- let checkPM = if ((i.callerPublicKey == value(pm)))
242- then true
243- else throw("you are not pending manager")
244- if ((checkPM == checkPM))
245- then [StringEntry(keyManagerPublicKey(), toBase58String(value(pm))), DeleteEntry(keyPendingManagerPublicKey())]
347+ let userAddress = if ((userAddressStr == ""))
348+ then i.caller
349+ else {
350+ let checkCaller = mustThis(i)
351+ if ((checkCaller == checkCaller))
352+ then valueOrErrorMessage(addressFromString(userAddressStr), wrapErr("invalid user address"))
353+ else throw("Strict value is not equal to itself.")
354+ }
355+ if ((userAddress == userAddress))
356+ then {
357+ let baseAssetId = parseAssetId(baseAssetIdStr)
358+ let shareAssetId = value(parseAssetId(valueOrErrorMessage(getString(keyShareAssetId(baseAssetId)), wrapErr("invalid base asset id"))))
359+ if ((shareAssetId == shareAssetId))
360+ then {
361+ let period = valueOrErrorMessage(getInteger(keyPeriod(baseAssetId)), wrapErr("invalid period"))
362+ if ((period == period))
363+ then {
364+ let userBaseAssetAmountToConvert = value(parseInt(split(valueOrElse(getString(keyUserBaseAssetAmountToConvert(baseAssetId, userAddress)), "%d%d%d__0__0"), separator)[1]))
365+ let checkAmountToConvert = if ((userBaseAssetAmountToConvert > 0))
366+ then true
367+ else throwErr("nothing to claim")
368+ if ((checkAmountToConvert == checkAmountToConvert))
369+ then {
370+ let userBaseAssetAmountToConvertPeriod = valueOrErrorMessage(getInteger(keyUserBaseAssetAmountToConvertPeriod(baseAssetId, userAddress)), wrapErr("failed to get period"))
371+ let checkPeriod = if ((period > userBaseAssetAmountToConvertPeriod))
372+ then true
373+ else throwErr("invalid period")
374+ if ((checkPeriod == checkPeriod))
375+ then {
376+ let price = toBigInt(valueOrErrorMessage(getBinary(keyPricePeriodPut(baseAssetId, userBaseAssetAmountToConvertPeriod)), wrapErr("failed to get price")))
377+ let shareAssetAmount = toInt(fraction(toBigInt(userBaseAssetAmountToConvert), scale18BigInt, price))
378+ $Tuple2([StringEntry(keyUserBaseAssetAmountToConvert(baseAssetId, userAddress), makeString(["%d%d%d", toString(0), toString(lastBlock.timestamp), toString(period)], separator)), DeleteEntry(keyUserBaseAssetAmountToConvertPeriod(baseAssetId, userAddress)), ScriptTransfer(userAddress, shareAssetAmount, shareAssetId), StringEntry(keyHistoryEntry(baseAssetId, "claimShareAsset", period, userAddress, i.transactionId), makeString(["%d%d%d%d", toString(shareAssetAmount), toString(lastBlock.timestamp), toString(price), toString(userBaseAssetAmountToConvert)], separator))], unit)
379+ }
380+ else throw("Strict value is not equal to itself.")
381+ }
382+ else throw("Strict value is not equal to itself.")
383+ }
384+ else throw("Strict value is not equal to itself.")
385+ }
386+ else throw("Strict value is not equal to itself.")
387+ }
388+ else throw("Strict value is not equal to itself.")
389+ }
390+ else throw("Strict value is not equal to itself.")
391+ }
392+
393+
394+
395+@Callable(i)
396+func get () = {
397+ let checks = [shutdownCheck(i)]
398+ if ((checks == checks))
399+ then {
400+ let pmt = if ((size(i.payments) == 1))
401+ then i.payments[0]
402+ else throwErr("exactly 1 payment is expected")
403+ let shareAssetId = pmt.assetId
404+ let baseAssetId = value(parseAssetId(valueOrErrorMessage(getString(keyBaseAssetId(shareAssetId)), wrapErr("invalid share asset id"))))
405+ if ((baseAssetId == baseAssetId))
406+ then {
407+ let userAddress = i.caller
408+ let $t01564215831 = valueOrErrorMessage(getPoolInfo(baseAssetId), wrapErr("invalid asset"))
409+ let poolAddress = $t01564215831._1
410+ let lpAssetId = $t01564215831._2
411+ let period = value(getInteger(keyPeriod(baseAssetId)))
412+ let userShareAssetAmountToConvertPeriodOption = getInteger(keyUserShareAssetAmountToConvertPeriod(baseAssetId, userAddress))
413+ let claimBaseAssetInvocation = if ((userShareAssetAmountToConvertPeriodOption == unit))
414+ then unit
415+ else {
416+ let userShareAssetAmountToConvertPeriod = value(userShareAssetAmountToConvertPeriodOption)
417+ if ((userShareAssetAmountToConvertPeriod == period))
418+ then unit
419+ else invoke(this, "claimBaseAsset", [assetIdToString(baseAssetId), toString(userAddress)], nil)
420+ }
421+ if ((claimBaseAssetInvocation == claimBaseAssetInvocation))
422+ then {
423+ let shareAssetAmountToConvert = valueOrElse(getInteger(keyShareAssetAmountToConvert(baseAssetId)), 0)
424+ let userShareAssetAmountToConvert = value(parseInt(split(valueOrElse(getString(keyUserShareAssetAmountToConvert(baseAssetId, userAddress)), "%d%d%d__0__0"), separator)[1]))
425+ $Tuple2([IntegerEntry(keyShareAssetAmountToConvert(baseAssetId), (shareAssetAmountToConvert + pmt.amount)), StringEntry(keyUserShareAssetAmountToConvert(baseAssetId, userAddress), makeString(["%d%d%d", toString((userShareAssetAmountToConvert + pmt.amount)), toString(lastBlock.timestamp), toString(period)], separator)), IntegerEntry(keyUserShareAssetAmountToConvertPeriod(baseAssetId, userAddress), period), StringEntry(keyHistoryEntry(baseAssetId, "get", period, userAddress, i.transactionId), makeString(["%d%d%d", toString(pmt.amount), toString(lastBlock.timestamp), toString(userShareAssetAmountToConvert)], separator))], unit)
426+ }
427+ else throw("Strict value is not equal to itself.")
428+ }
429+ else throw("Strict value is not equal to itself.")
430+ }
431+ else throw("Strict value is not equal to itself.")
432+ }
433+
434+
435+
436+@Callable(i)
437+func claimBaseAsset (baseAssetIdStr,userAddressStr) = {
438+ let checks = [shutdownCheck(i)]
439+ if ((checks == checks))
440+ then {
441+ let userAddress = if ((userAddressStr == ""))
442+ then i.caller
443+ else {
444+ let checkCaller = mustThis(i)
445+ if ((checkCaller == checkCaller))
446+ then valueOrErrorMessage(addressFromString(userAddressStr), wrapErr("invalid user address"))
447+ else throw("Strict value is not equal to itself.")
448+ }
449+ if ((userAddress == userAddress))
450+ then {
451+ let baseAssetId = parseAssetId(baseAssetIdStr)
452+ let shareAssetId = value(parseAssetId(valueOrErrorMessage(getString(keyShareAssetId(baseAssetId)), wrapErr("invalid base asset id"))))
453+ if ((shareAssetId == shareAssetId))
454+ then {
455+ let period = valueOrErrorMessage(getInteger(keyPeriod(baseAssetId)), wrapErr("invalid period"))
456+ if ((period == period))
457+ then {
458+ let userShareAssetAmountToConvert = value(parseInt(split(valueOrElse(getString(keyUserShareAssetAmountToConvert(baseAssetId, userAddress)), "%d%d%d__0__0"), separator)[1]))
459+ let userShareAssetAmountToConvertPeriod = valueOrErrorMessage(getInteger(keyUserShareAssetAmountToConvertPeriod(baseAssetId, userAddress)), wrapErr("failed to get period"))
460+ let checkPeriod = if ((period > userShareAssetAmountToConvertPeriod))
461+ then true
462+ else throwErr("invalid period")
463+ if ((checkPeriod == checkPeriod))
464+ then {
465+ let price = toBigInt(valueOrErrorMessage(getBinary(keyPricePeriodGet(baseAssetId, userShareAssetAmountToConvertPeriod)), wrapErr("failed to get price")))
466+ let baseAssetAmount = toInt(fraction(toBigInt(userShareAssetAmountToConvert), price, scale18BigInt))
467+ $Tuple2([StringEntry(keyUserShareAssetAmountToConvert(baseAssetId, userAddress), makeString(["%d%d%d", toString(0), toString(lastBlock.timestamp), toString(period)], separator)), DeleteEntry(keyUserShareAssetAmountToConvertPeriod(baseAssetId, userAddress)), ScriptTransfer(userAddress, baseAssetAmount, baseAssetId), StringEntry(keyHistoryEntry(baseAssetId, "claimBaseAsset", period, userAddress, i.transactionId), makeString(["%d%d%d%d", toString(baseAssetAmount), toString(lastBlock.timestamp), toString(price), toString(userShareAssetAmountToConvertPeriod)], separator))], unit)
468+ }
469+ else throw("Strict value is not equal to itself.")
470+ }
471+ else throw("Strict value is not equal to itself.")
472+ }
473+ else throw("Strict value is not equal to itself.")
474+ }
475+ else throw("Strict value is not equal to itself.")
476+ }
477+ else throw("Strict value is not equal to itself.")
478+ }
479+
480+
481+
482+@Callable(i)
483+func finalize (baseAssetIdStr) = {
484+ let checks = [shutdownCheck(i)]
485+ if ((checks == checks))
486+ then {
487+ let baseAssetId = parseAssetId(baseAssetIdStr)
488+ let shareAssetId = value(parseAssetId(valueOrErrorMessage(getString(keyShareAssetId(baseAssetId)), wrapErr("invalid base asset id"))))
489+ if ((shareAssetId == shareAssetId))
490+ then {
491+ let shareAssetInfo = valueOrErrorMessage(assetInfo(shareAssetId), wrapErr("invalid share asset id"))
492+ let period = valueOrErrorMessage(getInteger(keyPeriod(baseAssetId)), wrapErr("invalid period"))
493+ if ((period == period))
494+ then {
495+ let periodStartHeightOption = getInteger(keyPeriodStartHeight(baseAssetId, period))
496+ let checkDelay = if ((periodStartHeightOption == unit))
497+ then unit
498+ else {
499+ let delay = (height - value(periodStartHeightOption))
500+ let blocksToWait = max([0, (minDelay - delay)])
501+ if ((blocksToWait == 0))
502+ then unit
503+ else throwErr(makeString(["finalization will be possible in ", toString(blocksToWait), " blocks"], ""))
504+ }
505+ if ((checkDelay == checkDelay))
506+ then {
507+ let $t02127221453 = valueOrErrorMessage(getPoolInfo(baseAssetId), wrapErr("invalid asset"))
508+ let poolAddress = $t02127221453._1
509+ let lpAssetId = $t02127221453._2
510+ let stakingReward = valueOrErrorMessage({
511+ let @ = invoke(stakingContract, "claimWxDoNotThrow", [assetIdToString(lpAssetId)], nil)
512+ if ($isInstanceOf(@, "Int"))
513+ then @
514+ else unit
515+ }, wrapErr("invalid claimWx result"))
516+ if ((stakingReward == stakingReward))
517+ then {
518+ let baseAssetAmountToConvert = valueOrElse(getInteger(keyBaseAssetAmountToConvert(baseAssetId)), 0)
519+ let shareAssetAmountToConvert = valueOrElse(getInteger(keyShareAssetAmountToConvert(baseAssetId)), 0)
520+ let checkFinalizationIsRequired = {
521+ let isFinalizationRequired = if (if ((stakingReward > 0))
522+ then true
523+ else (baseAssetAmountToConvert > 0))
524+ then true
525+ else (shareAssetAmountToConvert > 0)
526+ if (isFinalizationRequired)
527+ then true
528+ else throwErr("nothing to finalize")
529+ }
530+ if ((checkFinalizationIsRequired == checkFinalizationIsRequired))
531+ then {
532+ let useStakingReward = if ((stakingReward > 0))
533+ then {
534+ let lockPart = fraction(stakingReward, lockFraction, lockFractionMultiplier)
535+ let convertPart = (stakingReward - lockPart)
536+ let r = invoke(boostingContract, "userMaxDurationREADONLY", [toString(this)], nil)
537+ let lock = if ((lockPart > 0))
538+ then match r {
539+ case _ =>
540+ if (if (if ($isInstanceOf($match0._1, "String"))
541+ then $isInstanceOf($match0._2, "Int")
542+ else false)
543+ then $isInstanceOf($match0, "(String, Int)")
544+ else false)
545+ then {
546+ let function = $match0._1
547+ let duration = $match0._2
548+ if ((lockPart > 0))
549+ then invoke(boostingContract, function, [duration], [AttachedPayment(wxAssetId, lockPart)])
550+ else unit
551+ }
552+ else throwErr("invalid lock params")
553+ }
554+ else unit
555+ if ((lock == lock))
556+ then {
557+ let convertedAmount = if ((convertPart > 0))
558+ then {
559+ let inAssetId = wxAssetId
560+ let minimumToReceive = 0
561+ let outAssetIdStr = assetIdToString(usdtAssetId)
562+ let targetAddress = toString(this)
563+ valueOrErrorMessage({
564+ let @ = invoke(swapContract, "swap", [minimumToReceive, outAssetIdStr, targetAddress], [AttachedPayment(inAssetId, convertPart)])
565+ if ($isInstanceOf(@, "Int"))
566+ then @
567+ else unit
568+ }, wrapErr("invalid swap result"))
569+ }
570+ else 0
571+ if ((convertedAmount == convertedAmount))
572+ then {
573+ let lpAssetAmount = if ((convertedAmount > 0))
574+ then {
575+ let minOutAmount = 0
576+ let autoStake = true
577+ valueOrErrorMessage({
578+ let @ = invoke(poolAddress, "putOneTknV2", [minOutAmount, autoStake], [AttachedPayment(usdtAssetId, convertedAmount)])
579+ if ($isInstanceOf(@, "Int"))
580+ then @
581+ else unit
582+ }, wrapErr("invalid putOneTknV2 result"))
583+ }
584+ else 0
585+ if ((lpAssetAmount == lpAssetAmount))
586+ then lpAssetAmount
587+ else throw("Strict value is not equal to itself.")
588+ }
589+ else throw("Strict value is not equal to itself.")
590+ }
591+ else throw("Strict value is not equal to itself.")
592+ }
593+ else unit
594+ if ((useStakingReward == useStakingReward))
595+ then {
596+ let getActions = if ((shareAssetAmountToConvert > 0))
597+ then {
598+ let price = calcPrice(lpAssetId, shareAssetId)
599+ if ((price == price))
600+ then {
601+ let unstakeAmount = toInt(fraction(toBigInt(shareAssetAmountToConvert), price, scale18BigInt, FLOOR))
602+ let baseAssetAmount = {
603+ let outAssetId = baseAssetId
604+ let minOutAmount = 0
605+ valueOrErrorMessage({
606+ let @ = invoke(poolAddress, "unstakeAndGetOneTknV2", [unstakeAmount, assetIdToString(outAssetId), minOutAmount], nil)
607+ if ($isInstanceOf(@, "Int"))
608+ then @
609+ else unit
610+ }, wrapErr("invalid unstakeAndGetOneTknV2 result"))
611+ }
612+ if ((baseAssetAmount == baseAssetAmount))
613+ then {
614+ let shareAssetBurn = if ((shareAssetInfo.issuer == this))
615+ then invoke(this, "burn", [shareAssetId, shareAssetAmountToConvert], nil)
616+ else throwErr("invalid share asset issuer")
617+ if ((shareAssetBurn == shareAssetBurn))
618+ then {
619+ let priceGet = fraction(toBigInt(baseAssetAmount), scale18BigInt, toBigInt(shareAssetAmountToConvert), FLOOR)
620+ let priceGetUpdateActions = [BinaryEntry(keyPricePeriodGet(baseAssetId, period), toBytes(priceGet)), StringEntry(keyPriceGetHistory(baseAssetId), toString(priceGet))]
621+ priceGetUpdateActions
622+ }
623+ else throw("Strict value is not equal to itself.")
624+ }
625+ else throw("Strict value is not equal to itself.")
626+ }
627+ else throw("Strict value is not equal to itself.")
628+ }
629+ else nil
630+ if ((getActions == getActions))
631+ then {
632+ let putActions = if ((baseAssetAmountToConvert > 0))
633+ then {
634+ let lpAssetAmount = {
635+ let minOutAmount = 0
636+ let autoStake = true
637+ valueOrErrorMessage({
638+ let @ = invoke(poolAddress, "putOneTknV2", [minOutAmount, autoStake], [AttachedPayment(baseAssetId, baseAssetAmountToConvert)])
639+ if ($isInstanceOf(@, "Int"))
640+ then @
641+ else unit
642+ }, wrapErr("invalid putOneTknV2 result"))
643+ }
644+ if ((lpAssetAmount == lpAssetAmount))
645+ then {
646+ let price = calcPrice(lpAssetId, shareAssetId)
647+ if ((price == price))
648+ then {
649+ let checkPrice = if ((value(toInt(price)) != 0))
650+ then true
651+ else throw("price is ZERO")
652+ if ((checkPrice == checkPrice))
653+ then {
654+ let shareAssetAmount = toInt(fraction(toBigInt(lpAssetAmount), scale18BigInt, price, FLOOR))
655+ let checkShareAssetAmount = if ((value(toInt(price)) != 0))
656+ then true
657+ else throw("shareAssetAmount is ZERO")
658+ if ((checkShareAssetAmount == checkShareAssetAmount))
659+ then {
660+ let shareAssetReissue = if ((shareAssetInfo.issuer == this))
661+ then invoke(this, "emit", [shareAssetId, shareAssetAmount], nil)
662+ else throwErr("invalid share asset issuer")
663+ if ((shareAssetReissue == shareAssetReissue))
664+ then {
665+ let pricePut = fraction(toBigInt(baseAssetAmountToConvert), scale18BigInt, toBigInt(shareAssetAmount))
666+ let pricePutUpdateActions = [BinaryEntry(keyPricePeriodPut(baseAssetId, period), toBytes(pricePut)), StringEntry(keyPricePutHistory(baseAssetId), toString(pricePut))]
667+ pricePutUpdateActions
668+ }
669+ else throw("Strict value is not equal to itself.")
670+ }
671+ else throw("Strict value is not equal to itself.")
672+ }
673+ else throw("Strict value is not equal to itself.")
674+ }
675+ else throw("Strict value is not equal to itself.")
676+ }
677+ else throw("Strict value is not equal to itself.")
678+ }
679+ else nil
680+ if ((putActions == putActions))
681+ then {
682+ let newPeriod = (period + 1)
683+ let lastPrice = calcPrice(lpAssetId, shareAssetId)
684+ let actions = (([IntegerEntry(keyPeriod(baseAssetId), newPeriod), IntegerEntry(keyPeriodStartHeight(baseAssetId, newPeriod), height), IntegerEntry(keyShareAssetAmountToConvert(baseAssetId), 0), IntegerEntry(keyBaseAssetAmountToConvert(baseAssetId), 0), BinaryEntry(keyPricePeriod(baseAssetId, period), toBytes(lastPrice)), StringEntry(keyPriceHistory(baseAssetId), toString(lastPrice))] ++ putActions) ++ getActions)
685+ $Tuple2(actions, toBytes(lastPrice))
686+ }
687+ else throw("Strict value is not equal to itself.")
688+ }
689+ else throw("Strict value is not equal to itself.")
690+ }
691+ else throw("Strict value is not equal to itself.")
692+ }
693+ else throw("Strict value is not equal to itself.")
694+ }
695+ else throw("Strict value is not equal to itself.")
696+ }
697+ else throw("Strict value is not equal to itself.")
698+ }
699+ else throw("Strict value is not equal to itself.")
700+ }
246701 else throw("Strict value is not equal to itself.")
247702 }
248703 else throw("Strict value is not equal to itself.")
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let SEP = "__"
4+let separator = "__"
55
6-let feeScale = toBigInt(100000000)
6+let shareAssetDecimals = 8
77
8-func getStringOrFail (key) = valueOrErrorMessage(getString(this, key), ("No data for this.key=" + key))
8+let wavesString = "WAVES"
9+
10+let scale18 = 1000000000000000000
11+
12+let scale18BigInt = toBigInt(scale18)
13+
14+func wrapErr (msg) = makeString(["lp_staking_pools.ride:", msg], " ")
915
1016
11-let poolDisabled = throw("Pool disabled")
17+func throwErr (msg) = throw(wrapErr(msg))
1218
13-let poolNotExist = throw("Pool is not exist")
1419
15-let slippageTooBig = throw("Slippage is too big")
20+func errKeyIsNotDefined (address,key) = wrapErr(makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
21+
22+
23+func getStrOrFail (address,key) = valueOrErrorMessage(getString(address, key), errKeyIsNotDefined(address, key))
24+
25+
26+func getIntOrFail (address,key) = valueOrErrorMessage(getInteger(address, key), errKeyIsNotDefined(address, key))
27+
28+
29+func parseAssetId (input) = if ((input == wavesString))
30+ then unit
31+ else fromBase58String(input)
32+
33+
34+func assetIdToString (input) = if ((input == unit))
35+ then wavesString
36+ else toBase58String(value(input))
37+
38+
39+func ensurePositive (v) = if ((v >= 0))
40+ then v
41+ else throwErr("value should be positive")
42+
43+
44+func keyFactoryContract () = makeString(["%s", "factoryContract"], separator)
45+
46+
47+func keyLpStakingContract () = makeString(["%s", "lpStakingContract"], separator)
48+
49+
50+func keyStakingContract () = makeString(["%s", "stakingContract"], separator)
51+
52+
53+func keyBoostingContract () = makeString(["%s", "boostingContract"], separator)
54+
55+
56+func keySwapContract () = makeString(["%s", "swapContract"], separator)
57+
58+
59+func keyAssetsStoreContract () = makeString(["%s", "assetsStoreContract"], separator)
60+
61+
62+func keyUsdtAssetId () = makeString(["%s", "usdtAssetId"], separator)
63+
64+
65+func keyWxAssetId () = makeString(["%s", "wxAssetId"], separator)
66+
67+
68+func keyShutdown () = makeString(["%s", "shutdown"], separator)
69+
70+
71+func keyMinDelay () = makeString(["%s", "minDelay"], separator)
72+
73+
74+func keyLockFraction () = makeString(["%s", "lockFraction"], separator)
75+
76+
77+func keyShareAssetId (baseAssetId) = makeString(["%s%s", assetIdToString(baseAssetId), "shareAssetId"], separator)
78+
79+
80+func keyBaseAssetId (shareAssetId) = makeString(["%s%s", assetIdToString(shareAssetId), "baseAssetId"], separator)
81+
82+
83+func keyPeriod (baseAssetId) = makeString(["%s%s", assetIdToString(baseAssetId), "period"], separator)
84+
85+
86+func keyPeriodStartHeight (baseAssetId,period) = makeString(["%s%s%d", assetIdToString(baseAssetId), "periodStartHeight", toString(period)], separator)
87+
88+
89+func keyBaseAssetAmountToConvert (baseAssetId) = makeString(["%s%s", assetIdToString(baseAssetId), "baseAssetAmountToConvert"], separator)
90+
91+
92+func keyShareAssetAmountToConvert (baseAssetId) = makeString(["%s%s", assetIdToString(baseAssetId), "shareAssetAmountToConvert"], separator)
93+
94+
95+func keyUserBaseAssetAmountToConvert (baseAssetId,userAddress) = makeString(["%s%s%s", assetIdToString(baseAssetId), toString(userAddress), "baseAssetAmountToConvert"], separator)
96+
97+
98+func keyUserBaseAssetAmountToConvertPeriod (baseAssetId,userAddress) = makeString(["%s%s%s%s", assetIdToString(baseAssetId), toString(userAddress), "baseAssetAmountToConvert", "period"], separator)
99+
100+
101+func keyUserShareAssetAmountToConvert (baseAssetId,userAddress) = makeString(["%s%s%s", assetIdToString(baseAssetId), toString(userAddress), "shareAssetAmountToConvert"], separator)
102+
103+
104+func keyUserShareAssetAmountToConvertPeriod (baseAssetId,userAddress) = makeString(["%s%s%s%s", assetIdToString(baseAssetId), toString(userAddress), "shareAssetAmountToConvert", "period"], separator)
105+
106+
107+func keyPricePeriod (baseAssetId,period) = makeString(["%s%s%d", assetIdToString(baseAssetId), "price", toString(period)], separator)
108+
109+
110+func keyPriceHistory (baseAssetId) = makeString(["%s%s%s%d%d", assetIdToString(baseAssetId), "price", "history", toString(lastBlock.height), toString(lastBlock.timestamp)], separator)
111+
112+
113+func keyPricePeriodPut (baseAssetId,period) = makeString(["%s%s%d%s", assetIdToString(baseAssetId), "price", toString(period), "put"], separator)
114+
115+
116+func keyPricePutHistory (baseAssetId) = makeString(["%s%s%s%s%d%d", assetIdToString(baseAssetId), "price", "history", "put", toString(lastBlock.height), toString(lastBlock.timestamp)], separator)
117+
118+
119+func keyPricePeriodGet (baseAssetId,period) = makeString(["%s%s%d%s", assetIdToString(baseAssetId), "price", toString(period), "get"], separator)
120+
121+
122+func keyPriceGetHistory (baseAssetId) = makeString(["%s%s%s%s%d%d", assetIdToString(baseAssetId), "price", "history", "get", toString(lastBlock.height), toString(lastBlock.timestamp)], separator)
123+
124+
125+func keyHistoryEntry (baseAssetId,operation,period,userAddress,txId) = makeString(["%s%s%s%s", "history", toBase58String(value(baseAssetId)), operation, toString(userAddress), toBase58String(txId), toString(height)], separator)
126+
16127
17128 func keyManagerPublicKey () = "%s__managerPublicKey"
18129
19130
20-func keyPendingManagerPublicKey () = "%s__pendingManagerPublicKey"
131+func keyManagerVaultAddress () = "%s__managerVaultAddress"
21132
22133
23-func fc () = "%s__factoryContract"
24-
25-
26-let factoryContract = addressFromStringValue(getStringOrFail(fc()))
27-
28-func protocolFee () = makeString(["%s", "protocolFee"], SEP)
29-
30-
31-func poolFee () = makeString(["%s", "poolFee"], SEP)
32-
33-
34-func getStringOrFailFromAddress (address,key) = valueOrErrorMessage(getString(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
35-
36-
37-let keyFeeCollectorAddress = "%s__feeCollectorAddress"
38-
39-let feeCollectorAddress = addressFromStringValue(getStringOrFailFromAddress(factoryContract, keyFeeCollectorAddress))
40-
41-func asInt (val) = match val {
42- case valInt: Int =>
43- valInt
134+func getManagerVaultAddressOrThis () = match getString(keyManagerVaultAddress()) {
135+ case s: String =>
136+ addressFromStringValue(s)
44137 case _ =>
45- throw("fail to cast into Int")
138+ this
46139 }
47140
48141
49-func dataMappingPoolAssets (internalAmountAssetStr,internalPriceAssetStr) = makeString(["%d%d", toString(internalAmountAssetStr), toString(internalPriceAssetStr)], SEP)
142+func managerPublicKeyOrUnit () = {
143+ let managerVaultAddress = getManagerVaultAddressOrThis()
144+ match getString(managerVaultAddress, keyManagerPublicKey()) {
145+ case s: String =>
146+ fromBase58String(s)
147+ case _: Unit =>
148+ unit
149+ case _ =>
150+ throw("Match error")
151+ }
152+ }
50153
51154
52-func managerPublicKeyOrUnit () = match getString(keyManagerPublicKey()) {
53- case s: String =>
54- fromBase58String(s)
155+let permissionDeniedError = throw("Permission denied")
156+
157+func mustThis (i) = if ((i.caller == this))
158+ then true
159+ else permissionDeniedError
160+
161+
162+func mustManager (i) = match managerPublicKeyOrUnit() {
163+ case pk: ByteVector =>
164+ if ((i.callerPublicKey == pk))
165+ then true
166+ else permissionDeniedError
55167 case _: Unit =>
56- unit
168+ mustThis(i)
57169 case _ =>
58170 throw("Match error")
59171 }
60172
61173
62-func pendingManagerPublicKeyOrUnit () = match getString(keyPendingManagerPublicKey()) {
63- case s: String =>
64- fromBase58String(s)
65- case _: Unit =>
66- unit
67- case _ =>
68- throw("Match error")
69-}
174+let shutdown = valueOrElse(getBoolean(keyShutdown()), false)
175+
176+func shutdownCheck (i) = if (if (!(shutdown))
177+ then true
178+ else mustManager(i))
179+ then true
180+ else throw("operation is disabled")
70181
71182
72-func isManager (i) = match managerPublicKeyOrUnit() {
73- case pk: ByteVector =>
74- (i.callerPublicKey == pk)
75- case _: Unit =>
76- (i.caller == this)
77- case _ =>
78- throw("Match error")
79-}
183+let factoryContract = addressFromStringValue(getStrOrFail(this, keyFactoryContract()))
80184
185+let lpStakingContract = addressFromStringValue(getStrOrFail(this, keyLpStakingContract()))
81186
82-func mustManager (i) = if (isManager(i))
83- then true
84- else throw("permission denied")
187+let stakingContract = addressFromStringValue(getStrOrFail(this, keyStakingContract()))
85188
189+let boostingContract = addressFromStringValue(getStrOrFail(this, keyBoostingContract()))
86190
87-func getAccBalance (assetId) = if ((assetId == "WAVES"))
88- then wavesBalance(this).available
89- else assetBalance(this, fromBase58String(assetId))
191+let swapContract = addressFromStringValue(getStrOrFail(this, keySwapContract()))
90192
193+let assetsStoreContract = addressFromStringValue(getStrOrFail(this, keyAssetsStoreContract()))
91194
92-func getPoolAddressAndCheckPoolStatus (assetIn,assetOut) = {
93- let lpNonReverse = {
94- let @ = invoke(factoryContract, "getLpAssetFromPoolAssetsREADONLY", [assetIn, assetOut], nil)
95- if ($isInstanceOf(@, "String"))
195+let usdtAssetId = parseAssetId(getStrOrFail(this, keyUsdtAssetId()))
196+
197+let wxAssetId = parseAssetId(getStrOrFail(this, keyWxAssetId()))
198+
199+let minDelayDefault = 1440
200+
201+let minDelay = valueOrElse(getInteger(this, keyMinDelay()), minDelayDefault)
202+
203+let lockFractionMultiplier = 100000000
204+
205+let lockFractionDefault = fraction(1, lockFractionMultiplier, 2)
206+
207+let lockFraction = valueOrElse(getInteger(this, keyLockFraction()), lockFractionDefault)
208+
209+func getPoolInfo (amountAssetId) = {
210+ let amountAssetIdStr = assetIdToString(amountAssetId)
211+ let priceAssetIdStr = assetIdToString(usdtAssetId)
212+ let poolInfoOption = {
213+ let @ = invoke(factoryContract, "poolInfoREADONLY", [amountAssetIdStr, priceAssetIdStr], nil)
214+ if ($isInstanceOf(@, "(Address, ByteVector)"))
96215 then @
97216 else unit
98217 }
99- let lpReverse = {
100- let @ = invoke(factoryContract, "getLpAssetFromPoolAssetsREADONLY", [assetOut, assetIn], nil)
101- if ($isInstanceOf(@, "String"))
218+ poolInfoOption
219+ }
220+
221+
222+func calcPrice (lpAssetId,shareAssetId) = {
223+ let shareAssetInfo = valueOrErrorMessage(assetInfo(shareAssetId), "failed to get share asset info")
224+ let shareAssetEmission = shareAssetInfo.quantity
225+ let stakedAmount = ensurePositive(valueOrErrorMessage({
226+ let @ = invoke(stakingContract, "stakedByUserREADONLY", [assetIdToString(lpAssetId), toString(this)], nil)
227+ if ($isInstanceOf(@, "Int"))
102228 then @
103229 else unit
104- }
105- let $t025332992 = if ((lpNonReverse != unit))
106- then {
107- let pool = {
108- let @ = invoke(factoryContract, "getPoolAddressFromLpAssetREADONLY", [value(lpNonReverse)], nil)
109- if ($isInstanceOf(@, "String"))
110- then @
111- else throw(($getType(@) + " couldn't be cast to String"))
112- }
113- $Tuple2(false, pool)
114- }
115- else if ((lpReverse != unit))
116- then {
117- let pool = {
118- let @ = invoke(factoryContract, "getPoolAddressFromLpAssetREADONLY", [value(lpReverse)], nil)
119- if ($isInstanceOf(@, "String"))
120- then @
121- else throw(($getType(@) + " couldn't be cast to String"))
122- }
123- $Tuple2(true, pool)
124- }
125- else poolNotExist
126- let isReverse = $t025332992._1
127- let pool = $t025332992._2
128- let poolStatus = {
129- let @ = invoke(factoryContract, "getPoolStatusREADONLY", [pool], nil)
130- if ($isInstanceOf(@, "Int"))
131- then @
132- else throw(($getType(@) + " couldn't be cast to Int"))
133- }
134- let check = if ((poolStatus == 1))
135- then true
136- else poolDisabled
137- if ((check == check))
138- then {
139- let poolAdr = addressFromStringValue(valueOrElse(pool, ""))
140- $Tuple2(poolAdr, isReverse)
141- }
142- else throw("Strict value is not equal to itself.")
230+ }, wrapErr("invalid stakedByUserREADONLY result")))
231+ let price = if ((shareAssetEmission == 0))
232+ then scale18BigInt
233+ else fraction(toBigInt(stakedAmount), scale18BigInt, toBigInt(shareAssetEmission), FLOOR)
234+ price
143235 }
144236
145237
146238 @Callable(i)
147-func swapCalculateREADONLY (amountIn,assetIn,assetOut) = {
148- let prFee = value(getInteger(protocolFee()))
149- let feeProtocolAmountCalc = fraction(toBigInt(amountIn), toBigInt(prFee), feeScale)
150- let plFee = value(getInteger(poolFee()))
151- let feePoolAmountCalc = fraction(toBigInt(amountIn), toBigInt(plFee), feeScale)
152- let feeProtocolAmount = if ((toInt(feeProtocolAmountCalc) == 0))
153- then toBigInt(1)
154- else feeProtocolAmountCalc
155- let feePoolAmount = if ((toInt(feePoolAmountCalc) == 0))
156- then toBigInt(1)
157- else feePoolAmountCalc
158- let cleanAmountIn = ((toBigInt(amountIn) - feeProtocolAmount) - feePoolAmount)
159- let $t039804058 = getPoolAddressAndCheckPoolStatus(assetIn, assetOut)
160- let poolAdr = $t039804058._1
161- let isReverse = $t039804058._2
162- let res = {
163- let @ = invoke(poolAdr, "calculateAmountOutForSwapREADONLY", [toInt(cleanAmountIn), isReverse, toInt(feePoolAmount)], nil)
164- if ($isInstanceOf(@, "Int"))
165- then @
166- else throw(($getType(@) + " couldn't be cast to Int"))
167- }
168- $Tuple2(nil, res)
169- }
170-
171-
172-
173-@Callable(i)
174-func swap (amountOutMin,assetOutRaw,addressTo) = {
175- let assetOut = if ((assetOutRaw == ""))
176- then "WAVES"
177- else assetOutRaw
178- let pmt = value(i.payments[0])
179- let assetIn = if ((pmt.assetId == unit))
180- then "WAVES"
181- else toBase58String(value(pmt.assetId))
182- let amountIn = value(pmt.amount)
183- let prFee = value(getInteger(protocolFee()))
184- let feeProtocolAmountCalc = fraction(toBigInt(amountIn), toBigInt(prFee), feeScale)
185- let plFee = value(getInteger(poolFee()))
186- let feePoolAmountCalc = fraction(toBigInt(amountIn), toBigInt(plFee), feeScale)
187- let feeProtocolAmount = if ((toInt(feeProtocolAmountCalc) == 0))
188- then toBigInt(1)
189- else feeProtocolAmountCalc
190- let feePoolAmount = if ((toInt(feePoolAmountCalc) == 0))
191- then toBigInt(1)
192- else feePoolAmountCalc
193- let cleanAmountIn = ((toBigInt(amountIn) - feeProtocolAmount) - feePoolAmount)
194- let checks = [if ((size(i.payments) == 1))
195- then true
196- else throw("exactly 1 payment are expected")]
197- if ((checks == checks))
239+func emit (assetId,amount) = {
240+ let checkCaller = mustThis(i)
241+ if ((checkCaller == checkCaller))
198242 then {
199- let $t052605338 = getPoolAddressAndCheckPoolStatus(assetIn, assetOut)
200- let poolAdr = $t052605338._1
201- let isReverse = $t052605338._2
202- let assetInAttachedPayment = if ((assetIn == "WAVES"))
203- then unit
204- else fromBase58String(assetIn)
205- let totalGetRaw = {
206- let @ = invoke(poolAdr, "calculateAmountOutForSwapAndSendTokens", [toInt(cleanAmountIn), isReverse, amountOutMin, addressTo, toInt(feePoolAmount)], [AttachedPayment(assetInAttachedPayment, toInt(cleanAmountIn))])
207- if ($isInstanceOf(@, "Int"))
208- then @
209- else throw(($getType(@) + " couldn't be cast to Int"))
210- }
211- $Tuple2([ScriptTransfer(feeCollectorAddress, toInt(feeProtocolAmount), assetInAttachedPayment), ScriptTransfer(poolAdr, toInt(feePoolAmount), assetInAttachedPayment)], totalGetRaw)
243+ let isReissuable = true
244+ $Tuple2([Reissue(assetId, amount, isReissuable)], amount)
212245 }
213246 else throw("Strict value is not equal to itself.")
214247 }
215248
216249
217250
218251 @Callable(i)
219-func setManager (pendingManagerPublicKey) = {
220- let checkCaller = mustManager(i)
252+func burn (assetId,amount) = {
253+ let checkCaller = mustThis(i)
221254 if ((checkCaller == checkCaller))
255+ then $Tuple2([Burn(assetId, amount)], amount)
256+ else throw("Strict value is not equal to itself.")
257+ }
258+
259+
260+
261+@Callable(i)
262+func create (baseAssetIdStr,shareAssetIdStr,shareAssetName,shareAssetDescription,shareAssetLogo) = {
263+ let shareAssetLabel = "STAKING_LP"
264+ let baseAssetId = parseAssetId(baseAssetIdStr)
265+ let checks = [mustManager(i), if (isDefined(getPoolInfo(baseAssetId)))
266+ then true
267+ else throwErr("invalid base asset")]
268+ if ((checks == checks))
222269 then {
223- let checkManagerPublicKey = fromBase58String(pendingManagerPublicKey)
224- if ((checkManagerPublicKey == checkManagerPublicKey))
225- then [StringEntry(keyPendingManagerPublicKey(), pendingManagerPublicKey)]
270+ let commonState = [IntegerEntry(keyPeriod(baseAssetId), 0)]
271+ if ((shareAssetIdStr == ""))
272+ then {
273+ let shareAssetIssueAmount = 1
274+ let shareAssetIssueAction = Issue(shareAssetName, shareAssetDescription, shareAssetIssueAmount, shareAssetDecimals, true)
275+ let calculatedShareAssetId = calculateAssetId(shareAssetIssueAction)
276+ let shareAssetBurnAction = Burn(calculatedShareAssetId, shareAssetIssueAmount)
277+ let calculatedShareAssetIdStr = toBase58String(calculatedShareAssetId)
278+ let createOrUpdate = invoke(assetsStoreContract, "createOrUpdate", [calculatedShareAssetIdStr, shareAssetLogo, false], nil)
279+ if ((createOrUpdate == createOrUpdate))
280+ then {
281+ let addLabel = invoke(assetsStoreContract, "addLabel", [calculatedShareAssetIdStr, shareAssetLabel], nil)
282+ if ((addLabel == addLabel))
283+ then $Tuple2((commonState ++ [shareAssetIssueAction, shareAssetBurnAction, StringEntry(keyShareAssetId(baseAssetId), calculatedShareAssetIdStr), StringEntry(keyBaseAssetId(calculatedShareAssetId), baseAssetIdStr)]), calculatedShareAssetIdStr)
284+ else throw("Strict value is not equal to itself.")
285+ }
286+ else throw("Strict value is not equal to itself.")
287+ }
288+ else {
289+ let shareAssetId = fromBase58String(shareAssetIdStr)
290+ let shareAssetInfo = valueOrErrorMessage(assetInfo(shareAssetId), wrapErr("invalid share asset id"))
291+ let checkIssuer = if ((shareAssetInfo.issuer == lpStakingContract))
292+ then true
293+ else throwErr("invalid share asset id issuer")
294+ if ((checkIssuer == checkIssuer))
295+ then $Tuple2((commonState ++ [StringEntry(keyShareAssetId(baseAssetId), shareAssetIdStr), StringEntry(keyBaseAssetId(shareAssetId), baseAssetIdStr)]), shareAssetIdStr)
296+ else throw("Strict value is not equal to itself.")
297+ }
298+ }
299+ else throw("Strict value is not equal to itself.")
300+ }
301+
302+
303+
304+@Callable(i)
305+func put () = {
306+ let pmt = if ((size(i.payments) == 1))
307+ then i.payments[0]
308+ else throwErr("exactly 1 payment is expected")
309+ let baseAssetId = pmt.assetId
310+ let userAddress = i.caller
311+ let checks = [shutdownCheck(i), if (isDefined(getString(keyShareAssetId(baseAssetId))))
312+ then true
313+ else throwErr("invalid asset")]
314+ if ((checks == checks))
315+ then {
316+ let $t01112911232 = valueOrErrorMessage(getPoolInfo(baseAssetId), wrapErr("invalid asset"))
317+ let poolAddress = $t01112911232._1
318+ let lpAssetId = $t01112911232._2
319+ let period = value(getInteger(keyPeriod(baseAssetId)))
320+ let userBaseAssetAmountToConvertPeriodOption = getInteger(keyUserBaseAssetAmountToConvertPeriod(baseAssetId, userAddress))
321+ let claimShareAssetInvocation = if ((userBaseAssetAmountToConvertPeriodOption == unit))
322+ then unit
323+ else {
324+ let userBaseAssetAmountToConvertPeriod = value(userBaseAssetAmountToConvertPeriodOption)
325+ if ((userBaseAssetAmountToConvertPeriod == period))
326+ then unit
327+ else invoke(this, "claimShareAsset", [assetIdToString(baseAssetId), toString(userAddress)], nil)
328+ }
329+ if ((claimShareAssetInvocation == claimShareAssetInvocation))
330+ then {
331+ let baseAssetAmountToConvert = valueOrElse(getInteger(keyBaseAssetAmountToConvert(baseAssetId)), 0)
332+ let userBaseAssetAmountToConvert = value(parseInt(split(valueOrElse(getString(keyUserBaseAssetAmountToConvert(baseAssetId, userAddress)), "%d%d%d__0__0"), separator)[1]))
333+ $Tuple2([IntegerEntry(keyBaseAssetAmountToConvert(baseAssetId), (baseAssetAmountToConvert + pmt.amount)), StringEntry(keyUserBaseAssetAmountToConvert(baseAssetId, userAddress), makeString(["%d%d%d", toString((userBaseAssetAmountToConvert + pmt.amount)), toString(lastBlock.timestamp), toString(period)], separator)), IntegerEntry(keyUserBaseAssetAmountToConvertPeriod(baseAssetId, userAddress), period), StringEntry(keyHistoryEntry(baseAssetId, "put", period, userAddress, i.transactionId), makeString(["%d%d%d", toString(pmt.amount), toString(lastBlock.timestamp), toString(userBaseAssetAmountToConvert)], separator))], unit)
334+ }
226335 else throw("Strict value is not equal to itself.")
227336 }
228337 else throw("Strict value is not equal to itself.")
229338 }
230339
231340
232341
233342 @Callable(i)
234-func confirmManager () = {
235- let pm = pendingManagerPublicKeyOrUnit()
236- let hasPM = if (isDefined(pm))
237- then true
238- else throw("no pending manager")
239- if ((hasPM == hasPM))
343+func claimShareAsset (baseAssetIdStr,userAddressStr) = {
344+ let checks = [shutdownCheck(i)]
345+ if ((checks == checks))
240346 then {
241- let checkPM = if ((i.callerPublicKey == value(pm)))
242- then true
243- else throw("you are not pending manager")
244- if ((checkPM == checkPM))
245- then [StringEntry(keyManagerPublicKey(), toBase58String(value(pm))), DeleteEntry(keyPendingManagerPublicKey())]
347+ let userAddress = if ((userAddressStr == ""))
348+ then i.caller
349+ else {
350+ let checkCaller = mustThis(i)
351+ if ((checkCaller == checkCaller))
352+ then valueOrErrorMessage(addressFromString(userAddressStr), wrapErr("invalid user address"))
353+ else throw("Strict value is not equal to itself.")
354+ }
355+ if ((userAddress == userAddress))
356+ then {
357+ let baseAssetId = parseAssetId(baseAssetIdStr)
358+ let shareAssetId = value(parseAssetId(valueOrErrorMessage(getString(keyShareAssetId(baseAssetId)), wrapErr("invalid base asset id"))))
359+ if ((shareAssetId == shareAssetId))
360+ then {
361+ let period = valueOrErrorMessage(getInteger(keyPeriod(baseAssetId)), wrapErr("invalid period"))
362+ if ((period == period))
363+ then {
364+ let userBaseAssetAmountToConvert = value(parseInt(split(valueOrElse(getString(keyUserBaseAssetAmountToConvert(baseAssetId, userAddress)), "%d%d%d__0__0"), separator)[1]))
365+ let checkAmountToConvert = if ((userBaseAssetAmountToConvert > 0))
366+ then true
367+ else throwErr("nothing to claim")
368+ if ((checkAmountToConvert == checkAmountToConvert))
369+ then {
370+ let userBaseAssetAmountToConvertPeriod = valueOrErrorMessage(getInteger(keyUserBaseAssetAmountToConvertPeriod(baseAssetId, userAddress)), wrapErr("failed to get period"))
371+ let checkPeriod = if ((period > userBaseAssetAmountToConvertPeriod))
372+ then true
373+ else throwErr("invalid period")
374+ if ((checkPeriod == checkPeriod))
375+ then {
376+ let price = toBigInt(valueOrErrorMessage(getBinary(keyPricePeriodPut(baseAssetId, userBaseAssetAmountToConvertPeriod)), wrapErr("failed to get price")))
377+ let shareAssetAmount = toInt(fraction(toBigInt(userBaseAssetAmountToConvert), scale18BigInt, price))
378+ $Tuple2([StringEntry(keyUserBaseAssetAmountToConvert(baseAssetId, userAddress), makeString(["%d%d%d", toString(0), toString(lastBlock.timestamp), toString(period)], separator)), DeleteEntry(keyUserBaseAssetAmountToConvertPeriod(baseAssetId, userAddress)), ScriptTransfer(userAddress, shareAssetAmount, shareAssetId), StringEntry(keyHistoryEntry(baseAssetId, "claimShareAsset", period, userAddress, i.transactionId), makeString(["%d%d%d%d", toString(shareAssetAmount), toString(lastBlock.timestamp), toString(price), toString(userBaseAssetAmountToConvert)], separator))], unit)
379+ }
380+ else throw("Strict value is not equal to itself.")
381+ }
382+ else throw("Strict value is not equal to itself.")
383+ }
384+ else throw("Strict value is not equal to itself.")
385+ }
386+ else throw("Strict value is not equal to itself.")
387+ }
388+ else throw("Strict value is not equal to itself.")
389+ }
390+ else throw("Strict value is not equal to itself.")
391+ }
392+
393+
394+
395+@Callable(i)
396+func get () = {
397+ let checks = [shutdownCheck(i)]
398+ if ((checks == checks))
399+ then {
400+ let pmt = if ((size(i.payments) == 1))
401+ then i.payments[0]
402+ else throwErr("exactly 1 payment is expected")
403+ let shareAssetId = pmt.assetId
404+ let baseAssetId = value(parseAssetId(valueOrErrorMessage(getString(keyBaseAssetId(shareAssetId)), wrapErr("invalid share asset id"))))
405+ if ((baseAssetId == baseAssetId))
406+ then {
407+ let userAddress = i.caller
408+ let $t01564215831 = valueOrErrorMessage(getPoolInfo(baseAssetId), wrapErr("invalid asset"))
409+ let poolAddress = $t01564215831._1
410+ let lpAssetId = $t01564215831._2
411+ let period = value(getInteger(keyPeriod(baseAssetId)))
412+ let userShareAssetAmountToConvertPeriodOption = getInteger(keyUserShareAssetAmountToConvertPeriod(baseAssetId, userAddress))
413+ let claimBaseAssetInvocation = if ((userShareAssetAmountToConvertPeriodOption == unit))
414+ then unit
415+ else {
416+ let userShareAssetAmountToConvertPeriod = value(userShareAssetAmountToConvertPeriodOption)
417+ if ((userShareAssetAmountToConvertPeriod == period))
418+ then unit
419+ else invoke(this, "claimBaseAsset", [assetIdToString(baseAssetId), toString(userAddress)], nil)
420+ }
421+ if ((claimBaseAssetInvocation == claimBaseAssetInvocation))
422+ then {
423+ let shareAssetAmountToConvert = valueOrElse(getInteger(keyShareAssetAmountToConvert(baseAssetId)), 0)
424+ let userShareAssetAmountToConvert = value(parseInt(split(valueOrElse(getString(keyUserShareAssetAmountToConvert(baseAssetId, userAddress)), "%d%d%d__0__0"), separator)[1]))
425+ $Tuple2([IntegerEntry(keyShareAssetAmountToConvert(baseAssetId), (shareAssetAmountToConvert + pmt.amount)), StringEntry(keyUserShareAssetAmountToConvert(baseAssetId, userAddress), makeString(["%d%d%d", toString((userShareAssetAmountToConvert + pmt.amount)), toString(lastBlock.timestamp), toString(period)], separator)), IntegerEntry(keyUserShareAssetAmountToConvertPeriod(baseAssetId, userAddress), period), StringEntry(keyHistoryEntry(baseAssetId, "get", period, userAddress, i.transactionId), makeString(["%d%d%d", toString(pmt.amount), toString(lastBlock.timestamp), toString(userShareAssetAmountToConvert)], separator))], unit)
426+ }
427+ else throw("Strict value is not equal to itself.")
428+ }
429+ else throw("Strict value is not equal to itself.")
430+ }
431+ else throw("Strict value is not equal to itself.")
432+ }
433+
434+
435+
436+@Callable(i)
437+func claimBaseAsset (baseAssetIdStr,userAddressStr) = {
438+ let checks = [shutdownCheck(i)]
439+ if ((checks == checks))
440+ then {
441+ let userAddress = if ((userAddressStr == ""))
442+ then i.caller
443+ else {
444+ let checkCaller = mustThis(i)
445+ if ((checkCaller == checkCaller))
446+ then valueOrErrorMessage(addressFromString(userAddressStr), wrapErr("invalid user address"))
447+ else throw("Strict value is not equal to itself.")
448+ }
449+ if ((userAddress == userAddress))
450+ then {
451+ let baseAssetId = parseAssetId(baseAssetIdStr)
452+ let shareAssetId = value(parseAssetId(valueOrErrorMessage(getString(keyShareAssetId(baseAssetId)), wrapErr("invalid base asset id"))))
453+ if ((shareAssetId == shareAssetId))
454+ then {
455+ let period = valueOrErrorMessage(getInteger(keyPeriod(baseAssetId)), wrapErr("invalid period"))
456+ if ((period == period))
457+ then {
458+ let userShareAssetAmountToConvert = value(parseInt(split(valueOrElse(getString(keyUserShareAssetAmountToConvert(baseAssetId, userAddress)), "%d%d%d__0__0"), separator)[1]))
459+ let userShareAssetAmountToConvertPeriod = valueOrErrorMessage(getInteger(keyUserShareAssetAmountToConvertPeriod(baseAssetId, userAddress)), wrapErr("failed to get period"))
460+ let checkPeriod = if ((period > userShareAssetAmountToConvertPeriod))
461+ then true
462+ else throwErr("invalid period")
463+ if ((checkPeriod == checkPeriod))
464+ then {
465+ let price = toBigInt(valueOrErrorMessage(getBinary(keyPricePeriodGet(baseAssetId, userShareAssetAmountToConvertPeriod)), wrapErr("failed to get price")))
466+ let baseAssetAmount = toInt(fraction(toBigInt(userShareAssetAmountToConvert), price, scale18BigInt))
467+ $Tuple2([StringEntry(keyUserShareAssetAmountToConvert(baseAssetId, userAddress), makeString(["%d%d%d", toString(0), toString(lastBlock.timestamp), toString(period)], separator)), DeleteEntry(keyUserShareAssetAmountToConvertPeriod(baseAssetId, userAddress)), ScriptTransfer(userAddress, baseAssetAmount, baseAssetId), StringEntry(keyHistoryEntry(baseAssetId, "claimBaseAsset", period, userAddress, i.transactionId), makeString(["%d%d%d%d", toString(baseAssetAmount), toString(lastBlock.timestamp), toString(price), toString(userShareAssetAmountToConvertPeriod)], separator))], unit)
468+ }
469+ else throw("Strict value is not equal to itself.")
470+ }
471+ else throw("Strict value is not equal to itself.")
472+ }
473+ else throw("Strict value is not equal to itself.")
474+ }
475+ else throw("Strict value is not equal to itself.")
476+ }
477+ else throw("Strict value is not equal to itself.")
478+ }
479+
480+
481+
482+@Callable(i)
483+func finalize (baseAssetIdStr) = {
484+ let checks = [shutdownCheck(i)]
485+ if ((checks == checks))
486+ then {
487+ let baseAssetId = parseAssetId(baseAssetIdStr)
488+ let shareAssetId = value(parseAssetId(valueOrErrorMessage(getString(keyShareAssetId(baseAssetId)), wrapErr("invalid base asset id"))))
489+ if ((shareAssetId == shareAssetId))
490+ then {
491+ let shareAssetInfo = valueOrErrorMessage(assetInfo(shareAssetId), wrapErr("invalid share asset id"))
492+ let period = valueOrErrorMessage(getInteger(keyPeriod(baseAssetId)), wrapErr("invalid period"))
493+ if ((period == period))
494+ then {
495+ let periodStartHeightOption = getInteger(keyPeriodStartHeight(baseAssetId, period))
496+ let checkDelay = if ((periodStartHeightOption == unit))
497+ then unit
498+ else {
499+ let delay = (height - value(periodStartHeightOption))
500+ let blocksToWait = max([0, (minDelay - delay)])
501+ if ((blocksToWait == 0))
502+ then unit
503+ else throwErr(makeString(["finalization will be possible in ", toString(blocksToWait), " blocks"], ""))
504+ }
505+ if ((checkDelay == checkDelay))
506+ then {
507+ let $t02127221453 = valueOrErrorMessage(getPoolInfo(baseAssetId), wrapErr("invalid asset"))
508+ let poolAddress = $t02127221453._1
509+ let lpAssetId = $t02127221453._2
510+ let stakingReward = valueOrErrorMessage({
511+ let @ = invoke(stakingContract, "claimWxDoNotThrow", [assetIdToString(lpAssetId)], nil)
512+ if ($isInstanceOf(@, "Int"))
513+ then @
514+ else unit
515+ }, wrapErr("invalid claimWx result"))
516+ if ((stakingReward == stakingReward))
517+ then {
518+ let baseAssetAmountToConvert = valueOrElse(getInteger(keyBaseAssetAmountToConvert(baseAssetId)), 0)
519+ let shareAssetAmountToConvert = valueOrElse(getInteger(keyShareAssetAmountToConvert(baseAssetId)), 0)
520+ let checkFinalizationIsRequired = {
521+ let isFinalizationRequired = if (if ((stakingReward > 0))
522+ then true
523+ else (baseAssetAmountToConvert > 0))
524+ then true
525+ else (shareAssetAmountToConvert > 0)
526+ if (isFinalizationRequired)
527+ then true
528+ else throwErr("nothing to finalize")
529+ }
530+ if ((checkFinalizationIsRequired == checkFinalizationIsRequired))
531+ then {
532+ let useStakingReward = if ((stakingReward > 0))
533+ then {
534+ let lockPart = fraction(stakingReward, lockFraction, lockFractionMultiplier)
535+ let convertPart = (stakingReward - lockPart)
536+ let r = invoke(boostingContract, "userMaxDurationREADONLY", [toString(this)], nil)
537+ let lock = if ((lockPart > 0))
538+ then match r {
539+ case _ =>
540+ if (if (if ($isInstanceOf($match0._1, "String"))
541+ then $isInstanceOf($match0._2, "Int")
542+ else false)
543+ then $isInstanceOf($match0, "(String, Int)")
544+ else false)
545+ then {
546+ let function = $match0._1
547+ let duration = $match0._2
548+ if ((lockPart > 0))
549+ then invoke(boostingContract, function, [duration], [AttachedPayment(wxAssetId, lockPart)])
550+ else unit
551+ }
552+ else throwErr("invalid lock params")
553+ }
554+ else unit
555+ if ((lock == lock))
556+ then {
557+ let convertedAmount = if ((convertPart > 0))
558+ then {
559+ let inAssetId = wxAssetId
560+ let minimumToReceive = 0
561+ let outAssetIdStr = assetIdToString(usdtAssetId)
562+ let targetAddress = toString(this)
563+ valueOrErrorMessage({
564+ let @ = invoke(swapContract, "swap", [minimumToReceive, outAssetIdStr, targetAddress], [AttachedPayment(inAssetId, convertPart)])
565+ if ($isInstanceOf(@, "Int"))
566+ then @
567+ else unit
568+ }, wrapErr("invalid swap result"))
569+ }
570+ else 0
571+ if ((convertedAmount == convertedAmount))
572+ then {
573+ let lpAssetAmount = if ((convertedAmount > 0))
574+ then {
575+ let minOutAmount = 0
576+ let autoStake = true
577+ valueOrErrorMessage({
578+ let @ = invoke(poolAddress, "putOneTknV2", [minOutAmount, autoStake], [AttachedPayment(usdtAssetId, convertedAmount)])
579+ if ($isInstanceOf(@, "Int"))
580+ then @
581+ else unit
582+ }, wrapErr("invalid putOneTknV2 result"))
583+ }
584+ else 0
585+ if ((lpAssetAmount == lpAssetAmount))
586+ then lpAssetAmount
587+ else throw("Strict value is not equal to itself.")
588+ }
589+ else throw("Strict value is not equal to itself.")
590+ }
591+ else throw("Strict value is not equal to itself.")
592+ }
593+ else unit
594+ if ((useStakingReward == useStakingReward))
595+ then {
596+ let getActions = if ((shareAssetAmountToConvert > 0))
597+ then {
598+ let price = calcPrice(lpAssetId, shareAssetId)
599+ if ((price == price))
600+ then {
601+ let unstakeAmount = toInt(fraction(toBigInt(shareAssetAmountToConvert), price, scale18BigInt, FLOOR))
602+ let baseAssetAmount = {
603+ let outAssetId = baseAssetId
604+ let minOutAmount = 0
605+ valueOrErrorMessage({
606+ let @ = invoke(poolAddress, "unstakeAndGetOneTknV2", [unstakeAmount, assetIdToString(outAssetId), minOutAmount], nil)
607+ if ($isInstanceOf(@, "Int"))
608+ then @
609+ else unit
610+ }, wrapErr("invalid unstakeAndGetOneTknV2 result"))
611+ }
612+ if ((baseAssetAmount == baseAssetAmount))
613+ then {
614+ let shareAssetBurn = if ((shareAssetInfo.issuer == this))
615+ then invoke(this, "burn", [shareAssetId, shareAssetAmountToConvert], nil)
616+ else throwErr("invalid share asset issuer")
617+ if ((shareAssetBurn == shareAssetBurn))
618+ then {
619+ let priceGet = fraction(toBigInt(baseAssetAmount), scale18BigInt, toBigInt(shareAssetAmountToConvert), FLOOR)
620+ let priceGetUpdateActions = [BinaryEntry(keyPricePeriodGet(baseAssetId, period), toBytes(priceGet)), StringEntry(keyPriceGetHistory(baseAssetId), toString(priceGet))]
621+ priceGetUpdateActions
622+ }
623+ else throw("Strict value is not equal to itself.")
624+ }
625+ else throw("Strict value is not equal to itself.")
626+ }
627+ else throw("Strict value is not equal to itself.")
628+ }
629+ else nil
630+ if ((getActions == getActions))
631+ then {
632+ let putActions = if ((baseAssetAmountToConvert > 0))
633+ then {
634+ let lpAssetAmount = {
635+ let minOutAmount = 0
636+ let autoStake = true
637+ valueOrErrorMessage({
638+ let @ = invoke(poolAddress, "putOneTknV2", [minOutAmount, autoStake], [AttachedPayment(baseAssetId, baseAssetAmountToConvert)])
639+ if ($isInstanceOf(@, "Int"))
640+ then @
641+ else unit
642+ }, wrapErr("invalid putOneTknV2 result"))
643+ }
644+ if ((lpAssetAmount == lpAssetAmount))
645+ then {
646+ let price = calcPrice(lpAssetId, shareAssetId)
647+ if ((price == price))
648+ then {
649+ let checkPrice = if ((value(toInt(price)) != 0))
650+ then true
651+ else throw("price is ZERO")
652+ if ((checkPrice == checkPrice))
653+ then {
654+ let shareAssetAmount = toInt(fraction(toBigInt(lpAssetAmount), scale18BigInt, price, FLOOR))
655+ let checkShareAssetAmount = if ((value(toInt(price)) != 0))
656+ then true
657+ else throw("shareAssetAmount is ZERO")
658+ if ((checkShareAssetAmount == checkShareAssetAmount))
659+ then {
660+ let shareAssetReissue = if ((shareAssetInfo.issuer == this))
661+ then invoke(this, "emit", [shareAssetId, shareAssetAmount], nil)
662+ else throwErr("invalid share asset issuer")
663+ if ((shareAssetReissue == shareAssetReissue))
664+ then {
665+ let pricePut = fraction(toBigInt(baseAssetAmountToConvert), scale18BigInt, toBigInt(shareAssetAmount))
666+ let pricePutUpdateActions = [BinaryEntry(keyPricePeriodPut(baseAssetId, period), toBytes(pricePut)), StringEntry(keyPricePutHistory(baseAssetId), toString(pricePut))]
667+ pricePutUpdateActions
668+ }
669+ else throw("Strict value is not equal to itself.")
670+ }
671+ else throw("Strict value is not equal to itself.")
672+ }
673+ else throw("Strict value is not equal to itself.")
674+ }
675+ else throw("Strict value is not equal to itself.")
676+ }
677+ else throw("Strict value is not equal to itself.")
678+ }
679+ else nil
680+ if ((putActions == putActions))
681+ then {
682+ let newPeriod = (period + 1)
683+ let lastPrice = calcPrice(lpAssetId, shareAssetId)
684+ let actions = (([IntegerEntry(keyPeriod(baseAssetId), newPeriod), IntegerEntry(keyPeriodStartHeight(baseAssetId, newPeriod), height), IntegerEntry(keyShareAssetAmountToConvert(baseAssetId), 0), IntegerEntry(keyBaseAssetAmountToConvert(baseAssetId), 0), BinaryEntry(keyPricePeriod(baseAssetId, period), toBytes(lastPrice)), StringEntry(keyPriceHistory(baseAssetId), toString(lastPrice))] ++ putActions) ++ getActions)
685+ $Tuple2(actions, toBytes(lastPrice))
686+ }
687+ else throw("Strict value is not equal to itself.")
688+ }
689+ else throw("Strict value is not equal to itself.")
690+ }
691+ else throw("Strict value is not equal to itself.")
692+ }
693+ else throw("Strict value is not equal to itself.")
694+ }
695+ else throw("Strict value is not equal to itself.")
696+ }
697+ else throw("Strict value is not equal to itself.")
698+ }
699+ else throw("Strict value is not equal to itself.")
700+ }
246701 else throw("Strict value is not equal to itself.")
247702 }
248703 else throw("Strict value is not equal to itself.")
249704 }
250705
251706
252707 @Verifier(tx)
253708 func verify () = {
254709 let targetPublicKey = match managerPublicKeyOrUnit() {
255710 case pk: ByteVector =>
256711 pk
257712 case _: Unit =>
258713 tx.senderPublicKey
259714 case _ =>
260715 throw("Match error")
261716 }
262717 sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey)
263718 }
264719

github/deemru/w8io/c3f4982 
68.39 ms