tx · 2YG32vXKqsqm5bGr318anrWctr9Uz2BQZiLuui7yxava

3N9be2mwrA52WJho6DiesZkk4351GvpnWuj:  -0.04000000 Waves

2022.08.23 15:02 [2197103] smart account 3N9be2mwrA52WJho6DiesZkk4351GvpnWuj > SELF 0.00000000 Waves

{ "type": 13, "id": "2YG32vXKqsqm5bGr318anrWctr9Uz2BQZiLuui7yxava", "fee": 4000000, "feeAssetId": null, "timestamp": 1661256134478, "version": 1, "sender": "3N9be2mwrA52WJho6DiesZkk4351GvpnWuj", "senderPublicKey": "6mzmbCza9iqbzxMEELcEA4Xc9NeF4CYpbTtz1zMK3C7x", "proofs": [ "4SotD7V912zkrhzX1SEPyh9JdEXCT4u8ofEiBLs7ENbnDzsnuyday9jGQupZnn1j3Dw1JHh6hVVzevGNVdhr2FHv", "2dVCiGFL1xtLWMzWPFU8N8r2DqrqNqf5sfqLF2K8qYCLYtAcA5HXiVZFUG95J86ACEnXkSub3DHffFdF3GMcHrUG", "KwW6sVYzY2AbLutypET98j5ivkQLSWcpBLP2ywmPY7YQQz6mUAvcTKjdZ2YkXM5hATNUihcHBpbmQ7NgT7Eyu9V" ], "script": "base64:BgJOCAISDgoMCAgICAgIAQEBAQEBEgUKAwgIARIAEgASBQoDCAEIEgMKAQESBAoCAQgSABIECgIIARIECgIBARIECgIIARIFCgMIAQESABIApQEBD2dldFN0cmluZ09yRmFpbAIHYWRkcmVzcwNrZXkJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQdhZGRyZXNzBQNrZXkJALkJAgkAzAgCAgptYW5kYXRvcnkgCQDMCAIJAKUIAQUHYWRkcmVzcwkAzAgCAgEuCQDMCAIFA2tleQkAzAgCAg8gaXMgbm90IGRlZmluZWQFA25pbAIAAQVsY2FsYwEBbAkAuQgBBQFsAQ5nZXROdW1iZXJCeUtleQEDa2V5CQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFA2tleQAAAQ5nZXRTdHJpbmdCeUtleQEDa2V5CQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMFA2tleQIAAQxnZXRCb29sQnlLZXkBA2tleQkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzBQNrZXkHARhnZXROdW1iZXJCeUFkZHJlc3NBbmRLZXkCB2FkZHJlc3MDa2V5CQELdmFsdWVPckVsc2UCCQCaCAIFB2FkZHJlc3MFA2tleQAAARhnZXRTdHJpbmdCeUFkZHJlc3NBbmRLZXkCB2FkZHJlc3MDa2V5CQELdmFsdWVPckVsc2UCCQCdCAIJARFAZXh0ck5hdGl2ZSgxMDYyKQEFB2FkZHJlc3MFA2tleQIAARZnZXRCb29sQnlBZGRyZXNzQW5kS2V5AgdhZGRyZXNzA2tleQkBC3ZhbHVlT3JFbHNlAgkAmwgCBQdhZGRyZXNzBQNrZXkHAQlhc0FueUxpc3QBAXYEByRtYXRjaDAFAXYDCQABAgUHJG1hdGNoMAIJTGlzdFtBbnldBAFsBQckbWF0Y2gwBQFsCQACAQIbZmFpbCB0byBjYXN0IGludG8gTGlzdFtBbnldAQhhc1N0cmluZwEBdgQHJG1hdGNoMAUBdgMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAXMFByRtYXRjaDAFAXMJAAIBAhhmYWlsIHRvIGNhc3QgaW50byBTdHJpbmcBBWFzSW50AQF2BAckbWF0Y2gwBQF2AwkAAQIFByRtYXRjaDACA0ludAQBaQUHJG1hdGNoMAUBaQkAAgECFWZhaWwgdG8gY2FzdCBpbnRvIEludAEHYXNCeXRlcwEDdmFsBAckbWF0Y2gwBQN2YWwDCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQHdmFsQnl0ZQUHJG1hdGNoMAUHdmFsQnl0ZQkAAgECHGZhaWwgdG8gY2FzdCBpbnRvIEJ5dGVWZWN0b3IBCWFzUGF5bWVudAEBdgQHJG1hdGNoMAUBdgMJAAECBQckbWF0Y2gwAg9BdHRhY2hlZFBheW1lbnQEAXAFByRtYXRjaDAFAXAJAAIBAiFmYWlsIHRvIGNhc3QgaW50byBBdHRhY2hlZFBheW1lbnQBEmFzU3dhcFBhcmFtc1NUUlVDVAEBdgQHJG1hdGNoMAUBdgMJAAECBQckbWF0Y2gwAiMoSW50LCBJbnQsIEludCwgSW50LCBJbnQsIEludCwgSW50KQQGc3RydWN0BQckbWF0Y2gwBQZzdHJ1Y3QJAAIBAh1mYWlsIHRvIGNhc3QgaW50byBUdXBsZTUgaW50cwADU0VQAgJfXwAHV0FWRUxFVACAwtcvAAVQQVVMSQDAhD0ACFBSSUNFTEVUAMCEPQAOREVGQVVMVFNXQVBGRUUAoJwBAAtCUlBST1RFQ1RFRACgjQYADElkeE5ldEFtb3VudAAAAAxJZHhGZWVBbW91bnQAAQAOSWR4R3Jvc3NBbW91bnQAAgAZSWR4Q29udHJvbENmZ05ldXRyaW5vRGFwcAABABhJZHhDb250cm9sQ2ZnQXVjdGlvbkRhcHAAAgAUSWR4Q29udHJvbENmZ1JwZERhcHAAAwAVSWR4Q29udHJvbENmZ01hdGhEYXBwAAQAHElkeENvbnRyb2xDZmdMaXF1aWRhdGlvbkRhcHAABQAVSWR4Q29udHJvbENmZ1Jlc3REYXBwAAYAHUlkeENvbnRyb2xDZmdOb2RlUmVnaXN0cnlEYXBwAAcAHElkeENvbnRyb2xDZmdOc2J0U3Rha2luZ0RhcHAACAAZSWR4Q29udHJvbENmZ01lZGlhdG9yRGFwcAAJABxJZHhDb250cm9sQ2ZnU3VyZlN0YWtpbmdEYXBwAAoAIElkeENvbnRyb2xDZmdHbnNidENvbnRyb2xsZXJEYXBwAAsBEWtleUNvbnRyb2xBZGRyZXNzAAIcJXMlc19fY29uZmlnX19jb250cm9sQWRkcmVzcwENa2V5Q29udHJvbENmZwACESVzX19jb250cm9sQ29uZmlnARRyZWFkQ29udHJvbENmZ09yRmFpbAEHY29udHJvbAkAtQkCCQEPZ2V0U3RyaW5nT3JGYWlsAgUHY29udHJvbAkBDWtleUNvbnRyb2xDZmcABQNTRVABGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIKY29udHJvbENmZwNpZHgJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQCRAwIFCmNvbnRyb2xDZmcFA2lkeAkArAICAi1Db250cm9sIGNmZyBkb2Vzbid0IGNvbnRhaW4gYWRkcmVzcyBhdCBpbmRleCAJAKQDAQUDaWR4AA9jb250cm9sQ29udHJhY3QJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwkBEWtleUNvbnRyb2xBZGRyZXNzAAIjM040TlM3ZDRKbzlhNkYxNExpRlVLS1lWZFVra2YyZVA0WngACmNvbnRyb2xDZmcJARRyZWFkQ29udHJvbENmZ09yRmFpbAEFD2NvbnRyb2xDb250cmFjdAAMbWF0aENvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUKY29udHJvbENmZwUVSWR4Q29udHJvbENmZ01hdGhEYXBwABNuc2J0U3Rha2luZ0NvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUKY29udHJvbENmZwUcSWR4Q29udHJvbENmZ05zYnRTdGFraW5nRGFwcAATc3VyZlN0YWtpbmdDb250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFCmNvbnRyb2xDZmcFHElkeENvbnRyb2xDZmdTdXJmU3Rha2luZ0RhcHAAF2duc2J0Q29udHJvbGxlckNvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUKY29udHJvbENmZwUgSWR4Q29udHJvbENmZ0duc2J0Q29udHJvbGxlckRhcHAAD2F1Y3Rpb25Db250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFCmNvbnRyb2xDZmcFGElkeENvbnRyb2xDZmdBdWN0aW9uRGFwcAASTmV1dHJpbm9Bc3NldElkS2V5AhFuZXV0cmlub19hc3NldF9pZAAOQm9uZEFzc2V0SWRLZXkCDWJvbmRfYXNzZXRfaWQAEkF1Y3Rpb25Db250cmFjdEtleQIQYXVjdGlvbl9jb250cmFjdAAWTnNidFN0YWtpbmdDb250cmFjdEtleQITbnNidFN0YWtpbmdDb250cmFjdAAWTGlxdWlkYXRpb25Db250cmFjdEtleQIUbGlxdWlkYXRpb25fY29udHJhY3QADlJQRENvbnRyYWN0S2V5AgxycGRfY29udHJhY3QAEUNvbnRvbENvbnRyYWN0S2V5AhBjb250cm9sX2NvbnRyYWN0AA9NYXRoQ29udHJhY3RLZXkCDW1hdGhfY29udHJhY3QAG0JhbGFuY2VXYXZlc0xvY2tJbnRlcnZhbEtleQIbYmFsYW5jZV93YXZlc19sb2NrX2ludGVydmFsAB5CYWxhbmNlTmV1dHJpbm9Mb2NrSW50ZXJ2YWxLZXkCHmJhbGFuY2VfbmV1dHJpbm9fbG9ja19pbnRlcnZhbAAVTWluV2F2ZXNTd2FwQW1vdW50S2V5AhVtaW5fd2F2ZXNfc3dhcF9hbW91bnQAGE1pbk5ldXRyaW5vU3dhcEFtb3VudEtleQIYbWluX25ldXRyaW5vX3N3YXBfYW1vdW50ABtOb2RlT3JhY2xlUHJvdmlkZXJQdWJLZXlLZXkCFG5vZGVfb3JhY2xlX3Byb3ZpZGVyABVOZXV0cmlub091dEZlZVBhcnRLZXkCGG5ldXRyaW5vT3V0X3N3YXBfZmVlUGFydAASV2F2ZXNPdXRGZWVQYXJ0S2V5AhV3YXZlc091dF9zd2FwX2ZlZVBhcnQBD2tleU5vZGVSZWdpc3RyeQEHYWRkcmVzcwkArAICAgQlc19fBQdhZGRyZXNzAAhQcmljZUtleQIFcHJpY2UADVByaWNlSW5kZXhLZXkCC3ByaWNlX2luZGV4AAxJc0Jsb2NrZWRLZXkCCmlzX2Jsb2NrZWQBEmdldFByaWNlSGlzdG9yeUtleQEFYmxvY2sJAKwCAgkArAICBQhQcmljZUtleQIBXwkApAMBBQVibG9jawEYZ2V0SGVpZ2h0UHJpY2VCeUluZGV4S2V5AQVpbmRleAkArAICCQCsAgIFDVByaWNlSW5kZXhLZXkCAV8JAKQDAQUFaW5kZXgBFWdldFN0YWtpbmdOb2RlQnlJbmRleAEDaWR4CQEOZ2V0U3RyaW5nQnlLZXkBCQC5CQIJAMwIAgIGJXMlZCVzCQDMCAICBWxlYXNlCQDMCAIJAKQDAQUDaWR4CQDMCAICC25vZGVBZGRyZXNzBQNuaWwFA1NFUAEcZ2V0U3Rha2luZ05vZGVBZGRyZXNzQnlJbmRleAEDaWR4CQERQGV4dHJOYXRpdmUoMTA2MikBCQEVZ2V0U3Rha2luZ05vZGVCeUluZGV4AQUDaWR4AR9nZXRSZXNlcnZlZEFtb3VudEZvclNwb25zb3JzaGlwAAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQC5CQIJAMwIAgIEJXMlcwkAzAgCAgVsZWFzZQkAzAgCAhdzcG9uc29yc2hpcFdhdmVzUmVzZXJ2ZQUDbmlsBQNTRVAJAGgCAOgHBQdXQVZFTEVUARhnZXRCYWxhbmNlVW5sb2NrQmxvY2tLZXkBBW93bmVyCQCsAgICFWJhbGFuY2VfdW5sb2NrX2Jsb2NrXwUFb3duZXIBDWdldExlYXNlSWRLZXkBCW5vZGVJbmRleAkAuQkCCQDMCAICBiVzJWQlcwkAzAgCAgVsZWFzZQkAzAgCCQCkAwEFCW5vZGVJbmRleAkAzAgCAgJpZAUDbmlsBQNTRVABFmdldExlYXNlSWRCeUFkZHJlc3NLZXkBC25vZGVBZGRyZXNzCQC5CQIJAMwIAgIGJXMlcyVzCQDMCAICDmxlYXNlQnlBZGRyZXNzCQDMCAIFC25vZGVBZGRyZXNzCQDMCAICAmlkBQNuaWwFA1NFUAERZ2V0TGVhc2VBbW91bnRLZXkBCW5vZGVJbmRleAkAuQkCCQDMCAICBiVzJWQlcwkAzAgCAgVsZWFzZQkAzAgCCQCkAwEFCW5vZGVJbmRleAkAzAgCAgZhbW91bnQFA25pbAUDU0VQARpnZXRMZWFzZUFtb3VudEJ5QWRkcmVzc0tleQELbm9kZUFkZHJlc3MJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgIObGVhc2VCeUFkZHJlc3MJAMwIAgULbm9kZUFkZHJlc3MJAMwIAgIGYW1vdW50BQNuaWwFA1NFUAEYZ2V0TGVhc2VHcm91cE5vZGVMaXN0S2V5AQhncm91cE51bQkAuQkCCQDMCAICBiVzJWQlcwkAzAgCAgpsZWFzZUdyb3VwCQDMCAIJAKQDAQUIZ3JvdXBOdW0JAMwIAgIIbm9kZUxpc3QFA25pbAUDU0VQARBtaW5Td2FwQW1vdW50S0VZAQhzd2FwVHlwZQkArAICCQCsAgICBG1pbl8FCHN3YXBUeXBlAgxfc3dhcF9hbW91bnQBDnRvdGFsTG9ja2VkS0VZAQhzd2FwVHlwZQkArAICAg1iYWxhbmNlX2xvY2tfBQhzd2FwVHlwZQEUdG90YWxMb2NrZWRCeVVzZXJLRVkCCHN3YXBUeXBlBW93bmVyCQC5CQIJAMwIAgIMYmFsYW5jZV9sb2NrCQDMCAIFCHN3YXBUeXBlCQDMCAIFBW93bmVyBQNuaWwCAV8BFmJhbGFuY2VMb2NrSW50ZXJ2YWxLRVkBCHN3YXBUeXBlCQCsAgIJAKwCAgIIYmFsYW5jZV8FCHN3YXBUeXBlAg5fbG9ja19pbnRlcnZhbAEabm9kZUJhbGFuY2VMb2NrSW50ZXJ2YWxLRVkAAhpiYWxhbmNlX25vZGVfbG9ja19pbnRlcnZhbAENb3V0RmVlUGFydEtFWQEIc3dhcFR5cGUJAKwCAgUIc3dhcFR5cGUCEE91dF9zd2FwX2ZlZVBhcnQBEXN3YXBzVGltZWZyYW1lS0VZAAIPc3dhcHNfdGltZWZyYW1lAQ5iclByb3RlY3RlZEtFWQACF21pbl9CUl9wcm90ZWN0aW9uX2xldmVsARFtaW5Td2FwQW1vdW50UkVBRAEIc3dhcFR5cGUJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBEG1pblN3YXBBbW91bnRLRVkBBQhzd2FwVHlwZQAAARJzd2Fwc1RpbWVmcmFtZVJFQUQACQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJARFzd2Fwc1RpbWVmcmFtZUtFWQAAoAsBD3RvdGFsTG9ja2VkUkVBRAEIc3dhcFR5cGUJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBDnRvdGFsTG9ja2VkS0VZAQUIc3dhcFR5cGUAAAEVdG90YWxMb2NrZWRCeVVzZXJSRUFEAghzd2FwVHlwZQVvd25lcgkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEUdG90YWxMb2NrZWRCeVVzZXJLRVkCBQhzd2FwVHlwZQUFb3duZXIAAAEXYmFsYW5jZUxvY2tJbnRlcnZhbFJFQUQBCHN3YXBUeXBlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJARZiYWxhbmNlTG9ja0ludGVydmFsS0VZAQUIc3dhcFR5cGUAoAsBG25vZGVCYWxhbmNlTG9ja0ludGVydmFsUkVBRAAJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBGm5vZGVCYWxhbmNlTG9ja0ludGVydmFsS0VZAAABARhrZXlTd2FwVXNlclNwZW50SW5QZXJpb2QBC3VzZXJBZGRyZXNzCQC5CQIJAMwIAgIEJXMlcwkAzAgCAhVzd2FwVXNlclNwZW50SW5QZXJpb2QJAMwIAgULdXNlckFkZHJlc3MFA25pbAUDU0VQARVrZXlVc2VyTGFzdFN3YXBIZWlnaHQBC3VzZXJBZGRyZXNzCQC5CQIJAMwIAgIEJXMlcwkAzAgCAhJ1c2VyTGFzdFN3YXBIZWlnaHQJAMwIAgULdXNlckFkZHJlc3MFA25pbAUDU0VQARZjb252ZXJ0TmV1dHJpbm9Ub1dhdmVzAgZhbW91bnQFcHJpY2UJAGsDCQBrAwUGYW1vdW50BQhQUklDRUxFVAUFcHJpY2UFB1dBVkVMRVQFBVBBVUxJARZjb252ZXJ0V2F2ZXNUb05ldXRyaW5vAgZhbW91bnQFcHJpY2UJAGsDCQBrAwUGYW1vdW50BQVwcmljZQUIUFJJQ0VMRVQFBVBBVUxJBQdXQVZFTEVUARJjb252ZXJ0V2F2ZXNUb0JvbmQCBmFtb3VudAVwcmljZQkBFmNvbnZlcnRXYXZlc1RvTmV1dHJpbm8CBQZhbW91bnQFBXByaWNlARZjb252ZXJ0SnNvbkFycmF5VG9MaXN0AQlqc29uQXJyYXkJALUJAgUJanNvbkFycmF5AgEsARFtaW5Td2FwQW1vdW50RkFJTAIIc3dhcFR5cGUNbWluU3dhcEFtb3VudAkAAgEJAKwCAgkArAICCQCsAgICGFRoZSBzcGVjaWZpZWQgYW1vdW50IGluIAUIc3dhcFR5cGUCKyBzd2FwIGlzIGxlc3MgdGhhbiB0aGUgcmVxdWlyZWQgbWluaW11bSBvZiAJAKQDAQUNbWluU3dhcEFtb3VudAEVZW1lcmdlbmN5U2h1dGRvd25GQUlMAAkAAgECWmNvbnRyYWN0IGlzIGJsb2NrZWQgYnkgRU1FUkdFTkNZIFNIVVRET1dOIGFjdGlvbnMgdW50aWxsIHJlYWN0aXZhdGlvbiBieSBlbWVyZ2VuY3kgb3JhY2xlcwEOcHJpY2VJbmRleEZBSUwFBWluZGV4CnByaWNlSW5kZXgLaW5kZXhIZWlnaHQMdW5sb2NrSGVpZ2h0D3ByZXZJbmRleEhlaWdodAkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICI2ludmFsaWQgcHJpY2UgaGlzdG9yeSBpbmRleDogaW5kZXg9CQCkAwEFBWluZGV4AgwgcHJpY2VJbmRleD0JAKQDAQUKcHJpY2VJbmRleAINIGluZGV4SGVpZ2h0PQkApAMBBQtpbmRleEhlaWdodAIOIHVubG9ja0hlaWdodD0JAKQDAQUMdW5sb2NrSGVpZ2h0AhEgcHJldkluZGV4SGVpZ2h0PQkApAMBBQ9wcmV2SW5kZXhIZWlnaHQAD25ldXRyaW5vQXNzZXRJZAkA2QQBCQEOZ2V0U3RyaW5nQnlLZXkBBRJOZXV0cmlub0Fzc2V0SWRLZXkACnByaWNlSW5kZXgJARhnZXROdW1iZXJCeUFkZHJlc3NBbmRLZXkCBQ9jb250cm9sQ29udHJhY3QFDVByaWNlSW5kZXhLZXkACWlzQmxvY2tlZAkBFmdldEJvb2xCeUFkZHJlc3NBbmRLZXkCBQ9jb250cm9sQ29udHJhY3QFDElzQmxvY2tlZEtleQAYbm9kZU9yYWNsZVByb3ZpZGVyUHViS2V5CQDZBAEJAQ5nZXRTdHJpbmdCeUtleQEFG05vZGVPcmFjbGVQcm92aWRlclB1YktleUtleQALYm9uZEFzc2V0SWQJANkEAQIsRjNpYXh6cnVGZUt1amZWZllTWkVrZWpwamg2N3dtUmZQQ1JIaU5tV0twM1oAFWRlcHJlY2F0ZWRCb25kQXNzZXRJZAkA2QQBAiw5NzVha1pCZm5NajUxM1U3TVphSEt6UXJtc0V4NWFFM3dkV0tUckhCaGJqRgAQbmV1dHJpbm9Db250cmFjdAUEdGhpcwAMY3VycmVudFByaWNlCQEYZ2V0TnVtYmVyQnlBZGRyZXNzQW5kS2V5AgUPY29udHJvbENvbnRyYWN0BQhQcmljZUtleQEbY2hlY2tJc1ZhbGlkTWluU3BvbnNvcmVkRmVlAQJ0eAQOTUlOVFJBTlNGRVJGRUUAoI0GBBZTcG9uc29yZWRGZWVVcHBlckJvdW5kAOgHBA9yZWFsTmV1dHJpbm9GZWUJARZjb252ZXJ0V2F2ZXNUb05ldXRyaW5vAgUOTUlOVFJBTlNGRVJGRUUFDGN1cnJlbnRQcmljZQQObWluTmV1dHJpbm9GZWUJAGgCBQ9yZWFsTmV1dHJpbm9GZWUAAgQObWF4TmV1dHJpbm9GZWUJAGsDBQ9yZWFsTmV1dHJpbm9GZWUFFlNwb25zb3JlZEZlZVVwcGVyQm91bmQAZAQIaW5wdXRGZWUJAQV2YWx1ZQEIBQJ0eBRtaW5TcG9uc29yZWRBc3NldEZlZQMDCQBnAgUIaW5wdXRGZWUFDm1pbk5ldXRyaW5vRmVlCQBnAgUObWF4TmV1dHJpbm9GZWUFCGlucHV0RmVlBwkAAAIIBQJ0eAdhc3NldElkBQ9uZXV0cmlub0Fzc2V0SWQHAQ9nZXRQcmljZUhpc3RvcnkBBWJsb2NrCQEYZ2V0TnVtYmVyQnlBZGRyZXNzQW5kS2V5AgUPY29udHJvbENvbnRyYWN0CQESZ2V0UHJpY2VIaXN0b3J5S2V5AQUFYmxvY2sBFWdldEhlaWdodFByaWNlQnlJbmRleAEFaW5kZXgJARhnZXROdW1iZXJCeUFkZHJlc3NBbmRLZXkCBQ9jb250cm9sQ29udHJhY3QJARhnZXRIZWlnaHRQcmljZUJ5SW5kZXhLZXkBBQVpbmRleAEWa2V5TG9ja1BhcmFtVXNlckFtb3VudAELdXNlckFkZHJlc3MJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgILcGFyYW1CeVVzZXIJAMwIAgULdXNlckFkZHJlc3MJAMwIAgIGYW1vdW50BQNuaWwFA1NFUAAMc0lkeFN3YXBUeXBlAAEACnNJZHhTdGF0dXMAAgAMc0lkeEluQW1vdW50AAMACXNJZHhQcmljZQAEABBzSWR4T3V0TmV0QW1vdW50AAUAEHNJZHhPdXRGZWVBbW91bnQABgAPc0lkeFN0YXJ0SGVpZ2h0AAcAEnNJZHhTdGFydFRpbWVzdGFtcAAIAA1zSWR4RW5kSGVpZ2h0AAkAEHNJZHhFbmRUaW1lc3RhbXAACgAUc0lkeFNlbGZVbmxvY2tIZWlnaHQACwAUc0lkeFJhbmRVbmxvY2tIZWlnaHQADAAJc0lkeEluZGV4AA0AEHNJZHhXaXRoZHJhd1R4SWQADgALc0lkeE1pblJhbmQADwALc0lkeE1heFJhbmQAEAEHc3dhcEtFWQILdXNlckFkZHJlc3MEdHhJZAkAuQkCCQDMCAICBCVzJXMJAMwIAgULdXNlckFkZHJlc3MJAMwIAgUEdHhJZAUDbmlsBQNTRVABC3N0clN3YXBEQVRBEAhzd2FwVHlwZQZzdGF0dXMIaW5BbW91bnQFcHJpY2UMb3V0TmV0QW1vdW50DG91dEZlZUFtb3VudAtzdGFydEhlaWdodA5zdGFydFRpbWVzdGFtcAllbmRIZWlnaHQMZW5kVGltZXN0YW1wEHNlbGZVbmxvY2tIZWlnaHQQcmFuZFVubG9ja0hlaWdodAVpbmRleAx3aXRoZHJhd1R4SWQHcmFuZE1pbgdyYW5kTWF4CQC5CQIJAMwIAgIcJXMlcyVkJWQlZCVkJWQlZCVkJWQlZCVkJWQlcwkAzAgCBQhzd2FwVHlwZQkAzAgCBQZzdGF0dXMJAMwIAgUIaW5BbW91bnQJAMwIAgUFcHJpY2UJAMwIAgUMb3V0TmV0QW1vdW50CQDMCAIFDG91dEZlZUFtb3VudAkAzAgCBQtzdGFydEhlaWdodAkAzAgCBQ5zdGFydFRpbWVzdGFtcAkAzAgCBQllbmRIZWlnaHQJAMwIAgUMZW5kVGltZXN0YW1wCQDMCAIFEHNlbGZVbmxvY2tIZWlnaHQJAMwIAgUQcmFuZFVubG9ja0hlaWdodAkAzAgCBQVpbmRleAkAzAgCBQx3aXRoZHJhd1R4SWQJAMwIAgUHcmFuZE1pbgkAzAgCBQdyYW5kTWF4BQNuaWwFA1NFUAEPcGVuZGluZ1N3YXBEQVRBAwhzd2FwVHlwZQ1pbkFzc2V0QW1vdW50EHNlbGZVbmxvY2tIZWlnaHQJAQtzdHJTd2FwREFUQRAFCHN3YXBUeXBlAgdQRU5ESU5HCQCkAwEFDWluQXNzZXRBbW91bnQCATACATACATAJAKQDAQUGaGVpZ2h0CQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wAgEwAgEwCQCkAwEFEHNlbGZVbmxvY2tIZWlnaHQCATACATACBE5VTEwCATACATABDmZpbmlzaFN3YXBEQVRBBwlkYXRhQXJyYXkFcHJpY2UMb3V0TmV0QW1vdW50DG91dEZlZUFtb3VudBByYW5kVW5sb2NrSGVpZ2h0BWluZGV4DHdpdGhkcmF3VHhJZAkBC3N0clN3YXBEQVRBEAkAkQMCBQlkYXRhQXJyYXkFDHNJZHhTd2FwVHlwZQIIRklOSVNIRUQJAJEDAgUJZGF0YUFycmF5BQxzSWR4SW5BbW91bnQJAKQDAQUFcHJpY2UJAKQDAQUMb3V0TmV0QW1vdW50CQCkAwEFDG91dEZlZUFtb3VudAkAkQMCBQlkYXRhQXJyYXkFD3NJZHhTdGFydEhlaWdodAkAkQMCBQlkYXRhQXJyYXkFEnNJZHhTdGFydFRpbWVzdGFtcAkApAMBBQZoZWlnaHQJAKQDAQgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAJEDAgUJZGF0YUFycmF5BRRzSWR4U2VsZlVubG9ja0hlaWdodAkApAMBBRByYW5kVW5sb2NrSGVpZ2h0CQCkAwEFBWluZGV4BQx3aXRoZHJhd1R4SWQJAJEDAgUJZGF0YUFycmF5BQtzSWR4TWluUmFuZAkAkQMCBQlkYXRhQXJyYXkFC3NJZHhNYXhSYW5kARJzd2FwRGF0YUZhaWxPclJFQUQCC3VzZXJBZGRyZXNzCHN3YXBUeElkBAdzd2FwS2V5CQEHc3dhcEtFWQIFC3VzZXJBZGRyZXNzBQhzd2FwVHhJZAkAtQkCCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUEdGhpcwUHc3dhcEtleQkArAICAhFubyBzd2FwIGRhdGEgZm9yIAUHc3dhcEtleQUDU0VQAQlhcHBseUZlZXMDDmFtb3VudE91dEdyb3NzC2luQW10VG9TVVJGB2ZlZVBhcnQECWZlZUFtb3VudAkAawMFDmFtb3VudE91dEdyb3NzBQdmZWVQYXJ0BQVQQVVMSQkAzAgCCQBlAgUOYW1vdW50T3V0R3Jvc3MFCWZlZUFtb3VudAkAzAgCBQlmZWVBbW91bnQFA25pbAEDYWJzAQF4AwkAZgIAAAUBeAkBAS0BBQF4BQF4AQpzZWxlY3ROb2RlAQ11bmxlYXNlQW1vdW50BA1hbW91bnRUb0xlYXNlCQBlAgkAZQIICQDvBwEFEG5ldXRyaW5vQ29udHJhY3QJYXZhaWxhYmxlBQ11bmxlYXNlQW1vdW50CQEfZ2V0UmVzZXJ2ZWRBbW91bnRGb3JTcG9uc29yc2hpcAAECm9sZExlYXNlZDAJAQ5nZXROdW1iZXJCeUtleQEJARFnZXRMZWFzZUFtb3VudEtleQEAAAQKb2xkTGVhc2VkMQkBDmdldE51bWJlckJ5S2V5AQkBEWdldExlYXNlQW1vdW50S2V5AQABBApuZXdMZWFzZWQwCQBkAgUNYW1vdW50VG9MZWFzZQUKb2xkTGVhc2VkMAQKbmV3TGVhc2VkMQkAZAIFDWFtb3VudFRvTGVhc2UFCm9sZExlYXNlZDEDAwkAZgIFCm5ld0xlYXNlZDAAAAYJAGYCBQpuZXdMZWFzZWQxAAAEBmRlbHRhMAkBA2FicwEJAGUCBQpuZXdMZWFzZWQwBQpvbGRMZWFzZWQxBAZkZWx0YTEJAQNhYnMBCQBlAgUKbmV3TGVhc2VkMQUKb2xkTGVhc2VkMAMJAGcCBQZkZWx0YTEFBmRlbHRhMAkAlAoCAAAFCm5ld0xlYXNlZDAJAJQKAgABBQpuZXdMZWFzZWQxCQCUCgIA////////////AQAAAQh0aGlzT25seQEBaQMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECLVBlcm1pc3Npb24gZGVuaWVkOiB0aGlzIGNvbnRyYWN0IG9ubHkgYWxsb3dlZAYBFnByZXBhcmVVbmxlYXNlQW5kTGVhc2UBDXVubGVhc2VBbW91bnQECW5vZGVUdXBsZQkBCnNlbGVjdE5vZGUBBQ11bmxlYXNlQW1vdW50BAlub2RlSW5kZXgIBQlub2RlVHVwbGUCXzEEDm5ld0xlYXNlQW1vdW50CAUJbm9kZVR1cGxlAl8yAwkAZgIFDm5ld0xlYXNlQW1vdW50AAAECmxlYXNlSWRLZXkJAQ1nZXRMZWFzZUlkS2V5AQUJbm9kZUluZGV4BAhvbGRMZWFzZQkAnAgCBQR0aGlzBQpsZWFzZUlkS2V5BA51bmxlYXNlT3JFbXB0eQMJAQlpc0RlZmluZWQBBQhvbGRMZWFzZQkAzAgCCQELTGVhc2VDYW5jZWwBCQEFdmFsdWUBBQhvbGRMZWFzZQUDbmlsBQNuaWwEDmxlYXNlQW1vdW50S2V5CQERZ2V0TGVhc2VBbW91bnRLZXkBBQlub2RlSW5kZXgEBWxlYXNlCQDECAIJARxnZXRTdGFraW5nTm9kZUFkZHJlc3NCeUluZGV4AQUJbm9kZUluZGV4BQ5uZXdMZWFzZUFtb3VudAkAzggCBQ51bmxlYXNlT3JFbXB0eQkAzAgCBQVsZWFzZQkAzAgCCQELQmluYXJ5RW50cnkCBQpsZWFzZUlkS2V5CQEFbGNhbGMBBQVsZWFzZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEWdldExlYXNlQW1vdW50S2V5AQUJbm9kZUluZGV4BQ5uZXdMZWFzZUFtb3VudAUDbmlsBQNuaWwBDHJlYWROb2RlSW5mbwEHbm9kZUlkeAQLbm9kZUFkZHJlc3MJARxnZXRTdGFraW5nTm9kZUFkZHJlc3NCeUluZGV4AQUHbm9kZUlkeAQMbGVhc2VkQW10S0VZCQERZ2V0TGVhc2VBbW91bnRLZXkBBQdub2RlSWR4BAlsZWFzZWRBbXQJAQ5nZXROdW1iZXJCeUtleQEFDGxlYXNlZEFtdEtFWQQKbGVhc2VJZEtFWQkBDWdldExlYXNlSWRLZXkBBQdub2RlSWR4BAdsZWFzZUlkCQEFdmFsdWUBCQCcCAIFBHRoaXMFCmxlYXNlSWRLRVkJAJcKBQULbm9kZUFkZHJlc3MFDGxlYXNlZEFtdEtFWQUJbGVhc2VkQW10BQpsZWFzZUlkS0VZBQdsZWFzZUlkAQpjb21tb25Td2FwBQhzd2FwVHlwZQlwbXRBbW91bnQOdXNlckFkZHJlc3NTdHIGdHhJZDU4G3N3YXBQYXJhbXNCeVVzZXJTWVNSRUFET05MWQQOc3dhcExpbWl0U3BlbnQIBRtzd2FwUGFyYW1zQnlVc2VyU1lTUkVBRE9OTFkCXzIEDmJsY2tzMkxtdFJlc2V0CAUbc3dhcFBhcmFtc0J5VXNlclNZU1JFQURPTkxZAl8zBBF3YXZlc1N3YXBMaW1pdE1heAgFG3N3YXBQYXJhbXNCeVVzZXJTWVNSRUFET05MWQJfNgQQdXNkblN3YXBMaW1pdE1heAgFG3N3YXBQYXJhbXNCeVVzZXJTWVNSRUFET05MWQJfNwQNbWluU3dhcEFtb3VudAkBEW1pblN3YXBBbW91bnRSRUFEAQUIc3dhcFR5cGUEC3RvdGFsTG9ja2VkCQEPdG90YWxMb2NrZWRSRUFEAQUIc3dhcFR5cGUEEXRvdGFsTG9ja2VkQnlVc2VyCQEVdG90YWxMb2NrZWRCeVVzZXJSRUFEAgUIc3dhcFR5cGUFDnVzZXJBZGRyZXNzU3RyBAtub2RlQWRkcmVzcwkBFWdldFN0YWtpbmdOb2RlQnlJbmRleAEAAAQMcHJpY2VCeUluZGV4CQEPZ2V0UHJpY2VIaXN0b3J5AQkBFWdldEhlaWdodFByaWNlQnlJbmRleAEFCnByaWNlSW5kZXgEDGlzU3dhcEJ5Tm9kZQkAAAIFC25vZGVBZGRyZXNzBQ51c2VyQWRkcmVzc1N0cgQWYmFsYW5jZUxvY2tNYXhJbnRlcnZhbAMFDGlzU3dhcEJ5Tm9kZQkBG25vZGVCYWxhbmNlTG9ja0ludGVydmFsUkVBRAAJARdiYWxhbmNlTG9ja0ludGVydmFsUkVBRAEFCHN3YXBUeXBlBBBzZWxmVW5sb2NrSGVpZ2h0CQBkAgUGaGVpZ2h0BRZiYWxhbmNlTG9ja01heEludGVydmFsBA5zd2FwVXNkblZvbHVtZQMJAAACBQhzd2FwVHlwZQIIbmV1dHJpbm8FCXBtdEFtb3VudAkBFmNvbnZlcnRXYXZlc1RvTmV1dHJpbm8CBQlwbXRBbW91bnQFDHByaWNlQnlJbmRleAQMc3dhcExpbWl0TWF4AwkAAAIFCHN3YXBUeXBlAghuZXV0cmlubwUQdXNkblN3YXBMaW1pdE1heAkBFmNvbnZlcnRXYXZlc1RvTmV1dHJpbm8CBRF3YXZlc1N3YXBMaW1pdE1heAUMcHJpY2VCeUluZGV4AwkAZgIFDW1pblN3YXBBbW91bnQFCXBtdEFtb3VudAkBEW1pblN3YXBBbW91bnRGQUlMAgUIc3dhcFR5cGUFDW1pblN3YXBBbW91bnQDAwkBASEBBQxpc1N3YXBCeU5vZGUJAGYCBQ5zd2FwTGltaXRTcGVudAAABwkAAgEJAKwCAgI6WW91IGhhdmUgZXhjZWVkZWQgc3dhcCBsaW1pdCEgTmV4dCBhbGxvd2VkIHN3YXAgaGVpZ2h0IGlzIAkApAMBCQBkAgUGaGVpZ2h0BQ5ibGNrczJMbXRSZXNldAMDCQEBIQEFDGlzU3dhcEJ5Tm9kZQkAZgIFDnN3YXBVc2RuVm9sdW1lBQxzd2FwTGltaXRNYXgHCQACAQkArAICCQCsAgIJAKwCAgIuWW91IGhhdmUgZXhjZWVkZWQgeW91ciBzd2FwIGxpbWl0ISBSZXF1ZXN0ZWQ6IAkApAMBBQ5zd2FwVXNkblZvbHVtZQINLCBhdmFpbGFibGU6IAkApAMBBQxzd2FwTGltaXRNYXgDBQlpc0Jsb2NrZWQJARVlbWVyZ2VuY3lTaHV0ZG93bkZBSUwABAlsZWFzZVBhcnQDCQAAAgUIc3dhcFR5cGUCBXdhdmVzCQEWcHJlcGFyZVVubGVhc2VBbmRMZWFzZQEAAAUDbmlsCQCUCgIJAM4IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBGGtleVN3YXBVc2VyU3BlbnRJblBlcmlvZAEFDnVzZXJBZGRyZXNzU3RyBQ5zd2FwVXNkblZvbHVtZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBFWtleVVzZXJMYXN0U3dhcEhlaWdodAEFDnVzZXJBZGRyZXNzU3RyBQZoZWlnaHQJAMwIAgkBDEludGVnZXJFbnRyeQIJARR0b3RhbExvY2tlZEJ5VXNlcktFWQIFCHN3YXBUeXBlBQ51c2VyQWRkcmVzc1N0cgkAZAIFEXRvdGFsTG9ja2VkQnlVc2VyBQlwbXRBbW91bnQJAMwIAgkBDEludGVnZXJFbnRyeQIJARhnZXRCYWxhbmNlVW5sb2NrQmxvY2tLZXkBBQ51c2VyQWRkcmVzc1N0cgUQc2VsZlVubG9ja0hlaWdodAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvdGFsTG9ja2VkS0VZAQUIc3dhcFR5cGUJAGQCBQt0b3RhbExvY2tlZAUJcG10QW1vdW50CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQdzd2FwS0VZAgUOdXNlckFkZHJlc3NTdHIFBnR4SWQ1OAkBD3BlbmRpbmdTd2FwREFUQQMFCHN3YXBUeXBlBQlwbXRBbW91bnQFEHNlbGZVbmxvY2tIZWlnaHQFA25pbAUJbGVhc2VQYXJ0BQR1bml0AA9uTWV0cmljSWR4UHJpY2UAAAAbbk1ldHJpY0lkeFVzZG5Mb2NrZWRCYWxhbmNlAAEAHG5NZXRyaWNJZHhXYXZlc0xvY2tlZEJhbGFuY2UAAgARbk1ldHJpY0lkeFJlc2VydmUAAwAXbk1ldHJpY0lkeFJlc2VydmVJblVzZG4ABAAUbk1ldHJpY0lkeFVzZG5TdXBwbHkABQARbk1ldHJpY0lkeFN1cnBsdXMABgAYbk1ldHJpY0lkeFN1cnBsdXNQZXJjZW50AAcADG5NZXRyaWNJZHhCUgAIABRuTWV0cmljSWR4TnNidFN1cHBseQAJABduTWV0cmljSWR4TWF4TnNidFN1cHBseQAKABRuTWV0cmljSWR4U3VyZlN1cHBseQALAAxiRnVuY0lkeFN1cmYAAAANYkZ1bmNJZHhXYXZlcwABAAxiRnVuY0lkeFVzZG4AAgAUYkZ1bmNJZHhSZXNlcnZlU3RhcnQAAwATYkZ1bmNJZHhTdXBwbHlTdGFydAAEAA9iRnVuY0lkeEJSU3RhcnQABQASYkZ1bmNJZHhSZXNlcnZlRW5kAAYAEWJGdW5jSWR4U3VwcGx5RW5kAAcADWJGdW5jSWR4QlJFbmQACAAMYkZ1bmNJZHhSZXN0AAkAEmJGdW5jSWR4V2F2ZXNQcmljZQAKAQ9jYWxjV2l0aGRyYXdXMlUCB3dhdmVzSW4FcHJpY2UEC291dEFtdEdyb3NzCQEWY29udmVydFdhdmVzVG9OZXV0cmlubwIFB3dhdmVzSW4FBXByaWNlCQCbCgkFC291dEFtdEdyb3NzBQ9uZXV0cmlub0Fzc2V0SWQAAAUEdW5pdAAABQd3YXZlc0luAAAAAAAAAQ9jYWxjV2l0aGRyYXdVMlcFBnVzZG5JbgVwcmljZQJicg5yZXNlcnZlc0luVXNkbgp1c2RuU3VwcGx5BAticlByb3RlY3RlZAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEOYnJQcm90ZWN0ZWRLRVkABQtCUlBST1RFQ1RFRAQZbWF4QWxsb3dlZFVzZG5CZWZvcmVNaW5CcgMJAGcCBQticlByb3RlY3RlZAUCYnIAAAkAawMJAGUCBQ5yZXNlcnZlc0luVXNkbgkAawMFC2JyUHJvdGVjdGVkBQp1c2RuU3VwcGx5BQVQQVVMSQUFUEFVTEkJAGUCBQVQQVVMSQULYnJQcm90ZWN0ZWQEFmFsbG93ZWRVc2RuQmVmb3JlTWluQnIDCQBmAgUGdXNkbkluBRltYXhBbGxvd2VkVXNkbkJlZm9yZU1pbkJyBRltYXhBbGxvd2VkVXNkbkJlZm9yZU1pbkJyBQZ1c2RuSW4EFWFsbG93ZWRVc2RuQWZ0ZXJNaW5CcgMJAGYCBQZ1c2RuSW4FGW1heEFsbG93ZWRVc2RuQmVmb3JlTWluQnIJAGsDCQBlAgUGdXNkbkluBRltYXhBbGxvd2VkVXNkbkJlZm9yZU1pbkJyBQJicgUFUEFVTEkAAAQLYWxsb3dlZFVzZG4JAGQCBRZhbGxvd2VkVXNkbkJlZm9yZU1pbkJyBRVhbGxvd2VkVXNkbkFmdGVyTWluQnIECXVzZG4yU1VSRgkAZQIFBnVzZG5JbgULYWxsb3dlZFVzZG4EC291dEFtdEdyb3NzCQEWY29udmVydE5ldXRyaW5vVG9XYXZlcwIFC2FsbG93ZWRVc2RuBQVwcmljZQkAmwoJBQtvdXRBbXRHcm9zcwUEdW5pdAUJdXNkbjJTVVJGBQ9uZXV0cmlub0Fzc2V0SWQFC291dEFtdEdyb3NzBQthbGxvd2VkVXNkbgUZbWF4QWxsb3dlZFVzZG5CZWZvcmVNaW5CcgUWYWxsb3dlZFVzZG5CZWZvcmVNaW5CcgUVYWxsb3dlZFVzZG5BZnRlck1pbkJyAQxjYWxjV2l0aGRyYXcDCHN3YXBUeXBlCGluQW1vdW50BXByaWNlBApvdXRGZWVQYXJ0CQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQ1vdXRGZWVQYXJ0S0VZAQUIc3dhcFR5cGUFDkRFRkFVTFRTV0FQRkVFAwMJAGYCAAAFCm91dEZlZVBhcnQGCQBnAgUKb3V0RmVlUGFydAUFUEFVTEkJAAIBCQCsAgIJAKwCAgkArAICAh5pbnZhbGlkIG91dEZlZVBhcnQgY29uZmlnIGZvciAFCHN3YXBUeXBlAhIgc3dhcDogb3V0RmVlUGFydD0JAKQDAQUKb3V0RmVlUGFydAQLYnJQcm90ZWN0ZWQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBDmJyUHJvdGVjdGVkS0VZAAULQlJQUk9URUNURUQED25ldXRyaW5vTWV0cmljcwkBCWFzQW55TGlzdAEJAPwHBAUMbWF0aENvbnRyYWN0AhpjYWxjTmV1dGlub01ldHJpY3NSRUFET05MWQUDbmlsBQNuaWwEAkJSCQEFYXNJbnQBCQCRAwIFD25ldXRyaW5vTWV0cmljcwUMbk1ldHJpY0lkeEJSBA5yZXNlcnZlc0luVXNkbgkBBWFzSW50AQkAkQMCBQ9uZXV0cmlub01ldHJpY3MFF25NZXRyaWNJZHhSZXNlcnZlSW5Vc2RuBAp1c2RuU3VwcGx5CQEFYXNJbnQBCQCRAwIFD25ldXRyaW5vTWV0cmljcwUUbk1ldHJpY0lkeFVzZG5TdXBwbHkEDG91dERhdGFUdXBsZQMJAAACBQhzd2FwVHlwZQIFd2F2ZXMJAQ9jYWxjV2l0aGRyYXdXMlUCBQhpbkFtb3VudAUFcHJpY2UDCQAAAgUIc3dhcFR5cGUCCG5ldXRyaW5vCQEPY2FsY1dpdGhkcmF3VTJXBQUIaW5BbW91bnQFBXByaWNlBQJCUgUOcmVzZXJ2ZXNJblVzZG4FCnVzZG5TdXBwbHkJAAIBCQCsAgICFlVuc3VwcG9ydGVkIHN3YXAgdHlwZSAFCHN3YXBUeXBlBAtvdXRBbXRHcm9zcwgFDG91dERhdGFUdXBsZQJfMQQKb3V0QXNzZXRJZAgFDG91dERhdGFUdXBsZQJfMgQPaW5BbXRUb1N1cmZQYXJ0CAUMb3V0RGF0YVR1cGxlAl8zBAlpbkFzc2V0SWQIBQxvdXREYXRhVHVwbGUCXzQECnVubGVhc2VBbXQIBQxvdXREYXRhVHVwbGUCXzUEDHBheW91dHNBcnJheQkBCWFwcGx5RmVlcwMFC291dEFtdEdyb3NzBQ9pbkFtdFRvU3VyZlBhcnQFCm91dEZlZVBhcnQECW91dE5ldEFtdAkAkQMCBQxwYXlvdXRzQXJyYXkFDElkeE5ldEFtb3VudAQJb3V0RmVlQW10CQCRAwIFDHBheW91dHNBcnJheQUMSWR4RmVlQW1vdW50BApvdXRTdXJmQW10AwkAZwIAAAUPaW5BbXRUb1N1cmZQYXJ0AAAECnN1cmZSZXN1bHQJAQlhc0FueUxpc3QBCQD8BwQFDG1hdGhDb250cmFjdAIUc3VyZkZ1bmN0aW9uUkVBRE9OTFkJAMwIAgUPaW5BbXRUb1N1cmZQYXJ0CQDMCAIFCWluQXNzZXRJZAUDbmlsBQNuaWwJAQVhc0ludAEJAJEDAgUKc3VyZlJlc3VsdAUMYkZ1bmNJZHhTdXJmCQCZCgcFCW91dE5ldEFtdAUKb3V0QXNzZXRJZAUKb3V0U3VyZkFtdAUPaW5BbXRUb1N1cmZQYXJ0BQp1bmxlYXNlQW10BQlvdXRGZWVBbXQFC291dEFtdEdyb3NzAQ5jb21tb25XaXRoZHJhdwQHYWNjb3VudAVpbmRleAhzd2FwVHhJZAx3aXRoZHJhd1R4SWQEC3VzZXJBZGRyZXNzCQERQGV4dHJOYXRpdmUoMTA2MikBBQdhY2NvdW50BAlkYXRhQXJyYXkJARJzd2FwRGF0YUZhaWxPclJFQUQCBQdhY2NvdW50BQhzd2FwVHhJZAQQc2VsZlVubG9ja0hlaWdodAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCWRhdGFBcnJheQUUc0lkeFNlbGZVbmxvY2tIZWlnaHQECHN3YXBUeXBlCQCRAwIFCWRhdGFBcnJheQUMc0lkeFN3YXBUeXBlBAhpbkFtb3VudAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCWRhdGFBcnJheQUMc0lkeEluQW1vdW50BApzd2FwU3RhdHVzCQCRAwIFCWRhdGFBcnJheQUKc0lkeFN0YXR1cwQLc3RhcnRIZWlnaHQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQlkYXRhQXJyYXkFD3NJZHhTdGFydEhlaWdodAQKb3V0RmVlUGFydAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQENb3V0RmVlUGFydEtFWQEFCHN3YXBUeXBlBQ5ERUZBVUxUU1dBUEZFRQQLdG90YWxMb2NrZWQJAQ90b3RhbExvY2tlZFJFQUQBBQhzd2FwVHlwZQQRdG90YWxMb2NrZWRCeVVzZXIJARV0b3RhbExvY2tlZEJ5VXNlclJFQUQCBQhzd2FwVHlwZQUHYWNjb3VudAQMdW5sb2NrSGVpZ2h0BRBzZWxmVW5sb2NrSGVpZ2h0BAtpbmRleEhlaWdodAkBFWdldEhlaWdodFByaWNlQnlJbmRleAEFBWluZGV4BA9wcmV2SW5kZXhIZWlnaHQJARVnZXRIZWlnaHRQcmljZUJ5SW5kZXgBCQBlAgUFaW5kZXgAAQQMcHJpY2VCeUluZGV4CQEPZ2V0UHJpY2VIaXN0b3J5AQULaW5kZXhIZWlnaHQDBQlpc0Jsb2NrZWQJARVlbWVyZ2VuY3lTaHV0ZG93bkZBSUwAAwkBAiE9AgUKc3dhcFN0YXR1cwIHUEVORElORwkAAgECH3N3YXAgaGFzIGJlZW4gYWxyZWFkeSBwcm9jZXNzZWQDCQBmAgUMdW5sb2NrSGVpZ2h0BQZoZWlnaHQJAAIBCQCsAgIJAKwCAgIRcGxlYXNlIHdhaXQgZm9yOiAJAKQDAQUMdW5sb2NrSGVpZ2h0Ah8gYmxvY2sgaGVpZ2h0IHRvIHdpdGhkcmF3IGZ1bmRzAwMDCQBmAgUFaW5kZXgFCnByaWNlSW5kZXgGCQBmAgUMdW5sb2NrSGVpZ2h0BQtpbmRleEhlaWdodAYDCQECIT0CBQ9wcmV2SW5kZXhIZWlnaHQAAAkAZwIFD3ByZXZJbmRleEhlaWdodAUMdW5sb2NrSGVpZ2h0BwkBDnByaWNlSW5kZXhGQUlMBQUFaW5kZXgFCnByaWNlSW5kZXgFC2luZGV4SGVpZ2h0BQx1bmxvY2tIZWlnaHQFD3ByZXZJbmRleEhlaWdodAQNd2l0aGRyYXdUdXBsZQkBDGNhbGNXaXRoZHJhdwMFCHN3YXBUeXBlBQhpbkFtb3VudAUMcHJpY2VCeUluZGV4BAxvdXROZXRBbW91bnQIBQ13aXRoZHJhd1R1cGxlAl8xBApvdXRBc3NldElkCAUNd2l0aGRyYXdUdXBsZQJfMgQKb3V0U3VyZkFtdAgFDXdpdGhkcmF3VHVwbGUCXzMED2luQW10VG9TdXJmUGFydAgFDXdpdGhkcmF3VHVwbGUCXzQECnVubGVhc2VBbXQIBQ13aXRoZHJhd1R1cGxlAl81BAxvdXRGZWVBbW91bnQIBQ13aXRoZHJhd1R1cGxlAl82BAtvdXRBbXRHcm9zcwgFDXdpdGhkcmF3VHVwbGUCXzcDCQBnAgAABQtvdXRBbXRHcm9zcwkAAgECE2JhbGFuY2UgZXF1YWxzIHplcm8EBXN0YXRlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEUdG90YWxMb2NrZWRCeVVzZXJLRVkCBQhzd2FwVHlwZQUHYWNjb3VudAkAZQIFEXRvdGFsTG9ja2VkQnlVc2VyBQhpbkFtb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvdGFsTG9ja2VkS0VZAQUIc3dhcFR5cGUJAGUCBQt0b3RhbExvY2tlZAUIaW5BbW91bnQJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwULdXNlckFkZHJlc3MFDG91dE5ldEFtb3VudAUKb3V0QXNzZXRJZAkAzAgCCQELU3RyaW5nRW50cnkCCQEHc3dhcEtFWQIFB2FjY291bnQFCHN3YXBUeElkCQEOZmluaXNoU3dhcERBVEEHBQlkYXRhQXJyYXkFDHByaWNlQnlJbmRleAUMb3V0TmV0QW1vdW50BQxvdXRGZWVBbW91bnQFDHVubG9ja0hlaWdodAUFaW5kZXgFDHdpdGhkcmF3VHhJZAUDbmlsBA1zdXJmQ29uZGl0aW9uAwkAZgIFCm91dFN1cmZBbXQAAAQLaXNzdWVSZXN1bHQJAPwHBAUPYXVjdGlvbkNvbnRyYWN0Aglpc3N1ZVN1cmYJAMwIAgUKb3V0U3VyZkFtdAkAzAgCBQdhY2NvdW50BQNuaWwFA25pbAMJAAACBQtpc3N1ZVJlc3VsdAULaXNzdWVSZXN1bHQAAAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgAAAwkAAAIFDXN1cmZDb25kaXRpb24FDXN1cmZDb25kaXRpb24JAJUKAwUFc3RhdGUJAQ9BdHRhY2hlZFBheW1lbnQCBQpvdXRBc3NldElkBQxvdXRGZWVBbW91bnQFCnVubGVhc2VBbXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4OAWkBC2NvbnN0cnVjdG9yDBJuZXV0cmlub0Fzc2V0SWRQcm0OYm9uZEFzc2V0SWRQcm0SYXVjdGlvbkNvbnRyYWN0UHJtFmxpcXVpZGF0aW9uQ29udHJhY3RQcm0OcnBkQ29udHJhY3RQcm0bbm9kZU9yYWNsZVByb3ZpZGVyUHViS2V5UHJtG2JhbGFuY2VXYXZlc0xvY2tJbnRlcnZhbFBybR5iYWxhbmNlTmV1dHJpbm9Mb2NrSW50ZXJ2YWxQcm0VbWluV2F2ZXNTd2FwQW1vdW50UHJtGG1pbk5ldXRyaW5vU3dhcEFtb3VudFBybRVuZXV0cmlub091dEZlZVBhcnRQcm0Sd2F2ZXNPdXRGZWVQYXJ0UHJtBAtjaGVja0NhbGxlcgkBCHRoaXNPbmx5AQUBaQMJAAACBQtjaGVja0NhbGxlcgULY2hlY2tDYWxsZXIDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAhNubyBwYXltZW50cyBhbGxvd2VkCQDMCAIJAQtTdHJpbmdFbnRyeQIFEk5ldXRyaW5vQXNzZXRJZEtleQUSbmV1dHJpbm9Bc3NldElkUHJtCQDMCAIJAQtTdHJpbmdFbnRyeQIFDkJvbmRBc3NldElkS2V5BQ5ib25kQXNzZXRJZFBybQkAzAgCCQELU3RyaW5nRW50cnkCBRJBdWN0aW9uQ29udHJhY3RLZXkFEmF1Y3Rpb25Db250cmFjdFBybQkAzAgCCQELU3RyaW5nRW50cnkCBRZMaXF1aWRhdGlvbkNvbnRyYWN0S2V5BRZsaXF1aWRhdGlvbkNvbnRyYWN0UHJtCQDMCAIJAQtTdHJpbmdFbnRyeQIFDlJQRENvbnRyYWN0S2V5BQ5ycGRDb250cmFjdFBybQkAzAgCCQELU3RyaW5nRW50cnkCBRtOb2RlT3JhY2xlUHJvdmlkZXJQdWJLZXlLZXkFG25vZGVPcmFjbGVQcm92aWRlclB1YktleVBybQkAzAgCCQEMSW50ZWdlckVudHJ5AgUbQmFsYW5jZVdhdmVzTG9ja0ludGVydmFsS2V5BRtiYWxhbmNlV2F2ZXNMb2NrSW50ZXJ2YWxQcm0JAMwIAgkBDEludGVnZXJFbnRyeQIFHkJhbGFuY2VOZXV0cmlub0xvY2tJbnRlcnZhbEtleQUeYmFsYW5jZU5ldXRyaW5vTG9ja0ludGVydmFsUHJtCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRVNaW5XYXZlc1N3YXBBbW91bnRLZXkFFW1pbldhdmVzU3dhcEFtb3VudFBybQkAzAgCCQEMSW50ZWdlckVudHJ5AgUYTWluTmV1dHJpbm9Td2FwQW1vdW50S2V5BRhtaW5OZXV0cmlub1N3YXBBbW91bnRQcm0JAMwIAgkBDEludGVnZXJFbnRyeQIFFU5ldXRyaW5vT3V0RmVlUGFydEtleQUVbmV1dHJpbm9PdXRGZWVQYXJ0UHJtCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJXYXZlc091dEZlZVBhcnRLZXkFEndhdmVzT3V0RmVlUGFydFBybQUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDWNvbnN0cnVjdG9yVjIDDG1hdGhDb250cmFjdBNuc2J0U3Rha2luZ0NvbnRyYWN0FHN3YXBzVGltZWZyYW1lQmxvY2tzBAtjaGVja0NhbGxlcgkBCHRoaXNPbmx5AQUBaQMJAAACBQtjaGVja0NhbGxlcgULY2hlY2tDYWxsZXIDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAhNubyBwYXltZW50cyBhbGxvd2VkCQDMCAIJAQtTdHJpbmdFbnRyeQIFD01hdGhDb250cmFjdEtleQUMbWF0aENvbnRyYWN0CQDMCAIJAQtTdHJpbmdFbnRyeQIFFk5zYnRTdGFraW5nQ29udHJhY3RLZXkFE25zYnRTdGFraW5nQ29udHJhY3QJAMwIAgkBDEludGVnZXJFbnRyeQIJARFzd2Fwc1RpbWVmcmFtZUtFWQAFFHN3YXBzVGltZWZyYW1lQmxvY2tzBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQETc3dhcFdhdmVzVG9OZXV0cmlubwADCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAixzd2FwV2F2ZXNUb05ldXRyaW5vIHJlcXVpcmUgb25seSBvbmUgcGF5bWVudAQDcG10CQEFdmFsdWUBCQCRAwIIBQFpCHBheW1lbnRzAAADCQEJaXNEZWZpbmVkAQgFA3BtdAdhc3NldElkCQACAQIpT25seSBXYXZlcyB0b2tlbiBpcyBhbGxvd2VkIGZvciBzd2FwcGluZy4EC3VzZXJBZGRyZXNzCQClCAEIBQFpBmNhbGxlcgQGdHhJZDU4CQDYBAEIBQFpDXRyYW5zYWN0aW9uSWQEEHN3YXBQYXJhbXNTVFJVQ1QJARJhc1N3YXBQYXJhbXNTVFJVQ1QBCQD8BwQFBHRoaXMCG3N3YXBQYXJhbXNCeVVzZXJTWVNSRUFET05MWQkAzAgCBQt1c2VyQWRkcmVzcwkAzAgCAAAFA25pbAUDbmlsBBBjb21tb25Td2FwUmVzdWx0CQEKY29tbW9uU3dhcAUCBXdhdmVzCAUDcG10BmFtb3VudAULdXNlckFkZHJlc3MFBnR4SWQ1OAUQc3dhcFBhcmFtc1NUUlVDVAUQY29tbW9uU3dhcFJlc3VsdAFpARNzd2FwTmV1dHJpbm9Ub1dhdmVzAAMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECLHN3YXBOZXV0cmlub1RvV2F2ZXMgcmVxdWlyZSBvbmx5IG9uZSBwYXltZW50BANwbXQJAQV2YWx1ZQEJAJEDAggFAWkIcGF5bWVudHMAAAMJAQIhPQIIBQNwbXQHYXNzZXRJZAUPbmV1dHJpbm9Bc3NldElkCQACAQI6T25seSBhcHByb3ByaWF0ZSBOZXV0cmlubyB0b2tlbnMgYXJlIGFsbG93ZWQgZm9yIHN3YXBwaW5nLgQLdXNlckFkZHJlc3MJAKUIAQgFAWkGY2FsbGVyBAZ0eElkNTgJANgEAQgFAWkNdHJhbnNhY3Rpb25JZAQQc3dhcFBhcmFtc1NUUlVDVAkBEmFzU3dhcFBhcmFtc1NUUlVDVAEJAPwHBAUEdGhpcwIbc3dhcFBhcmFtc0J5VXNlclNZU1JFQURPTkxZCQDMCAIFC3VzZXJBZGRyZXNzCQDMCAIAAAUDbmlsBQNuaWwEEGNvbW1vblN3YXBSZXN1bHQJAQpjb21tb25Td2FwBQIIbmV1dHJpbm8IBQNwbXQGYW1vdW50BQt1c2VyQWRkcmVzcwUGdHhJZDU4BRBzd2FwUGFyYW1zU1RSVUNUBRBjb21tb25Td2FwUmVzdWx0AWkBCHdpdGhkcmF3AwdhY2NvdW50BWluZGV4CHN3YXBUeElkBAR0eElkCQDYBAEIBQFpDXRyYW5zYWN0aW9uSWQDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAhNubyBwYXltZW50cyBhbGxvd2VkBAtjb21tb25UdXBsZQkBDmNvbW1vbldpdGhkcmF3BAUHYWNjb3VudAUFaW5kZXgFCHN3YXBUeElkBQR0eElkBAVzdGF0ZQgFC2NvbW1vblR1cGxlAl8xBANmZWUIBQtjb21tb25UdXBsZQJfMgQKdW5sZWFzZUFtdAgFC2NvbW1vblR1cGxlAl8zBBF1bmxlYXNlSW52T3JFbXB0eQkA/AcEBQR0aGlzAhdpbnRlcm5hbFVubGVhc2VBbmRMZWFzZQkAzAgCBQp1bmxlYXNlQW10BQNuaWwFA25pbAMJAAACBRF1bmxlYXNlSW52T3JFbXB0eQURdW5sZWFzZUludk9yRW1wdHkECWduc2J0RGF0YQkBCWFzQW55TGlzdAEJAPwHBAUXZ25zYnRDb250cm9sbGVyQ29udHJhY3QCFGduc2J0SW5mb1NZU1JFQURPTkxZCQDMCAICAAkAzAgCAAAJAMwIAgAABQNuaWwFA25pbAQNZ25zYnRBbXRUb3RhbAkBBWFzSW50AQkAkQMCBQlnbnNidERhdGEAAQQVZ25zYnRBbXRGcm9tU3VyZlRvdGFsCQEFYXNJbnQBCQCRAwIJAQlhc0FueUxpc3QBCQCRAwIFCWduc2J0RGF0YQADAAMECnN1cmZGZWVBbXQDCQECIT0CBQ1nbnNidEFtdFRvdGFsAAAJAGsDCAUDZmVlBmFtb3VudAUVZ25zYnRBbXRGcm9tU3VyZlRvdGFsBQ1nbnNidEFtdFRvdGFsAAAECm5zYnRGZWVBbXQJAGUCCAUDZmVlBmFtb3VudAUKc3VyZkZlZUFtdAQLc3VyZkRlcG9zaXQDCQBmAgUKc3VyZkZlZUFtdAAABAdzdXJmSW52CQD8BwQFE3N1cmZTdGFraW5nQ29udHJhY3QCB2RlcG9zaXQFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AggFA2ZlZQdhc3NldElkBQpzdXJmRmVlQW10BQNuaWwDCQAAAgUHc3VyZkludgUHc3VyZkludgUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgULc3VyZkRlcG9zaXQFC3N1cmZEZXBvc2l0BAtuc2J0RGVwb3NpdAMJAGYCBQpuc2J0RmVlQW10AAAEB25zYnRJbnYJAPwHBAUTbnNidFN0YWtpbmdDb250cmFjdAIHZGVwb3NpdAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCAUDZmVlB2Fzc2V0SWQFCm5zYnRGZWVBbXQFA25pbAMJAAACBQduc2J0SW52BQduc2J0SW52BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBQtuc2J0RGVwb3NpdAULbnNidERlcG9zaXQFBXN0YXRlCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBF2ludGVybmFsVW5sZWFzZUFuZExlYXNlAQ11bmxlYXNlQW1vdW50AwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQIsaW50ZXJuYWxVbmxlYXNlQW5kTGVhc2UgaXMgbm90IHB1YmxpYyBtZXRob2QJARZwcmVwYXJlVW5sZWFzZUFuZExlYXNlAQUNdW5sZWFzZUFtb3VudAFpARJ0cmFuc2ZlclVzZG5Ub1VzZXICBmFtb3VudARhZGRyAwkBAiE9AggFAWkGY2FsbGVyBQ9hdWN0aW9uQ29udHJhY3QJAAIBAiNPbmx5IGF1Y3Rpb24gY29udHJhY3QgaXMgYXV0aG9yaXplZAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCQERQGV4dHJOYXRpdmUoMTA2MikBBQRhZGRyBQZhbW91bnQFD25ldXRyaW5vQXNzZXRJZAUDbmlsAWkBC2FjY2VwdFdhdmVzAAMJAQIhPQIIBQFpBmNhbGxlcgUPYXVjdGlvbkNvbnRyYWN0CQACAQIyQ3VycmVudGx5IG9ubHkgYXVjdGlvbiBjb250cmFjdCBpcyBhbGxvd2VkIHRvIGNhbGwJAJQKAgkBFnByZXBhcmVVbmxlYXNlQW5kTGVhc2UBAAACB3N1Y2Nlc3MBaQEPYXBwcm92ZUxlYXNpbmdzAgZuTGlzdFMIZ3JvdXBOdW0EBGxBbXQJAGgCADIFB1dBVkVMRVQEBW5JZHhzCQDMCAIAAAkAzAgCAAEJAMwIAgACCQDMCAIAAwkAzAgCAAQJAMwIAgAFCQDMCAIABgkAzAgCAAcFA25pbAQHbW5nUHViUwkBC3ZhbHVlT3JFbHNlAgkAoggBAhwlcyVzX19jZmdfX2xlYXNpbmdNYW5hZ2VyUHViAiw3QVVNWDU0dWtZTVl2UG1tYTd5b0ZmNU5qWmhzNEJ1NW56M0V6OUVWOHN1cgQGbW5nUHViCQDZBAEFB21uZ1B1YlMEDm5vZGVSZWdBZGRyU3RyCQELdmFsdWVPckVsc2UCCQCiCAECHyVzJXNfX2NmZ19fbm9kZXNSZWdpc3RyeUFkZHJlc3MCIzNQOXZLcVFLalVkbXBYQWZpV2F1OGtyUkVZQVkxWHI2OXBFBAtub2RlUmVnQWRkcgkBEUBleHRyTmF0aXZlKDEwNjIpAQUObm9kZVJlZ0FkZHJTdHIEEWxHcm91cE5vZGVMaXN0S0VZCQEYZ2V0TGVhc2VHcm91cE5vZGVMaXN0S2V5AQUIZ3JvdXBOdW0ECmxHck5vZGVPcHQJAJ0IAgUEdGhpcwURbEdyb3VwTm9kZUxpc3RLRVkDCQEJaXNEZWZpbmVkAQUKbEdyTm9kZU9wdAkAAgEJAKwCAgkArAICAgZncm91cCAJAKQDAQUIZ3JvdXBOdW0CFCBhbHJlYWR5IGluaXRpYWxpemVkBAVuTGlzdAkAtQkCBQZuTGlzdFMFA1NFUAQIZXhwQ291bnQJAJADAQUFbklkeHMDCQECIT0CCAUBaQ9jYWxsZXJQdWJsaWNLZXkFBm1uZ1B1YgkAAgECHmFwcHJvdmVMZWFzaW5ncyBub3QgYXV0aG9yaXplZAQNJHQwMzM2MzkzMzcwMQkBDHJlYWROb2RlSW5mbwEAAAQGbkFkZHIwCAUNJHQwMzM2MzkzMzcwMQJfMQQIbEFtdEtFWTAIBQ0kdDAzMzYzOTMzNzAxAl8yBAVsQW10MAgFDSR0MDMzNjM5MzM3MDECXzMEB2xJZEtFWTAIBQ0kdDAzMzYzOTMzNzAxAl80BARsSWQwCAUNJHQwMzM2MzkzMzcwMQJfNQQNJHQwMzM3MDQzMzc2NgkBDHJlYWROb2RlSW5mbwEAAQQGbkFkZHIxCAUNJHQwMzM3MDQzMzc2NgJfMQQIbEFtdEtFWTEIBQ0kdDAzMzcwNDMzNzY2Al8yBAVsQW10MQgFDSR0MDMzNzA0MzM3NjYCXzMEB2xJZEtFWTEIBQ0kdDAzMzcwNDMzNzY2Al80BARsSWQxCAUNJHQwMzM3MDQzMzc2NgJfNQQFbmV3TDAJAMQIAgUGbkFkZHIwCQBlAgUFbEFtdDAJAGkCCQBoAgUEbEFtdAUIZXhwQ291bnQAAgQFbmV3TDEJAMQIAgUGbkFkZHIxCQBlAgUFbEFtdDEJAGkCCQBoAgUEbEFtdAUIZXhwQ291bnQAAgQKdmFsaWRhdGlvbgkA/AcEBQtub2RlUmVnQWRkcgIadmFsaWRhdGVBbmRBcHByb3ZlTGVhc2luZ3MJAMwIAgUGbkxpc3RTBQNuaWwFA25pbAMJAAACBQp2YWxpZGF0aW9uBQp2YWxpZGF0aW9uCgEjZm9yRWFjaE5vZGVWYWxpZGF0ZUFuZEdlbmVyYXRlTGVhc2UCAWEBaQQEbm9kZQkAkQMCBQVuTGlzdAUBaQQCbGEJAMQIAgkBEUBleHRyTmF0aXZlKDEwNjIpAQUEbm9kZQUEbEFtdAkAzggCBQFhCQDMCAIFAmxhCQDMCAIJAQtCaW5hcnlFbnRyeQIJARZnZXRMZWFzZUlkQnlBZGRyZXNzS2V5AQUEbm9kZQkBBWxjYWxjAQUCbGEJAMwIAgkBDEludGVnZXJFbnRyeQIJARpnZXRMZWFzZUFtb3VudEJ5QWRkcmVzc0tleQEFBG5vZGUFBGxBbXQFA25pbAkAzggCCQDMCAIJAQtTdHJpbmdFbnRyeQIFEWxHcm91cE5vZGVMaXN0S0VZBQZuTGlzdFMJAMwIAgkBC0JpbmFyeUVudHJ5AgUHbElkS0VZMAkBBWxjYWxjAQUFbmV3TDAJAMwIAgkBC0JpbmFyeUVudHJ5AgUHbElkS0VZMQkBBWxjYWxjAQUFbmV3TDEJAMwIAgkBDEludGVnZXJFbnRyeQIFCGxBbXRLRVkwCAUFbmV3TDAGYW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCBQhsQW10S0VZMQgFBW5ld0wxBmFtb3VudAkAzAgCCQELTGVhc2VDYW5jZWwBBQRsSWQwCQDMCAIJAQtMZWFzZUNhbmNlbAEFBGxJZDEJAMwIAgUFbmV3TDAJAMwIAgUFbmV3TDEFA25pbAoAAiRsBQVuSWR4cwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEjZm9yRWFjaE5vZGVWYWxpZGF0ZUFuZEdlbmVyYXRlTGVhc2UCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDgJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAICQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBEXJlYmFsYW5jZUxlYXNpbmdzAgZhbW91bnQIZ3JvdXBOdW0EBW5JZHhzCQDMCAIAAAkAzAgCAAEJAMwIAgACCQDMCAIAAwkAzAgCAAQJAMwIAgAFCQDMCAIABgkAzAgCAAcFA25pbAQHbW5nUHViUwkBC3ZhbHVlT3JFbHNlAgkAoggBAhwlcyVzX19jZmdfX2xlYXNpbmdNYW5hZ2VyUHViAiw3QVVNWDU0dWtZTVl2UG1tYTd5b0ZmNU5qWmhzNEJ1NW56M0V6OUVWOHN1cgQGbW5nUHViCQDZBAEFB21uZ1B1YlMEEWxHcm91cE5vZGVMaXN0S0VZCQEYZ2V0TGVhc2VHcm91cE5vZGVMaXN0S2V5AQUIZ3JvdXBOdW0EBm5MaXN0UwkBD2dldFN0cmluZ09yRmFpbAIFBHRoaXMFEWxHcm91cE5vZGVMaXN0S0VZBAVuTGlzdAkAtQkCBQZuTGlzdFMFA1NFUAMJAQIhPQIIBQFpD2NhbGxlclB1YmxpY0tleQUGbW5nUHViCQACAQIgcmViYWxhbmNlTGVhc2luZ3Mgbm90IGF1dGhvcml6ZWQECnVubGVhc2VBbXQJAGQCCQBpAgUGYW1vdW50CQCQAwEFBW5MaXN0AAEEDSR0MDM1MTgzMzUyNDUJAQxyZWFkTm9kZUluZm8BAAAEBm5BZGRyMAgFDSR0MDM1MTgzMzUyNDUCXzEECGxBbXRLRVkwCAUNJHQwMzUxODMzNTI0NQJfMgQFbEFtdDAIBQ0kdDAzNTE4MzM1MjQ1Al8zBAdsSWRLRVkwCAUNJHQwMzUxODMzNTI0NQJfNAQEbElkMAgFDSR0MDM1MTgzMzUyNDUCXzUEBW5ld0wwCQDECAIFBm5BZGRyMAkAZAIFBWxBbXQwCQBoAgUKdW5sZWFzZUFtdAkAkAMBBQVuTGlzdAoBFGZvckVhY2hOb2RlRG9VbmxlYXNlAgFhAWkEBG5vZGUJAJEDAgUFbkxpc3QFAWkEBmxJZEtFWQkBFmdldExlYXNlSWRCeUFkZHJlc3NLZXkBBQRub2RlBANsSWQJARFAZXh0ck5hdGl2ZSgxMDUyKQIFBHRoaXMFBmxJZEtFWQQHbEFtdEtFWQkBGmdldExlYXNlQW1vdW50QnlBZGRyZXNzS2V5AQUEbm9kZQQEbEFtdAkBEUBleHRyTmF0aXZlKDEwNTApAgUEdGhpcwUHbEFtdEtFWQQDdWxhCQELTGVhc2VDYW5jZWwBCQEFdmFsdWUBBQNsSWQEAmxhCQDECAIJARFAZXh0ck5hdGl2ZSgxMDYyKQEFBG5vZGUJAGUCBQRsQW10BQp1bmxlYXNlQW10CQDOCAIFAWEJAMwIAgkBC0xlYXNlQ2FuY2VsAQkBBXZhbHVlAQUDbElkCQDMCAIFAmxhCQDMCAIJAQtCaW5hcnlFbnRyeQIFBmxJZEtFWQkBBWxjYWxjAQUCbGEJAMwIAgkBDEludGVnZXJFbnRyeQIFB2xBbXRLRVkIBQJsYQZhbW91bnQFA25pbAkAzggCCgACJGwFBW5JZHhzCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARRmb3JFYWNoTm9kZURvVW5sZWFzZQIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQITTGlzdCBzaXplIGV4Y2VlZHMgOAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgJAMwIAgkBC0JpbmFyeUVudHJ5AgUHbElkS0VZMAkBBWxjYWxjAQUFbmV3TDAJAMwIAgkBDEludGVnZXJFbnRyeQIFCGxBbXRLRVkwCAUFbmV3TDAGYW1vdW50CQDMCAIJAQtMZWFzZUNhbmNlbAEFBGxJZDAJAMwIAgUFbmV3TDAFA25pbAFpARtzd2FwUGFyYW1zQnlVc2VyU1lTUkVBRE9OTFkCDnVzZXJBZGRyZXNzU3RyCWduc2J0RGlmZgQJZ25zYnREYXRhCQEJYXNBbnlMaXN0AQkA/AcEBRdnbnNidENvbnRyb2xsZXJDb250cmFjdAIUZ25zYnRJbmZvU1lTUkVBRE9OTFkJAMwIAgUOdXNlckFkZHJlc3NTdHIJAMwIAgAACQDMCAIAAAUDbmlsBQNuaWwECGduc2J0QW10CQBkAgkBBWFzSW50AQkAkQMCBQlnbnNidERhdGEAAAUJZ25zYnREaWZmBA1nbnNidEFtdFRvdGFsCQBkAgkBBWFzSW50AQkAkQMCBQlnbnNidERhdGEAAQUJZ25zYnREaWZmBA1zd2FwTGltaXREYXRhCQEJYXNBbnlMaXN0AQkA/AcEBQxtYXRoQ29udHJhY3QCFWNhbGNTd2FwTGltaXRSRUFET05MWQkAzAgCBQhnbnNidEFtdAUDbmlsBQNuaWwEF3dhdmVzU3dhcExpbWl0SW5Vc2RuTWF4CQEFYXNJbnQBCQCRAwIFDXN3YXBMaW1pdERhdGEAAAQRd2F2ZXNTd2FwTGltaXRNYXgJAQVhc0ludAEJAJEDAgUNc3dhcExpbWl0RGF0YQABBBB1c2RuU3dhcExpbWl0TWF4CQEFYXNJbnQBCQCRAwIFDXN3YXBMaW1pdERhdGEAAgQObGFzdFN3YXBIZWlnaHQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBFWtleVVzZXJMYXN0U3dhcEhlaWdodAEFDnVzZXJBZGRyZXNzU3RyAAAEF3N3YXBMaW1pdFRpbWVsaWZlQmxvY2tzCQESc3dhcHNUaW1lZnJhbWVSRUFEAAQZcGFzc2VkQmxvY2tzQWZ0ZXJMYXN0U3dhcAkAZQIFBmhlaWdodAUObGFzdFN3YXBIZWlnaHQEEWlzU3dhcFRpbWVsaWZlTmV3CQBnAgUZcGFzc2VkQmxvY2tzQWZ0ZXJMYXN0U3dhcAUXc3dhcExpbWl0VGltZWxpZmVCbG9ja3MEFHN3YXBMaW1pdFNwZW50SW5Vc2RuAwURaXNTd2FwVGltZWxpZmVOZXcAAAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEYa2V5U3dhcFVzZXJTcGVudEluUGVyaW9kAQUOdXNlckFkZHJlc3NTdHIAAAQOYmxja3MyTG10UmVzZXQDBRFpc1N3YXBUaW1lbGlmZU5ldwAACQBlAgUXc3dhcExpbWl0VGltZWxpZmVCbG9ja3MFGXBhc3NlZEJsb2Nrc0FmdGVyTGFzdFN3YXAJAJQKAgUDbmlsCQCZCgcFF3dhdmVzU3dhcExpbWl0SW5Vc2RuTWF4BRRzd2FwTGltaXRTcGVudEluVXNkbgUOYmxja3MyTG10UmVzZXQFCGduc2J0QW10BQ1nbnNidEFtdFRvdGFsBRF3YXZlc1N3YXBMaW1pdE1heAUQdXNkblN3YXBMaW1pdE1heAFpAR1jYWxjV2l0aGRyYXdSZXN1bHRTWVNSRUFET05MWQMIc3dhcFR5cGUIaW5BbW91bnQFcHJpY2UJAJQKAgUDbmlsCQEMY2FsY1dpdGhkcmF3AwUIc3dhcFR5cGUFCGluQW1vdW50BQVwcmljZQFpAR91cGRhdGVSZXNlcnZlc0FuZE5ldXRyaW5vU3VwcGx5AAoBFmdldE51bWJlckJ5S2V5SW50ZXJuYWwBA2tleQQHJG1hdGNoMAkAmggCBQR0aGlzBQNrZXkDCQABAgUHJG1hdGNoMAIDSW50BAFhBQckbWF0Y2gwBQFhAAAEB25NZXRyaXgJAQlhc0FueUxpc3QBCQD8BwQFDG1hdGhDb250cmFjdAIaY2FsY05ldXRpbm9NZXRyaWNzUkVBRE9OTFkFA25pbAUDbmlsBANpZHgJARZnZXROdW1iZXJCeUtleUludGVybmFsAQIidXBkYXRlUmVzZXJ2ZXNBbmROZXV0cmlub1N1cHBseUlkeAQGbmV3SWR4CQBkAgUDaWR4AAEJAMwIAgkBDEludGVnZXJFbnRyeQICInVwZGF0ZVJlc2VydmVzQW5kTmV1dHJpbm9TdXBwbHlJZHgFBm5ld0lkeAkAzAgCCQEMSW50ZWdlckVudHJ5AgIHcmVzZXJ2ZQkBBWFzSW50AQkAkQMCBQduTWV0cml4AAMJAMwIAgkBDEludGVnZXJFbnRyeQICDm5ldXRyaW5vU3VwcGx5CQEFYXNJbnQBCQCRAwIFB25NZXRyaXgABQkAzAgCCQEMSW50ZWdlckVudHJ5AgIOcmVzZXJ2ZXNJblVzZG4JARZjb252ZXJ0V2F2ZXNUb05ldXRyaW5vAgkBBWFzSW50AQkAkQMCBQduTWV0cml4AAMJAQVhc0ludAEJAJEDAgUHbk1ldHJpeAAACQDMCAIJAQxJbnRlZ2VyRW50cnkCAgdzdXJwbHVzCQEFYXNJbnQBCQCRAwIFB25NZXRyaXgABgkAzAgCCQEMSW50ZWdlckVudHJ5AgIHZGVmaWNpdAkBAS0BCQEFYXNJbnQBCQCRAwIFB25NZXRyaXgABgUDbmlsAWkBFndhdmVzQmFsYW5jZXNWc1BheW1lbnQABAFiCQDvBwEFBHRoaXMJAMwIAgkBDEludGVnZXJFbnRyeQICFndhdmVzQmFsYW5jZV9hdmFpbGFibGUIBQFiCWF2YWlsYWJsZQkAzAgCCQEMSW50ZWdlckVudHJ5AgIUd2F2ZXNCYWxhbmNlX3JlZ3VsYXIIBQFiB3JlZ3VsYXIJAMwIAgkBDEludGVnZXJFbnRyeQICF3dhdmVzQmFsYW5jZV9nZW5lcmF0aW5nCAUBYgpnZW5lcmF0aW5nCQDMCAIJAQxJbnRlZ2VyRW50cnkCAhZ3YXZlc0JhbGFuY2VfZWZmZWN0aXZlCAUBYgllZmZlY3RpdmUJAMwIAgkBDEludGVnZXJFbnRyeQICDXdhdmVzX3BheW1lbnQICQEFdmFsdWUBCQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50BQNuaWwBAnR4AQZ2ZXJpZnkABAJpZAkA2AQBCAUCdHgCaWQEE3B1YktleUFkbWluc0xpc3RTdHIJALkJAgkAzAgCAixFeHRFRUsxOW5tS2o5bUNwbld5dkVFSkZZQVRMTWNWRU12b2hoVUhreUhObQkAzAgCAixFdjVweTVGZkJRWDljWnBZS25mUXJUQjQ5QnlmOFFtcFpXZURWUmltNHlWNwkAzAgCAixEVXV1TGpYdTk4bkJ3WmM3ZnF3Q1RqdEEzbm5Sd2dUYmtNU3I1U1UyTm1EUgkAzAgCAixEVXV1TGpYdTk4bkJ3WmM3ZnF3Q1RqdEEzbm5Sd2dUYmtNU3I1U1UyTm1EUgUDbmlsBQNTRVAEEHB1YktleUFkbWluc0xpc3QJALUJAgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ9jb250cm9sQ29udHJhY3QCDCVzX19tdWx0aXNpZwUTcHViS2V5QWRtaW5zTGlzdFN0cgUDU0VQBAVjb3VudAkAZAIJAGQCCQBkAgMJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAAJANkEAQkAkQMCBRBwdWJLZXlBZG1pbnNMaXN0AAAAAQAAAwkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAQkA2QQBCQCRAwIFEHB1YktleUFkbWluc0xpc3QAAQABAAADCQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwACCQDZBAEJAJEDAgUQcHViS2V5QWRtaW5zTGlzdAACAAEAAAMJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAMJANkEAQkAkQMCBRBwdWJLZXlBZG1pbnNMaXN0AAMAAgAABAckbWF0Y2gwBQJ0eAMJAAECBQckbWF0Y2gwAhVTcG9uc29yRmVlVHJhbnNhY3Rpb24ECXNwb25zb3JUeAUHJG1hdGNoMAMJARtjaGVja0lzVmFsaWRNaW5TcG9uc29yZWRGZWUBBQlzcG9uc29yVHgJAGcCBQVjb3VudAADBwkAZwIFBWNvdW50AAMlKItO", "chainId": 84, "height": 2197103, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 2YTUDVy5c9WEf2XUhRfABTXnpMgw11i9VWM6xBZivQZx Next: 6q9jKmWEtf4idm22x5gtq7n6L7fSH7RW7HtZjWQmmbbC 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
116116 func keyControlAddress () = "%s%s__config__controlAddress"
117117
118118
119119 func keyControlCfg () = "%s__controlConfig"
120120
121121
122122 func readControlCfgOrFail (control) = split(getStringOrFail(control, keyControlCfg()), SEP)
123123
124124
125125 func getContractAddressOrFail (controlCfg,idx) = valueOrErrorMessage(addressFromString(controlCfg[idx]), ("Control cfg doesn't contain address at index " + toString(idx)))
126126
127127
128128 let controlContract = addressFromStringValue(valueOrElse(getString(this, keyControlAddress()), "3N4NS7d4Jo9a6F14LiFUKKYVdUkkf2eP4Zx"))
129129
130130 let controlCfg = readControlCfgOrFail(controlContract)
131131
132132 let mathContract = getContractAddressOrFail(controlCfg, IdxControlCfgMathDapp)
133133
134134 let nsbtStakingContract = getContractAddressOrFail(controlCfg, IdxControlCfgNsbtStakingDapp)
135135
136136 let surfStakingContract = getContractAddressOrFail(controlCfg, IdxControlCfgSurfStakingDapp)
137137
138138 let gnsbtControllerContract = getContractAddressOrFail(controlCfg, IdxControlCfgGnsbtControllerDapp)
139139
140140 let auctionContract = getContractAddressOrFail(controlCfg, IdxControlCfgAuctionDapp)
141141
142142 let NeutrinoAssetIdKey = "neutrino_asset_id"
143143
144144 let BondAssetIdKey = "bond_asset_id"
145145
146146 let AuctionContractKey = "auction_contract"
147147
148148 let NsbtStakingContractKey = "nsbtStakingContract"
149149
150150 let LiquidationContractKey = "liquidation_contract"
151151
152152 let RPDContractKey = "rpd_contract"
153153
154154 let ContolContractKey = "control_contract"
155155
156156 let MathContractKey = "math_contract"
157157
158158 let BalanceWavesLockIntervalKey = "balance_waves_lock_interval"
159159
160160 let BalanceNeutrinoLockIntervalKey = "balance_neutrino_lock_interval"
161161
162162 let MinWavesSwapAmountKey = "min_waves_swap_amount"
163163
164164 let MinNeutrinoSwapAmountKey = "min_neutrino_swap_amount"
165165
166166 let NodeOracleProviderPubKeyKey = "node_oracle_provider"
167167
168168 let NeutrinoOutFeePartKey = "neutrinoOut_swap_feePart"
169169
170170 let WavesOutFeePartKey = "wavesOut_swap_feePart"
171171
172172 func keyNodeRegistry (address) = ("%s__" + address)
173173
174174
175175 let PriceKey = "price"
176176
177177 let PriceIndexKey = "price_index"
178178
179179 let IsBlockedKey = "is_blocked"
180180
181181 func getPriceHistoryKey (block) = ((PriceKey + "_") + toString(block))
182182
183183
184184 func getHeightPriceByIndexKey (index) = ((PriceIndexKey + "_") + toString(index))
185185
186186
187187 func getStakingNodeByIndex (idx) = getStringByKey(makeString(["%s%d%s", "lease", toString(idx), "nodeAddress"], SEP))
188188
189189
190190 func getStakingNodeAddressByIndex (idx) = addressFromStringValue(getStakingNodeByIndex(idx))
191191
192192
193193 func getReservedAmountForSponsorship () = valueOrElse(getInteger(this, makeString(["%s%s", "lease", "sponsorshipWavesReserve"], SEP)), (1000 * WAVELET))
194194
195195
196196 func getBalanceUnlockBlockKey (owner) = ("balance_unlock_block_" + owner)
197197
198198
199199 func getLeaseIdKey (nodeIndex) = makeString(["%s%d%s", "lease", toString(nodeIndex), "id"], SEP)
200200
201201
202202 func getLeaseIdByAddressKey (nodeAddress) = makeString(["%s%s%s", "leaseByAddress", nodeAddress, "id"], SEP)
203203
204204
205205 func getLeaseAmountKey (nodeIndex) = makeString(["%s%d%s", "lease", toString(nodeIndex), "amount"], SEP)
206206
207207
208208 func getLeaseAmountByAddressKey (nodeAddress) = makeString(["%s%s%s", "leaseByAddress", nodeAddress, "amount"], SEP)
209209
210210
211211 func getLeaseGroupNodeListKey (groupNum) = makeString(["%s%d%s", "leaseGroup", toString(groupNum), "nodeList"], SEP)
212212
213213
214214 func minSwapAmountKEY (swapType) = (("min_" + swapType) + "_swap_amount")
215215
216216
217217 func totalLockedKEY (swapType) = ("balance_lock_" + swapType)
218218
219219
220220 func totalLockedByUserKEY (swapType,owner) = makeString(["balance_lock", swapType, owner], "_")
221221
222222
223223 func balanceLockIntervalKEY (swapType) = (("balance_" + swapType) + "_lock_interval")
224224
225225
226226 func nodeBalanceLockIntervalKEY () = "balance_node_lock_interval"
227227
228228
229229 func outFeePartKEY (swapType) = (swapType + "Out_swap_feePart")
230230
231231
232232 func swapsTimeframeKEY () = "swaps_timeframe"
233233
234234
235235 func brProtectedKEY () = "min_BR_protection_level"
236236
237237
238238 func minSwapAmountREAD (swapType) = valueOrElse(getInteger(this, minSwapAmountKEY(swapType)), 0)
239239
240240
241241 func swapsTimeframeREAD () = valueOrElse(getInteger(this, swapsTimeframeKEY()), 1440)
242242
243243
244244 func totalLockedREAD (swapType) = valueOrElse(getInteger(this, totalLockedKEY(swapType)), 0)
245245
246246
247247 func totalLockedByUserREAD (swapType,owner) = valueOrElse(getInteger(this, totalLockedByUserKEY(swapType, owner)), 0)
248248
249249
250250 func balanceLockIntervalREAD (swapType) = valueOrElse(getInteger(this, balanceLockIntervalKEY(swapType)), 1440)
251251
252252
253253 func nodeBalanceLockIntervalREAD () = valueOrElse(getInteger(this, nodeBalanceLockIntervalKEY()), 1)
254254
255255
256256 func keySwapUserSpentInPeriod (userAddress) = makeString(["%s%s", "swapUserSpentInPeriod", userAddress], SEP)
257257
258258
259259 func keyUserLastSwapHeight (userAddress) = makeString(["%s%s", "userLastSwapHeight", userAddress], SEP)
260260
261261
262262 func convertNeutrinoToWaves (amount,price) = fraction(fraction(amount, PRICELET, price), WAVELET, PAULI)
263263
264264
265265 func convertWavesToNeutrino (amount,price) = fraction(fraction(amount, price, PRICELET), PAULI, WAVELET)
266266
267267
268268 func convertWavesToBond (amount,price) = convertWavesToNeutrino(amount, price)
269269
270270
271271 func convertJsonArrayToList (jsonArray) = split(jsonArray, ",")
272272
273273
274274 func minSwapAmountFAIL (swapType,minSwapAmount) = throw(((("The specified amount in " + swapType) + " swap is less than the required minimum of ") + toString(minSwapAmount)))
275275
276276
277277 func emergencyShutdownFAIL () = throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
278278
279279
280280 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)))
281281
282282
283283 let neutrinoAssetId = fromBase58String(getStringByKey(NeutrinoAssetIdKey))
284284
285285 let priceIndex = getNumberByAddressAndKey(controlContract, PriceIndexKey)
286286
287287 let isBlocked = getBoolByAddressAndKey(controlContract, IsBlockedKey)
288288
289289 let nodeOracleProviderPubKey = fromBase58String(getStringByKey(NodeOracleProviderPubKeyKey))
290290
291291 let bondAssetId = fromBase58String("F3iaxzruFeKujfVfYSZEkejpjh67wmRfPCRHiNmWKp3Z")
292292
293293 let deprecatedBondAssetId = fromBase58String("975akZBfnMj513U7MZaHKzQrmsEx5aE3wdWKTrHBhbjF")
294294
295295 let neutrinoContract = this
296296
297297 let currentPrice = getNumberByAddressAndKey(controlContract, PriceKey)
298298
299299 func checkIsValidMinSponsoredFee (tx) = {
300300 let MINTRANSFERFEE = 100000
301301 let SponsoredFeeUpperBound = 1000
302302 let realNeutrinoFee = convertWavesToNeutrino(MINTRANSFERFEE, currentPrice)
303303 let minNeutrinoFee = (realNeutrinoFee * 2)
304304 let maxNeutrinoFee = fraction(realNeutrinoFee, SponsoredFeeUpperBound, 100)
305305 let inputFee = value(tx.minSponsoredAssetFee)
306306 if (if ((inputFee >= minNeutrinoFee))
307307 then (maxNeutrinoFee >= inputFee)
308308 else false)
309309 then (tx.assetId == neutrinoAssetId)
310310 else false
311311 }
312312
313313
314314 func getPriceHistory (block) = getNumberByAddressAndKey(controlContract, getPriceHistoryKey(block))
315315
316316
317317 func getHeightPriceByIndex (index) = getNumberByAddressAndKey(controlContract, getHeightPriceByIndexKey(index))
318318
319319
320320 func keyLockParamUserAmount (userAddress) = makeString(["%s%s%s", "paramByUser", userAddress, "amount"], SEP)
321321
322322
323323 let sIdxSwapType = 1
324324
325325 let sIdxStatus = 2
326326
327327 let sIdxInAmount = 3
328328
329329 let sIdxPrice = 4
330330
331331 let sIdxOutNetAmount = 5
332332
333333 let sIdxOutFeeAmount = 6
334334
335335 let sIdxStartHeight = 7
336336
337337 let sIdxStartTimestamp = 8
338338
339339 let sIdxEndHeight = 9
340340
341341 let sIdxEndTimestamp = 10
342342
343343 let sIdxSelfUnlockHeight = 11
344344
345345 let sIdxRandUnlockHeight = 12
346346
347347 let sIdxIndex = 13
348348
349349 let sIdxWithdrawTxId = 14
350350
351351 let sIdxMinRand = 15
352352
353353 let sIdxMaxRand = 16
354354
355355 func swapKEY (userAddress,txId) = makeString(["%s%s", userAddress, txId], SEP)
356356
357357
358358 func strSwapDATA (swapType,status,inAmount,price,outNetAmount,outFeeAmount,startHeight,startTimestamp,endHeight,endTimestamp,selfUnlockHeight,randUnlockHeight,index,withdrawTxId,randMin,randMax) = makeString(["%s%s%d%d%d%d%d%d%d%d%d%d%d%s", swapType, status, inAmount, price, outNetAmount, outFeeAmount, startHeight, startTimestamp, endHeight, endTimestamp, selfUnlockHeight, randUnlockHeight, index, withdrawTxId, randMin, randMax], SEP)
359359
360360
361361 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")
362362
363363
364364 func finishSwapDATA (dataArray,price,outNetAmount,outFeeAmount,randUnlockHeight,index,withdrawTxId) = 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])
365365
366366
367367 func swapDataFailOrREAD (userAddress,swapTxId) = {
368368 let swapKey = swapKEY(userAddress, swapTxId)
369369 split(valueOrErrorMessage(getString(this, swapKey), ("no swap data for " + swapKey)), SEP)
370370 }
371371
372372
373373 func applyFees (amountOutGross,inAmtToSURF,feePart) = {
374374 let feeAmount = fraction(amountOutGross, feePart, PAULI)
375375 [(amountOutGross - feeAmount), feeAmount]
376376 }
377377
378378
379379 func abs (x) = if ((0 > x))
380380 then -(x)
381381 else x
382382
383383
384384 func selectNode (unleaseAmount) = {
385385 let amountToLease = ((wavesBalance(neutrinoContract).available - unleaseAmount) - getReservedAmountForSponsorship())
386386 let oldLeased0 = getNumberByKey(getLeaseAmountKey(0))
387387 let oldLeased1 = getNumberByKey(getLeaseAmountKey(1))
388388 let newLeased0 = (amountToLease + oldLeased0)
389389 let newLeased1 = (amountToLease + oldLeased1)
390390 if (if ((newLeased0 > 0))
391391 then true
392392 else (newLeased1 > 0))
393393 then {
394394 let delta0 = abs((newLeased0 - oldLeased1))
395395 let delta1 = abs((newLeased1 - oldLeased0))
396396 if ((delta1 >= delta0))
397397 then $Tuple2(0, newLeased0)
398398 else $Tuple2(1, newLeased1)
399399 }
400400 else $Tuple2(-1, 0)
401401 }
402402
403403
404404 func thisOnly (i) = if ((i.caller != this))
405405 then throw("Permission denied: this contract only allowed")
406406 else true
407407
408408
409409 func prepareUnleaseAndLease (unleaseAmount) = {
410410 let nodeTuple = selectNode(unleaseAmount)
411411 let nodeIndex = nodeTuple._1
412412 let newLeaseAmount = nodeTuple._2
413413 if ((newLeaseAmount > 0))
414414 then {
415415 let leaseIdKey = getLeaseIdKey(nodeIndex)
416416 let oldLease = getBinary(this, leaseIdKey)
417417 let unleaseOrEmpty = if (isDefined(oldLease))
418418 then [LeaseCancel(value(oldLease))]
419419 else nil
420420 let leaseAmountKey = getLeaseAmountKey(nodeIndex)
421421 let lease = Lease(getStakingNodeAddressByIndex(nodeIndex), newLeaseAmount)
422422 (unleaseOrEmpty ++ [lease, BinaryEntry(leaseIdKey, lcalc(lease)), IntegerEntry(getLeaseAmountKey(nodeIndex), newLeaseAmount)])
423423 }
424424 else nil
425425 }
426426
427427
428428 func readNodeInfo (nodeIdx) = {
429429 let nodeAddress = getStakingNodeAddressByIndex(nodeIdx)
430430 let leasedAmtKEY = getLeaseAmountKey(nodeIdx)
431431 let leasedAmt = getNumberByKey(leasedAmtKEY)
432432 let leaseIdKEY = getLeaseIdKey(nodeIdx)
433433 let leaseId = value(getBinary(this, leaseIdKEY))
434434 $Tuple5(nodeAddress, leasedAmtKEY, leasedAmt, leaseIdKEY, leaseId)
435435 }
436436
437437
438438 func commonSwap (swapType,pmtAmount,userAddressStr,txId58,swapParamsByUserSYSREADONLY) = {
439439 let swapLimitSpent = swapParamsByUserSYSREADONLY._2
440440 let blcks2LmtReset = swapParamsByUserSYSREADONLY._3
441441 let wavesSwapLimitMax = swapParamsByUserSYSREADONLY._6
442442 let usdnSwapLimitMax = swapParamsByUserSYSREADONLY._7
443443 let minSwapAmount = minSwapAmountREAD(swapType)
444444 let totalLocked = totalLockedREAD(swapType)
445445 let totalLockedByUser = totalLockedByUserREAD(swapType, userAddressStr)
446446 let nodeAddress = getStakingNodeByIndex(0)
447447 let priceByIndex = getPriceHistory(getHeightPriceByIndex(priceIndex))
448448 let isSwapByNode = (nodeAddress == userAddressStr)
449449 let balanceLockMaxInterval = if (isSwapByNode)
450450 then nodeBalanceLockIntervalREAD()
451451 else balanceLockIntervalREAD(swapType)
452452 let selfUnlockHeight = (height + balanceLockMaxInterval)
453453 let swapUsdnVolume = if ((swapType == "neutrino"))
454454 then pmtAmount
455455 else convertWavesToNeutrino(pmtAmount, priceByIndex)
456456 let swapLimitMax = if ((swapType == "neutrino"))
457457 then usdnSwapLimitMax
458458 else convertWavesToNeutrino(wavesSwapLimitMax, priceByIndex)
459459 if ((minSwapAmount > pmtAmount))
460460 then minSwapAmountFAIL(swapType, minSwapAmount)
461461 else if (if (!(isSwapByNode))
462462 then (swapLimitSpent > 0)
463463 else false)
464464 then throw(("You have exceeded swap limit! Next allowed swap height is " + toString((height + blcks2LmtReset))))
465465 else if (if (!(isSwapByNode))
466466 then (swapUsdnVolume > swapLimitMax)
467467 else false)
468468 then throw(((("You have exceeded your swap limit! Requested: " + toString(swapUsdnVolume)) + ", available: ") + toString(swapLimitMax)))
469469 else if (isBlocked)
470470 then emergencyShutdownFAIL()
471471 else {
472472 let leasePart = if ((swapType == "waves"))
473473 then prepareUnleaseAndLease(0)
474474 else nil
475475 $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)
476476 }
477477 }
478478
479479
480480 let nMetricIdxPrice = 0
481481
482482 let nMetricIdxUsdnLockedBalance = 1
483483
484484 let nMetricIdxWavesLockedBalance = 2
485485
486486 let nMetricIdxReserve = 3
487487
488488 let nMetricIdxReserveInUsdn = 4
489489
490490 let nMetricIdxUsdnSupply = 5
491491
492492 let nMetricIdxSurplus = 6
493493
494494 let nMetricIdxSurplusPercent = 7
495495
496496 let nMetricIdxBR = 8
497497
498498 let nMetricIdxNsbtSupply = 9
499499
500500 let nMetricIdxMaxNsbtSupply = 10
501501
502502 let nMetricIdxSurfSupply = 11
503503
504504 let bFuncIdxSurf = 0
505505
506506 let bFuncIdxWaves = 1
507507
508508 let bFuncIdxUsdn = 2
509509
510510 let bFuncIdxReserveStart = 3
511511
512512 let bFuncIdxSupplyStart = 4
513513
514514 let bFuncIdxBRStart = 5
515515
516516 let bFuncIdxReserveEnd = 6
517517
518518 let bFuncIdxSupplyEnd = 7
519519
520520 let bFuncIdxBREnd = 8
521521
522522 let bFuncIdxRest = 9
523523
524524 let bFuncIdxWavesPrice = 10
525525
526526 func calcWithdrawW2U (wavesIn,price) = {
527527 let outAmtGross = convertWavesToNeutrino(wavesIn, price)
528528 $Tuple9(outAmtGross, neutrinoAssetId, 0, unit, 0, wavesIn, 0, 0, 0)
529529 }
530530
531531
532532 func calcWithdrawU2W (usdnIn,price,br,reservesInUsdn,usdnSupply) = {
533533 let brProtected = valueOrElse(getInteger(this, brProtectedKEY()), BRPROTECTED)
534534 let maxAllowedUsdnBeforeMinBr = if ((brProtected >= br))
535535 then 0
536536 else fraction((reservesInUsdn - fraction(brProtected, usdnSupply, PAULI)), PAULI, (PAULI - brProtected))
537537 let allowedUsdnBeforeMinBr = if ((usdnIn > maxAllowedUsdnBeforeMinBr))
538538 then maxAllowedUsdnBeforeMinBr
539539 else usdnIn
540540 let allowedUsdnAfterMinBr = if ((usdnIn > maxAllowedUsdnBeforeMinBr))
541541 then fraction((usdnIn - maxAllowedUsdnBeforeMinBr), br, PAULI)
542542 else 0
543543 let allowedUsdn = (allowedUsdnBeforeMinBr + allowedUsdnAfterMinBr)
544544 let usdn2SURF = (usdnIn - allowedUsdn)
545545 let outAmtGross = convertNeutrinoToWaves(allowedUsdn, price)
546546 $Tuple9(outAmtGross, unit, usdn2SURF, neutrinoAssetId, outAmtGross, allowedUsdn, maxAllowedUsdnBeforeMinBr, allowedUsdnBeforeMinBr, allowedUsdnAfterMinBr)
547547 }
548548
549549
550550 func calcWithdraw (swapType,inAmount,price) = {
551551 let outFeePart = valueOrElse(getInteger(this, outFeePartKEY(swapType)), DEFAULTSWAPFEE)
552552 if (if ((0 > outFeePart))
553553 then true
554554 else (outFeePart >= PAULI))
555555 then throw(((("invalid outFeePart config for " + swapType) + " swap: outFeePart=") + toString(outFeePart)))
556556 else {
557557 let brProtected = valueOrElse(getInteger(this, brProtectedKEY()), BRPROTECTED)
558558 let neutrinoMetrics = asAnyList(invoke(mathContract, "calcNeutinoMetricsREADONLY", nil, nil))
559559 let BR = asInt(neutrinoMetrics[nMetricIdxBR])
560560 let reservesInUsdn = asInt(neutrinoMetrics[nMetricIdxReserveInUsdn])
561561 let usdnSupply = asInt(neutrinoMetrics[nMetricIdxUsdnSupply])
562562 let outDataTuple = if ((swapType == "waves"))
563563 then calcWithdrawW2U(inAmount, price)
564564 else if ((swapType == "neutrino"))
565565 then calcWithdrawU2W(inAmount, price, BR, reservesInUsdn, usdnSupply)
566566 else throw(("Unsupported swap type " + swapType))
567567 let outAmtGross = outDataTuple._1
568568 let outAssetId = outDataTuple._2
569569 let inAmtToSurfPart = outDataTuple._3
570570 let inAssetId = outDataTuple._4
571571 let unleaseAmt = outDataTuple._5
572572 let payoutsArray = applyFees(outAmtGross, inAmtToSurfPart, outFeePart)
573573 let outNetAmt = payoutsArray[IdxNetAmount]
574574 let outFeeAmt = payoutsArray[IdxFeeAmount]
575575 let outSurfAmt = if ((0 >= inAmtToSurfPart))
576576 then 0
577577 else {
578578 let surfResult = asAnyList(invoke(mathContract, "surfFunctionREADONLY", [inAmtToSurfPart, inAssetId], nil))
579579 asInt(surfResult[bFuncIdxSurf])
580580 }
581581 $Tuple7(outNetAmt, outAssetId, outSurfAmt, inAmtToSurfPart, unleaseAmt, outFeeAmt, outAmtGross)
582582 }
583583 }
584584
585585
586586 func commonWithdraw (account,index,swapTxId,withdrawTxId) = {
587587 let userAddress = addressFromStringValue(account)
588588 let dataArray = swapDataFailOrREAD(account, swapTxId)
589589 let selfUnlockHeight = parseIntValue(dataArray[sIdxSelfUnlockHeight])
590590 let swapType = dataArray[sIdxSwapType]
591591 let inAmount = parseIntValue(dataArray[sIdxInAmount])
592592 let swapStatus = dataArray[sIdxStatus]
593593 let startHeight = parseIntValue(dataArray[sIdxStartHeight])
594594 let outFeePart = valueOrElse(getInteger(this, outFeePartKEY(swapType)), DEFAULTSWAPFEE)
595595 let totalLocked = totalLockedREAD(swapType)
596596 let totalLockedByUser = totalLockedByUserREAD(swapType, account)
597597 let unlockHeight = selfUnlockHeight
598598 let indexHeight = getHeightPriceByIndex(index)
599599 let prevIndexHeight = getHeightPriceByIndex((index - 1))
600600 let priceByIndex = getPriceHistory(indexHeight)
601601 if (isBlocked)
602602 then emergencyShutdownFAIL()
603603 else if ((swapStatus != "PENDING"))
604604 then throw("swap has been already processed")
605605 else if ((unlockHeight > height))
606606 then throw((("please wait for: " + toString(unlockHeight)) + " block height to withdraw funds"))
607607 else if (if (if ((index > priceIndex))
608608 then true
609609 else (unlockHeight > indexHeight))
610610 then true
611611 else if ((prevIndexHeight != 0))
612612 then (prevIndexHeight >= unlockHeight)
613613 else false)
614614 then priceIndexFAIL(index, priceIndex, indexHeight, unlockHeight, prevIndexHeight)
615615 else {
616616 let withdrawTuple = calcWithdraw(swapType, inAmount, priceByIndex)
617617 let outNetAmount = withdrawTuple._1
618618 let outAssetId = withdrawTuple._2
619619 let outSurfAmt = withdrawTuple._3
620620 let inAmtToSurfPart = withdrawTuple._4
621621 let unleaseAmt = withdrawTuple._5
622622 let outFeeAmount = withdrawTuple._6
623623 let outAmtGross = withdrawTuple._7
624624 if ((0 >= outAmtGross))
625625 then throw("balance equals zero")
626626 else {
627627 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))]
628628 let surfCondition = if ((outSurfAmt > 0))
629629 then {
630630 let issueResult = invoke(auctionContract, "issueSurf", [outSurfAmt, account], nil)
631631 if ((issueResult == issueResult))
632632 then 0
633633 else throw("Strict value is not equal to itself.")
634634 }
635635 else 0
636636 if ((surfCondition == surfCondition))
637637 then $Tuple3(state, AttachedPayment(outAssetId, outFeeAmount), unleaseAmt)
638638 else throw("Strict value is not equal to itself.")
639639 }
640640 }
641641 }
642642
643643
644644 @Callable(i)
645645 func constructor (neutrinoAssetIdPrm,bondAssetIdPrm,auctionContractPrm,liquidationContractPrm,rpdContractPrm,nodeOracleProviderPubKeyPrm,balanceWavesLockIntervalPrm,balanceNeutrinoLockIntervalPrm,minWavesSwapAmountPrm,minNeutrinoSwapAmountPrm,neutrinoOutFeePartPrm,wavesOutFeePartPrm) = {
646646 let checkCaller = thisOnly(i)
647647 if ((checkCaller == checkCaller))
648648 then if ((size(i.payments) != 0))
649649 then throw("no payments allowed")
650650 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)]
651651 else throw("Strict value is not equal to itself.")
652652 }
653653
654654
655655
656656 @Callable(i)
657657 func constructorV2 (mathContract,nsbtStakingContract,swapsTimeframeBlocks) = {
658658 let checkCaller = thisOnly(i)
659659 if ((checkCaller == checkCaller))
660660 then if ((size(i.payments) != 0))
661661 then throw("no payments allowed")
662662 else [StringEntry(MathContractKey, mathContract), StringEntry(NsbtStakingContractKey, nsbtStakingContract), IntegerEntry(swapsTimeframeKEY(), swapsTimeframeBlocks)]
663663 else throw("Strict value is not equal to itself.")
664664 }
665665
666666
667667
668668 @Callable(i)
669669 func swapWavesToNeutrino () = if ((size(i.payments) != 1))
670670 then throw("swapWavesToNeutrino require only one payment")
671671 else {
672672 let pmt = value(i.payments[0])
673673 if (isDefined(pmt.assetId))
674674 then throw("Only Waves token is allowed for swapping.")
675675 else {
676676 let userAddress = toString(i.caller)
677677 let txId58 = toBase58String(i.transactionId)
678678 let swapParamsSTRUCT = asSwapParamsSTRUCT(invoke(this, "swapParamsByUserSYSREADONLY", [userAddress, 0], nil))
679679 let commonSwapResult = commonSwap("waves", pmt.amount, userAddress, txId58, swapParamsSTRUCT)
680680 commonSwapResult
681681 }
682682 }
683683
684684
685685
686686 @Callable(i)
687687 func swapNeutrinoToWaves () = if ((size(i.payments) != 1))
688688 then throw("swapNeutrinoToWaves require only one payment")
689689 else {
690690 let pmt = value(i.payments[0])
691691 if ((pmt.assetId != neutrinoAssetId))
692692 then throw("Only appropriate Neutrino tokens are allowed for swapping.")
693693 else {
694694 let userAddress = toString(i.caller)
695695 let txId58 = toBase58String(i.transactionId)
696696 let swapParamsSTRUCT = asSwapParamsSTRUCT(invoke(this, "swapParamsByUserSYSREADONLY", [userAddress, 0], nil))
697697 let commonSwapResult = commonSwap("neutrino", pmt.amount, userAddress, txId58, swapParamsSTRUCT)
698698 commonSwapResult
699699 }
700700 }
701701
702702
703703
704704 @Callable(i)
705705 func withdraw (account,index,swapTxId) = {
706706 let txId = toBase58String(i.transactionId)
707707 if ((size(i.payments) != 0))
708708 then throw("no payments allowed")
709709 else {
710710 let commonTuple = commonWithdraw(account, index, swapTxId, txId)
711711 let state = commonTuple._1
712712 let fee = commonTuple._2
713713 let unleaseAmt = commonTuple._3
714714 let unleaseInvOrEmpty = invoke(this, "internalUnleaseAndLease", [unleaseAmt], nil)
715715 if ((unleaseInvOrEmpty == unleaseInvOrEmpty))
716716 then {
717717 let gnsbtData = asAnyList(invoke(gnsbtControllerContract, "gnsbtInfoSYSREADONLY", ["", 0, 0], nil))
718718 let gnsbtAmtTotal = asInt(gnsbtData[1])
719719 let gnsbtAmtFromSurfTotal = asInt(asAnyList(gnsbtData[3])[3])
720720 let surfFeeAmt = if ((gnsbtAmtTotal != 0))
721721 then fraction(fee.amount, gnsbtAmtFromSurfTotal, gnsbtAmtTotal)
722722 else 0
723723 let nsbtFeeAmt = (fee.amount - surfFeeAmt)
724724 let surfDeposit = if ((surfFeeAmt > 0))
725725 then {
726726 let surfInv = invoke(surfStakingContract, "deposit", nil, [AttachedPayment(fee.assetId, surfFeeAmt)])
727727 if ((surfInv == surfInv))
728728 then nil
729729 else throw("Strict value is not equal to itself.")
730730 }
731731 else nil
732732 if ((surfDeposit == surfDeposit))
733733 then {
734734 let nsbtDeposit = if ((nsbtFeeAmt > 0))
735735 then {
736736 let nsbtInv = invoke(nsbtStakingContract, "deposit", nil, [AttachedPayment(fee.assetId, nsbtFeeAmt)])
737737 if ((nsbtInv == nsbtInv))
738738 then nil
739739 else throw("Strict value is not equal to itself.")
740740 }
741741 else nil
742742 if ((nsbtDeposit == nsbtDeposit))
743743 then state
744744 else throw("Strict value is not equal to itself.")
745745 }
746746 else throw("Strict value is not equal to itself.")
747747 }
748748 else throw("Strict value is not equal to itself.")
749749 }
750750 }
751751
752752
753753
754754 @Callable(i)
755755 func internalUnleaseAndLease (unleaseAmount) = if ((i.caller != this))
756756 then throw("internalUnleaseAndLease is not public method")
757757 else prepareUnleaseAndLease(unleaseAmount)
758758
759759
760760
761761 @Callable(i)
762762 func transferUsdnToUser (amount,addr) = if ((i.caller != auctionContract))
763763 then throw("Only auction contract is authorized")
764764 else [ScriptTransfer(addressFromStringValue(addr), amount, neutrinoAssetId)]
765765
766766
767767
768768 @Callable(i)
769769 func acceptWaves () = if ((i.caller != auctionContract))
770770 then throw("Currently only auction contract is allowed to call")
771771 else $Tuple2(prepareUnleaseAndLease(0), "success")
772772
773773
774774
775775 @Callable(i)
776776 func approveLeasings (nListS,groupNum) = {
777777 let lAmt = (50 * WAVELET)
778778 let nIdxs = [0, 1, 2, 3, 4, 5, 6, 7]
779779 let mngPubS = valueOrElse(getString("%s%s__cfg__leasingManagerPub"), "7AUMX54ukYMYvPmma7yoFf5NjZhs4Bu5nz3Ez9EV8sur")
780780 let mngPub = fromBase58String(mngPubS)
781781 let nodeRegAddrStr = valueOrElse(getString("%s%s__cfg__nodesRegistryAddress"), "3P9vKqQKjUdmpXAfiWau8krREYAY1Xr69pE")
782782 let nodeRegAddr = addressFromStringValue(nodeRegAddrStr)
783783 let lGroupNodeListKEY = getLeaseGroupNodeListKey(groupNum)
784784 let lGrNodeOpt = getString(this, lGroupNodeListKEY)
785785 if (isDefined(lGrNodeOpt))
786786 then throw((("group " + toString(groupNum)) + " already initialized"))
787787 else {
788788 let nList = split(nListS, SEP)
789789 let expCount = size(nIdxs)
790790 if ((i.callerPublicKey != mngPub))
791791 then throw("approveLeasings not authorized")
792792 else {
793793 let $t03363933701 = readNodeInfo(0)
794794 let nAddr0 = $t03363933701._1
795795 let lAmtKEY0 = $t03363933701._2
796796 let lAmt0 = $t03363933701._3
797797 let lIdKEY0 = $t03363933701._4
798798 let lId0 = $t03363933701._5
799799 let $t03370433766 = readNodeInfo(1)
800800 let nAddr1 = $t03370433766._1
801801 let lAmtKEY1 = $t03370433766._2
802802 let lAmt1 = $t03370433766._3
803803 let lIdKEY1 = $t03370433766._4
804804 let lId1 = $t03370433766._5
805805 let newL0 = Lease(nAddr0, (lAmt0 - ((lAmt * expCount) / 2)))
806806 let newL1 = Lease(nAddr1, (lAmt1 - ((lAmt * expCount) / 2)))
807807 let validation = invoke(nodeRegAddr, "validateAndApproveLeasings", [nListS], nil)
808808 if ((validation == validation))
809809 then {
810810 func forEachNodeValidateAndGenerateLease (a,i) = {
811811 let node = nList[i]
812812 let la = Lease(addressFromStringValue(node), lAmt)
813813 (a ++ [la, BinaryEntry(getLeaseIdByAddressKey(node), lcalc(la)), IntegerEntry(getLeaseAmountByAddressKey(node), lAmt)])
814814 }
815815
816816 ([StringEntry(lGroupNodeListKEY, nListS), BinaryEntry(lIdKEY0, lcalc(newL0)), BinaryEntry(lIdKEY1, lcalc(newL1)), IntegerEntry(lAmtKEY0, newL0.amount), IntegerEntry(lAmtKEY1, newL1.amount), LeaseCancel(lId0), LeaseCancel(lId1), newL0, newL1] ++ {
817817 let $l = nIdxs
818818 let $s = size($l)
819819 let $acc0 = nil
820820 func $f0_1 ($a,$i) = if (($i >= $s))
821821 then $a
822822 else forEachNodeValidateAndGenerateLease($a, $l[$i])
823823
824824 func $f0_2 ($a,$i) = if (($i >= $s))
825825 then $a
826826 else throw("List size exceeds 8")
827827
828828 $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)
829829 })
830830 }
831831 else throw("Strict value is not equal to itself.")
832832 }
833833 }
834834 }
835835
836836
837837
838838 @Callable(i)
839839 func rebalanceLeasings (amount,groupNum) = {
840840 let nIdxs = [0, 1, 2, 3, 4, 5, 6, 7]
841841 let mngPubS = valueOrElse(getString("%s%s__cfg__leasingManagerPub"), "7AUMX54ukYMYvPmma7yoFf5NjZhs4Bu5nz3Ez9EV8sur")
842842 let mngPub = fromBase58String(mngPubS)
843843 let lGroupNodeListKEY = getLeaseGroupNodeListKey(groupNum)
844844 let nListS = getStringOrFail(this, lGroupNodeListKEY)
845845 let nList = split(nListS, SEP)
846846 if ((i.callerPublicKey != mngPub))
847847 then throw("rebalanceLeasings not authorized")
848848 else {
849849 let unleaseAmt = ((amount / size(nList)) + 1)
850850 let $t03518335245 = readNodeInfo(0)
851851 let nAddr0 = $t03518335245._1
852852 let lAmtKEY0 = $t03518335245._2
853853 let lAmt0 = $t03518335245._3
854854 let lIdKEY0 = $t03518335245._4
855855 let lId0 = $t03518335245._5
856856 let newL0 = Lease(nAddr0, (lAmt0 + (unleaseAmt * size(nList))))
857857 func forEachNodeDoUnlease (a,i) = {
858858 let node = nList[i]
859859 let lIdKEY = getLeaseIdByAddressKey(node)
860860 let lId = getBinaryValue(this, lIdKEY)
861861 let lAmtKEY = getLeaseAmountByAddressKey(node)
862862 let lAmt = getIntegerValue(this, lAmtKEY)
863863 let ula = LeaseCancel(value(lId))
864864 let la = Lease(addressFromStringValue(node), (lAmt - unleaseAmt))
865865 (a ++ [LeaseCancel(value(lId)), la, BinaryEntry(lIdKEY, lcalc(la)), IntegerEntry(lAmtKEY, la.amount)])
866866 }
867867
868868 ({
869869 let $l = nIdxs
870870 let $s = size($l)
871871 let $acc0 = nil
872872 func $f0_1 ($a,$i) = if (($i >= $s))
873873 then $a
874874 else forEachNodeDoUnlease($a, $l[$i])
875875
876876 func $f0_2 ($a,$i) = if (($i >= $s))
877877 then $a
878878 else throw("List size exceeds 8")
879879
880880 $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)
881881 } ++ [BinaryEntry(lIdKEY0, lcalc(newL0)), IntegerEntry(lAmtKEY0, newL0.amount), LeaseCancel(lId0), newL0])
882882 }
883883 }
884884
885885
886886
887887 @Callable(i)
888888 func swapParamsByUserSYSREADONLY (userAddressStr,gnsbtDiff) = {
889889 let gnsbtData = asAnyList(invoke(gnsbtControllerContract, "gnsbtInfoSYSREADONLY", [userAddressStr, 0, 0], nil))
890890 let gnsbtAmt = (asInt(gnsbtData[0]) + gnsbtDiff)
891891 let gnsbtAmtTotal = (asInt(gnsbtData[1]) + gnsbtDiff)
892892 let swapLimitData = asAnyList(invoke(mathContract, "calcSwapLimitREADONLY", [gnsbtAmt], nil))
893893 let wavesSwapLimitInUsdnMax = asInt(swapLimitData[0])
894894 let wavesSwapLimitMax = asInt(swapLimitData[1])
895895 let usdnSwapLimitMax = asInt(swapLimitData[2])
896896 let lastSwapHeight = valueOrElse(getInteger(this, keyUserLastSwapHeight(userAddressStr)), 0)
897897 let swapLimitTimelifeBlocks = swapsTimeframeREAD()
898898 let passedBlocksAfterLastSwap = (height - lastSwapHeight)
899899 let isSwapTimelifeNew = (passedBlocksAfterLastSwap >= swapLimitTimelifeBlocks)
900900 let swapLimitSpentInUsdn = if (isSwapTimelifeNew)
901901 then 0
902902 else valueOrElse(getInteger(this, keySwapUserSpentInPeriod(userAddressStr)), 0)
903903 let blcks2LmtReset = if (isSwapTimelifeNew)
904904 then 0
905905 else (swapLimitTimelifeBlocks - passedBlocksAfterLastSwap)
906906 $Tuple2(nil, $Tuple7(wavesSwapLimitInUsdnMax, swapLimitSpentInUsdn, blcks2LmtReset, gnsbtAmt, gnsbtAmtTotal, wavesSwapLimitMax, usdnSwapLimitMax))
907907 }
908908
909909
910910
911911 @Callable(i)
912912 func calcWithdrawResultSYSREADONLY (swapType,inAmount,price) = $Tuple2(nil, calcWithdraw(swapType, inAmount, price))
913913
914914
915915
916916 @Callable(i)
917917 func updateReservesAndNeutrinoSupply () = {
918918 func getNumberByKeyInternal (key) = match getInteger(this, key) {
919919 case a: Int =>
920920 a
921921 case _ =>
922922 0
923923 }
924924
925925 let nMetrix = asAnyList(invoke(mathContract, "calcNeutinoMetricsREADONLY", nil, nil))
926926 let idx = getNumberByKeyInternal("updateReservesAndNeutrinoSupplyIdx")
927927 let newIdx = (idx + 1)
928928 [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])))]
929929 }
930930
931931
932932
933933 @Callable(i)
934934 func wavesBalancesVsPayment () = {
935935 let b = wavesBalance(this)
936936 [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)]
937937 }
938938
939939
940940 @Verifier(tx)
941941 func verify () = {
942942 let id = toBase58String(tx.id)
943943 let pubKeyAdminsListStr = makeString(["ExtEEK19nmKj9mCpnWyvEEJFYATLMcVEMvohhUHkyHNm", "Ev5py5FfBQX9cZpYKnfQrTB49Byf8QmpZWeDVRim4yV7", "DUuuLjXu98nBwZc7fqwCTjtA3nnRwgTbkMSr5SU2NmDR", "DUuuLjXu98nBwZc7fqwCTjtA3nnRwgTbkMSr5SU2NmDR"], SEP)
944944 let pubKeyAdminsList = split(valueOrElse(getString(controlContract, "%s__multisig"), pubKeyAdminsListStr), SEP)
945945 let count = ((((if (sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(pubKeyAdminsList[0])))
946946 then 1
947947 else 0) + (if (sigVerify(tx.bodyBytes, tx.proofs[1], fromBase58String(pubKeyAdminsList[1])))
948948 then 1
949949 else 0)) + (if (sigVerify(tx.bodyBytes, tx.proofs[2], fromBase58String(pubKeyAdminsList[2])))
950950 then 1
951951 else 0)) + (if (sigVerify(tx.bodyBytes, tx.proofs[3], fromBase58String(pubKeyAdminsList[3])))
952952 then 2
953953 else 0))
954954 match tx {
955955 case sponsorTx: SponsorFeeTransaction =>
956956 if (checkIsValidMinSponsoredFee(sponsorTx))
957957 then (count >= 3)
958958 else false
959959 case _ =>
960960 (count >= 3)
961961 }
962962 }
963963

github/deemru/w8io/3ef1775 
206.34 ms