tx · H5i8EbwgnoT7454PvRmYuF3zCY4By548q8yg7vDFFp6d

3MA1DeVfqd2a4rK5JC8Cx3PEx7d2AZRvaGp:  -0.06000000 Waves

2026.05.04 19:01 [526120] smart account 3MA1DeVfqd2a4rK5JC8Cx3PEx7d2AZRvaGp > SELF 0.00000000 Waves

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

github/deemru/w8io
104.31 ms