tx · 5XeZwk7EdGCUhBmXJMqW8Z2mEZj41XWFp7qTpFRHTSjQ

3Mzbx34Ex5rRbn39vUHx9kiwh3nneF8S5we:  -0.02000000 Waves

2022.02.10 19:25 [1917755] smart account 3Mzbx34Ex5rRbn39vUHx9kiwh3nneF8S5we > SELF 0.00000000 Waves

{ "type": 13, "id": "5XeZwk7EdGCUhBmXJMqW8Z2mEZj41XWFp7qTpFRHTSjQ", "fee": 2000000, "feeAssetId": null, "timestamp": 1644510348577, "version": 1, "sender": "3Mzbx34Ex5rRbn39vUHx9kiwh3nneF8S5we", "senderPublicKey": "BxuvXsg8sFXf7MNECYrdsEgrMMMkWVKKhbcFdoormLWF", "proofs": [ "3ehUUCwUjMxPJRhT65JTQixYrQP5frer6dWUCfCPpuKuRnrSphZv8fEworemDHmsGVBfz3HPp6E2zNP8oKmB9wc", "5QCWkuwPHiv8BSoNKk7ZuQPPzjnBUMQd9FcPsyvVKUgWoWauhXSr6eTJCy3JHPzRe5vXitrSwyivEHiTzd3J6MfB", "5JXpXaZLcu113RajrvQXPbz8xAsxqCcvjVnFZbZgGCQCPEETBZ8B5sitG879UFpciV76q7DawtVtdDDWzu4DsmLY" ], "script": "base64:AAIFAAAAAAAAAFsIAhIDCgEBEhAKDggICAgICAgIAQEBAQEBEggKBggICAEBARIGCgQIAQgIEgYKBAgBCAISAwoBCBIECgIICBIFCgMIAQgSBgoECAEIAhIAEgASAwoBARIDCgEIAAAAfgEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABAAAAA2tleQkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAR0aGlzBQAAAANrZXkAAAAAAAAAAAABAAAADmdldFN0cmluZ0J5S2V5AAAAAQAAAANrZXkJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQdAAAAAgUAAAAEdGhpcwUAAAADa2V5AgAAAAABAAAADGdldEJvb2xCeUtleQAAAAEAAAADa2V5CQEAAAALdmFsdWVPckVsc2UAAAACCQAEGwAAAAIFAAAABHRoaXMFAAAAA2tleQcBAAAAGGdldE51bWJlckJ5QWRkcmVzc0FuZEtleQAAAAIAAAAHYWRkcmVzcwAAAANrZXkJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQaAAAAAgkBAAAAEUBleHRyTmF0aXZlKDEwNjIpAAAAAQUAAAAHYWRkcmVzcwUAAAADa2V5AAAAAAAAAAAAAQAAABhnZXRTdHJpbmdCeUFkZHJlc3NBbmRLZXkAAAACAAAAB2FkZHJlc3MAAAADa2V5CQEAAAALdmFsdWVPckVsc2UAAAACCQAEHQAAAAIJAQAAABFAZXh0ck5hdGl2ZSgxMDYyKQAAAAEFAAAAB2FkZHJlc3MFAAAAA2tleQIAAAAAAQAAABZnZXRCb29sQnlBZGRyZXNzQW5kS2V5AAAAAgAAAAdhZGRyZXNzAAAAA2tleQkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBsAAAACCQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABBQAAAAdhZGRyZXNzBQAAAANrZXkHAAAAABBwdWJLZXlBZG1pbnNMaXN0CQAETAAAAAICAAAALEdYeG1aYUNpZ1BnSnNUNmQxY0xyOG5VWEE2NW5HWDhWN0Z1QXp6clk4d1FFCQAETAAAAAICAAAALDN4dW14NGhyUHBlZW9vNzlITEdiWkNnZno5NUwzOVpGZHh4d1dlU1VDMlB1CQAETAAAAAICAAAALEQ0Q3F0SzVmQnNuelJvMzNaTWhyTTduaUxzZURIMnVSb0s2d2VCcTJKUTNBCQAETAAAAAICAAAALDVXUlhGU2p3Y1RiTmZLY0pzOFpxWG1TU1dZc1NWSlV0TXZNcVpqNWhINE5jBQAAAANuaWwBAAAABWFzSW50AAAAAQAAAAN2YWwEAAAAByRtYXRjaDAFAAAAA3ZhbAMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAADSW50BAAAAAZ2YWxJbnQFAAAAByRtYXRjaDAFAAAABnZhbEludAkAAAIAAAABAgAAABdGYWlsZWQgdG8gY2FzdCBpbnRvIEludAAAAAADU0VQAgAAAAJfXwAAAAAHV0FWRUxFVAAAAAAABfXhAAAAAAAFUEFVTEkAAAAAAAAPQkAAAAAACFBSSUNFTEVUAAAAAAAAD0JAAAAAAA5ERUZBVUxUU1dBUEZFRQAAAAAAAABOIAAAAAAMSWR4TmV0QW1vdW50AAAAAAAAAAAAAAAAAAxJZHhGZWVBbW91bnQAAAAAAAAAAAEAAAAADklkeEdyb3NzQW1vdW50AAAAAAAAAAACAAAAAA9kb3JhMk5zYnRTeW1ib2wCAAAACU5TQlQtVVNEVAAAAAAHbWluUmFuZAAAAAAAAAAAPAAAAAAHbWF4UmFuZAAAAAAAAAAFoAAAAAASTmV1dHJpbm9Bc3NldElkS2V5AgAAABFuZXV0cmlub19hc3NldF9pZAAAAAAOQm9uZEFzc2V0SWRLZXkCAAAADWJvbmRfYXNzZXRfaWQAAAAAEkF1Y3Rpb25Db250cmFjdEtleQIAAAAQYXVjdGlvbl9jb250cmFjdAAAAAAWTGlxdWlkYXRpb25Db250cmFjdEtleQIAAAAUbGlxdWlkYXRpb25fY29udHJhY3QAAAAADlJQRENvbnRyYWN0S2V5AgAAAAxycGRfY29udHJhY3QAAAAAEkNvbnRyb2xDb250cmFjdEtleQIAAAAQY29udHJvbF9jb250cmFjdAAAAAAbQmFsYW5jZVdhdmVzTG9ja0ludGVydmFsS2V5AgAAABtiYWxhbmNlX3dhdmVzX2xvY2tfaW50ZXJ2YWwAAAAAHkJhbGFuY2VOZXV0cmlub0xvY2tJbnRlcnZhbEtleQIAAAAeYmFsYW5jZV9uZXV0cmlub19sb2NrX2ludGVydmFsAAAAABVNaW5XYXZlc1N3YXBBbW91bnRLZXkCAAAAFW1pbl93YXZlc19zd2FwX2Ftb3VudAAAAAAYTWluTmV1dHJpbm9Td2FwQW1vdW50S2V5AgAAABhtaW5fbmV1dHJpbm9fc3dhcF9hbW91bnQAAAAAG05vZGVPcmFjbGVQcm92aWRlclB1YktleUtleQIAAAAUbm9kZV9vcmFjbGVfcHJvdmlkZXIAAAAAFU5ldXRyaW5vT3V0RmVlUGFydEtleQIAAAAYbmV1dHJpbm9PdXRfc3dhcF9mZWVQYXJ0AAAAABJXYXZlc091dEZlZVBhcnRLZXkCAAAAFXdhdmVzT3V0X3N3YXBfZmVlUGFydAAAAAASUnNhUmFuZFB1YmxpYzU4S2V5AgAAAA9yYW5kX3JzYV9wdWJsaWMAAAAAEGtleUdOc2J0Q29udHJhY3QCAAAAESVzX19nTnNidENvbnRyYWN0AAAAABNrZXlOc2J0TG9ja0NvbnRyYWN0AgAAABQlc19fbnNidExvY2tDb250cmFjdAAAAAAQa2V5RG9yYTJDb250cmFjdAIAAAARJXNfX2RvcmEyQ29udHJhY3QAAAAAEWtleVF1aWNrU3dhcERlbGF5AgAAABIlc19fcXVpY2tTd2FwRGVsYXkAAAAAGWtleVF1aWNrU3dhcExpbWl0RHVyYXRpb24CAAAAGiVzX19xdWlja1N3YXBMaW1pdER1cmF0aW9uAAAAABdrZXlEb3JhMkxhc3RIZWlnaHRMaW1pdAIAAAAYJXNfX2RvcmEyTGFzdEhlaWdodExpbWl0AAAAAAhQcmljZUtleQIAAAAFcHJpY2UAAAAADVByaWNlSW5kZXhLZXkCAAAAC3ByaWNlX2luZGV4AAAAAAxJc0Jsb2NrZWRLZXkCAAAACmlzX2Jsb2NrZWQBAAAAEmdldFByaWNlSGlzdG9yeUtleQAAAAEAAAAFYmxvY2sJAAEsAAAAAgkAASwAAAACBQAAAAhQcmljZUtleQIAAAABXwkAAaQAAAABBQAAAAVibG9jawEAAAAYZ2V0SGVpZ2h0UHJpY2VCeUluZGV4S2V5AAAAAQAAAAVpbmRleAkAASwAAAACCQABLAAAAAIFAAAADVByaWNlSW5kZXhLZXkCAAAAAV8JAAGkAAAAAQUAAAAFaW5kZXgBAAAAFWdldFN0YWtpbmdOb2RlQnlJbmRleAAAAAEAAAADaWR4CQEAAAAOZ2V0U3RyaW5nQnlLZXkAAAABCQAEuQAAAAIJAARMAAAAAgIAAAAGJXMlZCVzCQAETAAAAAICAAAABWxlYXNlCQAETAAAAAIJAAGkAAAAAQUAAAADaWR4CQAETAAAAAICAAAAC25vZGVBZGRyZXNzBQAAAANuaWwFAAAAA1NFUAEAAAAcZ2V0U3Rha2luZ05vZGVBZGRyZXNzQnlJbmRleAAAAAEAAAADaWR4CQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABCQEAAAAVZ2V0U3Rha2luZ05vZGVCeUluZGV4AAAAAQUAAAADaWR4AQAAAB9nZXRSZXNlcnZlZEFtb3VudEZvclNwb25zb3JzaGlwAAAAAAkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAR0aGlzCQAEuQAAAAIJAARMAAAAAgIAAAAEJXMlcwkABEwAAAACAgAAAAVsZWFzZQkABEwAAAACAgAAABdzcG9uc29yc2hpcFdhdmVzUmVzZXJ2ZQUAAAADbmlsBQAAAANTRVAJAABoAAAAAgAAAAAAAAAD6AUAAAAHV0FWRUxFVAEAAAAYZ2V0QmFsYW5jZVVubG9ja0Jsb2NrS2V5AAAAAQAAAAVvd25lcgkAASwAAAACAgAAABViYWxhbmNlX3VubG9ja19ibG9ja18FAAAABW93bmVyAQAAAA1nZXRMZWFzZUlkS2V5AAAAAQAAAAlub2RlSW5kZXgJAAS5AAAAAgkABEwAAAACAgAAAAYlcyVkJXMJAARMAAAAAgIAAAAFbGVhc2UJAARMAAAAAgkAAaQAAAABBQAAAAlub2RlSW5kZXgJAARMAAAAAgIAAAACaWQFAAAAA25pbAUAAAADU0VQAQAAABFnZXRMZWFzZUFtb3VudEtleQAAAAEAAAAJbm9kZUluZGV4CQAEuQAAAAIJAARMAAAAAgIAAAAGJXMlZCVzCQAETAAAAAICAAAABWxlYXNlCQAETAAAAAIJAAGkAAAAAQUAAAAJbm9kZUluZGV4CQAETAAAAAICAAAABmFtb3VudAUAAAADbmlsBQAAAANTRVABAAAAEG1pblN3YXBBbW91bnRLRVkAAAABAAAACHN3YXBUeXBlCQABLAAAAAIJAAEsAAAAAgIAAAAEbWluXwUAAAAIc3dhcFR5cGUCAAAADF9zd2FwX2Ftb3VudAEAAAAOdG90YWxMb2NrZWRLRVkAAAABAAAACHN3YXBUeXBlCQABLAAAAAICAAAADWJhbGFuY2VfbG9ja18FAAAACHN3YXBUeXBlAQAAABR0b3RhbExvY2tlZEJ5VXNlcktFWQAAAAIAAAAIc3dhcFR5cGUAAAAFb3duZXIJAAS5AAAAAgkABEwAAAACAgAAAAxiYWxhbmNlX2xvY2sJAARMAAAAAgUAAAAIc3dhcFR5cGUJAARMAAAAAgUAAAAFb3duZXIFAAAAA25pbAIAAAABXwEAAAAWYmFsYW5jZUxvY2tJbnRlcnZhbEtFWQAAAAEAAAAIc3dhcFR5cGUJAAEsAAAAAgkAASwAAAACAgAAAAhiYWxhbmNlXwUAAAAIc3dhcFR5cGUCAAAADl9sb2NrX2ludGVydmFsAQAAABltaW5CYWxhbmNlTG9ja0ludGVydmFsS0VZAAAAAQAAAAhzd2FwVHlwZQkAASwAAAACCQABLAAAAAICAAAACGJhbGFuY2VfBQAAAAhzd2FwVHlwZQIAAAAWX2xvY2tfaW50ZXJ2YWxfbWluaW11bQEAAAAabm9kZUJhbGFuY2VMb2NrSW50ZXJ2YWxLRVkAAAAAAgAAABpiYWxhbmNlX25vZGVfbG9ja19pbnRlcnZhbAEAAAANb3V0RmVlUGFydEtFWQAAAAEAAAAIc3dhcFR5cGUJAAEsAAAAAgUAAAAIc3dhcFR5cGUCAAAAEE91dF9zd2FwX2ZlZVBhcnQBAAAAHWtleVF1aWNrU3dhcFVzZXJTcGVudEluUGVyaW9kAAAAAQAAAAt1c2VyQWRkcmVzcwkABLkAAAACCQAETAAAAAICAAAABCVzJXMJAARMAAAAAgIAAAAacXVpY2tTd2FwVXNlclNwZW50SW5QZXJpb2QJAARMAAAAAgkABCUAAAABBQAAAAt1c2VyQWRkcmVzcwUAAAADbmlsBQAAAANTRVABAAAAGmtleVVzZXJMYXN0UXVpY2tTd2FwSGVpZ2h0AAAAAQAAAAt1c2VyQWRkcmVzcwkABLkAAAACCQAETAAAAAICAAAABCVzJXMJAARMAAAAAgIAAAAXdXNlckxhc3RRdWlja1N3YXBIZWlnaHQJAARMAAAAAgkABCUAAAABBQAAAAt1c2VyQWRkcmVzcwUAAAADbmlsBQAAAANTRVABAAAADWtleURvcmEyUHJpY2UAAAABAAAABnN5bWJvbAkABLkAAAACCQAETAAAAAICAAAABCVzJXMJAARMAAAAAgIAAAAFcHJpY2UJAARMAAAAAgUAAAAGc3ltYm9sBQAAAANuaWwFAAAAA1NFUAEAAAASa2V5RG9yYTJMYXN0SGVpZ2h0AAAAAQAAAAZzeW1ib2wJAAS5AAAAAgkABEwAAAACAgAAAAQlcyVzCQAETAAAAAICAAAACmxhc3RIZWlnaHQJAARMAAAAAgUAAAAGc3ltYm9sBQAAAANuaWwFAAAAA1NFUAEAAAARbWluU3dhcEFtb3VudFJFQUQAAAABAAAACHN3YXBUeXBlCQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAABHRoaXMJAQAAABBtaW5Td2FwQW1vdW50S0VZAAAAAQUAAAAIc3dhcFR5cGUAAAAAAAAAAAABAAAAD3RvdGFsTG9ja2VkUkVBRAAAAAEAAAAIc3dhcFR5cGUJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQaAAAAAgUAAAAEdGhpcwkBAAAADnRvdGFsTG9ja2VkS0VZAAAAAQUAAAAIc3dhcFR5cGUAAAAAAAAAAAABAAAAFXRvdGFsTG9ja2VkQnlVc2VyUkVBRAAAAAIAAAAIc3dhcFR5cGUAAAAFb3duZXIJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQaAAAAAgUAAAAEdGhpcwkBAAAAFHRvdGFsTG9ja2VkQnlVc2VyS0VZAAAAAgUAAAAIc3dhcFR5cGUFAAAABW93bmVyAAAAAAAAAAAAAQAAABdiYWxhbmNlTG9ja0ludGVydmFsUkVBRAAAAAEAAAAIc3dhcFR5cGUJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQaAAAAAgUAAAAEdGhpcwkBAAAAFmJhbGFuY2VMb2NrSW50ZXJ2YWxLRVkAAAABBQAAAAhzd2FwVHlwZQUAAAAHbWF4UmFuZAEAAAAabWluQmFsYW5jZUxvY2tJbnRlcnZhbFJFQUQAAAABAAAACHN3YXBUeXBlCQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAABHRoaXMJAQAAABltaW5CYWxhbmNlTG9ja0ludGVydmFsS0VZAAAAAQUAAAAIc3dhcFR5cGUFAAAAB21pblJhbmQBAAAAG25vZGVCYWxhbmNlTG9ja0ludGVydmFsUkVBRAAAAAAJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQaAAAAAgUAAAAEdGhpcwkBAAAAGm5vZGVCYWxhbmNlTG9ja0ludGVydmFsS0VZAAAAAAAAAAAAAAAAAQEAAAAWY29udmVydE5ldXRyaW5vVG9XYXZlcwAAAAIAAAAGYW1vdW50AAAABXByaWNlCQAAawAAAAMJAABrAAAAAwUAAAAGYW1vdW50BQAAAAhQUklDRUxFVAUAAAAFcHJpY2UFAAAAB1dBVkVMRVQFAAAABVBBVUxJAQAAABZjb252ZXJ0V2F2ZXNUb05ldXRyaW5vAAAAAgAAAAZhbW91bnQAAAAFcHJpY2UJAABrAAAAAwkAAGsAAAADBQAAAAZhbW91bnQFAAAABXByaWNlBQAAAAhQUklDRUxFVAUAAAAFUEFVTEkFAAAAB1dBVkVMRVQBAAAAEmNvbnZlcnRXYXZlc1RvQm9uZAAAAAIAAAAGYW1vdW50AAAABXByaWNlCQEAAAAWY29udmVydFdhdmVzVG9OZXV0cmlubwAAAAIFAAAABmFtb3VudAUAAAAFcHJpY2UBAAAAFmNvbnZlcnRKc29uQXJyYXlUb0xpc3QAAAABAAAACWpzb25BcnJheQkABLUAAAACBQAAAAlqc29uQXJyYXkCAAAAASwBAAAAEW1pblN3YXBBbW91bnRGQUlMAAAAAgAAAAhzd2FwVHlwZQAAAA1taW5Td2FwQW1vdW50CQAAAgAAAAEJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAGFRoZSBzcGVjaWZpZWQgYW1vdW50IGluIAUAAAAIc3dhcFR5cGUCAAAAKyBzd2FwIGlzIGxlc3MgdGhhbiB0aGUgcmVxdWlyZWQgbWluaW11bSBvZiAJAAGkAAAAAQUAAAANbWluU3dhcEFtb3VudAEAAAAVZW1lcmdlbmN5U2h1dGRvd25GQUlMAAAAAAkAAAIAAAABAgAAAFpjb250cmFjdCBpcyBibG9ja2VkIGJ5IEVNRVJHRU5DWSBTSFVURE9XTiBhY3Rpb25zIHVudGlsbCByZWFjdGl2YXRpb24gYnkgZW1lcmdlbmN5IG9yYWNsZXMBAAAADnByaWNlSW5kZXhGQUlMAAAABQAAAAVpbmRleAAAAApwcmljZUluZGV4AAAAC2luZGV4SGVpZ2h0AAAADHVubG9ja0hlaWdodAAAAA9wcmV2SW5kZXhIZWlnaHQJAAACAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAjaW52YWxpZCBwcmljZSBoaXN0b3J5IGluZGV4OiBpbmRleD0JAAGkAAAAAQUAAAAFaW5kZXgCAAAADCBwcmljZUluZGV4PQkAAaQAAAABBQAAAApwcmljZUluZGV4AgAAAA0gaW5kZXhIZWlnaHQ9CQABpAAAAAEFAAAAC2luZGV4SGVpZ2h0AgAAAA4gdW5sb2NrSGVpZ2h0PQkAAaQAAAABBQAAAAx1bmxvY2tIZWlnaHQCAAAAESBwcmV2SW5kZXhIZWlnaHQ9CQABpAAAAAEFAAAAD3ByZXZJbmRleEhlaWdodAAAAAATbGlxdWlkYXRpb25Db250cmFjdAkBAAAADmdldFN0cmluZ0J5S2V5AAAAAQUAAAAWTGlxdWlkYXRpb25Db250cmFjdEtleQAAAAAPbmV1dHJpbm9Bc3NldElkCQACWQAAAAEJAQAAAA5nZXRTdHJpbmdCeUtleQAAAAEFAAAAEk5ldXRyaW5vQXNzZXRJZEtleQAAAAAPYXVjdGlvbkNvbnRyYWN0CQEAAAAOZ2V0U3RyaW5nQnlLZXkAAAABBQAAABJBdWN0aW9uQ29udHJhY3RLZXkAAAAAC3JwZENvbnRyYWN0CQEAAAAOZ2V0U3RyaW5nQnlLZXkAAAABBQAAAA5SUERDb250cmFjdEtleQAAAAAPY29udHJvbENvbnRyYWN0CQEAAAAOZ2V0U3RyaW5nQnlLZXkAAAABBQAAABJDb250cm9sQ29udHJhY3RLZXkAAAAACnByaWNlSW5kZXgJAQAAABhnZXROdW1iZXJCeUFkZHJlc3NBbmRLZXkAAAACBQAAAA9jb250cm9sQ29udHJhY3QFAAAADVByaWNlSW5kZXhLZXkAAAAACWlzQmxvY2tlZAkBAAAAFmdldEJvb2xCeUFkZHJlc3NBbmRLZXkAAAACBQAAAA9jb250cm9sQ29udHJhY3QFAAAADElzQmxvY2tlZEtleQAAAAAYbm9kZU9yYWNsZVByb3ZpZGVyUHViS2V5CQACWQAAAAEJAQAAAA5nZXRTdHJpbmdCeUtleQAAAAEFAAAAG05vZGVPcmFjbGVQcm92aWRlclB1YktleUtleQAAAAALYm9uZEFzc2V0SWQJAAJZAAAAAQIAAAAsQkdoUFlxdVhTSzZVWWpuUExFbjk0Z0ZoZXRwNEp2Zjd0b2VrRVk0eDFWREgAAAAAFWRlcHJlY2F0ZWRCb25kQXNzZXRJZAkAAlkAAAABAgAAACw5NzVha1pCZm5NajUxM1U3TVphSEt6UXJtc0V4NWFFM3dkV0tUckhCaGJqRgAAAAAGcnNhUHViCQACWwAAAAEJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABB0AAAACBQAAAAR0aGlzBQAAABJSc2FSYW5kUHVibGljNThLZXkCAAAAJVJTQSBwdWJsaWMga2V5IGhhcyBub3QgYmVlbiBzcGVjaWZpZWQAAAAAEG5ldXRyaW5vQ29udHJhY3QFAAAABHRoaXMAAAAADGN1cnJlbnRQcmljZQkBAAAAGGdldE51bWJlckJ5QWRkcmVzc0FuZEtleQAAAAIFAAAAD2NvbnRyb2xDb250cmFjdAUAAAAIUHJpY2VLZXkAAAAAFW5ldXRyaW5vTG9ja2VkQmFsYW5jZQkBAAAAD3RvdGFsTG9ja2VkUkVBRAAAAAECAAAACG5ldXRyaW5vAAAAABJ3YXZlc0xvY2tlZEJhbGFuY2UJAQAAAA90b3RhbExvY2tlZFJFQUQAAAABAgAAAAV3YXZlcwAAAAAHcmVzZXJ2ZQkAAGUAAAACCAkAA+8AAAABBQAAABBuZXV0cmlub0NvbnRyYWN0AAAAB3JlZ3VsYXIFAAAAEndhdmVzTG9ja2VkQmFsYW5jZQAAAAAObmV1dHJpbm9TdXBwbHkJAABlAAAAAgkAAGUAAAACCQAAZAAAAAIFAAAAFW5ldXRyaW5vTG9ja2VkQmFsYW5jZQgJAQAAAAV2YWx1ZQAAAAEJAAPsAAAAAQUAAAAPbmV1dHJpbm9Bc3NldElkAAAACHF1YW50aXR5CQAD8AAAAAIFAAAAEG5ldXRyaW5vQ29udHJhY3QFAAAAD25ldXRyaW5vQXNzZXRJZAkAA/AAAAACCQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABBQAAABNsaXF1aWRhdGlvbkNvbnRyYWN0BQAAAA9uZXV0cmlub0Fzc2V0SWQAAAAAB3N1cnBsdXMJAABlAAAAAgkBAAAAFmNvbnZlcnRXYXZlc1RvTmV1dHJpbm8AAAACBQAAAAdyZXNlcnZlBQAAAAxjdXJyZW50UHJpY2UFAAAADm5ldXRyaW5vU3VwcGx5AAAAAAdkZWZpY2l0CQAAZQAAAAIFAAAADm5ldXRyaW5vU3VwcGx5CQEAAAAWY29udmVydFdhdmVzVG9OZXV0cmlubwAAAAIFAAAAB3Jlc2VydmUFAAAADGN1cnJlbnRQcmljZQEAAAAbY2hlY2tJc1ZhbGlkTWluU3BvbnNvcmVkRmVlAAAAAQAAAAJ0eAQAAAAOTUlOVFJBTlNGRVJGRUUAAAAAAAABhqAEAAAAFlNwb25zb3JlZEZlZVVwcGVyQm91bmQAAAAAAAAAA+gEAAAAD3JlYWxOZXV0cmlub0ZlZQkBAAAAFmNvbnZlcnRXYXZlc1RvTmV1dHJpbm8AAAACBQAAAA5NSU5UUkFOU0ZFUkZFRQUAAAAMY3VycmVudFByaWNlBAAAAA5taW5OZXV0cmlub0ZlZQkAAGgAAAACBQAAAA9yZWFsTmV1dHJpbm9GZWUAAAAAAAAAAAIEAAAADm1heE5ldXRyaW5vRmVlCQAAawAAAAMFAAAAD3JlYWxOZXV0cmlub0ZlZQUAAAAWU3BvbnNvcmVkRmVlVXBwZXJCb3VuZAAAAAAAAAAAZAQAAAAIaW5wdXRGZWUJAQAAAAV2YWx1ZQAAAAEIBQAAAAJ0eAAAABRtaW5TcG9uc29yZWRBc3NldEZlZQMDCQAAZwAAAAIFAAAACGlucHV0RmVlBQAAAA5taW5OZXV0cmlub0ZlZQkAAGcAAAACBQAAAA5tYXhOZXV0cmlub0ZlZQUAAAAIaW5wdXRGZWUHCQAAAAAAAAIIBQAAAAJ0eAAAAAdhc3NldElkBQAAAA9uZXV0cmlub0Fzc2V0SWQHAQAAAA9nZXRQcmljZUhpc3RvcnkAAAABAAAABWJsb2NrCQEAAAAYZ2V0TnVtYmVyQnlBZGRyZXNzQW5kS2V5AAAAAgUAAAAPY29udHJvbENvbnRyYWN0CQEAAAASZ2V0UHJpY2VIaXN0b3J5S2V5AAAAAQUAAAAFYmxvY2sBAAAAFWdldEhlaWdodFByaWNlQnlJbmRleAAAAAEAAAAFaW5kZXgJAQAAABhnZXROdW1iZXJCeUFkZHJlc3NBbmRLZXkAAAACBQAAAA9jb250cm9sQ29udHJhY3QJAQAAABhnZXRIZWlnaHRQcmljZUJ5SW5kZXhLZXkAAAABBQAAAAVpbmRleAAAAAAMc0lkeFN3YXBUeXBlAAAAAAAAAAABAAAAAApzSWR4U3RhdHVzAAAAAAAAAAACAAAAAAxzSWR4SW5BbW91bnQAAAAAAAAAAAMAAAAACXNJZHhQcmljZQAAAAAAAAAABAAAAAAQc0lkeE91dE5ldEFtb3VudAAAAAAAAAAABQAAAAAQc0lkeE91dEZlZUFtb3VudAAAAAAAAAAABgAAAAAPc0lkeFN0YXJ0SGVpZ2h0AAAAAAAAAAAHAAAAABJzSWR4U3RhcnRUaW1lc3RhbXAAAAAAAAAAAAgAAAAADXNJZHhFbmRIZWlnaHQAAAAAAAAAAAkAAAAAEHNJZHhFbmRUaW1lc3RhbXAAAAAAAAAAAAoAAAAAFHNJZHhTZWxmVW5sb2NrSGVpZ2h0AAAAAAAAAAALAAAAABRzSWR4UmFuZFVubG9ja0hlaWdodAAAAAAAAAAADAAAAAAJc0lkeEluZGV4AAAAAAAAAAANAAAAABBzSWR4V2l0aGRyYXdUeElkAAAAAAAAAAAOAAAAAAtzSWR4TWluUmFuZAAAAAAAAAAADwAAAAALc0lkeE1heFJhbmQAAAAAAAAAABAAAAAAC3NJZHhJc1F1aWNrAAAAAAAAAAARAQAAAAdzd2FwS0VZAAAAAgAAAAt1c2VyQWRkcmVzcwAAAAR0eElkCQAEuQAAAAIJAARMAAAAAgIAAAAEJXMlcwkABEwAAAACBQAAAAt1c2VyQWRkcmVzcwkABEwAAAACBQAAAAR0eElkBQAAAANuaWwFAAAAA1NFUAEAAAALc3RyU3dhcERBVEEAAAARAAAACHN3YXBUeXBlAAAABnN0YXR1cwAAAAhpbkFtb3VudAAAAAVwcmljZQAAAAxvdXROZXRBbW91bnQAAAAMb3V0RmVlQW1vdW50AAAAC3N0YXJ0SGVpZ2h0AAAADnN0YXJ0VGltZXN0YW1wAAAACWVuZEhlaWdodAAAAAxlbmRUaW1lc3RhbXAAAAAQc2VsZlVubG9ja0hlaWdodAAAABByYW5kVW5sb2NrSGVpZ2h0AAAABWluZGV4AAAADHdpdGhkcmF3VHhJZAAAAAdyYW5kTWluAAAAB3JhbmRNYXgAAAAHaXNRdWljawkABLkAAAACCQAETAAAAAICAAAAHCVzJXMlZCVkJWQlZCVkJWQlZCVkJWQlZCVkJXMJAARMAAAAAgUAAAAIc3dhcFR5cGUJAARMAAAAAgUAAAAGc3RhdHVzCQAETAAAAAIFAAAACGluQW1vdW50CQAETAAAAAIFAAAABXByaWNlCQAETAAAAAIFAAAADG91dE5ldEFtb3VudAkABEwAAAACBQAAAAxvdXRGZWVBbW91bnQJAARMAAAAAgUAAAALc3RhcnRIZWlnaHQJAARMAAAAAgUAAAAOc3RhcnRUaW1lc3RhbXAJAARMAAAAAgUAAAAJZW5kSGVpZ2h0CQAETAAAAAIFAAAADGVuZFRpbWVzdGFtcAkABEwAAAACBQAAABBzZWxmVW5sb2NrSGVpZ2h0CQAETAAAAAIFAAAAEHJhbmRVbmxvY2tIZWlnaHQJAARMAAAAAgUAAAAFaW5kZXgJAARMAAAAAgUAAAAMd2l0aGRyYXdUeElkCQAETAAAAAIFAAAAB3JhbmRNaW4JAARMAAAAAgUAAAAHcmFuZE1heAkABEwAAAACBQAAAAdpc1F1aWNrBQAAAANuaWwFAAAAA1NFUAEAAAAPcGVuZGluZ1N3YXBEQVRBAAAAAwAAAAhzd2FwVHlwZQAAAA1pbkFzc2V0QW1vdW50AAAAEHNlbGZVbmxvY2tIZWlnaHQJAQAAAAtzdHJTd2FwREFUQQAAABEFAAAACHN3YXBUeXBlAgAAAAdQRU5ESU5HCQABpAAAAAEFAAAADWluQXNzZXRBbW91bnQCAAAAATACAAAAATACAAAAATAJAAGkAAAAAQUAAAAGaGVpZ2h0CQABpAAAAAEIBQAAAAlsYXN0QmxvY2sAAAAJdGltZXN0YW1wAgAAAAEwAgAAAAEwCQABpAAAAAEFAAAAEHNlbGZVbmxvY2tIZWlnaHQCAAAAATACAAAAATACAAAABE5VTEwJAAGkAAAAAQkBAAAAGm1pbkJhbGFuY2VMb2NrSW50ZXJ2YWxSRUFEAAAAAQUAAAAIc3dhcFR5cGUJAAGkAAAAAQkBAAAAF2JhbGFuY2VMb2NrSW50ZXJ2YWxSRUFEAAAAAQUAAAAIc3dhcFR5cGUJAAGlAAAAAQcBAAAAEmFjY2VsZXJhdGVTd2FwREFUQQAAAAEAAAAJZGF0YUFycmF5CQEAAAALc3RyU3dhcERBVEEAAAARCQABkQAAAAIFAAAACWRhdGFBcnJheQUAAAAMc0lkeFN3YXBUeXBlCQABkQAAAAIFAAAACWRhdGFBcnJheQUAAAAKc0lkeFN0YXR1cwkAAZEAAAACBQAAAAlkYXRhQXJyYXkFAAAADHNJZHhJbkFtb3VudAkAAZEAAAACBQAAAAlkYXRhQXJyYXkFAAAACXNJZHhQcmljZQkAAZEAAAACBQAAAAlkYXRhQXJyYXkFAAAAEHNJZHhPdXROZXRBbW91bnQJAAGRAAAAAgUAAAAJZGF0YUFycmF5BQAAABBzSWR4T3V0RmVlQW1vdW50CQABkQAAAAIFAAAACWRhdGFBcnJheQUAAAAPc0lkeFN0YXJ0SGVpZ2h0CQABkQAAAAIFAAAACWRhdGFBcnJheQUAAAASc0lkeFN0YXJ0VGltZXN0YW1wCQABkQAAAAIFAAAACWRhdGFBcnJheQUAAAANc0lkeEVuZEhlaWdodAkAAZEAAAACBQAAAAlkYXRhQXJyYXkFAAAAEHNJZHhFbmRUaW1lc3RhbXAJAAGRAAAAAgUAAAAJZGF0YUFycmF5BQAAABRzSWR4U2VsZlVubG9ja0hlaWdodAkAAZEAAAACBQAAAAlkYXRhQXJyYXkFAAAAFHNJZHhSYW5kVW5sb2NrSGVpZ2h0CQABkQAAAAIFAAAACWRhdGFBcnJheQUAAAAJc0lkeEluZGV4CQABkQAAAAIFAAAACWRhdGFBcnJheQUAAAAQc0lkeFdpdGhkcmF3VHhJZAkAAZEAAAACBQAAAAlkYXRhQXJyYXkFAAAAC3NJZHhNaW5SYW5kCQABkQAAAAIFAAAACWRhdGFBcnJheQUAAAALc0lkeE1heFJhbmQJAAGlAAAAAQYBAAAADmZpbmlzaFN3YXBEQVRBAAAABwAAAAlkYXRhQXJyYXkAAAAFcHJpY2UAAAAMb3V0TmV0QW1vdW50AAAADG91dEZlZUFtb3VudAAAABByYW5kVW5sb2NrSGVpZ2h0AAAABWluZGV4AAAADHdpdGhkcmF3VHhJZAkBAAAAC3N0clN3YXBEQVRBAAAAEQkAAZEAAAACBQAAAAlkYXRhQXJyYXkFAAAADHNJZHhTd2FwVHlwZQIAAAAIRklOSVNIRUQJAAGRAAAAAgUAAAAJZGF0YUFycmF5BQAAAAxzSWR4SW5BbW91bnQJAAGkAAAAAQUAAAAFcHJpY2UJAAGkAAAAAQUAAAAMb3V0TmV0QW1vdW50CQABpAAAAAEFAAAADG91dEZlZUFtb3VudAkAAZEAAAACBQAAAAlkYXRhQXJyYXkFAAAAD3NJZHhTdGFydEhlaWdodAkAAZEAAAACBQAAAAlkYXRhQXJyYXkFAAAAEnNJZHhTdGFydFRpbWVzdGFtcAkAAaQAAAABBQAAAAZoZWlnaHQJAAGkAAAAAQgFAAAACWxhc3RCbG9jawAAAAl0aW1lc3RhbXAJAAGRAAAAAgUAAAAJZGF0YUFycmF5BQAAABRzSWR4U2VsZlVubG9ja0hlaWdodAkAAaQAAAABBQAAABByYW5kVW5sb2NrSGVpZ2h0CQABpAAAAAEFAAAABWluZGV4BQAAAAx3aXRoZHJhd1R4SWQJAAGRAAAAAgUAAAAJZGF0YUFycmF5BQAAAAtzSWR4TWluUmFuZAkAAZEAAAACBQAAAAlkYXRhQXJyYXkFAAAAC3NJZHhNYXhSYW5kCQABkQAAAAIFAAAACWRhdGFBcnJheQUAAAALc0lkeElzUXVpY2sBAAAAEnN3YXBEYXRhRmFpbE9yUkVBRAAAAAIAAAALdXNlckFkZHJlc3MAAAAIc3dhcFR4SWQEAAAAB3N3YXBLZXkJAQAAAAdzd2FwS0VZAAAAAgUAAAALdXNlckFkZHJlc3MFAAAACHN3YXBUeElkCQAEtQAAAAIJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABB0AAAACBQAAAAR0aGlzBQAAAAdzd2FwS2V5CQABLAAAAAICAAAAEW5vIHN3YXAgZGF0YSBmb3IgBQAAAAdzd2FwS2V5BQAAAANTRVABAAAACWFwcGx5RmVlcwAAAAIAAAALYW1vdW50R3Jvc3MAAAAHZmVlUGFydAQAAAAJZmVlQW1vdW50CQAAawAAAAMFAAAAC2Ftb3VudEdyb3NzBQAAAAdmZWVQYXJ0BQAAAAVQQVVMSQkABEwAAAACCQAAZQAAAAIFAAAAC2Ftb3VudEdyb3NzBQAAAAlmZWVBbW91bnQJAARMAAAAAgUAAAAJZmVlQW1vdW50CQAETAAAAAIFAAAAC2Ftb3VudEdyb3NzBQAAAANuaWwBAAAAFnJhbmRVbmxvY2tIZWlnaHRPckZhaWwAAAAFAAAABHR4SWQAAAAGcnNhU2lnAAAACHN3YXBUeXBlAAAAC3N0YXJ0SGVpZ2h0AAAAEG1pbk1heFJhbmRzVHVwbGUEAAAACmlzUnNhVmFsaWQJAAooAAAABAUAAAAGU0hBMjU2CQABmwAAAAEFAAAABHR4SWQFAAAABnJzYVNpZwUAAAAGcnNhUHViAwkBAAAAASEAAAABBQAAAAppc1JzYVZhbGlkCQAAAgAAAAECAAAAFWludmFsaWQgUlNBIHNpZ25hdHVyZQQAAAAWbWluQmFsYW5jZUxvY2tJbnRlcnZhbAgFAAAAEG1pbk1heFJhbmRzVHVwbGUAAAACXzEEAAAAFm1heEJhbGFuY2VMb2NrSW50ZXJ2YWwIBQAAABBtaW5NYXhSYW5kc1R1cGxlAAAAAl8yBAAAAARyYW5kCQAAagAAAAIJAASxAAAAAQkAC1QAAAABBQAAAAZyc2FTaWcJAABlAAAAAgUAAAAWbWF4QmFsYW5jZUxvY2tJbnRlcnZhbAUAAAAWbWluQmFsYW5jZUxvY2tJbnRlcnZhbAQAAAAQcmFuZExvY2tJbnRlcnZhbAkAAGQAAAACBQAAABZtaW5CYWxhbmNlTG9ja0ludGVydmFsAwkAAGYAAAACAAAAAAAAAAAABQAAAARyYW5kCQEAAAABLQAAAAEFAAAABHJhbmQFAAAABHJhbmQJAABkAAAAAgUAAAALc3RhcnRIZWlnaHQFAAAAEHJhbmRMb2NrSW50ZXJ2YWwBAAAAA2FicwAAAAEAAAABeAMJAABmAAAAAgAAAAAAAAAAAAUAAAABeAkBAAAAAS0AAAABBQAAAAF4BQAAAAF4AQAAAApzZWxlY3ROb2RlAAAAAQAAAA11bmxlYXNlQW1vdW50BAAAAA1hbW91bnRUb0xlYXNlCQAAZQAAAAIJAABlAAAAAggJAAPvAAAAAQUAAAAQbmV1dHJpbm9Db250cmFjdAAAAAlhdmFpbGFibGUFAAAADXVubGVhc2VBbW91bnQJAQAAAB9nZXRSZXNlcnZlZEFtb3VudEZvclNwb25zb3JzaGlwAAAAAAQAAAAKb2xkTGVhc2VkMAkBAAAADmdldE51bWJlckJ5S2V5AAAAAQkBAAAAEWdldExlYXNlQW1vdW50S2V5AAAAAQAAAAAAAAAAAAQAAAAKb2xkTGVhc2VkMQkBAAAADmdldE51bWJlckJ5S2V5AAAAAQkBAAAAEWdldExlYXNlQW1vdW50S2V5AAAAAQAAAAAAAAAAAQQAAAAKbmV3TGVhc2VkMAkAAGQAAAACBQAAAA1hbW91bnRUb0xlYXNlBQAAAApvbGRMZWFzZWQwBAAAAApuZXdMZWFzZWQxCQAAZAAAAAIFAAAADWFtb3VudFRvTGVhc2UFAAAACm9sZExlYXNlZDEDAwkAAGYAAAACBQAAAApuZXdMZWFzZWQwAAAAAAAAAAAABgkAAGYAAAACBQAAAApuZXdMZWFzZWQxAAAAAAAAAAAABAAAAAZkZWx0YTAJAQAAAANhYnMAAAABCQAAZQAAAAIFAAAACm5ld0xlYXNlZDAFAAAACm9sZExlYXNlZDEEAAAABmRlbHRhMQkBAAAAA2FicwAAAAEJAABlAAAAAgUAAAAKbmV3TGVhc2VkMQUAAAAKb2xkTGVhc2VkMAMJAABnAAAAAgUAAAAGZGVsdGExBQAAAAZkZWx0YTAJAAUUAAAAAgAAAAAAAAAAAAUAAAAKbmV3TGVhc2VkMAkABRQAAAACAAAAAAAAAAABBQAAAApuZXdMZWFzZWQxCQAFFAAAAAIA//////////8AAAAAAAAAAAABAAAAFnByZXBhcmVVbmxlYXNlQW5kTGVhc2UAAAABAAAADXVubGVhc2VBbW91bnQEAAAADSR0MDE2MjEyMTYzMDAJAQAAAApzZWxlY3ROb2RlAAAAAQUAAAANdW5sZWFzZUFtb3VudAQAAAAJbm9kZUluZGV4CAUAAAANJHQwMTYyMTIxNjMwMAAAAAJfMQQAAAAObmV3TGVhc2VBbW91bnQIBQAAAA0kdDAxNjIxMjE2MzAwAAAAAl8yAwkAAGYAAAACBQAAAA5uZXdMZWFzZUFtb3VudAAAAAAAAAAAAAQAAAAKbGVhc2VJZEtleQkBAAAADWdldExlYXNlSWRLZXkAAAABBQAAAAlub2RlSW5kZXgEAAAACG9sZExlYXNlCQAEHAAAAAIFAAAABHRoaXMFAAAACmxlYXNlSWRLZXkEAAAADnVubGVhc2VPckVtcHR5AwkBAAAACWlzRGVmaW5lZAAAAAEFAAAACG9sZExlYXNlCQAETAAAAAIJAQAAAAtMZWFzZUNhbmNlbAAAAAEJAQAAAAV2YWx1ZQAAAAEFAAAACG9sZExlYXNlBQAAAANuaWwFAAAAA25pbAQAAAAObGVhc2VBbW91bnRLZXkJAQAAABFnZXRMZWFzZUFtb3VudEtleQAAAAEFAAAACW5vZGVJbmRleAQAAAAFbGVhc2UJAAREAAAAAgkBAAAAHGdldFN0YWtpbmdOb2RlQWRkcmVzc0J5SW5kZXgAAAABBQAAAAlub2RlSW5kZXgFAAAADm5ld0xlYXNlQW1vdW50CQAETgAAAAIFAAAADnVubGVhc2VPckVtcHR5CQAETAAAAAIFAAAABWxlYXNlCQAETAAAAAIJAQAAAAtCaW5hcnlFbnRyeQAAAAIFAAAACmxlYXNlSWRLZXkJAAQ5AAAAAQUAAAAFbGVhc2UJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAABFnZXRMZWFzZUFtb3VudEtleQAAAAEFAAAACW5vZGVJbmRleAUAAAAObmV3TGVhc2VBbW91bnQFAAAAA25pbAUAAAADbmlsAQAAABBnZXREb3JhMk5TQlRJbmZvAAAAAAQAAAANZG9yYTJDb250cmFjdAkBAAAAEUBleHRyTmF0aXZlKDEwNjIpAAAAAQkBAAAAEUBleHRyTmF0aXZlKDEwNTMpAAAAAgUAAAAEdGhpcwUAAAAQa2V5RG9yYTJDb250cmFjdAkABRQAAAACCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAANZG9yYTJDb250cmFjdAkBAAAADWtleURvcmEyUHJpY2UAAAABBQAAAA9kb3JhMk5zYnRTeW1ib2wCAAAAF05TQlQgcHJpY2UgaXMgdW5kZWZpbmVkCQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAADWRvcmEyQ29udHJhY3QJAQAAABJrZXlEb3JhMkxhc3RIZWlnaHQAAAABBQAAAA9kb3JhMk5zYnRTeW1ib2wAAAAAAAAAAAABAAAACHRoaXNPbmx5AAAAAQAAAAFpAwkBAAAAAiE9AAAAAggFAAAAAWkAAAAGY2FsbGVyBQAAAAR0aGlzCQAAAgAAAAECAAAALVBlcm1pc3Npb24gZGVuaWVkOiB0aGlzIGNvbnRyYWN0IG9ubHkgYWxsb3dlZAYAAAANAAAAAWkBAAAAHXByZXBhcmVVbmxlYXNlQW5kTGVhc2VXcmFwcGVyAAAAAQAAAA11bmxlYXNlQW1vdW50BAAAAAtjaGVja0NhbGxlcgkABEwAAAACCQEAAAAIdGhpc09ubHkAAAABBQAAAAFpBQAAAANuaWwDCQAAAAAAAAIFAAAAC2NoZWNrQ2FsbGVyBQAAAAtjaGVja0NhbGxlcgkBAAAAFnByZXBhcmVVbmxlYXNlQW5kTGVhc2UAAAABBQAAAA11bmxlYXNlQW1vdW50CQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgAAAAFpAQAAAAtjb25zdHJ1Y3RvcgAAAA4AAAASbmV1dHJpbm9Bc3NldElkUHJtAAAADmJvbmRBc3NldElkUHJtAAAAEmF1Y3Rpb25Db250cmFjdFBybQAAABZsaXF1aWRhdGlvbkNvbnRyYWN0UHJtAAAADnJwZENvbnRyYWN0UHJtAAAAEmNvbnRyb2xDb250cmFjdFBybQAAABtub2RlT3JhY2xlUHJvdmlkZXJQdWJLZXlQcm0AAAATcnNhUmFuZFB1YmxpY0tleVBybQAAABtiYWxhbmNlV2F2ZXNMb2NrSW50ZXJ2YWxQcm0AAAAeYmFsYW5jZU5ldXRyaW5vTG9ja0ludGVydmFsUHJtAAAAFW1pbldhdmVzU3dhcEFtb3VudFBybQAAABhtaW5OZXV0cmlub1N3YXBBbW91bnRQcm0AAAAVbmV1dHJpbm9PdXRGZWVQYXJ0UHJtAAAAEndhdmVzT3V0RmVlUGFydFBybQQAAAALY2hlY2tDYWxsZXIJAQAAAAh0aGlzT25seQAAAAEFAAAAAWkDCQAAAAAAAAIFAAAAC2NoZWNrQ2FsbGVyBQAAAAtjaGVja0NhbGxlcgkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAABJOZXV0cmlub0Fzc2V0SWRLZXkFAAAAEm5ldXRyaW5vQXNzZXRJZFBybQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAAA5Cb25kQXNzZXRJZEtleQUAAAAOYm9uZEFzc2V0SWRQcm0JAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAASQXVjdGlvbkNvbnRyYWN0S2V5BQAAABJhdWN0aW9uQ29udHJhY3RQcm0JAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAAWTGlxdWlkYXRpb25Db250cmFjdEtleQUAAAAWbGlxdWlkYXRpb25Db250cmFjdFBybQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAAA5SUERDb250cmFjdEtleQUAAAAOcnBkQ29udHJhY3RQcm0JAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAASQ29udHJvbENvbnRyYWN0S2V5BQAAABJjb250cm9sQ29udHJhY3RQcm0JAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAAbTm9kZU9yYWNsZVByb3ZpZGVyUHViS2V5S2V5BQAAABtub2RlT3JhY2xlUHJvdmlkZXJQdWJLZXlQcm0JAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAASUnNhUmFuZFB1YmxpYzU4S2V5BQAAABNyc2FSYW5kUHVibGljS2V5UHJtCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABtCYWxhbmNlV2F2ZXNMb2NrSW50ZXJ2YWxLZXkFAAAAG2JhbGFuY2VXYXZlc0xvY2tJbnRlcnZhbFBybQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAeQmFsYW5jZU5ldXRyaW5vTG9ja0ludGVydmFsS2V5BQAAAB5iYWxhbmNlTmV1dHJpbm9Mb2NrSW50ZXJ2YWxQcm0JAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAFU1pbldhdmVzU3dhcEFtb3VudEtleQUAAAAVbWluV2F2ZXNTd2FwQW1vdW50UHJtCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABhNaW5OZXV0cmlub1N3YXBBbW91bnRLZXkFAAAAGG1pbk5ldXRyaW5vU3dhcEFtb3VudFBybQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAVTmV1dHJpbm9PdXRGZWVQYXJ0S2V5BQAAABVuZXV0cmlub091dEZlZVBhcnRQcm0JAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAEldhdmVzT3V0RmVlUGFydEtleQUAAAASd2F2ZXNPdXRGZWVQYXJ0UHJtBQAAAANuaWwJAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAAAAAWkBAAAADWNvbnN0cnVjdG9yVjIAAAAGAAAADWdOc2J0Q29udHJhY3QAAAAQbnNidExvY2tDb250cmFjdAAAAA1kb3JhMkNvbnRyYWN0AAAADnF1aWNrU3dhcERlbGF5AAAAFnF1aWNrU3dhcExpbWl0RHVyYXRpb24AAAAUZG9yYTJMYXN0SGVpZ2h0TGltaXQEAAAAC2NoZWNrQ2FsbGVyCQEAAAAIdGhpc09ubHkAAAABBQAAAAFpAwkAAAAAAAACBQAAAAtjaGVja0NhbGxlcgUAAAALY2hlY2tDYWxsZXIJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAAQa2V5R05zYnRDb250cmFjdAUAAAANZ05zYnRDb250cmFjdAkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAABNrZXlOc2J0TG9ja0NvbnRyYWN0BQAAABBuc2J0TG9ja0NvbnRyYWN0CQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAAEGtleURvcmEyQ29udHJhY3QFAAAADWRvcmEyQ29udHJhY3QJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAEWtleVF1aWNrU3dhcERlbGF5BQAAAA5xdWlja1N3YXBEZWxheQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAZa2V5UXVpY2tTd2FwTGltaXREdXJhdGlvbgUAAAAWcXVpY2tTd2FwTGltaXREdXJhdGlvbgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAXa2V5RG9yYTJMYXN0SGVpZ2h0TGltaXQFAAAAFGRvcmEyTGFzdEhlaWdodExpbWl0BQAAAANuaWwJAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAAAAAWkBAAAACmNvbW1vblN3YXAAAAAEAAAACHN3YXBUeXBlAAAABmFtb3VudAAAAAdhY2NvdW50AAAABHR4SWQEAAAAC2NoZWNrQ2FsbGVyCQEAAAAIdGhpc09ubHkAAAABBQAAAAFpAwkAAAAAAAACBQAAAAtjaGVja0NhbGxlcgUAAAALY2hlY2tDYWxsZXIEAAAADW1pblN3YXBBbW91bnQJAQAAABFtaW5Td2FwQW1vdW50UkVBRAAAAAEFAAAACHN3YXBUeXBlBAAAAAt0b3RhbExvY2tlZAkBAAAAD3RvdGFsTG9ja2VkUkVBRAAAAAEFAAAACHN3YXBUeXBlBAAAABF0b3RhbExvY2tlZEJ5VXNlcgkBAAAAFXRvdGFsTG9ja2VkQnlVc2VyUkVBRAAAAAIFAAAACHN3YXBUeXBlBQAAAAdhY2NvdW50BAAAAAtub2RlQWRkcmVzcwkBAAAAFWdldFN0YWtpbmdOb2RlQnlJbmRleAAAAAEAAAAAAAAAAAAEAAAAFmJhbGFuY2VMb2NrTWF4SW50ZXJ2YWwDCQAAAAAAAAIFAAAAC25vZGVBZGRyZXNzBQAAAAdhY2NvdW50CQEAAAAbbm9kZUJhbGFuY2VMb2NrSW50ZXJ2YWxSRUFEAAAAAAkBAAAAF2JhbGFuY2VMb2NrSW50ZXJ2YWxSRUFEAAAAAQUAAAAIc3dhcFR5cGUEAAAAEHNlbGZVbmxvY2tIZWlnaHQJAABkAAAAAgUAAAAGaGVpZ2h0BQAAABZiYWxhbmNlTG9ja01heEludGVydmFsAwkAAGYAAAACBQAAAA1taW5Td2FwQW1vdW50BQAAAAZhbW91bnQJAQAAABFtaW5Td2FwQW1vdW50RkFJTAAAAAIFAAAACHN3YXBUeXBlBQAAAA1taW5Td2FwQW1vdW50AwUAAAAJaXNCbG9ja2VkCQEAAAAVZW1lcmdlbmN5U2h1dGRvd25GQUlMAAAAAAQAAAAJbGVhc2VQYXJ0AwkAAAAAAAACBQAAAAhzd2FwVHlwZQIAAAAFd2F2ZXMJAQAAABZwcmVwYXJlVW5sZWFzZUFuZExlYXNlAAAAAQAAAAAAAAAAAAUAAAADbmlsCQAETgAAAAIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAABR0b3RhbExvY2tlZEJ5VXNlcktFWQAAAAIFAAAACHN3YXBUeXBlBQAAAAdhY2NvdW50CQAAZAAAAAIFAAAAEXRvdGFsTG9ja2VkQnlVc2VyBQAAAAZhbW91bnQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAABhnZXRCYWxhbmNlVW5sb2NrQmxvY2tLZXkAAAABBQAAAAdhY2NvdW50BQAAABBzZWxmVW5sb2NrSGVpZ2h0CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAAOdG90YWxMb2NrZWRLRVkAAAABBQAAAAhzd2FwVHlwZQkAAGQAAAACBQAAAAt0b3RhbExvY2tlZAUAAAAGYW1vdW50CQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAAAdzd2FwS0VZAAAAAgUAAAAHYWNjb3VudAUAAAAEdHhJZAkBAAAAD3BlbmRpbmdTd2FwREFUQQAAAAMFAAAACHN3YXBUeXBlBQAAAAZhbW91bnQFAAAAEHNlbGZVbmxvY2tIZWlnaHQFAAAAA25pbAUAAAAJbGVhc2VQYXJ0CQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgAAAAFpAQAAAA5jb21tb25XaXRoZHJhdwAAAAQAAAAHYWNjb3VudAAAAAVpbmRleAAAAAhzd2FwVHhJZAAAAAZyc2FTaWcEAAAAC3VzZXJBZGRyZXNzCQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABBQAAAAdhY2NvdW50BAAAAAtjaGVja0NhbGxlcgkBAAAACHRoaXNPbmx5AAAAAQUAAAABaQMJAAAAAAAAAgUAAAALY2hlY2tDYWxsZXIFAAAAC2NoZWNrQ2FsbGVyBAAAAAlkYXRhQXJyYXkJAQAAABJzd2FwRGF0YUZhaWxPclJFQUQAAAACBQAAAAdhY2NvdW50BQAAAAhzd2FwVHhJZAQAAAAQc2VsZlVubG9ja0hlaWdodAkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAACWRhdGFBcnJheQUAAAAUc0lkeFNlbGZVbmxvY2tIZWlnaHQEAAAACHN3YXBUeXBlCQABkQAAAAIFAAAACWRhdGFBcnJheQUAAAAMc0lkeFN3YXBUeXBlBAAAAAhpbkFtb3VudAkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAACWRhdGFBcnJheQUAAAAMc0lkeEluQW1vdW50BAAAAApzd2FwU3RhdHVzCQABkQAAAAIFAAAACWRhdGFBcnJheQUAAAAKc0lkeFN0YXR1cwQAAAALc3RhcnRIZWlnaHQJAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAAAlkYXRhQXJyYXkFAAAAD3NJZHhTdGFydEhlaWdodAQAAAAHaXNRdWljawkAAAAAAAACCQABkQAAAAIFAAAACWRhdGFBcnJheQUAAAALc0lkeElzUXVpY2sCAAAABHRydWUEAAAADWNoZWNrU3dhcFR5cGUDAwkBAAAAAiE9AAAAAgUAAAAIc3dhcFR5cGUCAAAABXdhdmVzCQEAAAACIT0AAAACBQAAAAhzd2FwVHlwZQIAAAAIbmV1dHJpbm8HCQAAAgAAAAEJAAEsAAAAAgIAAAAWVW5zdXBwb3J0ZWQgc3dhcCB0eXBlIAUAAAAIc3dhcFR5cGUGAwkAAAAAAAACBQAAAA1jaGVja1N3YXBUeXBlBQAAAA1jaGVja1N3YXBUeXBlBAAAAApvdXRGZWVQYXJ0CQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAABHRoaXMJAQAAAA1vdXRGZWVQYXJ0S0VZAAAAAQUAAAAIc3dhcFR5cGUFAAAADkRFRkFVTFRTV0FQRkVFBAAAAAt0b3RhbExvY2tlZAkBAAAAD3RvdGFsTG9ja2VkUkVBRAAAAAEFAAAACHN3YXBUeXBlBAAAABF0b3RhbExvY2tlZEJ5VXNlcgkBAAAAFXRvdGFsTG9ja2VkQnlVc2VyUkVBRAAAAAIFAAAACHN3YXBUeXBlBQAAAAdhY2NvdW50BAAAAAx1bmxvY2tIZWlnaHQDBQAAAAdpc1F1aWNrCQAAZAAAAAIFAAAAC3N0YXJ0SGVpZ2h0CQEAAAARQGV4dHJOYXRpdmUoMTA1MCkAAAACBQAAAAR0aGlzBQAAABFrZXlRdWlja1N3YXBEZWxheQMJAAAAAAAAAgUAAAAGcnNhU2lnAQAAAAAFAAAAEHNlbGZVbmxvY2tIZWlnaHQJAQAAABZyYW5kVW5sb2NrSGVpZ2h0T3JGYWlsAAAABQUAAAAIc3dhcFR4SWQFAAAABnJzYVNpZwUAAAAIc3dhcFR5cGUFAAAAC3N0YXJ0SGVpZ2h0CQAFFAAAAAIJAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAAAlkYXRhQXJyYXkFAAAAC3NJZHhNaW5SYW5kCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAJZGF0YUFycmF5BQAAAAtzSWR4TWF4UmFuZAQAAAALaW5kZXhIZWlnaHQJAQAAABVnZXRIZWlnaHRQcmljZUJ5SW5kZXgAAAABBQAAAAVpbmRleAQAAAAPcHJldkluZGV4SGVpZ2h0CQEAAAAVZ2V0SGVpZ2h0UHJpY2VCeUluZGV4AAAAAQkAAGUAAAACBQAAAAVpbmRleAAAAAAAAAAAAQQAAAAMcHJpY2VCeUluZGV4CQEAAAAPZ2V0UHJpY2VIaXN0b3J5AAAAAQUAAAALaW5kZXhIZWlnaHQEAAAADSR0MDIyMzQzMjI1MzkDCQAAAAAAAAIFAAAACHN3YXBUeXBlAgAAAAV3YXZlcwkABRQAAAACCQEAAAAWY29udmVydFdhdmVzVG9OZXV0cmlubwAAAAIFAAAACGluQW1vdW50BQAAAAxwcmljZUJ5SW5kZXgFAAAAD25ldXRyaW5vQXNzZXRJZAkABRQAAAACCQEAAAAWY29udmVydE5ldXRyaW5vVG9XYXZlcwAAAAIFAAAACGluQW1vdW50BQAAAAxwcmljZUJ5SW5kZXgFAAAABHVuaXQEAAAADm91dEFtb3VudEdyb3NzCAUAAAANJHQwMjIzNDMyMjUzOQAAAAJfMQQAAAAIb3V0QXNzZXQIBQAAAA0kdDAyMjM0MzIyNTM5AAAAAl8yBAAAAAxwYXlvdXRzQXJyYXkJAQAAAAlhcHBseUZlZXMAAAACBQAAAA5vdXRBbW91bnRHcm9zcwUAAAAKb3V0RmVlUGFydAQAAAAMb3V0TmV0QW1vdW50CQABkQAAAAIFAAAADHBheW91dHNBcnJheQUAAAAMSWR4TmV0QW1vdW50BAAAAAxvdXRGZWVBbW91bnQJAAGRAAAAAgUAAAAMcGF5b3V0c0FycmF5BQAAAAxJZHhG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U3dhcFR5cGUEAAAACGluQW1vdW50CQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAJZGF0YUFycmF5BQAAAAxzSWR4SW5BbW91bnQEAAAACnN3YXBTdGF0dXMJAAGRAAAAAgUAAAAJZGF0YUFycmF5BQAAAApzSWR4U3RhdHVzBAAAAAdpc1F1aWNrCQAAAAAAAAIJAAGRAAAAAgUAAAAJZGF0YUFycmF5BQAAAAtzSWR4SXNRdWljawIAAAAEdHJ1ZQQAAAANJHQwMjU0NDYyNTY1NAQAAAAHJG1hdGNoMAkAA/wAAAAEBQAAAAR0aGlzAgAAABZxdWlja1N3YXBMaW1pdFJFQURPTkxZCQAETAAAAAIJAAQlAAAAAQUAAAALdXNlckFkZHJlc3MFAAAAA25pbAUAAAADbmlsAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAAooSW50LCBJbnQpBAAAAAFyBQAAAAckbWF0Y2gwCQAFFAAAAAIIBQAAAAFyAAAAAl8xCAUAAAABcgAAAAJfMgkAAAIAAAABAgAAABJUeXBlIGNhc3RpbmcgZXJyb3IEAAAAE3F1aWNrU3dhcExpbWl0VG90YWwIBQAAAA0kdDAyNTQ0NjI1NjU0AAAAAl8xBAAAABJxdWlja1N3YXBVc2VyU3BlbnQIBQAAAA0kdDAyNTQ0NjI1NjU0AAAAAl8yBAAAAA5xdWlja1N3YXBMaW1pdAkAAGUAAAACBQAAABNxdWlja1N3YXBMaW1pdFRvdGFsBQAAABJxdWlja1N3YXBVc2VyU3BlbnQEAAAADHByaWNlQnlJbmRleAkBAAAAD2dldFByaWNlSGlzdG9yeQAAAAEJAQAAABVnZXRIZWlnaHRQcmljZUJ5SW5kZXgAAAABBQAAAApwcmljZUluZGV4BAAAAA5zd2FwVXNkblZvbHVtZQMJAAAAAAAAAgUAAAAIc3dhcFR5cGUCAAAACG5ldXRyaW5vBQAAAAhpbkFtb3VudAkBAAAAFmNvbnZlcnRXYXZlc1RvTmV1dHJpbm8AAAACBQAAAAhpbkFtb3VudAUAAAAMcHJpY2VCeUluZGV4BAAAAAZjaGVja3MJAARMAAAAAgMJAQAAAAIhPQAAAAIFAAAACnN3YXBTdGF0dXMCAAAAB1BFTkRJTkcJAAACAAAAAQIAAAAfU3dhcCBoYXMgYmVlbiBhbHJlYWR5IHByb2Nlc3NlZAYJAARMAAAAAgMFAAAAB2lzUXVpY2sJAAACAAAAAQIAAAAhU3dhcCBoYXMgYmVlbiBhbHJlYWR5IGFjY2VsZXJhdGVkBgkABEwAAAACAwkAAGYAAAACBQAAAA5zd2FwVXNkblZvbHVtZQUAAAAOcXVpY2tTd2FwTGltaXQJAAACAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAA0WW91IGhhdmUgZXhjZWVkZWQgdGhlIHF1aWNrIHN3YXBzIGxpbWl0ISBSZXF1ZXN0ZWQ6IAkAAaQAAAABBQAAAA5zd2FwVXNkblZvbHVtZQIAAAANLCBhdmFpbGFibGU6IAkAAaQAAAABBQAAAA5xdWlja1N3YXBMaW1pdAYFAAAAA25pbAMJAAAAAAAAAgUAAAAGY2hlY2tzBQAAAAZjaGVja3MJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAAB1rZXlRdWlja1N3YXBVc2VyU3BlbnRJblBlcmlvZAAAAAEFAAAAC3VzZXJBZGRyZXNzCQAAZAAAAAIFAAAADnN3YXBVc2RuVm9sdW1lBQAAABJxdWlja1N3YXBVc2VyU3BlbnQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAABprZXlVc2VyTGFzdFF1aWNrU3dhcEhlaWdodAAAAAEFAAAAC3VzZXJBZGRyZXNzBQAAAAZoZWlnaHQJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAB3N3YXBLRVkAAAACBQAAAAdhY2NvdW50BQAAAAhzd2FwVHhJZAkBAAAAEmFjY2VsZXJhdGVTd2FwREFUQQAAAAEFAAAACWRhdGFBcnJheQUAAAADbmlsCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAABaQEAAAAId2l0aGRyYXcAAAADAAAAB2FjY291bnQAAAAFaW5kZXgAAAAIc3dhcFR4SWQEAAAABnJlc3VsdAkAA/wAAAAEBQAAAAR0aGlzAgAAAA5jb21tb25X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", "chainId": 84, "height": 1917755, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 9nuYJyRQF7GUgaR9wSrw27NxonyhMsEuzXLBBmZj1csK Next: BRTJwTHcVKR7RPDQ6xsKZmT8aWmzE93r5CA68kTTysan Diff:
OldNewDifferences
1-{-# STDLIB_VERSION 4 #-}
1+{-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 func getNumberByKey (key) = valueOrElse(getInteger(this, key), 0)
2121
2222 let pubKeyAdminsList = ["GXxmZaCigPgJsT6d1cLr8nUXA65nGX8V7FuAzzrY8wQE", "3xumx4hrPpeeoo79HLGbZCgfz95L39ZFdxxwWeSUC2Pu", "D4CqtK5fBsnzRo33ZMhrM7niLseDH2uRoK6weBq2JQ3A", "5WRXFSjwcTbNfKcJs8ZqXmSSWYsSVJUtMvMqZj5hH4Nc"]
2323
24-let SENDTXEXPIRE = 30
24+func asInt (val) = match val {
25+ case valInt: Int =>
26+ valInt
27+ case _ =>
28+ throw("Failed to cast into Int")
29+}
2530
26-let LISTSPLITSYMBOL = "_"
2731
28-let LISTDATASYMBOL = "+"
32+let SEP = "__"
2933
3034 let WAVELET = 100000000
3135
3943
4044 let IdxFeeAmount = 1
4145
46+let IdxGrossAmount = 2
47+
48+let dora2NsbtSymbol = "NSBT-USDT"
49+
50+let minRand = 60
51+
52+let maxRand = 1440
53+
4254 let NeutrinoAssetIdKey = "neutrino_asset_id"
4355
4456 let BondAssetIdKey = "bond_asset_id"
4961
5062 let RPDContractKey = "rpd_contract"
5163
52-let ContolContractKey = "control_contract"
64+let ControlContractKey = "control_contract"
5365
5466 let BalanceWavesLockIntervalKey = "balance_waves_lock_interval"
5567
6577
6678 let WavesOutFeePartKey = "wavesOut_swap_feePart"
6779
68-let FeesManagerAddressKey = "fees_manager_address"
80+let RsaRandPublic58Key = "rand_rsa_public"
6981
70-let RPDBalanceKey = "rpd_balance"
82+let keyGNsbtContract = "%s__gNsbtContract"
7183
72-func getRPDContractBalanceKey (assetId) = ((RPDBalanceKey + "_") + toBase58String(assetId))
84+let keyNsbtLockContract = "%s__nsbtLockContract"
7385
86+let keyDora2Contract = "%s__dora2Contract"
87+
88+let keyQuickSwapDelay = "%s__quickSwapDelay"
89+
90+let keyQuickSwapLimitDuration = "%s__quickSwapLimitDuration"
91+
92+let keyDora2LastHeightLimit = "%s__dora2LastHeightLimit"
7493
7594 let PriceKey = "price"
7695
84103 func getHeightPriceByIndexKey (index) = ((PriceIndexKey + "_") + toString(index))
85104
86105
87-let BalanceLockedkKey = "balance_lock_"
88-
89-let WavesLockedBalanceKey = (BalanceLockedkKey + "waves")
90-
91-let NeutrinoLockedBalanceKey = (BalanceLockedkKey + "neutrino")
92-
93-func getRPDSnapshotContractBalanceKey (count,assetId) = ((((RPDBalanceKey + "_") + toBase58String(assetId)) + "_") + toString(count))
106+func getStakingNodeByIndex (idx) = getStringByKey(makeString(["%s%d%s", "lease", toString(idx), "nodeAddress"], SEP))
94107
95108
96-func getCancelLeaseTxReserveFeeKey (hash) = (("cancel_lease_tx_reserve_fee" + "_") + hash)
109+func getStakingNodeAddressByIndex (idx) = addressFromStringValue(getStakingNodeByIndex(idx))
97110
98111
99-func getWavesLockedBalanceKey (owner) = ((WavesLockedBalanceKey + "_") + owner)
100-
101-
102-func getNeutrinoLockedBalanceKey (owner) = ((NeutrinoLockedBalanceKey + "_") + owner)
112+func getReservedAmountForSponsorship () = valueOrElse(getInteger(this, makeString(["%s%s", "lease", "sponsorshipWavesReserve"], SEP)), (1000 * WAVELET))
103113
104114
105115 func getBalanceUnlockBlockKey (owner) = ("balance_unlock_block_" + owner)
106116
107117
108-func getRPDProfitKey (count) = (("rpd_profit" + "_") + toString(count))
118+func getLeaseIdKey (nodeIndex) = makeString(["%s%d%s", "lease", toString(nodeIndex), "id"], SEP)
119+
120+
121+func getLeaseAmountKey (nodeIndex) = makeString(["%s%d%s", "lease", toString(nodeIndex), "amount"], SEP)
122+
123+
124+func minSwapAmountKEY (swapType) = (("min_" + swapType) + "_swap_amount")
125+
126+
127+func totalLockedKEY (swapType) = ("balance_lock_" + swapType)
128+
129+
130+func totalLockedByUserKEY (swapType,owner) = makeString(["balance_lock", swapType, owner], "_")
131+
132+
133+func balanceLockIntervalKEY (swapType) = (("balance_" + swapType) + "_lock_interval")
134+
135+
136+func minBalanceLockIntervalKEY (swapType) = (("balance_" + swapType) + "_lock_interval_minimum")
137+
138+
139+func nodeBalanceLockIntervalKEY () = "balance_node_lock_interval"
140+
141+
142+func outFeePartKEY (swapType) = (swapType + "Out_swap_feePart")
143+
144+
145+func keyQuickSwapUserSpentInPeriod (userAddress) = makeString(["%s%s", "quickSwapUserSpentInPeriod", toString(userAddress)], SEP)
146+
147+
148+func keyUserLastQuickSwapHeight (userAddress) = makeString(["%s%s", "userLastQuickSwapHeight", toString(userAddress)], SEP)
149+
150+
151+func keyDora2Price (symbol) = makeString(["%s%s", "price", symbol], SEP)
152+
153+
154+func keyDora2LastHeight (symbol) = makeString(["%s%s", "lastHeight", symbol], SEP)
155+
156+
157+func minSwapAmountREAD (swapType) = valueOrElse(getInteger(this, minSwapAmountKEY(swapType)), 0)
158+
159+
160+func totalLockedREAD (swapType) = valueOrElse(getInteger(this, totalLockedKEY(swapType)), 0)
161+
162+
163+func totalLockedByUserREAD (swapType,owner) = valueOrElse(getInteger(this, totalLockedByUserKEY(swapType, owner)), 0)
164+
165+
166+func balanceLockIntervalREAD (swapType) = valueOrElse(getInteger(this, balanceLockIntervalKEY(swapType)), maxRand)
167+
168+
169+func minBalanceLockIntervalREAD (swapType) = valueOrElse(getInteger(this, minBalanceLockIntervalKEY(swapType)), minRand)
170+
171+
172+func nodeBalanceLockIntervalREAD () = valueOrElse(getInteger(this, nodeBalanceLockIntervalKEY()), 1)
109173
110174
111175 func convertNeutrinoToWaves (amount,price) = fraction(fraction(amount, PRICELET, price), WAVELET, PAULI)
120184 func convertJsonArrayToList (jsonArray) = split(jsonArray, ",")
121185
122186
187+func minSwapAmountFAIL (swapType,minSwapAmount) = throw(((("The specified amount in " + swapType) + " swap is less than the required minimum of ") + toString(minSwapAmount)))
188+
189+
190+func emergencyShutdownFAIL () = throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
191+
192+
193+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)))
194+
195+
123196 let liquidationContract = getStringByKey(LiquidationContractKey)
124197
125-let neutrinoAssetIdString = getStringByKey(NeutrinoAssetIdKey)
126-
127-let neutrinoAssetId = fromBase58String(neutrinoAssetIdString)
198+let neutrinoAssetId = fromBase58String(getStringByKey(NeutrinoAssetIdKey))
128199
129200 let auctionContract = getStringByKey(AuctionContractKey)
130201
131202 let rpdContract = getStringByKey(RPDContractKey)
132203
133-let controlContract = getStringByKey(ContolContractKey)
204+let controlContract = getStringByKey(ControlContractKey)
134205
135206 let priceIndex = getNumberByAddressAndKey(controlContract, PriceIndexKey)
136207
138209
139210 let nodeOracleProviderPubKey = fromBase58String(getStringByKey(NodeOracleProviderPubKeyKey))
140211
141-let balanceWavesLockInterval = getNumberByKey(BalanceWavesLockIntervalKey)
142-
143-let balanceNeutrinoLockInterval = getNumberByKey(BalanceNeutrinoLockIntervalKey)
144-
145-let minWavesSwapAmount = getNumberByKey(MinWavesSwapAmountKey)
146-
147-let minNeutrinoSwapAmount = getNumberByKey(MinNeutrinoSwapAmountKey)
148-
149212 let bondAssetId = fromBase58String("BGhPYquXSK6UYjnPLEn94gFhetp4Jvf7toekEY4x1VDH")
150213
151214 let deprecatedBondAssetId = fromBase58String("975akZBfnMj513U7MZaHKzQrmsEx5aE3wdWKTrHBhbjF")
215+
216+let rsaPub = fromBase64String(valueOrErrorMessage(getString(this, RsaRandPublic58Key), "RSA public key has not been specified"))
152217
153218 let neutrinoContract = this
154219
155220 let currentPrice = getNumberByAddressAndKey(controlContract, PriceKey)
156221
157-let neutrinoLockedBalance = getNumberByKey(NeutrinoLockedBalanceKey)
222+let neutrinoLockedBalance = totalLockedREAD("neutrino")
158223
159-let wavesLockedBalance = getNumberByKey(WavesLockedBalanceKey)
224+let wavesLockedBalance = totalLockedREAD("waves")
160225
161226 let reserve = (wavesBalance(neutrinoContract).regular - wavesLockedBalance)
162227
181246 }
182247
183248
184-func getRPDContractBalance (assetId) = getNumberByAddressAndKey(rpdContract, getRPDContractBalanceKey(assetId))
185-
186-
187249 func getPriceHistory (block) = getNumberByAddressAndKey(controlContract, getPriceHistoryKey(block))
188250
189251
190252 func getHeightPriceByIndex (index) = getNumberByAddressAndKey(controlContract, getHeightPriceByIndexKey(index))
191253
192254
193-func getCancelLeaseTxReserveFee (hash) = getNumberByKey(getCancelLeaseTxReserveFeeKey(hash))
255+let sIdxSwapType = 1
256+
257+let sIdxStatus = 2
258+
259+let sIdxInAmount = 3
260+
261+let sIdxPrice = 4
262+
263+let sIdxOutNetAmount = 5
264+
265+let sIdxOutFeeAmount = 6
266+
267+let sIdxStartHeight = 7
268+
269+let sIdxStartTimestamp = 8
270+
271+let sIdxEndHeight = 9
272+
273+let sIdxEndTimestamp = 10
274+
275+let sIdxSelfUnlockHeight = 11
276+
277+let sIdxRandUnlockHeight = 12
278+
279+let sIdxIndex = 13
280+
281+let sIdxWithdrawTxId = 14
282+
283+let sIdxMinRand = 15
284+
285+let sIdxMaxRand = 16
286+
287+let sIdxIsQuick = 17
288+
289+func swapKEY (userAddress,txId) = makeString(["%s%s", userAddress, txId], SEP)
194290
195291
196-func getWavesLockedBalance (owner) = getNumberByKey(getWavesLockedBalanceKey(owner))
292+func strSwapDATA (swapType,status,inAmount,price,outNetAmount,outFeeAmount,startHeight,startTimestamp,endHeight,endTimestamp,selfUnlockHeight,randUnlockHeight,index,withdrawTxId,randMin,randMax,isQuick) = 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, isQuick], SEP)
197293
198294
199-func getNeutrinoLockedBalance (owner) = getNumberByKey(getNeutrinoLockedBalanceKey(owner))
295+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", toString(minBalanceLockIntervalREAD(swapType)), toString(balanceLockIntervalREAD(swapType)), toString(false))
200296
201297
202-func getUnlockBalanceBlock (owner) = getNumberByKey(getBalanceUnlockBlockKey(owner))
298+func accelerateSwapDATA (dataArray) = strSwapDATA(dataArray[sIdxSwapType], dataArray[sIdxStatus], dataArray[sIdxInAmount], dataArray[sIdxPrice], dataArray[sIdxOutNetAmount], dataArray[sIdxOutFeeAmount], dataArray[sIdxStartHeight], dataArray[sIdxStartTimestamp], dataArray[sIdxEndHeight], dataArray[sIdxEndTimestamp], dataArray[sIdxSelfUnlockHeight], dataArray[sIdxRandUnlockHeight], dataArray[sIdxIndex], dataArray[sIdxWithdrawTxId], dataArray[sIdxMinRand], dataArray[sIdxMaxRand], toString(true))
203299
204300
205-func getRPDProfit (count) = getNumberByKey(getRPDProfitKey(count))
301+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], dataArray[sIdxIsQuick])
302+
303+
304+func swapDataFailOrREAD (userAddress,swapTxId) = {
305+ let swapKey = swapKEY(userAddress, swapTxId)
306+ split(valueOrErrorMessage(getString(this, swapKey), ("no swap data for " + swapKey)), SEP)
307+ }
206308
207309
208310 func applyFees (amountGross,feePart) = {
209311 let feeAmount = fraction(amountGross, feePart, PAULI)
210-[(amountGross - feeAmount), feeAmount]
312+[(amountGross - feeAmount), feeAmount, amountGross]
211313 }
212314
213315
316+func randUnlockHeightOrFail (txId,rsaSig,swapType,startHeight,minMaxRandsTuple) = {
317+ let isRsaValid = rsaVerify_16Kb(SHA256, toBytes(txId), rsaSig, rsaPub)
318+ if (!(isRsaValid))
319+ then throw("invalid RSA signature")
320+ else {
321+ let minBalanceLockInterval = minMaxRandsTuple._1
322+ let maxBalanceLockInterval = minMaxRandsTuple._2
323+ let rand = (toInt(sha256_16Kb(rsaSig)) % (maxBalanceLockInterval - minBalanceLockInterval))
324+ let randLockInterval = (minBalanceLockInterval + (if ((0 > rand))
325+ then -(rand)
326+ else rand))
327+ (startHeight + randLockInterval)
328+ }
329+ }
330+
331+
332+func abs (x) = if ((0 > x))
333+ then -(x)
334+ else x
335+
336+
337+func selectNode (unleaseAmount) = {
338+ let amountToLease = ((wavesBalance(neutrinoContract).available - unleaseAmount) - getReservedAmountForSponsorship())
339+ let oldLeased0 = getNumberByKey(getLeaseAmountKey(0))
340+ let oldLeased1 = getNumberByKey(getLeaseAmountKey(1))
341+ let newLeased0 = (amountToLease + oldLeased0)
342+ let newLeased1 = (amountToLease + oldLeased1)
343+ if (if ((newLeased0 > 0))
344+ then true
345+ else (newLeased1 > 0))
346+ then {
347+ let delta0 = abs((newLeased0 - oldLeased1))
348+ let delta1 = abs((newLeased1 - oldLeased0))
349+ if ((delta1 >= delta0))
350+ then $Tuple2(0, newLeased0)
351+ else $Tuple2(1, newLeased1)
352+ }
353+ else $Tuple2(-1, 0)
354+ }
355+
356+
357+func prepareUnleaseAndLease (unleaseAmount) = {
358+ let $t01621216300 = selectNode(unleaseAmount)
359+ let nodeIndex = $t01621216300._1
360+ let newLeaseAmount = $t01621216300._2
361+ if ((newLeaseAmount > 0))
362+ then {
363+ let leaseIdKey = getLeaseIdKey(nodeIndex)
364+ let oldLease = getBinary(this, leaseIdKey)
365+ let unleaseOrEmpty = if (isDefined(oldLease))
366+ then [LeaseCancel(value(oldLease))]
367+ else nil
368+ let leaseAmountKey = getLeaseAmountKey(nodeIndex)
369+ let lease = Lease(getStakingNodeAddressByIndex(nodeIndex), newLeaseAmount)
370+ (unleaseOrEmpty ++ [lease, BinaryEntry(leaseIdKey, calculateLeaseId(lease)), IntegerEntry(getLeaseAmountKey(nodeIndex), newLeaseAmount)])
371+ }
372+ else nil
373+ }
374+
375+
376+func getDora2NSBTInfo () = {
377+ let dora2Contract = addressFromStringValue(getStringValue(this, keyDora2Contract))
378+ $Tuple2(valueOrErrorMessage(getInteger(dora2Contract, keyDora2Price(dora2NsbtSymbol)), "NSBT price is undefined"), valueOrElse(getInteger(dora2Contract, keyDora2LastHeight(dora2NsbtSymbol)), 0))
379+ }
380+
381+
382+func thisOnly (i) = if ((i.caller != this))
383+ then throw("Permission denied: this contract only allowed")
384+ else true
385+
386+
214387 @Callable(i)
215-func swapWavesToNeutrino () = {
216- let pmt = value(i.payments[0])
217- let account = toString(i.caller)
218- if ((minWavesSwapAmount > pmt.amount))
219- then throw((("The specified Waves amount is less than the required minimum of " + toString(minWavesSwapAmount)) + " wavelets."))
220- else if (isDefined(pmt.assetId))
221- then throw("Only Waves token is allowed for swapping.")
222- else if (isBlocked)
223- then throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
224- else if ((getUnlockBalanceBlock(account) > height))
225- then throw((("await " + toString((getUnlockBalanceBlock(account) - height))) + " blocks"))
226- else if (if ((getNeutrinoLockedBalance(account) != 0))
227- then true
228- else (getWavesLockedBalance(account) != 0))
229- then throw("please withdraw locked funds first")
230- else [IntegerEntry(getWavesLockedBalanceKey(account), pmt.amount), IntegerEntry(getBalanceUnlockBlockKey(account), (height + balanceWavesLockInterval)), IntegerEntry(WavesLockedBalanceKey, (wavesLockedBalance + pmt.amount))]
388+func prepareUnleaseAndLeaseWrapper (unleaseAmount) = {
389+ let checkCaller = [thisOnly(i)]
390+ if ((checkCaller == checkCaller))
391+ then prepareUnleaseAndLease(unleaseAmount)
392+ else throw("Strict value is not equal to itself.")
231393 }
232394
233395
234396
235397 @Callable(i)
236-func swapNeutrinoToWaves () = {
237- let pmt = value(i.payments[0])
238- let account = toString(i.caller)
239- if ((minNeutrinoSwapAmount > pmt.amount))
240- then throw((("The specified Neutrino amount is less than the required minimum of " + toString(minNeutrinoSwapAmount)) + " Neutrino cents."))
241- else if (isBlocked)
242- then throw("The contract is blocked by EMERGENCY SHUTDOWN. Please wait for reactivation by emergency oracles.")
243- else if ((pmt.assetId != neutrinoAssetId))
244- then throw("Only appropriate Neutrino tokens are allowed for swapping.")
245- else if ((getUnlockBalanceBlock(account) > height))
246- then throw((("await " + toString((getUnlockBalanceBlock(account) - height))) + " blocks"))
247- else if (if ((getNeutrinoLockedBalance(account) != 0))
248- then true
249- else (getWavesLockedBalance(account) != 0))
250- then throw("please withdraw locked funds first")
251- else [IntegerEntry(getNeutrinoLockedBalanceKey(account), pmt.amount), IntegerEntry(getBalanceUnlockBlockKey(account), (height + balanceNeutrinoLockInterval)), IntegerEntry(NeutrinoLockedBalanceKey, (neutrinoLockedBalance + pmt.amount))]
398+func constructor (neutrinoAssetIdPrm,bondAssetIdPrm,auctionContractPrm,liquidationContractPrm,rpdContractPrm,controlContractPrm,nodeOracleProviderPubKeyPrm,rsaRandPublicKeyPrm,balanceWavesLockIntervalPrm,balanceNeutrinoLockIntervalPrm,minWavesSwapAmountPrm,minNeutrinoSwapAmountPrm,neutrinoOutFeePartPrm,wavesOutFeePartPrm) = {
399+ let checkCaller = thisOnly(i)
400+ if ((checkCaller == checkCaller))
401+ then [StringEntry(NeutrinoAssetIdKey, neutrinoAssetIdPrm), StringEntry(BondAssetIdKey, bondAssetIdPrm), StringEntry(AuctionContractKey, auctionContractPrm), StringEntry(LiquidationContractKey, liquidationContractPrm), StringEntry(RPDContractKey, rpdContractPrm), StringEntry(ControlContractKey, controlContractPrm), StringEntry(NodeOracleProviderPubKeyKey, nodeOracleProviderPubKeyPrm), StringEntry(RsaRandPublic58Key, rsaRandPublicKeyPrm), IntegerEntry(BalanceWavesLockIntervalKey, balanceWavesLockIntervalPrm), IntegerEntry(BalanceNeutrinoLockIntervalKey, balanceNeutrinoLockIntervalPrm), IntegerEntry(MinWavesSwapAmountKey, minWavesSwapAmountPrm), IntegerEntry(MinNeutrinoSwapAmountKey, minNeutrinoSwapAmountPrm), IntegerEntry(NeutrinoOutFeePartKey, neutrinoOutFeePartPrm), IntegerEntry(WavesOutFeePartKey, wavesOutFeePartPrm)]
402+ else throw("Strict value is not equal to itself.")
252403 }
253404
254405
255406
256407 @Callable(i)
257-func withdraw (account,index) = {
408+func constructorV2 (gNsbtContract,nsbtLockContract,dora2Contract,quickSwapDelay,quickSwapLimitDuration,dora2LastHeightLimit) = {
409+ let checkCaller = thisOnly(i)
410+ if ((checkCaller == checkCaller))
411+ then [StringEntry(keyGNsbtContract, gNsbtContract), StringEntry(keyNsbtLockContract, nsbtLockContract), StringEntry(keyDora2Contract, dora2Contract), IntegerEntry(keyQuickSwapDelay, quickSwapDelay), IntegerEntry(keyQuickSwapLimitDuration, quickSwapLimitDuration), IntegerEntry(keyDora2LastHeightLimit, dora2LastHeightLimit)]
412+ else throw("Strict value is not equal to itself.")
413+ }
414+
415+
416+
417+@Callable(i)
418+func commonSwap (swapType,amount,account,txId) = {
419+ let checkCaller = thisOnly(i)
420+ if ((checkCaller == checkCaller))
421+ then {
422+ let minSwapAmount = minSwapAmountREAD(swapType)
423+ let totalLocked = totalLockedREAD(swapType)
424+ let totalLockedByUser = totalLockedByUserREAD(swapType, account)
425+ let nodeAddress = getStakingNodeByIndex(0)
426+ let balanceLockMaxInterval = if ((nodeAddress == account))
427+ then nodeBalanceLockIntervalREAD()
428+ else balanceLockIntervalREAD(swapType)
429+ let selfUnlockHeight = (height + balanceLockMaxInterval)
430+ if ((minSwapAmount > amount))
431+ then minSwapAmountFAIL(swapType, minSwapAmount)
432+ else if (isBlocked)
433+ then emergencyShutdownFAIL()
434+ else {
435+ let leasePart = if ((swapType == "waves"))
436+ then prepareUnleaseAndLease(0)
437+ else nil
438+ ([IntegerEntry(totalLockedByUserKEY(swapType, account), (totalLockedByUser + amount)), IntegerEntry(getBalanceUnlockBlockKey(account), selfUnlockHeight), IntegerEntry(totalLockedKEY(swapType), (totalLocked + amount)), StringEntry(swapKEY(account, txId), pendingSwapDATA(swapType, amount, selfUnlockHeight))] ++ leasePart)
439+ }
440+ }
441+ else throw("Strict value is not equal to itself.")
442+ }
443+
444+
445+
446+@Callable(i)
447+func commonWithdraw (account,index,swapTxId,rsaSig) = {
258448 let userAddress = addressFromStringValue(account)
259- let feeManagerAddress = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(this, FeesManagerAddressKey), (FeesManagerAddressKey + " is not specified"))), (FeesManagerAddressKey + " invalid address format"))
260- let unlockHeight = getUnlockBalanceBlock(account)
261- let userWavesLockedBalance = getWavesLockedBalance(account)
262- let userNeutrinoLockedBalance = getNeutrinoLockedBalance(account)
263- let indexHeight = getHeightPriceByIndex(index)
264- let prevIndexHeight = getHeightPriceByIndex((index - 1))
265- let priceByIndex = getPriceHistory(indexHeight)
266- let neutrinoAmountGross = convertWavesToNeutrino(userWavesLockedBalance, priceByIndex)
267- let wavesAmountGross = convertNeutrinoToWaves(userNeutrinoLockedBalance, priceByIndex)
268- let neutrinoOutFeePart = valueOrElse(getInteger(this, NeutrinoOutFeePartKey), DEFAULTSWAPFEE)
269- let wavesOutFeePart = valueOrElse(getInteger(this, WavesOutFeePartKey), DEFAULTSWAPFEE)
270- let neutrinoPayoutsArray = applyFees(neutrinoAmountGross, neutrinoOutFeePart)
271- let wavesPayoutsArray = applyFees(wavesAmountGross, wavesOutFeePart)
272- if (isBlocked)
273- then throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
274- else if ((unlockHeight > height))
275- then throw((("please wait for: " + toString(unlockHeight)) + " block height to withdraw WAVES funds"))
276- else if (if (if ((index > priceIndex))
277- then true
278- else (unlockHeight > indexHeight))
279- then true
280- else if ((prevIndexHeight != 0))
281- then (prevIndexHeight >= unlockHeight)
282- else false)
283- then throw(((((((((("invalid price history index: index=" + toString(index)) + " priceIndex=") + toString(priceIndex)) + " indexHeight=") + toString(indexHeight)) + " unlockHeight=") + toString(unlockHeight)) + " prevIndexHeight=") + toString(prevIndexHeight)))
284- else if (if ((0 >= neutrinoAmountGross))
285- then (0 >= wavesAmountGross)
286- else false)
287- then throw("balance equals zero")
288- else if (if ((0 > neutrinoOutFeePart))
449+ let checkCaller = thisOnly(i)
450+ if ((checkCaller == checkCaller))
451+ then {
452+ let dataArray = swapDataFailOrREAD(account, swapTxId)
453+ let selfUnlockHeight = parseIntValue(dataArray[sIdxSelfUnlockHeight])
454+ let swapType = dataArray[sIdxSwapType]
455+ let inAmount = parseIntValue(dataArray[sIdxInAmount])
456+ let swapStatus = dataArray[sIdxStatus]
457+ let startHeight = parseIntValue(dataArray[sIdxStartHeight])
458+ let isQuick = (dataArray[sIdxIsQuick] == "true")
459+ let checkSwapType = if (if ((swapType != "waves"))
460+ then (swapType != "neutrino")
461+ else false)
462+ then throw(("Unsupported swap type " + swapType))
463+ else true
464+ if ((checkSwapType == checkSwapType))
465+ then {
466+ let outFeePart = valueOrElse(getInteger(this, outFeePartKEY(swapType)), DEFAULTSWAPFEE)
467+ let totalLocked = totalLockedREAD(swapType)
468+ let totalLockedByUser = totalLockedByUserREAD(swapType, account)
469+ let unlockHeight = if (isQuick)
470+ then (startHeight + getIntegerValue(this, keyQuickSwapDelay))
471+ else if ((rsaSig == base58''))
472+ then selfUnlockHeight
473+ else randUnlockHeightOrFail(swapTxId, rsaSig, swapType, startHeight, $Tuple2(parseIntValue(dataArray[sIdxMinRand]), parseIntValue(dataArray[sIdxMaxRand])))
474+ let indexHeight = getHeightPriceByIndex(index)
475+ let prevIndexHeight = getHeightPriceByIndex((index - 1))
476+ let priceByIndex = getPriceHistory(indexHeight)
477+ let $t02234322539 = if ((swapType == "waves"))
478+ then $Tuple2(convertWavesToNeutrino(inAmount, priceByIndex), neutrinoAssetId)
479+ else $Tuple2(convertNeutrinoToWaves(inAmount, priceByIndex), unit)
480+ let outAmountGross = $t02234322539._1
481+ let outAsset = $t02234322539._2
482+ let payoutsArray = applyFees(outAmountGross, outFeePart)
483+ let outNetAmount = payoutsArray[IdxNetAmount]
484+ let outFeeAmount = payoutsArray[IdxFeeAmount]
485+ let checks = [if (isBlocked)
486+ then emergencyShutdownFAIL()
487+ else true, if ((swapStatus != "PENDING"))
488+ then throw("swap has been already processed")
489+ else true, if ((unlockHeight > height))
490+ then throw((("please wait for: " + toString(unlockHeight)) + " block height to withdraw funds"))
491+ else true, if (if (if ((index > priceIndex))
289492 then true
290- else (0 > wavesOutFeePart))
291- then throw(((("invalid fees data: neutrinoOutFeePart=" + toString(neutrinoOutFeePart)) + " wavesOutFeePart=") + toString(wavesOutFeePart)))
292- else [IntegerEntry(getWavesLockedBalanceKey(account), 0), IntegerEntry(getNeutrinoLockedBalanceKey(account), 0), IntegerEntry(WavesLockedBalanceKey, (wavesLockedBalance - userWavesLockedBalance)), IntegerEntry(NeutrinoLockedBalanceKey, (neutrinoLockedBalance - userNeutrinoLockedBalance)), ScriptTransfer(userAddress, wavesPayoutsArray[IdxNetAmount], unit), ScriptTransfer(feeManagerAddress, wavesPayoutsArray[IdxFeeAmount], unit), ScriptTransfer(userAddress, neutrinoPayoutsArray[IdxNetAmount], neutrinoAssetId), ScriptTransfer(feeManagerAddress, neutrinoPayoutsArray[IdxFeeAmount], neutrinoAssetId)]
493+ else (unlockHeight > indexHeight))
494+ then true
495+ else if ((prevIndexHeight != 0))
496+ then (prevIndexHeight >= unlockHeight)
497+ else false)
498+ then priceIndexFAIL(index, priceIndex, indexHeight, unlockHeight, prevIndexHeight)
499+ else true, if ((0 >= payoutsArray[IdxGrossAmount]))
500+ then throw("balance equals zero")
501+ else true, if (if ((0 > outFeePart))
502+ then true
503+ else (outFeePart >= PAULI))
504+ then throw(((("invalid outFeePart config for " + swapType) + " swap: outFeePart=") + toString(outFeePart)))
505+ else true]
506+ if ((checks == checks))
507+ then {
508+ let leasePart = if (if ((swapType == "neutrino"))
509+ then (outAmountGross > 0)
510+ else false)
511+ then invoke(this, "prepareUnleaseAndLeaseWrapper", [outAmountGross], nil)
512+ else unit
513+ if ((leasePart == leasePart))
514+ then {
515+ let sendFee = invoke(addressFromStringValue(getStringValue(this, keyGNsbtContract)), "deposit", nil, [AttachedPayment(outAsset, outFeeAmount)])
516+ if ((sendFee == sendFee))
517+ then [IntegerEntry(totalLockedByUserKEY(swapType, account), (totalLockedByUser - inAmount)), IntegerEntry(totalLockedKEY(swapType), (totalLocked - inAmount)), ScriptTransfer(userAddress, outNetAmount, outAsset), StringEntry(swapKEY(account, swapTxId), finishSwapDATA(dataArray, priceByIndex, outNetAmount, outFeeAmount, unlockHeight, index, toBase58String(i.transactionId)))]
518+ else throw("Strict value is not equal to itself.")
519+ }
520+ else throw("Strict value is not equal to itself.")
521+ }
522+ else throw("Strict value is not equal to itself.")
523+ }
524+ else throw("Strict value is not equal to itself.")
525+ }
526+ else throw("Strict value is not equal to itself.")
527+ }
528+
529+
530+
531+@Callable(i)
532+func swap (swapType) = {
533+ let accelerate = true
534+ let wavesToNeutrino = (swapType == "waves")
535+ let neutrinoToWaves = (swapType == "neutrino")
536+ let pmt = value(i.payments[0])
537+ let account = toString(i.caller)
538+ let swapTxId = toBase58String(i.transactionId)
539+ if (if (wavesToNeutrino)
540+ then (pmt.assetId != unit)
541+ else false)
542+ then throw("Only Waves token is allowed for swapping.")
543+ else if (if (neutrinoToWaves)
544+ then (pmt.assetId != neutrinoAssetId)
545+ else false)
546+ then throw("Only appropriate Neutrino tokens are allowed for swapping.")
547+ else if (if (!(wavesToNeutrino))
548+ then !(neutrinoToWaves)
549+ else false)
550+ then throw("Invalid swap type")
551+ else {
552+ let commonSwapInv = invoke(this, "commonSwap", [swapType, pmt.amount, account, swapTxId], nil)
553+ if ((commonSwapInv == commonSwapInv))
554+ then {
555+ let accelerateInv = if (accelerate)
556+ then invoke(this, "accelerate", [account, swapTxId], nil)
557+ else true
558+ if ((accelerateInv == accelerateInv))
559+ then nil
560+ else throw("Strict value is not equal to itself.")
561+ }
562+ else throw("Strict value is not equal to itself.")
563+ }
564+ }
565+
566+
567+
568+@Callable(i)
569+func accelerate (account,swapTxId) = {
570+ let checkCaller = thisOnly(i)
571+ if ((checkCaller == checkCaller))
572+ then {
573+ let userAddress = addressFromStringValue(account)
574+ let dataArray = swapDataFailOrREAD(account, swapTxId)
575+ let swapType = dataArray[sIdxSwapType]
576+ let inAmount = parseIntValue(dataArray[sIdxInAmount])
577+ let swapStatus = dataArray[sIdxStatus]
578+ let isQuick = (dataArray[sIdxIsQuick] == "true")
579+ let $t02544625654 = match invoke(this, "quickSwapLimitREADONLY", [toString(userAddress)], nil) {
580+ case r: (Int, Int) =>
581+ $Tuple2(r._1, r._2)
582+ case _ =>
583+ throw("Type casting error")
584+ }
585+ let quickSwapLimitTotal = $t02544625654._1
586+ let quickSwapUserSpent = $t02544625654._2
587+ let quickSwapLimit = (quickSwapLimitTotal - quickSwapUserSpent)
588+ let priceByIndex = getPriceHistory(getHeightPriceByIndex(priceIndex))
589+ let swapUsdnVolume = if ((swapType == "neutrino"))
590+ then inAmount
591+ else convertWavesToNeutrino(inAmount, priceByIndex)
592+ let checks = [if ((swapStatus != "PENDING"))
593+ then throw("Swap has been already processed")
594+ else true, if (isQuick)
595+ then throw("Swap has been already accelerated")
596+ else true, if ((swapUsdnVolume > quickSwapLimit))
597+ then throw(((("You have exceeded the quick swaps limit! Requested: " + toString(swapUsdnVolume)) + ", available: ") + toString(quickSwapLimit)))
598+ else true]
599+ if ((checks == checks))
600+ then [IntegerEntry(keyQuickSwapUserSpentInPeriod(userAddress), (swapUsdnVolume + quickSwapUserSpent)), IntegerEntry(keyUserLastQuickSwapHeight(userAddress), height), StringEntry(swapKEY(account, swapTxId), accelerateSwapDATA(dataArray))]
601+ else throw("Strict value is not equal to itself.")
602+ }
603+ else throw("Strict value is not equal to itself.")
604+ }
605+
606+
607+
608+@Callable(i)
609+func withdraw (account,index,swapTxId) = {
610+ let result = invoke(this, "commonWithdraw", [account, index, swapTxId, base58''], nil)
611+ if ((result == result))
612+ then nil
613+ else throw("Strict value is not equal to itself.")
614+ }
615+
616+
617+
618+@Callable(i)
619+func withdrawRand (account,index,swapTxId,rsaSig) = {
620+ let result = invoke(this, "commonWithdraw", [account, index, swapTxId, rsaSig], nil)
621+ if ((result == result))
622+ then nil
623+ else throw("Strict value is not equal to itself.")
293624 }
294625
295626
308639 }
309640
310641
642+
643+@Callable(i)
644+func acceptWaves () = if ((i.caller != addressFromStringValue(auctionContract)))
645+ then throw("Currently only auction contract is allowed to call")
646+ else $Tuple2(prepareUnleaseAndLease(0), "success")
647+
648+
649+
650+@Callable(i)
651+func calcTotalQuickSwapLimitREADONLY (gNsbtAmount) = {
652+ let $t02870528762 = getDora2NSBTInfo()
653+ let nsbtPrice = $t02870528762._1
654+ let nsbtPriceLastHeight = $t02870528762._2
655+ let check = if (((height - nsbtPriceLastHeight) > getIntegerValue(this, keyDora2LastHeightLimit)))
656+ then throw("NSBT price is outdated")
657+ else true
658+ if ((check == check))
659+ then $Tuple2(nil, fraction(gNsbtAmount, nsbtPrice, WAVELET))
660+ else throw("Strict value is not equal to itself.")
661+ }
662+
663+
664+
665+@Callable(i)
666+func quickSwapLimitREADONLY (userAddressStr) = {
667+ let limitAvalableWaves = toString((10000 * 100000000))
668+ let limitAvalableUsdn = toString((100000 * 1000000))
669+ let limitRemainingBlocksToReset = toString(940)
670+ $Tuple2(nil, makeString(["%d%d%d", limitAvalableWaves, limitAvalableUsdn, limitRemainingBlocksToReset], SEP))
671+ }
672+
673+
311674 @Verifier(tx)
312675 func verify () = {
313676 let id = toBase58String(tx.id)
677+ let minSignaturesNumber = 3
314678 let count = ((((if (sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(pubKeyAdminsList[0])))
315679 then 1
316680 else 0) + (if (sigVerify(tx.bodyBytes, tx.proofs[1], fromBase58String(pubKeyAdminsList[1])))
320684 else 0)) + (if (sigVerify(tx.bodyBytes, tx.proofs[3], fromBase58String(pubKeyAdminsList[3])))
321685 then 2
322686 else 0))
687+ let isSignaturesValid = (count >= minSignaturesNumber)
323688 match tx {
324- case leasingTx: LeaseCancelTransaction|LeaseTransaction =>
325- sigVerify(leasingTx.bodyBytes, leasingTx.proofs[0], nodeOracleProviderPubKey)
326689 case sponsorTx: SponsorFeeTransaction =>
327- if (checkIsValidMinSponsoredFee(sponsorTx))
328- then (count >= 3)
690+ if (isSignaturesValid)
691+ then checkIsValidMinSponsoredFee(sponsorTx)
329692 else false
330693 case _ =>
331- (count >= 3)
694+ isSignaturesValid
332695 }
333696 }
334697
Full:
OldNewDifferences
1-{-# STDLIB_VERSION 4 #-}
1+{-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 func getNumberByKey (key) = valueOrElse(getInteger(this, key), 0)
55
66
77 func getStringByKey (key) = valueOrElse(getString(this, key), "")
88
99
1010 func getBoolByKey (key) = valueOrElse(getBoolean(this, key), false)
1111
1212
1313 func getNumberByAddressAndKey (address,key) = valueOrElse(getInteger(addressFromStringValue(address), key), 0)
1414
1515
1616 func getStringByAddressAndKey (address,key) = valueOrElse(getString(addressFromStringValue(address), key), "")
1717
1818
1919 func getBoolByAddressAndKey (address,key) = valueOrElse(getBoolean(addressFromStringValue(address), key), false)
2020
2121
2222 let pubKeyAdminsList = ["GXxmZaCigPgJsT6d1cLr8nUXA65nGX8V7FuAzzrY8wQE", "3xumx4hrPpeeoo79HLGbZCgfz95L39ZFdxxwWeSUC2Pu", "D4CqtK5fBsnzRo33ZMhrM7niLseDH2uRoK6weBq2JQ3A", "5WRXFSjwcTbNfKcJs8ZqXmSSWYsSVJUtMvMqZj5hH4Nc"]
2323
24-let SENDTXEXPIRE = 30
24+func asInt (val) = match val {
25+ case valInt: Int =>
26+ valInt
27+ case _ =>
28+ throw("Failed to cast into Int")
29+}
2530
26-let LISTSPLITSYMBOL = "_"
2731
28-let LISTDATASYMBOL = "+"
32+let SEP = "__"
2933
3034 let WAVELET = 100000000
3135
3236 let PAULI = 1000000
3337
3438 let PRICELET = 1000000
3539
3640 let DEFAULTSWAPFEE = 20000
3741
3842 let IdxNetAmount = 0
3943
4044 let IdxFeeAmount = 1
4145
46+let IdxGrossAmount = 2
47+
48+let dora2NsbtSymbol = "NSBT-USDT"
49+
50+let minRand = 60
51+
52+let maxRand = 1440
53+
4254 let NeutrinoAssetIdKey = "neutrino_asset_id"
4355
4456 let BondAssetIdKey = "bond_asset_id"
4557
4658 let AuctionContractKey = "auction_contract"
4759
4860 let LiquidationContractKey = "liquidation_contract"
4961
5062 let RPDContractKey = "rpd_contract"
5163
52-let ContolContractKey = "control_contract"
64+let ControlContractKey = "control_contract"
5365
5466 let BalanceWavesLockIntervalKey = "balance_waves_lock_interval"
5567
5668 let BalanceNeutrinoLockIntervalKey = "balance_neutrino_lock_interval"
5769
5870 let MinWavesSwapAmountKey = "min_waves_swap_amount"
5971
6072 let MinNeutrinoSwapAmountKey = "min_neutrino_swap_amount"
6173
6274 let NodeOracleProviderPubKeyKey = "node_oracle_provider"
6375
6476 let NeutrinoOutFeePartKey = "neutrinoOut_swap_feePart"
6577
6678 let WavesOutFeePartKey = "wavesOut_swap_feePart"
6779
68-let FeesManagerAddressKey = "fees_manager_address"
80+let RsaRandPublic58Key = "rand_rsa_public"
6981
70-let RPDBalanceKey = "rpd_balance"
82+let keyGNsbtContract = "%s__gNsbtContract"
7183
72-func getRPDContractBalanceKey (assetId) = ((RPDBalanceKey + "_") + toBase58String(assetId))
84+let keyNsbtLockContract = "%s__nsbtLockContract"
7385
86+let keyDora2Contract = "%s__dora2Contract"
87+
88+let keyQuickSwapDelay = "%s__quickSwapDelay"
89+
90+let keyQuickSwapLimitDuration = "%s__quickSwapLimitDuration"
91+
92+let keyDora2LastHeightLimit = "%s__dora2LastHeightLimit"
7493
7594 let PriceKey = "price"
7695
7796 let PriceIndexKey = "price_index"
7897
7998 let IsBlockedKey = "is_blocked"
8099
81100 func getPriceHistoryKey (block) = ((PriceKey + "_") + toString(block))
82101
83102
84103 func getHeightPriceByIndexKey (index) = ((PriceIndexKey + "_") + toString(index))
85104
86105
87-let BalanceLockedkKey = "balance_lock_"
88-
89-let WavesLockedBalanceKey = (BalanceLockedkKey + "waves")
90-
91-let NeutrinoLockedBalanceKey = (BalanceLockedkKey + "neutrino")
92-
93-func getRPDSnapshotContractBalanceKey (count,assetId) = ((((RPDBalanceKey + "_") + toBase58String(assetId)) + "_") + toString(count))
106+func getStakingNodeByIndex (idx) = getStringByKey(makeString(["%s%d%s", "lease", toString(idx), "nodeAddress"], SEP))
94107
95108
96-func getCancelLeaseTxReserveFeeKey (hash) = (("cancel_lease_tx_reserve_fee" + "_") + hash)
109+func getStakingNodeAddressByIndex (idx) = addressFromStringValue(getStakingNodeByIndex(idx))
97110
98111
99-func getWavesLockedBalanceKey (owner) = ((WavesLockedBalanceKey + "_") + owner)
100-
101-
102-func getNeutrinoLockedBalanceKey (owner) = ((NeutrinoLockedBalanceKey + "_") + owner)
112+func getReservedAmountForSponsorship () = valueOrElse(getInteger(this, makeString(["%s%s", "lease", "sponsorshipWavesReserve"], SEP)), (1000 * WAVELET))
103113
104114
105115 func getBalanceUnlockBlockKey (owner) = ("balance_unlock_block_" + owner)
106116
107117
108-func getRPDProfitKey (count) = (("rpd_profit" + "_") + toString(count))
118+func getLeaseIdKey (nodeIndex) = makeString(["%s%d%s", "lease", toString(nodeIndex), "id"], SEP)
119+
120+
121+func getLeaseAmountKey (nodeIndex) = makeString(["%s%d%s", "lease", toString(nodeIndex), "amount"], SEP)
122+
123+
124+func minSwapAmountKEY (swapType) = (("min_" + swapType) + "_swap_amount")
125+
126+
127+func totalLockedKEY (swapType) = ("balance_lock_" + swapType)
128+
129+
130+func totalLockedByUserKEY (swapType,owner) = makeString(["balance_lock", swapType, owner], "_")
131+
132+
133+func balanceLockIntervalKEY (swapType) = (("balance_" + swapType) + "_lock_interval")
134+
135+
136+func minBalanceLockIntervalKEY (swapType) = (("balance_" + swapType) + "_lock_interval_minimum")
137+
138+
139+func nodeBalanceLockIntervalKEY () = "balance_node_lock_interval"
140+
141+
142+func outFeePartKEY (swapType) = (swapType + "Out_swap_feePart")
143+
144+
145+func keyQuickSwapUserSpentInPeriod (userAddress) = makeString(["%s%s", "quickSwapUserSpentInPeriod", toString(userAddress)], SEP)
146+
147+
148+func keyUserLastQuickSwapHeight (userAddress) = makeString(["%s%s", "userLastQuickSwapHeight", toString(userAddress)], SEP)
149+
150+
151+func keyDora2Price (symbol) = makeString(["%s%s", "price", symbol], SEP)
152+
153+
154+func keyDora2LastHeight (symbol) = makeString(["%s%s", "lastHeight", symbol], SEP)
155+
156+
157+func minSwapAmountREAD (swapType) = valueOrElse(getInteger(this, minSwapAmountKEY(swapType)), 0)
158+
159+
160+func totalLockedREAD (swapType) = valueOrElse(getInteger(this, totalLockedKEY(swapType)), 0)
161+
162+
163+func totalLockedByUserREAD (swapType,owner) = valueOrElse(getInteger(this, totalLockedByUserKEY(swapType, owner)), 0)
164+
165+
166+func balanceLockIntervalREAD (swapType) = valueOrElse(getInteger(this, balanceLockIntervalKEY(swapType)), maxRand)
167+
168+
169+func minBalanceLockIntervalREAD (swapType) = valueOrElse(getInteger(this, minBalanceLockIntervalKEY(swapType)), minRand)
170+
171+
172+func nodeBalanceLockIntervalREAD () = valueOrElse(getInteger(this, nodeBalanceLockIntervalKEY()), 1)
109173
110174
111175 func convertNeutrinoToWaves (amount,price) = fraction(fraction(amount, PRICELET, price), WAVELET, PAULI)
112176
113177
114178 func convertWavesToNeutrino (amount,price) = fraction(fraction(amount, price, PRICELET), PAULI, WAVELET)
115179
116180
117181 func convertWavesToBond (amount,price) = convertWavesToNeutrino(amount, price)
118182
119183
120184 func convertJsonArrayToList (jsonArray) = split(jsonArray, ",")
121185
122186
187+func minSwapAmountFAIL (swapType,minSwapAmount) = throw(((("The specified amount in " + swapType) + " swap is less than the required minimum of ") + toString(minSwapAmount)))
188+
189+
190+func emergencyShutdownFAIL () = throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
191+
192+
193+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)))
194+
195+
123196 let liquidationContract = getStringByKey(LiquidationContractKey)
124197
125-let neutrinoAssetIdString = getStringByKey(NeutrinoAssetIdKey)
126-
127-let neutrinoAssetId = fromBase58String(neutrinoAssetIdString)
198+let neutrinoAssetId = fromBase58String(getStringByKey(NeutrinoAssetIdKey))
128199
129200 let auctionContract = getStringByKey(AuctionContractKey)
130201
131202 let rpdContract = getStringByKey(RPDContractKey)
132203
133-let controlContract = getStringByKey(ContolContractKey)
204+let controlContract = getStringByKey(ControlContractKey)
134205
135206 let priceIndex = getNumberByAddressAndKey(controlContract, PriceIndexKey)
136207
137208 let isBlocked = getBoolByAddressAndKey(controlContract, IsBlockedKey)
138209
139210 let nodeOracleProviderPubKey = fromBase58String(getStringByKey(NodeOracleProviderPubKeyKey))
140211
141-let balanceWavesLockInterval = getNumberByKey(BalanceWavesLockIntervalKey)
142-
143-let balanceNeutrinoLockInterval = getNumberByKey(BalanceNeutrinoLockIntervalKey)
144-
145-let minWavesSwapAmount = getNumberByKey(MinWavesSwapAmountKey)
146-
147-let minNeutrinoSwapAmount = getNumberByKey(MinNeutrinoSwapAmountKey)
148-
149212 let bondAssetId = fromBase58String("BGhPYquXSK6UYjnPLEn94gFhetp4Jvf7toekEY4x1VDH")
150213
151214 let deprecatedBondAssetId = fromBase58String("975akZBfnMj513U7MZaHKzQrmsEx5aE3wdWKTrHBhbjF")
215+
216+let rsaPub = fromBase64String(valueOrErrorMessage(getString(this, RsaRandPublic58Key), "RSA public key has not been specified"))
152217
153218 let neutrinoContract = this
154219
155220 let currentPrice = getNumberByAddressAndKey(controlContract, PriceKey)
156221
157-let neutrinoLockedBalance = getNumberByKey(NeutrinoLockedBalanceKey)
222+let neutrinoLockedBalance = totalLockedREAD("neutrino")
158223
159-let wavesLockedBalance = getNumberByKey(WavesLockedBalanceKey)
224+let wavesLockedBalance = totalLockedREAD("waves")
160225
161226 let reserve = (wavesBalance(neutrinoContract).regular - wavesLockedBalance)
162227
163228 let neutrinoSupply = (((neutrinoLockedBalance + value(assetInfo(neutrinoAssetId)).quantity) - assetBalance(neutrinoContract, neutrinoAssetId)) - assetBalance(addressFromStringValue(liquidationContract), neutrinoAssetId))
164229
165230 let surplus = (convertWavesToNeutrino(reserve, currentPrice) - neutrinoSupply)
166231
167232 let deficit = (neutrinoSupply - convertWavesToNeutrino(reserve, currentPrice))
168233
169234 func checkIsValidMinSponsoredFee (tx) = {
170235 let MINTRANSFERFEE = 100000
171236 let SponsoredFeeUpperBound = 1000
172237 let realNeutrinoFee = convertWavesToNeutrino(MINTRANSFERFEE, currentPrice)
173238 let minNeutrinoFee = (realNeutrinoFee * 2)
174239 let maxNeutrinoFee = fraction(realNeutrinoFee, SponsoredFeeUpperBound, 100)
175240 let inputFee = value(tx.minSponsoredAssetFee)
176241 if (if ((inputFee >= minNeutrinoFee))
177242 then (maxNeutrinoFee >= inputFee)
178243 else false)
179244 then (tx.assetId == neutrinoAssetId)
180245 else false
181246 }
182247
183248
184-func getRPDContractBalance (assetId) = getNumberByAddressAndKey(rpdContract, getRPDContractBalanceKey(assetId))
185-
186-
187249 func getPriceHistory (block) = getNumberByAddressAndKey(controlContract, getPriceHistoryKey(block))
188250
189251
190252 func getHeightPriceByIndex (index) = getNumberByAddressAndKey(controlContract, getHeightPriceByIndexKey(index))
191253
192254
193-func getCancelLeaseTxReserveFee (hash) = getNumberByKey(getCancelLeaseTxReserveFeeKey(hash))
255+let sIdxSwapType = 1
256+
257+let sIdxStatus = 2
258+
259+let sIdxInAmount = 3
260+
261+let sIdxPrice = 4
262+
263+let sIdxOutNetAmount = 5
264+
265+let sIdxOutFeeAmount = 6
266+
267+let sIdxStartHeight = 7
268+
269+let sIdxStartTimestamp = 8
270+
271+let sIdxEndHeight = 9
272+
273+let sIdxEndTimestamp = 10
274+
275+let sIdxSelfUnlockHeight = 11
276+
277+let sIdxRandUnlockHeight = 12
278+
279+let sIdxIndex = 13
280+
281+let sIdxWithdrawTxId = 14
282+
283+let sIdxMinRand = 15
284+
285+let sIdxMaxRand = 16
286+
287+let sIdxIsQuick = 17
288+
289+func swapKEY (userAddress,txId) = makeString(["%s%s", userAddress, txId], SEP)
194290
195291
196-func getWavesLockedBalance (owner) = getNumberByKey(getWavesLockedBalanceKey(owner))
292+func strSwapDATA (swapType,status,inAmount,price,outNetAmount,outFeeAmount,startHeight,startTimestamp,endHeight,endTimestamp,selfUnlockHeight,randUnlockHeight,index,withdrawTxId,randMin,randMax,isQuick) = 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, isQuick], SEP)
197293
198294
199-func getNeutrinoLockedBalance (owner) = getNumberByKey(getNeutrinoLockedBalanceKey(owner))
295+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", toString(minBalanceLockIntervalREAD(swapType)), toString(balanceLockIntervalREAD(swapType)), toString(false))
200296
201297
202-func getUnlockBalanceBlock (owner) = getNumberByKey(getBalanceUnlockBlockKey(owner))
298+func accelerateSwapDATA (dataArray) = strSwapDATA(dataArray[sIdxSwapType], dataArray[sIdxStatus], dataArray[sIdxInAmount], dataArray[sIdxPrice], dataArray[sIdxOutNetAmount], dataArray[sIdxOutFeeAmount], dataArray[sIdxStartHeight], dataArray[sIdxStartTimestamp], dataArray[sIdxEndHeight], dataArray[sIdxEndTimestamp], dataArray[sIdxSelfUnlockHeight], dataArray[sIdxRandUnlockHeight], dataArray[sIdxIndex], dataArray[sIdxWithdrawTxId], dataArray[sIdxMinRand], dataArray[sIdxMaxRand], toString(true))
203299
204300
205-func getRPDProfit (count) = getNumberByKey(getRPDProfitKey(count))
301+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], dataArray[sIdxIsQuick])
302+
303+
304+func swapDataFailOrREAD (userAddress,swapTxId) = {
305+ let swapKey = swapKEY(userAddress, swapTxId)
306+ split(valueOrErrorMessage(getString(this, swapKey), ("no swap data for " + swapKey)), SEP)
307+ }
206308
207309
208310 func applyFees (amountGross,feePart) = {
209311 let feeAmount = fraction(amountGross, feePart, PAULI)
210-[(amountGross - feeAmount), feeAmount]
312+[(amountGross - feeAmount), feeAmount, amountGross]
211313 }
212314
213315
316+func randUnlockHeightOrFail (txId,rsaSig,swapType,startHeight,minMaxRandsTuple) = {
317+ let isRsaValid = rsaVerify_16Kb(SHA256, toBytes(txId), rsaSig, rsaPub)
318+ if (!(isRsaValid))
319+ then throw("invalid RSA signature")
320+ else {
321+ let minBalanceLockInterval = minMaxRandsTuple._1
322+ let maxBalanceLockInterval = minMaxRandsTuple._2
323+ let rand = (toInt(sha256_16Kb(rsaSig)) % (maxBalanceLockInterval - minBalanceLockInterval))
324+ let randLockInterval = (minBalanceLockInterval + (if ((0 > rand))
325+ then -(rand)
326+ else rand))
327+ (startHeight + randLockInterval)
328+ }
329+ }
330+
331+
332+func abs (x) = if ((0 > x))
333+ then -(x)
334+ else x
335+
336+
337+func selectNode (unleaseAmount) = {
338+ let amountToLease = ((wavesBalance(neutrinoContract).available - unleaseAmount) - getReservedAmountForSponsorship())
339+ let oldLeased0 = getNumberByKey(getLeaseAmountKey(0))
340+ let oldLeased1 = getNumberByKey(getLeaseAmountKey(1))
341+ let newLeased0 = (amountToLease + oldLeased0)
342+ let newLeased1 = (amountToLease + oldLeased1)
343+ if (if ((newLeased0 > 0))
344+ then true
345+ else (newLeased1 > 0))
346+ then {
347+ let delta0 = abs((newLeased0 - oldLeased1))
348+ let delta1 = abs((newLeased1 - oldLeased0))
349+ if ((delta1 >= delta0))
350+ then $Tuple2(0, newLeased0)
351+ else $Tuple2(1, newLeased1)
352+ }
353+ else $Tuple2(-1, 0)
354+ }
355+
356+
357+func prepareUnleaseAndLease (unleaseAmount) = {
358+ let $t01621216300 = selectNode(unleaseAmount)
359+ let nodeIndex = $t01621216300._1
360+ let newLeaseAmount = $t01621216300._2
361+ if ((newLeaseAmount > 0))
362+ then {
363+ let leaseIdKey = getLeaseIdKey(nodeIndex)
364+ let oldLease = getBinary(this, leaseIdKey)
365+ let unleaseOrEmpty = if (isDefined(oldLease))
366+ then [LeaseCancel(value(oldLease))]
367+ else nil
368+ let leaseAmountKey = getLeaseAmountKey(nodeIndex)
369+ let lease = Lease(getStakingNodeAddressByIndex(nodeIndex), newLeaseAmount)
370+ (unleaseOrEmpty ++ [lease, BinaryEntry(leaseIdKey, calculateLeaseId(lease)), IntegerEntry(getLeaseAmountKey(nodeIndex), newLeaseAmount)])
371+ }
372+ else nil
373+ }
374+
375+
376+func getDora2NSBTInfo () = {
377+ let dora2Contract = addressFromStringValue(getStringValue(this, keyDora2Contract))
378+ $Tuple2(valueOrErrorMessage(getInteger(dora2Contract, keyDora2Price(dora2NsbtSymbol)), "NSBT price is undefined"), valueOrElse(getInteger(dora2Contract, keyDora2LastHeight(dora2NsbtSymbol)), 0))
379+ }
380+
381+
382+func thisOnly (i) = if ((i.caller != this))
383+ then throw("Permission denied: this contract only allowed")
384+ else true
385+
386+
214387 @Callable(i)
215-func swapWavesToNeutrino () = {
216- let pmt = value(i.payments[0])
217- let account = toString(i.caller)
218- if ((minWavesSwapAmount > pmt.amount))
219- then throw((("The specified Waves amount is less than the required minimum of " + toString(minWavesSwapAmount)) + " wavelets."))
220- else if (isDefined(pmt.assetId))
221- then throw("Only Waves token is allowed for swapping.")
222- else if (isBlocked)
223- then throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
224- else if ((getUnlockBalanceBlock(account) > height))
225- then throw((("await " + toString((getUnlockBalanceBlock(account) - height))) + " blocks"))
226- else if (if ((getNeutrinoLockedBalance(account) != 0))
227- then true
228- else (getWavesLockedBalance(account) != 0))
229- then throw("please withdraw locked funds first")
230- else [IntegerEntry(getWavesLockedBalanceKey(account), pmt.amount), IntegerEntry(getBalanceUnlockBlockKey(account), (height + balanceWavesLockInterval)), IntegerEntry(WavesLockedBalanceKey, (wavesLockedBalance + pmt.amount))]
388+func prepareUnleaseAndLeaseWrapper (unleaseAmount) = {
389+ let checkCaller = [thisOnly(i)]
390+ if ((checkCaller == checkCaller))
391+ then prepareUnleaseAndLease(unleaseAmount)
392+ else throw("Strict value is not equal to itself.")
231393 }
232394
233395
234396
235397 @Callable(i)
236-func swapNeutrinoToWaves () = {
237- let pmt = value(i.payments[0])
238- let account = toString(i.caller)
239- if ((minNeutrinoSwapAmount > pmt.amount))
240- then throw((("The specified Neutrino amount is less than the required minimum of " + toString(minNeutrinoSwapAmount)) + " Neutrino cents."))
241- else if (isBlocked)
242- then throw("The contract is blocked by EMERGENCY SHUTDOWN. Please wait for reactivation by emergency oracles.")
243- else if ((pmt.assetId != neutrinoAssetId))
244- then throw("Only appropriate Neutrino tokens are allowed for swapping.")
245- else if ((getUnlockBalanceBlock(account) > height))
246- then throw((("await " + toString((getUnlockBalanceBlock(account) - height))) + " blocks"))
247- else if (if ((getNeutrinoLockedBalance(account) != 0))
248- then true
249- else (getWavesLockedBalance(account) != 0))
250- then throw("please withdraw locked funds first")
251- else [IntegerEntry(getNeutrinoLockedBalanceKey(account), pmt.amount), IntegerEntry(getBalanceUnlockBlockKey(account), (height + balanceNeutrinoLockInterval)), IntegerEntry(NeutrinoLockedBalanceKey, (neutrinoLockedBalance + pmt.amount))]
398+func constructor (neutrinoAssetIdPrm,bondAssetIdPrm,auctionContractPrm,liquidationContractPrm,rpdContractPrm,controlContractPrm,nodeOracleProviderPubKeyPrm,rsaRandPublicKeyPrm,balanceWavesLockIntervalPrm,balanceNeutrinoLockIntervalPrm,minWavesSwapAmountPrm,minNeutrinoSwapAmountPrm,neutrinoOutFeePartPrm,wavesOutFeePartPrm) = {
399+ let checkCaller = thisOnly(i)
400+ if ((checkCaller == checkCaller))
401+ then [StringEntry(NeutrinoAssetIdKey, neutrinoAssetIdPrm), StringEntry(BondAssetIdKey, bondAssetIdPrm), StringEntry(AuctionContractKey, auctionContractPrm), StringEntry(LiquidationContractKey, liquidationContractPrm), StringEntry(RPDContractKey, rpdContractPrm), StringEntry(ControlContractKey, controlContractPrm), StringEntry(NodeOracleProviderPubKeyKey, nodeOracleProviderPubKeyPrm), StringEntry(RsaRandPublic58Key, rsaRandPublicKeyPrm), IntegerEntry(BalanceWavesLockIntervalKey, balanceWavesLockIntervalPrm), IntegerEntry(BalanceNeutrinoLockIntervalKey, balanceNeutrinoLockIntervalPrm), IntegerEntry(MinWavesSwapAmountKey, minWavesSwapAmountPrm), IntegerEntry(MinNeutrinoSwapAmountKey, minNeutrinoSwapAmountPrm), IntegerEntry(NeutrinoOutFeePartKey, neutrinoOutFeePartPrm), IntegerEntry(WavesOutFeePartKey, wavesOutFeePartPrm)]
402+ else throw("Strict value is not equal to itself.")
252403 }
253404
254405
255406
256407 @Callable(i)
257-func withdraw (account,index) = {
408+func constructorV2 (gNsbtContract,nsbtLockContract,dora2Contract,quickSwapDelay,quickSwapLimitDuration,dora2LastHeightLimit) = {
409+ let checkCaller = thisOnly(i)
410+ if ((checkCaller == checkCaller))
411+ then [StringEntry(keyGNsbtContract, gNsbtContract), StringEntry(keyNsbtLockContract, nsbtLockContract), StringEntry(keyDora2Contract, dora2Contract), IntegerEntry(keyQuickSwapDelay, quickSwapDelay), IntegerEntry(keyQuickSwapLimitDuration, quickSwapLimitDuration), IntegerEntry(keyDora2LastHeightLimit, dora2LastHeightLimit)]
412+ else throw("Strict value is not equal to itself.")
413+ }
414+
415+
416+
417+@Callable(i)
418+func commonSwap (swapType,amount,account,txId) = {
419+ let checkCaller = thisOnly(i)
420+ if ((checkCaller == checkCaller))
421+ then {
422+ let minSwapAmount = minSwapAmountREAD(swapType)
423+ let totalLocked = totalLockedREAD(swapType)
424+ let totalLockedByUser = totalLockedByUserREAD(swapType, account)
425+ let nodeAddress = getStakingNodeByIndex(0)
426+ let balanceLockMaxInterval = if ((nodeAddress == account))
427+ then nodeBalanceLockIntervalREAD()
428+ else balanceLockIntervalREAD(swapType)
429+ let selfUnlockHeight = (height + balanceLockMaxInterval)
430+ if ((minSwapAmount > amount))
431+ then minSwapAmountFAIL(swapType, minSwapAmount)
432+ else if (isBlocked)
433+ then emergencyShutdownFAIL()
434+ else {
435+ let leasePart = if ((swapType == "waves"))
436+ then prepareUnleaseAndLease(0)
437+ else nil
438+ ([IntegerEntry(totalLockedByUserKEY(swapType, account), (totalLockedByUser + amount)), IntegerEntry(getBalanceUnlockBlockKey(account), selfUnlockHeight), IntegerEntry(totalLockedKEY(swapType), (totalLocked + amount)), StringEntry(swapKEY(account, txId), pendingSwapDATA(swapType, amount, selfUnlockHeight))] ++ leasePart)
439+ }
440+ }
441+ else throw("Strict value is not equal to itself.")
442+ }
443+
444+
445+
446+@Callable(i)
447+func commonWithdraw (account,index,swapTxId,rsaSig) = {
258448 let userAddress = addressFromStringValue(account)
259- let feeManagerAddress = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(this, FeesManagerAddressKey), (FeesManagerAddressKey + " is not specified"))), (FeesManagerAddressKey + " invalid address format"))
260- let unlockHeight = getUnlockBalanceBlock(account)
261- let userWavesLockedBalance = getWavesLockedBalance(account)
262- let userNeutrinoLockedBalance = getNeutrinoLockedBalance(account)
263- let indexHeight = getHeightPriceByIndex(index)
264- let prevIndexHeight = getHeightPriceByIndex((index - 1))
265- let priceByIndex = getPriceHistory(indexHeight)
266- let neutrinoAmountGross = convertWavesToNeutrino(userWavesLockedBalance, priceByIndex)
267- let wavesAmountGross = convertNeutrinoToWaves(userNeutrinoLockedBalance, priceByIndex)
268- let neutrinoOutFeePart = valueOrElse(getInteger(this, NeutrinoOutFeePartKey), DEFAULTSWAPFEE)
269- let wavesOutFeePart = valueOrElse(getInteger(this, WavesOutFeePartKey), DEFAULTSWAPFEE)
270- let neutrinoPayoutsArray = applyFees(neutrinoAmountGross, neutrinoOutFeePart)
271- let wavesPayoutsArray = applyFees(wavesAmountGross, wavesOutFeePart)
272- if (isBlocked)
273- then throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
274- else if ((unlockHeight > height))
275- then throw((("please wait for: " + toString(unlockHeight)) + " block height to withdraw WAVES funds"))
276- else if (if (if ((index > priceIndex))
277- then true
278- else (unlockHeight > indexHeight))
279- then true
280- else if ((prevIndexHeight != 0))
281- then (prevIndexHeight >= unlockHeight)
282- else false)
283- then throw(((((((((("invalid price history index: index=" + toString(index)) + " priceIndex=") + toString(priceIndex)) + " indexHeight=") + toString(indexHeight)) + " unlockHeight=") + toString(unlockHeight)) + " prevIndexHeight=") + toString(prevIndexHeight)))
284- else if (if ((0 >= neutrinoAmountGross))
285- then (0 >= wavesAmountGross)
286- else false)
287- then throw("balance equals zero")
288- else if (if ((0 > neutrinoOutFeePart))
449+ let checkCaller = thisOnly(i)
450+ if ((checkCaller == checkCaller))
451+ then {
452+ let dataArray = swapDataFailOrREAD(account, swapTxId)
453+ let selfUnlockHeight = parseIntValue(dataArray[sIdxSelfUnlockHeight])
454+ let swapType = dataArray[sIdxSwapType]
455+ let inAmount = parseIntValue(dataArray[sIdxInAmount])
456+ let swapStatus = dataArray[sIdxStatus]
457+ let startHeight = parseIntValue(dataArray[sIdxStartHeight])
458+ let isQuick = (dataArray[sIdxIsQuick] == "true")
459+ let checkSwapType = if (if ((swapType != "waves"))
460+ then (swapType != "neutrino")
461+ else false)
462+ then throw(("Unsupported swap type " + swapType))
463+ else true
464+ if ((checkSwapType == checkSwapType))
465+ then {
466+ let outFeePart = valueOrElse(getInteger(this, outFeePartKEY(swapType)), DEFAULTSWAPFEE)
467+ let totalLocked = totalLockedREAD(swapType)
468+ let totalLockedByUser = totalLockedByUserREAD(swapType, account)
469+ let unlockHeight = if (isQuick)
470+ then (startHeight + getIntegerValue(this, keyQuickSwapDelay))
471+ else if ((rsaSig == base58''))
472+ then selfUnlockHeight
473+ else randUnlockHeightOrFail(swapTxId, rsaSig, swapType, startHeight, $Tuple2(parseIntValue(dataArray[sIdxMinRand]), parseIntValue(dataArray[sIdxMaxRand])))
474+ let indexHeight = getHeightPriceByIndex(index)
475+ let prevIndexHeight = getHeightPriceByIndex((index - 1))
476+ let priceByIndex = getPriceHistory(indexHeight)
477+ let $t02234322539 = if ((swapType == "waves"))
478+ then $Tuple2(convertWavesToNeutrino(inAmount, priceByIndex), neutrinoAssetId)
479+ else $Tuple2(convertNeutrinoToWaves(inAmount, priceByIndex), unit)
480+ let outAmountGross = $t02234322539._1
481+ let outAsset = $t02234322539._2
482+ let payoutsArray = applyFees(outAmountGross, outFeePart)
483+ let outNetAmount = payoutsArray[IdxNetAmount]
484+ let outFeeAmount = payoutsArray[IdxFeeAmount]
485+ let checks = [if (isBlocked)
486+ then emergencyShutdownFAIL()
487+ else true, if ((swapStatus != "PENDING"))
488+ then throw("swap has been already processed")
489+ else true, if ((unlockHeight > height))
490+ then throw((("please wait for: " + toString(unlockHeight)) + " block height to withdraw funds"))
491+ else true, if (if (if ((index > priceIndex))
289492 then true
290- else (0 > wavesOutFeePart))
291- then throw(((("invalid fees data: neutrinoOutFeePart=" + toString(neutrinoOutFeePart)) + " wavesOutFeePart=") + toString(wavesOutFeePart)))
292- else [IntegerEntry(getWavesLockedBalanceKey(account), 0), IntegerEntry(getNeutrinoLockedBalanceKey(account), 0), IntegerEntry(WavesLockedBalanceKey, (wavesLockedBalance - userWavesLockedBalance)), IntegerEntry(NeutrinoLockedBalanceKey, (neutrinoLockedBalance - userNeutrinoLockedBalance)), ScriptTransfer(userAddress, wavesPayoutsArray[IdxNetAmount], unit), ScriptTransfer(feeManagerAddress, wavesPayoutsArray[IdxFeeAmount], unit), ScriptTransfer(userAddress, neutrinoPayoutsArray[IdxNetAmount], neutrinoAssetId), ScriptTransfer(feeManagerAddress, neutrinoPayoutsArray[IdxFeeAmount], neutrinoAssetId)]
493+ else (unlockHeight > indexHeight))
494+ then true
495+ else if ((prevIndexHeight != 0))
496+ then (prevIndexHeight >= unlockHeight)
497+ else false)
498+ then priceIndexFAIL(index, priceIndex, indexHeight, unlockHeight, prevIndexHeight)
499+ else true, if ((0 >= payoutsArray[IdxGrossAmount]))
500+ then throw("balance equals zero")
501+ else true, if (if ((0 > outFeePart))
502+ then true
503+ else (outFeePart >= PAULI))
504+ then throw(((("invalid outFeePart config for " + swapType) + " swap: outFeePart=") + toString(outFeePart)))
505+ else true]
506+ if ((checks == checks))
507+ then {
508+ let leasePart = if (if ((swapType == "neutrino"))
509+ then (outAmountGross > 0)
510+ else false)
511+ then invoke(this, "prepareUnleaseAndLeaseWrapper", [outAmountGross], nil)
512+ else unit
513+ if ((leasePart == leasePart))
514+ then {
515+ let sendFee = invoke(addressFromStringValue(getStringValue(this, keyGNsbtContract)), "deposit", nil, [AttachedPayment(outAsset, outFeeAmount)])
516+ if ((sendFee == sendFee))
517+ then [IntegerEntry(totalLockedByUserKEY(swapType, account), (totalLockedByUser - inAmount)), IntegerEntry(totalLockedKEY(swapType), (totalLocked - inAmount)), ScriptTransfer(userAddress, outNetAmount, outAsset), StringEntry(swapKEY(account, swapTxId), finishSwapDATA(dataArray, priceByIndex, outNetAmount, outFeeAmount, unlockHeight, index, toBase58String(i.transactionId)))]
518+ else throw("Strict value is not equal to itself.")
519+ }
520+ else throw("Strict value is not equal to itself.")
521+ }
522+ else throw("Strict value is not equal to itself.")
523+ }
524+ else throw("Strict value is not equal to itself.")
525+ }
526+ else throw("Strict value is not equal to itself.")
527+ }
528+
529+
530+
531+@Callable(i)
532+func swap (swapType) = {
533+ let accelerate = true
534+ let wavesToNeutrino = (swapType == "waves")
535+ let neutrinoToWaves = (swapType == "neutrino")
536+ let pmt = value(i.payments[0])
537+ let account = toString(i.caller)
538+ let swapTxId = toBase58String(i.transactionId)
539+ if (if (wavesToNeutrino)
540+ then (pmt.assetId != unit)
541+ else false)
542+ then throw("Only Waves token is allowed for swapping.")
543+ else if (if (neutrinoToWaves)
544+ then (pmt.assetId != neutrinoAssetId)
545+ else false)
546+ then throw("Only appropriate Neutrino tokens are allowed for swapping.")
547+ else if (if (!(wavesToNeutrino))
548+ then !(neutrinoToWaves)
549+ else false)
550+ then throw("Invalid swap type")
551+ else {
552+ let commonSwapInv = invoke(this, "commonSwap", [swapType, pmt.amount, account, swapTxId], nil)
553+ if ((commonSwapInv == commonSwapInv))
554+ then {
555+ let accelerateInv = if (accelerate)
556+ then invoke(this, "accelerate", [account, swapTxId], nil)
557+ else true
558+ if ((accelerateInv == accelerateInv))
559+ then nil
560+ else throw("Strict value is not equal to itself.")
561+ }
562+ else throw("Strict value is not equal to itself.")
563+ }
564+ }
565+
566+
567+
568+@Callable(i)
569+func accelerate (account,swapTxId) = {
570+ let checkCaller = thisOnly(i)
571+ if ((checkCaller == checkCaller))
572+ then {
573+ let userAddress = addressFromStringValue(account)
574+ let dataArray = swapDataFailOrREAD(account, swapTxId)
575+ let swapType = dataArray[sIdxSwapType]
576+ let inAmount = parseIntValue(dataArray[sIdxInAmount])
577+ let swapStatus = dataArray[sIdxStatus]
578+ let isQuick = (dataArray[sIdxIsQuick] == "true")
579+ let $t02544625654 = match invoke(this, "quickSwapLimitREADONLY", [toString(userAddress)], nil) {
580+ case r: (Int, Int) =>
581+ $Tuple2(r._1, r._2)
582+ case _ =>
583+ throw("Type casting error")
584+ }
585+ let quickSwapLimitTotal = $t02544625654._1
586+ let quickSwapUserSpent = $t02544625654._2
587+ let quickSwapLimit = (quickSwapLimitTotal - quickSwapUserSpent)
588+ let priceByIndex = getPriceHistory(getHeightPriceByIndex(priceIndex))
589+ let swapUsdnVolume = if ((swapType == "neutrino"))
590+ then inAmount
591+ else convertWavesToNeutrino(inAmount, priceByIndex)
592+ let checks = [if ((swapStatus != "PENDING"))
593+ then throw("Swap has been already processed")
594+ else true, if (isQuick)
595+ then throw("Swap has been already accelerated")
596+ else true, if ((swapUsdnVolume > quickSwapLimit))
597+ then throw(((("You have exceeded the quick swaps limit! Requested: " + toString(swapUsdnVolume)) + ", available: ") + toString(quickSwapLimit)))
598+ else true]
599+ if ((checks == checks))
600+ then [IntegerEntry(keyQuickSwapUserSpentInPeriod(userAddress), (swapUsdnVolume + quickSwapUserSpent)), IntegerEntry(keyUserLastQuickSwapHeight(userAddress), height), StringEntry(swapKEY(account, swapTxId), accelerateSwapDATA(dataArray))]
601+ else throw("Strict value is not equal to itself.")
602+ }
603+ else throw("Strict value is not equal to itself.")
604+ }
605+
606+
607+
608+@Callable(i)
609+func withdraw (account,index,swapTxId) = {
610+ let result = invoke(this, "commonWithdraw", [account, index, swapTxId, base58''], nil)
611+ if ((result == result))
612+ then nil
613+ else throw("Strict value is not equal to itself.")
614+ }
615+
616+
617+
618+@Callable(i)
619+func withdrawRand (account,index,swapTxId,rsaSig) = {
620+ let result = invoke(this, "commonWithdraw", [account, index, swapTxId, rsaSig], nil)
621+ if ((result == result))
622+ then nil
623+ else throw("Strict value is not equal to itself.")
293624 }
294625
295626
296627
297628 @Callable(i)
298629 func transferToAuction () = {
299630 let auctionNBAmount = (neutrinoSupply - assetBalance(addressFromStringValue(auctionContract), bondAssetId))
300631 let surplusWithLiquidation = (surplus - assetBalance(addressFromStringValue(liquidationContract), neutrinoAssetId))
301632 if (isBlocked)
302633 then throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
303634 else if ((auctionNBAmount > (1 * PAULI)))
304635 then [ScriptTransfer(addressFromStringValue(auctionContract), auctionNBAmount, bondAssetId)]
305636 else if ((surplusWithLiquidation >= (1 * PAULI)))
306637 then [ScriptTransfer(addressFromStringValue(liquidationContract), surplusWithLiquidation, neutrinoAssetId)]
307638 else throw(((((((("bond were generated or do not need it. Deficit:" + toString(auctionNBAmount)) + "|") + toString(0)) + ". Surplus:") + toString(surplusWithLiquidation)) + "|") + toString(surplus)))
308639 }
309640
310641
642+
643+@Callable(i)
644+func acceptWaves () = if ((i.caller != addressFromStringValue(auctionContract)))
645+ then throw("Currently only auction contract is allowed to call")
646+ else $Tuple2(prepareUnleaseAndLease(0), "success")
647+
648+
649+
650+@Callable(i)
651+func calcTotalQuickSwapLimitREADONLY (gNsbtAmount) = {
652+ let $t02870528762 = getDora2NSBTInfo()
653+ let nsbtPrice = $t02870528762._1
654+ let nsbtPriceLastHeight = $t02870528762._2
655+ let check = if (((height - nsbtPriceLastHeight) > getIntegerValue(this, keyDora2LastHeightLimit)))
656+ then throw("NSBT price is outdated")
657+ else true
658+ if ((check == check))
659+ then $Tuple2(nil, fraction(gNsbtAmount, nsbtPrice, WAVELET))
660+ else throw("Strict value is not equal to itself.")
661+ }
662+
663+
664+
665+@Callable(i)
666+func quickSwapLimitREADONLY (userAddressStr) = {
667+ let limitAvalableWaves = toString((10000 * 100000000))
668+ let limitAvalableUsdn = toString((100000 * 1000000))
669+ let limitRemainingBlocksToReset = toString(940)
670+ $Tuple2(nil, makeString(["%d%d%d", limitAvalableWaves, limitAvalableUsdn, limitRemainingBlocksToReset], SEP))
671+ }
672+
673+
311674 @Verifier(tx)
312675 func verify () = {
313676 let id = toBase58String(tx.id)
677+ let minSignaturesNumber = 3
314678 let count = ((((if (sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(pubKeyAdminsList[0])))
315679 then 1
316680 else 0) + (if (sigVerify(tx.bodyBytes, tx.proofs[1], fromBase58String(pubKeyAdminsList[1])))
317681 then 1
318682 else 0)) + (if (sigVerify(tx.bodyBytes, tx.proofs[2], fromBase58String(pubKeyAdminsList[2])))
319683 then 1
320684 else 0)) + (if (sigVerify(tx.bodyBytes, tx.proofs[3], fromBase58String(pubKeyAdminsList[3])))
321685 then 2
322686 else 0))
687+ let isSignaturesValid = (count >= minSignaturesNumber)
323688 match tx {
324- case leasingTx: LeaseCancelTransaction|LeaseTransaction =>
325- sigVerify(leasingTx.bodyBytes, leasingTx.proofs[0], nodeOracleProviderPubKey)
326689 case sponsorTx: SponsorFeeTransaction =>
327- if (checkIsValidMinSponsoredFee(sponsorTx))
328- then (count >= 3)
690+ if (isSignaturesValid)
691+ then checkIsValidMinSponsoredFee(sponsorTx)
329692 else false
330693 case _ =>
331- (count >= 3)
694+ isSignaturesValid
332695 }
333696 }
334697

github/deemru/w8io/6500d08 
120.38 ms