tx · 4miPxsuaLsmyZAHScyYLGijQPP5DM2dmkU5rZnRTz2b5

3PHVATdeZezu7hbhi978kGv476jqhvzgJpv:  -0.04300000 Waves

2024.01.14 23:31 [3997462] smart account 3PHVATdeZezu7hbhi978kGv476jqhvzgJpv > SELF 0.00000000 Waves

{ "type": 13, "id": "4miPxsuaLsmyZAHScyYLGijQPP5DM2dmkU5rZnRTz2b5", "fee": 4300000, "feeAssetId": null, "timestamp": 1705264371011, "version": 2, "chainId": 87, "sender": "3PHVATdeZezu7hbhi978kGv476jqhvzgJpv", "senderPublicKey": "DmhQFUw8zZuRaAERuZQvbbmUrEaTkhVrHL1NGafsSzH5", "proofs": [ "3LHJuHPAGPCP4J1WqMtZ4dvwtWXemrNsF2f4shYfgWta3EwTspfbCH3UiMQ3eF8gpj54sPBc7Cu3crxDVrHBbAzo" ], "script": "base64:BgLjOAgCEgASBQoDAQQBEgcKBQEEAQgBEgQKAgEEEgMKAQESBAoCAQQSBAoCCAESBAoCCAESBAoCCAESBQoDAQgBEgASBAoCAQESAwoBARIFCgMBAQESBAoCCAgSABIAEgMKAQgSBQoDAQEBEgQKAgEBEgQKAggBEgQKAggIEgsKCQgBAQIBAggEBBIGCgQICAEIEgASAwoBARIDCgEBEgQKAggBIgpsUGRlY2ltYWxzIgZzY2FsZTgiDHNjYWxlOEJpZ0ludCIHc2NhbGUxOCIKemVyb0JpZ0ludCIEYmlnMCIEYmlnMSIEYmlnMiILd2F2ZXNTdHJpbmciA1NFUCIKUG9vbEFjdGl2ZSIPUG9vbFB1dERpc2FibGVkIhNQb29sTWF0Y2hlckRpc2FibGVkIgxQb29sU2h1dGRvd24iDmlkeFBvb2xBZGRyZXNzIg1pZHhQb29sU3RhdHVzIhBpZHhQb29sTFBBc3NldElkIg1pZHhBbXRBc3NldElkIg9pZHhQcmljZUFzc2V0SWQiDmlkeEFtdEFzc2V0RGNtIhBpZHhQcmljZUFzc2V0RGNtIg5pZHhJQW10QXNzZXRJZCIQaWR4SVByaWNlQXNzZXRJZCINaWR4TFBBc3NldERjbSISaWR4UG9vbEFtdEFzc2V0QW10IhRpZHhQb29sUHJpY2VBc3NldEFtdCIRaWR4UG9vbExQQXNzZXRBbXQiGWlkeEZhY3RvcnlTdGFraW5nQ29udHJhY3QiGmlkeEZhY3RvcnlTbGlwcGFnZUNvbnRyYWN0IgV0b1gxOCIHb3JpZ1ZhbCINb3JpZ1NjYWxlTXVsdCILdG9YMThCaWdJbnQiB2Zyb21YMTgiA3ZhbCIPcmVzdWx0U2NhbGVNdWx0Igxmcm9tWDE4Um91bmQiBXJvdW5kIgd0b1NjYWxlIgNhbXQiCHJlc1NjYWxlIghjdXJTY2FsZSIDYWJzIglhYnNCaWdJbnQiDHN3YXBDb250cmFjdCICZmMiE2tleU1hbmFnZXJQdWJsaWNLZXkiFmtleU1hbmFnZXJWYXVsdEFkZHJlc3MiAnBsIgJwaCIBaCIJdGltZXN0YW1wIgNwYXUiC3VzZXJBZGRyZXNzIgR0eElkIgNnYXUiAmFhIgJwYSIGa2V5RmVlIgpmZWVEZWZhdWx0IgNmZWUiBmtleUtMcCIVa2V5S0xwUmVmcmVzaGVkSGVpZ2h0IhJrZXlLTHBSZWZyZXNoRGVsYXkiFmtMcFJlZnJlc2hEZWxheURlZmF1bHQiD2tMcFJlZnJlc2hEZWxheSIUa2V5QWRkaXRpb25hbEJhbGFuY2UiB2Fzc2V0SWQiFmtleVN0YWtpbmdBc3NldEJhbGFuY2UiGmdldEFkZGl0aW9uYWxCYWxhbmNlT3JaZXJvIhxnZXRTdGFraW5nQXNzZXRCYWxhbmNlT3JaZXJvIhBrZXlGYWN0b3J5Q29uZmlnIg1rZXlNYXRjaGVyUHViIilrZXlNYXBwaW5nUG9vbENvbnRyYWN0QWRkcmVzc1RvUG9vbEFzc2V0cyITcG9vbENvbnRyYWN0QWRkcmVzcyINa2V5UG9vbENvbmZpZyIJaUFtdEFzc2V0IgtpUHJpY2VBc3NldCIfa2V5TWFwcGluZ3NCYXNlQXNzZXQyaW50ZXJuYWxJZCIMYmFzZUFzc2V0U3RyIhNrZXlBbGxQb29sc1NodXRkb3duIg1rZXlQb29sV2VpZ2h0Ig9jb250cmFjdEFkZHJlc3MiFmtleUFsbG93ZWRMcFNjcmlwdEhhc2giFmtleUZlZUNvbGxlY3RvckFkZHJlc3MiFmtleVNraXBPcmRlclZhbGlkYXRpb24iC3Bvb2xBZGRyZXNzIg90aHJvd09yZGVyRXJyb3IiCm9yZGVyVmFsaWQiDm9yZGVyVmFsaWRJbmZvIgtzZW5kZXJWYWxpZCIMbWF0Y2hlclZhbGlkIhdhZGRyZXNzRnJvbVN0cmluZ09yVGhpcyINYWRkcmVzc1N0cmluZyIHJG1hdGNoMCIBYSIcZ2V0TWFuYWdlclZhdWx0QWRkcmVzc09yVGhpcyIOZmFjdG9yeUFkZHJlc3MiA2ZjYSIBcyIPZ2V0U3RyaW5nT3JGYWlsIgdhZGRyZXNzIgNrZXkiDGdldEludE9yRmFpbCIIdGhyb3dFcnIiA21zZyIGZm10RXJyIg9mYWN0b3J5Q29udHJhY3QiE2ZlZUNvbGxlY3RvckFkZHJlc3MiBWluRmVlIgFAIgZvdXRGZWUiFWtleUFkZHJlc3NXaGl0ZWxpc3RlZCIUaXNBZGRyZXNzV2hpdGVsaXN0ZWQiEGlzR2xvYmFsU2h1dGRvd24iE2dldE1hdGNoZXJQdWJPckZhaWwiDWdldFBvb2xDb25maWciCGFtdEFzc2V0IgpwcmljZUFzc2V0IgxwYXJzZUFzc2V0SWQiBWlucHV0Ig9hc3NldElkVG9TdHJpbmciD3BhcnNlUG9vbENvbmZpZyIKcG9vbENvbmZpZyIQcG9vbENvbmZpZ1BhcnNlZCILJHQwOTc2OTk5MzUiDmNmZ1Bvb2xBZGRyZXNzIg1jZmdQb29sU3RhdHVzIgxjZmdMcEFzc2V0SWQiEGNmZ0Ftb3VudEFzc2V0SWQiD2NmZ1ByaWNlQXNzZXRJZCIWY2ZnQW1vdW50QXNzZXREZWNpbWFscyIVY2ZnUHJpY2VBc3NldERlY2ltYWxzIhBnZXRGYWN0b3J5Q29uZmlnIg9zdGFraW5nQ29udHJhY3QiEHNsaXBwYWdlQ29udHJhY3QiEWRhdGFQdXRBY3Rpb25JbmZvIg1pbkFtdEFzc2V0QW10Ig9pblByaWNlQXNzZXRBbXQiCG91dExwQW10IgVwcmljZSIdc2xpcHBhZ2VUb2xlcmFuY2VQYXNzZWRCeVVzZXIiFXNsaXBwYWdlVG9sZXJhbmNlUmVhbCIIdHhIZWlnaHQiC3R4VGltZXN0YW1wIhJzbGlwYWdlQW10QXNzZXRBbXQiFHNsaXBhZ2VQcmljZUFzc2V0QW10IhFkYXRhR2V0QWN0aW9uSW5mbyIOb3V0QW10QXNzZXRBbXQiEG91dFByaWNlQXNzZXRBbXQiB2luTHBBbXQiDWdldEFjY0JhbGFuY2UiDWJhbGFuY2VPblBvb2wiDHRvdGFsQmFsYW5jZSIPY2FsY1ByaWNlQmlnSW50IghwckFtdFgxOCIIYW1BbXRYMTgiFGNhbGNQcmljZUJpZ0ludFJvdW5kIgdnZXRSYXRlIgVwcm94eSIDaW52IgFyIgdkZXBvc2l0IgZhbW91bnQiDnN0YWtpbmdBc3NldElkIhhjdXJyZW50QWRkaXRpb25hbEJhbGFuY2UiGmN1cnJlbnRTdGFraW5nQXNzZXRCYWxhbmNlIgVhc3NldCINZGVwb3NpdEludm9rZSIUcmVjZWl2ZWRTdGFraW5nQXNzZXQiFG5ld0FkZGl0aW9uYWxCYWxhbmNlIhZuZXdTdGFraW5nQXNzZXRCYWxhbmNlIgh3aXRoZHJhdyIMcHJveHlSYXRlTXVsIg1wcm9maXRBZGRyZXNzIhBjdXJyZW50UHJveHlSYXRlIgdvbGRSYXRlIgxzdGFraW5nQXNzZXQiFG9sZFNlbmRTdGFraW5nQW1vdW50IhZzZW5kU3Rha2luZ0Fzc2V0QW1vdW50Igxwcm9maXRBbW91bnQiDndpdGhkcmF3SW52b2tlIg5yZWNlaXZlZEFzc2V0cyITZ2V0TGVhc2VQcm94eUNvbmZpZyIRcmViYWxhbmNlSW50ZXJuYWwiC3RhcmdldFJhdGlvIgptaW5CYWxhbmNlIhRsZWFzYWJsZVRvdGFsQmFsYW5jZSIXdGFyZ2V0QWRkaXRpb25hbEJhbGFuY2UiBGRpZmYiD3NlbmRBc3NldEFtb3VudCIOZ2V0QXNzZXRBbW91bnQiDnJlYmFsYW5jZUFzc2V0Ig0kdDAxNjE3MTE2MzA3Igppc0xlYXNhYmxlIgtsZWFzZWRSYXRpbyIMcHJveHlBZGRyZXNzIgxwcm94eUFzc2V0SWQiFHN0YWtpbmdQcm9maXRBZGRyZXNzIhl3aXRoZHJhd0FuZFJlYmFsYW5jZUFzc2V0IglnZXRBbW91bnQiDSR0MDE2NzA2MTY4NDIiF25ld1RvdGFsTGVhc2FibGVCYWxhbmNlIg53aXRoZHJhd0Ftb3VudCIXd2l0aGRyYXdBbmRSZWJhbGFuY2VBbGwiFGFtb3VudEFzc2V0T3V0QW1vdW50IhNwcmljZUFzc2V0T3V0QW1vdW50IhJBbUFtdFdpdGhkcmF3U3RhdGUiElByQW10V2l0aGRyYXdTdGF0ZSIQcHJpdmF0ZUNhbGNQcmljZSIKYW1Bc3NldERjbSIKcHJBc3NldERjbSIFYW1BbXQiBXByQW10Ig5hbXRBc3NldEFtdFgxOCIQcHJpY2VBc3NldEFtdFgxOCIKY2FsY1ByaWNlcyIFbHBBbXQiA2NmZyILYW10QXNzZXREY20iDXByaWNlQXNzZXREY20iCHByaWNlWDE4IghscEFtdFgxOCITbHBQcmljZUluQW1Bc3NldFgxOCITbHBQcmljZUluUHJBc3NldFgxOCIPY2FsY3VsYXRlUHJpY2VzIgZwcmljZXMiFGVzdGltYXRlR2V0T3BlcmF0aW9uIgZ0eElkNTgiCnBtdEFzc2V0SWQiCHBtdExwQW10IglscEFzc2V0SWQiCWFtQXNzZXRJZCIJcHJBc3NldElkIgpwb29sU3RhdHVzIgpscEVtaXNzaW9uIglhbUJhbGFuY2UiDGFtQmFsYW5jZVgxOCIJcHJCYWxhbmNlIgxwckJhbGFuY2VYMTgiC2N1clByaWNlWDE4IghjdXJQcmljZSILcG10THBBbXRYMTgiDWxwRW1pc3Npb25YMTgiC291dEFtQW10WDE4IgtvdXRQckFtdFgxOCIIb3V0QW1BbXQiCG91dFByQW10IgVzdGF0ZSIUZXN0aW1hdGVQdXRPcGVyYXRpb24iEXNsaXBwYWdlVG9sZXJhbmNlIgxpbkFtQXNzZXRBbXQiC2luQW1Bc3NldElkIgxpblByQXNzZXRBbXQiC2luUHJBc3NldElkIgppc0V2YWx1YXRlIgZlbWl0THAiDGFtQXNzZXRJZFN0ciIMcHJBc3NldElkU3RyIgtpQW10QXNzZXRJZCINaVByaWNlQXNzZXRJZCIOaW5BbUFzc2V0SWRTdHIiDmluUHJBc3NldElkU3RyIg9pbkFtQXNzZXRBbXRYMTgiD2luUHJBc3NldEFtdFgxOCIMdXNlclByaWNlWDE4IgNyZXMiC3NsaXBwYWdlWDE4IhRzbGlwcGFnZVRvbGVyYW5jZVgxOCIKcHJWaWFBbVgxOCIKYW1WaWFQclgxOCIMZXhwZWN0ZWRBbXRzIhFleHBBbXRBc3NldEFtdFgxOCITZXhwUHJpY2VBc3NldEFtdFgxOCIJY2FsY0xwQW10Ig5jYWxjQW1Bc3NldFBtdCIOY2FsY1ByQXNzZXRQbXQiDHNsaXBwYWdlQ2FsYyIJZW1pdExwQW10IgZhbURpZmYiBnByRGlmZiILY29tbW9uU3RhdGUiB2NhbGNLTHAiDWFtb3VudEJhbGFuY2UiDHByaWNlQmFsYW5jZSIQYW1vdW50QmFsYW5jZVgxOCIPcHJpY2VCYWxhbmNlWDE4Igp1cGRhdGVkS0xwIg5jYWxjQ3VycmVudEtMcCIQYW1vdW50QXNzZXREZWx0YSIPcHJpY2VBc3NldERlbHRhIhRscEFzc2V0RW1pc3Npb25EZWx0YSISYW1vdW50QXNzZXRCYWxhbmNlIhFwcmljZUFzc2V0QmFsYW5jZSIPbHBBc3NldEVtaXNzaW9uIgpjdXJyZW50S0xwIhJyZWZyZXNoS0xwSW50ZXJuYWwiF2Ftb3VudEFzc2V0QmFsYW5jZURlbHRhIhZwcmljZUFzc2V0QmFsYW5jZURlbHRhIgdhY3Rpb25zIhNza2lwT3JkZXJWYWxpZGF0aW9uIhJ2YWxpZGF0ZVVwZGF0ZWRLTHAiBm9sZEtMcCIbdmFsaWRhdGVNYXRjaGVyT3JkZXJBbGxvd2VkIgVvcmRlciIRYW1vdW50QXNzZXRBbW91bnQiEHByaWNlQXNzZXRBbW91bnQiDSR0MDI5MjMxMjk0NDMiA2tMcCINJHQwMjk4ODMyOTk4MyINdW51c2VkQWN0aW9ucyIGa0xwTmV3Igxpc09yZGVyVmFsaWQiBGluZm8iCWNvbW1vbkdldCIBaSIDcG10IgZwbXRBbXQiDWlzR2V0RGlzYWJsZWQiCWNvbW1vblB1dCIKYW1Bc3NldFBtdCIKcHJBc3NldFBtdCIGZXN0UHV0Ig1pc1B1dERpc2FibGVkIgRlbWl0IgdlbWl0SW52Ig1lbWl0SW52TGVnYWN5IhVsZWdhY3lGYWN0b3J5Q29udHJhY3QiB3Rha2VGZWUiCWZlZUFtb3VudCIPY2FsY1B1dE9uZVRva2VuIhBwYXltZW50QW1vdW50UmF3Ig5wYXltZW50QXNzZXRJZCIGaXNFdmFsIhBhbW91bnRCYWxhbmNlUmF3Ig9wcmljZUJhbGFuY2VSYXciFHBheW1lbnRJbkFtb3VudEFzc2V0Ig0kdDAzMzE2OTMzNDYyIhBhbW91bnRCYWxhbmNlT2xkIg9wcmljZUJhbGFuY2VPbGQiDSR0MDMzNDY2MzM2MTUiFGFtb3VudEFzc2V0QW1vdW50UmF3IhNwcmljZUFzc2V0QW1vdW50UmF3Ig0kdDAzMzc0NzMzODExIg1wYXltZW50QW1vdW50IhBhbW91bnRCYWxhbmNlTmV3Ig9wcmljZUJhbGFuY2VOZXciC3ByaWNlTmV3WDE4IghwcmljZU5ldyIOcGF5bWVudEJhbGFuY2UiFHBheW1lbnRCYWxhbmNlQmlnSW50IgxzdXBwbHlCaWdJbnQiC2NoZWNoU3VwcGx5Ig1kZXBvc2l0QmlnSW50Igtpc3N1ZUFtb3VudCILcHJpY2VPbGRYMTgiCHByaWNlT2xkIgRsb3NzIg0kdDAzNTQ5MjM1NjU5IgdiYWxhbmNlIg9pc3N1ZUFtb3VudEJvdGgiD2NhbGNHZXRPbmVUb2tlbiIKb3V0QXNzZXRJZCIGY2hlY2tzIhBvdXRJbkFtb3VudEFzc2V0Ig1iYWxhbmNlQmlnSW50IhhvdXRJbkFtb3VudEFzc2V0RGVjaW1hbHMiDGFtQmFsYW5jZU9sZCIMcHJCYWxhbmNlT2xkIgpvdXRCYWxhbmNlIhBvdXRCYWxhbmNlQmlnSW50Ig5yZWRlZW1lZEJpZ0ludCIJYW1vdW50UmF3Ig0kdDAzNzczNzM3NzkzIgt0b3RhbEFtb3VudCINJHQwMzc3OTczODAyMyILb3V0QW1BbW91bnQiC291dFByQW1vdW50IgxhbUJhbGFuY2VOZXciDHByQmFsYW5jZU5ldyIYYW1vdW50Qm90aEluUGF5bWVudEFzc2V0IhZtYW5hZ2VyUHVibGljS2V5T3JVbml0IhNtYW5hZ2VyVmF1bHRBZGRyZXNzIglpc01hbmFnZXIiAnBrIgttdXN0TWFuYWdlciICcGQiDWNsZWFuQW1vdW50SW4iCWlzUmV2ZXJzZSINZmVlUG9vbEFtb3VudCINJHQwMzk4ODE0MDE4NiIIYXNzZXRPdXQiB2Fzc2V0SW4iEnBvb2xBc3NldEluQmFsYW5jZSITcG9vbEFzc2V0T3V0QmFsYW5jZSIJYW1vdW50T3V0IgRvbGRLIgRuZXdLIgZjaGVja0siDGFtb3VudE91dE1pbiIJYWRkcmVzc1RvIgtzd2FwQ29udGFjdCISaXNQb29sU3dhcERpc2FibGVkIg5pc1N3YXBEaXNhYmxlZCIIY2hlY2tNaW4iEXJlZnJlc2hLTHBBY3Rpb25zIg5yZWJhbGFuY2VTdGF0ZSINd2l0aGRyYXdTdGF0ZSIPc2hvdWxkQXV0b1N0YWtlIgRhbUlkIgRwcklkIgxzbGlwcGFnZUFJbnYiDHNsaXBwYWdlUEludiIKbHBUcmFuc2ZlciILc2xwU3Rha2VJbnYiDSR0MDQ1MzYyNDU4MjQiEWlzVXBkYXRlZEtMcFZhbGlkIgNyZWIiC21heFNsaXBwYWdlIg0kdDA0NjQzNjQ2NTAxIgxtaW5PdXRBbW91bnQiCWF1dG9TdGFrZSIgaXNQb29sT25lVG9rZW5PcGVyYXRpb25zRGlzYWJsZWQiB3BheW1lbnQiDSR0MDQ3NzMwNDc4ODIiBWJvbnVzIhNlbWl0QW1vdW50RXN0aW1hdGVkIgplbWl0QW1vdW50IghzdGFrZUludiIHc2VuZEZlZSINJHQwNDg0Njg0ODY2NSINJHQwNDg2Njg0ODc3NiINJHQwNDkxMzE0OTI4OCINb3V0QXNzZXRJZFN0ciINJHQwNTAyMTA1MDM2MyIPYW1vdW50RXN0aW1hdGVkIgdidXJuSW52Ig1hc3NldFRyYW5zZmVyIg0kdDA1MTAyNzUxMjc0IhBmZWVBbW91bnRGb3JDYWxjIg0kdDA1MTI3NzUxMzg1Ig0kdDA1MTY2MzUxODE5Ig11bnN0YWtlQW1vdW50Igp1bnN0YWtlSW52Ig0kdDA1Mjc2MTUyOTEyIg0kdDA1MzU3MTUzODE4Ig0kdDA1MzgyMTUzOTI5IhRidXJuTFBBc3NldE9uRmFjdG9yeSINJHQwNTUwMjQ1NTEwNSISbm9MZXNzVGhlbkFtdEFzc2V0IhRub0xlc3NUaGVuUHJpY2VBc3NldCINJHQwNTYyMDA1NjI4MSINY2hlY2tQYXltZW50cyIPY2hlY2tQb29sU3RhdHVzIg0kdDA1NzYyOTU3NzEwIhVub0xlc3NUaGVuQW1vdW50QXNzZXQiDGNoZWNrQW1vdW50cyINJHQwNTkxODg1OTI2OSILYW10QXNzZXRTdHIiDXByaWNlQXNzZXRTdHIiGGxhc3RSZWZyZXNoZWRCbG9ja0hlaWdodCIdY2hlY2tMYXN0UmVmcmVzaGVkQmxvY2tIZWlnaHQiDSR0MDYwNDczNjA1MzciEGtMcFVwZGF0ZUFjdGlvbnMiCmFtdEFzc2V0SWQiDHByaWNlQXNzZXRJZCINcG9vbExQQmFsYW5jZSISYWNjQW10QXNzZXRCYWxhbmNlIhRhY2NQcmljZUFzc2V0QmFsYW5jZSIKcHJpY2VzTGlzdCIPbHBBbXRBc3NldFNoYXJlIhFscFByaWNlQXNzZXRTaGFyZSIKcG9vbFdlaWdodCIMY3VyUHJpY2VDYWxjIgxhbUJhbGFuY2VSYXciDHByQmFsYW5jZVJhdyIPYW1CYWxhbmNlUmF3WDE4Ig9wckJhbGFuY2VSYXdYMTgiEHBheW1lbnRMcEFzc2V0SWQiDHBheW1lbnRMcEFtdCICdHgiBnZlcmlmeSIPdGFyZ2V0UHVibGljS2V5IgptYXRjaGVyUHViIg0kdDA2OTE5OTY5MzE2IgduZXdIYXNoIgthbGxvd2VkSGFzaCILY3VycmVudEhhc2iEAQABYQAIAAFiAIDC1y8AAWMJALYCAQCAwtcvAAFkCQC2AgEAgICQu7rWrfANAAFlCQC2AgEAAAABZgkAtgIBAAAAAWcJALYCAQABAAFoCQC2AgEAAgABaQIFV0FWRVMAAWoCAl9fAAFrAAEAAWwAAgABbQADAAFuAAQAAW8AAQABcAACAAFxAAMAAXIABAABcwAFAAF0AAYAAXUABwABdgAIAAF3AAkAAXgACgABeQABAAF6AAIAAUEAAwABQgABAAFDAAcBAUQCAUUBRgkAvAIDCQC2AgEFAUUFAWQJALYCAQUBRgEBRwIBRQFGCQC8AgMFAUUFAWQFAUYBAUgCAUkBSgkAoAMBCQC8AgMFAUkJALYCAQUBSgUBZAEBSwMBSQFKAUwJAKADAQkAvQIEBQFJCQC2AgEFAUoFAWQFAUwBAU0DAU4BTwFQCQBrAwUBTgUBTwUBUAEBUQEBSQMJAGYCAAAFAUkJAQEtAQUBSQUBSQEBUgEBSQMJAL8CAgUBZQUBSQkAvgIBBQFJBQFJAQFTAAIQJXNfX3N3YXBDb250cmFjdAEBVAACEyVzX19mYWN0b3J5Q29udHJhY3QBAVUAAhQlc19fbWFuYWdlclB1YmxpY0tleQEBVgACFyVzX19tYW5hZ2VyVmF1bHRBZGRyZXNzAQFXAAIRJXMlc19fcHJpY2VfX2xhc3QBAVgCAVkBWgkAuQkCCQDMCAICGCVzJXMlZCVkX19wcmljZV9faGlzdG9yeQkAzAgCCQCkAwEFAVkJAMwIAgkApAMBBQFaBQNuaWwFAWoBAmFhAgJhYgJhYwkArAICCQCsAgIJAKwCAgILJXMlcyVzX19QX18FAmFiAgJfXwUCYWMBAmFkAgJhYgJhYwkArAICCQCsAgIJAKwCAgILJXMlcyVzX19HX18FAmFiAgJfXwUCYWMBAmFlAAIPJXNfX2Ftb3VudEFzc2V0AQJhZgACDiVzX19wcmljZUFzc2V0AAJhZwIHJXNfX2ZlZQACYWgJAGsDAAoFAWIAkE4AAmFpCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFAmFnBQJhaAACYWoJALkJAgkAzAgCAgIlcwkAzAgCAgNrTHAFA25pbAUBagACYWsJALkJAgkAzAgCAgIlcwkAzAgCAhJrTHBSZWZyZXNoZWRIZWlnaHQFA25pbAUBagACYWwJALkJAgkAzAgCAgIlcwkAzAgCAg9yZWZyZXNoS0xwRGVsYXkFA25pbAUBagACYW0AHgACYW4JAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUCYWwFAmFtAQJhbwECYXAJALkJAgkAzAgCAgQlcyVzCQDMCAICDXN0YWtlZEJhbGFuY2UJAMwIAgUCYXAFA25pbAUBagECYXEBAmFwCQC5CQIJAMwIAgIEJXMlcwkAzAgCAhFzaGFyZUFzc2V0QmFsYW5jZQkAzAgCBQJhcAUDbmlsBQFqAQJhcgECYXAJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBAmFvAQUCYXAAAAECYXMBAmFwCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQJhcQEFAmFwAAABAmF0AAIRJXNfX2ZhY3RvcnlDb25maWcBAmF1AAIYJXMlc19fbWF0Y2hlcl9fcHVibGljS2V5AQJhdgECYXcJAKwCAgkArAICAgglcyVzJXNfXwUCYXcCIF9fbWFwcGluZ3NfX3Bvb2xDb250cmFjdDJMcEFzc2V0AQJheAICYXkCYXoJAKwCAgkArAICCQCsAgIJAKwCAgIIJWQlZCVzX18FAmF5AgJfXwUCYXoCCF9fY29uZmlnAQJhQQECYUIJAKwCAgIoJXMlcyVzX19tYXBwaW5nc19fYmFzZUFzc2V0MmludGVybmFsSWRfXwUCYUIBAmFDAAIMJXNfX3NodXRkb3duAQJhRAECYUUJAKwCAgISJXMlc19fcG9vbFdlaWdodF9fBQJhRQECYUYAAhclc19fYWxsb3dlZExwU2NyaXB0SGFzaAACYUcCFyVzX19mZWVDb2xsZWN0b3JBZGRyZXNzAQJhSAECYUkJAKwCAgIbJXMlc19fc2tpcE9yZGVyVmFsaWRhdGlvbl9fBQJhSQECYUoEAmFLAmFMAmFNAmFOCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICJG9yZGVyIHZhbGlkYXRpb24gZmFpbGVkOiBvcmRlclZhbGlkPQkApQMBBQJhSwICICgFAmFMAgEpAg0gc2VuZGVyVmFsaWQ9CQClAwEFAmFNAg4gbWF0Y2hlclZhbGlkPQkApQMBBQJhTgECYU8BAmFQBAJhUQkApggBBQJhUAMJAAECBQJhUQIHQWRkcmVzcwQCYVIFAmFRBQJhUgUEdGhpcwECYVMABAJhVAQCYVEJAKIIAQkBAVQAAwkAAQIFAmFRAgZTdHJpbmcEAmFVBQJhUQkBAmFPAQUCYVUFBHRoaXMEAmFRCQCdCAIFAmFUCQEBVgADCQABAgUCYVECBlN0cmluZwQCYVYFAmFRCQECYU8BBQJhVgUEdGhpcwECYVcCAmFYAmFZCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUCYVgFAmFZCQC5CQIJAMwIAgIKbWFuZGF0b3J5IAkAzAgCCQClCAEFAmFYCQDMCAICAS4JAMwIAgUCYVkJAMwIAgIPIGlzIG5vdCBkZWZpbmVkBQNuaWwCAAECYVoCAmFYAmFZCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUCYVgFAmFZCQC5CQIJAMwIAgIKbWFuZGF0b3J5IAkAzAgCCQClCAEFAmFYCQDMCAICAS4JAMwIAgUCYVkJAMwIAgIPIGlzIG5vdCBkZWZpbmVkBQNuaWwCAAECYmEBAmJiCQACAQkAuQkCCQDMCAICCGxwLnJpZGU6CQDMCAIFAmJiBQNuaWwCASABAmJjAQJiYgkAuQkCCQDMCAICCGxwLnJpZGU6CQDMCAIFAmJiBQNuaWwCASAAAmJkCQERQGV4dHJOYXRpdmUoMTA2MikBCQECYVcCBQR0aGlzCQEBVAAAAmJlCQERQGV4dHJOYXRpdmUoMTA2MikBCQECYVcCBQJiZAUCYUcAAmJmCgACYmcJAPwHBAUCYmQCEGdldEluRmVlUkVBRE9OTFkJAMwIAgkApQgBBQR0aGlzBQNuaWwFA25pbAMJAAECBQJiZwIDSW50BQJiZwkAAgEJAKwCAgkAAwEFAmJnAhggY291bGRuJ3QgYmUgY2FzdCB0byBJbnQAAmJoCgACYmcJAPwHBAUCYmQCEWdldE91dEZlZVJFQURPTkxZCQDMCAIJAKUIAQUEdGhpcwUDbmlsBQNuaWwDCQABAgUCYmcCA0ludAUCYmcJAAIBCQCsAgIJAAMBBQJiZwIYIGNvdWxkbid0IGJlIGNhc3QgdG8gSW50AQJiaQECYVgJALkJAgkAzAgCAgQlcyVzCQDMCAICC3doaXRlbGlzdGVkCQDMCAIJAKUIAQUCYVgFA25pbAUBagECYmoBAmFYCQELdmFsdWVPckVsc2UCCQCbCAIFAmJkCQECYmkBBQJhWAcBAmJrAAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQJiZAkBAmFDAAcBAmJsAAkA2QQBCQECYVcCBQJiZAkBAmF1AAECYm0ABAJibgkBAmFXAgUEdGhpcwkBAmFlAAQCYm8JAQJhVwIFBHRoaXMJAQJhZgAEAmF6CQECYVoCBQJiZAkBAmFBAQUCYm8EAmF5CQECYVoCBQJiZAkBAmFBAQUCYm4JALUJAgkBAmFXAgUCYmQJAQJheAIJAKQDAQUCYXkJAKQDAQUCYXoFAWoBAmJwAQJicQMJAAACBQJicQUBaQUEdW5pdAkA2QQBBQJicQECYnIBAmJxAwkAAAIFAmJxBQR1bml0BQFpCQDYBAEJAQV2YWx1ZQEFAmJxAQJicwECYnQJAJkKBwkBEUBleHRyTmF0aXZlKDEwNjIpAQkAkQMCBQJidAUBbwkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmJ0BQFwCQDZBAEJAJEDAgUCYnQFAXEJAQJicAEJAJEDAgUCYnQFAXIJAQJicAEJAJEDAgUCYnQFAXMJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJidAUBdAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmJ0BQF1AAJidQkBAmJzAQkBAmJtAAACYnYFAmJ1AAJidwgFAmJ2Al8xAAJieAgFAmJ2Al8yAAJieQgFAmJ2Al8zAAJieggFAmJ2Al80AAJiQQgFAmJ2Al81AAJiQggFAmJ2Al82AAJiQwgFAmJ2Al83AQJiRAAJALUJAgkBAmFXAgUCYmQJAQJhdAAFAWoAAmJFCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkAkQMCCQECYkQABQFCAhlpbmNvcnJlY3Qgc3Rha2luZyBhZGRyZXNzAAJiRgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJAJEDAgkBAmJEAAUBQwIZaW5jb3JyZWN0IHN0YWtpbmcgYWRkcmVzcwECYkcKAmJIAmJJAmJKAmJLAmJMAmJNAmJOAmJPAmJQAmJRCQC5CQIJAMwIAgIUJWQlZCVkJWQlZCVkJWQlZCVkJWQJAMwIAgkApAMBBQJiSAkAzAgCCQCkAwEFAmJJCQDMCAIJAKQDAQUCYkoJAMwIAgkApAMBBQJiSwkAzAgCCQCkAwEFAmJMCQDMCAIJAKQDAQUCYk0JAMwIAgkApAMBBQJiTgkAzAgCCQCkAwEFAmJPCQDMCAIJAKQDAQUCYlAJAMwIAgkApAMBBQJiUQUDbmlsBQFqAQJiUgYCYlMCYlQCYlUCYksCYk4CYk8JALkJAgkAzAgCAgwlZCVkJWQlZCVkJWQJAMwIAgkApAMBBQJiUwkAzAgCCQCkAwEFAmJUCQDMCAIJAKQDAQUCYlUJAMwIAgkApAMBBQJiSwkAzAgCCQCkAwEFAmJOCQDMCAIJAKQDAQUCYk8FA25pbAUBagECYlYBAmFwBAJiVwMJAAACBQJhcAIFV0FWRVMICQDvBwEFBHRoaXMJYXZhaWxhYmxlCQDwBwIFBHRoaXMJANkEAQUCYXAEAmJYCQBlAgkAZAIFAmJXCQECYXIBBQJhcAkBAmFzAQUCYXAJAJYDAQkAzAgCAAAJAMwIAgUCYlgFA25pbAECYlkCAmJaAmNhCQC8AgMFAmJaBQFkBQJjYQECY2IDAmJaAmNhAUwJAL0CBAUCYloFAWQFAmNhBQFMAQJjYwECY2QEAmNlCQD8BwQFAmNkAgdnZXRSYXRlBQNuaWwFA25pbAMJAAACBQJjZQUCY2UEAmFRBQJjZQMJAAECBQJhUQIDSW50BAJjZgUCYVEFAmNmCQECYmEBAiBwcm94eS5nZXRSYXRlKCkgdW5leHBlY3RlZCB2YWx1ZQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgECY2cEAmFwAmNoAmNpAmNkBAJjagkBAmFyAQUCYXADCQAAAgUCY2oFAmNqBAJjawkBAmFzAQUCY2kDCQAAAgUCY2sFAmNrBAJjbAkBAmJwAQUCYXADCQBmAgUCY2gAAAQCY20JAPwHBAUCY2QCB2RlcG9zaXQFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUCY2wFAmNoBQNuaWwDCQAAAgUCY20FAmNtBAJhUQUCY20DCQABAgUCYVECA0ludAQCY24FAmFRBAJjbwkAZAIFAmNqBQJjaAQCY3AJAGQCBQJjawUCY24JAMwIAgkBDEludGVnZXJFbnRyeQIJAQJhbwEFAmFwBQJjbwkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAmFxAQUCY2kFAmNwBQNuaWwFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQJjcQYCYXACY2gCY2kCY2QCY3ICY3MEAmNqCQECYXIBBQJhcAMJAAACBQJjagUCY2oEAmNrCQECYXMBBQJjaQMJAAACBQJjawUCY2sEAmN0CQECY2MBBQJjZAMJAAACBQJjdAUCY3QEAmN1CQBrAwUCY3IFAmNqBQJjawQCY3YJAQJicAEFAmNpBAJjdwkAawMFAmNyBQJjaAUCY3UEAmN4CQBrAwUCY3IFAmNoBQJjdAQCY3kJAJYDAQkAzAgCAAAJAMwIAgkAZQIFAmN3BQJjeAUDbmlsAwkAZgIFAmN4AAAEAmN6CQD8BwQFAmNkAgh3aXRoZHJhdwUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQJjdgUCY3gFA25pbAMJAAACBQJjegUCY3oEAmFRBQJjegMJAAECBQJhUQIDSW50BAJjQQUCYVEEAmNvCQBlAgUCY2oFAmNBBAJjcAkAZQIJAGUCBQJjawUCY3gFAmN5CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQECYW8BBQJhcAUCY28JAMwIAgkBDEludGVnZXJFbnRyeQIJAQJhcQEFAmNpBQJjcAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQJjcwUCY3kJAQJicAEFAmNpBQNuaWwFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQJjQgECYXAEAmFRCQD8BwQFAmJkAhpnZXRQb29sTGVhc2VDb25maWdSRUFET05MWQkAzAgCCQClCAEFBHRoaXMJAMwIAgUCYXAFA25pbAUDbmlsAwkAAQIFAmFRAjAoQm9vbGVhbiwgSW50LCBJbnQsIFN0cmluZywgU3RyaW5nLCBJbnQsIFN0cmluZykEAmFSBQJhUQUCYVIJAQJiYQEJAKwCAgkArAICAgFbBQJhcAIdXSBnZXRMZWFzZVByb3h5Q29uZmlnKCkgZXJyb3IBAmNDBwJjRAJhcAJjaQJjRQJjZAJjcgJjcwQCY2oJAQJhcgEFAmFwAwkAAAIFAmNqBQJjagQCY2sJAQJhcwEFAmNpAwkAAAIFAmNrBQJjawQCY0YJAJYDAQkAzAgCAAAJAMwIAgkAZQIJAQJiVgEFAmFwBQJjRQUDbmlsBAJjRwkAawMFAmNEBQJjRgBkBAJjSAkAZQIFAmNqBQJjRwMJAAACBQJjSAAABQNuaWwDCQBmAgAABQJjSAQCY0kJAQEtAQUCY0gJAQJjZwQFAmFwBQJjSQUCY2kFAmNkBAJjSgUCY0gJAQJjcQYFAmFwBQJjSgUCY2kFAmNkBQJjcgUCY3MJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BAmNLAQJhcAQCY0wJAQJjQgEFAmFwBAJjTQgFAmNMAl8xBAJjTggFAmNMAl8yBAJjRQgFAmNMAl8zBAJjTwgFAmNMAl80BAJjUAgFAmNMAl81BAJjcggFAmNMAl82BAJjUQgFAmNMAl83AwUCY00JAQJjQwcFAmNOBQJhcAUCY1AFAmNFCQERQGV4dHJOYXRpdmUoMTA2MikBBQJjTwUCY3IJARFAZXh0ck5hdGl2ZSgxMDYyKQEFAmNRBQNuaWwBAmNSAgJhcAJjUwQCY1QJAQJjQgEFAmFwBAJjTQgFAmNUAl8xBAJjTggFAmNUAl8yBAJjRQgFAmNUAl8zBAJjTwgFAmNUAl80BAJjUAgFAmNUAl81BAJjcggFAmNUAl82BAJjUQgFAmNUAl83AwUCY00EAmNVCQCWAwEJAMwIAgAACQDMCAIJAGUCCQBlAgkBAmJWAQUCYXAFAmNTBQJjRQUDbmlsAwkAAAIFAmNVBQJjVQQCY28JAGsDBQJjTgUCY1UAZAMJAAACBQJjbwUCY28EAmNWCQBlAgkBAmFyAQUCYXAFAmNvAwkAAAIFAmNWBQJjVgMJAGYCAAAFAmNWCQECY2cEBQJhcAkBAS0BBQJjVgUCY1AJARFAZXh0ck5hdGl2ZSgxMDYyKQEFAmNPCQECY3EGBQJhcAUCY1YFAmNQCQERQGV4dHJOYXRpdmUoMTA2MikBBQJjTwUCY3IJARFAZXh0ck5hdGl2ZSgxMDYyKQEFAmNRCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwBAmNXAgJjWAJjWQQCY1oJAQJjUgIJAQJhVwIFBHRoaXMJAQJhZQAFAmNYBAJkYQkBAmNSAgkBAmFXAgUEdGhpcwkBAmFmAAUCY1kJAM4IAgUCY1oFAmRhAQJkYgQCZGMCZGQCZGUCZGYEAmRnCQEBRAIFAmRlBQJkYwQCZGgJAQFEAgUCZGYFAmRkCQECYlkCBQJkaAUCZGcBAmRpAwJkZQJkZgJkagQCZGsJAQJibQAEAmRsCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCZGsFAXQEAmRtCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCZGsFAXUEAmRuCQECZGIEBQJkbAUCZG0FAmRlBQJkZgQCY2EJAQFEAgUCZGUFAmRsBAJiWgkBAUQCBQJkZgUCZG0EAmRvCQEBRAIFAmRqBQFiBAJkcAkBAmJZAgUCY2EFAmRvBAJkcQkBAmJZAgUCYloFAmRvCQDMCAIFAmRuCQDMCAIFAmRwCQDMCAIFAmRxBQNuaWwBAmRyAwJkZQJkZgJkagQCZHMJAQJkaQMFAmRlBQJkZgUCZGoJAMwIAgkBAUgCCQCRAwIFAmRzAAAFAWIJAMwIAgkBAUgCCQCRAwIFAmRzAAEFAWIJAMwIAgkBAUgCCQCRAwIFAmRzAAIFAWIFA25pbAECZHQEAmR1AmR2AmR3AmFiBAJkawkBAmJtAAQCZHgJAJEDAgUCZGsFAXEEAmR5CQCRAwIFAmRrBQFyBAJkegkAkQMCBQJkawUBcwQCZGMJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJkawUBdAQCZGQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJkawUBdQQCZEEJAJEDAgUCZGsFAXAEAmRCCAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQDsBwEJANkEAQUCZHgJAKwCAgkArAICAgZBc3NldCAFAmR4Ag4gZG9lc24ndCBleGlzdAhxdWFudGl0eQMJAQIhPQIFAmR4BQJkdgkAAgECFUludmFsaWQgYXNzZXQgcGFzc2VkLgQCZEMJAQJiVgEFAmR5BAJkRAkBAUQCBQJkQwUCZGMEAmRFCQECYlYBBQJkegQCZEYJAQFEAgUCZEUFAmRkBAJkRwkBAmJZAgUCZEYFAmREBAJkSAkBAUgCBQJkRwUBYgQCZEkJAQFEAgUCZHcFAWIEAmRKCQEBRAIFAmRCBQFiBAJkSwkAvAIDBQJkRAUCZEkFAmRKBAJkTAkAvAIDBQJkRgUCZEkFAmRKBAJkTQkBAUsDBQJkSwUCZGMFBUZMT09SBAJkTgkBAUsDBQJkTAUCZGQFBUZMT09SBAJkTwMJAAACBQJkdQIABQNuaWwJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUCYWIFAmRNAwkAAAIFAmR5AgVXQVZFUwUEdW5pdAkA2QQBBQJkeQkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQJhYgUCZE4DCQAAAgUCZHoCBVdBVkVTBQR1bml0CQDZBAEFAmR6CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQJhZAIJAKUIAQUCYWIFAmR1CQECYlIGBQJkTQUCZE4FAmR3BQJkSAUGaGVpZ2h0CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAVcABQJkSAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAVgCBQZoZWlnaHQIBQlsYXN0QmxvY2sJdGltZXN0YW1wBQJkSAUDbmlsCQCcCgoFAmRNBQJkTgUCZHkFAmR6BQJkQwUCZEUFAmRCBQJkRwUCZEEFAmRPAQJkUAkCZHUCZFECZFICZFMCZFQCZFUCYWICZFYCZFcEAmRrCQECYm0ABAJkeAkA2QQBCQCRAwIFAmRrBQFxBAJkWAkAkQMCBQJkawUBcgQCZFkJAJEDAgUCZGsFAXMEAmRaCQCRAwIFAmRrBQF2BAJlYQkAkQMCBQJkawUBdwQCZGwJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJkawUBdAQCZG0JAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJkawUBdQQCZEEJAJEDAgUCZGsFAXAEAmRCCAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQDsBwEFAmR4CQCsAgIJAKwCAgIGQXNzZXQgCQDYBAEFAmR4Ag4gZG9lc24ndCBleGlzdAhxdWFudGl0eQQCZWIJANgEAQkBC3ZhbHVlT3JFbHNlAgUCZFMJANkEAQIFV0FWRVMEAmVjCQDYBAEJAQt2YWx1ZU9yRWxzZQIFAmRVCQDZBAECBVdBVkVTAwMJAQIhPQIFAmRYBQJlYgYJAQIhPQIFAmRZBQJlYwkAAgECIkludmFsaWQgYW10IG9yIHByaWNlIGFzc2V0IHBhc3NlZC4EAmRDAwUCZFYJAQJiVgEFAmRYCQBlAgkBAmJWAQUCZFgFAmRSBAJkRQMFAmRWCQECYlYBBQJkWQkAZQIJAQJiVgEFAmRZBQJkVAQCZWQJAQFEAgUCZFIFAmRsBAJlZQkBAUQCBQJkVAUCZG0EAmVmCQECYlkCBQJlZQUCZWQEAmRECQEBRAIFAmRDBQJkbAQCZEYJAQFEAgUCZEUFAmRtBAJlZwMJAAACBQJkQgAABAJkRwUBZQQCZWgFAWUEAmRvCQB2BgkAuQICBQJlZAUCZWUAAAkAtgIBAAUAAQAABQRET1dOCQCXCgUJAQFIAgUCZG8FAWIJAQFIAgUCZWQFAmRsCQEBSAIFAmVlBQJkbQkBAmJZAgkAtwICBQJkRgUCZWUJALcCAgUCZEQFAmVkBQJlaAQCZEcJAQJiWQIFAmRGBQJkRAQCZWgJALwCAwkBAVIBCQC4AgIFAmRHBQJlZgUBZAUCZEcEAmVpCQEBRAIFAmRRBQFiAwMJAQIhPQIFAmRHBQFlCQC/AgIFAmVoBQJlaQcJAAIBCQCsAgIJAKwCAgkArAICAg9QcmljZSBzbGlwcGFnZSAJAKYDAQUCZWgCHiBleGNlZWRlZCB0aGUgcGFzc2VkIGxpbWl0IG9mIAkApgMBBQJlaQQCZEoJAQFEAgUCZEIFAWIEAmVqCQC9AgQFAmVkCQECY2IDBQJkRgUCZEQFB0NFSUxJTkcFAWQFB0NFSUxJTkcEAmVrCQC9AgQFAmVlBQFkCQECY2IDBQJkRgUCZEQFBUZMT09SBQdDRUlMSU5HBAJlbAMJAL8CAgUCZWoFAmVlCQCUCgIFAmVrBQJlZQkAlAoCBQJlZAUCZWoEAmVtCAUCZWwCXzEEAmVuCAUCZWwCXzIEAmRvCQC9AgQFAmRKBQJlbgUCZEYFBUZMT09SCQCXCgUJAQFLAwUCZG8FAWIFBUZMT09SCQEBSwMFAmVtBQJkbAUHQ0VJTElORwkBAUsDBQJlbgUCZG0FB0NFSUxJTkcFAmRHBQJlaAQCZW8IBQJlZwJfMQQCZXAIBQJlZwJfMgQCZXEIBQJlZwJfMwQCZEgJAQFIAggFAmVnAl80BQFiBAJlcgkBAUgCCAUCZWcCXzUFAWIDCQBnAgAABQJlbwkAAgECNkludmFsaWQgY2FsY3VsYXRpb25zLiBMUCBjYWxjdWxhdGVkIGlzIGxlc3MgdGhhbiB6ZXJvLgQCZXMDCQEBIQEFAmRXAAAFAmVvBAJldAkAZQIFAmRSBQJlcAQCZXUJAGUCBQJkVAUCZXEEAmV2CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEBVwAFAmRICQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEBWAIFBmhlaWdodAgFCWxhc3RCbG9jawl0aW1lc3RhbXAFAmRICQDMCAIJAQtTdHJpbmdFbnRyeQIJAQJhYQIFAmFiBQJkdQkBAmJHCgUCZXAFAmVxBQJlcwUCZEgFAmRRBQJlcgUGaGVpZ2h0CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAUCZXQFAmV1BQNuaWwJAJ8KDQUCZW8FAmVzBQJkSAUCZEMFAmRFBQJkQgUCZHgFAmRBBQJldgUCZXQFAmV1BQJkUwUCZFUBAmV3AwJleAJleQJkQgQCZXoJAQFHAgUCZXgJALYCAQUCYkIEAmVBCQEBRwIFAmV5CQC2AgEFAmJDBAJlQgkAvAIDCQB2BgkAuQICBQJlegUCZUEAAAkAtgIBAAUAAQASBQRET1dOBQFnBQJkQgMJAAACBQJkQgUBZgUBZgUCZUIBAmVDAwJlRAJlRQJlRgQCZUcJALgCAgkAtgIBCQECYlYBCQECYnIBBQJiegUCZUQEAmVICQC4AgIJALYCAQkBAmJWAQkBAmJyAQUCYkEFAmVFBAJlSQkAuAICCQC2AgEICQEFdmFsdWUBCQDsBwEFAmJ5CHF1YW50aXR5BQJlRgQCZUoJAQJldwMFAmVHBQJlSAUCZUkFAmVKAQJlSwMCZUwCZU0CZUYEAmVHCQBkAgkBAmJWAQkBAmJyAQUCYnoFAmVMBAJlSAkAZAIJAQJiVgEJAQJicgEFAmJBBQJlTQQCZUkJAGQCCAkBBXZhbHVlAQkA7AcBBQJieQhxdWFudGl0eQUCZUYEAmVCCQECZXcDCQC2AgEFAmVHCQC2AgEFAmVICQC2AgEFAmVJBAJlTgkAzAgCCQEMSW50ZWdlckVudHJ5AgUCYWsFBmhlaWdodAkAzAgCCQELU3RyaW5nRW50cnkCBQJhagkApgMBBQJlQgUDbmlsCQCUCgIFAmVOBQJlQgECZU8ACQELdmFsdWVPckVsc2UCCQCbCAIFAmJkCQECYUgBCQClCAEFBHRoaXMHAQJlUAICZVECZUIDCQDAAgIFAmVCBQJlUQYJAQJiYQEJALkJAgkAzAgCAiJ1cGRhdGVkIEtMcCBsb3dlciB0aGFuIGN1cnJlbnQgS0xwCQDMCAIJAKYDAQUCZVEJAMwIAgkApgMBBQJlQgUDbmlsAgEgAQJlUgECZVMEAmVHCQECYlYBCQECYnIBBQJiegQCZUgJAQJiVgEJAQJicgEFAmJBBAJlVAgFAmVTBmFtb3VudAQCZVUJAG4ECAUCZVMGYW1vdW50CAUCZVMFcHJpY2UFAWIFBUZMT09SBAJlVgMJAAACCAUCZVMJb3JkZXJUeXBlBQNCdXkJAJQKAgUCZVQJAQEtAQUCZVUJAJQKAgkBAS0BBQJlVAUCZVUEAmVMCAUCZVYCXzEEAmVNCAUCZVYCXzIDAwMJAQJiawAGCQAAAgUCYngFAW0GCQAAAgUCYngFAW4JAAIBAhxFeGNoYW5nZSBvcGVyYXRpb25zIGRpc2FibGVkAwMJAQIhPQIICAUCZVMJYXNzZXRQYWlyC2Ftb3VudEFzc2V0BQJiegYJAQIhPQIICAUCZVMJYXNzZXRQYWlyCnByaWNlQXNzZXQFAmJBCQACAQITV3Jvbmcgb3JkZXIgYXNzZXRzLgQCZVcJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAqAMBCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMFAmFqAgEwCQECYmMBAgtpbnZhbGlkIGtMcAQCZVgJAQJlSwMFAmVMBQJlTQAABAJlWQgFAmVYAl8xBAJlWggFAmVYAl8yBAJmYQkAwAICBQJlWgUCZVcEAmZiCQC5CQIJAMwIAgIEa0xwPQkAzAgCCQCmAwEFAmVXCQDMCAICCCBrTHBOZXc9CQDMCAIJAKYDAQUCZVoJAMwIAgIUIGFtb3VudEFzc2V0QmFsYW5jZT0JAMwIAgkApAMBBQJlRwkAzAgCAhMgcHJpY2VBc3NldEJhbGFuY2U9CQDMCAIJAKQDAQUCZUgJAMwIAgIZIGFtb3VudEFzc2V0QmFsYW5jZURlbHRhPQkAzAgCCQCkAwEFAmVMCQDMCAICGCBwcmljZUFzc2V0QmFsYW5jZURlbHRhPQkAzAgCCQCkAwEFAmVNCQDMCAICCCBoZWlnaHQ9CQDMCAIJAKQDAQUGaGVpZ2h0BQNuaWwCAAkAlAoCBQJmYQUCZmIBAmZjAQJmZAMJAQIhPQIJAJADAQgFAmZkCHBheW1lbnRzAAEJAAIBAh1leGFjdGx5IDEgcGF5bWVudCBpcyBleHBlY3RlZAQCZmUJAQV2YWx1ZQEJAJEDAggFAmZkCHBheW1lbnRzAAAEAmR2CQEFdmFsdWUBCAUCZmUHYXNzZXRJZAQCZmYIBQJmZQZhbW91bnQEAmVnCQECZHQECQDYBAEIBQJmZA10cmFuc2FjdGlvbklkCQDYBAEFAmR2BQJmZggFAmZkBmNhbGxlcgQCZE0IBQJlZwJfMQQCZE4IBQJlZwJfMgQCZE8IBQJlZwNfMTAEAmZnAwkBASEBCQECYmoBCAUCZmQGY2FsbGVyAwkBAmJrAAYJAAACBQJieAUBbgcDBQJmZwkAAgEJAKwCAgIsR2V0IG9wZXJhdGlvbiBpcyBibG9ja2VkIGJ5IGFkbWluLiBTdGF0dXMgPSAJAKQDAQUCYngJAJcKBQUCZE0FAmROBQJmZgUCZHYFAmRPAQJmaAMCZmQCZFECZFcDCQECIT0CCQCQAwEIBQJmZAhwYXltZW50cwACCQACAQIfZXhhY3RseSAyIHBheW1lbnRzIGFyZSBleHBlY3RlZAQCZmkJAQV2YWx1ZQEJAJEDAggFAmZkCHBheW1lbnRzAAAEAmZqCQEFdmFsdWUBCQCRAwIIBQJmZAhwYXltZW50cwABBAJmawkBAmRQCQkA2AQBCAUCZmQNdHJhbnNhY3Rpb25JZAUCZFEIBQJmaQZhbW91bnQIBQJmaQdhc3NldElkCAUCZmoGYW1vdW50CAUCZmoHYXNzZXRJZAkApQgBCAUCZmQGY2FsbGVyBwUCZFcEAmZsAwkBASEBCQECYmoBCAUCZmQGY2FsbGVyAwMJAQJiawAGCQAAAgUCYngFAWwGCQAAAgUCYngFAW4HAwUCZmwJAAIBCQCsAgICLFB1dCBvcGVyYXRpb24gaXMgYmxvY2tlZCBieSBhZG1pbi4gU3RhdHVzID0gCQCkAwEFAmJ4BQJmawECZm0BAmNoBAJmbgkA/AcEBQJiZAIEZW1pdAkAzAgCBQJjaAUDbmlsBQNuaWwDCQAAAgUCZm4FAmZuBAJmbwQCYVEFAmZuAwkAAQIFAmFRAgdBZGRyZXNzBAJmcAUCYVEJAPwHBAUCZnACBGVtaXQJAMwIAgUCY2gFA25pbAUDbmlsBQR1bml0AwkAAAIFAmZvBQJmbwUCY2gJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BAmZxAgJjaAJhaQQCZnIDCQAAAgUCYWkAAAAACQBrAwUCY2gFAmFpBQFiCQCUCgIJAGUCBQJjaAUCZnIFAmZyAQJmcwQCZnQCZnUCYWICYWMEAmZ2CQAAAgUCYWMFBHVuaXQEAmZ3CQECYlYBCQECYnIBBQJiegQCZngJAQJiVgEJAQJicgEFAmJBBAJmeQMJAAACBQJmdQUCYnoGAwkAAAIFAmZ1BQJiQQcJAQJiYQECDWludmFsaWQgYXNzZXQEAmZ6AwUCZnYJAJQKAgUCZncFAmZ4AwUCZnkJAJQKAgkAZQIFAmZ3BQJmdAUCZngJAJQKAgUCZncJAGUCBQJmeAUCZnQEAmZBCAUCZnoCXzEEAmZCCAUCZnoCXzIEAmZDAwUCZnkJAJQKAgUCZnQAAAkAlAoCAAAFAmZ0BAJmRAgFAmZDAl8xBAJmRQgFAmZDAl8yBAJlVAgJAQJmcQIFAmZEBQJiZgJfMQQCZVUICQECZnECBQJmRQUCYmYCXzEEAmZGCQECZnECBQJmdAUCYmYEAmZHCAUCZkYCXzEEAmZyCAUCZkYCXzIEAmZICQBkAgUCZkEFAmVUBAJmSQkAZAIFAmZCBQJlVQQCZkoJAQJiWQIJAQFEAgUCZkkFAmJDCQEBRAIFAmZIBQJiQgQCZksJAQFIAgUCZkoFAWIEAmZMAwUCZnkFAmZBBQJmQgQCZk0JALYCAQUCZkwEAmZOCQC2AgEICQETdmFsdWVPckVycm9yTWVzc2FnZQIJAOwHAQUCYnkJAKwCAgkArAICAgZhc3NldCAJANgEAQUCYnkCDiBkb2Vzbid0IGV4aXN0CHF1YW50aXR5BAJmTwMJAL8CAgUCZk4FAWYGCQECYmEBAiJpbml0aWFsIGRlcG9zaXQgcmVxdWlyZXMgYWxsIGNvaW5zAwkAAAIFAmZPBQJmTwQCZlAJALYCAQUCZkcEAmZRCQCWAwEJAMwIAgAACQDMCAIJAKADAQkAugICCQC5AgIFAmZOCQC4AgIJAQpzcXJ0QmlnSW50BAkAtwICBQFkCQC6AgIJALkCAgUCZlAFAWQFAmZNABIAEgUERE9XTgUBZAUBZAUDbmlsBAJldgMFAmZ2BQNuaWwJAMwIAgkBDEludGVnZXJFbnRyeQIJAQFXAAUCZksJAMwIAgkBDEludGVnZXJFbnRyeQIJAQFYAgUGaGVpZ2h0CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAUCZksJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAmFhAgkApQgBCQEFdmFsdWUBBQJhYgkA2AQBCQEFdmFsdWUBBQJhYwkBAmJHCgUCZkQFAmZFBQJmUQUCZksAAAAABQZoZWlnaHQIBQlsYXN0QmxvY2sJdGltZXN0YW1wAAAAAAUDbmlsBAJmUgkBAmJZAgkBAUQCBQJmQgUCYkMJAQFEAgUCZkEFAmJCBAJmUwkBAUgCBQJmUgUBYgQCZlQEAmZVAwUCZnkJAJQKAgUCZkQFAmZBCQCUCgIFAmZFBQJmQgQCY2gIBQJmVQJfMQQCZlYIBQJmVQJfMgQCZlcJAKADAQkAvAIDBQJmTgkAtgIBCQBpAgUCY2gAAgkAtgIBBQJmVgkAawMJAGUCBQJmUQUCZlcFAWIFAmZXCQCXCgUFAmZRBQJldgUCZnIFAmZUBQJmeQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgECZlgFAmZZAmZHAmZ1AmFiAmFjBAJmdgkAAAIFAmFjBQR1bml0BAJkawkBAmJtAAQCZGwJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJkawUBdAQCZG0JAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJkawUBdQQCZloJAMwIAgMJAAACBQJmdQUCYnkGCQECYmEBAhBpbnZhbGlkIGxwIGFzc2V0BQNuaWwDCQAAAgUCZloFAmZaBAJnYQMJAAACBQJmWQUCYnoGAwkAAAIFAmZZBQJiQQcJAQJiYQECDWludmFsaWQgYXNzZXQEAmdiAwUCZ2EJALYCAQkBAmJWAQkBAmJyAQUCYnoJALYCAQkBAmJWAQkBAmJyAQUCYkEEAmdjAwUCZ2EFAmRsBQJkbQQCZ2QJAQJiVgEJAQJicgEFAmJ6BAJnZQkBAmJWAQkBAmJyAQUCYkEEAmdmAwUCZ2EFAmdkBQJnZQQCZ2cJALYCAQUCZ2YEAmZOCQC2AgEICQETdmFsdWVPckVycm9yTWVzc2FnZQIJAOwHAQUCYnkJAKwCAgkArAICAgZhc3NldCAJANgEAQUCYnkCDiBkb2Vzbid0IGV4aXN0CHF1YW50aXR5BAJnaAkAtgIBBQJmRwQCZ2kJAJYDAQkAzAgCAAAJAMwIAgkAoAMBCQC6AgIJALkCAgUCZ2IJALgCAgUBZAkAdgYJALgCAgUBZAkAugICCQC5AgIFAmdoBQFkBQJmTgASBQFoAAAAEgUERE9XTgUBZAUDbmlsBAJnagkBAmZxAgUCZ2kFAmJoBAJnawgFAmdqAl8xBAJmcggFAmdqAl8yBAJnbAMFAmdhCQCWCgQFAmdrAAAJAGUCBQJnZAUCZ2kFAmdlCQCWCgQAAAUCZ2sFAmdkCQBlAgUCZ2UFAmdpBAJnbQgFAmdsAl8xBAJnbggFAmdsAl8yBAJnbwgFAmdsAl8zBAJncAgFAmdsAl80BAJmSgkBAmJZAgkBAUQCBQJncAUCYkMJAQFEAgUCZ28FAmJCBAJmSwkBAUgCBQJmSgUBYgQCZXYDBQJmdgUDbmlsCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQJhZAIJAKUIAQkBBXZhbHVlAQUCYWIJANgEAQkBBXZhbHVlAQUCYWMJAQJiUgYFAmdtBQJnbgUCZkcFAmZLBQZoZWlnaHQIBQlsYXN0QmxvY2sJdGltZXN0YW1wCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEBVwAFAmZLCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEBWAIFBmhlaWdodAgFCWxhc3RCbG9jawl0aW1lc3RhbXAFAmZLBQNuaWwEAmZSCQECYlkCCQEBRAIFAmdlBQJiQwkBAUQCBQJnZAUCYkIEAmZTCQEBSAIFAmZSBQFiBAJmVAQCZ3EJAGgCCQCgAwEJALwCAwUCZ2IFAmdoBQJmTgACCQBrAwkAZQIFAmdrBQJncQUBYgUCZ3EJAJcKBQUCZ2sFAmV2BQJmcgUCZlQFAmdhCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQJncgAEAmdzCQECYVMABAJhUQkAnQgCBQJncwkBAVUAAwkAAQIFAmFRAgZTdHJpbmcEAmFWBQJhUQkA2QQBBQJhVgMJAAECBQJhUQIEVW5pdAUEdW5pdAkAAgECC01hdGNoIGVycm9yAQJndAECZmQEAmFRCQECZ3IAAwkAAQIFAmFRAgpCeXRlVmVjdG9yBAJndQUCYVEJAAACCAUCZmQPY2FsbGVyUHVibGljS2V5BQJndQMJAAECBQJhUQIEVW5pdAkAAAIIBQJmZAZjYWxsZXIFBHRoaXMJAAIBAgtNYXRjaCBlcnJvcgECZ3YBAmZkBAJndwkAAgECEVBlcm1pc3Npb24gZGVuaWVkBAJhUQkBAmdyAAMJAAECBQJhUQIKQnl0ZVZlY3RvcgQCZ3UFAmFRAwkAAAIIBQJmZA9jYWxsZXJQdWJsaWNLZXkFAmd1BgUCZ3cDCQABAgUCYVECBFVuaXQDCQAAAggFAmZkBmNhbGxlcgUEdGhpcwYFAmd3CQACAQILTWF0Y2ggZXJyb3IcAmZkAQlyZWJhbGFuY2UACQDOCAIJAQJjSwEJAQJhVwIFBHRoaXMJAQJhZQAJAQJjSwEJAQJhVwIFBHRoaXMJAQJhZgACZmQBIWNhbGN1bGF0ZUFtb3VudE91dEZvclN3YXBSRUFET05MWQMCZ3gCZ3kCZ3oEAmdBAwkAAAIFAmd5BwQCZ0IJAQJhVwIFBHRoaXMJAQJhZgAEAmdDCQECYVcCBQR0aGlzCQECYWUACQCUCgIFAmdCBQJnQwQCZ0IJAQJhVwIFBHRoaXMJAQJhZQAEAmdDCQECYVcCBQR0aGlzCQECYWYACQCUCgIFAmdCBQJnQwQCZ0IIBQJnQQJfMQQCZ0MIBQJnQQJfMgQCZ0QJAQJiVgEFAmdDBAJnRQkBAmJWAQUCZ0IEAmdGCQBrAwUCZ0UFAmd4CQBkAgUCZ0QFAmd4BAJnRwkAuQICCQC2AgEFAmdECQC2AgEFAmdFBAJnSAkAuQICCQC3AgIJALcCAgkAtgIBCQECYlYBBQJnQwkAtgIBBQJneAkAtgIBBQJnegkAuAICCQC2AgEJAQJiVgEFAmdCCQC2AgEFAmdGBAJnSQMJAMACAgUCZ0gFAmdHBgkAAgECFG5ldyBLIGlzIGZld2VyIGVycm9yAwkAAAIFAmdJBQJnSQkAlAoCBQNuaWwFAmdGCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmZkASZjYWxjdWxhdGVBbW91bnRPdXRGb3JTd2FwQW5kU2VuZFRva2VucwUCZ3gCZ3kCZ0oCZ0sCZ3oEAmdMCgACYmcJAPwHBAUCYmQCF2dldFN3YXBDb250cmFjdFJFQURPTkxZBQNuaWwFA25pbAMJAAECBQJiZwIGU3RyaW5nBQJiZwkAAgEJAKwCAgkAAwEFAmJnAhsgY291bGRuJ3QgYmUgY2FzdCB0byBTdHJpbmcEAmdNCgACYmcJAPwHBAUCYmQCGmlzUG9vbFN3YXBEaXNhYmxlZFJFQURPTkxZCQDMCAIJAKUIAQUEdGhpcwUDbmlsBQNuaWwDCQABAgUCYmcCB0Jvb2xlYW4FAmJnCQACAQkArAICCQADAQUCYmcCHCBjb3VsZG4ndCBiZSBjYXN0IHRvIEJvb2xlYW4EAmdOAwkBASEBCQECYmoBCAUCZmQGY2FsbGVyAwMJAQJiawAGCQAAAgUCYngFAW4GBQJnTQcEAmZaCQDMCAIDAwkBASEBBQJnTgYJAQJndAEFAmZkBgkBAmJhAQIic3dhcCBvcGVyYXRpb24gaXMgYmxvY2tlZCBieSBhZG1pbgkAzAgCAwkAZwIICQEFdmFsdWUBCQCRAwIIBQJmZAhwYXltZW50cwAABmFtb3VudAUCZ3gGCQECYmEBAgxXcm9uZyBhbW91bnQJAMwIAgMJAAACCAUCZmQGY2FsbGVyCQERQGV4dHJOYXRpdmUoMTA2MikBBQJnTAYJAQJiYQECEVBlcm1pc3Npb24gZGVuaWVkBQNuaWwDCQAAAgUCZloFAmZaBAJmZQkBBXZhbHVlAQkAkQMCCAUCZmQIcGF5bWVudHMAAAQCZ0MJAQJicgEIBQJmZQdhc3NldElkBAJnQgMJAAACBQJneQcJAQJhVwIFBHRoaXMJAQJhZgAJAQJhVwIFBHRoaXMJAQJhZQAEAmdECQBlAgkAZQIJAQJiVgEFAmdDCAkBBXZhbHVlAQkAkQMCCAUCZmQIcGF5bWVudHMAAAZhbW91bnQFAmd6BAJnRQkBAmJWAQUCZ0IEAmdGCQBrAwUCZ0UFAmd4CQBkAgUCZ0QFAmd4BAJnRwkAuQICCQC2AgEFAmdECQC2AgEFAmdFBAJnSAkAuQICCQC3AgIJALYCAQkBAmJWAQUCZ0MJALYCAQUCZ3oJALgCAgkAtgIBCQECYlYBBQJnQgkAtgIBBQJnRgQCZ0kDCQDAAgIFAmdIBQJnRwYJAAIBAhRuZXcgSyBpcyBmZXdlciBlcnJvcgMJAAACBQJnSQUCZ0kEAmdPAwkAZwIFAmdGBQJnSgYJAAIBAixFeGNoYW5nZSByZXN1bHQgaXMgZmV3ZXIgY29pbnMgdGhhbiBleHBlY3RlZAMJAAACBQJnTwUCZ08EAmVMAwUCZ3kJAQEtAQUCZ0YFAmd6BAJlTQMFAmd5BQJnegkBAS0BBQJnRgQCZ1AICQECZUsDBQJlTAUCZU0AAAJfMQMJAAACBQJnUAUCZ1AEAmdRCQECY0sBBQJnQwMJAAACBQJnUQUCZ1EEAmdSCQECY1ICBQJnQgUCZ0YDCQAAAgUCZ1IFAmdSCQCUCgIJAM4IAgkAzggCBQJnUgUCZ1EJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwkBEUBleHRyTmF0aXZlKDEwNjIpAQUCZ0sFAmdGCQECYnABBQJnQgUDbmlsBQJnRgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJmZAEDcHV0AgJkUQJnUwMJAGYCAAAFAmRRCQACAQIgSW52YWxpZCBzbGlwcGFnZVRvbGVyYW5jZSBwYXNzZWQEAmZrCQECZmgDBQJmZAUCZFEGBAJlcwgFAmZrAl8yBAJkeAgFAmZrAl83BAJkTwgFAmZrAl85BAJldAgFAmZrA18xMAQCZXUIBQJmawNfMTEEAmdUCAUCZmsDXzEyBAJnVQgFAmZrA18xMwQCZmkJALYCAQgJAQV2YWx1ZQEJAJEDAggFAmZkCHBheW1lbnRzAAAGYW1vdW50BAJmagkAtgIBCAkBBXZhbHVlAQkAkQMCCAUCZmQIcGF5bWVudHMAAQZhbW91bnQEAmVKCQECZUMDBQJmaQUCZmoJALYCAQAAAwkAAAIFAmVKBQJlSgQCZm4JAPwHBAUCYmQCBGVtaXQJAMwIAgUCZXMFA25pbAUDbmlsAwkAAAIFAmZuBQJmbgQCZm8EAmFRBQJmbgMJAAECBQJhUQIHQWRkcmVzcwQCZnAFAmFRCQD8BwQFAmZwAgRlbWl0CQDMCAIFAmVzBQNuaWwFA25pbAUEdW5pdAMJAAACBQJmbwUCZm8EAmdWAwkAZgIFAmV0AAAJAPwHBAUCYkYCA3B1dAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQJnVAUCZXQFA25pbAUDbmlsAwkAAAIFAmdWBQJnVgQCZ1cDCQBmAgUCZXUAAAkA/AcEBQJiRgIDcHV0BQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFAmdVBQJldQUDbmlsBQNuaWwDCQAAAgUCZ1cFAmdXBAJnWAMFAmdTBAJnWQkA/AcEBQJiRQIFc3Rha2UFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUCZHgFAmVzBQNuaWwDCQAAAgUCZ1kFAmdZBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAmZkBmNhbGxlcgUCZXMFAmR4BQNuaWwEAmdaCQECZUsDAAAAAAAAAwkAAAIFAmdaBQJnWgQCZUIIBQJnWgJfMgQCZ1AIBQJnWgJfMQQCaGEJAQJlUAIFAmVKBQJlQgMJAAACBQJoYQUCaGEEAmhiCQD8BwQFBHRoaXMCCXJlYmFsYW5jZQUDbmlsBQNuaWwDCQAAAgUCaGIFAmhiCQDOCAIJAM4IAgUCZE8FAmdYBQJnUAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJmZAEKcHV0Rm9yRnJlZQECaGMDCQBmAgAABQJoYwkAAgECFEludmFsaWQgdmFsdWUgcGFzc2VkBAJmawkBAmZoAwUCZmQFAmhjBwQCZE8IBQJmawJfOQQCZmkJALYCAQgJAQV2YWx1ZQEJAJEDAggFAmZkCHBheW1lbnRzAAAGYW1vdW50BAJmagkAtgIBCAkBBXZhbHVlAQkAkQMCCAUCZmQIcGF5bWVudHMAAQZhbW91bnQEAmVKCQECZUMDBQJmaQUCZmoJALYCAQAAAwkAAAIFAmVKBQJlSgQCaGQJAQJlSwMAAAAAAAAEAmdQCAUCaGQCXzEEAmVCCAUCaGQCXzIEAmhhCQECZVACBQJlSgUCZUIDCQAAAgUCaGEFAmhhCQDOCAIFAmRPBQJnUAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJmZAEJcHV0T25lVGtuAgJoZQJoZgQCaGcKAAJiZwkA/AcEBQJiZAIoaXNQb29sT25lVG9rZW5PcGVyYXRpb25zRGlzYWJsZWRSRUFET05MWQkAzAgCCQClCAEFBHRoaXMFA25pbAUDbmlsAwkAAQIFAmJnAgdCb29sZWFuBQJiZwkAAgEJAKwCAgkAAwEFAmJnAhwgY291bGRuJ3QgYmUgY2FzdCB0byBCb29sZWFuBAJmbAMJAQEhAQkBAmJqAQgFAmZkBmNhbGxlcgMDAwkBAmJrAAYJAAACBQJieAUBbAYJAAACBQJieAUBbgYFAmhnBwQCZloJAMwIAgMDCQEBIQEFAmZsBgkBAmd0AQUCZmQGCQECYmEBAiFwdXQgb3BlcmF0aW9uIGlzIGJsb2NrZWQgYnkgYWRtaW4JAMwIAgMJAAACCQCQAwEIBQJmZAhwYXltZW50cwABBgkBAmJhAQIeZXhhY3RseSAxIHBheW1lbnQgYXJlIGV4cGVjdGVkBQNuaWwDCQAAAgUCZloFAmZaBAJoaAkAkQMCCAUCZmQIcGF5bWVudHMAAAQCZnUIBQJoaAdhc3NldElkBAJmdAgFAmhoBmFtb3VudAQCZUoDCQAAAgUCZnUFAmJ6CQECZUMDCQC2AgEFAmZ0CQC2AgEAAAkAtgIBAAADCQAAAgUCZnUFAmJBCQECZUMDCQC2AgEAAAkAtgIBBQJmdAkAtgIBAAAJAQJiYQECHnBheW1lbnQgYXNzZXQgaXMgbm90IHN1cHBvcnRlZAMJAAACBQJlSgUCZUoEAmFiCAUCZmQGY2FsbGVyBAJhYwgFAmZkDXRyYW5zYWN0aW9uSWQEAmhpCQECZnMEBQJmdAUCZnUFAmFiBQJhYwMJAAACBQJoaQUCaGkEAmZ5CAUCaGkCXzUEAmhqCAUCaGkCXzQEAmZyCAUCaGkCXzMEAmV2CAUCaGkCXzIEAmhrCAUCaGkCXzEEAmhsAwMJAGYCBQJoZQAACQBmAgUCaGUFAmhrBwkBAmJhAQkAuQkCCQDMCAICH2Ftb3VudCB0byByZWNlaXZlIGlzIGxlc3MgdGhhbiAJAMwIAgkApAMBBQJoZQUDbmlsAgAFAmhrBAJmbgkBAmZtAQUCaGwDCQAAAgUCZm4FAmZuBAJnWAMFAmhmBAJobQkA/AcEBQJiRQIFc3Rha2UFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUCYnkFAmhsBQNuaWwDCQAAAgUCaG0FAmhtBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAmZkBmNhbGxlcgUCaGwFAmJ5BQNuaWwEAmhuAwkAZgIFAmZyAAAJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUCYmUFAmZyBQJmdQUDbmlsBQNuaWwEAmhvAwkAAAIFBHRoaXMFAmJlCQCUCgIAAAAAAwUCZnkJAJQKAgkBAS0BBQJmcgAACQCUCgIAAAkBAS0BBQJmcgQCZUwIBQJobwJfMQQCZU0IBQJobwJfMgQCaHAJAQJlSwMFAmVMBQJlTQAABAJnUAgFAmhwAl8xBAJlQggFAmhwAl8yBAJlVwkBBXZhbHVlAQkAoggBBQJhagQCaGEJAQJlUAIFAmVKBQJlQgMJAAACBQJoYQUCaGEEAmhiCQD8BwQFBHRoaXMCCXJlYmFsYW5jZQUDbmlsBQNuaWwDCQAAAgUCaGIFAmhiCQCUCgIJAM4IAgkAzggCCQDOCAIFAmV2BQJnWAUCaG4FAmdQBQJobAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJmZAERcHV0T25lVGtuUkVBRE9OTFkCAmZ1AmZ0BAJocQkBAmZzBAUCZnQJAQJicAEFAmZ1BQR1bml0BQR1bml0BAJoawgFAmhxAl8xBAJldggFAmhxAl8yBAJmcggFAmhxAl8zBAJoaggFAmhxAl80BAJmeQgFAmhxAl81CQCUCgIFA25pbAkAlQoDBQJoawUCZnIFAmhqAmZkAQlnZXRPbmVUa24CAmhyAmhlBAJoZwoAAmJnCQD8BwQFAmJkAihpc1Bvb2xPbmVUb2tlbk9wZXJhdGlvbnNEaXNhYmxlZFJFQURPTkxZCQDMCAIJAKUIAQUEdGhpcwUDbmlsBQNuaWwDCQABAgUCYmcCB0Jvb2xlYW4FAmJnCQACAQkArAICCQADAQUCYmcCHCBjb3VsZG4ndCBiZSBjYXN0IHRvIEJvb2xlYW4EAmZnAwkBASEBCQECYmoBCAUCZmQGY2FsbGVyAwMJAQJiawAGCQAAAgUCYngFAW4GBQJoZwcEAmZaCQDMCAIDAwkBASEBBQJmZwYJAQJndAEFAmZkBgkBAmJhAQIhZ2V0IG9wZXJhdGlvbiBpcyBibG9ja2VkIGJ5IGFkbWluCQDMCAIDCQAAAgkAkAMBCAUCZmQIcGF5bWVudHMAAQYJAQJiYQECHmV4YWN0bHkgMSBwYXltZW50IGFyZSBleHBlY3RlZAUDbmlsAwkAAAIFAmZaBQJmWgQCZlkJAQJicAEFAmhyBAJoaAkAkQMCCAUCZmQIcGF5bWVudHMAAAQCZnUIBQJoaAdhc3NldElkBAJmRwgFAmhoBmFtb3VudAQCZUoJAQJlQwMJALYCAQAACQC2AgEAAAkAtgIBAAADCQAAAgUCZUoFAmVKBAJhYggFAmZkBmNhbGxlcgQCYWMIBQJmZA10cmFuc2FjdGlvbklkBAJocwkBAmZYBQUCZlkFAmZHBQJmdQUCYWIFAmFjAwkAAAIFAmhzBQJocwQCZ2EIBQJocwJfNQQCaGoIBQJocwJfNAQCZnIIBQJocwJfMwQCZXYIBQJocwJfMgQCaHQIBQJocwJfMQQCY2gDAwkAZgIFAmhlAAAJAGYCBQJoZQUCaHQHCQECYmEBCQC5CQIJAMwIAgIfYW1vdW50IHRvIHJlY2VpdmUgaXMgbGVzcyB0aGFuIAkAzAgCCQCkAwEFAmhlBQNuaWwCAAUCaHQEAmh1CQD8BwQFAmJkAgRidXJuCQDMCAIFAmZHBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFAmZ1BQJmRwUDbmlsAwkAAAIFAmh1BQJodQQCZ1IJAQJjUgIFAmhyCQBkAgUCY2gJAJYDAQkAzAgCAAAJAMwIAgUCZnIFA25pbAQCaHYJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUCYWIFAmNoBQJmWQUDbmlsBAJobgMJAGYCBQJmcgAACQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFAmJlBQJmcgUCZlkFA25pbAUDbmlsBAJodwQCaHgDCQAAAgUEdGhpcwUCYmUAAAUCZnIDBQJnYQkAlAoCCQEBLQEJAGQCBQJjaAUCaHgAAAkAlAoCAAAJAQEtAQkAZAIFAmNoBQJoeAQCZUwIBQJodwJfMQQCZU0IBQJodwJfMgQCaHkJAQJlSwMFAmVMBQJlTQAABAJnUAgFAmh5Al8xBAJlQggFAmh5Al8yBAJoYQkBAmVQAgUCZUoFAmVCAwkAAAIFAmhhBQJoYQkAlAoCCQDOCAIJAM4IAgkAzggCCQDOCAIFAmV2BQJnUgUCaHYFAmhuBQJnUAUCY2gJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CZmQBEWdldE9uZVRrblJFQURPTkxZAgJmWQJmRwQCaHoJAQJmWAUJAQJicAEFAmZZBQJmRwUCYnkFBHVuaXQFBHVuaXQEAmh0CAUCaHoCXzEEAmV2CAUCaHoCXzIEAmZyCAUCaHoCXzMEAmhqCAUCaHoCXzQEAmdhCAUCaHoCXzUJAJQKAgUDbmlsCQCVCgMFAmh0BQJmcgUCaGoCZmQBE3Vuc3Rha2VBbmRHZXRPbmVUa24DAmhBAmhyAmhlBAJoZwoAAmJnCQD8BwQFAmJkAihpc1Bvb2xPbmVUb2tlbk9wZXJhdGlvbnNEaXNhYmxlZFJFQURPTkxZCQDMCAIJAKUIAQUEdGhpcwUDbmlsBQNuaWwDCQABAgUCYmcCB0Jvb2xlYW4FAmJnCQACAQkArAICCQADAQUCYmcCHCBjb3VsZG4ndCBiZSBjYXN0IHRvIEJvb2xlYW4EAmZnAwkBASEBCQECYmoBCAUCZmQGY2FsbGVyAwMJAQJiawAGCQAAAgUCYngFAW4GBQJoZwcEAmZaCQDMCAIDAwkBASEBBQJmZwYJAQJndAEFAmZkBgkBAmJhAQIhZ2V0IG9wZXJhdGlvbiBpcyBibG9ja2VkIGJ5IGFkbWluCQDMCAIDCQAAAgkAkAMBCAUCZmQIcGF5bWVudHMAAAYJAQJiYQECGG5vIHBheW1lbnRzIGFyZSBleHBlY3RlZAUDbmlsAwkAAAIFAmZaBQJmWgQCZlkJAQJicAEFAmhyBAJhYggFAmZkBmNhbGxlcgQCYWMIBQJmZA10cmFuc2FjdGlvbklkBAJlSgkBAmVDAwkAtgIBAAAJALYCAQAACQC2AgEAAAMJAAACBQJlSgUCZUoEAmhCCQD8BwQFAmJFAgd1bnN0YWtlCQDMCAIJANgEAQUCYnkJAMwIAgUCaEEFA25pbAUDbmlsAwkAAAIFAmhCBQJoQgQCaEMJAQJmWAUFAmZZBQJoQQUCYnkFAmFiBQJhYwMJAAACBQJoQwUCaEMEAmdhCAUCaEMCXzUEAmhqCAUCaEMCXzQEAmZyCAUCaEMCXzMEAmV2CAUCaEMCXzIEAmh0CAUCaEMCXzEEAmNoAwMJAGYCBQJoZQAACQBmAgUCaGUFAmh0BwkBAmJhAQkAuQkCCQDMCAICH2Ftb3VudCB0byByZWNlaXZlIGlzIGxlc3MgdGhhbiAJAMwIAgkApAMBBQJoZQUDbmlsAgAFAmh0BAJodQkA/AcEBQJiZAIEYnVybgkAzAgCBQJoQQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQJieQUCaEEFA25pbAMJAAACBQJodQUCaHUEAmdSCQECY1ICBQJocgkAZAIFAmNoCQCWAwEJAMwIAgAACQDMCAIFAmZyBQNuaWwEAmh2CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQJmZAZjYWxsZXIFAmNoBQJmWQUDbmlsBAJobgMJAGYCBQJmcgAACQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFAmJlBQJmcgUCZlkFA25pbAUDbmlsBAJoRAQCaHgDCQAAAgUEdGhpcwUCYmUAAAUCZnIDBQJnYQkAlAoCCQEBLQEJAGQCBQJjaAUCaHgAAAkAlAoCAAAJAQEtAQkAZAIFAmNoBQJoeAQCZUwIBQJoRAJfMQQCZU0IBQJoRAJfMgQCaEUJAQJlSwMFAmVMBQJlTQAABAJnUAgFAmhFAl8xBAJlQggFAmhFAl8yBAJoYQkBAmVQAgUCZUoFAmVCAwkAAAIFAmhhBQJoYQkAlAoCCQDOCAIJAM4IAgkAzggCCQDOCAIFAmV2BQJnUgUCaHYFAmhuBQJnUAUCY2gJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CZmQBA2dldAAEAmVnCQECZmMBBQJmZAQCZE0IBQJlZwJfMQQCZE4IBQJlZwJfMgQCZmYIBQJlZwJfMwQCZHYIBQJlZwJfNAQCZE8IBQJlZwJfNQQCZ1IJAQJjVwIFAmRNBQJkTgQCZUoJAQJlQwMJALYCAQAACQC2AgEAAAkAtgIBAAADCQAAAgUCZUoFAmVKBAJoRgkA/AcEBQJiZAIEYnVybgkAzAgCBQJmZgUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQJkdgUCZmYFA25pbAMJAAACBQJoRgUCaEYEAmhHCQECZUsDCQEBLQEFAmRNCQEBLQEFAmROAAAEAmdQCAUCaEcCXzEEAmVCCAUCaEcCXzIEAmhhCQECZVACBQJlSgUCZUIDCQAAAgUCaGEFAmhhCQDOCAIJAM4IAgUCZ1IFAmRPBQJnUAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJmZAEJZ2V0Tm9MZXNzAgJoSAJoSQQCZWcJAQJmYwEFAmZkBAJkTQgFAmVnAl8xBAJkTggFAmVnAl8yBAJmZggFAmVnAl8zBAJkdggFAmVnAl80BAJkTwgFAmVnAl81AwkAZgIFAmhIBQJkTQkAAgEJAKwCAgkArAICCQCsAgICHG5vTGVzc1RoZW5BbXRBc3NldCBmYWlsZWQ6ICAJAKQDAQUCZE0CAyA8IAkApAMBBQJoSAMJAGYCBQJoSQUCZE4JAAIBCQCsAgIJAKwCAgkArAICAh1ub0xlc3NUaGVuUHJpY2VBc3NldCBmYWlsZWQ6IAkApAMBBQJkTgIDIDwgCQCkAwEFAmhJBAJnUgkBAmNXAgUCZE0FAmROBAJlSgkBAmVDAwkAtgIBAAAJALYCAQAACQC2AgEAAAMJAAACBQJlSgUCZUoEAmhGCQD8BwQFAmJkAgRidXJuCQDMCAIFAmZmBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFAmR2BQJmZgUDbmlsAwkAAAIFAmhGBQJoRgQCaEoJAQJlSwMJAQEtAQUCZE0JAQEtAQUCZE4AAAQCZ1AIBQJoSgJfMQQCZUIIBQJoSgJfMgQCaGEJAQJlUAIFAmVKBQJlQgMJAAACBQJoYQUCaGEJAM4IAgkAzggCBQJnUgUCZE8FAmdQCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmZkAQ11bnN0YWtlQW5kR2V0AQJjaAQCaEsDCQECIT0CCQCQAwEIBQJmZAhwYXltZW50cwAACQACAQIYTm8gcGF5bWVudHMgYXJlIGV4cGVjdGVkBgMJAAACBQJoSwUCaEsEAmRrCQECYm0ABAJkeAkA2QQBCQCRAwIFAmRrBQFxBAJlSgkBAmVDAwkAtgIBAAAJALYCAQAACQC2AgEAAAMJAAACBQJlSgUCZUoEAmhCCQD8BwQFAmJFAgd1bnN0YWtlCQDMCAIJANgEAQUCZHgJAMwIAgUCY2gFA25pbAUDbmlsAwkAAAIFAmhCBQJoQgQCZWcJAQJkdAQJANgEAQgFAmZkDXRyYW5zYWN0aW9uSWQJANgEAQUCZHgFAmNoCAUCZmQGY2FsbGVyBAJkTQgFAmVnAl8xBAJkTggFAmVnAl8yBAJkQQkBDXBhcnNlSW50VmFsdWUBCAUCZWcCXzkEAmRPCAUCZWcDXzEwBAJnUgkBAmNXAgUCZE0FAmROBAJmZwMJAQEhAQkBAmJqAQgFAmZkBmNhbGxlcgMJAQJiawAGCQAAAgUCYngFAW4HBAJoTAMFAmZnCQACAQkArAICAixHZXQgb3BlcmF0aW9uIGlzIGJsb2NrZWQgYnkgYWRtaW4uIFN0YXR1cyA9IAkApAMBBQJkQQYDCQAAAgUCaEwFAmhMBAJoRgkA/AcEBQJiZAIEYnVybgkAzAgCBQJjaAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQJkeAUCY2gFA25pbAMJAAACBQJoRgUCaEYEAmhNCQECZUsDCQEBLQEFAmRNCQEBLQEFAmROAAAEAmdQCAUCaE0CXzEEAmVCCAUCaE0CXzIEAmhhCQECZVACBQJlSgUCZUIDCQAAAgUCaGEFAmhhCQDOCAIJAM4IAgUCZ1IFAmRPBQJnUAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJmZAETdW5zdGFrZUFuZEdldE5vTGVzcwMCaEECaE4CaEkEAmZnAwkBASEBCQECYmoBCAUCZmQGY2FsbGVyAwkBAmJrAAYJAAACBQJieAUBbgcEAmZaCQDMCAIDCQEBIQEFAmZnBgkAAgECIWdldCBvcGVyYXRpb24gaXMgYmxvY2tlZCBieSBhZG1pbgkAzAgCAwkAAAIJAJADAQgFAmZkCHBheW1lbnRzAAAGCQACAQIYbm8gcGF5bWVudHMgYXJlIGV4cGVjdGVkBQNuaWwDCQAAAgUCZloFAmZaBAJlSgkBAmVDAwkAtgIBAAAJALYCAQAACQC2AgEAAAMJAAACBQJlSgUCZUoEAmhCCQD8BwQFAmJFAgd1bnN0YWtlCQDMCAIJANgEAQUCYnkJAMwIAgUCaEEFA25pbAUDbmlsAwkAAAIFAmhCBQJoQgQCZWcJAQJkdAQJANgEAQgFAmZkDXRyYW5zYWN0aW9uSWQJANgEAQUCYnkFAmhBCAUCZmQGY2FsbGVyBAJkTQgFAmVnAl8xBAJkTggFAmVnAl8yBAJkTwgFAmVnA18xMAQCZ1IJAQJjVwIFAmRNBQJkTgQCaE8JAMwIAgMJAGcCBQJkTQUCaE4GCQACAQkAuQkCCQDMCAICLGFtb3VudCBhc3NldCBhbW91bnQgdG8gcmVjZWl2ZSBpcyBsZXNzIHRoYW4gCQDMCAIJAKQDAQUCaE4FA25pbAIACQDMCAIDCQBnAgUCZE4FAmhJBgkAAgEJALkJAgkAzAgCAitwcmljZSBhc3NldCBhbW91bnQgdG8gcmVjZWl2ZSBpcyBsZXNzIHRoYW4gCQDMCAIJAKQDAQUCaEkFA25pbAIABQNuaWwDCQAAAgUCaE8FAmhPBAJoRgkA/AcEBQJiZAIEYnVybgkAzAgCBQJoQQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQJieQUCaEEFA25pbAMJAAACBQJoRgUCaEYEAmhQCQECZUsDCQEBLQEFAmRNCQEBLQEFAmROAAAEAmdQCAUCaFACXzEEAmVCCAUCaFACXzIEAmhhCQECZVACBQJlSgUCZUIDCQAAAgUCaGEFAmhhCQDOCAIJAM4IAgUCZ1IFAmRPBQJnUAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJmZAEIYWN0aXZhdGUCAmhRAmhSAwkBAiE9AgkApQgBCAUCZmQGY2FsbGVyCQClCAEFAmJkCQACAQIScGVybWlzc2lvbnMgZGVuaWVkCQCUCgIJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAmFlAAUCaFEJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAmFmAAUCaFIFA25pbAIHc3VjY2VzcwJmZAEKcmVmcmVzaEtMcAAEAmhTCQELdmFsdWVPckVsc2UCCQCfCAEFAmFrAAAEAmhUAwkAZwIJAGUCBQZoZWlnaHQFAmhTBQJhbgUEdW5pdAkBAmJhAQkAuQkCCQDMCAIJAKQDAQUCYW4JAMwIAgIvIGJsb2NrcyBoYXZlIG5vdCBwYXNzZWQgc2luY2UgdGhlIHByZXZpb3VzIGNhbGwFA25pbAIAAwkAAAIFAmhUBQJoVAQCZVcJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAqAMBCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMFAmFqAgEwCQECYmMBAgtpbnZhbGlkIGtMcAQCaFUJAQJlSwMAAAAAAAAEAmhWCAUCaFUCXzEEAmVCCAUCaFUCXzIEAmVOAwkBAiE9AgUCZVcFAmVCBQJoVgkBAmJhAQISbm90aGluZyB0byByZWZyZXNoCQCUCgIFAmVOCQCmAwEFAmVCCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmZkARxnZXRQb29sQ29uZmlnV3JhcHBlclJFQURPTkxZAAkAlAoCBQNuaWwJAQJibQACZmQBHGdldEFjY0JhbGFuY2VXcmFwcGVyUkVBRE9OTFkBAmFwCQCUCgIFA25pbAkBAmJWAQUCYXACZmQBGWNhbGNQcmljZXNXcmFwcGVyUkVBRE9OTFkDAmRlAmRmAmRqBAJkcwkBAmRpAwUCZGUFAmRmBQJkagkAlAoCBQNuaWwJAMwIAgkApgMBCQCRAwIFAmRzAAAJAMwIAgkApgMBCQCRAwIFAmRzAAEJAMwIAgkApgMBCQCRAwIFAmRzAAIFA25pbAJmZAEUdG9YMThXcmFwcGVyUkVBRE9OTFkCAUUBRgkAlAoCBQNuaWwJAKYDAQkBAUQCBQFFBQFGAmZkARZmcm9tWDE4V3JhcHBlclJFQURPTkxZAgFJAUoJAJQKAgUDbmlsCQEBSAIJAKcDAQUBSQUBSgJmZAEeY2FsY1ByaWNlQmlnSW50V3JhcHBlclJFQURPTkxZAgJiWgJjYQkAlAoCBQNuaWwJAKYDAQkBAmJZAgkApwMBBQJiWgkApwMBBQJjYQJmZAEjZXN0aW1hdGVQdXRPcGVyYXRpb25XcmFwcGVyUkVBRE9OTFkJAmR1AmRRAmRSAmRTAmRUAmRVAmFiAmRWAmRXCQCUCgIFA25pbAkBAmRQCQUCZHUFAmRRBQJkUgUCZFMFAmRUBQJkVQUCYWIFAmRWBQJkVwJmZAEjZXN0aW1hdGVHZXRPcGVyYXRpb25XcmFwcGVyUkVBRE9OTFkEAmR1AmR2AmR3AmFiBAJlZwkBAmR0BAUCZHUFAmR2BQJkdwkBEUBleHRyTmF0aXZlKDEwNjIpAQUCYWIJAJQKAgUDbmlsCQCcCgoIBQJlZwJfMQgFAmVnAl8yCAUCZWcCXzMIBQJlZwJfNAgFAmVnAl81CAUCZWcCXzYIBQJlZwJfNwkApgMBCAUCZWcCXzgIBQJlZwJfOQgFAmVnA18xMAJmZAENc3RhdHNSRUFET05MWQAEAmRrCQECYm0ABAJkeAkA2QQBCQCRAwIFAmRrBQFxBAJoVwkAkQMCBQJkawUBcgQCaFgJAJEDAgUCZGsFAXMEAmRaCQCRAwIFAmRrBQF2BAJlYQkAkQMCBQJkawUBdwQCZGwJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJkawUBdAQCZG0JAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJkawUBdQQCaFkICQETdmFsdWVPckVycm9yTWVzc2FnZQIJAOwHAQUCZHgJAKwCAgkArAICAgZBc3NldCAJANgEAQUCZHgCDiBkb2Vzbid0IGV4aXN0CHF1YW50aXR5BAJoWgkBAmJWAQUCaFcEAmlhCQECYlYBBQJoWAQCaWIDCQAAAgUCaFkAAAkAzAgCBQFlCQDMCAIFAWUJAMwIAgUBZQUDbmlsCQECZGkDBQJoWgUCaWEFAmhZBAJkSAAABAJpYwkBAUgCCQCRAwIFAmliAAEFAWIEAmlkCQEBSAIJAJEDAgUCaWIAAgUBYgQCaWUJAQV2YWx1ZQEJAJoIAgUCYmQJAQJhRAEJAKUIAQUEdGhpcwkAlAoCBQNuaWwJALkJAgkAzAgCAg4lZCVkJWQlZCVkJWQlZAkAzAgCCQCkAwEFAmhaCQDMCAIJAKQDAQUCaWEJAMwIAgkApAMBBQJoWQkAzAgCCQCkAwEFAmRICQDMCAIJAKQDAQUCaWMJAMwIAgkApAMBBQJpZAkAzAgCCQCkAwEFAmllBQNuaWwFAWoCZmQBIGV2YWx1YXRlUHV0QnlBbW91bnRBc3NldFJFQURPTkxZAQJkUgQCZGsJAQJibQAEAmR4CQDZBAEJAJEDAgUCZGsFAXEEAmRYCQCRAwIFAmRrBQFyBAJkeQkA2QQBBQJkWAQCZFkJAJEDAgUCZGsFAXMEAmR6CQDZBAEFAmRZBAJkbAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmRrBQF0BAJkbQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmRrBQF1BAJkQQkAkQMCBQJkawUBcAQCaFkICQETdmFsdWVPckVycm9yTWVzc2FnZQIJAOwHAQUCZHgJAKwCAgkArAICAgZBc3NldCAJANgEAQUCZHgCDiBkb2Vzbid0IGV4aXN0CHF1YW50aXR5BAJoWgkBAmJWAQUCZFgEAmlhCQECYlYBBQJkWQQCZGcJAQFEAgUCaFoFAmRsBAJkaAkBAUQCBQJpYQUCZG0EAmRHAwkAAAIFAmhZAAAFAWUJAQJiWQIFAmRoBQJkZwQCZWQJAQFEAgUCZFIFAmRsBAJlZQkAvAIDBQJlZAUCZEcFAWQEAmRUCQEBSAIFAmVlBQJkbQQCZmsJAQJkUAkCAACgwh4FAmRSBQJkeQUCZFQFAmR6AgAGBwQCZW8IBQJmawJfMQQCaWYIBQJmawJfMwQCZEMIBQJmawJfNAQCZEUIBQJmawJfNQQCZEIIBQJmawJfNgkAlAoCBQNuaWwJALkJAgkAzAgCAhAlZCVkJWQlZCVkJWQlZCVkCQDMCAIJAKQDAQUCZW8JAMwIAgkApAMBCQEBSAIFAmRHBQFiCQDMCAIJAKQDAQUCZEMJAMwIAgkApAMBBQJkRQkAzAgCCQCkAwEFAmRCCQDMCAIFAmRBCQDMCAIJAKQDAQUCZFIJAMwIAgkApAMBBQJkVAUDbmlsBQFqAmZkAR9ldmFsdWF0ZVB1dEJ5UHJpY2VBc3NldFJFQURPTkxZAQJkVAQCZGsJAQJibQAEAmR4CQDZBAEJAJEDAgUCZGsFAXEEAmRYCQCRAwIFAmRrBQFyBAJkeQkA2QQBBQJkWAQCZFkJAJEDAgUCZGsFAXMEAmR6CQDZBAEFAmRZBAJkbAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmRrBQF0BAJkbQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmRrBQF1BAJkQQkAkQMCBQJkawUBcAQCaFkICQETdmFsdWVPckVycm9yTWVzc2FnZQIJAOwHAQUCZHgJAKwCAgkArAICAgZBc3NldCAJANgEAQUCZHgCDiBkb2Vzbid0IGV4aXN0CHF1YW50aXR5BAJpZwkBAmJWAQUCZFgEAmloCQECYlYBBQJkWQQCaWkJAQFEAgUCaWcFAmRsBAJpagkBAUQCBQJpaAUCZG0EAmRHAwkAAAIFAmhZAAAFAWUJAQJiWQIFAmlqBQJpaQQCZWUJAQFEAgUCZFQFAmRtBAJlZAkAvAIDBQJlZQUBZAUCZEcEAmRSCQEBSAIFAmVkBQJkbAQCZmsJAQJkUAkCAACgwh4FAmRSBQJkeQUCZFQFAmR6AgAGBwQCZW8IBQJmawJfMQQCaWYIBQJmawJfMwQCZEMIBQJmawJfNAQCZEUIBQJmawJfNQQCZEIIBQJmawJfNgkAlAoCBQNuaWwJALkJAgkAzAgCAhAlZCVkJWQlZCVkJWQlZCVkCQDMCAIJAKQDAQUCZW8JAMwIAgkApAMBCQEBSAIFAmRHBQFiCQDMCAIJAKQDAQUCZEMJAMwIAgkApAMBBQJkRQkAzAgCCQCkAwEFAmRCCQDMCAIFAmRBCQDMCAIJAKQDAQUCZFIJAMwIAgkApAMBBQJkVAUDbmlsBQFqAmZkARNldmFsdWF0ZUdldFJFQURPTkxZAgJpawJpbAQCZWcJAQJkdAQCAAUCaWsFAmlsBQR0aGlzBAJkTQgFAmVnAl8xBAJkTggFAmVnAl8yBAJkQwgFAmVnAl81BAJkRQgFAmVnAl82BAJkQggFAmVnAl83BAJkSAgFAmVnAl84BAJkQQkBDXBhcnNlSW50VmFsdWUBCAUCZWcCXzkJAJQKAgUDbmlsCQC5CQIJAMwIAgIOJWQlZCVkJWQlZCVkJWQJAMwIAgkApAMBBQJkTQkAzAgCCQCkAwEFAmROCQDMCAIJAKQDAQUCZEMJAMwIAgkApAMBBQJkRQkAzAgCCQCkAwEFAmRCCQDMCAIJAKYDAQUCZEgJAMwIAgkApAMBBQJkQQUDbmlsBQFqAQJpbQECaW4ABAJpbwQCYVEJAQJncgADCQABAgUCYVECCkJ5dGVWZWN0b3IEAmd1BQJhUQUCZ3UDCQABAgUCYVECBFVuaXQIBQJpbQ9zZW5kZXJQdWJsaWNLZXkJAAIBAgtNYXRjaCBlcnJvcgQCYVEFAmltAwkAAQIFAmFRAgVPcmRlcgQCZVMFAmFRBAJpcAkBAmJsAAQCaXEDCQECZU8ACQCUCgIGAgAJAQJlUgEFAmVTBAJhSwgFAmlxAl8xBAJhTAgFAmlxAl8yBAJhTQkA9AMDCAUCZVMJYm9keUJ5dGVzCQCRAwIIBQJlUwZwcm9vZnMAAAgFAmVTD3NlbmRlclB1YmxpY0tleQQCYU4JAPQDAwgFAmVTCWJvZHlCeXRlcwkAkQMCCAUCZVMGcHJvb2ZzAAEFAmlwAwMDBQJhSwUCYU0HBQJhTgcGCQECYUoEBQJhSwUCYUwFAmFNBQJhTgMJAAECBQJhUQIUU2V0U2NyaXB0VHJhbnNhY3Rpb24EAmFWBQJhUQMJAPQDAwgFAmltCWJvZHlCeXRlcwkAkQMCCAUCaW0GcHJvb2ZzAAAFAmlvBgQCaXIJAPYDAQkBBXZhbHVlAQgFAmFWBnNjcmlwdAQCaXMJANsEAQkBBXZhbHVlAQkAnQgCBQJiZAkBAmFGAAQCaXQJAPEHAQUEdGhpcwMJAAACBQJpcwUCaXIJAQIhPQIFAml0BQJpcgcJAPQDAwgFAmltCWJvZHlCeXRlcwkAkQMCCAUCaW0GcHJvb2ZzAAAFAmlv1lDrtA==", "height": 3997462, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: none Next: J7eyNHvgPT7B15WVruaUkuAXomnUr9PHG4xRveWkEsnq 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 keyManagerPublicKey () = "%s__managerPublicKey"
94+
95+
96+func keyManagerVaultAddress () = "%s__managerVaultAddress"
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 keyAdditionalBalance (assetId) = makeString(["%s%s", "stakedBalance", assetId], SEP)
134+
135+
136+func keyStakingAssetBalance (assetId) = makeString(["%s%s", "shareAssetBalance", assetId], SEP)
137+
138+
139+func getAdditionalBalanceOrZero (assetId) = valueOrElse(getInteger(this, keyAdditionalBalance(assetId)), 0)
140+
141+
142+func getStakingAssetBalanceOrZero (assetId) = valueOrElse(getInteger(this, keyStakingAssetBalance(assetId)), 0)
143+
144+
145+func keyFactoryConfig () = "%s__factoryConfig"
146+
147+
148+func keyMatcherPub () = "%s%s__matcher__publicKey"
149+
150+
151+func keyMappingPoolContractAddressToPoolAssets (poolContractAddress) = (("%s%s%s__" + poolContractAddress) + "__mappings__poolContract2LpAsset")
152+
153+
154+func keyPoolConfig (iAmtAsset,iPriceAsset) = (((("%d%d%s__" + iAmtAsset) + "__") + iPriceAsset) + "__config")
155+
156+
157+func keyMappingsBaseAsset2internalId (baseAssetStr) = ("%s%s%s__mappings__baseAsset2internalId__" + baseAssetStr)
158+
159+
160+func keyAllPoolsShutdown () = "%s__shutdown"
161+
162+
163+func keyPoolWeight (contractAddress) = ("%s%s__poolWeight__" + contractAddress)
164+
165+
166+func keyAllowedLpScriptHash () = "%s__allowedLpScriptHash"
167+
168+
169+let keyFeeCollectorAddress = "%s__feeCollectorAddress"
170+
171+func keySkipOrderValidation (poolAddress) = ("%s%s__skipOrderValidation__" + poolAddress)
172+
173+
174+func throwOrderError (orderValid,orderValidInfo,senderValid,matcherValid) = throw((((((((("order validation failed: orderValid=" + toString(orderValid)) + " (") + orderValidInfo) + ")") + " senderValid=") + toString(senderValid)) + " matcherValid=") + toString(matcherValid)))
175+
176+
177+func addressFromStringOrThis (addressString) = match addressFromString(addressString) {
178+ case a: Address =>
179+ a
180+ case _ =>
181+ this
182+}
183+
184+
185+func getManagerVaultAddressOrThis () = {
186+ let factoryAddress = match getString(fc()) {
187+ case fca: String =>
188+ addressFromStringOrThis(fca)
189+ case _ =>
190+ this
191+ }
192+ match getString(factoryAddress, keyManagerVaultAddress()) {
193+ case s: String =>
194+ addressFromStringOrThis(s)
195+ case _ =>
196+ this
197+ }
198+ }
199+
200+
201+func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
202+
203+
204+func getIntOrFail (address,key) = valueOrErrorMessage(getInteger(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
205+
206+
207+func throwErr (msg) = throw(makeString(["lp.ride:", msg], " "))
208+
209+
210+func fmtErr (msg) = makeString(["lp.ride:", msg], " ")
211+
212+
213+let factoryContract = addressFromStringValue(getStringOrFail(this, fc()))
214+
215+let feeCollectorAddress = addressFromStringValue(getStringOrFail(factoryContract, keyFeeCollectorAddress))
216+
217+let inFee = {
218+ let @ = invoke(factoryContract, "getInFeeREADONLY", [toString(this)], nil)
219+ if ($isInstanceOf(@, "Int"))
220+ then @
221+ else throw(($getType(@) + " couldn't be cast to Int"))
222+ }
223+
224+let outFee = {
225+ let @ = invoke(factoryContract, "getOutFeeREADONLY", [toString(this)], nil)
226+ if ($isInstanceOf(@, "Int"))
227+ then @
228+ else throw(($getType(@) + " couldn't be cast to Int"))
229+ }
230+
231+func keyAddressWhitelisted (address) = makeString(["%s%s", "whitelisted", toString(address)], SEP)
232+
233+
234+func isAddressWhitelisted (address) = valueOrElse(getBoolean(factoryContract, keyAddressWhitelisted(address)), false)
235+
236+
237+func isGlobalShutdown () = valueOrElse(getBoolean(factoryContract, keyAllPoolsShutdown()), false)
238+
239+
240+func getMatcherPubOrFail () = fromBase58String(getStringOrFail(factoryContract, keyMatcherPub()))
241+
242+
243+func getPoolConfig () = {
244+ let amtAsset = getStringOrFail(this, aa())
245+ let priceAsset = getStringOrFail(this, pa())
246+ let iPriceAsset = getIntOrFail(factoryContract, keyMappingsBaseAsset2internalId(priceAsset))
247+ let iAmtAsset = getIntOrFail(factoryContract, keyMappingsBaseAsset2internalId(amtAsset))
248+ split(getStringOrFail(factoryContract, keyPoolConfig(toString(iAmtAsset), toString(iPriceAsset))), SEP)
249+ }
250+
251+
252+func parseAssetId (input) = if ((input == wavesString))
253+ then unit
254+ else fromBase58String(input)
255+
256+
257+func assetIdToString (input) = if ((input == unit))
258+ then wavesString
259+ else toBase58String(value(input))
260+
261+
262+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]))
263+
264+
265+let poolConfigParsed = parsePoolConfig(getPoolConfig())
266+
267+let $t097699935 = poolConfigParsed
268+
269+let cfgPoolAddress = $t097699935._1
270+
271+let cfgPoolStatus = $t097699935._2
272+
273+let cfgLpAssetId = $t097699935._3
274+
275+let cfgAmountAssetId = $t097699935._4
276+
277+let cfgPriceAssetId = $t097699935._5
278+
279+let cfgAmountAssetDecimals = $t097699935._6
280+
281+let cfgPriceAssetDecimals = $t097699935._7
282+
283+func getFactoryConfig () = split(getStringOrFail(factoryContract, keyFactoryConfig()), SEP)
284+
285+
286+let stakingContract = valueOrErrorMessage(addressFromString(getFactoryConfig()[idxFactoryStakingContract]), "incorrect staking address")
287+
288+let slippageContract = valueOrErrorMessage(addressFromString(getFactoryConfig()[idxFactorySlippageContract]), "incorrect staking address")
289+
290+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)
291+
292+
293+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)
294+
295+
296+func getAccBalance (assetId) = {
297+ let balanceOnPool = if ((assetId == "WAVES"))
298+ then wavesBalance(this).available
299+ else assetBalance(this, fromBase58String(assetId))
300+ let totalBalance = ((balanceOnPool + getAdditionalBalanceOrZero(assetId)) - getStakingAssetBalanceOrZero(assetId))
301+ max([0, totalBalance])
302+ }
303+
304+
305+func calcPriceBigInt (prAmtX18,amAmtX18) = fraction(prAmtX18, scale18, amAmtX18)
306+
307+
308+func calcPriceBigIntRound (prAmtX18,amAmtX18,round) = fraction(prAmtX18, scale18, amAmtX18, round)
309+
310+
311+func getRate (proxy) = {
312+ let inv = invoke(proxy, "getRate", nil, nil)
313+ if ((inv == inv))
314+ then match inv {
315+ case r: Int =>
316+ r
317+ case _ =>
318+ throwErr("proxy.getRate() unexpected value")
319+ }
320+ else throw("Strict value is not equal to itself.")
321+ }
322+
323+
324+func deposit (assetId,amount,stakingAssetId,proxy) = {
325+ let currentAdditionalBalance = getAdditionalBalanceOrZero(assetId)
326+ if ((currentAdditionalBalance == currentAdditionalBalance))
327+ then {
328+ let currentStakingAssetBalance = getStakingAssetBalanceOrZero(stakingAssetId)
329+ if ((currentStakingAssetBalance == currentStakingAssetBalance))
330+ then {
331+ let asset = parseAssetId(assetId)
332+ if ((amount > 0))
333+ then {
334+ let depositInvoke = invoke(proxy, "deposit", nil, [AttachedPayment(asset, amount)])
335+ if ((depositInvoke == depositInvoke))
336+ then match depositInvoke {
337+ case receivedStakingAsset: Int =>
338+ let newAdditionalBalance = (currentAdditionalBalance + amount)
339+ let newStakingAssetBalance = (currentStakingAssetBalance + receivedStakingAsset)
340+[IntegerEntry(keyAdditionalBalance(assetId), newAdditionalBalance), IntegerEntry(keyStakingAssetBalance(stakingAssetId), newStakingAssetBalance)]
341+ case _ =>
342+ nil
343+ }
344+ else throw("Strict value is not equal to itself.")
345+ }
346+ else nil
347+ }
348+ else throw("Strict value is not equal to itself.")
349+ }
350+ else throw("Strict value is not equal to itself.")
351+ }
352+
353+
354+func withdraw (assetId,amount,stakingAssetId,proxy,proxyRateMul,profitAddress) = {
355+ let currentAdditionalBalance = getAdditionalBalanceOrZero(assetId)
356+ if ((currentAdditionalBalance == currentAdditionalBalance))
357+ then {
358+ let currentStakingAssetBalance = getStakingAssetBalanceOrZero(stakingAssetId)
359+ if ((currentStakingAssetBalance == currentStakingAssetBalance))
360+ then {
361+ let currentProxyRate = getRate(proxy)
362+ if ((currentProxyRate == currentProxyRate))
363+ then {
364+ let oldRate = fraction(proxyRateMul, currentAdditionalBalance, currentStakingAssetBalance)
365+ let stakingAsset = parseAssetId(stakingAssetId)
366+ let oldSendStakingAmount = fraction(proxyRateMul, amount, oldRate)
367+ let sendStakingAssetAmount = fraction(proxyRateMul, amount, currentProxyRate)
368+ let profitAmount = max([0, (oldSendStakingAmount - sendStakingAssetAmount)])
369+ if ((sendStakingAssetAmount > 0))
370+ then {
371+ let withdrawInvoke = invoke(proxy, "withdraw", nil, [AttachedPayment(stakingAsset, sendStakingAssetAmount)])
372+ if ((withdrawInvoke == withdrawInvoke))
373+ then match withdrawInvoke {
374+ case receivedAssets: Int =>
375+ let newAdditionalBalance = (currentAdditionalBalance - receivedAssets)
376+ let newStakingAssetBalance = ((currentStakingAssetBalance - sendStakingAssetAmount) - profitAmount)
377+[IntegerEntry(keyAdditionalBalance(assetId), newAdditionalBalance), IntegerEntry(keyStakingAssetBalance(stakingAssetId), newStakingAssetBalance), ScriptTransfer(profitAddress, profitAmount, parseAssetId(stakingAssetId))]
378+ case _ =>
379+ nil
380+ }
381+ else throw("Strict value is not equal to itself.")
382+ }
383+ else nil
384+ }
385+ else throw("Strict value is not equal to itself.")
386+ }
387+ else throw("Strict value is not equal to itself.")
388+ }
389+ else throw("Strict value is not equal to itself.")
390+ }
391+
392+
393+func getLeaseProxyConfig (assetId) = match invoke(factoryContract, "getPoolLeaseConfigREADONLY", [toString(this), assetId], nil) {
394+ case a: (Boolean, Int, Int, String, String, Int, String) =>
395+ a
396+ case _ =>
397+ throwErr((("[" + assetId) + "] getLeaseProxyConfig() error"))
398+}
399+
400+
401+func rebalanceInternal (targetRatio,assetId,stakingAssetId,minBalance,proxy,proxyRateMul,profitAddress) = {
402+ let currentAdditionalBalance = getAdditionalBalanceOrZero(assetId)
403+ if ((currentAdditionalBalance == currentAdditionalBalance))
404+ then {
405+ let currentStakingAssetBalance = getStakingAssetBalanceOrZero(stakingAssetId)
406+ if ((currentStakingAssetBalance == currentStakingAssetBalance))
407+ then {
408+ let leasableTotalBalance = max([0, (getAccBalance(assetId) - minBalance)])
409+ let targetAdditionalBalance = fraction(targetRatio, leasableTotalBalance, 100)
410+ let diff = (currentAdditionalBalance - targetAdditionalBalance)
411+ if ((diff == 0))
412+ then nil
413+ else if ((0 > diff))
414+ then {
415+ let sendAssetAmount = -(diff)
416+ deposit(assetId, sendAssetAmount, stakingAssetId, proxy)
417+ }
418+ else {
419+ let getAssetAmount = diff
420+ withdraw(assetId, getAssetAmount, stakingAssetId, proxy, proxyRateMul, profitAddress)
421+ }
422+ }
423+ else throw("Strict value is not equal to itself.")
424+ }
425+ else throw("Strict value is not equal to itself.")
426+ }
427+
428+
429+func rebalanceAsset (assetId) = {
430+ let $t01617116307 = getLeaseProxyConfig(assetId)
431+ let isLeasable = $t01617116307._1
432+ let leasedRatio = $t01617116307._2
433+ let minBalance = $t01617116307._3
434+ let proxyAddress = $t01617116307._4
435+ let proxyAssetId = $t01617116307._5
436+ let proxyRateMul = $t01617116307._6
437+ let stakingProfitAddress = $t01617116307._7
438+ if (isLeasable)
439+ then rebalanceInternal(leasedRatio, assetId, proxyAssetId, minBalance, addressFromStringValue(proxyAddress), proxyRateMul, addressFromStringValue(stakingProfitAddress))
440+ else nil
441+ }
442+
443+
444+func withdrawAndRebalanceAsset (assetId,getAmount) = {
445+ let $t01670616842 = getLeaseProxyConfig(assetId)
446+ let isLeasable = $t01670616842._1
447+ let leasedRatio = $t01670616842._2
448+ let minBalance = $t01670616842._3
449+ let proxyAddress = $t01670616842._4
450+ let proxyAssetId = $t01670616842._5
451+ let proxyRateMul = $t01670616842._6
452+ let stakingProfitAddress = $t01670616842._7
453+ if (isLeasable)
454+ then {
455+ let newTotalLeasableBalance = max([0, ((getAccBalance(assetId) - getAmount) - minBalance)])
456+ if ((newTotalLeasableBalance == newTotalLeasableBalance))
457+ then {
458+ let newAdditionalBalance = fraction(leasedRatio, newTotalLeasableBalance, 100)
459+ if ((newAdditionalBalance == newAdditionalBalance))
460+ then {
461+ let withdrawAmount = (getAdditionalBalanceOrZero(assetId) - newAdditionalBalance)
462+ if ((withdrawAmount == withdrawAmount))
463+ then if ((0 > withdrawAmount))
464+ then deposit(assetId, -(withdrawAmount), proxyAssetId, addressFromStringValue(proxyAddress))
465+ else withdraw(assetId, withdrawAmount, proxyAssetId, addressFromStringValue(proxyAddress), proxyRateMul, addressFromStringValue(stakingProfitAddress))
466+ else throw("Strict value is not equal to itself.")
467+ }
468+ else throw("Strict value is not equal to itself.")
469+ }
470+ else throw("Strict value is not equal to itself.")
471+ }
472+ else nil
473+ }
474+
475+
476+func withdrawAndRebalanceAll (amountAssetOutAmount,priceAssetOutAmount) = {
477+ let AmAmtWithdrawState = withdrawAndRebalanceAsset(getStringOrFail(this, aa()), amountAssetOutAmount)
478+ let PrAmtWithdrawState = withdrawAndRebalanceAsset(getStringOrFail(this, pa()), priceAssetOutAmount)
479+ (AmAmtWithdrawState ++ PrAmtWithdrawState)
480+ }
481+
482+
483+func privateCalcPrice (amAssetDcm,prAssetDcm,amAmt,prAmt) = {
484+ let amtAssetAmtX18 = toX18(amAmt, amAssetDcm)
485+ let priceAssetAmtX18 = toX18(prAmt, prAssetDcm)
486+ calcPriceBigInt(priceAssetAmtX18, amtAssetAmtX18)
487+ }
488+
489+
490+func calcPrices (amAmt,prAmt,lpAmt) = {
491+ let cfg = getPoolConfig()
492+ let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
493+ let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
494+ let priceX18 = privateCalcPrice(amtAssetDcm, priceAssetDcm, amAmt, prAmt)
495+ let amAmtX18 = toX18(amAmt, amtAssetDcm)
496+ let prAmtX18 = toX18(prAmt, priceAssetDcm)
497+ let lpAmtX18 = toX18(lpAmt, scale8)
498+ let lpPriceInAmAssetX18 = calcPriceBigInt(amAmtX18, lpAmtX18)
499+ let lpPriceInPrAssetX18 = calcPriceBigInt(prAmtX18, lpAmtX18)
500+[priceX18, lpPriceInAmAssetX18, lpPriceInPrAssetX18]
501+ }
502+
503+
504+func calculatePrices (amAmt,prAmt,lpAmt) = {
505+ let prices = calcPrices(amAmt, prAmt, lpAmt)
506+[fromX18(prices[0], scale8), fromX18(prices[1], scale8), fromX18(prices[2], scale8)]
507+ }
508+
509+
510+func estimateGetOperation (txId58,pmtAssetId,pmtLpAmt,userAddress) = {
511+ let cfg = getPoolConfig()
512+ let lpAssetId = cfg[idxPoolLPAssetId]
513+ let amAssetId = cfg[idxAmtAssetId]
514+ let prAssetId = cfg[idxPriceAssetId]
515+ let amAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
516+ let prAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
517+ let poolStatus = cfg[idxPoolStatus]
518+ let lpEmission = valueOrErrorMessage(assetInfo(fromBase58String(lpAssetId)), (("Asset " + lpAssetId) + " doesn't exist")).quantity
519+ if ((lpAssetId != pmtAssetId))
520+ then throw("Invalid asset passed.")
521+ else {
522+ let amBalance = getAccBalance(amAssetId)
523+ let amBalanceX18 = toX18(amBalance, amAssetDcm)
524+ let prBalance = getAccBalance(prAssetId)
525+ let prBalanceX18 = toX18(prBalance, prAssetDcm)
526+ let curPriceX18 = calcPriceBigInt(prBalanceX18, amBalanceX18)
527+ let curPrice = fromX18(curPriceX18, scale8)
528+ let pmtLpAmtX18 = toX18(pmtLpAmt, scale8)
529+ let lpEmissionX18 = toX18(lpEmission, scale8)
530+ let outAmAmtX18 = fraction(amBalanceX18, pmtLpAmtX18, lpEmissionX18)
531+ let outPrAmtX18 = fraction(prBalanceX18, pmtLpAmtX18, lpEmissionX18)
532+ let outAmAmt = fromX18Round(outAmAmtX18, amAssetDcm, FLOOR)
533+ let outPrAmt = fromX18Round(outPrAmtX18, prAssetDcm, FLOOR)
534+ let state = if ((txId58 == ""))
535+ then nil
536+ else [ScriptTransfer(userAddress, outAmAmt, if ((amAssetId == "WAVES"))
537+ then unit
538+ else fromBase58String(amAssetId)), ScriptTransfer(userAddress, outPrAmt, if ((prAssetId == "WAVES"))
539+ then unit
540+ 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)]
541+ $Tuple10(outAmAmt, outPrAmt, amAssetId, prAssetId, amBalance, prBalance, lpEmission, curPriceX18, poolStatus, state)
542+ }
543+ }
544+
545+
546+func estimatePutOperation (txId58,slippageTolerance,inAmAssetAmt,inAmAssetId,inPrAssetAmt,inPrAssetId,userAddress,isEvaluate,emitLp) = {
547+ let cfg = getPoolConfig()
548+ let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
549+ let amAssetIdStr = cfg[idxAmtAssetId]
550+ let prAssetIdStr = cfg[idxPriceAssetId]
551+ let iAmtAssetId = cfg[idxIAmtAssetId]
552+ let iPriceAssetId = cfg[idxIPriceAssetId]
553+ let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
554+ let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
555+ let poolStatus = cfg[idxPoolStatus]
556+ let lpEmission = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
557+ let inAmAssetIdStr = toBase58String(valueOrElse(inAmAssetId, fromBase58String("WAVES")))
558+ let inPrAssetIdStr = toBase58String(valueOrElse(inPrAssetId, fromBase58String("WAVES")))
559+ if (if ((amAssetIdStr != inAmAssetIdStr))
560+ then true
561+ else (prAssetIdStr != inPrAssetIdStr))
562+ then throw("Invalid amt or price asset passed.")
563+ else {
564+ let amBalance = if (isEvaluate)
565+ then getAccBalance(amAssetIdStr)
566+ else (getAccBalance(amAssetIdStr) - inAmAssetAmt)
567+ let prBalance = if (isEvaluate)
568+ then getAccBalance(prAssetIdStr)
569+ else (getAccBalance(prAssetIdStr) - inPrAssetAmt)
570+ let inAmAssetAmtX18 = toX18(inAmAssetAmt, amtAssetDcm)
571+ let inPrAssetAmtX18 = toX18(inPrAssetAmt, priceAssetDcm)
572+ let userPriceX18 = calcPriceBigInt(inPrAssetAmtX18, inAmAssetAmtX18)
573+ let amBalanceX18 = toX18(amBalance, amtAssetDcm)
574+ let prBalanceX18 = toX18(prBalance, priceAssetDcm)
575+ let res = if ((lpEmission == 0))
576+ then {
577+ let curPriceX18 = zeroBigInt
578+ let slippageX18 = zeroBigInt
579+ let lpAmtX18 = pow((inAmAssetAmtX18 * inPrAssetAmtX18), 0, toBigInt(5), 1, 0, DOWN)
580+ $Tuple5(fromX18(lpAmtX18, scale8), fromX18(inAmAssetAmtX18, amtAssetDcm), fromX18(inPrAssetAmtX18, priceAssetDcm), calcPriceBigInt((prBalanceX18 + inPrAssetAmtX18), (amBalanceX18 + inAmAssetAmtX18)), slippageX18)
581+ }
582+ else {
583+ let curPriceX18 = calcPriceBigInt(prBalanceX18, amBalanceX18)
584+ let slippageX18 = fraction(absBigInt((curPriceX18 - userPriceX18)), scale18, curPriceX18)
585+ let slippageToleranceX18 = toX18(slippageTolerance, scale8)
586+ if (if ((curPriceX18 != zeroBigInt))
587+ then (slippageX18 > slippageToleranceX18)
588+ else false)
589+ then throw(((("Price slippage " + toString(slippageX18)) + " exceeded the passed limit of ") + toString(slippageToleranceX18)))
590+ else {
591+ let lpEmissionX18 = toX18(lpEmission, scale8)
592+ let prViaAmX18 = fraction(inAmAssetAmtX18, calcPriceBigIntRound(prBalanceX18, amBalanceX18, CEILING), scale18, CEILING)
593+ let amViaPrX18 = fraction(inPrAssetAmtX18, scale18, calcPriceBigIntRound(prBalanceX18, amBalanceX18, FLOOR), CEILING)
594+ let expectedAmts = if ((prViaAmX18 > inPrAssetAmtX18))
595+ then $Tuple2(amViaPrX18, inPrAssetAmtX18)
596+ else $Tuple2(inAmAssetAmtX18, prViaAmX18)
597+ let expAmtAssetAmtX18 = expectedAmts._1
598+ let expPriceAssetAmtX18 = expectedAmts._2
599+ let lpAmtX18 = fraction(lpEmissionX18, expPriceAssetAmtX18, prBalanceX18, FLOOR)
600+ $Tuple5(fromX18Round(lpAmtX18, scale8, FLOOR), fromX18Round(expAmtAssetAmtX18, amtAssetDcm, CEILING), fromX18Round(expPriceAssetAmtX18, priceAssetDcm, CEILING), curPriceX18, slippageX18)
601+ }
602+ }
603+ let calcLpAmt = res._1
604+ let calcAmAssetPmt = res._2
605+ let calcPrAssetPmt = res._3
606+ let curPrice = fromX18(res._4, scale8)
607+ let slippageCalc = fromX18(res._5, scale8)
608+ if ((0 >= calcLpAmt))
609+ then throw("Invalid calculations. LP calculated is less than zero.")
610+ else {
611+ let emitLpAmt = if (!(emitLp))
612+ then 0
613+ else calcLpAmt
614+ let amDiff = (inAmAssetAmt - calcAmAssetPmt)
615+ let prDiff = (inPrAssetAmt - calcPrAssetPmt)
616+ 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))]
617+ $Tuple13(calcLpAmt, emitLpAmt, curPrice, amBalance, prBalance, lpEmission, lpAssetId, poolStatus, commonState, amDiff, prDiff, inAmAssetId, inPrAssetId)
618+ }
619+ }
620+ }
621+
622+
623+func calcKLp (amountBalance,priceBalance,lpEmission) = {
624+ let amountBalanceX18 = toX18BigInt(amountBalance, toBigInt(cfgAmountAssetDecimals))
625+ let priceBalanceX18 = toX18BigInt(priceBalance, toBigInt(cfgPriceAssetDecimals))
626+ let updatedKLp = fraction(pow((amountBalanceX18 * priceBalanceX18), 0, toBigInt(5), 1, 18, DOWN), big1, lpEmission)
627+ if ((lpEmission == big0))
628+ then big0
629+ else updatedKLp
630+ }
631+
632+
633+func calcCurrentKLp (amountAssetDelta,priceAssetDelta,lpAssetEmissionDelta) = {
634+ let amountAssetBalance = (toBigInt(getAccBalance(assetIdToString(cfgAmountAssetId))) - amountAssetDelta)
635+ let priceAssetBalance = (toBigInt(getAccBalance(assetIdToString(cfgPriceAssetId))) - priceAssetDelta)
636+ let lpAssetEmission = (toBigInt(value(assetInfo(cfgLpAssetId)).quantity) - lpAssetEmissionDelta)
637+ let currentKLp = calcKLp(amountAssetBalance, priceAssetBalance, lpAssetEmission)
638+ currentKLp
639+ }
640+
641+
642+func refreshKLpInternal (amountAssetBalanceDelta,priceAssetBalanceDelta,lpAssetEmissionDelta) = {
643+ let amountAssetBalance = (getAccBalance(assetIdToString(cfgAmountAssetId)) + amountAssetBalanceDelta)
644+ let priceAssetBalance = (getAccBalance(assetIdToString(cfgPriceAssetId)) + priceAssetBalanceDelta)
645+ let lpAssetEmission = (value(assetInfo(cfgLpAssetId)).quantity + lpAssetEmissionDelta)
646+ let updatedKLp = calcKLp(toBigInt(amountAssetBalance), toBigInt(priceAssetBalance), toBigInt(lpAssetEmission))
647+ let actions = [IntegerEntry(keyKLpRefreshedHeight, height), StringEntry(keyKLp, toString(updatedKLp))]
648+ $Tuple2(actions, updatedKLp)
649+ }
650+
651+
652+func skipOrderValidation () = valueOrElse(getBoolean(factoryContract, keySkipOrderValidation(toString(this))), false)
653+
654+
655+func validateUpdatedKLp (oldKLp,updatedKLp) = if ((updatedKLp >= oldKLp))
656+ then true
657+ else throwErr(makeString(["updated KLp lower than current KLp", toString(oldKLp), toString(updatedKLp)], " "))
658+
659+
660+func validateMatcherOrderAllowed (order) = {
661+ let amountAssetBalance = getAccBalance(assetIdToString(cfgAmountAssetId))
662+ let priceAssetBalance = getAccBalance(assetIdToString(cfgPriceAssetId))
663+ let amountAssetAmount = order.amount
664+ let priceAssetAmount = fraction(order.amount, order.price, scale8, FLOOR)
665+ let $t02923129443 = if ((order.orderType == Buy))
666+ then $Tuple2(amountAssetAmount, -(priceAssetAmount))
667+ else $Tuple2(-(amountAssetAmount), priceAssetAmount)
668+ let amountAssetBalanceDelta = $t02923129443._1
669+ let priceAssetBalanceDelta = $t02923129443._2
670+ if (if (if (isGlobalShutdown())
671+ then true
672+ else (cfgPoolStatus == PoolMatcherDisabled))
673+ then true
674+ else (cfgPoolStatus == PoolShutdown))
675+ then throw("Exchange operations disabled")
676+ else if (if ((order.assetPair.amountAsset != cfgAmountAssetId))
677+ then true
678+ else (order.assetPair.priceAsset != cfgPriceAssetId))
679+ then throw("Wrong order assets.")
680+ else {
681+ let kLp = valueOrErrorMessage(parseBigInt(valueOrElse(getString(this, keyKLp), "0")), fmtErr("invalid kLp"))
682+ let $t02988329983 = refreshKLpInternal(amountAssetBalanceDelta, priceAssetBalanceDelta, 0)
683+ let unusedActions = $t02988329983._1
684+ let kLpNew = $t02988329983._2
685+ let isOrderValid = (kLpNew >= kLp)
686+ let info = makeString(["kLp=", toString(kLp), " kLpNew=", toString(kLpNew), " amountAssetBalance=", toString(amountAssetBalance), " priceAssetBalance=", toString(priceAssetBalance), " amountAssetBalanceDelta=", toString(amountAssetBalanceDelta), " priceAssetBalanceDelta=", toString(priceAssetBalanceDelta), " height=", toString(height)], "")
687+ $Tuple2(isOrderValid, info)
688+ }
689+ }
690+
691+
692+func commonGet (i) = if ((size(i.payments) != 1))
693+ then throw("exactly 1 payment is expected")
694+ else {
695+ let pmt = value(i.payments[0])
696+ let pmtAssetId = value(pmt.assetId)
697+ let pmtAmt = pmt.amount
698+ let res = estimateGetOperation(toBase58String(i.transactionId), toBase58String(pmtAssetId), pmtAmt, i.caller)
699+ let outAmAmt = res._1
700+ let outPrAmt = res._2
701+ let state = res._10
702+ let isGetDisabled = if (!(isAddressWhitelisted(i.caller)))
703+ then if (isGlobalShutdown())
704+ then true
705+ else (cfgPoolStatus == PoolShutdown)
706+ else false
707+ if (isGetDisabled)
708+ then throw(("Get operation is blocked by admin. Status = " + toString(cfgPoolStatus)))
709+ else $Tuple5(outAmAmt, outPrAmt, pmtAmt, pmtAssetId, state)
710+ }
711+
712+
713+func commonPut (i,slippageTolerance,emitLp) = if ((size(i.payments) != 2))
714+ then throw("exactly 2 payments are expected")
715+ else {
716+ let amAssetPmt = value(i.payments[0])
717+ let prAssetPmt = value(i.payments[1])
718+ let estPut = estimatePutOperation(toBase58String(i.transactionId), slippageTolerance, amAssetPmt.amount, amAssetPmt.assetId, prAssetPmt.amount, prAssetPmt.assetId, toString(i.caller), false, emitLp)
719+ let isPutDisabled = if (!(isAddressWhitelisted(i.caller)))
720+ then if (if (isGlobalShutdown())
721+ then true
722+ else (cfgPoolStatus == PoolPutDisabled))
723+ then true
724+ else (cfgPoolStatus == PoolShutdown)
725+ else false
726+ if (isPutDisabled)
727+ then throw(("Put operation is blocked by admin. Status = " + toString(cfgPoolStatus)))
728+ else estPut
729+ }
730+
731+
732+func emit (amount) = {
733+ let emitInv = invoke(factoryContract, "emit", [amount], nil)
734+ if ((emitInv == emitInv))
735+ then {
736+ let emitInvLegacy = match emitInv {
737+ case legacyFactoryContract: Address =>
738+ invoke(legacyFactoryContract, "emit", [amount], nil)
739+ case _ =>
740+ unit
741+ }
742+ if ((emitInvLegacy == emitInvLegacy))
743+ then amount
744+ else throw("Strict value is not equal to itself.")
745+ }
746+ else throw("Strict value is not equal to itself.")
747+ }
748+
749+
750+func takeFee (amount,fee) = {
751+ let feeAmount = if ((fee == 0))
752+ then 0
753+ else fraction(amount, fee, scale8)
754+ $Tuple2((amount - feeAmount), feeAmount)
755+ }
756+
757+
758+func calcPutOneToken (paymentAmountRaw,paymentAssetId,userAddress,txId) = {
759+ let isEval = (txId == unit)
760+ let amountBalanceRaw = getAccBalance(assetIdToString(cfgAmountAssetId))
761+ let priceBalanceRaw = getAccBalance(assetIdToString(cfgPriceAssetId))
762+ let paymentInAmountAsset = if ((paymentAssetId == cfgAmountAssetId))
763+ then true
764+ else if ((paymentAssetId == cfgPriceAssetId))
765+ then false
766+ else throwErr("invalid asset")
767+ let $t03316933462 = if (isEval)
768+ then $Tuple2(amountBalanceRaw, priceBalanceRaw)
769+ else if (paymentInAmountAsset)
770+ then $Tuple2((amountBalanceRaw - paymentAmountRaw), priceBalanceRaw)
771+ else $Tuple2(amountBalanceRaw, (priceBalanceRaw - paymentAmountRaw))
772+ let amountBalanceOld = $t03316933462._1
773+ let priceBalanceOld = $t03316933462._2
774+ let $t03346633615 = if (paymentInAmountAsset)
775+ then $Tuple2(paymentAmountRaw, 0)
776+ else $Tuple2(0, paymentAmountRaw)
777+ let amountAssetAmountRaw = $t03346633615._1
778+ let priceAssetAmountRaw = $t03346633615._2
779+ let amountAssetAmount = takeFee(amountAssetAmountRaw, inFee)._1
780+ let priceAssetAmount = takeFee(priceAssetAmountRaw, inFee)._1
781+ let $t03374733811 = takeFee(paymentAmountRaw, inFee)
782+ let paymentAmount = $t03374733811._1
783+ let feeAmount = $t03374733811._2
784+ let amountBalanceNew = (amountBalanceOld + amountAssetAmount)
785+ let priceBalanceNew = (priceBalanceOld + priceAssetAmount)
786+ let priceNewX18 = calcPriceBigInt(toX18(priceBalanceNew, cfgPriceAssetDecimals), toX18(amountBalanceNew, cfgAmountAssetDecimals))
787+ let priceNew = fromX18(priceNewX18, scale8)
788+ let paymentBalance = if (paymentInAmountAsset)
789+ then amountBalanceOld
790+ else priceBalanceOld
791+ let paymentBalanceBigInt = toBigInt(paymentBalance)
792+ let supplyBigInt = toBigInt(valueOrErrorMessage(assetInfo(cfgLpAssetId), (("asset " + toBase58String(cfgLpAssetId)) + " doesn't exist")).quantity)
793+ let chechSupply = if ((supplyBigInt > big0))
794+ then true
795+ else throwErr("initial deposit requires all coins")
796+ if ((chechSupply == chechSupply))
797+ then {
798+ let depositBigInt = toBigInt(paymentAmount)
799+ let issueAmount = max([0, toInt(((supplyBigInt * (sqrtBigInt((scale18 + ((depositBigInt * scale18) / paymentBalanceBigInt)), 18, 18, DOWN) - scale18)) / scale18))])
800+ let commonState = if (isEval)
801+ then nil
802+ 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))]
803+ let priceOldX18 = calcPriceBigInt(toX18(priceBalanceOld, cfgPriceAssetDecimals), toX18(amountBalanceOld, cfgAmountAssetDecimals))
804+ let priceOld = fromX18(priceOldX18, scale8)
805+ let loss = {
806+ let $t03549235659 = if (paymentInAmountAsset)
807+ then $Tuple2(amountAssetAmountRaw, amountBalanceOld)
808+ else $Tuple2(priceAssetAmountRaw, priceBalanceOld)
809+ let amount = $t03549235659._1
810+ let balance = $t03549235659._2
811+ let issueAmountBoth = toInt(fraction(supplyBigInt, toBigInt((amount / 2)), toBigInt(balance)))
812+ fraction((issueAmount - issueAmountBoth), scale8, issueAmountBoth)
813+ }
814+ $Tuple5(issueAmount, commonState, feeAmount, loss, paymentInAmountAsset)
815+ }
816+ else throw("Strict value is not equal to itself.")
817+ }
818+
819+
820+func calcGetOneToken (outAssetId,paymentAmount,paymentAssetId,userAddress,txId) = {
821+ let isEval = (txId == unit)
822+ let cfg = getPoolConfig()
823+ let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
824+ let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
825+ let checks = [if ((paymentAssetId == cfgLpAssetId))
826+ then true
827+ else throwErr("invalid lp asset")]
828+ if ((checks == checks))
829+ then {
830+ let outInAmountAsset = if ((outAssetId == cfgAmountAssetId))
831+ then true
832+ else if ((outAssetId == cfgPriceAssetId))
833+ then false
834+ else throwErr("invalid asset")
835+ let balanceBigInt = if (outInAmountAsset)
836+ then toBigInt(getAccBalance(assetIdToString(cfgAmountAssetId)))
837+ else toBigInt(getAccBalance(assetIdToString(cfgPriceAssetId)))
838+ let outInAmountAssetDecimals = if (outInAmountAsset)
839+ then amtAssetDcm
840+ else priceAssetDcm
841+ let amBalanceOld = getAccBalance(assetIdToString(cfgAmountAssetId))
842+ let prBalanceOld = getAccBalance(assetIdToString(cfgPriceAssetId))
843+ let outBalance = if (outInAmountAsset)
844+ then amBalanceOld
845+ else prBalanceOld
846+ let outBalanceBigInt = toBigInt(outBalance)
847+ let supplyBigInt = toBigInt(valueOrErrorMessage(assetInfo(cfgLpAssetId), (("asset " + toBase58String(cfgLpAssetId)) + " doesn't exist")).quantity)
848+ let redeemedBigInt = toBigInt(paymentAmount)
849+ let amountRaw = max([0, toInt(((balanceBigInt * (scale18 - pow((scale18 - ((redeemedBigInt * scale18) / supplyBigInt)), 18, big2, 0, 18, DOWN))) / scale18))])
850+ let $t03773737793 = takeFee(amountRaw, outFee)
851+ let totalAmount = $t03773737793._1
852+ let feeAmount = $t03773737793._2
853+ let $t03779738023 = if (outInAmountAsset)
854+ then $Tuple4(totalAmount, 0, (amBalanceOld - amountRaw), prBalanceOld)
855+ else $Tuple4(0, totalAmount, amBalanceOld, (prBalanceOld - amountRaw))
856+ let outAmAmount = $t03779738023._1
857+ let outPrAmount = $t03779738023._2
858+ let amBalanceNew = $t03779738023._3
859+ let prBalanceNew = $t03779738023._4
860+ let priceNewX18 = calcPriceBigInt(toX18(prBalanceNew, cfgPriceAssetDecimals), toX18(amBalanceNew, cfgAmountAssetDecimals))
861+ let priceNew = fromX18(priceNewX18, scale8)
862+ let commonState = if (isEval)
863+ then nil
864+ 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)]
865+ let priceOldX18 = calcPriceBigInt(toX18(prBalanceOld, cfgPriceAssetDecimals), toX18(amBalanceOld, cfgAmountAssetDecimals))
866+ let priceOld = fromX18(priceOldX18, scale8)
867+ let loss = {
868+ let amountBothInPaymentAsset = (toInt(fraction(balanceBigInt, redeemedBigInt, supplyBigInt)) * 2)
869+ fraction((totalAmount - amountBothInPaymentAsset), scale8, amountBothInPaymentAsset)
870+ }
871+ $Tuple5(totalAmount, commonState, feeAmount, loss, outInAmountAsset)
872+ }
873+ else throw("Strict value is not equal to itself.")
874+ }
875+
876+
877+func managerPublicKeyOrUnit () = {
878+ let managerVaultAddress = getManagerVaultAddressOrThis()
879+ match getString(managerVaultAddress, keyManagerPublicKey()) {
880+ case s: String =>
881+ fromBase58String(s)
882+ case _: Unit =>
883+ unit
884+ case _ =>
885+ throw("Match error")
886+ }
887+ }
888+
889+
890+func isManager (i) = match managerPublicKeyOrUnit() {
891+ case pk: ByteVector =>
892+ (i.callerPublicKey == pk)
893+ case _: Unit =>
894+ (i.caller == this)
895+ case _ =>
896+ throw("Match error")
897+}
898+
899+
900+func mustManager (i) = {
901+ let pd = throw("Permission denied")
902+ match managerPublicKeyOrUnit() {
903+ case pk: ByteVector =>
904+ if ((i.callerPublicKey == pk))
905+ then true
906+ else pd
907+ case _: Unit =>
908+ if ((i.caller == this))
909+ then true
910+ else pd
911+ case _ =>
912+ throw("Match error")
913+ }
914+ }
915+
916+
917+@Callable(i)
918+func rebalance () = (rebalanceAsset(getStringOrFail(this, aa())) ++ rebalanceAsset(getStringOrFail(this, pa())))
919+
920+
921+
922+@Callable(i)
923+func calculateAmountOutForSwapREADONLY (cleanAmountIn,isReverse,feePoolAmount) = {
924+ let $t03988140186 = if ((isReverse == false))
925+ then {
926+ let assetOut = getStringOrFail(this, pa())
927+ let assetIn = getStringOrFail(this, aa())
928+ $Tuple2(assetOut, assetIn)
929+ }
930+ else {
931+ let assetOut = getStringOrFail(this, aa())
932+ let assetIn = getStringOrFail(this, pa())
933+ $Tuple2(assetOut, assetIn)
934+ }
935+ let assetOut = $t03988140186._1
936+ let assetIn = $t03988140186._2
937+ let poolAssetInBalance = getAccBalance(assetIn)
938+ let poolAssetOutBalance = getAccBalance(assetOut)
939+ let amountOut = fraction(poolAssetOutBalance, cleanAmountIn, (poolAssetInBalance + cleanAmountIn))
940+ let oldK = (toBigInt(poolAssetInBalance) * toBigInt(poolAssetOutBalance))
941+ let newK = (((toBigInt(getAccBalance(assetIn)) + toBigInt(cleanAmountIn)) + toBigInt(feePoolAmount)) * (toBigInt(getAccBalance(assetOut)) - toBigInt(amountOut)))
942+ let checkK = if ((newK >= oldK))
943+ then true
944+ else throw("new K is fewer error")
945+ if ((checkK == checkK))
946+ then $Tuple2(nil, amountOut)
947+ else throw("Strict value is not equal to itself.")
948+ }
949+
950+
951+
952+@Callable(i)
953+func calculateAmountOutForSwapAndSendTokens (cleanAmountIn,isReverse,amountOutMin,addressTo,feePoolAmount) = {
954+ let swapContact = {
955+ let @ = invoke(factoryContract, "getSwapContractREADONLY", nil, nil)
956+ if ($isInstanceOf(@, "String"))
957+ then @
958+ else throw(($getType(@) + " couldn't be cast to String"))
959+ }
960+ let isPoolSwapDisabled = {
961+ let @ = invoke(factoryContract, "isPoolSwapDisabledREADONLY", [toString(this)], nil)
962+ if ($isInstanceOf(@, "Boolean"))
963+ then @
964+ else throw(($getType(@) + " couldn't be cast to Boolean"))
965+ }
966+ let isSwapDisabled = if (!(isAddressWhitelisted(i.caller)))
967+ then if (if (isGlobalShutdown())
968+ then true
969+ else (cfgPoolStatus == PoolShutdown))
970+ then true
971+ else isPoolSwapDisabled
972+ else false
973+ let checks = [if (if (!(isSwapDisabled))
974+ then true
975+ else isManager(i))
976+ then true
977+ else throwErr("swap operation is blocked by admin"), if ((value(i.payments[0]).amount >= cleanAmountIn))
978+ then true
979+ else throwErr("Wrong amount"), if ((i.caller == addressFromStringValue(swapContact)))
980+ then true
981+ else throwErr("Permission denied")]
982+ if ((checks == checks))
983+ then {
984+ let pmt = value(i.payments[0])
985+ let assetIn = assetIdToString(pmt.assetId)
986+ let assetOut = if ((isReverse == false))
987+ then getStringOrFail(this, pa())
988+ else getStringOrFail(this, aa())
989+ let poolAssetInBalance = ((getAccBalance(assetIn) - value(i.payments[0]).amount) - feePoolAmount)
990+ let poolAssetOutBalance = getAccBalance(assetOut)
991+ let amountOut = fraction(poolAssetOutBalance, cleanAmountIn, (poolAssetInBalance + cleanAmountIn))
992+ let oldK = (toBigInt(poolAssetInBalance) * toBigInt(poolAssetOutBalance))
993+ let newK = ((toBigInt(getAccBalance(assetIn)) + toBigInt(feePoolAmount)) * (toBigInt(getAccBalance(assetOut)) - toBigInt(amountOut)))
994+ let checkK = if ((newK >= oldK))
995+ then true
996+ else throw("new K is fewer error")
997+ if ((checkK == checkK))
998+ then {
999+ let checkMin = if ((amountOut >= amountOutMin))
1000+ then true
1001+ else throw("Exchange result is fewer coins than expected")
1002+ if ((checkMin == checkMin))
1003+ then {
1004+ let amountAssetBalanceDelta = if (isReverse)
1005+ then -(amountOut)
1006+ else feePoolAmount
1007+ let priceAssetBalanceDelta = if (isReverse)
1008+ then feePoolAmount
1009+ else -(amountOut)
1010+ let refreshKLpActions = refreshKLpInternal(amountAssetBalanceDelta, priceAssetBalanceDelta, 0)._1
1011+ if ((refreshKLpActions == refreshKLpActions))
1012+ then {
1013+ let rebalanceState = rebalanceAsset(assetIn)
1014+ if ((rebalanceState == rebalanceState))
1015+ then {
1016+ let withdrawState = withdrawAndRebalanceAsset(assetOut, amountOut)
1017+ if ((withdrawState == withdrawState))
1018+ then $Tuple2(((withdrawState ++ rebalanceState) ++ [ScriptTransfer(addressFromStringValue(addressTo), amountOut, parseAssetId(assetOut))]), amountOut)
1019+ else throw("Strict value is not equal to itself.")
1020+ }
1021+ else throw("Strict value is not equal to itself.")
1022+ }
1023+ else throw("Strict value is not equal to itself.")
1024+ }
1025+ else throw("Strict value is not equal to itself.")
1026+ }
1027+ else throw("Strict value is not equal to itself.")
1028+ }
1029+ else throw("Strict value is not equal to itself.")
1030+ }
1031+
1032+
1033+
1034+@Callable(i)
1035+func put (slippageTolerance,shouldAutoStake) = if ((0 > slippageTolerance))
1036+ then throw("Invalid slippageTolerance passed")
1037+ else {
1038+ let estPut = commonPut(i, slippageTolerance, true)
1039+ let emitLpAmt = estPut._2
1040+ let lpAssetId = estPut._7
1041+ let state = estPut._9
1042+ let amDiff = estPut._10
1043+ let prDiff = estPut._11
1044+ let amId = estPut._12
1045+ let prId = estPut._13
1046+ let amAssetPmt = toBigInt(value(i.payments[0]).amount)
1047+ let prAssetPmt = toBigInt(value(i.payments[1]).amount)
1048+ let currentKLp = calcCurrentKLp(amAssetPmt, prAssetPmt, toBigInt(0))
1049+ if ((currentKLp == currentKLp))
1050+ then {
1051+ let emitInv = invoke(factoryContract, "emit", [emitLpAmt], nil)
1052+ if ((emitInv == emitInv))
1053+ then {
1054+ let emitInvLegacy = match emitInv {
1055+ case legacyFactoryContract: Address =>
1056+ invoke(legacyFactoryContract, "emit", [emitLpAmt], nil)
1057+ case _ =>
1058+ unit
1059+ }
1060+ if ((emitInvLegacy == emitInvLegacy))
1061+ then {
1062+ let slippageAInv = if ((amDiff > 0))
1063+ then invoke(slippageContract, "put", nil, [AttachedPayment(amId, amDiff)])
1064+ else nil
1065+ if ((slippageAInv == slippageAInv))
1066+ then {
1067+ let slippagePInv = if ((prDiff > 0))
1068+ then invoke(slippageContract, "put", nil, [AttachedPayment(prId, prDiff)])
1069+ else nil
1070+ if ((slippagePInv == slippagePInv))
1071+ then {
1072+ let lpTransfer = if (shouldAutoStake)
1073+ then {
1074+ let slpStakeInv = invoke(stakingContract, "stake", nil, [AttachedPayment(lpAssetId, emitLpAmt)])
1075+ if ((slpStakeInv == slpStakeInv))
1076+ then nil
1077+ else throw("Strict value is not equal to itself.")
1078+ }
1079+ else [ScriptTransfer(i.caller, emitLpAmt, lpAssetId)]
1080+ let $t04536245824 = refreshKLpInternal(0, 0, 0)
1081+ if (($t04536245824 == $t04536245824))
1082+ then {
1083+ let updatedKLp = $t04536245824._2
1084+ let refreshKLpActions = $t04536245824._1
1085+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
1086+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
1087+ then {
1088+ let reb = invoke(this, "rebalance", nil, nil)
1089+ if ((reb == reb))
1090+ then ((state ++ lpTransfer) ++ refreshKLpActions)
1091+ else throw("Strict value is not equal to itself.")
1092+ }
1093+ else throw("Strict value is not equal to itself.")
1094+ }
1095+ else throw("Strict value is not equal to itself.")
1096+ }
1097+ else throw("Strict value is not equal to itself.")
1098+ }
1099+ else throw("Strict value is not equal to itself.")
1100+ }
1101+ else throw("Strict value is not equal to itself.")
1102+ }
1103+ else throw("Strict value is not equal to itself.")
1104+ }
1105+ else throw("Strict value is not equal to itself.")
1106+ }
1107+
1108+
1109+
1110+@Callable(i)
1111+func putForFree (maxSlippage) = if ((0 > maxSlippage))
1112+ then throw("Invalid value passed")
1113+ else {
1114+ let estPut = commonPut(i, maxSlippage, false)
1115+ let state = estPut._9
1116+ let amAssetPmt = toBigInt(value(i.payments[0]).amount)
1117+ let prAssetPmt = toBigInt(value(i.payments[1]).amount)
1118+ let currentKLp = calcCurrentKLp(amAssetPmt, prAssetPmt, toBigInt(0))
1119+ if ((currentKLp == currentKLp))
1120+ then {
1121+ let $t04643646501 = refreshKLpInternal(0, 0, 0)
1122+ let refreshKLpActions = $t04643646501._1
1123+ let updatedKLp = $t04643646501._2
1124+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
1125+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
1126+ then (state ++ refreshKLpActions)
1127+ else throw("Strict value is not equal to itself.")
1128+ }
1129+ else throw("Strict value is not equal to itself.")
1130+ }
1131+
1132+
1133+
1134+@Callable(i)
1135+func putOneTkn (minOutAmount,autoStake) = {
1136+ let isPoolOneTokenOperationsDisabled = {
1137+ let @ = invoke(factoryContract, "isPoolOneTokenOperationsDisabledREADONLY", [toString(this)], nil)
1138+ if ($isInstanceOf(@, "Boolean"))
1139+ then @
1140+ else throw(($getType(@) + " couldn't be cast to Boolean"))
1141+ }
1142+ let isPutDisabled = if (!(isAddressWhitelisted(i.caller)))
1143+ then if (if (if (isGlobalShutdown())
1144+ then true
1145+ else (cfgPoolStatus == PoolPutDisabled))
1146+ then true
1147+ else (cfgPoolStatus == PoolShutdown))
1148+ then true
1149+ else isPoolOneTokenOperationsDisabled
1150+ else false
1151+ let checks = [if (if (!(isPutDisabled))
1152+ then true
1153+ else isManager(i))
1154+ then true
1155+ else throwErr("put operation is blocked by admin"), if ((size(i.payments) == 1))
1156+ then true
1157+ else throwErr("exactly 1 payment are expected")]
1158+ if ((checks == checks))
1159+ then {
1160+ let payment = i.payments[0]
1161+ let paymentAssetId = payment.assetId
1162+ let paymentAmountRaw = payment.amount
1163+ let currentKLp = if ((paymentAssetId == cfgAmountAssetId))
1164+ then calcCurrentKLp(toBigInt(paymentAmountRaw), toBigInt(0), toBigInt(0))
1165+ else if ((paymentAssetId == cfgPriceAssetId))
1166+ then calcCurrentKLp(toBigInt(0), toBigInt(paymentAmountRaw), toBigInt(0))
1167+ else throwErr("payment asset is not supported")
1168+ if ((currentKLp == currentKLp))
1169+ then {
1170+ let userAddress = i.caller
1171+ let txId = i.transactionId
1172+ let $t04773047882 = calcPutOneToken(paymentAmountRaw, paymentAssetId, userAddress, txId)
1173+ if (($t04773047882 == $t04773047882))
1174+ then {
1175+ let paymentInAmountAsset = $t04773047882._5
1176+ let bonus = $t04773047882._4
1177+ let feeAmount = $t04773047882._3
1178+ let commonState = $t04773047882._2
1179+ let emitAmountEstimated = $t04773047882._1
1180+ let emitAmount = if (if ((minOutAmount > 0))
1181+ then (minOutAmount > emitAmountEstimated)
1182+ else false)
1183+ then throwErr(makeString(["amount to receive is less than ", toString(minOutAmount)], ""))
1184+ else emitAmountEstimated
1185+ let emitInv = emit(emitAmount)
1186+ if ((emitInv == emitInv))
1187+ then {
1188+ let lpTransfer = if (autoStake)
1189+ then {
1190+ let stakeInv = invoke(stakingContract, "stake", nil, [AttachedPayment(cfgLpAssetId, emitAmount)])
1191+ if ((stakeInv == stakeInv))
1192+ then nil
1193+ else throw("Strict value is not equal to itself.")
1194+ }
1195+ else [ScriptTransfer(i.caller, emitAmount, cfgLpAssetId)]
1196+ let sendFee = if ((feeAmount > 0))
1197+ then [ScriptTransfer(feeCollectorAddress, feeAmount, paymentAssetId)]
1198+ else nil
1199+ let $t04846848665 = if ((this == feeCollectorAddress))
1200+ then $Tuple2(0, 0)
1201+ else if (paymentInAmountAsset)
1202+ then $Tuple2(-(feeAmount), 0)
1203+ else $Tuple2(0, -(feeAmount))
1204+ let amountAssetBalanceDelta = $t04846848665._1
1205+ let priceAssetBalanceDelta = $t04846848665._2
1206+ let $t04866848776 = refreshKLpInternal(amountAssetBalanceDelta, priceAssetBalanceDelta, 0)
1207+ let refreshKLpActions = $t04866848776._1
1208+ let updatedKLp = $t04866848776._2
1209+ let kLp = value(getString(keyKLp))
1210+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
1211+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
1212+ then {
1213+ let reb = invoke(this, "rebalance", nil, nil)
1214+ if ((reb == reb))
1215+ then $Tuple2((((commonState ++ lpTransfer) ++ sendFee) ++ refreshKLpActions), emitAmount)
1216+ else throw("Strict value is not equal to itself.")
1217+ }
1218+ else throw("Strict value is not equal to itself.")
1219+ }
1220+ else throw("Strict value is not equal to itself.")
1221+ }
1222+ else throw("Strict value is not equal to itself.")
1223+ }
1224+ else throw("Strict value is not equal to itself.")
1225+ }
1226+ else throw("Strict value is not equal to itself.")
1227+ }
1228+
1229+
1230+
1231+@Callable(i)
1232+func putOneTknREADONLY (paymentAssetId,paymentAmountRaw) = {
1233+ let $t04913149288 = calcPutOneToken(paymentAmountRaw, parseAssetId(paymentAssetId), unit, unit)
1234+ let emitAmountEstimated = $t04913149288._1
1235+ let commonState = $t04913149288._2
1236+ let feeAmount = $t04913149288._3
1237+ let bonus = $t04913149288._4
1238+ let paymentInAmountAsset = $t04913149288._5
1239+ $Tuple2(nil, $Tuple3(emitAmountEstimated, feeAmount, bonus))
1240+ }
1241+
1242+
1243+
1244+@Callable(i)
1245+func getOneTkn (outAssetIdStr,minOutAmount) = {
1246+ let isPoolOneTokenOperationsDisabled = {
1247+ let @ = invoke(factoryContract, "isPoolOneTokenOperationsDisabledREADONLY", [toString(this)], nil)
1248+ if ($isInstanceOf(@, "Boolean"))
1249+ then @
1250+ else throw(($getType(@) + " couldn't be cast to Boolean"))
1251+ }
1252+ let isGetDisabled = if (!(isAddressWhitelisted(i.caller)))
1253+ then if (if (isGlobalShutdown())
1254+ then true
1255+ else (cfgPoolStatus == PoolShutdown))
1256+ then true
1257+ else isPoolOneTokenOperationsDisabled
1258+ else false
1259+ let checks = [if (if (!(isGetDisabled))
1260+ then true
1261+ else isManager(i))
1262+ then true
1263+ else throwErr("get operation is blocked by admin"), if ((size(i.payments) == 1))
1264+ then true
1265+ else throwErr("exactly 1 payment are expected")]
1266+ if ((checks == checks))
1267+ then {
1268+ let outAssetId = parseAssetId(outAssetIdStr)
1269+ let payment = i.payments[0]
1270+ let paymentAssetId = payment.assetId
1271+ let paymentAmount = payment.amount
1272+ let currentKLp = calcCurrentKLp(toBigInt(0), toBigInt(0), toBigInt(0))
1273+ if ((currentKLp == currentKLp))
1274+ then {
1275+ let userAddress = i.caller
1276+ let txId = i.transactionId
1277+ let $t05021050363 = calcGetOneToken(outAssetId, paymentAmount, paymentAssetId, userAddress, txId)
1278+ if (($t05021050363 == $t05021050363))
1279+ then {
1280+ let outInAmountAsset = $t05021050363._5
1281+ let bonus = $t05021050363._4
1282+ let feeAmount = $t05021050363._3
1283+ let commonState = $t05021050363._2
1284+ let amountEstimated = $t05021050363._1
1285+ let amount = if (if ((minOutAmount > 0))
1286+ then (minOutAmount > amountEstimated)
1287+ else false)
1288+ then throwErr(makeString(["amount to receive is less than ", toString(minOutAmount)], ""))
1289+ else amountEstimated
1290+ let burnInv = invoke(factoryContract, "burn", [paymentAmount], [AttachedPayment(paymentAssetId, paymentAmount)])
1291+ if ((burnInv == burnInv))
1292+ then {
1293+ let withdrawState = withdrawAndRebalanceAsset(outAssetIdStr, (amount + max([0, feeAmount])))
1294+ let assetTransfer = [ScriptTransfer(userAddress, amount, outAssetId)]
1295+ let sendFee = if ((feeAmount > 0))
1296+ then [ScriptTransfer(feeCollectorAddress, feeAmount, outAssetId)]
1297+ else nil
1298+ let $t05102751274 = {
1299+ let feeAmountForCalc = if ((this == feeCollectorAddress))
1300+ then 0
1301+ else feeAmount
1302+ if (outInAmountAsset)
1303+ then $Tuple2(-((amount + feeAmountForCalc)), 0)
1304+ else $Tuple2(0, -((amount + feeAmountForCalc)))
1305+ }
1306+ let amountAssetBalanceDelta = $t05102751274._1
1307+ let priceAssetBalanceDelta = $t05102751274._2
1308+ let $t05127751385 = refreshKLpInternal(amountAssetBalanceDelta, priceAssetBalanceDelta, 0)
1309+ let refreshKLpActions = $t05127751385._1
1310+ let updatedKLp = $t05127751385._2
1311+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
1312+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
1313+ then $Tuple2(((((commonState ++ withdrawState) ++ assetTransfer) ++ sendFee) ++ refreshKLpActions), amount)
1314+ else throw("Strict value is not equal to itself.")
1315+ }
1316+ else throw("Strict value is not equal to itself.")
1317+ }
1318+ else throw("Strict value is not equal to itself.")
1319+ }
1320+ else throw("Strict value is not equal to itself.")
1321+ }
1322+ else throw("Strict value is not equal to itself.")
1323+ }
1324+
1325+
1326+
1327+@Callable(i)
1328+func getOneTknREADONLY (outAssetId,paymentAmount) = {
1329+ let $t05166351819 = calcGetOneToken(parseAssetId(outAssetId), paymentAmount, cfgLpAssetId, unit, unit)
1330+ let amountEstimated = $t05166351819._1
1331+ let commonState = $t05166351819._2
1332+ let feeAmount = $t05166351819._3
1333+ let bonus = $t05166351819._4
1334+ let outInAmountAsset = $t05166351819._5
1335+ $Tuple2(nil, $Tuple3(amountEstimated, feeAmount, bonus))
1336+ }
1337+
1338+
1339+
1340+@Callable(i)
1341+func unstakeAndGetOneTkn (unstakeAmount,outAssetIdStr,minOutAmount) = {
1342+ let isPoolOneTokenOperationsDisabled = {
1343+ let @ = invoke(factoryContract, "isPoolOneTokenOperationsDisabledREADONLY", [toString(this)], nil)
1344+ if ($isInstanceOf(@, "Boolean"))
1345+ then @
1346+ else throw(($getType(@) + " couldn't be cast to Boolean"))
1347+ }
1348+ let isGetDisabled = if (!(isAddressWhitelisted(i.caller)))
1349+ then if (if (isGlobalShutdown())
1350+ then true
1351+ else (cfgPoolStatus == PoolShutdown))
1352+ then true
1353+ else isPoolOneTokenOperationsDisabled
1354+ else false
1355+ let checks = [if (if (!(isGetDisabled))
1356+ then true
1357+ else isManager(i))
1358+ then true
1359+ else throwErr("get operation is blocked by admin"), if ((size(i.payments) == 0))
1360+ then true
1361+ else throwErr("no payments are expected")]
1362+ if ((checks == checks))
1363+ then {
1364+ let outAssetId = parseAssetId(outAssetIdStr)
1365+ let userAddress = i.caller
1366+ let txId = i.transactionId
1367+ let currentKLp = calcCurrentKLp(toBigInt(0), toBigInt(0), toBigInt(0))
1368+ if ((currentKLp == currentKLp))
1369+ then {
1370+ let unstakeInv = invoke(stakingContract, "unstake", [toBase58String(cfgLpAssetId), unstakeAmount], nil)
1371+ if ((unstakeInv == unstakeInv))
1372+ then {
1373+ let $t05276152912 = calcGetOneToken(outAssetId, unstakeAmount, cfgLpAssetId, userAddress, txId)
1374+ if (($t05276152912 == $t05276152912))
1375+ then {
1376+ let outInAmountAsset = $t05276152912._5
1377+ let bonus = $t05276152912._4
1378+ let feeAmount = $t05276152912._3
1379+ let commonState = $t05276152912._2
1380+ let amountEstimated = $t05276152912._1
1381+ let amount = if (if ((minOutAmount > 0))
1382+ then (minOutAmount > amountEstimated)
1383+ else false)
1384+ then throwErr(makeString(["amount to receive is less than ", toString(minOutAmount)], ""))
1385+ else amountEstimated
1386+ let burnInv = invoke(factoryContract, "burn", [unstakeAmount], [AttachedPayment(cfgLpAssetId, unstakeAmount)])
1387+ if ((burnInv == burnInv))
1388+ then {
1389+ let withdrawState = withdrawAndRebalanceAsset(outAssetIdStr, (amount + max([0, feeAmount])))
1390+ let assetTransfer = [ScriptTransfer(i.caller, amount, outAssetId)]
1391+ let sendFee = if ((feeAmount > 0))
1392+ then [ScriptTransfer(feeCollectorAddress, feeAmount, outAssetId)]
1393+ else nil
1394+ let $t05357153818 = {
1395+ let feeAmountForCalc = if ((this == feeCollectorAddress))
1396+ then 0
1397+ else feeAmount
1398+ if (outInAmountAsset)
1399+ then $Tuple2(-((amount + feeAmountForCalc)), 0)
1400+ else $Tuple2(0, -((amount + feeAmountForCalc)))
1401+ }
1402+ let amountAssetBalanceDelta = $t05357153818._1
1403+ let priceAssetBalanceDelta = $t05357153818._2
1404+ let $t05382153929 = refreshKLpInternal(amountAssetBalanceDelta, priceAssetBalanceDelta, 0)
1405+ let refreshKLpActions = $t05382153929._1
1406+ let updatedKLp = $t05382153929._2
1407+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
1408+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
1409+ then $Tuple2(((((commonState ++ withdrawState) ++ assetTransfer) ++ sendFee) ++ refreshKLpActions), amount)
1410+ else throw("Strict value is not equal to itself.")
1411+ }
1412+ else throw("Strict value is not equal to itself.")
1413+ }
1414+ else throw("Strict value is not equal to itself.")
1415+ }
1416+ else throw("Strict value is not equal to itself.")
1417+ }
1418+ else throw("Strict value is not equal to itself.")
1419+ }
1420+ else throw("Strict value is not equal to itself.")
1421+ }
1422+
1423+
1424+
1425+@Callable(i)
1426+func get () = {
1427+ let res = commonGet(i)
1428+ let outAmAmt = res._1
1429+ let outPrAmt = res._2
1430+ let pmtAmt = res._3
1431+ let pmtAssetId = res._4
1432+ let state = res._5
1433+ let withdrawState = withdrawAndRebalanceAll(outAmAmt, outPrAmt)
1434+ let currentKLp = calcCurrentKLp(toBigInt(0), toBigInt(0), toBigInt(0))
1435+ if ((currentKLp == currentKLp))
1436+ then {
1437+ let burnLPAssetOnFactory = invoke(factoryContract, "burn", [pmtAmt], [AttachedPayment(pmtAssetId, pmtAmt)])
1438+ if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
1439+ then {
1440+ let $t05502455105 = refreshKLpInternal(-(outAmAmt), -(outPrAmt), 0)
1441+ let refreshKLpActions = $t05502455105._1
1442+ let updatedKLp = $t05502455105._2
1443+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
1444+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
1445+ then ((withdrawState ++ state) ++ refreshKLpActions)
1446+ else throw("Strict value is not equal to itself.")
1447+ }
1448+ else throw("Strict value is not equal to itself.")
1449+ }
1450+ else throw("Strict value is not equal to itself.")
1451+ }
1452+
1453+
1454+
1455+@Callable(i)
1456+func getNoLess (noLessThenAmtAsset,noLessThenPriceAsset) = {
1457+ let res = commonGet(i)
1458+ let outAmAmt = res._1
1459+ let outPrAmt = res._2
1460+ let pmtAmt = res._3
1461+ let pmtAssetId = res._4
1462+ let state = res._5
1463+ if ((noLessThenAmtAsset > outAmAmt))
1464+ then throw(((("noLessThenAmtAsset failed: " + toString(outAmAmt)) + " < ") + toString(noLessThenAmtAsset)))
1465+ else if ((noLessThenPriceAsset > outPrAmt))
1466+ then throw(((("noLessThenPriceAsset failed: " + toString(outPrAmt)) + " < ") + toString(noLessThenPriceAsset)))
1467+ else {
1468+ let withdrawState = withdrawAndRebalanceAll(outAmAmt, outPrAmt)
1469+ let currentKLp = calcCurrentKLp(toBigInt(0), toBigInt(0), toBigInt(0))
1470+ if ((currentKLp == currentKLp))
1471+ then {
1472+ let burnLPAssetOnFactory = invoke(factoryContract, "burn", [pmtAmt], [AttachedPayment(pmtAssetId, pmtAmt)])
1473+ if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
1474+ then {
1475+ let $t05620056281 = refreshKLpInternal(-(outAmAmt), -(outPrAmt), 0)
1476+ let refreshKLpActions = $t05620056281._1
1477+ let updatedKLp = $t05620056281._2
1478+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
1479+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
1480+ then ((withdrawState ++ state) ++ refreshKLpActions)
1481+ else throw("Strict value is not equal to itself.")
1482+ }
1483+ else throw("Strict value is not equal to itself.")
1484+ }
1485+ else throw("Strict value is not equal to itself.")
1486+ }
1487+ }
1488+
1489+
1490+
1491+@Callable(i)
1492+func unstakeAndGet (amount) = {
1493+ let checkPayments = if ((size(i.payments) != 0))
1494+ then throw("No payments are expected")
1495+ else true
1496+ if ((checkPayments == checkPayments))
1497+ then {
1498+ let cfg = getPoolConfig()
1499+ let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
1500+ let currentKLp = calcCurrentKLp(toBigInt(0), toBigInt(0), toBigInt(0))
1501+ if ((currentKLp == currentKLp))
1502+ then {
1503+ let unstakeInv = invoke(stakingContract, "unstake", [toBase58String(lpAssetId), amount], nil)
1504+ if ((unstakeInv == unstakeInv))
1505+ then {
1506+ let res = estimateGetOperation(toBase58String(i.transactionId), toBase58String(lpAssetId), amount, i.caller)
1507+ let outAmAmt = res._1
1508+ let outPrAmt = res._2
1509+ let poolStatus = parseIntValue(res._9)
1510+ let state = res._10
1511+ let withdrawState = withdrawAndRebalanceAll(outAmAmt, outPrAmt)
1512+ let isGetDisabled = if (!(isAddressWhitelisted(i.caller)))
1513+ then if (isGlobalShutdown())
1514+ then true
1515+ else (cfgPoolStatus == PoolShutdown)
1516+ else false
1517+ let checkPoolStatus = if (isGetDisabled)
1518+ then throw(("Get operation is blocked by admin. Status = " + toString(poolStatus)))
1519+ else true
1520+ if ((checkPoolStatus == checkPoolStatus))
1521+ then {
1522+ let burnLPAssetOnFactory = invoke(factoryContract, "burn", [amount], [AttachedPayment(lpAssetId, amount)])
1523+ if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
1524+ then {
1525+ let $t05762957710 = refreshKLpInternal(-(outAmAmt), -(outPrAmt), 0)
1526+ let refreshKLpActions = $t05762957710._1
1527+ let updatedKLp = $t05762957710._2
1528+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
1529+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
1530+ then ((withdrawState ++ state) ++ refreshKLpActions)
1531+ else throw("Strict value is not equal to itself.")
1532+ }
1533+ else throw("Strict value is not equal to itself.")
1534+ }
1535+ else throw("Strict value is not equal to itself.")
1536+ }
1537+ else throw("Strict value is not equal to itself.")
1538+ }
1539+ else throw("Strict value is not equal to itself.")
1540+ }
1541+ else throw("Strict value is not equal to itself.")
1542+ }
1543+
1544+
1545+
1546+@Callable(i)
1547+func unstakeAndGetNoLess (unstakeAmount,noLessThenAmountAsset,noLessThenPriceAsset) = {
1548+ let isGetDisabled = if (!(isAddressWhitelisted(i.caller)))
1549+ then if (isGlobalShutdown())
1550+ then true
1551+ else (cfgPoolStatus == PoolShutdown)
1552+ else false
1553+ let checks = [if (!(isGetDisabled))
1554+ then true
1555+ else throw("get operation is blocked by admin"), if ((size(i.payments) == 0))
1556+ then true
1557+ else throw("no payments are expected")]
1558+ if ((checks == checks))
1559+ then {
1560+ let currentKLp = calcCurrentKLp(toBigInt(0), toBigInt(0), toBigInt(0))
1561+ if ((currentKLp == currentKLp))
1562+ then {
1563+ let unstakeInv = invoke(stakingContract, "unstake", [toBase58String(cfgLpAssetId), unstakeAmount], nil)
1564+ if ((unstakeInv == unstakeInv))
1565+ then {
1566+ let res = estimateGetOperation(toBase58String(i.transactionId), toBase58String(cfgLpAssetId), unstakeAmount, i.caller)
1567+ let outAmAmt = res._1
1568+ let outPrAmt = res._2
1569+ let state = res._10
1570+ let withdrawState = withdrawAndRebalanceAll(outAmAmt, outPrAmt)
1571+ let checkAmounts = [if ((outAmAmt >= noLessThenAmountAsset))
1572+ then true
1573+ else throw(makeString(["amount asset amount to receive is less than ", toString(noLessThenAmountAsset)], "")), if ((outPrAmt >= noLessThenPriceAsset))
1574+ then true
1575+ else throw(makeString(["price asset amount to receive is less than ", toString(noLessThenPriceAsset)], ""))]
1576+ if ((checkAmounts == checkAmounts))
1577+ then {
1578+ let burnLPAssetOnFactory = invoke(factoryContract, "burn", [unstakeAmount], [AttachedPayment(cfgLpAssetId, unstakeAmount)])
1579+ if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
1580+ then {
1581+ let $t05918859269 = refreshKLpInternal(-(outAmAmt), -(outPrAmt), 0)
1582+ let refreshKLpActions = $t05918859269._1
1583+ let updatedKLp = $t05918859269._2
1584+ let isUpdatedKLpValid = validateUpdatedKLp(currentKLp, updatedKLp)
1585+ if ((isUpdatedKLpValid == isUpdatedKLpValid))
1586+ then ((withdrawState ++ state) ++ refreshKLpActions)
1587+ else throw("Strict value is not equal to itself.")
1588+ }
1589+ else throw("Strict value is not equal to itself.")
1590+ }
1591+ else throw("Strict value is not equal to itself.")
1592+ }
1593+ else throw("Strict value is not equal to itself.")
1594+ }
1595+ else throw("Strict value is not equal to itself.")
1596+ }
1597+ else throw("Strict value is not equal to itself.")
1598+ }
1599+
1600+
1601+
1602+@Callable(i)
1603+func activate (amtAssetStr,priceAssetStr) = if ((toString(i.caller) != toString(factoryContract)))
1604+ then throw("permissions denied")
1605+ else $Tuple2([StringEntry(aa(), amtAssetStr), StringEntry(pa(), priceAssetStr)], "success")
1606+
1607+
1608+
1609+@Callable(i)
1610+func refreshKLp () = {
1611+ let lastRefreshedBlockHeight = valueOrElse(getInteger(keyKLpRefreshedHeight), 0)
1612+ let checkLastRefreshedBlockHeight = if (((height - lastRefreshedBlockHeight) >= kLpRefreshDelay))
1613+ then unit
1614+ else throwErr(makeString([toString(kLpRefreshDelay), " blocks have not passed since the previous call"], ""))
1615+ if ((checkLastRefreshedBlockHeight == checkLastRefreshedBlockHeight))
1616+ then {
1617+ let kLp = valueOrErrorMessage(parseBigInt(valueOrElse(getString(this, keyKLp), "0")), fmtErr("invalid kLp"))
1618+ let $t06047360537 = refreshKLpInternal(0, 0, 0)
1619+ let kLpUpdateActions = $t06047360537._1
1620+ let updatedKLp = $t06047360537._2
1621+ let actions = if ((kLp != updatedKLp))
1622+ then kLpUpdateActions
1623+ else throwErr("nothing to refresh")
1624+ $Tuple2(actions, toString(updatedKLp))
1625+ }
1626+ else throw("Strict value is not equal to itself.")
1627+ }
1628+
1629+
1630+
1631+@Callable(i)
1632+func getPoolConfigWrapperREADONLY () = $Tuple2(nil, getPoolConfig())
1633+
1634+
1635+
1636+@Callable(i)
1637+func getAccBalanceWrapperREADONLY (assetId) = $Tuple2(nil, getAccBalance(assetId))
1638+
1639+
1640+
1641+@Callable(i)
1642+func calcPricesWrapperREADONLY (amAmt,prAmt,lpAmt) = {
1643+ let prices = calcPrices(amAmt, prAmt, lpAmt)
1644+ $Tuple2(nil, [toString(prices[0]), toString(prices[1]), toString(prices[2])])
1645+ }
1646+
1647+
1648+
1649+@Callable(i)
1650+func toX18WrapperREADONLY (origVal,origScaleMult) = $Tuple2(nil, toString(toX18(origVal, origScaleMult)))
1651+
1652+
1653+
1654+@Callable(i)
1655+func fromX18WrapperREADONLY (val,resultScaleMult) = $Tuple2(nil, fromX18(parseBigIntValue(val), resultScaleMult))
1656+
1657+
1658+
1659+@Callable(i)
1660+func calcPriceBigIntWrapperREADONLY (prAmtX18,amAmtX18) = $Tuple2(nil, toString(calcPriceBigInt(parseBigIntValue(prAmtX18), parseBigIntValue(amAmtX18))))
1661+
1662+
1663+
1664+@Callable(i)
1665+func estimatePutOperationWrapperREADONLY (txId58,slippageTolerance,inAmAssetAmt,inAmAssetId,inPrAssetAmt,inPrAssetId,userAddress,isEvaluate,emitLp) = $Tuple2(nil, estimatePutOperation(txId58, slippageTolerance, inAmAssetAmt, inAmAssetId, inPrAssetAmt, inPrAssetId, userAddress, isEvaluate, emitLp))
1666+
1667+
1668+
1669+@Callable(i)
1670+func estimateGetOperationWrapperREADONLY (txId58,pmtAssetId,pmtLpAmt,userAddress) = {
1671+ let res = estimateGetOperation(txId58, pmtAssetId, pmtLpAmt, addressFromStringValue(userAddress))
1672+ $Tuple2(nil, $Tuple10(res._1, res._2, res._3, res._4, res._5, res._6, res._7, toString(res._8), res._9, res._10))
1673+ }
1674+
1675+
1676+
1677+@Callable(i)
1678+func statsREADONLY () = {
1679+ let cfg = getPoolConfig()
1680+ let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
1681+ let amtAssetId = cfg[idxAmtAssetId]
1682+ let priceAssetId = cfg[idxPriceAssetId]
1683+ let iAmtAssetId = cfg[idxIAmtAssetId]
1684+ let iPriceAssetId = cfg[idxIPriceAssetId]
1685+ let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
1686+ let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
1687+ let poolLPBalance = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
1688+ let accAmtAssetBalance = getAccBalance(amtAssetId)
1689+ let accPriceAssetBalance = getAccBalance(priceAssetId)
1690+ let pricesList = if ((poolLPBalance == 0))
1691+ then [zeroBigInt, zeroBigInt, zeroBigInt]
1692+ else calcPrices(accAmtAssetBalance, accPriceAssetBalance, poolLPBalance)
1693+ let curPrice = 0
1694+ let lpAmtAssetShare = fromX18(pricesList[1], scale8)
1695+ let lpPriceAssetShare = fromX18(pricesList[2], scale8)
1696+ let poolWeight = value(getInteger(factoryContract, keyPoolWeight(toString(this))))
1697+ $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))
1698+ }
1699+
1700+
1701+
1702+@Callable(i)
1703+func evaluatePutByAmountAssetREADONLY (inAmAssetAmt) = {
1704+ let cfg = getPoolConfig()
1705+ let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
1706+ let amAssetIdStr = cfg[idxAmtAssetId]
1707+ let amAssetId = fromBase58String(amAssetIdStr)
1708+ let prAssetIdStr = cfg[idxPriceAssetId]
1709+ let prAssetId = fromBase58String(prAssetIdStr)
1710+ let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
1711+ let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
1712+ let poolStatus = cfg[idxPoolStatus]
1713+ let poolLPBalance = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
1714+ let accAmtAssetBalance = getAccBalance(amAssetIdStr)
1715+ let accPriceAssetBalance = getAccBalance(prAssetIdStr)
1716+ let amtAssetAmtX18 = toX18(accAmtAssetBalance, amtAssetDcm)
1717+ let priceAssetAmtX18 = toX18(accPriceAssetBalance, priceAssetDcm)
1718+ let curPriceX18 = if ((poolLPBalance == 0))
1719+ then zeroBigInt
1720+ else calcPriceBigInt(priceAssetAmtX18, amtAssetAmtX18)
1721+ let inAmAssetAmtX18 = toX18(inAmAssetAmt, amtAssetDcm)
1722+ let inPrAssetAmtX18 = fraction(inAmAssetAmtX18, curPriceX18, scale18)
1723+ let inPrAssetAmt = fromX18(inPrAssetAmtX18, priceAssetDcm)
1724+ let estPut = estimatePutOperation("", 500000, inAmAssetAmt, amAssetId, inPrAssetAmt, prAssetId, "", true, false)
1725+ let calcLpAmt = estPut._1
1726+ let curPriceCalc = estPut._3
1727+ let amBalance = estPut._4
1728+ let prBalance = estPut._5
1729+ let lpEmission = estPut._6
1730+ $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))
1731+ }
1732+
1733+
1734+
1735+@Callable(i)
1736+func evaluatePutByPriceAssetREADONLY (inPrAssetAmt) = {
1737+ let cfg = getPoolConfig()
1738+ let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
1739+ let amAssetIdStr = cfg[idxAmtAssetId]
1740+ let amAssetId = fromBase58String(amAssetIdStr)
1741+ let prAssetIdStr = cfg[idxPriceAssetId]
1742+ let prAssetId = fromBase58String(prAssetIdStr)
1743+ let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
1744+ let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
1745+ let poolStatus = cfg[idxPoolStatus]
1746+ let poolLPBalance = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
1747+ let amBalanceRaw = getAccBalance(amAssetIdStr)
1748+ let prBalanceRaw = getAccBalance(prAssetIdStr)
1749+ let amBalanceRawX18 = toX18(amBalanceRaw, amtAssetDcm)
1750+ let prBalanceRawX18 = toX18(prBalanceRaw, priceAssetDcm)
1751+ let curPriceX18 = if ((poolLPBalance == 0))
1752+ then zeroBigInt
1753+ else calcPriceBigInt(prBalanceRawX18, amBalanceRawX18)
1754+ let inPrAssetAmtX18 = toX18(inPrAssetAmt, priceAssetDcm)
1755+ let inAmAssetAmtX18 = fraction(inPrAssetAmtX18, scale18, curPriceX18)
1756+ let inAmAssetAmt = fromX18(inAmAssetAmtX18, amtAssetDcm)
1757+ let estPut = estimatePutOperation("", 500000, inAmAssetAmt, amAssetId, inPrAssetAmt, prAssetId, "", true, false)
1758+ let calcLpAmt = estPut._1
1759+ let curPriceCalc = estPut._3
1760+ let amBalance = estPut._4
1761+ let prBalance = estPut._5
1762+ let lpEmission = estPut._6
1763+ $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))
1764+ }
1765+
1766+
1767+
1768+@Callable(i)
1769+func evaluateGetREADONLY (paymentLpAssetId,paymentLpAmt) = {
1770+ let res = estimateGetOperation("", paymentLpAssetId, paymentLpAmt, this)
1771+ let outAmAmt = res._1
1772+ let outPrAmt = res._2
1773+ let amBalance = res._5
1774+ let prBalance = res._6
1775+ let lpEmission = res._7
1776+ let curPrice = res._8
1777+ let poolStatus = parseIntValue(res._9)
1778+ $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))
1779+ }
1780+
1781+
1782+@Verifier(tx)
1783+func verify () = {
1784+ let targetPublicKey = match managerPublicKeyOrUnit() {
1785+ case pk: ByteVector =>
1786+ pk
1787+ case _: Unit =>
1788+ tx.senderPublicKey
1789+ case _ =>
1790+ throw("Match error")
1791+ }
1792+ match tx {
1793+ case order: Order =>
1794+ let matcherPub = getMatcherPubOrFail()
1795+ let $t06919969316 = if (skipOrderValidation())
1796+ then $Tuple2(true, "")
1797+ else validateMatcherOrderAllowed(order)
1798+ let orderValid = $t06919969316._1
1799+ let orderValidInfo = $t06919969316._2
1800+ let senderValid = sigVerify(order.bodyBytes, order.proofs[0], order.senderPublicKey)
1801+ let matcherValid = sigVerify(order.bodyBytes, order.proofs[1], matcherPub)
1802+ if (if (if (orderValid)
1803+ then senderValid
1804+ else false)
1805+ then matcherValid
1806+ else false)
1807+ then true
1808+ else throwOrderError(orderValid, orderValidInfo, senderValid, matcherValid)
1809+ case s: SetScriptTransaction =>
1810+ if (sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey))
1811+ then true
1812+ else {
1813+ let newHash = blake2b256(value(s.script))
1814+ let allowedHash = fromBase64String(value(getString(factoryContract, keyAllowedLpScriptHash())))
1815+ let currentHash = scriptHash(this)
1816+ if ((allowedHash == newHash))
1817+ then (currentHash != newHash)
1818+ else false
1819+ }
1820+ case _ =>
1821+ sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey)
1822+ }
1823+ }
1824+

github/deemru/w8io/3ef1775 
90.47 ms