tx · CtbKMKGZiTMJ9hijAUPxWHt7T1HetyA9C6zR5VyUbV6J

3P6FoYa7U4MmFY5rvMv7XdCZQYg9MHVYAyF:  -0.05400000 Waves

2024.04.23 16:24 [4141453] smart account 3P6FoYa7U4MmFY5rvMv7XdCZQYg9MHVYAyF > SELF 0.00000000 Waves

{ "type": 13, "id": "CtbKMKGZiTMJ9hijAUPxWHt7T1HetyA9C6zR5VyUbV6J", "fee": 5400000, "feeAssetId": null, "timestamp": 1713878740761, "version": 2, "chainId": 87, "sender": "3P6FoYa7U4MmFY5rvMv7XdCZQYg9MHVYAyF", "senderPublicKey": "3iaLmoNPhkhnCLpYzoU1SEBC5WookvBTrP6N68nReiNs", "proofs": [ "4ensBFebdCJoQmo2uzuARDzB6sJ1A1aeCgcbzTwNipAQzjMoStgTTtzxtauriaB7ucbYDTJ98xjVuhqPEwsUYye" ], "script": "base64:BgJbCAISCAoGCAgICAgBEgASABIDCgEEEgMKAQQSABIDCgEIEgMKAQESABIDCgEIEgQKAggBEgUKAwgIARIDCgEIEgMKAQESBwoFCAgIAQESABIDCgEIEgUKAwgICFMAB1ZFUlNJT04CDVBaLTEuMi4zIFBST0QACWNvbmZpZ1N0cgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzAg1jb25maWdBZGRyZXNzAiMzUFBFQlJnNHMyYWYyclEyWmJMdmR1MUhmZDRWbzZRVkRUbwAOQ09ORklHX0FERFJFU1MDCQAAAgUJY29uZmlnU3RyAgAFBHRoaXMJAQdBZGRyZXNzAQkA2QQBBQljb25maWdTdHIAFUFzc2V0c1dlaWdodHNEZWNpbWFscwAEAAVTY2FsZQCQTgAGU2NhbGU4AIDC1y8AB1NjYWxlMTYAgICE/qbe4REACEZlZVNjYWxlAJBOABFQb29sVG9rZW5EZWNpbWFscwAIAA5Qb29sVG9rZW5TY2FsZQkAbAYACgAABRFQb29sVG9rZW5EZWNpbWFscwAAAAAFBkhBTEZVUAAQTUlOX1NURVBTX0FNT1VOVAkBC3ZhbHVlT3JFbHNlAgkAmggCBQ5DT05GSUdfQUREUkVTUwIQbWluX3N0ZXBzX2Ftb3VudAABABBNQVhfU1RFUFNfQU1PVU5UCQELdmFsdWVPckVsc2UCCQCaCAIFDkNPTkZJR19BRERSRVNTAhBtYXhfc3RlcHNfYW1vdW50APQDABJNSU5fU1RFUFNfSU5URVJWQUwJAQt2YWx1ZU9yRWxzZQIJAJoIAgUOQ09ORklHX0FERFJFU1MCEm1pbl9zdGVwc19pbnRlcnZhbAABABJNQVhfU1RFUFNfSU5URVJWQUwJAQt2YWx1ZU9yRWxzZQIJAJoIAgUOQ09ORklHX0FERFJFU1MCEm1heF9zdGVwc19pbnRlcnZhbACQTgAKTUlOX1dFSUdIVAkBC3ZhbHVlT3JFbHNlAgkAmggCBQ5DT05GSUdfQUREUkVTUwIKbWluX3dlaWdodABkAApNQVhfV0VJR0hUCQELdmFsdWVPckVsc2UCCQCaCAIFDkNPTkZJR19BRERSRVNTAgptYXhfd2VpZ2h0AKxNAQ10cnlHZXRJbnRlZ2VyAQNrZXkEByRtYXRjaDAJAJoIAgUEdGhpcwUDa2V5AwkAAQIFByRtYXRjaDACA0ludAQBYgUHJG1hdGNoMAUBYgAAAQx0cnlHZXRCaW5hcnkBA2tleQQHJG1hdGNoMAkAnAgCBQR0aGlzBQNrZXkDCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQBYgUHJG1hdGNoMAUBYgEAAQx0cnlHZXRTdHJpbmcBA2tleQQHJG1hdGNoMAkAnQgCBQR0aGlzBQNrZXkDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFiBQckbWF0Y2gwBQFiAgABE3RyeUdldFN0cmluZ09yVGhyb3cBA2tleQQHJG1hdGNoMAkAnQgCBQR0aGlzBQNrZXkDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFiBQckbWF0Y2gwBQFiCQACAQkArAICAh1ubyBzdWNoIGtleSBpbiBkYXRhIHN0b3JhZ2U6IAUDa2V5AQ5nZXRBc3NldFN0cmluZwEHYXNzZXRJZAQHJG1hdGNoMAUHYXNzZXRJZAMJAAECBQckbWF0Y2gwAgpCeXRlVmVjdG9yBAFiBQckbWF0Y2gwCQDYBAEFAWICBVdBVkVTAQ1nZXRBc3NldEJ5dGVzAQphc3NldElkU3RyAwkAAAIFCmFzc2V0SWRTdHICBVdBVkVTBQR1bml0CQDZBAEFCmFzc2V0SWRTdHIBD2dldFRva2VuQmFsYW5jZQEHYXNzZXRJZAQHJG1hdGNoMAUHYXNzZXRJZAMJAAECBQckbWF0Y2gwAgpCeXRlVmVjdG9yBAF0BQckbWF0Y2gwCQDwBwIFBHRoaXMFAXQICQDvBwEFBHRoaXMJYXZhaWxhYmxlARNhZGRBc3NldEJ5dGVzVG9MaXN0AgVhY2N1bQRpdGVtCQDOCAIFBWFjY3VtCQDMCAIJAQ1nZXRBc3NldEJ5dGVzAQUEaXRlbQUDbmlsARRhZGRBc3NldFdlaWdodFRvTGlzdAIFYWNjdW0EaXRlbQkAzggCBQVhY2N1bQkAzAgCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdzdGF0aWNfCQEOZ2V0QXNzZXRTdHJpbmcBBQRpdGVtAgdfd2VpZ2h0BQNuaWwBF2FkZEFzc2V0V2VpZ2h0VG9TdHJMaXN0AgVhY2N1bQRpdGVtCQDOCAIFBWFjY3VtCQDMCAIJAKQDAQkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHc3RhdGljXwUEaXRlbQIHX3dlaWdodAUDbmlsARZhZGRBc3NldERlY2ltYWxzVG9MaXN0AgVhY2N1bQRpdGVtCQDOCAIFBWFjY3VtCQDMCAIJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB3N0YXRpY18JAQ5nZXRBc3NldFN0cmluZwEFBGl0ZW0CCV9kZWNpbWFscwUDbmlsARNhZGRBc3NldFNjYWxlVG9MaXN0AgVhY2N1bQRpdGVtCQDOCAIFBWFjY3VtCQDMCAIJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB3N0YXRpY18JAQ5nZXRBc3NldFN0cmluZwEFBGl0ZW0CBl9zY2FsZQUDbmlsAQxhZGRJbnRUb0xpc3QCBWFjY3VtBGl0ZW0JAM4IAgUFYWNjdW0JAMwIAgkBDXBhcnNlSW50VmFsdWUBBQRpdGVtBQNuaWwADnVzZG5Bc3NldElkU3RyCQELdmFsdWVPckVsc2UCCQCdCAIFDkNPTkZJR19BRERSRVNTAg51c2RuQXNzZXRJZFN0cgIsREcyeEZrUGREd0tVb0JrekdBaFF0THBTR3pmWExpQ1lQRXplS0gyQWQyNHAAEHB1enpsZUFzc2V0SWRTdHIJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUOQ09ORklHX0FERFJFU1MCEHB1enpsZUFzc2V0SWRTdHICLEhFQjhRYXc5eHJXcFdzOHRIc2lBVFlHQldEQnRQMlM3a2NQQUxyTXU0M0FTAA51c2R0QXNzZXRJZFN0cgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ5DT05GSUdfQUREUkVTUwIOdXNkdEFzc2V0SWRTdHICLDM0TjlZY0VFVExXbjkzcVlRNjRFc1AxeDg5dFNydUpVNDRSckVNU1hYRVBKABF1c2R0UHB0QXNzZXRJZFN0cgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ5DT05GSUdfQUREUkVTUwIRdXNkdFBwdEFzc2V0SWRTdHICLDl3YzNMWE5BNFRFQnNYeUt0b0xFOW1yYkREN1dNSFh2WHJDalp2YWJMQXNpAA5yb21lQXNzZXRJZFN0cgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ5DT05GSUdfQUREUkVTUwIOcm9tZUFzc2V0SWRTdHICLEFQNENiNXhMWUdINlppZ0hyZUNaSG9YcFFUV0RrUHNHMkJIcWZEVXg2dGFKAA93YXZlc0Fzc2V0SWRTdHICBVdBVkVTAAt1c2RuQXNzZXRJZAkA2QQBBQ51c2RuQXNzZXRJZFN0cgANcHV6emxlQXNzZXRJZAkA2QQBBRBwdXp6bGVBc3NldElkU3RyAAt1c2R0QXNzZXRJZAkA2QQBBQ51c2R0QXNzZXRJZFN0cgAOdXNkdFBwdEFzc2V0SWQJANkEAQURdXNkdFBwdEFzc2V0SWRTdHIAC3JvbWVBc3NldElkCQDZBAEFDnJvbWVBc3NldElkU3RyAAx3YXZlc0Fzc2V0SWQFBHVuaXQAFXN1cHBvcnRlZEZlZUFzc2V0c1N0cgkAzAgCBQ51c2RuQXNzZXRJZFN0cgkAzAgCBRBwdXp6bGVBc3NldElkU3RyCQDMCAIFDnVzZHRBc3NldElkU3RyCQDMCAIFEXVzZHRQcHRBc3NldElkU3RyCQDMCAIFD3dhdmVzQXNzZXRJZFN0cgkAzAgCBQ5yb21lQXNzZXRJZFN0cgUDbmlsABFwYXJlbnRQb29sQWRkcmVzcwkBB0FkZHJlc3MBCQDZBAEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUOQ09ORklHX0FERFJFU1MCEXBhcmVudFBvb2xBZGRyZXNzAiMzUEZEZ3p1MVV0c3dBa0NNeHFxUWpiVGVIYVg0Y01hYjhLaAANbWFzdGVyQWRkcmVzcwkBB0FkZHJlc3MBCQDZBAEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUOQ09ORklHX0FERFJFU1MCDW1hc3RlckFkZHJlc3MCIzNQTGp3SGN6OU5FdWFUbzYzTlpSOUI5b2tRaUtReFpTYm1mAAxtYXN0ZXJQdWJLZXkJANkEAQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ5DT05GSUdfQUREUkVTUwIMbWFzdGVyUHViS2V5Aiw0ejhDS1NZUUJLa3p4N1BCYjV1QlAxWVBhNllBSFJOVEFwVzFzUVZIVDVlVQANb3JhY2xlQWRkcmVzcwkBB0FkZHJlc3MBCQDZBAEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUOQ09ORklHX0FERFJFU1MCDW9yYWNsZUFkZHJlc3MCIzNQOGQxRTFCTEtvRDUyeTNiUUoxYkRUZDJURDFncGFMbjl0AA5zdGFraW5nQWRkcmVzcwkBB0FkZHJlc3MBCQDZBAEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUOQ09ORklHX0FERFJFU1MCDnN0YWtpbmdBZGRyZXNzAiMzUEZUYnl3cXh0RmZ1a1gzSHlUODgxZzRpVzVLNFFMM0ZBUwALZmVlc0FkZHJlc3MJAQdBZGRyZXNzAQkA2QQBCQELdmFsdWVPckVsc2UCCQCdCAIFDkNPTkZJR19BRERSRVNTAgtmZWVzQWRkcmVzcwIjM1BGV0FWS21YamZIWHl6SmIxMmpDYmhQNFVoaTl0NHVXaUQAD3Bvb2xzSHViQWRkcmVzcwkBB0FkZHJlc3MBCQDZBAEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUOQ09ORklHX0FERFJFU1MCD3Bvb2xzSHViQWRkcmVzcwIjM1A1WXV0akROQzNoQUJCVnN2ZUZ1WlRUYlE1UGR0U0RCZ2sAEnNodXRkb3duQWRkcmVzc1N0cgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ5DT05GSUdfQUREUkVTUwIPc2h1dGRvd25BZGRyZXNzAiMzUEVwdjloUkZXRUVCVTIyV1JuTHN3MWJINFlHdGNVNzI4bwAPbGF5ZXIyQWRkcmVzc2VzCQELdmFsdWVPckVsc2UCCQCdCAIFDkNPTkZJR19BRERSRVNTAg9sYXllcjJBZGRyZXNzZXMCRzNQUjFRdmk5bUhUMzVTd1dFa0xTcXFFMkw4dGhpUExkVldVLDNQUW9CZlVLSGtKQWVHV2hvb0xQN1dTOG92YjU0YXY5SnAyAApnb3ZBZGRyZXNzCQEHQWRkcmVzcwEJANkEAQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ5DT05GSUdfQUREUkVTUwIKZ292QWRkcmVzcwIjM1A2dXJvOXhDc0U4dGU3OFFaanpxeTdhcThuYXRTemRjZUMAEWNvbGRNYXN0ZXJBZGRyZXNzCQEHQWRkcmVzcwEJANkEAQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ5DT05GSUdfQUREUkVTUwIRY29sZE1hc3RlckFkZHJlc3MCIzNQSzluaFBmUGJNQnlnQjlaZ0hWTUhhUWJTb29qd3JCZnhqAAFUCQENdHJ5R2V0SW50ZWdlcgECE3N0YXRpY190b2tlbnNBbW91bnQACGFzc2V0SWRzCgACJGwJALUJAgkBDHRyeUdldFN0cmluZwECD3N0YXRpY190b2tlbklkcwIBLAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQETYWRkQXNzZXRCeXRlc1RvTGlzdAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgANQXNzZXRzV2VpZ2h0cwoAAiRsBQhhc3NldElkcwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMV8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEUYWRkQXNzZXRXZWlnaHRUb0xpc3QCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjFfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYxXzICCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACERlY2ltYWxzCgACJGwFCGFzc2V0SWRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYyXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARZhZGRBc3NldERlY2ltYWxzVG9MaXN0AgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYyXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmMl8yAgkBBSRmMl8xAgkBBSRmMl8xAgkBBSRmMl8xAgkBBSRmMl8xAgkBBSRmMl8xAgkBBSRmMl8xAgkBBSRmMl8xAgkBBSRmMl8xAgkBBSRmMl8xAgkBBSRmMl8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAZTY2FsZXMKAAIkbAUIYXNzZXRJZHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjNfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBE2FkZEFzc2V0U2NhbGVUb0xpc3QCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjNfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYzXzICCQEFJGYzXzECCQEFJGYzXzECCQEFJGYzXzECCQEFJGYzXzECCQEFJGYzXzECCQEFJGYzXzECCQEFJGYzXzECCQEFJGYzXzECCQEFJGYzXzECCQEFJGYzXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoAA0ZlZQkBDXRyeUdldEludGVnZXIBAgpzdGF0aWNfZmVlAAxlYXJuZWRBc3NldHMFCGFzc2V0SWRzAQppc1NodXRkb3duAAQPc2h1dGRvd25BZGRyZXNzCQCmCAEFEnNodXRkb3duQWRkcmVzc1N0cgMJAAACBQ9zaHV0ZG93bkFkZHJlc3MFBHVuaXQHBAckbWF0Y2gwCQCbCAIJAQV2YWx1ZQEFD3NodXRkb3duQWRkcmVzcwILaXNfc2h1dGRvd24DCQABAgUHJG1hdGNoMAIHQm9vbGVhbgQBeAUHJG1hdGNoMAUBeAcBFmdldEN1cnJlbnRUb2tlbkJhbGFuY2UBCHRva2VuTnVtBAp0b2tlbklkU3RyCQEOZ2V0QXNzZXRTdHJpbmcBCQCRAwIFCGFzc2V0SWRzBQh0b2tlbk51bQkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHZ2xvYmFsXwUKdG9rZW5JZFN0cgIIX2JhbGFuY2UBCGdldEtNdWx0AAQHJG1hdGNoMAkAnwgBAgxzdGF0aWNfS011bHQDCQABAgUHJG1hdGNoMAIDSW50BAF4BQckbWF0Y2gwBQF4BQdTY2FsZTE2ARJzYXZlQ3VycmVudFdlaWdodHMABAphc3NldElkc0xpCQC1CQIJAQx0cnlHZXRTdHJpbmcBAg9zdGF0aWNfdG9rZW5JZHMCASwKAQFzAgVhY2N1bQdhc3NldElkCQDOCAIFBWFjY3VtCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgICFnJlYmFsYW5jZV9zdGFydFdlaWdodF8FB2Fzc2V0SWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB3N0YXRpY18FB2Fzc2V0SWQCB193ZWlnaHQFA25pbAoAAiRsBQphc3NldElkc0xpCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQFzAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY0XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNF8yAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKARlnZXRWaXJ0dWFsUG9vbFRva2VuQW1vdW50AAkAawMJAQ10cnlHZXRJbnRlZ2VyAQIXZ2xvYmFsX3Bvb2xUb2tlbl9hbW91bnQJAQhnZXRLTXVsdAAFB1NjYWxlMTYBEGNhbGN1bGF0ZVBJc3N1ZWQCBmFtb3VudAd0b2tlbklkBAdQc3VwcGx5CQEZZ2V0VmlydHVhbFBvb2xUb2tlbkFtb3VudAAEB0JhbGFuY2UJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB2dsb2JhbF8JAQ5nZXRBc3NldFN0cmluZwEFB3Rva2VuSWQCCF9iYWxhbmNlBAJ0MQkAbgQFBmFtb3VudAUHUHN1cHBseQUHQmFsYW5jZQUERE9XTgUCdDEBDWdldE1pblBJc3N1ZWQBCHBheW1lbnRzCgEHaGFuZGxlcgIFYWNjdW0HY3VycmVudAQHUElzc3VlZAkBEGNhbGN1bGF0ZVBJc3N1ZWQCCAUHY3VycmVudAZhbW91bnQIBQdjdXJyZW50B2Fzc2V0SWQDCQAAAgUHUElzc3VlZAAACQACAQIkb25lIG9mIHRoZSB0b2tlbnMgYW1vdW50cyBpcyB0b28gbG93AwMJAAACBQVhY2N1bQAABgkAZgIFBWFjY3VtBQdQSXNzdWVkBQdQSXNzdWVkBQVhY2N1bQQJbWluUElzc2VkCgACJGwFCHBheW1lbnRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAAACgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQdoYW5kbGVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY0XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNF8yAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKBQltaW5QSXNzZWQBEmNhbGN1bGF0ZVVzZG5WYWx1ZQQHYXNzZXRJZAZhbW91bnQIYUJhbGFuY2UQZ2l2ZW5Vc2RuQmFsYW5jZQQKdXNkbkluUG9vbAkAzwgCBQhhc3NldElkcwULdXNkbkFzc2V0SWQEDHB1enpsZUluUG9vbAkAzwgCBQhhc3NldElkcwUNcHV6emxlQXNzZXRJZAQKdXNkdEluUG9vbAkAzwgCBQhhc3NldElkcwULdXNkdEFzc2V0SWQEDXVzZHRQcHRJblBvb2wJAM8IAgUIYXNzZXRJZHMFDnVzZHRQcHRBc3NldElkBAt3YXZlc0luUG9vbAkAzwgCBQhhc3NldElkcwUEdW5pdAQLYXNzZXRXZWlnaHQJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB3N0YXRpY18JAQ5nZXRBc3NldFN0cmluZwEFB2Fzc2V0SWQCB193ZWlnaHQEC2ZlZUFzc2V0U3RyCQEMdHJ5R2V0U3RyaW5nAQIPc3RhdGljX2ZlZVRva2VuAwkAAAIFC2ZlZUFzc2V0U3RyBRBwdXp6bGVBc3NldElkU3RyBAxwdXp6bGVXZWlnaHQJAJEDAgUNQXNzZXRzV2VpZ2h0cwkBBXZhbHVlAQkAzwgCBQhhc3NldElkcwUNcHV6emxlQXNzZXRJZAQNcHV6emxlQmFsYW5jZQkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHZ2xvYmFsXwUQcHV6emxlQXNzZXRJZFN0cgIIX2JhbGFuY2UEDmFtb3VudEluUHV6emxlCQBrAwUGYW1vdW50CQBpAgUNcHV6emxlQmFsYW5jZQUMcHV6emxlV2VpZ2h0CQBpAgUIYUJhbGFuY2UFC2Fzc2V0V2VpZ2h0BAtwdXp6bGVQcmljZQkBEUBleHRyTmF0aXZlKDEwNTApAgURcGFyZW50UG9vbEFkZHJlc3MCFmdsb2JhbF9sYXN0UHV6emxlUHJpY2UJAGsDCQBoAgUOYW1vdW50SW5QdXp6bGUFC3B1enpsZVByaWNlAAEFBlNjYWxlOAMJAAACBQtmZWVBc3NldFN0cgUOdXNkdEFzc2V0SWRTdHIECnVzZHRXZWlnaHQJAJEDAgUNQXNzZXRzV2VpZ2h0cwkBBXZhbHVlAQUKdXNkdEluUG9vbAQLdXNkdEJhbGFuY2UJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB2dsb2JhbF8FDnVzZHRBc3NldElkU3RyAghfYmFsYW5jZQkAawMFBmFtb3VudAkAaQIFC3VzZHRCYWxhbmNlBQp1c2R0V2VpZ2h0CQBpAgUIYUJhbGFuY2UFC2Fzc2V0V2VpZ2h0AwkAAAIFC2ZlZUFzc2V0U3RyBRF1c2R0UHB0QXNzZXRJZFN0cgQKdXNkdFdlaWdodAkAkQMCBQ1Bc3NldHNXZWlnaHRzCQEFdmFsdWUBBQ11c2R0UHB0SW5Qb29sBAt1c2R0QmFsYW5jZQkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHZ2xvYmFsXwURdXNkdFBwdEFzc2V0SWRTdHICCF9iYWxhbmNlCQBrAwUGYW1vdW50CQBpAgULdXNkdEJhbGFuY2UFCnVzZHRXZWlnaHQJAGkCBQhhQmFsYW5jZQULYXNzZXRXZWlnaHQDCQAAAgULZmVlQXNzZXRTdHIFDnVzZG5Bc3NldElkU3RyBAp1c2RuV2VpZ2h0CQCRAwIFDUFzc2V0c1dlaWdodHMJAQV2YWx1ZQEJAM8IAgUIYXNzZXRJZHMFC3VzZG5Bc3NldElkBAt1c2RuQmFsYW5jZQQHJG1hdGNoMAUQZ2l2ZW5Vc2RuQmFsYW5jZQMJAAECBQckbWF0Y2gwAgNJbnQEAXgFByRtYXRjaDAFEGdpdmVuVXNkbkJhbGFuY2UJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB2dsb2JhbF8JAQ5nZXRBc3NldFN0cmluZwEFC3VzZG5Bc3NldElkAghfYmFsYW5jZQkAawMFBmFtb3VudAkAaQIJAQV2YWx1ZQEFC3VzZG5CYWxhbmNlBQp1c2RuV2VpZ2h0CQBpAgUIYUJhbGFuY2UFC2Fzc2V0V2VpZ2h0BAt3YXZlc1dlaWdodAC4FwQId0JhbGFuY2UJAGkCCQENdHJ5R2V0SW50ZWdlcgECFGdsb2JhbF9XQVZFU19iYWxhbmNlADIJAGsDBQZhbW91bnQJAGkCBQh3QmFsYW5jZQULd2F2ZXNXZWlnaHQJAGkCBQhhQmFsYW5jZQULYXNzZXRXZWlnaHQBEmdldFByaWNlRnJvbU9yYWNsZQEKYXNzZXRJZFN0cgQHJG1hdGNoMAkAmggCBQ1vcmFjbGVBZGRyZXNzCQCsAgIFCmFzc2V0SWRTdHICB190d2FwNUIDCQABAgUHJG1hdGNoMAIDSW50BAF4BQckbWF0Y2gwBQF4AAABEWNhbGN1bGF0ZVVzZFZhbHVlAwdhc3NldElkBmFtb3VudAhhQmFsYW5jZQQLYXNzZXRXZWlnaHQJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB3N0YXRpY18JAQ5nZXRBc3NldFN0cmluZwEFB2Fzc2V0SWQCB193ZWlnaHQEC2ZlZUFzc2V0U3RyCQEMdHJ5R2V0U3RyaW5nAQIPc3RhdGljX2ZlZVRva2VuBA1mZWVBc3NldFNjYWxlCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQCsAgIJAKwCAgIHc3RhdGljXwULZmVlQXNzZXRTdHICBl9zY2FsZQQLZmVlQXNzZXROdW0JAQV2YWx1ZQEJAM8IAgUIYXNzZXRJZHMJAQ1nZXRBc3NldEJ5dGVzAQULZmVlQXNzZXRTdHIEDmZlZUFzc2V0V2VpZ2h0CQCRAwIFDUFzc2V0c1dlaWdodHMFC2ZlZUFzc2V0TnVtBA9mZWVBc3NldEJhbGFuY2UJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB2dsb2JhbF8FC2ZlZUFzc2V0U3RyAghfYmFsYW5jZQQNdmFsSW5GZWVBc3NldAkAawMFBmFtb3VudAkAaQIFD2ZlZUFzc2V0QmFsYW5jZQUOZmVlQXNzZXRXZWlnaHQJAGkCBQhhQmFsYW5jZQULYXNzZXRXZWlnaHQEDWZlZUFzc2V0UHJpY2UJARJnZXRQcmljZUZyb21PcmFjbGUBBQtmZWVBc3NldFN0cgkAawMFDXZhbEluRmVlQXNzZXQFDWZlZUFzc2V0UHJpY2UFDWZlZUFzc2V0U2NhbGUBE2NoZWNrVG9rZW5zVmFsaWRpdHkBCHBheW1lbnRzCgEIaGFuZGxlcjECBWFjY3VtB3BheW1lbnQJAM4IAgUFYWNjdW0JAMwIAggFB3BheW1lbnQHYXNzZXRJZAUDbmlsBANpZHMKAAIkbAUIcGF5bWVudHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjRfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBCGhhbmRsZXIxAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY0XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNF8yAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAwkAAAIFA2lkcwUDaWRzCgEIaGFuZGxlcjICBWFjY3VtB2Fzc2V0SWQDCQECIT0CCQDPCAIFA2lkcwUHYXNzZXRJZAUEdW5pdAkAZAIFBWFjY3VtAAEJAAIBCQCsAgICFGFzc2V0IG5vdCBhdHRhY2hlZDogCQEOZ2V0QXNzZXRTdHJpbmcBBQdhc3NldElkBAZjaGVja3MKAAIkbAUIYXNzZXRJZHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwAAAKAQUkZjVfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBCGhhbmRsZXIyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY1XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNV8yAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAwkAAAIFBmNoZWNrcwUGY2hlY2tzBgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgETaGFuZGxlUG9vbFRva2Vuc0FkZAQHUElzc3VlZAhwYXltZW50cwt1c2VyQWRkcmVzcwpuZWVkQ2hhbmdlCgEVZ2V0VG9rZW5QYXltZW50QW1vdW50AQd0b2tlbklkCgEHaGFuZGxlcgIFYWNjdW0HcGF5bWVudAMJAAACCAUHcGF5bWVudAdhc3NldElkBQd0b2tlbklkCAUHcGF5bWVudAZhbW91bnQFBWFjY3VtCgACJGwFCHBheW1lbnRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAAACgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQdoYW5kbGVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY0XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNF8yAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKCgERaGFuZGxlVG9rZW5DaGFuZ2UCBWFjY3VtB3Rva2VuSWQEAkJrCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdnbG9iYWxfCQEOZ2V0QXNzZXRTdHJpbmcBBQd0b2tlbklkAghfYmFsYW5jZQQHUFN1cHBseQkBGWdldFZpcnR1YWxQb29sVG9rZW5BbW91bnQABA10b2tlbkRlY2ltYWxzCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdzdGF0aWNfCQEOZ2V0QXNzZXRTdHJpbmcBBQd0b2tlbklkAgZfc2NhbGUEAmExCQC9AgQJALkCAgkAtgIBCQBkAgUHUFN1cHBseQUHUElzc3VlZAkAtgIBBQZTY2FsZTgJALYCAQUNdG9rZW5EZWNpbWFscwkAtgIBBQdQU3VwcGx5BQdDRUlMSU5HBAJEawkAoAMBCQC9AgQJALgCAgUCYTEJALkCAgkAtgIBBQ10b2tlbkRlY2ltYWxzCQC2AgEFBlNjYWxlOAkAtgIBBQJCawkAuQICCQC2AgEFDXRva2VuRGVjaW1hbHMJALYCAQUGU2NhbGU4BQdDRUlMSU5HBA1wYXltZW50QW1vdW50CQEVZ2V0VG9rZW5QYXltZW50QW1vdW50AQUHdG9rZW5JZAQIdG9SZXR1cm4JAGUCBQ1wYXltZW50QW1vdW50BQJEawQBdAMDBQpuZWVkQ2hhbmdlCQBmAgUIdG9SZXR1cm4AAAcJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwULdXNlckFkZHJlc3MFCHRvUmV0dXJuBQd0b2tlbklkBQNuaWwFA25pbAkAzggCCQDOCAIFBWFjY3VtBQF0CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgIHZ2xvYmFsXwkBDmdldEFzc2V0U3RyaW5nAQUHdG9rZW5JZAIIX2JhbGFuY2UJAGQCBQJCawUCRGsFA25pbAoAAiRsBQhhc3NldElkcwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmNF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQERaGFuZGxlVG9rZW5DaGFuZ2UCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjRfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY0XzICCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoBFmhhbmRsZVBvb2xUb2tlbnNSZWRlZW0CCVBSZWRlZW1lZAt1c2VyQWRkcmVzcwoBEWhhbmRsZVRva2VuUmVkZWVtAgVhY2N1bQd0b2tlbklkBAJCawkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHZ2xvYmFsXwkBDmdldEFzc2V0U3RyaW5nAQUHdG9rZW5JZAIIX2JhbGFuY2UEB1BTdXBwbHkJARlnZXRWaXJ0dWFsUG9vbFRva2VuQW1vdW50AAQNdG9rZW5EZWNpbWFscwkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHc3RhdGljXwkBDmdldEFzc2V0U3RyaW5nAQUHdG9rZW5JZAIGX3NjYWxlBAZwc3VwcGwJAL0CBAkAuQICCQC2AgEJAGUCBQdQU3VwcGx5BQlQUmVkZWVtZWQJALYCAQUGU2NhbGU4CQC2AgEFBlNjYWxlOAkAtgIBBQdQU3VwcGx5BQRET1dOBAZhbW91bnQJAKADAQkAvQIECQC4AgIJALYCAQUHU2NhbGUxNgUGcHN1cHBsCQC2AgEFAkJrCQC2AgEFB1NjYWxlMTYFB0NFSUxJTkcJAM4IAgUFYWNjdW0JAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkArAICAgdnbG9iYWxfCQEOZ2V0QXNzZXRTdHJpbmcBBQd0b2tlbklkAghfYmFsYW5jZQkAZQIFAkJrBQZhbW91bnQJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwULdXNlckFkZHJlc3MFBmFtb3VudAUHdG9rZW5JZAUDbmlsCgACJGwFCGFzc2V0SWRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARFoYW5kbGVUb2tlblJlZGVlbQIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjRfMgIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgESY2FsY3VsYXRlT3V0QW1vdW50BQhBbW91bnRJbgdhc3NldEluCGFzc2V0T3V0CUJhbGFuY2VJbgpCYWxhbmNlT3V0BAdJbmRleEluCQEFdmFsdWUBCQDPCAIFCGFzc2V0SWRzBQdhc3NldEluBAhJbmRleE91dAkBBXZhbHVlAQkAzwgCBQhhc3NldElkcwUIYXNzZXRPdXQDCQAAAgUHSW5kZXhJbgUISW5kZXhPdXQFCEFtb3VudEluCQBuBAUKQmFsYW5jZU91dAkAZQIJAGgCBQZTY2FsZTgFBlNjYWxlOAkAoAMBCQB2BgkAvQIECQC5AgIJALYCAQUJQmFsYW5jZUluCQC2AgEAkE4JALYCAQkAaAIFBlNjYWxlOAUGU2NhbGU4CQC5AgIJALYCAQkAZAIFCUJhbGFuY2VJbgUIQW1vdW50SW4JALYCAQCQTgUGSEFMRlVQABAJALYCAQkAawMJAJEDAgUNQXNzZXRzV2VpZ2h0cwUHSW5kZXhJbgCAoJSljR0JAJEDAgUNQXNzZXRzV2VpZ2h0cwUISW5kZXhPdXQADAAQBQdDRUlMSU5HCQBoAgUGU2NhbGU4BQZTY2FsZTgFCEhBTEZFVkVOAR1jYWxjdWxhdGVDdXJyZW50QXNzZXRJbnRlcmVzdAQHYXNzZXRJZAphc3NldElkU3RyCGFCYWxhbmNlFnRva2VuRWFybmluZ3NMYXN0Q2hlY2sEC3RvdGFsU3Rha2VkCQENdHJ5R2V0SW50ZWdlcgECEmdsb2JhbF9pbmRleFN0YWtlZAQVdG9rZW5CYWxhbmNlTGFzdENoZWNrBRZ0b2tlbkVhcm5pbmdzTGFzdENoZWNrBBNjdXJyZW50QmFsYW5jZURlbHRhCQBlAgkBD2dldFRva2VuQmFsYW5jZQEFB2Fzc2V0SWQFCGFCYWxhbmNlBBRjdXJyZW50VG9rZW5FYXJuaW5ncwMJAGYCBRNjdXJyZW50QmFsYW5jZURlbHRhBRV0b2tlbkJhbGFuY2VMYXN0Q2hlY2sFE2N1cnJlbnRCYWxhbmNlRGVsdGEFFXRva2VuQmFsYW5jZUxhc3RDaGVjawQLbmV3RWFybmluZ3MJAGUCBRRjdXJyZW50VG9rZW5FYXJuaW5ncwUVdG9rZW5CYWxhbmNlTGFzdENoZWNrBAtuZXdJbnRlcmVzdAMJAAACBQt0b3RhbFN0YWtlZAAAAAAJAGsDBQtuZXdFYXJuaW5ncwUGU2NhbGU4BQt0b3RhbFN0YWtlZAQRbGFzdENoZWNrSW50ZXJlc3QJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICEWdsb2JhbF9sYXN0Q2hlY2tfBQphc3NldElkU3RyAglfaW50ZXJlc3QJAGQCBRFsYXN0Q2hlY2tJbnRlcmVzdAULbmV3SW50ZXJlc3QBC2NsYWltUmVzdWx0AQdhZGRyZXNzBAphZGRyZXNzU3RyCQClCAEFB2FkZHJlc3MEDHB1enpsZUFtb3VudAkBDXRyeUdldEludGVnZXIBCQCsAgIFCmFkZHJlc3NTdHICDF9pbmRleFN0YWtlZAoBB2hhbmRsZXICBWFjY3VtB2Fzc2V0SWQECmFzc2V0SWRTdHIJAQ5nZXRBc3NldFN0cmluZwEFB2Fzc2V0SWQECGFCYWxhbmNlCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdnbG9iYWxfCQEOZ2V0QXNzZXRTdHJpbmcBBQdhc3NldElkAghfYmFsYW5jZQQWdG9rZW5FYXJuaW5nc0xhc3RDaGVjawkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIRZ2xvYmFsX2xhc3RDaGVja18FCmFzc2V0SWRTdHICCV9lYXJuaW5ncwQUY3VycmVudFRva2VuSW50ZXJlc3QJAR1jYWxjdWxhdGVDdXJyZW50QXNzZXRJbnRlcmVzdAQFB2Fzc2V0SWQFCmFzc2V0SWRTdHIFCGFCYWxhbmNlBRZ0b2tlbkVhcm5pbmdzTGFzdENoZWNrBBRjdXJyZW50VG9rZW5FYXJuaW5ncwkAlgMBCQDMCAIFFnRva2VuRWFybmluZ3NMYXN0Q2hlY2sJAMwIAgkAZQIJAQ9nZXRUb2tlbkJhbGFuY2UBBQdhc3NldElkBQhhQmFsYW5jZQUDbmlsBAxyZXdhcmRBbW91bnQJAGsDBQxwdXp6bGVBbW91bnQJAGUCBRRjdXJyZW50VG9rZW5JbnRlcmVzdAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgkArAICBQphZGRyZXNzU3RyAgtfbGFzdENoZWNrXwUKYXNzZXRJZFN0cgIJX2ludGVyZXN0BQZTY2FsZTgECHRyYW5zZmVyAwkAAAIFDHJld2FyZEFtb3VudAAABQNuaWwJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUHYWRkcmVzcwUMcmV3YXJkQW1vdW50BQdhc3NldElkBQNuaWwJAJQKAgkAzggCCQDOCAIIBQVhY2N1bQJfMQUIdHJhbnNmZXIJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkArAICAhFnbG9iYWxfbGFzdENoZWNrXwUKYXNzZXRJZFN0cgIJX2Vhcm5pbmdzCQBlAgUUY3VycmVudFRva2VuRWFybmluZ3MFDHJld2FyZEFtb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgICEWdsb2JhbF9sYXN0Q2hlY2tfBQphc3NldElkU3RyAglfaW50ZXJlc3QFFGN1cnJlbnRUb2tlbkludGVyZXN0CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgkArAICBQphZGRyZXNzU3RyAgtfbGFzdENoZWNrXwUKYXNzZXRJZFN0cgIJX2ludGVyZXN0BRRjdXJyZW50VG9rZW5JbnRlcmVzdAUDbmlsCQBkAggFBWFjY3VtAl8yCQERY2FsY3VsYXRlVXNkVmFsdWUDBQdhc3NldElkBQxyZXdhcmRBbW91bnQFCGFCYWxhbmNlBAVhY2N1bQoAAiRsBQxlYXJuZWRBc3NldHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCUCgIFA25pbAAACgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQdoYW5kbGVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY0XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNF8yAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKCQCUCgIJAM4IAggFBWFjY3VtAl8xCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIFCmFkZHJlc3NTdHICEV9jbGFpbWVkUmV3YXJkVVNECQBkAgkBDXRyeUdldEludGVnZXIBCQCsAgIFCmFkZHJlc3NTdHICEV9jbGFpbWVkUmV3YXJkVVNECAUFYWNjdW0CXzIJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgUKYWRkcmVzc1N0cgIKX2xhc3RDbGFpbQgFCWxhc3RCbG9jawl0aW1lc3RhbXAFA25pbAgFBWFjY3VtAl8yARBpbmRleFN0YWtlUmVzdWx0AgphZGRyZXNzU3RyBmFtb3VudAQCbGkICQELY2xhaW1SZXN1bHQBCQERQGV4dHJOYXRpdmUoMTA2MikBBQphZGRyZXNzU3RyAl8xCQDOCAIFAmxpCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIFCmFkZHJlc3NTdHICDF9pbmRleFN0YWtlZAkAZAIJAQ10cnlHZXRJbnRlZ2VyAQkArAICBQphZGRyZXNzU3RyAgxfaW5kZXhTdGFrZWQFBmFtb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgISZ2xvYmFsX2luZGV4U3Rha2VkCQBkAgkBDXRyeUdldEludGVnZXIBAhJnbG9iYWxfaW5kZXhTdGFrZWQFBmFtb3VudAUDbmlsAQNzdW0CBWFjY3VtAW4JAGQCBQVhY2N1bQkBDXBhcnNlSW50VmFsdWUBBQFuAQ1jaGVja0ZlZUFzc2V0AgVhY2N1bQRuZXh0AwMJAQIhPQIJAM8IAgUVc3VwcG9ydGVkRmVlQXNzZXRzU3RyBQRuZXh0BQR1bml0CQAAAgUFYWNjdW0CAAcFBG5leHQFBWFjY3VtARJnZXRUbXBSZWJhbGFuY2VJZHMBDW5ld0Fzc2V0SWRzTGkEEWN1cnJlbnRBc3NldElkc0xpCQC1CQIJAQx0cnlHZXRTdHJpbmcBAg9zdGF0aWNfdG9rZW5JZHMCASwEBnJlc3VsdAUNbmV3QXNzZXRJZHNMaQoBAWYCBWFjY3VtB2Fzc2V0SWQDCQAAAgkAzwgCBQZyZXN1bHQFB2Fzc2V0SWQFBHVuaXQJAM4IAgUFYWNjdW0JAMwIAgUHYXNzZXRJZAUDbmlsBQVhY2N1bQoAAiRsBRFjdXJyZW50QXNzZXRJZHNMaQoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFBnJlc3VsdAoBBSRmNF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEBZgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNF8yAgIkYQIkaQMJAGcCBQIk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JGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoJAMwIAgkBC1N0cmluZ0VudHJ5AgIPc3RhdGljX3Rva2VuSWRzBQthc3NldElkc1N0cgkAzAgCCQELU3RyaW5nRW50cnkCAg9zdGF0aWNfZmVlVG9rZW4FC2ZlZUFzc2V0U3RyCQDMCAIJAQtTdHJpbmdFbnRyeQICE3N0YXRpY190b2tlbldlaWdodHMFD2Fzc2V0V2VpZ2h0c1N0cgkAzAgCCQEMSW50ZWdlckVudHJ5AgITc3RhdGljX3Rva2Vuc0Ftb3VudAkAkAMBBQphc3NldElkc0xpCQDMCAIJAQtTdHJpbmdFbnRyeQICEXN0YXRpY19wb29sRG9tYWluBQpwb29sRG9tYWluCQDMCAIJAQtTdHJpbmdFbnRyeQICEnN0YXRpY19iYXNlVG9rZW5JZAUOYmFzZVRva2VuSWRTdHIJAMwIAgkBC1N0cmluZ0VudHJ5AgIQc3RhdGljX3Bvb2xPd25lcgUJcG9vbE93bmVyCQDMCAIJAQxJbnRlZ2VyRW50cnkCAgpzdGF0aWNfZmVlBQNmZWUJAMwIAgkBDEludGVnZXJFbnRyeQICDHN0YXRpY19LTXVsdAUHU2NhbGUxNgkAzAgCCQEMSW50ZWdlckVudHJ5AgITZ2xvYmFsX3dhc1ByZUluaXRlZAABBQNuaWwBaQEGZGVJbml0AAMJAQppc1NodXRkb3duAAkAAgECE2NvbnRyYWN0IGlzIG9uIHN0b3ADCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAgphZG1pbiBvbmx5CQDMCAIJAQxJbnRlZ2VyRW50cnkCAhBnbG9iYWxfd2FzSW5pdGVkAAAFA25pbAFpAQRpbml0AAoBC3ByZXBhcmVMaXN0AAoBB2hhbmRsZXICBWFjY3VtAW4JAM4IAgUFYWNjdW0JAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkArAICAgdnbG9iYWxfCQEOZ2V0QXNzZXRTdHJpbmcBCAUBbgdhc3NldElkAghfYmFsYW5jZQgFAW4GYW1vdW50BQNuaWwKAAIkbAgFAWkIcGF5bWVudHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjRfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBB2hhbmRsZXICBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjRfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY0XzICCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoKARljYWxjdWxhdGVQb29sVG9rZW5zQW1vdW50AQhwYXltZW50cwoBB2hhbmRsZXICBWFjY3VtA3BtdAQHYXNzZXRJZAgFA3BtdAdhc3NldElkCgEIaGFuZGxlcjICBWFjY3VtAW4DCQAAAgUBbgUHYXNzZXRJZAkBBXZhbHVlAQkAzwgCBQhhc3NldElkcwUBbgUFYWNjdW0EBVRva2VuCgACJGwFCGFzc2V0SWRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAABCgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQhoYW5kbGVyMgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjRfMgIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgkAawMFBWFjY3VtCQBsBggFA3BtdAZhbW91bnQJAJEDAgUIRGVjaW1hbHMFBVRva2VuCQCRAwIFDUFzc2V0c1dlaWdodHMFBVRva2VuBRVBc3NldHNXZWlnaHRzRGVjaW1hbHMACAUFRkxPT1IFBlNjYWxlOAoAAiRsBQhwYXltZW50cwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFDlBvb2xUb2tlblNjYWxlCgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQdoYW5kbGVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY0XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNF8yAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAwkBCmlzU2h1dGRvd24ACQACAQITY29udHJhY3QgaXMgb24gc3RvcAMJAGYCCQENdHJ5R2V0SW50ZWdlcgECEGdsb2JhbF93YXNJbml0ZWQAAAkAAgECE3Bvb2wgYWxyZWFkeSBpbml0ZWQEEWluaXRpYWxQb29sVG9rZW5zCQEZY2FsY3VsYXRlUG9vbFRva2Vuc0Ftb3VudAEIBQFpCHBheW1lbnRzAwkAAAIFEWluaXRpYWxQb29sVG9rZW5zAAAJAAIBAjJ5b3UgbmVlZCBhIGJpZ2dlciB0b2tlbnMgYW1vdW50IHRvIGxhdW5jaCB0aGUgcG9vbAQOcG9vbFRva2VuSXNzdWUJAMMIBwkArAICAgNQWiAJAQx0cnlHZXRTdHJpbmcBAhFzdGF0aWNfcG9vbERvbWFpbgIdUHV6emxlIFN3YXA6IHBvb2wgaW5kZXggdG9rZW4FEWluaXRpYWxQb29sVG9rZW5zBRFQb29sVG9rZW5EZWNpbWFscwYFBHVuaXQAAAQLcG9vbFRva2VuSWQJALgIAQUOcG9vbFRva2VuSXNzdWUJAM4IAgkBC3ByZXBhcmVMaXN0AAkAzAgCBQ5wb29sVG9rZW5Jc3N1ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgIXZ2xvYmFsX3Bvb2xUb2tlbl9hbW91bnQFEWluaXRpYWxQb29sVG9rZW5zCQDMCAIJAQxJbnRlZ2VyRW50cnkCAhBnbG9iYWxfd2FzSW5pdGVkAAEJAMwIAgkBC0JpbmFyeUVudHJ5AgITZ2xvYmFsX3Bvb2xUb2tlbl9pZAULcG9vbFRva2VuSWQJAMwIAgkBC1N0cmluZ0VudHJ5AgIWc3RhdGljX3Bvb2xUb2tlbl9pZFN0cgkBDmdldEFzc2V0U3RyaW5nAQULcG9vbFRva2VuSWQJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkApQgBCAUBaQZjYWxsZXICDF9pbmRleFN0YWtlZAURaW5pdGlhbFBvb2xUb2tlbnMJAMwIAgkBDEludGVnZXJFbnRyeQICEmdsb2JhbF9pbmRleFN0YWtlZAURaW5pdGlhbFBvb2xUb2tlbnMFA25pbAFpAQ1nZW5lcmF0ZUluZGV4AQpuZWVkQ2hhbmdlAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwUBVAkAAgEJAKwCAgI7eW91IG5lZWQgdG8gYXR0YWNoIGFsbCBwb29sIHRva2Vucy4gYW1vdW50IG9mIHBvb2wgdG9rZW5zOiAJAKQDAQUBVAMJAQEhAQkBE2NoZWNrVG9rZW5zVmFsaWRpdHkBCAUBaQhwYXltZW50cwkAAgECFXdyb25nIGFzc2V0cyBhdHRhY2hlZAQNUElzc3VlZE5vTXVsdAkBDWdldE1pblBJc3N1ZWQBCAUBaQhwYXltZW50cwQGcmVzdWx0CQETaGFuZGxlUG9vbFRva2Vuc0FkZAQFDVBJc3N1ZWROb011bHQIBQFpCHBheW1lbnRzCAUBaQxvcmlnaW5DYWxsZXIFCm5lZWRDaGFuZ2UED1BJc3N1ZWRXaXRoTXVsdAkAbgQFDVBJc3N1ZWROb011bHQFB1NjYWxlMTYJAQhnZXRLTXVsdAAFBERPV04EB3JlaXNzdWUJAQdSZWlzc3VlAwkBEUBleHRyTmF0aXZlKDEwNTcpAQITZ2xvYmFsX3Bvb2xUb2tlbl9pZAUPUElzc3VlZFdpdGhNdWx0BgkAlAoCCQDOCAIFBnJlc3VsdAkAzAgCBQdyZWlzc3VlCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgUPUElzc3VlZFdpdGhNdWx0CQEMdHJ5R2V0QmluYXJ5AQITZ2xvYmFsX3Bvb2xUb2tlbl9pZAkAzAgCCQEMSW50ZWdlckVudHJ5AgIXZ2xvYmFsX3Bvb2xUb2tlbl9hbW91bnQJAGQCCQENdHJ5R2V0SW50ZWdlcgECF2dsb2JhbF9wb29sVG9rZW5fYW1vdW50BQ9QSXNzdWVkV2l0aE11bHQFA25pbAUPUElzc3VlZFdpdGhNdWx0AWkBC3JlZGVlbUluZGV4AQxzZW5kVG9PcmlnaW4EA3BtdAkAkQMCCAUBaQhwYXltZW50cwAAAwkBAiE9AggFA3BtdAdhc3NldElkCQEMdHJ5R2V0QmluYXJ5AQITZ2xvYmFsX3Bvb2xUb2tlbl9pZAkAAgECHnBsZWFzZSBhdHRhY2ggcG9vbCBzaGFyZSB0b2tlbgMJAQppc1NodXRkb3duAAkAAgECE2NvbnRyYWN0IGlzIG9uIHN0b3AEEVBSZWRlZW1lZFdpdGhNdWx0CAUDcG10BmFtb3VudAQTUFJlZGVlbWVkV2l0aE5vTXVsdAkAbgQFEVBSZWRlZW1lZFdpdGhNdWx0CQEIZ2V0S011bHQABQdTY2FsZTE2BQRET1dOBAZyZXN1bHQJARZoYW5kbGVQb29sVG9rZW5zUmVkZWVtAgUTUFJlZGVlbWVkV2l0aE5vTXVsdAMFDHNlbmRUb09yaWdpbggFAWkMb3JpZ2luQ2FsbGVyCAUBaQZjYWxsZXIJAM4IAgUGcmVzdWx0CQDMCAIJAQRCdXJuAgkBDHRyeUdldEJpbmFyeQECE2dsb2JhbF9wb29sVG9rZW5faWQFEVBSZWRlZW1lZFdpdGhNdWx0CQDMCAIJAQxJbnRlZ2VyRW50cnkCAhdnbG9iYWxfcG9vbFRva2VuX2Ftb3VudAkAZQIJAQ10cnlHZXRJbnRlZ2VyAQIXZ2xvYmFsX3Bvb2xUb2tlbl9hbW91bnQFEVBSZWRlZW1lZFdpdGhNdWx0BQNuaWwBaQEKc3Rha2VJbmRleAAECmFkZHJlc3NTdHIJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyBANwbXQJAJEDAggFAWkIcGF5bWVudHMAAAMJAQIhPQIJAQV2YWx1ZQEIBQNwbXQHYXNzZXRJZAkBDHRyeUdldEJpbmFyeQECE2dsb2JhbF9wb29sVG9rZW5faWQJAAIBAhR3cm9uZyBhc3NldCBhdHRhY2hlZAkBEGluZGV4U3Rha2VSZXN1bHQCBQphZGRyZXNzU3RyCAUDcG10BmFtb3VudAFpAQ1zdGFrZUluZGV4Rm9yAQphZGRyZXNzU3RyBANwbXQJAJEDAggFAWkIcGF5bWVudHMAAAMJAQIhPQIJAQV2YWx1ZQEIBQNwbXQHYXNzZXRJZAkBDHRyeUdldEJpbmFyeQECE2dsb2JhbF9wb29sVG9rZW5faWQJAAIBAhR3cm9uZyBhc3NldCBhdHRhY2hlZAkBEGluZGV4U3Rha2VSZXN1bHQCBQphZGRyZXNzU3RyCAUDcG10BmFtb3VudAFpAQx1bnN0YWtlSW5kZXgBC2luZGV4QW1vdW50BAphZGRyZXNzU3RyAwkBAiE9AgkAswkCBQ9sYXllcjJBZGRyZXNzZXMJAKUIAQgFAWkGY2FsbGVyBQR1bml0CQClCAEIBQFpDG9yaWdpbkNhbGxlcgkApQgBCAUBaQZjYWxsZXIEDmluZGV4QXZhaWxhYmxlCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgUKYWRkcmVzc1N0cgIMX2luZGV4U3Rha2VkAwkBCmlzU2h1dGRvd24ACQACAQITY29udHJhY3QgaXMgb24gc3RvcAMJAGYCBQtpbmRleEFtb3VudAUOaW5kZXhBdmFpbGFibGUJAAIBAiV5b3UgZG9uJ3QgaGF2ZSBpbmRleCB0b2tlbnMgYXZhaWxhYmxlAwkBCmlzU2h1dGRvd24ACQACAQITY29udHJhY3QgaXMgb24gc3RvcAkAzggCCAkBC2NsYWltUmVzdWx0AQkBEUBleHRyTmF0aXZlKDEwNjIpAQUKYWRkcmVzc1N0cgJfMQkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICBQphZGRyZXNzU3RyAgxfaW5kZXhTdGFrZWQJAGUCBQ5pbmRleEF2YWlsYWJsZQULaW5kZXhBbW91bnQJAMwIAgkBDEludGVnZXJFbnRyeQICEmdsb2JhbF9pbmRleFN0YWtlZAkAZQIJAQ10cnlHZXRJbnRlZ2VyAQISZ2xvYmFsX2luZGV4U3Rha2VkBQtpbmRleEFtb3VudAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIFC2luZGV4QW1vdW50CQERQGV4dHJOYXRpdmUoMTA1NykBAhNnbG9iYWxfcG9vbFRva2VuX2lkBQNuaWwBaQERY2xhaW1JbmRleFJld2FyZHMAAwkBCmlzU2h1dGRvd24ACQACAQITY29udHJhY3QgaXMgb24gc3RvcAkBC2NsYWltUmVzdWx0AQgFAWkGY2FsbGVyAWkBDWV2YWx1YXRlQ2xhaW0BBHVzZXIJAJQKAgUDbmlsCAkBC2NsYWltUmVzdWx0AQkBEUBleHRyTmF0aXZlKDEwNjIpAQUEdXNlcgJfMgFpAQRzd2FwAghhc3NldE91dAdtaW5pbXVtBANwbXQDCQAAAgkAkAMBCAUBaQhwYXltZW50cwABCQEFdmFsdWUBCQCRAwIIBQFpCHBheW1lbnRzAAAJAAIBAiFwbGVhc2UgYXR0YWNoIGV4YWN0bHkgb25lIHBheW1lbnQECEFtb3VudEluCQEFdmFsdWUBCAkAkQMCCAUBaQhwYXltZW50cwAABmFtb3VudAQHQXNzZXRJbggFA3BtdAdhc3NldElkBAhBc3NldE91dAkBDWdldEFzc2V0Qnl0ZXMBBQhhc3NldE91dAQHYXNzZXRJbgkBDmdldEFzc2V0U3RyaW5nAQUHQXNzZXRJbgQHc2NhbGVJbgkAaQIFBlNjYWxlOAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHc3RhdGljXwUHYXNzZXRJbgIGX3NjYWxlBAhzY2FsZU91dAkAaQIFBlNjYWxlOAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHc3RhdGljXwUIYXNzZXRPdXQCBl9zY2FsZQQOZmVlQXNzZXRPdXRTdHIJAQx0cnlHZXRTdHJpbmcBAg9zdGF0aWNfZmVlVG9rZW4EC2ZlZUFzc2V0T3V0AwkAAAIFDmZlZUFzc2V0T3V0U3RyAgAFC3VzZG5Bc3NldElkCQENZ2V0QXNzZXRCeXRlcwEFDmZlZUFzc2V0T3V0U3RyBA5Bc3NldEluQmFsYW5jZQkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHZ2xvYmFsXwkBDmdldEFzc2V0U3RyaW5nAQUHQXNzZXRJbgIIX2JhbGFuY2UED0Fzc2V0T3V0QmFsYW5jZQkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHZ2xvYmFsXwUIYXNzZXRPdXQCCF9iYWxhbmNlBBRBc3NldEluQmFsYW5jZVNjYWxlZAkAaAIFDkFzc2V0SW5CYWxhbmNlBQdzY2FsZUluBBVBc3NldE91dEJhbGFuY2VTY2FsZWQJAGgCBQ9Bc3NldE91dEJhbGFuY2UFCHNjYWxlT3V0BAtmZWVBbW91bnRJbgkAawMFCEFtb3VudEluBQNGZWUFCEZlZVNjYWxlBA1jbGVhbkFtb3VudEluCQBlAgUIQW1vdW50SW4FC2ZlZUFtb3VudEluBBNjbGVhbkFtb3VudEluU2NhbGVkCQBoAgUNY2xlYW5BbW91bnRJbgUHc2NhbGVJbgQKQW1vdW50T3V0MQkBEmNhbGN1bGF0ZU91dEFtb3VudAUFE2NsZWFuQW1vdW50SW5TY2FsZWQFB0Fzc2V0SW4FCEFzc2V0T3V0BRRBc3NldEluQmFsYW5jZVNjYWxlZAUVQXNzZXRPdXRCYWxhbmNlU2NhbGVkBAlBbW91bnRPdXQJAGsDBQpBbW91bnRPdXQxAAEFCHNjYWxlT3V0BBBBc3NldE91dEJhbGFuY2UyCQBlAgUPQXNzZXRPdXRCYWxhbmNlBQlBbW91bnRPdXQED0Fzc2V0SW5CYWxhbmNlMgkAZAIFDkFzc2V0SW5CYWxhbmNlBQ1jbGVhbkFtb3VudEluBBJmZWVBc3NldE91dEJhbGFuY2UDCQAAAgULZmVlQXNzZXRPdXQFB0Fzc2V0SW4FD0Fzc2V0SW5CYWxhbmNlMgMJAAACBQtmZWVBc3NldE91dAUIQXNzZXRPdXQFEEFzc2V0T3V0QmFsYW5jZTIJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB2dsb2JhbF8JAQ5nZXRBc3NldFN0cmluZwEFC2ZlZUFzc2V0T3V0AghfYmFsYW5jZQQMZmVlQW1vdW50T3V0CQESY2FsY3VsYXRlT3V0QW1vdW50BQULZmVlQW1vdW50SW4FB0Fzc2V0SW4FC2ZlZUFzc2V0T3V0BQ5Bc3NldEluQmFsYW5jZQUSZmVlQXNzZXRPdXRCYWxhbmNlAwkAZgIFB21pbmltdW0FCUFtb3VudE91dAkAAgECKWFtb3VudCB0byByZWNpZXZlIGlzIGxvd2VyIHRoYW4gZ2l2ZW4gb25lAwkAAAIFCEFzc2V0T3V0BQdBc3NldEluCQACAQIYdGhpcyBzd2FwIGlzIG5vdCBhbGxvd2VkAwkAZgIAAAkAZQIFD0Fzc2V0T3V0QmFsYW5jZQUJQW1vdW50T3V0CQACAQIbY29udHJhY3QgaXMgb3V0IG9mIHJlc2VydmVzAwkBCmlzU2h1dGRvd24ACQACAQITY29udHJhY3QgaXMgb24gc3RvcAQKY3JlYXRvckZlZQkAawMFDGZlZUFtb3VudE91dAABAAoEC3Byb3RvY29sRmVlCQBrAwUMZmVlQW1vdW50T3V0AAQACgQMbmV3QmFsYW5jZUluBQ9Bc3NldEluQmFsYW5jZTIEDW5ld0JhbGFuY2VPdXQJAGUCBRBBc3NldE91dEJhbGFuY2UyAwkAAAIFCEFzc2V0T3V0BQtmZWVBc3NldE91dAUMZmVlQW1vdW50T3V0AAAEEm5ld0JhbGFuY2VGZWVBc3NldAMDCQECIT0CBQtmZWVBc3NldE91dAUHQXNzZXRJbgkBAiE9AgULZmVlQXNzZXRPdXQFCEFzc2V0T3V0BwkAZQIFEmZlZUFzc2V0T3V0QmFsYW5jZQUMZmVlQW1vdW50T3V0BQR1bml0BA1hc3NldEluQ2hhbmdlCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgICB2dsb2JhbF8JAQ5nZXRBc3NldFN0cmluZwEFB0Fzc2V0SW4CCF9iYWxhbmNlBQxuZXdCYWxhbmNlSW4EDmFzc2V0T3V0Q2hhbmdlCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgICB2dsb2JhbF8FCGFzc2V0T3V0AghfYmFsYW5jZQUNbmV3QmFsYW5jZU91dAQRZmVlQXNzZXRPdXRDaGFuZ2UDCQECIT0CBRJuZXdCYWxhbmNlRmVlQXNzZXQFBHVuaXQJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgIHZ2xvYmFsXwkBDmdldEFzc2V0U3RyaW5nAQULZmVlQXNzZXRPdXQCCF9iYWxhbmNlCQEFdmFsdWUBBRJuZXdCYWxhbmNlRmVlQXNzZXQJAQtTdHJpbmdFbnRyeQICBWhlbGxvAgV3b3JsZAQMdm9sdW1lVXBkYXRlCQESY2FsY3VsYXRlVXNkblZhbHVlBAUHQXNzZXRJbgUIQW1vdW50SW4FDkFzc2V0SW5CYWxhbmNlBRJmZWVBc3NldE91dEJhbGFuY2UED3ZvbHVtZVVzZFVwZGF0ZQkBEWNhbGN1bGF0ZVVzZFZhbHVlAwUHQXNzZXRJbgUIQW1vdW50SW4FDkFzc2V0SW5CYWxhbmNlCQCUCgIJAMwIAgUOYXNzZXRPdXRDaGFuZ2UJAMwIAgUNYXNzZXRJbkNoYW5nZQkAzAgCBRFmZWVBc3NldE91dENoYW5nZQkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIFCUFtb3VudE91dAUIQXNzZXRPdXQJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwkBEUBleHRyTmF0aXZlKDEwNjIpAQkBDHRyeUdldFN0cmluZwECEHN0YXRpY19wb29sT3duZXIFCmNyZWF0b3JGZWUFC2ZlZUFzc2V0T3V0CQDMCAIJAQxJbnRlZ2VyRW50cnkCAhRnbG9iYWxfZWFybmVkQnlPd25lcgkAZAIJAQ10cnlHZXRJbnRlZ2VyAQIUZ2xvYmFsX2Vhcm5lZEJ5T3duZXIFCmNyZWF0b3JGZWUJAMwIAgkBDEludGVnZXJFbnRyeQICDWdsb2JhbF92b2x1bWUJAGQCCQENdHJ5R2V0SW50ZWdlcgECDWdsb2JhbF92b2x1bWUFDHZvbHVtZVVwZGF0ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgIRZ2xvYmFsX3ZvbHVtZV91c2QJAGQCCQENdHJ5R2V0SW50ZWdlcgECEWdsb2JhbF92b2x1bWVfdXNkBQ92b2x1bWVVc2RVcGRhdGUJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwULZmVlc0FkZHJlc3MFC3Byb3RvY29sRmVlBQtmZWVBc3NldE91dAUDbmlsBQlBbW91bnRPdXQBaQEMc3dhcFJlYWRPbmx5Awdhc3NldEluCGFzc2V0T3V0CEFtb3VudEluBAdBc3NldEluCQENZ2V0QXNzZXRCeXRlcwEFB2Fzc2V0SW4ECEFzc2V0T3V0CQENZ2V0QXNzZXRCeXRlcwEFCGFzc2V0T3V0BAdzY2FsZUluCQBpAgUGU2NhbGU4CQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdzdGF0aWNfBQdhc3NldEluAgZfc2NhbGUECHNjYWxlT3V0CQBpAgUGU2NhbGU4CQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdzdGF0aWNfBQhhc3NldE91dAIGX3NjYWxlBA5mZWVBc3NldE91dFN0cgkBDHRyeUdldFN0cmluZwECD3N0YXRpY19mZWVUb2tlbgQLZmVlQXNzZXRPdXQDCQAAAgUOZmVlQXNzZXRPdXRTdHICAAULdXNkbkFzc2V0SWQJAQ1nZXRBc3NldEJ5dGVzAQUOZmVlQXNzZXRPdXRTdHIEDkFzc2V0SW5CYWxhbmNlCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdnbG9iYWxfCQEOZ2V0QXNzZXRTdHJpbmcBBQdBc3NldEluAghfYmFsYW5jZQQPQXNzZXRPdXRCYWxhbmNlCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdnbG9iYWxfBQhhc3NldE91dAIIX2JhbGFuY2UEFEFzc2V0SW5CYWxhbmNlU2NhbGVkCQBoAgUOQXNzZXRJbkJhbGFuY2UFB3NjYWxlSW4EFUFzc2V0T3V0QmFsYW5jZVNjYWxlZAkAaAIFD0Fzc2V0T3V0QmFsYW5jZQUIc2NhbGVPdXQEC2ZlZUFtb3VudEluCQBrAwUIQW1vdW50SW4FA0ZlZQUIRmVlU2NhbGUEDWNsZWFuQW1vdW50SW4JAGUCBQhBbW91bnRJbgULZmVlQW1vdW50SW4EE2NsZWFuQW1vdW50SW5TY2FsZWQJAGgCBQ1jbGVhbkFtb3VudEluBQdzY2FsZUluBApBbW91bnRPdXQxCQESY2FsY3VsYXRlT3V0QW1vdW50BQUTY2xlYW5BbW91bnRJblNjYWxlZAUHQXNzZXRJbgUIQXNzZXRPdXQFFEFzc2V0SW5CYWxhbmNlU2NhbGVkBRVBc3NldE91dEJhbGFuY2VTY2FsZWQECUFtb3VudE91dAkAawMFCkFtb3VudE91dDEAAQUIc2NhbGVPdXQEEEFzc2V0T3V0QmFsYW5jZTIJAGUCBQ9Bc3NldE91dEJhbGFuY2UFCUFtb3VudE91dAQPQXNzZXRJbkJhbGFuY2UyCQBkAgUOQXNzZXRJbkJhbGFuY2UFDWNsZWFuQW1vdW50SW4EEmZlZUFzc2V0T3V0QmFsYW5jZQMJAAACBQtmZWVBc3NldE91dAUHQXNzZXRJbgUPQXNzZXRJbkJhbGFuY2UyAwkAAAIFC2ZlZUFzc2V0T3V0BQhBc3NldE91dAUQQXNzZXRPdXRCYWxhbmNlMgkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHZ2xvYmFsXwkBDmdldEFzc2V0U3RyaW5nAQULZmVlQXNzZXRPdXQCCF9iYWxhbmNlBAxmZWVBbW91bnRPdXQJARJjYWxjdWxhdGVPdXRBbW91bnQFBQtmZWVBbW91bnRJbgUHQXNzZXRJbgULZmVlQXNzZXRPdXQFDkFzc2V0SW5CYWxhbmNlBRJmZWVBc3NldE91dEJhbGFuY2UDCQAAAgUIQXNzZXRPdXQFB0Fzc2V0SW4JAAIBAhh0aGlzIHN3YXAgaXMgbm90IGFsbG93ZWQDCQBmAgAACQBlAgUPQXNzZXRPdXRCYWxhbmNlBQlBbW91bnRPdXQJAAIBAhtjb250cmFjdCBpcyBvdXQgb2YgcmVzZXJ2ZXMDCQEKaXNTaHV0ZG93bgAJAAIBAhNjb250cmFjdCBpcyBvbiBzdG9wCQCUCgIFA25pbAUJQW1vdW50T3V0AWkBEXRyYW5zZmVyT3duZXJzaGlwAQ9uZXdPd25lckFkZHJlc3MDCQECIT0CCQClCAEIBQFpBmNhbGxlcgkBDHRyeUdldFN0cmluZwECEHN0YXRpY19wb29sT3duZXIJAAIBAid0aGlzIGNhbGwgYXZhaWxhYmxlIG9ubHkgZm9yIHBvb2wgb3duZXIJAMwIAgkBC1N0cmluZ0VudHJ5AgIQc3RhdGljX3Bvb2xPd25lcgUPbmV3T3duZXJBZGRyZXNzBQNuaWwBaQEGc2V0RmVlAQZuZXdGZWUDCQECIT0CCQClCAEIBQFpBmNhbGxlcgkBDHRyeUdldFN0cmluZwECEHN0YXRpY19wb29sT3duZXIJAAIBAid0aGlzIGNhbGwgYXZhaWxhYmxlIG9ubHkgZm9yIHBvb2wgb3duZXIDCQBmAgABCQELdmFsdWVPckVsc2UCCQCaCAIFCmdvdkFkZHJlc3MJAKwCAgILYXBwcm92ZWRUeF8JANgEAQgFAWkNdHJhbnNhY3Rpb25JZAAACQACAQIzdGhpcyB0cmFuc2FjdGlvbiBuZWVkcyBhcHByb3ZhbCBmcm9tIHB1enpsZSBuZXR3b3JrCQDMCAIJAQxJbnRlZ2VyRW50cnkCAgpzdGF0aWNfZmVlBQZuZXdGZWUFA25pbAFpARJzZXRSZWJhbGFuY2luZ1BsYW4FC2Fzc2V0SWRzU3RyD2Fzc2V0V2VpZ2h0c1N0cg5iYXNlVG9rZW5JZFN0cgtzdGVwc0Ftb3VudA1zdGVwc0ludGVydmFsAwkBAiE9AggFAWkGY2FsbGVyCQERQGV4dHJOYXRpdmUoMTA2MikBCQEMdHJ5R2V0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C2FkZGVkQXNzZXRzCAUBaQhwYXltZW50cwQMdmFsaWRXZWlnaHRzCQEPdmFsaWRhdGVXZWlnaHRzAQUUbmV3QXNzZXRXZWlnaHRzU3RyTGkDCQAAAgUMdmFsaWRXZWlnaHRzBQx2YWxpZFdlaWdodHMDCQECIT0CBQ12YWxpZFBheW1lbnRzCQBkAgkAkAMBBQthZGRlZEFzc2V0cwkAkAMBCAUBaQhwYXltZW50cwkAAgECMVBheW1lbnRzIG5vdCBwcmVzZW50IG9yIHNvbWV0aGluZyB3cm9uZyB3aXRoIHRoZW0DCQECIT0CCQCQAwEFEG5ld0Fzc2V0SWRzU3RyTGkJAJADAQUUbmV3QXNzZXRXZWlnaHRzU3RyTGkJAAIBAjFhc3NldElkcyBhbmQgYXNzZXRXZWlnaHRzIHNob3VsZCBoYXZlIHNhbWUgbGVuZ3RoAwkBAiE9AgUNdmFsaWRQYXltZW50cwkAZAIJAJADAQULYWRkZWRBc3NldHMJAJADAQgFAWkIcGF5bWVudHMJAAIBAjFQYXltZW50cyBub3QgcHJlc2VudCBvciBzb21ldGhpbmcgd3Jvbmcgd2l0aCB0aGVtAwkAAAIFC2ZlZUFzc2V0U3RyAgAJAAIBAkFwb29sIG11c3QgaGF2ZSBvbmUgb2YgdGhlIHN1cHBvcnRlZCBmZWUgYXNzZXRzIGluIHRoZSBjb21wb3NpdGlvbgMJAAACCQDPCAIFEG5ld0Fzc2V0SWRzU3RyTGkFDmJhc2VUb2tlbklkU3RyBQR1bml0CQACAQIpYmFzZVRva2VuSWQgc2hvdWxkIGJlIHByZXNlbnQgaW4gYXNzZXRJZHMDAwkAZgIFEE1JTl9TVEVQU19BTU9VTlQFC3N0ZXBzQW1vdW50BgkAZgIFC3N0ZXBzQW1vdW50BRBNQVhfU1RFUFNfQU1PVU5UCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgICH1N0ZXBzIGFtb3VudCBzaG91bGQgYmUgYmV0d2VlbiAJAKQDAQUQTUlOX1NURVBTX0FNT1VOVAIFIGFuZCAJAKQDAQUQTUFYX1NURVBTX0FNT1VOVAILLCBjdXJyZW50OiAJAKQDAQULc3RlcHNBbW91bnQDAwkAZgIFEk1JTl9TVEVQU19JTlRFUlZBTAUNc3RlcHNJbnRlcnZhbAYJAGYCBQ1zdGVwc0ludGVydmFsBRJNQVhfU1RFUFNfSU5URVJWQUwJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIhU3RlcHMgaW50ZXJ2YWwgc2hvdWxkIGJlIGJldHdlZW4gCQCkAwEFEk1JTl9TVEVQU19JTlRFUlZBTAIFIGFuZCAJAKQDAQUSTUFYX1NURVBTX0lOVEVSVkFMAgssIGN1cnJlbnQ6IAkApAMBBQ1zdGVwc0ludGVydmFsAwkBAiE9AgUPYXNzZXRXZWlnaHRzU3VtAJBOCQACAQkArAICAjZzdW0gb2YgdG9rZW4gd2VpZ2h0cyBtdXN0IGJlIGVxdWFsIHRvIDEwMDAwLCBjdXJyZW50OiAJAKQDAQUPYXNzZXRXZWlnaHRzU3VtCgEBZgIFYWNjdW0KYXNzZXRJZFN0cgQJb2xkV2VpZ2h0CQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdzdGF0aWNfBQphc3NldElkU3RyAgdfd2VpZ2h0BAluZXdXZWlnaHQDCQAAAgkAzwgCBRBuZXdBc3NldElkc1N0ckxpBQphc3NldElkU3RyBQR1bml0AAAJAQ1wYXJzZUludFZhbHVlAQkBBXZhbHVlAQkAkQMCBRRuZXdBc3NldFdlaWdodHNTdHJMaQkBBXZhbHVlAQkAzwgCBRBuZXdBc3NldElkc1N0ckxpBQphc3NldElkU3RyBAxkZWx0YVBlclN0ZXAJAGsDCQBlAgUJbmV3V2VpZ2h0BQlvbGRXZWlnaHQAkE4FC3N0ZXBzQW1vdW50CQDOCAIFBWFjY3VtCQDMCAIJAKQDAQUMZGVsdGFQZXJTdGVwBQNuaWwEDXRtcEFzc2V0SWRzTGkJARJnZXRUbXBSZWJhbGFuY2VJZHMBBRBuZXdBc3NldElkc1N0ckxpBAthc3NldERlbHRhcwoAAiRsBQ10bXBBc3NldElkc0xpCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGY4XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQFmAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY4XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmOF8yAgkBBSRmOF8xAgkBBSRmOF8xAgkBBSRmOF8xAgkBBSRmOF8xAgkBBSRmOF8xAgkBBSRmOF8xAgkBBSRmOF8xAgkBBSRmOF8xAgkBBSRmOF8xAgkBBSRmOF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKBA5uZXdUb2tlbnNBZGRlZAkAZgIJARFjaGVja1Rva2Vuc0NoYW5nZQEFEG5ld0Fzc2V0SWRzU3RyTGkAAAoBEnJlY29yZEFzc2V0UGF5bWVudAIFYWNjdW0EbmV4dAkAzggCBQVhY2N1bQkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhpyZWJhbGFuY2VfYXR0YWNoZWRQYXltZW50XwkBDmdldEFzc2V0U3RyaW5nAQgFBG5leHQHYXNzZXRJZAgFBG5leHQGYW1vdW50BQNuaWwEDnBheW1lbnRFbnRyaWVzCgACJGwIBQFpCHBheW1lbnRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGY5XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARJyZWNvcmRBc3NldFBheW1lbnQCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjlfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY5XzICCQEFJGY5XzECCQEFJGY5XzECCQEFJGY5XzECCQEFJGY5XzECCQEFJGY5XzECCQEFJGY5XzECCQEFJGY5XzECCQEFJGY5XzECCQEFJGY5XzECCQEFJGY5XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoEDHN0b3JlV2VpZ2h0cwkBEnNhdmVDdXJyZW50V2VpZ2h0cwAEEHJlcXVlc3RHb3ZJbnZva2UJAPwHBAUKZ292QWRkcmVzcwIScmVxdWVzdFJlYmFsYW5jaW5nCQDMCAIJANgEAQgFAWkNdHJhbnNhY3Rpb25JZAUDbmlsBQNuaWwDCQAAAgUQcmVxdWVzdEdvdkludm9rZQUQcmVxdWVzdEdvdkludm9rZQkAzggCCQDOCAIJAMwIAgkBC1N0cmluZ0VudHJ5AgIVcmViYWxhbmNlX2FkZGVkQXNzZXRzCQC5CQIFC2FkZGVkQXNzZXRzAgEsCQDMCAIJAQtTdHJpbmdFbnRyeQICF3JlYmFsYW5jZV9yZW1vdmVkQXNzZXRzCQC5CQIFDXJlbW92ZWRBc3NldHMCASwJAMwIAgkBC1N0cmluZ0VudHJ5AgIVdG1wX3JlYmFsYW5jZUFzc2V0SWRzCQC5CQIFDXRtcEFzc2V0SWRzTGkCASwJAMwIAgkBDEJvb2xlYW5FbnRyeQICFHJlYmFsYW5jZV9pblByb2dyZXNzBgkAzAgCCQEMQm9vbGVhbkVudHJ5AgIYcmViYWxhbmNlX25ld1Rva2Vuc0FkZGVkBQ5uZXdUb2tlbnNBZGRlZAkAzAgCCQEMSW50ZWdlckVudHJ5AgITcmViYWxhbmNlX3N0ZXBzRG9uZQAACQDMCAIJAQxJbnRlZ2VyRW50cnkCAhhyZWJhbGFuY2VfbGFzdFN0ZXBIZWlnaHQFBmhlaWdodAkAzAgCCQEMSW50ZWdlckVudHJ5AgIVcmViYWxhbmNlX3N0ZXBzQW1vdW50BQtzdGVwc0Ftb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgIXcmViYWxhbmNlX3N0ZXBzSW50ZXJ2YWwFDXN0ZXBzSW50ZXJ2YWwJAMwIAgkBC1N0cmluZ0VudHJ5AgIScmViYWxhbmNlX2Fzc2V0SWRzBQthc3NldElkc1N0cgkAzAgCCQELU3RyaW5nRW50cnkCAhhyZWJhbGFuY2VfbmV3QmFzZVRva2VuSWQFDmJhc2VUb2tlbklkU3RyCQDMCAIJAQtTdHJpbmdFbnRyeQICFXJlYmFsYW5jZV9hc3NldERlbHRhcwkAuQkCBQthc3NldERlbHRhcwIBLAUDbmlsBQ5wYXltZW50RW50cmllcwUMc3RvcmVXZWlnaHRzCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBD3N0ZXBSZWJhbGFuY2luZwAEBXJlYklkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUKZ292QWRkcmVzcwkArAICAhVwb29sX2xhc3RSZWJhbGFuY2luZ18JAKUIAQUEdGhpcwIscmViYWxhbmNpbmcgaXMgbm90IHJlZ2lzdGVyZWQgYXQgZ292IGFkZHJlc3MDCQEBIQEJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhpcwIUcmViYWxhbmNlX2luUHJvZ3Jlc3MHCQACAQIabm8gcmViYWxhbmNpbmcgaW4gcHJvZ3Jlc3MDCQECIT0CCQELdmFsdWVPckVsc2UCCQCaCAIFCmdvdkFkZHJlc3MJAKwCAgITcmViYWxhbmNpbmdfc3RhdHVzXwUFcmViSWQAAAACCQACAQIzdGhpcyB0cmFuc2FjdGlvbiBuZWVkcyBhcHByb3ZhbCBmcm9tIHB1enpsZSBuZXR3b3JrBA5sYXN0U3RlcEhlaWdodAkBEUBleHRyTmF0aXZlKDEwNTUpAQIYcmViYWxhbmNlX2xhc3RTdGVwSGVpZ2h0BAxzdGVwSW50ZXJ2YWwJARFAZXh0ck5hdGl2ZSgxMDU1KQECF3JlYmFsYW5jZV9zdGVwc0ludGVydmFsBAlzdGVwc0RvbmUJARFAZXh0ck5hdGl2ZSgxMDU1KQECE3JlYmFsYW5jZV9zdGVwc0RvbmUEDm5leHRTdGVwSGVpZ2h0CQBkAgUObGFzdFN0ZXBIZWlnaHQFDHN0ZXBJbnRlcnZhbAMJAGYCBQ5uZXh0U3RlcEhlaWdodAUGaGVpZ2h0CQACAQIRY2FuJ3QgYmUgZG9uZSB5ZXQEC2Fzc2V0RGVsdGFzCQC1CQIJARFAZXh0ck5hdGl2ZSgxMDU4KQECFXJlYmFsYW5jZV9hc3NldERlbHRhcwIBLAQObmV3QXNzZXRJZHNTdHIJARFAZXh0ck5hdGl2ZSgxMDU4KQECFXRtcF9yZWJhbGFuY2VBc3NldElkcwQLbmV3QXNzZXRJZHMJALUJAgUObmV3QXNzZXRJZHNTdHICASwKAQFmAgVhY2N1bQphc3NldElkU3RyCQDOCAIFBWFjY3VtCQDMCAIJAKQDAQkAbgQJAGQCCQBoAgkBC3ZhbHVlT3JFbHNlAgkAnwgBCQCsAgICFnJlYmFsYW5jZV9zdGFydFdlaWdodF8FCmFzc2V0SWRTdHIAAACQTgkAaAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQthc3NldERlbHRhcwkBBXZhbHVlAQkAzwgCBQtuZXdBc3NldElkcwUKYXNzZXRJZFN0cgkAZAIFCXN0ZXBzRG9uZQABAAEAkE4FBkhBTEZVUAUDbmlsBAluZXdTaGFyZXMJALkJAgoAAiRsBQtuZXdBc3NldElkcwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmNF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEBZgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjRfMgIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgIBLAQObmV3VG9rZW5zQWRkZWQJARFAZXh0ck5hdGl2ZSgxMDU2KQECGHJlYmFsYW5jZV9uZXdUb2tlbnNBZGRlZAQDaW52AwMFDm5ld1Rva2Vuc0FkZGVkCQAAAgUJc3RlcHNEb25lAAAHCQD8BwQFBHRoaXMCGmRvUmViYWxhbmNpbmdXaXRoTmV3VG9rZW5zCQDMCAIFDm5ld0Fzc2V0SWRzU3RyCQDMCAIFCW5ld1NoYXJlcwkAzAgCCQERQGV4dHJOYXRpdmUoMTA1OCkBAhhyZWJhbGFuY2VfbmV3QmFzZVRva2VuSWQFA25pbAUDbmlsCQD8BwQFBHRoaXMCDWRvUmViYWxhbmNpbmcJAMwIAgUJbmV3U2hhcmVzBQNuaWwFA25pbAMJAAACBQNpbnYFA2ludgQMbm90aWZ5SW52b2tlCQD8BwQFD3Bvb2xzSHViQWRkcmVzcwIQbm90aWZ5UG9vbENoYW5nZQUDbmlsBQNuaWwDCQAAAgUMbm90aWZ5SW52b2tlBQxub3RpZnlJbnZva2UECmlzRmluaXNoZWQJAGcCCQBkAgUJc3RlcHNEb25lAAEJARFAZXh0ck5hdGl2ZSgxMDU1KQECFXJlYmFsYW5jZV9zdGVwc0Ftb3VudAQHYWN0aW9ucwkAzAgCCQEMQm9vbGVhbkVudHJ5AgIUcmViYWxhbmNlX2luUHJvZ3Jlc3MJAQEhAQUKaXNGaW5pc2hlZAkAzAgCCQEMSW50ZWdlckVudHJ5AgITcmViYWxhbmNlX3N0ZXBzRG9uZQkAZAIFCXN0ZXBzRG9uZQABCQDMCAIJAQxJbnRlZ2VyRW50cnkCAhhyZWJhbGFuY2VfbGFzdFN0ZXBIZWlnaHQFBmhlaWdodAUDbmlsAwkAAAIFCXN0ZXBzRG9uZQAACQDOCAIFB2FjdGlvbnMJAMwIAgkBC1N0cmluZ0VudHJ5AgIPc3RhdGljX3Rva2VuSWRzBQ5uZXdBc3NldElkc1N0cgUDbmlsAwUKaXNGaW5pc2hlZAQPcmVtb3ZlZEFzc2V0c0xpCQC1CQIJAQx0cnlHZXRTdHJpbmcBAhdyZWJhbGFuY2VfcmVtb3ZlZEFzc2V0cwIBLAoBBnJtRGF0YQIFYWNjdW0HYXNzZXRJZAkAzggCBQVhY2N1bQkAzAgCCQELRGVsZXRlRW50cnkBCQCsAgIJAKwCAgIHc3RhdGljXwUHYXNzZXRJZAIGX3NjYWxlCQDMCAIJAQtEZWxldGVFbnRyeQEJAKwCAgkArAICAgdzdGF0aWNfBQdhc3NldElkAglfZGVjaW1hbHMJAMwIAgkBC0RlbGV0ZUVudHJ5AQkArAICCQCsAgICB3N0YXRpY18FB2Fzc2V0SWQCB193ZWlnaHQJAMwIAgkBC0RlbGV0ZUVudHJ5AQkArAICCQCsAgICB2dsb2JhbF8FB2Fzc2V0SWQCCF9iYWxhbmNlCQDMCAIJAQtEZWxldGVFbnRyeQEJAKwCAgIacmViYWxhbmNlX2F0dGFjaGVkUGF5bWVudF8FB2Fzc2V0SWQFA25pbAQCcm0KAAIkbAUPcmVtb3ZlZEFzc2V0c0xpCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGY1XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQZybURhdGECBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjVfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY1XzICCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECCQEFJGY1XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoEDWFkZGVkQXNzZXRzTGkJALUJAgkBDHRyeUdldFN0cmluZwECFXJlYmFsYW5jZV9hZGRlZEFzc2V0cwIBLAoBEWFkZFJlbW92ZVBheW1lbnRzAgVhY2N1bQdhc3NldElkCQDOCAIFBWFjY3VtCQDMCAIJAQtEZWxldGVFbnRyeQEJAKwCAgIacmViYWxhbmNlX2F0dGFjaGVkUGF5bWVudF8FB2Fzc2V0SWQFA25pbAQKcm1QYXltZW50cwoAAiRsBQ1hZGRlZEFzc2V0c0xpCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGY2XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARFhZGRSZW1vdmVQYXltZW50cwIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNl8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjZfMgIJAQUkZjZfMQIJAQUkZjZfMQIJAQUkZjZfMQIJAQUkZjZfMQIJAQUkZjZfMQIJAQUkZjZfMQIJAQUkZjZfMQIJAQUkZjZfMQIJAQUkZjZfMQIJAQUkZjZfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgQRZmluYWxBc3NldHNJZHNTdHIJAQx0cnlHZXRTdHJpbmcBAhJyZWJhbGFuY2VfYXNzZXRJZHMEEEFzc2V0c1dlaWdodHNTdHIKAAIkbAkAtQkCBRFmaW5hbEFzc2V0c0lkc1N0cgIBLAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmN18xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEXYWRkQXNzZXRXZWlnaHRUb1N0ckxpc3QCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjdfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY3XzICCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoEBm5vdGlmeQkA/AcEBQpnb3ZBZGRyZXNzAhVub3RpZnlSZWJhbGFuY2luZ0RvbmUJAMwIAgUFcmViSWQFA25pbAUDbmlsAwkAAAIFBm5vdGlmeQUGbm90aWZ5CQDOCAIJAM4IAgkAzggCBQdhY3Rpb25zBQJybQUKcm1QYXltZW50cwkAzAgCCQELU3RyaW5nRW50cnkCAg9zdGF0aWNfdG9rZW5JZHMFEWZpbmFsQXNzZXRzSWRzU3RyCQDMCAIJAQtTdHJpbmdFbnRyeQICE3N0YXRpY190b2tlbldlaWdodHMJALkJAgUQQXNzZXRzV2VpZ2h0c1N0cgIBLAkAzAgCCQEMSW50ZWdlckVudHJ5AgITc3RhdGljX3Rva2Vuc0Ftb3VudAkAkAMBCQC1CQIFEWZpbmFsQXNzZXRzSWRzU3RyAgEsBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4EEWZpbmFsQXNzZXRzSWRzU3RyCQEMdHJ5R2V0U3RyaW5nAQIScmViYWxhbmNlX2Fzc2V0SWRzBBBBc3NldHNXZWlnaHRzU3RyCgACJGwJALUJAgURZmluYWxBc3NldHNJZHNTdHICASwKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjVfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBF2FkZEFzc2V0V2VpZ2h0VG9TdHJMaXN0AgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY1XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNV8yAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKCQDOCAIFB2FjdGlvbnMJAMwIAgkBC1N0cmluZ0VudHJ5AgITc3RhdGljX3Rva2VuV2VpZ2h0cwkAuQkCBRBBc3NldHNXZWlnaHRzU3RyAgEsBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQENZG9S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Y2VlZHMgMTAJAQUkZjdfMgIJAQUkZjdfMQIJAQUkZjdfMQIJAQUkZjdfMQIJAQUkZjdfMQIJAQUkZjdfMQIJAQUkZjdfMQIJAQUkZjdfMQIJAQUkZjdfMQIJAQUkZjdfMQIJAQUkZjdfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgQGd2VpZ2h0CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUUbmV3QXNzZXRXZWlnaHRzU3RyTGkFCFRva2VuTnVtBA5iYWxhbmNlSW5TdGF0ZQkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHZ2xvYmFsXwUKYXNzZXRJZFN0cgIIX2JhbGFuY2UEEGJhbGFuY2VJblBheW1lbnQJAJEDAgUQYXR0YWNoZWRCYWxhbmNlcwUIVG9rZW5OdW0EB2JhbGFuY2UJAGQCBQ5iYWxhbmNlSW5TdGF0ZQUQYmFsYW5jZUluUGF5bWVudAQNYXNzZXREZWNpbWFscwMJAAACBQdhc3NldElkBQR1bml0AAgICQEFdmFsdWUBCQDsBwEJAQV2YWx1ZQEFB2Fzc2V0SWQIZGVjaW1hbHMDCQBnAgAABQdiYWxhbmNlCQACAQkArAICAkR5b3UgbmVlZCB0byBhdHRhY2ggYWxsIG5ldyBhc3NldHMgaW4gcGF5bWVudC4gdGhpcyBhc3NldCBpcyBtaXNzZWQ6IAUKYXNzZXRJZFN0cgkAawMFCGN1cnJlbnRLCQBsBgUHYmFsYW5jZQUNYXNzZXREZWNpbWFscwUGd2VpZ2h0BRVBc3NldHNXZWlnaHRzRGVjaW1hbHMACAUFRkxPT1IFBlNjYWxlOAQEbmV3SwoAAiRsBQtuZXdBc3NldElkcwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFDlBvb2xUb2tlblNjYWxlCgEFJGY3XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARJteWx0aXBseUFzc2V0c0ZvcksCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjdfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY3XzICCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoECG5ld0tNdWx0CQBrAwUIb2xkS011bHQFBG5ld0sFBG9sZEsKARNhZGRUb2tlbkRhdGFFbnRyaWVzAgVhY2N1bQhhc3NldE51bQQKYXNzZXRJZFN0cgkAkQMCBRBuZXdBc3NldElkc1N0ckxpBQhhc3NldE51bQQHYXNzZXRJZAkAkQMCBQtuZXdBc3NldElkcwUIYXNzZXROdW0EDWFzc2V0RGVjaW1hbHMDCQAAAgUHYXNzZXRJZAUEdW5pdAAICAkBBXZhbHVlAQkA7AcBCQEFdmFsdWUBBQdhc3NldElkCGRlY2ltYWxzBAxuZXdBc3NldERhdGEDCQECIT0CCQDPCAIFC2FkZGVkQXNzZXRzBQphc3NldElkU3RyBQR1bml0CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgIHZ2xvYmFsXwUKYXNzZXRJZFN0cgIIX2JhbGFuY2UJAJEDAgUQYXR0YWNoZWRCYWxhbmNlcwUIYXNzZXROdW0JAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkArAICAgdzdGF0aWNfBQphc3NldElkU3RyAgZfc2NhbGUJAGwGAAoAAAUNYXNzZXREZWNpbWFscwAAAAAFBERPV04JAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkArAICAgdzdGF0aWNfBQphc3NldElkU3RyAglfZGVjaW1hbHMFDWFzc2V0RGVjaW1hbHMFA25pbAUDbmlsAwkAZwIFCGFzc2V0TnVtCQCQAwEFFG5ld0Fzc2V0V2VpZ2h0c1N0ckxpBQVhY2N1bQkAzggCCQDOCAIFBWFjY3VtCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgIHc3RhdGljXwUKYXNzZXRJZFN0cgIHX3dlaWdodAkBBXZhbHVlAQkAtgkBCQCRAwIFFG5ld0Fzc2V0V2VpZ2h0c1N0ckxpBQhhc3NldE51bQUDbmlsBQxuZXdBc3NldERhdGEJAM4IAgoAAiRsCQDMCAIAAAkAzAgCAAEJAMwIAgACCQDMCAIAAwkAzAgCAAQJAMwIAgAFCQDMCAIABgkAzAgCAAcJAMwIAgAICQDMCAIACQUDbmlsCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGY4XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARNhZGRUb2tlbkRhdGFFbnRyaWVzAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY4XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmOF8yAgkBBSRmOF8xAgkBBSRmOF8xAgkBBSRmOF8xAgkBBSRmOF8xAgkBBSRmOF8xAgkBBSRmOF8xAgkBBSRmOF8xAgkBBSRmOF8xAgkBBSRmOF8xAgkBBSRmOF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKCQDMCAIJAQtTdHJpbmdFbnRyeQICD3N0YXRpY190b2tlbklkcwULYXNzZXRJZHNTdHIJAMwIAgkBC1N0cmluZ0VudHJ5AgIPc3RhdGljX2ZlZVRva2VuBQtmZWVBc3NldFN0cgkAzAgCCQELU3RyaW5nRW50cnkCAhNzdGF0aWNfdG9rZW5XZWlnaHRzBQ9hc3NldFdlaWdodHNTdHIJAMwIAgkBDEludGVnZXJFbnRyeQICE3N0YXRpY190b2tlbnNBbW91bnQJAJADAQULbmV3QXNzZXRJZHMJAMwIAgkBDEludGVnZXJFbnRyeQICDHN0YXRpY19LTXVsdAUIbmV3S011bHQFA25pbAECdHgBBnZlcmlmeQADAwkAAAIJAQt2YWx1ZU9yRWxzZQIJAJ8IAQITZ2xvYmFsX3dhc1ByZUluaXRlZAAAAAADCQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwAACAUCdHgPc2VuZGVyUHVibGljS2V5BgkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAUMbWFzdGVyUHViS2V5BwYEByRtYXRjaDAFAnR4AwkAAQIFByRtYXRjaDACFFNldFNjcmlwdFRyYW5zYWN0aW9uBAJ0eAUHJG1hdGNoMAQKc2NyaXB0RnVsbAkBBXZhbHVlAQgFAnR4BnNjcmlwdAQEaGFzaAkA2AQBCQD3AwEFCnNjcmlwdEZ1bGwDCQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwAABQxtYXN0ZXJQdWJLZXkJAGYCCQELdmFsdWVPckVsc2UCCQCaCAIFEWNvbGRNYXN0ZXJBZGRyZXNzCQCsAgICD2FwcHJvdmVkU2NyaXB0XwUEaGFzaAAABQZoZWlnaHQHAwkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAUMbWFzdGVyUHViS2V5CQBmAgkBC3ZhbHVlT3JFbHNlAgkAmggCBRFjb2xkTWFzdGVyQWRkcmVzcwkArAICAgthcHByb3ZlZFR4XwkA2AQBCAUCdHgCaWQAAAAAB2vb2Ig=", "height": 4141453, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: BBua3PEBgJ9Q6YCV4LW12FX4h1peLaFdtQ5kXGE2BoSP Next: none Diff:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let VERSION = "PZ-1.2.1 PROD"
4+let VERSION = "PZ-1.2.3 PROD"
55
66 let configStr = valueOrElse(getString(this, "configAddress"), "3PPEBRg4s2af2rQ2ZbLvdu1Hfd4Vo6QVDTo")
77
11021102 @Callable(i)
11031103 func setRebalancingPlan (assetIdsStr,assetWeightsStr,baseTokenIdStr,stepsAmount,stepsInterval) = if ((i.caller != addressFromStringValue(tryGetString("static_poolOwner"))))
11041104 then throw("this call available only for pool owner")
1105- else if ((1 > valueOrElse(getInteger(govAddress, ("approvedTx_" + toBase58String(i.transactionId))), 0)))
1106- then throw("this transaction needs approval from puzzle network")
1107- else if (valueOrElse(getBoolean(this, "rebalance_inProgress"), false))
1108- then throw("rebalancing in progress")
1109- else {
1110- let newAssetWeightsStrLi = split(assetWeightsStr, ",")
1111- let newAssetIdsStrLi = split(assetIdsStr, ",")
1112- let feeAssetStr = {
1113- let $l = newAssetIdsStrLi
1114- let $s = size($l)
1115- let $acc0 = ""
1116- func $f4_1 ($a,$i) = if (($i >= $s))
1117- then $a
1118- else checkFeeAsset($a, $l[$i])
1105+ else if (valueOrElse(getBoolean(this, "rebalance_inProgress"), false))
1106+ then throw("rebalancing in progress")
1107+ else {
1108+ let newAssetWeightsStrLi = split(assetWeightsStr, ",")
1109+ let newAssetIdsStrLi = split(assetIdsStr, ",")
1110+ let feeAssetStr = {
1111+ let $l = newAssetIdsStrLi
1112+ let $s = size($l)
1113+ let $acc0 = ""
1114+ func $f4_1 ($a,$i) = if (($i >= $s))
1115+ then $a
1116+ else checkFeeAsset($a, $l[$i])
11191117
1120- func $f4_2 ($a,$i) = if (($i >= $s))
1121- then $a
1122- else throw("List size exceeds 10")
1118+ func $f4_2 ($a,$i) = if (($i >= $s))
1119+ then $a
1120+ else throw("List size exceeds 10")
11231121
1124- $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)
1125- }
1126- let assetWeightsSum = {
1127- let $l = newAssetWeightsStrLi
1128- let $s = size($l)
1129- let $acc0 = 0
1130- func $f5_1 ($a,$i) = if (($i >= $s))
1131- then $a
1132- else sum($a, $l[$i])
1122+ $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)
1123+ }
1124+ let assetWeightsSum = {
1125+ let $l = newAssetWeightsStrLi
1126+ let $s = size($l)
1127+ let $acc0 = 0
1128+ func $f5_1 ($a,$i) = if (($i >= $s))
1129+ then $a
1130+ else sum($a, $l[$i])
11331131
1134- func $f5_2 ($a,$i) = if (($i >= $s))
1135- then $a
1136- else throw("List size exceeds 10")
1132+ func $f5_2 ($a,$i) = if (($i >= $s))
1133+ then $a
1134+ else throw("List size exceeds 10")
11371135
1138- $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)
1139- }
1140- let oldAssetIds = getStringValue("static_tokenIds")
1141- let oldAssetIdsLi = split(oldAssetIds, ",")
1142- func findAdded (accum,next) = if ((indexOf(oldAssetIdsLi, next) == unit))
1143- then (accum ++ [next])
1144- else accum
1136+ $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)
1137+ }
1138+ let oldAssetIds = getStringValue("static_tokenIds")
1139+ let oldAssetIdsLi = split(oldAssetIds, ",")
1140+ func findAdded (accum,next) = if ((indexOf(oldAssetIdsLi, next) == unit))
1141+ then (accum ++ [next])
1142+ else accum
11451143
1146- func findRemoved (accum,next) = if ((indexOf(newAssetIdsStrLi, next) == unit))
1147- then (accum ++ [next])
1148- else accum
1144+ func findRemoved (accum,next) = if ((indexOf(newAssetIdsStrLi, next) == unit))
1145+ then (accum ++ [next])
1146+ else accum
11491147
1150- let addedAssets = {
1151- let $l = newAssetIdsStrLi
1152- let $s = size($l)
1153- let $acc0 = nil
1154- func $f6_1 ($a,$i) = if (($i >= $s))
1155- then $a
1156- else findAdded($a, $l[$i])
1148+ let addedAssets = {
1149+ let $l = newAssetIdsStrLi
1150+ let $s = size($l)
1151+ let $acc0 = nil
1152+ func $f6_1 ($a,$i) = if (($i >= $s))
1153+ then $a
1154+ else findAdded($a, $l[$i])
11571155
1158- func $f6_2 ($a,$i) = if (($i >= $s))
1159- then $a
1160- else throw("List size exceeds 10")
1156+ func $f6_2 ($a,$i) = if (($i >= $s))
1157+ then $a
1158+ else throw("List size exceeds 10")
11611159
1162- $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)
1163- }
1164- let removedAssets = {
1165- let $l = oldAssetIdsLi
1166- let $s = size($l)
1167- let $acc0 = nil
1168- func $f7_1 ($a,$i) = if (($i >= $s))
1169- then $a
1170- else findRemoved($a, $l[$i])
1160+ $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)
1161+ }
1162+ let removedAssets = {
1163+ let $l = oldAssetIdsLi
1164+ let $s = size($l)
1165+ let $acc0 = nil
1166+ func $f7_1 ($a,$i) = if (($i >= $s))
1167+ then $a
1168+ else findRemoved($a, $l[$i])
11711169
1172- func $f7_2 ($a,$i) = if (($i >= $s))
1173- then $a
1174- else throw("List size exceeds 10")
1170+ func $f7_2 ($a,$i) = if (($i >= $s))
1171+ then $a
1172+ else throw("List size exceeds 10")
11751173
1176- $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)
1177- }
1178- let validPayments = validatePayments(addedAssets, i.payments)
1179- let validWeights = validateWeights(newAssetWeightsStrLi)
1180- if ((validWeights == validWeights))
1181- then if ((validPayments != (size(addedAssets) + size(i.payments))))
1182- then throw("Payments not present or something wrong with them")
1183- else if ((size(newAssetIdsStrLi) != size(newAssetWeightsStrLi)))
1184- then throw("assetIds and assetWeights should have same length")
1185- else if ((validPayments != (size(addedAssets) + size(i.payments))))
1186- then throw("Payments not present or something wrong with them")
1187- else if ((feeAssetStr == ""))
1188- then throw("pool must have one of the supported fee assets in the composition")
1189- else if ((indexOf(newAssetIdsStrLi, baseTokenIdStr) == unit))
1190- then throw("baseTokenId should be present in assetIds")
1191- else if (if ((MIN_STEPS_AMOUNT > stepsAmount))
1174+ $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)
1175+ }
1176+ let validPayments = validatePayments(addedAssets, i.payments)
1177+ let validWeights = validateWeights(newAssetWeightsStrLi)
1178+ if ((validWeights == validWeights))
1179+ then if ((validPayments != (size(addedAssets) + size(i.payments))))
1180+ then throw("Payments not present or something wrong with them")
1181+ else if ((size(newAssetIdsStrLi) != size(newAssetWeightsStrLi)))
1182+ then throw("assetIds and assetWeights should have same length")
1183+ else if ((validPayments != (size(addedAssets) + size(i.payments))))
1184+ then throw("Payments not present or something wrong with them")
1185+ else if ((feeAssetStr == ""))
1186+ then throw("pool must have one of the supported fee assets in the composition")
1187+ else if ((indexOf(newAssetIdsStrLi, baseTokenIdStr) == unit))
1188+ then throw("baseTokenId should be present in assetIds")
1189+ else if (if ((MIN_STEPS_AMOUNT > stepsAmount))
1190+ then true
1191+ else (stepsAmount > MAX_STEPS_AMOUNT))
1192+ then throw(((((("Steps amount should be between " + toString(MIN_STEPS_AMOUNT)) + " and ") + toString(MAX_STEPS_AMOUNT)) + ", current: ") + toString(stepsAmount)))
1193+ else if (if ((MIN_STEPS_INTERVAL > stepsInterval))
11921194 then true
1193- else (stepsAmount > MAX_STEPS_AMOUNT))
1194- then throw(((((("Steps amount should be between " + toString(MIN_STEPS_AMOUNT)) + " and ") + toString(MAX_STEPS_AMOUNT)) + ", current: ") + toString(stepsAmount)))
1195- else if (if ((MIN_STEPS_INTERVAL > stepsInterval))
1196- then true
1197- else (stepsInterval > MAX_STEPS_INTERVAL))
1198- then throw(((((("Steps interval should be between " + toString(MIN_STEPS_INTERVAL)) + " and ") + toString(MAX_STEPS_INTERVAL)) + ", current: ") + toString(stepsInterval)))
1199- else if ((assetWeightsSum != 10000))
1200- then throw(("sum of token weights must be equal to 10000, current: " + toString(assetWeightsSum)))
1201- else {
1202- func f (accum,assetIdStr) = {
1203- let oldWeight = tryGetInteger((("static_" + assetIdStr) + "_weight"))
1204- let newWeight = if ((indexOf(newAssetIdsStrLi, assetIdStr) == unit))
1205- then 0
1206- else parseIntValue(value(newAssetWeightsStrLi[value(indexOf(newAssetIdsStrLi, assetIdStr))]))
1207- let deltaPerStep = fraction((newWeight - oldWeight), 10000, stepsAmount)
1208- (accum ++ [toString(deltaPerStep)])
1209- }
1195+ else (stepsInterval > MAX_STEPS_INTERVAL))
1196+ then throw(((((("Steps interval should be between " + toString(MIN_STEPS_INTERVAL)) + " and ") + toString(MAX_STEPS_INTERVAL)) + ", current: ") + toString(stepsInterval)))
1197+ else if ((assetWeightsSum != 10000))
1198+ then throw(("sum of token weights must be equal to 10000, current: " + toString(assetWeightsSum)))
1199+ else {
1200+ func f (accum,assetIdStr) = {
1201+ let oldWeight = tryGetInteger((("static_" + assetIdStr) + "_weight"))
1202+ let newWeight = if ((indexOf(newAssetIdsStrLi, assetIdStr) == unit))
1203+ then 0
1204+ else parseIntValue(value(newAssetWeightsStrLi[value(indexOf(newAssetIdsStrLi, assetIdStr))]))
1205+ let deltaPerStep = fraction((newWeight - oldWeight), 10000, stepsAmount)
1206+ (accum ++ [toString(deltaPerStep)])
1207+ }
12101208
1211- let tmpAssetIdsLi = getTmpRebalanceIds(newAssetIdsStrLi)
1212- let assetDeltas = {
1213- let $l = tmpAssetIdsLi
1214- let $s = size($l)
1215- let $acc0 = nil
1216- func $f8_1 ($a,$i) = if (($i >= $s))
1217- then $a
1218- else f($a, $l[$i])
1209+ let tmpAssetIdsLi = getTmpRebalanceIds(newAssetIdsStrLi)
1210+ let assetDeltas = {
1211+ let $l = tmpAssetIdsLi
1212+ let $s = size($l)
1213+ let $acc0 = nil
1214+ func $f8_1 ($a,$i) = if (($i >= $s))
1215+ then $a
1216+ else f($a, $l[$i])
12191217
1220- func $f8_2 ($a,$i) = if (($i >= $s))
1221- then $a
1222- else throw("List size exceeds 10")
1218+ func $f8_2 ($a,$i) = if (($i >= $s))
1219+ then $a
1220+ else throw("List size exceeds 10")
12231221
1224- $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)
1225- }
1226- let newTokensAdded = (checkTokensChange(newAssetIdsStrLi) > 0)
1227- func recordAssetPayment (accum,next) = (accum ++ [IntegerEntry(("rebalance_attachedPayment_" + getAssetString(next.assetId)), next.amount)])
1222+ $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)
1223+ }
1224+ let newTokensAdded = (checkTokensChange(newAssetIdsStrLi) > 0)
1225+ func recordAssetPayment (accum,next) = (accum ++ [IntegerEntry(("rebalance_attachedPayment_" + getAssetString(next.assetId)), next.amount)])
12281226
1229- let paymentEntries = {
1230- let $l = i.payments
1231- let $s = size($l)
1232- let $acc0 = nil
1233- func $f9_1 ($a,$i) = if (($i >= $s))
1234- then $a
1235- else recordAssetPayment($a, $l[$i])
1227+ let paymentEntries = {
1228+ let $l = i.payments
1229+ let $s = size($l)
1230+ let $acc0 = nil
1231+ func $f9_1 ($a,$i) = if (($i >= $s))
1232+ then $a
1233+ else recordAssetPayment($a, $l[$i])
12361234
1237- func $f9_2 ($a,$i) = if (($i >= $s))
1238- then $a
1239- else throw("List size exceeds 10")
1235+ func $f9_2 ($a,$i) = if (($i >= $s))
1236+ then $a
1237+ else throw("List size exceeds 10")
12401238
1241- $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)
1242- }
1243- let storeWeights = saveCurrentWeights()
1244- let notifyInvoke = invoke(poolsHubAddress, "notifyPoolChange", nil, nil)
1245- if ((notifyInvoke == notifyInvoke))
1246- 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)
1247- else throw("Strict value is not equal to itself.")
1239+ $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)
12481240 }
1249- else throw("Strict value is not equal to itself.")
1250- }
1241+ let storeWeights = saveCurrentWeights()
1242+ let requestGovInvoke = invoke(govAddress, "requestRebalancing", [toBase58String(i.transactionId)], nil)
1243+ if ((requestGovInvoke == requestGovInvoke))
1244+ 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)
1245+ else throw("Strict value is not equal to itself.")
1246+ }
1247+ else throw("Strict value is not equal to itself.")
1248+ }
12511249
12521250
12531251
12541252 @Callable(i)
1255-func stepRebalancing () = if (!(valueOrElse(getBoolean(this, "rebalance_inProgress"), false)))
1256- then throw("no rebalancing in progress")
1257- else {
1258- let lastStepHeight = getIntegerValue("rebalance_lastStepHeight")
1259- let stepInterval = getIntegerValue("rebalance_stepsInterval")
1260- let stepsDone = getIntegerValue("rebalance_stepsDone")
1261- let nextStepHeight = (lastStepHeight + stepInterval)
1262- if ((nextStepHeight > height))
1263- then throw("can't be done yet")
1253+func stepRebalancing () = {
1254+ let rebId = valueOrErrorMessage(getString(govAddress, ("pool_lastRebalancing_" + toString(this))), "rebalancing is not registered at gov address")
1255+ if (!(valueOrElse(getBoolean(this, "rebalance_inProgress"), false)))
1256+ then throw("no rebalancing in progress")
1257+ else if ((valueOrElse(getInteger(govAddress, ("rebalancing_status_" + rebId)), 0) != 2))
1258+ then throw("this transaction needs approval from puzzle network")
12641259 else {
1265- let assetDeltas = split(getStringValue("rebalance_assetDeltas"), ",")
1266- let newAssetIdsStr = getStringValue("tmp_rebalanceAssetIds")
1267- let newAssetIds = split(newAssetIdsStr, ",")
1268- 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))])
1260+ let lastStepHeight = getIntegerValue("rebalance_lastStepHeight")
1261+ let stepInterval = getIntegerValue("rebalance_stepsInterval")
1262+ let stepsDone = getIntegerValue("rebalance_stepsDone")
1263+ let nextStepHeight = (lastStepHeight + stepInterval)
1264+ if ((nextStepHeight > height))
1265+ then throw("can't be done yet")
1266+ else {
1267+ let assetDeltas = split(getStringValue("rebalance_assetDeltas"), ",")
1268+ let newAssetIdsStr = getStringValue("tmp_rebalanceAssetIds")
1269+ let newAssetIds = split(newAssetIdsStr, ",")
1270+ 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))])
12691271
1270- let newShares = makeString({
1271- let $l = newAssetIds
1272- let $s = size($l)
1273- let $acc0 = nil
1274- func $f4_1 ($a,$i) = if (($i >= $s))
1275- then $a
1276- else f($a, $l[$i])
1272+ let newShares = makeString({
1273+ let $l = newAssetIds
1274+ let $s = size($l)
1275+ let $acc0 = nil
1276+ func $f4_1 ($a,$i) = if (($i >= $s))
1277+ then $a
1278+ else f($a, $l[$i])
12771279
1278- func $f4_2 ($a,$i) = if (($i >= $s))
1279- then $a
1280- else throw("List size exceeds 10")
1280+ func $f4_2 ($a,$i) = if (($i >= $s))
1281+ then $a
1282+ else throw("List size exceeds 10")
12811283
1282- $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)
1283- }, ",")
1284- let newTokensAdded = getBooleanValue("rebalance_newTokensAdded")
1285- let inv = if (if (newTokensAdded)
1286- then (stepsDone == 0)
1287- else false)
1288- then invoke(this, "doRebalancingWithNewTokens", [newAssetIdsStr, newShares, getStringValue("rebalance_newBaseTokenId")], nil)
1289- else invoke(this, "doRebalancing", [newShares], nil)
1290- if ((inv == inv))
1291- then {
1292- let notifyInvoke = invoke(poolsHubAddress, "notifyPoolChange", nil, nil)
1293- if ((notifyInvoke == notifyInvoke))
1284+ $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)
1285+ }, ",")
1286+ let newTokensAdded = getBooleanValue("rebalance_newTokensAdded")
1287+ let inv = if (if (newTokensAdded)
1288+ then (stepsDone == 0)
1289+ else false)
1290+ then invoke(this, "doRebalancingWithNewTokens", [newAssetIdsStr, newShares, getStringValue("rebalance_newBaseTokenId")], nil)
1291+ else invoke(this, "doRebalancing", [newShares], nil)
1292+ if ((inv == inv))
12941293 then {
1295- let isFinished = ((stepsDone + 1) >= getIntegerValue("rebalance_stepsAmount"))
1296- let actions = [BooleanEntry("rebalance_inProgress", !(isFinished)), IntegerEntry("rebalance_stepsDone", (stepsDone + 1)), IntegerEntry("rebalance_lastStepHeight", height)]
1297- if ((stepsDone == 0))
1298- then (actions ++ [StringEntry("static_tokenIds", newAssetIdsStr)])
1299- else if (isFinished)
1300- then {
1301- let removedAssetsLi = split(tryGetString("rebalance_removedAssets"), ",")
1302- 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))])
1294+ let notifyInvoke = invoke(poolsHubAddress, "notifyPoolChange", nil, nil)
1295+ if ((notifyInvoke == notifyInvoke))
1296+ then {
1297+ let isFinished = ((stepsDone + 1) >= getIntegerValue("rebalance_stepsAmount"))
1298+ let actions = [BooleanEntry("rebalance_inProgress", !(isFinished)), IntegerEntry("rebalance_stepsDone", (stepsDone + 1)), IntegerEntry("rebalance_lastStepHeight", height)]
1299+ if ((stepsDone == 0))
1300+ then (actions ++ [StringEntry("static_tokenIds", newAssetIdsStr)])
1301+ else if (isFinished)
1302+ then {
1303+ let removedAssetsLi = split(tryGetString("rebalance_removedAssets"), ",")
1304+ 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))])
13031305
1304- let rm = {
1305- let $l = removedAssetsLi
1306- let $s = size($l)
1307- let $acc0 = nil
1308- func $f5_1 ($a,$i) = if (($i >= $s))
1309- then $a
1310- else rmData($a, $l[$i])
1306+ let rm = {
1307+ let $l = removedAssetsLi
1308+ let $s = size($l)
1309+ let $acc0 = nil
1310+ func $f5_1 ($a,$i) = if (($i >= $s))
1311+ then $a
1312+ else rmData($a, $l[$i])
13111313
1312- func $f5_2 ($a,$i) = if (($i >= $s))
1313- then $a
1314- else throw("List size exceeds 10")
1314+ func $f5_2 ($a,$i) = if (($i >= $s))
1315+ then $a
1316+ else throw("List size exceeds 10")
13151317
1316- $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)
1317- }
1318- let addedAssetsLi = split(tryGetString("rebalance_addedAssets"), ",")
1319- func addRemovePayments (accum,assetId) = (accum ++ [DeleteEntry(("rebalance_attachedPayment_" + assetId))])
1318+ $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)
1319+ }
1320+ let addedAssetsLi = split(tryGetString("rebalance_addedAssets"), ",")
1321+ func addRemovePayments (accum,assetId) = (accum ++ [DeleteEntry(("rebalance_attachedPayment_" + assetId))])
13201322
1321- let rmPayments = {
1322- let $l = addedAssetsLi
1323- let $s = size($l)
1324- let $acc0 = nil
1325- func $f6_1 ($a,$i) = if (($i >= $s))
1326- then $a
1327- else addRemovePayments($a, $l[$i])
1323+ let rmPayments = {
1324+ let $l = addedAssetsLi
1325+ let $s = size($l)
1326+ let $acc0 = nil
1327+ func $f6_1 ($a,$i) = if (($i >= $s))
1328+ then $a
1329+ else addRemovePayments($a, $l[$i])
13281330
1329- func $f6_2 ($a,$i) = if (($i >= $s))
1330- then $a
1331- else throw("List size exceeds 10")
1331+ func $f6_2 ($a,$i) = if (($i >= $s))
1332+ then $a
1333+ else throw("List size exceeds 10")
13321334
1333- $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)
1334- }
1335- let finalAssetsIdsStr = tryGetString("rebalance_assetIds")
1336- let AssetsWeightsStr = {
1337- let $l = split(finalAssetsIdsStr, ",")
1338- let $s = size($l)
1339- let $acc0 = nil
1340- func $f7_1 ($a,$i) = if (($i >= $s))
1341- then $a
1342- else addAssetWeightToStrList($a, $l[$i])
1335+ $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)
1336+ }
1337+ let finalAssetsIdsStr = tryGetString("rebalance_assetIds")
1338+ let AssetsWeightsStr = {
1339+ let $l = split(finalAssetsIdsStr, ",")
1340+ let $s = size($l)
1341+ let $acc0 = nil
1342+ func $f7_1 ($a,$i) = if (($i >= $s))
1343+ then $a
1344+ else addAssetWeightToStrList($a, $l[$i])
13431345
1344- func $f7_2 ($a,$i) = if (($i >= $s))
1345- then $a
1346- else throw("List size exceeds 10")
1346+ func $f7_2 ($a,$i) = if (($i >= $s))
1347+ then $a
1348+ else throw("List size exceeds 10")
13471349
1348- $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)
1349- }
1350- (((actions ++ rm) ++ rmPayments) ++ [StringEntry("static_tokenIds", finalAssetsIdsStr), StringEntry("static_tokenWeights", makeString(AssetsWeightsStr, ",")), IntegerEntry("static_tokensAmount", size(split(finalAssetsIdsStr, ",")))])
1351- }
1352- else {
1353- let finalAssetsIdsStr = tryGetString("rebalance_assetIds")
1354- let AssetsWeightsStr = {
1355- let $l = split(finalAssetsIdsStr, ",")
1356- let $s = size($l)
1357- let $acc0 = nil
1358- func $f5_1 ($a,$i) = if (($i >= $s))
1359- then $a
1360- else addAssetWeightToStrList($a, $l[$i])
1350+ $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)
1351+ }
1352+ let notify = invoke(govAddress, "notifyRebalancingDone", [rebId], nil)
1353+ if ((notify == notify))
1354+ then (((actions ++ rm) ++ rmPayments) ++ [StringEntry("static_tokenIds", finalAssetsIdsStr), StringEntry("static_tokenWeights", makeString(AssetsWeightsStr, ",")), IntegerEntry("static_tokensAmount", size(split(finalAssetsIdsStr, ",")))])
1355+ else throw("Strict value is not equal to itself.")
1356+ }
1357+ else {
1358+ let finalAssetsIdsStr = tryGetString("rebalance_assetIds")
1359+ let AssetsWeightsStr = {
1360+ let $l = split(finalAssetsIdsStr, ",")
1361+ let $s = size($l)
1362+ let $acc0 = nil
1363+ func $f5_1 ($a,$i) = if (($i >= $s))
1364+ then $a
1365+ else addAssetWeightToStrList($a, $l[$i])
13611366
1362- func $f5_2 ($a,$i) = if (($i >= $s))
1363- then $a
1364- else throw("List size exceeds 10")
1367+ func $f5_2 ($a,$i) = if (($i >= $s))
1368+ then $a
1369+ else throw("List size exceeds 10")
13651370
1366- $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)
1367- }
1368- (actions ++ [StringEntry("static_tokenWeights", makeString(AssetsWeightsStr, ","))])
1369- }
1371+ $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)
1372+ }
1373+ (actions ++ [StringEntry("static_tokenWeights", makeString(AssetsWeightsStr, ","))])
1374+ }
1375+ }
1376+ else throw("Strict value is not equal to itself.")
13701377 }
13711378 else throw("Strict value is not equal to itself.")
13721379 }
1373- else throw("Strict value is not equal to itself.")
13741380 }
1375- }
1381+ }
13761382
13771383
13781384
16121618
16131619
16141620 @Verifier(tx)
1615-func verify () = if ((valueOrElse(getInteger("global_wasPreInited"), 0) == 0))
1616- then sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
1621+func verify () = if (if ((valueOrElse(getInteger("global_wasPreInited"), 0) == 0))
1622+ then if (sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey))
1623+ then true
1624+ else sigVerify(tx.bodyBytes, tx.proofs[0], masterPubKey)
1625+ else false)
1626+ then true
16171627 else match tx {
16181628 case tx: SetScriptTransaction =>
16191629 let scriptFull = value(tx.script)
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let VERSION = "PZ-1.2.1 PROD"
4+let VERSION = "PZ-1.2.3 PROD"
55
66 let configStr = valueOrElse(getString(this, "configAddress"), "3PPEBRg4s2af2rQ2ZbLvdu1Hfd4Vo6QVDTo")
77
88 let CONFIG_ADDRESS = if ((configStr == ""))
99 then this
1010 else Address(fromBase58String(configStr))
1111
1212 let AssetsWeightsDecimals = 4
1313
1414 let Scale = 10000
1515
1616 let Scale8 = 100000000
1717
1818 let Scale16 = 10000000000000000
1919
2020 let FeeScale = 10000
2121
2222 let PoolTokenDecimals = 8
2323
2424 let PoolTokenScale = pow(10, 0, PoolTokenDecimals, 0, 0, HALFUP)
2525
2626 let MIN_STEPS_AMOUNT = valueOrElse(getInteger(CONFIG_ADDRESS, "min_steps_amount"), 1)
2727
2828 let MAX_STEPS_AMOUNT = valueOrElse(getInteger(CONFIG_ADDRESS, "max_steps_amount"), 500)
2929
3030 let MIN_STEPS_INTERVAL = valueOrElse(getInteger(CONFIG_ADDRESS, "min_steps_interval"), 1)
3131
3232 let MAX_STEPS_INTERVAL = valueOrElse(getInteger(CONFIG_ADDRESS, "max_steps_interval"), 10000)
3333
3434 let MIN_WEIGHT = valueOrElse(getInteger(CONFIG_ADDRESS, "min_weight"), 100)
3535
3636 let MAX_WEIGHT = valueOrElse(getInteger(CONFIG_ADDRESS, "max_weight"), 9900)
3737
3838 func tryGetInteger (key) = match getInteger(this, key) {
3939 case b: Int =>
4040 b
4141 case _ =>
4242 0
4343 }
4444
4545
4646 func tryGetBinary (key) = match getBinary(this, key) {
4747 case b: ByteVector =>
4848 b
4949 case _ =>
5050 base58''
5151 }
5252
5353
5454 func tryGetString (key) = match getString(this, key) {
5555 case b: String =>
5656 b
5757 case _ =>
5858 ""
5959 }
6060
6161
6262 func tryGetStringOrThrow (key) = match getString(this, key) {
6363 case b: String =>
6464 b
6565 case _ =>
6666 throw(("no such key in data storage: " + key))
6767 }
6868
6969
7070 func getAssetString (assetId) = match assetId {
7171 case b: ByteVector =>
7272 toBase58String(b)
7373 case _ =>
7474 "WAVES"
7575 }
7676
7777
7878 func getAssetBytes (assetIdStr) = if ((assetIdStr == "WAVES"))
7979 then unit
8080 else fromBase58String(assetIdStr)
8181
8282
8383 func getTokenBalance (assetId) = match assetId {
8484 case t: ByteVector =>
8585 assetBalance(this, t)
8686 case _ =>
8787 wavesBalance(this).available
8888 }
8989
9090
9191 func addAssetBytesToList (accum,item) = (accum ++ [getAssetBytes(item)])
9292
9393
9494 func addAssetWeightToList (accum,item) = (accum ++ [tryGetInteger((("static_" + getAssetString(item)) + "_weight"))])
9595
9696
9797 func addAssetWeightToStrList (accum,item) = (accum ++ [toString(tryGetInteger((("static_" + item) + "_weight")))])
9898
9999
100100 func addAssetDecimalsToList (accum,item) = (accum ++ [tryGetInteger((("static_" + getAssetString(item)) + "_decimals"))])
101101
102102
103103 func addAssetScaleToList (accum,item) = (accum ++ [tryGetInteger((("static_" + getAssetString(item)) + "_scale"))])
104104
105105
106106 func addIntToList (accum,item) = (accum ++ [parseIntValue(item)])
107107
108108
109109 let usdnAssetIdStr = valueOrElse(getString(CONFIG_ADDRESS, "usdnAssetIdStr"), "DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p")
110110
111111 let puzzleAssetIdStr = valueOrElse(getString(CONFIG_ADDRESS, "puzzleAssetIdStr"), "HEB8Qaw9xrWpWs8tHsiATYGBWDBtP2S7kcPALrMu43AS")
112112
113113 let usdtAssetIdStr = valueOrElse(getString(CONFIG_ADDRESS, "usdtAssetIdStr"), "34N9YcEETLWn93qYQ64EsP1x89tSruJU44RrEMSXXEPJ")
114114
115115 let usdtPptAssetIdStr = valueOrElse(getString(CONFIG_ADDRESS, "usdtPptAssetIdStr"), "9wc3LXNA4TEBsXyKtoLE9mrbDD7WMHXvXrCjZvabLAsi")
116116
117117 let romeAssetIdStr = valueOrElse(getString(CONFIG_ADDRESS, "romeAssetIdStr"), "AP4Cb5xLYGH6ZigHreCZHoXpQTWDkPsG2BHqfDUx6taJ")
118118
119119 let wavesAssetIdStr = "WAVES"
120120
121121 let usdnAssetId = fromBase58String(usdnAssetIdStr)
122122
123123 let puzzleAssetId = fromBase58String(puzzleAssetIdStr)
124124
125125 let usdtAssetId = fromBase58String(usdtAssetIdStr)
126126
127127 let usdtPptAssetId = fromBase58String(usdtPptAssetIdStr)
128128
129129 let romeAssetId = fromBase58String(romeAssetIdStr)
130130
131131 let wavesAssetId = unit
132132
133133 let supportedFeeAssetsStr = [usdnAssetIdStr, puzzleAssetIdStr, usdtAssetIdStr, usdtPptAssetIdStr, wavesAssetIdStr, romeAssetIdStr]
134134
135135 let parentPoolAddress = Address(fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "parentPoolAddress"), "3PFDgzu1UtswAkCMxqqQjbTeHaX4cMab8Kh")))
136136
137137 let masterAddress = Address(fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "masterAddress"), "3PLjwHcz9NEuaTo63NZR9B9okQiKQxZSbmf")))
138138
139139 let masterPubKey = fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "masterPubKey"), "4z8CKSYQBKkzx7PBb5uBP1YPa6YAHRNTApW1sQVHT5eU"))
140140
141141 let oracleAddress = Address(fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "oracleAddress"), "3P8d1E1BLKoD52y3bQJ1bDTd2TD1gpaLn9t")))
142142
143143 let stakingAddress = Address(fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "stakingAddress"), "3PFTbywqxtFfukX3HyT881g4iW5K4QL3FAS")))
144144
145145 let feesAddress = Address(fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "feesAddress"), "3PFWAVKmXjfHXyzJb12jCbhP4Uhi9t4uWiD")))
146146
147147 let poolsHubAddress = Address(fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "poolsHubAddress"), "3P5YutjDNC3hABBVsveFuZTTbQ5PdtSDBgk")))
148148
149149 let shutdownAddressStr = valueOrElse(getString(CONFIG_ADDRESS, "shutdownAddress"), "3PEpv9hRFWEEBU22WRnLsw1bH4YGtcU728o")
150150
151151 let layer2Addresses = valueOrElse(getString(CONFIG_ADDRESS, "layer2Addresses"), "3PR1Qvi9mHT35SwWEkLSqqE2L8thiPLdVWU,3PQoBfUKHkJAeGWhooLP7WS8ovb54av9Jp2")
152152
153153 let govAddress = Address(fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "govAddress"), "3P6uro9xCsE8te78QZjzqy7aq8natSzdceC")))
154154
155155 let coldMasterAddress = Address(fromBase58String(valueOrElse(getString(CONFIG_ADDRESS, "coldMasterAddress"), "3PK9nhPfPbMBygB9ZgHVMHaQbSoojwrBfxj")))
156156
157157 let T = tryGetInteger("static_tokensAmount")
158158
159159 let assetIds = {
160160 let $l = split(tryGetString("static_tokenIds"), ",")
161161 let $s = size($l)
162162 let $acc0 = nil
163163 func $f0_1 ($a,$i) = if (($i >= $s))
164164 then $a
165165 else addAssetBytesToList($a, $l[$i])
166166
167167 func $f0_2 ($a,$i) = if (($i >= $s))
168168 then $a
169169 else throw("List size exceeds 10")
170170
171171 $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)
172172 }
173173
174174 let AssetsWeights = {
175175 let $l = assetIds
176176 let $s = size($l)
177177 let $acc0 = nil
178178 func $f1_1 ($a,$i) = if (($i >= $s))
179179 then $a
180180 else addAssetWeightToList($a, $l[$i])
181181
182182 func $f1_2 ($a,$i) = if (($i >= $s))
183183 then $a
184184 else throw("List size exceeds 10")
185185
186186 $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)
187187 }
188188
189189 let Decimals = {
190190 let $l = assetIds
191191 let $s = size($l)
192192 let $acc0 = nil
193193 func $f2_1 ($a,$i) = if (($i >= $s))
194194 then $a
195195 else addAssetDecimalsToList($a, $l[$i])
196196
197197 func $f2_2 ($a,$i) = if (($i >= $s))
198198 then $a
199199 else throw("List size exceeds 10")
200200
201201 $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)
202202 }
203203
204204 let Scales = {
205205 let $l = assetIds
206206 let $s = size($l)
207207 let $acc0 = nil
208208 func $f3_1 ($a,$i) = if (($i >= $s))
209209 then $a
210210 else addAssetScaleToList($a, $l[$i])
211211
212212 func $f3_2 ($a,$i) = if (($i >= $s))
213213 then $a
214214 else throw("List size exceeds 10")
215215
216216 $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)
217217 }
218218
219219 let Fee = tryGetInteger("static_fee")
220220
221221 let earnedAssets = assetIds
222222
223223 func isShutdown () = {
224224 let shutdownAddress = addressFromString(shutdownAddressStr)
225225 if ((shutdownAddress == unit))
226226 then false
227227 else match getBoolean(value(shutdownAddress), "is_shutdown") {
228228 case x: Boolean =>
229229 x
230230 case _ =>
231231 false
232232 }
233233 }
234234
235235
236236 func getCurrentTokenBalance (tokenNum) = {
237237 let tokenIdStr = getAssetString(assetIds[tokenNum])
238238 tryGetInteger((("global_" + tokenIdStr) + "_balance"))
239239 }
240240
241241
242242 func getKMult () = match getInteger("static_KMult") {
243243 case x: Int =>
244244 x
245245 case _ =>
246246 Scale16
247247 }
248248
249249
250250 func saveCurrentWeights () = {
251251 let assetIdsLi = split(tryGetString("static_tokenIds"), ",")
252252 func s (accum,assetId) = (accum ++ [IntegerEntry(("rebalance_startWeight_" + assetId), tryGetInteger((("static_" + assetId) + "_weight")))])
253253
254254 let $l = assetIdsLi
255255 let $s = size($l)
256256 let $acc0 = nil
257257 func $f4_1 ($a,$i) = if (($i >= $s))
258258 then $a
259259 else s($a, $l[$i])
260260
261261 func $f4_2 ($a,$i) = if (($i >= $s))
262262 then $a
263263 else throw("List size exceeds 10")
264264
265265 $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)
266266 }
267267
268268
269269 func getVirtualPoolTokenAmount () = fraction(tryGetInteger("global_poolToken_amount"), getKMult(), Scale16)
270270
271271
272272 func calculatePIssued (amount,tokenId) = {
273273 let Psupply = getVirtualPoolTokenAmount()
274274 let Balance = tryGetInteger((("global_" + getAssetString(tokenId)) + "_balance"))
275275 let t1 = fraction(amount, Psupply, Balance, DOWN)
276276 t1
277277 }
278278
279279
280280 func getMinPIssued (payments) = {
281281 func handler (accum,current) = {
282282 let PIssued = calculatePIssued(current.amount, current.assetId)
283283 if ((PIssued == 0))
284284 then throw("one of the tokens amounts is too low")
285285 else if (if ((accum == 0))
286286 then true
287287 else (accum > PIssued))
288288 then PIssued
289289 else accum
290290 }
291291
292292 let minPIssed = {
293293 let $l = payments
294294 let $s = size($l)
295295 let $acc0 = 0
296296 func $f4_1 ($a,$i) = if (($i >= $s))
297297 then $a
298298 else handler($a, $l[$i])
299299
300300 func $f4_2 ($a,$i) = if (($i >= $s))
301301 then $a
302302 else throw("List size exceeds 10")
303303
304304 $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)
305305 }
306306 minPIssed
307307 }
308308
309309
310310 func calculateUsdnValue (assetId,amount,aBalance,givenUsdnBalance) = {
311311 let usdnInPool = indexOf(assetIds, usdnAssetId)
312312 let puzzleInPool = indexOf(assetIds, puzzleAssetId)
313313 let usdtInPool = indexOf(assetIds, usdtAssetId)
314314 let usdtPptInPool = indexOf(assetIds, usdtPptAssetId)
315315 let wavesInPool = indexOf(assetIds, unit)
316316 let assetWeight = tryGetInteger((("static_" + getAssetString(assetId)) + "_weight"))
317317 let feeAssetStr = tryGetString("static_feeToken")
318318 if ((feeAssetStr == puzzleAssetIdStr))
319319 then {
320320 let puzzleWeight = AssetsWeights[value(indexOf(assetIds, puzzleAssetId))]
321321 let puzzleBalance = tryGetInteger((("global_" + puzzleAssetIdStr) + "_balance"))
322322 let amountInPuzzle = fraction(amount, (puzzleBalance / puzzleWeight), (aBalance / assetWeight))
323323 let puzzlePrice = getIntegerValue(parentPoolAddress, "global_lastPuzzlePrice")
324324 fraction((amountInPuzzle * puzzlePrice), 1, Scale8)
325325 }
326326 else if ((feeAssetStr == usdtAssetIdStr))
327327 then {
328328 let usdtWeight = AssetsWeights[value(usdtInPool)]
329329 let usdtBalance = tryGetInteger((("global_" + usdtAssetIdStr) + "_balance"))
330330 fraction(amount, (usdtBalance / usdtWeight), (aBalance / assetWeight))
331331 }
332332 else if ((feeAssetStr == usdtPptAssetIdStr))
333333 then {
334334 let usdtWeight = AssetsWeights[value(usdtPptInPool)]
335335 let usdtBalance = tryGetInteger((("global_" + usdtPptAssetIdStr) + "_balance"))
336336 fraction(amount, (usdtBalance / usdtWeight), (aBalance / assetWeight))
337337 }
338338 else if ((feeAssetStr == usdnAssetIdStr))
339339 then {
340340 let usdnWeight = AssetsWeights[value(indexOf(assetIds, usdnAssetId))]
341341 let usdnBalance = match givenUsdnBalance {
342342 case x: Int =>
343343 givenUsdnBalance
344344 case _ =>
345345 tryGetInteger((("global_" + getAssetString(usdnAssetId)) + "_balance"))
346346 }
347347 fraction(amount, (value(usdnBalance) / usdnWeight), (aBalance / assetWeight))
348348 }
349349 else {
350350 let wavesWeight = 3000
351351 let wBalance = (tryGetInteger("global_WAVES_balance") / 50)
352352 fraction(amount, (wBalance / wavesWeight), (aBalance / assetWeight))
353353 }
354354 }
355355
356356
357357 func getPriceFromOracle (assetIdStr) = match getInteger(oracleAddress, (assetIdStr + "_twap5B")) {
358358 case x: Int =>
359359 x
360360 case _ =>
361361 0
362362 }
363363
364364
365365 func calculateUsdValue (assetId,amount,aBalance) = {
366366 let assetWeight = tryGetInteger((("static_" + getAssetString(assetId)) + "_weight"))
367367 let feeAssetStr = tryGetString("static_feeToken")
368368 let feeAssetScale = getIntegerValue(this, (("static_" + feeAssetStr) + "_scale"))
369369 let feeAssetNum = value(indexOf(assetIds, getAssetBytes(feeAssetStr)))
370370 let feeAssetWeight = AssetsWeights[feeAssetNum]
371371 let feeAssetBalance = tryGetInteger((("global_" + feeAssetStr) + "_balance"))
372372 let valInFeeAsset = fraction(amount, (feeAssetBalance / feeAssetWeight), (aBalance / assetWeight))
373373 let feeAssetPrice = getPriceFromOracle(feeAssetStr)
374374 fraction(valInFeeAsset, feeAssetPrice, feeAssetScale)
375375 }
376376
377377
378378 func checkTokensValidity (payments) = {
379379 func handler1 (accum,payment) = (accum ++ [payment.assetId])
380380
381381 let ids = {
382382 let $l = payments
383383 let $s = size($l)
384384 let $acc0 = nil
385385 func $f4_1 ($a,$i) = if (($i >= $s))
386386 then $a
387387 else handler1($a, $l[$i])
388388
389389 func $f4_2 ($a,$i) = if (($i >= $s))
390390 then $a
391391 else throw("List size exceeds 10")
392392
393393 $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)
394394 }
395395 if ((ids == ids))
396396 then {
397397 func handler2 (accum,assetId) = if ((indexOf(ids, assetId) != unit))
398398 then (accum + 1)
399399 else throw(("asset not attached: " + getAssetString(assetId)))
400400
401401 let checks = {
402402 let $l = assetIds
403403 let $s = size($l)
404404 let $acc0 = 0
405405 func $f5_1 ($a,$i) = if (($i >= $s))
406406 then $a
407407 else handler2($a, $l[$i])
408408
409409 func $f5_2 ($a,$i) = if (($i >= $s))
410410 then $a
411411 else throw("List size exceeds 10")
412412
413413 $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)
414414 }
415415 if ((checks == checks))
416416 then true
417417 else throw("Strict value is not equal to itself.")
418418 }
419419 else throw("Strict value is not equal to itself.")
420420 }
421421
422422
423423 func handlePoolTokensAdd (PIssued,payments,userAddress,needChange) = {
424424 func getTokenPaymentAmount (tokenId) = {
425425 func handler (accum,payment) = if ((payment.assetId == tokenId))
426426 then payment.amount
427427 else accum
428428
429429 let $l = payments
430430 let $s = size($l)
431431 let $acc0 = 0
432432 func $f4_1 ($a,$i) = if (($i >= $s))
433433 then $a
434434 else handler($a, $l[$i])
435435
436436 func $f4_2 ($a,$i) = if (($i >= $s))
437437 then $a
438438 else throw("List size exceeds 10")
439439
440440 $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)
441441 }
442442
443443 func handleTokenChange (accum,tokenId) = {
444444 let Bk = tryGetInteger((("global_" + getAssetString(tokenId)) + "_balance"))
445445 let PSupply = getVirtualPoolTokenAmount()
446446 let tokenDecimals = tryGetInteger((("static_" + getAssetString(tokenId)) + "_scale"))
447447 let a1 = fraction((toBigInt((PSupply + PIssued)) * toBigInt(Scale8)), toBigInt(tokenDecimals), toBigInt(PSupply), CEILING)
448448 let Dk = toInt(fraction((a1 - (toBigInt(tokenDecimals) * toBigInt(Scale8))), toBigInt(Bk), (toBigInt(tokenDecimals) * toBigInt(Scale8)), CEILING))
449449 let paymentAmount = getTokenPaymentAmount(tokenId)
450450 let toReturn = (paymentAmount - Dk)
451451 let t = if (if (needChange)
452452 then (toReturn > 0)
453453 else false)
454454 then [ScriptTransfer(userAddress, toReturn, tokenId)]
455455 else nil
456456 ((accum ++ t) ++ [IntegerEntry((("global_" + getAssetString(tokenId)) + "_balance"), (Bk + Dk))])
457457 }
458458
459459 let $l = assetIds
460460 let $s = size($l)
461461 let $acc0 = nil
462462 func $f4_1 ($a,$i) = if (($i >= $s))
463463 then $a
464464 else handleTokenChange($a, $l[$i])
465465
466466 func $f4_2 ($a,$i) = if (($i >= $s))
467467 then $a
468468 else throw("List size exceeds 10")
469469
470470 $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)
471471 }
472472
473473
474474 func handlePoolTokensRedeem (PRedeemed,userAddress) = {
475475 func handleTokenRedeem (accum,tokenId) = {
476476 let Bk = tryGetInteger((("global_" + getAssetString(tokenId)) + "_balance"))
477477 let PSupply = getVirtualPoolTokenAmount()
478478 let tokenDecimals = tryGetInteger((("static_" + getAssetString(tokenId)) + "_scale"))
479479 let psuppl = fraction((toBigInt((PSupply - PRedeemed)) * toBigInt(Scale8)), toBigInt(Scale8), toBigInt(PSupply), DOWN)
480480 let amount = toInt(fraction((toBigInt(Scale16) - psuppl), toBigInt(Bk), toBigInt(Scale16), CEILING))
481481 (accum ++ [IntegerEntry((("global_" + getAssetString(tokenId)) + "_balance"), (Bk - amount)), ScriptTransfer(userAddress, amount, tokenId)])
482482 }
483483
484484 let $l = assetIds
485485 let $s = size($l)
486486 let $acc0 = nil
487487 func $f4_1 ($a,$i) = if (($i >= $s))
488488 then $a
489489 else handleTokenRedeem($a, $l[$i])
490490
491491 func $f4_2 ($a,$i) = if (($i >= $s))
492492 then $a
493493 else throw("List size exceeds 10")
494494
495495 $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)
496496 }
497497
498498
499499 func calculateOutAmount (AmountIn,assetIn,assetOut,BalanceIn,BalanceOut) = {
500500 let IndexIn = value(indexOf(assetIds, assetIn))
501501 let IndexOut = value(indexOf(assetIds, assetOut))
502502 if ((IndexIn == IndexOut))
503503 then AmountIn
504504 else fraction(BalanceOut, ((Scale8 * Scale8) - toInt(pow(fraction((toBigInt(BalanceIn) * toBigInt(10000)), toBigInt((Scale8 * Scale8)), (toBigInt((BalanceIn + AmountIn)) * toBigInt(10000)), HALFUP), 16, toBigInt(fraction(AssetsWeights[IndexIn], 1000000000000, AssetsWeights[IndexOut])), 12, 16, CEILING))), (Scale8 * Scale8), HALFEVEN)
505505 }
506506
507507
508508 func calculateCurrentAssetInterest (assetId,assetIdStr,aBalance,tokenEarningsLastCheck) = {
509509 let totalStaked = tryGetInteger("global_indexStaked")
510510 let tokenBalanceLastCheck = tokenEarningsLastCheck
511511 let currentBalanceDelta = (getTokenBalance(assetId) - aBalance)
512512 let currentTokenEarnings = if ((currentBalanceDelta > tokenBalanceLastCheck))
513513 then currentBalanceDelta
514514 else tokenBalanceLastCheck
515515 let newEarnings = (currentTokenEarnings - tokenBalanceLastCheck)
516516 let newInterest = if ((totalStaked == 0))
517517 then 0
518518 else fraction(newEarnings, Scale8, totalStaked)
519519 let lastCheckInterest = tryGetInteger((("global_lastCheck_" + assetIdStr) + "_interest"))
520520 (lastCheckInterest + newInterest)
521521 }
522522
523523
524524 func claimResult (address) = {
525525 let addressStr = toString(address)
526526 let puzzleAmount = tryGetInteger((addressStr + "_indexStaked"))
527527 func handler (accum,assetId) = {
528528 let assetIdStr = getAssetString(assetId)
529529 let aBalance = tryGetInteger((("global_" + getAssetString(assetId)) + "_balance"))
530530 let tokenEarningsLastCheck = tryGetInteger((("global_lastCheck_" + assetIdStr) + "_earnings"))
531531 let currentTokenInterest = calculateCurrentAssetInterest(assetId, assetIdStr, aBalance, tokenEarningsLastCheck)
532532 let currentTokenEarnings = max([tokenEarningsLastCheck, (getTokenBalance(assetId) - aBalance)])
533533 let rewardAmount = fraction(puzzleAmount, (currentTokenInterest - tryGetInteger((((addressStr + "_lastCheck_") + assetIdStr) + "_interest"))), Scale8)
534534 let transfer = if ((rewardAmount == 0))
535535 then nil
536536 else [ScriptTransfer(address, rewardAmount, assetId)]
537537 $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)))
538538 }
539539
540540 let accum = {
541541 let $l = earnedAssets
542542 let $s = size($l)
543543 let $acc0 = $Tuple2(nil, 0)
544544 func $f4_1 ($a,$i) = if (($i >= $s))
545545 then $a
546546 else handler($a, $l[$i])
547547
548548 func $f4_2 ($a,$i) = if (($i >= $s))
549549 then $a
550550 else throw("List size exceeds 10")
551551
552552 $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)
553553 }
554554 $Tuple2((accum._1 ++ [IntegerEntry((addressStr + "_claimedRewardUSD"), (tryGetInteger((addressStr + "_claimedRewardUSD")) + accum._2)), IntegerEntry((addressStr + "_lastClaim"), lastBlock.timestamp)]), accum._2)
555555 }
556556
557557
558558 func indexStakeResult (addressStr,amount) = {
559559 let li = claimResult(addressFromStringValue(addressStr))._1
560560 (li ++ [IntegerEntry((addressStr + "_indexStaked"), (tryGetInteger((addressStr + "_indexStaked")) + amount)), IntegerEntry("global_indexStaked", (tryGetInteger("global_indexStaked") + amount))])
561561 }
562562
563563
564564 func sum (accum,n) = (accum + parseIntValue(n))
565565
566566
567567 func checkFeeAsset (accum,next) = if (if ((indexOf(supportedFeeAssetsStr, next) != unit))
568568 then (accum == "")
569569 else false)
570570 then next
571571 else accum
572572
573573
574574 func getTmpRebalanceIds (newAssetIdsLi) = {
575575 let currentAssetIdsLi = split(tryGetString("static_tokenIds"), ",")
576576 let result = newAssetIdsLi
577577 func f (accum,assetId) = if ((indexOf(result, assetId) == unit))
578578 then (accum ++ [assetId])
579579 else accum
580580
581581 let $l = currentAssetIdsLi
582582 let $s = size($l)
583583 let $acc0 = result
584584 func $f4_1 ($a,$i) = if (($i >= $s))
585585 then $a
586586 else f($a, $l[$i])
587587
588588 func $f4_2 ($a,$i) = if (($i >= $s))
589589 then $a
590590 else throw("List size exceeds 10")
591591
592592 $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)
593593 }
594594
595595
596596 func checkTokensChange (newAssetIdsLi) = {
597597 let currentAssetIdsLi = split(tryGetString("static_tokenIds"), ",")
598598 func rem (accum,assetId) = if ((indexOf(newAssetIdsLi, assetId) == unit))
599599 then (accum + 1)
600600 else accum
601601
602602 func add (accum,assetId) = if ((indexOf(currentAssetIdsLi, assetId) == unit))
603603 then (accum + 1)
604604 else accum
605605
606606 let removed = {
607607 let $l = currentAssetIdsLi
608608 let $s = size($l)
609609 let $acc0 = 0
610610 func $f4_1 ($a,$i) = if (($i >= $s))
611611 then $a
612612 else rem($a, $l[$i])
613613
614614 func $f4_2 ($a,$i) = if (($i >= $s))
615615 then $a
616616 else throw("List size exceeds 10")
617617
618618 $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)
619619 }
620620 let added = {
621621 let $l = newAssetIdsLi
622622 let $s = size($l)
623623 let $acc0 = 0
624624 func $f5_1 ($a,$i) = if (($i >= $s))
625625 then $a
626626 else add($a, $l[$i])
627627
628628 func $f5_2 ($a,$i) = if (($i >= $s))
629629 then $a
630630 else throw("List size exceeds 10")
631631
632632 $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)
633633 }
634634 (removed + added)
635635 }
636636
637637
638638 func validatePayments (assetsList,payments) = {
639639 func getPaymentAssets (accum,next) = if ((0 >= next.amount))
640640 then throw(((("Too low payment amount for " + getAssetString(next.assetId)) + ": ") + toString(next.amount)))
641641 else (accum ++ [getAssetString(next.assetId)])
642642
643643 let paymentList = {
644644 let $l = payments
645645 let $s = size($l)
646646 let $acc0 = nil
647647 func $f4_1 ($a,$i) = if (($i >= $s))
648648 then $a
649649 else getPaymentAssets($a, $l[$i])
650650
651651 func $f4_2 ($a,$i) = if (($i >= $s))
652652 then $a
653653 else throw("List size exceeds 10")
654654
655655 $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)
656656 }
657657 func f1 (accum,next) = if ((indexOf(assetsList, next) == unit))
658658 then throw(((next + " asset is present in payments, but is not in new assets: ") + makeString(assetsList, ",")))
659659 else (accum + 1)
660660
661661 func f2 (accum,next) = if ((indexOf(paymentList, next) == unit))
662662 then throw(((next + " asset is present in new assets, but is not in payments: ") + makeString(paymentList, ",")))
663663 else (accum + 1)
664664
665665 let a1 = {
666666 let $l = paymentList
667667 let $s = size($l)
668668 let $acc0 = 0
669669 func $f5_1 ($a,$i) = if (($i >= $s))
670670 then $a
671671 else f1($a, $l[$i])
672672
673673 func $f5_2 ($a,$i) = if (($i >= $s))
674674 then $a
675675 else throw("List size exceeds 10")
676676
677677 $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)
678678 }
679679 let a2 = {
680680 let $l = assetsList
681681 let $s = size($l)
682682 let $acc0 = 0
683683 func $f6_1 ($a,$i) = if (($i >= $s))
684684 then $a
685685 else f2($a, $l[$i])
686686
687687 func $f6_2 ($a,$i) = if (($i >= $s))
688688 then $a
689689 else throw("List size exceeds 10")
690690
691691 $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)
692692 }
693693 (a1 + a2)
694694 }
695695
696696
697697 func validateWeights (weights) = {
698698 func v (accum,w) = {
699699 let wInt = valueOrErrorMessage(parseInt(w), ("Wrong weight format: " + w))
700700 if (if ((MIN_WEIGHT > wInt))
701701 then true
702702 else (wInt > MAX_WEIGHT))
703703 then throw(((((("Weight should be in range " + toString(MIN_WEIGHT)) + " - ") + toString(MAX_WEIGHT)) + ", current: ") + w))
704704 else accum
705705 }
706706
707707 let $l = weights
708708 let $s = size($l)
709709 let $acc0 = 0
710710 func $f4_1 ($a,$i) = if (($i >= $s))
711711 then $a
712712 else v($a, $l[$i])
713713
714714 func $f4_2 ($a,$i) = if (($i >= $s))
715715 then $a
716716 else throw("List size exceeds 10")
717717
718718 $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)
719719 }
720720
721721
722722 @Callable(i)
723723 func preInit (assetIdsStr,assetWeightsStr,baseTokenIdStr,poolDomain,poolOwner,fee) = {
724724 let poolOwnerAddress = Address(fromBase58String(poolOwner))
725725 let assetIdsStrLi = split(assetIdsStr, ",")
726726 let assetIdsLi = {
727727 let $l = assetIdsStrLi
728728 let $s = size($l)
729729 let $acc0 = nil
730730 func $f4_1 ($a,$i) = if (($i >= $s))
731731 then $a
732732 else addAssetBytesToList($a, $l[$i])
733733
734734 func $f4_2 ($a,$i) = if (($i >= $s))
735735 then $a
736736 else throw("List size exceeds 10")
737737
738738 $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)
739739 }
740740 let feeAssetStr = {
741741 let $l = assetIdsStrLi
742742 let $s = size($l)
743743 let $acc0 = ""
744744 func $f5_1 ($a,$i) = if (($i >= $s))
745745 then $a
746746 else checkFeeAsset($a, $l[$i])
747747
748748 func $f5_2 ($a,$i) = if (($i >= $s))
749749 then $a
750750 else throw("List size exceeds 10")
751751
752752 $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)
753753 }
754754 if (isShutdown())
755755 then throw("contract is on stop")
756756 else if ((this != i.caller))
757757 then throw("admin only")
758758 else if ((feeAssetStr == ""))
759759 then throw("pool must have one of the supported fee assets in the composition")
760760 else if ((size(poolDomain) > 13))
761761 then throw("too large pool domain")
762762 else if (if ((fee > 500))
763763 then true
764764 else (0 > fee))
765765 then throw("fee value must be between 50 and 500 (0.5-5%)")
766766 else {
767767 let assetWeightsStrLi = split(assetWeightsStr, ",")
768768 let assetWeightsSum = {
769769 let $l = assetWeightsStrLi
770770 let $s = size($l)
771771 let $acc0 = 0
772772 func $f6_1 ($a,$i) = if (($i >= $s))
773773 then $a
774774 else sum($a, $l[$i])
775775
776776 func $f6_2 ($a,$i) = if (($i >= $s))
777777 then $a
778778 else throw("List size exceeds 10")
779779
780780 $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)
781781 }
782782 func addTokenDataEntries (accum,assetNum) = if ((assetNum >= size(assetIdsLi)))
783783 then accum
784784 else {
785785 let assetDecimals = match assetIdsLi[assetNum] {
786786 case x: ByteVector =>
787787 value(assetInfo(x)).decimals
788788 case _ =>
789789 8
790790 }
791791 (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])))])
792792 }
793793
794794 if ((assetWeightsSum != 10000))
795795 then throw("sum of token weights must be equal to 10000")
796796 else ({
797797 let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
798798 let $s = size($l)
799799 let $acc0 = nil
800800 func $f7_1 ($a,$i) = if (($i >= $s))
801801 then $a
802802 else addTokenDataEntries($a, $l[$i])
803803
804804 func $f7_2 ($a,$i) = if (($i >= $s))
805805 then $a
806806 else throw("List size exceeds 10")
807807
808808 $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)
809809 } ++ [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)])
810810 }
811811 }
812812
813813
814814
815815 @Callable(i)
816816 func deInit () = if (isShutdown())
817817 then throw("contract is on stop")
818818 else if ((i.caller != this))
819819 then throw("admin only")
820820 else [IntegerEntry("global_wasInited", 0)]
821821
822822
823823
824824 @Callable(i)
825825 func init () = {
826826 func prepareList () = {
827827 func handler (accum,n) = (accum ++ [IntegerEntry((("global_" + getAssetString(n.assetId)) + "_balance"), n.amount)])
828828
829829 let $l = i.payments
830830 let $s = size($l)
831831 let $acc0 = nil
832832 func $f4_1 ($a,$i) = if (($i >= $s))
833833 then $a
834834 else handler($a, $l[$i])
835835
836836 func $f4_2 ($a,$i) = if (($i >= $s))
837837 then $a
838838 else throw("List size exceeds 10")
839839
840840 $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)
841841 }
842842
843843 func calculatePoolTokensAmount (payments) = {
844844 func handler (accum,pmt) = {
845845 let assetId = pmt.assetId
846846 func handler2 (accum,n) = if ((n == assetId))
847847 then value(indexOf(assetIds, n))
848848 else accum
849849
850850 let Token = {
851851 let $l = assetIds
852852 let $s = size($l)
853853 let $acc0 = 1
854854 func $f4_1 ($a,$i) = if (($i >= $s))
855855 then $a
856856 else handler2($a, $l[$i])
857857
858858 func $f4_2 ($a,$i) = if (($i >= $s))
859859 then $a
860860 else throw("List size exceeds 10")
861861
862862 $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)
863863 }
864864 fraction(accum, pow(pmt.amount, Decimals[Token], AssetsWeights[Token], AssetsWeightsDecimals, 8, FLOOR), Scale8)
865865 }
866866
867867 let $l = payments
868868 let $s = size($l)
869869 let $acc0 = PoolTokenScale
870870 func $f4_1 ($a,$i) = if (($i >= $s))
871871 then $a
872872 else handler($a, $l[$i])
873873
874874 func $f4_2 ($a,$i) = if (($i >= $s))
875875 then $a
876876 else throw("List size exceeds 10")
877877
878878 $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)
879879 }
880880
881881 if (isShutdown())
882882 then throw("contract is on stop")
883883 else if ((tryGetInteger("global_wasInited") > 0))
884884 then throw("pool already inited")
885885 else {
886886 let initialPoolTokens = calculatePoolTokensAmount(i.payments)
887887 if ((initialPoolTokens == 0))
888888 then throw("you need a bigger tokens amount to launch the pool")
889889 else {
890890 let poolTokenIssue = Issue(("PZ " + tryGetString("static_poolDomain")), "Puzzle Swap: pool index token", initialPoolTokens, PoolTokenDecimals, true, unit, 0)
891891 let poolTokenId = calculateAssetId(poolTokenIssue)
892892 (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)])
893893 }
894894 }
895895 }
896896
897897
898898
899899 @Callable(i)
900900 func generateIndex (needChange) = if ((size(i.payments) != T))
901901 then throw(("you need to attach all pool tokens. amount of pool tokens: " + toString(T)))
902902 else if (!(checkTokensValidity(i.payments)))
903903 then throw("wrong assets attached")
904904 else {
905905 let PIssuedNoMult = getMinPIssued(i.payments)
906906 let result = handlePoolTokensAdd(PIssuedNoMult, i.payments, i.originCaller, needChange)
907907 let PIssuedWithMult = fraction(PIssuedNoMult, Scale16, getKMult(), DOWN)
908908 let reissue = Reissue(getBinaryValue("global_poolToken_id"), PIssuedWithMult, true)
909909 $Tuple2((result ++ [reissue, ScriptTransfer(i.caller, PIssuedWithMult, tryGetBinary("global_poolToken_id")), IntegerEntry("global_poolToken_amount", (tryGetInteger("global_poolToken_amount") + PIssuedWithMult))]), PIssuedWithMult)
910910 }
911911
912912
913913
914914 @Callable(i)
915915 func redeemIndex (sendToOrigin) = {
916916 let pmt = i.payments[0]
917917 if ((pmt.assetId != tryGetBinary("global_poolToken_id")))
918918 then throw("please attach pool share token")
919919 else if (isShutdown())
920920 then throw("contract is on stop")
921921 else {
922922 let PRedeemedWithMult = pmt.amount
923923 let PRedeemedWithNoMult = fraction(PRedeemedWithMult, getKMult(), Scale16, DOWN)
924924 let result = handlePoolTokensRedeem(PRedeemedWithNoMult, if (sendToOrigin)
925925 then i.originCaller
926926 else i.caller)
927927 (result ++ [Burn(tryGetBinary("global_poolToken_id"), PRedeemedWithMult), IntegerEntry("global_poolToken_amount", (tryGetInteger("global_poolToken_amount") - PRedeemedWithMult))])
928928 }
929929 }
930930
931931
932932
933933 @Callable(i)
934934 func stakeIndex () = {
935935 let addressStr = toString(i.originCaller)
936936 let pmt = i.payments[0]
937937 if ((value(pmt.assetId) != tryGetBinary("global_poolToken_id")))
938938 then throw("wrong asset attached")
939939 else indexStakeResult(addressStr, pmt.amount)
940940 }
941941
942942
943943
944944 @Callable(i)
945945 func stakeIndexFor (addressStr) = {
946946 let pmt = i.payments[0]
947947 if ((value(pmt.assetId) != tryGetBinary("global_poolToken_id")))
948948 then throw("wrong asset attached")
949949 else indexStakeResult(addressStr, pmt.amount)
950950 }
951951
952952
953953
954954 @Callable(i)
955955 func unstakeIndex (indexAmount) = {
956956 let addressStr = if ((indexOf(layer2Addresses, toString(i.caller)) != unit))
957957 then toString(i.originCaller)
958958 else toString(i.caller)
959959 let indexAvailable = tryGetInteger((addressStr + "_indexStaked"))
960960 if (isShutdown())
961961 then throw("contract is on stop")
962962 else if ((indexAmount > indexAvailable))
963963 then throw("you don't have index tokens available")
964964 else if (isShutdown())
965965 then throw("contract is on stop")
966966 else (claimResult(addressFromStringValue(addressStr))._1 ++ [IntegerEntry((addressStr + "_indexStaked"), (indexAvailable - indexAmount)), IntegerEntry("global_indexStaked", (tryGetInteger("global_indexStaked") - indexAmount)), ScriptTransfer(i.caller, indexAmount, getBinaryValue("global_poolToken_id"))])
967967 }
968968
969969
970970
971971 @Callable(i)
972972 func claimIndexRewards () = if (isShutdown())
973973 then throw("contract is on stop")
974974 else claimResult(i.caller)
975975
976976
977977
978978 @Callable(i)
979979 func evaluateClaim (user) = $Tuple2(nil, claimResult(addressFromStringValue(user))._2)
980980
981981
982982
983983 @Callable(i)
984984 func swap (assetOut,minimum) = {
985985 let pmt = if ((size(i.payments) == 1))
986986 then value(i.payments[0])
987987 else throw("please attach exactly one payment")
988988 let AmountIn = value(i.payments[0].amount)
989989 let AssetIn = pmt.assetId
990990 let AssetOut = getAssetBytes(assetOut)
991991 let assetIn = getAssetString(AssetIn)
992992 let scaleIn = (Scale8 / tryGetInteger((("static_" + assetIn) + "_scale")))
993993 let scaleOut = (Scale8 / tryGetInteger((("static_" + assetOut) + "_scale")))
994994 let feeAssetOutStr = tryGetString("static_feeToken")
995995 let feeAssetOut = if ((feeAssetOutStr == ""))
996996 then usdnAssetId
997997 else getAssetBytes(feeAssetOutStr)
998998 let AssetInBalance = tryGetInteger((("global_" + getAssetString(AssetIn)) + "_balance"))
999999 let AssetOutBalance = tryGetInteger((("global_" + assetOut) + "_balance"))
10001000 let AssetInBalanceScaled = (AssetInBalance * scaleIn)
10011001 let AssetOutBalanceScaled = (AssetOutBalance * scaleOut)
10021002 let feeAmountIn = fraction(AmountIn, Fee, FeeScale)
10031003 let cleanAmountIn = (AmountIn - feeAmountIn)
10041004 let cleanAmountInScaled = (cleanAmountIn * scaleIn)
10051005 let AmountOut1 = calculateOutAmount(cleanAmountInScaled, AssetIn, AssetOut, AssetInBalanceScaled, AssetOutBalanceScaled)
10061006 let AmountOut = fraction(AmountOut1, 1, scaleOut)
10071007 let AssetOutBalance2 = (AssetOutBalance - AmountOut)
10081008 let AssetInBalance2 = (AssetInBalance + cleanAmountIn)
10091009 let feeAssetOutBalance = if ((feeAssetOut == AssetIn))
10101010 then AssetInBalance2
10111011 else if ((feeAssetOut == AssetOut))
10121012 then AssetOutBalance2
10131013 else tryGetInteger((("global_" + getAssetString(feeAssetOut)) + "_balance"))
10141014 let feeAmountOut = calculateOutAmount(feeAmountIn, AssetIn, feeAssetOut, AssetInBalance, feeAssetOutBalance)
10151015 if ((minimum > AmountOut))
10161016 then throw("amount to recieve is lower than given one")
10171017 else if ((AssetOut == AssetIn))
10181018 then throw("this swap is not allowed")
10191019 else if ((0 > (AssetOutBalance - AmountOut)))
10201020 then throw("contract is out of reserves")
10211021 else if (isShutdown())
10221022 then throw("contract is on stop")
10231023 else {
10241024 let creatorFee = fraction(feeAmountOut, 1, 10)
10251025 let protocolFee = fraction(feeAmountOut, 4, 10)
10261026 let newBalanceIn = AssetInBalance2
10271027 let newBalanceOut = (AssetOutBalance2 - (if ((AssetOut == feeAssetOut))
10281028 then feeAmountOut
10291029 else 0))
10301030 let newBalanceFeeAsset = if (if ((feeAssetOut != AssetIn))
10311031 then (feeAssetOut != AssetOut)
10321032 else false)
10331033 then (feeAssetOutBalance - feeAmountOut)
10341034 else unit
10351035 let assetInChange = IntegerEntry((("global_" + getAssetString(AssetIn)) + "_balance"), newBalanceIn)
10361036 let assetOutChange = IntegerEntry((("global_" + assetOut) + "_balance"), newBalanceOut)
10371037 let feeAssetOutChange = if ((newBalanceFeeAsset != unit))
10381038 then IntegerEntry((("global_" + getAssetString(feeAssetOut)) + "_balance"), value(newBalanceFeeAsset))
10391039 else StringEntry("hello", "world")
10401040 let volumeUpdate = calculateUsdnValue(AssetIn, AmountIn, AssetInBalance, feeAssetOutBalance)
10411041 let volumeUsdUpdate = calculateUsdValue(AssetIn, AmountIn, AssetInBalance)
10421042 $Tuple2([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)
10431043 }
10441044 }
10451045
10461046
10471047
10481048 @Callable(i)
10491049 func swapReadOnly (assetIn,assetOut,AmountIn) = {
10501050 let AssetIn = getAssetBytes(assetIn)
10511051 let AssetOut = getAssetBytes(assetOut)
10521052 let scaleIn = (Scale8 / tryGetInteger((("static_" + assetIn) + "_scale")))
10531053 let scaleOut = (Scale8 / tryGetInteger((("static_" + assetOut) + "_scale")))
10541054 let feeAssetOutStr = tryGetString("static_feeToken")
10551055 let feeAssetOut = if ((feeAssetOutStr == ""))
10561056 then usdnAssetId
10571057 else getAssetBytes(feeAssetOutStr)
10581058 let AssetInBalance = tryGetInteger((("global_" + getAssetString(AssetIn)) + "_balance"))
10591059 let AssetOutBalance = tryGetInteger((("global_" + assetOut) + "_balance"))
10601060 let AssetInBalanceScaled = (AssetInBalance * scaleIn)
10611061 let AssetOutBalanceScaled = (AssetOutBalance * scaleOut)
10621062 let feeAmountIn = fraction(AmountIn, Fee, FeeScale)
10631063 let cleanAmountIn = (AmountIn - feeAmountIn)
10641064 let cleanAmountInScaled = (cleanAmountIn * scaleIn)
10651065 let AmountOut1 = calculateOutAmount(cleanAmountInScaled, AssetIn, AssetOut, AssetInBalanceScaled, AssetOutBalanceScaled)
10661066 let AmountOut = fraction(AmountOut1, 1, scaleOut)
10671067 let AssetOutBalance2 = (AssetOutBalance - AmountOut)
10681068 let AssetInBalance2 = (AssetInBalance + cleanAmountIn)
10691069 let feeAssetOutBalance = if ((feeAssetOut == AssetIn))
10701070 then AssetInBalance2
10711071 else if ((feeAssetOut == AssetOut))
10721072 then AssetOutBalance2
10731073 else tryGetInteger((("global_" + getAssetString(feeAssetOut)) + "_balance"))
10741074 let feeAmountOut = calculateOutAmount(feeAmountIn, AssetIn, feeAssetOut, AssetInBalance, feeAssetOutBalance)
10751075 if ((AssetOut == AssetIn))
10761076 then throw("this swap is not allowed")
10771077 else if ((0 > (AssetOutBalance - AmountOut)))
10781078 then throw("contract is out of reserves")
10791079 else if (isShutdown())
10801080 then throw("contract is on stop")
10811081 else $Tuple2(nil, AmountOut)
10821082 }
10831083
10841084
10851085
10861086 @Callable(i)
10871087 func transferOwnership (newOwnerAddress) = if ((toString(i.caller) != tryGetString("static_poolOwner")))
10881088 then throw("this call available only for pool owner")
10891089 else [StringEntry("static_poolOwner", newOwnerAddress)]
10901090
10911091
10921092
10931093 @Callable(i)
10941094 func setFee (newFee) = if ((toString(i.caller) != tryGetString("static_poolOwner")))
10951095 then throw("this call available only for pool owner")
10961096 else if ((1 > valueOrElse(getInteger(govAddress, ("approvedTx_" + toBase58String(i.transactionId))), 0)))
10971097 then throw("this transaction needs approval from puzzle network")
10981098 else [IntegerEntry("static_fee", newFee)]
10991099
11001100
11011101
11021102 @Callable(i)
11031103 func setRebalancingPlan (assetIdsStr,assetWeightsStr,baseTokenIdStr,stepsAmount,stepsInterval) = if ((i.caller != addressFromStringValue(tryGetString("static_poolOwner"))))
11041104 then throw("this call available only for pool owner")
1105- else if ((1 > valueOrElse(getInteger(govAddress, ("approvedTx_" + toBase58String(i.transactionId))), 0)))
1106- then throw("this transaction needs approval from puzzle network")
1107- else if (valueOrElse(getBoolean(this, "rebalance_inProgress"), false))
1108- then throw("rebalancing in progress")
1109- else {
1110- let newAssetWeightsStrLi = split(assetWeightsStr, ",")
1111- let newAssetIdsStrLi = split(assetIdsStr, ",")
1112- let feeAssetStr = {
1113- let $l = newAssetIdsStrLi
1114- let $s = size($l)
1115- let $acc0 = ""
1116- func $f4_1 ($a,$i) = if (($i >= $s))
1117- then $a
1118- else checkFeeAsset($a, $l[$i])
1105+ else if (valueOrElse(getBoolean(this, "rebalance_inProgress"), false))
1106+ then throw("rebalancing in progress")
1107+ else {
1108+ let newAssetWeightsStrLi = split(assetWeightsStr, ",")
1109+ let newAssetIdsStrLi = split(assetIdsStr, ",")
1110+ let feeAssetStr = {
1111+ let $l = newAssetIdsStrLi
1112+ let $s = size($l)
1113+ let $acc0 = ""
1114+ func $f4_1 ($a,$i) = if (($i >= $s))
1115+ then $a
1116+ else checkFeeAsset($a, $l[$i])
11191117
1120- func $f4_2 ($a,$i) = if (($i >= $s))
1121- then $a
1122- else throw("List size exceeds 10")
1118+ func $f4_2 ($a,$i) = if (($i >= $s))
1119+ then $a
1120+ else throw("List size exceeds 10")
11231121
1124- $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)
1125- }
1126- let assetWeightsSum = {
1127- let $l = newAssetWeightsStrLi
1128- let $s = size($l)
1129- let $acc0 = 0
1130- func $f5_1 ($a,$i) = if (($i >= $s))
1131- then $a
1132- else sum($a, $l[$i])
1122+ $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)
1123+ }
1124+ let assetWeightsSum = {
1125+ let $l = newAssetWeightsStrLi
1126+ let $s = size($l)
1127+ let $acc0 = 0
1128+ func $f5_1 ($a,$i) = if (($i >= $s))
1129+ then $a
1130+ else sum($a, $l[$i])
11331131
1134- func $f5_2 ($a,$i) = if (($i >= $s))
1135- then $a
1136- else throw("List size exceeds 10")
1132+ func $f5_2 ($a,$i) = if (($i >= $s))
1133+ then $a
1134+ else throw("List size exceeds 10")
11371135
1138- $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)
1139- }
1140- let oldAssetIds = getStringValue("static_tokenIds")
1141- let oldAssetIdsLi = split(oldAssetIds, ",")
1142- func findAdded (accum,next) = if ((indexOf(oldAssetIdsLi, next) == unit))
1143- then (accum ++ [next])
1144- else accum
1136+ $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)
1137+ }
1138+ let oldAssetIds = getStringValue("static_tokenIds")
1139+ let oldAssetIdsLi = split(oldAssetIds, ",")
1140+ func findAdded (accum,next) = if ((indexOf(oldAssetIdsLi, next) == unit))
1141+ then (accum ++ [next])
1142+ else accum
11451143
1146- func findRemoved (accum,next) = if ((indexOf(newAssetIdsStrLi, next) == unit))
1147- then (accum ++ [next])
1148- else accum
1144+ func findRemoved (accum,next) = if ((indexOf(newAssetIdsStrLi, next) == unit))
1145+ then (accum ++ [next])
1146+ else accum
11491147
1150- let addedAssets = {
1151- let $l = newAssetIdsStrLi
1152- let $s = size($l)
1153- let $acc0 = nil
1154- func $f6_1 ($a,$i) = if (($i >= $s))
1155- then $a
1156- else findAdded($a, $l[$i])
1148+ let addedAssets = {
1149+ let $l = newAssetIdsStrLi
1150+ let $s = size($l)
1151+ let $acc0 = nil
1152+ func $f6_1 ($a,$i) = if (($i >= $s))
1153+ then $a
1154+ else findAdded($a, $l[$i])
11571155
1158- func $f6_2 ($a,$i) = if (($i >= $s))
1159- then $a
1160- else throw("List size exceeds 10")
1156+ func $f6_2 ($a,$i) = if (($i >= $s))
1157+ then $a
1158+ else throw("List size exceeds 10")
11611159
1162- $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)
1163- }
1164- let removedAssets = {
1165- let $l = oldAssetIdsLi
1166- let $s = size($l)
1167- let $acc0 = nil
1168- func $f7_1 ($a,$i) = if (($i >= $s))
1169- then $a
1170- else findRemoved($a, $l[$i])
1160+ $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)
1161+ }
1162+ let removedAssets = {
1163+ let $l = oldAssetIdsLi
1164+ let $s = size($l)
1165+ let $acc0 = nil
1166+ func $f7_1 ($a,$i) = if (($i >= $s))
1167+ then $a
1168+ else findRemoved($a, $l[$i])
11711169
1172- func $f7_2 ($a,$i) = if (($i >= $s))
1173- then $a
1174- else throw("List size exceeds 10")
1170+ func $f7_2 ($a,$i) = if (($i >= $s))
1171+ then $a
1172+ else throw("List size exceeds 10")
11751173
1176- $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)
1177- }
1178- let validPayments = validatePayments(addedAssets, i.payments)
1179- let validWeights = validateWeights(newAssetWeightsStrLi)
1180- if ((validWeights == validWeights))
1181- then if ((validPayments != (size(addedAssets) + size(i.payments))))
1182- then throw("Payments not present or something wrong with them")
1183- else if ((size(newAssetIdsStrLi) != size(newAssetWeightsStrLi)))
1184- then throw("assetIds and assetWeights should have same length")
1185- else if ((validPayments != (size(addedAssets) + size(i.payments))))
1186- then throw("Payments not present or something wrong with them")
1187- else if ((feeAssetStr == ""))
1188- then throw("pool must have one of the supported fee assets in the composition")
1189- else if ((indexOf(newAssetIdsStrLi, baseTokenIdStr) == unit))
1190- then throw("baseTokenId should be present in assetIds")
1191- else if (if ((MIN_STEPS_AMOUNT > stepsAmount))
1174+ $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)
1175+ }
1176+ let validPayments = validatePayments(addedAssets, i.payments)
1177+ let validWeights = validateWeights(newAssetWeightsStrLi)
1178+ if ((validWeights == validWeights))
1179+ then if ((validPayments != (size(addedAssets) + size(i.payments))))
1180+ then throw("Payments not present or something wrong with them")
1181+ else if ((size(newAssetIdsStrLi) != size(newAssetWeightsStrLi)))
1182+ then throw("assetIds and assetWeights should have same length")
1183+ else if ((validPayments != (size(addedAssets) + size(i.payments))))
1184+ then throw("Payments not present or something wrong with them")
1185+ else if ((feeAssetStr == ""))
1186+ then throw("pool must have one of the supported fee assets in the composition")
1187+ else if ((indexOf(newAssetIdsStrLi, baseTokenIdStr) == unit))
1188+ then throw("baseTokenId should be present in assetIds")
1189+ else if (if ((MIN_STEPS_AMOUNT > stepsAmount))
1190+ then true
1191+ else (stepsAmount > MAX_STEPS_AMOUNT))
1192+ then throw(((((("Steps amount should be between " + toString(MIN_STEPS_AMOUNT)) + " and ") + toString(MAX_STEPS_AMOUNT)) + ", current: ") + toString(stepsAmount)))
1193+ else if (if ((MIN_STEPS_INTERVAL > stepsInterval))
11921194 then true
1193- else (stepsAmount > MAX_STEPS_AMOUNT))
1194- then throw(((((("Steps amount should be between " + toString(MIN_STEPS_AMOUNT)) + " and ") + toString(MAX_STEPS_AMOUNT)) + ", current: ") + toString(stepsAmount)))
1195- else if (if ((MIN_STEPS_INTERVAL > stepsInterval))
1196- then true
1197- else (stepsInterval > MAX_STEPS_INTERVAL))
1198- then throw(((((("Steps interval should be between " + toString(MIN_STEPS_INTERVAL)) + " and ") + toString(MAX_STEPS_INTERVAL)) + ", current: ") + toString(stepsInterval)))
1199- else if ((assetWeightsSum != 10000))
1200- then throw(("sum of token weights must be equal to 10000, current: " + toString(assetWeightsSum)))
1201- else {
1202- func f (accum,assetIdStr) = {
1203- let oldWeight = tryGetInteger((("static_" + assetIdStr) + "_weight"))
1204- let newWeight = if ((indexOf(newAssetIdsStrLi, assetIdStr) == unit))
1205- then 0
1206- else parseIntValue(value(newAssetWeightsStrLi[value(indexOf(newAssetIdsStrLi, assetIdStr))]))
1207- let deltaPerStep = fraction((newWeight - oldWeight), 10000, stepsAmount)
1208- (accum ++ [toString(deltaPerStep)])
1209- }
1195+ else (stepsInterval > MAX_STEPS_INTERVAL))
1196+ then throw(((((("Steps interval should be between " + toString(MIN_STEPS_INTERVAL)) + " and ") + toString(MAX_STEPS_INTERVAL)) + ", current: ") + toString(stepsInterval)))
1197+ else if ((assetWeightsSum != 10000))
1198+ then throw(("sum of token weights must be equal to 10000, current: " + toString(assetWeightsSum)))
1199+ else {
1200+ func f (accum,assetIdStr) = {
1201+ let oldWeight = tryGetInteger((("static_" + assetIdStr) + "_weight"))
1202+ let newWeight = if ((indexOf(newAssetIdsStrLi, assetIdStr) == unit))
1203+ then 0
1204+ else parseIntValue(value(newAssetWeightsStrLi[value(indexOf(newAssetIdsStrLi, assetIdStr))]))
1205+ let deltaPerStep = fraction((newWeight - oldWeight), 10000, stepsAmount)
1206+ (accum ++ [toString(deltaPerStep)])
1207+ }
12101208
1211- let tmpAssetIdsLi = getTmpRebalanceIds(newAssetIdsStrLi)
1212- let assetDeltas = {
1213- let $l = tmpAssetIdsLi
1214- let $s = size($l)
1215- let $acc0 = nil
1216- func $f8_1 ($a,$i) = if (($i >= $s))
1217- then $a
1218- else f($a, $l[$i])
1209+ let tmpAssetIdsLi = getTmpRebalanceIds(newAssetIdsStrLi)
1210+ let assetDeltas = {
1211+ let $l = tmpAssetIdsLi
1212+ let $s = size($l)
1213+ let $acc0 = nil
1214+ func $f8_1 ($a,$i) = if (($i >= $s))
1215+ then $a
1216+ else f($a, $l[$i])
12191217
1220- func $f8_2 ($a,$i) = if (($i >= $s))
1221- then $a
1222- else throw("List size exceeds 10")
1218+ func $f8_2 ($a,$i) = if (($i >= $s))
1219+ then $a
1220+ else throw("List size exceeds 10")
12231221
1224- $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)
1225- }
1226- let newTokensAdded = (checkTokensChange(newAssetIdsStrLi) > 0)
1227- func recordAssetPayment (accum,next) = (accum ++ [IntegerEntry(("rebalance_attachedPayment_" + getAssetString(next.assetId)), next.amount)])
1222+ $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)
1223+ }
1224+ let newTokensAdded = (checkTokensChange(newAssetIdsStrLi) > 0)
1225+ func recordAssetPayment (accum,next) = (accum ++ [IntegerEntry(("rebalance_attachedPayment_" + getAssetString(next.assetId)), next.amount)])
12281226
1229- let paymentEntries = {
1230- let $l = i.payments
1231- let $s = size($l)
1232- let $acc0 = nil
1233- func $f9_1 ($a,$i) = if (($i >= $s))
1234- then $a
1235- else recordAssetPayment($a, $l[$i])
1227+ let paymentEntries = {
1228+ let $l = i.payments
1229+ let $s = size($l)
1230+ let $acc0 = nil
1231+ func $f9_1 ($a,$i) = if (($i >= $s))
1232+ then $a
1233+ else recordAssetPayment($a, $l[$i])
12361234
1237- func $f9_2 ($a,$i) = if (($i >= $s))
1238- then $a
1239- else throw("List size exceeds 10")
1235+ func $f9_2 ($a,$i) = if (($i >= $s))
1236+ then $a
1237+ else throw("List size exceeds 10")
12401238
1241- $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)
1242- }
1243- let storeWeights = saveCurrentWeights()
1244- let notifyInvoke = invoke(poolsHubAddress, "notifyPoolChange", nil, nil)
1245- if ((notifyInvoke == notifyInvoke))
1246- 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)
1247- else throw("Strict value is not equal to itself.")
1239+ $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)
12481240 }
1249- else throw("Strict value is not equal to itself.")
1250- }
1241+ let storeWeights = saveCurrentWeights()
1242+ let requestGovInvoke = invoke(govAddress, "requestRebalancing", [toBase58String(i.transactionId)], nil)
1243+ if ((requestGovInvoke == requestGovInvoke))
1244+ 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)
1245+ else throw("Strict value is not equal to itself.")
1246+ }
1247+ else throw("Strict value is not equal to itself.")
1248+ }
12511249
12521250
12531251
12541252 @Callable(i)
1255-func stepRebalancing () = if (!(valueOrElse(getBoolean(this, "rebalance_inProgress"), false)))
1256- then throw("no rebalancing in progress")
1257- else {
1258- let lastStepHeight = getIntegerValue("rebalance_lastStepHeight")
1259- let stepInterval = getIntegerValue("rebalance_stepsInterval")
1260- let stepsDone = getIntegerValue("rebalance_stepsDone")
1261- let nextStepHeight = (lastStepHeight + stepInterval)
1262- if ((nextStepHeight > height))
1263- then throw("can't be done yet")
1253+func stepRebalancing () = {
1254+ let rebId = valueOrErrorMessage(getString(govAddress, ("pool_lastRebalancing_" + toString(this))), "rebalancing is not registered at gov address")
1255+ if (!(valueOrElse(getBoolean(this, "rebalance_inProgress"), false)))
1256+ then throw("no rebalancing in progress")
1257+ else if ((valueOrElse(getInteger(govAddress, ("rebalancing_status_" + rebId)), 0) != 2))
1258+ then throw("this transaction needs approval from puzzle network")
12641259 else {
1265- let assetDeltas = split(getStringValue("rebalance_assetDeltas"), ",")
1266- let newAssetIdsStr = getStringValue("tmp_rebalanceAssetIds")
1267- let newAssetIds = split(newAssetIdsStr, ",")
1268- 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))])
1260+ let lastStepHeight = getIntegerValue("rebalance_lastStepHeight")
1261+ let stepInterval = getIntegerValue("rebalance_stepsInterval")
1262+ let stepsDone = getIntegerValue("rebalance_stepsDone")
1263+ let nextStepHeight = (lastStepHeight + stepInterval)
1264+ if ((nextStepHeight > height))
1265+ then throw("can't be done yet")
1266+ else {
1267+ let assetDeltas = split(getStringValue("rebalance_assetDeltas"), ",")
1268+ let newAssetIdsStr = getStringValue("tmp_rebalanceAssetIds")
1269+ let newAssetIds = split(newAssetIdsStr, ",")
1270+ 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))])
12691271
1270- let newShares = makeString({
1271- let $l = newAssetIds
1272- let $s = size($l)
1273- let $acc0 = nil
1274- func $f4_1 ($a,$i) = if (($i >= $s))
1275- then $a
1276- else f($a, $l[$i])
1272+ let newShares = makeString({
1273+ let $l = newAssetIds
1274+ let $s = size($l)
1275+ let $acc0 = nil
1276+ func $f4_1 ($a,$i) = if (($i >= $s))
1277+ then $a
1278+ else f($a, $l[$i])
12771279
1278- func $f4_2 ($a,$i) = if (($i >= $s))
1279- then $a
1280- else throw("List size exceeds 10")
1280+ func $f4_2 ($a,$i) = if (($i >= $s))
1281+ then $a
1282+ else throw("List size exceeds 10")
12811283
1282- $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)
1283- }, ",")
1284- let newTokensAdded = getBooleanValue("rebalance_newTokensAdded")
1285- let inv = if (if (newTokensAdded)
1286- then (stepsDone == 0)
1287- else false)
1288- then invoke(this, "doRebalancingWithNewTokens", [newAssetIdsStr, newShares, getStringValue("rebalance_newBaseTokenId")], nil)
1289- else invoke(this, "doRebalancing", [newShares], nil)
1290- if ((inv == inv))
1291- then {
1292- let notifyInvoke = invoke(poolsHubAddress, "notifyPoolChange", nil, nil)
1293- if ((notifyInvoke == notifyInvoke))
1284+ $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)
1285+ }, ",")
1286+ let newTokensAdded = getBooleanValue("rebalance_newTokensAdded")
1287+ let inv = if (if (newTokensAdded)
1288+ then (stepsDone == 0)
1289+ else false)
1290+ then invoke(this, "doRebalancingWithNewTokens", [newAssetIdsStr, newShares, getStringValue("rebalance_newBaseTokenId")], nil)
1291+ else invoke(this, "doRebalancing", [newShares], nil)
1292+ if ((inv == inv))
12941293 then {
1295- let isFinished = ((stepsDone + 1) >= getIntegerValue("rebalance_stepsAmount"))
1296- let actions = [BooleanEntry("rebalance_inProgress", !(isFinished)), IntegerEntry("rebalance_stepsDone", (stepsDone + 1)), IntegerEntry("rebalance_lastStepHeight", height)]
1297- if ((stepsDone == 0))
1298- then (actions ++ [StringEntry("static_tokenIds", newAssetIdsStr)])
1299- else if (isFinished)
1300- then {
1301- let removedAssetsLi = split(tryGetString("rebalance_removedAssets"), ",")
1302- 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))])
1294+ let notifyInvoke = invoke(poolsHubAddress, "notifyPoolChange", nil, nil)
1295+ if ((notifyInvoke == notifyInvoke))
1296+ then {
1297+ let isFinished = ((stepsDone + 1) >= getIntegerValue("rebalance_stepsAmount"))
1298+ let actions = [BooleanEntry("rebalance_inProgress", !(isFinished)), IntegerEntry("rebalance_stepsDone", (stepsDone + 1)), IntegerEntry("rebalance_lastStepHeight", height)]
1299+ if ((stepsDone == 0))
1300+ then (actions ++ [StringEntry("static_tokenIds", newAssetIdsStr)])
1301+ else if (isFinished)
1302+ then {
1303+ let removedAssetsLi = split(tryGetString("rebalance_removedAssets"), ",")
1304+ 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))])
13031305
1304- let rm = {
1305- let $l = removedAssetsLi
1306- let $s = size($l)
1307- let $acc0 = nil
1308- func $f5_1 ($a,$i) = if (($i >= $s))
1309- then $a
1310- else rmData($a, $l[$i])
1306+ let rm = {
1307+ let $l = removedAssetsLi
1308+ let $s = size($l)
1309+ let $acc0 = nil
1310+ func $f5_1 ($a,$i) = if (($i >= $s))
1311+ then $a
1312+ else rmData($a, $l[$i])
13111313
1312- func $f5_2 ($a,$i) = if (($i >= $s))
1313- then $a
1314- else throw("List size exceeds 10")
1314+ func $f5_2 ($a,$i) = if (($i >= $s))
1315+ then $a
1316+ else throw("List size exceeds 10")
13151317
1316- $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)
1317- }
1318- let addedAssetsLi = split(tryGetString("rebalance_addedAssets"), ",")
1319- func addRemovePayments (accum,assetId) = (accum ++ [DeleteEntry(("rebalance_attachedPayment_" + assetId))])
1318+ $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)
1319+ }
1320+ let addedAssetsLi = split(tryGetString("rebalance_addedAssets"), ",")
1321+ func addRemovePayments (accum,assetId) = (accum ++ [DeleteEntry(("rebalance_attachedPayment_" + assetId))])
13201322
1321- let rmPayments = {
1322- let $l = addedAssetsLi
1323- let $s = size($l)
1324- let $acc0 = nil
1325- func $f6_1 ($a,$i) = if (($i >= $s))
1326- then $a
1327- else addRemovePayments($a, $l[$i])
1323+ let rmPayments = {
1324+ let $l = addedAssetsLi
1325+ let $s = size($l)
1326+ let $acc0 = nil
1327+ func $f6_1 ($a,$i) = if (($i >= $s))
1328+ then $a
1329+ else addRemovePayments($a, $l[$i])
13281330
1329- func $f6_2 ($a,$i) = if (($i >= $s))
1330- then $a
1331- else throw("List size exceeds 10")
1331+ func $f6_2 ($a,$i) = if (($i >= $s))
1332+ then $a
1333+ else throw("List size exceeds 10")
13321334
1333- $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)
1334- }
1335- let finalAssetsIdsStr = tryGetString("rebalance_assetIds")
1336- let AssetsWeightsStr = {
1337- let $l = split(finalAssetsIdsStr, ",")
1338- let $s = size($l)
1339- let $acc0 = nil
1340- func $f7_1 ($a,$i) = if (($i >= $s))
1341- then $a
1342- else addAssetWeightToStrList($a, $l[$i])
1335+ $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)
1336+ }
1337+ let finalAssetsIdsStr = tryGetString("rebalance_assetIds")
1338+ let AssetsWeightsStr = {
1339+ let $l = split(finalAssetsIdsStr, ",")
1340+ let $s = size($l)
1341+ let $acc0 = nil
1342+ func $f7_1 ($a,$i) = if (($i >= $s))
1343+ then $a
1344+ else addAssetWeightToStrList($a, $l[$i])
13431345
1344- func $f7_2 ($a,$i) = if (($i >= $s))
1345- then $a
1346- else throw("List size exceeds 10")
1346+ func $f7_2 ($a,$i) = if (($i >= $s))
1347+ then $a
1348+ else throw("List size exceeds 10")
13471349
1348- $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)
1349- }
1350- (((actions ++ rm) ++ rmPayments) ++ [StringEntry("static_tokenIds", finalAssetsIdsStr), StringEntry("static_tokenWeights", makeString(AssetsWeightsStr, ",")), IntegerEntry("static_tokensAmount", size(split(finalAssetsIdsStr, ",")))])
1351- }
1352- else {
1353- let finalAssetsIdsStr = tryGetString("rebalance_assetIds")
1354- let AssetsWeightsStr = {
1355- let $l = split(finalAssetsIdsStr, ",")
1356- let $s = size($l)
1357- let $acc0 = nil
1358- func $f5_1 ($a,$i) = if (($i >= $s))
1359- then $a
1360- else addAssetWeightToStrList($a, $l[$i])
1350+ $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)
1351+ }
1352+ let notify = invoke(govAddress, "notifyRebalancingDone", [rebId], nil)
1353+ if ((notify == notify))
1354+ then (((actions ++ rm) ++ rmPayments) ++ [StringEntry("static_tokenIds", finalAssetsIdsStr), StringEntry("static_tokenWeights", makeString(AssetsWeightsStr, ",")), IntegerEntry("static_tokensAmount", size(split(finalAssetsIdsStr, ",")))])
1355+ else throw("Strict value is not equal to itself.")
1356+ }
1357+ else {
1358+ let finalAssetsIdsStr = tryGetString("rebalance_assetIds")
1359+ let AssetsWeightsStr = {
1360+ let $l = split(finalAssetsIdsStr, ",")
1361+ let $s = size($l)
1362+ let $acc0 = nil
1363+ func $f5_1 ($a,$i) = if (($i >= $s))
1364+ then $a
1365+ else addAssetWeightToStrList($a, $l[$i])
13611366
1362- func $f5_2 ($a,$i) = if (($i >= $s))
1363- then $a
1364- else throw("List size exceeds 10")
1367+ func $f5_2 ($a,$i) = if (($i >= $s))
1368+ then $a
1369+ else throw("List size exceeds 10")
13651370
1366- $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)
1367- }
1368- (actions ++ [StringEntry("static_tokenWeights", makeString(AssetsWeightsStr, ","))])
1369- }
1371+ $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)
1372+ }
1373+ (actions ++ [StringEntry("static_tokenWeights", makeString(AssetsWeightsStr, ","))])
1374+ }
1375+ }
1376+ else throw("Strict value is not equal to itself.")
13701377 }
13711378 else throw("Strict value is not equal to itself.")
13721379 }
1373- else throw("Strict value is not equal to itself.")
13741380 }
1375- }
1381+ }
13761382
13771383
13781384
13791385 @Callable(i)
13801386 func doRebalancing (assetWeightsStr) = {
13811387 let assetWeightsStrLi = split(assetWeightsStr, ",")
13821388 let assetWeightsSum = {
13831389 let $l = assetWeightsStrLi
13841390 let $s = size($l)
13851391 let $acc0 = 0
13861392 func $f4_1 ($a,$i) = if (($i >= $s))
13871393 then $a
13881394 else sum($a, $l[$i])
13891395
13901396 func $f4_2 ($a,$i) = if (($i >= $s))
13911397 then $a
13921398 else throw("List size exceeds 10")
13931399
13941400 $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)
13951401 }
13961402 let assetIdsStrLi = split(tryGetString("static_tokenIds"), ",")
13971403 if ((i.caller != this))
13981404 then throw("this call available only for admin")
13991405 else {
14001406 let oldKMult = getKMult()
14011407 func handler (pars,assetId) = {
14021408 let accum = pars._1
14031409 let assetIdStr = getAssetString(assetId)
14041410 func handler2 (accum,n) = if ((n == assetId))
14051411 then value(indexOf(assetIds, n))
14061412 else accum
14071413
14081414 let Token = {
14091415 let $l = assetIds
14101416 let $s = size($l)
14111417 let $acc0 = 1
14121418 func $f5_1 ($a,$i) = if (($i >= $s))
14131419 then $a
14141420 else handler2($a, $l[$i])
14151421
14161422 func $f5_2 ($a,$i) = if (($i >= $s))
14171423 then $a
14181424 else throw("List size exceeds 10")
14191425
14201426 $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)
14211427 }
14221428 let balance = tryGetInteger((("global_" + assetIdStr) + "_balance"))
14231429 let weight = if ((pars._2 == "new"))
14241430 then parseIntValue(assetWeightsStrLi[Token])
14251431 else tryGetInteger((("static_" + assetIdStr) + "_weight"))
14261432 $Tuple2(fraction(accum, pow(balance, Decimals[Token], weight, AssetsWeightsDecimals, 8, FLOOR), Scale8), pars._2)
14271433 }
14281434
14291435 let newK = ( let $l = assetIds
14301436 let $s = size($l)
14311437 let $acc0 = $Tuple2(PoolTokenScale, "new")
14321438 func $f5_1 ($a,$i) = if (($i >= $s))
14331439 then $a
14341440 else handler($a, $l[$i])
14351441
14361442 func $f5_2 ($a,$i) = if (($i >= $s))
14371443 then $a
14381444 else throw("List size exceeds 10")
14391445
14401446 $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
14411447 let oldK = ( let $l = assetIds
14421448 let $s = size($l)
14431449 let $acc0 = $Tuple2(PoolTokenScale, "old")
14441450 func $f6_1 ($a,$i) = if (($i >= $s))
14451451 then $a
14461452 else handler($a, $l[$i])
14471453
14481454 func $f6_2 ($a,$i) = if (($i >= $s))
14491455 then $a
14501456 else throw("List size exceeds 10")
14511457
14521458 $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
14531459 let newKMult = fraction(oldKMult, newK, oldK)
14541460 func addTokenDataEntries (accum,assetNum) = if ((assetNum >= size(assetWeightsStrLi)))
14551461 then accum
14561462 else (accum ++ [IntegerEntry((("static_" + assetIdsStrLi[assetNum]) + "_weight"), value(parseInt(assetWeightsStrLi[assetNum])))])
14571463
14581464 ({
14591465 let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
14601466 let $s = size($l)
14611467 let $acc0 = nil
14621468 func $f7_1 ($a,$i) = if (($i >= $s))
14631469 then $a
14641470 else addTokenDataEntries($a, $l[$i])
14651471
14661472 func $f7_2 ($a,$i) = if (($i >= $s))
14671473 then $a
14681474 else throw("List size exceeds 10")
14691475
14701476 $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)
14711477 } ++ [IntegerEntry("static_KMult", newKMult)])
14721478 }
14731479 }
14741480
14751481
14761482
14771483 @Callable(i)
14781484 func doRebalancingWithNewTokens (assetIdsStr,assetWeightsStr,baseTokenIdStr) = {
14791485 let newAssetWeightsStrLi = split(assetWeightsStr, ",")
14801486 let prevAssetIdsStrLi = split(tryGetString("static_tokenIds"), ",")
14811487 let newAssetIdsStrLi = split(assetIdsStr, ",")
14821488 let newAssetIds = {
14831489 let $l = newAssetIdsStrLi
14841490 let $s = size($l)
14851491 let $acc0 = nil
14861492 func $f4_1 ($a,$i) = if (($i >= $s))
14871493 then $a
14881494 else addAssetBytesToList($a, $l[$i])
14891495
14901496 func $f4_2 ($a,$i) = if (($i >= $s))
14911497 then $a
14921498 else throw("List size exceeds 10")
14931499
14941500 $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)
14951501 }
14961502 let feeAssetStr = {
14971503 let $l = newAssetIdsStrLi
14981504 let $s = size($l)
14991505 let $acc0 = ""
15001506 func $f5_1 ($a,$i) = if (($i >= $s))
15011507 then $a
15021508 else checkFeeAsset($a, $l[$i])
15031509
15041510 func $f5_2 ($a,$i) = if (($i >= $s))
15051511 then $a
15061512 else throw("List size exceeds 10")
15071513
15081514 $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)
15091515 }
15101516 let addedAssets = split(tryGetString("rebalance_addedAssets"), ",")
15111517 func findAssetPayment (assetId) = valueOrElse(getInteger(("rebalance_attachedPayment_" + getAssetString(assetId))), 0)
15121518
15131519 func addAssetBalanceToLi (li,assetId) = (li ++ [findAssetPayment(assetId)])
15141520
15151521 let attachedBalances = {
15161522 let $l = newAssetIds
15171523 let $s = size($l)
15181524 let $acc0 = nil
15191525 func $f6_1 ($a,$i) = if (($i >= $s))
15201526 then $a
15211527 else addAssetBalanceToLi($a, $l[$i])
15221528
15231529 func $f6_2 ($a,$i) = if (($i >= $s))
15241530 then $a
15251531 else throw("List size exceeds 10")
15261532
15271533 $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)
15281534 }
15291535 if ((i.caller != this))
15301536 then throw(("this call available only for admin, " + toString(i.caller)))
15311537 else {
15321538 let oldKMult = getKMult()
15331539 let oldK = getVirtualPoolTokenAmount()
15341540 func myltiplyAssetsForK (pars,assetId) = {
15351541 func findAssetNum (accum,n) = if ((n == assetId))
15361542 then value(indexOf(newAssetIds, n))
15371543 else accum
15381544
15391545 let currentK = pars
15401546 let assetIdStr = getAssetString(assetId)
15411547 let TokenNum = {
15421548 let $l = newAssetIds
15431549 let $s = size($l)
15441550 let $acc0 = 1
15451551 func $f7_1 ($a,$i) = if (($i >= $s))
15461552 then $a
15471553 else findAssetNum($a, $l[$i])
15481554
15491555 func $f7_2 ($a,$i) = if (($i >= $s))
15501556 then $a
15511557 else throw("List size exceeds 10")
15521558
15531559 $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)
15541560 }
15551561 let weight = parseIntValue(newAssetWeightsStrLi[TokenNum])
15561562 let balanceInState = tryGetInteger((("global_" + assetIdStr) + "_balance"))
15571563 let balanceInPayment = attachedBalances[TokenNum]
15581564 let balance = (balanceInState + balanceInPayment)
15591565 let assetDecimals = if ((assetId == unit))
15601566 then 8
15611567 else value(assetInfo(value(assetId))).decimals
15621568 if ((0 >= balance))
15631569 then throw(("you need to attach all new assets in payment. this asset is missed: " + assetIdStr))
15641570 else fraction(currentK, pow(balance, assetDecimals, weight, AssetsWeightsDecimals, 8, FLOOR), Scale8)
15651571 }
15661572
15671573 let newK = {
15681574 let $l = newAssetIds
15691575 let $s = size($l)
15701576 let $acc0 = PoolTokenScale
15711577 func $f7_1 ($a,$i) = if (($i >= $s))
15721578 then $a
15731579 else myltiplyAssetsForK($a, $l[$i])
15741580
15751581 func $f7_2 ($a,$i) = if (($i >= $s))
15761582 then $a
15771583 else throw("List size exceeds 10")
15781584
15791585 $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)
15801586 }
15811587 let newKMult = fraction(oldKMult, newK, oldK)
15821588 func addTokenDataEntries (accum,assetNum) = {
15831589 let assetIdStr = newAssetIdsStrLi[assetNum]
15841590 let assetId = newAssetIds[assetNum]
15851591 let assetDecimals = if ((assetId == unit))
15861592 then 8
15871593 else value(assetInfo(value(assetId))).decimals
15881594 let newAssetData = if ((indexOf(addedAssets, assetIdStr) != unit))
15891595 then [IntegerEntry((("global_" + assetIdStr) + "_balance"), attachedBalances[assetNum]), IntegerEntry((("static_" + assetIdStr) + "_scale"), pow(10, 0, assetDecimals, 0, 0, DOWN)), IntegerEntry((("static_" + assetIdStr) + "_decimals"), assetDecimals)]
15901596 else nil
15911597 if ((assetNum >= size(newAssetWeightsStrLi)))
15921598 then accum
15931599 else ((accum ++ [IntegerEntry((("static_" + assetIdStr) + "_weight"), value(parseInt(newAssetWeightsStrLi[assetNum])))]) ++ newAssetData)
15941600 }
15951601
15961602 ({
15971603 let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
15981604 let $s = size($l)
15991605 let $acc0 = nil
16001606 func $f8_1 ($a,$i) = if (($i >= $s))
16011607 then $a
16021608 else addTokenDataEntries($a, $l[$i])
16031609
16041610 func $f8_2 ($a,$i) = if (($i >= $s))
16051611 then $a
16061612 else throw("List size exceeds 10")
16071613
16081614 $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)
16091615 } ++ [StringEntry("static_tokenIds", assetIdsStr), StringEntry("static_feeToken", feeAssetStr), StringEntry("static_tokenWeights", assetWeightsStr), IntegerEntry("static_tokensAmount", size(newAssetIds)), IntegerEntry("static_KMult", newKMult)])
16101616 }
16111617 }
16121618
16131619
16141620 @Verifier(tx)
1615-func verify () = if ((valueOrElse(getInteger("global_wasPreInited"), 0) == 0))
1616- then sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
1621+func verify () = if (if ((valueOrElse(getInteger("global_wasPreInited"), 0) == 0))
1622+ then if (sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey))
1623+ then true
1624+ else sigVerify(tx.bodyBytes, tx.proofs[0], masterPubKey)
1625+ else false)
1626+ then true
16171627 else match tx {
16181628 case tx: SetScriptTransaction =>
16191629 let scriptFull = value(tx.script)
16201630 let hash = toBase58String(sha256(scriptFull))
16211631 if (sigVerify(tx.bodyBytes, tx.proofs[0], masterPubKey))
16221632 then (valueOrElse(getInteger(coldMasterAddress, ("approvedScript_" + hash)), 0) > height)
16231633 else false
16241634 case _ =>
16251635 if (sigVerify(tx.bodyBytes, tx.proofs[0], masterPubKey))
16261636 then (valueOrElse(getInteger(coldMasterAddress, ("approvedTx_" + toBase58String(tx.id))), 0) > 0)
16271637 else false
16281638 }
16291639

github/deemru/w8io/6500d08 
290.27 ms