tx · 2wFN1vzWGFCQ6eQ7EQWqkHTijKALeY7z8QMcDptsY6fv

3M8K8kCPftc8h4EVK6a7wFnxc6bNKFr2J2X:  -0.06000000 Waves

2026.06.24 04:27 [824754] smart account 3M8K8kCPftc8h4EVK6a7wFnxc6bNKFr2J2X > SELF 0.00000000 Waves

{ "type": 13, "id": "2wFN1vzWGFCQ6eQ7EQWqkHTijKALeY7z8QMcDptsY6fv", "fee": 6000000, "feeAssetId": null, "timestamp": 1782264434960, "version": 2, "chainId": 82, "sender": "3M8K8kCPftc8h4EVK6a7wFnxc6bNKFr2J2X", "senderPublicKey": "8VMqkR6ZPJL2CKCVYmgiWw7rUmcsvmxNVpfSvNfEDUFT", "proofs": [ "4ufGVibZ4Xp1UzUXRkMTbLivd1xC2t9toKC7ZXXzUQgUku3jWe1ZGy66PZNsPcZohvpB4nG718t1kav9c8u5JcNr" ], "script": "base64:BgKqAQgCEgASBAoCCAESBAoCCAESABIDCgEIEgQKAggBEgMKAQgSBAoCCAESBAoCCAESABIGCgQICAgIEgYKBAgICAgSBAoCCAgSBAoCCAgSAwoBBBIDCgEIEgMKAQgSAwoBCBIDCgEEEggKBgQIAQgICBIFCgMECAgSBgoEBAgECBIDCgEEEgQKAggEEgQKAggEEgMKAQQSAwoBBBIDCgEIEgMKAQgSAwoBCBIALQANQ09OVFJBQ1RfVFlQRQIOTEVORC1MUC1NQVJLRVQAB1ZFUlNJT04CCVBMUC0xLjIuMQETZ2V0QWRkcmVzc0Zyb21TdGF0ZQEDa2V5CQELdmFsdWVPckVsc2UCCQCmCAEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwkArAICAg5zZXR1cF9hZGRyZXNzXwUDa2V5AiMzUEV3UmNZTkFVdG9GdktwQmhLb2l3YWpuWmZkb0RSNmg0aAkBB0FkZHJlc3MBARoBV46zaotfT5rTy6/BBdbIYhwwXDI85kwhvgEVZ2V0QWRkcmVzc2VzRnJvbVN0YXRlAQNrZXkKAQFmAgVhY2N1bQRuZXh0CQDOCAIFBWFjY3VtCQDMCAIJAQt2YWx1ZU9yRWxzZQIJAKYIAQUEbmV4dAkBB0FkZHJlc3MBARoBV46zaotfT5rTy6/BBdbIYhwwXDI85kwhvgUDbmlsCgACJGwJALwJAgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzCQCsAgICDnNldHVwX2FkZHJlc3NfBQNrZXkCIzNQRXdSY1lOQVV0b0Z2S3BCaEtvaXdham5aZmRvRFI2aDRoAgEsCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQFmAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxNQkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAScmVzZXJ2ZUZ1bmRBZGRyZXNzCQETZ2V0QWRkcmVzc0Zyb21TdGF0ZQECC3Jlc2VydmVGdW5kAA1vcmFjbGVBZGRyZXNzCQETZ2V0QWRkcmVzc0Zyb21TdGF0ZQECBm9yYWNsZQARYWdncmVnYXRvckFkZHJlc3MJARNnZXRBZGRyZXNzRnJvbVN0YXRlAQIKYWdncmVnYXRvcgAMYWRtaW5BZGRyZXNzCQETZ2V0QWRkcmVzc0Zyb21TdGF0ZQECBWFkbWluABFzdGFibGVGdW5kQWRkcmVzcwkBE2dldEFkZHJlc3NGcm9tU3RhdGUBAgpzdGFibGVGdW5kABNmZWVDb2xsZWN0b3JBZGRyZXNzCQETZ2V0QWRkcmVzc0Zyb21TdGF0ZQECDGZlZUNvbGxlY3RvcgARc2h1dGRvd25XaGl0ZWxpc3QJARVnZXRBZGRyZXNzZXNGcm9tU3RhdGUBAg9zaHV0ZG93bkNhbGxlcnMAFGxpcXVpZGF0b3JzV2hpdGVsaXN0CQEVZ2V0QWRkcmVzc2VzRnJvbVN0YXRlAQILbGlxdWlkYXRvcnMBFnZlcmlmeUxpcXVpZGF0b3JSaWdodHMBB2FkZHJlc3MJAQIhPQIJAM8IAgUUbGlxdWlkYXRvcnNXaGl0ZWxpc3QFB2FkZHJlc3MFBHVuaXQAC3Jlc2VydmVGdW5kCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMCFHNldHVwX3Jlc2VydmVGdW5kRmVlABQADHN0YWJsZXNJZFN0cgkAtQkCCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMCEHNldHVwX3N0YWJsZXNJZHMCWTl3YzNMWE5BNFRFQnNYeUt0b0xFOW1yYkREN1dNSFh2WHJDalp2YWJMQXNpLEhHZ2FiVHFVUzhXdFZGVUp6Zm1yVERNZ0VjY0p1WkxCUGhGZ1FGeHZuc29XAgEsAQxnZXRSYXRlQ3VydmUBCmFzc2V0SWRTdHIEDmN1cnZlUmF0ZVN0ckxpCQC1CQIJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwkArAICAhBzZXR1cF9yYXRlQ3VydmVfBQphc3NldElkU3RyAiUyMDAwMDAwMCwxMDAwMDAwMDAsNjAwMDAwMDAsNDAwMDAwMDAwAgEsCQCWCgQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQ5jdXJ2ZVJhdGVTdHJMaQAACQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUOY3VydmVSYXRlU3RyTGkAAQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFDmN1cnZlUmF0ZVN0ckxpAAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQ5jdXJ2ZVJhdGVTdHJMaQADARNnZXRSZXdhcmRzU3BsaXR0aW5nAQphc3NldElkU3RyBBVyZXdhcmRzU3BsaXR0aW5nU3RyTGkJALUJAgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzCQCsAgICF3NldHVwX3Jld2FyZHNTcGxpdHRpbmdfBQphc3NldElkU3RyAggzMCw1MCwyMAIBLAkAlQoDCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUVcmV3YXJkc1NwbGl0dGluZ1N0ckxpAAAJAQ1wYXJzZUludFZhbHVlAQkAkQMCBRVyZXdhcmRzU3BsaXR0aW5nU3RyTGkAAQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFFXJld2FyZHNTcGxpdHRpbmdTdHJMaQACAAlzZW50aW5lbHMJAMwIAgkBB0FkZHJlc3MBARoBV9fhI1GOfKuIWtXXKJd12Ih104+uIwWm4QkAzAgCCQEHQWRkcmVzcwEBGgFX+Pr6AibAUYvsajtGM0nSHHGwdYv5pMqaCQDMCAIJAQdBZGRyZXNzAQEaAVdJARj2Q38/TGzhZ3Xlt+SXL95QLbKD3fEJAMwIAgkBB0FkZHJlc3MBARoBV0vDbM77M1hDWENREO7v7iEQF0vyeMt8MgUDbmlsAAZTY2FsZTgAgMLXLwAHU2NhbGUxMACAyK+gJQAHU2NhbGUxNgkAaAIFBlNjYWxlOAUGU2NhbGU4AAlkYXlCbG9ja3MAoAsAFXdpdGhkcmF3YWxMaW1pdEJsb2NrcwkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzAhtzZXR1cF93aXRoZHJhd2FsTGltaXRCbG9ja3MAZAEKbGlJbnRUb1N0cgECbGkKAQFmAgVhY2N1bQRuZXh0CQCsAgIJAKwCAgUFYWNjdW0JAKQDAQUEbmV4dAIBLAoAAiRsBQJsaQoAAiRzCQCQAwEFAiRsCgAFJGFjYzACAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEBZgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTIJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwBDXRyeUdldEludGVnZXIBA2tleQQHJG1hdGNoMAkAmggCBQR0aGlzBQNrZXkDCQABAgUHJG1hdGNoMAIDSW50BAFiBQckbWF0Y2gwBQFiAAABDXRyeUdldEJvb2xlYW4BA2tleQQHJG1hdGNoMAkAmwgCBQR0aGlzBQNrZXkDCQABAgUHJG1hdGNoMAIHQm9vbGVhbgQBYgUHJG1hdGNoMAUBYgcBDHRyeUdldFN0cmluZwEDa2V5BAckbWF0Y2gwCQCdCAIFBHRoaXMFA2tleQMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAWIFByRtYXRjaDAFAWICAAEMdHJ5R2V0QmluYXJ5AQNrZXkEByRtYXRjaDAJAJwIAgUEdGhpcwUDa2V5AwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEAWIFByRtYXRjaDAFAWIBAAEOZ2V0QXNzZXRTdHJpbmcBB2Fzc2V0SWQEByRtYXRjaDAFB2Fzc2V0SWQDCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQBYgUHJG1hdGNoMAkA2AQBBQFiAgVXQVZFUwENZ2V0QXNzZXRCeXRlcwEKYXNzZXRJZFN0cgMJAAACBQphc3NldElkU3RyAgVXQVZFUwUEdW5pdAkA2QQBBQphc3NldElkU3RyAQpnZXRCYWxhbmNlAQphc3NldElkU3RyAwkAAAIFCmFzc2V0SWRTdHICBVdBVkVTCAkA7wcBBQR0aGlzCWF2YWlsYWJsZQkA8AcCBQR0aGlzCQDZBAEFCmFzc2V0SWRTdHIBD2dldE1hcmtldEFzc2V0cwAJALUJAgkBDHRyeUdldFN0cmluZwECDHNldHVwX3Rva2VucwIBLAENZ2V0T3V0ZGF0ZWRVcgEKYXNzZXRJZFN0cgQEZG93bgkAawMJAQ10cnlHZXRJbnRlZ2VyAQkArAICAg90b3RhbF9zdXBwbGllZF8FCmFzc2V0SWRTdHIJAQ10cnlHZXRJbnRlZ2VyAQkArAICBQphc3NldElkU3RyAgZfc1JhdGUFB1NjYWxlMTYDCQAAAgUEZG93bgAAAAAJAGsDBQZTY2FsZTgJAGsDCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfYm9ycm93ZWRfBQphc3NldElkU3RyCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgUKYXNzZXRJZFN0cgIGX2JSYXRlBQdTY2FsZTE2BQRkb3duAQtnZXRJbnRlcmVzdAEKYXNzZXRJZFN0cgQCdXIJAQ1nZXRPdXRkYXRlZFVyAQUKYXNzZXRJZFN0cgQFY3VydmUJAQxnZXRSYXRlQ3VydmUBBQphc3NldElkU3RyBARyYXRlCQBkAggFBWN1cnZlAl8xAwkAZwIIBQVjdXJ2ZQJfMwUCdXIJAGsDBQJ1cggFBWN1cnZlAl8yCAUFY3VydmUCXzMJAGQCCAUFY3VydmUCXzIJAGsDCQBlAgUCdXIIBQVjdXJ2ZQJfMwgFBWN1cnZlAl80CQBlAgCAwtcvCAUFY3VydmUCXzMJAJYDAQkAzAgCCQBrAwUEcmF0ZQUGU2NhbGU4CQBoAgUJZGF5QmxvY2tzAO0CCQDMCAIAAQUDbmlsARB0b2tlblJhdGVzUmVjYWxjAQphc3NldElkU3RyBAhpbnRlcmVzdAkBC2dldEludGVyZXN0AQUKYXNzZXRJZFN0cgQCdXIJAQ1nZXRPdXRkYXRlZFVyAQUKYXNzZXRJZFN0cgQQbGFzdFJlY2FsY0hlaWdodAkBDXRyeUdldEludGVnZXIBAg5sYXN0UmF0ZUhlaWdodAQJbGFzdEJSYXRlCQCWAwEJAMwIAgkBDXRyeUdldEludGVnZXIBCQCsAgIFCmFzc2V0SWRTdHICBl9iUmF0ZQkAzAgCBQdTY2FsZTE2BQNuaWwECG5ld0JSYXRlCQBkAgUJbGFzdEJSYXRlCQBoAgkAZQIFBmhlaWdodAUQbGFzdFJlY2FsY0hlaWdodAUIaW50ZXJlc3QECWxhc3RTUmF0ZQkAlgMBCQDMCAIJAQ10cnlHZXRJbnRlZ2VyAQkArAICBQphc3NldElkU3RyAgZfc1JhdGUJAMwIAgUHU2NhbGUxNgUDbmlsBAhuZXdTUmF0ZQkAZAIFCWxhc3RTUmF0ZQkAaQIJAGgCCQBoAgkAZQIFBmhlaWdodAUQbGFzdFJlY2FsY0hlaWdodAkAawMFCGludGVyZXN0BQJ1cgUGU2NhbGU4CQBlAgBkBQtyZXNlcnZlRnVuZABkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIFCmFzc2V0SWRTdHICBl9zUmF0ZQUIbmV3U1JhdGUJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgUKYXNzZXRJZFN0cgIGX2JSYXRlBQhuZXdCUmF0ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgIObGFzdFJhdGVIZWlnaHQFBmhlaWdodAUDbmlsAQ1nZXRBY3R1YWxSYXRlAgphc3NldElkU3RyCHJhdGVUeXBlCgEBZgIFYWNjdW0FdG9rZW4EBnJlY2FsYwkBEHRva2VuUmF0ZXNSZWNhbGMBBQV0b2tlbgkAlAoCAwkBAiE9AgUFdG9rZW4FCmFzc2V0SWRTdHIIBQVhY2N1bQJfMQMJAAACBQhyYXRlVHlwZQIFc1JhdGUICQCRAwIFBnJlY2FsYwAABXZhbHVlCAkAkQMCBQZyZWNhbGMAAQV2YWx1ZQkAzggCCAUFYWNjdW0CXzIFBnJlY2FsYwoAAiRsCQEPZ2V0TWFya2V0QXNzZXRzAAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJQKAgAABQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBAWYCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEyCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAQVnZXRVcgEKYXNzZXRJZFN0cgQFcmF0ZXMJARB0b2tlblJhdGVzUmVjYWxjAQUKYXNzZXRJZFN0cgQEZG93bgkAawMJAQ10cnlHZXRJbnRlZ2VyAQkArAICAg90b3RhbF9zdXBwbGllZF8FCmFzc2V0SWRTdHIICQCRAwIFBXJhdGVzAAAFdmFsdWUFB1NjYWxlMTYJAGsDBQZTY2FsZTgJAGsDCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfYm9ycm93ZWRfBQphc3NldElkU3RyCAkAkQMCBQVyYXRlcwABBXZhbHVlBQdTY2FsZTE2BQRkb3duAQtyYXRlc1JlY2FsYwAKAQFmAgVhY2N1bQV0b2tlbgkAzggCBQVhY2N1bQkBEHRva2VuUmF0ZXNSZWNhbGMBBQV0b2tlbgoAAiRsCQEPZ2V0TWFya2V0QXNzZXRzAAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEBZgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTIJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwBFWdldFRva2VuUHJpY2VXaXRoUmlzawIKYXNzZXRJZFN0cgxyaXNrQXZlcnNpdHkDCQECIT0CCQDPCAIFDHN0YWJsZXNJZFN0cgUKYXNzZXRJZFN0cgUEdW5pdAkAlAoCAMCEPQDAhD0EBXByaWNlCQERQGV4dHJOYXRpdmUoMTA1MCkCBQ1vcmFjbGVBZGRyZXNzCQCsAgIFCmFzc2V0SWRTdHICB190d2FwNUIECXJpc2tMZXZlbAkBEUBleHRyTmF0aXZlKDEwNTApAgUNb3JhY2xlQWRkcmVzcwkArAICBQphc3NldElkU3RyAgpfcmlza0xldmVsAwkAZwIFDHJpc2tBdmVyc2l0eQUJcmlza0xldmVsCQCUCgIFBXByaWNlBQVwcmljZQkAAgEJAKwCAgkArAICAhtvcmFjbGUgcHJpY2VzIGRvbid0IG1hdGNoOiAJAKQDAQUFcHJpY2UCIyBpcyB0aGUgcHJpY2UsIGJ1dCByaXNrIGlzIHRvbyBoaWdoAQ1nZXRUb2tlblByaWNlAQphc3NldElkU3RyCQEVZ2V0VG9rZW5QcmljZVdpdGhSaXNrAgUKYXNzZXRJZFN0cgADARNnZXRUb2tlblByaWNlQ2FwcGVkAQphc3NldElkU3RyBAskdDA3OTg3ODA1MAkBFWdldFRva2VuUHJpY2VXaXRoUmlzawIFCmFzc2V0SWRTdHIAAwQIbWluUHJpY2UIBQskdDA3OTg3ODA1MAJfMQQIbWF4UHJpY2UIBQskdDA3OTg3ODA1MAJfMgQPbWF4QWxsb3dlZFByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAKwCAgIPc2V0dXBfbWF4UHJpY2VfBQphc3NldElkU3RyAP///////////wEED21pbkFsbG93ZWRQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgICD3NldHVwX21pblByaWNlXwUKYXNzZXRJZFN0cgD///////////8BAwMJAQIhPQIFD21heEFsbG93ZWRQcmljZQD///////////8BCQBmAgUIbWF4UHJpY2UFD21heEFsbG93ZWRQcmljZQcJAJQKAgUPbWF4QWxsb3dlZFByaWNlBQ9tYXhBbGxvd2VkUHJpY2UDAwkBAiE9AgUPbWluQWxsb3dlZFByaWNlAP///////////wEJAGYCBQ9taW5BbGxvd2VkUHJpY2UFCG1pblByaWNlBwkAlAoCBQ9taW5BbGxvd2VkUHJpY2UFD21pbkFsbG93ZWRQcmljZQkAlAoCBQhtaW5QcmljZQUIbWF4UHJpY2UBDmNhbGNBc3NldFNjYWxlAQphc3NldElkU3RyBAhkZWNpbWFscwMJAAACBQphc3NldElkU3RyAgVXQVZFUwAICAkBBXZhbHVlAQkA7AcBCQDZBAEFCmFzc2V0SWRTdHIIZGVjaW1hbHMJAGwGAAoAAAUIZGVjaW1hbHMAAAAABQRET1dOARJjYWxjVXNlckNvbGxhdGVyYWwBB2FkZHJlc3MEFHVzZXJDb2xsYXRlcmFsSW52b2tlCQD8BwQFBHRoaXMCEWdldFVzZXJDb2xsYXRlcmFsCQDMCAIHCQDMCAIFB2FkZHJlc3MJAMwIAgYJAMwIAgIABQNuaWwFA25pbAMJAAACBRR1c2VyQ29sbGF0ZXJhbEludm9rZQUUdXNlckNvbGxhdGVyYWxJbnZva2UEE3VzZXJDb2xsYXRlcmFsVmFsdWUEByRtYXRjaDAFFHVzZXJDb2xsYXRlcmFsSW52b2tlAwkAAQIFByRtYXRjaDACA0ludAQBeAUHJG1hdGNoMAUBeAkAAgECJGlzc3VlIHdoaWxlIGRvaW5nIGluLWRhcHAgaW52b2NhdGlvbgMJAAACBRN1c2VyQ29sbGF0ZXJhbFZhbHVlBRN1c2VyQ29sbGF0ZXJhbFZhbHVlBRN1c2VyQ29sbGF0ZXJhbFZhbHVlCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuARRjaGVja1dpdGhkcmF3YWxMaW1pdAQHYWRkcmVzcwphc3NldElkU3RyDmFtb3VudEludGVybmFsBXNSYXRlBA93aXRoZHJhd2FsTGltaXQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkArAICCQCsAgICBnNldHVwXwUKYXNzZXRJZFN0cgITX21heFdpdGhkcmF3UGVyMTAwQgD///////////8BAwkAAAIFD3dpdGhkcmF3YWxMaW1pdAD///////////8BBQNuaWwEDXRvdGFsU3VwcGxpZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICAg90b3RhbF9zdXBwbGllZF8FCmFzc2V0SWRTdHIECGxpbWl0Q2FwCQBrAwUNdG90YWxTdXBwbGllZAUPd2l0aGRyYXdhbExpbWl0AGQEBWxhc3RICQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICBQdhZGRyZXNzAhVfd2l0aGRyYXdMaW1pdEhlaWdodF8FCmFzc2V0SWRTdHIEB2VsYXBzZWQJAGUCBQZoZWlnaHQFBWxhc3RIBA13aW5kb3dFeHBpcmVkCQBmAgUHZWxhcHNlZAUVd2l0aGRyYXdhbExpbWl0QmxvY2tzBAtjdXJyZW50VXNlZAMFDXdpbmRvd0V4cGlyZWQAAAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgUHYWRkcmVzcwITX3dpdGhkcmF3TGltaXRVc2VkXwUKYXNzZXRJZFN0cgQNYmxvY2tzVG9SZXNldAMFDXdpbmRvd0V4cGlyZWQFFXdpdGhkcmF3YWxMaW1pdEJsb2NrcwkAZQIFFXdpdGhkcmF3YWxMaW1pdEJsb2NrcwUHZWxhcHNlZAQJYXZhaWxhYmxlCQBlAgUIbGltaXRDYXAFC2N1cnJlbnRVc2VkBA9hdmFpbGFibGVTY2FsZWQJAG4EBQlhdmFpbGFibGUFBXNSYXRlBQdTY2FsZTE2BQdDRUlMSU5HAwkAZgIFDmFtb3VudEludGVybmFsBQlhdmFpbGFibGUJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIed2l0aGRyYXdhbCBsaW1pdCBleGNlZWRlZCBmb3IgBQphc3NldElkU3RyAg0sIGF2YWlsYWJsZTogCQCkAwEFD2F2YWlsYWJsZVNjYWxlZAITLCBibG9ja3MgdG8gcmVzZXQ6IAkApAMBBQ1ibG9ja3NUb1Jlc2V0CQDOCAIDBQ13aW5kb3dFeHBpcmVkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgUHYWRkcmVzcwIVX3dpdGhkcmF3TGltaXRIZWlnaHRfBQphc3NldElkU3RyBQZoZWlnaHQFA25pbAUDbmlsCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgUHYWRkcmVzcwITX3dpdGhkcmF3TGltaXRVc2VkXwUKYXNzZXRJZFN0cgkAZAIFC2N1cnJlbnRVc2VkBQ5hbW91bnRJbnRlcm5hbAUDbmlsARBjaGVja0JvcnJvd0xpbWl0BQdhZGRyZXNzCmFzc2V0SWRTdHIOYW1vdW50SW50ZXJuYWwFYlJhdGUFc1JhdGUEC2JvcnJvd0xpbWl0CQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAKwCAgkArAICAgZzZXR1cF8FCmFzc2V0SWRTdHICEV9tYXhCb3Jyb3dQZXIxMDBCAP///////////wEDCQAAAgULYm9ycm93TGltaXQA////////////AQUDbmlsBA10b3RhbFN1cHBsaWVkCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfc3VwcGxpZWRfBQphc3NldElkU3RyBA5saW1pdENhcFN1cHBseQkAawMFDXRvdGFsU3VwcGxpZWQFC2JvcnJvd0xpbWl0AGQECGxpbWl0Q2FwCQBrAwkAawMFDmxpbWl0Q2FwU3VwcGx5BQVzUmF0ZQUHU2NhbGUxNgUHU2NhbGUxNgUFYlJhdGUEBWxhc3RICQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICBQdhZGRyZXNzAhNfYm9ycm93TGltaXRIZWlnaHRfBQphc3NldElkU3RyBAdlbGFwc2VkCQBlAgUGaGVpZ2h0BQVsYXN0SAQNd2luZG93RXhwaXJlZAkAZgIFB2VsYXBzZWQFFXdpdGhkcmF3YWxMaW1pdEJsb2NrcwQLY3VycmVudFVzZWQDBQ13aW5kb3dFeHBpcmVkAAAJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgIFB2FkZHJlc3MCEV9ib3Jyb3dMaW1pdFVzZWRfBQphc3NldElkU3RyBA1ibG9ja3NUb1Jlc2V0AwUNd2luZG93RXhwaXJlZAUVd2l0aGRyYXdhbExpbWl0QmxvY2tzCQBlAgUVd2l0aGRyYXdhbExpbWl0QmxvY2tzBQdlbGFwc2VkBAlhdmFpbGFibGUJAGUCBQhsaW1pdENhcAULY3VycmVudFVzZWQED2F2YWlsYWJsZVNjYWxlZAkAbgQFCWF2YWlsYWJsZQUFYlJhdGUFB1NjYWxlMTYFB0NFSUxJTkcDCQBmAgUOYW1vdW50SW50ZXJuYWwFCWF2YWlsYWJsZQkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAhpib3Jyb3cgbGltaXQgZXhjZWVkZWQgZm9yIAUKYXNzZXRJZFN0cgINLCBhdmFpbGFibGU6IAkApAMBBQ9hdmFpbGFibGVTY2FsZWQCEywgYmxvY2tzIHRvIHJlc2V0OiAJAKQDAQUNYmxvY2tzVG9SZXNldAkAzggCAwUNd2luZG93RXhwaXJlZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgIFB2FkZHJlc3MCE19ib3Jyb3dMaW1pdEhlaWdodF8FCmFzc2V0SWRTdHIFBmhlaWdodAUDbmlsBQNuaWwJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkArAICBQdhZGRyZXNzAhFfYm9ycm93TGltaXRVc2VkXwUKYXNzZXRJZFN0cgkAZAIFC2N1cnJlbnRVc2VkBQ5hbW91bnRJbnRlcm5hbAUDbmlsHwFpAQZzdXBwbHkAAwkBASEBCQENdHJ5R2V0Qm9vbGVhbgECDHNldHVwX2FjdGl2ZQkAAgECEW1hcmtldCBpcyBzdG9wcGVkAwMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQYJAAACCAkAkQMCCAUBaQhwYXltZW50cwAABmFtb3VudAAACQACAQIcMSBwYXltZW50IGhhcyB0byBiZSBhdHRhY2hlZAQKYXNzZXRJZFN0cgkBDmdldEFzc2V0U3RyaW5nAQgJAJEDAggFAWkIcGF5bWVudHMAAAdhc3NldElkBAthc3NldEFtb3VudAgJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQEDSR0MDEyMDU4MTIxMjUJAQ1nZXRBY3R1YWxSYXRlAgUKYXNzZXRJZFN0cgIFc1JhdGUEBXNSYXRlCAUNJHQwMTIwNTgxMjEyNQJfMQQRcmF0ZXNSZWNhbGNSZXN1bHQIBQ0kdDAxMjA1ODEyMTI1Al8yBAZhbW91bnQJAG4EBQthc3NldEFtb3VudAUHU2NhbGUxNgUFc1JhdGUFBERPV04EB2FkZHJlc3MJAKUIAQgFAWkGY2FsbGVyBAltYXhTdXBwbHkEByRtYXRjaDAJAKIIAQkArAICAhBzZXR1cF9tYXhTdXBwbHlfBQphc3NldElkU3RyAwkAAQIFByRtYXRjaDACBlN0cmluZwQBeAUHJG1hdGNoMAkBDXBhcnNlSW50VmFsdWUBBQF4CQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIQc2V0dXBfbWF4U3VwcGx5XwUKYXNzZXRJZFN0cgQKYXNzZXRQcmljZQkBE2dldFRva2VuUHJpY2VDYXBwZWQBBQphc3NldElkU3RyBBJuZXdBZGRyZXNzU3VwcGxpZWQJAGQCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICBQdhZGRyZXNzAgpfc3VwcGxpZWRfBQphc3NldElkU3RyBQZhbW91bnQEEG5ld1RvdGFsU3VwcGxpZWQJAGQCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfc3VwcGxpZWRfBQphc3NldElkU3RyBQZhbW91bnQEBHJhdGUICQENZ2V0QWN0dWFsUmF0ZQIFCmFzc2V0SWRTdHICBXNSYXRlAl8xBAphc3NldFNjYWxlCQEOY2FsY0Fzc2V0U2NhbGUBBQphc3NldElkU3RyBBNuZXdUb3RhbFN1cHBsaWVkVXNkCQBrAwkAawMFEG5ld1RvdGFsU3VwcGxpZWQFBHJhdGUFB1NjYWxlMTYIBQphc3NldFByaWNlAl8xBQphc3NldFNjYWxlAwkAAAIJALMJAgkBDHRyeUdldFN0cmluZwECDHNldHVwX3Rva2VucwUKYXNzZXRJZFN0cgUEdW5pdAkAAgECKXRoaXMgYXNzZXQgaXMgbm90IHN1cHBvcnRlZCBieSB0aGUgbWFya2V0AwMJAQIhPQIFCW1heFN1cHBseQAACQBmAgUTbmV3VG90YWxTdXBwbGllZFVzZAUJbWF4U3VwcGx5BwkAAgECM21heCB0b3RhbCBzdXBwbHkgZm9yIHRoaXMgdG9rZW4gcmVhY2hlZCBpbiB0aGUgcG9vbAMJAGYCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgINc2V0dXBfcGF1c2VkXwUKYXNzZXRJZFN0cgAACQACAQIodGhpcyBhc3NldCBjYW4ndCBiZSBzdXBwbGllZCBvciBib3Jyb3dlZAQDaW52AwkBAiE9AgkBDHRyeUdldFN0cmluZwEJAKwCAgIQc2V0dXBfYXV0b3N0YWtlXwUKYXNzZXRJZFN0cgIACQD8BwQFBHRoaXMCCnN0YWtlVG9rZW4JAMwIAgUKYXNzZXRJZFN0cgkAzAgCBQthc3NldEFtb3VudAUDbmlsBQNuaWwFBHVuaXQDCQAAAgUDaW52BQNpbnYJAM4IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgIFB2FkZHJlc3MCCl9zdXBwbGllZF8FCmFzc2V0SWRTdHIFEm5ld0FkZHJlc3NTdXBwbGllZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAg90b3RhbF9zdXBwbGllZF8FCmFzc2V0SWRTdHIFEG5ld1RvdGFsU3VwcGxpZWQFA25pbAURcmF0ZXNSZWNhbGNSZXN1bHQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEId2l0aGRyYXcCCmFzc2V0SWRTdHILYXNzZXRBbW91bnQEDSR0MDEzNjkyMTM3NTkJAQ1nZXRBY3R1YWxSYXRlAgUKYXNzZXRJZFN0cgIFc1JhdGUEBXNSYXRlCAUNJHQwMTM2OTIxMzc1OQJfMQQRcmF0ZXNSZWNhbGNSZXN1bHQIBQ0kdDAxMzY5MjEzNzU5Al8yBAZhbW91bnQJAG4EBQthc3NldEFtb3VudAUHU2NhbGUxNgUFc1JhdGUFB0NFSUxJTkcEB2FkZHJlc3MJAKUIAQgFAWkGY2FsbGVyBA1hc3NldFN1cHBsaWVkCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfc3VwcGxpZWRfBQphc3NldElkU3RyBA1hc3NldEJvcnJvd2VkCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfYm9ycm93ZWRfBQphc3NldElkU3RyBBF1c2VyQXNzZXRTdXBwbGllZAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgUHYWRkcmVzcwIKX3N1cHBsaWVkXwUKYXNzZXRJZFN0cgQRdXNlckFzc2V0Qm9ycm93ZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgIFB2FkZHJlc3MCCl9ib3Jyb3dlZF8FCmFzc2V0SWRTdHIEEmNvbGxhdGVyYWxWYWx1ZUludgkA/AcEBQR0aGlzAhFnZXRVc2VyQ29sbGF0ZXJhbAkAzAgCBwkAzAgCBQdhZGRyZXNzCQDMCAIGCQDMCAIJAKwCAgkArAICBQphc3NldElkU3RyAgosc3VwcGxpZWQsCQCkAwEJAQEtAQUGYW1vdW50BQNuaWwFA25pbAMJAAACBRJjb2xsYXRlcmFsVmFsdWVJbnYFEmNvbGxhdGVyYWxWYWx1ZUludgQPY29sbGF0ZXJhbFZhbHVlBAckbWF0Y2gwBRJjb2xsYXRlcmFsVmFsdWVJbnYDCQABAgUHJG1hdGNoMAIDSW50BAF4BQckbWF0Y2gwBQF4CQACAQIfY2FuJ3QgZ2V0IHVzZXIgY29sbGF0ZXJhbCB2YWx1ZQMJAQEhAQkBDXRyeUdldEJvb2xlYW4BAgxzZXR1cF9hY3RpdmUJAAIBAhFtYXJrZXQgaXMgc3RvcHBlZAMJAGYCAAAFD2NvbGxhdGVyYWxWYWx1ZQkAAgECMnlvdSBkb250IGhhdmUgZW5vdWdoIGNvbGxhdGVyYWwgZm9yIHRoaXMgb3BlcmF0aW9uAwkAZgIFBmFtb3VudAkAZQIFDWFzc2V0U3VwcGxpZWQFDWFzc2V0Qm9ycm93ZWQJAAIBAip0aGlzIGFtb3VudCBpcyBub3QgYXZhaWxhYmxlIG9uIHRoZSBtYXJrZXQDCQBmAgUGYW1vdW50CQBlAgURdXNlckFzc2V0U3VwcGxpZWQFEXVzZXJBc3NldEJvcnJvd2VkCQACAQIqdGhpcyBhbW91bnQgaXMgbm90IGF2YWlsYWJsZSBmb3IgdGhpcyB1c2VyBANpbnYDCQECIT0CCQEMdHJ5R2V0U3RyaW5nAQkArAICAhBzZXR1cF9hdXRvc3Rha2VfBQphc3NldElkU3RyAgAJAPwHBAUEdGhpcwIMdW5zdGFrZVRva2VuCQDMCAIFCmFzc2V0SWRTdHIJAMwIAgULYXNzZXRBbW91bnQFA25pbAUDbmlsBQR1bml0AwkAAAIFA2ludgUDaW52BBFsaW1pdENoZWNrQWN0aW9ucwkBFGNoZWNrV2l0aGRyYXdhbExpbWl0BAUHYWRkcmVzcwUKYXNzZXRJZFN0cgUGYW1vdW50BQVzUmF0ZQMJAAACBRFsaW1pdENoZWNrQWN0aW9ucwURbGltaXRDaGVja0FjdGlvbnMJAM4IAgkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgUHYWRkcmVzcwIKX3N1cHBsaWVkXwUKYXNzZXRJZFN0cgkAZQIJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgIFB2FkZHJlc3MCCl9zdXBwbGllZF8FCmFzc2V0SWRTdHIFBmFtb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAg90b3RhbF9zdXBwbGllZF8FCmFzc2V0SWRTdHIJAGUCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfc3VwcGxpZWRfBQphc3NldElkU3RyBQZhbW91bnQJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyBQthc3NldEFtb3VudAkBDWdldEFzc2V0Qnl0ZXMBBQphc3NldElkU3RyBQNuaWwFEXJhdGVzUmVjYWxjUmVzdWx0BRFsaW1pdENoZWNrQWN0aW9ucwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQZib3Jyb3cCCmFzc2V0SWRTdHILYXNzZXRBbW91bnQEB2FkZHJlc3MJAKUIAQgFAWkGY2FsbGVyBA0kdDAxNTUyMzE1NTkwCQENZ2V0QWN0dWFsUmF0ZQIFCmFzc2V0SWRTdHICBWJSYXRlBAViUmF0ZQgFDSR0MDE1NTIzMTU1OTACXzEEEXJhdGVzUmVjYWxjUmVzdWx0CAUNJHQwMTU1MjMxNTU5MAJfMgQGYW1vdW50CQBuBAULYXNzZXRBbW91bnQFB1NjYWxlMTYFBWJSYXRlBQdDRUlMSU5HBBJjb2xsYXRlcmFsVmFsdWVJbnYJAPwHBAUEdGhpcwIRZ2V0VXNlckNvbGxhdGVyYWwJAMwIAgcJAMwIAgUHYWRkcmVzcwkAzAgCBgkAzAgCCQCsAgIJAKwCAgUKYXNzZXRJZFN0cgIKLGJvcnJvd2VkLAkApAMBBQZhbW91bnQFA25pbAUDbmlsAwkAAAIFEmNvbGxhdGVyYWxWYWx1ZUludgUSY29sbGF0ZXJhbFZhbHVlSW52BA9jb2xsYXRlcmFsVmFsdWUEByRtYXRjaDAFEmNvbGxhdGVyYWxWYWx1ZUludgMJAAECBQckbWF0Y2gwAgNJbnQEAXgFByRtYXRjaDAFAXgJAAIBAh9jYW4ndCBnZXQgdXNlciBjb2xsYXRlcmFsIHZhbHVlAwkBASEBCQENdHJ5R2V0Qm9vbGVhbgECDHNldHVwX2FjdGl2ZQkAAgECEW1hcmtldCBpcyBzdG9wcGVkAwkAZgIAAAUPY29sbGF0ZXJhbFZhbHVlCQACAQIheW91IGhhdmUgdG8gc3VwcGx5IG1vcmUgdG8gYm9ycm93AwkAAAIJAQ10cnlHZXRJbnRlZ2VyAQkArAICAhRzZXR1cF9ib3Jyb3dFbmFibGVkXwUKYXNzZXRJZFN0cgAACQACAQIcdGhpcyBhc3NldCBjYW4ndCBiZSBib3Jyb3dlZAMJAGYCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgINc2V0dXBfcGF1c2VkXwUKYXNzZXRJZFN0cgAACQACAQIodGhpcyBhc3NldCBjYW4ndCBiZSBzdXBwbGllZCBvciBib3Jyb3dlZAQNYXNzZXRTdXBwbGllZAkBDXRyeUdldEludGVnZXIBCQCsAgICD3RvdGFsX3N1cHBsaWVkXwUKYXNzZXRJZFN0cgQNYXNzZXRCb3Jyb3dlZAkBDXRyeUdldEludGVnZXIBCQCsAgICD3RvdGFsX2JvcnJvd2VkXwUKYXNzZXRJZFN0cgQRdXNlckFzc2V0Qm9ycm93ZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgIFB2FkZHJlc3MCCl9ib3Jyb3dlZF8FCmFzc2V0SWRTdHIDCQBmAgUGYW1vdW50CQBlAgUNYXNzZXRTdXBwbGllZAUNYXNzZXRCb3Jyb3dlZAkAAgECHHRoaXMgYW1vdW50IGlzIG5vdCBhdmFpbGFibGUEA2ludgMJAQIhPQIJAQx0cnlHZXRTdHJpbmcBCQCsAgICEHNldHVwX2F1dG9zdGFrZV8FCmFzc2V0SWRTdHICAAkA/AcEBQR0aGlzAgx1bnN0YWtlVG9rZW4JAMwIAgUKYXNzZXRJZFN0cgkAzAgCBQthc3NldEFtb3VudAUDbmlsBQNuaWwFBHVuaXQDCQAAAgUDaW52BQNpbnYEBXNSYXRlCAkAkQMCBRFyYXRlc1JlY2FsY1Jlc3VsdAkAaAIJAQV2YWx1ZQEJAM8IAgkBD2dldE1hcmtldEFzc2V0cwAFCmFzc2V0SWRTdHIAAwV2YWx1ZQQRbGltaXRDaGVja0FjdGlvbnMJARBjaGVja0JvcnJvd0xpbWl0BQUHYWRkcmVzcwUKYXNzZXRJZFN0cgUGYW1vdW50BQViUmF0ZQUFc1JhdGUDCQAAAgURbGltaXRDaGVja0FjdGlvbnMFEWxpbWl0Q2hlY2tBY3Rpb25zCQDOCAIJAM4IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgIFB2FkZHJlc3MCCl9ib3Jyb3dlZF8FCmFzc2V0SWRTdHIJAGQCBRF1c2VyQXNzZXRCb3Jyb3dlZAUGYW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgICD3RvdGFsX2JvcnJvd2VkXwUKYXNzZXRJZFN0cgkAZAIFDWFzc2V0Qm9ycm93ZWQFBmFtb3VudAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIFC2Fzc2V0QW1vdW50CQENZ2V0QXNzZXRCeXRlcwEFCmFzc2V0SWRTdHIFA25pbAURcmF0ZXNSZWNhbGNSZXN1bHQFEWxpbWl0Q2hlY2tBY3Rpb25zCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBBXJlcGF5AAMJAQEhAQkBDXRyeUdldEJvb2xlYW4BAgxzZXR1cF9hY3RpdmUJAAIBAhFtYXJrZXQgaXMgc3RvcHBlZAMDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEGCQAAAggJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQAAAkAAgECHDEgcGF5bWVudCBoYXMgdG8gYmUgYXR0YWNoZWQECmFzc2V0SWRTdHIJAQ5nZXRBc3NldFN0cmluZwEICQCRAwIIBQFpCHBheW1lbnRzAAAHYXNzZXRJZAQLYXNzZXRBbW91bnQICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50BA0kdDAxNzY4NDE3NzUxCQENZ2V0QWN0dWFsUmF0ZQIFCmFzc2V0SWRTdHICBWJSYXRlBAViUmF0ZQgFDSR0MDE3Njg0MTc3NTECXzEEEXJhdGVzUmVjYWxjUmVzdWx0CAUNJHQwMTc2ODQxNzc1MQJfMgQGYW1vdW50CQBuBAULYXNzZXRBbW91bnQFB1NjYWxlMTYFBWJSYXRlBQdDRUlMSU5HBAdhZGRyZXNzCQClCAEIBQFpBmNhbGxlcgQNYXNzZXRTdXBwbGllZAkBDXRyeUdldEludGVnZXIBCQCsAgICD3RvdGFsX3N1cHBsaWVkXwUKYXNzZXRJZFN0cgQNYXNzZXRCb3Jyb3dlZAkBDXRyeUdldEludGVnZXIBCQCsAgICD3RvdGFsX2JvcnJvd2VkXwUKYXNzZXRJZFN0cgQRdXNlckFzc2V0Qm9ycm93ZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgIFB2FkZHJlc3MCCl9ib3Jyb3dlZF8FCmFzc2V0SWRTdHIECmFtb3VudExlZnQJAGUCBRF1c2VyQXNzZXRCb3Jyb3dlZAUGYW1vdW50BAtyZXBheUFtb3VudAMJAGcCBQphbW91bnRMZWZ0AAAFBmFtb3VudAURdXNlckFzc2V0Qm9ycm93ZWQDCQAAAgkAswkCCQEMdHJ5R2V0U3RyaW5nAQIMc2V0dXBfdG9rZW5zBQphc3NldElkU3RyBQR1bml0CQACAQIpdGhpcyBhc3NldCBpcyBub3Qgc3VwcG9ydGVkIGJ5IHRoZSBtYXJrZXQEA2ludgMJAQIhPQIJAQx0cnlHZXRTdHJpbmcBCQCsAgICEHNldHVwX2F1dG9zdGFrZV8FCmFzc2V0SWRTdHICAAkA/AcEBQR0aGlzAgpzdGFrZVRva2VuCQDMCAIFCmFzc2V0SWRTdHIJAMwIAgULYXNzZXRBbW91bnQFA25pbAUDbmlsBQR1bml0AwkAAAIFA2ludgUDaW52BAxleGNlc3NUb2tlbnMJAGUCBQthc3NldEFtb3VudAkAawMFC3JlcGF5QW1vdW50BQViUmF0ZQUHU2NhbGUxNgkAzggCCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkArAICBQdhZGRyZXNzAgpfYm9ycm93ZWRfBQphc3NldElkU3RyCQBlAgURdXNlckFzc2V0Qm9ycm93ZWQFC3JlcGF5QW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgICD3RvdGFsX2JvcnJvd2VkXwUKYXNzZXRJZFN0cgkAZQIFDWFzc2V0Qm9ycm93ZWQFC3JlcGF5QW1vdW50BQNuaWwFEXJhdGVzUmVjYWxjUmVzdWx0AwkAZwIFCmFtb3VudExlZnQAAAUDbmlsCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgUMZXhjZXNzVG9rZW5zCAkAkQMCCAUBaQhwYXltZW50cwAAB2Fzc2V0SWQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQhyZXBheUZvcgEHYWRkcmVzcwMJAQEhAQkBDXRyeUdldEJvb2xlYW4BAgxzZXR1cF9hY3RpdmUJAAIBAhFtYXJrZXQgaXMgc3RvcHBlZAMJAQIhPQIIBQFpBmNhbGxlcgUScmVzZXJ2ZUZ1bmRBZGRyZXNzCQACAQInYXZhaWxhYmxlIG9ubHkgZm9yIHJlc2VydmUgZnVuZCBhZGRyZXNzAwkAAAIFB2FkZHJlc3MCBmdsb2JhbAkAAgECIHlvdSBjYW4ndCByZXBheSBmb3IgZXZlcnlvbmUgOl8pAwMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQYJAAACCAkAkQMCCAUBaQhwYXltZW50cwAABmFtb3VudAAACQACAQIcMSBwYXltZW50IGhhcyB0byBiZSBhdHRhY2hlZAQKYXNzZXRJZFN0cgkBDmdldEFzc2V0U3RyaW5nAQgJAJEDAggFAWkIcGF5bWVudHMAAAdhc3NldElkBAthc3NldEFtb3VudAgJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQEDSR0MDE5NDI3MTk0OTQJAQ1nZXRBY3R1YWxSYXRlAgUKYXNzZXRJZFN0cgIFYlJhdGUEBWJSYXRlCAUNJHQwMTk0MjcxOTQ5NAJfMQQRcmF0ZXNSZWNhbGNSZXN1bHQIBQ0kdDAxOTQyNzE5NDk0Al8yBAZhbW91bnQJAG4EBQthc3NldEFtb3VudAUHU2NhbGUxNgUFYlJhdGUFB0NFSUxJTkcEDWFzc2V0U3VwcGxpZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICAg90b3RhbF9zdXBwbGllZF8FCmFzc2V0SWRTdHIEDWFzc2V0Qm9ycm93ZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICAg90b3RhbF9ib3Jyb3dlZF8FCmFzc2V0SWRTdHIEEXVzZXJBc3NldEJvcnJvd2VkCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICBQdhZGRyZXNzAgpfYm9ycm93ZWRfBQphc3NldElkU3RyBAphbW91bnRMZWZ0CQBlAgURdXNlckFzc2V0Qm9ycm93ZWQFBmFtb3VudAQLcmVwYXlBbW91bnQDCQBnAgUKYW1vdW50TGVmdAAABQZhbW91bnQFEXVzZXJBc3NldEJvcnJvd2VkAwkAAAIJALMJAgkBDHRyeUdldFN0cmluZwECDHNldHVwX3Rva2VucwUKYXNzZXRJZFN0cgUEdW5pdAkAAgECKXRoaXMgYXNzZXQgaXMgbm90IHN1cHBvcnRlZCBieSB0aGUgbWFya2V0BANpbnYDCQECIT0CCQEMdHJ5R2V0U3RyaW5nAQkArAICAhBzZXR1cF9hdXRvc3Rha2VfBQphc3NldElkU3RyAgAJAPwHBAUEdGhpcwIKc3Rha2VUb2tlbgkAzAgCBQphc3NldElkU3RyCQDMCAIFC2Fzc2V0QW1vdW50BQNuaWwFA25pbAUEdW5pdAMJAAACBQNpbnYFA2ludgQMZXhjZXNzVG9rZW5zCQBlAgULYXNzZXRBbW91bnQJAGsDBQtyZXBheUFtb3VudAUFYlJhdGUFB1NjYWxlMTYJAM4IAgkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgUHYWRkcmVzcwIKX2JvcnJvd2VkXwUKYXNzZXRJZFN0cgkAZQIFEXVzZXJBc3NldEJvcnJvd2VkBQtyZXBheUFtb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAg90b3RhbF9ib3Jyb3dlZF8FCmFzc2V0SWRTdHIJAGUCBQ1hc3NldEJvcnJvd2VkBQtyZXBheUFtb3VudAUDbmlsBRFyYXRlc1JlY2FsY1Jlc3VsdAMJAGcCBQphbW91bnRMZWZ0AAAFA25pbAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIFDGV4Y2Vzc1Rva2VucwgJAJEDAggFAWkIcGF5bWVudHMAAAdhc3NldElkBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEKc3Rha2VUb2tlbgIKYXNzZXRJZFN0cgZhbW91bnQEEGF1dG9zdGFrZUFkZHJlc3MJAQt2YWx1ZU9yRWxzZQIJAKYIAQkBDHRyeUdldFN0cmluZwEJAKwCAgIQc2V0dXBfYXV0b3N0YWtlXwUKYXNzZXRJZFN0cgkBB0FkZHJlc3MBARoBV3vJqP6V1issYKZ2YPlTI8WKEFoN716o2wQVc3Rha2VyU3VwcG9ydGVkQXNzZXRzCQERQGV4dHJOYXRpdmUoMTA1MykCBRBhdXRvc3Rha2VBZGRyZXNzAhVzZXR1cF9zdXBwb3J0ZWRBc3NldHMDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAixvbmx5IGZvciBpbnRlcm5hbCBzbWFydCBjb250cmFjdCBpbnZvY2F0aW9ucwMJAAACCQCzCQIFFXN0YWtlclN1cHBvcnRlZEFzc2V0cwUKYXNzZXRJZFN0cgUEdW5pdAUDbmlsBAxhbW91bnRTdGFrZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICAhFhdXRvc3Rha2VfYW1vdW50XwUKYXNzZXRJZFN0cgQIc3Rha2VJbnYJAP0HBAUQYXV0b3N0YWtlQWRkcmVzcwIHc3Rha2VMUAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQENZ2V0QXNzZXRCeXRlcwEFCmFzc2V0SWRTdHIFBmFtb3VudAUDbmlsAwkAAAIFCHN0YWtlSW52BQhzdGFrZUludgkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhFhdXRvc3Rha2VfYW1vdW50XwUKYXNzZXRJZFN0cgkAZAIFDGFtb3VudFN0YWtlZAUGYW1vdW50BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQENc3Rha2VUb2tlbkFsbAEKYXNzZXRJZFN0cgMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECLG9ubHkgZm9yIGludGVybmFsIHNtYXJ0IGNvbnRyYWN0IGludm9jYXRpb25zBAZhbW91bnQJAQpnZXRCYWxhbmNlAQUKYXNzZXRJZFN0cgQDaW52CQD9BwQFBHRoaXMCCnN0YWtlVG9rZW4JAMwIAgUKYXNzZXRJZFN0cgkAzAgCBQZhbW91bnQFA25pbAUDbmlsAwkAAAIFA2ludgUDaW52BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEMdW5zdGFrZVRva2VuAgphc3NldElkU3RyBmFtb3VudAQQYXV0b3N0YWtlQWRkcmVzcwkBC3ZhbHVlT3JFbHNlAgkApggBCQEMdHJ5R2V0U3RyaW5nAQkArAICAhBzZXR1cF9hdXRvc3Rha2VfBQphc3NldElkU3RyCQEHQWRkcmVzcwEBGgFXe8mo/pXWKyxgpnZg+VMjxYoQWg3vXqjbBBVzdGFrZXJTdXBwb3J0ZWRBc3NldHMJARFAZXh0ck5hdGl2ZSgxMDUzKQIFEGF1dG9zdGFrZUFkZHJlc3MCFXNldHVwX3N1cHBvcnRlZEFzc2V0cwMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECLG9ubHkgZm9yIGludGVybmFsIHNtYXJ0IGNvbnRyYWN0IGludm9jYXRpb25zAwkAAAIJALMJAgUVc3Rha2VyU3VwcG9ydGVkQXNzZXRzBQphc3NldElkU3RyBQR1bml0BQNuaWwEDGFtb3VudFN0YWtlZAkBDXRyeUdldEludGVnZXIBCQCsAgICEWF1dG9zdGFrZV9hbW91bnRfBQphc3NldElkU3RyBAhzdGFrZUludgkA/QcEBRBhdXRvc3Rha2VBZGRyZXNzAgl1bnN0YWtlTFAJAMwIAgUKYXNzZXRJZFN0cgkAzAgCBQZhbW91bnQFA25pbAUDbmlsAwkAAAIFCHN0YWtlSW52BQhzdGFrZUludgkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhFhdXRvc3Rha2VfYW1vdW50XwUKYXNzZXRJZFN0cgkAZQIFDGFtb3VudFN0YWtlZAUGYW1vdW50BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQELYWRkSW50ZXJlc3QCCmFzc2V0SWRTdHIGYW1vdW50AwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQIYb25seSBmb3Igc2VsZiBpbnZvY2F0aW9uBAZlYXJuZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICAhVhdXRvc3Rha2VfbGFzdEVhcm5lZF8FCmFzc2V0SWRTdHIECmxhc3RIZWlnaHQJAQ10cnlHZXRJbnRlZ2VyAQkArAICAhRhdXRvc3Rha2VfbGFzdEJsb2NrXwUKYXNzZXRJZFN0cgQLY2xlYW5BbW91bnQJAGsDBQZhbW91bnQAUABkBApzdGFraW5nRmVlCQBlAgUGYW1vdW50BQtjbGVhbkFtb3VudAQMc3RhdGVDaGFuZ2VzAwMJAAACBQpsYXN0SGVpZ2h0BQZoZWlnaHQGCQAAAgUGYW1vdW50AAAFA25pbAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhhhdXRvc3Rha2VfcHJlTGFzdEVhcm5lZF8FCmFzc2V0SWRTdHIFBmVhcm5lZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhdhdXRvc3Rha2VfcHJlTGFzdEJsb2NrXwUKYXNzZXRJZFN0cgUKbGFzdEhlaWdodAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhVhdXRvc3Rha2VfbGFzdEVhcm5lZF8FCmFzc2V0SWRTdHIJAGQCBQZlYXJuZWQFC2NsZWFuQW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgICFGF1dG9zdGFrZV9sYXN0QmxvY2tfBQphc3NldElkU3RyBQZoZWlnaHQFA25pbAkAzggCBQxzdGF0ZUNoYW5nZXMJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgUKYXNzZXRJZFN0cgIGX3NSYXRlCQBkAgkBDXRyeUdldEludGVnZXIBCQCsAgIFCmFzc2V0SWRTdHICBl9zUmF0ZQkAawMFB1NjYWxlMTYFC2NsZWFuQW1vdW50CQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfc3VwcGxpZWRfBQphc3NldElkU3RyCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgIEZmVlXwUKYXNzZXRJZFN0cgIIX3N0YWtpbmcJAGQCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgRmZWVfBQphc3NldElkU3RyAghfc3Rha2luZwUKc3Rha2luZ0ZlZQUDbmlsAWkBE2FkZEludGVyZXN0RVhURVJOQUwABAdhc3NldElkCAkAkQMCCAUBaQhwYXltZW50cwAAB2Fzc2V0SWQECmFzc2V0SWRTdHIJAQ5nZXRBc3NldFN0cmluZwEFB2Fzc2V0SWQECXNwbGl0dGluZwkBE2dldFJld2FyZHNTcGxpdHRpbmcBBQphc3NldElkU3RyBAZhbW91bnQJAGsDCAkAkQMCCAUBaQhwYXltZW50cwAABmFtb3VudAgFCXNwbGl0dGluZwJfMgBkBAZlYXJuZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICAhVhdXRvc3Rha2VfbGFzdEVhcm5lZF8FCmFzc2V0SWRTdHIECmxhc3RIZWlnaHQJAQ10cnlHZXRJbnRlZ2VyAQkArAICAhRhdXRvc3Rha2VfbGFzdEJsb2NrXwUKYXNzZXRJZFN0cgQMc3RhdGVDaGFuZ2VzAwMJAAACBQpsYXN0SGVpZ2h0BQZoZWlnaHQGCQAAAgUGYW1vdW50AAAFA25pbAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhhhdXRvc3Rha2VfcHJlTGFzdEVhcm5lZF8FCmFzc2V0SWRTdHIFBmVhcm5lZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhdhdXRvc3Rha2VfcHJlTGFzdEJsb2NrXwUKYXNzZXRJZFN0cgUKbGFzdEhlaWdodAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhVhdXRvc3Rha2VfbGFzdEVhcm5lZF8FCmFzc2V0SWRTdHIJAGQCBQZlYXJuZWQFBmFtb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhRhdXRvc3Rha2VfbGFzdEJsb2NrXwUKYXNzZXRJZFN0cgUGaGVpZ2h0BQNuaWwJAM4IAgUMc3RhdGVDaGFuZ2VzCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIFCmFzc2V0SWRTdHICBl9zUmF0ZQkAZAIJAQ10cnlHZXRJbnRlZ2VyAQkArAICBQphc3NldElkU3RyAgZfc1JhdGUJAGsDBQdTY2FsZTE2BQZhbW91bnQJAQ10cnlHZXRJbnRlZ2VyAQkArAICAg90b3RhbF9zdXBwbGllZF8FCmFzc2V0SWRTdHIJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwURc3RhYmxlRnVuZEFkZHJlc3MJAGsDCAkAkQMCCAUBaQhwYXltZW50cwAABmFtb3VudAgFCXNwbGl0dGluZwJfMQBkBQdhc3NldElkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgIEZmVlXwUKYXNzZXRJZFN0cgIIX3N0YWtpbmcJAGQCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgRmZWVfBQphc3NldElkU3RyAghfc3Rha2luZwkAawMICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50CAUJc3BsaXR0aW5nAl8zAGQFA25pbAFpAQdwcmVJbml0BAZ0b2tlbnMEbHR2cwNsdHMJcGVuYWx0aWVzCgEBZgIFYWNjdW0FdG9rZW4JAM4IAgUFYWNjdW0JAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgUFdG9rZW4CBl9iUmF0ZQUHU2NhbGUxNgkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICBQV0b2tlbgIGX3NSYXRlBQdTY2FsZTE2BQNuaWwDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAgphZG1pbiBvbmx5BAVyYXRlcwoAAiRsCQC1CQIFBnRva2VucwIBLAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEBZgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTIJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwJAM4IAgkAzAgCCQELU3RyaW5nRW50cnkCAgxzZXR1cF90b2tlbnMFBnRva2VucwkAzAgCCQELU3RyaW5nRW50cnkCAgpzZXR1cF9sdHZzBQRsdHZzCQDMCAIJAQtTdHJpbmdFbnRyeQICCXNldHVwX2x0cwUDbHRzCQDMCAIJAQtTdHJpbmdFbnRyeQICD3NldHVwX3BlbmFsdGllcwUJcGVuYWx0aWVzCQDMCAIJAQxCb29sZWFuRW50cnkCAgxzZXR1cF9hY3RpdmUGBQNuaWwFBXJhdGVzAWkBDGluaXROZXdUb2tlbgQFdG9rZW4DbHR2Amx0B3BlbmFsdHkDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAgphZG1pbiBvbmx5CQDMCAIJAQtTdHJpbmdFbnRyeQICDHNldHVwX3Rva2VucwkArAICCQCsAgIJAQx0cnlHZXRTdHJpbmcBAgxzZXR1cF90b2tlbnMCASwFBXRva2VuCQDMCAIJAQtTdHJpbmdFbnRyeQICCnNldHVwX2x0dnMJAKwCAgkArAICCQEMdHJ5R2V0U3RyaW5nAQIKc2V0dXBfbHR2cwIBLAUDbHR2CQDMCAIJAQtTdHJpbmdFbnRyeQICCXNldHVwX2x0cwkArAICCQCsAgIJAQx0cnlHZXRTdHJpbmcBAglzZXR1cF9sdHMCASwFAmx0CQDMCAIJAQtTdHJpbmdFbnRyeQICD3NldHVwX3BlbmFsdGllcwkArAICCQCsAgIJAQx0cnlHZXRTdHJpbmcBAg9zZXR1cF9wZW5hbHRpZXMCASwFB3BlbmFsdHkJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgUFdG9rZW4CBl9iUmF0ZQUHU2NhbGUxNgkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICBQV0b2tlbgIGX3NSYXRlBQdTY2FsZTE2BQNuaWwBaQEPdXBkYXRlUGFyYW1ldGVyAgNrZXkDdmFsAwMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkBAiE9AggFAWkGY2FsbGVyBQxhZG1pbkFkZHJlc3MHCQACAQIKYWRtaW4gb25seQkAzAgCCQEMSW50ZWdlckVudHJ5AgUDa2V5CQENcGFyc2VJbnRWYWx1ZQEFA3ZhbAUDbmlsAWkBDHVwZGF0ZVN0cmluZwIDa2V5A3ZhbAMDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAQIhPQIIBQFpBmNhbGxlcgUMYWRtaW5BZGRyZXNzBwkAAgECCmFkbWluIG9ubHkJAMwIAgkBC1N0cmluZ0VudHJ5AgUDa2V5BQN2YWwFA25pbAFpARJjbGFpbVRvUmVzZXJ2ZUZ1bmQBBWRlYnVnBAhfYWxsb3dlZAMJAQIhPQIJAJ0IAgUEdGhpcwIac2V0dXBfYWRkcmVzc19mZWVDb2xsZWN0b3IFBHVuaXQJAAIBAkNmZWUgY29sbGVjdG9yIGlzIGNvbmZpZ3VyZWQsIHVzZSBjbGFpbUZlZXMoKS9jbGFpbUZlZXNBbGwoKSBpbnN0ZWFkBQR1bml0AwkAAAIFCF9hbGxvd2VkBQhfYWxsb3dlZAQGYXNzZXRzCQEPZ2V0TWFya2V0QXNzZXRzAAQFcmF0ZXMICQENZ2V0QWN0dWFsUmF0ZQIJAJEDAgUGYXNzZXRzAAACBXNSYXRlAl8yBAJsaQkAzAgCAAAJAMwIAgABCQDMCAIAAgkAzAgCAAMJAMwIAgAECQDMCAIABQkAzAgCAAYJAMwIAgAHCQDMCAIACAkAzAgCAAkJAMwIAgAKCQDMCAIACwUDbmlsCgEBZgIFYWNjdW0BbgMJAGcCBQFuCQCQAwEFBmFzc2V0cwUFYWNjdW0ECmFzc2V0SWRTdHIJAJEDAgUGYXNzZXRzBQFuBAZhbW91bnQJAGUCCQBkAgkAZAIJAQpnZXRCYWxhbmNlAQUKYXNzZXRJZFN0cgkBDXRyeUdldEludGVnZXIBCQCsAgICEWF1dG9zdGFrZV9hbW91bnRfBQphc3NldElkU3RyCQBrAwkBDXRyeUdldEludGVnZXIBCQCsAgICD3RvdGFsX2JvcnJvd2VkXwUKYXNzZXRJZFN0cggJAJEDAgUFcmF0ZXMJAGQCCQBoAgUBbgADAAEFdmFsdWUFB1NjYWxlMTYJAGsDCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfc3VwcGxpZWRfBQphc3NldElkU3RyCAkAkQMCBQVyYXRlcwkAaAIFAW4AAwV2YWx1ZQUHU2NhbGUxNgQDaW52AwkBAiE9AgkBDHRyeUdldFN0cmluZwEJAKwCAgIQc2V0dXBfYXV0b3N0YWtlXwUKYXNzZXRJZFN0cgIACQD8BwQFBHRoaXMCDHVuc3Rha2VUb2tlbgkAzAgCBQphc3NldElkU3RyCQDMCAIFBmFtb3VudAUDbmlsBQNuaWwFBHVuaXQDCQAAAgUDaW52BQNpbnYJAM4IAgUFYWNjdW0JAMwIAgUGYW1vdW50BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4ECXBhcmFtZXRlcgoAAiRsBQJsaQoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEBZgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTIJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwKAQJmMgIFYWNjdW0BbgMJAGcCBQFuCQCQAwEFBmFzc2V0cwUFYWNjdW0ECmFzc2V0SWRTdHIJAJEDAgUGYXNzZXRzBQFuCQDOCAIFBWFjY3VtCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFEnJlc2VydmVGdW5kQWRkcmVzcwkAlgMBCQDMCAIJAJEDAgUJcGFyYW1ldGVyBQFuCQDMCAIAAAUDbmlsCQENZ2V0QXNzZXRCeXRlcwEFCmFzc2V0SWRTdHIFA25pbAMFBWRlYnVnCQACAQkBCmxpSW50VG9TdHIBBQlwYXJhbWV0ZXIJAJQKAgoAAiRsBQJsaQoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMV8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQECZjICBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjFfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEyCQEFJGYxXzICCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMBQlwYXJhbWV0ZXIJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEJY2xhaW1GZWVzAQphc3NldElkU3RyAwkAAAIJAJ0IAgUEdGhpcwIac2V0dXBfYWRkcmVzc19mZWVDb2xsZWN0b3IFBHVuaXQJAAIBAhxmZWUgY29sbGVjdG9yIG5vdCBjb25maWd1cmVkAwkAAAIJALMJAgkBDHRyeUdldFN0cmluZwECDHNldHVwX3Rva2VucwUKYXNzZXRJZFN0cgUEdW5pdAkAAgECKXRoaXMgYXNzZXQgaXMgbm90IHN1cHBvcnRlZCBieSB0aGUgbWFya2V0BAhpc1N0YWtlZAkBAiE9AgkBDHRyeUdldFN0cmluZwEJAKwCAgIQc2V0dXBfYXV0b3N0YWtlXwUKYXNzZXRJZFN0cgIABAVyYXRlcwkBEHRva2VuUmF0ZXNSZWNhbGMBBQphc3NldElkU3RyBAVzUmF0ZQgJAJEDAgUFcmF0ZXMAAAV2YWx1ZQQFYlJhdGUICQCRAwIFBXJhdGVzAAEFdmFsdWUEA2JhbAkBCmdldEJhbGFuY2UBBQphc3NldElkU3RyBANsaXEJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICBGZlZV8FCmFzc2V0SWRTdHICDF9saXF1aWRhdGlvbgQDc3RrCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgRmZWVfBQphc3NldElkU3RyAghfc3Rha2luZwQIaW50ZXJlc3QDBQhpc1N0YWtlZAAACQCWAwEJAMwIAgkAZQIJAGUCCQBlAgkAZAIFA2JhbAkAawMJAQ10cnlHZXRJbnRlZ2VyAQkArAICAg90b3RhbF9ib3Jyb3dlZF8FCmFzc2V0SWRTdHIFBWJSYXRlBQdTY2FsZTE2CQBrAwkBDXRyeUdldEludGVnZXIBCQCsAgICD3RvdGFsX3N1cHBsaWVkXwUKYXNzZXRJZFN0cgUFc1JhdGUFB1NjYWxlMTYFA2xpcQUDc3RrCQDMCAIAAAUDbmlsBANwYXkJAJcDAQkAzAgCCQBkAgkAZAIFCGludGVyZXN0BQNzdGsFA2xpcQkAzAgCBQNiYWwFA25pbAMJAGcCAAAFA3BheQUDbmlsBARsaXFQCQCXAwEJAMwIAgUDbGlxCQDMCAIFA3BheQUDbmlsBARzdGtQCQCXAwEJAMwIAgUDc3RrCQDMCAIJAGUCBQNwYXkFBGxpcVAFA25pbAQJaW50ZXJlc3RQCQBlAgkAZQIFA3BheQUEbGlxUAUEc3RrUAQJcmVjb3JkSW52CQD8BwQFE2ZlZUNvbGxlY3RvckFkZHJlc3MCC3Byb2Nlc3NGZWVzCQDMCAIFCmFzc2V0SWRTdHIJAMwIAgUJaW50ZXJlc3RQCQDMCAIFBHN0a1AJAMwIAgUEbGlxUAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQENZ2V0QXNzZXRCeXRlcwEFCmFzc2V0SWRTdHIFA3BheQUDbmlsAwkAAAIFCXJlY29yZEludgUJcmVjb3JkSW52CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgIEZmVlXwUKYXNzZXRJZFN0cgIMX2xpcXVpZGF0aW9uCQBlAgUDbGlxBQRsaXFQCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgIEZmVlXwUKYXNzZXRJZFN0cgIIX3N0YWtpbmcJAGUCBQNzdGsFBHN0a1AFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQxjbGFpbUZlZXNBbGwBCnRva2Vuc0xpc3QEBnRva2VucwMJAAACBQp0b2tlbnNMaXN0AgAJAQ9nZXRNYXJrZXRBc3NldHMACQC1CQIFCnRva2Vuc0xpc3QCASwKAQFmAgVhY2N1bQV0b2tlbgQDaW52CQD8BwQFBHRoaXMCCWNsYWltRmVlcwkAzAgCBQV0b2tlbgUDbmlsBQNuaWwDCQAAAgUDaW52BQNpbnYFBWFjY3VtCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBARkb25lCgACJGwFBnRva2VucwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFBHVuaXQKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBAWYCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEyCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAwkAAAIFBGRvbmUFBGRvbmUFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQdyZVNldHVwAQphc3NldElkU3RyBAtsYXN0UmVzZXR1cAkBDXRyeUdldEludGVnZXIBAhJyZXNldHVwX2xhc3RVcGRhdGUDCQBmAgUJZGF5QmxvY2tzCQBlAgUGaGVpZ2h0BQtsYXN0UmVzZXR1cAkAAgECIGNhbiBiZSB1cGRhdGVkIG9ubHkgb25jZSBwZXIgZGF5BANsdHMJALUJAgkBDHRyeUdldFN0cmluZwECCXNldHVwX2x0cwIBLAQGYXNzZXRzCQEPZ2V0TWFya2V0QXNzZXRzAAQCdXIJAQVnZXRVcgEFCmFzc2V0SWRTdHIEBnRlbXBMVAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIGc2V0dXBfBQphc3NldElkU3RyAgdfdGVtcExUBAJsdAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBmFzc2V0cwkBBXZhbHVlAQkAzwgCBQZhc3NldHMFCmFzc2V0SWRTdHIDCQBmAgUCdXIAgJX1KgkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgICBnNldHVwXwUKYXNzZXRJZFN0cgIHX3RlbXBMVAkAawMFBnRlbXBMVAD3TQCQTgUDbmlsAwMJAGYCBQJsdAUGdGVtcExUCQBmAgCAlfUqBQJ1cgcJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkArAICAgZzZXR1cF8FCmFzc2V0SWRTdHICB190ZW1wTFQJAGsDBQZ0ZW1wTFQAqU4AkE4FA25pbAUDbmlsAWkBCHNodXRkb3duAQhzaHV0ZG93bgMJAAACCQDPCAIFEXNodXRkb3duV2hpdGVsaXN0CAUBaQZjYWxsZXIFBHVuaXQJAAIBAhd1c2VyIG5vdCBpbiBhIHdoaXRlbGlzdAkAzAgCCQEMQm9vbGVhbkVudHJ5AgIMc2V0dXBfYWN0aXZlCQEBIQEFCHNodXRkb3duBQNuaWwBaQEJbGlxdWlkYXRlBgVkZWJ1ZwdhZGRyZXNzC2Fzc2V0QW1vdW50C3NBc3NldElkU3RyC2JBc3NldElkU3RyCHJvdXRlU3RyAwkBASEBCQEWdmVyaWZ5TGlxdWlkYXRvclJpZ2h0cwEIBQFpBmNhbGxlcgkAAgECKHRlbXBvcmFyaWx5IGF2YWlsYWJsZSBmb3Igd2hpdGVsaXN0IG9ubHkDCQEBIQEJAQ10cnlHZXRCb29sZWFuAQIMc2V0dXBfYWN0aXZlCQACAQIRbWFya2V0IGlzIHN0b3BwZWQEDnVzZXJDb2xsYXRlcmFsCQESY2FsY1VzZXJDb2xsYXRlcmFsAQUHYWRkcmVzcwMJAAACBQ51c2VyQ29sbGF0ZXJhbAUOdXNlckNvbGxhdGVyYWwEDSR0MDM1NDY3MzU1MjkJAQ1nZXRBY3R1YWxSYXRlAgULc0Fzc2V0SWRTdHICBXNSYXRlBAVzUmF0ZQgFDSR0MDM1NDY3MzU1MjkCXzEEC3JhdGVzUmVzdWx0CAUNJHQwMzU0NjczNTUyOQJfMgQNJHQwMzU1MzQzNTYwMwkBDWdldEFjdHVhbFJhdGUCBQtiQXNzZXRJZFN0cgIFYlJhdGUEBWJSYXRlCAUNJHQwMzU1MzQzNTYwMwJfMQQScmF0ZXNSZWNhbGNSZXN1bHQyCAUNJHQwMzU1MzQzNTYwMwJfMgQMc0Fzc2V0QW1vdW50CQBrAwULYXNzZXRBbW91bnQFB1NjYWxlMTYFBXNSYXRlBBBjdXJyZW50U1Bvc2l0aW9uCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICBQdhZGRyZXNzAgpfc3VwcGxpZWRfBQtzQXNzZXRJZFN0cgQTY3VycmVudEJQb3NpdGlvblZhbAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgUHYWRkcmVzcwIKX2JvcnJvd2VkXwULYkFzc2V0SWRTdHIEEGN1cnJlbnRCUG9zaXRpb24DCQBmAgUTY3VycmVudEJQb3NpdGlvblZhbAAABRNjdXJyZW50QlBvc2l0aW9uVmFsCQACAQIgdXNlciBoYXMgbm8gYm9ycm93IGluIHRoaXMgdG9rZW4DCQBmAgUOdXNlckNvbGxhdGVyYWwAAAkAAgECGHVzZXIgY2FuJ3QgYmUgbGlxdWlkYXRlZAMJAGYCBQxzQXNzZXRBbW91bnQFEGN1cnJlbnRTUG9zaXRpb24JAAIBAjJwb3NpdGlvbiB0byBsaXF1aWRhdGUgaXMgYmlnZ2VyIHRoYW4gdXNlcidzIHN1cHBseQQDaW52AwkBAiE9AgkBDHRyeUdldFN0cmluZwEJAKwCAgIQc2V0dXBfYXV0b3N0YWtlXwULc0Fzc2V0SWRTdHICAAkA/AcEBQR0aGlzAgx1bnN0YWtlVG9rZW4JAMwIAgULc0Fzc2V0SWRTdHIJAMwIAgUMc0Fzc2V0QW1vdW50BQNuaWwFA25pbAUEdW5pdAMJAAACBQNpbnYFA2ludgQOYmFsYW5jZTBCZWZvcmUJAQpnZXRCYWxhbmNlAQULc0Fzc2V0SWRTdHIDCQAAAgUOYmFsYW5jZTBCZWZvcmUFDmJhbGFuY2UwQmVmb3JlBA5iYWxhbmNlMUJlZm9yZQkBCmdldEJhbGFuY2UBBQtiQXNzZXRJZFN0cgMJAAACBQ5iYWxhbmNlMUJlZm9yZQUOYmFsYW5jZTFCZWZvcmUEDmV4Y2hhbmdlSW52b2tlCQD8BwQFEWFnZ3JlZ2F0b3JBZGRyZXNzAgRzd2FwCQDMCAIFCHJvdXRlU3RyCQDMCAIAAAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQENZ2V0QXNzZXRCeXRlcwEFC3NBc3NldElkU3RyBQthc3NldEFtb3VudAUDbmlsAwkAAAIFDmV4Y2hhbmdlSW52b2tlBQ5leGNoYW5nZUludm9rZQQKYXNzZXQwU29sZAkAZQIFDmJhbGFuY2UwQmVmb3JlCQEKZ2V0QmFsYW5jZQEFC3NBc3NldElkU3RyAwkAAAIFCmFzc2V0MFNvbGQFCmFzc2V0MFNvbGQEDGFzc2V0MUJvdWdodAkAZQIJAQpnZXRCYWxhbmNlAQULYkFzc2V0SWRTdHIFDmJhbGFuY2UxQmVmb3JlAwkAAAIFDGFzc2V0MUJvdWdodAUMYXNzZXQxQm91Z2h0BAthc3NldDBQcmljZQgJARNnZXRUb2tlblByaWNlQ2FwcGVkAQULc0Fzc2V0SWRTdHICXzEEC2Fzc2V0MFNjYWxlCQEOY2FsY0Fzc2V0U2NhbGUBBQtzQXNzZXRJZFN0cgQJYXNzZXQwVXNkCQBrAwUKYXNzZXQwU29sZAULYXNzZXQwUHJpY2UFC2Fzc2V0MFNjYWxlBAthc3NldDFQcmljZQgJARNnZXRUb2tlblByaWNlQ2FwcGVkAQULYkFzc2V0SWRTdHICXzIEC2Fzc2V0MVNjYWxlCQEOY2FsY0Fzc2V0U2NhbGUBBQtiQXNzZXRJZFN0cgQJYXNzZXQxVXNkCQBrAwUMYXNzZXQxQm91Z2h0BQthc3NldDFQcmljZQULYXNzZXQxU2NhbGUEB3BlbmFsdHkJAQ1wYXJzZUludFZhbHVlAQkAkQMCCQC1CQIJAQx0cnlHZXRTdHJpbmcBAg9zZXR1cF9wZW5hbHRpZXMCASwJAQV2YWx1ZQEJAM8IAgkBD2dldE1hcmtldEFzc2V0cwAFC2JBc3NldElkU3RyBBFsaXF1aWRhdGlvblByb2ZpdAkAZQIFCWFzc2V0MVVzZAkAawMFCWFzc2V0MFVzZAkAZQIFBlNjYWxlOAUHcGVuYWx0eQUGU2NhbGU4BAxzQXNzZXRDaGFuZ2UJAGsDBQphc3NldDBTb2xkBQdTY2FsZTE2BQVzUmF0ZQQMYkFzc2V0Q2hhbmdlCQBrAwkAawMFDGFzc2V0MUJvdWdodAUHU2NhbGUxNgUFYlJhdGUJAGUCBQZTY2FsZTgJAGsDBRFsaXF1aWRhdGlvblByb2ZpdAUGU2NhbGU4BQlhc3NldDFVc2QFBlNjYWxlOAMJAGYCBQphc3NldDBTb2xkBQthc3NldEFtb3VudAkAAgECI21vcmUgYXNzZXRzIGV4Y2hhbmdlZCB0aGFuIGV4cGVjdGVkAwkAZgIAAAURbGlxdWlkYXRpb25Qcm9maXQJAAIBAi9wcmljZSBpbXBhY3QgaXMgYmlnZ2VyIHRoYW4gbGlxdWlkYXRpb24gcGVuYWx0eQkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgIFB2FkZHJlc3MCCl9zdXBwbGllZF8FC3NBc3NldElkU3RyCQBlAgUQY3VycmVudFNQb3NpdGlvbgUMc0Fzc2V0Q2hhbmdlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgUHYWRkcmVzcwIKX2JvcnJvd2VkXwULYkFzc2V0SWRTdHIJAGUCBRBjdXJyZW50QlBvc2l0aW9uBQxiQXNzZXRDaGFuZ2UJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgIPdG90YWxfc3VwcGxpZWRfBQtzQXNzZXRJZFN0cgkAZQIJAQ10cnlHZXRJbnRlZ2VyAQkArAICAg90b3RhbF9zdXBwbGllZF8FC3NBc3NldElkU3RyBQxzQXNzZXRDaGFuZ2UJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgIPdG90YWxfYm9ycm93ZWRfBQtiQXNzZXRJZFN0cgkAZQIJAQ10cnlHZXRJbnRlZ2VyAQkArAICAg90b3RhbF9ib3Jyb3dlZF8FC2JBc3NldElkU3RyBQxiQXNzZXRDaGFuZ2UJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkArAICAgRmZWVfBQtiQXNzZXRJZFN0cgIMX2xpcXVpZGF0aW9uCQBkAgkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIEZmVlXwULYkFzc2V0SWRTdHICDF9saXF1aWRhdGlvbgkAZQIFDGFzc2V0MUJvdWdodAkAawMFDGJBc3NldENoYW5nZQUFYlJhdGUFB1NjYWxlMTYFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQtsaXF1aWRhdGVWMgMFZGVidWcHYWRkcmVzcwtzQXNzZXRJZFN0cgMJAQEhAQkBFnZlcmlmeUxpcXVpZGF0b3JSaWdodHMBCAUBaQZjYWxsZXIJAAIBAih0ZW1wb3JhcmlseSBhdmFpbGFibGUgZm9yIHdoaXRlbGlzdCBvbmx5AwkBASEBCQENdHJ5R2V0Qm9vbGVhbgECDHNldHVwX2FjdGl2ZQkAAgECEW1hcmtldCBpcyBzdG9wcGVkBAhiQXNzZXRJZAgJAJEDAggFAWkIcGF5bWVudHMAAAdhc3NldElkBAtiQXNzZXRJZFN0cgkBDmdldEFzc2V0U3RyaW5nAQUIYkFzc2V0SWQEDGJBc3NldEFtb3VudAgJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQEDnVzZXJDb2xsYXRlcmFsCQESY2FsY1VzZXJDb2xsYXRlcmFsAQUHYWRkcmVzcwMJAAACBQ51c2VyQ29sbGF0ZXJhbAUOdXNlckNvbGxhdGVyYWwDCQBmAgUOdXNlckNvbGxhdGVyYWwAAAkAAgECGHVzZXIgY2FuJ3QgYmUgbGlxdWlkYXRlZAQMbWFya2V0QXNzZXRzCQEPZ2V0TWFya2V0QXNzZXRzAAQJYXNzZXQxTnVtCQEFdmFsdWUBCQDPCAIFDG1hcmtldEFzc2V0cwULYkFzc2V0SWRTdHIECWFzc2V0ME51bQkBBXZhbHVlAQkAzwgCBQxtYXJrZXRBc3NldHMFC3NBc3NldElkU3RyBA0kdDAzOTIyNDM5Mjg2CQENZ2V0QWN0dWFsUmF0ZQIFC2JBc3NldElkU3RyAgViUmF0ZQQFYlJhdGUIBQ0kdDAzOTIyNDM5Mjg2Al8xBAtyYXRlc1Jlc3VsdAgFDSR0MDM5MjI0MzkyODYCXzIEC2Fzc2V0MVByaWNlCAkBE2dldFRva2VuUHJpY2VDYXBwZWQBBQtiQXNzZXRJZFN0cgJfMgQLYXNzZXQxU2NhbGUJAQ5jYWxjQXNzZXRTY2FsZQEFC2JBc3NldElkU3RyBApiQW1vdW50VXNkCQBrAwUMYkFzc2V0QW1vdW50BQthc3NldDFQcmljZQULYXNzZXQxU2NhbGUEB3BlbmFsdHkJAQ1wYXJzZUludFZhbHVlAQkBBXZhbHVlAQkAkQMCCQC1CQIJAQx0cnlHZXRTdHJpbmcBAg9zZXR1cF9wZW5hbHRpZXMCASwFCWFzc2V0MU51bQQLYXNzZXQwUHJpY2UICQETZ2V0VG9rZW5QcmljZUNhcHBlZAEFC3NBc3NldElkU3RyAl8xBAthc3NldDBTY2FsZQkBDmNhbGNBc3NldFNjYWxlAQULc0Fzc2V0SWRTdHIECnNBbW91bnRVc2QJAGsDBQpiQW1vdW50VXNkCQBkAgUGU2NhbGU4BQdwZW5hbHR5BQZTY2FsZTgEDHNBc3NldEFtb3VudAkAawMFCnNBbW91bnRVc2QFC2Fzc2V0MFNjYWxlBQthc3NldDBQcmljZQQHYkFtb3VudAkAawMFDGJBc3NldEFtb3VudAUHU2NhbGUxNgUFYlJhdGUEB3NBbW91bnQJAGsDBQxzQXNzZXRBbW91bnQFB1NjYWxlMTYICQCRAwIFC3JhdGVzUmVzdWx0CQBoAgUJYXNzZXQwTnVtAAMFdmFsdWUEEGN1cnJlbnRTUG9zaXRpb24JAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgIFB2FkZHJlc3MCCl9zdXBwbGllZF8FC3NBc3NldElkU3RyBBNjdXJyZW50QlBvc2l0aW9uVmFsCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICBQdhZGRyZXNzAgpfYm9ycm93ZWRfBQtiQXNzZXRJZFN0cgQQY3VycmVudEJQb3NpdGlvbgMJAGYCBRNjdXJyZW50QlBvc2l0aW9uVmFsAAAFE2N1cnJlbnRCUG9zaXRpb25WYWwJAAIBAiB1c2VyIGhhcyBubyBib3Jyb3cgaW4gdGhpcyB0b2tlbgMJAGYCBQdzQW1vdW50BRBjdXJyZW50U1Bvc2l0aW9uCQACAQIycG9zaXRpb24gdG8gbGlxdWlkYXRlIGlzIGJpZ2dlciB0aGFuIHVzZXIncyBzdXBwbHkEA2ludgMJAQIhPQIJAQx0cnlHZXRTdHJpbmcBCQCsAgICEHNldHVwX2F1dG9zdGFrZV8FC3NBc3NldElkU3RyAgAJAPwHBAUEdGhpcwIMdW5zdGFrZVRva2VuCQDMCAIFC3NBc3NldElkU3RyCQDMCAIFDHNBc3NldEFtb3VudAUDbmlsBQNuaWwFBHVuaXQDCQAAAgUDaW52BQNpbnYDBQVkZWJ1ZwkAAgECFWxpcXVpZGF0aW9uIHdpbGwgcGFzcwkAzggCCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgUMc0Fzc2V0QW1vdW50CQENZ2V0QXNzZXRCeXRlcwEFC3NBc3NldElkU3RyCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgUHYWRkcmVzcwIKX3N1cHBsaWVkXwULc0Fzc2V0SWRTdHIJAGUCBRBjdXJyZW50U1Bvc2l0aW9uBQdzQW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgUHYWRkcmVzcwIKX2JvcnJvd2VkXwULYkFzc2V0SWRTdHIJAGUCBRBjdXJyZW50QlBvc2l0aW9uBQdiQW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgICD3RvdGFsX3N1cHBsaWVkXwULc0Fzc2V0SWRTdHIJAGUCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfc3VwcGxpZWRfBQtzQXNzZXRJZFN0cgUHc0Ftb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAg90b3RhbF9ib3Jyb3dlZF8FC2JBc3NldElkU3RyCQBlAgkBDXRyeUdldEludGVnZXIBCQCsAgICD3RvdGFsX2JvcnJvd2VkXwULYkFzc2V0SWRTdHIFB2JBbW91bnQFA25pbAULcmF0ZXNSZXN1bHQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQERZ2V0VXNlckNvbGxhdGVyYWwEBWRlYnVnB2FkZHJlc3MNbWludXNCb3Jyb3dlZAthZnRlckNoYW5nZQQGYXNzZXRzCQEPZ2V0TWFya2V0QXNzZXRzAAQEbHR2cwkAtQkCCQEMdHJ5R2V0U3RyaW5nAQIKc2V0dXBfbHR2cwIBLAQDbHRzCQC1CQIJAQx0cnlHZXRTdHJpbmcBAglzZXR1cF9sdHMCASwEBXJhdGVzCAkBDWdldEFjdHVhbFJhdGUCCQCRAwIFBmFzc2V0cwAAAgVzUmF0ZQJfMgQNY2hhbmdlSGFuZGxlcgkAtQkCBQthZnRlckNoYW5nZQIBLAoBAWYCBWFjY3VtBG5leHQDCQBnAgUEbmV4dAkAkAMBBQZhc3NldHMFBWFjY3VtBAx1c2VyU3VwcGxpZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgIFB2FkZHJlc3MCCl9zdXBwbGllZF8JAJEDAgUGYXNzZXRzBQRuZXh0BAx1c2VyQm9ycm93ZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgIFB2FkZHJlc3MCCl9ib3Jyb3dlZF8JAJEDAgUGYXNzZXRzBQRuZXh0BBNuZWVkVG9rZW5BY2NvdW50aW5nAwkAAAIFC2FmdGVyQ2hhbmdlAgADAwkBAiE9AgUMdXNlckJvcnJvd2VkAAAGCQECIT0CBQx1c2VyU3VwcGxpZWQAAAYHBgMFE25lZWRUb2tlbkFjY291bnRpbmcECmFzc2V0U2NhbGUJAQ5jYWxjQXNzZXRTY2FsZQEJAJEDAgUGYXNzZXRzBQRuZXh0BAphc3NldFByaWNlCQETZ2V0VG9rZW5QcmljZUNhcHBlZAEJAJEDAgUGYXNzZXRzBQRuZXh0CQBlAgkAZAIFBWFjY3VtCQBrAwkAawMJAGsDCQBkAgUMdXNlclN1cHBsaWVkAwMDCQECIT0CBQthZnRlckNoYW5nZQIACQAAAgkAkQMCBQ1jaGFuZ2VIYW5kbGVyAAAJAJEDAgUGYXNzZXRzBQRuZXh0BwkAAAIJAJEDAgUNY2hhbmdlSGFuZGxlcgABAghzdXBwbGllZAcJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQ1jaGFuZ2VIYW5kbGVyAAIAAAgJAJEDAgUFcmF0ZXMJAGgCBQRuZXh0AAMFdmFsdWUFB1NjYWxlMTYJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQRsdHZzBQRuZXh0BQZTY2FsZTgIBQphc3NldFByaWNlAl8xBQphc3NldFNjYWxlAwUNbWludXNCb3Jyb3dlZAkAawMJAGsDCQBrAwkAZAIFDHVzZXJCb3Jyb3dlZAMDAwkBAiE9AgULYWZ0ZXJDaGFuZ2UCAAkAAAIJAJEDAgUNY2hhbmdlSGFuZGxlcgAACQCRAwIFBmFzc2V0cwUEbmV4dAcJAAACCQCRAwIFDWNoYW5nZUhhbmRsZXIAAQIIYm9ycm93ZWQHCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUNY2hhbmdlSGFuZGxlcgACAAAICQCRAwIFBXJhdGVzCQBkAgkAaAIFBG5leHQAAwABBXZhbHVlBQdTY2FsZTE2BQZTY2FsZTgJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQNsdHMFBG5leHQIBQphc3NldFByaWNlAl8yBQphc3NldFNjYWxlAAAFBWFjY3VtBAZyZXN1bHQKAAIkbAkAzAgCAAAJAMwIAgABCQDMCAIAAgkAzAgCAAMJAMwIAgAECQDMCAIABQkAzAgCAAYJAMwIAgAHCQDMCAIACAkAzAgCAAkJAMwIAgAKCQDMCAIACwUDbmlsCgACJHMJAJADAQUCJGwKAAUkYWNjMAAACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQFmAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMgkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAMFBWRlYnVnCQACAQkApAMBBQZyZXN1bHQJAJQKAgUFcmF0ZXMFBnJlc3VsdAFpAQlnZXRQcmljZXMBBWRlYnVnBAZhc3NldHMJAQ9nZXRNYXJrZXRBc3NldHMACgEBZgIFYWNjdW0EbmV4dAMJAGcCBQRuZXh0CQCQAwEFBmFzc2V0cwUFYWNjdW0ECmFzc2V0UHJpY2UJARVnZXRUb2tlblByaWNlV2l0aFJpc2sCCQCRAwIFBmFzc2V0cwUEbmV4dAADCQCsAgIJAKwCAgkArAICCQCsAgIFBWFjY3VtCQCkAwEIBQphc3NldFByaWNlAl8xAgEsCQCkAwEIBQphc3NldFByaWNlAl8yAgF8BAZyZXN1bHQKAAIkbAkAzAgCAAAJAMwIAgABCQDMCAIAAgkAzAgCAAMJAMwIAgAECQDMCAIABQkAzAgCAAYJAMwIAgAHCQDMCAIACAkAzAgCAAkJAMwIAgAKCQDMCAIACwUDbmlsCgACJHMJAJADAQUCJGwKAAUkYWNjMAIACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQFmAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMgkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAMFBWRlYnVnCQACAQUGcmVzdWx0CQCUCgIFA25pbAUGcmVzdWx0AWkBGWNhbGN1bGF0ZVV0aWxpemF0aW9uUmF0aW8CCmFzc2V0SWRTdHIFZGVidWcDBQVkZWJ1ZwkAAgEJAKQDAQkBBWdldFVyAQUKYXNzZXRJZFN0cgkAlAoCBQNuaWwJAQVnZXRVcgEFCmFzc2V0SWRTdHIBaQETY2FsY3VsYXRlT3V0ZGF0ZWRVUgIKYXNzZXRJZFN0cgVkZWJ1ZwMFBWRlYnVnCQACAQkApAMBCQENZ2V0T3V0ZGF0ZWRVcgEFCmFzc2V0SWRTdHIJAJQKAgUDbmlsCQENZ2V0T3V0ZGF0ZWRVcgEFCmFzc2V0SWRTdHIBaQETY2FsY3VsYXRlVG9rZW5SYXRlcwEFZGVidWcKAQFmAgVhY2N1bQphc3NldElkU3RyBAVyYXRlcwkBEHRva2VuUmF0ZXNSZWNhbGMBBQphc3NldElkU3RyCQCUCgIJAKwCAgkArAICCQCsAgIJAKwCAggFBWFjY3VtAl8xCQCkAwEICQCRAwIFBXJhdGVzAAEFdmFsdWUCAXwJAKQDAQgJAJEDAgUFcmF0ZXMAAAV2YWx1ZQIBLAkAzggCCAUFYWNjdW0CXzIFBXJhdGVzBAlwYXJhbWV0ZXIKAAIkbAkBD2dldE1hcmtldEFzc2V0cwAKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCUCgICAAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQFmAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMgkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAMFBWRlYnVnCQACAQgFCXBhcmFtZXRlcgJfMQkAlAoCCAUJcGFyYW1ldGVyAl8yCAUJcGFyYW1ldGVyAl8xAWkBF2NhbGN1bGF0ZVRva2Vuc0ludGVyZXN0AQVkZWJ1ZwoBAWYCBWFjY3VtCmFzc2V0SWRTdHIEBHJhdGUJAGsDCQELZ2V0SW50ZXJlc3QBBQphc3NldElkU3RyBQlkYXlCbG9ja3MFBlNjYWxlOAkArAICCQCsAgIFBWFjY3VtCQCkAwEFBHJhdGUCASwECXBhcmFtZXRlcgoAAiRsCQEPZ2V0TWFya2V0QXNzZXRzAAoAAiRzCQCQAwEFAiRsCgAFJGFjYzACAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEBZgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTIJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwDBQVkZWJ1ZwkAAgEFCXBhcmFtZXRlcgkAlAoCBQNuaWwFCXBhcmFtZXRlcgFpARJzZXRBcHByb3ZlckFkZHJlc3MBD2FwcHJvdmVyQWRkcmVzcwQGaXNTZWxmAwkAAAIIBQFpBmNhbGxlcgUEdGhpcwYJAAIBAhBPbmx5IHNlbGYgaW52b2tlAwkAAAIFBmlzU2VsZgUGaXNTZWxmBBBfYXBwcm92ZXJBZGRyZXNzCQCmCAEFD2FwcHJvdmVyQWRkcmVzcwQKYXBwcm92ZXJPawQHJG1hdGNoMAUQX2FwcHJvdmVyQWRkcmVzcwMJAAECBQckbWF0Y2gwAgdBZGRyZXNzBAF0BQckbWF0Y2gwBgcEDmNhblNldEFwcHJvdmVyAwMFCmFwcHJvdmVyT2sGCQAAAgUPYXBwcm92ZXJBZGRyZXNzAgAGCQACAQIWV3JvbmcgYXBwcm92ZXIgYWRkcmVzcwMJAAACBQ5jYW5TZXRBcHByb3ZlcgUOY2FuU2V0QXBwcm92ZXIECGlzSW5pdGVkCQELdmFsdWVPckVsc2UCCQCbCAIJAQV2YWx1ZQEFEF9hcHByb3ZlckFkZHJlc3MCBklOSVRFRAcECWhhc0FkbWlucwkBAiE9AgkBC3ZhbHVlT3JFbHNlAgkAnQgCCQEFdmFsdWUBBRBfYXBwcm92ZXJBZGRyZXNzAgtBRE1JTlNfUEJLUwIAAgAEEmlzQXBwcm92ZXJDb250cmFjdAMDCQAAAgUPYXBwcm92ZXJBZGRyZXNzAgAGAwUIaXNJbml0ZWQFCWhhc0FkbWlucwcGCQACAQIgQWRkcmVzcyBpcyBub3QgYXBwcm92ZXIgY29udHJhY3QDCQAAAgUSaXNBcHByb3ZlckNvbnRyYWN0BRJpc0FwcHJvdmVyQ29udHJhY3QJAMwIAgkBC1N0cmluZ0VudHJ5AgIQQVBQUk9WRVJfQUREUkVTUwUPYXBwcm92ZXJBZGRyZXNzBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQENaW5pdE5ld01hc3RlcgEGbWFzdGVyBAlhZGRyZXNzT0sEByRtYXRjaDAJAKYIAQUGbWFzdGVyAwkAAQIFByRtYXRjaDACB0FkZHJlc3MEAWEFByRtYXRjaDAGBwMJAQEhAQUJYWRkcmVzc09LCQACAQkArAICAhJpbmNvcnJlY3QgYWRkcmVzcyAFBm1hc3RlcgMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECHGF2YWlsYWJsZSBmb3Igc2VsZiBjYWxsIG9ubHkJAMwIAgkBC1N0cmluZ0VudHJ5AgIPdmVyaWZpZXJfbWFzdGVyBQZtYXN0ZXIFA25pbAFpARByZXF1ZXN0TmV3TWFzdGVyAQluZXdNYXN0ZXIECWFkZHJlc3NPSwQHJG1hdGNoMAkApggBBQluZXdNYXN0ZXIDCQABAgUHJG1hdGNoMAIHQWRkcmVzcwQBYQUHJG1hdGNoMAYHAwkBASEBBQlhZGRyZXNzT0sJAAIBCQCsAgICEmluY29ycmVjdCBhZGRyZXNzIAUJbmV3TWFzdGVyAwkAAAIJAM8IAgUJc2VudGluZWxzCAUBaQZjYWxsZXIFBHVuaXQJAAIBAg53aGl0ZWxpc3Qgb25seQkAzAgCCQELU3RyaW5nRW50cnkCAhJ2ZXJpZmllcl9uZXdNYXN0ZXIFCW5ld01hc3RlcgkAzAgCCQEMSW50ZWdlckVudHJ5AgIfdmVyaWZpZXJfbmV3TWFzdGVyRWxpZ2libGVBZnRlcgkAZAIFBmhlaWdodACQTgUDbmlsAWkBEWFjdGl2YXRlTmV3TWFzdGVyAAQOZWxpZ2libGVIZWlnaHQJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMCH3ZlcmlmaWVyX25ld01hc3RlckVsaWdpYmxlQWZ0ZXIECW5ld01hc3RlcgkBEUBleHRyTmF0aXZlKDEwNTMpAgUEdGhpcwISdmVyaWZpZXJfbmV3TWFzdGVyAwkAAAIJAM8IAgUJc2VudGluZWxzCAUBaQZjYWxsZXIFBHVuaXQJAAIBAg53aGl0ZWxpc3Qgb25seQMJAGYCBQ5lbGlnaWJsZUhlaWdodAUGaGVpZ2h0CQACAQIibmV3IG1hc3RlciBjYW5ub3QgYmUgYWN0aXZhdGVkIHlldAkAzAgCCQELRGVsZXRlRW50cnkBAhJ2ZXJpZmllcl9uZXdNYXN0ZXIJAMwIAgkBC0RlbGV0ZUVudHJ5AQIfdmVyaWZpZXJfbmV3TWFzdGVyRWxpZ2libGVBZnRlcgkAzAgCCQELU3RyaW5nRW50cnkCAg92ZXJpZmllcl9tYXN0ZXIFCW5ld01hc3RlcgUDbmlsAQJ0eAEGdmVyaWZ5AAQLbXVsdGlzaWdTdHIJAQt2YWx1ZU9yRWxzZQIJAKIIAQIQQVBQUk9WRVJfQUREUkVTUwIABA9tdWx0aXNpZ0FkZHJlc3MJAKYIAQULbXVsdGlzaWdTdHIECm11bHRpc2lnT2sEByRtYXRjaDAFD211bHRpc2lnQWRkcmVzcwMJAAECBQckbWF0Y2gwAgdBZGRyZXNzBAF0BQckbWF0Y2gwBgcECGlzSW5pdGVkAwUKbXVsdGlzaWdPawkBC3ZhbHVlT3JFbHNlAgkAmwgCCQEFdmFsdWUBBQ9tdWx0aXNpZ0FkZHJlc3MCBklOSVRFRAcHBAloYXNBZG1pbnMDBQptdWx0aXNpZ09rCQECIT0CCQELdmFsdWVPckVsc2UCCQCdCAIJAQV2YWx1ZQEFD211bHRpc2lnQWRkcmVzcwILQURNSU5TX1BCS1MCAAIABwMDAwUKbXVsdGlzaWdPawUIaXNJbml0ZWQHBQloYXNBZG1pbnMHBAckbWF0Y2gwBQJ0eAMJAAECBQckbWF0Y2gwAhRTZXRTY3JpcHRUcmFuc2FjdGlvbgQDdHR4BQckbWF0Y2gwBAckbWF0Y2gxCAUDdHR4BnNjcmlwdAMJAAECBQckbWF0Y2gxAgpCeXRlVmVjdG9yBAZzY3JpcHQFByRtYXRjaDEEC3NjcmlwdEhhc2hhCQDYBAEJAPYDAQUGc2NyaXB0BAl2YWxpZEZyb20JARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCCQEFdmFsdWUBBQ9tdWx0aXNpZ0FkZHJlc3MJAKwCAgkArAICCQCsAgIJAKwCAgIIc2NyaXB0JSUFDUNPTlRSQUNUX1RZUEUCAiUlBQtzY3JpcHRIYXNoYQILJSV2YWxpZEZyb20CEXZhbGlkRnJvbSBub3Qgc2V0BAd2YWxpZFRvCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgkBBXZhbHVlAQUPbXVsdGlzaWdBZGRyZXNzCQCsAgIJAKwCAgkArAICCQCsAgICCHNjcmlwdCUlBQ1DT05UUkFDVF9UWVBFAgIlJQULc2NyaXB0SGFzaGECCSUldmFsaWRUbwIPdmFsaWRUbyBub3Qgc2V0AwkAZwIFBmhlaWdodAUJdmFsaWRGcm9tCQBnAgUHdmFsaWRUbwUGaGVpZ2h0BwcEA290eAUHJG1hdGNoMAQGdGFza0lkCQCsAgIJAKwCAgkArAICAgN0eF8JAKUIAQUEdGhpcwIBXwkA2AQBCAUDb3R4AmlkBAppc0FwcHJvdmVkCQELdmFsdWVPckVsc2UCCQCbCAIJAQV2YWx1ZQEFD211bHRpc2lnQWRkcmVzcwkArAICCQCsAgIJAKwCAgkApQgBBQR0aGlzAgFfCQDYBAEIBQNvdHgCaWQCCl9fYXBwcm92ZWQHBAxhcHByb3ZlZEZyb20JAQt2YWx1ZU9yRWxzZQIJAJoIAgkBBXZhbHVlAQUPbXVsdGlzaWdBZGRyZXNzCQCsAgIFBnRhc2tJZAIOX19hcHByb3ZlZEZyb20AAAMFCmlzQXBwcm92ZWQJAGcCBQZoZWlnaHQFDGFwcHJvdmVkRnJvbQcEDW1hc3RlckFkZHJlc3MJAKIIAQIPdmVyaWZpZXJfbWFzdGVyBBBhcHByb3ZlZEJ5TWFzdGVyBAckbWF0Y2gwBQ1tYXN0ZXJBZGRyZXNzAwkAAQIFByRtYXRjaDACBlN0cmluZwQBeAUHJG1hdGNoMAQHJG1hdGNoMQkAmggCCQERQGV4dHJOYXRpdmUoMTA2MikBBQF4CQCsAgICC2FwcHJvdmVkVHhfCQDYBAEIBQJ0eAJpZAMJAAECBQckbWF0Y2gxAgNJbnQEAXkFByRtYXRjaDEFAXkAAAABAwkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAgFAnR4D3NlbmRlclB1YmxpY0tleQkAZgIFEGFwcHJvdmVkQnlNYXN0ZXIAAAd7n8qs", "height": 824754, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: AxQRTYSX23GW8Zoay2b8K5e5Hu7JVycM1KegNqGhbcGy Next: none Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let CONTRACT_TYPE = "LEND-LP-MARKET"
55
66 let VERSION = "PLP-1.2.1"
77
88 func getAddressFromState (key) = valueOrElse(addressFromString(valueOrElse(getString(this, ("setup_address_" + key)), "3PEwRcYNAUtoFvKpBhKoiwajnZfdoDR6h4h")), Address(base58'3PEwRcYNAUtoFvKpBhKoiwajnZfdoDR6h4h'))
99
1010
1111 func getAddressesFromState (key) = {
1212 func f (accum,next) = (accum ++ [valueOrElse(addressFromString(next), Address(base58'3PEwRcYNAUtoFvKpBhKoiwajnZfdoDR6h4h'))])
1313
1414 let $l = split_4C(valueOrElse(getString(this, ("setup_address_" + key)), "3PEwRcYNAUtoFvKpBhKoiwajnZfdoDR6h4h"), ",")
1515 let $s = size($l)
1616 let $acc0 = nil
1717 func $f0_1 ($a,$i) = if (($i >= $s))
1818 then $a
1919 else f($a, $l[$i])
2020
2121 func $f0_2 ($a,$i) = if (($i >= $s))
2222 then $a
2323 else throw("List size exceeds 15")
2424
2525 $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)
2626 }
2727
2828
2929 let reserveFundAddress = getAddressFromState("reserveFund")
3030
3131 let oracleAddress = getAddressFromState("oracle")
3232
3333 let aggregatorAddress = getAddressFromState("aggregator")
3434
3535 let adminAddress = getAddressFromState("admin")
3636
3737 let stableFundAddress = getAddressFromState("stableFund")
3838
3939 let feeCollectorAddress = getAddressFromState("feeCollector")
4040
4141 let shutdownWhitelist = getAddressesFromState("shutdownCallers")
4242
4343 let liquidatorsWhitelist = getAddressesFromState("liquidators")
4444
4545 func verifyLiquidatorRights (address) = (indexOf(liquidatorsWhitelist, address) != unit)
4646
4747
4848 let reserveFund = valueOrElse(getInteger(this, "setup_reserveFundFee"), 20)
4949
5050 let stablesIdStr = split(valueOrElse(getString(this, "setup_stablesIds"), "9wc3LXNA4TEBsXyKtoLE9mrbDD7WMHXvXrCjZvabLAsi,HGgabTqUS8WtVFUJzfmrTDMgEccJuZLBPhFgQFxvnsoW"), ",")
5151
5252 func getRateCurve (assetIdStr) = {
5353 let curveRateStrLi = split(valueOrElse(getString(this, ("setup_rateCurve_" + assetIdStr)), "20000000,100000000,60000000,400000000"), ",")
5454 $Tuple4(parseIntValue(curveRateStrLi[0]), parseIntValue(curveRateStrLi[1]), parseIntValue(curveRateStrLi[2]), parseIntValue(curveRateStrLi[3]))
5555 }
5656
5757
5858 func getRewardsSplitting (assetIdStr) = {
5959 let rewardsSplittingStrLi = split(valueOrElse(getString(this, ("setup_rewardsSplitting_" + assetIdStr)), "30,50,20"), ",")
6060 $Tuple3(parseIntValue(rewardsSplittingStrLi[0]), parseIntValue(rewardsSplittingStrLi[1]), parseIntValue(rewardsSplittingStrLi[2]))
6161 }
6262
6363
6464 let sentinels = [Address(base58'3PMcMiMEs6w56NRGacksXtFG5zS7doE9fpL'), Address(base58'3PQdNxynJy5mche2kxMVc5shXWzK8Gstq3o'), Address(base58'3P8auNWJkxxByyJtwErFXaxiXcGM45qQ1hA'), Address(base58'3P8qVX189qpoTJZQQQdKS9endHK5sxWsvrd')]
6565
6666 let Scale8 = 100000000
6767
6868 let Scale10 = 10000000000
6969
7070 let Scale16 = (Scale8 * Scale8)
7171
7272 let dayBlocks = 1440
7373
7474 let withdrawalLimitBlocks = valueOrElse(getInteger(this, "setup_withdrawalLimitBlocks"), 100)
7575
7676 func liIntToStr (li) = {
7777 func f (accum,next) = ((accum + toString(next)) + ",")
7878
7979 let $l = li
8080 let $s = size($l)
8181 let $acc0 = ""
8282 func $f0_1 ($a,$i) = if (($i >= $s))
8383 then $a
8484 else f($a, $l[$i])
8585
8686 func $f0_2 ($a,$i) = if (($i >= $s))
8787 then $a
8888 else throw("List size exceeds 12")
8989
9090 $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)
9191 }
9292
9393
9494 func tryGetInteger (key) = match getInteger(this, key) {
9595 case b: Int =>
9696 b
9797 case _ =>
9898 0
9999 }
100100
101101
102102 func tryGetBoolean (key) = match getBoolean(this, key) {
103103 case b: Boolean =>
104104 b
105105 case _ =>
106106 false
107107 }
108108
109109
110110 func tryGetString (key) = match getString(this, key) {
111111 case b: String =>
112112 b
113113 case _ =>
114114 ""
115115 }
116116
117117
118118 func tryGetBinary (key) = match getBinary(this, key) {
119119 case b: ByteVector =>
120120 b
121121 case _ =>
122122 base58''
123123 }
124124
125125
126126 func getAssetString (assetId) = match assetId {
127127 case b: ByteVector =>
128128 toBase58String(b)
129129 case _ =>
130130 "WAVES"
131131 }
132132
133133
134134 func getAssetBytes (assetIdStr) = if ((assetIdStr == "WAVES"))
135135 then unit
136136 else fromBase58String(assetIdStr)
137137
138138
139139 func getBalance (assetIdStr) = if ((assetIdStr == "WAVES"))
140140 then wavesBalance(this).available
141141 else assetBalance(this, fromBase58String(assetIdStr))
142142
143143
144144 func getMarketAssets () = split(tryGetString("setup_tokens"), ",")
145145
146146
147147 func getOutdatedUr (assetIdStr) = {
148148 let down = fraction(tryGetInteger(("total_supplied_" + assetIdStr)), tryGetInteger((assetIdStr + "_sRate")), Scale16)
149149 if ((down == 0))
150150 then 0
151151 else fraction(Scale8, fraction(tryGetInteger(("total_borrowed_" + assetIdStr)), tryGetInteger((assetIdStr + "_bRate")), Scale16), down)
152152 }
153153
154154
155155 func getInterest (assetIdStr) = {
156156 let ur = getOutdatedUr(assetIdStr)
157157 let curve = getRateCurve(assetIdStr)
158158 let rate = (curve._1 + (if ((curve._3 >= ur))
159159 then fraction(ur, curve._2, curve._3)
160160 else (curve._2 + fraction((ur - curve._3), curve._4, (100000000 - curve._3)))))
161161 max([fraction(rate, Scale8, (dayBlocks * 365)), 1])
162162 }
163163
164164
165165 func tokenRatesRecalc (assetIdStr) = {
166166 let interest = getInterest(assetIdStr)
167167 let ur = getOutdatedUr(assetIdStr)
168168 let lastRecalcHeight = tryGetInteger("lastRateHeight")
169169 let lastBRate = max([tryGetInteger((assetIdStr + "_bRate")), Scale16])
170170 let newBRate = (lastBRate + ((height - lastRecalcHeight) * interest))
171171 let lastSRate = max([tryGetInteger((assetIdStr + "_sRate")), Scale16])
172172 let newSRate = (lastSRate + ((((height - lastRecalcHeight) * fraction(interest, ur, Scale8)) * (100 - reserveFund)) / 100))
173173 [IntegerEntry((assetIdStr + "_sRate"), newSRate), IntegerEntry((assetIdStr + "_bRate"), newBRate), IntegerEntry("lastRateHeight", height)]
174174 }
175175
176176
177177 func getActualRate (assetIdStr,rateType) = {
178178 func f (accum,token) = {
179179 let recalc = tokenRatesRecalc(token)
180180 $Tuple2(if ((token != assetIdStr))
181181 then accum._1
182182 else if ((rateType == "sRate"))
183183 then recalc[0].value
184184 else recalc[1].value, (accum._2 ++ recalc))
185185 }
186186
187187 let $l = getMarketAssets()
188188 let $s = size($l)
189189 let $acc0 = $Tuple2(0, nil)
190190 func $f0_1 ($a,$i) = if (($i >= $s))
191191 then $a
192192 else f($a, $l[$i])
193193
194194 func $f0_2 ($a,$i) = if (($i >= $s))
195195 then $a
196196 else throw("List size exceeds 12")
197197
198198 $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)
199199 }
200200
201201
202202 func getUr (assetIdStr) = {
203203 let rates = tokenRatesRecalc(assetIdStr)
204204 let down = fraction(tryGetInteger(("total_supplied_" + assetIdStr)), rates[0].value, Scale16)
205205 fraction(Scale8, fraction(tryGetInteger(("total_borrowed_" + assetIdStr)), rates[1].value, Scale16), down)
206206 }
207207
208208
209209 func ratesRecalc () = {
210210 func f (accum,token) = (accum ++ tokenRatesRecalc(token))
211211
212212 let $l = getMarketAssets()
213213 let $s = size($l)
214214 let $acc0 = nil
215215 func $f0_1 ($a,$i) = if (($i >= $s))
216216 then $a
217217 else f($a, $l[$i])
218218
219219 func $f0_2 ($a,$i) = if (($i >= $s))
220220 then $a
221221 else throw("List size exceeds 12")
222222
223223 $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)
224224 }
225225
226226
227227 func getTokenPriceWithRisk (assetIdStr,riskAversity) = if ((indexOf(stablesIdStr, assetIdStr) != unit))
228228 then $Tuple2(1000000, 1000000)
229229 else {
230230 let price = getIntegerValue(oracleAddress, (assetIdStr + "_twap5B"))
231231 let riskLevel = getIntegerValue(oracleAddress, (assetIdStr + "_riskLevel"))
232232 if ((riskAversity >= riskLevel))
233233 then $Tuple2(price, price)
234234 else throw((("oracle prices don't match: " + toString(price)) + " is the price, but risk is too high"))
235235 }
236236
237237
238238 func getTokenPrice (assetIdStr) = getTokenPriceWithRisk(assetIdStr, 3)
239239
240240
241241 func getTokenPriceCapped (assetIdStr) = {
242242 let $t079878050 = getTokenPriceWithRisk(assetIdStr, 3)
243243 let minPrice = $t079878050._1
244244 let maxPrice = $t079878050._2
245245 let maxAllowedPrice = valueOrElse(getInteger(this, ("setup_maxPrice_" + assetIdStr)), -1)
246246 let minAllowedPrice = valueOrElse(getInteger(this, ("setup_minPrice_" + assetIdStr)), -1)
247247 if (if ((maxAllowedPrice != -1))
248248 then (maxPrice > maxAllowedPrice)
249249 else false)
250250 then $Tuple2(maxAllowedPrice, maxAllowedPrice)
251251 else if (if ((minAllowedPrice != -1))
252252 then (minAllowedPrice > minPrice)
253253 else false)
254254 then $Tuple2(minAllowedPrice, minAllowedPrice)
255255 else $Tuple2(minPrice, maxPrice)
256256 }
257257
258258
259259 func calcAssetScale (assetIdStr) = {
260260 let decimals = if ((assetIdStr == "WAVES"))
261261 then 8
262262 else value(assetInfo(fromBase58String(assetIdStr))).decimals
263263 pow(10, 0, decimals, 0, 0, DOWN)
264264 }
265265
266266
267267 func calcUserCollateral (address) = {
268268 let userCollateralInvoke = invoke(this, "getUserCollateral", [false, address, true, ""], nil)
269269 if ((userCollateralInvoke == userCollateralInvoke))
270270 then {
271271 let userCollateralValue = match userCollateralInvoke {
272272 case x: Int =>
273273 x
274274 case _ =>
275275 throw("issue while doing in-dapp invocation")
276276 }
277277 if ((userCollateralValue == userCollateralValue))
278278 then userCollateralValue
279279 else throw("Strict value is not equal to itself.")
280280 }
281281 else throw("Strict value is not equal to itself.")
282282 }
283283
284284
285285 func checkWithdrawalLimit (address,assetIdStr,amountInternal,sRate) = {
286286 let withdrawalLimit = valueOrElse(getInteger(this, (("setup_" + assetIdStr) + "_maxWithdrawPer100B")), -1)
287287 if ((withdrawalLimit == -1))
288288 then nil
289289 else {
290290 let totalSupplied = tryGetInteger(("total_supplied_" + assetIdStr))
291291 let limitCap = fraction(totalSupplied, withdrawalLimit, 100)
292292 let lastH = tryGetInteger(((address + "_withdrawLimitHeight_") + assetIdStr))
293293 let elapsed = (height - lastH)
294294 let windowExpired = (elapsed > withdrawalLimitBlocks)
295295 let currentUsed = if (windowExpired)
296296 then 0
297297 else tryGetInteger(((address + "_withdrawLimitUsed_") + assetIdStr))
298298 let blocksToReset = if (windowExpired)
299299 then withdrawalLimitBlocks
300300 else (withdrawalLimitBlocks - elapsed)
301301 let available = (limitCap - currentUsed)
302302 let availableScaled = fraction(available, sRate, Scale16, CEILING)
303303 if ((amountInternal > available))
304304 then throw(((((("withdrawal limit exceeded for " + assetIdStr) + ", available: ") + toString(availableScaled)) + ", blocks to reset: ") + toString(blocksToReset)))
305305 else ((if (windowExpired)
306306 then [IntegerEntry(((address + "_withdrawLimitHeight_") + assetIdStr), height)]
307307 else nil) ++ [IntegerEntry(((address + "_withdrawLimitUsed_") + assetIdStr), (currentUsed + amountInternal))])
308308 }
309309 }
310310
311311
312312 func checkBorrowLimit (address,assetIdStr,amountInternal,bRate,sRate) = {
313313 let borrowLimit = valueOrElse(getInteger(this, (("setup_" + assetIdStr) + "_maxBorrowPer100B")), -1)
314314 if ((borrowLimit == -1))
315315 then nil
316316 else {
317317 let totalSupplied = tryGetInteger(("total_supplied_" + assetIdStr))
318318 let limitCapSupply = fraction(totalSupplied, borrowLimit, 100)
319319 let limitCap = fraction(fraction(limitCapSupply, sRate, Scale16), Scale16, bRate)
320320 let lastH = tryGetInteger(((address + "_borrowLimitHeight_") + assetIdStr))
321321 let elapsed = (height - lastH)
322322 let windowExpired = (elapsed > withdrawalLimitBlocks)
323323 let currentUsed = if (windowExpired)
324324 then 0
325325 else tryGetInteger(((address + "_borrowLimitUsed_") + assetIdStr))
326326 let blocksToReset = if (windowExpired)
327327 then withdrawalLimitBlocks
328328 else (withdrawalLimitBlocks - elapsed)
329329 let available = (limitCap - currentUsed)
330330 let availableScaled = fraction(available, bRate, Scale16, CEILING)
331331 if ((amountInternal > available))
332332 then throw(((((("borrow limit exceeded for " + assetIdStr) + ", available: ") + toString(availableScaled)) + ", blocks to reset: ") + toString(blocksToReset)))
333333 else ((if (windowExpired)
334334 then [IntegerEntry(((address + "_borrowLimitHeight_") + assetIdStr), height)]
335335 else nil) ++ [IntegerEntry(((address + "_borrowLimitUsed_") + assetIdStr), (currentUsed + amountInternal))])
336336 }
337337 }
338338
339339
340340 @Callable(i)
341341 func supply () = if (!(tryGetBoolean("setup_active")))
342342 then throw("market is stopped")
343343 else if (if ((size(i.payments) != 1))
344344 then true
345345 else (i.payments[0].amount == 0))
346346 then throw("1 payment has to be attached")
347347 else {
348348 let assetIdStr = getAssetString(i.payments[0].assetId)
349349 let assetAmount = i.payments[0].amount
350350 let $t01205812125 = getActualRate(assetIdStr, "sRate")
351351 let sRate = $t01205812125._1
352352 let ratesRecalcResult = $t01205812125._2
353353 let amount = fraction(assetAmount, Scale16, sRate, DOWN)
354354 let address = toString(i.caller)
355355 let maxSupply = match getString(("setup_maxSupply_" + assetIdStr)) {
356356 case x: String =>
357357 parseIntValue(x)
358358 case _ =>
359359 tryGetInteger(("setup_maxSupply_" + assetIdStr))
360360 }
361361 let assetPrice = getTokenPriceCapped(assetIdStr)
362362 let newAddressSupplied = (tryGetInteger(((address + "_supplied_") + assetIdStr)) + amount)
363363 let newTotalSupplied = (tryGetInteger(("total_supplied_" + assetIdStr)) + amount)
364364 let rate = getActualRate(assetIdStr, "sRate")._1
365365 let assetScale = calcAssetScale(assetIdStr)
366366 let newTotalSuppliedUsd = fraction(fraction(newTotalSupplied, rate, Scale16), assetPrice._1, assetScale)
367367 if ((indexOf(tryGetString("setup_tokens"), assetIdStr) == unit))
368368 then throw("this asset is not supported by the market")
369369 else if (if ((maxSupply != 0))
370370 then (newTotalSuppliedUsd > maxSupply)
371371 else false)
372372 then throw("max total supply for this token reached in the pool")
373373 else if ((tryGetInteger(("setup_paused_" + assetIdStr)) > 0))
374374 then throw("this asset can't be supplied or borrowed")
375375 else {
376376 let inv = if ((tryGetString(("setup_autostake_" + assetIdStr)) != ""))
377377 then invoke(this, "stakeToken", [assetIdStr, assetAmount], nil)
378378 else unit
379379 if ((inv == inv))
380380 then ([IntegerEntry(((address + "_supplied_") + assetIdStr), newAddressSupplied), IntegerEntry(("total_supplied_" + assetIdStr), newTotalSupplied)] ++ ratesRecalcResult)
381381 else throw("Strict value is not equal to itself.")
382382 }
383383 }
384384
385385
386386
387387 @Callable(i)
388388 func withdraw (assetIdStr,assetAmount) = {
389389 let $t01369213759 = getActualRate(assetIdStr, "sRate")
390390 let sRate = $t01369213759._1
391391 let ratesRecalcResult = $t01369213759._2
392392 let amount = fraction(assetAmount, Scale16, sRate, CEILING)
393393 let address = toString(i.caller)
394394 let assetSupplied = tryGetInteger(("total_supplied_" + assetIdStr))
395395 let assetBorrowed = tryGetInteger(("total_borrowed_" + assetIdStr))
396396 let userAssetSupplied = tryGetInteger(((address + "_supplied_") + assetIdStr))
397397 let userAssetBorrowed = tryGetInteger(((address + "_borrowed_") + assetIdStr))
398398 let collateralValueInv = invoke(this, "getUserCollateral", [false, address, true, ((assetIdStr + ",supplied,") + toString(-(amount)))], nil)
399399 if ((collateralValueInv == collateralValueInv))
400400 then {
401401 let collateralValue = match collateralValueInv {
402402 case x: Int =>
403403 x
404404 case _ =>
405405 throw("can't get user collateral value")
406406 }
407407 if (!(tryGetBoolean("setup_active")))
408408 then throw("market is stopped")
409409 else if ((0 > collateralValue))
410410 then throw("you dont have enough collateral for this operation")
411411 else if ((amount > (assetSupplied - assetBorrowed)))
412412 then throw("this amount is not available on the market")
413413 else if ((amount > (userAssetSupplied - userAssetBorrowed)))
414414 then throw("this amount is not available for this user")
415415 else {
416416 let inv = if ((tryGetString(("setup_autostake_" + assetIdStr)) != ""))
417417 then invoke(this, "unstakeToken", [assetIdStr, assetAmount], nil)
418418 else unit
419419 if ((inv == inv))
420420 then {
421421 let limitCheckActions = checkWithdrawalLimit(address, assetIdStr, amount, sRate)
422422 if ((limitCheckActions == limitCheckActions))
423423 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)
424424 else throw("Strict value is not equal to itself.")
425425 }
426426 else throw("Strict value is not equal to itself.")
427427 }
428428 }
429429 else throw("Strict value is not equal to itself.")
430430 }
431431
432432
433433
434434 @Callable(i)
435435 func borrow (assetIdStr,assetAmount) = {
436436 let address = toString(i.caller)
437437 let $t01552315590 = getActualRate(assetIdStr, "bRate")
438438 let bRate = $t01552315590._1
439439 let ratesRecalcResult = $t01552315590._2
440440 let amount = fraction(assetAmount, Scale16, bRate, CEILING)
441441 let collateralValueInv = invoke(this, "getUserCollateral", [false, address, true, ((assetIdStr + ",borrowed,") + toString(amount))], nil)
442442 if ((collateralValueInv == collateralValueInv))
443443 then {
444444 let collateralValue = match collateralValueInv {
445445 case x: Int =>
446446 x
447447 case _ =>
448448 throw("can't get user collateral value")
449449 }
450450 if (!(tryGetBoolean("setup_active")))
451451 then throw("market is stopped")
452452 else if ((0 > collateralValue))
453453 then throw("you have to supply more to borrow")
454454 else if ((tryGetInteger(("setup_borrowEnabled_" + assetIdStr)) == 0))
455455 then throw("this asset can't be borrowed")
456456 else if ((tryGetInteger(("setup_paused_" + assetIdStr)) > 0))
457457 then throw("this asset can't be supplied or borrowed")
458458 else {
459459 let assetSupplied = tryGetInteger(("total_supplied_" + assetIdStr))
460460 let assetBorrowed = tryGetInteger(("total_borrowed_" + assetIdStr))
461461 let userAssetBorrowed = tryGetInteger(((address + "_borrowed_") + assetIdStr))
462462 if ((amount > (assetSupplied - assetBorrowed)))
463463 then throw("this amount is not available")
464464 else {
465465 let inv = if ((tryGetString(("setup_autostake_" + assetIdStr)) != ""))
466466 then invoke(this, "unstakeToken", [assetIdStr, assetAmount], nil)
467467 else unit
468468 if ((inv == inv))
469469 then {
470470 let sRate = ratesRecalcResult[(value(indexOf(getMarketAssets(), assetIdStr)) * 3)].value
471471 let limitCheckActions = checkBorrowLimit(address, assetIdStr, amount, bRate, sRate)
472472 if ((limitCheckActions == limitCheckActions))
473473 then (([IntegerEntry(((address + "_borrowed_") + assetIdStr), (userAssetBorrowed + amount)), IntegerEntry(("total_borrowed_" + assetIdStr), (assetBorrowed + amount)), ScriptTransfer(i.caller, assetAmount, getAssetBytes(assetIdStr))] ++ ratesRecalcResult) ++ limitCheckActions)
474474 else throw("Strict value is not equal to itself.")
475475 }
476476 else throw("Strict value is not equal to itself.")
477477 }
478478 }
479479 }
480480 else throw("Strict value is not equal to itself.")
481481 }
482482
483483
484484
485485 @Callable(i)
486486 func repay () = if (!(tryGetBoolean("setup_active")))
487487 then throw("market is stopped")
488488 else if (if ((size(i.payments) != 1))
489489 then true
490490 else (i.payments[0].amount == 0))
491491 then throw("1 payment has to be attached")
492492 else {
493493 let assetIdStr = getAssetString(i.payments[0].assetId)
494494 let assetAmount = i.payments[0].amount
495495 let $t01768417751 = getActualRate(assetIdStr, "bRate")
496496 let bRate = $t01768417751._1
497497 let ratesRecalcResult = $t01768417751._2
498498 let amount = fraction(assetAmount, Scale16, bRate, CEILING)
499499 let address = toString(i.caller)
500500 let assetSupplied = tryGetInteger(("total_supplied_" + assetIdStr))
501501 let assetBorrowed = tryGetInteger(("total_borrowed_" + assetIdStr))
502502 let userAssetBorrowed = tryGetInteger(((address + "_borrowed_") + assetIdStr))
503503 let amountLeft = (userAssetBorrowed - amount)
504504 let repayAmount = if ((amountLeft >= 0))
505505 then amount
506506 else userAssetBorrowed
507507 if ((indexOf(tryGetString("setup_tokens"), assetIdStr) == unit))
508508 then throw("this asset is not supported by the market")
509509 else {
510510 let inv = if ((tryGetString(("setup_autostake_" + assetIdStr)) != ""))
511511 then invoke(this, "stakeToken", [assetIdStr, assetAmount], nil)
512512 else unit
513513 if ((inv == inv))
514514 then {
515515 let excessTokens = (assetAmount - fraction(repayAmount, bRate, Scale16))
516516 (([IntegerEntry(((address + "_borrowed_") + assetIdStr), (userAssetBorrowed - repayAmount)), IntegerEntry(("total_borrowed_" + assetIdStr), (assetBorrowed - repayAmount))] ++ ratesRecalcResult) ++ (if ((amountLeft >= 0))
517517 then nil
518518 else [ScriptTransfer(i.caller, excessTokens, i.payments[0].assetId)]))
519519 }
520520 else throw("Strict value is not equal to itself.")
521521 }
522522 }
523523
524524
525525
526526 @Callable(i)
527527 func repayFor (address) = if (!(tryGetBoolean("setup_active")))
528528 then throw("market is stopped")
529529 else if ((i.caller != reserveFundAddress))
530530 then throw("available only for reserve fund address")
531531 else if ((address == "global"))
532532 then throw("you can't repay for everyone :_)")
533533 else if (if ((size(i.payments) != 1))
534534 then true
535535 else (i.payments[0].amount == 0))
536536 then throw("1 payment has to be attached")
537537 else {
538538 let assetIdStr = getAssetString(i.payments[0].assetId)
539539 let assetAmount = i.payments[0].amount
540540 let $t01942719494 = getActualRate(assetIdStr, "bRate")
541541 let bRate = $t01942719494._1
542542 let ratesRecalcResult = $t01942719494._2
543543 let amount = fraction(assetAmount, Scale16, bRate, CEILING)
544544 let assetSupplied = tryGetInteger(("total_supplied_" + assetIdStr))
545545 let assetBorrowed = tryGetInteger(("total_borrowed_" + assetIdStr))
546546 let userAssetBorrowed = tryGetInteger(((address + "_borrowed_") + assetIdStr))
547547 let amountLeft = (userAssetBorrowed - amount)
548548 let repayAmount = if ((amountLeft >= 0))
549549 then amount
550550 else userAssetBorrowed
551551 if ((indexOf(tryGetString("setup_tokens"), assetIdStr) == unit))
552552 then throw("this asset is not supported by the market")
553553 else {
554554 let inv = if ((tryGetString(("setup_autostake_" + assetIdStr)) != ""))
555555 then invoke(this, "stakeToken", [assetIdStr, assetAmount], nil)
556556 else unit
557557 if ((inv == inv))
558558 then {
559559 let excessTokens = (assetAmount - fraction(repayAmount, bRate, Scale16))
560560 (([IntegerEntry(((address + "_borrowed_") + assetIdStr), (userAssetBorrowed - repayAmount)), IntegerEntry(("total_borrowed_" + assetIdStr), (assetBorrowed - repayAmount))] ++ ratesRecalcResult) ++ (if ((amountLeft >= 0))
561561 then nil
562562 else [ScriptTransfer(i.caller, excessTokens, i.payments[0].assetId)]))
563563 }
564564 else throw("Strict value is not equal to itself.")
565565 }
566566 }
567567
568568
569569
570570 @Callable(i)
571571 func stakeToken (assetIdStr,amount) = {
572572 let autostakeAddress = valueOrElse(addressFromString(tryGetString(("setup_autostake_" + assetIdStr))), Address(base58'3PDDRRS5gKyDQRpJskzWTdxREHGu1FNpdwg'))
573573 let stakerSupportedAssets = getStringValue(autostakeAddress, "setup_supportedAssets")
574574 if ((i.caller != this))
575575 then throw("only for internal smart contract invocations")
576576 else if ((indexOf(stakerSupportedAssets, assetIdStr) == unit))
577577 then nil
578578 else {
579579 let amountStaked = tryGetInteger(("autostake_amount_" + assetIdStr))
580580 let stakeInv = reentrantInvoke(autostakeAddress, "stakeLP", nil, [AttachedPayment(getAssetBytes(assetIdStr), amount)])
581581 if ((stakeInv == stakeInv))
582582 then [IntegerEntry(("autostake_amount_" + assetIdStr), (amountStaked + amount))]
583583 else throw("Strict value is not equal to itself.")
584584 }
585585 }
586586
587587
588588
589589 @Callable(i)
590590 func stakeTokenAll (assetIdStr) = if ((i.caller != this))
591591 then throw("only for internal smart contract invocations")
592592 else {
593593 let amount = getBalance(assetIdStr)
594594 let inv = reentrantInvoke(this, "stakeToken", [assetIdStr, amount], nil)
595595 if ((inv == inv))
596596 then nil
597597 else throw("Strict value is not equal to itself.")
598598 }
599599
600600
601601
602602 @Callable(i)
603603 func unstakeToken (assetIdStr,amount) = {
604604 let autostakeAddress = valueOrElse(addressFromString(tryGetString(("setup_autostake_" + assetIdStr))), Address(base58'3PDDRRS5gKyDQRpJskzWTdxREHGu1FNpdwg'))
605605 let stakerSupportedAssets = getStringValue(autostakeAddress, "setup_supportedAssets")
606606 if ((i.caller != this))
607607 then throw("only for internal smart contract invocations")
608608 else if ((indexOf(stakerSupportedAssets, assetIdStr) == unit))
609609 then nil
610610 else {
611611 let amountStaked = tryGetInteger(("autostake_amount_" + assetIdStr))
612612 let stakeInv = reentrantInvoke(autostakeAddress, "unstakeLP", [assetIdStr, amount], nil)
613613 if ((stakeInv == stakeInv))
614614 then [IntegerEntry(("autostake_amount_" + assetIdStr), (amountStaked - amount))]
615615 else throw("Strict value is not equal to itself.")
616616 }
617617 }
618618
619619
620620
621621 @Callable(i)
622622 func addInterest (assetIdStr,amount) = if ((i.caller != this))
623623 then throw("only for self invocation")
624624 else {
625625 let earned = tryGetInteger(("autostake_lastEarned_" + assetIdStr))
626626 let lastHeight = tryGetInteger(("autostake_lastBlock_" + assetIdStr))
627627 let cleanAmount = fraction(amount, 80, 100)
628628 let stakingFee = (amount - cleanAmount)
629629 let stateChanges = if (if ((lastHeight == height))
630630 then true
631631 else (amount == 0))
632632 then nil
633633 else [IntegerEntry(("autostake_preLastEarned_" + assetIdStr), earned), IntegerEntry(("autostake_preLastBlock_" + assetIdStr), lastHeight), IntegerEntry(("autostake_lastEarned_" + assetIdStr), (earned + cleanAmount)), IntegerEntry(("autostake_lastBlock_" + assetIdStr), height)]
634634 (stateChanges ++ [IntegerEntry((assetIdStr + "_sRate"), (tryGetInteger((assetIdStr + "_sRate")) + fraction(Scale16, cleanAmount, tryGetInteger(("total_supplied_" + assetIdStr))))), IntegerEntry((("fee_" + assetIdStr) + "_staking"), (tryGetInteger((("fee_" + assetIdStr) + "_staking")) + stakingFee))])
635635 }
636636
637637
638638
639639 @Callable(i)
640640 func addInterestEXTERNAL () = {
641641 let assetId = i.payments[0].assetId
642642 let assetIdStr = getAssetString(assetId)
643643 let splitting = getRewardsSplitting(assetIdStr)
644644 let amount = fraction(i.payments[0].amount, splitting._2, 100)
645645 let earned = tryGetInteger(("autostake_lastEarned_" + assetIdStr))
646646 let lastHeight = tryGetInteger(("autostake_lastBlock_" + assetIdStr))
647647 let stateChanges = if (if ((lastHeight == height))
648648 then true
649649 else (amount == 0))
650650 then nil
651651 else [IntegerEntry(("autostake_preLastEarned_" + assetIdStr), earned), IntegerEntry(("autostake_preLastBlock_" + assetIdStr), lastHeight), IntegerEntry(("autostake_lastEarned_" + assetIdStr), (earned + amount)), IntegerEntry(("autostake_lastBlock_" + assetIdStr), height)]
652652 (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)))])
653653 }
654654
655655
656656
657657 @Callable(i)
658658 func preInit (tokens,ltvs,lts,penalties) = {
659659 func f (accum,token) = (accum ++ [IntegerEntry((token + "_bRate"), Scale16), IntegerEntry((token + "_sRate"), Scale16)])
660660
661661 if ((i.caller != this))
662662 then throw("admin only")
663663 else {
664664 let rates = {
665665 let $l = split(tokens, ",")
666666 let $s = size($l)
667667 let $acc0 = nil
668668 func $f0_1 ($a,$i) = if (($i >= $s))
669669 then $a
670670 else f($a, $l[$i])
671671
672672 func $f0_2 ($a,$i) = if (($i >= $s))
673673 then $a
674674 else throw("List size exceeds 12")
675675
676676 $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)
677677 }
678678 ([StringEntry("setup_tokens", tokens), StringEntry("setup_ltvs", ltvs), StringEntry("setup_lts", lts), StringEntry("setup_penalties", penalties), BooleanEntry("setup_active", true)] ++ rates)
679679 }
680680 }
681681
682682
683683
684684 @Callable(i)
685685 func initNewToken (token,ltv,lt,penalty) = if ((i.caller != this))
686686 then throw("admin only")
687687 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)]
688688
689689
690690
691691 @Callable(i)
692692 func updateParameter (key,val) = if (if ((i.caller != this))
693693 then (i.caller != adminAddress)
694694 else false)
695695 then throw("admin only")
696696 else [IntegerEntry(key, parseIntValue(val))]
697697
698698
699699
700700 @Callable(i)
701701 func updateString (key,val) = if (if ((i.caller != this))
702702 then (i.caller != adminAddress)
703703 else false)
704704 then throw("admin only")
705705 else [StringEntry(key, val)]
706706
707707
708708
709709 @Callable(i)
710710 func claimToReserveFund (debug) = {
711711 let _allowed = if ((getString(this, "setup_address_feeCollector") != unit))
712712 then throw("fee collector is configured, use claimFees()/claimFeesAll() instead")
713713 else unit
714714 if ((_allowed == _allowed))
715715 then {
716716 let assets = getMarketAssets()
717717 let rates = getActualRate(assets[0], "sRate")._2
718718 let li = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
719719 func f (accum,n) = if ((n >= size(assets)))
720720 then accum
721721 else {
722722 let assetIdStr = assets[n]
723723 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))
724724 let inv = if ((tryGetString(("setup_autostake_" + assetIdStr)) != ""))
725725 then invoke(this, "unstakeToken", [assetIdStr, amount], nil)
726726 else unit
727727 if ((inv == inv))
728728 then (accum ++ [amount])
729729 else throw("Strict value is not equal to itself.")
730730 }
731731
732732 let parameter = {
733733 let $l = li
734734 let $s = size($l)
735735 let $acc0 = nil
736736 func $f0_1 ($a,$i) = if (($i >= $s))
737737 then $a
738738 else f($a, $l[$i])
739739
740740 func $f0_2 ($a,$i) = if (($i >= $s))
741741 then $a
742742 else throw("List size exceeds 12")
743743
744744 $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)
745745 }
746746 func f2 (accum,n) = if ((n >= size(assets)))
747747 then accum
748748 else {
749749 let assetIdStr = assets[n]
750750 (accum ++ [ScriptTransfer(reserveFundAddress, max([parameter[n], 0]), getAssetBytes(assetIdStr))])
751751 }
752752
753753 if (debug)
754754 then throw(liIntToStr(parameter))
755755 else $Tuple2({
756756 let $l = li
757757 let $s = size($l)
758758 let $acc0 = nil
759759 func $f1_1 ($a,$i) = if (($i >= $s))
760760 then $a
761761 else f2($a, $l[$i])
762762
763763 func $f1_2 ($a,$i) = if (($i >= $s))
764764 then $a
765765 else throw("List size exceeds 12")
766766
767767 $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)
768768 }, parameter)
769769 }
770770 else throw("Strict value is not equal to itself.")
771771 }
772772
773773
774774
775775 @Callable(i)
776776 func claimFees (assetIdStr) = if ((getString(this, "setup_address_feeCollector") == unit))
777777 then throw("fee collector not configured")
778778 else if ((indexOf(tryGetString("setup_tokens"), assetIdStr) == unit))
779779 then throw("this asset is not supported by the market")
780780 else {
781781 let isStaked = (tryGetString(("setup_autostake_" + assetIdStr)) != "")
782782 let rates = tokenRatesRecalc(assetIdStr)
783783 let sRate = rates[0].value
784784 let bRate = rates[1].value
785785 let bal = getBalance(assetIdStr)
786786 let liq = tryGetInteger((("fee_" + assetIdStr) + "_liquidation"))
787787 let stk = tryGetInteger((("fee_" + assetIdStr) + "_staking"))
788788 let interest = if (isStaked)
789789 then 0
790790 else max([((((bal + fraction(tryGetInteger(("total_borrowed_" + assetIdStr)), bRate, Scale16)) - fraction(tryGetInteger(("total_supplied_" + assetIdStr)), sRate, Scale16)) - liq) - stk), 0])
791791 let pay = min([((interest + stk) + liq), bal])
792792 if ((0 >= pay))
793793 then nil
794794 else {
795795 let liqP = min([liq, pay])
796796 let stkP = min([stk, (pay - liqP)])
797797 let interestP = ((pay - liqP) - stkP)
798798 let recordInv = invoke(feeCollectorAddress, "processFees", [assetIdStr, interestP, stkP, liqP], [AttachedPayment(getAssetBytes(assetIdStr), pay)])
799799 if ((recordInv == recordInv))
800800 then [IntegerEntry((("fee_" + assetIdStr) + "_liquidation"), (liq - liqP)), IntegerEntry((("fee_" + assetIdStr) + "_staking"), (stk - stkP))]
801801 else throw("Strict value is not equal to itself.")
802802 }
803803 }
804804
805805
806806
807807 @Callable(i)
808808 func claimFeesAll (tokensList) = {
809809 let tokens = if ((tokensList == ""))
810810 then getMarketAssets()
811811 else split(tokensList, ",")
812812 func f (accum,token) = {
813813 let inv = invoke(this, "claimFees", [token], nil)
814814 if ((inv == inv))
815815 then accum
816816 else throw("Strict value is not equal to itself.")
817817 }
818818
819819 let done = {
820820 let $l = tokens
821821 let $s = size($l)
822822 let $acc0 = unit
823823 func $f0_1 ($a,$i) = if (($i >= $s))
824824 then $a
825825 else f($a, $l[$i])
826826
827827 func $f0_2 ($a,$i) = if (($i >= $s))
828828 then $a
829829 else throw("List size exceeds 12")
830830
831831 $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)
832832 }
833833 if ((done == done))
834834 then nil
835835 else throw("Strict value is not equal to itself.")
836836 }
837837
838838
839839
840840 @Callable(i)
841841 func reSetup (assetIdStr) = {
842842 let lastResetup = tryGetInteger("resetup_lastUpdate")
843843 if ((dayBlocks > (height - lastResetup)))
844844 then throw("can be updated only once per day")
845845 else {
846846 let lts = split(tryGetString("setup_lts"), ",")
847847 let assets = getMarketAssets()
848848 let ur = getUr(assetIdStr)
849849 let tempLT = tryGetInteger((("setup_" + assetIdStr) + "_tempLT"))
850850 let lt = parseIntValue(assets[value(indexOf(assets, assetIdStr))])
851851 if ((ur > 90000000))
852852 then [IntegerEntry((("setup_" + assetIdStr) + "_tempLT"), fraction(tempLT, 9975, 10000))]
853853 else if (if ((lt > tempLT))
854854 then (90000000 > ur)
855855 else false)
856856 then [IntegerEntry((("setup_" + assetIdStr) + "_tempLT"), fraction(tempLT, 10025, 10000))]
857857 else nil
858858 }
859859 }
860860
861861
862862
863863 @Callable(i)
864864 func shutdown (shutdown) = if ((indexOf(shutdownWhitelist, i.caller) == unit))
865865 then throw("user not in a whitelist")
866866 else [BooleanEntry("setup_active", !(shutdown))]
867867
868868
869869
870870 @Callable(i)
871871 func liquidate (debug,address,assetAmount,sAssetIdStr,bAssetIdStr,routeStr) = if (!(verifyLiquidatorRights(i.caller)))
872872 then throw("temporarily available for whitelist only")
873873 else if (!(tryGetBoolean("setup_active")))
874874 then throw("market is stopped")
875875 else {
876876 let userCollateral = calcUserCollateral(address)
877877 if ((userCollateral == userCollateral))
878878 then {
879879 let $t03546735529 = getActualRate(sAssetIdStr, "sRate")
880880 let sRate = $t03546735529._1
881881 let ratesResult = $t03546735529._2
882882 let $t03553435603 = getActualRate(bAssetIdStr, "bRate")
883883 let bRate = $t03553435603._1
884884 let ratesRecalcResult2 = $t03553435603._2
885885 let sAssetAmount = fraction(assetAmount, Scale16, sRate)
886886 let currentSPosition = tryGetInteger(((address + "_supplied_") + sAssetIdStr))
887887 let currentBPositionVal = tryGetInteger(((address + "_borrowed_") + bAssetIdStr))
888888 let currentBPosition = if ((currentBPositionVal > 0))
889889 then currentBPositionVal
890890 else throw("user has no borrow in this token")
891891 if ((userCollateral > 0))
892892 then throw("user can't be liquidated")
893893 else if ((sAssetAmount > currentSPosition))
894894 then throw("position to liquidate is bigger than user's supply")
895895 else {
896896 let inv = if ((tryGetString(("setup_autostake_" + sAssetIdStr)) != ""))
897897 then invoke(this, "unstakeToken", [sAssetIdStr, sAssetAmount], nil)
898898 else unit
899899 if ((inv == inv))
900900 then {
901901 let balance0Before = getBalance(sAssetIdStr)
902902 if ((balance0Before == balance0Before))
903903 then {
904904 let balance1Before = getBalance(bAssetIdStr)
905905 if ((balance1Before == balance1Before))
906906 then {
907907 let exchangeInvoke = invoke(aggregatorAddress, "swap", [routeStr, 0], [AttachedPayment(getAssetBytes(sAssetIdStr), assetAmount)])
908908 if ((exchangeInvoke == exchangeInvoke))
909909 then {
910910 let asset0Sold = (balance0Before - getBalance(sAssetIdStr))
911911 if ((asset0Sold == asset0Sold))
912912 then {
913913 let asset1Bought = (getBalance(bAssetIdStr) - balance1Before)
914914 if ((asset1Bought == asset1Bought))
915915 then {
916916 let asset0Price = getTokenPriceCapped(sAssetIdStr)._1
917917 let asset0Scale = calcAssetScale(sAssetIdStr)
918918 let asset0Usd = fraction(asset0Sold, asset0Price, asset0Scale)
919919 let asset1Price = getTokenPriceCapped(bAssetIdStr)._2
920920 let asset1Scale = calcAssetScale(bAssetIdStr)
921921 let asset1Usd = fraction(asset1Bought, asset1Price, asset1Scale)
922922 let penalty = parseIntValue(split(tryGetString("setup_penalties"), ",")[value(indexOf(getMarketAssets(), bAssetIdStr))])
923923 let liquidationProfit = (asset1Usd - fraction(asset0Usd, (Scale8 - penalty), Scale8))
924924 let sAssetChange = fraction(asset0Sold, Scale16, sRate)
925925 let bAssetChange = fraction(fraction(asset1Bought, Scale16, bRate), (Scale8 - fraction(liquidationProfit, Scale8, asset1Usd)), Scale8)
926926 if ((asset0Sold > assetAmount))
927927 then throw("more assets exchanged than expected")
928928 else if ((0 > liquidationProfit))
929929 then throw("price impact is bigger than liquidation penalty")
930930 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))))]
931931 }
932932 else throw("Strict value is not equal to itself.")
933933 }
934934 else throw("Strict value is not equal to itself.")
935935 }
936936 else throw("Strict value is not equal to itself.")
937937 }
938938 else throw("Strict value is not equal to itself.")
939939 }
940940 else throw("Strict value is not equal to itself.")
941941 }
942942 else throw("Strict value is not equal to itself.")
943943 }
944944 }
945945 else throw("Strict value is not equal to itself.")
946946 }
947947
948948
949949
950950 @Callable(i)
951951 func liquidateV2 (debug,address,sAssetIdStr) = if (!(verifyLiquidatorRights(i.caller)))
952952 then throw("temporarily available for whitelist only")
953953 else if (!(tryGetBoolean("setup_active")))
954954 then throw("market is stopped")
955955 else {
956956 let bAssetId = i.payments[0].assetId
957957 let bAssetIdStr = getAssetString(bAssetId)
958958 let bAssetAmount = i.payments[0].amount
959959 let userCollateral = calcUserCollateral(address)
960960 if ((userCollateral == userCollateral))
961961 then if ((userCollateral > 0))
962962 then throw("user can't be liquidated")
963963 else {
964964 let marketAssets = getMarketAssets()
965965 let asset1Num = value(indexOf(marketAssets, bAssetIdStr))
966966 let asset0Num = value(indexOf(marketAssets, sAssetIdStr))
967967 let $t03922439286 = getActualRate(bAssetIdStr, "bRate")
968968 let bRate = $t03922439286._1
969969 let ratesResult = $t03922439286._2
970970 let asset1Price = getTokenPriceCapped(bAssetIdStr)._2
971971 let asset1Scale = calcAssetScale(bAssetIdStr)
972972 let bAmountUsd = fraction(bAssetAmount, asset1Price, asset1Scale)
973973 let penalty = parseIntValue(value(split(tryGetString("setup_penalties"), ",")[asset1Num]))
974974 let asset0Price = getTokenPriceCapped(sAssetIdStr)._1
975975 let asset0Scale = calcAssetScale(sAssetIdStr)
976976 let sAmountUsd = fraction(bAmountUsd, (Scale8 + penalty), Scale8)
977977 let sAssetAmount = fraction(sAmountUsd, asset0Scale, asset0Price)
978978 let bAmount = fraction(bAssetAmount, Scale16, bRate)
979979 let sAmount = fraction(sAssetAmount, Scale16, ratesResult[(asset0Num * 3)].value)
980980 let currentSPosition = tryGetInteger(((address + "_supplied_") + sAssetIdStr))
981981 let currentBPositionVal = tryGetInteger(((address + "_borrowed_") + bAssetIdStr))
982982 let currentBPosition = if ((currentBPositionVal > 0))
983983 then currentBPositionVal
984984 else throw("user has no borrow in this token")
985985 if ((sAmount > currentSPosition))
986986 then throw("position to liquidate is bigger than user's supply")
987987 else {
988988 let inv = if ((tryGetString(("setup_autostake_" + sAssetIdStr)) != ""))
989989 then invoke(this, "unstakeToken", [sAssetIdStr, sAssetAmount], nil)
990990 else unit
991991 if ((inv == inv))
992992 then if (debug)
993993 then throw("liquidation will pass")
994994 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)
995995 else throw("Strict value is not equal to itself.")
996996 }
997997 }
998998 else throw("Strict value is not equal to itself.")
999999 }
10001000
10011001
10021002
10031003 @Callable(i)
10041004 func getUserCollateral (debug,address,minusBorrowed,afterChange) = {
10051005 let assets = getMarketAssets()
10061006 let ltvs = split(tryGetString("setup_ltvs"), ",")
10071007 let lts = split(tryGetString("setup_lts"), ",")
10081008 let rates = getActualRate(assets[0], "sRate")._2
10091009 let changeHandler = split(afterChange, ",")
10101010 func f (accum,next) = if ((next >= size(assets)))
10111011 then accum
10121012 else {
10131013 let userSupplied = tryGetInteger(((address + "_supplied_") + assets[next]))
10141014 let userBorrowed = tryGetInteger(((address + "_borrowed_") + assets[next]))
10151015 let needTokenAccounting = if ((afterChange == ""))
10161016 then if (if ((userBorrowed != 0))
10171017 then true
10181018 else (userSupplied != 0))
10191019 then true
10201020 else false
10211021 else true
10221022 if (needTokenAccounting)
10231023 then {
10241024 let assetScale = calcAssetScale(assets[next])
10251025 let assetPrice = getTokenPriceCapped(assets[next])
10261026 ((accum + fraction(fraction(fraction((userSupplied + (if (if (if ((afterChange != ""))
10271027 then (changeHandler[0] == assets[next])
10281028 else false)
10291029 then (changeHandler[1] == "supplied")
10301030 else false)
10311031 then parseIntValue(changeHandler[2])
10321032 else 0)), rates[(next * 3)].value, Scale16), parseIntValue(ltvs[next]), Scale8), assetPrice._1, assetScale)) - (if (minusBorrowed)
10331033 then fraction(fraction(fraction((userBorrowed + (if (if (if ((afterChange != ""))
10341034 then (changeHandler[0] == assets[next])
10351035 else false)
10361036 then (changeHandler[1] == "borrowed")
10371037 else false)
10381038 then parseIntValue(changeHandler[2])
10391039 else 0)), rates[((next * 3) + 1)].value, Scale16), Scale8, parseIntValue(lts[next])), assetPrice._2, assetScale)
10401040 else 0))
10411041 }
10421042 else accum
10431043 }
10441044
10451045 let result = {
10461046 let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
10471047 let $s = size($l)
10481048 let $acc0 = 0
10491049 func $f0_1 ($a,$i) = if (($i >= $s))
10501050 then $a
10511051 else f($a, $l[$i])
10521052
10531053 func $f0_2 ($a,$i) = if (($i >= $s))
10541054 then $a
10551055 else throw("List size exceeds 12")
10561056
10571057 $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)
10581058 }
10591059 if (debug)
10601060 then throw(toString(result))
10611061 else $Tuple2(rates, result)
10621062 }
10631063
10641064
10651065
10661066 @Callable(i)
10671067 func getPrices (debug) = {
10681068 let assets = getMarketAssets()
10691069 func f (accum,next) = if ((next >= size(assets)))
10701070 then accum
10711071 else {
10721072 let assetPrice = getTokenPriceWithRisk(assets[next], 3)
10731073 ((((accum + toString(assetPrice._1)) + ",") + toString(assetPrice._2)) + "|")
10741074 }
10751075
10761076 let result = {
10771077 let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
10781078 let $s = size($l)
10791079 let $acc0 = ""
10801080 func $f0_1 ($a,$i) = if (($i >= $s))
10811081 then $a
10821082 else f($a, $l[$i])
10831083
10841084 func $f0_2 ($a,$i) = if (($i >= $s))
10851085 then $a
10861086 else throw("List size exceeds 12")
10871087
10881088 $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)
10891089 }
10901090 if (debug)
10911091 then throw(result)
10921092 else $Tuple2(nil, result)
10931093 }
10941094
10951095
10961096
10971097 @Callable(i)
10981098 func calculateUtilizationRatio (assetIdStr,debug) = if (debug)
10991099 then throw(toString(getUr(assetIdStr)))
11001100 else $Tuple2(nil, getUr(assetIdStr))
11011101
11021102
11031103
11041104 @Callable(i)
11051105 func calculateOutdatedUR (assetIdStr,debug) = if (debug)
11061106 then throw(toString(getOutdatedUr(assetIdStr)))
11071107 else $Tuple2(nil, getOutdatedUr(assetIdStr))
11081108
11091109
11101110
11111111 @Callable(i)
11121112 func calculateTokenRates (debug) = {
11131113 func f (accum,assetIdStr) = {
11141114 let rates = tokenRatesRecalc(assetIdStr)
11151115 $Tuple2(((((accum._1 + toString(rates[1].value)) + "|") + toString(rates[0].value)) + ","), (accum._2 ++ rates))
11161116 }
11171117
11181118 let parameter = {
11191119 let $l = getMarketAssets()
11201120 let $s = size($l)
11211121 let $acc0 = $Tuple2("", nil)
11221122 func $f0_1 ($a,$i) = if (($i >= $s))
11231123 then $a
11241124 else f($a, $l[$i])
11251125
11261126 func $f0_2 ($a,$i) = if (($i >= $s))
11271127 then $a
11281128 else throw("List size exceeds 12")
11291129
11301130 $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)
11311131 }
11321132 if (debug)
11331133 then throw(parameter._1)
11341134 else $Tuple2(parameter._2, parameter._1)
11351135 }
11361136
11371137
11381138
11391139 @Callable(i)
11401140 func calculateTokensInterest (debug) = {
11411141 func f (accum,assetIdStr) = {
11421142 let rate = fraction(getInterest(assetIdStr), dayBlocks, Scale8)
11431143 ((accum + toString(rate)) + ",")
11441144 }
11451145
11461146 let parameter = {
11471147 let $l = getMarketAssets()
11481148 let $s = size($l)
11491149 let $acc0 = ""
11501150 func $f0_1 ($a,$i) = if (($i >= $s))
11511151 then $a
11521152 else f($a, $l[$i])
11531153
11541154 func $f0_2 ($a,$i) = if (($i >= $s))
11551155 then $a
11561156 else throw("List size exceeds 12")
11571157
11581158 $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)
11591159 }
11601160 if (debug)
11611161 then throw(parameter)
11621162 else $Tuple2(nil, parameter)
11631163 }
11641164
11651165
11661166
11671167 @Callable(i)
11681168 func setApproverAddress (approverAddress) = {
11691169 let isSelf = if ((i.caller == this))
11701170 then true
11711171 else throw("Only self invoke")
11721172 if ((isSelf == isSelf))
11731173 then {
11741174 let _approverAddress = addressFromString(approverAddress)
11751175 let approverOk = match _approverAddress {
11761176 case t: Address =>
11771177 true
11781178 case _ =>
11791179 false
11801180 }
11811181 let canSetApprover = if (if (approverOk)
11821182 then true
11831183 else (approverAddress == ""))
11841184 then true
11851185 else throw("Wrong approver address")
11861186 if ((canSetApprover == canSetApprover))
11871187 then {
11881188 let isInited = valueOrElse(getBoolean(value(_approverAddress), "INITED"), false)
11891189 let hasAdmins = (valueOrElse(getString(value(_approverAddress), "ADMINS_PBKS"), "") != "")
11901190 let isApproverContract = if (if ((approverAddress == ""))
11911191 then true
11921192 else if (isInited)
11931193 then hasAdmins
11941194 else false)
11951195 then true
11961196 else throw("Address is not approver contract")
11971197 if ((isApproverContract == isApproverContract))
11981198 then [StringEntry("APPROVER_ADDRESS", approverAddress)]
11991199 else throw("Strict value is not equal to itself.")
12001200 }
12011201 else throw("Strict value is not equal to itself.")
12021202 }
12031203 else throw("Strict value is not equal to itself.")
12041204 }
12051205
12061206
12071207
12081208 @Callable(i)
12091209 func initNewMaster (master) = {
12101210 let addressOK = match addressFromString(master) {
12111211 case a: Address =>
12121212 true
12131213 case _ =>
12141214 false
12151215 }
12161216 if (!(addressOK))
12171217 then throw(("incorrect address " + master))
12181218 else if ((i.caller != this))
12191219 then throw("available for self call only")
12201220 else [StringEntry("verifier_master", master)]
12211221 }
12221222
12231223
12241224
12251225 @Callable(i)
12261226 func requestNewMaster (newMaster) = {
12271227 let addressOK = match addressFromString(newMaster) {
12281228 case a: Address =>
12291229 true
12301230 case _ =>
12311231 false
12321232 }
12331233 if (!(addressOK))
12341234 then throw(("incorrect address " + newMaster))
12351235 else if ((indexOf(sentinels, i.caller) == unit))
12361236 then throw("whitelist only")
12371237 else [StringEntry("verifier_newMaster", newMaster), IntegerEntry("verifier_newMasterEligibleAfter", (height + 10000))]
12381238 }
12391239
12401240
12411241
12421242 @Callable(i)
12431243 func activateNewMaster () = {
12441244 let eligibleHeight = getIntegerValue(this, "verifier_newMasterEligibleAfter")
12451245 let newMaster = getStringValue(this, "verifier_newMaster")
12461246 if ((indexOf(sentinels, i.caller) == unit))
12471247 then throw("whitelist only")
12481248 else if ((eligibleHeight > height))
12491249 then throw("new master cannot be activated yet")
12501250 else [DeleteEntry("verifier_newMaster"), DeleteEntry("verifier_newMasterEligibleAfter"), StringEntry("verifier_master", newMaster)]
12511251 }
12521252
12531253
12541254 @Verifier(tx)
12551255 func verify () = {
12561256 let multisigStr = valueOrElse(getString("APPROVER_ADDRESS"), "")
12571257 let multisigAddress = addressFromString(multisigStr)
12581258 let multisigOk = match multisigAddress {
12591259 case t: Address =>
12601260 true
12611261 case _ =>
12621262 false
12631263 }
12641264 let isInited = if (multisigOk)
12651265 then valueOrElse(getBoolean(value(multisigAddress), "INITED"), false)
12661266 else false
12671267 let hasAdmins = if (multisigOk)
12681268 then (valueOrElse(getString(value(multisigAddress), "ADMINS_PBKS"), "") != "")
12691269 else false
12701270 if (if (if (multisigOk)
12711271 then isInited
12721272 else false)
12731273 then hasAdmins
12741274 else false)
12751275 then match tx {
12761276 case ttx: SetScriptTransaction =>
12771277 match ttx.script {
12781278 case script: ByteVector =>
12791279 let scriptHasha = toBase58String(blake2b256(script))
12801280 let validFrom = valueOrErrorMessage(getInteger(value(multisigAddress), (((("script%%" + CONTRACT_TYPE) + "%%") + scriptHasha) + "%%validFrom")), "validFrom not set")
12811281 let validTo = valueOrErrorMessage(getInteger(value(multisigAddress), (((("script%%" + CONTRACT_TYPE) + "%%") + scriptHasha) + "%%validTo")), "validTo not set")
12821282 if ((height >= validFrom))
12831283 then (validTo >= height)
12841284 else false
12851285 case _ =>
12861286 false
12871287 }
12881288 case otx =>
12891289 let taskId = ((("tx_" + toString(this)) + "_") + toBase58String(otx.id))
12901290 let isApproved = valueOrElse(getBoolean(value(multisigAddress), (((toString(this) + "_") + toBase58String(otx.id)) + "__approved")), false)
12911291 let approvedFrom = valueOrElse(getInteger(value(multisigAddress), (taskId + "__approvedFrom")), 0)
12921292 if (isApproved)
12931293 then (height >= approvedFrom)
12941294 else false
12951295 }
12961296 else {
12971297 let masterAddress = getString("verifier_master")
12981298 let approvedByMaster = match masterAddress {
12991299 case x: String =>
13001300 match getInteger(addressFromStringValue(x), ("approvedTx_" + toBase58String(tx.id))) {
13011301 case y: Int =>
13021302 y
13031303 case _ =>
13041304 0
13051305 }
13061306 case _ =>
13071307 1
13081308 }
13091309 if (sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey))
13101310 then (approvedByMaster > 0)
13111311 else false
13121312 }
13131313 }
13141314

github/deemru/w8io
347.14 ms