tx · AjxmAyBmg6NhyfiEgatzbnCi3MfvUGqGVofNEry9Pjnf

3N4Pj4MutKVgrmcuX7jgyVGWoBhDyKYFZBj:  -0.01400000 Waves

2019.11.15 14:43 [766151] smart account 3N4Pj4MutKVgrmcuX7jgyVGWoBhDyKYFZBj > SELF 0.00000000 Waves

{ "type": 13, "id": "AjxmAyBmg6NhyfiEgatzbnCi3MfvUGqGVofNEry9Pjnf", "fee": 1400000, "feeAssetId": null, "timestamp": 1573818281326, "version": 1, "sender": "3N4Pj4MutKVgrmcuX7jgyVGWoBhDyKYFZBj", "senderPublicKey": "7YuxEiQSearE3DvFS84DXzV5gad9qxsq4bTy633SAYBj", "proofs": [ "UnHTE2JnkViA2msHLja3ubjEnjAZLwsa8QCYD4nZWy4bnbhdYAMEJm1x459NoUdcUAYhtx6GhKcvStHSYWQqxE9" ], "script": "base64:AAIDAAAAAAAAACwIARIAEgASBQoDCAEIEgASAwoBCBIAEgYKBAgBAQgSAwoBCBIHCgUICAEBCAAAAGYBAAAADmdldE51bWJlckJ5S2V5AAAAAQAAAANrZXkEAAAAByRtYXRjaDAJAAQaAAAAAgUAAAAEdGhpcwUAAAADa2V5AwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAANJbnQEAAAAAWEFAAAAByRtYXRjaDAFAAAAAWEAAAAAAAAAAAABAAAADmdldFN0cmluZ0J5S2V5AAAAAQAAAANrZXkEAAAAByRtYXRjaDAJAAQdAAAAAgUAAAAEdGhpcwUAAAADa2V5AwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAAZTdHJpbmcEAAAAAWEFAAAAByRtYXRjaDAFAAAAAWECAAAAAAEAAAAMZ2V0Qm9vbEJ5S2V5AAAAAQAAAANrZXkEAAAAByRtYXRjaDAJAAQbAAAAAgUAAAAEdGhpcwUAAAADa2V5AwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAAdCb29sZWFuBAAAAAFhBQAAAAckbWF0Y2gwBQAAAAFhBwEAAAAYZ2V0TnVtYmVyQnlBZGRyZXNzQW5kS2V5AAAAAgAAAAdhZGRyZXNzAAAAA2tleQQAAAAHJG1hdGNoMAkABBoAAAACCQEAAAAcQGV4dHJVc2VyKGFkZHJlc3NGcm9tU3RyaW5nKQAAAAEFAAAAB2FkZHJlc3MFAAAAA2tleQMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAADSW50BAAAAAFhBQAAAAckbWF0Y2gwBQAAAAFhAAAAAAAAAAAAAQAAABhnZXRTdHJpbmdCeUFkZHJlc3NBbmRLZXkAAAACAAAAB2FkZHJlc3MAAAADa2V5BAAAAAckbWF0Y2gwCQAEHQAAAAIJAQAAABxAZXh0clVzZXIoYWRkcmVzc0Zyb21TdHJpbmcpAAAAAQUAAAAHYWRkcmVzcwUAAAADa2V5AwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAAZTdHJpbmcEAAAAAWEFAAAAByRtYXRjaDAFAAAAAWECAAAAAAEAAAAWZ2V0Qm9vbEJ5QWRkcmVzc0FuZEtleQAAAAIAAAAHYWRkcmVzcwAAAANrZXkEAAAAByRtYXRjaDAJAAQbAAAAAgkBAAAAHEBleHRyVXNlcihhZGRyZXNzRnJvbVN0cmluZykAAAABBQAAAAdhZGRyZXNzBQAAAANrZXkDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAB0Jvb2xlYW4EAAAAAWEFAAAAByRtYXRjaDAFAAAAAWEHAAAAAAxTRU5EVFhFWFBJUkUAAAAAAAAAAB4AAAAAD0xJU1RTUExJVFNZTUJPTAIAAAABXwAAAAAOTElTVERBVEFTWU1CT0wCAAAAASsAAAAAB1dBVkVMRVQAAAAAAAX14QAAAAAABVBBVUxJAAAAAAAAAABkAAAAAA1DUllUSUNBTFNIQVJFAAAAAAAAAAAUAAAAAAxMRUFTSU5HU0hBUkUAAAAAAAAAAFoAAAAADUxFQVNJTlRYQ09VTlQAAAAAAAAAAAoAAAAADURFRklDSVRPRkZTRVQAAAAAAAAAAAoAAAAADFdBVkVTQVNTRVRJRAIAAAAFd2F2ZXMAAAAACENBTkNFTEVEAgAAAAhjYW5jZWxlZAAAAAADTkVXAgAAAANuZXcAAAAAEk5ldXRyaW5vQXNzZXRJZEtleQIAAAARbmV1dHJpbm9fYXNzZXRfaWQAAAAADkJvbmRBc3NldElkS2V5AgAAAA1ib25kX2Fzc2V0X2lkAAAAABJSZXNlcnZlQ29udHJhY3RLZXkCAAAAEHJlc2VydmVfY29udHJhY3QAAAAAEkF1Y3Rpb25Db250cmFjdEtleQIAAAAQYXVjdGlvbl9jb250cmFjdAAAAAAWTGlxdWlkYXRpb25Db250cmFjdEtleQIAAAAUbGlxdWlkYXRpb25fY29udHJhY3QAAAAADlJQRENvbnRyYWN0S2V5AgAAAAxycGRfY29udHJhY3QAAAAAEUNvbnRvbENvbnRyYWN0S2V5AgAAABBjb250cm9sX2NvbnRyYWN0AAAAABZCYWxhbmNlTG9ja0ludGVydmFsS2V5AgAAABViYWxhbmNlX2xvY2tfaW50ZXJ2YWwAAAAAFU1pbldhdmVzU3dhcEFtb3VudEtleQIAAAAVbWluX3dhdmVzX3N3YXBfYW1vdW50AAAAABhNaW5OZXV0cmlub1N3YXBBbW91bnRLZXkCAAAAGG1pbl9uZXV0cmlub19zd2FwX2Ftb3VudAAAAAAOTm9kZUFkZHJlc3NLZXkCAAAADG5vZGVfYWRkcmVzcwAAAAAVTm9kZU9yYWNsZVByb3ZpZGVyS2V5AgAAABRvcmFjbGVfbm9kZV9wcm92aWRlcgAAAAASTGVhc2luZ0ludGVydmFsS2V5AgAAABBsZWFzaW5nX2ludGVydmFsAAAAAA1SUERCYWxhbmNlS2V5AgAAAAtycGRfYmFsYW5jZQEAAAAYZ2V0UlBEQ29udHJhY3RCYWxhbmNlS2V5AAAAAQAAAAdhc3NldElkCQABLAAAAAIJAAEsAAAAAgUAAAANUlBEQmFsYW5jZUtleQIAAAABXwkAAlgAAAABBQAAAAdhc3NldElkAAAAABFUb3RhbE9yZGVyYm9va0tleQIAAAAPdG90YWxfb3JkZXJib29rAAAAABxUb3RhbExpcXVpZGF0aW9uT3JkZXJib29rS2V5AgAAABt0b3RhbF9saXF1aWRhdGlvbl9vcmRlcmJvb2sAAAAACFByaWNlS2V5AgAAAAVwcmljZQAAAAANUHJpY2VJbmRleEtleQIAAAALcHJpY2VfaW5kZXgAAAAADElzQmxvY2tlZEtleQIAAAAKaXNfYmxvY2tlZAAAAAAVTGVhc2luZ0V4cGlyZUJsb2NrS2V5AgAAABRsZWFzaW5nX2V4cGlyZV9ibG9jawAAAAAOSXNSZWJhbGFuY2VLZXkCAAAADGlzX3JlYmFsYW5jZQAAAAARTGVhc2luZ1R4Q291bnRLZXkCAAAADWxlYXNpbmdfaW5kZXgAAAAAEExlYXNpbmdBbW91bnRLZXkCAAAADmxlYXNpbmdfYW1vdW50AQAAABJnZXRQcmljZUhpc3RvcnlLZXkAAAABAAAABWJsb2NrCQABLAAAAAIJAAEsAAAAAgUAAAAIUHJpY2VLZXkCAAAAAV8JAAGkAAAAAQUAAAAFYmxvY2sBAAAAGGdldEhlaWdodFByaWNlQnlJbmRleEtleQAAAAEAAAAFaW5kZXgJAAEsAAAAAgkAASwAAAACBQAAAA1QcmljZUluZGV4S2V5AgAAAAFfCQABpAAAAAEFAAAABWluZGV4AAAAAA9SUERTeW5jSW5kZXhLZXkCAAAADnJwZF9zeW5jX2luZGV4AQAAACBnZXRSUERTbmFwc2hvdENvbnRyYWN0QmFsYW5jZUtleQAAAAIAAAAFY291bnQAAAAHYXNzZXRJZAkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACBQAAAA1SUERCYWxhbmNlS2V5AgAAAAFfCQACWAAAAAEFAAAAB2Fzc2V0SWQCAAAAAV8JAAGkAAAAAQUAAAAFY291bnQBAAAAHWdldENhbmNlbExlYXNlVHhSZXNlcnZlRmVlS2V5AAAAAQAAAARoYXNoCQABLAAAAAIJAAEsAAAAAgIAAAAbY2FuY2VsX2xlYXNlX3R4X3Jlc2VydmVfZmVlAgAAAAFfBQAAAARoYXNoAQAAABpnZXRBY2NvdW50TG9ja2VkQmFsYW5jZUtleQAAAAIAAAAFb3duZXIAAAAHYXNzZXRJZAkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAIYmFsYW5jZV8FAAAAB2Fzc2V0SWQCAAAAAV8FAAAABW93bmVyAQAAABhnZXRCYWxhbmNlVW5sb2NrQmxvY2tLZXkAAAABAAAABW93bmVyCQABLAAAAAICAAAADmJhbGFuY2VfYmxvY2tfBQAAAAVvd25lcgEAAAAPZ2V0UlBEUHJvZml0S2V5AAAAAQAAAAVjb3VudAkAASwAAAACCQABLAAAAAICAAAACnJwZF9wcm9maXQCAAAAAV8JAAGkAAAAAQUAAAAFY291bnQBAAAAE2dldExvY2tlZEJhbGFuY2VLZXkAAAABAAAAB2Fzc2V0SWQJAAEsAAAAAgIAAAAIYmFsYW5jZV8FAAAAB2Fzc2V0SWQBAAAAE2dldExlYXNlVHhTdGF0dXNLZXkAAAABAAAABGhhc2gJAAEsAAAAAgkAASwAAAACAgAAAA9sZWFzZV90eF9zdGF0dXMCAAAAAV8FAAAABGhhc2gBAAAAGWdldExlYXNlVHhBbW91bnRCeUhhc2hLZXkAAAABAAAABGhhc2gJAAEsAAAAAgkAASwAAAACBQAAABBMZWFzaW5nQW1vdW50S2V5AgAAAAFfBQAAAARoYXNoAQAAABhnZXRMZWFzZVR4Qnl0ZXNCeUhhc2hLZXkAAAABAAAABGhhc2gJAAEsAAAAAgkAASwAAAACAgAAAAhsZWFzZV90eAIAAAABXwUAAAAEaGFzaAEAAAAcZ2V0TGVhc2VUeEV4cGlyZVNlbmRCbG9ja0tleQAAAAEAAAAEaGFzaAkAASwAAAACCQABLAAAAAICAAAAE2xlYXNpbmdfZXhwaXJlX3NlbmQCAAAAAV8FAAAABGhhc2gBAAAAFmNvbnZlcnROZXV0cmlub1RvV2F2ZXMAAAACAAAABmFtb3VudAAAAAVwcmljZQkAAGkAAAACCQAAaAAAAAIJAABpAAAAAgkAAGgAAAACBQAAAAZhbW91bnQAAAAAAAAAAGQFAAAABXByaWNlBQAAAAdXQVZFTEVUBQAAAAVQQVVMSQEAAAAWY29udmVydFdhdmVzVG9OZXV0cmlubwAAAAIAAAAGYW1vdW50AAAABXByaWNlCQAAaQAAAAIJAABoAAAAAgkAAGkAAAACCQAAaAAAAAIFAAAABmFtb3VudAUAAAAFcHJpY2UAAAAAAAAAAGQFAAAABVBBVUxJBQAAAAdXQVZFTEVUAQAAABVjb252ZXJ0TmV1dHJpbm9Ub0JvbmQAAAABAAAABmFtb3VudAkAAGkAAAACBQAAAAZhbW91bnQFAAAABVBBVUxJAQAAABVjb252ZXJ0Qm9uZFRvTmV1dHJpbm8AAAABAAAABmFtb3VudAkAAGgAAAACBQAAAAZhbW91bnQFAAAABVBBVUxJAQAAABJjb252ZXJ0V2F2ZXNUb0JvbmQAAAACAAAABmFtb3VudAAAAAVwcmljZQkBAAAAFWNvbnZlcnROZXV0cmlub1RvQm9uZAAAAAEJAQAAABZjb252ZXJ0V2F2ZXNUb05ldXRyaW5vAAAAAgUAAAAGYW1vdW50BQAAAAVwcmljZQEAAAAQZ2V0TG9ja2VkQmFsYW5jZQAAAAEAAAAHYXNzZXRJZAkBAAAADmdldE51bWJlckJ5S2V5AAAAAQkBAAAAE2dldExvY2tlZEJhbGFuY2VLZXkAAAABBQAAAAdhc3NldElkAAAAABNsaXF1aWRhdGlvbkNvbnRyYWN0CQEAAAAOZ2V0U3RyaW5nQnlLZXkAAAABBQAAABZMaXF1aWRhdGlvbkNvbnRyYWN0S2V5AAAAABVuZXV0cmlub0Fzc2V0SWRTdHJpbmcJAQAAAA5nZXRTdHJpbmdCeUtleQAAAAEFAAAAEk5ldXRyaW5vQXNzZXRJZEtleQAAAAAPbmV1dHJpbm9Bc3NldElkCQACWQAAAAEFAAAAFW5ldXRyaW5vQXNzZXRJZFN0cmluZwAAAAAPcmVzZXJ2ZUNvbnRyYWN0CQEAAAAOZ2V0U3RyaW5nQnlLZXkAAAABBQAAABJSZXNlcnZlQ29udHJhY3RLZXkAAAAAD2F1Y3Rpb25Db250cmFjdAkBAAAADmdldFN0cmluZ0J5S2V5AAAAAQUAAAASQXVjdGlvbkNvbnRyYWN0S2V5AAAAAAtycGRDb250cmFjdAkBAAAADmdldFN0cmluZ0J5S2V5AAAAAQUAAAAOUlBEQ29udHJhY3RLZXkAAAAAD2NvbnRyb2xDb250cmFjdAkBAAAADmdldFN0cmluZ0J5S2V5AAAAAQUAAAARQ29udG9sQ29udHJhY3RLZXkAAAAADGN1cnJlbnRQcmljZQkBAAAAGGdldE51bWJlckJ5QWRkcmVzc0FuZEtleQAAAAIFAAAAD2NvbnRyb2xDb250cmFjdAUAAAAIUHJpY2VLZXkAAAAACnByaWNlSW5kZXgJAQAAABhnZXROdW1iZXJCeUFkZHJlc3NBbmRLZXkAAAACBQAAAA9jb250cm9sQ29udHJhY3QFAAAADVByaWNlSW5kZXhLZXkAAAAACWlzQmxvY2tlZAkBAAAAFmdldEJvb2xCeUFkZHJlc3NBbmRLZXkAAAACBQAAAA9jb250cm9sQ29udHJhY3QFAAAADElzQmxvY2tlZEtleQAAAAAObGVhc2luZ1R4Q291bnQJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEFAAAAEUxlYXNpbmdUeENvdW50S2V5AAAAAAtpc1JlYmFsYW5jZQkBAAAADGdldEJvb2xCeUtleQAAAAEFAAAADklzUmViYWxhbmNlS2V5AAAAAA9sZWFzaW5nSW50ZXJ2YWwJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEFAAAAEkxlYXNpbmdJbnRlcnZhbEtleQAAAAASbGVhc2luZ0V4cGlyZUJsb2NrCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABBQAAABVMZWFzaW5nRXhwaXJlQmxvY2tLZXkAAAAADWxlYXNpbmdBbW91bnQJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEFAAAAEExlYXNpbmdBbW91bnRLZXkAAAAAC25vZGVBZGRyZXNzCQEAAAAOZ2V0U3RyaW5nQnlLZXkAAAABBQAAAA5Ob2RlQWRkcmVzc0tleQAAAAAVbm9kZU9yYWNsZVByb3ZpZGVyS2V5CQEAAAAOZ2V0U3RyaW5nQnlLZXkAAAABBQAAABVOb2RlT3JhY2xlUHJvdmlkZXJLZXkAAAAADHJwZFN5bmNJbmRleAkBAAAADmdldE51bWJlckJ5S2V5AAAAAQUAAAAPUlBEU3luY0luZGV4S2V5AAAAABNiYWxhbmNlTG9ja0ludGVydmFsCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABBQAAABZCYWxhbmNlTG9ja0ludGVydmFsS2V5AAAAABJtaW5XYXZlc1N3YXBBbW91bnQJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEFAAAAFU1pbldhdmVzU3dhcEFtb3VudEtleQAAAAAVbWluTmV1dHJpbm9Td2FwQW1vdW50CQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABBQAAABhNaW5OZXV0cmlub1N3YXBBbW91bnRLZXkAAAAAB3Jlc2VydmUJAABlAAAAAgkBAAAADHdhdmVzQmFsYW5jZQAAAAEFAAAABHRoaXMJAQAAABBnZXRMb2NrZWRCYWxhbmNlAAAAAQUAAAAMV0FWRVNBU1NFVElEAAAAABVyZXNlcnZlV2l0aG91dExlYXNpbmcJAABlAAAAAgUAAAAHcmVzZXJ2ZQUAAAANbGVhc2luZ0Ftb3VudAAAAAALYm9uZEFzc2V0SWQJAAJZAAAAAQkBAAAADmdldFN0cmluZ0J5S2V5AAAAAQUAAAAOQm9uZEFzc2V0SWRLZXkAAAAACmJvbmRTdXBwbHkJAABlAAAAAggJAQAAAAdleHRyYWN0AAAAAQkAA+wAAAABBQAAAAtib25kQXNzZXRJZAAAAAhxdWFudGl0eQkAA+sAAAACBQAAAAR0aGlzBQAAAAtib25kQXNzZXRJZAAAAAAObmV1dHJpbm9TdXBwbHkJAABkAAAAAgkAAGUAAAACCAkBAAAAB2V4dHJhY3QAAAABCQAD7AAAAAEFAAAAD25ldXRyaW5vQXNzZXRJZAAAAAhxdWFudGl0eQkAA+sAAAACBQAAAAR0aGlzBQAAAA9uZXV0cmlub0Fzc2V0SWQJAQAAABBnZXRMb2NrZWRCYWxhbmNlAAAAAQUAAAAVbmV1dHJpbm9Bc3NldElkU3RyaW5nAAAAAAdzdXJwbHVzCQAAZQAAAAIJAQAAABZjb252ZXJ0V2F2ZXNUb05ldXRyaW5vAAAAAgUAAAAHcmVzZXJ2ZQUAAAAMY3VycmVudFByaWNlBQAAAA5uZXV0cmlub1N1cHBseQAAAAAHZGVmaWNpdAkAAGUAAAACBQAAAA5uZXV0cmlub1N1cHBseQkBAAAAFmNvbnZlcnRXYXZlc1RvTmV1dHJpbm8AAAACBQAAAAdyZXNlcnZlBQAAAAxjdXJyZW50UHJpY2UBAAAAFWdldFJQRENvbnRyYWN0QmFsYW5jZQAAAAEAAAAHYXNzZXRJZAkBAAAAGGdldE51bWJlckJ5QWRkcmVzc0FuZEtleQAAAAIFAAAAC3JwZENvbnRyYWN0CQEAAAAYZ2V0UlBEQ29udHJhY3RCYWxhbmNlS2V5AAAAAQUAAAAHYXNzZXRJZAAAAAAZdG90YWxMaXF1aWRhdGlvbk9yZGVyYm9vawkBAAAAGGdldE51bWJlckJ5QWRkcmVzc0FuZEtleQAAAAIFAAAAD2F1Y3Rpb25Db250cmFjdAUAAAAcVG90YWxMaXF1aWRhdGlvbk9yZGVyYm9va0tleQAAAAAOdG90YWxPcmRlcmJvb2sJAQAAABhnZXROdW1iZXJCeUFkZHJlc3NBbmRLZXkAAAACBQAAAA9hdWN0aW9uQ29udHJhY3QFAAAAEVRvdGFsT3JkZXJib29rS2V5AQAAAA9nZXRQcmljZUhpc3RvcnkAAAABAAAABWJsb2NrCQEAAAAYZ2V0TnVtYmVyQnlBZGRyZXNzQW5kS2V5AAAAAgUAAAAPY29udHJvbENvbnRyYWN0CQEAAAASZ2V0UHJpY2VIaXN0b3J5S2V5AAAAAQUAAAAFYmxvY2sBAAAAFWdldEhlaWdodFByaWNlQnlJbmRleAAAAAEAAAAFaW5kZXgJAQAAABhnZXROdW1iZXJCeUFkZHJlc3NBbmRLZXkAAAACBQAAAA9jb250cm9sQ29udHJhY3QJAQAAABhnZXRIZWlnaHRQcmljZUJ5SW5kZXhLZXkAAAABBQAAAAVpbmRleAEAAAAaZ2V0Q2FuY2VsTGVhc2VUeFJlc2VydmVGZWUAAAABAAAABGhhc2gJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEJAQAAAB1nZXRDYW5jZWxMZWFzZVR4UmVzZXJ2ZUZlZUtleQAAAAEFAAAABGhhc2gBAAAAF2dldEFjY291bnRMb2NrZWRCYWxhbmNlAAAAAgAAAAVvd25lcgAAAAdhc3NldElkCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAaZ2V0QWNjb3VudExvY2tlZEJhbGFuY2VLZXkAAAACBQAAAAVvd25lcgUAAAAHYXNzZXRJZAEAAAAVZ2V0VW5sb2NrQmFsYW5jZUJsb2NrAAAAAQAAAAVvd25lcgkBAAAADmdldE51bWJlckJ5S2V5AAAAAQkBAAAAGGdldEJhbGFuY2VVbmxvY2tCbG9ja0tleQAAAAEFAAAABW93bmVyAQAAAAxnZXRSUERQcm9maXQAAAABAAAABWNvdW50CQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAPZ2V0UlBEUHJvZml0S2V5AAAAAQUAAAAFY291bnQBAAAAEGdldExlYXNlVHhTdGF0dXMAAAABAAAABGhhc2gJAQAAAA5nZXRTdHJpbmdCeUtleQAAAAEJAQAAABNnZXRMZWFzZVR4U3RhdHVzS2V5AAAAAQUAAAAEaGFzaAEAAAAWZ2V0TGVhc2VUeEFtb3VudEJ5SGFzaAAAAAEAAAAEaGFzaAkBAAAADmdldE51bWJlckJ5S2V5AAAAAQkBAAAAGWdldExlYXNlVHhBbW91bnRCeUhhc2hLZXkAAAABBQAAAARoYXNoAQAAABVnZXRMZWFzZVR4Qnl0ZXNCeUhhc2gAAAABAAAABGhhc2gJAQAAAA5nZXRTdHJpbmdCeUtleQAAAAEJAQAAABhnZXRMZWFzZVR4Qnl0ZXNCeUhhc2hLZXkAAAABBQAAAARoYXNoAQAAABlnZXRMZWFzZVR4RXhwaXJlU2VuZEJsb2NrAAAAAQAAAARoYXNoCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAcZ2V0TGVhc2VUeEV4cGlyZVNlbmRCbG9ja0tleQAAAAEFAAAABGhhc2gAAAAJAAAAAWkBAAAAE3N3YXBXYXZlc1RvTmV1dHJpbm8AAAAABAAAAANwbXQJAQAAAAdleHRyYWN0AAAAAQgFAAAAAWkAAAAHcGF5bWVudAQAAAAHYWNjb3VudAkABCUAAAABCAUAAAABaQAAAAZjYWxsZXIDCQAAZgAAAAIFAAAAEm1pbldhdmVzU3dhcEFtb3VudAgFAAAAA3BtdAAAAAZhbW91bnQJAAACAAAAAQkAASwAAAACCQABLAAAAAICAAAALWFuIGFtb3VudCBpcyBsZXNzIHRoYW4gbWluIGF2YWlsYWJsZSBhbW91bnQ6IAkAAaQAAAABBQAAABJtaW5XYXZlc1N3YXBBbW91bnQCAAAACSB3YXZlbGV0cwMJAQAAAAlpc0RlZmluZWQAAAABCAUAAAADcG10AAAAB2Fzc2V0SWQJAAACAAAAAQIAAAASY2FuIHVzZSB3YXZlcyBvbmx5AwUAAAAJaXNCbG9ja2VkCQAAAgAAAAECAAAAWmNvbnRyYWN0IGlzIGJsb2NrZWQgYnkgRU1FUkdFTkNZIFNIVVRET1dOIGFjdGlvbnMgdW50aWxsIHJlYWN0aXZhdGlvbiBieSBlbWVyZ2VuY3kgb3JhY2xlcwMJAABmAAAAAgkBAAAAFWdldFVubG9ja0JhbGFuY2VCbG9jawAAAAEFAAAAB2FjY291bnQFAAAABmhlaWdodAkAAAIAAAABCQABLAAAAAIJAAEsAAAAAgIAAAAGYXdhaXQgCQABpAAAAAEJAABlAAAAAgkBAAAAFWdldFVubG9ja0JhbGFuY2VCbG9jawAAAAEFAAAAB2FjY291bnQFAAAABmhlaWdodAIAAAAHIGJsb2NrcwMJAQAAAAIhPQAAAAIJAQAAABdnZXRBY2NvdW50TG9ja2VkQmFsYW5jZQAAAAIFAAAAB2FjY291bnQFAAAADFdBVkVTQVNTRVRJRAAAAAAAAAAAAAkAAAIAAAABAgAAACJwbGVhc2Ugd2l0aGRyYXcgbG9ja2VkIGZ1bmRzIGZpcnN0CQEAAAAIV3JpdGVTZXQAAAABCQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACCQEAAAAaZ2V0QWNjb3VudExvY2tlZEJhbGFuY2VLZXkAAAACBQAAAAdhY2NvdW50BQAAAAxXQVZFU0FTU0VUSUQIBQAAAANwbXQAAAAGYW1vdW50CQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACCQEAAAAYZ2V0QmFsYW5jZVVubG9ja0Jsb2NrS2V5AAAAAQUAAAAHYWNjb3VudAkAAGQAAAACBQAAAAZoZWlnaHQFAAAAE2JhbGFuY2VMb2NrSW50ZXJ2YWwJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIJAQAAABNnZXRMb2NrZWRCYWxhbmNlS2V5AAAAAQUAAAAMV0FWRVNBU1NFVElECQAAZAAAAAIJAQAAABBnZXRMb2NrZWRCYWxhbmNlAAAAAQUAAAAMV0FWRVNBU1NFVElECAUAAAADcG10AAAABmFtb3VudAUAAAADbmlsAAAAAWkBAAAAE3N3YXBOZXV0cmlub1RvV2F2ZXMAAAAABAAAAANwbXQJAQAAAAdleHRyYWN0AAAAAQgFAAAAAWkAAAAHcGF5bWVudAQAAAAHYWNjb3VudAkABCUAAAABCAUAAAABaQAAAAZjYWxsZXIDCQAAZgAAAAIFAAAAFW1pbk5ldXRyaW5vU3dhcEFtb3VudAgFAAAAA3BtdAAAAAZhbW91bnQJAAACAAAAAQkAASwAAAACCQABLAAAAAICAAAALWFuIGFtb3VudCBpcyBsZXNzIHRoYW4gbWluIGF2YWlsYWJsZSBhbW91bnQ6IAkAAaQAAAABBQAAABVtaW5OZXV0cmlub1N3YXBBbW91bnQCAAAADyBuZXV0cmlubyBjZW50cwMFAAAACWlzQmxvY2tlZAkAAAIAAAABAgAAAFpjb250cmFjdCBpcyBibG9ja2VkIGJ5IEVNRVJHRU5DWSBTSFVURE9XTiBhY3Rpb25zIHVudGlsbCByZWFjdGl2YXRpb24gYnkgZW1lcmdlbmN5IG9yYWNsZXMDCQEAAAACIT0AAAACCAUAAAADcG10AAAAB2Fzc2V0SWQFAAAAD25ldXRyaW5vQXNzZXRJZAkAAAIAAAABAgAAAChjYW4gdXNlIGFwcHJvcHJpYXRlIG5ldXRyaW5vIHRva2VucyBvbmx5AwkAAGYAAAACCQEAAAAVZ2V0VW5sb2NrQmFsYW5jZUJsb2NrAAAAAQUAAAAHYWNjb3VudAUAAAAGaGVpZ2h0CQAAAgAAAAEJAAEsAAAAAgkAASwAAAACAgAAAAZhd2FpdCAJAAGkAAAAAQkAAGUAAAACCQEAAAAVZ2V0VW5sb2NrQmFsYW5jZUJsb2NrAAAAAQUAAAAHYWNjb3VudAUAAAAGaGVpZ2h0AgAAAAcgYmxvY2tzAwkBAAAAAiE9AAAAAgkBAAAAF2dldEFjY291bnRMb2NrZWRCYWxhbmNlAAAAAgUAAAAHYWNjb3VudAUAAAAVbmV1dHJpbm9Bc3NldElkU3RyaW5nAAAAAAAAAAAACQAAAgAAAAECAAAAInBsZWFzZSB3aXRoZHJhdyBsb2NrZWQgZnVuZHMgZmlyc3QEAAAAEG5ld0xvY2tlZEJhbGFuY2UJAABkAAAAAgkBAAAAEGdldExvY2tlZEJhbGFuY2UAAAABBQAAABVuZXV0cmlub0Fzc2V0SWRTdHJpbmcIBQAAAANwbXQAAAAGYW1vdW50CQEAAAAIV3JpdGVTZXQAAAABCQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACCQEAAAAaZ2V0QWNjb3VudExvY2tlZEJhbGFuY2VLZXkAAAACBQAAAAdhY2NvdW50BQAAABVuZXV0cmlub0Fzc2V0SWRTdHJpbmcIBQAAAANwbXQAAAAGYW1vdW50CQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACCQEAAAAYZ2V0QmFsYW5jZVVubG9ja0Jsb2NrS2V5AAAAAQUAAAAHYWNjb3VudAkAAGQAAAACBQAAAAZoZWlnaHQFAAAAE2JhbGFuY2VMb2NrSW50ZXJ2YWwJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIJAQAAABNnZXRMb2NrZWRCYWxhbmNlS2V5AAAAAQUAAAAVbmV1dHJpbm9Bc3NldElkU3RyaW5nBQAAABBuZXdMb2NrZWRCYWxhbmNlCQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACBQAAAA5Jc1JlYmFsYW5jZUtleQMJAABnAAAAAgUAAAAVcmVzZXJ2ZVdpdGhvdXRMZWFzaW5nCQEAAAAWY29udmVydE5ldXRyaW5vVG9XYXZlcwAAAAIFAAAAEG5ld0xvY2tlZEJhbGFuY2UFAAAADGN1cnJlbnRQcmljZQcGBQAAAANuaWwAAAABaQEAAAAId2l0aGRyYXcAAAADAAAAB2FjY291bnQAAAAFaW5kZXgAAAANbG9ja2VkQXNzZXRJZAQAAAAMdW5sb2NrSGVpZ2h0CQEAAAAVZ2V0VW5sb2NrQmFsYW5jZUJsb2NrAAAAAQUAAAAHYWNjb3VudAQAAAANbG9ja2VkQmFsYW5jZQkBAAAAF2dldEFjY291bnRMb2NrZWRCYWxhbmNlAAAAAgUAAAAHYWNjb3VudAUAAAANbG9ja2VkQXNzZXRJZAQAAAALaW5kZXhIZWlnaHQJAQAAABVnZXRIZWlnaHRQcmljZUJ5SW5kZXgAAAABBQAAAAVpbmRleAQAAAAPbmV4dEluZGV4SGVpZ2h0CQEAAAAVZ2V0SGVpZ2h0UHJpY2VCeUluZGV4AAAAAQkAAGQAAAACBQAAAAVpbmRleAAAAAAAAAAAAQQAAAAMcHJpY2VCeUluZGV4CQEAAAAPZ2V0UHJpY2VIaXN0b3J5AAAAAQUAAAALaW5kZXhIZWlnaHQEAAAABmFtb3VudAMJAAAAAAAAAgUAAAANbG9ja2VkQXNzZXRJZAUAAAAVbmV1dHJpbm9Bc3NldElkU3RyaW5nCQEAAAAWY29udmVydE5ldXRyaW5vVG9XYXZlcwAAAAIFAAAADWxvY2tlZEJhbGFuY2UFAAAADHByaWNlQnlJbmRleAkBAAAAFmNvbnZlcnRXYXZlc1RvTmV1dHJpbm8AAAACBQAAAA1sb2NrZWRCYWxhbmNlBQAAAAxwcmljZUJ5SW5kZXgDBQAAAAlpc0Jsb2NrZWQJAAACAAAAAQIAAABaY29udHJhY3QgaXMgYmxvY2tlZCBieSBFTUVSR0VOQ1kgU0hVVERPV04gYWN0aW9ucyB1bnRpbGwgcmVhY3RpdmF0aW9uIGJ5IGVtZXJnZW5jeSBvcmFjbGVzAwkAAGcAAAACAAAAAAAAAAAABQAAAAZhbW91bnQJAAACAAAAAQkAASwAAAACCQABLAAAAAICAAAAFWJhbGFuY2UgZXF1YWxzIHplcm8gKAUAAAANbG9ja2VkQXNzZXRJZAIAAAABKQMJAABmAAAAAgUAAAAMdW5sb2NrSGVpZ2h0BQAAAAZoZWlnaHQJAAACAAAAAQkAASwAAAACCQABLAAAAAICAAAAEXBsZWFzZSB3YWl0IGZvcjogCQABpAAAAAEFAAAADHVubG9ja0hlaWdodAIAAAAlIGJsb2NrIGhlaWdodCB0byB3aXRoZHJhdyBXQVZFUyBmdW5kcwMDAwkAAGYAAAACBQAAAAVpbmRleAUAAAAKcHJpY2VJbmRleAYJAABmAAAAAgUAAAALaW5kZXhIZWlnaHQFAAAADHVubG9ja0hlaWdodAYDCQEAAAACIT0AAAACBQAAAA9uZXh0SW5kZXhIZWlnaHQAAAAAAAAAAAAJAABnAAAAAgUAAAAMdW5sb2NrSGVpZ2h0BQAAAA9uZXh0SW5kZXhIZWlnaHQHCQAAAgAAAAECAAAAG2ludmFsaWQgcHJpY2UgaGlzdG9yeSBpbmRleAkBAAAADFNjcmlwdFJlc3VsdAAAAAIJAQAAAAhXcml0ZVNldAAAAAEJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIJAQAAABpnZXRBY2NvdW50TG9ja2VkQmFsYW5jZUtleQAAAAIFAAAAB2FjY291bnQFAAAADWxvY2tlZEFzc2V0SWQAAAAAAAAAAAAJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIJAQAAABNnZXRMb2NrZWRCYWxhbmNlS2V5AAAAAQUAAAANbG9ja2VkQXNzZXRJZAkAAGUAAAACCQEAAAAQZ2V0TG9ja2VkQmFsYW5jZQAAAAEFAAAADWxvY2tlZEFzc2V0SWQFAAAADWxvY2tlZEJhbGFuY2UFAAAAA25pbAkBAAAAC1RyYW5zZmVyU2V0AAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAcQGV4dHJVc2VyKGFkZHJlc3NGcm9tU3RyaW5nKQAAAAEFAAAAB2FjY291bnQFAAAABmFtb3VudAMJAAAAAAAAAgUAAAANbG9ja2VkQXNzZXRJZAUAAAAVbmV1dHJpbm9Bc3NldElkU3RyaW5nBQAAAAR1bml0BQAAAA9uZXV0cmlub0Fzc2V0SWQFAAAAA25pbAAAAAFpAQAAABF0cmFuc2ZlclRvQXVjdGlvbgAAAAAEAAAAEWRlZmljaXRCb25kQW1vdW50CQAAZQAAAAIJAABlAAAAAgkBAAAAFWNvbnZlcnROZXV0cmlub1RvQm9uZAAAAAEFAAAAB2RlZmljaXQJAAPrAAAAAgkBAAAAHEBleHRyVXNlcihhZGRyZXNzRnJvbVN0cmluZykAAAABBQAAAA9hdWN0aW9uQ29udHJhY3QFAAAAC2JvbmRBc3NldElkBQAAABl0b3RhbExpcXVpZGF0aW9uT3JkZXJib29rBAAAAAtzdXJwbHVzQm9uZAkAAGUAAAACCQAAZQAAAAIJAQAAABVjb252ZXJ0TmV1dHJpbm9Ub0JvbmQAAAABBQAAAAdzdXJwbHVzCQAD6wAAAAIJAQAAABxAZXh0clVzZXIoYWRkcmVzc0Zyb21TdHJpbmcpAAAAAQUAAAAPYXVjdGlvbkNvbnRyYWN0BQAAAA9uZXV0cmlub0Fzc2V0SWQFAAAADnRvdGFsT3JkZXJib29rAwUAAAAJaXNCbG9ja2VkCQAAAgAAAAECAAAAWmNvbnRyYWN0IGlzIGJsb2NrZWQgYnkgRU1FUkdFTkNZIFNIVVRET1dOIGFjdGlvbnMgdW50aWxsIHJlYWN0aXZhdGlvbiBieSBlbWVyZ2VuY3kgb3JhY2xlcwMJAABnAAAAAgUAAAARZGVmaWNpdEJvbmRBbW91bnQJAABpAAAAAgkAAGgAAAACBQAAAA5uZXV0cmlub1N1cHBseQUAAAANREVGSUNJVE9GRlNFVAAAAAAAAAAAZAkBAAAAC1RyYW5zZmVyU2V0AAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAcQGV4dHJVc2VyKGFkZHJlc3NGcm9tU3RyaW5nKQAAAAEFAAAAD2F1Y3Rpb25Db250cmFjdAUAAAARZGVmaWNpdEJvbmRBbW91bnQFAAAAC2JvbmRBc3NldElkBQAAAANuaWwDCQAAZgAAAAIFAAAAC3N1cnBsdXNCb25kAAAAAAAAAAAACQEAAAALVHJhbnNmZXJTZXQAAAABCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAABxAZXh0clVzZXIoYWRkcmVzc0Zyb21TdHJpbmcpAAAAAQUAAAATbGlxdWlkYXRpb25Db250cmFjdAkBAAAAFWNvbnZlcnRCb25kVG9OZXV0cmlubwAAAAEFAAAAC3N1cnBsdXNCb25kBQAAAA9uZXV0cmlub0Fzc2V0SWQFAAAAA25pbAkAAAIAAAABAgAAACVib25kIHdlcmUgZ2VuZXJhdGVkIG9yIGRvIG5vdCBuZWVkIGl0AAAAAWkBAAAACHRyYW5zZmVyAAAAAQAAAAdhY2NvdW50BAAAAANwbXQJAQAAAAdleHRyYWN0AAAAAQgFAAAAAWkAAAAHcGF5bWVudAkBAAAAC1RyYW5zZmVyU2V0AAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAcQGV4dHJVc2VyKGFkZHJlc3NGcm9tU3RyaW5nKQAAAAEFAAAAB2FjY291bnQIBQAAAANwbXQAAAAGYW1vdW50CAUAAAADcG10AAAAB2Fzc2V0SWQFAAAAA25pbAAAAAFpAQAAAApub2RlUmV3YXJkAAAAAAQAAAADcG10CQEAAAAFdmFsdWUAAAABCAUAAAABaQAAAAdwYXltZW50AwkBAAAAAiE9AAAAAggFAAAAAWkAAAAGY2FsbGVyCQEAAAAcQGV4dHJVc2VyKGFkZHJlc3NGcm9tU3RyaW5nKQAAAAEFAAAAC25vZGVBZGRyZXNzCQAAAgAAAAECAAAAR29ubHkgbm9kZSBhY2NvdW50IGlzIGFibGUgdG8gdHJhbnNmZXIgc3Rha2luZyByZXdhcmRzIGZyb20gbWFpbiBhY2NvdW50AwkBAAAACWlzRGVmaW5lZAAAAAEIBQAAAANwbXQAAAAHYXNzZXRJZAkAAAIAAAABAgAAABl3YXZlcyB0b2tlbnMgb25seSBhbGxvd2VkBAAAAAZhbW91bnQJAQAAABZjb252ZXJ0V2F2ZXNUb05ldXRyaW5vAAAAAggFAAAAA3BtdAAAAAZhbW91bnQFAAAADGN1cnJlbnRQcmljZQQAAAAPbmV3UnBkU3luY0luZGV4CQAAZAAAAAIFAAAADHJwZFN5bmNJbmRleAAAAAAAAAAAAQkBAAAADFNjcmlwdFJlc3VsdAAAAAIJAQAAAAhXcml0ZVNldAAAAAEJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIFAAAAD1JQRFN5bmNJbmRleEtleQUAAAAPbmV3UnBkU3luY0luZGV4CQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACCQEAAAAPZ2V0UlBEUHJvZml0S2V5AAAAAQUAAAAMcnBkU3luY0luZGV4BQAAAAZhbW91bnQJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIJAQAAACBnZXRSUERTbmFwc2hvdENvbnRyYWN0QmFsYW5jZUtleQAAAAIFAAAADHJwZFN5bmNJbmRleAUAAAAPbmV1dHJpbm9Bc3NldElkCQEAAAAVZ2V0UlBEQ29udHJhY3RCYWxhbmNlAAAAAQUAAAAPbmV1dHJpbm9Bc3NldElkBQAAAANuaWwJAQAAAAtUcmFuc2ZlclNldAAAAAEJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwkBAAAAHEBleHRyVXNlcihhZGRyZXNzRnJvbVN0cmluZykAAAABBQAAAAtycGRDb250cmFjdAUAAAAGYW1v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ZWVSZXNlcnZlCQAAZAAAAAIFAAAADWxlYXNpbmdBbW91bnQFAAAABmFtb3VudAUAAAAVcmVzZXJ2ZVdpdGhvdXRMZWFzaW5nAgAAAAEpCQEAAAAIV3JpdGVTZXQAAAABCQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACCQEAAAAdZ2V0Q2FuY2VsTGVhc2VUeFJlc2VydmVGZWVLZXkAAAABBQAAAAZ0eEhhc2gFAAAAA2ZlZQkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgUAAAARTGVhc2luZ1R4Q291bnRLZXkDCQAAAAAAAAIJAQAAABBnZXRMZWFzZVR4U3RhdHVzAAAAAQUAAAAGdHhIYXNoAgAAAAAJAABkAAAAAgUAAAAObGVhc2luZ1R4Q291bnQAAAAAAAAAAAEFAAAADmxlYXNpbmdUeENvdW50CQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACBQAAABBMZWFzaW5nQW1vdW50S2V5CQAAZAAAAAIFAAAADWxlYXNpbmdBbW91bnQFAAAABmFtb3VudAkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgUAAAAVTGVhc2luZ0V4cGlyZUJsb2NrS2V5AwkAAGYAAAACBQAAAAZoZWlnaHQFAAAAEmxlYXNpbmdFeHBpcmVCbG9jawkAAGQAAAACBQAAAAZoZWlnaHQFAAAAD2xlYXNpbmdJbnRlcnZhbAUAAAASbGVhc2luZ0V4cGlyZUJsb2NrCQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACCQEAAAATZ2V0TGVhc2VUeFN0YXR1c0tleQAAAAEFAAAABnR4SGFzaAUAAAADTkVXCQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACCQEAAAAcZ2V0TGVhc2VUeEV4cGlyZVNlbmRCbG9ja0tleQAAAAEFAAAABnR4SGFzaAkAAGQAAAACBQAAAAZoZWlnaHQFAAAADFNFTkRUWEVYUElSRQkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgkBAAAAGWdldExlYXNlVHhBbW91bnRCeUhhc2hLZXkAAAABBQAAAAZ0eEhhc2gFAAAABmFtb3VudAkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgkBAAAAGGdldExlYXNlVHhCeXRlc0J5SGFzaEtleQAAAAEFAAAABnR4SGFzaAkAAloAAAABBQAAAAd0eEJ5dGVzBQAAAANuaWwAAAABaQEAAAASY2FuY2VsU3R1Y2tMZWFzZVR4AAAAAQAAAAZ0eEhhc2gDAwMJAAAAAAAAAgkBAAAAEGdldExlYXNlVHhTdGF0dXMAAAABBQAAAAZ0eEhhc2gFAAAAA05FVwkBAAAAASEAAAABCQEAAAAJaXNEZWZpbmVkAAAAAQkAA+kAAAABCQACWQAAAAEFAAAABnR4SGFzaAcJAABmAAAAAgUAAAAGaGVpZ2h0CQEAAAAZZ2V0TGVhc2VUeEV4cGlyZVNlbmRCbG9jawAAAAEFAAAABnR4SGFzaAcEAAAABmFtb3VudAkBAAAAFmdldExlYXNlVHhBbW91bnRCeUhhc2gAAAABBQAAAAZ0eEhhc2gJAQAAAAhXcml0ZVNldAAAAAEJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIFAAAAEUxlYXNpbmdUeENvdW50S2V5CQAAZQAAAAIFAAAADmxlYXNpbmdUeENvdW50AAAAAAAAAAABCQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACBQAAABBMZWFzaW5nQW1vdW50S2V5CQAAZQAAAAIFAAAADWxlYXNpbmdBbW91bnQFAAAABmFtb3VudAkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgkBAAAAE2dldExlYXNlVHhTdGF0dXNLZXkAAAABBQAAAAZ0eEhhc2gFAAAACENBTkNFTEVECQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACBQAAAA5Jc1JlYmFsYW5jZUtleQMJAABnAAAAAgkAAGUAAAACBQAAABVyZXNlcnZlV2l0aG91dExlYXNpbmcFAAAABmFtb3VudAkBAAAAFmNvbnZlcnROZXV0cmlub1RvV2F2ZXMAAAACCQEAAAAQZ2V0TG9ja2VkQmFsYW5jZQAAAAEFAAAAFW5ldXRyaW5vQXNzZXRJZFN0cmluZwUAAAAMY3VycmVudFByaWNlBwYFAAAAA25pbAkAAAIAAAABAgAAAA9pbnZhbGlkIHR4IGhhc2gAAAABaQEAAAAVcmVnaXN0cmF0aW9uVW5sZWFzZVR4AAAABQAAAA1jaGFpbklkU3RyaW5nAAAAD3NlbmRlclB1Ymxp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", "chainId": 84, "height": 766151, "spentComplexity": 0 } View: original | compacted Prev: 8M7Vhsc4YYVbpyUyxpUrXehUV5fmMbv4EeiPLXN9b3qS Next: none Diff:
OldNewDifferences
3333 }
3434
3535
36-func getStringByAddressAndKey (address,key) = match getString(this, key) {
36+func getStringByAddressAndKey (address,key) = match getString(addressFromStringValue(address), key) {
3737 case a: String =>
3838 a
3939 case _ =>
4141 }
4242
4343
44+func getBoolByAddressAndKey (address,key) = match getBoolean(addressFromStringValue(address), key) {
45+ case a: Boolean =>
46+ a
47+ case _ =>
48+ false
49+}
50+
51+
52+let SENDTXEXPIRE = 30
53+
4454 let LISTSPLITSYMBOL = "_"
4555
4656 let LISTDATASYMBOL = "+"
4757
4858 let WAVELET = 100000000
4959
50-let CENTSINDOLLAR = 100
60+let PAULI = 100
61+
62+let CRYTICALSHARE = 20
63+
64+let LEASINGSHARE = 90
65+
66+let LEASINTXCOUNT = 10
67+
68+let DEFICITOFFSET = 10
69+
70+let WAVESASSETID = "waves"
5171
5272 let CANCELED = "canceled"
5373
5474 let NEW = "new"
5575
56-let FILLED = "filled"
57-
5876 let NeutrinoAssetIdKey = "neutrino_asset_id"
5977
6078 let BondAssetIdKey = "bond_asset_id"
6179
80+let ReserveContractKey = "reserve_contract"
81+
6282 let AuctionContractKey = "auction_contract"
83+
84+let LiquidationContractKey = "liquidation_contract"
6385
6486 let RPDContractKey = "rpd_contract"
6587
88+let ContolContractKey = "control_contract"
89+
6690 let BalanceLockIntervalKey = "balance_lock_interval"
67-
68-let VoteIntervalKey = "vote_interval"
6991
7092 let MinWavesSwapAmountKey = "min_waves_swap_amount"
7193
7294 let MinNeutrinoSwapAmountKey = "min_neutrino_swap_amount"
7395
74-let PriceOffsetKey = "price_offset"
96+let NodeAddressKey = "node_address"
7597
76-let ProvidingIntervalKey = "providing_interval"
98+let NodeOracleProviderKey = "oracle_node_provider"
99+
100+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"
77110
78111 let PriceKey = "price"
79112
80-let NeutrinoBalanceKey = "neutrino_"
81-
82-let WavesBalanceKey = "waves_"
83-
84-let BalanceUnlockBlockKey = "balance_block_"
85-
86-let OrderbookKey = "orderbook"
87-
88-let OrderTotalKey = "order_total_"
89-
90-let OrderOwnerKey = "order_owner_"
91-
92-let OrderHeightKey = "order_height_"
93-
94-let OrderFilledTotalKey = "order_filled_total_"
95-
96-let OrderStatusKey = "order_status_"
97-
98-let RPDSyncIndexKey = "rpd_sync_index"
99-
100-let RPDProfitKey = "rpd_profit"
101-
102-let RPDBalanceKey = "rpd_balance"
113+let PriceIndexKey = "price_index"
103114
104115 let IsBlockedKey = "is_blocked"
105116
106-let BlackSwarmPriceKey = "black_swarm_price"
117+let LeasingExpireBlockKey = "leasing_expire_block"
107118
108-let AdminVoteKey = "admin_vote_"
119+let IsRebalanceKey = "is_rebalance"
109120
110-let AdminVotePriceKey = "admin_vote_price_"
121+let LeasingTxCountKey = "leasing_index"
111122
112-let BlockExpireVoteKey = "vote_expire_block"
123+let LeasingAmountKey = "leasing_amount"
113124
114-let AdminKey = "admin_"
115-
116-let IsPricePendingKey = "is_pending_price"
117-
118-let OracleKey = "oracle_"
119-
120-let OracleIsProvideKey = "oracle_is_provide_"
121-
122-let OracleProvidePriceKey = "oracle_price_provide_"
123-
124-let BlockExpireProvidingKey = "providing_expire_block"
125-
126-let ApprovedLeaseTxKey = "leasetx"
127-
128-let IsLeasingProfitTxExistKey = "is_leasing_profit"
129-
130-func getAdminKey (count) = (AdminKey + toString(count))
125+func getPriceHistoryKey (block) = ((PriceKey + "_") + toString(block))
131126
132127
133-func getAdminVoteKey (owner) = (AdminVoteKey + owner)
128+func getHeightPriceByIndexKey (index) = ((PriceIndexKey + "_") + toString(index))
134129
135130
136-func getAdminVotePriceKey (owner) = (AdminVotePriceKey + owner)
137-
138-
139-func getOracleKey (count) = (OracleKey + toString(count))
140-
141-
142-func getOracleIsProvideKey (owner) = (OracleIsProvideKey + owner)
143-
144-
145-func getOracleProvidePriceKey (owner) = (OracleProvidePriceKey + owner)
146-
131+let RPDSyncIndexKey = "rpd_sync_index"
147132
148133 func getRPDSnapshotContractBalanceKey (count,assetId) = ((((RPDBalanceKey + "_") + toBase58String(assetId)) + "_") + toString(count))
149134
150135
151-func getRPDContractBalanceKey (assetId) = ((RPDBalanceKey + "_") + toBase58String(assetId))
136+func getCancelLeaseTxReserveFeeKey (hash) = (("cancel_lease_tx_reserve_fee" + "_") + hash)
152137
153138
154-func getRPDProfitKey (count) = ((RPDProfitKey + "_") + toString(count))
139+func getAccountLockedBalanceKey (owner,assetId) = ((("balance_" + assetId) + "_") + owner)
155140
156141
157-func getNeutrinoBalanceKey (owner) = (NeutrinoBalanceKey + owner)
142+func getBalanceUnlockBlockKey (owner) = ("balance_block_" + owner)
158143
159144
160-func getWavesBalanceKey (owner) = (WavesBalanceKey + owner)
145+func getRPDProfitKey (count) = (("rpd_profit" + "_") + toString(count))
161146
162147
163-func getBalanceUnlockBlockKey (owner) = (BalanceUnlockBlockKey + owner)
148+func getLockedBalanceKey (assetId) = ("balance_" + assetId)
164149
165150
166-func getBlackSwarmPriceKey (block) = ((BlackSwarmPriceKey + "_") + toString(block))
151+func getLeaseTxStatusKey (hash) = (("lease_tx_status" + "_") + hash)
167152
168153
169-func getPriceHistoryKey (block) = ((PriceKey + "_") + toString(block))
154+func getLeaseTxAmountByHashKey (hash) = ((LeasingAmountKey + "_") + hash)
170155
171156
172-func getOwnerPubKeyByLeaseTxIdKey (txId) = ((ApprovedLeaseTxKey + "_") + txId)
157+func getLeaseTxBytesByHashKey (hash) = (("lease_tx" + "_") + hash)
173158
174159
175-func getIsLeasingProfitTxExistKey (txId) = ((IsLeasingProfitTxExistKey + "_") + txId)
160+func getLeaseTxExpireSendBlockKey (hash) = (("leasing_expire_send" + "_") + hash)
176161
177162
178-func getOrderTotalKey (orderId) = (OrderTotalKey + orderId)
163+func convertNeutrinoToWaves (amount,price) = ((((amount * 100) / price) * WAVELET) / PAULI)
179164
180165
181-func getOrderOwnerKey (orderId) = (OrderOwnerKey + orderId)
166+func convertWavesToNeutrino (amount,price) = ((((amount * price) / 100) * PAULI) / WAVELET)
182167
183168
184-func getOrderHeightKey (orderId) = (OrderHeightKey + orderId)
169+func convertNeutrinoToBond (amount) = (amount / PAULI)
185170
186171
187-func getOrderStatusKey (orderId) = (OrderStatusKey + orderId)
172+func convertBondToNeutrino (amount) = (amount * PAULI)
188173
189174
190-func getOrderFilledTotalKey (orderId) = (OrderFilledTotalKey + orderId)
175+func convertWavesToBond (amount,price) = convertNeutrinoToBond(convertWavesToNeutrino(amount, price))
191176
192177
193-let price = getNumberByKey(PriceKey)
194-
195-func convertNeutrinoToWaves (amount) = ((((amount * 100) / price) * WAVELET) / CENTSINDOLLAR)
178+func getLockedBalance (assetId) = getNumberByKey(getLockedBalanceKey(assetId))
196179
197180
198-func convertWavesToNeutrino (amount) = ((((amount * price) / 100) * CENTSINDOLLAR) / WAVELET)
181+let liquidationContract = getStringByKey(LiquidationContractKey)
199182
183+let neutrinoAssetIdString = getStringByKey(NeutrinoAssetIdKey)
200184
201-func convertNeutrinoToBond (amount) = (amount / CENTSINDOLLAR)
185+let neutrinoAssetId = fromBase58String(neutrinoAssetIdString)
202186
187+let reserveContract = getStringByKey(ReserveContractKey)
203188
204-func convertBondToNeutrino (amount) = (amount * CENTSINDOLLAR)
189+let auctionContract = getStringByKey(AuctionContractKey)
205190
191+let rpdContract = getStringByKey(RPDContractKey)
206192
207-func convertWavesToBond (amount) = convertNeutrinoToBond(convertWavesToNeutrino(amount))
193+let controlContract = getStringByKey(ContolContractKey)
208194
195+let currentPrice = getNumberByAddressAndKey(controlContract, PriceKey)
209196
210-let providingInterval = getNumberByKey(ProvidingIntervalKey)
197+let priceIndex = getNumberByAddressAndKey(controlContract, PriceIndexKey)
211198
212-let blockExpireProviding = getNumberByKey(BlockExpireProvidingKey)
199+let isBlocked = getBoolByAddressAndKey(controlContract, IsBlockedKey)
213200
214-let isPricePending = getBoolByKey(IsPricePendingKey)
201+let leasingTxCount = getNumberByKey(LeasingTxCountKey)
215202
216-let percentPriceOffset = getNumberByKey(PriceOffsetKey)
203+let isRebalance = getBoolByKey(IsRebalanceKey)
204+
205+let leasingInterval = getNumberByKey(LeasingIntervalKey)
206+
207+let leasingExpireBlock = getNumberByKey(LeasingExpireBlockKey)
208+
209+let leasingAmount = getNumberByKey(LeasingAmountKey)
210+
211+let nodeAddress = getStringByKey(NodeAddressKey)
212+
213+let nodeOracleProviderKey = getStringByKey(NodeOracleProviderKey)
217214
218215 let rpdSyncIndex = getNumberByKey(RPDSyncIndexKey)
219216
220-let voteInterval = getNumberByKey(VoteIntervalKey)
221-
222-let blockExpireVote = getNumberByKey(BlockExpireVoteKey)
223-
224217 let balanceLockInterval = getNumberByKey(BalanceLockIntervalKey)
225-
226-let isBlocked = getBoolByKey(IsBlockedKey)
227218
228219 let minWavesSwapAmount = getNumberByKey(MinWavesSwapAmountKey)
229220
230221 let minNeutrinoSwapAmount = getNumberByKey(MinNeutrinoSwapAmountKey)
231222
232-let neutrinoAssetId = fromBase58String(getStringByKey(NeutrinoAssetIdKey))
223+let reserve = (wavesBalance(this) - getLockedBalance(WAVESASSETID))
233224
234-let auctionContract = getStringByKey(AuctionContractKey)
235-
236-let rpdContract = getStringByKey(RPDContractKey)
237-
238-let reserve = wavesBalance(this)
239-
240-let orderbook = getStringByKey(OrderbookKey)
225+let reserveWithoutLeasing = (reserve - leasingAmount)
241226
242227 let bondAssetId = fromBase58String(getStringByKey(BondAssetIdKey))
243228
244-let bondSupply = {
245- let info = extract(assetInfo(bondAssetId))
246- (info.quantity - assetBalance(this, bondAssetId))
247- }
229+let bondSupply = (extract(assetInfo(bondAssetId)).quantity - assetBalance(this, bondAssetId))
248230
249-let neutrinoSupply = {
250- let info = extract(assetInfo(neutrinoAssetId))
251- (info.quantity - assetBalance(this, neutrinoAssetId))
252- }
231+let neutrinoSupply = ((extract(assetInfo(neutrinoAssetId)).quantity - assetBalance(this, neutrinoAssetId)) + getLockedBalance(neutrinoAssetIdString))
253232
254-let surplus = (convertWavesToNeutrino(reserve) - neutrinoSupply)
233+let surplus = (convertWavesToNeutrino(reserve, currentPrice) - neutrinoSupply)
255234
256-let oracleOne = getStringByKey(getOracleKey(0))
257-
258-let oracleTwo = getStringByKey(getOracleKey(1))
259-
260-let oracleThree = getStringByKey(getOracleKey(2))
261-
262-let adminOne = getStringByKey(getAdminKey(0))
263-
264-let adminTwo = getStringByKey(getAdminKey(1))
265-
266-let adminThree = getStringByKey(getAdminKey(2))
267-
268-func getOwnerPubKeyByLeaseTxId (owner) = getStringByAddressAndKey(rpdContract, getOwnerPubKeyByLeaseTxIdKey(owner))
269-
235+let deficit = (neutrinoSupply - convertWavesToNeutrino(reserve, currentPrice))
270236
271237 func getRPDContractBalance (assetId) = getNumberByAddressAndKey(rpdContract, getRPDContractBalanceKey(assetId))
272238
273239
274-func isLeasingProfitTxExist (txId) = getBoolByKey(getIsLeasingProfitTxExistKey(txId))
240+let totalLiquidationOrderbook = getNumberByAddressAndKey(auctionContract, TotalLiquidationOrderbookKey)
241+
242+let totalOrderbook = getNumberByAddressAndKey(auctionContract, TotalOrderbookKey)
243+
244+func getPriceHistory (block) = getNumberByAddressAndKey(controlContract, getPriceHistoryKey(block))
275245
276246
277-func getAdminVoteInt (owner) = if (getBoolByKey(getAdminVoteKey(owner)))
278- then 1
279- else 0
247+func getHeightPriceByIndex (index) = getNumberByAddressAndKey(controlContract, getHeightPriceByIndexKey(index))
280248
281249
282-func getAdminVotePrice (owner) = getNumberByKey(getAdminVotePriceKey(owner))
250+func getCancelLeaseTxReserveFee (hash) = getNumberByKey(getCancelLeaseTxReserveFeeKey(hash))
283251
284252
285-func isOracleProvide (owner) = getBoolByKey(getOracleIsProvideKey(owner))
286-
287-
288-func isOracleProvideInt (owner) = if (isOracleProvide(owner))
289- then 1
290- else 0
291-
292-
293-func getOracleProvidePrice (owner) = getNumberByKey(getOracleProvidePriceKey(owner))
294-
295-
296-func getWavesBalance (owner) = getNumberByKey(getWavesBalanceKey(owner))
297-
298-
299-func getNeutrinoBalance (owner) = getNumberByKey(getNeutrinoBalanceKey(owner))
253+func getAccountLockedBalance (owner,assetId) = getNumberByKey(getAccountLockedBalanceKey(owner, assetId))
300254
301255
302256 func getUnlockBalanceBlock (owner) = getNumberByKey(getBalanceUnlockBlockKey(owner))
303257
304258
305-func getOrderTotal (id) = getNumberByKey(getOrderTotalKey(id))
306-
307-
308-func getOrderOwner (id) = getStringByKey(getOrderOwnerKey(id))
309-
310-
311-func getOrderFilledTotal (id) = getNumberByKey(getOrderFilledTotalKey(id))
312-
313-
314259 func getRPDProfit (count) = getNumberByKey(getRPDProfitKey(count))
315260
316261
317-func getOrderElementById (id) = (id + LISTSPLITSYMBOL)
262+func getLeaseTxStatus (hash) = getStringByKey(getLeaseTxStatusKey(hash))
318263
319264
320-func addOrder (orderId) = (orderbook + getOrderElementById(orderId))
265+func getLeaseTxAmountByHash (hash) = getNumberByKey(getLeaseTxAmountByHashKey(hash))
321266
322267
323-func dropOrder (orderId) = {
324- let parts = split(orderbook, getOrderElementById(orderId))
325- (parts[0] + parts[1])
326- }
268+func getLeaseTxBytesByHash (hash) = getStringByKey(getLeaseTxBytesByHashKey(hash))
327269
328270
329-@Callable(i)
330-func setCurrentPrice (newPrice) = {
331- let account = toString(i.caller)
332- let priceProvidingCount = (((isOracleProvideInt(oracleOne) + isOracleProvideInt(oracleTwo)) + isOracleProvideInt(oracleThree)) + 1)
333- if (isBlocked)
334- then throw("contract is blocked")
335- else if (if (if ((account != oracleOne))
336- then (account != oracleTwo)
337- else false)
338- then (account != oracleThree)
339- else false)
340- then throw("permission denied")
341- else if (if ((blockExpireProviding >= height))
342- then isOracleProvide(account)
343- else false)
344- then throw("price is already provided")
345- else if (if ((height > blockExpireProviding))
346- then isPricePending
347- else false)
348- then throw("use finilizeCurrentPrice")
349- else WriteSet([DataEntry(getOracleProvidePriceKey(account), newPrice), DataEntry(BlockExpireProvidingKey, if ((height > blockExpireProviding))
350- then (height + providingInterval)
351- else blockExpireProviding), DataEntry(getOracleIsProvideKey(oracleOne), if ((height > blockExpireProviding))
352- then false
353- else isOracleProvide(oracleOne)), DataEntry(getOracleIsProvideKey(oracleTwo), if ((height > blockExpireProviding))
354- then false
355- else isOracleProvide(oracleTwo)), DataEntry(getOracleIsProvideKey(oracleThree), if ((height > blockExpireProviding))
356- then false
357- else isOracleProvide(oracleThree)), DataEntry(getOracleIsProvideKey(account), true), DataEntry(IsPricePendingKey, if (if ((blockExpireProviding >= height))
358- then (priceProvidingCount >= 2)
359- else false)
360- then true
361- else isPricePending)])
362- }
363-
364-
365-
366-@Callable(i)
367-func finilizeCurrentPrice () = {
368- let account = toString(i.caller)
369- let priceProvidingCount = ((isOracleProvideInt(oracleOne) + isOracleProvideInt(oracleTwo)) + isOracleProvideInt(oracleThree))
370- let newPrice = ((((getOracleProvidePrice(oracleOne) * isOracleProvideInt(oracleOne)) + (getOracleProvidePrice(oracleTwo) * isOracleProvideInt(oracleTwo))) + (getOracleProvidePrice(oracleThree) * isOracleProvideInt(oracleThree))) / priceProvidingCount)
371- if (isBlocked)
372- then throw("contract is blocked")
373- else if (if (if ((account != oracleOne))
374- then (account != oracleTwo)
375- else false)
376- then (account != oracleThree)
377- else false)
378- then throw("permission denied")
379- else if (if (!(isPricePending))
380- then true
381- else (blockExpireProviding >= height))
382- then throw("wait for the end of the price providing")
383- else if ((2 > priceProvidingCount))
384- then throw("2/3 oracles need to set a price")
385- else if (if ((newPrice >= (price + ((price * percentPriceOffset) / 100))))
386- then true
387- else ((price - ((price * percentPriceOffset) / 100)) >= newPrice))
388- then WriteSet([DataEntry(IsBlockedKey, true), DataEntry(getBlackSwarmPriceKey(height), newPrice)])
389- else WriteSet([DataEntry(PriceKey, newPrice), DataEntry(getPriceHistoryKey(height), newPrice), DataEntry(IsPricePendingKey, false)])
390- }
391-
392-
393-
394-@Callable(i)
395-func adminUnlock (newPrice) = {
396- let account = toString(i.caller)
397- let adminOneVote = if ((account != adminOne))
398- then getAdminVoteInt(adminOne)
399- else 0
400- let adminTwoVote = if ((account != adminTwo))
401- then getAdminVoteInt(adminTwo)
402- else 0
403- let adminThreeVote = if ((account != adminThree))
404- then getAdminVoteInt(adminThree)
405- else 0
406- let adminOnePrice = if (((getAdminVotePrice(adminOne) * adminOneVote) == newPrice))
407- then 1
408- else 0
409- let adminTwoPrice = if (((getAdminVotePrice(adminTwo) * adminTwoVote) == newPrice))
410- then 1
411- else 0
412- let adminThreePrice = if (((getAdminVotePrice(adminThree) * adminThreeVote) == newPrice))
413- then 1
414- else 0
415- if (!(isBlocked))
416- then throw("Contract is not blocked")
417- else if (if (((((adminOnePrice + adminTwoPrice) + adminThreePrice) + 1) >= 2))
418- then (blockExpireVote >= height)
419- else false)
420- then WriteSet([DataEntry(IsBlockedKey, false), DataEntry(PriceKey, newPrice), DataEntry(getPriceHistoryKey(height), newPrice), DataEntry(getAdminVoteKey(adminOne), false), DataEntry(getAdminVoteKey(adminTwo), false), DataEntry(getAdminVoteKey(adminThree), false), DataEntry(BlockExpireVoteKey, 0), DataEntry(BlockExpireProvidingKey, 0), DataEntry(IsPricePendingKey, false)])
421- else WriteSet([DataEntry(getAdminVotePriceKey(account), newPrice), DataEntry(BlockExpireVoteKey, if ((height > blockExpireVote))
422- then (height + voteInterval)
423- else blockExpireVote), DataEntry(getAdminVoteKey(adminOne), if ((height > blockExpireVote))
424- then false
425- else (adminOneVote == 1)), DataEntry(getAdminVoteKey(adminTwo), if ((height > blockExpireVote))
426- then false
427- else (adminTwoVote == 1)), DataEntry(getAdminVoteKey(adminThree), if ((height > blockExpireVote))
428- then false
429- else (adminThreeVote == 1)), DataEntry(getAdminVoteKey(account), true)])
430- }
431-
432-
433-
434-@Callable(i)
435-func adminLock () = {
436- let account = toString(i.caller)
437- let adminOneVote = if ((account != adminOne))
438- then getAdminVoteInt(adminOne)
439- else 1
440- let adminTwoVote = if ((account != adminTwo))
441- then getAdminVoteInt(adminTwo)
442- else 1
443- let adminThreeVote = if ((account != adminThree))
444- then getAdminVoteInt(adminThree)
445- else 1
446- if (isBlocked)
447- then throw("Contract is blocked")
448- else if ((((adminOneVote + adminTwoVote) + adminThreeVote) >= 2))
449- then WriteSet([DataEntry(IsBlockedKey, true), DataEntry(getAdminVoteKey(adminOne), false), DataEntry(getAdminVoteKey(adminTwo), false), DataEntry(getAdminVoteKey(adminThree), false), DataEntry(BlockExpireVoteKey, 0)])
450- else WriteSet([DataEntry(BlockExpireVoteKey, if ((height > blockExpireVote))
451- then (height + voteInterval)
452- else blockExpireVote), DataEntry(getAdminVoteKey(adminOne), if ((height > blockExpireVote))
453- then false
454- else (adminOneVote == 1)), DataEntry(getAdminVoteKey(adminTwo), if ((height > blockExpireVote))
455- then false
456- else (adminTwoVote == 1)), DataEntry(getAdminVoteKey(adminThree), if ((height > blockExpireVote))
457- then false
458- else (adminThreeVote == 1))])
459- }
460-
271+func getLeaseTxExpireSendBlock (hash) = getNumberByKey(getLeaseTxExpireSendBlockKey(hash))
461272
462273
463274 @Callable(i)
464275 func swapWavesToNeutrino () = {
465276 let pmt = extract(i.payment)
277+ let account = toString(i.caller)
466278 if ((minWavesSwapAmount > pmt.amount))
467- then throw("amount less min")
279+ then throw((("an amount is less than min available amount: " + toString(minWavesSwapAmount)) + " wavelets"))
468280 else if (isDefined(pmt.assetId))
469281 then throw("can use waves only")
470282 else if (isBlocked)
471- then throw("contract is blocked")
472- else {
473- let amount = convertWavesToNeutrino(pmt.amount)
474- TransferSet([ScriptTransfer(i.caller, amount, neutrinoAssetId)])
475- }
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))])
476289 }
477290
478291
480293 @Callable(i)
481294 func swapNeutrinoToWaves () = {
482295 let pmt = extract(i.payment)
296+ let account = toString(i.caller)
483297 if ((minNeutrinoSwapAmount > pmt.amount))
484- then throw("amount less min")
298+ then throw((("an amount is less than min available amount: " + toString(minNeutrinoSwapAmount)) + " neutrino cents"))
485299 else if (isBlocked)
486- then throw("contract is blocked")
300+ then throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
487301 else if ((pmt.assetId != neutrinoAssetId))
488- then throw("can use neutrino only")
489- else {
490- let account = toBase58String(i.caller.bytes)
491- let amount = convertNeutrinoToWaves(pmt.amount)
492- WriteSet([DataEntry(getWavesBalanceKey(account), (getWavesBalance(account) + amount)), DataEntry(getBalanceUnlockBlockKey(account), (height + balanceLockInterval))])
493- }
302+ then throw("can use appropriate neutrino tokens only")
303+ else if ((getUnlockBalanceBlock(account) > height))
304+ then throw((("await " + toString((getUnlockBalanceBlock(account) - height))) + " blocks"))
305+ else if ((getAccountLockedBalance(account, neutrinoAssetIdString) != 0))
306+ then throw("please withdraw locked funds first")
307+ else {
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)))
310+ then false
311+ else true)])
312+ }
494313 }
495314
496315
497316
498317 @Callable(i)
499-func withdraw (account) = if ((getUnlockBalanceBlock(account) > height))
500- then throw("wait a couple of blocks for withdraw")
501- else ScriptResult(WriteSet([DataEntry(getWavesBalanceKey(account), 0), DataEntry(getNeutrinoBalanceKey(account), 0)]), TransferSet([ScriptTransfer(addressFromStringValue(account), getNeutrinoBalance(account), neutrinoAssetId), ScriptTransfer(addressFromStringValue(account), getWavesBalance(account), unit)]))
502-
503-
504-
505-@Callable(i)
506-func generateBond () = {
507- let deficit = (neutrinoSupply - convertWavesToNeutrino(reserve))
508- let balanceAuction = assetBalance(addressFromStringValue(auctionContract), bondAssetId)
509- let amount = (convertNeutrinoToBond(deficit) - balanceAuction)
318+func withdraw (account,index,lockedAssetId) = {
319+ let unlockHeight = getUnlockBalanceBlock(account)
320+ let lockedBalance = getAccountLockedBalance(account, lockedAssetId)
321+ let indexHeight = getHeightPriceByIndex(index)
322+ let nextIndexHeight = getHeightPriceByIndex((index + 1))
323+ let priceByIndex = getPriceHistory(indexHeight)
324+ let amount = if ((lockedAssetId == neutrinoAssetIdString))
325+ then convertNeutrinoToWaves(lockedBalance, priceByIndex)
326+ else convertWavesToNeutrino(lockedBalance, priceByIndex)
510327 if (isBlocked)
511- then throw("contract is blocked")
512- else if ((amount > 0))
513- then TransferSet([ScriptTransfer(addressFromStringValue(auctionContract), amount, bondAssetId)])
514- else throw("bond were generated or do not need it")
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)]))
515344 }
516345
517346
518347
519348 @Callable(i)
520-func setOrder () = {
521- let pmt = extract(i.payment)
522- let newOrderId = toBase58String(keccak256(((toBytes(pmt.amount) + i.caller.bytes) + toBytes(height))))
523- if ((pmt.assetId != bondAssetId))
524- then throw("can use bond only")
525- else if ((getOrderOwner(newOrderId) != ""))
526- then throw("order exists")
527- 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)])
528- }
529-
530-
531-
532-@Callable(i)
533-func cancelOrder (orderId) = {
534- let owner = getOrderOwner(orderId)
535- let amount = (getOrderTotal(orderId) - getOrderFilledTotal(orderId))
536- if ((owner != toString(i.caller)))
537- then throw("permission denied")
538- else ScriptResult(WriteSet([DataEntry(OrderbookKey, dropOrder(orderId)), DataEntry(getOrderStatusKey(orderId), CANCELED)]), TransferSet([ScriptTransfer(i.caller, amount, bondAssetId)]))
539- }
540-
541-
542-
543-@Callable(i)
544-func addLeasingCheck (id) = {
545- let tx = value(transferTransactionById(fromBase58String(id)))
546- if (if ((tx.recipient != addressFromStringValue(rpdContract)))
547- then true
548- else isLeasingProfitTxExist(id))
549- then throw("invalid transaction id")
550- else {
551- let amount = convertWavesToNeutrino(tx.amount)
552- let newRpdSyncIndex = (rpdSyncIndex + 1)
553- ScriptResult(WriteSet([DataEntry(RPDSyncIndexKey, newRpdSyncIndex), DataEntry(getRPDProfitKey(rpdSyncIndex), amount), DataEntry(getRPDSnapshotContractBalanceKey(rpdSyncIndex, neutrinoAssetId), getRPDContractBalance(neutrinoAssetId)), DataEntry(getRPDSnapshotContractBalanceKey(rpdSyncIndex, bondAssetId), getRPDContractBalance(bondAssetId)), DataEntry(getIsLeasingProfitTxExistKey(id), true)]), TransferSet([ScriptTransfer(addressFromStringValue(rpdContract), amount, neutrinoAssetId)]))
554- }
555- }
556-
557-
558-
559-@Callable(i)
560-func executeOrder () = {
561- let orderId = split(orderbook, LISTSPLITSYMBOL)[0]
562- let orderTotal = getOrderTotal(orderId)
563- let orderOwner = getOrderOwner(orderId)
564- let filledTotal = getOrderFilledTotal(orderId)
349+func transferToAuction () = {
350+ let deficitBondAmount = ((convertNeutrinoToBond(deficit) - assetBalance(addressFromStringValue(auctionContract), bondAssetId)) - totalLiquidationOrderbook)
351+ let surplusBond = ((convertNeutrinoToBond(surplus) - assetBalance(addressFromStringValue(auctionContract), neutrinoAssetId)) - totalOrderbook)
565352 if (isBlocked)
566- then throw("contract is blocked")
567- else if ((0 >= surplus))
568- then throw("surplus is less than zero")
569- else if ((orderOwner == ""))
570- then {
571- let newRpdSyncIndex = (rpdSyncIndex + 1)
572- ScriptResult(WriteSet([DataEntry(RPDSyncIndexKey, newRpdSyncIndex), DataEntry(getRPDProfitKey(rpdSyncIndex), surplus), DataEntry(getRPDSnapshotContractBalanceKey(rpdSyncIndex, neutrinoAssetId), getRPDContractBalance(neutrinoAssetId)), DataEntry(getRPDSnapshotContractBalanceKey(rpdSyncIndex, bondAssetId), getRPDContractBalance(bondAssetId))]), TransferSet([ScriptTransfer(addressFromStringValue(rpdContract), surplus, neutrinoAssetId)]))
573- }
574- else {
575- let amount = (orderTotal - filledTotal)
576- let surplusBond = convertNeutrinoToBond(surplus)
577- let status = if ((surplusBond >= amount))
578- then FILLED
579- else NEW
580- let newFilledTotal = if ((surplusBond >= amount))
581- then orderTotal
582- else surplusBond
583- ScriptResult(WriteSet([DataEntry(OrderbookKey, dropOrder(orderId)), DataEntry(getOrderFilledTotalKey(orderId), (filledTotal + newFilledTotal)), DataEntry(getOrderStatusKey(orderId), status)]), TransferSet([ScriptTransfer(addressFromStringValue(orderOwner), convertBondToNeutrino(newFilledTotal), neutrinoAssetId)]))
584- }
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")
585359 }
586360
587361
589363 @Callable(i)
590364 func transfer (account) = {
591365 let pmt = extract(i.payment)
592- if (isDefined(pmt.assetId))
593- then throw("can use waves only at the moment")
594- else TransferSet([ScriptTransfer(addressFromStringValue(account), pmt.amount, unit)])
366+ TransferSet([ScriptTransfer(addressFromStringValue(account), pmt.amount, pmt.assetId)])
367+ }
368+
369+
370+
371+@Callable(i)
372+func nodeReward () = {
373+ let pmt = value(i.payment)
374+ if ((i.caller != addressFromStringValue(nodeAddress)))
375+ then throw("only node account is able to transfer staking rewards from main account")
376+ else if (isDefined(pmt.assetId))
377+ then throw("waves tokens only allowed")
378+ else {
379+ let amount = convertWavesToNeutrino(pmt.amount, currentPrice)
380+ let newRpdSyncIndex = (rpdSyncIndex + 1)
381+ ScriptResult(WriteSet([DataEntry(RPDSyncIndexKey, newRpdSyncIndex), DataEntry(getRPDProfitKey(rpdSyncIndex), amount), DataEntry(getRPDSnapshotContractBalanceKey(rpdSyncIndex, neutrinoAssetId), getRPDContractBalance(neutrinoAssetId))]), TransferSet([ScriptTransfer(addressFromStringValue(rpdContract), amount, neutrinoAssetId)]))
382+ }
383+ }
384+
385+
386+
387+@Callable(i)
388+func registrationLeaseTx (senderPublicKey,fee,timestamp,leaseTxHash) = {
389+ let totalFreeReserve = (((reserve * LEASINGSHARE) / 100) - convertNeutrinoToWaves(getLockedBalance(neutrinoAssetIdString), currentPrice))
390+ let amount = (totalFreeReserve / LEASINTXCOUNT)
391+ let txBytes = (((((base58'3h1H' + fromBase58String(senderPublicKey)) + fromBase58String(nodeAddress)) + toBytes(amount)) + toBytes(fee)) + toBytes(timestamp))
392+ let txHashBytes = blake2b256(txBytes)
393+ let txHash = toBase58String(txHashBytes)
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))
406+ then true
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))])
424+ }
425+
426+
427+
428+@Callable(i)
429+func cancelStuckLeaseTx (txHash) = if (if (if ((getLeaseTxStatus(txHash) == NEW))
430+ then !(isDefined(transactionHeightById(fromBase58String(txHash))))
431+ else false)
432+ then (height > getLeaseTxExpireSendBlock(txHash))
433+ else false)
434+ then {
435+ let amount = getLeaseTxAmountByHash(txHash)
436+ WriteSet([DataEntry(LeasingTxCountKey, (leasingTxCount - 1)), DataEntry(LeasingAmountKey, (leasingAmount - amount)), DataEntry(getLeaseTxStatusKey(txHash), CANCELED), DataEntry(IsRebalanceKey, if (((reserveWithoutLeasing - amount) >= convertNeutrinoToWaves(getLockedBalance(neutrinoAssetIdString), currentPrice)))
437+ then false
438+ else true)])
439+ }
440+ else throw("invalid tx hash")
441+
442+
443+
444+@Callable(i)
445+func registrationUnleaseTx (chainIdString,senderPublicKey,fee,timestamp,leaseTxHash) = {
446+ let txBytes = (((((base58'gm' + toBytes(chainIdString)) + fromBase58String(senderPublicKey)) + toBytes(fee)) + toBytes(timestamp)) + fromBase58String(leaseTxHash))
447+ let txHash = blake2b256(txBytes)
448+ if ((getLeaseTxStatus(leaseTxHash) != NEW))
449+ then throw("invalid tx status")
450+ else if ((this != addressFromPublicKey(fromBase58String(senderPublicKey))))
451+ then throw("invalid pubKey")
452+ else if (!(isDefined(transactionHeightById(txHash))))
453+ then throw("blockchain does not contain this transaction")
454+ else {
455+ let amount = getLeaseTxAmountByHash(leaseTxHash)
456+ WriteSet([DataEntry(LeasingTxCountKey, (leasingTxCount - 1)), DataEntry(LeasingAmountKey, (leasingAmount - amount)), DataEntry(getLeaseTxStatusKey(leaseTxHash), CANCELED), DataEntry(IsRebalanceKey, if (((reserveWithoutLeasing - amount) >= convertNeutrinoToWaves(getLockedBalance(neutrinoAssetIdString), currentPrice)))
457+ then false
458+ else true)])
459+ }
595460 }
596461
597462
598463 @Verifier(tx)
599-func verify () = match tx {
600- case leaseTx: LeaseTransaction =>
601- sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(getOwnerPubKeyByLeaseTxId(toBase58String(leaseTx.id))))
602- case unleaseTx: LeaseCancelTransaction =>
603- sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(getOwnerPubKeyByLeaseTxId(toBase58String(unleaseTx.leaseId))))
604- case _ =>
605- sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
606-}
464+func verify () = {
465+ let id = toBase58String(tx.id)
466+ match tx {
467+ case leaseTx: LeaseTransaction =>
468+ if (if ((leasingExpireBlock >= height))
469+ then (getLeaseTxExpireSendBlock(id) >= height)
470+ else false)
471+ then (getLeaseTxStatus(id) == NEW)
472+ else false
473+ case unleaseTx: LeaseCancelTransaction =>
474+ let leaseId = toBase58String(unleaseTx.leaseId)
475+ if (if (if ((height > leasingExpireBlock))
476+ then true
477+ else isRebalance)
478+ then (unleaseTx.fee == getCancelLeaseTxReserveFee(leaseId))
479+ else false)
480+ then (getLeaseTxStatus(leaseId) == NEW)
481+ else false
482+ case _ =>
483+ sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
484+ }
485+ }
607486
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
36-func getStringByAddressAndKey (address,key) = match getString(this, key) {
36+func getStringByAddressAndKey (address,key) = match getString(addressFromStringValue(address), key) {
3737 case a: String =>
3838 a
3939 case _ =>
4040 ""
4141 }
4242
4343
44+func getBoolByAddressAndKey (address,key) = match getBoolean(addressFromStringValue(address), key) {
45+ case a: Boolean =>
46+ a
47+ case _ =>
48+ false
49+}
50+
51+
52+let SENDTXEXPIRE = 30
53+
4454 let LISTSPLITSYMBOL = "_"
4555
4656 let LISTDATASYMBOL = "+"
4757
4858 let WAVELET = 100000000
4959
50-let CENTSINDOLLAR = 100
60+let PAULI = 100
61+
62+let CRYTICALSHARE = 20
63+
64+let LEASINGSHARE = 90
65+
66+let LEASINTXCOUNT = 10
67+
68+let DEFICITOFFSET = 10
69+
70+let WAVESASSETID = "waves"
5171
5272 let CANCELED = "canceled"
5373
5474 let NEW = "new"
5575
56-let FILLED = "filled"
57-
5876 let NeutrinoAssetIdKey = "neutrino_asset_id"
5977
6078 let BondAssetIdKey = "bond_asset_id"
6179
80+let ReserveContractKey = "reserve_contract"
81+
6282 let AuctionContractKey = "auction_contract"
83+
84+let LiquidationContractKey = "liquidation_contract"
6385
6486 let RPDContractKey = "rpd_contract"
6587
88+let ContolContractKey = "control_contract"
89+
6690 let BalanceLockIntervalKey = "balance_lock_interval"
67-
68-let VoteIntervalKey = "vote_interval"
6991
7092 let MinWavesSwapAmountKey = "min_waves_swap_amount"
7193
7294 let MinNeutrinoSwapAmountKey = "min_neutrino_swap_amount"
7395
74-let PriceOffsetKey = "price_offset"
96+let NodeAddressKey = "node_address"
7597
76-let ProvidingIntervalKey = "providing_interval"
98+let NodeOracleProviderKey = "oracle_node_provider"
99+
100+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"
77110
78111 let PriceKey = "price"
79112
80-let NeutrinoBalanceKey = "neutrino_"
81-
82-let WavesBalanceKey = "waves_"
83-
84-let BalanceUnlockBlockKey = "balance_block_"
85-
86-let OrderbookKey = "orderbook"
87-
88-let OrderTotalKey = "order_total_"
89-
90-let OrderOwnerKey = "order_owner_"
91-
92-let OrderHeightKey = "order_height_"
93-
94-let OrderFilledTotalKey = "order_filled_total_"
95-
96-let OrderStatusKey = "order_status_"
97-
98-let RPDSyncIndexKey = "rpd_sync_index"
99-
100-let RPDProfitKey = "rpd_profit"
101-
102-let RPDBalanceKey = "rpd_balance"
113+let PriceIndexKey = "price_index"
103114
104115 let IsBlockedKey = "is_blocked"
105116
106-let BlackSwarmPriceKey = "black_swarm_price"
117+let LeasingExpireBlockKey = "leasing_expire_block"
107118
108-let AdminVoteKey = "admin_vote_"
119+let IsRebalanceKey = "is_rebalance"
109120
110-let AdminVotePriceKey = "admin_vote_price_"
121+let LeasingTxCountKey = "leasing_index"
111122
112-let BlockExpireVoteKey = "vote_expire_block"
123+let LeasingAmountKey = "leasing_amount"
113124
114-let AdminKey = "admin_"
115-
116-let IsPricePendingKey = "is_pending_price"
117-
118-let OracleKey = "oracle_"
119-
120-let OracleIsProvideKey = "oracle_is_provide_"
121-
122-let OracleProvidePriceKey = "oracle_price_provide_"
123-
124-let BlockExpireProvidingKey = "providing_expire_block"
125-
126-let ApprovedLeaseTxKey = "leasetx"
127-
128-let IsLeasingProfitTxExistKey = "is_leasing_profit"
129-
130-func getAdminKey (count) = (AdminKey + toString(count))
125+func getPriceHistoryKey (block) = ((PriceKey + "_") + toString(block))
131126
132127
133-func getAdminVoteKey (owner) = (AdminVoteKey + owner)
128+func getHeightPriceByIndexKey (index) = ((PriceIndexKey + "_") + toString(index))
134129
135130
136-func getAdminVotePriceKey (owner) = (AdminVotePriceKey + owner)
137-
138-
139-func getOracleKey (count) = (OracleKey + toString(count))
140-
141-
142-func getOracleIsProvideKey (owner) = (OracleIsProvideKey + owner)
143-
144-
145-func getOracleProvidePriceKey (owner) = (OracleProvidePriceKey + owner)
146-
131+let RPDSyncIndexKey = "rpd_sync_index"
147132
148133 func getRPDSnapshotContractBalanceKey (count,assetId) = ((((RPDBalanceKey + "_") + toBase58String(assetId)) + "_") + toString(count))
149134
150135
151-func getRPDContractBalanceKey (assetId) = ((RPDBalanceKey + "_") + toBase58String(assetId))
136+func getCancelLeaseTxReserveFeeKey (hash) = (("cancel_lease_tx_reserve_fee" + "_") + hash)
152137
153138
154-func getRPDProfitKey (count) = ((RPDProfitKey + "_") + toString(count))
139+func getAccountLockedBalanceKey (owner,assetId) = ((("balance_" + assetId) + "_") + owner)
155140
156141
157-func getNeutrinoBalanceKey (owner) = (NeutrinoBalanceKey + owner)
142+func getBalanceUnlockBlockKey (owner) = ("balance_block_" + owner)
158143
159144
160-func getWavesBalanceKey (owner) = (WavesBalanceKey + owner)
145+func getRPDProfitKey (count) = (("rpd_profit" + "_") + toString(count))
161146
162147
163-func getBalanceUnlockBlockKey (owner) = (BalanceUnlockBlockKey + owner)
148+func getLockedBalanceKey (assetId) = ("balance_" + assetId)
164149
165150
166-func getBlackSwarmPriceKey (block) = ((BlackSwarmPriceKey + "_") + toString(block))
151+func getLeaseTxStatusKey (hash) = (("lease_tx_status" + "_") + hash)
167152
168153
169-func getPriceHistoryKey (block) = ((PriceKey + "_") + toString(block))
154+func getLeaseTxAmountByHashKey (hash) = ((LeasingAmountKey + "_") + hash)
170155
171156
172-func getOwnerPubKeyByLeaseTxIdKey (txId) = ((ApprovedLeaseTxKey + "_") + txId)
157+func getLeaseTxBytesByHashKey (hash) = (("lease_tx" + "_") + hash)
173158
174159
175-func getIsLeasingProfitTxExistKey (txId) = ((IsLeasingProfitTxExistKey + "_") + txId)
160+func getLeaseTxExpireSendBlockKey (hash) = (("leasing_expire_send" + "_") + hash)
176161
177162
178-func getOrderTotalKey (orderId) = (OrderTotalKey + orderId)
163+func convertNeutrinoToWaves (amount,price) = ((((amount * 100) / price) * WAVELET) / PAULI)
179164
180165
181-func getOrderOwnerKey (orderId) = (OrderOwnerKey + orderId)
166+func convertWavesToNeutrino (amount,price) = ((((amount * price) / 100) * PAULI) / WAVELET)
182167
183168
184-func getOrderHeightKey (orderId) = (OrderHeightKey + orderId)
169+func convertNeutrinoToBond (amount) = (amount / PAULI)
185170
186171
187-func getOrderStatusKey (orderId) = (OrderStatusKey + orderId)
172+func convertBondToNeutrino (amount) = (amount * PAULI)
188173
189174
190-func getOrderFilledTotalKey (orderId) = (OrderFilledTotalKey + orderId)
175+func convertWavesToBond (amount,price) = convertNeutrinoToBond(convertWavesToNeutrino(amount, price))
191176
192177
193-let price = getNumberByKey(PriceKey)
194-
195-func convertNeutrinoToWaves (amount) = ((((amount * 100) / price) * WAVELET) / CENTSINDOLLAR)
178+func getLockedBalance (assetId) = getNumberByKey(getLockedBalanceKey(assetId))
196179
197180
198-func convertWavesToNeutrino (amount) = ((((amount * price) / 100) * CENTSINDOLLAR) / WAVELET)
181+let liquidationContract = getStringByKey(LiquidationContractKey)
199182
183+let neutrinoAssetIdString = getStringByKey(NeutrinoAssetIdKey)
200184
201-func convertNeutrinoToBond (amount) = (amount / CENTSINDOLLAR)
185+let neutrinoAssetId = fromBase58String(neutrinoAssetIdString)
202186
187+let reserveContract = getStringByKey(ReserveContractKey)
203188
204-func convertBondToNeutrino (amount) = (amount * CENTSINDOLLAR)
189+let auctionContract = getStringByKey(AuctionContractKey)
205190
191+let rpdContract = getStringByKey(RPDContractKey)
206192
207-func convertWavesToBond (amount) = convertNeutrinoToBond(convertWavesToNeutrino(amount))
193+let controlContract = getStringByKey(ContolContractKey)
208194
195+let currentPrice = getNumberByAddressAndKey(controlContract, PriceKey)
209196
210-let providingInterval = getNumberByKey(ProvidingIntervalKey)
197+let priceIndex = getNumberByAddressAndKey(controlContract, PriceIndexKey)
211198
212-let blockExpireProviding = getNumberByKey(BlockExpireProvidingKey)
199+let isBlocked = getBoolByAddressAndKey(controlContract, IsBlockedKey)
213200
214-let isPricePending = getBoolByKey(IsPricePendingKey)
201+let leasingTxCount = getNumberByKey(LeasingTxCountKey)
215202
216-let percentPriceOffset = getNumberByKey(PriceOffsetKey)
203+let isRebalance = getBoolByKey(IsRebalanceKey)
204+
205+let leasingInterval = getNumberByKey(LeasingIntervalKey)
206+
207+let leasingExpireBlock = getNumberByKey(LeasingExpireBlockKey)
208+
209+let leasingAmount = getNumberByKey(LeasingAmountKey)
210+
211+let nodeAddress = getStringByKey(NodeAddressKey)
212+
213+let nodeOracleProviderKey = getStringByKey(NodeOracleProviderKey)
217214
218215 let rpdSyncIndex = getNumberByKey(RPDSyncIndexKey)
219216
220-let voteInterval = getNumberByKey(VoteIntervalKey)
221-
222-let blockExpireVote = getNumberByKey(BlockExpireVoteKey)
223-
224217 let balanceLockInterval = getNumberByKey(BalanceLockIntervalKey)
225-
226-let isBlocked = getBoolByKey(IsBlockedKey)
227218
228219 let minWavesSwapAmount = getNumberByKey(MinWavesSwapAmountKey)
229220
230221 let minNeutrinoSwapAmount = getNumberByKey(MinNeutrinoSwapAmountKey)
231222
232-let neutrinoAssetId = fromBase58String(getStringByKey(NeutrinoAssetIdKey))
223+let reserve = (wavesBalance(this) - getLockedBalance(WAVESASSETID))
233224
234-let auctionContract = getStringByKey(AuctionContractKey)
235-
236-let rpdContract = getStringByKey(RPDContractKey)
237-
238-let reserve = wavesBalance(this)
239-
240-let orderbook = getStringByKey(OrderbookKey)
225+let reserveWithoutLeasing = (reserve - leasingAmount)
241226
242227 let bondAssetId = fromBase58String(getStringByKey(BondAssetIdKey))
243228
244-let bondSupply = {
245- let info = extract(assetInfo(bondAssetId))
246- (info.quantity - assetBalance(this, bondAssetId))
247- }
229+let bondSupply = (extract(assetInfo(bondAssetId)).quantity - assetBalance(this, bondAssetId))
248230
249-let neutrinoSupply = {
250- let info = extract(assetInfo(neutrinoAssetId))
251- (info.quantity - assetBalance(this, neutrinoAssetId))
252- }
231+let neutrinoSupply = ((extract(assetInfo(neutrinoAssetId)).quantity - assetBalance(this, neutrinoAssetId)) + getLockedBalance(neutrinoAssetIdString))
253232
254-let surplus = (convertWavesToNeutrino(reserve) - neutrinoSupply)
233+let surplus = (convertWavesToNeutrino(reserve, currentPrice) - neutrinoSupply)
255234
256-let oracleOne = getStringByKey(getOracleKey(0))
257-
258-let oracleTwo = getStringByKey(getOracleKey(1))
259-
260-let oracleThree = getStringByKey(getOracleKey(2))
261-
262-let adminOne = getStringByKey(getAdminKey(0))
263-
264-let adminTwo = getStringByKey(getAdminKey(1))
265-
266-let adminThree = getStringByKey(getAdminKey(2))
267-
268-func getOwnerPubKeyByLeaseTxId (owner) = getStringByAddressAndKey(rpdContract, getOwnerPubKeyByLeaseTxIdKey(owner))
269-
235+let deficit = (neutrinoSupply - convertWavesToNeutrino(reserve, currentPrice))
270236
271237 func getRPDContractBalance (assetId) = getNumberByAddressAndKey(rpdContract, getRPDContractBalanceKey(assetId))
272238
273239
274-func isLeasingProfitTxExist (txId) = getBoolByKey(getIsLeasingProfitTxExistKey(txId))
240+let totalLiquidationOrderbook = getNumberByAddressAndKey(auctionContract, TotalLiquidationOrderbookKey)
241+
242+let totalOrderbook = getNumberByAddressAndKey(auctionContract, TotalOrderbookKey)
243+
244+func getPriceHistory (block) = getNumberByAddressAndKey(controlContract, getPriceHistoryKey(block))
275245
276246
277-func getAdminVoteInt (owner) = if (getBoolByKey(getAdminVoteKey(owner)))
278- then 1
279- else 0
247+func getHeightPriceByIndex (index) = getNumberByAddressAndKey(controlContract, getHeightPriceByIndexKey(index))
280248
281249
282-func getAdminVotePrice (owner) = getNumberByKey(getAdminVotePriceKey(owner))
250+func getCancelLeaseTxReserveFee (hash) = getNumberByKey(getCancelLeaseTxReserveFeeKey(hash))
283251
284252
285-func isOracleProvide (owner) = getBoolByKey(getOracleIsProvideKey(owner))
286-
287-
288-func isOracleProvideInt (owner) = if (isOracleProvide(owner))
289- then 1
290- else 0
291-
292-
293-func getOracleProvidePrice (owner) = getNumberByKey(getOracleProvidePriceKey(owner))
294-
295-
296-func getWavesBalance (owner) = getNumberByKey(getWavesBalanceKey(owner))
297-
298-
299-func getNeutrinoBalance (owner) = getNumberByKey(getNeutrinoBalanceKey(owner))
253+func getAccountLockedBalance (owner,assetId) = getNumberByKey(getAccountLockedBalanceKey(owner, assetId))
300254
301255
302256 func getUnlockBalanceBlock (owner) = getNumberByKey(getBalanceUnlockBlockKey(owner))
303257
304258
305-func getOrderTotal (id) = getNumberByKey(getOrderTotalKey(id))
306-
307-
308-func getOrderOwner (id) = getStringByKey(getOrderOwnerKey(id))
309-
310-
311-func getOrderFilledTotal (id) = getNumberByKey(getOrderFilledTotalKey(id))
312-
313-
314259 func getRPDProfit (count) = getNumberByKey(getRPDProfitKey(count))
315260
316261
317-func getOrderElementById (id) = (id + LISTSPLITSYMBOL)
262+func getLeaseTxStatus (hash) = getStringByKey(getLeaseTxStatusKey(hash))
318263
319264
320-func addOrder (orderId) = (orderbook + getOrderElementById(orderId))
265+func getLeaseTxAmountByHash (hash) = getNumberByKey(getLeaseTxAmountByHashKey(hash))
321266
322267
323-func dropOrder (orderId) = {
324- let parts = split(orderbook, getOrderElementById(orderId))
325- (parts[0] + parts[1])
326- }
268+func getLeaseTxBytesByHash (hash) = getStringByKey(getLeaseTxBytesByHashKey(hash))
327269
328270
329-@Callable(i)
330-func setCurrentPrice (newPrice) = {
331- let account = toString(i.caller)
332- let priceProvidingCount = (((isOracleProvideInt(oracleOne) + isOracleProvideInt(oracleTwo)) + isOracleProvideInt(oracleThree)) + 1)
333- if (isBlocked)
334- then throw("contract is blocked")
335- else if (if (if ((account != oracleOne))
336- then (account != oracleTwo)
337- else false)
338- then (account != oracleThree)
339- else false)
340- then throw("permission denied")
341- else if (if ((blockExpireProviding >= height))
342- then isOracleProvide(account)
343- else false)
344- then throw("price is already provided")
345- else if (if ((height > blockExpireProviding))
346- then isPricePending
347- else false)
348- then throw("use finilizeCurrentPrice")
349- else WriteSet([DataEntry(getOracleProvidePriceKey(account), newPrice), DataEntry(BlockExpireProvidingKey, if ((height > blockExpireProviding))
350- then (height + providingInterval)
351- else blockExpireProviding), DataEntry(getOracleIsProvideKey(oracleOne), if ((height > blockExpireProviding))
352- then false
353- else isOracleProvide(oracleOne)), DataEntry(getOracleIsProvideKey(oracleTwo), if ((height > blockExpireProviding))
354- then false
355- else isOracleProvide(oracleTwo)), DataEntry(getOracleIsProvideKey(oracleThree), if ((height > blockExpireProviding))
356- then false
357- else isOracleProvide(oracleThree)), DataEntry(getOracleIsProvideKey(account), true), DataEntry(IsPricePendingKey, if (if ((blockExpireProviding >= height))
358- then (priceProvidingCount >= 2)
359- else false)
360- then true
361- else isPricePending)])
362- }
363-
364-
365-
366-@Callable(i)
367-func finilizeCurrentPrice () = {
368- let account = toString(i.caller)
369- let priceProvidingCount = ((isOracleProvideInt(oracleOne) + isOracleProvideInt(oracleTwo)) + isOracleProvideInt(oracleThree))
370- let newPrice = ((((getOracleProvidePrice(oracleOne) * isOracleProvideInt(oracleOne)) + (getOracleProvidePrice(oracleTwo) * isOracleProvideInt(oracleTwo))) + (getOracleProvidePrice(oracleThree) * isOracleProvideInt(oracleThree))) / priceProvidingCount)
371- if (isBlocked)
372- then throw("contract is blocked")
373- else if (if (if ((account != oracleOne))
374- then (account != oracleTwo)
375- else false)
376- then (account != oracleThree)
377- else false)
378- then throw("permission denied")
379- else if (if (!(isPricePending))
380- then true
381- else (blockExpireProviding >= height))
382- then throw("wait for the end of the price providing")
383- else if ((2 > priceProvidingCount))
384- then throw("2/3 oracles need to set a price")
385- else if (if ((newPrice >= (price + ((price * percentPriceOffset) / 100))))
386- then true
387- else ((price - ((price * percentPriceOffset) / 100)) >= newPrice))
388- then WriteSet([DataEntry(IsBlockedKey, true), DataEntry(getBlackSwarmPriceKey(height), newPrice)])
389- else WriteSet([DataEntry(PriceKey, newPrice), DataEntry(getPriceHistoryKey(height), newPrice), DataEntry(IsPricePendingKey, false)])
390- }
391-
392-
393-
394-@Callable(i)
395-func adminUnlock (newPrice) = {
396- let account = toString(i.caller)
397- let adminOneVote = if ((account != adminOne))
398- then getAdminVoteInt(adminOne)
399- else 0
400- let adminTwoVote = if ((account != adminTwo))
401- then getAdminVoteInt(adminTwo)
402- else 0
403- let adminThreeVote = if ((account != adminThree))
404- then getAdminVoteInt(adminThree)
405- else 0
406- let adminOnePrice = if (((getAdminVotePrice(adminOne) * adminOneVote) == newPrice))
407- then 1
408- else 0
409- let adminTwoPrice = if (((getAdminVotePrice(adminTwo) * adminTwoVote) == newPrice))
410- then 1
411- else 0
412- let adminThreePrice = if (((getAdminVotePrice(adminThree) * adminThreeVote) == newPrice))
413- then 1
414- else 0
415- if (!(isBlocked))
416- then throw("Contract is not blocked")
417- else if (if (((((adminOnePrice + adminTwoPrice) + adminThreePrice) + 1) >= 2))
418- then (blockExpireVote >= height)
419- else false)
420- then WriteSet([DataEntry(IsBlockedKey, false), DataEntry(PriceKey, newPrice), DataEntry(getPriceHistoryKey(height), newPrice), DataEntry(getAdminVoteKey(adminOne), false), DataEntry(getAdminVoteKey(adminTwo), false), DataEntry(getAdminVoteKey(adminThree), false), DataEntry(BlockExpireVoteKey, 0), DataEntry(BlockExpireProvidingKey, 0), DataEntry(IsPricePendingKey, false)])
421- else WriteSet([DataEntry(getAdminVotePriceKey(account), newPrice), DataEntry(BlockExpireVoteKey, if ((height > blockExpireVote))
422- then (height + voteInterval)
423- else blockExpireVote), DataEntry(getAdminVoteKey(adminOne), if ((height > blockExpireVote))
424- then false
425- else (adminOneVote == 1)), DataEntry(getAdminVoteKey(adminTwo), if ((height > blockExpireVote))
426- then false
427- else (adminTwoVote == 1)), DataEntry(getAdminVoteKey(adminThree), if ((height > blockExpireVote))
428- then false
429- else (adminThreeVote == 1)), DataEntry(getAdminVoteKey(account), true)])
430- }
431-
432-
433-
434-@Callable(i)
435-func adminLock () = {
436- let account = toString(i.caller)
437- let adminOneVote = if ((account != adminOne))
438- then getAdminVoteInt(adminOne)
439- else 1
440- let adminTwoVote = if ((account != adminTwo))
441- then getAdminVoteInt(adminTwo)
442- else 1
443- let adminThreeVote = if ((account != adminThree))
444- then getAdminVoteInt(adminThree)
445- else 1
446- if (isBlocked)
447- then throw("Contract is blocked")
448- else if ((((adminOneVote + adminTwoVote) + adminThreeVote) >= 2))
449- then WriteSet([DataEntry(IsBlockedKey, true), DataEntry(getAdminVoteKey(adminOne), false), DataEntry(getAdminVoteKey(adminTwo), false), DataEntry(getAdminVoteKey(adminThree), false), DataEntry(BlockExpireVoteKey, 0)])
450- else WriteSet([DataEntry(BlockExpireVoteKey, if ((height > blockExpireVote))
451- then (height + voteInterval)
452- else blockExpireVote), DataEntry(getAdminVoteKey(adminOne), if ((height > blockExpireVote))
453- then false
454- else (adminOneVote == 1)), DataEntry(getAdminVoteKey(adminTwo), if ((height > blockExpireVote))
455- then false
456- else (adminTwoVote == 1)), DataEntry(getAdminVoteKey(adminThree), if ((height > blockExpireVote))
457- then false
458- else (adminThreeVote == 1))])
459- }
460-
271+func getLeaseTxExpireSendBlock (hash) = getNumberByKey(getLeaseTxExpireSendBlockKey(hash))
461272
462273
463274 @Callable(i)
464275 func swapWavesToNeutrino () = {
465276 let pmt = extract(i.payment)
277+ let account = toString(i.caller)
466278 if ((minWavesSwapAmount > pmt.amount))
467- then throw("amount less min")
279+ then throw((("an amount is less than min available amount: " + toString(minWavesSwapAmount)) + " wavelets"))
468280 else if (isDefined(pmt.assetId))
469281 then throw("can use waves only")
470282 else if (isBlocked)
471- then throw("contract is blocked")
472- else {
473- let amount = convertWavesToNeutrino(pmt.amount)
474- TransferSet([ScriptTransfer(i.caller, amount, neutrinoAssetId)])
475- }
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))])
476289 }
477290
478291
479292
480293 @Callable(i)
481294 func swapNeutrinoToWaves () = {
482295 let pmt = extract(i.payment)
296+ let account = toString(i.caller)
483297 if ((minNeutrinoSwapAmount > pmt.amount))
484- then throw("amount less min")
298+ then throw((("an amount is less than min available amount: " + toString(minNeutrinoSwapAmount)) + " neutrino cents"))
485299 else if (isBlocked)
486- then throw("contract is blocked")
300+ then throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
487301 else if ((pmt.assetId != neutrinoAssetId))
488- then throw("can use neutrino only")
489- else {
490- let account = toBase58String(i.caller.bytes)
491- let amount = convertNeutrinoToWaves(pmt.amount)
492- WriteSet([DataEntry(getWavesBalanceKey(account), (getWavesBalance(account) + amount)), DataEntry(getBalanceUnlockBlockKey(account), (height + balanceLockInterval))])
493- }
302+ then throw("can use appropriate neutrino tokens only")
303+ else if ((getUnlockBalanceBlock(account) > height))
304+ then throw((("await " + toString((getUnlockBalanceBlock(account) - height))) + " blocks"))
305+ else if ((getAccountLockedBalance(account, neutrinoAssetIdString) != 0))
306+ then throw("please withdraw locked funds first")
307+ else {
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)))
310+ then false
311+ else true)])
312+ }
494313 }
495314
496315
497316
498317 @Callable(i)
499-func withdraw (account) = if ((getUnlockBalanceBlock(account) > height))
500- then throw("wait a couple of blocks for withdraw")
501- else ScriptResult(WriteSet([DataEntry(getWavesBalanceKey(account), 0), DataEntry(getNeutrinoBalanceKey(account), 0)]), TransferSet([ScriptTransfer(addressFromStringValue(account), getNeutrinoBalance(account), neutrinoAssetId), ScriptTransfer(addressFromStringValue(account), getWavesBalance(account), unit)]))
502-
503-
504-
505-@Callable(i)
506-func generateBond () = {
507- let deficit = (neutrinoSupply - convertWavesToNeutrino(reserve))
508- let balanceAuction = assetBalance(addressFromStringValue(auctionContract), bondAssetId)
509- let amount = (convertNeutrinoToBond(deficit) - balanceAuction)
318+func withdraw (account,index,lockedAssetId) = {
319+ let unlockHeight = getUnlockBalanceBlock(account)
320+ let lockedBalance = getAccountLockedBalance(account, lockedAssetId)
321+ let indexHeight = getHeightPriceByIndex(index)
322+ let nextIndexHeight = getHeightPriceByIndex((index + 1))
323+ let priceByIndex = getPriceHistory(indexHeight)
324+ let amount = if ((lockedAssetId == neutrinoAssetIdString))
325+ then convertNeutrinoToWaves(lockedBalance, priceByIndex)
326+ else convertWavesToNeutrino(lockedBalance, priceByIndex)
510327 if (isBlocked)
511- then throw("contract is blocked")
512- else if ((amount > 0))
513- then TransferSet([ScriptTransfer(addressFromStringValue(auctionContract), amount, bondAssetId)])
514- else throw("bond were generated or do not need it")
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)]))
515344 }
516345
517346
518347
519348 @Callable(i)
520-func setOrder () = {
521- let pmt = extract(i.payment)
522- let newOrderId = toBase58String(keccak256(((toBytes(pmt.amount) + i.caller.bytes) + toBytes(height))))
523- if ((pmt.assetId != bondAssetId))
524- then throw("can use bond only")
525- else if ((getOrderOwner(newOrderId) != ""))
526- then throw("order exists")
527- 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)])
528- }
529-
530-
531-
532-@Callable(i)
533-func cancelOrder (orderId) = {
534- let owner = getOrderOwner(orderId)
535- let amount = (getOrderTotal(orderId) - getOrderFilledTotal(orderId))
536- if ((owner != toString(i.caller)))
537- then throw("permission denied")
538- else ScriptResult(WriteSet([DataEntry(OrderbookKey, dropOrder(orderId)), DataEntry(getOrderStatusKey(orderId), CANCELED)]), TransferSet([ScriptTransfer(i.caller, amount, bondAssetId)]))
539- }
540-
541-
542-
543-@Callable(i)
544-func addLeasingCheck (id) = {
545- let tx = value(transferTransactionById(fromBase58String(id)))
546- if (if ((tx.recipient != addressFromStringValue(rpdContract)))
547- then true
548- else isLeasingProfitTxExist(id))
549- then throw("invalid transaction id")
550- else {
551- let amount = convertWavesToNeutrino(tx.amount)
552- let newRpdSyncIndex = (rpdSyncIndex + 1)
553- ScriptResult(WriteSet([DataEntry(RPDSyncIndexKey, newRpdSyncIndex), DataEntry(getRPDProfitKey(rpdSyncIndex), amount), DataEntry(getRPDSnapshotContractBalanceKey(rpdSyncIndex, neutrinoAssetId), getRPDContractBalance(neutrinoAssetId)), DataEntry(getRPDSnapshotContractBalanceKey(rpdSyncIndex, bondAssetId), getRPDContractBalance(bondAssetId)), DataEntry(getIsLeasingProfitTxExistKey(id), true)]), TransferSet([ScriptTransfer(addressFromStringValue(rpdContract), amount, neutrinoAssetId)]))
554- }
555- }
556-
557-
558-
559-@Callable(i)
560-func executeOrder () = {
561- let orderId = split(orderbook, LISTSPLITSYMBOL)[0]
562- let orderTotal = getOrderTotal(orderId)
563- let orderOwner = getOrderOwner(orderId)
564- let filledTotal = getOrderFilledTotal(orderId)
349+func transferToAuction () = {
350+ let deficitBondAmount = ((convertNeutrinoToBond(deficit) - assetBalance(addressFromStringValue(auctionContract), bondAssetId)) - totalLiquidationOrderbook)
351+ let surplusBond = ((convertNeutrinoToBond(surplus) - assetBalance(addressFromStringValue(auctionContract), neutrinoAssetId)) - totalOrderbook)
565352 if (isBlocked)
566- then throw("contract is blocked")
567- else if ((0 >= surplus))
568- then throw("surplus is less than zero")
569- else if ((orderOwner == ""))
570- then {
571- let newRpdSyncIndex = (rpdSyncIndex + 1)
572- ScriptResult(WriteSet([DataEntry(RPDSyncIndexKey, newRpdSyncIndex), DataEntry(getRPDProfitKey(rpdSyncIndex), surplus), DataEntry(getRPDSnapshotContractBalanceKey(rpdSyncIndex, neutrinoAssetId), getRPDContractBalance(neutrinoAssetId)), DataEntry(getRPDSnapshotContractBalanceKey(rpdSyncIndex, bondAssetId), getRPDContractBalance(bondAssetId))]), TransferSet([ScriptTransfer(addressFromStringValue(rpdContract), surplus, neutrinoAssetId)]))
573- }
574- else {
575- let amount = (orderTotal - filledTotal)
576- let surplusBond = convertNeutrinoToBond(surplus)
577- let status = if ((surplusBond >= amount))
578- then FILLED
579- else NEW
580- let newFilledTotal = if ((surplusBond >= amount))
581- then orderTotal
582- else surplusBond
583- ScriptResult(WriteSet([DataEntry(OrderbookKey, dropOrder(orderId)), DataEntry(getOrderFilledTotalKey(orderId), (filledTotal + newFilledTotal)), DataEntry(getOrderStatusKey(orderId), status)]), TransferSet([ScriptTransfer(addressFromStringValue(orderOwner), convertBondToNeutrino(newFilledTotal), neutrinoAssetId)]))
584- }
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")
585359 }
586360
587361
588362
589363 @Callable(i)
590364 func transfer (account) = {
591365 let pmt = extract(i.payment)
592- if (isDefined(pmt.assetId))
593- then throw("can use waves only at the moment")
594- else TransferSet([ScriptTransfer(addressFromStringValue(account), pmt.amount, unit)])
366+ TransferSet([ScriptTransfer(addressFromStringValue(account), pmt.amount, pmt.assetId)])
367+ }
368+
369+
370+
371+@Callable(i)
372+func nodeReward () = {
373+ let pmt = value(i.payment)
374+ if ((i.caller != addressFromStringValue(nodeAddress)))
375+ then throw("only node account is able to transfer staking rewards from main account")
376+ else if (isDefined(pmt.assetId))
377+ then throw("waves tokens only allowed")
378+ else {
379+ let amount = convertWavesToNeutrino(pmt.amount, currentPrice)
380+ let newRpdSyncIndex = (rpdSyncIndex + 1)
381+ ScriptResult(WriteSet([DataEntry(RPDSyncIndexKey, newRpdSyncIndex), DataEntry(getRPDProfitKey(rpdSyncIndex), amount), DataEntry(getRPDSnapshotContractBalanceKey(rpdSyncIndex, neutrinoAssetId), getRPDContractBalance(neutrinoAssetId))]), TransferSet([ScriptTransfer(addressFromStringValue(rpdContract), amount, neutrinoAssetId)]))
382+ }
383+ }
384+
385+
386+
387+@Callable(i)
388+func registrationLeaseTx (senderPublicKey,fee,timestamp,leaseTxHash) = {
389+ let totalFreeReserve = (((reserve * LEASINGSHARE) / 100) - convertNeutrinoToWaves(getLockedBalance(neutrinoAssetIdString), currentPrice))
390+ let amount = (totalFreeReserve / LEASINTXCOUNT)
391+ let txBytes = (((((base58'3h1H' + fromBase58String(senderPublicKey)) + fromBase58String(nodeAddress)) + toBytes(amount)) + toBytes(fee)) + toBytes(timestamp))
392+ let txHashBytes = blake2b256(txBytes)
393+ let txHash = toBase58String(txHashBytes)
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))
406+ then true
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))])
424+ }
425+
426+
427+
428+@Callable(i)
429+func cancelStuckLeaseTx (txHash) = if (if (if ((getLeaseTxStatus(txHash) == NEW))
430+ then !(isDefined(transactionHeightById(fromBase58String(txHash))))
431+ else false)
432+ then (height > getLeaseTxExpireSendBlock(txHash))
433+ else false)
434+ then {
435+ let amount = getLeaseTxAmountByHash(txHash)
436+ WriteSet([DataEntry(LeasingTxCountKey, (leasingTxCount - 1)), DataEntry(LeasingAmountKey, (leasingAmount - amount)), DataEntry(getLeaseTxStatusKey(txHash), CANCELED), DataEntry(IsRebalanceKey, if (((reserveWithoutLeasing - amount) >= convertNeutrinoToWaves(getLockedBalance(neutrinoAssetIdString), currentPrice)))
437+ then false
438+ else true)])
439+ }
440+ else throw("invalid tx hash")
441+
442+
443+
444+@Callable(i)
445+func registrationUnleaseTx (chainIdString,senderPublicKey,fee,timestamp,leaseTxHash) = {
446+ let txBytes = (((((base58'gm' + toBytes(chainIdString)) + fromBase58String(senderPublicKey)) + toBytes(fee)) + toBytes(timestamp)) + fromBase58String(leaseTxHash))
447+ let txHash = blake2b256(txBytes)
448+ if ((getLeaseTxStatus(leaseTxHash) != NEW))
449+ then throw("invalid tx status")
450+ else if ((this != addressFromPublicKey(fromBase58String(senderPublicKey))))
451+ then throw("invalid pubKey")
452+ else if (!(isDefined(transactionHeightById(txHash))))
453+ then throw("blockchain does not contain this transaction")
454+ else {
455+ let amount = getLeaseTxAmountByHash(leaseTxHash)
456+ WriteSet([DataEntry(LeasingTxCountKey, (leasingTxCount - 1)), DataEntry(LeasingAmountKey, (leasingAmount - amount)), DataEntry(getLeaseTxStatusKey(leaseTxHash), CANCELED), DataEntry(IsRebalanceKey, if (((reserveWithoutLeasing - amount) >= convertNeutrinoToWaves(getLockedBalance(neutrinoAssetIdString), currentPrice)))
457+ then false
458+ else true)])
459+ }
595460 }
596461
597462
598463 @Verifier(tx)
599-func verify () = match tx {
600- case leaseTx: LeaseTransaction =>
601- sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(getOwnerPubKeyByLeaseTxId(toBase58String(leaseTx.id))))
602- case unleaseTx: LeaseCancelTransaction =>
603- sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(getOwnerPubKeyByLeaseTxId(toBase58String(unleaseTx.leaseId))))
604- case _ =>
605- sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
606-}
464+func verify () = {
465+ let id = toBase58String(tx.id)
466+ match tx {
467+ case leaseTx: LeaseTransaction =>
468+ if (if ((leasingExpireBlock >= height))
469+ then (getLeaseTxExpireSendBlock(id) >= height)
470+ else false)
471+ then (getLeaseTxStatus(id) == NEW)
472+ else false
473+ case unleaseTx: LeaseCancelTransaction =>
474+ let leaseId = toBase58String(unleaseTx.leaseId)
475+ if (if (if ((height > leasingExpireBlock))
476+ then true
477+ else isRebalance)
478+ then (unleaseTx.fee == getCancelLeaseTxReserveFee(leaseId))
479+ else false)
480+ then (getLeaseTxStatus(leaseId) == NEW)
481+ else false
482+ case _ =>
483+ sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
484+ }
485+ }
607486

github/deemru/w8io/026f985 
230.26 ms