tx · 9qP6orXxGJQLsJTmJtuF6DXFpS1dqFm36e2ELHq6tMom

3N95taAsiWcVMmXdVShZ2ann6MAboXrFT1b:  -0.01400000 Waves

2021.07.20 16:18 [1621989] smart account 3N95taAsiWcVMmXdVShZ2ann6MAboXrFT1b > SELF 0.00000000 Waves

{ "type": 13, "id": "9qP6orXxGJQLsJTmJtuF6DXFpS1dqFm36e2ELHq6tMom", "fee": 1400000, "feeAssetId": null, "timestamp": 1626787132542, "version": 2, "chainId": 84, "sender": "3N95taAsiWcVMmXdVShZ2ann6MAboXrFT1b", "senderPublicKey": "EDQ1awBPdPh8m86bDaSLf5pynLiRVX4kcPLMxYLRScq5", "proofs": [ "2YyzjC5LBqzSRHJTc1UiPzNACPx1vRJZdTDvntmAH8pDvYXwjkzuVLBWkanzEwfnsdgLBRdsSEcDZeDJpaSBDBw2", "65sHiKSFwPKowRN3swNBBqZqtVbs8HDyY3rREfz6Yu99d4FG5VnosqeSsWWXecQw3hiGKa3Rv3zf5f4mUNCTn1Ar" ], "script": "base64:AAIEAAAAAAAAACoIAhIDCgEEEgcKBQEBCAgEEgMKAQESAwoBARIAEgMKAQESABIAEgMKAQEAAABHAAAAAAd2ZXJzaW9uAgAAAAUxLjAuMAAAAAAKa2V5VmVyc2lvbgIAAAAHdmVyc2lvbgAAAAAJa2V5QWN0aXZlAgAAAAZhY3RpdmUAAAAAC2tleUFzc2V0SWRBAgAAAApBX2Fzc2V0X2lkAAAAAAtrZXlBc3NldElkQgIAAAAKQl9hc3NldF9pZAAAAAALa2V5QmFsYW5jZUECAAAAD0FfYXNzZXRfYmFsYW5jZQAAAAALa2V5QmFsYW5jZUICAAAAD0JfYXNzZXRfYmFsYW5jZQAAAAAPa2V5QmFsYW5jZUluaXRBAgAAAAxBX2Fzc2V0X2luaXQAAAAAD2tleUJhbGFuY2VJbml0QgIAAAAMQl9hc3NldF9pbml0AAAAAA9rZXlTaGFyZUFzc2V0SWQCAAAADnNoYXJlX2Fzc2V0X2lkAAAAABNrZXlTaGFyZUFzc2V0U3VwcGx5AgAAABJzaGFyZV9hc3NldF9zdXBwbHkAAAAADWtleUNvbW1pc3Npb24CAAAACmNvbW1pc3Npb24AAAAAG2tleUNvbW1pc3Npb25TY2FsZURlbGltaXRlcgIAAAAaY29tbWlzc2lvbl9zY2FsZV9kZWxpbWl0ZXIAAAAACGtleUNhdXNlAgAAAA5zaHV0ZG93bl9jYXVzZQAAAAAPa2V5Rmlyc3RIYXJ2ZXN0AgAAAA1maXJzdF9oYXJ2ZXN0AAAAABVrZXlGaXJzdEhhcnZlc3RIZWlnaHQCAAAAFGZpcnN0X2hhcnZlc3RfaGVpZ2h0AAAAAAtrU2hhcmVMaW1pdAIAAAAcc2hhcmVfbGltaXRfb25fZmlyc3RfaGFydmVzdAAAAAALa0Jhc2VQZXJpb2QCAAAAC2Jhc2VfcGVyaW9kAAAAAA1rUGVyaW9kTGVuZ3RoAgAAAA1wZXJpb2RfbGVuZ3RoAAAAAAxrU3RhcnRIZWlnaHQCAAAADHN0YXJ0X2hlaWdodAAAAAATa0ZpcnN0SGFydmVzdEhlaWdodAIAAAAUZmlyc3RfaGFydmVzdF9oZWlnaHQAAAAADGFkbWluUHViS2V5MQEAAAAgBM915WTQwQ9OZ7kfE2TEGg3qhCRCMX0zkF1AWAqdk0oAAAAA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QgAAAAUFAAAACXNoYXJlTmFtZQUAAAAQc2hhcmVEZXNjcmlwdGlvbgUAAAASc2hhcmVJbml0aWFsU3VwcGx5BQAAAA1zaGFyZURlY2ltYWxzBgQAAAAMc2hhcmVJc3N1ZUlkCQAEOAAAAAEFAAAACnNoYXJlSXNzdWUEAAAACWJhc2VFbnRyeQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAAAprZXlWZXJzaW9uBQAAAAd2ZXJzaW9uCQAETAAAAAIJAQAAAAxCb29sZWFuRW50cnkAAAACBQAAAAlrZXlBY3RpdmUGCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAAC2tleUFzc2V0SWRBBQAAAA5wbXRTdHJBc3NldElkQQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAAAtrZXlBc3NldElkQgUAAAAOcG10U3RyQXNzZXRJZEIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAC2tleUJhbGFuY2VBBQAAAApwbXRBbW91bnRBCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAtrZXlCYWxhbmNlQgUAAAAKcG10QW1vdW50QgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAANa2V5Q29tbWlzc2lvbgUAAAAKY29tbWlzc2lvbgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAba2V5Q29tbWlzc2lvblNjYWxlRGVsaW1pdGVyBQAAABhjb21taXNzaW9uU2NhbGVEZWxpbWl0ZXIJAARMAAAAAgUAAAAKc2hhcmVJc3N1ZQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAAA9rZXlTaGFyZUFzc2V0SWQJAAJYAAAAAQUAAAAMc2hhcmVJc3N1ZUlkCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABNrZXlTaGFyZUFzc2V0U3VwcGx5BQAAABJzaGFyZUluaXRpYWxTdXBwbHkJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAABJzaGFyZUluaXRpYWxTdXBwbHkFAAAADHNoYXJlSXNzdWVJZAUAAAADbmlsAwUAAAAMZmlyc3RIYXJ2ZXN0CQAETgAAAAIFAAAACWJhc2VFbnRyeQkABEwAAAACCQEAAAAMQm9vbGVhbkVudHJ5AAAAAgUAAAAPa2V5Rmlyc3RIYXJ2ZXN0BQAAAAxmaXJzdEhhcnZlc3QJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAFWtleUZpcnN0SGFydmVzdEhlaWdodAkAAGQAAAACBQAAAAtzdGFydEhlaWdodAkAAGgAAAACBQAAABVmaXJzdEhhcnZlc3RFbmRQZXJpb2QFAAAADHBlcmlvZExlbmd0aAUAAAADbmlsBQAAAAliYXNlRW50cnkAAAABaQEAAAARaW5pdFdpdGhJbml0UmF0aW8AAAAFAAAACWFtdEFzc2V0QQAAAAlhbXRBc3NldEIAAAALc3RyQXNzZXRJZEEAAAALc3RyQXNzZXRJZEIAAAAMZmlyc3RIYXJ2ZXN0BAAAAAskdDA5MDEwOTA5NwkBAAAAFmdldEFzc2V0SW5mb0Zyb21TdHJpbmcAAAABBQAAAAtzdHJBc3NldElkQQQAAAAOcG10U3RyQXNzZXRJZEEIBQAAAAskdDA5MDEwOTA5NwAAAAJfMQQAAAANcG10QXNzZXROYW1lQQgFAAAACyR0MDkwMTA5MDk3AAAAAl8yBAAAAAxwbXREZWNpbWFsc0EIBQAAAAskdDA5MDEwOTA5NwAAAAJfMwQAAAALJHQwOTEwMjkxODkJAQAAABZnZXRBc3NldEluZm9Gcm9tU3RyaW5nAAAAAQUAAAALc3RyQXNzZXRJZEIEAAAADnBtdFN0ckFzc2V0SWRCCAUAAAALJHQwOTEwMjkxODkAAAACXzEEAAAADXBtdEFzc2V0TmFtZUIIBQAAAAskdDA5MTAyOTE4OQAAAAJfMgQAAAAMcG10RGVjaW1hbHNCCAUAAAALJHQwOTEwMjkxODkAAAACXzMDCQEAAAABIQAAAAEJAQAAAA9jb250YWluc0VsZW1lbnQAAAACCQAETAAAAAIFAAAADGFkbWluUHViS2V5MQkABEwAAAACBQAAAAxhZG1pblB1YktleTIJAARMAAAAAgUAAAAMYWRtaW5QdWJLZXkzCQAETAAAAAIFAAAAEmFkbWluUHViS2V5U3Rha2luZwUAAAADbmlsCAUAAAABaQAAAA9jYWxsZXJQdWJsaWNLZXkJAAACAAAAAQIAAAAhT25seSBhZG1pbiBjYW4gY2FsbCB0aGlzIGZ1bmN0aW9uAwkBAAAACWlzRGVmaW5lZAAAAAEJAAQbAAAAAgUAAAAEdGhpcwUAAAAJa2V5QWN0aXZlCQAAAgAAAAECAAAAFkRBcHAgaXMgYWxyZWFkeSBhY3RpdmUDCQAAAAAAAAIFAAAAC3N0ckFzc2V0SWRBBQAAAAtzdHJBc3NldElkQgkAAAIAAAABAgAAABhBc3NldHMgbXVzdCBiZSBkaWZmZXJlbnQEAAAACXNoYXJlTmFtZQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAABcwkAAS8AAAACBQAAAA1wbXRBc3NldE5hbWVBAAAAAAAAAAAHAgAAAAFfCQABLwAAAAIFAAAADXBtdEFzc2V0TmFtZUIAAAAAAAAAAAcEAAAAEHNoYXJlRGVzY3JpcHRpb24JAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAACJTaGFyZVRva2VuIG9mIFN3b3BGaSBwcm90b2NvbCBmb3IgBQAAAA1wbXRBc3NldE5hbWVBAgAAAAUgYW5kIAUAAAANcG10QXNzZXROYW1lQgIAAAAMIGF0IGFkZHJlc3MgCQAEJQAAAAEFAAAABHRoaXMEAAAADXNoYXJlRGVjaW1hbHMJAABpAAAAAgkAAGQAAAACBQAAAAxwbXREZWNpbWFsc0EFAAAADHBtdERlY2ltYWxzQgAAAAAAAAAAAgQAAAASc2hhcmVJbml0aWFsU3VwcGx5AAAAAAAAAAAABAAAAApzaGFyZUlzc3VlCQAEQgAAAAUFAAAACXNoYXJlTmFtZQUAAAAQc2hhcmVEZXNjcmlwdGlvbgUAAAASc2hhcmVJbml0aWFsU3VwcGx5BQAAAA1zaGFyZURlY2ltYWxzBgQAAAAMc2hhcmVJc3N1ZUlkCQAEOAAAAAEFAAAACnNoYXJlSXNzdWUEAAAACWJhc2VFbnRyeQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAAAprZXlWZXJzaW9uBQAAAAd2ZXJzaW9uCQAETAAAAAIJAQAAAAxCb29sZWFuRW50cnkAAAACBQAAAAlrZXlBY3RpdmUGCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAAC2tleUFzc2V0SWRBBQAAAA5wbXRTdHJBc3NldElkQQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAAAtrZXlBc3NldElkQgUAAAAOcG10U3RyQXNzZXRJZEIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAD2tleUJhbGFuY2VJbml0QQUAAAAJYW10QXNzZXRBCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAA9rZXlCYWxhbmNlSW5pdEIFAAAACWFtdEFzc2V0QgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAALa2V5QmFsYW5jZUEAAAAAAAAAAAAJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAC2tleUJhbGFuY2VCAAAAAAAAAAAACQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAA1rZXlDb21taXNzaW9uBQAAAApjb21taXNzaW9uCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABtrZXlDb21taXNzaW9uU2NhbGVEZWxpbWl0ZXIFAAAAGGNvbW1pc3Npb25TY2FsZURlbGltaXRlcgkABEwAAAACBQAAAApzaGFyZUlzc3VlCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAAD2tleVNoYXJlQXNzZXRJZAkAAlgAAAABBQAAAAxzaGFyZUlzc3VlSWQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAE2tleVNoYXJlQXNzZXRTdXBwbHkFAAAAEnNoYXJlSW5pdGlhbFN1cHBseQUAAAADbmlsAwUAAAAMZmlyc3RIYXJ2ZXN0CQAETgAAAAIFAAAACWJhc2VFbnRyeQkABEwAAAACCQEAAAAMQm9vbGVhbkVudHJ5AAAAAgUAAAAPa2V5Rmlyc3RIYXJ2ZXN0BQAAAAxmaXJzdEhhcnZlc3QJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAFWtleUZpcnN0SGFydmVzdEhlaWdodAkAAGQAAAACBQAAAAtzdGFydEhlaWdodAkAAGgAAAACBQAAABVmaXJzdEhhcnZlc3RFbmRQZXJpb2QFAAAADHBlcmlvZExlbmd0aAUAAAADbmlsBQAAAAliYXNlRW50cnkAAAABaQEAAAAYa2VlcExpbWl0Rm9yRmlyc3RIYXJ2ZXN0AAAAAQAAAApzaGFyZUxpbWl0AwkBAAAAASEAAAABBQAAAAhpc0FjdGl2ZQkAAAIAAAABAgAAAB9EQXBwIGlzIGluYWN0aXZlIGF0IHRoaXMgbW9tZW50AwkBAAAAASEAAAABCQEAAAAPY29udGFpbnNFbGVtZW50AAAAAgkABEwAAAACBQAAAAxhZG1pblB1YktleTEJAARMAAAAAgUAAAAMYWRtaW5QdWJLZXkyCQAETAAAAAIFAAAADGFkbWluUHViS2V5MwkABEwAAAACBQAAABJhZG1pblB1YktleVN0YWtpbmcFAAAAA25pbAgFAAAAAWkAAAAPY2FsbGVyUHVibGljS2V5CQAAAgAAAAECAAAAIU9ubHkgYWRtaW4gY2FuIGNhbGwgdGhpcyBmdW5jdGlvbgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAALa1NoYXJlTGltaXQFAAAACnNoYXJlTGltaXQFAAAAA25pbAAAAAFpAQAAABZyZXBsZW5pc2hXaXRoVHdvVG9rZW5zAAAAAQAAABFzbGlwcGFnZVRvbGVyYW5jZQQAAAALcG10QXNzZXRJZEEICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAAB2Fzc2V0SWQEAAAAC3BtdEFzc2V0SWRCCAkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAQAAAAdhc3NldElkBAAAAApwbXRBbW91bnRBCQEAAAAQZGVkdWN0U3Rha2luZ0ZlZQAAAAIICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAABmFtb3VudAUAAAALcG10QXNzZXRJZEEEAAAACnBtdEFtb3VudEIJAQAAABBkZWR1Y3RTdGFraW5nRmVlAAAAAggJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAEAAAAGYW1vdW50BQAAAAtwbXRBc3NldElkQgMDCQAAAAAAAAIFAAAACGJhbGFuY2VBAAAAAAAAAAAACQAAAAAAAAIFAAAACGJhbGFuY2VCAAAAAAAAAAAABwQAAAANJHQwMTE4NzQxMTk1MQkBAAAADGdldEFzc2V0SW5mbwAAAAEFAAAAC3BtdEFzc2V0SWRBBAAAAA5wbXRTdHJBc3NldElkQQgFAAAADSR0MDExODc0MTE5NTEAAAACXzEEAAAADXBtdEFzc2V0TmFtZUEIBQAAAA0kdDAxMTg3NDExOTUxAAAAAl8yBAAAAAxwbXREZWNpbWFsc0EIBQAAAA0kdDAxMTg3NDExOTUxAAAAAl8zBAAAAA0kdDAxMTk2MDEyMDM3CQEAAAAMZ2V0QXNzZXRJbmZvAAAAAQUAAAALcG10QXNzZXRJZEIEAAAADnBtdFN0ckFzc2V0SWRCCAUAAAANJHQwMTE5NjAxMjAzNwAAAAJfMQQAAAANcG10QXNzZXROYW1lQggFAAAADSR0MDExOTYwMTIwMzcAAAACXzIEAAAADHBtdERlY2ltYWxzQggFAAAADSR0MDExOTYwMTIwMzcAAAACXzMEAAAACnRva2VuUmF0aW8JAABrAAAAAwkAAGsAAAADBQAAAAphc3NldEluaXRBBQAAAAtzY2FsZVZhbHVlOAUAAAAKcG10QW1vdW50QQUAAAALc2NhbGVWYWx1ZTMJAABrAAAAAwUAAAAKYXNzZXRJbml0QgUAAAALc2NhbGVWYWx1ZTgFAAAACnBtdEFtb3VudEIDCQAAAAAAAAIFAAAAC3BtdEFzc2V0SWRBBQAAAAtwbXRBc3NldElkQgkAAAIAAAABAgAAABhBc3NldHMgbXVzdCBiZSBkaWZmZXJlbnQEAAAADXNoYXJlRGVjaW1hbHMJAABpAAAAAgkAAGQAAAACBQAAAAxwbXREZWNpbWFsc0EFAAAADHBtdERlY2ltYWxzQgAAAAAAAAAAAgQAAAASc2hhcmVJbml0aWFsU3VwcGx5CQAAawAAAAMJAABsAAAABgUAAAAKcG10QW1vdW50QQUAAAAMcG10RGVjaW1hbHNBAAAAAAAAAAAFAAAAAAAAAAABBQAAAAxwbXREZWNpbWFsc0EFAAAACEhBTEZET1dOCQAAbAAAAAYFAAAACnBtdEFtb3VudEIFAAAADHBtdERlY2ltYWxzQgAAAAAAAAAABQAAAAAAAAAAAQUAAAAMcG10RGVjaW1hbHNCBQAAAAhIQUxGRE9XTgkAAGwAAAAGAAAAAAAAAAAKAAAAAAAAAAAABQAAAA1zaGFyZURlY2ltYWxzAAAAAAAAAAAAAAAAAAAAAAAABQAAAAhIQUxGRE9XTgMJAQAAAAEhAAAAAQUAAAAIaXNBY3RpdmUJAAACAAAAAQIAAAAfREFwcCBpcyBpbmFjdGl2ZSBhdCB0aGlzIG1vbWVudAMDCQAAZgAAAAIAAAAAAAAAAAAFAAAAEXNsaXBwYWdlVG9sZXJhbmNlBgkAAGYAAAACBQAAABFzbGlwcGFnZVRvbGVyYW5jZQUAAAAac2xpcHBhZ2VUb2xlcmFuY2VEZWxpbWl0ZXIJAAACAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAApU2xpcHBhZ2UgdG9sZXJhbmNlIG11c3QgYmUgYmV0d2VlbiAwIGFuZCAJAAGkAAAAAQUAAAAac2xpcHBhZ2VUb2xlcmFuY2VEZWxpbWl0ZXICAAAAFiBpbmNsdXNpdmVseS4gQWN0dWFsOiAJAAGkAAAAAQUAAAARc2xpcHBhZ2VUb2xlcmFuY2UDCQEAAAACIT0AAAACCQABkAAAAAEIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAACCQAAAgAAAAECAAAAHFR3byBhdHRhY2hlZCBhc3NldHMgZXhwZWN0ZWQDAwkAAGYAAAACCQAAaQAAAAIJAABoAAAAAgUAAAALc2NhbGVWYWx1ZTMJAABlAAAAAgUAAAAac2xpcHBhZ2VUb2xlcmFuY2VEZWxpbWl0ZXIFAAAAEXNsaXBwYWdlVG9sZXJhbmNlBQAAABpzbGlwcGFnZVRvbGVyYW5jZURlbGltaXRlcgUAAAAKdG9rZW5SYXRpbwYJAABmAAAAAgUAAAAKdG9rZW5SYXRpbwkAAGkAAAACCQAAaAAAAAIFAAAAC3NjYWxlVmFsdWUzCQAAZAAAAAIFAAAAGnNsaXBwYWdlVG9sZXJhbmNlRGVsaW1pdGVyBQAAABFzbGlwcGFnZVRvbGVyYW5jZQUAAAAac2xpcHBhZ2VUb2xlcmFuY2VEZWxpbWl0ZXIJAAACAAAAAQIAAAA9SW5jb3JyZWN0IGFzc2V0cyBhbW91bnQ6IGFtb3VudHMgbXVzdCBoYXZlIHRoZSBjb250cmFjdCByYXRpbwMDCQEAAAACIT0AAAACBQAAAAtwbXRBc3NldElkQQUAAAAIYXNzZXRJZEEGCQEAAAACIT0AAAACBQAAAAtwbXRBc3NldElkQgUAAAAIYXNzZXRJZEIJAAACAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAlSW5jb3JyZWN0IGFzc2V0cyBhdHRhY2hlZC4gRXhwZWN0ZWQ6IAUAAAALc3RyQXNzZXRJZEECAAAABSBhbmQgBQAAAAtzdHJBc3NldElkQgMJAAAAAAAAAgUAAAASc2hhcmVJbml0aWFsU3VwcGx5AAAAAAAAAAAACQAAAgAAAAECAAAAHVRvbyBzbWFsbCBhbW91bnQgdG8gcmVwbGVuaXNoAwkBAAAAASEAAAABBQAAABBoYXNFbm91Z2hCYWxhbmNlCQAETgAAAAIJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAAApwbXRBbW91bnRBBQAAAAtwbXRBc3NldElkQQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIFAAAACnBtdEFtb3VudEIFAAAAC3BtdEFzc2V0SWRCBQAAAANuaWwJAQAAABFzdXNwZW5kU3VzcGljaW91cwAAAAAJAARMAAAAAgkBAAAAB1JlaXNzdWUAAAADBQAAAAxzaGFyZUFzc2V0SWQFAAAAEnNoYXJlSW5pdGlhbFN1cHBseQYJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAC2tleUJhbGFuY2VBBQAAAApwbXRBbW91bnRBCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAtrZXlCYWxhbmNlQgUAAAAKcG10QW1vdW50QgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAATa2V5U2hhcmVBc3NldFN1cHBseQUAAAASc2hhcmVJbml0aWFsU3VwcGx5CQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAASc2hhcmVJbml0aWFsU3VwcGx5BQAAAAxzaGFyZUFzc2V0SWQFAAAAA25pbAQAAAAKdG9rZW5SYXRpbwkAAGsAAAADCQAAawAAAAMFAAAACGJhbGFuY2VBBQAAAAtzY2FsZVZhbHVlOAUAAAAKcG10QW1vdW50QQUAAAALc2NhbGVWYWx1ZTMJAABrAAAAAwUAAAAIYmFsYW5jZUIFAAAAC3NjYWxlVmFsdWU4BQAAAApwbXRBbW91bnRCBAAAABNyYXRpb1NoYXJlVG9rZW5zSW5BCQAAawAAAAMFAAAACnBtdEFtb3VudEEFAAAAC3NjYWxlVmFsdWU4BQAAAAhiYWxhbmNlQQQAAAATcmF0aW9TaGFyZVRva2Vuc0luQgkAAGsAAAADBQAAAApwbXRBbW91bnRCBQAAAAtzY2FsZVZhbHVlOAUAAAAIYmFsYW5jZUIEAAAAFXNoYXJlVG9rZW5Ub1BheUFtb3VudAkAAGsAAAADCQABlwAAAAEJAARMAAAAAgUAAAATcmF0aW9TaGFyZVRva2Vuc0luQQkABEwAAAACBQAAABNyYXRpb1NoYXJlVG9rZW5zSW5CBQAAAANuaWwFAAAAEHNoYXJlQXNzZXRTdXBwbHkFAAAAC3NjYWxlVmFsdWU4AwkBAAAAASEAAAABBQAAAAhpc0FjdGl2ZQkAAAIAAAABAgAAAB9EQXBwIGlzIGluYWN0aXZlIGF0IHRoaXMgbW9tZW50AwMJAABmAAAAAgAAAAAAAAAAAAUAAAARc2xpcHBhZ2VUb2xlcmFuY2UGCQAAZgAAAAIFAAAAEXNsaXBwYWdlVG9sZXJhbmNlBQAAABpzbGlwcGFnZVRvbGVyYW5jZURlbGltaXRlcgkAAAIAAAABCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAClTbGlwcGFnZSB0b2xlcmFuY2UgbXVzdCBiZSBiZXR3ZWVuIDAgYW5kIAkAAaQAAAABBQAAABpzbGlwcGFnZVRvbGVyYW5jZURlbGltaXRlcgIAAAAWIGluY2x1c2l2ZWx5LiBBY3R1YWw6IAkAAaQAAAABBQAAABFzbGlwcGFnZVRvbGVyYW5jZQMJAQAAAAIhPQAAAAIJAAGQAAAAAQgFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAIJAAACAAAAAQIAAAAcVHdvIGF0dGFjaGVkIGFzc2V0cyBleHBlY3RlZAMDCQEAAAACIT0AAAACBQAAAAtwbXRBc3NldElkQQUAAAAIYXNzZXRJZEEGCQEAAAACIT0AAAACBQAAAAtwbXRBc3NldElkQgUAAAAIYXNzZXRJZEIJAAACAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAlSW5jb3JyZWN0IGFzc2V0cyBhdHRhY2hlZC4gRXhwZWN0ZWQ6IAUAAAALc3RyQXNzZXRJZEECAAAABSBhbmQgBQAAAAtzdHJBc3NldElkQgMDCQAAZgAAAAIJAABpAAAAAgkAAGgAAAACBQAAAAtzY2FsZVZhbHVlMwkAAGUAAAACBQAAABpzbGlwcGFnZVRvbGVyYW5jZURlbGltaXRlcgUAAAARc2xpcHBhZ2VUb2xlcmFuY2UFAAAAGnNsaXBwYWdlVG9sZXJhbmNlRGVsaW1pdGVyBQAAAAp0b2tlblJhdGlvBgkAAGYAAAACBQAAAAp0b2tlblJhdGlvCQAAaQAAAAIJAABoAAAAAgUAAAALc2NhbGVWYWx1ZTMJAABkAAAAAgUAAAAac2xpcHBhZ2VUb2xlcmFuY2VEZWxpbWl0ZXIFAAAAEXNsaXBwYWdlVG9sZXJhbmNlBQAAABpzbGlwcGFnZVRvbGVyYW5jZURlbGltaXRlcgkAAAIAAAABAgAAAD1JbmNvcnJlY3QgYXNzZXRzIGFtb3VudDogYW1vdW50cyBtdXN0IGhhdmUgdGhlIGNvbnRyYWN0IHJhdGlvAwkAAAAAAAACBQAAABVzaGFyZVRva2VuVG9QYXlBbW91bnQAAAAAAAAAAAAJAAACAAAAAQIAAAAdVG9vIHNtYWxsIGFtb3VudCB0byByZXBsZW5pc2gDCQEAAAABIQAAAAEFAAAAEGhhc0Vub3VnaEJhbGFuY2UJAAROAAAAAgkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIFAAAACnBtdEFtb3VudEEFAAAAC3BtdEFzc2V0SWRBCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAAKcG10QW1vdW50QgUAAAALcG10QXNzZXRJZEIFAAAAA25pbAkBAAAAEXN1c3BlbmRTdXNwaWNpb3VzAAAAAAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAALa2V5QmFsYW5jZUEJAABkAAAAAgUAAAAIYmFsYW5jZUEFAAAACnBtdEFtb3VudEEJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAC2tleUJhbGFuY2VCCQAAZAAAAAIFAAAACGJhbGFuY2VCBQAAAApwbXRBbW91bnRCCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABNrZXlTaGFyZUFzc2V0U3VwcGx5CQAAZAAAAAIFAAAAEHNoYXJlQXNzZXRTdXBwbHkFAAAAFXNoYXJlVG9rZW5Ub1BheUFtb3VudAkABEwAAAACCQEAAAAHUmVpc3N1ZQAAAAMFAAAADHNoYXJlQXNzZXRJZAUAAAAVc2hhcmVUb2tlblRvUGF5QW1vdW50BgkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIFAAAAFXNoYXJlVG9rZW5Ub1BheUFtb3VudAUAAAAMc2hhcmVBc3NldElkBQAAAANuaWwAAAABaQEAAAAId2l0aGRyYXcAAAAABAAAAA0kdDAxNjQ0OTE2NTk5CQAFFAAAAAIICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAABmFtb3VudAgJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAAAAAHYXNzZXRJZAQAAAAJcG10QW1vdW50CAUAAAANJHQwMTY0NDkxNjU5OQAAAAJfMQQAAAAKcG10QXNzZXRJZAgFAAAADSR0MDE2NDQ5MTY1OTkAAAACXzIEAAAADGFtb3VudFRvUGF5QQkBAAAAEGRlZHVjdFN0YWtpbmdGZWUAAAACCQAAawAAAAMFAAAACXBtdEFtb3VudAUAAAAIYmFsYW5jZUEFAAAAEHNoYXJlQXNzZXRTdXBwbHkFAAAACGFzc2V0SWRBBAAAAAxhbW91bnRUb1BheUIJAQAAABBkZWR1Y3RTdGFraW5nRmVlAAAAAgkAAGsAAAADBQAAAAlwbXRBbW91bnQFAAAACGJhbGFuY2VCBQAAABBzaGFyZUFzc2V0U3VwcGx5BQAAAAhhc3NldElkQgMJAQAAAAEhAAAAAQUAAAAIaXNBY3RpdmUJAAACAAAAAQIAAAAfREFwcCBpcyBpbmFjdGl2ZSBhdCB0aGlzIG1vbWVudAMJAQAAAAIhPQAAAAIJAAGQAAAAAQgFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAEJAAACAAAAAQIAAAAdT25lIGF0dGFjaGVkIHBheW1lbnQgZXhwZWN0ZWQDCQEAAAACIT0AAAACBQAAAApwbXRBc3NldElkBQAAAAxzaGFyZUFzc2V0SWQJAAACAAAAAQkAASwAAAACAgAAACRJbmNvcnJlY3QgYXNzZXQgYXR0YWNoZWQuIEV4cGVjdGVkOiAJAAJYAAAAAQUAAAAMc2hhcmVBc3NldElkAwkBAAAAASEAAAABBQAAABBoYXNFbm91Z2hCYWxhbmNlCQAETgAAAAIJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAAAlwbXRBbW91bnQFAAAACnBtdEFzc2V0SWQFAAAAA25pbAkBAAAAEXN1c3BlbmRTdXNwaWNpb3VzAAAAAAMDCQAAZgAAAAIFAAAADGFtb3VudFRvUGF5QQUAAAARYXZhaWxhYmxlQmFsYW5jZUEGCQAAZgAAAAIFAAAADGFtb3VudFRvUGF5QgUAAAARYXZhaWxhYmxlQmFsYW5jZUIJAQAAACJ0aHJvd0luc3VmZmljaWVudEF2YWlsYWJsZUJhbGFuY2VzAAAAAgUAAAAMYW1vdW50VG9QYXlBBQAAAAxhbW91bnRUb1BheUIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAC2tleUJhbGFuY2VBCQAAZQAAAAIFAAAACGJhbGFuY2VBBQAAAAxhbW91bnRUb1BheUEJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAC2tleUJhbGFuY2VCCQAAZQAAAAIFAAAACGJhbGFuY2VCBQAAAAxhbW91bnRUb1BheUIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAE2tleVNoYXJlQXNzZXRTdXBwbHkJAABlAAAAAgUAAAAQc2hhcmVBc3NldFN1cHBseQUAAAAJcG10QW1vdW50CQAETAAAAAIJAQAAAARCdXJuAAAAAgUAAAAMc2hhcmVBc3NldElkBQAAAAlwbXRBbW91bnQJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAAAxhbW91bnRUb1BheUEFAAAACGFzc2V0SWRBCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAAMYW1vdW50VG9QYXlCBQAAAAhhc3NldElkQgUAAAADbmlsAAAAAWkBAAAACGV4Y2hhbmdlAAAAAQAAABJtaW5BbW91bnRUb1JlY2VpdmUEAAAADSR0MDE3ODA1MTc4ODAJAAUUAAAAAggJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAAAAAGYW1vdW50CAkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAAAAAdhc3NldElkBAAAAAlwbXRBbW91bnQIBQAAAA0kdDAxNzgwNTE3ODgwAAAAAl8xBAAAAApwbXRBc3NldElkCAUAAAANJHQwMTc4MDUxNzg4MAAAAAJfMgoBAAAADWNhbGN1bGF0ZUZlZXMAAAACAAAACXRva2VuRnJvbQAAAAd0b2tlblRvBAAAABBhbW91bnRXaXRob3V0RmVlCQAAawAAAAMFAAAAB3Rva2VuVG8FAAAACXBtdEFtb3VudAkAAGQAAAACBQAAAAlwbXRBbW91bnQFAAAACXRva2VuRnJvbQQAAAANYW1vdW50V2l0aEZlZQkAAGsAAAADBQAAABBhbW91bnRXaXRob3V0RmVlCQAAZQAAAAIFAAAAGGNvbW1pc3Npb25TY2FsZURlbGltaXRlcgUAAAAKY29tbWlzc2lvbgUAAAAYY29tbWlzc2lvblNjYWxlRGVsaW1pdGVyBAAAABBnb3Zlcm5hbmNlUmV3YXJkCQAAawAAAAMFAAAAEGFtb3VudFdpdGhvdXRGZWUFAAAAFGNvbW1pc3Npb25Hb3Zlcm5hbmNlBQAAABhjb21taXNzaW9uU2NhbGVEZWxpbWl0ZXIDCQAAZgAAAAIFAAAAEm1pbkFtb3VudFRvUmVjZWl2ZQUAAAANYW1vdW50V2l0aEZlZQkAAAIAAAABCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAB1DYWxjdWxhdGVkIGFtb3VudCB0byByZWNlaXZlIAkAAaQAAAABBQAAAA1hbW91bnRXaXRoRmVlAgAAACAgaXMgbGVzcyB0aGFuIHNwZWNpZmllZCBtaW5pbXVtIAkAAaQAAAABBQAAABJtaW5BbW91bnRUb1JlY2VpdmUJAAUVAAAAAwUAAAAQYW1vdW50V2l0aG91dEZlZQUAAAANYW1vdW50V2l0aEZlZQUAAAAQZ292ZXJuYW5jZVJld2FyZAMJAQAAAAEhAAAAAQUAAAAIaXNBY3RpdmUJAAACAAAAAQIAAAAfREFwcCBpcyBpbmFjdGl2ZSBhdCB0aGlzIG1vbWVudAMDCQAAAAAAAAIFAAAACGJhbGFuY2VBAAAAAAAAAAAABgkAAAAAAAACBQAAAAhiYWxhbmNlQgAAAAAAAAAAAAkAAAIAAAABAgAAACBDYW4ndCBleGNoYW5nZSB3aXRoIHplcm8gYmFsYW5jZQMJAABnAAAAAgAAAAAAAAAAAAUAAAASbWluQW1vdW50VG9SZWNlaXZlCQAAAgAAAAEJAAEsAAAAAgIAAAA0TWluaW1hbCBhbW91bnQgdG8gcmVjZWl2ZSBtdXN0IGJlIHBvc2l0aXZlLiBBY3R1YWw6IAkAAaQAAAABBQAAABJtaW5BbW91bnRUb1JlY2VpdmUDCQEAAAACIT0AAAACCQABkAAAAAEIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAABCQAAAgAAAAECAAAAHU9uZSBhdHRhY2hlZCBwYXltZW50IGV4cGVjdGVkAwkBAAAAASEAAAABBQAAABBoYXNFbm91Z2hCYWxhbmNlCQAETgAAAAIJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAAAlwbXRBbW91bnQFAAAACnBtdEFzc2V0SWQFAAAAA25pbAkBAAAAEXN1c3BlbmRTdXNwaWNpb3VzAAAAAAMJAAAAAAAAAgUAAAAKcG10QXNzZXRJZAUAAAAIYXNzZXRJZEEEAAAAC2Fzc2V0SWRTZW5kBQAAAAhhc3NldElkQgQAAAANJHQwMTkxNTQxOTI0NQkBAAAADWNhbGN1bGF0ZUZlZXMAAAACBQAAAAhiYWxhbmNlQQUAAAAIYmFsYW5jZUIEAAAAEGFtb3VudFdpdGhvdXRGZWUIBQAAAA0kdDAxOTE1NDE5MjQ1AAAAAl8xBAAAAA1hbW91bnRXaXRoRmVlCAUAAAANJHQwMTkxNTQxOTI0NQAAAAJfMgQAAAAQZ292ZXJuYW5jZVJld2FyZAgFAAAADSR0MDE5MTU0MTkyNDUAAAACXzMEAAAAC25ld0JhbGFuY2VBCQAAZAAAAAIFAAAACGJhbGFuY2VBBQAAAAlwbXRBbW91bnQEAAAAC25ld0JhbGFuY2VCCQAAZQAAAAIJAABlAAAAAgUAAAAIYmFsYW5jZUIFAAAADWFtb3VudFdpdGhGZWUFAAAAEGdvdmVybmFuY2VSZXdhcmQDAwMJAAAAAAAAAgUAAAAIYXNzZXRJZEEFAAAABFVTRE4JAABnAAAAAgUAAAAQc3Rha2VkQW1vdW50VVNETgUAAAALbmV3QmFsYW5jZUEHBgMJAAAAAAAAAgUAAAAIYXNzZXRJZEIFAAAABFVTRE4JAABnAAAAAgUAAAAQc3Rha2VkQW1vdW50VVNETgUAAAALbmV3QmFsYW5jZUIHCQEAAAAhdGhyb3dJbnN1ZmZpY2llbnRBdmFpbGFibGVCYWxhbmNlAAAAAwUAAAANYW1vdW50V2l0aEZlZQUAAAARYXZhaWxhYmxlQmFsYW5jZUIFAAAACmFzc2V0TmFtZUIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAC2tleUJhbGFuY2VBBQAAAAtuZXdCYWxhbmNlQQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAALa2V5QmFsYW5jZUIFAAAAC25ld0JhbGFuY2VCCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAANYW1vdW50V2l0aEZlZQUAAAALYXNzZXRJZFNlbmQJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwUAAAANd2FsbGV0QWRkcmVzcwUAAAAQZ292ZXJuYW5jZVJld2FyZAUAAAALYXNzZXRJZFNlbmQFAAAAA25pbAMJAAAAAAAAAgUAAAAKcG10QXNzZXRJZAUAAAAIYXNzZXRJZEIEAAAAC2Fzc2V0SWRTZW5kBQAAAAhhc3NldElkQQQAAAANJHQwMjAxMTQyMDIwNQkBAAAADWNhbGN1bGF0ZUZlZXMAAAACBQAAAAhiYWxhbmNlQgUAAAAIYmFsYW5jZUEEAAAAEGFtb3VudFdpdGhvdXRGZWUIBQAAAA0kdDAyMDExNDIwMjA1AAAAAl8xBAAAAA1hbW91bnRXaXRoRmVlCAUAAAANJHQwMjAxMTQyMDIwNQAAAAJfMgQAAAAQZ292ZXJuYW5jZVJld2FyZAgFAAAADSR0MDIwMTE0MjAyMDUAAAACXzMEAAAAC25ld0JhbGFuY2VBCQAAZQAAAAIJAABlAAAAAgUAAAAIYmFsYW5jZUEFAAAADWFtb3VudFdpdGhGZWUFAAAAEGdvdmVybmFuY2VSZXdhcmQEAAAAC25ld0JhbGFuY2VCCQAAZAAAAAIFAAAACGJhbGFuY2VCBQAAAAlwbXRBbW91bnQDAwMJAAAAAAAAAgUAAAAIYXNzZXRJZEEFAAAABFVTRE4JAABnAAAAAgUAAAAQc3Rha2VkQW1vdW50VVNETgUAAAALbmV3QmFsYW5jZUEHBgMJAAAAAAAAAgUAAAAIYXNzZXRJZEIFAAAABFVTRE4JAABnAAAAAgUAAAAQc3Rha2VkQW1vdW50VVNETgUAAAALbmV3QmFsYW5jZUIHCQEAAAAhdGhyb3dJbnN1ZmZpY2llbnRBdmFpbGFibGVCYWxhbmNlAAAAAwUAAAANYW1vdW50V2l0aEZlZQUAAAARYXZhaWxhYmxlQmFsYW5jZUEFAAAACmFzc2V0TmFtZUEJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAC2tleUJhbGFuY2VBBQAAAAtuZXdCYWxhbmNlQQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAALa2V5QmFsYW5jZUIFAAAAC25ld0JhbGFuY2VCCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAANYW1vdW50V2l0aEZlZQUAAAALYXNzZXRJZFNlbmQJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwUAAAANd2FsbGV0QWRkcmVzcwUAAAAQZ292ZXJuYW5jZVJld2FyZAUAAAALYXNzZXRJZFNlbmQFAAAAA25pbAkAAAIAAAABCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAACRJbmNvcnJlY3QgYXNzZXQgYXR0YWNoZWQuIEV4cGVjdGVkOiAFAAAAC3N0ckFzc2V0SWRBAgAAAAQgb3IgBQAAAAtzdHJBc3NldElkQgAAAAFpAQAAAAhzaHV0ZG93bgAAAAADCQEAAAABIQAAAAEFAAAACGlzQWN0aXZlCQAAAgAAAAEJAAEsAAAAAgIAAAAiREFwcCBpcyBhbHJlYWR5IHN1c3BlbmRlZC4gQ2F1c2U6IAkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABB0AAAACBQAAAAR0aGlzBQAAAAhrZXlDYXVzZQIAAAAadGhlIGNhdXNlIHdhc24ndCBzcGVjaWZpZWQDCQEAAAABIQAAAAEJAQAAAA9jb250YWluc0VsZW1lbnQAAAACCQAETAAAAAIFAAAADGFkbWluUHViS2V5MQkABEwAAAACBQAAAAxhZG1pblB1YktleTIJAARMAAAAAgUAAAAMYWRtaW5QdWJLZXkzCQAETAAAAAIFAAAAFGFkbWluUHViS2V5U3RhcnRTdG9wBQAAAANuaWwIBQAAAAFpAAAAD2NhbGxlclB1YmxpY0tleQkAAAIAAAABAgAAACFPbmx5IGFkbWluIGNhbiBjYWxsIHRoaXMgZnVuY3Rpb24JAQAAAAdzdXNwZW5kAAAAAQIAAAAPUGF1c2VkIGJ5IGFkbWluAAAAAWkBAAAACGFjdGl2YXRlAAAAAAMFAAAACGlzQWN0aXZlCQAAAgAAAAECAAAAFkRBcHAgaXMgYWxyZWFkeSBhY3RpdmUDCQEAAAABIQAAAAEJAQAAAA9jb250YWluc0VsZW1lbnQAAAACCQAETAAAAAIFAAAADGFkbWluUHViS2V5MQkABEwAAAACBQAAAAxhZG1pblB1YktleTIJAARMAAAAAgUAAAAMYWRtaW5QdWJLZXkzCQAETAAAAAIFAAAAFGFkbWluUHViS2V5U3RhcnRTdG9wBQAAAANuaWwIBQAAAAFpAAAAD2NhbGxlclB1YmxpY0tleQkAAAIAAAABAgAAACFPbmx5IGFkbWluIGNhbiBjYWxsIHRoaXMgZnVuY3Rpb24JAARMAAAAAgkBAAAADEJvb2xlYW5FbnRyeQAAAAIFAAAACWtleUFjdGl2ZQYJAARMAAAAAgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQUAAAAIa2V5Q2F1c2UFAAAAA25pbAAAAAFpAQAAABl0YWtlSW50b0FjY291bnRFeHRyYUZ1bmRzAAAAAQAAAAthbW91bnRMZWF2ZQQAAAAddW5jb3VudGFibGVBbW91bnRFbnJvbGxBc3NldEEJAABlAAAAAgUAAAAZYWNjb3VudEJhbGFuY2VXaXRoU3Rha2VkQQUAAAAIYmFsYW5jZUEEAAAAHXVuY291bnRhYmxlQW1vdW50RW5yb2xsQXNzZXRCCQAAZQAAAAIFAAAAGWFjY291bnRCYWxhbmNlV2l0aFN0YWtlZEIFAAAACGJhbGFuY2VCBAAAAA1hbW91bnRFbnJvbGxBCQAAZQAAAAIFAAAAHXVuY291bnRhYmxlQW1vdW50RW5yb2xsQXNzZXRBAwkAAAAAAAACBQAAAAhhc3NldElkQQUAAAAEdW5pdAUAAAALYW1vdW50TGVhdmUAAAAAAAAAAAAEAAAADWFtb3VudEVucm9sbEIJAABlAAAAAgUAAAAddW5jb3VudGFibGVBbW91bnRFbnJvbGxBc3NldEIDCQAAAAAAAAIFAAAACGFzc2V0SWRCBQAAAAR1bml0BQAAAAthbW91bnRMZWF2ZQAAAAAAAAAAAAMJAQAAAAEhAAAAAQUAAAAIaXNBY3RpdmUJAAACAAAAAQIAAAAfREFwcCBpcyBpbmFjdGl2ZSBhdCB0aGlzIG1vbWVudAMJAQAAAAIhPQAAAAIIBQAAAAFpAAAABmNhbGxlcgUAAAAEdGhpcwkAAAIAAAABAgAAACtPbmx5IHRoZSBEQXBwIGl0c2VsZiBjYW4gY2FsbCB0aGlzIGZ1bmN0aW9uAwkAAGYAAAACAAAAAAAAAAAABQAAAAthbW91bnRMZWF2ZQkAAAIAAAABCQABLAAAAAICAAAAM0FyZ3VtZW50ICdhbW91bnRMZWF2ZScgY2Fubm90IGJlIG5lZ2F0aXZlLiBBY3R1YWw6IAkAAaQAAAABBQAAAAthbW91bnRMZWF2ZQMDCQAAZgAAAAIAAAAAAAAAAAAFAAAAHXVuY291bnRhYmxlQW1vdW50RW5yb2xsQXNzZXRBBgkAAGYAAAACAAAAAAAAAAAABQAAAB11bmNvdW50YWJsZUFtb3VudEVucm9sbEFzc2V0QgkBAAAAB3N1c3BlbmQAAAABAgAAABZFbnJvbGwgYW1vdW50IG5lZ2F0aXZlAwMJAABmAAAAAgAAAAAAAAAAAAUAAAANYW1vdW50RW5y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", "height": 1621989, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: H2KR9fy8hox29uNCgEcJZjhCeJYHgE7PHCrTKhhFmndp Next: Gp1B9iArShJ62KJUTrSrA5H9GNXnr9qeVMJ8fTLxe7in Diff:
OldNewDifferences
1515
1616 let keyBalanceB = "B_asset_balance"
1717
18+let keyBalanceInitA = "A_asset_init"
19+
20+let keyBalanceInitB = "B_asset_init"
21+
1822 let keyShareAssetId = "share_asset_id"
1923
2024 let keyShareAssetSupply = "share_asset_supply"
2428 let keyCommissionScaleDelimiter = "commission_scale_delimiter"
2529
2630 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"
2745
2846 let adminPubKey1 = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
2947
3553
3654 let adminPubKeyStaking = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
3755
38-let governanceAddress = Address(base58'3NAGTtZz6WpupSN89NZD5rMZwwziZEg4Kx4')
56+let walletPubKey = base58'5CqqMkmtXXt35KRH9LdWA3ap6TffPvTT5SHQzYrVFbBw'
3957
40-let stakingAddressUSDN = Address(base58'3N6q7sCGSSLBUXDdjBdYGTJbZGZfhhh8cNg')
58+let walletAddress = Address(base58'3NAGTtZz6WpupSN89NZD5rMZwwziZEg4Kx4')
59+
60+let votingAddress = Address(base58'3MrJgdL1GniipErHy44YF9idzLaUL2iX5DQ')
61+
62+let stakingAddress = Address(base58'3N6q7sCGSSLBUXDdjBdYGTJbZGZfhhh8cNg')
63+
64+let USDNToWavesExchanger = Address(base58'3N3g1MVp6DXyfqhq8sMPA6CRRkTTPtBsZeh')
65+
66+let basePeriod = valueOrErrorMessage(getInteger(votingAddress, kBasePeriod), "Empty kBasePeriod")
67+
68+let startHeight = valueOrErrorMessage(getInteger(votingAddress, kStartHeight), "Empty kStartHeight")
69+
70+let periodLength = valueOrErrorMessage(getInteger(votingAddress, kPeriodLength), "Empty kPeriodLength")
71+
72+let firstHarvestEndPeriod = ((basePeriod + ((height - startHeight) / periodLength)) + 3)
4173
4274 let USDN = base58'8UrfDVd5GreeUwm7uPk7eYz1eMv376kzR52C6sANPkwS'
43-
44-let NSBT = base58'36mg8NZTaFRDygiVwb8uBnLR51hetJruUCZcxhaVcHj9'
45-
46-let SWOP = base58'2HAJrwa8q4SxBx9cHYaBTQdBjdk5wwqdof7ccpAx2uhZ'
47-
48-let swopUSDNtoWAVES = Address(base58'3N3g1MVp6DXyfqhq8sMPA6CRRkTTPtBsZeh')
49-
50-let swopUSDNtoNSBT = Address(base58'3N95taAsiWcVMmXdVShZ2ann6MAboXrFT1b')
5175
5276 let stakingFeeInUSDN = 270000
5377
115139 }
116140
117141
118-func stakedAmount (stakingAddress,asset) = {
119- let stakedAmountCalculated = match getInteger(stakingAddress, ((("rpd_balance_" + asset) + "_") + toString(this))) {
120- case staked: Int =>
121- staked
122- case nothing: Unit =>
123- 0
124- case _ =>
125- throw("Match error")
126- }
127- stakedAmountCalculated
128- }
142+let stakedAmountUSDN = match getInteger(stakingAddress, ((("rpd_balance_" + toBase58String(USDN)) + "_") + toString(this))) {
143+ case staked: Int =>
144+ staked
145+ case nothing: Unit =>
146+ 0
147+ case _ =>
148+ throw("Match error")
149+}
129150
151+let assetInitA = getIntegerValue(this, keyBalanceInitA)
130152
131-let stakedAmountA = stakedAmount(stakingAddressUSDN, strAssetIdA)
153+let assetInitB = getIntegerValue(this, keyBalanceInitB)
132154
133-let stakedAmountB = stakedAmount(stakingAddressUSDN, strAssetIdB)
155+let availableBalanceA = (balanceA - (if ((assetIdA == USDN))
156+ then stakedAmountUSDN
157+ else 0))
134158
135-let availableBalanceA = (balanceA - stakedAmountA)
159+let availableBalanceB = (balanceB - (if ((assetIdB == USDN))
160+ then stakedAmountUSDN
161+ else 0))
136162
137-let availableBalanceB = (balanceB - stakedAmountB)
163+let accountBalanceWithStakedA = (accountBalance(assetIdA) + (if ((assetIdA == USDN))
164+ then stakedAmountUSDN
165+ else 0))
138166
139-let accountBalanceWithStakedA = (accountBalance(assetIdA) + stakedAmountA)
140-
141-let accountBalanceWithStakedB = (accountBalance(assetIdB) + stakedAmountB)
167+let accountBalanceWithStakedB = (accountBalance(assetIdB) + (if ((assetIdB == USDN))
168+ then stakedAmountUSDN
169+ else 0))
142170
143171 let hasEnoughBalance = if ((accountBalanceWithStakedA >= balanceA))
144172 then (accountBalanceWithStakedB >= balanceB)
156184 }
157185
158186
159-func suspend (cause) = [BooleanEntry(keyActive, false), StringEntry(keyCause, cause)]
187+func getAssetInfoFromString (assetStr) = if ((assetStr == "WAVES"))
188+ then $Tuple3("WAVES", "WAVES", 8)
189+ else {
190+ let stringId = assetStr
191+ let id = fromBase58String(assetStr)
192+ let info = valueOrErrorMessage(assetInfo(id), (("Asset " + stringId) + " doesn't exist"))
193+ $Tuple3(stringId, info.name, info.decimals)
194+ }
160195
161196
162-func stakedTokenCount () = {
163- let isStakedA = if ((stakedAmountA > 0))
164- then 1
165- else 0
166- let isStakedB = if ((stakedAmountB > 0))
167- then 1
168- else 0
169- (isStakedA + isStakedB)
170- }
197+func suspend (cause) = [BooleanEntry(keyActive, false), StringEntry(keyCause, cause)]
171198
172199
173200 func deductStakingFee (amount,assetId) = if ((assetId == USDN))
174201 then {
175- let result = (amount - (stakedTokenCount() * stakingFeeInUSDN))
202+ let result = (amount - stakingFeeInUSDN)
176203 if ((0 >= result))
177204 then throw((((("Insufficient amount " + toString(amount)) + " to deduct staking fee ") + toString(stakingFeeInUSDN)) + " USD-N"))
178205 else result
190217
191218
192219 @Callable(i)
193-func init () = {
194- let $t056135690 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
195- let pmtAmountA = $t056135690._1
196- let pmtAssetIdA = $t056135690._2
197- let $t056955772 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
198- let pmtAmountB = $t056955772._1
199- let pmtAssetIdB = $t056955772._2
200- let $t057775854 = getAssetInfo(pmtAssetIdA)
201- let pmtStrAssetIdA = $t057775854._1
202- let pmtAssetNameA = $t057775854._2
203- let pmtDecimalsA = $t057775854._3
204- let $t058595936 = getAssetInfo(pmtAssetIdB)
205- let pmtStrAssetIdB = $t058595936._1
206- let pmtAssetNameB = $t058595936._2
207- let pmtDecimalsB = $t058595936._3
208- if (isDefined(getBoolean(this, keyActive)))
209- then throw("DApp is already active")
210- else if ((pmtAssetIdA == pmtAssetIdB))
211- then throw("Assets must be different")
212- else {
213- let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
214- let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
215- let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
216- let shareInitialSupply = fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, HALFDOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, HALFDOWN), pow(10, 0, shareDecimals, 0, 0, HALFDOWN))
217- let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
218- let shareIssueId = calculateAssetId(shareIssue)
219-[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)]
220- }
220+func init (firstHarvest) = {
221+ let $t064796556 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
222+ let pmtAmountA = $t064796556._1
223+ let pmtAssetIdA = $t064796556._2
224+ let $t065616638 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
225+ let pmtAmountB = $t065616638._1
226+ let pmtAssetIdB = $t065616638._2
227+ let $t066436720 = getAssetInfo(pmtAssetIdA)
228+ let pmtStrAssetIdA = $t066436720._1
229+ let pmtAssetNameA = $t066436720._2
230+ let pmtDecimalsA = $t066436720._3
231+ let $t067256802 = getAssetInfo(pmtAssetIdB)
232+ let pmtStrAssetIdB = $t067256802._1
233+ let pmtAssetNameB = $t067256802._2
234+ let pmtDecimalsB = $t067256802._3
235+ if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
236+ then throw("Only admin can call this function")
237+ else if (isDefined(getBoolean(this, keyActive)))
238+ then throw("DApp is already active")
239+ else if ((pmtAssetIdA == pmtAssetIdB))
240+ then throw("Assets must be different")
241+ else {
242+ let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
243+ let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
244+ let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
245+ let shareInitialSupply = fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, HALFDOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, HALFDOWN), pow(10, 0, shareDecimals, 0, 0, HALFDOWN))
246+ let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
247+ let shareIssueId = calculateAssetId(shareIssue)
248+ 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)]
249+ if (firstHarvest)
250+ then (baseEntry ++ [BooleanEntry(keyFirstHarvest, firstHarvest), IntegerEntry(keyFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
251+ else baseEntry
252+ }
221253 }
254+
255+
256+
257+@Callable(i)
258+func initWithInitRatio (amtAssetA,amtAssetB,strAssetIdA,strAssetIdB,firstHarvest) = {
259+ let $t090109097 = getAssetInfoFromString(strAssetIdA)
260+ let pmtStrAssetIdA = $t090109097._1
261+ let pmtAssetNameA = $t090109097._2
262+ let pmtDecimalsA = $t090109097._3
263+ let $t091029189 = getAssetInfoFromString(strAssetIdB)
264+ let pmtStrAssetIdB = $t091029189._1
265+ let pmtAssetNameB = $t091029189._2
266+ let pmtDecimalsB = $t091029189._3
267+ if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
268+ then throw("Only admin can call this function")
269+ else if (isDefined(getBoolean(this, keyActive)))
270+ then throw("DApp is already active")
271+ else if ((strAssetIdA == strAssetIdB))
272+ then throw("Assets must be different")
273+ else {
274+ let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
275+ let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
276+ let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
277+ let shareInitialSupply = 0
278+ let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
279+ let shareIssueId = calculateAssetId(shareIssue)
280+ 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)]
281+ if (firstHarvest)
282+ then (baseEntry ++ [BooleanEntry(keyFirstHarvest, firstHarvest), IntegerEntry(keyFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
283+ else baseEntry
284+ }
285+ }
286+
287+
288+
289+@Callable(i)
290+func keepLimitForFirstHarvest (shareLimit) = if (!(isActive))
291+ then throw("DApp is inactive at this moment")
292+ else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
293+ then throw("Only admin can call this function")
294+ else [IntegerEntry(kShareLimit, shareLimit)]
222295
223296
224297
228301 let pmtAssetIdB = i.payments[1].assetId
229302 let pmtAmountA = deductStakingFee(i.payments[0].amount, pmtAssetIdA)
230303 let pmtAmountB = deductStakingFee(i.payments[1].amount, pmtAssetIdB)
231- let tokenRatio = fraction(fraction(balanceA, scaleValue8, pmtAmountA), scaleValue3, fraction(balanceB, scaleValue8, pmtAmountB))
232- let ratioShareTokensInA = fraction(pmtAmountA, scaleValue8, balanceA)
233- let ratioShareTokensInB = fraction(pmtAmountB, scaleValue8, balanceB)
234- let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scaleValue8)
235- if (!(isActive))
236- then throw("DApp is inactive at this moment")
237- else if (if ((0 > slippageTolerance))
238- then true
239- else (slippageTolerance > slippageToleranceDelimiter))
240- then throw(((("Slippage tolerance must be between 0 and " + toString(slippageToleranceDelimiter)) + " inclusively. Actual: ") + toString(slippageTolerance)))
241- else if ((size(i.payments) != 2))
242- then throw("Two attached assets expected")
243- else if (if ((pmtAssetIdA != assetIdA))
304+ if (if ((balanceA == 0))
305+ then (balanceB == 0)
306+ else false)
307+ then {
308+ let $t01187411951 = getAssetInfo(pmtAssetIdA)
309+ let pmtStrAssetIdA = $t01187411951._1
310+ let pmtAssetNameA = $t01187411951._2
311+ let pmtDecimalsA = $t01187411951._3
312+ let $t01196012037 = getAssetInfo(pmtAssetIdB)
313+ let pmtStrAssetIdB = $t01196012037._1
314+ let pmtAssetNameB = $t01196012037._2
315+ let pmtDecimalsB = $t01196012037._3
316+ let tokenRatio = fraction(fraction(assetInitA, scaleValue8, pmtAmountA), scaleValue3, fraction(assetInitB, scaleValue8, pmtAmountB))
317+ if ((pmtAssetIdA == pmtAssetIdB))
318+ then throw("Assets must be different")
319+ else {
320+ let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
321+ let shareInitialSupply = fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, HALFDOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, HALFDOWN), pow(10, 0, shareDecimals, 0, 0, HALFDOWN))
322+ if (!(isActive))
323+ then throw("DApp is inactive at this moment")
324+ else if (if ((0 > slippageTolerance))
325+ then true
326+ else (slippageTolerance > slippageToleranceDelimiter))
327+ then throw(((("Slippage tolerance must be between 0 and " + toString(slippageToleranceDelimiter)) + " inclusively. Actual: ") + toString(slippageTolerance)))
328+ else if ((size(i.payments) != 2))
329+ then throw("Two attached assets expected")
330+ else if (if ((((scaleValue3 * (slippageToleranceDelimiter - slippageTolerance)) / slippageToleranceDelimiter) > tokenRatio))
331+ then true
332+ else (tokenRatio > ((scaleValue3 * (slippageToleranceDelimiter + slippageTolerance)) / slippageToleranceDelimiter)))
333+ then throw("Incorrect assets amount: amounts must have the contract ratio")
334+ else if (if ((pmtAssetIdA != assetIdA))
335+ then true
336+ else (pmtAssetIdB != assetIdB))
337+ then throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
338+ else if ((shareInitialSupply == 0))
339+ then throw("Too small amount to replenish")
340+ else if (!(hasEnoughBalance))
341+ then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
342+ else [Reissue(shareAssetId, shareInitialSupply, true), IntegerEntry(keyBalanceA, pmtAmountA), IntegerEntry(keyBalanceB, pmtAmountB), IntegerEntry(keyShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareAssetId)]
343+ }
344+ }
345+ else {
346+ let tokenRatio = fraction(fraction(balanceA, scaleValue8, pmtAmountA), scaleValue3, fraction(balanceB, scaleValue8, pmtAmountB))
347+ let ratioShareTokensInA = fraction(pmtAmountA, scaleValue8, balanceA)
348+ let ratioShareTokensInB = fraction(pmtAmountB, scaleValue8, balanceB)
349+ let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scaleValue8)
350+ if (!(isActive))
351+ then throw("DApp is inactive at this moment")
352+ else if (if ((0 > slippageTolerance))
244353 then true
245- else (pmtAssetIdB != assetIdB))
246- then throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
247- else if (if ((((scaleValue3 * (slippageToleranceDelimiter - slippageTolerance)) / slippageToleranceDelimiter) > tokenRatio))
248- then true
249- else (tokenRatio > ((scaleValue3 * (slippageToleranceDelimiter + slippageTolerance)) / slippageToleranceDelimiter)))
250- then throw("Incorrect assets amount: amounts must have the contract ratio")
251- else if ((shareTokenToPayAmount == 0))
252- then throw("Too small amount to replenish")
253- else if (!(hasEnoughBalance))
254- then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
255- else [IntegerEntry(keyBalanceA, (balanceA + pmtAmountA)), IntegerEntry(keyBalanceB, (balanceB + pmtAmountB)), IntegerEntry(keyShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId)]
354+ else (slippageTolerance > slippageToleranceDelimiter))
355+ then throw(((("Slippage tolerance must be between 0 and " + toString(slippageToleranceDelimiter)) + " inclusively. Actual: ") + toString(slippageTolerance)))
356+ else if ((size(i.payments) != 2))
357+ then throw("Two attached assets expected")
358+ else if (if ((pmtAssetIdA != assetIdA))
359+ then true
360+ else (pmtAssetIdB != assetIdB))
361+ then throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
362+ else if (if ((((scaleValue3 * (slippageToleranceDelimiter - slippageTolerance)) / slippageToleranceDelimiter) > tokenRatio))
363+ then true
364+ else (tokenRatio > ((scaleValue3 * (slippageToleranceDelimiter + slippageTolerance)) / slippageToleranceDelimiter)))
365+ then throw("Incorrect assets amount: amounts must have the contract ratio")
366+ else if ((shareTokenToPayAmount == 0))
367+ then throw("Too small amount to replenish")
368+ else if (!(hasEnoughBalance))
369+ then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
370+ else [IntegerEntry(keyBalanceA, (balanceA + pmtAmountA)), IntegerEntry(keyBalanceB, (balanceB + pmtAmountB)), IntegerEntry(keyShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId)]
371+ }
256372 }
257373
258374
259375
260376 @Callable(i)
261377 func withdraw () = {
262- let $t01000910159 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
263- let pmtAmount = $t01000910159._1
264- let pmtAssetId = $t01000910159._2
378+ let $t01644916599 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
379+ let pmtAmount = $t01644916599._1
380+ let pmtAssetId = $t01644916599._2
265381 let amountToPayA = deductStakingFee(fraction(pmtAmount, balanceA, shareAssetSupply), assetIdA)
266382 let amountToPayB = deductStakingFee(fraction(pmtAmount, balanceB, shareAssetSupply), assetIdB)
267383 if (!(isActive))
283399
284400 @Callable(i)
285401 func exchange (minAmountToReceive) = {
286- let $t01136511440 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
287- let pmtAmount = $t01136511440._1
288- let pmtAssetId = $t01136511440._2
402+ let $t01780517880 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
403+ let pmtAmount = $t01780517880._1
404+ let pmtAssetId = $t01780517880._2
289405 func calculateFees (tokenFrom,tokenTo) = {
290406 let amountWithoutFee = fraction(tokenTo, pmtAmount, (pmtAmount + tokenFrom))
291407 let amountWithFee = fraction(amountWithoutFee, (commissionScaleDelimiter - commission), commissionScaleDelimiter)
297413
298414 if (!(isActive))
299415 then throw("DApp is inactive at this moment")
300- else if ((0 >= minAmountToReceive))
301- then throw(("Minimal amount to receive must be positive. Actual: " + toString(minAmountToReceive)))
302- else if ((size(i.payments) != 1))
303- then throw("One attached payment expected")
304- else if (!(hasEnoughBalance))
305- then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
306- else if ((pmtAssetId == assetIdA))
307- then {
308- let assetIdSend = assetIdB
309- let $t01261512706 = calculateFees(balanceA, balanceB)
310- let amountWithoutFee = $t01261512706._1
311- let amountWithFee = $t01261512706._2
312- let governanceReward = $t01261512706._3
313- let newBalanceA = (balanceA + pmtAmount)
314- let newBalanceB = ((balanceB - amountWithFee) - governanceReward)
315- if (if ((stakedAmountA >= newBalanceA))
316- then true
317- else (stakedAmountB >= newBalanceB))
318- then throwInsufficientAvailableBalance(amountWithFee, availableBalanceB, assetNameB)
319- else [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(governanceAddress, governanceReward, assetIdSend)]
320- }
321- else if ((pmtAssetId == assetIdB))
416+ else if (if ((balanceA == 0))
417+ then true
418+ else (balanceB == 0))
419+ then throw("Can't exchange with zero balance")
420+ else if ((0 >= minAmountToReceive))
421+ then throw(("Minimal amount to receive must be positive. Actual: " + toString(minAmountToReceive)))
422+ else if ((size(i.payments) != 1))
423+ then throw("One attached payment expected")
424+ else if (!(hasEnoughBalance))
425+ then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
426+ else if ((pmtAssetId == assetIdA))
322427 then {
323- let assetIdSend = assetIdA
324- let $t01352913620 = calculateFees(balanceB, balanceA)
325- let amountWithoutFee = $t01352913620._1
326- let amountWithFee = $t01352913620._2
327- let governanceReward = $t01352913620._3
328- let newBalanceA = ((balanceA - amountWithFee) - governanceReward)
329- let newBalanceB = (balanceB + pmtAmount)
330- if (if ((stakedAmountA >= newBalanceA))
428+ let assetIdSend = assetIdB
429+ let $t01915419245 = calculateFees(balanceA, balanceB)
430+ let amountWithoutFee = $t01915419245._1
431+ let amountWithFee = $t01915419245._2
432+ let governanceReward = $t01915419245._3
433+ let newBalanceA = (balanceA + pmtAmount)
434+ let newBalanceB = ((balanceB - amountWithFee) - governanceReward)
435+ if (if (if ((assetIdA == USDN))
436+ then (stakedAmountUSDN >= newBalanceA)
437+ else false)
331438 then true
332- else (stakedAmountB >= newBalanceB))
333- then throwInsufficientAvailableBalance(amountWithFee, availableBalanceA, assetNameA)
334- else [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(governanceAddress, governanceReward, assetIdSend)]
439+ else if ((assetIdB == USDN))
440+ then (stakedAmountUSDN >= newBalanceB)
441+ else false)
442+ then throwInsufficientAvailableBalance(amountWithFee, availableBalanceB, assetNameB)
443+ else [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)]
335444 }
336- else throw(((("Incorrect asset attached. Expected: " + strAssetIdA) + " or ") + strAssetIdB))
445+ else if ((pmtAssetId == assetIdB))
446+ then {
447+ let assetIdSend = assetIdA
448+ let $t02011420205 = calculateFees(balanceB, balanceA)
449+ let amountWithoutFee = $t02011420205._1
450+ let amountWithFee = $t02011420205._2
451+ let governanceReward = $t02011420205._3
452+ let newBalanceA = ((balanceA - amountWithFee) - governanceReward)
453+ let newBalanceB = (balanceB + pmtAmount)
454+ if (if (if ((assetIdA == USDN))
455+ then (stakedAmountUSDN >= newBalanceA)
456+ else false)
457+ then true
458+ else if ((assetIdB == USDN))
459+ then (stakedAmountUSDN >= newBalanceB)
460+ else false)
461+ then throwInsufficientAvailableBalance(amountWithFee, availableBalanceA, assetNameA)
462+ else [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)]
463+ }
464+ else throw(((("Incorrect asset attached. Expected: " + strAssetIdA) + " or ") + strAssetIdB))
337465 }
338466
339467
387515 @Verifier(tx)
388516 func verify () = match tx {
389517 case invoke: InvokeScriptTransaction =>
390- if (if (if (sigVerify(invoke.bodyBytes, invoke.proofs[0], adminPubKeyStaking))
391- then (invoke.dApp == stakingAddressUSDN)
518+ let callTakeIntoAccount = if ((invoke.dApp == this))
519+ then (invoke.function == "takeIntoAccountExtraFunds")
520+ else false
521+ let callStaking = if ((invoke.dApp == stakingAddress))
522+ then if (if (if ((invoke.function == "lockNeutrino"))
523+ then (size(invoke.payments) == 1)
524+ else false)
525+ then (invoke.payments[0].assetId == USDN)
526+ else false)
527+ then true
528+ else if ((invoke.function == "unlockNeutrino"))
529+ then (size(invoke.payments) == 0)
530+ else false
531+ else false
532+ let exchangeToWaves = if (if (if ((invoke.dApp == USDNToWavesExchanger))
533+ then (invoke.function == "exchange")
534+ else false)
535+ then (assetIdA == USDN)
392536 else false)
393537 then true
394- else if (if (sigVerify(invoke.bodyBytes, invoke.proofs[0], adminPubKeyStaking))
395- then (invoke.function == "exchange")
396- else false)
397- then if (if (if (if ((assetIdA == NSBT))
398- then (assetIdB == USDN)
399- else false)
400- then (invoke.dApp == swopUSDNtoWAVES)
401- else false)
402- then if ((invoke.payments[0].assetId == unit))
403- then true
404- else (invoke.payments[0].assetId == USDN)
405- else false)
406- then true
407- else if (if ((assetIdA == NSBT))
408- then (assetIdB == SWOP)
409- else false)
410- then if (if ((invoke.dApp == swopUSDNtoNSBT))
411- then (invoke.payments[0].assetId == USDN)
412- else false)
413- then true
414- else if ((invoke.dApp == swopUSDNtoWAVES))
415- then if ((invoke.payments[0].assetId == unit))
416- then true
417- else (invoke.payments[0].assetId == USDN)
418- else false
419- else false
420- else false)
538+ else if ((assetIdB == USDN))
539+ then (invoke.payments[0].assetId == USDN)
540+ else false
541+ let signedByAdmin = if (if (if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
421542 then true
422- else if (if (sigVerify(invoke.bodyBytes, invoke.proofs[0], adminPubKeyStaking))
423- then (invoke.dApp == this)
424- else false)
425- then (invoke.function == "takeIntoAccountExtraFunds")
426- else false
543+ else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey2))
544+ then true
545+ else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey3))
546+ then true
547+ else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKeyStaking)
548+ if (if (if (callTakeIntoAccount)
549+ then true
550+ else callStaking)
551+ then true
552+ else exchangeToWaves)
553+ then signedByAdmin
554+ else false
427555 case _ =>
428556 let adminPubKey1Signed = if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
429557 then 1
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 4 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let version = "1.0.0"
55
66 let keyVersion = "version"
77
88 let keyActive = "active"
99
1010 let keyAssetIdA = "A_asset_id"
1111
1212 let keyAssetIdB = "B_asset_id"
1313
1414 let keyBalanceA = "A_asset_balance"
1515
1616 let keyBalanceB = "B_asset_balance"
1717
18+let keyBalanceInitA = "A_asset_init"
19+
20+let keyBalanceInitB = "B_asset_init"
21+
1822 let keyShareAssetId = "share_asset_id"
1923
2024 let keyShareAssetSupply = "share_asset_supply"
2125
2226 let keyCommission = "commission"
2327
2428 let keyCommissionScaleDelimiter = "commission_scale_delimiter"
2529
2630 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"
2745
2846 let adminPubKey1 = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
2947
3048 let adminPubKey2 = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
3149
3250 let adminPubKey3 = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
3351
3452 let adminPubKeyStartStop = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
3553
3654 let adminPubKeyStaking = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
3755
38-let governanceAddress = Address(base58'3NAGTtZz6WpupSN89NZD5rMZwwziZEg4Kx4')
56+let walletPubKey = base58'5CqqMkmtXXt35KRH9LdWA3ap6TffPvTT5SHQzYrVFbBw'
3957
40-let stakingAddressUSDN = Address(base58'3N6q7sCGSSLBUXDdjBdYGTJbZGZfhhh8cNg')
58+let walletAddress = Address(base58'3NAGTtZz6WpupSN89NZD5rMZwwziZEg4Kx4')
59+
60+let votingAddress = Address(base58'3MrJgdL1GniipErHy44YF9idzLaUL2iX5DQ')
61+
62+let stakingAddress = Address(base58'3N6q7sCGSSLBUXDdjBdYGTJbZGZfhhh8cNg')
63+
64+let USDNToWavesExchanger = Address(base58'3N3g1MVp6DXyfqhq8sMPA6CRRkTTPtBsZeh')
65+
66+let basePeriod = valueOrErrorMessage(getInteger(votingAddress, kBasePeriod), "Empty kBasePeriod")
67+
68+let startHeight = valueOrErrorMessage(getInteger(votingAddress, kStartHeight), "Empty kStartHeight")
69+
70+let periodLength = valueOrErrorMessage(getInteger(votingAddress, kPeriodLength), "Empty kPeriodLength")
71+
72+let firstHarvestEndPeriod = ((basePeriod + ((height - startHeight) / periodLength)) + 3)
4173
4274 let USDN = base58'8UrfDVd5GreeUwm7uPk7eYz1eMv376kzR52C6sANPkwS'
43-
44-let NSBT = base58'36mg8NZTaFRDygiVwb8uBnLR51hetJruUCZcxhaVcHj9'
45-
46-let SWOP = base58'2HAJrwa8q4SxBx9cHYaBTQdBjdk5wwqdof7ccpAx2uhZ'
47-
48-let swopUSDNtoWAVES = Address(base58'3N3g1MVp6DXyfqhq8sMPA6CRRkTTPtBsZeh')
49-
50-let swopUSDNtoNSBT = Address(base58'3N95taAsiWcVMmXdVShZ2ann6MAboXrFT1b')
5175
5276 let stakingFeeInUSDN = 270000
5377
5478 let isActive = getBooleanValue(this, keyActive)
5579
5680 let strAssetIdA = getStringValue(this, keyAssetIdA)
5781
5882 let strAssetIdB = getStringValue(this, keyAssetIdB)
5983
6084 let assetIdA = if ((strAssetIdA == "WAVES"))
6185 then unit
6286 else fromBase58String(strAssetIdA)
6387
6488 let assetIdB = if ((strAssetIdB == "WAVES"))
6589 then unit
6690 else fromBase58String(strAssetIdB)
6791
6892 let assetNameA = match assetIdA {
6993 case id: ByteVector =>
7094 value(assetInfo(id)).name
7195 case waves: Unit =>
7296 "WAVES"
7397 case _ =>
7498 throw("Match error")
7599 }
76100
77101 let assetNameB = match assetIdB {
78102 case id: ByteVector =>
79103 value(assetInfo(id)).name
80104 case waves: Unit =>
81105 "WAVES"
82106 case _ =>
83107 throw("Match error")
84108 }
85109
86110 let balanceA = getIntegerValue(this, keyBalanceA)
87111
88112 let balanceB = getIntegerValue(this, keyBalanceB)
89113
90114 let shareAssetId = fromBase58String(getStringValue(this, keyShareAssetId))
91115
92116 let shareAssetSupply = getIntegerValue(this, keyShareAssetSupply)
93117
94118 let commission = 3000
95119
96120 let commissionGovernance = 1200
97121
98122 let commissionScaleDelimiter = 1000000
99123
100124 let scaleValue3 = 1000
101125
102126 let scaleValue8 = 100000000
103127
104128 let slippageToleranceDelimiter = 1000
105129
106130 let scaleValue8Digits = 8
107131
108132 func accountBalance (assetId) = match assetId {
109133 case id: ByteVector =>
110134 assetBalance(this, id)
111135 case waves: Unit =>
112136 wavesBalance(this).available
113137 case _ =>
114138 throw("Match error")
115139 }
116140
117141
118-func stakedAmount (stakingAddress,asset) = {
119- let stakedAmountCalculated = match getInteger(stakingAddress, ((("rpd_balance_" + asset) + "_") + toString(this))) {
120- case staked: Int =>
121- staked
122- case nothing: Unit =>
123- 0
124- case _ =>
125- throw("Match error")
126- }
127- stakedAmountCalculated
128- }
142+let stakedAmountUSDN = match getInteger(stakingAddress, ((("rpd_balance_" + toBase58String(USDN)) + "_") + toString(this))) {
143+ case staked: Int =>
144+ staked
145+ case nothing: Unit =>
146+ 0
147+ case _ =>
148+ throw("Match error")
149+}
129150
151+let assetInitA = getIntegerValue(this, keyBalanceInitA)
130152
131-let stakedAmountA = stakedAmount(stakingAddressUSDN, strAssetIdA)
153+let assetInitB = getIntegerValue(this, keyBalanceInitB)
132154
133-let stakedAmountB = stakedAmount(stakingAddressUSDN, strAssetIdB)
155+let availableBalanceA = (balanceA - (if ((assetIdA == USDN))
156+ then stakedAmountUSDN
157+ else 0))
134158
135-let availableBalanceA = (balanceA - stakedAmountA)
159+let availableBalanceB = (balanceB - (if ((assetIdB == USDN))
160+ then stakedAmountUSDN
161+ else 0))
136162
137-let availableBalanceB = (balanceB - stakedAmountB)
163+let accountBalanceWithStakedA = (accountBalance(assetIdA) + (if ((assetIdA == USDN))
164+ then stakedAmountUSDN
165+ else 0))
138166
139-let accountBalanceWithStakedA = (accountBalance(assetIdA) + stakedAmountA)
140-
141-let accountBalanceWithStakedB = (accountBalance(assetIdB) + stakedAmountB)
167+let accountBalanceWithStakedB = (accountBalance(assetIdB) + (if ((assetIdB == USDN))
168+ then stakedAmountUSDN
169+ else 0))
142170
143171 let hasEnoughBalance = if ((accountBalanceWithStakedA >= balanceA))
144172 then (accountBalanceWithStakedB >= balanceB)
145173 else false
146174
147175 func getAssetInfo (assetId) = match assetId {
148176 case id: ByteVector =>
149177 let stringId = toBase58String(id)
150178 let info = valueOrErrorMessage(assetInfo(id), (("Asset " + stringId) + " doesn't exist"))
151179 $Tuple3(stringId, info.name, info.decimals)
152180 case waves: Unit =>
153181 $Tuple3("WAVES", "WAVES", 8)
154182 case _ =>
155183 throw("Match error")
156184 }
157185
158186
159-func suspend (cause) = [BooleanEntry(keyActive, false), StringEntry(keyCause, cause)]
187+func getAssetInfoFromString (assetStr) = if ((assetStr == "WAVES"))
188+ then $Tuple3("WAVES", "WAVES", 8)
189+ else {
190+ let stringId = assetStr
191+ let id = fromBase58String(assetStr)
192+ let info = valueOrErrorMessage(assetInfo(id), (("Asset " + stringId) + " doesn't exist"))
193+ $Tuple3(stringId, info.name, info.decimals)
194+ }
160195
161196
162-func stakedTokenCount () = {
163- let isStakedA = if ((stakedAmountA > 0))
164- then 1
165- else 0
166- let isStakedB = if ((stakedAmountB > 0))
167- then 1
168- else 0
169- (isStakedA + isStakedB)
170- }
197+func suspend (cause) = [BooleanEntry(keyActive, false), StringEntry(keyCause, cause)]
171198
172199
173200 func deductStakingFee (amount,assetId) = if ((assetId == USDN))
174201 then {
175- let result = (amount - (stakedTokenCount() * stakingFeeInUSDN))
202+ let result = (amount - stakingFeeInUSDN)
176203 if ((0 >= result))
177204 then throw((((("Insufficient amount " + toString(amount)) + " to deduct staking fee ") + toString(stakingFeeInUSDN)) + " USD-N"))
178205 else result
179206 }
180207 else amount
181208
182209
183210 func throwInsufficientAvailableBalance (amount,available,assetName) = throw((((((((("Insufficient DApp balance to pay " + toString(amount)) + " ") + assetName) + " due to staking. Available: ") + toString(available)) + " ") + assetName) + ". Please contact support in Telegram: https://t.me/swopfisupport"))
184211
185212
186213 func throwInsufficientAvailableBalances (amountA,amountB) = throw((((((((((((((((("Insufficient DApp balance to pay " + toString(amountA)) + " ") + assetNameA) + " and ") + toString(amountB)) + " ") + assetNameB) + " due to staking. Available: ") + toString(availableBalanceA)) + " ") + assetNameA) + " and ") + toString(availableBalanceB)) + " ") + assetNameB) + ". Please contact support in Telegram: https://t.me/swopfisupport"))
187214
188215
189216 func suspendSuspicious () = suspend(((((((((((((((("Suspicious state. Actual balances: " + toString(accountBalanceWithStakedA)) + " ") + assetNameA) + ", ") + toString(accountBalanceWithStakedB)) + " ") + assetNameB) + ". State: ") + toString(balanceA)) + " ") + assetNameA) + ", ") + toString(balanceB)) + " ") + assetNameB))
190217
191218
192219 @Callable(i)
193-func init () = {
194- let $t056135690 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
195- let pmtAmountA = $t056135690._1
196- let pmtAssetIdA = $t056135690._2
197- let $t056955772 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
198- let pmtAmountB = $t056955772._1
199- let pmtAssetIdB = $t056955772._2
200- let $t057775854 = getAssetInfo(pmtAssetIdA)
201- let pmtStrAssetIdA = $t057775854._1
202- let pmtAssetNameA = $t057775854._2
203- let pmtDecimalsA = $t057775854._3
204- let $t058595936 = getAssetInfo(pmtAssetIdB)
205- let pmtStrAssetIdB = $t058595936._1
206- let pmtAssetNameB = $t058595936._2
207- let pmtDecimalsB = $t058595936._3
208- if (isDefined(getBoolean(this, keyActive)))
209- then throw("DApp is already active")
210- else if ((pmtAssetIdA == pmtAssetIdB))
211- then throw("Assets must be different")
212- else {
213- let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
214- let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
215- let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
216- let shareInitialSupply = fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, HALFDOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, HALFDOWN), pow(10, 0, shareDecimals, 0, 0, HALFDOWN))
217- let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
218- let shareIssueId = calculateAssetId(shareIssue)
219-[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)]
220- }
220+func init (firstHarvest) = {
221+ let $t064796556 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
222+ let pmtAmountA = $t064796556._1
223+ let pmtAssetIdA = $t064796556._2
224+ let $t065616638 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
225+ let pmtAmountB = $t065616638._1
226+ let pmtAssetIdB = $t065616638._2
227+ let $t066436720 = getAssetInfo(pmtAssetIdA)
228+ let pmtStrAssetIdA = $t066436720._1
229+ let pmtAssetNameA = $t066436720._2
230+ let pmtDecimalsA = $t066436720._3
231+ let $t067256802 = getAssetInfo(pmtAssetIdB)
232+ let pmtStrAssetIdB = $t067256802._1
233+ let pmtAssetNameB = $t067256802._2
234+ let pmtDecimalsB = $t067256802._3
235+ if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
236+ then throw("Only admin can call this function")
237+ else if (isDefined(getBoolean(this, keyActive)))
238+ then throw("DApp is already active")
239+ else if ((pmtAssetIdA == pmtAssetIdB))
240+ then throw("Assets must be different")
241+ else {
242+ let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
243+ let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
244+ let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
245+ let shareInitialSupply = fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, HALFDOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, HALFDOWN), pow(10, 0, shareDecimals, 0, 0, HALFDOWN))
246+ let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
247+ let shareIssueId = calculateAssetId(shareIssue)
248+ 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)]
249+ if (firstHarvest)
250+ then (baseEntry ++ [BooleanEntry(keyFirstHarvest, firstHarvest), IntegerEntry(keyFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
251+ else baseEntry
252+ }
221253 }
254+
255+
256+
257+@Callable(i)
258+func initWithInitRatio (amtAssetA,amtAssetB,strAssetIdA,strAssetIdB,firstHarvest) = {
259+ let $t090109097 = getAssetInfoFromString(strAssetIdA)
260+ let pmtStrAssetIdA = $t090109097._1
261+ let pmtAssetNameA = $t090109097._2
262+ let pmtDecimalsA = $t090109097._3
263+ let $t091029189 = getAssetInfoFromString(strAssetIdB)
264+ let pmtStrAssetIdB = $t091029189._1
265+ let pmtAssetNameB = $t091029189._2
266+ let pmtDecimalsB = $t091029189._3
267+ if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
268+ then throw("Only admin can call this function")
269+ else if (isDefined(getBoolean(this, keyActive)))
270+ then throw("DApp is already active")
271+ else if ((strAssetIdA == strAssetIdB))
272+ then throw("Assets must be different")
273+ else {
274+ let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
275+ let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
276+ let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
277+ let shareInitialSupply = 0
278+ let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
279+ let shareIssueId = calculateAssetId(shareIssue)
280+ 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)]
281+ if (firstHarvest)
282+ then (baseEntry ++ [BooleanEntry(keyFirstHarvest, firstHarvest), IntegerEntry(keyFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
283+ else baseEntry
284+ }
285+ }
286+
287+
288+
289+@Callable(i)
290+func keepLimitForFirstHarvest (shareLimit) = if (!(isActive))
291+ then throw("DApp is inactive at this moment")
292+ else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
293+ then throw("Only admin can call this function")
294+ else [IntegerEntry(kShareLimit, shareLimit)]
222295
223296
224297
225298 @Callable(i)
226299 func replenishWithTwoTokens (slippageTolerance) = {
227300 let pmtAssetIdA = i.payments[0].assetId
228301 let pmtAssetIdB = i.payments[1].assetId
229302 let pmtAmountA = deductStakingFee(i.payments[0].amount, pmtAssetIdA)
230303 let pmtAmountB = deductStakingFee(i.payments[1].amount, pmtAssetIdB)
231- let tokenRatio = fraction(fraction(balanceA, scaleValue8, pmtAmountA), scaleValue3, fraction(balanceB, scaleValue8, pmtAmountB))
232- let ratioShareTokensInA = fraction(pmtAmountA, scaleValue8, balanceA)
233- let ratioShareTokensInB = fraction(pmtAmountB, scaleValue8, balanceB)
234- let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scaleValue8)
235- if (!(isActive))
236- then throw("DApp is inactive at this moment")
237- else if (if ((0 > slippageTolerance))
238- then true
239- else (slippageTolerance > slippageToleranceDelimiter))
240- then throw(((("Slippage tolerance must be between 0 and " + toString(slippageToleranceDelimiter)) + " inclusively. Actual: ") + toString(slippageTolerance)))
241- else if ((size(i.payments) != 2))
242- then throw("Two attached assets expected")
243- else if (if ((pmtAssetIdA != assetIdA))
304+ if (if ((balanceA == 0))
305+ then (balanceB == 0)
306+ else false)
307+ then {
308+ let $t01187411951 = getAssetInfo(pmtAssetIdA)
309+ let pmtStrAssetIdA = $t01187411951._1
310+ let pmtAssetNameA = $t01187411951._2
311+ let pmtDecimalsA = $t01187411951._3
312+ let $t01196012037 = getAssetInfo(pmtAssetIdB)
313+ let pmtStrAssetIdB = $t01196012037._1
314+ let pmtAssetNameB = $t01196012037._2
315+ let pmtDecimalsB = $t01196012037._3
316+ let tokenRatio = fraction(fraction(assetInitA, scaleValue8, pmtAmountA), scaleValue3, fraction(assetInitB, scaleValue8, pmtAmountB))
317+ if ((pmtAssetIdA == pmtAssetIdB))
318+ then throw("Assets must be different")
319+ else {
320+ let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
321+ let shareInitialSupply = fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, HALFDOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, HALFDOWN), pow(10, 0, shareDecimals, 0, 0, HALFDOWN))
322+ if (!(isActive))
323+ then throw("DApp is inactive at this moment")
324+ else if (if ((0 > slippageTolerance))
325+ then true
326+ else (slippageTolerance > slippageToleranceDelimiter))
327+ then throw(((("Slippage tolerance must be between 0 and " + toString(slippageToleranceDelimiter)) + " inclusively. Actual: ") + toString(slippageTolerance)))
328+ else if ((size(i.payments) != 2))
329+ then throw("Two attached assets expected")
330+ else if (if ((((scaleValue3 * (slippageToleranceDelimiter - slippageTolerance)) / slippageToleranceDelimiter) > tokenRatio))
331+ then true
332+ else (tokenRatio > ((scaleValue3 * (slippageToleranceDelimiter + slippageTolerance)) / slippageToleranceDelimiter)))
333+ then throw("Incorrect assets amount: amounts must have the contract ratio")
334+ else if (if ((pmtAssetIdA != assetIdA))
335+ then true
336+ else (pmtAssetIdB != assetIdB))
337+ then throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
338+ else if ((shareInitialSupply == 0))
339+ then throw("Too small amount to replenish")
340+ else if (!(hasEnoughBalance))
341+ then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
342+ else [Reissue(shareAssetId, shareInitialSupply, true), IntegerEntry(keyBalanceA, pmtAmountA), IntegerEntry(keyBalanceB, pmtAmountB), IntegerEntry(keyShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareAssetId)]
343+ }
344+ }
345+ else {
346+ let tokenRatio = fraction(fraction(balanceA, scaleValue8, pmtAmountA), scaleValue3, fraction(balanceB, scaleValue8, pmtAmountB))
347+ let ratioShareTokensInA = fraction(pmtAmountA, scaleValue8, balanceA)
348+ let ratioShareTokensInB = fraction(pmtAmountB, scaleValue8, balanceB)
349+ let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scaleValue8)
350+ if (!(isActive))
351+ then throw("DApp is inactive at this moment")
352+ else if (if ((0 > slippageTolerance))
244353 then true
245- else (pmtAssetIdB != assetIdB))
246- then throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
247- else if (if ((((scaleValue3 * (slippageToleranceDelimiter - slippageTolerance)) / slippageToleranceDelimiter) > tokenRatio))
248- then true
249- else (tokenRatio > ((scaleValue3 * (slippageToleranceDelimiter + slippageTolerance)) / slippageToleranceDelimiter)))
250- then throw("Incorrect assets amount: amounts must have the contract ratio")
251- else if ((shareTokenToPayAmount == 0))
252- then throw("Too small amount to replenish")
253- else if (!(hasEnoughBalance))
254- then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
255- else [IntegerEntry(keyBalanceA, (balanceA + pmtAmountA)), IntegerEntry(keyBalanceB, (balanceB + pmtAmountB)), IntegerEntry(keyShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId)]
354+ else (slippageTolerance > slippageToleranceDelimiter))
355+ then throw(((("Slippage tolerance must be between 0 and " + toString(slippageToleranceDelimiter)) + " inclusively. Actual: ") + toString(slippageTolerance)))
356+ else if ((size(i.payments) != 2))
357+ then throw("Two attached assets expected")
358+ else if (if ((pmtAssetIdA != assetIdA))
359+ then true
360+ else (pmtAssetIdB != assetIdB))
361+ then throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
362+ else if (if ((((scaleValue3 * (slippageToleranceDelimiter - slippageTolerance)) / slippageToleranceDelimiter) > tokenRatio))
363+ then true
364+ else (tokenRatio > ((scaleValue3 * (slippageToleranceDelimiter + slippageTolerance)) / slippageToleranceDelimiter)))
365+ then throw("Incorrect assets amount: amounts must have the contract ratio")
366+ else if ((shareTokenToPayAmount == 0))
367+ then throw("Too small amount to replenish")
368+ else if (!(hasEnoughBalance))
369+ then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
370+ else [IntegerEntry(keyBalanceA, (balanceA + pmtAmountA)), IntegerEntry(keyBalanceB, (balanceB + pmtAmountB)), IntegerEntry(keyShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId)]
371+ }
256372 }
257373
258374
259375
260376 @Callable(i)
261377 func withdraw () = {
262- let $t01000910159 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
263- let pmtAmount = $t01000910159._1
264- let pmtAssetId = $t01000910159._2
378+ let $t01644916599 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
379+ let pmtAmount = $t01644916599._1
380+ let pmtAssetId = $t01644916599._2
265381 let amountToPayA = deductStakingFee(fraction(pmtAmount, balanceA, shareAssetSupply), assetIdA)
266382 let amountToPayB = deductStakingFee(fraction(pmtAmount, balanceB, shareAssetSupply), assetIdB)
267383 if (!(isActive))
268384 then throw("DApp is inactive at this moment")
269385 else if ((size(i.payments) != 1))
270386 then throw("One attached payment expected")
271387 else if ((pmtAssetId != shareAssetId))
272388 then throw(("Incorrect asset attached. Expected: " + toBase58String(shareAssetId)))
273389 else if (!(hasEnoughBalance))
274390 then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
275391 else if (if ((amountToPayA > availableBalanceA))
276392 then true
277393 else (amountToPayB > availableBalanceB))
278394 then throwInsufficientAvailableBalances(amountToPayA, amountToPayB)
279395 else [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)]
280396 }
281397
282398
283399
284400 @Callable(i)
285401 func exchange (minAmountToReceive) = {
286- let $t01136511440 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
287- let pmtAmount = $t01136511440._1
288- let pmtAssetId = $t01136511440._2
402+ let $t01780517880 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
403+ let pmtAmount = $t01780517880._1
404+ let pmtAssetId = $t01780517880._2
289405 func calculateFees (tokenFrom,tokenTo) = {
290406 let amountWithoutFee = fraction(tokenTo, pmtAmount, (pmtAmount + tokenFrom))
291407 let amountWithFee = fraction(amountWithoutFee, (commissionScaleDelimiter - commission), commissionScaleDelimiter)
292408 let governanceReward = fraction(amountWithoutFee, commissionGovernance, commissionScaleDelimiter)
293409 if ((minAmountToReceive > amountWithFee))
294410 then throw(((("Calculated amount to receive " + toString(amountWithFee)) + " is less than specified minimum ") + toString(minAmountToReceive)))
295411 else $Tuple3(amountWithoutFee, amountWithFee, governanceReward)
296412 }
297413
298414 if (!(isActive))
299415 then throw("DApp is inactive at this moment")
300- else if ((0 >= minAmountToReceive))
301- then throw(("Minimal amount to receive must be positive. Actual: " + toString(minAmountToReceive)))
302- else if ((size(i.payments) != 1))
303- then throw("One attached payment expected")
304- else if (!(hasEnoughBalance))
305- then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
306- else if ((pmtAssetId == assetIdA))
307- then {
308- let assetIdSend = assetIdB
309- let $t01261512706 = calculateFees(balanceA, balanceB)
310- let amountWithoutFee = $t01261512706._1
311- let amountWithFee = $t01261512706._2
312- let governanceReward = $t01261512706._3
313- let newBalanceA = (balanceA + pmtAmount)
314- let newBalanceB = ((balanceB - amountWithFee) - governanceReward)
315- if (if ((stakedAmountA >= newBalanceA))
316- then true
317- else (stakedAmountB >= newBalanceB))
318- then throwInsufficientAvailableBalance(amountWithFee, availableBalanceB, assetNameB)
319- else [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(governanceAddress, governanceReward, assetIdSend)]
320- }
321- else if ((pmtAssetId == assetIdB))
416+ else if (if ((balanceA == 0))
417+ then true
418+ else (balanceB == 0))
419+ then throw("Can't exchange with zero balance")
420+ else if ((0 >= minAmountToReceive))
421+ then throw(("Minimal amount to receive must be positive. Actual: " + toString(minAmountToReceive)))
422+ else if ((size(i.payments) != 1))
423+ then throw("One attached payment expected")
424+ else if (!(hasEnoughBalance))
425+ then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
426+ else if ((pmtAssetId == assetIdA))
322427 then {
323- let assetIdSend = assetIdA
324- let $t01352913620 = calculateFees(balanceB, balanceA)
325- let amountWithoutFee = $t01352913620._1
326- let amountWithFee = $t01352913620._2
327- let governanceReward = $t01352913620._3
328- let newBalanceA = ((balanceA - amountWithFee) - governanceReward)
329- let newBalanceB = (balanceB + pmtAmount)
330- if (if ((stakedAmountA >= newBalanceA))
428+ let assetIdSend = assetIdB
429+ let $t01915419245 = calculateFees(balanceA, balanceB)
430+ let amountWithoutFee = $t01915419245._1
431+ let amountWithFee = $t01915419245._2
432+ let governanceReward = $t01915419245._3
433+ let newBalanceA = (balanceA + pmtAmount)
434+ let newBalanceB = ((balanceB - amountWithFee) - governanceReward)
435+ if (if (if ((assetIdA == USDN))
436+ then (stakedAmountUSDN >= newBalanceA)
437+ else false)
331438 then true
332- else (stakedAmountB >= newBalanceB))
333- then throwInsufficientAvailableBalance(amountWithFee, availableBalanceA, assetNameA)
334- else [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(governanceAddress, governanceReward, assetIdSend)]
439+ else if ((assetIdB == USDN))
440+ then (stakedAmountUSDN >= newBalanceB)
441+ else false)
442+ then throwInsufficientAvailableBalance(amountWithFee, availableBalanceB, assetNameB)
443+ else [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)]
335444 }
336- else throw(((("Incorrect asset attached. Expected: " + strAssetIdA) + " or ") + strAssetIdB))
445+ else if ((pmtAssetId == assetIdB))
446+ then {
447+ let assetIdSend = assetIdA
448+ let $t02011420205 = calculateFees(balanceB, balanceA)
449+ let amountWithoutFee = $t02011420205._1
450+ let amountWithFee = $t02011420205._2
451+ let governanceReward = $t02011420205._3
452+ let newBalanceA = ((balanceA - amountWithFee) - governanceReward)
453+ let newBalanceB = (balanceB + pmtAmount)
454+ if (if (if ((assetIdA == USDN))
455+ then (stakedAmountUSDN >= newBalanceA)
456+ else false)
457+ then true
458+ else if ((assetIdB == USDN))
459+ then (stakedAmountUSDN >= newBalanceB)
460+ else false)
461+ then throwInsufficientAvailableBalance(amountWithFee, availableBalanceA, assetNameA)
462+ else [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)]
463+ }
464+ else throw(((("Incorrect asset attached. Expected: " + strAssetIdA) + " or ") + strAssetIdB))
337465 }
338466
339467
340468
341469 @Callable(i)
342470 func shutdown () = if (!(isActive))
343471 then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, keyCause), "the cause wasn't specified")))
344472 else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStartStop], i.callerPublicKey)))
345473 then throw("Only admin can call this function")
346474 else suspend("Paused by admin")
347475
348476
349477
350478 @Callable(i)
351479 func activate () = if (isActive)
352480 then throw("DApp is already active")
353481 else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStartStop], i.callerPublicKey)))
354482 then throw("Only admin can call this function")
355483 else [BooleanEntry(keyActive, true), DeleteEntry(keyCause)]
356484
357485
358486
359487 @Callable(i)
360488 func takeIntoAccountExtraFunds (amountLeave) = {
361489 let uncountableAmountEnrollAssetA = (accountBalanceWithStakedA - balanceA)
362490 let uncountableAmountEnrollAssetB = (accountBalanceWithStakedB - balanceB)
363491 let amountEnrollA = (uncountableAmountEnrollAssetA - (if ((assetIdA == unit))
364492 then amountLeave
365493 else 0))
366494 let amountEnrollB = (uncountableAmountEnrollAssetB - (if ((assetIdB == unit))
367495 then amountLeave
368496 else 0))
369497 if (!(isActive))
370498 then throw("DApp is inactive at this moment")
371499 else if ((i.caller != this))
372500 then throw("Only the DApp itself can call this function")
373501 else if ((0 > amountLeave))
374502 then throw(("Argument 'amountLeave' cannot be negative. Actual: " + toString(amountLeave)))
375503 else if (if ((0 > uncountableAmountEnrollAssetA))
376504 then true
377505 else (0 > uncountableAmountEnrollAssetB))
378506 then suspend("Enroll amount negative")
379507 else if (if ((0 > amountEnrollA))
380508 then true
381509 else (0 > amountEnrollB))
382510 then throw("Too large amountLeave")
383511 else [IntegerEntry(keyBalanceA, (balanceA + amountEnrollA)), IntegerEntry(keyBalanceB, (balanceB + amountEnrollB)), IntegerEntry(("last_income_" + strAssetIdA), amountEnrollA), IntegerEntry(("last_income_" + strAssetIdB), amountEnrollB)]
384512 }
385513
386514
387515 @Verifier(tx)
388516 func verify () = match tx {
389517 case invoke: InvokeScriptTransaction =>
390- if (if (if (sigVerify(invoke.bodyBytes, invoke.proofs[0], adminPubKeyStaking))
391- then (invoke.dApp == stakingAddressUSDN)
518+ let callTakeIntoAccount = if ((invoke.dApp == this))
519+ then (invoke.function == "takeIntoAccountExtraFunds")
520+ else false
521+ let callStaking = if ((invoke.dApp == stakingAddress))
522+ then if (if (if ((invoke.function == "lockNeutrino"))
523+ then (size(invoke.payments) == 1)
524+ else false)
525+ then (invoke.payments[0].assetId == USDN)
526+ else false)
527+ then true
528+ else if ((invoke.function == "unlockNeutrino"))
529+ then (size(invoke.payments) == 0)
530+ else false
531+ else false
532+ let exchangeToWaves = if (if (if ((invoke.dApp == USDNToWavesExchanger))
533+ then (invoke.function == "exchange")
534+ else false)
535+ then (assetIdA == USDN)
392536 else false)
393537 then true
394- else if (if (sigVerify(invoke.bodyBytes, invoke.proofs[0], adminPubKeyStaking))
395- then (invoke.function == "exchange")
396- else false)
397- then if (if (if (if ((assetIdA == NSBT))
398- then (assetIdB == USDN)
399- else false)
400- then (invoke.dApp == swopUSDNtoWAVES)
401- else false)
402- then if ((invoke.payments[0].assetId == unit))
403- then true
404- else (invoke.payments[0].assetId == USDN)
405- else false)
406- then true
407- else if (if ((assetIdA == NSBT))
408- then (assetIdB == SWOP)
409- else false)
410- then if (if ((invoke.dApp == swopUSDNtoNSBT))
411- then (invoke.payments[0].assetId == USDN)
412- else false)
413- then true
414- else if ((invoke.dApp == swopUSDNtoWAVES))
415- then if ((invoke.payments[0].assetId == unit))
416- then true
417- else (invoke.payments[0].assetId == USDN)
418- else false
419- else false
420- else false)
538+ else if ((assetIdB == USDN))
539+ then (invoke.payments[0].assetId == USDN)
540+ else false
541+ let signedByAdmin = if (if (if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
421542 then true
422- else if (if (sigVerify(invoke.bodyBytes, invoke.proofs[0], adminPubKeyStaking))
423- then (invoke.dApp == this)
424- else false)
425- then (invoke.function == "takeIntoAccountExtraFunds")
426- else false
543+ else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey2))
544+ then true
545+ else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey3))
546+ then true
547+ else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKeyStaking)
548+ if (if (if (callTakeIntoAccount)
549+ then true
550+ else callStaking)
551+ then true
552+ else exchangeToWaves)
553+ then signedByAdmin
554+ else false
427555 case _ =>
428556 let adminPubKey1Signed = if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
429557 then 1
430558 else 0
431559 let adminPubKey2Signed = if (sigVerify(tx.bodyBytes, tx.proofs[1], adminPubKey2))
432560 then 1
433561 else 0
434562 let adminPubKey3Signed = if (sigVerify(tx.bodyBytes, tx.proofs[2], adminPubKey3))
435563 then 1
436564 else 0
437565 (((adminPubKey1Signed + adminPubKey2Signed) + adminPubKey3Signed) >= 2)
438566 }
439567

github/deemru/w8io/026f985 
90.83 ms