tx · GGXMBdksGU9SRPo24E1H28ufA95DQpgS8FbZV59CKLRk

3Mt9Nh39gKm24JXVSvcn1mCwxvVcBiGMqY9:  -0.01400000 Waves

2021.07.30 13:56 [1636277] smart account 3Mt9Nh39gKm24JXVSvcn1mCwxvVcBiGMqY9 > SELF 0.00000000 Waves

{ "type": 13, "id": "GGXMBdksGU9SRPo24E1H28ufA95DQpgS8FbZV59CKLRk", "fee": 1400000, "feeAssetId": null, "timestamp": 1627642594936, "version": 2, "chainId": 84, "sender": "3Mt9Nh39gKm24JXVSvcn1mCwxvVcBiGMqY9", "senderPublicKey": "VLgrg9cZDVy1x4bBFdv3d2v7RUCAS8jYvf84qLWAm6d", "proofs": [ "3RhaUzC1jg91FbuqLiFtcbJMeNctRkcmLqorf2KvA1C8gpP7pirMLnm2YDzAi1mEkpiR7amhn1NVJmTNmhWjBCMi", "2E6iokivSLPLCtAp4YezUt9qaEsGFhxMNeaid7LQq6XFHubjrDG6hAQ2tDHeHmnmQSX91HHGGYUTUrARC1UAAWRg" ], "script": "base64:AAIFAAAAAAAAACoIAhIDCgEEEgcKBQEBCAgEEgMKAQESAwoBARIAEgMKAQESABIAEgMKAQEAAABUAAAAAAd2ZXJzaW9uAgAAAAUxLjAuMAAAAAAKa2V5VmVyc2lvbgIAAAAHdmVyc2lvbgAAAAAJa2V5QWN0aXZlAgAAAAZhY3RpdmUAAAAAC2tleUFzc2V0SWRBAgAAAApBX2Fzc2V0X2lkAAAAAAtrZXlBc3NldElkQgIAAAAKQl9hc3NldF9pZAAAAAALa2V5QmFsYW5jZUECAAAAD0FfYXNzZXRfYmFsYW5jZQAAAAALa2V5QmFsYW5jZUICAAAAD0JfYXNzZXRfYmFsYW5jZQAAAAAPa2V5QmFsYW5jZUluaXRBAgAAAAxBX2Fzc2V0X2luaXQAAAAAD2tleUJhbGFuY2VJbml0QgIAAAAMQl9hc3NldF9pbml0AAAAAA9rZXlTaGFyZUFzc2V0SWQCAAAADnNoYXJlX2Fzc2V0X2lkAAAAABNrZXlTaGFyZUFzc2V0U3VwcGx5AgAAABJzaGFyZV9hc3NldF9zdXBwbHkAAAAADWtleUNvbW1pc3Npb24CAAAACmNvbW1pc3Npb24AAAAAG2tleUNvbW1pc3Npb25TY2FsZURlbGltaXRlcgIAAAAaY29tbWlzc2lvbl9zY2FsZV9kZWxpbWl0ZXIAAAAACGtleUNhdXNlAgAAAA5zaHV0ZG93bl9jYXVzZQAAAAAPa2V5Rmlyc3RIYXJ2ZXN0AgAAAA1maXJzdF9oYXJ2ZXN0AAAAABVrZXlGaXJzdEhhcnZlc3RIZWlnaHQCAAAAFGZpcnN0X2hhcnZlc3RfaGVpZ2h0AAAAAAtrU2hhcmVMaW1pdAIAAAAcc2hhcmVfbGltaXRfb25fZmlyc3RfaGFydmVzdAAAAAALa0Jhc2VQZXJpb2QCAAAAC2Jhc2VfcGVyaW9kAAAAAA1rUGVyaW9kTGVuZ3RoAgAAAA1wZXJpb2RfbGVuZ3RoAAAAAAxrU3RhcnRIZWlnaHQCAAAADHN0YXJ0X2hlaWdodAAAAAATa0ZpcnN0SGFydmVzdEhlaWdodAIAAAAUZmlyc3RfaGFydmVzdF9oZWlnaHQAAAAAD2tleUFkbWluUHViS2V5MQIAAAALYWRtaW5fcHViXzEAAAAAD2tleUFkbWluUHViS2V5MgIA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AQUAAAAEdGhpcwMJAAAAAAAAAgUAAAADYUlkBQAAAARFVVJOCQAEGgAAAAIFAAAAEnN0YWtpbmdFVVJOQWRkcmVzcwkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAYJXMlcyVzX19zdGFraW5nQmFsYW5jZV9fCQACWAAAAAEFAAAAA2FJZAIAAAACX18JAAQlAAAAAQUAAAAEdGhpcwAAAAAAAAAAAAMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAEVW5pdAAAAAAAAAAAAAkAAAIAAAABAgAAAAtNYXRjaCBlcnJvcgQAAAAHJG1hdGNoMAUAAAAWc3Rha2VkQW1vdW50Q2FsY3VsYXRlZAMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAADSW50BAAAAAFpBQAAAAckbWF0Y2gwBQAAAAFpAAAAAAAAAAAAAAAAAA1zdGFrZWRBbW91bnRBCQEAAAAMc3Rha2VkQW1vdW50AAAAAQUAAAAIYXNzZXRJZEEAAAAADXN0YWtlZEFtb3VudEIJAQAAAAxzdGFrZWRBbW91bnQAAAABBQAAAAhhc3NldElkQgAAAAAKYXNzZXRJbml0QQkBAAAAEUBleHRyTmF0aXZlKDEwNTApAAAAAgUAAAAEdGhpcwUAAAAPa2V5QmFsYW5jZUluaXRBAAAAAAphc3NldEluaXRCCQEAAAARQGV4dHJOYXRpdmUoMTA1MCkAAAACBQAAAAR0aGlzBQAAAA9rZXlCYWxhbmNlSW5pdEIAAAAAEWF2YWlsYWJsZUJhbGFuY2VBCQAAZQAAAAIFAAAACGJhbGFuY2VBBQAAAA1zdGFrZWRBbW91bnRBAAAAABFhdmFpbGFibGVCYWxhbmNlQgkAAGUAAAACBQAAAAhiYWxhbmNlQgUAAAANc3Rha2VkQW1vdW50QgAAAAAZYWNjb3VudEJhbGFuY2VXaXRoU3Rha2VkQQkAAGQAAAACCQEAAAAOYWNjb3VudEJhbGFuY2UAAAABBQAAAAhhc3NldElkQQUAAAANc3Rha2VkQW1vdW50QQAAAAAZYWNjb3VudEJhbGFuY2VXaXRoU3Rha2VkQgkAAGQAAAACCQEAAAAOYWNjb3VudEJhbGFuY2UAAAABBQAAAAhhc3NldElkQgUAAAANc3Rha2VkQW1vdW50QgAAAAAQaGFzRW5v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AAAMSW50ZWdlckVudHJ5AAAAAgUAAAALa2V5QmFsYW5jZUEFAAAACnBtdEFtb3VudEEJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAC2tleUJhbGFuY2VCBQAAAApwbXRBbW91bnRCCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAA1rZXlDb21taXNzaW9uBQAAAApjb21taXNzaW9uCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABtrZXlDb21taXNzaW9uU2NhbGVEZWxpbWl0ZXIFAAAAGGNvbW1pc3Npb25TY2FsZURlbGltaXRlcgkABEwAAAACBQAAAApzaGFyZUlzc3VlCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAAD2tleVNoYXJlQXNzZXRJZAkAAlgAAAABBQAAAAxzaGFyZUlzc3VlSWQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAE2tleVNoYXJlQXNzZXRTdXBwbHkFAAAAEnNoYXJlSW5pdGlhbFN1cHBseQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIFAAAAEnNoYXJlSW5pdGlhbFN1cHBseQUAAAAMc2hhcmVJc3N1ZUlkBQAAAANuaWwDBQAAAAxmaXJzdEhhcnZlc3QJAAROAAAAAgUAAAAJYmFzZUVudHJ5CQAETAAAAAIJAQAAAAxCb29sZWFuRW50cnkAAAACBQAAAA9rZXlGaXJzdEhhcnZlc3QFAAAADGZpcnN0SGFydmVzdAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAVa2V5Rmlyc3RIYXJ2ZXN0SGVpZ2h0CQAAZAAAAAIFAAAAC3N0YXJ0SGVpZ2h0CQAAaAAAAAIFAAAAFWZpcnN0SGFydmVzdEVuZFBlcmlvZAUAAAAMcGVyaW9kTGVuZ3RoBQAAAANuaWwFAAAACWJhc2VFbnRyeQAAAAFpAQAAABFpbml0V2l0aEluaXRSYXRpbwAAAAUAAAAJYW10QXNzZXRBAAAACWFtdEFzc2V0QgAAAAtzdHJBc3NldElkQQAAAAtzdHJBc3NldElkQgAAAAxmaXJzdEhhcnZlc3QEAAAADSR0MDEwNTY5MTA2NTYJAQAAABZnZXRBc3NldEluZm9Gcm9tU3RyaW5nAAAAAQUAAAALc3RyQXNzZXRJZEEEAAAADnBtdFN0ckFzc2V0SWRBCAUAAAANJHQwMTA1NjkxMDY1NgAAAAJfMQQAAAANcG10QXNzZXROYW1lQQgFAAAADSR0MDEwNTY5MTA2NTYAAAACXzIEAAAADHBtdERlY2ltYWxzQQgFAAAADSR0MDEwNTY5MTA2NTYAAAACXzMEAAAADSR0MDEwNjYxMTA3NDgJAQAAABZnZXRBc3NldEluZm9Gcm9tU3RyaW5nAAAAAQUAAAALc3RyQXNzZXRJZEIEAAAADnBtdFN0ckFzc2V0SWRCCAUAAAANJHQwMTA2NjExMDc0OAAAAAJfMQQAAAANcG10QXNzZXROYW1lQggFAAAADSR0MDEwNjYxMTA3NDgAAAACXzIEAAAADHBtdERlY2ltYWxzQggFAAAADSR0MDEwNjYxMTA3NDgAAAACXzMDCQEAAAABIQAAAAEJAQAAAA9jb250YWluc0VsZW1lbnQAAAACCQAETAAAAAIFAAAADGFkbWluUHViS2V5MQkABEwAAAACBQAAAAxhZG1pblB1YktleTIJAARMAAAAAgUAAAAMYWRtaW5QdWJLZXkzCQAETAAAAAIFAAAAEmFkbWluUHViS2V5U3Rha2luZwUAAAADbmlsCAUAAAABaQAAAA9jYWxsZXJQdWJsaWNLZXkJAAACAAAAAQIAAAAhT25seSBhZG1pbiBjYW4gY2FsbCB0aGlzIGZ1bmN0aW9uAwkBAAAACWlzRGVmaW5lZAAAAAEJAAQbAAAAAgUAAAAEdGhpcwUAAAAJa2V5QWN0aXZlCQAAAgAAAAECAAAAFkRBcHAgaXMgYWxyZWFkeSBhY3RpdmUDCQAAAAAAAAIFAAAAC3N0ckFzc2V0SWRBBQAAAAtzdHJBc3NldElkQgkAAAIAAAABAgAAABhBc3NldHMgbXVzdCBiZSBkaWZmZXJlbnQEAAAACXNoYXJlTmFtZQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAABcwkAAS8AAAACBQAAAA1wbXRBc3NldE5hbWVBAAAAAAAAAAAHAgAAAAFfCQABLwAAAAIFAAAADXBtdEFzc2V0TmFtZUIAAAAAAAAAAAcEAAAAEHNoYXJlRGVzY3JpcHRpb24JAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAACJTaGFyZVRva2VuIG9mIFN3b3BGaSBwcm90b2NvbCBmb3IgBQAAAA1wbXRBc3NldE5hbWVBAgAAAAUgYW5kIAUAAAANcG10QXNzZXROYW1lQgIAAAAMIGF0IGFkZHJlc3MgCQAEJQAAAAEFAAAABHRoaXMEAAAADXNoYXJlRGVjaW1hbHMJAABpAAAAAgkAAGQAAAACBQAAAAxwbXREZWNpbWFsc0EFAAAADHBtdERlY2ltYWxzQgAAAAAAAAAAAgQAAAASc2hhcmVJbml0aWFsU3VwcGx5AAAAAAAAAAAABAAAAApzaGFyZUlzc3VlCQAEQgAAAAUFAAAACXNoYXJlTmFtZQUAAAAQc2hhcmVEZXNjcmlwdGlvbgUAAAASc2hhcmVJbml0aWFsU3VwcGx5BQAAAA1zaGFyZURlY2ltYWxzBgQAAAAMc2hhcmVJc3N1ZUlkCQAEOAAAAAEFAAAACnNoYXJlSXNzdWUEAAAACWJhc2VFbnRyeQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAAAprZXlWZXJzaW9uBQAAAAd2ZXJzaW9uCQAETAAAAAIJAQAAAAxCb29sZWFuRW50cnkAAAACBQAAAAlrZXlBY3RpdmUGCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAAC2tleUFzc2V0SWRBBQAAAA5wbXRTdHJBc3NldElkQQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAAAtrZXlBc3NldElkQgUAAAAOcG10U3RyQXNzZXRJZEIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAD2tleUJhbGFuY2VJbml0QQUAAAAJYW10QXNzZXRBCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAA9rZXlCYWxhbmNlSW5pdEIFAAAACWFtdEFzc2V0QgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAALa2V5QmFsYW5jZUEAAAAAAAAAAAAJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAC2tleUJhbGFuY2VCAAAAAAAAAAAACQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAA1rZXlDb21taXNzaW9uBQAAAApjb21taXNzaW9uCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABtrZXlDb21taXNzaW9uU2NhbGVEZWxpbWl0ZXIFAAAAGGNvbW1pc3Npb25TY2FsZURlbGltaXRlcgkABEwAAAACBQAAAApzaGFyZUlzc3VlCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAAD2tleVNoYXJlQXNzZXRJZAkAAlgAAAABBQAAAAxzaGFyZUlzc3VlSWQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAE2tleVNoYXJlQXNzZXRTdXBwbHkFAAAAEnNoYXJlSW5pdGlhbFN1cHBseQUAAAADbmlsAwUAAAAMZmlyc3RIYXJ2ZXN0CQAETgAAAAIFAAAACWJhc2VFbnRyeQkABEwAAAACCQEAAAAMQm9vbGVhbkVudHJ5AAAAAgUAAAAPa2V5Rmlyc3RIYXJ2ZXN0BQAAAAxmaXJzdEhhcnZlc3QJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAFWtleUZpcnN0SGFydmVzdEhlaWdodAkAAGQAAAACBQAAAAtzdGFydEhlaWdodAkAAGgAAAACBQAAABVmaXJzdEhhcnZlc3RFbmRQZXJpb2QFAAAADHBlcmlvZExlbmd0aAUAAAADbmlsBQAAAAliYXNlRW50cnkAAAABaQEAAAAYa2VlcExpbWl0Rm9yRmlyc3RIYXJ2ZXN0AAAAAQAAAApzaGFyZUxpbWl0AwkBAAAAASEAAAABBQAAAAhpc0FjdGl2ZQkAAAIAAAABAgAAAB9EQXBwIGlzIGluYWN0aXZlIGF0IHRoaXMgbW9tZW50AwkBAAAAASEAAAABCQEAAAAPY29udGFpbnNFbGVtZW50AAAAAgkABEwAAAACBQAAAAxhZG1pblB1YktleTEJAARMAAAAAgUAAAAMYWRtaW5QdWJLZXkyCQAETAAAAAIFAAAADGFkbWluUHViS2V5MwkABEwAAAACBQAAABJhZG1pblB1YktleVN0YWtpbmcFAAAAA25pbAgFAAAAAWkAAAAPY2FsbGVyUHVibGljS2V5CQAAAgAAAAECAAAAIU9ubHkgYWRtaW4gY2FuIGNhbGwgdGhpcyBmdW5jdGlvbgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAALa1NoYXJlTGltaXQFAAAACnNoYXJlTGltaXQFAAAAA25pbAAAAAFpAQAAABZyZXBsZW5pc2hXaXRoVHdvVG9rZW5zAAAAAQAAABFzbGlwcGFnZVRvbGVyYW5jZQQAAAALcG10QXNzZXRJZEEICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAAB2Fzc2V0SWQEAAAAC3BtdEFzc2V0SWRCCAkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAQAAAAdhc3NldElkBAAAAApwbXRBbW91bnRBCQEAAAAQZGVkdWN0U3Rha2luZ0ZlZQAAAAMICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAABmFtb3VudAUAAAALcG10QXNzZXRJZEEFAAAAC3BtdEFzc2V0SWRCBAAAAApwbXRBbW91bnRCCQEAAAAQZGVkdWN0U3Rha2luZ0ZlZQAAAAMICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAABAAAABmFtb3VudAUAAAALcG10QXNzZXRJZEIFAAAAC3BtdEFzc2V0SWRBAwMJAAAAAAAAAgUAAAAIYmFsYW5jZUEAAAAAAAAAAAAJAAAAAAAAAgUAAAAIYmFsYW5jZUIAAAAAAAAAAAAHBAAAAA0kdDAxMzQ1OTEzNTM2CQEAAAAMZ2V0QXNzZXRJbmZvAAAAAQUAAAALcG10QXNzZXRJZEEEAAAADnBtdFN0ckFzc2V0SWRBCAUAAAANJHQwMTM0NTkxMzUzNgAAAAJfMQQAAAANcG10QXNzZXROYW1lQQgFAAAADSR0MDEzNDU5MTM1MzYAAAACXzIEAAAADHBtdERlY2ltYWxzQQgFAAAADSR0MDEzNDU5MTM1MzYAAAACXzMEAAAADSR0MDEzNTQ1MTM2MjIJAQAAAAxnZXRBc3NldEluZm8AAAABBQAAAAtwbXRBc3NldElkQgQAAAAOcG10U3RyQXNzZXRJZEIIBQAAAA0kdDAxMzU0NTEzNjIyAAAAAl8xBAAAAA1wbXRBc3NldE5hbWVCCAUAAAANJHQwMTM1NDUxMzYyMgAAAAJfMgQAAAAMcG10RGVjaW1hbHNCCAUAAAANJHQwMTM1NDUxMzYyMgAAAAJfMwQAAAAKdG9rZW5SYXRpbwkAAGsAAAADCQAAawAAAAMFAAAACmFzc2V0SW5pdEEFAAAAC3NjYWxlVmFsdWU4BQAAAApwbXRBbW91bnRBBQAAAAtzY2FsZVZhbHVlMwkAAGsAAAADBQAAAAphc3NldEluaXRCBQAAAAtzY2FsZVZhbHVlOAUAAAAKcG10QW1vdW50QgMJAAAAAAAAAgUAAAALcG10QXNzZXRJZEEFAAAAC3BtdEFzc2V0SWRCCQAAAgAAAAECAAAAGEFzc2V0cyBtdXN0IGJlIGRpZmZlcmVudAQAAAANc2hhcmVEZWNpbWFscwkAAGkAAAACCQAAZAAAAAIFAAAADHBtdERlY2ltYWxzQQUAAAAMcG10RGVjaW1hbHNCAAAAAAAAAAACBAAAABJzaGFyZUluaXRpYWxTdXBwbHkJAABrAAAAAwkAAGwAAAAGBQAAAApwbXRBbW91bnRBBQAAAAxwbXREZWNpbWFsc0EAAAAAAAAAAAUAAAAAAAAAAAEFAAAADHBtdERlY2ltYWxzQQUAAAAERE9XTgkAAGwAAAAGBQAAAApwbXRBbW91bnRCBQAAAAxwbXREZWNpbWFsc0IAAAAAAAAAAAUAAAAAAAAAAAEFAAAADHBtdERlY2ltYWxzQgUAAAAERE9XTgkAAGwAAAAGAAAAAAAAAAAKAAAAAAAAAAAABQAAAA1zaGFyZURlY2ltYWxzAAAAAAAAAAAAAAAAAAAAAAAABQAAAARET1dOAwkBAAAAASEAAAABBQAAAAhpc0FjdGl2ZQkAAAIAAAABAgAAAB9EQXBwIGlzIGluYWN0aXZlIGF0IHRoaXMgbW9tZW50AwMJAABmAAAAAgAAAAAAAAAAAAUAAAARc2xpcHBhZ2VUb2xlcmFuY2UGCQAAZgAAAAIFAAAAEXNsaXBwYWdlVG9sZXJhbmNlBQAAABpzbGlwcGFnZVRvbGVyYW5jZURlbGltaXRlcgkAAAIAAAABCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAClTbGlwcGFnZSB0b2xlcmFuY2UgbXVzdCBiZSBiZXR3ZWVuIDAgYW5kIAkAAaQAAAABBQAAABpzbGlwcGFnZVRvbGVyYW5jZURlbGltaXRlcgIAAAAWIGluY2x1c2l2ZWx5LiBBY3R1YWw6IAkAAaQAAAABBQAAABFzbGlwcGFnZVRvbGVyYW5jZQMJAQAAAAIhPQAAAAIJAAGQAAAAAQgFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAIJAAACAAAAAQIAAAAcVHdvIGF0dGFjaGVkIGFzc2V0cyBleHBlY3RlZAMDCQAAZgAAAAIJAABpAAAAAgkAAGgAAAACBQAAAAtzY2FsZVZhbHVlMwkAAGUAAAACBQAAABpzbGlwcGFnZVRvbGVyYW5jZURlbGltaXRlcgUAAAARc2xpcHBhZ2VUb2xlcmFuY2UFAAAAGnNsaXBwYWdlVG9sZXJhbmNlRGVsaW1pdGVyBQAAAAp0b2tlblJhdGlvBgkAAGYAAAACBQAAAAp0b2tlblJhdGlvCQAAaQAAAAIJAABoAAAAAgUAAAALc2NhbGVWYWx1ZTMJAABkAAAAAgUAAAAac2xpcHBhZ2VUb2xlcmFuY2VEZWxpbWl0ZXIFAAAAEXNsaXBwYWdlVG9sZXJhbmNlBQAAABpzbGlwcGFnZVRvbGVyYW5jZURlbGltaXRlcgkAAAIAAAABAgAAAD1JbmNvcnJlY3QgYXNzZXRzIGFtb3VudDogYW1vdW50cyBtdXN0IGhhdmUgdGhlIGNvbnRyYWN0IHJhdGlvAwMJAQAAAAIhPQAAAAIFAAAAC3BtdEFzc2V0SWRBBQAAAAhhc3NldElkQQYJAQAAAAIhPQAAAAIFAAAAC3BtdEFzc2V0SWRCBQAAAAhhc3NldElkQgkAAAIAAAABCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAACVJbmNvcnJlY3QgYXNzZXRzIGF0dGFjaGVkLiBFeHBlY3RlZDogBQAAAAtzdHJBc3NldElkQQIAAAAFIGFuZCAFAAAAC3N0ckFzc2V0SWRCAwkAAAAAAAACBQAAABJzaGFyZUluaXRpYWxTdXBwbHkAAAAAAAAAAAAJAAACAAAAAQIAAAAdVG9vIHNtYWxsIGFtb3VudCB0byByZXBsZW5pc2gDCQEAAAABIQAAAAEFAAAAEGhhc0Vub3VnaEJhbGFuY2UJAAROAAAAAgkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIFAAAACnBtdEFtb3VudEEFAAAAC3BtdEFzc2V0SWRBCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAAKcG10QW1vdW50QgUAAAALcG10QXNzZXRJZEIFAAAAA25pbAkBAAAAEXN1c3BlbmRTdXNwaWNpb3VzAAAAAAkABEwAAAACCQEAAAAHUmVpc3N1ZQAAAAMFAAAADHNoYXJlQXNzZXRJZAUAAAASc2hhcmVJbml0aWFsU3VwcGx5BgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAALa2V5QmFsYW5jZUEFAAAACnBtdEFtb3VudEEJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAC2tleUJhbGFuY2VCBQAAAApwbXRBbW91bnRCCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABNrZXlTaGFyZUFzc2V0U3VwcGx5BQAAABJzaGFyZUluaXRpYWxTdXBwbHkJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAABJzaGFyZUluaXRpYWxTdXBwbHkFAAAADHNoYXJlQXNzZXRJZAUAAAADbmlsBAAAAAp0b2tlblJhdGlvCQAAawAAAAMJAABrAAAAAwUAAAAIYmFsYW5jZUEFAAAAC3NjYWxlVmFsdWU4BQAAAApwbXRBbW91bnRBBQAAAAtzY2FsZVZhbHVlMwkAAGsAAAADBQAAAAhiYWxhbmNlQgUAAAALc2NhbGVWYWx1ZTgFAAAACnBtdEFtb3VudEIEAAAAE3JhdGlvU2hhcmVUb2tlbnNJbkEJAABrAAAAAwUAAAAKcG10QW1vdW50QQUAAAALc2NhbGVWYWx1ZTgFAAAACGJhbGFuY2VBBAAAABNyYXRpb1NoYXJlVG9rZW5zSW5CCQAAawAAAAMFAAAACnBtdEFtb3VudEIFAAAAC3NjYWxlVmFsdWU4BQAAAAhiYWxhbmNlQgQAAAAVc2hhcmVUb2tlblRvUGF5QW1vdW50CQAAawAAAAMJAAGXAAAAAQkABEwAAAACBQAAABNyYXRpb1NoYXJlVG9rZW5zSW5BCQAETAAAAAIFAAAAE3JhdGlvU2hhcmVUb2tlbnNJbkIFAAAAA25pbAUAAAAQc2hhcmVBc3NldFN1cHBseQUAAAALc2NhbGVWYWx1ZTgDCQEAAAABIQAAAAEFAAAACGlzQWN0aXZlCQAAAgAAAAECAAAAH0RBcHAgaXMgaW5hY3RpdmUgYXQgdGhpcyBtb21lbnQDAwkAAGYAAAACAAAAAAAAAAAABQAAABFzbGlwcGFnZVRvbGVyYW5jZQYJAABmAAAAAgUAAAARc2xpcHBhZ2VUb2xlcmFuY2UFAAAAGnNsaXBwYWdlVG9sZXJhbmNlRGVsaW1pdGVyCQAAAgAAAAEJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAKVNsaXBwYWdlIHRvbGVyYW5jZSBtdXN0IGJlIGJldHdlZW4gMCBhbmQgCQABpAAAAAEFAAAAGnNsaXBwYWdlVG9sZXJhbmNlRGVsaW1pdGVyAgAAABYgaW5jbHVzaXZlbHkuIEFjdHVhbDogCQABpAAAAAEFAAAAEXNsaXBwYWdlVG9sZXJhbmNlAwkBAAAAAiE9AAAAAgkAAZAAAAABCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAgkAAAIAAAABAgAAABxUd28gYXR0YWNoZWQgYXNzZXRzIGV4cGVjdGVkAwMJAQAAAAIhPQAAAAIFAAAAC3BtdEFzc2V0SWRBBQAAAAhhc3NldElkQQYJAQAAAAIhPQAAAAIFAAAAC3BtdEFzc2V0SWRCBQAAAAhhc3NldElkQgkAAAIAAAABCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAACVJbmNvcnJlY3QgYXNzZXRzIGF0dGFjaGVkLiBFeHBlY3RlZDogBQAAAAtzdHJBc3NldElkQQIAAAAFIGFuZCAFAAAAC3N0ckFzc2V0SWRCAwMJAABmAAAAAgkAAGkAAAACCQAAaAAAAAIFAAAAC3NjYWxlVmFsdWUzCQAAZQAAAAIFAAAAGnNsaXBwYWdlVG9sZXJhbmNlRGVsaW1pdGVyBQAAABFzbGlwcGFnZVRvbGVyYW5jZQUAAAAac2xpcHBhZ2VUb2xlcmFuY2VEZWxpbWl0ZXIFAAAACnRva2VuUmF0aW8GCQAAZgAAAAIFAAAACnRva2VuUmF0aW8JAABpAAAAAgkAAGgAAAACBQAAAAtzY2FsZVZhbHVlMwkAAGQAAAACBQAAABpzbGlwcGFnZVRvbGVyYW5jZURlbGltaXRlcgUAAAARc2xpcHBhZ2VUb2xlcmFuY2UFAAAAGnNsaXBwYWdlVG9sZXJhbmNlRGVsaW1pdGVyCQAAAgAAAAECAAAAPUluY29ycmVjdCBhc3NldHMgYW1vdW50OiBhbW91bnRzIG11c3QgaGF2ZSB0aGUgY29udHJhY3QgcmF0aW8DCQAAAAAAAAIFAAAAFXNoYXJlVG9rZW5Ub1BheUFtb3VudAAAAAAAAAAAAAkAAAIAAAABAgAAAB1Ub28gc21hbGwgYW1vdW50IHRvIHJlcGxlbmlzaAMJAQAAAAEhAAAAAQUAAAAQaGFzRW5vdWdoQmFsYW5jZQkABE4AAAACCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAAKcG10QW1vdW50QQUAAAALcG10QXNzZXRJZEEJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAAApwbXRBbW91bnRCBQAAAAtwbXRBc3NldElkQgUAAAADbmlsCQEAAAARc3VzcGVuZFN1c3BpY2lvdXMAAAAACQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAtrZXlCYWxhbmNlQQkAAGQAAAACBQAAAAhiYWxhbmNlQQUAAAAKcG10QW1vdW50QQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAALa2V5QmFsYW5jZUIJAABkAAAAAgUAAAAIYmFsYW5jZUIFAAAACnBtdEFtb3VudEIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAE2tleVNoYXJlQXNzZXRTdXBwbHkJAABkAAAAAgUAAAAQc2hhcmVBc3NldFN1cHBseQUAAAAVc2hhcmVUb2tlblRvUGF5QW1vdW50CQAETAAAAAIJAQAAAAdSZWlzc3VlAAAAAwUAAAAMc2hhcmVBc3NldElkBQAAABVzaGFyZVRva2VuVG9QYXlBbW91bnQGCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAAVc2hhcmVUb2tlblRvUGF5QW1vdW50BQAAAAxzaGFyZUFzc2V0SWQFAAAAA25pbAAAAAFpAQAAAAh3aXRoZHJhdwAAAAAEAAAADSR0MDE4MDIxMTgxNzEJAAUUAAAAAggJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAAAAAGYW1vdW50CAkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAAAAAdhc3NldElkBAAAAAlwbXRBbW91bnQIBQAAAA0kdDAxODAyMTE4MTcxAAAAAl8xBAAAAApwbXRBc3NldElkCAUAAAANJHQwMTgwMjExODE3MQAAAAJfMgQAAAAMYW1vdW50VG9QYXlBCQEAAAAQZGVkdWN0U3Rha2luZ0ZlZQAAAAMJAABrAAAAAwUAAAAJcG10QW1vdW50BQAAAAhiYWxhbmNlQQUAAAAQc2hhcmVBc3NldFN1cHBseQUAAAAIYXNzZXRJZEEFAAAACGFzc2V0SWRCBAAAAAxhbW91bnRUb1BheUIJAQAAABBkZWR1Y3RTdGFraW5nRmVlAAAAAwkAAGsAAAADBQAAAAlwbXRBbW91bnQFAAAACGJhbGFuY2VCBQAAABBzaGFyZUFzc2V0U3VwcGx5BQAAAAhhc3NldElkQgUAAAAIYXNzZXRJZEEDCQEAAAABIQAAAAEFAAAACGlzQWN0aXZlCQAAAgAAAAECAAAAH0RBcHAgaXMgaW5hY3RpdmUgYXQgdGhpcyBtb21lbnQDCQEAAAACIT0AAAACCQABkAAAAAEIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAABCQAAAgAAAAECAAAAHU9uZSBhdHRhY2hlZCBwYXltZW50IGV4cGVjdGVkAwkBAAAAAiE9AAAAAgUAAAAKcG10QXNzZXRJZAUAAAAMc2hhcmVBc3NldElkCQAAAgAAAAEJAAEsAAAAAgIAAAAkSW5jb3JyZWN0IGFzc2V0IGF0dGFjaGVkLiBFeHBlY3RlZDogCQACWAAAAAEFAAAADHNoYXJlQXNzZXRJZAMJAQAAAAEhAAAAAQUAAAAQaGFzRW5vdWdoQmFsYW5jZQkABE4AAAACCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAAJcG10QW1vdW50BQAAAApwbXRBc3NldElkBQAAAANuaWwJAQAAABFzdXNwZW5kU3VzcGljaW91cwAAAAADAwkAAGYAAAACBQAAAAxhbW91bnRUb1BheUEFAAAAEWF2YWlsYWJsZUJhbGFuY2VBBgkAAGYAAAACBQAAAAxhbW91bnRUb1BheUIFAAAAEWF2YWlsYWJsZUJhbGFuY2VCCQEAAAAidGhyb3dJbnN1ZmZpY2llbnRBdmFpbGFibGVCYWxhbmNlcwAAAAIFAAAADGFtb3VudFRvUGF5QQUAAAAMYW1vdW50VG9QYXlCCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAtrZXlCYWxhbmNlQQkAAGUAAAACBQAAAAhiYWxhbmNlQQUAAAAMYW1vdW50VG9QYXlBCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAtrZXlCYWxhbmNlQgkAAGUAAAACBQAAAAhiYWxhbmNlQgUAAAAMYW1vdW50VG9QYXlCCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABNrZXlTaGFyZUFzc2V0U3VwcGx5CQAAZQAAAAIFAAAAEHNoYXJlQXNzZXRTdXBwbHkFAAAACXBtdEFtb3VudAkABEwAAAACCQEAAAAEQnVybgAAAAIFAAAADHNoYXJlQXNzZXRJZAUAAAAJcG10QW1vdW50CQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAAMYW1vdW50VG9QYXlBBQAAAAhhc3NldElkQQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIFAAAADGFtb3VudFRvUGF5QgUAAAAIYXNzZXRJZEIFAAAAA25pbAAAAAFpAQAAAAhleGNoYW5nZQAAAAEAAAASbWluQW1vdW50VG9SZWNlaXZlBAAAAA0kdDAxOTM5NzE5NDcyCQAFFAAAAAIICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAABmFtb3VudAgJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAAAAAHYXNzZXRJZAQAAAAJcG10QW1vdW50CAUAAAANJHQwMTkzOTcxOTQ3MgAAAAJfMQQAAAAKcG10QXNzZXRJZAgFAAAADSR0MDE5Mzk3MTk0NzIAAAACXzIKAQAAAA1jYWxjdWxhdGVGZWVzAAAAAgAAAAl0b2tlbkZyb20AAAAHdG9rZW5UbwQAAAAQYW1vdW50V2l0aG91dEZlZQkAAGsAAAADBQAAAAd0b2tlblRvBQAAAAlwbXRBbW91bnQJAABkAAAAAgUAAAAJcG10QW1vdW50BQAAAAl0b2tlbkZyb20EAAAADWFtb3VudFdpdGhGZWUJAABrAAAAAwUAAAAQYW1vdW50V2l0aG91dEZlZQkAAGUAAAACBQAAABhjb21taXNzaW9uU2NhbGVEZWxpbWl0ZXIFAAAACmNvbW1pc3Npb24FAAAAGGNvbW1pc3Npb25TY2FsZURlbGltaXRlcgQAAAAQZ292ZXJuYW5jZVJld2FyZAkAAGsAAAADBQAAABBhbW91bnRXaXRob3V0RmVlBQAAABRjb21taXNzaW9uR292ZXJuYW5jZQUAAAAYY29tbWlzc2lvblNjYWxlRGVsaW1pdGVyAwkAAGYAAAACBQAAABJtaW5BbW91bnRUb1JlY2VpdmUFAAAADWFtb3VudFdpdGhGZWUJAAACAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAdQ2FsY3VsYXRlZCBhbW91bnQgdG8gcmVjZWl2ZSAJAAGkAAAAAQUAAAANYW1vdW50V2l0aEZlZQIAAAAgIGlzIGxlc3MgdGhhbiBzcGVjaWZpZWQgbWluaW11bSAJAAGkAAAAAQUAAAASbWluQW1vdW50VG9SZWNlaXZlCQAFFQAAAAMFAAAAEGFtb3VudFdpdGhvdXRGZWUFAAAADWFtb3VudFdpdGhGZWUFAAAAEGdvdmVybmFuY2VSZXdhcmQDCQEAAAABIQAAAAEFAAAACGlzQWN0aXZlCQAAAgAAAAECAAAAH0RBcHAgaXMgaW5hY3RpdmUgYXQgdGhpcyBtb21lbnQDAwkAAAAAAAACBQAAAAhiYWxhbmNlQQAAAAAAAAAAAAYJAAAAAAAAAgUAAAAIYmFsYW5jZUIAAAAAAAAAAAAJAAACAAAAAQIAAAAgQ2FuJ3QgZXhjaGFuZ2Ugd2l0aCB6ZXJvIGJhbGFuY2UDCQAAZwAAAAIAAAAAAAAAAAAFAAAAEm1pbkFtb3VudFRvUmVjZWl2ZQkAAAIAAAABCQABLAAAAAICAAAANE1pbmltYWwgYW1vdW50IHRvIHJlY2VpdmUgbXVzdCBiZSBwb3NpdGl2ZS4gQWN0dWFsOiAJAAGkAAAAAQUAAAASbWluQW1vdW50VG9SZWNlaXZlAwkBAAAAAiE9AAAAAgkAAZAAAAABCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAQkAAAIAAAABAgAAAB1PbmUgYXR0YWNoZWQgcGF5bWVudCBleHBlY3RlZAMJAQAAAAEhAAAAAQUAAAAQaGFzRW5vdWdoQmFsYW5jZQkABE4AAAACCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAAJcG10QW1vdW50BQAAAApwbXRBc3NldElkBQAAAANuaWwJAQAAABFzdXNwZW5kU3VzcGljaW91cwAAAAADCQAAAAAAAAIFAAAACnBtdEFzc2V0SWQFAAAACGFzc2V0SWRBBAAAAAthc3NldElkU2VuZAUAAAAIYXNzZXRJZEIEAAAADSR0MDIwNzQ2MjA4MzcJAQAAAA1jYWxjdWxhdGVGZWVzAAAAAgUAAAAIYmFsYW5jZUEFAAAACGJhbGFuY2VCBAAAABBhbW91bnRXaXRob3V0RmVlCAUAAAANJHQwMjA3NDYyMDgzNwAAAAJfMQQAAAANYW1vdW50V2l0aEZlZQgFAAAADSR0MDIwNzQ2MjA4MzcAAAACXzIEAAAAEGdvdmVybmFuY2VSZXdhcmQIBQAAAA0kdDAyMDc0NjIwODM3AAAAAl8zBAAAAAtuZXdCYWxhbmNlQQkAAGQAAAACBQAAAAhiYWxhbmNlQQUAAAAJcG10QW1vdW50BAAAAAtuZXdCYWxhbmNlQgkAAGUAAAACCQAAZQAAAAIFAAAACGJhbGFuY2VCBQAAAA1hbW91bnRXaXRoRmVlBQAAABBnb3Zlcm5hbmNlUmV3YXJkAwMJAABnAAAAAgUAAAANc3Rha2VkQW1vdW50QQUAAAALbmV3QmFsYW5jZUEGCQAAZwAAAAIFAAAADXN0YWtlZEFtb3VudEIFAAAAC25ld0JhbGFuY2VCCQEAAAAhdGhyb3dJbnN1ZmZpY2llbnRBdmFpbGFibGVCYWxhbmNlAAAAAwUAAAANYW1vdW50V2l0aEZlZQUAAAARYXZhaWxhYmxlQmFsYW5jZUIFAAAACmFzc2V0TmFtZUIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAC2tleUJhbGFuY2VBBQAAAAtuZXdCYWxhbmNlQQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAALa2V5QmFsYW5jZUIFAAAAC25ld0JhbGFuY2VCCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAANYW1vdW50V2l0aEZlZQUAAAALYXNzZXRJZFNlbmQJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwUAAAANd2FsbGV0QWRkcmVzcwUAAAAQZ292ZXJuYW5jZVJld2FyZAUAAAALYXNzZXRJZFNlbmQFAAAAA25pbAMJAAAAAAAAAgUAAAAKcG10QXNzZXRJZAUAAAAIYXNzZXRJZEIEAAAAC2Fzc2V0SWRTZW5kBQAAAAhhc3NldElkQQQAAAANJHQwMjE2NTYyMTc0NwkBAAAADWNhbGN1bGF0ZUZlZXMAAAACBQAAAAhiYWxhbmNlQgUAAAAIYmFsYW5jZUEEAAAAEGFtb3VudFdpdGhvdXRGZWUIBQAAAA0kdDAyMTY1NjIxNzQ3AAAAAl8xBAAAAA1hbW91bnRXaXRoRmVlCAUAAAANJHQwMjE2NTYyMTc0NwAAAAJfMgQAAAAQZ292ZXJuYW5jZVJld2FyZAgFAAAADSR0MDIxNjU2MjE3NDcAAAACXzMEAAAAC25ld0JhbGFuY2VBCQAAZQAAAAIJAABlAAAAAgUAAAAIYmFsYW5jZUEFAAAADWFtb3VudFdpdGhGZWUFAAAAEGdvdmVybmFuY2VSZXdhcmQEAAAAC25ld0JhbGFuY2VCCQAAZAAAAAIFAAAACGJhbGFuY2VCBQAAAAlwbXRBbW91bnQDAwkAAGcAAAACBQAAAA1zdGFrZWRBbW91bnRBBQAAAAtuZXdCYWxhbmNlQQYJAABnAAAAAgUAAAANc3Rha2VkQW1vdW50QgUAAAALbmV3QmFsYW5jZUIJAQAAACF0aHJvd0luc3VmZmljaWVudEF2YWlsYWJsZUJhbGFuY2UAAAADBQAAAA1hbW91bnRXaXRoRmVlBQAAABFhdmFpbGFibGVCYWxhbmNlQQUAAAAKYXNzZXROYW1lQQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAALa2V5QmFsYW5jZUEFAAAAC25ld0JhbGFuY2VBCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAtrZXlCYWxhbmNlQgUAAAALbmV3QmFsYW5jZUIJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAAA1hbW91bnRXaXRoRmVlBQAAAAthc3NldElkU2VuZAkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADBQAAAA13YWxsZXRBZGRyZXNzBQAAABBnb3Zlcm5hbmNlUmV3YXJkBQAAAAthc3NldElkU2VuZAUAAAADbmlsCQAAAgAAAAEJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAJEluY29ycmVjdCBhc3NldCBhdHRhY2hlZC4gRXhwZWN0ZWQ6IAUAAAALc3RyQXNzZXRJZEECAAAABCBvciAFAAAAC3N0ckFzc2V0SWRCAAAAAWkBAAAACHNodXRkb3duAAAAAAMJAQAAAAEhAAAAAQUAAAAIaXNBY3RpdmUJAAACAAAAAQkAASwAAAACAgAAACJEQXBwIGlzIGFscmVhZHkgc3VzcGVuZGVkLiBDYXVzZTogCQEAAAALdmFsdWVPckVsc2UAAAACCQAEHQAAAAIFAAAABHRoaXMFAAAACGtleUNhdXNlAgAAABp0aGUgY2F1c2Ugd2Fzbid0IHNwZWNpZmllZAMJAQAAAAEhAAAAAQkBAAAAD2NvbnRhaW5zRWxlbWVudAAAAAIJAARMAAAAAgUAAAAMYWRtaW5QdWJLZXkxCQAETAAAAAIFAAAADGFkbWluUHViS2V5MgkABEwAAAACBQAAAAxhZG1pblB1YktleTMJAARMAAAAAgUAAAAUYWRtaW5QdWJLZXlTdGFydFN0b3AFAAAAA25pbAgFAAAAAWkAAAAPY2FsbGVyUHVibGljS2V5CQAAAgAAAAECAAAAIU9ubHkgYWRtaW4gY2FuIGNhbGwgdGhpcyBmdW5jdGlvbgkBAAAAB3N1c3BlbmQAAAABAgAAAA9QYXVzZWQgYnkgYWRtaW4AAAABaQEAAAAIYWN0aXZhdGUAAAAAAwUAAAAIaXNBY3RpdmUJAAACAAAAAQIAAAAWREFwcCBpcyBhbHJlYWR5IGFjdGl2ZQMJAQAAAAEhAAAAAQkBAAAAD2NvbnRhaW5zRWxlbWVudAAAAAIJAARMAAAAAgUAAAAMYWRtaW5QdWJLZXkxCQAETAAAAAIFAAAADGFkbWluUHViS2V5MgkABEwAAAACBQAAAAxhZG1pblB1YktleTMJAARMAAAAAgUAAAAUYWRtaW5QdWJLZXlTdGFydFN0b3AFAAAAA25pbAgFAAAAAWkAAAAPY2FsbGVyUHVibGljS2V5CQAAAgAAAAECAAAAIU9ubHkgYWRtaW4gY2FuIGNhbGwgdGhpcyBmdW5jdGlvbgkABEwAAAACCQEAAAAMQm9vbGVhbkVudHJ5AAAAAgUAAAAJa2V5QWN0aXZlBgkABEwAAAACCQEAAAALRGVsZXRlRW50cnkAAAABBQAAAAhrZXlDYXVzZQUAAAADbmlsAAAAAWkBAAAAGXRha2VJbnRvQWNjb3VudEV4dHJhRnVuZHMAAAABAAAAC2Ftb3VudExlYXZlBAAAAB11bmNvdW50YWJsZUFtb3VudEVucm9sbEFzc2V0QQkAAGUAAAACBQAAABlhY2NvdW50QmFsYW5jZVdpdGhTdGFrZWRBBQAAAAhiYWxhbmNlQQQAAAAddW5jb3VudGFibGVBbW91bnRFbnJvbGxBc3NldEIJAABlAAAAAgUAAAAZYWNjb3VudEJhbGFuY2VXaXRoU3Rha2VkQgUAAAAIYmFsYW5jZUIEAAAADWFtb3VudEVucm9sbEEJAABlAAAAAgUAAAAddW5jb3VudGFibGVBbW91bnRFbnJvbGxBc3NldEEDCQAAAAAAAAIFAAAACGFzc2V0SWRBBQAAAAR1bml0BQAAAAthbW91bnRMZWF2ZQAAAAAAAAAAAAQAAAANYW1vdW50RW5yb2xsQgkAAGUAAAACBQAAAB11bmNvdW50YWJsZUFtb3VudEVucm9sbEFzc2V0QgMJAAAAAAAAAgUAAAAIYXNzZXRJZEIFAAAABHVuaXQFAAAAC2Ftb3VudExlYXZlAAAAAAAAAAAAAwkBAAAAASEAAAABBQAAAAhpc0FjdGl2ZQkAAAIA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", "height": 1636277, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 8nSvALjAeerJSWM76g7WRyNctWV5rmMzxBqXkeTiXxei Next: none Diff:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let keyShareTokensLocked = "_total_share_tokens_locked"
4+let version = "1.0.0"
55
6-let kShareLimit = "share_limit_on_first_harvest"
6+let keyVersion = "version"
77
88 let keyActive = "active"
9-
10-let keyCause = "shutdown_cause"
11-
12-let keyRewardPoolFractionCurrent = "_current_pool_fraction_reward"
13-
14-let keyRewardPoolFractionPrevious = "_previous_pool_fraction_reward"
15-
16-let keyHeightPoolFraction = "_pool_reward_update_height"
17-
18-let keyTotalRewardPerBlockCurrent = "total_reward_per_block_current"
19-
20-let keyTotalRewardPerBlockPrevious = "total_reward_per_block_previous"
21-
22-let keyRewardUpdateHeight = "reward_update_height"
23-
24-let keyLastInterest = "_last_interest"
25-
26-let keyLastInterestHeight = "_last_interest_height"
27-
28-let keyUserShareTokensLocked = "_share_tokens_locked"
29-
30-let keyUserLastInterest = "_last_interest"
31-
32-let keySWOPid = "SWOP_id"
33-
34-let keyUserSWOPClaimedAmount = "_SWOP_claimed_amount"
35-
36-let keyUserSWOPLastClaimedAmount = "_SWOP_last_claimed_amount"
37-
38-let keyAvailableSWOP = "_available_SWOP"
39-
40-let keyFarmingStartHeight = "farming_start_height"
41-
42-let keyAPY = "apy"
43-
44-let kPreviousTotalVoteSWOP = "previous_total_vote_SWOP"
45-
46-let keySwopYearEmission = "swop_year_emission"
47-
48-let keyBalancecpmmA = "A_asset_balance"
49-
50-let keyBalancecpmmB = "B_asset_balance"
51-
52-let kHarvestPoolActiveVoteStrucVoting = "_harvest_pool_activeVote_struc"
53-
54-let kHarvestUserPoolActiveVoteStrucVoting = "_harvest_user_pool_activeVote_struc"
55-
56-let keyLimitShareFirstHarvest = "share_limit_on_first_harvest"
579
5810 let keyAssetIdA = "A_asset_id"
5911
6012 let keyAssetIdB = "B_asset_id"
6113
14+let keyBalanceA = "A_asset_balance"
15+
16+let keyBalanceB = "B_asset_balance"
17+
18+let keyBalanceInitA = "A_asset_init"
19+
20+let keyBalanceInitB = "B_asset_init"
21+
22+let keyShareAssetId = "share_asset_id"
23+
24+let keyShareAssetSupply = "share_asset_supply"
25+
26+let keyCommission = "commission"
27+
28+let keyCommissionScaleDelimiter = "commission_scale_delimiter"
29+
30+let keyCause = "shutdown_cause"
31+
32+let keyFirstHarvest = "first_harvest"
33+
6234 let keyFirstHarvestHeight = "first_harvest_height"
6335
64-let keyfirstHarvestCpmm = "first_harvest"
36+let kShareLimit = "share_limit_on_first_harvest"
6537
66-let keyTempPrevSum = "sum_reward_previous"
38+let kBasePeriod = "base_period"
6739
68-let keyTempCurSum = "sum_reward_current"
40+let kPeriodLength = "period_length"
6941
70-let governanceAddress = Address(base58'3N5W8da2iiijVieA6qLGo7KzCJj8B19smWU')
42+let kStartHeight = "start_height"
7143
72-let wallet = Address(base58'3NAGTtZz6WpupSN89NZD5rMZwwziZEg4Kx4')
73-
74-let votingAddress = Address(base58'3MrJgdL1GniipErHy44YF9idzLaUL2iX5DQ')
75-
76-let adminIncreaseInterestAddress = Address(base58'3NAGTtZz6WpupSN89NZD5rMZwwziZEg4Kx4')
77-
78-let oneWeekInBlock = 10106
79-
80-let totalVoteShare = 10000000000
81-
82-let scaleValue1 = 10
83-
84-let scaleValue3 = 1000
85-
86-let scaleValue5 = 100000
87-
88-let scaleValue6 = 1000000
89-
90-let scaleValue8 = 100000000
91-
92-let scaleValue11 = 100000000000
44+let kFirstHarvestHeight = "first_harvest_height"
9345
9446 let keyAdminPubKey1 = "admin_pub_1"
9547
11365
11466 let adminPubKey3 = getAdminPub(keyAdminPubKey3)
11567
116-func strAssetIdA (pool) = getStringValue(pool, keyAssetIdA)
68+let adminPubKeyStartStop = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
11769
70+let adminPubKeyStaking = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
11871
119-func strAssetIdB (pool) = getStringValue(pool, keyAssetIdB)
72+let walletAddress = Address(base58'3NAGTtZz6WpupSN89NZD5rMZwwziZEg4Kx4')
12073
74+let votingAddress = Address(base58'3MrJgdL1GniipErHy44YF9idzLaUL2iX5DQ')
12175
122-func assetIdA (pool) = if ((strAssetIdA(pool) == "WAVES"))
123- then unit
124- else fromBase58String(strAssetIdA(pool))
76+let USDN = base58'8UrfDVd5GreeUwm7uPk7eYz1eMv376kzR52C6sANPkwS'
12577
78+let NSBT = base58'36mg8NZTaFRDygiVwb8uBnLR51hetJruUCZcxhaVcHj9'
12679
127-func assetIdB (pool) = if ((strAssetIdB(pool) == "WAVES"))
128- then unit
129- else fromBase58String(strAssetIdB(pool))
80+let SWOP = base58'2HAJrwa8q4SxBx9cHYaBTQdBjdk5wwqdof7ccpAx2uhZ'
13081
82+let EURN = base58'ECBCkHS68DckpBrzLeoRgYbFg7sCVqR176mPqbXsj9pA'
13183
132-let kBasePeriod = "base_period"
84+let stakingUSDNNSBTAddress = Address(base58'3N6q7sCGSSLBUXDdjBdYGTJbZGZfhhh8cNg')
13385
134-let kPeriodLength = "period_length"
86+let stakingEURNAddress = Address(base58'3MyVqAbmKWh339gF6hy8faWw1jGeTV2wnGE')
13587
136-let kStartHeight = "start_height"
88+let USDNToWavesExchanger = Address(base58'3N77kfPbQyjXWpDALX3xjKw3iEGMWEctV37')
13789
138-let kFirstHarvestHeight = "first_harvest_height"
90+let USDNToNSBTExchanger = Address(base58'3Mye9wVR7d2mc6Y5ZJTu11svzgUQ7o8H9dA')
13991
140-let kDurationFullVotePower = "duration_full_vote_power"
92+let stakingFeeInUSDN = 270000
14193
142-let kMinVotePower = "min_vote_power"
94+let stakingFeeInEURN = 234000
14395
14496 let basePeriod = valueOrErrorMessage(getInteger(votingAddress, kBasePeriod), "Empty kBasePeriod")
14597
14799
148100 let periodLength = valueOrErrorMessage(getInteger(votingAddress, kPeriodLength), "Empty kPeriodLength")
149101
150-let durationFullVotePower = valueOrErrorMessage(getInteger(votingAddress, kDurationFullVotePower), "Empty kDurationFullVotePower")
151-
152-let minVotePower = valueOrErrorMessage(getInteger(votingAddress, kMinVotePower), "Empty kMinVotePower")
102+let firstHarvestEndPeriod = ((basePeriod + ((height - startHeight) / periodLength)) + 3)
153103
154104 let isActive = getBooleanValue(this, keyActive)
155105
156-let currPeriod = (basePeriod + ((height - startHeight) / periodLength))
106+let strAssetIdA = getStringValue(this, keyAssetIdA)
157107
158-func getLimitToken (pool) = valueOrElse(getIntegerValue(pool, keyLimitShareFirstHarvest), 0)
108+let strAssetIdB = getStringValue(this, keyAssetIdB)
159109
110+let assetIdA = if ((strAssetIdA == "WAVES"))
111+ then unit
112+ else fromBase58String(strAssetIdA)
160113
161-let APY = getIntegerValue(this, keyAPY)
114+let assetIdB = if ((strAssetIdB == "WAVES"))
115+ then unit
116+ else fromBase58String(strAssetIdB)
162117
163-let SwopYearEmission = getIntegerValue(this, keySwopYearEmission)
164-
165-func assetNameA (pool) = match assetIdA(pool) {
118+let assetNameA = match assetIdA {
166119 case id: ByteVector =>
167120 value(assetInfo(id)).name
168121 case waves: Unit =>
171124 throw("Match error")
172125 }
173126
174-
175-func assetNameB (pool) = match assetIdB(pool) {
127+let assetNameB = match assetIdB {
176128 case id: ByteVector =>
177129 value(assetInfo(id)).name
178130 case waves: Unit =>
181133 throw("Match error")
182134 }
183135
136+let balanceA = getIntegerValue(this, keyBalanceA)
184137
185-let SWOP = fromBase58String(getStringValue(this, keySWOPid))
138+let balanceB = getIntegerValue(this, keyBalanceB)
186139
187-func isFirstHarvest (pool) = valueOrElse(getBoolean(pool, keyfirstHarvestCpmm), false)
140+let shareAssetId = fromBase58String(getStringValue(this, keyShareAssetId))
188141
142+let shareAssetSupply = getIntegerValue(this, keyShareAssetSupply)
189143
190-func getHeightFirstHarvest (pool) = valueOrElse(getInteger(pool, keyFirstHarvestHeight), 0)
144+let commission = 3000
191145
146+let commissionGovernance = 1200
192147
193-func getBalanceA (pool) = valueOrErrorMessage(getInteger(pool, keyBalancecpmmA), ("No data on the key: " + keyBalancecpmmA))
148+let commissionScaleDelimiter = 1000000
194149
150+let scaleValue3 = 1000
195151
196-func getBalanceB (pool) = valueOrErrorMessage(getInteger(pool, keyBalancecpmmB), ("No data on the key: " + keyBalancecpmmB))
152+let scaleValue8 = 100000000
197153
154+let slippageToleranceDelimiter = 1000
198155
199-func getShareLimitToken (pool) = valueOrErrorMessage(getInteger(pool, kShareLimit), ("No data on the key: " + kShareLimit))
200-
201-
202-func getTotalShareTokenLocked (pool) = valueOrErrorMessage(getInteger(this, (pool + keyShareTokensLocked)), (("No data on the key: " + pool) + keyShareTokensLocked))
203-
204-
205-func getShareAssetId (pool) = fromBase58String(getStringValue(value(addressFromString(pool)), "share_asset_id"))
206-
156+let scaleValue8Digits = 8
207157
208158 func accountBalance (assetId) = match assetId {
209159 case id: ByteVector =>
214164 throw("Match error")
215165 }
216166
167+
168+func stakedAmount (assetId) = {
169+ let stakedAmountCalculated = match assetId {
170+ case aId: ByteVector =>
171+ if (if ((aId == USDN))
172+ then true
173+ else (aId == NSBT))
174+ then getInteger(stakingUSDNNSBTAddress, ((("rpd_balance_" + toBase58String(aId)) + "_") + toString(this)))
175+ else if ((aId == EURN))
176+ then getInteger(stakingEURNAddress, ((("%s%s%s__stakingBalance__" + toBase58String(aId)) + "__") + toString(this)))
177+ else 0
178+ case _: Unit =>
179+ 0
180+ case _ =>
181+ throw("Match error")
182+ }
183+ match stakedAmountCalculated {
184+ case i: Int =>
185+ i
186+ case _ =>
187+ 0
188+ }
189+ }
190+
191+
192+let stakedAmountA = stakedAmount(assetIdA)
193+
194+let stakedAmountB = stakedAmount(assetIdB)
195+
196+let assetInitA = getIntegerValue(this, keyBalanceInitA)
197+
198+let assetInitB = getIntegerValue(this, keyBalanceInitB)
199+
200+let availableBalanceA = (balanceA - stakedAmountA)
201+
202+let availableBalanceB = (balanceB - stakedAmountB)
203+
204+let accountBalanceWithStakedA = (accountBalance(assetIdA) + stakedAmountA)
205+
206+let accountBalanceWithStakedB = (accountBalance(assetIdB) + stakedAmountB)
207+
208+let hasEnoughBalance = if ((accountBalanceWithStakedA >= balanceA))
209+ then (accountBalanceWithStakedB >= balanceB)
210+ else false
217211
218212 func getAssetInfo (assetId) = match assetId {
219213 case id: ByteVector =>
227221 }
228222
229223
230-func calcScaleValue (assetId1,assetId2) = {
231- let assetId1Decimals = value(assetInfo(assetId1)).decimals
232- let assetId2Decimals = value(assetInfo(assetId2)).decimals
233- let scaleDigits = ((assetId2Decimals - assetId1Decimals) + 8)
234- pow(10, 0, scaleDigits, 0, 0, DOWN)
235- }
236-
237-
238-func userAvailableSWOP (pool,user) = valueOrElse(getInteger(this, (((pool + "_") + toString(user)) + keyAvailableSWOP)), 0)
239-
240-
241-func rewardInfo (pool) = {
242- let totalRewardPerBlockCurrent = valueOrErrorMessage(getInteger(governanceAddress, keyTotalRewardPerBlockCurrent), ((("No data on the key: " + keyTotalRewardPerBlockCurrent) + " at address ") + toString(governanceAddress)))
243- let totalRewardPerBlockPrevious = valueOrErrorMessage(getInteger(governanceAddress, keyTotalRewardPerBlockPrevious), ((("No data on the key: " + keyTotalRewardPerBlockPrevious) + " at address ") + toString(governanceAddress)))
244- let rewardPoolFractionCurrent = valueOrErrorMessage(getInteger(governanceAddress, (pool + keyRewardPoolFractionCurrent)), (((("No data on the key: " + pool) + keyRewardPoolFractionCurrent) + " at address ") + toString(governanceAddress)))
245- let rewardUpdateHeight = valueOrErrorMessage(getInteger(governanceAddress, keyRewardUpdateHeight), ((("No data on the key: " + keyRewardUpdateHeight) + " at address ") + toString(governanceAddress)))
246- let poolRewardUpdateHeight = valueOrElse(getInteger(governanceAddress, (pool + keyHeightPoolFraction)), 0)
247- let rewardPoolFractionPrevious = valueOrErrorMessage(getInteger(governanceAddress, (pool + keyRewardPoolFractionPrevious)), (((("No data on the key: " + pool) + keyRewardPoolFractionPrevious) + " at address ") + toString(governanceAddress)))
248- let rewardPoolCurrent = fraction(totalRewardPerBlockCurrent, rewardPoolFractionCurrent, totalVoteShare)
249- let rewardPoolPrevious = fraction(totalRewardPerBlockPrevious, rewardPoolFractionPrevious, totalVoteShare)
250- if (if ((rewardPoolCurrent > totalRewardPerBlockCurrent))
251- then true
252- else (rewardPoolPrevious > totalRewardPerBlockPrevious))
253- then throw("rewardPoolCurrent > totalRewardPerBlockCurrent or rewardPoolPrevious > totalRewardPerBlockPrevious")
254- else $Tuple4(rewardPoolCurrent, rewardUpdateHeight, rewardPoolPrevious, poolRewardUpdateHeight)
255- }
256-
257-
258-func getLastInterestInfo (pool) = {
259- let lastInterest = valueOrErrorMessage(getInteger(this, (pool + keyLastInterest)), (("No data on the key: " + pool) + keyLastInterest))
260- let lastInterestHeight = valueOrElse(getInteger(this, (pool + keyLastInterestHeight)), height)
261- $Tuple2(lastInterestHeight, lastInterest)
262- }
263-
264-
265-func getUserInterestInfo (pool,userAddress) = {
266- let userLastInterest = getInteger(this, (((pool + "_") + toString(userAddress)) + keyUserLastInterest))
267- let userShare = getInteger(this, (((pool + "_") + toString(userAddress)) + keyUserShareTokensLocked))
268- let lastInterest = valueOrErrorMessage(getInteger(this, (pool + keyLastInterest)), (("No data on the key: " + pool) + keyLastInterest))
269- let userLastInterestValue = match userLastInterest {
270- case userLastInterest: Int =>
271- userLastInterest
272- case _ =>
273- lastInterest
274- }
275- let userShareTokensAmount = match userShare {
276- case userShare: Int =>
277- userShare
278- case _ =>
279- 0
280- }
281- $Tuple2(userLastInterestValue, userShareTokensAmount)
282- }
283-
284-
285-func calcInterest (lastInterestHeight,rewardUpdateHeight,poolRewardUpdateHeight,lastInterest,currentRewardPerBlock,shareTokenLocked,previousRewardPerBlock,shareAssetId,scaleValue,pmtAmount) = if ((shareTokenLocked == 0))
286- then 0
287- else if ((poolRewardUpdateHeight != 0))
288- then if (if ((rewardUpdateHeight > height))
289- then (rewardUpdateHeight == poolRewardUpdateHeight)
290- else false)
291- then {
292- let reward = (previousRewardPerBlock * (height - lastInterestHeight))
293- (lastInterest + fraction(reward, scaleValue, shareTokenLocked))
294- }
295- else if (if ((height > rewardUpdateHeight))
296- then (rewardUpdateHeight != poolRewardUpdateHeight)
297- else false)
298- then {
299- let reward = (previousRewardPerBlock * (height - lastInterestHeight))
300- (lastInterest + fraction(reward, scaleValue, shareTokenLocked))
301- }
302- else if (if (if ((height > rewardUpdateHeight))
303- then (rewardUpdateHeight == poolRewardUpdateHeight)
304- else false)
305- then (lastInterestHeight > rewardUpdateHeight)
306- else false)
307- then {
308- let reward = (currentRewardPerBlock * (height - lastInterestHeight))
309- (lastInterest + fraction(reward, scaleValue, shareTokenLocked))
310- }
311- else {
312- let rewardAfterLastInterestBeforeReawardUpdate = (previousRewardPerBlock * (rewardUpdateHeight - lastInterestHeight))
313- let interestAfterUpdate = (lastInterest + fraction(rewardAfterLastInterestBeforeReawardUpdate, scaleValue, shareTokenLocked))
314- let reward = (currentRewardPerBlock * (height - rewardUpdateHeight))
315- (interestAfterUpdate + fraction(reward, scaleValue, shareTokenLocked))
316- }
317- else if ((rewardUpdateHeight > height))
318- then {
319- let reward = (previousRewardPerBlock * (height - lastInterestHeight))
320- (lastInterest + fraction(reward, scaleValue, shareTokenLocked))
321- }
322- else if ((lastInterestHeight > rewardUpdateHeight))
323- then {
324- let reward = (currentRewardPerBlock * (height - rewardUpdateHeight))
325- (lastInterest + fraction(reward, scaleValue, shareTokenLocked))
326- }
327- else {
328- let rewardAfterLastInterestBeforeReawardUpdate = (previousRewardPerBlock * (rewardUpdateHeight - lastInterestHeight))
329- let interestAfterUpdate = (lastInterest + fraction(rewardAfterLastInterestBeforeReawardUpdate, scaleValue, shareTokenLocked))
330- let reward = (currentRewardPerBlock * (height - rewardUpdateHeight))
331- (interestAfterUpdate + fraction(reward, scaleValue, shareTokenLocked))
332- }
333-
334-
335-func claimCalc (pool,caller,pmtAmount) = {
336- let shareAssetId = getShareAssetId(pool)
337- let scaleValue = calcScaleValue(SWOP, shareAssetId)
338- let shareTokenLocked = getTotalShareTokenLocked(pool)
339- let $t01344513510 = getLastInterestInfo(pool)
340- let lastInterestHeight = $t01344513510._1
341- let lastInterest = $t01344513510._2
342- let $t01351513627 = rewardInfo(pool)
343- let currentRewardPerBlock = $t01351513627._1
344- let rewardUpdateHeight = $t01351513627._2
345- let previousRewardPerBlock = $t01351513627._3
346- let poolRewardUpdateHeight = $t01351513627._4
347- let $t01363213711 = getUserInterestInfo(pool, caller)
348- let userLastInterest = $t01363213711._1
349- let userShareTokensAmount = $t01363213711._2
350- let currentInterest = calcInterest(lastInterestHeight, rewardUpdateHeight, poolRewardUpdateHeight, lastInterest, currentRewardPerBlock, shareTokenLocked, previousRewardPerBlock, shareAssetId, scaleValue, pmtAmount)
351- let claimAmount = fraction(userShareTokensAmount, (currentInterest - userLastInterest), scaleValue)
352- let userNewInterest = currentInterest
353- $Tuple4(userNewInterest, currentInterest, claimAmount, userShareTokensAmount)
354- }
355-
356-
357-func calculateProtocolReward (pool) = {
358- let $t01423114296 = getLastInterestInfo(pool)
359- let lastInterestHeight = $t01423114296._1
360- let lastInterest = $t01423114296._2
361- let $t01430114412 = rewardInfo(pool)
362- let currentRewardPerBlock = $t01430114412._1
363- let rewardUpdateHeight = $t01430114412._2
364- let previousRewardPerBlock = $t01430114412._3
365- let poolRewardUpdateHeight = $t01430114412._4
366- let shareTokenLocked = getTotalShareTokenLocked(pool)
367- if (if ((shareTokenLocked == 0))
368- then (poolRewardUpdateHeight == 0)
369- else false)
370- then if ((rewardUpdateHeight > height))
371- then {
372- let reward = (previousRewardPerBlock * (height - lastInterestHeight))
373- reward
374- }
375- else if ((lastInterestHeight > rewardUpdateHeight))
376- then {
377- let reward = (currentRewardPerBlock * (height - lastInterestHeight))
378- reward
379- }
380- else {
381- let rewardAfterLastInterestBeforeReawardUpdate = (previousRewardPerBlock * (rewardUpdateHeight - lastInterestHeight))
382- let reward = (currentRewardPerBlock * (height - rewardUpdateHeight))
383- (reward + rewardAfterLastInterestBeforeReawardUpdate)
384- }
385- else if (if ((shareTokenLocked == 0))
386- then (poolRewardUpdateHeight != 0)
387- else false)
388- then if (if ((rewardUpdateHeight > height))
389- then (rewardUpdateHeight == poolRewardUpdateHeight)
390- else false)
391- then {
392- let reward = (previousRewardPerBlock * (height - lastInterestHeight))
393- reward
394- }
395- else if (if ((height > rewardUpdateHeight))
396- then (rewardUpdateHeight != poolRewardUpdateHeight)
397- else false)
398- then {
399- let reward = (previousRewardPerBlock * (height - lastInterestHeight))
400- reward
401- }
402- else if (if (if ((height > rewardUpdateHeight))
403- then (rewardUpdateHeight == poolRewardUpdateHeight)
404- else false)
405- then (lastInterestHeight > rewardUpdateHeight)
406- else false)
407- then {
408- let reward = (currentRewardPerBlock * (height - lastInterestHeight))
409- reward
410- }
411- else {
412- let rewardAfterLastInterestBeforeReawardUpdate = (previousRewardPerBlock * (rewardUpdateHeight - lastInterestHeight))
413- let reward = (currentRewardPerBlock * (height - rewardUpdateHeight))
414- (reward + rewardAfterLastInterestBeforeReawardUpdate)
415- }
416- else 0
417- }
418-
419-
420-func checkPmtAssetIdCorrect (pool,pmtAssetId) = {
421- let poolShareAssetId = fromBase58String(getStringValue(value(addressFromString(pool)), "share_asset_id"))
422- if ((pmtAssetId == poolShareAssetId))
423- then true
424- else false
425- }
426-
427-
428-func getUserSWOPClaimedAmount (pool,user) = valueOrElse(getInteger(this, (((pool + "_") + toString(user)) + keyUserSWOPClaimedAmount)), 0)
224+func getAssetInfoFromString (assetStr) = if ((assetStr == "WAVES"))
225+ then $Tuple3("WAVES", "WAVES", 8)
226+ else {
227+ let stringId = assetStr
228+ let id = fromBase58String(assetStr)
229+ let info = valueOrErrorMessage(assetInfo(id), (("Asset " + stringId) + " doesn't exist"))
230+ $Tuple3(stringId, info.name, info.decimals)
231+ }
429232
430233
431234 func suspend (cause) = [BooleanEntry(keyActive, false), StringEntry(keyCause, cause)]
432235
433236
434-@Callable(i)
435-func init (earlyLP) = if (isDefined(getString(this, keySWOPid)))
436- then throw("SWOP already initialized")
437- else {
438- let initAmount = 100000000000000
439- let SWOPissue = Issue("SWOP", "SWOP protocol token", initAmount, 8, true)
440- let SWOPid = calculateAssetId(SWOPissue)
441-[BooleanEntry(keyActive, true), Issue("SWOP", "SWOP protocol token", initAmount, 8, true), StringEntry(keySWOPid, toBase58String(SWOPid))]
237+func deductStakingFee (amount,assetId,secondAssetId) = if (if ((assetId == USDN))
238+ then true
239+ else (assetId == EURN))
240+ then {
241+ let stakinFee = if ((assetId == USDN))
242+ then (stakingFeeInUSDN * (if ((secondAssetId == NSBT))
243+ then 2
244+ else 1))
245+ else if ((assetId == EURN))
246+ then stakingFeeInEURN
247+ else 0
248+ let result = (amount - stakinFee)
249+ if ((0 >= result))
250+ then throw((((("Insufficient amount " + toString(amount)) + " to deduct staking fee ") + toString(stakinFee)) + "USDN/EURN"))
251+ else result
442252 }
253+ else amount
443254
255+
256+func getStakingFee (assetId,secondAssetId) = if ((assetId == USDN))
257+ then (stakingFeeInUSDN * (if ((secondAssetId == NSBT))
258+ then 2
259+ else 1))
260+ else if ((assetId == EURN))
261+ then stakingFeeInEURN
262+ else 0
263+
264+
265+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"))
266+
267+
268+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"))
269+
270+
271+func suspendSuspicious () = suspend(((((((((((((((("Suspicious state. Actual balances: " + toString(accountBalanceWithStakedA)) + " ") + assetNameA) + ", ") + toString(accountBalanceWithStakedB)) + " ") + assetNameB) + ". State: ") + toString(balanceA)) + " ") + assetNameA) + ", ") + toString(balanceB)) + " ") + assetNameB))
444272
445273
446274 @Callable(i)
447-func initPoolShareFarming (pool) = if ((i.caller != this))
448- then throw("Only the DApp itself can call this function")
449- else {
450- let $t01739417497 = rewardInfo(pool)
451- let currentReward = $t01739417497._1
452- let rewardUpdateHeight = $t01739417497._2
453- let previousRewardPerBlock = $t01739417497._3
454- let poolRewardUpdateHeight = $t01739417497._4
455-[IntegerEntry((pool + keyShareTokensLocked), 0), IntegerEntry((pool + keyLastInterest), 0), IntegerEntry((pool + keyLastInterestHeight), height)]
456- }
457-
458-
459-
460-@Callable(i)
461-func updatePoolInterest (pool) = if ((i.caller != wallet))
462- then throw("Only the Admin itself can call this function")
463- else if (!(isActive))
464- then throw("DApp is inactive at this moment")
465- else {
466- let $t01790618026 = claimCalc(pool, adminIncreaseInterestAddress, 0)
467- let userNewInterest = $t01790618026._1
468- let currentInterest = $t01790618026._2
469- let claimAmount = $t01790618026._3
470- let userShareTokensAmount = $t01790618026._4
471- let $t01803118134 = rewardInfo(pool)
472- let currentReward = $t01803118134._1
473- let rewardUpdateHeight = $t01803118134._2
474- let previousRewardPerBlock = $t01803118134._3
475- let poolRewardUpdateHeight = $t01803118134._4
476-[IntegerEntry((pool + keyLastInterest), userNewInterest), IntegerEntry((pool + keyLastInterestHeight), height)]
477- }
478-
479-
480-
481-@Callable(i)
482-func lockShareTokens (pool) = {
483- let $t01832618401 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
484- let pmtAmount = $t01832618401._1
485- let pmtAssetId = $t01832618401._2
486- let $t01840618479 = getAssetInfo(pmtAssetId)
487- let pmtStrAssetId = $t01840618479._1
488- let pmtAssetName = $t01840618479._2
489- let pmtDecimals = $t01840618479._3
490- let $t01848418592 = claimCalc(pool, i.caller, pmtAmount)
491- let userNewInterest = $t01848418592._1
492- let currentInterest = $t01848418592._2
493- let claimAmount = $t01848418592._3
494- let userShareTokensAmount = $t01848418592._4
495- let userShareAmountNew = (userShareTokensAmount + pmtAmount)
496- let availableFundsNew = (userAvailableSWOP(pool, i.caller) + claimAmount)
497- let totalShareAmount = getTotalShareTokenLocked(pool)
498- let totalShareAmountNew = (totalShareAmount + pmtAmount)
499- let userClaimedAmount = getUserSWOPClaimedAmount(pool, i.caller)
500- let userClaimedAmountNew = (userClaimedAmount + claimAmount)
501- let baseEntry = [IntegerEntry((((pool + "_") + toString(i.caller)) + keyUserLastInterest), userNewInterest), IntegerEntry((((pool + "_") + toString(i.caller)) + keyUserShareTokensLocked), userShareAmountNew), IntegerEntry((pool + keyShareTokensLocked), totalShareAmountNew), IntegerEntry((pool + keyLastInterest), currentInterest), IntegerEntry((pool + keyLastInterestHeight), height), IntegerEntry((((pool + "_") + toString(i.caller)) + keyUserSWOPClaimedAmount), userClaimedAmountNew), IntegerEntry((((pool + "_") + toString(i.caller)) + keyUserSWOPLastClaimedAmount), claimAmount), IntegerEntry((((pool + "_") + toString(i.caller)) + keyAvailableSWOP), availableFundsNew)]
502- if ((0 >= pmtAmount))
503- then throw("You can't lock token")
504- else if (!(isActive))
505- then throw("DApp is inactive at this moment")
506- else if (!(checkPmtAssetIdCorrect(pool, pmtAssetId)))
507- then throw("Incorrect pmtAssetId")
508- else if (if (isFirstHarvest(Address(fromBase58String(pool))))
509- then (getHeightFirstHarvest(Address(fromBase58String(pool))) > height)
510- else false)
511- then {
512- let harvestPeriod = ((((getHeightFirstHarvest(Address(fromBase58String(pool))) - startHeight) + 1) / periodLength) - 1)
513- let amountOfVoting = split(getStringValue(votingAddress, (((toString(i.caller) + "_") + pool) + "_user_pool_struc")), "_")
514- let amountPoolStract = split(getStringValue(votingAddress, (pool + "_pool_struc")), "_")
515- let amountActiveVoteUserPoolStract = split(valueOrElse(getString(votingAddress, (((toString(i.caller) + "_") + pool) + kHarvestUserPoolActiveVoteStrucVoting)), ""), "_")
516- let amountPoolActiveVoteStract = split(valueOrElse(getString(votingAddress, (pool + kHarvestPoolActiveVoteStrucVoting)), ""), "_")
517- let userShareTokenLocked = userShareTokensAmount
518- let userPoolActiveVote = if ((toString(currPeriod) == amountOfVoting[2]))
519- then valueOrElse(parseInt(amountActiveVoteUserPoolStract[0]), 0)
520- else valueOrElse(parseInt(amountOfVoting[1]), 0)
521- let poolActiveVote = if ((toString(currPeriod) == amountPoolStract[2]))
522- then valueOrElse(parseInt(amountPoolActiveVoteStract[0]), 0)
523- else valueOrElse(parseInt(amountPoolStract[1]), 0)
524- let protocolReward = calculateProtocolReward(pool)
525- if ((userPoolActiveVote != 0))
526- then {
527- let limitShareToken = getShareLimitToken(addressFromStringValue(pool))
528- let shareToken = (fraction(limitShareToken, userPoolActiveVote, poolActiveVote) - userShareTokenLocked)
529- if (if ((size(amountActiveVoteUserPoolStract) > 1))
530- then (valueOrElse(parseInt(amountActiveVoteUserPoolStract[1]), 0) >= harvestPeriod)
531- else false)
532- then throw("You can't share token")
533- else if ((pmtAmount > limitShareToken))
534- then throw(("You can't share token more than " + toString(limitShareToken)))
535- else if ((shareToken > 0))
536- then if ((fraction(99, (accountBalance(pmtAssetId) + pmtAmount), 100) > totalShareAmountNew))
537- then throw("Balance of share-token is greater than totalAmount")
538- else if (if ((totalShareAmount == 0))
539- then (shareToken >= pmtAmount)
540- else false)
541- then (baseEntry ++ [ScriptTransfer(wallet, protocolReward, SWOP)])
542- else if ((shareToken >= pmtAmount))
543- then baseEntry
544- else throw(("Your maximum share token is " + toString(shareToken)))
545- else throw("You can't share token")
546- }
547- else throw("Your amount of token less than 0")
548- }
549- else baseEntry
275+func init (firstHarvest) = {
276+ let $t080018078 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
277+ let pmtAmountA = $t080018078._1
278+ let pmtAssetIdA = $t080018078._2
279+ let $t080838160 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
280+ let pmtAmountB = $t080838160._1
281+ let pmtAssetIdB = $t080838160._2
282+ let $t081658242 = getAssetInfo(pmtAssetIdA)
283+ let pmtStrAssetIdA = $t081658242._1
284+ let pmtAssetNameA = $t081658242._2
285+ let pmtDecimalsA = $t081658242._3
286+ let $t082478324 = getAssetInfo(pmtAssetIdB)
287+ let pmtStrAssetIdB = $t082478324._1
288+ let pmtAssetNameB = $t082478324._2
289+ let pmtDecimalsB = $t082478324._3
290+ if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
291+ then throw("Only admin can call this function")
292+ else if (isDefined(getBoolean(this, keyActive)))
293+ then throw("DApp is already active")
294+ else if ((pmtAssetIdA == pmtAssetIdB))
295+ then throw("Assets must be different")
296+ else {
297+ let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
298+ let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
299+ let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
300+ let arg1 = pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN)
301+ let arg2 = pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN)
302+ let arg3 = pow(10, 0, shareDecimals, 0, 0, DOWN)
303+ let shareInitialSupply = fraction(arg1, arg2, arg3)
304+ let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
305+ let shareIssueId = calculateAssetId(shareIssue)
306+ 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)]
307+ if (firstHarvest)
308+ then (baseEntry ++ [BooleanEntry(keyFirstHarvest, firstHarvest), IntegerEntry(keyFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
309+ else baseEntry
310+ }
550311 }
551312
552313
553314
554315 @Callable(i)
555-func withdrawShareTokens (pool,shareTokensWithdrawAmount) = {
556- let shareTokensId = fromBase58String(getStringValue(value(addressFromString(pool)), "share_asset_id"))
557- let $t02306523165 = claimCalc(pool, i.caller, 1)
558- let userNewInterest = $t02306523165._1
559- let currentInterest = $t02306523165._2
560- let claimAmount = $t02306523165._3
561- let userShareTokensAmount = $t02306523165._4
562- let userShareAmountNew = (userShareTokensAmount - shareTokensWithdrawAmount)
563- let availableFundsNew = (userAvailableSWOP(pool, i.caller) + claimAmount)
564- let totalShareAmount = getTotalShareTokenLocked(pool)
565- let totalShareAmountNew = (totalShareAmount - shareTokensWithdrawAmount)
566- let userClaimedAmount = getUserSWOPClaimedAmount(pool, i.caller)
567- let userClaimedAmountNew = (userClaimedAmount + claimAmount)
568- if ((shareTokensWithdrawAmount > userShareTokensAmount))
569- then throw("Withdraw amount more then user locked amount")
570- else if (!(isActive))
571- then throw("DApp is inactive at this moment")
572- else if ((shareTokensWithdrawAmount > userShareTokensAmount))
573- then throw("Withdraw amount more then user locked amount")
574- else if ((fraction(99, (accountBalance(shareTokensId) - shareTokensWithdrawAmount), 100) > totalShareAmountNew))
575- then throw("Balance of share-token is greater than totalAmount")
576- else [IntegerEntry((((pool + "_") + toString(i.caller)) + keyUserLastInterest), userNewInterest), IntegerEntry((((pool + "_") + toString(i.caller)) + keyUserShareTokensLocked), userShareAmountNew), IntegerEntry((pool + keyLastInterest), currentInterest), IntegerEntry((pool + keyLastInterestHeight), height), IntegerEntry((pool + keyShareTokensLocked), totalShareAmountNew), IntegerEntry((((pool + "_") + toString(i.caller)) + keyAvailableSWOP), availableFundsNew), IntegerEntry((((pool + "_") + toString(i.caller)) + keyUserSWOPClaimedAmount), userClaimedAmountNew), IntegerEntry((((pool + "_") + toString(i.caller)) + keyUserSWOPLastClaimedAmount), claimAmount), ScriptTransfer(i.caller, shareTokensWithdrawAmount, shareTokensId)]
316+func initWithInitRatio (amtAssetA,amtAssetB,strAssetIdA,strAssetIdB,firstHarvest) = {
317+ let $t01056910656 = getAssetInfoFromString(strAssetIdA)
318+ let pmtStrAssetIdA = $t01056910656._1
319+ let pmtAssetNameA = $t01056910656._2
320+ let pmtDecimalsA = $t01056910656._3
321+ let $t01066110748 = getAssetInfoFromString(strAssetIdB)
322+ let pmtStrAssetIdB = $t01066110748._1
323+ let pmtAssetNameB = $t01066110748._2
324+ let pmtDecimalsB = $t01066110748._3
325+ if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
326+ then throw("Only admin can call this function")
327+ else if (isDefined(getBoolean(this, keyActive)))
328+ then throw("DApp is already active")
329+ else if ((strAssetIdA == strAssetIdB))
330+ then throw("Assets must be different")
331+ else {
332+ let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
333+ let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
334+ let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
335+ let shareInitialSupply = 0
336+ let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
337+ let shareIssueId = calculateAssetId(shareIssue)
338+ 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)]
339+ if (firstHarvest)
340+ then (baseEntry ++ [BooleanEntry(keyFirstHarvest, firstHarvest), IntegerEntry(keyFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
341+ else baseEntry
342+ }
577343 }
578344
579345
580346
581347 @Callable(i)
582-func claim (pool) = {
583- let shareTokensId = fromBase58String(getStringValue(value(addressFromString(pool)), "share_asset_id"))
584- let shareTokenLocked = getTotalShareTokenLocked(pool)
585- let $t02517125236 = getLastInterestInfo(pool)
586- let lastInterestHeight = $t02517125236._1
587- let lastInterest = $t02517125236._2
588- let $t02524125353 = rewardInfo(pool)
589- let currentRewardPerBlock = $t02524125353._1
590- let rewardUpdateHeight = $t02524125353._2
591- let previousRewardPerBlock = $t02524125353._3
592- let poolRewardUpdateHeight = $t02524125353._4
593- let $t02535825458 = claimCalc(pool, i.caller, 1)
594- let userNewInterest = $t02535825458._1
595- let currentInterest = $t02535825458._2
596- let claimAmount = $t02535825458._3
597- let userShareTokensAmount = $t02535825458._4
598- let availableFund = (userAvailableSWOP(pool, i.caller) + claimAmount)
599- let userClaimedAmount = getUserSWOPClaimedAmount(pool, i.caller)
600- let userClaimedAmountNew = (userClaimedAmount + claimAmount)
601- if ((availableFund == 0))
602- then throw("You have 0 available SWOP")
603- else if (!(isActive))
604- then throw("DApp is inactive at this moment")
605- else if ((availableFund == 0))
606- then throw("You have 0 available SWOP")
607- else if ((fraction(99, accountBalance(shareTokensId), 100) > shareTokenLocked))
608- then throw("Balance of share-token is greater than totalAmount")
609- else [IntegerEntry((((pool + "_") + toString(i.caller)) + keyUserLastInterest), userNewInterest), IntegerEntry((pool + keyLastInterest), currentInterest), IntegerEntry((pool + keyLastInterestHeight), height), IntegerEntry((((pool + "_") + toString(i.caller)) + keyAvailableSWOP), 0), IntegerEntry((((pool + "_") + toString(i.caller)) + keyUserSWOPClaimedAmount), userClaimedAmountNew), IntegerEntry((((pool + "_") + toString(i.caller)) + keyUserSWOPLastClaimedAmount), claimAmount), ScriptTransfer(i.caller, availableFund, SWOP)]
348+func keepLimitForFirstHarvest (shareLimit) = if (!(isActive))
349+ then throw("DApp is inactive at this moment")
350+ else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
351+ then throw("Only admin can call this function")
352+ else [IntegerEntry(kShareLimit, shareLimit)]
353+
354+
355+
356+@Callable(i)
357+func replenishWithTwoTokens (slippageTolerance) = {
358+ let pmtAssetIdA = i.payments[0].assetId
359+ let pmtAssetIdB = i.payments[1].assetId
360+ let pmtAmountA = deductStakingFee(i.payments[0].amount, pmtAssetIdA, pmtAssetIdB)
361+ let pmtAmountB = deductStakingFee(i.payments[1].amount, pmtAssetIdB, pmtAssetIdA)
362+ if (if ((balanceA == 0))
363+ then (balanceB == 0)
364+ else false)
365+ then {
366+ let $t01345913536 = getAssetInfo(pmtAssetIdA)
367+ let pmtStrAssetIdA = $t01345913536._1
368+ let pmtAssetNameA = $t01345913536._2
369+ let pmtDecimalsA = $t01345913536._3
370+ let $t01354513622 = getAssetInfo(pmtAssetIdB)
371+ let pmtStrAssetIdB = $t01354513622._1
372+ let pmtAssetNameB = $t01354513622._2
373+ let pmtDecimalsB = $t01354513622._3
374+ let tokenRatio = fraction(fraction(assetInitA, scaleValue8, pmtAmountA), scaleValue3, fraction(assetInitB, scaleValue8, pmtAmountB))
375+ if ((pmtAssetIdA == pmtAssetIdB))
376+ then throw("Assets must be different")
377+ else {
378+ let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
379+ let shareInitialSupply = fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN), pow(10, 0, shareDecimals, 0, 0, DOWN))
380+ if (!(isActive))
381+ then throw("DApp is inactive at this moment")
382+ else if (if ((0 > slippageTolerance))
383+ then true
384+ else (slippageTolerance > slippageToleranceDelimiter))
385+ then throw(((("Slippage tolerance must be between 0 and " + toString(slippageToleranceDelimiter)) + " inclusively. Actual: ") + toString(slippageTolerance)))
386+ else if ((size(i.payments) != 2))
387+ then throw("Two attached assets expected")
388+ else if (if ((((scaleValue3 * (slippageToleranceDelimiter - slippageTolerance)) / slippageToleranceDelimiter) > tokenRatio))
389+ then true
390+ else (tokenRatio > ((scaleValue3 * (slippageToleranceDelimiter + slippageTolerance)) / slippageToleranceDelimiter)))
391+ then throw("Incorrect assets amount: amounts must have the contract ratio")
392+ else if (if ((pmtAssetIdA != assetIdA))
393+ then true
394+ else (pmtAssetIdB != assetIdB))
395+ then throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
396+ else if ((shareInitialSupply == 0))
397+ then throw("Too small amount to replenish")
398+ else if (!(hasEnoughBalance))
399+ then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
400+ else [Reissue(shareAssetId, shareInitialSupply, true), IntegerEntry(keyBalanceA, pmtAmountA), IntegerEntry(keyBalanceB, pmtAmountB), IntegerEntry(keyShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareAssetId)]
401+ }
402+ }
403+ else {
404+ let tokenRatio = fraction(fraction(balanceA, scaleValue8, pmtAmountA), scaleValue3, fraction(balanceB, scaleValue8, pmtAmountB))
405+ let ratioShareTokensInA = fraction(pmtAmountA, scaleValue8, balanceA)
406+ let ratioShareTokensInB = fraction(pmtAmountB, scaleValue8, balanceB)
407+ let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scaleValue8)
408+ if (!(isActive))
409+ then throw("DApp is inactive at this moment")
410+ else if (if ((0 > slippageTolerance))
411+ then true
412+ else (slippageTolerance > slippageToleranceDelimiter))
413+ then throw(((("Slippage tolerance must be between 0 and " + toString(slippageToleranceDelimiter)) + " inclusively. Actual: ") + toString(slippageTolerance)))
414+ else if ((size(i.payments) != 2))
415+ then throw("Two attached assets expected")
416+ else if (if ((pmtAssetIdA != assetIdA))
417+ then true
418+ else (pmtAssetIdB != assetIdB))
419+ then throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
420+ else if (if ((((scaleValue3 * (slippageToleranceDelimiter - slippageTolerance)) / slippageToleranceDelimiter) > tokenRatio))
421+ then true
422+ else (tokenRatio > ((scaleValue3 * (slippageToleranceDelimiter + slippageTolerance)) / slippageToleranceDelimiter)))
423+ then throw("Incorrect assets amount: amounts must have the contract ratio")
424+ else if ((shareTokenToPayAmount == 0))
425+ then throw("Too small amount to replenish")
426+ else if (!(hasEnoughBalance))
427+ then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
428+ else [IntegerEntry(keyBalanceA, (balanceA + pmtAmountA)), IntegerEntry(keyBalanceB, (balanceB + pmtAmountB)), IntegerEntry(keyShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId)]
429+ }
430+ }
431+
432+
433+
434+@Callable(i)
435+func withdraw () = {
436+ let $t01802118171 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
437+ let pmtAmount = $t01802118171._1
438+ let pmtAssetId = $t01802118171._2
439+ let amountToPayA = deductStakingFee(fraction(pmtAmount, balanceA, shareAssetSupply), assetIdA, assetIdB)
440+ let amountToPayB = deductStakingFee(fraction(pmtAmount, balanceB, shareAssetSupply), assetIdB, assetIdA)
441+ if (!(isActive))
442+ then throw("DApp is inactive at this moment")
443+ else if ((size(i.payments) != 1))
444+ then throw("One attached payment expected")
445+ else if ((pmtAssetId != shareAssetId))
446+ then throw(("Incorrect asset attached. Expected: " + toBase58String(shareAssetId)))
447+ else if (!(hasEnoughBalance))
448+ then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
449+ else if (if ((amountToPayA > availableBalanceA))
450+ then true
451+ else (amountToPayB > availableBalanceB))
452+ then throwInsufficientAvailableBalances(amountToPayA, amountToPayB)
453+ 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)]
454+ }
455+
456+
457+
458+@Callable(i)
459+func exchange (minAmountToReceive) = {
460+ let $t01939719472 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
461+ let pmtAmount = $t01939719472._1
462+ let pmtAssetId = $t01939719472._2
463+ func calculateFees (tokenFrom,tokenTo) = {
464+ let amountWithoutFee = fraction(tokenTo, pmtAmount, (pmtAmount + tokenFrom))
465+ let amountWithFee = fraction(amountWithoutFee, (commissionScaleDelimiter - commission), commissionScaleDelimiter)
466+ let governanceReward = fraction(amountWithoutFee, commissionGovernance, commissionScaleDelimiter)
467+ if ((minAmountToReceive > amountWithFee))
468+ then throw(((("Calculated amount to receive " + toString(amountWithFee)) + " is less than specified minimum ") + toString(minAmountToReceive)))
469+ else $Tuple3(amountWithoutFee, amountWithFee, governanceReward)
470+ }
471+
472+ if (!(isActive))
473+ then throw("DApp is inactive at this moment")
474+ else if (if ((balanceA == 0))
475+ then true
476+ else (balanceB == 0))
477+ then throw("Can't exchange with zero balance")
478+ else if ((0 >= minAmountToReceive))
479+ then throw(("Minimal amount to receive must be positive. Actual: " + toString(minAmountToReceive)))
480+ else if ((size(i.payments) != 1))
481+ then throw("One attached payment expected")
482+ else if (!(hasEnoughBalance))
483+ then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
484+ else if ((pmtAssetId == assetIdA))
485+ then {
486+ let assetIdSend = assetIdB
487+ let $t02074620837 = calculateFees(balanceA, balanceB)
488+ let amountWithoutFee = $t02074620837._1
489+ let amountWithFee = $t02074620837._2
490+ let governanceReward = $t02074620837._3
491+ let newBalanceA = (balanceA + pmtAmount)
492+ let newBalanceB = ((balanceB - amountWithFee) - governanceReward)
493+ if (if ((stakedAmountA >= newBalanceA))
494+ then true
495+ else (stakedAmountB >= newBalanceB))
496+ then throwInsufficientAvailableBalance(amountWithFee, availableBalanceB, assetNameB)
497+ else [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)]
498+ }
499+ else if ((pmtAssetId == assetIdB))
500+ then {
501+ let assetIdSend = assetIdA
502+ let $t02165621747 = calculateFees(balanceB, balanceA)
503+ let amountWithoutFee = $t02165621747._1
504+ let amountWithFee = $t02165621747._2
505+ let governanceReward = $t02165621747._3
506+ let newBalanceA = ((balanceA - amountWithFee) - governanceReward)
507+ let newBalanceB = (balanceB + pmtAmount)
508+ if (if ((stakedAmountA >= newBalanceA))
509+ then true
510+ else (stakedAmountB >= newBalanceB))
511+ then throwInsufficientAvailableBalance(amountWithFee, availableBalanceA, assetNameA)
512+ else [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)]
513+ }
514+ else throw(((("Incorrect asset attached. Expected: " + strAssetIdA) + " or ") + strAssetIdB))
610515 }
611516
612517
614519 @Callable(i)
615520 func shutdown () = if (!(isActive))
616521 then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, keyCause), "the cause wasn't specified")))
617- else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3], i.callerPublicKey)))
522+ else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStartStop], i.callerPublicKey)))
618523 then throw("Only admin can call this function")
619524 else suspend("Paused by admin")
620525
623528 @Callable(i)
624529 func activate () = if (isActive)
625530 then throw("DApp is already active")
626- else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3], i.callerPublicKey)))
531+ else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStartStop], i.callerPublicKey)))
627532 then throw("Only admin can call this function")
628533 else [BooleanEntry(keyActive, true), DeleteEntry(keyCause)]
629534
630535
536+
537+@Callable(i)
538+func takeIntoAccountExtraFunds (amountLeave) = {
539+ let uncountableAmountEnrollAssetA = (accountBalanceWithStakedA - balanceA)
540+ let uncountableAmountEnrollAssetB = (accountBalanceWithStakedB - balanceB)
541+ let amountEnrollA = (uncountableAmountEnrollAssetA - (if ((assetIdA == unit))
542+ then amountLeave
543+ else 0))
544+ let amountEnrollB = (uncountableAmountEnrollAssetB - (if ((assetIdB == unit))
545+ then amountLeave
546+ else 0))
547+ if (!(isActive))
548+ then throw("DApp is inactive at this moment")
549+ else if ((i.caller != this))
550+ then throw("Only the DApp itself can call this function")
551+ else if ((0 > amountLeave))
552+ then throw(("Argument 'amountLeave' cannot be negative. Actual: " + toString(amountLeave)))
553+ else if (if ((0 > uncountableAmountEnrollAssetA))
554+ then true
555+ else (0 > uncountableAmountEnrollAssetB))
556+ then suspend("Enroll amount negative")
557+ else if (if ((0 > amountEnrollA))
558+ then true
559+ else (0 > amountEnrollB))
560+ then throw("Too large amountLeave")
561+ else [IntegerEntry(keyBalanceA, (balanceA + amountEnrollA)), IntegerEntry(keyBalanceB, (balanceB + amountEnrollB)), IntegerEntry(("last_income_" + strAssetIdA), amountEnrollA), IntegerEntry(("last_income_" + strAssetIdB), amountEnrollB)]
562+ }
563+
564+
631565 @Verifier(tx)
632566 func verify () = match tx {
567+ case inv: InvokeScriptTransaction =>
568+ let callTakeIntoAccount = if ((inv.dApp == this))
569+ then (inv.function == "takeIntoAccountExtraFunds")
570+ else false
571+ let callStaking = if (if ((inv.dApp == stakingUSDNNSBTAddress))
572+ then if (if (if ((inv.function == "lockNeutrino"))
573+ then (size(inv.payments) == 1)
574+ else false)
575+ then if ((inv.payments[0].assetId == USDN))
576+ then true
577+ else (inv.payments[0].assetId == NSBT)
578+ else false)
579+ then true
580+ else if ((inv.function == "unlockNeutrino"))
581+ then (size(inv.payments) == 0)
582+ else false
583+ else false)
584+ then true
585+ else if ((inv.dApp == stakingEURNAddress))
586+ then if (if (if ((inv.function == "startStaking"))
587+ then (size(inv.payments) == 1)
588+ else false)
589+ then (inv.payments[0].assetId == EURN)
590+ else false)
591+ then true
592+ else if ((inv.function == "stopStaking"))
593+ then (size(inv.payments) == 0)
594+ else false
595+ else false
596+ let exchangeToWaves = if (if (if ((inv.dApp == USDNToWavesExchanger))
597+ then (inv.function == "exchange")
598+ else false)
599+ then (assetIdA == USDN)
600+ else false)
601+ then true
602+ else if (if ((assetIdB == USDN))
603+ then (size(inv.payments) == 1)
604+ else false)
605+ then (inv.payments[0].assetId == USDN)
606+ else false
607+ let exchangeToNSBTs = if (if (if ((inv.dApp == USDNToNSBTExchanger))
608+ then (inv.function == "exchange")
609+ else false)
610+ then (assetIdA == NSBT)
611+ else false)
612+ then true
613+ else if (if ((assetIdB == NSBT))
614+ then (size(inv.payments) == 1)
615+ else false)
616+ then (inv.payments[0].assetId == USDN)
617+ else false
618+ let signedByAdmin = if (if (if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
619+ then true
620+ else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey2))
621+ then true
622+ else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey3))
623+ then true
624+ else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKeyStaking)
625+ if (if (if (if (callTakeIntoAccount)
626+ then true
627+ else callStaking)
628+ then true
629+ else exchangeToWaves)
630+ then true
631+ else exchangeToNSBTs)
632+ then signedByAdmin
633+ else false
633634 case _ =>
634635 let adminPubKey1Signed = if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
635636 then 1
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let keyShareTokensLocked = "_total_share_tokens_locked"
4+let version = "1.0.0"
55
6-let kShareLimit = "share_limit_on_first_harvest"
6+let keyVersion = "version"
77
88 let keyActive = "active"
9-
10-let keyCause = "shutdown_cause"
11-
12-let keyRewardPoolFractionCurrent = "_current_pool_fraction_reward"
13-
14-let keyRewardPoolFractionPrevious = "_previous_pool_fraction_reward"
15-
16-let keyHeightPoolFraction = "_pool_reward_update_height"
17-
18-let keyTotalRewardPerBlockCurrent = "total_reward_per_block_current"
19-
20-let keyTotalRewardPerBlockPrevious = "total_reward_per_block_previous"
21-
22-let keyRewardUpdateHeight = "reward_update_height"
23-
24-let keyLastInterest = "_last_interest"
25-
26-let keyLastInterestHeight = "_last_interest_height"
27-
28-let keyUserShareTokensLocked = "_share_tokens_locked"
29-
30-let keyUserLastInterest = "_last_interest"
31-
32-let keySWOPid = "SWOP_id"
33-
34-let keyUserSWOPClaimedAmount = "_SWOP_claimed_amount"
35-
36-let keyUserSWOPLastClaimedAmount = "_SWOP_last_claimed_amount"
37-
38-let keyAvailableSWOP = "_available_SWOP"
39-
40-let keyFarmingStartHeight = "farming_start_height"
41-
42-let keyAPY = "apy"
43-
44-let kPreviousTotalVoteSWOP = "previous_total_vote_SWOP"
45-
46-let keySwopYearEmission = "swop_year_emission"
47-
48-let keyBalancecpmmA = "A_asset_balance"
49-
50-let keyBalancecpmmB = "B_asset_balance"
51-
52-let kHarvestPoolActiveVoteStrucVoting = "_harvest_pool_activeVote_struc"
53-
54-let kHarvestUserPoolActiveVoteStrucVoting = "_harvest_user_pool_activeVote_struc"
55-
56-let keyLimitShareFirstHarvest = "share_limit_on_first_harvest"
579
5810 let keyAssetIdA = "A_asset_id"
5911
6012 let keyAssetIdB = "B_asset_id"
6113
14+let keyBalanceA = "A_asset_balance"
15+
16+let keyBalanceB = "B_asset_balance"
17+
18+let keyBalanceInitA = "A_asset_init"
19+
20+let keyBalanceInitB = "B_asset_init"
21+
22+let keyShareAssetId = "share_asset_id"
23+
24+let keyShareAssetSupply = "share_asset_supply"
25+
26+let keyCommission = "commission"
27+
28+let keyCommissionScaleDelimiter = "commission_scale_delimiter"
29+
30+let keyCause = "shutdown_cause"
31+
32+let keyFirstHarvest = "first_harvest"
33+
6234 let keyFirstHarvestHeight = "first_harvest_height"
6335
64-let keyfirstHarvestCpmm = "first_harvest"
36+let kShareLimit = "share_limit_on_first_harvest"
6537
66-let keyTempPrevSum = "sum_reward_previous"
38+let kBasePeriod = "base_period"
6739
68-let keyTempCurSum = "sum_reward_current"
40+let kPeriodLength = "period_length"
6941
70-let governanceAddress = Address(base58'3N5W8da2iiijVieA6qLGo7KzCJj8B19smWU')
42+let kStartHeight = "start_height"
7143
72-let wallet = Address(base58'3NAGTtZz6WpupSN89NZD5rMZwwziZEg4Kx4')
73-
74-let votingAddress = Address(base58'3MrJgdL1GniipErHy44YF9idzLaUL2iX5DQ')
75-
76-let adminIncreaseInterestAddress = Address(base58'3NAGTtZz6WpupSN89NZD5rMZwwziZEg4Kx4')
77-
78-let oneWeekInBlock = 10106
79-
80-let totalVoteShare = 10000000000
81-
82-let scaleValue1 = 10
83-
84-let scaleValue3 = 1000
85-
86-let scaleValue5 = 100000
87-
88-let scaleValue6 = 1000000
89-
90-let scaleValue8 = 100000000
91-
92-let scaleValue11 = 100000000000
44+let kFirstHarvestHeight = "first_harvest_height"
9345
9446 let keyAdminPubKey1 = "admin_pub_1"
9547
9648 let keyAdminPubKey2 = "admin_pub_2"
9749
9850 let keyAdminPubKey3 = "admin_pub_3"
9951
10052 let oracle = Address(base58'3NBBWfzZtZtszaXbitTKnrB2xXwv26Bn7H9')
10153
10254 func getAdminPub (keyAdminPub) = match getString(oracle, keyAdminPub) {
10355 case string: String =>
10456 fromBase58String(string)
10557 case nothing =>
10658 throw("Admin public key is empty")
10759 }
10860
10961
11062 let adminPubKey1 = getAdminPub(keyAdminPubKey1)
11163
11264 let adminPubKey2 = getAdminPub(keyAdminPubKey2)
11365
11466 let adminPubKey3 = getAdminPub(keyAdminPubKey3)
11567
116-func strAssetIdA (pool) = getStringValue(pool, keyAssetIdA)
68+let adminPubKeyStartStop = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
11769
70+let adminPubKeyStaking = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
11871
119-func strAssetIdB (pool) = getStringValue(pool, keyAssetIdB)
72+let walletAddress = Address(base58'3NAGTtZz6WpupSN89NZD5rMZwwziZEg4Kx4')
12073
74+let votingAddress = Address(base58'3MrJgdL1GniipErHy44YF9idzLaUL2iX5DQ')
12175
122-func assetIdA (pool) = if ((strAssetIdA(pool) == "WAVES"))
123- then unit
124- else fromBase58String(strAssetIdA(pool))
76+let USDN = base58'8UrfDVd5GreeUwm7uPk7eYz1eMv376kzR52C6sANPkwS'
12577
78+let NSBT = base58'36mg8NZTaFRDygiVwb8uBnLR51hetJruUCZcxhaVcHj9'
12679
127-func assetIdB (pool) = if ((strAssetIdB(pool) == "WAVES"))
128- then unit
129- else fromBase58String(strAssetIdB(pool))
80+let SWOP = base58'2HAJrwa8q4SxBx9cHYaBTQdBjdk5wwqdof7ccpAx2uhZ'
13081
82+let EURN = base58'ECBCkHS68DckpBrzLeoRgYbFg7sCVqR176mPqbXsj9pA'
13183
132-let kBasePeriod = "base_period"
84+let stakingUSDNNSBTAddress = Address(base58'3N6q7sCGSSLBUXDdjBdYGTJbZGZfhhh8cNg')
13385
134-let kPeriodLength = "period_length"
86+let stakingEURNAddress = Address(base58'3MyVqAbmKWh339gF6hy8faWw1jGeTV2wnGE')
13587
136-let kStartHeight = "start_height"
88+let USDNToWavesExchanger = Address(base58'3N77kfPbQyjXWpDALX3xjKw3iEGMWEctV37')
13789
138-let kFirstHarvestHeight = "first_harvest_height"
90+let USDNToNSBTExchanger = Address(base58'3Mye9wVR7d2mc6Y5ZJTu11svzgUQ7o8H9dA')
13991
140-let kDurationFullVotePower = "duration_full_vote_power"
92+let stakingFeeInUSDN = 270000
14193
142-let kMinVotePower = "min_vote_power"
94+let stakingFeeInEURN = 234000
14395
14496 let basePeriod = valueOrErrorMessage(getInteger(votingAddress, kBasePeriod), "Empty kBasePeriod")
14597
14698 let startHeight = valueOrErrorMessage(getInteger(votingAddress, kStartHeight), "Empty kStartHeight")
14799
148100 let periodLength = valueOrErrorMessage(getInteger(votingAddress, kPeriodLength), "Empty kPeriodLength")
149101
150-let durationFullVotePower = valueOrErrorMessage(getInteger(votingAddress, kDurationFullVotePower), "Empty kDurationFullVotePower")
151-
152-let minVotePower = valueOrErrorMessage(getInteger(votingAddress, kMinVotePower), "Empty kMinVotePower")
102+let firstHarvestEndPeriod = ((basePeriod + ((height - startHeight) / periodLength)) + 3)
153103
154104 let isActive = getBooleanValue(this, keyActive)
155105
156-let currPeriod = (basePeriod + ((height - startHeight) / periodLength))
106+let strAssetIdA = getStringValue(this, keyAssetIdA)
157107
158-func getLimitToken (pool) = valueOrElse(getIntegerValue(pool, keyLimitShareFirstHarvest), 0)
108+let strAssetIdB = getStringValue(this, keyAssetIdB)
159109
110+let assetIdA = if ((strAssetIdA == "WAVES"))
111+ then unit
112+ else fromBase58String(strAssetIdA)
160113
161-let APY = getIntegerValue(this, keyAPY)
114+let assetIdB = if ((strAssetIdB == "WAVES"))
115+ then unit
116+ else fromBase58String(strAssetIdB)
162117
163-let SwopYearEmission = getIntegerValue(this, keySwopYearEmission)
164-
165-func assetNameA (pool) = match assetIdA(pool) {
118+let assetNameA = match assetIdA {
166119 case id: ByteVector =>
167120 value(assetInfo(id)).name
168121 case waves: Unit =>
169122 "WAVES"
170123 case _ =>
171124 throw("Match error")
172125 }
173126
174-
175-func assetNameB (pool) = match assetIdB(pool) {
127+let assetNameB = match assetIdB {
176128 case id: ByteVector =>
177129 value(assetInfo(id)).name
178130 case waves: Unit =>
179131 "WAVES"
180132 case _ =>
181133 throw("Match error")
182134 }
183135
136+let balanceA = getIntegerValue(this, keyBalanceA)
184137
185-let SWOP = fromBase58String(getStringValue(this, keySWOPid))
138+let balanceB = getIntegerValue(this, keyBalanceB)
186139
187-func isFirstHarvest (pool) = valueOrElse(getBoolean(pool, keyfirstHarvestCpmm), false)
140+let shareAssetId = fromBase58String(getStringValue(this, keyShareAssetId))
188141
142+let shareAssetSupply = getIntegerValue(this, keyShareAssetSupply)
189143
190-func getHeightFirstHarvest (pool) = valueOrElse(getInteger(pool, keyFirstHarvestHeight), 0)
144+let commission = 3000
191145
146+let commissionGovernance = 1200
192147
193-func getBalanceA (pool) = valueOrErrorMessage(getInteger(pool, keyBalancecpmmA), ("No data on the key: " + keyBalancecpmmA))
148+let commissionScaleDelimiter = 1000000
194149
150+let scaleValue3 = 1000
195151
196-func getBalanceB (pool) = valueOrErrorMessage(getInteger(pool, keyBalancecpmmB), ("No data on the key: " + keyBalancecpmmB))
152+let scaleValue8 = 100000000
197153
154+let slippageToleranceDelimiter = 1000
198155
199-func getShareLimitToken (pool) = valueOrErrorMessage(getInteger(pool, kShareLimit), ("No data on the key: " + kShareLimit))
200-
201-
202-func getTotalShareTokenLocked (pool) = valueOrErrorMessage(getInteger(this, (pool + keyShareTokensLocked)), (("No data on the key: " + pool) + keyShareTokensLocked))
203-
204-
205-func getShareAssetId (pool) = fromBase58String(getStringValue(value(addressFromString(pool)), "share_asset_id"))
206-
156+let scaleValue8Digits = 8
207157
208158 func accountBalance (assetId) = match assetId {
209159 case id: ByteVector =>
210160 assetBalance(this, id)
211161 case waves: Unit =>
212162 wavesBalance(this).available
213163 case _ =>
214164 throw("Match error")
215165 }
216166
167+
168+func stakedAmount (assetId) = {
169+ let stakedAmountCalculated = match assetId {
170+ case aId: ByteVector =>
171+ if (if ((aId == USDN))
172+ then true
173+ else (aId == NSBT))
174+ then getInteger(stakingUSDNNSBTAddress, ((("rpd_balance_" + toBase58String(aId)) + "_") + toString(this)))
175+ else if ((aId == EURN))
176+ then getInteger(stakingEURNAddress, ((("%s%s%s__stakingBalance__" + toBase58String(aId)) + "__") + toString(this)))
177+ else 0
178+ case _: Unit =>
179+ 0
180+ case _ =>
181+ throw("Match error")
182+ }
183+ match stakedAmountCalculated {
184+ case i: Int =>
185+ i
186+ case _ =>
187+ 0
188+ }
189+ }
190+
191+
192+let stakedAmountA = stakedAmount(assetIdA)
193+
194+let stakedAmountB = stakedAmount(assetIdB)
195+
196+let assetInitA = getIntegerValue(this, keyBalanceInitA)
197+
198+let assetInitB = getIntegerValue(this, keyBalanceInitB)
199+
200+let availableBalanceA = (balanceA - stakedAmountA)
201+
202+let availableBalanceB = (balanceB - stakedAmountB)
203+
204+let accountBalanceWithStakedA = (accountBalance(assetIdA) + stakedAmountA)
205+
206+let accountBalanceWithStakedB = (accountBalance(assetIdB) + stakedAmountB)
207+
208+let hasEnoughBalance = if ((accountBalanceWithStakedA >= balanceA))
209+ then (accountBalanceWithStakedB >= balanceB)
210+ else false
217211
218212 func getAssetInfo (assetId) = match assetId {
219213 case id: ByteVector =>
220214 let stringId = toBase58String(id)
221215 let info = valueOrErrorMessage(assetInfo(id), (("Asset " + stringId) + " doesn't exist"))
222216 $Tuple3(stringId, info.name, info.decimals)
223217 case waves: Unit =>
224218 $Tuple3("WAVES", "WAVES", 8)
225219 case _ =>
226220 throw("Match error")
227221 }
228222
229223
230-func calcScaleValue (assetId1,assetId2) = {
231- let assetId1Decimals = value(assetInfo(assetId1)).decimals
232- let assetId2Decimals = value(assetInfo(assetId2)).decimals
233- let scaleDigits = ((assetId2Decimals - assetId1Decimals) + 8)
234- pow(10, 0, scaleDigits, 0, 0, DOWN)
235- }
236-
237-
238-func userAvailableSWOP (pool,user) = valueOrElse(getInteger(this, (((pool + "_") + toString(user)) + keyAvailableSWOP)), 0)
239-
240-
241-func rewardInfo (pool) = {
242- let totalRewardPerBlockCurrent = valueOrErrorMessage(getInteger(governanceAddress, keyTotalRewardPerBlockCurrent), ((("No data on the key: " + keyTotalRewardPerBlockCurrent) + " at address ") + toString(governanceAddress)))
243- let totalRewardPerBlockPrevious = valueOrErrorMessage(getInteger(governanceAddress, keyTotalRewardPerBlockPrevious), ((("No data on the key: " + keyTotalRewardPerBlockPrevious) + " at address ") + toString(governanceAddress)))
244- let rewardPoolFractionCurrent = valueOrErrorMessage(getInteger(governanceAddress, (pool + keyRewardPoolFractionCurrent)), (((("No data on the key: " + pool) + keyRewardPoolFractionCurrent) + " at address ") + toString(governanceAddress)))
245- let rewardUpdateHeight = valueOrErrorMessage(getInteger(governanceAddress, keyRewardUpdateHeight), ((("No data on the key: " + keyRewardUpdateHeight) + " at address ") + toString(governanceAddress)))
246- let poolRewardUpdateHeight = valueOrElse(getInteger(governanceAddress, (pool + keyHeightPoolFraction)), 0)
247- let rewardPoolFractionPrevious = valueOrErrorMessage(getInteger(governanceAddress, (pool + keyRewardPoolFractionPrevious)), (((("No data on the key: " + pool) + keyRewardPoolFractionPrevious) + " at address ") + toString(governanceAddress)))
248- let rewardPoolCurrent = fraction(totalRewardPerBlockCurrent, rewardPoolFractionCurrent, totalVoteShare)
249- let rewardPoolPrevious = fraction(totalRewardPerBlockPrevious, rewardPoolFractionPrevious, totalVoteShare)
250- if (if ((rewardPoolCurrent > totalRewardPerBlockCurrent))
251- then true
252- else (rewardPoolPrevious > totalRewardPerBlockPrevious))
253- then throw("rewardPoolCurrent > totalRewardPerBlockCurrent or rewardPoolPrevious > totalRewardPerBlockPrevious")
254- else $Tuple4(rewardPoolCurrent, rewardUpdateHeight, rewardPoolPrevious, poolRewardUpdateHeight)
255- }
256-
257-
258-func getLastInterestInfo (pool) = {
259- let lastInterest = valueOrErrorMessage(getInteger(this, (pool + keyLastInterest)), (("No data on the key: " + pool) + keyLastInterest))
260- let lastInterestHeight = valueOrElse(getInteger(this, (pool + keyLastInterestHeight)), height)
261- $Tuple2(lastInterestHeight, lastInterest)
262- }
263-
264-
265-func getUserInterestInfo (pool,userAddress) = {
266- let userLastInterest = getInteger(this, (((pool + "_") + toString(userAddress)) + keyUserLastInterest))
267- let userShare = getInteger(this, (((pool + "_") + toString(userAddress)) + keyUserShareTokensLocked))
268- let lastInterest = valueOrErrorMessage(getInteger(this, (pool + keyLastInterest)), (("No data on the key: " + pool) + keyLastInterest))
269- let userLastInterestValue = match userLastInterest {
270- case userLastInterest: Int =>
271- userLastInterest
272- case _ =>
273- lastInterest
274- }
275- let userShareTokensAmount = match userShare {
276- case userShare: Int =>
277- userShare
278- case _ =>
279- 0
280- }
281- $Tuple2(userLastInterestValue, userShareTokensAmount)
282- }
283-
284-
285-func calcInterest (lastInterestHeight,rewardUpdateHeight,poolRewardUpdateHeight,lastInterest,currentRewardPerBlock,shareTokenLocked,previousRewardPerBlock,shareAssetId,scaleValue,pmtAmount) = if ((shareTokenLocked == 0))
286- then 0
287- else if ((poolRewardUpdateHeight != 0))
288- then if (if ((rewardUpdateHeight > height))
289- then (rewardUpdateHeight == poolRewardUpdateHeight)
290- else false)
291- then {
292- let reward = (previousRewardPerBlock * (height - lastInterestHeight))
293- (lastInterest + fraction(reward, scaleValue, shareTokenLocked))
294- }
295- else if (if ((height > rewardUpdateHeight))
296- then (rewardUpdateHeight != poolRewardUpdateHeight)
297- else false)
298- then {
299- let reward = (previousRewardPerBlock * (height - lastInterestHeight))
300- (lastInterest + fraction(reward, scaleValue, shareTokenLocked))
301- }
302- else if (if (if ((height > rewardUpdateHeight))
303- then (rewardUpdateHeight == poolRewardUpdateHeight)
304- else false)
305- then (lastInterestHeight > rewardUpdateHeight)
306- else false)
307- then {
308- let reward = (currentRewardPerBlock * (height - lastInterestHeight))
309- (lastInterest + fraction(reward, scaleValue, shareTokenLocked))
310- }
311- else {
312- let rewardAfterLastInterestBeforeReawardUpdate = (previousRewardPerBlock * (rewardUpdateHeight - lastInterestHeight))
313- let interestAfterUpdate = (lastInterest + fraction(rewardAfterLastInterestBeforeReawardUpdate, scaleValue, shareTokenLocked))
314- let reward = (currentRewardPerBlock * (height - rewardUpdateHeight))
315- (interestAfterUpdate + fraction(reward, scaleValue, shareTokenLocked))
316- }
317- else if ((rewardUpdateHeight > height))
318- then {
319- let reward = (previousRewardPerBlock * (height - lastInterestHeight))
320- (lastInterest + fraction(reward, scaleValue, shareTokenLocked))
321- }
322- else if ((lastInterestHeight > rewardUpdateHeight))
323- then {
324- let reward = (currentRewardPerBlock * (height - rewardUpdateHeight))
325- (lastInterest + fraction(reward, scaleValue, shareTokenLocked))
326- }
327- else {
328- let rewardAfterLastInterestBeforeReawardUpdate = (previousRewardPerBlock * (rewardUpdateHeight - lastInterestHeight))
329- let interestAfterUpdate = (lastInterest + fraction(rewardAfterLastInterestBeforeReawardUpdate, scaleValue, shareTokenLocked))
330- let reward = (currentRewardPerBlock * (height - rewardUpdateHeight))
331- (interestAfterUpdate + fraction(reward, scaleValue, shareTokenLocked))
332- }
333-
334-
335-func claimCalc (pool,caller,pmtAmount) = {
336- let shareAssetId = getShareAssetId(pool)
337- let scaleValue = calcScaleValue(SWOP, shareAssetId)
338- let shareTokenLocked = getTotalShareTokenLocked(pool)
339- let $t01344513510 = getLastInterestInfo(pool)
340- let lastInterestHeight = $t01344513510._1
341- let lastInterest = $t01344513510._2
342- let $t01351513627 = rewardInfo(pool)
343- let currentRewardPerBlock = $t01351513627._1
344- let rewardUpdateHeight = $t01351513627._2
345- let previousRewardPerBlock = $t01351513627._3
346- let poolRewardUpdateHeight = $t01351513627._4
347- let $t01363213711 = getUserInterestInfo(pool, caller)
348- let userLastInterest = $t01363213711._1
349- let userShareTokensAmount = $t01363213711._2
350- let currentInterest = calcInterest(lastInterestHeight, rewardUpdateHeight, poolRewardUpdateHeight, lastInterest, currentRewardPerBlock, shareTokenLocked, previousRewardPerBlock, shareAssetId, scaleValue, pmtAmount)
351- let claimAmount = fraction(userShareTokensAmount, (currentInterest - userLastInterest), scaleValue)
352- let userNewInterest = currentInterest
353- $Tuple4(userNewInterest, currentInterest, claimAmount, userShareTokensAmount)
354- }
355-
356-
357-func calculateProtocolReward (pool) = {
358- let $t01423114296 = getLastInterestInfo(pool)
359- let lastInterestHeight = $t01423114296._1
360- let lastInterest = $t01423114296._2
361- let $t01430114412 = rewardInfo(pool)
362- let currentRewardPerBlock = $t01430114412._1
363- let rewardUpdateHeight = $t01430114412._2
364- let previousRewardPerBlock = $t01430114412._3
365- let poolRewardUpdateHeight = $t01430114412._4
366- let shareTokenLocked = getTotalShareTokenLocked(pool)
367- if (if ((shareTokenLocked == 0))
368- then (poolRewardUpdateHeight == 0)
369- else false)
370- then if ((rewardUpdateHeight > height))
371- then {
372- let reward = (previousRewardPerBlock * (height - lastInterestHeight))
373- reward
374- }
375- else if ((lastInterestHeight > rewardUpdateHeight))
376- then {
377- let reward = (currentRewardPerBlock * (height - lastInterestHeight))
378- reward
379- }
380- else {
381- let rewardAfterLastInterestBeforeReawardUpdate = (previousRewardPerBlock * (rewardUpdateHeight - lastInterestHeight))
382- let reward = (currentRewardPerBlock * (height - rewardUpdateHeight))
383- (reward + rewardAfterLastInterestBeforeReawardUpdate)
384- }
385- else if (if ((shareTokenLocked == 0))
386- then (poolRewardUpdateHeight != 0)
387- else false)
388- then if (if ((rewardUpdateHeight > height))
389- then (rewardUpdateHeight == poolRewardUpdateHeight)
390- else false)
391- then {
392- let reward = (previousRewardPerBlock * (height - lastInterestHeight))
393- reward
394- }
395- else if (if ((height > rewardUpdateHeight))
396- then (rewardUpdateHeight != poolRewardUpdateHeight)
397- else false)
398- then {
399- let reward = (previousRewardPerBlock * (height - lastInterestHeight))
400- reward
401- }
402- else if (if (if ((height > rewardUpdateHeight))
403- then (rewardUpdateHeight == poolRewardUpdateHeight)
404- else false)
405- then (lastInterestHeight > rewardUpdateHeight)
406- else false)
407- then {
408- let reward = (currentRewardPerBlock * (height - lastInterestHeight))
409- reward
410- }
411- else {
412- let rewardAfterLastInterestBeforeReawardUpdate = (previousRewardPerBlock * (rewardUpdateHeight - lastInterestHeight))
413- let reward = (currentRewardPerBlock * (height - rewardUpdateHeight))
414- (reward + rewardAfterLastInterestBeforeReawardUpdate)
415- }
416- else 0
417- }
418-
419-
420-func checkPmtAssetIdCorrect (pool,pmtAssetId) = {
421- let poolShareAssetId = fromBase58String(getStringValue(value(addressFromString(pool)), "share_asset_id"))
422- if ((pmtAssetId == poolShareAssetId))
423- then true
424- else false
425- }
426-
427-
428-func getUserSWOPClaimedAmount (pool,user) = valueOrElse(getInteger(this, (((pool + "_") + toString(user)) + keyUserSWOPClaimedAmount)), 0)
224+func getAssetInfoFromString (assetStr) = if ((assetStr == "WAVES"))
225+ then $Tuple3("WAVES", "WAVES", 8)
226+ else {
227+ let stringId = assetStr
228+ let id = fromBase58String(assetStr)
229+ let info = valueOrErrorMessage(assetInfo(id), (("Asset " + stringId) + " doesn't exist"))
230+ $Tuple3(stringId, info.name, info.decimals)
231+ }
429232
430233
431234 func suspend (cause) = [BooleanEntry(keyActive, false), StringEntry(keyCause, cause)]
432235
433236
434-@Callable(i)
435-func init (earlyLP) = if (isDefined(getString(this, keySWOPid)))
436- then throw("SWOP already initialized")
437- else {
438- let initAmount = 100000000000000
439- let SWOPissue = Issue("SWOP", "SWOP protocol token", initAmount, 8, true)
440- let SWOPid = calculateAssetId(SWOPissue)
441-[BooleanEntry(keyActive, true), Issue("SWOP", "SWOP protocol token", initAmount, 8, true), StringEntry(keySWOPid, toBase58String(SWOPid))]
237+func deductStakingFee (amount,assetId,secondAssetId) = if (if ((assetId == USDN))
238+ then true
239+ else (assetId == EURN))
240+ then {
241+ let stakinFee = if ((assetId == USDN))
242+ then (stakingFeeInUSDN * (if ((secondAssetId == NSBT))
243+ then 2
244+ else 1))
245+ else if ((assetId == EURN))
246+ then stakingFeeInEURN
247+ else 0
248+ let result = (amount - stakinFee)
249+ if ((0 >= result))
250+ then throw((((("Insufficient amount " + toString(amount)) + " to deduct staking fee ") + toString(stakinFee)) + "USDN/EURN"))
251+ else result
442252 }
253+ else amount
443254
255+
256+func getStakingFee (assetId,secondAssetId) = if ((assetId == USDN))
257+ then (stakingFeeInUSDN * (if ((secondAssetId == NSBT))
258+ then 2
259+ else 1))
260+ else if ((assetId == EURN))
261+ then stakingFeeInEURN
262+ else 0
263+
264+
265+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"))
266+
267+
268+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"))
269+
270+
271+func suspendSuspicious () = suspend(((((((((((((((("Suspicious state. Actual balances: " + toString(accountBalanceWithStakedA)) + " ") + assetNameA) + ", ") + toString(accountBalanceWithStakedB)) + " ") + assetNameB) + ". State: ") + toString(balanceA)) + " ") + assetNameA) + ", ") + toString(balanceB)) + " ") + assetNameB))
444272
445273
446274 @Callable(i)
447-func initPoolShareFarming (pool) = if ((i.caller != this))
448- then throw("Only the DApp itself can call this function")
449- else {
450- let $t01739417497 = rewardInfo(pool)
451- let currentReward = $t01739417497._1
452- let rewardUpdateHeight = $t01739417497._2
453- let previousRewardPerBlock = $t01739417497._3
454- let poolRewardUpdateHeight = $t01739417497._4
455-[IntegerEntry((pool + keyShareTokensLocked), 0), IntegerEntry((pool + keyLastInterest), 0), IntegerEntry((pool + keyLastInterestHeight), height)]
456- }
457-
458-
459-
460-@Callable(i)
461-func updatePoolInterest (pool) = if ((i.caller != wallet))
462- then throw("Only the Admin itself can call this function")
463- else if (!(isActive))
464- then throw("DApp is inactive at this moment")
465- else {
466- let $t01790618026 = claimCalc(pool, adminIncreaseInterestAddress, 0)
467- let userNewInterest = $t01790618026._1
468- let currentInterest = $t01790618026._2
469- let claimAmount = $t01790618026._3
470- let userShareTokensAmount = $t01790618026._4
471- let $t01803118134 = rewardInfo(pool)
472- let currentReward = $t01803118134._1
473- let rewardUpdateHeight = $t01803118134._2
474- let previousRewardPerBlock = $t01803118134._3
475- let poolRewardUpdateHeight = $t01803118134._4
476-[IntegerEntry((pool + keyLastInterest), userNewInterest), IntegerEntry((pool + keyLastInterestHeight), height)]
477- }
478-
479-
480-
481-@Callable(i)
482-func lockShareTokens (pool) = {
483- let $t01832618401 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
484- let pmtAmount = $t01832618401._1
485- let pmtAssetId = $t01832618401._2
486- let $t01840618479 = getAssetInfo(pmtAssetId)
487- let pmtStrAssetId = $t01840618479._1
488- let pmtAssetName = $t01840618479._2
489- let pmtDecimals = $t01840618479._3
490- let $t01848418592 = claimCalc(pool, i.caller, pmtAmount)
491- let userNewInterest = $t01848418592._1
492- let currentInterest = $t01848418592._2
493- let claimAmount = $t01848418592._3
494- let userShareTokensAmount = $t01848418592._4
495- let userShareAmountNew = (userShareTokensAmount + pmtAmount)
496- let availableFundsNew = (userAvailableSWOP(pool, i.caller) + claimAmount)
497- let totalShareAmount = getTotalShareTokenLocked(pool)
498- let totalShareAmountNew = (totalShareAmount + pmtAmount)
499- let userClaimedAmount = getUserSWOPClaimedAmount(pool, i.caller)
500- let userClaimedAmountNew = (userClaimedAmount + claimAmount)
501- let baseEntry = [IntegerEntry((((pool + "_") + toString(i.caller)) + keyUserLastInterest), userNewInterest), IntegerEntry((((pool + "_") + toString(i.caller)) + keyUserShareTokensLocked), userShareAmountNew), IntegerEntry((pool + keyShareTokensLocked), totalShareAmountNew), IntegerEntry((pool + keyLastInterest), currentInterest), IntegerEntry((pool + keyLastInterestHeight), height), IntegerEntry((((pool + "_") + toString(i.caller)) + keyUserSWOPClaimedAmount), userClaimedAmountNew), IntegerEntry((((pool + "_") + toString(i.caller)) + keyUserSWOPLastClaimedAmount), claimAmount), IntegerEntry((((pool + "_") + toString(i.caller)) + keyAvailableSWOP), availableFundsNew)]
502- if ((0 >= pmtAmount))
503- then throw("You can't lock token")
504- else if (!(isActive))
505- then throw("DApp is inactive at this moment")
506- else if (!(checkPmtAssetIdCorrect(pool, pmtAssetId)))
507- then throw("Incorrect pmtAssetId")
508- else if (if (isFirstHarvest(Address(fromBase58String(pool))))
509- then (getHeightFirstHarvest(Address(fromBase58String(pool))) > height)
510- else false)
511- then {
512- let harvestPeriod = ((((getHeightFirstHarvest(Address(fromBase58String(pool))) - startHeight) + 1) / periodLength) - 1)
513- let amountOfVoting = split(getStringValue(votingAddress, (((toString(i.caller) + "_") + pool) + "_user_pool_struc")), "_")
514- let amountPoolStract = split(getStringValue(votingAddress, (pool + "_pool_struc")), "_")
515- let amountActiveVoteUserPoolStract = split(valueOrElse(getString(votingAddress, (((toString(i.caller) + "_") + pool) + kHarvestUserPoolActiveVoteStrucVoting)), ""), "_")
516- let amountPoolActiveVoteStract = split(valueOrElse(getString(votingAddress, (pool + kHarvestPoolActiveVoteStrucVoting)), ""), "_")
517- let userShareTokenLocked = userShareTokensAmount
518- let userPoolActiveVote = if ((toString(currPeriod) == amountOfVoting[2]))
519- then valueOrElse(parseInt(amountActiveVoteUserPoolStract[0]), 0)
520- else valueOrElse(parseInt(amountOfVoting[1]), 0)
521- let poolActiveVote = if ((toString(currPeriod) == amountPoolStract[2]))
522- then valueOrElse(parseInt(amountPoolActiveVoteStract[0]), 0)
523- else valueOrElse(parseInt(amountPoolStract[1]), 0)
524- let protocolReward = calculateProtocolReward(pool)
525- if ((userPoolActiveVote != 0))
526- then {
527- let limitShareToken = getShareLimitToken(addressFromStringValue(pool))
528- let shareToken = (fraction(limitShareToken, userPoolActiveVote, poolActiveVote) - userShareTokenLocked)
529- if (if ((size(amountActiveVoteUserPoolStract) > 1))
530- then (valueOrElse(parseInt(amountActiveVoteUserPoolStract[1]), 0) >= harvestPeriod)
531- else false)
532- then throw("You can't share token")
533- else if ((pmtAmount > limitShareToken))
534- then throw(("You can't share token more than " + toString(limitShareToken)))
535- else if ((shareToken > 0))
536- then if ((fraction(99, (accountBalance(pmtAssetId) + pmtAmount), 100) > totalShareAmountNew))
537- then throw("Balance of share-token is greater than totalAmount")
538- else if (if ((totalShareAmount == 0))
539- then (shareToken >= pmtAmount)
540- else false)
541- then (baseEntry ++ [ScriptTransfer(wallet, protocolReward, SWOP)])
542- else if ((shareToken >= pmtAmount))
543- then baseEntry
544- else throw(("Your maximum share token is " + toString(shareToken)))
545- else throw("You can't share token")
546- }
547- else throw("Your amount of token less than 0")
548- }
549- else baseEntry
275+func init (firstHarvest) = {
276+ let $t080018078 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
277+ let pmtAmountA = $t080018078._1
278+ let pmtAssetIdA = $t080018078._2
279+ let $t080838160 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
280+ let pmtAmountB = $t080838160._1
281+ let pmtAssetIdB = $t080838160._2
282+ let $t081658242 = getAssetInfo(pmtAssetIdA)
283+ let pmtStrAssetIdA = $t081658242._1
284+ let pmtAssetNameA = $t081658242._2
285+ let pmtDecimalsA = $t081658242._3
286+ let $t082478324 = getAssetInfo(pmtAssetIdB)
287+ let pmtStrAssetIdB = $t082478324._1
288+ let pmtAssetNameB = $t082478324._2
289+ let pmtDecimalsB = $t082478324._3
290+ if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
291+ then throw("Only admin can call this function")
292+ else if (isDefined(getBoolean(this, keyActive)))
293+ then throw("DApp is already active")
294+ else if ((pmtAssetIdA == pmtAssetIdB))
295+ then throw("Assets must be different")
296+ else {
297+ let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
298+ let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
299+ let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
300+ let arg1 = pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN)
301+ let arg2 = pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN)
302+ let arg3 = pow(10, 0, shareDecimals, 0, 0, DOWN)
303+ let shareInitialSupply = fraction(arg1, arg2, arg3)
304+ let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
305+ let shareIssueId = calculateAssetId(shareIssue)
306+ 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)]
307+ if (firstHarvest)
308+ then (baseEntry ++ [BooleanEntry(keyFirstHarvest, firstHarvest), IntegerEntry(keyFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
309+ else baseEntry
310+ }
550311 }
551312
552313
553314
554315 @Callable(i)
555-func withdrawShareTokens (pool,shareTokensWithdrawAmount) = {
556- let shareTokensId = fromBase58String(getStringValue(value(addressFromString(pool)), "share_asset_id"))
557- let $t02306523165 = claimCalc(pool, i.caller, 1)
558- let userNewInterest = $t02306523165._1
559- let currentInterest = $t02306523165._2
560- let claimAmount = $t02306523165._3
561- let userShareTokensAmount = $t02306523165._4
562- let userShareAmountNew = (userShareTokensAmount - shareTokensWithdrawAmount)
563- let availableFundsNew = (userAvailableSWOP(pool, i.caller) + claimAmount)
564- let totalShareAmount = getTotalShareTokenLocked(pool)
565- let totalShareAmountNew = (totalShareAmount - shareTokensWithdrawAmount)
566- let userClaimedAmount = getUserSWOPClaimedAmount(pool, i.caller)
567- let userClaimedAmountNew = (userClaimedAmount + claimAmount)
568- if ((shareTokensWithdrawAmount > userShareTokensAmount))
569- then throw("Withdraw amount more then user locked amount")
570- else if (!(isActive))
571- then throw("DApp is inactive at this moment")
572- else if ((shareTokensWithdrawAmount > userShareTokensAmount))
573- then throw("Withdraw amount more then user locked amount")
574- else if ((fraction(99, (accountBalance(shareTokensId) - shareTokensWithdrawAmount), 100) > totalShareAmountNew))
575- then throw("Balance of share-token is greater than totalAmount")
576- else [IntegerEntry((((pool + "_") + toString(i.caller)) + keyUserLastInterest), userNewInterest), IntegerEntry((((pool + "_") + toString(i.caller)) + keyUserShareTokensLocked), userShareAmountNew), IntegerEntry((pool + keyLastInterest), currentInterest), IntegerEntry((pool + keyLastInterestHeight), height), IntegerEntry((pool + keyShareTokensLocked), totalShareAmountNew), IntegerEntry((((pool + "_") + toString(i.caller)) + keyAvailableSWOP), availableFundsNew), IntegerEntry((((pool + "_") + toString(i.caller)) + keyUserSWOPClaimedAmount), userClaimedAmountNew), IntegerEntry((((pool + "_") + toString(i.caller)) + keyUserSWOPLastClaimedAmount), claimAmount), ScriptTransfer(i.caller, shareTokensWithdrawAmount, shareTokensId)]
316+func initWithInitRatio (amtAssetA,amtAssetB,strAssetIdA,strAssetIdB,firstHarvest) = {
317+ let $t01056910656 = getAssetInfoFromString(strAssetIdA)
318+ let pmtStrAssetIdA = $t01056910656._1
319+ let pmtAssetNameA = $t01056910656._2
320+ let pmtDecimalsA = $t01056910656._3
321+ let $t01066110748 = getAssetInfoFromString(strAssetIdB)
322+ let pmtStrAssetIdB = $t01066110748._1
323+ let pmtAssetNameB = $t01066110748._2
324+ let pmtDecimalsB = $t01066110748._3
325+ if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
326+ then throw("Only admin can call this function")
327+ else if (isDefined(getBoolean(this, keyActive)))
328+ then throw("DApp is already active")
329+ else if ((strAssetIdA == strAssetIdB))
330+ then throw("Assets must be different")
331+ else {
332+ let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
333+ let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
334+ let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
335+ let shareInitialSupply = 0
336+ let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
337+ let shareIssueId = calculateAssetId(shareIssue)
338+ 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)]
339+ if (firstHarvest)
340+ then (baseEntry ++ [BooleanEntry(keyFirstHarvest, firstHarvest), IntegerEntry(keyFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
341+ else baseEntry
342+ }
577343 }
578344
579345
580346
581347 @Callable(i)
582-func claim (pool) = {
583- let shareTokensId = fromBase58String(getStringValue(value(addressFromString(pool)), "share_asset_id"))
584- let shareTokenLocked = getTotalShareTokenLocked(pool)
585- let $t02517125236 = getLastInterestInfo(pool)
586- let lastInterestHeight = $t02517125236._1
587- let lastInterest = $t02517125236._2
588- let $t02524125353 = rewardInfo(pool)
589- let currentRewardPerBlock = $t02524125353._1
590- let rewardUpdateHeight = $t02524125353._2
591- let previousRewardPerBlock = $t02524125353._3
592- let poolRewardUpdateHeight = $t02524125353._4
593- let $t02535825458 = claimCalc(pool, i.caller, 1)
594- let userNewInterest = $t02535825458._1
595- let currentInterest = $t02535825458._2
596- let claimAmount = $t02535825458._3
597- let userShareTokensAmount = $t02535825458._4
598- let availableFund = (userAvailableSWOP(pool, i.caller) + claimAmount)
599- let userClaimedAmount = getUserSWOPClaimedAmount(pool, i.caller)
600- let userClaimedAmountNew = (userClaimedAmount + claimAmount)
601- if ((availableFund == 0))
602- then throw("You have 0 available SWOP")
603- else if (!(isActive))
604- then throw("DApp is inactive at this moment")
605- else if ((availableFund == 0))
606- then throw("You have 0 available SWOP")
607- else if ((fraction(99, accountBalance(shareTokensId), 100) > shareTokenLocked))
608- then throw("Balance of share-token is greater than totalAmount")
609- else [IntegerEntry((((pool + "_") + toString(i.caller)) + keyUserLastInterest), userNewInterest), IntegerEntry((pool + keyLastInterest), currentInterest), IntegerEntry((pool + keyLastInterestHeight), height), IntegerEntry((((pool + "_") + toString(i.caller)) + keyAvailableSWOP), 0), IntegerEntry((((pool + "_") + toString(i.caller)) + keyUserSWOPClaimedAmount), userClaimedAmountNew), IntegerEntry((((pool + "_") + toString(i.caller)) + keyUserSWOPLastClaimedAmount), claimAmount), ScriptTransfer(i.caller, availableFund, SWOP)]
348+func keepLimitForFirstHarvest (shareLimit) = if (!(isActive))
349+ then throw("DApp is inactive at this moment")
350+ else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
351+ then throw("Only admin can call this function")
352+ else [IntegerEntry(kShareLimit, shareLimit)]
353+
354+
355+
356+@Callable(i)
357+func replenishWithTwoTokens (slippageTolerance) = {
358+ let pmtAssetIdA = i.payments[0].assetId
359+ let pmtAssetIdB = i.payments[1].assetId
360+ let pmtAmountA = deductStakingFee(i.payments[0].amount, pmtAssetIdA, pmtAssetIdB)
361+ let pmtAmountB = deductStakingFee(i.payments[1].amount, pmtAssetIdB, pmtAssetIdA)
362+ if (if ((balanceA == 0))
363+ then (balanceB == 0)
364+ else false)
365+ then {
366+ let $t01345913536 = getAssetInfo(pmtAssetIdA)
367+ let pmtStrAssetIdA = $t01345913536._1
368+ let pmtAssetNameA = $t01345913536._2
369+ let pmtDecimalsA = $t01345913536._3
370+ let $t01354513622 = getAssetInfo(pmtAssetIdB)
371+ let pmtStrAssetIdB = $t01354513622._1
372+ let pmtAssetNameB = $t01354513622._2
373+ let pmtDecimalsB = $t01354513622._3
374+ let tokenRatio = fraction(fraction(assetInitA, scaleValue8, pmtAmountA), scaleValue3, fraction(assetInitB, scaleValue8, pmtAmountB))
375+ if ((pmtAssetIdA == pmtAssetIdB))
376+ then throw("Assets must be different")
377+ else {
378+ let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
379+ let shareInitialSupply = fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN), pow(10, 0, shareDecimals, 0, 0, DOWN))
380+ if (!(isActive))
381+ then throw("DApp is inactive at this moment")
382+ else if (if ((0 > slippageTolerance))
383+ then true
384+ else (slippageTolerance > slippageToleranceDelimiter))
385+ then throw(((("Slippage tolerance must be between 0 and " + toString(slippageToleranceDelimiter)) + " inclusively. Actual: ") + toString(slippageTolerance)))
386+ else if ((size(i.payments) != 2))
387+ then throw("Two attached assets expected")
388+ else if (if ((((scaleValue3 * (slippageToleranceDelimiter - slippageTolerance)) / slippageToleranceDelimiter) > tokenRatio))
389+ then true
390+ else (tokenRatio > ((scaleValue3 * (slippageToleranceDelimiter + slippageTolerance)) / slippageToleranceDelimiter)))
391+ then throw("Incorrect assets amount: amounts must have the contract ratio")
392+ else if (if ((pmtAssetIdA != assetIdA))
393+ then true
394+ else (pmtAssetIdB != assetIdB))
395+ then throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
396+ else if ((shareInitialSupply == 0))
397+ then throw("Too small amount to replenish")
398+ else if (!(hasEnoughBalance))
399+ then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
400+ else [Reissue(shareAssetId, shareInitialSupply, true), IntegerEntry(keyBalanceA, pmtAmountA), IntegerEntry(keyBalanceB, pmtAmountB), IntegerEntry(keyShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareAssetId)]
401+ }
402+ }
403+ else {
404+ let tokenRatio = fraction(fraction(balanceA, scaleValue8, pmtAmountA), scaleValue3, fraction(balanceB, scaleValue8, pmtAmountB))
405+ let ratioShareTokensInA = fraction(pmtAmountA, scaleValue8, balanceA)
406+ let ratioShareTokensInB = fraction(pmtAmountB, scaleValue8, balanceB)
407+ let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scaleValue8)
408+ if (!(isActive))
409+ then throw("DApp is inactive at this moment")
410+ else if (if ((0 > slippageTolerance))
411+ then true
412+ else (slippageTolerance > slippageToleranceDelimiter))
413+ then throw(((("Slippage tolerance must be between 0 and " + toString(slippageToleranceDelimiter)) + " inclusively. Actual: ") + toString(slippageTolerance)))
414+ else if ((size(i.payments) != 2))
415+ then throw("Two attached assets expected")
416+ else if (if ((pmtAssetIdA != assetIdA))
417+ then true
418+ else (pmtAssetIdB != assetIdB))
419+ then throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
420+ else if (if ((((scaleValue3 * (slippageToleranceDelimiter - slippageTolerance)) / slippageToleranceDelimiter) > tokenRatio))
421+ then true
422+ else (tokenRatio > ((scaleValue3 * (slippageToleranceDelimiter + slippageTolerance)) / slippageToleranceDelimiter)))
423+ then throw("Incorrect assets amount: amounts must have the contract ratio")
424+ else if ((shareTokenToPayAmount == 0))
425+ then throw("Too small amount to replenish")
426+ else if (!(hasEnoughBalance))
427+ then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
428+ else [IntegerEntry(keyBalanceA, (balanceA + pmtAmountA)), IntegerEntry(keyBalanceB, (balanceB + pmtAmountB)), IntegerEntry(keyShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId)]
429+ }
430+ }
431+
432+
433+
434+@Callable(i)
435+func withdraw () = {
436+ let $t01802118171 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
437+ let pmtAmount = $t01802118171._1
438+ let pmtAssetId = $t01802118171._2
439+ let amountToPayA = deductStakingFee(fraction(pmtAmount, balanceA, shareAssetSupply), assetIdA, assetIdB)
440+ let amountToPayB = deductStakingFee(fraction(pmtAmount, balanceB, shareAssetSupply), assetIdB, assetIdA)
441+ if (!(isActive))
442+ then throw("DApp is inactive at this moment")
443+ else if ((size(i.payments) != 1))
444+ then throw("One attached payment expected")
445+ else if ((pmtAssetId != shareAssetId))
446+ then throw(("Incorrect asset attached. Expected: " + toBase58String(shareAssetId)))
447+ else if (!(hasEnoughBalance))
448+ then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
449+ else if (if ((amountToPayA > availableBalanceA))
450+ then true
451+ else (amountToPayB > availableBalanceB))
452+ then throwInsufficientAvailableBalances(amountToPayA, amountToPayB)
453+ 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)]
454+ }
455+
456+
457+
458+@Callable(i)
459+func exchange (minAmountToReceive) = {
460+ let $t01939719472 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
461+ let pmtAmount = $t01939719472._1
462+ let pmtAssetId = $t01939719472._2
463+ func calculateFees (tokenFrom,tokenTo) = {
464+ let amountWithoutFee = fraction(tokenTo, pmtAmount, (pmtAmount + tokenFrom))
465+ let amountWithFee = fraction(amountWithoutFee, (commissionScaleDelimiter - commission), commissionScaleDelimiter)
466+ let governanceReward = fraction(amountWithoutFee, commissionGovernance, commissionScaleDelimiter)
467+ if ((minAmountToReceive > amountWithFee))
468+ then throw(((("Calculated amount to receive " + toString(amountWithFee)) + " is less than specified minimum ") + toString(minAmountToReceive)))
469+ else $Tuple3(amountWithoutFee, amountWithFee, governanceReward)
470+ }
471+
472+ if (!(isActive))
473+ then throw("DApp is inactive at this moment")
474+ else if (if ((balanceA == 0))
475+ then true
476+ else (balanceB == 0))
477+ then throw("Can't exchange with zero balance")
478+ else if ((0 >= minAmountToReceive))
479+ then throw(("Minimal amount to receive must be positive. Actual: " + toString(minAmountToReceive)))
480+ else if ((size(i.payments) != 1))
481+ then throw("One attached payment expected")
482+ else if (!(hasEnoughBalance))
483+ then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
484+ else if ((pmtAssetId == assetIdA))
485+ then {
486+ let assetIdSend = assetIdB
487+ let $t02074620837 = calculateFees(balanceA, balanceB)
488+ let amountWithoutFee = $t02074620837._1
489+ let amountWithFee = $t02074620837._2
490+ let governanceReward = $t02074620837._3
491+ let newBalanceA = (balanceA + pmtAmount)
492+ let newBalanceB = ((balanceB - amountWithFee) - governanceReward)
493+ if (if ((stakedAmountA >= newBalanceA))
494+ then true
495+ else (stakedAmountB >= newBalanceB))
496+ then throwInsufficientAvailableBalance(amountWithFee, availableBalanceB, assetNameB)
497+ else [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)]
498+ }
499+ else if ((pmtAssetId == assetIdB))
500+ then {
501+ let assetIdSend = assetIdA
502+ let $t02165621747 = calculateFees(balanceB, balanceA)
503+ let amountWithoutFee = $t02165621747._1
504+ let amountWithFee = $t02165621747._2
505+ let governanceReward = $t02165621747._3
506+ let newBalanceA = ((balanceA - amountWithFee) - governanceReward)
507+ let newBalanceB = (balanceB + pmtAmount)
508+ if (if ((stakedAmountA >= newBalanceA))
509+ then true
510+ else (stakedAmountB >= newBalanceB))
511+ then throwInsufficientAvailableBalance(amountWithFee, availableBalanceA, assetNameA)
512+ else [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)]
513+ }
514+ else throw(((("Incorrect asset attached. Expected: " + strAssetIdA) + " or ") + strAssetIdB))
610515 }
611516
612517
613518
614519 @Callable(i)
615520 func shutdown () = if (!(isActive))
616521 then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, keyCause), "the cause wasn't specified")))
617- else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3], i.callerPublicKey)))
522+ else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStartStop], i.callerPublicKey)))
618523 then throw("Only admin can call this function")
619524 else suspend("Paused by admin")
620525
621526
622527
623528 @Callable(i)
624529 func activate () = if (isActive)
625530 then throw("DApp is already active")
626- else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3], i.callerPublicKey)))
531+ else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStartStop], i.callerPublicKey)))
627532 then throw("Only admin can call this function")
628533 else [BooleanEntry(keyActive, true), DeleteEntry(keyCause)]
629534
630535
536+
537+@Callable(i)
538+func takeIntoAccountExtraFunds (amountLeave) = {
539+ let uncountableAmountEnrollAssetA = (accountBalanceWithStakedA - balanceA)
540+ let uncountableAmountEnrollAssetB = (accountBalanceWithStakedB - balanceB)
541+ let amountEnrollA = (uncountableAmountEnrollAssetA - (if ((assetIdA == unit))
542+ then amountLeave
543+ else 0))
544+ let amountEnrollB = (uncountableAmountEnrollAssetB - (if ((assetIdB == unit))
545+ then amountLeave
546+ else 0))
547+ if (!(isActive))
548+ then throw("DApp is inactive at this moment")
549+ else if ((i.caller != this))
550+ then throw("Only the DApp itself can call this function")
551+ else if ((0 > amountLeave))
552+ then throw(("Argument 'amountLeave' cannot be negative. Actual: " + toString(amountLeave)))
553+ else if (if ((0 > uncountableAmountEnrollAssetA))
554+ then true
555+ else (0 > uncountableAmountEnrollAssetB))
556+ then suspend("Enroll amount negative")
557+ else if (if ((0 > amountEnrollA))
558+ then true
559+ else (0 > amountEnrollB))
560+ then throw("Too large amountLeave")
561+ else [IntegerEntry(keyBalanceA, (balanceA + amountEnrollA)), IntegerEntry(keyBalanceB, (balanceB + amountEnrollB)), IntegerEntry(("last_income_" + strAssetIdA), amountEnrollA), IntegerEntry(("last_income_" + strAssetIdB), amountEnrollB)]
562+ }
563+
564+
631565 @Verifier(tx)
632566 func verify () = match tx {
567+ case inv: InvokeScriptTransaction =>
568+ let callTakeIntoAccount = if ((inv.dApp == this))
569+ then (inv.function == "takeIntoAccountExtraFunds")
570+ else false
571+ let callStaking = if (if ((inv.dApp == stakingUSDNNSBTAddress))
572+ then if (if (if ((inv.function == "lockNeutrino"))
573+ then (size(inv.payments) == 1)
574+ else false)
575+ then if ((inv.payments[0].assetId == USDN))
576+ then true
577+ else (inv.payments[0].assetId == NSBT)
578+ else false)
579+ then true
580+ else if ((inv.function == "unlockNeutrino"))
581+ then (size(inv.payments) == 0)
582+ else false
583+ else false)
584+ then true
585+ else if ((inv.dApp == stakingEURNAddress))
586+ then if (if (if ((inv.function == "startStaking"))
587+ then (size(inv.payments) == 1)
588+ else false)
589+ then (inv.payments[0].assetId == EURN)
590+ else false)
591+ then true
592+ else if ((inv.function == "stopStaking"))
593+ then (size(inv.payments) == 0)
594+ else false
595+ else false
596+ let exchangeToWaves = if (if (if ((inv.dApp == USDNToWavesExchanger))
597+ then (inv.function == "exchange")
598+ else false)
599+ then (assetIdA == USDN)
600+ else false)
601+ then true
602+ else if (if ((assetIdB == USDN))
603+ then (size(inv.payments) == 1)
604+ else false)
605+ then (inv.payments[0].assetId == USDN)
606+ else false
607+ let exchangeToNSBTs = if (if (if ((inv.dApp == USDNToNSBTExchanger))
608+ then (inv.function == "exchange")
609+ else false)
610+ then (assetIdA == NSBT)
611+ else false)
612+ then true
613+ else if (if ((assetIdB == NSBT))
614+ then (size(inv.payments) == 1)
615+ else false)
616+ then (inv.payments[0].assetId == USDN)
617+ else false
618+ let signedByAdmin = if (if (if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
619+ then true
620+ else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey2))
621+ then true
622+ else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey3))
623+ then true
624+ else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKeyStaking)
625+ if (if (if (if (callTakeIntoAccount)
626+ then true
627+ else callStaking)
628+ then true
629+ else exchangeToWaves)
630+ then true
631+ else exchangeToNSBTs)
632+ then signedByAdmin
633+ else false
633634 case _ =>
634635 let adminPubKey1Signed = if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
635636 then 1
636637 else 0
637638 let adminPubKey2Signed = if (sigVerify(tx.bodyBytes, tx.proofs[1], adminPubKey2))
638639 then 1
639640 else 0
640641 let adminPubKey3Signed = if (sigVerify(tx.bodyBytes, tx.proofs[2], adminPubKey3))
641642 then 1
642643 else 0
643644 (((adminPubKey1Signed + adminPubKey2Signed) + adminPubKey3Signed) >= 2)
644645 }
645646

github/deemru/w8io/169f3d6 
99.95 ms