tx · 9UmTQPhZdqdw33XaFC2zqjPh6WbvU8Sc2nEANFGJtfSk

3MNrEDcv4w3K7JJZArPtMquCGe9yHqoRmf3:  -0.05500000 Waves

2025.09.23 03:00 [312567] smart account 3MNrEDcv4w3K7JJZArPtMquCGe9yHqoRmf3 > SELF 0.00000000 Waves

{ "type": 13, "id": "9UmTQPhZdqdw33XaFC2zqjPh6WbvU8Sc2nEANFGJtfSk", "fee": 5500000, "feeAssetId": null, "timestamp": 1758585634513, "version": 2, "chainId": 82, "sender": "3MNrEDcv4w3K7JJZArPtMquCGe9yHqoRmf3", "senderPublicKey": "76ayfRPpNddmJULUzgeLkksDokcpP9NqyhEfTLptt3fQ", "proofs": [ "4U64Yjkezk5DSNuV9espPKC3M67EaLyEdZXX3Xt9UGF3qjCmTrSg5q6qKsXnK5EBQTH97vnjQt4Cq8cARtbcA836" ], "script": "base64:BgJcCAISBAoCCAgSCQoHCAgICAgIARIAEgkKBwgICAgIAQgSAwoBBBIDCgEBEgASAwoBCBIDCgEBEgASAwoBCBIAEgQKAggBEgQKAggBEgUKAwgIARIDCgEIEgMKAQFkAAdWRVJTSU9OAhdQWi0zLjYuMTAgUFJPRC1yZWZhY3RvcgAJY29uZmlnU3RyCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMCDWNvbmZpZ0FkZHJlc3MCIzNQTW9FaWJkTGVXcWNVUlE4MzUxWGhhV3d5YWNEYzdHNGU1AA5DT05GSUdfQUREUkVTUwMJAAACBQljb25maWdTdHICAAUEdGhpcwkBB0FkZHJlc3MBCQDZBAEFCWNvbmZpZ1N0cgAVQXNzZXRzV2VpZ2h0c0RlY2ltYWxzAAQABVNjYWxlAJBOAAZTY2FsZTgAgMLXLwAHU2NhbGUxMgCAoJSljR0AB1NjYWxlMTYAgICE/qbe4REACEZlZVNjYWxlAJBOABFQb29sVG9rZW5EZWNpbWFscwAIAA5Qb29sVG9rZW5TY2FsZQkAbAYACgAABRFQb29sVG9rZW5EZWNpbWFscwAAAAAFBkhBTEZVUAAQTUlOX1NURVBTX0FNT1VOVAkBC3ZhbHVlT3JFbHNlAgkAmggCBQ5DT05GSUdfQUREUkVTUwIQbWluX3N0ZXBzX2Ftb3VudAABABBNQVhfU1RFUFNfQU1PVU5UCQELdmFsdWVPckVsc2UCCQCaCAIFDkNPTkZJR19BRERSRVNTAhBtYXhfc3RlcHNfYW1vdW50APQDABJNSU5fU1RFUFNfSU5URVJWQUwJAQt2YWx1ZU9yRWxzZQIJAJoIAgUOQ09ORklHX0FERFJFU1MCEm1pbl9zdGVwc19pbnRlcnZhbAABABJNQVhfU1RFUFNfSU5URVJWQUwJAQt2YWx1ZU9yRWxzZQIJAJoIAgUOQ09ORklHX0FERFJFU1MCEm1heF9zdGVwc19pbnRlcnZhbACQTgAKTUlOX1dFSUdIVAkBC3ZhbHVlT3JFbHNlAgkAmggCBQ5DT05GSUdfQUREUkVTUwIKbWluX3dlaWdodABkAApNQVhfV0VJR0hUCQELdmFsdWVPckVsc2UCCQCaCAIFDkNPTkZJR19BRERSRVNTAgptYXhfd2VpZ2h0AKxNAQ10cnlHZXRJbnRlZ2VyAQNrZXkEByRtYXRjaDAJAJoIAgUEdGhpcwUDa2V5AwkAAQIFByRtYXRjaDACA0ludAQBYgUHJG1hdGNoMAUBYgAAAQx0cnlHZXRCaW5hcnkBA2tleQQHJG1hdGNoMAkAnAgCBQR0aGlzBQNrZXkDCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQBYgUHJG1hdGNoMAUBYgEAAQx0cnlHZXRTdHJpbmcBA2tleQQHJG1hdGNoMAkAnQgCBQR0aGlzBQNrZXkDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFiBQckbWF0Y2gwBQFiAgABE3RyeUdldFN0cmluZ09yVGhyb3cBA2tleQQHJG1hdGNoMAkAnQgCBQR0aGlzBQNrZXkDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFiBQckbWF0Y2gwBQFiCQACAQkArAICAh1ubyBzdWNoIGtleSBpbiBkYXRhIHN0b3JhZ2U6IAUDa2V5AQ5nZXRBc3NldFN0cmluZwEHYXNzZXRJZAQHJG1hdGNoMAUHYXNzZXRJZAMJAAECBQckbWF0Y2gwAgpCeXRlVmVjdG9yBAFiBQckbWF0Y2gwCQDYBAEFAWICBVdBVkVTAQ1nZXRBc3NldEJ5dGVzAQphc3NldElkU3RyAwkAAAIFCmFzc2V0SWRTdHICBVdBVkVTBQR1bml0CQDZBAEFCmFzc2V0SWRTdHIBD2dldFRva2VuQmFsYW5jZQEHYXNzZXRJZAQHJG1hdGNoMAUHYXNzZXRJZAMJAAECBQckbWF0Y2gwAgpCeXRlVmVjdG9yBAF0BQckbWF0Y2gwCQDwBwIFBHRoaXMFAXQICQDvBwEFBHRoaXMJYXZhaWxhYmxlARNhZGRBc3NldEJ5dGVzVG9MaXN0AgVhY2N1bQRpdGVtCQDOCAIFBWFjY3VtCQDMCAIJAQ1nZXRBc3NldEJ5dGVzAQUEaXRlbQUDbmlsARRhZGRBc3NldFdlaWdodFRvTGlzdAIFYWNjdW0EaXRlbQkAzggCBQVhY2N1bQkAzAgCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdzdGF0aWNfCQEOZ2V0QXNzZXRTdHJpbmcBBQRpdGVtAgdfd2VpZ2h0BQNuaWwBF2FkZEFzc2V0V2VpZ2h0VG9TdHJMaXN0AgVhY2N1bQRpdGVtCQDOCAIFBWFjY3VtCQDMCAIJAKQDAQkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHc3RhdGljXwUEaXRlbQIHX3dlaWdodAUDbmlsARZhZGRBc3NldERlY2ltYWxzVG9MaXN0AgVhY2N1bQRpdGVtCQDOCAIFBWFjY3VtCQDMCAIJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB3N0YXRpY18JAQ5nZXRBc3NldFN0cmluZwEFBGl0ZW0CCV9kZWNpbWFscwUDbmlsARNhZGRBc3NldFNjYWxlVG9MaXN0AgVhY2N1bQRpdGVtCQDOCAIFBWFjY3VtCQDMCAIJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB3N0YXRpY18JAQ5nZXRBc3NldFN0cmluZwEFBGl0ZW0CBl9zY2FsZQUDbmlsAQxhZGRJbnRUb0xpc3QCBWFjY3VtBGl0ZW0JAM4IAgUFYWNjdW0JAMwIAgkBDXBhcnNlSW50VmFsdWUBBQRpdGVtBQNuaWwBEXBhcnN0U3RyVG9JbnRMaXN0AQFzCgEBZgIFYWNjdW0EbmV4dAkAzggCBQVhY2N1bQkAzAgCCQENcGFyc2VJbnRWYWx1ZQEFBG5leHQFA25pbAoAAiRsCQC1CQIFAXMCASwKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBAWYCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoADnVzZG5Bc3NldElkU3RyCQELdmFsdWVPckVsc2UCCQCdCAIFDkNPTkZJR19BRERSRVNTAg51c2RuQXNzZXRJZFN0cgIsREcyeEZrUGREd0tVb0JrekdBaFF0THBTR3pmWExpQ1lQRXplS0gyQWQyNHAAEHB1enpsZUFzc2V0SWRTdHIJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUOQ09ORklHX0FERFJFU1MCEHB1enpsZUFzc2V0SWRTdHICLEhFQjhRYXc5eHJXcFdzOHRIc2lBVFlHQldEQnRQMlM3a2NQQUxyTXU0M0FTAA51c2R0QXNzZXRJZFN0cgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ5DT05GSUdfQUREUkVTUwIOdXNkdEFzc2V0SWRTdHICLDM0TjlZY0VFVExXbjkzcVlRNjRFc1AxeDg5dFNydUpVNDRSckVNU1hYRVBKABF1c2R0UHB0QXNzZXRJZFN0cgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ5DT05GSUdfQUREUkVTUwIRdXNkdFBwdEFzc2V0SWRTdHICLDl3YzNMWE5BNFRFQnNYeUt0b0xFOW1yYkREN1dNSFh2WHJDalp2YWJMQXNpAA5yb21lQXNzZXRJZFN0cgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ5DT05GSUdfQUREUkVTUwIOcm9tZUFzc2V0SWRTdHICLEFQNENiNXhMWUdINlppZ0hyZUNaSG9YcFFUV0RrUHNHMkJIcWZEVXg2dGFKAA93YXZlc0Fzc2V0SWRTdHICBVdBVkVTAAt1c2RuQXNzZXRJZAkA2QQBBQ51c2RuQXNzZXRJZFN0cgANcHV6emxlQXNzZXRJZAkA2QQBBRBwdXp6bGVBc3NldElkU3RyAAt1c2R0QXNzZXRJZAkA2QQBBQ51c2R0QXNzZXRJZFN0cgAOdXNkdFBwdEFzc2V0SWQJANkEAQURdXNkdFBwdEFzc2V0SWRTdHIAC3JvbWVBc3NldElkCQDZBAEFDnJvbWVBc3NldElkU3RyAAx3YXZlc0Fzc2V0SWQFBHVuaXQAFXN1cHBvcnRlZEZlZUFzc2V0c1N0cgkAzAgCBQ51c2RuQXNzZXRJZFN0cgkAzAgCBRBwdXp6bGVBc3NldElkU3RyCQDMCAIFDnVzZHRBc3NldElkU3RyCQDMCAIFEXVzZHRQcHRBc3NldElkU3RyCQDMCAIFD3dhdmVzQXNzZXRJZFN0cgkAzAgCBQ5yb21lQXNzZXRJZFN0cgUDbmlsABFwYXJlbnRQb29sQWRkcmVzcwkBB0FkZHJlc3MBCQDZBAEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUOQ09ORklHX0FERFJFU1MCEXBhcmVudFBvb2xBZGRyZXNzAiMzUEZEZ3p1MVV0c3dBa0NNeHFxUWpiVGVIYVg0Y01hYjhLaAANbWFzdGVyQWRkcmVzcwkBB0FkZHJlc3MBCQDZBAEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUOQ09ORklHX0FERFJFU1MCDW1hc3RlckFkZHJlc3MCIzNQTGp3SGN6OU5FdWFUbzYzTlpSOUI5b2tRaUtReFpTYm1mAAxtYXN0ZXJQdWJLZXkJANkEAQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ5DT05GSUdfQUREUkVTUwIMbWFzdGVyUHViS2V5AiwyalRKR3FIU29weWo1ZDFjamJVZTZmMmpYcUdNSEU0MTJjeTN2R3dZb1JiUAANb3JhY2xlQWRkcmVzcwkBB0FkZHJlc3MBCQDZBAEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUOQ09ORklHX0FERFJFU1MCDW9yYWNsZUFkZHJlc3MCIzNQOGQxRTFCTEtvRDUyeTNiUUoxYkRUZDJURDFncGFMbjl0AA5zdGFraW5nQWRkcmVzcwkBB0FkZHJlc3MBCQDZBAEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUOQ09ORklHX0FERFJFU1MCDnN0YWtpbmdBZGRyZXNzAiMzUEZUYnl3cXh0RmZ1a1gzSHlUODgxZzRpVzVLNFFMM0ZBUwALZmVlc0FkZHJlc3MJAQdBZGRyZXNzAQkA2QQBCQELdmFsdWVPckVsc2UCCQCdCAIFDkNPTkZJR19BRERSRVNTAgtmZWVzQWRkcmVzcwIjM1BGV0FWS21YamZIWHl6SmIxMmpDYmhQNFVoaTl0NHVXaUQAD3Bvb2xzSHViQWRkcmVzcwkBB0FkZHJlc3MBCQDZBAEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUOQ09ORklHX0FERFJFU1MCD3Bvb2xzSHViQWRkcmVzcwIjM1A1UkdZeUNuRUxGOEpUUHhnWDU0ZEJHendrUU1LVUo1SDcAEnNodXRkb3duQWRkcmVzc1N0cgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ5DT05GSUdfQUREUkVTUwIPc2h1dGRvd25BZGRyZXNzAiMzUEVwdjloUkZXRUVCVTIyV1JuTHN3MWJINFlHdGNVNzI4bwAPbGF5ZXIyQWRkcmVzc2VzCQELdmFsdWVPckVsc2UCCQCdCAIFDkNPTkZJR19BRERSRVNTAg9sYXllcjJBZGRyZXNzZXMCRzNQUjFRdmk5bUhUMzVTd1dFa0xTcXFFMkw4dGhpUExkVldVLDNQUW9CZlVLSGtKQWVHV2hvb0xQN1dTOG92YjU0YXY5SnAyAApnb3ZBZGRyZXNzCQEHQWRkcmVzcwEJANkEAQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ5DT05GSUdfQUREUkVTUwIKZ292QWRkcmVzcwIjM1A2dXJvOXhDc0U4dGU3OFFaanpxeTdhcThuYXRTemRjZUMAEWNvbGRNYXN0ZXJBZGRyZXNzCQEHQWRkcmVzcwEJANkEAQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ5DT05GSUdfQUREUkVTUwIRY29sZE1hc3RlckFkZHJlc3MCIzNQSzluaFBmUGJNQnlnQjlaZ0hWTUhhUWJTb29qd3JCZnhqAAFUCQENdHJ5R2V0SW50ZWdlcgECE3N0YXRpY190b2tlbnNBbW91bnQACGFzc2V0SWRzCgACJGwJALUJAgkBDHRyeUdldFN0cmluZwECD3N0YXRpY190b2tlbklkcwIBLAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQETYWRkQXNzZXRCeXRlc1RvTGlzdAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgANQXNzZXRzV2VpZ2h0cwoAAiRsBQhhc3NldElkcwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMV8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEUYWRkQXNzZXRXZWlnaHRUb0xpc3QCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjFfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYxXzICCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACERlY2ltYWxzCgACJGwFCGFzc2V0SWRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYyXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARZhZGRBc3NldERlY2ltYWxzVG9MaXN0AgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYyXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmMl8yAgkBBSRmMl8xAgkBBSRmMl8xAgkBBSRmMl8xAgkBBSRmMl8xAgkBBSRmMl8xAgkBBSRmMl8xAgkBBSRmMl8xAgkBBSRmMl8xAgkBBSRmMl8xAgkBBSRmMl8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAZTY2FsZXMKAAIkbAUIYXNzZXRJZHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjNfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBE2FkZEFzc2V0U2NhbGVUb0xpc3QCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjNfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYzXzICCQEFJGYzXzECCQEFJGYzXzECCQEFJGYzXzECCQEFJGYzXzECCQEFJGYzXzECCQEFJGYzXzECCQEFJGYzXzECCQEFJGYzXzECCQEFJGYzXzECCQEFJGYzXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoAA0ZlZQkBDXRyeUdldEludGVnZXIBAgpzdGF0aWNfZmVlAAxlYXJuZWRBc3NldHMFCGFzc2V0SWRzAQRfZ2V0Agdhc3NldElkBXBhcmFtCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICCQCsAgICB2dsb2JhbF8FB2Fzc2V0SWQCAV8FBXBhcmFtAQ9fZ2V0X2ZlZXNFYXJuZWQBB2Fzc2V0SWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICAhJnbG9iYWxfZmVlc0Vhcm5lZF8FB2Fzc2V0SWQBF19nZXRfbGFzdENoZWNrX2ludGVyZXN0AQdhc3NldElkCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAhFnbG9iYWxfbGFzdENoZWNrXwUHYXNzZXRJZAIJX2ludGVyZXN0ARBfZ2V0X2V4dHJhRWFybmVkAQdhc3NldElkCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgITZ2xvYmFsX2V4dHJhRWFybmVkXwUHYXNzZXRJZAEVbG9hZEdsb2JhbFRva2VuUGFyYW1zAQdhc3NldElkBAckbWF0Y2gwCQCiCAEJAKwCAgINZ2xvYmFsUGFyYW1zXwUHYXNzZXRJZAMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAXAFByRtYXRjaDAEBnBhcmFtcwkAtQkCBQFwAgJfXwkAmgoICQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUGcGFyYW1zAAAJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQZwYXJhbXMAAQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBnBhcmFtcwACCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUGcGFyYW1zAAMJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQZwYXJhbXMABAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBnBhcmFtcwAFCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUGcGFyYW1zAAYJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQZwYXJhbXMABwkAmgoICQEEX2dldAIFB2Fzc2V0SWQCB2JhbGFuY2UJAQRfZ2V0AgUHYXNzZXRJZAILZmFjdEJhbGFuY2UJAQ9fZ2V0X2ZlZXNFYXJuZWQBBQdhc3NldElkCQEXX2dldF9sYXN0Q2hlY2tfaW50ZXJlc3QBBQdhc3NldElkCQEQX2dldF9leHRyYUVhcm5lZAEFB2Fzc2V0SWQJAQRfZ2V0AgUHYXNzZXRJZAIHc2VsbG9mZgkBBF9nZXQCBQdhc3NldElkAhNzZWxsb2ZmU3RhcnRCYWxhbmNlCQEEX2dldAIFB2Fzc2V0SWQCEnNlbGxvZmZTdGFydEhlaWdodAEVc2F2ZUdsb2JhbFRva2VuUGFyYW1zAgdhc3NldElkBnBhcmFtcwkBC1N0cmluZ0VudHJ5AgkArAICAg1nbG9iYWxQYXJhbXNfBQdhc3NldElkCQC5CQIJAMwIAgkApAMBCAUGcGFyYW1zAl8xCQDMCAIJAKQDAQgFBnBhcmFtcwJfMgkAzAgCCQCkAwEIBQZwYXJhbXMCXzMJAMwIAgkApAMBCAUGcGFyYW1zAl80CQDMCAIJAKQDAQgFBnBhcmFtcwJfNQkAzAgCCQCkAwEIBQZwYXJhbXMCXzYJAMwIAgkApAMBCAUGcGFyYW1zAl83CQDMCAIJAKQDAQgFBnBhcmFtcwJfOAUDbmlsAgJfXwEKaXNTaHV0ZG93bgAED3NodXRkb3duQWRkcmVzcwkApggBBRJzaHV0ZG93bkFkZHJlc3NTdHIDCQAAAgUPc2h1dGRvd25BZGRyZXNzBQR1bml0BwQHJG1hdGNoMAkAmwgCCQEFdmFsdWUBBQ9zaHV0ZG93bkFkZHJlc3MCC2lzX3NodXRkb3duAwkAAQIFByRtYXRjaDACB0Jvb2xlYW4EAXgFByRtYXRjaDAFAXgHAQ5nZXRGYWN0QmFsYW5jZQEKYXNzZXRJZFN0cgQLYXNzZXRQYXJhbXMJARVsb2FkR2xvYmFsVG9rZW5QYXJhbXMBBQphc3NldElkU3RyCAULYXNzZXRQYXJhbXMCXzIBFmdldEN1cnJlbnRUb2tlbkJhbGFuY2UBCHRva2VuTnVtBAp0b2tlbklkU3RyCQEOZ2V0QXNzZXRTdHJpbmcBCQCRAwIFCGFzc2V0SWRzBQh0b2tlbk51bQQLdG9rZW5QYXJhbXMJARVsb2FkR2xvYmFsVG9rZW5QYXJhbXMBBQp0b2tlbklkU3RyCAULdG9rZW5QYXJhbXMCXzEBDXN0YWtlSWZOZWVkZWQCCmFzc2V0SWRTdHIGYW1vdW50BAdzdGFrZVR4AwkBAiE9AgkBDHRyeUdldFN0cmluZwEJAKwCAgIXc3RhdGljX3N0YWtpbmdDb250cmFjdF8FCmFzc2V0SWRTdHICAAkA/AcECQERQGV4dHJOYXRpdmUoMTA2MikBCQEMdHJ5R2V0U3RyaW5nAQkArAICAhdzdGF0aWNfc3Rha2luZ0NvbnRyYWN0XwUKYXNzZXRJZFN0cgIFc3Rha2UFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBDWdldEFzc2V0Qnl0ZXMBBQphc3NldElkU3RyBQZhbW91bnQFA25pbAUEdW5pdAMJAAACBQdzdGFrZVR4BQdzdGFrZVR4BgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgEPdW5zdGFrZUlmTmVlZGVkAgphc3NldElkU3RyBmFtb3VudAQJdW5zdGFrZVR4AwkBAiE9AgkBDHRyeUdldFN0cmluZwEJAKwCAgIXc3RhdGljX3N0YWtpbmdDb250cmFjdF8FCmFzc2V0SWRTdHICAAkA/AcECQERQGV4dHJOYXRpdmUoMTA2MikBCQEMdHJ5R2V0U3RyaW5nAQkArAICAhdzdGF0aWNfc3Rha2luZ0NvbnRyYWN0XwUKYXNzZXRJZFN0cgIHdW5zdGFrZQkAzAgCBQZhbW91bnQFA25pbAUDbmlsBQR1bml0AwkAAAIFCXVuc3Rha2VUeAUJdW5zdGFrZVR4BgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgERYnVybkluZGV4SWZOZWVkZWQBBmFtb3VudAQKaW5kZXhJZFN0cgkBDHRyeUdldFN0cmluZwECFnN0YXRpY19wb29sVG9rZW5faWRTdHIDCQAAAgUKaW5kZXhJZFN0cgIABQNuaWwDCQAAAgkA7AcBCQDZBAEFCmluZGV4SWRTdHIFBHVuaXQFA25pbAkAzAgCCQEEQnVybgIJANkEAQUKaW5kZXhJZFN0cgUGYW1vdW50BQNuaWwBEW1pbnRJbmRleElmTmVlZGVkAQZhbW91bnQECmluZGV4SWRTdHIJAQx0cnlHZXRTdHJpbmcBAhZzdGF0aWNfcG9vbFRva2VuX2lkU3RyAwkAAAIFCmluZGV4SWRTdHICAAUDbmlsAwkAAAIJAOwHAQkA2QQBBQppbmRleElkU3RyBQR1bml0BQNuaWwJAMwIAgkBB1JlaXNzdWUDCQDZBAEFCmluZGV4SWRTdHIFBmFtb3VudAYFA25pbAEIZ2V0S011bHQABAckbWF0Y2gwCQCfCAECDHN0YXRpY19LTXVsdAMJAAECBQckbWF0Y2gwAgNJbnQEAXgFByRtYXRjaDAFAXgFB1NjYWxlMTYBEnNhdmVDdXJyZW50V2VpZ2h0cwAECmFzc2V0SWRzTGkJALUJAgkBDHRyeUdldFN0cmluZwECD3N0YXRpY190b2tlbklkcwIBLAoBAXMCBWFjY3VtB2Fzc2V0SWQJAM4IAgUFYWNjdW0JAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgIWcmViYWxhbmNlX3N0YXJ0V2VpZ2h0XwUHYXNzZXRJZAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHc3RhdGljXwUHYXNzZXRJZAIHX3dlaWdodAUDbmlsCgACJGwFCmFzc2V0SWRzTGkKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjRfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBAXMCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjRfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY0XzICCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoBGWdldFZpcnR1YWxQb29sVG9rZW5BbW91bnQACQBrAwkBDXRyeUdldEludGVnZXIBAhdnbG9iYWxfcG9vbFRva2VuX2Ftb3VudAkBCGdldEtNdWx0AAUHU2NhbGUxNgEQY2FsY3VsYXRlUElzc3VlZAIGYW1vdW50B3Rva2VuSWQEB1BzdXBwbHkJARlnZXRWaXJ0dWFsUG9vbFRva2VuQW1vdW50AAQHQmFsYW5jZQkBDmdldEZhY3RCYWxhbmNlAQkBDmdldEFzc2V0U3RyaW5nAQUHdG9rZW5JZAQCdDEJAG4EBQZhbW91bnQFB1BzdXBwbHkFB0JhbGFuY2UFBERPV04FAnQxAQ1nZXRNaW5QSXNzdWVkAQhwYXltZW50cwoBB2hhbmRsZXICBWFjY3VtB2N1cnJlbnQDCQAAAgkBDmdldEZhY3RCYWxhbmNlAQkBDmdldEFzc2V0U3RyaW5nAQgFB2N1cnJlbnQHYXNzZXRJZAAABQVhY2N1bQQHUElzc3VlZAkBEGNhbGN1bGF0ZVBJc3N1ZWQCCAUHY3VycmVudAZhbW91bnQIBQdjdXJyZW50B2Fzc2V0SWQDCQAAAgUHUElzc3VlZAAACQACAQIkb25lIG9mIHRoZSB0b2tlbnMgYW1vdW50cyBpcyB0b28gbG93AwMJAAACBQVhY2N1bQAABgkAZgIFBWFjY3VtBQdQSXNzdWVkBQdQSXNzdWVkBQVhY2N1bQQJbWluUElzc2VkCgACJGwFCHBheW1lbnRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAAACgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQdoYW5kbGVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY0XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNF8yAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKBQltaW5QSXNzZWQBEmdldFByaWNlRnJvbU9yYWNsZQEKYXNzZXRJZFN0cgQHJG1hdGNoMAkAmggCBQ1vcmFjbGVBZGRyZXNzCQCsAgIFCmFzc2V0SWRTdHICB190d2FwNUIDCQABAgUHJG1hdGNoMAIDSW50BAF4BQckbWF0Y2gwBQF4AAABEWNhbGN1bGF0ZVVzZFZhbHVlBAdhc3NldElkBmFtb3VudAhhQmFsYW5jZQ9mZWVBc3NldEJhbGFuY2UEC2Fzc2V0V2VpZ2h0CQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdzdGF0aWNfCQEOZ2V0QXNzZXRTdHJpbmcBBQdhc3NldElkAgdfd2VpZ2h0BAtmZWVBc3NldFN0cgkBDHRyeUdldFN0cmluZwECD3N0YXRpY19mZWVUb2tlbgQNZmVlQXNzZXRTY2FsZQkBEUBleHRyTmF0aXZlKDEwNTApAgUEdGhpcwkArAICCQCsAgICB3N0YXRpY18FC2ZlZUFzc2V0U3RyAgZfc2NhbGUEC2ZlZUFzc2V0TnVtCQEFdmFsdWUBCQDPCAIFCGFzc2V0SWRzCQENZ2V0QXNzZXRCeXRlcwEFC2ZlZUFzc2V0U3RyBA5mZWVBc3NldFdlaWdodAkAkQMCBQ1Bc3NldHNXZWlnaHRzBQtmZWVBc3NldE51bQQNdmFsSW5GZWVBc3NldAkAawMFBmFtb3VudAkAaQIFD2ZlZUFzc2V0QmFsYW5jZQUOZmVlQXNzZXRXZWlnaHQJAGkCBQhhQmFsYW5jZQULYXNzZXRXZWlnaHQEDWZlZUFzc2V0UHJpY2UJARJnZXRQcmljZUZyb21PcmFjbGUBBQtmZWVBc3NldFN0cgkAawMFDXZhbEluRmVlQXNzZXQFDWZlZUFzc2V0UHJpY2UFDWZlZUFzc2V0U2NhbGUBFGNhbGNBdmdDb25jZW50cmF0aW9uAAoBAWYCBWFjY3VtBG5leHQECmFzc2V0SWRTdHIJAQ5nZXRBc3NldFN0cmluZwEFBG5leHQEBndlaWdodAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHc3RhdGljXwUKYXNzZXRJZFN0cgIHX3dlaWdodAQLYXNzZXRQYXJhbXMJARVsb2FkR2xvYmFsVG9rZW5QYXJhbXMBBQphc3NldElkU3RyBBBhc3NldEZhY3RCYWxhbmNlCAULYXNzZXRQYXJhbXMCXzIEEGFzc2V0VmlydEJhbGFuY2UIBQthc3NldFBhcmFtcwJfMQkAlAoCCQBkAggFBWFjY3VtAl8xCQBrAwUQYXNzZXRGYWN0QmFsYW5jZQUGd2VpZ2h0BRBhc3NldFZpcnRCYWxhbmNlCQBkAggFBWFjY3VtAl8yBQZ3ZWlnaHQKAAIkbAUIYXNzZXRJZHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCUCgIAAAAACgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQFmAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY0XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNF8yAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKARNjaGVja1Rva2Vuc1ZhbGlkaXR5AQhwYXltZW50cwoBCGhhbmRsZXIxAgVhY2N1bQdwYXltZW50CQDOCAIFBWFjY3VtCQDMCAIIBQdwYXltZW50B2Fzc2V0SWQFA25pbAQDaWRzCgACJGwFCHBheW1lbnRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQhoYW5kbGVyMQIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjRfMgIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgMJAAACBQNpZHMFA2lkcwoBCGhhbmRsZXIyAgVhY2N1bQdhc3NldElkAwkBAiE9AgkAzwgCBQNpZHMFB2Fzc2V0SWQFBHVuaXQJAGQCBQVhY2N1bQABCQACAQkArAICAhRhc3NldCBub3QgYXR0YWNoZWQ6IAkBDmdldEFzc2V0U3RyaW5nAQUHYXNzZXRJZAQGY2hlY2tzCgACJGwFCGFzc2V0SWRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAAACgEFJGY1XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQhoYW5kbGVyMgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNV8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjVfMgIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgMJAAACBQZjaGVja3MFBmNoZWNrcwYJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BE2hhbmRsZVBvb2xUb2tlbnNBZGQEB1BJc3N1ZWQIcGF5bWVudHMLdXNlckFkZHJlc3MKbmVlZENoYW5nZQoBFWdldFRva2VuUGF5bWVudEFtb3VudAEHdG9rZW5JZAoBB2hhbmRsZXICBWFjY3VtB3BheW1lbnQDCQAAAggFB3BheW1lbnQHYXNzZXRJZAUHdG9rZW5JZAgFB3BheW1lbnQGYW1vdW50BQVhY2N1bQoAAiRsBQhwYXltZW50cwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAAAAoBBSRmNF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEHaGFuZGxlcgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjRfMgIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgoBEWhhbmRsZVRva2VuQ2hhbmdlAgVhY2N1bQd0b2tlbklkBAphc3NldElkU3RyCQEOZ2V0QXNzZXRTdHJpbmcBBQd0b2tlbklkBAthc3NldFBhcmFtcwkBFWxvYWRHbG9iYWxUb2tlblBhcmFtcwEFCmFzc2V0SWRTdHIEDXBheW1lbnRBbW91bnQJARVnZXRUb2tlblBheW1lbnRBbW91bnQBBQd0b2tlbklkBAJCawgFC2Fzc2V0UGFyYW1zAl8yBAdQU3VwcGx5CQEZZ2V0VmlydHVhbFBvb2xUb2tlbkFtb3VudAAEDXRva2VuRGVjaW1hbHMJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB3N0YXRpY18FCmFzc2V0SWRTdHICBl9zY2FsZQQCYTEJAL0CBAkAuQICCQC2AgEJAGQCBQdQU3VwcGx5BQdQSXNzdWVkCQC2AgEFBlNjYWxlOAkAtgIBBQ10b2tlbkRlY2ltYWxzCQC2AgEFB1BTdXBwbHkFB0NFSUxJTkcEAkRrCQCgAwEJAL0CBAkAuAICBQJhMQkAuQICCQC2AgEFDXRva2VuRGVjaW1hbHMJALYCAQUGU2NhbGU4CQC2AgEFAkJrCQC5AgIJALYCAQUNdG9rZW5EZWNpbWFscwkAtgIBBQZTY2FsZTgFB0NFSUxJTkcECHRvUmV0dXJuCQBlAgUNcGF5bWVudEFtb3VudAUCRGsEB3N0YWtlVHgJAQ1zdGFrZUlmTmVlZGVkAgUKYXNzZXRJZFN0cgUCRGsDCQAAAgUHc3Rha2VUeAUHc3Rha2VUeAQBdAMDBQpuZWVkQ2hhbmdlCQBmAgUIdG9SZXR1cm4AAAcJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwULdXNlckFkZHJlc3MFCHRvUmV0dXJuBQd0b2tlbklkBQNuaWwFA25pbAQTc2VsbG9mZlN0YXJ0QmFsYW5jZQMJAQIhPQIIBQthc3NldFBhcmFtcwJfOAkAaAIJAGkCBQZoZWlnaHQAZABkCAULYXNzZXRQYXJhbXMCXzcJAGsDCAULYXNzZXRQYXJhbXMCXzcJAGQCBQdQU3VwcGx5BQdQSXNzdWVkBQdQU3VwcGx5BA5hc3NldFBhcmFtc1VwZAkAmgoICQBrAwgFC2Fzc2V0UGFyYW1zAl8xCQBkAgUHUFN1cHBseQUHUElzc3VlZAUHUFN1cHBseQkAZAIIBQthc3NldFBhcmFtcwJfMgUCRGsIBQthc3NldFBhcmFtcwJfMwgFC2Fzc2V0UGFyYW1zAl80CAULYXNzZXRQYXJhbXMCXzUIBQthc3NldFBhcmFtcwJfNgUTc2VsbG9mZlN0YXJ0QmFsYW5jZQgFC2Fzc2V0UGFyYW1zAl84CQDOCAIJAM4IAgUFYWNjdW0FAXQJAMwIAgkBFXNhdmVHbG9iYWxUb2tlblBhcmFtcwIFCmFzc2V0SWRTdHIFDmFzc2V0UGFyYW1zVXBkBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4KAAIkbAUIYXNzZXRJZHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjRfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBEWhhbmRsZVRva2VuQ2hhbmdlAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY0XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNF8yAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKARZjYWxjTWludGVkV2l0aE9uZVRva2VuAg9hc3NldEFkZGVkSWRTdHIGYW1vdW50BAdQU3VwcGx5CQEZZ2V0VmlydHVhbFBvb2xUb2tlbkFtb3VudAAEC2Fzc2V0UGFyYW1zCQEVbG9hZEdsb2JhbFRva2VuUGFyYW1zAQUPYXNzZXRBZGRlZElkU3RyBBBhc3NldEZhY3RCYWxhbmNlCAULYXNzZXRQYXJhbXMCXzIEEGFzc2V0VmlydEJhbGFuY2UIBQthc3NldFBhcmFtcwJfMQQLYXNzZXRXZWlnaHQJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB3N0YXRpY18FD2Fzc2V0QWRkZWRJZFN0cgIHX3dlaWdodAQKYXNzZXRTY2FsZQkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHc3RhdGljXwUPYXNzZXRBZGRlZElkU3RyAgZfc2NhbGUEDWFzc2V0RGVjaW1hbHMJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB3N0YXRpY18FD2Fzc2V0QWRkZWRJZFN0cgIJX2RlY2ltYWxzBBNQSXNzdWVkTm9NdWx0aXBsaWVyCQBrAwUHUFN1cHBseQkAZQIJAKADAQkAdgYJALYCAQkAZAIFCmFzc2V0U2NhbGUJAGsDBQZhbW91bnQFCmFzc2V0U2NhbGUFEGFzc2V0VmlydEJhbGFuY2UFDWFzc2V0RGVjaW1hbHMJALYCAQULYXNzZXRXZWlnaHQABAAIBQRET1dOBQZTY2FsZTgFBlNjYWxlOAQHYXZnQ29uYwkBFGNhbGNBdmdDb25jZW50cmF0aW9uAAQHUElzc3VlZAkAawMFE1BJc3N1ZWROb011bHRpcGxpZXIIBQdhdmdDb25jAl8yCAUHYXZnQ29uYwJfMQQOYXNzZXRQYXJhbXNVcGQJAJoKCAkAZAIFEGFzc2V0VmlydEJhbGFuY2UFBmFtb3VudAkAZAIFEGFzc2V0RmFjdEJhbGFuY2UFBmFtb3VudAgFC2Fzc2V0UGFyYW1zAl8zCAULYXNzZXRQYXJhbXMCXzQIBQthc3NldFBhcmFtcwJfNQgFC2Fzc2V0UGFyYW1zAl82CAULYXNzZXRQYXJhbXMCXzcIBQthc3NldFBhcmFtcwJfOAkAlAoCCQDMCAIJARVzYXZlR2xvYmFsVG9rZW5QYXJhbXMCBQ9hc3NldEFkZGVkSWRTdHIFDmFzc2V0UGFyYW1zVXBkBQNuaWwFB1BJc3N1ZWQBFmNhbGNSZWRlZW1XaXRoT25lVG9rZW4CDWFzc2V0T3V0SWRTdHIJUFJlZGVlbWVkBAdQU3VwcGx5CQEZZ2V0VmlydHVhbFBvb2xUb2tlbkFtb3VudAAEC2Fzc2V0UGFyYW1zCQEVbG9hZEdsb2JhbFRva2VuUGFyYW1zAQUNYXNzZXRPdXRJZFN0cgQQYXNzZXRGYWN0QmFsYW5jZQgFC2Fzc2V0UGFyYW1zAl8yBBBhc3NldFZpcnRCYWxhbmNlCAULYXNzZXRQYXJhbXMCXzEEC2Fzc2V0V2VpZ2h0CQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdzdGF0aWNfBQ1hc3NldE91dElkU3RyAgdfd2VpZ2h0BAphc3NldFNjYWxlCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdzdGF0aWNfBQ1hc3NldE91dElkU3RyAgZfc2NhbGUEDWFzc2V0RGVjaW1hbHMJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB3N0YXRpY18FDWFzc2V0T3V0SWRTdHICCV9kZWNpbWFscwQVYW1vdW50T3V0Tm9NdWxpdHBsaWVyCQBrAwUQYXNzZXRWaXJ0QmFsYW5jZQkAZQIFBlNjYWxlOAkAoAMBCQB2BgkAtgIBCQBlAgUKYXNzZXRTY2FsZQkAawMFCVBSZWRlZW1lZAUKYXNzZXRTY2FsZQUHUFN1cHBseQUNYXNzZXREZWNpbWFscwkAtgIBCQBrAwCQTgCQTgULYXNzZXRXZWlnaHQABAAIBQRET1dOBQZTY2FsZTgEB2F2Z0NvbmMJARRjYWxjQXZnQ29uY2VudHJhdGlvbgAECWFtb3VudE91dAkAawMFFWFtb3VudE91dE5vTXVsaXRwbGllcggFB2F2Z0NvbmMCXzEIBQdhdmdDb25jAl8yAwkAZgIFCWFtb3VudE91dAUQYXNzZXRGYWN0QmFsYW5jZQkAAgECNG5vIGF2YWlsYWJsZSBmYWN0IGxpcXVpZGl0eSB0byB3aXRoZHJhdyBpbiBvbmUgdG9rZW4EDmFzc2V0UGFyYW1zVXBkCQCaCggJAGUCBRBhc3NldFZpcnRCYWxhbmNlBQlhbW91bnRPdXQJAGUCBRBhc3NldEZhY3RCYWxhbmNlBQlhbW91bnRPdXQIBQthc3NldFBhcmFtcwJfMwgFC2Fzc2V0UGFyYW1zAl80CAULYXNzZXRQYXJhbXMCXzUIBQthc3NldFBhcmFtcwJfNggFC2Fzc2V0UGFyYW1zAl83CAULYXNzZXRQYXJhbXMCXzgJAJQKAgkAzAgCCQEVc2F2ZUdsb2JhbFRva2VuUGFyYW1zAgUNYXNzZXRPdXRJZFN0cgUOYXNzZXRQYXJhbXNVcGQFA25pbAUJYW1vdW50T3V0ARZoYW5kbGVQb29sVG9rZW5zUmVkZWVtAglQUmVkZWVtZWQLdXNlckFkZHJlc3MKARFoYW5kbGVUb2tlblJlZGVlbQIFYWNjdW0HdG9rZW5JZAQKYXNzZXRJZFN0cgkBDmdldEFzc2V0U3RyaW5nAQUHdG9rZW5JZAQLYXNzZXRQYXJhbXMJARVsb2FkR2xvYmFsVG9rZW5QYXJhbXMBBQphc3NldElkU3RyBAJCawgFC2Fzc2V0UGFyYW1zAl8yBAdQU3VwcGx5CQEZZ2V0VmlydHVhbFBvb2xUb2tlbkFtb3VudAAEDXRva2VuRGVjaW1hbHMJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB3N0YXRpY18FCmFzc2V0SWRTdHICBl9zY2FsZQQGcHN1cHBsCQC9AgQJALkCAgkAtgIBCQBlAgUHUFN1cHBseQUJUFJlZGVlbWVkCQC2AgEFBlNjYWxlOAkAtgIBBQZTY2FsZTgJALYCAQUHUFN1cHBseQUERE9XTgQGYW1vdW50CQCgAwEJAL0CBAkAuAICCQC2AgEFB1NjYWxlMTYFBnBzdXBwbAkAtgIBBQJCawkAtgIBBQdTY2FsZTE2BQdDRUlMSU5HBAl1bnN0YWtlVHgJAQ91bnN0YWtlSWZOZWVkZWQCBQphc3NldElkU3RyBQZhbW91bnQDCQAAAgUJdW5zdGFrZVR4BQl1bnN0YWtlVHgEE3NlbGxvZmZTdGFydEJhbGFuY2UDCQECIT0CCAULYXNzZXRQYXJhbXMCXzgJAGgCCQBpAgUGaGVpZ2h0AGQAZAgFC2Fzc2V0UGFyYW1zAl83CQBrAwgFC2Fzc2V0UGFyYW1zAl83CQBlAgUHUFN1cHBseQUJUFJlZGVlbWVkBQdQU3VwcGx5BA5hc3NldFBhcmFtc1VwZAkAmgoICQBrAwgFC2Fzc2V0UGFyYW1zAl8xCQBlAgUHUFN1cHBseQUJUFJlZGVlbWVkBQdQU3VwcGx5CQBlAggFC2Fzc2V0UGFyYW1zAl8yBQZhbW91bnQIBQthc3NldFBhcmFtcwJfMwgFC2Fzc2V0UGFyYW1zAl80CAULYXNzZXRQYXJhbXMCXzUIBQthc3NldFBhcmFtcwJfNgUTc2VsbG9mZlN0YXJ0QmFsYW5jZQgFC2Fzc2V0UGFyYW1zAl84CQDOCAIJAM4IAgUFYWNjdW0JAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwULdXNlckFkZHJlc3MFBmFtb3VudAUHdG9rZW5JZAUDbmlsCQDMCAIJARVzYXZlR2xvYmFsVG9rZW5QYXJhbXMCBQphc3NldElkU3RyBQ5hc3NldFBhcmFtc1VwZAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCgACJGwFCGFzc2V0SWRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARFoYW5kbGVUb2tlblJlZGVlbQIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjRfMgIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgESY2FsY3VsYXRlT3V0QW1vdW50BQhBbW91bnRJbgdhc3NldEluCGFzc2V0T3V0CUJhbGFuY2VJbgpCYWxhbmNlT3V0BAdJbmRleEluCQEFdmFsdWUBCQDPCAIFCGFzc2V0SWRzBQdhc3NldEluBAhJbmRleE91dAkBBXZhbHVlAQkAzwgCBQhhc3NldElkcwUIYXNzZXRPdXQDCQAAAgUHSW5kZXhJbgUISW5kZXhPdXQFCEFtb3VudEluCQBuBAUKQmFsYW5jZU91dAkAZQIJAGgCBQZTY2FsZTgFBlNjYWxlOAkAoAMBCQB2BgkAvQIECQC5AgIJALYCAQUJQmFsYW5jZUluCQC2AgEAkE4JALYCAQkAaAIFBlNjYWxlOAUGU2NhbGU4CQC5AgIJALYCAQkAZAIFCUJhbGFuY2VJbgUIQW1vdW50SW4JALYCAQCQTgUGSEFMRlVQABAJALYCAQkAawMJAJEDAgUNQXNzZXRzV2VpZ2h0cwUHSW5kZXhJbgCAoJSljR0JAJEDAgUNQXNzZXRzV2VpZ2h0cwUISW5kZXhPdXQADAAQBQdDRUlMSU5HCQBoAgUGU2NhbGU4BQZTY2FsZTgFCEhBTEZFVkVOAQtjbGFpbVJlc3VsdAEHYWRkcmVzcwQKYWRkcmVzc1N0cgkApQgBBQdhZGRyZXNzBAtpbmRleEFtb3VudAkBDXRyeUdldEludGVnZXIBCQCsAgIFCmFkZHJlc3NTdHICDF9pbmRleFN0YWtlZAQLZmVlQXNzZXRTdHIJAQx0cnlHZXRTdHJpbmcBAg9zdGF0aWNfZmVlVG9rZW4EDmZlZUFzc2V0UGFyYW1zCQEVbG9hZEdsb2JhbFRva2VuUGFyYW1zAQULZmVlQXNzZXRTdHIED2ZlZVRva2VuQmFsYW5jZQgFDmZlZUFzc2V0UGFyYW1zAl8xCgEHaGFuZGxlcgIFYWNjdW0HYXNzZXRJZAQKYXNzZXRJZFN0cgkBDmdldEFzc2V0U3RyaW5nAQUHYXNzZXRJZAQLYXNzZXRQYXJhbXMJARVsb2FkR2xvYmFsVG9rZW5QYXJhbXMBBQphc3NldElkU3RyBBRjdXJyZW50VG9rZW5JbnRlcmVzdAgFC2Fzc2V0UGFyYW1zAl80BAhhQmFsYW5jZQgFC2Fzc2V0UGFyYW1zAl8xBAxyZXdhcmRBbW91bnQJAGsDBQtpbmRleEFtb3VudAkAZQIFFGN1cnJlbnRUb2tlbkludGVyZXN0CQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICCQCsAgIFCmFkZHJlc3NTdHICC19sYXN0Q2hlY2tfBQphc3NldElkU3RyAglfaW50ZXJlc3QFB1NjYWxlMTYECnVuc3Rha2VJbnYJAQ91bnN0YWtlSWZOZWVkZWQCBQphc3NldElkU3RyBQxyZXdhcmRBbW91bnQDCQAAAgUKdW5zdGFrZUludgUKdW5zdGFrZUludgQIdHJhbnNmZXIDCQAAAgUMcmV3YXJkQW1vdW50AAAFA25pbAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQdhZGRyZXNzBQxyZXdhcmRBbW91bnQFB2Fzc2V0SWQFA25pbAkAlAoCCQDOCAIJAM4IAggFBWFjY3VtAl8xBQh0cmFuc2ZlcgkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgIJAKwCAgUKYWRkcmVzc1N0cgILX2xhc3RDaGVja18FCmFzc2V0SWRTdHICCV9pbnRlcmVzdAUUY3VycmVudFRva2VuSW50ZXJlc3QFA25pbAkAZAIIBQVhY2N1bQJfMgkBEWNhbGN1bGF0ZVVzZFZhbHVlBAUHYXNzZXRJZAUMcmV3YXJkQW1vdW50BQhhQmFsYW5jZQUPZmVlVG9rZW5CYWxhbmNlCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBAVhY2N1bQoAAiRsBQxlYXJuZWRBc3NldHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCUCgIFA25pbAAACgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQdoYW5kbGVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY0XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNF8yAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKCQCUCgIJAM4IAggFBWFjY3VtAl8xCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIFCmFkZHJlc3NTdHICEV9jbGFpbWVkUmV3YXJkVVNECQBkAgkBDXRyeUdldEludGVnZXIBCQCsAgIFCmFkZHJlc3NTdHICEV9jbGFpbWVkUmV3YXJkVVNECAUFYWNjdW0CXzIJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgUKYWRkcmVzc1N0cgIKX2xhc3RDbGFpbQgFCWxhc3RCbG9jawl0aW1lc3RhbXAFA25pbAgFBWFjY3VtAl8yARBpbmRleFN0YWtlUmVzdWx0AgphZGRyZXNzU3RyBmFtb3VudAQCbGkICQELY2xhaW1SZXN1bHQBCQERQGV4dHJOYXRpdmUoMTA2MikBBQphZGRyZXNzU3RyAl8xCQDOCAIFAmxpCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIFCmFkZHJlc3NTdHICDF9pbmRleFN0YWtlZAkAZAIJAQ10cnlHZXRJbnRlZ2VyAQkArAICBQphZGRyZXNzU3RyAgxfaW5kZXhTdGFrZWQFBmFtb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgISZ2xvYmFsX2luZGV4U3Rha2VkCQBkAgkBDXRyeUdldEludGVnZXIBAhJnbG9iYWxfaW5kZXhTdGFrZWQFBmFtb3VudAUDbmlsAQNzdW0CBWFjY3VtAW4JAGQCBQVhY2N1bQkBDXBhcnNlSW50VmFsdWUBBQFuAQ1jaGVja0ZlZUFzc2V0AgVhY2N1bQRuZXh0AwMJAQIhPQIJAM8IAgUVc3VwcG9ydGVkRmVlQXNzZXRzU3RyBQRuZXh0BQR1bml0CQAAAgUFYWNjdW0CAAcFBG5leHQFBWFjY3VtARJjYWxjSW50ZXJlc3RDaGFuZ2UCCmFzc2V0SWRTdHIFbHBGZWUECnRvdGFsSW5kZXgJAQ10cnlHZXRJbnRlZ2VyAQISZ2xvYmFsX2luZGV4U3Rha2VkBA1pbnRlcmVzdERlbHRhCQBrAwUFbHBGZWUFB1NjYWxlMTYFCnRvdGFsSW5kZXgFDWludGVyZXN0RGVsdGEBDnVwZFNlbGxvZmZEYXRhBAphc3NldElkU3RyCGFtb3VudEluB2JhbGFuY2UNc2VsbG9mZlBhcmFtcwQNY3VycmVudFBlcmlvZAkAaAIJAGkCBQZoZWlnaHQAZABkBApwcmV2UGVyaW9kCAUNc2VsbG9mZlBhcmFtcwJfMgQLcHJldlNlbGxvZmYDCQAAAgUNY3VycmVudFBlcmlvZAUKcHJldlBlcmlvZAgFDXNlbGxvZmZQYXJhbXMCXzEAAAQTc2VsbG9mZlN0YXJ0QmFsYW5jZQMJAAACBQ1jdXJyZW50UGVyaW9kBQpwcmV2UGVyaW9kCAUNc2VsbG9mZlBhcmFtcwJfMwUHYmFsYW5jZQQMc2VsbG9mZkRlbHRhCQBrAwUHU2NhbGUxNgUIYW1vdW50SW4FE3NlbGxvZmZTdGFydEJhbGFuY2UECm1heFNlbGxvZmYJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB3N0YXRpY18FCmFzc2V0SWRTdHICC19tYXhTZWxsb2ZmAwMJAGYCCQBkAgULcHJldlNlbGxvZmYFDHNlbGxvZmZEZWx0YQUKbWF4U2VsbG9mZgkBAiE9AgUKbWF4U2VsbG9mZgAABwkAAgEJAKwCAgIjbWF4IHNlbGxvZmYgcmVhY2hlZCBmb3IgdGhpcyBhc3NldCAFCmFzc2V0SWRTdHIEBnN0YXJ0SAMJAAACBQ1jdXJyZW50UGVyaW9kBQpwcmV2UGVyaW9kBQpwcmV2UGVyaW9kBQ1jdXJyZW50UGVyaW9kBAZzdGFydEIDCQAAAgUNY3VycmVudFBlcmlvZAUKcHJldlBlcmlvZAgFDXNlbGxvZmZQYXJhbXMCXzMFE3NlbGxvZmZTdGFydEJhbGFuY2UJAJUKAwkAZAIFC3ByZXZTZWxsb2ZmBQxzZWxsb2ZmRGVsdGEFBnN0YXJ0SAUGc3RhcnRCARJnZXRUbXBSZWJhbGFuY2VJZHMBDW5ld0Fzc2V0SWRzTGkEEWN1cnJlbnRBc3NldElkc0xpCQC1CQIJAQx0cnlHZXRTdHJpbmcBAg9zdGF0aWNfdG9rZW5JZHMCASwEBnJlc3VsdAUNbmV3QXNzZXRJZHNMaQoBAWYCBWFjY3VtB2Fzc2V0SWQDCQAAAgkAzwgCBQZyZXN1bHQFB2Fzc2V0SWQFBHVuaXQJAM4IAgUFYWNjdW0JAMwIAgUHYXNzZXRJZAUDbmlsBQVhY2N1bQoAAiRsBRFjdXJyZW50QXNzZXRJZHNMaQoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFBnJlc3VsdAoBBSRmNF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEBZgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjRfMgIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgERY2hlY2tUb2tlbnNDaGFuZ2UBDW5ld0Fzc2V0SWRzTGkEEWN1cnJlbnRBc3NldElkc0xpCQC1CQIJAQx0cnlHZXRTdHJpbmcBAg9zdGF0aWNfdG9rZW5JZHMCASwKAQNyZW0CBWFjY3VtB2Fzc2V0SWQDCQAAAgkAzwgCBQ1uZXdBc3NldElkc0xpBQdhc3NldElkBQR1bml0CQBkAgUFYWNjdW0AAQUFYWNjdW0KAQNhZGQCBWFjY3VtB2Fzc2V0SWQDCQAAAgkAzwgCBRFjdXJyZW50QXNzZXRJZHNMaQUHYXNzZXRJZAUEdW5pdAkAZAIFBWFjY3VtAAEFBWFjY3VtBAdyZW1vdmVkCgACJGwFEWN1cnJlbnRBc3NldElkc0xpCgACJHMJAJADAQUCJGwKAAUkYWNjMAAACgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQNyZW0CBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjRfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY0XzICCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoEBWFkZGVkCgACJGwFDW5ld0Fzc2V0SWRzTGkKAAIkcwkAkAMBBQIkbAoABSRhY2MwAAAKAQUkZjVfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBA2FkZAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNV8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjVfMgIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgkAZAIFB3JlbW92ZWQFBWFkZGVkARB2YWxpZGF0ZVBheW1lbnRzAgphc3NldHNMaXN0CHBheW1lbnRzCgEQZ2V0UGF5bWVudEFzc2V0cwIFYWNjdW0EbmV4dAMJAGcCAAAIBQRuZXh0BmFtb3VudAkAAgEJAKwCAgkArAICCQCsAgICG1RvbyBsb3cgcGF5bWVudCBhbW91bnQgZm9yIAkBDmdldEFzc2V0U3RyaW5nAQgFBG5leHQHYXNzZXRJZAICOiAJAKQDAQgFBG5leHQGYW1vdW50CQDOCAIFBWFjY3VtCQDMCAIJAQ5nZXRBc3NldFN0cmluZwEIBQRuZXh0B2Fzc2V0SWQFA25pbAQLcGF5bWVudExpc3QKAAIkbAUIcGF5bWVudHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjRfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBEGdldFBheW1lbnRBc3NldHMCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjRfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY0XzICCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoKAQJmMQIFYWNjdW0EbmV4dAMJAAACCQDPCAIFCmFzc2V0c0xpc3QFBG5leHQFBHVuaXQJAAIBCQCsAgIJAKwCAgUEbmV4dAI5IGFzc2V0IGlzIHByZXNlbnQgaW4gcGF5bWVudHMsIGJ1dCBpcyBub3QgaW4gbmV3IGFzc2V0czogCQC5CQIFCmFzc2V0c0xpc3QCASwJAGQCBQVhY2N1bQABCgECZjICBWFjY3VtBG5leHQDCQAAAgkAzwgCBQtwYXltZW50TGlzdAUEbmV4dAUEdW5pdAkAAgEJAKwCAgkArAICBQRuZXh0AjkgYXNzZXQgaXMgcHJlc2VudCBpbiBuZXcgYXNzZXRzLCBidXQgaXMgbm90IGluIHBheW1lbnRzOiAJALkJAgULcGF5bWVudExpc3QCASwJAGQCBQVhY2N1bQABBAJhMQoAAiRsBQtwYXltZW50TGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAAAAoBBSRmNV8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQECZjECBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjVfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY1XzICCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoEAmEyCgACJGwFCmFzc2V0c0xpc3QKAAIkcwkAkAMBBQIkbAoABSRhY2MwAAAKAQUkZjZfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBAmYyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY2XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNl8yAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKCQBkAgUCYTEFAmEyAQ92YWxpZGF0ZVdlaWdodHMBB3dlaWdodHMKAQF2AgVhY2N1bQF3BAR3SW50CQETdmFsdWVPckVycm9yTWVzc2FnZQIJALYJAQUBdwkArAICAhVXcm9uZyB3ZWlnaHQgZm9ybWF0OiAFAXcDAwkAZgIFCk1JTl9XRUlHSFQFBHdJbnQGCQBmAgUEd0ludAUKTUFYX1dFSUdIVAkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAhpXZWlnaHQgc2hvdWxkIGJlIGluIHJhbmdlIAkApAMBBQpNSU5fV0VJR0hUAgMgLSAJAKQDAQUKTUFYX1dFSUdIVAILLCBjdXJyZW50OiAFAXcJAGQCBQVhY2N1bQUEd0ludAoAAiRsBQd3ZWlnaHRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAAACgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQF2AgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY0XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNF8yAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAQdnZXRQMVAyAgphc3NldElkU3RyDmJhc2VBc3NldElkU3RyBAthc3NldFBhcmFtcwkBFWxvYWRHbG9iYWxUb2tlblBhcmFtcwEFCmFzc2V0SWRTdHIED2Jhc2VBc3NldFBhcmFtcwkBFWxvYWRHbG9iYWxUb2tlblBhcmFtcwEFDmJhc2VBc3NldElkU3RyBAJCMQgFD2Jhc2VBc3NldFBhcmFtcwJfMQQCQjIIBQthc3NldFBhcmFtcwJfMQQCRjEIBQ9iYXNlQXNzZXRQYXJhbXMCXzIEAkYyCAULYXNzZXRQYXJhbXMCXzIEAlMxCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdzdGF0aWNfBQ5iYXNlQXNzZXRJZFN0cgIGX3NjYWxlBAJTMgkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHc3RhdGljXwUKYXNzZXRJZFN0cgIGX3NjYWxlBAJEMQkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHc3RhdGljXwUOYmFzZUFzc2V0SWRTdHICCV9kZWNpbWFscwQCRDIJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB3N0YXRpY18FCmFzc2V0SWRTdHICCV9kZWNpbWFscwQCVzEJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB3N0YXRpY18FDmJhc2VBc3NldElkU3RyAgdfd2VpZ2h0BAJXMgkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHc3RhdGljXwUKYXNzZXRJZFN0cgIHX3dlaWdodAQEVzFXMgkAawMFAlcxAJBOBQJXMgQEVzJXMQkAawMFAlcyAJBOBQJXMQQNcDFfdW53ZWlnaHRlZAkAawMJAGUCBQJCMQUCRjEFAlMxCQBrAwUCQjIJAGwGCQBrAwUCQjEFAlMxCQBlAgUCQjEFAkYxBQJEMQUEVzFXMgAEBQJEMQUHQ0VJTElORwUCUzIEAnAxCQBrAwUNcDFfdW53ZWlnaHRlZAUEVzJXMQCQTgMJAAACBQJCMgUCRjIJAJQKAgUCcDEFBHVuaXQEDXAyX3Vud2VpZ2h0ZWQJAGsDCQBrAwUCQjEJAGwGCQBrAwUCQjIFAlMyCQBlAgUCQjIFAkYyBQJEMgUEVzJXMQAEBQJEMgUFRkxPT1IFAlMyBQJTMgkAZQIFAkIyBQJGMgQCcDIJAGsDBQ1wMl91bndlaWdodGVkBQRXMlcxAJBOCQCUCgIFAnAxBQJwMhEBaQETYWRkVW5kZXJseWluZ1N0YWtlcgINc3Rha2VyQWRkcmVzcwphc3NldElkU3RyAwkBAiE9AgUEdGhpcwgFAWkGY2FsbGVyCQACAQIKYWRtaW4gb25seQkAzAgCCQELU3RyaW5nRW50cnkCCQCsAgICF3N0YXRpY19zdGFraW5nQ29udHJhY3RfBQphc3NldElkU3RyBQ1zdGFrZXJBZGRyZXNzBQNuaWwBaQEHcHJlSW5pdAcLYXNzZXRJZHNTdHIPYXNzZXRXZWlnaHRzU3RyEmFzc2V0TWF4U2VsbG9mZlN0cg5iYXNlVG9rZW5JZFN0cgpwb29sRG9tYWluCXBvb2xPd25lcgNmZWUEEHBvb2xPd25lckFkZHJlc3MJARFAZXh0ck5hdGl2ZSgxMDYyKQEFCXBvb2xPd25lcgQNYXNzZXRJZHNTdHJMaQkAtQkCBQthc3NldElkc1N0cgIBLAQUYXNzZXRNYXhTZWxsb2ZmU3RyTGkJALUJAgUSYXNzZXRNYXhTZWxsb2ZmU3RyAgEsBBFhc3NldFdlaWdodHNTdHJMaQkAtQkCBQ9hc3NldFdlaWdodHNTdHICASwECmFzc2V0SWRzTGkKAAIkbAUNYXNzZXRJZHNTdHJMaQoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmNF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQETYWRkQXNzZXRCeXRlc1RvTGlzdAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjRfMgIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgQRZmVlQXNzZXRDaG9zZW5TdHIKAAIkbAUNYXNzZXRJZHNTdHJMaQoAAiRzCQCQAwEFAiRsCgAFJGFjYzACAAoBBSRmNV8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQENY2hlY2tGZWVBc3NldAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNV8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjVfMgIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgQLZmVlQXNzZXRTdHIDCQAAAgURZmVlQXNzZXRDaG9zZW5TdHICAAUOYmFzZVRva2VuSWRTdHIFEWZlZUFzc2V0Q2hvc2VuU3RyAwkBCmlzU2h1dGRvd24ACQACAQITY29udHJhY3QgaXMgb24gc3RvcAMJAQIhPQIFBHRoaXMIBQFpBmNhbGxlcgkAAgECCmFkbWluIG9ubHkDCQBmAgkAsQIBBQpwb29sRG9tYWluAA0JAAIBAhV0b28gbGFyZ2UgcG9vbCBkb21haW4DAwkAZgIFA2ZlZQD0AwYJAGYCAAAFA2ZlZQkAAgECKmZlZSB2YWx1ZSBtdXN0IGJlIGJldHdlZW4gMCBhbmQgNTAwICgwLTUlKQMJAQIhPQIJAQ92YWxpZGF0ZVdlaWdodHMBBRFhc3NldFdlaWdodHNTdHJMaQCQTgkAAgEJAKwCAgImd2VpZ2h0cyBzdW0gc2hvdWxkIGJlIDEwMDAwLCBjdXJyZW50OiAJAKQDAQkBD3ZhbGlkYXRlV2VpZ2h0cwEFEWFzc2V0V2VpZ2h0c1N0ckxpCgETYWRkVG9rZW5EYXRhRW50cmllcwIFYWNjdW0IYXNzZXROdW0DCQBnAgUIYXNzZXROdW0JAJADAQUKYXNzZXRJZHNMaQUFYWNjdW0EE2Fzc2V0U3Rha2luZ0FkZHJlc3MKAAFACQD8BwQFD3Bvb2xzSHViQWRkcmVzcwIQdXNlRW1wdHlDb250cmFjdAkAzAgCCQCsAgICB3N0YWtlcl8JAJEDAgUNYXNzZXRJZHNTdHJMaQUIYXNzZXROdW0FA25pbAUDbmlsAwkAAQIFAUACBlN0cmluZwUBQAkAAgEJAKwCAgkAAwEFAUACGyBjb3VsZG4ndCBiZSBjYXN0IHRvIFN0cmluZwMJAAACBRNhc3NldFN0YWtpbmdBZGRyZXNzBRNhc3NldFN0YWtpbmdBZGRyZXNzBA1hc3NldERlY2ltYWxzBAckbWF0Y2gwCQCRAwIFCmFzc2V0SWRzTGkFCGFzc2V0TnVtAwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEAXgFByRtYXRjaDAICQEFdmFsdWUBCQDsBwEFAXgIZGVjaW1hbHMACAkAzggCCQDOCAIFBWFjY3VtCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgIHc3RhdGljXwkAkQMCBQ1hc3NldElkc1N0ckxpBQhhc3NldE51bQIGX3NjYWxlCQBsBgAKAAAFDWFzc2V0RGVjaW1hbHMAAAAABQRET1dOCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgIHc3RhdGljXwkAkQMCBQ1hc3NldElkc1N0ckxpBQhhc3NldE51bQIJX2RlY2ltYWxzBQ1hc3NldERlY2ltYWxzCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgIHc3RhdGljXwkAkQMCBQ1hc3NldElkc1N0ckxpBQhhc3NldE51bQIHX3dlaWdodAkBBXZhbHVlAQkAtgkBCQCRAwIFEWFzc2V0V2VpZ2h0c1N0ckxpBQhhc3NldE51bQkAzAgCCQELU3RyaW5nRW50cnkCCQCsAgICF3N0YXRpY19zdGFraW5nQ29udHJhY3RfCQCRAwIFDWFzc2V0SWRzU3RyTGkFCGFzc2V0TnVtBRNhc3NldFN0YWtpbmdBZGRyZXNzBQNuaWwDCQAAAgkAkQMCBRRhc3NldE1heFNlbGxvZmZTdHJMaQUIYXNzZXROdW0CAAUDbmlsCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgIHc3RhdGljXwkAkQMCBQ1hc3NldElkc1N0ckxpBQhhc3NldE51bQILX21heFNlbGxvZmYJAGgCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUUYXNzZXRNYXhTZWxsb2ZmU3RyTGkFCGFzc2V0TnVtBQdTY2FsZTEyBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAM4IAgoAAiRsCQDMCAIAAAkAzAgCAAEJAMwIAgACCQDMCAIAAwkAzAgCAAQJAMwIAgAFCQDMCAIABgkAzAgCAAcJAMwIAgAICQDMCAIACQUDbmlsCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGY2XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARNhZGRUb2tlbkRhdGFFbnRyaWVzAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY2XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNl8yAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKCQDMCAIJAQtTdHJpbmdFbnRyeQICD3N0YXRpY190b2tlbklkcwULYXNzZXRJZHNTdHIJAMwIAgkBC1N0cmluZ0VudHJ5AgIPc3RhdGljX2ZlZVRva2VuBQtmZWVBc3NldFN0cgkAzAgCCQELU3RyaW5nRW50cnkCAhNzdGF0aWNfdG9rZW5XZWlnaHRzBQ9hc3NldFdlaWdodHNTdHIJAMwIAgkBDEludGVnZXJFbnRyeQICE3N0YXRpY190b2tlbnNBbW91bnQJAJADAQUKYXNzZXRJZHNMaQkAzAgCCQELU3RyaW5nRW50cnkCAhFzdGF0aWNfcG9vbERvbWFpbgUKcG9vbERvbWFpbgkAzAgCCQELU3RyaW5nRW50cnkCAhZzdGF0aWNfcG9vbFRva2VuX2lkU3RyAgAJAMwIAgkBC1N0cmluZ0VudHJ5AgISc3RhdGljX2Jhc2VUb2tlbklkBQ5iYXNlVG9rZW5JZFN0cgkAzAgCCQELU3RyaW5nRW50cnkCAhBzdGF0aWNfcG9vbE93bmVyBQlwb29sT3duZXIJAMwIAgkBDEludGVnZXJFbnRyeQICCnN0YXRpY19mZWUFA2ZlZQkAzAgCCQEMSW50ZWdlckVudHJ5AgIMc3RhdGljX0tNdWx0BQdTY2FsZTE2CQDMCAIJAQxJbnRlZ2VyRW50cnkCAhJnbG9iYWxfaW5kZXhTdGFrZWQAAAkAzAgCCQEMSW50ZWdlckVudHJ5AgIXZ2xvYmFsX3Bvb2xUb2tlbl9hbW91bnQAAAkAzAgCCQEMSW50ZWdlckVudHJ5AgITZ2xvYmFsX3dhc1ByZUluaXRlZAABBQNuaWwBaQEGZGVJbml0AAMJAQppc1NodXRkb3duAAkAAgECE2NvbnRyYWN0IGlzIG9uIHN0b3ADCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAgphZG1pbiBvbmx5CQDMCAIJAQxJbnRlZ2VyRW50cnkCAhBnbG9iYWxfd2FzSW5pdGVkAAAFA25pbAFpAQRpbml0Bwthc3NldElkc1N0cg9hc3NldFdlaWdodHNTdHISYXNzZXRNYXhTZWxsb2ZmU3RyDmJhc2VUb2tlbklkU3RyCnBvb2xEb21haW4DZmVlDHZCYWxhbmNlc1N0cgQKcHJlSW5pdEludgkA/AcEBQR0aGlzAgdwcmVJbml0CQDMCAIFC2Fzc2V0SWRzU3RyCQDMCAIFD2Fzc2V0V2VpZ2h0c1N0cgkAzAgCBRJhc3NldE1heFNlbGxvZmZTdHIJAMwIAgUOYmFzZVRva2VuSWRTdHIJAMwIAgUKcG9vbERvbWFpbgkAzAgCCQClCAEIBQFpBmNhbGxlcgkAzAgCBQNmZWUFA25pbAUDbmlsAwkAAAIFCnByZUluaXRJbnYFCnByZUluaXRJbnYECXZCYWxhbmNlcwkBEXBhcnN0U3RyVG9JbnRMaXN0AQUMdkJhbGFuY2VzU3RyCgEQZ2V0UGF5bWVudEFtb3VudAEKYXNzZXRJZFN0cgoBB2hhbmRsZXICBWFjY3VtB3BheW1lbnQDCQAAAgkBDmdldEFzc2V0U3RyaW5nAQgFB3BheW1lbnQHYXNzZXRJZAUKYXNzZXRJZFN0cggFB3BheW1lbnQGYW1vdW50BQVhY2N1bQoAAiRsCAUBaQhwYXltZW50cwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAAAAoBBSRmNF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEHaGFuZGxlcgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjRfMgIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgoBC3ByZXBhcmVMaXN0AAoBB2hhbmRsZXICBWFjY3VtB2Fzc2V0SWQECmFzc2V0SWRTdHIJAQ5nZXRBc3NldFN0cmluZwEFB2Fzc2V0SWQEAW4JAQV2YWx1ZQEJAM8IAgUIYXNzZXRJZHMFB2Fzc2V0SWQEDXBheW1lbnRBbW91bnQJARBnZXRQYXltZW50QW1vdW50AQUKYXNzZXRJZFN0cgQLYXNzZXRQYXJhbXMJARVsb2FkR2xvYmFsVG9rZW5QYXJhbXMBBQphc3NldElkU3RyBA5hc3NldFBhcmFtc1VwZAkAmgoICQCRAwIFCXZCYWxhbmNlcwUBbgUNcGF5bWVudEFtb3VudAgFC2Fzc2V0UGFyYW1zAl8zCAULYXNzZXRQYXJhbXMCXzQIBQthc3NldFBhcmFtcwJfNQgFC2Fzc2V0UGFyYW1zAl82CAULYXNzZXRQYXJhbXMCXzcIBQthc3NldFBhcmFtcwJfOAkAzggCBQVhY2N1bQkAzAgCCQEVc2F2ZUdsb2JhbFRva2VuUGFyYW1zAgUKYXNzZXRJZFN0cgUOYXNzZXRQYXJhbXNVcGQFA25pbAoAAiRsBQhhc3NldElkcwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmNF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEHaGFuZGxlcgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjRfMgIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgoBGWNhbGN1bGF0ZVBvb2xUb2tlbnNBbW91bnQBB2Fzc2V0SWQKAQdoYW5kbGVyAgVhY2N1bQdhc3NldElkCgEIaGFuZGxlcjICBWFjY3VtAW4DCQAAAgUBbgUHYXNzZXRJZAkBBXZhbHVlAQkAzwgCBQhhc3NldElkcwUBbgUFYWNjdW0EBVRva2VuCgACJGwFCGFzc2V0SWRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAABCgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQhoYW5kbGVyMgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjRfMgIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgkAawMFBWFjY3VtCQBsBgkAkQMCBQl2QmFsYW5jZXMFBVRva2VuCQCRAwIFCERlY2ltYWxzBQVUb2tlbgkAkQMCBQ1Bc3NldHNXZWlnaHRzBQVUb2tlbgUVQXNzZXRzV2VpZ2h0c0RlY2ltYWxzAAgFBUZMT09SBQZTY2FsZTgKAAIkbAUIYXNzZXRJZHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQ5Qb29sVG9rZW5TY2FsZQoBBSRmNF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEHaGFuZGxlcgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjRfMgIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgMJAQppc1NodXRkb3duAAkAAgECE2NvbnRyYWN0IGlzIG9uIHN0b3ADCQAAAgkAkAMBCAUBaQhwYXltZW50cwAACQACAQI5YXQgbGVhc3Qgc29tZSBvZiB0aGUgYXNzZXRzIHNob3VsZCBiZSBwcm92aWRlZCBhcyBwYXltZW50AwkAZgIJAQ10cnlHZXRJbnRlZ2VyAQIQZ2xvYmFsX3dhc0luaXRlZAAACQACAQITcG9vbCBhbHJlYWR5IGluaXRlZAQRaW5pdGlhbFBvb2xUb2tlbnMJARljYWxjdWxhdGVQb29sVG9rZW5zQW1vdW50AQUIYXNzZXRJZHMEDG5vdGlmeUludm9rZQkA/AcEBQ9wb29sc0h1YkFkZHJlc3MCC2FkZFNlbGZQb29sBQNuaWwFA25pbAMJAAACBQxub3RpZnlJbnZva2UFDG5vdGlmeUludm9rZQMJAAACBRFpbml0aWFsUG9vbFRva2VucwAACQACAQIyeW91IG5lZWQgYSBiaWdnZXIgdG9rZW5zIGFtb3VudCB0byBsYXVuY2ggdGhlIHBvb2wJAM4IAgkBC3ByZXBhcmVMaXN0AAkAzAgCCQEMSW50ZWdlckVudHJ5AgIXZ2xvYmFsX3Bvb2xUb2tlbl9hbW91bnQFEWluaXRpYWxQb29sVG9rZW5zCQDMCAIJAQxJbnRlZ2VyRW50cnkCAhBnbG9iYWxfd2FzSW5pdGVkAAEJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkApQgBCAUBaQZjYWxsZXICDF9pbmRleFN0YWtlZAURaW5pdGlhbFBvb2xUb2tlbnMJAMwIAgkBDEludGVnZXJFbnRyeQICEmdsb2JhbF9pbmRleFN0YWtlZAURaW5pdGlhbFBvb2xUb2tlbnMFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ1nZW5lcmF0ZUluZGV4AQpuZWVkQ2hhbmdlAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwUBVAkAAgEJAKwCAgI7eW91IG5lZWQgdG8gYXR0YWNoIGFsbCBwb29sIHRva2Vucy4gYW1vdW50IG9mIHBvb2wgdG9rZW5zOiAJAKQDAQUBVAMJAQEhAQkBE2NoZWNrVG9rZW5zVmFsaWRpdHkBCAUBaQhwYXltZW50cwkAAgECFXdyb25nIGFzc2V0cyBhdHRhY2hlZAQNUElzc3VlZE5vTXVsdAkBDWdldE1pblBJc3N1ZWQBCAUBaQhwYXltZW50cwQGcmVzdWx0CQETaGFuZGxlUG9vbFRva2Vuc0FkZAQFDVBJc3N1ZWROb011bHQIBQFpCHBheW1lbnRzCAUBaQxvcmlnaW5DYWxsZXIFCm5lZWRDaGFuZ2UED1BJc3N1ZWRXaXRoTXVsdAkAbgQFDVBJc3N1ZWROb011bHQFB1NjYWxlMTYJAQhnZXRLTXVsdAAFBERPV04JAJQKAgkAzggCCQDOCAIJAM4IAgUGcmVzdWx0CAkBC2NsYWltUmVzdWx0AQgFAWkGY2FsbGVyAl8xCQERbWludEluZGV4SWZOZWVkZWQBBQ9QSXNzdWVkV2l0aE11bHQJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkApQgBCAUBaQZjYWxsZXICDF9pbmRleFN0YWtlZAkAZAIJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQClCAEIBQFpBmNhbGxlcgIMX2luZGV4U3Rha2VkBQ9QSXNzdWVkV2l0aE11bHQJAMwIAgkBDEludGVnZXJFbnRyeQICEmdsb2JhbF9pbmRleFN0YWtlZAkAZAIJAQ10cnlHZXRJbnRlZ2VyAQISZ2xvYmFsX2luZGV4U3Rha2VkBQ9QSXNzdWVkV2l0aE11bHQJAMwIAgkBDEludGVnZXJFbnRyeQICF2dsb2JhbF9wb29sVG9rZW5fYW1vdW50CQBkAgkBDXRyeUdldEludGVnZXIBAhdnbG9iYWxfcG9vbFRva2VuX2Ftb3VudAUPUElzc3VlZFdpdGhNdWx0BQNuaWwFD1BJc3N1ZWRXaXRoTXVsdAFpAQtyZWRlZW1JbmRleAEPcG9vbFRva2VuQW1vdW50AwkAZgIFD3Bvb2xUb2tlbkFtb3VudAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKUIAQgFAWkGY2FsbGVyAgxfaW5kZXhTdGFrZWQJAAIBAix1c2VyIGRvZXNuJ3QgaGF2ZSB0aGlzIGFtb3VudCBvZiBwb29sIHRva2VucwMJAQppc1NodXRkb3duAAkAAgECE2NvbnRyYWN0IGlzIG9uIHN0b3AEEVBSZWRlZW1lZFdpdGhNdWx0BQ9wb29sVG9rZW5BbW91bnQEE1BSZWRlZW1lZFdpdGhOb011bHQJAG4EBRFQUmVkZWVtZWRXaXRoTXVsdAkBCGdldEtNdWx0AAUHU2NhbGUxNgUERE9XTgQGcmVzdWx0CQEWaGFuZGxlUG9vbFRva2Vuc1JlZGVlbQIFE1BSZWRlZW1lZFdpdGhOb011bHQIBQFpBmNhbGxlcgkAzggCCQDOCAIJAM4IAgUGcmVzdWx0CAkBC2NsYWltUmVzdWx0AQgFAWkGY2FsbGVyAl8xCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKUIAQgFAWkGY2FsbGVyAgxfaW5kZXhTdGFrZWQJAGUCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkApQgBCAUBaQZjYWxsZXICDF9pbmRleFN0YWtlZAURUFJlZGVlbWVkV2l0aE11bHQJAMwIAgkBDEludGVnZXJFbnRyeQICEmdsb2JhbF9pbmRleFN0YWtlZAkAZQIJAQ10cnlHZXRJbnRlZ2VyAQISZ2xvYmFsX2luZGV4U3Rha2VkBRFQUmVkZWVtZWRXaXRoTXVsdAkAzAgCCQEMSW50ZWdlckVudHJ5AgIXZ2xvYmFsX3Bvb2xUb2tlbl9hbW91bnQJAGUCCQENdHJ5R2V0SW50ZWdlcgECF2dsb2JhbF9wb29sVG9rZW5fYW1vdW50BRFQUmVkZWVtZWRXaXRoTXVsdAUDbmlsCQERYnVybkluZGV4SWZOZWVkZWQBBQ9wb29sVG9rZW5BbW91bnQBaQEKc3Rha2VJbmRleAAECmFkZHJlc3NTdHIJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyBANwbXQJAJEDAggFAWkIcGF5bWVudHMAAAMJAQIhPQIJAQV2YWx1ZQEIBQNwbXQHYXNzZXRJZAkA2QQBCQEMdHJ5R2V0U3RyaW5nAQIWc3RhdGljX3Bvb2xUb2tlbl9pZFN0cgkAAgECFHdyb25nIGFzc2V0IGF0dGFjaGVkCQEQaW5kZXhTdGFrZVJlc3VsdAIFCmFkZHJlc3NTdHIIBQNwbXQGYW1vdW50AWkBDXN0YWtlSW5kZXhGb3IBCmFkZHJlc3NTdHIEA3BtdAkAkQMCCAUBaQhwYXltZW50cwAAAwkBAiE9AgkBBXZhbHVlAQgFA3BtdAdhc3NldElkCQDZBAEJAQx0cnlHZXRTdHJpbmcBAhZzdGF0aWNfcG9vbFRva2VuX2lkU3RyCQACAQIUd3JvbmcgYXNzZXQgYXR0YWNoZWQJARBpbmRleFN0YWtlUmVzdWx0AgUKYWRkcmVzc1N0cggFA3BtdAZhbW91bnQBaQEMdW5zdGFrZUluZGV4AQtpbmRleEFtb3VudAoBCmlzc3VlSW5kZXgABAVpc3N1ZQkAwwgHCQCsAgICA1BSIAkBDHRyeUdldFN0cmluZwECEXN0YXRpY19wb29sRG9tYWluAhJQdXp6bGUgUmFuZ2UgSW5kZXgJAQ10cnlHZXRJbnRlZ2VyAQIXZ2xvYmFsX3Bvb2xUb2tlbl9hbW91bnQFEVBvb2xUb2tlbkRlY2ltYWxzBgUEdW5pdAAABA5wb29sVG9rZW5JZFN0cgkA2AQBCQC4CAEFBWlzc3VlCQCUCgIJAMwIAgUFaXNzdWUJAMwIAgkBC1N0cmluZ0VudHJ5AgIWc3RhdGljX3Bvb2xUb2tlbl9pZFN0cgUOcG9vbFRva2VuSWRTdHIFA25pbAUOcG9vbFRva2VuSWRTdHIEDSR0MDQwMDQ3NDAyMTMDCQAAAgkBDHRyeUdldFN0cmluZwECFnN0YXRpY19wb29sVG9rZW5faWRTdHICAAkBCmlzc3VlSW5kZXgACQCUCgIFA25pbAkBDHRyeUdldFN0cmluZwECFnN0YXRpY19wb29sVG9rZW5faWRTdHIEFHBvb2xUb2tlbklzc3VlUmVzdWx0CAUNJHQwNDAwNDc0MDIxMwJfMQQOcG9vbFRva2VuSWRTdHIIBQ0kdDA0MDA0NzQwMjEzAl8yBAtwb29sVG9rZW5JZAkA2QQBBQ5wb29sVG9rZW5JZFN0cgQKYWRkcmVzc1N0cgkApQgBCAUBaQZjYWxsZXIEDmluZGV4QXZhaWxhYmxlCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgUKYWRkcmVzc1N0cgIMX2luZGV4U3Rha2VkAwkBCmlzU2h1dGRvd24ACQACAQITY29udHJhY3QgaXMgb24gc3RvcAMJAGYCBQtpbmRleEFtb3VudAUOaW5kZXhBdmFpbGFibGUJAAIBAiV5b3UgZG9uJ3QgaGF2ZSBpbmRleCB0b2tlbnMgYXZhaWxhYmxlAwkBCmlzU2h1dGRvd24ACQACAQITY29udHJhY3QgaXMgb24gc3RvcAkAzggCCQDOCAIFFHBvb2xUb2tlbklzc3VlUmVzdWx0CAkBC2NsYWltUmVzdWx0AQkBEUBleHRyTmF0aXZlKDEwNjIpAQUKYWRkcmVzc1N0cgJfMQkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICBQphZGRyZXNzU3RyAgxfaW5kZXhTdGFrZWQJAGUCBQ5pbmRleEF2YWlsYWJsZQULaW5kZXhBbW91bnQJAMwIAgkBDEludGVnZXJFbnRyeQICEmdsb2JhbF9pbmRleFN0YWtlZAkAZQIJAQ10cnlHZXRJbnRlZ2VyAQISZ2xvYmFsX2luZGV4U3Rha2VkBQtpbmRleEFtb3VudAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIFC2luZGV4QW1vdW50BQtwb29sVG9rZW5JZAUDbmlsAWkBEWNsYWltSW5kZXhSZXdhcmRzAAMJAQppc1NodXRkb3duAAkAAgECE2NvbnRyYWN0IGlzIG9uIHN0b3AJAQtjbGFpbVJlc3VsdAEIBQFpBmNhbGxlcgFpAQ1ldmFsdWF0ZUNsYWltAQR1c2VyCQCUCgIFA25pbAgJAQtjbGFpbVJlc3VsdAEJARFAZXh0ck5hdGl2ZSgxMDYyKQEFBHVzZXICXzIBaQETYWRkSW50ZXJlc3RFeHRlcm5hbAAEB2Fzc2V0SWQICQEFdmFsdWUBCQCRAwIIBQFpCHBheW1lbnRzAAAHYXNzZXRJZAQKYXNzZXRJZFN0cgkBDmdldEFzc2V0U3RyaW5nAQUHYXNzZXRJZAQGYW1vdW50CAkAkQMCCAUBaQhwYXltZW50cwAABmFtb3VudAQHc3Rha2VUeAkBDXN0YWtlSWZOZWVkZWQCBQphc3NldElkU3RyBQZhbW91bnQDCQAAAgUHc3Rha2VUeAUHc3Rha2VUeAMJAAACCQDPCAIFCGFzc2V0SWRzBQdhc3NldElkBQR1bml0CQACAQIweW91IGNhbiBvbmx5IGFkZCBpbnRlcmVzdCBmb3IgYXNzZXRzIGluIHRoZSBwb29sBAZwYXJhbXMJARVsb2FkR2xvYmFsVG9rZW5QYXJhbXMBBQphc3NldElkU3RyBA1pbnRlcmVzdERlbHRhCQESY2FsY0ludGVyZXN0Q2hhbmdlAgUKYXNzZXRJZFN0cgUGYW1vdW50BAl1cGRQYXJhbXMJAJoKCAgFBnBhcmFtcwJfMQgFBnBhcmFtcwJfMggFBnBhcmFtcwJfMwkAZAIIBQZwYXJhbXMCXzQFDWludGVyZXN0RGVsdGEJAGQCCAUGcGFyYW1zAl81BQZhbW91bnQIBQZwYXJhbXMCXzYIBQZwYXJhbXMCXzcIBQZwYXJhbXMCXzgJAMwIAgkBFXNhdmVHbG9iYWxUb2tlblBhcmFtcwIFCmFzc2V0SWRTdHIFCXVwZFBhcmFtcwUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBFG5vdGlmeVN0YWtpbmdQYXltZW50Agphc3NldElkU3RyBmFtb3VudAQHYXNzZXRJZAkBDWdldEFzc2V0Qnl0ZXMBBQphc3NldElkU3RyAwkAAAIJAM8IAgUIYXNzZXRJZHMFB2Fzc2V0SWQFBHVuaXQJAAIBAjB5b3UgY2FuIG9ubHkgYWRkIGludGVyZXN0IGZvciBhc3NldHMgaW4gdGhlIHBvb2wDCQECIT0CCQEMdHJ5R2V0U3RyaW5nAQkArAICAhdzdGF0aWNfc3Rha2luZ0NvbnRyYWN0XwUKYXNzZXRJZFN0cgkApQgBCAUBaQZjYWxsZXIJAAIBAiZjYW4gb25seSBiZSBpbnZva2VkIGJ5IHN0YWtlciBjb250cmFjdAQGcGFyYW1zCQEVbG9hZEdsb2JhbFRva2VuUGFyYW1zAQUKYXNzZXRJZFN0cgQNaW50ZXJlc3REZWx0YQkBEmNhbGNJbnRlcmVzdENoYW5nZQIFCmFzc2V0SWRTdHIFBmFtb3VudAQJdXBkUGFyYW1zCQCaCggIBQZwYXJhbXMCXzEIBQZwYXJhbXMCXzIIBQZwYXJhbXMCXzMJAGQCCAUGcGFyYW1zAl80BQ1pbnRlcmVzdERlbHRhCQBkAggFBnBhcmFtcwJfNQUGYW1vdW50CAUGcGFyYW1zAl82CAUGcGFyYW1zAl83CAUGcGFyYW1zAl84CQDMCAIJARVzYXZlR2xvYmFsVG9rZW5QYXJhbXMCBQphc3NldElkU3RyBQl1cGRQYXJhbXMFA25pbAFpAQRzd2FwAghhc3NldE91dAdtaW5pbXVtBANwbXQDCQAAAgkAkAMBCAUBaQhwYXltZW50cwABCQEFdmFsdWUBCQCRAwIIBQFpCHBheW1lbnRzAAAJAAIBAiFwbGVhc2UgYXR0YWNoIGV4YWN0bHkgb25lIHBheW1lbnQECEFtb3VudEluCQEFdmFsdWUBCAkAkQMCCAUBaQhwYXltZW50cwAABmFtb3VudAQHQXNzZXRJbggFA3BtdAdhc3NldElkBAhBc3NldE91dAkBDWdldEFzc2V0Qnl0ZXMBBQhhc3NldE91dAQHYXNzZXRJbgkBDmdldEFzc2V0U3RyaW5nAQUHQXNzZXRJbgQHc2NhbGVJbgkAaQIFBlNjYWxlOAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHc3RhdGljXwUHYXNzZXRJbgIGX3NjYWxlBAhzY2FsZU91dAkAaQIFBlNjYWxlOAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHc3RhdGljXwUIYXNzZXRPdXQCBl9zY2FsZQQNYXNzZXRJblBhcmFtcwkBFWxvYWRHbG9iYWxUb2tlblBhcmFtcwEJAQ5nZXRBc3NldFN0cmluZwEFB0Fzc2V0SW4EDmFzc2V0T3V0UGFyYW1zCQEVbG9hZEdsb2JhbFRva2VuUGFyYW1zAQUIYXNzZXRPdXQEDkFzc2V0SW5CYWxhbmNlCAUNYXNzZXRJblBhcmFtcwJfMQQSQXNzZXRJbkZhY3RCYWxhbmNlCAUNYXNzZXRJblBhcmFtcwJfMgQRYXNzZXRJbkZlZXNFYXJuZWQIBQ1hc3NldEluUGFyYW1zAl8zBBhhc3NldEluTGFzdENoZWNrSW50ZXJlc3QIBQ1hc3NldEluUGFyYW1zAl80BA9Bc3NldE91dEJhbGFuY2UIBQ5hc3NldE91dFBhcmFtcwJfMQQTYXNzZXRPdXRGYWN0QmFsYW5jZQgFDmFzc2V0T3V0UGFyYW1zAl8yBBRBc3NldEluQmFsYW5jZVNjYWxlZAkAaAIFDkFzc2V0SW5CYWxhbmNlBQdzY2FsZUluBBVBc3NldE91dEJhbGFuY2VTY2FsZWQJAGgCBQ9Bc3NldE91dEJhbGFuY2UFCHNjYWxlT3V0BAtmZWVBbW91bnRJbgkAawMFCEFtb3VudEluBQNGZWUFCEZlZVNjYWxlBA1jbGVhbkFtb3VudEluCQBlAgUIQW1vdW50SW4FC2ZlZUFtb3VudEluBBNjbGVhbkFtb3VudEluU2NhbGVkCQBoAgUNY2xlYW5BbW91bnRJbgUHc2NhbGVJbgQKQW1vdW50T3V0MQkBEmNhbGN1bGF0ZU91dEFtb3VudAUFE2NsZWFuQW1vdW50SW5TY2FsZWQFB0Fzc2V0SW4FCEFzc2V0T3V0BRRBc3NldEluQmFsYW5jZVNjYWxlZAUVQXNzZXRPdXRCYWxhbmNlU2NhbGVkBAlBbW91bnRPdXQJAGsDBQpBbW91bnRPdXQxAAEFCHNjYWxlT3V0BBBBc3NldE91dEJhbGFuY2UyCQBlAgUPQXNzZXRPdXRCYWxhbmNlBQlBbW91bnRPdXQED0Fzc2V0SW5CYWxhbmNlMgkAZAIFDkFzc2V0SW5CYWxhbmNlBQ1jbGVhbkFtb3VudEluAwkAZgIFB21pbmltdW0FCUFtb3VudE91dAkAAgECKWFtb3VudCB0byByZWNpZXZlIGlzIGxvd2VyIHRoYW4gZ2l2ZW4gb25lAwkAAAIFCEFzc2V0T3V0BQdBc3NldEluCQACAQIYdGhpcyBzd2FwIGlzIG5vdCBhbGxvd2VkAwkAZgIAAAkAZQIFE2Fzc2V0T3V0RmFjdEJhbGFuY2UFCUFtb3VudE91dAkAAgECG2NvbnRyYWN0IGlzIG91dCBvZiByZXNlcnZlcwMJAQppc1NodXRkb3duAAkAAgECE2NvbnRyYWN0IGlzIG9uIHN0b3ADCQELdmFsdWVPckVsc2UCCQCbCAIFD3Bvb2xzSHViQWRkcmVzcwkArAICAhJnbG9iYWxfc2h1dGRvd25Jbl8FB2Fzc2V0SW4HCQACAQIbdG9rZW4gSU4gdHJhZGVzIGFyZSBzdG9wcGVkAwkBC3ZhbHVlT3JFbHNlAgkAmwgCBQ9wb29sc0h1YkFkZHJlc3MJAKwCAgITZ2xvYmFsX3NodXRkb3duT3V0XwUIYXNzZXRPdXQHCQACAQIcdG9rZW4gT1VUIHRyYWRlcyBhcmUgc3RvcHBlZAQLcHJvdG9jb2xGZWUJAGsDBQtmZWVBbW91bnRJbgAFAAoEBWxwRmVlCQBlAgULZmVlQW1vdW50SW4FC3Byb3RvY29sRmVlBA1pbnRlcmVzdERlbHRhCQESY2FsY0ludGVyZXN0Q2hhbmdlAgUHYXNzZXRJbgUFbHBGZWUEB3N0YWtlVHgJAQ1zdGFrZUlmTmVlZGVkAgUHYXNzZXRJbgkAZAIFDWNsZWFuQW1vdW50SW4FBWxwRmVlAwkAAAIFB3N0YWtlVHgFB3N0YWtlVHgECXVuc3Rha2VUeAkBD3Vuc3Rha2VJZk5lZWRlZAIFCGFzc2V0T3V0BQlBbW91bnRPdXQDCQAAAgUJdW5zdGFrZVR4BQl1bnN0YWtlVHgEDG5ld0JhbGFuY2VJbgUPQXNzZXRJbkJhbGFuY2UyBA1uZXdCYWxhbmNlT3V0BRBBc3NldE91dEJhbGFuY2UyBBJhc3NldEluU2VsbG9mZkRhdGEJAQ51cGRTZWxsb2ZmRGF0YQQFB2Fzc2V0SW4FDWNsZWFuQW1vdW50SW4FDkFzc2V0SW5CYWxhbmNlCQCVCgMIBQ1hc3NldEluUGFyYW1zAl82CAUNYXNzZXRJblBhcmFtcwJfNwgFDWFzc2V0SW5QYXJhbXMCXzgEE2Fzc2V0T3V0U2VsbG9mZkRhdGEJAQ51cGRTZWxsb2ZmRGF0YQQFCGFzc2V0T3V0CQEBLQEFCUFtb3VudE91dAUPQXNzZXRPdXRCYWxhbmNlCQCVCgMIBQ5hc3NldE91dFBhcmFtcwJfNggFDmFzc2V0T3V0UGFyYW1zAl83CAUOYXNzZXRPdXRQYXJhbXMCXzgEEmFzc2V0SW5GaW5hbFBhcmFtcwkAmgoIBQxuZXdCYWxhbmNlSW4JAGQCBRJBc3NldEluRmFjdEJhbGFuY2UFDWNsZWFuQW1vdW50SW4JAGQCBRFhc3NldEluRmVlc0Vhcm5lZAUFbHBGZWUJAGQCBRhhc3NldEluTGFzdENoZWNrSW50ZXJlc3QFDWludGVyZXN0RGVsdGEIBQ1hc3NldEluUGFyYW1zAl81CAUSYXNzZXRJblNlbGxvZmZEYXRhAl8xCAUSYXNzZXRJblNlbGxvZmZEYXRhAl8yCAUSYXNzZXRJblNlbGxvZmZEYXRhAl8zBBNhc3NldE91dEZpbmFsUGFyYW1zCQCaCggFDW5ld0JhbGFuY2VPdXQJAGUCBRNhc3NldE91dEZhY3RCYWxhbmNlBQlBbW91bnRPdXQIBQ5hc3NldE91dFBhcmFtcwJfMwgFDmFzc2V0T3V0UGFyYW1zAl80CAUOYXNzZXRPdXRQYXJhbXMCXzUIBRNhc3NldE91dFNlbGxvZmZEYXRhAl8xCAUTYXNzZXRPdXRTZWxsb2ZmRGF0YQJfMggFE2Fzc2V0T3V0U2VsbG9mZkRhdGECXzMEDWFzc2V0SW5DaGFuZ2UJARVzYXZlR2xvYmFsVG9rZW5QYXJhbXMCBQdhc3NldEluBRJhc3NldEluRmluYWxQYXJhbXMEDmFzc2V0T3V0Q2hhbmdlCQEVc2F2ZUdsb2JhbFRva2VuUGFyYW1zAgUIYXNzZXRPdXQFE2Fzc2V0T3V0RmluYWxQYXJhbXMEC2ZlZUFzc2V0U3RyCQEMdHJ5R2V0U3RyaW5nAQIPc3RhdGljX2ZlZVRva2VuBA5mZWVBc3NldFBhcmFtcwkBFWxvYWRHbG9iYWxUb2tlblBhcmFtcwEFC2ZlZUFzc2V0U3RyBA9mZWVUb2tlbkJhbGFuY2UIBQ5mZWVBc3NldFBhcmFtcwJfMQQPdm9sdW1lVXNkVXBkYXRlCQERY2FsY3VsYXRlVXNkVmFsdWUEBQdBc3NldEluBQhBbW91bnRJbgUOQXNzZXRJbkJhbGFuY2UFD2ZlZVRva2VuQmFsYW5jZQkAlAoCCQDMCAIFDWFzc2V0SW5DaGFuZ2UJAMwIAgUOYXNzZXRPdXRDaGFuZ2UJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyBQlBbW91bnRPdXQFCEFzc2V0T3V0CQDMCAIJAQxJbnRlZ2VyRW50cnkCAhFnbG9iYWxfdm9sdW1lX3VzZAkAZAIJAQ10cnlHZXRJbnRlZ2VyAQIRZ2xvYmFsX3ZvbHVtZV91c2QFD3ZvbHVtZVVzZFVwZGF0ZQkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQtmZWVzQWRkcmVzcwULcHJvdG9jb2xGZWUJAQ1nZXRBc3NldEJ5dGVzAQUHYXNzZXRJbgUDbmlsBQlBbW91bnRPdXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEMc3dhcFJlYWRPbmx5Awdhc3NldEluCGFzc2V0T3V0CEFtb3VudEluBAdBc3NldEluCQENZ2V0QXNzZXRCeXRlcwEFB2Fzc2V0SW4ECEFzc2V0T3V0CQENZ2V0QXNzZXRCeXRlcwEFCGFzc2V0T3V0BAdzY2FsZUluCQBpAgUGU2NhbGU4CQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdzdGF0aWNfBQdhc3NldEluAgZfc2NhbGUECHNjYWxlT3V0CQBpAgUGU2NhbGU4CQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdzdGF0aWNfBQhhc3NldE91dAIGX3NjYWxlBA5mZWVBc3NldE91dFN0cgkBDHRyeUdldFN0cmluZwECD3N0YXRpY19mZWVUb2tlbgQLZmVlQXNzZXRPdXQDCQAAAgUOZmVlQXNzZXRPdXRTdHICAAULdXNkbkFzc2V0SWQJAQ1nZXRBc3NldEJ5dGVzAQUOZmVlQXNzZXRPdXRTdHIEDWFzc2V0SW5QYXJhbXMJARVsb2FkR2xvYmFsVG9rZW5QYXJhbXMBCQEOZ2V0QXNzZXRTdHJpbmcBBQdBc3NldEluBA5hc3NldE91dFBhcmFtcwkBFWxvYWRHbG9iYWxUb2tlblBhcmFtcwEFCGFzc2V0T3V0BA5Bc3NldEluQmFsYW5jZQgFDWFzc2V0SW5QYXJhbXMCXzEEEkFzc2V0SW5GYWN0QmFsYW5jZQgFDWFzc2V0SW5QYXJhbXMCXzIEEWFzc2V0SW5GZWVzRWFybmVkCAUNYXNzZXRJblBhcmFtcwJfMwQYYXNzZXRJbkxhc3RDaGVja0ludGVyZXN0CAUNYXNzZXRJblBhcmFtcwJfNAQPQXNzZXRPdXRCYWxhbmNlCAUOYXNzZXRPdXRQYXJhbXMCXzEEE2Fzc2V0T3V0RmFjdEJhbGFuY2UIBQ5hc3NldE91dFBhcmFtcwJfMgQUQXNzZXRJbkJhbGFuY2VTY2FsZWQJAGgCBQ5Bc3NldEluQmFsYW5jZQUHc2NhbGVJbgQVQXNzZXRPdXRCYWxhbmNlU2NhbGVkCQBoAgUPQXNzZXRPdXRCYWxhbmNlBQhzY2FsZU91dAQLZmVlQW1vdW50SW4JAGsDBQhBbW91bnRJbgUDRmVlBQhGZWVTY2FsZQQNY2xlYW5BbW91bnRJbgkAZQIFCEFtb3VudEluBQtmZWVBbW91bnRJbgQTY2xlYW5BbW91bnRJblNjYWxlZAkAaAIFDWNsZWFuQW1vdW50SW4FB3NjYWxlSW4ECkFtb3VudE91dDEJARJjYWxjdWxhdGVPdXRBbW91bnQFBRNjbGVhbkFtb3VudEluU2NhbGVkBQdBc3NldEluBQhBc3NldE91dAUUQXNzZXRJbkJhbGFuY2VTY2FsZWQFFUFzc2V0T3V0QmFsYW5jZVNjYWxlZAQJQW1vdW50T3V0CQBrAwUKQW1vdW50T3V0MQABBQhzY2FsZU91dAQQQXNzZXRPdXRCYWxhbmNlMgkAZQIFD0Fzc2V0T3V0QmFsYW5jZQUJQW1vdW50T3V0BA9Bc3NldEluQmFsYW5jZTIJAGQCBQ5Bc3NldEluQmFsYW5jZQUNY2xlYW5BbW91bnRJbgMJAAACBQhBc3NldE91dAUHQXNzZXRJbgkAAgECGHRoaXMgc3dhcCBpcyBub3QgYWxsb3dlZAMJAGYCAAAJAGUCCAUOYXNzZXRPdXRQYXJhbXMCXzIFCUFtb3VudE91dAkAAgECG2NvbnRyYWN0IGlzIG91dCBvZiByZXNlcnZlcwMJAQppc1NodXRkb3duAAkAAgECE2NvbnRyYWN0IGlzIG9uIHN0b3AJAJQKAgUDbmlsBQlBbW91bnRPdXQBaQERdHJhbnNmZXJPd25lcnNoaXABD25ld093bmVyQWRkcmVzcwMJAQIhPQIJAKUIAQgFAWkGY2FsbGVyCQEMdHJ5R2V0U3RyaW5nAQIQc3RhdGljX3Bvb2xPd25lcgkAAgECJ3RoaXMgY2FsbCBhdmFpbGFibGUgb25seSBmb3IgcG9vbCBvd25lcgkAzAgCCQELU3RyaW5nRW50cnkCAhBzdGF0aWNfcG9vbE93bmVyBQ9uZXdPd25lckFkZHJlc3MFA25pbAFpAQZzZXRGZWUBBm5ld0ZlZQMJAQIhPQIJAKUIAQgFAWkGY2FsbGVyCQEMdHJ5R2V0U3RyaW5nAQIQc3RhdGljX3Bvb2xPd25lcgkAAgECJ3RoaXMgY2FsbCBhdmFpbGFibGUgb25seSBmb3IgcG9vbCBvd25lcgkAzAgCCQEMSW50ZWdlckVudHJ5AgIKc3RhdGljX2ZlZQUGbmV3RmVlBQNuaWwBAnR4AQZ2ZXJpZnkACQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwAABQxtYXN0ZXJQdWJLZXkdUeiK", "height": 312567, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: none Next: 2gHv2jHHKtpZn6LynKLivuNbM2FiERCfHY7rXJA5nfaw Full:
OldNewDifferences
1-# no script
1+{-# STDLIB_VERSION 6 #-}
2+{-# SCRIPT_TYPE ACCOUNT #-}
3+{-# CONTENT_TYPE DAPP #-}
4+let VERSION = "PZ-3.6.10 PROD-refactor"
5+
6+let configStr = valueOrElse(getString(this, "configAddress"), "3PMoEibdLeWqcURQ8351XhaWwyacDc7G4e5")
7+
8+let CONFIG_ADDRESS = if ((configStr == ""))
9+ then this
10+ else Address(fromBase58String(configStr))
11+
12+let AssetsWeightsDecimals = 4
13+
14+let Scale = 10000
15+
16+let Scale8 = 100000000
17+
18+let Scale12 = 1000000000000
19+
20+let Scale16 = 10000000000000000
21+
22+let FeeScale = 10000
23+
24+let PoolTokenDecimals = 8
25+
26+let PoolTokenScale = pow(10, 0, PoolTokenDecimals, 0, 0, HALFUP)
27+
28+let MIN_STEPS_AMOUNT = valueOrElse(getInteger(CONFIG_ADDRESS, "min_steps_amount"), 1)
29+
30+let MAX_STEPS_AMOUNT = valueOrElse(getInteger(CONFIG_ADDRESS, "max_steps_amount"), 500)
31+
32+let MIN_STEPS_INTERVAL = valueOrElse(getInteger(CONFIG_ADDRESS, "min_steps_interval"), 1)
33+
34+let MAX_STEPS_INTERVAL = valueOrElse(getInteger(CONFIG_ADDRESS, "max_steps_interval"), 10000)
35+
36+let MIN_WEIGHT = valueOrElse(getInteger(CONFIG_ADDRESS, "min_weight"), 100)
37+
38+let MAX_WEIGHT = valueOrElse(getInteger(CONFIG_ADDRESS, "max_weight"), 9900)
39+
40+func tryGetInteger (key) = match getInteger(this, key) {
41+ case b: Int =>
42+ b
43+ case _ =>
44+ 0
45+}
46+
47+
48+func tryGetBinary (key) = match getBinary(this, key) {
49+ case b: ByteVector =>
50+ b
51+ case _ =>
52+ base58''
53+}
54+
55+
56+func tryGetString (key) = match getString(this, key) {
57+ case b: String =>
58+ b
59+ case _ =>
60+ ""
61+}
62+
63+
64+func tryGetStringOrThrow (key) = match getString(this, key) {
65+ case b: String =>
66+ b
67+ case _ =>
68+ throw(("no such key in data storage: " + key))
69+}
70+
71+
72+func getAssetString (assetId) = match assetId {
73+ case b: ByteVector =>
74+ toBase58String(b)
75+ case _ =>
76+ "WAVES"
77+}
78+
79+
80+func getAssetBytes (assetIdStr) = if ((assetIdStr == "WAVES"))
81+ then unit
82+ else fromBase58String(assetIdStr)
83+
84+
85+func getTokenBalance (assetId) = match assetId {
86+ case t: ByteVector =>
87+ assetBalance(this, t)
88+ case _ =>
89+ wavesBalance(this).available
90+}
91+
92+
93+func addAssetBytesToList (accum,item) = (accum ++ [getAssetBytes(item)])
94+
95+
96+func addAssetWeightToList (accum,item) = (accum ++ [tryGetInteger((("static_" + getAssetString(item)) + "_weight"))])
97+
98+
99+func addAssetWeightToStrList (accum,item) = (accum ++ [toString(tryGetInteger((("static_" + item) + "_weight")))])
100+
101+
102+func addAssetDecimalsToList (accum,item) = (accum ++ [tryGetInteger((("static_" + getAssetString(item)) + "_decimals"))])
103+
104+
105+func addAssetScaleToList (accum,item) = (accum ++ [tryGetInteger((("static_" + getAssetString(item)) + "_scale"))])
106+
107+
108+func addIntToList (accum,item) = (accum ++ [parseIntValue(item)])
109+
110+
111+func parstStrToIntList (s) = {
112+ func f (accum,next) = (accum ++ [parseIntValue(next)])
113+
114+ let $l = split(s, ",")
115+ let $s = size($l)
116+ let $acc0 = nil
117+ func $f0_1 ($a,$i) = if (($i >= $s))
118+ then $a
119+ else f($a, $l[$i])
120+
121+ func $f0_2 ($a,$i) = if (($i >= $s))
122+ then $a
123+ else throw("List size exceeds 10")
124+
125+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
126+ }
127+
128+
129+let usdnAssetIdStr = valueOrElse(getString(CONFIG_ADDRESS, "usdnAssetIdStr"), "DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p")
130+
131+let puzzleAssetIdStr = valueOrElse(getString(CONFIG_ADDRESS, "puzzleAssetIdStr"), "HEB8Qaw9xrWpWs8tHsiATYGBWDBtP2S7kcPALrMu43AS")
132+
133+let usdtAssetIdStr = valueOrElse(getString(CONFIG_ADDRESS, "usdtAssetIdStr"), "34N9YcEETLWn93qYQ64EsP1x89tSruJU44RrEMSXXEPJ")
134+
135+let usdtPptAssetIdStr = valueOrElse(getString(CONFIG_ADDRESS, "usdtPptAssetIdStr"), "9wc3LXNA4TEBsXyKtoLE9mrbDD7WMHXvXrCjZvabLAsi")
136+
137+let romeAssetIdStr = valueOrElse(getString(CONFIG_ADDRESS, "romeAssetIdStr"), "AP4Cb5xLYGH6ZigHreCZHoXpQTWDkPsG2BHqfDUx6taJ")
138+
139+let wavesAssetIdStr = "WAVES"
140+
141+let usdnAssetId = fromBase58String(usdnAssetIdStr)
142+
143+let puzzleAssetId = fromBase58String(puzzleAssetIdStr)
144+
145+let usdtAssetId = fromBase58String(usdtAssetIdStr)
146+
147+let usdtPptAssetId = fromBase58String(usdtPptAssetIdStr)
148+
149+let romeAssetId = fromBase58String(romeAssetIdStr)
150+
151+let wavesAssetId = unit
152+
153+let supportedFeeAssetsStr = [usdnAssetIdStr, puzzleAssetIdStr, usdtAssetIdStr, usdtPptAssetIdStr, wavesAssetIdStr, romeAssetIdStr]
154+
155+let parentPoolAddress = Address(fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "parentPoolAddress"), "3PFDgzu1UtswAkCMxqqQjbTeHaX4cMab8Kh")))
156+
157+let masterAddress = Address(fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "masterAddress"), "3PLjwHcz9NEuaTo63NZR9B9okQiKQxZSbmf")))
158+
159+let masterPubKey = fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "masterPubKey"), "2jTJGqHSopyj5d1cjbUe6f2jXqGMHE412cy3vGwYoRbP"))
160+
161+let oracleAddress = Address(fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "oracleAddress"), "3P8d1E1BLKoD52y3bQJ1bDTd2TD1gpaLn9t")))
162+
163+let stakingAddress = Address(fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "stakingAddress"), "3PFTbywqxtFfukX3HyT881g4iW5K4QL3FAS")))
164+
165+let feesAddress = Address(fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "feesAddress"), "3PFWAVKmXjfHXyzJb12jCbhP4Uhi9t4uWiD")))
166+
167+let poolsHubAddress = Address(fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "poolsHubAddress"), "3P5RGYyCnELF8JTPxgX54dBGzwkQMKUJ5H7")))
168+
169+let shutdownAddressStr = valueOrElse(getString(CONFIG_ADDRESS, "shutdownAddress"), "3PEpv9hRFWEEBU22WRnLsw1bH4YGtcU728o")
170+
171+let layer2Addresses = valueOrElse(getString(CONFIG_ADDRESS, "layer2Addresses"), "3PR1Qvi9mHT35SwWEkLSqqE2L8thiPLdVWU,3PQoBfUKHkJAeGWhooLP7WS8ovb54av9Jp2")
172+
173+let govAddress = Address(fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "govAddress"), "3P6uro9xCsE8te78QZjzqy7aq8natSzdceC")))
174+
175+let coldMasterAddress = Address(fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "coldMasterAddress"), "3PK9nhPfPbMBygB9ZgHVMHaQbSoojwrBfxj")))
176+
177+let T = tryGetInteger("static_tokensAmount")
178+
179+let assetIds = {
180+ let $l = split(tryGetString("static_tokenIds"), ",")
181+ let $s = size($l)
182+ let $acc0 = nil
183+ func $f0_1 ($a,$i) = if (($i >= $s))
184+ then $a
185+ else addAssetBytesToList($a, $l[$i])
186+
187+ func $f0_2 ($a,$i) = if (($i >= $s))
188+ then $a
189+ else throw("List size exceeds 10")
190+
191+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
192+ }
193+
194+let AssetsWeights = {
195+ let $l = assetIds
196+ let $s = size($l)
197+ let $acc0 = nil
198+ func $f1_1 ($a,$i) = if (($i >= $s))
199+ then $a
200+ else addAssetWeightToList($a, $l[$i])
201+
202+ func $f1_2 ($a,$i) = if (($i >= $s))
203+ then $a
204+ else throw("List size exceeds 10")
205+
206+ $f1_2($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)
207+ }
208+
209+let Decimals = {
210+ let $l = assetIds
211+ let $s = size($l)
212+ let $acc0 = nil
213+ func $f2_1 ($a,$i) = if (($i >= $s))
214+ then $a
215+ else addAssetDecimalsToList($a, $l[$i])
216+
217+ func $f2_2 ($a,$i) = if (($i >= $s))
218+ then $a
219+ else throw("List size exceeds 10")
220+
221+ $f2_2($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
222+ }
223+
224+let Scales = {
225+ let $l = assetIds
226+ let $s = size($l)
227+ let $acc0 = nil
228+ func $f3_1 ($a,$i) = if (($i >= $s))
229+ then $a
230+ else addAssetScaleToList($a, $l[$i])
231+
232+ func $f3_2 ($a,$i) = if (($i >= $s))
233+ then $a
234+ else throw("List size exceeds 10")
235+
236+ $f3_2($f3_1($f3_1($f3_1($f3_1($f3_1($f3_1($f3_1($f3_1($f3_1($f3_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
237+ }
238+
239+let Fee = tryGetInteger("static_fee")
240+
241+let earnedAssets = assetIds
242+
243+func _get (assetId,param) = tryGetInteger(((("global_" + assetId) + "_") + param))
244+
245+
246+func _get_feesEarned (assetId) = tryGetInteger(("global_feesEarned_" + assetId))
247+
248+
249+func _get_lastCheck_interest (assetId) = tryGetInteger((("global_lastCheck_" + assetId) + "_interest"))
250+
251+
252+func _get_extraEarned (assetId) = tryGetInteger(("global_extraEarned_" + assetId))
253+
254+
255+func loadGlobalTokenParams (assetId) = match getString(("globalParams_" + assetId)) {
256+ case p: String =>
257+ let params = split(p, "__")
258+ $Tuple8(parseIntValue(params[0]), parseIntValue(params[1]), parseIntValue(params[2]), parseIntValue(params[3]), parseIntValue(params[4]), parseIntValue(params[5]), parseIntValue(params[6]), parseIntValue(params[7]))
259+ case _ =>
260+ $Tuple8(_get(assetId, "balance"), _get(assetId, "factBalance"), _get_feesEarned(assetId), _get_lastCheck_interest(assetId), _get_extraEarned(assetId), _get(assetId, "selloff"), _get(assetId, "selloffStartBalance"), _get(assetId, "selloffStartHeight"))
261+}
262+
263+
264+func saveGlobalTokenParams (assetId,params) = StringEntry(("globalParams_" + assetId), makeString([toString(params._1), toString(params._2), toString(params._3), toString(params._4), toString(params._5), toString(params._6), toString(params._7), toString(params._8)], "__"))
265+
266+
267+func isShutdown () = {
268+ let shutdownAddress = addressFromString(shutdownAddressStr)
269+ if ((shutdownAddress == unit))
270+ then false
271+ else match getBoolean(value(shutdownAddress), "is_shutdown") {
272+ case x: Boolean =>
273+ x
274+ case _ =>
275+ false
276+ }
277+ }
278+
279+
280+func getFactBalance (assetIdStr) = {
281+ let assetParams = loadGlobalTokenParams(assetIdStr)
282+ assetParams._2
283+ }
284+
285+
286+func getCurrentTokenBalance (tokenNum) = {
287+ let tokenIdStr = getAssetString(assetIds[tokenNum])
288+ let tokenParams = loadGlobalTokenParams(tokenIdStr)
289+ tokenParams._1
290+ }
291+
292+
293+func stakeIfNeeded (assetIdStr,amount) = {
294+ let stakeTx = if ((tryGetString(("static_stakingContract_" + assetIdStr)) != ""))
295+ then invoke(addressFromStringValue(tryGetString(("static_stakingContract_" + assetIdStr))), "stake", nil, [AttachedPayment(getAssetBytes(assetIdStr), amount)])
296+ else unit
297+ if ((stakeTx == stakeTx))
298+ then true
299+ else throw("Strict value is not equal to itself.")
300+ }
301+
302+
303+func unstakeIfNeeded (assetIdStr,amount) = {
304+ let unstakeTx = if ((tryGetString(("static_stakingContract_" + assetIdStr)) != ""))
305+ then invoke(addressFromStringValue(tryGetString(("static_stakingContract_" + assetIdStr))), "unstake", [amount], nil)
306+ else unit
307+ if ((unstakeTx == unstakeTx))
308+ then true
309+ else throw("Strict value is not equal to itself.")
310+ }
311+
312+
313+func burnIndexIfNeeded (amount) = {
314+ let indexIdStr = tryGetString("static_poolToken_idStr")
315+ if ((indexIdStr == ""))
316+ then nil
317+ else if ((assetInfo(fromBase58String(indexIdStr)) == unit))
318+ then nil
319+ else [Burn(fromBase58String(indexIdStr), amount)]
320+ }
321+
322+
323+func mintIndexIfNeeded (amount) = {
324+ let indexIdStr = tryGetString("static_poolToken_idStr")
325+ if ((indexIdStr == ""))
326+ then nil
327+ else if ((assetInfo(fromBase58String(indexIdStr)) == unit))
328+ then nil
329+ else [Reissue(fromBase58String(indexIdStr), amount, true)]
330+ }
331+
332+
333+func getKMult () = match getInteger("static_KMult") {
334+ case x: Int =>
335+ x
336+ case _ =>
337+ Scale16
338+}
339+
340+
341+func saveCurrentWeights () = {
342+ let assetIdsLi = split(tryGetString("static_tokenIds"), ",")
343+ func s (accum,assetId) = (accum ++ [IntegerEntry(("rebalance_startWeight_" + assetId), tryGetInteger((("static_" + assetId) + "_weight")))])
344+
345+ let $l = assetIdsLi
346+ let $s = size($l)
347+ let $acc0 = nil
348+ func $f4_1 ($a,$i) = if (($i >= $s))
349+ then $a
350+ else s($a, $l[$i])
351+
352+ func $f4_2 ($a,$i) = if (($i >= $s))
353+ then $a
354+ else throw("List size exceeds 10")
355+
356+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
357+ }
358+
359+
360+func getVirtualPoolTokenAmount () = fraction(tryGetInteger("global_poolToken_amount"), getKMult(), Scale16)
361+
362+
363+func calculatePIssued (amount,tokenId) = {
364+ let Psupply = getVirtualPoolTokenAmount()
365+ let Balance = getFactBalance(getAssetString(tokenId))
366+ let t1 = fraction(amount, Psupply, Balance, DOWN)
367+ t1
368+ }
369+
370+
371+func getMinPIssued (payments) = {
372+ func handler (accum,current) = if ((getFactBalance(getAssetString(current.assetId)) == 0))
373+ then accum
374+ else {
375+ let PIssued = calculatePIssued(current.amount, current.assetId)
376+ if ((PIssued == 0))
377+ then throw("one of the tokens amounts is too low")
378+ else if (if ((accum == 0))
379+ then true
380+ else (accum > PIssued))
381+ then PIssued
382+ else accum
383+ }
384+
385+ let minPIssed = {
386+ let $l = payments
387+ let $s = size($l)
388+ let $acc0 = 0
389+ func $f4_1 ($a,$i) = if (($i >= $s))
390+ then $a
391+ else handler($a, $l[$i])
392+
393+ func $f4_2 ($a,$i) = if (($i >= $s))
394+ then $a
395+ else throw("List size exceeds 10")
396+
397+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
398+ }
399+ minPIssed
400+ }
401+
402+
403+func getPriceFromOracle (assetIdStr) = match getInteger(oracleAddress, (assetIdStr + "_twap5B")) {
404+ case x: Int =>
405+ x
406+ case _ =>
407+ 0
408+}
409+
410+
411+func calculateUsdValue (assetId,amount,aBalance,feeAssetBalance) = {
412+ let assetWeight = tryGetInteger((("static_" + getAssetString(assetId)) + "_weight"))
413+ let feeAssetStr = tryGetString("static_feeToken")
414+ let feeAssetScale = getIntegerValue(this, (("static_" + feeAssetStr) + "_scale"))
415+ let feeAssetNum = value(indexOf(assetIds, getAssetBytes(feeAssetStr)))
416+ let feeAssetWeight = AssetsWeights[feeAssetNum]
417+ let valInFeeAsset = fraction(amount, (feeAssetBalance / feeAssetWeight), (aBalance / assetWeight))
418+ let feeAssetPrice = getPriceFromOracle(feeAssetStr)
419+ fraction(valInFeeAsset, feeAssetPrice, feeAssetScale)
420+ }
421+
422+
423+func calcAvgConcentration () = {
424+ func f (accum,next) = {
425+ let assetIdStr = getAssetString(next)
426+ let weight = tryGetInteger((("static_" + assetIdStr) + "_weight"))
427+ let assetParams = loadGlobalTokenParams(assetIdStr)
428+ let assetFactBalance = assetParams._2
429+ let assetVirtBalance = assetParams._1
430+ $Tuple2((accum._1 + fraction(assetFactBalance, weight, assetVirtBalance)), (accum._2 + weight))
431+ }
432+
433+ let $l = assetIds
434+ let $s = size($l)
435+ let $acc0 = $Tuple2(0, 0)
436+ func $f4_1 ($a,$i) = if (($i >= $s))
437+ then $a
438+ else f($a, $l[$i])
439+
440+ func $f4_2 ($a,$i) = if (($i >= $s))
441+ then $a
442+ else throw("List size exceeds 10")
443+
444+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
445+ }
446+
447+
448+func checkTokensValidity (payments) = {
449+ func handler1 (accum,payment) = (accum ++ [payment.assetId])
450+
451+ let ids = {
452+ let $l = payments
453+ let $s = size($l)
454+ let $acc0 = nil
455+ func $f4_1 ($a,$i) = if (($i >= $s))
456+ then $a
457+ else handler1($a, $l[$i])
458+
459+ func $f4_2 ($a,$i) = if (($i >= $s))
460+ then $a
461+ else throw("List size exceeds 10")
462+
463+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
464+ }
465+ if ((ids == ids))
466+ then {
467+ func handler2 (accum,assetId) = if ((indexOf(ids, assetId) != unit))
468+ then (accum + 1)
469+ else throw(("asset not attached: " + getAssetString(assetId)))
470+
471+ let checks = {
472+ let $l = assetIds
473+ let $s = size($l)
474+ let $acc0 = 0
475+ func $f5_1 ($a,$i) = if (($i >= $s))
476+ then $a
477+ else handler2($a, $l[$i])
478+
479+ func $f5_2 ($a,$i) = if (($i >= $s))
480+ then $a
481+ else throw("List size exceeds 10")
482+
483+ $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
484+ }
485+ if ((checks == checks))
486+ then true
487+ else throw("Strict value is not equal to itself.")
488+ }
489+ else throw("Strict value is not equal to itself.")
490+ }
491+
492+
493+func handlePoolTokensAdd (PIssued,payments,userAddress,needChange) = {
494+ func getTokenPaymentAmount (tokenId) = {
495+ func handler (accum,payment) = if ((payment.assetId == tokenId))
496+ then payment.amount
497+ else accum
498+
499+ let $l = payments
500+ let $s = size($l)
501+ let $acc0 = 0
502+ func $f4_1 ($a,$i) = if (($i >= $s))
503+ then $a
504+ else handler($a, $l[$i])
505+
506+ func $f4_2 ($a,$i) = if (($i >= $s))
507+ then $a
508+ else throw("List size exceeds 10")
509+
510+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
511+ }
512+
513+ func handleTokenChange (accum,tokenId) = {
514+ let assetIdStr = getAssetString(tokenId)
515+ let assetParams = loadGlobalTokenParams(assetIdStr)
516+ let paymentAmount = getTokenPaymentAmount(tokenId)
517+ let Bk = assetParams._2
518+ let PSupply = getVirtualPoolTokenAmount()
519+ let tokenDecimals = tryGetInteger((("static_" + assetIdStr) + "_scale"))
520+ let a1 = fraction((toBigInt((PSupply + PIssued)) * toBigInt(Scale8)), toBigInt(tokenDecimals), toBigInt(PSupply), CEILING)
521+ let Dk = toInt(fraction((a1 - (toBigInt(tokenDecimals) * toBigInt(Scale8))), toBigInt(Bk), (toBigInt(tokenDecimals) * toBigInt(Scale8)), CEILING))
522+ let toReturn = (paymentAmount - Dk)
523+ let stakeTx = stakeIfNeeded(assetIdStr, Dk)
524+ if ((stakeTx == stakeTx))
525+ then {
526+ let t = if (if (needChange)
527+ then (toReturn > 0)
528+ else false)
529+ then [ScriptTransfer(userAddress, toReturn, tokenId)]
530+ else nil
531+ let selloffStartBalance = if ((assetParams._8 != ((height / 100) * 100)))
532+ then assetParams._7
533+ else fraction(assetParams._7, (PSupply + PIssued), PSupply)
534+ let assetParamsUpd = $Tuple8(fraction(assetParams._1, (PSupply + PIssued), PSupply), (assetParams._2 + Dk), assetParams._3, assetParams._4, assetParams._5, assetParams._6, selloffStartBalance, assetParams._8)
535+ ((accum ++ t) ++ [saveGlobalTokenParams(assetIdStr, assetParamsUpd)])
536+ }
537+ else throw("Strict value is not equal to itself.")
538+ }
539+
540+ let $l = assetIds
541+ let $s = size($l)
542+ let $acc0 = nil
543+ func $f4_1 ($a,$i) = if (($i >= $s))
544+ then $a
545+ else handleTokenChange($a, $l[$i])
546+
547+ func $f4_2 ($a,$i) = if (($i >= $s))
548+ then $a
549+ else throw("List size exceeds 10")
550+
551+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
552+ }
553+
554+
555+func calcMintedWithOneToken (assetAddedIdStr,amount) = {
556+ let PSupply = getVirtualPoolTokenAmount()
557+ let assetParams = loadGlobalTokenParams(assetAddedIdStr)
558+ let assetFactBalance = assetParams._2
559+ let assetVirtBalance = assetParams._1
560+ let assetWeight = tryGetInteger((("static_" + assetAddedIdStr) + "_weight"))
561+ let assetScale = tryGetInteger((("static_" + assetAddedIdStr) + "_scale"))
562+ let assetDecimals = tryGetInteger((("static_" + assetAddedIdStr) + "_decimals"))
563+ let PIssuedNoMultiplier = fraction(PSupply, (toInt(pow(toBigInt((assetScale + fraction(amount, assetScale, assetVirtBalance))), assetDecimals, toBigInt(assetWeight), 4, 8, DOWN)) - Scale8), Scale8)
564+ let avgConc = calcAvgConcentration()
565+ let PIssued = fraction(PIssuedNoMultiplier, avgConc._2, avgConc._1)
566+ let assetParamsUpd = $Tuple8((assetVirtBalance + amount), (assetFactBalance + amount), assetParams._3, assetParams._4, assetParams._5, assetParams._6, assetParams._7, assetParams._8)
567+ $Tuple2([saveGlobalTokenParams(assetAddedIdStr, assetParamsUpd)], PIssued)
568+ }
569+
570+
571+func calcRedeemWithOneToken (assetOutIdStr,PRedeemed) = {
572+ let PSupply = getVirtualPoolTokenAmount()
573+ let assetParams = loadGlobalTokenParams(assetOutIdStr)
574+ let assetFactBalance = assetParams._2
575+ let assetVirtBalance = assetParams._1
576+ let assetWeight = tryGetInteger((("static_" + assetOutIdStr) + "_weight"))
577+ let assetScale = tryGetInteger((("static_" + assetOutIdStr) + "_scale"))
578+ let assetDecimals = tryGetInteger((("static_" + assetOutIdStr) + "_decimals"))
579+ let amountOutNoMulitplier = fraction(assetVirtBalance, (Scale8 - toInt(pow(toBigInt((assetScale - fraction(PRedeemed, assetScale, PSupply))), assetDecimals, toBigInt(fraction(10000, 10000, assetWeight)), 4, 8, DOWN))), Scale8)
580+ let avgConc = calcAvgConcentration()
581+ let amountOut = fraction(amountOutNoMulitplier, avgConc._1, avgConc._2)
582+ if ((amountOut > assetFactBalance))
583+ then throw("no available fact liquidity to withdraw in one token")
584+ else {
585+ let assetParamsUpd = $Tuple8((assetVirtBalance - amountOut), (assetFactBalance - amountOut), assetParams._3, assetParams._4, assetParams._5, assetParams._6, assetParams._7, assetParams._8)
586+ $Tuple2([saveGlobalTokenParams(assetOutIdStr, assetParamsUpd)], amountOut)
587+ }
588+ }
589+
590+
591+func handlePoolTokensRedeem (PRedeemed,userAddress) = {
592+ func handleTokenRedeem (accum,tokenId) = {
593+ let assetIdStr = getAssetString(tokenId)
594+ let assetParams = loadGlobalTokenParams(assetIdStr)
595+ let Bk = assetParams._2
596+ let PSupply = getVirtualPoolTokenAmount()
597+ let tokenDecimals = tryGetInteger((("static_" + assetIdStr) + "_scale"))
598+ let psuppl = fraction((toBigInt((PSupply - PRedeemed)) * toBigInt(Scale8)), toBigInt(Scale8), toBigInt(PSupply), DOWN)
599+ let amount = toInt(fraction((toBigInt(Scale16) - psuppl), toBigInt(Bk), toBigInt(Scale16), CEILING))
600+ let unstakeTx = unstakeIfNeeded(assetIdStr, amount)
601+ if ((unstakeTx == unstakeTx))
602+ then {
603+ let selloffStartBalance = if ((assetParams._8 != ((height / 100) * 100)))
604+ then assetParams._7
605+ else fraction(assetParams._7, (PSupply - PRedeemed), PSupply)
606+ let assetParamsUpd = $Tuple8(fraction(assetParams._1, (PSupply - PRedeemed), PSupply), (assetParams._2 - amount), assetParams._3, assetParams._4, assetParams._5, assetParams._6, selloffStartBalance, assetParams._8)
607+ ((accum ++ [ScriptTransfer(userAddress, amount, tokenId)]) ++ [saveGlobalTokenParams(assetIdStr, assetParamsUpd)])
608+ }
609+ else throw("Strict value is not equal to itself.")
610+ }
611+
612+ let $l = assetIds
613+ let $s = size($l)
614+ let $acc0 = nil
615+ func $f4_1 ($a,$i) = if (($i >= $s))
616+ then $a
617+ else handleTokenRedeem($a, $l[$i])
618+
619+ func $f4_2 ($a,$i) = if (($i >= $s))
620+ then $a
621+ else throw("List size exceeds 10")
622+
623+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
624+ }
625+
626+
627+func calculateOutAmount (AmountIn,assetIn,assetOut,BalanceIn,BalanceOut) = {
628+ let IndexIn = value(indexOf(assetIds, assetIn))
629+ let IndexOut = value(indexOf(assetIds, assetOut))
630+ if ((IndexIn == IndexOut))
631+ then AmountIn
632+ else fraction(BalanceOut, ((Scale8 * Scale8) - toInt(pow(fraction((toBigInt(BalanceIn) * toBigInt(10000)), toBigInt((Scale8 * Scale8)), (toBigInt((BalanceIn + AmountIn)) * toBigInt(10000)), HALFUP), 16, toBigInt(fraction(AssetsWeights[IndexIn], 1000000000000, AssetsWeights[IndexOut])), 12, 16, CEILING))), (Scale8 * Scale8), HALFEVEN)
633+ }
634+
635+
636+func claimResult (address) = {
637+ let addressStr = toString(address)
638+ let indexAmount = tryGetInteger((addressStr + "_indexStaked"))
639+ let feeAssetStr = tryGetString("static_feeToken")
640+ let feeAssetParams = loadGlobalTokenParams(feeAssetStr)
641+ let feeTokenBalance = feeAssetParams._1
642+ func handler (accum,assetId) = {
643+ let assetIdStr = getAssetString(assetId)
644+ let assetParams = loadGlobalTokenParams(assetIdStr)
645+ let currentTokenInterest = assetParams._4
646+ let aBalance = assetParams._1
647+ let rewardAmount = fraction(indexAmount, (currentTokenInterest - tryGetInteger((((addressStr + "_lastCheck_") + assetIdStr) + "_interest"))), Scale16)
648+ let unstakeInv = unstakeIfNeeded(assetIdStr, rewardAmount)
649+ if ((unstakeInv == unstakeInv))
650+ then {
651+ let transfer = if ((rewardAmount == 0))
652+ then nil
653+ else [ScriptTransfer(address, rewardAmount, assetId)]
654+ $Tuple2(((accum._1 ++ transfer) ++ [IntegerEntry((((addressStr + "_lastCheck_") + assetIdStr) + "_interest"), currentTokenInterest)]), (accum._2 + calculateUsdValue(assetId, rewardAmount, aBalance, feeTokenBalance)))
655+ }
656+ else throw("Strict value is not equal to itself.")
657+ }
658+
659+ let accum = {
660+ let $l = earnedAssets
661+ let $s = size($l)
662+ let $acc0 = $Tuple2(nil, 0)
663+ func $f4_1 ($a,$i) = if (($i >= $s))
664+ then $a
665+ else handler($a, $l[$i])
666+
667+ func $f4_2 ($a,$i) = if (($i >= $s))
668+ then $a
669+ else throw("List size exceeds 10")
670+
671+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
672+ }
673+ $Tuple2((accum._1 ++ [IntegerEntry((addressStr + "_claimedRewardUSD"), (tryGetInteger((addressStr + "_claimedRewardUSD")) + accum._2)), IntegerEntry((addressStr + "_lastClaim"), lastBlock.timestamp)]), accum._2)
674+ }
675+
676+
677+func indexStakeResult (addressStr,amount) = {
678+ let li = claimResult(addressFromStringValue(addressStr))._1
679+ (li ++ [IntegerEntry((addressStr + "_indexStaked"), (tryGetInteger((addressStr + "_indexStaked")) + amount)), IntegerEntry("global_indexStaked", (tryGetInteger("global_indexStaked") + amount))])
680+ }
681+
682+
683+func sum (accum,n) = (accum + parseIntValue(n))
684+
685+
686+func checkFeeAsset (accum,next) = if (if ((indexOf(supportedFeeAssetsStr, next) != unit))
687+ then (accum == "")
688+ else false)
689+ then next
690+ else accum
691+
692+
693+func calcInterestChange (assetIdStr,lpFee) = {
694+ let totalIndex = tryGetInteger("global_indexStaked")
695+ let interestDelta = fraction(lpFee, Scale16, totalIndex)
696+ interestDelta
697+ }
698+
699+
700+func updSelloffData (assetIdStr,amountIn,balance,selloffParams) = {
701+ let currentPeriod = ((height / 100) * 100)
702+ let prevPeriod = selloffParams._2
703+ let prevSelloff = if ((currentPeriod == prevPeriod))
704+ then selloffParams._1
705+ else 0
706+ let selloffStartBalance = if ((currentPeriod == prevPeriod))
707+ then selloffParams._3
708+ else balance
709+ let selloffDelta = fraction(Scale16, amountIn, selloffStartBalance)
710+ let maxSelloff = tryGetInteger((("static_" + assetIdStr) + "_maxSelloff"))
711+ if (if (((prevSelloff + selloffDelta) > maxSelloff))
712+ then (maxSelloff != 0)
713+ else false)
714+ then throw(("max selloff reached for this asset " + assetIdStr))
715+ else {
716+ let startH = if ((currentPeriod == prevPeriod))
717+ then prevPeriod
718+ else currentPeriod
719+ let startB = if ((currentPeriod == prevPeriod))
720+ then selloffParams._3
721+ else selloffStartBalance
722+ $Tuple3((prevSelloff + selloffDelta), startH, startB)
723+ }
724+ }
725+
726+
727+func getTmpRebalanceIds (newAssetIdsLi) = {
728+ let currentAssetIdsLi = split(tryGetString("static_tokenIds"), ",")
729+ let result = newAssetIdsLi
730+ func f (accum,assetId) = if ((indexOf(result, assetId) == unit))
731+ then (accum ++ [assetId])
732+ else accum
733+
734+ let $l = currentAssetIdsLi
735+ let $s = size($l)
736+ let $acc0 = result
737+ func $f4_1 ($a,$i) = if (($i >= $s))
738+ then $a
739+ else f($a, $l[$i])
740+
741+ func $f4_2 ($a,$i) = if (($i >= $s))
742+ then $a
743+ else throw("List size exceeds 10")
744+
745+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
746+ }
747+
748+
749+func checkTokensChange (newAssetIdsLi) = {
750+ let currentAssetIdsLi = split(tryGetString("static_tokenIds"), ",")
751+ func rem (accum,assetId) = if ((indexOf(newAssetIdsLi, assetId) == unit))
752+ then (accum + 1)
753+ else accum
754+
755+ func add (accum,assetId) = if ((indexOf(currentAssetIdsLi, assetId) == unit))
756+ then (accum + 1)
757+ else accum
758+
759+ let removed = {
760+ let $l = currentAssetIdsLi
761+ let $s = size($l)
762+ let $acc0 = 0
763+ func $f4_1 ($a,$i) = if (($i >= $s))
764+ then $a
765+ else rem($a, $l[$i])
766+
767+ func $f4_2 ($a,$i) = if (($i >= $s))
768+ then $a
769+ else throw("List size exceeds 10")
770+
771+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
772+ }
773+ let added = {
774+ let $l = newAssetIdsLi
775+ let $s = size($l)
776+ let $acc0 = 0
777+ func $f5_1 ($a,$i) = if (($i >= $s))
778+ then $a
779+ else add($a, $l[$i])
780+
781+ func $f5_2 ($a,$i) = if (($i >= $s))
782+ then $a
783+ else throw("List size exceeds 10")
784+
785+ $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
786+ }
787+ (removed + added)
788+ }
789+
790+
791+func validatePayments (assetsList,payments) = {
792+ func getPaymentAssets (accum,next) = if ((0 >= next.amount))
793+ then throw(((("Too low payment amount for " + getAssetString(next.assetId)) + ": ") + toString(next.amount)))
794+ else (accum ++ [getAssetString(next.assetId)])
795+
796+ let paymentList = {
797+ let $l = payments
798+ let $s = size($l)
799+ let $acc0 = nil
800+ func $f4_1 ($a,$i) = if (($i >= $s))
801+ then $a
802+ else getPaymentAssets($a, $l[$i])
803+
804+ func $f4_2 ($a,$i) = if (($i >= $s))
805+ then $a
806+ else throw("List size exceeds 10")
807+
808+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
809+ }
810+ func f1 (accum,next) = if ((indexOf(assetsList, next) == unit))
811+ then throw(((next + " asset is present in payments, but is not in new assets: ") + makeString(assetsList, ",")))
812+ else (accum + 1)
813+
814+ func f2 (accum,next) = if ((indexOf(paymentList, next) == unit))
815+ then throw(((next + " asset is present in new assets, but is not in payments: ") + makeString(paymentList, ",")))
816+ else (accum + 1)
817+
818+ let a1 = {
819+ let $l = paymentList
820+ let $s = size($l)
821+ let $acc0 = 0
822+ func $f5_1 ($a,$i) = if (($i >= $s))
823+ then $a
824+ else f1($a, $l[$i])
825+
826+ func $f5_2 ($a,$i) = if (($i >= $s))
827+ then $a
828+ else throw("List size exceeds 10")
829+
830+ $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
831+ }
832+ let a2 = {
833+ let $l = assetsList
834+ let $s = size($l)
835+ let $acc0 = 0
836+ func $f6_1 ($a,$i) = if (($i >= $s))
837+ then $a
838+ else f2($a, $l[$i])
839+
840+ func $f6_2 ($a,$i) = if (($i >= $s))
841+ then $a
842+ else throw("List size exceeds 10")
843+
844+ $f6_2($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
845+ }
846+ (a1 + a2)
847+ }
848+
849+
850+func validateWeights (weights) = {
851+ func v (accum,w) = {
852+ let wInt = valueOrErrorMessage(parseInt(w), ("Wrong weight format: " + w))
853+ if (if ((MIN_WEIGHT > wInt))
854+ then true
855+ else (wInt > MAX_WEIGHT))
856+ then throw(((((("Weight should be in range " + toString(MIN_WEIGHT)) + " - ") + toString(MAX_WEIGHT)) + ", current: ") + w))
857+ else (accum + wInt)
858+ }
859+
860+ let $l = weights
861+ let $s = size($l)
862+ let $acc0 = 0
863+ func $f4_1 ($a,$i) = if (($i >= $s))
864+ then $a
865+ else v($a, $l[$i])
866+
867+ func $f4_2 ($a,$i) = if (($i >= $s))
868+ then $a
869+ else throw("List size exceeds 10")
870+
871+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
872+ }
873+
874+
875+func getP1P2 (assetIdStr,baseAssetIdStr) = {
876+ let assetParams = loadGlobalTokenParams(assetIdStr)
877+ let baseAssetParams = loadGlobalTokenParams(baseAssetIdStr)
878+ let B1 = baseAssetParams._1
879+ let B2 = assetParams._1
880+ let F1 = baseAssetParams._2
881+ let F2 = assetParams._2
882+ let S1 = tryGetInteger((("static_" + baseAssetIdStr) + "_scale"))
883+ let S2 = tryGetInteger((("static_" + assetIdStr) + "_scale"))
884+ let D1 = tryGetInteger((("static_" + baseAssetIdStr) + "_decimals"))
885+ let D2 = tryGetInteger((("static_" + assetIdStr) + "_decimals"))
886+ let W1 = tryGetInteger((("static_" + baseAssetIdStr) + "_weight"))
887+ let W2 = tryGetInteger((("static_" + assetIdStr) + "_weight"))
888+ let W1W2 = fraction(W1, 10000, W2)
889+ let W2W1 = fraction(W2, 10000, W1)
890+ let p1_unweighted = fraction((B1 - F1), S1, fraction(B2, pow(fraction(B1, S1, (B1 - F1)), D1, W1W2, 4, D1, CEILING), S2))
891+ let p1 = fraction(p1_unweighted, W2W1, 10000)
892+ if ((B2 == F2))
893+ then $Tuple2(p1, unit)
894+ else {
895+ let p2_unweighted = fraction(fraction(B1, pow(fraction(B2, S2, (B2 - F2)), D2, W2W1, 4, D2, FLOOR), S2), S2, (B2 - F2))
896+ let p2 = fraction(p2_unweighted, W2W1, 10000)
897+ $Tuple2(p1, p2)
898+ }
899+ }
900+
901+
902+@Callable(i)
903+func addUnderlyingStaker (stakerAddress,assetIdStr) = if ((this != i.caller))
904+ then throw("admin only")
905+ else [StringEntry(("static_stakingContract_" + assetIdStr), stakerAddress)]
906+
907+
908+
909+@Callable(i)
910+func preInit (assetIdsStr,assetWeightsStr,assetMaxSelloffStr,baseTokenIdStr,poolDomain,poolOwner,fee) = {
911+ let poolOwnerAddress = addressFromStringValue(poolOwner)
912+ let assetIdsStrLi = split(assetIdsStr, ",")
913+ let assetMaxSelloffStrLi = split(assetMaxSelloffStr, ",")
914+ let assetWeightsStrLi = split(assetWeightsStr, ",")
915+ let assetIdsLi = {
916+ let $l = assetIdsStrLi
917+ let $s = size($l)
918+ let $acc0 = nil
919+ func $f4_1 ($a,$i) = if (($i >= $s))
920+ then $a
921+ else addAssetBytesToList($a, $l[$i])
922+
923+ func $f4_2 ($a,$i) = if (($i >= $s))
924+ then $a
925+ else throw("List size exceeds 10")
926+
927+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
928+ }
929+ let feeAssetChosenStr = {
930+ let $l = assetIdsStrLi
931+ let $s = size($l)
932+ let $acc0 = ""
933+ func $f5_1 ($a,$i) = if (($i >= $s))
934+ then $a
935+ else checkFeeAsset($a, $l[$i])
936+
937+ func $f5_2 ($a,$i) = if (($i >= $s))
938+ then $a
939+ else throw("List size exceeds 10")
940+
941+ $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
942+ }
943+ let feeAssetStr = if ((feeAssetChosenStr == ""))
944+ then baseTokenIdStr
945+ else feeAssetChosenStr
946+ if (isShutdown())
947+ then throw("contract is on stop")
948+ else if ((this != i.caller))
949+ then throw("admin only")
950+ else if ((size(poolDomain) > 13))
951+ then throw("too large pool domain")
952+ else if (if ((fee > 500))
953+ then true
954+ else (0 > fee))
955+ then throw("fee value must be between 0 and 500 (0-5%)")
956+ else if ((validateWeights(assetWeightsStrLi) != 10000))
957+ then throw(("weights sum should be 10000, current: " + toString(validateWeights(assetWeightsStrLi))))
958+ else {
959+ func addTokenDataEntries (accum,assetNum) = if ((assetNum >= size(assetIdsLi)))
960+ then accum
961+ else {
962+ let assetStakingAddress = {
963+ let @ = invoke(poolsHubAddress, "useEmptyContract", [("staker_" + assetIdsStrLi[assetNum])], nil)
964+ if ($isInstanceOf(@, "String"))
965+ then @
966+ else throw(($getType(@) + " couldn't be cast to String"))
967+ }
968+ if ((assetStakingAddress == assetStakingAddress))
969+ then {
970+ let assetDecimals = match assetIdsLi[assetNum] {
971+ case x: ByteVector =>
972+ value(assetInfo(x)).decimals
973+ case _ =>
974+ 8
975+ }
976+ ((accum ++ [IntegerEntry((("static_" + assetIdsStrLi[assetNum]) + "_scale"), pow(10, 0, assetDecimals, 0, 0, DOWN)), IntegerEntry((("static_" + assetIdsStrLi[assetNum]) + "_decimals"), assetDecimals), IntegerEntry((("static_" + assetIdsStrLi[assetNum]) + "_weight"), value(parseInt(assetWeightsStrLi[assetNum]))), StringEntry(("static_stakingContract_" + assetIdsStrLi[assetNum]), assetStakingAddress)]) ++ (if ((assetMaxSelloffStrLi[assetNum] == ""))
977+ then nil
978+ else [IntegerEntry((("static_" + assetIdsStrLi[assetNum]) + "_maxSelloff"), (parseIntValue(assetMaxSelloffStrLi[assetNum]) * Scale12))]))
979+ }
980+ else throw("Strict value is not equal to itself.")
981+ }
982+
983+ ({
984+ let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
985+ let $s = size($l)
986+ let $acc0 = nil
987+ func $f6_1 ($a,$i) = if (($i >= $s))
988+ then $a
989+ else addTokenDataEntries($a, $l[$i])
990+
991+ func $f6_2 ($a,$i) = if (($i >= $s))
992+ then $a
993+ else throw("List size exceeds 10")
994+
995+ $f6_2($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
996+ } ++ [StringEntry("static_tokenIds", assetIdsStr), StringEntry("static_feeToken", feeAssetStr), StringEntry("static_tokenWeights", assetWeightsStr), IntegerEntry("static_tokensAmount", size(assetIdsLi)), StringEntry("static_poolDomain", poolDomain), StringEntry("static_poolToken_idStr", ""), StringEntry("static_baseTokenId", baseTokenIdStr), StringEntry("static_poolOwner", poolOwner), IntegerEntry("static_fee", fee), IntegerEntry("static_KMult", Scale16), IntegerEntry("global_indexStaked", 0), IntegerEntry("global_poolToken_amount", 0), IntegerEntry("global_wasPreInited", 1)])
997+ }
998+ }
999+
1000+
1001+
1002+@Callable(i)
1003+func deInit () = if (isShutdown())
1004+ then throw("contract is on stop")
1005+ else if ((i.caller != this))
1006+ then throw("admin only")
1007+ else [IntegerEntry("global_wasInited", 0)]
1008+
1009+
1010+
1011+@Callable(i)
1012+func init (assetIdsStr,assetWeightsStr,assetMaxSelloffStr,baseTokenIdStr,poolDomain,fee,vBalancesStr) = {
1013+ let preInitInv = invoke(this, "preInit", [assetIdsStr, assetWeightsStr, assetMaxSelloffStr, baseTokenIdStr, poolDomain, toString(i.caller), fee], nil)
1014+ if ((preInitInv == preInitInv))
1015+ then {
1016+ let vBalances = parstStrToIntList(vBalancesStr)
1017+ func getPaymentAmount (assetIdStr) = {
1018+ func handler (accum,payment) = if ((getAssetString(payment.assetId) == assetIdStr))
1019+ then payment.amount
1020+ else accum
1021+
1022+ let $l = i.payments
1023+ let $s = size($l)
1024+ let $acc0 = 0
1025+ func $f4_1 ($a,$i) = if (($i >= $s))
1026+ then $a
1027+ else handler($a, $l[$i])
1028+
1029+ func $f4_2 ($a,$i) = if (($i >= $s))
1030+ then $a
1031+ else throw("List size exceeds 10")
1032+
1033+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1034+ }
1035+
1036+ func prepareList () = {
1037+ func handler (accum,assetId) = {
1038+ let assetIdStr = getAssetString(assetId)
1039+ let n = value(indexOf(assetIds, assetId))
1040+ let paymentAmount = getPaymentAmount(assetIdStr)
1041+ let assetParams = loadGlobalTokenParams(assetIdStr)
1042+ let assetParamsUpd = $Tuple8(vBalances[n], paymentAmount, assetParams._3, assetParams._4, assetParams._5, assetParams._6, assetParams._7, assetParams._8)
1043+ (accum ++ [saveGlobalTokenParams(assetIdStr, assetParamsUpd)])
1044+ }
1045+
1046+ let $l = assetIds
1047+ let $s = size($l)
1048+ let $acc0 = nil
1049+ func $f4_1 ($a,$i) = if (($i >= $s))
1050+ then $a
1051+ else handler($a, $l[$i])
1052+
1053+ func $f4_2 ($a,$i) = if (($i >= $s))
1054+ then $a
1055+ else throw("List size exceeds 10")
1056+
1057+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1058+ }
1059+
1060+ func calculatePoolTokensAmount (assetId) = {
1061+ func handler (accum,assetId) = {
1062+ func handler2 (accum,n) = if ((n == assetId))
1063+ then value(indexOf(assetIds, n))
1064+ else accum
1065+
1066+ let Token = {
1067+ let $l = assetIds
1068+ let $s = size($l)
1069+ let $acc0 = 1
1070+ func $f4_1 ($a,$i) = if (($i >= $s))
1071+ then $a
1072+ else handler2($a, $l[$i])
1073+
1074+ func $f4_2 ($a,$i) = if (($i >= $s))
1075+ then $a
1076+ else throw("List size exceeds 10")
1077+
1078+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1079+ }
1080+ fraction(accum, pow(vBalances[Token], Decimals[Token], AssetsWeights[Token], AssetsWeightsDecimals, 8, FLOOR), Scale8)
1081+ }
1082+
1083+ let $l = assetIds
1084+ let $s = size($l)
1085+ let $acc0 = PoolTokenScale
1086+ func $f4_1 ($a,$i) = if (($i >= $s))
1087+ then $a
1088+ else handler($a, $l[$i])
1089+
1090+ func $f4_2 ($a,$i) = if (($i >= $s))
1091+ then $a
1092+ else throw("List size exceeds 10")
1093+
1094+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1095+ }
1096+
1097+ if (isShutdown())
1098+ then throw("contract is on stop")
1099+ else if ((size(i.payments) == 0))
1100+ then throw("at least some of the assets should be provided as payment")
1101+ else if ((tryGetInteger("global_wasInited") > 0))
1102+ then throw("pool already inited")
1103+ else {
1104+ let initialPoolTokens = calculatePoolTokensAmount(assetIds)
1105+ let notifyInvoke = invoke(poolsHubAddress, "addSelfPool", nil, nil)
1106+ if ((notifyInvoke == notifyInvoke))
1107+ then if ((initialPoolTokens == 0))
1108+ then throw("you need a bigger tokens amount to launch the pool")
1109+ else (prepareList() ++ [IntegerEntry("global_poolToken_amount", initialPoolTokens), IntegerEntry("global_wasInited", 1), IntegerEntry((toString(i.caller) + "_indexStaked"), initialPoolTokens), IntegerEntry("global_indexStaked", initialPoolTokens)])
1110+ else throw("Strict value is not equal to itself.")
1111+ }
1112+ }
1113+ else throw("Strict value is not equal to itself.")
1114+ }
1115+
1116+
1117+
1118+@Callable(i)
1119+func generateIndex (needChange) = if ((size(i.payments) != T))
1120+ then throw(("you need to attach all pool tokens. amount of pool tokens: " + toString(T)))
1121+ else if (!(checkTokensValidity(i.payments)))
1122+ then throw("wrong assets attached")
1123+ else {
1124+ let PIssuedNoMult = getMinPIssued(i.payments)
1125+ let result = handlePoolTokensAdd(PIssuedNoMult, i.payments, i.originCaller, needChange)
1126+ let PIssuedWithMult = fraction(PIssuedNoMult, Scale16, getKMult(), DOWN)
1127+ $Tuple2((((result ++ claimResult(i.caller)._1) ++ mintIndexIfNeeded(PIssuedWithMult)) ++ [IntegerEntry((toString(i.caller) + "_indexStaked"), (tryGetInteger((toString(i.caller) + "_indexStaked")) + PIssuedWithMult)), IntegerEntry("global_indexStaked", (tryGetInteger("global_indexStaked") + PIssuedWithMult)), IntegerEntry("global_poolToken_amount", (tryGetInteger("global_poolToken_amount") + PIssuedWithMult))]), PIssuedWithMult)
1128+ }
1129+
1130+
1131+
1132+@Callable(i)
1133+func redeemIndex (poolTokenAmount) = if ((poolTokenAmount > tryGetInteger((toString(i.caller) + "_indexStaked"))))
1134+ then throw("user doesn't have this amount of pool tokens")
1135+ else if (isShutdown())
1136+ then throw("contract is on stop")
1137+ else {
1138+ let PRedeemedWithMult = poolTokenAmount
1139+ let PRedeemedWithNoMult = fraction(PRedeemedWithMult, getKMult(), Scale16, DOWN)
1140+ let result = handlePoolTokensRedeem(PRedeemedWithNoMult, i.caller)
1141+ (((result ++ claimResult(i.caller)._1) ++ [IntegerEntry((toString(i.caller) + "_indexStaked"), (tryGetInteger((toString(i.caller) + "_indexStaked")) - PRedeemedWithMult)), IntegerEntry("global_indexStaked", (tryGetInteger("global_indexStaked") - PRedeemedWithMult)), IntegerEntry("global_poolToken_amount", (tryGetInteger("global_poolToken_amount") - PRedeemedWithMult))]) ++ burnIndexIfNeeded(poolTokenAmount))
1142+ }
1143+
1144+
1145+
1146+@Callable(i)
1147+func stakeIndex () = {
1148+ let addressStr = toString(i.originCaller)
1149+ let pmt = i.payments[0]
1150+ if ((value(pmt.assetId) != fromBase58String(tryGetString("static_poolToken_idStr"))))
1151+ then throw("wrong asset attached")
1152+ else indexStakeResult(addressStr, pmt.amount)
1153+ }
1154+
1155+
1156+
1157+@Callable(i)
1158+func stakeIndexFor (addressStr) = {
1159+ let pmt = i.payments[0]
1160+ if ((value(pmt.assetId) != fromBase58String(tryGetString("static_poolToken_idStr"))))
1161+ then throw("wrong asset attached")
1162+ else indexStakeResult(addressStr, pmt.amount)
1163+ }
1164+
1165+
1166+
1167+@Callable(i)
1168+func unstakeIndex (indexAmount) = {
1169+ func issueIndex () = {
1170+ let issue = Issue(("PR " + tryGetString("static_poolDomain")), "Puzzle Range Index", tryGetInteger("global_poolToken_amount"), PoolTokenDecimals, true, unit, 0)
1171+ let poolTokenIdStr = toBase58String(calculateAssetId(issue))
1172+ $Tuple2([issue, StringEntry("static_poolToken_idStr", poolTokenIdStr)], poolTokenIdStr)
1173+ }
1174+
1175+ let $t04004740213 = if ((tryGetString("static_poolToken_idStr") == ""))
1176+ then issueIndex()
1177+ else $Tuple2(nil, tryGetString("static_poolToken_idStr"))
1178+ let poolTokenIssueResult = $t04004740213._1
1179+ let poolTokenIdStr = $t04004740213._2
1180+ let poolTokenId = fromBase58String(poolTokenIdStr)
1181+ let addressStr = toString(i.caller)
1182+ let indexAvailable = tryGetInteger((addressStr + "_indexStaked"))
1183+ if (isShutdown())
1184+ then throw("contract is on stop")
1185+ else if ((indexAmount > indexAvailable))
1186+ then throw("you don't have index tokens available")
1187+ else if (isShutdown())
1188+ then throw("contract is on stop")
1189+ else ((poolTokenIssueResult ++ claimResult(addressFromStringValue(addressStr))._1) ++ [IntegerEntry((addressStr + "_indexStaked"), (indexAvailable - indexAmount)), IntegerEntry("global_indexStaked", (tryGetInteger("global_indexStaked") - indexAmount)), ScriptTransfer(i.caller, indexAmount, poolTokenId)])
1190+ }
1191+
1192+
1193+
1194+@Callable(i)
1195+func claimIndexRewards () = if (isShutdown())
1196+ then throw("contract is on stop")
1197+ else claimResult(i.caller)
1198+
1199+
1200+
1201+@Callable(i)
1202+func evaluateClaim (user) = $Tuple2(nil, claimResult(addressFromStringValue(user))._2)
1203+
1204+
1205+
1206+@Callable(i)
1207+func addInterestExternal () = {
1208+ let assetId = value(i.payments[0]).assetId
1209+ let assetIdStr = getAssetString(assetId)
1210+ let amount = i.payments[0].amount
1211+ let stakeTx = stakeIfNeeded(assetIdStr, amount)
1212+ if ((stakeTx == stakeTx))
1213+ then if ((indexOf(assetIds, assetId) == unit))
1214+ then throw("you can only add interest for assets in the pool")
1215+ else {
1216+ let params = loadGlobalTokenParams(assetIdStr)
1217+ let interestDelta = calcInterestChange(assetIdStr, amount)
1218+ let updParams = $Tuple8(params._1, params._2, params._3, (params._4 + interestDelta), (params._5 + amount), params._6, params._7, params._8)
1219+[saveGlobalTokenParams(assetIdStr, updParams)]
1220+ }
1221+ else throw("Strict value is not equal to itself.")
1222+ }
1223+
1224+
1225+
1226+@Callable(i)
1227+func notifyStakingPayment (assetIdStr,amount) = {
1228+ let assetId = getAssetBytes(assetIdStr)
1229+ if ((indexOf(assetIds, assetId) == unit))
1230+ then throw("you can only add interest for assets in the pool")
1231+ else if ((tryGetString(("static_stakingContract_" + assetIdStr)) != toString(i.caller)))
1232+ then throw("can only be invoked by staker contract")
1233+ else {
1234+ let params = loadGlobalTokenParams(assetIdStr)
1235+ let interestDelta = calcInterestChange(assetIdStr, amount)
1236+ let updParams = $Tuple8(params._1, params._2, params._3, (params._4 + interestDelta), (params._5 + amount), params._6, params._7, params._8)
1237+[saveGlobalTokenParams(assetIdStr, updParams)]
1238+ }
1239+ }
1240+
1241+
1242+
1243+@Callable(i)
1244+func swap (assetOut,minimum) = {
1245+ let pmt = if ((size(i.payments) == 1))
1246+ then value(i.payments[0])
1247+ else throw("please attach exactly one payment")
1248+ let AmountIn = value(i.payments[0].amount)
1249+ let AssetIn = pmt.assetId
1250+ let AssetOut = getAssetBytes(assetOut)
1251+ let assetIn = getAssetString(AssetIn)
1252+ let scaleIn = (Scale8 / tryGetInteger((("static_" + assetIn) + "_scale")))
1253+ let scaleOut = (Scale8 / tryGetInteger((("static_" + assetOut) + "_scale")))
1254+ let assetInParams = loadGlobalTokenParams(getAssetString(AssetIn))
1255+ let assetOutParams = loadGlobalTokenParams(assetOut)
1256+ let AssetInBalance = assetInParams._1
1257+ let AssetInFactBalance = assetInParams._2
1258+ let assetInFeesEarned = assetInParams._3
1259+ let assetInLastCheckInterest = assetInParams._4
1260+ let AssetOutBalance = assetOutParams._1
1261+ let assetOutFactBalance = assetOutParams._2
1262+ let AssetInBalanceScaled = (AssetInBalance * scaleIn)
1263+ let AssetOutBalanceScaled = (AssetOutBalance * scaleOut)
1264+ let feeAmountIn = fraction(AmountIn, Fee, FeeScale)
1265+ let cleanAmountIn = (AmountIn - feeAmountIn)
1266+ let cleanAmountInScaled = (cleanAmountIn * scaleIn)
1267+ let AmountOut1 = calculateOutAmount(cleanAmountInScaled, AssetIn, AssetOut, AssetInBalanceScaled, AssetOutBalanceScaled)
1268+ let AmountOut = fraction(AmountOut1, 1, scaleOut)
1269+ let AssetOutBalance2 = (AssetOutBalance - AmountOut)
1270+ let AssetInBalance2 = (AssetInBalance + cleanAmountIn)
1271+ if ((minimum > AmountOut))
1272+ then throw("amount to recieve is lower than given one")
1273+ else if ((AssetOut == AssetIn))
1274+ then throw("this swap is not allowed")
1275+ else if ((0 > (assetOutFactBalance - AmountOut)))
1276+ then throw("contract is out of reserves")
1277+ else if (isShutdown())
1278+ then throw("contract is on stop")
1279+ else if (valueOrElse(getBoolean(poolsHubAddress, ("global_shutdownIn_" + assetIn)), false))
1280+ then throw("token IN trades are stopped")
1281+ else if (valueOrElse(getBoolean(poolsHubAddress, ("global_shutdownOut_" + assetOut)), false))
1282+ then throw("token OUT trades are stopped")
1283+ else {
1284+ let protocolFee = fraction(feeAmountIn, 5, 10)
1285+ let lpFee = (feeAmountIn - protocolFee)
1286+ let interestDelta = calcInterestChange(assetIn, lpFee)
1287+ let stakeTx = stakeIfNeeded(assetIn, (cleanAmountIn + lpFee))
1288+ if ((stakeTx == stakeTx))
1289+ then {
1290+ let unstakeTx = unstakeIfNeeded(assetOut, AmountOut)
1291+ if ((unstakeTx == unstakeTx))
1292+ then {
1293+ let newBalanceIn = AssetInBalance2
1294+ let newBalanceOut = AssetOutBalance2
1295+ let assetInSelloffData = updSelloffData(assetIn, cleanAmountIn, AssetInBalance, $Tuple3(assetInParams._6, assetInParams._7, assetInParams._8))
1296+ let assetOutSelloffData = updSelloffData(assetOut, -(AmountOut), AssetOutBalance, $Tuple3(assetOutParams._6, assetOutParams._7, assetOutParams._8))
1297+ let assetInFinalParams = $Tuple8(newBalanceIn, (AssetInFactBalance + cleanAmountIn), (assetInFeesEarned + lpFee), (assetInLastCheckInterest + interestDelta), assetInParams._5, assetInSelloffData._1, assetInSelloffData._2, assetInSelloffData._3)
1298+ let assetOutFinalParams = $Tuple8(newBalanceOut, (assetOutFactBalance - AmountOut), assetOutParams._3, assetOutParams._4, assetOutParams._5, assetOutSelloffData._1, assetOutSelloffData._2, assetOutSelloffData._3)
1299+ let assetInChange = saveGlobalTokenParams(assetIn, assetInFinalParams)
1300+ let assetOutChange = saveGlobalTokenParams(assetOut, assetOutFinalParams)
1301+ let feeAssetStr = tryGetString("static_feeToken")
1302+ let feeAssetParams = loadGlobalTokenParams(feeAssetStr)
1303+ let feeTokenBalance = feeAssetParams._1
1304+ let volumeUsdUpdate = calculateUsdValue(AssetIn, AmountIn, AssetInBalance, feeTokenBalance)
1305+ $Tuple2([assetInChange, assetOutChange, ScriptTransfer(i.caller, AmountOut, AssetOut), IntegerEntry("global_volume_usd", (tryGetInteger("global_volume_usd") + volumeUsdUpdate)), ScriptTransfer(feesAddress, protocolFee, getAssetBytes(assetIn))], AmountOut)
1306+ }
1307+ else throw("Strict value is not equal to itself.")
1308+ }
1309+ else throw("Strict value is not equal to itself.")
1310+ }
1311+ }
1312+
1313+
1314+
1315+@Callable(i)
1316+func swapReadOnly (assetIn,assetOut,AmountIn) = {
1317+ let AssetIn = getAssetBytes(assetIn)
1318+ let AssetOut = getAssetBytes(assetOut)
1319+ let scaleIn = (Scale8 / tryGetInteger((("static_" + assetIn) + "_scale")))
1320+ let scaleOut = (Scale8 / tryGetInteger((("static_" + assetOut) + "_scale")))
1321+ let feeAssetOutStr = tryGetString("static_feeToken")
1322+ let feeAssetOut = if ((feeAssetOutStr == ""))
1323+ then usdnAssetId
1324+ else getAssetBytes(feeAssetOutStr)
1325+ let assetInParams = loadGlobalTokenParams(getAssetString(AssetIn))
1326+ let assetOutParams = loadGlobalTokenParams(assetOut)
1327+ let AssetInBalance = assetInParams._1
1328+ let AssetInFactBalance = assetInParams._2
1329+ let assetInFeesEarned = assetInParams._3
1330+ let assetInLastCheckInterest = assetInParams._4
1331+ let AssetOutBalance = assetOutParams._1
1332+ let assetOutFactBalance = assetOutParams._2
1333+ let AssetInBalanceScaled = (AssetInBalance * scaleIn)
1334+ let AssetOutBalanceScaled = (AssetOutBalance * scaleOut)
1335+ let feeAmountIn = fraction(AmountIn, Fee, FeeScale)
1336+ let cleanAmountIn = (AmountIn - feeAmountIn)
1337+ let cleanAmountInScaled = (cleanAmountIn * scaleIn)
1338+ let AmountOut1 = calculateOutAmount(cleanAmountInScaled, AssetIn, AssetOut, AssetInBalanceScaled, AssetOutBalanceScaled)
1339+ let AmountOut = fraction(AmountOut1, 1, scaleOut)
1340+ let AssetOutBalance2 = (AssetOutBalance - AmountOut)
1341+ let AssetInBalance2 = (AssetInBalance + cleanAmountIn)
1342+ if ((AssetOut == AssetIn))
1343+ then throw("this swap is not allowed")
1344+ else if ((0 > (assetOutParams._2 - AmountOut)))
1345+ then throw("contract is out of reserves")
1346+ else if (isShutdown())
1347+ then throw("contract is on stop")
1348+ else $Tuple2(nil, AmountOut)
1349+ }
1350+
1351+
1352+
1353+@Callable(i)
1354+func transferOwnership (newOwnerAddress) = if ((toString(i.caller) != tryGetString("static_poolOwner")))
1355+ then throw("this call available only for pool owner")
1356+ else [StringEntry("static_poolOwner", newOwnerAddress)]
1357+
1358+
1359+
1360+@Callable(i)
1361+func setFee (newFee) = if ((toString(i.caller) != tryGetString("static_poolOwner")))
1362+ then throw("this call available only for pool owner")
1363+ else [IntegerEntry("static_fee", newFee)]
1364+
1365+
1366+@Verifier(tx)
1367+func verify () = sigVerify(tx.bodyBytes, tx.proofs[0], masterPubKey)
1368+

github/deemru/w8io
47.04 ms