tx · DnW8skvSzGLGUhA92pVxtTssjk2SpbytVgqNcvWu5Jzw

3PC9BfRwJWWiw9AREE2B3eWzCks3CYtg4yo:  -0.01400000 Waves

2019.10.07 19:16 [1739807] smart account 3PC9BfRwJWWiw9AREE2B3eWzCks3CYtg4yo > SELF 0.00000000 Waves

{ "type": 13, "id": "DnW8skvSzGLGUhA92pVxtTssjk2SpbytVgqNcvWu5Jzw", "fee": 1400000, "feeAssetId": null, "timestamp": 1570465115411, "version": 1, "sender": "3PC9BfRwJWWiw9AREE2B3eWzCks3CYtg4yo", "senderPublicKey": "BRnVwSVctnV8pge5vRpsJdWnkjWEJspFb6QvrmZvu3Ht", "proofs": [ "4u28f3CsceMy5cJz24AfMQtPcMyNVFWxn2F1W57PhpTDjdfzLFQMccaeMGG3moJ4LswTkZM19nN9RivwdTNye5tA" ], "script": "base64:AAIDAAAAAAAAAAAAAABlAQAAAA5nZXROdW1iZXJCeUtleQAAAAEAAAADa2V5BAAAAAckbWF0Y2gwCQAEGgAAAAIFAAAABHRoaXMFAAAAA2tleQMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAADSW50BAAAAAFhBQAAAAckbWF0Y2gwBQAAAAFhAAAAAAAAAAAAAQAAAA5nZXRTdHJpbmdCeUtleQAAAAEAAAADa2V5BAAAAAckbWF0Y2gwCQAEHQAAAAIFAAAABHRoaXMFAAAAA2tleQMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAGU3RyaW5nBAAAAAFhBQAAAAckbWF0Y2gwBQAAAAFhAgAAAAABAAAADGdldEJvb2xCeUtleQAAAAEAAAADa2V5BAAAAAckbWF0Y2gwCQAEGwAAAAIFAAAABHRoaXMFAAAAA2tleQMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAHQm9vbGVhbgQAAAABYQUAAAAHJG1hdGNoMAUAAAABYQcBAAAAGGdldE51bWJlckJ5QWRkcmVzc0FuZEtleQAAAAIAAAAHYWRkcmVzcwAAAANrZXkEAAAAByRtYXRjaDAJAAQaAAAAAgkBAAAAHEBleHRyVXNlcihhZGRyZXNzRnJvbVN0cmluZykAAAABBQAAAAdhZGRyZXNzBQAAAANrZXkDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAA0ludAQAAAABYQUAAAAHJG1hdGNoMAUAAAABYQAAAAAAAAAAAAAAAAAPTElTVFNQTElUU1lNQk9MAgAAAAFfAAAAAA5MSVNUREFUQVNZTUJPTAIAAAABKwAAAAAHV0FWRUxFVAAAAAAABfXhAAAAAAANQ0VOVFNJTkRPTExBUgAAAAAAAAAAZAAAAAAIQ0FOQ0VMRUQCAAAACGNhbmNlbGVkAAAAAANORVcCAAAAA25ldwAAAAAGRklMTEVEAgAAAAZmaWxsZWQAAAAAEk5ldXRyaW5vQXNzZXRJZEtleQIAAAARbmV1dHJpbm9fYXNzZXRfaWQAAAAADkJvbmRBc3NldElkS2V5AgAAAA1ib25kX2Fzc2V0X2lkAAAAABJBdWN0aW9uQ29udHJhY3RLZXkCAAAAEGF1Y3Rpb25fY29udHJhY3QAAAAAFkJhbGFuY2VMb2NrSW50ZXJ2YWxLZXkCAAAAFWJhbGFuY2VfbG9ja19pbnRlcnZhbAAAAAAPVm90ZUludGVydmFsS2V5AgAAAA12b3RlX2ludGVydmFsAAAAABVNaW5XYXZlc1N3YXBBbW91bnRLZXkCAAAAFW1pbl93YXZlc19zd2FwX2Ftb3VudAAAAAAYTWluTmV1dHJpbm9Td2FwQW1vdW50S2V5AgAAABhtaW5fbmV1dHJpbm9fc3dhcF9hbW91bnQAAAAADlByaWNlT2Zmc2V0S2V5AgAAAAxwcmljZV9vZmZzZXQAAAAAFFByb3ZpZGluZ0ludGVydmFsS2V5AgAAABJwcm92aWRpbmdfaW50ZXJ2YWwAAAAACFByaWNlS2V5AgAAAAVwcmljZQAAAAASTmV1dHJpbm9CYWxhbmNlS2V5AgAAAAluZXV0cmlub18AAAAAD1dhdmVzQmFsYW5jZUtleQIAAAAGd2F2ZXNfAAAAABVCYWxhbmNlVW5sb2NrQmxvY2tLZXkCAAAADmJhbGFuY2VfYmxvY2tfAAAAAAxPcmRlcmJvb2tLZXkCAAAACW9yZGVyYm9vawAAAAANT3JkZXJUb3RhbEtleQIAAAAMb3JkZXJfdG90YWxfAAAAAA1PcmRlck93bmVyS2V5AgAAAAxvcmRlcl9vd25lcl8AAAAADk9yZGVySGVpZ2h0S2V5AgAAAA1vcmRlcl9oZWlnaHRfAAAAABNPcmRlckZpbGxlZFRvdGFsS2V5AgAAABNvcmRlcl9maWxsZWRfdG90YWxfAAAAAA5PcmRlclN0YXR1c0tleQIAAAANb3JkZXJfc3RhdHVzXwAAAAAMSXNCbG9ja2VkS2V5AgAAAAppc19ibG9ja2VkAAAAABJCbGFja1N3YXJtUHJpY2VLZXkCAAAAEWJsYWNrX3N3YXJtX3ByaWNlAAAAAAxBZG1pblZvdGVLZXkCAAAAC2FkbWluX3ZvdGVfAAAAABFBZG1pblZvdGVQcmljZUtleQIAAAARYWRtaW5fdm90ZV9wcmljZV8AAAAAEkJsb2NrRXhwaXJlVm90ZUtleQIAAAARdm90ZV9leHBpcmVfYmxvY2sAAAAACEFkbWluS2V5AgAAAAZhZG1pbl8AAAAAEUlzUHJpY2VQZW5kaW5nS2V5AgAAABBpc19wZW5kaW5nX3ByaWNlAAAAAAlPcmFjbGVLZXkCAAAAB29yYWNsZV8AAAAAEk9yYWNsZUlzUHJvdmlkZUtleQIAAAASb3JhY2xlX2lzX3Byb3ZpZGVfAAAAABVPcmFjbGVQcm92aWRlUHJpY2VLZXkCAAAAFW9yYWNsZV9wcmljZV9wcm92aWRlXwAAAAAXQmxvY2tFeHBpcmVQcm92aWRpbmdLZXkCAAAAFnByb3ZpZGluZ19leHBpcmVfYmxvY2sBAAAAC2dldEFkbWluS2V5AAAAAQAAAAVjb3VudAkAASwAAAACBQAAAAhBZG1pbktleQkAAaQAAAABBQAAAAVjb3VudAEAAAAPZ2V0QWRtaW5Wb3RlS2V5AAAAAQAAAAVvd25lcgkAASwAAAACBQAAAAxBZG1pblZvdGVLZXkFAAAABW93bmVyAQAAABRnZXRBZG1pblZvdGVQcmljZUtleQAAAAEAAAAFb3duZXIJAAEsAAAAAgUAAAARQWRtaW5Wb3RlUHJpY2VLZXkFAAAABW93bmVyAQAAAAxnZXRPcmFjbGVLZXkAAAABAAAABWNvdW50CQABLAAAAAIFAAAACU9yYWNsZUtleQkAAaQAAAABBQAAAAVjb3VudAEAAAAVZ2V0T3JhY2xlSXNQcm92aWRlS2V5AAAAAQAAAAVvd25lcgkAASwAAAACBQAAABJPcmFjbGVJc1Byb3ZpZGVLZXkFAAAABW93bmVyAQAAABhnZXRPcmFjbGVQcm92aWRlUHJpY2VLZXkAAAABAAAABW93bmVyCQABLAAAAAIFAAAAFU9yYWNsZVByb3ZpZGVQcmljZUtleQUAAAAFb3duZXIBAAAAFWdldE5ldXRyaW5vQmFsYW5jZUtleQAAAAEAAAAFb3duZXIJAAEsAAAAAgUAAAASTmV1dHJpbm9CYWxhbmNlS2V5BQAAAAVvd25lcgEAAAASZ2V0V2F2ZXNCYWxhbmNlS2V5AAAAAQAAAAVvd25lcgkAASwAAAACBQAAAA9XYXZlc0JhbGFuY2VLZXkFAAAABW93bmVyAQAAABhnZXRCYWxhbmNlVW5sb2NrQmxvY2tLZXkAAAABAAAABW93bmVyCQABLAAAAAIFAAAAFUJhbGFuY2VVbmxvY2tCbG9ja0tleQUAAAAFb3duZXIBAAAAFWdldEJsYWNrU3dhcm1QcmljZUtleQAAAAEAAAAFYmxvY2sJAAEsAAAAAgkAASwAAAACBQAAABJCbGFja1N3YXJtUHJpY2VLZXkCAAAAAV8JAAGkAAAAAQUAAAAFYmxvY2sBAAAAEmdldFByaWNlSGlzdG9yeUtleQAAAAEAAAAFYmxvY2sJAAEsAAAAAgkAASwAAAACBQAAAAhQcmljZUtleQIAAAABXwkAAaQAAAABBQAAAAVibG9jawEAAAAQZ2V0T3JkZXJUb3RhbEtleQAAAAEAAAAHb3JkZXJJZAkAASwAAAACBQAAAA1PcmRlclRvdGFsS2V5BQAAAAdvcmRlcklkAQAAABBnZXRPcmRlck93bmVyS2V5AAAAAQAAAAdvcmRlcklkCQABLAAAAAIFAAAADU9yZGVyT3duZXJLZXkFAAAAB29yZGVySWQBAAAAEWdldE9yZGVySGVpZ2h0S2V5AAAAAQAAAAdvcmRlcklkCQABLAAAAAIFAAAADk9yZGVySGVpZ2h0S2V5BQAAAAdvcmRlcklkAQAAABFnZXRPcmRlclN0YXR1c0tleQAAAAEAAAAHb3JkZXJJZAkAASwAAAACBQAAAA5PcmRlclN0YXR1c0tleQUAAAAHb3JkZXJJZAEAAAAWZ2V0T3JkZXJGaWxsZWRUb3RhbEtleQAAAAEAAAAHb3JkZXJJZAkAASwAAAACBQAAABNPcmRlckZpbGxlZFRvdGFsS2V5BQAAAAdvcmRlcklkAAAAAAVwcmljZQkBAAAADmdldE51bWJlckJ5S2V5AAAAAQUAAAAIUHJpY2VLZXkBAAAAFmNvbnZlcnROZXV0cmlub1RvV2F2ZXMAAAABAAAABmFtb3VudAkAAGkAAAACCQAAaAAAAAIJAABpAAAAAgkAAGgAAAACBQAAAAZhbW91bnQAAAAAAAAAAGQFAAAABXByaWNlBQAAAAdXQVZFTEVUBQAAAA1DRU5UU0lORE9MTEFSAQAAABZjb252ZXJ0V2F2ZXNUb05ldXRyaW5vAAAAAQAAAAZhbW91bnQJAABpAAAAAgkAAGgAAAACCQAAaQAAAAIJAABoAAAAAgUAAAAGYW1vdW50BQAAAAVwcmljZQAAAAAAAAAAZAUAAAANQ0VOVFNJTkRPTExBUgUAAAAHV0FWRUxFVAEAAAAVY29udmVydE5ldXRyaW5vVG9Cb25kAAAAAQAAAAZhbW91bnQJAABpAAAAAgUAAAAGYW1vdW50BQAAAA1DRU5UU0lORE9MTEFSAQAAABVjb252ZXJ0Qm9uZFRvTmV1dHJpbm8AAAABAAAABmFtb3VudAkAAGgAAAACBQAAAAZhbW91bnQFAAAADUNFTlRTSU5ET0xMQVIBAAAAEmNvbnZlcnRXYXZlc1RvQm9uZAAAAAEAAAAGYW1vdW50CQEAAAAVY29udmVydE5ldXRyaW5vVG9Cb25kAAAAAQkBAAAAFmNvbnZlcnRXYXZlc1RvTmV1dHJpbm8AAAABBQAAAAZhbW91bnQAAAAAEXByb3ZpZGluZ0ludGVydmFsCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABBQAAABRQcm92aWRpbmdJbnRlcnZhbEtleQAAAAAUYmxvY2tFeHBpcmVQcm92aWRpbmcJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEFAAAAF0Jsb2NrRXhwaXJlUHJvdmlkaW5nS2V5AAAAAA5pc1ByaWNlUGVuZGluZwkBAAAADGdldEJvb2xCeUtleQAAAAEFAAAAEUlzUHJpY2VQZW5kaW5nS2V5AAAAABJwZXJjZW50UHJpY2VPZmZzZXQJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEFAAAADlByaWNlT2Zmc2V0S2V5AAAAAAx2b3RlSW50ZXJ2YWwJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEFAAAAD1ZvdGVJbnRlcnZhbEtleQAAAAAPYmxvY2tFeHBpcmVWb3RlCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABBQAAABJCbG9ja0V4cGlyZVZvdGVLZXkAAAAAE2JhbGFuY2VMb2NrSW50ZXJ2YWwJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEFAAAAFkJhbGFuY2VMb2NrSW50ZXJ2YWxLZXkAAAAACWlzQmxvY2tlZAkBAAAADGdldEJvb2xCeUtleQAAAAEFAAAADElzQmxvY2tlZEtleQAAAAASbWluV2F2ZXNTd2FwQW1vdW50CQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABBQAAABVNaW5XYXZlc1N3YXBBbW91bnRLZXkAAAAAFW1pbk5ldXRyaW5vU3dhcEFtb3VudAkBAAAADmdldE51bWJlckJ5S2V5AAAAAQUAAAAYTWluTmV1dHJpbm9Td2FwQW1vdW50S2V5AAAAAA9uZXV0cmlub0Fzc2V0SWQJAAJZAAAAAQkBAAAADmdldFN0cmluZ0J5S2V5AAAAAQUAAAASTmV1dHJpbm9Bc3NldElkS2V5AAAAAA9hdWN0aW9uQ29udHJhY3QJAQAAAA5nZXRTdHJpbmdCeUtleQAAAAEFAAAAEkF1Y3Rpb25Db250cmFjdEtleQAAAAAHcmVzZXJ2ZQkBAAAADHdhdmVzQmFsYW5jZQAAAAEFAAAABHRoaXMAAAAACW9yZGVyYm9vawkBAAAADmdldFN0cmluZ0J5S2V5AAAAAQUAAAAMT3JkZXJib29rS2V5AAAAAAtib25kQXNzZXRJZAkAAlkAAAABCQEAAAAOZ2V0U3RyaW5nQnlLZXkAAAABBQAAAA5Cb25kQXNzZXRJZEtleQAAAAAKYm9uZFN1cHBseQQAAAAEaW5mbwkBAAAAB2V4dHJhY3QAAAABCQAD7AAAAAEFAAAAC2JvbmRBc3NldElkCQAAZQAAAAIIBQAAAARpbmZvAAAACHF1YW50aXR5CQAD6wAAAAIFAAAABHRoaXMFAAAAC2JvbmRBc3NldElkAAAAAA5uZXV0cmlub1N1cHBseQQAAAAEaW5mbwkBAAAAB2V4dHJhY3QAAAABCQAD7AAAAAEFAAAAD25ldXRyaW5vQXNzZXRJZAkAAGUAAAACCAUAAAAEaW5mbwAAAAhxdWFudGl0eQkAA+sAAAACBQAAAAR0aGlzBQAAAA9uZXV0cmlub0Fzc2V0SWQAAAAAB3N1cnBsdXMJAABlAAAAAgkBAAAAFmNvbnZlcnRXYXZlc1RvTmV1dHJpbm8AAAABBQAAAAdyZXNlcnZlBQAAAA5uZXV0cmlub1N1cHBseQAAAAAJb3JhY2xlT25lCQEAAAAOZ2V0U3RyaW5nQnlLZXkAAAABCQEAAAAMZ2V0T3JhY2xlS2V5AAAAAQAAAAAAAAAAAAAAAAAJb3JhY2xlVHdvCQEAAAAOZ2V0U3RyaW5nQnlLZXkAAAABCQEAAAAMZ2V0T3JhY2xlS2V5AAAAAQAAAAAAAAAAAQAAAAALb3JhY2xlVGhyZWUJAQAAAA5nZXRTdHJpbmdCeUtleQAAAAEJAQAAAAxnZXRPcmFjbGVLZXkAAAABAAAAAAAAAAACAAAAAAhhZG1pbk9uZQkBAAAADmdldFN0cmluZ0J5S2V5AAAAAQkBAAAAC2dldEFkbWluS2V5AAAAAQAAAAAAAAAAAAAAAAAIYWRtaW5Ud28JAQAAAA5nZXRTdHJpbmdCeUtleQAAAAEJAQAAAAtnZXRBZG1pbktleQAAAAEAAAAAAAAAAAEAAAAACmFkbWluVGhyZWUJAQAAAA5nZXRTdHJpbmdCeUtleQAAAAEJAQAAAAtnZXRBZG1pbktleQAAAAEAAAAAAAAAAAIBAAAAD2dldEFkbWluVm90ZUludAAAAAEAAAAFb3duZXIDCQEAAAAMZ2V0Qm9vbEJ5S2V5AAAAAQkBAAAAD2dldEFkbWluVm90ZUtleQAAAAEFAAAABW93bmVyAAAAAAAAAAABAAAAAAAAAAAAAQAAABFnZXRBZG1pblZvdGVQcmljZQAAAAEAAAAFb3duZXIJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEJAQAAABRnZXRBZG1pblZvdGVQcmljZUtleQAAAAEFAAAABW93bmVyAQAAAA9pc09yYWNsZVByb3ZpZGUAAAABAAAABW93bmVyCQEAAAAMZ2V0Qm9vbEJ5S2V5AAAAAQkBAAAAFWdldE9yYWNsZUlzUHJvdmlkZUtleQAAAAEFAAAABW93bmVyAQAAABJpc09yYWNsZVByb3ZpZGVJbnQAAAABAAAABW93bmVyAwkBAAAAD2lzT3JhY2xlUHJvdmlkZQAAAAEFAAAABW93bmVyAAAAAAAAAAABAAAAAAAAAAAAAQAAABVnZXRPcmFjbGVQcm92aWRlUHJpY2UAAAABAAAABW93bmVyCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAYZ2V0T3JhY2xlUHJvdmlkZVByaWNlS2V5AAAAAQUAAAAFb3duZXIBAAAAD2dldFdhdmVzQmFsYW5jZQAAAAEAAAAFb3duZXIJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEJAQAAABJnZXRXYXZlc0JhbGFuY2VLZXkAAAABBQAAAAVvd25lcgEAAAASZ2V0TmV1dHJpbm9CYWxhbmNlAAAAAQAAAAVvd25lcgkBAAAADmdldE51bWJlckJ5S2V5AAAAAQkBAAAAFWdldE5ldXRyaW5vQmFsYW5jZUtleQAAAAEFAAAABW93bmVyAQAAABVnZXRVbmxvY2tCYWxhbmNlQmxvY2sAAAABAAAABW93bmVyCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAYZ2V0QmFsYW5jZVVubG9ja0Jsb2NrS2V5AAAAAQUAAAAFb3duZXIBAAAADWdldE9yZGVyVG90YWwAAAABAAAAAmlkCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAQZ2V0T3JkZXJUb3RhbEtleQAAAAEFAAAAAmlkAQAAAA1nZXRPcmRlck93bmVyAAAAAQAAAAJpZAkBAAAADmdldFN0cmluZ0J5S2V5AAAAAQkBAAAAEGdldE9yZGVyT3duZXJLZXkAAAABBQAAAAJpZAEAAAATZ2V0T3JkZXJGaWxsZWRUb3RhbAAAAAEAAAACaWQJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEJAQAAABZnZXRPcmRlckZpbGxlZFRvdGFsS2V5AAAAAQUAAAACaWQBAAAAE2dldE9yZGVyRWxlbWVudEJ5SWQAAAABAAAAAmlkCQABLAAAAAIFAAAAAmlkBQAAAA9MSVNUU1BMSVRTWU1CT0wBAAAACGFkZE9yZGVyAAAAAQAAAAdvcmRlcklkCQABLAAAAAIFAAAACW9yZGVyYm9vawkBAAAAE2dldE9yZGVyRWxlbWVudEJ5SWQAAAABBQAAAAdvcmRlcklkAQAAAAlkcm9wT3JkZXIAAAABAAAAB29yZGVySWQEAAAABXBhcnRzCQAEtQAAAAIFAAAACW9yZGVyYm9vawkBAAAAE2dldE9yZGVyRWxlbWVudEJ5SWQAAAABBQAAAAdvcmRlcklkCQABLAAAAAIJAAGRAAAAAgUAAAAFcGFydHMAAAAAAAAAAAAJAAGRAAAAAgUAAAAFcGFydHMAAAAAAAAAAAEAAAAMAAAAAWkBAAAAD3NldEN1cnJlbnRQcmljZQAAAAEAAAAIbmV3UHJpY2UEAAAAB2FjY291bnQJAAQlAAAAAQgFAAAAAWkAAAAGY2FsbGVyBAAAABNwcmljZVByb3ZpZGluZ0NvdW50CQAAZAAAAAIJAABkAAAAAgkAAGQAAAACCQEAAAASaXNPcmFjbGVQcm92aWRlSW50AAAAAQUAAAAJb3JhY2xlT25lCQEAAAASaXNPcmFjbGVQcm92aWRlSW50AAAAAQUAAAAJb3JhY2xlVHdvCQEAAAASaXNPcmFjbGVQcm92aWRlSW50AAAAAQUAAAALb3JhY2xlVGhyZWUAAAAAAAAAAAEDBQAAAAlpc0Jsb2NrZWQJAAACAAAAAQIAAAATY29udHJhY3QgaXMgYmxvY2tlZAMDAwkBAAAAAiE9AAAAAgUAAAAHYWNjb3VudAUAAAAJb3JhY2xlT25lCQEAAAACIT0AAAACBQAAAAdhY2NvdW50BQAAAAlvcmFjbGVUd28HCQEAAAACIT0AAAACBQAAAAdhY2NvdW50BQAAAAtvcmFjbGVUaHJlZQcJAAACAAAAAQIAAAARcGVybWlzc2lvbiBkZW5pZWQDAwkAAGcAAAACBQAAABRibG9ja0V4cGlyZVByb3ZpZGluZwUAAAAGaGVpZ2h0CQEAAAAPaXNPcmFjbGVQcm92aWRlAAAAAQUAAAAHYWNjb3VudAcJAAACAAAAAQIAAAAZcHJpY2UgaXMgYWxyZWFkeSBwcm92aWRlZAMDCQAAZgAAAAIFAAAABmhlaWdodAUAAAAUYmxvY2tFeHBpcmVQcm92aWRpbmcFAAAADmlzUHJpY2VQZW5kaW5nBwkAAAIAAAABAgAAABh1c2UgZmluaWxpemVDdXJyZW50UHJpY2UJAQAAAAhXcml0ZVNldAAAAAEJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIJAQAAABhnZXRPcmFjbGVQcm92aWRlUHJpY2VLZXkAAAABBQAAAAdhY2NvdW50BQAAAAhuZXdQcmljZQkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgUAAAAXQmxvY2tFeHBpcmVQcm92aWRpbmdLZXkDCQAAZgAAAAIFAAAABmhlaWdodAUAAAAUYmxvY2tFeHBpcmVQcm92aWRpbmcJAABkAAAAAgUAAAAGaGVpZ2h0BQAAABFwcm92aWRpbmdJbnRlcnZhbAUAAAAUYmxvY2tFeHBpcmVQcm92aWRpbmcJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIJAQAAABVnZXRPcmFjbGVJc1Byb3ZpZGVLZXkAAAABBQAAAAlvcmFjbGVPbmUDCQAAZgAAAAIFAAAABmhlaWdodAUAAAAUYmxvY2tFeHBpcmVQcm92aWRpbmcHCQEAAAAPaXNPcmFjbGVQcm92aWRlAAAAAQUAAAAJb3JhY2xlT25lCQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACCQEAAAAVZ2V0T3JhY2xlSXNQcm92aWRlS2V5AAAAAQUAAAAJb3JhY2xlVHdvAwkAAGYAAAACBQAAAAZoZWlnaHQFAAAAFGJsb2NrRXhwaXJlUHJvdmlkaW5nBwkBAAAAD2lzT3JhY2xlUHJvdmlkZQAAAAEFAAAACW9yYWNsZVR3bwkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgkBAAAAFWdldE9yYWNsZUlzUHJvdmlkZUtleQAAAAEFAAAAC29yYWNsZVRocmVlAwkAAGYAAAACBQAAAAZoZWlnaHQFAAAAFGJsb2NrRXhwaXJlUHJvdmlkaW5nBwkBAAAAD2lzT3JhY2xlUHJvdmlkZQAAAAEFAAAAC29yYWNsZVRocmVlCQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACCQEAAAAVZ2V0T3JhY2xlSXNQcm92aWRlS2V5AAAAAQUAAAAHYWNjb3VudAYJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIFAAAAEUlzUHJpY2VQZW5kaW5nS2V5AwMJAABnAAAAAgUAAAAUYmxvY2tFeHBpcmVQcm92aWRpbmcFAAAABmhlaWdodAkAAGcAAAACBQAAABNwcmljZVByb3ZpZGluZ0NvdW50AAAAAAAAAAACBwYFAAAADmlzUHJpY2VQZW5kaW5nBQAAAANuaWwAAAABaQEAAAAUZmluaWxpemVDdXJyZW50UHJpY2UAAAAABAAAAAdhY2NvdW50CQAEJQAAAAEIBQAAAAFpAAAABmNhbGxlcgQAAAATcHJpY2VQcm92aWRpbmdDb3VudAkAAGQAAAACCQAAZAAAAAIJAQAAABJpc09yYWNsZVByb3ZpZGVJbnQAAAABBQAAAAlvcmFjbGVPbmUJAQAAABJpc09yYWNsZVByb3ZpZGVJbnQAAAABBQAAAAlvcmFjbGVUd28JAQAAABJpc09yYWNsZVByb3ZpZGVJbnQAAAABBQAAAAtvcmFjbGVUaHJlZQQAAAAIbmV3UHJpY2UJAABpAAAAAgkAAGQAAAACCQAAZAAAAAIJAABoAAAAAgkBAAAAFWdldE9yYWNsZVByb3ZpZGVQcmljZQAAAAEFAAAACW9yYWNsZU9uZQkBAAAAEmlzT3JhY2xlUHJvdmlkZUludAAAAAEFAAAACW9yYWNsZU9u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YUVudHJ5AAAAAgkBAAAAFWdldE5ldXRyaW5vQmFsYW5jZUtleQAAAAEFAAAAB2FjY291bnQAAAAAAAAAAAAFAAAAA25pbAkBAAAAC1RyYW5zZmVyU2V0AAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAcQGV4dHJVc2VyKGFkZHJlc3NGcm9tU3RyaW5nKQAAAAEFAAAAB2FjY291bnQJAQAAABJnZXROZXV0cmlub0JhbGFuY2UAAAABBQAAAAdhY2NvdW50BQAAAA9uZXV0cmlub0Fzc2V0SWQJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwkBAAAAHEBleHRyVXNlcihhZGRyZXNzRnJvbVN0cmluZykAAAABBQAAAAdhY2NvdW50CQEAAAAPZ2V0V2F2ZXNCYWxhbmNlAAAAAQUAAAAHYWNjb3VudAUAAAAEdW5pdAUAAAADbmlsAAAAAWkBAAAADGdlbmVyYXRlQm9uZAAAAAAEAAAAB2RlZmljaXQJAABlAAAAAgUAAAAObmV1dHJpbm9TdXBwbHkJAQAAABZjb252ZXJ0V2F2ZXNUb05ldXRyaW5vAAAAAQUAAAAHcmVzZXJ2ZQQAAAAOYmFsYW5jZUF1Y3Rpb24JAAPrAAAAAgkBAAAAHEBleHRyVXNlcihhZGRyZXNzRnJvbVN0cmluZykAAAABBQAAAA9hdWN0aW9uQ29udHJhY3QFAAAAC2JvbmRBc3NldElkBAAAAAZhbW91bnQJAABlAAAAAgkBAAAAFWNvbnZlcnROZXV0cmlub1RvQm9uZAAAAAEFAAAAB2RlZmljaXQFAAAADmJhbGFuY2VBdWN0aW9uAwUAAAAJaXNCbG9ja2VkCQAAAgAAAAECAAAAE2NvbnRyYWN0IGlzIGJsb2NrZWQDCQAAZgAAAAIFAAAABmFtb3VudAAAAAAAAAAAAAkBAAAAC1RyYW5zZmVyU2V0AAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAcQGV4dHJVc2VyKGFkZHJlc3NGcm9tU3RyaW5nKQAAAAEFAAAAD2F1Y3Rpb25Db250cmFjdAUAAAAGYW1vdW50BQAAAAtib25kQXNzZXRJZAUAAAADbmlsCQAAAgAAAAECAAAAJWJvbmQg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AAtzdXJwbHVzQm9uZAkBAAAAFWNvbnZlcnROZXV0cmlub1RvQm9uZAAAAAEFAAAAB3N1cnBsdXMEAAAABnN0YXR1cwMJAABnAAAAAgUAAAALc3VycGx1c0JvbmQFAAAABmFtb3VudAUAAAAGRklMTEVEBQAAAANORVcEAAAADm5ld0ZpbGxlZFRvdGFsAwkAAGcAAAACBQAAAAtzdXJwbHVzQm9uZAUAAAAGYW1vdW50BQAAAApvcmRlclRvdGFsBQAAAAtzdXJwbHVzQm9uZAkBAAAADFNjcmlwdFJlc3VsdAAAAAIJAQAAAAhXcml0ZVNldAAAAAEJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIFAAAADE9yZGVyYm9va0tleQkBAAAACWRyb3BPcmRlcgAAAAEFAAAAB29yZGVySWQJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIJAQAAABZnZXRPcmRlckZpbGxlZFRvdGFsS2V5AAAAAQUAAAAHb3JkZXJJZAkAAGQAAAACBQAAAAtmaWxsZWRUb3RhbAUAAAAObmV3RmlsbGVkVG90YWwJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIJAQAAABFnZXRPcmRlclN0YXR1c0tleQAAAAEFAAAAB29yZGVySWQFAAAABnN0YXR1cwUAAAADbmlsCQEAAAALVHJhbnNmZXJTZXQAAAABCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAABxAZXh0clVzZXIoYWRkcmVzc0Zyb21TdHJpbmcpAAAAAQUAAAAKb3JkZXJPd25lcgkBAAAAFWNvbnZlcnRCb25kVG9OZXV0cmlubwAAAAEFAAAADm5ld0ZpbGxlZFRvdGFsBQAAAA9uZXV0cmlub0Fzc2V0SWQFAAAAA25pbAAAAAFpAQAAAAh0cmFuc2ZlcgAAAAEAAAAHYWNjb3VudAQAAAADcG10CQEAAAAHZXh0cmFjdAAAAAEIBQAAAAFpAAAAB3BheW1lbnQDCQEAAAAJaXNEZWZpbmVkAAAAAQgFAAAAA3BtdAAAAAdhc3NldElkCQAAAgAAAAECAAAAIGNhbiB1c2Ugd2F2ZXMgb25seSBhdCB0aGUgbW9tZW50CQEAAAALVHJhbnNmZXJTZXQAAAABCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAABxAZXh0clVzZXIoYWRkcmVzc0Zyb21TdHJpbmcpAAAAAQUAAAAHYWNjb3VudAgFAAAAA3BtdAAAAAZhbW91bnQFAAAABHVuaXQFAAAAA25pbAAAAAD+nyCI", "chainId": 87, "height": 1739807, "spentComplexity": 0 } View: original | compacted Prev: F9LmrEz8o4hdQZJFMFNwkiwVxUv4A3oPivQC8ESZyiLA Next: 7ZQ3Pp3CnW673uQuaD4wedk6TzZpGeDjNLU4HcCmAm4N Diff:
OldNewDifferences
2525 }
2626
2727
28-func getNumberByKeyAndAddress (address,key) = match getInteger(addressFromStringValue(address), key) {
28+func getNumberByAddressAndKey (address,key) = match getInteger(addressFromStringValue(address), key) {
2929 case a: Int =>
3030 a
3131 case _ =>
3333 }
3434
3535
36-func getStringByKeyAndAddress (address,key) = match getString(addressFromStringValue(address), key) {
37- case a: String =>
38- a
39- case _ =>
40- ""
41-}
36+let LISTSPLITSYMBOL = "_"
4237
38+let LISTDATASYMBOL = "+"
4339
44-func getBoolByKeyAndAddress (address,key) = match getBoolean(addressFromStringValue(address), key) {
45- case a: Boolean =>
46- a
47- case _ =>
48- false
49-}
40+let WAVELET = 100000000
5041
42+let CENTSINDOLLAR = 100
5143
52-let ListSplitSymbol = "_"
44+let CANCELED = "canceled"
5345
54-let BalanceLockBlock = 10
46+let NEW = "new"
5547
56-let ListDataSplitSymbol = "+"
57-
58-let Wavelet = 100000000
59-
60-let MinimalBondOrder = (10 * Wavelet)
61-
62-let MinimalSurplus = (10 * Wavelet)
63-
64-let ApplyBlockTimeout = 10
48+let FILLED = "filled"
6549
6650 let NeutrinoAssetIdKey = "neutrino_asset_id"
6751
6953
7054 let AuctionContractKey = "auction_contract"
7155
56+let BalanceLockIntervalKey = "balance_lock_interval"
57+
58+let VoteIntervalKey = "vote_interval"
59+
60+let MinWavesSwapAmountKey = "min_waves_swap_amount"
61+
62+let MinNeutrinoSwapAmountKey = "min_neutrino_swap_amount"
63+
64+let PriceOffsetKey = "price_offset"
65+
66+let ProvidingIntervalKey = "providing_interval"
67+
7268 let PriceKey = "price"
7369
7470 let NeutrinoBalanceKey = "neutrino_"
7571
7672 let WavesBalanceKey = "waves_"
7773
78-let BalanceBlockKey = "balance_block_"
74+let BalanceUnlockBlockKey = "balance_block_"
7975
8076 let OrderbookKey = "orderbook"
8177
8985
9086 let OrderStatusKey = "order_status_"
9187
92-let OracleKey = "oracle"
88+let IsBlockedKey = "is_blocked"
89+
90+let BlackSwarmPriceKey = "black_swarm_price"
91+
92+let AdminVoteKey = "admin_vote_"
93+
94+let AdminVotePriceKey = "admin_vote_price_"
95+
96+let BlockExpireVoteKey = "vote_expire_block"
97+
98+let AdminKey = "admin_"
99+
100+let IsPricePendingKey = "is_pending_price"
101+
102+let OracleKey = "oracle_"
103+
104+let OracleIsProvideKey = "oracle_is_provide_"
105+
106+let OracleProvidePriceKey = "oracle_price_provide_"
107+
108+let BlockExpireProvidingKey = "providing_expire_block"
109+
110+func getAdminKey (count) = (AdminKey + toString(count))
111+
112+
113+func getAdminVoteKey (owner) = (AdminVoteKey + owner)
114+
115+
116+func getAdminVotePriceKey (owner) = (AdminVotePriceKey + owner)
117+
118+
119+func getOracleKey (count) = (OracleKey + toString(count))
120+
121+
122+func getOracleIsProvideKey (owner) = (OracleIsProvideKey + owner)
123+
124+
125+func getOracleProvidePriceKey (owner) = (OracleProvidePriceKey + owner)
126+
127+
128+func getNeutrinoBalanceKey (owner) = (NeutrinoBalanceKey + owner)
129+
130+
131+func getWavesBalanceKey (owner) = (WavesBalanceKey + owner)
132+
133+
134+func getBalanceUnlockBlockKey (owner) = (BalanceUnlockBlockKey + owner)
135+
136+
137+func getBlackSwarmPriceKey (block) = ((BlackSwarmPriceKey + "_") + toString(block))
138+
139+
140+func getPriceHistoryKey (block) = ((PriceKey + "_") + toString(block))
141+
142+
143+func getOrderTotalKey (orderId) = (OrderTotalKey + orderId)
144+
145+
146+func getOrderOwnerKey (orderId) = (OrderOwnerKey + orderId)
147+
148+
149+func getOrderHeightKey (orderId) = (OrderHeightKey + orderId)
150+
151+
152+func getOrderStatusKey (orderId) = (OrderStatusKey + orderId)
153+
154+
155+func getOrderFilledTotalKey (orderId) = (OrderFilledTotalKey + orderId)
156+
157+
158+let price = getNumberByKey(PriceKey)
159+
160+func convertNeutrinoToWaves (amount) = ((((amount * 100) / price) * WAVELET) / CENTSINDOLLAR)
161+
162+
163+func convertWavesToNeutrino (amount) = ((((amount * price) / 100) * CENTSINDOLLAR) / WAVELET)
164+
165+
166+func convertNeutrinoToBond (amount) = (amount / CENTSINDOLLAR)
167+
168+
169+func convertBondToNeutrino (amount) = (amount * CENTSINDOLLAR)
170+
171+
172+func convertWavesToBond (amount) = convertNeutrinoToBond(convertWavesToNeutrino(amount))
173+
174+
175+let providingInterval = getNumberByKey(ProvidingIntervalKey)
176+
177+let blockExpireProviding = getNumberByKey(BlockExpireProvidingKey)
178+
179+let isPricePending = getBoolByKey(IsPricePendingKey)
180+
181+let percentPriceOffset = getNumberByKey(PriceOffsetKey)
182+
183+let voteInterval = getNumberByKey(VoteIntervalKey)
184+
185+let blockExpireVote = getNumberByKey(BlockExpireVoteKey)
186+
187+let balanceLockInterval = getNumberByKey(BalanceLockIntervalKey)
188+
189+let isBlocked = getBoolByKey(IsBlockedKey)
190+
191+let minWavesSwapAmount = getNumberByKey(MinWavesSwapAmountKey)
192+
193+let minNeutrinoSwapAmount = getNumberByKey(MinNeutrinoSwapAmountKey)
93194
94195 let neutrinoAssetId = fromBase58String(getStringByKey(NeutrinoAssetIdKey))
95196
96197 let auctionContract = getStringByKey(AuctionContractKey)
97-
98-let price = getNumberByKey(PriceKey)
99198
100199 let reserve = wavesBalance(this)
101200
102201 let orderbook = getStringByKey(OrderbookKey)
103202
104203 let bondAssetId = fromBase58String(getStringByKey(BondAssetIdKey))
105-
106-let oracle = getStringByKey(OracleKey)
107204
108205 let bondSupply = {
109206 let info = extract(assetInfo(bondAssetId))
115212 (info.quantity - assetBalance(this, neutrinoAssetId))
116213 }
117214
118-func getWavesBalance (owner) = getNumberByKey((WavesBalanceKey + owner))
215+let surplus = (convertWavesToNeutrino(reserve) - neutrinoSupply)
216+
217+let oracleOne = getStringByKey(getOracleKey(0))
218+
219+let oracleTwo = getStringByKey(getOracleKey(1))
220+
221+let oracleThree = getStringByKey(getOracleKey(2))
222+
223+let adminOne = getStringByKey(getAdminKey(0))
224+
225+let adminTwo = getStringByKey(getAdminKey(1))
226+
227+let adminThree = getStringByKey(getAdminKey(2))
228+
229+func getAdminVoteInt (owner) = if (getBoolByKey(getAdminVoteKey(owner)))
230+ then 1
231+ else 0
119232
120233
121-func getNeutrinoBalance (owner) = getNumberByKey((NeutrinoBalanceKey + owner))
234+func getAdminVotePrice (owner) = getNumberByKey(getAdminVotePriceKey(owner))
122235
123236
124-func getBalanceBlock (owner) = getNumberByKey((BalanceBlockKey + owner))
237+func isOracleProvide (owner) = getBoolByKey(getOracleIsProvideKey(owner))
125238
126239
127-func getOrderTotal (id) = getNumberByKey((OrderTotalKey + id))
240+func isOracleProvideInt (owner) = if (isOracleProvide(owner))
241+ then 1
242+ else 0
128243
129244
130-func getOrderOwner (id) = getStringByKey((OrderOwnerKey + id))
245+func getOracleProvidePrice (owner) = getNumberByKey(getOracleProvidePriceKey(owner))
131246
132247
133-func getOrderFilledTotal (id) = getNumberByKey((OrderFilledTotalKey + id))
248+func getWavesBalance (owner) = getNumberByKey(getWavesBalanceKey(owner))
134249
135250
136-func convertNeutrinoToWaves (amount) = ((amount * 100) / price)
251+func getNeutrinoBalance (owner) = getNumberByKey(getNeutrinoBalanceKey(owner))
137252
138253
139-func convertWavesToNeutrino (amount) = ((amount * price) / 100)
254+func getUnlockBalanceBlock (owner) = getNumberByKey(getBalanceUnlockBlockKey(owner))
140255
141256
142-func convertNeutrinoToBond (amount) = (amount / Wavelet)
257+func getOrderTotal (id) = getNumberByKey(getOrderTotalKey(id))
143258
144259
145-func convertBondToNeutrino (amount) = (amount * Wavelet)
260+func getOrderOwner (id) = getStringByKey(getOrderOwnerKey(id))
146261
147262
148-func convertWavesToBond (amount) = convertNeutrinoToBond(convertWavesToNeutrino(amount))
263+func getOrderFilledTotal (id) = getNumberByKey(getOrderFilledTotalKey(id))
149264
150265
151-let surplus = (convertWavesToNeutrino(reserve) - neutrinoSupply)
266+func getOrderElementById (id) = (id + LISTSPLITSYMBOL)
152267
153-let CANCELED = "canceled"
154268
155-let NEW = "new"
269+func addOrder (orderId) = (orderbook + getOrderElementById(orderId))
156270
157-let FILLED = "filled"
271+
272+func dropOrder (orderId) = {
273+ let parts = split(orderbook, getOrderElementById(orderId))
274+ (parts[0] + parts[1])
275+ }
276+
158277
159278 @Callable(i)
160-func setCurrentPrice (price) = {
279+func setCurrentPrice (newPrice) = {
161280 let account = toString(i.caller)
162- if ((account != oracle))
163- then throw("permission denied")
164- else WriteSet([DataEntry(PriceKey, price), DataEntry(((PriceKey + ListSplitSymbol) + toString(height)), price)])
281+ let priceProvidingCount = (((isOracleProvideInt(oracleOne) + isOracleProvideInt(oracleTwo)) + isOracleProvideInt(oracleThree)) + 1)
282+ if (isBlocked)
283+ then throw("contract is blocked")
284+ else if (if (if ((account != oracleOne))
285+ then (account != oracleTwo)
286+ else false)
287+ then (account != oracleThree)
288+ else false)
289+ then throw("permission denied")
290+ else if (if ((blockExpireProviding >= height))
291+ then isOracleProvide(account)
292+ else false)
293+ then throw("price is already provided")
294+ else if (if ((height > blockExpireProviding))
295+ then isPricePending
296+ else false)
297+ then throw("use finilizeCurrentPrice")
298+ else WriteSet([DataEntry(getOracleProvidePriceKey(account), newPrice), DataEntry(BlockExpireProvidingKey, if ((height > blockExpireProviding))
299+ then (height + providingInterval)
300+ else blockExpireProviding), DataEntry(getOracleIsProvideKey(oracleOne), if ((height > blockExpireProviding))
301+ then false
302+ else isOracleProvide(oracleOne)), DataEntry(getOracleIsProvideKey(oracleTwo), if ((height > blockExpireProviding))
303+ then false
304+ else isOracleProvide(oracleTwo)), DataEntry(getOracleIsProvideKey(oracleThree), if ((height > blockExpireProviding))
305+ then false
306+ else isOracleProvide(oracleThree)), DataEntry(getOracleIsProvideKey(account), true), DataEntry(IsPricePendingKey, if (if ((blockExpireProviding >= height))
307+ then (priceProvidingCount >= 2)
308+ else false)
309+ then true
310+ else isPricePending)])
311+ }
312+
313+
314+
315+@Callable(i)
316+func finilizeCurrentPrice () = {
317+ let account = toString(i.caller)
318+ let priceProvidingCount = ((isOracleProvideInt(oracleOne) + isOracleProvideInt(oracleTwo)) + isOracleProvideInt(oracleThree))
319+ let newPrice = ((((getOracleProvidePrice(oracleOne) * isOracleProvideInt(oracleOne)) + (getOracleProvidePrice(oracleTwo) * isOracleProvideInt(oracleTwo))) + (getOracleProvidePrice(oracleThree) * isOracleProvideInt(oracleThree))) / priceProvidingCount)
320+ if (isBlocked)
321+ then throw("contract is blocked")
322+ else if (if (if ((account != oracleOne))
323+ then (account != oracleTwo)
324+ else false)
325+ then (account != oracleThree)
326+ else false)
327+ then throw("permission denied")
328+ else if (if (!(isPricePending))
329+ then true
330+ else (blockExpireProviding >= height))
331+ then throw("wait for the end of the price providing")
332+ else if ((2 > priceProvidingCount))
333+ then throw("2/3 oracles need to set a price")
334+ else if (if ((newPrice >= (price + ((price * percentPriceOffset) / 100))))
335+ then true
336+ else ((price - ((price * percentPriceOffset) / 100)) >= newPrice))
337+ then WriteSet([DataEntry(IsBlockedKey, true), DataEntry(getBlackSwarmPriceKey(height), newPrice)])
338+ else WriteSet([DataEntry(PriceKey, newPrice), DataEntry(getPriceHistoryKey(height), newPrice), DataEntry(IsPricePendingKey, false)])
339+ }
340+
341+
342+
343+@Callable(i)
344+func adminUnlock (newPrice) = {
345+ let account = toString(i.caller)
346+ let adminOneVote = if ((account != adminOne))
347+ then getAdminVoteInt(adminOne)
348+ else 0
349+ let adminTwoVote = if ((account != adminTwo))
350+ then getAdminVoteInt(adminTwo)
351+ else 0
352+ let adminThreeVote = if ((account != adminThree))
353+ then getAdminVoteInt(adminThree)
354+ else 0
355+ let adminOnePrice = if (((getAdminVotePrice(adminOne) * adminOneVote) == newPrice))
356+ then 1
357+ else 0
358+ let adminTwoPrice = if (((getAdminVotePrice(adminTwo) * adminTwoVote) == newPrice))
359+ then 1
360+ else 0
361+ let adminThreePrice = if (((getAdminVotePrice(adminThree) * adminThreeVote) == newPrice))
362+ then 1
363+ else 0
364+ if (!(isBlocked))
365+ then throw("Contract is not blocked")
366+ else if (if (((((adminOnePrice + adminTwoPrice) + adminThreePrice) + 1) >= 2))
367+ then (blockExpireVote >= height)
368+ else false)
369+ 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)])
370+ else WriteSet([DataEntry(getAdminVotePriceKey(account), newPrice), DataEntry(BlockExpireVoteKey, if ((height > blockExpireVote))
371+ then (height + voteInterval)
372+ else blockExpireVote), DataEntry(getAdminVoteKey(adminOne), if ((height > blockExpireVote))
373+ then false
374+ else (adminOneVote == 1)), DataEntry(getAdminVoteKey(adminTwo), if ((height > blockExpireVote))
375+ then false
376+ else (adminTwoVote == 1)), DataEntry(getAdminVoteKey(adminThree), if ((height > blockExpireVote))
377+ then false
378+ else (adminThreeVote == 1)), DataEntry(getAdminVoteKey(account), true)])
379+ }
380+
381+
382+
383+@Callable(i)
384+func adminLock () = {
385+ let account = toString(i.caller)
386+ let adminOneVote = if ((account != adminOne))
387+ then getAdminVoteInt(adminOne)
388+ else 1
389+ let adminTwoVote = if ((account != adminTwo))
390+ then getAdminVoteInt(adminTwo)
391+ else 1
392+ let adminThreeVote = if ((account != adminThree))
393+ then getAdminVoteInt(adminThree)
394+ else 1
395+ if (isBlocked)
396+ then throw("Contract is blocked")
397+ else if ((((adminOneVote + adminTwoVote) + adminThreeVote) >= 2))
398+ then WriteSet([DataEntry(IsBlockedKey, true), DataEntry(getAdminVoteKey(adminOne), false), DataEntry(getAdminVoteKey(adminTwo), false), DataEntry(getAdminVoteKey(adminThree), false), DataEntry(BlockExpireVoteKey, 0)])
399+ else WriteSet([DataEntry(BlockExpireVoteKey, if ((height > blockExpireVote))
400+ then (height + voteInterval)
401+ else blockExpireVote), DataEntry(getAdminVoteKey(adminOne), if ((height > blockExpireVote))
402+ then false
403+ else (adminOneVote == 1)), DataEntry(getAdminVoteKey(adminTwo), if ((height > blockExpireVote))
404+ then false
405+ else (adminTwoVote == 1)), DataEntry(getAdminVoteKey(adminThree), if ((height > blockExpireVote))
406+ then false
407+ else (adminThreeVote == 1))])
165408 }
166409
167410
169412 @Callable(i)
170413 func swapWavesToNeutrino () = {
171414 let pmt = extract(i.payment)
172- if (isDefined(pmt.assetId))
173- then throw("can use waves only")
174- else {
175- let account = toBase58String(i.caller.bytes)
176- let amount = convertWavesToNeutrino(pmt.amount)
177- WriteSet([DataEntry((NeutrinoBalanceKey + toString(i.caller)), (amount + getNeutrinoBalance(account))), DataEntry((BalanceBlockKey + toString(i.caller)), (height + BalanceLockBlock))])
178- }
415+ if ((minWavesSwapAmount > pmt.amount))
416+ then throw("amount less min")
417+ else if (isDefined(pmt.assetId))
418+ then throw("can use waves only")
419+ else if (isBlocked)
420+ then throw("contract is blocked")
421+ else {
422+ let amount = convertWavesToNeutrino(pmt.amount)
423+ TransferSet([ScriptTransfer(i.caller, amount, neutrinoAssetId)])
424+ }
179425 }
180426
181427
183429 @Callable(i)
184430 func swapNeutrinoToWaves () = {
185431 let pmt = extract(i.payment)
186- if ((pmt.assetId != neutrinoAssetId))
187- then throw("can use neutrino only")
188- else {
189- let account = toBase58String(i.caller.bytes)
190- let amount = convertNeutrinoToWaves(pmt.amount)
191- WriteSet([DataEntry((WavesBalanceKey + toString(i.caller)), (amount + getWavesBalance(account))), DataEntry((BalanceBlockKey + toString(i.caller)), (height + BalanceLockBlock))])
192- }
432+ if ((minNeutrinoSwapAmount > pmt.amount))
433+ then throw("amount less min")
434+ else if (isBlocked)
435+ then throw("contract is blocked")
436+ else if ((pmt.assetId != neutrinoAssetId))
437+ then throw("can use neutrino only")
438+ else {
439+ let account = toBase58String(i.caller.bytes)
440+ let amount = convertNeutrinoToWaves(pmt.amount)
441+ WriteSet([DataEntry(getWavesBalanceKey(account), (getWavesBalance(account) + amount)), DataEntry(getBalanceUnlockBlockKey(account), (height + balanceLockInterval))])
442+ }
193443 }
194444
195445
196446
197447 @Callable(i)
198-func withdraw (account) = if ((getBalanceBlock(account) >= height))
448+func withdraw (account) = if ((getUnlockBalanceBlock(account) > height))
199449 then throw("wait a couple of blocks for withdraw")
200- else ScriptResult(WriteSet([DataEntry((WavesBalanceKey + account), 0), DataEntry((NeutrinoBalanceKey + account), 0)]), TransferSet([ScriptTransfer(addressFromStringValue(account), getNeutrinoBalance(account), neutrinoAssetId), ScriptTransfer(addressFromStringValue(account), getWavesBalance(account), unit)]))
450+ else ScriptResult(WriteSet([DataEntry(getWavesBalanceKey(account), 0), DataEntry(getNeutrinoBalanceKey(account), 0)]), TransferSet([ScriptTransfer(addressFromStringValue(account), getNeutrinoBalance(account), neutrinoAssetId), ScriptTransfer(addressFromStringValue(account), getWavesBalance(account), unit)]))
201451
202452
203453
206456 let deficit = (neutrinoSupply - convertWavesToNeutrino(reserve))
207457 let balanceAuction = assetBalance(addressFromStringValue(auctionContract), bondAssetId)
208458 let amount = (convertNeutrinoToBond(deficit) - balanceAuction)
209- if ((amount > 0))
210- then TransferSet([ScriptTransfer(addressFromStringValue(auctionContract), amount, bondAssetId)])
211- else throw("bond were generated or do not need it")
459+ if (isBlocked)
460+ then throw("contract is blocked")
461+ else if ((amount > 0))
462+ then TransferSet([ScriptTransfer(addressFromStringValue(auctionContract), amount, bondAssetId)])
463+ else throw("bond were generated or do not need it")
212464 }
213465
214466
221473 then throw("can use bond only")
222474 else if ((getOrderOwner(newOrderId) != ""))
223475 then throw("order exists")
224- else WriteSet([DataEntry(OrderbookKey, ((orderbook + newOrderId) + ListSplitSymbol)), DataEntry((OrderTotalKey + newOrderId), pmt.amount), DataEntry((OrderOwnerKey + newOrderId), toString(i.caller)), DataEntry((OrderHeightKey + newOrderId), height), DataEntry((OrderStatusKey + newOrderId), NEW)])
476+ 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)])
225477 }
226478
227479
232484 let amount = (getOrderTotal(orderId) - getOrderFilledTotal(orderId))
233485 if ((owner != toString(i.caller)))
234486 then throw("permission denied")
235- else {
236- let parts = split(orderbook, (orderId + ListSplitSymbol))
237- ScriptResult(WriteSet([DataEntry(OrderbookKey, (parts[0] + parts[1])), DataEntry((OrderStatusKey + orderId), CANCELED)]), TransferSet([ScriptTransfer(i.caller, amount, bondAssetId)]))
238- }
487+ else ScriptResult(WriteSet([DataEntry(OrderbookKey, dropOrder(orderId)), DataEntry(getOrderStatusKey(orderId), CANCELED)]), TransferSet([ScriptTransfer(i.caller, amount, bondAssetId)]))
239488 }
240489
241490
242491
243492 @Callable(i)
244493 func executeOrder () = {
245- let orderId = split(orderbook, ListSplitSymbol)[0]
494+ let orderId = split(orderbook, LISTSPLITSYMBOL)[0]
246495 let orderTotal = getOrderTotal(orderId)
247496 let orderOwner = getOrderOwner(orderId)
248497 let filledTotal = getOrderFilledTotal(orderId)
249- if ((0 >= surplus))
250- then throw("surplus is less than zero")
251- else {
252- let amount = (orderTotal - filledTotal)
253- let surplusBond = convertNeutrinoToBond(surplus)
254- let status = if ((surplusBond >= amount))
255- then FILLED
256- else NEW
257- let newFilledTotal = if ((surplusBond >= amount))
258- then orderTotal
259- else surplusBond
260- ScriptResult(WriteSet([DataEntry(OrderbookKey, split(orderbook, (orderId + ListSplitSymbol))[1]), DataEntry((OrderFilledTotalKey + orderId), (filledTotal + newFilledTotal)), DataEntry((OrderStatusKey + orderId), status)]), TransferSet([ScriptTransfer(addressFromStringValue(orderOwner), convertBondToNeutrino(newFilledTotal), neutrinoAssetId)]))
261- }
498+ if (isBlocked)
499+ then throw("contract is blocked")
500+ else if ((0 >= surplus))
501+ then throw("surplus is less than zero")
502+ else {
503+ let amount = (orderTotal - filledTotal)
504+ let surplusBond = convertNeutrinoToBond(surplus)
505+ let status = if ((surplusBond >= amount))
506+ then FILLED
507+ else NEW
508+ let newFilledTotal = if ((surplusBond >= amount))
509+ then orderTotal
510+ else surplusBond
511+ ScriptResult(WriteSet([DataEntry(OrderbookKey, dropOrder(orderId)), DataEntry(getOrderFilledTotalKey(orderId), (filledTotal + newFilledTotal)), DataEntry(getOrderStatusKey(orderId), status)]), TransferSet([ScriptTransfer(addressFromStringValue(orderOwner), convertBondToNeutrino(newFilledTotal), neutrinoAssetId)]))
512+ }
513+ }
514+
515+
516+
517+@Callable(i)
518+func transfer (account) = {
519+ let pmt = extract(i.payment)
520+ if (isDefined(pmt.assetId))
521+ then throw("can use waves only at the moment")
522+ else TransferSet([ScriptTransfer(addressFromStringValue(account), pmt.amount, unit)])
262523 }
263524
264525
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
28-func getNumberByKeyAndAddress (address,key) = match getInteger(addressFromStringValue(address), key) {
28+func getNumberByAddressAndKey (address,key) = match getInteger(addressFromStringValue(address), key) {
2929 case a: Int =>
3030 a
3131 case _ =>
3232 0
3333 }
3434
3535
36-func getStringByKeyAndAddress (address,key) = match getString(addressFromStringValue(address), key) {
37- case a: String =>
38- a
39- case _ =>
40- ""
41-}
36+let LISTSPLITSYMBOL = "_"
4237
38+let LISTDATASYMBOL = "+"
4339
44-func getBoolByKeyAndAddress (address,key) = match getBoolean(addressFromStringValue(address), key) {
45- case a: Boolean =>
46- a
47- case _ =>
48- false
49-}
40+let WAVELET = 100000000
5041
42+let CENTSINDOLLAR = 100
5143
52-let ListSplitSymbol = "_"
44+let CANCELED = "canceled"
5345
54-let BalanceLockBlock = 10
46+let NEW = "new"
5547
56-let ListDataSplitSymbol = "+"
57-
58-let Wavelet = 100000000
59-
60-let MinimalBondOrder = (10 * Wavelet)
61-
62-let MinimalSurplus = (10 * Wavelet)
63-
64-let ApplyBlockTimeout = 10
48+let FILLED = "filled"
6549
6650 let NeutrinoAssetIdKey = "neutrino_asset_id"
6751
6852 let BondAssetIdKey = "bond_asset_id"
6953
7054 let AuctionContractKey = "auction_contract"
7155
56+let BalanceLockIntervalKey = "balance_lock_interval"
57+
58+let VoteIntervalKey = "vote_interval"
59+
60+let MinWavesSwapAmountKey = "min_waves_swap_amount"
61+
62+let MinNeutrinoSwapAmountKey = "min_neutrino_swap_amount"
63+
64+let PriceOffsetKey = "price_offset"
65+
66+let ProvidingIntervalKey = "providing_interval"
67+
7268 let PriceKey = "price"
7369
7470 let NeutrinoBalanceKey = "neutrino_"
7571
7672 let WavesBalanceKey = "waves_"
7773
78-let BalanceBlockKey = "balance_block_"
74+let BalanceUnlockBlockKey = "balance_block_"
7975
8076 let OrderbookKey = "orderbook"
8177
8278 let OrderTotalKey = "order_total_"
8379
8480 let OrderOwnerKey = "order_owner_"
8581
8682 let OrderHeightKey = "order_height_"
8783
8884 let OrderFilledTotalKey = "order_filled_total_"
8985
9086 let OrderStatusKey = "order_status_"
9187
92-let OracleKey = "oracle"
88+let IsBlockedKey = "is_blocked"
89+
90+let BlackSwarmPriceKey = "black_swarm_price"
91+
92+let AdminVoteKey = "admin_vote_"
93+
94+let AdminVotePriceKey = "admin_vote_price_"
95+
96+let BlockExpireVoteKey = "vote_expire_block"
97+
98+let AdminKey = "admin_"
99+
100+let IsPricePendingKey = "is_pending_price"
101+
102+let OracleKey = "oracle_"
103+
104+let OracleIsProvideKey = "oracle_is_provide_"
105+
106+let OracleProvidePriceKey = "oracle_price_provide_"
107+
108+let BlockExpireProvidingKey = "providing_expire_block"
109+
110+func getAdminKey (count) = (AdminKey + toString(count))
111+
112+
113+func getAdminVoteKey (owner) = (AdminVoteKey + owner)
114+
115+
116+func getAdminVotePriceKey (owner) = (AdminVotePriceKey + owner)
117+
118+
119+func getOracleKey (count) = (OracleKey + toString(count))
120+
121+
122+func getOracleIsProvideKey (owner) = (OracleIsProvideKey + owner)
123+
124+
125+func getOracleProvidePriceKey (owner) = (OracleProvidePriceKey + owner)
126+
127+
128+func getNeutrinoBalanceKey (owner) = (NeutrinoBalanceKey + owner)
129+
130+
131+func getWavesBalanceKey (owner) = (WavesBalanceKey + owner)
132+
133+
134+func getBalanceUnlockBlockKey (owner) = (BalanceUnlockBlockKey + owner)
135+
136+
137+func getBlackSwarmPriceKey (block) = ((BlackSwarmPriceKey + "_") + toString(block))
138+
139+
140+func getPriceHistoryKey (block) = ((PriceKey + "_") + toString(block))
141+
142+
143+func getOrderTotalKey (orderId) = (OrderTotalKey + orderId)
144+
145+
146+func getOrderOwnerKey (orderId) = (OrderOwnerKey + orderId)
147+
148+
149+func getOrderHeightKey (orderId) = (OrderHeightKey + orderId)
150+
151+
152+func getOrderStatusKey (orderId) = (OrderStatusKey + orderId)
153+
154+
155+func getOrderFilledTotalKey (orderId) = (OrderFilledTotalKey + orderId)
156+
157+
158+let price = getNumberByKey(PriceKey)
159+
160+func convertNeutrinoToWaves (amount) = ((((amount * 100) / price) * WAVELET) / CENTSINDOLLAR)
161+
162+
163+func convertWavesToNeutrino (amount) = ((((amount * price) / 100) * CENTSINDOLLAR) / WAVELET)
164+
165+
166+func convertNeutrinoToBond (amount) = (amount / CENTSINDOLLAR)
167+
168+
169+func convertBondToNeutrino (amount) = (amount * CENTSINDOLLAR)
170+
171+
172+func convertWavesToBond (amount) = convertNeutrinoToBond(convertWavesToNeutrino(amount))
173+
174+
175+let providingInterval = getNumberByKey(ProvidingIntervalKey)
176+
177+let blockExpireProviding = getNumberByKey(BlockExpireProvidingKey)
178+
179+let isPricePending = getBoolByKey(IsPricePendingKey)
180+
181+let percentPriceOffset = getNumberByKey(PriceOffsetKey)
182+
183+let voteInterval = getNumberByKey(VoteIntervalKey)
184+
185+let blockExpireVote = getNumberByKey(BlockExpireVoteKey)
186+
187+let balanceLockInterval = getNumberByKey(BalanceLockIntervalKey)
188+
189+let isBlocked = getBoolByKey(IsBlockedKey)
190+
191+let minWavesSwapAmount = getNumberByKey(MinWavesSwapAmountKey)
192+
193+let minNeutrinoSwapAmount = getNumberByKey(MinNeutrinoSwapAmountKey)
93194
94195 let neutrinoAssetId = fromBase58String(getStringByKey(NeutrinoAssetIdKey))
95196
96197 let auctionContract = getStringByKey(AuctionContractKey)
97-
98-let price = getNumberByKey(PriceKey)
99198
100199 let reserve = wavesBalance(this)
101200
102201 let orderbook = getStringByKey(OrderbookKey)
103202
104203 let bondAssetId = fromBase58String(getStringByKey(BondAssetIdKey))
105-
106-let oracle = getStringByKey(OracleKey)
107204
108205 let bondSupply = {
109206 let info = extract(assetInfo(bondAssetId))
110207 (info.quantity - assetBalance(this, bondAssetId))
111208 }
112209
113210 let neutrinoSupply = {
114211 let info = extract(assetInfo(neutrinoAssetId))
115212 (info.quantity - assetBalance(this, neutrinoAssetId))
116213 }
117214
118-func getWavesBalance (owner) = getNumberByKey((WavesBalanceKey + owner))
215+let surplus = (convertWavesToNeutrino(reserve) - neutrinoSupply)
216+
217+let oracleOne = getStringByKey(getOracleKey(0))
218+
219+let oracleTwo = getStringByKey(getOracleKey(1))
220+
221+let oracleThree = getStringByKey(getOracleKey(2))
222+
223+let adminOne = getStringByKey(getAdminKey(0))
224+
225+let adminTwo = getStringByKey(getAdminKey(1))
226+
227+let adminThree = getStringByKey(getAdminKey(2))
228+
229+func getAdminVoteInt (owner) = if (getBoolByKey(getAdminVoteKey(owner)))
230+ then 1
231+ else 0
119232
120233
121-func getNeutrinoBalance (owner) = getNumberByKey((NeutrinoBalanceKey + owner))
234+func getAdminVotePrice (owner) = getNumberByKey(getAdminVotePriceKey(owner))
122235
123236
124-func getBalanceBlock (owner) = getNumberByKey((BalanceBlockKey + owner))
237+func isOracleProvide (owner) = getBoolByKey(getOracleIsProvideKey(owner))
125238
126239
127-func getOrderTotal (id) = getNumberByKey((OrderTotalKey + id))
240+func isOracleProvideInt (owner) = if (isOracleProvide(owner))
241+ then 1
242+ else 0
128243
129244
130-func getOrderOwner (id) = getStringByKey((OrderOwnerKey + id))
245+func getOracleProvidePrice (owner) = getNumberByKey(getOracleProvidePriceKey(owner))
131246
132247
133-func getOrderFilledTotal (id) = getNumberByKey((OrderFilledTotalKey + id))
248+func getWavesBalance (owner) = getNumberByKey(getWavesBalanceKey(owner))
134249
135250
136-func convertNeutrinoToWaves (amount) = ((amount * 100) / price)
251+func getNeutrinoBalance (owner) = getNumberByKey(getNeutrinoBalanceKey(owner))
137252
138253
139-func convertWavesToNeutrino (amount) = ((amount * price) / 100)
254+func getUnlockBalanceBlock (owner) = getNumberByKey(getBalanceUnlockBlockKey(owner))
140255
141256
142-func convertNeutrinoToBond (amount) = (amount / Wavelet)
257+func getOrderTotal (id) = getNumberByKey(getOrderTotalKey(id))
143258
144259
145-func convertBondToNeutrino (amount) = (amount * Wavelet)
260+func getOrderOwner (id) = getStringByKey(getOrderOwnerKey(id))
146261
147262
148-func convertWavesToBond (amount) = convertNeutrinoToBond(convertWavesToNeutrino(amount))
263+func getOrderFilledTotal (id) = getNumberByKey(getOrderFilledTotalKey(id))
149264
150265
151-let surplus = (convertWavesToNeutrino(reserve) - neutrinoSupply)
266+func getOrderElementById (id) = (id + LISTSPLITSYMBOL)
152267
153-let CANCELED = "canceled"
154268
155-let NEW = "new"
269+func addOrder (orderId) = (orderbook + getOrderElementById(orderId))
156270
157-let FILLED = "filled"
271+
272+func dropOrder (orderId) = {
273+ let parts = split(orderbook, getOrderElementById(orderId))
274+ (parts[0] + parts[1])
275+ }
276+
158277
159278 @Callable(i)
160-func setCurrentPrice (price) = {
279+func setCurrentPrice (newPrice) = {
161280 let account = toString(i.caller)
162- if ((account != oracle))
163- then throw("permission denied")
164- else WriteSet([DataEntry(PriceKey, price), DataEntry(((PriceKey + ListSplitSymbol) + toString(height)), price)])
281+ let priceProvidingCount = (((isOracleProvideInt(oracleOne) + isOracleProvideInt(oracleTwo)) + isOracleProvideInt(oracleThree)) + 1)
282+ if (isBlocked)
283+ then throw("contract is blocked")
284+ else if (if (if ((account != oracleOne))
285+ then (account != oracleTwo)
286+ else false)
287+ then (account != oracleThree)
288+ else false)
289+ then throw("permission denied")
290+ else if (if ((blockExpireProviding >= height))
291+ then isOracleProvide(account)
292+ else false)
293+ then throw("price is already provided")
294+ else if (if ((height > blockExpireProviding))
295+ then isPricePending
296+ else false)
297+ then throw("use finilizeCurrentPrice")
298+ else WriteSet([DataEntry(getOracleProvidePriceKey(account), newPrice), DataEntry(BlockExpireProvidingKey, if ((height > blockExpireProviding))
299+ then (height + providingInterval)
300+ else blockExpireProviding), DataEntry(getOracleIsProvideKey(oracleOne), if ((height > blockExpireProviding))
301+ then false
302+ else isOracleProvide(oracleOne)), DataEntry(getOracleIsProvideKey(oracleTwo), if ((height > blockExpireProviding))
303+ then false
304+ else isOracleProvide(oracleTwo)), DataEntry(getOracleIsProvideKey(oracleThree), if ((height > blockExpireProviding))
305+ then false
306+ else isOracleProvide(oracleThree)), DataEntry(getOracleIsProvideKey(account), true), DataEntry(IsPricePendingKey, if (if ((blockExpireProviding >= height))
307+ then (priceProvidingCount >= 2)
308+ else false)
309+ then true
310+ else isPricePending)])
311+ }
312+
313+
314+
315+@Callable(i)
316+func finilizeCurrentPrice () = {
317+ let account = toString(i.caller)
318+ let priceProvidingCount = ((isOracleProvideInt(oracleOne) + isOracleProvideInt(oracleTwo)) + isOracleProvideInt(oracleThree))
319+ let newPrice = ((((getOracleProvidePrice(oracleOne) * isOracleProvideInt(oracleOne)) + (getOracleProvidePrice(oracleTwo) * isOracleProvideInt(oracleTwo))) + (getOracleProvidePrice(oracleThree) * isOracleProvideInt(oracleThree))) / priceProvidingCount)
320+ if (isBlocked)
321+ then throw("contract is blocked")
322+ else if (if (if ((account != oracleOne))
323+ then (account != oracleTwo)
324+ else false)
325+ then (account != oracleThree)
326+ else false)
327+ then throw("permission denied")
328+ else if (if (!(isPricePending))
329+ then true
330+ else (blockExpireProviding >= height))
331+ then throw("wait for the end of the price providing")
332+ else if ((2 > priceProvidingCount))
333+ then throw("2/3 oracles need to set a price")
334+ else if (if ((newPrice >= (price + ((price * percentPriceOffset) / 100))))
335+ then true
336+ else ((price - ((price * percentPriceOffset) / 100)) >= newPrice))
337+ then WriteSet([DataEntry(IsBlockedKey, true), DataEntry(getBlackSwarmPriceKey(height), newPrice)])
338+ else WriteSet([DataEntry(PriceKey, newPrice), DataEntry(getPriceHistoryKey(height), newPrice), DataEntry(IsPricePendingKey, false)])
339+ }
340+
341+
342+
343+@Callable(i)
344+func adminUnlock (newPrice) = {
345+ let account = toString(i.caller)
346+ let adminOneVote = if ((account != adminOne))
347+ then getAdminVoteInt(adminOne)
348+ else 0
349+ let adminTwoVote = if ((account != adminTwo))
350+ then getAdminVoteInt(adminTwo)
351+ else 0
352+ let adminThreeVote = if ((account != adminThree))
353+ then getAdminVoteInt(adminThree)
354+ else 0
355+ let adminOnePrice = if (((getAdminVotePrice(adminOne) * adminOneVote) == newPrice))
356+ then 1
357+ else 0
358+ let adminTwoPrice = if (((getAdminVotePrice(adminTwo) * adminTwoVote) == newPrice))
359+ then 1
360+ else 0
361+ let adminThreePrice = if (((getAdminVotePrice(adminThree) * adminThreeVote) == newPrice))
362+ then 1
363+ else 0
364+ if (!(isBlocked))
365+ then throw("Contract is not blocked")
366+ else if (if (((((adminOnePrice + adminTwoPrice) + adminThreePrice) + 1) >= 2))
367+ then (blockExpireVote >= height)
368+ else false)
369+ 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)])
370+ else WriteSet([DataEntry(getAdminVotePriceKey(account), newPrice), DataEntry(BlockExpireVoteKey, if ((height > blockExpireVote))
371+ then (height + voteInterval)
372+ else blockExpireVote), DataEntry(getAdminVoteKey(adminOne), if ((height > blockExpireVote))
373+ then false
374+ else (adminOneVote == 1)), DataEntry(getAdminVoteKey(adminTwo), if ((height > blockExpireVote))
375+ then false
376+ else (adminTwoVote == 1)), DataEntry(getAdminVoteKey(adminThree), if ((height > blockExpireVote))
377+ then false
378+ else (adminThreeVote == 1)), DataEntry(getAdminVoteKey(account), true)])
379+ }
380+
381+
382+
383+@Callable(i)
384+func adminLock () = {
385+ let account = toString(i.caller)
386+ let adminOneVote = if ((account != adminOne))
387+ then getAdminVoteInt(adminOne)
388+ else 1
389+ let adminTwoVote = if ((account != adminTwo))
390+ then getAdminVoteInt(adminTwo)
391+ else 1
392+ let adminThreeVote = if ((account != adminThree))
393+ then getAdminVoteInt(adminThree)
394+ else 1
395+ if (isBlocked)
396+ then throw("Contract is blocked")
397+ else if ((((adminOneVote + adminTwoVote) + adminThreeVote) >= 2))
398+ then WriteSet([DataEntry(IsBlockedKey, true), DataEntry(getAdminVoteKey(adminOne), false), DataEntry(getAdminVoteKey(adminTwo), false), DataEntry(getAdminVoteKey(adminThree), false), DataEntry(BlockExpireVoteKey, 0)])
399+ else WriteSet([DataEntry(BlockExpireVoteKey, if ((height > blockExpireVote))
400+ then (height + voteInterval)
401+ else blockExpireVote), DataEntry(getAdminVoteKey(adminOne), if ((height > blockExpireVote))
402+ then false
403+ else (adminOneVote == 1)), DataEntry(getAdminVoteKey(adminTwo), if ((height > blockExpireVote))
404+ then false
405+ else (adminTwoVote == 1)), DataEntry(getAdminVoteKey(adminThree), if ((height > blockExpireVote))
406+ then false
407+ else (adminThreeVote == 1))])
165408 }
166409
167410
168411
169412 @Callable(i)
170413 func swapWavesToNeutrino () = {
171414 let pmt = extract(i.payment)
172- if (isDefined(pmt.assetId))
173- then throw("can use waves only")
174- else {
175- let account = toBase58String(i.caller.bytes)
176- let amount = convertWavesToNeutrino(pmt.amount)
177- WriteSet([DataEntry((NeutrinoBalanceKey + toString(i.caller)), (amount + getNeutrinoBalance(account))), DataEntry((BalanceBlockKey + toString(i.caller)), (height + BalanceLockBlock))])
178- }
415+ if ((minWavesSwapAmount > pmt.amount))
416+ then throw("amount less min")
417+ else if (isDefined(pmt.assetId))
418+ then throw("can use waves only")
419+ else if (isBlocked)
420+ then throw("contract is blocked")
421+ else {
422+ let amount = convertWavesToNeutrino(pmt.amount)
423+ TransferSet([ScriptTransfer(i.caller, amount, neutrinoAssetId)])
424+ }
179425 }
180426
181427
182428
183429 @Callable(i)
184430 func swapNeutrinoToWaves () = {
185431 let pmt = extract(i.payment)
186- if ((pmt.assetId != neutrinoAssetId))
187- then throw("can use neutrino only")
188- else {
189- let account = toBase58String(i.caller.bytes)
190- let amount = convertNeutrinoToWaves(pmt.amount)
191- WriteSet([DataEntry((WavesBalanceKey + toString(i.caller)), (amount + getWavesBalance(account))), DataEntry((BalanceBlockKey + toString(i.caller)), (height + BalanceLockBlock))])
192- }
432+ if ((minNeutrinoSwapAmount > pmt.amount))
433+ then throw("amount less min")
434+ else if (isBlocked)
435+ then throw("contract is blocked")
436+ else if ((pmt.assetId != neutrinoAssetId))
437+ then throw("can use neutrino only")
438+ else {
439+ let account = toBase58String(i.caller.bytes)
440+ let amount = convertNeutrinoToWaves(pmt.amount)
441+ WriteSet([DataEntry(getWavesBalanceKey(account), (getWavesBalance(account) + amount)), DataEntry(getBalanceUnlockBlockKey(account), (height + balanceLockInterval))])
442+ }
193443 }
194444
195445
196446
197447 @Callable(i)
198-func withdraw (account) = if ((getBalanceBlock(account) >= height))
448+func withdraw (account) = if ((getUnlockBalanceBlock(account) > height))
199449 then throw("wait a couple of blocks for withdraw")
200- else ScriptResult(WriteSet([DataEntry((WavesBalanceKey + account), 0), DataEntry((NeutrinoBalanceKey + account), 0)]), TransferSet([ScriptTransfer(addressFromStringValue(account), getNeutrinoBalance(account), neutrinoAssetId), ScriptTransfer(addressFromStringValue(account), getWavesBalance(account), unit)]))
450+ else ScriptResult(WriteSet([DataEntry(getWavesBalanceKey(account), 0), DataEntry(getNeutrinoBalanceKey(account), 0)]), TransferSet([ScriptTransfer(addressFromStringValue(account), getNeutrinoBalance(account), neutrinoAssetId), ScriptTransfer(addressFromStringValue(account), getWavesBalance(account), unit)]))
201451
202452
203453
204454 @Callable(i)
205455 func generateBond () = {
206456 let deficit = (neutrinoSupply - convertWavesToNeutrino(reserve))
207457 let balanceAuction = assetBalance(addressFromStringValue(auctionContract), bondAssetId)
208458 let amount = (convertNeutrinoToBond(deficit) - balanceAuction)
209- if ((amount > 0))
210- then TransferSet([ScriptTransfer(addressFromStringValue(auctionContract), amount, bondAssetId)])
211- else throw("bond were generated or do not need it")
459+ if (isBlocked)
460+ then throw("contract is blocked")
461+ else if ((amount > 0))
462+ then TransferSet([ScriptTransfer(addressFromStringValue(auctionContract), amount, bondAssetId)])
463+ else throw("bond were generated or do not need it")
212464 }
213465
214466
215467
216468 @Callable(i)
217469 func setOrder () = {
218470 let pmt = extract(i.payment)
219471 let newOrderId = toBase58String(keccak256(((toBytes(pmt.amount) + i.caller.bytes) + toBytes(height))))
220472 if ((pmt.assetId != bondAssetId))
221473 then throw("can use bond only")
222474 else if ((getOrderOwner(newOrderId) != ""))
223475 then throw("order exists")
224- else WriteSet([DataEntry(OrderbookKey, ((orderbook + newOrderId) + ListSplitSymbol)), DataEntry((OrderTotalKey + newOrderId), pmt.amount), DataEntry((OrderOwnerKey + newOrderId), toString(i.caller)), DataEntry((OrderHeightKey + newOrderId), height), DataEntry((OrderStatusKey + newOrderId), NEW)])
476+ 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)])
225477 }
226478
227479
228480
229481 @Callable(i)
230482 func cancelOrder (orderId) = {
231483 let owner = getOrderOwner(orderId)
232484 let amount = (getOrderTotal(orderId) - getOrderFilledTotal(orderId))
233485 if ((owner != toString(i.caller)))
234486 then throw("permission denied")
235- else {
236- let parts = split(orderbook, (orderId + ListSplitSymbol))
237- ScriptResult(WriteSet([DataEntry(OrderbookKey, (parts[0] + parts[1])), DataEntry((OrderStatusKey + orderId), CANCELED)]), TransferSet([ScriptTransfer(i.caller, amount, bondAssetId)]))
238- }
487+ else ScriptResult(WriteSet([DataEntry(OrderbookKey, dropOrder(orderId)), DataEntry(getOrderStatusKey(orderId), CANCELED)]), TransferSet([ScriptTransfer(i.caller, amount, bondAssetId)]))
239488 }
240489
241490
242491
243492 @Callable(i)
244493 func executeOrder () = {
245- let orderId = split(orderbook, ListSplitSymbol)[0]
494+ let orderId = split(orderbook, LISTSPLITSYMBOL)[0]
246495 let orderTotal = getOrderTotal(orderId)
247496 let orderOwner = getOrderOwner(orderId)
248497 let filledTotal = getOrderFilledTotal(orderId)
249- if ((0 >= surplus))
250- then throw("surplus is less than zero")
251- else {
252- let amount = (orderTotal - filledTotal)
253- let surplusBond = convertNeutrinoToBond(surplus)
254- let status = if ((surplusBond >= amount))
255- then FILLED
256- else NEW
257- let newFilledTotal = if ((surplusBond >= amount))
258- then orderTotal
259- else surplusBond
260- ScriptResult(WriteSet([DataEntry(OrderbookKey, split(orderbook, (orderId + ListSplitSymbol))[1]), DataEntry((OrderFilledTotalKey + orderId), (filledTotal + newFilledTotal)), DataEntry((OrderStatusKey + orderId), status)]), TransferSet([ScriptTransfer(addressFromStringValue(orderOwner), convertBondToNeutrino(newFilledTotal), neutrinoAssetId)]))
261- }
498+ if (isBlocked)
499+ then throw("contract is blocked")
500+ else if ((0 >= surplus))
501+ then throw("surplus is less than zero")
502+ else {
503+ let amount = (orderTotal - filledTotal)
504+ let surplusBond = convertNeutrinoToBond(surplus)
505+ let status = if ((surplusBond >= amount))
506+ then FILLED
507+ else NEW
508+ let newFilledTotal = if ((surplusBond >= amount))
509+ then orderTotal
510+ else surplusBond
511+ ScriptResult(WriteSet([DataEntry(OrderbookKey, dropOrder(orderId)), DataEntry(getOrderFilledTotalKey(orderId), (filledTotal + newFilledTotal)), DataEntry(getOrderStatusKey(orderId), status)]), TransferSet([ScriptTransfer(addressFromStringValue(orderOwner), convertBondToNeutrino(newFilledTotal), neutrinoAssetId)]))
512+ }
513+ }
514+
515+
516+
517+@Callable(i)
518+func transfer (account) = {
519+ let pmt = extract(i.payment)
520+ if (isDefined(pmt.assetId))
521+ then throw("can use waves only at the moment")
522+ else TransferSet([ScriptTransfer(addressFromStringValue(account), pmt.amount, unit)])
262523 }
263524
264525

github/deemru/w8io/6500d08 
100.69 ms