tx · 2kv8WEwGcrNd5rqGYyUPQhCHYMFd6m8MaK3sTAPAn2wq

3M6uKD65e2BWsBfkjpbXS4rotVhYJnobk6W:  -0.06000000 Waves

2026.06.01 23:14 [765047] smart account 3M6uKD65e2BWsBfkjpbXS4rotVhYJnobk6W > SELF 0.00000000 Waves

{ "type": 13, "id": "2kv8WEwGcrNd5rqGYyUPQhCHYMFd6m8MaK3sTAPAn2wq", "fee": 6000000, "feeAssetId": null, "timestamp": 1780344871229, "version": 2, "chainId": 82, "sender": "3M6uKD65e2BWsBfkjpbXS4rotVhYJnobk6W", "senderPublicKey": "4ubc4NJHCmFePWLMbbzJ48aCTHPeYwo8K6SnTVJmF6rB", "proofs": [ "3F1wnEZAUmcySmsVPVZAzwkhvvSZp2DA87iZuHW9mi4A1WdHivXqo2pGCHS3XekY4VBYaaNbtcqSKnniJV1Mo57m" ], "script": "base64:BgJgCAISAwoBCBIICgYICAgICAESABIAEgMKAQQSAwoBBBIAEgMKAQgSAwoBARIAEgMKAQgSBAoCCAESBQoDCAgBEgMKAQgSAwoBARIHCgUICAgBARIAEgMKAQgSBQoDCAgIXgAHVkVSU0lPTgINUFotMS40LjggUFJPRAANQ09OVFJBQ1RfVFlQRQIJTVVMVElQT09MAA1XQVZFU19SRVNFUlZFAICt4gQACWNvbmZpZ1N0cgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzAg1jb25maWdBZGRyZXNzAiMzUFBFQlJnNHMyYWYyclEyWmJMdmR1MUhmZDRWbzZRVkRUbwAOQ09ORklHX0FERFJFU1MDCQAAAgUJY29uZmlnU3RyAgAFBHRoaXMJAQdBZGRyZXNzAQkA2QQBBQljb25maWdTdHIAFUFzc2V0c1dlaWdodHNEZWNpbWFscwAEAAVTY2FsZQCQTgAGU2NhbGU4AIDC1y8AB1NjYWxlMTYAgICE/qbe4REACEZlZVNjYWxlAJBOABFQb29sVG9rZW5EZWNpbWFscwAIAA5Qb29sVG9rZW5TY2FsZQkAbAYACgAABRFQb29sVG9rZW5EZWNpbWFscwAAAAAFBkhBTEZVUAAVR0xPQkFMX01JTl9TVEVQX0xJTUlUAAIAEE1JTl9TVEVQU19BTU9VTlQJAJYDAQkAzAgCBRVHTE9CQUxfTUlOX1NURVBfTElNSVQJAMwIAgkBC3ZhbHVlT3JFbHNlAgkAmggCBQ5DT05GSUdfQUREUkVTUwIQbWluX3N0ZXBzX2Ftb3VudAUVR0xPQkFMX01JTl9TVEVQX0xJTUlUBQNuaWwAEE1BWF9TVEVQU19BTU9VTlQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUOQ09ORklHX0FERFJFU1MCEG1heF9zdGVwc19hbW91bnQA9AMAEk1JTl9TVEVQU19JTlRFUlZBTAkBC3ZhbHVlT3JFbHNlAgkAmggCBQ5DT05GSUdfQUREUkVTUwISbWluX3N0ZXBzX2ludGVydmFsAAEAEk1BWF9TVEVQU19JTlRFUlZBTAkBC3ZhbHVlT3JFbHNlAgkAmggCBQ5DT05GSUdfQUREUkVTUwISbWF4X3N0ZXBzX2ludGVydmFsAJBOAApNSU5fV0VJR0hUCQELdmFsdWVPckVsc2UCCQCaCAIFDkNPTkZJR19BRERSRVNTAgptaW5fd2VpZ2h0AGQACk1BWF9XRUlHSFQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUOQ09ORklHX0FERFJFU1MCCm1heF93ZWlnaHQArE0BC2dldF92ZXJzaW9uAAUHVkVSU0lPTgENdHJ5R2V0SW50ZWdlcgEDa2V5BAckbWF0Y2gwCQCaCAIFBHRoaXMFA2tleQMJAAECBQckbWF0Y2gwAgNJbnQEAWIFByRtYXRjaDAFAWIAAAEMdHJ5R2V0QmluYXJ5AQNrZXkEByRtYXRjaDAJAJwIAgUEdGhpcwUDa2V5AwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEAWIFByRtYXRjaDAFAWIBAAEMdHJ5R2V0U3RyaW5nAQNrZXkEByRtYXRjaDAJAJ0IAgUEdGhpcwUDa2V5AwkAAQIFByRtYXRjaDACBlN0cmluZwQBYgUHJG1hdGNoMAUBYgIAARN0cnlHZXRTdHJpbmdPclRocm93AQNrZXkEByRtYXRjaDAJAJ0IAgUEdGhpcwUDa2V5AwkAAQIFByRtYXRjaDACBlN0cmluZwQBYgUHJG1hdGNoMAUBYgkAAgEJAKwCAgIdbm8gc3VjaCBrZXkgaW4gZGF0YSBzdG9yYWdlOiAFA2tleQEOZ2V0QXNzZXRTdHJpbmcBB2Fzc2V0SWQEByRtYXRjaDAFB2Fzc2V0SWQDCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQBYgUHJG1hdGNoMAkA2AQBBQFiAgVXQVZFUwENZ2V0QXNzZXRCeXRlcwEKYXNzZXRJZFN0cgMJAAACBQphc3NldElkU3RyAgVXQVZFUwUEdW5pdAkA2QQBBQphc3NldElkU3RyAQ9nZXRUb2tlbkJhbGFuY2UBB2Fzc2V0SWQEByRtYXRjaDAFB2Fzc2V0SWQDCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQBdAUHJG1hdGNoMAkA8AcCBQR0aGlzBQF0CAkA7wcBBQR0aGlzB3JlZ3VsYXIBDmdldE5vZGVBZGRyZXNzAAQObm9kZUFkZHJlc3NTdHIJAQx0cnlHZXRTdHJpbmcBAhJzdGF0aWNfbm9kZUFkZHJlc3MDCQAAAgUObm9kZUFkZHJlc3NTdHICAAUEdW5pdAkApggBBQ5ub2RlQWRkcmVzc1N0cgEVcmViYWxhbmNlTGVhc2VBY3Rpb25zAgh3YXZlc091dAhub2RlQWRkcgQLX2lzUG9zaXRpdmUDCQBmAgAABQh3YXZlc091dAkAAgECIW5lZ2F0aXZlIGFtb3VudCBvZiBXQVZFUyB0byBsZWFzZQYDCQAAAgULX2lzUG9zaXRpdmUFC19pc1Bvc2l0aXZlBA5jdXJyZW50TGVhc2VJZAkBDHRyeUdldFN0cmluZwECEmdsb2JhbF9sYXN0TGVhc2VJZAQRY2FuY2VsTGVhc2VBY3Rpb24DCQECIT0CBQ5jdXJyZW50TGVhc2VJZAIACQDMCAIJAQtMZWFzZUNhbmNlbAEJANkEAQUOY3VycmVudExlYXNlSWQFA25pbAUDbmlsBAckbWF0Y2gwBQhub2RlQWRkcgMJAAECBQckbWF0Y2gwAgdBZGRyZXNzBARub2RlBQckbWF0Y2gwBA5uZXdMZWFzZUFtb3VudAkAZQIJAGUCCAkA7wcBBQR0aGlzB3JlZ3VsYXIFCHdhdmVzT3V0BQ1XQVZFU19SRVNFUlZFAwkAZgIFDm5ld0xlYXNlQW1vdW50AAAEC2xlYXNlQWN0aW9uCQDECAIFBG5vZGUFDm5ld0xlYXNlQW1vdW50BApuZXdMZWFzZUlkCQDYBAEJALkIAQULbGVhc2VBY3Rpb24DCQAAAgUKbmV3TGVhc2VJZAUOY3VycmVudExlYXNlSWQFA25pbAkAzggCBRFjYW5jZWxMZWFzZUFjdGlvbgkAzAgCBQtsZWFzZUFjdGlvbgkAzAgCCQELU3RyaW5nRW50cnkCAhJnbG9iYWxfbGFzdExlYXNlSWQFCm5ld0xlYXNlSWQJAMwIAgkBDEludGVnZXJFbnRyeQICFmdsb2JhbF9sYXN0TGVhc2VBbW91bnQFDm5ld0xlYXNlQW1vdW50BQNuaWwJAM4IAgURY2FuY2VsTGVhc2VBY3Rpb24DCQECIT0CBQ5jdXJyZW50TGVhc2VJZAIACQDMCAIJAQtEZWxldGVFbnRyeQECEmdsb2JhbF9sYXN0TGVhc2VJZAkAzAgCCQELRGVsZXRlRW50cnkBAhZnbG9iYWxfbGFzdExlYXNlQW1vdW50BQNuaWwFA25pbAkAzggCBRFjYW5jZWxMZWFzZUFjdGlvbgMJAQIhPQIFDmN1cnJlbnRMZWFzZUlkAgAJAMwIAgkBC0RlbGV0ZUVudHJ5AQISZ2xvYmFsX2xhc3RMZWFzZUlkCQDMCAIJAQtEZWxldGVFbnRyeQECFmdsb2JhbF9sYXN0TGVhc2VBbW91bnQFA25pbAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuARNhZGRBc3NldEJ5dGVzVG9MaXN0AgVhY2N1bQRpdGVtCQDOCAIFBWFjY3VtCQDMCAIJAQ1nZXRBc3NldEJ5dGVzAQUEaXRlbQUDbmlsARRhZGRBc3NldFdlaWdodFRvTGlzdAIFYWNjdW0EaXRlbQkAzggCBQVhY2N1bQkAzAgCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdzdGF0aWNfCQEOZ2V0QXNzZXRTdHJpbmcBBQRpdGVtAgdfd2VpZ2h0BQNuaWwBF2FkZEFzc2V0V2VpZ2h0VG9TdHJMaXN0AgVhY2N1bQRpdGVtCQDOCAIFBWFjY3VtCQDMCAIJAKQDAQkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHc3RhdGljXwUEaXRlbQIHX3dlaWdodAUDbmlsARZhZGRBc3NldERlY2ltYWxzVG9MaXN0AgVhY2N1bQRpdGVtCQDOCAIFBWFjY3VtCQDMCAIJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB3N0YXRpY18JAQ5nZXRBc3NldFN0cmluZwEFBGl0ZW0CCV9kZWNpbWFscwUDbmlsARNhZGRBc3NldFNjYWxlVG9MaXN0AgVhY2N1bQRpdGVtCQDOCAIFBWFjY3VtCQDMCAIJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB3N0YXRpY18JAQ5nZXRBc3NldFN0cmluZwEFBGl0ZW0CBl9zY2FsZQUDbmlsAQxhZGRJbnRUb0xpc3QCBWFjY3VtBGl0ZW0JAM4IAgUFYWNjdW0JAMwIAgkBDXBhcnNlSW50VmFsdWUBBQRpdGVtBQNuaWwADnVzZG5Bc3NldElkU3RyCQELdmFsdWVPckVsc2UCCQCdCAIFDkNPTkZJR19BRERSRVNTAg51c2RuQXNzZXRJZFN0cgIsREcyeEZrUGREd0tVb0JrekdBaFF0THBTR3pmWExpQ1lQRXplS0gyQWQyNHAAEHB1enpsZUFzc2V0SWRTdHIJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUOQ09ORklHX0FERFJFU1MCEHB1enpsZUFzc2V0SWRTdHICLEhFQjhRYXc5eHJXcFdzOHRIc2lBVFlHQldEQnRQMlM3a2NQQUxyTXU0M0FTAA51c2R0QXNzZXRJZFN0cgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ5DT05GSUdfQUREUkVTUwIOdXNkdEFzc2V0SWRTdHICLDM0TjlZY0VFVExXbjkzcVlRNjRFc1AxeDg5dFNydUpVNDRSckVNU1hYRVBKABF1c2R0UHB0QXNzZXRJZFN0cgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ5DT05GSUdfQUREUkVTUwIRdXNkdFBwdEFzc2V0SWRTdHICLDl3YzNMWE5BNFRFQnNYeUt0b0xFOW1yYkREN1dNSFh2WHJDalp2YWJMQXNpAA5yb21lQXNzZXRJZFN0cgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ5DT05GSUdfQUREUkVTUwIOcm9tZUFzc2V0SWRTdHICLEFQNENiNXhMWUdINlppZ0hyZUNaSG9YcFFUV0RrUHNHMkJIcWZEVXg2dGFKAA93YXZlc0Fzc2V0SWRTdHICBVdBVkVTAAt1c2RuQXNzZXRJZAkA2QQBBQ51c2RuQXNzZXRJZFN0cgANcHV6emxlQXNzZXRJZAkA2QQBBRBwdXp6bGVBc3NldElkU3RyAAt1c2R0QXNzZXRJZAkA2QQBBQ51c2R0QXNzZXRJZFN0cgAOdXNkdFBwdEFzc2V0SWQJANkEAQURdXNkdFBwdEFzc2V0SWRTdHIAC3JvbWVBc3NldElkCQDZBAEFDnJvbWVBc3NldElkU3RyAAx3YXZlc0Fzc2V0SWQFBHVuaXQAFXN1cHBvcnRlZEZlZUFzc2V0c1N0cgkAzAgCBQ51c2RuQXNzZXRJZFN0cgkAzAgCBRBwdXp6bGVBc3NldElkU3RyCQDMCAIFDnVzZHRBc3NldElkU3RyCQDMCAIFEXVzZHRQcHRBc3NldElkU3RyCQDMCAIFD3dhdmVzQXNzZXRJZFN0cgkAzAgCBQ5yb21lQXNzZXRJZFN0cgUDbmlsABFwYXJlbnRQb29sQWRkcmVzcwkBB0FkZHJlc3MBCQDZBAEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUOQ09ORklHX0FERFJFU1MCEXBhcmVudFBvb2xBZGRyZXNzAiMzUEZEZ3p1MVV0c3dBa0NNeHFxUWpiVGVIYVg0Y01hYjhLaAANbWFzdGVyQWRkcmVzcwkBB0FkZHJlc3MBCQDZBAEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUOQ09ORklHX0FERFJFU1MCDW1hc3RlckFkZHJlc3MCIzNQTGp3SGN6OU5FdWFUbzYzTlpSOUI5b2tRaUtReFpTYm1mAAxtYXN0ZXJQdWJLZXkJANkEAQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ5DT05GSUdfQUREUkVTUwIMbWFzdGVyUHViS2V5Aiw0ejhDS1NZUUJLa3p4N1BCYjV1QlAxWVBhNllBSFJOVEFwVzFzUVZIVDVlVQANb3JhY2xlQWRkcmVzcwkBB0FkZHJlc3MBCQDZBAEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUOQ09ORklHX0FERFJFU1MCDW9yYWNsZUFkZHJlc3MCIzNQOGQxRTFCTEtvRDUyeTNiUUoxYkRUZDJURDFncGFMbjl0AA5zdGFraW5nQWRkcmVzcwkBB0FkZHJlc3MBCQDZBAEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUOQ09ORklHX0FERFJFU1MCDnN0YWtpbmdBZGRyZXNzAiMzUEZUYnl3cXh0RmZ1a1gzSHlUODgxZzRpVzVLNFFMM0ZBUwALZmVlc0FkZHJlc3MJAQdBZGRyZXNzAQkA2QQBCQELdmFsdWVPckVsc2UCCQCdCAIFDkNPTkZJR19BRERSRVNTAgtmZWVzQWRkcmVzcwIjM1BGV0FWS21YamZIWHl6SmIxMmpDYmhQNFVoaTl0NHVXaUQAD3Bvb2xzSHViQWRkcmVzcwkBB0FkZHJlc3MBCQDZBAEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUOQ09ORklHX0FERFJFU1MCD3Bvb2xzSHViQWRkcmVzcwIjM1A1WXV0akROQzNoQUJCVnN2ZUZ1WlRUYlE1UGR0U0RCZ2sAEnNodXRkb3duQWRkcmVzc1N0cgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ5DT05GSUdfQUREUkVTUwIPc2h1dGRvd25BZGRyZXNzAiMzUEVwdjloUkZXRUVCVTIyV1JuTHN3MWJINFlHdGNVNzI4bwAPbGF5ZXIyQWRkcmVzc2VzCQELdmFsdWVPckVsc2UCCQCdCAIFDkNPTkZJR19BRERSRVNTAg9sYXllcjJBZGRyZXNzZXMCRzNQUjFRdmk5bUhUMzVTd1dFa0xTcXFFMkw4dGhpUExkVldVLDNQUW9CZlVLSGtKQWVHV2hvb0xQN1dTOG92YjU0YXY5SnAyAApnb3ZBZGRyZXNzCQEHQWRkcmVzcwEJANkEAQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ5DT05GSUdfQUREUkVTUwIKZ292QWRkcmVzcwIjM1A2dXJvOXhDc0U4dGU3OFFaanpxeTdhcThuYXRTemRjZUMAEWNvbGRNYXN0ZXJBZGRyZXNzCQEHQWRkcmVzcwEJANkEAQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ5DT05GSUdfQUREUkVTUwIRY29sZE1hc3RlckFkZHJlc3MCIzNQSzluaFBmUGJNQnlnQjlaZ0hWTUhhUWJTb29qd3JCZnhqAAFUCQENdHJ5R2V0SW50ZWdlcgECE3N0YXRpY190b2tlbnNBbW91bnQACGFzc2V0SWRzCgACJGwJALUJAgkBDHRyeUdldFN0cmluZwECD3N0YXRpY190b2tlbklkcwIBLAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQETYWRkQXNzZXRCeXRlc1RvTGlzdAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgANQXNzZXRzV2VpZ2h0cwoAAiRsBQhhc3NldElkcwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMV8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEUYWRkQXNzZXRXZWlnaHRUb0xpc3QCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjFfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYxXzICCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACERlY2ltYWxzCgACJGwFCGFzc2V0SWRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYyXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARZhZGRBc3NldERlY2ltYWxzVG9MaXN0AgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYyXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmMl8yAgkBBSRmMl8xAgkBBSRmMl8xAgkBBSRmMl8xAgkBBSRmMl8xAgkBBSRmMl8xAgkBBSRmMl8xAgkBBSRmMl8xAgkBBSRmMl8xAgkBBSRmMl8xAgkBBSRmMl8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAZTY2FsZXMKAAIkbAUIYXNzZXRJZHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjNfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBE2FkZEFzc2V0U2NhbGVUb0xpc3QCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjNfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYzXzICCQEFJGYzXzECCQEFJGYzXzECCQEFJGYzXzECCQEFJGYzXzECCQEFJGYzXzECCQEFJGYzXzECCQEFJGYzXzECCQEFJGYzXzECCQEFJGYzXzECCQEFJGYzXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoAA0ZlZQkBDXRyeUdldEludGVnZXIBAgpzdGF0aWNfZmVlAAxlYXJuZWRBc3NldHMFCGFzc2V0SWRzAQppc1NodXRkb3duAAQPc2h1dGRvd25BZGRyZXNzCQCmCAEFEnNodXRkb3duQWRkcmVzc1N0cgMJAAACBQ9zaHV0ZG93bkFkZHJlc3MFBHVuaXQHBA5nbG9iYWxTaHV0ZG93bgQHJG1hdGNoMAkAmwgCCQEFdmFsdWUBBQ9zaHV0ZG93bkFkZHJlc3MCC2lzX3NodXRkb3duAwkAAQIFByRtYXRjaDACB0Jvb2xlYW4EAXgFByRtYXRjaDAFAXgHBAxwb29sU2h1dGRvd24JAQt2YWx1ZU9yRWxzZQIJAJsIAgkBBXZhbHVlAQUPc2h1dGRvd25BZGRyZXNzCQCsAgICDXBvb2xTaHV0ZG93bl8JAKUIAQUEdGhpcwcDBQ5nbG9iYWxTaHV0ZG93bgYFDHBvb2xTaHV0ZG93bgEWZ2V0Q3VycmVudFRva2VuQmFsYW5jZQEIdG9rZW5OdW0ECnRva2VuSWRTdHIJAQ5nZXRBc3NldFN0cmluZwEJAJEDAgUIYXNzZXRJZHMFCHRva2VuTnVtCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdnbG9iYWxfBQp0b2tlbklkU3RyAghfYmFsYW5jZQEIZ2V0S011bHQABAckbWF0Y2gwCQCfCAECDHN0YXRpY19LTXVsdAMJAAECBQckbWF0Y2gwAgNJbnQEAXgFByRtYXRjaDAFAXgFB1NjYWxlMTYBEnNhdmVDdXJyZW50V2VpZ2h0cwAECmFzc2V0SWRzTGkJALUJAgkBDHRyeUdldFN0cmluZwECD3N0YXRpY190b2tlbklkcwIBLAoBAXMCBWFjY3VtB2Fzc2V0SWQJAM4IAgUFYWNjdW0JAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgIWcmViYWxhbmNlX3N0YXJ0V2VpZ2h0XwUHYXNzZXRJZAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHc3RhdGljXwUHYXNzZXRJZAIHX3dlaWdodAUDbmlsCgACJGwFCmFzc2V0SWRzTGkKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjRfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBAXMCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjRfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY0XzICCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoBGWdldFZpcnR1YWxQb29sVG9rZW5BbW91bnQACQBrAwkBDXRyeUdldEludGVnZXIBAhdnbG9iYWxfcG9vbFRva2VuX2Ftb3VudAkBCGdldEtNdWx0AAUHU2NhbGUxNgEQY2FsY3VsYXRlUElzc3VlZAIGYW1vdW50B3Rva2VuSWQEB1BzdXBwbHkJARlnZXRWaXJ0dWFsUG9vbFRva2VuQW1vdW50AAQHQmFsYW5jZQkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHZ2xvYmFsXwkBDmdldEFzc2V0U3RyaW5nAQUHdG9rZW5JZAIIX2JhbGFuY2UEAnQxCQBuBAUGYW1vdW50BQdQc3VwcGx5BQdCYWxhbmNlBQRET1dOBQJ0MQENZ2V0TWluUElzc3VlZAEIcGF5bWVudHMKAQdoYW5kbGVyAgVhY2N1bQdjdXJyZW50BAdQSXNzdWVkCQEQY2FsY3VsYXRlUElzc3VlZAIIBQdjdXJyZW50BmFtb3VudAgFB2N1cnJlbnQHYXNzZXRJZAMJAAACBQdQSXNzdWVkAAAJAAIBAiRvbmUgb2YgdGhlIHRva2VucyBhbW91bnRzIGlzIHRvbyBsb3cDAwkAAAIFBWFjY3VtAAAGCQBmAgUFYWNjdW0FB1BJc3N1ZWQFB1BJc3N1ZWQFBWFjY3VtBAltaW5QSXNzZWQKAAIkbAUIcGF5bWVudHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwAAAKAQUkZjRfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBB2hhbmRsZXICBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjRfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY0XzICCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoFCW1pblBJc3NlZAESY2FsY3VsYXRlVXNkblZhbHVlBAdhc3NldElkBmFtb3VudAhhQmFsYW5jZRBnaXZlblVzZG5CYWxhbmNlBAp1c2RuSW5Qb29sCQDPCAIFCGFzc2V0SWRzBQt1c2RuQXNzZXRJZAQMcHV6emxlSW5Qb29sCQDPCAIFCGFzc2V0SWRzBQ1wdXp6bGVBc3NldElkBAp1c2R0SW5Qb29sCQDPCAIFCGFzc2V0SWRzBQt1c2R0QXNzZXRJZAQNdXNkdFBwdEluUG9vbAkAzwgCBQhhc3NldElkcwUOdXNkdFBwdEFzc2V0SWQEC3dhdmVzSW5Qb29sCQDPCAIFCGFzc2V0SWRzBQR1bml0BAthc3NldFdlaWdodAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHc3RhdGljXwkBDmdldEFzc2V0U3RyaW5nAQUHYXNzZXRJZAIHX3dlaWdodAQLZmVlQXNzZXRTdHIJAQx0cnlHZXRTdHJpbmcBAg9zdGF0aWNfZmVlVG9rZW4DCQAAAgULZmVlQXNzZXRTdHIFEHB1enpsZUFzc2V0SWRTdHIEDHB1enpsZVdlaWdodAkAkQMCBQ1Bc3NldHNXZWlnaHRzCQEFdmFsdWUBCQDPCAIFCGFzc2V0SWRzBQ1wdXp6bGVBc3NldElkBA1wdXp6bGVCYWxhbmNlCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdnbG9iYWxfBRBwdXp6bGVBc3NldElkU3RyAghfYmFsYW5jZQQOYW1vdW50SW5QdXp6bGUJAGsDBQZhbW91bnQJAGkCBQ1wdXp6bGVCYWxhbmNlBQxwdXp6bGVXZWlnaHQJAGkCBQhhQmFsYW5jZQULYXNzZXRXZWlnaHQEC3B1enpsZVByaWNlCQERQGV4dHJOYXRpdmUoMTA1MCkCBRFwYXJlbnRQb29sQWRkcmVzcwIWZ2xvYmFsX2xhc3RQdXp6bGVQcmljZQkAawMJAGgCBQ5hbW91bnRJblB1enpsZQULcHV6emxlUHJpY2UAAQUGU2NhbGU4AwkAAAIFC2ZlZUFzc2V0U3RyBQ51c2R0QXNzZXRJZFN0cgQKdXNkdFdlaWdodAkAkQMCBQ1Bc3NldHNXZWlnaHRzCQEFdmFsdWUBBQp1c2R0SW5Qb29sBAt1c2R0QmFsYW5jZQkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHZ2xvYmFsXwUOdXNkdEFzc2V0SWRTdHICCF9iYWxhbmNlCQBrAwUGYW1vdW50CQBpAgULdXNkdEJhbGFuY2UFCnVzZHRXZWlnaHQJAGkCBQhhQmFsYW5jZQULYXNzZXRXZWlnaHQDCQAAAgULZmVlQXNzZXRTdHIFEXVzZHRQcHRBc3NldElkU3RyBAp1c2R0V2VpZ2h0CQCRAwIFDUFzc2V0c1dlaWdodHMJAQV2YWx1ZQEFDXVzZHRQcHRJblBvb2wEC3VzZHRCYWxhbmNlCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdnbG9iYWxfBRF1c2R0UHB0QXNzZXRJZFN0cgIIX2JhbGFuY2UJAGsDBQZhbW91bnQJAGkCBQt1c2R0QmFsYW5jZQUKdXNkdFdlaWdodAkAaQIFCGFCYWxhbmNlBQthc3NldFdlaWdodAMJAAACBQtmZWVBc3NldFN0cgUOdXNkbkFzc2V0SWRTdHIECnVzZG5XZWlnaHQJAJEDAgUNQXNzZXRzV2VpZ2h0cwkBBXZhbHVlAQkAzwgCBQhhc3NldElkcwULdXNkbkFzc2V0SWQEC3VzZG5CYWxhbmNlBAckbWF0Y2gwBRBnaXZlblVzZG5CYWxhbmNlAwkAAQIFByRtYXRjaDACA0ludAQBeAUHJG1hdGNoMAUQZ2l2ZW5Vc2RuQmFsYW5jZQkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHZ2xvYmFsXwkBDmdldEFzc2V0U3RyaW5nAQULdXNkbkFzc2V0SWQCCF9iYWxhbmNlCQBrAwUGYW1vdW50CQBpAgkBBXZhbHVlAQULdXNkbkJhbGFuY2UFCnVzZG5XZWlnaHQJAGkCBQhhQmFsYW5jZQULYXNzZXRXZWlnaHQEC3dhdmVzV2VpZ2h0ALgXBAh3QmFsYW5jZQkAaQIJAQ10cnlHZXRJbnRlZ2VyAQIUZ2xvYmFsX1dBVkVTX2JhbGFuY2UAMgkAawMFBmFtb3VudAkAaQIFCHdCYWxhbmNlBQt3YXZlc1dlaWdodAkAaQIFCGFCYWxhbmNlBQthc3NldFdlaWdodAESZ2V0UHJpY2VGcm9tT3JhY2xlAQphc3NldElkU3RyBAckbWF0Y2gwCQCaCAIFDW9yYWNsZUFkZHJlc3MJAKwCAgUKYXNzZXRJZFN0cgIHX3R3YXA1QgMJAAECBQckbWF0Y2gwAgNJbnQEAXgFByRtYXRjaDAFAXgAAAERY2FsY3VsYXRlVXNkVmFsdWUDB2Fzc2V0SWQGYW1vdW50CGFCYWxhbmNlBAthc3NldFdlaWdodAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHc3RhdGljXwkBDmdldEFzc2V0U3RyaW5nAQUHYXNzZXRJZAIHX3dlaWdodAQLZmVlQXNzZXRTdHIJAQx0cnlHZXRTdHJpbmcBAg9zdGF0aWNfZmVlVG9rZW4EDWZlZUFzc2V0U2NhbGUJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMJAKwCAgkArAICAgdzdGF0aWNfBQtmZWVBc3NldFN0cgIGX3NjYWxlBAtmZWVBc3NldE51bQkBBXZhbHVlAQkAzwgCBQhhc3NldElkcwkBDWdldEFzc2V0Qnl0ZXMBBQtmZWVBc3NldFN0cgQOZmVlQXNzZXRXZWlnaHQJAJEDAgUNQXNzZXRzV2VpZ2h0cwULZmVlQXNzZXROdW0ED2ZlZUFzc2V0QmFsYW5jZQkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHZ2xvYmFsXwULZmVlQXNzZXRTdHICCF9iYWxhbmNlBA12YWxJbkZlZUFzc2V0CQBrAwUGYW1vdW50CQBpAgUPZmVlQXNzZXRCYWxhbmNlBQ5mZWVBc3NldFdlaWdodAkAaQIFCGFCYWxhbmNlBQthc3NldFdlaWdodAQNZmVlQXNzZXRQcmljZQkBEmdldFByaWNlRnJvbU9yYWNsZQEFC2ZlZUFzc2V0U3RyCQBrAwUNdmFsSW5GZWVBc3NldAUNZmVlQXNzZXRQcmljZQUNZmVlQXNzZXRTY2FsZQETY2hlY2tUb2tlbnNWYWxpZGl0eQEIcGF5bWVudHMKAQhoYW5kbGVyMQIFYWNjdW0HcGF5bWVudAkAzggCBQVhY2N1bQkAzAgCCAUHcGF5bWVudAdhc3NldElkBQNuaWwEA2lkcwoAAiRsBQhwYXltZW50cwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmNF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEIaGFuZGxlcjECBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjRfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY0XzICCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoDCQAAAgUDaWRzBQNpZHMKAQhoYW5kbGVyMgIFYWNjdW0HYXNzZXRJZAMJAQIhPQIJAM8IAgUDaWRzBQdhc3NldElkBQR1bml0CQBkAgUFYWNjdW0AAQkAAgEJAKwCAgIUYXNzZXQgbm90IGF0dGFjaGVkOiAJAQ5nZXRBc3NldFN0cmluZwEFB2Fzc2V0SWQEBmNoZWNrcwoAAiRsBQhhc3NldElkcwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAAAAoBBSRmNV8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEIaGFuZGxlcjICBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjVfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY1XzICCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoDCQAAAgUGY2hlY2tzBQZjaGVja3MGCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuARNoYW5kbGVQb29sVG9rZW5zQWRkBAdQSXNzdWVkCHBheW1lbnRzC3VzZXJBZGRyZXNzCm5lZWRDaGFuZ2UKARVnZXRUb2tlblBheW1lbnRBbW91bnQBB3Rva2VuSWQKAQdoYW5kbGVyAgVhY2N1bQdwYXltZW50AwkAAAIIBQdwYXltZW50B2Fzc2V0SWQFB3Rva2VuSWQIBQdwYXltZW50BmFtb3VudAUFYWNjdW0KAAIkbAUIcGF5bWVudHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwAAAKAQUkZjRfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBB2hhbmRsZXICBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjRfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY0XzICCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoKARFoYW5kbGVUb2tlbkNoYW5nZQIFYWNjdW0HdG9rZW5JZAQCQmsJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB2dsb2JhbF8JAQ5nZXRBc3NldFN0cmluZwEFB3Rva2VuSWQCCF9iYWxhbmNlBAdQU3VwcGx5CQEZZ2V0VmlydHVhbFBvb2xUb2tlbkFtb3VudAAEAkRrCQCgAwEJAL0CBAkAtgIBBQdQSXNzdWVkCQC2AgEFAkJrCQC2AgEFB1BTdXBwbHkFB0NFSUxJTkcEDXBheW1lbnRBbW91bnQJARVnZXRUb2tlblBheW1lbnRBbW91bnQBBQd0b2tlbklkBAh0b1JldHVybgkAZQIFDXBheW1lbnRBbW91bnQFAkRrBAF0AwMFCm5lZWRDaGFuZ2UJAGYCBQh0b1JldHVybgAABwkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQt1c2VyQWRkcmVzcwUIdG9SZXR1cm4FB3Rva2VuSWQFA25pbAUDbmlsCQDOCAIJAM4IAgUFYWNjdW0FAXQJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkArAICAgdnbG9iYWxfCQEOZ2V0QXNzZXRTdHJpbmcBBQd0b2tlbklkAghfYmFsYW5jZQkAZAIFAkJrBQJEawUDbmlsCgACJGwFCGFzc2V0SWRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARFoYW5kbGVUb2tlbkNoYW5nZQIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjRfMgIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgEWaGFuZGxlUG9vbFRva2Vuc1JlZGVlbQIJUFJlZGVlbWVkC3VzZXJBZGRyZXNzCgERaGFuZGxlVG9rZW5SZWRlZW0CBWFjY3VtB3Rva2VuSWQEAkJrCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdnbG9iYWxfCQEOZ2V0QXNzZXRTdHJpbmcBBQd0b2tlbklkAghfYmFsYW5jZQQHUFN1cHBseQkBGWdldFZpcnR1YWxQb29sVG9rZW5BbW91bnQABAZhbW91bnQJAKADAQkAvQIECQC2AgEFCVBSZWRlZW1lZAkAtgIBBQJCawkAtgIBBQdQU3VwcGx5BQRET1dOCQDOCAIFBWFjY3VtCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgIHZ2xvYmFsXwkBDmdldEFzc2V0U3RyaW5nAQUHdG9rZW5JZAIIX2JhbGFuY2UJAGUCBQJCawUGYW1vdW50CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFC3VzZXJBZGRyZXNzBQZhbW91bnQFB3Rva2VuSWQFA25pbAoAAiRsBQhhc3NldElkcwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmNF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQERaGFuZGxlVG9rZW5SZWRlZW0CBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjRfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY0XzICCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoBF2NhbGN1bGF0ZU91dEFtb3VudF9ET1dOBQhBbW91bnRJbgdhc3NldEluCGFzc2V0T3V0CUJhbGFuY2VJbgpCYWxhbmNlT3V0BAdJbmRleEluCQEFdmFsdWUBCQDPCAIFCGFzc2V0SWRzBQdhc3NldEluBAhJbmRleE91dAkBBXZhbHVlAQkAzwgCBQhhc3NldElkcwUIYXNzZXRPdXQDCQAAAgUHSW5kZXhJbgUISW5kZXhPdXQFCEFtb3VudEluCQBuBAUKQmFsYW5jZU91dAkAZQIJAGgCBQZTY2FsZTgFBlNjYWxlOAkAoAMBCQB2BgkAvQIECQC5AgIJALYCAQUJQmFsYW5jZUluCQC2AgEAkE4JALYCAQkAaAIFBlNjYWxlOAUGU2NhbGU4CQC5AgIJALYCAQkAZAIFCUJhbGFuY2VJbgUIQW1vdW50SW4JALYCAQCQTgUGSEFMRlVQABAJALYCAQkAawMJAJEDAgUNQXNzZXRzV2VpZ2h0cwUHSW5kZXhJbgCAoJSljR0JAJEDAgUNQXNzZXRzV2VpZ2h0cwUISW5kZXhPdXQADAAQBQdDRUlMSU5HCQBoAgUGU2NhbGU4BQZTY2FsZTgFBERPV04BGmNhbGN1bGF0ZU91dEFtb3VudF9DRUlMSU5HBQhBbW91bnRJbgdhc3NldEluCGFzc2V0T3V0CUJhbGFuY2VJbgpCYWxhbmNlT3V0BAdJbmRleEluCQEFdmFsdWUBCQDPCAIFCGFzc2V0SWRzBQdhc3NldEluBAhJbmRleE91dAkBBXZhbHVlAQkAzwgCBQhhc3NldElkcwUIYXNzZXRPdXQDCQAAAgUHSW5kZXhJbgUISW5kZXhPdXQFCEFtb3VudEluCQBuBAUKQmFsYW5jZU91dAkAZQIJAGgCBQZTY2FsZTgFBlNjYWxlOAkAoAMBCQB2BgkAvQIECQC5AgIJALYCAQUJQmFsYW5jZUluCQC2AgEAkE4JALYCAQkAaAIFBlNjYWxlOAUGU2NhbGU4CQC5AgIJALYCAQkAZAIFCUJhbGFuY2VJbgUIQW1vdW50SW4JALYCAQCQTgUGSEFMRlVQABAJALYCAQkAawMJAJEDAgUNQXNzZXRzV2VpZ2h0cwUHSW5kZXhJbgCAoJSljR0JAJEDAgUNQXNzZXRzV2VpZ2h0cwUISW5kZXhPdXQADAAQBQdDRUlMSU5HCQBoAgUGU2NhbGU4BQZTY2FsZTgFB0NFSUxJTkcBHWNhbGN1bGF0ZUN1cnJlbnRBc3NldEludGVyZXN0BAdhc3NldElkCmFzc2V0SWRTdHIIYUJhbGFuY2UWdG9rZW5FYXJuaW5nc0xhc3RDaGVjawQLdG90YWxTdGFrZWQJAQ10cnlHZXRJbnRlZ2VyAQISZ2xvYmFsX2luZGV4U3Rha2VkBBV0b2tlbkJhbGFuY2VMYXN0Q2hlY2sFFnRva2VuRWFybmluZ3NMYXN0Q2hlY2sEE2N1cnJlbnRCYWxhbmNlRGVsdGEJAGUCCQEPZ2V0VG9rZW5CYWxhbmNlAQUHYXNzZXRJZAUIYUJhbGFuY2UEFGN1cnJlbnRUb2tlbkVhcm5pbmdzAwkAZgIFE2N1cnJlbnRCYWxhbmNlRGVsdGEFFXRva2VuQmFsYW5jZUxhc3RDaGVjawUTY3VycmVudEJhbGFuY2VEZWx0YQUVdG9rZW5CYWxhbmNlTGFzdENoZWNrBAtuZXdFYXJuaW5ncwkAZQIFFGN1cnJlbnRUb2tlbkVhcm5pbmdzBRV0b2tlbkJhbGFuY2VMYXN0Q2hlY2sEC25ld0ludGVyZXN0AwkAAAIFC3RvdGFsU3Rha2VkAAAAAAkAawMFC25ld0Vhcm5pbmdzBQZTY2FsZTgFC3RvdGFsU3Rha2VkBBFsYXN0Q2hlY2tJbnRlcmVzdAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIRZ2xvYmFsX2xhc3RDaGVja18FCmFzc2V0SWRTdHICCV9pbnRlcmVzdAkAZAIFEWxhc3RDaGVja0ludGVyZXN0BQtuZXdJbnRlcmVzdAELY2xhaW1SZXN1bHQBB2FkZHJlc3MECmFkZHJlc3NTdHIJAKUIAQUHYWRkcmVzcwQMcHV6emxlQW1vdW50CQENdHJ5R2V0SW50ZWdlcgEJAKwCAgUKYWRkcmVzc1N0cgIMX2luZGV4U3Rha2VkCgEHaGFuZGxlcgIFYWNjdW0HYXNzZXRJZAQKYXNzZXRJZFN0cgkBDmdldEFzc2V0U3RyaW5nAQUHYXNzZXRJZAQIYUJhbGFuY2UJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB2dsb2JhbF8JAQ5nZXRBc3NldFN0cmluZwEFB2Fzc2V0SWQCCF9iYWxhbmNlBBZ0b2tlbkVhcm5pbmdzTGFzdENoZWNrCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAhFnbG9iYWxfbGFzdENoZWNrXwUKYXNzZXRJZFN0cgIJX2Vhcm5pbmdzBBRjdXJyZW50VG9rZW5JbnRlcmVzdAkBHWNhbGN1bGF0ZUN1cnJlbnRBc3NldEludGVyZXN0BAUHYXNzZXRJZAUKYXNzZXRJZFN0cgUIYUJhbGFuY2UFFnRva2VuRWFybmluZ3NMYXN0Q2hlY2sEFGN1cnJlbnRUb2tlbkVhcm5pbmdzCQCWAwEJAMwIAgUWdG9rZW5FYXJuaW5nc0xhc3RDaGVjawkAzAgCCQBlAgkBD2dldFRva2VuQmFsYW5jZQEFB2Fzc2V0SWQFCGFCYWxhbmNlBQNuaWwEDHJld2FyZEFtb3VudAkAawMFDHB1enpsZUFtb3VudAkAZQIFFGN1cnJlbnRUb2tlbkludGVyZXN0CQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICCQCsAgIFCmFkZHJlc3NTdHICC19sYXN0Q2hlY2tfBQphc3NldElkU3RyAglfaW50ZXJlc3QFBlNjYWxlOAQIdHJhbnNmZXIDCQAAAgUMcmV3YXJkQW1vdW50AAAFA25pbAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQdhZGRyZXNzBQxyZXdhcmRBbW91bnQFB2Fzc2V0SWQFA25pbAkAlAoCCQDOCAIJAM4IAggFBWFjY3VtAl8xBQh0cmFuc2ZlcgkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgICEWdsb2JhbF9sYXN0Q2hlY2tfBQphc3NldElkU3RyAglfZWFybmluZ3MJAGUCBRRjdXJyZW50VG9rZW5FYXJuaW5ncwUMcmV3YXJkQW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgIRZ2xvYmFsX2xhc3RDaGVja18FCmFzc2V0SWRTdHICCV9pbnRlcmVzdAUUY3VycmVudFRva2VuSW50ZXJlc3QJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkArAICCQCsAgIFCmFkZHJlc3NTdHICC19sYXN0Q2hlY2tfBQphc3NldElkU3RyAglfaW50ZXJlc3QFFGN1cnJlbnRUb2tlbkludGVyZXN0BQNuaWwJAGQCCAUFYWNjdW0CXzIJARFjYWxjdWxhdGVVc2RWYWx1ZQMFB2Fzc2V0SWQFDHJld2FyZEFtb3VudAUIYUJhbGFuY2UEBWFjY3VtCgACJGwFDGVhcm5lZEFzc2V0cwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJQKAgUDbmlsAAAKAQUkZjRfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBB2hhbmRsZXICBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjRfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY0XzICCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoJAJQKAgkAzggCCAUFYWNjdW0CXzEJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgUKYWRkcmVzc1N0cgIRX2NsYWltZWRSZXdhcmRVU0QJAGQCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgUKYWRkcmVzc1N0cgIRX2NsYWltZWRSZXdhcmRVU0QIBQVhY2N1bQJfMgkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICBQphZGRyZXNzU3RyAgpfbGFzdENsYWltCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAUDbmlsCAUFYWNjdW0CXzIBE2dldFdhdmVzQ2xhaW1BbW91bnQBB2FkZHJlc3MDCQAAAgkAzwgCBQhhc3NldElkcwUEdW5pdAUEdW5pdAAABAphZGRyZXNzU3RyCQClCAEFB2FkZHJlc3MEDHB1enpsZUFtb3VudAkBDXRyeUdldEludGVnZXIBCQCsAgIFCmFkZHJlc3NTdHICDF9pbmRleFN0YWtlZAQIYUJhbGFuY2UJAQ10cnlHZXRJbnRlZ2VyAQIUZ2xvYmFsX1dBVkVTX2JhbGFuY2UEFnRva2VuRWFybmluZ3NMYXN0Q2hlY2sJAQ10cnlHZXRJbnRlZ2VyAQIfZ2xvYmFsX2xhc3RDaGVja19XQVZFU19lYXJuaW5ncwQUY3VycmVudFRva2VuSW50ZXJlc3QJAR1jYWxjdWxhdGVDdXJyZW50QXNzZXRJbnRlcmVzdAQFBHVuaXQCBVdBVkVTBQhhQmFsYW5jZQUWdG9rZW5FYXJuaW5nc0xhc3RDaGVjawQMcmV3YXJkQW1vdW50CQBrAwUMcHV6emxlQW1vdW50CQBlAgUUY3VycmVudFRva2VuSW50ZXJlc3QJAQ10cnlHZXRJbnRlZ2VyAQkArAICBQphZGRyZXNzU3RyAhlfbGFzdENoZWNrX1dBVkVTX2ludGVyZXN0BQZTY2FsZTgJAJYDAQkAzAgCAAAJAMwIAgUMcmV3YXJkQW1vdW50BQNuaWwBFGdldFdhdmVzUmVkZWVtQW1vdW50AQlQUmVkZWVtZWQDCQAAAgkAzwgCBQhhc3NldElkcwUEdW5pdAUEdW5pdAAABAJCawkBDXRyeUdldEludGVnZXIBAhRnbG9iYWxfV0FWRVNfYmFsYW5jZQQHUFN1cHBseQkBGWdldFZpcnR1YWxQb29sVG9rZW5BbW91bnQACQCgAwEJAL0CBAkAtgIBBQlQUmVkZWVtZWQJALYCAQUCQmsJALYCAQUHUFN1cHBseQUHQ0VJTElORwEUZ2V0V2F2ZXNDaGFuZ2VBbW91bnQDB1BJc3N1ZWQIcGF5bWVudHMKbmVlZENoYW5nZQMDCQEBIQEFCm5lZWRDaGFuZ2UGCQAAAgkAzwgCBQhhc3NldElkcwUEdW5pdAUEdW5pdAAACgEQZmluZFdhdmVzUGF5bWVudAIFYWNjdW0DcG10AwkAAAIIBQNwbXQHYXNzZXRJZAUEdW5pdAgFA3BtdAZhbW91bnQFBWFjY3VtBAh3YXZlc1BtdAoAAiRsBQhwYXltZW50cwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAAAAoBBSRmNF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEQZmluZFdhdmVzUGF5bWVudAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjRfMgIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgMJAAACBQh3YXZlc1BtdAAAAAAEAkJrCQENdHJ5R2V0SW50ZWdlcgECFGdsb2JhbF9XQVZFU19iYWxhbmNlBAdQU3VwcGx5CQEZZ2V0VmlydHVhbFBvb2xUb2tlbkFtb3VudAAEAkRrCQCgAwEJAL0CBAkAtgIBBQdQSXNzdWVkCQC2AgEFAkJrCQC2AgEFB1BTdXBwbHkFB0NFSUxJTkcJAJYDAQkAzAgCAAAJAMwIAgkAZQIFCHdhdmVzUG10BQJEawUDbmlsARBpbmRleFN0YWtlUmVzdWx0AgphZGRyZXNzU3RyBmFtb3VudAQCbGkICQELY2xhaW1SZXN1bHQBCQERQGV4dHJOYXRpdmUoMTA2MikBBQphZGRyZXNzU3RyAl8xCQDOCAIFAmxpCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIFCmFkZHJlc3NTdHICDF9pbmRleFN0YWtlZAkAZAIJAQ10cnlHZXRJbnRlZ2VyAQkArAICBQphZGRyZXNzU3RyAgxfaW5kZXhTdGFrZWQFBmFtb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgISZ2xvYmFsX2luZGV4U3Rha2VkCQBkAgkBDXRyeUdldEludGVnZXIBAhJnbG9iYWxfaW5kZXhTdGFrZWQFBmFtb3VudAUDbmlsAQ9pc093bmVyT3JNYXN0ZXIBBmNhbGxlcgQMb3duZXJBZGRyZXNzCQERQGV4dHJOYXRpdmUoMTA2MikBCQEMdHJ5R2V0U3RyaW5nAQIQc3RhdGljX3Bvb2xPd25lcgMJAAACBQZjYWxsZXIFDG93bmVyQWRkcmVzcwYJAAACBQZjYWxsZXIFDW1hc3RlckFkZHJlc3MBA3N1bQIFYWNjdW0BbgkAZAIFBWFjY3VtCQENcGFyc2VJbnRWYWx1ZQEFAW4BDWNoZWNrRmVlQXNzZXQCBWFjY3VtBG5leHQDAwkBAiE9AgkAzwgCBRVzdXBwb3J0ZWRGZWVBc3NldHNTdHIFBG5leHQFBHVuaXQJAAACBQVhY2N1bQIABwUEbmV4dAUFYWNjdW0BEmdldFRtcFJlYmFsYW5jZUlkcwENbmV3QXNzZXRJZHNMaQQRY3VycmVudEFzc2V0SWRzTGkJALUJAgkBDHRyeUdldFN0cmluZwECD3N0YXRpY190b2tlbklkcwIBLAQGcmVzdWx0BQ1uZXdBc3NldElkc0xpCgEBZgIFYWNjdW0HYXNzZXRJZAMJAAACCQDPCAIFBnJlc3VsdAUHYXNzZXRJZAUEdW5pdAkAzggCBQVhY2N1bQkAzAgCBQdhc3NldElkBQNuaWwFBWFjY3VtCgACJGwFEWN1cnJlbnRBc3NldElkc0xpCgACJHMJAJADAQUCJGwKAAUkYWNjMAUGcmVzdWx0CgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQFmAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY0XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNF8yAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKARFjaGVja1Rva2Vuc0NoYW5nZQENbmV3QXNzZXRJZHNMaQQRY3VycmVudEFzc2V0SWRzTGkJALUJAgkBDHRyeUdldFN0cmluZwECD3N0YXRpY190b2tlbklkcwIBLAoBA3JlbQIFYWNjdW0HYXNzZXRJZAMJAAACCQDPCAIFDW5ld0Fzc2V0SWRzTGkFB2Fzc2V0SWQFBHVuaXQJAGQCBQVhY2N1bQABBQVhY2N1bQoBA2FkZAIFYWNjdW0HYXNzZXRJZAMJAAACCQDPCAIFEWN1cnJlbnRBc3NldElkc0xpBQdhc3NldElkBQR1bml0CQBkAgUFYWNjdW0AAQUFYWNjdW0EB3JlbW92ZWQKAAIkbAURY3VycmVudEFzc2V0SWRzTGkKAAIkcwkAkAMBBQIkbAoABSRhY2MwAAAKAQUkZjRfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBA3JlbQIF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dGNoMAIHQWRkcmVzcwQBdAUHJG1hdGNoMAYHBApjYW5TZXROb2RlAwMFBm5vZGVPawYJAAACBQtub2RlQWRkcmVzcwIABgkAAgECEldyb25nIG5vZGUgYWRkcmVzcwMJAAACBQpjYW5TZXROb2RlBQpjYW5TZXROb2RlBAdzZWxmU2V0AwkAAAIFDF9ub2RlQWRkcmVzcwUEdGhpcwkAAgECLE5vZGUgYWRkcmVzcyBjYW4ndCBiZSBjb250cmFjdCdzIG93biBhZGRyZXNzBgMJAAACBQdzZWxmU2V0BQdzZWxmU2V0BAtuZXdOb2RlQWRkcgMJAQIhPQIFC25vZGVBZGRyZXNzAgAFDF9ub2RlQWRkcmVzcwUEdW5pdAQMbGVhc2VBY3Rpb25zCQEVcmViYWxhbmNlTGVhc2VBY3Rpb25zAgAABQtuZXdOb2RlQWRkcgkAzggCBQxsZWFzZUFjdGlvbnMJAMwIAgkBC1N0cmluZ0VudHJ5AgISc3RhdGljX25vZGVBZGRyZXNzBQtub2RlQWRkcmVzcwUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBB3ByZUluaXQGC2Fzc2V0SWRzU3RyD2Fzc2V0V2VpZ2h0c1N0cg5iYXNlVG9rZW5JZFN0cgpwb29sRG9tYWluCXBvb2xPd25lcgNmZWUED19jaGVja1Bvb2xPd25lcgMJAAACCQCmCAEFCXBvb2xPd25lcgUEdW5pdAkAAgECGHdyb25nIHBvb2wgb3duZXIgYWRkcmVzcwYDCQAAAgUPX2NoZWNrUG9vbE93bmVyBQ9fY2hlY2tQb29sT3duZXIEDWFzc2V0SWRzU3RyTGkJALUJAgULYXNzZXRJZHNTdHICASwECmFzc2V0SWRzTGkKAAIkbAUNYXNzZXRJZHNTdHJMaQoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmNF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQETYWRkQXNzZXRCeXRlc1RvTGlzdAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjRfMgIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgQLZmVlQXNzZXRTdHIKAAIkbAUNYXNzZXRJZHNTdHJMaQoAAiRzCQCQAwEFAiRsCgAFJGFjYzACAAoBBSRmNV8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQENY2hlY2tGZWVBc3NldAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNV8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjVfMgIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgQLYmFzZVByZXNlbnQDCQAAAgkAzwgCBQ1hc3NldElkc1N0ckxpBQ5iYXNlVG9rZW5JZFN0cgUEdW5pdAkAAgECGmJhc2UgdG9rZW4gbWlzc2luZyBpbiBsaXN0BgMJAAACBQtiYXNlUHJlc2VudAULYmFzZVByZXNlbnQDCQEKaXNTaHV0ZG93bgAJAAIBAhNjb250cmFjdCBpcyBvbiBzdG9wAwkBAiE9AgUEdGhpcwgFAWkGY2FsbGVyCQACAQIKYWRtaW4gb25seQMJAAACBQtmZWVBc3NldFN0cgIACQACAQJBcG9vbCBtdXN0IGhhdmUgb25lIG9mIHRoZSBzdXBwb3J0ZWQgZmVlIGFzc2V0cyBpbiB0aGUgY29tcG9zaXRpb24DCQBmAgkAsQIBBQpwb29sRG9tYWluAA0JAAIBAhV0b28gbGFyZ2UgcG9vbCBkb21haW4DAwkAZgIFA2ZlZQD0AwYJAGYCAAAFA2ZlZQkAAgECLWZlZSB2YWx1ZSBtdXN0IGJlIGJldHdlZW4gNTAgYW5kIDUwMCAoMC41LTUlKQQRYXNzZXRXZWlnaHRzU3RyTGkJALUJAgUPYXNzZXRXZWlnaHRzU3RyAgEsBA9hc3NldFdlaWdodHNTdW0KAAIkbAURYXNzZXRXZWlnaHRzU3RyTGkKAAIkcwkAkAMBBQIkbAoABSRhY2MwAAAKAQUkZjZfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBA3N1bQIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNl8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjZfMgIJAQUkZjZfMQIJAQUkZjZfMQIJAQUkZjZfMQIJAQUkZjZfMQIJAQUkZjZfMQIJAQUkZjZfMQIJAQUkZjZfMQIJAQUkZjZfMQIJAQUkZjZfMQIJAQUkZjZfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgQLc2FtZUxlbmd0aHMDCQECIT0CCQCQAwEFDWFzc2V0SWRzU3RyTGkJAJADAQURYXNzZXRXZWlnaHRzU3RyTGkJAAIBAiRhc3NldElkcyBhbmQgd2VpZ2h0cyBsZW5ndGggbWlzbWF0Y2gGAwkAAAIFC3NhbWVMZW5ndGhzBQtzYW1lTGVuZ3RocwoBE2FkZFRva2VuRGF0YUVudHJpZXMCBWFjY3VtCGFzc2V0TnVtAwkAZwIFCGFzc2V0TnVtCQCQAwEFCmFzc2V0SWRzTGkFBWFjY3VtBA1hc3NldERlY2ltYWxzBAckbWF0Y2gwCQCRAwIFCmFzc2V0SWRzTGkFCGFzc2V0TnVtAwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEAXgFByRtYXRjaDAICQEFdmFsdWUBCQDsBwEFAXgIZGVjaW1hbHMACAkAzggCBQVhY2N1bQkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgICB3N0YXRpY18JAJEDAgUNYXNzZXRJZHNTdHJMaQUIYXNzZXROdW0CBl9zY2FsZQkAbAYACgAABQ1hc3NldERlY2ltYWxzAAAAAAUERE9XTgkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgICB3N0YXRpY18JAJEDAgUNYXNzZXRJZHNTdHJMaQUIYXNzZXROdW0CCV9kZWNpbWFscwUNYXNzZXREZWNpbWFscwkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgICB3N0YXRpY18JAJEDAgUNYXNzZXRJZHNTdHJMaQUIYXNzZXROdW0CB193ZWlnaHQJAQV2YWx1ZQEJALYJAQkAkQMCBRFhc3NldFdlaWdodHNTdHJMaQUIYXNzZXROdW0FA25pbAMJAQIhPQIFD2Fzc2V0V2VpZ2h0c1N1bQCQTgkAAgECK3N1bSBvZiB0b2tlbiB3ZWlnaHRzIG11c3QgYmUgZXF1YWwgdG8gMTAwMDAJAM4IAgoAAiRsCQDMCAIAAAkAzAgCAAEJAMwIAgACCQDMCAIAAwkAzAgCAAQJAMwIAgAFCQDMCAIABgkAzAgCAAcJAMwIAgAICQDMCAIACQUDbmlsCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGY3XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARNhZGRUb2tlbkRhdGFFbnRyaWVzAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY3XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmN18yAgkBBSRmN18xAgkBBSRmN18xAgkBBSRmN18xAgkBBSRmN18xAgkBBSRmN18xAgkBBSRmN18xAgkBBSRmN18xAgkBBSRmN18xAgkBBSRmN18xAgkBBSRmN18xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKCQDMCAIJAQtTdHJpbmdFbnRyeQICD3N0YXRpY190b2tlbklkcwULYXNzZXRJZHNTdHIJAMwIAgkBC1N0cmluZ0VudHJ5AgIPc3RhdGljX2ZlZVRva2VuBQtmZWVBc3NldFN0cgkAzAgCCQELU3RyaW5nRW50cnkCAhNzdGF0aWNfdG9rZW5XZWlnaHRzBQ9hc3NldFdlaWdodHNTdHIJAMwIAgkBDEludGVnZXJFbnRyeQICE3N0YXRpY190b2tlbnNBbW91bnQJAJADAQUKYXNzZXRJZHNMaQkAzAgCCQELU3RyaW5nRW50cnkCAhFzdGF0aWNfcG9vbERvbWFpbgUKcG9vbERvbWFpbgkAzAgCCQELU3RyaW5nRW50cnkCAhJzdGF0aWNfYmFzZVRva2VuSWQFDmJhc2VUb2tlbklkU3RyCQDMCAIJAQtTdHJpbmdFbnRyeQICEHN0YXRpY19wb29sT3duZXIFCXBvb2xPd25lcgkAzAgCCQEMSW50ZWdlckVudHJ5AgIKc3RhdGljX2ZlZQUDZmVlCQDMCAIJAQxJbnRlZ2VyRW50cnkCAgxzdGF0aWNfS011bHQFB1NjYWxlMTYJAMwIAgkBDEludGVnZXJFbnRyeQICE2dsb2JhbF93YXNQcmVJbml0ZWQAAQUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBBmRlSW5pdAADCQEKaXNTaHV0ZG93bgAJAAIBAhNjb250cmFjdCBpcyBvbiBzdG9wAwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQIKYWRtaW4gb25seQkAzAgCCQEMSW50ZWdlckVudHJ5AgIQZ2xvYmFsX3dhc0luaXRlZAAABQNuaWwBaQEEaW5pdAAKAQtwcmVwYXJlTGlzdAAKAQdoYW5kbGVyAgVhY2N1bQFuCQDOCAIFBWFjY3VtCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgIHZ2xvYmFsXwkBDmdldEFzc2V0U3RyaW5nAQgFAW4HYXNzZXRJZAIIX2JhbGFuY2UIBQFuBmFtb3VudAUDbmlsCgACJGwIBQFpCHBheW1lbnRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQdoYW5kbGVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY0XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNF8yAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKBBJfY2hlY2tQYXltZW50c1NpemUDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzBQFUCQACAQkArAICCQCsAgICE3lvdSBuZWVkIHRvIGF0dGFjaCAJAKQDAQUBVAIYIHRva2VucyB0byBpbml0IHRoZSBwb29sBwMJAAACBRJfY2hlY2tQYXltZW50c1NpemUFEl9jaGVja1BheW1lbnRzU2l6ZQQUX2NoZWNrVG9rZW5zVmFsaWRpdHkDCQEBIQEJARNjaGVja1Rva2Vuc1ZhbGlkaXR5AQgFAWkIcGF5bWVudHMJAAIBAhV3cm9uZyBhc3NldHMgYXR0YWNoZWQHAwkAAAIFFF9jaGVja1Rva2Vuc1ZhbGlkaXR5BRRfY2hlY2tUb2tlbnNWYWxpZGl0eQoBGWNhbGN1bGF0ZVBvb2xUb2tlbnNBbW91bnQBCHBheW1lbnRzCgEHaGFuZGxlcgIFYWNjdW0DcG10BAdhc3NldElkCAUDcG10B2Fzc2V0SWQKAQhoYW5kbGVyMgIFYWNjdW0BbgMJAAACBQFuBQdhc3NldElkCQEFdmFsdWUBCQDPCAIFCGFzc2V0SWRzBQFuBQVhY2N1bQQFVG9rZW4KAAIkbAUIYXNzZXRJZHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwAAEKAQUkZjRfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBCGhhbmRsZXIyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY0XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNF8yAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKCQBrAwUFYWNjdW0JAGwGCAUDcG10BmFtb3VudAkAkQMCBQhEZWNpbWFscwUFVG9rZW4JAJEDAgUNQXNzZXRzV2VpZ2h0cwUFVG9rZW4FFUFzc2V0c1dlaWdodHNEZWNpbWFscwAIBQVGTE9PUgUGU2NhbGU4CgACJGwFCHBheW1lbnRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAUOUG9vbFRva2VuU2NhbGUKAQUkZjRfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBB2hhbmRsZXICBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjRfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY0XzICCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoDCQEKaXNTaHV0ZG93bgAJAAIBAhNjb250cmFjdCBpcyBvbiBzdG9wAwkAZgIJAQ10cnlHZXRJbnRlZ2VyAQIQZ2xvYmFsX3dhc0luaXRlZAAACQACAQITcG9vbCBhbHJlYWR5IGluaXRlZAQRaW5pdGlhbFBvb2xUb2tlbnMJARljYWxjdWxhdGVQb29sVG9rZW5zQW1vdW50AQgFAWkIcGF5bWVudHMDCQAAAgURaW5pdGlhbFBvb2xUb2tlbnMAAAkAAgECMnlvdSBuZWVkIGEgYmlnZ2VyIHRva2VucyBhbW91bnQgdG8gbGF1bmNoIHRoZSBwb29sBA5wb29sVG9rZW5Jc3N1ZQkAwwgHCQCsAgICA1BaIAkBDHRyeUdldFN0cmluZwECEXN0YXRpY19wb29sRG9tYWluAh1QdXp6bGUgU3dhcDogcG9vbCBpbmRleCB0b2tlbgURaW5pdGlhbFBvb2xUb2tlbnMFEVBvb2xUb2tlbkRlY2ltYWxzBgUEdW5pdAAABAtwb29sVG9rZW5JZAkAuAgBBQ5wb29sVG9rZW5Jc3N1ZQkAzggCCQDOCAIJAQtwcmVwYXJlTGlzdAAJAMwIAgUOcG9vbFRva2VuSXNzdWUJAMwIAgkBDEludGVnZXJFbnRyeQICF2dsb2JhbF9wb29sVG9rZW5fYW1vdW50BRFpbml0aWFsUG9vbFRva2VucwkAzAgCCQEMSW50ZWdlckVudHJ5AgIQZ2xvYmFsX3dhc0luaXRlZAABCQDMCAIJAQtCaW5hcnlFbnRyeQICE2dsb2JhbF9wb29sVG9rZW5faWQFC3Bvb2xUb2tlbklkCQDMCAIJAQtTdHJpbmdFbnRyeQICFnN0YXRpY19wb29sVG9rZW5faWRTdHIJAQ5nZXRBc3NldFN0cmluZwEFC3Bvb2xUb2tlbklkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKUIAQgFAWkGY2FsbGVyAgxfaW5kZXhTdGFrZWQFEWluaXRpYWxQb29sVG9rZW5zCQDMCAIJAQxJbnRlZ2VyRW50cnkCAhJnbG9iYWxfaW5kZXhTdGFrZWQFEWluaXRpYWxQb29sVG9rZW5zBQNuaWwJARVyZWJhbGFuY2VMZWFzZUFjdGlvbnMCAAAJAQ5nZXROb2RlQWRkcmVzcwAJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQENZ2VuZXJhdGVJbmRleAEKbmVlZENoYW5nZQMJAQppc1NodXRkb3duAAkAAgECE2NvbnRyYWN0IGlzIG9uIHN0b3ADCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzBQFUCQACAQkArAICAjt5b3UgbmVlZCB0byBhdHRhY2ggYWxsIHBvb2wgdG9rZW5zLiBhbW91bnQgb2YgcG9vbCB0b2tlbnM6IAkApAMBBQFUAwkBASEBCQETY2hlY2tUb2tlbnNWYWxpZGl0eQEIBQFpCHBheW1lbnRzCQACAQIVd3JvbmcgYXNzZXRzIGF0dGFjaGVkBA1QSXNzdWVkTm9NdWx0CQENZ2V0TWluUElzc3VlZAEIBQFpCHBheW1lbnRzBAZyZXN1bHQJARNoYW5kbGVQb29sVG9rZW5zQWRkBAUNUElzc3VlZE5vTXVsdAgFAWkIcGF5bWVudHMIBQFpDG9yaWdpbkNhbGxlcgUKbmVlZENoYW5nZQQPUElzc3VlZFdpdGhNdWx0CQBuBAUNUElzc3VlZE5vTXVsdAUHU2NhbGUxNgkBCGdldEtNdWx0AAUERE9XTgQHcmVpc3N1ZQkBB1JlaXNzdWUDCQERQGV4dHJOYXRpdmUoMTA1NykBAhNnbG9iYWxfcG9vbFRva2VuX2lkBQ9QSXNzdWVkV2l0aE11bHQGBAh3YXZlc091dAkBFGdldFdhdmVzQ2hhbmdlQW1vdW50AwUNUElzc3VlZE5vTXVsdAgFAWkIcGF5bWVudHMFCm5lZWRDaGFuZ2UEDGxlYXNlQWN0aW9ucwkBFXJlYmFsYW5jZUxlYXNlQWN0aW9ucwIFCHdhdmVzT3V0CQEOZ2V0Tm9kZUFkZHJlc3MACQCUCgIJAM4IAgkAzggCBQxsZWFzZUFjdGlvbnMFBnJlc3VsdAkAzAgCBQdyZWlzc3VlCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgUPUElzc3VlZFdpdGhNdWx0CQEMdHJ5R2V0QmluYXJ5AQITZ2xvYmFsX3Bvb2xUb2tlbl9pZAkAzAgCCQEMSW50ZWdlckVudHJ5AgIXZ2xvYmFsX3Bvb2xUb2tlbl9hbW91bnQJAGQCCQENdHJ5R2V0SW50ZWdlcgECF2dsb2JhbF9wb29sVG9rZW5fYW1vdW50BQ9QSXNzdWVkV2l0aE11bHQFA25pbAUPUElzc3VlZFdpdGhNdWx0AWkBC3JlZGVlbUluZGV4AQxzZW5kVG9PcmlnaW4EEl9jaGVja1BheW1lbnRzU2l6ZQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECIXBsZWFzZSBhdHRhY2ggZXhhY3RseSBvbmUgcGF5bWVudAcDCQAAAgUSX2NoZWNrUGF5bWVudHNTaXplBRJfY2hlY2tQYXltZW50c1NpemUEA3BtdAkAkQMCCAUBaQhwYXltZW50cwAAAwkBAiE9AggFA3BtdAdhc3NldElkCQEMdHJ5R2V0QmluYXJ5AQITZ2xvYmFsX3Bvb2xUb2tlbl9pZAkAAgECHnBsZWFzZSBhdHRhY2ggcG9vbCBzaGFyZSB0b2tlbgMJAQppc1NodXRkb3duAAkAAgECE2NvbnRyYWN0IGlzIG9uIHN0b3AEEVBSZWRlZW1lZFdpdGhNdWx0CAUDcG10BmFtb3VudAQTUFJlZGVlbWVkV2l0aE5vTXVsdAkAbgQFEVBSZWRlZW1lZFdpdGhNdWx0CQEIZ2V0S011bHQABQdTY2FsZTE2BQRET1dOBAZyZXN1bHQJARZoYW5kbGVQb29sVG9rZW5zUmVkZWVtAgUTUFJlZGVlbWVkV2l0aE5vTXVsdAMFDHNlbmRUb09yaWdpbggFAWkMb3JpZ2luQ2FsbGVyCAUBaQZjYWxsZXIECHdhdmVzT3V0CQEUZ2V0V2F2ZXNSZWRlZW1BbW91bnQBBRNQUmVkZWVtZWRXaXRoTm9NdWx0BAxsZWFzZUFjdGlvbnMJARVyZWJhbGFuY2VMZWFzZUFjdGlvbnMCBQh3YXZlc091dAkBDmdldE5vZGVBZGRyZXNzAAkAzggCCQDOCAIFDGxlYXNlQWN0aW9ucwUGcmVzdWx0CQDMCAIJAQRCdXJuAgkBDHRyeUdldEJpbmFyeQECE2dsb2JhbF9wb29sVG9rZW5faWQFEVBSZWRlZW1lZFdpdGhNdWx0CQDMCAIJAQxJbnRlZ2VyRW50cnkCAhdnbG9iYWxfcG9vbFRva2VuX2Ftb3VudAkAZQIJAQ10cnlHZXRJbnRlZ2VyAQIXZ2xvYmFsX3Bvb2xUb2tlbl9hbW91bnQFEVBSZWRlZW1lZFdpdGhNdWx0BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEKc3Rha2VJbmRleAAEC19pc1NodXRkb3duAwkBCmlzU2h1dGRvd24ACQACAQITY29udHJhY3QgaXMgb24gc3RvcAcDCQAAAgULX2lzU2h1dGRvd24FC19pc1NodXRkb3duBBJfY2hlY2tQYXltZW50c1NpemUDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAiFwbGVhc2UgYXR0YWNoIGV4YWN0bHkgb25lIHBheW1lbnQHAwkAAAIFEl9jaGVja1BheW1lbnRzU2l6ZQUSX2NoZWNrUGF5bWVudHNTaXplBAphZGRyZXNzU3RyCQClCAEIBQFpDG9yaWdpbkNhbGxlcgQDcG10CQCRAwIIBQFpCHBheW1lbnRzAAADCQECIT0CCQEFdmFsdWUBCAUDcG10B2Fzc2V0SWQJAQx0cnlHZXRCaW5hcnkBAhNnbG9iYWxfcG9vbFRva2VuX2lkCQACAQIUd3JvbmcgYXNzZXQgYXR0YWNoZWQEDXdhdmVzQ2xhaW1PdXQJARNnZXRXYXZlc0NsYWltQW1vdW50AQgFAWkMb3JpZ2luQ2FsbGVyCQDOCAIJARVyZWJhbGFuY2VMZWFzZUFjdGlvbnMCBQ13YXZlc0NsYWltT3V0CQEOZ2V0Tm9kZUFkZHJlc3MACQEQaW5kZXhTdGFrZVJlc3VsdAIFCmFkZHJlc3NTdHIIBQNwbXQGYW1vdW50CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDXN0YWtlSW5kZXhGb3IBCmFkZHJlc3NTdHIEC19pc1NodXRkb3duAwkBCmlzU2h1dGRvd24ACQACAQITY29udHJhY3QgaXMgb24gc3RvcAcDCQAAAgULX2lzU2h1dGRvd24FC19pc1NodXRkb3duBBJfY2hlY2tQYXltZW50c1NpemUDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAiFwbGVhc2UgYXR0YWNoIGV4YWN0bHkgb25lIHBheW1lbnQHAwkAAAIFEl9jaGVja1BheW1lbnRzU2l6ZQUSX2NoZWNrUGF5bWVudHNTaXplBANwbXQJAJEDAggFAWkIcGF5bWVudHMAAAMJAQIhPQIJAQV2YWx1ZQEIBQNwbXQHYXNzZXRJZAkBDHRyeUdldEJpbmFyeQECE2dsb2JhbF9wb29sVG9rZW5faWQJAAIBAhR3cm9uZyBhc3NldCBhdHRhY2hlZAQNd2F2ZXNDbGFpbU91dAkBE2dldFdhdmVzQ2xhaW1BbW91bnQBCQERQGV4dHJOYXRpdmUoMTA2MikBBQphZGRyZXNzU3RyCQDOCAIJARVyZWJhbGFuY2VMZWFzZUFjdGlvbnMCBQ13YXZlc0NsYWltT3V0CQEOZ2V0Tm9kZUFkZHJlc3MACQEQaW5kZXhTdGFrZVJlc3VsdAIFCmFkZHJlc3NTdHIIBQNwbXQGYW1vdW50CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDHVuc3Rha2VJbmRleAELaW5kZXhBbW91bnQEDl9pc1ZhbGlkQW1vdW50AwkAZwIAAAULaW5kZXhBbW91bnQJAAIBAhlhbW91bnQgc2hvdWxkIGJlIHBvc2l0aXZlBwMJAAACBQ5faXNWYWxpZEFtb3VudAUOX2lzVmFsaWRBbW91bnQECGlzTGF5ZXIyCQEPY29udGFpbnNFbGVtZW50AgkAtQkCBQ9sYXllcjJBZGRyZXNzZXMCASwJAKUIAQgFAWkGY2FsbGVyBAphZGRyZXNzU3RyAwUIaXNMYXllcjIJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyCQClCAEIBQFpBmNhbGxlcgQOaW5kZXhBdmFpbGFibGUJAQ10cnlHZXRJbnRlZ2VyAQkArAICBQphZGRyZXNzU3RyAgxfaW5kZXhTdGFrZWQDCQEKaXNTaHV0ZG93bgAJAAIBAhNjb250cmFjdCBpcyBvbiBzdG9wAwkAZgIFC2luZGV4QW1vdW50BQ5pbmRleEF2YWlsYWJsZQkAAgECJXlvdSBkb24ndCBoYXZlIGluZGV4IHRva2VucyBhdmFpbGFibGUEDXdhdmVzQ2xhaW1PdXQJARNnZXRXYXZlc0NsYWltQW1vdW50AQkBEUBleHRyTmF0aXZlKDEwNjIpAQUKYWRkcmVzc1N0cgkAzggCCQDOCAIJARVyZWJhbGFuY2VMZWFzZUFjdGlvbnMCBQ13YXZlc0NsYWltT3V0CQEOZ2V0Tm9kZUFkZHJlc3MACAkBC2NsYWltUmVzdWx0AQkBEUBleHRyTmF0aXZlKDEwNjIpAQUKYWRkcmVzc1N0cgJfMQkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICBQphZGRyZXNzU3RyAgxfaW5kZXhTdGFrZWQJAGUCBQ5pbmRleEF2YWlsYWJsZQULaW5kZXhBbW91bnQJAMwIAgkBDEludGVnZXJFbnRyeQICEmdsb2JhbF9pbmRleFN0YWtlZAkAZQIJAQ10cnlHZXRJbnRlZ2VyAQISZ2xvYmFsX2luZGV4U3Rha2VkBQtpbmRleEFtb3VudAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIFC2luZGV4QW1vdW50CQERQGV4dHJOYXRpdmUoMTA1NykBAhNnbG9iYWxfcG9vbFRva2VuX2lkBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQERY2xhaW1JbmRleFJld2FyZHMAAwkBCmlzU2h1dGRvd24ACQACAQITY29udHJhY3QgaXMgb24gc3RvcAQNd2F2ZXNDbGFpbU91dAkBE2dldFdhdmVzQ2xhaW1BbW91bnQBCAUBaQZjYWxsZXIEAmNyCQELY2xhaW1SZXN1bHQBCAUBaQZjYWxsZXIJAJQKAgkAzggCCQEVcmViYWxhbmNlTGVhc2VBY3Rpb25zAgUNd2F2ZXNDbGFpbU91dAkBDmdldE5vZGVBZGRyZXNzAAgFAmNyAl8xCAUCY3ICXzIBaQENZXZhbHVhdGVDbGFpbQEEdXNlcgkAlAoCBQNuaWwICQELY2xhaW1SZXN1bHQBCQERQGV4dHJOYXRpdmUoMTA2MikBBQR1c2VyAl8yAWkBBHN3YXACCGFzc2V0T3V0B21pbmltdW0EA3BtdAMJAAACCQCQAwEIBQFpCHBheW1lbnRzAAEJAQV2YWx1ZQEJAJEDAggFAWkIcGF5bWVudHMAAAkAAgECIXBsZWFzZSBhdHRhY2ggZXhhY3RseSBvbmUgcGF5bWVudAQIQW1vdW50SW4JAQV2YWx1ZQEICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50BAdBc3NldEluCAUDcG10B2Fzc2V0SWQECEFzc2V0T3V0CQENZ2V0QXNzZXRCeXRlcwEFCGFzc2V0T3V0BAdhc3NldEluCQEOZ2V0QXNzZXRTdHJpbmcBBQdBc3NldEluBAdzY2FsZUluCQBpAgUGU2NhbGU4CQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdzdGF0aWNfBQdhc3NldEluAgZfc2NhbGUECHNjYWxlT3V0CQBpAgUGU2NhbGU4CQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdzdGF0aWNfBQhhc3NldE91dAIGX3NjYWxlBA5mZWVBc3NldE91dFN0cgkBDHRyeUdldFN0cmluZwECD3N0YXRpY19mZWVUb2tlbgQLZmVlQXNzZXRPdXQDCQAAAgUOZmVlQXNzZXRPdXRTdHICAAULdXNkbkFzc2V0SWQJAQ1nZXRBc3NldEJ5dGVzAQUOZmVlQXNzZXRPdXRTdHIEDkFzc2V0SW5CYWxhbmNlCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdnbG9iYWxfCQEOZ2V0QXNzZXRTdHJpbmcBBQdBc3NldEluAghfYmFsYW5jZQQPQXNzZXRPdXRCYWxhbmNlCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdnbG9iYWxfBQhhc3NldE91dAIIX2JhbGFuY2UEFEFzc2V0SW5CYWxhbmNlU2NhbGVkCQBoAgUOQXNzZXRJbkJhbGFuY2UFB3NjYWxlSW4EFUFzc2V0T3V0QmFsYW5jZVNjYWxlZAkAaAIFD0Fzc2V0T3V0QmFsYW5jZQUIc2NhbGVPdXQEC2ZlZUFtb3VudEluCQBuBAUIQW1vdW50SW4FA0ZlZQUIRmVlU2NhbGUFB0NFSUxJTkcEDWNsZWFuQW1vdW50SW4JAGUCBQhBbW91bnRJbgULZmVlQW1vdW50SW4EE2NsZWFuQW1vdW50SW5TY2FsZWQJAGgCBQ1jbGVhbkFtb3VudEluBQdzY2FsZUluBApBbW91bnRPdXQxCQEXY2FsY3VsYXRlT3V0QW1vdW50X0RPV04FBRNjbGVhbkFtb3VudEluU2NhbGVkBQdBc3NldEluBQhBc3NldE91dAUUQXNzZXRJbkJhbGFuY2VTY2FsZWQFFUFzc2V0T3V0QmFsYW5jZVNjYWxlZAQJQW1vdW50T3V0CQBrAwUKQW1vdW50T3V0MQABBQhzY2FsZU91dAQQQXNzZXRPdXRCYWxhbmNlMgkAZQIFD0Fzc2V0T3V0QmFsYW5jZQUJQW1vdW50T3V0BA9Bc3NldEluQmFsYW5jZTIJAGQCBQ5Bc3NldEluQmFsYW5jZQUNY2xlYW5BbW91bnRJbgQSZmVlQXNzZXRPdXRCYWxhbmNlAwkAAAIFC2ZlZUFzc2V0T3V0BQdBc3NldEluBQ9Bc3NldEluQmFsYW5jZTIDCQAAAgULZmVlQXNzZXRPdXQFCEFzc2V0T3V0BRBBc3NldE91dEJhbGFuY2UyCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdnbG9iYWxfCQEOZ2V0QXNzZXRTdHJpbmcBBQtmZWVBc3NldE91dAIIX2JhbGFuY2UEDGZlZUFtb3VudE91dAkBGmNhbGN1bGF0ZU91dEFtb3VudF9DRUlMSU5HBQULZmVlQW1vdW50SW4FB0Fzc2V0SW4FC2ZlZUFzc2V0T3V0BQ5Bc3NldEluQmFsYW5jZQUSZmVlQXNzZXRPdXRCYWxhbmNlAwkAZgIFB21pbmltdW0FCUFtb3VudE91dAkAAgECKWFtb3VudCB0byByZWNpZXZlIGlzIGxvd2VyIHRoYW4gZ2l2ZW4gb25lAwkAAAIFCEFzc2V0T3V0BQdBc3NldEluCQACAQIYdGhpcyBzd2FwIGlzIG5vdCBhbGxvd2VkAwkAZgIAAAkAZQIFD0Fzc2V0T3V0QmFsYW5jZQUJQW1vdW50T3V0CQACAQIbY29udHJhY3QgaXMgb3V0IG9mIHJlc2VydmVzAwkBCmlzU2h1dGRvd24ACQACAQITY29udHJhY3QgaXMgb24gc3RvcAQKY3JlYXRvckZlZQkAawMFDGZlZUFtb3VudE91dAABAAoEC3Byb3RvY29sRmVlCQBrAwUMZmVlQW1vdW50T3V0AAQACgQMbmV3QmFsYW5jZUluAwkAAAIFC2ZlZUFzc2V0T3V0BQdBc3NldEluBQ9Bc3NldEluQmFsYW5jZTIJAGQCBQ5Bc3NldEluQmFsYW5jZQUIQW1vdW50SW4EDW5ld0JhbGFuY2VPdXQJAGUCBRBBc3NldE91dEJhbGFuY2UyAwkAAAIFCEFzc2V0T3V0BQtmZWVBc3NldE91dAUMZmVlQW1vdW50T3V0AAAEEm5ld0JhbGFuY2VGZWVBc3NldAMDCQECIT0CBQtmZWVBc3NldE91dAUHQXNzZXRJbgkBAiE9AgULZmVlQXNzZXRPdXQFCEFzc2V0T3V0BwkAZQIFEmZlZUFzc2V0T3V0QmFsYW5jZQUMZmVlQW1vdW50T3V0BQR1bml0BA1hc3NldEluQ2hhbmdlCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgICB2dsb2JhbF8JAQ5nZXRBc3NldFN0cmluZwEFB0Fzc2V0SW4CCF9iYWxhbmNlBQxuZXdCYWxhbmNlSW4EDmFzc2V0T3V0Q2hhbmdlCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgICB2dsb2JhbF8FCGFzc2V0T3V0AghfYmFsYW5jZQUNbmV3QmFsYW5jZU91dAQRZmVlQXNzZXRPdXRDaGFuZ2UDCQECIT0CBRJuZXdCYWxhbmNlRmVlQXNzZXQFBHVuaXQJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkArAICAgdnbG9iYWxfCQEOZ2V0QXNzZXRTdHJpbmcBBQtmZWVBc3NldE91dAIIX2JhbGFuY2UJAQV2YWx1ZQEFEm5ld0JhbGFuY2VGZWVBc3NldAUDbmlsBQNuaWwEDHZvbHVtZVVwZGF0ZQkBEmNhbGN1bGF0ZVVzZG5WYWx1ZQQFB0Fzc2V0SW4FCEFtb3VudEluBQ5Bc3NldEluQmFsYW5jZQUSZmVlQXNzZXRPdXRCYWxhbmNlBA92b2x1bWVVc2RVcGRhdGUJARFjYWxjdWxhdGVVc2RWYWx1ZQMFB0Fzc2V0SW4FCEFtb3VudEluBQ5Bc3NldEluQmFsYW5jZQQId2F2ZXNPdXQJAGQCAwkAAAIFCEFzc2V0T3V0BQR1bml0BQlBbW91bnRPdXQAAAMJAAACBQtmZWVBc3NldE91dAUEdW5pdAkAZAIFCmNyZWF0b3JGZWUFC3Byb3RvY29sRmVlAAAEFHNob3VsZFJlYmFsYW5jZUxlYXNlAwMJAAACBQdBc3NldEluBQR1bml0BgkAAAIFCEFzc2V0T3V0BQR1bml0BgkAAAIFC2ZlZUFzc2V0T3V0BQR1bml0BAxsZWFzZUFjdGlvbnMDBRRzaG91bGRSZWJhbGFuY2VMZWFzZQkBFXJlYmFsYW5jZUxlYXNlQWN0aW9ucwIFCHdhdmVzT3V0CQEOZ2V0Tm9kZUFkZHJlc3MABQNuaWwJAJQKAgkAzggCCQDOCAIJAM4IAgUMbGVhc2VBY3Rpb25zCQDMCAIFDmFzc2V0T3V0Q2hhbmdlCQDMCAIFDWFzc2V0SW5DaGFuZ2UFA25pbAURZmVlQXNzZXRPdXRDaGFuZ2UJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyBQlBbW91bnRPdXQFCEFzc2V0T3V0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQx0cnlHZXRTdHJpbmcBAhBzdGF0aWNfcG9vbE93bmVyBQpjcmVhdG9yRmVlBQtmZWVBc3NldE91dAkAzAgCCQEMSW50ZWdlckVudHJ5AgIUZ2xvYmFsX2Vhcm5lZEJ5T3duZXIJAGQCCQENdHJ5R2V0SW50ZWdlcgECFGdsb2JhbF9lYXJuZWRCeU93bmVyBQpjcmVhdG9yRmVlCQDMCAIJAQxJbnRlZ2VyRW50cnkCAg1nbG9iYWxfdm9sdW1lCQBkAgkBDXRyeUdldEludGVnZXIBAg1nbG9iYWxfdm9sdW1lBQx2b2x1bWVVcGRhdGUJAMwIAgkBDEludGVnZXJFbnRyeQICEWdsb2JhbF92b2x1bWVfdXNkCQBkAgkBDXRyeUdldEludGVnZXIBAhFnbG9iYWxfdm9sdW1lX3VzZAUPdm9sdW1lVXNkVXBkYXRlCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFC2ZlZXNBZGRyZXNzBQtwcm90b2NvbEZlZQULZmVlQXNzZXRPdXQFA25pbAUJQW1vdW50T3V0AWkBDHN3YXBSZWFkT25seQMHYXNzZXRJbghhc3NldE91dAhBbW91bnRJbgQHQXNzZXRJbgkBDWdldEFzc2V0Qnl0ZXMBBQdhc3NldEluBAhBc3NldE91dAkBDWdldEFzc2V0Qnl0ZXMBBQhhc3NldE91dAQHc2NhbGVJbgkAaQIFBlNjYWxlOAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHc3RhdGljXwUHYXNzZXRJbgIGX3NjYWxlBAhzY2FsZU91dAkAaQIFBlNjYWxlOAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHc3RhdGljXwUIYXNzZXRPdXQCBl9zY2FsZQQOZmVlQXNzZXRPdXRTdHIJAQx0cnlHZXRTdHJpbmcBAg9zdGF0aWNfZmVlVG9rZW4EC2ZlZUFzc2V0T3V0AwkAAAIFDmZlZUFzc2V0T3V0U3RyAgAFC3VzZG5Bc3NldElkCQENZ2V0QXNzZXRCeXRlcwEFDmZlZUFzc2V0T3V0U3RyBA5Bc3NldEluQmFsYW5jZQkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHZ2xvYmFsXwkBDmdldEFzc2V0U3RyaW5nAQUHQXNzZXRJbgIIX2JhbGFuY2UED0Fzc2V0T3V0QmFsYW5jZQkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHZ2xvYmFsXwUIYXNzZXRPdXQCCF9iYWxhbmNlBBRBc3NldEluQmFsYW5jZVNjYWxlZAkAaAIFDkFzc2V0SW5CYWxhbmNlBQdzY2FsZUluBBVBc3NldE91dEJhbGFuY2VTY2FsZWQJAGgCBQ9Bc3NldE91dEJhbGFuY2UFCHNjYWxlT3V0BAtmZWVBbW91bnRJbgkAbgQFCEFtb3VudEluBQNGZWUFCEZlZVNjYWxlBQdDRUlMSU5HBA1jbGVhbkFtb3VudEluCQBlAgUIQW1vdW50SW4FC2ZlZUFtb3VudEluBBNjbGVhbkFtb3VudEluU2NhbGVkCQBoAgUNY2xlYW5BbW91bnRJbgUHc2NhbGVJbgQKQW1vdW50T3V0MQkBF2NhbGN1bGF0ZU91dEFtb3VudF9ET1dOBQUTY2xlYW5BbW91bnRJblNjYWxlZAUHQXNzZXRJbgUIQXNzZXRPdXQFFEFzc2V0SW5CYWxhbmNlU2NhbGVkBRVBc3NldE91dEJhbGFuY2VTY2FsZWQECUFtb3VudE91dAkAawMFCkFtb3VudE91dDEAAQUIc2NhbGVPdXQEEEFzc2V0T3V0QmFsYW5jZTIJAGUCBQ9Bc3NldE91dEJhbGFuY2UFCUFtb3VudE91dAQPQXNzZXRJbkJhbGFuY2UyCQBkAgUOQXNzZXRJbkJhbGFuY2UFDWNsZWFuQW1vdW50SW4EEmZlZUFzc2V0T3V0QmFsYW5jZQMJAAACBQtmZWVBc3NldE91dAUHQXNzZXRJbgUPQXNzZXRJbkJhbGFuY2UyAwkAAAIFC2ZlZUFzc2V0T3V0BQhBc3NldE91dAUQQXNzZXRPdXRCYWxhbmNlMgkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHZ2xvYmFsXwkBDmdldEFzc2V0U3RyaW5nAQULZmVlQXNzZXRPdXQCCF9iYWxhbmNlBAxmZWVBbW91bnRPdXQJARpjYWxjdWxhdGVPdXRBbW91bnRfQ0VJTElORwUFC2ZlZUFtb3VudEluBQdBc3NldEluBQtmZWVBc3NldE91dAUOQXNzZXRJbkJhbGFuY2UFEmZlZUFzc2V0T3V0QmFsYW5jZQMJAAACBQhBc3NldE91dAUHQXNzZXRJbgkAAgECGHRoaXMgc3dhcCBpcyBub3QgYWxsb3dlZAMJAGYCAAAJAGUCBQ9Bc3NldE91dEJhbGFuY2UFCUFtb3VudE91dAkAAgECG2NvbnRyYWN0IGlzIG91dCBvZiByZXNlcnZlcwMJAQppc1NodXRkb3duAAkAAgECE2NvbnRyYWN0IGlzIG9uIHN0b3AJAJQKAgUDbmlsBQlBbW91bnRPdXQBaQERdHJhbnNmZXJPd25lcnNoaXABD25ld093bmVyQWRkcmVzcwQLX2lzU2h1dGRvd24DCQEKaXNTaHV0ZG93bgAJAAIBAhNjb250cmFjdCBpcyBvbiBzdG9wBwMJAAACBQtfaXNTaHV0ZG93bgULX2lzU2h1dGRvd24DCQECIT0CCQClCAEIBQFpBmNhbGxlcgkBDHRyeUdldFN0cmluZwECEHN0YXRpY19wb29sT3duZXIJAAIBAid0aGlzIGNhbGwgYXZhaWxhYmxlIG9ubHkgZm9yIHBvb2wgb3duZXIDCQAAAgkApggBBQ9uZXdPd25lckFkZHJlc3MFBHVuaXQJAAIBAg9pbnZhbGlkIGFkZHJlc3MJAMwIAgkBC1N0cmluZ0VudHJ5AgIQc3RhdGljX3Bvb2xPd25lcgUPbmV3T3duZXJBZGRyZXNzBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEGc2V0RmVlAQZuZXdGZWUEDl9pc1Bvc2l0aXZlRmVlAwkAZgIAAAUGbmV3RmVlCQACAQIVZmVlIGNhbid0IGJlIG5lZ2F0aXZlBgMJAAACBQ5faXNQb3NpdGl2ZUZlZQUOX2lzUG9zaXRpdmVGZWUDCQECIT0CCQClCAEIBQFpBmNhbGxlcgkBDHRyeUdldFN0cmluZwECEHN0YXRpY19wb29sT3duZXIJAAIBAid0aGlzIGNhbGwgYXZhaWxhYmxlIG9ubHkgZm9yIHBvb2wgb3duZXIDCQBmAgABCQELdmFsdWVPckVsc2UCCQCaCAIFCmdvdkFkZHJlc3MJAKwCAgILYXBwcm92ZWRUeF8JANgEAQgFAWkNdHJhbnNhY3Rpb25JZAAACQACAQIzdGhpcyB0cmFuc2FjdGlvbiBuZWVkcyBhcHByb3ZhbCBmcm9tIHB1enpsZSBuZXR3b3JrCQDMCAIJAQxJbnRlZ2VyRW50cnkCAgpzdGF0aWNfZmVlBQZuZXdGZWUFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARJzZXRSZWJhbGFuY2luZ1BsYW4FC2Fzc2V0SWRzU3RyD2Fzc2V0V2VpZ2h0c1N0cg5iYXNlVG9rZW5JZFN0cgtzdGVwc0Ftb3VudA1zdGVwc0ludGVydmFsBAtfaXNTaHV0ZG93bgMJAQppc1NodXRkb3duAAkAAgECE2NvbnRyYWN0IGlzIG9uIHN0b3AGAwkAAAIFC19pc1NodXRkb3duBQtfaXNTaHV0ZG93bgMJAQIhPQIIBQFpBmNhbGxlcgkBEUBleHRyTmF0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EHZhbGlkYXRlUGF5bWVudHMCBQthZGRlZEFzc2V0cwgFAWkIcGF5bWVudHMEDHZhbGlkV2VpZ2h0cwkBD3ZhbGlkYXRlV2VpZ2h0cwEFFG5ld0Fzc2V0V2VpZ2h0c1N0ckxpAwkAAAIFDHZhbGlkV2VpZ2h0cwUMdmFsaWRXZWlnaHRzAwkBAiE9AgUNdmFsaWRQYXltZW50cwkAZAIJAJADAQULYWRkZWRBc3NldHMJAJADAQgFAWkIcGF5bWVudHMJAAIBAjFQYXltZW50cyBub3QgcHJlc2VudCBvciBzb21ldGhpbmcgd3Jvbmcgd2l0aCB0aGVtAwkBAiE9AgkAkAMBBRBuZXdBc3NldElkc1N0ckxpCQCQAwEFFG5ld0Fzc2V0V2VpZ2h0c1N0ckxpCQACAQIxYXNzZXRJZHMgYW5kIGFzc2V0V2VpZ2h0cyBzaG91bGQgaGF2ZSBzYW1lIGxlbmd0aAMJAAACBQtmZWVBc3NldFN0cgIACQACAQJBcG9vbCBtdXN0IGhhdmUgb25lIG9mIHRoZSBzdXBwb3J0ZWQgZmVlIGFzc2V0cyBpbiB0aGUgY29tcG9zaXRpb24DCQAAAgkAzwgCBRBuZXdBc3NldElkc1N0ckxpBQ5iYXNlVG9rZW5JZFN0cgUEdW5pdAkAAgECKWJhc2VUb2tlbklkIHNob3VsZCBiZSBwcmVzZW50IGluIGFzc2V0SWRzAwMJAGYCBRBNSU5fU1RFUFNfQU1PVU5UBQtzdGVwc0Ftb3VudAYJAGYCBQtzdGVwc0Ftb3VudAUQTUFYX1NURVBTX0FNT1VOVAkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAh9TdGVwcyBhbW91bnQgc2hvdWxkIGJlIGJldHdlZW4gCQCkAwEFEE1JTl9TVEVQU19BTU9VTlQCBSBhbmQgCQCkAwEFEE1BWF9TVEVQU19BTU9VTlQCCywgY3VycmVudDogCQCkAwEFC3N0ZXBzQW1vdW50AwMJAGYCBRJNSU5fU1RFUFNfSU5URVJWQUwFDXN0ZXBzSW50ZXJ2YWwGCQBmAgUNc3RlcHNJbnRlcnZhbAUSTUFYX1NURVBTX0lOVEVSVkFMCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgICIVN0ZXBzIGludGVydmFsIHNob3VsZCBiZSBiZXR3ZWVuIAkApAMBBRJNSU5fU1RFUFNfSU5URVJWQUwCBSBhbmQgCQCkAwEFEk1BWF9TVEVQU19JTlRFUlZBTAILLCBjdXJyZW50OiAJAKQDAQUNc3RlcHNJbnRlcnZhbAMJAQIhPQIFD2Fzc2V0V2VpZ2h0c1N1bQCQTgkAAgEJAKwCAgI2c3VtIG9mIHRva2VuIHdlaWdodHMgbXVzdCBiZSBlcXVhbCB0byAxMDAwMCwgY3VycmVudDogCQCkAwEFD2Fzc2V0V2VpZ2h0c1N1bQoBAWYCBWFjY3VtCmFzc2V0SWRTdHIECW9sZFdlaWdodAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHc3RhdGljXwUKYXNzZXRJZFN0cgIHX3dlaWdodAQJbmV3V2VpZ2h0AwkAAAIJAM8IAgUQbmV3QXNzZXRJZHNTdHJMaQUKYXNzZXRJZFN0cgUEdW5pdAAACQENcGFyc2VJbnRWYWx1ZQEJAQV2YWx1ZQEJAJEDAgUUbmV3QXNzZXRXZWlnaHRzU3RyTGkJAQV2YWx1ZQEJAM8IAgUQbmV3QXNzZXRJZHNTdHJMaQUKYXNzZXRJZFN0cgQMZGVsdGFQZXJTdGVwCQBrAwkAZQIFCW5ld1dlaWdodAUJb2xkV2VpZ2h0AJBOBQtzdGVwc0Ftb3VudAkAzggCBQVhY2N1bQkAzAgCCQCkAwEFDGRlbHRhUGVyU3RlcAUDbmlsBA10bXBBc3NldElkc0xpCQESZ2V0VG1wUmViYWxhbmNlSWRzAQUQbmV3QXNzZXRJZHNTdHJMaQQLYXNzZXREZWx0YXMKAAIkbAUNdG1wQXNzZXRJZHNMaQoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmOF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEBZgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmOF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjhfMgIJAQUkZjhfMQIJAQUkZjhfMQIJAQUkZjhfMQIJAQUkZjhfMQIJAQUkZjhfMQIJAQUkZjhfMQIJAQUkZjhfMQIJAQUkZjhfMQIJAQUkZjhfMQIJAQUkZjhfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgQObmV3VG9rZW5zQWRkZWQJAGYCCQERY2hlY2tUb2tlbnNDaGFuZ2UBBRBuZXdBc3NldElkc1N0ckxpAAAKARJyZWNvcmRBc3NldFBheW1lbnQCBWFjY3VtBG5leHQJAM4IAgUFYWNjdW0JAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgIacmViYWxhbmNlX2F0dGFjaGVkUGF5bWVudF8JAQ5nZXRBc3NldFN0cmluZwEIBQRuZXh0B2Fzc2V0SWQIBQRuZXh0BmFtb3VudAUDbmlsBA5wYXltZW50RW50cmllcwoAAiRsCAUBaQhwYXltZW50cwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmOV8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEScmVjb3JkQXNzZXRQYXltZW50AgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY5XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmOV8yAgkBBSRmOV8xAgkBBSRmOV8xAgkBBSRmOV8xAgkBBSRmOV8xAgkBBSRmOV8xAgkBBSRmOV8xAgkBBSRmOV8xAgkBBSRmOV8xAgkBBSRmOV8xAgkBBSRmOV8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKBAxzdG9yZVdlaWdodHMJARJzYXZlQ3VycmVudFdlaWdodHMABBByZXF1ZXN0R292SW52b2tlCQD8BwQFCmdvdkFkZHJlc3MCEnJlcXVlc3RSZWJhbGFuY2luZwkAzAgCCQDYBAEIBQFpDXRyYW5zYWN0aW9uSWQFA25pbAUDbmlsAwkAAAIFEHJlcXVlc3RHb3ZJbnZva2UFEHJlcXVlc3RHb3ZJbnZva2UJAM4IAgkAzggCCQDMCAIJAQtTdHJpbmdFbnRyeQICFXJlYmFsYW5jZV9hZGRlZEFzc2V0cwkAuQkCBQthZGRlZEFzc2V0cwIBLAkAzAgCCQELU3RyaW5nRW50cnkCAhdyZWJhbGFuY2VfcmVtb3ZlZEFzc2V0cwkAuQkCBQ1yZW1vdmVkQXNzZXRzAgEsCQDMCAIJAQtTdHJpbmdFbnRyeQICFXRtcF9yZWJhbGFuY2VBc3NldElkcwkAuQkCBQ10bXBBc3NldElkc0xpAgEsCQDMCAIJAQxCb29sZWFuRW50cnkCAhRyZWJhbGFuY2VfaW5Qcm9ncmVzcwYJAMwIAgkBDEJvb2xlYW5FbnRyeQICGHJlYmFsYW5jZV9uZXdUb2tlbnNBZGRlZAUObmV3VG9rZW5zQWRkZWQJAMwIAgkBDEludGVnZXJFbnRyeQICE3JlYmFsYW5jZV9zdGVwc0RvbmUAAAkAzAgCCQEMSW50ZWdlckVudHJ5AgIYcmViYWxhbmNlX2xhc3RTdGVwSGVpZ2h0BQZoZWlnaHQJAMwIAgkBDEludGVnZXJFbnRyeQICFXJlYmFsYW5jZV9zdGVwc0Ftb3VudAULc3RlcHNBbW91bnQJAMwIAgkBDEludGVnZXJFbnRyeQICF3JlYmFsYW5jZV9zdGVwc0ludGVydmFsBQ1zdGVwc0ludGVydmFsCQDMCAIJAQtTdHJpbmdFbnRyeQICEnJlYmFsYW5jZV9hc3NldElkcwULYXNzZXRJZHNTdHIJAMwIAgkBC1N0cmluZ0VudHJ5AgIYcmViYWxhbmNlX25ld0Jhc2VUb2tlbklkBQ5iYXNlVG9rZW5JZFN0cgkAzAgCCQELU3RyaW5nRW50cnkCAhVyZWJhbGFuY2VfYXNzZXREZWx0YXMJALkJAgULYXNzZXREZWx0YXMCASwFA25pbAUOcGF5bWVudEVudHJpZXMFDHN0b3JlV2VpZ2h0cwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ9zdGVwUmViYWxhbmNpbmcABAtfaXNTaHV0ZG93bgMJAQppc1NodXRkb3duAAkAAgECE2NvbnRyYWN0IGlzIG9uIHN0b3AGAwkAAAIFC19pc1NodXRkb3duBQtfaXNTaHV0ZG93bgQFcmViSWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQpnb3ZBZGRyZXNzCQCsAgICFXBvb2xfbGFzdFJlYmFsYW5jaW5nXwkApQgBBQR0aGlzAixyZWJhbGFuY2luZyBpcyBub3QgcmVnaXN0ZXJlZCBhdCBnb3YgYWRkcmVzcwMJAQEhAQkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzAhRyZWJhbGFuY2VfaW5Qcm9ncmVzcwcJAAIBAhpubyByZWJhbGFuY2luZyBpbiBwcm9ncmVzcwMJAQIhPQIJAQt2YWx1ZU9yRWxzZQIJAJoIAgUKZ292QWRkcmVzcwkArAICAhNyZWJhbGFuY2luZ19zdGF0dXNfBQVyZWJJZAAAAAIJAAIBAjN0aGlzIHRyYW5zYWN0aW9uIG5lZWRzIGFwcHJvdmFsIGZyb20gcHV6emxlIG5ldHdvcmsEDmxhc3RTdGVwSGVpZ2h0CQERQGV4dHJOYXRpdmUoMTA1NSkBAhhyZWJhbGFuY2VfbGFzdFN0ZXBIZWlnaHQEDHN0ZXBJbnRlcnZhbAkBEUBleHRyTmF0aXZlKDEwNTUpAQIXcmViYWxhbmNlX3N0ZXBzSW50ZXJ2YWwECXN0ZXBzRG9uZQkBEUBleHRyTmF0aXZlKDEwNTUpAQITcmViYWxhbmNlX3N0ZXBzRG9uZQQObmV4dFN0ZXBIZWlnaHQJAGQCBQ5sYXN0U3RlcEhlaWdodAUMc3RlcEludGVydmFsAwkAZgIFDm5leHRTdGVwSGVpZ2h0BQZoZWlnaHQJAAIBAhFjYW4ndCBiZSBkb25lIHlldAQLYXNzZXREZWx0YXMJALUJAgkBEUBleHRyTmF0aXZlKDEwNTgpAQIVcmViYWxhbmNlX2Fzc2V0RGVsdGFzAgEsBA5uZXdBc3NldElkc1N0cgkBEUBleHRyTmF0aXZlKDEwNTgpAQIVdG1wX3JlYmFsYW5jZUFzc2V0SWRzBAtuZXdBc3NldElkcwkAtQkCBQ5uZXdBc3NldElkc1N0cgIBLAoBAWYCBWFjY3VtCmFzc2V0SWRTdHIJAM4IAgUFYWNjdW0JAMwIAgkApAMBCQBuBAkAZAIJAGgCCQELdmFsdWVPckVsc2UCCQCfCAEJAKwCAgIWcmViYWxhbmNlX3N0YXJ0V2VpZ2h0XwUKYXNzZXRJZFN0cgAAAJBOCQBoAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFC2Fzc2V0RGVsdGFzCQEFdmFsdWUBCQDPCAIFC25ld0Fzc2V0SWRzBQphc3NldElkU3RyCQBkAgUJc3RlcHNEb25lAAEAAQCQTgUGSEFMRlVQBQNuaWwECW5ld1NoYXJlcwkAuQkCCgACJGwFC25ld0Fzc2V0SWRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQFmAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY0XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNF8yAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAgEsBA5uZXdUb2tlbnNBZGRlZAkBEUBleHRyTmF0aXZlKDEwNTYpAQIYcmViYWxhbmNlX25ld1Rva2Vuc0FkZGVkBANpbnYDAwUObmV3VG9rZW5zQWRkZWQJAAACBQlzdGVwc0RvbmUAAAcJAPwHBAUEdGhpcwIaZG9SZWJhbGFuY2luZ1dpdGhOZXdUb2tlbnMJAMwIAgUObmV3QXNzZXRJZHNTdHIJAMwIAgUJbmV3U2hhcmVzCQDMCAIJARFAZXh0ck5hdGl2ZSgxMDU4KQECGHJlYmFsYW5jZV9uZXdCYXNlVG9rZW5JZAUDbmlsBQNuaWwJAPwHBAUEdGhpcwINZG9SZWJhbGFuY2luZwkAzAgCBQluZXdTaGFyZXMFA25pbAUDbmlsAwkAAAIFA2ludgUDaW52BAxub3RpZnlJbnZva2UJAPwHBAUPcG9vbHNIdWJBZGRyZXNzAhBub3RpZnlQb29sQ2hhbmdlBQNuaWwFA25pbAMJAAACBQxub3RpZnlJbnZva2UFDG5vdGlmeUludm9rZQQKaXNGaW5pc2hlZAkAZwIJAGQCBQlzdGVwc0RvbmUAAQkBEUBleHRyTmF0aXZlKDEwNTUpAQIVcmViYWxhbmNlX3N0ZXBzQW1vdW50BAdhY3Rpb25zCQDMCAIJAQxCb29sZWFuRW50cnkCAhRyZWJhbGFuY2VfaW5Qcm9ncmVzcwkBASEBBQppc0ZpbmlzaGVkCQDMCAIJAQxJbnRlZ2VyRW50cnkCAhNyZWJhbGFuY2Vfc3RlcHNEb25lCQBkAgUJc3RlcHNEb25lAAEJAMwIAgkBDEludGVnZXJFbnRyeQICGHJlYmFsYW5jZV9sYXN0U3RlcEhlaWdodAUGaGVpZ2h0BQNuaWwDCQAAAgUJc3RlcHNEb25lAAAJAM4IAgUHYWN0aW9ucwkAzAgCCQELU3RyaW5nRW50cnkCAg9zdGF0aWNfdG9rZW5JZHMFDm5ld0Fzc2V0SWRzU3RyBQNuaWwDBQppc0ZpbmlzaGVkBA9yZW1vdmVkQXNzZXRzTGkJALUJAgkBDHRyeUdldFN0cmluZwECF3JlYmFsYW5jZV9yZW1vdmVkQXNzZXRzAgEsCgEGcm1EYXRhAgVhY2N1bQdhc3NldElkCQDOCAIFBWFjY3VtCQDMCAIJAQtEZWxldGVFbnRyeQEJAKwCAgkArAICAgdzdGF0aWNfBQdhc3NldElkAgZfc2NhbGUJAMwIAgkBC0RlbGV0ZUVudHJ5AQkArAICCQCsAgICB3N0YXRpY18FB2Fzc2V0SWQCCV9kZWNpbWFscwkAzAgCCQELRGVsZXRlRW50cnkBCQCsAgIJAKwCAgIHc3RhdGljXwUHYXNzZXRJZAIHX3dlaWdodAkAzAgCCQELRGVsZXRlRW50cnkBCQCsAgIJAKwCAgIHZ2xvYmFsXwUHYXNzZXRJZAIIX2JhbGFuY2UJAMwIAgkBC0RlbGV0ZUVudHJ5AQkArAICAhpyZWJhbGFuY2VfYXR0YWNoZWRQYXltZW50XwUHYXNzZXRJZAUDbmlsBAJybQoAAiRsBQ9yZW1vdmVkQXNzZXRzTGkKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjVfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBBnJtRGF0YQIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNV8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjVfMgIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgQNYWRkZWRBc3NldHNMaQkAtQkCCQEMdHJ5R2V0U3RyaW5nAQIVcmViYWxhbmNlX2FkZGVkQXNzZXRzAgEsCgERYWRkUmVtb3ZlUGF5bWVudHMCBWFjY3VtB2Fzc2V0SWQJAM4IAgUFYWNjdW0JAMwIAgkBC0RlbGV0ZUVudHJ5AQkArAICAhpyZWJhbGFuY2VfYXR0YWNoZWRQYXltZW50XwUHYXNzZXRJZAUDbmlsBApybVBheW1lbnRzCgACJGwFDWFkZGVkQXNzZXRzTGkKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjZfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBEWFkZFJlbW92ZVBheW1lbnRzAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY2XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNl8yAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKBBFmaW5hbEFzc2V0c0lkc1N0cgkBDHRyeUdldFN0cmluZwECEnJlYmFsYW5jZV9hc3NldElkcwQQQXNzZXRzV2VpZ2h0c1N0cgoAAiRsCQC1CQIFEWZpbmFsQXNzZXRzSWRzU3RyAgEsCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGY3XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARdhZGRBc3NldFdlaWdodFRvU3RyTGlzdAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmN18yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjdfMgIJAQUkZjdfMQIJAQUkZjdfMQIJAQUkZjdfMQIJAQUkZjdfMQIJAQUkZjdfMQIJAQUkZjdfMQIJAQUkZjdfMQIJAQUkZjdfMQIJAQUkZjdfMQIJAQUkZjdfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgQGbm90aWZ5CQD8BwQFCmdvdkFkZHJlc3MCFW5vdGlmeVJlYmFsYW5jaW5nRG9uZQkAzAgCBQVyZWJJZAUDbmlsBQNuaWwDCQAAAgUGbm90aWZ5BQZub3RpZnkJAM4IAgkAzggCCQDOCAIFB2FjdGlvbnMFAnJtBQpybVBheW1lbnRzCQDMCAIJAQtTdHJpbmdFbnRyeQICD3N0YXRpY190b2tlbklkcwURZmluYWxBc3NldHNJZHNTdHIJAMwIAgkBC1N0cmluZ0VudHJ5AgITc3RhdGljX3Rva2VuV2VpZ2h0cwkAuQkCBRBBc3NldHNXZWlnaHRzU3RyAgEsCQDMCAIJAQxJbnRlZ2VyRW50cnkCAhNzdGF0aWNfdG9rZW5zQW1vdW50CQCQAwEJALUJAgURZmluYWxBc3NldHNJZHNTdHICASwFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgQRZmluYWxBc3NldHNJZHNTdHIJAQx0cnlHZXRTdHJpbmcBAhJyZWJhbGFuY2VfYXNzZXRJZHMEEEFzc2V0c1dlaWdodHNTdHIKAAIkbAkAtQkCBRFmaW5hbEFzc2V0c0lkc1N0cgIBLAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmNV8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEXYWRkQXNzZXRXZWlnaHRUb1N0ckxpc3QCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjVfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY1XzICCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoJAM4IAgUHYWN0aW9ucwkAzAgCCQELU3RyaW5nRW50cnkCAhNzdGF0aWNfdG9rZW5XZWlnaHRzCQC5CQIFEEFzc2V0c1dlaWdodHNTdHICASwFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ1kb1JlYmFsYW5jaW5nAQ9hc3NldFdlaWdodHNTdHIEC19pc1NodXRkb3duAwkBCmlzU2h1dGRvd24ACQACAQITY29udHJhY3QgaXMgb24gc3RvcAYDCQAAAgULX2lzU2h1dGRvd24FC19pc1NodXRkb3duBBFhc3NldFdlaWdodHNTdHJMaQkAtQkCBQ9hc3NldFdlaWdodHNTdHICASwED2Fzc2V0V2VpZ2h0c1N1bQoAAiRsBRFhc3NldFdlaWdodHNTdHJMaQoAAiRzCQCQAwEFAiRsCgAFJGFjYzAAAAoBBSRmNF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEDc3VtAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY0XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNF8yAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKBA1hc3NldElkc1N0ckxpCQC1CQIJAQx0cnlHZXRTdHJpbmcBAg9zdGF0aWNfdG9rZW5JZHMCASwDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAiJ0aGlzIGNhbGwgYXZhaWxhYmxlIG9ubHkgZm9yIGFkbWluBAhvbGRLTXVsdAkBCGdldEtNdWx0AAoBB2hhbmRsZXICBHBhcnMHYXNzZXRJZAQFYWNjdW0IBQRwYXJzAl8xBAphc3NldElkU3RyCQEOZ2V0QXNzZXRTdHJpbmcBBQdhc3NldElkCgEIaGFuZGxlcjICBWFjY3VtAW4DCQAAAgUBbgUHYXNzZXRJZAkBBXZhbHVlAQkAzwgCBQhhc3NldElkcwUBbgUFYWNjdW0EBVRva2VuCgACJGwFCGFzc2V0SWRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAABCgEFJGY1XzECAiRhAiRpAwkAZwIFAiRpBQIk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CgkAzAgCCQEMSW50ZWdlckVudHJ5AgIMc3RhdGljX0tNdWx0BQhuZXdLTXVsdAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBGmRvUmViYWxhbmNpbmdXaXRoTmV3VG9rZW5zAwthc3NldElkc1N0cg9hc3NldFdlaWdodHNTdHIOYmFzZVRva2VuSWRTdHIEC19pc1NodXRkb3duAwkBCmlzU2h1dGRvd24ACQACAQITY29udHJhY3QgaXMgb24gc3RvcAYDCQAAAgULX2lzU2h1dGRvd24FC19pc1NodXRkb3duBBRuZXdBc3NldFdlaWdodHNTdHJMaQkAtQkCBQ9hc3NldFdlaWdodHNTdHICASwEEXByZXZBc3NldElkc1N0ckxpCQC1CQIJAQx0cnlHZXRTdHJpbmcBAg9zdGF0aWNfdG9rZW5JZHMCASwEEG5ld0Fzc2V0SWRzU3RyTGkJALUJAgULYXNzZXRJZHNTdHICASwEC25ld0Fzc2V0SWRzCgACJGwFEG5ld0Fzc2V0SWRzU3RyTGkKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjRfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBE2FkZEFzc2V0Qnl0ZXNUb0xpc3QCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjRfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY0XzICCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoEC2ZlZUFzc2V0U3RyCgACJGwFEG5ld0Fzc2V0SWRzU3RyTGkKAAIkcwkAkAMBBQIkbAoABSRhY2MwAgAKAQUkZjVfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBDWNoZWNrRmVlQXNzZXQCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjVfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY1XzICCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoEC2FkZGVkQXNzZXRzCQC1CQIJAQx0cnlHZXRTdHJpbmcBAhVyZWJhbGFuY2VfYWRkZWRBc3NldHMCASwKARBmaW5kQXNzZXRQYXltZW50AQdhc3NldElkCQELdmFsdWVPckVsc2UCCQCfCAEJAKwCAgIacmViYWxhbmNlX2F0dGFjaGVkUGF5bWVudF8JAQ5nZXRBc3NldFN0cmluZwEFB2Fzc2V0SWQAAAoBE2FkZEFzc2V0QmFsYW5jZVRvTGkCAmxpB2Fzc2V0SWQJAM4IAgUCbGkJAMwIAgkBEGZpbmRBc3NldFBheW1lbnQBBQdhc3NldElkBQNuaWwEEGF0dGFjaGVkQmFsYW5jZXMKAAIkbAULbmV3QXNzZXRJZHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjZfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBE2FkZEFzc2V0QmFsYW5jZVRvTGkCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjZfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY2XzICCQEFJGY2XzECCQEFJGY2XzECCQEFJGY2XzECCQEFJGY2XzECCQEFJGY2XzECCQEFJGY2XzECCQEFJGY2XzECCQEFJGY2XzECCQEFJGY2XzECCQEFJGY2XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBCQCsAgICJHRoaXMgY2FsbCBhdmFpbGFibGUgb25seSBmb3IgYWRtaW4sIAkApQgBCAUBaQZjYWxsZXIECG9sZEtNdWx0CQEIZ2V0S011bHQABARvbGRLCQEZZ2V0VmlydHVhbFBvb2xUb2tlbkFtb3VudAAKARJteWx0aXBseUFzc2V0c0ZvcksCBHBhcnMHYXNzZXRJZAoBDGZpbmRBc3NldE51bQIFYWNjdW0BbgMJAAACBQFuBQdhc3NldElkCQEFdmFsdWUBCQDPCAIFC25ld0Fzc2V0SWRzBQFuBQVhY2N1bQQIY3VycmVudEsFBHBhcnMECmFzc2V0SWRTdHIJAQ5nZXRBc3NldFN0cmluZwEFB2Fzc2V0SWQECFRva2VuTnVtCgACJGwFC25ld0Fzc2V0SWRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAABCgEFJGY3XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQxmaW5kQXNzZXROdW0CBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjdfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY3XzICCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoEBndlaWdodAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFFG5ld0Fzc2V0V2VpZ2h0c1N0ckxpBQhUb2tlbk51bQQOYmFsYW5jZUluU3RhdGUJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB2dsb2JhbF8FCmFzc2V0SWRTdHICCF9iYWxhbmNlBBBiYWxhbmNlSW5QYXltZW50CQCRAwIFEGF0dGFjaGVkQmFsYW5jZXMFCFRva2VuTnVtBAdiYWxhbmNlCQBkAgUOYmFsYW5jZUluU3RhdGUFEGJhbGFuY2VJblBheW1lbnQEDWFzc2V0RGVjaW1hbHMDCQAAAgUHYXNzZXRJZAUEdW5pdAAICAkBBXZhbHVlAQkA7AcBCQEFdmFsdWUBBQdhc3NldElkCGRlY2ltYWxzAwkAZwIAAAUHYmFsYW5jZQkAAgEJAKwCAgJEeW91IG5lZWQgdG8gYXR0YWNoIGFsbCBuZXcgYXNzZXRzIGluIHBheW1lbnQuIHRoaXMgYXNzZXQgaXMgbWlzc2VkOiAFCmFzc2V0SWRTdHIJAGsDBQhjdXJyZW50SwkAbAYFB2JhbGFuY2UFDWFzc2V0RGVjaW1hbHMFBndlaWdodAUVQXNzZXRzV2VpZ2h0c0RlY2ltYWxzAAgFBUZMT09SBQZTY2FsZTgEBG5ld0sKAAIkbAULbmV3QXNzZXRJZHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQ5Qb29sVG9rZW5TY2FsZQoBBSRmN18xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQESbXlsdGlwbHlBc3NldHNGb3JLAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY3XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmN18yAgkBBSRmN18xAgkBBSRmN18xAgkBBSRmN18xAgkBBSRmN18xAgkBBSRmN18xAgkBBSRmN18xAgkBBSRmN18xAgkBBSRmN18xAgkBBSRmN18xAgkBBSRmN18xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKBAhuZXdLTXVsdAkAawMFCG9sZEtNdWx0BQRuZXdLBQRvbGRLCgETYWRkVG9rZW5EYXRhRW50cmllcwIFYWNjdW0IYXNzZXROdW0ECmFzc2V0SWRTdHIJAJEDAgUQbmV3QXNzZXRJZHNTdHJMaQUIYXNzZXROdW0EB2Fzc2V0SWQJAJEDAgULbmV3QXNzZXRJZHMFCGFzc2V0TnVtBA1hc3NldERlY2ltYWxzAwkAAAIFB2Fzc2V0SWQFBHVuaXQACAgJAQV2YWx1ZQEJAOwHAQkBBXZhbHVlAQUHYXNzZXRJZAhkZWNpbWFscwQMbmV3QXNzZXREYXRhAwkBAiE9AgkAzwgCBQthZGRlZEFzc2V0cwUKYXNzZXRJZFN0cgUEdW5pdAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgICB2dsb2JhbF8FCmFzc2V0SWRTdHICCF9iYWxhbmNlCQCRAwIFEGF0dGFjaGVkQmFsYW5jZXMFCGFzc2V0TnVtCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgIHc3RhdGljXwUKYXNzZXRJZFN0cgIGX3NjYWxlCQBsBgAKAAAFDWFzc2V0RGVjaW1hbHMAAAAABQRET1dOCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgIHc3RhdGljXwUKYXNzZXRJZFN0cgIJX2RlY2ltYWxzBQ1hc3NldERlY2ltYWxzBQNuaWwFA25pbAMJAGcCBQhhc3NldE51bQkAkAMBBRRuZXdBc3NldFdlaWdodHNTdHJMaQUFYWNjdW0JAM4IAgkAzggCBQVhY2N1bQkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgICB3N0YXRpY18FCmFzc2V0SWRTdHICB193ZWlnaHQJAQV2YWx1ZQEJALYJAQkAkQMCBRRuZXdBc3NldFdlaWdodHNTdHJMaQUIYXNzZXROdW0FA25pbAUMbmV3QXNzZXREYXRhCQDOCAIKAAIkbAkAzAgCAAAJAMwIAgABCQDMCAIAAgkAzAgCAAMJAMwIAgAECQDMCAIABQkAzAgCAAYJAMwIAgAHCQDMCAIACAkAzAgCAAkFA25pbAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmOF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQETYWRkVG9rZW5EYXRhRW50cmllcwIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmOF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjhfMgIJAQUkZjhfMQIJAQUkZjhfMQIJAQUkZjhfMQIJAQUkZjhfMQIJAQUkZjhfMQIJAQUkZjhfMQIJAQUkZjhfMQIJAQUkZjhfMQIJAQUkZjhfMQIJAQUkZjhfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgkAzAgCCQELU3RyaW5nRW50cnkCAg9zdGF0aWNfdG9rZW5JZHMFC2Fzc2V0SWRzU3RyCQDMCAIJAQtTdHJpbmdFbnRyeQICD3N0YXRpY19mZWVUb2tlbgULZmVlQXNzZXRTdHIJAMwIAgkBC1N0cmluZ0VudHJ5AgITc3RhdGljX3Rva2VuV2VpZ2h0cwUPYXNzZXRXZWlnaHRzU3RyCQDMCAIJAQxJbnRlZ2VyRW50cnkCAhNzdGF0aWNfdG9rZW5zQW1vdW50CQCQAwEFC25ld0Fzc2V0SWRzCQDMCAIJAQxJbnRlZ2VyRW50cnkCAgxzdGF0aWNfS011bHQFCG5ld0tNdWx0BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BAnR4AQZ2ZXJpZnkAAwMJAAACCQELdmFsdWVPckVsc2UCCQCfCAECE2dsb2JhbF93YXNQcmVJbml0ZWQAAAAAAwkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAgFAnR4D3NlbmRlclB1YmxpY0tleQYJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAAFDG1hc3RlclB1YktleQcGBAxfbXVsdGlzaWdTdHICIzNQSmRWRXJINVZtVll2a3VOM0F5cnJ0ZDF6Q1o0WHJ1NmdUBAttdWx0aXNpZ1N0cgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzAhBBUFBST1ZFUl9BRERSRVNTBQxfbXVsdGlzaWdTdHIED211bHRpc2lnQWRkcmVzcwkApggBBQttdWx0aXNpZ1N0cgQKbXVsdGlzaWdPawQHJG1hdGNoMAUPbXVsdGlzaWdBZGRyZXNzAwkAAQIFByRtYXRjaDACB0FkZHJlc3MEAXQFByRtYXRjaDAGBwQIaXNJbml0ZWQDBQptdWx0aXNpZ09rCQELdmFsdWVPckVsc2UCCQCbCAIJAQV2YWx1ZQEFD211bHRpc2lnQWRkcmVzcwIGSU5JVEVEBwcECWhhc0FkbWlucwMFCm11bHRpc2lnT2sJAQIhPQIJAQt2YWx1ZU9yRWxzZQIJAJ0IAgkBBXZhbHVlAQUPbXVsdGlzaWdBZGRyZXNzAgtBRE1JTlNfUEJLUwIAAgAHAwMDBQptdWx0aXNpZ09rBQhpc0luaXRlZAcFCWhhc0FkbWlucwcEByRtYXRjaDAFAnR4AwkAAQIFByRtYXRjaDACFFNldFNjcmlwdFRyYW5zYWN0aW9uBAN0dHgFByRtYXRjaDAEByRtYXRjaDEIBQN0dHgGc2NyaXB0AwkAAQIFByRtYXRjaDECCkJ5dGVWZWN0b3IEBnNjcmlwdAUHJG1hdGNoMQQLc2NyaXB0SGFzaGEJANgEAQkA9gMBBQZzY3JpcHQECXZhbGlkRnJvbQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIJAQV2YWx1ZQEFD211bHRpc2lnQWRkcmVzcwkArAICCQCsAgIJAKwCAgkArAICAghzY3JpcHQlJQUNQ09OVFJBQ1RfVFlQRQICJSUFC3NjcmlwdEhhc2hhAgslJXZhbGlkRnJvbQIRdmFsaWRGcm9tIG5vdCBzZXQEB3ZhbGlkVG8JARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCCQEFdmFsdWUBBQ9tdWx0aXNpZ0FkZHJlc3MJAKwCAgkArAICCQCsAgIJAKwCAgIIc2NyaXB0JSUFDUNPTlRSQUNUX1RZUEUCAiUlBQtzY3JpcHRIYXNoYQIJJSV2YWxpZFRvAg92YWxpZFRvIG5vdCBzZXQDCQBnAgUGaGVpZ2h0BQl2YWxpZEZyb20JAGcCBQd2YWxpZFRvBQZoZWlnaHQHBwQDb3R4BQckbWF0Y2gwBAZ0YXNrSWQJAKwCAgkArAICCQCsAgICA3R4XwkApQgBBQR0aGlzAgFfCQDYBAEIBQNvdHgCaWQECmlzQXBwcm92ZWQJAQt2YWx1ZU9yRWxzZQIJAJsIAgkBBXZhbHVlAQUPbXVsdGlzaWdBZGRyZXNzCQCsAgIJAKwCAgkArAICCQClCAEFBHRoaXMCAV8JANgEAQgFA290eAJpZAIKX19hcHByb3ZlZAcEDGFwcHJvdmVkRnJvbQkBC3ZhbHVlT3JFbHNlAgkAmggCCQEFdmFsdWUBBQ9tdWx0aXNpZ0FkZHJlc3MJAKwCAgUGdGFza0lkAg5fX2FwcHJvdmVkRnJvbQAAAwUKaXNBcHByb3ZlZAkAZwIFBmhlaWdodAUMYXBwcm92ZWRGcm9tBwQHJG1hdGNoMAUCdHgDCQABAgUHJG1hdGNoMAIUU2V0U2NyaXB0VHJhbnNhY3Rpb24EA3R0eAUHJG1hdGNoMAMJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAAIBQJ0eA9zZW5kZXJQdWJsaWNLZXkGCQD0AwMIBQN0dHgJYm9keUJ5dGVzCQCRAwIIBQN0dHgGcHJvb2ZzAAAFDG1hc3RlclB1YktleQfuOGDu", "height": 765047, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: none Next: none Full:
OldNewDifferences
1-# no script
1+{-# STDLIB_VERSION 6 #-}
2+{-# SCRIPT_TYPE ACCOUNT #-}
3+{-# CONTENT_TYPE DAPP #-}
4+let VERSION = "PZ-1.4.8 PROD"
5+
6+let CONTRACT_TYPE = "MULTIPOOL"
7+
8+let WAVES_RESERVE = 10000000
9+
10+let configStr = valueOrElse(getString(this, "configAddress"), "3PPEBRg4s2af2rQ2ZbLvdu1Hfd4Vo6QVDTo")
11+
12+let CONFIG_ADDRESS = if ((configStr == ""))
13+ then this
14+ else Address(fromBase58String(configStr))
15+
16+let AssetsWeightsDecimals = 4
17+
18+let Scale = 10000
19+
20+let Scale8 = 100000000
21+
22+let Scale16 = 10000000000000000
23+
24+let FeeScale = 10000
25+
26+let PoolTokenDecimals = 8
27+
28+let PoolTokenScale = pow(10, 0, PoolTokenDecimals, 0, 0, HALFUP)
29+
30+let GLOBAL_MIN_STEP_LIMIT = 2
31+
32+let MIN_STEPS_AMOUNT = max([GLOBAL_MIN_STEP_LIMIT, valueOrElse(getInteger(CONFIG_ADDRESS, "min_steps_amount"), GLOBAL_MIN_STEP_LIMIT)])
33+
34+let MAX_STEPS_AMOUNT = valueOrElse(getInteger(CONFIG_ADDRESS, "max_steps_amount"), 500)
35+
36+let MIN_STEPS_INTERVAL = valueOrElse(getInteger(CONFIG_ADDRESS, "min_steps_interval"), 1)
37+
38+let MAX_STEPS_INTERVAL = valueOrElse(getInteger(CONFIG_ADDRESS, "max_steps_interval"), 10000)
39+
40+let MIN_WEIGHT = valueOrElse(getInteger(CONFIG_ADDRESS, "min_weight"), 100)
41+
42+let MAX_WEIGHT = valueOrElse(getInteger(CONFIG_ADDRESS, "max_weight"), 9900)
43+
44+func get_version () = VERSION
45+
46+
47+func tryGetInteger (key) = match getInteger(this, key) {
48+ case b: Int =>
49+ b
50+ case _ =>
51+ 0
52+}
53+
54+
55+func tryGetBinary (key) = match getBinary(this, key) {
56+ case b: ByteVector =>
57+ b
58+ case _ =>
59+ base58''
60+}
61+
62+
63+func tryGetString (key) = match getString(this, key) {
64+ case b: String =>
65+ b
66+ case _ =>
67+ ""
68+}
69+
70+
71+func tryGetStringOrThrow (key) = match getString(this, key) {
72+ case b: String =>
73+ b
74+ case _ =>
75+ throw(("no such key in data storage: " + key))
76+}
77+
78+
79+func getAssetString (assetId) = match assetId {
80+ case b: ByteVector =>
81+ toBase58String(b)
82+ case _ =>
83+ "WAVES"
84+}
85+
86+
87+func getAssetBytes (assetIdStr) = if ((assetIdStr == "WAVES"))
88+ then unit
89+ else fromBase58String(assetIdStr)
90+
91+
92+func getTokenBalance (assetId) = match assetId {
93+ case t: ByteVector =>
94+ assetBalance(this, t)
95+ case _ =>
96+ wavesBalance(this).regular
97+}
98+
99+
100+func getNodeAddress () = {
101+ let nodeAddressStr = tryGetString("static_nodeAddress")
102+ if ((nodeAddressStr == ""))
103+ then unit
104+ else addressFromString(nodeAddressStr)
105+ }
106+
107+
108+func rebalanceLeaseActions (wavesOut,nodeAddr) = {
109+ let _isPositive = if ((0 > wavesOut))
110+ then throw("negative amount of WAVES to lease")
111+ else true
112+ if ((_isPositive == _isPositive))
113+ then {
114+ let currentLeaseId = tryGetString("global_lastLeaseId")
115+ let cancelLeaseAction = if ((currentLeaseId != ""))
116+ then [LeaseCancel(fromBase58String(currentLeaseId))]
117+ else nil
118+ match nodeAddr {
119+ case node: Address =>
120+ let newLeaseAmount = ((wavesBalance(this).regular - wavesOut) - WAVES_RESERVE)
121+ if ((newLeaseAmount > 0))
122+ then {
123+ let leaseAction = Lease(node, newLeaseAmount)
124+ let newLeaseId = toBase58String(calculateLeaseId(leaseAction))
125+ if ((newLeaseId == currentLeaseId))
126+ then nil
127+ else (cancelLeaseAction ++ [leaseAction, StringEntry("global_lastLeaseId", newLeaseId), IntegerEntry("global_lastLeaseAmount", newLeaseAmount)])
128+ }
129+ else (cancelLeaseAction ++ (if ((currentLeaseId != ""))
130+ then [DeleteEntry("global_lastLeaseId"), DeleteEntry("global_lastLeaseAmount")]
131+ else nil))
132+ case _ =>
133+ (cancelLeaseAction ++ (if ((currentLeaseId != ""))
134+ then [DeleteEntry("global_lastLeaseId"), DeleteEntry("global_lastLeaseAmount")]
135+ else nil))
136+ }
137+ }
138+ else throw("Strict value is not equal to itself.")
139+ }
140+
141+
142+func addAssetBytesToList (accum,item) = (accum ++ [getAssetBytes(item)])
143+
144+
145+func addAssetWeightToList (accum,item) = (accum ++ [tryGetInteger((("static_" + getAssetString(item)) + "_weight"))])
146+
147+
148+func addAssetWeightToStrList (accum,item) = (accum ++ [toString(tryGetInteger((("static_" + item) + "_weight")))])
149+
150+
151+func addAssetDecimalsToList (accum,item) = (accum ++ [tryGetInteger((("static_" + getAssetString(item)) + "_decimals"))])
152+
153+
154+func addAssetScaleToList (accum,item) = (accum ++ [tryGetInteger((("static_" + getAssetString(item)) + "_scale"))])
155+
156+
157+func addIntToList (accum,item) = (accum ++ [parseIntValue(item)])
158+
159+
160+let usdnAssetIdStr = valueOrElse(getString(CONFIG_ADDRESS, "usdnAssetIdStr"), "DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p")
161+
162+let puzzleAssetIdStr = valueOrElse(getString(CONFIG_ADDRESS, "puzzleAssetIdStr"), "HEB8Qaw9xrWpWs8tHsiATYGBWDBtP2S7kcPALrMu43AS")
163+
164+let usdtAssetIdStr = valueOrElse(getString(CONFIG_ADDRESS, "usdtAssetIdStr"), "34N9YcEETLWn93qYQ64EsP1x89tSruJU44RrEMSXXEPJ")
165+
166+let usdtPptAssetIdStr = valueOrElse(getString(CONFIG_ADDRESS, "usdtPptAssetIdStr"), "9wc3LXNA4TEBsXyKtoLE9mrbDD7WMHXvXrCjZvabLAsi")
167+
168+let romeAssetIdStr = valueOrElse(getString(CONFIG_ADDRESS, "romeAssetIdStr"), "AP4Cb5xLYGH6ZigHreCZHoXpQTWDkPsG2BHqfDUx6taJ")
169+
170+let wavesAssetIdStr = "WAVES"
171+
172+let usdnAssetId = fromBase58String(usdnAssetIdStr)
173+
174+let puzzleAssetId = fromBase58String(puzzleAssetIdStr)
175+
176+let usdtAssetId = fromBase58String(usdtAssetIdStr)
177+
178+let usdtPptAssetId = fromBase58String(usdtPptAssetIdStr)
179+
180+let romeAssetId = fromBase58String(romeAssetIdStr)
181+
182+let wavesAssetId = unit
183+
184+let supportedFeeAssetsStr = [usdnAssetIdStr, puzzleAssetIdStr, usdtAssetIdStr, usdtPptAssetIdStr, wavesAssetIdStr, romeAssetIdStr]
185+
186+let parentPoolAddress = Address(fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "parentPoolAddress"), "3PFDgzu1UtswAkCMxqqQjbTeHaX4cMab8Kh")))
187+
188+let masterAddress = Address(fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "masterAddress"), "3PLjwHcz9NEuaTo63NZR9B9okQiKQxZSbmf")))
189+
190+let masterPubKey = fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "masterPubKey"), "4z8CKSYQBKkzx7PBb5uBP1YPa6YAHRNTApW1sQVHT5eU"))
191+
192+let oracleAddress = Address(fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "oracleAddress"), "3P8d1E1BLKoD52y3bQJ1bDTd2TD1gpaLn9t")))
193+
194+let stakingAddress = Address(fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "stakingAddress"), "3PFTbywqxtFfukX3HyT881g4iW5K4QL3FAS")))
195+
196+let feesAddress = Address(fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "feesAddress"), "3PFWAVKmXjfHXyzJb12jCbhP4Uhi9t4uWiD")))
197+
198+let poolsHubAddress = Address(fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "poolsHubAddress"), "3P5YutjDNC3hABBVsveFuZTTbQ5PdtSDBgk")))
199+
200+let shutdownAddressStr = valueOrElse(getString(CONFIG_ADDRESS, "shutdownAddress"), "3PEpv9hRFWEEBU22WRnLsw1bH4YGtcU728o")
201+
202+let layer2Addresses = valueOrElse(getString(CONFIG_ADDRESS, "layer2Addresses"), "3PR1Qvi9mHT35SwWEkLSqqE2L8thiPLdVWU,3PQoBfUKHkJAeGWhooLP7WS8ovb54av9Jp2")
203+
204+let govAddress = Address(fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "govAddress"), "3P6uro9xCsE8te78QZjzqy7aq8natSzdceC")))
205+
206+let coldMasterAddress = Address(fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "coldMasterAddress"), "3PK9nhPfPbMBygB9ZgHVMHaQbSoojwrBfxj")))
207+
208+let T = tryGetInteger("static_tokensAmount")
209+
210+let assetIds = {
211+ let $l = split(tryGetString("static_tokenIds"), ",")
212+ let $s = size($l)
213+ let $acc0 = nil
214+ func $f0_1 ($a,$i) = if (($i >= $s))
215+ then $a
216+ else addAssetBytesToList($a, $l[$i])
217+
218+ func $f0_2 ($a,$i) = if (($i >= $s))
219+ then $a
220+ else throw("List size exceeds 10")
221+
222+ $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)
223+ }
224+
225+let AssetsWeights = {
226+ let $l = assetIds
227+ let $s = size($l)
228+ let $acc0 = nil
229+ func $f1_1 ($a,$i) = if (($i >= $s))
230+ then $a
231+ else addAssetWeightToList($a, $l[$i])
232+
233+ func $f1_2 ($a,$i) = if (($i >= $s))
234+ then $a
235+ else throw("List size exceeds 10")
236+
237+ $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)
238+ }
239+
240+let Decimals = {
241+ let $l = assetIds
242+ let $s = size($l)
243+ let $acc0 = nil
244+ func $f2_1 ($a,$i) = if (($i >= $s))
245+ then $a
246+ else addAssetDecimalsToList($a, $l[$i])
247+
248+ func $f2_2 ($a,$i) = if (($i >= $s))
249+ then $a
250+ else throw("List size exceeds 10")
251+
252+ $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)
253+ }
254+
255+let Scales = {
256+ let $l = assetIds
257+ let $s = size($l)
258+ let $acc0 = nil
259+ func $f3_1 ($a,$i) = if (($i >= $s))
260+ then $a
261+ else addAssetScaleToList($a, $l[$i])
262+
263+ func $f3_2 ($a,$i) = if (($i >= $s))
264+ then $a
265+ else throw("List size exceeds 10")
266+
267+ $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)
268+ }
269+
270+let Fee = tryGetInteger("static_fee")
271+
272+let earnedAssets = assetIds
273+
274+func isShutdown () = {
275+ let shutdownAddress = addressFromString(shutdownAddressStr)
276+ if ((shutdownAddress == unit))
277+ then false
278+ else {
279+ let globalShutdown = match getBoolean(value(shutdownAddress), "is_shutdown") {
280+ case x: Boolean =>
281+ x
282+ case _ =>
283+ false
284+ }
285+ let poolShutdown = valueOrElse(getBoolean(value(shutdownAddress), ("poolShutdown_" + toString(this))), false)
286+ if (globalShutdown)
287+ then true
288+ else poolShutdown
289+ }
290+ }
291+
292+
293+func getCurrentTokenBalance (tokenNum) = {
294+ let tokenIdStr = getAssetString(assetIds[tokenNum])
295+ tryGetInteger((("global_" + tokenIdStr) + "_balance"))
296+ }
297+
298+
299+func getKMult () = match getInteger("static_KMult") {
300+ case x: Int =>
301+ x
302+ case _ =>
303+ Scale16
304+}
305+
306+
307+func saveCurrentWeights () = {
308+ let assetIdsLi = split(tryGetString("static_tokenIds"), ",")
309+ func s (accum,assetId) = (accum ++ [IntegerEntry(("rebalance_startWeight_" + assetId), tryGetInteger((("static_" + assetId) + "_weight")))])
310+
311+ let $l = assetIdsLi
312+ let $s = size($l)
313+ let $acc0 = nil
314+ func $f4_1 ($a,$i) = if (($i >= $s))
315+ then $a
316+ else s($a, $l[$i])
317+
318+ func $f4_2 ($a,$i) = if (($i >= $s))
319+ then $a
320+ else throw("List size exceeds 10")
321+
322+ $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)
323+ }
324+
325+
326+func getVirtualPoolTokenAmount () = fraction(tryGetInteger("global_poolToken_amount"), getKMult(), Scale16)
327+
328+
329+func calculatePIssued (amount,tokenId) = {
330+ let Psupply = getVirtualPoolTokenAmount()
331+ let Balance = tryGetInteger((("global_" + getAssetString(tokenId)) + "_balance"))
332+ let t1 = fraction(amount, Psupply, Balance, DOWN)
333+ t1
334+ }
335+
336+
337+func getMinPIssued (payments) = {
338+ func handler (accum,current) = {
339+ let PIssued = calculatePIssued(current.amount, current.assetId)
340+ if ((PIssued == 0))
341+ then throw("one of the tokens amounts is too low")
342+ else if (if ((accum == 0))
343+ then true
344+ else (accum > PIssued))
345+ then PIssued
346+ else accum
347+ }
348+
349+ let minPIssed = {
350+ let $l = payments
351+ let $s = size($l)
352+ let $acc0 = 0
353+ func $f4_1 ($a,$i) = if (($i >= $s))
354+ then $a
355+ else handler($a, $l[$i])
356+
357+ func $f4_2 ($a,$i) = if (($i >= $s))
358+ then $a
359+ else throw("List size exceeds 10")
360+
361+ $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)
362+ }
363+ minPIssed
364+ }
365+
366+
367+func calculateUsdnValue (assetId,amount,aBalance,givenUsdnBalance) = {
368+ let usdnInPool = indexOf(assetIds, usdnAssetId)
369+ let puzzleInPool = indexOf(assetIds, puzzleAssetId)
370+ let usdtInPool = indexOf(assetIds, usdtAssetId)
371+ let usdtPptInPool = indexOf(assetIds, usdtPptAssetId)
372+ let wavesInPool = indexOf(assetIds, unit)
373+ let assetWeight = tryGetInteger((("static_" + getAssetString(assetId)) + "_weight"))
374+ let feeAssetStr = tryGetString("static_feeToken")
375+ if ((feeAssetStr == puzzleAssetIdStr))
376+ then {
377+ let puzzleWeight = AssetsWeights[value(indexOf(assetIds, puzzleAssetId))]
378+ let puzzleBalance = tryGetInteger((("global_" + puzzleAssetIdStr) + "_balance"))
379+ let amountInPuzzle = fraction(amount, (puzzleBalance / puzzleWeight), (aBalance / assetWeight))
380+ let puzzlePrice = getIntegerValue(parentPoolAddress, "global_lastPuzzlePrice")
381+ fraction((amountInPuzzle * puzzlePrice), 1, Scale8)
382+ }
383+ else if ((feeAssetStr == usdtAssetIdStr))
384+ then {
385+ let usdtWeight = AssetsWeights[value(usdtInPool)]
386+ let usdtBalance = tryGetInteger((("global_" + usdtAssetIdStr) + "_balance"))
387+ fraction(amount, (usdtBalance / usdtWeight), (aBalance / assetWeight))
388+ }
389+ else if ((feeAssetStr == usdtPptAssetIdStr))
390+ then {
391+ let usdtWeight = AssetsWeights[value(usdtPptInPool)]
392+ let usdtBalance = tryGetInteger((("global_" + usdtPptAssetIdStr) + "_balance"))
393+ fraction(amount, (usdtBalance / usdtWeight), (aBalance / assetWeight))
394+ }
395+ else if ((feeAssetStr == usdnAssetIdStr))
396+ then {
397+ let usdnWeight = AssetsWeights[value(indexOf(assetIds, usdnAssetId))]
398+ let usdnBalance = match givenUsdnBalance {
399+ case x: Int =>
400+ givenUsdnBalance
401+ case _ =>
402+ tryGetInteger((("global_" + getAssetString(usdnAssetId)) + "_balance"))
403+ }
404+ fraction(amount, (value(usdnBalance) / usdnWeight), (aBalance / assetWeight))
405+ }
406+ else {
407+ let wavesWeight = 3000
408+ let wBalance = (tryGetInteger("global_WAVES_balance") / 50)
409+ fraction(amount, (wBalance / wavesWeight), (aBalance / assetWeight))
410+ }
411+ }
412+
413+
414+func getPriceFromOracle (assetIdStr) = match getInteger(oracleAddress, (assetIdStr + "_twap5B")) {
415+ case x: Int =>
416+ x
417+ case _ =>
418+ 0
419+}
420+
421+
422+func calculateUsdValue (assetId,amount,aBalance) = {
423+ let assetWeight = tryGetInteger((("static_" + getAssetString(assetId)) + "_weight"))
424+ let feeAssetStr = tryGetString("static_feeToken")
425+ let feeAssetScale = getIntegerValue(this, (("static_" + feeAssetStr) + "_scale"))
426+ let feeAssetNum = value(indexOf(assetIds, getAssetBytes(feeAssetStr)))
427+ let feeAssetWeight = AssetsWeights[feeAssetNum]
428+ let feeAssetBalance = tryGetInteger((("global_" + feeAssetStr) + "_balance"))
429+ let valInFeeAsset = fraction(amount, (feeAssetBalance / feeAssetWeight), (aBalance / assetWeight))
430+ let feeAssetPrice = getPriceFromOracle(feeAssetStr)
431+ fraction(valInFeeAsset, feeAssetPrice, feeAssetScale)
432+ }
433+
434+
435+func checkTokensValidity (payments) = {
436+ func handler1 (accum,payment) = (accum ++ [payment.assetId])
437+
438+ let ids = {
439+ let $l = payments
440+ let $s = size($l)
441+ let $acc0 = nil
442+ func $f4_1 ($a,$i) = if (($i >= $s))
443+ then $a
444+ else handler1($a, $l[$i])
445+
446+ func $f4_2 ($a,$i) = if (($i >= $s))
447+ then $a
448+ else throw("List size exceeds 10")
449+
450+ $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)
451+ }
452+ if ((ids == ids))
453+ then {
454+ func handler2 (accum,assetId) = if ((indexOf(ids, assetId) != unit))
455+ then (accum + 1)
456+ else throw(("asset not attached: " + getAssetString(assetId)))
457+
458+ let checks = {
459+ let $l = assetIds
460+ let $s = size($l)
461+ let $acc0 = 0
462+ func $f5_1 ($a,$i) = if (($i >= $s))
463+ then $a
464+ else handler2($a, $l[$i])
465+
466+ func $f5_2 ($a,$i) = if (($i >= $s))
467+ then $a
468+ else throw("List size exceeds 10")
469+
470+ $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)
471+ }
472+ if ((checks == checks))
473+ then true
474+ else throw("Strict value is not equal to itself.")
475+ }
476+ else throw("Strict value is not equal to itself.")
477+ }
478+
479+
480+func handlePoolTokensAdd (PIssued,payments,userAddress,needChange) = {
481+ func getTokenPaymentAmount (tokenId) = {
482+ func handler (accum,payment) = if ((payment.assetId == tokenId))
483+ then payment.amount
484+ else accum
485+
486+ let $l = payments
487+ let $s = size($l)
488+ let $acc0 = 0
489+ func $f4_1 ($a,$i) = if (($i >= $s))
490+ then $a
491+ else handler($a, $l[$i])
492+
493+ func $f4_2 ($a,$i) = if (($i >= $s))
494+ then $a
495+ else throw("List size exceeds 10")
496+
497+ $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)
498+ }
499+
500+ func handleTokenChange (accum,tokenId) = {
501+ let Bk = tryGetInteger((("global_" + getAssetString(tokenId)) + "_balance"))
502+ let PSupply = getVirtualPoolTokenAmount()
503+ let Dk = toInt(fraction(toBigInt(PIssued), toBigInt(Bk), toBigInt(PSupply), CEILING))
504+ let paymentAmount = getTokenPaymentAmount(tokenId)
505+ let toReturn = (paymentAmount - Dk)
506+ let t = if (if (needChange)
507+ then (toReturn > 0)
508+ else false)
509+ then [ScriptTransfer(userAddress, toReturn, tokenId)]
510+ else nil
511+ ((accum ++ t) ++ [IntegerEntry((("global_" + getAssetString(tokenId)) + "_balance"), (Bk + Dk))])
512+ }
513+
514+ let $l = assetIds
515+ let $s = size($l)
516+ let $acc0 = nil
517+ func $f4_1 ($a,$i) = if (($i >= $s))
518+ then $a
519+ else handleTokenChange($a, $l[$i])
520+
521+ func $f4_2 ($a,$i) = if (($i >= $s))
522+ then $a
523+ else throw("List size exceeds 10")
524+
525+ $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)
526+ }
527+
528+
529+func handlePoolTokensRedeem (PRedeemed,userAddress) = {
530+ func handleTokenRedeem (accum,tokenId) = {
531+ let Bk = tryGetInteger((("global_" + getAssetString(tokenId)) + "_balance"))
532+ let PSupply = getVirtualPoolTokenAmount()
533+ let amount = toInt(fraction(toBigInt(PRedeemed), toBigInt(Bk), toBigInt(PSupply), DOWN))
534+ (accum ++ [IntegerEntry((("global_" + getAssetString(tokenId)) + "_balance"), (Bk - amount)), ScriptTransfer(userAddress, amount, tokenId)])
535+ }
536+
537+ let $l = assetIds
538+ let $s = size($l)
539+ let $acc0 = nil
540+ func $f4_1 ($a,$i) = if (($i >= $s))
541+ then $a
542+ else handleTokenRedeem($a, $l[$i])
543+
544+ func $f4_2 ($a,$i) = if (($i >= $s))
545+ then $a
546+ else throw("List size exceeds 10")
547+
548+ $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)
549+ }
550+
551+
552+func calculateOutAmount_DOWN (AmountIn,assetIn,assetOut,BalanceIn,BalanceOut) = {
553+ let IndexIn = value(indexOf(assetIds, assetIn))
554+ let IndexOut = value(indexOf(assetIds, assetOut))
555+ if ((IndexIn == IndexOut))
556+ then AmountIn
557+ 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), DOWN)
558+ }
559+
560+
561+func calculateOutAmount_CEILING (AmountIn,assetIn,assetOut,BalanceIn,BalanceOut) = {
562+ let IndexIn = value(indexOf(assetIds, assetIn))
563+ let IndexOut = value(indexOf(assetIds, assetOut))
564+ if ((IndexIn == IndexOut))
565+ then AmountIn
566+ 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), CEILING)
567+ }
568+
569+
570+func calculateCurrentAssetInterest (assetId,assetIdStr,aBalance,tokenEarningsLastCheck) = {
571+ let totalStaked = tryGetInteger("global_indexStaked")
572+ let tokenBalanceLastCheck = tokenEarningsLastCheck
573+ let currentBalanceDelta = (getTokenBalance(assetId) - aBalance)
574+ let currentTokenEarnings = if ((currentBalanceDelta > tokenBalanceLastCheck))
575+ then currentBalanceDelta
576+ else tokenBalanceLastCheck
577+ let newEarnings = (currentTokenEarnings - tokenBalanceLastCheck)
578+ let newInterest = if ((totalStaked == 0))
579+ then 0
580+ else fraction(newEarnings, Scale8, totalStaked)
581+ let lastCheckInterest = tryGetInteger((("global_lastCheck_" + assetIdStr) + "_interest"))
582+ (lastCheckInterest + newInterest)
583+ }
584+
585+
586+func claimResult (address) = {
587+ let addressStr = toString(address)
588+ let puzzleAmount = tryGetInteger((addressStr + "_indexStaked"))
589+ func handler (accum,assetId) = {
590+ let assetIdStr = getAssetString(assetId)
591+ let aBalance = tryGetInteger((("global_" + getAssetString(assetId)) + "_balance"))
592+ let tokenEarningsLastCheck = tryGetInteger((("global_lastCheck_" + assetIdStr) + "_earnings"))
593+ let currentTokenInterest = calculateCurrentAssetInterest(assetId, assetIdStr, aBalance, tokenEarningsLastCheck)
594+ let currentTokenEarnings = max([tokenEarningsLastCheck, (getTokenBalance(assetId) - aBalance)])
595+ let rewardAmount = fraction(puzzleAmount, (currentTokenInterest - tryGetInteger((((addressStr + "_lastCheck_") + assetIdStr) + "_interest"))), Scale8)
596+ let transfer = if ((rewardAmount == 0))
597+ then nil
598+ else [ScriptTransfer(address, rewardAmount, assetId)]
599+ $Tuple2(((accum._1 ++ transfer) ++ [IntegerEntry((("global_lastCheck_" + assetIdStr) + "_earnings"), (currentTokenEarnings - rewardAmount)), IntegerEntry((("global_lastCheck_" + assetIdStr) + "_interest"), currentTokenInterest), IntegerEntry((((addressStr + "_lastCheck_") + assetIdStr) + "_interest"), currentTokenInterest)]), (accum._2 + calculateUsdValue(assetId, rewardAmount, aBalance)))
600+ }
601+
602+ let accum = {
603+ let $l = earnedAssets
604+ let $s = size($l)
605+ let $acc0 = $Tuple2(nil, 0)
606+ func $f4_1 ($a,$i) = if (($i >= $s))
607+ then $a
608+ else handler($a, $l[$i])
609+
610+ func $f4_2 ($a,$i) = if (($i >= $s))
611+ then $a
612+ else throw("List size exceeds 10")
613+
614+ $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)
615+ }
616+ $Tuple2((accum._1 ++ [IntegerEntry((addressStr + "_claimedRewardUSD"), (tryGetInteger((addressStr + "_claimedRewardUSD")) + accum._2)), IntegerEntry((addressStr + "_lastClaim"), lastBlock.timestamp)]), accum._2)
617+ }
618+
619+
620+func getWavesClaimAmount (address) = if ((indexOf(assetIds, unit) == unit))
621+ then 0
622+ else {
623+ let addressStr = toString(address)
624+ let puzzleAmount = tryGetInteger((addressStr + "_indexStaked"))
625+ let aBalance = tryGetInteger("global_WAVES_balance")
626+ let tokenEarningsLastCheck = tryGetInteger("global_lastCheck_WAVES_earnings")
627+ let currentTokenInterest = calculateCurrentAssetInterest(unit, "WAVES", aBalance, tokenEarningsLastCheck)
628+ let rewardAmount = fraction(puzzleAmount, (currentTokenInterest - tryGetInteger((addressStr + "_lastCheck_WAVES_interest"))), Scale8)
629+ max([0, rewardAmount])
630+ }
631+
632+
633+func getWavesRedeemAmount (PRedeemed) = if ((indexOf(assetIds, unit) == unit))
634+ then 0
635+ else {
636+ let Bk = tryGetInteger("global_WAVES_balance")
637+ let PSupply = getVirtualPoolTokenAmount()
638+ toInt(fraction(toBigInt(PRedeemed), toBigInt(Bk), toBigInt(PSupply), CEILING))
639+ }
640+
641+
642+func getWavesChangeAmount (PIssued,payments,needChange) = if (if (!(needChange))
643+ then true
644+ else (indexOf(assetIds, unit) == unit))
645+ then 0
646+ else {
647+ func findWavesPayment (accum,pmt) = if ((pmt.assetId == unit))
648+ then pmt.amount
649+ else accum
650+
651+ let wavesPmt = {
652+ let $l = payments
653+ let $s = size($l)
654+ let $acc0 = 0
655+ func $f4_1 ($a,$i) = if (($i >= $s))
656+ then $a
657+ else findWavesPayment($a, $l[$i])
658+
659+ func $f4_2 ($a,$i) = if (($i >= $s))
660+ then $a
661+ else throw("List size exceeds 10")
662+
663+ $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)
664+ }
665+ if ((wavesPmt == 0))
666+ then 0
667+ else {
668+ let Bk = tryGetInteger("global_WAVES_balance")
669+ let PSupply = getVirtualPoolTokenAmount()
670+ let Dk = toInt(fraction(toBigInt(PIssued), toBigInt(Bk), toBigInt(PSupply), CEILING))
671+ max([0, (wavesPmt - Dk)])
672+ }
673+ }
674+
675+
676+func indexStakeResult (addressStr,amount) = {
677+ let li = claimResult(addressFromStringValue(addressStr))._1
678+ (li ++ [IntegerEntry((addressStr + "_indexStaked"), (tryGetInteger((addressStr + "_indexStaked")) + amount)), IntegerEntry("global_indexStaked", (tryGetInteger("global_indexStaked") + amount))])
679+ }
680+
681+
682+func isOwnerOrMaster (caller) = {
683+ let ownerAddress = addressFromStringValue(tryGetString("static_poolOwner"))
684+ if ((caller == ownerAddress))
685+ then true
686+ else (caller == masterAddress)
687+ }
688+
689+
690+func sum (accum,n) = (accum + parseIntValue(n))
691+
692+
693+func checkFeeAsset (accum,next) = if (if ((indexOf(supportedFeeAssetsStr, next) != unit))
694+ then (accum == "")
695+ else false)
696+ then next
697+ else accum
698+
699+
700+func getTmpRebalanceIds (newAssetIdsLi) = {
701+ let currentAssetIdsLi = split(tryGetString("static_tokenIds"), ",")
702+ let result = newAssetIdsLi
703+ func f (accum,assetId) = if ((indexOf(result, assetId) == unit))
704+ then (accum ++ [assetId])
705+ else accum
706+
707+ let $l = currentAssetIdsLi
708+ let $s = size($l)
709+ let $acc0 = result
710+ func $f4_1 ($a,$i) = if (($i >= $s))
711+ then $a
712+ else f($a, $l[$i])
713+
714+ func $f4_2 ($a,$i) = if (($i >= $s))
715+ then $a
716+ else throw("List size exceeds 10")
717+
718+ $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)
719+ }
720+
721+
722+func checkTokensChange (newAssetIdsLi) = {
723+ let currentAssetIdsLi = split(tryGetString("static_tokenIds"), ",")
724+ func rem (accum,assetId) = if ((indexOf(newAssetIdsLi, assetId) == unit))
725+ then (accum + 1)
726+ else accum
727+
728+ func add (accum,assetId) = if ((indexOf(currentAssetIdsLi, assetId) == unit))
729+ then (accum + 1)
730+ else accum
731+
732+ let removed = {
733+ let $l = currentAssetIdsLi
734+ let $s = size($l)
735+ let $acc0 = 0
736+ func $f4_1 ($a,$i) = if (($i >= $s))
737+ then $a
738+ else rem($a, $l[$i])
739+
740+ func $f4_2 ($a,$i) = if (($i >= $s))
741+ then $a
742+ else throw("List size exceeds 10")
743+
744+ $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)
745+ }
746+ let added = {
747+ let $l = newAssetIdsLi
748+ let $s = size($l)
749+ let $acc0 = 0
750+ func $f5_1 ($a,$i) = if (($i >= $s))
751+ then $a
752+ else add($a, $l[$i])
753+
754+ func $f5_2 ($a,$i) = if (($i >= $s))
755+ then $a
756+ else throw("List size exceeds 10")
757+
758+ $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)
759+ }
760+ (removed + added)
761+ }
762+
763+
764+func validatePayments (assetsList,payments) = {
765+ func getPaymentAssets (accum,next) = if ((0 >= next.amount))
766+ then throw(((("Too low payment amount for " + getAssetString(next.assetId)) + ": ") + toString(next.amount)))
767+ else (accum ++ [getAssetString(next.assetId)])
768+
769+ let paymentList = {
770+ let $l = payments
771+ let $s = size($l)
772+ let $acc0 = nil
773+ func $f4_1 ($a,$i) = if (($i >= $s))
774+ then $a
775+ else getPaymentAssets($a, $l[$i])
776+
777+ func $f4_2 ($a,$i) = if (($i >= $s))
778+ then $a
779+ else throw("List size exceeds 10")
780+
781+ $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)
782+ }
783+ func f1 (accum,next) = if ((indexOf(assetsList, next) == unit))
784+ then throw(((next + " asset is present in payments, but is not in new assets: ") + makeString(assetsList, ",")))
785+ else (accum + 1)
786+
787+ func f2 (accum,next) = if ((indexOf(paymentList, next) == unit))
788+ then throw(((next + " asset is present in new assets, but is not in payments: ") + makeString(paymentList, ",")))
789+ else (accum + 1)
790+
791+ let a1 = {
792+ let $l = paymentList
793+ let $s = size($l)
794+ let $acc0 = 0
795+ func $f5_1 ($a,$i) = if (($i >= $s))
796+ then $a
797+ else f1($a, $l[$i])
798+
799+ func $f5_2 ($a,$i) = if (($i >= $s))
800+ then $a
801+ else throw("List size exceeds 10")
802+
803+ $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)
804+ }
805+ let a2 = {
806+ let $l = assetsList
807+ let $s = size($l)
808+ let $acc0 = 0
809+ func $f6_1 ($a,$i) = if (($i >= $s))
810+ then $a
811+ else f2($a, $l[$i])
812+
813+ func $f6_2 ($a,$i) = if (($i >= $s))
814+ then $a
815+ else throw("List size exceeds 10")
816+
817+ $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)
818+ }
819+ (a1 + a2)
820+ }
821+
822+
823+func validateWeights (weights) = {
824+ func v (accum,w) = {
825+ let wInt = valueOrErrorMessage(parseInt(w), ("Wrong weight format: " + w))
826+ if (if ((MIN_WEIGHT > wInt))
827+ then true
828+ else (wInt > MAX_WEIGHT))
829+ then throw(((((("Weight should be in range " + toString(MIN_WEIGHT)) + " - ") + toString(MAX_WEIGHT)) + ", current: ") + w))
830+ else accum
831+ }
832+
833+ let $l = weights
834+ let $s = size($l)
835+ let $acc0 = 0
836+ func $f4_1 ($a,$i) = if (($i >= $s))
837+ then $a
838+ else v($a, $l[$i])
839+
840+ func $f4_2 ($a,$i) = if (($i >= $s))
841+ then $a
842+ else throw("List size exceeds 10")
843+
844+ $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)
845+ }
846+
847+
848+@Callable(i)
849+func setWavesNode (nodeAddress) = if (!(isOwnerOrMaster(i.caller)))
850+ then throw("admin/owner only")
851+ else {
852+ let _nodeAddress = addressFromString(nodeAddress)
853+ let nodeOk = match _nodeAddress {
854+ case t: Address =>
855+ true
856+ case _ =>
857+ false
858+ }
859+ let canSetNode = if (if (nodeOk)
860+ then true
861+ else (nodeAddress == ""))
862+ then true
863+ else throw("Wrong node address")
864+ if ((canSetNode == canSetNode))
865+ then {
866+ let selfSet = if ((_nodeAddress == this))
867+ then throw("Node address can't be contract's own address")
868+ else true
869+ if ((selfSet == selfSet))
870+ then {
871+ let newNodeAddr = if ((nodeAddress != ""))
872+ then _nodeAddress
873+ else unit
874+ let leaseActions = rebalanceLeaseActions(0, newNodeAddr)
875+ (leaseActions ++ [StringEntry("static_nodeAddress", nodeAddress)])
876+ }
877+ else throw("Strict value is not equal to itself.")
878+ }
879+ else throw("Strict value is not equal to itself.")
880+ }
881+
882+
883+
884+@Callable(i)
885+func preInit (assetIdsStr,assetWeightsStr,baseTokenIdStr,poolDomain,poolOwner,fee) = {
886+ let _checkPoolOwner = if ((addressFromString(poolOwner) == unit))
887+ then throw("wrong pool owner address")
888+ else true
889+ if ((_checkPoolOwner == _checkPoolOwner))
890+ then {
891+ let assetIdsStrLi = split(assetIdsStr, ",")
892+ let assetIdsLi = {
893+ let $l = assetIdsStrLi
894+ let $s = size($l)
895+ let $acc0 = nil
896+ func $f4_1 ($a,$i) = if (($i >= $s))
897+ then $a
898+ else addAssetBytesToList($a, $l[$i])
899+
900+ func $f4_2 ($a,$i) = if (($i >= $s))
901+ then $a
902+ else throw("List size exceeds 10")
903+
904+ $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)
905+ }
906+ let feeAssetStr = {
907+ let $l = assetIdsStrLi
908+ let $s = size($l)
909+ let $acc0 = ""
910+ func $f5_1 ($a,$i) = if (($i >= $s))
911+ then $a
912+ else checkFeeAsset($a, $l[$i])
913+
914+ func $f5_2 ($a,$i) = if (($i >= $s))
915+ then $a
916+ else throw("List size exceeds 10")
917+
918+ $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)
919+ }
920+ let basePresent = if ((indexOf(assetIdsStrLi, baseTokenIdStr) == unit))
921+ then throw("base token missing in list")
922+ else true
923+ if ((basePresent == basePresent))
924+ then if (isShutdown())
925+ then throw("contract is on stop")
926+ else if ((this != i.caller))
927+ then throw("admin only")
928+ else if ((feeAssetStr == ""))
929+ then throw("pool must have one of the supported fee assets in the composition")
930+ else if ((size(poolDomain) > 13))
931+ then throw("too large pool domain")
932+ else if (if ((fee > 500))
933+ then true
934+ else (0 > fee))
935+ then throw("fee value must be between 50 and 500 (0.5-5%)")
936+ else {
937+ let assetWeightsStrLi = split(assetWeightsStr, ",")
938+ let assetWeightsSum = {
939+ let $l = assetWeightsStrLi
940+ let $s = size($l)
941+ let $acc0 = 0
942+ func $f6_1 ($a,$i) = if (($i >= $s))
943+ then $a
944+ else sum($a, $l[$i])
945+
946+ func $f6_2 ($a,$i) = if (($i >= $s))
947+ then $a
948+ else throw("List size exceeds 10")
949+
950+ $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)
951+ }
952+ let sameLengths = if ((size(assetIdsStrLi) != size(assetWeightsStrLi)))
953+ then throw("assetIds and weights length mismatch")
954+ else true
955+ if ((sameLengths == sameLengths))
956+ then {
957+ func addTokenDataEntries (accum,assetNum) = if ((assetNum >= size(assetIdsLi)))
958+ then accum
959+ else {
960+ let assetDecimals = match assetIdsLi[assetNum] {
961+ case x: ByteVector =>
962+ value(assetInfo(x)).decimals
963+ case _ =>
964+ 8
965+ }
966+ (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])))])
967+ }
968+
969+ if ((assetWeightsSum != 10000))
970+ then throw("sum of token weights must be equal to 10000")
971+ else ({
972+ let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
973+ let $s = size($l)
974+ let $acc0 = nil
975+ func $f7_1 ($a,$i) = if (($i >= $s))
976+ then $a
977+ else addTokenDataEntries($a, $l[$i])
978+
979+ func $f7_2 ($a,$i) = if (($i >= $s))
980+ then $a
981+ else throw("List size exceeds 10")
982+
983+ $f7_2($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
984+ } ++ [StringEntry("static_tokenIds", assetIdsStr), StringEntry("static_feeToken", feeAssetStr), StringEntry("static_tokenWeights", assetWeightsStr), IntegerEntry("static_tokensAmount", size(assetIdsLi)), StringEntry("static_poolDomain", poolDomain), StringEntry("static_baseTokenId", baseTokenIdStr), StringEntry("static_poolOwner", poolOwner), IntegerEntry("static_fee", fee), IntegerEntry("static_KMult", Scale16), IntegerEntry("global_wasPreInited", 1)])
985+ }
986+ else throw("Strict value is not equal to itself.")
987+ }
988+ else throw("Strict value is not equal to itself.")
989+ }
990+ else throw("Strict value is not equal to itself.")
991+ }
992+
993+
994+
995+@Callable(i)
996+func deInit () = if (isShutdown())
997+ then throw("contract is on stop")
998+ else if ((i.caller != this))
999+ then throw("admin only")
1000+ else [IntegerEntry("global_wasInited", 0)]
1001+
1002+
1003+
1004+@Callable(i)
1005+func init () = {
1006+ func prepareList () = {
1007+ func handler (accum,n) = (accum ++ [IntegerEntry((("global_" + getAssetString(n.assetId)) + "_balance"), n.amount)])
1008+
1009+ let $l = i.payments
1010+ let $s = size($l)
1011+ let $acc0 = nil
1012+ func $f4_1 ($a,$i) = if (($i >= $s))
1013+ then $a
1014+ else handler($a, $l[$i])
1015+
1016+ func $f4_2 ($a,$i) = if (($i >= $s))
1017+ then $a
1018+ else throw("List size exceeds 10")
1019+
1020+ $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)
1021+ }
1022+
1023+ let _checkPaymentsSize = if ((size(i.payments) != T))
1024+ then throw((("you need to attach " + toString(T)) + " tokens to init the pool"))
1025+ else false
1026+ if ((_checkPaymentsSize == _checkPaymentsSize))
1027+ then {
1028+ let _checkTokensValidity = if (!(checkTokensValidity(i.payments)))
1029+ then throw("wrong assets attached")
1030+ else false
1031+ if ((_checkTokensValidity == _checkTokensValidity))
1032+ then {
1033+ func calculatePoolTokensAmount (payments) = {
1034+ func handler (accum,pmt) = {
1035+ let assetId = pmt.assetId
1036+ func handler2 (accum,n) = if ((n == assetId))
1037+ then value(indexOf(assetIds, n))
1038+ else accum
1039+
1040+ let Token = {
1041+ let $l = assetIds
1042+ let $s = size($l)
1043+ let $acc0 = 1
1044+ func $f4_1 ($a,$i) = if (($i >= $s))
1045+ then $a
1046+ else handler2($a, $l[$i])
1047+
1048+ func $f4_2 ($a,$i) = if (($i >= $s))
1049+ then $a
1050+ else throw("List size exceeds 10")
1051+
1052+ $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)
1053+ }
1054+ fraction(accum, pow(pmt.amount, Decimals[Token], AssetsWeights[Token], AssetsWeightsDecimals, 8, FLOOR), Scale8)
1055+ }
1056+
1057+ let $l = payments
1058+ let $s = size($l)
1059+ let $acc0 = PoolTokenScale
1060+ func $f4_1 ($a,$i) = if (($i >= $s))
1061+ then $a
1062+ else handler($a, $l[$i])
1063+
1064+ func $f4_2 ($a,$i) = if (($i >= $s))
1065+ then $a
1066+ else throw("List size exceeds 10")
1067+
1068+ $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)
1069+ }
1070+
1071+ if (isShutdown())
1072+ then throw("contract is on stop")
1073+ else if ((tryGetInteger("global_wasInited") > 0))
1074+ then throw("pool already inited")
1075+ else {
1076+ let initialPoolTokens = calculatePoolTokensAmount(i.payments)
1077+ if ((initialPoolTokens == 0))
1078+ then throw("you need a bigger tokens amount to launch the pool")
1079+ else {
1080+ let poolTokenIssue = Issue(("PZ " + tryGetString("static_poolDomain")), "Puzzle Swap: pool index token", initialPoolTokens, PoolTokenDecimals, true, unit, 0)
1081+ let poolTokenId = calculateAssetId(poolTokenIssue)
1082+ ((prepareList() ++ [poolTokenIssue, IntegerEntry("global_poolToken_amount", initialPoolTokens), IntegerEntry("global_wasInited", 1), BinaryEntry("global_poolToken_id", poolTokenId), StringEntry("static_poolToken_idStr", getAssetString(poolTokenId)), IntegerEntry((toString(i.caller) + "_indexStaked"), initialPoolTokens), IntegerEntry("global_indexStaked", initialPoolTokens)]) ++ rebalanceLeaseActions(0, getNodeAddress()))
1083+ }
1084+ }
1085+ }
1086+ else throw("Strict value is not equal to itself.")
1087+ }
1088+ else throw("Strict value is not equal to itself.")
1089+ }
1090+
1091+
1092+
1093+@Callable(i)
1094+func generateIndex (needChange) = if (isShutdown())
1095+ then throw("contract is on stop")
1096+ else if ((size(i.payments) != T))
1097+ then throw(("you need to attach all pool tokens. amount of pool tokens: " + toString(T)))
1098+ else if (!(checkTokensValidity(i.payments)))
1099+ then throw("wrong assets attached")
1100+ else {
1101+ let PIssuedNoMult = getMinPIssued(i.payments)
1102+ let result = handlePoolTokensAdd(PIssuedNoMult, i.payments, i.originCaller, needChange)
1103+ let PIssuedWithMult = fraction(PIssuedNoMult, Scale16, getKMult(), DOWN)
1104+ let reissue = Reissue(getBinaryValue("global_poolToken_id"), PIssuedWithMult, true)
1105+ let wavesOut = getWavesChangeAmount(PIssuedNoMult, i.payments, needChange)
1106+ let leaseActions = rebalanceLeaseActions(wavesOut, getNodeAddress())
1107+ $Tuple2(((leaseActions ++ result) ++ [reissue, ScriptTransfer(i.caller, PIssuedWithMult, tryGetBinary("global_poolToken_id")), IntegerEntry("global_poolToken_amount", (tryGetInteger("global_poolToken_amount") + PIssuedWithMult))]), PIssuedWithMult)
1108+ }
1109+
1110+
1111+
1112+@Callable(i)
1113+func redeemIndex (sendToOrigin) = {
1114+ let _checkPaymentsSize = if ((size(i.payments) != 1))
1115+ then throw("please attach exactly one payment")
1116+ else false
1117+ if ((_checkPaymentsSize == _checkPaymentsSize))
1118+ then {
1119+ let pmt = i.payments[0]
1120+ if ((pmt.assetId != tryGetBinary("global_poolToken_id")))
1121+ then throw("please attach pool share token")
1122+ else if (isShutdown())
1123+ then throw("contract is on stop")
1124+ else {
1125+ let PRedeemedWithMult = pmt.amount
1126+ let PRedeemedWithNoMult = fraction(PRedeemedWithMult, getKMult(), Scale16, DOWN)
1127+ let result = handlePoolTokensRedeem(PRedeemedWithNoMult, if (sendToOrigin)
1128+ then i.originCaller
1129+ else i.caller)
1130+ let wavesOut = getWavesRedeemAmount(PRedeemedWithNoMult)
1131+ let leaseActions = rebalanceLeaseActions(wavesOut, getNodeAddress())
1132+ ((leaseActions ++ result) ++ [Burn(tryGetBinary("global_poolToken_id"), PRedeemedWithMult), IntegerEntry("global_poolToken_amount", (tryGetInteger("global_poolToken_amount") - PRedeemedWithMult))])
1133+ }
1134+ }
1135+ else throw("Strict value is not equal to itself.")
1136+ }
1137+
1138+
1139+
1140+@Callable(i)
1141+func stakeIndex () = {
1142+ let _isShutdown = if (isShutdown())
1143+ then throw("contract is on stop")
1144+ else false
1145+ if ((_isShutdown == _isShutdown))
1146+ then {
1147+ let _checkPaymentsSize = if ((size(i.payments) != 1))
1148+ then throw("please attach exactly one payment")
1149+ else false
1150+ if ((_checkPaymentsSize == _checkPaymentsSize))
1151+ then {
1152+ let addressStr = toString(i.originCaller)
1153+ let pmt = i.payments[0]
1154+ if ((value(pmt.assetId) != tryGetBinary("global_poolToken_id")))
1155+ then throw("wrong asset attached")
1156+ else {
1157+ let wavesClaimOut = getWavesClaimAmount(i.originCaller)
1158+ (rebalanceLeaseActions(wavesClaimOut, getNodeAddress()) ++ indexStakeResult(addressStr, pmt.amount))
1159+ }
1160+ }
1161+ else throw("Strict value is not equal to itself.")
1162+ }
1163+ else throw("Strict value is not equal to itself.")
1164+ }
1165+
1166+
1167+
1168+@Callable(i)
1169+func stakeIndexFor (addressStr) = {
1170+ let _isShutdown = if (isShutdown())
1171+ then throw("contract is on stop")
1172+ else false
1173+ if ((_isShutdown == _isShutdown))
1174+ then {
1175+ let _checkPaymentsSize = if ((size(i.payments) != 1))
1176+ then throw("please attach exactly one payment")
1177+ else false
1178+ if ((_checkPaymentsSize == _checkPaymentsSize))
1179+ then {
1180+ let pmt = i.payments[0]
1181+ if ((value(pmt.assetId) != tryGetBinary("global_poolToken_id")))
1182+ then throw("wrong asset attached")
1183+ else {
1184+ let wavesClaimOut = getWavesClaimAmount(addressFromStringValue(addressStr))
1185+ (rebalanceLeaseActions(wavesClaimOut, getNodeAddress()) ++ indexStakeResult(addressStr, pmt.amount))
1186+ }
1187+ }
1188+ else throw("Strict value is not equal to itself.")
1189+ }
1190+ else throw("Strict value is not equal to itself.")
1191+ }
1192+
1193+
1194+
1195+@Callable(i)
1196+func unstakeIndex (indexAmount) = {
1197+ let _isValidAmount = if ((0 >= indexAmount))
1198+ then throw("amount should be positive")
1199+ else false
1200+ if ((_isValidAmount == _isValidAmount))
1201+ then {
1202+ let isLayer2 = containsElement(split(layer2Addresses, ","), toString(i.caller))
1203+ let addressStr = if (isLayer2)
1204+ then toString(i.originCaller)
1205+ else toString(i.caller)
1206+ let indexAvailable = tryGetInteger((addressStr + "_indexStaked"))
1207+ if (isShutdown())
1208+ then throw("contract is on stop")
1209+ else if ((indexAmount > indexAvailable))
1210+ then throw("you don't have index tokens available")
1211+ else {
1212+ let wavesClaimOut = getWavesClaimAmount(addressFromStringValue(addressStr))
1213+ ((rebalanceLeaseActions(wavesClaimOut, getNodeAddress()) ++ claimResult(addressFromStringValue(addressStr))._1) ++ [IntegerEntry((addressStr + "_indexStaked"), (indexAvailable - indexAmount)), IntegerEntry("global_indexStaked", (tryGetInteger("global_indexStaked") - indexAmount)), ScriptTransfer(i.caller, indexAmount, getBinaryValue("global_poolToken_id"))])
1214+ }
1215+ }
1216+ else throw("Strict value is not equal to itself.")
1217+ }
1218+
1219+
1220+
1221+@Callable(i)
1222+func claimIndexRewards () = if (isShutdown())
1223+ then throw("contract is on stop")
1224+ else {
1225+ let wavesClaimOut = getWavesClaimAmount(i.caller)
1226+ let cr = claimResult(i.caller)
1227+ $Tuple2((rebalanceLeaseActions(wavesClaimOut, getNodeAddress()) ++ cr._1), cr._2)
1228+ }
1229+
1230+
1231+
1232+@Callable(i)
1233+func evaluateClaim (user) = $Tuple2(nil, claimResult(addressFromStringValue(user))._2)
1234+
1235+
1236+
1237+@Callable(i)
1238+func swap (assetOut,minimum) = {
1239+ let pmt = if ((size(i.payments) == 1))
1240+ then value(i.payments[0])
1241+ else throw("please attach exactly one payment")
1242+ let AmountIn = value(i.payments[0].amount)
1243+ let AssetIn = pmt.assetId
1244+ let AssetOut = getAssetBytes(assetOut)
1245+ let assetIn = getAssetString(AssetIn)
1246+ let scaleIn = (Scale8 / tryGetInteger((("static_" + assetIn) + "_scale")))
1247+ let scaleOut = (Scale8 / tryGetInteger((("static_" + assetOut) + "_scale")))
1248+ let feeAssetOutStr = tryGetString("static_feeToken")
1249+ let feeAssetOut = if ((feeAssetOutStr == ""))
1250+ then usdnAssetId
1251+ else getAssetBytes(feeAssetOutStr)
1252+ let AssetInBalance = tryGetInteger((("global_" + getAssetString(AssetIn)) + "_balance"))
1253+ let AssetOutBalance = tryGetInteger((("global_" + assetOut) + "_balance"))
1254+ let AssetInBalanceScaled = (AssetInBalance * scaleIn)
1255+ let AssetOutBalanceScaled = (AssetOutBalance * scaleOut)
1256+ let feeAmountIn = fraction(AmountIn, Fee, FeeScale, CEILING)
1257+ let cleanAmountIn = (AmountIn - feeAmountIn)
1258+ let cleanAmountInScaled = (cleanAmountIn * scaleIn)
1259+ let AmountOut1 = calculateOutAmount_DOWN(cleanAmountInScaled, AssetIn, AssetOut, AssetInBalanceScaled, AssetOutBalanceScaled)
1260+ let AmountOut = fraction(AmountOut1, 1, scaleOut)
1261+ let AssetOutBalance2 = (AssetOutBalance - AmountOut)
1262+ let AssetInBalance2 = (AssetInBalance + cleanAmountIn)
1263+ let feeAssetOutBalance = if ((feeAssetOut == AssetIn))
1264+ then AssetInBalance2
1265+ else if ((feeAssetOut == AssetOut))
1266+ then AssetOutBalance2
1267+ else tryGetInteger((("global_" + getAssetString(feeAssetOut)) + "_balance"))
1268+ let feeAmountOut = calculateOutAmount_CEILING(feeAmountIn, AssetIn, feeAssetOut, AssetInBalance, feeAssetOutBalance)
1269+ if ((minimum > AmountOut))
1270+ then throw("amount to recieve is lower than given one")
1271+ else if ((AssetOut == AssetIn))
1272+ then throw("this swap is not allowed")
1273+ else if ((0 > (AssetOutBalance - AmountOut)))
1274+ then throw("contract is out of reserves")
1275+ else if (isShutdown())
1276+ then throw("contract is on stop")
1277+ else {
1278+ let creatorFee = fraction(feeAmountOut, 1, 10)
1279+ let protocolFee = fraction(feeAmountOut, 4, 10)
1280+ let newBalanceIn = if ((feeAssetOut == AssetIn))
1281+ then AssetInBalance2
1282+ else (AssetInBalance + AmountIn)
1283+ let newBalanceOut = (AssetOutBalance2 - (if ((AssetOut == feeAssetOut))
1284+ then feeAmountOut
1285+ else 0))
1286+ let newBalanceFeeAsset = if (if ((feeAssetOut != AssetIn))
1287+ then (feeAssetOut != AssetOut)
1288+ else false)
1289+ then (feeAssetOutBalance - feeAmountOut)
1290+ else unit
1291+ let assetInChange = IntegerEntry((("global_" + getAssetString(AssetIn)) + "_balance"), newBalanceIn)
1292+ let assetOutChange = IntegerEntry((("global_" + assetOut) + "_balance"), newBalanceOut)
1293+ let feeAssetOutChange = if ((newBalanceFeeAsset != unit))
1294+ then [IntegerEntry((("global_" + getAssetString(feeAssetOut)) + "_balance"), value(newBalanceFeeAsset))]
1295+ else nil
1296+ let volumeUpdate = calculateUsdnValue(AssetIn, AmountIn, AssetInBalance, feeAssetOutBalance)
1297+ let volumeUsdUpdate = calculateUsdValue(AssetIn, AmountIn, AssetInBalance)
1298+ let wavesOut = ((if ((AssetOut == unit))
1299+ then AmountOut
1300+ else 0) + (if ((feeAssetOut == unit))
1301+ then (creatorFee + protocolFee)
1302+ else 0))
1303+ let shouldRebalanceLease = if (if ((AssetIn == unit))
1304+ then true
1305+ else (AssetOut == unit))
1306+ then true
1307+ else (feeAssetOut == unit)
1308+ let leaseActions = if (shouldRebalanceLease)
1309+ then rebalanceLeaseActions(wavesOut, getNodeAddress())
1310+ else nil
1311+ $Tuple2((((leaseActions ++ [assetOutChange, assetInChange]) ++ feeAssetOutChange) ++ [ScriptTransfer(i.caller, AmountOut, AssetOut), ScriptTransfer(addressFromStringValue(tryGetString("static_poolOwner")), creatorFee, feeAssetOut), IntegerEntry("global_earnedByOwner", (tryGetInteger("global_earnedByOwner") + creatorFee)), IntegerEntry("global_volume", (tryGetInteger("global_volume") + volumeUpdate)), IntegerEntry("global_volume_usd", (tryGetInteger("global_volume_usd") + volumeUsdUpdate)), ScriptTransfer(feesAddress, protocolFee, feeAssetOut)]), AmountOut)
1312+ }
1313+ }
1314+
1315+
1316+
1317+@Callable(i)
1318+func swapReadOnly (assetIn,assetOut,AmountIn) = {
1319+ let AssetIn = getAssetBytes(assetIn)
1320+ let AssetOut = getAssetBytes(assetOut)
1321+ let scaleIn = (Scale8 / tryGetInteger((("static_" + assetIn) + "_scale")))
1322+ let scaleOut = (Scale8 / tryGetInteger((("static_" + assetOut) + "_scale")))
1323+ let feeAssetOutStr = tryGetString("static_feeToken")
1324+ let feeAssetOut = if ((feeAssetOutStr == ""))
1325+ then usdnAssetId
1326+ else getAssetBytes(feeAssetOutStr)
1327+ let AssetInBalance = tryGetInteger((("global_" + getAssetString(AssetIn)) + "_balance"))
1328+ let AssetOutBalance = tryGetInteger((("global_" + assetOut) + "_balance"))
1329+ let AssetInBalanceScaled = (AssetInBalance * scaleIn)
1330+ let AssetOutBalanceScaled = (AssetOutBalance * scaleOut)
1331+ let feeAmountIn = fraction(AmountIn, Fee, FeeScale, CEILING)
1332+ let cleanAmountIn = (AmountIn - feeAmountIn)
1333+ let cleanAmountInScaled = (cleanAmountIn * scaleIn)
1334+ let AmountOut1 = calculateOutAmount_DOWN(cleanAmountInScaled, AssetIn, AssetOut, AssetInBalanceScaled, AssetOutBalanceScaled)
1335+ let AmountOut = fraction(AmountOut1, 1, scaleOut)
1336+ let AssetOutBalance2 = (AssetOutBalance - AmountOut)
1337+ let AssetInBalance2 = (AssetInBalance + cleanAmountIn)
1338+ let feeAssetOutBalance = if ((feeAssetOut == AssetIn))
1339+ then AssetInBalance2
1340+ else if ((feeAssetOut == AssetOut))
1341+ then AssetOutBalance2
1342+ else tryGetInteger((("global_" + getAssetString(feeAssetOut)) + "_balance"))
1343+ let feeAmountOut = calculateOutAmount_CEILING(feeAmountIn, AssetIn, feeAssetOut, AssetInBalance, feeAssetOutBalance)
1344+ if ((AssetOut == AssetIn))
1345+ then throw("this swap is not allowed")
1346+ else if ((0 > (AssetOutBalance - AmountOut)))
1347+ then throw("contract is out of reserves")
1348+ else if (isShutdown())
1349+ then throw("contract is on stop")
1350+ else $Tuple2(nil, AmountOut)
1351+ }
1352+
1353+
1354+
1355+@Callable(i)
1356+func transferOwnership (newOwnerAddress) = {
1357+ let _isShutdown = if (isShutdown())
1358+ then throw("contract is on stop")
1359+ else false
1360+ if ((_isShutdown == _isShutdown))
1361+ then if ((toString(i.caller) != tryGetString("static_poolOwner")))
1362+ then throw("this call available only for pool owner")
1363+ else if ((addressFromString(newOwnerAddress) == unit))
1364+ then throw("invalid address")
1365+ else [StringEntry("static_poolOwner", newOwnerAddress)]
1366+ else throw("Strict value is not equal to itself.")
1367+ }
1368+
1369+
1370+
1371+@Callable(i)
1372+func setFee (newFee) = {
1373+ let _isPositiveFee = if ((0 > newFee))
1374+ then throw("fee can't be negative")
1375+ else true
1376+ if ((_isPositiveFee == _isPositiveFee))
1377+ then if ((toString(i.caller) != tryGetString("static_poolOwner")))
1378+ then throw("this call available only for pool owner")
1379+ else if ((1 > valueOrElse(getInteger(govAddress, ("approvedTx_" + toBase58String(i.transactionId))), 0)))
1380+ then throw("this transaction needs approval from puzzle network")
1381+ else [IntegerEntry("static_fee", newFee)]
1382+ else throw("Strict value is not equal to itself.")
1383+ }
1384+
1385+
1386+
1387+@Callable(i)
1388+func setRebalancingPlan (assetIdsStr,assetWeightsStr,baseTokenIdStr,stepsAmount,stepsInterval) = {
1389+ let _isShutdown = if (isShutdown())
1390+ then throw("contract is on stop")
1391+ else true
1392+ if ((_isShutdown == _isShutdown))
1393+ then if ((i.caller != addressFromStringValue(tryGetString("static_poolOwner"))))
1394+ then throw("this call available only for pool owner")
1395+ else if (valueOrElse(getBoolean(this, "rebalance_inProgress"), false))
1396+ then throw("rebalancing in progress")
1397+ else {
1398+ let newAssetWeightsStrLi = split(assetWeightsStr, ",")
1399+ let newAssetIdsStrLi = split(assetIdsStr, ",")
1400+ let feeAssetStr = {
1401+ let $l = newAssetIdsStrLi
1402+ let $s = size($l)
1403+ let $acc0 = ""
1404+ func $f4_1 ($a,$i) = if (($i >= $s))
1405+ then $a
1406+ else checkFeeAsset($a, $l[$i])
1407+
1408+ func $f4_2 ($a,$i) = if (($i >= $s))
1409+ then $a
1410+ else throw("List size exceeds 10")
1411+
1412+ $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)
1413+ }
1414+ let assetWeightsSum = {
1415+ let $l = newAssetWeightsStrLi
1416+ let $s = size($l)
1417+ let $acc0 = 0
1418+ func $f5_1 ($a,$i) = if (($i >= $s))
1419+ then $a
1420+ else sum($a, $l[$i])
1421+
1422+ func $f5_2 ($a,$i) = if (($i >= $s))
1423+ then $a
1424+ else throw("List size exceeds 10")
1425+
1426+ $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)
1427+ }
1428+ let oldAssetIds = getStringValue("static_tokenIds")
1429+ let oldAssetIdsLi = split(oldAssetIds, ",")
1430+ func findAdded (accum,next) = if ((indexOf(oldAssetIdsLi, next) == unit))
1431+ then (accum ++ [next])
1432+ else accum
1433+
1434+ func findRemoved (accum,next) = if ((indexOf(newAssetIdsStrLi, next) == unit))
1435+ then (accum ++ [next])
1436+ else accum
1437+
1438+ let addedAssets = {
1439+ let $l = newAssetIdsStrLi
1440+ let $s = size($l)
1441+ let $acc0 = nil
1442+ func $f6_1 ($a,$i) = if (($i >= $s))
1443+ then $a
1444+ else findAdded($a, $l[$i])
1445+
1446+ func $f6_2 ($a,$i) = if (($i >= $s))
1447+ then $a
1448+ else throw("List size exceeds 10")
1449+
1450+ $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)
1451+ }
1452+ let removedAssets = {
1453+ let $l = oldAssetIdsLi
1454+ let $s = size($l)
1455+ let $acc0 = nil
1456+ func $f7_1 ($a,$i) = if (($i >= $s))
1457+ then $a
1458+ else findRemoved($a, $l[$i])
1459+
1460+ func $f7_2 ($a,$i) = if (($i >= $s))
1461+ then $a
1462+ else throw("List size exceeds 10")
1463+
1464+ $f7_2($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1465+ }
1466+ let validPayments = validatePayments(addedAssets, i.payments)
1467+ let validWeights = validateWeights(newAssetWeightsStrLi)
1468+ if ((validWeights == validWeights))
1469+ then if ((validPayments != (size(addedAssets) + size(i.payments))))
1470+ then throw("Payments not present or something wrong with them")
1471+ else if ((size(newAssetIdsStrLi) != size(newAssetWeightsStrLi)))
1472+ then throw("assetIds and assetWeights should have same length")
1473+ else if ((feeAssetStr == ""))
1474+ then throw("pool must have one of the supported fee assets in the composition")
1475+ else if ((indexOf(newAssetIdsStrLi, baseTokenIdStr) == unit))
1476+ then throw("baseTokenId should be present in assetIds")
1477+ else if (if ((MIN_STEPS_AMOUNT > stepsAmount))
1478+ then true
1479+ else (stepsAmount > MAX_STEPS_AMOUNT))
1480+ then throw(((((("Steps amount should be between " + toString(MIN_STEPS_AMOUNT)) + " and ") + toString(MAX_STEPS_AMOUNT)) + ", current: ") + toString(stepsAmount)))
1481+ else if (if ((MIN_STEPS_INTERVAL > stepsInterval))
1482+ then true
1483+ else (stepsInterval > MAX_STEPS_INTERVAL))
1484+ then throw(((((("Steps interval should be between " + toString(MIN_STEPS_INTERVAL)) + " and ") + toString(MAX_STEPS_INTERVAL)) + ", current: ") + toString(stepsInterval)))
1485+ else if ((assetWeightsSum != 10000))
1486+ then throw(("sum of token weights must be equal to 10000, current: " + toString(assetWeightsSum)))
1487+ else {
1488+ func f (accum,assetIdStr) = {
1489+ let oldWeight = tryGetInteger((("static_" + assetIdStr) + "_weight"))
1490+ let newWeight = if ((indexOf(newAssetIdsStrLi, assetIdStr) == unit))
1491+ then 0
1492+ else parseIntValue(value(newAssetWeightsStrLi[value(indexOf(newAssetIdsStrLi, assetIdStr))]))
1493+ let deltaPerStep = fraction((newWeight - oldWeight), 10000, stepsAmount)
1494+ (accum ++ [toString(deltaPerStep)])
1495+ }
1496+
1497+ let tmpAssetIdsLi = getTmpRebalanceIds(newAssetIdsStrLi)
1498+ let assetDeltas = {
1499+ let $l = tmpAssetIdsLi
1500+ let $s = size($l)
1501+ let $acc0 = nil
1502+ func $f8_1 ($a,$i) = if (($i >= $s))
1503+ then $a
1504+ else f($a, $l[$i])
1505+
1506+ func $f8_2 ($a,$i) = if (($i >= $s))
1507+ then $a
1508+ else throw("List size exceeds 10")
1509+
1510+ $f8_2($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1511+ }
1512+ let newTokensAdded = (checkTokensChange(newAssetIdsStrLi) > 0)
1513+ func recordAssetPayment (accum,next) = (accum ++ [IntegerEntry(("rebalance_attachedPayment_" + getAssetString(next.assetId)), next.amount)])
1514+
1515+ let paymentEntries = {
1516+ let $l = i.payments
1517+ let $s = size($l)
1518+ let $acc0 = nil
1519+ func $f9_1 ($a,$i) = if (($i >= $s))
1520+ then $a
1521+ else recordAssetPayment($a, $l[$i])
1522+
1523+ func $f9_2 ($a,$i) = if (($i >= $s))
1524+ then $a
1525+ else throw("List size exceeds 10")
1526+
1527+ $f9_2($f9_1($f9_1($f9_1($f9_1($f9_1($f9_1($f9_1($f9_1($f9_1($f9_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1528+ }
1529+ let storeWeights = saveCurrentWeights()
1530+ let requestGovInvoke = invoke(govAddress, "requestRebalancing", [toBase58String(i.transactionId)], nil)
1531+ if ((requestGovInvoke == requestGovInvoke))
1532+ then (([StringEntry("rebalance_addedAssets", makeString(addedAssets, ",")), StringEntry("rebalance_removedAssets", makeString(removedAssets, ",")), StringEntry("tmp_rebalanceAssetIds", makeString(tmpAssetIdsLi, ",")), BooleanEntry("rebalance_inProgress", true), BooleanEntry("rebalance_newTokensAdded", newTokensAdded), IntegerEntry("rebalance_stepsDone", 0), IntegerEntry("rebalance_lastStepHeight", height), IntegerEntry("rebalance_stepsAmount", stepsAmount), IntegerEntry("rebalance_stepsInterval", stepsInterval), StringEntry("rebalance_assetIds", assetIdsStr), StringEntry("rebalance_newBaseTokenId", baseTokenIdStr), StringEntry("rebalance_assetDeltas", makeString(assetDeltas, ","))] ++ paymentEntries) ++ storeWeights)
1533+ else throw("Strict value is not equal to itself.")
1534+ }
1535+ else throw("Strict value is not equal to itself.")
1536+ }
1537+ else throw("Strict value is not equal to itself.")
1538+ }
1539+
1540+
1541+
1542+@Callable(i)
1543+func stepRebalancing () = {
1544+ let _isShutdown = if (isShutdown())
1545+ then throw("contract is on stop")
1546+ else true
1547+ if ((_isShutdown == _isShutdown))
1548+ then {
1549+ let rebId = valueOrErrorMessage(getString(govAddress, ("pool_lastRebalancing_" + toString(this))), "rebalancing is not registered at gov address")
1550+ if (!(valueOrElse(getBoolean(this, "rebalance_inProgress"), false)))
1551+ then throw("no rebalancing in progress")
1552+ else if ((valueOrElse(getInteger(govAddress, ("rebalancing_status_" + rebId)), 0) != 2))
1553+ then throw("this transaction needs approval from puzzle network")
1554+ else {
1555+ let lastStepHeight = getIntegerValue("rebalance_lastStepHeight")
1556+ let stepInterval = getIntegerValue("rebalance_stepsInterval")
1557+ let stepsDone = getIntegerValue("rebalance_stepsDone")
1558+ let nextStepHeight = (lastStepHeight + stepInterval)
1559+ if ((nextStepHeight > height))
1560+ then throw("can't be done yet")
1561+ else {
1562+ let assetDeltas = split(getStringValue("rebalance_assetDeltas"), ",")
1563+ let newAssetIdsStr = getStringValue("tmp_rebalanceAssetIds")
1564+ let newAssetIds = split(newAssetIdsStr, ",")
1565+ func f (accum,assetIdStr) = (accum ++ [toString(fraction(((valueOrElse(getInteger(("rebalance_startWeight_" + assetIdStr)), 0) * 10000) + (parseIntValue(assetDeltas[value(indexOf(newAssetIds, assetIdStr))]) * (stepsDone + 1))), 1, 10000, HALFUP))])
1566+
1567+ let newShares = makeString({
1568+ let $l = newAssetIds
1569+ let $s = size($l)
1570+ let $acc0 = nil
1571+ func $f4_1 ($a,$i) = if (($i >= $s))
1572+ then $a
1573+ else f($a, $l[$i])
1574+
1575+ func $f4_2 ($a,$i) = if (($i >= $s))
1576+ then $a
1577+ else throw("List size exceeds 10")
1578+
1579+ $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)
1580+ }, ",")
1581+ let newTokensAdded = getBooleanValue("rebalance_newTokensAdded")
1582+ let inv = if (if (newTokensAdded)
1583+ then (stepsDone == 0)
1584+ else false)
1585+ then invoke(this, "doRebalancingWithNewTokens", [newAssetIdsStr, newShares, getStringValue("rebalance_newBaseTokenId")], nil)
1586+ else invoke(this, "doRebalancing", [newShares], nil)
1587+ if ((inv == inv))
1588+ then {
1589+ let notifyInvoke = invoke(poolsHubAddress, "notifyPoolChange", nil, nil)
1590+ if ((notifyInvoke == notifyInvoke))
1591+ then {
1592+ let isFinished = ((stepsDone + 1) >= getIntegerValue("rebalance_stepsAmount"))
1593+ let actions = [BooleanEntry("rebalance_inProgress", !(isFinished)), IntegerEntry("rebalance_stepsDone", (stepsDone + 1)), IntegerEntry("rebalance_lastStepHeight", height)]
1594+ if ((stepsDone == 0))
1595+ then (actions ++ [StringEntry("static_tokenIds", newAssetIdsStr)])
1596+ else if (isFinished)
1597+ then {
1598+ let removedAssetsLi = split(tryGetString("rebalance_removedAssets"), ",")
1599+ func rmData (accum,assetId) = (accum ++ [DeleteEntry((("static_" + assetId) + "_scale")), DeleteEntry((("static_" + assetId) + "_decimals")), DeleteEntry((("static_" + assetId) + "_weight")), DeleteEntry((("global_" + assetId) + "_balance")), DeleteEntry(("rebalance_attachedPayment_" + assetId))])
1600+
1601+ let rm = {
1602+ let $l = removedAssetsLi
1603+ let $s = size($l)
1604+ let $acc0 = nil
1605+ func $f5_1 ($a,$i) = if (($i >= $s))
1606+ then $a
1607+ else rmData($a, $l[$i])
1608+
1609+ func $f5_2 ($a,$i) = if (($i >= $s))
1610+ then $a
1611+ else throw("List size exceeds 10")
1612+
1613+ $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)
1614+ }
1615+ let addedAssetsLi = split(tryGetString("rebalance_addedAssets"), ",")
1616+ func addRemovePayments (accum,assetId) = (accum ++ [DeleteEntry(("rebalance_attachedPayment_" + assetId))])
1617+
1618+ let rmPayments = {
1619+ let $l = addedAssetsLi
1620+ let $s = size($l)
1621+ let $acc0 = nil
1622+ func $f6_1 ($a,$i) = if (($i >= $s))
1623+ then $a
1624+ else addRemovePayments($a, $l[$i])
1625+
1626+ func $f6_2 ($a,$i) = if (($i >= $s))
1627+ then $a
1628+ else throw("List size exceeds 10")
1629+
1630+ $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)
1631+ }
1632+ let finalAssetsIdsStr = tryGetString("rebalance_assetIds")
1633+ let AssetsWeightsStr = {
1634+ let $l = split(finalAssetsIdsStr, ",")
1635+ let $s = size($l)
1636+ let $acc0 = nil
1637+ func $f7_1 ($a,$i) = if (($i >= $s))
1638+ then $a
1639+ else addAssetWeightToStrList($a, $l[$i])
1640+
1641+ func $f7_2 ($a,$i) = if (($i >= $s))
1642+ then $a
1643+ else throw("List size exceeds 10")
1644+
1645+ $f7_2($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1646+ }
1647+ let notify = invoke(govAddress, "notifyRebalancingDone", [rebId], nil)
1648+ if ((notify == notify))
1649+ then (((actions ++ rm) ++ rmPayments) ++ [StringEntry("static_tokenIds", finalAssetsIdsStr), StringEntry("static_tokenWeights", makeString(AssetsWeightsStr, ",")), IntegerEntry("static_tokensAmount", size(split(finalAssetsIdsStr, ",")))])
1650+ else throw("Strict value is not equal to itself.")
1651+ }
1652+ else {
1653+ let finalAssetsIdsStr = tryGetString("rebalance_assetIds")
1654+ let AssetsWeightsStr = {
1655+ let $l = split(finalAssetsIdsStr, ",")
1656+ let $s = size($l)
1657+ let $acc0 = nil
1658+ func $f5_1 ($a,$i) = if (($i >= $s))
1659+ then $a
1660+ else addAssetWeightToStrList($a, $l[$i])
1661+
1662+ func $f5_2 ($a,$i) = if (($i >= $s))
1663+ then $a
1664+ else throw("List size exceeds 10")
1665+
1666+ $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)
1667+ }
1668+ (actions ++ [StringEntry("static_tokenWeights", makeString(AssetsWeightsStr, ","))])
1669+ }
1670+ }
1671+ else throw("Strict value is not equal to itself.")
1672+ }
1673+ else throw("Strict value is not equal to itself.")
1674+ }
1675+ }
1676+ }
1677+ else throw("Strict value is not equal to itself.")
1678+ }
1679+
1680+
1681+
1682+@Callable(i)
1683+func doRebalancing (assetWeightsStr) = {
1684+ let _isShutdown = if (isShutdown())
1685+ then throw("contract is on stop")
1686+ else true
1687+ if ((_isShutdown == _isShutdown))
1688+ then {
1689+ let assetWeightsStrLi = split(assetWeightsStr, ",")
1690+ let assetWeightsSum = {
1691+ let $l = assetWeightsStrLi
1692+ let $s = size($l)
1693+ let $acc0 = 0
1694+ func $f4_1 ($a,$i) = if (($i >= $s))
1695+ then $a
1696+ else sum($a, $l[$i])
1697+
1698+ func $f4_2 ($a,$i) = if (($i >= $s))
1699+ then $a
1700+ else throw("List size exceeds 10")
1701+
1702+ $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)
1703+ }
1704+ let assetIdsStrLi = split(tryGetString("static_tokenIds"), ",")
1705+ if ((i.caller != this))
1706+ then throw("this call available only for admin")
1707+ else {
1708+ let oldKMult = getKMult()
1709+ func handler (pars,assetId) = {
1710+ let accum = pars._1
1711+ let assetIdStr = getAssetString(assetId)
1712+ func handler2 (accum,n) = if ((n == assetId))
1713+ then value(indexOf(assetIds, n))
1714+ else accum
1715+
1716+ let Token = {
1717+ let $l = assetIds
1718+ let $s = size($l)
1719+ let $acc0 = 1
1720+ func $f5_1 ($a,$i) = if (($i >= $s))
1721+ then $a
1722+ else handler2($a, $l[$i])
1723+
1724+ func $f5_2 ($a,$i) = if (($i >= $s))
1725+ then $a
1726+ else throw("List size exceeds 10")
1727+
1728+ $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)
1729+ }
1730+ let balance = tryGetInteger((("global_" + assetIdStr) + "_balance"))
1731+ let weight = if ((pars._2 == "new"))
1732+ then parseIntValue(assetWeightsStrLi[Token])
1733+ else tryGetInteger((("static_" + assetIdStr) + "_weight"))
1734+ $Tuple2(fraction(accum, pow(balance, Decimals[Token], weight, AssetsWeightsDecimals, 8, FLOOR), Scale8), pars._2)
1735+ }
1736+
1737+ let newK = ( let $l = assetIds
1738+ let $s = size($l)
1739+ let $acc0 = $Tuple2(PoolTokenScale, "new")
1740+ func $f5_1 ($a,$i) = if (($i >= $s))
1741+ then $a
1742+ else handler($a, $l[$i])
1743+
1744+ func $f5_2 ($a,$i) = if (($i >= $s))
1745+ then $a
1746+ else throw("List size exceeds 10")
1747+
1748+ $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))._1
1749+ let oldK = ( let $l = assetIds
1750+ let $s = size($l)
1751+ let $acc0 = $Tuple2(PoolTokenScale, "old")
1752+ func $f6_1 ($a,$i) = if (($i >= $s))
1753+ then $a
1754+ else handler($a, $l[$i])
1755+
1756+ func $f6_2 ($a,$i) = if (($i >= $s))
1757+ then $a
1758+ else throw("List size exceeds 10")
1759+
1760+ $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))._1
1761+ let newKMult = fraction(oldKMult, newK, oldK)
1762+ func addTokenDataEntries (accum,assetNum) = if ((assetNum >= size(assetWeightsStrLi)))
1763+ then accum
1764+ else (accum ++ [IntegerEntry((("static_" + assetIdsStrLi[assetNum]) + "_weight"), value(parseInt(assetWeightsStrLi[assetNum])))])
1765+
1766+ ({
1767+ let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1768+ let $s = size($l)
1769+ let $acc0 = nil
1770+ func $f7_1 ($a,$i) = if (($i >= $s))
1771+ then $a
1772+ else addTokenDataEntries($a, $l[$i])
1773+
1774+ func $f7_2 ($a,$i) = if (($i >= $s))
1775+ then $a
1776+ else throw("List size exceeds 10")
1777+
1778+ $f7_2($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1779+ } ++ [IntegerEntry("static_KMult", newKMult)])
1780+ }
1781+ }
1782+ else throw("Strict value is not equal to itself.")
1783+ }
1784+
1785+
1786+
1787+@Callable(i)
1788+func doRebalancingWithNewTokens (assetIdsStr,assetWeightsStr,baseTokenIdStr) = {
1789+ let _isShutdown = if (isShutdown())
1790+ then throw("contract is on stop")
1791+ else true
1792+ if ((_isShutdown == _isShutdown))
1793+ then {
1794+ let newAssetWeightsStrLi = split(assetWeightsStr, ",")
1795+ let prevAssetIdsStrLi = split(tryGetString("static_tokenIds"), ",")
1796+ let newAssetIdsStrLi = split(assetIdsStr, ",")
1797+ let newAssetIds = {
1798+ let $l = newAssetIdsStrLi
1799+ let $s = size($l)
1800+ let $acc0 = nil
1801+ func $f4_1 ($a,$i) = if (($i >= $s))
1802+ then $a
1803+ else addAssetBytesToList($a, $l[$i])
1804+
1805+ func $f4_2 ($a,$i) = if (($i >= $s))
1806+ then $a
1807+ else throw("List size exceeds 10")
1808+
1809+ $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)
1810+ }
1811+ let feeAssetStr = {
1812+ let $l = newAssetIdsStrLi
1813+ let $s = size($l)
1814+ let $acc0 = ""
1815+ func $f5_1 ($a,$i) = if (($i >= $s))
1816+ then $a
1817+ else checkFeeAsset($a, $l[$i])
1818+
1819+ func $f5_2 ($a,$i) = if (($i >= $s))
1820+ then $a
1821+ else throw("List size exceeds 10")
1822+
1823+ $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)
1824+ }
1825+ let addedAssets = split(tryGetString("rebalance_addedAssets"), ",")
1826+ func findAssetPayment (assetId) = valueOrElse(getInteger(("rebalance_attachedPayment_" + getAssetString(assetId))), 0)
1827+
1828+ func addAssetBalanceToLi (li,assetId) = (li ++ [findAssetPayment(assetId)])
1829+
1830+ let attachedBalances = {
1831+ let $l = newAssetIds
1832+ let $s = size($l)
1833+ let $acc0 = nil
1834+ func $f6_1 ($a,$i) = if (($i >= $s))
1835+ then $a
1836+ else addAssetBalanceToLi($a, $l[$i])
1837+
1838+ func $f6_2 ($a,$i) = if (($i >= $s))
1839+ then $a
1840+ else throw("List size exceeds 10")
1841+
1842+ $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)
1843+ }
1844+ if ((i.caller != this))
1845+ then throw(("this call available only for admin, " + toString(i.caller)))
1846+ else {
1847+ let oldKMult = getKMult()
1848+ let oldK = getVirtualPoolTokenAmount()
1849+ func myltiplyAssetsForK (pars,assetId) = {
1850+ func findAssetNum (accum,n) = if ((n == assetId))
1851+ then value(indexOf(newAssetIds, n))
1852+ else accum
1853+
1854+ let currentK = pars
1855+ let assetIdStr = getAssetString(assetId)
1856+ let TokenNum = {
1857+ let $l = newAssetIds
1858+ let $s = size($l)
1859+ let $acc0 = 1
1860+ func $f7_1 ($a,$i) = if (($i >= $s))
1861+ then $a
1862+ else findAssetNum($a, $l[$i])
1863+
1864+ func $f7_2 ($a,$i) = if (($i >= $s))
1865+ then $a
1866+ else throw("List size exceeds 10")
1867+
1868+ $f7_2($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1869+ }
1870+ let weight = parseIntValue(newAssetWeightsStrLi[TokenNum])
1871+ let balanceInState = tryGetInteger((("global_" + assetIdStr) + "_balance"))
1872+ let balanceInPayment = attachedBalances[TokenNum]
1873+ let balance = (balanceInState + balanceInPayment)
1874+ let assetDecimals = if ((assetId == unit))
1875+ then 8
1876+ else value(assetInfo(value(assetId))).decimals
1877+ if ((0 >= balance))
1878+ then throw(("you need to attach all new assets in payment. this asset is missed: " + assetIdStr))
1879+ else fraction(currentK, pow(balance, assetDecimals, weight, AssetsWeightsDecimals, 8, FLOOR), Scale8)
1880+ }
1881+
1882+ let newK = {
1883+ let $l = newAssetIds
1884+ let $s = size($l)
1885+ let $acc0 = PoolTokenScale
1886+ func $f7_1 ($a,$i) = if (($i >= $s))
1887+ then $a
1888+ else myltiplyAssetsForK($a, $l[$i])
1889+
1890+ func $f7_2 ($a,$i) = if (($i >= $s))
1891+ then $a
1892+ else throw("List size exceeds 10")
1893+
1894+ $f7_2($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1895+ }
1896+ let newKMult = fraction(oldKMult, newK, oldK)
1897+ func addTokenDataEntries (accum,assetNum) = {
1898+ let assetIdStr = newAssetIdsStrLi[assetNum]
1899+ let assetId = newAssetIds[assetNum]
1900+ let assetDecimals = if ((assetId == unit))
1901+ then 8
1902+ else value(assetInfo(value(assetId))).decimals
1903+ let newAssetData = if ((indexOf(addedAssets, assetIdStr) != unit))
1904+ then [IntegerEntry((("global_" + assetIdStr) + "_balance"), attachedBalances[assetNum]), IntegerEntry((("static_" + assetIdStr) + "_scale"), pow(10, 0, assetDecimals, 0, 0, DOWN)), IntegerEntry((("static_" + assetIdStr) + "_decimals"), assetDecimals)]
1905+ else nil
1906+ if ((assetNum >= size(newAssetWeightsStrLi)))
1907+ then accum
1908+ else ((accum ++ [IntegerEntry((("static_" + assetIdStr) + "_weight"), value(parseInt(newAssetWeightsStrLi[assetNum])))]) ++ newAssetData)
1909+ }
1910+
1911+ ({
1912+ let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1913+ let $s = size($l)
1914+ let $acc0 = nil
1915+ func $f8_1 ($a,$i) = if (($i >= $s))
1916+ then $a
1917+ else addTokenDataEntries($a, $l[$i])
1918+
1919+ func $f8_2 ($a,$i) = if (($i >= $s))
1920+ then $a
1921+ else throw("List size exceeds 10")
1922+
1923+ $f8_2($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1924+ } ++ [StringEntry("static_tokenIds", assetIdsStr), StringEntry("static_feeToken", feeAssetStr), StringEntry("static_tokenWeights", assetWeightsStr), IntegerEntry("static_tokensAmount", size(newAssetIds)), IntegerEntry("static_KMult", newKMult)])
1925+ }
1926+ }
1927+ else throw("Strict value is not equal to itself.")
1928+ }
1929+
1930+
1931+@Verifier(tx)
1932+func verify () = if (if ((valueOrElse(getInteger("global_wasPreInited"), 0) == 0))
1933+ then if (sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey))
1934+ then true
1935+ else sigVerify(tx.bodyBytes, tx.proofs[0], masterPubKey)
1936+ else false)
1937+ then true
1938+ else {
1939+ let _multisigStr = "3PJdVErH5VmVYvkuN3Ayrrtd1zCZ4Xru6gT"
1940+ let multisigStr = valueOrElse(getString(this, "APPROVER_ADDRESS"), _multisigStr)
1941+ let multisigAddress = addressFromString(multisigStr)
1942+ let multisigOk = match multisigAddress {
1943+ case t: Address =>
1944+ true
1945+ case _ =>
1946+ false
1947+ }
1948+ let isInited = if (multisigOk)
1949+ then valueOrElse(getBoolean(value(multisigAddress), "INITED"), false)
1950+ else false
1951+ let hasAdmins = if (multisigOk)
1952+ then (valueOrElse(getString(value(multisigAddress), "ADMINS_PBKS"), "") != "")
1953+ else false
1954+ if (if (if (multisigOk)
1955+ then isInited
1956+ else false)
1957+ then hasAdmins
1958+ else false)
1959+ then match tx {
1960+ case ttx: SetScriptTransaction =>
1961+ match ttx.script {
1962+ case script: ByteVector =>
1963+ let scriptHasha = toBase58String(blake2b256(script))
1964+ let validFrom = valueOrErrorMessage(getInteger(value(multisigAddress), (((("script%%" + CONTRACT_TYPE) + "%%") + scriptHasha) + "%%validFrom")), "validFrom not set")
1965+ let validTo = valueOrErrorMessage(getInteger(value(multisigAddress), (((("script%%" + CONTRACT_TYPE) + "%%") + scriptHasha) + "%%validTo")), "validTo not set")
1966+ if ((height >= validFrom))
1967+ then (validTo >= height)
1968+ else false
1969+ case _ =>
1970+ false
1971+ }
1972+ case otx =>
1973+ let taskId = ((("tx_" + toString(this)) + "_") + toBase58String(otx.id))
1974+ let isApproved = valueOrElse(getBoolean(value(multisigAddress), (((toString(this) + "_") + toBase58String(otx.id)) + "__approved")), false)
1975+ let approvedFrom = valueOrElse(getInteger(value(multisigAddress), (taskId + "__approvedFrom")), 0)
1976+ if (isApproved)
1977+ then (height >= approvedFrom)
1978+ else false
1979+ }
1980+ else match tx {
1981+ case ttx: SetScriptTransaction =>
1982+ if (sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey))
1983+ then true
1984+ else sigVerify(ttx.bodyBytes, ttx.proofs[0], masterPubKey)
1985+ case _ =>
1986+ false
1987+ }
1988+ }
1989+

github/deemru/w8io
1135.54 ms