tx · 78QiufZqSN7Yw8MhycDuyq6QBQNLfXJnQKBiAq3uHBMU

3N23sqNJqpVXnHxv4nKXriWA8N6QLsPKd5K:  -0.02900000 Waves

2022.11.01 14:15 [2297978] smart account 3N23sqNJqpVXnHxv4nKXriWA8N6QLsPKd5K > SELF 0.00000000 Waves

{ "type": 13, "id": "78QiufZqSN7Yw8MhycDuyq6QBQNLfXJnQKBiAq3uHBMU", "fee": 2900000, "feeAssetId": null, "timestamp": 1667301262691, "version": 1, "sender": "3N23sqNJqpVXnHxv4nKXriWA8N6QLsPKd5K", "senderPublicKey": "2fTQW76r4FCNaSvj5ycqdyqgJWWapZ2m25zmQLckTQwJ", "proofs": [ "5BRGZcMPNS49i4yr8M3MuQ19PKp7aPCaAVG46vq8NypUc5sKoVZLAVbYq3sVvtFHLT7J3fAnXVaWA5h2tqRhijax" ], "script": "base64:BgLJJggCEgMKAQgSABIECgIBBBIDCgEBEgQKAgEEEgQKAggBEgQKAggBEgQKAggBEgUKAwEIARIAEgQKAgEBEgMKAQESBAoCCAgSABIDCgEIEgUKAwEBARIECgIBARIECgIIARIECgIICBILCgkIAQECAQIIBAQSBgoECAgBCBIAEgMKAQESAwoBARIECgIIASIKbFBkZWNpbWFscyIGc2NhbGU4IgxzY2FsZThCaWdJbnQiB3NjYWxlMTgiCnplcm9CaWdJbnQiBGJpZzAiBGJpZzEiBGJpZzIiC3dhdmVzU3RyaW5nIgNTRVAiClBvb2xBY3RpdmUiD1Bvb2xQdXREaXNhYmxlZCITUG9vbE1hdGNoZXJEaXNhYmxlZCIMUG9vbFNodXRkb3duIg5pZHhQb29sQWRkcmVzcyINaWR4UG9vbFN0YXR1cyIQaWR4UG9vbExQQXNzZXRJZCINaWR4QW10QXNzZXRJZCIPaWR4UHJpY2VBc3NldElkIg5pZHhBbXRBc3NldERjbSIQaWR4UHJpY2VBc3NldERjbSIOaWR4SUFtdEFzc2V0SWQiEGlkeElQcmljZUFzc2V0SWQiDWlkeExQQXNzZXREY20iEmlkeFBvb2xBbXRBc3NldEFtdCIUaWR4UG9vbFByaWNlQXNzZXRBbXQiEWlkeFBvb2xMUEFzc2V0QW10IhlpZHhGYWN0b3J5U3Rha2luZ0NvbnRyYWN0IhppZHhGYWN0b3J5U2xpcHBhZ2VDb250cmFjdCIFdG9YMTgiB29yaWdWYWwiDW9yaWdTY2FsZU11bHQiB2Zyb21YMTgiA3ZhbCIPcmVzdWx0U2NhbGVNdWx0Igd0b1NjYWxlIgNhbXQiCHJlc1NjYWxlIghjdXJTY2FsZSIDYWJzIglhYnNCaWdJbnQiAmZjIgNtcGsiBHBtcGsiAnBsIgJwaCIBaCIJdGltZXN0YW1wIgNwYXUiC3VzZXJBZGRyZXNzIgR0eElkIgNnYXUiAmFhIgJwYSIGa2V5RmVlIgpmZWVEZWZhdWx0IgNmZWUiEGtleUZhY3RvcnlDb25maWciDWtleU1hdGNoZXJQdWIiKWtleU1hcHBpbmdQb29sQ29udHJhY3RBZGRyZXNzVG9Qb29sQXNzZXRzIhNwb29sQ29udHJhY3RBZGRyZXNzIg1rZXlQb29sQ29uZmlnIglpQW10QXNzZXQiC2lQcmljZUFzc2V0Ih9rZXlNYXBwaW5nc0Jhc2VBc3NldDJpbnRlcm5hbElkIgxiYXNlQXNzZXRTdHIiE2tleUFsbFBvb2xzU2h1dGRvd24iDWtleVBvb2xXZWlnaHQiD2NvbnRyYWN0QWRkcmVzcyIWa2V5QWxsb3dlZExwU2NyaXB0SGFzaCIWa2V5RmVlQ29sbGVjdG9yQWRkcmVzcyIPdGhyb3dPcmRlckVycm9yIgpvcmRlclZhbGlkIgtzZW5kZXJWYWxpZCIMbWF0Y2hlclZhbGlkIg9nZXRTdHJpbmdPckZhaWwiB2FkZHJlc3MiA2tleSIMZ2V0SW50T3JGYWlsIgh0aHJvd0VyciIDbXNnIg9mYWN0b3J5Q29udHJhY3QiE2ZlZUNvbGxlY3RvckFkZHJlc3MiEGlzR2xvYmFsU2h1dGRvd24iE2dldE1hdGNoZXJQdWJPckZhaWwiDWdldFBvb2xDb25maWciCGFtdEFzc2V0IgpwcmljZUFzc2V0IgxwYXJzZUFzc2V0SWQiBWlucHV0Ig9hc3NldElkVG9TdHJpbmciD3BhcnNlUG9vbENvbmZpZyIKcG9vbENvbmZpZyIQcG9vbENvbmZpZ1BhcnNlZCILJHQwNzU0Mzc3MDkiDmNmZ1Bvb2xBZGRyZXNzIg1jZmdQb29sU3RhdHVzIgxjZmdMcEFzc2V0SWQiEGNmZ0Ftb3VudEFzc2V0SWQiD2NmZ1ByaWNlQXNzZXRJZCIWY2ZnQW1vdW50QXNzZXREZWNpbWFscyIVY2ZnUHJpY2VBc3NldERlY2ltYWxzIhBnZXRGYWN0b3J5Q29uZmlnIg9zdGFraW5nQ29udHJhY3QiEHNsaXBwYWdlQ29udHJhY3QiEWRhdGFQdXRBY3Rpb25JbmZvIg1pbkFtdEFzc2V0QW10Ig9pblByaWNlQXNzZXRBbXQiCG91dExwQW10IgVwcmljZSIdc2xpcHBhZ2VUb2xlcmFuY2VQYXNzZWRCeVVzZXIiFXNsaXBwYWdlVG9sZXJhbmNlUmVhbCIIdHhIZWlnaHQiC3R4VGltZXN0YW1wIhJzbGlwYWdlQW10QXNzZXRBbXQiFHNsaXBhZ2VQcmljZUFzc2V0QW10IhFkYXRhR2V0QWN0aW9uSW5mbyIOb3V0QW10QXNzZXRBbXQiEG91dFByaWNlQXNzZXRBbXQiB2luTHBBbXQiDWdldEFjY0JhbGFuY2UiB2Fzc2V0SWQiD2NhbGNQcmljZUJpZ0ludCIIcHJBbXRYMTgiCGFtQW10WDE4IhBwcml2YXRlQ2FsY1ByaWNlIgphbUFzc2V0RGNtIgpwckFzc2V0RGNtIgVhbUFtdCIFcHJBbXQiDmFtdEFzc2V0QW10WDE4IhBwcmljZUFzc2V0QW10WDE4IgpjYWxjUHJpY2VzIgVscEFtdCIDY2ZnIgthbXRBc3NldERjbSINcHJpY2VBc3NldERjbSIIcHJpY2VYMTgiCGxwQW10WDE4IhNscFByaWNlSW5BbUFzc2V0WDE4IhNscFByaWNlSW5QckFzc2V0WDE4Ig9jYWxjdWxhdGVQcmljZXMiBnByaWNlcyIUZXN0aW1hdGVHZXRPcGVyYXRpb24iBnR4SWQ1OCIKcG10QXNzZXRJZCIIcG10THBBbXQiCWxwQXNzZXRJZCIJYW1Bc3NldElkIglwckFzc2V0SWQiCnBvb2xTdGF0dXMiCmxwRW1pc3Npb24iCWFtQmFsYW5jZSIMYW1CYWxhbmNlWDE4IglwckJhbGFuY2UiDHByQmFsYW5jZVgxOCILY3VyUHJpY2VYMTgiCGN1clByaWNlIgtwbXRMcEFtdFgxOCINbHBFbWlzc2lvblgxOCILb3V0QW1BbXRYMTgiC291dFByQW10WDE4IghvdXRBbUFtdCIIb3V0UHJBbXQiBXN0YXRlIhRlc3RpbWF0ZVB1dE9wZXJhdGlvbiIRc2xpcHBhZ2VUb2xlcmFuY2UiDGluQW1Bc3NldEFtdCILaW5BbUFzc2V0SWQiDGluUHJBc3NldEFtdCILaW5QckFzc2V0SWQiCmlzRXZhbHVhdGUiBmVtaXRMcCIMYW1Bc3NldElkU3RyIgxwckFzc2V0SWRTdHIiC2lBbXRBc3NldElkIg1pUHJpY2VBc3NldElkIg5pbkFtQXNzZXRJZFN0ciIOaW5QckFzc2V0SWRTdHIiD2luQW1Bc3NldEFtdFgxOCIPaW5QckFzc2V0QW10WDE4Igx1c2VyUHJpY2VYMTgiA3JlcyILc2xpcHBhZ2VYMTgiFHNsaXBwYWdlVG9sZXJhbmNlWDE4IgpwclZpYUFtWDE4IgphbVZpYVByWDE4IgxleHBlY3RlZEFtdHMiEWV4cEFtdEFzc2V0QW10WDE4IhNleHBQcmljZUFzc2V0QW10WDE4IgljYWxjTHBBbXQiDmNhbGNBbUFzc2V0UG10Ig5jYWxjUHJBc3NldFBtdCIMc2xpcHBhZ2VDYWxjIgllbWl0THBBbXQiBmFtRGlmZiIGcHJEaWZmIgtjb21tb25TdGF0ZSIbdmFsaWRhdGVNYXRjaGVyT3JkZXJBbGxvd2VkIgVvcmRlciIKYW10QXNzZXRJZCIMcHJpY2VBc3NldElkIhJhY2NBbXRBc3NldEJhbGFuY2UiFGFjY1ByaWNlQXNzZXRCYWxhbmNlIg1vcmRlckFtdEFzc2V0IhBvcmRlckFtdEFzc2V0U3RyIg9vcmRlclByaWNlQXNzZXQiEm9yZGVyUHJpY2VBc3NldFN0ciIKb3JkZXJQcmljZSIIcHJpY2VEY20iEGNhc3RlZE9yZGVyUHJpY2UiEWlzT3JkZXJQcmljZVZhbGlkIgljb21tb25HZXQiAWkiA3BtdCIGcG10QW10Igljb21tb25QdXQiCmFtQXNzZXRQbXQiCnByQXNzZXRQbXQiBmVzdFB1dCIEZW1pdCIGYW1vdW50IgdlbWl0SW52Ig1lbWl0SW52TGVnYWN5IgckbWF0Y2gwIhVsZWdhY3lGYWN0b3J5Q29udHJhY3QiB3Rha2VGZWUiCWZlZUFtb3VudCIPY2FsY1B1dE9uZVRva2VuIhBwYXltZW50QW1vdW50UmF3Ig5wYXltZW50QXNzZXRJZCIGaXNFdmFsIhBhbW91bnRCYWxhbmNlUmF3Ig9wcmljZUJhbGFuY2VSYXciFHBheW1lbnRJbkFtb3VudEFzc2V0Ig0kdDAyMjU3MDIyODYzIhBhbW91bnRCYWxhbmNlT2xkIg9wcmljZUJhbGFuY2VPbGQiDSR0MDIyODY3MjMwMTYiFGFtb3VudEFzc2V0QW1vdW50UmF3IhNwcmljZUFzc2V0QW1vdW50UmF3IhFhbW91bnRBc3NldEFtb3VudCIQcHJpY2VBc3NldEFtb3VudCINJHQwMjMxMzgyMzE5NyINcGF5bWVudEFtb3VudCIQYW1vdW50QmFsYW5jZU5ldyIPcHJpY2VCYWxhbmNlTmV3IgtwcmljZU5ld1gxOCIIcHJpY2VOZXciDnBheW1lbnRCYWxhbmNlIhRwYXltZW50QmFsYW5jZUJpZ0ludCIMc3VwcGx5QmlnSW50IgtjaGVjaFN1cHBseSINZGVwb3NpdEJpZ0ludCILaXNzdWVBbW91bnQiC3ByaWNlT2xkWDE4IghwcmljZU9sZCILcHJpY2VJbXBhY3QiD2NhbGNHZXRPbmVUb2tlbiIKb3V0QXNzZXRJZCIGY2hlY2tzIhBvdXRJbkFtb3VudEFzc2V0Ig1iYWxhbmNlQmlnSW50IgxhbUJhbGFuY2VPbGQiDHByQmFsYW5jZU9sZCIKb3V0QmFsYW5jZSIQb3V0QmFsYW5jZUJpZ0ludCIOcmVkZWVtZWRCaWdJbnQiCWFtb3VudFJhdyINJHQwMjYxMzUyNjE4NSILdG90YWxBbW91bnQiDSR0MDI2MTg5MjY0MTUiC291dEFtQW1vdW50IgtvdXRQckFtb3VudCIMYW1CYWxhbmNlTmV3IgxwckJhbGFuY2VOZXciFm1hbmFnZXJQdWJsaWNLZXlPclVuaXQiAXMiHXBlbmRpbmdNYW5hZ2VyUHVibGljS2V5T3JVbml0IgttdXN0TWFuYWdlciICcGQiAnBrIhdwZW5kaW5nTWFuYWdlclB1YmxpY0tleSILY2hlY2tDYWxsZXIiFWNoZWNrTWFuYWdlclB1YmxpY0tleSICcG0iBWhhc1BNIgdjaGVja1BNIg9zaG91bGRBdXRvU3Rha2UiBGFtSWQiBHBySWQiDHNsaXBwYWdlQUludiIMc2xpcHBhZ2VQSW52IgpscFRyYW5zZmVyIgtzbHBTdGFrZUludiILbWF4U2xpcHBhZ2UiDG1pbk91dEFtb3VudCIJYXV0b1N0YWtlIiBpc1Bvb2xPbmVUb2tlbk9wZXJhdGlvbnNEaXNhYmxlZCIBQCINaXNQdXREaXNhYmxlZCIHcGF5bWVudCINJHQwMzA5OTczMTEyNCITZW1pdEFtb3VudEVzdGltYXRlZCIFYm9udXMiCmVtaXRBbW91bnQiCHN0YWtlSW52IgdzZW5kRmVlIg0kdDAzMTg1MzMxOTg4Ig1vdXRBc3NldElkU3RyIg1pc0dldERpc2FibGVkIg0kdDAzMjc2MDMyODkyIg9hbW91bnRFc3RpbWF0ZWQiB2J1cm5JbnYiDWFzc2V0VHJhbnNmZXIiDSR0MDMzNTI3MzM2NjUiDXVuc3Rha2VBbW91bnQiCnVuc3Rha2VJbnYiDSR0MDM0NDU3MzQ1ODciCW91dEFtdEFtdCIUYnVybkxQQXNzZXRPbkZhY3RvcnkiEm5vTGVzc1RoZW5BbXRBc3NldCIUbm9MZXNzVGhlblByaWNlQXNzZXQiDWNoZWNrUGF5bWVudHMiD2NoZWNrUG9vbFN0YXR1cyILYW10QXNzZXRTdHIiDXByaWNlQXNzZXRTdHIiDXBvb2xMUEJhbGFuY2UiCnByaWNlc0xpc3QiD2xwQW10QXNzZXRTaGFyZSIRbHBQcmljZUFzc2V0U2hhcmUiCnBvb2xXZWlnaHQiDGN1clByaWNlQ2FsYyIMYW1CYWxhbmNlUmF3IgxwckJhbGFuY2VSYXciD2FtQmFsYW5jZVJhd1gxOCIPcHJCYWxhbmNlUmF3WDE4IhBwYXltZW50THBBc3NldElkIgxwYXltZW50THBBbXQiAnR4IgZ2ZXJpZnkiD3RhcmdldFB1YmxpY0tleSIKbWF0Y2hlclB1YiIHbmV3SGFzaCILYWxsb3dlZEhhc2giC2N1cnJlbnRIYXNoYgABYQAIAAFiAIDC1y8AAWMJALYCAQCAwtcvAAFkCQC2AgEAgICQu7rWrfANAAFlCQC2AgEAAAABZgkAtgIBAAAAAWcJALYCAQABAAFoCQC2AgEAAgABaQIFV0FWRVMAAWoCAl9fAAFrAAEAAWwAAgABbQADAAFuAAQAAW8AAQABcAACAAFxAAMAAXIABAABcwAFAAF0AAYAAXUABwABdgAIAAF3AAkAAXgACgABeQABAAF6AAIAAUEAAwABQgABAAFDAAcBAUQCAUUBRgkAvAIDCQC2AgEFAUUFAWQJALYCAQUBRgEBRwIBSAFJCQCgAwEJALwCAwUBSAkAtgIBBQFJBQFkAQFKAwFLAUwBTQkAawMFAUsFAUwFAU0BAU4BAUgDCQBmAgAABQFICQEBLQEFAUgFAUgBAU8BAUgDCQC/AgIFAWUFAUgJAL4CAQUBSAUBSAEBUAACEyVzX19mYWN0b3J5Q29udHJhY3QBAVEAAhQlc19fbWFuYWdlclB1YmxpY0tleQEBUgACGyVzX19wZW5kaW5nTWFuYWdlclB1YmxpY0tleQEBUwACESVzJXNfX3ByaWNlX19sYXN0AQFUAgFVAVYJALkJAgkAzAgCAhglcyVzJWQlZF9fcHJpY2VfX2hpc3RvcnkJAMwIAgkApAMBBQFVCQDMCAIJAKQDAQUBVgUDbmlsBQFqAQFXAgFYAVkJAKwCAgkArAICCQCsAgICCyVzJXMlc19fUF9fBQFYAgJfXwUBWQEBWgIBWAFZCQCsAgIJAKwCAgkArAICAgslcyVzJXNfX0dfXwUBWAICX18FAVkBAmFhAAIPJXNfX2Ftb3VudEFzc2V0AQJhYgACDiVzX19wcmljZUFzc2V0AAJhYwIHJXNfX2ZlZQACYWQJAGsDAAUFAWIAkE4AAmFlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFAmFjBQJhZAECYWYAAhElc19fZmFjdG9yeUNvbmZpZwECYWcAAhglcyVzX19tYXRjaGVyX19wdWJsaWNLZXkBAmFoAQJhaQkArAICCQCsAgICCCVzJXMlc19fBQJhaQIgX19tYXBwaW5nc19fcG9vbENvbnRyYWN0MkxwQXNzZXQBAmFqAgJhawJhbAkArAICCQCsAgIJAKwCAgkArAICAgglZCVkJXNfXwUCYWsCAl9fBQJhbAIIX19jb25maWcBAmFtAQJhbgkArAICAiglcyVzJXNfX21hcHBpbmdzX19iYXNlQXNzZXQyaW50ZXJuYWxJZF9fBQJhbgECYW8AAgwlc19fc2h1dGRvd24BAmFwAQJhcQkArAICAhIlcyVzX19wb29sV2VpZ2h0X18FAmFxAQJhcgACFyVzX19hbGxvd2VkTHBTY3JpcHRIYXNoAAJhcwIXJXNfX2ZlZUNvbGxlY3RvckFkZHJlc3MBAmF0AwJhdQJhdgJhdwkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAiRvcmRlciB2YWxpZGF0aW9uIGZhaWxlZDogb3JkZXJWYWxpZD0JAKUDAQUCYXUCDSBzZW5kZXJWYWxpZD0JAKUDAQUCYXYCDiBtYXRjaGVyVmFsaWQ9CQClAwEFAmF3AQJheAICYXkCYXoJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQJheQUCYXoJALkJAgkAzAgCAgptYW5kYXRvcnkgCQDMCAIJAKUIAQUCYXkJAMwIAgIBLgkAzAgCBQJhegkAzAgCAg8gaXMgbm90IGRlZmluZWQFA25pbAIAAQJhQQICYXkCYXoJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQJheQUCYXoJALkJAgkAzAgCAgptYW5kYXRvcnkgCQDMCAIJAKUIAQUCYXkJAMwIAgIBLgkAzAgCBQJhegkAzAgCAg8gaXMgbm90IGRlZmluZWQFA25pbAIAAQJhQgECYUMJAAIBCQC5CQIJAMwIAgIIbHAucmlkZToJAMwIAgUCYUMFA25pbAIBIAACYUQJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQJheAIFBHRoaXMJAQFQAAACYUUJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQJheAIFAmFEBQJhcwECYUYACQELdmFsdWVPckVsc2UCCQCbCAIFAmFECQECYW8ABwECYUcACQDZBAEJAQJheAIFAmFECQECYWcAAQJhSAAEAmFJCQECYXgCBQR0aGlzCQECYWEABAJhSgkBAmF4AgUEdGhpcwkBAmFiAAQCYWwJAQJhQQIFAmFECQECYW0BBQJhSgQCYWsJAQJhQQIFAmFECQECYW0BBQJhSQkAtQkCCQECYXgCBQJhRAkBAmFqAgkApAMBBQJhawkApAMBBQJhbAUBagECYUsBAmFMAwkAAAIFAmFMBQFpBQR1bml0CQDZBAEFAmFMAQJhTQECYUwDCQAAAgUCYUwFBHVuaXQFAWkJANgEAQkBBXZhbHVlAQUCYUwBAmFOAQJhTwkAmQoHCQERQGV4dHJOYXRpdmUoMTA2MikBCQCRAwIFAmFPBQFvCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCYU8FAXAJANkEAQkAkQMCBQJhTwUBcQkBAmFLAQkAkQMCBQJhTwUBcgkBAmFLAQkAkQMCBQJhTwUBcwkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmFPBQF0CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCYU8FAXUAAmFQCQECYU4BCQECYUgAAAJhUQUCYVAAAmFSCAUCYVECXzEAAmFTCAUCYVECXzIAAmFUCAUCYVECXzMAAmFVCAUCYVECXzQAAmFWCAUCYVECXzUAAmFXCAUCYVECXzYAAmFYCAUCYVECXzcBAmFZAAkAtQkCCQECYXgCBQJhRAkBAmFmAAUBagACYVoJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQCRAwIJAQJhWQAFAUICGWluY29ycmVjdCBzdGFraW5nIGFkZHJlc3MAAmJhCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkAkQMCCQECYVkABQFDAhlpbmNvcnJlY3Qgc3Rha2luZyBhZGRyZXNzAQJiYgoCYmMCYmQCYmUCYmYCYmcCYmgCYmkCYmoCYmsCYmwJALkJAgkAzAgCAhQlZCVkJWQlZCVkJWQlZCVkJWQlZAkAzAgCCQCkAwEFAmJjCQDMCAIJAKQDAQUCYmQJAMwIAgkApAMBBQJiZQkAzAgCCQCkAwEFAmJmCQDMCAIJAKQDAQUCYmcJAMwIAgkApAMBBQJiaAkAzAgCCQCkAwEFAmJpCQDMCAIJAKQDAQUCYmoJAMwIAgkApAMBBQJiawkAzAgCCQCkAwEFAmJsBQNuaWwFAWoBAmJtBgJibgJibwJicAJiZgJiaQJiagkAuQkCCQDMCAICDCVkJWQlZCVkJWQlZAkAzAgCCQCkAwEFAmJuCQDMCAIJAKQDAQUCYm8JAMwIAgkApAMBBQJicAkAzAgCCQCkAwEFAmJmCQDMCAIJAKQDAQUCYmkJAMwIAgkApAMBBQJiagUDbmlsBQFqAQJicQECYnIDCQAAAgUCYnICBVdBVkVTCAkA7wcBBQR0aGlzCWF2YWlsYWJsZQkA8AcCBQR0aGlzCQDZBAEFAmJyAQJicwICYnQCYnUJALwCAwUCYnQFAWQFAmJ1AQJidgQCYncCYngCYnkCYnoEAmJBCQEBRAIFAmJ5BQJidwQCYkIJAQFEAgUCYnoFAmJ4CQECYnMCBQJiQgUCYkEBAmJDAwJieQJiegJiRAQCYkUJAQJhSAAEAmJGCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCYkUFAXQEAmJHCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCYkUFAXUEAmJICQECYnYEBQJiRgUCYkcFAmJ5BQJiegQCYnUJAQFEAgUCYnkFAmJGBAJidAkBAUQCBQJiegUCYkcEAmJJCQEBRAIFAmJEBQFiBAJiSgkBAmJzAgUCYnUFAmJJBAJiSwkBAmJzAgUCYnQFAmJJCQDMCAIFAmJICQDMCAIFAmJKCQDMCAIFAmJLBQNuaWwBAmJMAwJieQJiegJiRAQCYk0JAQJiQwMFAmJ5BQJiegUCYkQJAMwIAgkBAUcCCQCRAwIFAmJNAAAFAWIJAMwIAgkBAUcCCQCRAwIFAmJNAAEFAWIJAMwIAgkBAUcCCQCRAwIFAmJNAAIFAWIFA25pbAECYk4EAmJPAmJQAmJRAVgEAmJFCQECYUgABAJiUgkAkQMCBQJiRQUBcQQCYlMJAJEDAgUCYkUFAXIEAmJUCQCRAwIFAmJFBQFzBAJidwkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmJFBQF0BAJieAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmJFBQF1BAJiVQkAkQMCBQJiRQUBcAQCYlYICQETdmFsdWVPckVycm9yTWVzc2FnZQIJAOwHAQkA2QQBBQJiUgkArAICCQCsAgICBkFzc2V0IAUCYlICDiBkb2Vzbid0IGV4aXN0CHF1YW50aXR5AwkBAiE9AgUCYlIFAmJQCQACAQIVSW52YWxpZCBhc3NldCBwYXNzZWQuBAJiVwkBAmJxAQUCYlMEAmJYCQEBRAIFAmJXBQJidwQCYlkJAQJicQEFAmJUBAJiWgkBAUQCBQJiWQUCYngEAmNhCQECYnMCBQJiWgUCYlgEAmNiCQEBRwIFAmNhBQFiBAJjYwkBAUQCBQJiUQUBYgQCY2QJAQFEAgUCYlYFAWIEAmNlCQC8AgMFAmJYBQJjYwUCY2QEAmNmCQC8AgMFAmJaBQJjYwUCY2QEAmNnCQEBRwIFAmNlBQJidwQCY2gJAQFHAgUCY2YFAmJ4BAJjaQMJAAACBQJiTwIABQNuaWwJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUBWAUCY2cDCQAAAgUCYlMCBVdBVkVTBQR1bml0CQDZBAEFAmJTCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFAVgFAmNoAwkAAAIFAmJUAgVXQVZFUwUEdW5pdAkA2QQBBQJiVAkAzAgCCQELU3RyaW5nRW50cnkCCQEBWgIJAKUIAQUBWAUCYk8JAQJibQYFAmNnBQJjaAUCYlEFAmNiBQZoZWlnaHQIBQlsYXN0QmxvY2sJdGltZXN0YW1wCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEBUwAFAmNiCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEBVAIFBmhlaWdodAgFCWxhc3RCbG9jawl0aW1lc3RhbXAFAmNiBQNuaWwJAJwKCgUCY2cFAmNoBQJiUwUCYlQFAmJXBQJiWQUCYlYFAmNhBQJiVQUCY2kBAmNqCQJiTwJjawJjbAJjbQJjbgJjbwFYAmNwAmNxBAJiRQkBAmFIAAQCYlIJANkEAQkAkQMCBQJiRQUBcQQCY3IJAJEDAgUCYkUFAXIEAmNzCQCRAwIFAmJFBQFzBAJjdAkAkQMCBQJiRQUBdgQCY3UJAJEDAgUCYkUFAXcEAmJGCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCYkUFAXQEAmJHCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCYkUFAXUEAmJVCQCRAwIFAmJFBQFwBAJiVggJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkA7AcBBQJiUgkArAICCQCsAgICBkFzc2V0IAkA2AQBBQJiUgIOIGRvZXNuJ3QgZXhpc3QIcXVhbnRpdHkEAmN2CQDYBAEJAQt2YWx1ZU9yRWxzZQIFAmNtCQDZBAECBVdBVkVTBAJjdwkA2AQBCQELdmFsdWVPckVsc2UCBQJjbwkA2QQBAgVXQVZFUwMDCQECIT0CBQJjcgUCY3YGCQECIT0CBQJjcwUCY3cJAAIBAiJJbnZhbGlkIGFtdCBvciBwcmljZSBhc3NldCBwYXNzZWQuBAJiVwMFAmNwCQECYnEBBQJjcgkAZQIJAQJicQEFAmNyBQJjbAQCYlkDBQJjcAkBAmJxAQUCY3MJAGUCCQECYnEBBQJjcwUCY24EAmN4CQEBRAIFAmNsBQJiRgQCY3kJAQFEAgUCY24FAmJHBAJjegkBAmJzAgUCY3kFAmN4BAJiWAkBAUQCBQJiVwUCYkYEAmJaCQEBRAIFAmJZBQJiRwQCY0EDCQAAAgUCYlYAAAQCY2EFAWUEAmNCBQFlBAJiSQkAdgYJALkCAgUCY3gFAmN5AAAJALYCAQAFAAEAAAUERE9XTgkAlwoFCQEBRwIFAmJJBQFiCQEBRwIFAmN4BQJiRgkBAUcCBQJjeQUCYkcJAQJicwIJALcCAgUCYloFAmN5CQC3AgIFAmJYBQJjeAUCY0IEAmNhCQECYnMCBQJiWgUCYlgEAmNCCQC8AgMJAQFPAQkAuAICBQJjYQUCY3oFAWQFAmNhBAJjQwkBAUQCBQJjawUBYgMDCQECIT0CBQJjYQUBZQkAvwICBQJjQgUCY0MHCQACAQkArAICCQCsAgIJAKwCAgIPUHJpY2Ugc2xpcHBhZ2UgCQCmAwEFAmNCAh4gZXhjZWVkZWQgdGhlIHBhc3NlZCBsaW1pdCBvZiAJAKYDAQUCY0MEAmNkCQEBRAIFAmJWBQFiBAJjRAkAvAIDBQJjeAUCY2EFAWQEAmNFCQC8AgMFAmN5BQFkBQJjYQQCY0YDCQC/AgIFAmNEBQJjeQkAlAoCBQJjRQUCY3kJAJQKAgUCY3gFAmNEBAJjRwgFAmNGAl8xBAJjSAgFAmNGAl8yBAJiSQkAvAIDBQJjZAUCY0gFAmJaCQCXCgUJAQFHAgUCYkkFAWIJAQFHAgUCY0cFAmJGCQEBRwIFAmNIBQJiRwUCY2EFAmNCBAJjSQgFAmNBAl8xBAJjSggFAmNBAl8yBAJjSwgFAmNBAl8zBAJjYgkBAUcCCAUCY0ECXzQFAWIEAmNMCQEBRwIIBQJjQQJfNQUBYgMJAGcCAAAFAmNJCQACAQI2SW52YWxpZCBjYWxjdWxhdGlvbnMuIExQIGNhbGN1bGF0ZWQgaXMgbGVzcyB0aGFuIHplcm8uBAJjTQMJAQEhAQUCY3EAAAUCY0kEAmNOCQBlAgUCY2wFAmNKBAJjTwkAZQIFAmNuBQJjSwQCY1AJAMwIAgkBDEludGVnZXJFbnRyeQIJAQFTAAUCY2IJAMwIAgkBDEludGVnZXJFbnRyeQIJAQFUAgUGaGVpZ2h0CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAUCY2IJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAVcCBQFYBQJiTwkBAmJiCgUCY0oFAmNLBQJjTQUCY2IFAmNrBQJjTAUGaGVpZ2h0CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAUCY04FAmNPBQNuaWwJAJ8KDQUCY0kFAmNNBQJjYgUCYlcFAmJZBQJiVgUCYlIFAmJVBQJjUAUCY04FAmNPBQJjbQUCY28BAmNRAQJjUgQCYkUJAQJhSAAEAmNTCQCRAwIFAmJFBQFyBAJjVAkAkQMCBQJiRQUBcwQCYlUJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJiRQUBcAQCYkYJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJiRQUBdAQCYkcJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJiRQUBdQQCY1UJAQJicQEFAmNTBAJjVgkBAmJxAQUCY1QEAmNhAwkAAAIIBQJjUglvcmRlclR5cGUFA0J1eQkBAmJ2BAUCYkYFAmJHCQBkAgUCY1UIBQJjUgZhbW91bnQFAmNWCQECYnYEBQJiRgUCYkcJAGUCBQJjVQgFAmNSBmFtb3VudAUCY1YEAmNiCQEBRwIFAmNhBQFiAwMDCQECYUYABgkAAAIFAmJVBQFtBgkAAAIFAmJVBQFuCQACAQIcRXhjaGFuZ2Ugb3BlcmF0aW9ucyBkaXNhYmxlZAQCY1cICAUCY1IJYXNzZXRQYWlyC2Ftb3VudEFzc2V0BAJjWAMJAAACBQJjVwUEdW5pdAIFV0FWRVMJANgEAQkBBXZhbHVlAQUCY1cEAmNZCAgFAmNSCWFzc2V0UGFpcgpwcmljZUFzc2V0BAJjWgMJAAACBQJjWQUEdW5pdAIFV0FWRVMJANgEAQkBBXZhbHVlAQUCY1kDAwkBAiE9AgUCY1gFAmNTBgkBAiE9AgUCY1oFAmNUCQACAQITV3Jvbmcgb3JkZXIgYXNzZXRzLgQCZGEIBQJjUgVwcmljZQQCZGIJAGsDBQFiBQJiRwUCYkYEAmRjCQEBSgMFAmRhBQFiBQJkYgQCZGQDCQAAAggFAmNSCW9yZGVyVHlwZQUDQnV5CQBnAgUCY2IFAmRjCQBnAgUCZGMFAmNiBgECZGUBAmRmAwkBAiE9AgkAkAMBCAUCZGYIcGF5bWVudHMAAQkAAgECHWV4YWN0bHkgMSBwYXltZW50IGlzIGV4cGVjdGVkBAJkZwkBBXZhbHVlAQkAkQMCCAUCZGYIcGF5bWVudHMAAAQCYlAJAQV2YWx1ZQEIBQJkZwdhc3NldElkBAJkaAgFAmRnBmFtb3VudAQCY0EJAQJiTgQJANgEAQgFAmRmDXRyYW5zYWN0aW9uSWQJANgEAQUCYlAFAmRoCAUCZGYGY2FsbGVyBAJjZwgFAmNBAl8xBAJjaAgFAmNBAl8yBAJiVQkBDXBhcnNlSW50VmFsdWUBCAUCY0ECXzkEAmNpCAUCY0EDXzEwAwMJAQJhRgAGCQAAAgUCYlUFAW4JAAIBCQCsAgICLEdldCBvcGVyYXRpb24gaXMgYmxvY2tlZCBieSBhZG1pbi4gU3RhdHVzID0gCQCkAwEFAmJVCQCXCgUFAmNnBQJjaAUCZGgFAmJQBQJjaQECZGkDAmRmAmNrAmNxAwkBAiE9AgkAkAMBCAUCZGYIcGF5bWVudHMAAgkAAgECH2V4YWN0bHkgMiBwYXltZW50cyBhcmUgZXhwZWN0ZWQEAmRqCQEFdmFsdWUBCQCRAwIIBQJkZghwYXltZW50cwAABAJkawkBBXZhbHVlAQkAkQMCCAUCZGYIcGF5bWVudHMAAQQCZGwJAQJjagkJANgEAQgFAmRmDXRyYW5zYWN0aW9uSWQFAmNrCAUCZGoGYW1vdW50CAUCZGoHYXNzZXRJZAgFAmRrBmFtb3VudAgFAmRrB2Fzc2V0SWQJAKUIAQgFAmRmBmNhbGxlcgcFAmNxBAJiVQkBDXBhcnNlSW50VmFsdWUBCAUCZGwCXzgDAwMJAQJhRgAGCQAAAgUCYlUFAWwGCQAAAgUCYlUFAW4JAAIBCQCsAgICLFB1dCBvcGVyYXRpb24gaXMgYmxvY2tlZCBieSBhZG1pbi4gU3RhdHVzID0gCQCkAwEFAmJVBQJkbAECZG0BAmRuBAJkbwkA/AcEBQJhRAIEZW1pdAkAzAgCBQJkbgUDbmlsBQNuaWwDCQAAAgUCZG8FAmRvBAJkcAQCZHEFAmRvAwkAAQIFAmRxAgdBZGRyZXNzBAJkcgUCZHEJAPwHBAUCZHICBGVtaXQJAMwIAgUCZG4FA25pbAUDbmlsBQR1bml0AwkAAAIFAmRwBQJkcAUCZG4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BAmRzAQJkbgQCZHQJAGsDBQJkbgUCYWUFAWIJAJQKAgkAZQIFAmRuBQJkdAUCZHQBAmR1BAJkdgJkdwFYAVkEAmR4CQAAAgUBWQUEdW5pdAQCZHkJAQJicQEJAQJhTQEFAmFVBAJkegkBAmJxAQkBAmFNAQUCYVYEAmRBAwkAAAIFAmR3BQJhVQYDCQAAAgUCZHcFAmFWBwkBAmFCAQINaW52YWxpZCBhc3NldAQCZEIDBQJkeAkAlAoCBQJkeQUCZHoDBQJkQQkAlAoCCQBlAgUCZHkFAmR2BQJkegkAlAoCBQJkeQkAZQIFAmR6BQJkdgQCZEMIBQJkQgJfMQQCZEQIBQJkQgJfMgQCZEUDBQJkQQkAlAoCBQJkdgAACQCUCgIAAAUCZHYEAmRGCAUCZEUCXzEEAmRHCAUCZEUCXzIEAmRICAkBAmRzAQUCZEYCXzEEAmRJCAkBAmRzAQUCZEcCXzEEAmRKCQECZHMBBQJkdgQCZEsIBQJkSgJfMQQCZHQIBQJkSgJfMgQCZEwJAGQCBQJkQwUCZEgEAmRNCQBkAgUCZEQFAmRJBAJkTgkBAmJzAgkBAUQCBQJkTQUCYVgJAQFEAgUCZEwFAmFXBAJkTwkBAUcCBQJkTgUBYgQCZFADBQJkQQUCZEMFAmREBAJkUQkAtgIBBQJkUAQCZFIJALYCAQgJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkA7AcBBQJhVAkArAICCQCsAgICBmFzc2V0IAkA2AQBBQJhVAIOIGRvZXNuJ3QgZXhpc3QIcXVhbnRpdHkEAmRTAwkAvwICBQJkUgUBZgYJAQJhQgECImluaXRpYWwgZGVwb3NpdCByZXF1aXJlcyBhbGwgY29pbnMDCQAAAgUCZFMFAmRTBAJkVAkAtgIBBQJkSwQCZFUJAJYDAQkAzAgCAAAJAMwIAgkAoAMBCQC6AgIJALkCAgUCZFIJALgCAgkBCnNxcnRCaWdJbnQECQC3AgIFAWQJALoCAgkAuQICBQJkVAUBZAUCZFEAEgASBQRET1dOBQFkBQFkBQNuaWwEAmNQAwUCZHgFA25pbAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAVMABQJkTwkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAVQCBQZoZWlnaHQIBQlsYXN0QmxvY2sJdGltZXN0YW1wBQJkTwkAzAgCCQELU3RyaW5nRW50cnkCCQEBVwIJAKUIAQkBBXZhbHVlAQUBWAkA2AQBCQEFdmFsdWUBBQFZCQECYmIKBQJkRgUCZEcFAmRVBQJkTwAAAAAFBmhlaWdodAgFCWxhc3RCbG9jawl0aW1lc3RhbXAAAAAABQNuaWwEAmRWCQECYnMCCQEBRAIFAmREBQJhWAkBAUQCBQJkQwUCYVcEAmRXCQEBRwIFAmRWBQFiBAJkWAkBAU4BCQBpAgkAaAIJAGUCBQJkTwUCZFcFAWIFAmRXCQCWCgQFAmRVBQJjUAUCZHQFAmRYCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQJkWQUCZFoCZEsCZHcBWAFZBAJkeAkAAAIFAVkFBHVuaXQEAmVhCQDMCAIDCQAAAgUCZHcFAmFUBgkBAmFCAQIQaW52YWxpZCBscCBhc3NldAUDbmlsAwkAAAIFAmVhBQJlYQQCZWIDCQAAAgUCZFoFAmFVBgMJAAACBQJkWgUCYVYHCQECYUIBAg1pbnZhbGlkIGFzc2V0BAJlYwMFAmViCQC2AgEJAQJicQEJAQJhTQEFAmFVCQC2AgEJAQJicQEJAQJhTQEFAmFWBAJlZAkBAmJxAQkBAmFNAQUCYVUEAmVlCQECYnEBCQECYU0BBQJhVgQCZWYDBQJlYgUCZWQFAmVlBAJlZwkAtgIBBQJlZgQCZFIJALYCAQgJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkA7AcBBQJhVAkArAICCQCsAgICBmFzc2V0IAkA2AQBBQJhVAIOIGRvZXNuJ3QgZXhpc3QIcXVhbnRpdHkEAmVoCQC2AgEFAmRLBAJlaQkAlgMBCQDMCAIAAAkAzAgCCQCgAwEJALoCAgkAuQICBQJlYwkAuAICBQFkCQB2BgkAuAICBQFkCQC6AgIJALkCAgUCZWgFAWQFAmRSABIFAWgAAAASBQRET1dOBQFkBQNuaWwEAmVqCQECZHMBBQJlaQQCZWsIBQJlagJfMQQCZHQIBQJlagJfMgQCZWwDBQJlYgkAlgoEBQJlawAACQBlAgUCZWQFAmVpBQJlZQkAlgoEAAAFAmVrBQJlZAkAZQIFAmVlBQJlaQQCZW0IBQJlbAJfMQQCZW4IBQJlbAJfMgQCZW8IBQJlbAJfMwQCZXAIBQJlbAJfNAQCZE4JAQJicwIJAQFEAgUCZXAFAmFYCQEBRAIFAmVvBQJhVwQCZE8JAQFHAgUCZE4FAWIEAmNQAwUCZHgFA25pbAkAzAgCCQELU3RyaW5nRW50cnkCCQEBWgIJAKUIAQkBBXZhbHVlAQUBWAkA2AQBCQEFdmFsdWUBBQFZCQECYm0GBQJlbQUCZW4FAmRLBQJkTwUGaGVpZ2h0CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAVMABQJkTwkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAVQCBQZoZWlnaHQIBQlsYXN0QmxvY2sJdGltZXN0YW1wBQJkTwUDbmlsBAJkVgkBAmJzAgkBAUQCBQJlZQUCYVgJAQFEAgUCZWQFAmFXBAJkVwkBAUcCBQJkVgUBYgQCZFgJAQFOAQkAaQIJAGgCCQBlAgUCZE8FAmRXBQFiBQJkVwkAlgoEBQJlawUCY1AFAmR0BQJkWAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgECZXEABAJkcQkAoggBCQEBUQADCQABAgUCZHECBlN0cmluZwQCZXIFAmRxCQDZBAEFAmVyAwkAAQIFAmRxAgRVbml0BQR1bml0CQACAQILTWF0Y2ggZXJyb3IBAmVzAAQCZHEJAKIIAQkBAVIAAwkAAQIFAmRxAgZTdHJpbmcEAmVyBQJkcQkA2QQBBQJlcgMJAAECBQJkcQIEVW5pdAUEdW5pdAkAAgECC01hdGNoIGVycm9yAQJldAECZGYEAmV1CQACAQIRUGVybWlzc2lvbiBkZW5pZWQEAmRxCQECZXEAAwkAAQIFAmRxAgpCeXRlVmVjdG9yBAJldgUCZHEDCQAAAggFAmRmD2NhbGxlclB1YmxpY0tleQUCZXYGBQJldQMJAAECBQJkcQIEVW5pdAMJAAACCAUCZGYGY2FsbGVyBQR0aGlzBgUCZXUJAAIBAgtNYXRjaCBlcnJvchkCZGYBCnNldE1hbmFnZXIBAmV3BAJleAkBAmV0AQUCZGYDCQAAAgUCZXgFAmV4BAJleQkA2QQBBQJldwMJAAACBQJleQUCZXkJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAVIABQJldwUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmRmAQ5jb25maXJtTWFuYWdlcgAEAmV6CQECZXMABAJlQQMJAQlpc0RlZmluZWQBBQJlegYJAAIBAhJObyBwZW5kaW5nIG1hbmFnZXIDCQAAAgUCZUEFAmVBBAJlQgMJAAACCAUCZGYPY2FsbGVyUHVibGljS2V5CQEFdmFsdWUBBQJlegYJAAIBAhtZb3UgYXJlIG5vdCBwZW5kaW5nIG1hbmFnZXIDCQAAAgUCZUIFAmVCCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQFRAAkA2AQBCQEFdmFsdWUBBQJlegkAzAgCCQELRGVsZXRlRW50cnkBCQEBUgAFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJkZgEDcHV0AgJjawJlQwMJAGYCAAAFAmNrCQACAQIgSW52YWxpZCBzbGlwcGFnZVRvbGVyYW5jZSBwYXNzZWQEAmRsCQECZGkDBQJkZgUCY2sGBAJjTQgFAmRsAl8yBAJiUggFAmRsAl83BAJjaQgFAmRsAl85BAJjTggFAmRsA18xMAQCY08IBQJkbANfMTEEAmVECAUCZGwDXzEyBAJlRQgFAmRsA18xMwQCZG8JAPwHBAUCYUQCBGVtaXQJAMwIAgUCY00FA25pbAUDbmlsAwkAAAIFAmRvBQJkbwQCZHAEAmRxBQJkbwMJAAECBQJkcQIHQWRkcmVzcwQCZHIFAmRxCQD8BwQFAmRyAgRlbWl0CQDMCAIFAmNNBQNuaWwFA25pbAUEdW5pdAMJAAACBQJkcAUCZHAEAmVGAwkAZgIFAmNOAAAJAPwHBAUCYmECA3B1dAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQJlRAUCY04FA25pbAUDbmlsAwkAAAIFAmVGBQJlRgQCZUcDCQBmAgUCY08AAAkA/AcEBQJiYQIDcHV0BQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFAmVFBQJjTwUDbmlsBQNuaWwDCQAAAgUCZUcFAmVHBAJlSAMFAmVDBAJlSQkA/AcEBQJhWgIFc3Rha2UFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUCYlIFAmNNBQNuaWwDCQAAAgUCZUkFAmVJBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAmRmBmNhbGxlcgUCY00FAmJSBQNuaWwJAM4IAgUCY2kFAmVICQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmRmAQpwdXRGb3JGcmVlAQJlSgMJAGYCAAAFAmVKCQACAQIUSW52YWxpZCB2YWx1ZSBwYXNzZWQEAmRsCQECZGkDBQJkZgUCZUoHCAUCZGwCXzkCZGYBCXB1dE9uZVRrbgICZUsCZUwEAmVNCgACZU4JAPwHBAUCYUQCKGlzUG9vbE9uZVRva2VuT3BlcmF0aW9uc0Rpc2FibGVkUkVBRE9OTFkJAMwIAgkApQgBBQR0aGlzBQNuaWwFA25pbAMJAAECBQJlTgIHQm9vbGVhbgUCZU4JAAIBCQCsAgIJAAMBBQJlTgIcIGNvdWxkbid0IGJlIGNhc3QgdG8gQm9vbGVhbgQCZU8DAwMJAQJhRgAGCQAAAgUCYVMFAWwGCQAAAgUCYVMFAW4GBQJlTQQCZWEJAMwIAgMJAQEhAQUCZU8GCQECYUIBAiFwdXQgb3BlcmF0aW9uIGlzIGJsb2NrZWQgYnkgYWRtaW4JAMwIAgMJAAACCQCQAwEIBQJkZghwYXltZW50cwABBgkBAmFCAQIeZXhhY3RseSAxIHBheW1lbnQgYXJlIGV4cGVjdGVkBQNuaWwDCQAAAgUCZWEFAmVhBAJlUAkAkQMCCAUCZGYIcGF5bWVudHMAAAQCZHcIBQJlUAdhc3NldElkBAJkdggFAmVQBmFtb3VudAQBWAgFAmRmBmNhbGxlcgQBWQgFAmRmDXRyYW5zYWN0aW9uSWQEAmVRCQECZHUEBQJkdgUCZHcFAVgFAVkEAmVSCAUCZVECXzEEAmNQCAUCZVECXzIEAmR0CAUCZVECXzMEAmVTCAUCZVECXzQEAmVUAwMJAGYCBQJlSwAACQBmAgUCZUsFAmVSBwkBAmFCAQkAuQkCCQDMCAICH2Ftb3VudCB0byByZWNlaXZlIGlzIGxlc3MgdGhhbiAJAMwIAgkApAMBBQJlSwUDbmlsAgAFAmVSBAJkbwkBAmRtAQUCZVQDCQAAAgUCZG8FAmRvBAJlSAMFAmVMBAJlVQkA/AcEBQJhWgIFc3Rha2UFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUCYVQFAmVUBQNuaWwDCQAAAgUCZVUFAmVVBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAmRmBmNhbGxlcgUCZVQFAmFUBQNuaWwEAmVWAwkAZgIFAmR0AAAJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUCYUUFAmR0BQJkdwUDbmlsBQNuaWwJAJQKAgkAzggCCQDOCAIFAmNQBQJlSAUCZVYFAmVUCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmRmARFwdXRPbmVUa25SRUFET05MWQICZHcCZHYEAmVXCQECZHUEBQJkdgkBAmFLAQUCZHcFBHVuaXQFBHVuaXQEAmVSCAUCZVcCXzEEAmNQCAUCZVcCXzIEAmR0CAUCZVcCXzMEAmVTCAUCZVcCXzQJAJQKAgUDbmlsCQCVCgMFAmVSBQJkdAUCZVMCZGYBCWdldE9uZVRrbgICZVgCZUsEAmVNCgACZU4JAPwHBAUCYUQCKGlzUG9vbE9uZVRva2VuT3BlcmF0aW9uc0Rpc2FibGVkUkVBRE9OTFkJAMwIAgkApQgBBQR0aGlzBQNuaWwFA25pbAMJAAECBQJlTgIHQm9vbGVhbgUCZU4JAAIBCQCsAgIJAAMBBQJlTgIcIGNvdWxkbid0IGJlIGNhc3QgdG8gQm9vbGVhbgQCZVkDAwkBAmFGAAYJAAACBQJhUwUBbgYFAmVNBAJlYQkAzAgCAwkBASEBBQJlWQYJAQJhQgECIWdldCBvcGVyYXRpb24gaXMgYmxvY2tlZCBieSBhZG1pbgkAzAgCAwkAAAIJAJADAQgFAmRmCHBheW1lbnRzAAEGCQECYUIBAh5leGFjdGx5IDEgcGF5bWVudCBhcmUgZXhwZWN0ZWQFA25pbAMJAAACBQJlYQUCZWEEAmRaCQECYUsBBQJlWAQCZVAJAJEDAggFAmRmCHBheW1lbnRzAAAEAmR3CAUCZVAHYXNzZXRJZAQCZEsIBQJlUAZhbW91bnQEAVgIBQJkZgZjYWxsZXIEAVkIBQJkZg10cmFuc2FjdGlvbklkBAJlWgkBAmRZBQUCZFoFAmRLBQJkdwUBWAUBWQQCZmEIBQJlWgJfMQQCY1AIBQJlWgJfMgQCZHQIBQJlWgJfMwQCZVMIBQJlWgJfNAQCZG4DAwkAZgIFAmVLAAAJAGYCBQJlSwUCZmEHCQECYUIBCQC5CQIJAMwIAgIfYW1vdW50IHRvIHJlY2VpdmUgaXMgbGVzcyB0aGFuIAkAzAgCCQCkAwEFAmVLBQNuaWwCAAUCZmEEAmZiCQD8BwQFAmFEAgRidXJuCQDMCAIFAmRLBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFAmR3BQJkSwUDbmlsAwkAAAIFAmZiBQJmYgQCZmMJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUBWAUCZG4FAmRaBQNuaWwEAmVWAwkAZgIFAmR0AAAJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUCYUUFAmR0BQJkWgUDbmlsBQNuaWwJAJQKAgkAzggCCQDOCAIFAmNQBQJmYwUCZVYFAmRuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmRmARFnZXRPbmVUa25SRUFET05MWQICZFoCZEsEAmZkCQECZFkFCQECYUsBBQJkWgUCZEsFAmFUBQR1bml0BQR1bml0BAJmYQgFAmZkAl8xBAJjUAgFAmZkAl8yBAJkdAgFAmZkAl8zBAJlUwgFAmZkAl80CQCUCgIFA25pbAkAlQoDBQJmYQUCZHQFAmVTAmRmARN1bnN0YWtlQW5kR2V0T25lVGtuAwJmZQJlWAJlSwQCZU0KAAJlTgkA/AcEBQJhRAIoaXNQb29sT25lVG9rZW5PcGVyYXRpb25zRGlzYWJsZWRSRUFET05MWQkAzAgCCQClCAEFBHRoaXMFA25pbAUDbmlsAwkAAQIFAmVOAgdCb29sZWFuBQJlTgkAAgEJAKwCAgkAAwEFAmVOAhwgY291bGRuJ3QgYmUgY2FzdCB0byBCb29sZWFuBAJlWQMDCQECYUYABgkAAAIFAmFTBQFuBgUCZU0EAmVhCQDMCAIDCQEBIQEFAmVZBgkBAmFCAQIhZ2V0IG9wZXJhdGlvbiBpcyBibG9ja2VkIGJ5IGFkbWluCQDMCAIDCQAAAgkAkAMBCAUCZGYIcGF5bWVudHMAAAYJAQJhQgECGG5vIHBheW1lbnRzIGFyZSBleHBlY3RlZAUDbmlsAwkAAAIFAmVhBQJlYQQCZFoJAQJhSwEFAmVYBAFYCAUCZGYGY2FsbGVyBAFZCAUCZGYNdHJhbnNhY3Rpb25JZAQCZmYJAPwHBAUCYVoCB3Vuc3Rha2UJAMwIAgkA2AQBBQJhVAkAzAgCBQJmZQUDbmlsBQNuaWwDCQAAAgUCZmYFAmZmBAJmZwkBAmRZBQUCZFoFAmZlBQJhVAUBWAUBWQQCZmEIBQJmZwJfMQQCY1AIBQJmZwJfMgQCZHQIBQJmZwJfMwQCZVMIBQJmZwJfNAQCZG4DAwkAZgIFAmVLAAAJAGYCBQJlSwUCZmEHCQECYUIBCQC5CQIJAMwIAgIfYW1vdW50IHRvIHJlY2VpdmUgaXMgbGVzcyB0aGFuIAkAzAgCCQCkAwEFAmVLBQNuaWwCAAUCZmEEAmZiCQD8BwQFAmFEAgRidXJuCQDMCAIFAmZlBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFAmFUBQJmZQUDbmlsAwkAAAIFAmZiBQJmYgQCZmMJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAmRmBmNhbGxlcgUCZG4FAmRaBQNuaWwEAmVWAwkAZgIFAmR0AAAJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUCYUUFAmR0BQJkWgUDbmlsBQNuaWwJAJQKAgkAzggCCQDOCAIFAmNQBQJmYwUCZVYFAmRuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmRmAQNnZXQABAJjQQkBAmRlAQUCZGYEAmZoCAUCY0ECXzEEAmNoCAUCY0ECXzIEAmRoCAUCY0ECXzMEAmJQCAUCY0ECXzQEAmNpCAUCY0ECXzUEAmZpCQD8BwQFAmFEAgRidXJuCQDMCAIFAmRoBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFAmJQBQJkaAUDbmlsAwkAAAIFAmZpBQJmaQUCY2kJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CZGYBCWdldE5vTGVzcwICZmoCZmsEAmNBCQECZGUBBQJkZgQCY2cIBQJjQQJfMQQCY2gIBQJjQQJfMgQCZGgIBQJjQQJfMwQCYlAIBQJjQQJfNAQCY2kIBQJjQQJfNQMJAGYCBQJmagUCY2cJAAIBCQCsAgIJAKwCAgkArAICAhxub0xlc3NUaGVuQW10QXNzZXQgZmFpbGVkOiAgCQCkAwEFAmNnAgMgPCAJAKQDAQUCZmoDCQBmAgUCZmsFAmNoCQACAQkArAICCQCsAgIJAKwCAgIdbm9MZXNzVGhlblByaWNlQXNzZXQgZmFpbGVkOiAJAKQDAQUCY2gCAyA8IAkApAMBBQJmawQCZmkJAPwHBAUCYUQCBGJ1cm4JAMwIAgUCZGgFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUCYlAFAmRoBQNuaWwDCQAAAgUCZmkFAmZpBQJjaQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJkZgENdW5zdGFrZUFuZEdldAECZG4EAmZsAwkBAiE9AgkAkAMBCAUCZGYIcGF5bWVudHMAAAkAAgECGE5vIHBheW1lbnRzIGFyZSBleHBlY3RlZAYDCQAAAgUCZmwFAmZsBAJiRQkBAmFIAAQCYlIJANkEAQkAkQMCBQJiRQUBcQQCZmYJAPwHBAUCYVoCB3Vuc3Rha2UJAMwIAgkA2AQBBQJiUgkAzAgCBQJkbgUDbmlsBQNuaWwDCQAAAgUCZmYFAmZmBAJjQQkBAmJOBAkA2AQBCAUCZGYNdHJhbnNhY3Rpb25JZAkA2AQBBQJiUgUCZG4IBQJkZgZjYWxsZXIEAmJVCQENcGFyc2VJbnRWYWx1ZQEIBQJjQQJfOQQCY2kIBQJjQQNfMTAEAmZtAwMJAQJhRgAGCQAAAgUCYlUFAW4JAAIBCQCsAgICLEdldCBvcGVyYXRpb24gaXMgYmxvY2tlZCBieSBhZG1pbi4gU3RhdHVzID0gCQCkAwEFAmJVBgMJAAACBQJmbQUCZm0EAmZpCQD8BwQFAmFEAgRidXJuCQDMCAIFAmRuBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFAmJSBQJkbgUDbmlsAwkAAAIFAmZpBQJmaQUCY2kJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CZGYBCGFjdGl2YXRlAgJmbgJmbwMJAQIhPQIJAKUIAQgFAmRmBmNhbGxlcgkApQgBBQJhRAkAAgECEnBlcm1pc3Npb25zIGRlbmllZAkAlAoCCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQJhYQAFAmZuCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQJhYgAFAmZvBQNuaWwCB3N1Y2Nlc3MCZGYBHGdldFBvb2xDb25maWdXcmFwcGVyUkVBRE9OTFkACQCUCgIFA25pbAkBAmFIAAJkZgEcZ2V0QWNjQmFsYW5jZVdyYXBwZXJSRUFET05MWQECYnIJAJQKAgUDbmlsCQECYnEBBQJicgJkZgEZY2FsY1ByaWNlc1dyYXBwZXJSRUFET05MWQMCYnkCYnoCYkQEAmJNCQECYkMDBQJieQUCYnoFAmJECQCUCgIFA25pbAkAzAgCCQCmAwEJAJEDAgUCYk0AAAkAzAgCCQCmAwEJAJEDAgUCYk0AAQkAzAgCCQCmAwEJAJEDAgUCYk0AAgUDbmlsAmRmARR0b1gxOFdyYXBwZXJSRUFET05MWQIBRQFGCQCUCgIFA25pbAkApgMBCQEBRAIFAUUFAUYCZGYBFmZyb21YMThXcmFwcGVyUkVBRE9OTFkCAUgBSQkAlAoCBQNuaWwJAQFHAgkApwMBBQFIBQFJAmRmAR5jYWxjUHJpY2VCaWdJbnRXcmFwcGVyUkVBRE9OTFkCAmJ0AmJ1CQCUCgIFA25pbAkApgMBCQECYnMCCQCnAwEFAmJ0CQCnAwEFAmJ1AmRmASNlc3RpbWF0ZVB1dE9wZXJhdGlvbldyYXBwZXJSRUFET05MWQkCYk8CY2sCY2wCY20CY24CY28BWAJjcAJjcQkAlAoCBQNuaWwJAQJjagkFAmJPBQJjawUCY2wFAmNtBQJjbgUCY28FAVgFAmNwBQJjcQJkZgEjZXN0aW1hdGVHZXRPcGVyYXRpb25XcmFwcGVyUkVBRE9OTFkEAmJPAmJQAmJRAVgEAmNBCQECYk4EBQJiTwUCYlAFAmJRCQERQGV4dHJOYXRpdmUoMTA2MikBBQFYCQCUCgIFA25pbAkAnAoKCAUCY0ECXzEIBQJjQQJfMggFAmNBAl8zCAUCY0ECXzQIBQJjQQJfNQgFAmNBAl82CAUCY0ECXzcJAKYDAQgFAmNBAl84CAUCY0ECXzkIBQJjQQNfMTACZGYBDXN0YXRzUkVBRE9OTFkABAJiRQkBAmFIAAQCYlIJANkEAQkAkQMCBQJiRQUBcQQCY1MJAJEDAgUCYkUFAXIEAmNUCQCRAwIFAmJFBQFzBAJjdAkAkQMCBQJiRQUBdgQCY3UJAJEDAgUCYkUFAXcEAmJGCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCYkUFAXQEAmJHCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCYkUFAXUEAmZwCAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQDsBwEFAmJSCQCsAgIJAKwCAgIGQXNzZXQgCQDYBAEFAmJSAg4gZG9lc24ndCBleGlzdAhxdWFudGl0eQQCY1UJAQJicQEFAmNTBAJjVgkBAmJxAQUCY1QEAmZxAwkAAAIFAmZwAAAJAMwIAgUBZQkAzAgCBQFlCQDMCAIFAWUFA25pbAkBAmJDAwUCY1UFAmNWBQJmcAQCY2IAAAQCZnIJAQFHAgkAkQMCBQJmcQABBQFiBAJmcwkBAUcCCQCRAwIFAmZxAAIFAWIEAmZ0CQEFdmFsdWUBCQCaCAIFAmFECQECYXABCQClCAEFBHRoaXMJAJQKAgUDbmlsCQC5CQIJAMwIAgIOJWQlZCVkJWQlZCVkJWQJAMwIAgkApAMBBQJjVQkAzAgCCQCkAwEFAmNWCQDMCAIJAKQDAQUCZnAJAMwIAgkApAMBBQJjYgkAzAgCCQCkAwEFAmZyCQDMCAIJAKQDAQUCZnMJAMwIAgkApAMBBQJmdAUDbmlsBQFqAmRmASBldmFsdWF0ZVB1dEJ5QW1vdW50QXNzZXRSRUFET05MWQECY2wEAmJFCQECYUgABAJiUgkA2QQBCQCRAwIFAmJFBQFxBAJjcgkAkQMCBQJiRQUBcgQCYlMJANkEAQUCY3IEAmNzCQCRAwIFAmJFBQFzBAJiVAkA2QQBBQJjcwQCYkYJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJiRQUBdAQCYkcJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJiRQUBdQQCYlUJAJEDAgUCYkUFAXAEAmZwCAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQDsBwEFAmJSCQCsAgIJAKwCAgIGQXNzZXQgCQDYBAEFAmJSAg4gZG9lc24ndCBleGlzdAhxdWFudGl0eQQCY1UJAQJicQEFAmNyBAJjVgkBAmJxAQUCY3MEAmJBCQEBRAIFAmNVBQJiRgQCYkIJAQFEAgUCY1YFAmJHBAJjYQMJAAACBQJmcAAABQFlCQECYnMCBQJiQgUCYkEEAmN4CQEBRAIFAmNsBQJiRgQCY3kJALwCAwUCY3gFAmNhBQFkBAJjbgkBAUcCBQJjeQUCYkcEAmRsCQECY2oJAgAAoMIeBQJjbAUCYlMFAmNuBQJiVAIABgcEAmNJCAUCZGwCXzEEAmZ1CAUCZGwCXzMEAmJXCAUCZGwCXzQEAmJZCAUCZGwCXzUEAmJWCAUCZGwCXzYJAJQKAgUDbmlsCQC5CQIJAMwIAgIQJWQlZCVkJWQlZCVkJWQlZAkAzAgCCQCkAwEFAmNJCQDMCAIJAKQDAQkBAUcCBQJjYQUBYgkAzAgCCQCkAwEFAmJXCQDMCAIJAKQDAQUCYlkJAMwIAgkApAMBBQJiVgkAzAgCBQJiVQkAzAgCCQCkAwEFAmNsCQDMCAIJAKQDAQUCY24FA25pbAUBagJkZgEfZXZhbHVhdGVQdXRCeVByaWNlQXNzZXRSRUFET05MWQECY24EAmJFCQECYUgABAJiUgkA2QQBCQCRAwIFAmJFBQFxBAJjcgkAkQMCBQJiRQUBcgQCYlMJANkEAQUCY3IEAmNzCQCRAwIFAmJFBQFzBAJiVAkA2QQBBQJjcwQCYkYJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJiRQUBdAQCYkcJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJiRQUBdQQCYlUJAJEDAgUCYkUFAXAEAmZwCAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQDsBwEFAmJSCQCsAgIJAKwCAgIGQXNzZXQgCQDYBAEFAmJSAg4gZG9lc24ndCBleGlzdAhxdWFudGl0eQQCZnYJAQJicQEFAmNyBAJmdwkBAmJxAQUCY3MEAmZ4CQEBRAIFAmZ2BQJiRgQCZnkJAQFEAgUCZncFAmJHBAJjYQMJAAACBQJmcAAABQFlCQECYnMCBQJmeQUCZngEAmN5CQEBRAIFAmNuBQJiRwQCY3gJALwCAwUCY3kFAWQFAmNhBAJjbAkBAUcCBQJjeAUCYkYEAmRsCQECY2oJAgAAoMIeBQJjbAUCYlMFAmNuBQJiVAIABgcEAmNJCAUCZGwCXzEEAmZ1CAUCZGwCXzMEAmJXCAUCZGwCXzQEAmJZCAUCZGwCXzUEAmJWCAUCZGwCXzYJAJQKAgUDbmlsCQC5CQIJAMwIAgIQJWQlZCVkJWQlZCVkJWQlZAkAzAgCCQCkAwEFAmNJCQDMCAIJAKQDAQkBAUcCBQJjYQUBYgkAzAgCCQCkAwEFAmJXCQDMCAIJAKQDAQUCYlkJAMwIAgkApAMBBQJiVgkAzAgCBQJiVQkAzAgCCQCkAwEFAmNsCQDMCAIJAKQDAQUCY24FA25pbAUBagJkZgETZXZhbHVhdGVHZXRSRUFET05MWQICZnoCZkEEAmNBCQECYk4EAgAFAmZ6BQJmQQUEdGhpcwQCY2cIBQJjQQJfMQQCY2gIBQJjQQJfMgQCYlcIBQJjQQJfNQQCYlkIBQJjQQJfNgQCYlYIBQJjQQJfNwQCY2IIBQJjQQJfOAQCYlUJAQ1wYXJzZUludFZhbHVlAQgFAmNBAl85CQCUCgIFA25pbAkAuQkCCQDMCAICDiVkJWQlZCVkJWQlZCVkCQDMCAIJAKQDAQUCY2cJAMwIAgkApAMBBQJjaAkAzAgCCQCkAwEFAmJXCQDMCAIJAKQDAQUCYlkJAMwIAgkApAMBBQJiVgkAzAgCCQCmAwEFAmNiCQDMCAIJAKQDAQUCYlUFA25pbAUBagECZkIBAmZDAAQCZkQEAmRxCQECZXEAAwkAAQIFAmRxAgpCeXRlVmVjdG9yBAJldgUCZHEFAmV2AwkAAQIFAmRxAgRVbml0CAUCZkIPc2VuZGVyUHVibGljS2V5CQACAQILTWF0Y2ggZXJyb3IEAmRxBQJmQgMJAAECBQJkcQIFT3JkZXIEAmNSBQJkcQQCZkUJAQJhRwAEAmF1CQECY1EBBQJjUgQCYXYJAPQDAwgFAmNSCWJvZHlCeXRlcwkAkQMCCAUCY1IGcHJvb2ZzAAAIBQJjUg9zZW5kZXJQdWJsaWNLZXkEAmF3CQD0AwMIBQJjUglib2R5Qnl0ZXMJAJEDAggFAmNSBnByb29mcwABBQJmRQMDAwUCYXUFAmF2BwUCYXcHBgkBAmF0AwUCYXUFAmF2BQJhdwMJAAECBQJkcQIUU2V0U2NyaXB0VHJhbnNhY3Rpb24EAmVyBQJkcQQCZkYJAPYDAQkBBXZhbHVlAQgFAmVyBnNjcmlwdAQCZkcJANsEAQkBBXZhbHVlAQkAnQgCBQJhRAkBAmFyAAQCZkgJAPEHAQUEdGhpcwMDCQAAAgUCZkcFAmZGCQECIT0CBQJmSAUCZkYHBgkA9AMDCAUCZkIJYm9keUJ5dGVzCQCRAwIIBQJmQgZwcm9vZnMAAAUCZkQJAPQDAwgFAmZCCWJvZHlCeXRlcwkAkQMCCAUCZkIGcHJvb2ZzAAAFAmZE+JLASw==", "chainId": 84, "height": 2297978, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: J8fPypMAgDDmdoZKDmKQik3nviLtSYREhL7WtUe9o6jw Next: HMvaNqbQ9Bs8XTPhuNgKdTT8Cg1umABbowb8esc1dn8p Diff:
OldNewDifferences
1010 let scale18 = toBigInt(1000000000000000000)
1111
1212 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"
1321
1422 let SEP = "__"
1523
6068 func toScale (amt,resScale,curScale) = fraction(amt, resScale, curScale)
6169
6270
63-func abs (val) = if ((zeroBigInt > val))
71+func abs (val) = if ((0 > val))
72+ then -(val)
73+ else val
74+
75+
76+func absBigInt (val) = if ((zeroBigInt > val))
6477 then -(val)
6578 else val
6679
92105 func pa () = "%s__priceAsset"
93106
94107
108+let keyFee = "%s__fee"
109+
110+let feeDefault = fraction(5, scale8, 10000)
111+
112+let fee = valueOrElse(getInteger(this, keyFee), feeDefault)
113+
95114 func keyFactoryConfig () = "%s__factoryConfig"
96115
97116
116135 func keyAllowedLpScriptHash () = "%s__allowedLpScriptHash"
117136
118137
138+let keyFeeCollectorAddress = "%s__feeCollectorAddress"
139+
119140 func throwOrderError (orderValid,senderValid,matcherValid) = throw(((((("order validation failed: orderValid=" + toString(orderValid)) + " senderValid=") + toString(senderValid)) + " matcherValid=") + toString(matcherValid)))
120141
121142
125146 func getIntOrFail (address,key) = valueOrErrorMessage(getInteger(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
126147
127148
149+func throwErr (msg) = throw(makeString(["lp.ride:", msg], " "))
150+
151+
128152 let factoryContract = addressFromStringValue(getStringOrFail(this, fc()))
153+
154+let feeCollectorAddress = addressFromStringValue(getStringOrFail(factoryContract, keyFeeCollectorAddress))
129155
130156 func isGlobalShutdown () = valueOrElse(getBoolean(factoryContract, keyAllPoolsShutdown()), false)
131157
142168 }
143169
144170
171+func parseAssetId (input) = if ((input == wavesString))
172+ then unit
173+ else fromBase58String(input)
174+
175+
176+func assetIdToString (input) = if ((input == unit))
177+ then wavesString
178+ else toBase58String(value(input))
179+
180+
181+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]))
182+
183+
184+let poolConfigParsed = parsePoolConfig(getPoolConfig())
185+
186+let $t075437709 = poolConfigParsed
187+
188+let cfgPoolAddress = $t075437709._1
189+
190+let cfgPoolStatus = $t075437709._2
191+
192+let cfgLpAssetId = $t075437709._3
193+
194+let cfgAmountAssetId = $t075437709._4
195+
196+let cfgPriceAssetId = $t075437709._5
197+
198+let cfgAmountAssetDecimals = $t075437709._6
199+
200+let cfgPriceAssetDecimals = $t075437709._7
201+
145202 func getFactoryConfig () = split(getStringOrFail(factoryContract, keyFactoryConfig()), SEP)
146203
204+
205+let stakingContract = valueOrErrorMessage(addressFromString(getFactoryConfig()[idxFactoryStakingContract]), "incorrect staking address")
206+
207+let slippageContract = valueOrErrorMessage(addressFromString(getFactoryConfig()[idxFactorySlippageContract]), "incorrect staking address")
147208
148209 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)
149210
260321 }
261322 else {
262323 let curPriceX18 = calcPriceBigInt(prBalanceX18, amBalanceX18)
263- let slippageX18 = fraction(abs((curPriceX18 - userPriceX18)), scale18, curPriceX18)
324+ let slippageX18 = fraction(absBigInt((curPriceX18 - userPriceX18)), scale18, curPriceX18)
264325 let slippageToleranceX18 = toX18(slippageTolerance, scale8)
265326 if (if ((curPriceX18 != zeroBigInt))
266327 then (slippageX18 > slippageToleranceX18)
380441 }
381442
382443
444+func emit (amount) = {
445+ let emitInv = invoke(factoryContract, "emit", [amount], nil)
446+ if ((emitInv == emitInv))
447+ then {
448+ let emitInvLegacy = match emitInv {
449+ case legacyFactoryContract: Address =>
450+ invoke(legacyFactoryContract, "emit", [amount], nil)
451+ case _ =>
452+ unit
453+ }
454+ if ((emitInvLegacy == emitInvLegacy))
455+ then amount
456+ else throw("Strict value is not equal to itself.")
457+ }
458+ else throw("Strict value is not equal to itself.")
459+ }
460+
461+
462+func takeFee (amount) = {
463+ let feeAmount = fraction(amount, fee, scale8)
464+ $Tuple2((amount - feeAmount), feeAmount)
465+ }
466+
467+
468+func calcPutOneToken (paymentAmountRaw,paymentAssetId,userAddress,txId) = {
469+ let isEval = (txId == unit)
470+ let amountBalanceRaw = getAccBalance(assetIdToString(cfgAmountAssetId))
471+ let priceBalanceRaw = getAccBalance(assetIdToString(cfgPriceAssetId))
472+ let paymentInAmountAsset = if ((paymentAssetId == cfgAmountAssetId))
473+ then true
474+ else if ((paymentAssetId == cfgPriceAssetId))
475+ then false
476+ else throwErr("invalid asset")
477+ let $t02257022863 = if (isEval)
478+ then $Tuple2(amountBalanceRaw, priceBalanceRaw)
479+ else if (paymentInAmountAsset)
480+ then $Tuple2((amountBalanceRaw - paymentAmountRaw), priceBalanceRaw)
481+ else $Tuple2(amountBalanceRaw, (priceBalanceRaw - paymentAmountRaw))
482+ let amountBalanceOld = $t02257022863._1
483+ let priceBalanceOld = $t02257022863._2
484+ let $t02286723016 = if (paymentInAmountAsset)
485+ then $Tuple2(paymentAmountRaw, 0)
486+ else $Tuple2(0, paymentAmountRaw)
487+ let amountAssetAmountRaw = $t02286723016._1
488+ let priceAssetAmountRaw = $t02286723016._2
489+ let amountAssetAmount = takeFee(amountAssetAmountRaw)._1
490+ let priceAssetAmount = takeFee(priceAssetAmountRaw)._1
491+ let $t02313823197 = takeFee(paymentAmountRaw)
492+ let paymentAmount = $t02313823197._1
493+ let feeAmount = $t02313823197._2
494+ let amountBalanceNew = (amountBalanceOld + amountAssetAmount)
495+ let priceBalanceNew = (priceBalanceOld + priceAssetAmount)
496+ let priceNewX18 = calcPriceBigInt(toX18(priceBalanceNew, cfgPriceAssetDecimals), toX18(amountBalanceNew, cfgAmountAssetDecimals))
497+ let priceNew = fromX18(priceNewX18, scale8)
498+ let paymentBalance = if (paymentInAmountAsset)
499+ then amountBalanceOld
500+ else priceBalanceOld
501+ let paymentBalanceBigInt = toBigInt(paymentBalance)
502+ let supplyBigInt = toBigInt(valueOrErrorMessage(assetInfo(cfgLpAssetId), (("asset " + toBase58String(cfgLpAssetId)) + " doesn't exist")).quantity)
503+ let chechSupply = if ((supplyBigInt > big0))
504+ then true
505+ else throwErr("initial deposit requires all coins")
506+ if ((chechSupply == chechSupply))
507+ then {
508+ let depositBigInt = toBigInt(paymentAmount)
509+ let issueAmount = max([0, toInt(((supplyBigInt * (sqrtBigInt((scale18 + ((depositBigInt * scale18) / paymentBalanceBigInt)), 18, 18, DOWN) - scale18)) / scale18))])
510+ let commonState = if (isEval)
511+ then nil
512+ 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))]
513+ let priceOldX18 = calcPriceBigInt(toX18(priceBalanceOld, cfgPriceAssetDecimals), toX18(amountBalanceOld, cfgAmountAssetDecimals))
514+ let priceOld = fromX18(priceOldX18, scale8)
515+ let priceImpact = abs((((priceNew - priceOld) * scale8) / priceOld))
516+ $Tuple4(issueAmount, commonState, feeAmount, priceImpact)
517+ }
518+ else throw("Strict value is not equal to itself.")
519+ }
520+
521+
522+func calcGetOneToken (outAssetId,paymentAmount,paymentAssetId,userAddress,txId) = {
523+ let isEval = (txId == unit)
524+ let checks = [if ((paymentAssetId == cfgLpAssetId))
525+ then true
526+ else throwErr("invalid lp asset")]
527+ if ((checks == checks))
528+ then {
529+ let outInAmountAsset = if ((outAssetId == cfgAmountAssetId))
530+ then true
531+ else if ((outAssetId == cfgPriceAssetId))
532+ then false
533+ else throwErr("invalid asset")
534+ let balanceBigInt = if (outInAmountAsset)
535+ then toBigInt(getAccBalance(assetIdToString(cfgAmountAssetId)))
536+ else toBigInt(getAccBalance(assetIdToString(cfgPriceAssetId)))
537+ let amBalanceOld = getAccBalance(assetIdToString(cfgAmountAssetId))
538+ let prBalanceOld = getAccBalance(assetIdToString(cfgPriceAssetId))
539+ let outBalance = if (outInAmountAsset)
540+ then amBalanceOld
541+ else prBalanceOld
542+ let outBalanceBigInt = toBigInt(outBalance)
543+ let supplyBigInt = toBigInt(valueOrErrorMessage(assetInfo(cfgLpAssetId), (("asset " + toBase58String(cfgLpAssetId)) + " doesn't exist")).quantity)
544+ let redeemedBigInt = toBigInt(paymentAmount)
545+ let amountRaw = max([0, toInt(((balanceBigInt * (scale18 - pow((scale18 - ((redeemedBigInt * scale18) / supplyBigInt)), 18, big2, 0, 18, DOWN))) / scale18))])
546+ let $t02613526185 = takeFee(amountRaw)
547+ let totalAmount = $t02613526185._1
548+ let feeAmount = $t02613526185._2
549+ let $t02618926415 = if (outInAmountAsset)
550+ then $Tuple4(totalAmount, 0, (amBalanceOld - amountRaw), prBalanceOld)
551+ else $Tuple4(0, totalAmount, amBalanceOld, (prBalanceOld - amountRaw))
552+ let outAmAmount = $t02618926415._1
553+ let outPrAmount = $t02618926415._2
554+ let amBalanceNew = $t02618926415._3
555+ let prBalanceNew = $t02618926415._4
556+ let priceNewX18 = calcPriceBigInt(toX18(prBalanceNew, cfgPriceAssetDecimals), toX18(amBalanceNew, cfgAmountAssetDecimals))
557+ let priceNew = fromX18(priceNewX18, scale8)
558+ let commonState = if (isEval)
559+ then nil
560+ 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)]
561+ let priceOldX18 = calcPriceBigInt(toX18(prBalanceOld, cfgPriceAssetDecimals), toX18(amBalanceOld, cfgAmountAssetDecimals))
562+ let priceOld = fromX18(priceOldX18, scale8)
563+ let priceImpact = abs((((priceNew - priceOld) * scale8) / priceOld))
564+ $Tuple4(totalAmount, commonState, feeAmount, priceImpact)
565+ }
566+ else throw("Strict value is not equal to itself.")
567+ }
568+
569+
383570 func managerPublicKeyOrUnit () = match getString(mpk()) {
384571 case s: String =>
385572 fromBase58String(s)
418605
419606
420607 @Callable(i)
421-func constructor (factoryContract) = {
422- let checkCaller = mustManager(i)
423- if ((checkCaller == checkCaller))
424- then [StringEntry(fc(), factoryContract)]
425- else throw("Strict value is not equal to itself.")
426- }
427-
428-
429-
430-@Callable(i)
431608 func setManager (pendingManagerPublicKey) = {
432609 let checkCaller = mustManager(i)
433610 if ((checkCaller == checkCaller))
463640
464641
465642 @Callable(i)
466-func put (slippageTolerance,shouldAutoStake) = {
467- let factoryCfg = getFactoryConfig()
468- let stakingContract = valueOrErrorMessage(addressFromString(factoryCfg[idxFactoryStakingContract]), "Error. Incorrect staking address.")
469- let slippageContract = valueOrErrorMessage(addressFromString(factoryCfg[idxFactorySlippageContract]), "Error. Incorrect slippage contract address.")
470- if ((0 > slippageTolerance))
471- then throw("Invalid slippageTolerance passed")
472- else {
473- let estPut = commonPut(i, slippageTolerance, true)
474- let emitLpAmt = estPut._2
475- let lpAssetId = estPut._7
476- let state = estPut._9
477- let amDiff = estPut._10
478- let prDiff = estPut._11
479- let amId = estPut._12
480- let prId = estPut._13
481- let emitInv = invoke(factoryContract, "emit", [emitLpAmt], nil)
482- if ((emitInv == emitInv))
483- then {
484- let emitInvLegacy = match emitInv {
485- case legacyFactoryContract: Address =>
486- invoke(legacyFactoryContract, "emit", [emitLpAmt], nil)
487- case _ =>
488- unit
489- }
490- if ((emitInvLegacy == emitInvLegacy))
491- then {
492- let slippageAInv = if ((amDiff > 0))
493- then invoke(slippageContract, "put", nil, [AttachedPayment(amId, amDiff)])
494- else nil
495- if ((slippageAInv == slippageAInv))
496- then {
497- let slippagePInv = if ((prDiff > 0))
498- then invoke(slippageContract, "put", nil, [AttachedPayment(prId, prDiff)])
499- else nil
500- if ((slippagePInv == slippagePInv))
501- then {
502- let lpTransfer = if (shouldAutoStake)
503- then {
504- let slpStakeInv = invoke(stakingContract, "stake", nil, [AttachedPayment(lpAssetId, emitLpAmt)])
505- if ((slpStakeInv == slpStakeInv))
506- then nil
507- else throw("Strict value is not equal to itself.")
508- }
509- else [ScriptTransfer(i.caller, emitLpAmt, lpAssetId)]
510- (state ++ lpTransfer)
511- }
512- else throw("Strict value is not equal to itself.")
513- }
514- else throw("Strict value is not equal to itself.")
515- }
516- else throw("Strict value is not equal to itself.")
517- }
518- else throw("Strict value is not equal to itself.")
519- }
520- }
643+func put (slippageTolerance,shouldAutoStake) = if ((0 > slippageTolerance))
644+ then throw("Invalid slippageTolerance passed")
645+ else {
646+ let estPut = commonPut(i, slippageTolerance, true)
647+ let emitLpAmt = estPut._2
648+ let lpAssetId = estPut._7
649+ let state = estPut._9
650+ let amDiff = estPut._10
651+ let prDiff = estPut._11
652+ let amId = estPut._12
653+ let prId = estPut._13
654+ let emitInv = invoke(factoryContract, "emit", [emitLpAmt], nil)
655+ if ((emitInv == emitInv))
656+ then {
657+ let emitInvLegacy = match emitInv {
658+ case legacyFactoryContract: Address =>
659+ invoke(legacyFactoryContract, "emit", [emitLpAmt], nil)
660+ case _ =>
661+ unit
662+ }
663+ if ((emitInvLegacy == emitInvLegacy))
664+ then {
665+ let slippageAInv = if ((amDiff > 0))
666+ then invoke(slippageContract, "put", nil, [AttachedPayment(amId, amDiff)])
667+ else nil
668+ if ((slippageAInv == slippageAInv))
669+ then {
670+ let slippagePInv = if ((prDiff > 0))
671+ then invoke(slippageContract, "put", nil, [AttachedPayment(prId, prDiff)])
672+ else nil
673+ if ((slippagePInv == slippagePInv))
674+ then {
675+ let lpTransfer = if (shouldAutoStake)
676+ then {
677+ let slpStakeInv = invoke(stakingContract, "stake", nil, [AttachedPayment(lpAssetId, emitLpAmt)])
678+ if ((slpStakeInv == slpStakeInv))
679+ then nil
680+ else throw("Strict value is not equal to itself.")
681+ }
682+ else [ScriptTransfer(i.caller, emitLpAmt, lpAssetId)]
683+ (state ++ lpTransfer)
684+ }
685+ else throw("Strict value is not equal to itself.")
686+ }
687+ else throw("Strict value is not equal to itself.")
688+ }
689+ else throw("Strict value is not equal to itself.")
690+ }
691+ else throw("Strict value is not equal to itself.")
692+ }
521693
522694
523695
528700 let estPut = commonPut(i, maxSlippage, false)
529701 estPut._9
530702 }
703+
704+
705+
706+@Callable(i)
707+func putOneTkn (minOutAmount,autoStake) = {
708+ let isPoolOneTokenOperationsDisabled = {
709+ let @ = invoke(factoryContract, "isPoolOneTokenOperationsDisabledREADONLY", [toString(this)], nil)
710+ if ($isInstanceOf(@, "Boolean"))
711+ then @
712+ else throw(($getType(@) + " couldn't be cast to Boolean"))
713+ }
714+ let isPutDisabled = if (if (if (isGlobalShutdown())
715+ then true
716+ else (cfgPoolStatus == PoolPutDisabled))
717+ then true
718+ else (cfgPoolStatus == PoolShutdown))
719+ then true
720+ else isPoolOneTokenOperationsDisabled
721+ let checks = [if (!(isPutDisabled))
722+ then true
723+ else throwErr("put operation is blocked by admin"), if ((size(i.payments) == 1))
724+ then true
725+ else throwErr("exactly 1 payment are expected")]
726+ if ((checks == checks))
727+ then {
728+ let payment = i.payments[0]
729+ let paymentAssetId = payment.assetId
730+ let paymentAmountRaw = payment.amount
731+ let userAddress = i.caller
732+ let txId = i.transactionId
733+ let $t03099731124 = calcPutOneToken(paymentAmountRaw, paymentAssetId, userAddress, txId)
734+ let emitAmountEstimated = $t03099731124._1
735+ let commonState = $t03099731124._2
736+ let feeAmount = $t03099731124._3
737+ let bonus = $t03099731124._4
738+ let emitAmount = if (if ((minOutAmount > 0))
739+ then (minOutAmount > emitAmountEstimated)
740+ else false)
741+ then throwErr(makeString(["amount to receive is less than ", toString(minOutAmount)], ""))
742+ else emitAmountEstimated
743+ let emitInv = emit(emitAmount)
744+ if ((emitInv == emitInv))
745+ then {
746+ let lpTransfer = if (autoStake)
747+ then {
748+ let stakeInv = invoke(stakingContract, "stake", nil, [AttachedPayment(cfgLpAssetId, emitAmount)])
749+ if ((stakeInv == stakeInv))
750+ then nil
751+ else throw("Strict value is not equal to itself.")
752+ }
753+ else [ScriptTransfer(i.caller, emitAmount, cfgLpAssetId)]
754+ let sendFee = if ((feeAmount > 0))
755+ then [ScriptTransfer(feeCollectorAddress, feeAmount, paymentAssetId)]
756+ else nil
757+ $Tuple2(((commonState ++ lpTransfer) ++ sendFee), emitAmount)
758+ }
759+ else throw("Strict value is not equal to itself.")
760+ }
761+ else throw("Strict value is not equal to itself.")
762+ }
763+
764+
765+
766+@Callable(i)
767+func putOneTknREADONLY (paymentAssetId,paymentAmountRaw) = {
768+ let $t03185331988 = calcPutOneToken(paymentAmountRaw, parseAssetId(paymentAssetId), unit, unit)
769+ let emitAmountEstimated = $t03185331988._1
770+ let commonState = $t03185331988._2
771+ let feeAmount = $t03185331988._3
772+ let bonus = $t03185331988._4
773+ $Tuple2(nil, $Tuple3(emitAmountEstimated, feeAmount, bonus))
774+ }
775+
776+
777+
778+@Callable(i)
779+func getOneTkn (outAssetIdStr,minOutAmount) = {
780+ let isPoolOneTokenOperationsDisabled = {
781+ let @ = invoke(factoryContract, "isPoolOneTokenOperationsDisabledREADONLY", [toString(this)], nil)
782+ if ($isInstanceOf(@, "Boolean"))
783+ then @
784+ else throw(($getType(@) + " couldn't be cast to Boolean"))
785+ }
786+ let isGetDisabled = if (if (isGlobalShutdown())
787+ then true
788+ else (cfgPoolStatus == PoolShutdown))
789+ then true
790+ else isPoolOneTokenOperationsDisabled
791+ let checks = [if (!(isGetDisabled))
792+ then true
793+ else throwErr("get operation is blocked by admin"), if ((size(i.payments) == 1))
794+ then true
795+ else throwErr("exactly 1 payment are expected")]
796+ if ((checks == checks))
797+ then {
798+ let outAssetId = parseAssetId(outAssetIdStr)
799+ let payment = i.payments[0]
800+ let paymentAssetId = payment.assetId
801+ let paymentAmount = payment.amount
802+ let userAddress = i.caller
803+ let txId = i.transactionId
804+ let $t03276032892 = calcGetOneToken(outAssetId, paymentAmount, paymentAssetId, userAddress, txId)
805+ let amountEstimated = $t03276032892._1
806+ let commonState = $t03276032892._2
807+ let feeAmount = $t03276032892._3
808+ let bonus = $t03276032892._4
809+ let amount = if (if ((minOutAmount > 0))
810+ then (minOutAmount > amountEstimated)
811+ else false)
812+ then throwErr(makeString(["amount to receive is less than ", toString(minOutAmount)], ""))
813+ else amountEstimated
814+ let burnInv = invoke(factoryContract, "burn", [paymentAmount], [AttachedPayment(paymentAssetId, paymentAmount)])
815+ if ((burnInv == burnInv))
816+ then {
817+ let assetTransfer = [ScriptTransfer(userAddress, amount, outAssetId)]
818+ let sendFee = if ((feeAmount > 0))
819+ then [ScriptTransfer(feeCollectorAddress, feeAmount, outAssetId)]
820+ else nil
821+ $Tuple2(((commonState ++ assetTransfer) ++ sendFee), amount)
822+ }
823+ else throw("Strict value is not equal to itself.")
824+ }
825+ else throw("Strict value is not equal to itself.")
826+ }
827+
828+
829+
830+@Callable(i)
831+func getOneTknREADONLY (outAssetId,paymentAmount) = {
832+ let $t03352733665 = calcGetOneToken(parseAssetId(outAssetId), paymentAmount, cfgLpAssetId, unit, unit)
833+ let amountEstimated = $t03352733665._1
834+ let commonState = $t03352733665._2
835+ let feeAmount = $t03352733665._3
836+ let bonus = $t03352733665._4
837+ $Tuple2(nil, $Tuple3(amountEstimated, feeAmount, bonus))
838+ }
839+
840+
841+
842+@Callable(i)
843+func unstakeAndGetOneTkn (unstakeAmount,outAssetIdStr,minOutAmount) = {
844+ let isPoolOneTokenOperationsDisabled = {
845+ let @ = invoke(factoryContract, "isPoolOneTokenOperationsDisabledREADONLY", [toString(this)], nil)
846+ if ($isInstanceOf(@, "Boolean"))
847+ then @
848+ else throw(($getType(@) + " couldn't be cast to Boolean"))
849+ }
850+ let isGetDisabled = if (if (isGlobalShutdown())
851+ then true
852+ else (cfgPoolStatus == PoolShutdown))
853+ then true
854+ else isPoolOneTokenOperationsDisabled
855+ let checks = [if (!(isGetDisabled))
856+ then true
857+ else throwErr("get operation is blocked by admin"), if ((size(i.payments) == 0))
858+ then true
859+ else throwErr("no payments are expected")]
860+ if ((checks == checks))
861+ then {
862+ let outAssetId = parseAssetId(outAssetIdStr)
863+ let userAddress = i.caller
864+ let txId = i.transactionId
865+ let unstakeInv = invoke(stakingContract, "unstake", [toBase58String(cfgLpAssetId), unstakeAmount], nil)
866+ if ((unstakeInv == unstakeInv))
867+ then {
868+ let $t03445734587 = calcGetOneToken(outAssetId, unstakeAmount, cfgLpAssetId, userAddress, txId)
869+ let amountEstimated = $t03445734587._1
870+ let commonState = $t03445734587._2
871+ let feeAmount = $t03445734587._3
872+ let bonus = $t03445734587._4
873+ let amount = if (if ((minOutAmount > 0))
874+ then (minOutAmount > amountEstimated)
875+ else false)
876+ then throwErr(makeString(["amount to receive is less than ", toString(minOutAmount)], ""))
877+ else amountEstimated
878+ let burnInv = invoke(factoryContract, "burn", [unstakeAmount], [AttachedPayment(cfgLpAssetId, unstakeAmount)])
879+ if ((burnInv == burnInv))
880+ then {
881+ let assetTransfer = [ScriptTransfer(i.caller, amount, outAssetId)]
882+ let sendFee = if ((feeAmount > 0))
883+ then [ScriptTransfer(feeCollectorAddress, feeAmount, outAssetId)]
884+ else nil
885+ $Tuple2(((commonState ++ assetTransfer) ++ sendFee), amount)
886+ }
887+ else throw("Strict value is not equal to itself.")
888+ }
889+ else throw("Strict value is not equal to itself.")
890+ }
891+ else throw("Strict value is not equal to itself.")
892+ }
531893
532894
533895
577939 if ((checkPayments == checkPayments))
578940 then {
579941 let cfg = getPoolConfig()
580- let factoryCfg = getFactoryConfig()
581942 let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
582- let stakingContract = valueOrErrorMessage(addressFromString(factoryCfg[idxFactoryStakingContract]), "Error. Incorrect staking address.")
583943 let unstakeInv = invoke(stakingContract, "unstake", [toBase58String(lpAssetId), amount], nil)
584944 if ((unstakeInv == unstakeInv))
585945 then {
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let lPdecimals = 8
55
66 let scale8 = 100000000
77
88 let scale8BigInt = toBigInt(100000000)
99
1010 let scale18 = toBigInt(1000000000000000000)
1111
1212 let zeroBigInt = toBigInt(0)
13+
14+let big0 = toBigInt(0)
15+
16+let big1 = toBigInt(1)
17+
18+let big2 = toBigInt(2)
19+
20+let wavesString = "WAVES"
1321
1422 let SEP = "__"
1523
1624 let PoolActive = 1
1725
1826 let PoolPutDisabled = 2
1927
2028 let PoolMatcherDisabled = 3
2129
2230 let PoolShutdown = 4
2331
2432 let idxPoolAddress = 1
2533
2634 let idxPoolStatus = 2
2735
2836 let idxPoolLPAssetId = 3
2937
3038 let idxAmtAssetId = 4
3139
3240 let idxPriceAssetId = 5
3341
3442 let idxAmtAssetDcm = 6
3543
3644 let idxPriceAssetDcm = 7
3745
3846 let idxIAmtAssetId = 8
3947
4048 let idxIPriceAssetId = 9
4149
4250 let idxLPAssetDcm = 10
4351
4452 let idxPoolAmtAssetAmt = 1
4553
4654 let idxPoolPriceAssetAmt = 2
4755
4856 let idxPoolLPAssetAmt = 3
4957
5058 let idxFactoryStakingContract = 1
5159
5260 let idxFactorySlippageContract = 7
5361
5462 func toX18 (origVal,origScaleMult) = fraction(toBigInt(origVal), scale18, toBigInt(origScaleMult))
5563
5664
5765 func fromX18 (val,resultScaleMult) = toInt(fraction(val, toBigInt(resultScaleMult), scale18))
5866
5967
6068 func toScale (amt,resScale,curScale) = fraction(amt, resScale, curScale)
6169
6270
63-func abs (val) = if ((zeroBigInt > val))
71+func abs (val) = if ((0 > val))
72+ then -(val)
73+ else val
74+
75+
76+func absBigInt (val) = if ((zeroBigInt > val))
6477 then -(val)
6578 else val
6679
6780
6881 func fc () = "%s__factoryContract"
6982
7083
7184 func mpk () = "%s__managerPublicKey"
7285
7386
7487 func pmpk () = "%s__pendingManagerPublicKey"
7588
7689
7790 func pl () = "%s%s__price__last"
7891
7992
8093 func ph (h,timestamp) = makeString(["%s%s%d%d__price__history", toString(h), toString(timestamp)], SEP)
8194
8295
8396 func pau (userAddress,txId) = ((("%s%s%s__P__" + userAddress) + "__") + txId)
8497
8598
8699 func gau (userAddress,txId) = ((("%s%s%s__G__" + userAddress) + "__") + txId)
87100
88101
89102 func aa () = "%s__amountAsset"
90103
91104
92105 func pa () = "%s__priceAsset"
93106
94107
108+let keyFee = "%s__fee"
109+
110+let feeDefault = fraction(5, scale8, 10000)
111+
112+let fee = valueOrElse(getInteger(this, keyFee), feeDefault)
113+
95114 func keyFactoryConfig () = "%s__factoryConfig"
96115
97116
98117 func keyMatcherPub () = "%s%s__matcher__publicKey"
99118
100119
101120 func keyMappingPoolContractAddressToPoolAssets (poolContractAddress) = (("%s%s%s__" + poolContractAddress) + "__mappings__poolContract2LpAsset")
102121
103122
104123 func keyPoolConfig (iAmtAsset,iPriceAsset) = (((("%d%d%s__" + iAmtAsset) + "__") + iPriceAsset) + "__config")
105124
106125
107126 func keyMappingsBaseAsset2internalId (baseAssetStr) = ("%s%s%s__mappings__baseAsset2internalId__" + baseAssetStr)
108127
109128
110129 func keyAllPoolsShutdown () = "%s__shutdown"
111130
112131
113132 func keyPoolWeight (contractAddress) = ("%s%s__poolWeight__" + contractAddress)
114133
115134
116135 func keyAllowedLpScriptHash () = "%s__allowedLpScriptHash"
117136
118137
138+let keyFeeCollectorAddress = "%s__feeCollectorAddress"
139+
119140 func throwOrderError (orderValid,senderValid,matcherValid) = throw(((((("order validation failed: orderValid=" + toString(orderValid)) + " senderValid=") + toString(senderValid)) + " matcherValid=") + toString(matcherValid)))
120141
121142
122143 func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
123144
124145
125146 func getIntOrFail (address,key) = valueOrErrorMessage(getInteger(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
126147
127148
149+func throwErr (msg) = throw(makeString(["lp.ride:", msg], " "))
150+
151+
128152 let factoryContract = addressFromStringValue(getStringOrFail(this, fc()))
153+
154+let feeCollectorAddress = addressFromStringValue(getStringOrFail(factoryContract, keyFeeCollectorAddress))
129155
130156 func isGlobalShutdown () = valueOrElse(getBoolean(factoryContract, keyAllPoolsShutdown()), false)
131157
132158
133159 func getMatcherPubOrFail () = fromBase58String(getStringOrFail(factoryContract, keyMatcherPub()))
134160
135161
136162 func getPoolConfig () = {
137163 let amtAsset = getStringOrFail(this, aa())
138164 let priceAsset = getStringOrFail(this, pa())
139165 let iPriceAsset = getIntOrFail(factoryContract, keyMappingsBaseAsset2internalId(priceAsset))
140166 let iAmtAsset = getIntOrFail(factoryContract, keyMappingsBaseAsset2internalId(amtAsset))
141167 split(getStringOrFail(factoryContract, keyPoolConfig(toString(iAmtAsset), toString(iPriceAsset))), SEP)
142168 }
143169
144170
171+func parseAssetId (input) = if ((input == wavesString))
172+ then unit
173+ else fromBase58String(input)
174+
175+
176+func assetIdToString (input) = if ((input == unit))
177+ then wavesString
178+ else toBase58String(value(input))
179+
180+
181+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]))
182+
183+
184+let poolConfigParsed = parsePoolConfig(getPoolConfig())
185+
186+let $t075437709 = poolConfigParsed
187+
188+let cfgPoolAddress = $t075437709._1
189+
190+let cfgPoolStatus = $t075437709._2
191+
192+let cfgLpAssetId = $t075437709._3
193+
194+let cfgAmountAssetId = $t075437709._4
195+
196+let cfgPriceAssetId = $t075437709._5
197+
198+let cfgAmountAssetDecimals = $t075437709._6
199+
200+let cfgPriceAssetDecimals = $t075437709._7
201+
145202 func getFactoryConfig () = split(getStringOrFail(factoryContract, keyFactoryConfig()), SEP)
146203
204+
205+let stakingContract = valueOrErrorMessage(addressFromString(getFactoryConfig()[idxFactoryStakingContract]), "incorrect staking address")
206+
207+let slippageContract = valueOrErrorMessage(addressFromString(getFactoryConfig()[idxFactorySlippageContract]), "incorrect staking address")
147208
148209 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)
149210
150211
151212 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)
152213
153214
154215 func getAccBalance (assetId) = if ((assetId == "WAVES"))
155216 then wavesBalance(this).available
156217 else assetBalance(this, fromBase58String(assetId))
157218
158219
159220 func calcPriceBigInt (prAmtX18,amAmtX18) = fraction(prAmtX18, scale18, amAmtX18)
160221
161222
162223 func privateCalcPrice (amAssetDcm,prAssetDcm,amAmt,prAmt) = {
163224 let amtAssetAmtX18 = toX18(amAmt, amAssetDcm)
164225 let priceAssetAmtX18 = toX18(prAmt, prAssetDcm)
165226 calcPriceBigInt(priceAssetAmtX18, amtAssetAmtX18)
166227 }
167228
168229
169230 func calcPrices (amAmt,prAmt,lpAmt) = {
170231 let cfg = getPoolConfig()
171232 let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
172233 let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
173234 let priceX18 = privateCalcPrice(amtAssetDcm, priceAssetDcm, amAmt, prAmt)
174235 let amAmtX18 = toX18(amAmt, amtAssetDcm)
175236 let prAmtX18 = toX18(prAmt, priceAssetDcm)
176237 let lpAmtX18 = toX18(lpAmt, scale8)
177238 let lpPriceInAmAssetX18 = calcPriceBigInt(amAmtX18, lpAmtX18)
178239 let lpPriceInPrAssetX18 = calcPriceBigInt(prAmtX18, lpAmtX18)
179240 [priceX18, lpPriceInAmAssetX18, lpPriceInPrAssetX18]
180241 }
181242
182243
183244 func calculatePrices (amAmt,prAmt,lpAmt) = {
184245 let prices = calcPrices(amAmt, prAmt, lpAmt)
185246 [fromX18(prices[0], scale8), fromX18(prices[1], scale8), fromX18(prices[2], scale8)]
186247 }
187248
188249
189250 func estimateGetOperation (txId58,pmtAssetId,pmtLpAmt,userAddress) = {
190251 let cfg = getPoolConfig()
191252 let lpAssetId = cfg[idxPoolLPAssetId]
192253 let amAssetId = cfg[idxAmtAssetId]
193254 let prAssetId = cfg[idxPriceAssetId]
194255 let amAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
195256 let prAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
196257 let poolStatus = cfg[idxPoolStatus]
197258 let lpEmission = valueOrErrorMessage(assetInfo(fromBase58String(lpAssetId)), (("Asset " + lpAssetId) + " doesn't exist")).quantity
198259 if ((lpAssetId != pmtAssetId))
199260 then throw("Invalid asset passed.")
200261 else {
201262 let amBalance = getAccBalance(amAssetId)
202263 let amBalanceX18 = toX18(amBalance, amAssetDcm)
203264 let prBalance = getAccBalance(prAssetId)
204265 let prBalanceX18 = toX18(prBalance, prAssetDcm)
205266 let curPriceX18 = calcPriceBigInt(prBalanceX18, amBalanceX18)
206267 let curPrice = fromX18(curPriceX18, scale8)
207268 let pmtLpAmtX18 = toX18(pmtLpAmt, scale8)
208269 let lpEmissionX18 = toX18(lpEmission, scale8)
209270 let outAmAmtX18 = fraction(amBalanceX18, pmtLpAmtX18, lpEmissionX18)
210271 let outPrAmtX18 = fraction(prBalanceX18, pmtLpAmtX18, lpEmissionX18)
211272 let outAmAmt = fromX18(outAmAmtX18, amAssetDcm)
212273 let outPrAmt = fromX18(outPrAmtX18, prAssetDcm)
213274 let state = if ((txId58 == ""))
214275 then nil
215276 else [ScriptTransfer(userAddress, outAmAmt, if ((amAssetId == "WAVES"))
216277 then unit
217278 else fromBase58String(amAssetId)), ScriptTransfer(userAddress, outPrAmt, if ((prAssetId == "WAVES"))
218279 then unit
219280 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)]
220281 $Tuple10(outAmAmt, outPrAmt, amAssetId, prAssetId, amBalance, prBalance, lpEmission, curPriceX18, poolStatus, state)
221282 }
222283 }
223284
224285
225286 func estimatePutOperation (txId58,slippageTolerance,inAmAssetAmt,inAmAssetId,inPrAssetAmt,inPrAssetId,userAddress,isEvaluate,emitLp) = {
226287 let cfg = getPoolConfig()
227288 let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
228289 let amAssetIdStr = cfg[idxAmtAssetId]
229290 let prAssetIdStr = cfg[idxPriceAssetId]
230291 let iAmtAssetId = cfg[idxIAmtAssetId]
231292 let iPriceAssetId = cfg[idxIPriceAssetId]
232293 let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
233294 let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
234295 let poolStatus = cfg[idxPoolStatus]
235296 let lpEmission = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
236297 let inAmAssetIdStr = toBase58String(valueOrElse(inAmAssetId, fromBase58String("WAVES")))
237298 let inPrAssetIdStr = toBase58String(valueOrElse(inPrAssetId, fromBase58String("WAVES")))
238299 if (if ((amAssetIdStr != inAmAssetIdStr))
239300 then true
240301 else (prAssetIdStr != inPrAssetIdStr))
241302 then throw("Invalid amt or price asset passed.")
242303 else {
243304 let amBalance = if (isEvaluate)
244305 then getAccBalance(amAssetIdStr)
245306 else (getAccBalance(amAssetIdStr) - inAmAssetAmt)
246307 let prBalance = if (isEvaluate)
247308 then getAccBalance(prAssetIdStr)
248309 else (getAccBalance(prAssetIdStr) - inPrAssetAmt)
249310 let inAmAssetAmtX18 = toX18(inAmAssetAmt, amtAssetDcm)
250311 let inPrAssetAmtX18 = toX18(inPrAssetAmt, priceAssetDcm)
251312 let userPriceX18 = calcPriceBigInt(inPrAssetAmtX18, inAmAssetAmtX18)
252313 let amBalanceX18 = toX18(amBalance, amtAssetDcm)
253314 let prBalanceX18 = toX18(prBalance, priceAssetDcm)
254315 let res = if ((lpEmission == 0))
255316 then {
256317 let curPriceX18 = zeroBigInt
257318 let slippageX18 = zeroBigInt
258319 let lpAmtX18 = pow((inAmAssetAmtX18 * inPrAssetAmtX18), 0, toBigInt(5), 1, 0, DOWN)
259320 $Tuple5(fromX18(lpAmtX18, scale8), fromX18(inAmAssetAmtX18, amtAssetDcm), fromX18(inPrAssetAmtX18, priceAssetDcm), calcPriceBigInt((prBalanceX18 + inPrAssetAmtX18), (amBalanceX18 + inAmAssetAmtX18)), slippageX18)
260321 }
261322 else {
262323 let curPriceX18 = calcPriceBigInt(prBalanceX18, amBalanceX18)
263- let slippageX18 = fraction(abs((curPriceX18 - userPriceX18)), scale18, curPriceX18)
324+ let slippageX18 = fraction(absBigInt((curPriceX18 - userPriceX18)), scale18, curPriceX18)
264325 let slippageToleranceX18 = toX18(slippageTolerance, scale8)
265326 if (if ((curPriceX18 != zeroBigInt))
266327 then (slippageX18 > slippageToleranceX18)
267328 else false)
268329 then throw(((("Price slippage " + toString(slippageX18)) + " exceeded the passed limit of ") + toString(slippageToleranceX18)))
269330 else {
270331 let lpEmissionX18 = toX18(lpEmission, scale8)
271332 let prViaAmX18 = fraction(inAmAssetAmtX18, curPriceX18, scale18)
272333 let amViaPrX18 = fraction(inPrAssetAmtX18, scale18, curPriceX18)
273334 let expectedAmts = if ((prViaAmX18 > inPrAssetAmtX18))
274335 then $Tuple2(amViaPrX18, inPrAssetAmtX18)
275336 else $Tuple2(inAmAssetAmtX18, prViaAmX18)
276337 let expAmtAssetAmtX18 = expectedAmts._1
277338 let expPriceAssetAmtX18 = expectedAmts._2
278339 let lpAmtX18 = fraction(lpEmissionX18, expPriceAssetAmtX18, prBalanceX18)
279340 $Tuple5(fromX18(lpAmtX18, scale8), fromX18(expAmtAssetAmtX18, amtAssetDcm), fromX18(expPriceAssetAmtX18, priceAssetDcm), curPriceX18, slippageX18)
280341 }
281342 }
282343 let calcLpAmt = res._1
283344 let calcAmAssetPmt = res._2
284345 let calcPrAssetPmt = res._3
285346 let curPrice = fromX18(res._4, scale8)
286347 let slippageCalc = fromX18(res._5, scale8)
287348 if ((0 >= calcLpAmt))
288349 then throw("Invalid calculations. LP calculated is less than zero.")
289350 else {
290351 let emitLpAmt = if (!(emitLp))
291352 then 0
292353 else calcLpAmt
293354 let amDiff = (inAmAssetAmt - calcAmAssetPmt)
294355 let prDiff = (inPrAssetAmt - calcPrAssetPmt)
295356 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))]
296357 $Tuple13(calcLpAmt, emitLpAmt, curPrice, amBalance, prBalance, lpEmission, lpAssetId, poolStatus, commonState, amDiff, prDiff, inAmAssetId, inPrAssetId)
297358 }
298359 }
299360 }
300361
301362
302363 func validateMatcherOrderAllowed (order) = {
303364 let cfg = getPoolConfig()
304365 let amtAssetId = cfg[idxAmtAssetId]
305366 let priceAssetId = cfg[idxPriceAssetId]
306367 let poolStatus = parseIntValue(cfg[idxPoolStatus])
307368 let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
308369 let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
309370 let accAmtAssetBalance = getAccBalance(amtAssetId)
310371 let accPriceAssetBalance = getAccBalance(priceAssetId)
311372 let curPriceX18 = if ((order.orderType == Buy))
312373 then privateCalcPrice(amtAssetDcm, priceAssetDcm, (accAmtAssetBalance + order.amount), accPriceAssetBalance)
313374 else privateCalcPrice(amtAssetDcm, priceAssetDcm, (accAmtAssetBalance - order.amount), accPriceAssetBalance)
314375 let curPrice = fromX18(curPriceX18, scale8)
315376 if (if (if (isGlobalShutdown())
316377 then true
317378 else (poolStatus == PoolMatcherDisabled))
318379 then true
319380 else (poolStatus == PoolShutdown))
320381 then throw("Exchange operations disabled")
321382 else {
322383 let orderAmtAsset = order.assetPair.amountAsset
323384 let orderAmtAssetStr = if ((orderAmtAsset == unit))
324385 then "WAVES"
325386 else toBase58String(value(orderAmtAsset))
326387 let orderPriceAsset = order.assetPair.priceAsset
327388 let orderPriceAssetStr = if ((orderPriceAsset == unit))
328389 then "WAVES"
329390 else toBase58String(value(orderPriceAsset))
330391 if (if ((orderAmtAssetStr != amtAssetId))
331392 then true
332393 else (orderPriceAssetStr != priceAssetId))
333394 then throw("Wrong order assets.")
334395 else {
335396 let orderPrice = order.price
336397 let priceDcm = fraction(scale8, priceAssetDcm, amtAssetDcm)
337398 let castedOrderPrice = toScale(orderPrice, scale8, priceDcm)
338399 let isOrderPriceValid = if ((order.orderType == Buy))
339400 then (curPrice >= castedOrderPrice)
340401 else (castedOrderPrice >= curPrice)
341402 true
342403 }
343404 }
344405 }
345406
346407
347408 func commonGet (i) = if ((size(i.payments) != 1))
348409 then throw("exactly 1 payment is expected")
349410 else {
350411 let pmt = value(i.payments[0])
351412 let pmtAssetId = value(pmt.assetId)
352413 let pmtAmt = pmt.amount
353414 let res = estimateGetOperation(toBase58String(i.transactionId), toBase58String(pmtAssetId), pmtAmt, i.caller)
354415 let outAmAmt = res._1
355416 let outPrAmt = res._2
356417 let poolStatus = parseIntValue(res._9)
357418 let state = res._10
358419 if (if (isGlobalShutdown())
359420 then true
360421 else (poolStatus == PoolShutdown))
361422 then throw(("Get operation is blocked by admin. Status = " + toString(poolStatus)))
362423 else $Tuple5(outAmAmt, outPrAmt, pmtAmt, pmtAssetId, state)
363424 }
364425
365426
366427 func commonPut (i,slippageTolerance,emitLp) = if ((size(i.payments) != 2))
367428 then throw("exactly 2 payments are expected")
368429 else {
369430 let amAssetPmt = value(i.payments[0])
370431 let prAssetPmt = value(i.payments[1])
371432 let estPut = estimatePutOperation(toBase58String(i.transactionId), slippageTolerance, amAssetPmt.amount, amAssetPmt.assetId, prAssetPmt.amount, prAssetPmt.assetId, toString(i.caller), false, emitLp)
372433 let poolStatus = parseIntValue(estPut._8)
373434 if (if (if (isGlobalShutdown())
374435 then true
375436 else (poolStatus == PoolPutDisabled))
376437 then true
377438 else (poolStatus == PoolShutdown))
378439 then throw(("Put operation is blocked by admin. Status = " + toString(poolStatus)))
379440 else estPut
380441 }
381442
382443
444+func emit (amount) = {
445+ let emitInv = invoke(factoryContract, "emit", [amount], nil)
446+ if ((emitInv == emitInv))
447+ then {
448+ let emitInvLegacy = match emitInv {
449+ case legacyFactoryContract: Address =>
450+ invoke(legacyFactoryContract, "emit", [amount], nil)
451+ case _ =>
452+ unit
453+ }
454+ if ((emitInvLegacy == emitInvLegacy))
455+ then amount
456+ else throw("Strict value is not equal to itself.")
457+ }
458+ else throw("Strict value is not equal to itself.")
459+ }
460+
461+
462+func takeFee (amount) = {
463+ let feeAmount = fraction(amount, fee, scale8)
464+ $Tuple2((amount - feeAmount), feeAmount)
465+ }
466+
467+
468+func calcPutOneToken (paymentAmountRaw,paymentAssetId,userAddress,txId) = {
469+ let isEval = (txId == unit)
470+ let amountBalanceRaw = getAccBalance(assetIdToString(cfgAmountAssetId))
471+ let priceBalanceRaw = getAccBalance(assetIdToString(cfgPriceAssetId))
472+ let paymentInAmountAsset = if ((paymentAssetId == cfgAmountAssetId))
473+ then true
474+ else if ((paymentAssetId == cfgPriceAssetId))
475+ then false
476+ else throwErr("invalid asset")
477+ let $t02257022863 = if (isEval)
478+ then $Tuple2(amountBalanceRaw, priceBalanceRaw)
479+ else if (paymentInAmountAsset)
480+ then $Tuple2((amountBalanceRaw - paymentAmountRaw), priceBalanceRaw)
481+ else $Tuple2(amountBalanceRaw, (priceBalanceRaw - paymentAmountRaw))
482+ let amountBalanceOld = $t02257022863._1
483+ let priceBalanceOld = $t02257022863._2
484+ let $t02286723016 = if (paymentInAmountAsset)
485+ then $Tuple2(paymentAmountRaw, 0)
486+ else $Tuple2(0, paymentAmountRaw)
487+ let amountAssetAmountRaw = $t02286723016._1
488+ let priceAssetAmountRaw = $t02286723016._2
489+ let amountAssetAmount = takeFee(amountAssetAmountRaw)._1
490+ let priceAssetAmount = takeFee(priceAssetAmountRaw)._1
491+ let $t02313823197 = takeFee(paymentAmountRaw)
492+ let paymentAmount = $t02313823197._1
493+ let feeAmount = $t02313823197._2
494+ let amountBalanceNew = (amountBalanceOld + amountAssetAmount)
495+ let priceBalanceNew = (priceBalanceOld + priceAssetAmount)
496+ let priceNewX18 = calcPriceBigInt(toX18(priceBalanceNew, cfgPriceAssetDecimals), toX18(amountBalanceNew, cfgAmountAssetDecimals))
497+ let priceNew = fromX18(priceNewX18, scale8)
498+ let paymentBalance = if (paymentInAmountAsset)
499+ then amountBalanceOld
500+ else priceBalanceOld
501+ let paymentBalanceBigInt = toBigInt(paymentBalance)
502+ let supplyBigInt = toBigInt(valueOrErrorMessage(assetInfo(cfgLpAssetId), (("asset " + toBase58String(cfgLpAssetId)) + " doesn't exist")).quantity)
503+ let chechSupply = if ((supplyBigInt > big0))
504+ then true
505+ else throwErr("initial deposit requires all coins")
506+ if ((chechSupply == chechSupply))
507+ then {
508+ let depositBigInt = toBigInt(paymentAmount)
509+ let issueAmount = max([0, toInt(((supplyBigInt * (sqrtBigInt((scale18 + ((depositBigInt * scale18) / paymentBalanceBigInt)), 18, 18, DOWN) - scale18)) / scale18))])
510+ let commonState = if (isEval)
511+ then nil
512+ 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))]
513+ let priceOldX18 = calcPriceBigInt(toX18(priceBalanceOld, cfgPriceAssetDecimals), toX18(amountBalanceOld, cfgAmountAssetDecimals))
514+ let priceOld = fromX18(priceOldX18, scale8)
515+ let priceImpact = abs((((priceNew - priceOld) * scale8) / priceOld))
516+ $Tuple4(issueAmount, commonState, feeAmount, priceImpact)
517+ }
518+ else throw("Strict value is not equal to itself.")
519+ }
520+
521+
522+func calcGetOneToken (outAssetId,paymentAmount,paymentAssetId,userAddress,txId) = {
523+ let isEval = (txId == unit)
524+ let checks = [if ((paymentAssetId == cfgLpAssetId))
525+ then true
526+ else throwErr("invalid lp asset")]
527+ if ((checks == checks))
528+ then {
529+ let outInAmountAsset = if ((outAssetId == cfgAmountAssetId))
530+ then true
531+ else if ((outAssetId == cfgPriceAssetId))
532+ then false
533+ else throwErr("invalid asset")
534+ let balanceBigInt = if (outInAmountAsset)
535+ then toBigInt(getAccBalance(assetIdToString(cfgAmountAssetId)))
536+ else toBigInt(getAccBalance(assetIdToString(cfgPriceAssetId)))
537+ let amBalanceOld = getAccBalance(assetIdToString(cfgAmountAssetId))
538+ let prBalanceOld = getAccBalance(assetIdToString(cfgPriceAssetId))
539+ let outBalance = if (outInAmountAsset)
540+ then amBalanceOld
541+ else prBalanceOld
542+ let outBalanceBigInt = toBigInt(outBalance)
543+ let supplyBigInt = toBigInt(valueOrErrorMessage(assetInfo(cfgLpAssetId), (("asset " + toBase58String(cfgLpAssetId)) + " doesn't exist")).quantity)
544+ let redeemedBigInt = toBigInt(paymentAmount)
545+ let amountRaw = max([0, toInt(((balanceBigInt * (scale18 - pow((scale18 - ((redeemedBigInt * scale18) / supplyBigInt)), 18, big2, 0, 18, DOWN))) / scale18))])
546+ let $t02613526185 = takeFee(amountRaw)
547+ let totalAmount = $t02613526185._1
548+ let feeAmount = $t02613526185._2
549+ let $t02618926415 = if (outInAmountAsset)
550+ then $Tuple4(totalAmount, 0, (amBalanceOld - amountRaw), prBalanceOld)
551+ else $Tuple4(0, totalAmount, amBalanceOld, (prBalanceOld - amountRaw))
552+ let outAmAmount = $t02618926415._1
553+ let outPrAmount = $t02618926415._2
554+ let amBalanceNew = $t02618926415._3
555+ let prBalanceNew = $t02618926415._4
556+ let priceNewX18 = calcPriceBigInt(toX18(prBalanceNew, cfgPriceAssetDecimals), toX18(amBalanceNew, cfgAmountAssetDecimals))
557+ let priceNew = fromX18(priceNewX18, scale8)
558+ let commonState = if (isEval)
559+ then nil
560+ 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)]
561+ let priceOldX18 = calcPriceBigInt(toX18(prBalanceOld, cfgPriceAssetDecimals), toX18(amBalanceOld, cfgAmountAssetDecimals))
562+ let priceOld = fromX18(priceOldX18, scale8)
563+ let priceImpact = abs((((priceNew - priceOld) * scale8) / priceOld))
564+ $Tuple4(totalAmount, commonState, feeAmount, priceImpact)
565+ }
566+ else throw("Strict value is not equal to itself.")
567+ }
568+
569+
383570 func managerPublicKeyOrUnit () = match getString(mpk()) {
384571 case s: String =>
385572 fromBase58String(s)
386573 case _: Unit =>
387574 unit
388575 case _ =>
389576 throw("Match error")
390577 }
391578
392579
393580 func pendingManagerPublicKeyOrUnit () = match getString(pmpk()) {
394581 case s: String =>
395582 fromBase58String(s)
396583 case _: Unit =>
397584 unit
398585 case _ =>
399586 throw("Match error")
400587 }
401588
402589
403590 func mustManager (i) = {
404591 let pd = throw("Permission denied")
405592 match managerPublicKeyOrUnit() {
406593 case pk: ByteVector =>
407594 if ((i.callerPublicKey == pk))
408595 then true
409596 else pd
410597 case _: Unit =>
411598 if ((i.caller == this))
412599 then true
413600 else pd
414601 case _ =>
415602 throw("Match error")
416603 }
417604 }
418605
419606
420607 @Callable(i)
421-func constructor (factoryContract) = {
422- let checkCaller = mustManager(i)
423- if ((checkCaller == checkCaller))
424- then [StringEntry(fc(), factoryContract)]
425- else throw("Strict value is not equal to itself.")
426- }
427-
428-
429-
430-@Callable(i)
431608 func setManager (pendingManagerPublicKey) = {
432609 let checkCaller = mustManager(i)
433610 if ((checkCaller == checkCaller))
434611 then {
435612 let checkManagerPublicKey = fromBase58String(pendingManagerPublicKey)
436613 if ((checkManagerPublicKey == checkManagerPublicKey))
437614 then [StringEntry(pmpk(), pendingManagerPublicKey)]
438615 else throw("Strict value is not equal to itself.")
439616 }
440617 else throw("Strict value is not equal to itself.")
441618 }
442619
443620
444621
445622 @Callable(i)
446623 func confirmManager () = {
447624 let pm = pendingManagerPublicKeyOrUnit()
448625 let hasPM = if (isDefined(pm))
449626 then true
450627 else throw("No pending manager")
451628 if ((hasPM == hasPM))
452629 then {
453630 let checkPM = if ((i.callerPublicKey == value(pm)))
454631 then true
455632 else throw("You are not pending manager")
456633 if ((checkPM == checkPM))
457634 then [StringEntry(mpk(), toBase58String(value(pm))), DeleteEntry(pmpk())]
458635 else throw("Strict value is not equal to itself.")
459636 }
460637 else throw("Strict value is not equal to itself.")
461638 }
462639
463640
464641
465642 @Callable(i)
466-func put (slippageTolerance,shouldAutoStake) = {
467- let factoryCfg = getFactoryConfig()
468- let stakingContract = valueOrErrorMessage(addressFromString(factoryCfg[idxFactoryStakingContract]), "Error. Incorrect staking address.")
469- let slippageContract = valueOrErrorMessage(addressFromString(factoryCfg[idxFactorySlippageContract]), "Error. Incorrect slippage contract address.")
470- if ((0 > slippageTolerance))
471- then throw("Invalid slippageTolerance passed")
472- else {
473- let estPut = commonPut(i, slippageTolerance, true)
474- let emitLpAmt = estPut._2
475- let lpAssetId = estPut._7
476- let state = estPut._9
477- let amDiff = estPut._10
478- let prDiff = estPut._11
479- let amId = estPut._12
480- let prId = estPut._13
481- let emitInv = invoke(factoryContract, "emit", [emitLpAmt], nil)
482- if ((emitInv == emitInv))
483- then {
484- let emitInvLegacy = match emitInv {
485- case legacyFactoryContract: Address =>
486- invoke(legacyFactoryContract, "emit", [emitLpAmt], nil)
487- case _ =>
488- unit
489- }
490- if ((emitInvLegacy == emitInvLegacy))
491- then {
492- let slippageAInv = if ((amDiff > 0))
493- then invoke(slippageContract, "put", nil, [AttachedPayment(amId, amDiff)])
494- else nil
495- if ((slippageAInv == slippageAInv))
496- then {
497- let slippagePInv = if ((prDiff > 0))
498- then invoke(slippageContract, "put", nil, [AttachedPayment(prId, prDiff)])
499- else nil
500- if ((slippagePInv == slippagePInv))
501- then {
502- let lpTransfer = if (shouldAutoStake)
503- then {
504- let slpStakeInv = invoke(stakingContract, "stake", nil, [AttachedPayment(lpAssetId, emitLpAmt)])
505- if ((slpStakeInv == slpStakeInv))
506- then nil
507- else throw("Strict value is not equal to itself.")
508- }
509- else [ScriptTransfer(i.caller, emitLpAmt, lpAssetId)]
510- (state ++ lpTransfer)
511- }
512- else throw("Strict value is not equal to itself.")
513- }
514- else throw("Strict value is not equal to itself.")
515- }
516- else throw("Strict value is not equal to itself.")
517- }
518- else throw("Strict value is not equal to itself.")
519- }
520- }
643+func put (slippageTolerance,shouldAutoStake) = if ((0 > slippageTolerance))
644+ then throw("Invalid slippageTolerance passed")
645+ else {
646+ let estPut = commonPut(i, slippageTolerance, true)
647+ let emitLpAmt = estPut._2
648+ let lpAssetId = estPut._7
649+ let state = estPut._9
650+ let amDiff = estPut._10
651+ let prDiff = estPut._11
652+ let amId = estPut._12
653+ let prId = estPut._13
654+ let emitInv = invoke(factoryContract, "emit", [emitLpAmt], nil)
655+ if ((emitInv == emitInv))
656+ then {
657+ let emitInvLegacy = match emitInv {
658+ case legacyFactoryContract: Address =>
659+ invoke(legacyFactoryContract, "emit", [emitLpAmt], nil)
660+ case _ =>
661+ unit
662+ }
663+ if ((emitInvLegacy == emitInvLegacy))
664+ then {
665+ let slippageAInv = if ((amDiff > 0))
666+ then invoke(slippageContract, "put", nil, [AttachedPayment(amId, amDiff)])
667+ else nil
668+ if ((slippageAInv == slippageAInv))
669+ then {
670+ let slippagePInv = if ((prDiff > 0))
671+ then invoke(slippageContract, "put", nil, [AttachedPayment(prId, prDiff)])
672+ else nil
673+ if ((slippagePInv == slippagePInv))
674+ then {
675+ let lpTransfer = if (shouldAutoStake)
676+ then {
677+ let slpStakeInv = invoke(stakingContract, "stake", nil, [AttachedPayment(lpAssetId, emitLpAmt)])
678+ if ((slpStakeInv == slpStakeInv))
679+ then nil
680+ else throw("Strict value is not equal to itself.")
681+ }
682+ else [ScriptTransfer(i.caller, emitLpAmt, lpAssetId)]
683+ (state ++ lpTransfer)
684+ }
685+ else throw("Strict value is not equal to itself.")
686+ }
687+ else throw("Strict value is not equal to itself.")
688+ }
689+ else throw("Strict value is not equal to itself.")
690+ }
691+ else throw("Strict value is not equal to itself.")
692+ }
521693
522694
523695
524696 @Callable(i)
525697 func putForFree (maxSlippage) = if ((0 > maxSlippage))
526698 then throw("Invalid value passed")
527699 else {
528700 let estPut = commonPut(i, maxSlippage, false)
529701 estPut._9
530702 }
703+
704+
705+
706+@Callable(i)
707+func putOneTkn (minOutAmount,autoStake) = {
708+ let isPoolOneTokenOperationsDisabled = {
709+ let @ = invoke(factoryContract, "isPoolOneTokenOperationsDisabledREADONLY", [toString(this)], nil)
710+ if ($isInstanceOf(@, "Boolean"))
711+ then @
712+ else throw(($getType(@) + " couldn't be cast to Boolean"))
713+ }
714+ let isPutDisabled = if (if (if (isGlobalShutdown())
715+ then true
716+ else (cfgPoolStatus == PoolPutDisabled))
717+ then true
718+ else (cfgPoolStatus == PoolShutdown))
719+ then true
720+ else isPoolOneTokenOperationsDisabled
721+ let checks = [if (!(isPutDisabled))
722+ then true
723+ else throwErr("put operation is blocked by admin"), if ((size(i.payments) == 1))
724+ then true
725+ else throwErr("exactly 1 payment are expected")]
726+ if ((checks == checks))
727+ then {
728+ let payment = i.payments[0]
729+ let paymentAssetId = payment.assetId
730+ let paymentAmountRaw = payment.amount
731+ let userAddress = i.caller
732+ let txId = i.transactionId
733+ let $t03099731124 = calcPutOneToken(paymentAmountRaw, paymentAssetId, userAddress, txId)
734+ let emitAmountEstimated = $t03099731124._1
735+ let commonState = $t03099731124._2
736+ let feeAmount = $t03099731124._3
737+ let bonus = $t03099731124._4
738+ let emitAmount = if (if ((minOutAmount > 0))
739+ then (minOutAmount > emitAmountEstimated)
740+ else false)
741+ then throwErr(makeString(["amount to receive is less than ", toString(minOutAmount)], ""))
742+ else emitAmountEstimated
743+ let emitInv = emit(emitAmount)
744+ if ((emitInv == emitInv))
745+ then {
746+ let lpTransfer = if (autoStake)
747+ then {
748+ let stakeInv = invoke(stakingContract, "stake", nil, [AttachedPayment(cfgLpAssetId, emitAmount)])
749+ if ((stakeInv == stakeInv))
750+ then nil
751+ else throw("Strict value is not equal to itself.")
752+ }
753+ else [ScriptTransfer(i.caller, emitAmount, cfgLpAssetId)]
754+ let sendFee = if ((feeAmount > 0))
755+ then [ScriptTransfer(feeCollectorAddress, feeAmount, paymentAssetId)]
756+ else nil
757+ $Tuple2(((commonState ++ lpTransfer) ++ sendFee), emitAmount)
758+ }
759+ else throw("Strict value is not equal to itself.")
760+ }
761+ else throw("Strict value is not equal to itself.")
762+ }
763+
764+
765+
766+@Callable(i)
767+func putOneTknREADONLY (paymentAssetId,paymentAmountRaw) = {
768+ let $t03185331988 = calcPutOneToken(paymentAmountRaw, parseAssetId(paymentAssetId), unit, unit)
769+ let emitAmountEstimated = $t03185331988._1
770+ let commonState = $t03185331988._2
771+ let feeAmount = $t03185331988._3
772+ let bonus = $t03185331988._4
773+ $Tuple2(nil, $Tuple3(emitAmountEstimated, feeAmount, bonus))
774+ }
775+
776+
777+
778+@Callable(i)
779+func getOneTkn (outAssetIdStr,minOutAmount) = {
780+ let isPoolOneTokenOperationsDisabled = {
781+ let @ = invoke(factoryContract, "isPoolOneTokenOperationsDisabledREADONLY", [toString(this)], nil)
782+ if ($isInstanceOf(@, "Boolean"))
783+ then @
784+ else throw(($getType(@) + " couldn't be cast to Boolean"))
785+ }
786+ let isGetDisabled = if (if (isGlobalShutdown())
787+ then true
788+ else (cfgPoolStatus == PoolShutdown))
789+ then true
790+ else isPoolOneTokenOperationsDisabled
791+ let checks = [if (!(isGetDisabled))
792+ then true
793+ else throwErr("get operation is blocked by admin"), if ((size(i.payments) == 1))
794+ then true
795+ else throwErr("exactly 1 payment are expected")]
796+ if ((checks == checks))
797+ then {
798+ let outAssetId = parseAssetId(outAssetIdStr)
799+ let payment = i.payments[0]
800+ let paymentAssetId = payment.assetId
801+ let paymentAmount = payment.amount
802+ let userAddress = i.caller
803+ let txId = i.transactionId
804+ let $t03276032892 = calcGetOneToken(outAssetId, paymentAmount, paymentAssetId, userAddress, txId)
805+ let amountEstimated = $t03276032892._1
806+ let commonState = $t03276032892._2
807+ let feeAmount = $t03276032892._3
808+ let bonus = $t03276032892._4
809+ let amount = if (if ((minOutAmount > 0))
810+ then (minOutAmount > amountEstimated)
811+ else false)
812+ then throwErr(makeString(["amount to receive is less than ", toString(minOutAmount)], ""))
813+ else amountEstimated
814+ let burnInv = invoke(factoryContract, "burn", [paymentAmount], [AttachedPayment(paymentAssetId, paymentAmount)])
815+ if ((burnInv == burnInv))
816+ then {
817+ let assetTransfer = [ScriptTransfer(userAddress, amount, outAssetId)]
818+ let sendFee = if ((feeAmount > 0))
819+ then [ScriptTransfer(feeCollectorAddress, feeAmount, outAssetId)]
820+ else nil
821+ $Tuple2(((commonState ++ assetTransfer) ++ sendFee), amount)
822+ }
823+ else throw("Strict value is not equal to itself.")
824+ }
825+ else throw("Strict value is not equal to itself.")
826+ }
827+
828+
829+
830+@Callable(i)
831+func getOneTknREADONLY (outAssetId,paymentAmount) = {
832+ let $t03352733665 = calcGetOneToken(parseAssetId(outAssetId), paymentAmount, cfgLpAssetId, unit, unit)
833+ let amountEstimated = $t03352733665._1
834+ let commonState = $t03352733665._2
835+ let feeAmount = $t03352733665._3
836+ let bonus = $t03352733665._4
837+ $Tuple2(nil, $Tuple3(amountEstimated, feeAmount, bonus))
838+ }
839+
840+
841+
842+@Callable(i)
843+func unstakeAndGetOneTkn (unstakeAmount,outAssetIdStr,minOutAmount) = {
844+ let isPoolOneTokenOperationsDisabled = {
845+ let @ = invoke(factoryContract, "isPoolOneTokenOperationsDisabledREADONLY", [toString(this)], nil)
846+ if ($isInstanceOf(@, "Boolean"))
847+ then @
848+ else throw(($getType(@) + " couldn't be cast to Boolean"))
849+ }
850+ let isGetDisabled = if (if (isGlobalShutdown())
851+ then true
852+ else (cfgPoolStatus == PoolShutdown))
853+ then true
854+ else isPoolOneTokenOperationsDisabled
855+ let checks = [if (!(isGetDisabled))
856+ then true
857+ else throwErr("get operation is blocked by admin"), if ((size(i.payments) == 0))
858+ then true
859+ else throwErr("no payments are expected")]
860+ if ((checks == checks))
861+ then {
862+ let outAssetId = parseAssetId(outAssetIdStr)
863+ let userAddress = i.caller
864+ let txId = i.transactionId
865+ let unstakeInv = invoke(stakingContract, "unstake", [toBase58String(cfgLpAssetId), unstakeAmount], nil)
866+ if ((unstakeInv == unstakeInv))
867+ then {
868+ let $t03445734587 = calcGetOneToken(outAssetId, unstakeAmount, cfgLpAssetId, userAddress, txId)
869+ let amountEstimated = $t03445734587._1
870+ let commonState = $t03445734587._2
871+ let feeAmount = $t03445734587._3
872+ let bonus = $t03445734587._4
873+ let amount = if (if ((minOutAmount > 0))
874+ then (minOutAmount > amountEstimated)
875+ else false)
876+ then throwErr(makeString(["amount to receive is less than ", toString(minOutAmount)], ""))
877+ else amountEstimated
878+ let burnInv = invoke(factoryContract, "burn", [unstakeAmount], [AttachedPayment(cfgLpAssetId, unstakeAmount)])
879+ if ((burnInv == burnInv))
880+ then {
881+ let assetTransfer = [ScriptTransfer(i.caller, amount, outAssetId)]
882+ let sendFee = if ((feeAmount > 0))
883+ then [ScriptTransfer(feeCollectorAddress, feeAmount, outAssetId)]
884+ else nil
885+ $Tuple2(((commonState ++ assetTransfer) ++ sendFee), amount)
886+ }
887+ else throw("Strict value is not equal to itself.")
888+ }
889+ else throw("Strict value is not equal to itself.")
890+ }
891+ else throw("Strict value is not equal to itself.")
892+ }
531893
532894
533895
534896 @Callable(i)
535897 func get () = {
536898 let res = commonGet(i)
537899 let outAmtAmt = res._1
538900 let outPrAmt = res._2
539901 let pmtAmt = res._3
540902 let pmtAssetId = res._4
541903 let state = res._5
542904 let burnLPAssetOnFactory = invoke(factoryContract, "burn", [pmtAmt], [AttachedPayment(pmtAssetId, pmtAmt)])
543905 if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
544906 then state
545907 else throw("Strict value is not equal to itself.")
546908 }
547909
548910
549911
550912 @Callable(i)
551913 func getNoLess (noLessThenAmtAsset,noLessThenPriceAsset) = {
552914 let res = commonGet(i)
553915 let outAmAmt = res._1
554916 let outPrAmt = res._2
555917 let pmtAmt = res._3
556918 let pmtAssetId = res._4
557919 let state = res._5
558920 if ((noLessThenAmtAsset > outAmAmt))
559921 then throw(((("noLessThenAmtAsset failed: " + toString(outAmAmt)) + " < ") + toString(noLessThenAmtAsset)))
560922 else if ((noLessThenPriceAsset > outPrAmt))
561923 then throw(((("noLessThenPriceAsset failed: " + toString(outPrAmt)) + " < ") + toString(noLessThenPriceAsset)))
562924 else {
563925 let burnLPAssetOnFactory = invoke(factoryContract, "burn", [pmtAmt], [AttachedPayment(pmtAssetId, pmtAmt)])
564926 if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
565927 then state
566928 else throw("Strict value is not equal to itself.")
567929 }
568930 }
569931
570932
571933
572934 @Callable(i)
573935 func unstakeAndGet (amount) = {
574936 let checkPayments = if ((size(i.payments) != 0))
575937 then throw("No payments are expected")
576938 else true
577939 if ((checkPayments == checkPayments))
578940 then {
579941 let cfg = getPoolConfig()
580- let factoryCfg = getFactoryConfig()
581942 let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
582- let stakingContract = valueOrErrorMessage(addressFromString(factoryCfg[idxFactoryStakingContract]), "Error. Incorrect staking address.")
583943 let unstakeInv = invoke(stakingContract, "unstake", [toBase58String(lpAssetId), amount], nil)
584944 if ((unstakeInv == unstakeInv))
585945 then {
586946 let res = estimateGetOperation(toBase58String(i.transactionId), toBase58String(lpAssetId), amount, i.caller)
587947 let poolStatus = parseIntValue(res._9)
588948 let state = res._10
589949 let checkPoolStatus = if (if (isGlobalShutdown())
590950 then true
591951 else (poolStatus == PoolShutdown))
592952 then throw(("Get operation is blocked by admin. Status = " + toString(poolStatus)))
593953 else true
594954 if ((checkPoolStatus == checkPoolStatus))
595955 then {
596956 let burnLPAssetOnFactory = invoke(factoryContract, "burn", [amount], [AttachedPayment(lpAssetId, amount)])
597957 if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
598958 then state
599959 else throw("Strict value is not equal to itself.")
600960 }
601961 else throw("Strict value is not equal to itself.")
602962 }
603963 else throw("Strict value is not equal to itself.")
604964 }
605965 else throw("Strict value is not equal to itself.")
606966 }
607967
608968
609969
610970 @Callable(i)
611971 func activate (amtAssetStr,priceAssetStr) = if ((toString(i.caller) != toString(factoryContract)))
612972 then throw("permissions denied")
613973 else $Tuple2([StringEntry(aa(), amtAssetStr), StringEntry(pa(), priceAssetStr)], "success")
614974
615975
616976
617977 @Callable(i)
618978 func getPoolConfigWrapperREADONLY () = $Tuple2(nil, getPoolConfig())
619979
620980
621981
622982 @Callable(i)
623983 func getAccBalanceWrapperREADONLY (assetId) = $Tuple2(nil, getAccBalance(assetId))
624984
625985
626986
627987 @Callable(i)
628988 func calcPricesWrapperREADONLY (amAmt,prAmt,lpAmt) = {
629989 let prices = calcPrices(amAmt, prAmt, lpAmt)
630990 $Tuple2(nil, [toString(prices[0]), toString(prices[1]), toString(prices[2])])
631991 }
632992
633993
634994
635995 @Callable(i)
636996 func toX18WrapperREADONLY (origVal,origScaleMult) = $Tuple2(nil, toString(toX18(origVal, origScaleMult)))
637997
638998
639999
6401000 @Callable(i)
6411001 func fromX18WrapperREADONLY (val,resultScaleMult) = $Tuple2(nil, fromX18(parseBigIntValue(val), resultScaleMult))
6421002
6431003
6441004
6451005 @Callable(i)
6461006 func calcPriceBigIntWrapperREADONLY (prAmtX18,amAmtX18) = $Tuple2(nil, toString(calcPriceBigInt(parseBigIntValue(prAmtX18), parseBigIntValue(amAmtX18))))
6471007
6481008
6491009
6501010 @Callable(i)
6511011 func estimatePutOperationWrapperREADONLY (txId58,slippageTolerance,inAmAssetAmt,inAmAssetId,inPrAssetAmt,inPrAssetId,userAddress,isEvaluate,emitLp) = $Tuple2(nil, estimatePutOperation(txId58, slippageTolerance, inAmAssetAmt, inAmAssetId, inPrAssetAmt, inPrAssetId, userAddress, isEvaluate, emitLp))
6521012
6531013
6541014
6551015 @Callable(i)
6561016 func estimateGetOperationWrapperREADONLY (txId58,pmtAssetId,pmtLpAmt,userAddress) = {
6571017 let res = estimateGetOperation(txId58, pmtAssetId, pmtLpAmt, addressFromStringValue(userAddress))
6581018 $Tuple2(nil, $Tuple10(res._1, res._2, res._3, res._4, res._5, res._6, res._7, toString(res._8), res._9, res._10))
6591019 }
6601020
6611021
6621022
6631023 @Callable(i)
6641024 func statsREADONLY () = {
6651025 let cfg = getPoolConfig()
6661026 let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
6671027 let amtAssetId = cfg[idxAmtAssetId]
6681028 let priceAssetId = cfg[idxPriceAssetId]
6691029 let iAmtAssetId = cfg[idxIAmtAssetId]
6701030 let iPriceAssetId = cfg[idxIPriceAssetId]
6711031 let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
6721032 let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
6731033 let poolLPBalance = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
6741034 let accAmtAssetBalance = getAccBalance(amtAssetId)
6751035 let accPriceAssetBalance = getAccBalance(priceAssetId)
6761036 let pricesList = if ((poolLPBalance == 0))
6771037 then [zeroBigInt, zeroBigInt, zeroBigInt]
6781038 else calcPrices(accAmtAssetBalance, accPriceAssetBalance, poolLPBalance)
6791039 let curPrice = 0
6801040 let lpAmtAssetShare = fromX18(pricesList[1], scale8)
6811041 let lpPriceAssetShare = fromX18(pricesList[2], scale8)
6821042 let poolWeight = value(getInteger(factoryContract, keyPoolWeight(toString(this))))
6831043 $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))
6841044 }
6851045
6861046
6871047
6881048 @Callable(i)
6891049 func evaluatePutByAmountAssetREADONLY (inAmAssetAmt) = {
6901050 let cfg = getPoolConfig()
6911051 let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
6921052 let amAssetIdStr = cfg[idxAmtAssetId]
6931053 let amAssetId = fromBase58String(amAssetIdStr)
6941054 let prAssetIdStr = cfg[idxPriceAssetId]
6951055 let prAssetId = fromBase58String(prAssetIdStr)
6961056 let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
6971057 let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
6981058 let poolStatus = cfg[idxPoolStatus]
6991059 let poolLPBalance = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
7001060 let accAmtAssetBalance = getAccBalance(amAssetIdStr)
7011061 let accPriceAssetBalance = getAccBalance(prAssetIdStr)
7021062 let amtAssetAmtX18 = toX18(accAmtAssetBalance, amtAssetDcm)
7031063 let priceAssetAmtX18 = toX18(accPriceAssetBalance, priceAssetDcm)
7041064 let curPriceX18 = if ((poolLPBalance == 0))
7051065 then zeroBigInt
7061066 else calcPriceBigInt(priceAssetAmtX18, amtAssetAmtX18)
7071067 let inAmAssetAmtX18 = toX18(inAmAssetAmt, amtAssetDcm)
7081068 let inPrAssetAmtX18 = fraction(inAmAssetAmtX18, curPriceX18, scale18)
7091069 let inPrAssetAmt = fromX18(inPrAssetAmtX18, priceAssetDcm)
7101070 let estPut = estimatePutOperation("", 500000, inAmAssetAmt, amAssetId, inPrAssetAmt, prAssetId, "", true, false)
7111071 let calcLpAmt = estPut._1
7121072 let curPriceCalc = estPut._3
7131073 let amBalance = estPut._4
7141074 let prBalance = estPut._5
7151075 let lpEmission = estPut._6
7161076 $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))
7171077 }
7181078
7191079
7201080
7211081 @Callable(i)
7221082 func evaluatePutByPriceAssetREADONLY (inPrAssetAmt) = {
7231083 let cfg = getPoolConfig()
7241084 let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
7251085 let amAssetIdStr = cfg[idxAmtAssetId]
7261086 let amAssetId = fromBase58String(amAssetIdStr)
7271087 let prAssetIdStr = cfg[idxPriceAssetId]
7281088 let prAssetId = fromBase58String(prAssetIdStr)
7291089 let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
7301090 let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
7311091 let poolStatus = cfg[idxPoolStatus]
7321092 let poolLPBalance = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
7331093 let amBalanceRaw = getAccBalance(amAssetIdStr)
7341094 let prBalanceRaw = getAccBalance(prAssetIdStr)
7351095 let amBalanceRawX18 = toX18(amBalanceRaw, amtAssetDcm)
7361096 let prBalanceRawX18 = toX18(prBalanceRaw, priceAssetDcm)
7371097 let curPriceX18 = if ((poolLPBalance == 0))
7381098 then zeroBigInt
7391099 else calcPriceBigInt(prBalanceRawX18, amBalanceRawX18)
7401100 let inPrAssetAmtX18 = toX18(inPrAssetAmt, priceAssetDcm)
7411101 let inAmAssetAmtX18 = fraction(inPrAssetAmtX18, scale18, curPriceX18)
7421102 let inAmAssetAmt = fromX18(inAmAssetAmtX18, amtAssetDcm)
7431103 let estPut = estimatePutOperation("", 500000, inAmAssetAmt, amAssetId, inPrAssetAmt, prAssetId, "", true, false)
7441104 let calcLpAmt = estPut._1
7451105 let curPriceCalc = estPut._3
7461106 let amBalance = estPut._4
7471107 let prBalance = estPut._5
7481108 let lpEmission = estPut._6
7491109 $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))
7501110 }
7511111
7521112
7531113
7541114 @Callable(i)
7551115 func evaluateGetREADONLY (paymentLpAssetId,paymentLpAmt) = {
7561116 let res = estimateGetOperation("", paymentLpAssetId, paymentLpAmt, this)
7571117 let outAmAmt = res._1
7581118 let outPrAmt = res._2
7591119 let amBalance = res._5
7601120 let prBalance = res._6
7611121 let lpEmission = res._7
7621122 let curPrice = res._8
7631123 let poolStatus = parseIntValue(res._9)
7641124 $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))
7651125 }
7661126
7671127
7681128 @Verifier(tx)
7691129 func verify () = {
7701130 let targetPublicKey = match managerPublicKeyOrUnit() {
7711131 case pk: ByteVector =>
7721132 pk
7731133 case _: Unit =>
7741134 tx.senderPublicKey
7751135 case _ =>
7761136 throw("Match error")
7771137 }
7781138 match tx {
7791139 case order: Order =>
7801140 let matcherPub = getMatcherPubOrFail()
7811141 let orderValid = validateMatcherOrderAllowed(order)
7821142 let senderValid = sigVerify(order.bodyBytes, order.proofs[0], order.senderPublicKey)
7831143 let matcherValid = sigVerify(order.bodyBytes, order.proofs[1], matcherPub)
7841144 if (if (if (orderValid)
7851145 then senderValid
7861146 else false)
7871147 then matcherValid
7881148 else false)
7891149 then true
7901150 else throwOrderError(orderValid, senderValid, matcherValid)
7911151 case s: SetScriptTransaction =>
7921152 let newHash = blake2b256(value(s.script))
7931153 let allowedHash = fromBase64String(value(getString(factoryContract, keyAllowedLpScriptHash())))
7941154 let currentHash = scriptHash(this)
7951155 if (if ((allowedHash == newHash))
7961156 then (currentHash != newHash)
7971157 else false)
7981158 then true
7991159 else sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey)
8001160 case _ =>
8011161 sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey)
8021162 }
8031163 }
8041164

github/deemru/w8io/026f985 
151.68 ms