tx · C9w26qg2W4oAte8wXCCxar2tVxHtPF7PVDyCUgWKbm8Y

3N74GDduMoMAhHk7dApH6P9VDWKhFZ417FD:  -0.03700000 Waves

2023.04.20 11:05 [2542610] smart account 3N74GDduMoMAhHk7dApH6P9VDWKhFZ417FD > SELF 0.00000000 Waves

{ "type": 13, "id": "C9w26qg2W4oAte8wXCCxar2tVxHtPF7PVDyCUgWKbm8Y", "fee": 3700000, "feeAssetId": null, "timestamp": 1681977941512, "version": 2, "chainId": 84, "sender": "3N74GDduMoMAhHk7dApH6P9VDWKhFZ417FD", "senderPublicKey": "C94AxUmoNDGMx49Ry1Q3s6UNv8WgGMUeBb6zhLbfFk8v", "proofs": [ "5wwrcfWpijMmu8Hc5FSYkBAmCeTbZLj2Mnk7BzJ62r4X9YkLt9cbjnHQemSZvnpKcDbKzV2xAhpoTbjVvT5VdoCs" ], "script": "base64:BgLiLwgCEgUKAwEEARIHCgUBBAEIARIDCgEIEgASBAoCAQQSAwoBARIECgIBBBIECgIIARIECgIIARIECgIIARIFCgMBCAESABIECgIBARIDCgEBEgUKAwEBARIECgIICBIAEgASAwoBCBIFCgMBAQESBAoCAQESBAoCCAESBAoCCAgSCwoJCAEBAgECCAQEEgYKBAgIAQgSABIDCgEBEgMKAQESBAoCCAEiCmxQZGVjaW1hbHMiBnNjYWxlOCIMc2NhbGU4QmlnSW50IgdzY2FsZTE4Igp6ZXJvQmlnSW50IgRiaWcwIgRiaWcxIgRiaWcyIgt3YXZlc1N0cmluZyIDU0VQIgpQb29sQWN0aXZlIg9Qb29sUHV0RGlzYWJsZWQiE1Bvb2xNYXRjaGVyRGlzYWJsZWQiDFBvb2xTaHV0ZG93biIOaWR4UG9vbEFkZHJlc3MiDWlkeFBvb2xTdGF0dXMiEGlkeFBvb2xMUEFzc2V0SWQiDWlkeEFtdEFzc2V0SWQiD2lkeFByaWNlQXNzZXRJZCIOaWR4QW10QXNzZXREY20iEGlkeFByaWNlQXNzZXREY20iDmlkeElBbXRBc3NldElkIhBpZHhJUHJpY2VBc3NldElkIg1pZHhMUEFzc2V0RGNtIhJpZHhQb29sQW10QXNzZXRBbXQiFGlkeFBvb2xQcmljZUFzc2V0QW10IhFpZHhQb29sTFBBc3NldEFtdCIZaWR4RmFjdG9yeVN0YWtpbmdDb250cmFjdCIaaWR4RmFjdG9yeVNsaXBwYWdlQ29udHJhY3QiBXRvWDE4IgdvcmlnVmFsIg1vcmlnU2NhbGVNdWx0Igt0b1gxOEJpZ0ludCIHZnJvbVgxOCIDdmFsIg9yZXN1bHRTY2FsZU11bHQiDGZyb21YMThSb3VuZCIFcm91bmQiB3RvU2NhbGUiA2FtdCIIcmVzU2NhbGUiCGN1clNjYWxlIgNhYnMiCWFic0JpZ0ludCIMc3dhcENvbnRyYWN0IgJmYyIDbXBrIgRwbXBrIgJwbCICcGgiAWgiCXRpbWVzdGFtcCIDcGF1Igt1c2VyQWRkcmVzcyIEdHhJZCIDZ2F1IgJhYSICcGEiBmtleUZlZSIKZmVlRGVmYXVsdCIDZmVlIgZrZXlLTHAiFWtleUtMcFJlZnJlc2hlZEhlaWdodCISa2V5S0xwUmVmcmVzaERlbGF5IhZrTHBSZWZyZXNoRGVsYXlEZWZhdWx0Ig9rTHBSZWZyZXNoRGVsYXkiEGtleUZhY3RvcnlDb25maWciDWtleU1hdGNoZXJQdWIiKWtleU1hcHBpbmdQb29sQ29udHJhY3RBZGRyZXNzVG9Qb29sQXNzZXRzIhNwb29sQ29udHJhY3RBZGRyZXNzIg1rZXlQb29sQ29uZmlnIglpQW10QXNzZXQiC2lQcmljZUFzc2V0Ih9rZXlNYXBwaW5nc0Jhc2VBc3NldDJpbnRlcm5hbElkIgxiYXNlQXNzZXRTdHIiE2tleUFsbFBvb2xzU2h1dGRvd24iDWtleVBvb2xXZWlnaHQiD2NvbnRyYWN0QWRkcmVzcyIWa2V5QWxsb3dlZExwU2NyaXB0SGFzaCIWa2V5RmVlQ29sbGVjdG9yQWRkcmVzcyIPdGhyb3dPcmRlckVycm9yIgpvcmRlclZhbGlkIg5vcmRlclZhbGlkSW5mbyILc2VuZGVyVmFsaWQiDG1hdGNoZXJWYWxpZCIPZ2V0U3RyaW5nT3JGYWlsIgdhZGRyZXNzIgNrZXkiDGdldEludE9yRmFpbCIIdGhyb3dFcnIiA21zZyIGZm10RXJyIg9mYWN0b3J5Q29udHJhY3QiE2ZlZUNvbGxlY3RvckFkZHJlc3MiBWluRmVlIgFAIgZvdXRGZWUiEGlzR2xvYmFsU2h1dGRvd24iE2dldE1hdGNoZXJQdWJPckZhaWwiDWdldFBvb2xDb25maWciCGFtdEFzc2V0IgpwcmljZUFzc2V0IgxwYXJzZUFzc2V0SWQiBWlucHV0Ig9hc3NldElkVG9TdHJpbmciD3BhcnNlUG9vbENvbmZpZyIKcG9vbENvbmZpZyIQcG9vbENvbmZpZ1BhcnNlZCILJHQwODQ2OTg2MzUiDmNmZ1Bvb2xBZGRyZXNzIg1jZmdQb29sU3RhdHVzIgxjZmdMcEFzc2V0SWQiEGNmZ0Ftb3VudEFzc2V0SWQiD2NmZ1ByaWNlQXNzZXRJZCIWY2ZnQW1vdW50QXNzZXREZWNpbWFscyIVY2ZnUHJpY2VBc3NldERlY2ltYWxzIhBnZXRGYWN0b3J5Q29uZmlnIg9zdGFraW5nQ29udHJhY3QiEHNsaXBwYWdlQ29udHJhY3QiEWRhdGFQdXRBY3Rpb25JbmZvIg1pbkFtdEFzc2V0QW10Ig9pblByaWNlQXNzZXRBbXQiCG91dExwQW10IgVwcmljZSIdc2xpcHBhZ2VUb2xlcmFuY2VQYXNzZWRCeVVzZXIiFXNsaXBwYWdlVG9sZXJhbmNlUmVhbCIIdHhIZWlnaHQiC3R4VGltZXN0YW1wIhJzbGlwYWdlQW10QXNzZXRBbXQiFHNsaXBhZ2VQcmljZUFzc2V0QW10IhFkYXRhR2V0QWN0aW9uSW5mbyIOb3V0QW10QXNzZXRBbXQiEG91dFByaWNlQXNzZXRBbXQiB2luTHBBbXQiDWdldEFjY0JhbGFuY2UiB2Fzc2V0SWQiD2NhbGNQcmljZUJpZ0ludCIIcHJBbXRYMTgiCGFtQW10WDE4IhRjYWxjUHJpY2VCaWdJbnRSb3VuZCIQcHJpdmF0ZUNhbGNQcmljZSIKYW1Bc3NldERjbSIKcHJBc3NldERjbSIFYW1BbXQiBXByQW10Ig5hbXRBc3NldEFtdFgxOCIQcHJpY2VBc3NldEFtdFgxOCIKY2FsY1ByaWNlcyIFbHBBbXQiA2NmZyILYW10QXNzZXREY20iDXByaWNlQXNzZXREY20iCHByaWNlWDE4IghscEFtdFgxOCITbHBQcmljZUluQW1Bc3NldFgxOCITbHBQcmljZUluUHJBc3NldFgxOCIPY2FsY3VsYXRlUHJpY2VzIgZwcmljZXMiFGVzdGltYXRlR2V0T3BlcmF0aW9uIgZ0eElkNTgiCnBtdEFzc2V0SWQiCHBtdExwQW10IglscEFzc2V0SWQiCWFtQXNzZXRJZCIJcHJBc3NldElkIgpwb29sU3RhdHVzIgpscEVtaXNzaW9uIglhbUJhbGFuY2UiDGFtQmFsYW5jZVgxOCIJcHJCYWxhbmNlIgxwckJhbGFuY2VYMTgiC2N1clByaWNlWDE4IghjdXJQcmljZSILcG10THBBbXRYMTgiDWxwRW1pc3Npb25YMTgiC291dEFtQW10WDE4IgtvdXRQckFtdFgxOCIIb3V0QW1BbXQiCG91dFByQW10IgVzdGF0ZSIUZXN0aW1hdGVQdXRPcGVyYXRpb24iEXNsaXBwYWdlVG9sZXJhbmNlIgxpbkFtQXNzZXRBbXQiC2luQW1Bc3NldElkIgxpblByQXNzZXRBbXQiC2luUHJBc3NldElkIgppc0V2YWx1YXRlIgZlbWl0THAiDGFtQXNzZXRJZFN0ciIMcHJBc3NldElkU3RyIgtpQW10QXNzZXRJZCINaVByaWNlQXNzZXRJZCIOaW5BbUFzc2V0SWRTdHIiDmluUHJBc3NldElkU3RyIg9pbkFtQXNzZXRBbXRYMTgiD2luUHJBc3NldEFtdFgxOCIMdXNlclByaWNlWDE4IgNyZXMiC3NsaXBwYWdlWDE4IhRzbGlwcGFnZVRvbGVyYW5jZVgxOCIKcHJWaWFBbVgxOCIKYW1WaWFQclgxOCIMZXhwZWN0ZWRBbXRzIhFleHBBbXRBc3NldEFtdFgxOCITZXhwUHJpY2VBc3NldEFtdFgxOCIJY2FsY0xwQW10Ig5jYWxjQW1Bc3NldFBtdCIOY2FsY1ByQXNzZXRQbXQiDHNsaXBwYWdlQ2FsYyIJZW1pdExwQW10IgZhbURpZmYiBnByRGlmZiILY29tbW9uU3RhdGUiB2NhbGNLTHAiDWFtb3VudEJhbGFuY2UiDHByaWNlQmFsYW5jZSIQYW1vdW50QmFsYW5jZVgxOCIPcHJpY2VCYWxhbmNlWDE4Igp1cGRhdGVkS0xwIg5jYWxjQ3VycmVudEtMcCIQYW1vdW50QXNzZXREZWx0YSIPcHJpY2VBc3NldERlbHRhIhRscEFzc2V0RW1pc3Npb25EZWx0YSISYW1vdW50QXNzZXRCYWxhbmNlIhFwcmljZUFzc2V0QmFsYW5jZSIPbHBBc3NldEVtaXNzaW9uIgpjdXJyZW50S0xwIhJyZWZyZXNoS0xwSW50ZXJuYWwiF2Ftb3VudEFzc2V0QmFsYW5jZURlbHRhIhZwcmljZUFzc2V0QmFsYW5jZURlbHRhIgdhY3Rpb25zIhJ2YWxpZGF0ZVVwZGF0ZWRLTHAiBm9sZEtMcCIbdmFsaWRhdGVNYXRjaGVyT3JkZXJBbGxvd2VkIgVvcmRlciIRYW1vdW50QXNzZXRBbW91bnQiEHByaWNlQXNzZXRBbW91bnQiDSR0MDIxNTQxMjE3NTMiA2tMcCINJHQwMjIxOTMyMjI5MyINdW51c2VkQWN0aW9ucyIGa0xwTmV3Igxpc09yZGVyVmFsaWQiBGluZm8iCWNvbW1vbkdldCIBaSIDcG10IgZwbXRBbXQiCWNvbW1vblB1dCIKYW1Bc3NldFBtdCIKcHJBc3NldFBtdCIGZXN0UHV0IgRlbWl0IgZhbW91bnQiB2VtaXRJbnYiDWVtaXRJbnZMZWdhY3kiByRtYXRjaDAiFWxlZ2FjeUZhY3RvcnlDb250cmFjdCIHdGFrZUZlZSIJZmVlQW1vdW50Ig9jYWxjUHV0T25lVG9rZW4iEHBheW1lbnRBbW91bnRSYXciDnBheW1lbnRBc3NldElkIgZpc0V2YWwiEGFtb3VudEJhbGFuY2VSYXciD3ByaWNlQmFsYW5jZVJhdyIUcGF5bWVudEluQW1vdW50QXNzZXQiDSR0MDI1NDA2MjU2OTkiEGFtb3VudEJhbGFuY2VPbGQiD3ByaWNlQmFsYW5jZU9sZCINJHQwMjU3MDMyNTg1MiIUYW1vdW50QXNzZXRBbW91bnRSYXciE3ByaWNlQXNzZXRBbW91bnRSYXciDSR0MDI1OTg0MjYwNDgiDXBheW1lbnRBbW91bnQiEGFtb3VudEJhbGFuY2VOZXciD3ByaWNlQmFsYW5jZU5ldyILcHJpY2VOZXdYMTgiCHByaWNlTmV3Ig5wYXltZW50QmFsYW5jZSIUcGF5bWVudEJhbGFuY2VCaWdJbnQiDHN1cHBseUJpZ0ludCILY2hlY2hTdXBwbHkiDWRlcG9zaXRCaWdJbnQiC2lzc3VlQW1vdW50IgtwcmljZU9sZFgxOCIIcHJpY2VPbGQiBGxvc3MiDSR0MDI3NzI5Mjc4OTYiB2JhbGFuY2UiD2lzc3VlQW1vdW50Qm90aCIPY2FsY0dldE9uZVRva2VuIgpvdXRBc3NldElkIgZjaGVja3MiEG91dEluQW1vdW50QXNzZXQiDWJhbGFuY2VCaWdJbnQiGG91dEluQW1vdW50QXNzZXREZWNpbWFscyIMYW1CYWxhbmNlT2xkIgxwckJhbGFuY2VPbGQiCm91dEJhbGFuY2UiEG91dEJhbGFuY2VCaWdJbnQiDnJlZGVlbWVkQmlnSW50IglhbW91bnRSYXciDSR0MDI5OTc0MzAwMzAiC3RvdGFsQW1vdW50Ig0kdDAzMDAzNDMwMjYwIgtvdXRBbUFtb3VudCILb3V0UHJBbW91bnQiDGFtQmFsYW5jZU5ldyIMcHJCYWxhbmNlTmV3IhhhbW91bnRCb3RoSW5QYXltZW50QXNzZXQiFm1hbmFnZXJQdWJsaWNLZXlPclVuaXQiAXMiHXBlbmRpbmdNYW5hZ2VyUHVibGljS2V5T3JVbml0Iglpc01hbmFnZXIiAnBrIgttdXN0TWFuYWdlciICcGQiDWNsZWFuQW1vdW50SW4iCWlzUmV2ZXJzZSINZmVlUG9vbEFtb3VudCINJHQwMzE5NzczMjI4MiIIYXNzZXRPdXQiB2Fzc2V0SW4iEnBvb2xBc3NldEluQmFsYW5jZSITcG9vbEFzc2V0T3V0QmFsYW5jZSIJYW1vdW50T3V0IgRvbGRLIgRuZXdLIgZjaGVja0siDGFtb3VudE91dE1pbiIJYWRkcmVzc1RvIgtzd2FwQ29udGFjdCIIY2hlY2tNaW4iF3BlbmRpbmdNYW5hZ2VyUHVibGljS2V5IgtjaGVja0NhbGxlciIVY2hlY2tNYW5hZ2VyUHVibGljS2V5IgJwbSIFaGFzUE0iB2NoZWNrUE0iD3Nob3VsZEF1dG9TdGFrZSIEYW1JZCIEcHJJZCIMc2xpcHBhZ2VBSW52IgxzbGlwcGFnZVBJbnYiCmxwVHJhbnNmZXIiC3NscFN0YWtlSW52Ig0kdDAzNzE2NjM3NjI4IhFyZWZyZXNoS0xwQWN0aW9ucyIRaXNVcGRhdGVkS0xwVmFsaWQiC21heFNsaXBwYWdlIg0kdDAzODE5MDM4MjU1IgxtaW5PdXRBbW91bnQiCWF1dG9TdGFrZSIgaXNQb29sT25lVG9rZW5PcGVyYXRpb25zRGlzYWJsZWQiDWlzUHV0RGlzYWJsZWQiB3BheW1lbnQiDSR0MDM5NDQzMzk1OTUiBWJvbnVzIhNlbWl0QW1vdW50RXN0aW1hdGVkIgplbWl0QW1vdW50IghzdGFrZUludiIHc2VuZEZlZSINJHQwNDAxODE0MDM3OCINJHQwNDAzODE0MDQ4OSINJHQwNDA3OTU0MDk1MiINb3V0QXNzZXRJZFN0ciINaXNHZXREaXNhYmxlZCINJHQwNDE4Mzc0MTk5MCIPYW1vdW50RXN0aW1hdGVkIgdidXJuSW52Ig1hc3NldFRyYW5zZmVyIg0kdDA0MjQ5MDQyNzM3IhBmZWVBbW91bnRGb3JDYWxjIg0kdDA0Mjc0MDQyODQ4Ig0kdDA0MzEwNTQzMjYxIg11bnN0YWtlQW1vdW50Igp1bnN0YWtlSW52Ig0kdDA0NDE2NjQ0MzE3Ig0kdDA0NDgxMjQ1MDU5Ig0kdDA0NTA2MjQ1MTcwIglvdXRBbXRBbXQiFGJ1cm5MUEFzc2V0T25GYWN0b3J5Ig0kdDA0NjExNjQ2MTk4IhJub0xlc3NUaGVuQW10QXNzZXQiFG5vTGVzc1RoZW5QcmljZUFzc2V0Ig0kdDA0NzE0NzQ3MjI4Ig1jaGVja1BheW1lbnRzIg9jaGVja1Bvb2xTdGF0dXMiDSR0MDQ4MzU0NDg0MzUiFW5vTGVzc1RoZW5BbW91bnRBc3NldCIMY2hlY2tBbW91bnRzIg0kdDA0OTczMDQ5ODExIgthbXRBc3NldFN0ciINcHJpY2VBc3NldFN0ciIYbGFzdFJlZnJlc2hlZEJsb2NrSGVpZ2h0Ih1jaGVja0xhc3RSZWZyZXNoZWRCbG9ja0hlaWdodCINJHQwNTA5OTg1MTA2MiIQa0xwVXBkYXRlQWN0aW9ucyIKYW10QXNzZXRJZCIMcHJpY2VBc3NldElkIg1wb29sTFBCYWxhbmNlIhJhY2NBbXRBc3NldEJhbGFuY2UiFGFjY1ByaWNlQXNzZXRCYWxhbmNlIgpwcmljZXNMaXN0Ig9scEFtdEFzc2V0U2hhcmUiEWxwUHJpY2VBc3NldFNoYXJlIgpwb29sV2VpZ2h0IgxjdXJQcmljZUNhbGMiDGFtQmFsYW5jZVJhdyIMcHJCYWxhbmNlUmF3Ig9hbUJhbGFuY2VSYXdYMTgiD3ByQmFsYW5jZVJhd1gxOCIQcGF5bWVudExwQXNzZXRJZCIMcGF5bWVudExwQW10IgJ0eCIGdmVyaWZ5Ig90YXJnZXRQdWJsaWNLZXkiCm1hdGNoZXJQdWIiDSR0MDU5NzI0NTk3OTMiB25ld0hhc2giC2FsbG93ZWRIYXNoIgtjdXJyZW50SGFzaHMAAWEACAABYgCAwtcvAAFjCQC2AgEAgMLXLwABZAkAtgIBAICAkLu61q3wDQABZQkAtgIBAAAAAWYJALYCAQAAAAFnCQC2AgEAAQABaAkAtgIBAAIAAWkCBVdBVkVTAAFqAgJfXwABawABAAFsAAIAAW0AAwABbgAEAAFvAAEAAXAAAgABcQADAAFyAAQAAXMABQABdAAGAAF1AAcAAXYACAABdwAJAAF4AAoAAXkAAQABegAC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ZWVSRUFET05MWQkAzAgCCQClCAEFBHRoaXMFA25pbAUDbmlsAwkAAQIFAmFSAgNJbnQFAmFSCQACAQkArAICCQADAQUCYVICGCBjb3VsZG4ndCBiZSBjYXN0IHRvIEludAACYVMKAAJhUgkA/AcEBQJhTwIRZ2V0T3V0RmVlUkVBRE9OTFkJAMwIAgkApQgBBQR0aGlzBQNuaWwFA25pbAMJAAECBQJhUgIDSW50BQJhUgkAAgEJAKwCAgkAAwEFAmFSAhggY291bGRuJ3QgYmUgY2FzdCB0byBJbnQBAmFUAAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQJhTwkBAmF4AAcBAmFVAAkA2QQBCQECYUgCBQJhTwkBAmFwAAECYVYABAJhVwkBAmFIAgUEdGhpcwkBAmFlAAQCYVgJAQJhSAIFBHRoaXMJAQJhZgAEAmF1CQECYUsCBQJhTwkBAmF2AQUCYVgEAmF0CQECYUsCBQJhTwkBAmF2AQUCYVcJALUJAgkBAmFIAgUCYU8JAQJhcwIJAKQDAQUCYXQJAKQDAQUCYXUFAWoBAmFZAQJhWgMJAAACBQJhWgUBaQUEdW5pdAkA2QQBBQJhWgECYmEBAmFaAwkAAAIFAmFaBQR1bml0BQFpCQDYBAEJAQV2YWx1ZQEFAmFaAQJiYgECYmMJAJkKBwkBEUBleHRyTmF0aXZlKDEwNjIpAQkAkQMCBQJiYwUBbwkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmJjBQFwCQDZBAEJAJEDAgUCYmMFAXEJAQJhWQEJAJEDAgUCYmMFAXIJAQJhWQEJAJEDAgUCYmMFAXMJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJiYwUBdAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmJjBQF1AAJiZAkBAmJiAQkBAmFWAAACYmUFAmJkAAJiZggFAmJlAl8xAAJiZwgFAmJlAl8yAAJiaAgFAmJlAl8zAAJiaQgFAmJlAl80AAJiaggFAmJlAl81AAJiawgFAmJlAl82AAJibAgFAmJlAl83AQJibQAJALUJAgkBAmFIAgUCYU8JAQJhbwAFAWoAAmJuCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkAkQMCCQECYm0ABQFCAhlpbmNvcnJlY3Qgc3Rha2luZyBhZGRyZXNzAAJibwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJAJEDAgkBAmJtAAUBQwIZaW5jb3JyZWN0IHN0YWtpbmcgYWRkcmVzcwECYnAKAmJxAmJyAmJzAmJ0AmJ1AmJ2AmJ3AmJ4AmJ5AmJ6CQC5CQIJAMwIAgIUJWQlZCVkJWQlZCVkJWQlZCVkJWQJAMwIAgkApAMBBQJicQkAzAgCCQCkAwEFAmJyCQDMCAIJAKQDAQUCYnMJAMwIAgkApAMBBQJidAkAzAgCCQCkAwEFAmJ1CQDMCAIJAKQDAQUCYnYJAMwIAgkApAMBBQJidwkAzAgCCQCkAwEFAmJ4CQDMCAIJAKQDAQUCYnkJAMwIAgkApAMBBQJiegUDbmlsBQFqAQJiQQYCYkICYkMCYkQCYnQCYncCYngJALkJAgkAzAgCAgwlZCVkJWQlZCVkJWQJAMwIAgkApAMBBQJiQgkAzAgCCQCkAwEFAmJDCQDMCAIJAKQDAQUCYkQJAMwIAgkApAMBBQJidAkAzAgCCQCkAwEFAmJ3CQDMCAIJAKQDAQUCYngFA25pbAUBagECYkUBAmJGAwkAAAIFAmJGAgVXQVZFUwgJAO8HAQUEdGhpcwlhdmFpbGFibGUJAPAHAgUEdGhpcwkA2QQBBQJiRgECYkcCAmJIAmJJCQC8AgMFAmJIBQFkBQJiSQECYkoDAmJIAmJJAUwJAL0CBAUCYkgFAWQFAmJJBQFMAQJiSwQCYkwCYk0CYk4CYk8EAmJQCQEBRAIFAmJOBQJiTAQCYlEJAQFEAgUCYk8FAmJNCQECYkcCBQJiUQUCYlABAmJSAwJiTgJiTwJiUwQCYlQJAQJhVgAEAmJVCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCYlQFAXQEAmJWCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCYlQFAXUEAmJXCQECYksEBQJiVQUCYlYFAmJOBQJiTwQCYkkJAQFEAgUCYk4FAmJVBAJiSAkBAUQCBQJiTwUCYlYEAmJYCQEBRAIFAmJTBQFiBAJiWQkBAmJHAgUCYkkFAmJYBAJiWgkBAmJHAgUCYkgFAmJYCQDMCAIFAmJXCQDMCAIFAmJZCQDMCAIFAmJaBQNuaWwBAmNhAwJiTgJiTwJiUwQCY2IJAQJiUgMFAmJOBQJiTwUCYlMJAMwIAgkBAUgCCQCRAwIFAmNiAAAFAWIJAMwIAgkBAUgCCQCRAwIFAmNiAAEFAWIJAMwIAgkBAUgCCQCRAwIFAmNiAAIFAWIFA25pbAECY2MEAmNkAmNlAmNmAmFiBAJiVAkBAmFWAAQCY2cJAJEDAgUCYlQFAXEEAmNoCQCRAwIFAmJUBQFyBAJjaQkAkQMCBQJiVAUBcwQCYkwJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJiVAUBdAQCYk0JAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJiVAUBdQQCY2oJAJEDAgUCYlQFAXAEAmNrCAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQDsBwEJANkEAQUCY2cJAKwCAgkArAICAgZBc3NldCAFAmNnAg4gZG9lc24ndCBleGlzdAhxdWFudGl0eQMJAQIhPQIFAmNnBQJjZQkAAgECFUludmFsaWQgYXNzZXQgcGFzc2VkLgQCY2wJAQJiRQEFAmNoBAJjbQkBAUQCBQJjbAUCYkwEAmNuCQECYkUBBQJjaQQCY28JAQFEAgUCY24FAmJNBAJjcAkBAmJHAgUCY28FAmNtBAJjcQkBAUgCBQJjcAUBYgQCY3IJAQFEAgUCY2YFAWIEAmNzCQEBRAIFAmNrBQFiBAJjdAkAvAIDBQJjbQUCY3IFAmNzBAJjdQkAvAIDBQJjbwUCY3IFAmNzBAJjdgkBAUsDBQJjdAUCYkwFBUZMT09SBAJjdwkBAUsDBQJjdQUCYk0FBUZMT09SBAJjeAMJAAACBQJjZAIABQNuaWwJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUCYWIFAmN2AwkAAAIFAmNoAgVXQVZFUwUEdW5pdAkA2QQBBQJjaAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQJhYgUCY3cDCQAAAgUCY2kCBVdBVkVTBQR1bml0CQDZBAEFAmNpCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQJhZAIJAKUIAQUCYWIFAmNkCQECYkEGBQJjdgUCY3cFAmNmBQJjcQUGaGVpZ2h0CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAVcABQJjcQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAVgCBQZoZWlnaHQIBQlsYXN0QmxvY2sJdGltZXN0YW1wBQJjcQUDbmlsCQCcCgoFAmN2BQJjdwUCY2gFAmNpBQJjbAUCY24FAmNrBQJjcAUCY2oFAmN4AQJjeQkCY2QCY3oCY0ECY0ICY0MCY0QCYWICY0UCY0YEAmJUCQECYVYABAJjZwkA2QQBCQCRAwIFAmJUBQFxBAJjRwkAkQMCBQJiVAUBcgQCY0gJAJEDAgUCYlQFAXMEAmNJCQCRAwIFAmJUBQF2BAJjSgkAkQMCBQJiVAUBdwQCYlUJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJiVAUBdAQCYlYJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJiVAUBdQQCY2oJAJEDAgUCYlQFAXAEAmNrCAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQDsBwEFAmNnCQCsAgIJAKwCAgIGQXNzZXQgCQDYBAEFAmNnAg4gZG9lc24ndCBleGlzdAhxdWFudGl0eQQCY0sJANgEAQkBC3ZhbHVlT3JFbHNlAgUCY0IJANkEAQIFV0FWRVMEAmNMCQDYBAEJAQt2YWx1ZU9yRWxzZQIFAmNECQDZBAECBVdBVkVTAwMJAQIhPQIFAmNHBQJjSwYJAQIhPQIFAmNIBQJjTAkAAgECIkludmFsaWQgYW10IG9yIHByaWNlIGFzc2V0IHBhc3NlZC4EAmNsAwUCY0UJAQJiRQEFAmNHCQBlAgkBAmJFAQUCY0cFAmNBBAJjbgMFAmNFCQECYkUBBQJjSAkAZQIJAQJiRQEFAmNIBQJjQwQCY00JAQFEAgUCY0EFAmJVBAJjTgkBAUQCBQJjQwUCYlYEAmNPCQECYkcCBQJjTgUCY00EAmNtCQEBRAIFAmNsBQJiVQQCY28JAQFEAgUCY24FAmJWBAJjUAMJAAACBQJjawAABAJjcAUBZQQCY1EFAWUEAmJYCQB2BgkAuQICBQJjTQUCY04AAAkAtgIBAAUAAQAABQRET1dOCQCXCgUJAQFIAgUCYlgFAWIJAQFIAgUCY00FAmJVCQEBSAIFAmNOBQJiVgkBAmJHAgkAtwICBQJjbwUCY04JALcCAgUCY20FAmNNBQJjUQQCY3AJAQJiRwIFAmNvBQJjbQQCY1EJALwCAwkBAVIBCQC4AgIFAmNwBQJjTwUBZAUCY3AEAmNSCQEBRAIFAmN6BQFiAwMJAQIhPQIFAmNwBQFlCQC/AgIFAmNRBQJjUgcJAAIBCQCsAgIJAKwCAgkArAICAg9QcmljZSBzbGlwcGFnZSAJAKYDAQUCY1ECHiBleGNlZWRlZCB0aGUgcGFzc2VkIGxpbWl0IG9mIAkApgMBBQJjUgQCY3MJAQFEAgUCY2sFAWIEAmNTCQC9AgQFAmNNCQECYkoDBQJjbwUCY20FB0NFSUxJTkcFAWQFB0NFSUxJTkcEAmNUCQC9AgQFAmNOBQFkCQECYkoDBQJjbwUCY20FBUZMT09SBQdDRUlMSU5HBAJjVQMJAL8CAgUCY1MFAmNOCQCUCgIFAmNUBQJjTgkAlAoCBQJjTQUCY1MEAmNWCAUCY1UCXzEEAmNXCAUCY1UCXzIEAmJYCQC9AgQFAmNzBQJjVwUCY28FBUZMT09SCQCXCgUJAQFLAwUCYlgFAWIFBUZMT09SCQEBSwMFAmNWBQJiVQUHQ0VJTElORwkBAUsDBQJjVwUCYlYFB0NFSUxJTkcFAmNwBQJjUQQCY1gIBQJjUAJfMQQCY1kIBQJjUAJfMgQCY1oIBQJjUAJfMwQCY3EJAQFIAggFAmNQAl80BQFiBAJkYQkBAUgCCAUCY1ACXzUFAWIDCQBnAgAABQJjWAkAAgECNkludmFsaWQgY2FsY3VsYXRpb25zLiBMUCBjYWxjdWxhdGVkIGlzIGxlc3MgdGhhbiB6ZXJvLgQCZGIDCQEBIQEFAmNGAAAFAmNYBAJkYwkAZQIFAmNBBQJjWQQCZGQJAGUCBQJjQwUCY1oEAmRlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEBVwAFAmNxCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEBWAIFBmhlaWdodAgFCWxhc3RCbG9jawl0aW1lc3RhbXAFAmNxCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQJhYQIFAmFiBQJjZAkBAmJwCgUCY1kFAmNaBQJkYgUCY3EFAmN6BQJkYQUGaGVpZ2h0CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAUCZGMFAmRkBQNuaWwJAJ8KDQUCY1gFAmRiBQJjcQUCY2wFAmNuBQJjawUCY2cFAmNqBQJkZQUCZGMFAmRkBQJjQgUCY0QBAmRmAwJkZwJkaAJjawQCZGkJAQFHAgUCZGcJALYCAQUCYmsEAmRqCQEBRwIFAmRoCQC2AgEFAmJsBAJkawkAvAIDCQB2BgkAuQICBQJkaQUCZGoAAAkAtgIBAAUAAQASBQRET1dOBQFnBQJjawMJAAACBQJjawUBZgUBZgUCZGsBAmRsAwJkbQJkbgJkbwQCZHAJALgCAgkAtgIBCQECYkUBCQECYmEBBQJiaQUCZG0EAmRxCQC4AgIJALYCAQkBAmJFAQkBAmJhAQUCYmoFAmRuBAJkcgkAuAICCQC2AgEICQEFdmFsdWUBCQDsBwEFAmJoCHF1YW50aXR5BQJkbwQCZHMJAQJkZgMFAmRwBQJkcQUCZHIFAmRzAQJkdAMCZHUCZHYCZG8EAmRwCQBkAgkBAmJFAQkBAmJhAQUCYmkFAmR1BAJkcQkAZAIJAQJiRQEJAQJiYQEFAmJqBQJkdgQCZHIJAGQCCAkBBXZhbHVlAQkA7AcBBQJiaAhxdWFudGl0eQUCZG8EAmRrCQECZGYDCQC2AgEFAmRwCQC2AgEFAmRxCQC2AgEFAmRyBAJkdwkAzAgCCQEMSW50ZWdlckVudHJ5AgUCYWsFBmhlaWdodAkAzAgCCQELU3RyaW5nRW50cnkCBQJhagkApgMBBQJkawUDbmlsCQCUCgIFAmR3BQJkawECZHgCAmR5AmRrAwkAwAICBQJkawUCZHkGCQECYUwBCQC5CQIJAMwIAgIidXBkYXRlZCBLTHAgbG93ZXIgdGhhbiBjdXJyZW50IEtMcAkAzAgCCQCmAwEFAmR5CQDMCAIJAKYDAQUCZGsFA25pbAIBIAECZHoBAmRBBAJkcAkBAmJFAQkBAmJhAQUCYmkEAmRxCQECYkUBCQECYmEBBQJiagQCZEIIBQJkQQZhbW91bnQEAmRDCQBuBAgFAmRBBmFtb3VudAgFAmRBBXByaWNlBQFiBQVGTE9PUgQCZEQDCQAAAggFAmRBCW9yZGVyVHlwZQUDQnV5CQCUCgIFAmRCCQEBLQEFAmRDCQCUCgIJAQEtAQUCZEIFAmRDBAJkdQgFAmREAl8xBAJkdggFAmREAl8yAwMDCQECYVQABgkAAAIFAmJnBQFtBgkAAAIFAmJnBQFuCQACAQIcRXhjaGFuZ2Ugb3BlcmF0aW9ucyBkaXNhYmxlZAMDCQECIT0CCAgFAmRBCWFzc2V0UGFpcgthbW91bnRBc3NldAUCYmkGCQECIT0CCAgFAmRBCWFzc2V0UGFpcgpwcmljZUFzc2V0BQJiagkAAgECE1dyb25nIG9yZGVyIGFzc2V0cy4EAmRFCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKgDAQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzBQJhagIBMAkBAmFOAQILaW52YWxpZCBrTHAEAmRGCQECZHQDBQJkdQUCZHYAAAQCZEcIBQJkRgJfMQQCZEgIBQJkRgJfMgQCZEkJAMACAgUCZEgFAmRFBAJkSgkAuQkCCQDMCAICBGtMcD0JAMwIAgkApgMBBQJkRQkAzAgCAggga0xwTmV3PQkAzAgCCQCmAwEFAmRICQDMCAICFCBhbW91bnRBc3NldEJhbGFuY2U9CQDMCAIJAKQDAQUCZHAJAMwIAgITIHByaWNlQXNzZXRCYWxhbmNlPQkAzAgCCQCkAwEFAmRxCQDMCAICGSBhbW91bnRBc3NldEJhbGFuY2VEZWx0YT0JAMwIAgkApAMBBQJkdQkAzAgCAhggcHJpY2VBc3NldEJhbGFuY2VEZWx0YT0JAMwIAgkApAMBBQJkdgkAzAgCAgggaGVpZ2h0PQkAzAgCCQCkAwEFBmhlaWdodAUDbmlsAgAJAJQKAgUCZEkFAmRKAQJkSwECZEwDCQECIT0CCQCQAwEIBQJkTAhwYXltZW50cwABCQACAQIdZXhhY3RseSAxIHBheW1lbnQgaXMgZXhwZWN0ZWQEAmRNCQEFdmFsdWUBCQCRAwIIBQJkTAhwYXltZW50cwAABAJjZQkBBXZhbHVlAQgFAmRNB2Fzc2V0SWQEAmROCAUCZE0GYW1vdW50BAJjUAkBAmNjBAkA2AQBCAUCZEwNdHJhbnNhY3Rpb25JZAkA2AQBBQJjZQUCZE4IBQJkTAZjYWxsZXIEAmN2CAUCY1ACXzEEAmN3CAUCY1ACXzIEAmNqCQENcGFyc2VJbnRWYWx1ZQEIBQJjUAJfOQQCY3gIBQJjUANfMTADAwkBAmFUAAYJAAACBQJjagUBbgkAAgEJAKwCAgIsR2V0IG9wZXJhdGlvbiBpcyBibG9ja2VkIGJ5IGFkbWluLiBTdGF0dXMgPSAJAKQDAQUCY2oJAJcKBQUCY3YFAmN3BQJkTgUCY2UFAmN4AQJkTwMCZEwCY3oCY0YDCQECIT0CCQCQAwEIBQJkTAhwYXltZW50cwACCQACAQIfZXhhY3RseSAyIHBheW1lbnRzIGFyZSBleHBlY3RlZAQCZFAJAQV2YWx1ZQEJAJEDAggFAmRMCHBheW1lbnRzAAAEAmRRCQEFdmFsdWUBCQCRAwIIBQJkTAhwYXltZW50cwABBAJkUgkBAmN5CQkA2AQBCAUCZEwNdHJhbnNhY3Rpb25JZAUCY3oIBQJkUAZhbW91bnQIBQJkUAdhc3NldElkCAUCZFEGYW1vdW50CAUCZFEHYXNzZXRJZAkApQgBCAUCZEwGY2FsbGVyBwUCY0YEAmNqCQENcGFyc2VJbnRWYWx1ZQEIBQJkUgJfOAMDAwkBAmFUAAYJAAACBQJjagUBbAYJAAACBQJjagUBbgkAAgEJAKwCAgIsUHV0IG9wZXJhdGlvbiBpcyBibG9ja2VkIGJ5IGFkbWluLiBTdGF0dXMgPSAJAKQDAQUCY2oFAmRSAQJkUwECZFQEAmRVCQD8BwQFAmFPAgRlbWl0CQDMCAIFAmRUBQNuaWwFA25pbAMJAAACBQJkVQUCZFUEAmRWBAJkVwUCZFUDCQABAgUCZFcCB0FkZHJlc3MEAmRYBQJkVwkA/AcEBQJkWAIEZW1pdAkAzAgCBQJkVAUDbmlsBQNuaWwFBHVuaXQDCQAAAgUCZFYFAmRWBQJkVAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgECZFkCAmRUAmFpBAJkWgMJAAACBQJhaQAAAAAJAGsDBQJkVAUCYWkFAWIJAJQKAgkAZQIFAmRUBQJkWgUCZFoBAmVhBAJlYgJlYwJhYgJhYwQCZWQJAAACBQJhYwUEdW5pdAQCZWUJAQJiRQEJAQJiYQEFAmJpBAJlZgkBAmJFAQkBAmJhAQUCYmoEAmVnAwkAAAIFAmVjBQJiaQYDCQAAAgUCZWMFAmJqBwkBAmFMAQINaW52YWxpZCBhc3NldAQCZWgDBQJlZAkAlAoCBQJlZQUCZWYDBQJlZwkAlAoCCQBlAgUCZWUFAmViBQJlZgkAlAoCBQJlZQkAZQIFAmVmBQJlYgQCZWkIBQJlaAJfMQQCZWoIBQJlaAJfMgQCZWsDBQJlZwkAlAoCBQJlYgAACQCUCgIAAAUCZWIEAmVsCAUCZWsCXzEEAmVtCAUCZWsCXzIEAmRCCAkBAmRZAgUCZWwFAmFRAl8xBAJkQwgJAQJkWQIFAmVtBQJhUQJfMQQCZW4JAQJkWQIFAmViBQJhUQQCZW8IBQJlbgJfMQQCZFoIBQJlbgJfMgQCZXAJAGQCBQJlaQUCZEIEAmVxCQBkAgUCZWoFAmRDBAJlcgkBAmJHAgkBAUQCBQJlcQUCYmwJAQFEAgUCZXAFAmJrBAJlcwkBAUgCBQJlcgUBYgQCZXQDBQJlZwUCZWkFAmVqBAJldQkAtgIBBQJldAQCZXYJALYCAQgJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkA7AcBBQJiaAkArAICCQCsAgICBmFzc2V0IAkA2AQBBQJiaAIOIGRvZXNuJ3QgZXhpc3QIcXVhbnRpdHkEAmV3AwkAvwICBQJldgUBZgYJAQJhTAECImluaXRpYWwgZGVwb3NpdCByZXF1aXJlcyBhbGwgY29pbnMDCQAAAgUCZXcFAmV3BAJleAkAtgIBBQJlbwQCZXkJAJYDAQkAzAgCAAAJAMwIAgkAoAMBCQC6AgIJALkCAgUCZXYJALgCAgkBCnNxcnRCaWdJbnQECQC3AgIFAWQJALoCAgkAuQICBQJleAUBZAUCZXUAEgASBQRET1dOBQFkBQFkBQNuaWwEAmRlAwUCZWQFA25pbAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAVcABQJlcwkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAVgCBQZoZWlnaHQIBQlsYXN0QmxvY2sJdGltZXN0YW1wBQJlcwkAzAgCCQELU3RyaW5nRW50cnkCCQECYWECCQClCAEJAQV2YWx1ZQEFAmFiCQDYBAEJAQV2YWx1ZQEFAmFjCQECYnAKBQJlbAUCZW0FAmV5BQJlcwAAAAAFBmhlaWdodAgFCWxhc3RCbG9jawl0aW1lc3RhbXAAAAAABQNuaWwEAmV6CQECYkcCCQEBRAIFAmVqBQJibAkBAUQCBQJlaQUCYmsEAmVBCQEBSAIFAmV6BQFiBAJlQgQCZUMDBQJlZwkAlAoCBQJlbAUCZWkJAJQKAgUCZW0FAmVqBAJkVAgFAmVDAl8xBAJlRAgFAmVDAl8yBAJlRQkAoAMBCQC8AgMFAmV2CQC2AgEJAGkCBQJkVAACCQC2AgEFAmVECQBrAwkAZQIFAmV5BQJlRQUBYgUCZUUJAJcKBQUCZXkFAmRlBQJkWgUCZUIFAmVnCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQJlRgUCZUcCZW8CZWMCYWICYWMEAmVkCQAAAgUCYWMFBHVuaXQEAmJUCQECYVYABAJiVQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmJUBQF0BAJiVgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmJUBQF1BAJlSAkAzAgCAwkAAAIFAmVjBQJiaAYJAQJhTAECEGludmFsaWQgbHAgYXNzZXQFA25pbAMJAAACBQJlSAUCZUgEAmVJAwkAAAIFAmVHBQJiaQYDCQAAAgUCZUcFAmJqBwkBAmFMAQINaW52YWxpZCBhc3NldAQCZUoDBQJlSQkAtgIBCQECYkUBCQECYmEBBQJiaQkAtgIBCQECYkUBCQECYmEBBQJiagQCZUsDBQJlSQUCYlUFAmJWBAJlTAkBAmJFAQkBAmJhAQUCYmkEAmVNCQECYkUBCQECYmEBBQJiagQCZU4DBQJlSQUCZUwFAmVNBAJlTwkAtgIBBQJlTgQCZXYJALYCAQgJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkA7AcBBQJiaAkArAICCQCsAgICBmFzc2V0IAkA2AQBBQJiaAIOIGRvZXNuJ3QgZXhpc3QIcXVhbnRpdHkEAmVQCQC2AgEFAmVvBAJlUQkAlgMBCQDMCAIAAAkAzAgCCQCgAwEJALoCAgkAuQICBQJlSgkAuAICBQFkCQB2BgkAuAICBQFkCQC6AgIJALkCAgUCZVAFAWQFAmV2ABIFAWgAAAASBQRET1dOBQFkBQNuaWwEAmVSCQECZFkCBQJlUQUCYVMEAmVTCAUCZVICXzEEAmRaCAUCZVICXzIEAmVUAwUCZUkJAJYKBAUCZVMAAAkAZQIFAmVMBQJlUQUCZU0JAJYKBAAABQJlUwUCZUwJAGUCBQJlTQUCZVEEAmVVCAUCZVQCXzEEAmVWCAUCZVQCXzIEAmVXCAUCZVQCXzMEAmVYCAUCZVQCXzQEAmVyCQECYkcCCQEBRAIFAmVYBQJibAkBAUQCBQJlVwUCYmsEAmVzCQEBSAIFAmVyBQFiBAJkZQMFAmVkBQNuaWwJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAmFkAgkApQgBCQEFdmFsdWUBBQJhYgkA2AQBCQEFdmFsdWUBBQJhYwkBAmJBBgUCZVUFAmVWBQJlbwUCZXMFBmhlaWdodAgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAMwIAgkBDEludGVnZXJFbnRyeQIJAQFXAAUCZXMJAMwIAgkBDEludGVnZXJFbnRyeQIJAQFYAgUGaGVpZ2h0CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAUCZXMFA25pbAQCZXoJAQJiRwIJAQFEAgUCZU0FAmJsCQEBRAIFAmVMBQJiawQCZUEJAQFIAgUCZXoFAWIEAmVCBAJlWQkAaAIJAKADAQkAvAIDBQJlSgUCZVAFAmV2AAIJAGsDCQBlAgUCZVMFAmVZBQFiBQJlWQkAlwoFBQJlUwUCZGUFAmRaBQJlQgUCZUkJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BAmVaAAQCZFcJAKIIAQkBAVUAAwkAAQIFAmRXAgZTdHJpbmcEAmZhBQJkVwkA2QQBBQJmYQMJAAECBQJkVwIEVW5pdAUEdW5pdAkAAgECC01hdGNoIGVycm9yAQJmYgAEAmRXCQCiCAEJAQFWAAMJAAECBQJkVwIGU3RyaW5nBAJmYQUCZFcJANkEAQUCZmEDCQABAgUCZFcCBFVuaXQFBHVuaXQJAAIBAgtNYXRjaCBlcnJvcgECZmMBAmRMBAJkVwkBAmVaAAMJAAECBQJkVwIKQnl0ZVZlY3RvcgQCZmQFAmRXCQAAAggFAmRMD2NhbGxlclB1YmxpY0tleQUCZmQDCQABAgUCZFcCBFVuaXQJAAACCAUCZEwGY2FsbGVyBQR0aGlzCQACAQILTWF0Y2ggZXJyb3IBAmZlAQJkTAQCZmYJAAIBAhFQZXJtaXNzaW9uIGRlbmllZAQCZFcJAQJlWgADCQABAgUCZFcCCkJ5dGVWZWN0b3IEAmZkBQJkVwMJAAACCAUCZEwPY2FsbGVyUHVibGljS2V5BQJmZAYFAmZmAwkAAQIFAmRXAgRVbml0AwkAAAIIBQJkTAZjYWxsZXIFBHRoaXMGBQJmZgkAAgECC01hdGNoIGVycm9yHQJkTAEhY2FsY3VsYXRlQW1vdW50T3V0Rm9yU3dhcFJFQURPTkxZAwJmZwJmaAJmaQQCZmoDCQAAAgUCZmgHBAJmawkBAmFIAgUEdGhpcwkBAmFmAAQCZmwJAQJhSAIFBHRoaXMJAQJhZQAJAJQKAgUCZmsFAmZsBAJmawkBAmFIAgUEdGhpcwkBAmFlAAQCZmwJAQJhSAIFBHRoaXMJAQJhZgAJAJQKAgUCZmsFAmZsBAJmawgFAmZqAl8xBAJmbAgFAmZqAl8yBAJmbQkBAmJFAQUCZmwEAmZuCQECYkUBBQJmawQCZm8JAGsDBQJmbgUCZmcJAGQCBQJmbQUCZmcEAmZwCQC5AgIJALYCAQUCZm0JALYCAQUCZm4EAmZxCQC5AgIJALcCAgkAtwICCQC2AgEJAQJiRQEFAmZsCQC2AgEFAmZnCQC2AgEFAmZpCQC4AgIJALYCAQkBAmJFAQUCZmsJALYCAQUCZm8EAmZyAwkAwAICBQJmcQUCZnAGCQACAQIUbmV3IEsgaXMgZmV3ZXIgZXJyb3IDCQAAAgUCZnIFAmZyCQCUCgIFA25pbAUCZm8JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CZEwBJmNhbGN1bGF0ZUFtb3VudE91dEZvclN3YXBBbmRTZW5kVG9rZW5zBQJmZwJmaAJmcwJmdAJmaQQCZnUKAAJhUgkA/AcEBQJhTwIXZ2V0U3dhcENvbnRyYWN0UkVBRE9OTFkFA25pbAUDbmlsAwkAAQIFAmFSAgZTdHJpbmcFAmFSCQACAQkArAICCQADAQUCYVICGyBjb3VsZG4ndCBiZSBjYXN0IHRvIFN0cmluZwQCZUgJAMwIAgMJAGcCCAkBBXZhbHVlAQkAkQMCCAUCZEwIcGF5bWVudHMAAAZhbW91bnQFAmZnBgkBAmFMAQIMV3JvbmcgYW1vdW50CQDMCAIDCQAAAggFAmRMBmNhbGxlcgkBEUBleHRyTmF0aXZlKDEwNjIpAQUCZnUGCQECYUwBAhFQZXJtaXNzaW9uIGRlbmllZAUDbmlsAwkAAAIFAmVIBQJlSAQCZE0JAQV2YWx1ZQEJAJEDAggFAmRMCHBheW1lbnRzAAAEAmZsCQECYmEBCAUCZE0HYXNzZXRJZAQCZmsDCQAAAgUCZmgHCQECYUgCBQR0aGlzCQECYWYACQECYUgCBQR0aGlzCQECYWUABAJmbQkAZQIJAQJiRQEFAmZsCAkBBXZhbHVlAQkAkQMCCAUCZEwIcGF5bWVudHMAAAZhbW91bnQEAmZuCQECYkUBBQJmawQCZm8JAGsDBQJmbgUCZmcJAGQCBQJmbQUCZmcEAmZwCQC5AgIJALYCAQUCZm0JALYCAQUCZm4EAmZxCQC5AgIJALcCAgkAtgIBCQECYkUBBQJmbAkAtgIBBQJmaQkAuAICCQC2AgEJAQJiRQEFAmZrCQC2AgEFAmZvBAJmcgMJAMACAgUCZnEFAmZwBgkAAgECFG5ldyBLIGlzIGZld2VyIGVycm9yAwkAAAIFAmZyBQJmcgQCZnYDCQBnAgUCZm8FAmZzBgkAAgECLEV4Y2hhbmdlIHJlc3VsdCBpcyBmZXdlciBjb2lucyB0aGFuIGV4cGVjdGVkAwkAAAIFAmZ2BQJmdgkAlAoCCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMJARFAZXh0ck5hdGl2ZSgxMDYyKQEFAmZ0BQJmbwkBAmFZAQUCZmsFA25pbAUCZm8JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CZEwBCnNldE1hbmFnZXIBAmZ3BAJmeAkBAmZlAQUCZEwDCQAAAgUCZngFAmZ4BAJmeQkA2QQBBQJmdwMJAAACBQJmeQUCZnkJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAVYABQJmdwUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmRMAQ5jb25maXJtTWFuYWdlcgAEAmZ6CQECZmIABAJmQQMJAQlpc0RlZmluZWQBBQJmegYJAAIBAhJObyBwZW5kaW5nIG1hbmFnZXIDCQAAAgUCZkEFAmZBBAJmQgMJAAACCAUCZEwPY2FsbGVyUHVibGljS2V5CQEFdmFsdWUBBQJmegYJAAIBAhtZb3UgYXJlIG5vdCBwZW5kaW5nIG1hbmFnZXIDCQAAAgUCZkIFAmZCCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQFVAAkA2AQBCQEFdmFsdWUBBQJmegkAzAgCCQELRGVsZXRlRW50cnkBCQEBVgAFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJkTAEDcHV0AgJjegJmQwMJAGYCAAAFAmN6CQACAQIgSW52YWxpZCBzbGlwcGFnZVRvbGVyYW5jZSBwYXNzZWQEAmRSCQECZE8DBQJkTAUCY3oGBAJkYggFAmRSAl8yBAJjZwgFAmRSAl83BAJjeAgFAmRSAl85BAJkYwgFAmRSA18xMAQCZGQIBQJkUgNfMTEEAmZECAUCZFIDXzEyBAJmRQgFAmRSA18xMwQCZFAJALYCAQgJAQV2YWx1ZQEJAJEDAggFAmRMCHBheW1lbnRzAAAGYW1vdW50BAJkUQkAtgIBCAkBBXZhbHVlAQkAkQMCCAUCZEwIcGF5bWVudHMAAQZhbW91bnQEAmRzCQECZGwDBQJkUAUCZFEJALYCAQAAAwkAAAIFAmRzBQJkcwQCZFUJAPwHBAUCYU8CBGVtaXQJAMwIAgUCZGIFA25pbAUDbmlsAwkAAAIFAmRVBQJkVQQCZFYEAmRXBQJkVQMJAAECBQJkVwIHQWRkcmVzcwQCZFgFAmRXCQD8BwQFAmRYAgRlbWl0CQDMCAIFAmRiBQNuaWwFA25pbAUEdW5pdAMJAAACBQJkVgUCZFYEAmZGAwkAZgIFAmRjAAAJAPwHBAUCYm8CA3B1dAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQJmRAUCZGMFA25pbAUDbmlsAwkAAAIFAmZGBQJmRgQCZkcDCQBmAgUCZGQAAAkA/AcEBQJibwIDcHV0BQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFAmZFBQJkZAUDbmlsBQNuaWwDCQAAAgUCZkcFAmZHBAJmSAMFAmZDBAJmSQkA/AcEBQJibgIFc3Rha2UFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUCY2cFAmRiBQNuaWwDCQAAAgUCZkkFAmZJBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAmRMBmNhbGxlcgUCZGIFAmNnBQNuaWwEAmZKCQECZHQDAAAAAAAAAwkAAAIFAmZKBQJmSgQCZGsIBQJmSgJfMgQCZksIBQJmSgJfMQQCZkwJAQJkeAIFAmRzBQJkawMJAAACBQJmTAUCZkwJAM4IAgkAzggCBQJjeAUCZkgFAmZLCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmRMAQpwdXRGb3JGcmVlAQJmTQMJAGYCAAAFAmZNCQACAQIUSW52YWxpZCB2YWx1ZSBwYXNzZWQEAmRSCQECZE8DBQJkTAUCZk0HBAJjeAgFAmRSAl85BAJkUAkAtgIBCAkBBXZhbHVlAQkAkQMCCAUCZEwIcGF5bWVudHMAAAZhbW91bnQEAmRRCQC2AgEICQEFdmFsdWUBCQCRAwIIBQJkTAhwYXltZW50cwABBmFtb3VudAQCZHMJAQJkbAMFAmRQBQJkUQkAtgIBAAADCQAAAgUCZHMFAmRzBAJmTgkBAmR0AwAAAAAAAAQCZksIBQJmTgJfMQQCZGsIBQJmTgJfMgQCZkwJAQJkeAIFAmRzBQJkawMJAAACBQJmTAUCZkwJAM4IAgUCY3gFAmZLCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmRMAQlwdXRPbmVUa24CAmZPAmZQBAJmUQoAAmFSCQD8BwQFAmFPAihpc1Bvb2xPbmVUb2tlbk9wZXJhdGlvbnNEaXNhYmxlZFJFQURPTkxZCQDMCAIJAKUIAQUEdGhpcwUDbmlsBQNuaWwDCQABAgUCYVICB0Jvb2xlYW4FAmFSCQACAQkArAICCQADAQUCYVICHCBjb3VsZG4ndCBiZSBjYXN0IHRvIEJvb2xlYW4EAmZSAwMDCQECYVQABgkAAAIFAmJnBQFsBgkAAAIFAmJnBQFuBgUCZlEEAmVICQDMCAIDAwkBASEBBQJmUgYJAQJmYwEFAmRMBgkBAmFMAQIhcHV0IG9wZXJhdGlvbiBpcyBibG9ja2VkIGJ5IGFkbWluCQDMCAIDCQAAAgkAkAMBCAUCZEwIcGF5bWVudHMAAQYJAQJhTAECHmV4YWN0bHkgMSBwYXltZW50IGFyZSBleHBlY3RlZAUDbmlsAwkAAAIFAmVIBQJlSAQCZlMJAJEDAggFAmRMCHBheW1lbnRzAAAEAmVjCAUCZlMHYXNzZXRJZAQCZWIIBQJmUwZhbW91bnQEAmRzAwkAAAIFAmVjBQJiaQkBAmRsAwkAtgIBBQJlYgkAtgIBAAAJALYCAQAAAwkAAAIFAmVjBQJiagkBAmRsAwkAtgIBAAAJALYCAQUCZWIJALYCAQAACQECYUwBAh5wYXltZW50IGFzc2V0IGlzIG5vdCBzdXBwb3J0ZWQDCQAAAgUCZHMFAmRzBAJhYggFAmRMBmNhbGxlcgQCYWMIBQJkTA10cmFuc2FjdGlvbklkBAJmVAkBAmVhBAUCZWIFAmVjBQJhYgUCYWMDCQAAAgUCZlQFAmZUBAJlZwgFAmZUAl81BAJmVQgFAmZUAl80BAJkWggFAmZUAl8zBAJkZQgFAmZUAl8yBAJmVggFAmZUAl8xBAJmVwMDCQBmAgUCZk8AAAkAZgIFAmZPBQJmVgcJAQJhTAEJALkJAgkAzAgCAh9hbW91bnQgdG8gcmVjZWl2ZSBpcyBsZXNzIHRoYW4gCQDMCAIJAKQDAQUCZk8FA25pbAIABQJmVgQCZFUJAQJkUwEFAmZXAwkAAAIFAmRVBQJkVQQCZkgDBQJmUAQCZlgJAPwHBAUCYm4CBXN0YWtlBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFAmJoBQJmVwUDbmlsAwkAAAIFAmZYBQJmWAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQJkTAZjYWxsZXIFAmZXBQJiaAUDbmlsBAJmWQMJAGYCBQJkWgAACQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFAmFQBQJkWgUCZWMFA25pbAUDbmlsBAJmWgMJAAACBQR0aGlzBQJhUAkAlAoCAAAAAAMFAmVnCQCUCgIJAQEtAQUCZFoAAAkAlAoCAAAJAQEtAQUCZFoEAmR1CAUCZloCXzEEAmR2CAUCZloCXzIEAmdhCQECZHQDBQJkdQUCZHYAAAQCZksIBQJnYQJfMQQCZGsIBQJnYQJfMgQCZEUJAQV2YWx1ZQEJAKIIAQUCYWoEAmZMCQECZHgCBQJkcwUCZGsDCQAAAgUCZkwFAmZMCQCUCgIJAM4IAgkAzggCCQDOCAIFAmRlBQJmSAUCZlkFAmZLBQJmVwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJkTAERcHV0T25lVGtuUkVBRE9OTFkCAmVjAmViBAJnYgkBAmVhBAUCZWIJAQJhWQEFAmVjBQR1bml0BQR1bml0BAJmVggFAmdiAl8xBAJkZQgFAmdiAl8yBAJkWggFAmdiAl8zBAJmVQgFAmdiAl80BAJlZwgFAmdiAl81CQCUCgIFA25pbAkAlQoDBQJmVgUCZFoFAmZVAmRMAQlnZXRPbmVUa24CAmdjAmZPBAJmUQoAAmFSCQD8BwQFAmFPAihpc1Bvb2xPbmVUb2tlbk9wZXJhdGlvbnNEaXNhYmxlZFJFQURPTkxZCQDMCAIJAKUIAQUEdGhpcwUDbmlsBQNuaWwDCQABAgUCYVICB0Jvb2xlYW4FAmFSCQACAQkArAICCQADAQUCYVICHCBjb3VsZG4ndCBiZSBjYXN0IHRvIEJvb2xlYW4EAmdkAwMJAQJhVAAGCQAAAgUCYmcFAW4GBQJmUQQCZUgJAMwIAgMDCQEBIQEFAmdkBgkBAmZjAQUCZEwGCQECYUwBAiFnZXQgb3BlcmF0aW9uIGlzIGJsb2NrZWQgYnkgYWRtaW4JAMwIAgMJAAACCQCQAwEIBQJkTAhwYXltZW50cwABBgkBAmFMAQIeZXhhY3RseSAxIHBheW1lbnQgYXJlIGV4cGVjdGVkBQNuaWwDCQAAAgUCZUgFAmVIBAJlRwkBAmFZAQUCZ2MEAmZTCQCRAwIIBQJkTAhwYXltZW50cwAABAJlYwgFAmZTB2Fzc2V0SWQEAmVvCAUCZlMGYW1vdW50BAJkcwkBAmRsAwkAtgIBAAAJALYCAQAACQC2AgEAAAMJAAACBQJkcwUCZHMEAmFiCAUCZEwGY2FsbGVyBAJhYwgFAmRMDXRyYW5zYWN0aW9uSWQEAmdlCQECZUYFBQJlRwUCZW8FAmVjBQJhYgUCYWMDCQAAAgUCZ2UFAmdlBAJlSQgFAmdlAl81BAJmVQgFAmdlAl80BAJkWggFAmdlAl8zBAJkZQgFAmdlAl8yBAJnZggFAmdlAl8xBAJkVAMDCQBmAgUCZk8AAAkAZgIFAmZPBQJnZgcJAQJhTAEJALkJAgkAzAgCAh9hbW91bnQgdG8gcmVjZWl2ZSBpcyBsZXNzIHRoYW4gCQDMCAIJAKQDAQUCZk8FA25pbAIABQJnZgQCZ2cJAPwHBAUCYU8CBGJ1cm4JAMwIAgUCZW8FA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUCZWMFAmVvBQNuaWwDCQAAAgUCZ2cFAmdnBAJnaAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQJhYgUCZFQFAmVHBQNuaWwEAmZZAwkAZgIFAmRaAAAJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUCYVAFAmRaBQJlRwUDbmlsBQNuaWwEAmdpBAJnagMJAAACBQR0aGlzBQJhUAAABQJkWgMFAmVJCQCUCgIJAQEtAQkAZAIFAmRUBQJnagAACQCUCgIAAAkBAS0BCQBkAgUCZFQFAmdqBAJkdQgFAmdpAl8xBAJkdggFAmdpAl8yBAJnawkBAmR0AwUCZHUFAmR2AAAEAmZLCAUCZ2sCXzEEAmRrCAUCZ2sCXzIEAmZMCQECZHgCBQJkcwUCZGsDCQAAAgUCZkwFAmZMCQCUCgIJAM4IAgkAzggCCQDOCAIFAmRlBQJnaAUCZlkFAmZLBQJkVAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJkTAERZ2V0T25lVGtuUkVBRE9OTFkCAmVHAmVvBAJnbAkBAmVGBQkBAmFZAQUCZUcFAmVvBQJiaAUEdW5pdAUEdW5pdAQCZ2YIBQJnbAJfMQQCZGUIBQJnbAJfMgQCZFoIBQJnbAJfMwQCZlUIBQJnbAJfNAQCZUkIBQJnbAJfNQkAlAoCBQNuaWwJAJUKAwUCZ2YFAmRaBQJmVQJkTAETdW5zdGFrZUFuZEdldE9uZVRrbgMCZ20CZ2MCZk8EAmZRCgACYVIJAPwHBAUCYU8CKGlzUG9vbE9uZVRva2VuT3BlcmF0aW9uc0Rpc2FibGVkUkVBRE9OTFkJAMwIAgkApQgBBQR0aGlzBQNuaWwFA25pbAMJAAECBQJhUgIHQm9vbGVhbgUCYVIJAAIBCQCsAgIJAAMBBQJhUgIcIGNvdWxkbid0IGJlIGNhc3QgdG8gQm9vbGVhbgQCZ2QDAwkBAmFUAAYJAAACBQJiZwUBbgYFAmZRBAJlSAkAzAgCAwMJAQEhAQUCZ2QGCQECZmMBBQJkTAYJAQJhTAECIWdldCBvcGVyYXRpb24gaXMgYmxvY2tlZCBieSBhZG1pbgkAzAgCAwkAAAIJAJADAQgFAmRMCHBheW1lbnRzAAAGCQECYUwBAhhubyBwYXltZW50cyBhcmUgZXhwZWN0ZWQFA25pbAMJAAACBQJlSAUCZUgEAmVHCQECYVkBBQJnYwQCYWIIBQJkTAZjYWxsZXIEAmFjCAUCZEwNdHJhbnNhY3Rpb25JZAQCZHMJAQJkbAMJALYCAQAACQC2AgEAAAkAtgIBAAADCQAAAgUCZHMFAmRzBAJnbgkA/AcEBQJibgIHdW5zdGFrZQkAzAgCCQDYBAEFAmJoCQDMCAIFAmdtBQNuaWwFA25pbAMJAAACBQJnbgUCZ24EAmdvCQECZUYFBQJlRwUCZ20FAmJoBQJhYgUCYWMDCQAAAgUCZ28FAmdvBAJlSQgFAmdvAl81BAJmVQgFAmdvAl80BAJkWggFAmdvAl8zBAJkZQgFAmdvAl8yBAJnZggFAmdvAl8xBAJkVAMDCQBmAgUCZk8AAAkAZgIFAmZPBQJnZgcJAQJhTAEJALkJAgkAzAgCAh9hbW91bnQgdG8gcmVjZWl2ZSBpcyBsZXNzIHRoYW4gCQDMCAIJAKQDAQUCZk8FA25pbAIABQJnZgQCZ2cJAPwHBAUCYU8CBGJ1cm4JAMwIAgUCZ20FA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUCYmgFAmdtBQNuaWwDCQAAAgUCZ2cFAmdnBAJnaAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUCZEwGY2FsbGVyBQJkVAUCZUcFA25pbAQCZlkDCQBmAgUCZFoAAAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQJhUAUCZFoFAmVHBQNuaWwFA25pbAQCZ3AEAmdqAwkAAAIFBHRoaXMFAmFQAAAFAmRaAwUCZUkJAJQKAgkBAS0BCQBkAgUCZFQFAmdqAAAJAJQKAgAACQEBLQEJAGQCBQJkVAUCZ2oEAmR1CAUCZ3ACXzEEAmR2CAUCZ3ACXzIEAmdxCQECZHQDBQJkdQUCZHYAAAQCZksIBQJncQJfMQQCZGsIBQJncQJfMgQCZkwJAQJkeAIFAmRzBQJkawMJAAACBQJmTAUCZkwJAJQKAgkAzggCCQDOCAIJAM4IAgUCZGUFAmdoBQJmWQUCZksFAmRUCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmRMAQNnZXQABAJjUAkBAmRLAQUCZEwEAmdyCAUCY1ACXzEEAmN3CAUCY1ACXzIEAmROCAUCY1ACXzMEAmNlCAUCY1ACXzQEAmN4CAUCY1ACXzUEAmRzCQECZGwDCQC2AgEAAAkAtgIBAAAJALYCAQAAAwkAAAIFAmRzBQJkcwQCZ3MJAPwHBAUCYU8CBGJ1cm4JAMwIAgUCZE4FA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUCY2UFAmROBQNuaWwDCQAAAgUCZ3MFAmdzBAJndAkBAmR0AwkBAS0BBQJncgkBAS0BBQJjdwAABAJmSwgFAmd0Al8xBAJkawgFAmd0Al8yBAJmTAkBAmR4AgUCZHMFAmRrAwkAAAIFAmZMBQJmTAkAzggCBQJjeAUCZksJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CZEwBCWdldE5vTGVzcwICZ3UCZ3YEAmNQCQECZEsBBQJkTAQCY3YIBQJjUAJfMQQCY3cIBQJjUAJfMgQCZE4IBQJjUAJfMwQCY2UIBQJjUAJfNAQCY3gIBQJjUAJfNQMJAGYCBQJndQUCY3YJAAIBCQCsAgIJAKwCAgkArAICAhxub0xlc3NUaGVuQW10QXNzZXQgZmFpbGVkOiAgCQCkAwEFAmN2AgMgPCAJAKQDAQUCZ3UDCQBmAgUCZ3YFAmN3CQACAQkArAICCQCsAgIJAKwCAgIdbm9MZXNzVGhlblByaWNlQXNzZXQgZmFpbGVkOiAJAKQDAQUCY3cCAyA8IAkApAMBBQJndgQCZHMJAQJkbAMJALYCAQAACQC2AgEAAAkAtgIBAAADCQAAAgUCZHMFAmRzBAJncwkA/AcEBQJhTwIEYnVybgkAzAgCBQJkTgUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQJjZQUCZE4FA25pbAMJAAACBQJncwUCZ3MEAmd3CQECZHQDCQEBLQEFAmN2CQEBLQEFAmN3AAAEAmZLCAUCZ3cCXzEEAmRrCAUCZ3cCXzIEAmZMCQECZHgCBQJkcwUCZGsDCQAAAgUCZkwFAmZMCQDOCAIFAmN4BQJmSwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJkTAENdW5zdGFrZUFuZEdldAECZFQEAmd4AwkBAiE9AgkAkAMBCAUCZEwIcGF5bWVudHMAAAkAAgECGE5vIHBheW1lbnRzIGFyZSBleHBlY3RlZAYDCQAAAgUCZ3gFAmd4BAJiVAkBAmFWAAQCY2cJANkEAQkAkQMCBQJiVAUBcQQCZHMJAQJkbAMJALYCAQAACQC2AgEAAAkAtgIBAAADCQAAAgUCZHMFAmRzBAJnbgkA/AcEBQJibgIHdW5zdGFrZQkAzAgCCQDYBAEFAmNnCQDMCAIFAmRUBQNuaWwFA25pbAMJAAACBQJnbgUCZ24EAmNQCQECY2MECQDYBAEIBQJkTA10cmFuc2FjdGlvbklkCQDYBAEFAmNnBQJkVAgFAmRMBmNhbGxlcgQCY3YIBQJjUAJfMQQCY3cIBQJjUAJfMgQCY2oJAQ1wYXJzZUludFZhbHVlAQgFAmNQAl85BAJjeAgFAmNQA18xMAQCZ3kDAwkBAmFUAAYJAAACBQJjagUBbgkAAgEJAKwCAgIsR2V0IG9wZXJhdGlvbiBpcyBibG9ja2VkIGJ5IGFkbWluLiBTdGF0dXMgPSAJAKQDAQUCY2oGAwkAAAIFAmd5BQJneQQCZ3MJAPwHBAUCYU8CBGJ1cm4JAMwIAgUCZFQFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUCY2cFAmRUBQNuaWwDCQAAAgUCZ3MFAmdzBAJnegkBAmR0AwkBAS0BBQJjdgkBAS0BBQJjdwAABAJmSwgFAmd6Al8xBAJkawgFAmd6Al8yBAJmTAkBAmR4AgUCZHMFAmRrAwkAAAIFAmZMBQJmTAkAzggCBQJjeAUCZksJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CZEwBE3Vuc3Rha2VBbmRHZXROb0xlc3MDAmdtAmdBAmd2BAJnZAMJAQJhVAAGCQAAAgUCYmcFAW4EAmVICQDMCAIDCQEBIQEFAmdkBgkAAgECIWdldCBvcGVyYXRpb24gaXMgYmxvY2tlZCBieSBhZG1pbgkAzAgCAwkAAAIJAJADAQgFAmRMCHBheW1lbnRzAAAGCQACAQIYbm8gcGF5bWVudHMgYXJlIGV4cGVjdGVkBQNuaWwDCQAAAgUCZUgFAmVIBAJkcwkBAmRsAwkAtgIBAAAJALYCAQAACQC2AgEAAAMJAAACBQJkcwUCZHMEAmduCQD8BwQFAmJuAgd1bnN0YWtlCQDMCAIJANgEAQUCYmgJAMwIAgUCZ20FA25pbAUDbmlsAwkAAAIFAmduBQJnbgQCY1AJAQJjYwQJANgEAQgFAmRMDXRyYW5zYWN0aW9uSWQJANgEAQUCYmgFAmdtCAUCZEwGY2FsbGVyBAJjdggFAmNQAl8xBAJjdwgFAmNQAl8yBAJjeAgFAmNQA18xMAQCZ0IJAMwIAgMJAGcCBQJjdgUCZ0EGCQACAQkAuQkCCQDMCAICLGFtb3VudCBhc3NldCBhbW91bnQgdG8gcmVjZWl2ZSBpcyBsZXNzIHRoYW4gCQDMCAIJAKQDAQUCZ0EFA25pbAIACQDMCAIDCQBnAgUCY3cFAmd2BgkAAgEJALkJAgkAzAgCAitwcmljZSBhc3NldCBhbW91bnQgdG8gcmVjZWl2ZSBpcyBsZXNzIHRoYW4gCQDMCAIJAKQDAQUCZ3YFA25pbAIABQNuaWwDCQAAAgUCZ0IFAmdCBAJncwkA/AcEBQJhTwIEYnVybgkAzAgCBQJnbQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQJiaAUCZ20FA25pbAMJAAACBQJncwUCZ3MEAmdDCQECZHQDCQEBLQEFAmN2CQEBLQEFAmN3AAAEAmZLCAUCZ0MCXzEEAmRrCAUCZ0MCXzIEAmZMCQECZHgCBQJkcwUCZGsDCQAAAgUCZkwFAmZMCQDOCAIFAmN4BQJmSwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJkTAEIYWN0aXZhdGUCAmdEAmdFAwkBAiE9AgkApQgBCAUCZEwGY2FsbGVyCQClCAEFAmFPCQACAQIScGVybWlzc2lvbnMgZGVuaWVkCQCUCgIJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAmFlAAUCZ0QJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAmFmAAUCZ0UFA25pbAIHc3VjY2VzcwJkTAEKcmVmcmVzaEtMcAAEAmdGCQELdmFsdWVPckVsc2UCCQCfCAEFAmFrAAAEAmdHAwkAZwIJAGUCBQZoZWlnaHQFAmdGBQJhbgUEdW5pdAkBAmFMAQkAuQkCCQDMCAIJAKQDAQUCYW4JAMwIAgIvIGJsb2NrcyBoYXZlIG5vdCBwYXNzZWQgc2luY2UgdGhlIHByZXZpb3VzIGNhbGwFA25pbAIAAwkAAAIFAmdHBQJnRwQCZEUJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAqAMBCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMFAmFqAgEwCQECYU4BAgtpbnZhbGlkIGtMcAQCZ0gJAQJkdAMAAAAAAAAEAmdJCAUCZ0gCXzEEAmRrCAUCZ0gCXzIEAmR3AwkBAiE9AgUCZEUFAmRrBQJnSQkBAmFMAQISbm90aGluZyB0byByZWZyZXNoCQCUCgIFAmR3CQCmAwEFAmRrCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmRMARxnZXRQb29sQ29uZmlnV3JhcHBl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CAIFAmNqCQDMCAIJAKQDAQUCY0EJAMwIAgkApAMBBQJjQwUDbmlsBQFqAmRMARNldmFsdWF0ZUdldFJFQURPTkxZAgJnWAJnWQQCY1AJAQJjYwQCAAUCZ1gFAmdZBQR0aGlzBAJjdggFAmNQAl8xBAJjdwgFAmNQAl8yBAJjbAgFAmNQAl81BAJjbggFAmNQAl82BAJjawgFAmNQAl83BAJjcQgFAmNQAl84BAJjagkBDXBhcnNlSW50VmFsdWUBCAUCY1ACXzkJAJQKAgUDbmlsCQC5CQIJAMwIAgIOJWQlZCVkJWQlZCVkJWQJAMwIAgkApAMBBQJjdgkAzAgCCQCkAwEFAmN3CQDMCAIJAKQDAQUCY2wJAMwIAgkApAMBBQJjbgkAzAgCCQCkAwEFAmNrCQDMCAIJAKYDAQUCY3EJAMwIAgkApAMBBQJjagUDbmlsBQFqAQJnWgECaGEABAJoYgQCZFcJAQJlWgADCQABAgUCZFcCCkJ5dGVWZWN0b3IEAmZkBQJkVwUCZmQDCQABAgUCZFcCBFVuaXQIBQJnWg9zZW5kZXJQdWJsaWNLZXkJAAIBAgtNYXRjaCBlcnJvcgQCZFcFAmdaAwkAAQIFAmRXAgVPcmRlcgQCZEEFAmRXBAJoYwkBAmFVAAQCaGQJAQJkegEFAmRBBAJhRAgFAmhkAl8xBAJhRQgFAmhkAl8yBAJhRgkA9AMDCAUCZEEJYm9keUJ5dGVzCQCRAwIIBQJkQQZwcm9vZnMAAAgFAmRBD3NlbmRlclB1YmxpY0tleQQCYUcJAPQDAwgFAmRBCWJvZHlCeXRlcwkAkQMCCAUCZEEGcHJvb2ZzAAEFAmhjAwMDBQJhRAUCYUYHBQJhRwcGCQECYUMEBQJhRAUCYUUFAmFGBQJhRwMJAAECBQJkVwIUU2V0U2NyaXB0VHJhbnNhY3Rpb24EAmZhBQJkVwMJAPQDAwgFAmdaCWJvZHlCeXRlcwkAkQMCCAUCZ1oGcHJvb2ZzAAAFAmhiBgQCaGUJAPYDAQkBBXZhbHVlAQgFAmZhBnNjcmlwdAQCaGYJANsEAQkBBXZhbHVlAQkAnQgCBQJhTwkBAmFBAAQCaGcJAPEHAQUEdGhpcwMJAAACBQJoZgUCaGUJAQIhPQIFAmhnBQJoZQcJAPQDAwgFAmdaCWJvZHlCeXRlcwkAkQMCCAUCZ1oGcHJvb2ZzAAAFAmhiqF/ylA==", "height": 2542610, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: none Next: 9YDuFcb4KH94A61b2iK6U6nfQELgaqdKkxgNYbt8S9TE Full:
OldNewDifferences
1-# no script
1+{-# STDLIB_VERSION 6 #-}
2+{-# SCRIPT_TYPE ACCOUNT #-}
3+{-# CONTENT_TYPE DAPP #-}
4+let lPdecimals = 8
5+
6+let scale8 = 100000000
7+
8+let scale8BigInt = toBigInt(100000000)
9+
10+let scale18 = toBigInt(1000000000000000000)
11+
12+let zeroBigInt = toBigInt(0)
13+
14+let big0 = toBigInt(0)
15+
16+let big1 = toBigInt(1)
17+
18+let big2 = toBigInt(2)
19+
20+let wavesString = "WAVES"
21+
22+let SEP = "__"
23+
24+let PoolActive = 1
25+
26+let PoolPutDisabled = 2
27+
28+let PoolMatcherDisabled = 3
29+
30+let PoolShutdown = 4
31+
32+let idxPoolAddress = 1
33+
34+let idxPoolStatus = 2
35+
36+let idxPoolLPAssetId = 3
37+
38+let idxAmtAssetId = 4
39+
40+let idxPriceAssetId = 5
41+
42+let idxAmtAssetDcm = 6
43+
44+let idxPriceAssetDcm = 7
45+
46+let idxIAmtAssetId = 8
47+
48+let idxIPriceAssetId = 9
49+
50+let idxLPAssetDcm = 10
51+
52+let idxPoolAmtAssetAmt = 1
53+
54+let idxPoolPriceAssetAmt = 2
55+
56+let idxPoolLPAssetAmt = 3
57+
58+let idxFactoryStakingContract = 1
59+
60+let idxFactorySlippageContract = 7
61+
62+func toX18 (origVal,origScaleMult) = fraction(toBigInt(origVal), scale18, toBigInt(origScaleMult))
63+
64+
65+func toX18BigInt (origVal,origScaleMult) = fraction(origVal, scale18, origScaleMult)
66+
67+
68+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))
72+
73+
74+func toScale (amt,resScale,curScale) = fraction(amt, resScale, curScale)
75+
76+
77+func abs (val) = if ((0 > val))
78+ then -(val)
79+ else val
80+
81+
82+func absBigInt (val) = if ((zeroBigInt > val))
83+ then -(val)
84+ else val
85+
86+
87+func swapContract () = "%s__swapContract"
88+
89+
90+func fc () = "%s__factoryContract"
91+
92+
93+func mpk () = "%s__managerPublicKey"
94+
95+
96+func pmpk () = "%s__pendingManagerPublicKey"
97+
98+
99+func pl () = "%s%s__price__last"
100+
101+
102+func ph (h,timestamp) = makeString(["%s%s%d%d__price__history", toString(h), toString(timestamp)], SEP)
103+
104+
105+func pau (userAddress,txId) = ((("%s%s%s__P__" + userAddress) + "__") + txId)
106+
107+
108+func gau (userAddress,txId) = ((("%s%s%s__G__" + userAddress) + "__") + txId)
109+
110+
111+func aa () = "%s__amountAsset"
112+
113+
114+func pa () = "%s__priceAsset"
115+
116+
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+
133+func keyFactoryConfig () = "%s__factoryConfig"
134+
135+
136+func keyMatcherPub () = "%s%s__matcher__publicKey"
137+
138+
139+func keyMappingPoolContractAddressToPoolAssets (poolContractAddress) = (("%s%s%s__" + poolContractAddress) + "__mappings__poolContract2LpAsset")
140+
141+
142+func keyPoolConfig (iAmtAsset,iPriceAsset) = (((("%d%d%s__" + iAmtAsset) + "__") + iPriceAsset) + "__config")
143+
144+
145+func keyMappingsBaseAsset2internalId (baseAssetStr) = ("%s%s%s__mappings__baseAsset2internalId__" + baseAssetStr)
146+
147+
148+func keyAllPoolsShutdown () = "%s__shutdown"
149+
150+
151+func keyPoolWeight (contractAddress) = ("%s%s__poolWeight__" + contractAddress)
152+
153+
154+func keyAllowedLpScriptHash () = "%s__allowedLpScriptHash"
155+
156+
157+let keyFeeCollectorAddress = "%s__feeCollectorAddress"
158+
159+func throwOrderError (orderValid,orderValidInfo,senderValid,matcherValid) = throw((((((((("order validation failed: orderValid=" + toString(orderValid)) + " (") + orderValidInfo) + ")") + " senderValid=") + toString(senderValid)) + " matcherValid=") + toString(matcherValid)))
160+
161+
162+func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
163+
164+
165+func getIntOrFail (address,key) = valueOrErrorMessage(getInteger(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
166+
167+
168+func throwErr (msg) = throw(makeString(["lp.ride:", msg], " "))
169+
170+
171+func fmtErr (msg) = makeString(["lp.ride:", msg], " ")
172+
173+
174+let factoryContract = addressFromStringValue(getStringOrFail(this, fc()))
175+
176+let feeCollectorAddress = addressFromStringValue(getStringOrFail(factoryContract, keyFeeCollectorAddress))
177+
178+let inFee = {
179+ let @ = invoke(factoryContract, "getInFeeREADONLY", [toString(this)], nil)
180+ if ($isInstanceOf(@, "Int"))
181+ then @
182+ else throw(($getType(@) + " couldn't be cast to Int"))
183+ }
184+
185+let outFee = {
186+ let @ = invoke(factoryContract, "getOutFeeREADONLY", [toString(this)], nil)
187+ if ($isInstanceOf(@, "Int"))
188+ then @
189+ else throw(($getType(@) + " couldn't be cast to Int"))
190+ }
191+
192+func isGlobalShutdown () = valueOrElse(getBoolean(factoryContract, keyAllPoolsShutdown()), false)
193+
194+
195+func getMatcherPubOrFail () = fromBase58String(getStringOrFail(factoryContract, keyMatcherPub()))
196+
197+
198+func getPoolConfig () = {
199+ let amtAsset = getStringOrFail(this, aa())
200+ let priceAsset = getStringOrFail(this, pa())
201+ let iPriceAsset = getIntOrFail(factoryContract, keyMappingsBaseAsset2internalId(priceAsset))
202+ let iAmtAsset = getIntOrFail(factoryContract, keyMappingsBaseAsset2internalId(amtAsset))
203+ split(getStringOrFail(factoryContract, keyPoolConfig(toString(iAmtAsset), toString(iPriceAsset))), SEP)
204+ }
205+
206+
207+func parseAssetId (input) = if ((input == wavesString))
208+ then unit
209+ else fromBase58String(input)
210+
211+
212+func assetIdToString (input) = if ((input == unit))
213+ then wavesString
214+ else toBase58String(value(input))
215+
216+
217+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]))
218+
219+
220+let poolConfigParsed = parsePoolConfig(getPoolConfig())
221+
222+let $t084698635 = poolConfigParsed
223+
224+let cfgPoolAddress = $t084698635._1
225+
226+let cfgPoolStatus = $t084698635._2
227+
228+let cfgLpAssetId = $t084698635._3
229+
230+let cfgAmountAssetId = $t084698635._4
231+
232+let cfgPriceAssetId = $t084698635._5
233+
234+let cfgAmountAssetDecimals = $t084698635._6
235+
236+let cfgPriceAssetDecimals = $t084698635._7
237+
238+func getFactoryConfig () = split(getStringOrFail(factoryContract, keyFactoryConfig()), SEP)
239+
240+
241+let stakingContract = valueOrErrorMessage(addressFromString(getFactoryConfig()[idxFactoryStakingContract]), "incorrect staking address")
242+
243+let slippageContract = valueOrErrorMessage(addressFromString(getFactoryConfig()[idxFactorySlippageContract]), "incorrect staking address")
244+
245+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)
246+
247+
248+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)
249+
250+
251+func getAccBalance (assetId) = if ((assetId == "WAVES"))
252+ then wavesBalance(this).available
253+ else assetBalance(this, fromBase58String(assetId))
254+
255+
256+func calcPriceBigInt (prAmtX18,amAmtX18) = fraction(prAmtX18, scale18, amAmtX18)
257+
258+
259+func calcPriceBigIntRound (prAmtX18,amAmtX18,round) = fraction(prAmtX18, scale18, amAmtX18, round)
260+
261+
262+func privateCalcPrice (amAssetDcm,prAssetDcm,amAmt,prAmt) = {
263+ let amtAssetAmtX18 = toX18(amAmt, amAssetDcm)
264+ let priceAssetAmtX18 = toX18(prAmt, prAssetDcm)
265+ calcPriceBigInt(priceAssetAmtX18, amtAssetAmtX18)
266+ }
267+
268+
269+func calcPrices (amAmt,prAmt,lpAmt) = {
270+ let cfg = getPoolConfig()
271+ let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
272+ let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
273+ let priceX18 = privateCalcPrice(amtAssetDcm, priceAssetDcm, amAmt, prAmt)
274+ let amAmtX18 = toX18(amAmt, amtAssetDcm)
275+ let prAmtX18 = toX18(prAmt, priceAssetDcm)
276+ let lpAmtX18 = toX18(lpAmt, scale8)
277+ let lpPriceInAmAssetX18 = calcPriceBigInt(amAmtX18, lpAmtX18)
278+ let lpPriceInPrAssetX18 = calcPriceBigInt(prAmtX18, lpAmtX18)
279+[priceX18, lpPriceInAmAssetX18, lpPriceInPrAssetX18]
280+ }
281+
282+
283+func calculatePrices (amAmt,prAmt,lpAmt) = {
284+ let prices = calcPrices(amAmt, prAmt, lpAmt)
285+[fromX18(prices[0], scale8), fromX18(prices[1], scale8), fromX18(prices[2], scale8)]
286+ }
287+
288+
289+func estimateGetOperation (txId58,pmtAssetId,pmtLpAmt,userAddress) = {
290+ let cfg = getPoolConfig()
291+ let lpAssetId = cfg[idxPoolLPAssetId]
292+ let amAssetId = cfg[idxAmtAssetId]
293+ let prAssetId = cfg[idxPriceAssetId]
294+ let amAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
295+ let prAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
296+ let poolStatus = cfg[idxPoolStatus]
297+ let lpEmission = valueOrErrorMessage(assetInfo(fromBase58String(lpAssetId)), (("Asset " + lpAssetId) + " doesn't exist")).quantity
298+ if ((lpAssetId != pmtAssetId))
299+ then throw("Invalid asset passed.")
300+ else {
301+ let amBalance = getAccBalance(amAssetId)
302+ let amBalanceX18 = toX18(amBalance, amAssetDcm)
303+ let prBalance = getAccBalance(prAssetId)
304+ let prBalanceX18 = toX18(prBalance, prAssetDcm)
305+ let curPriceX18 = calcPriceBigInt(prBalanceX18, amBalanceX18)
306+ let curPrice = fromX18(curPriceX18, scale8)
307+ let pmtLpAmtX18 = toX18(pmtLpAmt, scale8)
308+ let lpEmissionX18 = toX18(lpEmission, scale8)
309+ let outAmAmtX18 = fraction(amBalanceX18, pmtLpAmtX18, lpEmissionX18)
310+ let outPrAmtX18 = fraction(prBalanceX18, pmtLpAmtX18, lpEmissionX18)
311+ let outAmAmt = fromX18Round(outAmAmtX18, amAssetDcm, FLOOR)
312+ let outPrAmt = fromX18Round(outPrAmtX18, prAssetDcm, FLOOR)
313+ let state = if ((txId58 == ""))
314+ then nil
315+ else [ScriptTransfer(userAddress, outAmAmt, if ((amAssetId == "WAVES"))
316+ then unit
317+ else fromBase58String(amAssetId)), ScriptTransfer(userAddress, outPrAmt, if ((prAssetId == "WAVES"))
318+ then unit
319+ 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)]
320+ $Tuple10(outAmAmt, outPrAmt, amAssetId, prAssetId, amBalance, prBalance, lpEmission, curPriceX18, poolStatus, state)
321+ }
322+ }
323+
324+
325+func estimatePutOperation (txId58,slippageTolerance,inAmAssetAmt,inAmAssetId,inPrAssetAmt,inPrAssetId,userAddress,isEvaluate,emitLp) = {
326+ let cfg = getPoolConfig()
327+ let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
328+ let amAssetIdStr = cfg[idxAmtAssetId]
329+ let prAssetIdStr = cfg[idxPriceAssetId]
330+ let iAmtAssetId = cfg[idxIAmtAssetId]
331+ let iPriceAssetId = cfg[idxIPriceAssetId]
332+ let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
333+ let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
334+ let poolStatus = cfg[idxPoolStatus]
335+ let lpEmission = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
336+ let inAmAssetIdStr = toBase58String(valueOrElse(inAmAssetId, fromBase58String("WAVES")))
337+ let inPrAssetIdStr = toBase58String(valueOrElse(inPrAssetId, fromBase58String("WAVES")))
338+ if (if ((amAssetIdStr != inAmAssetIdStr))
339+ then true
340+ else (prAssetIdStr != inPrAssetIdStr))
341+ then throw("Invalid amt or price asset passed.")
342+ else {
343+ let amBalance = if (isEvaluate)
344+ then getAccBalance(amAssetIdStr)
345+ else (getAccBalance(amAssetIdStr) - inAmAssetAmt)
346+ let prBalance = if (isEvaluate)
347+ then getAccBalance(prAssetIdStr)
348+ else (getAccBalance(prAssetIdStr) - inPrAssetAmt)
349+ let inAmAssetAmtX18 = toX18(inAmAssetAmt, amtAssetDcm)
350+ let inPrAssetAmtX18 = toX18(inPrAssetAmt, priceAssetDcm)
351+ let userPriceX18 = calcPriceBigInt(inPrAssetAmtX18, inAmAssetAmtX18)
352+ let amBalanceX18 = toX18(amBalance, amtAssetDcm)
353+ let prBalanceX18 = toX18(prBalance, priceAssetDcm)
354+ let res = if ((lpEmission == 0))
355+ then {
356+ let curPriceX18 = zeroBigInt
357+ let slippageX18 = zeroBigInt
358+ let lpAmtX18 = pow((inAmAssetAmtX18 * inPrAssetAmtX18), 0, toBigInt(5), 1, 0, DOWN)
359+ $Tuple5(fromX18(lpAmtX18, scale8), fromX18(inAmAssetAmtX18, amtAssetDcm), fromX18(inPrAssetAmtX18, priceAssetDcm), calcPriceBigInt((prBalanceX18 + inPrAssetAmtX18), (amBalanceX18 + inAmAssetAmtX18)), slippageX18)
360+ }
361+ else {
362+ let curPriceX18 = calcPriceBigInt(prBalanceX18, amBalanceX18)
363+ let slippageX18 = fraction(absBigInt((curPriceX18 - userPriceX18)), scale18, curPriceX18)
364+ let slippageToleranceX18 = toX18(slippageTolerance, scale8)
365+ if (if ((curPriceX18 != zeroBigInt))
366+ then (slippageX18 > slippageToleranceX18)
367+ else false)
368+ then throw(((("Price slippage " + toString(slippageX18)) + " exceeded the passed limit of ") + toString(slippageToleranceX18)))
369+ else {
370+ let lpEmissionX18 = toX18(lpEmission, scale8)
371+ let prViaAmX18 = fraction(inAmAssetAmtX18, calcPriceBigIntRound(prBalanceX18, amBalanceX18, CEILING), scale18, CEILING)
372+ let amViaPrX18 = fraction(inPrAssetAmtX18, scale18, calcPriceBigIntRound(prBalanceX18, amBalanceX18, FLOOR), CEILING)
373+ let expectedAmts = if ((prViaAmX18 > inPrAssetAmtX18))
374+ then $Tuple2(amViaPrX18, inPrAssetAmtX18)
375+ else $Tuple2(inAmAssetAmtX18, prViaAmX18)
376+ let expAmtAssetAmtX18 = expectedAmts._1
377+ let expPriceAssetAmtX18 = expectedAmts._2
378+ let lpAmtX18 = fraction(lpEmissionX18, expPriceAssetAmtX18, prBalanceX18, FLOOR)
379+ $Tuple5(fromX18Round(lpAmtX18, scale8, FLOOR), fromX18Round(expAmtAssetAmtX18, amtAssetDcm, CEILING), fromX18Round(expPriceAssetAmtX18, priceAssetDcm, CEILING), curPriceX18, slippageX18)
380+ }
381+ }
382+ let calcLpAmt = res._1
383+ let calcAmAssetPmt = res._2
384+ let calcPrAssetPmt = res._3
385+ let curPrice = fromX18(res._4, scale8)
386+ let slippageCalc = fromX18(res._5, scale8)
387+ if ((0 >= calcLpAmt))
388+ then throw("Invalid calculations. LP calculated is less than zero.")
389+ else {
390+ let emitLpAmt = if (!(emitLp))
391+ then 0
392+ else calcLpAmt
393+ let amDiff = (inAmAssetAmt - calcAmAssetPmt)
394+ let prDiff = (inPrAssetAmt - calcPrAssetPmt)
395+ 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))]
396+ $Tuple13(calcLpAmt, emitLpAmt, curPrice, amBalance, prBalance, lpEmission, lpAssetId, poolStatus, commonState, amDiff, prDiff, inAmAssetId, inPrAssetId)
397+ }
398+ }
399+ }
400+
401+
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+
436+func validateMatcherOrderAllowed (order) = {
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
446+ if (if (if (isGlobalShutdown())
447+ then true
448+ else (cfgPoolStatus == PoolMatcherDisabled))
449+ then true
450+ else (cfgPoolStatus == PoolShutdown))
451+ then throw("Exchange operations disabled")
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+ }
465+ }
466+
467+
468+func commonGet (i) = if ((size(i.payments) != 1))
469+ then throw("exactly 1 payment is expected")
470+ else {
471+ let pmt = value(i.payments[0])
472+ let pmtAssetId = value(pmt.assetId)
473+ let pmtAmt = pmt.amount
474+ let res = estimateGetOperation(toBase58String(i.transactionId), toBase58String(pmtAssetId), pmtAmt, i.caller)
475+ let outAmAmt = res._1
476+ let outPrAmt = res._2
477+ let poolStatus = parseIntValue(res._9)
478+ let state = res._10
479+ if (if (isGlobalShutdown())
480+ then true
481+ else (poolStatus == PoolShutdown))
482+ then throw(("Get operation is blocked by admin. Status = " + toString(poolStatus)))
483+ else $Tuple5(outAmAmt, outPrAmt, pmtAmt, pmtAssetId, state)
484+ }
485+
486+
487+func commonPut (i,slippageTolerance,emitLp) = if ((size(i.payments) != 2))
488+ then throw("exactly 2 payments are expected")
489+ else {
490+ let amAssetPmt = value(i.payments[0])
491+ let prAssetPmt = value(i.payments[1])
492+ let estPut = estimatePutOperation(toBase58String(i.transactionId), slippageTolerance, amAssetPmt.amount, amAssetPmt.assetId, prAssetPmt.amount, prAssetPmt.assetId, toString(i.caller), false, emitLp)
493+ let poolStatus = parseIntValue(estPut._8)
494+ if (if (if (isGlobalShutdown())
495+ then true
496+ else (poolStatus == PoolPutDisabled))
497+ then true
498+ else (poolStatus == PoolShutdown))
499+ then throw(("Put operation is blocked by admin. Status = " + toString(poolStatus)))
500+ else estPut
501+ }
502+
503+
504+func emit (amount) = {
505+ let emitInv = invoke(factoryContract, "emit", [amount], nil)
506+ if ((emitInv == emitInv))
507+ then {
508+ let emitInvLegacy = match emitInv {
509+ case legacyFactoryContract: Address =>
510+ invoke(legacyFactoryContract, "emit", [amount], nil)
511+ case _ =>
512+ unit
513+ }
514+ if ((emitInvLegacy == emitInvLegacy))
515+ then amount
516+ else throw("Strict value is not equal to itself.")
517+ }
518+ else throw("Strict value is not equal to itself.")
519+ }
520+
521+
522+func takeFee (amount,fee) = {
523+ let feeAmount = if ((fee == 0))
524+ then 0
525+ else fraction(amount, fee, scale8)
526+ $Tuple2((amount - feeAmount), feeAmount)
527+ }
528+
529+
530+func calcPutOneToken (paymentAmountRaw,paymentAssetId,userAddress,txId) = {
531+ let isEval = (txId == unit)
532+ let amountBalanceRaw = getAccBalance(assetIdToString(cfgAmountAssetId))
533+ let priceBalanceRaw = getAccBalance(assetIdToString(cfgPriceAssetId))
534+ let paymentInAmountAsset = if ((paymentAssetId == cfgAmountAssetId))
535+ then true
536+ else if ((paymentAssetId == cfgPriceAssetId))
537+ then false
538+ else throwErr("invalid asset")
539+ let $t02540625699 = if (isEval)
540+ then $Tuple2(amountBalanceRaw, priceBalanceRaw)
541+ else if (paymentInAmountAsset)
542+ then $Tuple2((amountBalanceRaw - paymentAmountRaw), priceBalanceRaw)
543+ else $Tuple2(amountBalanceRaw, (priceBalanceRaw - paymentAmountRaw))
544+ let amountBalanceOld = $t02540625699._1
545+ let priceBalanceOld = $t02540625699._2
546+ let $t02570325852 = if (paymentInAmountAsset)
547+ then $Tuple2(paymentAmountRaw, 0)
548+ else $Tuple2(0, paymentAmountRaw)
549+ let amountAssetAmountRaw = $t02570325852._1
550+ let priceAssetAmountRaw = $t02570325852._2
551+ let amountAssetAmount = takeFee(amountAssetAmountRaw, inFee)._1
552+ let priceAssetAmount = takeFee(priceAssetAmountRaw, inFee)._1
553+ let $t02598426048 = takeFee(paymentAmountRaw, inFee)
554+ let paymentAmount = $t02598426048._1
555+ let feeAmount = $t02598426048._2
556+ let amountBalanceNew = (amountBalanceOld + amountAssetAmount)
557+ let priceBalanceNew = (priceBalanceOld + priceAssetAmount)
558+ let priceNewX18 = calcPriceBigInt(toX18(priceBalanceNew, cfgPriceAssetDecimals), toX18(amountBalanceNew, cfgAmountAssetDecimals))
559+ let priceNew = fromX18(priceNewX18, scale8)
560+ let paymentBalance = if (paymentInAmountAsset)
561+ then amountBalanceOld
562+ else priceBalanceOld
563+ let paymentBalanceBigInt = toBigInt(paymentBalance)
564+ let supplyBigInt = toBigInt(valueOrErrorMessage(assetInfo(cfgLpAssetId), (("asset " + toBase58String(cfgLpAssetId)) + " doesn't exist")).quantity)
565+ let chechSupply = if ((supplyBigInt > big0))
566+ then true
567+ else throwErr("initial deposit requires all coins")
568+ if ((chechSupply == chechSupply))
569+ then {
570+ let depositBigInt = toBigInt(paymentAmount)
571+ let issueAmount = max([0, toInt(((supplyBigInt * (sqrtBigInt((scale18 + ((depositBigInt * scale18) / paymentBalanceBigInt)), 18, 18, DOWN) - scale18)) / scale18))])
572+ let commonState = if (isEval)
573+ then nil
574+ 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))]
575+ let priceOldX18 = calcPriceBigInt(toX18(priceBalanceOld, cfgPriceAssetDecimals), toX18(amountBalanceOld, cfgAmountAssetDecimals))
576+ let priceOld = fromX18(priceOldX18, scale8)
577+ let loss = {
578+ let $t02772927896 = if (paymentInAmountAsset)
579+ then $Tuple2(amountAssetAmountRaw, amountBalanceOld)
580+ else $Tuple2(priceAssetAmountRaw, priceBalanceOld)
581+ let amount = $t02772927896._1
582+ let balance = $t02772927896._2
583+ let issueAmountBoth = toInt(fraction(supplyBigInt, toBigInt((amount / 2)), toBigInt(balance)))
584+ fraction((issueAmount - issueAmountBoth), scale8, issueAmountBoth)
585+ }
586+ $Tuple5(issueAmount, commonState, feeAmount, loss, paymentInAmountAsset)
587+ }
588+ else throw("Strict value is not equal to itself.")
589+ }
590+
591+
592+func calcGetOneToken (outAssetId,paymentAmount,paymentAssetId,userAddress,txId) = {
593+ let isEval = (txId == unit)
594+ let cfg = getPoolConfig()
595+ let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
596+ let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
597+ let checks = [if ((paymentAssetId == cfgLpAssetId))
598+ then true
599+ else throwErr("invalid lp asset")]
600+ if ((checks == checks))
601+ then {
602+ let outInAmountAsset = if ((outAssetId == cfgAmountAssetId))
603+ then true
604+ else if ((outAssetId == cfgPriceAssetId))
605+ then false
606+ else throwErr("invalid asset")
607+ let balanceBigInt = if (outInAmountAsset)
608+ then toBigInt(getAccBalance(assetIdToString(cfgAmountAssetId)))
609+ else toBigInt(getAccBalance(assetIdToString(cfgPriceAssetId)))
610+ let outInAmountAssetDecimals = if (outInAmountAsset)
611+ then amtAssetDcm
612+ else priceAssetDcm
613+ let amBalanceOld = getAccBalance(assetIdToString(cfgAmountAssetId))
614+ let prBalanceOld = getAccBalance(assetIdToString(cfgPriceAssetId))
615+ let outBalance = if (outInAmountAsset)
616+ then amBalanceOld
617+ else prBalanceOld
618+ let outBalanceBigInt = toBigInt(outBalance)
619+ let supplyBigInt = toBigInt(valueOrErrorMessage(assetInfo(cfgLpAssetId), (("asset " + toBase58String(cfgLpAssetId)) + " doesn't exist")).quantity)
620+ let redeemedBigInt = toBigInt(paymentAmount)
621+ let amountRaw = max([0, toInt(((balanceBigInt * (scale18 - pow((scale18 - ((redeemedBigInt * scale18) / supplyBigInt)), 18, big2, 0, 18, DOWN))) / scale18))])
622+ let $t02997430030 = takeFee(amountRaw, outFee)
623+ let totalAmount = $t02997430030._1
624+ let feeAmount = $t02997430030._2
625+ let $t03003430260 = if (outInAmountAsset)
626+ then $Tuple4(totalAmount, 0, (amBalanceOld - amountRaw), prBalanceOld)
627+ else $Tuple4(0, totalAmount, amBalanceOld, (prBalanceOld - amountRaw))
628+ let outAmAmount = $t03003430260._1
629+ let outPrAmount = $t03003430260._2
630+ let amBalanceNew = $t03003430260._3
631+ let prBalanceNew = $t03003430260._4
632+ let priceNewX18 = calcPriceBigInt(toX18(prBalanceNew, cfgPriceAssetDecimals), toX18(amBalanceNew, cfgAmountAssetDecimals))
633+ let priceNew = fromX18(priceNewX18, scale8)
634+ let commonState = if (isEval)
635+ then nil
636+ 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)]
637+ let priceOldX18 = calcPriceBigInt(toX18(prBalanceOld, cfgPriceAssetDecimals), toX18(amBalanceOld, cfgAmountAssetDecimals))
638+ let priceOld = fromX18(priceOldX18, scale8)
639+ let loss = {
640+ let amountBothInPaymentAsset = (toInt(fraction(balanceBigInt, redeemedBigInt, supplyBigInt)) * 2)
641+ fraction((totalAmount - amountBothInPaymentAsset), scale8, amountBothInPaymentAsset)
642+ }
643+ $Tuple5(totalAmount, commonState, feeAmount, loss, outInAmountAsset)
644+ }
645+ else throw("Strict value is not equal to itself.")
646+ }
647+
648+
649+func managerPublicKeyOrUnit () = match getString(mpk()) {
650+ case s: String =>
651+ fromBase58String(s)
652+ case _: Unit =>
653+ unit
654+ case _ =>
655+ throw("Match error")
656+}
657+
658+
659+func pendingManagerPublicKeyOrUnit () = match getString(pmpk()) {
660+ case s: String =>
661+ fromBase58String(s)
662+ case _: Unit =>
663+ unit
664+ case _ =>
665+ throw("Match error")
666+}
667+
668+
669+func isManager (i) = match managerPublicKeyOrUnit() {
670+ case pk: ByteVector =>
671+ (i.callerPublicKey == pk)
672+ case _: Unit =>
673+ (i.caller == this)
674+ case _ =>
675+ throw("Match error")
676+}
677+
678+
679+func mustManager (i) = {
680+ let pd = throw("Permission denied")
681+ match managerPublicKeyOrUnit() {
682+ case pk: ByteVector =>
683+ if ((i.callerPublicKey == pk))
684+ then true
685+ else pd
686+ case _: Unit =>
687+ if ((i.caller == this))
688+ then true
689+ else pd
690+ case _ =>
691+ throw("Match error")
692+ }
693+ }
694+
695+
696+@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)
771+func setManager (pendingManagerPublicKey) = {
772+ let checkCaller = mustManager(i)
773+ if ((checkCaller == checkCaller))
774+ then {
775+ let checkManagerPublicKey = fromBase58String(pendingManagerPublicKey)
776+ if ((checkManagerPublicKey == checkManagerPublicKey))
777+ then [StringEntry(pmpk(), pendingManagerPublicKey)]
778+ else throw("Strict value is not equal to itself.")
779+ }
780+ else throw("Strict value is not equal to itself.")
781+ }
782+
783+
784+
785+@Callable(i)
786+func confirmManager () = {
787+ let pm = pendingManagerPublicKeyOrUnit()
788+ let hasPM = if (isDefined(pm))
789+ then true
790+ else throw("No pending manager")
791+ if ((hasPM == hasPM))
792+ then {
793+ let checkPM = if ((i.callerPublicKey == value(pm)))
794+ then true
795+ else throw("You are not pending manager")
796+ if ((checkPM == checkPM))
797+ then [StringEntry(mpk(), toBase58String(value(pm))), DeleteEntry(pmpk())]
798+ else throw("Strict value is not equal to itself.")
799+ }
800+ else throw("Strict value is not equal to itself.")
801+ }
802+
803+
804+
805+@Callable(i)
806+func put (slippageTolerance,shouldAutoStake) = if ((0 > slippageTolerance))
807+ then throw("Invalid slippageTolerance passed")
808+ else {
809+ let estPut = commonPut(i, slippageTolerance, true)
810+ let emitLpAmt = estPut._2
811+ let lpAssetId = estPut._7
812+ let state = estPut._9
813+ let amDiff = estPut._10
814+ let prDiff = estPut._11
815+ let amId = estPut._12
816+ let prId = estPut._13
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))
821+ then {
822+ let emitInv = invoke(factoryContract, "emit", [emitLpAmt], nil)
823+ if ((emitInv == emitInv))
824+ then {
825+ let emitInvLegacy = match emitInv {
826+ case legacyFactoryContract: Address =>
827+ invoke(legacyFactoryContract, "emit", [emitLpAmt], nil)
828+ case _ =>
829+ unit
830+ }
831+ if ((emitInvLegacy == emitInvLegacy))
832+ then {
833+ let slippageAInv = if ((amDiff > 0))
834+ then invoke(slippageContract, "put", nil, [AttachedPayment(amId, amDiff)])
835+ else nil
836+ if ((slippageAInv == slippageAInv))
837+ then {
838+ let slippagePInv = if ((prDiff > 0))
839+ then invoke(slippageContract, "put", nil, [AttachedPayment(prId, prDiff)])
840+ else nil
841+ if ((slippagePInv == slippagePInv))
842+ then {
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+ }
861+ else throw("Strict value is not equal to itself.")
862+ }
863+ else throw("Strict value is not equal to itself.")
864+ }
865+ else throw("Strict value is not equal to itself.")
866+ }
867+ else throw("Strict value is not equal to itself.")
868+ }
869+ else throw("Strict value is not equal to itself.")
870+ }
871+ else throw("Strict value is not equal to itself.")
872+ }
873+
874+
875+
876+@Callable(i)
877+func putForFree (maxSlippage) = if ((0 > maxSlippage))
878+ then throw("Invalid value passed")
879+ else {
880+ let estPut = commonPut(i, maxSlippage, false)
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.")
896+ }
897+
898+
899+
900+@Callable(i)
901+func putOneTkn (minOutAmount,autoStake) = {
902+ let isPoolOneTokenOperationsDisabled = {
903+ let @ = invoke(factoryContract, "isPoolOneTokenOperationsDisabledREADONLY", [toString(this)], nil)
904+ if ($isInstanceOf(@, "Boolean"))
905+ then @
906+ else throw(($getType(@) + " couldn't be cast to Boolean"))
907+ }
908+ let isPutDisabled = if (if (if (isGlobalShutdown())
909+ then true
910+ else (cfgPoolStatus == PoolPutDisabled))
911+ then true
912+ else (cfgPoolStatus == PoolShutdown))
913+ then true
914+ else isPoolOneTokenOperationsDisabled
915+ let checks = [if (if (!(isPutDisabled))
916+ then true
917+ else isManager(i))
918+ then true
919+ else throwErr("put operation is blocked by admin"), if ((size(i.payments) == 1))
920+ then true
921+ else throwErr("exactly 1 payment are expected")]
922+ if ((checks == checks))
923+ then {
924+ let payment = i.payments[0]
925+ let paymentAssetId = payment.assetId
926+ let paymentAmountRaw = payment.amount
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))
933+ then {
934+ let userAddress = i.caller
935+ let txId = i.transactionId
936+ let $t03944339595 = calcPutOneToken(paymentAmountRaw, paymentAssetId, userAddress, txId)
937+ if (($t03944339595 == $t03944339595))
938+ then {
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))
951+ then {
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)
977+ else throw("Strict value is not equal to itself.")
978+ }
979+ else throw("Strict value is not equal to itself.")
980+ }
981+ else throw("Strict value is not equal to itself.")
982+ }
983+ else throw("Strict value is not equal to itself.")
984+ }
985+ else throw("Strict value is not equal to itself.")
986+ }
987+
988+
989+
990+@Callable(i)
991+func putOneTknREADONLY (paymentAssetId,paymentAmountRaw) = {
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
998+ $Tuple2(nil, $Tuple3(emitAmountEstimated, feeAmount, bonus))
999+ }
1000+
1001+
1002+
1003+@Callable(i)
1004+func getOneTkn (outAssetIdStr,minOutAmount) = {
1005+ let isPoolOneTokenOperationsDisabled = {
1006+ let @ = invoke(factoryContract, "isPoolOneTokenOperationsDisabledREADONLY", [toString(this)], nil)
1007+ if ($isInstanceOf(@, "Boolean"))
1008+ then @
1009+ else throw(($getType(@) + " couldn't be cast to Boolean"))
1010+ }
1011+ let isGetDisabled = if (if (isGlobalShutdown())
1012+ then true
1013+ else (cfgPoolStatus == PoolShutdown))
1014+ then true
1015+ else isPoolOneTokenOperationsDisabled
1016+ let checks = [if (if (!(isGetDisabled))
1017+ then true
1018+ else isManager(i))
1019+ then true
1020+ else throwErr("get operation is blocked by admin"), if ((size(i.payments) == 1))
1021+ then true
1022+ else throwErr("exactly 1 payment are expected")]
1023+ if ((checks == checks))
1024+ then {
1025+ let outAssetId = parseAssetId(outAssetIdStr)
1026+ let payment = i.payments[0]
1027+ let paymentAssetId = payment.assetId
1028+ let paymentAmount = payment.amount
1029+ let currentKLp = calcCurrentKLp(toBigInt(0), toBigInt(0), toBigInt(0))
1030+ if ((currentKLp == currentKLp))
1031+ then {
1032+ let userAddress = i.caller
1033+ let txId = i.transactionId
1034+ let $t04183741990 = calcGetOneToken(outAssetId, paymentAmount, paymentAssetId, userAddress, txId)
1035+ if (($t04183741990 == $t04183741990))
1036+ then {
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.")
1073+ }
1074+ else throw("Strict value is not equal to itself.")
1075+ }
1076+ else throw("Strict value is not equal to itself.")
1077+ }
1078+ else throw("Strict value is not equal to itself.")
1079+ }
1080+
1081+
1082+
1083+@Callable(i)
1084+func getOneTknREADONLY (outAssetId,paymentAmount) = {
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
1091+ $Tuple2(nil, $Tuple3(amountEstimated, feeAmount, bonus))
1092+ }
1093+
1094+
1095+
1096+@Callable(i)
1097+func unstakeAndGetOneTkn (unstakeAmount,outAssetIdStr,minOutAmount) = {
1098+ let isPoolOneTokenOperationsDisabled = {
1099+ let @ = invoke(factoryContract, "isPoolOneTokenOperationsDisabledREADONLY", [toString(this)], nil)
1100+ if ($isInstanceOf(@, "Boolean"))
1101+ then @
1102+ else throw(($getType(@) + " couldn't be cast to Boolean"))
1103+ }
1104+ let isGetDisabled = if (if (isGlobalShutdown())
1105+ then true
1106+ else (cfgPoolStatus == PoolShutdown))
1107+ then true
1108+ else isPoolOneTokenOperationsDisabled
1109+ let checks = [if (if (!(isGetDisabled))
1110+ then true
1111+ else isManager(i))
1112+ then true
1113+ else throwErr("get operation is blocked by admin"), if ((size(i.payments) == 0))
1114+ then true
1115+ else throwErr("no payments are expected")]
1116+ if ((checks == checks))
1117+ then {
1118+ let outAssetId = parseAssetId(outAssetIdStr)
1119+ let userAddress = i.caller
1120+ let txId = i.transactionId
1121+ let currentKLp = calcCurrentKLp(toBigInt(0), toBigInt(0), toBigInt(0))
1122+ if ((currentKLp == currentKLp))
1123+ then {
1124+ let unstakeInv = invoke(stakingContract, "unstake", [toBase58String(cfgLpAssetId), unstakeAmount], nil)
1125+ if ((unstakeInv == unstakeInv))
1126+ then {
1127+ let $t04416644317 = calcGetOneToken(outAssetId, unstakeAmount, cfgLpAssetId, userAddress, txId)
1128+ if (($t04416644317 == $t04416644317))
1129+ then {
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.")
1166+ }
1167+ else throw("Strict value is not equal to itself.")
1168+ }
1169+ else throw("Strict value is not equal to itself.")
1170+ }
1171+ else throw("Strict value is not equal to itself.")
1172+ }
1173+ else throw("Strict value is not equal to itself.")
1174+ }
1175+
1176+
1177+
1178+@Callable(i)
1179+func get () = {
1180+ let res = commonGet(i)
1181+ let outAmtAmt = res._1
1182+ let outPrAmt = res._2
1183+ let pmtAmt = res._3
1184+ let pmtAssetId = res._4
1185+ let state = res._5
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+ }
1202+ else throw("Strict value is not equal to itself.")
1203+ }
1204+
1205+
1206+
1207+@Callable(i)
1208+func getNoLess (noLessThenAmtAsset,noLessThenPriceAsset) = {
1209+ let res = commonGet(i)
1210+ let outAmAmt = res._1
1211+ let outPrAmt = res._2
1212+ let pmtAmt = res._3
1213+ let pmtAssetId = res._4
1214+ let state = res._5
1215+ if ((noLessThenAmtAsset > outAmAmt))
1216+ then throw(((("noLessThenAmtAsset failed: " + toString(outAmAmt)) + " < ") + toString(noLessThenAmtAsset)))
1217+ else if ((noLessThenPriceAsset > outPrAmt))
1218+ then throw(((("noLessThenPriceAsset failed: " + toString(outPrAmt)) + " < ") + toString(noLessThenPriceAsset)))
1219+ else {
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+ }
1236+ else throw("Strict value is not equal to itself.")
1237+ }
1238+ }
1239+
1240+
1241+
1242+@Callable(i)
1243+func unstakeAndGet (amount) = {
1244+ let checkPayments = if ((size(i.payments) != 0))
1245+ then throw("No payments are expected")
1246+ else true
1247+ if ((checkPayments == checkPayments))
1248+ then {
1249+ let cfg = getPoolConfig()
1250+ let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
1251+ let currentKLp = calcCurrentKLp(toBigInt(0), toBigInt(0), toBigInt(0))
1252+ if ((currentKLp == currentKLp))
1253+ then {
1254+ let unstakeInv = invoke(stakingContract, "unstake", [toBase58String(lpAssetId), amount], nil)
1255+ if ((unstakeInv == unstakeInv))
1256+ then {
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+ }
1282+ else throw("Strict value is not equal to itself.")
1283+ }
1284+ else throw("Strict value is not equal to itself.")
1285+ }
1286+ else throw("Strict value is not equal to itself.")
1287+ }
1288+ else throw("Strict value is not equal to itself.")
1289+ }
1290+
1291+
1292+
1293+@Callable(i)
1294+func unstakeAndGetNoLess (unstakeAmount,noLessThenAmountAsset,noLessThenPriceAsset) = {
1295+ let isGetDisabled = if (isGlobalShutdown())
1296+ then true
1297+ else (cfgPoolStatus == PoolShutdown)
1298+ let checks = [if (!(isGetDisabled))
1299+ then true
1300+ else throw("get operation is blocked by admin"), if ((size(i.payments) == 0))
1301+ then true
1302+ else throw("no payments are expected")]
1303+ if ((checks == checks))
1304+ then {
1305+ let currentKLp = calcCurrentKLp(toBigInt(0), toBigInt(0), toBigInt(0))
1306+ if ((currentKLp == currentKLp))
1307+ then {
1308+ let unstakeInv = invoke(stakingContract, "unstake", [toBase58String(cfgLpAssetId), unstakeAmount], nil)
1309+ if ((unstakeInv == unstakeInv))
1310+ then {
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+ }
1335+ else throw("Strict value is not equal to itself.")
1336+ }
1337+ else throw("Strict value is not equal to itself.")
1338+ }
1339+ else throw("Strict value is not equal to itself.")
1340+ }
1341+ else throw("Strict value is not equal to itself.")
1342+ }
1343+
1344+
1345+
1346+@Callable(i)
1347+func activate (amtAssetStr,priceAssetStr) = if ((toString(i.caller) != toString(factoryContract)))
1348+ then throw("permissions denied")
1349+ 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+ }
1372+
1373+
1374+
1375+@Callable(i)
1376+func getPoolConfigWrapperREADONLY () = $Tuple2(nil, getPoolConfig())
1377+
1378+
1379+
1380+@Callable(i)
1381+func getAccBalanceWrapperREADONLY (assetId) = $Tuple2(nil, getAccBalance(assetId))
1382+
1383+
1384+
1385+@Callable(i)
1386+func calcPricesWrapperREADONLY (amAmt,prAmt,lpAmt) = {
1387+ let prices = calcPrices(amAmt, prAmt, lpAmt)
1388+ $Tuple2(nil, [toString(prices[0]), toString(prices[1]), toString(prices[2])])
1389+ }
1390+
1391+
1392+
1393+@Callable(i)
1394+func toX18WrapperREADONLY (origVal,origScaleMult) = $Tuple2(nil, toString(toX18(origVal, origScaleMult)))
1395+
1396+
1397+
1398+@Callable(i)
1399+func fromX18WrapperREADONLY (val,resultScaleMult) = $Tuple2(nil, fromX18(parseBigIntValue(val), resultScaleMult))
1400+
1401+
1402+
1403+@Callable(i)
1404+func calcPriceBigIntWrapperREADONLY (prAmtX18,amAmtX18) = $Tuple2(nil, toString(calcPriceBigInt(parseBigIntValue(prAmtX18), parseBigIntValue(amAmtX18))))
1405+
1406+
1407+
1408+@Callable(i)
1409+func estimatePutOperationWrapperREADONLY (txId58,slippageTolerance,inAmAssetAmt,inAmAssetId,inPrAssetAmt,inPrAssetId,userAddress,isEvaluate,emitLp) = $Tuple2(nil, estimatePutOperation(txId58, slippageTolerance, inAmAssetAmt, inAmAssetId, inPrAssetAmt, inPrAssetId, userAddress, isEvaluate, emitLp))
1410+
1411+
1412+
1413+@Callable(i)
1414+func estimateGetOperationWrapperREADONLY (txId58,pmtAssetId,pmtLpAmt,userAddress) = {
1415+ let res = estimateGetOperation(txId58, pmtAssetId, pmtLpAmt, addressFromStringValue(userAddress))
1416+ $Tuple2(nil, $Tuple10(res._1, res._2, res._3, res._4, res._5, res._6, res._7, toString(res._8), res._9, res._10))
1417+ }
1418+
1419+
1420+
1421+@Callable(i)
1422+func statsREADONLY () = {
1423+ let cfg = getPoolConfig()
1424+ let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
1425+ let amtAssetId = cfg[idxAmtAssetId]
1426+ let priceAssetId = cfg[idxPriceAssetId]
1427+ let iAmtAssetId = cfg[idxIAmtAssetId]
1428+ let iPriceAssetId = cfg[idxIPriceAssetId]
1429+ let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
1430+ let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
1431+ let poolLPBalance = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
1432+ let accAmtAssetBalance = getAccBalance(amtAssetId)
1433+ let accPriceAssetBalance = getAccBalance(priceAssetId)
1434+ let pricesList = if ((poolLPBalance == 0))
1435+ then [zeroBigInt, zeroBigInt, zeroBigInt]
1436+ else calcPrices(accAmtAssetBalance, accPriceAssetBalance, poolLPBalance)
1437+ let curPrice = 0
1438+ let lpAmtAssetShare = fromX18(pricesList[1], scale8)
1439+ let lpPriceAssetShare = fromX18(pricesList[2], scale8)
1440+ let poolWeight = value(getInteger(factoryContract, keyPoolWeight(toString(this))))
1441+ $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))
1442+ }
1443+
1444+
1445+
1446+@Callable(i)
1447+func evaluatePutByAmountAssetREADONLY (inAmAssetAmt) = {
1448+ let cfg = getPoolConfig()
1449+ let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
1450+ let amAssetIdStr = cfg[idxAmtAssetId]
1451+ let amAssetId = fromBase58String(amAssetIdStr)
1452+ let prAssetIdStr = cfg[idxPriceAssetId]
1453+ let prAssetId = fromBase58String(prAssetIdStr)
1454+ let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
1455+ let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
1456+ let poolStatus = cfg[idxPoolStatus]
1457+ let poolLPBalance = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
1458+ let accAmtAssetBalance = getAccBalance(amAssetIdStr)
1459+ let accPriceAssetBalance = getAccBalance(prAssetIdStr)
1460+ let amtAssetAmtX18 = toX18(accAmtAssetBalance, amtAssetDcm)
1461+ let priceAssetAmtX18 = toX18(accPriceAssetBalance, priceAssetDcm)
1462+ let curPriceX18 = if ((poolLPBalance == 0))
1463+ then zeroBigInt
1464+ else calcPriceBigInt(priceAssetAmtX18, amtAssetAmtX18)
1465+ let inAmAssetAmtX18 = toX18(inAmAssetAmt, amtAssetDcm)
1466+ let inPrAssetAmtX18 = fraction(inAmAssetAmtX18, curPriceX18, scale18)
1467+ let inPrAssetAmt = fromX18(inPrAssetAmtX18, priceAssetDcm)
1468+ let estPut = estimatePutOperation("", 500000, inAmAssetAmt, amAssetId, inPrAssetAmt, prAssetId, "", true, false)
1469+ let calcLpAmt = estPut._1
1470+ let curPriceCalc = estPut._3
1471+ let amBalance = estPut._4
1472+ let prBalance = estPut._5
1473+ let lpEmission = estPut._6
1474+ $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))
1475+ }
1476+
1477+
1478+
1479+@Callable(i)
1480+func evaluatePutByPriceAssetREADONLY (inPrAssetAmt) = {
1481+ let cfg = getPoolConfig()
1482+ let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
1483+ let amAssetIdStr = cfg[idxAmtAssetId]
1484+ let amAssetId = fromBase58String(amAssetIdStr)
1485+ let prAssetIdStr = cfg[idxPriceAssetId]
1486+ let prAssetId = fromBase58String(prAssetIdStr)
1487+ let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
1488+ let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
1489+ let poolStatus = cfg[idxPoolStatus]
1490+ let poolLPBalance = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
1491+ let amBalanceRaw = getAccBalance(amAssetIdStr)
1492+ let prBalanceRaw = getAccBalance(prAssetIdStr)
1493+ let amBalanceRawX18 = toX18(amBalanceRaw, amtAssetDcm)
1494+ let prBalanceRawX18 = toX18(prBalanceRaw, priceAssetDcm)
1495+ let curPriceX18 = if ((poolLPBalance == 0))
1496+ then zeroBigInt
1497+ else calcPriceBigInt(prBalanceRawX18, amBalanceRawX18)
1498+ let inPrAssetAmtX18 = toX18(inPrAssetAmt, priceAssetDcm)
1499+ let inAmAssetAmtX18 = fraction(inPrAssetAmtX18, scale18, curPriceX18)
1500+ let inAmAssetAmt = fromX18(inAmAssetAmtX18, amtAssetDcm)
1501+ let estPut = estimatePutOperation("", 500000, inAmAssetAmt, amAssetId, inPrAssetAmt, prAssetId, "", true, false)
1502+ let calcLpAmt = estPut._1
1503+ let curPriceCalc = estPut._3
1504+ let amBalance = estPut._4
1505+ let prBalance = estPut._5
1506+ let lpEmission = estPut._6
1507+ $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))
1508+ }
1509+
1510+
1511+
1512+@Callable(i)
1513+func evaluateGetREADONLY (paymentLpAssetId,paymentLpAmt) = {
1514+ let res = estimateGetOperation("", paymentLpAssetId, paymentLpAmt, this)
1515+ let outAmAmt = res._1
1516+ let outPrAmt = res._2
1517+ let amBalance = res._5
1518+ let prBalance = res._6
1519+ let lpEmission = res._7
1520+ let curPrice = res._8
1521+ let poolStatus = parseIntValue(res._9)
1522+ $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))
1523+ }
1524+
1525+
1526+@Verifier(tx)
1527+func verify () = {
1528+ let targetPublicKey = match managerPublicKeyOrUnit() {
1529+ case pk: ByteVector =>
1530+ pk
1531+ case _: Unit =>
1532+ tx.senderPublicKey
1533+ case _ =>
1534+ throw("Match error")
1535+ }
1536+ match tx {
1537+ case order: Order =>
1538+ let matcherPub = getMatcherPubOrFail()
1539+ let $t05972459793 = validateMatcherOrderAllowed(order)
1540+ let orderValid = $t05972459793._1
1541+ let orderValidInfo = $t05972459793._2
1542+ let senderValid = sigVerify(order.bodyBytes, order.proofs[0], order.senderPublicKey)
1543+ let matcherValid = sigVerify(order.bodyBytes, order.proofs[1], matcherPub)
1544+ if (if (if (orderValid)
1545+ then senderValid
1546+ else false)
1547+ then matcherValid
1548+ else false)
1549+ then true
1550+ else throwOrderError(orderValid, orderValidInfo, senderValid, matcherValid)
1551+ case s: SetScriptTransaction =>
1552+ if (sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey))
1553+ then true
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+ }
1562+ case _ =>
1563+ sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey)
1564+ }
1565+ }
1566+

github/deemru/w8io/6500d08 
97.13 ms