tx · F86jSxc3DhGaMp39H6RLNfzNRz25ZK9sd4vT4pCXzZKS

3N43aBk5aqHBop72haz2xQTTv9ATSmR4UEL:  -0.01400000 Waves

2022.01.18 13:56 [1884285] smart account 3N43aBk5aqHBop72haz2xQTTv9ATSmR4UEL > SELF 0.00000000 Waves

{ "type": 13, "id": "F86jSxc3DhGaMp39H6RLNfzNRz25ZK9sd4vT4pCXzZKS", "fee": 1400000, "feeAssetId": null, "timestamp": 1642503279987, "version": 2, "chainId": 84, "sender": "3N43aBk5aqHBop72haz2xQTTv9ATSmR4UEL", "senderPublicKey": "CDcEP1otXnBCVTs5MNPuC1q1bxR3CETiDTb5diL4TZna", "proofs": [ "4yzm89hnjS4FAApaUMn2NGCK7JaPLTyCMFRwA9oZeeTieAX62TABjewpqYDWAv4zrPSE16dp2Ysham9XQiC7iHi", "5pf6npxuD39efpseUj98xXjDPyzS9GF7meYgLeCYubGXdjnC4DsT8pikAX8jYHZQUmctwZE22rpCnxLgYyeFxJ3S" ], "script": "base64:AAIFAAAAAAAAADAIAhIDCgEEEgcKBQEBCAgEEgMKAQESAwoBARIAEgMKAQESABIAEgASBQoDBAEIEgAAAABYAAAAAAd2ZXJzaW9uAgAAAAUxLjAuMAAAAAAKa2V5VmVyc2lvbgIAAAAHdmVyc2lvbgAAAAAJa2V5QWN0aXZlAgAAAAZhY3RpdmUAAAAAC2tleUFzc2V0SWRBAgAAAApBX2Fzc2V0X2lkAAAAAAtrZXlBc3NldElkQgIAAAAKQl9hc3NldF9pZAAAAAALa2V5QmFsYW5jZUECAAAAD0FfYXNzZXRfYmFsYW5jZQAAAAALa2V5QmFsYW5jZUICAAAAD0JfYXNzZXRfYmFsYW5jZQAAAAAPa2V5QmFsYW5jZUluaXRBAgAAAAxBX2Fzc2V0X2luaXQAAAAAD2tleUJhbGFuY2VJbml0QgIAAAAMQl9hc3NldF9pbml0AAAAAA9rZXlTaGFyZUFzc2V0SWQCAAAADnNoYXJlX2Fzc2V0X2lkAAAAABNrZXlTaGFyZUFzc2V0U3VwcGx5AgAAABJzaGFyZV9hc3NldF9zdXBwbHkAAAAADWtleUNvbW1pc3Npb24CAAAACmNvbW1pc3Npb24AAAAAG2tleUNvbW1pc3Npb25TY2FsZURlbGltaXRlcgIAAAAaY29tbWlzc2lvbl9zY2FsZV9kZWxpbWl0ZXIAAAAACGtleUNhdXNlAgAAAA5zaHV0ZG93bl9jYXVzZQAAAAAPa2V5Rmlyc3RIYXJ2ZXN0AgAAAA1maXJzdF9oYXJ2ZXN0AAAAABVrZXlGaXJzdEhhcnZlc3RIZWlnaHQCAAAAFGZpcnN0X2hhcnZlc3RfaGVpZ2h0AAAAAAtrU2hhcmVMaW1pdAIAAAAcc2hhcmVfbGltaXRfb25fZmlyc3RfaGFydmVzdAAAAAALa0Jhc2VQZXJpb2QCAAAAC2Jhc2VfcGVyaW9kAAAAAA1rUGVyaW9kTGVuZ3RoAgAAAA1wZXJpb2RfbGVuZ3RoAAAAAAxrU3RhcnRIZWlnaHQCAAAADHN0YXJ0X2hlaWdodAAAAAATa0ZpcnN0SGFydmVzdEhlaWdodAIAAAAUZmlyc3RfaGFydmVzdF9oZWlnaHQAAAAAEmtleVVTRE5OU0JUQWRkcmVzcwIAAAAYc3Rha2luZ191c2RubnNidF9hZGRyZXNzAAAAAA5rZXlFVVJOQWRkcmVzcwIAAAAUc3Rha2luZ19ldXJuX2FkZHJlc3MAAAAADmtleUxlYXNpbmdQb29sAgAAAA9sZWFzaW5nX2FkZHJlc3MAAAAAEGtleUxlYXNpbmdBbW91bnQCAAAADmxlYXNpbmdfYW1vdW50AAAAAAxrZXlMZWFzaW5nSWQCAAAACmxlYXNpbmdfaWQAAAAAD2tleUFkbWluUHViS2V5MQIAAAALYWRtaW5fcHViXzEAAAAAD2tleUFkbWluUHViS2V5MgIAAAALYWRtaW5fcHViXzIAAAAAD2tleUFkbWluUHViS2V5MwIAAAALYWRtaW5fcHViXzMAAAAABm9yYWNsZQkBAAAAB0FkZHJlc3MAAAABAQAAABoBVOlFqh6QLzqu8boO5i6akl8amITh82KzCAEAAAALZ2V0QWRtaW5QdWIAAAABAAAAC2tleUFkbWluUHViBAAAAAckbWF0Y2gwCQAEHQAAAAIFAAAABm9yYWNsZQUAAAALa2V5QWRtaW5QdWIDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAABlN0cmluZwQAAAAGc3RyaW5nBQAAAAckbWF0Y2gwCQACWQAAAAEFAAAABnN0cmluZwQAAAAHbm90aGluZwUAAAAHJG1hdGNoMAkAAAIAAAABAgAAABlBZG1pbiBwdWJsaWMga2V5IGlzIGVtcHR5AAAAAAxhZG1pblB1YktleTEJAQAAAAtnZXRBZG1pblB1YgAAAAEFAAAAD2tleUFkbWluUHViS2V5MQAAAAAMYWRtaW5QdWJLZXkyCQEAAAALZ2V0QWRtaW5QdWIAAAABBQAAAA9rZXlBZG1pblB1YktleTIAAAAADGFkbWluUHViS2V5MwkBAAAAC2dldEFkbWluUHViAAAAAQUAAAAPa2V5QWRtaW5QdWJLZXkzAAAAABRhZG1pblB1YktleVN0YXJ0U3RvcAEAAAAgBM915WTQwQ9OZ7kfE2TEGg3qhCRCMX0zkF1AWAqdk0oAAAAAEmFkbWluUHViS2V5U3Rha2luZwEAAAAgBM915WTQwQ9OZ7kfE2TEGg3qhCRCMX0zkF1AWAqdk0oAAAAADXdhbGxldEFkZHJlc3MJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVTfPUuXiVhZ3hXg5FELVt09el+9tX+FIYkAAAAADXZvdGluZ0FkZHJlc3MJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVQaNn7fV6KdJ2lc/r/3JtTn+6HDaD4gyn8AAAAABFVTRE4BAAAAIG8ko8qrMNxSKZjoLGFa7lp/I03CLXW76Z2qVODS0AfBAAAAAAROU0JUAQAAACAfMcqomheEmok3YjT1FeDjokifQYVi6vQeAO1aIhqpJAAAAAAEU1dPUAEAAAAgEv+BIJFIbrNA9tN9ExhCV/1vofsy06rszWo/nWl9O/gAAAAABEVVUk4BAAAAIMQE2t9aD0a2OEs+TuVY8nwo/62rHJEwmJzJLDjfxJK/AAAAAA1zdGFraW5nQXNzZXRzCQAETAAAAAICAAAABVdBVkVTCQAETAAAAAIJAAJYAAAAAQUAAAAEVVNETgkABEwAAAACCQACWAAAAAEFAAAABE5TQlQJAARMAAAAAgkAAlgAAAABBQAAAARFVVJOBQAAAANuaWwAAAAAFnN0YWtpbmdVU0ROTlNCVEFkZHJlc3MJAQAAAAdBZGRyZXNzAAAAAQkAAlkAAAABCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQdAAAAAgUAAAAGb3JhY2xlBQAAABJrZXlVU0ROTlNCVEFkZHJlc3MCAAAAF25vIHVzZG4gc3Rha2luZyBhZGRyZXNzAAAAABJzdGFraW5nRVVSTkFkZHJlc3MJAQAAAAdBZGRyZXNzAAAAAQkAAlkAAAABCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQdAAAAAgUAAAAGb3JhY2xlBQAAAA5rZXlFVVJOQWRkcmVzcwIAAAAXbm8gZXVybiBzdGFraW5nIGFkZHJlc3MAAAAAFFVTRE5Ub1dhdmVzRXhjaGFuZ2VyCQEAAAAHQWRkcmVzcwAAAAEBAAAAGgFUypap/9cFMncn8kUuv9CKh+qtjirIv4W0AAAAABNVU0ROVG9OU0JURXhjaGFuZ2VyCQEAAAAHQWRkcmVzcwAAAAEBAAAAGgFUEWMEcf3cA2tBGebrexcf04K7NL8f1D3ZAAAAAApiYXNlUGVyaW9kCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAANdm90aW5nQWRkcmVzcwUAAAALa0Jhc2VQZXJpb2QCAAAAEUVtcHR5IGtCYXNlUGVyaW9kAAAAAAtzdGFydEhlaWdodAkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEGgAAAAIFAAAADXZvdGluZ0FkZHJlc3MFAAAADGtTdGFydEhlaWdodAIAAAASRW1wdHkga1N0YXJ0SGVpZ2h0AAAAAAxwZXJpb2RMZW5ndGgJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABBoAAAACBQAAAA12b3RpbmdBZGRyZXNzBQAAAA1rUGVyaW9kTGVuZ3RoAgAAABNFbXB0eSBrUGVyaW9kTGVuZ3RoAAAAABVmaXJzdEhhcnZlc3RFbmRQZXJpb2QJAABkAAAAAgkAAGQAAAACBQAAAApiYXNlUGVyaW9kCQAAaQAAAAIJAABlAAAAAgUAAAAGaGVpZ2h0BQAAAAtzdGFydEhlaWdodAUAAAAMcGVyaW9kTGVuZ3RoAAAAAAAAAAADAAAAAAZhY3RpdmUJAQAAABFAZXh0ck5hdGl2ZSgxMDUxKQAAAAIFAAAABHRoaXMFAAAACWtleUFjdGl2ZQAAAAALc3RyQXNzZXRJZEEJAQAAABFAZXh0ck5hdGl2ZSgxMDUzKQAAAAIFAAAABHRoaXMFAAAAC2tleUFzc2V0SWRBAAAAAAtzdHJBc3NldElkQgkBAAAAEUBleHRyTmF0aXZlKDEwNTMpAAAAAgUAAAAEdGhpcwUAAAALa2V5QXNzZXRJZEIAAAAACGFzc2V0SWRBAwkAAAAAAAACBQAAAAtzdHJBc3NldElkQQIAAAAFV0FWRVMFAAAABHVuaXQJAAJZAAAAAQUAAAALc3RyQXNzZXRJZEEAAAAACGFzc2V0SWRCAwkAAAAAAAACBQAAAAtzdHJBc3NldElkQgIAAAAFV0FWRVMFAAAABHVuaXQJAAJZAAAAAQUAAAALc3RyQXNzZXRJZEIAAAAACmFzc2V0TmFtZUEEAAAAByRtYXRjaDAFAAAACGFzc2V0SWRBAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAApCeXRlVmVjdG9yBAAAAAJpZAUAAAAHJG1hdGNoMAgJAQAAAAV2YWx1ZQAAAAEJAAPsAAAAAQUAAAACaWQAAAAEbmFtZQMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAEVW5pdAQAAAAFd2F2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AAABBQAAAAhhc3NldElkQgAAAAAKYXNzZXRJbml0QQkBAAAAEUBleHRyTmF0aXZlKDEwNTApAAAAAgUAAAAEdGhpcwUAAAAPa2V5QmFsYW5jZUluaXRBAAAAAAphc3NldEluaXRCCQEAAAARQGV4dHJOYXRpdmUoMTA1MCkAAAACBQAAAAR0aGlzBQAAAA9rZXlCYWxhbmNlSW5pdEIAAAAAEWF2YWlsYWJsZUJhbGFuY2VBCQAAZQAAAAIFAAAACGJhbGFuY2VBBQAAAA1zdGFrZWRBbW91bnRBAAAAABFhdmFpbGFibGVCYWxhbmNlQgkAAGUAAAACBQAAAAhiYWxhbmNlQgUAAAANc3Rha2VkQW1vdW50QgAAAAAZYWNjb3VudEJhbGFuY2VXaXRoU3Rha2VkQQkAAGQAAAACCQEAAAAOYWNjb3VudEJhbGFuY2UAAAABBQAAAAhhc3NldElkQQUAAAANc3Rha2VkQW1vdW50QQAAAAAZYWNjb3VudEJhbGFuY2VXaXRoU3Rha2VkQgkAAGQAAAACCQEAAAAOYWNjb3VudEJhbGFuY2UAAAABBQAAAAhhc3NldElkQgUAAAANc3Rha2VkQW1vdW50QgAAAAAQaGFzRW5vdWdoQmFsYW5jZQMJAABnAAAAAgUAAAAZYWNjb3VudEJhbGFuY2VXaXRoU3Rha2VkQQUAAAAIYmFsYW5jZUEJAABnAAAAAgUAAAAZYWNjb3VudEJhbGFuY2VXaXRoU3Rha2VkQgUAAAAIYmFsYW5jZUIHAQAAAAxnZXRBc3NldEluZm8AAAABAAAAB2Fzc2V0SWQEAAAAByRtYXRjaDAFAAAAB2Fzc2V0SWQDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAACkJ5dGVWZWN0b3IEAAAAAmlkBQAAAAckbWF0Y2gwBAAAAAhzdHJpbmdJZAkAAlgAAAABBQAAAAJpZAQAAAAEaW5mbwkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAD7AAAAAEFAAAAAmlkCQABLAAAAAIJAAEsAAAAAgIAAAAGQXNzZXQgBQAAAAhzdHJpbmdJZAIAAAAOIGRvZXNuJ3QgZXhpc3QJAAUVAAAAAwUAAAAIc3RyaW5nSWQIBQAAAARpbmZvAAAABG5hbWUIBQAAAARpbmZvAAAACGRlY2ltYWxzAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAARVbml0BAAAAAV3YXZlcwUAAAAHJG1hdGNoMAkABRUAAAADAgAAAAVXQVZFUwIAAAAFV0FWRVMAAAAAAAAAAAgJAAACAAAAAQIAAAALTWF0Y2ggZXJyb3IBAAAAFmdldEFzc2V0SW5mb0Zyb21TdHJpbmcAAAABAAAACGFzc2V0U3RyAwkAAAAAAAACBQAAAAhhc3NldFN0cgIAAAAFV0FWRVMJAAUVAAAAAwIAAAAFV0FWRVMCAAAABVdBVkVTAAAAAAAAAAAIBAAAAAhzdHJpbmdJZAUAAAAIYXNzZXRTdHIEAAAAAmlkCQACWQAAAAEFAAAACGFzc2V0U3RyBAAAAARpbmZvCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAPsAAAAAQUAAAACaWQJAAEsAAAAAgkAASwAAAACAgAAAAZBc3NldCAFAAAACHN0cmluZ0lkAgAAAA4gZG9lc24ndCBleGlzdAkABRUAAAADBQAAAAhzdHJpbmdJZAgFAAAABGluZm8AAAAEbmFtZQgFAAAABGluZm8AAAAIZGVjaW1hbHMBAAAAB3N1c3BlbmQAAAABAAAABWNhdXNlCQAETAAAAAIJAQAAAAxCb29sZWFuRW50cnkAAAACBQAAAAlrZXlBY3RpdmUHCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAACGtleUNhdXNlBQAAAAVjYXVzZQUAAAADbmlsAQAAABhjYWxjU3Rha2luZ0Z1bmNBbmRBZGRyZXMAAAACAAAABXN0YWtlAAAAB2Fzc2V0SWQDBQAAAAVzdGFrZQMJAAAAAAAAAgUAAAAHYXNzZXRJZAUAAAAEVVNETgkABRQAAAACAgAAAAxsb2NrTmV1dHJpbm8FAAAAFnN0YWtpbmdVU0ROTlNCVEFkZHJlc3MDCQAAAAAAAAIFAAAAB2Fzc2V0SWQFAAAABE5TQlQJAAUUAAAAAgIAAAAIbG9ja05zYnQFAAAAFnN0YWtpbmdVU0ROTlNCVEFkZHJlc3MJAAUUAAAAAgIAAAAMc3RhcnRTdGFraW5nBQAAABJzdGFraW5nRVVSTkFkZHJlc3MDCQAAAAAAAAIFAAAAB2Fzc2V0SWQFAAAABFVTRE4JAAUUAAAAAgIAAAAOdW5sb2NrTmV1dHJpbm8FAAAAFnN0YWtpbmdVU0ROTlNCVEFkZHJlc3MDCQAAAAAAAAIFAAAAB2Fzc2V0SWQFAAAABE5TQlQJAAUUAAAAAgIAAAAKdW5sb2NrTnNidAUAAAAWc3Rha2luZ1VTRE5OU0JUQWRkcmVzcwkABRQAAAACAgAAAAtzdG9wU3Rha2luZwUAAAASc3Rha2luZ0VVUk5BZGRyZXNzAQAAABFjYWxjU3Rha2luZ1BhcmFtcwAAAAMAAAAFc3Rha2UAAAAGYW1vdW50AAAAB2Fzc2V0SWQDBQAAAAVzdGFrZQQAAAALJHQwNjkyMjY5ODgJAQAAABhjYWxjU3Rha2luZ0Z1bmNBbmRBZGRyZXMAAAACBQAAAAVzdGFrZQUAAAAHYXNzZXRJZAQAAAAEY2FsbAgFAAAACyR0MDY5MjI2OTg4AAAAAl8xBAAAAAtzdGFraW5nQWRkcggFAAAACyR0MDY5MjI2OTg4AAAAAl8yCQAFFgAAAAQFAAAABGNhbGwFAAAAC3N0YWtpbmdBZGRyBQAAAANuaWwJAARMAAAAAgkBAAAAD0F0dGFjaGVkUGF5bWVudAAAAAIFAAAAB2Fzc2V0SWQFAAAABmFtb3VudAUAAAADbmlsBAAAAAskdDA3MDc0NzE0MAkBAAAAGGNhbGNTdGFraW5nRnVuY0FuZEFkZHJlcwAAAAIFAAAABXN0YWtlBQAAAAdhc3NldElkBAAAAARjYWxsCAUAAAALJHQwNzA3NDcxNDAAAAACXzEEAAAAC3N0YWtpbmdBZGRyCAUAAAALJHQwNzA3NDcxNDAAAAACXzIJAAUWAAAABAUAAAAEY2FsbAUAAAALc3Rha2luZ0FkZHIJAARMAAAAAgUAAAAGYW1vdW50CQAETAAAAAIJAAJYAAAAAQUAAAAHYXNzZXRJZAUAAAADbmlsBQAAAANuaWwBAAAADWNhbGN1bGF0ZUZlZXMAAAAEAAAACXBtdEFtb3VudAAAABJtaW5BbW91bnRUb1JlY2VpdmUAAAAJdG9rZW5Gcm9tAAAAB3Rva2VuVG8EAAAAEGFtb3VudFdpdGhvdXRGZWUJAABrAAAAAwUAAAAHdG9rZW5UbwUAAAAJcG10QW1vdW50CQAAZAAAAAIFAAAACXBtdEFtb3VudAUAAAAJdG9rZW5Gcm9tBAAAAA1hbW91bnRXaXRoRmVlCQAAawAAAAMFAAAAEGFtb3VudFdpdGhvdXRGZWUJAABlAAAAAgUAAAAYY29tbWlzc2lvblNjYWxlRGVsaW1pdGVyBQAAAApjb21taXNzaW9uBQAAABhjb21taXNzaW9uU2NhbGVEZWxpbWl0ZXIEAAAAEGdvdmVybmFuY2VSZXdhcmQJAABrAAAAAwUAAAAQYW1vdW50V2l0aG91dEZlZQUAAAAUY29tbWlzc2lvbkdvdmVybmFuY2UFAAAAGGNvbW1pc3Npb25TY2FsZURlbGltaXRlcgMJAABmAAAAAgUAAAASbWluQW1vdW50VG9SZWNlaXZlBQAAAA1hbW91bnRXaXRoRmVlCQAAAgAAAAEJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAHUNhbGN1bGF0ZWQgYW1vdW50IHRvIHJlY2VpdmUgCQABpAAAAAEFAAAADWFtb3VudFdpdGhGZWUCAAAAICBpcyBsZXNzIHRoYW4gc3BlY2lmaWVkIG1pbmltdW0gCQABpAAAAAEFAAAAEm1pbkFtb3VudFRvUmVjZWl2ZQkABRUAAAADBQAAABBhbW91bnRXaXRob3V0RmVlBQAAAA1hbW91bnRXaXRoRmVlBQAAABBnb3Zlcm5hbmNlUmV3YXJkAQAAABFzdXNwZW5kU3VzcGljaW91cwAAAAAJAQAAAAdzdXNwZW5kAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAjU3VzcGljaW91cyBzdGF0ZS4gQWN0dWFsIGJhbGFuY2VzOiAJAAGkAAAAAQUAAAAZYWNjb3VudEJhbGFuY2VXaXRoU3Rha2VkQQIAAAABIAUAAAAKYXNzZXROYW1lQQIAAAACLCAJAAGkAAAAAQUAAAAZYWNjb3VudEJhbGFuY2VXaXRoU3Rha2VkQgIAAAABIAUAAAAKYXNzZXROYW1lQgIAAAAJLiBTdGF0ZTogCQABpAAAAAEFAAAACGJhbGFuY2VBAgAAAAEgBQAAAAphc3NldE5hbWVBAgAAAAIsIAkAAaQA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CQEAAAALU3RyaW5nRW50cnkAAAACBQAAAAtrZXlBc3NldElkQQUAAAAOcG10U3RyQXNzZXRJZEEJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAALa2V5QXNzZXRJZEIFAAAADnBtdFN0ckFzc2V0SWRCCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAtrZXlCYWxhbmNlQQUAAAAKcG10QW1vdW50QQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAALa2V5QmFsYW5jZUIFAAAACnBtdEFtb3VudEIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAADWtleUNvbW1pc3Npb24FAAAACmNvbW1pc3Npb24JAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAG2tleUNvbW1pc3Npb25TY2FsZURlbGltaXRlcgUAAAAYY29tbWlzc2lvblNjYWxlRGVsaW1pdGVyCQAETAAAAAIFAAAACnNoYXJlSXNzdWUJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAAPa2V5U2hhcmVBc3NldElkCQACWAAAAAEFAAAADHNoYXJlSXNzdWVJZAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAATa2V5U2hhcmVBc3NldFN1cHBseQUAAAASc2hhcmVJbml0aWFsU3VwcGx5CQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAASc2hhcmVJbml0aWFsU3VwcGx5BQAAAAxzaGFyZUlzc3VlSWQFAAAAA25pbAMFAAAADGZpcnN0SGFydmVzdAkABE4AAAACBQAAAAliYXNlRW50cnkJAARMAAAAAgkBAAAADEJvb2xlYW5FbnRyeQAAAAIFAAAAD2tleUZpcnN0SGFydmVzdAUAAAAMZmlyc3RIYXJ2ZXN0CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABVrZXlGaXJzdEhhcnZlc3RIZWlnaHQJAABkAAAAAgUAAAALc3RhcnRIZWlnaHQJAABoAAAAAgUAAAAVZmlyc3RIYXJ2ZXN0RW5kUGVyaW9kBQAAAAxwZXJpb2RMZW5ndGgFAAAAA25pbAUAAAAJYmFzZUVudHJ5CQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAABaQEAAAARaW5pdFdpdGhJbml0UmF0aW8AAAAFAAAACWFtdEFzc2V0QQAAAAlhbXRBc3NldEIAAAALc3RyQXNzZXRJZEEAAAALc3RyQXNzZXRJZEIAAAAMZmlyc3RIYXJ2ZXN0BAAAAA0kdDAxMTIyMjExMzA5CQEAAAAWZ2V0QXNzZXRJbmZvRnJvbVN0cmluZwAAAAEFAAAAC3N0ckFzc2V0SWRBBAAAAA5wbXRTdHJBc3NldElkQQgFAAAADSR0MDExMjIyMTEzMDkAAAACXzEEAAAADXBtdEFzc2V0TmFtZUEIBQAAAA0kdDAxMTIyMjExMzA5AAAAAl8yBAAAAAxwbXREZWNpbWFsc0EIBQAAAA0kdDAxMTIyMjExMzA5AAAAAl8zBAAAAA0kdDAxMTMxNDExNDAxCQEAAAAWZ2V0QXNzZXRJbmZvRnJvbVN0cmluZwAAAAEFAAAAC3N0ckFzc2V0SWRCBAAAAA5wbXRTdHJBc3NldElkQggFAAAADSR0MDExMzE0MTE0MDEAAAACXzEEAAAADXBtdEFzc2V0TmFtZUIIBQAAAA0kdDAxMTMxNDExNDAxAAAAAl8yBAAAAAxwbXREZWNpbWFsc0IIBQAAAA0kdDAxMTMxNDExNDAxAAAAAl8zAwkBAAAAASEAAAABCQEAAAAPY29udGFpbnNFbGVtZW50AAAAAgkABEwAAAACBQAAAAxhZG1pblB1YktleTEJAARMAAAAAgUAAAAMYWRtaW5QdWJLZXkyCQAETAAAAAIFAAAADGFkbWluUHViS2V5MwkABEwAAAACBQAAABJhZG1pblB1YktleVN0YWtpbmcFAAAAA25pbAgFAAAAAWkAAAAPY2FsbGVyUHVibGljS2V5CQAAAgAAAAECAAAAIU9ubHkgYWRtaW4gY2FuIGNhbGwgdGhpcyBmdW5jdGlvbgMJAQAAAAlpc0RlZmluZWQAAAABCQAEGwAAAAIFAAAABHRoaXMFAAAACWtleUFjdGl2ZQkAAAIAAAABAgAAABZEQXBwIGlzIGFscmVhZHkgYWN0aXZlAwkAAAAAAAACBQAAAAtzdHJBc3NldElkQQUAAAALc3RyQXNzZXRJZEIJAAACAAAAAQIAAAAYQXNzZXRzIG11c3QgYmUgZGlmZmVyZW50BAAAAAlzaGFyZU5hbWUJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAAXMJAAEvAAAAAgUAAAANcG10QXNzZXROYW1lQQAAAAAAAAAABwIAAAABXwkAAS8AAAACBQAAAA1wbXRBc3NldE5hbWVCAAAAAAAAAAAHBAAAABBzaGFyZURlc2NyaXB0aW9uCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAiU2hhcmVUb2tlbiBvZiBTd29wRmkgcHJvdG9jb2wgZm9yIAUAAAANcG10QXNzZXROYW1lQQIAAAAFIGFuZCAFAAAADXBtdEFzc2V0TmFtZUICAAAADCBhdCBhZGRyZXNzIAkABCUAAAABBQAAAAR0aGlzBAAAAA1zaGFyZURlY2ltYWxzCQAAaQAAAAIJAABkAAAAAgUAAAAMcG10RGVjaW1hbHNBBQAAAAxwbXREZWNpbWFsc0IAAAAAAAAAAAIEAAAAEnNoYXJlSW5pdGlhbFN1cHBseQAAAAAAAAAAAAQAAAAKc2hhcmVJc3N1ZQkABEIAAAAFBQAAAAlzaGFyZU5hbWUFAAAAEHNoYXJlRGVzY3JpcHRpb24FAAAAEnNoYXJlSW5pdGlhbFN1cHBseQUAAAANc2hhcmVEZWNpbWFscwYEAAAADHNoYXJlSXNzdWVJZAkABDgAAAABBQAAAApzaGFyZUlzc3VlBAAAAAliYXNlRW50cnkJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAAKa2V5VmVyc2lvbgUAAAAHdmVyc2lvbgkABEwAAAACCQEAAAAMQm9vbGVhbkVudHJ5AAAAAgUAAAAJa2V5QWN0aXZlBgkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAAAtrZXlBc3NldElkQQUAAAAOcG10U3RyQXNzZXRJZEEJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAALa2V5QXNzZXRJZEIFAAAADnBtdFN0ckFzc2V0SWRCCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAA9rZXlCYWxhbmNlSW5pdEEFAAAACWFtdEFzc2V0QQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAPa2V5QmFsYW5jZUluaXRCBQAAAAlhbXRBc3NldEIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAC2tleUJhbGFuY2VBAAAAAAAAAAAACQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAtrZXlCYWxhbmNlQgAAAAAAAAAAAAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAANa2V5Q29tbWlzc2lvbgUAAAAKY29tbWlzc2lvbgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAba2V5Q29tbWlzc2lvblNjYWxlRGVsaW1pdGVyBQAAABhjb21taXNzaW9uU2NhbGVEZWxpbWl0ZXIJAARMAAAAAgUAAAAKc2hhcmVJc3N1ZQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAAA9rZXlTaGFyZUFzc2V0SWQJAAJYAAAAAQUAAAAMc2hhcmVJc3N1ZUlkCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABNrZXlTaGFyZUFzc2V0U3VwcGx5BQAAABJzaGFyZUluaXRpYWxTdXBwbHkFAAAAA25pbAMFAAAADGZpcnN0SGFydmVzdAkABE4AAAACBQAAAAliYXNlRW50cnkJAARMAAAAAgkBAAAADEJvb2xlYW5FbnRyeQAAAAIFAAAAD2tleUZpcnN0SGFydmVzdAUAAAAMZmlyc3RIYXJ2ZXN0CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABVrZXlGaXJzdEhhcnZlc3RIZWlnaHQJAABkAAAAAgUAAAALc3RhcnRIZWlnaHQJAABoAAAAAgUAAAAVZmlyc3RIYXJ2ZXN0RW5kUGVyaW9kBQAAAAxwZXJpb2RMZW5ndGgFAAAAA25pbAUAAAAJYmFzZUVudHJ5AAAAAWkBAAAAGGtlZXBMaW1pdEZvckZpcnN0SGFydmVzdAAAAAEAAAAKc2hhcmVMaW1pdAkBAAAAC3ZhbHVlT3JFbHNl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c2NhbGVWYWx1ZTMJAABkAAAAAgUAAAAac2xpcHBhZ2VUb2xlcmFuY2VEZWxpbWl0ZXIFAAAAEXNsaXBwYWdlVG9sZXJhbmNlBQAAABpzbGlwcGFnZVRvbGVyYW5jZURlbGltaXRlcgkAAAIAAAABAgAAAD1JbmNvcnJlY3QgYXNzZXRzIGFtb3VudDogYW1vdW50cyBtdXN0IGhhdmUgdGhlIGNvbnRyYWN0IHJhdGlvAwkAAAAAAAACBQAAABVzaGFyZVRva2VuVG9QYXlBbW91bnQAAAAAAAAAAAAJAAACAAAAAQIAAAAdVG9vIHNtYWxsIGFtb3VudCB0byByZXBsZW5pc2gDCQEAAAABIQAAAAEFAAAAEGhhc0Vub3VnaEJhbGFuY2UJAAROAAAAAgkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIFAAAACnBtdEFtb3VudEEFAAAAC3BtdEFzc2V0SWRBCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAAKcG10QW1vdW50QgUAAAALcG10QXNzZXRJZEIFAAAAA25pbAkBAAAAEXN1c3BlbmRTdXNwaWNpb3VzAAAAAAQAAAAGc3Rha2UxAwkBAAAAD2NvbnRhaW5zRWxlbWVudAAAAAIFAAAADXN0YWtpbmdBc3NldHMFAAAADnBtdFN0ckFzc2V0SWRBCQAD/AAAAAQFAAAABHRoaXMCAAAADHN0YWtlVW5zdGFrZQkABEwAAAACBgkABEwAAAACBQAAAApwbXRBbW91bnRBCQAETAAAAAIFAAAADnBtdFN0ckFzc2V0SWRBBQAAAANuaWwFAAAAA25pbAAAAAAAAAAAAAMJAAAAAAAAAgUAAAAGc3Rha2UxBQAAAAZzdGFrZTEEAAAABnN0YWtlMgMJAQAAAA9jb250YWluc0VsZW1lbnQAAAACBQAAAA1zdGFraW5nQXNzZXRzBQAAAA5wbXRTdHJBc3NldElkQgkAA/wAAAAEBQAAAAR0aGlzAgAAAAxzdGFrZVVuc3Rha2UJAARMAAAAAgYJAARMAAAAAgUAAAAKcG10QW1vdW50QgkABEwAAAACBQAAAA5wbXRTdHJBc3NldElkQgUAAAADbmlsBQAA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CQAAAAAAAAIFAAAACGJhbGFuY2VCAAAAAAAAAAAACQAAAgAAAAECAAAAIENhbid0IGV4Y2hhbmdlIHdpdGggemVybyBiYWxhbmNlAwkAAGcAAAACAAAAAAAAAAAABQAAABJtaW5BbW91bnRUb1JlY2VpdmUJAAACAAAAAQkAASwAAAACAgAAADRNaW5pbWFsIGFtb3VudCB0byByZWNlaXZlIG11c3QgYmUgcG9zaXRpdmUuIEFjdHVhbDogCQABpAAAAAEFAAAAEm1pbkFtb3VudFRvUmVjZWl2ZQMJAQAAAAIhPQAAAAIJAAGQAAAAAQgFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAEJAAACAAAAAQIAAAAdT25lIGF0dGFjaGVkIHBheW1lbnQgZXhwZWN0ZWQDCQEAAAABIQAAAAEFAAAAEGhhc0Vub3VnaEJhbGFuY2UJAAROAAAAAgkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIFAAAACXBtdEFtb3VudAUAAAAKcG10QXNzZXRJZAUAAAADbmlsCQEAAAARc3VzcGVuZFN1c3BpY2lvdXMAAAAAAwkAAAAAAAACBQAAAApwbXRBc3NldElkBQAAAAhhc3NldElkQQQAAAALYXNzZXRJZFNlbmQFAAAACGFzc2V0SWRCBAAAAA0kdDAxODg0NTE4OTY3CQEAAAANY2FsY3VsYXRlRmVlcwAAAAQFAAAACXBtdEFtb3VudAUAAAASbWluQW1vdW50VG9SZWNlaXZlBQAAAAhiYWxhbmNlQQUAAAAIYmFsYW5jZUIEAAAAEGFtb3VudFdpdGhvdXRGZWUIBQAAAA0kdDAxODg0NTE4OTY3AAAAAl8xBAAAAA1hbW91bnRXaXRoRmVlCAUAAAANJHQwMTg4NDUxODk2NwAAAAJfMgQAAAAQZ292ZXJuYW5jZVJld2FyZAgFAAAADSR0MDE4ODQ1MTg5NjcAAAACXzMEAAAAC25ld0JhbGFuY2VBCQAAZAAAAAIFAAAACGJhbGFuY2VBBQAAAAlwbXRBbW91bnQEAAAAC25ld0JhbGFuY2VCCQAAZQAAAAIJAABlAAAAAgUAAAAIYmFsYW5jZUIFAAAADWFtb3VudFdpdGhGZWUFAAAAEGdvdmVybmFuY2VSZXdhcmQEAAAABnN0YWtlMQMJAQAAAA9jb250YWluc0VsZW1lbnQAAAACBQAAAA1zdGFraW5nQXNzZXRzBQAAAAtzdHJBc3NldElkQQkAA/wAAAAEBQAAAAR0aGlzAgAAAAxzdGFrZVVuc3Rha2UJAARMAAAAAgYJAARMAAAAAgUAAAAJcG10QW1vdW50CQAETAAAAAIFAAAAC3N0ckFzc2V0SWRBBQAAAANuaWwFAAAAA25pbAAAAAAAAAAAAAMJAAAAAAAAAgUAAAAGc3Rha2UxBQAAAAZzdGFrZTEEAAAABnN0YWtlMgMJAQAAAA9jb250YWluc0VsZW1lbnQAAAACBQAAAA1zdGFraW5nQXNzZXRzBQAAAAtzdHJBc3NldElkQgkAA/wAAAAEBQAAAAR0aGlzAgAAAAxzdGFrZVVuc3Rha2UJAARMAAAAAgcJAARMAAAAAgkAAGQAAAACBQAAAA1hbW91bnRXaXRoRmVlBQAAABBnb3Zlcm5hbmNlUmV3YXJkCQAETAAAAAIFAAAAC3N0ckFzc2V0SWRCBQAAAANuaWwFAAAAA25pbAAAAAAAAAAAAAMJAAAAAAAAAgUAAAAGc3Rha2UyBQAAAAZzdGFrZTIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAC2tleUJhbGFuY2VBBQAAAAtuZXdCYWxhbmNlQQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAALa2V5QmFsYW5jZUIFAAAAC25ld0JhbGFuY2VCCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAANYW1vdW50V2l0aEZlZQUAAAALYXNzZXRJZFNlbmQJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwUAAAANd2FsbGV0QWRkcmVzcwUAAAAQZ292ZXJuYW5jZVJld2FyZAUAAAALYXNzZXRJZFNlbmQFAAAAA25pbAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAwkAAAAAAAACBQAAAApwbXRBc3NldElkBQAAAAhhc3NldElkQgQAAAALYXNzZXRJZFNlbmQFAAAACGFzc2V0SWRBBAAAAA0kdDAxOTkyMjIwMDQ0CQEAAAANY2FsY3VsYXRlRmVlcwAAAAQFAAAACXBtdEFtb3VudAUAAAASbWluQW1vdW50VG9SZWNlaXZlBQAAAAhiYWxhbmNlQgUAAAAIYmFsYW5jZUEEAAAAEGFtb3VudFdpdGhvdXRGZWUIBQAAAA0kdDAxOTkyMjIwMDQ0AAAAAl8xBAAAAA1hbW91bnRXaXRoRmVlCAUAAAANJHQwMTk5MjIyMDA0NAAAAAJfMgQAAAAQZ292ZXJuYW5jZVJld2FyZAgFAAAADSR0MDE5OTIyMjAwNDQAAAACXzMEAAAAC25ld0JhbGFuY2VBCQAAZQAAAAIJAABlAAAAAgUAAAAIYmFsYW5jZUEFAAAADWFtb3VudFdpdGhGZWUFAAAAEGdvdmVybmFuY2VSZXdhcmQEAAAAC25ld0JhbGFuY2VCCQAAZAAAAAIFAAAACGJhbGFuY2VCBQAAAAlwbXRBbW91bnQEAAAABnN0YWtlMQMJAQAAAA9jb250YWluc0VsZW1lbnQAAAACBQAAAA1zdGFraW5nQXNzZXRzBQAAAAtzdHJBc3NldElkQQkAA/wAAAAEBQAAAAR0aGlzAgAAAAxzdGFrZVVuc3Rha2UJAARMAAAAAgcJAARMAAAAAgkAAGQAAAACBQAAAA1hbW91bnRXaXRoRmVlBQAAABBnb3Zlcm5hbmNlUmV3YXJkCQAETAAAAAIFAAAAC3N0ckFzc2V0SWRBBQAAAANuaWwFAAAAA25pbAAAAAAAAAAAAAMJAAAAAAAAAgUAAAAGc3Rha2UxBQAAAAZzdGFrZTEEAAAABnN0YWtlMgMJAQAAAA9jb250YWluc0VsZW1lbnQAAAACBQAAAA1zdGFraW5nQXNzZXRzBQAAAAtzdHJBc3NldElkQgkAA/wAAAAEBQAAAAR0aGlzAgAAAAxzdGFrZVVuc3Rha2UJAARMAAAAAgYJAARMAAAAAgUAAAAJcG10QW1vdW50CQAETAAAAAIFAAAAC3N0ckFzc2V0SWRCBQAAAANuaWwFAAAAA25pbAAAAAAAAAAAAAMJAAAAAAAAAgUAAAAGc3Rha2UyBQAAAAZzdGFrZTIJAARMAAAAAgkBAAAADEludGVnZXJFbnRy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LgkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAABaQEAAAAMc3Rha2VVbnN0YWtlAAAAAwAAAAVzdGFrZQAAAAZhbW91bnQAAAANYXNzZXRJZFN0cmluZwMJAQAAAAIhPQAAAAIIBQAAAAFpAAAABmNhbGxlcgUAAAAEdGhpcwkAAAIAAAABAgAAAC1Pbmx5IGNvbnRyYWN0IGl0c2VsZiBjYW4gaW52b2tlIHRoaXMgZnVuY3Rpb24DCQAAAAAAAAIFAAAADWFzc2V0SWRTdHJpbmcCAAAABVdBVkVTBAAAAARwb29sCQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQdAAAAAgUAAAAGb3JhY2xlBQAAAA5rZXlMZWFzaW5nUG9vbAIAAAAZTm8gbGVhc2luZyBwb29sIGluIG9yYWNsZQQAAAAJbGVhc2luZ0lkCQAEHAAAAAIFAAAABHRoaXMFAAAADGtleUxlYXNpbmdJZAQAAAANbGVhc2luZ0Ftb3VudAkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAR0aGlzBQAAABBrZXlMZWFzaW5nQW1vdW50AAAAAAAAAAAABAAAAA5uZXdMZWFzZUFtb3VudAMFAAAABXN0YWtlCQAAZAAAAAIFAAAADWxlYXNpbmdBbW91bnQFAAAABmFtb3VudAkAAGUAAAACBQAAAA1sZWFzaW5nQW1vdW50BQAAAAZhbW91bnQEAAAACG5ld0xlYXNlCQAERAAAAAIFAAAABHBvb2wFAAAADm5ld0xlYXNlQW1vdW50BAAAAApuZXdMZWFzZUlkCQAEOQAAAAEFAAAACG5ld0xlYXNlBAAAAAhiYXNlRXRyeQkABEwAAAACBQAAAAhuZXdMZWFzZQkABEwAAAACCQEAAAALQmluYXJ5RW50cnkAAAACBQAAAAxrZXlMZWFzaW5nSWQFAAAACm5ld0xlYXNlSWQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAEGtleUxlYXNpbmdBbW91bnQFAAAADm5ld0xlYXNlQW1vdW50BQAAAANuaWwEAAAAByRtYXRjaDAFAAAACWxlYXNpbmdJ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", "height": 1884285, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 8oXaSc615186C2rWMYrdUxNTdtPoFooVjmf23SUfiVS9 Next: F8nF3fqiPxFb8dqYxXqkZLHnqG3eGug9kpPvQTUBEiCQ Diff:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let version = "2.0.0"
4+let version = "1.0.0"
55
6-let kVersion = "version"
6+let keyVersion = "version"
77
8-let kActive = "active"
8+let keyActive = "active"
99
10-let kAssetIdA = "A_asset_id"
10+let keyAssetIdA = "A_asset_id"
1111
12-let kAssetIdB = "B_asset_id"
12+let keyAssetIdB = "B_asset_id"
1313
14-let kBalanceA = "A_asset_balance"
14+let keyBalanceA = "A_asset_balance"
1515
16-let kBalanceB = "B_asset_balance"
16+let keyBalanceB = "B_asset_balance"
1717
18-let kShareAssetId = "share_asset_id"
18+let keyBalanceInitA = "A_asset_init"
1919
20-let kShareAssetSupply = "share_asset_supply"
20+let keyBalanceInitB = "B_asset_init"
2121
22-let kFee = "commission"
22+let keyShareAssetId = "share_asset_id"
2323
24-let kFeeScaleDelimiter = "commission_scale_delimiter"
24+let keyShareAssetSupply = "share_asset_supply"
2525
26-let kInvariant = "invariant"
26+let keyCommission = "commission"
2727
28-let kCause = "shutdown_cause"
28+let keyCommissionScaleDelimiter = "commission_scale_delimiter"
29+
30+let keyCause = "shutdown_cause"
31+
32+let keyFirstHarvest = "first_harvest"
33+
34+let keyFirstHarvestHeight = "first_harvest_height"
35+
36+let kShareLimit = "share_limit_on_first_harvest"
37+
38+let kBasePeriod = "base_period"
39+
40+let kPeriodLength = "period_length"
41+
42+let kStartHeight = "start_height"
43+
44+let kFirstHarvestHeight = "first_harvest_height"
2945
3046 let keyUSDNNSBTAddress = "staking_usdnnsbt_address"
3147
3248 let keyEURNAddress = "staking_eurn_address"
49+
50+let keyLeasingPool = "leasing_address"
51+
52+let keyLeasingAmount = "leasing_amount"
53+
54+let keyLeasingId = "leasing_id"
3355
3456 let keyAdminPubKey1 = "admin_pub_1"
3557
3658 let keyAdminPubKey2 = "admin_pub_2"
3759
3860 let keyAdminPubKey3 = "admin_pub_3"
39-
40-let USDNToWavesExchanger = Address(base58'3N8PGkzXhbtTvEwEQTtE2xiTJmsDEQ9XfoZ')
4161
4262 let oracle = Address(base58'3NBBWfzZtZtszaXbitTKnrB2xXwv26Bn7H9')
4363
5575
5676 let adminPubKey3 = getAdminPub(keyAdminPubKey3)
5777
58-let admStartStop = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
78+let adminPubKeyStartStop = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
5979
60-let admStaking = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
80+let adminPubKeyStaking = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
6181
6282 let walletAddress = Address(base58'3NAGTtZz6WpupSN89NZD5rMZwwziZEg4Kx4')
6383
84+let votingAddress = Address(base58'3MrJgdL1GniipErHy44YF9idzLaUL2iX5DQ')
85+
6486 let USDN = base58'8UrfDVd5GreeUwm7uPk7eYz1eMv376kzR52C6sANPkwS'
87+
88+let NSBT = base58'36mg8NZTaFRDygiVwb8uBnLR51hetJruUCZcxhaVcHj9'
89+
90+let SWOP = base58'2HAJrwa8q4SxBx9cHYaBTQdBjdk5wwqdof7ccpAx2uhZ'
6591
6692 let EURN = base58'ECBCkHS68DckpBrzLeoRgYbFg7sCVqR176mPqbXsj9pA'
6793
68-let stakingAssets = [toBase58String(USDN), toBase58String(EURN)]
94+let stakingAssets = ["WAVES", toBase58String(USDN), toBase58String(NSBT), toBase58String(EURN)]
6995
7096 let stakingUSDNNSBTAddress = Address(fromBase58String(valueOrErrorMessage(getString(oracle, keyUSDNNSBTAddress), "no usdn staking address")))
7197
72-let stakingEURNAddress = Address(fromBase58String(valueOrErrorMessage(getString(oracle, keyEURNAddress), "no usdn staking address")))
98+let stakingEURNAddress = Address(fromBase58String(valueOrErrorMessage(getString(oracle, keyEURNAddress), "no eurn staking address")))
7399
74-let isActive = getBooleanValue(this, kActive)
100+let USDNToWavesExchanger = Address(base58'3N8PGkzXhbtTvEwEQTtE2xiTJmsDEQ9XfoZ')
75101
76-let strAssetIdA = getStringValue(this, kAssetIdA)
102+let USDNToNSBTExchanger = Address(base58'3MqW1t2cxdYy2emEMk3YtZkRwQPhHaTfWRe')
77103
78-let strAssetIdB = getStringValue(this, kAssetIdB)
104+let basePeriod = valueOrErrorMessage(getInteger(votingAddress, kBasePeriod), "Empty kBasePeriod")
105+
106+let startHeight = valueOrErrorMessage(getInteger(votingAddress, kStartHeight), "Empty kStartHeight")
107+
108+let periodLength = valueOrErrorMessage(getInteger(votingAddress, kPeriodLength), "Empty kPeriodLength")
109+
110+let firstHarvestEndPeriod = ((basePeriod + ((height - startHeight) / periodLength)) + 3)
111+
112+let active = getBooleanValue(this, keyActive)
113+
114+let strAssetIdA = getStringValue(this, keyAssetIdA)
115+
116+let strAssetIdB = getStringValue(this, keyAssetIdB)
79117
80118 let assetIdA = if ((strAssetIdA == "WAVES"))
81119 then unit
103141 throw("Match error")
104142 }
105143
106-let balanceA = getIntegerValue(this, kBalanceA)
144+let balanceA = getIntegerValue(this, keyBalanceA)
107145
108-let balanceB = getIntegerValue(this, kBalanceB)
146+let balanceB = getIntegerValue(this, keyBalanceB)
109147
110-let shareAssetId = fromBase58String(getStringValue(this, kShareAssetId))
148+let shareAssetId = fromBase58String(getStringValue(this, keyShareAssetId))
111149
112-let shareAssetSupply = getIntegerValue(this, kShareAssetSupply)
150+let shareAssetSupply = getIntegerValue(this, keyShareAssetSupply)
113151
114-let invariant = getIntegerValue(this, kInvariant)
152+let commission = 3000
115153
116-let fee = 500
154+let commissionGovernance = 1200
117155
118-let feeGovernance = 200
156+let commissionScaleDelimiter = 1000000
119157
120-let feeScale6 = 1000000
158+let scaleValue3 = 1000
121159
122-let scale3 = 1000
160+let scaleValue8 = 100000000
123161
124-let scale8 = 100000000
162+let slippageToleranceDelimiter = 1000
125163
126-let scale12 = 1000000000000
127-
128-let slippageScale3 = 1000
129-
130-let digits8 = 8
131-
132-let dAppThreshold = 50
133-
134-let dAppThresholdScale2 = 100
135-
136-let exchangeRatioLimitMin = 90000000
137-
138-let exchangeRatioLimitMax = 110000000
139-
140-let alpha = 50
141-
142-let alphaDigits = 2
143-
144-let beta = 46000000
164+let scaleValue8Digits = 8
145165
146166 func accountBalance (assetId) = match assetId {
147167 case id: ByteVector =>
156176 func stakedAmount (assetId) = {
157177 let stakedAmountCalculated = match assetId {
158178 case aId: ByteVector =>
159- if ((aId == USDN))
179+ if (if ((aId == USDN))
180+ then true
181+ else (aId == NSBT))
160182 then getInteger(stakingUSDNNSBTAddress, ((("rpd_balance_" + toBase58String(aId)) + "_") + toString(this)))
161183 else if ((aId == EURN))
162184 then getInteger(stakingEURNAddress, ((("%s%s%s__stakingBalance__" + toBase58String(aId)) + "__") + toString(this)))
163185 else 0
164186 case _: Unit =>
165- 0
187+ valueOrElse(getInteger(this, keyLeasingAmount), 0)
166188 case _ =>
167189 throw("Match error")
168190 }
179201
180202 let stakedAmountB = stakedAmount(assetIdB)
181203
204+let assetInitA = getIntegerValue(this, keyBalanceInitA)
205+
206+let assetInitB = getIntegerValue(this, keyBalanceInitB)
207+
182208 let availableBalanceA = (balanceA - stakedAmountA)
183209
184210 let availableBalanceB = (balanceB - stakedAmountB)
190216 let hasEnoughBalance = if ((accountBalanceWithStakedA >= balanceA))
191217 then (accountBalanceWithStakedB >= balanceB)
192218 else false
193-
194-func skewness (x,y) = (((fraction(scale12, x, y) + fraction(scale12, y, x)) / 2) / 10000)
195-
196-
197-func invariantCalc (x,y) = {
198- let sk = skewness(x, y)
199- (fraction((x + y), scale8, pow(sk, digits8, alpha, alphaDigits, digits8, CEILING)) + (2 * fraction(pow(fraction(x, y, scale8), 0, 5, 1, (digits8 / 2), DOWN), pow((sk - beta), digits8, alpha, alphaDigits, digits8, DOWN), scale8)))
200- }
201-
202-
203-func calculateSendAmount (amountToSendEstimated,minTokenReceiveAmount,tokenReceiveAmount,tokenId) = {
204- let slippageValue = (scale8 - ((scale8 * 1) / 10000000))
205- let deltaBetweenMaxAndMinSendValue = (amountToSendEstimated - minTokenReceiveAmount)
206- let x = (balanceA + tokenReceiveAmount)
207- let y = (balanceB + tokenReceiveAmount)
208- let invariantNew = if ((tokenId == assetIdA))
209- then invariantCalc(x, (balanceB - amountToSendEstimated))
210- else if ((tokenId == assetIdB))
211- then invariantCalc((balanceA - amountToSendEstimated), y)
212- else throw("Wrong asset in payment")
213- let invariantEstimatedRatio = fraction(scale8, invariant, invariantNew)
214- func getStepAmount (acc,step) = if ((acc == -1))
215- then {
216- let amountToSend = (amountToSendEstimated - ((step * deltaBetweenMaxAndMinSendValue) / 5))
217- let stepInvariant = if ((tokenId == assetIdA))
218- then invariantCalc(x, (balanceB - amountToSend))
219- else invariantCalc((balanceA - amountToSend), y)
220- if ((stepInvariant > invariant))
221- then amountToSend
222- else -1
223- }
224- else acc
225-
226- let stepAmount = {
227- let $l = [1, 2, 3, 4, 5]
228- let $s = size($l)
229- let $acc0 = -1
230- func $f0_1 ($a,$i) = if (($i >= $s))
231- then $a
232- else getStepAmount($a, $l[$i])
233-
234- func $f0_2 ($a,$i) = if (($i >= $s))
235- then $a
236- else throw("List size exceeds 5")
237-
238- $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
239- }
240- if ((0 > stepAmount))
241- then throw("something went wrong while working with amountToSend")
242- else if (if ((invariantEstimatedRatio > slippageValue))
243- then (invariantNew > invariant)
244- else false)
245- then amountToSendEstimated
246- else stepAmount
247- }
248-
249219
250220 func getAssetInfo (assetId) = match assetId {
251221 case id: ByteVector =>
259229 }
260230
261231
262-func suspend (cause) = [BooleanEntry(kActive, false), StringEntry(kCause, cause)]
232+func getAssetInfoFromString (assetStr) = if ((assetStr == "WAVES"))
233+ then $Tuple3("WAVES", "WAVES", 8)
234+ else {
235+ let stringId = assetStr
236+ let id = fromBase58String(assetStr)
237+ let info = valueOrErrorMessage(assetInfo(id), (("Asset " + stringId) + " doesn't exist"))
238+ $Tuple3(stringId, info.name, info.decimals)
239+ }
263240
264241
265-func throwIsActive () = throw("DApp is already active")
266-
267-
268-func throwIsInactive () = throw("DApp is inactive at this moment")
269-
270-
271-func throwOnlyAdmin () = throw("Only admin can call this function")
272-
273-
274-func throwAssets () = throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
275-
276-
277-func throwThreshold (threshold,amountA,amountB) = throw(((((((((("New balance in assets of the DApp is less than threshold " + toString(threshold)) + ": ") + toString(amountA)) + " ") + assetNameA) + ", ") + toString(amountB)) + " ") + assetNameB))
278-
279-
280-func suspendSuspicious () = suspend(((((((((((((((("Suspicious state. Actual balances: " + toString(balanceA)) + " ") + assetNameA) + ", ") + toString(balanceB)) + " ") + assetNameB) + ". State: ") + toString(accountBalance(assetIdA))) + " ") + assetNameA) + ", ") + toString(accountBalance(assetIdB))) + " ") + assetNameB))
242+func suspend (cause) = [BooleanEntry(keyActive, false), StringEntry(keyCause, cause)]
281243
282244
283245 func calcStakingFuncAndAddres (stake,assetId) = if (stake)
284246 then if ((assetId == USDN))
285247 then $Tuple2("lockNeutrino", stakingUSDNNSBTAddress)
286- else $Tuple2("startStaking", stakingEURNAddress)
248+ else if ((assetId == NSBT))
249+ then $Tuple2("lockNsbt", stakingUSDNNSBTAddress)
250+ else $Tuple2("startStaking", stakingEURNAddress)
287251 else if ((assetId == USDN))
288252 then $Tuple2("unlockNeutrino", stakingUSDNNSBTAddress)
289- else $Tuple2("stopStaking", stakingEURNAddress)
253+ else if ((assetId == NSBT))
254+ then $Tuple2("unlockNsbt", stakingUSDNNSBTAddress)
255+ else $Tuple2("stopStaking", stakingEURNAddress)
290256
291257
292258 func calcStakingParams (stake,amount,assetId) = if (stake)
293259 then {
294- let $t087598825 = calcStakingFuncAndAddres(stake, assetId)
295- let call = $t087598825._1
296- let stakingAddr = $t087598825._2
260+ let $t069226988 = calcStakingFuncAndAddres(stake, assetId)
261+ let call = $t069226988._1
262+ let stakingAddr = $t069226988._2
297263 $Tuple4(call, stakingAddr, nil, [AttachedPayment(assetId, amount)])
298264 }
299265 else {
300- let $t089118977 = calcStakingFuncAndAddres(stake, assetId)
301- let call = $t089118977._1
302- let stakingAddr = $t089118977._2
266+ let $t070747140 = calcStakingFuncAndAddres(stake, assetId)
267+ let call = $t070747140._1
268+ let stakingAddr = $t070747140._2
303269 $Tuple4(call, stakingAddr, [amount, toBase58String(assetId)], nil)
304270 }
305271
306272
273+func calculateFees (pmtAmount,minAmountToReceive,tokenFrom,tokenTo) = {
274+ let amountWithoutFee = fraction(tokenTo, pmtAmount, (pmtAmount + tokenFrom))
275+ let amountWithFee = fraction(amountWithoutFee, (commissionScaleDelimiter - commission), commissionScaleDelimiter)
276+ let governanceReward = fraction(amountWithoutFee, commissionGovernance, commissionScaleDelimiter)
277+ if ((minAmountToReceive > amountWithFee))
278+ then throw(((("Calculated amount to receive " + toString(amountWithFee)) + " is less than specified minimum ") + toString(minAmountToReceive)))
279+ else $Tuple3(amountWithoutFee, amountWithFee, governanceReward)
280+ }
281+
282+
283+func suspendSuspicious () = suspend(((((((((((((((("Suspicious state. Actual balances: " + toString(accountBalanceWithStakedA)) + " ") + assetNameA) + ", ") + toString(accountBalanceWithStakedB)) + " ") + assetNameB) + ". State: ") + toString(balanceA)) + " ") + assetNameA) + ", ") + toString(balanceB)) + " ") + assetNameB))
284+
285+
286+func isActive () = if (active)
287+ then unit
288+ else throw("DApp is inactive at this moment")
289+
290+
307291 @Callable(i)
308-func init () = {
309- let $t090829159 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
310- let pmtAmountA = $t090829159._1
311- let pmtAssetIdA = $t090829159._2
312- let $t091649241 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
313- let pmtAmountB = $t091649241._1
314- let pmtAssetIdB = $t091649241._2
315- let $t092469323 = getAssetInfo(pmtAssetIdA)
316- let pmtStrAssetIdA = $t092469323._1
317- let pmtAssetNameA = $t092469323._2
318- let pmtDecimalsA = $t092469323._3
319- let $t093289405 = getAssetInfo(pmtAssetIdB)
320- let pmtStrAssetIdB = $t093289405._1
321- let pmtAssetNameB = $t093289405._2
322- let pmtDecimalsB = $t093289405._3
323- if (isDefined(getBoolean(this, kActive)))
324- then throwIsActive()
325- else if ((pmtAssetIdA == pmtAssetIdB))
326- then throw("Assets must be different")
327- else {
328- let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
329- let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
330- let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
331- let shareInitialSupply = fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN), pow(10, 0, shareDecimals, 0, 0, DOWN))
332- let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
333- let shareIssueId = calculateAssetId(shareIssue)
334- let invariantCalculated = invariantCalc(pmtAmountA, pmtAmountB)
335- let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
336- then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
337- else 0
338- if ((stake1 == stake1))
339- then {
340- let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
341- then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
342- else 0
343- if ((stake2 == stake2))
344- then [StringEntry(kVersion, version), BooleanEntry(kActive, true), StringEntry(kAssetIdA, pmtStrAssetIdA), StringEntry(kAssetIdB, pmtStrAssetIdB), IntegerEntry(kBalanceA, pmtAmountA), IntegerEntry(kBalanceB, pmtAmountB), IntegerEntry(kInvariant, invariantCalculated), IntegerEntry(kFee, fee), IntegerEntry(kFeeScaleDelimiter, feeScale6), shareIssue, StringEntry(kShareAssetId, toBase58String(shareIssueId)), IntegerEntry(kShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareIssueId)]
345- else throw("Strict value is not equal to itself.")
346- }
347- else throw("Strict value is not equal to itself.")
348- }
292+func init (firstHarvest) = {
293+ let $t083108387 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
294+ let pmtAmountA = $t083108387._1
295+ let pmtAssetIdA = $t083108387._2
296+ let $t083928469 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
297+ let pmtAmountB = $t083928469._1
298+ let pmtAssetIdB = $t083928469._2
299+ let $t084748551 = getAssetInfo(pmtAssetIdA)
300+ let pmtStrAssetIdA = $t084748551._1
301+ let pmtAssetNameA = $t084748551._2
302+ let pmtDecimalsA = $t084748551._3
303+ let $t085568633 = getAssetInfo(pmtAssetIdB)
304+ let pmtStrAssetIdB = $t085568633._1
305+ let pmtAssetNameB = $t085568633._2
306+ let pmtDecimalsB = $t085568633._3
307+ if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
308+ then throw("Only admin can call this function")
309+ else if (isDefined(getBoolean(this, keyActive)))
310+ then throw("DApp is already active")
311+ else if ((pmtAssetIdA == pmtAssetIdB))
312+ then throw("Assets must be different")
313+ else {
314+ let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
315+ let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
316+ let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
317+ let arg1 = pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN)
318+ let arg2 = pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN)
319+ let arg3 = pow(10, 0, shareDecimals, 0, 0, DOWN)
320+ let shareInitialSupply = fraction(arg1, arg2, arg3)
321+ let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
322+ let shareIssueId = calculateAssetId(shareIssue)
323+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
324+ then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
325+ else 0
326+ if ((stake1 == stake1))
327+ then {
328+ let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
329+ then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
330+ else 0
331+ if ((stake2 == stake2))
332+ then {
333+ let baseEntry = [StringEntry(keyVersion, version), BooleanEntry(keyActive, true), StringEntry(keyAssetIdA, pmtStrAssetIdA), StringEntry(keyAssetIdB, pmtStrAssetIdB), IntegerEntry(keyBalanceA, pmtAmountA), IntegerEntry(keyBalanceB, pmtAmountB), IntegerEntry(keyCommission, commission), IntegerEntry(keyCommissionScaleDelimiter, commissionScaleDelimiter), shareIssue, StringEntry(keyShareAssetId, toBase58String(shareIssueId)), IntegerEntry(keyShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareIssueId)]
334+ if (firstHarvest)
335+ then (baseEntry ++ [BooleanEntry(keyFirstHarvest, firstHarvest), IntegerEntry(keyFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
336+ else baseEntry
337+ }
338+ else throw("Strict value is not equal to itself.")
339+ }
340+ else throw("Strict value is not equal to itself.")
341+ }
349342 }
350343
351344
352345
353346 @Callable(i)
354-func replenishWithTwoTokens (slippageTolerance) = {
355- let pmtAssetIdA = i.payments[0].assetId
356- let pmtAssetIdB = i.payments[1].assetId
357- let pmtAmountA = i.payments[0].amount
358- let pmtAmountB = i.payments[1].amount
359- let $t01192111998 = getAssetInfo(pmtAssetIdA)
360- let pmtStrAssetIdA = $t01192111998._1
361- let pmtAssetNameA = $t01192111998._2
362- let pmtDecimalsA = $t01192111998._3
363- let $t01200312197 = getAssetInfo(pmtAssetIdB)
364- let pmtStrAssetIdB = $t01200312197._1
365- let pmtAssetNameB = $t01200312197._2
366- let pmtDecimalsB = $t01200312197._3
367- let tokenRatio = fraction(fraction(scale8, balanceA, pmtAmountA), scale3, fraction(scale8, balanceB, pmtAmountB))
368- let ratioShareTokensInA = fraction(scale8, pmtAmountA, balanceA)
369- let ratioShareTokensInB = fraction(scale8, pmtAmountB, balanceB)
370- let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scale8)
371- let invariantCalculated = invariantCalc((balanceA + pmtAmountA), (balanceB + pmtAmountB))
372- if (!(isActive))
373- then throwIsInactive()
374- else if (if ((0 > slippageTolerance))
375- then true
376- else (slippageTolerance > 10))
377- then throw("Slippage tolerance must be <= 1%")
378- else if ((size(i.payments) != 2))
379- then throw("Two attached assets expected")
380- else if (if ((pmtAssetIdA != assetIdA))
381- then true
382- else (pmtAssetIdB != assetIdB))
383- then throwAssets()
384- else if (if ((((scale3 * (slippageScale3 - slippageTolerance)) / slippageScale3) > tokenRatio))
385- then true
386- else (tokenRatio > ((scale3 * (slippageScale3 + slippageTolerance)) / slippageScale3)))
387- then throw("Incorrect assets amount: amounts must have the contract ratio")
388- else if ((shareTokenToPayAmount == 0))
389- then throw("Too small amount to replenish")
390- else if (!(hasEnoughBalance))
391- then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
392- else {
393- let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
394- then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
395- else 0
396- if ((stake1 == stake1))
397- then {
398- let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
399- then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
400- else 0
401- if ((stake2 == stake2))
402- then [IntegerEntry(kBalanceA, (balanceA + pmtAmountA)), IntegerEntry(kBalanceB, (balanceB + pmtAmountB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), IntegerEntry(kInvariant, invariantCalculated), Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId)]
403- else throw("Strict value is not equal to itself.")
404- }
405- else throw("Strict value is not equal to itself.")
406- }
347+func initWithInitRatio (amtAssetA,amtAssetB,strAssetIdA,strAssetIdB,firstHarvest) = {
348+ let $t01122211309 = getAssetInfoFromString(strAssetIdA)
349+ let pmtStrAssetIdA = $t01122211309._1
350+ let pmtAssetNameA = $t01122211309._2
351+ let pmtDecimalsA = $t01122211309._3
352+ let $t01131411401 = getAssetInfoFromString(strAssetIdB)
353+ let pmtStrAssetIdB = $t01131411401._1
354+ let pmtAssetNameB = $t01131411401._2
355+ let pmtDecimalsB = $t01131411401._3
356+ if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
357+ then throw("Only admin can call this function")
358+ else if (isDefined(getBoolean(this, keyActive)))
359+ then throw("DApp is already active")
360+ else if ((strAssetIdA == strAssetIdB))
361+ then throw("Assets must be different")
362+ else {
363+ let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
364+ let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
365+ let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
366+ let shareInitialSupply = 0
367+ let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
368+ let shareIssueId = calculateAssetId(shareIssue)
369+ let baseEntry = [StringEntry(keyVersion, version), BooleanEntry(keyActive, true), StringEntry(keyAssetIdA, pmtStrAssetIdA), StringEntry(keyAssetIdB, pmtStrAssetIdB), IntegerEntry(keyBalanceInitA, amtAssetA), IntegerEntry(keyBalanceInitB, amtAssetB), IntegerEntry(keyBalanceA, 0), IntegerEntry(keyBalanceB, 0), IntegerEntry(keyCommission, commission), IntegerEntry(keyCommissionScaleDelimiter, commissionScaleDelimiter), shareIssue, StringEntry(keyShareAssetId, toBase58String(shareIssueId)), IntegerEntry(keyShareAssetSupply, shareInitialSupply)]
370+ if (firstHarvest)
371+ then (baseEntry ++ [BooleanEntry(keyFirstHarvest, firstHarvest), IntegerEntry(keyFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
372+ else baseEntry
373+ }
407374 }
408375
409376
410377
411378 @Callable(i)
412-func replenishWithOneToken (virtualSwapTokenPay,virtualSwapTokenGet) = {
413- let $t01449614571 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
414- let pmtAmount = $t01449614571._1
415- let pmtAssetId = $t01449614571._2
416- let $t01457614649 = getAssetInfo(pmtAssetId)
417- let pmtStrAssetId = $t01457614649._1
418- let pmtAssetName = $t01457614649._2
419- let pmtDecimals = $t01457614649._3
420- let pmtMinThreshold = 5000000
421- let thresholdValueForMinTolerance = 50000000
422- let tolerance = if ((thresholdValueForMinTolerance > pmtAmount))
423- then 100000
424- else 1
425- let slippageValueMinForReplenish = (scale8 - ((scale8 * tolerance) / 10000000))
426- let slippageValueMaxForReplenish = (scale8 + ((scale8 * tolerance) / 10000000))
427- let slippageValueMinForSwap = (scale8 - ((scale8 * 1) / 10000000))
428- if (!(isActive))
429- then throwIsInactive()
430- else if ((pmtMinThreshold > pmtAmount))
431- then throw((((("Payment amount " + toString(pmtAmount)) + " does not exceed the minimum amount of ") + toString(pmtMinThreshold)) + " tokens"))
379+func keepLimitForFirstHarvest (shareLimit) = valueOrElse(isActive(), if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
380+ then throw("Only admin can call this function")
381+ else [IntegerEntry(kShareLimit, shareLimit)])
382+
383+
384+
385+@Callable(i)
386+func replenishWithTwoTokens (slippageTolerance) = valueOrElse(isActive(), {
387+ let pmtAssetIdA = i.payments[0].assetId
388+ let pmtAssetIdB = i.payments[1].assetId
389+ let pmtAmountA = i.payments[0].amount
390+ let pmtAmountB = i.payments[1].amount
391+ let $t01386913946 = getAssetInfo(pmtAssetIdA)
392+ let pmtStrAssetIdA = $t01386913946._1
393+ let pmtAssetNameA = $t01386913946._2
394+ let pmtDecimalsA = $t01386913946._3
395+ let $t01395114028 = getAssetInfo(pmtAssetIdB)
396+ let pmtStrAssetIdB = $t01395114028._1
397+ let pmtAssetNameB = $t01395114028._2
398+ let pmtDecimalsB = $t01395114028._3
399+ let inital = if (if ((balanceA == 0))
400+ then (balanceB == 0)
401+ else false)
402+ then true
403+ else false
404+ let tokenRatio = if (inital)
405+ then fraction(fraction(assetInitA, scaleValue8, pmtAmountA), scaleValue3, fraction(assetInitB, scaleValue8, pmtAmountB))
406+ else fraction(fraction(balanceA, scaleValue8, pmtAmountA), scaleValue3, fraction(balanceB, scaleValue8, pmtAmountB))
407+ let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
408+ let shareTokenToPayAmount = if (inital)
409+ then fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN), pow(10, 0, shareDecimals, 0, 0, DOWN))
410+ else fraction(min([fraction(pmtAmountA, scaleValue8, balanceA), fraction(pmtAmountB, scaleValue8, balanceB)]), shareAssetSupply, scaleValue8)
411+ if (if ((0 > slippageTolerance))
412+ then true
413+ else (slippageTolerance > slippageToleranceDelimiter))
414+ then throw(((("Slippage tolerance must be between 0 and " + toString(slippageToleranceDelimiter)) + " inclusively. Actual: ") + toString(slippageTolerance)))
415+ else if ((size(i.payments) != 2))
416+ then throw("Two attached assets expected")
417+ else if (if ((pmtAssetIdA != assetIdA))
418+ then true
419+ else (pmtAssetIdB != assetIdB))
420+ then throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
421+ else if (if ((((scaleValue3 * (slippageToleranceDelimiter - slippageTolerance)) / slippageToleranceDelimiter) > tokenRatio))
422+ then true
423+ else (tokenRatio > ((scaleValue3 * (slippageToleranceDelimiter + slippageTolerance)) / slippageToleranceDelimiter)))
424+ then throw("Incorrect assets amount: amounts must have the contract ratio")
425+ else if ((shareTokenToPayAmount == 0))
426+ then throw("Too small amount to replenish")
427+ else if (!(hasEnoughBalance))
428+ then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
429+ else {
430+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
431+ then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
432+ else 0
433+ if ((stake1 == stake1))
434+ then {
435+ let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
436+ then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
437+ else 0
438+ if ((stake2 == stake2))
439+ then [Reissue(shareAssetId, shareTokenToPayAmount, true), IntegerEntry(keyBalanceA, (balanceA + pmtAmountA)), IntegerEntry(keyBalanceB, (balanceB + pmtAmountB)), IntegerEntry(keyShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId)]
440+ else throw("Strict value is not equal to itself.")
441+ }
442+ else throw("Strict value is not equal to itself.")
443+ }
444+ })
445+
446+
447+
448+@Callable(i)
449+func withdraw () = valueOrElse(isActive(), {
450+ let $t01683416909 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
451+ let pmtAmount = $t01683416909._1
452+ let pmtAssetId = $t01683416909._2
453+ let amountToPayA = fraction(pmtAmount, balanceA, shareAssetSupply)
454+ let amountToPayB = fraction(pmtAmount, balanceB, shareAssetSupply)
455+ if ((size(i.payments) != 1))
456+ then throw("One attached payment expected")
457+ else if ((pmtAssetId != shareAssetId))
458+ then throw(("Incorrect asset attached. Expected: " + toBase58String(shareAssetId)))
459+ else if (!(hasEnoughBalance))
460+ then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
461+ else {
462+ let stake1 = if (containsElement(stakingAssets, strAssetIdA))
463+ then invoke(this, "stakeUnstake", [false, amountToPayA, strAssetIdA], nil)
464+ else 0
465+ if ((stake1 == stake1))
466+ then {
467+ let stake2 = if (containsElement(stakingAssets, strAssetIdB))
468+ then invoke(this, "stakeUnstake", [false, amountToPayB, strAssetIdB], nil)
469+ else 0
470+ if ((stake2 == stake2))
471+ then [IntegerEntry(keyBalanceA, (balanceA - amountToPayA)), IntegerEntry(keyBalanceB, (balanceB - amountToPayB)), IntegerEntry(keyShareAssetSupply, (shareAssetSupply - pmtAmount)), Burn(shareAssetId, pmtAmount), ScriptTransfer(i.caller, amountToPayA, assetIdA), ScriptTransfer(i.caller, amountToPayB, assetIdB)]
472+ else throw("Strict value is not equal to itself.")
473+ }
474+ else throw("Strict value is not equal to itself.")
475+ }
476+ })
477+
478+
479+
480+@Callable(i)
481+func exchange (minAmountToReceive) = valueOrElse(isActive(), {
482+ let $t01821518290 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
483+ let pmtAmount = $t01821518290._1
484+ let pmtAssetId = $t01821518290._2
485+ if (if ((balanceA == 0))
486+ then true
487+ else (balanceB == 0))
488+ then throw("Can't exchange with zero balance")
489+ else if ((0 >= minAmountToReceive))
490+ then throw(("Minimal amount to receive must be positive. Actual: " + toString(minAmountToReceive)))
432491 else if ((size(i.payments) != 1))
433492 then throw("One attached payment expected")
434493 else if (!(hasEnoughBalance))
435494 then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
436- else if (if ((pmtAssetId != assetIdA))
437- then (pmtAssetId != assetIdB)
438- else false)
439- then throwAssets()
440- else {
441- let $t01566116426 = if ((pmtAssetId == assetIdA))
442- then $Tuple7((pmtAmount - virtualSwapTokenPay), virtualSwapTokenGet, (balanceA + virtualSwapTokenPay), (balanceB - virtualSwapTokenGet), invariantCalc((balanceA + pmtAmount), balanceB), (balanceA + pmtAmount), balanceB)
443- else $Tuple7(virtualSwapTokenGet, (pmtAmount - virtualSwapTokenPay), (balanceA - virtualSwapTokenGet), (balanceB + virtualSwapTokenPay), invariantCalc(balanceA, (balanceB + pmtAmount)), balanceA, (balanceB + pmtAmount))
444- let virtualReplenishA = $t01566116426._1
445- let virtualReplenishB = $t01566116426._2
446- let balanceAfterSwapA = $t01566116426._3
447- let balanceAfterSwapB = $t01566116426._4
448- let invariantCalculated = $t01566116426._5
449- let newBalanceA = $t01566116426._6
450- let newBalanceB = $t01566116426._7
451- let newBalanceEntry = if ((pmtAssetId == assetIdA))
452- then IntegerEntry(kBalanceA, newBalanceA)
453- else IntegerEntry(kBalanceB, newBalanceB)
454- let invariantNew = invariantCalc(balanceAfterSwapA, balanceAfterSwapB)
455- let invariantEstimatedRatio = fraction(scale8, invariant, invariantNew)
456- let ratioVirtualBalanceToVirtualReplenish = (fraction((scale8 * scale8), balanceAfterSwapA, balanceAfterSwapB) / fraction(scale8, virtualReplenishA, virtualReplenishB))
457- let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
458- if (if ((slippageValueMinForSwap >= invariantEstimatedRatio))
459- then true
460- else (invariant > invariantNew))
461- then throw("Incorrect virtualSwapTokenPay or virtualSwapTokenGet value")
462- else if (if ((slippageValueMinForReplenish > ratioVirtualBalanceToVirtualReplenish))
463- then true
464- else (ratioVirtualBalanceToVirtualReplenish > slippageValueMaxForReplenish))
465- then throw("Swap with virtualSwapTokenPay and virtualSwapTokenGet is possible, but ratio after virtual swap is incorrect")
466- else if (if ((dAppThresholdAmount > newBalanceA))
467- then true
468- else (dAppThresholdAmount > newBalanceB))
469- then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB)
470- else {
471- let stake1 = if (containsElement(stakingAssets, pmtStrAssetId))
472- then invoke(this, "stakeUnstake", [true, pmtAmount, pmtStrAssetId], nil)
473- else 0
474- if ((stake1 == stake1))
475- then {
476- let ratioShareTokensInA = fraction(virtualReplenishA, scale8, balanceAfterSwapA)
477- let ratioShareTokensInB = fraction(virtualReplenishB, scale8, balanceAfterSwapB)
478- let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scale8)
479-[Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), newBalanceEntry, IntegerEntry(kInvariant, invariantCalculated)]
480- }
481- else throw("Strict value is not equal to itself.")
482- }
495+ else if ((pmtAssetId == assetIdA))
496+ then {
497+ let assetIdSend = assetIdB
498+ let $t01884518967 = calculateFees(pmtAmount, minAmountToReceive, balanceA, balanceB)
499+ let amountWithoutFee = $t01884518967._1
500+ let amountWithFee = $t01884518967._2
501+ let governanceReward = $t01884518967._3
502+ let newBalanceA = (balanceA + pmtAmount)
503+ let newBalanceB = ((balanceB - amountWithFee) - governanceReward)
504+ let stake1 = if (containsElement(stakingAssets, strAssetIdA))
505+ then invoke(this, "stakeUnstake", [true, pmtAmount, strAssetIdA], nil)
506+ else 0
507+ if ((stake1 == stake1))
508+ then {
509+ let stake2 = if (containsElement(stakingAssets, strAssetIdB))
510+ then invoke(this, "stakeUnstake", [false, (amountWithFee + governanceReward), strAssetIdB], nil)
511+ else 0
512+ if ((stake2 == stake2))
513+ then [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)]
514+ else throw("Strict value is not equal to itself.")
515+ }
516+ else throw("Strict value is not equal to itself.")
483517 }
484- }
518+ else if ((pmtAssetId == assetIdB))
519+ then {
520+ let assetIdSend = assetIdA
521+ let $t01992220044 = calculateFees(pmtAmount, minAmountToReceive, balanceB, balanceA)
522+ let amountWithoutFee = $t01992220044._1
523+ let amountWithFee = $t01992220044._2
524+ let governanceReward = $t01992220044._3
525+ let newBalanceA = ((balanceA - amountWithFee) - governanceReward)
526+ let newBalanceB = (balanceB + pmtAmount)
527+ let stake1 = if (containsElement(stakingAssets, strAssetIdA))
528+ then invoke(this, "stakeUnstake", [false, (amountWithFee + governanceReward), strAssetIdA], nil)
529+ else 0
530+ if ((stake1 == stake1))
531+ then {
532+ let stake2 = if (containsElement(stakingAssets, strAssetIdB))
533+ then invoke(this, "stakeUnstake", [true, pmtAmount, strAssetIdB], nil)
534+ else 0
535+ if ((stake2 == stake2))
536+ then [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)]
537+ else throw("Strict value is not equal to itself.")
538+ }
539+ else throw("Strict value is not equal to itself.")
540+ }
541+ else throw(((("Incorrect asset attached. Expected: " + strAssetIdA) + " or ") + strAssetIdB))
542+ })
485543
486544
487545
488546 @Callable(i)
489-func withdraw () = {
490- let $t01865218795 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
491- let pmtAmount = $t01865218795._1
492- let pmtAssetId = $t01865218795._2
493- let amountToPayA = fraction(pmtAmount, balanceA, shareAssetSupply)
494- let amountToPayB = fraction(pmtAmount, balanceB, shareAssetSupply)
495- let invariantCalculated = invariantCalc((balanceA - amountToPayA), (balanceB - amountToPayB))
496- if (!(isActive))
497- then throwIsInactive()
498- else if ((size(i.payments) != 1))
499- then throw("One attached payment expected")
500- else if ((pmtAssetId != shareAssetId))
501- then throw(("Incorrect asset attached. Expected: " + toBase58String(shareAssetId)))
502- else if (!(hasEnoughBalance))
503- then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
504- else {
505- let stake1 = if (containsElement(stakingAssets, strAssetIdA))
506- then invoke(this, "stakeUnstake", [false, amountToPayA, strAssetIdA], nil)
507- else 0
508- if ((stake1 == stake1))
509- then {
510- let stake2 = if (containsElement(stakingAssets, strAssetIdB))
511- then invoke(this, "stakeUnstake", [false, amountToPayB, strAssetIdB], nil)
512- else 0
513- if ((stake2 == stake2))
514- then [IntegerEntry(kBalanceA, (balanceA - amountToPayA)), IntegerEntry(kBalanceB, (balanceB - amountToPayB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply - pmtAmount)), IntegerEntry(kInvariant, invariantCalculated), Burn(shareAssetId, pmtAmount), ScriptTransfer(i.caller, amountToPayA, assetIdA), ScriptTransfer(i.caller, amountToPayB, assetIdB)]
515- else throw("Strict value is not equal to itself.")
516- }
517- else throw("Strict value is not equal to itself.")
518- }
519- }
520-
521-
522-
523-@Callable(i)
524-func exchange (estimatedAmountToReceive,minAmountToReceive) = {
525- let $t02030920384 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
526- let pmtAmount = $t02030920384._1
527- let pmtAssetId = $t02030920384._2
528- if (!(isActive))
529- then throwIsInactive()
530- else if ((0 >= estimatedAmountToReceive))
531- then throw(("Estimated amount must be positive. Actual: " + toString(estimatedAmountToReceive)))
532- else if ((minAmountToReceive > estimatedAmountToReceive))
533- then throw(((("Minimal amount can't be greater than estimated. Estimated: " + toString(estimatedAmountToReceive)) + ". Minimal: ") + toString(minAmountToReceive)))
534- else if ((size(i.payments) != 1))
535- then throw("One attached payment expected")
536- else if (!(hasEnoughBalance))
537- then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
538- else if (if ((pmtAssetId != assetIdA))
539- then (pmtAssetId != assetIdB)
540- else false)
541- then throwAssets()
542- else if ((10000000 > pmtAmount))
543- then throw("Only swap of 10.000000 or more tokens is allowed")
544- else if (if ((exchangeRatioLimitMin > fraction(scale8, minAmountToReceive, pmtAmount)))
545- then true
546- else (fraction(scale8, estimatedAmountToReceive, pmtAmount) > exchangeRatioLimitMax))
547- then throw("Incorrect args and pmt ratio")
548- else {
549- let sendAssetId = if ((pmtAssetId == assetIdA))
550- then assetIdB
551- else assetIdA
552- let amount = calculateSendAmount(estimatedAmountToReceive, minAmountToReceive, pmtAmount, pmtAssetId)
553- let governanceReward = fraction(amount, feeGovernance, feeScale6)
554- let amountMinusFee = fraction(amount, (feeScale6 - fee), feeScale6)
555- let $t02180622068 = if ((pmtAssetId == assetIdA))
556- then $Tuple2((balanceA + pmtAmount), ((balanceB - amountMinusFee) - governanceReward))
557- else $Tuple2(((balanceA - amountMinusFee) - governanceReward), (balanceB + pmtAmount))
558- let newBalanceA = $t02180622068._1
559- let newBalanceB = $t02180622068._2
560- let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
561- if (if ((dAppThresholdAmount > newBalanceA))
562- then true
563- else (dAppThresholdAmount > newBalanceB))
564- then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB)
565- else {
566- let $t02236622439 = getAssetInfo(pmtAssetId)
567- let pmtStrAssetId = $t02236622439._1
568- let pmtAssetName = $t02236622439._2
569- let pmtDecimals = $t02236622439._3
570- let $t02245222529 = getAssetInfo(sendAssetId)
571- let sendStrAssetId = $t02245222529._1
572- let sendAssetName = $t02245222529._2
573- let sendDecimals = $t02245222529._3
574- let stake1 = if (containsElement(stakingAssets, pmtStrAssetId))
575- then invoke(this, "stakeUnstake", [true, pmtAmount, pmtStrAssetId], nil)
576- else 0
577- if ((stake1 == stake1))
578- then {
579- let stake2 = if (containsElement(stakingAssets, sendStrAssetId))
580- then invoke(this, "stakeUnstake", [false, (amountMinusFee + governanceReward), sendStrAssetId], nil)
581- else 0
582- if ((stake2 == stake2))
583- then [IntegerEntry(kBalanceA, newBalanceA), IntegerEntry(kBalanceB, newBalanceB), IntegerEntry(kInvariant, invariantCalc(newBalanceA, newBalanceB)), ScriptTransfer(i.caller, amountMinusFee, sendAssetId), ScriptTransfer(walletAddress, governanceReward, sendAssetId)]
584- else throw("Strict value is not equal to itself.")
585- }
586- else throw("Strict value is not equal to itself.")
587- }
588- }
589- }
590-
591-
592-
593-@Callable(i)
594-func shutdown () = if (!(isActive))
595- then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, kCause), "the cause wasn't specified")))
596- else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, admStartStop], i.callerPublicKey)))
597- then throwOnlyAdmin()
547+func shutdown () = if (!(active))
548+ then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, keyCause), "the cause wasn't specified")))
549+ else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStartStop], i.callerPublicKey)))
550+ then throw("Only admin can call this function")
598551 else suspend("Paused by admin")
599552
600553
601554
602555 @Callable(i)
603-func activate () = if (isActive)
604- then throwIsActive()
605- else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, admStartStop], i.callerPublicKey)))
606- then throwOnlyAdmin()
607- else [BooleanEntry(kActive, true), DeleteEntry(kCause)]
556+func activate () = if (active)
557+ then throw("DApp is already active")
558+ else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStartStop], i.callerPublicKey)))
559+ then throw("Only admin can call this function")
560+ else [BooleanEntry(keyActive, true), DeleteEntry(keyCause)]
608561
609562
610563
611564 @Callable(i)
612-func takeIntoAccountExtraFunds () = {
565+func takeIntoAccountExtraFunds () = valueOrElse(isActive(), {
613566 let amountEnrollA = (accountBalanceWithStakedA - balanceA)
614567 let amountEnrollB = (accountBalanceWithStakedB - balanceB)
615- let invariantNew = invariantCalc((balanceA + amountEnrollA), (balanceB + amountEnrollB))
616- if (!(isActive))
617- then throwIsInactive()
618- else if ((i.caller != walletAddress))
619- then throw("Only the wallet can call this function")
620- else if (if ((0 > amountEnrollA))
621- then true
622- else (0 > amountEnrollB))
623- then suspend("Enroll amount negative")
624- else if (if ((amountEnrollA == 0))
625- then (amountEnrollB == 0)
626- else false)
627- then throw("No money to take")
628- else {
629- let stake1 = if (if (containsElement(stakingAssets, strAssetIdA))
630- then (amountEnrollA > 0)
631- else false)
632- then invoke(this, "stakeUnstake", [true, amountEnrollA, strAssetIdA], nil)
633- else 0
634- if ((stake1 == stake1))
635- then {
636- let stake2 = if (if (containsElement(stakingAssets, strAssetIdB))
637- then (amountEnrollB > 0)
638- else false)
639- then invoke(this, "stakeUnstake", [true, amountEnrollB, strAssetIdB], nil)
640- else 0
641- if ((stake2 == stake2))
642- then [IntegerEntry(kInvariant, invariantNew), IntegerEntry(kBalanceA, (balanceA + amountEnrollA)), IntegerEntry(kBalanceB, (balanceB + amountEnrollB)), IntegerEntry(("last_income_" + strAssetIdA), amountEnrollA), IntegerEntry(("last_income_" + strAssetIdB), amountEnrollB)]
643- else throw("Strict value is not equal to itself.")
644- }
645- else throw("Strict value is not equal to itself.")
646- }
647- }
568+ if ((i.caller != walletAddress))
569+ then throw("Only the wallet can call this function")
570+ else if (if ((0 > amountEnrollA))
571+ then true
572+ else (0 > amountEnrollB))
573+ then suspend("Enroll amount negative")
574+ else if (if ((amountEnrollA == 0))
575+ then (amountEnrollB == 0)
576+ else false)
577+ then throw("No money to take")
578+ else {
579+ let stake1 = if (containsElement(stakingAssets, strAssetIdA))
580+ then invoke(this, "stakeUnstake", [true, amountEnrollA, strAssetIdA], nil)
581+ else 0
582+ if ((stake1 == stake1))
583+ then {
584+ let stake2 = if (containsElement(stakingAssets, strAssetIdB))
585+ then invoke(this, "stakeUnstake", [true, amountEnrollB, strAssetIdB], nil)
586+ else 0
587+ if ((stake2 == stake2))
588+ then [IntegerEntry(keyBalanceA, (balanceA + amountEnrollA)), IntegerEntry(keyBalanceB, (balanceB + amountEnrollB)), IntegerEntry(("last_income_" + strAssetIdA), amountEnrollA), IntegerEntry(("last_income_" + strAssetIdB), amountEnrollB)]
589+ else throw("Strict value is not equal to itself.")
590+ }
591+ else throw("Strict value is not equal to itself.")
592+ }
593+ })
648594
649595
650596
651597 @Callable(i)
652598 func stakeUnstake (stake,amount,assetIdString) = if ((i.caller != this))
653599 then throw("Only contract itself can invoke this function")
654- else {
655- let $t02559125694 = calcStakingParams(stake, amount, fromBase58String(assetIdString))
656- let call = $t02559125694._1
657- let addr = $t02559125694._2
658- let params = $t02559125694._3
659- let payments = $t02559125694._4
660- let inv = invoke(addr, call, params, payments)
661- if ((inv == inv))
662- then nil
663- else throw("Strict value is not equal to itself.")
664- }
600+ else if ((assetIdString == "WAVES"))
601+ then {
602+ let pool = addressFromStringValue(valueOrErrorMessage(getString(oracle, keyLeasingPool), "No leasing pool in oracle"))
603+ let leasingId = getBinary(this, keyLeasingId)
604+ let leasingAmount = valueOrElse(getInteger(this, keyLeasingAmount), 0)
605+ let newLeaseAmount = if (stake)
606+ then (leasingAmount + amount)
607+ else (leasingAmount - amount)
608+ let newLease = Lease(pool, newLeaseAmount)
609+ let newLeaseId = calculateLeaseId(newLease)
610+ let baseEtry = [newLease, BinaryEntry(keyLeasingId, newLeaseId), IntegerEntry(keyLeasingAmount, newLeaseAmount)]
611+ match leasingId {
612+ case lId: ByteVector =>
613+ ([LeaseCancel(lId)] ++ baseEtry)
614+ case _ =>
615+ baseEtry
616+ }
617+ }
618+ else {
619+ let $t02377823881 = calcStakingParams(stake, amount, fromBase58String(assetIdString))
620+ let call = $t02377823881._1
621+ let addr = $t02377823881._2
622+ let params = $t02377823881._3
623+ let payments = $t02377823881._4
624+ let inv = invoke(addr, call, params, payments)
625+ if ((inv == inv))
626+ then nil
627+ else throw("Strict value is not equal to itself.")
628+ }
665629
666630
667631
668632 @Callable(i)
669-func stakeAll () = if (!(isActive))
670- then throw("DApp is inactive at this moment")
671- else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, admStartStop], i.callerPublicKey)))
672- then throw("Only admin can call this function")
673- else {
674- let stake1 = if (containsElement(stakingAssets, strAssetIdA))
675- then {
676- let amountA = (balanceA - stakedAmountA)
677- if ((amountA > 0))
678- then invoke(this, "stakeUnstake", [true, amountA, strAssetIdA], nil)
679- else 0
680- }
681- else 0
682- if ((stake1 == stake1))
683- then {
684- let stake2 = if (containsElement(stakingAssets, strAssetIdB))
685- then {
686- let amountB = (balanceB - stakedAmountB)
687- if ((amountB > 0))
688- then invoke(this, "stakeUnstake", [true, amountB, strAssetIdB], nil)
689- else 0
690- }
691- else 0
692- if ((stake2 == stake2))
693- then nil
694- else throw("Strict value is not equal to itself.")
695- }
696- else throw("Strict value is not equal to itself.")
697- }
633+func stakeAll () = valueOrElse(isActive(), if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStartStop], i.callerPublicKey)))
634+ then throw("Only admin can call this function")
635+ else {
636+ let stake1 = if (containsElement(stakingAssets, strAssetIdA))
637+ then {
638+ let amountA = (balanceA - stakedAmountA)
639+ if ((amountA > 0))
640+ then invoke(this, "stakeUnstake", [true, amountA, strAssetIdA], nil)
641+ else 0
642+ }
643+ else 0
644+ if ((stake1 == stake1))
645+ then {
646+ let stake2 = if (containsElement(stakingAssets, strAssetIdB))
647+ then {
648+ let amountB = (balanceB - stakedAmountB)
649+ if ((amountB > 0))
650+ then invoke(this, "stakeUnstake", [true, amountB, strAssetIdB], nil)
651+ else 0
652+ }
653+ else 0
654+ if ((stake2 == stake2))
655+ then nil
656+ else throw("Strict value is not equal to itself.")
657+ }
658+ else throw("Strict value is not equal to itself.")
659+ })
698660
699661
700662 @Verifier(tx)
716678 let callTakeIntoAccount = if ((inv.dApp == this))
717679 then (inv.function == "takeIntoAccountExtraFunds")
718680 else false
681+ let exchangeToWaves = if (if (if ((inv.dApp == USDNToWavesExchanger))
682+ then (inv.function == "exchange")
683+ else false)
684+ then (assetIdA == USDN)
685+ else false)
686+ then true
687+ else if (if ((assetIdB == USDN))
688+ then (size(inv.payments) == 1)
689+ else false)
690+ then (inv.payments[0].assetId == USDN)
691+ else false
692+ let exchangeToNSBTs = if (if (if ((inv.dApp == USDNToNSBTExchanger))
693+ then (inv.function == "exchange")
694+ else false)
695+ then (assetIdA == NSBT)
696+ else false)
697+ then true
698+ else if (if ((assetIdB == NSBT))
699+ then (size(inv.payments) == 1)
700+ else false)
701+ then (inv.payments[0].assetId == USDN)
702+ else false
719703 let signedByAdmin = if (if (if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
720704 then true
721705 else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey2))
722706 then true
723707 else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey3))
724708 then true
725- else sigVerify(tx.bodyBytes, tx.proofs[0], admStaking)
726- if (if (callTakeIntoAccount)
709+ else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKeyStaking)
710+ if (if (if (if (callTakeIntoAccount)
711+ then true
712+ else exchangeToWaves)
713+ then true
714+ else exchangeToNSBTs)
727715 then signedByAdmin
728716 else false)
729717 then true
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let version = "2.0.0"
4+let version = "1.0.0"
55
6-let kVersion = "version"
6+let keyVersion = "version"
77
8-let kActive = "active"
8+let keyActive = "active"
99
10-let kAssetIdA = "A_asset_id"
10+let keyAssetIdA = "A_asset_id"
1111
12-let kAssetIdB = "B_asset_id"
12+let keyAssetIdB = "B_asset_id"
1313
14-let kBalanceA = "A_asset_balance"
14+let keyBalanceA = "A_asset_balance"
1515
16-let kBalanceB = "B_asset_balance"
16+let keyBalanceB = "B_asset_balance"
1717
18-let kShareAssetId = "share_asset_id"
18+let keyBalanceInitA = "A_asset_init"
1919
20-let kShareAssetSupply = "share_asset_supply"
20+let keyBalanceInitB = "B_asset_init"
2121
22-let kFee = "commission"
22+let keyShareAssetId = "share_asset_id"
2323
24-let kFeeScaleDelimiter = "commission_scale_delimiter"
24+let keyShareAssetSupply = "share_asset_supply"
2525
26-let kInvariant = "invariant"
26+let keyCommission = "commission"
2727
28-let kCause = "shutdown_cause"
28+let keyCommissionScaleDelimiter = "commission_scale_delimiter"
29+
30+let keyCause = "shutdown_cause"
31+
32+let keyFirstHarvest = "first_harvest"
33+
34+let keyFirstHarvestHeight = "first_harvest_height"
35+
36+let kShareLimit = "share_limit_on_first_harvest"
37+
38+let kBasePeriod = "base_period"
39+
40+let kPeriodLength = "period_length"
41+
42+let kStartHeight = "start_height"
43+
44+let kFirstHarvestHeight = "first_harvest_height"
2945
3046 let keyUSDNNSBTAddress = "staking_usdnnsbt_address"
3147
3248 let keyEURNAddress = "staking_eurn_address"
49+
50+let keyLeasingPool = "leasing_address"
51+
52+let keyLeasingAmount = "leasing_amount"
53+
54+let keyLeasingId = "leasing_id"
3355
3456 let keyAdminPubKey1 = "admin_pub_1"
3557
3658 let keyAdminPubKey2 = "admin_pub_2"
3759
3860 let keyAdminPubKey3 = "admin_pub_3"
39-
40-let USDNToWavesExchanger = Address(base58'3N8PGkzXhbtTvEwEQTtE2xiTJmsDEQ9XfoZ')
4161
4262 let oracle = Address(base58'3NBBWfzZtZtszaXbitTKnrB2xXwv26Bn7H9')
4363
4464 func getAdminPub (keyAdminPub) = match getString(oracle, keyAdminPub) {
4565 case string: String =>
4666 fromBase58String(string)
4767 case nothing =>
4868 throw("Admin public key is empty")
4969 }
5070
5171
5272 let adminPubKey1 = getAdminPub(keyAdminPubKey1)
5373
5474 let adminPubKey2 = getAdminPub(keyAdminPubKey2)
5575
5676 let adminPubKey3 = getAdminPub(keyAdminPubKey3)
5777
58-let admStartStop = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
78+let adminPubKeyStartStop = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
5979
60-let admStaking = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
80+let adminPubKeyStaking = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
6181
6282 let walletAddress = Address(base58'3NAGTtZz6WpupSN89NZD5rMZwwziZEg4Kx4')
6383
84+let votingAddress = Address(base58'3MrJgdL1GniipErHy44YF9idzLaUL2iX5DQ')
85+
6486 let USDN = base58'8UrfDVd5GreeUwm7uPk7eYz1eMv376kzR52C6sANPkwS'
87+
88+let NSBT = base58'36mg8NZTaFRDygiVwb8uBnLR51hetJruUCZcxhaVcHj9'
89+
90+let SWOP = base58'2HAJrwa8q4SxBx9cHYaBTQdBjdk5wwqdof7ccpAx2uhZ'
6591
6692 let EURN = base58'ECBCkHS68DckpBrzLeoRgYbFg7sCVqR176mPqbXsj9pA'
6793
68-let stakingAssets = [toBase58String(USDN), toBase58String(EURN)]
94+let stakingAssets = ["WAVES", toBase58String(USDN), toBase58String(NSBT), toBase58String(EURN)]
6995
7096 let stakingUSDNNSBTAddress = Address(fromBase58String(valueOrErrorMessage(getString(oracle, keyUSDNNSBTAddress), "no usdn staking address")))
7197
72-let stakingEURNAddress = Address(fromBase58String(valueOrErrorMessage(getString(oracle, keyEURNAddress), "no usdn staking address")))
98+let stakingEURNAddress = Address(fromBase58String(valueOrErrorMessage(getString(oracle, keyEURNAddress), "no eurn staking address")))
7399
74-let isActive = getBooleanValue(this, kActive)
100+let USDNToWavesExchanger = Address(base58'3N8PGkzXhbtTvEwEQTtE2xiTJmsDEQ9XfoZ')
75101
76-let strAssetIdA = getStringValue(this, kAssetIdA)
102+let USDNToNSBTExchanger = Address(base58'3MqW1t2cxdYy2emEMk3YtZkRwQPhHaTfWRe')
77103
78-let strAssetIdB = getStringValue(this, kAssetIdB)
104+let basePeriod = valueOrErrorMessage(getInteger(votingAddress, kBasePeriod), "Empty kBasePeriod")
105+
106+let startHeight = valueOrErrorMessage(getInteger(votingAddress, kStartHeight), "Empty kStartHeight")
107+
108+let periodLength = valueOrErrorMessage(getInteger(votingAddress, kPeriodLength), "Empty kPeriodLength")
109+
110+let firstHarvestEndPeriod = ((basePeriod + ((height - startHeight) / periodLength)) + 3)
111+
112+let active = getBooleanValue(this, keyActive)
113+
114+let strAssetIdA = getStringValue(this, keyAssetIdA)
115+
116+let strAssetIdB = getStringValue(this, keyAssetIdB)
79117
80118 let assetIdA = if ((strAssetIdA == "WAVES"))
81119 then unit
82120 else fromBase58String(strAssetIdA)
83121
84122 let assetIdB = if ((strAssetIdB == "WAVES"))
85123 then unit
86124 else fromBase58String(strAssetIdB)
87125
88126 let assetNameA = match assetIdA {
89127 case id: ByteVector =>
90128 value(assetInfo(id)).name
91129 case waves: Unit =>
92130 "WAVES"
93131 case _ =>
94132 throw("Match error")
95133 }
96134
97135 let assetNameB = match assetIdB {
98136 case id: ByteVector =>
99137 value(assetInfo(id)).name
100138 case waves: Unit =>
101139 "WAVES"
102140 case _ =>
103141 throw("Match error")
104142 }
105143
106-let balanceA = getIntegerValue(this, kBalanceA)
144+let balanceA = getIntegerValue(this, keyBalanceA)
107145
108-let balanceB = getIntegerValue(this, kBalanceB)
146+let balanceB = getIntegerValue(this, keyBalanceB)
109147
110-let shareAssetId = fromBase58String(getStringValue(this, kShareAssetId))
148+let shareAssetId = fromBase58String(getStringValue(this, keyShareAssetId))
111149
112-let shareAssetSupply = getIntegerValue(this, kShareAssetSupply)
150+let shareAssetSupply = getIntegerValue(this, keyShareAssetSupply)
113151
114-let invariant = getIntegerValue(this, kInvariant)
152+let commission = 3000
115153
116-let fee = 500
154+let commissionGovernance = 1200
117155
118-let feeGovernance = 200
156+let commissionScaleDelimiter = 1000000
119157
120-let feeScale6 = 1000000
158+let scaleValue3 = 1000
121159
122-let scale3 = 1000
160+let scaleValue8 = 100000000
123161
124-let scale8 = 100000000
162+let slippageToleranceDelimiter = 1000
125163
126-let scale12 = 1000000000000
127-
128-let slippageScale3 = 1000
129-
130-let digits8 = 8
131-
132-let dAppThreshold = 50
133-
134-let dAppThresholdScale2 = 100
135-
136-let exchangeRatioLimitMin = 90000000
137-
138-let exchangeRatioLimitMax = 110000000
139-
140-let alpha = 50
141-
142-let alphaDigits = 2
143-
144-let beta = 46000000
164+let scaleValue8Digits = 8
145165
146166 func accountBalance (assetId) = match assetId {
147167 case id: ByteVector =>
148168 assetBalance(this, id)
149169 case waves: Unit =>
150170 wavesBalance(this).available
151171 case _ =>
152172 throw("Match error")
153173 }
154174
155175
156176 func stakedAmount (assetId) = {
157177 let stakedAmountCalculated = match assetId {
158178 case aId: ByteVector =>
159- if ((aId == USDN))
179+ if (if ((aId == USDN))
180+ then true
181+ else (aId == NSBT))
160182 then getInteger(stakingUSDNNSBTAddress, ((("rpd_balance_" + toBase58String(aId)) + "_") + toString(this)))
161183 else if ((aId == EURN))
162184 then getInteger(stakingEURNAddress, ((("%s%s%s__stakingBalance__" + toBase58String(aId)) + "__") + toString(this)))
163185 else 0
164186 case _: Unit =>
165- 0
187+ valueOrElse(getInteger(this, keyLeasingAmount), 0)
166188 case _ =>
167189 throw("Match error")
168190 }
169191 match stakedAmountCalculated {
170192 case i: Int =>
171193 i
172194 case _ =>
173195 0
174196 }
175197 }
176198
177199
178200 let stakedAmountA = stakedAmount(assetIdA)
179201
180202 let stakedAmountB = stakedAmount(assetIdB)
181203
204+let assetInitA = getIntegerValue(this, keyBalanceInitA)
205+
206+let assetInitB = getIntegerValue(this, keyBalanceInitB)
207+
182208 let availableBalanceA = (balanceA - stakedAmountA)
183209
184210 let availableBalanceB = (balanceB - stakedAmountB)
185211
186212 let accountBalanceWithStakedA = (accountBalance(assetIdA) + stakedAmountA)
187213
188214 let accountBalanceWithStakedB = (accountBalance(assetIdB) + stakedAmountB)
189215
190216 let hasEnoughBalance = if ((accountBalanceWithStakedA >= balanceA))
191217 then (accountBalanceWithStakedB >= balanceB)
192218 else false
193-
194-func skewness (x,y) = (((fraction(scale12, x, y) + fraction(scale12, y, x)) / 2) / 10000)
195-
196-
197-func invariantCalc (x,y) = {
198- let sk = skewness(x, y)
199- (fraction((x + y), scale8, pow(sk, digits8, alpha, alphaDigits, digits8, CEILING)) + (2 * fraction(pow(fraction(x, y, scale8), 0, 5, 1, (digits8 / 2), DOWN), pow((sk - beta), digits8, alpha, alphaDigits, digits8, DOWN), scale8)))
200- }
201-
202-
203-func calculateSendAmount (amountToSendEstimated,minTokenReceiveAmount,tokenReceiveAmount,tokenId) = {
204- let slippageValue = (scale8 - ((scale8 * 1) / 10000000))
205- let deltaBetweenMaxAndMinSendValue = (amountToSendEstimated - minTokenReceiveAmount)
206- let x = (balanceA + tokenReceiveAmount)
207- let y = (balanceB + tokenReceiveAmount)
208- let invariantNew = if ((tokenId == assetIdA))
209- then invariantCalc(x, (balanceB - amountToSendEstimated))
210- else if ((tokenId == assetIdB))
211- then invariantCalc((balanceA - amountToSendEstimated), y)
212- else throw("Wrong asset in payment")
213- let invariantEstimatedRatio = fraction(scale8, invariant, invariantNew)
214- func getStepAmount (acc,step) = if ((acc == -1))
215- then {
216- let amountToSend = (amountToSendEstimated - ((step * deltaBetweenMaxAndMinSendValue) / 5))
217- let stepInvariant = if ((tokenId == assetIdA))
218- then invariantCalc(x, (balanceB - amountToSend))
219- else invariantCalc((balanceA - amountToSend), y)
220- if ((stepInvariant > invariant))
221- then amountToSend
222- else -1
223- }
224- else acc
225-
226- let stepAmount = {
227- let $l = [1, 2, 3, 4, 5]
228- let $s = size($l)
229- let $acc0 = -1
230- func $f0_1 ($a,$i) = if (($i >= $s))
231- then $a
232- else getStepAmount($a, $l[$i])
233-
234- func $f0_2 ($a,$i) = if (($i >= $s))
235- then $a
236- else throw("List size exceeds 5")
237-
238- $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
239- }
240- if ((0 > stepAmount))
241- then throw("something went wrong while working with amountToSend")
242- else if (if ((invariantEstimatedRatio > slippageValue))
243- then (invariantNew > invariant)
244- else false)
245- then amountToSendEstimated
246- else stepAmount
247- }
248-
249219
250220 func getAssetInfo (assetId) = match assetId {
251221 case id: ByteVector =>
252222 let stringId = toBase58String(id)
253223 let info = valueOrErrorMessage(assetInfo(id), (("Asset " + stringId) + " doesn't exist"))
254224 $Tuple3(stringId, info.name, info.decimals)
255225 case waves: Unit =>
256226 $Tuple3("WAVES", "WAVES", 8)
257227 case _ =>
258228 throw("Match error")
259229 }
260230
261231
262-func suspend (cause) = [BooleanEntry(kActive, false), StringEntry(kCause, cause)]
232+func getAssetInfoFromString (assetStr) = if ((assetStr == "WAVES"))
233+ then $Tuple3("WAVES", "WAVES", 8)
234+ else {
235+ let stringId = assetStr
236+ let id = fromBase58String(assetStr)
237+ let info = valueOrErrorMessage(assetInfo(id), (("Asset " + stringId) + " doesn't exist"))
238+ $Tuple3(stringId, info.name, info.decimals)
239+ }
263240
264241
265-func throwIsActive () = throw("DApp is already active")
266-
267-
268-func throwIsInactive () = throw("DApp is inactive at this moment")
269-
270-
271-func throwOnlyAdmin () = throw("Only admin can call this function")
272-
273-
274-func throwAssets () = throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
275-
276-
277-func throwThreshold (threshold,amountA,amountB) = throw(((((((((("New balance in assets of the DApp is less than threshold " + toString(threshold)) + ": ") + toString(amountA)) + " ") + assetNameA) + ", ") + toString(amountB)) + " ") + assetNameB))
278-
279-
280-func suspendSuspicious () = suspend(((((((((((((((("Suspicious state. Actual balances: " + toString(balanceA)) + " ") + assetNameA) + ", ") + toString(balanceB)) + " ") + assetNameB) + ". State: ") + toString(accountBalance(assetIdA))) + " ") + assetNameA) + ", ") + toString(accountBalance(assetIdB))) + " ") + assetNameB))
242+func suspend (cause) = [BooleanEntry(keyActive, false), StringEntry(keyCause, cause)]
281243
282244
283245 func calcStakingFuncAndAddres (stake,assetId) = if (stake)
284246 then if ((assetId == USDN))
285247 then $Tuple2("lockNeutrino", stakingUSDNNSBTAddress)
286- else $Tuple2("startStaking", stakingEURNAddress)
248+ else if ((assetId == NSBT))
249+ then $Tuple2("lockNsbt", stakingUSDNNSBTAddress)
250+ else $Tuple2("startStaking", stakingEURNAddress)
287251 else if ((assetId == USDN))
288252 then $Tuple2("unlockNeutrino", stakingUSDNNSBTAddress)
289- else $Tuple2("stopStaking", stakingEURNAddress)
253+ else if ((assetId == NSBT))
254+ then $Tuple2("unlockNsbt", stakingUSDNNSBTAddress)
255+ else $Tuple2("stopStaking", stakingEURNAddress)
290256
291257
292258 func calcStakingParams (stake,amount,assetId) = if (stake)
293259 then {
294- let $t087598825 = calcStakingFuncAndAddres(stake, assetId)
295- let call = $t087598825._1
296- let stakingAddr = $t087598825._2
260+ let $t069226988 = calcStakingFuncAndAddres(stake, assetId)
261+ let call = $t069226988._1
262+ let stakingAddr = $t069226988._2
297263 $Tuple4(call, stakingAddr, nil, [AttachedPayment(assetId, amount)])
298264 }
299265 else {
300- let $t089118977 = calcStakingFuncAndAddres(stake, assetId)
301- let call = $t089118977._1
302- let stakingAddr = $t089118977._2
266+ let $t070747140 = calcStakingFuncAndAddres(stake, assetId)
267+ let call = $t070747140._1
268+ let stakingAddr = $t070747140._2
303269 $Tuple4(call, stakingAddr, [amount, toBase58String(assetId)], nil)
304270 }
305271
306272
273+func calculateFees (pmtAmount,minAmountToReceive,tokenFrom,tokenTo) = {
274+ let amountWithoutFee = fraction(tokenTo, pmtAmount, (pmtAmount + tokenFrom))
275+ let amountWithFee = fraction(amountWithoutFee, (commissionScaleDelimiter - commission), commissionScaleDelimiter)
276+ let governanceReward = fraction(amountWithoutFee, commissionGovernance, commissionScaleDelimiter)
277+ if ((minAmountToReceive > amountWithFee))
278+ then throw(((("Calculated amount to receive " + toString(amountWithFee)) + " is less than specified minimum ") + toString(minAmountToReceive)))
279+ else $Tuple3(amountWithoutFee, amountWithFee, governanceReward)
280+ }
281+
282+
283+func suspendSuspicious () = suspend(((((((((((((((("Suspicious state. Actual balances: " + toString(accountBalanceWithStakedA)) + " ") + assetNameA) + ", ") + toString(accountBalanceWithStakedB)) + " ") + assetNameB) + ". State: ") + toString(balanceA)) + " ") + assetNameA) + ", ") + toString(balanceB)) + " ") + assetNameB))
284+
285+
286+func isActive () = if (active)
287+ then unit
288+ else throw("DApp is inactive at this moment")
289+
290+
307291 @Callable(i)
308-func init () = {
309- let $t090829159 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
310- let pmtAmountA = $t090829159._1
311- let pmtAssetIdA = $t090829159._2
312- let $t091649241 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
313- let pmtAmountB = $t091649241._1
314- let pmtAssetIdB = $t091649241._2
315- let $t092469323 = getAssetInfo(pmtAssetIdA)
316- let pmtStrAssetIdA = $t092469323._1
317- let pmtAssetNameA = $t092469323._2
318- let pmtDecimalsA = $t092469323._3
319- let $t093289405 = getAssetInfo(pmtAssetIdB)
320- let pmtStrAssetIdB = $t093289405._1
321- let pmtAssetNameB = $t093289405._2
322- let pmtDecimalsB = $t093289405._3
323- if (isDefined(getBoolean(this, kActive)))
324- then throwIsActive()
325- else if ((pmtAssetIdA == pmtAssetIdB))
326- then throw("Assets must be different")
327- else {
328- let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
329- let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
330- let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
331- let shareInitialSupply = fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN), pow(10, 0, shareDecimals, 0, 0, DOWN))
332- let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
333- let shareIssueId = calculateAssetId(shareIssue)
334- let invariantCalculated = invariantCalc(pmtAmountA, pmtAmountB)
335- let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
336- then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
337- else 0
338- if ((stake1 == stake1))
339- then {
340- let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
341- then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
342- else 0
343- if ((stake2 == stake2))
344- then [StringEntry(kVersion, version), BooleanEntry(kActive, true), StringEntry(kAssetIdA, pmtStrAssetIdA), StringEntry(kAssetIdB, pmtStrAssetIdB), IntegerEntry(kBalanceA, pmtAmountA), IntegerEntry(kBalanceB, pmtAmountB), IntegerEntry(kInvariant, invariantCalculated), IntegerEntry(kFee, fee), IntegerEntry(kFeeScaleDelimiter, feeScale6), shareIssue, StringEntry(kShareAssetId, toBase58String(shareIssueId)), IntegerEntry(kShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareIssueId)]
345- else throw("Strict value is not equal to itself.")
346- }
347- else throw("Strict value is not equal to itself.")
348- }
292+func init (firstHarvest) = {
293+ let $t083108387 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
294+ let pmtAmountA = $t083108387._1
295+ let pmtAssetIdA = $t083108387._2
296+ let $t083928469 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
297+ let pmtAmountB = $t083928469._1
298+ let pmtAssetIdB = $t083928469._2
299+ let $t084748551 = getAssetInfo(pmtAssetIdA)
300+ let pmtStrAssetIdA = $t084748551._1
301+ let pmtAssetNameA = $t084748551._2
302+ let pmtDecimalsA = $t084748551._3
303+ let $t085568633 = getAssetInfo(pmtAssetIdB)
304+ let pmtStrAssetIdB = $t085568633._1
305+ let pmtAssetNameB = $t085568633._2
306+ let pmtDecimalsB = $t085568633._3
307+ if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
308+ then throw("Only admin can call this function")
309+ else if (isDefined(getBoolean(this, keyActive)))
310+ then throw("DApp is already active")
311+ else if ((pmtAssetIdA == pmtAssetIdB))
312+ then throw("Assets must be different")
313+ else {
314+ let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
315+ let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
316+ let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
317+ let arg1 = pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN)
318+ let arg2 = pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN)
319+ let arg3 = pow(10, 0, shareDecimals, 0, 0, DOWN)
320+ let shareInitialSupply = fraction(arg1, arg2, arg3)
321+ let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
322+ let shareIssueId = calculateAssetId(shareIssue)
323+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
324+ then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
325+ else 0
326+ if ((stake1 == stake1))
327+ then {
328+ let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
329+ then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
330+ else 0
331+ if ((stake2 == stake2))
332+ then {
333+ let baseEntry = [StringEntry(keyVersion, version), BooleanEntry(keyActive, true), StringEntry(keyAssetIdA, pmtStrAssetIdA), StringEntry(keyAssetIdB, pmtStrAssetIdB), IntegerEntry(keyBalanceA, pmtAmountA), IntegerEntry(keyBalanceB, pmtAmountB), IntegerEntry(keyCommission, commission), IntegerEntry(keyCommissionScaleDelimiter, commissionScaleDelimiter), shareIssue, StringEntry(keyShareAssetId, toBase58String(shareIssueId)), IntegerEntry(keyShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareIssueId)]
334+ if (firstHarvest)
335+ then (baseEntry ++ [BooleanEntry(keyFirstHarvest, firstHarvest), IntegerEntry(keyFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
336+ else baseEntry
337+ }
338+ else throw("Strict value is not equal to itself.")
339+ }
340+ else throw("Strict value is not equal to itself.")
341+ }
349342 }
350343
351344
352345
353346 @Callable(i)
354-func replenishWithTwoTokens (slippageTolerance) = {
355- let pmtAssetIdA = i.payments[0].assetId
356- let pmtAssetIdB = i.payments[1].assetId
357- let pmtAmountA = i.payments[0].amount
358- let pmtAmountB = i.payments[1].amount
359- let $t01192111998 = getAssetInfo(pmtAssetIdA)
360- let pmtStrAssetIdA = $t01192111998._1
361- let pmtAssetNameA = $t01192111998._2
362- let pmtDecimalsA = $t01192111998._3
363- let $t01200312197 = getAssetInfo(pmtAssetIdB)
364- let pmtStrAssetIdB = $t01200312197._1
365- let pmtAssetNameB = $t01200312197._2
366- let pmtDecimalsB = $t01200312197._3
367- let tokenRatio = fraction(fraction(scale8, balanceA, pmtAmountA), scale3, fraction(scale8, balanceB, pmtAmountB))
368- let ratioShareTokensInA = fraction(scale8, pmtAmountA, balanceA)
369- let ratioShareTokensInB = fraction(scale8, pmtAmountB, balanceB)
370- let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scale8)
371- let invariantCalculated = invariantCalc((balanceA + pmtAmountA), (balanceB + pmtAmountB))
372- if (!(isActive))
373- then throwIsInactive()
374- else if (if ((0 > slippageTolerance))
375- then true
376- else (slippageTolerance > 10))
377- then throw("Slippage tolerance must be <= 1%")
378- else if ((size(i.payments) != 2))
379- then throw("Two attached assets expected")
380- else if (if ((pmtAssetIdA != assetIdA))
381- then true
382- else (pmtAssetIdB != assetIdB))
383- then throwAssets()
384- else if (if ((((scale3 * (slippageScale3 - slippageTolerance)) / slippageScale3) > tokenRatio))
385- then true
386- else (tokenRatio > ((scale3 * (slippageScale3 + slippageTolerance)) / slippageScale3)))
387- then throw("Incorrect assets amount: amounts must have the contract ratio")
388- else if ((shareTokenToPayAmount == 0))
389- then throw("Too small amount to replenish")
390- else if (!(hasEnoughBalance))
391- then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
392- else {
393- let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
394- then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
395- else 0
396- if ((stake1 == stake1))
397- then {
398- let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
399- then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
400- else 0
401- if ((stake2 == stake2))
402- then [IntegerEntry(kBalanceA, (balanceA + pmtAmountA)), IntegerEntry(kBalanceB, (balanceB + pmtAmountB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), IntegerEntry(kInvariant, invariantCalculated), Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId)]
403- else throw("Strict value is not equal to itself.")
404- }
405- else throw("Strict value is not equal to itself.")
406- }
347+func initWithInitRatio (amtAssetA,amtAssetB,strAssetIdA,strAssetIdB,firstHarvest) = {
348+ let $t01122211309 = getAssetInfoFromString(strAssetIdA)
349+ let pmtStrAssetIdA = $t01122211309._1
350+ let pmtAssetNameA = $t01122211309._2
351+ let pmtDecimalsA = $t01122211309._3
352+ let $t01131411401 = getAssetInfoFromString(strAssetIdB)
353+ let pmtStrAssetIdB = $t01131411401._1
354+ let pmtAssetNameB = $t01131411401._2
355+ let pmtDecimalsB = $t01131411401._3
356+ if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
357+ then throw("Only admin can call this function")
358+ else if (isDefined(getBoolean(this, keyActive)))
359+ then throw("DApp is already active")
360+ else if ((strAssetIdA == strAssetIdB))
361+ then throw("Assets must be different")
362+ else {
363+ let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
364+ let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
365+ let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
366+ let shareInitialSupply = 0
367+ let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
368+ let shareIssueId = calculateAssetId(shareIssue)
369+ let baseEntry = [StringEntry(keyVersion, version), BooleanEntry(keyActive, true), StringEntry(keyAssetIdA, pmtStrAssetIdA), StringEntry(keyAssetIdB, pmtStrAssetIdB), IntegerEntry(keyBalanceInitA, amtAssetA), IntegerEntry(keyBalanceInitB, amtAssetB), IntegerEntry(keyBalanceA, 0), IntegerEntry(keyBalanceB, 0), IntegerEntry(keyCommission, commission), IntegerEntry(keyCommissionScaleDelimiter, commissionScaleDelimiter), shareIssue, StringEntry(keyShareAssetId, toBase58String(shareIssueId)), IntegerEntry(keyShareAssetSupply, shareInitialSupply)]
370+ if (firstHarvest)
371+ then (baseEntry ++ [BooleanEntry(keyFirstHarvest, firstHarvest), IntegerEntry(keyFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
372+ else baseEntry
373+ }
407374 }
408375
409376
410377
411378 @Callable(i)
412-func replenishWithOneToken (virtualSwapTokenPay,virtualSwapTokenGet) = {
413- let $t01449614571 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
414- let pmtAmount = $t01449614571._1
415- let pmtAssetId = $t01449614571._2
416- let $t01457614649 = getAssetInfo(pmtAssetId)
417- let pmtStrAssetId = $t01457614649._1
418- let pmtAssetName = $t01457614649._2
419- let pmtDecimals = $t01457614649._3
420- let pmtMinThreshold = 5000000
421- let thresholdValueForMinTolerance = 50000000
422- let tolerance = if ((thresholdValueForMinTolerance > pmtAmount))
423- then 100000
424- else 1
425- let slippageValueMinForReplenish = (scale8 - ((scale8 * tolerance) / 10000000))
426- let slippageValueMaxForReplenish = (scale8 + ((scale8 * tolerance) / 10000000))
427- let slippageValueMinForSwap = (scale8 - ((scale8 * 1) / 10000000))
428- if (!(isActive))
429- then throwIsInactive()
430- else if ((pmtMinThreshold > pmtAmount))
431- then throw((((("Payment amount " + toString(pmtAmount)) + " does not exceed the minimum amount of ") + toString(pmtMinThreshold)) + " tokens"))
379+func keepLimitForFirstHarvest (shareLimit) = valueOrElse(isActive(), if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
380+ then throw("Only admin can call this function")
381+ else [IntegerEntry(kShareLimit, shareLimit)])
382+
383+
384+
385+@Callable(i)
386+func replenishWithTwoTokens (slippageTolerance) = valueOrElse(isActive(), {
387+ let pmtAssetIdA = i.payments[0].assetId
388+ let pmtAssetIdB = i.payments[1].assetId
389+ let pmtAmountA = i.payments[0].amount
390+ let pmtAmountB = i.payments[1].amount
391+ let $t01386913946 = getAssetInfo(pmtAssetIdA)
392+ let pmtStrAssetIdA = $t01386913946._1
393+ let pmtAssetNameA = $t01386913946._2
394+ let pmtDecimalsA = $t01386913946._3
395+ let $t01395114028 = getAssetInfo(pmtAssetIdB)
396+ let pmtStrAssetIdB = $t01395114028._1
397+ let pmtAssetNameB = $t01395114028._2
398+ let pmtDecimalsB = $t01395114028._3
399+ let inital = if (if ((balanceA == 0))
400+ then (balanceB == 0)
401+ else false)
402+ then true
403+ else false
404+ let tokenRatio = if (inital)
405+ then fraction(fraction(assetInitA, scaleValue8, pmtAmountA), scaleValue3, fraction(assetInitB, scaleValue8, pmtAmountB))
406+ else fraction(fraction(balanceA, scaleValue8, pmtAmountA), scaleValue3, fraction(balanceB, scaleValue8, pmtAmountB))
407+ let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
408+ let shareTokenToPayAmount = if (inital)
409+ then fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN), pow(10, 0, shareDecimals, 0, 0, DOWN))
410+ else fraction(min([fraction(pmtAmountA, scaleValue8, balanceA), fraction(pmtAmountB, scaleValue8, balanceB)]), shareAssetSupply, scaleValue8)
411+ if (if ((0 > slippageTolerance))
412+ then true
413+ else (slippageTolerance > slippageToleranceDelimiter))
414+ then throw(((("Slippage tolerance must be between 0 and " + toString(slippageToleranceDelimiter)) + " inclusively. Actual: ") + toString(slippageTolerance)))
415+ else if ((size(i.payments) != 2))
416+ then throw("Two attached assets expected")
417+ else if (if ((pmtAssetIdA != assetIdA))
418+ then true
419+ else (pmtAssetIdB != assetIdB))
420+ then throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
421+ else if (if ((((scaleValue3 * (slippageToleranceDelimiter - slippageTolerance)) / slippageToleranceDelimiter) > tokenRatio))
422+ then true
423+ else (tokenRatio > ((scaleValue3 * (slippageToleranceDelimiter + slippageTolerance)) / slippageToleranceDelimiter)))
424+ then throw("Incorrect assets amount: amounts must have the contract ratio")
425+ else if ((shareTokenToPayAmount == 0))
426+ then throw("Too small amount to replenish")
427+ else if (!(hasEnoughBalance))
428+ then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
429+ else {
430+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
431+ then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
432+ else 0
433+ if ((stake1 == stake1))
434+ then {
435+ let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
436+ then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
437+ else 0
438+ if ((stake2 == stake2))
439+ then [Reissue(shareAssetId, shareTokenToPayAmount, true), IntegerEntry(keyBalanceA, (balanceA + pmtAmountA)), IntegerEntry(keyBalanceB, (balanceB + pmtAmountB)), IntegerEntry(keyShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId)]
440+ else throw("Strict value is not equal to itself.")
441+ }
442+ else throw("Strict value is not equal to itself.")
443+ }
444+ })
445+
446+
447+
448+@Callable(i)
449+func withdraw () = valueOrElse(isActive(), {
450+ let $t01683416909 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
451+ let pmtAmount = $t01683416909._1
452+ let pmtAssetId = $t01683416909._2
453+ let amountToPayA = fraction(pmtAmount, balanceA, shareAssetSupply)
454+ let amountToPayB = fraction(pmtAmount, balanceB, shareAssetSupply)
455+ if ((size(i.payments) != 1))
456+ then throw("One attached payment expected")
457+ else if ((pmtAssetId != shareAssetId))
458+ then throw(("Incorrect asset attached. Expected: " + toBase58String(shareAssetId)))
459+ else if (!(hasEnoughBalance))
460+ then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
461+ else {
462+ let stake1 = if (containsElement(stakingAssets, strAssetIdA))
463+ then invoke(this, "stakeUnstake", [false, amountToPayA, strAssetIdA], nil)
464+ else 0
465+ if ((stake1 == stake1))
466+ then {
467+ let stake2 = if (containsElement(stakingAssets, strAssetIdB))
468+ then invoke(this, "stakeUnstake", [false, amountToPayB, strAssetIdB], nil)
469+ else 0
470+ if ((stake2 == stake2))
471+ then [IntegerEntry(keyBalanceA, (balanceA - amountToPayA)), IntegerEntry(keyBalanceB, (balanceB - amountToPayB)), IntegerEntry(keyShareAssetSupply, (shareAssetSupply - pmtAmount)), Burn(shareAssetId, pmtAmount), ScriptTransfer(i.caller, amountToPayA, assetIdA), ScriptTransfer(i.caller, amountToPayB, assetIdB)]
472+ else throw("Strict value is not equal to itself.")
473+ }
474+ else throw("Strict value is not equal to itself.")
475+ }
476+ })
477+
478+
479+
480+@Callable(i)
481+func exchange (minAmountToReceive) = valueOrElse(isActive(), {
482+ let $t01821518290 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
483+ let pmtAmount = $t01821518290._1
484+ let pmtAssetId = $t01821518290._2
485+ if (if ((balanceA == 0))
486+ then true
487+ else (balanceB == 0))
488+ then throw("Can't exchange with zero balance")
489+ else if ((0 >= minAmountToReceive))
490+ then throw(("Minimal amount to receive must be positive. Actual: " + toString(minAmountToReceive)))
432491 else if ((size(i.payments) != 1))
433492 then throw("One attached payment expected")
434493 else if (!(hasEnoughBalance))
435494 then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
436- else if (if ((pmtAssetId != assetIdA))
437- then (pmtAssetId != assetIdB)
438- else false)
439- then throwAssets()
440- else {
441- let $t01566116426 = if ((pmtAssetId == assetIdA))
442- then $Tuple7((pmtAmount - virtualSwapTokenPay), virtualSwapTokenGet, (balanceA + virtualSwapTokenPay), (balanceB - virtualSwapTokenGet), invariantCalc((balanceA + pmtAmount), balanceB), (balanceA + pmtAmount), balanceB)
443- else $Tuple7(virtualSwapTokenGet, (pmtAmount - virtualSwapTokenPay), (balanceA - virtualSwapTokenGet), (balanceB + virtualSwapTokenPay), invariantCalc(balanceA, (balanceB + pmtAmount)), balanceA, (balanceB + pmtAmount))
444- let virtualReplenishA = $t01566116426._1
445- let virtualReplenishB = $t01566116426._2
446- let balanceAfterSwapA = $t01566116426._3
447- let balanceAfterSwapB = $t01566116426._4
448- let invariantCalculated = $t01566116426._5
449- let newBalanceA = $t01566116426._6
450- let newBalanceB = $t01566116426._7
451- let newBalanceEntry = if ((pmtAssetId == assetIdA))
452- then IntegerEntry(kBalanceA, newBalanceA)
453- else IntegerEntry(kBalanceB, newBalanceB)
454- let invariantNew = invariantCalc(balanceAfterSwapA, balanceAfterSwapB)
455- let invariantEstimatedRatio = fraction(scale8, invariant, invariantNew)
456- let ratioVirtualBalanceToVirtualReplenish = (fraction((scale8 * scale8), balanceAfterSwapA, balanceAfterSwapB) / fraction(scale8, virtualReplenishA, virtualReplenishB))
457- let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
458- if (if ((slippageValueMinForSwap >= invariantEstimatedRatio))
459- then true
460- else (invariant > invariantNew))
461- then throw("Incorrect virtualSwapTokenPay or virtualSwapTokenGet value")
462- else if (if ((slippageValueMinForReplenish > ratioVirtualBalanceToVirtualReplenish))
463- then true
464- else (ratioVirtualBalanceToVirtualReplenish > slippageValueMaxForReplenish))
465- then throw("Swap with virtualSwapTokenPay and virtualSwapTokenGet is possible, but ratio after virtual swap is incorrect")
466- else if (if ((dAppThresholdAmount > newBalanceA))
467- then true
468- else (dAppThresholdAmount > newBalanceB))
469- then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB)
470- else {
471- let stake1 = if (containsElement(stakingAssets, pmtStrAssetId))
472- then invoke(this, "stakeUnstake", [true, pmtAmount, pmtStrAssetId], nil)
473- else 0
474- if ((stake1 == stake1))
475- then {
476- let ratioShareTokensInA = fraction(virtualReplenishA, scale8, balanceAfterSwapA)
477- let ratioShareTokensInB = fraction(virtualReplenishB, scale8, balanceAfterSwapB)
478- let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scale8)
479-[Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), newBalanceEntry, IntegerEntry(kInvariant, invariantCalculated)]
480- }
481- else throw("Strict value is not equal to itself.")
482- }
495+ else if ((pmtAssetId == assetIdA))
496+ then {
497+ let assetIdSend = assetIdB
498+ let $t01884518967 = calculateFees(pmtAmount, minAmountToReceive, balanceA, balanceB)
499+ let amountWithoutFee = $t01884518967._1
500+ let amountWithFee = $t01884518967._2
501+ let governanceReward = $t01884518967._3
502+ let newBalanceA = (balanceA + pmtAmount)
503+ let newBalanceB = ((balanceB - amountWithFee) - governanceReward)
504+ let stake1 = if (containsElement(stakingAssets, strAssetIdA))
505+ then invoke(this, "stakeUnstake", [true, pmtAmount, strAssetIdA], nil)
506+ else 0
507+ if ((stake1 == stake1))
508+ then {
509+ let stake2 = if (containsElement(stakingAssets, strAssetIdB))
510+ then invoke(this, "stakeUnstake", [false, (amountWithFee + governanceReward), strAssetIdB], nil)
511+ else 0
512+ if ((stake2 == stake2))
513+ then [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)]
514+ else throw("Strict value is not equal to itself.")
515+ }
516+ else throw("Strict value is not equal to itself.")
483517 }
484- }
518+ else if ((pmtAssetId == assetIdB))
519+ then {
520+ let assetIdSend = assetIdA
521+ let $t01992220044 = calculateFees(pmtAmount, minAmountToReceive, balanceB, balanceA)
522+ let amountWithoutFee = $t01992220044._1
523+ let amountWithFee = $t01992220044._2
524+ let governanceReward = $t01992220044._3
525+ let newBalanceA = ((balanceA - amountWithFee) - governanceReward)
526+ let newBalanceB = (balanceB + pmtAmount)
527+ let stake1 = if (containsElement(stakingAssets, strAssetIdA))
528+ then invoke(this, "stakeUnstake", [false, (amountWithFee + governanceReward), strAssetIdA], nil)
529+ else 0
530+ if ((stake1 == stake1))
531+ then {
532+ let stake2 = if (containsElement(stakingAssets, strAssetIdB))
533+ then invoke(this, "stakeUnstake", [true, pmtAmount, strAssetIdB], nil)
534+ else 0
535+ if ((stake2 == stake2))
536+ then [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)]
537+ else throw("Strict value is not equal to itself.")
538+ }
539+ else throw("Strict value is not equal to itself.")
540+ }
541+ else throw(((("Incorrect asset attached. Expected: " + strAssetIdA) + " or ") + strAssetIdB))
542+ })
485543
486544
487545
488546 @Callable(i)
489-func withdraw () = {
490- let $t01865218795 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
491- let pmtAmount = $t01865218795._1
492- let pmtAssetId = $t01865218795._2
493- let amountToPayA = fraction(pmtAmount, balanceA, shareAssetSupply)
494- let amountToPayB = fraction(pmtAmount, balanceB, shareAssetSupply)
495- let invariantCalculated = invariantCalc((balanceA - amountToPayA), (balanceB - amountToPayB))
496- if (!(isActive))
497- then throwIsInactive()
498- else if ((size(i.payments) != 1))
499- then throw("One attached payment expected")
500- else if ((pmtAssetId != shareAssetId))
501- then throw(("Incorrect asset attached. Expected: " + toBase58String(shareAssetId)))
502- else if (!(hasEnoughBalance))
503- then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
504- else {
505- let stake1 = if (containsElement(stakingAssets, strAssetIdA))
506- then invoke(this, "stakeUnstake", [false, amountToPayA, strAssetIdA], nil)
507- else 0
508- if ((stake1 == stake1))
509- then {
510- let stake2 = if (containsElement(stakingAssets, strAssetIdB))
511- then invoke(this, "stakeUnstake", [false, amountToPayB, strAssetIdB], nil)
512- else 0
513- if ((stake2 == stake2))
514- then [IntegerEntry(kBalanceA, (balanceA - amountToPayA)), IntegerEntry(kBalanceB, (balanceB - amountToPayB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply - pmtAmount)), IntegerEntry(kInvariant, invariantCalculated), Burn(shareAssetId, pmtAmount), ScriptTransfer(i.caller, amountToPayA, assetIdA), ScriptTransfer(i.caller, amountToPayB, assetIdB)]
515- else throw("Strict value is not equal to itself.")
516- }
517- else throw("Strict value is not equal to itself.")
518- }
519- }
520-
521-
522-
523-@Callable(i)
524-func exchange (estimatedAmountToReceive,minAmountToReceive) = {
525- let $t02030920384 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
526- let pmtAmount = $t02030920384._1
527- let pmtAssetId = $t02030920384._2
528- if (!(isActive))
529- then throwIsInactive()
530- else if ((0 >= estimatedAmountToReceive))
531- then throw(("Estimated amount must be positive. Actual: " + toString(estimatedAmountToReceive)))
532- else if ((minAmountToReceive > estimatedAmountToReceive))
533- then throw(((("Minimal amount can't be greater than estimated. Estimated: " + toString(estimatedAmountToReceive)) + ". Minimal: ") + toString(minAmountToReceive)))
534- else if ((size(i.payments) != 1))
535- then throw("One attached payment expected")
536- else if (!(hasEnoughBalance))
537- then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
538- else if (if ((pmtAssetId != assetIdA))
539- then (pmtAssetId != assetIdB)
540- else false)
541- then throwAssets()
542- else if ((10000000 > pmtAmount))
543- then throw("Only swap of 10.000000 or more tokens is allowed")
544- else if (if ((exchangeRatioLimitMin > fraction(scale8, minAmountToReceive, pmtAmount)))
545- then true
546- else (fraction(scale8, estimatedAmountToReceive, pmtAmount) > exchangeRatioLimitMax))
547- then throw("Incorrect args and pmt ratio")
548- else {
549- let sendAssetId = if ((pmtAssetId == assetIdA))
550- then assetIdB
551- else assetIdA
552- let amount = calculateSendAmount(estimatedAmountToReceive, minAmountToReceive, pmtAmount, pmtAssetId)
553- let governanceReward = fraction(amount, feeGovernance, feeScale6)
554- let amountMinusFee = fraction(amount, (feeScale6 - fee), feeScale6)
555- let $t02180622068 = if ((pmtAssetId == assetIdA))
556- then $Tuple2((balanceA + pmtAmount), ((balanceB - amountMinusFee) - governanceReward))
557- else $Tuple2(((balanceA - amountMinusFee) - governanceReward), (balanceB + pmtAmount))
558- let newBalanceA = $t02180622068._1
559- let newBalanceB = $t02180622068._2
560- let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
561- if (if ((dAppThresholdAmount > newBalanceA))
562- then true
563- else (dAppThresholdAmount > newBalanceB))
564- then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB)
565- else {
566- let $t02236622439 = getAssetInfo(pmtAssetId)
567- let pmtStrAssetId = $t02236622439._1
568- let pmtAssetName = $t02236622439._2
569- let pmtDecimals = $t02236622439._3
570- let $t02245222529 = getAssetInfo(sendAssetId)
571- let sendStrAssetId = $t02245222529._1
572- let sendAssetName = $t02245222529._2
573- let sendDecimals = $t02245222529._3
574- let stake1 = if (containsElement(stakingAssets, pmtStrAssetId))
575- then invoke(this, "stakeUnstake", [true, pmtAmount, pmtStrAssetId], nil)
576- else 0
577- if ((stake1 == stake1))
578- then {
579- let stake2 = if (containsElement(stakingAssets, sendStrAssetId))
580- then invoke(this, "stakeUnstake", [false, (amountMinusFee + governanceReward), sendStrAssetId], nil)
581- else 0
582- if ((stake2 == stake2))
583- then [IntegerEntry(kBalanceA, newBalanceA), IntegerEntry(kBalanceB, newBalanceB), IntegerEntry(kInvariant, invariantCalc(newBalanceA, newBalanceB)), ScriptTransfer(i.caller, amountMinusFee, sendAssetId), ScriptTransfer(walletAddress, governanceReward, sendAssetId)]
584- else throw("Strict value is not equal to itself.")
585- }
586- else throw("Strict value is not equal to itself.")
587- }
588- }
589- }
590-
591-
592-
593-@Callable(i)
594-func shutdown () = if (!(isActive))
595- then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, kCause), "the cause wasn't specified")))
596- else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, admStartStop], i.callerPublicKey)))
597- then throwOnlyAdmin()
547+func shutdown () = if (!(active))
548+ then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, keyCause), "the cause wasn't specified")))
549+ else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStartStop], i.callerPublicKey)))
550+ then throw("Only admin can call this function")
598551 else suspend("Paused by admin")
599552
600553
601554
602555 @Callable(i)
603-func activate () = if (isActive)
604- then throwIsActive()
605- else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, admStartStop], i.callerPublicKey)))
606- then throwOnlyAdmin()
607- else [BooleanEntry(kActive, true), DeleteEntry(kCause)]
556+func activate () = if (active)
557+ then throw("DApp is already active")
558+ else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStartStop], i.callerPublicKey)))
559+ then throw("Only admin can call this function")
560+ else [BooleanEntry(keyActive, true), DeleteEntry(keyCause)]
608561
609562
610563
611564 @Callable(i)
612-func takeIntoAccountExtraFunds () = {
565+func takeIntoAccountExtraFunds () = valueOrElse(isActive(), {
613566 let amountEnrollA = (accountBalanceWithStakedA - balanceA)
614567 let amountEnrollB = (accountBalanceWithStakedB - balanceB)
615- let invariantNew = invariantCalc((balanceA + amountEnrollA), (balanceB + amountEnrollB))
616- if (!(isActive))
617- then throwIsInactive()
618- else if ((i.caller != walletAddress))
619- then throw("Only the wallet can call this function")
620- else if (if ((0 > amountEnrollA))
621- then true
622- else (0 > amountEnrollB))
623- then suspend("Enroll amount negative")
624- else if (if ((amountEnrollA == 0))
625- then (amountEnrollB == 0)
626- else false)
627- then throw("No money to take")
628- else {
629- let stake1 = if (if (containsElement(stakingAssets, strAssetIdA))
630- then (amountEnrollA > 0)
631- else false)
632- then invoke(this, "stakeUnstake", [true, amountEnrollA, strAssetIdA], nil)
633- else 0
634- if ((stake1 == stake1))
635- then {
636- let stake2 = if (if (containsElement(stakingAssets, strAssetIdB))
637- then (amountEnrollB > 0)
638- else false)
639- then invoke(this, "stakeUnstake", [true, amountEnrollB, strAssetIdB], nil)
640- else 0
641- if ((stake2 == stake2))
642- then [IntegerEntry(kInvariant, invariantNew), IntegerEntry(kBalanceA, (balanceA + amountEnrollA)), IntegerEntry(kBalanceB, (balanceB + amountEnrollB)), IntegerEntry(("last_income_" + strAssetIdA), amountEnrollA), IntegerEntry(("last_income_" + strAssetIdB), amountEnrollB)]
643- else throw("Strict value is not equal to itself.")
644- }
645- else throw("Strict value is not equal to itself.")
646- }
647- }
568+ if ((i.caller != walletAddress))
569+ then throw("Only the wallet can call this function")
570+ else if (if ((0 > amountEnrollA))
571+ then true
572+ else (0 > amountEnrollB))
573+ then suspend("Enroll amount negative")
574+ else if (if ((amountEnrollA == 0))
575+ then (amountEnrollB == 0)
576+ else false)
577+ then throw("No money to take")
578+ else {
579+ let stake1 = if (containsElement(stakingAssets, strAssetIdA))
580+ then invoke(this, "stakeUnstake", [true, amountEnrollA, strAssetIdA], nil)
581+ else 0
582+ if ((stake1 == stake1))
583+ then {
584+ let stake2 = if (containsElement(stakingAssets, strAssetIdB))
585+ then invoke(this, "stakeUnstake", [true, amountEnrollB, strAssetIdB], nil)
586+ else 0
587+ if ((stake2 == stake2))
588+ then [IntegerEntry(keyBalanceA, (balanceA + amountEnrollA)), IntegerEntry(keyBalanceB, (balanceB + amountEnrollB)), IntegerEntry(("last_income_" + strAssetIdA), amountEnrollA), IntegerEntry(("last_income_" + strAssetIdB), amountEnrollB)]
589+ else throw("Strict value is not equal to itself.")
590+ }
591+ else throw("Strict value is not equal to itself.")
592+ }
593+ })
648594
649595
650596
651597 @Callable(i)
652598 func stakeUnstake (stake,amount,assetIdString) = if ((i.caller != this))
653599 then throw("Only contract itself can invoke this function")
654- else {
655- let $t02559125694 = calcStakingParams(stake, amount, fromBase58String(assetIdString))
656- let call = $t02559125694._1
657- let addr = $t02559125694._2
658- let params = $t02559125694._3
659- let payments = $t02559125694._4
660- let inv = invoke(addr, call, params, payments)
661- if ((inv == inv))
662- then nil
663- else throw("Strict value is not equal to itself.")
664- }
600+ else if ((assetIdString == "WAVES"))
601+ then {
602+ let pool = addressFromStringValue(valueOrErrorMessage(getString(oracle, keyLeasingPool), "No leasing pool in oracle"))
603+ let leasingId = getBinary(this, keyLeasingId)
604+ let leasingAmount = valueOrElse(getInteger(this, keyLeasingAmount), 0)
605+ let newLeaseAmount = if (stake)
606+ then (leasingAmount + amount)
607+ else (leasingAmount - amount)
608+ let newLease = Lease(pool, newLeaseAmount)
609+ let newLeaseId = calculateLeaseId(newLease)
610+ let baseEtry = [newLease, BinaryEntry(keyLeasingId, newLeaseId), IntegerEntry(keyLeasingAmount, newLeaseAmount)]
611+ match leasingId {
612+ case lId: ByteVector =>
613+ ([LeaseCancel(lId)] ++ baseEtry)
614+ case _ =>
615+ baseEtry
616+ }
617+ }
618+ else {
619+ let $t02377823881 = calcStakingParams(stake, amount, fromBase58String(assetIdString))
620+ let call = $t02377823881._1
621+ let addr = $t02377823881._2
622+ let params = $t02377823881._3
623+ let payments = $t02377823881._4
624+ let inv = invoke(addr, call, params, payments)
625+ if ((inv == inv))
626+ then nil
627+ else throw("Strict value is not equal to itself.")
628+ }
665629
666630
667631
668632 @Callable(i)
669-func stakeAll () = if (!(isActive))
670- then throw("DApp is inactive at this moment")
671- else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, admStartStop], i.callerPublicKey)))
672- then throw("Only admin can call this function")
673- else {
674- let stake1 = if (containsElement(stakingAssets, strAssetIdA))
675- then {
676- let amountA = (balanceA - stakedAmountA)
677- if ((amountA > 0))
678- then invoke(this, "stakeUnstake", [true, amountA, strAssetIdA], nil)
679- else 0
680- }
681- else 0
682- if ((stake1 == stake1))
683- then {
684- let stake2 = if (containsElement(stakingAssets, strAssetIdB))
685- then {
686- let amountB = (balanceB - stakedAmountB)
687- if ((amountB > 0))
688- then invoke(this, "stakeUnstake", [true, amountB, strAssetIdB], nil)
689- else 0
690- }
691- else 0
692- if ((stake2 == stake2))
693- then nil
694- else throw("Strict value is not equal to itself.")
695- }
696- else throw("Strict value is not equal to itself.")
697- }
633+func stakeAll () = valueOrElse(isActive(), if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStartStop], i.callerPublicKey)))
634+ then throw("Only admin can call this function")
635+ else {
636+ let stake1 = if (containsElement(stakingAssets, strAssetIdA))
637+ then {
638+ let amountA = (balanceA - stakedAmountA)
639+ if ((amountA > 0))
640+ then invoke(this, "stakeUnstake", [true, amountA, strAssetIdA], nil)
641+ else 0
642+ }
643+ else 0
644+ if ((stake1 == stake1))
645+ then {
646+ let stake2 = if (containsElement(stakingAssets, strAssetIdB))
647+ then {
648+ let amountB = (balanceB - stakedAmountB)
649+ if ((amountB > 0))
650+ then invoke(this, "stakeUnstake", [true, amountB, strAssetIdB], nil)
651+ else 0
652+ }
653+ else 0
654+ if ((stake2 == stake2))
655+ then nil
656+ else throw("Strict value is not equal to itself.")
657+ }
658+ else throw("Strict value is not equal to itself.")
659+ })
698660
699661
700662 @Verifier(tx)
701663 func verify () = {
702664 let multiSignedByAdmins = {
703665 let adminPubKey1Signed = if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
704666 then 1
705667 else 0
706668 let adminPubKey2Signed = if (sigVerify(tx.bodyBytes, tx.proofs[1], adminPubKey2))
707669 then 1
708670 else 0
709671 let adminPubKey3Signed = if (sigVerify(tx.bodyBytes, tx.proofs[2], adminPubKey3))
710672 then 1
711673 else 0
712674 (((adminPubKey1Signed + adminPubKey2Signed) + adminPubKey3Signed) >= 2)
713675 }
714676 match tx {
715677 case inv: InvokeScriptTransaction =>
716678 let callTakeIntoAccount = if ((inv.dApp == this))
717679 then (inv.function == "takeIntoAccountExtraFunds")
718680 else false
681+ let exchangeToWaves = if (if (if ((inv.dApp == USDNToWavesExchanger))
682+ then (inv.function == "exchange")
683+ else false)
684+ then (assetIdA == USDN)
685+ else false)
686+ then true
687+ else if (if ((assetIdB == USDN))
688+ then (size(inv.payments) == 1)
689+ else false)
690+ then (inv.payments[0].assetId == USDN)
691+ else false
692+ let exchangeToNSBTs = if (if (if ((inv.dApp == USDNToNSBTExchanger))
693+ then (inv.function == "exchange")
694+ else false)
695+ then (assetIdA == NSBT)
696+ else false)
697+ then true
698+ else if (if ((assetIdB == NSBT))
699+ then (size(inv.payments) == 1)
700+ else false)
701+ then (inv.payments[0].assetId == USDN)
702+ else false
719703 let signedByAdmin = if (if (if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
720704 then true
721705 else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey2))
722706 then true
723707 else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey3))
724708 then true
725- else sigVerify(tx.bodyBytes, tx.proofs[0], admStaking)
726- if (if (callTakeIntoAccount)
709+ else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKeyStaking)
710+ if (if (if (if (callTakeIntoAccount)
711+ then true
712+ else exchangeToWaves)
713+ then true
714+ else exchangeToNSBTs)
727715 then signedByAdmin
728716 else false)
729717 then true
730718 else multiSignedByAdmins
731719 case _ =>
732720 multiSignedByAdmins
733721 }
734722 }
735723

github/deemru/w8io/873ac7e 
190.00 ms