tx · 3rjxMpCVZhcGG6dFnmqwEPFBsH52PN8zHpANFzFgwc8z

3N6wAa7PMFZJu4Zrmp3avXmMnRTrRpMM9Lh:  -0.03800000 Waves

2023.02.27 15:30 [2468123] smart account 3N6wAa7PMFZJu4Zrmp3avXmMnRTrRpMM9Lh > SELF 0.00000000 Waves

{ "type": 13, "id": "3rjxMpCVZhcGG6dFnmqwEPFBsH52PN8zHpANFzFgwc8z", "fee": 3800000, "feeAssetId": null, "timestamp": 1677501126338, "version": 2, "chainId": 84, "sender": "3N6wAa7PMFZJu4Zrmp3avXmMnRTrRpMM9Lh", "senderPublicKey": "Cr8D7eozSzJh7XHsYTjBinPpo3SS83BrCGiBAJsjGxBo", "proofs": [ "Wb37WVVdPn1Uau1cxUaC25k1cT2qkdgDeYQhJTmjzduZz9ATKvfUgChENZfWQLiZdU5ANTJPo6BMhPXanSB4kiv" ], "script": "base64:BgLiLwgCEgUKAwEEARIHCgUBBAEIARIDCgEIEgASBAoCAQQSAwoBARIECgIBBBIECgIIARIECgIIARIECgIIARIFCgMBCAESABIECgIBARIDCgEBEgUKAwEBARIECgIICBIAEgASAwoBCBIFCgMBAQESBAoCAQESBAoCCAESBAoCCAgSCwoJCAEBAgECCAQEEgYKBAgIAQgSABIDCgEBEgMKAQESBAoCCAEiCmxQZGVjaW1hbHMiBnNjYWxlOCIMc2NhbGU4QmlnSW50IgdzY2FsZTE4Igp6ZXJvQmlnSW50IgRiaWcwIgRiaWcxIgRiaWcyIgt3YXZlc1N0cmluZyIDU0VQIgpQb29sQWN0aXZlIg9Qb29sUHV0RGlzYWJsZWQiE1Bvb2xNYXRjaGVyRGlzYWJsZWQiDFBvb2xTaHV0ZG93biIOaWR4UG9vbEFkZHJlc3MiDWlkeFBvb2xTdGF0dXMiEGlkeFBvb2xMUEFzc2V0SWQiDWlkeEFtdEFzc2V0SWQiD2lkeFByaWNlQXNzZXRJZCIOaWR4QW10QXNzZXREY20iEGlkeFByaWNlQXNzZXREY20iDmlkeElBbXRBc3NldElkIhBpZHhJUHJpY2VBc3NldElkIg1pZHhMUEFzc2V0RGNtIhJpZHhQb29sQW10QXNzZXRBbXQiFGlkeFBvb2xQcmljZUFzc2V0QW10IhFpZHhQb29sTFBBc3NldEFtdCIZaWR4RmFjdG9yeVN0YWtpbmdDb250cmFjdCIaaWR4RmFjdG9yeVNsaXBwYWdlQ29udHJhY3QiBXRvWDE4IgdvcmlnVmFsIg1vcmlnU2NhbGVNdWx0Igt0b1gxOEJpZ0ludCIHZnJvbVgxOCIDdmFsIg9yZXN1bHRTY2FsZU11bHQiDGZyb21YMThSb3VuZCIFcm91bmQiB3RvU2NhbGUiA2FtdCIIcmVzU2NhbGUiCGN1clNjYWxlIgNhYnMiCWFic0JpZ0ludCIMc3dhcENvbnRyYWN0IgJmYyIDbXBrIgRwbXBrIgJwbCICcGgiAWgiCXRpbWVzdGFtcCIDcGF1Igt1c2VyQWRkcmVzcyIEdHhJZCIDZ2F1IgJhYSICcGEiBmtleUZlZSIKZmVlRGVmYXVsdCIDZmVlIgZrZXlLTHAiFWtleUtMcFJlZnJlc2hlZEhlaWdodCISa2V5S0xwUmVmcmVzaERlbGF5IhZrTHBSZWZyZXNoRGVsYXlEZWZhdWx0Ig9rTHBSZWZyZXNoRGVsYXkiEGtleUZhY3RvcnlDb25maWciDWtleU1hdGNoZXJQdWIiKWtleU1hcHBpbmdQb29sQ29udHJhY3RBZGRyZXNzVG9Qb29sQXNzZXRzIhNwb29sQ29udHJhY3RBZGRyZXNzIg1rZXlQb29sQ29uZmlnIglpQW10QXNzZXQiC2lQcmljZUFzc2V0Ih9rZXlNYXBwaW5nc0Jhc2VBc3NldDJpbnRlcm5hbElkIgxiYXNlQXNzZXRTdHIiE2tleUFsbFBvb2xzU2h1dGRvd24iDWtleVBvb2xXZWlnaHQiD2NvbnRyYWN0QWRkcmVzcyIWa2V5QWxsb3dlZExwU2NyaXB0SGFzaCIWa2V5RmVlQ29sbGVjdG9yQWRkcmVzcyIPdGhyb3dPcmRlckVycm9yIgpvcmRlclZhbGlkIg5vcmRlclZhbGlkSW5mbyILc2VuZGVyVmFsaWQiDG1hdGNoZXJWYWxpZCIPZ2V0U3RyaW5nT3JGYWlsIgdhZGRyZXNzIgNrZXkiDGdldEludE9yRmFpbCIIdGhyb3dFcnIiA21zZyIGZm10RXJyIg9mYWN0b3J5Q29udHJhY3QiE2ZlZUNvbGxlY3RvckFkZHJlc3MiBWluRmVlIgFAIgZvdXRGZWUiEGlzR2xvYmFsU2h1dGRvd24iE2dldE1hdGNoZXJQdWJPckZhaWwiDWdldFBvb2xDb25maWciCGFtdEFzc2V0IgpwcmljZUFzc2V0IgxwYXJzZUFzc2V0SWQiBWlucHV0Ig9hc3NldElkVG9TdHJpbmciD3BhcnNlUG9vbENvbmZpZyIKcG9vbENvbmZpZyIQcG9vbENvbmZpZ1BhcnNlZCILJHQwODQ2OTg2MzUiDmNmZ1Bvb2xBZGRyZXNzIg1jZmdQb29sU3RhdHVzIgxjZmdMcEFzc2V0SWQiEGNmZ0Ftb3VudEFzc2V0SWQiD2NmZ1ByaWNlQXNzZXRJZCIWY2ZnQW1vdW50QXNzZXREZWNpbWFscyIVY2ZnUHJpY2VBc3NldERlY2ltYWxzIhBnZXRGYWN0b3J5Q29uZmlnIg9zdGFraW5nQ29udHJhY3QiEHNsaXBwYWdlQ29udHJhY3QiEWRhdGFQdXRBY3Rpb25JbmZvIg1pbkFtdEFzc2V0QW10Ig9pblByaWNlQXNzZXRBbXQiCG91dExwQW10IgVwcmljZSIdc2xpcHBhZ2VUb2xlcmFuY2VQYXNzZWRCeVVzZXIiFXNsaXBwYWdlVG9sZXJhbmNlUmVhbCIIdHhIZWlnaHQiC3R4VGltZXN0YW1wIhJzbGlwYWdlQW10QXNzZXRBbXQiFHNsaXBhZ2VQcmljZUFzc2V0QW10IhFkYXRhR2V0QWN0aW9uSW5mbyIOb3V0QW10QXNzZXRBbXQiEG91dFByaWNlQXNzZXRBbXQiB2luTHBBbXQiDWdldEFjY0JhbGFuY2UiB2Fzc2V0SWQiD2NhbGNQcmljZUJpZ0ludCIIcHJBbXRYMTgiCGFtQW10WDE4IhRjYWxjUHJpY2VCaWdJbnRSb3VuZCIQcHJpdmF0ZUNhbGNQcmljZSIKYW1Bc3NldERjbSIKcHJBc3NldERjbSIFYW1BbXQiBXByQW10Ig5hbXRBc3NldEFtdFgxOCIQcHJpY2VBc3NldEFtdFgxOCIKY2FsY1ByaWNlcyIFbHBBbXQiA2NmZyILYW10QXNzZXREY20iDXByaWNlQXNzZXREY20iCHByaWNlWDE4IghscEFtdFgxOCITbHBQcmljZUluQW1Bc3NldFgxOCITbHBQcmljZUluUHJBc3NldFgxOCIPY2FsY3VsYXRlUHJpY2VzIgZwcmljZXMiFGVzdGltYXRlR2V0T3BlcmF0aW9uIgZ0eElkNTgiCnBtdEFzc2V0SWQiCHBtdExwQW10IglscEFzc2V0SWQiCWFtQXNzZXRJZCIJcHJBc3NldElkIgpwb29sU3RhdHVzIgpscEVtaXNzaW9uIglhbUJhbGFuY2UiDGFtQmFsYW5jZVgxOCIJcHJCYWxhbmNlIgxwckJhbGFuY2VYMTgiC2N1clByaWNlWDE4IghjdXJQcmljZSILcG10THBBbXRYMTgiDWxwRW1pc3Npb25YMTgiC291dEFtQW10WDE4IgtvdXRQckFtdFgxOCIIb3V0QW1BbXQiCG91dFByQW10IgVzdGF0ZSIUZXN0aW1hdGVQdXRPcGVyYXRpb24iEXNsaXBwYWdlVG9sZXJhbmNlIgxpbkFtQXNzZXRBbXQiC2luQW1Bc3NldElkIgxpblByQXNzZXRBbXQiC2luUHJBc3NldElkIgppc0V2YWx1YXRlIgZlbWl0THAiDGFtQXNzZXRJZFN0ciIMcHJBc3NldElkU3RyIgtpQW10QXNzZXRJZCINaVByaWNlQXNzZXRJZCIOaW5BbUFzc2V0SWRTdHIiDmluUHJBc3NldElkU3RyIg9pbkFtQXNzZXRBbXRYMTgiD2luUHJBc3NldEFtdFgxOCIMdXNlclByaWNlWDE4IgNyZXMiC3NsaXBwYWdlWDE4IhRzbGlwcGFnZVRvbGVyYW5jZVgxOCIKcHJWaWFBbVgxOCIKYW1WaWFQclgxOCIMZXhwZWN0ZWRBbXRzIhFleHBBbXRBc3NldEFtdFgxOCITZXhwUHJpY2VBc3NldEFtdFgxOCIJY2FsY0xwQW10Ig5jYWxjQW1Bc3NldFBtdCIOY2FsY1ByQXNzZXRQbXQiDHNsaXBwYWdlQ2FsYyIJZW1pdExwQW10IgZhbURpZmYiBnByRGlmZiILY29tbW9uU3RhdGUiB2NhbGNLTHAiDWFtb3VudEJhbGFuY2UiDHByaWNlQmFsYW5jZSIQYW1vdW50QmFsYW5jZVgxOCIPcHJpY2VCYWxhbmNlWDE4Igp1cGRhdGVkS0xwIg5jYWxjQ3VycmVudEtMcCIQYW1vdW50QXNzZXREZWx0YSIPcHJpY2VBc3NldERlbHRhIhRscEFzc2V0RW1pc3Npb25EZWx0YSISYW1vdW50QXNzZXRCYWxhbmNlIhFwcmljZUFzc2V0QmFsYW5jZSIPbHBBc3NldEVtaXNzaW9uIgpjdXJyZW50S0xwIhJyZWZyZXNoS0xwSW50ZXJuYWwiF2Ftb3VudEFzc2V0QmFsYW5jZURlbHRhIhZwcmljZUFzc2V0QmFsYW5jZURlbHRhIgdhY3Rpb25zIhJ2YWxpZGF0ZVVwZGF0ZWRLTHAiBm9sZEtMcCIbdmFsaWRhdGVNYXRjaGVyT3JkZXJBbGxvd2VkIgVvcmRlciIRYW1vdW50QXNzZXRBbW91bnQiEHByaWNlQXNzZXRBbW91bnQiDSR0MDIxNTQxMjE3NTMiA2tMcCINJHQwMjIxOTMyMjI5MyINdW51c2VkQWN0aW9ucyIGa0xwTmV3Igxpc09yZGVyVmFsaWQiBGluZm8iCWNvbW1vbkdldCIBaSIDcG10IgZwbXRBbXQiCWNvbW1vblB1dCIKYW1Bc3NldFBtdCIKcHJBc3NldFBtdCIGZXN0UHV0IgRlbWl0IgZhbW91bnQiB2VtaXRJbnYiDWVtaXRJbnZMZWdhY3kiByRtYXRjaDAiFWxlZ2FjeUZhY3RvcnlDb250cmFjdCIHdGFrZUZlZSIJZmVlQW1vdW50Ig9jYWxjUHV0T25lVG9rZW4iEHBheW1lbnRBbW91bnRSYXciDnBheW1lbnRBc3NldElkIgZpc0V2YWwiEGFtb3VudEJhbGFuY2VSYXciD3ByaWNlQmFsYW5jZVJhdyIUcGF5bWVudEluQW1vdW50QXNzZXQiDSR0MDI1NDA2MjU2OTkiEGFtb3VudEJhbGFuY2VPbGQiD3ByaWNlQmFsYW5jZU9sZCINJHQwMjU3MDMyNTg1MiIUYW1vdW50QXNzZXRBbW91bnRSYXciE3ByaWNlQXNzZXRBbW91bnRSYXciDSR0MDI1OTg0MjYwNDgiDXBheW1lbnRBbW91bnQiEGFtb3VudEJhbGFuY2VOZXciD3ByaWNlQmFsYW5jZU5ldyILcHJpY2VOZXdYMTgiCHByaWNlTmV3Ig5wYXltZW50QmFsYW5jZSIUcGF5bWVudEJhbGFuY2VCaWdJbnQiDHN1cHBseUJpZ0ludCILY2hlY2hTdXBwbHkiDWRlcG9zaXRCaWdJbnQiC2lzc3VlQW1vdW50IgtwcmljZU9sZFgxOCIIcHJpY2VPbGQiBGxvc3MiDSR0MDI3NzI5Mjc4OTYiB2JhbGFuY2UiD2lzc3VlQW1vdW50Qm90aCIPY2FsY0dldE9uZVRva2VuIgpvdXRBc3NldElkIgZjaGVja3MiEG91dEluQW1vdW50QXNzZXQiDWJhbGFuY2VCaWdJbnQiGG91dEluQW1vdW50QXNzZXREZWNpbWFscyIMYW1CYWxhbmNlT2xkIgxwckJhbGFuY2VPbGQiCm91dEJhbGFuY2UiEG91dEJhbGFuY2VCaWdJbnQiDnJlZGVlbWVkQmlnSW50IglhbW91bnRSYXciDSR0MDI5OTc0MzAwMzAiC3RvdGFsQW1vdW50Ig0kdDAzMDAzNDMwMjYwIgtvdXRBbUFtb3VudCILb3V0UHJBbW91bnQiDGFtQmFsYW5jZU5ldyIMcHJCYWxhbmNlTmV3IhhhbW91bnRCb3RoSW5QYXltZW50QXNzZXQiFm1hbmFnZXJQdWJsaWNLZXlPclVuaXQiAXMiHXBlbmRpbmdNYW5hZ2VyUHVibGljS2V5T3JVbml0Iglpc01hbmFnZXIiAnBrIgttdXN0TWFuYWdlciICcGQiDWNsZWFuQW1vdW50SW4iCWlzUmV2ZXJzZSINZmVlUG9vbEFtb3VudCINJHQwMzE5NzczMjI4MiIIYXNzZXRPdXQiB2Fzc2V0SW4iEnBvb2xBc3NldEluQmFsYW5jZSITcG9vbEFzc2V0T3V0QmFsYW5jZSIJYW1vdW50T3V0IgRvbGRLIgRuZXdLIgZjaGVja0siDGFtb3VudE91dE1pbiIJYWRkcmVzc1RvIgtzd2FwQ29udGFjdCIIY2hlY2tNaW4iF3BlbmRpbmdNYW5hZ2VyUHVibGljS2V5IgtjaGVja0NhbGxlciIVY2hlY2tNYW5hZ2VyUHVibGljS2V5IgJwbSIFaGFzUE0iB2NoZWNrUE0iD3Nob3VsZEF1dG9TdGFrZSIEYW1JZCIEcHJJZCIMc2xpcHBhZ2VBSW52IgxzbGlwcGFnZVBJbnYiCmxwVHJhbnNmZXIiC3NscFN0YWtlSW52Ig0kdDAzNzE2NjM3NjI4IhFyZWZyZXNoS0xwQWN0aW9ucyIRaXNVcGRhdGVkS0xwVmFsaWQiC21heFNsaXBwYWdlIg0kdDAzODE5MDM4MjU1IgxtaW5PdXRBbW91bnQiCWF1dG9TdGFrZSIgaXNQb29sT25lVG9rZW5PcGVyYXRpb25zRGlzYWJsZWQiDWlzUHV0RGlzYWJsZWQiB3BheW1lbnQiDSR0MDM5NDQzMzk1OTUiBWJvbnVzIhNlbWl0QW1vdW50RXN0aW1hdGVkIgplbWl0QW1vdW50IghzdGFrZUludiIHc2VuZEZlZSINJHQwNDAxODE0MDM3OCINJHQwNDAzODE0MDQ4OSINJHQwNDA3OTU0MDk1MiINb3V0QXNzZXRJZFN0ciINaXNHZXREaXNhYmxlZCINJHQwNDE4Mzc0MTk5MCIPYW1vdW50RXN0aW1hdGVkIgdidXJuSW52Ig1hc3NldFRyYW5zZmVyIg0kdDA0MjQ5MDQyNzM3IhBmZWVBbW91bnRGb3JDYWxjIg0kdDA0Mjc0MDQyODQ4Ig0kdDA0MzEwNTQzMjYxIg11bnN0YWtlQW1vdW50Igp1bnN0YWtlSW52Ig0kdDA0NDE2NjQ0MzE3Ig0kdDA0NDgxMjQ1MDU5Ig0kdDA0NTA2MjQ1MTcwIglvdXRBbXRBbXQiFGJ1cm5MUEFzc2V0T25GYWN0b3J5Ig0kdDA0NjExNjQ2MTk4IhJub0xlc3NUaGVuQW10QXNzZXQiFG5vTGVzc1RoZW5QcmljZUFzc2V0Ig0kdDA0NzE0NzQ3MjI4Ig1jaGVja1BheW1lbnRzIg9jaGVja1Bvb2xTdGF0dXMiDSR0MDQ4MzU0NDg0MzUiFW5vTGVzc1RoZW5BbW91bnRBc3NldCIMY2hlY2tBbW91bnRzIg0kdDA0OTczMDQ5ODExIgthbXRBc3NldFN0ciINcHJpY2VBc3NldFN0ciIYbGFzdFJlZnJlc2hlZEJsb2NrSGVpZ2h0Ih1jaGVja0xhc3RSZWZyZXNoZWRCbG9ja0hlaWdodCINJHQwNTA5OTg1MTA2MiIQa0xwVXBkYXRlQWN0aW9ucyIKYW10QXNzZXRJZCIMcHJpY2VBc3NldElkIg1wb29sTFBCYWxhbmNlIhJhY2NBbXRBc3NldEJhbGFuY2UiFGFjY1ByaWNlQXNzZXRCYWxhbmNlIgpwcmljZXNMaXN0Ig9scEFtdEFzc2V0U2hhcmUiEWxwUHJpY2VBc3NldFNoYXJlIgpwb29sV2VpZ2h0IgxjdXJQcmljZUNhbGMiDGFtQmFsYW5jZVJhdyIMcHJCYWxhbmNlUmF3Ig9hbUJhbGFuY2VSYXdYMTgiD3ByQmFsYW5jZVJhd1gxOCIQcGF5bWVudExwQXNzZXRJZCIMcGF5bWVudExwQW10IgJ0eCIGdmVyaWZ5Ig90YXJnZXRQdWJsaWNLZXkiCm1hdGNoZXJQdWIiDSR0MDU5NzI0NTk3OTMiB25ld0hhc2giC2FsbG93ZWRIYXNoIgtjdXJyZW50SGFzaHMAAWEACAABYgCAwtcvAAFjCQC2AgEAgMLXLwABZAkAtgIBAICAkLu61q3wDQABZQkAtgIBAAAAAWYJALYCAQAAAAFnCQC2AgEAAQABaAkAtgIBAAIAAWkCBVdBVkVTAAFqAgJfXwABawABAAFsAAIAAW0AAwABbgAEAAFvAAEAAXAAAgABcQADAAFyAAQAAXMABQABdAAGAAF1AAcAAXYACAABdwAJAAF4AAoAAXkAAQABegACAAFBAAMAAUIAAQABQwAHAQFEAgFFAUYJALwCAwkAtgIBBQFFBQFkCQC2AgEFAUYBAUcCAUUBRgkAvAIDBQFFBQFkBQFGAQFIAgFJAUoJAKADAQkAvAIDBQFJCQC2AgEFAUoFAWQBAUsDAUkBSgFMCQCgAwEJAL0CBAUBSQkAtgIBBQFKBQFkBQFMAQFNAwFOAU8BUAkAawMFAU4FAU8FAVABAVEBAUkDCQBmAgAABQFJCQEBLQEFAUkFAUkBAVIBAUkDCQC/AgIFAWUFAUkJAL4CAQUBSQUBSQEBUwACECVzX19zd2FwQ29udHJhY3QBAVQAAhMlc19fZmFjdG9yeUNvbnRyYWN0AQFVAAIUJXNfX21hbmFnZXJQdWJsaWNLZXkBAVYAAhslc19fcGVuZGluZ01hbmFnZXJQdWJsaWNLZXkBAVcAAhElcyVzX19wcmljZV9fbGFzdAEBWAIBWQFaCQC5CQIJAMwIAgIYJXMlcyVkJWRfX3ByaWNlX19oaXN0b3J5CQDMCAIJAKQDAQUBWQkAzAgCCQCkAwEFAVoFA25pbAUBagECYWECAmFiAmFjCQCsAgIJAKwCAgkArAICAgslcyVzJXNfX1BfXwUCYWICAl9fBQJhYwECYWQCAmFiAmFjCQCsAgIJAKwCAgkArAICAgslcyVzJXNfX0dfXwUCYWICAl9fBQJhYwECYWUAAg8lc19fYW1vdW50QXNzZXQBAmFmAAIOJXNfX3ByaWNlQXNzZXQAAmFnAgclc19fZmVlAAJhaAkAawMACgUBYgCQTgACYWkJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUCYWcFAmFoAAJhagkAuQkCCQDMCAICAiVzCQDMCAICA2tMcAUDbmlsBQFqAAJhawkAuQkCCQDMCAICAiVzCQDMCAICEmtMcFJlZnJlc2hlZEhlaWdodAUDbmlsBQFqAAJhbAkAuQkCCQDMCAICAiVzCQDMCAICD3JlZnJlc2hLTHBEZWxheQUDbmlsBQFqAAJhbQAeAAJhbgkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQJhbAUCYW0BAmFvAAIRJXNfX2ZhY3RvcnlDb25maWcBAmFwAAIYJXMlc19fbWF0Y2hlcl9fcHVibGljS2V5AQJhcQECYXIJAKwCAgkArAICAgglcyVzJXNfXwUCYXICIF9fbWFwcGluZ3NfX3Bvb2xDb250cmFjdDJMcEFzc2V0AQJhcwICYXQCYXUJAKwCAgkArAICCQCsAgIJAKwCAgIIJWQlZCVzX18FAmF0AgJfXwUCYXUCCF9fY29uZmlnAQJhdgECYXcJAKwCAgIoJXMlcyVzX19tYXBwaW5nc19fYmFzZUFzc2V0MmludGVybmFsSWRfXwUCYXcBAmF4AAIMJXNfX3NodXRkb3duAQJheQECYXoJAKwCAgISJXMlc19fcG9vbFdlaWdodF9fBQJhegECYUEAAhclc19fYWxsb3dlZExwU2NyaXB0SGFzaAACYUICFyVzX19mZWVDb2xsZWN0b3JBZGRyZXNzAQJhQwQCYUQCYUUCYUYCYUcJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIkb3JkZXIgdmFsaWRhdGlvbiBmYWlsZWQ6IG9yZGVyVmFsaWQ9CQClAwEFAmFEAgIgKAUCYUUCASkCDSBzZW5kZXJWYWxpZD0JAKUDAQUCYUYCDiBtYXRjaGVyVmFsaWQ9CQClAwEFAmFHAQJhSAICYUkCYUoJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQJhSQUCYUoJALkJAgkAzAgCAgptYW5kYXRvcnkgCQDMCAIJAKUIAQUCYUkJAMwIAgIBLgkAzAgCBQJhSgkAzAgCAg8gaXMgbm90IGRlZmluZWQFA25pbAIAAQJhSwICYUkCYUoJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQJhSQUCYUoJALkJAgkAzAgCAgptYW5kYXRvcnkgCQDMCAIJAKUIAQUCYUkJAMwIAgIBLgkAzAgCBQJhSgkAzAgCAg8gaXMgbm90IGRlZmluZWQFA25pbAIAAQJhTAECYU0JAAIBCQC5CQIJAMwIAgIIbHAucmlkZToJAMwIAgUCYU0FA25pbAIBIAECYU4BAmFNCQC5CQIJAMwIAgIIbHAucmlkZToJAMwIAgUCYU0FA25pbAIBIAACYU8JARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQJhSAIFBHRoaXMJAQFUAAACYVAJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQJhSAIFAmFPBQJhQgACYVEKAAJhUgkA/AcEBQJhTwIQZ2V0SW5GZWVSRUFET05MWQkAzAgCCQClCAEFBHRoaXMFA25pbAUDbmlsAwkAAQIFAmFSAgNJbnQFAmFSCQACAQkArAICCQADAQUCYVICGCBjb3VsZG4ndCBiZSBjYXN0IHRvIEludAACYVMKAAJhUgkA/AcEBQJhTwIRZ2V0T3V0RmVlUkVBRE9OTFkJAMwIAgkApQgBBQR0aGlzBQNuaWwFA25pbAMJAAECBQJhUgIDSW50BQJhUgkAAgEJAKwCAgkAAwEFAmFSAhggY291bGRuJ3QgYmUgY2FzdCB0byBJbnQBAmFUAAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQJhTwkBAmF4AAcBAmFVAAkA2QQBCQECYUgCBQJhTwkBAmFwAAECYVYABAJhVwkBAmFIAgUEdGhpcwkBAmFlAAQCYVgJAQJhSAIFBHRoaXMJAQJhZgAEAmF1CQECYUsCBQJhTwkBAmF2AQUCYVgEAmF0CQECYUsCBQJhTwkBAmF2AQUCYVcJALUJAgkBAmFIAgUCYU8JAQJhcwIJAKQDAQUCYXQJAKQDAQUCYXUFAWoBAmFZAQJhWgMJAAACBQJhWgUBaQUEdW5pdAkA2QQBBQJhWgECYmEBAmFaAwkAAAIFAmFaBQR1bml0BQFpCQDYBAEJAQV2YWx1ZQEFAmFaAQJiYgECYmMJAJkKBwkBEUBleHRyTmF0aXZlKDEwNjIpAQkAkQMCBQJiYwUBbwkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmJjBQFwCQDZBAEJAJEDAgUCYmMFAXEJAQJhWQEJAJEDAgUCYmMFAXIJAQJhWQEJAJEDAgUCYmMFAXMJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJiYwUBdAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmJjBQF1AAJiZAkBAmJiAQkBAmFWAAACYmUFAmJkAAJiZggFAmJlAl8xAAJiZwgFAmJlAl8yAAJiaAgFAmJlAl8zAAJiaQgFAmJlAl80AAJiaggFAmJlAl81AAJiawgFAmJlAl82AAJibAgFAmJlAl83AQJibQAJALUJAgkBAmFIAgUCYU8JAQJhbwAFAWoAAmJuCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkAkQMCCQECYm0ABQFCAhlpbmNvcnJlY3Qgc3Rha2luZyBhZGRyZXNzAAJibwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJAJEDAgkBAmJtAAUBQwIZaW5jb3JyZWN0IHN0YWtpbmcgYWRkcmVzcwECYnAKAmJxAmJyAmJzAmJ0AmJ1AmJ2AmJ3AmJ4AmJ5AmJ6CQC5CQIJAMwIAgIUJWQlZCVkJWQlZCVkJWQlZCVkJWQJAMwIAgkApAMBBQJicQkAzAgCCQCkAwEFAmJyCQDMCAIJAKQDAQUCYnMJAMwIAgkApAMBBQJidAkAzAgCCQCkAwEFAmJ1CQDMCAIJAKQDAQUCYnYJAMwIAgkApAMBBQJidwkAzAgCCQCkAwEFAmJ4CQDMCAIJAKQDAQUCYnkJAMwIAgkApAMBBQJiegUDbmlsBQFqAQJiQQYCYkICYkMCYkQCYnQCYncCYngJALkJAgkAzAgCAgwlZCVkJWQlZCVkJWQJAMwIAgkApAMBBQJiQgkAzAgCCQCkAwEFAmJDCQDMCAIJAKQDAQUCYkQJAMwIAgkApAMBBQJidAkAzAgCCQCkAwEFAmJ3CQDMCAIJAKQDAQUCYngFA25pbAUBagECYkUBAmJGAwkAAAIFAmJGAgVXQVZFUwgJAO8HAQUEdGhpcwlhdmFpbGFibGUJAPAHAgUEdGhpcwkA2QQBBQJiRgECYkcCAmJIAmJJCQC8AgMFAmJIBQFkBQJiSQECYkoDAmJIAmJJAUwJAL0CBAUCYkgFAWQFAmJJBQFMAQJiSwQCYkwCYk0CYk4CYk8EAmJQCQEBRAIFAmJOBQJiTAQCYlEJAQFEAgUCYk8FAmJNCQECYkcCBQJiUQUCYlABAmJSAwJiTgJiTwJiUwQCYlQJAQJhVgAEAmJVCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCYlQFAXQEAmJWCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCYlQFAXUEAmJXCQECYksEBQJiVQUCYlYFAmJOBQJiTwQCYkkJAQFEAgUCYk4FAmJVBAJiSAkBAUQCBQJiTwUCYlYEAmJYCQEBRAIFAmJTBQFiBAJiWQkBAmJHAgUCYkkFAmJYBAJiWgkBAmJHAgUCYkgFAmJYCQDMCAIFAmJXCQDMCAIFAmJZCQDMCAIFAmJaBQNuaWwBAmNhAwJiTgJiTwJiUwQCY2IJAQJiUgMFAmJOBQJiTwUCYlMJAMwIAgkBAUgCCQCRAwIFAmNiAAAFAWIJAMwIAgkBAUgCCQCRAwIFAmNiAAEFAWIJAMwIAgkBAUgCCQCRAwIFAmNiAAIFAWIFA25pbAECY2MEAmNkAmNlAmNmAmFiBAJiVAkBAmFWAAQCY2cJAJEDAgUCYlQFAXEEAmNoCQCRAwIFAmJUBQFyBAJjaQkAkQMCBQJiVAUBcwQCYkwJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJiVAUBdAQCYk0JAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJiVAUBdQQCY2oJAJEDAgUCYlQFAXAEAmNrCAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQDsBwEJANkEAQUCY2cJAKwCAgkArAICAgZBc3NldCAFAmNnAg4gZG9lc24ndCBleGlzdAhxdWFudGl0eQMJAQIhPQIFAmNnBQJjZQkAAgECFUludmFsaWQgYXNzZXQgcGFzc2VkLgQCY2wJAQJiRQEFAmNoBAJjbQkBAUQCBQJjbAUCYkwEAmNuCQECYkUBBQJjaQQCY28JAQFEAgUCY24FAmJNBAJjcAkBAmJHAgUCY28FAmNtBAJjcQkBAUgCBQJjcAUBYgQCY3IJAQFEAgUCY2YFAWIEAmNzCQEBRAIFAmNrBQFiBAJjdAkAvAIDBQJjbQUCY3IFAmNzBAJjdQkAvAIDBQJjbwUCY3IFAmNzBAJjdgkBAUsDBQJjdAUCYkwFBUZMT09SBAJjdwkBAUsDBQJjdQUCYk0FBUZMT09SBAJjeAMJAAACBQJjZAIABQNuaWwJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUCYWIFAmN2AwkAAAIFAmNoAgVXQVZFUwUEdW5pdAkA2QQBBQJjaAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQJhYgUCY3cDCQAAAgUCY2kCBVdBVkVTBQR1bml0CQDZBAEFAmNpCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQJhZAIJAKUIAQUCYWIFAmNkCQECYkEGBQJjdgUCY3cFAmNmBQJjcQUGaGVpZ2h0CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAVcABQJjcQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAVgCBQZoZWlnaHQIBQlsYXN0QmxvY2sJdGltZXN0YW1wBQJjcQUDbmlsCQCcCgoFAmN2BQJjdwUCY2gFAmNpBQJjbAUCY24FAmNrBQJjcAUCY2oFAmN4AQJjeQkCY2QCY3oCY0ECY0ICY0MCY0QCYWICY0UCY0YEAmJUCQECYVYABAJjZwkA2QQBCQCRAwIFAmJUBQFxBAJjRwkAkQMCBQJiVAUBcgQCY0gJAJEDAgUCYlQFAXMEAmNJCQCRAwIFAmJUBQF2BAJjSgkAkQMCBQJiVAUBdwQCYlUJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJiVAUBdAQCYlYJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJiVAUBdQQCY2oJAJEDAgUCYlQFAXAEAmNrCAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQDsBwEFAmNnCQCsAgIJAKwCAgIGQXNzZXQgCQDYBAEFAmNnAg4gZG9lc24ndCBleGlzdAhxdWFudGl0eQQCY0sJANgEAQkBC3ZhbHVlT3JFbHNlAgUCY0IJANkEAQIFV0FWRVMEAmNMCQDYBAEJAQt2YWx1ZU9yRWxzZQIFAmNECQDZBAECBVdBVkVTAwMJAQIhPQIFAmNHBQJjSwYJAQIhPQIFAmNIBQJjTAkAAgECIkludmFsaWQgYW10IG9yIHByaWNlIGFzc2V0IHBhc3NlZC4EAmNsAwUCY0UJAQJiRQEFAmNHCQBlAgkBAmJFAQUCY0cFAmNBBAJjbgMFAmNFCQECYkUBBQJjSAkAZQIJAQJiRQEFAmNIBQJjQwQCY00JAQFEAgUCY0EFAmJVBAJjTgkBAUQCBQJjQwUCYlYEAmNPCQECYkcCBQJjTgUCY00EAmNtCQEBRAIFAmNsBQJiVQQCY28JAQFEAgUCY24FAmJWBAJjUAMJAAACBQJjawAABAJjcAUBZQQCY1EFAWUEAmJYCQB2BgkAuQICBQJjTQUCY04AAAkAtgIBAAUAAQAABQRET1dOCQCXCgUJAQFIAgUCYlgFAWIJAQFIAgUCY00FAmJVCQEBSAIFAmNOBQJiVgkBAmJHAgkAtwICBQJjbwUCY04JALcCAgUCY20FAmNNBQJjUQQCY3AJAQJiRwIFAmNvBQJjbQQCY1EJALwCAwkBAVIBCQC4AgIFAmNwBQJjTwUBZAUCY3AEAmNSCQEBRAIFAmN6BQFiAwMJAQIhPQIFAmNwBQFlCQC/AgIFAmNRBQJjUgcJAAIBCQCsAgIJAKwCAgkArAICAg9QcmljZSBzbGlwcGFnZSAJAKYDAQUCY1ECHiBleGNlZWRlZCB0aGUgcGFzc2VkIGxpbWl0IG9mIAkApgMBBQJjUgQCY3MJAQFEAgUCY2sFAWIEAmNTCQC9AgQFAmNNCQECYkoDBQJjbwUCY20FB0NFSUxJTkcFAWQFB0NFSUxJTkcEAmNUCQC9AgQFAmNOBQFkCQECYkoDBQJjbwUCY20FBUZMT09SBQdDRUlMSU5HBAJjVQMJAL8CAgUCY1MFAmNOCQCUCgIFAmNUBQJjTgkAlAoCBQJjTQUCY1MEAmNWCAUCY1UCXzEEAmNXCAUCY1UCXzIEAmJYCQC9AgQFAmNzBQJjVwUCY28FBUZMT09SCQCXCgUJAQFLAwUCYlgFAWIFBUZMT09SCQEBSwMFAmNWBQJiVQUHQ0VJTElORwkBAUsDBQJjVwUCYlYFB0NFSUxJTkcFAmNwBQJjUQQCY1gIBQJjUAJfMQQCY1kIBQJjUAJfMgQCY1oIBQJjUAJfMwQCY3EJAQFIAggFAmNQAl80BQFiBAJkYQkBAUgCCAUCY1ACXzUFAWIDCQBnAgAABQJjWAkAAgECNkludmFsaWQgY2FsY3VsYXRpb25zLiBMUCBjYWxjdWxhdGVkIGlzIGxlc3MgdGhhbiB6ZXJvLgQCZGIDCQEBIQEFAmNGAAAFAmNYBAJkYwkAZQIFAmNBBQJjWQQCZGQJAGUCBQJjQwUCY1oEAmRlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEBVwAFAmNxCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEBWAIFBmhlaWdodAgFCWxhc3RCbG9jawl0aW1lc3RhbXAFAmNxCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQJhYQIFAmFiBQJjZAkBAmJwCgUCY1kFAmNaBQJkYgUCY3EFAmN6BQJkYQUGaGVpZ2h0CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAUCZGMFAmRkBQNuaWwJAJ8KDQUCY1gFAmRiBQJjcQUCY2wFAmNuBQJjawUCY2cFAmNqBQJkZQUCZGMFAmRkBQJjQgUCY0QBAmRmAwJkZwJkaAJjawQCZGkJAQFHAgUCZGcJALYCAQUCYmsEAmRqCQEBRwIFAmRoCQC2AgEFAmJsBAJkawkAvAIDCQB2BgkAuQICBQJkaQUCZGoAAAkAtgIBAAUAAQASBQRET1dOBQFnBQJjawMJAAACBQJjawUBZgUBZgUCZGsBAmRsAwJkbQJkbgJkbwQCZHAJALgCAgkAtgIBCQECYkUBCQECYmEBBQJiaQUCZG0EAmRxCQC4AgIJALYCAQkBAmJFAQkBAmJhAQUCYmoFAmRuBAJkcgkAuAICCQC2AgEICQEFdmFsdWUBCQDsBwEFAmJoCHF1YW50aXR5BQJkbwQCZHMJAQJkZgMFAmRwBQJkcQUCZHIFAmRzAQJkdAMCZHUCZHYCZG8EAmRwCQBkAgkBAmJFAQkBAmJhAQUCYmkFAmR1BAJkcQkAZAIJAQJiRQEJAQJiYQEFAmJqBQJkdgQCZHIJAGQCCAkBBXZhbHVlAQkA7AcBBQJiaAhxdWFudGl0eQUCZG8EAmRrCQECZGYDCQC2AgEFAmRwCQC2AgEFAmRxCQC2AgEFAmRyBAJkdwkAzAgCCQEMSW50ZWdlckVudHJ5AgUCYWsFBmhlaWdodAkAzAgCCQELU3RyaW5nRW50cnkCBQJhagkApgMBBQJkawUDbmlsCQCUCgIFAmR3BQJkawECZHgCAmR5AmRrAwkAwAICBQJkawUCZHkGCQECYUwBCQC5CQIJAMwIAgIidXBkYXRlZCBLTHAgbG93ZXIgdGhhbiBjdXJyZW50IEtMcAkAzAgCCQCmAwEFAmR5CQDMCAIJAKYDAQUCZGsFA25pbAIBIAECZHoBAmRBBAJkcAkBAmJFAQkBAmJhAQUCYmkEAmRxCQECYkUBCQECYmEBBQJiagQCZEIIBQJkQQZhbW91bnQEAmRDCQBuBAgFAmRBBmFtb3VudAgFAmRBBXByaWNlBQFiBQVGTE9PUgQCZEQDCQAAAggFAmRBCW9yZGVyVHlwZQUDQnV5CQCUCgIFAmRCCQEBLQEFAmRDCQCUCgIJAQEtAQUCZEIFAmRDBAJkdQgFAmREAl8xBAJkdggFAmREAl8yAwMDCQECYVQABgkAAAIFAmJnBQFtBgkAAAIFAmJnBQFuCQACAQIcRXhjaGFuZ2Ugb3BlcmF0aW9ucyBkaXNhYmxlZAMDCQECIT0CCAgFAmRBCWFzc2V0UGFpcgthbW91bnRBc3NldAUCYmkGCQECIT0CCAgFAmRBCWFzc2V0UGFpcgpwcmljZUFzc2V0BQJiagkAAgECE1dyb25nIG9yZGVyIGFzc2V0cy4EAmRFCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKgDAQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzBQJhagIBMAkBAmFOAQILaW52YWxpZCBrTHAEAmRGCQECZHQDBQJkdQUCZHYAAAQCZEcIBQJkRgJfMQQCZEgIBQJkRgJfMgQCZEkJAMACAgUCZEgFAmRFBAJkSgkAuQkCCQDMCAICBGtMcD0JAMwIAgkApgMBBQJkRQkAzAgCAggga0xwTmV3PQkAzAgCCQCmAwEFAmRICQDMCAICFCBhbW91bnRBc3NldEJhbGFuY2U9CQDMCAIJAKQDAQUCZHAJAMwIAgITIHByaWNlQXNzZXRCYWxhbmNlPQkAzAgCCQCkAwEFAmRxCQDMCAICGSBhbW91bnRBc3NldEJhbGFuY2VEZWx0YT0JAMwIAgkApAMBBQJkdQkAzAgCAhggcHJpY2VBc3NldEJhbGFuY2VEZWx0YT0JAMwIAgkApAMBBQJkdgkAzAgCAgggaGVpZ2h0PQkAzAgCCQCkAwEFBmhlaWdodAUDbmlsAgAJAJQKAgUCZEkFAmRKAQJkSwECZEwDCQECIT0CCQCQAwEIBQJkTAhwYXltZW50cwABCQACAQIdZXhhY3RseSAxIHBheW1lbnQgaXMgZXhwZWN0ZWQEAmRNCQEFdmFsdWUBCQCRAwIIBQJkTAhwYXltZW50cwAABAJjZQkBBXZhbHVlAQgFAmRNB2Fzc2V0SWQEAmROCAUCZE0GYW1vdW50BAJjUAkBAmNjBAkA2AQBCAUCZEwNdHJhbnNhY3Rpb25JZAkA2AQBBQJjZQUCZE4IBQJkTAZjYWxsZXIEAmN2CAUCY1ACXzEEAmN3CAUCY1ACXzIEAmNqCQENcGFyc2VJbnRWYWx1ZQEIBQJjUAJfOQQCY3gIBQJjUANfMTADAwkBAmFUAAYJAAACBQJjagUBbgkAAgEJAKwCAgIsR2V0IG9wZXJhdGlvbiBpcyBibG9ja2VkIGJ5IGFkbWluLiBTdGF0dXMgPSAJAKQDAQUCY2oJAJcKBQUCY3YFAmN3BQJkTgUCY2UFAmN4AQJkTwMCZEwCY3oCY0YDCQECIT0CCQCQAwEIBQJkTAhwYXltZW50cwACCQACAQIfZXhhY3RseSAyIHBheW1lbnRzIGFyZSBleHBlY3RlZAQCZFAJAQV2YWx1ZQEJAJEDAggFAmRMCHBheW1lbnRzAAAEAmRRCQEFdmFsdWUBCQCRAwIIBQJkTAhwYXltZW50cwABBAJkUgkBAmN5CQkA2AQBCAUCZEwNdHJhbnNhY3Rpb25JZAUCY3oIBQJkUAZhbW91bnQIBQJkUAdhc3NldElkCAUCZFEGYW1vdW50CAUCZFEHYXNzZXRJZAkApQgBCAUCZEwGY2FsbGVyBwUCY0YEAmNqCQENcGFyc2VJbnRWYWx1ZQEIBQJkUgJfOAMDAwkBAmFUAAYJAAACBQJjagUBbAYJAAACBQJjagUBbgkAAgEJAKwCAgIsUHV0IG9wZXJhdGlvbiBpcyBibG9ja2VkIGJ5IGFkbWluLiBTdGF0dXMgPSAJAKQDAQUCY2oFAmRSAQJkUwECZFQEAmRVCQD8BwQFAmFPAgRlbWl0CQDMCAIFAmRUBQNuaWwFA25pbAMJAAACBQJkVQUCZFUEAmRWBAJkVwUCZFUDCQABAgUCZFcCB0FkZHJlc3MEAmRYBQJkVwkA/AcEBQJkWAIEZW1pdAkAzAgCBQJkVAUDbmlsBQNuaWwFBHVuaXQDCQAAAgUCZFYFAmRWBQJkVAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgECZFkCAmRUAmFpBAJkWgMJAAACBQJhaQAAAAAJAGsDBQJkVAUCYWkFAWIJAJQKAgkAZQIFAmRUBQJkWgUCZFoBAmVhBAJlYgJlYwJhYgJhYwQCZWQJAAACBQJhYwUEdW5pdAQCZWUJAQJiRQEJAQJiYQEFAmJpBAJlZgkBAmJFAQkBAmJhAQUCYmoEAmVnAwkAAAIFAmVjBQJiaQYDCQAAAgUCZWMFAmJqBwkBAmFMAQINaW52YWxpZCBhc3NldAQCZWgDBQJlZAkAlAoCBQJlZQUCZWYDBQJlZwkAlAoCCQBlAgUCZWUFAmViBQJlZgkAlAoCBQJlZQkAZQIFAmVmBQJlYgQCZWkIBQJlaAJfMQQCZWoIBQJlaAJfMgQCZWsDBQJlZwkAlAoCBQJlYgAACQCUCgIAAAUCZWIEAmVsCAUCZWsCXzEEAmVtCAUCZWsCXzIEAmRCCAkBAmRZAgUCZWwFAmFRAl8xBAJkQwgJAQJkWQIFAmVtBQJhUQJfMQQCZW4JAQJkWQIFAmViBQJhUQQCZW8IBQJlbgJfMQQCZFoIBQJlbgJfMgQCZXAJAGQCBQJlaQUCZEIEAmVxCQBkAgUCZWoFAmRDBAJlcgkBAmJHAgkBAUQCBQJlcQUCYmwJAQFEAgUCZXAFAmJrBAJlcwkBAUgCBQJlcgUBYgQCZXQDBQJlZwUCZWkFAmVqBAJldQkAtgIBBQJldAQCZXYJALYCAQgJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkA7AcBBQJiaAkArAICCQCsAgICBmFzc2V0IAkA2AQBBQJiaAIOIGRvZXNuJ3QgZXhpc3QIcXVhbnRpdHkEAmV3AwkAvwICBQJldgUBZgYJAQJhTAECImluaXRpYWwgZGVwb3NpdCByZXF1aXJlcyBhbGwgY29pbnMDCQAAAgUCZXcFAmV3BAJleAkAtgIBBQJlbwQCZXkJAJYDAQkAzAgCAAAJAMwIAgkAoAMBCQC6AgIJALkCAgUCZXYJALgCAgkBCnNxcnRCaWdJbnQECQC3AgIFAWQJALoCAgkAuQICBQJleAUBZAUCZXUAEgASBQRET1dOBQFkBQFkBQNuaWwEAmRlAwUCZWQFA25pbAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAVcABQJlcwkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAVgCBQZoZWlnaHQIBQlsYXN0QmxvY2sJdGltZXN0YW1wBQJlcwkAzAgCCQELU3RyaW5nRW50cnkCCQECYWECCQClCAEJAQV2YWx1ZQEFAmFiCQDYBAEJAQV2YWx1ZQEFAmFjCQECYnAKBQJlbAUCZW0FAmV5BQJlcwAAAAAFBmhlaWdodAgFCWxhc3RCbG9jawl0aW1lc3RhbXAAAAAABQNuaWwEAmV6CQECYkcCCQEBRAIFAmVqBQJibAkBAUQCBQJlaQUCYmsEAmVBCQEBSAIFAmV6BQFiBAJlQgQCZUMDBQJlZwkAlAoCBQJlbAUCZWkJAJQKAgUCZW0FAmVqBAJkVAgFAmVDAl8xBAJlRAgFAmVDAl8yBAJlRQkAoAMBCQC8AgMFAmV2CQC2AgEJAGkCBQJkVAACCQC2AgEFAmVECQBrAwkAZQIFAmV5BQJlRQUBYgUCZUUJAJcKBQUCZXkFAmRlBQJkWgUCZUIFAmVnCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQJlRgUCZUcCZW8CZWMCYWICYWMEAmVkCQAAAgUCYWMFBHVuaXQEAmJUCQECYVYABAJiVQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmJUBQF0BAJiVgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmJUBQF1BAJlSAkAzAgCAwkAAAIFAmVjBQJiaAYJAQJhTAECEGludmFsaWQgbHAgYXNzZXQFA25pbAMJAAACBQJlSAUCZUgEAmVJAwkAAAIFAmVHBQJiaQYDCQAAAgUCZUcFAmJqBwkBAmFMAQINaW52YWxpZCBhc3NldAQCZUoDBQJlSQkAtgIBCQECYkUBCQECYmEBBQJiaQkAtgIBCQECYkUBCQECYmEBBQJiagQCZUsDBQJlSQUCYlUFAmJWBAJlTAkBAmJFAQkBAmJhAQUCYmkEAmVNCQECYkUBCQECYmEBBQJiagQCZU4DBQJlSQUCZUwFAmVNBAJlTwkAtgIBBQJlTgQCZXYJALYCAQgJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkA7AcBBQJiaAkArAICCQCsAgICBmFzc2V0IAkA2AQBBQJiaAIOIGRvZXNuJ3QgZXhpc3QIcXVhbnRpdHkEAmVQCQC2AgEFAmVvBAJlUQkAlgMBCQDMCAIAAAkAzAgCCQCgAwEJALoCAgkAuQICBQJlSgkAuAICBQFkCQB2BgkAuAICBQFkCQC6AgIJALkCAgUCZVAFAWQFAmV2ABIFAWgAAAASBQRET1dOBQFkBQNuaWwEAmVSCQECZFkCBQJlUQUCYVMEAmVTCAUCZVICXzEEAmRaCAUCZVICXzIEAmVUAwUCZUkJAJYKBAUCZVMAAAkAZQIFAmVMBQJlUQUCZU0JAJYKBAAABQJlUwUCZUwJAGUCBQJlTQUCZVEEAmVVCAUCZVQCXzEEAmVWCAUCZVQCXzIEAmVXCAUCZVQCXzMEAmVYCAUCZVQCXzQEAmVyCQECYkcCCQEBRAIFAmVYBQJibAkBAUQCBQJlVwUCYmsEAmVzCQEBSAIFAmVyBQFiBAJkZQMFAmVkBQNuaWwJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAmFkAgkApQgBCQEFdmFsdWUBBQJhYgkA2AQBCQEFdmFsdWUBBQJhYwkBAmJBBgUCZVUFAmVWBQJlbwUCZXMFBmhlaWdodAgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAMwIAgkBDEludGVnZXJFbnRyeQIJAQFXAAUCZXMJAMwIAgkBDEludGVnZXJFbnRyeQIJAQFYAgUGaGVpZ2h0CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAUCZXMFA25pbAQCZXoJAQJiRwIJAQFEAgUCZU0FAmJsCQEBRAIFAmVMBQJiawQCZUEJAQFIAgUCZXoFAWIEAmVCBAJlWQkAaAIJAKADAQkAvAIDBQJlSgUCZVAFAmV2AAIJAGsDCQBlAgUCZVMFAmVZBQFiBQJlWQkAlwoFBQJlUwUCZGUFAmRaBQJlQgUCZUkJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BAmVaAAQCZFcJAKIIAQkBAVUAAwkAAQIFAmRXAgZTdHJpbmcEAmZhBQJkVwkA2QQBBQJmYQMJAAECBQJkVwIEVW5pdAUEdW5pdAkAAgECC01hdGNoIGVycm9yAQJmYgAEAmRXCQCiCAEJAQFWAAMJAAECBQJkVwIGU3RyaW5nBAJmYQUCZFcJANkEAQUCZmEDCQABAgUCZFcCBFVuaXQFBHVuaXQJAAIBAgtNYXRjaCBlcnJvcgECZmMBAmRMBAJkVwkBAmVaAAMJAAECBQJkVwIKQnl0ZVZlY3RvcgQCZmQFAmRXCQAAAggFAmRMD2NhbGxlclB1YmxpY0tleQUCZmQDCQABAgUCZFcCBFVuaXQJAAACCAUCZEwGY2FsbGVyBQR0aGlzCQACAQILTWF0Y2ggZXJyb3IBAmZlAQJkTAQCZmYJAAIBAhFQZXJtaXNzaW9uIGRlbmllZAQCZFcJAQJlWgADCQABAgUCZFcCCkJ5dGVWZWN0b3IEAmZkBQJkVwMJAAACCAUCZEwPY2FsbGVyUHVibGljS2V5BQJmZAYFAmZmAwkAAQIFAmRXAgRVbml0AwkAAAIIBQJkTAZjYWxsZXIFBHRoaXMGBQJmZgkAAgECC01hdGNoIGVycm9yHQJkTAEhY2FsY3VsYXRlQW1vdW50T3V0Rm9yU3dhcFJFQURPTkxZAwJmZwJmaAJmaQQCZmoDCQAAAgUCZmgHBAJmawkBAmFIAgUEdGhpcwkBAmFmAAQCZmwJAQJhSAIFBHRoaXMJAQJhZQAJAJQKAgUCZmsFAmZsBAJmawkBAmFIAgUEdGhpcwkBAmFlAAQCZmwJAQJhSAIFBHRoaXMJAQJhZgAJAJQKAgUCZmsFAmZsBAJmawgFAmZqAl8xBAJmbAgFAmZqAl8yBAJmbQkBAmJFAQUCZmwEAmZuCQECYkUBBQJmawQCZm8JAGsDBQJmbgUCZmcJAGQCBQJmbQUCZmcEAmZwCQC5AgIJALYCAQUCZm0JALYCAQUCZm4EAmZxCQC5AgIJALcCAgkAtwICCQC2AgEJAQJiRQEFAmZsCQC2AgEFAmZnCQC2AgEFAmZpCQC4AgIJALYCAQkBAmJFAQUCZmsJALYCAQUCZm8EAmZyAwkAwAICBQJmcQUCZnAGCQACAQIUbmV3IEsgaXMgZmV3ZXIgZXJyb3IDCQAAAgUCZnIFAmZyCQCUCgIFA25pbAUCZm8JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CZEwBJmNhbGN1bGF0ZUFtb3VudE91dEZvclN3YXBBbmRTZW5kVG9rZW5zBQJmZwJmaAJmcwJmdAJmaQQCZnUKAAJhUgkA/AcEBQJhTwIXZ2V0U3dhcENvbnRyYWN0UkVBRE9OTFkFA25pbAUDbmlsAwkAAQIFAmFSAgZTdHJpbmcFAmFSCQACAQkArAICCQADAQUCYVICGyBjb3VsZG4ndCBiZSBjYXN0IHRvIFN0cmluZwQCZUgJAMwIAgMJAGcCCAkBBXZhbHVlAQkAkQMCCAUCZEwIcGF5bWVudHMAAAZhbW91bnQFAmZnBgkBAmFMAQIMV3JvbmcgYW1vdW50CQDMCAIDCQAAAggFAmRMBmNhbGxlcgkBEUBleHRyTmF0aXZlKDEwNjIpAQUCZnUGCQECYUwBAhFQZXJtaXNzaW9uIGRlbmllZAUDbmlsAwkAAAIFAmVIBQJlSAQCZE0JAQV2YWx1ZQEJAJEDAggFAmRMCHBheW1lbnRzAAAEAmZsCQECYmEBCAUCZE0HYXNzZXRJZAQCZmsDCQAAAgUCZmgHCQECYUgCBQR0aGlzCQECYWYACQECYUgCBQR0aGlzCQECYWUABAJmbQkAZQIJAQJiRQEFAmZsCAkBBXZhbHVlAQkAkQMCCAUCZEwIcGF5bWVudHMAAAZhbW91bnQEAmZuCQECYkUBBQJmawQCZm8JAGsDBQJmbgUCZmcJAGQCBQJmbQUCZmcEAmZwCQC5AgIJALYCAQUCZm0JALYCAQUCZm4EAmZxCQC5AgIJALcCAgkAtgIBCQECYkUBBQJmbAkAtgIBBQJmaQkAuAICCQC2AgEJAQJiRQEFAmZrCQC2AgEFAmZvBAJmcgMJAMACAgUCZnEFAmZwBgkAAgECFG5ldyBLIGlzIGZld2VyIGVycm9yAwkAAAIFAmZyBQJmcgQCZnYDCQBnAgUCZm8FAmZzBgkAAgECLEV4Y2hhbmdlIHJlc3VsdCBpcyBmZXdlciBjb2lucyB0aGFuIGV4cGVjdGVkAwkAAAIFAmZ2BQJmdgkAlAoCCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMJARFAZXh0ck5hdGl2ZSgxMDYyKQEFAmZ0BQJmbwkBAmFZAQUCZmsFA25pbAUCZm8JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CZEwBCnNldE1hbmFnZXIBAmZ3BAJmeAkBAmZlAQUCZEwDCQAAAgUCZngFAmZ4BAJmeQkA2QQBBQJmdwMJAAACBQJmeQUCZnkJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAVYABQJmdwUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmRMAQ5jb25maXJtTWFuYWdlcgAEAmZ6CQECZmIABAJmQQMJAQlpc0RlZmluZWQBBQJmegYJAAIBAhJObyBwZW5kaW5nIG1hbmFnZXIDCQAAAgUCZkEFAmZBBAJmQgMJAAACCAUCZEwPY2FsbGVyUHVibGljS2V5CQEFdmFsdWUBBQJmegYJAAIBAhtZb3UgYXJlIG5vdCBwZW5kaW5nIG1hbmFnZXIDCQAAAgUCZkIFAmZCCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQFVAAkA2AQBCQEFdmFsdWUBBQJmegkAzAgCCQELRGVsZXRlRW50cnkBCQEBVgAFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJkTAEDcHV0AgJjegJmQwMJAGYCAAAFAmN6CQACAQIgSW52YWxpZCBzbGlwcGFnZVRvbGVyYW5jZSBwYXNzZWQEAmRSCQECZE8DBQJkTAUCY3oGBAJkYggFAmRSAl8yBAJjZwgFAmRSAl83BAJjeAgFAmRSAl85BAJkYwgFAmRSA18xMAQCZGQIBQJkUgNfMTEEAmZECAUCZFIDXzEyBAJmRQgFAmRSA18xMwQCZFAJALYCAQgJAQV2YWx1ZQEJAJEDAggFAmRMCHBheW1lbnRzAAAGYW1vdW50BAJkUQkAtgIBCAkBBXZhbHVlAQkAkQMCCAUCZEwIcGF5bWVudHMAAQZhbW91bnQEAmRzCQECZGwDBQJkUAUCZFEJALYCAQAAAwkAAAIFAmRzBQJkcwQCZFUJAPwHBAUCYU8CBGVtaXQJAMwIAgUCZGIFA25pbAUDbmlsAwkAAAIFAmRVBQJkVQQCZFYEAmRXBQJkVQMJAAECBQJkVwIHQWRkcmVzcwQCZFgFAmRXCQD8BwQFAmRYAgRlbWl0CQDMCAIFAmRiBQNuaWwFA25pbAUEdW5pdAMJAAACBQJkVgUCZFYEAmZGAwkAZgIFAmRjAAAJAPwHBAUCYm8CA3B1dAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQJmRAUCZGMFA25pbAUDbmlsAwkAAAIFAmZGBQJmRgQCZkcDCQBmAgUCZGQAAAkA/AcEBQJibwIDcHV0BQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFAmZFBQJkZAUDbmlsBQNuaWwDCQAAAgUCZkcFAmZHBAJmSAMFAmZDBAJmSQkA/AcEBQJibgIFc3Rha2UFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUCY2cFAmRiBQNuaWwDCQAAAgUCZkkFAmZJBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAmRMBmNhbGxlcgUCZGIFAmNnBQNuaWwEAmZKCQECZHQDAAAAAAAAAwkAAAIFAmZKBQJmSgQCZGsIBQJmSgJfMgQCZksIBQJmSgJfMQQCZkwJAQJkeAIFAmRzBQJkawMJAAACBQJmTAUCZkwJAM4IAgkAzggCBQJjeAUCZkgFAmZLCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmRMAQpwdXRGb3JGcmVlAQJmTQMJAGYCAAAFAmZNCQACAQIUSW52YWxpZCB2YWx1ZSBwYXNzZWQEAmRSCQECZE8DBQJkTAUCZk0HBAJjeAgFAmRSAl85BAJkUAkAtgIBCAkBBXZhbHVlAQkAkQMCCAUCZEwIcGF5bWVudHMAAAZhbW91bnQEAmRRCQC2AgEICQEFdmFsdWUBCQCRAwIIBQJkTAhwYXltZW50cwABBmFtb3VudAQCZHMJAQJkbAMFAmRQBQJkUQkAtgIBAAADCQAAAgUCZHMFAmRzBAJmTgkBAmR0AwAAAAAAAAQCZksIBQJmTgJfMQQCZGsIBQJmTgJfMgQCZkwJAQJkeAIFAmRzBQJkawMJAAACBQJmTAUCZkwJAM4IAgUCY3gFAmZLCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmRMAQlwdXRPbmVUa24CAmZPAmZQBAJmUQoAAmFSCQD8BwQFAmFPAihpc1Bvb2xPbmVUb2tlbk9wZXJhdGlvbnNEaXNhYmxlZFJFQURPTkxZCQDMCAIJAKUIAQUEdGhpcwUDbmlsBQNuaWwDCQABAgUCYVICB0Jvb2xlYW4FAmFSCQACAQkArAICCQADAQUCYVICHCBjb3VsZG4ndCBiZSBjYXN0IHRvIEJvb2xlYW4EAmZSAwMDCQECYVQABgkAAAIFAmJnBQFsBgkAAAIFAmJnBQFuBgUCZlEEAmVICQDMCAIDAwkBASEBBQJmUgYJAQJmYwEFAmRMBgkBAmFMAQIhcHV0IG9wZXJhdGlvbiBpcyBibG9ja2VkIGJ5IGFkbWluCQDMCAIDCQAAAgkAkAMBCAUCZEwIcGF5bWVudHMAAQYJAQJhTAECHmV4YWN0bHkgMSBwYXltZW50IGFyZSBleHBlY3RlZAUDbmlsAwkAAAIFAmVIBQJlSAQCZlMJAJEDAggFAmRMCHBheW1lbnRzAAAEAmVjCAUCZlMHYXNzZXRJZAQCZWIIBQJmUwZhbW91bnQEAmRzAwkAAAIFAmVjBQJiaQkBAmRsAwkAtgIBBQJlYgkAtgIBAAAJALYCAQAAAwkAAAIFAmVjBQJiagkBAmRsAwkAtgIBAAAJALYCAQUCZWIJALYCAQAACQECYUwBAh5wYXltZW50IGFzc2V0IGlzIG5vdCBzdXBwb3J0ZWQDCQAAAgUCZHMFAmRzBAJhYggFAmRMBmNhbGxlcgQCYWMIBQJkTA10cmFuc2FjdGlvbklkBAJmVAkBAmVhBAUCZWIFAmVjBQJhYgUCYWMDCQAAAgUCZlQFAmZUBAJlZwgFAmZUAl81BAJmVQgFAmZUAl80BAJkWggFAmZUAl8zBAJkZQgFAmZUAl8yBAJmVggFAmZUAl8xBAJmVwMDCQBmAgUCZk8AAAkAZgIFAmZPBQJmVgcJAQJhTAEJALkJAgkAzAgCAh9hbW91bnQgdG8gcmVjZWl2ZSBpcyBsZXNzIHRoYW4gCQDMCAIJAKQDAQUCZk8FA25pbAIABQJmVgQCZFUJAQJkUwEFAmZXAwkAAAIFAmRVBQJkVQQCZkgDBQJmUAQCZlgJAPwHBAUCYm4CBXN0YWtlBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFAmJoBQJmVwUDbmlsAwkAAAIFAmZYBQJmWAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQJkTAZjYWxsZXIFAmZXBQJiaAUDbmlsBAJmWQMJAGYCBQJkWgAACQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFAmFQBQJkWgUCZWMFA25pbAUDbmlsBAJmWgMJAAACBQR0aGlzBQJhUAkAlAoCAAAAAAMFAmVnCQCUCgIJAQEtAQUCZFoAAAkAlAoCAAAJAQEtAQUCZFoEAmR1CAUCZloCXzEEAmR2CAUCZloCXzIEAmdhCQECZHQDBQJkdQUCZHYAAAQCZksIBQJnYQJfMQQCZGsIBQJnYQJfMgQCZEUJAQV2YWx1ZQEJAKIIAQUCYWoEAmZMCQECZHgCBQJkcwUCZGsDCQAAAgUCZkwFAmZMCQCUCgIJAM4IAgkAzggCCQDOCAIFAmRlBQJmSAUCZlkFAmZLBQJmVwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJkTAERcHV0T25lVGtuUkVBRE9OTFkCAmVjAmViBAJnYgkBAmVhBAUCZWIJAQJhWQEFAmVjBQR1bml0BQR1bml0BAJmVggFAmdiAl8xBAJkZQgFAmdiAl8yBAJkWggFAmdiAl8zBAJmVQgFAmdiAl80BAJlZwgFAmdiAl81CQCUCgIFA25pbAkAlQoDBQJmVgUCZFoFAmZVAmRMAQlnZXRPbmVUa24CAmdjAmZPBAJmUQoAAmFSCQD8BwQFAmFPAihpc1Bvb2xPbmVUb2tlbk9wZXJhdGlvbnNEaXNhYmxlZFJFQURPTkxZCQDMCAIJAKUIAQUEdGhpcwUDbmlsBQNuaWwDCQABAgUCYVICB0Jvb2xlYW4FAmFSCQACAQkArAICCQADAQUCYVICHCBjb3VsZG4ndCBiZSBjYXN0IHRvIEJvb2xlYW4EAmdkAwMJAQJhVAAGCQAAAgUCYmcFAW4GBQJmUQQCZUgJAMwIAgMDCQEBIQEFAmdkBgkBAmZjAQUCZEwGCQECYUwBAiFnZXQgb3BlcmF0aW9uIGlzIGJsb2NrZWQgYnkgYWRtaW4JAMwIAgMJAAACCQCQAwEIBQJkTAhwYXltZW50cwABBgkBAmFMAQIeZXhhY3RseSAxIHBheW1lbnQgYXJlIGV4cGVjdGVkBQNuaWwDCQAAAgUCZUgFAmVIBAJlRwkBAmFZAQUCZ2MEAmZTCQCRAwIIBQJkTAhwYXltZW50cwAABAJlYwgFAmZTB2Fzc2V0SWQEAmVvCAUCZlMGYW1vdW50BAJkcwkBAmRsAwkAtgIBAAAJALYCAQAACQC2AgEAAAMJAAACBQJkcwUCZHMEAmFiCAUCZEwGY2FsbGVyBAJhYwgFAmRMDXRyYW5zYWN0aW9uSWQEAmdlCQECZUYFBQJlRwUCZW8FAmVjBQJhYgUCYWMDCQAAAgUCZ2UFAmdlBAJlSQgFAmdlAl81BAJmVQgFAmdlAl80BAJkWggFAmdlAl8zBAJkZQgFAmdlAl8yBAJnZggFAmdlAl8xBAJkVAMDCQBmAgUCZk8AAAkAZgIFAmZPBQJnZgcJAQJhTAEJALkJAgkAzAgCAh9hbW91bnQgdG8gcmVjZWl2ZSBpcyBsZXNzIHRoYW4gCQDMCAIJAKQDAQUCZk8FA25pbAIABQJnZgQCZ2cJAPwHBAUCYU8CBGJ1cm4JAMwIAgUCZW8FA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUCZWMFAmVvBQNuaWwDCQAAAgUCZ2cFAmdnBAJnaAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQJhYgUCZFQFAmVHBQNuaWwEAmZZAwkAZgIFAmRaAAAJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUCYVAFAmRaBQJlRwUDbmlsBQNuaWwEAmdpBAJnagMJAAACBQR0aGlzBQJhUAAABQJkWgMFAmVJCQCUCgIJAQEtAQkAZAIFAmRUBQJnagAACQCUCgIAAAkBAS0BCQBkAgUCZFQFAmdqBAJkdQgFAmdpAl8xBAJkdggFAmdpAl8yBAJnawkBAmR0AwUCZHUFAmR2AAAEAmZLCAUCZ2sCXzEEAmRrCAUCZ2sCXzIEAmZMCQECZHgCBQJkcwUCZGsDCQAAAgUCZkwFAmZMCQCUCgIJAM4IAgkAzggCCQDOCAIFAmRlBQJnaAUCZlkFAmZLBQJkVAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJkTAERZ2V0T25lVGtuUkVBRE9OTFkCAmVHAmVvBAJnbAkBAmVGBQkBAmFZAQUCZUcFAmVvBQJiaAUEdW5pdAUEdW5pdAQCZ2YIBQJnbAJfMQQCZGUIBQJnbAJfMgQCZFoIBQJnbAJfMwQCZlUIBQJnbAJfNAQCZUkIBQJnbAJfNQkAlAoCBQNuaWwJAJUKAwUCZ2YFAmRaBQJmVQJkTAETdW5zdGFrZUFuZEdldE9uZVRrbgMCZ20CZ2MCZk8EAmZRCgACYVIJAPwHBAUCYU8CKGlzUG9vbE9uZVRva2VuT3BlcmF0aW9uc0Rpc2FibGVkUkVBRE9OTFkJAMwIAgkApQgBBQR0aGlzBQNuaWwFA25pbAMJAAECBQJhUgIHQm9vbGVhbgUCYVIJAAIBCQCsAgIJAAMBBQJhUgIcIGNvdWxkbid0IGJlIGNhc3QgdG8gQm9vbGVhbgQCZ2QDAwkBAmFUAAYJAAACBQJiZwUBbgYFAmZRBAJlSAkAzAgCAwMJAQEhAQUCZ2QGCQECZmMBBQJkTAYJAQJhTAECIWdldCBvcGVyYXRpb24gaXMgYmxvY2tlZCBieSBhZG1pbgkAzAgCAwkAAAIJAJADAQgFAmRMCHBheW1lbnRzAAAGCQECYUwBAhhubyBwYXltZW50cyBhcmUgZXhwZWN0ZWQFA25pbAMJAAACBQJlSAUCZUgEAmVHCQECYVkBBQJnYwQCYWIIBQJkTAZjYWxsZXIEAmFjCAUCZEwNdHJhbnNhY3Rpb25JZAQCZHMJAQJkbAMJALYCAQAACQC2AgEAAAkAtgIBAAADCQAAAgUCZHMFAmRzBAJnbgkA/AcEBQJibgIHdW5zdGFrZQkAzAgCCQDYBAEFAmJoCQDMCAIFAmdtBQNuaWwFA25pbAMJAAACBQJnbgUCZ24EAmdvCQECZUYFBQJlRwUCZ20FAmJoBQJhYgUCYWMDCQAAAgUCZ28FAmdvBAJlSQgFAmdvAl81BAJmVQgFAmdvAl80BAJkWggFAmdvAl8zBAJkZQgFAmdvAl8yBAJnZggFAmdvAl8xBAJkVAMDCQBmAgUCZk8AAAkAZgIFAmZPBQJnZgcJAQJhTAEJALkJAgkAzAgCAh9hbW91bnQgdG8gcmVjZWl2ZSBpcyBsZXNzIHRoYW4gCQDMCAIJAKQDAQUCZk8FA25pbAIABQJnZgQCZ2cJAPwHBAUCYU8CBGJ1cm4JAMwIAgUCZ20FA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUCYmgFAmdtBQNuaWwDCQAAAgUCZ2cFAmdnBAJnaAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUCZEwGY2FsbGVyBQJkVAUCZUcFA25pbAQCZlkDCQBmAgUCZFoAAAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQJhUAUCZFoFAmVHBQNuaWwFA25pbAQCZ3AEAmdqAwkAAAIFBHRoaXMFAmFQAAAFAmRaAwUCZUkJAJQKAgkBAS0BCQBkAgUCZFQFAmdqAAAJAJQKAgAACQEBLQEJAGQCBQJkVAUCZ2oEAmR1CAUCZ3ACXzEEAmR2CAUCZ3ACXzIEAmdxCQECZHQDBQJkdQUCZHYAAAQCZksIBQJncQJfMQQCZGsIBQJncQJfMgQCZkwJAQJkeAIFAmRzBQJkawMJAAACBQJmTAUCZkwJAJQKAgkAzggCCQDOCAIJAM4IAgUCZGUFAmdoBQJmWQUCZksFAmRUCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmRMAQNnZXQABAJjUAkBAmRLAQUCZEwEAmdyCAUCY1ACXzEEAmN3CAUCY1ACXzIEAmROCAUCY1ACXzMEAmNlCAUCY1ACXzQEAmN4CAUCY1ACXzUEAmRzCQECZGwDCQC2AgEAAAkAtgIBAAAJALYCAQAAAwkAAAIFAmRzBQJkcwQCZ3MJAPwHBAUCYU8CBGJ1cm4JAMwIAgUCZE4FA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUCY2UFAmROBQNuaWwDCQAAAgUCZ3MFAmdzBAJndAkBAmR0AwkBAS0BBQJncgkBAS0BBQJjdwAABAJmSwgFAmd0Al8xBAJkawgFAmd0Al8yBAJmTAkBAmR4AgUCZHMFAmRrAwkAAAIFAmZMBQJmTAkAzggCBQJjeAUCZksJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CZEwBCWdldE5vTGVzcwICZ3UCZ3YEAmNQCQECZEsBBQJkTAQCY3YIBQJjUAJfMQQCY3cIBQJjUAJfMgQCZE4IBQJjUAJfMwQCY2UIBQJjUAJfNAQCY3gIBQJjUAJfNQMJAGYCBQJndQUCY3YJAAIBCQCsAgIJAKwCAgkArAICAhxub0xlc3NUaGVuQW10QXNzZXQgZmFpbGVkOiAgCQCkAwEFAmN2AgMgPCAJAKQDAQUCZ3UDCQBmAgUCZ3YFAmN3CQACAQkArAICCQCsAgIJAKwCAgIdbm9MZXNzVGhlblByaWNlQXNzZXQgZmFpbGVkOiAJAKQDAQUCY3cCAyA8IAkApAMBBQJndgQCZHMJAQJkbAMJALYCAQAACQC2AgEAAAkAtgIBAAADCQAAAgUCZHMFAmRzBAJncwkA/AcEBQJhTwIEYnVybgkAzAgCBQJkTgUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQJjZQUCZE4FA25pbAMJAAACBQJncwUCZ3MEAmd3CQECZHQDCQEBLQEFAmN2CQEBLQEFAmN3AAAEAmZLCAUCZ3cCXzEEAmRrCAUCZ3cCXzIEAmZMCQECZHgCBQJkcwUCZGsDCQAAAgUCZkwFAmZMCQDOCAIFAmN4BQJmSwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJkTAENdW5zdGFrZUFuZEdldAECZFQEAmd4AwkBAiE9AgkAkAMBCAUCZEwIcGF5bWVudHMAAAkAAgECGE5vIHBheW1lbnRzIGFyZSBleHBlY3RlZAYDCQAAAgUCZ3gFAmd4BAJiVAkBAmFWAAQCY2cJANkEAQkAkQMCBQJiVAUBcQQCZHMJAQJkbAMJALYCAQAACQC2AgEAAAkAtgIBAAADCQAAAgUCZHMFAmRzBAJnbgkA/AcEBQJibgIHdW5zdGFrZQkAzAgCCQDYBAEFAmNnCQDMCAIFAmRUBQNuaWwFA25pbAMJAAACBQJnbgUCZ24EAmNQCQECY2MECQDYBAEIBQJkTA10cmFuc2FjdGlvbklkCQDYBAEFAmNnBQJkVAgFAmRMBmNhbGxlcgQCY3YIBQJjUAJfMQQCY3cIBQJjUAJfMgQCY2oJAQ1wYXJzZUludFZhbHVlAQgFAmNQAl85BAJjeAgFAmNQA18xMAQCZ3kDAwkBAmFUAAYJAAACBQJjagUBbgkAAgEJAKwCAgIsR2V0IG9wZXJhdGlvbiBpcyBibG9ja2VkIGJ5IGFkbWluLiBTdGF0dXMgPSAJAKQDAQUCY2oGAwkAAAIFAmd5BQJneQQCZ3MJAPwHBAUCYU8CBGJ1cm4JAMwIAgUCZFQFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUCY2cFAmRUBQNuaWwDCQAAAgUCZ3MFAmdzBAJnegkBAmR0AwkBAS0BBQJjdgkBAS0BBQJjdwAABAJmSwgFAmd6Al8xBAJkawgFAmd6Al8yBAJmTAkBAmR4AgUCZHMFAmRrAwkAAAIFAmZMBQJmTAkAzggCBQJjeAUCZksJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CZEwBE3Vuc3Rha2VBbmRHZXROb0xlc3MDAmdtAmdBAmd2BAJnZAMJAQJhVAAGCQAAAgUCYmcFAW4EAmVICQDMCAIDCQEBIQEFAmdkBgkAAgECIWdldCBvcGVyYXRpb24gaXMgYmxvY2tlZCBieSBhZG1pbgkAzAgCAwkAAAIJAJADAQgFAmRMCHBheW1lbnRzAAAGCQACAQIYbm8gcGF5bWVudHMgYXJlIGV4cGVjdGVkBQNuaWwDCQAAAgUCZUgFAmVIBAJkcwkBAmRsAwkAtgIBAAAJALYCAQAACQC2AgEAAAMJAAACBQJkcwUCZHMEAmduCQD8BwQFAmJuAgd1bnN0YWtlCQDMCAIJANgEAQUCYmgJAMwIAgUCZ20FA25pbAUDbmlsAwkAAAIFAmduBQJnbgQCY1AJAQJjYwQJANgEAQgFAmRMDXRyYW5zYWN0aW9uSWQJANgEAQUCYmgFAmdtCAUCZEwGY2FsbGVyBAJjdggFAmNQAl8xBAJjdwgFAmNQAl8yBAJjeAgFAmNQA18xMAQCZ0IJAMwIAgMJAGcCBQJjdgUCZ0EGCQACAQkAuQkCCQDMCAICLGFtb3VudCBhc3NldCBhbW91bnQgdG8gcmVjZWl2ZSBpcyBsZXNzIHRoYW4gCQDMCAIJAKQDAQUCZ0EFA25pbAIACQDMCAIDCQBnAgUCY3cFAmd2BgkAAgEJALkJAgkAzAgCAitwcmljZSBhc3NldCBhbW91bnQgdG8gcmVjZWl2ZSBpcyBsZXNzIHRoYW4gCQDMCAIJAKQDAQUCZ3YFA25pbAIABQNuaWwDCQAAAgUCZ0IFAmdCBAJncwkA/AcEBQJhTwIEYnVybgkAzAgCBQJnbQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQJiaAUCZ20FA25pbAMJAAACBQJncwUCZ3MEAmdDCQECZHQDCQEBLQEFAmN2CQEBLQEFAmN3AAAEAmZLCAUCZ0MCXzEEAmRrCAUCZ0MCXzIEAmZMCQECZHgCBQJkcwUCZGsDCQAAAgUCZkwFAmZMCQDOCAIFAmN4BQJmSwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJkTAEIYWN0aXZhdGUCAmdEAmdFAwkBAiE9AgkApQgBCAUCZEwGY2FsbGVyCQClCAEFAmFPCQACAQIScGVybWlzc2lvbnMgZGVuaWVkCQCUCgIJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAmFlAAUCZ0QJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAmFmAAUCZ0UFA25pbAIHc3VjY2VzcwJkTAEKcmVmcmVzaEtMcAAEAmdGCQELdmFsdWVPckVsc2UCCQCfCAEFAmFrAAAEAmdHAwkAZwIJAGUCBQZoZWlnaHQFAmdGBQJhbgUEdW5pdAkBAmFMAQkAuQkCCQDMCAIJAKQDAQUCYW4JAMwIAgIvIGJsb2NrcyBoYXZlIG5vdCBwYXNzZWQgc2luY2UgdGhlIHByZXZpb3VzIGNhbGwFA25pbAIAAwkAAAIFAmdHBQJnRwQCZEUJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAqAMBCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMFAmFqAgEwCQECYU4BAgtpbnZhbGlkIGtMcAQCZ0gJAQJkdAMAAAAAAAAEAmdJCAUCZ0gCXzEEAmRrCAUCZ0gCXzIEAmR3AwkBAiE9AgUCZEUFAmRrBQJnSQkBAmFMAQISbm90aGluZyB0byByZWZyZXNoCQCUCgIFAmR3CQCmAwEFAmRrCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmRMARxnZXRQb29sQ29uZmlnV3JhcHBlclJFQURPTkxZAAkAlAoCBQNuaWwJAQJhVgACZEwBHGdldEFjY0JhbGFuY2VXcmFwcGVyUkVBRE9OTFkBAmJGCQCUCgIFA25pbAkBAmJFAQUCYkYCZEwBGWNhbGNQcmljZXNXcmFwcGVyUkVBRE9OTFkDAmJOAmJPAmJTBAJjYgkBAmJSAwUCYk4FAmJPBQJiUwkAlAoCBQNuaWwJAMwIAgkApgMBCQCRAwIFAmNiAAAJAMwIAgkApgMBCQCRAwIFAmNiAAEJAMwIAgkApgMBCQCRAwIFAmNiAAIFA25pbAJkTAEUdG9YMThXcmFwcGVyUkVBRE9OTFkCAUUBRgkAlAoCBQNuaWwJAKYDAQkBAUQCBQFFBQFGAmRMARZmcm9tWDE4V3JhcHBlclJFQURPTkxZAgFJAUoJAJQKAgUDbmlsCQEBSAIJAKcDAQUBSQUBSgJkTAEeY2FsY1ByaWNlQmlnSW50V3JhcHBlclJFQURPTkxZAgJiSAJiSQkAlAoCBQNuaWwJAKYDAQkBAmJHAgkApwMBBQJiSAkApwMBBQJiSQJkTAEjZXN0aW1hdGVQdXRPcGVyYXRpb25XcmFwcGVyUkVBRE9OTFkJAmNkAmN6AmNBAmNCAmNDAmNEAmFiAmNFAmNGCQCUCgIFA25pbAkBAmN5CQUCY2QFAmN6BQJjQQUCY0IFAmNDBQJjRAUCYWIFAmNFBQJjRgJkTAEjZXN0aW1hdGVHZXRPcGVyYXRpb25XcmFwcGVyUkVBRE9OTFkEAmNkAmNlAmNmAmFiBAJjUAkBAmNjBAUCY2QFAmNlBQJjZgkBEUBleHRyTmF0aXZlKDEwNjIpAQUCYWIJAJQKAgUDbmlsCQCcCgoIBQJjUAJfMQgFAmNQAl8yCAUCY1ACXzMIBQJjUAJfNAgFAmNQAl81CAUCY1ACXzYIBQJjUAJfNwkApgMBCAUCY1ACXzgIBQJjUAJfOQgFAmNQA18xMAJkTAENc3RhdHNSRUFET05MWQAEAmJUCQECYVYABAJjZwkA2QQBCQCRAwIFAmJUBQFxBAJnSgkAkQMCBQJiVAUBcgQCZ0sJAJEDAgUCYlQFAXMEAmNJCQCRAwIFAmJUBQF2BAJjSgkAkQMCBQJiVAUBdwQCYlUJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJiVAUBdAQCYlYJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJiVAUBdQQCZ0wICQETdmFsdWVPckVycm9yTWVzc2FnZQIJAOwHAQUCY2cJAKwCAgkArAICAgZBc3NldCAJANgEAQUCY2cCDiBkb2Vzbid0IGV4aXN0CHF1YW50aXR5BAJnTQkBAmJFAQUCZ0oEAmdOCQECYkUBBQJnSwQCZ08DCQAAAgUCZ0wAAAkAzAgCBQFlCQDMCAIFAWUJAMwIAgUBZQUDbmlsCQECYlIDBQJnTQUCZ04FAmdMBAJjcQAABAJnUAkBAUgCCQCRAwIFAmdPAAEFAWIEAmdRCQEBSAIJAJEDAgUCZ08AAgUBYgQCZ1IJAQV2YWx1ZQEJAJoIAgUCYU8JAQJheQEJAKUIAQUEdGhpcwkAlAoCBQNuaWwJALkJAgkAzAgCAg4lZCVkJWQlZCVkJWQlZAkAzAgCCQCkAwEFAmdNCQDMCAIJAKQDAQUCZ04JAMwIAgkApAMBBQJnTAkAzAgCCQCkAwEFAmNxCQDMCAIJAKQDAQUCZ1AJAMwIAgkApAMBBQJnUQkAzAgCCQCkAwEFAmdSBQNuaWwFAWoCZEwBIGV2YWx1YXRlUHV0QnlBbW91bnRBc3NldFJFQURPTkxZAQJjQQQCYlQJAQJhVgAEAmNnCQDZBAEJAJEDAgUCYlQFAXEEAmNHCQCRAwIFAmJUBQFyBAJjaAkA2QQBBQJjRwQCY0gJAJEDAgUCYlQFAXMEAmNpCQDZBAEFAmNIBAJiVQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmJUBQF0BAJiVgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmJUBQF1BAJjagkAkQMCBQJiVAUBcAQCZ0wICQETdmFsdWVPckVycm9yTWVzc2FnZQIJAOwHAQUCY2cJAKwCAgkArAICAgZBc3NldCAJANgEAQUCY2cCDiBkb2Vzbid0IGV4aXN0CHF1YW50aXR5BAJnTQkBAmJFAQUCY0cEAmdOCQECYkUBBQJjSAQCYlAJAQFEAgUCZ00FAmJVBAJiUQkBAUQCBQJnTgUCYlYEAmNwAwkAAAIFAmdMAAAFAWUJAQJiRwIFAmJRBQJiUAQCY00JAQFEAgUCY0EFAmJVBAJjTgkAvAIDBQJjTQUCY3AFAWQEAmNDCQEBSAIFAmNOBQJiVgQCZFIJAQJjeQkCAACgwh4FAmNBBQJjaAUCY0MFAmNpAgAGBwQCY1gIBQJkUgJfMQQCZ1MIBQJkUgJfMwQCY2wIBQJkUgJfNAQCY24IBQJkUgJfNQQCY2sIBQJkUgJfNgkAlAoCBQNuaWwJALkJAgkAzAgCAhAlZCVkJWQlZCVkJWQlZCVkCQDMCAIJAKQDAQUCY1gJAMwIAgkApAMBCQEBSAIFAmNwBQFiCQDMCAIJAKQDAQUCY2wJAMwIAgkApAMBBQJjbgkAzAgCCQCkAwEFAmNrCQDMCAIFAmNqCQDMCAIJAKQDAQUCY0EJAMwIAgkApAMBBQJjQwUDbmlsBQFqAmRMAR9ldmFsdWF0ZVB1dEJ5UHJpY2VBc3NldFJFQURPTkxZAQJjQwQCYlQJAQJhVgAEAmNnCQDZBAEJAJEDAgUCYlQFAXEEAmNHCQCRAwIFAmJUBQFyBAJjaAkA2QQBBQJjRwQCY0gJAJEDAgUCYlQFAXMEAmNpCQDZBAEFAmNIBAJiVQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmJUBQF0BAJiVgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmJUBQF1BAJjagkAkQMCBQJiVAUBcAQCZ0wICQETdmFsdWVPckVycm9yTWVzc2FnZQIJAOwHAQUCY2cJAKwCAgkArAICAgZBc3NldCAJANgEAQUCY2cCDiBkb2Vzbid0IGV4aXN0CHF1YW50aXR5BAJnVAkBAmJFAQUCY0cEAmdVCQECYkUBBQJjSAQCZ1YJAQFEAgUCZ1QFAmJVBAJnVwkBAUQCBQJnVQUCYlYEAmNwAwkAAAIFAmdMAAAFAWUJAQJiRwIFAmdXBQJnVgQCY04JAQFEAgUCY0MFAmJWBAJjTQkAvAIDBQJjTgUBZAUCY3AEAmNBCQEBSAIFAmNNBQJiVQQCZFIJAQJjeQkCAACgwh4FAmNBBQJjaAUCY0MFAmNpAgAGBwQCY1gIBQJkUgJfMQQCZ1MIBQJkUgJfMwQCY2wIBQJkUgJfNAQCY24IBQJkUgJfNQQCY2sIBQJkUgJfNgkAlAoCBQNuaWwJALkJAgkAzAgCAhAlZCVkJWQlZCVkJWQlZCVkCQDMCAIJAKQDAQUCY1gJAMwIAgkApAMBCQEBSAIFAmNwBQFiCQDMCAIJAKQDAQUCY2wJAMwIAgkApAMBBQJjbgkAzAgCCQCkAwEFAmNrCQDMCAIFAmNqCQDMCAIJAKQDAQUCY0EJAMwIAgkApAMBBQJjQwUDbmlsBQFqAmRMARNldmFsdWF0ZUdldFJFQURPTkxZAgJnWAJnWQQCY1AJAQJjYwQCAAUCZ1gFAmdZBQR0aGlzBAJjdggFAmNQAl8xBAJjdwgFAmNQAl8yBAJjbAgFAmNQAl81BAJjbggFAmNQAl82BAJjawgFAmNQAl83BAJjcQgFAmNQAl84BAJjagkBDXBhcnNlSW50VmFsdWUBCAUCY1ACXzkJAJQKAgUDbmlsCQC5CQIJAMwIAgIOJWQlZCVkJWQlZCVkJWQJAMwIAgkApAMBBQJjdgkAzAgCCQCkAwEFAmN3CQDMCAIJAKQDAQUCY2wJAMwIAgkApAMBBQJjbgkAzAgCCQCkAwEFAmNrCQDMCAIJAKYDAQUCY3EJAMwIAgkApAMBBQJjagUDbmlsBQFqAQJnWgECaGEABAJoYgQCZFcJAQJlWgADCQABAgUCZFcCCkJ5dGVWZWN0b3IEAmZkBQJkVwUCZmQDCQABAgUCZFcCBFVuaXQIBQJnWg9zZW5kZXJQdWJsaWNLZXkJAAIBAgtNYXRjaCBlcnJvcgQCZFcFAmdaAwkAAQIFAmRXAgVPcmRlcgQCZEEFAmRXBAJoYwkBAmFVAAQCaGQJAQJkegEFAmRBBAJhRAgFAmhkAl8xBAJhRQgFAmhkAl8yBAJhRgkA9AMDCAUCZEEJYm9keUJ5dGVzCQCRAwIIBQJkQQZwcm9vZnMAAAgFAmRBD3NlbmRlclB1YmxpY0tleQQCYUcJAPQDAwgFAmRBCWJvZHlCeXRlcwkAkQMCCAUCZEEGcHJvb2ZzAAEFAmhjAwMDBQJhRAUCYUYHBQJhRwcGCQECYUMEBQJhRAUCYUUFAmFGBQJhRwMJAAECBQJkVwIUU2V0U2NyaXB0VHJhbnNhY3Rpb24EAmZhBQJkVwMJAPQDAwgFAmdaCWJvZHlCeXRlcwkAkQMCCAUCZ1oGcHJvb2ZzAAAFAmhiBgQCaGUJAPYDAQkBBXZhbHVlAQgFAmZhBnNjcmlwdAQCaGYJANsEAQkBBXZhbHVlAQkAnQgCBQJhTwkBAmFBAAQCaGcJAPEHAQUEdGhpcwMJAAACBQJoZgUCaGUJAQIhPQIFAmhnBQJoZQcJAPQDAwgFAmdaCWJvZHlCeXRlcwkAkQMCCAUCZ1oGcHJvb2ZzAAAFAmhiqF/ylA==", "height": 2468123, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: AB5sqUbS6tGBTPcf6WwJjPAJeP8Xh3QCjTpnXZ1HRvej Next: 78Xq3Z89CRaYmaM1H19LEXesF7hCcYeYqo2uzdVbPniz Diff:
OldNewDifferences
6262 func toX18 (origVal,origScaleMult) = fraction(toBigInt(origVal), scale18, toBigInt(origScaleMult))
6363
6464
65+func toX18BigInt (origVal,origScaleMult) = fraction(origVal, scale18, origScaleMult)
66+
67+
6568 func fromX18 (val,resultScaleMult) = toInt(fraction(val, toBigInt(resultScaleMult), scale18))
69+
70+
71+func fromX18Round (val,resultScaleMult,round) = toInt(fraction(val, toBigInt(resultScaleMult), scale18, round))
6672
6773
6874 func toScale (amt,resScale,curScale) = fraction(amt, resScale, curScale)
7682 func absBigInt (val) = if ((zeroBigInt > val))
7783 then -(val)
7884 else val
85+
86+
87+func swapContract () = "%s__swapContract"
7988
8089
8190 func fc () = "%s__factoryContract"
105114 func pa () = "%s__priceAsset"
106115
107116
117+let keyFee = "%s__fee"
118+
119+let feeDefault = fraction(10, scale8, 10000)
120+
121+let fee = valueOrElse(getInteger(this, keyFee), feeDefault)
122+
123+let keyKLp = makeString(["%s", "kLp"], SEP)
124+
125+let keyKLpRefreshedHeight = makeString(["%s", "kLpRefreshedHeight"], SEP)
126+
127+let keyKLpRefreshDelay = makeString(["%s", "refreshKLpDelay"], SEP)
128+
129+let kLpRefreshDelayDefault = 30
130+
131+let kLpRefreshDelay = valueOrElse(getInteger(this, keyKLpRefreshDelay), kLpRefreshDelayDefault)
132+
108133 func keyFactoryConfig () = "%s__factoryConfig"
109134
110135
131156
132157 let keyFeeCollectorAddress = "%s__feeCollectorAddress"
133158
134-func throwOrderError (orderValid,senderValid,matcherValid) = throw(((((("order validation failed: orderValid=" + toString(orderValid)) + " senderValid=") + toString(senderValid)) + " matcherValid=") + toString(matcherValid)))
159+func throwOrderError (orderValid,orderValidInfo,senderValid,matcherValid) = throw((((((((("order validation failed: orderValid=" + toString(orderValid)) + " (") + orderValidInfo) + ")") + " senderValid=") + toString(senderValid)) + " matcherValid=") + toString(matcherValid)))
135160
136161
137162 func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
141166
142167
143168 func throwErr (msg) = throw(makeString(["lp.ride:", msg], " "))
169+
170+
171+func fmtErr (msg) = makeString(["lp.ride:", msg], " ")
144172
145173
146174 let factoryContract = addressFromStringValue(getStringOrFail(this, fc()))
191219
192220 let poolConfigParsed = parsePoolConfig(getPoolConfig())
193221
194-let $t076017767 = poolConfigParsed
222+let $t084698635 = poolConfigParsed
195223
196-let cfgPoolAddress = $t076017767._1
224+let cfgPoolAddress = $t084698635._1
197225
198-let cfgPoolStatus = $t076017767._2
226+let cfgPoolStatus = $t084698635._2
199227
200-let cfgLpAssetId = $t076017767._3
228+let cfgLpAssetId = $t084698635._3
201229
202-let cfgAmountAssetId = $t076017767._4
230+let cfgAmountAssetId = $t084698635._4
203231
204-let cfgPriceAssetId = $t076017767._5
232+let cfgPriceAssetId = $t084698635._5
205233
206-let cfgAmountAssetDecimals = $t076017767._6
234+let cfgAmountAssetDecimals = $t084698635._6
207235
208-let cfgPriceAssetDecimals = $t076017767._7
236+let cfgPriceAssetDecimals = $t084698635._7
209237
210238 func getFactoryConfig () = split(getStringOrFail(factoryContract, keyFactoryConfig()), SEP)
211239
226254
227255
228256 func calcPriceBigInt (prAmtX18,amAmtX18) = fraction(prAmtX18, scale18, amAmtX18)
257+
258+
259+func calcPriceBigIntRound (prAmtX18,amAmtX18,round) = fraction(prAmtX18, scale18, amAmtX18, round)
229260
230261
231262 func privateCalcPrice (amAssetDcm,prAssetDcm,amAmt,prAmt) = {
277308 let lpEmissionX18 = toX18(lpEmission, scale8)
278309 let outAmAmtX18 = fraction(amBalanceX18, pmtLpAmtX18, lpEmissionX18)
279310 let outPrAmtX18 = fraction(prBalanceX18, pmtLpAmtX18, lpEmissionX18)
280- let outAmAmt = fromX18(outAmAmtX18, amAssetDcm)
281- let outPrAmt = fromX18(outPrAmtX18, prAssetDcm)
311+ let outAmAmt = fromX18Round(outAmAmtX18, amAssetDcm, FLOOR)
312+ let outPrAmt = fromX18Round(outPrAmtX18, prAssetDcm, FLOOR)
282313 let state = if ((txId58 == ""))
283314 then nil
284315 else [ScriptTransfer(userAddress, outAmAmt, if ((amAssetId == "WAVES"))
337368 then throw(((("Price slippage " + toString(slippageX18)) + " exceeded the passed limit of ") + toString(slippageToleranceX18)))
338369 else {
339370 let lpEmissionX18 = toX18(lpEmission, scale8)
340- let prViaAmX18 = fraction(inAmAssetAmtX18, curPriceX18, scale18)
341- let amViaPrX18 = fraction(inPrAssetAmtX18, scale18, curPriceX18)
371+ let prViaAmX18 = fraction(inAmAssetAmtX18, calcPriceBigIntRound(prBalanceX18, amBalanceX18, CEILING), scale18, CEILING)
372+ let amViaPrX18 = fraction(inPrAssetAmtX18, scale18, calcPriceBigIntRound(prBalanceX18, amBalanceX18, FLOOR), CEILING)
342373 let expectedAmts = if ((prViaAmX18 > inPrAssetAmtX18))
343374 then $Tuple2(amViaPrX18, inPrAssetAmtX18)
344375 else $Tuple2(inAmAssetAmtX18, prViaAmX18)
345376 let expAmtAssetAmtX18 = expectedAmts._1
346377 let expPriceAssetAmtX18 = expectedAmts._2
347- let lpAmtX18 = fraction(lpEmissionX18, expPriceAssetAmtX18, prBalanceX18)
348- $Tuple5(fromX18(lpAmtX18, scale8), fromX18(expAmtAssetAmtX18, amtAssetDcm), fromX18(expPriceAssetAmtX18, priceAssetDcm), curPriceX18, slippageX18)
378+ let lpAmtX18 = fraction(lpEmissionX18, expPriceAssetAmtX18, prBalanceX18, FLOOR)
379+ $Tuple5(fromX18Round(lpAmtX18, scale8, FLOOR), fromX18Round(expAmtAssetAmtX18, amtAssetDcm, CEILING), fromX18Round(expPriceAssetAmtX18, priceAssetDcm, CEILING), curPriceX18, slippageX18)
349380 }
350381 }
351382 let calcLpAmt = res._1
368399 }
369400
370401
402+func calcKLp (amountBalance,priceBalance,lpEmission) = {
403+ let amountBalanceX18 = toX18BigInt(amountBalance, toBigInt(cfgAmountAssetDecimals))
404+ let priceBalanceX18 = toX18BigInt(priceBalance, toBigInt(cfgPriceAssetDecimals))
405+ let updatedKLp = fraction(pow((amountBalanceX18 * priceBalanceX18), 0, toBigInt(5), 1, 18, DOWN), big1, lpEmission)
406+ if ((lpEmission == big0))
407+ then big0
408+ else updatedKLp
409+ }
410+
411+
412+func calcCurrentKLp (amountAssetDelta,priceAssetDelta,lpAssetEmissionDelta) = {
413+ let amountAssetBalance = (toBigInt(getAccBalance(assetIdToString(cfgAmountAssetId))) - amountAssetDelta)
414+ let priceAssetBalance = (toBigInt(getAccBalance(assetIdToString(cfgPriceAssetId))) - priceAssetDelta)
415+ let lpAssetEmission = (toBigInt(value(assetInfo(cfgLpAssetId)).quantity) - lpAssetEmissionDelta)
416+ let currentKLp = calcKLp(amountAssetBalance, priceAssetBalance, lpAssetEmission)
417+ currentKLp
418+ }
419+
420+
421+func refreshKLpInternal (amountAssetBalanceDelta,priceAssetBalanceDelta,lpAssetEmissionDelta) = {
422+ let amountAssetBalance = (getAccBalance(assetIdToString(cfgAmountAssetId)) + amountAssetBalanceDelta)
423+ let priceAssetBalance = (getAccBalance(assetIdToString(cfgPriceAssetId)) + priceAssetBalanceDelta)
424+ let lpAssetEmission = (value(assetInfo(cfgLpAssetId)).quantity + lpAssetEmissionDelta)
425+ let updatedKLp = calcKLp(toBigInt(amountAssetBalance), toBigInt(priceAssetBalance), toBigInt(lpAssetEmission))
426+ let actions = [IntegerEntry(keyKLpRefreshedHeight, height), StringEntry(keyKLp, toString(updatedKLp))]
427+ $Tuple2(actions, updatedKLp)
428+ }
429+
430+
431+func validateUpdatedKLp (oldKLp,updatedKLp) = if ((updatedKLp >= oldKLp))
432+ then true
433+ else throwErr(makeString(["updated KLp lower than current KLp", toString(oldKLp), toString(updatedKLp)], " "))
434+
435+
371436 func validateMatcherOrderAllowed (order) = {
372- let cfg = getPoolConfig()
373- let amtAssetId = cfg[idxAmtAssetId]
374- let priceAssetId = cfg[idxPriceAssetId]
375- let poolStatus = parseIntValue(cfg[idxPoolStatus])
376- let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
377- let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
378- let accAmtAssetBalance = getAccBalance(amtAssetId)
379- let accPriceAssetBalance = getAccBalance(priceAssetId)
380- let curPriceX18 = if ((order.orderType == Buy))
381- then privateCalcPrice(amtAssetDcm, priceAssetDcm, (accAmtAssetBalance + order.amount), accPriceAssetBalance)
382- else privateCalcPrice(amtAssetDcm, priceAssetDcm, (accAmtAssetBalance - order.amount), accPriceAssetBalance)
383- let curPrice = fromX18(curPriceX18, scale8)
437+ let amountAssetBalance = getAccBalance(assetIdToString(cfgAmountAssetId))
438+ let priceAssetBalance = getAccBalance(assetIdToString(cfgPriceAssetId))
439+ let amountAssetAmount = order.amount
440+ let priceAssetAmount = fraction(order.amount, order.price, scale8, FLOOR)
441+ let $t02154121753 = if ((order.orderType == Buy))
442+ then $Tuple2(amountAssetAmount, -(priceAssetAmount))
443+ else $Tuple2(-(amountAssetAmount), priceAssetAmount)
444+ let amountAssetBalanceDelta = $t02154121753._1
445+ let priceAssetBalanceDelta = $t02154121753._2
384446 if (if (if (isGlobalShutdown())
385447 then true
386- else (poolStatus == PoolMatcherDisabled))
448+ else (cfgPoolStatus == PoolMatcherDisabled))
387449 then true
388- else (poolStatus == PoolShutdown))
450+ else (cfgPoolStatus == PoolShutdown))
389451 then throw("Exchange operations disabled")
390- else {
391- let orderAmtAsset = order.assetPair.amountAsset
392- let orderAmtAssetStr = if ((orderAmtAsset == unit))
393- then "WAVES"
394- else toBase58String(value(orderAmtAsset))
395- let orderPriceAsset = order.assetPair.priceAsset
396- let orderPriceAssetStr = if ((orderPriceAsset == unit))
397- then "WAVES"
398- else toBase58String(value(orderPriceAsset))
399- if (if ((orderAmtAssetStr != amtAssetId))
400- then true
401- else (orderPriceAssetStr != priceAssetId))
402- then throw("Wrong order assets.")
403- else {
404- let orderPrice = order.price
405- let priceDcm = fraction(scale8, priceAssetDcm, amtAssetDcm)
406- let castedOrderPrice = toScale(orderPrice, scale8, priceDcm)
407- let isOrderPriceValid = if ((order.orderType == Buy))
408- then (curPrice >= castedOrderPrice)
409- else (castedOrderPrice >= curPrice)
410- true
411- }
412- }
452+ else if (if ((order.assetPair.amountAsset != cfgAmountAssetId))
453+ then true
454+ else (order.assetPair.priceAsset != cfgPriceAssetId))
455+ then throw("Wrong order assets.")
456+ else {
457+ let kLp = valueOrErrorMessage(parseBigInt(valueOrElse(getString(this, keyKLp), "0")), fmtErr("invalid kLp"))
458+ let $t02219322293 = refreshKLpInternal(amountAssetBalanceDelta, priceAssetBalanceDelta, 0)
459+ let unusedActions = $t02219322293._1
460+ let kLpNew = $t02219322293._2
461+ let isOrderValid = (kLpNew >= kLp)
462+ let info = makeString(["kLp=", toString(kLp), " kLpNew=", toString(kLpNew), " amountAssetBalance=", toString(amountAssetBalance), " priceAssetBalance=", toString(priceAssetBalance), " amountAssetBalanceDelta=", toString(amountAssetBalanceDelta), " priceAssetBalanceDelta=", toString(priceAssetBalanceDelta), " height=", toString(height)], "")
463+ $Tuple2(isOrderValid, info)
464+ }
413465 }
414466
415467
484536 else if ((paymentAssetId == cfgPriceAssetId))
485537 then false
486538 else throwErr("invalid asset")
487- let $t02266422957 = if (isEval)
539+ let $t02540625699 = if (isEval)
488540 then $Tuple2(amountBalanceRaw, priceBalanceRaw)
489541 else if (paymentInAmountAsset)
490542 then $Tuple2((amountBalanceRaw - paymentAmountRaw), priceBalanceRaw)
491543 else $Tuple2(amountBalanceRaw, (priceBalanceRaw - paymentAmountRaw))
492- let amountBalanceOld = $t02266422957._1
493- let priceBalanceOld = $t02266422957._2
494- let $t02296123110 = if (paymentInAmountAsset)
544+ let amountBalanceOld = $t02540625699._1
545+ let priceBalanceOld = $t02540625699._2
546+ let $t02570325852 = if (paymentInAmountAsset)
495547 then $Tuple2(paymentAmountRaw, 0)
496548 else $Tuple2(0, paymentAmountRaw)
497- let amountAssetAmountRaw = $t02296123110._1
498- let priceAssetAmountRaw = $t02296123110._2
549+ let amountAssetAmountRaw = $t02570325852._1
550+ let priceAssetAmountRaw = $t02570325852._2
499551 let amountAssetAmount = takeFee(amountAssetAmountRaw, inFee)._1
500552 let priceAssetAmount = takeFee(priceAssetAmountRaw, inFee)._1
501- let $t02324223306 = takeFee(paymentAmountRaw, inFee)
502- let paymentAmount = $t02324223306._1
503- let feeAmount = $t02324223306._2
553+ let $t02598426048 = takeFee(paymentAmountRaw, inFee)
554+ let paymentAmount = $t02598426048._1
555+ let feeAmount = $t02598426048._2
504556 let amountBalanceNew = (amountBalanceOld + amountAssetAmount)
505557 let priceBalanceNew = (priceBalanceOld + priceAssetAmount)
506558 let priceNewX18 = calcPriceBigInt(toX18(priceBalanceNew, cfgPriceAssetDecimals), toX18(amountBalanceNew, cfgAmountAssetDecimals))
523575 let priceOldX18 = calcPriceBigInt(toX18(priceBalanceOld, cfgPriceAssetDecimals), toX18(amountBalanceOld, cfgAmountAssetDecimals))
524576 let priceOld = fromX18(priceOldX18, scale8)
525577 let loss = {
526- let $t02478324950 = if (paymentInAmountAsset)
578+ let $t02772927896 = if (paymentInAmountAsset)
527579 then $Tuple2(amountAssetAmountRaw, amountBalanceOld)
528580 else $Tuple2(priceAssetAmountRaw, priceBalanceOld)
529- let amount = $t02478324950._1
530- let balance = $t02478324950._2
581+ let amount = $t02772927896._1
582+ let balance = $t02772927896._2
531583 let issueAmountBoth = toInt(fraction(supplyBigInt, toBigInt((amount / 2)), toBigInt(balance)))
532584 fraction((issueAmount - issueAmountBoth), scale8, issueAmountBoth)
533585 }
534- $Tuple4(issueAmount, commonState, feeAmount, loss)
586+ $Tuple5(issueAmount, commonState, feeAmount, loss, paymentInAmountAsset)
535587 }
536588 else throw("Strict value is not equal to itself.")
537589 }
539591
540592 func calcGetOneToken (outAssetId,paymentAmount,paymentAssetId,userAddress,txId) = {
541593 let isEval = (txId == unit)
594+ let cfg = getPoolConfig()
595+ let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
596+ let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
542597 let checks = [if ((paymentAssetId == cfgLpAssetId))
543598 then true
544599 else throwErr("invalid lp asset")]
552607 let balanceBigInt = if (outInAmountAsset)
553608 then toBigInt(getAccBalance(assetIdToString(cfgAmountAssetId)))
554609 else toBigInt(getAccBalance(assetIdToString(cfgPriceAssetId)))
610+ let outInAmountAssetDecimals = if (outInAmountAsset)
611+ then amtAssetDcm
612+ else priceAssetDcm
555613 let amBalanceOld = getAccBalance(assetIdToString(cfgAmountAssetId))
556614 let prBalanceOld = getAccBalance(assetIdToString(cfgPriceAssetId))
557615 let outBalance = if (outInAmountAsset)
561619 let supplyBigInt = toBigInt(valueOrErrorMessage(assetInfo(cfgLpAssetId), (("asset " + toBase58String(cfgLpAssetId)) + " doesn't exist")).quantity)
562620 let redeemedBigInt = toBigInt(paymentAmount)
563621 let amountRaw = max([0, toInt(((balanceBigInt * (scale18 - pow((scale18 - ((redeemedBigInt * scale18) / supplyBigInt)), 18, big2, 0, 18, DOWN))) / scale18))])
564- let $t02653026586 = takeFee(amountRaw, outFee)
565- let totalAmount = $t02653026586._1
566- let feeAmount = $t02653026586._2
567- let $t02659026816 = if (outInAmountAsset)
622+ let $t02997430030 = takeFee(amountRaw, outFee)
623+ let totalAmount = $t02997430030._1
624+ let feeAmount = $t02997430030._2
625+ let $t03003430260 = if (outInAmountAsset)
568626 then $Tuple4(totalAmount, 0, (amBalanceOld - amountRaw), prBalanceOld)
569627 else $Tuple4(0, totalAmount, amBalanceOld, (prBalanceOld - amountRaw))
570- let outAmAmount = $t02659026816._1
571- let outPrAmount = $t02659026816._2
572- let amBalanceNew = $t02659026816._3
573- let prBalanceNew = $t02659026816._4
628+ let outAmAmount = $t03003430260._1
629+ let outPrAmount = $t03003430260._2
630+ let amBalanceNew = $t03003430260._3
631+ let prBalanceNew = $t03003430260._4
574632 let priceNewX18 = calcPriceBigInt(toX18(prBalanceNew, cfgPriceAssetDecimals), toX18(amBalanceNew, cfgAmountAssetDecimals))
575633 let priceNew = fromX18(priceNewX18, scale8)
576634 let commonState = if (isEval)
582640 let amountBothInPaymentAsset = (toInt(fraction(balanceBigInt, redeemedBigInt, supplyBigInt)) * 2)
583641 fraction((totalAmount - amountBothInPaymentAsset), scale8, amountBothInPaymentAsset)
584642 }
585- $Tuple4(totalAmount, commonState, feeAmount, loss)
643+ $Tuple5(totalAmount, commonState, feeAmount, loss, outInAmountAsset)
586644 }
587645 else throw("Strict value is not equal to itself.")
588646 }
636694
637695
638696 @Callable(i)
697+func calculateAmountOutForSwapREADONLY (cleanAmountIn,isReverse,feePoolAmount) = {
698+ let $t03197732282 = if ((isReverse == false))
699+ then {
700+ let assetOut = getStringOrFail(this, pa())
701+ let assetIn = getStringOrFail(this, aa())
702+ $Tuple2(assetOut, assetIn)
703+ }
704+ else {
705+ let assetOut = getStringOrFail(this, aa())
706+ let assetIn = getStringOrFail(this, pa())
707+ $Tuple2(assetOut, assetIn)
708+ }
709+ let assetOut = $t03197732282._1
710+ let assetIn = $t03197732282._2
711+ let poolAssetInBalance = getAccBalance(assetIn)
712+ let poolAssetOutBalance = getAccBalance(assetOut)
713+ let amountOut = fraction(poolAssetOutBalance, cleanAmountIn, (poolAssetInBalance + cleanAmountIn))
714+ let oldK = (toBigInt(poolAssetInBalance) * toBigInt(poolAssetOutBalance))
715+ let newK = (((toBigInt(getAccBalance(assetIn)) + toBigInt(cleanAmountIn)) + toBigInt(feePoolAmount)) * (toBigInt(getAccBalance(assetOut)) - toBigInt(amountOut)))
716+ let checkK = if ((newK >= oldK))
717+ then true
718+ else throw("new K is fewer error")
719+ if ((checkK == checkK))
720+ then $Tuple2(nil, amountOut)
721+ else throw("Strict value is not equal to itself.")
722+ }
723+
724+
725+
726+@Callable(i)
727+func calculateAmountOutForSwapAndSendTokens (cleanAmountIn,isReverse,amountOutMin,addressTo,feePoolAmount) = {
728+ let swapContact = {
729+ let @ = invoke(factoryContract, "getSwapContractREADONLY", nil, nil)
730+ if ($isInstanceOf(@, "String"))
731+ then @
732+ else throw(($getType(@) + " couldn't be cast to String"))
733+ }
734+ let checks = [if ((value(i.payments[0]).amount >= cleanAmountIn))
735+ then true
736+ else throwErr("Wrong amount"), if ((i.caller == addressFromStringValue(swapContact)))
737+ then true
738+ else throwErr("Permission denied")]
739+ if ((checks == checks))
740+ then {
741+ let pmt = value(i.payments[0])
742+ let assetIn = assetIdToString(pmt.assetId)
743+ let assetOut = if ((isReverse == false))
744+ then getStringOrFail(this, pa())
745+ else getStringOrFail(this, aa())
746+ let poolAssetInBalance = (getAccBalance(assetIn) - value(i.payments[0]).amount)
747+ let poolAssetOutBalance = getAccBalance(assetOut)
748+ let amountOut = fraction(poolAssetOutBalance, cleanAmountIn, (poolAssetInBalance + cleanAmountIn))
749+ let oldK = (toBigInt(poolAssetInBalance) * toBigInt(poolAssetOutBalance))
750+ let newK = ((toBigInt(getAccBalance(assetIn)) + toBigInt(feePoolAmount)) * (toBigInt(getAccBalance(assetOut)) - toBigInt(amountOut)))
751+ let checkK = if ((newK >= oldK))
752+ then true
753+ else throw("new K is fewer error")
754+ if ((checkK == checkK))
755+ then {
756+ let checkMin = if ((amountOut >= amountOutMin))
757+ then true
758+ else throw("Exchange result is fewer coins than expected")
759+ if ((checkMin == checkMin))
760+ then $Tuple2([ScriptTransfer(addressFromStringValue(addressTo), amountOut, parseAssetId(assetOut))], amountOut)
761+ else throw("Strict value is not equal to itself.")
762+ }
763+ else throw("Strict value is not equal to itself.")
764+ }
765+ else throw("Strict value is not equal to itself.")
766+ }
767+
768+
769+
770+@Callable(i)
639771 func setManager (pendingManagerPublicKey) = {
640772 let checkCaller = mustManager(i)
641773 if ((checkCaller == checkCaller))
682814 let prDiff = estPut._11
683815 let amId = estPut._12
684816 let prId = estPut._13
685- let emitInv = invoke(factoryContract, "emit", [emitLpAmt], nil)
686- if ((emitInv == emitInv))
817+ let amAssetPmt = toBigInt(value(i.payments[0]).amount)
818+ let prAssetPmt = toBigInt(value(i.payments[1]).amount)
819+ let currentKLp = calcCurrentKLp(amAssetPmt, prAssetPmt, toBigInt(0))
820+ if ((currentKLp == currentKLp))
687821 then {
688- let emitInvLegacy = match emitInv {
689- case legacyFactoryContract: Address =>
690- invoke(legacyFactoryContract, "emit", [emitLpAmt], nil)
691- case _ =>
692- unit
693- }
694- if ((emitInvLegacy == emitInvLegacy))
822+ let emitInv = invoke(factoryContract, "emit", [emitLpAmt], nil)
823+ if ((emitInv == emitInv))
695824 then {
696- let slippageAInv = if ((amDiff > 0))
697- then invoke(slippageContract, "put", nil, [AttachedPayment(amId, amDiff)])
698- else nil
699- if ((slippageAInv == slippageAInv))
825+ let emitInvLegacy = match emitInv {
826+ case legacyFactoryContract: Address =>
827+ invoke(legacyFactoryContract, "emit", [emitLpAmt], nil)
828+ case _ =>
829+ unit
830+ }
831+ if ((emitInvLegacy == emitInvLegacy))
700832 then {
701- let slippagePInv = if ((prDiff > 0))
702- then invoke(slippageContract, "put", nil, [AttachedPayment(prId, prDiff)])
833+ let slippageAInv = if ((amDiff > 0))
834+ then invoke(slippageContract, "put", nil, [AttachedPayment(amId, amDiff)])
703835 else nil
704- if ((slippagePInv == slippagePInv))
836+ if ((slippageAInv == slippageAInv))
705837 then {
706- let lpTransfer = if (shouldAutoStake)
838+ let slippagePInv = if ((prDiff > 0))
839+ then invoke(slippageContract, "put", nil, [AttachedPayment(prId, prDiff)])
840+ else nil
841+ if ((slippagePInv == slippagePInv))
707842 then {
708- let slpStakeInv = invoke(stakingContract, "stake", nil, [AttachedPayment(lpAssetId, emitLpAmt)])
709- if ((slpStakeInv == slpStakeInv))
710- then nil
843+ let lpTransfer = if (shouldAutoStake)
844+ then {
845+ let slpStakeInv = invoke(stakingContract, "stake", nil, [AttachedPayment(lpAssetId, emitLpAmt)])
846+ if ((slpStakeInv == slpStakeInv))
847+ then nil
848+ else throw("Strict value is not equal to itself.")
849+ }
850+ else [ScriptTransfer(i.caller, emitLpAmt, lpAssetId)]
851+ let $t03716637628 = refreshKLpInternal(0, 0, 0)
852+ if (($t03716637628 == $t03716637628))
853+ then {
854+ let updatedKLp = $t03716637628._2
855+ let refreshKLpActions = $t03716637628._1
856+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
857+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
858+ then ((state ++ lpTransfer) ++ refreshKLpActions)
859+ else throw("Strict value is not equal to itself.")
860+ }
711861 else throw("Strict value is not equal to itself.")
712862 }
713- else [ScriptTransfer(i.caller, emitLpAmt, lpAssetId)]
714- (state ++ lpTransfer)
863+ else throw("Strict value is not equal to itself.")
715864 }
716865 else throw("Strict value is not equal to itself.")
717866 }
729878 then throw("Invalid value passed")
730879 else {
731880 let estPut = commonPut(i, maxSlippage, false)
732- estPut._9
881+ let state = estPut._9
882+ let amAssetPmt = toBigInt(value(i.payments[0]).amount)
883+ let prAssetPmt = toBigInt(value(i.payments[1]).amount)
884+ let currentKLp = calcCurrentKLp(amAssetPmt, prAssetPmt, toBigInt(0))
885+ if ((currentKLp == currentKLp))
886+ then {
887+ let $t03819038255 = refreshKLpInternal(0, 0, 0)
888+ let refreshKLpActions = $t03819038255._1
889+ let updatedKLp = $t03819038255._2
890+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
891+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
892+ then (state ++ refreshKLpActions)
893+ else throw("Strict value is not equal to itself.")
894+ }
895+ else throw("Strict value is not equal to itself.")
733896 }
734897
735898
761924 let payment = i.payments[0]
762925 let paymentAssetId = payment.assetId
763926 let paymentAmountRaw = payment.amount
764- let userAddress = i.caller
765- let txId = i.transactionId
766- let $t03172331853 = calcPutOneToken(paymentAmountRaw, paymentAssetId, userAddress, txId)
767- if (($t03172331853 == $t03172331853))
927+ let currentKLp = if ((paymentAssetId == cfgAmountAssetId))
928+ then calcCurrentKLp(toBigInt(paymentAmountRaw), toBigInt(0), toBigInt(0))
929+ else if ((paymentAssetId == cfgPriceAssetId))
930+ then calcCurrentKLp(toBigInt(0), toBigInt(paymentAmountRaw), toBigInt(0))
931+ else throwErr("payment asset is not supported")
932+ if ((currentKLp == currentKLp))
768933 then {
769- let bonus = $t03172331853._4
770- let feeAmount = $t03172331853._3
771- let commonState = $t03172331853._2
772- let emitAmountEstimated = $t03172331853._1
773- let emitAmount = if (if ((minOutAmount > 0))
774- then (minOutAmount > emitAmountEstimated)
775- else false)
776- then throwErr(makeString(["amount to receive is less than ", toString(minOutAmount)], ""))
777- else emitAmountEstimated
778- let emitInv = emit(emitAmount)
779- if ((emitInv == emitInv))
934+ let userAddress = i.caller
935+ let txId = i.transactionId
936+ let $t03944339595 = calcPutOneToken(paymentAmountRaw, paymentAssetId, userAddress, txId)
937+ if (($t03944339595 == $t03944339595))
780938 then {
781- let lpTransfer = if (autoStake)
939+ let paymentInAmountAsset = $t03944339595._5
940+ let bonus = $t03944339595._4
941+ let feeAmount = $t03944339595._3
942+ let commonState = $t03944339595._2
943+ let emitAmountEstimated = $t03944339595._1
944+ let emitAmount = if (if ((minOutAmount > 0))
945+ then (minOutAmount > emitAmountEstimated)
946+ else false)
947+ then throwErr(makeString(["amount to receive is less than ", toString(minOutAmount)], ""))
948+ else emitAmountEstimated
949+ let emitInv = emit(emitAmount)
950+ if ((emitInv == emitInv))
782951 then {
783- let stakeInv = invoke(stakingContract, "stake", nil, [AttachedPayment(cfgLpAssetId, emitAmount)])
784- if ((stakeInv == stakeInv))
785- then nil
952+ let lpTransfer = if (autoStake)
953+ then {
954+ let stakeInv = invoke(stakingContract, "stake", nil, [AttachedPayment(cfgLpAssetId, emitAmount)])
955+ if ((stakeInv == stakeInv))
956+ then nil
957+ else throw("Strict value is not equal to itself.")
958+ }
959+ else [ScriptTransfer(i.caller, emitAmount, cfgLpAssetId)]
960+ let sendFee = if ((feeAmount > 0))
961+ then [ScriptTransfer(feeCollectorAddress, feeAmount, paymentAssetId)]
962+ else nil
963+ let $t04018140378 = if ((this == feeCollectorAddress))
964+ then $Tuple2(0, 0)
965+ else if (paymentInAmountAsset)
966+ then $Tuple2(-(feeAmount), 0)
967+ else $Tuple2(0, -(feeAmount))
968+ let amountAssetBalanceDelta = $t04018140378._1
969+ let priceAssetBalanceDelta = $t04018140378._2
970+ let $t04038140489 = refreshKLpInternal(amountAssetBalanceDelta, priceAssetBalanceDelta, 0)
971+ let refreshKLpActions = $t04038140489._1
972+ let updatedKLp = $t04038140489._2
973+ let kLp = value(getString(keyKLp))
974+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
975+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
976+ then $Tuple2((((commonState ++ lpTransfer) ++ sendFee) ++ refreshKLpActions), emitAmount)
786977 else throw("Strict value is not equal to itself.")
787978 }
788- else [ScriptTransfer(i.caller, emitAmount, cfgLpAssetId)]
789- let sendFee = if ((feeAmount > 0))
790- then [ScriptTransfer(feeCollectorAddress, feeAmount, paymentAssetId)]
791- else nil
792- $Tuple2(((commonState ++ lpTransfer) ++ sendFee), emitAmount)
979+ else throw("Strict value is not equal to itself.")
793980 }
794981 else throw("Strict value is not equal to itself.")
795982 }
802989
803990 @Callable(i)
804991 func putOneTknREADONLY (paymentAssetId,paymentAmountRaw) = {
805- let $t03258232717 = calcPutOneToken(paymentAmountRaw, parseAssetId(paymentAssetId), unit, unit)
806- let emitAmountEstimated = $t03258232717._1
807- let commonState = $t03258232717._2
808- let feeAmount = $t03258232717._3
809- let bonus = $t03258232717._4
992+ let $t04079540952 = calcPutOneToken(paymentAmountRaw, parseAssetId(paymentAssetId), unit, unit)
993+ let emitAmountEstimated = $t04079540952._1
994+ let commonState = $t04079540952._2
995+ let feeAmount = $t04079540952._3
996+ let bonus = $t04079540952._4
997+ let paymentInAmountAsset = $t04079540952._5
810998 $Tuple2(nil, $Tuple3(emitAmountEstimated, feeAmount, bonus))
811999 }
8121000
8381026 let payment = i.payments[0]
8391027 let paymentAssetId = payment.assetId
8401028 let paymentAmount = payment.amount
841- let userAddress = i.caller
842- let txId = i.transactionId
843- let $t03352233657 = calcGetOneToken(outAssetId, paymentAmount, paymentAssetId, userAddress, txId)
844- if (($t03352233657 == $t03352233657))
1029+ let currentKLp = calcCurrentKLp(toBigInt(0), toBigInt(0), toBigInt(0))
1030+ if ((currentKLp == currentKLp))
8451031 then {
846- let bonus = $t03352233657._4
847- let feeAmount = $t03352233657._3
848- let commonState = $t03352233657._2
849- let amountEstimated = $t03352233657._1
850- let amount = if (if ((minOutAmount > 0))
851- then (minOutAmount > amountEstimated)
852- else false)
853- then throwErr(makeString(["amount to receive is less than ", toString(minOutAmount)], ""))
854- else amountEstimated
855- let burnInv = invoke(factoryContract, "burn", [paymentAmount], [AttachedPayment(paymentAssetId, paymentAmount)])
856- if ((burnInv == burnInv))
1032+ let userAddress = i.caller
1033+ let txId = i.transactionId
1034+ let $t04183741990 = calcGetOneToken(outAssetId, paymentAmount, paymentAssetId, userAddress, txId)
1035+ if (($t04183741990 == $t04183741990))
8571036 then {
858- let assetTransfer = [ScriptTransfer(userAddress, amount, outAssetId)]
859- let sendFee = if ((feeAmount > 0))
860- then [ScriptTransfer(feeCollectorAddress, feeAmount, outAssetId)]
861- else nil
862- $Tuple2(((commonState ++ assetTransfer) ++ sendFee), amount)
1037+ let outInAmountAsset = $t04183741990._5
1038+ let bonus = $t04183741990._4
1039+ let feeAmount = $t04183741990._3
1040+ let commonState = $t04183741990._2
1041+ let amountEstimated = $t04183741990._1
1042+ let amount = if (if ((minOutAmount > 0))
1043+ then (minOutAmount > amountEstimated)
1044+ else false)
1045+ then throwErr(makeString(["amount to receive is less than ", toString(minOutAmount)], ""))
1046+ else amountEstimated
1047+ let burnInv = invoke(factoryContract, "burn", [paymentAmount], [AttachedPayment(paymentAssetId, paymentAmount)])
1048+ if ((burnInv == burnInv))
1049+ then {
1050+ let assetTransfer = [ScriptTransfer(userAddress, amount, outAssetId)]
1051+ let sendFee = if ((feeAmount > 0))
1052+ then [ScriptTransfer(feeCollectorAddress, feeAmount, outAssetId)]
1053+ else nil
1054+ let $t04249042737 = {
1055+ let feeAmountForCalc = if ((this == feeCollectorAddress))
1056+ then 0
1057+ else feeAmount
1058+ if (outInAmountAsset)
1059+ then $Tuple2(-((amount + feeAmountForCalc)), 0)
1060+ else $Tuple2(0, -((amount + feeAmountForCalc)))
1061+ }
1062+ let amountAssetBalanceDelta = $t04249042737._1
1063+ let priceAssetBalanceDelta = $t04249042737._2
1064+ let $t04274042848 = refreshKLpInternal(amountAssetBalanceDelta, priceAssetBalanceDelta, 0)
1065+ let refreshKLpActions = $t04274042848._1
1066+ let updatedKLp = $t04274042848._2
1067+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
1068+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
1069+ then $Tuple2((((commonState ++ assetTransfer) ++ sendFee) ++ refreshKLpActions), amount)
1070+ else throw("Strict value is not equal to itself.")
1071+ }
1072+ else throw("Strict value is not equal to itself.")
8631073 }
8641074 else throw("Strict value is not equal to itself.")
8651075 }
8721082
8731083 @Callable(i)
8741084 func getOneTknREADONLY (outAssetId,paymentAmount) = {
875- let $t03429234430 = calcGetOneToken(parseAssetId(outAssetId), paymentAmount, cfgLpAssetId, unit, unit)
876- let amountEstimated = $t03429234430._1
877- let commonState = $t03429234430._2
878- let feeAmount = $t03429234430._3
879- let bonus = $t03429234430._4
1085+ let $t04310543261 = calcGetOneToken(parseAssetId(outAssetId), paymentAmount, cfgLpAssetId, unit, unit)
1086+ let amountEstimated = $t04310543261._1
1087+ let commonState = $t04310543261._2
1088+ let feeAmount = $t04310543261._3
1089+ let bonus = $t04310543261._4
1090+ let outInAmountAsset = $t04310543261._5
8801091 $Tuple2(nil, $Tuple3(amountEstimated, feeAmount, bonus))
8811092 }
8821093
9071118 let outAssetId = parseAssetId(outAssetIdStr)
9081119 let userAddress = i.caller
9091120 let txId = i.transactionId
910- let unstakeInv = invoke(stakingContract, "unstake", [toBase58String(cfgLpAssetId), unstakeAmount], nil)
911- if ((unstakeInv == unstakeInv))
1121+ let currentKLp = calcCurrentKLp(toBigInt(0), toBigInt(0), toBigInt(0))
1122+ if ((currentKLp == currentKLp))
9121123 then {
913- let $t03525535388 = calcGetOneToken(outAssetId, unstakeAmount, cfgLpAssetId, userAddress, txId)
914- if (($t03525535388 == $t03525535388))
1124+ let unstakeInv = invoke(stakingContract, "unstake", [toBase58String(cfgLpAssetId), unstakeAmount], nil)
1125+ if ((unstakeInv == unstakeInv))
9151126 then {
916- let bonus = $t03525535388._4
917- let feeAmount = $t03525535388._3
918- let commonState = $t03525535388._2
919- let amountEstimated = $t03525535388._1
920- let amount = if (if ((minOutAmount > 0))
921- then (minOutAmount > amountEstimated)
922- else false)
923- then throwErr(makeString(["amount to receive is less than ", toString(minOutAmount)], ""))
924- else amountEstimated
925- let burnInv = invoke(factoryContract, "burn", [unstakeAmount], [AttachedPayment(cfgLpAssetId, unstakeAmount)])
926- if ((burnInv == burnInv))
1127+ let $t04416644317 = calcGetOneToken(outAssetId, unstakeAmount, cfgLpAssetId, userAddress, txId)
1128+ if (($t04416644317 == $t04416644317))
9271129 then {
928- let assetTransfer = [ScriptTransfer(i.caller, amount, outAssetId)]
929- let sendFee = if ((feeAmount > 0))
930- then [ScriptTransfer(feeCollectorAddress, feeAmount, outAssetId)]
931- else nil
932- $Tuple2(((commonState ++ assetTransfer) ++ sendFee), amount)
1130+ let outInAmountAsset = $t04416644317._5
1131+ let bonus = $t04416644317._4
1132+ let feeAmount = $t04416644317._3
1133+ let commonState = $t04416644317._2
1134+ let amountEstimated = $t04416644317._1
1135+ let amount = if (if ((minOutAmount > 0))
1136+ then (minOutAmount > amountEstimated)
1137+ else false)
1138+ then throwErr(makeString(["amount to receive is less than ", toString(minOutAmount)], ""))
1139+ else amountEstimated
1140+ let burnInv = invoke(factoryContract, "burn", [unstakeAmount], [AttachedPayment(cfgLpAssetId, unstakeAmount)])
1141+ if ((burnInv == burnInv))
1142+ then {
1143+ let assetTransfer = [ScriptTransfer(i.caller, amount, outAssetId)]
1144+ let sendFee = if ((feeAmount > 0))
1145+ then [ScriptTransfer(feeCollectorAddress, feeAmount, outAssetId)]
1146+ else nil
1147+ let $t04481245059 = {
1148+ let feeAmountForCalc = if ((this == feeCollectorAddress))
1149+ then 0
1150+ else feeAmount
1151+ if (outInAmountAsset)
1152+ then $Tuple2(-((amount + feeAmountForCalc)), 0)
1153+ else $Tuple2(0, -((amount + feeAmountForCalc)))
1154+ }
1155+ let amountAssetBalanceDelta = $t04481245059._1
1156+ let priceAssetBalanceDelta = $t04481245059._2
1157+ let $t04506245170 = refreshKLpInternal(amountAssetBalanceDelta, priceAssetBalanceDelta, 0)
1158+ let refreshKLpActions = $t04506245170._1
1159+ let updatedKLp = $t04506245170._2
1160+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
1161+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
1162+ then $Tuple2((((commonState ++ assetTransfer) ++ sendFee) ++ refreshKLpActions), amount)
1163+ else throw("Strict value is not equal to itself.")
1164+ }
1165+ else throw("Strict value is not equal to itself.")
9331166 }
9341167 else throw("Strict value is not equal to itself.")
9351168 }
9501183 let pmtAmt = res._3
9511184 let pmtAssetId = res._4
9521185 let state = res._5
953- let burnLPAssetOnFactory = invoke(factoryContract, "burn", [pmtAmt], [AttachedPayment(pmtAssetId, pmtAmt)])
954- if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
955- then state
1186+ let currentKLp = calcCurrentKLp(toBigInt(0), toBigInt(0), toBigInt(0))
1187+ if ((currentKLp == currentKLp))
1188+ then {
1189+ let burnLPAssetOnFactory = invoke(factoryContract, "burn", [pmtAmt], [AttachedPayment(pmtAssetId, pmtAmt)])
1190+ if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
1191+ then {
1192+ let $t04611646198 = refreshKLpInternal(-(outAmtAmt), -(outPrAmt), 0)
1193+ let refreshKLpActions = $t04611646198._1
1194+ let updatedKLp = $t04611646198._2
1195+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
1196+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
1197+ then (state ++ refreshKLpActions)
1198+ else throw("Strict value is not equal to itself.")
1199+ }
1200+ else throw("Strict value is not equal to itself.")
1201+ }
9561202 else throw("Strict value is not equal to itself.")
9571203 }
9581204
9711217 else if ((noLessThenPriceAsset > outPrAmt))
9721218 then throw(((("noLessThenPriceAsset failed: " + toString(outPrAmt)) + " < ") + toString(noLessThenPriceAsset)))
9731219 else {
974- let burnLPAssetOnFactory = invoke(factoryContract, "burn", [pmtAmt], [AttachedPayment(pmtAssetId, pmtAmt)])
975- if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
976- then state
1220+ let currentKLp = calcCurrentKLp(toBigInt(0), toBigInt(0), toBigInt(0))
1221+ if ((currentKLp == currentKLp))
1222+ then {
1223+ let burnLPAssetOnFactory = invoke(factoryContract, "burn", [pmtAmt], [AttachedPayment(pmtAssetId, pmtAmt)])
1224+ if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
1225+ then {
1226+ let $t04714747228 = refreshKLpInternal(-(outAmAmt), -(outPrAmt), 0)
1227+ let refreshKLpActions = $t04714747228._1
1228+ let updatedKLp = $t04714747228._2
1229+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
1230+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
1231+ then (state ++ refreshKLpActions)
1232+ else throw("Strict value is not equal to itself.")
1233+ }
1234+ else throw("Strict value is not equal to itself.")
1235+ }
9771236 else throw("Strict value is not equal to itself.")
9781237 }
9791238 }
9891248 then {
9901249 let cfg = getPoolConfig()
9911250 let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
992- let unstakeInv = invoke(stakingContract, "unstake", [toBase58String(lpAssetId), amount], nil)
993- if ((unstakeInv == unstakeInv))
1251+ let currentKLp = calcCurrentKLp(toBigInt(0), toBigInt(0), toBigInt(0))
1252+ if ((currentKLp == currentKLp))
9941253 then {
995- let res = estimateGetOperation(toBase58String(i.transactionId), toBase58String(lpAssetId), amount, i.caller)
996- let poolStatus = parseIntValue(res._9)
997- let state = res._10
998- let checkPoolStatus = if (if (isGlobalShutdown())
999- then true
1000- else (poolStatus == PoolShutdown))
1001- then throw(("Get operation is blocked by admin. Status = " + toString(poolStatus)))
1002- else true
1003- if ((checkPoolStatus == checkPoolStatus))
1254+ let unstakeInv = invoke(stakingContract, "unstake", [toBase58String(lpAssetId), amount], nil)
1255+ if ((unstakeInv == unstakeInv))
10041256 then {
1005- let burnLPAssetOnFactory = invoke(factoryContract, "burn", [amount], [AttachedPayment(lpAssetId, amount)])
1006- if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
1007- then state
1257+ let res = estimateGetOperation(toBase58String(i.transactionId), toBase58String(lpAssetId), amount, i.caller)
1258+ let outAmAmt = res._1
1259+ let outPrAmt = res._2
1260+ let poolStatus = parseIntValue(res._9)
1261+ let state = res._10
1262+ let checkPoolStatus = if (if (isGlobalShutdown())
1263+ then true
1264+ else (poolStatus == PoolShutdown))
1265+ then throw(("Get operation is blocked by admin. Status = " + toString(poolStatus)))
1266+ else true
1267+ if ((checkPoolStatus == checkPoolStatus))
1268+ then {
1269+ let burnLPAssetOnFactory = invoke(factoryContract, "burn", [amount], [AttachedPayment(lpAssetId, amount)])
1270+ if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
1271+ then {
1272+ let $t04835448435 = refreshKLpInternal(-(outAmAmt), -(outPrAmt), 0)
1273+ let refreshKLpActions = $t04835448435._1
1274+ let updatedKLp = $t04835448435._2
1275+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
1276+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
1277+ then (state ++ refreshKLpActions)
1278+ else throw("Strict value is not equal to itself.")
1279+ }
1280+ else throw("Strict value is not equal to itself.")
1281+ }
10081282 else throw("Strict value is not equal to itself.")
10091283 }
10101284 else throw("Strict value is not equal to itself.")
10281302 else throw("no payments are expected")]
10291303 if ((checks == checks))
10301304 then {
1031- let unstakeInv = invoke(stakingContract, "unstake", [toBase58String(cfgLpAssetId), unstakeAmount], nil)
1032- if ((unstakeInv == unstakeInv))
1305+ let currentKLp = calcCurrentKLp(toBigInt(0), toBigInt(0), toBigInt(0))
1306+ if ((currentKLp == currentKLp))
10331307 then {
1034- let res = estimateGetOperation(toBase58String(i.transactionId), toBase58String(cfgLpAssetId), unstakeAmount, i.caller)
1035- let outAmAmt = res._1
1036- let outPrAmt = res._2
1037- let state = res._10
1038- let checkAmounts = [if ((outAmAmt >= noLessThenAmountAsset))
1039- then true
1040- else throw(makeString(["amount asset amount to receive is less than ", toString(noLessThenAmountAsset)], "")), if ((outPrAmt >= noLessThenPriceAsset))
1041- then true
1042- else throw(makeString(["price asset amount to receive is less than ", toString(noLessThenPriceAsset)], ""))]
1043- if ((checkAmounts == checkAmounts))
1308+ let unstakeInv = invoke(stakingContract, "unstake", [toBase58String(cfgLpAssetId), unstakeAmount], nil)
1309+ if ((unstakeInv == unstakeInv))
10441310 then {
1045- let burnLPAssetOnFactory = invoke(factoryContract, "burn", [unstakeAmount], [AttachedPayment(cfgLpAssetId, unstakeAmount)])
1046- if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
1047- then state
1311+ let res = estimateGetOperation(toBase58String(i.transactionId), toBase58String(cfgLpAssetId), unstakeAmount, i.caller)
1312+ let outAmAmt = res._1
1313+ let outPrAmt = res._2
1314+ let state = res._10
1315+ let checkAmounts = [if ((outAmAmt >= noLessThenAmountAsset))
1316+ then true
1317+ else throw(makeString(["amount asset amount to receive is less than ", toString(noLessThenAmountAsset)], "")), if ((outPrAmt >= noLessThenPriceAsset))
1318+ then true
1319+ else throw(makeString(["price asset amount to receive is less than ", toString(noLessThenPriceAsset)], ""))]
1320+ if ((checkAmounts == checkAmounts))
1321+ then {
1322+ let burnLPAssetOnFactory = invoke(factoryContract, "burn", [unstakeAmount], [AttachedPayment(cfgLpAssetId, unstakeAmount)])
1323+ if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
1324+ then {
1325+ let $t04973049811 = refreshKLpInternal(-(outAmAmt), -(outPrAmt), 0)
1326+ let refreshKLpActions = $t04973049811._1
1327+ let updatedKLp = $t04973049811._2
1328+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
1329+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
1330+ then (state ++ refreshKLpActions)
1331+ else throw("Strict value is not equal to itself.")
1332+ }
1333+ else throw("Strict value is not equal to itself.")
1334+ }
10481335 else throw("Strict value is not equal to itself.")
10491336 }
10501337 else throw("Strict value is not equal to itself.")
10601347 func activate (amtAssetStr,priceAssetStr) = if ((toString(i.caller) != toString(factoryContract)))
10611348 then throw("permissions denied")
10621349 else $Tuple2([StringEntry(aa(), amtAssetStr), StringEntry(pa(), priceAssetStr)], "success")
1350+
1351+
1352+
1353+@Callable(i)
1354+func refreshKLp () = {
1355+ let lastRefreshedBlockHeight = valueOrElse(getInteger(keyKLpRefreshedHeight), 0)
1356+ let checkLastRefreshedBlockHeight = if (((height - lastRefreshedBlockHeight) >= kLpRefreshDelay))
1357+ then unit
1358+ else throwErr(makeString([toString(kLpRefreshDelay), " blocks have not passed since the previous call"], ""))
1359+ if ((checkLastRefreshedBlockHeight == checkLastRefreshedBlockHeight))
1360+ then {
1361+ let kLp = valueOrErrorMessage(parseBigInt(valueOrElse(getString(this, keyKLp), "0")), fmtErr("invalid kLp"))
1362+ let $t05099851062 = refreshKLpInternal(0, 0, 0)
1363+ let kLpUpdateActions = $t05099851062._1
1364+ let updatedKLp = $t05099851062._2
1365+ let actions = if ((kLp != updatedKLp))
1366+ then kLpUpdateActions
1367+ else throwErr("nothing to refresh")
1368+ $Tuple2(actions, toString(updatedKLp))
1369+ }
1370+ else throw("Strict value is not equal to itself.")
1371+ }
10631372
10641373
10651374
12271536 match tx {
12281537 case order: Order =>
12291538 let matcherPub = getMatcherPubOrFail()
1230- let orderValid = validateMatcherOrderAllowed(order)
1539+ let $t05972459793 = validateMatcherOrderAllowed(order)
1540+ let orderValid = $t05972459793._1
1541+ let orderValidInfo = $t05972459793._2
12311542 let senderValid = sigVerify(order.bodyBytes, order.proofs[0], order.senderPublicKey)
12321543 let matcherValid = sigVerify(order.bodyBytes, order.proofs[1], matcherPub)
12331544 if (if (if (orderValid)
12361547 then matcherValid
12371548 else false)
12381549 then true
1239- else throwOrderError(orderValid, senderValid, matcherValid)
1550+ else throwOrderError(orderValid, orderValidInfo, senderValid, matcherValid)
12401551 case s: SetScriptTransaction =>
1241- let newHash = blake2b256(value(s.script))
1242- let allowedHash = fromBase64String(value(getString(factoryContract, keyAllowedLpScriptHash())))
1243- let currentHash = scriptHash(this)
1244- if (if ((allowedHash == newHash))
1245- then (currentHash != newHash)
1246- else false)
1552+ if (sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey))
12471553 then true
1248- else sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey)
1554+ else {
1555+ let newHash = blake2b256(value(s.script))
1556+ let allowedHash = fromBase64String(value(getString(factoryContract, keyAllowedLpScriptHash())))
1557+ let currentHash = scriptHash(this)
1558+ if ((allowedHash == newHash))
1559+ then (currentHash != newHash)
1560+ else false
1561+ }
12491562 case _ =>
12501563 sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey)
12511564 }
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let lPdecimals = 8
55
66 let scale8 = 100000000
77
88 let scale8BigInt = toBigInt(100000000)
99
1010 let scale18 = toBigInt(1000000000000000000)
1111
1212 let zeroBigInt = toBigInt(0)
1313
1414 let big0 = toBigInt(0)
1515
1616 let big1 = toBigInt(1)
1717
1818 let big2 = toBigInt(2)
1919
2020 let wavesString = "WAVES"
2121
2222 let SEP = "__"
2323
2424 let PoolActive = 1
2525
2626 let PoolPutDisabled = 2
2727
2828 let PoolMatcherDisabled = 3
2929
3030 let PoolShutdown = 4
3131
3232 let idxPoolAddress = 1
3333
3434 let idxPoolStatus = 2
3535
3636 let idxPoolLPAssetId = 3
3737
3838 let idxAmtAssetId = 4
3939
4040 let idxPriceAssetId = 5
4141
4242 let idxAmtAssetDcm = 6
4343
4444 let idxPriceAssetDcm = 7
4545
4646 let idxIAmtAssetId = 8
4747
4848 let idxIPriceAssetId = 9
4949
5050 let idxLPAssetDcm = 10
5151
5252 let idxPoolAmtAssetAmt = 1
5353
5454 let idxPoolPriceAssetAmt = 2
5555
5656 let idxPoolLPAssetAmt = 3
5757
5858 let idxFactoryStakingContract = 1
5959
6060 let idxFactorySlippageContract = 7
6161
6262 func toX18 (origVal,origScaleMult) = fraction(toBigInt(origVal), scale18, toBigInt(origScaleMult))
6363
6464
65+func toX18BigInt (origVal,origScaleMult) = fraction(origVal, scale18, origScaleMult)
66+
67+
6568 func fromX18 (val,resultScaleMult) = toInt(fraction(val, toBigInt(resultScaleMult), scale18))
69+
70+
71+func fromX18Round (val,resultScaleMult,round) = toInt(fraction(val, toBigInt(resultScaleMult), scale18, round))
6672
6773
6874 func toScale (amt,resScale,curScale) = fraction(amt, resScale, curScale)
6975
7076
7177 func abs (val) = if ((0 > val))
7278 then -(val)
7379 else val
7480
7581
7682 func absBigInt (val) = if ((zeroBigInt > val))
7783 then -(val)
7884 else val
85+
86+
87+func swapContract () = "%s__swapContract"
7988
8089
8190 func fc () = "%s__factoryContract"
8291
8392
8493 func mpk () = "%s__managerPublicKey"
8594
8695
8796 func pmpk () = "%s__pendingManagerPublicKey"
8897
8998
9099 func pl () = "%s%s__price__last"
91100
92101
93102 func ph (h,timestamp) = makeString(["%s%s%d%d__price__history", toString(h), toString(timestamp)], SEP)
94103
95104
96105 func pau (userAddress,txId) = ((("%s%s%s__P__" + userAddress) + "__") + txId)
97106
98107
99108 func gau (userAddress,txId) = ((("%s%s%s__G__" + userAddress) + "__") + txId)
100109
101110
102111 func aa () = "%s__amountAsset"
103112
104113
105114 func pa () = "%s__priceAsset"
106115
107116
117+let keyFee = "%s__fee"
118+
119+let feeDefault = fraction(10, scale8, 10000)
120+
121+let fee = valueOrElse(getInteger(this, keyFee), feeDefault)
122+
123+let keyKLp = makeString(["%s", "kLp"], SEP)
124+
125+let keyKLpRefreshedHeight = makeString(["%s", "kLpRefreshedHeight"], SEP)
126+
127+let keyKLpRefreshDelay = makeString(["%s", "refreshKLpDelay"], SEP)
128+
129+let kLpRefreshDelayDefault = 30
130+
131+let kLpRefreshDelay = valueOrElse(getInteger(this, keyKLpRefreshDelay), kLpRefreshDelayDefault)
132+
108133 func keyFactoryConfig () = "%s__factoryConfig"
109134
110135
111136 func keyMatcherPub () = "%s%s__matcher__publicKey"
112137
113138
114139 func keyMappingPoolContractAddressToPoolAssets (poolContractAddress) = (("%s%s%s__" + poolContractAddress) + "__mappings__poolContract2LpAsset")
115140
116141
117142 func keyPoolConfig (iAmtAsset,iPriceAsset) = (((("%d%d%s__" + iAmtAsset) + "__") + iPriceAsset) + "__config")
118143
119144
120145 func keyMappingsBaseAsset2internalId (baseAssetStr) = ("%s%s%s__mappings__baseAsset2internalId__" + baseAssetStr)
121146
122147
123148 func keyAllPoolsShutdown () = "%s__shutdown"
124149
125150
126151 func keyPoolWeight (contractAddress) = ("%s%s__poolWeight__" + contractAddress)
127152
128153
129154 func keyAllowedLpScriptHash () = "%s__allowedLpScriptHash"
130155
131156
132157 let keyFeeCollectorAddress = "%s__feeCollectorAddress"
133158
134-func throwOrderError (orderValid,senderValid,matcherValid) = throw(((((("order validation failed: orderValid=" + toString(orderValid)) + " senderValid=") + toString(senderValid)) + " matcherValid=") + toString(matcherValid)))
159+func throwOrderError (orderValid,orderValidInfo,senderValid,matcherValid) = throw((((((((("order validation failed: orderValid=" + toString(orderValid)) + " (") + orderValidInfo) + ")") + " senderValid=") + toString(senderValid)) + " matcherValid=") + toString(matcherValid)))
135160
136161
137162 func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
138163
139164
140165 func getIntOrFail (address,key) = valueOrErrorMessage(getInteger(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
141166
142167
143168 func throwErr (msg) = throw(makeString(["lp.ride:", msg], " "))
169+
170+
171+func fmtErr (msg) = makeString(["lp.ride:", msg], " ")
144172
145173
146174 let factoryContract = addressFromStringValue(getStringOrFail(this, fc()))
147175
148176 let feeCollectorAddress = addressFromStringValue(getStringOrFail(factoryContract, keyFeeCollectorAddress))
149177
150178 let inFee = {
151179 let @ = invoke(factoryContract, "getInFeeREADONLY", [toString(this)], nil)
152180 if ($isInstanceOf(@, "Int"))
153181 then @
154182 else throw(($getType(@) + " couldn't be cast to Int"))
155183 }
156184
157185 let outFee = {
158186 let @ = invoke(factoryContract, "getOutFeeREADONLY", [toString(this)], nil)
159187 if ($isInstanceOf(@, "Int"))
160188 then @
161189 else throw(($getType(@) + " couldn't be cast to Int"))
162190 }
163191
164192 func isGlobalShutdown () = valueOrElse(getBoolean(factoryContract, keyAllPoolsShutdown()), false)
165193
166194
167195 func getMatcherPubOrFail () = fromBase58String(getStringOrFail(factoryContract, keyMatcherPub()))
168196
169197
170198 func getPoolConfig () = {
171199 let amtAsset = getStringOrFail(this, aa())
172200 let priceAsset = getStringOrFail(this, pa())
173201 let iPriceAsset = getIntOrFail(factoryContract, keyMappingsBaseAsset2internalId(priceAsset))
174202 let iAmtAsset = getIntOrFail(factoryContract, keyMappingsBaseAsset2internalId(amtAsset))
175203 split(getStringOrFail(factoryContract, keyPoolConfig(toString(iAmtAsset), toString(iPriceAsset))), SEP)
176204 }
177205
178206
179207 func parseAssetId (input) = if ((input == wavesString))
180208 then unit
181209 else fromBase58String(input)
182210
183211
184212 func assetIdToString (input) = if ((input == unit))
185213 then wavesString
186214 else toBase58String(value(input))
187215
188216
189217 func parsePoolConfig (poolConfig) = $Tuple7(addressFromStringValue(poolConfig[idxPoolAddress]), parseIntValue(poolConfig[idxPoolStatus]), fromBase58String(poolConfig[idxPoolLPAssetId]), parseAssetId(poolConfig[idxAmtAssetId]), parseAssetId(poolConfig[idxPriceAssetId]), parseIntValue(poolConfig[idxAmtAssetDcm]), parseIntValue(poolConfig[idxPriceAssetDcm]))
190218
191219
192220 let poolConfigParsed = parsePoolConfig(getPoolConfig())
193221
194-let $t076017767 = poolConfigParsed
222+let $t084698635 = poolConfigParsed
195223
196-let cfgPoolAddress = $t076017767._1
224+let cfgPoolAddress = $t084698635._1
197225
198-let cfgPoolStatus = $t076017767._2
226+let cfgPoolStatus = $t084698635._2
199227
200-let cfgLpAssetId = $t076017767._3
228+let cfgLpAssetId = $t084698635._3
201229
202-let cfgAmountAssetId = $t076017767._4
230+let cfgAmountAssetId = $t084698635._4
203231
204-let cfgPriceAssetId = $t076017767._5
232+let cfgPriceAssetId = $t084698635._5
205233
206-let cfgAmountAssetDecimals = $t076017767._6
234+let cfgAmountAssetDecimals = $t084698635._6
207235
208-let cfgPriceAssetDecimals = $t076017767._7
236+let cfgPriceAssetDecimals = $t084698635._7
209237
210238 func getFactoryConfig () = split(getStringOrFail(factoryContract, keyFactoryConfig()), SEP)
211239
212240
213241 let stakingContract = valueOrErrorMessage(addressFromString(getFactoryConfig()[idxFactoryStakingContract]), "incorrect staking address")
214242
215243 let slippageContract = valueOrErrorMessage(addressFromString(getFactoryConfig()[idxFactorySlippageContract]), "incorrect staking address")
216244
217245 func dataPutActionInfo (inAmtAssetAmt,inPriceAssetAmt,outLpAmt,price,slippageTolerancePassedByUser,slippageToleranceReal,txHeight,txTimestamp,slipageAmtAssetAmt,slipagePriceAssetAmt) = makeString(["%d%d%d%d%d%d%d%d%d%d", toString(inAmtAssetAmt), toString(inPriceAssetAmt), toString(outLpAmt), toString(price), toString(slippageTolerancePassedByUser), toString(slippageToleranceReal), toString(txHeight), toString(txTimestamp), toString(slipageAmtAssetAmt), toString(slipagePriceAssetAmt)], SEP)
218246
219247
220248 func dataGetActionInfo (outAmtAssetAmt,outPriceAssetAmt,inLpAmt,price,txHeight,txTimestamp) = makeString(["%d%d%d%d%d%d", toString(outAmtAssetAmt), toString(outPriceAssetAmt), toString(inLpAmt), toString(price), toString(txHeight), toString(txTimestamp)], SEP)
221249
222250
223251 func getAccBalance (assetId) = if ((assetId == "WAVES"))
224252 then wavesBalance(this).available
225253 else assetBalance(this, fromBase58String(assetId))
226254
227255
228256 func calcPriceBigInt (prAmtX18,amAmtX18) = fraction(prAmtX18, scale18, amAmtX18)
257+
258+
259+func calcPriceBigIntRound (prAmtX18,amAmtX18,round) = fraction(prAmtX18, scale18, amAmtX18, round)
229260
230261
231262 func privateCalcPrice (amAssetDcm,prAssetDcm,amAmt,prAmt) = {
232263 let amtAssetAmtX18 = toX18(amAmt, amAssetDcm)
233264 let priceAssetAmtX18 = toX18(prAmt, prAssetDcm)
234265 calcPriceBigInt(priceAssetAmtX18, amtAssetAmtX18)
235266 }
236267
237268
238269 func calcPrices (amAmt,prAmt,lpAmt) = {
239270 let cfg = getPoolConfig()
240271 let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
241272 let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
242273 let priceX18 = privateCalcPrice(amtAssetDcm, priceAssetDcm, amAmt, prAmt)
243274 let amAmtX18 = toX18(amAmt, amtAssetDcm)
244275 let prAmtX18 = toX18(prAmt, priceAssetDcm)
245276 let lpAmtX18 = toX18(lpAmt, scale8)
246277 let lpPriceInAmAssetX18 = calcPriceBigInt(amAmtX18, lpAmtX18)
247278 let lpPriceInPrAssetX18 = calcPriceBigInt(prAmtX18, lpAmtX18)
248279 [priceX18, lpPriceInAmAssetX18, lpPriceInPrAssetX18]
249280 }
250281
251282
252283 func calculatePrices (amAmt,prAmt,lpAmt) = {
253284 let prices = calcPrices(amAmt, prAmt, lpAmt)
254285 [fromX18(prices[0], scale8), fromX18(prices[1], scale8), fromX18(prices[2], scale8)]
255286 }
256287
257288
258289 func estimateGetOperation (txId58,pmtAssetId,pmtLpAmt,userAddress) = {
259290 let cfg = getPoolConfig()
260291 let lpAssetId = cfg[idxPoolLPAssetId]
261292 let amAssetId = cfg[idxAmtAssetId]
262293 let prAssetId = cfg[idxPriceAssetId]
263294 let amAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
264295 let prAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
265296 let poolStatus = cfg[idxPoolStatus]
266297 let lpEmission = valueOrErrorMessage(assetInfo(fromBase58String(lpAssetId)), (("Asset " + lpAssetId) + " doesn't exist")).quantity
267298 if ((lpAssetId != pmtAssetId))
268299 then throw("Invalid asset passed.")
269300 else {
270301 let amBalance = getAccBalance(amAssetId)
271302 let amBalanceX18 = toX18(amBalance, amAssetDcm)
272303 let prBalance = getAccBalance(prAssetId)
273304 let prBalanceX18 = toX18(prBalance, prAssetDcm)
274305 let curPriceX18 = calcPriceBigInt(prBalanceX18, amBalanceX18)
275306 let curPrice = fromX18(curPriceX18, scale8)
276307 let pmtLpAmtX18 = toX18(pmtLpAmt, scale8)
277308 let lpEmissionX18 = toX18(lpEmission, scale8)
278309 let outAmAmtX18 = fraction(amBalanceX18, pmtLpAmtX18, lpEmissionX18)
279310 let outPrAmtX18 = fraction(prBalanceX18, pmtLpAmtX18, lpEmissionX18)
280- let outAmAmt = fromX18(outAmAmtX18, amAssetDcm)
281- let outPrAmt = fromX18(outPrAmtX18, prAssetDcm)
311+ let outAmAmt = fromX18Round(outAmAmtX18, amAssetDcm, FLOOR)
312+ let outPrAmt = fromX18Round(outPrAmtX18, prAssetDcm, FLOOR)
282313 let state = if ((txId58 == ""))
283314 then nil
284315 else [ScriptTransfer(userAddress, outAmAmt, if ((amAssetId == "WAVES"))
285316 then unit
286317 else fromBase58String(amAssetId)), ScriptTransfer(userAddress, outPrAmt, if ((prAssetId == "WAVES"))
287318 then unit
288319 else fromBase58String(prAssetId)), StringEntry(gau(toString(userAddress), txId58), dataGetActionInfo(outAmAmt, outPrAmt, pmtLpAmt, curPrice, height, lastBlock.timestamp)), IntegerEntry(pl(), curPrice), IntegerEntry(ph(height, lastBlock.timestamp), curPrice)]
289320 $Tuple10(outAmAmt, outPrAmt, amAssetId, prAssetId, amBalance, prBalance, lpEmission, curPriceX18, poolStatus, state)
290321 }
291322 }
292323
293324
294325 func estimatePutOperation (txId58,slippageTolerance,inAmAssetAmt,inAmAssetId,inPrAssetAmt,inPrAssetId,userAddress,isEvaluate,emitLp) = {
295326 let cfg = getPoolConfig()
296327 let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
297328 let amAssetIdStr = cfg[idxAmtAssetId]
298329 let prAssetIdStr = cfg[idxPriceAssetId]
299330 let iAmtAssetId = cfg[idxIAmtAssetId]
300331 let iPriceAssetId = cfg[idxIPriceAssetId]
301332 let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
302333 let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
303334 let poolStatus = cfg[idxPoolStatus]
304335 let lpEmission = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
305336 let inAmAssetIdStr = toBase58String(valueOrElse(inAmAssetId, fromBase58String("WAVES")))
306337 let inPrAssetIdStr = toBase58String(valueOrElse(inPrAssetId, fromBase58String("WAVES")))
307338 if (if ((amAssetIdStr != inAmAssetIdStr))
308339 then true
309340 else (prAssetIdStr != inPrAssetIdStr))
310341 then throw("Invalid amt or price asset passed.")
311342 else {
312343 let amBalance = if (isEvaluate)
313344 then getAccBalance(amAssetIdStr)
314345 else (getAccBalance(amAssetIdStr) - inAmAssetAmt)
315346 let prBalance = if (isEvaluate)
316347 then getAccBalance(prAssetIdStr)
317348 else (getAccBalance(prAssetIdStr) - inPrAssetAmt)
318349 let inAmAssetAmtX18 = toX18(inAmAssetAmt, amtAssetDcm)
319350 let inPrAssetAmtX18 = toX18(inPrAssetAmt, priceAssetDcm)
320351 let userPriceX18 = calcPriceBigInt(inPrAssetAmtX18, inAmAssetAmtX18)
321352 let amBalanceX18 = toX18(amBalance, amtAssetDcm)
322353 let prBalanceX18 = toX18(prBalance, priceAssetDcm)
323354 let res = if ((lpEmission == 0))
324355 then {
325356 let curPriceX18 = zeroBigInt
326357 let slippageX18 = zeroBigInt
327358 let lpAmtX18 = pow((inAmAssetAmtX18 * inPrAssetAmtX18), 0, toBigInt(5), 1, 0, DOWN)
328359 $Tuple5(fromX18(lpAmtX18, scale8), fromX18(inAmAssetAmtX18, amtAssetDcm), fromX18(inPrAssetAmtX18, priceAssetDcm), calcPriceBigInt((prBalanceX18 + inPrAssetAmtX18), (amBalanceX18 + inAmAssetAmtX18)), slippageX18)
329360 }
330361 else {
331362 let curPriceX18 = calcPriceBigInt(prBalanceX18, amBalanceX18)
332363 let slippageX18 = fraction(absBigInt((curPriceX18 - userPriceX18)), scale18, curPriceX18)
333364 let slippageToleranceX18 = toX18(slippageTolerance, scale8)
334365 if (if ((curPriceX18 != zeroBigInt))
335366 then (slippageX18 > slippageToleranceX18)
336367 else false)
337368 then throw(((("Price slippage " + toString(slippageX18)) + " exceeded the passed limit of ") + toString(slippageToleranceX18)))
338369 else {
339370 let lpEmissionX18 = toX18(lpEmission, scale8)
340- let prViaAmX18 = fraction(inAmAssetAmtX18, curPriceX18, scale18)
341- let amViaPrX18 = fraction(inPrAssetAmtX18, scale18, curPriceX18)
371+ let prViaAmX18 = fraction(inAmAssetAmtX18, calcPriceBigIntRound(prBalanceX18, amBalanceX18, CEILING), scale18, CEILING)
372+ let amViaPrX18 = fraction(inPrAssetAmtX18, scale18, calcPriceBigIntRound(prBalanceX18, amBalanceX18, FLOOR), CEILING)
342373 let expectedAmts = if ((prViaAmX18 > inPrAssetAmtX18))
343374 then $Tuple2(amViaPrX18, inPrAssetAmtX18)
344375 else $Tuple2(inAmAssetAmtX18, prViaAmX18)
345376 let expAmtAssetAmtX18 = expectedAmts._1
346377 let expPriceAssetAmtX18 = expectedAmts._2
347- let lpAmtX18 = fraction(lpEmissionX18, expPriceAssetAmtX18, prBalanceX18)
348- $Tuple5(fromX18(lpAmtX18, scale8), fromX18(expAmtAssetAmtX18, amtAssetDcm), fromX18(expPriceAssetAmtX18, priceAssetDcm), curPriceX18, slippageX18)
378+ let lpAmtX18 = fraction(lpEmissionX18, expPriceAssetAmtX18, prBalanceX18, FLOOR)
379+ $Tuple5(fromX18Round(lpAmtX18, scale8, FLOOR), fromX18Round(expAmtAssetAmtX18, amtAssetDcm, CEILING), fromX18Round(expPriceAssetAmtX18, priceAssetDcm, CEILING), curPriceX18, slippageX18)
349380 }
350381 }
351382 let calcLpAmt = res._1
352383 let calcAmAssetPmt = res._2
353384 let calcPrAssetPmt = res._3
354385 let curPrice = fromX18(res._4, scale8)
355386 let slippageCalc = fromX18(res._5, scale8)
356387 if ((0 >= calcLpAmt))
357388 then throw("Invalid calculations. LP calculated is less than zero.")
358389 else {
359390 let emitLpAmt = if (!(emitLp))
360391 then 0
361392 else calcLpAmt
362393 let amDiff = (inAmAssetAmt - calcAmAssetPmt)
363394 let prDiff = (inPrAssetAmt - calcPrAssetPmt)
364395 let commonState = [IntegerEntry(pl(), curPrice), IntegerEntry(ph(height, lastBlock.timestamp), curPrice), StringEntry(pau(userAddress, txId58), dataPutActionInfo(calcAmAssetPmt, calcPrAssetPmt, emitLpAmt, curPrice, slippageTolerance, slippageCalc, height, lastBlock.timestamp, amDiff, prDiff))]
365396 $Tuple13(calcLpAmt, emitLpAmt, curPrice, amBalance, prBalance, lpEmission, lpAssetId, poolStatus, commonState, amDiff, prDiff, inAmAssetId, inPrAssetId)
366397 }
367398 }
368399 }
369400
370401
402+func calcKLp (amountBalance,priceBalance,lpEmission) = {
403+ let amountBalanceX18 = toX18BigInt(amountBalance, toBigInt(cfgAmountAssetDecimals))
404+ let priceBalanceX18 = toX18BigInt(priceBalance, toBigInt(cfgPriceAssetDecimals))
405+ let updatedKLp = fraction(pow((amountBalanceX18 * priceBalanceX18), 0, toBigInt(5), 1, 18, DOWN), big1, lpEmission)
406+ if ((lpEmission == big0))
407+ then big0
408+ else updatedKLp
409+ }
410+
411+
412+func calcCurrentKLp (amountAssetDelta,priceAssetDelta,lpAssetEmissionDelta) = {
413+ let amountAssetBalance = (toBigInt(getAccBalance(assetIdToString(cfgAmountAssetId))) - amountAssetDelta)
414+ let priceAssetBalance = (toBigInt(getAccBalance(assetIdToString(cfgPriceAssetId))) - priceAssetDelta)
415+ let lpAssetEmission = (toBigInt(value(assetInfo(cfgLpAssetId)).quantity) - lpAssetEmissionDelta)
416+ let currentKLp = calcKLp(amountAssetBalance, priceAssetBalance, lpAssetEmission)
417+ currentKLp
418+ }
419+
420+
421+func refreshKLpInternal (amountAssetBalanceDelta,priceAssetBalanceDelta,lpAssetEmissionDelta) = {
422+ let amountAssetBalance = (getAccBalance(assetIdToString(cfgAmountAssetId)) + amountAssetBalanceDelta)
423+ let priceAssetBalance = (getAccBalance(assetIdToString(cfgPriceAssetId)) + priceAssetBalanceDelta)
424+ let lpAssetEmission = (value(assetInfo(cfgLpAssetId)).quantity + lpAssetEmissionDelta)
425+ let updatedKLp = calcKLp(toBigInt(amountAssetBalance), toBigInt(priceAssetBalance), toBigInt(lpAssetEmission))
426+ let actions = [IntegerEntry(keyKLpRefreshedHeight, height), StringEntry(keyKLp, toString(updatedKLp))]
427+ $Tuple2(actions, updatedKLp)
428+ }
429+
430+
431+func validateUpdatedKLp (oldKLp,updatedKLp) = if ((updatedKLp >= oldKLp))
432+ then true
433+ else throwErr(makeString(["updated KLp lower than current KLp", toString(oldKLp), toString(updatedKLp)], " "))
434+
435+
371436 func validateMatcherOrderAllowed (order) = {
372- let cfg = getPoolConfig()
373- let amtAssetId = cfg[idxAmtAssetId]
374- let priceAssetId = cfg[idxPriceAssetId]
375- let poolStatus = parseIntValue(cfg[idxPoolStatus])
376- let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
377- let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
378- let accAmtAssetBalance = getAccBalance(amtAssetId)
379- let accPriceAssetBalance = getAccBalance(priceAssetId)
380- let curPriceX18 = if ((order.orderType == Buy))
381- then privateCalcPrice(amtAssetDcm, priceAssetDcm, (accAmtAssetBalance + order.amount), accPriceAssetBalance)
382- else privateCalcPrice(amtAssetDcm, priceAssetDcm, (accAmtAssetBalance - order.amount), accPriceAssetBalance)
383- let curPrice = fromX18(curPriceX18, scale8)
437+ let amountAssetBalance = getAccBalance(assetIdToString(cfgAmountAssetId))
438+ let priceAssetBalance = getAccBalance(assetIdToString(cfgPriceAssetId))
439+ let amountAssetAmount = order.amount
440+ let priceAssetAmount = fraction(order.amount, order.price, scale8, FLOOR)
441+ let $t02154121753 = if ((order.orderType == Buy))
442+ then $Tuple2(amountAssetAmount, -(priceAssetAmount))
443+ else $Tuple2(-(amountAssetAmount), priceAssetAmount)
444+ let amountAssetBalanceDelta = $t02154121753._1
445+ let priceAssetBalanceDelta = $t02154121753._2
384446 if (if (if (isGlobalShutdown())
385447 then true
386- else (poolStatus == PoolMatcherDisabled))
448+ else (cfgPoolStatus == PoolMatcherDisabled))
387449 then true
388- else (poolStatus == PoolShutdown))
450+ else (cfgPoolStatus == PoolShutdown))
389451 then throw("Exchange operations disabled")
390- else {
391- let orderAmtAsset = order.assetPair.amountAsset
392- let orderAmtAssetStr = if ((orderAmtAsset == unit))
393- then "WAVES"
394- else toBase58String(value(orderAmtAsset))
395- let orderPriceAsset = order.assetPair.priceAsset
396- let orderPriceAssetStr = if ((orderPriceAsset == unit))
397- then "WAVES"
398- else toBase58String(value(orderPriceAsset))
399- if (if ((orderAmtAssetStr != amtAssetId))
400- then true
401- else (orderPriceAssetStr != priceAssetId))
402- then throw("Wrong order assets.")
403- else {
404- let orderPrice = order.price
405- let priceDcm = fraction(scale8, priceAssetDcm, amtAssetDcm)
406- let castedOrderPrice = toScale(orderPrice, scale8, priceDcm)
407- let isOrderPriceValid = if ((order.orderType == Buy))
408- then (curPrice >= castedOrderPrice)
409- else (castedOrderPrice >= curPrice)
410- true
411- }
412- }
452+ else if (if ((order.assetPair.amountAsset != cfgAmountAssetId))
453+ then true
454+ else (order.assetPair.priceAsset != cfgPriceAssetId))
455+ then throw("Wrong order assets.")
456+ else {
457+ let kLp = valueOrErrorMessage(parseBigInt(valueOrElse(getString(this, keyKLp), "0")), fmtErr("invalid kLp"))
458+ let $t02219322293 = refreshKLpInternal(amountAssetBalanceDelta, priceAssetBalanceDelta, 0)
459+ let unusedActions = $t02219322293._1
460+ let kLpNew = $t02219322293._2
461+ let isOrderValid = (kLpNew >= kLp)
462+ let info = makeString(["kLp=", toString(kLp), " kLpNew=", toString(kLpNew), " amountAssetBalance=", toString(amountAssetBalance), " priceAssetBalance=", toString(priceAssetBalance), " amountAssetBalanceDelta=", toString(amountAssetBalanceDelta), " priceAssetBalanceDelta=", toString(priceAssetBalanceDelta), " height=", toString(height)], "")
463+ $Tuple2(isOrderValid, info)
464+ }
413465 }
414466
415467
416468 func commonGet (i) = if ((size(i.payments) != 1))
417469 then throw("exactly 1 payment is expected")
418470 else {
419471 let pmt = value(i.payments[0])
420472 let pmtAssetId = value(pmt.assetId)
421473 let pmtAmt = pmt.amount
422474 let res = estimateGetOperation(toBase58String(i.transactionId), toBase58String(pmtAssetId), pmtAmt, i.caller)
423475 let outAmAmt = res._1
424476 let outPrAmt = res._2
425477 let poolStatus = parseIntValue(res._9)
426478 let state = res._10
427479 if (if (isGlobalShutdown())
428480 then true
429481 else (poolStatus == PoolShutdown))
430482 then throw(("Get operation is blocked by admin. Status = " + toString(poolStatus)))
431483 else $Tuple5(outAmAmt, outPrAmt, pmtAmt, pmtAssetId, state)
432484 }
433485
434486
435487 func commonPut (i,slippageTolerance,emitLp) = if ((size(i.payments) != 2))
436488 then throw("exactly 2 payments are expected")
437489 else {
438490 let amAssetPmt = value(i.payments[0])
439491 let prAssetPmt = value(i.payments[1])
440492 let estPut = estimatePutOperation(toBase58String(i.transactionId), slippageTolerance, amAssetPmt.amount, amAssetPmt.assetId, prAssetPmt.amount, prAssetPmt.assetId, toString(i.caller), false, emitLp)
441493 let poolStatus = parseIntValue(estPut._8)
442494 if (if (if (isGlobalShutdown())
443495 then true
444496 else (poolStatus == PoolPutDisabled))
445497 then true
446498 else (poolStatus == PoolShutdown))
447499 then throw(("Put operation is blocked by admin. Status = " + toString(poolStatus)))
448500 else estPut
449501 }
450502
451503
452504 func emit (amount) = {
453505 let emitInv = invoke(factoryContract, "emit", [amount], nil)
454506 if ((emitInv == emitInv))
455507 then {
456508 let emitInvLegacy = match emitInv {
457509 case legacyFactoryContract: Address =>
458510 invoke(legacyFactoryContract, "emit", [amount], nil)
459511 case _ =>
460512 unit
461513 }
462514 if ((emitInvLegacy == emitInvLegacy))
463515 then amount
464516 else throw("Strict value is not equal to itself.")
465517 }
466518 else throw("Strict value is not equal to itself.")
467519 }
468520
469521
470522 func takeFee (amount,fee) = {
471523 let feeAmount = if ((fee == 0))
472524 then 0
473525 else fraction(amount, fee, scale8)
474526 $Tuple2((amount - feeAmount), feeAmount)
475527 }
476528
477529
478530 func calcPutOneToken (paymentAmountRaw,paymentAssetId,userAddress,txId) = {
479531 let isEval = (txId == unit)
480532 let amountBalanceRaw = getAccBalance(assetIdToString(cfgAmountAssetId))
481533 let priceBalanceRaw = getAccBalance(assetIdToString(cfgPriceAssetId))
482534 let paymentInAmountAsset = if ((paymentAssetId == cfgAmountAssetId))
483535 then true
484536 else if ((paymentAssetId == cfgPriceAssetId))
485537 then false
486538 else throwErr("invalid asset")
487- let $t02266422957 = if (isEval)
539+ let $t02540625699 = if (isEval)
488540 then $Tuple2(amountBalanceRaw, priceBalanceRaw)
489541 else if (paymentInAmountAsset)
490542 then $Tuple2((amountBalanceRaw - paymentAmountRaw), priceBalanceRaw)
491543 else $Tuple2(amountBalanceRaw, (priceBalanceRaw - paymentAmountRaw))
492- let amountBalanceOld = $t02266422957._1
493- let priceBalanceOld = $t02266422957._2
494- let $t02296123110 = if (paymentInAmountAsset)
544+ let amountBalanceOld = $t02540625699._1
545+ let priceBalanceOld = $t02540625699._2
546+ let $t02570325852 = if (paymentInAmountAsset)
495547 then $Tuple2(paymentAmountRaw, 0)
496548 else $Tuple2(0, paymentAmountRaw)
497- let amountAssetAmountRaw = $t02296123110._1
498- let priceAssetAmountRaw = $t02296123110._2
549+ let amountAssetAmountRaw = $t02570325852._1
550+ let priceAssetAmountRaw = $t02570325852._2
499551 let amountAssetAmount = takeFee(amountAssetAmountRaw, inFee)._1
500552 let priceAssetAmount = takeFee(priceAssetAmountRaw, inFee)._1
501- let $t02324223306 = takeFee(paymentAmountRaw, inFee)
502- let paymentAmount = $t02324223306._1
503- let feeAmount = $t02324223306._2
553+ let $t02598426048 = takeFee(paymentAmountRaw, inFee)
554+ let paymentAmount = $t02598426048._1
555+ let feeAmount = $t02598426048._2
504556 let amountBalanceNew = (amountBalanceOld + amountAssetAmount)
505557 let priceBalanceNew = (priceBalanceOld + priceAssetAmount)
506558 let priceNewX18 = calcPriceBigInt(toX18(priceBalanceNew, cfgPriceAssetDecimals), toX18(amountBalanceNew, cfgAmountAssetDecimals))
507559 let priceNew = fromX18(priceNewX18, scale8)
508560 let paymentBalance = if (paymentInAmountAsset)
509561 then amountBalanceOld
510562 else priceBalanceOld
511563 let paymentBalanceBigInt = toBigInt(paymentBalance)
512564 let supplyBigInt = toBigInt(valueOrErrorMessage(assetInfo(cfgLpAssetId), (("asset " + toBase58String(cfgLpAssetId)) + " doesn't exist")).quantity)
513565 let chechSupply = if ((supplyBigInt > big0))
514566 then true
515567 else throwErr("initial deposit requires all coins")
516568 if ((chechSupply == chechSupply))
517569 then {
518570 let depositBigInt = toBigInt(paymentAmount)
519571 let issueAmount = max([0, toInt(((supplyBigInt * (sqrtBigInt((scale18 + ((depositBigInt * scale18) / paymentBalanceBigInt)), 18, 18, DOWN) - scale18)) / scale18))])
520572 let commonState = if (isEval)
521573 then nil
522574 else [IntegerEntry(pl(), priceNew), IntegerEntry(ph(height, lastBlock.timestamp), priceNew), StringEntry(pau(toString(value(userAddress)), toBase58String(value(txId))), dataPutActionInfo(amountAssetAmountRaw, priceAssetAmountRaw, issueAmount, priceNew, 0, 0, height, lastBlock.timestamp, 0, 0))]
523575 let priceOldX18 = calcPriceBigInt(toX18(priceBalanceOld, cfgPriceAssetDecimals), toX18(amountBalanceOld, cfgAmountAssetDecimals))
524576 let priceOld = fromX18(priceOldX18, scale8)
525577 let loss = {
526- let $t02478324950 = if (paymentInAmountAsset)
578+ let $t02772927896 = if (paymentInAmountAsset)
527579 then $Tuple2(amountAssetAmountRaw, amountBalanceOld)
528580 else $Tuple2(priceAssetAmountRaw, priceBalanceOld)
529- let amount = $t02478324950._1
530- let balance = $t02478324950._2
581+ let amount = $t02772927896._1
582+ let balance = $t02772927896._2
531583 let issueAmountBoth = toInt(fraction(supplyBigInt, toBigInt((amount / 2)), toBigInt(balance)))
532584 fraction((issueAmount - issueAmountBoth), scale8, issueAmountBoth)
533585 }
534- $Tuple4(issueAmount, commonState, feeAmount, loss)
586+ $Tuple5(issueAmount, commonState, feeAmount, loss, paymentInAmountAsset)
535587 }
536588 else throw("Strict value is not equal to itself.")
537589 }
538590
539591
540592 func calcGetOneToken (outAssetId,paymentAmount,paymentAssetId,userAddress,txId) = {
541593 let isEval = (txId == unit)
594+ let cfg = getPoolConfig()
595+ let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
596+ let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
542597 let checks = [if ((paymentAssetId == cfgLpAssetId))
543598 then true
544599 else throwErr("invalid lp asset")]
545600 if ((checks == checks))
546601 then {
547602 let outInAmountAsset = if ((outAssetId == cfgAmountAssetId))
548603 then true
549604 else if ((outAssetId == cfgPriceAssetId))
550605 then false
551606 else throwErr("invalid asset")
552607 let balanceBigInt = if (outInAmountAsset)
553608 then toBigInt(getAccBalance(assetIdToString(cfgAmountAssetId)))
554609 else toBigInt(getAccBalance(assetIdToString(cfgPriceAssetId)))
610+ let outInAmountAssetDecimals = if (outInAmountAsset)
611+ then amtAssetDcm
612+ else priceAssetDcm
555613 let amBalanceOld = getAccBalance(assetIdToString(cfgAmountAssetId))
556614 let prBalanceOld = getAccBalance(assetIdToString(cfgPriceAssetId))
557615 let outBalance = if (outInAmountAsset)
558616 then amBalanceOld
559617 else prBalanceOld
560618 let outBalanceBigInt = toBigInt(outBalance)
561619 let supplyBigInt = toBigInt(valueOrErrorMessage(assetInfo(cfgLpAssetId), (("asset " + toBase58String(cfgLpAssetId)) + " doesn't exist")).quantity)
562620 let redeemedBigInt = toBigInt(paymentAmount)
563621 let amountRaw = max([0, toInt(((balanceBigInt * (scale18 - pow((scale18 - ((redeemedBigInt * scale18) / supplyBigInt)), 18, big2, 0, 18, DOWN))) / scale18))])
564- let $t02653026586 = takeFee(amountRaw, outFee)
565- let totalAmount = $t02653026586._1
566- let feeAmount = $t02653026586._2
567- let $t02659026816 = if (outInAmountAsset)
622+ let $t02997430030 = takeFee(amountRaw, outFee)
623+ let totalAmount = $t02997430030._1
624+ let feeAmount = $t02997430030._2
625+ let $t03003430260 = if (outInAmountAsset)
568626 then $Tuple4(totalAmount, 0, (amBalanceOld - amountRaw), prBalanceOld)
569627 else $Tuple4(0, totalAmount, amBalanceOld, (prBalanceOld - amountRaw))
570- let outAmAmount = $t02659026816._1
571- let outPrAmount = $t02659026816._2
572- let amBalanceNew = $t02659026816._3
573- let prBalanceNew = $t02659026816._4
628+ let outAmAmount = $t03003430260._1
629+ let outPrAmount = $t03003430260._2
630+ let amBalanceNew = $t03003430260._3
631+ let prBalanceNew = $t03003430260._4
574632 let priceNewX18 = calcPriceBigInt(toX18(prBalanceNew, cfgPriceAssetDecimals), toX18(amBalanceNew, cfgAmountAssetDecimals))
575633 let priceNew = fromX18(priceNewX18, scale8)
576634 let commonState = if (isEval)
577635 then nil
578636 else [StringEntry(gau(toString(value(userAddress)), toBase58String(value(txId))), dataGetActionInfo(outAmAmount, outPrAmount, paymentAmount, priceNew, height, lastBlock.timestamp)), IntegerEntry(pl(), priceNew), IntegerEntry(ph(height, lastBlock.timestamp), priceNew)]
579637 let priceOldX18 = calcPriceBigInt(toX18(prBalanceOld, cfgPriceAssetDecimals), toX18(amBalanceOld, cfgAmountAssetDecimals))
580638 let priceOld = fromX18(priceOldX18, scale8)
581639 let loss = {
582640 let amountBothInPaymentAsset = (toInt(fraction(balanceBigInt, redeemedBigInt, supplyBigInt)) * 2)
583641 fraction((totalAmount - amountBothInPaymentAsset), scale8, amountBothInPaymentAsset)
584642 }
585- $Tuple4(totalAmount, commonState, feeAmount, loss)
643+ $Tuple5(totalAmount, commonState, feeAmount, loss, outInAmountAsset)
586644 }
587645 else throw("Strict value is not equal to itself.")
588646 }
589647
590648
591649 func managerPublicKeyOrUnit () = match getString(mpk()) {
592650 case s: String =>
593651 fromBase58String(s)
594652 case _: Unit =>
595653 unit
596654 case _ =>
597655 throw("Match error")
598656 }
599657
600658
601659 func pendingManagerPublicKeyOrUnit () = match getString(pmpk()) {
602660 case s: String =>
603661 fromBase58String(s)
604662 case _: Unit =>
605663 unit
606664 case _ =>
607665 throw("Match error")
608666 }
609667
610668
611669 func isManager (i) = match managerPublicKeyOrUnit() {
612670 case pk: ByteVector =>
613671 (i.callerPublicKey == pk)
614672 case _: Unit =>
615673 (i.caller == this)
616674 case _ =>
617675 throw("Match error")
618676 }
619677
620678
621679 func mustManager (i) = {
622680 let pd = throw("Permission denied")
623681 match managerPublicKeyOrUnit() {
624682 case pk: ByteVector =>
625683 if ((i.callerPublicKey == pk))
626684 then true
627685 else pd
628686 case _: Unit =>
629687 if ((i.caller == this))
630688 then true
631689 else pd
632690 case _ =>
633691 throw("Match error")
634692 }
635693 }
636694
637695
638696 @Callable(i)
697+func calculateAmountOutForSwapREADONLY (cleanAmountIn,isReverse,feePoolAmount) = {
698+ let $t03197732282 = if ((isReverse == false))
699+ then {
700+ let assetOut = getStringOrFail(this, pa())
701+ let assetIn = getStringOrFail(this, aa())
702+ $Tuple2(assetOut, assetIn)
703+ }
704+ else {
705+ let assetOut = getStringOrFail(this, aa())
706+ let assetIn = getStringOrFail(this, pa())
707+ $Tuple2(assetOut, assetIn)
708+ }
709+ let assetOut = $t03197732282._1
710+ let assetIn = $t03197732282._2
711+ let poolAssetInBalance = getAccBalance(assetIn)
712+ let poolAssetOutBalance = getAccBalance(assetOut)
713+ let amountOut = fraction(poolAssetOutBalance, cleanAmountIn, (poolAssetInBalance + cleanAmountIn))
714+ let oldK = (toBigInt(poolAssetInBalance) * toBigInt(poolAssetOutBalance))
715+ let newK = (((toBigInt(getAccBalance(assetIn)) + toBigInt(cleanAmountIn)) + toBigInt(feePoolAmount)) * (toBigInt(getAccBalance(assetOut)) - toBigInt(amountOut)))
716+ let checkK = if ((newK >= oldK))
717+ then true
718+ else throw("new K is fewer error")
719+ if ((checkK == checkK))
720+ then $Tuple2(nil, amountOut)
721+ else throw("Strict value is not equal to itself.")
722+ }
723+
724+
725+
726+@Callable(i)
727+func calculateAmountOutForSwapAndSendTokens (cleanAmountIn,isReverse,amountOutMin,addressTo,feePoolAmount) = {
728+ let swapContact = {
729+ let @ = invoke(factoryContract, "getSwapContractREADONLY", nil, nil)
730+ if ($isInstanceOf(@, "String"))
731+ then @
732+ else throw(($getType(@) + " couldn't be cast to String"))
733+ }
734+ let checks = [if ((value(i.payments[0]).amount >= cleanAmountIn))
735+ then true
736+ else throwErr("Wrong amount"), if ((i.caller == addressFromStringValue(swapContact)))
737+ then true
738+ else throwErr("Permission denied")]
739+ if ((checks == checks))
740+ then {
741+ let pmt = value(i.payments[0])
742+ let assetIn = assetIdToString(pmt.assetId)
743+ let assetOut = if ((isReverse == false))
744+ then getStringOrFail(this, pa())
745+ else getStringOrFail(this, aa())
746+ let poolAssetInBalance = (getAccBalance(assetIn) - value(i.payments[0]).amount)
747+ let poolAssetOutBalance = getAccBalance(assetOut)
748+ let amountOut = fraction(poolAssetOutBalance, cleanAmountIn, (poolAssetInBalance + cleanAmountIn))
749+ let oldK = (toBigInt(poolAssetInBalance) * toBigInt(poolAssetOutBalance))
750+ let newK = ((toBigInt(getAccBalance(assetIn)) + toBigInt(feePoolAmount)) * (toBigInt(getAccBalance(assetOut)) - toBigInt(amountOut)))
751+ let checkK = if ((newK >= oldK))
752+ then true
753+ else throw("new K is fewer error")
754+ if ((checkK == checkK))
755+ then {
756+ let checkMin = if ((amountOut >= amountOutMin))
757+ then true
758+ else throw("Exchange result is fewer coins than expected")
759+ if ((checkMin == checkMin))
760+ then $Tuple2([ScriptTransfer(addressFromStringValue(addressTo), amountOut, parseAssetId(assetOut))], amountOut)
761+ else throw("Strict value is not equal to itself.")
762+ }
763+ else throw("Strict value is not equal to itself.")
764+ }
765+ else throw("Strict value is not equal to itself.")
766+ }
767+
768+
769+
770+@Callable(i)
639771 func setManager (pendingManagerPublicKey) = {
640772 let checkCaller = mustManager(i)
641773 if ((checkCaller == checkCaller))
642774 then {
643775 let checkManagerPublicKey = fromBase58String(pendingManagerPublicKey)
644776 if ((checkManagerPublicKey == checkManagerPublicKey))
645777 then [StringEntry(pmpk(), pendingManagerPublicKey)]
646778 else throw("Strict value is not equal to itself.")
647779 }
648780 else throw("Strict value is not equal to itself.")
649781 }
650782
651783
652784
653785 @Callable(i)
654786 func confirmManager () = {
655787 let pm = pendingManagerPublicKeyOrUnit()
656788 let hasPM = if (isDefined(pm))
657789 then true
658790 else throw("No pending manager")
659791 if ((hasPM == hasPM))
660792 then {
661793 let checkPM = if ((i.callerPublicKey == value(pm)))
662794 then true
663795 else throw("You are not pending manager")
664796 if ((checkPM == checkPM))
665797 then [StringEntry(mpk(), toBase58String(value(pm))), DeleteEntry(pmpk())]
666798 else throw("Strict value is not equal to itself.")
667799 }
668800 else throw("Strict value is not equal to itself.")
669801 }
670802
671803
672804
673805 @Callable(i)
674806 func put (slippageTolerance,shouldAutoStake) = if ((0 > slippageTolerance))
675807 then throw("Invalid slippageTolerance passed")
676808 else {
677809 let estPut = commonPut(i, slippageTolerance, true)
678810 let emitLpAmt = estPut._2
679811 let lpAssetId = estPut._7
680812 let state = estPut._9
681813 let amDiff = estPut._10
682814 let prDiff = estPut._11
683815 let amId = estPut._12
684816 let prId = estPut._13
685- let emitInv = invoke(factoryContract, "emit", [emitLpAmt], nil)
686- if ((emitInv == emitInv))
817+ let amAssetPmt = toBigInt(value(i.payments[0]).amount)
818+ let prAssetPmt = toBigInt(value(i.payments[1]).amount)
819+ let currentKLp = calcCurrentKLp(amAssetPmt, prAssetPmt, toBigInt(0))
820+ if ((currentKLp == currentKLp))
687821 then {
688- let emitInvLegacy = match emitInv {
689- case legacyFactoryContract: Address =>
690- invoke(legacyFactoryContract, "emit", [emitLpAmt], nil)
691- case _ =>
692- unit
693- }
694- if ((emitInvLegacy == emitInvLegacy))
822+ let emitInv = invoke(factoryContract, "emit", [emitLpAmt], nil)
823+ if ((emitInv == emitInv))
695824 then {
696- let slippageAInv = if ((amDiff > 0))
697- then invoke(slippageContract, "put", nil, [AttachedPayment(amId, amDiff)])
698- else nil
699- if ((slippageAInv == slippageAInv))
825+ let emitInvLegacy = match emitInv {
826+ case legacyFactoryContract: Address =>
827+ invoke(legacyFactoryContract, "emit", [emitLpAmt], nil)
828+ case _ =>
829+ unit
830+ }
831+ if ((emitInvLegacy == emitInvLegacy))
700832 then {
701- let slippagePInv = if ((prDiff > 0))
702- then invoke(slippageContract, "put", nil, [AttachedPayment(prId, prDiff)])
833+ let slippageAInv = if ((amDiff > 0))
834+ then invoke(slippageContract, "put", nil, [AttachedPayment(amId, amDiff)])
703835 else nil
704- if ((slippagePInv == slippagePInv))
836+ if ((slippageAInv == slippageAInv))
705837 then {
706- let lpTransfer = if (shouldAutoStake)
838+ let slippagePInv = if ((prDiff > 0))
839+ then invoke(slippageContract, "put", nil, [AttachedPayment(prId, prDiff)])
840+ else nil
841+ if ((slippagePInv == slippagePInv))
707842 then {
708- let slpStakeInv = invoke(stakingContract, "stake", nil, [AttachedPayment(lpAssetId, emitLpAmt)])
709- if ((slpStakeInv == slpStakeInv))
710- then nil
843+ let lpTransfer = if (shouldAutoStake)
844+ then {
845+ let slpStakeInv = invoke(stakingContract, "stake", nil, [AttachedPayment(lpAssetId, emitLpAmt)])
846+ if ((slpStakeInv == slpStakeInv))
847+ then nil
848+ else throw("Strict value is not equal to itself.")
849+ }
850+ else [ScriptTransfer(i.caller, emitLpAmt, lpAssetId)]
851+ let $t03716637628 = refreshKLpInternal(0, 0, 0)
852+ if (($t03716637628 == $t03716637628))
853+ then {
854+ let updatedKLp = $t03716637628._2
855+ let refreshKLpActions = $t03716637628._1
856+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
857+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
858+ then ((state ++ lpTransfer) ++ refreshKLpActions)
859+ else throw("Strict value is not equal to itself.")
860+ }
711861 else throw("Strict value is not equal to itself.")
712862 }
713- else [ScriptTransfer(i.caller, emitLpAmt, lpAssetId)]
714- (state ++ lpTransfer)
863+ else throw("Strict value is not equal to itself.")
715864 }
716865 else throw("Strict value is not equal to itself.")
717866 }
718867 else throw("Strict value is not equal to itself.")
719868 }
720869 else throw("Strict value is not equal to itself.")
721870 }
722871 else throw("Strict value is not equal to itself.")
723872 }
724873
725874
726875
727876 @Callable(i)
728877 func putForFree (maxSlippage) = if ((0 > maxSlippage))
729878 then throw("Invalid value passed")
730879 else {
731880 let estPut = commonPut(i, maxSlippage, false)
732- estPut._9
881+ let state = estPut._9
882+ let amAssetPmt = toBigInt(value(i.payments[0]).amount)
883+ let prAssetPmt = toBigInt(value(i.payments[1]).amount)
884+ let currentKLp = calcCurrentKLp(amAssetPmt, prAssetPmt, toBigInt(0))
885+ if ((currentKLp == currentKLp))
886+ then {
887+ let $t03819038255 = refreshKLpInternal(0, 0, 0)
888+ let refreshKLpActions = $t03819038255._1
889+ let updatedKLp = $t03819038255._2
890+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
891+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
892+ then (state ++ refreshKLpActions)
893+ else throw("Strict value is not equal to itself.")
894+ }
895+ else throw("Strict value is not equal to itself.")
733896 }
734897
735898
736899
737900 @Callable(i)
738901 func putOneTkn (minOutAmount,autoStake) = {
739902 let isPoolOneTokenOperationsDisabled = {
740903 let @ = invoke(factoryContract, "isPoolOneTokenOperationsDisabledREADONLY", [toString(this)], nil)
741904 if ($isInstanceOf(@, "Boolean"))
742905 then @
743906 else throw(($getType(@) + " couldn't be cast to Boolean"))
744907 }
745908 let isPutDisabled = if (if (if (isGlobalShutdown())
746909 then true
747910 else (cfgPoolStatus == PoolPutDisabled))
748911 then true
749912 else (cfgPoolStatus == PoolShutdown))
750913 then true
751914 else isPoolOneTokenOperationsDisabled
752915 let checks = [if (if (!(isPutDisabled))
753916 then true
754917 else isManager(i))
755918 then true
756919 else throwErr("put operation is blocked by admin"), if ((size(i.payments) == 1))
757920 then true
758921 else throwErr("exactly 1 payment are expected")]
759922 if ((checks == checks))
760923 then {
761924 let payment = i.payments[0]
762925 let paymentAssetId = payment.assetId
763926 let paymentAmountRaw = payment.amount
764- let userAddress = i.caller
765- let txId = i.transactionId
766- let $t03172331853 = calcPutOneToken(paymentAmountRaw, paymentAssetId, userAddress, txId)
767- if (($t03172331853 == $t03172331853))
927+ let currentKLp = if ((paymentAssetId == cfgAmountAssetId))
928+ then calcCurrentKLp(toBigInt(paymentAmountRaw), toBigInt(0), toBigInt(0))
929+ else if ((paymentAssetId == cfgPriceAssetId))
930+ then calcCurrentKLp(toBigInt(0), toBigInt(paymentAmountRaw), toBigInt(0))
931+ else throwErr("payment asset is not supported")
932+ if ((currentKLp == currentKLp))
768933 then {
769- let bonus = $t03172331853._4
770- let feeAmount = $t03172331853._3
771- let commonState = $t03172331853._2
772- let emitAmountEstimated = $t03172331853._1
773- let emitAmount = if (if ((minOutAmount > 0))
774- then (minOutAmount > emitAmountEstimated)
775- else false)
776- then throwErr(makeString(["amount to receive is less than ", toString(minOutAmount)], ""))
777- else emitAmountEstimated
778- let emitInv = emit(emitAmount)
779- if ((emitInv == emitInv))
934+ let userAddress = i.caller
935+ let txId = i.transactionId
936+ let $t03944339595 = calcPutOneToken(paymentAmountRaw, paymentAssetId, userAddress, txId)
937+ if (($t03944339595 == $t03944339595))
780938 then {
781- let lpTransfer = if (autoStake)
939+ let paymentInAmountAsset = $t03944339595._5
940+ let bonus = $t03944339595._4
941+ let feeAmount = $t03944339595._3
942+ let commonState = $t03944339595._2
943+ let emitAmountEstimated = $t03944339595._1
944+ let emitAmount = if (if ((minOutAmount > 0))
945+ then (minOutAmount > emitAmountEstimated)
946+ else false)
947+ then throwErr(makeString(["amount to receive is less than ", toString(minOutAmount)], ""))
948+ else emitAmountEstimated
949+ let emitInv = emit(emitAmount)
950+ if ((emitInv == emitInv))
782951 then {
783- let stakeInv = invoke(stakingContract, "stake", nil, [AttachedPayment(cfgLpAssetId, emitAmount)])
784- if ((stakeInv == stakeInv))
785- then nil
952+ let lpTransfer = if (autoStake)
953+ then {
954+ let stakeInv = invoke(stakingContract, "stake", nil, [AttachedPayment(cfgLpAssetId, emitAmount)])
955+ if ((stakeInv == stakeInv))
956+ then nil
957+ else throw("Strict value is not equal to itself.")
958+ }
959+ else [ScriptTransfer(i.caller, emitAmount, cfgLpAssetId)]
960+ let sendFee = if ((feeAmount > 0))
961+ then [ScriptTransfer(feeCollectorAddress, feeAmount, paymentAssetId)]
962+ else nil
963+ let $t04018140378 = if ((this == feeCollectorAddress))
964+ then $Tuple2(0, 0)
965+ else if (paymentInAmountAsset)
966+ then $Tuple2(-(feeAmount), 0)
967+ else $Tuple2(0, -(feeAmount))
968+ let amountAssetBalanceDelta = $t04018140378._1
969+ let priceAssetBalanceDelta = $t04018140378._2
970+ let $t04038140489 = refreshKLpInternal(amountAssetBalanceDelta, priceAssetBalanceDelta, 0)
971+ let refreshKLpActions = $t04038140489._1
972+ let updatedKLp = $t04038140489._2
973+ let kLp = value(getString(keyKLp))
974+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
975+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
976+ then $Tuple2((((commonState ++ lpTransfer) ++ sendFee) ++ refreshKLpActions), emitAmount)
786977 else throw("Strict value is not equal to itself.")
787978 }
788- else [ScriptTransfer(i.caller, emitAmount, cfgLpAssetId)]
789- let sendFee = if ((feeAmount > 0))
790- then [ScriptTransfer(feeCollectorAddress, feeAmount, paymentAssetId)]
791- else nil
792- $Tuple2(((commonState ++ lpTransfer) ++ sendFee), emitAmount)
979+ else throw("Strict value is not equal to itself.")
793980 }
794981 else throw("Strict value is not equal to itself.")
795982 }
796983 else throw("Strict value is not equal to itself.")
797984 }
798985 else throw("Strict value is not equal to itself.")
799986 }
800987
801988
802989
803990 @Callable(i)
804991 func putOneTknREADONLY (paymentAssetId,paymentAmountRaw) = {
805- let $t03258232717 = calcPutOneToken(paymentAmountRaw, parseAssetId(paymentAssetId), unit, unit)
806- let emitAmountEstimated = $t03258232717._1
807- let commonState = $t03258232717._2
808- let feeAmount = $t03258232717._3
809- let bonus = $t03258232717._4
992+ let $t04079540952 = calcPutOneToken(paymentAmountRaw, parseAssetId(paymentAssetId), unit, unit)
993+ let emitAmountEstimated = $t04079540952._1
994+ let commonState = $t04079540952._2
995+ let feeAmount = $t04079540952._3
996+ let bonus = $t04079540952._4
997+ let paymentInAmountAsset = $t04079540952._5
810998 $Tuple2(nil, $Tuple3(emitAmountEstimated, feeAmount, bonus))
811999 }
8121000
8131001
8141002
8151003 @Callable(i)
8161004 func getOneTkn (outAssetIdStr,minOutAmount) = {
8171005 let isPoolOneTokenOperationsDisabled = {
8181006 let @ = invoke(factoryContract, "isPoolOneTokenOperationsDisabledREADONLY", [toString(this)], nil)
8191007 if ($isInstanceOf(@, "Boolean"))
8201008 then @
8211009 else throw(($getType(@) + " couldn't be cast to Boolean"))
8221010 }
8231011 let isGetDisabled = if (if (isGlobalShutdown())
8241012 then true
8251013 else (cfgPoolStatus == PoolShutdown))
8261014 then true
8271015 else isPoolOneTokenOperationsDisabled
8281016 let checks = [if (if (!(isGetDisabled))
8291017 then true
8301018 else isManager(i))
8311019 then true
8321020 else throwErr("get operation is blocked by admin"), if ((size(i.payments) == 1))
8331021 then true
8341022 else throwErr("exactly 1 payment are expected")]
8351023 if ((checks == checks))
8361024 then {
8371025 let outAssetId = parseAssetId(outAssetIdStr)
8381026 let payment = i.payments[0]
8391027 let paymentAssetId = payment.assetId
8401028 let paymentAmount = payment.amount
841- let userAddress = i.caller
842- let txId = i.transactionId
843- let $t03352233657 = calcGetOneToken(outAssetId, paymentAmount, paymentAssetId, userAddress, txId)
844- if (($t03352233657 == $t03352233657))
1029+ let currentKLp = calcCurrentKLp(toBigInt(0), toBigInt(0), toBigInt(0))
1030+ if ((currentKLp == currentKLp))
8451031 then {
846- let bonus = $t03352233657._4
847- let feeAmount = $t03352233657._3
848- let commonState = $t03352233657._2
849- let amountEstimated = $t03352233657._1
850- let amount = if (if ((minOutAmount > 0))
851- then (minOutAmount > amountEstimated)
852- else false)
853- then throwErr(makeString(["amount to receive is less than ", toString(minOutAmount)], ""))
854- else amountEstimated
855- let burnInv = invoke(factoryContract, "burn", [paymentAmount], [AttachedPayment(paymentAssetId, paymentAmount)])
856- if ((burnInv == burnInv))
1032+ let userAddress = i.caller
1033+ let txId = i.transactionId
1034+ let $t04183741990 = calcGetOneToken(outAssetId, paymentAmount, paymentAssetId, userAddress, txId)
1035+ if (($t04183741990 == $t04183741990))
8571036 then {
858- let assetTransfer = [ScriptTransfer(userAddress, amount, outAssetId)]
859- let sendFee = if ((feeAmount > 0))
860- then [ScriptTransfer(feeCollectorAddress, feeAmount, outAssetId)]
861- else nil
862- $Tuple2(((commonState ++ assetTransfer) ++ sendFee), amount)
1037+ let outInAmountAsset = $t04183741990._5
1038+ let bonus = $t04183741990._4
1039+ let feeAmount = $t04183741990._3
1040+ let commonState = $t04183741990._2
1041+ let amountEstimated = $t04183741990._1
1042+ let amount = if (if ((minOutAmount > 0))
1043+ then (minOutAmount > amountEstimated)
1044+ else false)
1045+ then throwErr(makeString(["amount to receive is less than ", toString(minOutAmount)], ""))
1046+ else amountEstimated
1047+ let burnInv = invoke(factoryContract, "burn", [paymentAmount], [AttachedPayment(paymentAssetId, paymentAmount)])
1048+ if ((burnInv == burnInv))
1049+ then {
1050+ let assetTransfer = [ScriptTransfer(userAddress, amount, outAssetId)]
1051+ let sendFee = if ((feeAmount > 0))
1052+ then [ScriptTransfer(feeCollectorAddress, feeAmount, outAssetId)]
1053+ else nil
1054+ let $t04249042737 = {
1055+ let feeAmountForCalc = if ((this == feeCollectorAddress))
1056+ then 0
1057+ else feeAmount
1058+ if (outInAmountAsset)
1059+ then $Tuple2(-((amount + feeAmountForCalc)), 0)
1060+ else $Tuple2(0, -((amount + feeAmountForCalc)))
1061+ }
1062+ let amountAssetBalanceDelta = $t04249042737._1
1063+ let priceAssetBalanceDelta = $t04249042737._2
1064+ let $t04274042848 = refreshKLpInternal(amountAssetBalanceDelta, priceAssetBalanceDelta, 0)
1065+ let refreshKLpActions = $t04274042848._1
1066+ let updatedKLp = $t04274042848._2
1067+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
1068+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
1069+ then $Tuple2((((commonState ++ assetTransfer) ++ sendFee) ++ refreshKLpActions), amount)
1070+ else throw("Strict value is not equal to itself.")
1071+ }
1072+ else throw("Strict value is not equal to itself.")
8631073 }
8641074 else throw("Strict value is not equal to itself.")
8651075 }
8661076 else throw("Strict value is not equal to itself.")
8671077 }
8681078 else throw("Strict value is not equal to itself.")
8691079 }
8701080
8711081
8721082
8731083 @Callable(i)
8741084 func getOneTknREADONLY (outAssetId,paymentAmount) = {
875- let $t03429234430 = calcGetOneToken(parseAssetId(outAssetId), paymentAmount, cfgLpAssetId, unit, unit)
876- let amountEstimated = $t03429234430._1
877- let commonState = $t03429234430._2
878- let feeAmount = $t03429234430._3
879- let bonus = $t03429234430._4
1085+ let $t04310543261 = calcGetOneToken(parseAssetId(outAssetId), paymentAmount, cfgLpAssetId, unit, unit)
1086+ let amountEstimated = $t04310543261._1
1087+ let commonState = $t04310543261._2
1088+ let feeAmount = $t04310543261._3
1089+ let bonus = $t04310543261._4
1090+ let outInAmountAsset = $t04310543261._5
8801091 $Tuple2(nil, $Tuple3(amountEstimated, feeAmount, bonus))
8811092 }
8821093
8831094
8841095
8851096 @Callable(i)
8861097 func unstakeAndGetOneTkn (unstakeAmount,outAssetIdStr,minOutAmount) = {
8871098 let isPoolOneTokenOperationsDisabled = {
8881099 let @ = invoke(factoryContract, "isPoolOneTokenOperationsDisabledREADONLY", [toString(this)], nil)
8891100 if ($isInstanceOf(@, "Boolean"))
8901101 then @
8911102 else throw(($getType(@) + " couldn't be cast to Boolean"))
8921103 }
8931104 let isGetDisabled = if (if (isGlobalShutdown())
8941105 then true
8951106 else (cfgPoolStatus == PoolShutdown))
8961107 then true
8971108 else isPoolOneTokenOperationsDisabled
8981109 let checks = [if (if (!(isGetDisabled))
8991110 then true
9001111 else isManager(i))
9011112 then true
9021113 else throwErr("get operation is blocked by admin"), if ((size(i.payments) == 0))
9031114 then true
9041115 else throwErr("no payments are expected")]
9051116 if ((checks == checks))
9061117 then {
9071118 let outAssetId = parseAssetId(outAssetIdStr)
9081119 let userAddress = i.caller
9091120 let txId = i.transactionId
910- let unstakeInv = invoke(stakingContract, "unstake", [toBase58String(cfgLpAssetId), unstakeAmount], nil)
911- if ((unstakeInv == unstakeInv))
1121+ let currentKLp = calcCurrentKLp(toBigInt(0), toBigInt(0), toBigInt(0))
1122+ if ((currentKLp == currentKLp))
9121123 then {
913- let $t03525535388 = calcGetOneToken(outAssetId, unstakeAmount, cfgLpAssetId, userAddress, txId)
914- if (($t03525535388 == $t03525535388))
1124+ let unstakeInv = invoke(stakingContract, "unstake", [toBase58String(cfgLpAssetId), unstakeAmount], nil)
1125+ if ((unstakeInv == unstakeInv))
9151126 then {
916- let bonus = $t03525535388._4
917- let feeAmount = $t03525535388._3
918- let commonState = $t03525535388._2
919- let amountEstimated = $t03525535388._1
920- let amount = if (if ((minOutAmount > 0))
921- then (minOutAmount > amountEstimated)
922- else false)
923- then throwErr(makeString(["amount to receive is less than ", toString(minOutAmount)], ""))
924- else amountEstimated
925- let burnInv = invoke(factoryContract, "burn", [unstakeAmount], [AttachedPayment(cfgLpAssetId, unstakeAmount)])
926- if ((burnInv == burnInv))
1127+ let $t04416644317 = calcGetOneToken(outAssetId, unstakeAmount, cfgLpAssetId, userAddress, txId)
1128+ if (($t04416644317 == $t04416644317))
9271129 then {
928- let assetTransfer = [ScriptTransfer(i.caller, amount, outAssetId)]
929- let sendFee = if ((feeAmount > 0))
930- then [ScriptTransfer(feeCollectorAddress, feeAmount, outAssetId)]
931- else nil
932- $Tuple2(((commonState ++ assetTransfer) ++ sendFee), amount)
1130+ let outInAmountAsset = $t04416644317._5
1131+ let bonus = $t04416644317._4
1132+ let feeAmount = $t04416644317._3
1133+ let commonState = $t04416644317._2
1134+ let amountEstimated = $t04416644317._1
1135+ let amount = if (if ((minOutAmount > 0))
1136+ then (minOutAmount > amountEstimated)
1137+ else false)
1138+ then throwErr(makeString(["amount to receive is less than ", toString(minOutAmount)], ""))
1139+ else amountEstimated
1140+ let burnInv = invoke(factoryContract, "burn", [unstakeAmount], [AttachedPayment(cfgLpAssetId, unstakeAmount)])
1141+ if ((burnInv == burnInv))
1142+ then {
1143+ let assetTransfer = [ScriptTransfer(i.caller, amount, outAssetId)]
1144+ let sendFee = if ((feeAmount > 0))
1145+ then [ScriptTransfer(feeCollectorAddress, feeAmount, outAssetId)]
1146+ else nil
1147+ let $t04481245059 = {
1148+ let feeAmountForCalc = if ((this == feeCollectorAddress))
1149+ then 0
1150+ else feeAmount
1151+ if (outInAmountAsset)
1152+ then $Tuple2(-((amount + feeAmountForCalc)), 0)
1153+ else $Tuple2(0, -((amount + feeAmountForCalc)))
1154+ }
1155+ let amountAssetBalanceDelta = $t04481245059._1
1156+ let priceAssetBalanceDelta = $t04481245059._2
1157+ let $t04506245170 = refreshKLpInternal(amountAssetBalanceDelta, priceAssetBalanceDelta, 0)
1158+ let refreshKLpActions = $t04506245170._1
1159+ let updatedKLp = $t04506245170._2
1160+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
1161+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
1162+ then $Tuple2((((commonState ++ assetTransfer) ++ sendFee) ++ refreshKLpActions), amount)
1163+ else throw("Strict value is not equal to itself.")
1164+ }
1165+ else throw("Strict value is not equal to itself.")
9331166 }
9341167 else throw("Strict value is not equal to itself.")
9351168 }
9361169 else throw("Strict value is not equal to itself.")
9371170 }
9381171 else throw("Strict value is not equal to itself.")
9391172 }
9401173 else throw("Strict value is not equal to itself.")
9411174 }
9421175
9431176
9441177
9451178 @Callable(i)
9461179 func get () = {
9471180 let res = commonGet(i)
9481181 let outAmtAmt = res._1
9491182 let outPrAmt = res._2
9501183 let pmtAmt = res._3
9511184 let pmtAssetId = res._4
9521185 let state = res._5
953- let burnLPAssetOnFactory = invoke(factoryContract, "burn", [pmtAmt], [AttachedPayment(pmtAssetId, pmtAmt)])
954- if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
955- then state
1186+ let currentKLp = calcCurrentKLp(toBigInt(0), toBigInt(0), toBigInt(0))
1187+ if ((currentKLp == currentKLp))
1188+ then {
1189+ let burnLPAssetOnFactory = invoke(factoryContract, "burn", [pmtAmt], [AttachedPayment(pmtAssetId, pmtAmt)])
1190+ if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
1191+ then {
1192+ let $t04611646198 = refreshKLpInternal(-(outAmtAmt), -(outPrAmt), 0)
1193+ let refreshKLpActions = $t04611646198._1
1194+ let updatedKLp = $t04611646198._2
1195+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
1196+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
1197+ then (state ++ refreshKLpActions)
1198+ else throw("Strict value is not equal to itself.")
1199+ }
1200+ else throw("Strict value is not equal to itself.")
1201+ }
9561202 else throw("Strict value is not equal to itself.")
9571203 }
9581204
9591205
9601206
9611207 @Callable(i)
9621208 func getNoLess (noLessThenAmtAsset,noLessThenPriceAsset) = {
9631209 let res = commonGet(i)
9641210 let outAmAmt = res._1
9651211 let outPrAmt = res._2
9661212 let pmtAmt = res._3
9671213 let pmtAssetId = res._4
9681214 let state = res._5
9691215 if ((noLessThenAmtAsset > outAmAmt))
9701216 then throw(((("noLessThenAmtAsset failed: " + toString(outAmAmt)) + " < ") + toString(noLessThenAmtAsset)))
9711217 else if ((noLessThenPriceAsset > outPrAmt))
9721218 then throw(((("noLessThenPriceAsset failed: " + toString(outPrAmt)) + " < ") + toString(noLessThenPriceAsset)))
9731219 else {
974- let burnLPAssetOnFactory = invoke(factoryContract, "burn", [pmtAmt], [AttachedPayment(pmtAssetId, pmtAmt)])
975- if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
976- then state
1220+ let currentKLp = calcCurrentKLp(toBigInt(0), toBigInt(0), toBigInt(0))
1221+ if ((currentKLp == currentKLp))
1222+ then {
1223+ let burnLPAssetOnFactory = invoke(factoryContract, "burn", [pmtAmt], [AttachedPayment(pmtAssetId, pmtAmt)])
1224+ if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
1225+ then {
1226+ let $t04714747228 = refreshKLpInternal(-(outAmAmt), -(outPrAmt), 0)
1227+ let refreshKLpActions = $t04714747228._1
1228+ let updatedKLp = $t04714747228._2
1229+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
1230+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
1231+ then (state ++ refreshKLpActions)
1232+ else throw("Strict value is not equal to itself.")
1233+ }
1234+ else throw("Strict value is not equal to itself.")
1235+ }
9771236 else throw("Strict value is not equal to itself.")
9781237 }
9791238 }
9801239
9811240
9821241
9831242 @Callable(i)
9841243 func unstakeAndGet (amount) = {
9851244 let checkPayments = if ((size(i.payments) != 0))
9861245 then throw("No payments are expected")
9871246 else true
9881247 if ((checkPayments == checkPayments))
9891248 then {
9901249 let cfg = getPoolConfig()
9911250 let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
992- let unstakeInv = invoke(stakingContract, "unstake", [toBase58String(lpAssetId), amount], nil)
993- if ((unstakeInv == unstakeInv))
1251+ let currentKLp = calcCurrentKLp(toBigInt(0), toBigInt(0), toBigInt(0))
1252+ if ((currentKLp == currentKLp))
9941253 then {
995- let res = estimateGetOperation(toBase58String(i.transactionId), toBase58String(lpAssetId), amount, i.caller)
996- let poolStatus = parseIntValue(res._9)
997- let state = res._10
998- let checkPoolStatus = if (if (isGlobalShutdown())
999- then true
1000- else (poolStatus == PoolShutdown))
1001- then throw(("Get operation is blocked by admin. Status = " + toString(poolStatus)))
1002- else true
1003- if ((checkPoolStatus == checkPoolStatus))
1254+ let unstakeInv = invoke(stakingContract, "unstake", [toBase58String(lpAssetId), amount], nil)
1255+ if ((unstakeInv == unstakeInv))
10041256 then {
1005- let burnLPAssetOnFactory = invoke(factoryContract, "burn", [amount], [AttachedPayment(lpAssetId, amount)])
1006- if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
1007- then state
1257+ let res = estimateGetOperation(toBase58String(i.transactionId), toBase58String(lpAssetId), amount, i.caller)
1258+ let outAmAmt = res._1
1259+ let outPrAmt = res._2
1260+ let poolStatus = parseIntValue(res._9)
1261+ let state = res._10
1262+ let checkPoolStatus = if (if (isGlobalShutdown())
1263+ then true
1264+ else (poolStatus == PoolShutdown))
1265+ then throw(("Get operation is blocked by admin. Status = " + toString(poolStatus)))
1266+ else true
1267+ if ((checkPoolStatus == checkPoolStatus))
1268+ then {
1269+ let burnLPAssetOnFactory = invoke(factoryContract, "burn", [amount], [AttachedPayment(lpAssetId, amount)])
1270+ if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
1271+ then {
1272+ let $t04835448435 = refreshKLpInternal(-(outAmAmt), -(outPrAmt), 0)
1273+ let refreshKLpActions = $t04835448435._1
1274+ let updatedKLp = $t04835448435._2
1275+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
1276+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
1277+ then (state ++ refreshKLpActions)
1278+ else throw("Strict value is not equal to itself.")
1279+ }
1280+ else throw("Strict value is not equal to itself.")
1281+ }
10081282 else throw("Strict value is not equal to itself.")
10091283 }
10101284 else throw("Strict value is not equal to itself.")
10111285 }
10121286 else throw("Strict value is not equal to itself.")
10131287 }
10141288 else throw("Strict value is not equal to itself.")
10151289 }
10161290
10171291
10181292
10191293 @Callable(i)
10201294 func unstakeAndGetNoLess (unstakeAmount,noLessThenAmountAsset,noLessThenPriceAsset) = {
10211295 let isGetDisabled = if (isGlobalShutdown())
10221296 then true
10231297 else (cfgPoolStatus == PoolShutdown)
10241298 let checks = [if (!(isGetDisabled))
10251299 then true
10261300 else throw("get operation is blocked by admin"), if ((size(i.payments) == 0))
10271301 then true
10281302 else throw("no payments are expected")]
10291303 if ((checks == checks))
10301304 then {
1031- let unstakeInv = invoke(stakingContract, "unstake", [toBase58String(cfgLpAssetId), unstakeAmount], nil)
1032- if ((unstakeInv == unstakeInv))
1305+ let currentKLp = calcCurrentKLp(toBigInt(0), toBigInt(0), toBigInt(0))
1306+ if ((currentKLp == currentKLp))
10331307 then {
1034- let res = estimateGetOperation(toBase58String(i.transactionId), toBase58String(cfgLpAssetId), unstakeAmount, i.caller)
1035- let outAmAmt = res._1
1036- let outPrAmt = res._2
1037- let state = res._10
1038- let checkAmounts = [if ((outAmAmt >= noLessThenAmountAsset))
1039- then true
1040- else throw(makeString(["amount asset amount to receive is less than ", toString(noLessThenAmountAsset)], "")), if ((outPrAmt >= noLessThenPriceAsset))
1041- then true
1042- else throw(makeString(["price asset amount to receive is less than ", toString(noLessThenPriceAsset)], ""))]
1043- if ((checkAmounts == checkAmounts))
1308+ let unstakeInv = invoke(stakingContract, "unstake", [toBase58String(cfgLpAssetId), unstakeAmount], nil)
1309+ if ((unstakeInv == unstakeInv))
10441310 then {
1045- let burnLPAssetOnFactory = invoke(factoryContract, "burn", [unstakeAmount], [AttachedPayment(cfgLpAssetId, unstakeAmount)])
1046- if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
1047- then state
1311+ let res = estimateGetOperation(toBase58String(i.transactionId), toBase58String(cfgLpAssetId), unstakeAmount, i.caller)
1312+ let outAmAmt = res._1
1313+ let outPrAmt = res._2
1314+ let state = res._10
1315+ let checkAmounts = [if ((outAmAmt >= noLessThenAmountAsset))
1316+ then true
1317+ else throw(makeString(["amount asset amount to receive is less than ", toString(noLessThenAmountAsset)], "")), if ((outPrAmt >= noLessThenPriceAsset))
1318+ then true
1319+ else throw(makeString(["price asset amount to receive is less than ", toString(noLessThenPriceAsset)], ""))]
1320+ if ((checkAmounts == checkAmounts))
1321+ then {
1322+ let burnLPAssetOnFactory = invoke(factoryContract, "burn", [unstakeAmount], [AttachedPayment(cfgLpAssetId, unstakeAmount)])
1323+ if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
1324+ then {
1325+ let $t04973049811 = refreshKLpInternal(-(outAmAmt), -(outPrAmt), 0)
1326+ let refreshKLpActions = $t04973049811._1
1327+ let updatedKLp = $t04973049811._2
1328+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
1329+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
1330+ then (state ++ refreshKLpActions)
1331+ else throw("Strict value is not equal to itself.")
1332+ }
1333+ else throw("Strict value is not equal to itself.")
1334+ }
10481335 else throw("Strict value is not equal to itself.")
10491336 }
10501337 else throw("Strict value is not equal to itself.")
10511338 }
10521339 else throw("Strict value is not equal to itself.")
10531340 }
10541341 else throw("Strict value is not equal to itself.")
10551342 }
10561343
10571344
10581345
10591346 @Callable(i)
10601347 func activate (amtAssetStr,priceAssetStr) = if ((toString(i.caller) != toString(factoryContract)))
10611348 then throw("permissions denied")
10621349 else $Tuple2([StringEntry(aa(), amtAssetStr), StringEntry(pa(), priceAssetStr)], "success")
1350+
1351+
1352+
1353+@Callable(i)
1354+func refreshKLp () = {
1355+ let lastRefreshedBlockHeight = valueOrElse(getInteger(keyKLpRefreshedHeight), 0)
1356+ let checkLastRefreshedBlockHeight = if (((height - lastRefreshedBlockHeight) >= kLpRefreshDelay))
1357+ then unit
1358+ else throwErr(makeString([toString(kLpRefreshDelay), " blocks have not passed since the previous call"], ""))
1359+ if ((checkLastRefreshedBlockHeight == checkLastRefreshedBlockHeight))
1360+ then {
1361+ let kLp = valueOrErrorMessage(parseBigInt(valueOrElse(getString(this, keyKLp), "0")), fmtErr("invalid kLp"))
1362+ let $t05099851062 = refreshKLpInternal(0, 0, 0)
1363+ let kLpUpdateActions = $t05099851062._1
1364+ let updatedKLp = $t05099851062._2
1365+ let actions = if ((kLp != updatedKLp))
1366+ then kLpUpdateActions
1367+ else throwErr("nothing to refresh")
1368+ $Tuple2(actions, toString(updatedKLp))
1369+ }
1370+ else throw("Strict value is not equal to itself.")
1371+ }
10631372
10641373
10651374
10661375 @Callable(i)
10671376 func getPoolConfigWrapperREADONLY () = $Tuple2(nil, getPoolConfig())
10681377
10691378
10701379
10711380 @Callable(i)
10721381 func getAccBalanceWrapperREADONLY (assetId) = $Tuple2(nil, getAccBalance(assetId))
10731382
10741383
10751384
10761385 @Callable(i)
10771386 func calcPricesWrapperREADONLY (amAmt,prAmt,lpAmt) = {
10781387 let prices = calcPrices(amAmt, prAmt, lpAmt)
10791388 $Tuple2(nil, [toString(prices[0]), toString(prices[1]), toString(prices[2])])
10801389 }
10811390
10821391
10831392
10841393 @Callable(i)
10851394 func toX18WrapperREADONLY (origVal,origScaleMult) = $Tuple2(nil, toString(toX18(origVal, origScaleMult)))
10861395
10871396
10881397
10891398 @Callable(i)
10901399 func fromX18WrapperREADONLY (val,resultScaleMult) = $Tuple2(nil, fromX18(parseBigIntValue(val), resultScaleMult))
10911400
10921401
10931402
10941403 @Callable(i)
10951404 func calcPriceBigIntWrapperREADONLY (prAmtX18,amAmtX18) = $Tuple2(nil, toString(calcPriceBigInt(parseBigIntValue(prAmtX18), parseBigIntValue(amAmtX18))))
10961405
10971406
10981407
10991408 @Callable(i)
11001409 func estimatePutOperationWrapperREADONLY (txId58,slippageTolerance,inAmAssetAmt,inAmAssetId,inPrAssetAmt,inPrAssetId,userAddress,isEvaluate,emitLp) = $Tuple2(nil, estimatePutOperation(txId58, slippageTolerance, inAmAssetAmt, inAmAssetId, inPrAssetAmt, inPrAssetId, userAddress, isEvaluate, emitLp))
11011410
11021411
11031412
11041413 @Callable(i)
11051414 func estimateGetOperationWrapperREADONLY (txId58,pmtAssetId,pmtLpAmt,userAddress) = {
11061415 let res = estimateGetOperation(txId58, pmtAssetId, pmtLpAmt, addressFromStringValue(userAddress))
11071416 $Tuple2(nil, $Tuple10(res._1, res._2, res._3, res._4, res._5, res._6, res._7, toString(res._8), res._9, res._10))
11081417 }
11091418
11101419
11111420
11121421 @Callable(i)
11131422 func statsREADONLY () = {
11141423 let cfg = getPoolConfig()
11151424 let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
11161425 let amtAssetId = cfg[idxAmtAssetId]
11171426 let priceAssetId = cfg[idxPriceAssetId]
11181427 let iAmtAssetId = cfg[idxIAmtAssetId]
11191428 let iPriceAssetId = cfg[idxIPriceAssetId]
11201429 let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
11211430 let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
11221431 let poolLPBalance = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
11231432 let accAmtAssetBalance = getAccBalance(amtAssetId)
11241433 let accPriceAssetBalance = getAccBalance(priceAssetId)
11251434 let pricesList = if ((poolLPBalance == 0))
11261435 then [zeroBigInt, zeroBigInt, zeroBigInt]
11271436 else calcPrices(accAmtAssetBalance, accPriceAssetBalance, poolLPBalance)
11281437 let curPrice = 0
11291438 let lpAmtAssetShare = fromX18(pricesList[1], scale8)
11301439 let lpPriceAssetShare = fromX18(pricesList[2], scale8)
11311440 let poolWeight = value(getInteger(factoryContract, keyPoolWeight(toString(this))))
11321441 $Tuple2(nil, makeString(["%d%d%d%d%d%d%d", toString(accAmtAssetBalance), toString(accPriceAssetBalance), toString(poolLPBalance), toString(curPrice), toString(lpAmtAssetShare), toString(lpPriceAssetShare), toString(poolWeight)], SEP))
11331442 }
11341443
11351444
11361445
11371446 @Callable(i)
11381447 func evaluatePutByAmountAssetREADONLY (inAmAssetAmt) = {
11391448 let cfg = getPoolConfig()
11401449 let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
11411450 let amAssetIdStr = cfg[idxAmtAssetId]
11421451 let amAssetId = fromBase58String(amAssetIdStr)
11431452 let prAssetIdStr = cfg[idxPriceAssetId]
11441453 let prAssetId = fromBase58String(prAssetIdStr)
11451454 let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
11461455 let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
11471456 let poolStatus = cfg[idxPoolStatus]
11481457 let poolLPBalance = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
11491458 let accAmtAssetBalance = getAccBalance(amAssetIdStr)
11501459 let accPriceAssetBalance = getAccBalance(prAssetIdStr)
11511460 let amtAssetAmtX18 = toX18(accAmtAssetBalance, amtAssetDcm)
11521461 let priceAssetAmtX18 = toX18(accPriceAssetBalance, priceAssetDcm)
11531462 let curPriceX18 = if ((poolLPBalance == 0))
11541463 then zeroBigInt
11551464 else calcPriceBigInt(priceAssetAmtX18, amtAssetAmtX18)
11561465 let inAmAssetAmtX18 = toX18(inAmAssetAmt, amtAssetDcm)
11571466 let inPrAssetAmtX18 = fraction(inAmAssetAmtX18, curPriceX18, scale18)
11581467 let inPrAssetAmt = fromX18(inPrAssetAmtX18, priceAssetDcm)
11591468 let estPut = estimatePutOperation("", 500000, inAmAssetAmt, amAssetId, inPrAssetAmt, prAssetId, "", true, false)
11601469 let calcLpAmt = estPut._1
11611470 let curPriceCalc = estPut._3
11621471 let amBalance = estPut._4
11631472 let prBalance = estPut._5
11641473 let lpEmission = estPut._6
11651474 $Tuple2(nil, makeString(["%d%d%d%d%d%d%d%d", toString(calcLpAmt), toString(fromX18(curPriceX18, scale8)), toString(amBalance), toString(prBalance), toString(lpEmission), poolStatus, toString(inAmAssetAmt), toString(inPrAssetAmt)], SEP))
11661475 }
11671476
11681477
11691478
11701479 @Callable(i)
11711480 func evaluatePutByPriceAssetREADONLY (inPrAssetAmt) = {
11721481 let cfg = getPoolConfig()
11731482 let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
11741483 let amAssetIdStr = cfg[idxAmtAssetId]
11751484 let amAssetId = fromBase58String(amAssetIdStr)
11761485 let prAssetIdStr = cfg[idxPriceAssetId]
11771486 let prAssetId = fromBase58String(prAssetIdStr)
11781487 let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
11791488 let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
11801489 let poolStatus = cfg[idxPoolStatus]
11811490 let poolLPBalance = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
11821491 let amBalanceRaw = getAccBalance(amAssetIdStr)
11831492 let prBalanceRaw = getAccBalance(prAssetIdStr)
11841493 let amBalanceRawX18 = toX18(amBalanceRaw, amtAssetDcm)
11851494 let prBalanceRawX18 = toX18(prBalanceRaw, priceAssetDcm)
11861495 let curPriceX18 = if ((poolLPBalance == 0))
11871496 then zeroBigInt
11881497 else calcPriceBigInt(prBalanceRawX18, amBalanceRawX18)
11891498 let inPrAssetAmtX18 = toX18(inPrAssetAmt, priceAssetDcm)
11901499 let inAmAssetAmtX18 = fraction(inPrAssetAmtX18, scale18, curPriceX18)
11911500 let inAmAssetAmt = fromX18(inAmAssetAmtX18, amtAssetDcm)
11921501 let estPut = estimatePutOperation("", 500000, inAmAssetAmt, amAssetId, inPrAssetAmt, prAssetId, "", true, false)
11931502 let calcLpAmt = estPut._1
11941503 let curPriceCalc = estPut._3
11951504 let amBalance = estPut._4
11961505 let prBalance = estPut._5
11971506 let lpEmission = estPut._6
11981507 $Tuple2(nil, makeString(["%d%d%d%d%d%d%d%d", toString(calcLpAmt), toString(fromX18(curPriceX18, scale8)), toString(amBalance), toString(prBalance), toString(lpEmission), poolStatus, toString(inAmAssetAmt), toString(inPrAssetAmt)], SEP))
11991508 }
12001509
12011510
12021511
12031512 @Callable(i)
12041513 func evaluateGetREADONLY (paymentLpAssetId,paymentLpAmt) = {
12051514 let res = estimateGetOperation("", paymentLpAssetId, paymentLpAmt, this)
12061515 let outAmAmt = res._1
12071516 let outPrAmt = res._2
12081517 let amBalance = res._5
12091518 let prBalance = res._6
12101519 let lpEmission = res._7
12111520 let curPrice = res._8
12121521 let poolStatus = parseIntValue(res._9)
12131522 $Tuple2(nil, makeString(["%d%d%d%d%d%d%d", toString(outAmAmt), toString(outPrAmt), toString(amBalance), toString(prBalance), toString(lpEmission), toString(curPrice), toString(poolStatus)], SEP))
12141523 }
12151524
12161525
12171526 @Verifier(tx)
12181527 func verify () = {
12191528 let targetPublicKey = match managerPublicKeyOrUnit() {
12201529 case pk: ByteVector =>
12211530 pk
12221531 case _: Unit =>
12231532 tx.senderPublicKey
12241533 case _ =>
12251534 throw("Match error")
12261535 }
12271536 match tx {
12281537 case order: Order =>
12291538 let matcherPub = getMatcherPubOrFail()
1230- let orderValid = validateMatcherOrderAllowed(order)
1539+ let $t05972459793 = validateMatcherOrderAllowed(order)
1540+ let orderValid = $t05972459793._1
1541+ let orderValidInfo = $t05972459793._2
12311542 let senderValid = sigVerify(order.bodyBytes, order.proofs[0], order.senderPublicKey)
12321543 let matcherValid = sigVerify(order.bodyBytes, order.proofs[1], matcherPub)
12331544 if (if (if (orderValid)
12341545 then senderValid
12351546 else false)
12361547 then matcherValid
12371548 else false)
12381549 then true
1239- else throwOrderError(orderValid, senderValid, matcherValid)
1550+ else throwOrderError(orderValid, orderValidInfo, senderValid, matcherValid)
12401551 case s: SetScriptTransaction =>
1241- let newHash = blake2b256(value(s.script))
1242- let allowedHash = fromBase64String(value(getString(factoryContract, keyAllowedLpScriptHash())))
1243- let currentHash = scriptHash(this)
1244- if (if ((allowedHash == newHash))
1245- then (currentHash != newHash)
1246- else false)
1552+ if (sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey))
12471553 then true
1248- else sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey)
1554+ else {
1555+ let newHash = blake2b256(value(s.script))
1556+ let allowedHash = fromBase64String(value(getString(factoryContract, keyAllowedLpScriptHash())))
1557+ let currentHash = scriptHash(this)
1558+ if ((allowedHash == newHash))
1559+ then (currentHash != newHash)
1560+ else false
1561+ }
12491562 case _ =>
12501563 sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey)
12511564 }
12521565 }
12531566

github/deemru/w8io/3ef1775 
270.79 ms