tx · FtZp6uV39UF5dVuX19wNmQjkjBnLPGBRjJSG6mGXE11K

3MyDtNTkCNyRCw3o2qv5BPPS7vvUosiQe6F:  -0.01400000 Waves

2019.11.15 17:09 [766304] smart account 3MyDtNTkCNyRCw3o2qv5BPPS7vvUosiQe6F > SELF 0.00000000 Waves

{ "type": 13, "id": "FtZp6uV39UF5dVuX19wNmQjkjBnLPGBRjJSG6mGXE11K", "fee": 1400000, "feeAssetId": null, "timestamp": 1573826967582, "version": 1, "sender": "3MyDtNTkCNyRCw3o2qv5BPPS7vvUosiQe6F", "senderPublicKey": "3z5txV1G5GKezwMRCHZDkLThqb1Yggepxvi2wq6iP6oz", "proofs": [ "34UzHTjezEqGVyKG17Ymnn1e6PURWv6CEVa8zoCMZFGwh6BhvUNn5XtNZRVpzFFP1X1Xw42Wc3gZhVTGvkEvLYgs" ], "script": "base64:AAIDAAAAAAAAACwIARIAEgASBQoDCAEIEgASAwoBCBIAEgYKBAgBAQgSAwoBCBIHCgUICAEBCAAAAGYBAAAADmdldE51bWJlckJ5S2V5AAAAAQAAAANrZXkEAAAAByRtYXRjaDAJAAQaAAAAAgUAAAAEdGhpcwUAAAADa2V5AwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAANJbnQEAAAAAWEFAAAAByRtYXRjaDAFAAAAAWEAAAAAAAAAAAABAAAADmdldFN0cmluZ0J5S2V5AAAAAQAAAANrZXkEAAAAByRtYXRjaDAJAAQdAAAAAgUAAAAEdGhpcwUAAAADa2V5AwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAAZTdHJpbmcEAAAAAWEFAAAAByRtYXRjaDAFAAAAAWECAAAAAAEAAAAMZ2V0Qm9vbEJ5S2V5AAAAAQAAAANrZXkEAAAAByRtYXRjaDAJAAQbAAAAAgUAAAAEdGhpcwUAAAADa2V5AwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAAdCb29sZWFuBAAAAAFhBQAAAAckbWF0Y2gwBQAAAAFhBwEAAAAYZ2V0TnVtYmVyQnlBZGRyZXNzQW5kS2V5AAAAAgAAAAdhZGRyZXNzAAAAA2tleQQAAAAHJG1hdGNoMAkABBoAAAACCQEAAAAcQGV4dHJVc2VyKGFkZHJlc3NGcm9tU3RyaW5nKQAAAAEFAAAAB2FkZHJlc3MFAAAAA2tleQMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAADSW50BAAAAAFhBQAAAAckbWF0Y2gwBQAAAAFhAAAAAAAAAAAAAQAAABhnZXRTdHJpbmdCeUFkZHJlc3NBbmRLZXkAAAACAAAAB2FkZHJlc3MAAAADa2V5BAAAAAckbWF0Y2gwCQAEHQAAAAIJAQAAABxAZXh0clVzZXIoYWRkcmVzc0Zyb21TdHJpbmcpAAAAAQUAAAAHYWRkcmVzcwUAAAADa2V5AwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAAZTdHJpbmcEAAAAAWEFAAAAByRtYXRjaDAFAAAAAWECAAAAAAEAAAAWZ2V0Qm9vbEJ5QWRkcmVzc0FuZEtleQAAAAIAAAAHYWRkcmVzcwAAAANrZXkEAAAAByRtYXRjaDAJAAQbAAAAAgkBAAAAHEBleHRyVXNlcihhZGRyZXNzRnJvbVN0cmluZykAAAABBQAAAAdhZGRyZXNzBQAAAANrZXkDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAB0Jvb2xlYW4EAAAAAWEFAAAAByRtYXRjaDAFAAAAAWEHAAAAAAxTRU5EVFhFWFBJUkUAAAAAAAAAAB4AAAAAD0xJU1RTUExJVFNZTUJPTAIAAAABXwAAAAAOTElTVERBVEFTWU1CT0wCAAAAASsAAAAAB1dBVkVMRVQAAAAAAAX14QAAAAAABVBBVUxJAAAAAAAAAABkAAAAAA1DUllUSUNBTFNIQVJFAAAAAAAAAAAUAAAAAAxMRUFTSU5HU0hBUkUAAAAAAAAAAFoAAAAADUxFQVNJTlRYQ09VTlQAAAAAAAAAAAoAAAAADURFRklDSVRPRkZTRVQAAAAAAAAAAAoAAAAADFdBVkVTQVNTRVRJRAIAAAAFd2F2ZXMAAAAACENBTkNFTEVEAgAAAAhjYW5jZWxlZAAAAAADTkVXAgAAAANuZXcAAAAAEk5ldXRyaW5vQXNzZXRJZEtleQIAAAARbmV1dHJpbm9fYXNzZXRfaWQAAAAADkJvbmRBc3NldElkS2V5AgAAAA1ib25kX2Fzc2V0X2lkAAAAABJSZXNlcnZlQ29udHJhY3RLZXkCAAAAEHJlc2VydmVfY29udHJhY3QAAAAAEkF1Y3Rpb25Db250cmFjdEtleQIAAAAQYXVjdGlvbl9jb250cmFjdAAAAAAWTGlxdWlkYXRpb25Db250cmFjdEtleQIAAAAUbGlxdWlkYXRpb25fY29udHJhY3QAAAAADlJQRENvbnRyYWN0S2V5AgAAAAxycGRfY29udHJhY3QAAAAAEUNvbnRvbENvbnRyYWN0S2V5AgAAABBjb250cm9sX2NvbnRyYWN0AAAAABZCYWxhbmNlTG9ja0ludGVydmFsS2V5AgAAABViYWxhbmNlX2xvY2tfaW50ZXJ2YWwAAAAAFU1pbldhdmVzU3dhcEFtb3VudEtleQIAAAAVbWluX3dhdmVzX3N3YXBfYW1vdW50AAAAABhNaW5OZXV0cmlub1N3YXBBbW91bnRLZXkCAAAAGG1pbl9uZXV0cmlub19zd2FwX2Ftb3VudAAAAAAOTm9kZUFkZHJlc3NLZXkCAAAADG5vZGVfYWRkcmVzcwAAAAAVTm9kZU9yYWNsZVByb3ZpZGVyS2V5AgAAABRvcmFjbGVfbm9kZV9wcm92aWRlcgAAAAASTGVhc2luZ0ludGVydmFsS2V5AgAAABBsZWFzaW5nX2ludGVydmFsAAAAAA1SUERCYWxhbmNlS2V5AgAAAAtycGRfYmFsYW5jZQEAAAAYZ2V0UlBEQ29udHJhY3RCYWxhbmNlS2V5AAAAAQAAAAdhc3NldElkCQABLAAAAAIJAAEsAAAAAgUAAAANUlBEQmFsYW5jZUtleQIAAAABXwkAAlgAAAABBQAAAAdhc3NldElkAAAAABFUb3RhbE9yZGVyYm9va0tleQIAAAAPdG90YWxfb3JkZXJib29rAAAAABxUb3RhbExpcXVpZGF0aW9uT3JkZXJib29rS2V5AgAAABt0b3RhbF9saXF1aWRhdGlvbl9vcmRlcmJvb2sAAAAACFByaWNlS2V5AgAAAAVwcmljZQAAAAANUHJpY2VJbmRleEtleQIAAAALcHJpY2VfaW5kZXgAAAAADElzQmxvY2tlZEtleQIAAAAKaXNfYmxvY2tlZAAAAAAVTGVhc2luZ0V4cGlyZUJsb2NrS2V5AgAAABRsZWFzaW5nX2V4cGlyZV9ibG9jawAAAAAOSXNSZWJhbGFuY2VLZXkCAAAADGlzX3JlYmFsYW5jZQAAAAARTGVhc2luZ1R4Q291bnRLZXkCAAAADWxlYXNpbmdfaW5kZXgAAAAAEExlYXNpbmdBbW91bnRLZXkCAAAADmxlYXNpbmdfYW1vdW50AQAAABJnZXRQcmljZUhpc3RvcnlLZXkAAAABAAAABWJsb2NrCQABLAAAAAIJAAEsAAAAAgUAAAAIUHJpY2VLZXkCAAAAAV8JAAGkAAAAAQUAAAAFYmxvY2sBAAAAGGdldEhlaWdodFByaWNlQnlJbmRleEtleQAAAAEAAAAFaW5kZXgJAAEsAAAAAgkAASwAAAACBQAAAA1QcmljZUluZGV4S2V5AgAAAAFfCQABpAAAAAEFAAAABWluZGV4AAAAAA9SUERTeW5jSW5kZXhLZXkCAAAADnJwZF9zeW5jX2luZGV4AQAAACBnZXRSUERTbmFwc2hvdENvbnRyYWN0QmFsYW5jZUtleQAAAAIAAAAFY291bnQAAAAHYXNzZXRJZAkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACBQAAAA1SUERCYWxhbmNlS2V5AgAAAAFfCQACWAAAAAEFAAAAB2Fzc2V0SWQCAAAAAV8JAAGkAAAAAQUAAAAFY291bnQBAAAAHWdldENhbmNlbExlYXNlVHhSZXNlcnZlRmVlS2V5AAAAAQAAAARoYXNoCQABLAAAAAIJAAEsAAAAAgIAAAAbY2FuY2VsX2xlYXNlX3R4X3Jlc2VydmVfZmVlAgAAAAFfBQAAAARoYXNoAQAAABpnZXRBY2NvdW50TG9ja2VkQmFsYW5jZUtleQAAAAIAAAAFb3duZXIAAAAHYXNzZXRJZAkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAIYmFsYW5jZV8FAAAAB2Fzc2V0SWQCAAAAAV8FAAAABW93bmVyAQAAABhnZXRCYWxhbmNlVW5sb2NrQmxvY2tLZXkAAAABAAAABW93bmVyCQABLAAAAAICAAAADmJhbGFuY2VfYmxvY2tfBQAAAAVvd25lcgEAAAAPZ2V0UlBEUHJvZml0S2V5AAAAAQAAAAVjb3VudAkAASwAAAACCQABLAAAAAICAAAACnJwZF9wcm9maXQCAAAAAV8JAAGkAAAAAQUAAAAFY291bnQBAAAAE2dldExvY2tlZEJhbGFuY2VLZXkAAAABAAAAB2Fzc2V0SWQJAAEsAAAAAgIAAAAIYmFsYW5jZV8FAAAAB2Fzc2V0SWQBAAAAE2dldExlYXNlVHhTdGF0dXNLZXkAAAABAAAABGhhc2gJAAEsAAAAAgkAASwAAAACAgAAAA9sZWFzZV90eF9zdGF0dXMCAAAAAV8FAAAABGhhc2gBAAAAGWdldExlYXNlVHhBbW91bnRCeUhhc2hLZXkAAAABAAAABGhhc2gJAAEsAAAAAgkAASwAAAACBQAAABBMZWFzaW5nQW1vdW50S2V5AgAAAAFfBQAAAARoYXNoAQAAABhnZXRMZWFzZVR4Qnl0ZXNCeUhhc2hLZXkAAAABAAAABGhhc2gJAAEsAAAAAgkAASwAAAACAgAAAAhsZWFzZV90eAIAAAABXwUAAAAEaGFzaAEAAAAcZ2V0TGVhc2VUeEV4cGlyZVNlbmRCbG9ja0tleQAAAAEAAAAEaGFzaAkAASwAAAACCQABLAAAAAICAAAAE2xlYXNpbmdfZXhwaXJlX3NlbmQCAAAAAV8FAAAABGhhc2gBAAAAFmNvbnZlcnROZXV0cmlub1RvV2F2ZXMAAAACAAAABmFtb3VudAAAAAVwcmljZQkAAGkAAAACCQAAaAAAAAIJAABpAAAAAgkAAGgAAAACBQAAAAZhbW91bnQAAAAAAAAAAGQFAAAABXByaWNlBQAAAAdXQVZFTEVUBQAAAAVQQVVMSQEAAAAWY29udmVydFdhdmVzVG9OZXV0cmlubwAAAAIAAAAGYW1vdW50AAAABXByaWNlCQAAaQAAAAIJAABoAAAAAgkAAGkAAAACCQAAaAAAAAIFAAAABmFtb3VudAUAAAAFcHJpY2UAAAAAAAAAAGQFAAAABVBBVUxJBQAAAAdXQVZFTEVUAQAAABVjb252ZXJ0TmV1dHJpbm9Ub0JvbmQAAAABAAAABmFtb3VudAkAAGkAAAACBQAAAAZhbW91bnQFAAAABVBBVUxJAQAAABVjb252ZXJ0Qm9uZFRvTmV1dHJpbm8AAAABAAAABmFtb3VudAkAAGgAAAACBQAAAAZhbW91bnQFAAAABVBBVUxJAQAAABJjb252ZXJ0V2F2ZXNUb0JvbmQAAAACAAAABmFtb3VudAAAAAVwcmljZQkBAAAAFWNvbnZlcnROZXV0cmlub1RvQm9uZAAAAAEJAQAAABZjb252ZXJ0V2F2ZXNUb05ldXRyaW5vAAAAAgUAAAAGYW1vdW50BQAAAAVwcmljZQEAAAAQZ2V0TG9ja2VkQmFsYW5jZQAAAAEAAAAHYXNzZXRJZAkBAAAADmdldE51bWJlckJ5S2V5AAAAAQkBAAAAE2dldExvY2tlZEJhbGFuY2VLZXkAAAABBQAAAAdhc3NldElkAAAAABNsaXF1aWRhdGlvbkNvbnRyYWN0CQEAAAAOZ2V0U3RyaW5nQnlLZXkAAAABBQAAABZMaXF1aWRhdGlvbkNvbnRyYWN0S2V5AAAAABVuZXV0cmlub0Fzc2V0SWRTdHJpbmcJAQAAAA5nZXRTdHJpbmdCeUtleQAAAAEFAAAAEk5ldXRyaW5vQXNzZXRJZEtleQAAAAAPbmV1dHJpbm9Bc3NldElkCQACWQAAAAEFAAAAFW5ldXRyaW5vQXNzZXRJZFN0cmluZwAAAAAPcmVzZXJ2ZUNvbnRyYWN0CQEAAAAOZ2V0U3RyaW5nQnlLZXkAAAABBQAAABJSZXNlcnZlQ29udHJhY3RLZXkAAAAAD2F1Y3Rpb25Db250cmFjdAkBAAAADmdldFN0cmluZ0J5S2V5AAAAAQUAAAASQXVjdGlvbkNvbnRyYWN0S2V5AAAAAAtycGRDb250cmFjdAkBAAAADmdldFN0cmluZ0J5S2V5AAAAAQUAAAAOUlBEQ29udHJhY3RLZXkAAAAAD2NvbnRyb2xDb250cmFjdAkBAAAADmdldFN0cmluZ0J5S2V5AAAAAQUAAAARQ29udG9sQ29udHJhY3RLZXkAAAAADGN1cnJlbnRQcmljZQkBAAAAGGdldE51bWJlckJ5QWRkcmVzc0FuZEtleQAAAAIFAAAAD2NvbnRyb2xDb250cmFjdAUAAAAIUHJpY2VLZXkAAAAACnByaWNlSW5kZXgJAQAAABhnZXROdW1iZXJCeUFkZHJlc3NBbmRLZXkAAAACBQAAAA9jb250cm9sQ29udHJhY3QFAAAADVByaWNlSW5kZXhLZXkAAAAACWlzQmxvY2tlZAkBAAAAFmdldEJvb2xCeUFkZHJlc3NBbmRLZXkAAAACBQAAAA9jb250cm9sQ29udHJhY3QFAAAADElzQmxvY2tlZEtleQAAAAAObGVhc2luZ1R4Q291bnQJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEFAAAAEUxlYXNpbmdUeENvdW50S2V5AAAAAAtpc1JlYmFsYW5jZQkBAAAADGdldEJvb2xCeUtleQAAAAEFAAAADklzUmViYWxhbmNlS2V5AAAAAA9sZWFzaW5nSW50ZXJ2YWwJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEFAAAAEkxlYXNpbmdJbnRlcnZhbEtleQAAAAASbGVhc2luZ0V4cGlyZUJsb2NrCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABBQAAABVMZWFzaW5nRXhwaXJlQmxvY2tLZXkAAAAADWxlYXNpbmdBbW91bnQJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEFAAAAEExlYXNpbmdBbW91bnRLZXkAAAAAC25vZGVBZGRyZXNzCQEAAAAOZ2V0U3RyaW5nQnlLZXkAAAABBQAAAA5Ob2RlQWRkcmVzc0tleQAAAAAVbm9kZU9yYWNsZVByb3ZpZGVyS2V5CQEAAAAOZ2V0U3RyaW5nQnlLZXkAAAABBQAAABVOb2RlT3JhY2xlUHJvdmlkZXJLZXkAAAAADHJwZFN5bmNJbmRleAkBAAAADmdldE51bWJlckJ5S2V5AAAAAQUAAAAPUlBEU3luY0luZGV4S2V5AAAAABNiYWxhbmNlTG9ja0ludGVydmFsCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABBQAAABZCYWxhbmNlTG9ja0ludGVydmFsS2V5AAAAABJtaW5XYXZlc1N3YXBBbW91bnQJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEFAAAAFU1pbldhdmVzU3dhcEFtb3VudEtleQAAAAAVbWluTmV1dHJpbm9Td2FwQW1vdW50CQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABBQAAABhNaW5OZXV0cmlub1N3YXBBbW91bnRLZXkAAAAAB3Jlc2VydmUJAABlAAAAAgkBAAAADHdhdmVzQmFsYW5jZQAAAAEFAAAABHRoaXMJAQAAABBnZXRMb2NrZWRCYWxhbmNlAAAAAQUAAAAMV0FWRVNBU1NFVElEAAAAABVyZXNlcnZlV2l0aG91dExlYXNpbmcJAABlAAAAAgUAAAAHcmVzZXJ2ZQUAAAANbGVhc2luZ0Ftb3VudAAAAAALYm9uZEFzc2V0SWQJAAJZAAAAAQkBAAAADmdldFN0cmluZ0J5S2V5AAAAAQUAAAAOQm9uZEFzc2V0SWRLZXkAAAAACmJvbmRTdXBwbHkJAABlAAAAAggJAQAAAAdleHRyYWN0AAAAAQkAA+wAAAABBQAAAAtib25kQXNzZXRJZAAAAAhxdWFudGl0eQkAA+sAAAACBQAAAAR0aGlzBQAAAAtib25kQXNzZXRJZAAAAAAObmV1dHJpbm9TdXBwbHkJAABkAAAAAgkAAGUAAAACCAkBAAAAB2V4dHJhY3QAAAABCQAD7AAAAAEFAAAAD25ldXRyaW5vQXNzZXRJZAAAAAhxdWFudGl0eQkAA+sAAAACBQAAAAR0aGlzBQAAAA9uZXV0cmlub0Fzc2V0SWQJAQAAABBnZXRMb2NrZWRCYWxhbmNlAAAAAQUAAAAVbmV1dHJpbm9Bc3NldElkU3RyaW5nAAAAAAdzdXJwbHVzCQAAZQAAAAIJAQAAABZjb252ZXJ0V2F2ZXNUb05ldXRyaW5vAAAAAgUAAAAHcmVzZXJ2ZQUAAAAMY3VycmVudFByaWNlBQAAAA5uZXV0cmlub1N1cHBseQAAAAAHZGVmaWNpdAkAAGUAAAACBQAAAA5uZXV0cmlub1N1cHBseQkBAAAAFmNvbnZlcnRXYXZlc1RvTmV1dHJpbm8AAAACBQAAAAdyZXNlcnZlBQAAAAxjdXJyZW50UHJpY2UBAAAAFWdldFJQRENvbnRyYWN0QmFsYW5jZQAAAAEAAAAHYXNzZXRJZAkBAAAAGGdldE51bWJlckJ5QWRkcmVzc0FuZEtleQAAAAIFAAAAC3JwZENvbnRyYWN0CQEAAAAYZ2V0UlBEQ29udHJhY3RCYWxhbmNlS2V5AAAAAQUAAAAHYXNzZXRJZAAAAAAZdG90YWxMaXF1aWRhdGlvbk9yZGVyYm9vawkBAAAAGGdldE51bWJlckJ5QWRkcmVzc0FuZEtleQAAAAIFAAAAD2F1Y3Rpb25Db250cmFjdAUAAAAcVG90YWxMaXF1aWRhdGlvbk9yZGVyYm9va0tleQAAAAAOdG90YWxPcmRlcmJvb2sJAQAAABhnZXROdW1iZXJCeUFkZHJlc3NBbmRLZXkAAAACBQAAAA9hdWN0aW9uQ29udHJhY3QFAAAAEVRvdGFsT3JkZXJib29rS2V5AQAAAA9nZXRQcmljZUhpc3RvcnkAAAABAAAABWJsb2NrCQEAAAAYZ2V0TnVtYmVyQnlBZGRyZXNzQW5kS2V5AAAAAgUAAAAPY29udHJvbENvbnRyYWN0CQEAAAASZ2V0UHJpY2VIaXN0b3J5S2V5AAAAAQUAAAAFYmxvY2sBAAAAFWdldEhlaWdodFByaWNlQnlJbmRleAAAAAEAAAAFaW5kZXgJAQAAABhnZXROdW1iZXJCeUFkZHJlc3NBbmRLZXkAAAACBQAAAA9jb250cm9sQ29udHJhY3QJAQAAABhnZXRIZWlnaHRQcmljZUJ5SW5kZXhLZXkAAAABBQAAAAVpbmRleAEAAAAaZ2V0Q2FuY2VsTGVhc2VUeFJlc2VydmVGZWUAAAABAAAABGhhc2gJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEJAQAAAB1nZXRDYW5jZWxMZWFzZVR4UmVzZXJ2ZUZlZUtleQAAAAEFAAAABGhhc2gBAAAAF2dldEFjY291bnRMb2NrZWRCYWxhbmNlAAAAAgAAAAVvd25lcgAAAAdhc3NldElkCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAaZ2V0QWNjb3VudExvY2tlZEJhbGFuY2VLZXkAAAACBQAAAAVvd25lcgUAAAAHYXNzZXRJZAEAAAAVZ2V0VW5sb2NrQmFsYW5jZUJsb2NrAAAAAQAAAAVvd25lcgkBAAAADmdldE51bWJlckJ5S2V5AAAAAQkBAAAAGGdldEJhbGFuY2VVbmxvY2tCbG9ja0tleQAAAAEFAAAABW93bmVyAQAAAAxnZXRSUERQcm9maXQAAAABAAAABWNvdW50CQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAPZ2V0UlBEUHJvZml0S2V5AAAAAQUAAAAFY291bnQBAAAAEGdldExlYXNlVHhTdGF0dXMAAAABAAAABGhhc2gJAQAAAA5nZXRTdHJpbmdCeUtleQAAAAEJAQAAABNnZXRMZWFzZVR4U3RhdHVzS2V5AAAAAQUAAAAEaGFzaAEAAAAWZ2V0TGVhc2VUeEFtb3VudEJ5SGFzaAAAAAEAAAAEaGFzaAkBAAAADmdldE51bWJlckJ5S2V5AAAAAQkBAAAAGWdldExlYXNlVHhBbW91bnRCeUhhc2hLZXkAAAABBQAAAARoYXNoAQAAABVnZXRMZWFzZVR4Qnl0ZXNCeUhhc2gAAAABAAAABGhhc2gJAQAAAA5nZXRTdHJpbmdCeUtleQAAAAEJAQAAABhnZXRMZWFzZVR4Qnl0ZXNCeUhhc2hLZXkAAAABBQAAAARoYXNoAQAAABlnZXRMZWFzZVR4RXhwaXJlU2VuZEJsb2NrAAAAAQAAAARoYXNoCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAcZ2V0TGVhc2VUeEV4cGlyZVNlbmRCbG9ja0tleQAAAAEFAAAABGhhc2gAAAAJAAAAAWkBAAAAE3N3YXBXYXZlc1RvTmV1dHJpbm8AAAAABAAAAANwbXQJAQAAAAdleHRyYWN0AAAAAQgFAAAAAWkAAAAHcGF5bWVudAQAAAAHYWNjb3VudAkABCUAAAABCAUAAAABaQAAAAZjYWxsZXIDCQAAZgAAAAIFAAAAEm1pbldhdmVzU3dhcEFtb3VudAgFAAAAA3BtdAAAAAZhbW91bnQJAAACAAAAAQkAASwAAAACCQABLAAAAAICAAAALWFuIGFtb3VudCBpcyBsZXNzIHRoYW4gbWluIGF2YWlsYWJsZSBhbW91bnQ6IAkAAaQAAAABBQAAABJtaW5XYXZlc1N3YXBBbW91bnQCAAAACSB3YXZlbGV0cwMJAQAAAAlpc0RlZmluZWQAAAABCAUAAAADcG10AAAAB2Fzc2V0SWQJAAACAAAAAQIAAAASY2FuIHVzZSB3YXZlcyBvbmx5AwUAAAAJaXNCbG9ja2VkCQAAAgAAAAECAAAAWmNvbnRyYWN0IGlzIGJsb2NrZWQgYnkgRU1FUkdFTkNZIFNIVVRET1dOIGFjdGlvbnMgdW50aWxsIHJlYWN0aXZhdGlvbiBieSBlbWVyZ2VuY3kgb3JhY2xlcwMJAABmAAAAAgkBAAAAFWdldFVubG9ja0JhbGFuY2VCbG9jawAAAAEFAAAAB2FjY291bnQFAAAABmhlaWdodAkAAAIAAAABCQABLAAAAAIJAAEsAAAAAgIAAAAGYXdhaXQgCQABpAAAAAEJAABlAAAAAgkBAAAAFWdldFVubG9ja0JhbGFuY2VCbG9jawAAAAEFAAAAB2FjY291bnQFAAAABmhlaWdodAIAAAAHIGJsb2NrcwMJAQAAAAIhPQAAAAIJAQAAABdnZXRBY2NvdW50TG9ja2VkQmFsYW5jZQAAAAIFAAAAB2FjY291bnQFAAAADFdBVkVTQVNTRVRJRAAAAAAAAAAAAAkAAAIAAAABAgAAACJwbGVhc2Ugd2l0aGRyYXcgbG9ja2VkIGZ1bmRzIGZpcnN0CQEAAAAIV3JpdGVTZXQAAAABCQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACCQEAAAAaZ2V0QWNjb3VudExvY2tlZEJhbGFuY2VLZXkAAAACBQAAAAdhY2NvdW50BQAAAAxXQVZFU0FTU0VUSUQIBQAAAANwbXQAAAAGYW1vdW50CQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACCQEAAAAYZ2V0QmFsYW5jZVVubG9ja0Jsb2NrS2V5AAAAAQUAAAAHYWNjb3VudAkAAGQAAAACBQAAAAZoZWlnaHQFAAAAE2JhbGFuY2VMb2NrSW50ZXJ2YWwJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIJAQAAABNnZXRMb2NrZWRCYWxhbmNlS2V5AAAAAQUAAAAMV0FWRVNBU1NFVElECQAAZAAAAAIJAQAAABBnZXRMb2NrZWRCYWxhbmNlAAAAAQUAAAAMV0FWRVNBU1NFVElECAUAAAADcG10AAAABmFtb3VudAUAAAADbmlsAAAAAWkBAAAAE3N3YXBOZXV0cmlub1RvV2F2ZXMAAAAABAAAAANwbXQJAQAAAAdleHRyYWN0AAAAAQgFAAAAAWkAAAAHcGF5bWVudAQAAAAHYWNjb3VudAkABCUAAAABCAUAAAABaQAAAAZjYWxsZXIDCQAAZgAAAAIFAAAAFW1pbk5ldXRyaW5vU3dhcEFtb3VudAgFAAAAA3BtdAAAAAZhbW91bnQJAAACAAAAAQkAASwAAAACCQABLAAAAAICAAAALWFuIGFtb3VudCBpcyBsZXNzIHRoYW4gbWluIGF2YWlsYWJsZSBhbW91bnQ6IAkAAaQAAAABBQAAABVtaW5OZXV0cmlub1N3YXBBbW91bnQCAAAADyBuZXV0cmlubyBjZW50cwMFAAAACWlzQmxvY2tlZAkAAAIAAAABAgAAAFpjb250cmFjdCBpcyBibG9ja2VkIGJ5IEVNRVJHRU5DWSBTSFVURE9XTiBhY3Rpb25zIHVudGlsbCByZWFjdGl2YXRpb24gYnkgZW1lcmdlbmN5IG9yYWNsZXMDCQEAAAACIT0AAAACCAUAAAADcG10AAAAB2Fzc2V0SWQFAAAAD25ldXRyaW5vQXNzZXRJZAkAAAIAAAABAgAAAChjYW4gdXNlIGFwcHJvcHJpYXRlIG5ldXRyaW5vIHRva2VucyBvbmx5AwkAAGYAAAACCQEAAAAVZ2V0VW5sb2NrQmFsYW5jZUJsb2NrAAAAAQUAAAAHYWNjb3VudAUAAAAGaGVpZ2h0CQAAAgAAAAEJAAEsAAAAAgkAASwAAAACAgAAAAZhd2FpdCAJAAGkAAAAAQkAAGUAAAACCQEAAAAVZ2V0VW5sb2NrQmFsYW5jZUJsb2NrAAAAAQUAAAAHYWNjb3VudAUAAAAGaGVpZ2h0AgAAAAcgYmxvY2tzAwkBAAAAAiE9AAAAAgkBAAAAF2dldEFjY291bnRMb2NrZWRCYWxhbmNlAAAAAgUAAAAHYWNjb3VudAUAAAAVbmV1dHJpbm9Bc3NldElkU3RyaW5nAAAAAAAAAAAACQAAAgAAAAECAAAAInBsZWFzZSB3aXRoZHJhdyBsb2NrZWQgZnVuZHMgZmlyc3QEAAAAEG5ld0xvY2tlZEJhbGFuY2UJAABkAAAAAgkBAAAAEGdldExvY2tlZEJhbGFuY2UAAAABBQAAABVuZXV0cmlub0Fzc2V0SWRTdHJpbmcIBQAAAANwbXQAAAAGYW1vdW50CQEAAAAIV3JpdGVTZXQAAAABCQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACCQEAAAAaZ2V0QWNjb3VudExvY2tlZEJhbGFuY2VLZXkAAAACBQAAAAdhY2NvdW50BQAAABVuZXV0cmlub0Fzc2V0SWRTdHJpbmcIBQAAAANwbXQAAAAGYW1vdW50CQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACCQEAAAAYZ2V0QmFsYW5jZVVubG9ja0Jsb2NrS2V5AAAAAQUAAAAHYWNjb3VudAkAAGQAAAACBQAAAAZoZWlnaHQFAAAAE2JhbGFuY2VMb2NrSW50ZXJ2YWwJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIJAQAAABNnZXRMb2NrZWRCYWxhbmNlS2V5AAAAAQUAAAAVbmV1dHJpbm9Bc3NldElkU3RyaW5nBQAAABBuZXdMb2NrZWRCYWxhbmNlCQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACBQAAAA5Jc1JlYmFsYW5jZUtleQMJAABnAAAAAgUAAAAVcmVzZXJ2ZVdpdGhvdXRMZWFzaW5nCQEAAAAWY29udmVydE5ldXRyaW5vVG9XYXZlcwAAAAIFAAAAEG5ld0xvY2tlZEJhbGFuY2UFAAAADGN1cnJlbnRQcmljZQcGBQAAAANuaWwAAAABaQEAAAAId2l0aGRyYXcAAAADAAAAB2FjY291bnQAAAAFaW5kZXgAAAANbG9ja2VkQXNzZXRJZAQAAAAMdW5sb2NrSGVpZ2h0CQEAAAAVZ2V0VW5sb2NrQmFsYW5jZUJsb2NrAAAAAQUAAAAHYWNjb3VudAQAAAANbG9ja2VkQmFsYW5jZQkBAAAAF2dldEFjY291bnRMb2NrZWRCYWxhbmNlAAAAAgUAAAAHYWNjb3VudAUAAAANbG9ja2VkQXNzZXRJZAQAAAALaW5kZXhIZWlnaHQJAQAAABVnZXRIZWlnaHRQcmljZUJ5SW5kZXgAAAABBQAAAAVpbmRleAQAAAAPbmV4dEluZGV4SGVpZ2h0CQEAAAAVZ2V0SGVpZ2h0UHJpY2VCeUluZGV4AAAAAQkAAGQAAAACBQAAAAVpbmRleAAAAAAAAAAAAQQAAAAMcHJpY2VCeUluZGV4CQEAAAAPZ2V0UHJpY2VIaXN0b3J5AAAAAQUAAAALaW5kZXhIZWlnaHQEAAAABmFtb3VudAMJAAAAAAAAAgUAAAANbG9ja2VkQXNzZXRJZAUAAAAVbmV1dHJpbm9Bc3NldElkU3RyaW5nCQEAAAAWY29udmVydE5ldXRyaW5vVG9XYXZlcwAAAAIFAAAADWxvY2tlZEJhbGFuY2UFAAAADHByaWNlQnlJbmRleAkBAAAAFmNvbnZlcnRXYXZlc1RvTmV1dHJpbm8AAAACBQAAAA1sb2NrZWRCYWxhbmNlBQAAAAxwcmljZUJ5SW5kZXgDBQAAAAlpc0Jsb2NrZWQJAAACAAAAAQIAAABaY29udHJhY3QgaXMgYmxvY2tlZCBieSBFTUVSR0VOQ1kgU0hVVERPV04gYWN0aW9ucyB1bnRpbGwgcmVhY3RpdmF0aW9uIGJ5IGVtZXJnZW5jeSBvcmFjbGVzAwkAAGcAAAACAAAAAAAAAAAABQAAAAZhbW91bnQJAAACAAAAAQkAASwAAAACCQABLAAAAAICAAAAFWJhbGFuY2UgZXF1YWxzIHplcm8gKAUAAAANbG9ja2VkQXNzZXRJZAIAAAABKQMJAABmAAAAAgUAAAAMdW5sb2NrSGVpZ2h0BQAAAAZoZWlnaHQJAAACAAAAAQkAASwAAAACCQABLAAAAAICAAAAEXBsZWFzZSB3YWl0IGZvcjogCQABpAAAAAEFAAAADHVubG9ja0hlaWdodAIAAAAlIGJsb2NrIGhlaWdodCB0byB3aXRoZHJhdyBXQVZFUyBmdW5kcwMDAwkAAGYAAAACBQAAAAVpbmRleAUAAAAKcHJpY2VJbmRleAYJAABmAAAAAgUAAAALaW5kZXhIZWlnaHQFAAAADHVubG9ja0hlaWdodAYDCQEAAAACIT0AAAACBQAAAA9uZXh0SW5kZXhIZWlnaHQAAAAAAAAAAAAJAABnAAAAAgUAAAAMdW5sb2NrSGVpZ2h0BQAAAA9uZXh0SW5kZXhIZWlnaHQHCQAAAgAAAAECAAAAG2ludmFsaWQgcHJpY2UgaGlzdG9yeSBpbmRleAkBAAAADFNjcmlwdFJlc3VsdAAAAAIJAQAAAAhXcml0ZVNldAAAAAEJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIJAQAAABpnZXRBY2NvdW50TG9ja2VkQmFsYW5jZUtleQAAAAIFAAAAB2FjY291bnQFAAAADWxvY2tlZEFzc2V0SWQAAAAAAAAAAAAJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIJAQAAABNnZXRMb2NrZWRCYWxhbmNlS2V5AAAAAQUAAAANbG9ja2VkQXNzZXRJZAkAAGUAAAACCQEAAAAQZ2V0TG9ja2VkQmFsYW5jZQAAAAEFAAAADWxvY2tlZEFzc2V0SWQFAAAADWxvY2tlZEJhbGFuY2UFAAAAA25pbAkBAAAAC1RyYW5zZmVyU2V0AAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAcQGV4dHJVc2VyKGFkZHJlc3NGcm9tU3RyaW5nKQAAAAEFAAAAB2FjY291bnQFAAAABmFtb3VudAMJAAAAAAAAAgUAAAANbG9ja2VkQXNzZXRJZAUAAAAVbmV1dHJpbm9Bc3NldElkU3RyaW5nBQAAAAR1bml0BQAAAA9uZXV0cmlub0Fzc2V0SWQFAAAAA25pbAAAAAFpAQAAABF0cmFuc2ZlclRvQXVjdGlvbgAAAAAEAAAAEWRlZmljaXRCb25kQW1vdW50CQAAZQAAAAIJAABlAAAAAgkBAAAAFWNvbnZlcnROZXV0cmlub1RvQm9uZAAAAAEFAAAAB2RlZmljaXQJAAPrAAAAAgkBAAAAHEBleHRyVXNlcihhZGRyZXNzRnJvbVN0cmluZykAAAABBQAAAA9hdWN0aW9uQ29udHJhY3QFAAAAC2JvbmRBc3NldElkBQAAABl0b3RhbExpcXVpZGF0aW9uT3JkZXJib29rBAAAAAtzdXJwbHVzQm9uZAkAAGUAAAACCQAAZQAAAAIJAQAAABVjb252ZXJ0TmV1dHJpbm9Ub0JvbmQAAAABBQAAAAdzdXJwbHVzCQAD6wAAAAIJAQAAABxAZXh0clVzZXIoYWRkcmVzc0Zyb21TdHJpbmcpAAAAAQUAAAAPYXVjdGlvbkNvbnRyYWN0BQAAAA9uZXV0cmlub0Fzc2V0SWQFAAAADnRvdGFsT3JkZXJib29rAwUAAAAJaXNCbG9ja2VkCQAAAgAAAAECAAAAWmNvbnRyYWN0IGlzIGJsb2NrZWQgYnkgRU1FUkdFTkNZIFNIVVRET1dOIGFjdGlvbnMgdW50aWxsIHJlYWN0aXZhdGlvbiBieSBlbWVyZ2VuY3kgb3JhY2xlcwMJAABnAAAAAgUAAAARZGVmaWNpdEJvbmRBbW91bnQJAABpAAAAAgkAAGgAAAACBQAAAA5uZXV0cmlub1N1cHBseQUAAAANREVGSUNJVE9GRlNFVAAAAAAAAAAAZAkBAAAAC1RyYW5zZmVyU2V0AAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAcQGV4dHJVc2VyKGFkZHJlc3NGcm9tU3RyaW5nKQAAAAEFAAAAD2F1Y3Rpb25Db250cmFjdAUAAAARZGVmaWNpdEJvbmRBbW91bnQFAAAAC2JvbmRBc3NldElkBQAAAANuaWwDCQAAZgAAAAIFAAAAC3N1cnBsdXNCb25kAAAAAAAAAAAACQEAAAALVHJhbnNmZXJTZXQAAAABCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAABxAZXh0clVzZXIoYWRkcmVzc0Zyb21TdHJpbmcpAAAAAQUAAAATbGlxdWlkYXRpb25Db250cmFjdAkBAAAAFWNvbnZlcnRCb25kVG9OZXV0cmlubwAAAAEFAAAAC3N1cnBsdXNCb25kBQAAAA9uZXV0cmlub0Fzc2V0SWQFAAAAA25pbAkAAAIAAAABAgAAACVib25kIHdlcmUgZ2VuZXJhdGVkIG9yIGRvIG5vdCBuZWVkIGl0AAAAAWkBAAAACHRyYW5zZmVyAAAAAQAAAAdhY2NvdW50BAAAAANwbXQJAQAAAAdleHRyYWN0AAAAAQgFAAAAAWkAAAAHcGF5bWVudAkBAAAAC1RyYW5zZmVyU2V0AAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAcQGV4dHJVc2VyKGFkZHJlc3NGcm9tU3RyaW5nKQAAAAEFAAAAB2FjY291bnQIBQAAAANwbXQAAAAGYW1vdW50CAUAAAADcG10AAAAB2Fzc2V0SWQFAAAAA25pbAAAAAFpAQAAAApub2RlUmV3YXJkAAAAAAQAAAADcG10CQEAAAAFdmFsdWUAAAABCAUAAAABaQAAAAdwYXltZW50AwkBAAAAAiE9AAAAAggFAAAAAWkAAAAGY2FsbGVyCQEAAAAcQGV4dHJVc2VyKGFkZHJlc3NGcm9tU3RyaW5nKQAAAAEFAAAAC25vZGVBZGRyZXNzCQAAAgAAAAECAAAAR29ubHkgbm9kZSBhY2NvdW50IGlzIGFibGUgdG8gdHJhbnNmZXIgc3Rha2luZyByZXdhcmRzIGZyb20gbWFpbiBhY2NvdW50AwkBAAAACWlzRGVmaW5lZAAAAAEIBQAAAANwbXQAAAAHYXNzZXRJZAkAAAIAAAABAgAAABl3YXZlcyB0b2tlbnMgb25seSBhbGxvd2VkBAAAAAZhbW91bnQJAQAAABZjb252ZXJ0V2F2ZXNUb05ldXRyaW5vAAAAAggFAAAAA3BtdAAAAAZhbW91bnQFAAAADGN1cnJlbnRQcmljZQQAAAAPbmV3UnBkU3luY0luZGV4CQAAZAAAAAIFAAAADHJwZFN5bmNJbmRleAAAAAAAAAAAAQkBAAAADFNjcmlwdFJlc3VsdAAAAAIJAQAAAAhXcml0ZVNldAAAAAEJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIFAAAAD1JQRFN5bmNJbmRleEtleQUAAAAPbmV3UnBkU3luY0luZGV4CQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACCQEAAAAPZ2V0UlBEUHJvZml0S2V5AAAAAQUAAAAMcnBkU3luY0luZGV4BQAAAAZhbW91bnQJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIJAQAAACBnZXRSUERTbmFwc2hvdENvbnRyYWN0QmFsYW5jZUtleQAAAAIFAAAADHJwZFN5bmNJbmRleAUAAAAPbmV1dHJpbm9Bc3NldElkCQEAAAAVZ2V0UlBEQ29udHJhY3RCYWxhbmNlAAAAAQUAAAAPbmV1dHJpbm9Bc3NldElkBQAAAANuaWwJAQAAAAtUcmFuc2ZlclNldAAAAAEJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwkBAAAAHEBleHRyVXNlcihhZGRyZXNzRnJvbVN0cmluZykAAAABBQAAAAtycGRDb250cmFjdAUAAAAGYW1v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ZWVSZXNlcnZlCQAAZAAAAAIFAAAADWxlYXNpbmdBbW91bnQFAAAABmFtb3VudAUAAAAVcmVzZXJ2ZVdpdGhvdXRMZWFzaW5nAgAAAAEpCQEAAAAIV3JpdGVTZXQAAAABCQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACCQEAAAAdZ2V0Q2FuY2VsTGVhc2VUeFJlc2VydmVGZWVLZXkAAAABBQAAAAZ0eEhhc2gFAAAAA2ZlZQkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgUAAAARTGVhc2luZ1R4Q291bnRLZXkDCQAAAAAAAAIJAQAAABBnZXRMZWFzZVR4U3RhdHVzAAAAAQUAAAAGdHhIYXNoAgAAAAAJAABkAAAAAgUAAAAObGVhc2luZ1R4Q291bnQAAAAAAAAAAAEFAAAADmxlYXNpbmdUeENvdW50CQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACBQAAABBMZWFzaW5nQW1vdW50S2V5CQAAZAAAAAIFAAAADWxlYXNpbmdBbW91bnQFAAAABmFtb3VudAkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgUAAAAVTGVhc2luZ0V4cGlyZUJsb2NrS2V5AwkAAGYAAAACBQAAAAZoZWlnaHQFAAAAEmxlYXNpbmdFeHBpcmVCbG9jawkAAGQAAAACBQAAAAZoZWlnaHQFAAAAD2xlYXNpbmdJbnRlcnZhbAUAAAASbGVhc2luZ0V4cGlyZUJsb2NrCQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACCQEAAAATZ2V0TGVhc2VUeFN0YXR1c0tleQAAAAEFAAAABnR4SGFzaAUAAAADTkVXCQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACCQEAAAAcZ2V0TGVhc2VUeEV4cGlyZVNlbmRCbG9ja0tleQAAAAEFAAAABnR4SGFzaAkAAGQAAAACBQAAAAZoZWlnaHQFAAAADFNFTkRUWEVYUElSRQkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgkBAAAAGWdldExlYXNlVHhBbW91bnRCeUhhc2hLZXkAAAABBQAAAAZ0eEhhc2gFAAAABmFtb3VudAkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgkBAAAAGGdldExlYXNlVHhCeXRlc0J5SGFzaEtleQAAAAEFAAAABnR4SGFzaAkAAloAAAABBQAAAAd0eEJ5dGVzBQAAAANuaWwAAAABaQEAAAASY2FuY2VsU3R1Y2tMZWFzZVR4AAAAAQAAAAZ0eEhhc2gDAwMJAAAAAAAAAgkBAAAAEGdldExlYXNlVHhTdGF0dXMAAAABBQAAAAZ0eEhhc2gFAAAAA05FVwkBAAAAASEAAAABCQEAAAAJaXNEZWZpbmVkAAAAAQkAA+kAAAABCQACWQAAAAEFAAAABnR4SGFzaAcJAABmAAAAAgUAAAAGaGVpZ2h0CQEAAAAZZ2V0TGVhc2VUeEV4cGlyZVNlbmRCbG9jawAAAAEFAAAABnR4SGFzaAcEAAAABmFtb3VudAkBAAAAFmdldExlYXNlVHhBbW91bnRCeUhhc2gAAAABBQAAAAZ0eEhhc2gJAQAAAAhXcml0ZVNldAAAAAEJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIFAAAAEUxlYXNpbmdUeENvdW50S2V5CQAAZQAAAAIFAAAADmxlYXNpbmdUeENvdW50AAAAAAAAAAABCQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACBQAAABBMZWFzaW5nQW1vdW50S2V5CQAAZQAAAAIFAAAADWxlYXNpbmdBbW91bnQFAAAABmFtb3VudAkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgkBAAAAE2dldExlYXNlVHhTdGF0dXNLZXkAAAABBQAAAAZ0eEhhc2gFAAAACENBTkNFTEVECQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACBQAAAA5Jc1JlYmFsYW5jZUtleQMJAABnAAAAAgkAAGUAAAACBQAAABVyZXNlcnZlV2l0aG91dExlYXNpbmcFAAAABmFtb3VudAkBAAAAFmNvbnZlcnROZXV0cmlub1RvV2F2ZXMAAAACCQEAAAAQZ2V0TG9ja2VkQmFsYW5jZQAAAAEFAAAAFW5ldXRyaW5vQXNzZXRJZFN0cmluZwUAAAAMY3VycmVudFByaWNlBwYFAAAAA25pbAkAAAIAAAABAgAAAA9pbnZhbGlkIHR4IGhhc2gAAAABaQEAAAAVcmVnaXN0cmF0aW9uVW5sZWFzZVR4AAAABQAAAA1jaGFpbklkU3RyaW5nAAAAD3NlbmRlclB1Ymxp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", "chainId": 84, "height": 766304, "spentComplexity": 0 } View: original | compacted Prev: DvWKBSGRxUCpy1wx9tViiYeAdSqEL54QcWrbTv9VU3vV Next: 4zJxn7FXkWLnnSNgVhmkkYUQ7zMqKya3uTPWSxsyzr2S Diff:
OldNewDifferences
6565
6666 let LEASINTXCOUNT = 10
6767
68+let DEFICITOFFSET = 10
69+
70+let WAVESASSETID = "waves"
71+
6872 let CANCELED = "canceled"
6973
7074 let NEW = "new"
71-
72-let FILLED = "filled"
7375
7476 let NeutrinoAssetIdKey = "neutrino_asset_id"
7577
7880 let ReserveContractKey = "reserve_contract"
7981
8082 let AuctionContractKey = "auction_contract"
83+
84+let LiquidationContractKey = "liquidation_contract"
8185
8286 let RPDContractKey = "rpd_contract"
8387
9195
9296 let NodeAddressKey = "node_address"
9397
98+let NodeOracleProviderKey = "oracle_node_provider"
99+
94100 let LeasingIntervalKey = "leasing_interval"
101+
102+let RPDBalanceKey = "rpd_balance"
103+
104+func getRPDContractBalanceKey (assetId) = ((RPDBalanceKey + "_") + toBase58String(assetId))
105+
106+
107+let TotalOrderbookKey = "total_orderbook"
108+
109+let TotalLiquidationOrderbookKey = "total_liquidation_orderbook"
95110
96111 let PriceKey = "price"
97112
98113 let PriceIndexKey = "price_index"
99114
100-let ScriptUpdateIntervalKey = "script_update_interval"
101-
102-let NeutrinoBalanceKey = "neutrino_"
103-
104-let WavesBalanceKey = "waves_"
105-
106-let BalanceUnlockBlockKey = "balance_block_"
107-
108-let OrderbookKey = "orderbook"
109-
110-let OrderTotalKey = "order_total_"
111-
112-let OrderOwnerKey = "order_owner_"
113-
114-let OrderHeightKey = "order_height_"
115-
116-let OrderFilledTotalKey = "order_filled_total_"
117-
118-let OrderStatusKey = "order_status_"
119-
120-let RPDSyncIndexKey = "rpd_sync_index"
121-
122-let RPDProfitKey = "rpd_profit"
123-
124-let RPDBalanceKey = "rpd_balance"
125-
126115 let IsBlockedKey = "is_blocked"
127-
128-let IsLeasingProfitTxExistKey = "is_leasing_profit"
129-
130-let ScriptUpdateBlockKey = "script_update_block"
131-
132-let LeaseTxKey = "lease_tx"
133-
134-let LeaseTxStatusKey = "lease_tx_status"
135-
136-let LeasingAmountKey = "leasing_amount"
137-
138-let LeaseTxExpireSendBlockKey = "leasing_expire_send"
139116
140117 let LeasingExpireBlockKey = "leasing_expire_block"
141118
142119 let IsRebalanceKey = "is_rebalance"
143120
144-let SwapLockedBalanceKey = "swap_locked_balance"
145-
146-let SwapNeutrinoLockedBalanceKey = "swap_neutrino_locked_balance"
147-
148121 let LeasingTxCountKey = "leasing_index"
149122
150-func getRPDSnapshotContractBalanceKey (count,assetId) = ((((RPDBalanceKey + "_") + toBase58String(assetId)) + "_") + toString(count))
151-
152-
153-func getRPDContractBalanceKey (assetId) = ((RPDBalanceKey + "_") + toBase58String(assetId))
154-
155-
156-func getRPDProfitKey (count) = ((RPDProfitKey + "_") + toString(count))
157-
158-
159-func getNeutrinoBalanceKey (owner) = (NeutrinoBalanceKey + owner)
160-
161-
162-func getWavesBalanceKey (owner) = (WavesBalanceKey + owner)
163-
164-
165-func getBalanceUnlockBlockKey (owner) = (BalanceUnlockBlockKey + owner)
166-
167-
168-func getOrderTotalKey (orderId) = (OrderTotalKey + orderId)
169-
170-
171-func getOrderOwnerKey (orderId) = (OrderOwnerKey + orderId)
172-
173-
174-func getOrderHeightKey (orderId) = (OrderHeightKey + orderId)
175-
176-
177-func getOrderStatusKey (orderId) = (OrderStatusKey + orderId)
178-
179-
180-func getOrderFilledTotalKey (orderId) = (OrderFilledTotalKey + orderId)
181-
123+let LeasingAmountKey = "leasing_amount"
182124
183125 func getPriceHistoryKey (block) = ((PriceKey + "_") + toString(block))
184126
186128 func getHeightPriceByIndexKey (index) = ((PriceIndexKey + "_") + toString(index))
187129
188130
189-func getLeaseTxStatusKey (hash) = ((LeaseTxStatusKey + "_") + hash)
131+let RPDSyncIndexKey = "rpd_sync_index"
132+
133+func getRPDSnapshotContractBalanceKey (count,assetId) = ((((RPDBalanceKey + "_") + toBase58String(assetId)) + "_") + toString(count))
134+
135+
136+func getCancelLeaseTxReserveFeeKey (hash) = (("cancel_lease_tx_reserve_fee" + "_") + hash)
137+
138+
139+func getAccountLockedBalanceKey (owner,assetId) = ((("balance_" + assetId) + "_") + owner)
140+
141+
142+func getBalanceUnlockBlockKey (owner) = ("balance_block_" + owner)
143+
144+
145+func getRPDProfitKey (count) = (("rpd_profit" + "_") + toString(count))
146+
147+
148+func getLockedBalanceKey (assetId) = ("balance_" + assetId)
149+
150+
151+func getLeaseTxStatusKey (hash) = (("lease_tx_status" + "_") + hash)
190152
191153
192154 func getLeaseTxAmountByHashKey (hash) = ((LeasingAmountKey + "_") + hash)
193155
194156
195-func getLeaseTxBytesByHashKey (hash) = ((LeaseTxKey + "_") + hash)
157+func getLeaseTxBytesByHashKey (hash) = (("lease_tx" + "_") + hash)
196158
197159
198-func getLeaseTxExpireSendBlockKey (hash) = ((LeaseTxExpireSendBlockKey + "_") + hash)
160+func getLeaseTxExpireSendBlockKey (hash) = (("leasing_expire_send" + "_") + hash)
199161
200162
201-func getIsRebalanceByAddressKey (address) = ((IsRebalanceKey + "_") + address)
163+func convertNeutrinoToWaves (amount,price) = ((((amount * 100) / price) * WAVELET) / PAULI)
202164
203165
204-let controlContract = getStringByKey(ContolContractKey)
205-
206-let price = getNumberByAddressAndKey(controlContract, PriceKey)
207-
208-let priceIndex = getNumberByAddressAndKey(controlContract, PriceIndexKey)
209-
210-func convertNeutrinoToWavesByPrice (amount,convertPrice) = ((((amount * 100) / convertPrice) * WAVELET) / PAULI)
211-
212-
213-func convertNeutrinoToWaves (amount) = ((((amount * 100) / price) * WAVELET) / PAULI)
214-
215-
216-func convertWavesToNeutrino (amount) = ((((amount * price) / 100) * PAULI) / WAVELET)
166+func convertWavesToNeutrino (amount,price) = ((((amount * price) / 100) * PAULI) / WAVELET)
217167
218168
219169 func convertNeutrinoToBond (amount) = (amount / PAULI)
222172 func convertBondToNeutrino (amount) = (amount * PAULI)
223173
224174
225-func convertWavesToBond (amount) = convertNeutrinoToBond(convertWavesToNeutrino(amount))
175+func convertWavesToBond (amount,price) = convertNeutrinoToBond(convertWavesToNeutrino(amount, price))
226176
177+
178+func getLockedBalance (assetId) = getNumberByKey(getLockedBalanceKey(assetId))
179+
180+
181+let liquidationContract = getStringByKey(LiquidationContractKey)
182+
183+let neutrinoAssetIdString = getStringByKey(NeutrinoAssetIdKey)
184+
185+let neutrinoAssetId = fromBase58String(neutrinoAssetIdString)
186+
187+let reserveContract = getStringByKey(ReserveContractKey)
188+
189+let auctionContract = getStringByKey(AuctionContractKey)
190+
191+let rpdContract = getStringByKey(RPDContractKey)
192+
193+let controlContract = getStringByKey(ContolContractKey)
194+
195+let currentPrice = getNumberByAddressAndKey(controlContract, PriceKey)
196+
197+let priceIndex = getNumberByAddressAndKey(controlContract, PriceIndexKey)
198+
199+let isBlocked = getBoolByAddressAndKey(controlContract, IsBlockedKey)
227200
228201 let leasingTxCount = getNumberByKey(LeasingTxCountKey)
229202
235208
236209 let leasingAmount = getNumberByKey(LeasingAmountKey)
237210
238-let swapNeutrinoLockedBalance = getNumberByKey(SwapNeutrinoLockedBalanceKey)
239-
240-let swapWavesLockedBalance = getNumberByKey(SwapLockedBalanceKey)
241-
242211 let nodeAddress = getStringByKey(NodeAddressKey)
243212
244-let scriptUpdateInterval = getNumberByAddressAndKey(ContolContractKey, ScriptUpdateIntervalKey)
245-
246-let scriptUpdateBlock = getNumberByAddressAndKey(controlContract, ScriptUpdateBlockKey)
213+let nodeOracleProviderKey = getStringByKey(NodeOracleProviderKey)
247214
248215 let rpdSyncIndex = getNumberByKey(RPDSyncIndexKey)
249216
250217 let balanceLockInterval = getNumberByKey(BalanceLockIntervalKey)
251218
252-let isBlocked = getBoolByAddressAndKey(controlContract, IsBlockedKey)
253-
254219 let minWavesSwapAmount = getNumberByKey(MinWavesSwapAmountKey)
255220
256221 let minNeutrinoSwapAmount = getNumberByKey(MinNeutrinoSwapAmountKey)
257222
258-let neutrinoAssetId = fromBase58String(getStringByKey(NeutrinoAssetIdKey))
259-
260-let reserveContract = getStringByKey(ReserveContractKey)
261-
262-let auctionContract = getStringByKey(AuctionContractKey)
263-
264-let rpdContract = getStringByKey(RPDContractKey)
265-
266-let reserve = (wavesBalance(this) - swapWavesLockedBalance)
223+let reserve = (wavesBalance(this) - getLockedBalance(WAVESASSETID))
267224
268225 let reserveWithoutLeasing = (reserve - leasingAmount)
269226
270-let orderbook = getStringByKey(OrderbookKey)
271-
272227 let bondAssetId = fromBase58String(getStringByKey(BondAssetIdKey))
273228
274-let bondSupply = {
275- let info = extract(assetInfo(bondAssetId))
276- (info.quantity - assetBalance(this, bondAssetId))
277- }
229+let bondSupply = (extract(assetInfo(bondAssetId)).quantity - assetBalance(this, bondAssetId))
278230
279-let neutrinoSupply = {
280- let info = extract(assetInfo(neutrinoAssetId))
281- ((info.quantity - assetBalance(this, neutrinoAssetId)) + swapNeutrinoLockedBalance)
282- }
231+let neutrinoSupply = ((extract(assetInfo(neutrinoAssetId)).quantity - assetBalance(this, neutrinoAssetId)) + getLockedBalance(neutrinoAssetIdString))
283232
284-let surplus = (convertWavesToNeutrino(reserve) - neutrinoSupply)
233+let surplus = (convertWavesToNeutrino(reserve, currentPrice) - neutrinoSupply)
285234
286-let deficit = (neutrinoSupply - convertWavesToNeutrino(reserve))
235+let deficit = (neutrinoSupply - convertWavesToNeutrino(reserve, currentPrice))
287236
288237 func getRPDContractBalance (assetId) = getNumberByAddressAndKey(rpdContract, getRPDContractBalanceKey(assetId))
289238
290239
291-func getWavesBalance (owner) = getNumberByKey(getWavesBalanceKey(owner))
240+let totalLiquidationOrderbook = getNumberByAddressAndKey(auctionContract, TotalLiquidationOrderbookKey)
241+
242+let totalOrderbook = getNumberByAddressAndKey(auctionContract, TotalOrderbookKey)
243+
244+func getPriceHistory (block) = getNumberByAddressAndKey(controlContract, getPriceHistoryKey(block))
292245
293246
294-func getNeutrinoBalance (owner) = getNumberByKey(getNeutrinoBalanceKey(owner))
247+func getHeightPriceByIndex (index) = getNumberByAddressAndKey(controlContract, getHeightPriceByIndexKey(index))
248+
249+
250+func getCancelLeaseTxReserveFee (hash) = getNumberByKey(getCancelLeaseTxReserveFeeKey(hash))
251+
252+
253+func getAccountLockedBalance (owner,assetId) = getNumberByKey(getAccountLockedBalanceKey(owner, assetId))
295254
296255
297256 func getUnlockBalanceBlock (owner) = getNumberByKey(getBalanceUnlockBlockKey(owner))
298257
299258
300-func getOrderTotal (id) = getNumberByKey(getOrderTotalKey(id))
301-
302-
303-func getOrderOwner (id) = getStringByKey(getOrderOwnerKey(id))
304-
305-
306-func getOrderStatus (id) = getStringByKey(getOrderStatusKey(id))
307-
308-
309-func getOrderFilledTotal (id) = getNumberByKey(getOrderFilledTotalKey(id))
310-
311-
312259 func getRPDProfit (count) = getNumberByKey(getRPDProfitKey(count))
313-
314-
315-func getPriceHistory (block) = getNumberByAddressAndKey(controlContract, getPriceHistoryKey(block))
316-
317-
318-func getHeightPriceByIndex (index) = getNumberByAddressAndKey(controlContract, getHeightPriceByIndexKey(index))
319260
320261
321262 func getLeaseTxStatus (hash) = getStringByKey(getLeaseTxStatusKey(hash))
330271 func getLeaseTxExpireSendBlock (hash) = getNumberByKey(getLeaseTxExpireSendBlockKey(hash))
331272
332273
333-func getOrderElementById (id) = (id + LISTSPLITSYMBOL)
334-
335-
336-func addOrder (orderId) = (orderbook + getOrderElementById(orderId))
337-
338-
339-func dropOrder (orderId) = {
340- let parts = split(orderbook, getOrderElementById(orderId))
341- (parts[0] + parts[1])
342- }
343-
344-
345274 @Callable(i)
346275 func swapWavesToNeutrino () = {
347276 let pmt = extract(i.payment)
277+ let account = toString(i.caller)
348278 if ((minWavesSwapAmount > pmt.amount))
349- then throw("amount less min")
279+ then throw((("an amount is less than min available amount: " + toString(minWavesSwapAmount)) + " wavelets"))
350280 else if (isDefined(pmt.assetId))
351281 then throw("can use waves only")
352282 else if (isBlocked)
353- then throw("contract is blocked")
354- else {
355- let amount = convertWavesToNeutrino(pmt.amount)
356- TransferSet([ScriptTransfer(i.caller, amount, neutrinoAssetId)])
357- }
283+ then throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
284+ else if ((getUnlockBalanceBlock(account) > height))
285+ then throw((("await " + toString((getUnlockBalanceBlock(account) - height))) + " blocks"))
286+ else if ((getAccountLockedBalance(account, WAVESASSETID) != 0))
287+ then throw("please withdraw locked funds first")
288+ else WriteSet([DataEntry(getAccountLockedBalanceKey(account, WAVESASSETID), pmt.amount), DataEntry(getBalanceUnlockBlockKey(account), (height + balanceLockInterval)), DataEntry(getLockedBalanceKey(WAVESASSETID), (getLockedBalance(WAVESASSETID) + pmt.amount))])
358289 }
359290
360291
364295 let pmt = extract(i.payment)
365296 let account = toString(i.caller)
366297 if ((minNeutrinoSwapAmount > pmt.amount))
367- then throw("amount less min")
298+ then throw((("an amount is less than min available amount: " + toString(minNeutrinoSwapAmount)) + " neutrino cents"))
368299 else if (isBlocked)
369- then throw("contract is blocked")
300+ then throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
370301 else if ((pmt.assetId != neutrinoAssetId))
371- then throw("can use neutrino only")
302+ then throw("can use appropriate neutrino tokens only")
372303 else if ((getUnlockBalanceBlock(account) > height))
373304 then throw((("await " + toString((getUnlockBalanceBlock(account) - height))) + " blocks"))
374- else if ((getNeutrinoBalance(account) != 0))
375- then throw("use withdraw")
305+ else if ((getAccountLockedBalance(account, neutrinoAssetIdString) != 0))
306+ then throw("please withdraw locked funds first")
376307 else {
377- let neutrinoAmount = pmt.amount
378- let newSwapNeutrinoLockedBalance = (swapNeutrinoLockedBalance + neutrinoAmount)
379- WriteSet([DataEntry(getNeutrinoBalanceKey(account), (getNeutrinoBalance(account) + neutrinoAmount)), DataEntry(getBalanceUnlockBlockKey(account), (height + balanceLockInterval)), DataEntry(SwapNeutrinoLockedBalanceKey, newSwapNeutrinoLockedBalance), DataEntry(IsRebalanceKey, if ((reserveWithoutLeasing >= convertNeutrinoToWaves(newSwapNeutrinoLockedBalance)))
308+ let newLockedBalance = (getLockedBalance(neutrinoAssetIdString) + pmt.amount)
309+ WriteSet([DataEntry(getAccountLockedBalanceKey(account, neutrinoAssetIdString), pmt.amount), DataEntry(getBalanceUnlockBlockKey(account), (height + balanceLockInterval)), DataEntry(getLockedBalanceKey(neutrinoAssetIdString), newLockedBalance), DataEntry(IsRebalanceKey, if ((reserveWithoutLeasing >= convertNeutrinoToWaves(newLockedBalance, currentPrice)))
380310 then false
381311 else true)])
382312 }
385315
386316
387317 @Callable(i)
388-func withdraw (account,index) = {
318+func withdraw (account,index,lockedAssetId) = {
319+ let unlockHeight = getUnlockBalanceBlock(account)
320+ let lockedBalance = getAccountLockedBalance(account, lockedAssetId)
389321 let indexHeight = getHeightPriceByIndex(index)
390322 let nextIndexHeight = getHeightPriceByIndex((index + 1))
391- let unlockHeight = getUnlockBalanceBlock(account)
392- let neutrinoAmount = getNeutrinoBalance(account)
393- let indexPrice = getPriceHistory(indexHeight)
394- let amount = convertNeutrinoToWavesByPrice(neutrinoAmount, indexPrice)
395- let totalWavesWithdraw = (getWavesBalance(account) + amount)
323+ let priceByIndex = getPriceHistory(indexHeight)
324+ let amount = if ((lockedAssetId == neutrinoAssetIdString))
325+ then convertNeutrinoToWaves(lockedBalance, priceByIndex)
326+ else convertWavesToNeutrino(lockedBalance, priceByIndex)
396327 if (isBlocked)
397- then throw("contract is blocked")
398- else if ((unlockHeight > height))
399- then throw("wait a couple of blocks for withdraw")
400- else if (if (if ((index > priceIndex))
401- then true
402- else (indexHeight > unlockHeight))
403- then true
404- else if ((nextIndexHeight != 0))
405- then (unlockHeight >= nextIndexHeight)
406- else false)
407- then throw("invalid index")
408- else ScriptResult(WriteSet([DataEntry(getWavesBalanceKey(account), 0), DataEntry(getNeutrinoBalanceKey(account), 0), DataEntry(SwapLockedBalanceKey, (swapWavesLockedBalance - getWavesBalance(account))), DataEntry(SwapNeutrinoLockedBalanceKey, (swapNeutrinoLockedBalance - neutrinoAmount))]), TransferSet([ScriptTransfer(addressFromStringValue(account), totalWavesWithdraw, unit)]))
328+ then throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
329+ else if ((0 >= amount))
330+ then throw((("balance equals zero (" + lockedAssetId) + ")"))
331+ else if ((unlockHeight > height))
332+ then throw((("please wait for: " + toString(unlockHeight)) + " block height to withdraw WAVES funds"))
333+ else if (if (if ((index > priceIndex))
334+ then true
335+ else (indexHeight > unlockHeight))
336+ then true
337+ else if ((nextIndexHeight != 0))
338+ then (unlockHeight >= nextIndexHeight)
339+ else false)
340+ then throw("invalid price history index")
341+ else ScriptResult(WriteSet([DataEntry(getAccountLockedBalanceKey(account, lockedAssetId), 0), DataEntry(getLockedBalanceKey(lockedAssetId), (getLockedBalance(lockedAssetId) - lockedBalance))]), TransferSet([ScriptTransfer(addressFromStringValue(account), amount, if ((lockedAssetId == neutrinoAssetIdString))
342+ then unit
343+ else neutrinoAssetId)]))
409344 }
410345
411346
412347
413348 @Callable(i)
414-func generateBond () = {
415- let balanceAuction = assetBalance(addressFromStringValue(auctionContract), bondAssetId)
416- let amount = (convertNeutrinoToBond(deficit) - balanceAuction)
349+func transferToAuction () = {
350+ let deficitBondAmount = ((convertNeutrinoToBond(deficit) - assetBalance(addressFromStringValue(auctionContract), bondAssetId)) - totalLiquidationOrderbook)
351+ let surplusBond = ((convertNeutrinoToBond(surplus) - assetBalance(addressFromStringValue(auctionContract), neutrinoAssetId)) - totalOrderbook)
417352 if (isBlocked)
418- then throw("contract is blocked")
419- else if ((amount >= 10))
420- then TransferSet([ScriptTransfer(addressFromStringValue(auctionContract), amount, bondAssetId)])
421- else throw("bond were generated or do not need it")
422- }
423-
424-
425-
426-@Callable(i)
427-func setOrder () = {
428- let pmt = extract(i.payment)
429- let newOrderId = toBase58String(keccak256(((toBytes(pmt.amount) + i.caller.bytes) + toBytes(height))))
430- if ((pmt.assetId != bondAssetId))
431- then throw("can use bond only")
432- else if ((getOrderOwner(newOrderId) != ""))
433- then throw("order exists")
434- else WriteSet([DataEntry(OrderbookKey, addOrder(newOrderId)), DataEntry(getOrderTotalKey(newOrderId), pmt.amount), DataEntry(getOrderOwnerKey(newOrderId), toString(i.caller)), DataEntry(getOrderHeightKey(newOrderId), height), DataEntry(getOrderStatusKey(newOrderId), NEW)])
435- }
436-
437-
438-
439-@Callable(i)
440-func cancelOrder (orderId) = {
441- let owner = getOrderOwner(orderId)
442- let amount = (getOrderTotal(orderId) - getOrderFilledTotal(orderId))
443- if ((owner != toString(i.caller)))
444- then throw("permission denied")
445- else if ((getOrderStatus(orderId) != NEW))
446- then throw("invalid order status")
447- else ScriptResult(WriteSet([DataEntry(OrderbookKey, dropOrder(orderId)), DataEntry(getOrderStatusKey(orderId), CANCELED)]), TransferSet([ScriptTransfer(i.caller, amount, bondAssetId)]))
448- }
449-
450-
451-
452-@Callable(i)
453-func executeOrder () = {
454- let orderId = split(orderbook, LISTSPLITSYMBOL)[0]
455- let orderTotal = getOrderTotal(orderId)
456- let orderOwner = getOrderOwner(orderId)
457- let filledTotal = getOrderFilledTotal(orderId)
458- let surplusBond = convertNeutrinoToBond(surplus)
459- if (isBlocked)
460- then throw("contract is blocked")
461- else if ((0 >= surplusBond))
462- then throw("surplus is less than zero")
463- else if (if ((orderOwner == ""))
464- then (surplusBond >= 10)
465- else false)
466- then {
467- let newRpdSyncIndex = (rpdSyncIndex + 1)
468- ScriptResult(WriteSet([DataEntry(RPDSyncIndexKey, newRpdSyncIndex), DataEntry(getRPDProfitKey(rpdSyncIndex), surplus), DataEntry(getRPDSnapshotContractBalanceKey(rpdSyncIndex, neutrinoAssetId), getRPDContractBalance(neutrinoAssetId))]), TransferSet([ScriptTransfer(addressFromStringValue(rpdContract), surplus, neutrinoAssetId)]))
469- }
470- else {
471- let amount = (orderTotal - filledTotal)
472- let status = if ((surplusBond >= amount))
473- then FILLED
474- else NEW
475- let newFilledTotal = if ((surplusBond >= amount))
476- then amount
477- else surplusBond
478- ScriptResult(WriteSet([DataEntry(OrderbookKey, if ((surplusBond >= amount))
479- then dropOrder(orderId)
480- else orderbook), DataEntry(getOrderFilledTotalKey(orderId), (filledTotal + newFilledTotal)), DataEntry(getOrderStatusKey(orderId), status)]), TransferSet([ScriptTransfer(addressFromStringValue(orderOwner), convertBondToNeutrino(newFilledTotal), neutrinoAssetId)]))
481- }
353+ then throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
354+ else if ((deficitBondAmount >= ((neutrinoSupply * DEFICITOFFSET) / 100)))
355+ then TransferSet([ScriptTransfer(addressFromStringValue(auctionContract), deficitBondAmount, bondAssetId)])
356+ else if ((surplusBond > 0))
357+ then TransferSet([ScriptTransfer(addressFromStringValue(liquidationContract), convertBondToNeutrino(surplusBond), neutrinoAssetId)])
358+ else throw("bond were generated or do not need it")
482359 }
483360
484361
495372 func nodeReward () = {
496373 let pmt = value(i.payment)
497374 if ((i.caller != addressFromStringValue(nodeAddress)))
498- then throw("permission denied")
375+ then throw("only node account is able to transfer staking rewards from main account")
499376 else if (isDefined(pmt.assetId))
500- then throw("waves only")
377+ then throw("waves tokens only allowed")
501378 else {
502- let amount = convertWavesToNeutrino(pmt.amount)
379+ let amount = convertWavesToNeutrino(pmt.amount, currentPrice)
503380 let newRpdSyncIndex = (rpdSyncIndex + 1)
504381 ScriptResult(WriteSet([DataEntry(RPDSyncIndexKey, newRpdSyncIndex), DataEntry(getRPDProfitKey(rpdSyncIndex), amount), DataEntry(getRPDSnapshotContractBalanceKey(rpdSyncIndex, neutrinoAssetId), getRPDContractBalance(neutrinoAssetId))]), TransferSet([ScriptTransfer(addressFromStringValue(rpdContract), amount, neutrinoAssetId)]))
505382 }
509386
510387 @Callable(i)
511388 func registrationLeaseTx (senderPublicKey,fee,timestamp,leaseTxHash) = {
512- let totalFreeReserve = (((reserve * LEASINGSHARE) / 100) - convertNeutrinoToWaves(swapNeutrinoLockedBalance))
389+ let totalFreeReserve = (((reserve * LEASINGSHARE) / 100) - convertNeutrinoToWaves(getLockedBalance(neutrinoAssetIdString), currentPrice))
513390 let amount = (totalFreeReserve / LEASINTXCOUNT)
514391 let txBytes = (((((base58'3h1H' + fromBase58String(senderPublicKey)) + fromBase58String(nodeAddress)) + toBytes(amount)) + toBytes(fee)) + toBytes(timestamp))
515392 let txHashBytes = blake2b256(txBytes)
516393 let txHash = toBase58String(txHashBytes)
517- if ((leaseTxHash != txHash))
518- then throw("invalid tx hash")
519- else if ((leasingTxCount >= LEASINTXCOUNT))
520- then throw("the number of leasing transactions is equal to the maximum")
521- else if ((this != addressFromPublicKey(fromBase58String(senderPublicKey))))
522- then throw("invalid pubKey")
523- else if (if ((lastBlock.timestamp > timestamp))
524- then true
525- else (timestamp > (lastBlock.timestamp + 5400000)))
526- then throw((("invalid timestamp(lastBlock: " + toString(lastBlock.timestamp)) + ")"))
527- else if ((getLeaseTxStatus(txHash) == ""))
528- then throw("tx is exist")
529- else if (if ((fee > 1000000))
394+ let pmt = extract(i.payment)
395+ if ((toString(i.caller) == nodeOracleProviderKey))
396+ then throw("invalid caller")
397+ else if (isDefined(pmt.assetId))
398+ then throw("invalid paymtn asset")
399+ else if ((leaseTxHash != txHash))
400+ then throw((("invalid tx hash(amount:" + toString(amount)) + ")"))
401+ else if ((leasingTxCount >= LEASINTXCOUNT))
402+ then throw("the number of leasing transactions is equal to the maximum")
403+ else if ((this != addressFromPublicKey(fromBase58String(senderPublicKey))))
404+ then throw("invalid pubKey")
405+ else if (if ((lastBlock.timestamp > timestamp))
530406 then true
531- else (500000 > fee))
532- then throw("invalid fee")
533- else if (((totalFreeReserve - (leasingAmount + amount)) > reserveWithoutLeasing))
534- then throw((("invalid amount(result:" + toString(((totalFreeReserve - (leasingAmount + amount)) > reserveWithoutLeasing))) + ")"))
535- else WriteSet([DataEntry(LeasingTxCountKey, if ((getLeaseTxStatus(txHash) == ""))
536- then (leasingTxCount + 1)
537- else leasingTxCount), DataEntry(LeasingAmountKey, (leasingAmount + amount)), DataEntry(LeasingExpireBlockKey, if ((height > leasingExpireBlock))
538- then (height + leasingInterval)
539- else leasingExpireBlock), DataEntry(getLeaseTxStatusKey(txHash), NEW), DataEntry(getLeaseTxExpireSendBlockKey(txHash), (height + SENDTXEXPIRE)), DataEntry(getLeaseTxAmountByHashKey(txHash), amount), DataEntry(getLeaseTxBytesByHashKey(txHash), toBase64String(txBytes))])
407+ else (timestamp > (lastBlock.timestamp + 5400000)))
408+ then throw((("invalid timestamp(lastBlock: " + toString(lastBlock.timestamp)) + ")"))
409+ else if ((getLeaseTxStatus(txHash) != ""))
410+ then throw("tx is exist")
411+ else if ((pmt.amount != (fee * 2)))
412+ then throw("invalid payment amount")
413+ else if (if ((fee > 1000000))
414+ then true
415+ else (500000 > fee))
416+ then throw("invalid fee")
417+ else if (((totalFreeReserve - (leasingAmount + amount)) > reserveWithoutLeasing))
418+ then throw((("invalid amount(result:" + toString(((totalFreeReserve - (leasingAmount + amount)) > reserveWithoutLeasing))) + ")"))
419+ else WriteSet([DataEntry(getCancelLeaseTxReserveFeeKey(txHash), fee), DataEntry(LeasingTxCountKey, if ((getLeaseTxStatus(txHash) == ""))
420+ then (leasingTxCount + 1)
421+ else leasingTxCount), DataEntry(LeasingAmountKey, (leasingAmount + amount)), DataEntry(LeasingExpireBlockKey, if ((height > leasingExpireBlock))
422+ then (height + leasingInterval)
423+ else leasingExpireBlock), DataEntry(getLeaseTxStatusKey(txHash), NEW), DataEntry(getLeaseTxExpireSendBlockKey(txHash), (height + SENDTXEXPIRE)), DataEntry(getLeaseTxAmountByHashKey(txHash), amount), DataEntry(getLeaseTxBytesByHashKey(txHash), toBase64String(txBytes))])
540424 }
541425
542426
549433 else false)
550434 then {
551435 let amount = getLeaseTxAmountByHash(txHash)
552- WriteSet([DataEntry(LeasingTxCountKey, (leasingTxCount - 1)), DataEntry(LeasingAmountKey, (leasingAmount - amount)), DataEntry(getLeaseTxStatusKey(txHash), CANCELED), DataEntry(IsRebalanceKey, if (((reserveWithoutLeasing - amount) >= convertNeutrinoToWaves(swapNeutrinoLockedBalance)))
436+ WriteSet([DataEntry(LeasingTxCountKey, (leasingTxCount - 1)), DataEntry(LeasingAmountKey, (leasingAmount - amount)), DataEntry(getLeaseTxStatusKey(txHash), CANCELED), DataEntry(IsRebalanceKey, if (((reserveWithoutLeasing - amount) >= convertNeutrinoToWaves(getLockedBalance(neutrinoAssetIdString), currentPrice)))
553437 then false
554438 else true)])
555439 }
569453 then throw("blockchain does not contain this transaction")
570454 else {
571455 let amount = getLeaseTxAmountByHash(leaseTxHash)
572- WriteSet([DataEntry(LeasingTxCountKey, (leasingTxCount - 1)), DataEntry(LeasingAmountKey, (leasingAmount - amount)), DataEntry(getLeaseTxStatusKey(leaseTxHash), CANCELED), DataEntry(IsRebalanceKey, if (((reserveWithoutLeasing - amount) >= convertNeutrinoToWaves(swapNeutrinoLockedBalance)))
456+ WriteSet([DataEntry(LeasingTxCountKey, (leasingTxCount - 1)), DataEntry(LeasingAmountKey, (leasingAmount - amount)), DataEntry(getLeaseTxStatusKey(leaseTxHash), CANCELED), DataEntry(IsRebalanceKey, if (((reserveWithoutLeasing - amount) >= convertNeutrinoToWaves(getLockedBalance(neutrinoAssetIdString), currentPrice)))
573457 then false
574458 else true)])
575459 }
584468 if (if ((leasingExpireBlock >= height))
585469 then (getLeaseTxExpireSendBlock(id) >= height)
586470 else false)
587- then (getLeaseTxStatusKey(id) == NEW)
471+ then (getLeaseTxStatus(id) == NEW)
588472 else false
589473 case unleaseTx: LeaseCancelTransaction =>
474+ let leaseId = toBase58String(unleaseTx.leaseId)
590475 if (if (if ((height > leasingExpireBlock))
591476 then true
592477 else isRebalance)
593- then if ((unleaseTx.fee >= 500000))
594- then (1000000 >= unleaseTx.fee)
595- else false
478+ then (unleaseTx.fee == getCancelLeaseTxReserveFee(leaseId))
596479 else false)
597- then (getLeaseTxStatusKey(toBase58String(unleaseTx.leaseId)) == NEW)
480+ then (getLeaseTxStatus(leaseId) == NEW)
598481 else false
599482 case _ =>
600483 sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 3 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 func getNumberByKey (key) = match getInteger(this, key) {
55 case a: Int =>
66 a
77 case _ =>
88 0
99 }
1010
1111
1212 func getStringByKey (key) = match getString(this, key) {
1313 case a: String =>
1414 a
1515 case _ =>
1616 ""
1717 }
1818
1919
2020 func getBoolByKey (key) = match getBoolean(this, key) {
2121 case a: Boolean =>
2222 a
2323 case _ =>
2424 false
2525 }
2626
2727
2828 func getNumberByAddressAndKey (address,key) = match getInteger(addressFromStringValue(address), key) {
2929 case a: Int =>
3030 a
3131 case _ =>
3232 0
3333 }
3434
3535
3636 func getStringByAddressAndKey (address,key) = match getString(addressFromStringValue(address), key) {
3737 case a: String =>
3838 a
3939 case _ =>
4040 ""
4141 }
4242
4343
4444 func getBoolByAddressAndKey (address,key) = match getBoolean(addressFromStringValue(address), key) {
4545 case a: Boolean =>
4646 a
4747 case _ =>
4848 false
4949 }
5050
5151
5252 let SENDTXEXPIRE = 30
5353
5454 let LISTSPLITSYMBOL = "_"
5555
5656 let LISTDATASYMBOL = "+"
5757
5858 let WAVELET = 100000000
5959
6060 let PAULI = 100
6161
6262 let CRYTICALSHARE = 20
6363
6464 let LEASINGSHARE = 90
6565
6666 let LEASINTXCOUNT = 10
6767
68+let DEFICITOFFSET = 10
69+
70+let WAVESASSETID = "waves"
71+
6872 let CANCELED = "canceled"
6973
7074 let NEW = "new"
71-
72-let FILLED = "filled"
7375
7476 let NeutrinoAssetIdKey = "neutrino_asset_id"
7577
7678 let BondAssetIdKey = "bond_asset_id"
7779
7880 let ReserveContractKey = "reserve_contract"
7981
8082 let AuctionContractKey = "auction_contract"
83+
84+let LiquidationContractKey = "liquidation_contract"
8185
8286 let RPDContractKey = "rpd_contract"
8387
8488 let ContolContractKey = "control_contract"
8589
8690 let BalanceLockIntervalKey = "balance_lock_interval"
8791
8892 let MinWavesSwapAmountKey = "min_waves_swap_amount"
8993
9094 let MinNeutrinoSwapAmountKey = "min_neutrino_swap_amount"
9195
9296 let NodeAddressKey = "node_address"
9397
98+let NodeOracleProviderKey = "oracle_node_provider"
99+
94100 let LeasingIntervalKey = "leasing_interval"
101+
102+let RPDBalanceKey = "rpd_balance"
103+
104+func getRPDContractBalanceKey (assetId) = ((RPDBalanceKey + "_") + toBase58String(assetId))
105+
106+
107+let TotalOrderbookKey = "total_orderbook"
108+
109+let TotalLiquidationOrderbookKey = "total_liquidation_orderbook"
95110
96111 let PriceKey = "price"
97112
98113 let PriceIndexKey = "price_index"
99114
100-let ScriptUpdateIntervalKey = "script_update_interval"
101-
102-let NeutrinoBalanceKey = "neutrino_"
103-
104-let WavesBalanceKey = "waves_"
105-
106-let BalanceUnlockBlockKey = "balance_block_"
107-
108-let OrderbookKey = "orderbook"
109-
110-let OrderTotalKey = "order_total_"
111-
112-let OrderOwnerKey = "order_owner_"
113-
114-let OrderHeightKey = "order_height_"
115-
116-let OrderFilledTotalKey = "order_filled_total_"
117-
118-let OrderStatusKey = "order_status_"
119-
120-let RPDSyncIndexKey = "rpd_sync_index"
121-
122-let RPDProfitKey = "rpd_profit"
123-
124-let RPDBalanceKey = "rpd_balance"
125-
126115 let IsBlockedKey = "is_blocked"
127-
128-let IsLeasingProfitTxExistKey = "is_leasing_profit"
129-
130-let ScriptUpdateBlockKey = "script_update_block"
131-
132-let LeaseTxKey = "lease_tx"
133-
134-let LeaseTxStatusKey = "lease_tx_status"
135-
136-let LeasingAmountKey = "leasing_amount"
137-
138-let LeaseTxExpireSendBlockKey = "leasing_expire_send"
139116
140117 let LeasingExpireBlockKey = "leasing_expire_block"
141118
142119 let IsRebalanceKey = "is_rebalance"
143120
144-let SwapLockedBalanceKey = "swap_locked_balance"
145-
146-let SwapNeutrinoLockedBalanceKey = "swap_neutrino_locked_balance"
147-
148121 let LeasingTxCountKey = "leasing_index"
149122
150-func getRPDSnapshotContractBalanceKey (count,assetId) = ((((RPDBalanceKey + "_") + toBase58String(assetId)) + "_") + toString(count))
151-
152-
153-func getRPDContractBalanceKey (assetId) = ((RPDBalanceKey + "_") + toBase58String(assetId))
154-
155-
156-func getRPDProfitKey (count) = ((RPDProfitKey + "_") + toString(count))
157-
158-
159-func getNeutrinoBalanceKey (owner) = (NeutrinoBalanceKey + owner)
160-
161-
162-func getWavesBalanceKey (owner) = (WavesBalanceKey + owner)
163-
164-
165-func getBalanceUnlockBlockKey (owner) = (BalanceUnlockBlockKey + owner)
166-
167-
168-func getOrderTotalKey (orderId) = (OrderTotalKey + orderId)
169-
170-
171-func getOrderOwnerKey (orderId) = (OrderOwnerKey + orderId)
172-
173-
174-func getOrderHeightKey (orderId) = (OrderHeightKey + orderId)
175-
176-
177-func getOrderStatusKey (orderId) = (OrderStatusKey + orderId)
178-
179-
180-func getOrderFilledTotalKey (orderId) = (OrderFilledTotalKey + orderId)
181-
123+let LeasingAmountKey = "leasing_amount"
182124
183125 func getPriceHistoryKey (block) = ((PriceKey + "_") + toString(block))
184126
185127
186128 func getHeightPriceByIndexKey (index) = ((PriceIndexKey + "_") + toString(index))
187129
188130
189-func getLeaseTxStatusKey (hash) = ((LeaseTxStatusKey + "_") + hash)
131+let RPDSyncIndexKey = "rpd_sync_index"
132+
133+func getRPDSnapshotContractBalanceKey (count,assetId) = ((((RPDBalanceKey + "_") + toBase58String(assetId)) + "_") + toString(count))
134+
135+
136+func getCancelLeaseTxReserveFeeKey (hash) = (("cancel_lease_tx_reserve_fee" + "_") + hash)
137+
138+
139+func getAccountLockedBalanceKey (owner,assetId) = ((("balance_" + assetId) + "_") + owner)
140+
141+
142+func getBalanceUnlockBlockKey (owner) = ("balance_block_" + owner)
143+
144+
145+func getRPDProfitKey (count) = (("rpd_profit" + "_") + toString(count))
146+
147+
148+func getLockedBalanceKey (assetId) = ("balance_" + assetId)
149+
150+
151+func getLeaseTxStatusKey (hash) = (("lease_tx_status" + "_") + hash)
190152
191153
192154 func getLeaseTxAmountByHashKey (hash) = ((LeasingAmountKey + "_") + hash)
193155
194156
195-func getLeaseTxBytesByHashKey (hash) = ((LeaseTxKey + "_") + hash)
157+func getLeaseTxBytesByHashKey (hash) = (("lease_tx" + "_") + hash)
196158
197159
198-func getLeaseTxExpireSendBlockKey (hash) = ((LeaseTxExpireSendBlockKey + "_") + hash)
160+func getLeaseTxExpireSendBlockKey (hash) = (("leasing_expire_send" + "_") + hash)
199161
200162
201-func getIsRebalanceByAddressKey (address) = ((IsRebalanceKey + "_") + address)
163+func convertNeutrinoToWaves (amount,price) = ((((amount * 100) / price) * WAVELET) / PAULI)
202164
203165
204-let controlContract = getStringByKey(ContolContractKey)
205-
206-let price = getNumberByAddressAndKey(controlContract, PriceKey)
207-
208-let priceIndex = getNumberByAddressAndKey(controlContract, PriceIndexKey)
209-
210-func convertNeutrinoToWavesByPrice (amount,convertPrice) = ((((amount * 100) / convertPrice) * WAVELET) / PAULI)
211-
212-
213-func convertNeutrinoToWaves (amount) = ((((amount * 100) / price) * WAVELET) / PAULI)
214-
215-
216-func convertWavesToNeutrino (amount) = ((((amount * price) / 100) * PAULI) / WAVELET)
166+func convertWavesToNeutrino (amount,price) = ((((amount * price) / 100) * PAULI) / WAVELET)
217167
218168
219169 func convertNeutrinoToBond (amount) = (amount / PAULI)
220170
221171
222172 func convertBondToNeutrino (amount) = (amount * PAULI)
223173
224174
225-func convertWavesToBond (amount) = convertNeutrinoToBond(convertWavesToNeutrino(amount))
175+func convertWavesToBond (amount,price) = convertNeutrinoToBond(convertWavesToNeutrino(amount, price))
226176
177+
178+func getLockedBalance (assetId) = getNumberByKey(getLockedBalanceKey(assetId))
179+
180+
181+let liquidationContract = getStringByKey(LiquidationContractKey)
182+
183+let neutrinoAssetIdString = getStringByKey(NeutrinoAssetIdKey)
184+
185+let neutrinoAssetId = fromBase58String(neutrinoAssetIdString)
186+
187+let reserveContract = getStringByKey(ReserveContractKey)
188+
189+let auctionContract = getStringByKey(AuctionContractKey)
190+
191+let rpdContract = getStringByKey(RPDContractKey)
192+
193+let controlContract = getStringByKey(ContolContractKey)
194+
195+let currentPrice = getNumberByAddressAndKey(controlContract, PriceKey)
196+
197+let priceIndex = getNumberByAddressAndKey(controlContract, PriceIndexKey)
198+
199+let isBlocked = getBoolByAddressAndKey(controlContract, IsBlockedKey)
227200
228201 let leasingTxCount = getNumberByKey(LeasingTxCountKey)
229202
230203 let isRebalance = getBoolByKey(IsRebalanceKey)
231204
232205 let leasingInterval = getNumberByKey(LeasingIntervalKey)
233206
234207 let leasingExpireBlock = getNumberByKey(LeasingExpireBlockKey)
235208
236209 let leasingAmount = getNumberByKey(LeasingAmountKey)
237210
238-let swapNeutrinoLockedBalance = getNumberByKey(SwapNeutrinoLockedBalanceKey)
239-
240-let swapWavesLockedBalance = getNumberByKey(SwapLockedBalanceKey)
241-
242211 let nodeAddress = getStringByKey(NodeAddressKey)
243212
244-let scriptUpdateInterval = getNumberByAddressAndKey(ContolContractKey, ScriptUpdateIntervalKey)
245-
246-let scriptUpdateBlock = getNumberByAddressAndKey(controlContract, ScriptUpdateBlockKey)
213+let nodeOracleProviderKey = getStringByKey(NodeOracleProviderKey)
247214
248215 let rpdSyncIndex = getNumberByKey(RPDSyncIndexKey)
249216
250217 let balanceLockInterval = getNumberByKey(BalanceLockIntervalKey)
251218
252-let isBlocked = getBoolByAddressAndKey(controlContract, IsBlockedKey)
253-
254219 let minWavesSwapAmount = getNumberByKey(MinWavesSwapAmountKey)
255220
256221 let minNeutrinoSwapAmount = getNumberByKey(MinNeutrinoSwapAmountKey)
257222
258-let neutrinoAssetId = fromBase58String(getStringByKey(NeutrinoAssetIdKey))
259-
260-let reserveContract = getStringByKey(ReserveContractKey)
261-
262-let auctionContract = getStringByKey(AuctionContractKey)
263-
264-let rpdContract = getStringByKey(RPDContractKey)
265-
266-let reserve = (wavesBalance(this) - swapWavesLockedBalance)
223+let reserve = (wavesBalance(this) - getLockedBalance(WAVESASSETID))
267224
268225 let reserveWithoutLeasing = (reserve - leasingAmount)
269226
270-let orderbook = getStringByKey(OrderbookKey)
271-
272227 let bondAssetId = fromBase58String(getStringByKey(BondAssetIdKey))
273228
274-let bondSupply = {
275- let info = extract(assetInfo(bondAssetId))
276- (info.quantity - assetBalance(this, bondAssetId))
277- }
229+let bondSupply = (extract(assetInfo(bondAssetId)).quantity - assetBalance(this, bondAssetId))
278230
279-let neutrinoSupply = {
280- let info = extract(assetInfo(neutrinoAssetId))
281- ((info.quantity - assetBalance(this, neutrinoAssetId)) + swapNeutrinoLockedBalance)
282- }
231+let neutrinoSupply = ((extract(assetInfo(neutrinoAssetId)).quantity - assetBalance(this, neutrinoAssetId)) + getLockedBalance(neutrinoAssetIdString))
283232
284-let surplus = (convertWavesToNeutrino(reserve) - neutrinoSupply)
233+let surplus = (convertWavesToNeutrino(reserve, currentPrice) - neutrinoSupply)
285234
286-let deficit = (neutrinoSupply - convertWavesToNeutrino(reserve))
235+let deficit = (neutrinoSupply - convertWavesToNeutrino(reserve, currentPrice))
287236
288237 func getRPDContractBalance (assetId) = getNumberByAddressAndKey(rpdContract, getRPDContractBalanceKey(assetId))
289238
290239
291-func getWavesBalance (owner) = getNumberByKey(getWavesBalanceKey(owner))
240+let totalLiquidationOrderbook = getNumberByAddressAndKey(auctionContract, TotalLiquidationOrderbookKey)
241+
242+let totalOrderbook = getNumberByAddressAndKey(auctionContract, TotalOrderbookKey)
243+
244+func getPriceHistory (block) = getNumberByAddressAndKey(controlContract, getPriceHistoryKey(block))
292245
293246
294-func getNeutrinoBalance (owner) = getNumberByKey(getNeutrinoBalanceKey(owner))
247+func getHeightPriceByIndex (index) = getNumberByAddressAndKey(controlContract, getHeightPriceByIndexKey(index))
248+
249+
250+func getCancelLeaseTxReserveFee (hash) = getNumberByKey(getCancelLeaseTxReserveFeeKey(hash))
251+
252+
253+func getAccountLockedBalance (owner,assetId) = getNumberByKey(getAccountLockedBalanceKey(owner, assetId))
295254
296255
297256 func getUnlockBalanceBlock (owner) = getNumberByKey(getBalanceUnlockBlockKey(owner))
298257
299258
300-func getOrderTotal (id) = getNumberByKey(getOrderTotalKey(id))
301-
302-
303-func getOrderOwner (id) = getStringByKey(getOrderOwnerKey(id))
304-
305-
306-func getOrderStatus (id) = getStringByKey(getOrderStatusKey(id))
307-
308-
309-func getOrderFilledTotal (id) = getNumberByKey(getOrderFilledTotalKey(id))
310-
311-
312259 func getRPDProfit (count) = getNumberByKey(getRPDProfitKey(count))
313-
314-
315-func getPriceHistory (block) = getNumberByAddressAndKey(controlContract, getPriceHistoryKey(block))
316-
317-
318-func getHeightPriceByIndex (index) = getNumberByAddressAndKey(controlContract, getHeightPriceByIndexKey(index))
319260
320261
321262 func getLeaseTxStatus (hash) = getStringByKey(getLeaseTxStatusKey(hash))
322263
323264
324265 func getLeaseTxAmountByHash (hash) = getNumberByKey(getLeaseTxAmountByHashKey(hash))
325266
326267
327268 func getLeaseTxBytesByHash (hash) = getStringByKey(getLeaseTxBytesByHashKey(hash))
328269
329270
330271 func getLeaseTxExpireSendBlock (hash) = getNumberByKey(getLeaseTxExpireSendBlockKey(hash))
331272
332273
333-func getOrderElementById (id) = (id + LISTSPLITSYMBOL)
334-
335-
336-func addOrder (orderId) = (orderbook + getOrderElementById(orderId))
337-
338-
339-func dropOrder (orderId) = {
340- let parts = split(orderbook, getOrderElementById(orderId))
341- (parts[0] + parts[1])
342- }
343-
344-
345274 @Callable(i)
346275 func swapWavesToNeutrino () = {
347276 let pmt = extract(i.payment)
277+ let account = toString(i.caller)
348278 if ((minWavesSwapAmount > pmt.amount))
349- then throw("amount less min")
279+ then throw((("an amount is less than min available amount: " + toString(minWavesSwapAmount)) + " wavelets"))
350280 else if (isDefined(pmt.assetId))
351281 then throw("can use waves only")
352282 else if (isBlocked)
353- then throw("contract is blocked")
354- else {
355- let amount = convertWavesToNeutrino(pmt.amount)
356- TransferSet([ScriptTransfer(i.caller, amount, neutrinoAssetId)])
357- }
283+ then throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
284+ else if ((getUnlockBalanceBlock(account) > height))
285+ then throw((("await " + toString((getUnlockBalanceBlock(account) - height))) + " blocks"))
286+ else if ((getAccountLockedBalance(account, WAVESASSETID) != 0))
287+ then throw("please withdraw locked funds first")
288+ else WriteSet([DataEntry(getAccountLockedBalanceKey(account, WAVESASSETID), pmt.amount), DataEntry(getBalanceUnlockBlockKey(account), (height + balanceLockInterval)), DataEntry(getLockedBalanceKey(WAVESASSETID), (getLockedBalance(WAVESASSETID) + pmt.amount))])
358289 }
359290
360291
361292
362293 @Callable(i)
363294 func swapNeutrinoToWaves () = {
364295 let pmt = extract(i.payment)
365296 let account = toString(i.caller)
366297 if ((minNeutrinoSwapAmount > pmt.amount))
367- then throw("amount less min")
298+ then throw((("an amount is less than min available amount: " + toString(minNeutrinoSwapAmount)) + " neutrino cents"))
368299 else if (isBlocked)
369- then throw("contract is blocked")
300+ then throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
370301 else if ((pmt.assetId != neutrinoAssetId))
371- then throw("can use neutrino only")
302+ then throw("can use appropriate neutrino tokens only")
372303 else if ((getUnlockBalanceBlock(account) > height))
373304 then throw((("await " + toString((getUnlockBalanceBlock(account) - height))) + " blocks"))
374- else if ((getNeutrinoBalance(account) != 0))
375- then throw("use withdraw")
305+ else if ((getAccountLockedBalance(account, neutrinoAssetIdString) != 0))
306+ then throw("please withdraw locked funds first")
376307 else {
377- let neutrinoAmount = pmt.amount
378- let newSwapNeutrinoLockedBalance = (swapNeutrinoLockedBalance + neutrinoAmount)
379- WriteSet([DataEntry(getNeutrinoBalanceKey(account), (getNeutrinoBalance(account) + neutrinoAmount)), DataEntry(getBalanceUnlockBlockKey(account), (height + balanceLockInterval)), DataEntry(SwapNeutrinoLockedBalanceKey, newSwapNeutrinoLockedBalance), DataEntry(IsRebalanceKey, if ((reserveWithoutLeasing >= convertNeutrinoToWaves(newSwapNeutrinoLockedBalance)))
308+ let newLockedBalance = (getLockedBalance(neutrinoAssetIdString) + pmt.amount)
309+ WriteSet([DataEntry(getAccountLockedBalanceKey(account, neutrinoAssetIdString), pmt.amount), DataEntry(getBalanceUnlockBlockKey(account), (height + balanceLockInterval)), DataEntry(getLockedBalanceKey(neutrinoAssetIdString), newLockedBalance), DataEntry(IsRebalanceKey, if ((reserveWithoutLeasing >= convertNeutrinoToWaves(newLockedBalance, currentPrice)))
380310 then false
381311 else true)])
382312 }
383313 }
384314
385315
386316
387317 @Callable(i)
388-func withdraw (account,index) = {
318+func withdraw (account,index,lockedAssetId) = {
319+ let unlockHeight = getUnlockBalanceBlock(account)
320+ let lockedBalance = getAccountLockedBalance(account, lockedAssetId)
389321 let indexHeight = getHeightPriceByIndex(index)
390322 let nextIndexHeight = getHeightPriceByIndex((index + 1))
391- let unlockHeight = getUnlockBalanceBlock(account)
392- let neutrinoAmount = getNeutrinoBalance(account)
393- let indexPrice = getPriceHistory(indexHeight)
394- let amount = convertNeutrinoToWavesByPrice(neutrinoAmount, indexPrice)
395- let totalWavesWithdraw = (getWavesBalance(account) + amount)
323+ let priceByIndex = getPriceHistory(indexHeight)
324+ let amount = if ((lockedAssetId == neutrinoAssetIdString))
325+ then convertNeutrinoToWaves(lockedBalance, priceByIndex)
326+ else convertWavesToNeutrino(lockedBalance, priceByIndex)
396327 if (isBlocked)
397- then throw("contract is blocked")
398- else if ((unlockHeight > height))
399- then throw("wait a couple of blocks for withdraw")
400- else if (if (if ((index > priceIndex))
401- then true
402- else (indexHeight > unlockHeight))
403- then true
404- else if ((nextIndexHeight != 0))
405- then (unlockHeight >= nextIndexHeight)
406- else false)
407- then throw("invalid index")
408- else ScriptResult(WriteSet([DataEntry(getWavesBalanceKey(account), 0), DataEntry(getNeutrinoBalanceKey(account), 0), DataEntry(SwapLockedBalanceKey, (swapWavesLockedBalance - getWavesBalance(account))), DataEntry(SwapNeutrinoLockedBalanceKey, (swapNeutrinoLockedBalance - neutrinoAmount))]), TransferSet([ScriptTransfer(addressFromStringValue(account), totalWavesWithdraw, unit)]))
328+ then throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
329+ else if ((0 >= amount))
330+ then throw((("balance equals zero (" + lockedAssetId) + ")"))
331+ else if ((unlockHeight > height))
332+ then throw((("please wait for: " + toString(unlockHeight)) + " block height to withdraw WAVES funds"))
333+ else if (if (if ((index > priceIndex))
334+ then true
335+ else (indexHeight > unlockHeight))
336+ then true
337+ else if ((nextIndexHeight != 0))
338+ then (unlockHeight >= nextIndexHeight)
339+ else false)
340+ then throw("invalid price history index")
341+ else ScriptResult(WriteSet([DataEntry(getAccountLockedBalanceKey(account, lockedAssetId), 0), DataEntry(getLockedBalanceKey(lockedAssetId), (getLockedBalance(lockedAssetId) - lockedBalance))]), TransferSet([ScriptTransfer(addressFromStringValue(account), amount, if ((lockedAssetId == neutrinoAssetIdString))
342+ then unit
343+ else neutrinoAssetId)]))
409344 }
410345
411346
412347
413348 @Callable(i)
414-func generateBond () = {
415- let balanceAuction = assetBalance(addressFromStringValue(auctionContract), bondAssetId)
416- let amount = (convertNeutrinoToBond(deficit) - balanceAuction)
349+func transferToAuction () = {
350+ let deficitBondAmount = ((convertNeutrinoToBond(deficit) - assetBalance(addressFromStringValue(auctionContract), bondAssetId)) - totalLiquidationOrderbook)
351+ let surplusBond = ((convertNeutrinoToBond(surplus) - assetBalance(addressFromStringValue(auctionContract), neutrinoAssetId)) - totalOrderbook)
417352 if (isBlocked)
418- then throw("contract is blocked")
419- else if ((amount >= 10))
420- then TransferSet([ScriptTransfer(addressFromStringValue(auctionContract), amount, bondAssetId)])
421- else throw("bond were generated or do not need it")
422- }
423-
424-
425-
426-@Callable(i)
427-func setOrder () = {
428- let pmt = extract(i.payment)
429- let newOrderId = toBase58String(keccak256(((toBytes(pmt.amount) + i.caller.bytes) + toBytes(height))))
430- if ((pmt.assetId != bondAssetId))
431- then throw("can use bond only")
432- else if ((getOrderOwner(newOrderId) != ""))
433- then throw("order exists")
434- else WriteSet([DataEntry(OrderbookKey, addOrder(newOrderId)), DataEntry(getOrderTotalKey(newOrderId), pmt.amount), DataEntry(getOrderOwnerKey(newOrderId), toString(i.caller)), DataEntry(getOrderHeightKey(newOrderId), height), DataEntry(getOrderStatusKey(newOrderId), NEW)])
435- }
436-
437-
438-
439-@Callable(i)
440-func cancelOrder (orderId) = {
441- let owner = getOrderOwner(orderId)
442- let amount = (getOrderTotal(orderId) - getOrderFilledTotal(orderId))
443- if ((owner != toString(i.caller)))
444- then throw("permission denied")
445- else if ((getOrderStatus(orderId) != NEW))
446- then throw("invalid order status")
447- else ScriptResult(WriteSet([DataEntry(OrderbookKey, dropOrder(orderId)), DataEntry(getOrderStatusKey(orderId), CANCELED)]), TransferSet([ScriptTransfer(i.caller, amount, bondAssetId)]))
448- }
449-
450-
451-
452-@Callable(i)
453-func executeOrder () = {
454- let orderId = split(orderbook, LISTSPLITSYMBOL)[0]
455- let orderTotal = getOrderTotal(orderId)
456- let orderOwner = getOrderOwner(orderId)
457- let filledTotal = getOrderFilledTotal(orderId)
458- let surplusBond = convertNeutrinoToBond(surplus)
459- if (isBlocked)
460- then throw("contract is blocked")
461- else if ((0 >= surplusBond))
462- then throw("surplus is less than zero")
463- else if (if ((orderOwner == ""))
464- then (surplusBond >= 10)
465- else false)
466- then {
467- let newRpdSyncIndex = (rpdSyncIndex + 1)
468- ScriptResult(WriteSet([DataEntry(RPDSyncIndexKey, newRpdSyncIndex), DataEntry(getRPDProfitKey(rpdSyncIndex), surplus), DataEntry(getRPDSnapshotContractBalanceKey(rpdSyncIndex, neutrinoAssetId), getRPDContractBalance(neutrinoAssetId))]), TransferSet([ScriptTransfer(addressFromStringValue(rpdContract), surplus, neutrinoAssetId)]))
469- }
470- else {
471- let amount = (orderTotal - filledTotal)
472- let status = if ((surplusBond >= amount))
473- then FILLED
474- else NEW
475- let newFilledTotal = if ((surplusBond >= amount))
476- then amount
477- else surplusBond
478- ScriptResult(WriteSet([DataEntry(OrderbookKey, if ((surplusBond >= amount))
479- then dropOrder(orderId)
480- else orderbook), DataEntry(getOrderFilledTotalKey(orderId), (filledTotal + newFilledTotal)), DataEntry(getOrderStatusKey(orderId), status)]), TransferSet([ScriptTransfer(addressFromStringValue(orderOwner), convertBondToNeutrino(newFilledTotal), neutrinoAssetId)]))
481- }
353+ then throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
354+ else if ((deficitBondAmount >= ((neutrinoSupply * DEFICITOFFSET) / 100)))
355+ then TransferSet([ScriptTransfer(addressFromStringValue(auctionContract), deficitBondAmount, bondAssetId)])
356+ else if ((surplusBond > 0))
357+ then TransferSet([ScriptTransfer(addressFromStringValue(liquidationContract), convertBondToNeutrino(surplusBond), neutrinoAssetId)])
358+ else throw("bond were generated or do not need it")
482359 }
483360
484361
485362
486363 @Callable(i)
487364 func transfer (account) = {
488365 let pmt = extract(i.payment)
489366 TransferSet([ScriptTransfer(addressFromStringValue(account), pmt.amount, pmt.assetId)])
490367 }
491368
492369
493370
494371 @Callable(i)
495372 func nodeReward () = {
496373 let pmt = value(i.payment)
497374 if ((i.caller != addressFromStringValue(nodeAddress)))
498- then throw("permission denied")
375+ then throw("only node account is able to transfer staking rewards from main account")
499376 else if (isDefined(pmt.assetId))
500- then throw("waves only")
377+ then throw("waves tokens only allowed")
501378 else {
502- let amount = convertWavesToNeutrino(pmt.amount)
379+ let amount = convertWavesToNeutrino(pmt.amount, currentPrice)
503380 let newRpdSyncIndex = (rpdSyncIndex + 1)
504381 ScriptResult(WriteSet([DataEntry(RPDSyncIndexKey, newRpdSyncIndex), DataEntry(getRPDProfitKey(rpdSyncIndex), amount), DataEntry(getRPDSnapshotContractBalanceKey(rpdSyncIndex, neutrinoAssetId), getRPDContractBalance(neutrinoAssetId))]), TransferSet([ScriptTransfer(addressFromStringValue(rpdContract), amount, neutrinoAssetId)]))
505382 }
506383 }
507384
508385
509386
510387 @Callable(i)
511388 func registrationLeaseTx (senderPublicKey,fee,timestamp,leaseTxHash) = {
512- let totalFreeReserve = (((reserve * LEASINGSHARE) / 100) - convertNeutrinoToWaves(swapNeutrinoLockedBalance))
389+ let totalFreeReserve = (((reserve * LEASINGSHARE) / 100) - convertNeutrinoToWaves(getLockedBalance(neutrinoAssetIdString), currentPrice))
513390 let amount = (totalFreeReserve / LEASINTXCOUNT)
514391 let txBytes = (((((base58'3h1H' + fromBase58String(senderPublicKey)) + fromBase58String(nodeAddress)) + toBytes(amount)) + toBytes(fee)) + toBytes(timestamp))
515392 let txHashBytes = blake2b256(txBytes)
516393 let txHash = toBase58String(txHashBytes)
517- if ((leaseTxHash != txHash))
518- then throw("invalid tx hash")
519- else if ((leasingTxCount >= LEASINTXCOUNT))
520- then throw("the number of leasing transactions is equal to the maximum")
521- else if ((this != addressFromPublicKey(fromBase58String(senderPublicKey))))
522- then throw("invalid pubKey")
523- else if (if ((lastBlock.timestamp > timestamp))
524- then true
525- else (timestamp > (lastBlock.timestamp + 5400000)))
526- then throw((("invalid timestamp(lastBlock: " + toString(lastBlock.timestamp)) + ")"))
527- else if ((getLeaseTxStatus(txHash) == ""))
528- then throw("tx is exist")
529- else if (if ((fee > 1000000))
394+ let pmt = extract(i.payment)
395+ if ((toString(i.caller) == nodeOracleProviderKey))
396+ then throw("invalid caller")
397+ else if (isDefined(pmt.assetId))
398+ then throw("invalid paymtn asset")
399+ else if ((leaseTxHash != txHash))
400+ then throw((("invalid tx hash(amount:" + toString(amount)) + ")"))
401+ else if ((leasingTxCount >= LEASINTXCOUNT))
402+ then throw("the number of leasing transactions is equal to the maximum")
403+ else if ((this != addressFromPublicKey(fromBase58String(senderPublicKey))))
404+ then throw("invalid pubKey")
405+ else if (if ((lastBlock.timestamp > timestamp))
530406 then true
531- else (500000 > fee))
532- then throw("invalid fee")
533- else if (((totalFreeReserve - (leasingAmount + amount)) > reserveWithoutLeasing))
534- then throw((("invalid amount(result:" + toString(((totalFreeReserve - (leasingAmount + amount)) > reserveWithoutLeasing))) + ")"))
535- else WriteSet([DataEntry(LeasingTxCountKey, if ((getLeaseTxStatus(txHash) == ""))
536- then (leasingTxCount + 1)
537- else leasingTxCount), DataEntry(LeasingAmountKey, (leasingAmount + amount)), DataEntry(LeasingExpireBlockKey, if ((height > leasingExpireBlock))
538- then (height + leasingInterval)
539- else leasingExpireBlock), DataEntry(getLeaseTxStatusKey(txHash), NEW), DataEntry(getLeaseTxExpireSendBlockKey(txHash), (height + SENDTXEXPIRE)), DataEntry(getLeaseTxAmountByHashKey(txHash), amount), DataEntry(getLeaseTxBytesByHashKey(txHash), toBase64String(txBytes))])
407+ else (timestamp > (lastBlock.timestamp + 5400000)))
408+ then throw((("invalid timestamp(lastBlock: " + toString(lastBlock.timestamp)) + ")"))
409+ else if ((getLeaseTxStatus(txHash) != ""))
410+ then throw("tx is exist")
411+ else if ((pmt.amount != (fee * 2)))
412+ then throw("invalid payment amount")
413+ else if (if ((fee > 1000000))
414+ then true
415+ else (500000 > fee))
416+ then throw("invalid fee")
417+ else if (((totalFreeReserve - (leasingAmount + amount)) > reserveWithoutLeasing))
418+ then throw((("invalid amount(result:" + toString(((totalFreeReserve - (leasingAmount + amount)) > reserveWithoutLeasing))) + ")"))
419+ else WriteSet([DataEntry(getCancelLeaseTxReserveFeeKey(txHash), fee), DataEntry(LeasingTxCountKey, if ((getLeaseTxStatus(txHash) == ""))
420+ then (leasingTxCount + 1)
421+ else leasingTxCount), DataEntry(LeasingAmountKey, (leasingAmount + amount)), DataEntry(LeasingExpireBlockKey, if ((height > leasingExpireBlock))
422+ then (height + leasingInterval)
423+ else leasingExpireBlock), DataEntry(getLeaseTxStatusKey(txHash), NEW), DataEntry(getLeaseTxExpireSendBlockKey(txHash), (height + SENDTXEXPIRE)), DataEntry(getLeaseTxAmountByHashKey(txHash), amount), DataEntry(getLeaseTxBytesByHashKey(txHash), toBase64String(txBytes))])
540424 }
541425
542426
543427
544428 @Callable(i)
545429 func cancelStuckLeaseTx (txHash) = if (if (if ((getLeaseTxStatus(txHash) == NEW))
546430 then !(isDefined(transactionHeightById(fromBase58String(txHash))))
547431 else false)
548432 then (height > getLeaseTxExpireSendBlock(txHash))
549433 else false)
550434 then {
551435 let amount = getLeaseTxAmountByHash(txHash)
552- WriteSet([DataEntry(LeasingTxCountKey, (leasingTxCount - 1)), DataEntry(LeasingAmountKey, (leasingAmount - amount)), DataEntry(getLeaseTxStatusKey(txHash), CANCELED), DataEntry(IsRebalanceKey, if (((reserveWithoutLeasing - amount) >= convertNeutrinoToWaves(swapNeutrinoLockedBalance)))
436+ WriteSet([DataEntry(LeasingTxCountKey, (leasingTxCount - 1)), DataEntry(LeasingAmountKey, (leasingAmount - amount)), DataEntry(getLeaseTxStatusKey(txHash), CANCELED), DataEntry(IsRebalanceKey, if (((reserveWithoutLeasing - amount) >= convertNeutrinoToWaves(getLockedBalance(neutrinoAssetIdString), currentPrice)))
553437 then false
554438 else true)])
555439 }
556440 else throw("invalid tx hash")
557441
558442
559443
560444 @Callable(i)
561445 func registrationUnleaseTx (chainIdString,senderPublicKey,fee,timestamp,leaseTxHash) = {
562446 let txBytes = (((((base58'gm' + toBytes(chainIdString)) + fromBase58String(senderPublicKey)) + toBytes(fee)) + toBytes(timestamp)) + fromBase58String(leaseTxHash))
563447 let txHash = blake2b256(txBytes)
564448 if ((getLeaseTxStatus(leaseTxHash) != NEW))
565449 then throw("invalid tx status")
566450 else if ((this != addressFromPublicKey(fromBase58String(senderPublicKey))))
567451 then throw("invalid pubKey")
568452 else if (!(isDefined(transactionHeightById(txHash))))
569453 then throw("blockchain does not contain this transaction")
570454 else {
571455 let amount = getLeaseTxAmountByHash(leaseTxHash)
572- WriteSet([DataEntry(LeasingTxCountKey, (leasingTxCount - 1)), DataEntry(LeasingAmountKey, (leasingAmount - amount)), DataEntry(getLeaseTxStatusKey(leaseTxHash), CANCELED), DataEntry(IsRebalanceKey, if (((reserveWithoutLeasing - amount) >= convertNeutrinoToWaves(swapNeutrinoLockedBalance)))
456+ WriteSet([DataEntry(LeasingTxCountKey, (leasingTxCount - 1)), DataEntry(LeasingAmountKey, (leasingAmount - amount)), DataEntry(getLeaseTxStatusKey(leaseTxHash), CANCELED), DataEntry(IsRebalanceKey, if (((reserveWithoutLeasing - amount) >= convertNeutrinoToWaves(getLockedBalance(neutrinoAssetIdString), currentPrice)))
573457 then false
574458 else true)])
575459 }
576460 }
577461
578462
579463 @Verifier(tx)
580464 func verify () = {
581465 let id = toBase58String(tx.id)
582466 match tx {
583467 case leaseTx: LeaseTransaction =>
584468 if (if ((leasingExpireBlock >= height))
585469 then (getLeaseTxExpireSendBlock(id) >= height)
586470 else false)
587- then (getLeaseTxStatusKey(id) == NEW)
471+ then (getLeaseTxStatus(id) == NEW)
588472 else false
589473 case unleaseTx: LeaseCancelTransaction =>
474+ let leaseId = toBase58String(unleaseTx.leaseId)
590475 if (if (if ((height > leasingExpireBlock))
591476 then true
592477 else isRebalance)
593- then if ((unleaseTx.fee >= 500000))
594- then (1000000 >= unleaseTx.fee)
595- else false
478+ then (unleaseTx.fee == getCancelLeaseTxReserveFee(leaseId))
596479 else false)
597- then (getLeaseTxStatusKey(toBase58String(unleaseTx.leaseId)) == NEW)
480+ then (getLeaseTxStatus(leaseId) == NEW)
598481 else false
599482 case _ =>
600483 sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
601484 }
602485 }
603486

github/deemru/w8io/026f985 
108.20 ms