tx · Ajom89W8cuwZjD2rJb91uyrTxnF149vusVg3H7cRstdv

3N9be2mwrA52WJho6DiesZkk4351GvpnWuj:  -0.04000000 Waves

2022.10.18 13:26 [2277712] smart account 3N9be2mwrA52WJho6DiesZkk4351GvpnWuj > SELF 0.00000000 Waves

{ "type": 13, "id": "Ajom89W8cuwZjD2rJb91uyrTxnF149vusVg3H7cRstdv", "fee": 4000000, "feeAssetId": null, "timestamp": 1666088861647, "version": 1, "sender": "3N9be2mwrA52WJho6DiesZkk4351GvpnWuj", "senderPublicKey": "6mzmbCza9iqbzxMEELcEA4Xc9NeF4CYpbTtz1zMK3C7x", "proofs": [ "4wxJTrPN5EUds1fTPoanqRexyxz4kh2VJobmNm7VMUGzPNUZX4QsGjQcskmH2ztrAfmjV6ijZinn7FktPSCKCHyd", "3CPjubERQdeK65h43urR5XVFsbYgzkBEWmgtpjqjcwjpkd5xNt9VeAeZ2fYro7mBHodjHJNdT8YYFV2eugW7Mfi1", "3EbBhwcHT3rkx5bwW14ec6BbGJC4Z4U386vi8gw7NCJaRUgNTCC3Byg9RxTkR31pbYNvDbnxCT3RvN6Vn2mJRuYW" ], "script": "base64:BgJXCAISDgoMCAgICAgIAQEBAQEBEgUKAwgIARIAEgASBQoDCAEIEgMKAQESBAoCAQgSABIFCgMIAQESBAoCAQESBAoCCAESBQoDCAEBEgYKBAgIAQESABIAqwEBD2dldFN0cmluZ09yRmFpbAIHYWRkcmVzcwNrZXkJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQdhZGRyZXNzBQNrZXkJALkJAgkAzAgCAgptYW5kYXRvcnkgCQDMCAIJAKUIAQUHYWRkcmVzcwkAzAgCAgEuCQDMCAIFA2tleQkAzAgCAg8gaXMgbm90IGRlZmluZWQFA25pbAIAAQVsY2FsYwEBbAkAuQgBBQFsAQ5nZXROdW1iZXJCeUtleQEDa2V5CQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFA2tleQAAAQ5nZXRTdHJpbmdCeUtleQEDa2V5CQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMFA2tleQIAAQxnZXRCb29sQnlLZXkBA2tleQkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzBQNrZXkHARhnZXROdW1iZXJCeUFkZHJlc3NBbmRLZXkCB2FkZHJlc3MDa2V5CQELdmFsdWVPckVsc2UCCQCaCAIFB2FkZHJlc3MFA2tleQAAARhnZXRTdHJpbmdCeUFkZHJlc3NBbmRLZXkCB2FkZHJlc3MDa2V5CQELdmFsdWVPckVsc2UCCQCdCAIJARFAZXh0ck5hdGl2ZSgxMDYyKQEFB2FkZHJlc3MFA2tleQIAARZnZXRCb29sQnlBZGRyZXNzQW5kS2V5AgdhZGRyZXNzA2tleQkBC3ZhbHVlT3JFbHNlAgkAmwgCBQdhZGRyZXNzBQNrZXkHAQlhc0FueUxpc3QBAXYEByRtYXRjaDAFAXYDCQABAgUHJG1hdGNoMAIJTGlzdFtBbnldBAFsBQckbWF0Y2gwBQFsCQACAQIbZmFpbCB0byBjYXN0IGludG8gTGlzdFtBbnldAQhhc1N0cmluZwEBdgQHJG1hdGNoMAUBdgMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAXMFByRtYXRjaDAFAXMJAAIBAhhmYWlsIHRvIGNhc3QgaW50byBTdHJpbmcBBWFzSW50AQF2BAckbWF0Y2gwBQF2AwkAAQIFByRtYXRjaDACA0ludAQBaQUHJG1hdGNoMAUBaQkAAgECFWZhaWwgdG8gY2FzdCBpbnRvIEludAEHYXNCeXRlcwEDdmFsBAckbWF0Y2gwBQN2YWwDCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQHdmFsQnl0ZQUHJG1hdGNoMAUHdmFsQnl0ZQkAAgECHGZhaWwgdG8gY2FzdCBpbnRvIEJ5dGVWZWN0b3IBCWFzUGF5bWVudAEBdgQHJG1hdGNoMAUBdgMJAAECBQckbWF0Y2gwAg9BdHRhY2hlZFBheW1lbnQEAXAFByRtYXRjaDAFAXAJAAIBAiFmYWlsIHRvIGNhc3QgaW50byBBdHRhY2hlZFBheW1lbnQBEmFzU3dhcFBhcmFtc1NUUlVDVAEBdgQHJG1hdGNoMAUBdgMJAAECBQckbWF0Y2gwAiMoSW50LCBJbnQsIEludCwgSW50LCBJbnQsIEludCwgSW50KQQGc3RydWN0BQckbWF0Y2gwBQZzdHJ1Y3QJAAIBAh1mYWlsIHRvIGNhc3QgaW50byBUdXBsZTUgaW50cwADU0VQAgJfXwAHV0FWRUxFVACAwtcvAAVQQVVMSQDAhD0ACFBSSUNFTEVUAMCEPQAOREVGQVVMVFNXQVBGRUUAoJwBAAtCUlBST1RFQ1RFRACgjQYADElkeE5ldEFtb3VudAAAAAxJZHhGZWVBbW91bnQAAQAOSWR4R3Jvc3NBbW91bnQAAgAZSWR4Q29udHJvbENmZ05ldXRyaW5vRGFwcAABABhJZHhDb250cm9sQ2ZnQXVjdGlvbkRhcHAAAgAUSWR4Q29udHJvbENmZ1JwZERhcHAAAwAVSWR4Q29udHJvbENmZ01hdGhEYXBwAAQAHElkeENvbnRyb2xDZmdMaXF1aWRhdGlvbkRhcHAABQAVSWR4Q29udHJvbENmZ1Jlc3REYXBwAAYAHUlkeENvbnRyb2xDZmdOb2RlUmVnaXN0cnlEYXBwAAcAHElkeENvbnRyb2xDZmdOc2J0U3Rha2luZ0RhcHAACAAZSWR4Q29udHJvbENmZ01lZGlhdG9yRGFwcAAJABxJZHhDb250cm9sQ2ZnU3VyZlN0YWtpbmdEYXBwAAoAIElkeENvbnRyb2xDZmdHbnNidENvbnRyb2xsZXJEYXBwAAsAF0lkeENvbnRyb2xDZmdSZXN0VjJEYXBwAAwAG0lkeENvbnRyb2xDZmdHb3Zlcm5hbmNlRGFwcAANARFrZXlDb250cm9sQWRkcmVzcwACHCVzJXNfX2NvbmZpZ19fY29udHJvbEFkZHJlc3MBDWtleUNvbnRyb2xDZmcAAhElc19fY29udHJvbENvbmZpZwEUcmVhZENvbnRyb2xDZmdPckZhaWwBB2NvbnRyb2wJALwJAgkBD2dldFN0cmluZ09yRmFpbAIFB2NvbnRyb2wJAQ1rZXlDb250cm9sQ2ZnAAUDU0VQARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCCmNvbnRyb2xDZmcDaWR4CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkAkQMCBQpjb250cm9sQ2ZnBQNpZHgJAKwCAgItQ29udHJvbCBjZmcgZG9lc24ndCBjb250YWluIGFkZHJlc3MgYXQgaW5kZXggCQCkAwEFA2lkeAAPY29udHJvbENvbnRyYWN0CQERQGV4dHJOYXRpdmUoMTA2MikBCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMJARFrZXlDb250cm9sQWRkcmVzcwACIzNONE5TN2Q0Sm85YTZGMTRMaUZVS0tZVmRVa2tmMmVQNFp4AApjb250cm9sQ2ZnCQEUcmVhZENvbnRyb2xDZmdPckZhaWwBBQ9jb250cm9sQ29udHJhY3QADG1hdGhDb250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFCmNvbnRyb2xDZmcFFUlkeENvbnRyb2xDZmdNYXRoRGFwcAATbnNidFN0YWtpbmdDb250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFCmNvbnRyb2xDZmcFHElkeENvbnRyb2xDZmdOc2J0U3Rha2luZ0RhcHAAE3N1cmZTdGFraW5nQ29udHJhY3QJARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCBQpjb250cm9sQ2ZnBRxJZHhDb250cm9sQ2ZnU3VyZlN0YWtpbmdEYXBwABdnbnNidENvbnRyb2xsZXJDb250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFCmNvbnRyb2xDZmcFIElkeENvbnRyb2xDZmdHbnNidENvbnRyb2xsZXJEYXBwAA9hdWN0aW9uQ29udHJhY3QJARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCBQpjb250cm9sQ2ZnBRhJZHhDb250cm9sQ2ZnQXVjdGlvbkRhcHAAFG5vZGVSZWdpc3RyeUNvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUKY29udHJvbENmZwUdSWR4Q29udHJvbENmZ05vZGVSZWdpc3RyeURhcHAAEmdvdmVybmFuY2VDb250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFCmNvbnRyb2xDZmcFG0lkeENvbnRyb2xDZmdHb3Zlcm5hbmNlRGFwcAASTmV1dHJpbm9Bc3NldElkS2V5AhFuZXV0cmlub19hc3NldF9pZAAOQm9uZEFzc2V0SWRLZXkCDWJvbmRfYXNzZXRfaWQAEkF1Y3Rpb25Db250cmFjdEtleQIQYXVjdGlvbl9jb250cmFjdAAWTnNidFN0YWtpbmdDb250cmFjdEtleQITbnNidFN0YWtpbmdDb250cmFjdAAWTGlxdWlkYXRpb25Db250cmFjdEtleQIUbGlxdWlkYXRpb25fY29udHJhY3QADlJQRENvbnRyYWN0S2V5AgxycGRfY29udHJhY3QAEUNvbnRvbENvbnRyYWN0S2V5AhBjb250cm9sX2NvbnRyYWN0AA9NYXRoQ29udHJhY3RLZXkCDW1hdGhfY29udHJhY3QAG0JhbGFuY2VXYXZlc0xvY2tJbnRlcnZhbEtleQIbYmFsYW5jZV93YXZlc19sb2NrX2ludGVydmFsAB5CYWxhbmNlTmV1dHJpbm9Mb2NrSW50ZXJ2YWxLZXkCHmJhbGFuY2VfbmV1dHJpbm9fbG9ja19pbnRlcnZhbAAVTWluV2F2ZXNTd2FwQW1vdW50S2V5AhVtaW5fd2F2ZXNfc3dhcF9hbW91bnQAGE1pbk5ldXRyaW5vU3dhcEFtb3VudEtleQIYbWluX25ldXRyaW5vX3N3YXBfYW1vdW50ABtOb2RlT3JhY2xlUHJvdmlkZXJQdWJLZXlLZXkCFG5vZGVfb3JhY2xlX3Byb3ZpZGVyABVOZXV0cmlub091dEZlZVBhcnRLZXkCGG5ldXRyaW5vT3V0X3N3YXBfZmVlUGFydAASV2F2ZXNPdXRGZWVQYXJ0S2V5AhV3YXZlc091dF9zd2FwX2ZlZVBhcnQBD2tleU5vZGVSZWdpc3RyeQEHYWRkcmVzcwkArAICAgQlc19fBQdhZGRyZXNzAAhQcmljZUtleQIFcHJpY2UADVByaWNlSW5kZXhLZXkCC3ByaWNlX2luZGV4AAxJc0Jsb2NrZWRLZXkCCmlzX2Jsb2NrZWQBEmdldFByaWNlSGlzdG9yeUtleQEFYmxvY2sJAKwCAgkArAICBQhQcmljZUtleQIBXwkApAMBBQVibG9jawEYZ2V0SGVpZ2h0UHJpY2VCeUluZGV4S2V5AQVpbmRleAkArAICCQCsAgIFDVByaWNlSW5kZXhLZXkCAV8JAKQDAQUFaW5kZXgBFWdldFN0YWtpbmdOb2RlQnlJbmRleAEDaWR4CQEOZ2V0U3RyaW5nQnlLZXkBCQC5CQIJAMwIAgIGJXMlZCVzCQDMCAICBWxlYXNlCQDMCAIJAKQDAQUDaWR4CQDMCAICC25vZGVBZGRyZXNzBQNuaWwFA1NFUAEcZ2V0U3Rha2luZ05vZGVBZGRyZXNzQnlJbmRleAEDaWR4CQERQGV4dHJOYXRpdmUoMTA2MikBCQEVZ2V0U3Rha2luZ05vZGVCeUluZGV4AQUDaWR4AR9nZXRSZXNlcnZlZEFtb3VudEZvclNwb25zb3JzaGlwAAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQC5CQIJAMwIAgIEJXMlcwkAzAgCAgVsZWFzZQkAzAgCAhdzcG9uc29yc2hpcFdhdmVzUmVzZXJ2ZQUDbmlsBQNTRVAJAGgCAOgHBQdXQVZFTEVUARhnZXRCYWxhbmNlVW5sb2NrQmxvY2tLZXkBBW93bmVyCQCsAgICFWJhbGFuY2VfdW5sb2NrX2Jsb2NrXwUFb3duZXIBDWdldExlYXNlSWRLZXkBCW5vZGVJbmRleAkAuQkCCQDMCAICBiVzJWQlcwkAzAgCAgVsZWFzZQkAzAgCCQCkAwEFCW5vZGVJbmRleAkAzAgCAgJpZAUDbmlsBQNTRVABFmdldExlYXNlSWRCeUFkZHJlc3NLZXkBC25vZGVBZGRyZXNzCQC5CQIJAMwIAgIGJXMlcyVzCQDMCAICDmxlYXNlQnlBZGRyZXNzCQDMCAIFC25vZGVBZGRyZXNzCQDMCAICAmlkBQNuaWwFA1NFUAERZ2V0TGVhc2VBbW91bnRLZXkBCW5vZGVJbmRleAkAuQkCCQDMCAICBiVzJWQlcwkAzAgCAgVsZWFzZQkAzAgCCQCkAwEFCW5vZGVJbmRleAkAzAgCAgZhbW91bnQFA25pbAUDU0VQARpnZXRMZWFzZUFtb3VudEJ5QWRkcmVzc0tleQELbm9kZUFkZHJlc3MJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgIObGVhc2VCeUFkZHJlc3MJAMwIAgULbm9kZUFkZHJlc3MJAMwIAgIGYW1vdW50BQNuaWwFA1NFUAEYZ2V0TGVhc2VHcm91cE5vZGVMaXN0S2V5AQhncm91cE51bQkAuQkCCQDMCAICBiVzJWQlcwkAzAgCAgpsZWFzZUdyb3VwCQDMCAIJAKQDAQUIZ3JvdXBOdW0JAMwIAgIIbm9kZUxpc3QFA25pbAUDU0VQARBtaW5Td2FwQW1vdW50S0VZAQhzd2FwVHlwZQkArAICCQCsAgICBG1pbl8FCHN3YXBUeXBlAgxfc3dhcF9hbW91bnQBDnRvdGFsTG9ja2VkS0VZAQhzd2FwVHlwZQkArAICAg1iYWxhbmNlX2xvY2tfBQhzd2FwVHlwZQEUdG90YWxMb2NrZWRCeVVzZXJLRVkCCHN3YXBUeXBlBW93bmVyCQC5CQIJAMwIAgIMYmFsYW5jZV9sb2NrCQDMCAIFCHN3YXBUeXBlCQDMCAIFBW93bmVyBQNuaWwCAV8BFmJhbGFuY2VMb2NrSW50ZXJ2YWxLRVkBCHN3YXBUeXBlCQCsAgIJAKwCAgIIYmFsYW5jZV8FCHN3YXBUeXBlAg5fbG9ja19pbnRlcnZhbAEabm9kZUJhbGFuY2VMb2NrSW50ZXJ2YWxLRVkAAhpiYWxhbmNlX25vZGVfbG9ja19pbnRlcnZhbAENb3V0RmVlUGFydEtFWQEIc3dhcFR5cGUJAKwCAgUIc3dhcFR5cGUCEE91dF9zd2FwX2ZlZVBhcnQBEXN3YXBzVGltZWZyYW1lS0VZAAIPc3dhcHNfdGltZWZyYW1lAQ5iclByb3RlY3RlZEtFWQACF21pbl9CUl9wcm90ZWN0aW9uX2xldmVsARFtaW5Td2FwQW1vdW50UkVBRAEIc3dhcFR5cGUJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBEG1pblN3YXBBbW91bnRLRVkBBQhzd2FwVHlwZQAAARJzd2Fwc1RpbWVmcmFtZVJFQUQACQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJARFzd2Fwc1RpbWVmcmFtZUtFWQAAoAsBD3RvdGFsTG9ja2VkUkVBRAEIc3dhcFR5cGUJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBDnRvdGFsTG9ja2VkS0VZAQUIc3dhcFR5cGUAAAEVdG90YWxMb2NrZWRCeVVzZXJSRUFEAghzd2FwVHlwZQVvd25lcgkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEUdG90YWxMb2NrZWRCeVVzZXJLRVkCBQhzd2FwVHlwZQUFb3duZXIAAAEXYmFsYW5jZUxvY2tJbnRlcnZhbFJFQUQBCHN3YXBUeXBlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJARZiYWxhbmNlTG9ja0ludGVydmFsS0VZAQUIc3dhcFR5cGUAoAsBG25vZGVCYWxhbmNlTG9ja0ludGVydmFsUkVBRAAJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBGm5vZGVCYWxhbmNlTG9ja0ludGVydmFsS0VZAAABARhrZXlTd2FwVXNlclNwZW50SW5QZXJpb2QBC3VzZXJBZGRyZXNzCQC5CQIJAMwIAgIEJXMlcwkAzAgCAhVzd2FwVXNlclNwZW50SW5QZXJpb2QJAMwIAgULdXNlckFkZHJlc3MFA25pbAUDU0VQARVrZXlVc2VyTGFzdFN3YXBIZWlnaHQBC3VzZXJBZGRyZXNzCQC5CQIJAMwIAgIEJXMlcwkAzAgCAhJ1c2VyTGFzdFN3YXBIZWlnaHQJAMwIAgULdXNlckFkZHJlc3MFA25pbAUDU0VQARZjb252ZXJ0TmV1dHJpbm9Ub1dhdmVzAgZhbW91bnQFcHJpY2UJAGsDCQBrAwUGYW1vdW50BQhQUklDRUxFVAUFcHJpY2UFB1dBVkVMRVQFBVBBVUxJARZjb252ZXJ0V2F2ZXNUb05ldXRyaW5vAgZhbW91bnQFcHJpY2UJAGsDCQBrAwUGYW1vdW50BQVwcmljZQUIUFJJQ0VMRVQFBVBBVUxJBQdXQVZFTEVUARJjb252ZXJ0V2F2ZXNUb0JvbmQCBmFtb3VudAVwcmljZQkBFmNvbnZlcnRXYXZlc1RvTmV1dHJpbm8CBQZhbW91bnQFBXByaWNlARZjb252ZXJ0SnNvbkFycmF5VG9MaXN0AQlqc29uQXJyYXkJALUJAgUJanNvbkFycmF5AgEsARFtaW5Td2FwQW1vdW50RkFJTAIIc3dhcFR5cGUNbWluU3dhcEFtb3VudAkAAgEJAKwCAgkArAICCQCsAgICGFRoZSBzcGVjaWZpZWQgYW1vdW50IGluIAUIc3dhcFR5cGUCKyBzd2FwIGlzIGxlc3MgdGhhbiB0aGUgcmVxdWlyZWQgbWluaW11bSBvZiAJAKQDAQUNbWluU3dhcEFtb3VudAEVZW1lcmdlbmN5U2h1dGRvd25GQUlMAAkAAgECWmNvbnRyYWN0IGlzIGJsb2NrZWQgYnkgRU1FUkdFTkNZIFNIVVRET1dOIGFjdGlvbnMgdW50aWxsIHJlYWN0aXZhdGlvbiBieSBlbWVyZ2VuY3kgb3JhY2xlcwEOcHJpY2VJbmRleEZBSUwFBWluZGV4CnByaWNlSW5kZXgLaW5kZXhIZWlnaHQMdW5sb2NrSGVpZ2h0D3ByZXZJbmRleEhlaWdodAkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICI2ludmFsaWQgcHJpY2UgaGlzdG9yeSBpbmRleDogaW5kZXg9CQCkAwEFBWluZGV4AgwgcHJpY2VJbmRleD0JAKQDAQUKcHJpY2VJbmRleAINIGluZGV4SGVpZ2h0PQkApAMBBQtpbmRleEhlaWdodAIOIHVubG9ja0hlaWdodD0JAKQDAQUMdW5sb2NrSGVpZ2h0AhEgcHJldkluZGV4SGVpZ2h0PQkApAMBBQ9wcmV2SW5kZXhIZWlnaHQAD25ldXRyaW5vQXNzZXRJZAkA2QQBCQEOZ2V0U3RyaW5nQnlLZXkBBRJOZXV0cmlub0Fzc2V0SWRLZXkACnByaWNlSW5kZXgJARhnZXROdW1iZXJCeUFkZHJlc3NBbmRLZXkCBQ9jb250cm9sQ29udHJhY3QFDVByaWNlSW5kZXhLZXkACWlzQmxvY2tlZAkBFmdldEJvb2xCeUFkZHJlc3NBbmRLZXkCBQ9jb250cm9sQ29udHJhY3QFDElzQmxvY2tlZEtleQAYbm9kZU9yYWNsZVByb3ZpZGVyUHViS2V5CQDZBAEJAQ5nZXRTdHJpbmdCeUtleQEFG05vZGVPcmFjbGVQcm92aWRlclB1YktleUtleQALYm9uZEFzc2V0SWQJANkEAQIsRjNpYXh6cnVGZUt1amZWZllTWkVrZWpwamg2N3dtUmZQQ1JIaU5tV0twM1oAFWRlcHJlY2F0ZWRCb25kQXNzZXRJZAkA2QQBAiw5NzVha1pCZm5NajUxM1U3TVphSEt6UXJtc0V4NWFFM3dkV0tUckhCaGJqRgAQbmV1dHJpbm9Db250cmFjdAUEdGhpcwAMY3VycmVudFByaWNlCQEYZ2V0TnVtYmVyQnlBZGRyZXNzQW5kS2V5AgUPY29udHJvbENvbnRyYWN0BQhQcmljZUtleQEbY2hlY2tJc1ZhbGlkTWluU3BvbnNvcmVkRmVlAQJ0eAQOTUlOVFJBTlNGRVJGRUUAoI0GBBZTcG9uc29yZWRGZWVVcHBlckJvdW5kAOgHBA9yZWFsTmV1dHJpbm9GZWUJARZjb252ZXJ0V2F2ZXNUb05ldXRyaW5vAgUOTUlOVFJBTlNGRVJGRUUFDGN1cnJlbnRQcmljZQQObWluTmV1dHJpbm9GZWUJAGgCBQ9yZWFsTmV1dHJpbm9GZWUAAgQObWF4TmV1dHJpbm9GZWUJAGsDBQ9yZWFsTmV1dHJpbm9GZWUFFlNwb25zb3JlZEZlZVVwcGVyQm91bmQAZAQIaW5wdXRGZWUJAQV2YWx1ZQEIBQJ0eBRtaW5TcG9uc29yZWRBc3NldEZlZQMDCQBnAgUIaW5wdXRGZWUFDm1pbk5ldXRyaW5vRmVlCQBnAgUObWF4TmV1dHJpbm9GZWUFCGlucHV0RmVlBwkAAAIIBQJ0eAdhc3NldElkBQ9uZXV0cmlub0Fzc2V0SWQHAQ9nZXRQcmljZUhpc3RvcnkBBWJsb2NrCQEYZ2V0TnVtYmVyQnlBZGRyZXNzQW5kS2V5AgUPY29udHJvbENvbnRyYWN0CQESZ2V0UHJpY2VIaXN0b3J5S2V5AQUFYmxvY2sBFWdldEhlaWdodFByaWNlQnlJbmRleAEFaW5kZXgJARhnZXROdW1iZXJCeUFkZHJlc3NBbmRLZXkCBQ9jb250cm9sQ29udHJhY3QJARhnZXRIZWlnaHRQcmljZUJ5SW5kZXhLZXkBBQVpbmRleAEWa2V5TG9ja1BhcmFtVXNlckFtb3VudAELdXNlckFkZHJlc3MJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgILcGFyYW1CeVVzZXIJAMwIAgULdXNlckFkZHJlc3MJAMwIAgIGYW1vdW50BQNuaWwFA1NFUAAMc0lkeFN3YXBUeXBlAAEACnNJZHhTdGF0dXMAAgAMc0lkeEluQW1vdW50AAMACXNJZHhQcmljZQAEABBzSWR4T3V0TmV0QW1vdW50AAUAEHNJZHhPdXRGZWVBbW91bnQABgAPc0lkeFN0YXJ0SGVpZ2h0AAcAEnNJZHhTdGFydFRpbWVzdGFtcAAIAA1zSWR4RW5kSGVpZ2h0AAkAEHNJZHhFbmRUaW1lc3RhbXAACgAUc0lkeFNlbGZVbmxvY2tIZWlnaHQACwAUc0lkeFJhbmRVbmxvY2tIZWlnaHQADAAJc0lkeEluZGV4AA0AEHNJZHhXaXRoZHJhd1R4SWQADgALc0lkeE1pblJhbmQADwALc0lkeE1heFJhbmQAEAARc0lkeE91dFN1cmZBbW91bnQAEQAGc0lkeEJSABIBB3N3YXBLRVkCC3VzZXJBZGRyZXNzBHR4SWQJALkJAgkAzAgCAgQlcyVzCQDMCAIFC3VzZXJBZGRyZXNzCQDMCAIFBHR4SWQFA25pbAUDU0VQAQtzdHJTd2FwREFUQRIIc3dhcFR5cGUGc3RhdHVzCGluQW1vdW50BXByaWNlDG91dE5ldEFtb3VudAxvdXRGZWVBbW91bnQLc3RhcnRIZWlnaHQOc3RhcnRUaW1lc3RhbXAJZW5kSGVpZ2h0DGVuZFRpbWVzdGFtcBBzZWxmVW5sb2NrSGVpZ2h0EHJhbmRVbmxvY2tIZWlnaHQFaW5kZXgMd2l0aGRyYXdUeElkB3JhbmRNaW4HcmFuZE1heApvdXRTdXJmQW10AmJyCQC5CQIJAMwIAgIkJXMlcyVkJWQlZCVkJWQlZCVkJWQlZCVkJWQlcyVkJWQlZCVkCQDMCAIFCHN3YXBUeXBlCQDMCAIFBnN0YXR1cwkAzAgCBQhpbkFtb3VudAkAzAgCBQVwcmljZQkAzAgCBQxvdXROZXRBbW91bnQJAMwIAgUMb3V0RmVlQW1vdW50CQDMCAIFC3N0YXJ0SGVpZ2h0CQDMCAIFDnN0YXJ0VGltZXN0YW1wCQDMCAIFCWVuZEhlaWdodAkAzAgCBQxlbmRUaW1lc3RhbXAJAMwIAgUQc2VsZlVubG9ja0hlaWdodAkAzAgCBRByYW5kVW5sb2NrSGVpZ2h0CQDMCAIFBWluZGV4CQDMCAIFDHdpdGhkcmF3VHhJZAkAzAgCBQdyYW5kTWluCQDMCAIFB3JhbmRNYXgJAMwIAgUKb3V0U3VyZkFtdAkAzAgCBQJicgUDbmlsBQNTRVABD3BlbmRpbmdTd2FwREFUQQMIc3dhcFR5cGUNaW5Bc3NldEFtb3VudBBzZWxmVW5sb2NrSGVpZ2h0CQELc3RyU3dhcERBVEESBQhzd2FwVHlwZQIHUEVORElORwkApAMBBQ1pbkFzc2V0QW1vdW50AgEwAgEwAgEwCQCkAwEFBmhlaWdodAkApAMBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAIBMAIBMAkApAMBBRBzZWxmVW5sb2NrSGVpZ2h0AgEwAgEwAgROVUxMAgEwAgEwAgEwAgEwAQ5maW5pc2hTd2FwREFUQQkJZGF0YUFycmF5BXByaWNlDG91dE5ldEFtb3VudAxvdXRGZWVBbW91bnQQcmFuZFVubG9ja0hlaWdodAVpbmRleAx3aXRoZHJhd1R4SWQKb3V0U3VyZkFtdAJicgkBC3N0clN3YXBEQVRBEgkAkQMCBQlkYXRhQXJyYXkFDHNJZHhTd2FwVHlwZQIIRklOSVNIRUQJAJEDAgUJZGF0YUFycmF5BQxzSWR4SW5BbW91bnQJAKQDAQUFcHJpY2UJAKQDAQUMb3V0TmV0QW1vdW50CQCkAwEFDG91dEZlZUFtb3VudAkAkQMCBQlkYXRhQXJyYXkFD3NJZHhTdGFydEhlaWdodAkAkQMCBQlkYXRhQXJyYXkFEnNJZHhTdGFydFRpbWVzdGFtcAkApAMBBQZoZWlnaHQJAKQDAQgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAJEDAgUJZGF0YUFycmF5BRRzSWR4U2VsZlVubG9ja0hlaWdodAkApAMBBRByYW5kVW5sb2NrSGVpZ2h0CQCkAwEFBWluZGV4BQx3aXRoZHJhd1R4SWQJAJEDAgUJZGF0YUFycmF5BQtzSWR4TWluUmFuZAkAkQMCBQlkYXRhQXJyYXkFC3NJZHhNYXhSYW5kCQCkAwEFCm91dFN1cmZBbXQJAKQDAQUCYnIBEnN3YXBEYXRhRmFpbE9yUkVBRAILdXNlckFkZHJlc3MIc3dhcFR4SWQEB3N3YXBLZXkJAQdzd2FwS0VZAgULdXNlckFkZHJlc3MFCHN3YXBUeElkCQC1CQIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQR0aGlzBQdzd2FwS2V5CQCsAgICEW5vIHN3YXAgZGF0YSBmb3IgBQdzd2FwS2V5BQNTRVABCWFwcGx5RmVlcwMOYW1vdW50T3V0R3Jvc3MLaW5BbXRUb1NVUkYHZmVlUGFydAQJZmVlQW1vdW50CQBrAwUOYW1vdW50T3V0R3Jvc3MFB2ZlZVBhcnQFBVBBVUxJCQDMCAIJAGUCBQ5hbW91bnRPdXRHcm9zcwUJZmVlQW1vdW50CQDMCAIFCWZlZUFtb3VudAUDbmlsAQNhYnMBAXgDCQBmAgAABQF4CQEBLQEFAXgFAXgBCnNlbGVjdE5vZGUBDXVubGVhc2VBbW91bnQEDWFtb3VudFRvTGVhc2UJAGUCCQBlAggJAO8HAQUQbmV1dHJpbm9Db250cmFjdAlhdmFpbGFibGUFDXVubGVhc2VBbW91bnQJAR9nZXRSZXNlcnZlZEFtb3VudEZvclNwb25zb3JzaGlwAAQKb2xkTGVhc2VkMAkBDmdldE51bWJlckJ5S2V5AQkBEWdldExlYXNlQW1vdW50S2V5AQAABApvbGRMZWFzZWQxCQEOZ2V0TnVtYmVyQnlLZXkBCQERZ2V0TGVhc2VBbW91bnRLZXkBAAEECm5ld0xlYXNlZDAJAGQCBQ1hbW91bnRUb0xlYXNlBQpvbGRMZWFzZWQwBApuZXdMZWFzZWQxCQBkAgUNYW1vdW50VG9MZWFzZQUKb2xkTGVhc2VkMQMDCQBmAgUKbmV3TGVhc2VkMAAABgkAZgIFCm5ld0xlYXNlZDEAAAQGZGVsdGEwCQEDYWJzAQkAZQIFCm5ld0xlYXNlZDAFCm9sZExlYXNlZDEEBmRlbHRhMQkBA2FicwEJAGUCBQpuZXdMZWFzZWQxBQpvbGRMZWFzZWQwAwkAZwIFBmRlbHRhMQUGZGVsdGEwCQCUCgIAAAUKbmV3TGVhc2VkMAkAlAoCAAEFCm5ld0xlYXNlZDEJAJQKAgD///////////8BAAABCHRoaXNPbmx5AQFpAwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQItUGVybWlzc2lvbiBkZW5pZWQ6IHRoaXMgY29udHJhY3Qgb25seSBhbGxvd2VkBgEWcHJlcGFyZVVubGVhc2VBbmRMZWFzZQENdW5sZWFzZUFtb3VudAQJbm9kZVR1cGxlCQEKc2VsZWN0Tm9kZQEFDXVubGVhc2VBbW91bnQECW5vZGVJbmRleAgFCW5vZGVUdXBsZQJfMQQObmV3TGVhc2VBbW91bnQIBQlub2RlVHVwbGUCXzIDCQBmAgUObmV3TGVhc2VBbW91bnQAAAQKbGVhc2VJZEtleQkBDWdldExlYXNlSWRLZXkBBQlub2RlSW5kZXgECG9sZExlYXNlCQCcCAIFBHRoaXMFCmxlYXNlSWRLZXkEDnVubGVhc2VPckVtcHR5AwkBCWlzRGVmaW5lZAEFCG9sZExlYXNlCQDMCAIJAQtMZWFzZUNhbmNlbAEJAQV2YWx1ZQEFCG9sZExlYXNlBQNuaWwFA25pbAQObGVhc2VBbW91bnRLZXkJARFnZXRMZWFzZUFtb3VudEtleQEFCW5vZGVJbmRleAQFbGVhc2UJAMQIAgkBHGdldFN0YWtpbmdOb2RlQWRkcmVzc0J5SW5kZXgBBQlub2RlSW5kZXgFDm5ld0xlYXNlQW1vdW50CQDOCAIFDnVubGVhc2VPckVtcHR5CQDMCAIFBWxlYXNlCQDMCAIJAQtCaW5hcnlFbnRyeQIFCmxlYXNlSWRLZXkJAQVsY2FsYwEFBWxlYXNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQERZ2V0TGVhc2VBbW91bnRLZXkBBQlub2RlSW5kZXgFDm5ld0xlYXNlQW1vdW50BQNuaWwFA25pbAEMcmVhZE5vZGVJbmZvAQdub2RlSWR4BAtub2RlQWRkcmVzcwkBHGdldFN0YWtpbmdOb2RlQWRkcmVzc0J5SW5kZXgBBQdub2RlSWR4BAxsZWFzZWRBbXRLRVkJARFnZXRMZWFzZUFtb3VudEtleQEFB25vZGVJZHgECWxlYXNlZEFtdAkBDmdldE51bWJlckJ5S2V5AQUMbGVhc2VkQW10S0VZBApsZWFzZUlkS0VZCQENZ2V0TGVhc2VJZEtleQEFB25vZGVJZHgEB2xlYXNlSWQJAQV2YWx1ZQEJAJwIAgUEdGhpcwUKbGVhc2VJZEtFWQkAlwoFBQtub2RlQWRkcmVzcwUMbGVhc2VkQW10S0VZBQlsZWFzZWRBbXQFCmxlYXNlSWRLRVkFB2xlYXNlSWQBCmNvbW1vblN3YXAFCHN3YXBUeXBlCXBtdEFtb3VudA51c2VyQWRkcmVzc1N0cgZ0eElkNTgbc3dhcFBhcmFtc0J5VXNlclNZU1JFQURPTkxZBA5zd2FwTGltaXRTcGVudAgFG3N3YXBQYXJhbXNCeVVzZXJTWVNSRUFET05MWQJfMgQOYmxja3MyTG10UmVzZXQIBRtzd2FwUGFyYW1zQnlVc2VyU1lTUkVBRE9OTFkCXzMEEXdhdmVzU3dhcExpbWl0TWF4CAUbc3dhcFBhcmFtc0J5VXNlclNZU1JFQURPTkxZAl82BBB1c2RuU3dhcExpbWl0TWF4CAUbc3dhcFBhcmFtc0J5VXNlclNZU1JFQURPTkxZAl83BA1taW5Td2FwQW1vdW50CQERbWluU3dhcEFtb3VudFJFQUQBBQhzd2FwVHlwZQQLdG90YWxMb2NrZWQJAQ90b3RhbExvY2tlZFJFQUQBBQhzd2FwVHlwZQQRdG90YWxMb2NrZWRCeVVzZXIJARV0b3RhbExvY2tlZEJ5VXNlclJFQUQCBQhzd2FwVHlwZQUOdXNlckFkZHJlc3NTdHIEC25vZGVBZGRyZXNzCQEVZ2V0U3Rha2luZ05vZGVCeUluZGV4AQAABAxwcmljZUJ5SW5kZXgJAQ9nZXRQcmljZUhpc3RvcnkBCQEVZ2V0SGVpZ2h0UHJpY2VCeUluZGV4AQUKcHJpY2VJbmRleAQMaXNTd2FwQnlOb2RlCQAAAgULbm9kZUFkZHJlc3MFDnVzZXJBZGRyZXNzU3RyBBZiYWxhbmNlTG9ja01heEludGVydmFsAwUMaXNTd2FwQnlOb2RlCQEbbm9kZUJhbGFuY2VMb2NrSW50ZXJ2YWxSRUFEAAkBF2JhbGFuY2VMb2NrSW50ZXJ2YWxSRUFEAQUIc3dhcFR5cGUEEHNlbGZVbmxvY2tIZWlnaHQJAGQCBQZoZWlnaHQFFmJhbGFuY2VMb2NrTWF4SW50ZXJ2YWwEDnN3YXBVc2RuVm9sdW1lAwkAAAIFCHN3YXBUeXBlAghuZXV0cmlubwUJcG10QW1vdW50CQEWY29udmVydFdhdmVzVG9OZXV0cmlubwIFCXBtdEFtb3VudAUMcHJpY2VCeUluZGV4BAxzd2FwTGltaXRNYXgDCQAAAgUIc3dhcFR5cGUCCG5ldXRyaW5vBRB1c2RuU3dhcExpbWl0TWF4CQEWY29udmVydFdhdmVzVG9OZXV0cmlubwIFEXdhdmVzU3dhcExpbWl0TWF4BQxwcmljZUJ5SW5kZXgDCQBmAgUNbWluU3dhcEFtb3VudAUJcG10QW1vdW50CQERbWluU3dhcEFtb3VudEZBSUwCBQhzd2FwVHlwZQUNbWluU3dhcEFtb3VudAMDCQEBIQEFDGlzU3dhcEJ5Tm9kZQkAZgIFDnN3YXBMaW1pdFNwZW50AAAHCQACAQkArAICAjpZb3UgaGF2ZSBleGNlZWRlZCBzd2FwIGxpbWl0ISBOZXh0IGFsbG93ZWQgc3dhcCBoZWlnaHQgaXMgCQCkAwEJAGQCBQZoZWlnaHQFDmJsY2tzMkxtdFJlc2V0AwMJAQEhAQUMaXNTd2FwQnlOb2RlCQBmAgUOc3dhcFVzZG5Wb2x1bWUFDHN3YXBMaW1pdE1heAcJAAIBCQCsAgIJAKwCAgkArAICAi5Zb3UgaGF2ZSBleGNlZWRlZCB5b3VyIHN3YXAgbGltaXQhIFJlcXVlc3RlZDogCQCkAwEFDnN3YXBVc2RuVm9sdW1lAg0sIGF2YWlsYWJsZTogCQCkAwEFDHN3YXBMaW1pdE1heAMFCWlzQmxvY2tlZAkBFWVtZXJnZW5jeVNodXRkb3duRkFJTAAECWxlYXNlUGFydAMJAAACBQhzd2FwVHlwZQIFd2F2ZXMJARZwcmVwYXJlVW5sZWFzZUFuZExlYXNlAQAABQNuaWwJAJQKAgkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEYa2V5U3dhcFVzZXJTcGVudEluUGVyaW9kAQUOdXNlckFkZHJlc3NTdHIFDnN3YXBVc2RuVm9sdW1lCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEVa2V5VXNlckxhc3RTd2FwSGVpZ2h0AQUOdXNlckFkZHJlc3NTdHIFBmhlaWdodAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBFHRvdGFsTG9ja2VkQnlVc2VyS0VZAgUIc3dhcFR5cGUFDnVzZXJBZGRyZXNzU3RyCQBkAgURdG90YWxMb2NrZWRCeVVzZXIFCXBtdEFtb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBGGdldEJhbGFuY2VVbmxvY2tCbG9ja0tleQEFDnVzZXJBZGRyZXNzU3RyBRBzZWxmVW5sb2NrSGVpZ2h0CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG90YWxMb2NrZWRLRVkBBQhzd2FwVHlwZQkAZAIFC3RvdGFsTG9ja2VkBQlwbXRBbW91bnQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBB3N3YXBLRVkCBQ51c2VyQWRkcmVzc1N0cgUGdHhJZDU4CQEPcGVuZGluZ1N3YXBEQVRBAwUIc3dhcFR5cGUFCXBtdEFtb3VudAUQc2VsZlVubG9ja0hlaWdodAUDbmlsBQlsZWFzZVBhcnQFBHVuaXQAD25NZXRyaWNJZHhQcmljZQAAABtuTWV0cmljSWR4VXNkbkxvY2tlZEJhbGFuY2UAAQAcbk1ldHJpY0lkeFdhdmVzTG9ja2VkQmFsYW5jZQACABFuTWV0cmljSWR4UmVzZXJ2ZQADABduTWV0cmljSWR4UmVzZXJ2ZUluVXNkbgAEABRuTWV0cmljSWR4VXNkblN1cHBseQAFABFuTWV0cmljSWR4U3VycGx1cwAGABhuTWV0cmljSWR4U3VycGx1c1BlcmNlbnQABwAMbk1ldHJpY0lkeEJSAAgAFG5NZXRyaWNJZHhOc2J0U3VwcGx5AAkAF25NZXRyaWNJZHhNYXhOc2J0U3VwcGx5AAoAFG5NZXRyaWNJZHhTdXJmU3VwcGx5AAsADGJGdW5jSWR4U3VyZgAAAA1iRnVuY0lkeFdhdmVzAAEADGJGdW5jSWR4VXNkbgACABRiRnVuY0lkeFJlc2VydmVTdGFydAADABNiRnVuY0lkeFN1cHBseVN0YXJ0AAQAD2JGdW5jSWR4QlJTdGFydAAFABJiRnVuY0lkeFJlc2VydmVFbmQABgARYkZ1bmNJZHhTdXBwbHlFbmQABwANYkZ1bmNJZHhCUkVuZAAIAAxiRnVuY0lkeFJlc3QACQASYkZ1bmNJZHhXYXZlc1ByaWNlAAoBD2NhbGNXaXRoZHJhd1cyVQIHd2F2ZXNJbgVwcmljZQQLb3V0QW10R3Jvc3MJARZjb252ZXJ0V2F2ZXNUb05ldXRyaW5vAgUHd2F2ZXNJbgUFcHJpY2UJAJsKCQULb3V0QW10R3Jvc3MFD25ldXRyaW5vQXNzZXRJZAAABQR1bml0AAAFB3dhdmVzSW4AAAAAAAABD2NhbGNXaXRoZHJhd1UyVwUGdXNkbkluBXByaWNlAmJyDnJlc2VydmVzSW5Vc2RuCnVzZG5TdXBwbHkEC2JyUHJvdGVjdGVkCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQ5iclByb3RlY3RlZEtFWQAFC0JSUFJPVEVDVEVEBBltYXhBbGxvd2VkVXNkbkJlZm9yZU1pbkJyAwkAZwIFC2JyUHJvdGVjdGVkBQJicgAACQBrAwkAZQIFDnJlc2VydmVzSW5Vc2RuCQBrAwULYnJQcm90ZWN0ZWQFCnVzZG5TdXBwbHkFBVBBVUxJBQVQQVVMSQkAZQIFBVBBVUxJBQticlByb3RlY3RlZAQWYWxsb3dlZFVzZG5CZWZvcmVNaW5CcgMJAGYCBQZ1c2RuSW4FGW1heEFsbG93ZWRVc2RuQmVmb3JlTWluQnIFGW1heEFsbG93ZWRVc2RuQmVmb3JlTWluQnIFBnVzZG5JbgQVYWxsb3dlZFVzZG5BZnRlck1pbkJyAwkAZgIFBnVzZG5JbgUZbWF4QWxsb3dlZFVzZG5CZWZvcmVNaW5CcgkAawMJAGUCBQZ1c2RuSW4FGW1heEFsbG93ZWRVc2RuQmVmb3JlTWluQnIFAmJyBQVQQVVMSQAABAthbGxvd2VkVXNkbgkAZAIFFmFsbG93ZWRVc2RuQmVmb3JlTWluQnIFFWFsbG93ZWRVc2RuQWZ0ZXJNaW5CcgQJdXNkbjJTVVJGCQBlAgUGdXNkbkluBQthbGxvd2VkVXNkbgQLb3V0QW10R3Jvc3MJARZjb252ZXJ0TmV1dHJpbm9Ub1dhdmVzAgULYWxsb3dlZFVzZG4FBXByaWNlCQCbCgkFC291dEFtdEdyb3NzBQR1bml0BQl1c2RuMlNVUkYFD25ldXRyaW5vQXNzZXRJZAULb3V0QW10R3Jvc3MFC2FsbG93ZWRVc2RuBRltYXhBbGxvd2VkVXNkbkJlZm9yZU1pbkJyBRZhbGxvd2VkVXNkbkJlZm9yZU1pbkJyBRVhbGxvd2VkVXNkbkFmdGVyTWluQnIBDGNhbGNXaXRoZHJhdwQIc3dhcFR5cGUIaW5BbW91bnQFcHJpY2UPbmV1dHJpbm9NZXRyaWNzBApvdXRGZWVQYXJ0CQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQ1vdXRGZWVQYXJ0S0VZAQUIc3dhcFR5cGUFDkRFRkFVTFRTV0FQRkVFAwMJAGYCAAAFCm91dEZlZVBhcnQGCQBnAgUKb3V0RmVlUGFydAUFUEFVTEkJAAIBCQCsAgIJAKwCAgkArAICAh5pbnZhbGlkIG91dEZlZVBhcnQgY29uZmlnIGZvciAFCHN3YXBUeXBlAhIgc3dhcDogb3V0RmVlUGFydD0JAKQDAQUKb3V0RmVlUGFydAQLYnJQcm90ZWN0ZWQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBDmJyUHJvdGVjdGVkS0VZAAULQlJQUk9URUNURUQEAkJSCQEFYXNJbnQBCQCRAwIFD25ldXRyaW5vTWV0cmljcwUMbk1ldHJpY0lkeEJSBA5yZXNlcnZlc0luVXNkbgkBBWFzSW50AQkAkQMCBQ9uZXV0cmlub01ldHJpY3MFF25NZXRyaWNJZHhSZXNlcnZlSW5Vc2RuBAp1c2RuU3VwcGx5CQEFYXNJbnQBCQCRAwIFD25ldXRyaW5vTWV0cmljcwUUbk1ldHJpY0lkeFVzZG5TdXBwbHkEDG91dERhdGFUdXBsZQMJAAACBQhzd2FwVHlwZQIFd2F2ZXMJAQ9jYWxjV2l0aGRyYXdXMlUCBQhpbkFtb3VudAUFcHJpY2UDCQAAAgUIc3dhcFR5cGUCCG5ldXRyaW5vCQEPY2FsY1dpdGhkcmF3VTJXBQUIaW5BbW91bnQFBXByaWNlBQJCUgUOcmVzZXJ2ZXNJblVzZG4FCnVzZG5TdXBwbHkJAAIBCQCsAgICFlVuc3VwcG9ydGVkIHN3YXAgdHlwZSAFCHN3YXBUeXBlBAtvdXRBbXRHcm9zcwgFDG91dERhdGFUdXBsZQJfMQQKb3V0QXNzZXRJZAgFDG91dERhdGFUdXBsZQJfMgQPaW5BbXRUb1N1cmZQYXJ0CAUMb3V0RGF0YVR1cGxlAl8zBAlpbkFzc2V0SWQIBQxvdXREYXRhVHVwbGUCXzQECnVubGVhc2VBbXQIBQxvdXREYXRhVHVwbGUCXzUEDHBheW91dHNBcnJheQkBCWFwcGx5RmVlcwMFC291dEFtdEdyb3NzBQ9pbkFtdFRvU3VyZlBhcnQFCm91dEZlZVBhcnQECW91dE5ldEFtdAkAkQMCBQxwYXlvdXRzQXJyYXkFDElkeE5ldEFtb3VudAQJb3V0RmVlQW10CQCRAwIFDHBheW91dHNBcnJheQUMSWR4RmVlQW1vdW50BApvdXRTdXJmQW10AwkAZwIAAAUPaW5BbXRUb1N1cmZQYXJ0AAAECnN1cmZSZXN1bHQJAQlhc0FueUxpc3QBCQD8BwQFDG1hdGhDb250cmFjdAIUc3VyZkZ1bmN0aW9uUkVBRE9OTFkJAMwIAgUPaW5BbXRUb1N1cmZQYXJ0CQDMCAIFCWluQXNzZXRJZAUDbmlsBQNuaWwJAQVhc0ludAEJAJEDAgUKc3VyZlJlc3VsdAUMYkZ1bmNJZHhTdXJmCQCZCgcFCW91dE5ldEFtdAUKb3V0QXNzZXRJZAUKb3V0U3VyZkFtdAUPaW5BbXRUb1N1cmZQYXJ0BQp1bmxlYXNlQW10BQlvdXRGZWVBbXQFC291dEFtdEdyb3NzAQ5jb21tb25XaXRoZHJhdwUHYWNjb3VudAVpbmRleAhzd2FwVHhJZAx3aXRoZHJhd1R4SWQPbmV1dHJpbm9NZXRyaWNzBAt1c2VyQWRkcmVzcwkBEUBleHRyTmF0aXZlKDEwNjIpAQUHYWNjb3VudAQJZGF0YUFycmF5CQESc3dhcERhdGFGYWlsT3JSRUFEAgUHYWNjb3VudAUIc3dhcFR4SWQEEHNlbGZVbmxvY2tIZWlnaHQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQlkYXRhQXJyYXkFFHNJZHhTZWxmVW5sb2NrSGVpZ2h0BAhzd2FwVHlwZQkAkQMCBQlkYXRhQXJyYXkFDHNJZHhTd2FwVHlwZQQIaW5BbW91bnQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQlkYXRhQXJyYXkFDHNJZHhJbkFtb3VudAQKc3dhcFN0YXR1cwkAkQMCBQlkYXRhQXJyYXkFCnNJZHhTdGF0dXMEC3N0YXJ0SGVpZ2h0CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUJZGF0YUFycmF5BQ9zSWR4U3RhcnRIZWlnaHQECm91dEZlZVBhcnQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBDW91dEZlZVBhcnRLRVkBBQhzd2FwVHlwZQUOREVGQVVMVFNXQVBGRUUEC3RvdGFsTG9ja2VkCQEPdG90YWxMb2NrZWRSRUFEAQUIc3dhcFR5cGUEEXRvdGFsTG9ja2VkQnlVc2VyCQEVdG90YWxMb2NrZWRCeVVzZXJSRUFEAgUIc3dhcFR5cGUFB2FjY291bnQEDHVubG9ja0hlaWdodAUQc2VsZlVubG9ja0hlaWdodAQLaW5kZXhIZWlnaHQJARVnZXRIZWlnaHRQcmljZUJ5SW5kZXgBBQVpbmRleAQPcHJldkluZGV4SGVpZ2h0CQEVZ2V0SGVpZ2h0UHJpY2VCeUluZGV4AQkAZQIFBWluZGV4AAEEDHByaWNlQnlJbmRleAkBD2dldFByaWNlSGlzdG9yeQEFC2luZGV4SGVpZ2h0AwUJaXNCbG9ja2VkCQEVZW1lcmdlbmN5U2h1dGRvd25GQUlMAAMJAQIhPQIFCnN3YXBTdGF0dXMCB1BFTkRJTkcJAAIBAh9zd2FwIGhhcyBiZWVuIGFscmVhZHkgcHJvY2Vzc2VkAwkAZgIFDHVubG9ja0hlaWdodAUGaGVpZ2h0CQACAQkArAICCQCsAgICEXBsZWFzZSB3YWl0IGZvcjogCQCkAwEFDHVubG9ja0hlaWdodAIfIGJsb2NrIGhlaWdodCB0byB3aXRoZHJhdyBmdW5kcwMDAwkAZgIFBWluZGV4BQpwcmljZUluZGV4BgkAZgIFDHVubG9ja0hlaWdodAULaW5kZXhIZWlnaHQGAwkBAiE9AgUPcHJldkluZGV4SGVpZ2h0AAAJAGcCBQ9wcmV2SW5kZXhIZWlnaHQFDHVubG9ja0hlaWdodAcJAQ5wcmljZUluZGV4RkFJTAUFBWluZGV4BQpwcmljZUluZGV4BQtpbmRleEhlaWdodAUMdW5sb2NrSGVpZ2h0BQ9wcmV2SW5kZXhIZWlnaHQEDXdpdGhkcmF3VHVwbGUJAQxjYWxjV2l0aGRyYXcEBQhzd2FwVHlwZQUIaW5BbW91bnQFDHByaWNlQnlJbmRleAUPbmV1dHJpbm9NZXRyaWNzBAxvdXROZXRBbW91bnQIBQ13aXRoZHJhd1R1cGxlAl8xBApvdXRBc3NldElkCAUNd2l0aGRyYXdUdXBsZQJfMgQKb3V0U3VyZkFtdAgFDXdpdGhkcmF3VHVwbGUCXzMED2luQW10VG9TdXJmUGFydAgFDXdpdGhkcmF3VHVwbGUCXzQECnVubGVhc2VBbXQIBQ13aXRoZHJhd1R1cGxlAl81BAxvdXRGZWVBbW91bnQIBQ13aXRoZHJhd1R1cGxlAl82BAtvdXRBbXRHcm9zcwgFDXdpdGhkcmF3VHVwbGUCXzcDCQBnAgAABQtvdXRBbXRHcm9zcwkAAgECE2JhbGFuY2UgZXF1YWxzIHplcm8EAkJSCQEFYXNJbnQBCQCRAwIFD25ldXRyaW5vTWV0cmljcwUMbk1ldHJpY0lkeEJSBAVzdGF0ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBFHRvdGFsTG9ja2VkQnlVc2VyS0VZAgUIc3dhcFR5cGUFB2FjY291bnQJAGUCBRF0b3RhbExvY2tlZEJ5VXNlcgUIaW5BbW91bnQJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b3RhbExvY2tlZEtFWQEFCHN3YXBUeXBlCQBlAgULdG90YWxMb2NrZWQFCGluQW1vdW50CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFC3VzZXJBZGRyZXNzBQxvdXROZXRBbW91bnQFCm91dEFzc2V0SWQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBB3N3YXBLRVkCBQdhY2NvdW50BQhzd2FwVHhJZAkBDmZpbmlzaFN3YXBEQVRBCQUJZGF0YUFycmF5BQxwcmljZUJ5SW5kZXgFDG91dE5ldEFtb3VudAUMb3V0RmVlQW1vdW50BQx1bmxvY2tIZWlnaHQFBWluZGV4BQx3aXRoZHJhd1R4SWQFCm91dFN1cmZBbXQFAkJSBQNuaWwEDXN1cmZDb25kaXRpb24DCQBmAgUKb3V0U3VyZkFtdAAABAtpc3N1ZVJlc3VsdAkA/AcEBQ9hdWN0aW9uQ29udHJhY3QCCWlzc3VlU3VyZgkAzAgCBQpvdXRTdXJmQW10CQDMCAIFB2FjY291bnQFA25pbAUDbmlsAwkAAAIFC2lzc3VlUmVzdWx0BQtpc3N1ZVJlc3VsdAAACQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAAADCQAAAgUNc3VyZkNvbmRpdGlvbgUNc3VyZkNvbmRpdGlvbgkAlQoDBQVzdGF0ZQkBD0F0dGFjaGVkUGF5bWVudAIFCm91dEFzc2V0SWQFDG91dEZlZUFtb3VudAUKdW5sZWFzZUFtdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLg8BaQELY29uc3RydWN0b3IMEm5ldXRyaW5vQXNzZXRJZFBybQ5ib25kQXNzZXRJZFBybRJhdWN0aW9uQ29udHJhY3RQcm0WbGlxdWlkYXRpb25Db250cmFjdFBybQ5ycGRDb250cmFjdFBybRtub2RlT3JhY2xlUHJvdmlkZXJQdWJLZXlQcm0bYmFsYW5jZVdhdmVzTG9ja0ludGVydmFsUHJtHmJhbGFuY2VOZXV0cmlub0xvY2tJbnRlcnZhbFBybRVtaW5XYXZlc1N3YXBBbW91bnRQcm0YbWluTmV1dHJpbm9Td2FwQW1vdW50UHJtFW5ldXRyaW5vT3V0RmVlUGFydFBybRJ3YXZlc091dEZlZVBhcnRQcm0EC2NoZWNrQ2FsbGVyCQEIdGhpc09ubHkBBQFpAwkAAAIFC2NoZWNrQ2FsbGVyBQtjaGVja0NhbGxlcgMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECE25vIHBheW1lbnRzIGFsbG93ZWQJAMwIAgkBC1N0cmluZ0VudHJ5AgUSTmV1dHJpbm9Bc3NldElkS2V5BRJuZXV0cmlub0Fzc2V0SWRQcm0JAMwIAgkBC1N0cmluZ0VudHJ5AgUOQm9uZEFzc2V0SWRLZXkFDmJvbmRBc3NldElkUHJtCQDMCAIJAQtTdHJpbmdFbnRyeQIFEkF1Y3Rpb25Db250cmFjdEtleQUSYXVjdGlvbkNvbnRyYWN0UHJtCQDMCAIJAQtTdHJpbmdFbnRyeQIFFkxpcXVpZGF0aW9uQ29udHJhY3RLZXkFFmxpcXVpZGF0aW9uQ29udHJhY3RQcm0JAMwIAgkBC1N0cmluZ0VudHJ5AgUOUlBEQ29udHJhY3RLZXkFDnJwZENvbnRyYWN0UHJtCQDMCAIJAQtTdHJpbmdFbnRyeQIFG05vZGVPcmFjbGVQcm92aWRlclB1YktleUtleQUbbm9kZU9yYWNsZVByb3ZpZGVyUHViS2V5UHJtCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRtCYWxhbmNlV2F2ZXNMb2NrSW50ZXJ2YWxLZXkFG2JhbGFuY2VXYXZlc0xvY2tJbnRlcnZhbFBybQkAzAgCCQEMSW50ZWdlckVudHJ5AgUeQmFsYW5jZU5ldXRyaW5vTG9ja0ludGVydmFsS2V5BR5iYWxhbmNlTmV1dHJpbm9Mb2NrSW50ZXJ2YWxQcm0JAMwIAgkBDEludGVnZXJFbnRyeQIFFU1pbldhdmVzU3dhcEFtb3VudEtleQUVbWluV2F2ZXNTd2FwQW1vdW50UHJtCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRhNaW5OZXV0cmlub1N3YXBBbW91bnRLZXkFGG1pbk5ldXRyaW5vU3dhcEFtb3VudFBybQkAzAgCCQEMSW50ZWdlckVudHJ5AgUVTmV1dHJpbm9PdXRGZWVQYXJ0S2V5BRVuZXV0cmlub091dEZlZVBhcnRQcm0JAMwIAgkBDEludGVnZXJFbnRyeQIFEldhdmVzT3V0RmVlUGFydEtleQUSd2F2ZXNPdXRGZWVQYXJ0UHJtBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQENY29uc3RydWN0b3JWMgMMbWF0aENvbnRyYWN0E25zYnRTdGFraW5nQ29udHJhY3QUc3dhcHNUaW1lZnJhbWVCbG9ja3MEC2NoZWNrQ2FsbGVyCQEIdGhpc09ubHkBBQFpAwkAAAIFC2NoZWNrQ2FsbGVyBQtjaGVja0NhbGxlcgMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECE25vIHBheW1lbnRzIGFsbG93ZWQJAMwIAgkBC1N0cmluZ0VudHJ5AgUPTWF0aENvbnRyYWN0S2V5BQxtYXRoQ29udHJhY3QJAMwIAgkBC1N0cmluZ0VudHJ5AgUWTnNidFN0YWtpbmdDb250cmFjdEtleQUTbnNidFN0YWtpbmdDb250cmFjdAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEXN3YXBzVGltZWZyYW1lS0VZAAUUc3dhcHNUaW1lZnJhbWVCbG9ja3MFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARNzd2FwV2F2ZXNUb05ldXRyaW5vAAMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECLHN3YXBXYXZlc1RvTmV1dHJpbm8gcmVxdWlyZSBvbmx5IG9uZSBwYXltZW50BANwbXQJAQV2YWx1ZQEJAJEDAggFAWkIcGF5bWVudHMAAAMJAQlpc0RlZmluZWQBCAUDcG10B2Fzc2V0SWQJAAIBAilPbmx5IFdhdmVzIHRva2VuIGlzIGFsbG93ZWQgZm9yIHN3YXBwaW5nLgQLdXNlckFkZHJlc3MJAKUIAQgFAWkGY2FsbGVyBAZ0eElkNTgJANgEAQgFAWkNdHJhbnNhY3Rpb25JZAQQc3dhcFBhcmFtc1NUUlVDVAkBEmFzU3dhcFBhcmFtc1NUUlVDVAEJAPwHBAUEdGhpcwIbc3dhcFBhcmFtc0J5VXNlclNZU1JFQURPTkxZCQDMCAIFC3VzZXJBZGRyZXNzCQDMCAIAAAUDbmlsBQNuaWwEEGNvbW1vblN3YXBSZXN1bHQJAQpjb21tb25Td2FwBQIFd2F2ZXMIBQNwbXQGYW1vdW50BQt1c2VyQWRkcmVzcwUGdHhJZDU4BRBzd2FwUGFyYW1zU1RSVUNUBRBjb21tb25Td2FwUmVzdWx0AWkBE3N3YXBOZXV0cmlub1RvV2F2ZXMAAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQACAQIsc3dhcE5ldXRyaW5vVG9XYXZlcyByZXF1aXJlIG9ubHkgb25lIHBheW1lbnQEA3BtdAkBBXZhbHVlAQkAkQMCCAUBaQhwYXltZW50cwAAAwkBAiE9AggFA3BtdAdhc3NldElkBQ9uZXV0cmlub0Fzc2V0SWQJAAIBAjpPbmx5IGFwcHJvcHJpYXRlIE5ldXRyaW5vIHRva2VucyBhcmUgYWxsb3dlZCBmb3Igc3dhcHBpbmcuBAt1c2VyQWRkcmVzcwkApQgBCAUBaQZjYWxsZXIEBnR4SWQ1OAkA2AQBCAUBaQ10cmFuc2FjdGlvbklkBBBzd2FwUGFyYW1zU1RSVUNUCQESYXNTd2FwUGFyYW1zU1RSVUNUAQkA/AcEBQR0aGlzAhtzd2FwUGFyYW1zQnlVc2VyU1lTUkVBRE9OTFkJAMwIAgULdXNlckFkZHJlc3MJAMwIAgAABQNuaWwFA25pbAQQY29tbW9uU3dhcFJlc3VsdAkBCmNvbW1vblN3YXAFAghuZXV0cmlubwgFA3BtdAZhbW91bnQFC3VzZXJBZGRyZXNzBQZ0eElkNTgFEHN3YXBQYXJhbXNTVFJVQ1QFEGNvbW1vblN3YXBSZXN1bHQBaQEId2l0aGRyYXcDB2FjY291bnQFaW5kZXgIc3dhcFR4SWQEBHR4SWQJANgEAQgFAWkNdHJhbnNhY3Rpb25JZAMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECE25vIHBheW1lbnRzIGFsbG93ZWQED25ldXRyaW5vTWV0cmljcwkBCWFzQW55TGlzdAEJAPwHBAUMbWF0aENvbnRyYWN0AhpjYWxjTmV1dGlub01ldHJpY3NSRUFET05MWQUDbmlsBQNuaWwEAkJSCQEFYXNJbnQBCQCRAwIFD25ldXRyaW5vTWV0cmljcwUMbk1ldHJpY0lkeEJSBAtjb21tb25UdXBsZQkBDmNvbW1vbldpdGhkcmF3BQUHYWNjb3VudAUFaW5kZXgFCHN3YXBUeElkBQR0eElkBQ9uZXV0cmlub01ldHJpY3MEBXN0YXRlCAULY29tbW9uVHVwbGUCXzEEA2ZlZQgFC2NvbW1vblR1cGxlAl8yBAp1bmxlYXNlQW10CAULY29tbW9uVHVwbGUCXzMEEXVubGVhc2VJbnZPckVtcHR5CQD8BwQFBHRoaXMCF2ludGVybmFsVW5sZWFzZUFuZExlYXNlCQDMCAIFCnVubGVhc2VBbXQFA25pbAUDbmlsAwkAAAIFEXVubGVhc2VJbnZPckVtcHR5BRF1bmxlYXNlSW52T3JFbXB0eQQJZ25zYnREYXRhCQEJYXNBbnlMaXN0AQkA/AcEBRdnbnNidENvbnRyb2xsZXJDb250cmFjdAIUZ25zYnRJbmZvU1lTUkVBRE9OTFkJAMwIAgIACQDMCAIAAAkAzAgCAAAFA25pbAUDbmlsBA1nbnNidEFtdFRvdGFsCQEFYXNJbnQBCQCRAwIFCWduc2J0RGF0YQABBBVnbnNidEFtdEZyb21TdXJmVG90YWwJAQVhc0ludAEJAJEDAgkBCWFzQW55TGlzdAEJAJEDAgUJZ25zYnREYXRhAAMAAwQLc3VyZkZlZUFtdDEDCQECIT0CBQ1nbnNidEFtdFRvdGFsAAAJAGsDCAUDZmVlBmFtb3VudAUVZ25zYnRBbXRGcm9tU3VyZlRvdGFsBQ1nbnNidEFtdFRvdGFsAAAEC3N1cmZGZWVBbXQyAwkBAiE9AgUNZ25zYnRBbXRUb3RhbAAACQBrAwgFA2ZlZQZhbW91bnQJAGUCBQVQQVVMSQUCQlIFBVBBVUxJAAAECnN1cmZGZWVBbXQJAJYDAQkAzAgCBQtzdXJmRmVlQW10MQkAzAgCBQtzdXJmRmVlQW10MgUDbmlsBApuc2J0RmVlQW10CQBlAggFA2ZlZQZhbW91bnQFCnN1cmZGZWVBbXQEC3N1cmZEZXBvc2l0AwkAZgIFCnN1cmZGZWVBbXQAAAQHc3VyZkludgkA/AcEBRNzdXJmU3Rha2luZ0NvbnRyYWN0AgdkZXBvc2l0BQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIIBQNmZWUHYXNzZXRJZAUKc3VyZkZlZUFtdAUDbmlsAwkAAAIFB3N1cmZJbnYFB3N1cmZJbnYFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFC3N1cmZEZXBvc2l0BQtzdXJmRGVwb3NpdAQLbnNidERlcG9zaXQDCQBmAgUKbnNidEZlZUFtdAAABAduc2J0SW52CQD8BwQFE25zYnRTdGFraW5nQ29udHJhY3QCB2RlcG9zaXQFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AggFA2ZlZQdhc3NldElkBQpuc2J0RmVlQW10BQNuaWwDCQAAAgUHbnNidEludgUHbnNidEludgUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgULbnNidERlcG9zaXQFC25zYnREZXBvc2l0BQVzdGF0ZQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARdpbnRlcm5hbFVubGVhc2VBbmRMZWFzZQENdW5sZWFzZUFtb3VudAMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECLGludGVybmFsVW5sZWFzZUFuZExlYXNlIGlzIG5vdCBwdWJsaWMgbWV0aG9kCQEWcHJlcGFyZVVubGVhc2VBbmRMZWFzZQEFDXVubGVhc2VBbW91bnQBaQESdHJhbnNmZXJVc2RuVG9Vc2VyAgZhbW91bnQEYWRkcgMJAQIhPQIIBQFpBmNhbGxlcgUPYXVjdGlvbkNvbnRyYWN0CQACAQIjT25seSBhdWN0aW9uIGNvbnRyYWN0IGlzIGF1dGhvcml6ZWQJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwkBEUBleHRyTmF0aXZlKDEwNjIpAQUEYWRkcgUGYW1vdW50BQ9uZXV0cmlub0Fzc2V0SWQFA25pbAFpAQthY2NlcHRXYXZlcwADAwkBAiE9AggFAWkGY2FsbGVyBQ9hdWN0aW9uQ29udHJhY3QJAQIhPQIIBQFpBmNhbGxlcgUSZ292ZXJuYW5jZUNvbnRyYWN0BwkAAgECQ0N1cnJlbnRseSBvbmx5IGF1Y3Rpb24gYW5kIGdvdmVybmFuY2UgY29udHJhY3RzIGFyZSBhbGxvd2VkIHRvIGNhbGwJAJQKAgkBFnByZXBhcmVVbmxlYXNlQW5kTGVhc2UBAAACB3N1Y2Nlc3MBaQEPYXBwcm92ZUxlYXNpbmdzAwZuTGlzdFMIZ3JvdXBOdW0EbEFtdAQFbklkeHMJAMwIAgAACQDMCAIAAQkAzAgCAAIJAMwIAgADCQDMCAIABAkAzAgCAAUJAMwIAgAGCQDMCAIABwUDbmlsBAdtbmdQdWJTCQELdmFsdWVPckVsc2UCCQCiCAECHCVzJXNfX2NmZ19fbGVhc2luZ01hbmFnZXJQdWICLDdBVU1YNTR1a1lNWXZQbW1hN3lvRmY1TmpaaHM0QnU1bnozRXo5RVY4c3VyBAZtbmdQdWIJANkEAQUHbW5nUHViUwQObm9kZVJlZ0FkZHJTdHIJAQt2YWx1ZU9yRWxzZQIJAKIIAQIfJXMlc19fY2ZnX19ub2Rlc1JlZ2lzdHJ5QWRkcmVzcwIjM1A5dktxUUtqVWRtcFhBZmlXYXU4a3JSRVlBWTFYcjY5cEUEC25vZGVSZWdBZGRyCQERQGV4dHJOYXRpdmUoMTA2MikBBQ5ub2RlUmVnQWRkclN0cgQRbEdyb3VwTm9kZUxpc3RLRVkJARhnZXRMZWFzZUdyb3VwTm9kZUxpc3RLZXkBBQhncm91cE51bQQKbEdyTm9kZU9wdAkAnQgCBQR0aGlzBRFsR3JvdXBOb2RlTGlzdEtFWQMJAQlpc0RlZmluZWQBBQpsR3JOb2RlT3B0CQACAQkArAICCQCsAgICBmdyb3VwIAkApAMBBQhncm91cE51bQIUIGFscmVhZHkgaW5pdGlhbGl6ZWQEBW5MaXN0CQC1CQIFBm5MaXN0UwUDU0VQBAhleHBDb3VudAkAkAMBBQVuSWR4cwMJAQIhPQIIBQFpD2NhbGxlclB1YmxpY0tleQUGbW5nUHViCQACAQIeYXBwcm92ZUxlYXNpbmdzIG5vdCBhdXRob3JpemVkBA0kdDAzNDY5NTM0NzU3CQEMcmVhZE5vZGVJbmZvAQAABAZuQWRkcjAIBQ0kdDAzNDY5NTM0NzU3Al8xBAhsQW10S0VZMAgFDSR0MDM0Njk1MzQ3NTcCXzIEBWxBbXQwCAUNJHQwMzQ2OTUzNDc1NwJfMwQHbElkS0VZMAgFDSR0MDM0Njk1MzQ3NTcCXzQEBGxJZDAIBQ0kdDAzNDY5NTM0NzU3Al81BAVuZXdMMAkAxAgCBQZuQWRkcjAJAGUCBQVsQW10MAkAaAIFBGxBbXQFCGV4cENvdW50BAp2YWxpZGF0aW9uCQD8BwQFC25vZGVSZWdBZGRyAhp2YWxpZGF0ZUFuZEFwcHJvdmVMZWFzaW5ncwkAzAgCBQZuTGlzdFMFA25pbAUDbmlsAwkAAAIFCnZhbGlkYXRpb24FCnZhbGlkYXRpb24KASNmb3JFYWNoTm9kZVZhbGlkYXRlQW5kR2VuZXJhdGVMZWFzZQIBYQFpBARub2RlCQCRAwIFBW5MaXN0BQFpBAJsYQkAxAgCCQERQGV4dHJOYXRpdmUoMTA2MikBBQRub2RlBQRsQW10CQDOCAIFAWEJAMwIAgUCbGEJAMwIAgkBC0JpbmFyeUVudHJ5AgkBFmdldExlYXNlSWRCeUFkZHJlc3NLZXkBBQRub2RlCQEFbGNhbGMBBQJsYQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBGmdldExlYXNlQW1vdW50QnlBZGRyZXNzS2V5AQUEbm9kZQUEbEFtdAUDbmlsCQDOCAIJAMwIAgkBC1N0cmluZ0VudHJ5AgURbEdyb3VwTm9kZUxpc3RLRVkFBm5MaXN0UwkAzAgCCQELQmluYXJ5RW50cnkCBQdsSWRLRVkwCQEFbGNhbGMBBQVuZXdMMAkAzAgCCQEMSW50ZWdlckVudHJ5AgUIbEFtdEtFWTAIBQVuZXdMMAZhbW91bnQJAMwIAgkBC0xlYXNlQ2FuY2VsAQUEbElkMAkAzAgCBQVuZXdMMAUDbmlsCgACJGwFBW5JZHhzCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJASNmb3JFYWNoTm9kZVZhbGlkYXRlQW5kR2VuZXJhdGVMZWFzZQIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQITTGlzdCBzaXplIGV4Y2VlZHMgOAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQERcmViYWxhbmNlTGVhc2luZ3MCBmFtb3VudAhncm91cE51bQQFbklkeHMJAMwIAgAACQDMCAIAAQkAzAgCAAIJAMwIAgADCQDMCAIABAkAzAgCAAUJAMwIAgAGCQDMCAIABwUDbmlsBAdtbmdQdWJTCQELdmFsdWVPckVsc2UCCQCiCAECHCVzJXNfX2NmZ19fbGVhc2luZ01hbmFnZXJQdWICLDdBVU1YNTR1a1lNWXZQbW1hN3lvRmY1TmpaaHM0QnU1bnozRXo5RVY4c3VyBAZtbmdQdWIJANkEAQUHbW5nUHViUwQRbEdyb3VwTm9kZUxpc3RLRVkJARhnZXRMZWFzZUdyb3VwTm9kZUxpc3RLZXkBBQhncm91cE51bQQGbkxpc3RTCQEPZ2V0U3RyaW5nT3JGYWlsAgUEdGhpcwURbEdyb3VwTm9kZUxpc3RLRVkEBW5MaXN0CQC1CQIFBm5MaXN0UwUDU0VQAwkBAiE9AggFAWkPY2FsbGVyUHVibGljS2V5BQZtbmdQdWIJAAIBAiByZWJhbGFuY2VMZWFzaW5ncyBub3QgYXV0aG9yaXplZAQKdW5sZWFzZUFtdAkAZAIJAGkCBQZhbW91bnQJAJADAQUFbkxpc3QAAQQNJHQwMzU5OTczNjA1OQkBDHJlYWROb2RlSW5mbwEAAAQGbkFkZHIwCAUNJHQwMzU5OTczNjA1OQJfMQQIbEFtdEtFWTAIBQ0kdDAzNTk5NzM2MDU5Al8yBAVsQW10MAgFDSR0MDM1OTk3MzYwNTkCXzMEB2xJZEtFWTAIBQ0kdDAzNTk5NzM2MDU5Al80BARsSWQwCAUNJHQwMzU5OTczNjA1OQJfNQQFbmV3TDAJAMQIAgUGbkFkZHIwCQBkAgUFbEFtdDAJAGgCBQp1bmxlYXNlQW10CQCQAwEFBW5MaXN0CgEUZm9yRWFjaE5vZGVEb1VubGVhc2UCAWEBaQQEbm9kZQkAkQMCBQVuTGlzdAUBaQQGbElkS0VZCQEWZ2V0TGVhc2VJZEJ5QWRkcmVzc0tleQEFBG5vZGUEA2xJZAkBEUBleHRyTmF0aXZlKDEwNTIpAgUEdGhpcwUGbElkS0VZBAdsQW10S0VZCQEaZ2V0TGVhc2VBbW91bnRCeUFkZHJlc3NLZXkBBQRub2RlBARsQW10CQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzBQdsQW10S0VZBAN1bGEJAQtMZWFzZUNhbmNlbAEJAQV2YWx1ZQEFA2xJZAQCbGEJAMQIAgkBEUBleHRyTmF0aXZlKDEwNjIpAQUEbm9kZQkAZQIFBGxBbXQFCnVubGVhc2VBbXQJAM4IAgUBYQkAzAgCCQELTGVhc2VDYW5jZWwBCQEFdmFsdWUBBQNsSWQJAMwIAgUCbGEJAMwIAgkBC0JpbmFyeUVudHJ5AgUGbElkS0VZCQEFbGNhbGMBBQJsYQkAzAgCCQEMSW50ZWdlckVudHJ5AgUHbEFtdEtFWQgFAmxhBmFtb3VudAUDbmlsCQDOCAIKAAIkbAUFbklkeHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBFGZvckVhY2hOb2RlRG9VbmxlYXNlAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA4CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAkAzAgCCQELQmluYXJ5RW50cnkCBQdsSWRLRVkwCQEFbGNhbGMBBQVuZXdMMAkAzAgCCQEMSW50ZWdlckVudHJ5AgUIbEFtdEtFWTAIBQVuZXdMMAZhbW91bnQJAMwIAgkBC0xlYXNlQ2FuY2VsAQUEbElkMAkAzAgCBQVuZXdMMAUDbmlsAWkBG3N3YXBQYXJhbXNCeVVzZXJTWVNSRUFET05MWQIOdXNlckFkZHJlc3NTdHIJZ25zYnREaWZmBAlnbnNidERhdGEJAQlhc0FueUxpc3QBCQD8BwQFF2duc2J0Q29udHJvbGxlckNvbnRyYWN0AhRnbnNidEluZm9TWVNSRUFET05MWQkAzAgCBQ51c2VyQWRkcmVzc1N0cgkAzAgCAAAJAMwIAgAABQNuaWwFA25pbAQIZ25zYnRBbXQJAGQCCQEFYXNJbnQBCQCRAwIFCWduc2J0RGF0YQAABQlnbnNidERpZmYEDWduc2J0QW10VG90YWwJAGQCCQEFYXNJbnQBCQCRAwIFCWduc2J0RGF0YQABBQlnbnNidERpZmYEDXN3YXBMaW1pdERhdGEJAQlhc0FueUxpc3QBCQD8BwQFDG1hdGhDb250cmFjdAIVY2FsY1N3YXBMaW1pdFJFQURPTkxZCQDMCAIFCGduc2J0QW10BQNuaWwFA25pbAQXd2F2ZXNTd2FwTGltaXRJblVzZG5NYXgJAQVhc0ludAEJAJEDAgUNc3dhcExpbWl0RGF0YQAABBF3YXZlc1N3YXBMaW1pdE1heAkBBWFzSW50AQkAkQMCBQ1zd2FwTGltaXREYXRhAAEEEHVzZG5Td2FwTGltaXRNYXgJAQVhc0ludAEJAJEDAgUNc3dhcExpbWl0RGF0YQACBA5sYXN0U3dhcEhlaWdodAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEVa2V5VXNlckxhc3RTd2FwSGVpZ2h0AQUOdXNlckFkZHJlc3NTdHIAAAQXc3dhcExpbWl0VGltZWxpZmVCbG9ja3MJARJzd2Fwc1RpbWVmcmFtZVJFQUQABBlwYXNzZWRCbG9ja3NBZnRlckxhc3RTd2FwCQBlAgUGaGVpZ2h0BQ5sYXN0U3dhcEhlaWdodAQRaXNTd2FwVGltZWxpZmVOZXcJAGcCBRlwYXNzZWRCbG9ja3NBZnRlckxhc3RTd2FwBRdzd2FwTGltaXRUaW1lbGlmZUJsb2NrcwQUc3dhcExpbWl0U3BlbnRJblVzZG4DBRFpc1N3YXBUaW1lbGlmZU5ldwAACQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJARhrZXlTd2FwVXNlclNwZW50SW5QZXJpb2QBBQ51c2VyQWRkcmVzc1N0cgAABA5ibGNrczJMbXRSZXNldAMFEWlzU3dhcFRpbWVsaWZlTmV3AAAJAGUCBRdzd2FwTGltaXRUaW1lbGlmZUJsb2NrcwUZcGFzc2VkQmxvY2tzQWZ0ZXJMYXN0U3dhcAkAlAoCBQNuaWwJAJkKBwUXd2F2ZXNTd2FwTGltaXRJblVzZG5NYXgFFHN3YXBMaW1pdFNwZW50SW5Vc2RuBQ5ibGNrczJMbXRSZXNldAUIZ25zYnRBbXQFDWduc2J0QW10VG90YWwFEXdhdmVzU3dhcExpbWl0TWF4BRB1c2RuU3dhcExpbWl0TWF4AWkBHWNhbGNXaXRoZHJhd1Jlc3VsdFNZU1JFQURPTkxZAwhzd2FwVHlwZQhpbkFtb3VudAVwcmljZQQPbmV1dHJpbm9NZXRyaWNzCQEJYXNBbnlMaXN0AQkA/AcEBQxtYXRoQ29udHJhY3QCGmNhbGNOZXV0aW5vTWV0cmljc1JFQURPTkxZBQNuaWwFA25pbAkAlAoCBQNuaWwJAQxjYWxjV2l0aGRyYXcEBQhzd2FwVHlwZQUIaW5BbW91bnQFBXByaWNlBQ9uZXV0cmlub01ldHJpY3MBaQEUcmVwbGFjZUNvbW11bml0eU5vZGUECm9sZEFkZHJTdHIKbmV3QWRkclN0cghncm91cE51bQ1wZW5hbHR5QW1vdW50BAdtbmdQdWJTCQELdmFsdWVPckVsc2UCCQCiCAECHCVzJXNfX2NmZ19fbGVhc2luZ01hbmFnZXJQdWICLDdBVU1YNTR1a1lNWXZQbW1hN3lvRmY1TmpaaHM0QnU1bnozRXo5RVY4c3VyBAZtbmdQdWIJANkEAQUHbW5nUHViUwMJAQIhPQIIBQFpD2NhbGxlclB1YmxpY0tleQUGbW5nUHViCQACAQIjcmVwbGFjZUNvbW11bml0eU5vZGUgbm90IGF1dGhvcml6ZWQECGdyb3VwS2V5CQEYZ2V0TGVhc2VHcm91cE5vZGVMaXN0S2V5AQUIZ3JvdXBOdW0EDmdyb3VwTm9kZUxpc3RTCQEPZ2V0U3RyaW5nT3JGYWlsAgUEdGhpcwUIZ3JvdXBLZXkDCQEBIQEJAQhjb250YWlucwIFDmdyb3VwTm9kZUxpc3RTBQpvbGRBZGRyU3RyCQACAQkArAICCQCsAgIJAKwCAgIGR3JvdXAgCQCkAwEFCGdyb3VwTnVtAhogZG9lcyBub3QgY29udGFpbiBhZGRyZXNzIAUKb2xkQWRkclN0cgQJZG9SZXBsYWNlCQD8BwQFFG5vZGVSZWdpc3RyeUNvbnRyYWN0AhNyZXBsYWNlQXBwcm92ZWROb2RlCQDMCAIFCm9sZEFkZHJTdHIJAMwIAgUKbmV3QWRkclN0cgkAzAgCBQhncm91cE51bQkAzAgCBQ1wZW5hbHR5QW1vdW50BQNuaWwFA25pbAMJAAACBQlkb1JlcGxhY2UFCWRvUmVwbGFjZQQNb2xkTGVhc2VJZEtleQkBFmdldExlYXNlSWRCeUFkZHJlc3NLZXkBBQpvbGRBZGRyU3RyBA5vbGRMZWFzZUFtdEtleQkBGmdldExlYXNlQW1vdW50QnlBZGRyZXNzS2V5AQUKb2xkQWRkclN0cgQIbGVhc2VBbXQJARFAZXh0ck5hdGl2ZSgxMDU1KQEFDm9sZExlYXNlQW10S2V5BA1uZXdMZWFzZUlkS2V5CQEWZ2V0TGVhc2VJZEJ5QWRkcmVzc0tleQEFCm9sZEFkZHJTdHIEDm5ld0xlYXNlQW10S2V5CQEaZ2V0TGVhc2VBbW91bnRCeUFkZHJlc3NLZXkBBQpvbGRBZGRyU3RyBAhuZXdMZWFzZQkAxAgCCQERQGV4dHJOYXRpdmUoMTA2MikBBQpuZXdBZGRyU3RyBQhsZWFzZUFtdAQVdXBkYXRlZEdyb3VwTm9kZUxpc3RTCQC5CQIJALUJAgUOZ3JvdXBOb2RlTGlzdFMFCm9sZEFkZHJTdHIFCm5ld0FkZHJTdHIJAJQKAgkAzAgCCQELTGVhc2VDYW5jZWwBCQERQGV4dHJOYXRpdmUoMTA1NykBBQ1vbGRMZWFzZUlkS2V5CQDMCAIJAQtEZWxldGVFbnRyeQEFDW9sZExlYXNlSWRLZXkJAMwIAgkBC0RlbGV0ZUVudHJ5AQUOb2xkTGVhc2VBbXRLZXkJAMwIAgkBC1N0cmluZ0VudHJ5AgUIZ3JvdXBLZXkFFXVwZGF0ZWRHcm91cE5vZGVMaXN0UwkAzAgCBQhuZXdMZWFzZQkAzAgCCQELQmluYXJ5RW50cnkCBQ1uZXdMZWFzZUlkS2V5CQEFbGNhbGMBBQhuZXdMZWFzZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUObmV3TGVhc2VBbXRLZXkFCGxlYXNlQW10BQNuaWwFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEfdXBkYXRlUmVzZXJ2ZXNBbmROZXV0cmlub1N1cHBseQAKARZnZXROdW1iZXJCeUtleUludGVybmFsAQNrZXkEByRtYXRjaDAJAJoIAgUEdGhpcwUDa2V5AwkAAQIFByRtYXRjaDACA0ludAQBYQUHJG1hdGNoMAUBYQAABAduTWV0cml4CQEJYXNBbnlMaXN0AQkA/AcEBQxtYXRoQ29udHJhY3QCGmNhbGNOZXV0aW5vTWV0cmljc1JFQURPTkxZBQNuaWwFA25pbAQDaWR4CQEWZ2V0TnVtYmVyQnlLZXlJbnRlcm5hbAECInVwZGF0ZVJlc2VydmVzQW5kTmV1dHJpbm9TdXBwbHlJZHgEBm5ld0lkeAkAZAIFA2lkeAABCQDMCAIJAQxJbnRlZ2VyRW50cnkCAiJ1cGRhdGVSZXNlcnZlc0FuZE5ldXRyaW5vU3VwcGx5SWR4BQZuZXdJZHgJAMwIAgkBDEludGVnZXJFbnRyeQICB3Jlc2VydmUJAQVhc0ludAEJAJEDAgUHbk1ldHJpeAADCQDMCAIJAQxJbnRlZ2VyRW50cnkCAg5uZXV0cmlub1N1cHBseQkBBWFzSW50AQkAkQMCBQduTWV0cml4AAUJAMwIAgkBDEludGVnZXJFbnRyeQICDnJlc2VydmVzSW5Vc2RuCQEWY29udmVydFdhdmVzVG9OZXV0cmlubwIJAQVhc0ludAEJAJEDAgUHbk1ldHJpeAADCQEFYXNJbnQBCQCRAwIFB25NZXRyaXgAAAkAzAgCCQEMSW50ZWdlckVudHJ5AgIHc3VycGx1cwkBBWFzSW50AQkAkQMCBQduTWV0cml4AAYJAMwIAgkBDEludGVnZXJFbnRyeQICB2RlZmljaXQJAQEtAQkBBWFzSW50AQkAkQMCBQduTWV0cml4AAYFA25pbAFpARZ3YXZlc0JhbGFuY2VzVnNQYXltZW50AAQBYgkA7wcBBQR0aGlzCQDMCAIJAQxJbnRlZ2VyRW50cnkCAhZ3YXZlc0JhbGFuY2VfYXZhaWxhYmxlCAUBYglhdmFpbGFibGUJAMwIAgkBDEludGVnZXJFbnRyeQICFHdhdmVzQmFsYW5jZV9yZWd1bGFyCAUBYgdyZWd1bGFyCQDMCAIJAQxJbnRlZ2VyRW50cnkCAhd3YXZlc0JhbGFuY2VfZ2VuZXJhdGluZwgFAWIKZ2VuZXJhdGluZwkAzAgCCQEMSW50ZWdlckVudHJ5AgIWd2F2ZXNCYWxhbmNlX2VmZmVjdGl2ZQgFAWIJZWZmZWN0aXZlCQDMCAIJAQxJbnRlZ2VyRW50cnkCAg13YXZlc19wYXltZW50CAkBBXZhbHVlAQkAkQMCCAUBaQhwYXltZW50cwAABmFtb3VudAUDbmlsAQJ0eAEGdmVyaWZ5AAQCaWQJANgEAQgFAnR4AmlkBBNwdWJLZXlBZG1pbnNMaXN0U3RyCQC5CQIJAMwIAgIsRXh0RUVLMTlubUtqOW1DcG5XeXZFRUpGWUFUTE1jVkVNdm9oaFVIa3lITm0JAMwIAgIsRXY1cHk1RmZCUVg5Y1pwWUtuZlFyVEI0OUJ5ZjhRbXBaV2VEVlJpbTR5VjcJAMwIAgIsRFV1dUxqWHU5OG5Cd1pjN2Zxd0NUanRBM25uUndnVGJrTVNyNVNVMk5tRFIJAMwIAgIsRFV1dUxqWHU5OG5Cd1pjN2Zxd0NUanRBM25uUndnVGJrTVNyNVNVMk5tRFIFA25pbAUDU0VQBBBwdWJLZXlBZG1pbnNMaXN0CQC1CQIJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUPY29udHJvbENvbnRyYWN0Agwlc19fbXVsdGlzaWcFE3B1YktleUFkbWluc0xpc3RTdHIFA1NFUAQFY291bnQJAGQCCQBkAgkAZAIDCQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwAACQDZBAEJAJEDAgUQcHViS2V5QWRtaW5zTGlzdAAAAAEAAAMJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAEJANkEAQkAkQMCBRBwdWJLZXlBZG1pbnNMaXN0AAEAAQAAAwkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAgkA2QQBCQCRAwIFEHB1YktleUFkbWluc0xpc3QAAgABAAADCQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwADCQDZBAEJAJEDAgUQcHViS2V5QWRtaW5zTGlzdAADAAIAAAQHJG1hdGNoMAUCdHgDCQABAgUHJG1hdGNoMAIVU3BvbnNvckZlZVRyYW5zYWN0aW9uBAlzcG9uc29yVHgFByRtYXRjaDADCQEbY2hlY2tJc1ZhbGlkTWluU3BvbnNvcmVkRmVlAQUJc3BvbnNvclR4CQBnAgUFY291bnQAAwcJAGcCBQVjb3VudAADlw42pw==", "chainId": 84, "height": 2277712, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: FBKpVvYZtNmJoLSRfrT4K54ipi1SzUzGcHGVAr44x6No Next: HfuG7NEucEjM7vF7E2obE6yPmbk9G5nSchDuNxQwBGCm Diff:
OldNewDifferences
113113
114114 let IdxControlCfgGnsbtControllerDapp = 11
115115
116+let IdxControlCfgRestV2Dapp = 12
117+
118+let IdxControlCfgGovernanceDapp = 13
119+
116120 func keyControlAddress () = "%s%s__config__controlAddress"
117121
118122
119123 func keyControlCfg () = "%s__controlConfig"
120124
121125
122-func readControlCfgOrFail (control) = split(getStringOrFail(control, keyControlCfg()), SEP)
126+func readControlCfgOrFail (control) = split_4C(getStringOrFail(control, keyControlCfg()), SEP)
123127
124128
125129 func getContractAddressOrFail (controlCfg,idx) = valueOrErrorMessage(addressFromString(controlCfg[idx]), ("Control cfg doesn't contain address at index " + toString(idx)))
140144 let auctionContract = getContractAddressOrFail(controlCfg, IdxControlCfgAuctionDapp)
141145
142146 let nodeRegistryContract = getContractAddressOrFail(controlCfg, IdxControlCfgNodeRegistryDapp)
147+
148+let governanceContract = getContractAddressOrFail(controlCfg, IdxControlCfgGovernanceDapp)
143149
144150 let NeutrinoAssetIdKey = "neutrino_asset_id"
145151
778784
779785
780786 @Callable(i)
781-func acceptWaves () = if ((i.caller != auctionContract))
782- then throw("Currently only auction contract is allowed to call")
787+func acceptWaves () = if (if ((i.caller != auctionContract))
788+ then (i.caller != governanceContract)
789+ else false)
790+ then throw("Currently only auction and governance contracts are allowed to call")
783791 else $Tuple2(prepareUnleaseAndLease(0), "success")
784792
785793
801809 if ((i.callerPublicKey != mngPub))
802810 then throw("approveLeasings not authorized")
803811 else {
804- let $t03446334525 = readNodeInfo(0)
805- let nAddr0 = $t03446334525._1
806- let lAmtKEY0 = $t03446334525._2
807- let lAmt0 = $t03446334525._3
808- let lIdKEY0 = $t03446334525._4
809- let lId0 = $t03446334525._5
812+ let $t03469534757 = readNodeInfo(0)
813+ let nAddr0 = $t03469534757._1
814+ let lAmtKEY0 = $t03469534757._2
815+ let lAmt0 = $t03469534757._3
816+ let lIdKEY0 = $t03469534757._4
817+ let lId0 = $t03469534757._5
810818 let newL0 = Lease(nAddr0, (lAmt0 - (lAmt * expCount)))
811819 let validation = invoke(nodeRegAddr, "validateAndApproveLeasings", [nListS], nil)
812820 if ((validation == validation))
851859 then throw("rebalanceLeasings not authorized")
852860 else {
853861 let unleaseAmt = ((amount / size(nList)) + 1)
854- let $t03576535827 = readNodeInfo(0)
855- let nAddr0 = $t03576535827._1
856- let lAmtKEY0 = $t03576535827._2
857- let lAmt0 = $t03576535827._3
858- let lIdKEY0 = $t03576535827._4
859- let lId0 = $t03576535827._5
862+ let $t03599736059 = readNodeInfo(0)
863+ let nAddr0 = $t03599736059._1
864+ let lAmtKEY0 = $t03599736059._2
865+ let lAmt0 = $t03599736059._3
866+ let lIdKEY0 = $t03599736059._4
867+ let lId0 = $t03599736059._5
860868 let newL0 = Lease(nAddr0, (lAmt0 + (unleaseAmt * size(nList))))
861869 func forEachNodeDoUnlease (a,i) = {
862870 let node = nList[i]
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
55
66
77 func lcalc (l) = calculateLeaseId(l)
88
99
1010 func getNumberByKey (key) = valueOrElse(getInteger(this, key), 0)
1111
1212
1313 func getStringByKey (key) = valueOrElse(getString(this, key), "")
1414
1515
1616 func getBoolByKey (key) = valueOrElse(getBoolean(this, key), false)
1717
1818
1919 func getNumberByAddressAndKey (address,key) = valueOrElse(getInteger(address, key), 0)
2020
2121
2222 func getStringByAddressAndKey (address,key) = valueOrElse(getString(addressFromStringValue(address), key), "")
2323
2424
2525 func getBoolByAddressAndKey (address,key) = valueOrElse(getBoolean(address, key), false)
2626
2727
2828 func asAnyList (v) = match v {
2929 case l: List[Any] =>
3030 l
3131 case _ =>
3232 throw("fail to cast into List[Any]")
3333 }
3434
3535
3636 func asString (v) = match v {
3737 case s: String =>
3838 s
3939 case _ =>
4040 throw("fail to cast into String")
4141 }
4242
4343
4444 func asInt (v) = match v {
4545 case i: Int =>
4646 i
4747 case _ =>
4848 throw("fail to cast into Int")
4949 }
5050
5151
5252 func asBytes (val) = match val {
5353 case valByte: ByteVector =>
5454 valByte
5555 case _ =>
5656 throw("fail to cast into ByteVector")
5757 }
5858
5959
6060 func asPayment (v) = match v {
6161 case p: AttachedPayment =>
6262 p
6363 case _ =>
6464 throw("fail to cast into AttachedPayment")
6565 }
6666
6767
6868 func asSwapParamsSTRUCT (v) = match v {
6969 case struct: (Int, Int, Int, Int, Int, Int, Int) =>
7070 struct
7171 case _ =>
7272 throw("fail to cast into Tuple5 ints")
7373 }
7474
7575
7676 let SEP = "__"
7777
7878 let WAVELET = 100000000
7979
8080 let PAULI = 1000000
8181
8282 let PRICELET = 1000000
8383
8484 let DEFAULTSWAPFEE = 20000
8585
8686 let BRPROTECTED = 100000
8787
8888 let IdxNetAmount = 0
8989
9090 let IdxFeeAmount = 1
9191
9292 let IdxGrossAmount = 2
9393
9494 let IdxControlCfgNeutrinoDapp = 1
9595
9696 let IdxControlCfgAuctionDapp = 2
9797
9898 let IdxControlCfgRpdDapp = 3
9999
100100 let IdxControlCfgMathDapp = 4
101101
102102 let IdxControlCfgLiquidationDapp = 5
103103
104104 let IdxControlCfgRestDapp = 6
105105
106106 let IdxControlCfgNodeRegistryDapp = 7
107107
108108 let IdxControlCfgNsbtStakingDapp = 8
109109
110110 let IdxControlCfgMediatorDapp = 9
111111
112112 let IdxControlCfgSurfStakingDapp = 10
113113
114114 let IdxControlCfgGnsbtControllerDapp = 11
115115
116+let IdxControlCfgRestV2Dapp = 12
117+
118+let IdxControlCfgGovernanceDapp = 13
119+
116120 func keyControlAddress () = "%s%s__config__controlAddress"
117121
118122
119123 func keyControlCfg () = "%s__controlConfig"
120124
121125
122-func readControlCfgOrFail (control) = split(getStringOrFail(control, keyControlCfg()), SEP)
126+func readControlCfgOrFail (control) = split_4C(getStringOrFail(control, keyControlCfg()), SEP)
123127
124128
125129 func getContractAddressOrFail (controlCfg,idx) = valueOrErrorMessage(addressFromString(controlCfg[idx]), ("Control cfg doesn't contain address at index " + toString(idx)))
126130
127131
128132 let controlContract = addressFromStringValue(valueOrElse(getString(this, keyControlAddress()), "3N4NS7d4Jo9a6F14LiFUKKYVdUkkf2eP4Zx"))
129133
130134 let controlCfg = readControlCfgOrFail(controlContract)
131135
132136 let mathContract = getContractAddressOrFail(controlCfg, IdxControlCfgMathDapp)
133137
134138 let nsbtStakingContract = getContractAddressOrFail(controlCfg, IdxControlCfgNsbtStakingDapp)
135139
136140 let surfStakingContract = getContractAddressOrFail(controlCfg, IdxControlCfgSurfStakingDapp)
137141
138142 let gnsbtControllerContract = getContractAddressOrFail(controlCfg, IdxControlCfgGnsbtControllerDapp)
139143
140144 let auctionContract = getContractAddressOrFail(controlCfg, IdxControlCfgAuctionDapp)
141145
142146 let nodeRegistryContract = getContractAddressOrFail(controlCfg, IdxControlCfgNodeRegistryDapp)
147+
148+let governanceContract = getContractAddressOrFail(controlCfg, IdxControlCfgGovernanceDapp)
143149
144150 let NeutrinoAssetIdKey = "neutrino_asset_id"
145151
146152 let BondAssetIdKey = "bond_asset_id"
147153
148154 let AuctionContractKey = "auction_contract"
149155
150156 let NsbtStakingContractKey = "nsbtStakingContract"
151157
152158 let LiquidationContractKey = "liquidation_contract"
153159
154160 let RPDContractKey = "rpd_contract"
155161
156162 let ContolContractKey = "control_contract"
157163
158164 let MathContractKey = "math_contract"
159165
160166 let BalanceWavesLockIntervalKey = "balance_waves_lock_interval"
161167
162168 let BalanceNeutrinoLockIntervalKey = "balance_neutrino_lock_interval"
163169
164170 let MinWavesSwapAmountKey = "min_waves_swap_amount"
165171
166172 let MinNeutrinoSwapAmountKey = "min_neutrino_swap_amount"
167173
168174 let NodeOracleProviderPubKeyKey = "node_oracle_provider"
169175
170176 let NeutrinoOutFeePartKey = "neutrinoOut_swap_feePart"
171177
172178 let WavesOutFeePartKey = "wavesOut_swap_feePart"
173179
174180 func keyNodeRegistry (address) = ("%s__" + address)
175181
176182
177183 let PriceKey = "price"
178184
179185 let PriceIndexKey = "price_index"
180186
181187 let IsBlockedKey = "is_blocked"
182188
183189 func getPriceHistoryKey (block) = ((PriceKey + "_") + toString(block))
184190
185191
186192 func getHeightPriceByIndexKey (index) = ((PriceIndexKey + "_") + toString(index))
187193
188194
189195 func getStakingNodeByIndex (idx) = getStringByKey(makeString(["%s%d%s", "lease", toString(idx), "nodeAddress"], SEP))
190196
191197
192198 func getStakingNodeAddressByIndex (idx) = addressFromStringValue(getStakingNodeByIndex(idx))
193199
194200
195201 func getReservedAmountForSponsorship () = valueOrElse(getInteger(this, makeString(["%s%s", "lease", "sponsorshipWavesReserve"], SEP)), (1000 * WAVELET))
196202
197203
198204 func getBalanceUnlockBlockKey (owner) = ("balance_unlock_block_" + owner)
199205
200206
201207 func getLeaseIdKey (nodeIndex) = makeString(["%s%d%s", "lease", toString(nodeIndex), "id"], SEP)
202208
203209
204210 func getLeaseIdByAddressKey (nodeAddress) = makeString(["%s%s%s", "leaseByAddress", nodeAddress, "id"], SEP)
205211
206212
207213 func getLeaseAmountKey (nodeIndex) = makeString(["%s%d%s", "lease", toString(nodeIndex), "amount"], SEP)
208214
209215
210216 func getLeaseAmountByAddressKey (nodeAddress) = makeString(["%s%s%s", "leaseByAddress", nodeAddress, "amount"], SEP)
211217
212218
213219 func getLeaseGroupNodeListKey (groupNum) = makeString(["%s%d%s", "leaseGroup", toString(groupNum), "nodeList"], SEP)
214220
215221
216222 func minSwapAmountKEY (swapType) = (("min_" + swapType) + "_swap_amount")
217223
218224
219225 func totalLockedKEY (swapType) = ("balance_lock_" + swapType)
220226
221227
222228 func totalLockedByUserKEY (swapType,owner) = makeString(["balance_lock", swapType, owner], "_")
223229
224230
225231 func balanceLockIntervalKEY (swapType) = (("balance_" + swapType) + "_lock_interval")
226232
227233
228234 func nodeBalanceLockIntervalKEY () = "balance_node_lock_interval"
229235
230236
231237 func outFeePartKEY (swapType) = (swapType + "Out_swap_feePart")
232238
233239
234240 func swapsTimeframeKEY () = "swaps_timeframe"
235241
236242
237243 func brProtectedKEY () = "min_BR_protection_level"
238244
239245
240246 func minSwapAmountREAD (swapType) = valueOrElse(getInteger(this, minSwapAmountKEY(swapType)), 0)
241247
242248
243249 func swapsTimeframeREAD () = valueOrElse(getInteger(this, swapsTimeframeKEY()), 1440)
244250
245251
246252 func totalLockedREAD (swapType) = valueOrElse(getInteger(this, totalLockedKEY(swapType)), 0)
247253
248254
249255 func totalLockedByUserREAD (swapType,owner) = valueOrElse(getInteger(this, totalLockedByUserKEY(swapType, owner)), 0)
250256
251257
252258 func balanceLockIntervalREAD (swapType) = valueOrElse(getInteger(this, balanceLockIntervalKEY(swapType)), 1440)
253259
254260
255261 func nodeBalanceLockIntervalREAD () = valueOrElse(getInteger(this, nodeBalanceLockIntervalKEY()), 1)
256262
257263
258264 func keySwapUserSpentInPeriod (userAddress) = makeString(["%s%s", "swapUserSpentInPeriod", userAddress], SEP)
259265
260266
261267 func keyUserLastSwapHeight (userAddress) = makeString(["%s%s", "userLastSwapHeight", userAddress], SEP)
262268
263269
264270 func convertNeutrinoToWaves (amount,price) = fraction(fraction(amount, PRICELET, price), WAVELET, PAULI)
265271
266272
267273 func convertWavesToNeutrino (amount,price) = fraction(fraction(amount, price, PRICELET), PAULI, WAVELET)
268274
269275
270276 func convertWavesToBond (amount,price) = convertWavesToNeutrino(amount, price)
271277
272278
273279 func convertJsonArrayToList (jsonArray) = split(jsonArray, ",")
274280
275281
276282 func minSwapAmountFAIL (swapType,minSwapAmount) = throw(((("The specified amount in " + swapType) + " swap is less than the required minimum of ") + toString(minSwapAmount)))
277283
278284
279285 func emergencyShutdownFAIL () = throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
280286
281287
282288 func priceIndexFAIL (index,priceIndex,indexHeight,unlockHeight,prevIndexHeight) = throw(((((((((("invalid price history index: index=" + toString(index)) + " priceIndex=") + toString(priceIndex)) + " indexHeight=") + toString(indexHeight)) + " unlockHeight=") + toString(unlockHeight)) + " prevIndexHeight=") + toString(prevIndexHeight)))
283289
284290
285291 let neutrinoAssetId = fromBase58String(getStringByKey(NeutrinoAssetIdKey))
286292
287293 let priceIndex = getNumberByAddressAndKey(controlContract, PriceIndexKey)
288294
289295 let isBlocked = getBoolByAddressAndKey(controlContract, IsBlockedKey)
290296
291297 let nodeOracleProviderPubKey = fromBase58String(getStringByKey(NodeOracleProviderPubKeyKey))
292298
293299 let bondAssetId = fromBase58String("F3iaxzruFeKujfVfYSZEkejpjh67wmRfPCRHiNmWKp3Z")
294300
295301 let deprecatedBondAssetId = fromBase58String("975akZBfnMj513U7MZaHKzQrmsEx5aE3wdWKTrHBhbjF")
296302
297303 let neutrinoContract = this
298304
299305 let currentPrice = getNumberByAddressAndKey(controlContract, PriceKey)
300306
301307 func checkIsValidMinSponsoredFee (tx) = {
302308 let MINTRANSFERFEE = 100000
303309 let SponsoredFeeUpperBound = 1000
304310 let realNeutrinoFee = convertWavesToNeutrino(MINTRANSFERFEE, currentPrice)
305311 let minNeutrinoFee = (realNeutrinoFee * 2)
306312 let maxNeutrinoFee = fraction(realNeutrinoFee, SponsoredFeeUpperBound, 100)
307313 let inputFee = value(tx.minSponsoredAssetFee)
308314 if (if ((inputFee >= minNeutrinoFee))
309315 then (maxNeutrinoFee >= inputFee)
310316 else false)
311317 then (tx.assetId == neutrinoAssetId)
312318 else false
313319 }
314320
315321
316322 func getPriceHistory (block) = getNumberByAddressAndKey(controlContract, getPriceHistoryKey(block))
317323
318324
319325 func getHeightPriceByIndex (index) = getNumberByAddressAndKey(controlContract, getHeightPriceByIndexKey(index))
320326
321327
322328 func keyLockParamUserAmount (userAddress) = makeString(["%s%s%s", "paramByUser", userAddress, "amount"], SEP)
323329
324330
325331 let sIdxSwapType = 1
326332
327333 let sIdxStatus = 2
328334
329335 let sIdxInAmount = 3
330336
331337 let sIdxPrice = 4
332338
333339 let sIdxOutNetAmount = 5
334340
335341 let sIdxOutFeeAmount = 6
336342
337343 let sIdxStartHeight = 7
338344
339345 let sIdxStartTimestamp = 8
340346
341347 let sIdxEndHeight = 9
342348
343349 let sIdxEndTimestamp = 10
344350
345351 let sIdxSelfUnlockHeight = 11
346352
347353 let sIdxRandUnlockHeight = 12
348354
349355 let sIdxIndex = 13
350356
351357 let sIdxWithdrawTxId = 14
352358
353359 let sIdxMinRand = 15
354360
355361 let sIdxMaxRand = 16
356362
357363 let sIdxOutSurfAmount = 17
358364
359365 let sIdxBR = 18
360366
361367 func swapKEY (userAddress,txId) = makeString(["%s%s", userAddress, txId], SEP)
362368
363369
364370 func strSwapDATA (swapType,status,inAmount,price,outNetAmount,outFeeAmount,startHeight,startTimestamp,endHeight,endTimestamp,selfUnlockHeight,randUnlockHeight,index,withdrawTxId,randMin,randMax,outSurfAmt,br) = makeString(["%s%s%d%d%d%d%d%d%d%d%d%d%d%s%d%d%d%d", swapType, status, inAmount, price, outNetAmount, outFeeAmount, startHeight, startTimestamp, endHeight, endTimestamp, selfUnlockHeight, randUnlockHeight, index, withdrawTxId, randMin, randMax, outSurfAmt, br], SEP)
365371
366372
367373 func pendingSwapDATA (swapType,inAssetAmount,selfUnlockHeight) = strSwapDATA(swapType, "PENDING", toString(inAssetAmount), "0", "0", "0", toString(height), toString(lastBlock.timestamp), "0", "0", toString(selfUnlockHeight), "0", "0", "NULL", "0", "0", "0", "0")
368374
369375
370376 func finishSwapDATA (dataArray,price,outNetAmount,outFeeAmount,randUnlockHeight,index,withdrawTxId,outSurfAmt,br) = strSwapDATA(dataArray[sIdxSwapType], "FINISHED", dataArray[sIdxInAmount], toString(price), toString(outNetAmount), toString(outFeeAmount), dataArray[sIdxStartHeight], dataArray[sIdxStartTimestamp], toString(height), toString(lastBlock.timestamp), dataArray[sIdxSelfUnlockHeight], toString(randUnlockHeight), toString(index), withdrawTxId, dataArray[sIdxMinRand], dataArray[sIdxMaxRand], toString(outSurfAmt), toString(br))
371377
372378
373379 func swapDataFailOrREAD (userAddress,swapTxId) = {
374380 let swapKey = swapKEY(userAddress, swapTxId)
375381 split(valueOrErrorMessage(getString(this, swapKey), ("no swap data for " + swapKey)), SEP)
376382 }
377383
378384
379385 func applyFees (amountOutGross,inAmtToSURF,feePart) = {
380386 let feeAmount = fraction(amountOutGross, feePart, PAULI)
381387 [(amountOutGross - feeAmount), feeAmount]
382388 }
383389
384390
385391 func abs (x) = if ((0 > x))
386392 then -(x)
387393 else x
388394
389395
390396 func selectNode (unleaseAmount) = {
391397 let amountToLease = ((wavesBalance(neutrinoContract).available - unleaseAmount) - getReservedAmountForSponsorship())
392398 let oldLeased0 = getNumberByKey(getLeaseAmountKey(0))
393399 let oldLeased1 = getNumberByKey(getLeaseAmountKey(1))
394400 let newLeased0 = (amountToLease + oldLeased0)
395401 let newLeased1 = (amountToLease + oldLeased1)
396402 if (if ((newLeased0 > 0))
397403 then true
398404 else (newLeased1 > 0))
399405 then {
400406 let delta0 = abs((newLeased0 - oldLeased1))
401407 let delta1 = abs((newLeased1 - oldLeased0))
402408 if ((delta1 >= delta0))
403409 then $Tuple2(0, newLeased0)
404410 else $Tuple2(1, newLeased1)
405411 }
406412 else $Tuple2(-1, 0)
407413 }
408414
409415
410416 func thisOnly (i) = if ((i.caller != this))
411417 then throw("Permission denied: this contract only allowed")
412418 else true
413419
414420
415421 func prepareUnleaseAndLease (unleaseAmount) = {
416422 let nodeTuple = selectNode(unleaseAmount)
417423 let nodeIndex = nodeTuple._1
418424 let newLeaseAmount = nodeTuple._2
419425 if ((newLeaseAmount > 0))
420426 then {
421427 let leaseIdKey = getLeaseIdKey(nodeIndex)
422428 let oldLease = getBinary(this, leaseIdKey)
423429 let unleaseOrEmpty = if (isDefined(oldLease))
424430 then [LeaseCancel(value(oldLease))]
425431 else nil
426432 let leaseAmountKey = getLeaseAmountKey(nodeIndex)
427433 let lease = Lease(getStakingNodeAddressByIndex(nodeIndex), newLeaseAmount)
428434 (unleaseOrEmpty ++ [lease, BinaryEntry(leaseIdKey, lcalc(lease)), IntegerEntry(getLeaseAmountKey(nodeIndex), newLeaseAmount)])
429435 }
430436 else nil
431437 }
432438
433439
434440 func readNodeInfo (nodeIdx) = {
435441 let nodeAddress = getStakingNodeAddressByIndex(nodeIdx)
436442 let leasedAmtKEY = getLeaseAmountKey(nodeIdx)
437443 let leasedAmt = getNumberByKey(leasedAmtKEY)
438444 let leaseIdKEY = getLeaseIdKey(nodeIdx)
439445 let leaseId = value(getBinary(this, leaseIdKEY))
440446 $Tuple5(nodeAddress, leasedAmtKEY, leasedAmt, leaseIdKEY, leaseId)
441447 }
442448
443449
444450 func commonSwap (swapType,pmtAmount,userAddressStr,txId58,swapParamsByUserSYSREADONLY) = {
445451 let swapLimitSpent = swapParamsByUserSYSREADONLY._2
446452 let blcks2LmtReset = swapParamsByUserSYSREADONLY._3
447453 let wavesSwapLimitMax = swapParamsByUserSYSREADONLY._6
448454 let usdnSwapLimitMax = swapParamsByUserSYSREADONLY._7
449455 let minSwapAmount = minSwapAmountREAD(swapType)
450456 let totalLocked = totalLockedREAD(swapType)
451457 let totalLockedByUser = totalLockedByUserREAD(swapType, userAddressStr)
452458 let nodeAddress = getStakingNodeByIndex(0)
453459 let priceByIndex = getPriceHistory(getHeightPriceByIndex(priceIndex))
454460 let isSwapByNode = (nodeAddress == userAddressStr)
455461 let balanceLockMaxInterval = if (isSwapByNode)
456462 then nodeBalanceLockIntervalREAD()
457463 else balanceLockIntervalREAD(swapType)
458464 let selfUnlockHeight = (height + balanceLockMaxInterval)
459465 let swapUsdnVolume = if ((swapType == "neutrino"))
460466 then pmtAmount
461467 else convertWavesToNeutrino(pmtAmount, priceByIndex)
462468 let swapLimitMax = if ((swapType == "neutrino"))
463469 then usdnSwapLimitMax
464470 else convertWavesToNeutrino(wavesSwapLimitMax, priceByIndex)
465471 if ((minSwapAmount > pmtAmount))
466472 then minSwapAmountFAIL(swapType, minSwapAmount)
467473 else if (if (!(isSwapByNode))
468474 then (swapLimitSpent > 0)
469475 else false)
470476 then throw(("You have exceeded swap limit! Next allowed swap height is " + toString((height + blcks2LmtReset))))
471477 else if (if (!(isSwapByNode))
472478 then (swapUsdnVolume > swapLimitMax)
473479 else false)
474480 then throw(((("You have exceeded your swap limit! Requested: " + toString(swapUsdnVolume)) + ", available: ") + toString(swapLimitMax)))
475481 else if (isBlocked)
476482 then emergencyShutdownFAIL()
477483 else {
478484 let leasePart = if ((swapType == "waves"))
479485 then prepareUnleaseAndLease(0)
480486 else nil
481487 $Tuple2(([IntegerEntry(keySwapUserSpentInPeriod(userAddressStr), swapUsdnVolume), IntegerEntry(keyUserLastSwapHeight(userAddressStr), height), IntegerEntry(totalLockedByUserKEY(swapType, userAddressStr), (totalLockedByUser + pmtAmount)), IntegerEntry(getBalanceUnlockBlockKey(userAddressStr), selfUnlockHeight), IntegerEntry(totalLockedKEY(swapType), (totalLocked + pmtAmount)), StringEntry(swapKEY(userAddressStr, txId58), pendingSwapDATA(swapType, pmtAmount, selfUnlockHeight))] ++ leasePart), unit)
482488 }
483489 }
484490
485491
486492 let nMetricIdxPrice = 0
487493
488494 let nMetricIdxUsdnLockedBalance = 1
489495
490496 let nMetricIdxWavesLockedBalance = 2
491497
492498 let nMetricIdxReserve = 3
493499
494500 let nMetricIdxReserveInUsdn = 4
495501
496502 let nMetricIdxUsdnSupply = 5
497503
498504 let nMetricIdxSurplus = 6
499505
500506 let nMetricIdxSurplusPercent = 7
501507
502508 let nMetricIdxBR = 8
503509
504510 let nMetricIdxNsbtSupply = 9
505511
506512 let nMetricIdxMaxNsbtSupply = 10
507513
508514 let nMetricIdxSurfSupply = 11
509515
510516 let bFuncIdxSurf = 0
511517
512518 let bFuncIdxWaves = 1
513519
514520 let bFuncIdxUsdn = 2
515521
516522 let bFuncIdxReserveStart = 3
517523
518524 let bFuncIdxSupplyStart = 4
519525
520526 let bFuncIdxBRStart = 5
521527
522528 let bFuncIdxReserveEnd = 6
523529
524530 let bFuncIdxSupplyEnd = 7
525531
526532 let bFuncIdxBREnd = 8
527533
528534 let bFuncIdxRest = 9
529535
530536 let bFuncIdxWavesPrice = 10
531537
532538 func calcWithdrawW2U (wavesIn,price) = {
533539 let outAmtGross = convertWavesToNeutrino(wavesIn, price)
534540 $Tuple9(outAmtGross, neutrinoAssetId, 0, unit, 0, wavesIn, 0, 0, 0)
535541 }
536542
537543
538544 func calcWithdrawU2W (usdnIn,price,br,reservesInUsdn,usdnSupply) = {
539545 let brProtected = valueOrElse(getInteger(this, brProtectedKEY()), BRPROTECTED)
540546 let maxAllowedUsdnBeforeMinBr = if ((brProtected >= br))
541547 then 0
542548 else fraction((reservesInUsdn - fraction(brProtected, usdnSupply, PAULI)), PAULI, (PAULI - brProtected))
543549 let allowedUsdnBeforeMinBr = if ((usdnIn > maxAllowedUsdnBeforeMinBr))
544550 then maxAllowedUsdnBeforeMinBr
545551 else usdnIn
546552 let allowedUsdnAfterMinBr = if ((usdnIn > maxAllowedUsdnBeforeMinBr))
547553 then fraction((usdnIn - maxAllowedUsdnBeforeMinBr), br, PAULI)
548554 else 0
549555 let allowedUsdn = (allowedUsdnBeforeMinBr + allowedUsdnAfterMinBr)
550556 let usdn2SURF = (usdnIn - allowedUsdn)
551557 let outAmtGross = convertNeutrinoToWaves(allowedUsdn, price)
552558 $Tuple9(outAmtGross, unit, usdn2SURF, neutrinoAssetId, outAmtGross, allowedUsdn, maxAllowedUsdnBeforeMinBr, allowedUsdnBeforeMinBr, allowedUsdnAfterMinBr)
553559 }
554560
555561
556562 func calcWithdraw (swapType,inAmount,price,neutrinoMetrics) = {
557563 let outFeePart = valueOrElse(getInteger(this, outFeePartKEY(swapType)), DEFAULTSWAPFEE)
558564 if (if ((0 > outFeePart))
559565 then true
560566 else (outFeePart >= PAULI))
561567 then throw(((("invalid outFeePart config for " + swapType) + " swap: outFeePart=") + toString(outFeePart)))
562568 else {
563569 let brProtected = valueOrElse(getInteger(this, brProtectedKEY()), BRPROTECTED)
564570 let BR = asInt(neutrinoMetrics[nMetricIdxBR])
565571 let reservesInUsdn = asInt(neutrinoMetrics[nMetricIdxReserveInUsdn])
566572 let usdnSupply = asInt(neutrinoMetrics[nMetricIdxUsdnSupply])
567573 let outDataTuple = if ((swapType == "waves"))
568574 then calcWithdrawW2U(inAmount, price)
569575 else if ((swapType == "neutrino"))
570576 then calcWithdrawU2W(inAmount, price, BR, reservesInUsdn, usdnSupply)
571577 else throw(("Unsupported swap type " + swapType))
572578 let outAmtGross = outDataTuple._1
573579 let outAssetId = outDataTuple._2
574580 let inAmtToSurfPart = outDataTuple._3
575581 let inAssetId = outDataTuple._4
576582 let unleaseAmt = outDataTuple._5
577583 let payoutsArray = applyFees(outAmtGross, inAmtToSurfPart, outFeePart)
578584 let outNetAmt = payoutsArray[IdxNetAmount]
579585 let outFeeAmt = payoutsArray[IdxFeeAmount]
580586 let outSurfAmt = if ((0 >= inAmtToSurfPart))
581587 then 0
582588 else {
583589 let surfResult = asAnyList(invoke(mathContract, "surfFunctionREADONLY", [inAmtToSurfPart, inAssetId], nil))
584590 asInt(surfResult[bFuncIdxSurf])
585591 }
586592 $Tuple7(outNetAmt, outAssetId, outSurfAmt, inAmtToSurfPart, unleaseAmt, outFeeAmt, outAmtGross)
587593 }
588594 }
589595
590596
591597 func commonWithdraw (account,index,swapTxId,withdrawTxId,neutrinoMetrics) = {
592598 let userAddress = addressFromStringValue(account)
593599 let dataArray = swapDataFailOrREAD(account, swapTxId)
594600 let selfUnlockHeight = parseIntValue(dataArray[sIdxSelfUnlockHeight])
595601 let swapType = dataArray[sIdxSwapType]
596602 let inAmount = parseIntValue(dataArray[sIdxInAmount])
597603 let swapStatus = dataArray[sIdxStatus]
598604 let startHeight = parseIntValue(dataArray[sIdxStartHeight])
599605 let outFeePart = valueOrElse(getInteger(this, outFeePartKEY(swapType)), DEFAULTSWAPFEE)
600606 let totalLocked = totalLockedREAD(swapType)
601607 let totalLockedByUser = totalLockedByUserREAD(swapType, account)
602608 let unlockHeight = selfUnlockHeight
603609 let indexHeight = getHeightPriceByIndex(index)
604610 let prevIndexHeight = getHeightPriceByIndex((index - 1))
605611 let priceByIndex = getPriceHistory(indexHeight)
606612 if (isBlocked)
607613 then emergencyShutdownFAIL()
608614 else if ((swapStatus != "PENDING"))
609615 then throw("swap has been already processed")
610616 else if ((unlockHeight > height))
611617 then throw((("please wait for: " + toString(unlockHeight)) + " block height to withdraw funds"))
612618 else if (if (if ((index > priceIndex))
613619 then true
614620 else (unlockHeight > indexHeight))
615621 then true
616622 else if ((prevIndexHeight != 0))
617623 then (prevIndexHeight >= unlockHeight)
618624 else false)
619625 then priceIndexFAIL(index, priceIndex, indexHeight, unlockHeight, prevIndexHeight)
620626 else {
621627 let withdrawTuple = calcWithdraw(swapType, inAmount, priceByIndex, neutrinoMetrics)
622628 let outNetAmount = withdrawTuple._1
623629 let outAssetId = withdrawTuple._2
624630 let outSurfAmt = withdrawTuple._3
625631 let inAmtToSurfPart = withdrawTuple._4
626632 let unleaseAmt = withdrawTuple._5
627633 let outFeeAmount = withdrawTuple._6
628634 let outAmtGross = withdrawTuple._7
629635 if ((0 >= outAmtGross))
630636 then throw("balance equals zero")
631637 else {
632638 let BR = asInt(neutrinoMetrics[nMetricIdxBR])
633639 let state = [IntegerEntry(totalLockedByUserKEY(swapType, account), (totalLockedByUser - inAmount)), IntegerEntry(totalLockedKEY(swapType), (totalLocked - inAmount)), ScriptTransfer(userAddress, outNetAmount, outAssetId), StringEntry(swapKEY(account, swapTxId), finishSwapDATA(dataArray, priceByIndex, outNetAmount, outFeeAmount, unlockHeight, index, withdrawTxId, outSurfAmt, BR))]
634640 let surfCondition = if ((outSurfAmt > 0))
635641 then {
636642 let issueResult = invoke(auctionContract, "issueSurf", [outSurfAmt, account], nil)
637643 if ((issueResult == issueResult))
638644 then 0
639645 else throw("Strict value is not equal to itself.")
640646 }
641647 else 0
642648 if ((surfCondition == surfCondition))
643649 then $Tuple3(state, AttachedPayment(outAssetId, outFeeAmount), unleaseAmt)
644650 else throw("Strict value is not equal to itself.")
645651 }
646652 }
647653 }
648654
649655
650656 @Callable(i)
651657 func constructor (neutrinoAssetIdPrm,bondAssetIdPrm,auctionContractPrm,liquidationContractPrm,rpdContractPrm,nodeOracleProviderPubKeyPrm,balanceWavesLockIntervalPrm,balanceNeutrinoLockIntervalPrm,minWavesSwapAmountPrm,minNeutrinoSwapAmountPrm,neutrinoOutFeePartPrm,wavesOutFeePartPrm) = {
652658 let checkCaller = thisOnly(i)
653659 if ((checkCaller == checkCaller))
654660 then if ((size(i.payments) != 0))
655661 then throw("no payments allowed")
656662 else [StringEntry(NeutrinoAssetIdKey, neutrinoAssetIdPrm), StringEntry(BondAssetIdKey, bondAssetIdPrm), StringEntry(AuctionContractKey, auctionContractPrm), StringEntry(LiquidationContractKey, liquidationContractPrm), StringEntry(RPDContractKey, rpdContractPrm), StringEntry(NodeOracleProviderPubKeyKey, nodeOracleProviderPubKeyPrm), IntegerEntry(BalanceWavesLockIntervalKey, balanceWavesLockIntervalPrm), IntegerEntry(BalanceNeutrinoLockIntervalKey, balanceNeutrinoLockIntervalPrm), IntegerEntry(MinWavesSwapAmountKey, minWavesSwapAmountPrm), IntegerEntry(MinNeutrinoSwapAmountKey, minNeutrinoSwapAmountPrm), IntegerEntry(NeutrinoOutFeePartKey, neutrinoOutFeePartPrm), IntegerEntry(WavesOutFeePartKey, wavesOutFeePartPrm)]
657663 else throw("Strict value is not equal to itself.")
658664 }
659665
660666
661667
662668 @Callable(i)
663669 func constructorV2 (mathContract,nsbtStakingContract,swapsTimeframeBlocks) = {
664670 let checkCaller = thisOnly(i)
665671 if ((checkCaller == checkCaller))
666672 then if ((size(i.payments) != 0))
667673 then throw("no payments allowed")
668674 else [StringEntry(MathContractKey, mathContract), StringEntry(NsbtStakingContractKey, nsbtStakingContract), IntegerEntry(swapsTimeframeKEY(), swapsTimeframeBlocks)]
669675 else throw("Strict value is not equal to itself.")
670676 }
671677
672678
673679
674680 @Callable(i)
675681 func swapWavesToNeutrino () = if ((size(i.payments) != 1))
676682 then throw("swapWavesToNeutrino require only one payment")
677683 else {
678684 let pmt = value(i.payments[0])
679685 if (isDefined(pmt.assetId))
680686 then throw("Only Waves token is allowed for swapping.")
681687 else {
682688 let userAddress = toString(i.caller)
683689 let txId58 = toBase58String(i.transactionId)
684690 let swapParamsSTRUCT = asSwapParamsSTRUCT(invoke(this, "swapParamsByUserSYSREADONLY", [userAddress, 0], nil))
685691 let commonSwapResult = commonSwap("waves", pmt.amount, userAddress, txId58, swapParamsSTRUCT)
686692 commonSwapResult
687693 }
688694 }
689695
690696
691697
692698 @Callable(i)
693699 func swapNeutrinoToWaves () = if ((size(i.payments) != 1))
694700 then throw("swapNeutrinoToWaves require only one payment")
695701 else {
696702 let pmt = value(i.payments[0])
697703 if ((pmt.assetId != neutrinoAssetId))
698704 then throw("Only appropriate Neutrino tokens are allowed for swapping.")
699705 else {
700706 let userAddress = toString(i.caller)
701707 let txId58 = toBase58String(i.transactionId)
702708 let swapParamsSTRUCT = asSwapParamsSTRUCT(invoke(this, "swapParamsByUserSYSREADONLY", [userAddress, 0], nil))
703709 let commonSwapResult = commonSwap("neutrino", pmt.amount, userAddress, txId58, swapParamsSTRUCT)
704710 commonSwapResult
705711 }
706712 }
707713
708714
709715
710716 @Callable(i)
711717 func withdraw (account,index,swapTxId) = {
712718 let txId = toBase58String(i.transactionId)
713719 if ((size(i.payments) != 0))
714720 then throw("no payments allowed")
715721 else {
716722 let neutrinoMetrics = asAnyList(invoke(mathContract, "calcNeutinoMetricsREADONLY", nil, nil))
717723 let BR = asInt(neutrinoMetrics[nMetricIdxBR])
718724 let commonTuple = commonWithdraw(account, index, swapTxId, txId, neutrinoMetrics)
719725 let state = commonTuple._1
720726 let fee = commonTuple._2
721727 let unleaseAmt = commonTuple._3
722728 let unleaseInvOrEmpty = invoke(this, "internalUnleaseAndLease", [unleaseAmt], nil)
723729 if ((unleaseInvOrEmpty == unleaseInvOrEmpty))
724730 then {
725731 let gnsbtData = asAnyList(invoke(gnsbtControllerContract, "gnsbtInfoSYSREADONLY", ["", 0, 0], nil))
726732 let gnsbtAmtTotal = asInt(gnsbtData[1])
727733 let gnsbtAmtFromSurfTotal = asInt(asAnyList(gnsbtData[3])[3])
728734 let surfFeeAmt1 = if ((gnsbtAmtTotal != 0))
729735 then fraction(fee.amount, gnsbtAmtFromSurfTotal, gnsbtAmtTotal)
730736 else 0
731737 let surfFeeAmt2 = if ((gnsbtAmtTotal != 0))
732738 then fraction(fee.amount, (PAULI - BR), PAULI)
733739 else 0
734740 let surfFeeAmt = max([surfFeeAmt1, surfFeeAmt2])
735741 let nsbtFeeAmt = (fee.amount - surfFeeAmt)
736742 let surfDeposit = if ((surfFeeAmt > 0))
737743 then {
738744 let surfInv = invoke(surfStakingContract, "deposit", nil, [AttachedPayment(fee.assetId, surfFeeAmt)])
739745 if ((surfInv == surfInv))
740746 then nil
741747 else throw("Strict value is not equal to itself.")
742748 }
743749 else nil
744750 if ((surfDeposit == surfDeposit))
745751 then {
746752 let nsbtDeposit = if ((nsbtFeeAmt > 0))
747753 then {
748754 let nsbtInv = invoke(nsbtStakingContract, "deposit", nil, [AttachedPayment(fee.assetId, nsbtFeeAmt)])
749755 if ((nsbtInv == nsbtInv))
750756 then nil
751757 else throw("Strict value is not equal to itself.")
752758 }
753759 else nil
754760 if ((nsbtDeposit == nsbtDeposit))
755761 then state
756762 else throw("Strict value is not equal to itself.")
757763 }
758764 else throw("Strict value is not equal to itself.")
759765 }
760766 else throw("Strict value is not equal to itself.")
761767 }
762768 }
763769
764770
765771
766772 @Callable(i)
767773 func internalUnleaseAndLease (unleaseAmount) = if ((i.caller != this))
768774 then throw("internalUnleaseAndLease is not public method")
769775 else prepareUnleaseAndLease(unleaseAmount)
770776
771777
772778
773779 @Callable(i)
774780 func transferUsdnToUser (amount,addr) = if ((i.caller != auctionContract))
775781 then throw("Only auction contract is authorized")
776782 else [ScriptTransfer(addressFromStringValue(addr), amount, neutrinoAssetId)]
777783
778784
779785
780786 @Callable(i)
781-func acceptWaves () = if ((i.caller != auctionContract))
782- then throw("Currently only auction contract is allowed to call")
787+func acceptWaves () = if (if ((i.caller != auctionContract))
788+ then (i.caller != governanceContract)
789+ else false)
790+ then throw("Currently only auction and governance contracts are allowed to call")
783791 else $Tuple2(prepareUnleaseAndLease(0), "success")
784792
785793
786794
787795 @Callable(i)
788796 func approveLeasings (nListS,groupNum,lAmt) = {
789797 let nIdxs = [0, 1, 2, 3, 4, 5, 6, 7]
790798 let mngPubS = valueOrElse(getString("%s%s__cfg__leasingManagerPub"), "7AUMX54ukYMYvPmma7yoFf5NjZhs4Bu5nz3Ez9EV8sur")
791799 let mngPub = fromBase58String(mngPubS)
792800 let nodeRegAddrStr = valueOrElse(getString("%s%s__cfg__nodesRegistryAddress"), "3P9vKqQKjUdmpXAfiWau8krREYAY1Xr69pE")
793801 let nodeRegAddr = addressFromStringValue(nodeRegAddrStr)
794802 let lGroupNodeListKEY = getLeaseGroupNodeListKey(groupNum)
795803 let lGrNodeOpt = getString(this, lGroupNodeListKEY)
796804 if (isDefined(lGrNodeOpt))
797805 then throw((("group " + toString(groupNum)) + " already initialized"))
798806 else {
799807 let nList = split(nListS, SEP)
800808 let expCount = size(nIdxs)
801809 if ((i.callerPublicKey != mngPub))
802810 then throw("approveLeasings not authorized")
803811 else {
804- let $t03446334525 = readNodeInfo(0)
805- let nAddr0 = $t03446334525._1
806- let lAmtKEY0 = $t03446334525._2
807- let lAmt0 = $t03446334525._3
808- let lIdKEY0 = $t03446334525._4
809- let lId0 = $t03446334525._5
812+ let $t03469534757 = readNodeInfo(0)
813+ let nAddr0 = $t03469534757._1
814+ let lAmtKEY0 = $t03469534757._2
815+ let lAmt0 = $t03469534757._3
816+ let lIdKEY0 = $t03469534757._4
817+ let lId0 = $t03469534757._5
810818 let newL0 = Lease(nAddr0, (lAmt0 - (lAmt * expCount)))
811819 let validation = invoke(nodeRegAddr, "validateAndApproveLeasings", [nListS], nil)
812820 if ((validation == validation))
813821 then {
814822 func forEachNodeValidateAndGenerateLease (a,i) = {
815823 let node = nList[i]
816824 let la = Lease(addressFromStringValue(node), lAmt)
817825 (a ++ [la, BinaryEntry(getLeaseIdByAddressKey(node), lcalc(la)), IntegerEntry(getLeaseAmountByAddressKey(node), lAmt)])
818826 }
819827
820828 ([StringEntry(lGroupNodeListKEY, nListS), BinaryEntry(lIdKEY0, lcalc(newL0)), IntegerEntry(lAmtKEY0, newL0.amount), LeaseCancel(lId0), newL0] ++ {
821829 let $l = nIdxs
822830 let $s = size($l)
823831 let $acc0 = nil
824832 func $f0_1 ($a,$i) = if (($i >= $s))
825833 then $a
826834 else forEachNodeValidateAndGenerateLease($a, $l[$i])
827835
828836 func $f0_2 ($a,$i) = if (($i >= $s))
829837 then $a
830838 else throw("List size exceeds 8")
831839
832840 $f0_2($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)
833841 })
834842 }
835843 else throw("Strict value is not equal to itself.")
836844 }
837845 }
838846 }
839847
840848
841849
842850 @Callable(i)
843851 func rebalanceLeasings (amount,groupNum) = {
844852 let nIdxs = [0, 1, 2, 3, 4, 5, 6, 7]
845853 let mngPubS = valueOrElse(getString("%s%s__cfg__leasingManagerPub"), "7AUMX54ukYMYvPmma7yoFf5NjZhs4Bu5nz3Ez9EV8sur")
846854 let mngPub = fromBase58String(mngPubS)
847855 let lGroupNodeListKEY = getLeaseGroupNodeListKey(groupNum)
848856 let nListS = getStringOrFail(this, lGroupNodeListKEY)
849857 let nList = split(nListS, SEP)
850858 if ((i.callerPublicKey != mngPub))
851859 then throw("rebalanceLeasings not authorized")
852860 else {
853861 let unleaseAmt = ((amount / size(nList)) + 1)
854- let $t03576535827 = readNodeInfo(0)
855- let nAddr0 = $t03576535827._1
856- let lAmtKEY0 = $t03576535827._2
857- let lAmt0 = $t03576535827._3
858- let lIdKEY0 = $t03576535827._4
859- let lId0 = $t03576535827._5
862+ let $t03599736059 = readNodeInfo(0)
863+ let nAddr0 = $t03599736059._1
864+ let lAmtKEY0 = $t03599736059._2
865+ let lAmt0 = $t03599736059._3
866+ let lIdKEY0 = $t03599736059._4
867+ let lId0 = $t03599736059._5
860868 let newL0 = Lease(nAddr0, (lAmt0 + (unleaseAmt * size(nList))))
861869 func forEachNodeDoUnlease (a,i) = {
862870 let node = nList[i]
863871 let lIdKEY = getLeaseIdByAddressKey(node)
864872 let lId = getBinaryValue(this, lIdKEY)
865873 let lAmtKEY = getLeaseAmountByAddressKey(node)
866874 let lAmt = getIntegerValue(this, lAmtKEY)
867875 let ula = LeaseCancel(value(lId))
868876 let la = Lease(addressFromStringValue(node), (lAmt - unleaseAmt))
869877 (a ++ [LeaseCancel(value(lId)), la, BinaryEntry(lIdKEY, lcalc(la)), IntegerEntry(lAmtKEY, la.amount)])
870878 }
871879
872880 ({
873881 let $l = nIdxs
874882 let $s = size($l)
875883 let $acc0 = nil
876884 func $f0_1 ($a,$i) = if (($i >= $s))
877885 then $a
878886 else forEachNodeDoUnlease($a, $l[$i])
879887
880888 func $f0_2 ($a,$i) = if (($i >= $s))
881889 then $a
882890 else throw("List size exceeds 8")
883891
884892 $f0_2($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)
885893 } ++ [BinaryEntry(lIdKEY0, lcalc(newL0)), IntegerEntry(lAmtKEY0, newL0.amount), LeaseCancel(lId0), newL0])
886894 }
887895 }
888896
889897
890898
891899 @Callable(i)
892900 func swapParamsByUserSYSREADONLY (userAddressStr,gnsbtDiff) = {
893901 let gnsbtData = asAnyList(invoke(gnsbtControllerContract, "gnsbtInfoSYSREADONLY", [userAddressStr, 0, 0], nil))
894902 let gnsbtAmt = (asInt(gnsbtData[0]) + gnsbtDiff)
895903 let gnsbtAmtTotal = (asInt(gnsbtData[1]) + gnsbtDiff)
896904 let swapLimitData = asAnyList(invoke(mathContract, "calcSwapLimitREADONLY", [gnsbtAmt], nil))
897905 let wavesSwapLimitInUsdnMax = asInt(swapLimitData[0])
898906 let wavesSwapLimitMax = asInt(swapLimitData[1])
899907 let usdnSwapLimitMax = asInt(swapLimitData[2])
900908 let lastSwapHeight = valueOrElse(getInteger(this, keyUserLastSwapHeight(userAddressStr)), 0)
901909 let swapLimitTimelifeBlocks = swapsTimeframeREAD()
902910 let passedBlocksAfterLastSwap = (height - lastSwapHeight)
903911 let isSwapTimelifeNew = (passedBlocksAfterLastSwap >= swapLimitTimelifeBlocks)
904912 let swapLimitSpentInUsdn = if (isSwapTimelifeNew)
905913 then 0
906914 else valueOrElse(getInteger(this, keySwapUserSpentInPeriod(userAddressStr)), 0)
907915 let blcks2LmtReset = if (isSwapTimelifeNew)
908916 then 0
909917 else (swapLimitTimelifeBlocks - passedBlocksAfterLastSwap)
910918 $Tuple2(nil, $Tuple7(wavesSwapLimitInUsdnMax, swapLimitSpentInUsdn, blcks2LmtReset, gnsbtAmt, gnsbtAmtTotal, wavesSwapLimitMax, usdnSwapLimitMax))
911919 }
912920
913921
914922
915923 @Callable(i)
916924 func calcWithdrawResultSYSREADONLY (swapType,inAmount,price) = {
917925 let neutrinoMetrics = asAnyList(invoke(mathContract, "calcNeutinoMetricsREADONLY", nil, nil))
918926 $Tuple2(nil, calcWithdraw(swapType, inAmount, price, neutrinoMetrics))
919927 }
920928
921929
922930
923931 @Callable(i)
924932 func replaceCommunityNode (oldAddrStr,newAddrStr,groupNum,penaltyAmount) = {
925933 let mngPubS = valueOrElse(getString("%s%s__cfg__leasingManagerPub"), "7AUMX54ukYMYvPmma7yoFf5NjZhs4Bu5nz3Ez9EV8sur")
926934 let mngPub = fromBase58String(mngPubS)
927935 if ((i.callerPublicKey != mngPub))
928936 then throw("replaceCommunityNode not authorized")
929937 else {
930938 let groupKey = getLeaseGroupNodeListKey(groupNum)
931939 let groupNodeListS = getStringOrFail(this, groupKey)
932940 if (!(contains(groupNodeListS, oldAddrStr)))
933941 then throw(((("Group " + toString(groupNum)) + " does not contain address ") + oldAddrStr))
934942 else {
935943 let doReplace = invoke(nodeRegistryContract, "replaceApprovedNode", [oldAddrStr, newAddrStr, groupNum, penaltyAmount], nil)
936944 if ((doReplace == doReplace))
937945 then {
938946 let oldLeaseIdKey = getLeaseIdByAddressKey(oldAddrStr)
939947 let oldLeaseAmtKey = getLeaseAmountByAddressKey(oldAddrStr)
940948 let leaseAmt = getIntegerValue(oldLeaseAmtKey)
941949 let newLeaseIdKey = getLeaseIdByAddressKey(oldAddrStr)
942950 let newLeaseAmtKey = getLeaseAmountByAddressKey(oldAddrStr)
943951 let newLease = Lease(addressFromStringValue(newAddrStr), leaseAmt)
944952 let updatedGroupNodeListS = makeString(split(groupNodeListS, oldAddrStr), newAddrStr)
945953 $Tuple2([LeaseCancel(getBinaryValue(oldLeaseIdKey)), DeleteEntry(oldLeaseIdKey), DeleteEntry(oldLeaseAmtKey), StringEntry(groupKey, updatedGroupNodeListS), newLease, BinaryEntry(newLeaseIdKey, lcalc(newLease)), IntegerEntry(newLeaseAmtKey, leaseAmt)], unit)
946954 }
947955 else throw("Strict value is not equal to itself.")
948956 }
949957 }
950958 }
951959
952960
953961
954962 @Callable(i)
955963 func updateReservesAndNeutrinoSupply () = {
956964 func getNumberByKeyInternal (key) = match getInteger(this, key) {
957965 case a: Int =>
958966 a
959967 case _ =>
960968 0
961969 }
962970
963971 let nMetrix = asAnyList(invoke(mathContract, "calcNeutinoMetricsREADONLY", nil, nil))
964972 let idx = getNumberByKeyInternal("updateReservesAndNeutrinoSupplyIdx")
965973 let newIdx = (idx + 1)
966974 [IntegerEntry("updateReservesAndNeutrinoSupplyIdx", newIdx), IntegerEntry("reserve", asInt(nMetrix[3])), IntegerEntry("neutrinoSupply", asInt(nMetrix[5])), IntegerEntry("reservesInUsdn", convertWavesToNeutrino(asInt(nMetrix[3]), asInt(nMetrix[0]))), IntegerEntry("surplus", asInt(nMetrix[6])), IntegerEntry("deficit", -(asInt(nMetrix[6])))]
967975 }
968976
969977
970978
971979 @Callable(i)
972980 func wavesBalancesVsPayment () = {
973981 let b = wavesBalance(this)
974982 [IntegerEntry("wavesBalance_available", b.available), IntegerEntry("wavesBalance_regular", b.regular), IntegerEntry("wavesBalance_generating", b.generating), IntegerEntry("wavesBalance_effective", b.effective), IntegerEntry("waves_payment", value(i.payments[0]).amount)]
975983 }
976984
977985
978986 @Verifier(tx)
979987 func verify () = {
980988 let id = toBase58String(tx.id)
981989 let pubKeyAdminsListStr = makeString(["ExtEEK19nmKj9mCpnWyvEEJFYATLMcVEMvohhUHkyHNm", "Ev5py5FfBQX9cZpYKnfQrTB49Byf8QmpZWeDVRim4yV7", "DUuuLjXu98nBwZc7fqwCTjtA3nnRwgTbkMSr5SU2NmDR", "DUuuLjXu98nBwZc7fqwCTjtA3nnRwgTbkMSr5SU2NmDR"], SEP)
982990 let pubKeyAdminsList = split(valueOrElse(getString(controlContract, "%s__multisig"), pubKeyAdminsListStr), SEP)
983991 let count = ((((if (sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(pubKeyAdminsList[0])))
984992 then 1
985993 else 0) + (if (sigVerify(tx.bodyBytes, tx.proofs[1], fromBase58String(pubKeyAdminsList[1])))
986994 then 1
987995 else 0)) + (if (sigVerify(tx.bodyBytes, tx.proofs[2], fromBase58String(pubKeyAdminsList[2])))
988996 then 1
989997 else 0)) + (if (sigVerify(tx.bodyBytes, tx.proofs[3], fromBase58String(pubKeyAdminsList[3])))
990998 then 2
991999 else 0))
9921000 match tx {
9931001 case sponsorTx: SponsorFeeTransaction =>
9941002 if (checkIsValidMinSponsoredFee(sponsorTx))
9951003 then (count >= 3)
9961004 else false
9971005 case _ =>
9981006 (count >= 3)
9991007 }
10001008 }
10011009

github/deemru/w8io/3ef1775 
142.68 ms