tx · 6F7JEUAysadsm5j6sAtHGzNhSM8EFmfuEsK2rDRU5Nis

3M4i6koV3NcMJq25ZJZu8j8Nor7Po3cWzcu:  -0.06000000 Waves

2026.06.23 15:43 [820040] smart account 3M4i6koV3NcMJq25ZJZu8j8Nor7Po3cWzcu > SELF 0.00000000 Waves

{ "type": 13, "id": "6F7JEUAysadsm5j6sAtHGzNhSM8EFmfuEsK2rDRU5Nis", "fee": 6000000, "feeAssetId": null, "timestamp": 1782218589512, "version": 2, "chainId": 82, "sender": "3M4i6koV3NcMJq25ZJZu8j8Nor7Po3cWzcu", "senderPublicKey": "7C6uWLoNmCjLuaaUV2orpzzVm2kW9cRh567Pi6BDfXoD", "proofs": [ "3UjByKR7Qsf5s45nG77518rbqX61gXg8GnDgVsPC5qdp3wVqj9QbVpnGkENcaomYGj47zqfNBrjqfbHtiy5XYiGi" ], "script": "base64:BgKqAQgCEgASBAoCCAESBAoCCAESABIDCgEIEgQKAggBEgMKAQgSBAoCCAESBAoCCAESABIGCgQICAgIEgYKBAgICAgSBAoCCAgSBAoCCAgSAwoBBBIDCgEIEgMKAQgSAwoBCBIDCgEEEggKBgQIAQgICBIFCgMECAgSBgoEBAgECBIDCgEEEgQKAggEEgQKAggEEgMKAQQSAwoBBBIDCgEIEgMKAQgSAwoBCBIALQANQ09OVFJBQ1RfVFlQRQIOTEVORC1MUC1NQVJLRVQAB1ZFUlNJT04CCVBMUC0xLjIuMAETZ2V0QWRkcmVzc0Zyb21TdGF0ZQEDa2V5CQELdmFsdWVPckVsc2UCCQCmCAEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwkArAICAg5zZXR1cF9hZGRyZXNzXwUDa2V5AiMzUEV3UmNZTkFVdG9GdktwQmhLb2l3YWpuWmZkb0RSNmg0aAkBB0FkZHJlc3MBARoBV46zaotfT5rTy6/BBdbIYhwwXDI85kwhvgEVZ2V0QWRkcmVzc2VzRnJvbVN0YXRlAQNrZXkKAQFmAgVhY2N1bQRuZXh0CQDOCAIFBWFjY3VtCQDMCAIJAQt2YWx1ZU9yRWxzZQIJAKYIAQUEbmV4dAkBB0FkZHJlc3MBARoBV46zaotfT5rTy6/BBdbIYhwwXDI85kwhvgUDbmlsCgACJGwJALwJAgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzCQCsAgICDnNldHVwX2FkZHJlc3NfBQNrZXkCIzNQRXdSY1lOQVV0b0Z2S3BCaEtvaXdham5aZmRvRFI2aDRoAgEsCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQFmAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxNQkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAScmVzZXJ2ZUZ1bmRBZGRyZXNzCQETZ2V0QWRkcmVzc0Zyb21TdGF0ZQECC3Jlc2VydmVGdW5kAA1vcmFjbGVBZGRyZXNzCQETZ2V0QWRkcmVzc0Zyb21TdGF0ZQECBm9yYWNsZQARYWdncmVnYXRvckFkZHJlc3MJARNnZXRBZGRyZXNzRnJvbVN0YXRlAQIKYWdncmVnYXRvcgAMYWRtaW5BZGRyZXNzCQETZ2V0QWRkcmVzc0Zyb21TdGF0ZQECBWFkbWluABFzdGFibGVGdW5kQWRkcmVzcwkBE2dldEFkZHJlc3NGcm9tU3RhdGUBAgpzdGFibGVGdW5kABNmZWVDb2xsZWN0b3JBZGRyZXNzCQETZ2V0QWRkcmVzc0Zyb21TdGF0ZQECDGZlZUNvbGxlY3RvcgARc2h1dGRvd25XaGl0ZWxpc3QJARVnZXRBZGRyZXNzZXNGcm9tU3RhdGUBAg9zaHV0ZG93bkNhbGxlcnMAFGxpcXVpZGF0b3JzV2hpdGVsaXN0CQEVZ2V0QWRkcmVzc2VzRnJvbVN0YXRlAQILbGlxdWlkYXRvcnMBFnZlcmlmeUxpcXVpZGF0b3JSaWdodHMBB2FkZHJlc3MJAQIhPQIJAM8IAgUUbGlxdWlkYXRvcnNXaGl0ZWxpc3QFB2FkZHJlc3MFBHVuaXQAC3Jlc2VydmVGdW5kCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMCFHNldHVwX3Jlc2VydmVGdW5kRmVlABQADHN0YWJsZXNJZFN0cgkAtQkCCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMCEHNldHVwX3N0YWJsZXNJZHMCWTl3YzNMWE5BNFRFQnNYeUt0b0xFOW1yYkREN1dNSFh2WHJDalp2YWJMQXNpLEhHZ2FiVHFVUzhXdFZGVUp6Zm1yVERNZ0VjY0p1WkxCUGhGZ1FGeHZuc29XAgEsAQxnZXRSYXRlQ3VydmUBCmFzc2V0SWRTdHIEDmN1cnZlUmF0ZVN0ckxpCQC1CQIJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwkArAICAhBzZXR1cF9yYXRlQ3VydmVfBQphc3NldElkU3RyAiUyMDAwMDAwMCwxMDAwMDAwMDAsNjAwMDAwMDAsNDAwMDAwMDAwAgEsCQCWCgQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQ5jdXJ2ZVJhdGVTdHJMaQAACQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUOY3VydmVSYXRlU3RyTGkAAQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFDmN1cnZlUmF0ZVN0ckxpAAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQ5jdXJ2ZVJhdGVTdHJMaQADARNnZXRSZXdhcmRzU3BsaXR0aW5nAQphc3NldElkU3RyBBVyZXdhcmRzU3BsaXR0aW5nU3RyTGkJALUJAgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzCQCsAgICF3NldHVwX3Jld2FyZHNTcGxpdHRpbmdfBQphc3NldElkU3RyAggzMCw1MCwyMAIBLAkAlQoDCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUVcmV3YXJkc1NwbGl0dGluZ1N0ckxpAAAJAQ1wYXJzZUludFZhbHVlAQkAkQMCBRVyZXdhcmRzU3BsaXR0aW5nU3RyTGkAAQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFFXJld2FyZHNTcGxpdHRpbmdTdHJMaQACAAlzZW50aW5lbHMJAMwIAgkBB0FkZHJlc3MBARoBV9fhI1GOfKuIWtXXKJd12Ih104+uIwWm4QkAzAgCCQEHQWRkcmVzcwEBGgFX+Pr6AibAUYvsajtGM0nSHHGwdYv5pMqaCQDMCAIJAQdBZGRyZXNzAQEaAVdJARj2Q38/TGzhZ3Xlt+SXL95QLbKD3fEJAMwIAgkBB0FkZHJlc3MBARoBV0vDbM77M1hDWENREO7v7iEQF0vyeMt8MgUDbmlsAAZTY2FsZTgAgMLXLwAHU2NhbGUxMACAyK+gJQAHU2NhbGUxNgkAaAIFBlNjYWxlOAUGU2NhbGU4AAlkYXlCbG9ja3MAoAsAFXdpdGhkcmF3YWxMaW1pdEJsb2NrcwkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzAhtzZXR1cF93aXRoZHJhd2FsTGltaXRCbG9ja3MAZAEKbGlJbnRUb1N0cgECbGkKAQFmAgVhY2N1bQRuZXh0CQCsAgIJAKwCAgUFYWNjdW0JAKQDAQUEbmV4dAIBLAoAAiRsBQJsaQoAAiRzCQCQAwEFAiRsCgAFJGFjYzACAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEBZgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTIJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwBDXRyeUdldEludGVnZXIBA2tleQQHJG1hdGNoMAkAmggCBQR0aGlzBQNrZXkDCQABAgUHJG1hdGNoMAIDSW50BAFiBQckbWF0Y2gwBQFiAAABDXRyeUdldEJvb2xlYW4BA2tleQQHJG1hdGNoMAkAmwgCBQR0aGlzBQNrZXkDCQABAgUHJG1hdGNoMAIHQm9vbGVhbgQBYgUHJG1hdGNoMAUBYgcBDHRyeUdldFN0cmluZwEDa2V5BAckbWF0Y2gwCQCdCAIFBHRoaXMFA2tleQMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAWIFByRtYXRjaDAFAWICAAEMdHJ5R2V0QmluYXJ5AQNrZXkEByRtYXRjaDAJAJwIAgUEdGhpcwUDa2V5AwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEAWIFByRtYXRjaDAFAWIBAAEOZ2V0QXNzZXRTdHJpbmcBB2Fzc2V0SWQEByRtYXRjaDAFB2Fzc2V0SWQDCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQBYgUHJG1hdGNoMAkA2AQBBQFiAgVXQVZFUwENZ2V0QXNzZXRCeXRlcwEKYXNzZXRJZFN0cgMJAAACBQphc3NldElkU3RyAgVXQVZFUwUEdW5pdAkA2QQBBQphc3NldElkU3RyAQpnZXRCYWxhbmNlAQphc3NldElkU3RyAwkAAAIFCmFzc2V0SWRTdHICBVdBVkVTCAkA7wcBBQR0aGlzCWF2YWlsYWJsZQkA8AcCBQR0aGlzCQDZBAEFCmFzc2V0SWRTdHIBD2dldE1hcmtldEFzc2V0cwAJALUJAgkBDHRyeUdldFN0cmluZwECDHNldHVwX3Rva2VucwIBLAENZ2V0T3V0ZGF0ZWRVcgEKYXNzZXRJZFN0cgQEZG93bgkAawMJAQ10cnlHZXRJbnRlZ2VyAQkArAICAg90b3RhbF9zdXBwbGllZF8FCmFzc2V0SWRTdHIJAQ10cnlHZXRJbnRlZ2VyAQkArAICBQphc3NldElkU3RyAgZfc1JhdGUFB1NjYWxlMTYDCQAAAgUEZG93bgAAAAAJAGsDBQZTY2FsZTgJAGsDCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfYm9ycm93ZWRfBQphc3NldElkU3RyCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgUKYXNzZXRJZFN0cgIGX2JSYXRlBQdTY2FsZTE2BQRkb3duAQtnZXRJbnRlcmVzdAEKYXNzZXRJZFN0cgQCdXIJAQ1nZXRPdXRkYXRlZFVyAQUKYXNzZXRJZFN0cgQFY3VydmUJAQxnZXRSYXRlQ3VydmUBBQphc3NldElkU3RyBARyYXRlCQBkAggFBWN1cnZlAl8xAwkAZwIIBQVjdXJ2ZQJfMwUCdXIJAGsDBQJ1cggFBWN1cnZlAl8yCAUFY3VydmUCXzMJAGQCCAUFY3VydmUCXzIJAGsDCQBlAgUCdXIIBQVjdXJ2ZQJfMwgFBWN1cnZlAl80CQBlAgCAwtcvCAUFY3VydmUCXzMJAJYDAQkAzAgCCQBrAwUEcmF0ZQUGU2NhbGU4CQBoAgUJZGF5QmxvY2tzAO0CCQDMCAIAAQUDbmlsARB0b2tlblJhdGVzUmVjYWxjAQphc3NldElkU3RyBAhpbnRlcmVzdAkBC2dldEludGVyZXN0AQUKYXNzZXRJZFN0cgQCdXIJAQ1nZXRPdXRkYXRlZFVyAQUKYXNzZXRJZFN0cgQQbGFzdFJlY2FsY0hlaWdodAkBDXRyeUdldEludGVnZXIBAg5sYXN0UmF0ZUhlaWdodAQJbGFzdEJSYXRlCQCWAwEJAMwIAgkBDXRyeUdldEludGVnZXIBCQCsAgIFCmFzc2V0SWRTdHICBl9iUmF0ZQkAzAgCBQdTY2FsZTE2BQNuaWwECG5ld0JSYXRlCQBkAgUJbGFzdEJSYXRlCQBoAgkAZQIFBmhlaWdodAUQbGFzdFJlY2FsY0hlaWdodAUIaW50ZXJlc3QECWxhc3RTUmF0ZQkAlgMBCQDMCAIJAQ10cnlHZXRJbnRlZ2VyAQkArAICBQphc3NldElkU3RyAgZfc1JhdGUJAMwIAgUHU2NhbGUxNgUDbmlsBAhuZXdTUmF0ZQkAZAIFCWxhc3RTUmF0ZQkAaQIJAGgCCQBoAgkAZQIFBmhlaWdodAUQbGFzdFJlY2FsY0hlaWdodAkAawMFCGludGVyZXN0BQJ1cgUGU2NhbGU4CQBlAgBkBQtyZXNlcnZlRnVuZABkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIFCmFzc2V0SWRTdHICBl9zUmF0ZQUIbmV3U1JhdGUJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgUKYXNzZXRJZFN0cgIGX2JSYXRlBQhuZXdCUmF0ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgIObGFzdFJhdGVIZWlnaHQFBmhlaWdodAUDbmlsAQ1nZXRBY3R1YWxSYXRlAgphc3NldElkU3RyCHJhdGVUeXBlCgEBZgIFYWNjdW0FdG9rZW4EBnJlY2FsYwkBEHRva2VuUmF0ZXNSZWNhbGMBBQV0b2tlbgkAlAoCAwkBAiE9AgUFdG9rZW4FCmFzc2V0SWRTdHIIBQVhY2N1bQJfMQMJAAACBQhyYXRlVHlwZQIFc1JhdGUICQCRAwIFBnJlY2FsYwAABXZhbHVlCAkAkQMCBQZyZWNhbGMAAQV2YWx1ZQkAzggCCAUFYWNjdW0CXzIFBnJlY2FsYwoAAiRsCQEPZ2V0TWFya2V0QXNzZXRzAAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJQKAgAABQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBAWYCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEyCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAQVnZXRVcgEKYXNzZXRJZFN0cgQFcmF0ZXMJARB0b2tlblJhdGVzUmVjYWxjAQUKYXNzZXRJZFN0cgQEZG93bgkAawMJAQ10cnlHZXRJbnRlZ2VyAQkArAICAg90b3RhbF9zdXBwbGllZF8FCmFzc2V0SWRTdHIICQCRAwIFBXJhdGVzAAAFdmFsdWUFB1NjYWxlMTYJAGsDBQZTY2FsZTgJAGsDCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfYm9ycm93ZWRfBQphc3NldElkU3RyCAkAkQMCBQVyYXRlcwABBXZhbHVlBQdTY2FsZTE2BQRkb3duAQtyYXRlc1JlY2FsYwAKAQFmAgVhY2N1bQV0b2tlbgkAzggCBQVhY2N1bQkBEHRva2VuUmF0ZXNSZWNhbGMBBQV0b2tlbgoAAiRsCQEPZ2V0TWFya2V0QXNzZXRzAAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEBZgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTIJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwBFWdldFRva2VuUHJpY2VXaXRoUmlzawIKYXNzZXRJZFN0cgxyaXNrQXZlcnNpdHkDCQECIT0CCQDPCAIFDHN0YWJsZXNJZFN0cgUKYXNzZXRJZFN0cgUEdW5pdAkAlAoCAMCEPQDAhD0EBXByaWNlCQERQGV4dHJOYXRpdmUoMTA1MCkCBQ1vcmFjbGVBZGRyZXNzCQCsAgIFCmFzc2V0SWRTdHICB190d2FwNUIECXJpc2tMZXZlbAkBEUBleHRyTmF0aXZlKDEwNTApAgUNb3JhY2xlQWRkcmVzcwkArAICBQphc3NldElkU3RyAgpfcmlza0xldmVsAwkAZwIFDHJpc2tBdmVyc2l0eQUJcmlza0xldmVsCQCUCgIFBXByaWNlBQVwcmljZQkAAgEJAKwCAgkArAICAhtvcmFjbGUgcHJpY2VzIGRvbid0IG1hdGNoOiAJAKQDAQUFcHJpY2UCIyBpcyB0aGUgcHJpY2UsIGJ1dCByaXNrIGlzIHRvbyBoaWdoAQ1nZXRUb2tlblByaWNlAQphc3NldElkU3RyCQEVZ2V0VG9rZW5QcmljZVdpdGhSaXNrAgUKYXNzZXRJZFN0cgADARNnZXRUb2tlblByaWNlQ2FwcGVkAQphc3NldElkU3RyBAskdDA3OTg3ODA1MAkBFWdldFRva2VuUHJpY2VXaXRoUmlzawIFCmFzc2V0SWRTdHIAAwQIbWluUHJpY2UIBQskdDA3OTg3ODA1MAJfMQQIbWF4UHJpY2UIBQskdDA3OTg3ODA1MAJfMgQPbWF4QWxsb3dlZFByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAKwCAgIPc2V0dXBfbWF4UHJpY2VfBQphc3NldElkU3RyAP///////////wEED21pbkFsbG93ZWRQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgICD3NldHVwX21pblByaWNlXwUKYXNzZXRJZFN0cgD///////////8BAwMJAQIhPQIFD21heEFsbG93ZWRQcmljZQD///////////8BCQBmAgUIbWF4UHJpY2UFD21heEFsbG93ZWRQcmljZQcJAJQKAgUPbWF4QWxsb3dlZFByaWNlBQ9tYXhBbGxvd2VkUHJpY2UDAwkBAiE9AgUPbWluQWxsb3dlZFByaWNlAP///////////wEJAGYCBQ9taW5BbGxvd2VkUHJpY2UFCG1pblByaWNlBwkAlAoCBQ9taW5BbGxvd2VkUHJpY2UFD21pbkFsbG93ZWRQcmljZQkAlAoCBQhtaW5QcmljZQUIbWF4UHJpY2UBDmNhbGNBc3NldFNjYWxlAQphc3NldElkU3RyBAhkZWNpbWFscwMJAAACBQphc3NldElkU3RyAgVXQVZFUwAICAkBBXZhbHVlAQkA7AcBCQDZBAEFCmFzc2V0SWRTdHIIZGVjaW1hbHMJAGwGAAoAAAUIZGVjaW1hbHMAAAAABQRET1dOARJjYWxjVXNlckNvbGxhdGVyYWwBB2FkZHJlc3MEFHVzZXJDb2xsYXRlcmFsSW52b2tlCQD8BwQFBHRoaXMCEWdldFVzZXJDb2xsYXRlcmFsCQDMCAIHCQDMCAIFB2FkZHJlc3MJAMwIAgYJAMwIAgIABQNuaWwFA25pbAMJAAACBRR1c2VyQ29sbGF0ZXJhbEludm9rZQUUdXNlckNvbGxhdGVyYWxJbnZva2UEE3VzZXJDb2xsYXRlcmFsVmFsdWUEByRtYXRjaDAFFHVzZXJDb2xsYXRlcmFsSW52b2tlAwkAAQIFByRtYXRjaDACA0ludAQBeAUHJG1hdGNoMAUBeAkAAgECJGlzc3VlIHdoaWxlIGRvaW5nIGluLWRhcHAgaW52b2NhdGlvbgMJAAACBRN1c2VyQ29sbGF0ZXJhbFZhbHVlBRN1c2VyQ29sbGF0ZXJhbFZhbHVlBRN1c2VyQ29sbGF0ZXJhbFZhbHVlCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuARRjaGVja1dpdGhkcmF3YWxMaW1pdAQHYWRkcmVzcwphc3NldElkU3RyDmFtb3VudEludGVybmFsBXNSYXRlBA93aXRoZHJhd2FsTGltaXQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkArAICCQCsAgICBnNldHVwXwUKYXNzZXRJZFN0cgITX21heFdpdGhkcmF3UGVyMTAwQgD///////////8BAwkAAAIFD3dpdGhkcmF3YWxMaW1pdAD///////////8BBQNuaWwEDXRvdGFsU3VwcGxpZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICAg90b3RhbF9zdXBwbGllZF8FCmFzc2V0SWRTdHIECGxpbWl0Q2FwCQBrAwUNdG90YWxTdXBwbGllZAUPd2l0aGRyYXdhbExpbWl0AGQEBWxhc3RICQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICBQdhZGRyZXNzAhVfd2l0aGRyYXdMaW1pdEhlaWdodF8FCmFzc2V0SWRTdHIEB2VsYXBzZWQJAGUCBQZoZWlnaHQFBWxhc3RIBA13aW5kb3dFeHBpcmVkCQBmAgUHZWxhcHNlZAUVd2l0aGRyYXdhbExpbWl0QmxvY2tzBAtjdXJyZW50VXNlZAMFDXdpbmRvd0V4cGlyZWQAAAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgUHYWRkcmVzcwITX3dpdGhkcmF3TGltaXRVc2VkXwUKYXNzZXRJZFN0cgQNYmxvY2tzVG9SZXNldAMFDXdpbmRvd0V4cGlyZWQFFXdpdGhkcmF3YWxMaW1pdEJsb2NrcwkAZQIFFXdpdGhkcmF3YWxMaW1pdEJsb2NrcwUHZWxhcHNlZAQJYXZhaWxhYmxlCQBlAgUIbGltaXRDYXAFC2N1cnJlbnRVc2VkBA9hdmFpbGFibGVTY2FsZWQJAG4EBQlhdmFpbGFibGUFBXNSYXRlBQdTY2FsZTE2BQdDRUlMSU5HAwkAZgIFDmFtb3VudEludGVybmFsBQlhdmFpbGFibGUJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIed2l0aGRyYXdhbCBsaW1pdCBleGNlZWRlZCBmb3IgBQphc3NldElkU3RyAg0sIGF2YWlsYWJsZTogCQCkAwEFD2F2YWlsYWJsZVNjYWxlZAITLCBibG9ja3MgdG8gcmVzZXQ6IAkApAMBBQ1ibG9ja3NUb1Jlc2V0CQDOCAIDBQ13aW5kb3dFeHBpcmVkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgUHYWRkcmVzcwIVX3dpdGhkcmF3TGltaXRIZWlnaHRfBQphc3NldElkU3RyBQZoZWlnaHQFA25pbAUDbmlsCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgUHYWRkcmVzcwITX3dpdGhkcmF3TGltaXRVc2VkXwUKYXNzZXRJZFN0cgkAZAIFC2N1cnJlbnRVc2VkBQ5hbW91bnRJbnRlcm5hbAUDbmlsARBjaGVja0JvcnJvd0xpbWl0BQdhZGRyZXNzCmFzc2V0SWRTdHIOYW1vdW50SW50ZXJuYWwFYlJhdGUFc1JhdGUEC2JvcnJvd0xpbWl0CQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAKwCAgkArAICAgZzZXR1cF8FCmFzc2V0SWRTdHICEV9tYXhCb3Jyb3dQZXIxMDBCAP///////////wEDCQAAAgULYm9ycm93TGltaXQA////////////AQUDbmlsBA10b3RhbFN1cHBsaWVkCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfc3VwcGxpZWRfBQphc3NldElkU3RyBA5saW1pdENhcFN1cHBseQkAawMFDXRvdGFsU3VwcGxpZWQFC2JvcnJvd0xpbWl0AGQECGxpbWl0Q2FwCQBrAwkAawMFDmxpbWl0Q2FwU3VwcGx5BQVzUmF0ZQUHU2NhbGUxNgUHU2NhbGUxNgUFYlJhdGUEBWxhc3RICQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICBQdhZGRyZXNzAhNfYm9ycm93TGltaXRIZWlnaHRfBQphc3NldElkU3RyBAdlbGFwc2VkCQBlAgUGaGVpZ2h0BQVsYXN0SAQNd2luZG93RXhwaXJlZAkAZgIFB2VsYXBzZWQFFXdpdGhkcmF3YWxMaW1pdEJsb2NrcwQLY3VycmVudFVzZWQDBQ13aW5kb3dFeHBpcmVkAAAJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgIFB2FkZHJlc3MCEV9ib3Jyb3dMaW1pdFVzZWRfBQphc3NldElkU3RyBA1ibG9ja3NUb1Jlc2V0AwUNd2luZG93RXhwaXJlZAUVd2l0aGRyYXdhbExpbWl0QmxvY2tzCQBlAgUVd2l0aGRyYXdhbExpbWl0QmxvY2tzBQdlbGFwc2VkBAlhdmFpbGFibGUJAGUCBQhsaW1pdENhcAULY3VycmVudFVzZWQED2F2YWlsYWJsZVNjYWxlZAkAbgQFCWF2YWlsYWJsZQUFYlJhdGUFB1NjYWxlMTYFB0NFSUxJTkcDCQBmAgUOYW1vdW50SW50ZXJuYWwFCWF2YWlsYWJsZQkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAhpib3Jyb3cgbGltaXQgZXhjZWVkZWQgZm9yIAUKYXNzZXRJZFN0cgINLCBhdmFpbGFibGU6IAkApAMBBQ9hdmFpbGFibGVTY2FsZWQCEywgYmxvY2tzIHRvIHJlc2V0OiAJAKQDAQUNYmxvY2tzVG9SZXNldAkAzggCAwUNd2luZG93RXhwaXJlZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgIFB2FkZHJlc3MCE19ib3Jyb3dMaW1pdEhlaWdodF8FCmFzc2V0SWRTdHIFBmhlaWdodAUDbmlsBQNuaWwJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkArAICBQdhZGRyZXNzAhFfYm9ycm93TGltaXRVc2VkXwUKYXNzZXRJZFN0cgkAZAIFC2N1cnJlbnRVc2VkBQ5hbW91bnRJbnRlcm5hbAUDbmlsHwFpAQZzdXBwbHkAAwkBASEBCQENdHJ5R2V0Qm9vbGVhbgECDHNldHVwX2FjdGl2ZQkAAgECEW1hcmtldCBpcyBzdG9wcGVkAwMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQYJAAACCAkAkQMCCAUBaQhwYXltZW50cwAABmFtb3VudAAACQACAQIcMSBwYXltZW50IGhhcyB0byBiZSBhdHRhY2hlZAQKYXNzZXRJZFN0cgkBDmdldEFzc2V0U3RyaW5nAQgJAJEDAggFAWkIcGF5bWVudHMAAAdhc3NldElkBAthc3NldEFtb3VudAgJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQEDSR0MDEyMDU4MTIxMjUJAQ1nZXRBY3R1YWxSYXRlAgUKYXNzZXRJZFN0cgIFc1JhdGUEBXNSYXRlCAUNJHQwMTIwNTgxMjEyNQJfMQQRcmF0ZXNSZWNhbGNSZXN1bHQIBQ0kdDAxMjA1ODEyMTI1Al8yBAZhbW91bnQJAG4EBQthc3NldEFtb3VudAUHU2NhbGUxNgUFc1JhdGUFBERPV04EB2FkZHJlc3MJAKUIAQgFAWkGY2FsbGVyBAltYXhTdXBwbHkEByRtYXRjaDAJAKIIAQkArAICAhBzZXR1cF9tYXhTdXBwbHlfBQphc3NldElkU3RyAwkAAQIFByRtYXRjaDACBlN0cmluZwQBeAUHJG1hdGNoMAkBDXBhcnNlSW50VmFsdWUBBQF4CQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIQc2V0dXBfbWF4U3VwcGx5XwUKYXNzZXRJZFN0cgQKYXNzZXRQcmljZQkBE2dldFRva2VuUHJpY2VDYXBwZWQBBQphc3NldElkU3RyBBJuZXdBZGRyZXNzU3VwcGxpZWQJAGQCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICBQdhZGRyZXNzAgpfc3VwcGxpZWRfBQphc3NldElkU3RyBQZhbW91bnQEEG5ld1RvdGFsU3VwcGxpZWQJAGQCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfc3VwcGxpZWRfBQphc3NldElkU3RyBQZhbW91bnQEBHJhdGUICQENZ2V0QWN0dWFsUmF0ZQIFCmFzc2V0SWRTdHICBXNSYXRlAl8xBAphc3NldFNjYWxlCQEOY2FsY0Fzc2V0U2NhbGUBBQphc3NldElkU3RyBBNuZXdUb3RhbFN1cHBsaWVkVXNkCQBrAwkAawMFEG5ld1RvdGFsU3VwcGxpZWQFBHJhdGUFB1NjYWxlMTYIBQphc3NldFByaWNlAl8xBQphc3NldFNjYWxlAwkAAAIJALMJAgkBDHRyeUdldFN0cmluZwECDHNldHVwX3Rva2VucwUKYXNzZXRJZFN0cgUEdW5pdAkAAgECKXRoaXMgYXNzZXQgaXMgbm90IHN1cHBvcnRlZCBieSB0aGUgbWFya2V0AwMJAQIhPQIFCW1heFN1cHBseQAACQBmAgUTbmV3VG90YWxTdXBwbGllZFVzZAUJbWF4U3VwcGx5BwkAAgECM21heCB0b3RhbCBzdXBwbHkgZm9yIHRoaXMgdG9rZW4gcmVhY2hlZCBpbiB0aGUgcG9vbAMJAGYCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgINc2V0dXBfcGF1c2VkXwUKYXNzZXRJZFN0cgAACQACAQIodGhpcyBhc3NldCBjYW4ndCBiZSBzdXBwbGllZCBvciBib3Jyb3dlZAQDaW52AwkBAiE9AgkBDHRyeUdldFN0cmluZwEJAKwCAgIQc2V0dXBfYXV0b3N0YWtlXwUKYXNzZXRJZFN0cgIACQD8BwQFBHRoaXMCCnN0YWtlVG9rZW4JAMwIAgUKYXNzZXRJZFN0cgkAzAgCBQthc3NldEFtb3VudAUDbmlsBQNuaWwFBHVuaXQDCQAAAgUDaW52BQNpbnYJAM4IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgIFB2FkZHJlc3MCCl9zdXBwbGllZF8FCmFzc2V0SWRTdHIFEm5ld0FkZHJlc3NTdXBwbGllZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAg90b3RhbF9zdXBwbGllZF8FCmFzc2V0SWRTdHIFEG5ld1RvdGFsU3VwcGxpZWQFA25pbAURcmF0ZXNSZWNhbGNSZXN1bHQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEId2l0aGRyYXcCCmFzc2V0SWRTdHILYXNzZXRBbW91bnQEDSR0MDEzNjkyMTM3NTkJAQ1nZXRBY3R1YWxSYXRlAgUKYXNzZXRJZFN0cgIFc1JhdGUEBXNSYXRlCAUNJHQwMTM2OTIxMzc1OQJfMQQRcmF0ZXNSZWNhbGNSZXN1bHQIBQ0kdDAxMzY5MjEzNzU5Al8yBAZhbW91bnQJAG4EBQthc3NldEFtb3VudAUHU2NhbGUxNgUFc1JhdGUFB0NFSUxJTkcEB2FkZHJlc3MJAKUIAQgFAWkGY2FsbGVyBA1hc3NldFN1cHBsaWVkCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfc3VwcGxpZWRfBQphc3NldElkU3RyBA1hc3NldEJvcnJvd2VkCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfYm9ycm93ZWRfBQphc3NldElkU3RyBBF1c2VyQXNzZXRTdXBwbGllZAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgUHYWRkcmVzcwIKX3N1cHBsaWVkXwUKYXNzZXRJZFN0cgQRdXNlckFzc2V0Qm9ycm93ZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgIFB2FkZHJlc3MCCl9ib3Jyb3dlZF8FCmFzc2V0SWRTdHIEEmNvbGxhdGVyYWxWYWx1ZUludgkA/AcEBQR0aGlzAhFnZXRVc2VyQ29sbGF0ZXJhbAkAzAgCBwkAzAgCBQdhZGRyZXNzCQDMCAIGCQDMCAIJAKwCAgkArAICBQphc3NldElkU3RyAgosc3VwcGxpZWQsCQCkAwEJAQEtAQUGYW1vdW50BQNuaWwFA25pbAMJAAACBRJjb2xsYXRlcmFsVmFsdWVJbnYFEmNvbGxhdGVyYWxWYWx1ZUludgQPY29sbGF0ZXJhbFZhbHVlBAckbWF0Y2gwBRJjb2xsYXRlcmFsVmFsdWVJbnYDCQABAgUHJG1hdGNoMAIDSW50BAF4BQckbWF0Y2gwBQF4CQACAQIfY2FuJ3QgZ2V0IHVzZXIgY29sbGF0ZXJhbCB2YWx1ZQMJAQEhAQkBDXRyeUdldEJvb2xlYW4BAgxzZXR1cF9hY3RpdmUJAAIBAhFtYXJrZXQgaXMgc3RvcHBlZAMJAGYCAAAFD2NvbGxhdGVyYWxWYWx1ZQkAAgECMnlvdSBkb250IGhhdmUgZW5vdWdoIGNvbGxhdGVyYWwgZm9yIHRoaXMgb3BlcmF0aW9uAwkAZgIFBmFtb3VudAkAZQIFDWFzc2V0U3VwcGxpZWQFDWFzc2V0Qm9ycm93ZWQJAAIBAip0aGlzIGFtb3VudCBpcyBub3QgYXZhaWxhYmxlIG9uIHRoZSBtYXJrZXQDCQBmAgUGYW1vdW50CQBlAgURdXNlckFzc2V0U3VwcGxpZWQFEXVzZXJBc3NldEJvcnJvd2VkCQACAQIqdGhpcyBhbW91bnQgaXMgbm90IGF2YWlsYWJsZSBmb3IgdGhpcyB1c2VyBANpbnYDCQECIT0CCQEMdHJ5R2V0U3RyaW5nAQkArAICAhBzZXR1cF9hdXRvc3Rha2VfBQphc3NldElkU3RyAgAJAPwHBAUEdGhpcwIMdW5zdGFrZVRva2VuCQDMCAIFCmFzc2V0SWRTdHIJAMwIAgULYXNzZXRBbW91bnQFA25pbAUDbmlsBQR1bml0AwkAAAIFA2ludgUDaW52BBFsaW1pdENoZWNrQWN0aW9ucwkBFGNoZWNrV2l0aGRyYXdhbExpbWl0BAUHYWRkcmVzcwUKYXNzZXRJZFN0cgUGYW1vdW50BQVzUmF0ZQMJAAACBRFsaW1pdENoZWNrQWN0aW9ucwURbGltaXRDaGVja0FjdGlvbnMJAM4IAgkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgUHYWRkcmVzcwIKX3N1cHBsaWVkXwUKYXNzZXRJZFN0cgkAZQIJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgIFB2FkZHJlc3MCCl9zdXBwbGllZF8FCmFzc2V0SWRTdHIFBmFtb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAg90b3RhbF9zdXBwbGllZF8FCmFzc2V0SWRTdHIJAGUCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfc3VwcGxpZWRfBQphc3NldElkU3RyBQZhbW91bnQJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyBQthc3NldEFtb3VudAkBDWdldEFzc2V0Qnl0ZXMBBQphc3NldElkU3RyBQNuaWwFEXJhdGVzUmVjYWxjUmVzdWx0BRFsaW1pdENoZWNrQWN0aW9ucwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQZib3Jyb3cCCmFzc2V0SWRTdHILYXNzZXRBbW91bnQEB2FkZHJlc3MJAKUIAQgFAWkGY2FsbGVyBA0kdDAxNTUyMzE1NTkwCQENZ2V0QWN0dWFsUmF0ZQIFCmFzc2V0SWRTdHICBWJSYXRlBAViUmF0ZQgFDSR0MDE1NTIzMTU1OTACXzEEEXJhdGVzUmVjYWxjUmVzdWx0CAUNJHQwMTU1MjMxNTU5MAJfMgQGYW1vdW50CQBuBAULYXNzZXRBbW91bnQFB1NjYWxlMTYFBWJSYXRlBQdDRUlMSU5HBBJjb2xsYXRlcmFsVmFsdWVJbnYJAPwHBAUEdGhpcwIRZ2V0VXNlckNvbGxhdGVyYWwJAMwIAgcJAMwIAgUHYWRkcmVzcwkAzAgCBgkAzAgCCQCsAgIJAKwCAgUKYXNzZXRJZFN0cgIKLGJvcnJvd2VkLAkApAMBBQZhbW91bnQFA25pbAUDbmlsAwkAAAIFEmNvbGxhdGVyYWxWYWx1ZUludgUSY29sbGF0ZXJhbFZhbHVlSW52BA9jb2xsYXRlcmFsVmFsdWUEByRtYXRjaDAFEmNvbGxhdGVyYWxWYWx1ZUludgMJAAECBQckbWF0Y2gwAgNJbnQEAXgFByRtYXRjaDAFAXgJAAIBAh9jYW4ndCBnZXQgdXNlciBjb2xsYXRlcmFsIHZhbHVlAwkBASEBCQENdHJ5R2V0Qm9vbGVhbgECDHNldHVwX2FjdGl2ZQkAAgECEW1hcmtldCBpcyBzdG9wcGVkAwkAZgIAAAUPY29sbGF0ZXJhbFZhbHVlCQACAQIheW91IGhhdmUgdG8gc3VwcGx5IG1vcmUgdG8gYm9ycm93AwkAAAIJAQ10cnlHZXRJbnRlZ2VyAQkArAICAhRzZXR1cF9ib3Jyb3dFbmFibGVkXwUKYXNzZXRJZFN0cgAACQACAQIcdGhpcyBhc3NldCBjYW4ndCBiZSBib3Jyb3dlZAMJAGYCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgINc2V0dXBfcGF1c2VkXwUKYXNzZXRJZFN0cgAACQACAQIodGhpcyBhc3NldCBjYW4ndCBiZSBzdXBwbGllZCBvciBib3Jyb3dlZAQNYXNzZXRTdXBwbGllZAkBDXRyeUdldEludGVnZXIBCQCsAgICD3RvdGFsX3N1cHBsaWVkXwUKYXNzZXRJZFN0cgQNYXNzZXRCb3Jyb3dlZAkBDXRyeUdldEludGVnZXIBCQCsAgICD3RvdGFsX2JvcnJvd2VkXwUKYXNzZXRJZFN0cgQRdXNlckFzc2V0Qm9ycm93ZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgIFB2FkZHJlc3MCCl9ib3Jyb3dlZF8FCmFzc2V0SWRTdHIDCQBmAgUGYW1vdW50CQBlAgUNYXNzZXRTdXBwbGllZAUNYXNzZXRCb3Jyb3dlZAkAAgECHHRoaXMgYW1vdW50IGlzIG5vdCBhdmFpbGFibGUEA2ludgMJAQIhPQIJAQx0cnlHZXRTdHJpbmcBCQCsAgICEHNldHVwX2F1dG9zdGFrZV8FCmFzc2V0SWRTdHICAAkA/AcEBQR0aGlzAgx1bnN0YWtlVG9rZW4JAMwIAgUKYXNzZXRJZFN0cgkAzAgCBQthc3NldEFtb3VudAUDbmlsBQNuaWwFBHVuaXQDCQAAAgUDaW52BQNpbnYEBXNSYXRlCAkAkQMCBRFyYXRlc1JlY2FsY1Jlc3VsdAkAaAIJAQV2YWx1ZQEJAM8IAgkBD2dldE1hcmtldEFzc2V0cwAFCmFzc2V0SWRTdHIAAwV2YWx1ZQQRbGltaXRDaGVja0FjdGlvbnMJARBjaGVja0JvcnJvd0xpbWl0BQUHYWRkcmVzcwUKYXNzZXRJZFN0cgUGYW1vdW50BQViUmF0ZQUFc1JhdGUDCQAAAgURbGltaXRDaGVja0FjdGlvbnMFEWxpbWl0Q2hlY2tBY3Rpb25zCQDOCAIJAM4IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgIFB2FkZHJlc3MCCl9ib3Jyb3dlZF8FCmFzc2V0SWRTdHIJAGQCBRF1c2VyQXNzZXRCb3Jyb3dlZAUGYW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgICD3RvdGFsX2JvcnJvd2VkXwUKYXNzZXRJZFN0cgkAZAIFDWFzc2V0Qm9ycm93ZWQFBmFtb3VudAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIFC2Fzc2V0QW1vdW50CQENZ2V0QXNzZXRCeXRlcwEFCmFzc2V0SWRTdHIFA25pbAURcmF0ZXNSZWNhbGNSZXN1bHQFEWxpbWl0Q2hlY2tBY3Rpb25zCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBBXJlcGF5AAMJAQEhAQkBDXRyeUdldEJvb2xlYW4BAgxzZXR1cF9hY3RpdmUJAAIBAhFtYXJrZXQgaXMgc3RvcHBlZAMDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEGCQAAAggJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQAAAkAAgECHDEgcGF5bWVudCBoYXMgdG8gYmUgYXR0YWNoZWQECmFzc2V0SWRTdHIJAQ5nZXRBc3NldFN0cmluZwEICQCRAwIIBQFpCHBheW1lbnRzAAAHYXNzZXRJZAQLYXNzZXRBbW91bnQICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50BA0kdDAxNzY4NDE3NzUxCQENZ2V0QWN0dWFsUmF0ZQIFCmFzc2V0SWRTdHICBWJSYXRlBAViUmF0ZQgFDSR0MDE3Njg0MTc3NTECXzEEEXJhdGVzUmVjYWxjUmVzdWx0CAUNJHQwMTc2ODQxNzc1MQJfMgQGYW1vdW50CQBuBAULYXNzZXRBbW91bnQFB1NjYWxlMTYFBWJSYXRlBQdDRUlMSU5HBAdhZGRyZXNzCQClCAEIBQFpBmNhbGxlcgQNYXNzZXRTdXBwbGllZAkBDXRyeUdldEludGVnZXIBCQCsAgICD3RvdGFsX3N1cHBsaWVkXwUKYXNzZXRJZFN0cgQNYXNzZXRCb3Jyb3dlZAkBDXRyeUdldEludGVnZXIBCQCsAgICD3RvdGFsX2JvcnJvd2VkXwUKYXNzZXRJZFN0cgQRdXNlckFzc2V0Qm9ycm93ZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgIFB2FkZHJlc3MCCl9ib3Jyb3dlZF8FCmFzc2V0SWRTdHIECmFtb3VudExlZnQJAGUCBRF1c2VyQXNzZXRCb3Jyb3dlZAUGYW1vdW50BAtyZXBheUFtb3VudAMJAGcCBQphbW91bnRMZWZ0AAAFBmFtb3VudAURdXNlckFzc2V0Qm9ycm93ZWQDCQAAAgkAswkCCQEMdHJ5R2V0U3RyaW5nAQIMc2V0dXBfdG9rZW5zBQphc3NldElkU3RyBQR1bml0CQACAQIpdGhpcyBhc3NldCBpcyBub3Qgc3VwcG9ydGVkIGJ5IHRoZSBtYXJrZXQEA2ludgMJAQIhPQIJAQx0cnlHZXRTdHJpbmcBCQCsAgICEHNldHVwX2F1dG9zdGFrZV8FCmFzc2V0SWRTdHICAAkA/AcEBQR0aGlzAgpzdGFrZVRva2VuCQDMCAIFCmFzc2V0SWRTdHIJAMwIAgULYXNzZXRBbW91bnQFA25pbAUDbmlsBQR1bml0AwkAAAIFA2ludgUDaW52BAxleGNlc3NUb2tlbnMJAGUCBQthc3NldEFtb3VudAkAawMFC3JlcGF5QW1vdW50BQViUmF0ZQUHU2NhbGUxNgkAzggCCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkArAICBQdhZGRyZXNzAgpfYm9ycm93ZWRfBQphc3NldElkU3RyCQBlAgURdXNlckFzc2V0Qm9ycm93ZWQFC3JlcGF5QW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgICD3RvdGFsX2JvcnJvd2VkXwUKYXNzZXRJZFN0cgkAZQIFDWFzc2V0Qm9ycm93ZWQFC3JlcGF5QW1vdW50BQNuaWwFEXJhdGVzUmVjYWxjUmVzdWx0AwkAZwIFCmFtb3VudExlZnQAAAUDbmlsCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgUMZXhjZXNzVG9rZW5zCAkAkQMCCAUBaQhwYXltZW50cwAAB2Fzc2V0SWQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQhyZXBheUZvcgEHYWRkcmVzcwMJAQEhAQkBDXRyeUdldEJvb2xlYW4BAgxzZXR1cF9hY3RpdmUJAAIBAhFtYXJrZXQgaXMgc3RvcHBlZAMJAQIhPQIIBQFpBmNhbGxlcgUScmVzZXJ2ZUZ1bmRBZGRyZXNzCQACAQInYXZhaWxhYmxlIG9ubHkgZm9yIHJlc2VydmUgZnVuZCBhZGRyZXNzAwkAAAIFB2FkZHJlc3MCBmdsb2JhbAkAAgECIHlvdSBjYW4ndCByZXBheSBmb3IgZXZlcnlvbmUgOl8pAwMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQYJAAACCAkAkQMCCAUBaQhwYXltZW50cwAABmFtb3VudAAACQACAQIcMSBwYXltZW50IGhhcyB0byBiZSBhdHRhY2hlZAQKYXNzZXRJZFN0cgkBDmdldEFzc2V0U3RyaW5nAQgJAJEDAggFAWkIcGF5bWVudHMAAAdhc3NldElkBAthc3NldEFtb3VudAgJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQEDSR0MDE5NDI3MTk0OTQJAQ1nZXRBY3R1YWxSYXRlAgUKYXNzZXRJZFN0cgIFYlJhdGUEBWJSYXRlCAUNJHQwMTk0MjcxOTQ5NAJfMQQRcmF0ZXNSZWNhbGNSZXN1bHQIBQ0kdDAxOTQyNzE5NDk0Al8yBAZhbW91bnQJAG4EBQthc3NldEFtb3VudAUHU2NhbGUxNgUFYlJhdGUFB0NFSUxJTkcEDWFzc2V0U3VwcGxpZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICAg90b3RhbF9zdXBwbGllZF8FCmFzc2V0SWRTdHIEDWFzc2V0Qm9ycm93ZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICAg90b3RhbF9ib3Jyb3dlZF8FCmFzc2V0SWRTdHIEEXVzZXJBc3NldEJvcnJvd2VkCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICBQdhZGRyZXNzAgpfYm9ycm93ZWRfBQphc3NldElkU3RyBAphbW91bnRMZWZ0CQBlAgURdXNlckFzc2V0Qm9ycm93ZWQFBmFtb3VudAQLcmVwYXlBbW91bnQDCQBnAgUKYW1vdW50TGVmdAAABQZhbW91bnQFEXVzZXJBc3NldEJvcnJvd2VkAwkAAAIJALMJAgkBDHRyeUdldFN0cmluZwECDHNldHVwX3Rva2VucwUKYXNzZXRJZFN0cgUEdW5pdAkAAgECKXRoaXMgYXNzZXQgaXMgbm90IHN1cHBvcnRlZCBieSB0aGUgbWFya2V0BANpbnYDCQECIT0CCQEMdHJ5R2V0U3RyaW5nAQkArAICAhBzZXR1cF9hdXRvc3Rha2VfBQphc3NldElkU3RyAgAJAPwHBAUEdGhpcwIKc3Rha2VUb2tlbgkAzAgCBQphc3NldElkU3RyCQDMCAIFC2Fzc2V0QW1vdW50BQNuaWwFA25pbAUEdW5pdAMJAAACBQNpbnYFA2ludgQMZXhjZXNzVG9rZW5zCQBlAgULYXNzZXRBbW91bnQJAGsDBQtyZXBheUFtb3VudAUFYlJhdGUFB1NjYWxlMTYJAM4IAgkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgUHYWRkcmVzcwIKX2JvcnJvd2VkXwUKYXNzZXRJZFN0cgkAZQIFEXVzZXJBc3NldEJvcnJvd2VkBQtyZXBheUFtb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAg90b3RhbF9ib3Jyb3dlZF8FCmFzc2V0SWRTdHIJAGUCBQ1hc3NldEJvcnJvd2VkBQtyZXBheUFtb3VudAUDbmlsBRFyYXRlc1JlY2FsY1Jlc3VsdAMJAGcCBQphbW91bnRMZWZ0AAAFA25pbAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIFDGV4Y2Vzc1Rva2VucwgJAJEDAggFAWkIcGF5bWVudHMAAAdhc3NldElkBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEKc3Rha2VUb2tlbgIKYXNzZXRJZFN0cgZhbW91bnQEEGF1dG9zdGFrZUFkZHJlc3MJAQt2YWx1ZU9yRWxzZQIJAKYIAQkBDHRyeUdldFN0cmluZwEJAKwCAgIQc2V0dXBfYXV0b3N0YWtlXwUKYXNzZXRJZFN0cgkBB0FkZHJlc3MBARoBV3vJqP6V1issYKZ2YPlTI8WKEFoN716o2wQVc3Rha2VyU3VwcG9ydGVkQXNzZXRzCQERQGV4dHJOYXRpdmUoMTA1MykCBRBhdXRvc3Rha2VBZGRyZXNzAhVzZXR1cF9zdXBwb3J0ZWRBc3NldHMDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAixvbmx5IGZvciBpbnRlcm5hbCBzbWFydCBjb250cmFjdCBpbnZvY2F0aW9ucwMJAAACCQCzCQIFFXN0YWtlclN1cHBvcnRlZEFzc2V0cwUKYXNzZXRJZFN0cgUEdW5pdAUDbmlsBAxhbW91bnRTdGFrZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICAhFhdXRvc3Rha2VfYW1vdW50XwUKYXNzZXRJZFN0cgQIc3Rha2VJbnYJAP0HBAUQYXV0b3N0YWtlQWRkcmVzcwIHc3Rha2VMUAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQENZ2V0QXNzZXRCeXRlcwEFCmFzc2V0SWRTdHIFBmFtb3VudAUDbmlsAwkAAAIFCHN0YWtlSW52BQhzdGFrZUludgkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhFhdXRvc3Rha2VfYW1vdW50XwUKYXNzZXRJZFN0cgkAZAIFDGFtb3VudFN0YWtlZAUGYW1vdW50BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQENc3Rha2VUb2tlbkFsbAEKYXNzZXRJZFN0cgMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECLG9ubHkgZm9yIGludGVybmFsIHNtYXJ0IGNvbnRyYWN0IGludm9jYXRpb25zBAZhbW91bnQJAQpnZXRCYWxhbmNlAQUKYXNzZXRJZFN0cgQDaW52CQD9BwQFBHRoaXMCCnN0YWtlVG9rZW4JAMwIAgUKYXNzZXRJZFN0cgkAzAgCBQZhbW91bnQFA25pbAUDbmlsAwkAAAIFA2ludgUDaW52BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEMdW5zdGFrZVRva2VuAgphc3NldElkU3RyBmFtb3VudAQQYXV0b3N0YWtlQWRkcmVzcwkBC3ZhbHVlT3JFbHNlAgkApggBCQEMdHJ5R2V0U3RyaW5nAQkArAICAhBzZXR1cF9hdXRvc3Rha2VfBQphc3NldElkU3RyCQEHQWRkcmVzcwEBGgFXe8mo/pXWKyxgpnZg+VMjxYoQWg3vXqjbBBVzdGFrZXJTdXBwb3J0ZWRBc3NldHMJARFAZXh0ck5hdGl2ZSgxMDUzKQIFEGF1dG9zdGFrZUFkZHJlc3MCFXNldHVwX3N1cHBvcnRlZEFzc2V0cwMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECLG9ubHkgZm9yIGludGVybmFsIHNtYXJ0IGNvbnRyYWN0IGludm9jYXRpb25zAwkAAAIJALMJAgUVc3Rha2VyU3VwcG9ydGVkQXNzZXRzBQphc3NldElkU3RyBQR1bml0BQNuaWwEDGFtb3VudFN0YWtlZAkBDXRyeUdldEludGVnZXIBCQCsAgICEWF1dG9zdGFrZV9hbW91bnRfBQphc3NldElkU3RyBAhzdGFrZUludgkA/QcEBRBhdXRvc3Rha2VBZGRyZXNzAgl1bnN0YWtlTFAJAMwIAgUKYXNzZXRJZFN0cgkAzAgCBQZhbW91bnQFA25pbAUDbmlsAwkAAAIFCHN0YWtlSW52BQhzdGFrZUludgkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhFhdXRvc3Rha2VfYW1vdW50XwUKYXNzZXRJZFN0cgkAZQIFDGFtb3VudFN0YWtlZAUGYW1vdW50BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQELYWRkSW50ZXJlc3QCCmFzc2V0SWRTdHIGYW1vdW50AwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQIYb25seSBmb3Igc2VsZiBpbnZvY2F0aW9uBAZlYXJuZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICAhVhdXRvc3Rha2VfbGFzdEVhcm5lZF8FCmFzc2V0SWRTdHIECmxhc3RIZWlnaHQJAQ10cnlHZXRJbnRlZ2VyAQkArAICAhRhdXRvc3Rha2VfbGFzdEJsb2NrXwUKYXNzZXRJZFN0cgQLY2xlYW5BbW91bnQJAGsDBQZhbW91bnQAUABkBApzdGFraW5nRmVlCQBlAgUGYW1vdW50BQtjbGVhbkFtb3VudAQMc3RhdGVDaGFuZ2VzAwMJAAACBQpsYXN0SGVpZ2h0BQZoZWlnaHQGCQAAAgUGYW1vdW50AAAFA25pbAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhhhdXRvc3Rha2VfcHJlTGFzdEVhcm5lZF8FCmFzc2V0SWRTdHIFBmVhcm5lZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhdhdXRvc3Rha2VfcHJlTGFzdEJsb2NrXwUKYXNzZXRJZFN0cgUKbGFzdEhlaWdodAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhVhdXRvc3Rha2VfbGFzdEVhcm5lZF8FCmFzc2V0SWRTdHIJAGQCBQZlYXJuZWQFC2NsZWFuQW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgICFGF1dG9zdGFrZV9sYXN0QmxvY2tfBQphc3NldElkU3RyBQZoZWlnaHQFA25pbAkAzggCBQxzdGF0ZUNoYW5nZXMJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgUKYXNzZXRJZFN0cgIGX3NSYXRlCQBkAgkBDXRyeUdldEludGVnZXIBCQCsAgIFCmFzc2V0SWRTdHICBl9zUmF0ZQkAawMFB1NjYWxlMTYFC2NsZWFuQW1vdW50CQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfc3VwcGxpZWRfBQphc3NldElkU3RyCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgIEZmVlXwUKYXNzZXRJZFN0cgIIX3N0YWtpbmcJAGQCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgRmZWVfBQphc3NldElkU3RyAghfc3Rha2luZwUKc3Rha2luZ0ZlZQUDbmlsAWkBE2FkZEludGVyZXN0RVhURVJOQUwABAdhc3NldElkCAkAkQMCCAUBaQhwYXltZW50cwAAB2Fzc2V0SWQECmFzc2V0SWRTdHIJAQ5nZXRBc3NldFN0cmluZwEFB2Fzc2V0SWQECXNwbGl0dGluZwkBE2dldFJld2FyZHNTcGxpdHRpbmcBBQphc3NldElkU3RyBAZhbW91bnQJAGsDCAkAkQMCCAUBaQhwYXltZW50cwAABmFtb3VudAgFCXNwbGl0dGluZwJfMgBkBAZlYXJuZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICAhVhdXRvc3Rha2VfbGFzdEVhcm5lZF8FCmFzc2V0SWRTdHIECmxhc3RIZWlnaHQJAQ10cnlHZXRJbnRlZ2VyAQkArAICAhRhdXRvc3Rha2VfbGFzdEJsb2NrXwUKYXNzZXRJZFN0cgQMc3RhdGVDaGFuZ2VzAwMJAAACBQpsYXN0SGVpZ2h0BQZoZWlnaHQGCQAAAgUGYW1vdW50AAAFA25pbAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhhhdXRvc3Rha2VfcHJlTGFzdEVhcm5lZF8FCmFzc2V0SWRTdHIFBmVhcm5lZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhdhdXRvc3Rha2VfcHJlTGFzdEJsb2NrXwUKYXNzZXRJZFN0cgUKbGFzdEhlaWdodAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhVhdXRvc3Rha2VfbGFzdEVhcm5lZF8FCmFzc2V0SWRTdHIJAGQCBQZlYXJuZWQFBmFtb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhRhdXRvc3Rha2VfbGFzdEJsb2NrXwUKYXNzZXRJZFN0cgUGaGVpZ2h0BQNuaWwJAM4IAgUMc3RhdGVDaGFuZ2VzCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIFCmFzc2V0SWRTdHICBl9zUmF0ZQkAZAIJAQ10cnlHZXRJbnRlZ2VyAQkArAICBQphc3NldElkU3RyAgZfc1JhdGUJAGsDBQdTY2FsZTE2BQZhbW91bnQJAQ10cnlHZXRJbnRlZ2VyAQkArAICAg90b3RhbF9zdXBwbGllZF8FCmFzc2V0SWRTdHIJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwURc3RhYmxlRnVuZEFkZHJlc3MJAGsDCAkAkQMCCAUBaQhwYXltZW50cwAABmFtb3VudAgFCXNwbGl0dGluZwJfMQBkBQdhc3NldElkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgIEZmVlXwUKYXNzZXRJZFN0cgIIX3N0YWtpbmcJAGQCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgRmZWVfBQphc3NldElkU3RyAghfc3Rha2luZwkAawMICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50CAUJc3BsaXR0aW5nAl8zAGQFA25pbAFpAQdwcmVJbml0BAZ0b2tlbnMEbHR2cwNsdHMJcGVuYWx0aWVzCgEBZgIFYWNjdW0FdG9rZW4JAM4IAgUFYWNjdW0JAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgUFdG9rZW4CBl9iUmF0ZQUHU2NhbGUxNgkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICBQV0b2tlbgIGX3NSYXRlBQdTY2FsZTE2BQNuaWwDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAgphZG1pbiBvbmx5BAVyYXRlcwoAAiRsCQC1CQIFBnRva2VucwIBLAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEBZgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTIJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwJAM4IAgkAzAgCCQELU3RyaW5nRW50cnkCAgxzZXR1cF90b2tlbnMFBnRva2VucwkAzAgCCQELU3RyaW5nRW50cnkCAgpzZXR1cF9sdHZzBQRsdHZzCQDMCAIJAQtTdHJpbmdFbnRyeQICCXNldHVwX2x0cwUDbHRzCQDMCAIJAQtTdHJpbmdFbnRyeQICD3NldHVwX3BlbmFsdGllcwUJcGVuYWx0aWVzCQDMCAIJAQxCb29sZWFuRW50cnkCAgxzZXR1cF9hY3RpdmUGBQNuaWwFBXJhdGVzAWkBDGluaXROZXdUb2tlbgQFdG9rZW4DbHR2Amx0B3BlbmFsdHkDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAgphZG1pbiBvbmx5CQDMCAIJAQtTdHJpbmdFbnRyeQICDHNldHVwX3Rva2VucwkArAICCQCsAgIJAQx0cnlHZXRTdHJpbmcBAgxzZXR1cF90b2tlbnMCASwFBXRva2VuCQDMCAIJAQtTdHJpbmdFbnRyeQICCnNldHVwX2x0dnMJAKwCAgkArAICCQEMdHJ5R2V0U3RyaW5nAQIKc2V0dXBfbHR2cwIBLAUDbHR2CQDMCAIJAQtTdHJpbmdFbnRyeQICCXNldHVwX2x0cwkArAICCQCsAgIJAQx0cnlHZXRTdHJpbmcBAglzZXR1cF9sdHMCASwFAmx0CQDMCAIJAQtTdHJpbmdFbnRyeQICD3NldHVwX3BlbmFsdGllcwkArAICCQCsAgIJAQx0cnlHZXRTdHJpbmcBAg9zZXR1cF9wZW5hbHRpZXMCASwFB3BlbmFsdHkJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgUFdG9rZW4CBl9iUmF0ZQUHU2NhbGUxNgkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICBQV0b2tlbgIGX3NSYXRlBQdTY2FsZTE2BQNuaWwBaQEPdXBkYXRlUGFyYW1ldGVyAgNrZXkDdmFsAwMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkBAiE9AggFAWkGY2FsbGVyBQxhZG1pbkFkZHJlc3MHCQACAQIKYWRtaW4gb25seQkAzAgCCQEMSW50ZWdlckVudHJ5AgUDa2V5CQENcGFyc2VJbnRWYWx1ZQEFA3ZhbAUDbmlsAWkBDHVwZGF0ZVN0cmluZwIDa2V5A3ZhbAMDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAQIhPQIIBQFpBmNhbGxlcgUMYWRtaW5BZGRyZXNzBwkAAgECCmFkbWluIG9ubHkJAMwIAgkBC1N0cmluZ0VudHJ5AgUDa2V5BQN2YWwFA25pbAFpARJjbGFpbVRvUmVzZXJ2ZUZ1bmQBBWRlYnVnBAZhc3NldHMJAQ9nZXRNYXJrZXRBc3NldHMABAVyYXRlcwgJAQ1nZXRBY3R1YWxSYXRlAgkAkQMCBQZhc3NldHMAAAIFc1JhdGUCXzIEAmxpCQDMCAIAAAkAzAgCAAEJAMwIAgACCQDMCAIAAwkAzAgCAAQJAMwIAgAFCQDMCAIABgkAzAgCAAcJAMwIAgAICQDMCAIACQkAzAgCAAoJAMwIAgALBQNuaWwKAQFmAgVhY2N1bQFuAwkAZwIFAW4JAJADAQUGYXNzZXRzBQVhY2N1bQQKYXNzZXRJZFN0cgkAkQMCBQZhc3NldHMFAW4EBmFtb3VudAkAZQIJAGQCCQBkAgkBCmdldEJhbGFuY2UBBQphc3NldElkU3RyCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIRYXV0b3N0YWtlX2Ftb3VudF8FCmFzc2V0SWRTdHIJAGsDCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfYm9ycm93ZWRfBQphc3NldElkU3RyCAkAkQMCBQVyYXRlcwkAZAIJAGgCBQFuAAMAAQV2YWx1ZQUHU2NhbGUxNgkAawMJAQ10cnlHZXRJbnRlZ2VyAQkArAICAg90b3RhbF9zdXBwbGllZF8FCmFzc2V0SWRTdHIICQCRAwIFBXJhdGVzCQBoAgUBbgADBXZhbHVlBQdTY2FsZTE2BANpbnYDCQECIT0CCQEMdHJ5R2V0U3RyaW5nAQkArAICAhBzZXR1cF9hdXRvc3Rha2VfBQphc3NldElkU3RyAgAJAPwHBAUEdGhpcwIMdW5zdGFrZVRva2VuCQDMCAIFCmFzc2V0SWRTdHIJAMwIAgUGYW1vdW50BQNuaWwFA25pbAUEdW5pdAMJAAACBQNpbnYFA2ludgkAzggCBQVhY2N1bQkAzAgCBQZhbW91bnQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgQJcGFyYW1ldGVyCgACJGwFAmxpCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQFmAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMgkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAoBAmYyAgVhY2N1bQFuAwkAZwIFAW4JAJADAQUGYXNzZXRzBQVhY2N1bQQKYXNzZXRJZFN0cgkAkQMCBQZhc3NldHMFAW4JAM4IAgUFYWNjdW0JAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUScmVzZXJ2ZUZ1bmRBZGRyZXNzCQCWAwEJAMwIAgkAkQMCBQlwYXJhbWV0ZXIFAW4JAMwIAgAABQNuaWwJAQ1nZXRBc3NldEJ5dGVzAQUKYXNzZXRJZFN0cgUDbmlsAwUFZGVidWcJAAIBCQEKbGlJbnRUb1N0cgEFCXBhcmFtZXRlcgkAlAoCCgACJGwFAmxpCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYxXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQJmMgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMV8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTIJAQUkZjFfMgIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwFCXBhcmFtZXRlcgFpAQljbGFpbUZlZXMBCmFzc2V0SWRTdHIDCQAAAgkAnQgCBQR0aGlzAhpzZXR1cF9hZGRyZXNzX2ZlZUNvbGxlY3RvcgUEdW5pdAkAAgECHGZlZSBjb2xsZWN0b3Igbm90IGNvbmZpZ3VyZWQECGlzU3Rha2VkCQECIT0CCQEMdHJ5R2V0U3RyaW5nAQkArAICAhBzZXR1cF9hdXRvc3Rha2VfBQphc3NldElkU3RyAgAEBXJhdGVzCQEQdG9rZW5SYXRlc1JlY2FsYwEFCmFzc2V0SWRTdHIEBXNSYXRlCAkAkQMCBQVyYXRlcwAABXZhbHVlBAViUmF0ZQgJAJEDAgUFcmF0ZXMAAQV2YWx1ZQQDYmFsCQEKZ2V0QmFsYW5jZQEFCmFzc2V0SWRTdHIEA2xpcQkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIEZmVlXwUKYXNzZXRJZFN0cgIMX2xpcXVpZGF0aW9uBANzdGsJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICBGZlZV8FCmFzc2V0SWRTdHICCF9zdGFraW5nBAhpbnRlcmVzdAMFCGlzU3Rha2VkAAAJAJYDAQkAzAgCCQBlAgkAZQIJAGUCCQBkAgUDYmFsCQBrAwkBDXRyeUdldEludGVnZXIBCQCsAgICD3RvdGFsX2JvcnJvd2VkXwUKYXNzZXRJZFN0cgUFYlJhdGUFB1NjYWxlMTYJAGsDCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfc3VwcGxpZWRfBQphc3NldElkU3RyBQVzUmF0ZQUHU2NhbGUxNgUDbGlxBQNzdGsJAMwIAgAABQNuaWwEA3BheQkAlwMBCQDMCAIJAGQCCQBkAgUIaW50ZXJlc3QFA3N0awUDbGlxCQDMCAIFA2JhbAUDbmlsAwkAZwIAAAUDcGF5BQVyYXRlcwQEbGlxUAkAlwMBCQDMCAIFA2xpcQkAzAgCBQNwYXkFA25pbAQEc3RrUAkAlwMBCQDMCAIFA3N0awkAzAgCCQBlAgUDcGF5BQRsaXFQBQNuaWwECWludGVyZXN0UAkAZQIJAGUCBQNwYXkFBGxpcVAFBHN0a1AECXJlY29yZEludgkA/AcEBRNmZWVDb2xsZWN0b3JBZGRyZXNzAgtwcm9jZXNzRmVlcwkAzAgCBQphc3NldElkU3RyCQDMCAIFCWludGVyZXN0UAkAzAgCBQRzdGtQCQDMCAIFBGxpcVAFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBDWdldEFzc2V0Qnl0ZXMBBQphc3NldElkU3RyBQNwYXkFA25pbAMJAAACBQlyZWNvcmRJbnYFCXJlY29yZEludgkAzggCBQVyYXRlcwkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgICBGZlZV8FCmFzc2V0SWRTdHICDF9saXF1aWRhdGlvbgkAZQIFA2xpcQUEbGlxUAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgICBGZlZV8FCmFzc2V0SWRTdHICCF9zdGFraW5nCQBlAgUDc3RrBQRzdGtQBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEMY2xhaW1GZWVzQWxsAQp0b2tlbnNMaXN0BAZ0b2tlbnMDCQAAAgUKdG9rZW5zTGlzdAIACQEPZ2V0TWFya2V0QXNzZXRzAAkAtQkCBQp0b2tlbnNMaXN0AgEsCgEBZgIFYWNjdW0FdG9rZW4EA2ludgkA/AcEBQR0aGlzAgljbGFpbUZlZXMJAMwIAgUFdG9rZW4FA25pbAUDbmlsAwkAAAIFA2ludgUDaW52BQVhY2N1bQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgQEZG9uZQoAAiRsBQZ0b2tlbnMKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQR1bml0CgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQFmAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMgkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAMJAAACBQRkb25lBQRkb25lBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEHcmVTZXR1cAEKYXNzZXRJZFN0cgQLbGFzdFJlc2V0dXAJAQ10cnlHZXRJbnRlZ2VyAQIScmVzZXR1cF9sYXN0VXBkYXRlAwkAZgIFCWRheUJsb2NrcwkAZQIFBmhlaWdodAULbGFzdFJlc2V0dXAJAAIBAiBjYW4gYmUgdXBkYXRlZCBvbmx5IG9uY2UgcGVyIGRheQQDbHRzCQC1CQIJAQx0cnlHZXRTdHJpbmcBAglzZXR1cF9sdHMCASwEBmFzc2V0cwkBD2dldE1hcmtldEFzc2V0cwAEAnVyCQEFZ2V0VXIBBQphc3NldElkU3RyBAZ0ZW1wTFQJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICBnNldHVwXwUKYXNzZXRJZFN0cgIHX3RlbXBMVAQCbHQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQZhc3NldHMJAQV2YWx1ZQEJAM8IAgUGYXNzZXRzBQphc3NldElkU3RyAwkAZgIFAnVyAICV9SoJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkArAICAgZzZXR1cF8FCmFzc2V0SWRTdHICB190ZW1wTFQJAGsDBQZ0ZW1wTFQA900AkE4FA25pbAMDCQBmAgUCbHQFBnRlbXBMVAkAZgIAgJX1KgUCdXIHCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgIGc2V0dXBfBQphc3NldElkU3RyAgdfdGVtcExUCQBrAwUGdGVtcExUAKlOAJBOBQNuaWwFA25pbAFpAQhzaHV0ZG93bgEIc2h1dGRvd24DCQAAAgkAzwgCBRFzaHV0ZG93bldoaXRlbGlzdAgFAWkGY2FsbGVyBQR1bml0CQACAQIXdXNlciBub3QgaW4gYSB3aGl0ZWxpc3QJAMwIAgkBDEJvb2xlYW5FbnRyeQICDHNldHVwX2FjdGl2ZQkBASEBBQhzaHV0ZG93bgUDbmlsAWkBCWxpcXVpZGF0ZQYFZGVidWcHYWRkcmVzcwthc3NldEFtb3VudAtzQXNzZXRJZFN0cgtiQXNzZXRJZFN0cghyb3V0ZVN0cgMJAQEhAQkBFnZlcmlmeUxpcXVpZGF0b3JSaWdodHMBCAUBaQZjYWxsZXIJAAIBAih0ZW1wb3JhcmlseSBhdmFpbGFibGUgZm9yIHdoaXRlbGlzdCBvbmx5AwkBASEBCQENdHJ5R2V0Qm9vbGVhbgECDHNldHVwX2FjdGl2ZQkAAgECEW1hcmtldCBpcyBzdG9wcGVkBA51c2VyQ29sbGF0ZXJhbAkBEmNhbGNVc2VyQ29sbGF0ZXJhbAEFB2FkZHJlc3MDCQAAAgUOdXNlckNvbGxhdGVyYWwFDnVzZXJDb2xsYXRlcmFsBA0kdDAzNDY2ODM0NzMwCQENZ2V0QWN0dWFsUmF0ZQIFC3NBc3NldElkU3RyAgVzUmF0ZQQFc1JhdGUIBQ0kdDAzNDY2ODM0NzMwAl8xBAtyYXRlc1Jlc3VsdAgFDSR0MDM0NjY4MzQ3MzACXzIEDSR0MDM0NzM1MzQ4MDQJAQ1nZXRBY3R1YWxSYXRlAgULYkFzc2V0SWRTdHICBWJSYXRlBAViUmF0ZQgFDSR0MDM0NzM1MzQ4MDQCXzEEEnJhdGVzUmVjYWxjUmVzdWx0MggFDSR0MDM0NzM1MzQ4MDQCXzIEDHNBc3NldEFtb3VudAkAawMFC2Fzc2V0QW1vdW50BQdTY2FsZTE2BQVzUmF0ZQQQY3VycmVudFNQb3NpdGlvbgkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgUHYWRkcmVzcwIKX3N1cHBsaWVkXwULc0Fzc2V0SWRTdHIEE2N1cnJlbnRCUG9zaXRpb25WYWwJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgIFB2FkZHJlc3MCCl9ib3Jyb3dlZF8FC2JBc3NldElkU3RyBBBjdXJyZW50QlBvc2l0aW9uAwkAZgIFE2N1cnJlbnRCUG9zaXRpb25WYWwAAAUTY3VycmVudEJQb3NpdGlvblZhbAkAAgECIHVzZXIgaGFzIG5vIGJvcnJvdyBpbiB0aGlzIHRva2VuAwkAZgIFDnVzZXJDb2xsYXRlcmFsAAAJAAIBAhh1c2VyIGNhbid0IGJlIGxpcXVpZGF0ZWQDCQBmAgUMc0Fzc2V0QW1vdW50BRBjdXJyZW50U1Bvc2l0aW9uCQACAQIycG9zaXRpb24gdG8gbGlxdWlkYXRlIGlzIGJpZ2dlciB0aGFuIHVzZXIncyBzdXBwbHkEA2ludgMJAQIhPQIJAQx0cnlHZXRTdHJpbmcBCQCsAgICEHNldHVwX2F1dG9zdGFrZV8FC3NBc3NldElkU3RyAgAJAPwHBAUEdGhpcwIMdW5zdGFrZVRva2VuCQDMCAIFC3NBc3NldElkU3RyCQDMCAIFDHNBc3NldEFtb3VudAUDbmlsBQNuaWwFBHVuaXQDCQAAAgUDaW52BQNpbnYEDmJhbGFuY2UwQmVmb3JlCQEKZ2V0QmFsYW5jZQEFC3NBc3NldElkU3RyAwkAAAIFDmJhbGFuY2UwQmVmb3JlBQ5iYWxhbmNlMEJlZm9yZQQOYmFsYW5jZTFCZWZvcmUJAQpnZXRCYWxhbmNlAQULYkFzc2V0SWRTdHIDCQAAAgUOYmFsYW5jZTFCZWZvcmUFDmJhbGFuY2UxQmVmb3JlBA5leGNoYW5nZUludm9rZQkA/AcEBRFhZ2dyZWdhdG9yQWRkcmVzcwIEc3dhcAkAzAgCBQhyb3V0ZVN0cgkAzAgCAAAFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBDWdldEFzc2V0Qnl0ZXMBBQtzQXNzZXRJZFN0cgULYXNzZXRBbW91bnQFA25pbAMJAAACBQ5leGNoYW5nZUludm9rZQUOZXhjaGFuZ2VJbnZva2UECmFzc2V0MFNvbGQJAGUCBQ5iYWxhbmNlMEJlZm9yZQkBCmdldEJhbGFuY2UBBQtzQXNzZXRJZFN0cgMJAAACBQphc3NldDBTb2xkBQphc3NldDBTb2xkBAxhc3NldDFCb3VnaHQJAGUCCQEKZ2V0QmFsYW5jZQEFC2JBc3NldElkU3RyBQ5iYWxhbmNlMUJlZm9yZQMJAAACBQxhc3NldDFCb3VnaHQFDGFzc2V0MUJvdWdodAQLYXNzZXQwUHJpY2UICQETZ2V0VG9rZW5QcmljZUNhcHBlZAEFC3NBc3NldElkU3RyAl8xBAthc3NldDBTY2FsZQkBDmNhbGNBc3NldFNjYWxlAQULc0Fzc2V0SWRTdHIECWFzc2V0MFVzZAkAawMFCmFzc2V0MFNvbGQFC2Fzc2V0MFByaWNlBQthc3NldDBTY2FsZQQLYXNzZXQxUHJpY2UICQETZ2V0VG9rZW5QcmljZUNhcHBlZAEFC2JBc3NldElkU3RyAl8yBAthc3NldDFTY2FsZQkBDmNhbGNBc3NldFNjYWxlAQULYkFzc2V0SWRTdHIECWFzc2V0MVVzZAkAawMFDGFzc2V0MUJvdWdodAULYXNzZXQxUHJpY2UFC2Fzc2V0MVNjYWxlBAdwZW5hbHR5CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgkAtQkCCQEMdHJ5R2V0U3RyaW5nAQIPc2V0dXBfcGVuYWx0aWVzAgEsCQEFdmFsdWUBCQDPCAIJAQ9nZXRNYXJrZXRBc3NldHMABQtiQXNzZXRJZFN0cgQRbGlxdWlkYXRpb25Qcm9maXQJAGUCBQlhc3NldDFVc2QJAGsDBQlhc3NldDBVc2QJAGUCBQZTY2FsZTgFB3BlbmFsdHkFBlNjYWxlOAQMc0Fzc2V0Q2hhbmdlCQBrAwUKYXNzZXQwU29sZAUHU2NhbGUxNgUFc1JhdGUEDGJBc3NldENoYW5nZQkAawMJAGsDBQxhc3NldDFCb3VnaHQFB1NjYWxlMTYFBWJSYXRlCQBlAgUGU2NhbGU4CQBrAwURbGlxdWlkYXRpb25Qcm9maXQFBlNjYWxlOAUJYXNzZXQxVXNkBQZTY2FsZTgDCQBmAgUKYXNzZXQwU29sZAULYXNzZXRBbW91bnQJAAIBAiNtb3JlIGFzc2V0cyBleGNoYW5nZWQgdGhhbiBleHBlY3RlZAMJAGYCAAAFEWxpcXVpZGF0aW9uUHJvZml0CQACAQIvcHJpY2UgaW1wYWN0IGlzIGJpZ2dlciB0aGFuIGxpcXVpZGF0aW9uIHBlbmFsdHkJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkArAICBQdhZGRyZXNzAgpfc3VwcGxpZWRfBQtzQXNzZXRJZFN0cgkAZQIFEGN1cnJlbnRTUG9zaXRpb24FDHNBc3NldENoYW5nZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgIFB2FkZHJlc3MCCl9ib3Jyb3dlZF8FC2JBc3NldElkU3RyCQBlAgUQY3VycmVudEJQb3NpdGlvbgUMYkFzc2V0Q2hhbmdlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgICD3RvdGFsX3N1cHBsaWVkXwULc0Fzc2V0SWRTdHIJAGUCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfc3VwcGxpZWRfBQtzQXNzZXRJZFN0cgUMc0Fzc2V0Q2hhbmdlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgICD3RvdGFsX2JvcnJvd2VkXwULYkFzc2V0SWRTdHIJAGUCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfYm9ycm93ZWRfBQtiQXNzZXRJZFN0cgUMYkFzc2V0Q2hhbmdlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgIEZmVlXwULYkFzc2V0SWRTdHICDF9saXF1aWRhdGlvbgkAZAIJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICBGZlZV8FC2JBc3NldElkU3RyAgxfbGlxdWlkYXRpb24JAGUCBQxhc3NldDFCb3VnaHQJAGsDBQxiQXNzZXRDaGFuZ2UFBWJSYXRlBQdTY2FsZTE2BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQELbGlxdWlkYXRlVjIDBWRlYnVnB2FkZHJlc3MLc0Fzc2V0SWRTdHIDCQEBIQEJARZ2ZXJpZnlMaXF1aWRhdG9yUmlnaHRzAQgFAWkGY2FsbGVyCQACAQIodGVtcG9yYXJpbHkgYXZhaWxhYmxlIGZvciB3aGl0ZWxpc3Qgb25seQMJAQEhAQkBDXRyeUdldEJvb2xlYW4BAgxzZXR1cF9hY3RpdmUJAAIBAhFtYXJrZXQgaXMgc3RvcHBlZAQIYkFzc2V0SWQICQCRAwIIBQFpCHBheW1lbnRzAAAHYXNzZXRJZAQLYkFzc2V0SWRTdHIJAQ5nZXRBc3NldFN0cmluZwEFCGJBc3NldElkBAxiQXNzZXRBbW91bnQICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50BA51c2VyQ29sbGF0ZXJhbAkBEmNhbGNVc2VyQ29sbGF0ZXJhbAEFB2FkZHJlc3MDCQAAAgUOdXNlckNvbGxhdGVyYWwFDnVzZXJDb2xsYXRlcmFsAwkAZgIFDnVzZXJDb2xsYXRlcmFsAAAJAAIBAhh1c2VyIGNhbid0IGJlIGxpcXVpZGF0ZWQEDG1hcmtldEFzc2V0cwkBD2dldE1hcmtldEFzc2V0cwAECWFzc2V0MU51bQkBBXZhbHVlAQkAzwgCBQxtYXJrZXRBc3NldHMFC2JBc3NldElkU3RyBAlhc3NldDBOdW0JAQV2YWx1ZQEJAM8IAgUMbWFya2V0QXNzZXRzBQtzQXNzZXRJZFN0cgQNJHQwMzg0MjUzODQ4NwkBDWdldEFjdHVhbFJhdGUCBQtiQXNzZXRJZFN0cgIFYlJhdGUEBWJSYXRlCAUNJHQwMzg0MjUzODQ4NwJfMQQLcmF0ZXNSZXN1bHQIBQ0kdDAzODQyNTM4NDg3Al8yBAthc3NldDFQcmljZQgJARNnZXRUb2tlblByaWNlQ2FwcGVkAQULYkFzc2V0SWRTdHICXzIEC2Fzc2V0MVNjYWxlCQEOY2FsY0Fzc2V0U2NhbGUBBQtiQXNzZXRJZFN0cgQKYkFtb3VudFVzZAkAawMFDGJBc3NldEFtb3VudAULYXNzZXQxUHJpY2UFC2Fzc2V0MVNjYWxlBAdwZW5hbHR5CQENcGFyc2VJbnRWYWx1ZQEJAQV2YWx1ZQEJAJEDAgkAtQkCCQEMdHJ5R2V0U3RyaW5nAQIPc2V0dXBfcGVuYWx0aWVzAgEsBQlhc3NldDFOdW0EC2Fzc2V0MFByaWNlCAkBE2dldFRva2VuUHJpY2VDYXBwZWQBBQtzQXNzZXRJZFN0cgJfMQQLYXNzZXQwU2NhbGUJAQ5jYWxjQXNzZXRTY2FsZQEFC3NBc3NldElkU3RyBApzQW1vdW50VXNkCQBrAwUKYkFtb3VudFVzZAkAZAIFBlNjYWxlOAUHcGVuYWx0eQUGU2NhbGU4BAxzQXNzZXRBbW91bnQJAGsDBQpzQW1vdW50VXNkBQthc3NldDBTY2FsZQULYXNzZXQwUHJpY2UEB2JBbW91bnQJAGsDBQxiQXNzZXRBbW91bnQFB1NjYWxlMTYFBWJSYXRlBAdzQW1vdW50CQBrAwUMc0Fzc2V0QW1vdW50BQdTY2FsZTE2CAkAkQMCBQtyYXRlc1Jlc3VsdAkAaAIFCWFzc2V0ME51bQADBXZhbHVlBBBjdXJyZW50U1Bvc2l0aW9uCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICBQdhZGRyZXNzAgpfc3VwcGxpZWRfBQtzQXNzZXRJZFN0cgQTY3VycmVudEJQb3NpdGlvblZhbAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgUHYWRkcmVzcwIKX2JvcnJvd2VkXwULYkFzc2V0SWRTdHIEEGN1cnJlbnRCUG9zaXRpb24DCQBmAgUTY3VycmVudEJQb3NpdGlvblZhbAAABRNjdXJyZW50QlBvc2l0aW9uVmFsCQACAQIgdXNlciBoYXMgbm8gYm9ycm93IGluIHRoaXMgdG9rZW4DCQBmAgUHc0Ftb3VudAUQY3VycmVudFNQb3NpdGlvbgkAAgECMnBvc2l0aW9uIHRvIGxpcXVpZGF0ZSBpcyBiaWdnZXIgdGhhbiB1c2VyJ3Mgc3VwcGx5BANpbnYDCQECIT0CCQEMdHJ5R2V0U3RyaW5nAQkArAICAhBzZXR1cF9hdXRvc3Rha2VfBQtzQXNzZXRJZFN0cgIACQD8BwQFBHRoaXMCDHVuc3Rha2VUb2tlbgkAzAgCBQtzQXNzZXRJZFN0cgkAzAgCBQxzQXNzZXRBbW91bnQFA25pbAUDbmlsBQR1bml0AwkAAAIFA2ludgUDaW52AwUFZGVidWcJAAIBAhVsaXF1aWRhdGlvbiB3aWxsIHBhc3MJAM4IAgkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIFDHNBc3NldEFtb3VudAkBDWdldEFzc2V0Qnl0ZXMBBQtzQXNzZXRJZFN0cgkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgIFB2FkZHJlc3MCCl9zdXBwbGllZF8FC3NBc3NldElkU3RyCQBlAgUQY3VycmVudFNQb3NpdGlvbgUHc0Ftb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgIFB2FkZHJlc3MCCl9ib3Jyb3dlZF8FC2JBc3NldElkU3RyCQBlAgUQY3VycmVudEJQb3NpdGlvbgUHYkFtb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAg90b3RhbF9zdXBwbGllZF8FC3NBc3NldElkU3RyCQBlAgkBDXRyeUdldEludGVnZXIBCQCsAgICD3RvdGFsX3N1cHBsaWVkXwULc0Fzc2V0SWRTdHIFB3NBbW91bnQJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgIPdG90YWxfYm9ycm93ZWRfBQtiQXNzZXRJZFN0cgkAZQIJAQ10cnlHZXRJbnRlZ2VyAQkArAICAg90b3RhbF9ib3Jyb3dlZF8FC2JBc3NldElkU3RyBQdiQW1vdW50BQNuaWwFC3JhdGVzUmVzdWx0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBEWdldFVzZXJDb2xsYXRlcmFsBAVkZWJ1ZwdhZGRyZXNzDW1pbnVzQm9ycm93ZWQLYWZ0ZXJDaGFuZ2UEBmFzc2V0cwkBD2dldE1hcmtldEFzc2V0cwAEBGx0dnMJALUJAgkBDHRyeUdldFN0cmluZwECCnNldHVwX2x0dnMCASwEA2x0cwkAtQkCCQEMdHJ5R2V0U3RyaW5nAQIJc2V0dXBfbHRzAgEsBAVyYXRlcwgJAQ1nZXRBY3R1YWxSYXRlAgkAkQMCBQZhc3NldHMAAAIFc1JhdGUCXzIEDWNoYW5nZUhhbmRsZXIJALUJAgULYWZ0ZXJDaGFuZ2UCASwKAQFmAgVhY2N1bQRuZXh0AwkAZwIFBG5leHQJAJADAQUGYXNzZXRzBQVhY2N1bQQMdXNlclN1cHBsaWVkCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICBQdhZGRyZXNzAgpfc3VwcGxpZWRfCQCRAwIFBmFzc2V0cwUEbmV4dAQMdXNlckJvcnJvd2VkCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICBQdhZGRyZXNzAgpfYm9ycm93ZWRfCQCRAwIFBmFzc2V0cwUEbmV4dAQTbmVlZFRva2VuQWNjb3VudGluZwMJAAACBQthZnRlckNoYW5nZQIAAwMJAQIhPQIFDHVzZXJCb3Jyb3dlZAAABgkBAiE9AgUMdXNlclN1cHBsaWVkAAAGBwYDBRNuZWVkVG9rZW5BY2NvdW50aW5nBAphc3NldFNjYWxlCQEOY2FsY0Fzc2V0U2NhbGUBCQCRAwIFBmFzc2V0cwUEbmV4dAQKYXNzZXRQcmljZQkBE2dldFRva2VuUHJpY2VDYXBwZWQBCQCRAwIFBmFzc2V0cwUEbmV4dAkAZQIJAGQCBQVhY2N1bQkAawMJAGsDCQBrAwkAZAIFDHVzZXJTdXBwbGllZAMDAwkBAiE9AgULYWZ0ZXJDaGFuZ2UCAAkAAAIJAJEDAgUNY2hhbmdlSGFuZGxlcgAACQCRAwIFBmFzc2V0cwUEbmV4dAcJAAACCQCRAwIFDWNoYW5nZUhhbmRsZXIAAQIIc3VwcGxpZWQHCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUNY2hhbmdlSGFuZGxlcgACAAAICQCRAwIFBXJhdGVzCQBoAgUEbmV4dAADBXZhbHVlBQdTY2FsZTE2CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUEbHR2cwUEbmV4dAUGU2NhbGU4CAUKYXNzZXRQcmljZQJfMQUKYXNzZXRTY2FsZQMFDW1pbnVzQm9ycm93ZWQJAGsDCQBrAwkAawMJAGQCBQx1c2VyQm9ycm93ZWQDAwMJAQIhPQIFC2FmdGVyQ2hhbmdlAgAJAAACCQCRAwIFDWNoYW5nZUhhbmRsZXIAAAkAkQMCBQZhc3NldHMFBG5leHQHCQAAAgkAkQMCBQ1jaGFuZ2VIYW5kbGVyAAECCGJvcnJvd2VkBwkBDXBhcnNlSW50VmFsdWUBCQCRAwIFDWNoYW5nZUhhbmRsZXIAAgAACAkAkQMCBQVyYXRlcwkAZAIJAGgCBQRuZXh0AAMAAQV2YWx1ZQUHU2NhbGUxNgUGU2NhbGU4CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUDbHRzBQRuZXh0CAUKYXNzZXRQcmljZQJfMgUKYXNzZXRTY2FsZQAABQVhY2N1bQQGcmVzdWx0CgACJGwJAMwIAgAACQDMCAIAAQkAzAgCAAIJAMwIAgADCQDMCAIABAkAzAgCAAUJAMwIAgAGCQDMCAIABwkAzAgCAAgJAMwIAgAJCQDMCAIACgkAzAgCAAsFA25pbAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAAAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEBZgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTIJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwDBQVkZWJ1ZwkAAgEJAKQDAQUGcmVzdWx0CQCUCgIFBXJhdGVzBQZyZXN1bHQBaQEJZ2V0UHJpY2VzAQVkZWJ1ZwQGYXNzZXRzCQEPZ2V0TWFya2V0QXNzZXRzAAoBAWYCBWFjY3VtBG5leHQDCQBnAgUEbmV4dAkAkAMBBQZhc3NldHMFBWFjY3VtBAphc3NldFByaWNlCQEVZ2V0VG9rZW5QcmljZVdpdGhSaXNrAgkAkQMCBQZhc3NldHMFBG5leHQAAwkArAICCQCsAgIJAKwCAgkArAICBQVhY2N1bQkApAMBCAUKYXNzZXRQcmljZQJfMQIBLAkApAMBCAUKYXNzZXRQcmljZQJfMgIBfAQGcmVzdWx0CgACJGwJAMwIAgAACQDMCAIAAQkAzAgCAAIJAMwIAgADCQDMCAIABAkAzAgCAAUJAMwIAgAGCQDMCAIABwkAzAgCAAgJAMwIAgAJCQDMCAIACgkAzAgCAAsFA25pbAoAAiRzCQCQAwEFAiRsCgAFJGFjYzACAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEBZgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTIJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwDBQVkZWJ1ZwkAAgEFBnJlc3VsdAkAlAoCBQNuaWwFBnJlc3VsdAFpARljYWxjdWxhdGVVdGlsaXphdGlvblJhdGlvAgphc3NldElkU3RyBWRlYnVnAwUFZGVidWcJAAIBCQCkAwEJAQVnZXRVcgEFCmFzc2V0SWRTdHIJAJQKAgUDbmlsCQEFZ2V0VXIBBQphc3NldElkU3RyAWkBE2NhbGN1bGF0ZU91dGRhdGVkVVICCmFzc2V0SWRTdHIFZGVidWcDBQVkZWJ1ZwkAAgEJAKQDAQkBDWdldE91dGRhdGVkVXIBBQphc3NldElkU3RyCQCUCgIFA25pbAkBDWdldE91dGRhdGVkVXIBBQphc3NldElkU3RyAWkBE2NhbGN1bGF0ZVRva2VuUmF0ZXMBBWRlYnVnCgEBZgIFYWNjdW0KYXNzZXRJZFN0cgQFcmF0ZXMJARB0b2tlblJhdGVzUmVjYWxjAQUKYXNzZXRJZFN0cgkAlAoCCQCsAgIJAKwCAgkArAICCQCsAgIIBQVhY2N1bQJfMQkApAMBCAkAkQMCBQVyYXRlcwABBXZhbHVlAgF8CQCkAwEICQCRAwIFBXJhdGVzAAAFdmFsdWUCASwJAM4IAggFBWFjY3VtAl8yBQVyYXRlcwQJcGFyYW1ldGVyCgACJGwJAQ9nZXRNYXJrZXRBc3NldHMACgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlAoCAgAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEBZgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTIJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwDBQVkZWJ1ZwkAAgEIBQlwYXJhbWV0ZXICXzEJAJQKAggFCXBhcmFtZXRlcgJfMggFCXBhcmFtZXRlcgJfMQFpARdjYWxjdWxhdGVUb2tlbnNJbnRlcmVzdAEFZGVidWcKAQFmAgVhY2N1bQphc3NldElkU3RyBARyYXRlCQBrAwkBC2dldEludGVyZXN0AQUKYXNzZXRJZFN0cgUJZGF5QmxvY2tzBQZTY2FsZTgJAKwCAgkArAICBQVhY2N1bQkApAMBBQRyYXRlAgEsBAlwYXJhbWV0ZXIKAAIkbAkBD2dldE1hcmtldEFzc2V0cwAKAAIkcwkAkAMBBQIkbAoABSRhY2MwAgAKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBAWYCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEyCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAwUFZGVidWcJAAIBBQlwYXJhbWV0ZXIJAJQKAgUDbmlsBQlwYXJhbWV0ZXIBaQESc2V0QXBwcm92ZXJBZGRyZXNzAQ9hcHByb3ZlckFkZHJlc3MEBmlzU2VsZgMJAAACCAUBaQZjYWxsZXIFBHRoaXMGCQACAQIQT25seSBzZWxmIGludm9rZQMJAAACBQZpc1NlbGYFBmlzU2VsZgQQX2FwcHJvdmVyQWRkcmVzcwkApggBBQ9hcHByb3ZlckFkZHJlc3MECmFwcHJvdmVyT2sEByRtYXRjaDAFEF9hcHByb3ZlckFkZHJlc3MDCQABAgUHJG1hdGNoMAIHQWRkcmVzcwQBdAUHJG1hdGNoMAYHBA5jYW5TZXRBcHByb3ZlcgMDBQphcHByb3Zlck9rBgkAAAIFD2FwcHJvdmVyQWRkcmVzcwIABgkAAgECFldyb25nIGFwcHJvdmVyIGFkZHJlc3MDCQAAAgUOY2FuU2V0QXBwcm92ZXIFDmNhblNldEFwcHJvdmVyBAhpc0luaXRlZAkBC3ZhbHVlT3JFbHNlAgkAmwgCCQEFdmFsdWUBBRBfYXBwcm92ZXJBZGRyZXNzAgZJTklURUQHBAloYXNBZG1pbnMJAQIhPQIJAQt2YWx1ZU9yRWxzZQIJAJ0IAgkBBXZhbHVlAQUQX2FwcHJvdmVyQWRkcmVzcwILQURNSU5TX1BCS1MCAAIABBJpc0FwcHJvdmVyQ29udHJhY3QDAwkAAAIFD2FwcHJvdmVyQWRkcmVzcwIABgMFCGlzSW5pdGVkBQloYXNBZG1pbnMHBgkAAgECIEFkZHJlc3MgaXMgbm90IGFwcHJvdmVyIGNvbnRyYWN0AwkAAAIFEmlzQXBwcm92ZXJDb250cmFjdAUSaXNBcHByb3ZlckNvbnRyYWN0CQDMCAIJAQtTdHJpbmdFbnRyeQICEEFQUFJPVkVSX0FERFJFU1MFD2FwcHJvdmVyQWRkcmVzcwUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDWluaXROZXdNYXN0ZXIBBm1hc3RlcgQJYWRkcmVzc09LBAckbWF0Y2gwCQCmCAEFBm1hc3RlcgMJAAECBQckbWF0Y2gwAgdBZGRyZXNzBAFhBQckbWF0Y2gwBgcDCQEBIQEFCWFkZHJlc3NPSwkAAgEJAKwCAgISaW5jb3JyZWN0IGFkZHJlc3MgBQZtYXN0ZXIDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAhxhdmFpbGFibGUgZm9yIHNlbGYgY2FsbCBvbmx5CQDMCAIJAQtTdHJpbmdFbnRyeQICD3ZlcmlmaWVyX21hc3RlcgUGbWFzdGVyBQNuaWwBaQEQcmVxdWVzdE5ld01hc3RlcgEJbmV3TWFzdGVyBAlhZGRyZXNzT0sEByRtYXRjaDAJAKYIAQUJbmV3TWFzdGVyAwkAAQIFByRtYXRjaDACB0FkZHJlc3MEAWEFByRtYXRjaDAGBwMJAQEhAQUJYWRkcmVzc09LCQACAQkArAICAhJpbmNvcnJlY3QgYWRkcmVzcyAFCW5ld01hc3RlcgMJAAACCQDPCAIFCXNlbnRpbmVscwgFAWkGY2FsbGVyBQR1bml0CQACAQIOd2hpdGVsaXN0IG9ubHkJAMwIAgkBC1N0cmluZ0VudHJ5AgISdmVyaWZpZXJfbmV3TWFzdGVyBQluZXdNYXN0ZXIJAMwIAgkBDEludGVnZXJFbnRyeQICH3ZlcmlmaWVyX25ld01hc3RlckVsaWdpYmxlQWZ0ZXIJAGQCBQZoZWlnaHQAkE4FA25pbAFpARFhY3RpdmF0ZU5ld01hc3RlcgAEDmVsaWdpYmxlSGVpZ2h0CQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzAh92ZXJpZmllcl9uZXdNYXN0ZXJFbGlnaWJsZUFmdGVyBAluZXdNYXN0ZXIJARFAZXh0ck5hdGl2ZSgxMDUzKQIFBHRoaXMCEnZlcmlmaWVyX25ld01hc3RlcgMJAAACCQDPCAIFCXNlbnRpbmVscwgFAWkGY2FsbGVyBQR1bml0CQACAQIOd2hpdGVsaXN0IG9ubHkDCQBmAgUOZWxpZ2libGVIZWlnaHQFBmhlaWdodAkAAgECIm5ldyBtYXN0ZXIgY2Fubm90IGJlIGFjdGl2YXRlZCB5ZXQJAMwIAgkBC0RlbGV0ZUVudHJ5AQISdmVyaWZpZXJfbmV3TWFzdGVyCQDMCAIJAQtEZWxldGVFbnRyeQECH3ZlcmlmaWVyX25ld01hc3RlckVsaWdpYmxlQWZ0ZXIJAMwIAgkBC1N0cmluZ0VudHJ5AgIPdmVyaWZpZXJfbWFzdGVyBQluZXdNYXN0ZXIFA25pbAECdHgBBnZlcmlmeQAEC211bHRpc2lnU3RyCQELdmFsdWVPckVsc2UCCQCiCAECEEFQUFJPVkVSX0FERFJFU1MCAAQPbXVsdGlzaWdBZGRyZXNzCQCmCAEFC211bHRpc2lnU3RyBAptdWx0aXNpZ09rBAckbWF0Y2gwBQ9tdWx0aXNpZ0FkZHJlc3MDCQABAgUHJG1hdGNoMAIHQWRkcmVzcwQBdAUHJG1hdGNoMAYHBAhpc0luaXRlZAMFCm11bHRpc2lnT2sJAQt2YWx1ZU9yRWxzZQIJAJsIAgkBBXZhbHVlAQUPbXVsdGlzaWdBZGRyZXNzAgZJTklURUQHBwQJaGFzQWRtaW5zAwUKbXVsdGlzaWdPawkBAiE9AgkBC3ZhbHVlT3JFbHNlAgkAnQgCCQEFdmFsdWUBBQ9tdWx0aXNpZ0FkZHJlc3MCC0FETUlOU19QQktTAgACAAcDAwMFCm11bHRpc2lnT2sFCGlzSW5pdGVkBwUJaGFzQWRtaW5zBwQHJG1hdGNoMAUCdHgDCQABAgUHJG1hdGNoMAIUU2V0U2NyaXB0VHJhbnNhY3Rpb24EA3R0eAUHJG1hdGNoMAQHJG1hdGNoMQgFA3R0eAZzY3JpcHQDCQABAgUHJG1hdGNoMQIKQnl0ZVZlY3RvcgQGc2NyaXB0BQckbWF0Y2gxBAtzY3JpcHRIYXNoYQkA2AQBCQD2AwEFBnNjcmlwdAQJdmFsaWRGcm9tCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgkBBXZhbHVlAQUPbXVsdGlzaWdBZGRyZXNzCQCsAgIJAKwCAgkArAICCQCsAgICCHNjcmlwdCUlBQ1DT05UUkFDVF9UWVBFAgIlJQULc2NyaXB0SGFzaGECCyUldmFsaWRGcm9tAhF2YWxpZEZyb20gbm90IHNldAQHdmFsaWRUbwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIJAQV2YWx1ZQEFD211bHRpc2lnQWRkcmVzcwkArAICCQCsAgIJAKwCAgkArAICAghzY3JpcHQlJQUNQ09OVFJBQ1RfVFlQRQICJSUFC3NjcmlwdEhhc2hhAgklJXZhbGlkVG8CD3ZhbGlkVG8gbm90IHNldAMJAGcCBQZoZWlnaHQFCXZhbGlkRnJvbQkAZwIFB3ZhbGlkVG8FBmhlaWdodAcHBANvdHgFByRtYXRjaDAEBnRhc2tJZAkArAICCQCsAgIJAKwCAgIDdHhfCQClCAEFBHRoaXMCAV8JANgEAQgFA290eAJpZAQKaXNBcHByb3ZlZAkBC3ZhbHVlT3JFbHNlAgkAmwgCCQEFdmFsdWUBBQ9tdWx0aXNpZ0FkZHJlc3MJAKwCAgkArAICCQCsAgIJAKUIAQUEdGhpcwIBXwkA2AQBCAUDb3R4AmlkAgpfX2FwcHJvdmVkBwQMYXBwcm92ZWRGcm9tCQELdmFsdWVPckVsc2UCCQCaCAIJAQV2YWx1ZQEFD211bHRpc2lnQWRkcmVzcwkArAICBQZ0YXNrSWQCDl9fYXBwcm92ZWRGcm9tAAADBQppc0FwcHJvdmVkCQBnAgUGaGVpZ2h0BQxhcHByb3ZlZEZyb20HBA1tYXN0ZXJBZGRyZXNzCQCiCAECD3ZlcmlmaWVyX21hc3RlcgQQYXBwcm92ZWRCeU1hc3RlcgQHJG1hdGNoMAUNbWFzdGVyQWRkcmVzcwMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAXgFByRtYXRjaDAEByRtYXRjaDEJAJoIAgkBEUBleHRyTmF0aXZlKDEwNjIpAQUBeAkArAICAgthcHByb3ZlZFR4XwkA2AQBCAUCdHgCaWQDCQABAgUHJG1hdGNoMQIDSW50BAF5BQckbWF0Y2gxBQF5AAAAAQMJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAAIBQJ0eA9zZW5kZXJQdWJsaWNLZXkJAGYCBRBhcHByb3ZlZEJ5TWFzdGVyAAAHQd1I8Q==", "height": 820040, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: none Next: none Full:
OldNewDifferences
1-# no script
1+{-# STDLIB_VERSION 6 #-}
2+{-# SCRIPT_TYPE ACCOUNT #-}
3+{-# CONTENT_TYPE DAPP #-}
4+let CONTRACT_TYPE = "LEND-LP-MARKET"
5+
6+let VERSION = "PLP-1.2.0"
7+
8+func getAddressFromState (key) = valueOrElse(addressFromString(valueOrElse(getString(this, ("setup_address_" + key)), "3PEwRcYNAUtoFvKpBhKoiwajnZfdoDR6h4h")), Address(base58'3PEwRcYNAUtoFvKpBhKoiwajnZfdoDR6h4h'))
9+
10+
11+func getAddressesFromState (key) = {
12+ func f (accum,next) = (accum ++ [valueOrElse(addressFromString(next), Address(base58'3PEwRcYNAUtoFvKpBhKoiwajnZfdoDR6h4h'))])
13+
14+ let $l = split_4C(valueOrElse(getString(this, ("setup_address_" + key)), "3PEwRcYNAUtoFvKpBhKoiwajnZfdoDR6h4h"), ",")
15+ let $s = size($l)
16+ let $acc0 = nil
17+ func $f0_1 ($a,$i) = if (($i >= $s))
18+ then $a
19+ else f($a, $l[$i])
20+
21+ func $f0_2 ($a,$i) = if (($i >= $s))
22+ then $a
23+ else throw("List size exceeds 15")
24+
25+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15)
26+ }
27+
28+
29+let reserveFundAddress = getAddressFromState("reserveFund")
30+
31+let oracleAddress = getAddressFromState("oracle")
32+
33+let aggregatorAddress = getAddressFromState("aggregator")
34+
35+let adminAddress = getAddressFromState("admin")
36+
37+let stableFundAddress = getAddressFromState("stableFund")
38+
39+let feeCollectorAddress = getAddressFromState("feeCollector")
40+
41+let shutdownWhitelist = getAddressesFromState("shutdownCallers")
42+
43+let liquidatorsWhitelist = getAddressesFromState("liquidators")
44+
45+func verifyLiquidatorRights (address) = (indexOf(liquidatorsWhitelist, address) != unit)
46+
47+
48+let reserveFund = valueOrElse(getInteger(this, "setup_reserveFundFee"), 20)
49+
50+let stablesIdStr = split(valueOrElse(getString(this, "setup_stablesIds"), "9wc3LXNA4TEBsXyKtoLE9mrbDD7WMHXvXrCjZvabLAsi,HGgabTqUS8WtVFUJzfmrTDMgEccJuZLBPhFgQFxvnsoW"), ",")
51+
52+func getRateCurve (assetIdStr) = {
53+ let curveRateStrLi = split(valueOrElse(getString(this, ("setup_rateCurve_" + assetIdStr)), "20000000,100000000,60000000,400000000"), ",")
54+ $Tuple4(parseIntValue(curveRateStrLi[0]), parseIntValue(curveRateStrLi[1]), parseIntValue(curveRateStrLi[2]), parseIntValue(curveRateStrLi[3]))
55+ }
56+
57+
58+func getRewardsSplitting (assetIdStr) = {
59+ let rewardsSplittingStrLi = split(valueOrElse(getString(this, ("setup_rewardsSplitting_" + assetIdStr)), "30,50,20"), ",")
60+ $Tuple3(parseIntValue(rewardsSplittingStrLi[0]), parseIntValue(rewardsSplittingStrLi[1]), parseIntValue(rewardsSplittingStrLi[2]))
61+ }
62+
63+
64+let sentinels = [Address(base58'3PMcMiMEs6w56NRGacksXtFG5zS7doE9fpL'), Address(base58'3PQdNxynJy5mche2kxMVc5shXWzK8Gstq3o'), Address(base58'3P8auNWJkxxByyJtwErFXaxiXcGM45qQ1hA'), Address(base58'3P8qVX189qpoTJZQQQdKS9endHK5sxWsvrd')]
65+
66+let Scale8 = 100000000
67+
68+let Scale10 = 10000000000
69+
70+let Scale16 = (Scale8 * Scale8)
71+
72+let dayBlocks = 1440
73+
74+let withdrawalLimitBlocks = valueOrElse(getInteger(this, "setup_withdrawalLimitBlocks"), 100)
75+
76+func liIntToStr (li) = {
77+ func f (accum,next) = ((accum + toString(next)) + ",")
78+
79+ let $l = li
80+ let $s = size($l)
81+ let $acc0 = ""
82+ func $f0_1 ($a,$i) = if (($i >= $s))
83+ then $a
84+ else f($a, $l[$i])
85+
86+ func $f0_2 ($a,$i) = if (($i >= $s))
87+ then $a
88+ else throw("List size exceeds 12")
89+
90+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12)
91+ }
92+
93+
94+func tryGetInteger (key) = match getInteger(this, key) {
95+ case b: Int =>
96+ b
97+ case _ =>
98+ 0
99+}
100+
101+
102+func tryGetBoolean (key) = match getBoolean(this, key) {
103+ case b: Boolean =>
104+ b
105+ case _ =>
106+ false
107+}
108+
109+
110+func tryGetString (key) = match getString(this, key) {
111+ case b: String =>
112+ b
113+ case _ =>
114+ ""
115+}
116+
117+
118+func tryGetBinary (key) = match getBinary(this, key) {
119+ case b: ByteVector =>
120+ b
121+ case _ =>
122+ base58''
123+}
124+
125+
126+func getAssetString (assetId) = match assetId {
127+ case b: ByteVector =>
128+ toBase58String(b)
129+ case _ =>
130+ "WAVES"
131+}
132+
133+
134+func getAssetBytes (assetIdStr) = if ((assetIdStr == "WAVES"))
135+ then unit
136+ else fromBase58String(assetIdStr)
137+
138+
139+func getBalance (assetIdStr) = if ((assetIdStr == "WAVES"))
140+ then wavesBalance(this).available
141+ else assetBalance(this, fromBase58String(assetIdStr))
142+
143+
144+func getMarketAssets () = split(tryGetString("setup_tokens"), ",")
145+
146+
147+func getOutdatedUr (assetIdStr) = {
148+ let down = fraction(tryGetInteger(("total_supplied_" + assetIdStr)), tryGetInteger((assetIdStr + "_sRate")), Scale16)
149+ if ((down == 0))
150+ then 0
151+ else fraction(Scale8, fraction(tryGetInteger(("total_borrowed_" + assetIdStr)), tryGetInteger((assetIdStr + "_bRate")), Scale16), down)
152+ }
153+
154+
155+func getInterest (assetIdStr) = {
156+ let ur = getOutdatedUr(assetIdStr)
157+ let curve = getRateCurve(assetIdStr)
158+ let rate = (curve._1 + (if ((curve._3 >= ur))
159+ then fraction(ur, curve._2, curve._3)
160+ else (curve._2 + fraction((ur - curve._3), curve._4, (100000000 - curve._3)))))
161+ max([fraction(rate, Scale8, (dayBlocks * 365)), 1])
162+ }
163+
164+
165+func tokenRatesRecalc (assetIdStr) = {
166+ let interest = getInterest(assetIdStr)
167+ let ur = getOutdatedUr(assetIdStr)
168+ let lastRecalcHeight = tryGetInteger("lastRateHeight")
169+ let lastBRate = max([tryGetInteger((assetIdStr + "_bRate")), Scale16])
170+ let newBRate = (lastBRate + ((height - lastRecalcHeight) * interest))
171+ let lastSRate = max([tryGetInteger((assetIdStr + "_sRate")), Scale16])
172+ let newSRate = (lastSRate + ((((height - lastRecalcHeight) * fraction(interest, ur, Scale8)) * (100 - reserveFund)) / 100))
173+[IntegerEntry((assetIdStr + "_sRate"), newSRate), IntegerEntry((assetIdStr + "_bRate"), newBRate), IntegerEntry("lastRateHeight", height)]
174+ }
175+
176+
177+func getActualRate (assetIdStr,rateType) = {
178+ func f (accum,token) = {
179+ let recalc = tokenRatesRecalc(token)
180+ $Tuple2(if ((token != assetIdStr))
181+ then accum._1
182+ else if ((rateType == "sRate"))
183+ then recalc[0].value
184+ else recalc[1].value, (accum._2 ++ recalc))
185+ }
186+
187+ let $l = getMarketAssets()
188+ let $s = size($l)
189+ let $acc0 = $Tuple2(0, nil)
190+ func $f0_1 ($a,$i) = if (($i >= $s))
191+ then $a
192+ else f($a, $l[$i])
193+
194+ func $f0_2 ($a,$i) = if (($i >= $s))
195+ then $a
196+ else throw("List size exceeds 12")
197+
198+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12)
199+ }
200+
201+
202+func getUr (assetIdStr) = {
203+ let rates = tokenRatesRecalc(assetIdStr)
204+ let down = fraction(tryGetInteger(("total_supplied_" + assetIdStr)), rates[0].value, Scale16)
205+ fraction(Scale8, fraction(tryGetInteger(("total_borrowed_" + assetIdStr)), rates[1].value, Scale16), down)
206+ }
207+
208+
209+func ratesRecalc () = {
210+ func f (accum,token) = (accum ++ tokenRatesRecalc(token))
211+
212+ let $l = getMarketAssets()
213+ let $s = size($l)
214+ let $acc0 = nil
215+ func $f0_1 ($a,$i) = if (($i >= $s))
216+ then $a
217+ else f($a, $l[$i])
218+
219+ func $f0_2 ($a,$i) = if (($i >= $s))
220+ then $a
221+ else throw("List size exceeds 12")
222+
223+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12)
224+ }
225+
226+
227+func getTokenPriceWithRisk (assetIdStr,riskAversity) = if ((indexOf(stablesIdStr, assetIdStr) != unit))
228+ then $Tuple2(1000000, 1000000)
229+ else {
230+ let price = getIntegerValue(oracleAddress, (assetIdStr + "_twap5B"))
231+ let riskLevel = getIntegerValue(oracleAddress, (assetIdStr + "_riskLevel"))
232+ if ((riskAversity >= riskLevel))
233+ then $Tuple2(price, price)
234+ else throw((("oracle prices don't match: " + toString(price)) + " is the price, but risk is too high"))
235+ }
236+
237+
238+func getTokenPrice (assetIdStr) = getTokenPriceWithRisk(assetIdStr, 3)
239+
240+
241+func getTokenPriceCapped (assetIdStr) = {
242+ let $t079878050 = getTokenPriceWithRisk(assetIdStr, 3)
243+ let minPrice = $t079878050._1
244+ let maxPrice = $t079878050._2
245+ let maxAllowedPrice = valueOrElse(getInteger(this, ("setup_maxPrice_" + assetIdStr)), -1)
246+ let minAllowedPrice = valueOrElse(getInteger(this, ("setup_minPrice_" + assetIdStr)), -1)
247+ if (if ((maxAllowedPrice != -1))
248+ then (maxPrice > maxAllowedPrice)
249+ else false)
250+ then $Tuple2(maxAllowedPrice, maxAllowedPrice)
251+ else if (if ((minAllowedPrice != -1))
252+ then (minAllowedPrice > minPrice)
253+ else false)
254+ then $Tuple2(minAllowedPrice, minAllowedPrice)
255+ else $Tuple2(minPrice, maxPrice)
256+ }
257+
258+
259+func calcAssetScale (assetIdStr) = {
260+ let decimals = if ((assetIdStr == "WAVES"))
261+ then 8
262+ else value(assetInfo(fromBase58String(assetIdStr))).decimals
263+ pow(10, 0, decimals, 0, 0, DOWN)
264+ }
265+
266+
267+func calcUserCollateral (address) = {
268+ let userCollateralInvoke = invoke(this, "getUserCollateral", [false, address, true, ""], nil)
269+ if ((userCollateralInvoke == userCollateralInvoke))
270+ then {
271+ let userCollateralValue = match userCollateralInvoke {
272+ case x: Int =>
273+ x
274+ case _ =>
275+ throw("issue while doing in-dapp invocation")
276+ }
277+ if ((userCollateralValue == userCollateralValue))
278+ then userCollateralValue
279+ else throw("Strict value is not equal to itself.")
280+ }
281+ else throw("Strict value is not equal to itself.")
282+ }
283+
284+
285+func checkWithdrawalLimit (address,assetIdStr,amountInternal,sRate) = {
286+ let withdrawalLimit = valueOrElse(getInteger(this, (("setup_" + assetIdStr) + "_maxWithdrawPer100B")), -1)
287+ if ((withdrawalLimit == -1))
288+ then nil
289+ else {
290+ let totalSupplied = tryGetInteger(("total_supplied_" + assetIdStr))
291+ let limitCap = fraction(totalSupplied, withdrawalLimit, 100)
292+ let lastH = tryGetInteger(((address + "_withdrawLimitHeight_") + assetIdStr))
293+ let elapsed = (height - lastH)
294+ let windowExpired = (elapsed > withdrawalLimitBlocks)
295+ let currentUsed = if (windowExpired)
296+ then 0
297+ else tryGetInteger(((address + "_withdrawLimitUsed_") + assetIdStr))
298+ let blocksToReset = if (windowExpired)
299+ then withdrawalLimitBlocks
300+ else (withdrawalLimitBlocks - elapsed)
301+ let available = (limitCap - currentUsed)
302+ let availableScaled = fraction(available, sRate, Scale16, CEILING)
303+ if ((amountInternal > available))
304+ then throw(((((("withdrawal limit exceeded for " + assetIdStr) + ", available: ") + toString(availableScaled)) + ", blocks to reset: ") + toString(blocksToReset)))
305+ else ((if (windowExpired)
306+ then [IntegerEntry(((address + "_withdrawLimitHeight_") + assetIdStr), height)]
307+ else nil) ++ [IntegerEntry(((address + "_withdrawLimitUsed_") + assetIdStr), (currentUsed + amountInternal))])
308+ }
309+ }
310+
311+
312+func checkBorrowLimit (address,assetIdStr,amountInternal,bRate,sRate) = {
313+ let borrowLimit = valueOrElse(getInteger(this, (("setup_" + assetIdStr) + "_maxBorrowPer100B")), -1)
314+ if ((borrowLimit == -1))
315+ then nil
316+ else {
317+ let totalSupplied = tryGetInteger(("total_supplied_" + assetIdStr))
318+ let limitCapSupply = fraction(totalSupplied, borrowLimit, 100)
319+ let limitCap = fraction(fraction(limitCapSupply, sRate, Scale16), Scale16, bRate)
320+ let lastH = tryGetInteger(((address + "_borrowLimitHeight_") + assetIdStr))
321+ let elapsed = (height - lastH)
322+ let windowExpired = (elapsed > withdrawalLimitBlocks)
323+ let currentUsed = if (windowExpired)
324+ then 0
325+ else tryGetInteger(((address + "_borrowLimitUsed_") + assetIdStr))
326+ let blocksToReset = if (windowExpired)
327+ then withdrawalLimitBlocks
328+ else (withdrawalLimitBlocks - elapsed)
329+ let available = (limitCap - currentUsed)
330+ let availableScaled = fraction(available, bRate, Scale16, CEILING)
331+ if ((amountInternal > available))
332+ then throw(((((("borrow limit exceeded for " + assetIdStr) + ", available: ") + toString(availableScaled)) + ", blocks to reset: ") + toString(blocksToReset)))
333+ else ((if (windowExpired)
334+ then [IntegerEntry(((address + "_borrowLimitHeight_") + assetIdStr), height)]
335+ else nil) ++ [IntegerEntry(((address + "_borrowLimitUsed_") + assetIdStr), (currentUsed + amountInternal))])
336+ }
337+ }
338+
339+
340+@Callable(i)
341+func supply () = if (!(tryGetBoolean("setup_active")))
342+ then throw("market is stopped")
343+ else if (if ((size(i.payments) != 1))
344+ then true
345+ else (i.payments[0].amount == 0))
346+ then throw("1 payment has to be attached")
347+ else {
348+ let assetIdStr = getAssetString(i.payments[0].assetId)
349+ let assetAmount = i.payments[0].amount
350+ let $t01205812125 = getActualRate(assetIdStr, "sRate")
351+ let sRate = $t01205812125._1
352+ let ratesRecalcResult = $t01205812125._2
353+ let amount = fraction(assetAmount, Scale16, sRate, DOWN)
354+ let address = toString(i.caller)
355+ let maxSupply = match getString(("setup_maxSupply_" + assetIdStr)) {
356+ case x: String =>
357+ parseIntValue(x)
358+ case _ =>
359+ tryGetInteger(("setup_maxSupply_" + assetIdStr))
360+ }
361+ let assetPrice = getTokenPriceCapped(assetIdStr)
362+ let newAddressSupplied = (tryGetInteger(((address + "_supplied_") + assetIdStr)) + amount)
363+ let newTotalSupplied = (tryGetInteger(("total_supplied_" + assetIdStr)) + amount)
364+ let rate = getActualRate(assetIdStr, "sRate")._1
365+ let assetScale = calcAssetScale(assetIdStr)
366+ let newTotalSuppliedUsd = fraction(fraction(newTotalSupplied, rate, Scale16), assetPrice._1, assetScale)
367+ if ((indexOf(tryGetString("setup_tokens"), assetIdStr) == unit))
368+ then throw("this asset is not supported by the market")
369+ else if (if ((maxSupply != 0))
370+ then (newTotalSuppliedUsd > maxSupply)
371+ else false)
372+ then throw("max total supply for this token reached in the pool")
373+ else if ((tryGetInteger(("setup_paused_" + assetIdStr)) > 0))
374+ then throw("this asset can't be supplied or borrowed")
375+ else {
376+ let inv = if ((tryGetString(("setup_autostake_" + assetIdStr)) != ""))
377+ then invoke(this, "stakeToken", [assetIdStr, assetAmount], nil)
378+ else unit
379+ if ((inv == inv))
380+ then ([IntegerEntry(((address + "_supplied_") + assetIdStr), newAddressSupplied), IntegerEntry(("total_supplied_" + assetIdStr), newTotalSupplied)] ++ ratesRecalcResult)
381+ else throw("Strict value is not equal to itself.")
382+ }
383+ }
384+
385+
386+
387+@Callable(i)
388+func withdraw (assetIdStr,assetAmount) = {
389+ let $t01369213759 = getActualRate(assetIdStr, "sRate")
390+ let sRate = $t01369213759._1
391+ let ratesRecalcResult = $t01369213759._2
392+ let amount = fraction(assetAmount, Scale16, sRate, CEILING)
393+ let address = toString(i.caller)
394+ let assetSupplied = tryGetInteger(("total_supplied_" + assetIdStr))
395+ let assetBorrowed = tryGetInteger(("total_borrowed_" + assetIdStr))
396+ let userAssetSupplied = tryGetInteger(((address + "_supplied_") + assetIdStr))
397+ let userAssetBorrowed = tryGetInteger(((address + "_borrowed_") + assetIdStr))
398+ let collateralValueInv = invoke(this, "getUserCollateral", [false, address, true, ((assetIdStr + ",supplied,") + toString(-(amount)))], nil)
399+ if ((collateralValueInv == collateralValueInv))
400+ then {
401+ let collateralValue = match collateralValueInv {
402+ case x: Int =>
403+ x
404+ case _ =>
405+ throw("can't get user collateral value")
406+ }
407+ if (!(tryGetBoolean("setup_active")))
408+ then throw("market is stopped")
409+ else if ((0 > collateralValue))
410+ then throw("you dont have enough collateral for this operation")
411+ else if ((amount > (assetSupplied - assetBorrowed)))
412+ then throw("this amount is not available on the market")
413+ else if ((amount > (userAssetSupplied - userAssetBorrowed)))
414+ then throw("this amount is not available for this user")
415+ else {
416+ let inv = if ((tryGetString(("setup_autostake_" + assetIdStr)) != ""))
417+ then invoke(this, "unstakeToken", [assetIdStr, assetAmount], nil)
418+ else unit
419+ if ((inv == inv))
420+ then {
421+ let limitCheckActions = checkWithdrawalLimit(address, assetIdStr, amount, sRate)
422+ if ((limitCheckActions == limitCheckActions))
423+ then (([IntegerEntry(((address + "_supplied_") + assetIdStr), (tryGetInteger(((address + "_supplied_") + assetIdStr)) - amount)), IntegerEntry(("total_supplied_" + assetIdStr), (tryGetInteger(("total_supplied_" + assetIdStr)) - amount)), ScriptTransfer(i.caller, assetAmount, getAssetBytes(assetIdStr))] ++ ratesRecalcResult) ++ limitCheckActions)
424+ else throw("Strict value is not equal to itself.")
425+ }
426+ else throw("Strict value is not equal to itself.")
427+ }
428+ }
429+ else throw("Strict value is not equal to itself.")
430+ }
431+
432+
433+
434+@Callable(i)
435+func borrow (assetIdStr,assetAmount) = {
436+ let address = toString(i.caller)
437+ let $t01552315590 = getActualRate(assetIdStr, "bRate")
438+ let bRate = $t01552315590._1
439+ let ratesRecalcResult = $t01552315590._2
440+ let amount = fraction(assetAmount, Scale16, bRate, CEILING)
441+ let collateralValueInv = invoke(this, "getUserCollateral", [false, address, true, ((assetIdStr + ",borrowed,") + toString(amount))], nil)
442+ if ((collateralValueInv == collateralValueInv))
443+ then {
444+ let collateralValue = match collateralValueInv {
445+ case x: Int =>
446+ x
447+ case _ =>
448+ throw("can't get user collateral value")
449+ }
450+ if (!(tryGetBoolean("setup_active")))
451+ then throw("market is stopped")
452+ else if ((0 > collateralValue))
453+ then throw("you have to supply more to borrow")
454+ else if ((tryGetInteger(("setup_borrowEnabled_" + assetIdStr)) == 0))
455+ then throw("this asset can't be borrowed")
456+ else if ((tryGetInteger(("setup_paused_" + assetIdStr)) > 0))
457+ then throw("this asset can't be supplied or borrowed")
458+ else {
459+ let assetSupplied = tryGetInteger(("total_supplied_" + assetIdStr))
460+ let assetBorrowed = tryGetInteger(("total_borrowed_" + assetIdStr))
461+ let userAssetBorrowed = tryGetInteger(((address + "_borrowed_") + assetIdStr))
462+ if ((amount > (assetSupplied - assetBorrowed)))
463+ then throw("this amount is not available")
464+ else {
465+ let inv = if ((tryGetString(("setup_autostake_" + assetIdStr)) != ""))
466+ then invoke(this, "unstakeToken", [assetIdStr, assetAmount], nil)
467+ else unit
468+ if ((inv == inv))
469+ then {
470+ let sRate = ratesRecalcResult[(value(indexOf(getMarketAssets(), assetIdStr)) * 3)].value
471+ let limitCheckActions = checkBorrowLimit(address, assetIdStr, amount, bRate, sRate)
472+ if ((limitCheckActions == limitCheckActions))
473+ then (([IntegerEntry(((address + "_borrowed_") + assetIdStr), (userAssetBorrowed + amount)), IntegerEntry(("total_borrowed_" + assetIdStr), (assetBorrowed + amount)), ScriptTransfer(i.caller, assetAmount, getAssetBytes(assetIdStr))] ++ ratesRecalcResult) ++ limitCheckActions)
474+ else throw("Strict value is not equal to itself.")
475+ }
476+ else throw("Strict value is not equal to itself.")
477+ }
478+ }
479+ }
480+ else throw("Strict value is not equal to itself.")
481+ }
482+
483+
484+
485+@Callable(i)
486+func repay () = if (!(tryGetBoolean("setup_active")))
487+ then throw("market is stopped")
488+ else if (if ((size(i.payments) != 1))
489+ then true
490+ else (i.payments[0].amount == 0))
491+ then throw("1 payment has to be attached")
492+ else {
493+ let assetIdStr = getAssetString(i.payments[0].assetId)
494+ let assetAmount = i.payments[0].amount
495+ let $t01768417751 = getActualRate(assetIdStr, "bRate")
496+ let bRate = $t01768417751._1
497+ let ratesRecalcResult = $t01768417751._2
498+ let amount = fraction(assetAmount, Scale16, bRate, CEILING)
499+ let address = toString(i.caller)
500+ let assetSupplied = tryGetInteger(("total_supplied_" + assetIdStr))
501+ let assetBorrowed = tryGetInteger(("total_borrowed_" + assetIdStr))
502+ let userAssetBorrowed = tryGetInteger(((address + "_borrowed_") + assetIdStr))
503+ let amountLeft = (userAssetBorrowed - amount)
504+ let repayAmount = if ((amountLeft >= 0))
505+ then amount
506+ else userAssetBorrowed
507+ if ((indexOf(tryGetString("setup_tokens"), assetIdStr) == unit))
508+ then throw("this asset is not supported by the market")
509+ else {
510+ let inv = if ((tryGetString(("setup_autostake_" + assetIdStr)) != ""))
511+ then invoke(this, "stakeToken", [assetIdStr, assetAmount], nil)
512+ else unit
513+ if ((inv == inv))
514+ then {
515+ let excessTokens = (assetAmount - fraction(repayAmount, bRate, Scale16))
516+ (([IntegerEntry(((address + "_borrowed_") + assetIdStr), (userAssetBorrowed - repayAmount)), IntegerEntry(("total_borrowed_" + assetIdStr), (assetBorrowed - repayAmount))] ++ ratesRecalcResult) ++ (if ((amountLeft >= 0))
517+ then nil
518+ else [ScriptTransfer(i.caller, excessTokens, i.payments[0].assetId)]))
519+ }
520+ else throw("Strict value is not equal to itself.")
521+ }
522+ }
523+
524+
525+
526+@Callable(i)
527+func repayFor (address) = if (!(tryGetBoolean("setup_active")))
528+ then throw("market is stopped")
529+ else if ((i.caller != reserveFundAddress))
530+ then throw("available only for reserve fund address")
531+ else if ((address == "global"))
532+ then throw("you can't repay for everyone :_)")
533+ else if (if ((size(i.payments) != 1))
534+ then true
535+ else (i.payments[0].amount == 0))
536+ then throw("1 payment has to be attached")
537+ else {
538+ let assetIdStr = getAssetString(i.payments[0].assetId)
539+ let assetAmount = i.payments[0].amount
540+ let $t01942719494 = getActualRate(assetIdStr, "bRate")
541+ let bRate = $t01942719494._1
542+ let ratesRecalcResult = $t01942719494._2
543+ let amount = fraction(assetAmount, Scale16, bRate, CEILING)
544+ let assetSupplied = tryGetInteger(("total_supplied_" + assetIdStr))
545+ let assetBorrowed = tryGetInteger(("total_borrowed_" + assetIdStr))
546+ let userAssetBorrowed = tryGetInteger(((address + "_borrowed_") + assetIdStr))
547+ let amountLeft = (userAssetBorrowed - amount)
548+ let repayAmount = if ((amountLeft >= 0))
549+ then amount
550+ else userAssetBorrowed
551+ if ((indexOf(tryGetString("setup_tokens"), assetIdStr) == unit))
552+ then throw("this asset is not supported by the market")
553+ else {
554+ let inv = if ((tryGetString(("setup_autostake_" + assetIdStr)) != ""))
555+ then invoke(this, "stakeToken", [assetIdStr, assetAmount], nil)
556+ else unit
557+ if ((inv == inv))
558+ then {
559+ let excessTokens = (assetAmount - fraction(repayAmount, bRate, Scale16))
560+ (([IntegerEntry(((address + "_borrowed_") + assetIdStr), (userAssetBorrowed - repayAmount)), IntegerEntry(("total_borrowed_" + assetIdStr), (assetBorrowed - repayAmount))] ++ ratesRecalcResult) ++ (if ((amountLeft >= 0))
561+ then nil
562+ else [ScriptTransfer(i.caller, excessTokens, i.payments[0].assetId)]))
563+ }
564+ else throw("Strict value is not equal to itself.")
565+ }
566+ }
567+
568+
569+
570+@Callable(i)
571+func stakeToken (assetIdStr,amount) = {
572+ let autostakeAddress = valueOrElse(addressFromString(tryGetString(("setup_autostake_" + assetIdStr))), Address(base58'3PDDRRS5gKyDQRpJskzWTdxREHGu1FNpdwg'))
573+ let stakerSupportedAssets = getStringValue(autostakeAddress, "setup_supportedAssets")
574+ if ((i.caller != this))
575+ then throw("only for internal smart contract invocations")
576+ else if ((indexOf(stakerSupportedAssets, assetIdStr) == unit))
577+ then nil
578+ else {
579+ let amountStaked = tryGetInteger(("autostake_amount_" + assetIdStr))
580+ let stakeInv = reentrantInvoke(autostakeAddress, "stakeLP", nil, [AttachedPayment(getAssetBytes(assetIdStr), amount)])
581+ if ((stakeInv == stakeInv))
582+ then [IntegerEntry(("autostake_amount_" + assetIdStr), (amountStaked + amount))]
583+ else throw("Strict value is not equal to itself.")
584+ }
585+ }
586+
587+
588+
589+@Callable(i)
590+func stakeTokenAll (assetIdStr) = if ((i.caller != this))
591+ then throw("only for internal smart contract invocations")
592+ else {
593+ let amount = getBalance(assetIdStr)
594+ let inv = reentrantInvoke(this, "stakeToken", [assetIdStr, amount], nil)
595+ if ((inv == inv))
596+ then nil
597+ else throw("Strict value is not equal to itself.")
598+ }
599+
600+
601+
602+@Callable(i)
603+func unstakeToken (assetIdStr,amount) = {
604+ let autostakeAddress = valueOrElse(addressFromString(tryGetString(("setup_autostake_" + assetIdStr))), Address(base58'3PDDRRS5gKyDQRpJskzWTdxREHGu1FNpdwg'))
605+ let stakerSupportedAssets = getStringValue(autostakeAddress, "setup_supportedAssets")
606+ if ((i.caller != this))
607+ then throw("only for internal smart contract invocations")
608+ else if ((indexOf(stakerSupportedAssets, assetIdStr) == unit))
609+ then nil
610+ else {
611+ let amountStaked = tryGetInteger(("autostake_amount_" + assetIdStr))
612+ let stakeInv = reentrantInvoke(autostakeAddress, "unstakeLP", [assetIdStr, amount], nil)
613+ if ((stakeInv == stakeInv))
614+ then [IntegerEntry(("autostake_amount_" + assetIdStr), (amountStaked - amount))]
615+ else throw("Strict value is not equal to itself.")
616+ }
617+ }
618+
619+
620+
621+@Callable(i)
622+func addInterest (assetIdStr,amount) = if ((i.caller != this))
623+ then throw("only for self invocation")
624+ else {
625+ let earned = tryGetInteger(("autostake_lastEarned_" + assetIdStr))
626+ let lastHeight = tryGetInteger(("autostake_lastBlock_" + assetIdStr))
627+ let cleanAmount = fraction(amount, 80, 100)
628+ let stakingFee = (amount - cleanAmount)
629+ let stateChanges = if (if ((lastHeight == height))
630+ then true
631+ else (amount == 0))
632+ then nil
633+ else [IntegerEntry(("autostake_preLastEarned_" + assetIdStr), earned), IntegerEntry(("autostake_preLastBlock_" + assetIdStr), lastHeight), IntegerEntry(("autostake_lastEarned_" + assetIdStr), (earned + cleanAmount)), IntegerEntry(("autostake_lastBlock_" + assetIdStr), height)]
634+ (stateChanges ++ [IntegerEntry((assetIdStr + "_sRate"), (tryGetInteger((assetIdStr + "_sRate")) + fraction(Scale16, cleanAmount, tryGetInteger(("total_supplied_" + assetIdStr))))), IntegerEntry((("fee_" + assetIdStr) + "_staking"), (tryGetInteger((("fee_" + assetIdStr) + "_staking")) + stakingFee))])
635+ }
636+
637+
638+
639+@Callable(i)
640+func addInterestEXTERNAL () = {
641+ let assetId = i.payments[0].assetId
642+ let assetIdStr = getAssetString(assetId)
643+ let splitting = getRewardsSplitting(assetIdStr)
644+ let amount = fraction(i.payments[0].amount, splitting._2, 100)
645+ let earned = tryGetInteger(("autostake_lastEarned_" + assetIdStr))
646+ let lastHeight = tryGetInteger(("autostake_lastBlock_" + assetIdStr))
647+ let stateChanges = if (if ((lastHeight == height))
648+ then true
649+ else (amount == 0))
650+ then nil
651+ else [IntegerEntry(("autostake_preLastEarned_" + assetIdStr), earned), IntegerEntry(("autostake_preLastBlock_" + assetIdStr), lastHeight), IntegerEntry(("autostake_lastEarned_" + assetIdStr), (earned + amount)), IntegerEntry(("autostake_lastBlock_" + assetIdStr), height)]
652+ (stateChanges ++ [IntegerEntry((assetIdStr + "_sRate"), (tryGetInteger((assetIdStr + "_sRate")) + fraction(Scale16, amount, tryGetInteger(("total_supplied_" + assetIdStr))))), ScriptTransfer(stableFundAddress, fraction(i.payments[0].amount, splitting._1, 100), assetId), IntegerEntry((("fee_" + assetIdStr) + "_staking"), (tryGetInteger((("fee_" + assetIdStr) + "_staking")) + fraction(i.payments[0].amount, splitting._3, 100)))])
653+ }
654+
655+
656+
657+@Callable(i)
658+func preInit (tokens,ltvs,lts,penalties) = {
659+ func f (accum,token) = (accum ++ [IntegerEntry((token + "_bRate"), Scale16), IntegerEntry((token + "_sRate"), Scale16)])
660+
661+ if ((i.caller != this))
662+ then throw("admin only")
663+ else {
664+ let rates = {
665+ let $l = split(tokens, ",")
666+ let $s = size($l)
667+ let $acc0 = nil
668+ func $f0_1 ($a,$i) = if (($i >= $s))
669+ then $a
670+ else f($a, $l[$i])
671+
672+ func $f0_2 ($a,$i) = if (($i >= $s))
673+ then $a
674+ else throw("List size exceeds 12")
675+
676+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12)
677+ }
678+ ([StringEntry("setup_tokens", tokens), StringEntry("setup_ltvs", ltvs), StringEntry("setup_lts", lts), StringEntry("setup_penalties", penalties), BooleanEntry("setup_active", true)] ++ rates)
679+ }
680+ }
681+
682+
683+
684+@Callable(i)
685+func initNewToken (token,ltv,lt,penalty) = if ((i.caller != this))
686+ then throw("admin only")
687+ else [StringEntry("setup_tokens", ((tryGetString("setup_tokens") + ",") + token)), StringEntry("setup_ltvs", ((tryGetString("setup_ltvs") + ",") + ltv)), StringEntry("setup_lts", ((tryGetString("setup_lts") + ",") + lt)), StringEntry("setup_penalties", ((tryGetString("setup_penalties") + ",") + penalty)), IntegerEntry((token + "_bRate"), Scale16), IntegerEntry((token + "_sRate"), Scale16)]
688+
689+
690+
691+@Callable(i)
692+func updateParameter (key,val) = if (if ((i.caller != this))
693+ then (i.caller != adminAddress)
694+ else false)
695+ then throw("admin only")
696+ else [IntegerEntry(key, parseIntValue(val))]
697+
698+
699+
700+@Callable(i)
701+func updateString (key,val) = if (if ((i.caller != this))
702+ then (i.caller != adminAddress)
703+ else false)
704+ then throw("admin only")
705+ else [StringEntry(key, val)]
706+
707+
708+
709+@Callable(i)
710+func claimToReserveFund (debug) = {
711+ let assets = getMarketAssets()
712+ let rates = getActualRate(assets[0], "sRate")._2
713+ let li = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
714+ func f (accum,n) = if ((n >= size(assets)))
715+ then accum
716+ else {
717+ let assetIdStr = assets[n]
718+ let amount = (((getBalance(assetIdStr) + tryGetInteger(("autostake_amount_" + assetIdStr))) + fraction(tryGetInteger(("total_borrowed_" + assetIdStr)), rates[((n * 3) + 1)].value, Scale16)) - fraction(tryGetInteger(("total_supplied_" + assetIdStr)), rates[(n * 3)].value, Scale16))
719+ let inv = if ((tryGetString(("setup_autostake_" + assetIdStr)) != ""))
720+ then invoke(this, "unstakeToken", [assetIdStr, amount], nil)
721+ else unit
722+ if ((inv == inv))
723+ then (accum ++ [amount])
724+ else throw("Strict value is not equal to itself.")
725+ }
726+
727+ let parameter = {
728+ let $l = li
729+ let $s = size($l)
730+ let $acc0 = nil
731+ func $f0_1 ($a,$i) = if (($i >= $s))
732+ then $a
733+ else f($a, $l[$i])
734+
735+ func $f0_2 ($a,$i) = if (($i >= $s))
736+ then $a
737+ else throw("List size exceeds 12")
738+
739+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12)
740+ }
741+ func f2 (accum,n) = if ((n >= size(assets)))
742+ then accum
743+ else {
744+ let assetIdStr = assets[n]
745+ (accum ++ [ScriptTransfer(reserveFundAddress, max([parameter[n], 0]), getAssetBytes(assetIdStr))])
746+ }
747+
748+ if (debug)
749+ then throw(liIntToStr(parameter))
750+ else $Tuple2({
751+ let $l = li
752+ let $s = size($l)
753+ let $acc0 = nil
754+ func $f1_1 ($a,$i) = if (($i >= $s))
755+ then $a
756+ else f2($a, $l[$i])
757+
758+ func $f1_2 ($a,$i) = if (($i >= $s))
759+ then $a
760+ else throw("List size exceeds 12")
761+
762+ $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12)
763+ }, parameter)
764+ }
765+
766+
767+
768+@Callable(i)
769+func claimFees (assetIdStr) = if ((getString(this, "setup_address_feeCollector") == unit))
770+ then throw("fee collector not configured")
771+ else {
772+ let isStaked = (tryGetString(("setup_autostake_" + assetIdStr)) != "")
773+ let rates = tokenRatesRecalc(assetIdStr)
774+ let sRate = rates[0].value
775+ let bRate = rates[1].value
776+ let bal = getBalance(assetIdStr)
777+ let liq = tryGetInteger((("fee_" + assetIdStr) + "_liquidation"))
778+ let stk = tryGetInteger((("fee_" + assetIdStr) + "_staking"))
779+ let interest = if (isStaked)
780+ then 0
781+ else max([((((bal + fraction(tryGetInteger(("total_borrowed_" + assetIdStr)), bRate, Scale16)) - fraction(tryGetInteger(("total_supplied_" + assetIdStr)), sRate, Scale16)) - liq) - stk), 0])
782+ let pay = min([((interest + stk) + liq), bal])
783+ if ((0 >= pay))
784+ then rates
785+ else {
786+ let liqP = min([liq, pay])
787+ let stkP = min([stk, (pay - liqP)])
788+ let interestP = ((pay - liqP) - stkP)
789+ let recordInv = invoke(feeCollectorAddress, "processFees", [assetIdStr, interestP, stkP, liqP], [AttachedPayment(getAssetBytes(assetIdStr), pay)])
790+ if ((recordInv == recordInv))
791+ then (rates ++ [IntegerEntry((("fee_" + assetIdStr) + "_liquidation"), (liq - liqP)), IntegerEntry((("fee_" + assetIdStr) + "_staking"), (stk - stkP))])
792+ else throw("Strict value is not equal to itself.")
793+ }
794+ }
795+
796+
797+
798+@Callable(i)
799+func claimFeesAll (tokensList) = {
800+ let tokens = if ((tokensList == ""))
801+ then getMarketAssets()
802+ else split(tokensList, ",")
803+ func f (accum,token) = {
804+ let inv = invoke(this, "claimFees", [token], nil)
805+ if ((inv == inv))
806+ then accum
807+ else throw("Strict value is not equal to itself.")
808+ }
809+
810+ let done = {
811+ let $l = tokens
812+ let $s = size($l)
813+ let $acc0 = unit
814+ func $f0_1 ($a,$i) = if (($i >= $s))
815+ then $a
816+ else f($a, $l[$i])
817+
818+ func $f0_2 ($a,$i) = if (($i >= $s))
819+ then $a
820+ else throw("List size exceeds 12")
821+
822+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12)
823+ }
824+ if ((done == done))
825+ then nil
826+ else throw("Strict value is not equal to itself.")
827+ }
828+
829+
830+
831+@Callable(i)
832+func reSetup (assetIdStr) = {
833+ let lastResetup = tryGetInteger("resetup_lastUpdate")
834+ if ((dayBlocks > (height - lastResetup)))
835+ then throw("can be updated only once per day")
836+ else {
837+ let lts = split(tryGetString("setup_lts"), ",")
838+ let assets = getMarketAssets()
839+ let ur = getUr(assetIdStr)
840+ let tempLT = tryGetInteger((("setup_" + assetIdStr) + "_tempLT"))
841+ let lt = parseIntValue(assets[value(indexOf(assets, assetIdStr))])
842+ if ((ur > 90000000))
843+ then [IntegerEntry((("setup_" + assetIdStr) + "_tempLT"), fraction(tempLT, 9975, 10000))]
844+ else if (if ((lt > tempLT))
845+ then (90000000 > ur)
846+ else false)
847+ then [IntegerEntry((("setup_" + assetIdStr) + "_tempLT"), fraction(tempLT, 10025, 10000))]
848+ else nil
849+ }
850+ }
851+
852+
853+
854+@Callable(i)
855+func shutdown (shutdown) = if ((indexOf(shutdownWhitelist, i.caller) == unit))
856+ then throw("user not in a whitelist")
857+ else [BooleanEntry("setup_active", !(shutdown))]
858+
859+
860+
861+@Callable(i)
862+func liquidate (debug,address,assetAmount,sAssetIdStr,bAssetIdStr,routeStr) = if (!(verifyLiquidatorRights(i.caller)))
863+ then throw("temporarily available for whitelist only")
864+ else if (!(tryGetBoolean("setup_active")))
865+ then throw("market is stopped")
866+ else {
867+ let userCollateral = calcUserCollateral(address)
868+ if ((userCollateral == userCollateral))
869+ then {
870+ let $t03466834730 = getActualRate(sAssetIdStr, "sRate")
871+ let sRate = $t03466834730._1
872+ let ratesResult = $t03466834730._2
873+ let $t03473534804 = getActualRate(bAssetIdStr, "bRate")
874+ let bRate = $t03473534804._1
875+ let ratesRecalcResult2 = $t03473534804._2
876+ let sAssetAmount = fraction(assetAmount, Scale16, sRate)
877+ let currentSPosition = tryGetInteger(((address + "_supplied_") + sAssetIdStr))
878+ let currentBPositionVal = tryGetInteger(((address + "_borrowed_") + bAssetIdStr))
879+ let currentBPosition = if ((currentBPositionVal > 0))
880+ then currentBPositionVal
881+ else throw("user has no borrow in this token")
882+ if ((userCollateral > 0))
883+ then throw("user can't be liquidated")
884+ else if ((sAssetAmount > currentSPosition))
885+ then throw("position to liquidate is bigger than user's supply")
886+ else {
887+ let inv = if ((tryGetString(("setup_autostake_" + sAssetIdStr)) != ""))
888+ then invoke(this, "unstakeToken", [sAssetIdStr, sAssetAmount], nil)
889+ else unit
890+ if ((inv == inv))
891+ then {
892+ let balance0Before = getBalance(sAssetIdStr)
893+ if ((balance0Before == balance0Before))
894+ then {
895+ let balance1Before = getBalance(bAssetIdStr)
896+ if ((balance1Before == balance1Before))
897+ then {
898+ let exchangeInvoke = invoke(aggregatorAddress, "swap", [routeStr, 0], [AttachedPayment(getAssetBytes(sAssetIdStr), assetAmount)])
899+ if ((exchangeInvoke == exchangeInvoke))
900+ then {
901+ let asset0Sold = (balance0Before - getBalance(sAssetIdStr))
902+ if ((asset0Sold == asset0Sold))
903+ then {
904+ let asset1Bought = (getBalance(bAssetIdStr) - balance1Before)
905+ if ((asset1Bought == asset1Bought))
906+ then {
907+ let asset0Price = getTokenPriceCapped(sAssetIdStr)._1
908+ let asset0Scale = calcAssetScale(sAssetIdStr)
909+ let asset0Usd = fraction(asset0Sold, asset0Price, asset0Scale)
910+ let asset1Price = getTokenPriceCapped(bAssetIdStr)._2
911+ let asset1Scale = calcAssetScale(bAssetIdStr)
912+ let asset1Usd = fraction(asset1Bought, asset1Price, asset1Scale)
913+ let penalty = parseIntValue(split(tryGetString("setup_penalties"), ",")[value(indexOf(getMarketAssets(), bAssetIdStr))])
914+ let liquidationProfit = (asset1Usd - fraction(asset0Usd, (Scale8 - penalty), Scale8))
915+ let sAssetChange = fraction(asset0Sold, Scale16, sRate)
916+ let bAssetChange = fraction(fraction(asset1Bought, Scale16, bRate), (Scale8 - fraction(liquidationProfit, Scale8, asset1Usd)), Scale8)
917+ if ((asset0Sold > assetAmount))
918+ then throw("more assets exchanged than expected")
919+ else if ((0 > liquidationProfit))
920+ then throw("price impact is bigger than liquidation penalty")
921+ else [IntegerEntry(((address + "_supplied_") + sAssetIdStr), (currentSPosition - sAssetChange)), IntegerEntry(((address + "_borrowed_") + bAssetIdStr), (currentBPosition - bAssetChange)), IntegerEntry(("total_supplied_" + sAssetIdStr), (tryGetInteger(("total_supplied_" + sAssetIdStr)) - sAssetChange)), IntegerEntry(("total_borrowed_" + bAssetIdStr), (tryGetInteger(("total_borrowed_" + bAssetIdStr)) - bAssetChange)), IntegerEntry((("fee_" + bAssetIdStr) + "_liquidation"), (tryGetInteger((("fee_" + bAssetIdStr) + "_liquidation")) + (asset1Bought - fraction(bAssetChange, bRate, Scale16))))]
922+ }
923+ else throw("Strict value is not equal to itself.")
924+ }
925+ else throw("Strict value is not equal to itself.")
926+ }
927+ else throw("Strict value is not equal to itself.")
928+ }
929+ else throw("Strict value is not equal to itself.")
930+ }
931+ else throw("Strict value is not equal to itself.")
932+ }
933+ else throw("Strict value is not equal to itself.")
934+ }
935+ }
936+ else throw("Strict value is not equal to itself.")
937+ }
938+
939+
940+
941+@Callable(i)
942+func liquidateV2 (debug,address,sAssetIdStr) = if (!(verifyLiquidatorRights(i.caller)))
943+ then throw("temporarily available for whitelist only")
944+ else if (!(tryGetBoolean("setup_active")))
945+ then throw("market is stopped")
946+ else {
947+ let bAssetId = i.payments[0].assetId
948+ let bAssetIdStr = getAssetString(bAssetId)
949+ let bAssetAmount = i.payments[0].amount
950+ let userCollateral = calcUserCollateral(address)
951+ if ((userCollateral == userCollateral))
952+ then if ((userCollateral > 0))
953+ then throw("user can't be liquidated")
954+ else {
955+ let marketAssets = getMarketAssets()
956+ let asset1Num = value(indexOf(marketAssets, bAssetIdStr))
957+ let asset0Num = value(indexOf(marketAssets, sAssetIdStr))
958+ let $t03842538487 = getActualRate(bAssetIdStr, "bRate")
959+ let bRate = $t03842538487._1
960+ let ratesResult = $t03842538487._2
961+ let asset1Price = getTokenPriceCapped(bAssetIdStr)._2
962+ let asset1Scale = calcAssetScale(bAssetIdStr)
963+ let bAmountUsd = fraction(bAssetAmount, asset1Price, asset1Scale)
964+ let penalty = parseIntValue(value(split(tryGetString("setup_penalties"), ",")[asset1Num]))
965+ let asset0Price = getTokenPriceCapped(sAssetIdStr)._1
966+ let asset0Scale = calcAssetScale(sAssetIdStr)
967+ let sAmountUsd = fraction(bAmountUsd, (Scale8 + penalty), Scale8)
968+ let sAssetAmount = fraction(sAmountUsd, asset0Scale, asset0Price)
969+ let bAmount = fraction(bAssetAmount, Scale16, bRate)
970+ let sAmount = fraction(sAssetAmount, Scale16, ratesResult[(asset0Num * 3)].value)
971+ let currentSPosition = tryGetInteger(((address + "_supplied_") + sAssetIdStr))
972+ let currentBPositionVal = tryGetInteger(((address + "_borrowed_") + bAssetIdStr))
973+ let currentBPosition = if ((currentBPositionVal > 0))
974+ then currentBPositionVal
975+ else throw("user has no borrow in this token")
976+ if ((sAmount > currentSPosition))
977+ then throw("position to liquidate is bigger than user's supply")
978+ else {
979+ let inv = if ((tryGetString(("setup_autostake_" + sAssetIdStr)) != ""))
980+ then invoke(this, "unstakeToken", [sAssetIdStr, sAssetAmount], nil)
981+ else unit
982+ if ((inv == inv))
983+ then if (debug)
984+ then throw("liquidation will pass")
985+ else ([ScriptTransfer(i.caller, sAssetAmount, getAssetBytes(sAssetIdStr)), IntegerEntry(((address + "_supplied_") + sAssetIdStr), (currentSPosition - sAmount)), IntegerEntry(((address + "_borrowed_") + bAssetIdStr), (currentBPosition - bAmount)), IntegerEntry(("total_supplied_" + sAssetIdStr), (tryGetInteger(("total_supplied_" + sAssetIdStr)) - sAmount)), IntegerEntry(("total_borrowed_" + bAssetIdStr), (tryGetInteger(("total_borrowed_" + bAssetIdStr)) - bAmount))] ++ ratesResult)
986+ else throw("Strict value is not equal to itself.")
987+ }
988+ }
989+ else throw("Strict value is not equal to itself.")
990+ }
991+
992+
993+
994+@Callable(i)
995+func getUserCollateral (debug,address,minusBorrowed,afterChange) = {
996+ let assets = getMarketAssets()
997+ let ltvs = split(tryGetString("setup_ltvs"), ",")
998+ let lts = split(tryGetString("setup_lts"), ",")
999+ let rates = getActualRate(assets[0], "sRate")._2
1000+ let changeHandler = split(afterChange, ",")
1001+ func f (accum,next) = if ((next >= size(assets)))
1002+ then accum
1003+ else {
1004+ let userSupplied = tryGetInteger(((address + "_supplied_") + assets[next]))
1005+ let userBorrowed = tryGetInteger(((address + "_borrowed_") + assets[next]))
1006+ let needTokenAccounting = if ((afterChange == ""))
1007+ then if (if ((userBorrowed != 0))
1008+ then true
1009+ else (userSupplied != 0))
1010+ then true
1011+ else false
1012+ else true
1013+ if (needTokenAccounting)
1014+ then {
1015+ let assetScale = calcAssetScale(assets[next])
1016+ let assetPrice = getTokenPriceCapped(assets[next])
1017+ ((accum + fraction(fraction(fraction((userSupplied + (if (if (if ((afterChange != ""))
1018+ then (changeHandler[0] == assets[next])
1019+ else false)
1020+ then (changeHandler[1] == "supplied")
1021+ else false)
1022+ then parseIntValue(changeHandler[2])
1023+ else 0)), rates[(next * 3)].value, Scale16), parseIntValue(ltvs[next]), Scale8), assetPrice._1, assetScale)) - (if (minusBorrowed)
1024+ then fraction(fraction(fraction((userBorrowed + (if (if (if ((afterChange != ""))
1025+ then (changeHandler[0] == assets[next])
1026+ else false)
1027+ then (changeHandler[1] == "borrowed")
1028+ else false)
1029+ then parseIntValue(changeHandler[2])
1030+ else 0)), rates[((next * 3) + 1)].value, Scale16), Scale8, parseIntValue(lts[next])), assetPrice._2, assetScale)
1031+ else 0))
1032+ }
1033+ else accum
1034+ }
1035+
1036+ let result = {
1037+ let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
1038+ let $s = size($l)
1039+ let $acc0 = 0
1040+ func $f0_1 ($a,$i) = if (($i >= $s))
1041+ then $a
1042+ else f($a, $l[$i])
1043+
1044+ func $f0_2 ($a,$i) = if (($i >= $s))
1045+ then $a
1046+ else throw("List size exceeds 12")
1047+
1048+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12)
1049+ }
1050+ if (debug)
1051+ then throw(toString(result))
1052+ else $Tuple2(rates, result)
1053+ }
1054+
1055+
1056+
1057+@Callable(i)
1058+func getPrices (debug) = {
1059+ let assets = getMarketAssets()
1060+ func f (accum,next) = if ((next >= size(assets)))
1061+ then accum
1062+ else {
1063+ let assetPrice = getTokenPriceWithRisk(assets[next], 3)
1064+ ((((accum + toString(assetPrice._1)) + ",") + toString(assetPrice._2)) + "|")
1065+ }
1066+
1067+ let result = {
1068+ let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
1069+ let $s = size($l)
1070+ let $acc0 = ""
1071+ func $f0_1 ($a,$i) = if (($i >= $s))
1072+ then $a
1073+ else f($a, $l[$i])
1074+
1075+ func $f0_2 ($a,$i) = if (($i >= $s))
1076+ then $a
1077+ else throw("List size exceeds 12")
1078+
1079+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12)
1080+ }
1081+ if (debug)
1082+ then throw(result)
1083+ else $Tuple2(nil, result)
1084+ }
1085+
1086+
1087+
1088+@Callable(i)
1089+func calculateUtilizationRatio (assetIdStr,debug) = if (debug)
1090+ then throw(toString(getUr(assetIdStr)))
1091+ else $Tuple2(nil, getUr(assetIdStr))
1092+
1093+
1094+
1095+@Callable(i)
1096+func calculateOutdatedUR (assetIdStr,debug) = if (debug)
1097+ then throw(toString(getOutdatedUr(assetIdStr)))
1098+ else $Tuple2(nil, getOutdatedUr(assetIdStr))
1099+
1100+
1101+
1102+@Callable(i)
1103+func calculateTokenRates (debug) = {
1104+ func f (accum,assetIdStr) = {
1105+ let rates = tokenRatesRecalc(assetIdStr)
1106+ $Tuple2(((((accum._1 + toString(rates[1].value)) + "|") + toString(rates[0].value)) + ","), (accum._2 ++ rates))
1107+ }
1108+
1109+ let parameter = {
1110+ let $l = getMarketAssets()
1111+ let $s = size($l)
1112+ let $acc0 = $Tuple2("", nil)
1113+ func $f0_1 ($a,$i) = if (($i >= $s))
1114+ then $a
1115+ else f($a, $l[$i])
1116+
1117+ func $f0_2 ($a,$i) = if (($i >= $s))
1118+ then $a
1119+ else throw("List size exceeds 12")
1120+
1121+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12)
1122+ }
1123+ if (debug)
1124+ then throw(parameter._1)
1125+ else $Tuple2(parameter._2, parameter._1)
1126+ }
1127+
1128+
1129+
1130+@Callable(i)
1131+func calculateTokensInterest (debug) = {
1132+ func f (accum,assetIdStr) = {
1133+ let rate = fraction(getInterest(assetIdStr), dayBlocks, Scale8)
1134+ ((accum + toString(rate)) + ",")
1135+ }
1136+
1137+ let parameter = {
1138+ let $l = getMarketAssets()
1139+ let $s = size($l)
1140+ let $acc0 = ""
1141+ func $f0_1 ($a,$i) = if (($i >= $s))
1142+ then $a
1143+ else f($a, $l[$i])
1144+
1145+ func $f0_2 ($a,$i) = if (($i >= $s))
1146+ then $a
1147+ else throw("List size exceeds 12")
1148+
1149+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12)
1150+ }
1151+ if (debug)
1152+ then throw(parameter)
1153+ else $Tuple2(nil, parameter)
1154+ }
1155+
1156+
1157+
1158+@Callable(i)
1159+func setApproverAddress (approverAddress) = {
1160+ let isSelf = if ((i.caller == this))
1161+ then true
1162+ else throw("Only self invoke")
1163+ if ((isSelf == isSelf))
1164+ then {
1165+ let _approverAddress = addressFromString(approverAddress)
1166+ let approverOk = match _approverAddress {
1167+ case t: Address =>
1168+ true
1169+ case _ =>
1170+ false
1171+ }
1172+ let canSetApprover = if (if (approverOk)
1173+ then true
1174+ else (approverAddress == ""))
1175+ then true
1176+ else throw("Wrong approver address")
1177+ if ((canSetApprover == canSetApprover))
1178+ then {
1179+ let isInited = valueOrElse(getBoolean(value(_approverAddress), "INITED"), false)
1180+ let hasAdmins = (valueOrElse(getString(value(_approverAddress), "ADMINS_PBKS"), "") != "")
1181+ let isApproverContract = if (if ((approverAddress == ""))
1182+ then true
1183+ else if (isInited)
1184+ then hasAdmins
1185+ else false)
1186+ then true
1187+ else throw("Address is not approver contract")
1188+ if ((isApproverContract == isApproverContract))
1189+ then [StringEntry("APPROVER_ADDRESS", approverAddress)]
1190+ else throw("Strict value is not equal to itself.")
1191+ }
1192+ else throw("Strict value is not equal to itself.")
1193+ }
1194+ else throw("Strict value is not equal to itself.")
1195+ }
1196+
1197+
1198+
1199+@Callable(i)
1200+func initNewMaster (master) = {
1201+ let addressOK = match addressFromString(master) {
1202+ case a: Address =>
1203+ true
1204+ case _ =>
1205+ false
1206+ }
1207+ if (!(addressOK))
1208+ then throw(("incorrect address " + master))
1209+ else if ((i.caller != this))
1210+ then throw("available for self call only")
1211+ else [StringEntry("verifier_master", master)]
1212+ }
1213+
1214+
1215+
1216+@Callable(i)
1217+func requestNewMaster (newMaster) = {
1218+ let addressOK = match addressFromString(newMaster) {
1219+ case a: Address =>
1220+ true
1221+ case _ =>
1222+ false
1223+ }
1224+ if (!(addressOK))
1225+ then throw(("incorrect address " + newMaster))
1226+ else if ((indexOf(sentinels, i.caller) == unit))
1227+ then throw("whitelist only")
1228+ else [StringEntry("verifier_newMaster", newMaster), IntegerEntry("verifier_newMasterEligibleAfter", (height + 10000))]
1229+ }
1230+
1231+
1232+
1233+@Callable(i)
1234+func activateNewMaster () = {
1235+ let eligibleHeight = getIntegerValue(this, "verifier_newMasterEligibleAfter")
1236+ let newMaster = getStringValue(this, "verifier_newMaster")
1237+ if ((indexOf(sentinels, i.caller) == unit))
1238+ then throw("whitelist only")
1239+ else if ((eligibleHeight > height))
1240+ then throw("new master cannot be activated yet")
1241+ else [DeleteEntry("verifier_newMaster"), DeleteEntry("verifier_newMasterEligibleAfter"), StringEntry("verifier_master", newMaster)]
1242+ }
1243+
1244+
1245+@Verifier(tx)
1246+func verify () = {
1247+ let multisigStr = valueOrElse(getString("APPROVER_ADDRESS"), "")
1248+ let multisigAddress = addressFromString(multisigStr)
1249+ let multisigOk = match multisigAddress {
1250+ case t: Address =>
1251+ true
1252+ case _ =>
1253+ false
1254+ }
1255+ let isInited = if (multisigOk)
1256+ then valueOrElse(getBoolean(value(multisigAddress), "INITED"), false)
1257+ else false
1258+ let hasAdmins = if (multisigOk)
1259+ then (valueOrElse(getString(value(multisigAddress), "ADMINS_PBKS"), "") != "")
1260+ else false
1261+ if (if (if (multisigOk)
1262+ then isInited
1263+ else false)
1264+ then hasAdmins
1265+ else false)
1266+ then match tx {
1267+ case ttx: SetScriptTransaction =>
1268+ match ttx.script {
1269+ case script: ByteVector =>
1270+ let scriptHasha = toBase58String(blake2b256(script))
1271+ let validFrom = valueOrErrorMessage(getInteger(value(multisigAddress), (((("script%%" + CONTRACT_TYPE) + "%%") + scriptHasha) + "%%validFrom")), "validFrom not set")
1272+ let validTo = valueOrErrorMessage(getInteger(value(multisigAddress), (((("script%%" + CONTRACT_TYPE) + "%%") + scriptHasha) + "%%validTo")), "validTo not set")
1273+ if ((height >= validFrom))
1274+ then (validTo >= height)
1275+ else false
1276+ case _ =>
1277+ false
1278+ }
1279+ case otx =>
1280+ let taskId = ((("tx_" + toString(this)) + "_") + toBase58String(otx.id))
1281+ let isApproved = valueOrElse(getBoolean(value(multisigAddress), (((toString(this) + "_") + toBase58String(otx.id)) + "__approved")), false)
1282+ let approvedFrom = valueOrElse(getInteger(value(multisigAddress), (taskId + "__approvedFrom")), 0)
1283+ if (isApproved)
1284+ then (height >= approvedFrom)
1285+ else false
1286+ }
1287+ else {
1288+ let masterAddress = getString("verifier_master")
1289+ let approvedByMaster = match masterAddress {
1290+ case x: String =>
1291+ match getInteger(addressFromStringValue(x), ("approvedTx_" + toBase58String(tx.id))) {
1292+ case y: Int =>
1293+ y
1294+ case _ =>
1295+ 0
1296+ }
1297+ case _ =>
1298+ 1
1299+ }
1300+ if (sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey))
1301+ then (approvedByMaster > 0)
1302+ else false
1303+ }
1304+ }
1305+

github/deemru/w8io
26.68 ms