2024.04.18 16:00 [3068231] smart account 3N9Zi6AcWcGbM23jQJ4fnzFsoHoTsxYDznr > SELF 0.00000000 Waves

{ "type": 13, "id": "BL3oJzDQxq8t8jLPudSUKH8mn4h5SHVfixt7y6njYRmi", "fee": 2800000, "feeAssetId": null, "timestamp": 1713445206034, "version": 2, "chainId": 84, "sender": "3N9Zi6AcWcGbM23jQJ4fnzFsoHoTsxYDznr", "senderPublicKey": "GFbasS3jufhZkK4xR7tdTjjnP8K33KvJFEDHRtxXDkaJ", "proofs": [ "3rFkBEEzkEg5owdnftXDPLsycjVJ68XapgcusYH3vJ8isi88gxu5HXdouPoYtDMuhYRSRwg2rsUbdac2MF7MqcEj" ], "script": "base64:BgL8HAgCEgQKAggBEgcKBQgICAgBEgQKAggIEgUKAwgIARIECgIICBIDCgEBEgMKAQESAwoBCBIECgIICBIECgIIBBIAEgMKAQESABIECgIICBIECgIICBIECgIICBIAEgQKAggIEgUKAwgIASIJc2VwYXJhdG9yIg5wb29sV2VpZ2h0TXVsdCIPbWF4RGVwdGhEZWZhdWx0IhlmaW5hbGl6YXRpb25TdGFnZUJhbGFuY2VzIhZmaW5hbGl6YXRpb25TdGFnZVRvdGFsIhdmaW5hbGl6YXRpb25TdGFnZVNoYXJlcyILd2F2ZXNTdHJpbmciDmtleUVwb2NoTGVuZ3RoIhFrZXlFcG9jaExlbmd0aE5ldyIVa2V5RXBvY2hMZW5ndGhCeUVwb2NoIgVlcG9jaCIPa2V5Q3VycmVudEVwb2NoIgtrZXlNYXhEZXB0aCIQa2V5UmVzdW1wdGlvbkZlZSIia2V5Vm90aW5nRW1pc3Npb25DYW5kaWRhdGVDb250cmFjdCIda2V5Vm90aW5nRW1pc3Npb25SYXRlQ29udHJhY3QiEmtleUZhY3RvcnlDb250cmFjdCITa2V5Qm9vc3RpbmdDb250cmFjdCISa2V5U3Rha2luZ0NvbnRyYWN0IhZrZXlBc3NldHNTdG9yZUNvbnRyYWN0IhRrZXlGaW5hbGl6YXRpb25TdGFnZSILa2V5TmV4dFBvb2wiC2tleU5leHRVc2VyIg5rZXlTdGFydEhlaWdodCIRa2V5Q3VycmVudEVwb2NoVWkiEGtleVN0YXJ0SGVpZ2h0VWkiHWtleUZpbmFsaXphdGlvblNob3VsZEJlRm9yY2VkIhZrZXlBbGxvd2VkTHBTY3JpcHRIYXNoIhxrZXlBbGxvd2VkTHBTdGFibGVTY3JpcHRIYXNoIhVrZXlTdGFydEhlaWdodEJ5RXBvY2giDGtleUZpbmFsaXplZCIJa2V5SW5MaXN0IgRwb29sIgskdDAyMTI3MjE2NyINYW1vdW50QXNzZXRJZCIMcHJpY2VBc3NldElkIhdrZXlJbnN1ZmZpY2llbnRCYWxhbmNlcyILJHQwMjMxNjIzNTYiB2tleVVzZWQiB2FkZHJlc3MiB2tleVZvdGUiCyR0MDI2NjQyNzA0Ig9rZXlWb3RpbmdSZXN1bHQiCyR0MDI4ODYyOTI2IhVrZXlWb3RpbmdSZXN1bHRTdGFrZWQiDGxwQXNzZXRJZFN0ciIMa2V5UG9vbFNoYXJlIgskdDAzMjQ3MzI4NyINa2V5VG90YWxWb3RlcyIPa2V5U3Rha2VkQnlVc2VyIg51c2VyQWRkcmVzc1N0ciIHd3JhcEVyciIDbXNnIgh0aHJvd0VyciIOZ2V0VmFsdWVPckZhaWwiA2tleSIEdHlwZSIFZXJyb3IiByRtYXRjaDAiA3N0ciIDaW50IgxnZXRTdHJPckZhaWwiAUAiDGdldEludE9yRmFpbCIMcG9vbFRvU3RyaW5nIgxzdHJpbmdUb1Bvb2wiBXBhcnRzIg9mYWN0b3J5Q29udHJhY3QiGklkeEZhY3RvcnlDZmdHd3hSZXdhcmREYXBwIg1rZXlGYWN0b3J5Q2ZnIhRyZWFkRmFjdG9yeUNmZ09yRmFpbCIHZmFjdG9yeSIZZ2V0R3d4UmV3YXJkQWRkcmVzc09yRmFpbCIKZmFjdG9yeUNmZyIMcGFyc2VBc3NldElkIgVpbnB1dCIPYXNzZXRJZFRvU3RyaW5nIgtnZXRQb29sSW5mbyIOcG9vbEluZm9PcHRpb24iFmdldExwQXNzZXRCeVBvb2xBc3NldHMiH2tleU1hcHBpbmdzQmFzZUFzc2V0MmludGVybmFsSWQiDGJhc2VBc3NldFN0ciIpa2V5TWFwcGluZ1Bvb2xBc3NldHNUb1Bvb2xDb250cmFjdEFkZHJlc3MiGGludGVybmFsQW1vdW50QXNzZXRJZFN0ciIXaW50ZXJuYWxQcmljZUFzc2V0SWRTdHIiH2tleU1hcHBpbmdQb29sQ29udHJhY3RUb0xQQXNzZXQiE3Bvb2xDb250cmFjdEFkZHJlc3MiFWFtb3VudEFzc2V0SW50ZXJuYWxJZCIUcHJpY2VBc3NldEludGVybmFsSWQiCWxwQXNzZXRJZCIYY2hlY2tXeEVtaXNzaW9uUG9vbExhYmVsIgskdDA2NjQ3NjY4NyIQZ3d4UmV3YXJkRGVwb3NpdCISZ3d4UmV3YXJkc0NvbnRyYWN0Ig1wb29sc0xpc3ROYW1lIhBnZXRWb3Rlc0xpc3ROYW1lIgskdDA3MTA0NzE0NCILa2V5TGlzdEhlYWQiCGxpc3ROYW1lIgRtZXRhIgtrZXlMaXN0U2l6ZSILa2V5TGlzdFByZXYiAmlkIgtrZXlMaXN0TmV4dCIMY29udGFpbnNOb2RlIgpoZWFkT3JVbml0IgpwcmV2T3JVbml0IgpuZXh0T3JVbml0IhFpbnNlcnROb2RlQWN0aW9ucyIIbGlzdFNpemUiCWNoZWNrTm9kZSIRZGVsZXRlTm9kZUFjdGlvbnMiFmtleU1hbmFnZXJWYXVsdEFkZHJlc3MiE2tleU1hbmFnZXJQdWJsaWNLZXkiHGdldE1hbmFnZXJWYXVsdEFkZHJlc3NPclRoaXMiAXMiFm1hbmFnZXJQdWJsaWNLZXlPclVuaXQiE21hbmFnZXJWYXVsdEFkZHJlc3MiCWlzTWFuYWdlciIBaSICcGsiC211c3RNYW5hZ2VyIghtdXN0VGhpcyILdXNlckFkZHJlc3MiDHRhcmdldEhlaWdodCIXYm9vc3RpbmdDb250cmFjdEFkZHJlc3MiH3ZvdGluZ0VtaXNzaW9uQ2FuZGlkYXRlQ29udHJhY3QiEGJvb3N0aW5nQ29udHJhY3QiD3N0YWtpbmdDb250cmFjdCILZXBvY2hMZW5ndGgiBmNoZWNrcyINaW5MaXN0QWN0aW9ucyIYY3VycmVudEVwb2NoSXNOb3REZWZpbmVkIhJzdGFydEhlaWdodEFjdGlvbnMiBmFtb3VudCILc3RhcnRIZWlnaHQiCWVuZEhlaWdodCIXZmluYWxpemF0aW9uU3RhZ2VPclVuaXQiBHVzZWQiBHZvdGUiCnBvb2xSZXN1bHQiCnRvdGFsVm90ZXMiE2d3eEFtb3VudEF0RW5kVG90YWwiCWF2YWlsYWJsZSIHbmV3Vm90ZSIKd3hFbWlzc2lvbiINdm90ZXNMaXN0TmFtZSIQdm90ZXNMaXN0QWN0aW9ucyIObmV3RXBvY2hMZW5ndGgiC25ld01heERlcHRoIgdwb29sU3RyIgtjaGVja0NhbGxlciINZXBvY2hQcmV2aW91cyINJHQwMTczNjgxNzQwOCISYmFsYW5jZUlzT2tDdXJyZW50IhNiYWxhbmNlSXNPa1ByZXZpb3VzIgdhY3Rpb25zIhNkZWxldGVXeEVtaXNzaW9uSW52Ig9tb2RpZnlXZWlnaHRJbnYiC3Bvb2xBZGRyZXNzIgluZXdTdGF0dXMiEHNldFBvb2xTdGF0dXNJbnYiC2xpc3RBY3Rpb25zIhNzdGFydEhlaWdodFByZXZpb3VzIhNlcG9jaExlbmd0aFByZXZpb3VzIhFlbmRIZWlnaHRQcmV2aW91cyIQY2hlY2tUYXJnZXRFcG9jaCINJHQwMTk3NjExOTgwMSIbZ3d4QW1vdW50QXRFbmRUb3RhbFByZXZpb3VzIgx2b3RpbmdSZXN1bHQiEnZvdGVQcmV2aW91c09wdGlvbiIMdm90ZVByZXZpb3VzIhp2b3RpbmdSZXN1bHRTdGFrZWRQcmV2aW91cyIMc3Rha2VkQnlVc2VyIhl2b3RpbmdSZXN1bHRTdGFrZWRBY3Rpb25zIgVmb3JjZSILdGFyZ2V0RXBvY2giDGN1cnJlbnRFcG9jaCINJHQwMjIyNzEyMjMxMSIBciITYXNzZXRzU3RvcmVDb250cmFjdCIFc2hhcmUiDXByZXZpb3VzRXBvY2giCG5ld0Vwb2NoIhRuZXdFcG9jaExlbmd0aE9wdGlvbiIVbmV3RXBvY2hMZW5ndGhBY3Rpb25zIgpwb29sT3JVbml0IgckbWF0Y2gxIgtuZXh0UG9vbFN0ciIObmV4dFBvb2xPclVuaXQiCnVzZXJPclVuaXQiDHBvb2xzSGVhZFN0ciIObmV4dFVzZXJPclVuaXQiBHVzZXIiBG5leHQiDnByb2Nlc3NWb3RlSW52IgckbWF0Y2gyIghuZXh0VXNlciITZ3d4UmV3YXJkRGVwb3NpdEludiIHY291bnRlciIadm90aW5nRW1pc3Npb25SYXRlQ29udHJhY3QiBnJlc3VsdCIDaW52IghtYXhEZXB0aCIWZmluYWxpemF0aW9uSW5Qcm9ncmVzcyIfc2xpcHBhZ2VUb2xlcmFuY2VPck1pbk91dEFtb3VudCINJHQwMzMyNjMzMzM5MyIKZmVlUGF5bWVudCIPa0Jvb3N0aW5nQ29uZmlnIg1pZHhDZmdBc3NldElkIgl3eEFzc2V0SWQiE2Ftb3VudEFzc2V0VmVyaWZpZWQiEnByaWNlQXNzZXRWZXJpZmllZCINcmVzdW1wdGlvbkZlZSIUbHBBc3NldEJhbGFuY2VCZWZvcmUiCWF1dG9TdGFrZSIDcHV0IgtiYWxhbmNlSXNPayIOcG9vbFNjcmlwdEhhc2giEWFsbG93ZWRTY3JpcHRIYXNoIghpc1N0YWJsZSIMZnVuY3Rpb25OYW1lIhNscEFzc2V0QmFsYW5jZUFmdGVyIhJscEFzc2V0QmFsYW5jZURpZmYiFmxwQXNzZXRUcmFuc2ZlckFjdGlvbnMiEHNldFd4RW1pc3Npb25JbnYiAnR4IgZ2ZXJpZnkiD3RhcmdldFB1YmxpY0tleUkAAWECAl9fAAFiAIDC1y8AAWMACgABZAAAAAFlAAEAAWYAAgABZwIFV0FWRVMAAWgJALkJAgkAzAgCAgIlcwkAzAgCAgtlcG9jaExlbmd0aAUDbmlsBQFhAAFpCQC5CQIJAMwIAgIEJXMlcwkAzAgCAhBlcG9jaExlbmd0aF9fbmV3BQNuaWwFAWEBAWoBAWsJALkJAgkAzAgCAgQlcyVkCQDMCAICC2Vwb2NoTGVuZ3RoCQDMCAIJAKQDAQUBawUDbmlsBQFhAAFsCQC5CQIJAMwIAgICJXMJAMwIAgIMY3VycmVudEVwb2NoBQNuaWwFAWEAAW0JALkJAgkAzAgCAgIlcwkAzAgCAghtYXhEZXB0aAUDbmlsBQFhAAFuCQC5CQIJAMwIAgICJXMJAMwIAgINcmVzdW1wdGlvbkZlZQUDbmlsBQFhAAFvCQC5CQIJAMwIAgICJXMJAMwIAgIfdm90aW5nRW1pc3Npb25DYW5kaWRhdGVDb250cmFjdAUDbmlsBQFhAAFwCQC5CQIJAMwIAgICJXMJAMwIAgIadm90aW5nRW1pc3Npb25SYXRlQ29udHJhY3QFA25pbAUBYQABcQkAuQkCCQDMCAICAiVzCQDMCAICD2ZhY3RvcnlDb250cmFjdAUDbmlsBQFhAAFyCQC5CQIJAMwIAgICJXMJAMwIAgIQYm9vc3RpbmdDb250cmFjdAUDbmlsBQFhAAFzCQC5CQIJAMwIAgICJXMJAMwIAgIPc3Rha2luZ0NvbnRyYWN0BQNuaWwFAWEAAXQJALkJAgkAzAgCAgIlcwkAzAgCAhNhc3NldHNTdG9yZUNvbnRyYWN0BQNuaWwFAWEAAXUJALkJAgkAzAgCAgIlcwkAzAgCAhFmaW5hbGl6YXRpb25TdGFnZQUDbmlsBQFhAAF2CQC5CQIJAMwIAgICJXMJAMwIAgIIbmV4dFBvb2wFA25pbAUBYQABdwkAuQkCCQDMCAICAiVzCQDMCAICCG5leHRVc2VyBQNuaWwFAWEAAXgJALkJAgkAzAgCAgIlcwkAzAgCAgtzdGFydEhlaWdodAUDbmlsBQFhAAF5CQC5CQIJAMwIAgICJXMJAMwIAgIOY3VycmVudEVwb2NoVWkFA25pbAUBYQABegkAuQkCCQDMCAICAiVzCQDMCAICDXN0YXJ0SGVpZ2h0VWkFA25pbAUBYQABQQkAuQkCCQDMCAICAiVzCQDMCAICBWZvcmNlBQNuaWwFAWEBAUIAAhclc19fYWxsb3dlZExwU2NyaXB0SGFzaAEBQwACHSVzX19hbGxvd2VkTHBTdGFibGVTY3JpcHRIYXNoAQFEAQFrCQC5CQIJAMwIAgIEJXMlZAkAzAgCAgtzdGFydEhlaWdodAkAzAgCCQCkAwEFAWsFA25pbAUBYQEBRQEBawkAuQkCCQDMCAICBCVzJWQJAMwIAgIJZmluYWxpemVkCQDMCAIJAKQDAQUBawUDbmlsBQFhAQFGAQFHBAFIBQFHBAFJCAUBSAJfMQQBSggFAUgCXzIJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgIGaW5MaXN0CQDMCAIFAUkJAMwIAgUBSgUDbmlsBQFhAQFLAgFHAWsEAUwFAUcEAUkIBQFMAl8xBAFKCAUBTAJfMgkAuQkCCQDMCAICCCVzJXMlcyVkCQDMCAICFGluc3VmZmljaWVudEJhbGFuY2VzCQDMCAIFAUkJAMwIAgUBSgkAzAgCCQCkAwEFAWsFA25pbAUBYQEBTQIBTgFrCQC5CQIJAMwIAgIGJXMlcyVkCQDMCAICBHVzZWQJAMwIAgkApQgBBQFOCQDMCAIJAKQDAQUBawUDbmlsBQFhAQFPAwFHAU4BawQBUAUBRwQBSQgFAVACXzEEAUoIBQFQAl8yCQC5CQIJAMwIAgIKJXMlcyVzJXMlZAkAzAgCAgR2b3RlCQDMCAIFAUkJAMwIAgUBSgkAzAgCCQClCAEFAU4JAMwIAgkApAMBBQFrBQNuaWwFAWEBAVECAUcBawQBUgUBRwQBSQgFAVICXzEEAUoIBQFSAl8yCQC5CQIJAMwIAgIIJXMlcyVzJWQJAMwIAgIMdm90aW5nUmVzdWx0CQDMCAIFAUkJAMwIAgUBSgkAzAgCCQCkAwEFAWsFA25pbAUBYQEBUwIBVAFrCQC5CQIJAMwIAgIGJXMlcyVkCQDMCAICEnZvdGluZ1Jlc3VsdFN0YWtlZAkAzAgCBQFUCQDMCAIJAKQDAQUBawUDbmlsBQFhAQFVAgFHAWsEAVYFAUcEAUkIBQFWAl8xBAFKCAUBVgJfMgkAuQkCCQDMCAICCCVzJXMlcyVkCQDMCAICCXBvb2xTaGFyZQkAzAgCBQFJCQDMCAIFAUoJAMwIAgkApAMBBQFrBQNuaWwFAWEBAVcBAWsJALkJAgkAzAgCAgQlcyVkCQDMCAICCnRvdGFsVm90ZXMJAMwIAgkApAMBBQFrBQNuaWwFAWEBAVgCAVQBWQkAuQkCCQDMCAICBiVzJXMlcwkAzAgCAgZzdGFrZWQJAMwIAgUBWQkAzAgCBQFUBQNuaWwFAWEBAVoBAmFhCQC5CQIJAMwIAgIVdm90aW5nX2VtaXNzaW9uLnJpZGU6CQDMCAIFAmFhBQNuaWwCASABAmFiAQJhYQkAAgEJAQFaAQUCYWEBAmFjAwFOAmFkAmFlBAJhZgkBAVoBCQC5CQIJAMwIAgIKbWFuZGF0b3J5IAkAzAgCCQClCAEFAU4JAMwIAgIBLgkAzAgCBQJhZAkAzAgCAg8gaXMgbm90IGRlZmluZWQFA25pbAIACQETdmFsdWVPckVycm9yTWVzc2FnZQIEAmFnBQJhZQMJAAECBQJhZwIGU3RyaW5nBAJhaAUCYWcJAJ0IAgUBTgUCYWQDCQABAgUCYWcCA0ludAQCYWkFAmFnCQCaCAIFAU4FAmFkCQECYWIBAhJpbnZhbGlkIGVudHJ5IHR5cGUFAmFmAQJhagIBTgJhZAoAAmFrCQECYWMDBQFOBQJhZAIAAwkAAQIFAmFrAgZTdHJpbmcFAmFrCQACAQkArAICCQADAQUCYWsCGyBjb3VsZG4ndCBiZSBjYXN0IHRvIFN0cmluZwECYWwCAU4CYWQKAAJhawkBAmFjAwUBTgUCYWQAAAMJAAECBQJhawIDSW50BQJhawkAAgEJAKwCAgkAAwEFAmFrAhggY291bGRuJ3QgYmUgY2FzdCB0byBJbnQBAmFtAQFHCQCsAgIJAKwCAggFAUcCXzEFAWEIBQFHAl8yAQJhbgECYWgEAmFvCQC1CQIFAmFoBQFhAwkAAAIJAJADAQUCYW8AAgkAlAoCCQCRAwIFAmFvAAAJAJEDAgUCYW8AAQkBAmFiAQITaW52YWxpZCBwb29sIHN0cmluZwACYXAJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQJhagIFBHRoaXMFAXEAAmFxAAoBAmFyAAIRJXNfX2ZhY3RvcnlDb25maWcBAmFzAQJhdAkAtQkCCQECYWoCBQJhdAkBAmFyAAUBYQECYXUBAmF2CQERQGV4dHJOYXRpdmUoMTA2MikBCQCRAwIFAmF2BQJhcQECYXcBAmF4AwkAAAIFAmF4BQFnBQR1bml0CQDZBAEFAmF4AQJheQECYXgDCQAAAgUCYXgFBHVuaXQFAWcJANgEAQkBBXZhbHVlAQUCYXgBAmF6AgFJAUoEAmFBCgACYWsJAPwHBAUCYXACEHBvb2xJbmZvUkVBRE9OTFkJAMwIAgUBSQkAzAgCBQFKBQNuaWwFA25pbAMJAAECBQJhawIVKEFkZHJlc3MsIEJ5dGVWZWN0b3IpBQJhawUEdW5pdAUCYUEBAmFCAgFJAUoKAQJhQwECYUQJAKwCAgIoJXMlcyVzX19tYXBwaW5nc19fYmFzZUFzc2V0MmludGVybmFsSWRfXwUCYUQKAQJhRQICYUYCYUcJAKwCAgkArAICCQCsAgIJAKwCAgIKJWQlZCVzJXNfXwkApAMBBQJhRgICX18JAKQDAQUCYUcCI19fbWFwcGluZ3NfX3Bvb2xBc3NldHMyUG9vbENvbnRyYWN0CgECYUgBAmFJCQCsAgIJAKwCAgIIJXMlcyVzX18FAmFJAiBfX21hcHBpbmdzX19wb29sQ29udHJhY3QyTHBBc3NldAQCYUoJAQJhbAIFAmFwCQECYUMBBQFJBAJhSwkBAmFsAgUCYXAJAQJhQwEFAUoEAmFJCQECYWoCBQJhcAkBAmFFAgUCYUoFAmFLBAJhTAkBAmFqAgUCYXAJAQJhSAEFAmFJBQJhTAECYU0BAUcEAmFOBQFHBAFJCAUCYU4CXzEEAUoIBQJhTgJfMgoAAmFrCQD8BwQFAmFwAhhjaGVja1d4RW1pc3Npb25Qb29sTGFiZWwJAMwIAgUBSQkAzAgCBQFKBQNuaWwFA25pbAMJAAECBQJhawIHQm9vbGVhbgUCYWsJAAIBCQCsAgIJAAMBBQJhawIcIGNvdWxkbid0IGJlIGNhc3QgdG8gQm9vbGVhbgECYU8ABAJhdgkBAmFzAQUCYXAEAmFQCQECYXUBBQJhdgkA/AcEBQJhUAIHZGVwb3NpdAUDbmlsBQNuaWwAAmFRAgVwb29scwECYVIBAUcEAmFTBQFHBAFJCAUCYVMCXzEEAUoIBQJhUwJfMgkAuQkCCQDMCAICBXZvdGVzCQDMCAIFAUkJAMwIAgUBSgUDbmlsBQFhAQJhVAECYVUEAmFWAwkAAAIFAmFVBQJhUQIEJXMlcwIIJXMlcyVzJXMJALkJAgkAzAgCBQJhVgkAzAgCBQJhVQkAzAgCAgRoZWFkBQNuaWwFAWEBAmFXAQJhVQQCYVYDCQAAAgUCYVUFAmFRAgQlcyVzAgglcyVzJXMlcwkAuQkCCQDMCAIFAmFWCQDMCAIFAmFVCQDMCAICBHNpemUFA25pbAUBYQECYVgCAmFVAmFZBAJhVgMJAAACBQJhVQUCYVECCCVzJXMlcyVzAgolcyVzJXMlcyVzCQC5CQIJAMwIAgUCYVYJAMwIAgUCYVUJAMwIAgUCYVkJAMwIAgIEcHJldgUDbmlsBQFhAQJhWgICYVUCYVkEAmFWAwkAAAIFAmFVBQJhUQIIJXMlcyVzJXMCCiVzJXMlcyVzJXMJALkJAgkAzAgCBQJhVgkAzAgCBQJhVQkAzAgCBQJhWQkAzAgCAgRuZXh0BQNuaWwFAWEBAmJhAgJhVQJhWQQCYmIJAJ0IAgUEdGhpcwkBAmFUAQUCYVUEAmJjCQCdCAIFBHRoaXMJAQJhWAIFAmFVBQJhWQQCYmQJAJ0IAgUEdGhpcwkBAmFaAgUCYVUFAmFZAwMJAAACBQJhWQkBC3ZhbHVlT3JFbHNlAgUCYmICAAYJAQIhPQIFAmJjBQR1bml0BgkBAiE9AgUCYmQFBHVuaXQBAmJlAgJhVQJhWQQCYmIJAJ0IAgUEdGhpcwkBAmFUAQUCYVUEAmJmCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQJhVwEFAmFVAAAEAmJnAwkBASEBCQECYmECBQJhVQUCYVkGCQECYWIBAgtOb2RlIGV4aXN0cwMJAAACBQJiZwUCYmcJAM4IAgkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQECYVcBBQJhVQkAZAIFAmJmAAEFA25pbAMJAQIhPQIFAmJiBQR1bml0CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQJhWgIFAmFVBQJhWQkBBXZhbHVlAQUCYmIJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAmFYAgUCYVUJAQV2YWx1ZQEFAmJiBQJhWQUDbmlsBQNuaWwJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAmFUAQUCYVUFAmFZBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BAmJoAgJhVQJhWQQCYmIJAJ0IAgUEdGhpcwkBAmFUAQUCYVUEAmJmCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQJhVwEFAmFVAAAEAmJjCQCdCAIFBHRoaXMJAQJhWAIFAmFVBQJhWQQCYmQJAJ0IAgUEdGhpcwkBAmFaAgUCYVUFAmFZCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIJAQJhVwEFAmFVCQBlAgUCYmYAAQUDbmlsAwMJAQIhPQIFAmJjBQR1bml0CQECIT0CBQJiZAUEdW5pdAcJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAmFaAgUCYVUJAQV2YWx1ZQEFAmJjCQEFdmFsdWUBBQJiZAkAzAgCCQELU3RyaW5nRW50cnkCCQECYVgCBQJhVQkBBXZhbHVlAQUCYmQJAQV2YWx1ZQEFAmJjCQDMCAIJAQtEZWxldGVFbnRyeQEJAQJhWAIFAmFVBQJhWQkAzAgCCQELRGVsZXRlRW50cnkBCQECYVoCBQJhVQUCYVkFA25pbAMJAQIhPQIFAmJkBQR1bml0CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQJhVAEFAmFVCQEFdmFsdWUBBQJiZAkAzAgCCQELRGVsZXRlRW50cnkBCQECYVoCBQJhVQUCYVkJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBAmFYAgUCYVUJAQV2YWx1ZQEFAmJkBQNuaWwDCQECIT0CBQJiYwUEdW5pdAkAzAgCCQELRGVsZXRlRW50cnkBCQECYVgCBQJhVQUCYVkJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBAmFaAgUCYVUJAQV2YWx1ZQEFAmJjBQNuaWwDCQAAAgUCYVkJAQt2YWx1ZU9yRWxzZQIFAmJiAgAJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBAmFUAQUCYVUFA25pbAkBAmFiAQkArAICCQCsAgIJAKwCAgIOaW52YWxpZCBub2RlOiAFAmFVAgEuBQJhWQECYmkAAhclc19fbWFuYWdlclZhdWx0QWRkcmVzcwECYmoAAhQlc19fbWFuYWdlclB1YmxpY0tleQECYmsABAJhZwkAoggBCQECYmkAAwkAAQIFAmFnAgZTdHJpbmcEAmJsBQJhZwkBEUBleHRyTmF0aXZlKDEwNjIpAQUCYmwFBHRoaXMBAmJtAAQCYm4JAQJiawAEAmFnCQCdCAIFAmJuCQECYmoAAwkAAQIFAmFnAgZTdHJpbmcEAmJsBQJhZwkA2QQBBQJibAMJAAECBQJhZwIEVW5pdAUEdW5pdAkAAgECC01hdGNoIGVycm9yAQJibwECYnAEAmFnCQECYm0AAwkAAQIFAmFnAgpCeXRlVmVjdG9yBAJicQUCYWcJAAACCAUCYnAPY2FsbGVyUHVibGljS2V5BQJicQMJAAECBQJhZwIEVW5pdAkAAAIIBQJicAZjYWxsZXIFBHRoaXMJAAIBAgtNYXRjaCBlcnJvcgECYnIBAmJwAwkBAmJvAQUCYnAGCQACAQIRcGVybWlzc2lvbiBkZW5pZWQBAmJzAQJicAMJAAACCAUCYnAGY2FsbGVyBQR0aGlzBgkAAgECEXBlcm1pc3Npb24gZGVuaWVkEwJicAEYZ2V0VXNlckd3eEFtb3VudEF0SGVpZ2h0AgJidAJidQQCYnYJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQECYWoCBQR0aGlzBQFyCQEBWgECIWludmFsaWQgYm9vc3RpbmcgY29udHJhY3QgYWRkcmVzcwkAlAoCBQNuaWwKAAJhawkA/AcEBQJidgIgZ2V0VXNlckd3eEFtb3VudEF0SGVpZ2h0UkVBRE9OTFkJAMwIAgUCYnQJAMwIAgUCYnUFA25pbAUDbmlsAwkAAQIFAmFrAgNJbnQFAmFrCQACAQkArAICCQADAQUCYWsCGCBjb3VsZG4ndCBiZSBjYXN0IHRvIEludAJicAELY29uc3RydWN0b3IFAmFwAmJ3AmJ4AmJ5AmJ6BAJiQQkAzAgCCQECYnIBBQJicAkAzAgCAwkBAiE9AgkApggBBQJhcAUEdW5pdAYCIGludmFsaWQgZmFjdG9yeSBjb250cmFjdCBhZGRyZXNzCQDMCAIDCQECIT0CCQCmCAEFAmJ3BQR1bml0BgIyaW52YWxpZCB2b3RpbmcgZW1pc3Npb24gY2FuZGlkYXRlIGNvbnRyYWN0IGFkZHJlc3MJAMwIAgMJAQIhPQIJAKYIAQUCYngFBHVuaXQGAiFpbnZhbGlkIGJvb3N0aW5nIGNvbnRyYWN0IGFkZHJlc3MJAMwIAgMJAQIhPQIJAKYIAQUCYnkFBHVuaXQGAiBpbnZhbGlkIHN0YWtpbmcgY29udHJhY3QgYWRkcmVzcwkAzAgCAwkAZgIFAmJ6AAAGCQECYWIBAhRpbnZhbGlkIGVwb2NoIGxlbmd0aAUDbmlsAwkAAAIFAmJBBQJiQQkAlAoCCQDMCAIJAQtTdHJpbmdFbnRyeQIFAXEFAmFwCQDMCAIJAQtTdHJpbmdFbnRyeQIFAW8FAmJ3CQDMCAIJAQtTdHJpbmdFbnRyeQIFAXIFAmJ4CQDMCAIJAQtTdHJpbmdFbnRyeQIFAXMFAmJ5CQDMCAIJAQxJbnRlZ2VyRW50cnkCBQFoBQJiegUDbmlsBQR1bml0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmJwAQZjcmVhdGUCAUkBSgQCYkEJAMwIAgMJAAACCQDYBAEICAUCYnAGY2FsbGVyBWJ5dGVzCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMFAW8CAAYJAQJicgEFAmJwBQNuaWwDCQAAAgUCYkEFAmJBBAFHCQCUCgIFAUkFAUoEAmJCCQDOCAIJAMwIAgkBDEJvb2xlYW5FbnRyeQIJAQFGAQUBRwYFA25pbAkBAmJlAgUCYVEJAQJhbQEFAUcEAmJDCQAAAgkAmggCBQR0aGlzBQFsBQR1bml0BAJiRAMFAmJDBAFrAAAJAMwIAgkBDEludGVnZXJFbnRyeQIFAWwFAWsJAMwIAgkBDEludGVnZXJFbnRyeQIJAQFEAQUBawUGaGVpZ2h0CQDMCAIJAQxJbnRlZ2VyRW50cnkCBQF4BQZoZWlnaHQJAMwIAgkBDEludGVnZXJFbnRyeQIFAXkFAWsJAMwIAgkBDEludGVnZXJFbnRyeQIFAXoFBmhlaWdodAUDbmlsBQNuaWwJAJQKAgkAzggCBQJiQgUCYkQFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CYnABBHZvdGUDAUkBSgJiRQQBRwkAlAoCBQFJBQFKBAFrCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFAWwAAAQCYkYJAQJhbAIFBHRoaXMJAQFEAQUBawQCYnoJAQJhbAIFBHRoaXMFAWgEAmJHCQBkAgUCYkYFAmJ6BAJiSAkAmggCBQR0aGlzBQF1BAJiSQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEBTQIIBQJicAZjYWxsZXIFAWsAAAQCYkoJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBAU8DBQFHCAUCYnAGY2FsbGVyBQFrAAAEAmJLCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQFRAgUBRwUBawAABAJiTAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEBVwEFAWsAAAQCYk0KAAJhawkA/AcEBQR0aGlzAhhnZXRVc2VyR3d4QW1vdW50QXRIZWlnaHQJAMwIAgkA2AQBCAgFAmJwBmNhbGxlcgVieXRlcwkAzAgCBQJiRwUDbmlsBQNuaWwDCQABAgUCYWsCA0ludAUCYWsJAAIBCQCsAgIJAAMBBQJhawIYIGNvdWxkbid0IGJlIGNhc3QgdG8gSW50BAJiTgkAZQIFAmJNBQJiSQQCYk8JAGQCBQJiSgUCYkUEAmJQCQECYU0BBQFHBAJiQQkAzAgCAwkBAiE9AgkAoAgBCQEBRgEFAUcFBHVuaXQGCQECYWIBAg5pbnZhbGlkIGFzc2V0cwkAzAgCAwkAZgIFAmJHBQZoZWlnaHQGCQECYWIBAg5pbnZhbGlkIGhlaWdodAkAzAgCAwkAAAIFAmJIBQR1bml0BgkBAmFiAQIYZmluYWxpemF0aW9uIGluIHByb2dyZXNzCQDMCAIDCQBmAgUCYk0AAAYJAQJhYgECE3lvdSBkbyBub3QgaGF2ZSBnV1gJAMwIAgMDCQBmAgUCYkUAAAkAZwIFAmJOBQJiRQcGCQECYWIBAg5pbnZhbGlkIGFtb3VudAkAzAgCAwUCYlAGCQECYWIBAh1wb29sIGhhc24ndCBXWF9FTUlTU0lPTiBsYWJlbAUDbmlsAwkAAAIFAmJBBQJiQQQCYlEJAQJhUgEFAUcEAVkJAKUIAQgFAmJwBmNhbGxlcgQCYlIDCQECYmECBQJiUQUBWQUDbmlsCQECYmUCBQJiUQUBWQkAlAoCCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIJAQFNAggFAmJwBmNhbGxlcgUBawkAZAIFAmJJBQJiRQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAU8DBQFHCAUCYnAGY2FsbGVyBQFrBQJiTwkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAVECBQFHBQFrCQBkAgUCYksFAmJFCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEBVwEFAWsJAGQCBQJiTAUCYkUFA25pbAUCYlIFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CYnABCmNhbmNlbFZvdGUCAUkBSgQBRwkAlAoCBQFJBQFKBAFrCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFAWwAAAQCYkYJAQJhbAIFBHRoaXMJAQFEAQUBawQCYnoJAQJhbAIFBHRoaXMFAWgEAmJHCQBkAgUCYkYFAmJ6BAJiSAkAmggCBQR0aGlzBQF1BAJiSQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEBTQIIBQJicAZjYWxsZXIFAWsAAAQCYkoJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBAU8DBQFHCAUCYnAGY2FsbGVyBQFrAAAEAmJLCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQFRAgUBRwUBawAABAJiTAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEBVwEFAWsAAAQCYkEJAMwIAgMJAQIhPQIJAKAIAQkBAUYBBQFHBQR1bml0BgkBAmFiAQIOaW52YWxpZCBhc3NldHMJAMwIAgMJAGYCBQJiRwUGaGVpZ2h0BgkBAmFiAQIOaW52YWxpZCBoZWlnaHQJAMwIAgMJAAACBQJiSAUEdW5pdAYJAQJhYgECGGZpbmFsaXphdGlvbiBpbiBwcm9ncmVzcwkAzAgCAwkAZgIFAmJKAAAGCQECYWIBAgdubyB2b3RlBQNuaWwDCQAAAgUCYkEFAmJBBAJiUQkBAmFSAQUBRwQBWQkApQgBCAUCYnAGY2FsbGVyCQCUCgIJAM4IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAU0CCAUCYnAGY2FsbGVyBQFrCQCWAwEJAMwIAgkAZQIFAmJJBQJiSgkAzAgCAAAFA25pbAkAzAgCCQELRGVsZXRlRW50cnkBCQEBTwMFAUcIBQJicAZjYWxsZXIFAWsJAMwIAgkBDEludGVnZXJFbnRyeQIJAQFRAgUBRwUBawkAZQIFAmJLBQJiSgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAVcBBQFrCQBlAgUCYkwFAmJKBQNuaWwJAQJiaAIFAmJRBQFZBQR1bml0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmJwAQ5zZXRFcG9jaExlbmd0aAECYlMEAmJBCQDMCAIJAQJicgEFAmJwCQDMCAIDCQBmAgUCYlMAAAYJAQJhYgECFGludmFsaWQgZXBvY2ggbGVuZ3RoBQNuaWwDCQAAAgUCYkEFAmJBCQCUCgIJAMwIAgkBDEludGVnZXJFbnRyeQIFAWkFAmJTBQNuaWwFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CYnABC3NldE1heERlcHRoAQJiVAQCYkEJAMwIAgkBAmJyAQUCYnAJAMwIAgMJAGYCBQJiVAAABgkBAmFiAQIRaW52YWxpZCBtYXggZGVwdGgFA25pbAMJAAACBQJiQQUCYkEJAJQKAgkAzAgCCQEMSW50ZWdlckVudHJ5AgUBbQUCYlQFA25pbAUEdW5pdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJicAEacHJvY2Vzc1Bvb2xCYWxhbmNlSU5URVJOQUwBAmJVBAJiVgkBAmJzAQUCYnADCQAAAgUCYlYFAmJWBAFrCQECYWwCBQR0aGlzBQFsBAJiVwkAZQIFAWsAAQQBRwkBAmFuAQUCYlUEAmJYBQFHBAFJCAUCYlgCXzEEAUoIBQJiWAJfMgQCYUwJAQJhQgIFAUkFAUoEAmJZCgACYWsJAPwHBAUCYXACDGNoZWNrQmFsYW5jZQkAzAgCBQJhTAUDbmlsBQNuaWwDCQABAgUCYWsCB0Jvb2xlYW4FAmFrCQACAQkArAICCQADAQUCYWsCHCBjb3VsZG4ndCBiZSBjYXN0IHRvIEJvb2xlYW4EAmJaCQEBIQEJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhpcwkBAUsCBQFHCQBlAgUCYlcAAQcEAmNhAwkBASEBBQJiWQMJAQEhAQUCYloEAmNiCQD8BwQFAmFwAhlkZWxldGVXeEVtaXNzaW9uUG9vbExhYmVsCQDMCAIFAUkJAMwIAgUBSgUDbmlsBQNuaWwDCQAAAgUCY2IFAmNiBAJjYwkA/AcEBQJhcAIMbW9kaWZ5V2VpZ2h0CQDMCAIFAmFMCQDMCAIAAAUDbmlsBQNuaWwDCQAAAgUCY2MFAmNjBAJjZAgJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkBAmF6AgUBSQUBSgkBAVoBAg5pbnZhbGlkIGFzc2V0cwJfMQQCY2UAAwQCY2YJAPwHBAUCYXACCm1hbmFnZVBvb2wJAMwIAgkApQgBBQJjZAkAzAgCBQJjZQUDbmlsBQNuaWwDCQAAAgUCY2YFAmNmBAJjZwkAzggCCQDMCAIJAQtEZWxldGVFbnRyeQEJAQFGAQUBRwUDbmlsCQECYmgCBQJhUQkBAmFtAQUBRwkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEBVQIFAUcFAmJXAAAFA25pbAUCY2cJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAMwIAgkBDEJvb2xlYW5FbnRyeQIJAQFLAgUBRwUCYlcGBQNuaWwFA25pbAkAlAoCBQJjYQUEdW5pdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJicAETcHJvY2Vzc1ZvdGVJTlRFUk5BTAICYlUBWQQCYlYJAQJicwEFAmJwAwkAAAIFAmJWBQJiVgQCYnQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBBQFZCQEBWgEJAKwCAgIqcHJvY2Vzc1ZvdGVJTlRFUk5BTDogaW52YWxpZCB1c2VyIGFkZHJlc3MgBQFZBAFrCQECYWwCBQR0aGlzBQFsBAJiVwkAZQIFAWsAAQQCYnoJAQJhbAIFBHRoaXMFAWgEAmJGCQECYWwCBQR0aGlzCQEBRAEFAWsEAmJHCQBkAgUCYkYFAmJ6BAJjaAkBAmFsAgUEdGhpcwkBAUQBBQJiVwQCY2kJAQJhbAIFBHRoaXMJAQFqAQUCYlcEAmNqCQBkAgUCY2gFAmNpBAJjawMJAGcCBQJiVwAABgkBAmFiAQIrcHJvY2Vzc1ZvdGVJTlRFUk5BTDogaW52YWxpZCBwcmV2aW91cyBlcG9jaAMJAAACBQJjawUCY2sEAUcJAQJhbgEFAmJVBAJjbAUBRwQBSQgFAmNsAl8xBAFKCAUCY2wCXzIEAmJNCgACYWsJAPwHBAUEdGhpcwIYZ2V0VXNlckd3eEFtb3VudEF0SGVpZ2h0CQDMCAIFAVkJAMwIAgUCYkcFA25pbAUDbmlsAwkAAQIFAmFrAgNJbnQFAmFrCQACAQkArAICCQADAQUCYWsCGCBjb3VsZG4ndCBiZSBjYXN0IHRvIEludAQCY20KAAJhawkA/AcEBQR0aGlzAhhnZXRVc2VyR3d4QW1vdW50QXRIZWlnaHQJAMwIAgUBWQkAzAgCBQJjagUDbmlsBQNuaWwDCQABAgUCYWsCA0ludAUCYWsJAAIBCQCsAgIJAAMBBQJhawIYIGNvdWxkbid0IGJlIGNhc3QgdG8gSW50BAJiTAkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEBVwEFAWsAAAQCY24JAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBAVECBQFHBQFrAAAEAmNvCQCfCAEJAQFPAwUBRwUCYnQFAmJXBAJjcAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCBQJjbwkBAVoBCQCsAgIJAKwCAgkArAICCQCsAgICFHByb2Nlc3NWb3RlSU5URVJOQUwgBQJiVQIBIAUBWQISOiBubyBwcmV2aW91cyB2b3RlBAJiSQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEBTQIFAmJ0BQFrAAAEAVQJAQJhQgIFAUkFAUoEAmNxCQELdmFsdWVPckVsc2UCCQCfCAEJAQFTAgUBVAUCYlcAAAQCYnkJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQJhagIFBHRoaXMFAXMEAmNyCQELdmFsdWVPckVsc2UCCQCaCAIFAmJ5CQEBWAIFAVQFAVkAAAQCY3MDAwkAAAIFAmNyAAAGCQAAAgUCY28FBHVuaXQFA25pbAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAVMCBQFUBQJiVwkAZAIFAmNxBQJjcAUDbmlsBAJhTAkBAmFCAgUBSQUBSgQCYk8DCQBmAgUCY20AAAkAawMFAmNwBQJiTQUCY20AAAQCY2EDAwkAAAIFAmNvBQR1bml0BgkAZwIAAAUCYk8JAQJiaAIJAQJhUgEFAUcFAVkJAMwIAgkBDEludGVnZXJFbnRyeQIJAQFPAwUBRwUCYnQFAWsFAmJPCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEBVwEFAWsJAGQCBQJiTAUCYk8JAMwIAgkBDEludGVnZXJFbnRyeQIJAQFRAgUBRwUBawkAZAIFAmNuBQJiTwkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAU0CBQJidAUBawkAZAIFAmJJBQJiTwUDbmlsCQCUCgIJAM4IAgUCY2EFAmNzBQR1bml0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmJwARNwcm9jZXNzUG9vbElOVEVSTkFMAgJiVQJjdAQCYlYJAQJicwEFAmJwAwkAAAIFAmJWBQJiVgQCY3UEAmN2CQECYWwCBQR0aGlzBQFsAwUCY3QFAmN2CQBlAgUCY3YAAQQCY2sDCQBnAgUCY3UAAAYJAQJhYgECKXByb2Nlc3NQb29sSU5URVJOQUw6IGludmFsaWQgdGFyZ2V0IGVwb2NoAwkAAAIFAmNrBQJjawQBRwkBAmFuAQUCYlUEAmN3BQFHBAFJCAUCY3cCXzEEAUoIBQJjdwJfMgQCYnkJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQJhagIFBHRoaXMFAXMEAmFMCQECYUICBQFJBQFKBAJjeAoAAmFrCQD8BwQFAmJ5AhJ1c2Vyc0xpc3RUcmF2ZXJzYWwJAMwIAgUCYUwFA25pbAUDbmlsAwkAAQIFAmFrAgdCb29sZWFuBQJhawkAAgEJAKwCAgkAAwEFAmFrAhwgY291bGRuJ3QgYmUgY2FzdCB0byBCb29sZWFuAwkAAAIFAmN4BQJjeAMFAmN4CQCUCgIFA25pbAYEAmN5CQERQGV4dHJOYXRpdmUoMTA2MikBCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUCYXAFAXQCHWludmFsaWQgYXNzZXRzIHN0b3JlIGNvbnRyYWN0BAJiTAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEBVwEFAmN1AAAEAmNuCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQFRAgUBRwUCY3UAAAQCY3oDCQAAAgUCYkwAAAAACQBrAwUCY24FAWIFAmJMBAJjYwkA/AcEBQJhcAIMbW9kaWZ5V2VpZ2h0CQDMCAIFAmFMCQDMCAIFAmN6BQNuaWwFA25pbAMJAAACBQJjYwUCY2MJAJQKAgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAVUCBQFHBQJjdQUCY3oFA25pbAcJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CYnABDmZpbmFsaXplSGVscGVyAAQCY3QJAQt2YWx1ZU9yRWxzZQIJAKAIAQUBQQcEAWsJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUBbAAABAJjQQkAZQIFAWsAAQQCYkYJAQJhbAIFBHRoaXMJAQFEAQUBawQCYnoJAQJhbAIFBHRoaXMFAWgEAmJHCQBkAgUCYkYFAmJ6BAJiSAkAmggCBQR0aGlzBQF1AwMDCQBnAgUGaGVpZ2h0BQJiRwkAAAIFAmJIBQR1bml0BwkBASEBBQJjdAcEAmNCCQBkAgUBawABBAJjQwkAmggCBQR0aGlzBQFpBAJjRAQCYWcFAmNDAwkAAQIFAmFnAgNJbnQEAmJTBQJhZwkAzAgCCQEMSW50ZWdlckVudHJ5AgUBaAUCYlMJAMwIAgkBC0RlbGV0ZUVudHJ5AQUBaQUDbmlsAwkAAQIFAmFnAgRVbml0BQNuaWwJAAIBAgtNYXRjaCBlcnJvcgkAlAoCCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIJAQFEAQUCY0IFBmhlaWdodAkAzAgCCQEMSW50ZWdlckVudHJ5AgUBeAUGaGVpZ2h0CQDMCAIJAQxJbnRlZ2VyRW50cnkCBQFsBQJjQgkAzAgCCQEMSW50ZWdlckVudHJ5AgUBdQUBZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAWoBBQFrBQJiegUDbmlsBQJjRAYDAwUCY3QJAAACBQJiSAUEdW5pdAcJAJQKAgkAzAgCCQEMSW50ZWdlckVudHJ5AgUBdQUBZgUDbmlsBgMJAAACBQJiSAUEdW5pdAkAlAoCBQNuaWwHAwkAAAIFAmJIBQFkBAJjRQkAoggBBQF2BAJhZwUCY0UDCQABAgUCYWcCBFVuaXQEAmNGCQCiCAEJAQJhVAEFAmFRAwkAAQIFAmNGAgRVbml0CQCUCgIJAMwIAgkBDEludGVnZXJFbnRyeQIFAXUFAWUJAMwIAgkBC0RlbGV0ZUVudHJ5AQUBdgUDbmlsBgMJAAECBQJjRgIGU3RyaW5nBAJjRwUCY0YJAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCBQF2BQJjRwUDbmlsBgkAAgECC01hdGNoIGVycm9yAwkAAQIFAmFnAgZTdHJpbmcEAmJVBQJhZwQCY0gJAKIIAQkBAmFaAgUCYVEFAmJVAwkAAAIFAmNIBQJjSAQCY3gJAPwHBAUEdGhpcwIacHJvY2Vzc1Bvb2xCYWxhbmNlSU5URVJOQUwJAMwIAgUCYlUFA25pbAUDbmlsAwkAAAIFAmN4BQJjeAQCY0YFAmNIAwkAAQIFAmNGAgRVbml0CQCUCgIJAMwIAgkBDEludGVnZXJFbnRyeQIFAXUFAWUJAMwIAgkBC0RlbGV0ZUVudHJ5AQUBdgUDbmlsBgMJAAECBQJjRgIGU3RyaW5nBAJjRwUCY0YJAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCBQF2BQJjRwUDbmlsBgkAAgECC01hdGNoIGVycm9yCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQILTWF0Y2ggZXJyb3IDCQAAAgUCYkgFAWUEAmNFCQCiCAEFAXYEAmNJCQCiCAEFAXcEAmFnBQJjRQMJAAECBQJhZwIEVW5pdAQCY0YJAKIIAQkBAmFUAQUCYVEDCQABAgUCY0YCBFVuaXQJAJQKAgkAzAgCCQEMSW50ZWdlckVudHJ5AgUBdQUBZgkAzAgCCQELRGVsZXRlRW50cnkBBQF2CQDMCAIJAQtEZWxldGVFbnRyeQEFAXcFA25pbAYDCQABAgUCY0YCBlN0cmluZwQCY0oFAmNGCQCUCgIJAMwIAgkBC1N0cmluZ0VudHJ5AgUBdgUCY0oFA25pbAYJAAIBAgtNYXRjaCBlcnJvcgMJAAECBQJhZwIGU3RyaW5nBAJiVQUCYWcEAUcJAQJhbgEFAmJVBAJjSwQCY0YFAmNJAwkAAQIFAmNGAgRVbml0CQCiCAEJAQJhVAEJAQJhUgEFAUcDCQABAgUCY0YCBlN0cmluZwQCY0wFAmNGBAJjTQkAoggBCQECYVoCCQECYVIBBQFHBQJjTAMJAAACBQJjTQUCY00EAmNOCQD8BwQFBHRoaXMCE3Byb2Nlc3NWb3RlSU5URVJOQUwJAMwIAgUCYlUJAMwIAgUCY0wFA25pbAUDbmlsAwkAAAIFAmNOBQJjTgUCY00JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAgtNYXRjaCBlcnJvcgQCY0YFAmNLAwkAAQIFAmNGAgRVbml0BAJjSAkAoggBCQECYVoCBQJhUQUCYlUEAmNPBQJjSAMJAAECBQJjTwIEVW5pdAkAlAoCCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQF1BQFmCQDMCAIJAQtEZWxldGVFbnRyeQEFAXYJAMwIAgkBC0RlbGV0ZUVudHJ5AQUBdwUDbmlsBgMJAAECBQJjTwIGU3RyaW5nBAJibAUCY08JAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCBQF2BQJibAkAzAgCCQELRGVsZXRlRW50cnkBBQF3BQNuaWwGCQACAQILTWF0Y2ggZXJyb3IDCQABAgUCY0YCBlN0cmluZwQCY1AFAmNGCQCUCgIJAMwIAgkBC1N0cmluZ0VudHJ5AgUBdwUCY1AFA25pbAYJAAIBAgtNYXRjaCBlcnJvcgkAAgECC01hdGNoIGVycm9yAwkAAAIFAmJIBQFmBAJjRQkAoggBBQF2BAJhZwUCY0UDCQABAgUCYWcCBFVuaXQEAmNGCQCiCAEJAQJhVAEFAmFRAwkAAQIFAmNGAgRVbml0BAJjYQMFAmN0CQDMCAIJAQtEZWxldGVFbnRyeQEFAXUJAMwIAgkBC0RlbGV0ZUVudHJ5AQUBQQUDbmlsCQDMCAIJAQtEZWxldGVFbnRyeQEFAXUJAMwIAgkBDEJvb2xlYW5FbnRyeQIJAQFFAQUCY0EGCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQF5BQFrCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQF6BQJiRgUDbmlsBAJjUQkBAmFPAAMJAAACBQJjUQUCY1EJAJQKAgUCY2EGCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAwkAAQIFAmNGAgZTdHJpbmcEAmNHBQJjRgkAlAoCCQDMCAIJAQtTdHJpbmdFbnRyeQIFAXYFAmNHBQNuaWwGCQACAQILTWF0Y2ggZXJyb3IDCQABAgUCYWcCBlN0cmluZwQCYlUFAmFnBAJjSAkAoggBCQECYVoCBQJhUQUCYlUDCQAAAgUCY0gFAmNIBAJjeAoAAmFrCQD8BwQFBHRoaXMCE3Byb2Nlc3NQb29sSU5URVJOQUwJAMwIAgUCYlUJAMwIAgUCY3QFA25pbAUDbmlsAwkAAQIFAmFrAgdCb29sZWFuBQJhawkAAgEJAKwCAgkAAwEFAmFrAhwgY291bGRuJ3QgYmUgY2FzdCB0byBCb29sZWFuAwkAAAIFAmN4BQJjeAMFAmN4CQCUCgIFA25pbAYEAmNGBQJjSAMJAAECBQJjRgIEVW5pdAQCY2EDBQJjdAkAzAgCCQELRGVsZXRlRW50cnkBBQF1CQDMCAIJAQtEZWxldGVFbnRyeQEFAUEJAMwIAgkBC0RlbGV0ZUVudHJ5AQUBdgUDbmlsCQDMCAIJAQtEZWxldGVFbnRyeQEFAXUJAMwIAgkBDEJvb2xlYW5FbnRyeQIJAQFFAQUCY0EGCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQF5BQFrCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQF6BQJiRgkAzAgCCQELRGVsZXRlRW50cnkBBQF2BQNuaWwEAmNRCQECYU8AAwkAAAIFAmNRBQJjUQkAlAoCBQJjYQYJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4DCQABAgUCY0YCBlN0cmluZwQCY0cFAmNGCQCUCgIJAMwIAgkBC1N0cmluZ0VudHJ5AgUBdgUCY0cFA25pbAYJAAIBAgtNYXRjaCBlcnJvcgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECC01hdGNoIGVycm9yCQECYWIBAhZmaW5hbGl6YXRpb24gaXMgYnJva2VuAmJwAQ9maW5hbGl6ZVdyYXBwZXIBAmNSBAJjUwkBEUBleHRyTmF0aXZlKDEwNjIpAQkBEUBleHRyTmF0aXZlKDEwNTMpAgUEdGhpcwUBcAQCY1QKAAJhawkA/AcEBQR0aGlzAg5maW5hbGl6ZUhlbHBlcgUDbmlsBQNuaWwDCQABAgUCYWsCB0Jvb2xlYW4FAmFrCQACAQkArAICCQADAQUCYWsCHCBjb3VsZG4ndCBiZSBjYXN0IHRvIEJvb2xlYW4DCQAAAgUCY1QFAmNUAwkBASEBBQJjVAMJAAACBQJjUgAACQECYWIBAh5DdXJyZW50IHZvdGluZyBpcyBub3Qgb3ZlciB5ZXQEAmNVCQD8BwQFAmNTAghmaW5hbGl6ZQUDbmlsBQNuaWwDCQAAAgUCY1UFAmNVCQCUCgIFA25pbAUEdW5pdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgQCY1YJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUBbQUBYwMJAGYCBQJjVgUCY1IEAmNVCQD8BwQFBHRoaXMCD2ZpbmFsaXplV3JhcHBlcgkAzAgCCQBkAgUCY1IAAQUDbmlsBQNuaWwDCQAAAgUCY1UFAmNVCQCUCgIFA25pbAUEdW5pdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAlAoCBQNuaWwFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CYnABCGZpbmFsaXplAAQCY1UJAPwHBAUEdGhpcwIPZmluYWxpemVXcmFwcGVyCQDMCAIAAAUDbmlsBQNuaWwDCQAAAgUCY1UFAmNVCQCUCgIFA25pbAUEdW5pdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJicAEUY29udGFpbnNOb2RlUkVBRE9OTFkCAmFVAmFZCQCUCgIFA25pbAkBAmJhAgUCYVUFAmFZAmJwAQppbnNlcnROb2RlAgJhVQJhWQQCYlYJAQJicgEFAmJwAwkAAAIFAmJWBQJiVgkAlAoCCQECYmUCBQJhVQUCYVkFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CYnABCmRlbGV0ZU5vZGUCAmFVAmFZBAJiVgkBAmJyAQUCYnADCQAAAgUCYlYFAmJWCQCUCgIJAQJiaAIFAmFVBQJhWQUEdW5pdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJicAEYaXNGaW5hbGl6YXRpb25JblByb2dyZXNzAAQCYkgJAJoIAgUEdGhpcwUBdQQCY1cJAQIhPQIFAmJIBQR1bml0CQCUCgIFA25pbAUCY1cCYnABCmRlbGV0ZVBvb2wCAUkBSgQCYlYDAwkAAAIIBQJicAZjYWxsZXIFAmFwBgkBAmJyAQUCYnAGCQECYWIBAhFQZXJtaXNzaW9uIGRlbmllZAMJAAACBQJiVgUCYlYEAmFVAgVwb29scwQBRwkAlAoCBQFJBQFKBAJhWQkAuQkCCQDMCAIFAUkJAMwIAgUBSgUDbmlsBQFhBAJjYQMJAQJiYQIFAmFVBQJhWQkBAmJoAgUCYVUFAmFZBQNuaWwJAM4IAgkAzAgCCQELRGVsZXRlRW50cnkBCQEBRgEFAUcFA25pbAUCY2EJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CYnABBnJlc3VtZQMBSQFKAmNYBAJiSAkAmggCBQR0aGlzBQF1BAJjWQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQECYXoCBQFJBQFKCQEBWgECDmludmFsaWQgYXNzZXRzBAJjZAgFAmNZAl8xBAJhTAgFAmNZAl8yBAJjWgkAkQMCCAUCYnAIcGF5bWVudHMAAAQCY3kJARFAZXh0ck5hdGl2ZSgxMDYyKQEJARFAZXh0ck5hdGl2ZSgxMDUzKQIFBHRoaXMFAXQEAmRhAgolc19fY29uZmlnBAJkYgABBAJieAkBEUBleHRyTmF0aXZlKDEwNjIpAQkBAmFqAgUEdGhpcwUBcgQCZGMJANkEAQkAkQMCCQC1CQIJARFAZXh0ck5hdGl2ZSgxMDUzKQIFAmJ4BQJkYQUBYQUCZGIEAmRkCgACYWsJAPwHBAUCY3kCEmlzVmVyaWZpZWRSRUFET05MWQkAzAgCBQFJBQNuaWwFA25pbAMJAAECBQJhawIHQm9vbGVhbgUCYWsJAAIBCQCsAgIJAAMBBQJhawIcIGNvdWxkbid0IGJlIGNhc3QgdG8gQm9vbGVhbgQCZGUKAAJhawkA/AcEBQJjeQISaXNWZXJpZmllZFJFQURPTkxZCQDMCAIFAUoFA25pbAUDbmlsAwkAAQIFAmFrAgdCb29sZWFuBQJhawkAAgEJAKwCAgkAAwEFAmFrAhwgY291bGRuJ3QgYmUgY2FzdCB0byBCb29sZWFuBAJkZgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFBHRoaXMFAW4CFmludmFsaWQgcmVzdW1wdGlvbiBmZWUEAmJBCQDMCAIDCQAAAgUCYkgFBHVuaXQGCQECYWIBAhtmaW5hbGl6YXRpb24gaXMgaW4gcHJvZ3Jlc3MJAMwIAgMJAAACCAUCY1oHYXNzZXRJZAUCZGMGCQECYWIBAhxpbnZhbGlkIGZlZSBwYXltZW50IGFzc2V0IGlkCQDMCAIDCQAAAggFAmNaBmFtb3VudAUCZGYGCQECYWIBAhppbnZhbGlkIGZlZSBwYXltZW50IGFtb3VudAkAzAgCAwMFAmRkBQJkZQcGCQECYWIBAh5ib3RoIGFzc2V0cyBzaG91bGQgYmUgdmVyaWZpZWQFA25pbAMJAAACBQJiQQUCYkEEAmRnCQDwBwIFBHRoaXMFAmFMAwkAAAIFAmRnBQJkZwQCZGgHBAJkaQMJAAACCQCQAwEIBQJicAhwYXltZW50cwABBAJkagoAAmFrCQD8BwQFAmFwAgxjaGVja0JhbGFuY2UJAMwIAgkBAmF5AQUCYUwFA25pbAUDbmlsAwkAAQIFAmFrAgdCb29sZWFuBQJhawkAAgEJAKwCAgkAAwEFAmFrAhwgY291bGRuJ3QgYmUgY2FzdCB0byBCb29sZWFuAwUCZGoGCQECYWIBAhlhc3NldHMgc2hvdWxkIGJlIGF0dGFjaGVkAwkAAAIJAJADAQgFAmJwCHBheW1lbnRzAAIEAmRrCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAPEHAQUCY2QJAQFaAQIccG9vbCBhZGRyZXNzIGlzIG5vdCBzY3JpcHRlZAQCZGwJANsEAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFAmFwCQEBQwAJAQFaAQIoYWxsb3dlZCBscCBzdGFibGUgc2NyaXB0IGhhc2ggaXMgbm90IHNldAQCZG0JAAACBQJkawUCZGwEAmRuAwUCZG0CC3B1dE9uZVRrblYyAglwdXRPbmVUa24JAPwHBAUCY2QFAmRuCQDMCAIFAmNYCQDMCAIFAmRoBQNuaWwJAMwIAgkAkQMCCAUCYnAIcGF5bWVudHMAAQUDbmlsAwkAAAIJAJADAQgFAmJwCHBheW1lbnRzAAMJAPwHBAUCY2QCA3B1dAkAzAgCBQJjWAkAzAgCBQJkaAUDbmlsCQDMCAIJAJEDAggFAmJwCHBheW1lbnRzAAEJAMwIAgkAkQMCCAUCYnAIcGF5bWVudHMAAgUDbmlsCQECYWIBAhVpbnZhbGlkIHBheW1lbnRzIHNpemUDCQAAAgUCZGkFAmRpBAJkbwkA8AcCBQR0aGlzBQJhTAMJAAACBQJkbwUCZG8EAmRwCQBlAgUCZG8FAmRnBAJkcQMJAGYCBQJkcAAACQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQJicAZjYWxsZXIFAmRwBQJhTAUDbmlsBQNuaWwEAmRyCQD8BwQFAmFwAhZzZXRXeEVtaXNzaW9uUG9vbExhYmVsCQDMCAIFAUkJAMwIAgUBSgUDbmlsBQNuaWwDCQAAAgUCZHIFAmRyBAFHCQCUCgIFAUkFAUoEAmJCCQDOCAIJAMwIAgkBDEJvb2xlYW5FbnRyeQIJAQFGAQUBRwYFA25pbAkBAmJlAgUCYVEJAQJhbQEFAUcJAJQKAgkAzggCBQJiQgUCZHEFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BAmRzAQJkdAAEAmR1BAJhZwkBAmJtAAMJAAECBQJhZwIKQnl0ZVZlY3RvcgQCYnEFAmFnBQJicQMJAAECBQJhZwIEVW5pdAgFAmRzD3NlbmRlclB1YmxpY0tleQkAAgECC01hdGNoIGVycm9yCQD0AwMIBQJkcwlib2R5Qnl0ZXMJAJEDAggFAmRzBnByb29mcwAABQJkdZVbatM=", "height": 3068231, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: KTryZkBiizn7FmoWa3HxgrzWHARH3brtXuWu8ijAznF Next: 5HmkgC4yPdmKxBECrSjaNrXpyJUdUC5mTa1Xgq85b2ru Diff:
OldNewDifferences
615615 }
616616 let totalVotes = valueOrElse(getInteger(keyTotalVotes(epoch)), 0)
617617 let votingResult = valueOrElse(getInteger(keyVotingResult(pool, epoch)), 0)
618- let votePrevious = valueOrErrorMessage(getInteger(keyVote(pool, userAddress, epochPrevious)), wrapErr((((("processVoteINTERNAL " + poolStr) + " ") + userAddressStr) + ": no previous vote")))
618+ let votePreviousOption = getInteger(keyVote(pool, userAddress, epochPrevious))
619+ let votePrevious = valueOrErrorMessage(votePreviousOption, wrapErr((((("processVoteINTERNAL " + poolStr) + " ") + userAddressStr) + ": no previous vote")))
619620 let used = valueOrElse(getInteger(this, keyUsed(userAddress, epoch)), 0)
620621 let lpAssetIdStr = getLpAssetByPoolAssets(amountAssetId, priceAssetId)
621622 let votingResultStakedPrevious = valueOrElse(getInteger(keyVotingResultStaked(lpAssetIdStr, epochPrevious)), 0)
622623 let stakingContract = addressFromStringValue(getStrOrFail(this, keyStakingContract))
623624 let stakedByUser = valueOrElse(getInteger(stakingContract, keyStakedByUser(lpAssetIdStr, userAddressStr)), 0)
624- let votingResultStakedActions = if ((stakedByUser == 0))
625+ let votingResultStakedActions = if (if ((stakedByUser == 0))
626+ then true
627+ else (votePreviousOption == unit))
625628 then nil
626629 else [IntegerEntry(keyVotingResultStaked(lpAssetIdStr, epochPrevious), (votingResultStakedPrevious + votePrevious))]
627630 let lpAssetId = getLpAssetByPoolAssets(amountAssetId, priceAssetId)
628631 let newVote = if ((gwxAmountAtEndTotalPrevious > 0))
629632 then fraction(votePrevious, gwxAmountAtEndTotal, gwxAmountAtEndTotalPrevious)
630633 else 0
631- let actions = if ((newVote > 0))
632- then [IntegerEntry(keyVote(pool, userAddress, epoch), newVote), IntegerEntry(keyTotalVotes(epoch), (totalVotes + newVote)), IntegerEntry(keyVotingResult(pool, epoch), (votingResult + newVote)), IntegerEntry(keyUsed(userAddress, epoch), (used + newVote))]
633- else deleteNodeActions(getVotesListName(pool), userAddressStr)
634+ let actions = if (if ((votePreviousOption == unit))
635+ then true
636+ else (0 >= newVote))
637+ then deleteNodeActions(getVotesListName(pool), userAddressStr)
638+ else [IntegerEntry(keyVote(pool, userAddress, epoch), newVote), IntegerEntry(keyTotalVotes(epoch), (totalVotes + newVote)), IntegerEntry(keyVotingResult(pool, epoch), (votingResult + newVote)), IntegerEntry(keyUsed(userAddress, epoch), (used + newVote))]
634639 $Tuple2((actions ++ votingResultStakedActions), unit)
635640 }
636641 else throw("Strict value is not equal to itself.")
657662 if ((checkTargetEpoch == checkTargetEpoch))
658663 then {
659664 let pool = stringToPool(poolStr)
660- let $t02216422204 = pool
661- let amountAssetId = $t02216422204._1
662- let priceAssetId = $t02216422204._2
665+ let $t02227122311 = pool
666+ let amountAssetId = $t02227122311._1
667+ let priceAssetId = $t02227122311._2
663668 let stakingContract = addressFromStringValue(getStrOrFail(this, keyStakingContract))
664669 let lpAssetId = getLpAssetByPoolAssets(amountAssetId, priceAssetId)
665670 let r = {
972977
973978 @Callable(i)
974979 func resume (amountAssetId,priceAssetId,slippageToleranceOrMinOutAmount) = {
975- let $t03308533215 = valueOrErrorMessage(getPoolInfo(amountAssetId, priceAssetId), wrapErr("invalid assets"))
976- let poolAddress = $t03308533215._1
977- let lpAssetId = $t03308533215._2
980+ let finalizationStageOrUnit = getInteger(this, keyFinalizationStage)
981+ let $t03326333393 = valueOrErrorMessage(getPoolInfo(amountAssetId, priceAssetId), wrapErr("invalid assets"))
982+ let poolAddress = $t03326333393._1
983+ let lpAssetId = $t03326333393._2
978984 let feePayment = i.payments[0]
979985 let assetsStoreContract = addressFromStringValue(getStringValue(this, keyAssetsStoreContract))
980986 let kBoostingConfig = "%s__config"
9941000 else throw(($getType(@) + " couldn't be cast to Boolean"))
9951001 }
9961002 let resumptionFee = valueOrErrorMessage(getInteger(this, keyResumptionFee), "invalid resumption fee")
997- let checks = [if ((feePayment.assetId == wxAssetId))
1003+ let checks = [if ((finalizationStageOrUnit == unit))
1004+ then true
1005+ else throwErr("finalization is in progress"), if ((feePayment.assetId == wxAssetId))
9981006 then true
9991007 else throwErr("invalid fee payment asset id"), if ((feePayment.amount == resumptionFee))
10001008 then true
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let separator = "__"
55
66 let poolWeightMult = 100000000
77
88 let maxDepthDefault = 10
99
1010 let finalizationStageBalances = 0
1111
1212 let finalizationStageTotal = 1
1313
1414 let finalizationStageShares = 2
1515
1616 let wavesString = "WAVES"
1717
1818 let keyEpochLength = makeString(["%s", "epochLength"], separator)
1919
2020 let keyEpochLengthNew = makeString(["%s%s", "epochLength__new"], separator)
2121
2222 func keyEpochLengthByEpoch (epoch) = makeString(["%s%d", "epochLength", toString(epoch)], separator)
2323
2424
2525 let keyCurrentEpoch = makeString(["%s", "currentEpoch"], separator)
2626
2727 let keyMaxDepth = makeString(["%s", "maxDepth"], separator)
2828
2929 let keyResumptionFee = makeString(["%s", "resumptionFee"], separator)
3030
3131 let keyVotingEmissionCandidateContract = makeString(["%s", "votingEmissionCandidateContract"], separator)
3232
3333 let keyVotingEmissionRateContract = makeString(["%s", "votingEmissionRateContract"], separator)
3434
3535 let keyFactoryContract = makeString(["%s", "factoryContract"], separator)
3636
3737 let keyBoostingContract = makeString(["%s", "boostingContract"], separator)
3838
3939 let keyStakingContract = makeString(["%s", "stakingContract"], separator)
4040
4141 let keyAssetsStoreContract = makeString(["%s", "assetsStoreContract"], separator)
4242
4343 let keyFinalizationStage = makeString(["%s", "finalizationStage"], separator)
4444
4545 let keyNextPool = makeString(["%s", "nextPool"], separator)
4646
4747 let keyNextUser = makeString(["%s", "nextUser"], separator)
4848
4949 let keyStartHeight = makeString(["%s", "startHeight"], separator)
5050
5151 let keyCurrentEpochUi = makeString(["%s", "currentEpochUi"], separator)
5252
5353 let keyStartHeightUi = makeString(["%s", "startHeightUi"], separator)
5454
5555 let keyFinalizationShouldBeForced = makeString(["%s", "force"], separator)
5656
5757 func keyAllowedLpScriptHash () = "%s__allowedLpScriptHash"
5858
5959
6060 func keyAllowedLpStableScriptHash () = "%s__allowedLpStableScriptHash"
6161
6262
6363 func keyStartHeightByEpoch (epoch) = makeString(["%s%d", "startHeight", toString(epoch)], separator)
6464
6565
6666 func keyFinalized (epoch) = makeString(["%s%d", "finalized", toString(epoch)], separator)
6767
6868
6969 func keyInList (pool) = {
7070 let $t021272167 = pool
7171 let amountAssetId = $t021272167._1
7272 let priceAssetId = $t021272167._2
7373 makeString(["%s%s%s", "inList", amountAssetId, priceAssetId], separator)
7474 }
7575
7676
7777 func keyInsufficientBalances (pool,epoch) = {
7878 let $t023162356 = pool
7979 let amountAssetId = $t023162356._1
8080 let priceAssetId = $t023162356._2
8181 makeString(["%s%s%s%d", "insufficientBalances", amountAssetId, priceAssetId, toString(epoch)], separator)
8282 }
8383
8484
8585 func keyUsed (address,epoch) = makeString(["%s%s%d", "used", toString(address), toString(epoch)], separator)
8686
8787
8888 func keyVote (pool,address,epoch) = {
8989 let $t026642704 = pool
9090 let amountAssetId = $t026642704._1
9191 let priceAssetId = $t026642704._2
9292 makeString(["%s%s%s%s%d", "vote", amountAssetId, priceAssetId, toString(address), toString(epoch)], separator)
9393 }
9494
9595
9696 func keyVotingResult (pool,epoch) = {
9797 let $t028862926 = pool
9898 let amountAssetId = $t028862926._1
9999 let priceAssetId = $t028862926._2
100100 makeString(["%s%s%s%d", "votingResult", amountAssetId, priceAssetId, toString(epoch)], separator)
101101 }
102102
103103
104104 func keyVotingResultStaked (lpAssetIdStr,epoch) = makeString(["%s%s%d", "votingResultStaked", lpAssetIdStr, toString(epoch)], separator)
105105
106106
107107 func keyPoolShare (pool,epoch) = {
108108 let $t032473287 = pool
109109 let amountAssetId = $t032473287._1
110110 let priceAssetId = $t032473287._2
111111 makeString(["%s%s%s%d", "poolShare", amountAssetId, priceAssetId, toString(epoch)], separator)
112112 }
113113
114114
115115 func keyTotalVotes (epoch) = makeString(["%s%d", "totalVotes", toString(epoch)], separator)
116116
117117
118118 func keyStakedByUser (lpAssetIdStr,userAddressStr) = makeString(["%s%s%s", "staked", userAddressStr, lpAssetIdStr], separator)
119119
120120
121121 func wrapErr (msg) = makeString(["voting_emission.ride:", msg], " ")
122122
123123
124124 func throwErr (msg) = throw(wrapErr(msg))
125125
126126
127127 func getValueOrFail (address,key,type) = {
128128 let error = wrapErr(makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
129129 valueOrErrorMessage( match type {
130130 case str: String =>
131131 getString(address, key)
132132 case int: Int =>
133133 getInteger(address, key)
134134 case _ =>
135135 throwErr("invalid entry type")
136136 }, error)
137137 }
138138
139139
140140 func getStrOrFail (address,key) = {
141141 let @ = getValueOrFail(address, key, "")
142142 if ($isInstanceOf(@, "String"))
143143 then @
144144 else throw(($getType(@) + " couldn't be cast to String"))
145145 }
146146
147147
148148 func getIntOrFail (address,key) = {
149149 let @ = getValueOrFail(address, key, 0)
150150 if ($isInstanceOf(@, "Int"))
151151 then @
152152 else throw(($getType(@) + " couldn't be cast to Int"))
153153 }
154154
155155
156156 func poolToString (pool) = ((pool._1 + separator) + pool._2)
157157
158158
159159 func stringToPool (str) = {
160160 let parts = split(str, separator)
161161 if ((size(parts) == 2))
162162 then $Tuple2(parts[0], parts[1])
163163 else throwErr("invalid pool string")
164164 }
165165
166166
167167 let factoryContract = addressFromStringValue(getStrOrFail(this, keyFactoryContract))
168168
169169 let IdxFactoryCfgGwxRewardDapp = 10
170170
171171 func keyFactoryCfg () = "%s__factoryConfig"
172172
173173
174174 func readFactoryCfgOrFail (factory) = split(getStrOrFail(factory, keyFactoryCfg()), separator)
175175
176176
177177 func getGwxRewardAddressOrFail (factoryCfg) = addressFromStringValue(factoryCfg[IdxFactoryCfgGwxRewardDapp])
178178
179179
180180 func parseAssetId (input) = if ((input == wavesString))
181181 then unit
182182 else fromBase58String(input)
183183
184184
185185 func assetIdToString (input) = if ((input == unit))
186186 then wavesString
187187 else toBase58String(value(input))
188188
189189
190190 func getPoolInfo (amountAssetId,priceAssetId) = {
191191 let poolInfoOption = {
192192 let @ = invoke(factoryContract, "poolInfoREADONLY", [amountAssetId, priceAssetId], nil)
193193 if ($isInstanceOf(@, "(Address, ByteVector)"))
194194 then @
195195 else unit
196196 }
197197 poolInfoOption
198198 }
199199
200200
201201 func getLpAssetByPoolAssets (amountAssetId,priceAssetId) = {
202202 func keyMappingsBaseAsset2internalId (baseAssetStr) = ("%s%s%s__mappings__baseAsset2internalId__" + baseAssetStr)
203203
204204 func keyMappingPoolAssetsToPoolContractAddress (internalAmountAssetIdStr,internalPriceAssetIdStr) = (((("%d%d%s%s__" + toString(internalAmountAssetIdStr)) + "__") + toString(internalPriceAssetIdStr)) + "__mappings__poolAssets2PoolContract")
205205
206206 func keyMappingPoolContractToLPAsset (poolContractAddress) = (("%s%s%s__" + poolContractAddress) + "__mappings__poolContract2LpAsset")
207207
208208 let amountAssetInternalId = getIntOrFail(factoryContract, keyMappingsBaseAsset2internalId(amountAssetId))
209209 let priceAssetInternalId = getIntOrFail(factoryContract, keyMappingsBaseAsset2internalId(priceAssetId))
210210 let poolContractAddress = getStrOrFail(factoryContract, keyMappingPoolAssetsToPoolContractAddress(amountAssetInternalId, priceAssetInternalId))
211211 let lpAssetId = getStrOrFail(factoryContract, keyMappingPoolContractToLPAsset(poolContractAddress))
212212 lpAssetId
213213 }
214214
215215
216216 func checkWxEmissionPoolLabel (pool) = {
217217 let $t066476687 = pool
218218 let amountAssetId = $t066476687._1
219219 let priceAssetId = $t066476687._2
220220 let @ = invoke(factoryContract, "checkWxEmissionPoolLabel", [amountAssetId, priceAssetId], nil)
221221 if ($isInstanceOf(@, "Boolean"))
222222 then @
223223 else throw(($getType(@) + " couldn't be cast to Boolean"))
224224 }
225225
226226
227227 func gwxRewardDeposit () = {
228228 let factoryCfg = readFactoryCfgOrFail(factoryContract)
229229 let gwxRewardsContract = getGwxRewardAddressOrFail(factoryCfg)
230230 invoke(gwxRewardsContract, "deposit", nil, nil)
231231 }
232232
233233
234234 let poolsListName = "pools"
235235
236236 func getVotesListName (pool) = {
237237 let $t071047144 = pool
238238 let amountAssetId = $t071047144._1
239239 let priceAssetId = $t071047144._2
240240 makeString(["votes", amountAssetId, priceAssetId], separator)
241241 }
242242
243243
244244 func keyListHead (listName) = {
245245 let meta = if ((listName == poolsListName))
246246 then "%s%s"
247247 else "%s%s%s%s"
248248 makeString([meta, listName, "head"], separator)
249249 }
250250
251251
252252 func keyListSize (listName) = {
253253 let meta = if ((listName == poolsListName))
254254 then "%s%s"
255255 else "%s%s%s%s"
256256 makeString([meta, listName, "size"], separator)
257257 }
258258
259259
260260 func keyListPrev (listName,id) = {
261261 let meta = if ((listName == poolsListName))
262262 then "%s%s%s%s"
263263 else "%s%s%s%s%s"
264264 makeString([meta, listName, id, "prev"], separator)
265265 }
266266
267267
268268 func keyListNext (listName,id) = {
269269 let meta = if ((listName == poolsListName))
270270 then "%s%s%s%s"
271271 else "%s%s%s%s%s"
272272 makeString([meta, listName, id, "next"], separator)
273273 }
274274
275275
276276 func containsNode (listName,id) = {
277277 let headOrUnit = getString(this, keyListHead(listName))
278278 let prevOrUnit = getString(this, keyListPrev(listName, id))
279279 let nextOrUnit = getString(this, keyListNext(listName, id))
280280 if (if ((id == valueOrElse(headOrUnit, "")))
281281 then true
282282 else (prevOrUnit != unit))
283283 then true
284284 else (nextOrUnit != unit)
285285 }
286286
287287
288288 func insertNodeActions (listName,id) = {
289289 let headOrUnit = getString(this, keyListHead(listName))
290290 let listSize = valueOrElse(getInteger(this, keyListSize(listName)), 0)
291291 let checkNode = if (!(containsNode(listName, id)))
292292 then true
293293 else throwErr("Node exists")
294294 if ((checkNode == checkNode))
295295 then (([IntegerEntry(keyListSize(listName), (listSize + 1))] ++ (if ((headOrUnit != unit))
296296 then [StringEntry(keyListNext(listName, id), value(headOrUnit)), StringEntry(keyListPrev(listName, value(headOrUnit)), id)]
297297 else nil)) ++ [StringEntry(keyListHead(listName), id)])
298298 else throw("Strict value is not equal to itself.")
299299 }
300300
301301
302302 func deleteNodeActions (listName,id) = {
303303 let headOrUnit = getString(this, keyListHead(listName))
304304 let listSize = valueOrElse(getInteger(this, keyListSize(listName)), 0)
305305 let prevOrUnit = getString(this, keyListPrev(listName, id))
306306 let nextOrUnit = getString(this, keyListNext(listName, id))
307307 ([IntegerEntry(keyListSize(listName), (listSize - 1))] ++ (if (if ((prevOrUnit != unit))
308308 then (nextOrUnit != unit)
309309 else false)
310310 then [StringEntry(keyListNext(listName, value(prevOrUnit)), value(nextOrUnit)), StringEntry(keyListPrev(listName, value(nextOrUnit)), value(prevOrUnit)), DeleteEntry(keyListPrev(listName, id)), DeleteEntry(keyListNext(listName, id))]
311311 else if ((nextOrUnit != unit))
312312 then [StringEntry(keyListHead(listName), value(nextOrUnit)), DeleteEntry(keyListNext(listName, id)), DeleteEntry(keyListPrev(listName, value(nextOrUnit)))]
313313 else if ((prevOrUnit != unit))
314314 then [DeleteEntry(keyListPrev(listName, id)), DeleteEntry(keyListNext(listName, value(prevOrUnit)))]
315315 else if ((id == valueOrElse(headOrUnit, "")))
316316 then [DeleteEntry(keyListHead(listName))]
317317 else throwErr(((("invalid node: " + listName) + ".") + id))))
318318 }
319319
320320
321321 func keyManagerVaultAddress () = "%s__managerVaultAddress"
322322
323323
324324 func keyManagerPublicKey () = "%s__managerPublicKey"
325325
326326
327327 func getManagerVaultAddressOrThis () = match getString(keyManagerVaultAddress()) {
328328 case s: String =>
329329 addressFromStringValue(s)
330330 case _ =>
331331 this
332332 }
333333
334334
335335 func managerPublicKeyOrUnit () = {
336336 let managerVaultAddress = getManagerVaultAddressOrThis()
337337 match getString(managerVaultAddress, keyManagerPublicKey()) {
338338 case s: String =>
339339 fromBase58String(s)
340340 case _: Unit =>
341341 unit
342342 case _ =>
343343 throw("Match error")
344344 }
345345 }
346346
347347
348348 func isManager (i) = match managerPublicKeyOrUnit() {
349349 case pk: ByteVector =>
350350 (i.callerPublicKey == pk)
351351 case _: Unit =>
352352 (i.caller == this)
353353 case _ =>
354354 throw("Match error")
355355 }
356356
357357
358358 func mustManager (i) = if (isManager(i))
359359 then true
360360 else throw("permission denied")
361361
362362
363363 func mustThis (i) = if ((i.caller == this))
364364 then true
365365 else throw("permission denied")
366366
367367
368368 @Callable(i)
369369 func getUserGwxAmountAtHeight (userAddress,targetHeight) = {
370370 let boostingContractAddress = valueOrErrorMessage(addressFromString(getStrOrFail(this, keyBoostingContract)), wrapErr("invalid boosting contract address"))
371371 $Tuple2(nil, {
372372 let @ = invoke(boostingContractAddress, "getUserGwxAmountAtHeightREADONLY", [userAddress, targetHeight], nil)
373373 if ($isInstanceOf(@, "Int"))
374374 then @
375375 else throw(($getType(@) + " couldn't be cast to Int"))
376376 })
377377 }
378378
379379
380380
381381 @Callable(i)
382382 func constructor (factoryContract,votingEmissionCandidateContract,boostingContract,stakingContract,epochLength) = {
383383 let checks = [mustManager(i), if ((addressFromString(factoryContract) != unit))
384384 then true
385385 else "invalid factory contract address", if ((addressFromString(votingEmissionCandidateContract) != unit))
386386 then true
387387 else "invalid voting emission candidate contract address", if ((addressFromString(boostingContract) != unit))
388388 then true
389389 else "invalid boosting contract address", if ((addressFromString(stakingContract) != unit))
390390 then true
391391 else "invalid staking contract address", if ((epochLength > 0))
392392 then true
393393 else throwErr("invalid epoch length")]
394394 if ((checks == checks))
395395 then $Tuple2([StringEntry(keyFactoryContract, factoryContract), StringEntry(keyVotingEmissionCandidateContract, votingEmissionCandidateContract), StringEntry(keyBoostingContract, boostingContract), StringEntry(keyStakingContract, stakingContract), IntegerEntry(keyEpochLength, epochLength)], unit)
396396 else throw("Strict value is not equal to itself.")
397397 }
398398
399399
400400
401401 @Callable(i)
402402 func create (amountAssetId,priceAssetId) = {
403403 let checks = [if ((toBase58String(i.caller.bytes) == valueOrElse(getString(this, keyVotingEmissionCandidateContract), "")))
404404 then true
405405 else mustManager(i)]
406406 if ((checks == checks))
407407 then {
408408 let pool = $Tuple2(amountAssetId, priceAssetId)
409409 let inListActions = ([BooleanEntry(keyInList(pool), true)] ++ insertNodeActions(poolsListName, poolToString(pool)))
410410 let currentEpochIsNotDefined = (getInteger(this, keyCurrentEpoch) == unit)
411411 let startHeightActions = if (currentEpochIsNotDefined)
412412 then {
413413 let epoch = 0
414414 [IntegerEntry(keyCurrentEpoch, epoch), IntegerEntry(keyStartHeightByEpoch(epoch), height), IntegerEntry(keyStartHeight, height), IntegerEntry(keyCurrentEpochUi, epoch), IntegerEntry(keyStartHeightUi, height)]
415415 }
416416 else nil
417417 $Tuple2((inListActions ++ startHeightActions), unit)
418418 }
419419 else throw("Strict value is not equal to itself.")
420420 }
421421
422422
423423
424424 @Callable(i)
425425 func vote (amountAssetId,priceAssetId,amount) = {
426426 let pool = $Tuple2(amountAssetId, priceAssetId)
427427 let epoch = valueOrElse(getInteger(this, keyCurrentEpoch), 0)
428428 let startHeight = getIntOrFail(this, keyStartHeightByEpoch(epoch))
429429 let epochLength = getIntOrFail(this, keyEpochLength)
430430 let endHeight = (startHeight + epochLength)
431431 let finalizationStageOrUnit = getInteger(this, keyFinalizationStage)
432432 let used = valueOrElse(getInteger(this, keyUsed(i.caller, epoch)), 0)
433433 let vote = valueOrElse(getInteger(this, keyVote(pool, i.caller, epoch)), 0)
434434 let poolResult = valueOrElse(getInteger(this, keyVotingResult(pool, epoch)), 0)
435435 let totalVotes = valueOrElse(getInteger(this, keyTotalVotes(epoch)), 0)
436436 let gwxAmountAtEndTotal = {
437437 let @ = invoke(this, "getUserGwxAmountAtHeight", [toBase58String(i.caller.bytes), endHeight], nil)
438438 if ($isInstanceOf(@, "Int"))
439439 then @
440440 else throw(($getType(@) + " couldn't be cast to Int"))
441441 }
442442 let available = (gwxAmountAtEndTotal - used)
443443 let newVote = (vote + amount)
444444 let wxEmission = checkWxEmissionPoolLabel(pool)
445445 let checks = [if ((getBoolean(keyInList(pool)) != unit))
446446 then true
447447 else throwErr("invalid assets"), if ((endHeight > height))
448448 then true
449449 else throwErr("invalid height"), if ((finalizationStageOrUnit == unit))
450450 then true
451451 else throwErr("finalization in progress"), if ((gwxAmountAtEndTotal > 0))
452452 then true
453453 else throwErr("you do not have gWX"), if (if ((amount > 0))
454454 then (available >= amount)
455455 else false)
456456 then true
457457 else throwErr("invalid amount"), if (wxEmission)
458458 then true
459459 else throwErr("pool hasn't WX_EMISSION label")]
460460 if ((checks == checks))
461461 then {
462462 let votesListName = getVotesListName(pool)
463463 let userAddressStr = toString(i.caller)
464464 let votesListActions = if (containsNode(votesListName, userAddressStr))
465465 then nil
466466 else insertNodeActions(votesListName, userAddressStr)
467467 $Tuple2(([IntegerEntry(keyUsed(i.caller, epoch), (used + amount)), IntegerEntry(keyVote(pool, i.caller, epoch), newVote), IntegerEntry(keyVotingResult(pool, epoch), (poolResult + amount)), IntegerEntry(keyTotalVotes(epoch), (totalVotes + amount))] ++ votesListActions), unit)
468468 }
469469 else throw("Strict value is not equal to itself.")
470470 }
471471
472472
473473
474474 @Callable(i)
475475 func cancelVote (amountAssetId,priceAssetId) = {
476476 let pool = $Tuple2(amountAssetId, priceAssetId)
477477 let epoch = valueOrElse(getInteger(this, keyCurrentEpoch), 0)
478478 let startHeight = getIntOrFail(this, keyStartHeightByEpoch(epoch))
479479 let epochLength = getIntOrFail(this, keyEpochLength)
480480 let endHeight = (startHeight + epochLength)
481481 let finalizationStageOrUnit = getInteger(this, keyFinalizationStage)
482482 let used = valueOrElse(getInteger(this, keyUsed(i.caller, epoch)), 0)
483483 let vote = valueOrElse(getInteger(this, keyVote(pool, i.caller, epoch)), 0)
484484 let poolResult = valueOrElse(getInteger(this, keyVotingResult(pool, epoch)), 0)
485485 let totalVotes = valueOrElse(getInteger(this, keyTotalVotes(epoch)), 0)
486486 let checks = [if ((getBoolean(keyInList(pool)) != unit))
487487 then true
488488 else throwErr("invalid assets"), if ((endHeight > height))
489489 then true
490490 else throwErr("invalid height"), if ((finalizationStageOrUnit == unit))
491491 then true
492492 else throwErr("finalization in progress"), if ((vote > 0))
493493 then true
494494 else throwErr("no vote")]
495495 if ((checks == checks))
496496 then {
497497 let votesListName = getVotesListName(pool)
498498 let userAddressStr = toString(i.caller)
499499 $Tuple2(([IntegerEntry(keyUsed(i.caller, epoch), max([(used - vote), 0])), DeleteEntry(keyVote(pool, i.caller, epoch)), IntegerEntry(keyVotingResult(pool, epoch), (poolResult - vote)), IntegerEntry(keyTotalVotes(epoch), (totalVotes - vote))] ++ deleteNodeActions(votesListName, userAddressStr)), unit)
500500 }
501501 else throw("Strict value is not equal to itself.")
502502 }
503503
504504
505505
506506 @Callable(i)
507507 func setEpochLength (newEpochLength) = {
508508 let checks = [mustManager(i), if ((newEpochLength > 0))
509509 then true
510510 else throwErr("invalid epoch length")]
511511 if ((checks == checks))
512512 then $Tuple2([IntegerEntry(keyEpochLengthNew, newEpochLength)], unit)
513513 else throw("Strict value is not equal to itself.")
514514 }
515515
516516
517517
518518 @Callable(i)
519519 func setMaxDepth (newMaxDepth) = {
520520 let checks = [mustManager(i), if ((newMaxDepth > 0))
521521 then true
522522 else throwErr("invalid max depth")]
523523 if ((checks == checks))
524524 then $Tuple2([IntegerEntry(keyMaxDepth, newMaxDepth)], unit)
525525 else throw("Strict value is not equal to itself.")
526526 }
527527
528528
529529
530530 @Callable(i)
531531 func processPoolBalanceINTERNAL (poolStr) = {
532532 let checkCaller = mustThis(i)
533533 if ((checkCaller == checkCaller))
534534 then {
535535 let epoch = getIntOrFail(this, keyCurrentEpoch)
536536 let epochPrevious = (epoch - 1)
537537 let pool = stringToPool(poolStr)
538538 let $t01736817408 = pool
539539 let amountAssetId = $t01736817408._1
540540 let priceAssetId = $t01736817408._2
541541 let lpAssetId = getLpAssetByPoolAssets(amountAssetId, priceAssetId)
542542 let balanceIsOkCurrent = {
543543 let @ = invoke(factoryContract, "checkBalance", [lpAssetId], nil)
544544 if ($isInstanceOf(@, "Boolean"))
545545 then @
546546 else throw(($getType(@) + " couldn't be cast to Boolean"))
547547 }
548548 let balanceIsOkPrevious = !(valueOrElse(getBoolean(this, keyInsufficientBalances(pool, (epochPrevious - 1))), false))
549549 let actions = if (!(balanceIsOkCurrent))
550550 then if (!(balanceIsOkPrevious))
551551 then {
552552 let deleteWxEmissionInv = invoke(factoryContract, "deleteWxEmissionPoolLabel", [amountAssetId, priceAssetId], nil)
553553 if ((deleteWxEmissionInv == deleteWxEmissionInv))
554554 then {
555555 let modifyWeightInv = invoke(factoryContract, "modifyWeight", [lpAssetId, 0], nil)
556556 if ((modifyWeightInv == modifyWeightInv))
557557 then {
558558 let poolAddress = valueOrErrorMessage(getPoolInfo(amountAssetId, priceAssetId), wrapErr("invalid assets"))._1
559559 let newStatus = 3
560560 let setPoolStatusInv = invoke(factoryContract, "managePool", [toString(poolAddress), newStatus], nil)
561561 if ((setPoolStatusInv == setPoolStatusInv))
562562 then {
563563 let listActions = ([DeleteEntry(keyInList(pool))] ++ deleteNodeActions(poolsListName, poolToString(pool)))
564564 ([IntegerEntry(keyPoolShare(pool, epochPrevious), 0)] ++ listActions)
565565 }
566566 else throw("Strict value is not equal to itself.")
567567 }
568568 else throw("Strict value is not equal to itself.")
569569 }
570570 else throw("Strict value is not equal to itself.")
571571 }
572572 else [BooleanEntry(keyInsufficientBalances(pool, epochPrevious), true)]
573573 else nil
574574 $Tuple2(actions, unit)
575575 }
576576 else throw("Strict value is not equal to itself.")
577577 }
578578
579579
580580
581581 @Callable(i)
582582 func processVoteINTERNAL (poolStr,userAddressStr) = {
583583 let checkCaller = mustThis(i)
584584 if ((checkCaller == checkCaller))
585585 then {
586586 let userAddress = valueOrErrorMessage(addressFromString(userAddressStr), wrapErr(("processVoteINTERNAL: invalid user address " + userAddressStr)))
587587 let epoch = getIntOrFail(this, keyCurrentEpoch)
588588 let epochPrevious = (epoch - 1)
589589 let epochLength = getIntOrFail(this, keyEpochLength)
590590 let startHeight = getIntOrFail(this, keyStartHeightByEpoch(epoch))
591591 let endHeight = (startHeight + epochLength)
592592 let startHeightPrevious = getIntOrFail(this, keyStartHeightByEpoch(epochPrevious))
593593 let epochLengthPrevious = getIntOrFail(this, keyEpochLengthByEpoch(epochPrevious))
594594 let endHeightPrevious = (startHeightPrevious + epochLengthPrevious)
595595 let checkTargetEpoch = if ((epochPrevious >= 0))
596596 then true
597597 else throwErr("processVoteINTERNAL: invalid previous epoch")
598598 if ((checkTargetEpoch == checkTargetEpoch))
599599 then {
600600 let pool = stringToPool(poolStr)
601601 let $t01976119801 = pool
602602 let amountAssetId = $t01976119801._1
603603 let priceAssetId = $t01976119801._2
604604 let gwxAmountAtEndTotal = {
605605 let @ = invoke(this, "getUserGwxAmountAtHeight", [userAddressStr, endHeight], nil)
606606 if ($isInstanceOf(@, "Int"))
607607 then @
608608 else throw(($getType(@) + " couldn't be cast to Int"))
609609 }
610610 let gwxAmountAtEndTotalPrevious = {
611611 let @ = invoke(this, "getUserGwxAmountAtHeight", [userAddressStr, endHeightPrevious], nil)
612612 if ($isInstanceOf(@, "Int"))
613613 then @
614614 else throw(($getType(@) + " couldn't be cast to Int"))
615615 }
616616 let totalVotes = valueOrElse(getInteger(keyTotalVotes(epoch)), 0)
617617 let votingResult = valueOrElse(getInteger(keyVotingResult(pool, epoch)), 0)
618- let votePrevious = valueOrErrorMessage(getInteger(keyVote(pool, userAddress, epochPrevious)), wrapErr((((("processVoteINTERNAL " + poolStr) + " ") + userAddressStr) + ": no previous vote")))
618+ let votePreviousOption = getInteger(keyVote(pool, userAddress, epochPrevious))
619+ let votePrevious = valueOrErrorMessage(votePreviousOption, wrapErr((((("processVoteINTERNAL " + poolStr) + " ") + userAddressStr) + ": no previous vote")))
619620 let used = valueOrElse(getInteger(this, keyUsed(userAddress, epoch)), 0)
620621 let lpAssetIdStr = getLpAssetByPoolAssets(amountAssetId, priceAssetId)
621622 let votingResultStakedPrevious = valueOrElse(getInteger(keyVotingResultStaked(lpAssetIdStr, epochPrevious)), 0)
622623 let stakingContract = addressFromStringValue(getStrOrFail(this, keyStakingContract))
623624 let stakedByUser = valueOrElse(getInteger(stakingContract, keyStakedByUser(lpAssetIdStr, userAddressStr)), 0)
624- let votingResultStakedActions = if ((stakedByUser == 0))
625+ let votingResultStakedActions = if (if ((stakedByUser == 0))
626+ then true
627+ else (votePreviousOption == unit))
625628 then nil
626629 else [IntegerEntry(keyVotingResultStaked(lpAssetIdStr, epochPrevious), (votingResultStakedPrevious + votePrevious))]
627630 let lpAssetId = getLpAssetByPoolAssets(amountAssetId, priceAssetId)
628631 let newVote = if ((gwxAmountAtEndTotalPrevious > 0))
629632 then fraction(votePrevious, gwxAmountAtEndTotal, gwxAmountAtEndTotalPrevious)
630633 else 0
631- let actions = if ((newVote > 0))
632- then [IntegerEntry(keyVote(pool, userAddress, epoch), newVote), IntegerEntry(keyTotalVotes(epoch), (totalVotes + newVote)), IntegerEntry(keyVotingResult(pool, epoch), (votingResult + newVote)), IntegerEntry(keyUsed(userAddress, epoch), (used + newVote))]
633- else deleteNodeActions(getVotesListName(pool), userAddressStr)
634+ let actions = if (if ((votePreviousOption == unit))
635+ then true
636+ else (0 >= newVote))
637+ then deleteNodeActions(getVotesListName(pool), userAddressStr)
638+ else [IntegerEntry(keyVote(pool, userAddress, epoch), newVote), IntegerEntry(keyTotalVotes(epoch), (totalVotes + newVote)), IntegerEntry(keyVotingResult(pool, epoch), (votingResult + newVote)), IntegerEntry(keyUsed(userAddress, epoch), (used + newVote))]
634639 $Tuple2((actions ++ votingResultStakedActions), unit)
635640 }
636641 else throw("Strict value is not equal to itself.")
637642 }
638643 else throw("Strict value is not equal to itself.")
639644 }
640645
641646
642647
643648 @Callable(i)
644649 func processPoolINTERNAL (poolStr,force) = {
645650 let checkCaller = mustThis(i)
646651 if ((checkCaller == checkCaller))
647652 then {
648653 let targetEpoch = {
649654 let currentEpoch = getIntOrFail(this, keyCurrentEpoch)
650655 if (force)
651656 then currentEpoch
652657 else (currentEpoch - 1)
653658 }
654659 let checkTargetEpoch = if ((targetEpoch >= 0))
655660 then true
656661 else throwErr("processPoolINTERNAL: invalid target epoch")
657662 if ((checkTargetEpoch == checkTargetEpoch))
658663 then {
659664 let pool = stringToPool(poolStr)
660- let $t02216422204 = pool
661- let amountAssetId = $t02216422204._1
662- let priceAssetId = $t02216422204._2
665+ let $t02227122311 = pool
666+ let amountAssetId = $t02227122311._1
667+ let priceAssetId = $t02227122311._2
663668 let stakingContract = addressFromStringValue(getStrOrFail(this, keyStakingContract))
664669 let lpAssetId = getLpAssetByPoolAssets(amountAssetId, priceAssetId)
665670 let r = {
666671 let @ = invoke(stakingContract, "usersListTraversal", [lpAssetId], nil)
667672 if ($isInstanceOf(@, "Boolean"))
668673 then @
669674 else throw(($getType(@) + " couldn't be cast to Boolean"))
670675 }
671676 if ((r == r))
672677 then if (r)
673678 then $Tuple2(nil, true)
674679 else {
675680 let assetsStoreContract = addressFromStringValue(valueOrErrorMessage(getString(factoryContract, keyAssetsStoreContract), "invalid assets store contract"))
676681 let totalVotes = valueOrElse(getInteger(this, keyTotalVotes(targetEpoch)), 0)
677682 let votingResult = valueOrElse(getInteger(this, keyVotingResult(pool, targetEpoch)), 0)
678683 let share = if ((totalVotes == 0))
679684 then 0
680685 else fraction(votingResult, poolWeightMult, totalVotes)
681686 let modifyWeightInv = invoke(factoryContract, "modifyWeight", [lpAssetId, share], nil)
682687 if ((modifyWeightInv == modifyWeightInv))
683688 then $Tuple2([IntegerEntry(keyPoolShare(pool, targetEpoch), share)], false)
684689 else throw("Strict value is not equal to itself.")
685690 }
686691 else throw("Strict value is not equal to itself.")
687692 }
688693 else throw("Strict value is not equal to itself.")
689694 }
690695 else throw("Strict value is not equal to itself.")
691696 }
692697
693698
694699
695700 @Callable(i)
696701 func finalizeHelper () = {
697702 let force = valueOrElse(getBoolean(keyFinalizationShouldBeForced), false)
698703 let epoch = valueOrElse(getInteger(this, keyCurrentEpoch), 0)
699704 let previousEpoch = (epoch - 1)
700705 let startHeight = getIntOrFail(this, keyStartHeightByEpoch(epoch))
701706 let epochLength = getIntOrFail(this, keyEpochLength)
702707 let endHeight = (startHeight + epochLength)
703708 let finalizationStageOrUnit = getInteger(this, keyFinalizationStage)
704709 if (if (if ((height >= endHeight))
705710 then (finalizationStageOrUnit == unit)
706711 else false)
707712 then !(force)
708713 else false)
709714 then {
710715 let newEpoch = (epoch + 1)
711716 let newEpochLengthOption = getInteger(this, keyEpochLengthNew)
712717 let newEpochLengthActions = match newEpochLengthOption {
713718 case newEpochLength: Int =>
714719 [IntegerEntry(keyEpochLength, newEpochLength), DeleteEntry(keyEpochLengthNew)]
715720 case _: Unit =>
716721 nil
717722 case _ =>
718723 throw("Match error")
719724 }
720725 $Tuple2(([IntegerEntry(keyStartHeightByEpoch(newEpoch), height), IntegerEntry(keyStartHeight, height), IntegerEntry(keyCurrentEpoch, newEpoch), IntegerEntry(keyFinalizationStage, finalizationStageBalances), IntegerEntry(keyEpochLengthByEpoch(epoch), epochLength)] ++ newEpochLengthActions), true)
721726 }
722727 else if (if (force)
723728 then (finalizationStageOrUnit == unit)
724729 else false)
725730 then $Tuple2([IntegerEntry(keyFinalizationStage, finalizationStageShares)], true)
726731 else if ((finalizationStageOrUnit == unit))
727732 then $Tuple2(nil, false)
728733 else if ((finalizationStageOrUnit == finalizationStageBalances))
729734 then {
730735 let poolOrUnit = getString(keyNextPool)
731736 match poolOrUnit {
732737 case _: Unit =>
733738 match getString(keyListHead(poolsListName)) {
734739 case _: Unit =>
735740 $Tuple2([IntegerEntry(keyFinalizationStage, finalizationStageTotal), DeleteEntry(keyNextPool)], true)
736741 case nextPoolStr: String =>
737742 $Tuple2([StringEntry(keyNextPool, nextPoolStr)], true)
738743 case _ =>
739744 throw("Match error")
740745 }
741746 case poolStr: String =>
742747 let nextPoolOrUnit = getString(keyListNext(poolsListName, poolStr))
743748 if ((nextPoolOrUnit == nextPoolOrUnit))
744749 then {
745750 let r = invoke(this, "processPoolBalanceINTERNAL", [poolStr], nil)
746751 if ((r == r))
747752 then match nextPoolOrUnit {
748753 case _: Unit =>
749754 $Tuple2([IntegerEntry(keyFinalizationStage, finalizationStageTotal), DeleteEntry(keyNextPool)], true)
750755 case nextPoolStr: String =>
751756 $Tuple2([StringEntry(keyNextPool, nextPoolStr)], true)
752757 case _ =>
753758 throw("Match error")
754759 }
755760 else throw("Strict value is not equal to itself.")
756761 }
757762 else throw("Strict value is not equal to itself.")
758763 case _ =>
759764 throw("Match error")
760765 }
761766 }
762767 else if ((finalizationStageOrUnit == finalizationStageTotal))
763768 then {
764769 let poolOrUnit = getString(keyNextPool)
765770 let userOrUnit = getString(keyNextUser)
766771 match poolOrUnit {
767772 case _: Unit =>
768773 match getString(keyListHead(poolsListName)) {
769774 case _: Unit =>
770775 $Tuple2([IntegerEntry(keyFinalizationStage, finalizationStageShares), DeleteEntry(keyNextPool), DeleteEntry(keyNextUser)], true)
771776 case poolsHeadStr: String =>
772777 $Tuple2([StringEntry(keyNextPool, poolsHeadStr)], true)
773778 case _ =>
774779 throw("Match error")
775780 }
776781 case poolStr: String =>
777782 let pool = stringToPool(poolStr)
778783 let nextUserOrUnit = match userOrUnit {
779784 case _: Unit =>
780785 getString(keyListHead(getVotesListName(pool)))
781786 case user: String =>
782787 let next = getString(keyListNext(getVotesListName(pool), user))
783788 if ((next == next))
784789 then {
785790 let processVoteInv = invoke(this, "processVoteINTERNAL", [poolStr, user], nil)
786791 if ((processVoteInv == processVoteInv))
787792 then next
788793 else throw("Strict value is not equal to itself.")
789794 }
790795 else throw("Strict value is not equal to itself.")
791796 case _ =>
792797 throw("Match error")
793798 }
794799 match nextUserOrUnit {
795800 case _: Unit =>
796801 let nextPoolOrUnit = getString(keyListNext(poolsListName, poolStr))
797802 match nextPoolOrUnit {
798803 case _: Unit =>
799804 $Tuple2([IntegerEntry(keyFinalizationStage, finalizationStageShares), DeleteEntry(keyNextPool), DeleteEntry(keyNextUser)], true)
800805 case s: String =>
801806 $Tuple2([StringEntry(keyNextPool, s), DeleteEntry(keyNextUser)], true)
802807 case _ =>
803808 throw("Match error")
804809 }
805810 case nextUser: String =>
806811 $Tuple2([StringEntry(keyNextUser, nextUser)], true)
807812 case _ =>
808813 throw("Match error")
809814 }
810815 case _ =>
811816 throw("Match error")
812817 }
813818 }
814819 else if ((finalizationStageOrUnit == finalizationStageShares))
815820 then {
816821 let poolOrUnit = getString(keyNextPool)
817822 match poolOrUnit {
818823 case _: Unit =>
819824 match getString(keyListHead(poolsListName)) {
820825 case _: Unit =>
821826 let actions = if (force)
822827 then [DeleteEntry(keyFinalizationStage), DeleteEntry(keyFinalizationShouldBeForced)]
823828 else [DeleteEntry(keyFinalizationStage), BooleanEntry(keyFinalized(previousEpoch), true), IntegerEntry(keyCurrentEpochUi, epoch), IntegerEntry(keyStartHeightUi, startHeight)]
824829 let gwxRewardDepositInv = gwxRewardDeposit()
825830 if ((gwxRewardDepositInv == gwxRewardDepositInv))
826831 then $Tuple2(actions, true)
827832 else throw("Strict value is not equal to itself.")
828833 case nextPoolStr: String =>
829834 $Tuple2([StringEntry(keyNextPool, nextPoolStr)], true)
830835 case _ =>
831836 throw("Match error")
832837 }
833838 case poolStr: String =>
834839 let nextPoolOrUnit = getString(keyListNext(poolsListName, poolStr))
835840 if ((nextPoolOrUnit == nextPoolOrUnit))
836841 then {
837842 let r = {
838843 let @ = invoke(this, "processPoolINTERNAL", [poolStr, force], nil)
839844 if ($isInstanceOf(@, "Boolean"))
840845 then @
841846 else throw(($getType(@) + " couldn't be cast to Boolean"))
842847 }
843848 if ((r == r))
844849 then if (r)
845850 then $Tuple2(nil, true)
846851 else match nextPoolOrUnit {
847852 case _: Unit =>
848853 let actions = if (force)
849854 then [DeleteEntry(keyFinalizationStage), DeleteEntry(keyFinalizationShouldBeForced), DeleteEntry(keyNextPool)]
850855 else [DeleteEntry(keyFinalizationStage), BooleanEntry(keyFinalized(previousEpoch), true), IntegerEntry(keyCurrentEpochUi, epoch), IntegerEntry(keyStartHeightUi, startHeight), DeleteEntry(keyNextPool)]
851856 let gwxRewardDepositInv = gwxRewardDeposit()
852857 if ((gwxRewardDepositInv == gwxRewardDepositInv))
853858 then $Tuple2(actions, true)
854859 else throw("Strict value is not equal to itself.")
855860 case nextPoolStr: String =>
856861 $Tuple2([StringEntry(keyNextPool, nextPoolStr)], true)
857862 case _ =>
858863 throw("Match error")
859864 }
860865 else throw("Strict value is not equal to itself.")
861866 }
862867 else throw("Strict value is not equal to itself.")
863868 case _ =>
864869 throw("Match error")
865870 }
866871 }
867872 else throwErr("finalization is broken")
868873 }
869874
870875
871876
872877 @Callable(i)
873878 func finalizeWrapper (counter) = {
874879 let votingEmissionRateContract = addressFromStringValue(getStringValue(this, keyVotingEmissionRateContract))
875880 let result = {
876881 let @ = invoke(this, "finalizeHelper", nil, nil)
877882 if ($isInstanceOf(@, "Boolean"))
878883 then @
879884 else throw(($getType(@) + " couldn't be cast to Boolean"))
880885 }
881886 if ((result == result))
882887 then if (!(result))
883888 then if ((counter == 0))
884889 then throwErr("Current voting is not over yet")
885890 else {
886891 let inv = invoke(votingEmissionRateContract, "finalize", nil, nil)
887892 if ((inv == inv))
888893 then $Tuple2(nil, unit)
889894 else throw("Strict value is not equal to itself.")
890895 }
891896 else {
892897 let maxDepth = valueOrElse(getInteger(this, keyMaxDepth), maxDepthDefault)
893898 if ((maxDepth > counter))
894899 then {
895900 let inv = invoke(this, "finalizeWrapper", [(counter + 1)], nil)
896901 if ((inv == inv))
897902 then $Tuple2(nil, unit)
898903 else throw("Strict value is not equal to itself.")
899904 }
900905 else $Tuple2(nil, unit)
901906 }
902907 else throw("Strict value is not equal to itself.")
903908 }
904909
905910
906911
907912 @Callable(i)
908913 func finalize () = {
909914 let inv = invoke(this, "finalizeWrapper", [0], nil)
910915 if ((inv == inv))
911916 then $Tuple2(nil, unit)
912917 else throw("Strict value is not equal to itself.")
913918 }
914919
915920
916921
917922 @Callable(i)
918923 func containsNodeREADONLY (listName,id) = $Tuple2(nil, containsNode(listName, id))
919924
920925
921926
922927 @Callable(i)
923928 func insertNode (listName,id) = {
924929 let checkCaller = mustManager(i)
925930 if ((checkCaller == checkCaller))
926931 then $Tuple2(insertNodeActions(listName, id), unit)
927932 else throw("Strict value is not equal to itself.")
928933 }
929934
930935
931936
932937 @Callable(i)
933938 func deleteNode (listName,id) = {
934939 let checkCaller = mustManager(i)
935940 if ((checkCaller == checkCaller))
936941 then $Tuple2(deleteNodeActions(listName, id), unit)
937942 else throw("Strict value is not equal to itself.")
938943 }
939944
940945
941946
942947 @Callable(i)
943948 func isFinalizationInProgress () = {
944949 let finalizationStageOrUnit = getInteger(this, keyFinalizationStage)
945950 let finalizationInProgress = (finalizationStageOrUnit != unit)
946951 $Tuple2(nil, finalizationInProgress)
947952 }
948953
949954
950955
951956 @Callable(i)
952957 func deletePool (amountAssetId,priceAssetId) = {
953958 let checkCaller = if (if ((i.caller == factoryContract))
954959 then true
955960 else mustManager(i))
956961 then true
957962 else throwErr("Permission denied")
958963 if ((checkCaller == checkCaller))
959964 then {
960965 let listName = "pools"
961966 let pool = $Tuple2(amountAssetId, priceAssetId)
962967 let id = makeString([amountAssetId, priceAssetId], separator)
963968 let actions = if (containsNode(listName, id))
964969 then deleteNodeActions(listName, id)
965970 else nil
966971 ([DeleteEntry(keyInList(pool))] ++ actions)
967972 }
968973 else throw("Strict value is not equal to itself.")
969974 }
970975
971976
972977
973978 @Callable(i)
974979 func resume (amountAssetId,priceAssetId,slippageToleranceOrMinOutAmount) = {
975- let $t03308533215 = valueOrErrorMessage(getPoolInfo(amountAssetId, priceAssetId), wrapErr("invalid assets"))
976- let poolAddress = $t03308533215._1
977- let lpAssetId = $t03308533215._2
980+ let finalizationStageOrUnit = getInteger(this, keyFinalizationStage)
981+ let $t03326333393 = valueOrErrorMessage(getPoolInfo(amountAssetId, priceAssetId), wrapErr("invalid assets"))
982+ let poolAddress = $t03326333393._1
983+ let lpAssetId = $t03326333393._2
978984 let feePayment = i.payments[0]
979985 let assetsStoreContract = addressFromStringValue(getStringValue(this, keyAssetsStoreContract))
980986 let kBoostingConfig = "%s__config"
981987 let idxCfgAssetId = 1
982988 let boostingContract = addressFromStringValue(getStrOrFail(this, keyBoostingContract))
983989 let wxAssetId = fromBase58String(split(getStringValue(boostingContract, kBoostingConfig), separator)[idxCfgAssetId])
984990 let amountAssetVerified = {
985991 let @ = invoke(assetsStoreContract, "isVerifiedREADONLY", [amountAssetId], nil)
986992 if ($isInstanceOf(@, "Boolean"))
987993 then @
988994 else throw(($getType(@) + " couldn't be cast to Boolean"))
989995 }
990996 let priceAssetVerified = {
991997 let @ = invoke(assetsStoreContract, "isVerifiedREADONLY", [priceAssetId], nil)
992998 if ($isInstanceOf(@, "Boolean"))
993999 then @
9941000 else throw(($getType(@) + " couldn't be cast to Boolean"))
9951001 }
9961002 let resumptionFee = valueOrErrorMessage(getInteger(this, keyResumptionFee), "invalid resumption fee")
997- let checks = [if ((feePayment.assetId == wxAssetId))
1003+ let checks = [if ((finalizationStageOrUnit == unit))
1004+ then true
1005+ else throwErr("finalization is in progress"), if ((feePayment.assetId == wxAssetId))
9981006 then true
9991007 else throwErr("invalid fee payment asset id"), if ((feePayment.amount == resumptionFee))
10001008 then true
10011009 else throwErr("invalid fee payment amount"), if (if (amountAssetVerified)
10021010 then priceAssetVerified
10031011 else false)
10041012 then true
10051013 else throwErr("both assets should be verified")]
10061014 if ((checks == checks))
10071015 then {
10081016 let lpAssetBalanceBefore = assetBalance(this, lpAssetId)
10091017 if ((lpAssetBalanceBefore == lpAssetBalanceBefore))
10101018 then {
10111019 let autoStake = false
10121020 let put = if ((size(i.payments) == 1))
10131021 then {
10141022 let balanceIsOk = {
10151023 let @ = invoke(factoryContract, "checkBalance", [assetIdToString(lpAssetId)], nil)
10161024 if ($isInstanceOf(@, "Boolean"))
10171025 then @
10181026 else throw(($getType(@) + " couldn't be cast to Boolean"))
10191027 }
10201028 if (balanceIsOk)
10211029 then true
10221030 else throwErr("assets should be attached")
10231031 }
10241032 else if ((size(i.payments) == 2))
10251033 then {
10261034 let poolScriptHash = valueOrErrorMessage(scriptHash(poolAddress), wrapErr("pool address is not scripted"))
10271035 let allowedScriptHash = fromBase64String(valueOrErrorMessage(getString(factoryContract, keyAllowedLpStableScriptHash()), wrapErr("allowed lp stable script hash is not set")))
10281036 let isStable = (poolScriptHash == allowedScriptHash)
10291037 let functionName = if (isStable)
10301038 then "putOneTknV2"
10311039 else "putOneTkn"
10321040 invoke(poolAddress, functionName, [slippageToleranceOrMinOutAmount, autoStake], [i.payments[1]])
10331041 }
10341042 else if ((size(i.payments) == 3))
10351043 then invoke(poolAddress, "put", [slippageToleranceOrMinOutAmount, autoStake], [i.payments[1], i.payments[2]])
10361044 else throwErr("invalid payments size")
10371045 if ((put == put))
10381046 then {
10391047 let lpAssetBalanceAfter = assetBalance(this, lpAssetId)
10401048 if ((lpAssetBalanceAfter == lpAssetBalanceAfter))
10411049 then {
10421050 let lpAssetBalanceDiff = (lpAssetBalanceAfter - lpAssetBalanceBefore)
10431051 let lpAssetTransferActions = if ((lpAssetBalanceDiff > 0))
10441052 then [ScriptTransfer(i.caller, lpAssetBalanceDiff, lpAssetId)]
10451053 else nil
10461054 let setWxEmissionInv = invoke(factoryContract, "setWxEmissionPoolLabel", [amountAssetId, priceAssetId], nil)
10471055 if ((setWxEmissionInv == setWxEmissionInv))
10481056 then {
10491057 let pool = $Tuple2(amountAssetId, priceAssetId)
10501058 let inListActions = ([BooleanEntry(keyInList(pool), true)] ++ insertNodeActions(poolsListName, poolToString(pool)))
10511059 $Tuple2((inListActions ++ lpAssetTransferActions), unit)
10521060 }
10531061 else throw("Strict value is not equal to itself.")
10541062 }
10551063 else throw("Strict value is not equal to itself.")
10561064 }
10571065 else throw("Strict value is not equal to itself.")
10581066 }
10591067 else throw("Strict value is not equal to itself.")
10601068 }
10611069 else throw("Strict value is not equal to itself.")
10621070 }
10631071
10641072
10651073 @Verifier(tx)
10661074 func verify () = {
10671075 let targetPublicKey = match managerPublicKeyOrUnit() {
10681076 case pk: ByteVector =>
10691077 pk
10701078 case _: Unit =>
10711079 tx.senderPublicKey
10721080 case _ =>
10731081 throw("Match error")
10741082 }
10751083 sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey)
10761084 }
10771085

github/deemru/w8io/786bc32 
149.20 ms