tx · J7m1LbaTwf6FUAVRhpAVcFYH8M2SAYEUrGr5mZp9ssrM

3NBxLzUPfiPbCtHzPFa4praXxPaiACyjPJm:  -0.08000000 Waves

2022.12.07 19:49 [2350176] smart account 3NBxLzUPfiPbCtHzPFa4praXxPaiACyjPJm > SELF 0.00000000 Waves

{ "type": 13, "id": "J7m1LbaTwf6FUAVRhpAVcFYH8M2SAYEUrGr5mZp9ssrM", "fee": 8000000, "feeAssetId": null, "timestamp": 1670431828103, "version": 2, "chainId": 84, "sender": "3NBxLzUPfiPbCtHzPFa4praXxPaiACyjPJm", "senderPublicKey": "3yVAHyimipVe9faj21nV1BmUdP7tHgttiWJM758YzUo6", "proofs": [ "3G8897LdWpANZhbaEErKfGwLB2tsYf3F8Uh9n46eTnWUtPKFQDLk1BkpWHMxRB7L84yJQNLJDuZfE2pDs7pePpUj" ], "script": "base64:BgJtCAISABIAEgMKAQESAwoBARILCgkBAQEBAQEBAQESEAoOAQEBAQEBAQgICAEBAQESAwoBARIFCgMBAQESBgoEAQEBCBIAEgMKAQESABIDCgEIEgASABIDCgEIEgMKAQgSAwoBARIAEgASAwoBCLABAAlrX29yYV9rZXkCCWtfb3JhX2tleQAPa19vcmFfYmxvY2tfa2V5Ag9rX29yYV9ibG9ja19rZXkABWtfb3JhAgVrX29yYQAJa19iYWxhbmNlAglrX2JhbGFuY2UADmtfcG9zaXRpb25TaXplAg5rX3Bvc2l0aW9uU2l6ZQAQa19wb3NpdGlvbk1hcmdpbgIQa19wb3NpdGlvbk1hcmdpbgAWa19wb3NpdGlvbk9wZW5Ob3Rpb25hbAIWa19wb3NpdGlvbk9wZW5Ob3Rpb25hbAAua19wb3NpdGlvbkxhc3RVcGRhdGVkQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgISa19wb3NpdGlvbkZyYWN0aW9uABRrX3Bvc2l0aW9uQ2xvc2VkRGF0ZQIUa19wb3NpdGlvbkNsb3NlZERhdGUAD2tfcG9zaXRpb25Bc3NldAIPa19wb3NpdGlvbkFzc2V0AA1rX2luaXRpYWxpemVkAg1rX2luaXRpYWxpemVkAAhrX3BhdXNlZAIIa19wYXVzZWQABWtfZmVlAgVrX2ZlZQAPa19mdW5kaW5nUGVyaW9kAg9rX2Z1bmRpbmdQZXJpb2QAEWtfaW5pdE1hcmdpblJhdGlvAhFrX2luaXRNYXJnaW5SYXRpbwAYa19tYWludGVuYW5jZU1hcmdpblJhdGlvAgVrX21tcgAVa19saXF1aWRhdGlvbkZlZVJhdGlvAhVrX2xpcXVpZGF0aW9uRmVlUmF0aW8AGWtfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8CFmtfcGFydExpcXVpZGF0aW9uUmF0aW8ADWtfc3ByZWFkTGltaXQCDWtfc3ByZWFkTGltaXQAEGtfbWF4UHJpY2VJbXBhY3QCEGtfbWF4UHJpY2VJbXBhY3QAEGtfbWF4UHJpY2VTcHJlYWQCEGtfbWF4UHJpY2VTcHJlYWQADWtfbGFzdERhdGFTdHICDWtfbGFzdERhdGFTdHIADmtfbGFzdE1pbnV0ZUlkAg5rX2xhc3RNaW51dGVJZAAda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UCHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlABNrX3R3YXBEYXRhTGFzdFByaWNlAhNrX3R3YXBEYXRhTGFzdFByaWNlABprX3R3YXBEYXRhUHJldmlvdXNNaW51dGVJZAIaa190d2FwRGF0YVByZXZpb3VzTWludXRlSWQAJWtfbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24CG2tfbGF0ZXN0TG9uZ1ByZW1pdW1GcmFjdGlvbgAma19sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24CHGtfbGF0ZXN0U2hvcnRQcmVtaXVtRnJhY3Rpb24AEmtfbmV4dEZ1bmRpbmdCbG9jawIea19uZXh0RnVuZGluZ0Jsb2NrTWluVGltZXN0YW1wABFrX2xvbmdGdW5kaW5nUmF0ZQIRa19sb25nRnVuZGluZ1JhdGUAEmtfc2hvcnRGdW5kaW5nUmF0ZQISa19zaG9ydEZ1bmRpbmdSYXRlABNrX3F1b3RlQXNzZXRSZXNlcnZlAghrX3F0QXN0UgASa19iYXNlQXNzZXRSZXNlcnZlAghrX2JzQXN0UgASa19xdW90ZUFzc2V0V2VpZ2h0AghrX3F0QXN0VwARa19iYXNlQXNzZXRXZWlnaHQCCGtfYnNBc3RXABNrX3RvdGFsUG9zaXRpb25TaXplAhNrX3RvdGFsUG9zaXRpb25TaXplABdrX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQIXa190b3RhbExvbmdQb3NpdGlvblNpemUAGGtfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQIYa190b3RhbFNob3J0UG9zaXRpb25TaXplABRrX2N1bXVsYXRpdmVOb3Rpb25hbAIUa19jdW11bGF0aXZlTm90aW9uYWwAFmtfb3BlbkludGVyZXN0Tm90aW9uYWwCFmtfb3BlbkludGVyZXN0Tm90aW9uYWwAFGtfY29vcmRpbmF0b3JBZGRyZXNzAhRrX2Nvb3JkaW5hdG9yQWRkcmVzcwAPa192YXVsdF9hZGRyZXNzAg9rX3ZhdWx0X2FkZHJlc3MAD2tfYWRtaW5fYWRkcmVzcwIPa19hZG1pbl9hZGRyZXNzABJrX2FkbWluX3B1YmxpY19rZXkCEmtfYWRtaW5fcHVibGljX2tleQANa19xdW90ZV9hc3NldAINa19xdW90ZV9hc3NldAAPa19xdW90ZV9zdGFraW5nAg9rX3F1b3RlX3N0YWtpbmcAEWtfc3Rha2luZ19hZGRyZXNzAhFrX3N0YWtpbmdfYWRkcmVzcwAPa19taW5lcl9hZGRyZXNzAg9rX21pbmVyX2FkZHJlc3MAEGtfb3JkZXJzX2FkZHJlc3MCEGtfb3JkZXJzX2FkZHJlc3MAEmtfcmVmZXJyYWxfYWRkcmVzcwISa19yZWZlcnJhbF9hZGRyZXNzABFrX21hbmFnZXJfYWRkcmVzcwIRa19tYW5hZ2VyX2FkZHJlc3MAFGtfY29sbGF0ZXJhbF9hZGRyZXNzAhRrX2NvbGxhdGVyYWxfYWRkcmVzcwASa19leGNoYW5nZV9hZGRyZXNzAhJrX2V4Y2hhbmdlX2FkZHJlc3MAFWtfbmZ0X21hbmFnZXJfYWRkcmVzcwIVa19uZnRfbWFuYWdlcl9hZGRyZXNzACBrX3RyYWRlcl9tYXJrZXRfYXNzZXRfY29sbGF0ZXJhbAIga190cmFkZXJfbWFya2V0X2Fzc2V0X2NvbGxhdGVyYWwBDnRvQ29tcG9zaXRlS2V5AgRfa2V5CF9hZGRyZXNzCQCsAgIJAKwCAgUEX2tleQIBXwUIX2FkZHJlc3MBC2Nvb3JkaW5hdG9yAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIFBHRoaXMFFGtfY29vcmRpbmF0b3JBZGRyZXNzAhNDb29yZGluYXRvciBub3Qgc2V0AQxhZG1pbkFkZHJlc3MACQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFD2tfYWRtaW5fYWRkcmVzcwEOYWRtaW5QdWJsaWNLZXkACQDZBAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFEmtfYWRtaW5fcHVibGljX2tleQEKcXVvdGVBc3NldAAJANkEAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUNa19xdW90ZV9hc3NldAERcXVvdGVBc3NldFN0YWtpbmcACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUPa19xdW90ZV9zdGFraW5nAhtRdW90ZSBhc3NldCBzdGFraW5nIG5vdCBzZXQBDnN0YWtpbmdBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFEWtfc3Rha2luZ19hZGRyZXNzAg9TdGFraW5nIG5vdCBzZXQBDHZhdWx0QWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABQ9rX3ZhdWx0X2FkZHJlc3MCDVZhdWx0IG5vdCBzZXQBDG1pbmVyQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABQ9rX21pbmVyX2FkZHJlc3MCDU1pbmVyIG5vdCBzZXQBDW9yZGVyc0FkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUQa19vcmRlcnNfYWRkcmVzcwIOT3JkZXJzIG5vdCBzZXQBD3JlZmVycmFsQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABRJrX3JlZmVycmFsX2FkZHJlc3MCEFJlZmVycmFsIG5vdCBzZXQBEW5mdE1hbmFnZXJBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFFWtfbmZ0X21hbmFnZXJfYWRkcmVzcwITTkZUIE1hbmFnZXIgbm90IHNldAERY29sbGF0ZXJhbEFkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUUa19jb2xsYXRlcmFsX2FkZHJlc3MCGkNvbGxhdGVyYWwgTWFuYWdlciBub3Qgc2V0AQtzd2FwQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgkBC2Nvb3JkaW5hdG9yAAUSa19leGNoYW5nZV9hZGRyZXNzAg9ObyBzd2FwIGFkZHJlc3MCFEludmFsaWQgc3dhcCBhZGRyZXNzABFrX3doaXRlbGlzdF9hc3NldAIRa193aGl0ZWxpc3RfYXNzZXQBEGlzV2hpdGVsaXN0QXNzZXQBCF9hc3NldElkCQELdmFsdWVPckVsc2UCCQCbCAIJARFjb2xsYXRlcmFsQWRkcmVzcwAJAQ50b0NvbXBvc2l0ZUtleQIFEWtfd2hpdGVsaXN0X2Fzc2V0BQhfYXNzZXRJZAcADWtfdG9rZW5fcGFyYW0CDWtfdG9rZW5fcGFyYW0ADGtfdG9rZW5fdHlwZQIMa190b2tlbl90eXBlABhGRUVfUkVEVUNUSU9OX1RPS0VOX1RZUEUCDWZlZV9yZWR1Y3Rpb24ACERJUl9MT05HAAEACURJUl9TSE9SVAACAA1UV0FQX0lOVEVSVkFMAA8AD09SQUNMRV9JTlRFUlZBTAAPAAdTRUNPTkRTAOgHAA9ERUNJTUFMX05VTUJFUlMABgAMREVDSU1BTF9VTklUCQBoAgABCQBoAgkAaAIJAGgCCQBoAgkAaAIACgAKAAoACgAKAAoAB09ORV9EQVkJAGgCAICjBQUMREVDSU1BTF9VTklUAAhBTExfRkVFUwBkAA9QTkxfT1BUSU9OX1NQT1QAAQARUE5MX09QVElPTl9PUkFDTEUAAgEBcwECX3gJAKwCAgkApAMBBQJfeAIBLAEEZGl2ZAICX3gCX3kJAG4EBQJfeAUMREVDSU1BTF9VTklUBQJfeQUISEFMRkVWRU4BBG11bGQCAl94Al95CQBuBAUCX3gFAl95BQxERUNJTUFMX1VOSVQFCEhBTEZFVkVOAQVzcXJ0ZAECX3gJAQRzcXJ0BAUCX3gFD0RFQ0lNQUxfTlVNQkVSUwUPREVDSU1BTF9OVU1CRVJTBQhIQUxGRVZFTgEEcG93ZAICX3gCX3kJAGwGBQJfeAUPREVDSU1BTF9OVU1CRVJTBQJfeQUPREVDSU1BTF9OVU1CRVJTBQ9ERUNJTUFMX05VTUJFUlMFCEhBTEZFVkVOAQViZGl2ZAICX3gCX3kJAL0CBAUCX3gJALYCAQUMREVDSU1BTF9VTklUBQJfeQUISEFMRkVWRU4BBWJtdWxkAgJfeAJfeQkAvQIEBQJfeAUCX3kJALYCAQUMREVDSU1BTF9VTklUBQhIQUxGRVZFTgEGYnNxcnRkAQJfeAkBCnNxcnRCaWdJbnQEBQJfeAUPREVDSU1BTF9OVU1CRVJTBQ9ERUNJTUFMX05VTUJFUlMFCEhBTEZFVkVOAQVicG93ZAICX3gCX3kJAHYGBQJfeAUPREVDSU1BTF9OVU1CRVJTBQJfeQUPREVDSU1BTF9OVU1CRVJTBQ9ERUNJTUFMX05VTUJFUlMFCEhBTEZFVkVOAQNhYnMBAl94AwkAZgIFAl94AAAFAl94CQEBLQEFAl94AQR2bWF4AgJfeAJfeQMJAGcCBQJfeAUCX3kFAl94BQJfeQEJbGlzdFRvU3RyAQVfbGlzdAoBBV9qb2luAgthY2N1bXVsYXRvcgN2YWwJAKwCAgkArAICBQthY2N1bXVsYXRvcgUDdmFsAgEsBApuZXdMaXN0U3RyCgACJGwFBV9saXN0CgACJHMJAJADAQUCJGwKAAUkYWNjMAIACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQVfam9pbgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMjAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUBAtuZXdMaXN0U3RyVQkAswICBQpuZXdMaXN0U3RyAAEEC25ld0xpc3RTdHJSAwkAAAIJAK8CAgULbmV3TGlzdFN0clUAAQIBLAkAsAICBQtuZXdMaXN0U3RyVQABBQtuZXdMaXN0U3RyVQULbmV3TGlzdFN0clIBCXN0clRvTGlzdAEEX3N0cgkAtQkCBQRfc3RyAgEsAQtwdXNoVG9RdWV1ZQMFX2xpc3QIX21heFNpemUGX3ZhbHVlAwkAZgIJAJADAQUFX2xpc3QFCF9tYXhTaXplCQDNCAIJANEIAgUFX2xpc3QAAAUGX3ZhbHVlCQDNCAIFBV9saXN0BQZfdmFsdWUBA2ludAEBawkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFBHRoaXMFAWsJAKwCAgINbm8gdmFsdWUgZm9yIAUBawEFaW50T3ICAWsDZGVmCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFAWsFA2RlZgEEc3RyQQIIX2FkZHJlc3MEX2tleQQDdmFsCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUIX2FkZHJlc3MFBF9rZXkJAKwCAgIRTm8gdmFsdWUgZm9yIGtleSAFBF9rZXkFA3ZhbAEEaW50QQIIX2FkZHJlc3MEX2tleQQDdmFsCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUIX2FkZHJlc3MFBF9rZXkJAKwCAgIRTm8gdmFsdWUgZm9yIGtleSAFBF9rZXkFA3ZhbAEIY2JhbGFuY2UACQEDaW50AQUJa19iYWxhbmNlAQNmZWUACQEDaW50AQUFa19mZWUBD2luaXRNYXJnaW5SYXRpbwAJAQNpbnQBBRFrX2luaXRNYXJnaW5SYXRpbwEGcXRBc3RSAAkBA2ludAEFE2tfcXVvdGVBc3NldFJlc2VydmUBBmJzQXN0UgAJAQNpbnQBBRJrX2Jhc2VBc3NldFJlc2VydmUBBnF0QXN0VwAJAQVpbnRPcgIFEmtfcXVvdGVBc3NldFdlaWdodAUMREVDSU1BTF9VTklUAQZic0FzdFcACQEFaW50T3ICBRFrX2Jhc2VBc3NldFdlaWdodAUMREVDSU1BTF9VTklUARF0b3RhbFBvc2l0aW9uU2l6ZQAJAQNpbnQBBRNrX3RvdGFsUG9zaXRpb25TaXplARJjdW11bGF0aXZlTm90aW9uYWwACQEDaW50AQUUa19jdW11bGF0aXZlTm90aW9uYWwBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAAkBA2ludAEFFmtfb3BlbkludGVyZXN0Tm90aW9uYWwBGW5leHRGdW5kaW5nQmxvY2tUaW1lc3RhbXAACQEDaW50AQUSa19uZXh0RnVuZGluZ0Jsb2NrARBmdW5kaW5nUGVyaW9kUmF3AAkBA2ludAEFD2tfZnVuZGluZ1BlcmlvZAEUZnVuZGluZ1BlcmlvZERlY2ltYWwACQBoAgkBEGZ1bmRpbmdQZXJpb2RSYXcABQxERUNJTUFMX1VOSVQBFGZ1bmRpbmdQZXJpb2RTZWNvbmRzAAkAaAIJARBmdW5kaW5nUGVyaW9kUmF3AAUHU0VDT05EUwEWbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwAJAQNpbnQBBRhrX21haW50ZW5hbmNlTWFyZ2luUmF0aW8BE2xpcXVpZGF0aW9uRmVlUmF0aW8ACQEDaW50AQUVa19saXF1aWRhdGlvbkZlZVJhdGlvARdwYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwAJAQNpbnQBBRlrX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAQtzcHJlYWRMaW1pdAAJAQNpbnQBBQ1rX3NwcmVhZExpbWl0AQ5tYXhQcmljZUltcGFjdAAJAQNpbnQBBRBrX21heFByaWNlSW1wYWN0AQ5tYXhQcmljZVNwcmVhZAAJAQNpbnQBBRBrX21heFByaWNlU3ByZWFkASNsYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAJAQNpbnQBBSVrX2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uASRsYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24ACQEDaW50AQUma19sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BFnRvdGFsU2hvcnRQb3NpdGlvblNpemUACQEDaW50AQUYa190b3RhbFNob3J0UG9zaXRpb25TaXplARV0b3RhbExvbmdQb3NpdGlvblNpemUACQEDaW50AQUXa190b3RhbExvbmdQb3NpdGlvblNpemUBD2dldEFjdHVhbENhbGxlcgEBaQkBC3ZhbHVlT3JFbHNlAgkAnQgCCQENb3JkZXJzQWRkcmVzcwACCGtfc2VuZGVyCQClCAEIBQFpBmNhbGxlcgEWcmVxdWlyZU1vcmVNYXJnaW5SYXRpbwMMX21hcmdpblJhdGlvEF9iYXNlTWFyZ2luUmF0aW8UX2xhcmdlclRoYW5PckVxdWFsVG8EFHJlbWFpbmluZ01hcmdpblJhdGlvCQBlAgUMX21hcmdpblJhdGlvBRBfYmFzZU1hcmdpblJhdGlvAwMFFF9sYXJnZXJUaGFuT3JFcXVhbFRvCQBmAgAABRRyZW1haW5pbmdNYXJnaW5SYXRpbwcJAAIBAg5JbnZhbGlkIG1hcmdpbgMDCQEBIQEFFF9sYXJnZXJUaGFuT3JFcXVhbFRvCQBnAgUUcmVtYWluaW5nTWFyZ2luUmF0aW8AAAcJAAIBAg5JbnZhbGlkIG1hcmdpbgYBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BDV9wb3NpdGlvblNpemUDCQAAAgUNX3Bvc2l0aW9uU2l6ZQAACQACAQIsU2hvdWxkIG5vdCBiZSBjYWxsZWQgd2l0aCBfcG9zaXRpb25TaXplID09IDADCQBmAgUNX3Bvc2l0aW9uU2l6ZQAACQEjbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24ACQEkbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAELZ2V0UG9zaXRpb24BB190cmFkZXIED3Bvc2l0aW9uU2l6ZU9wdAkAmggCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBQ5rX3Bvc2l0aW9uU2l6ZQUHX3RyYWRlcgQHJG1hdGNoMAUPcG9zaXRpb25TaXplT3B0AwkAAQIFByRtYXRjaDACA0ludAQMcG9zaXRpb25TaXplBQckbWF0Y2gwCQCWCgQFDHBvc2l0aW9uU2l6ZQkBEUBleHRyTmF0aXZlKDEwNTApAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUQa19wb3NpdGlvbk1hcmdpbgUHX3RyYWRlcgkBEUBleHRyTmF0aXZlKDEwNTApAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUWa19wb3NpdGlvbk9wZW5Ob3Rpb25hbAUHX3RyYWRlcgkBEUBleHRyTmF0aXZlKDEwNTApAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUua19wb3NpdGlvbkxhc3RVcGRhdGVkQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUHX3RyYWRlcgkAlgoEAAAAAAAAAAABEGdldFBvc2l0aW9uQXNzZXQBB190cmFkZXIEEHBvc2l0aW9uQXNzZXRPcHQJAJ0IAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUPa19wb3NpdGlvbkFzc2V0BQdfdHJhZGVyBAckbWF0Y2gwBRBwb3NpdGlvbkFzc2V0T3B0AwkAAQIFByRtYXRjaDACBlN0cmluZwQNcG9zaXRpb25Bc3NldAUHJG1hdGNoMAUNcG9zaXRpb25Bc3NldAkA2AQBCQEKcXVvdGVBc3NldAABE3JlcXVpcmVPcGVuUG9zaXRpb24BB190cmFkZXIDCQAAAggJAQtnZXRQb3NpdGlvbgEFB190cmFkZXICXzEAAAkAAgECEE5vIG9wZW4gcG9zaXRpb24GAQtpbml0aWFsaXplZAAJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhpcwUNa19pbml0aWFsaXplZAcBBnBhdXNlZAAJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhpcwUIa19wYXVzZWQHAQ11cGRhdGVSZXNlcnZlAwZfaXNBZGQRX3F1b3RlQXNzZXRBbW91bnQQX2Jhc2VBc3NldEFtb3VudAMFBl9pc0FkZAQHbmV3QmFzZQkAZQIJAQZic0FzdFIABRBfYmFzZUFzc2V0QW1vdW50AwkAZwIAAAUHbmV3QmFzZQkAAgECKlR4IGxlYWQgdG8gYmFzZSBhc3NldCByZXNlcnZlIDw9IDAsIHJldmVydAkAlgoECQBkAgkBBnF0QXN0UgAFEV9xdW90ZUFzc2V0QW1vdW50BQduZXdCYXNlCQBkAgkBEXRvdGFsUG9zaXRpb25TaXplAAUQX2Jhc2VBc3NldEFtb3VudAkAZAIJARJjdW11bGF0aXZlTm90aW9uYWwABRFfcXVvdGVBc3NldEFtb3VudAQIbmV3UXVvdGUJAGUCCQEGcXRBc3RSAAURX3F1b3RlQXNzZXRBbW91bnQDCQBnAgAABQhuZXdRdW90ZQkAAgECKlR4IGxlYWQgdG8gYmFzZSBxdW90ZSByZXNlcnZlIDw9IDAsIHJldmVydAkAlgoEBQhuZXdRdW90ZQkAZAIJAQZic0FzdFIABRBfYmFzZUFzc2V0QW1vdW50CQBlAgkBEXRvdGFsUG9zaXRpb25TaXplAAUQX2Jhc2VBc3NldEFtb3VudAkAZQIJARJjdW11bGF0aXZlTm90aW9uYWwABRFfcXVvdGVBc3NldEFtb3VudAENY2FsY0ludmFyaWFudAQHX3F0QXN0UgdfcXRBc3RXB19ic0FzdFIHX2JzQXN0VwkBBG11bGQCCQEEbXVsZAIFB19xdEFzdFIFB19xdEFzdFcJAQRtdWxkAgUHX2JzQXN0UgUHX2JzQXN0VwEJc3dhcElucHV0AgZfaXNBZGQRX3F1b3RlQXNzZXRBbW91bnQEB19xdEFzdFIJAQZxdEFzdFIABAdfYnNBc3RSCQEGYnNBc3RSAAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcABAFrCQENY2FsY0ludmFyaWFudAQFB19xdEFzdFIFB19xdEFzdFcFB19ic0FzdFIFB19ic0FzdFcEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIDBQZfaXNBZGQJAGQCBQdfcXRBc3RSBRFfcXVvdGVBc3NldEFtb3VudAkAZQIFB19xdEFzdFIFEV9xdW90ZUFzc2V0QW1vdW50BBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIJAQRkaXZkAgUBawkBBG11bGQCBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBQdfcXRBc3RXBBhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMJAQRkaXZkAgkBA2FicwEJAGUCBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFB19ic0FzdFIFB19xdEFzdFcEFWFtb3VudEJhc2VBc3NldEJvdWdodAMFBl9pc0FkZAUYYW1vdW50QmFzZUFzc2V0Qm91Z2h0QWJzCQEBLQEFGGFtb3VudEJhc2VBc3NldEJvdWdodEFicwQNJHQwMTYzMzMxNjUyNgkBDXVwZGF0ZVJlc2VydmUDBQZfaXNBZGQFEV9xdW90ZUFzc2V0QW1vdW50BRhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMEF3F1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIxCAUNJHQwMTYzMzMxNjUyNgJfMQQWYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyMQgFDSR0MDE2MzMzMTY1MjYCXzIEF3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIxCAUNJHQwMTYzMzMxNjUyNgJfMwQYY3VtdWxhdGl2ZU5vdGlvbmFsQWZ0ZXIxCAUNJHQwMTYzMzMxNjUyNgJfNAQLcHJpY2VCZWZvcmUJAQRkaXZkAgkBBG11bGQCBQdfcXRBc3RSBQdfcXRBc3RXCQEEbXVsZAIFB19ic0FzdFIFB19ic0FzdFcEC21hcmtldFByaWNlCQEEZGl2ZAIFEV9xdW90ZUFzc2V0QW1vdW50BRhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMECXByaWNlRGlmZgkBA2FicwEJAGUCBQtwcmljZUJlZm9yZQULbWFya2V0UHJpY2UEC3ByaWNlSW1wYWN0CQBlAgUMREVDSU1BTF9VTklUCQEEZGl2ZAIFC3ByaWNlQmVmb3JlCQBkAgULcHJpY2VCZWZvcmUFCXByaWNlRGlmZgQTbWF4UHJpY2VJbXBhY3RWYWx1ZQkBDm1heFByaWNlSW1wYWN0AAMJAGYCBQtwcmljZUltcGFjdAUTbWF4UHJpY2VJbXBhY3RWYWx1ZQkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgINUHJpY2UgaW1wYWN0IAkApAMBBQtwcmljZUltcGFjdAIUID4gbWF4IHByaWNlIGltcGFjdCAJAKQDAQUTbWF4UHJpY2VJbXBhY3RWYWx1ZQIVIGJlZm9yZSBxdW90ZSBhc3NldDogCQCkAwEFB19xdEFzdFICFCBiZWZvcmUgYmFzZSBhc3NldDogCQCkAwEFB19ic0FzdFICISBxdW90ZSBhc3NldCBhbW91bnQgdG8gZXhjaGFuZ2U6IAkApAMBBRFfcXVvdGVBc3NldEFtb3VudAIPIHByaWNlIGJlZm9yZTogCQCkAwEFC3ByaWNlQmVmb3JlAg4gbWFya2V0UHJpY2U6IAkApAMBBQttYXJrZXRQcmljZQkAlwoFBRVhbW91bnRCYXNlQXNzZXRCb3VnaHQFF3F1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIxBRZiYXNlQXNzZXRSZXNlcnZlQWZ0ZXIxBRd0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyMQUYY3VtdWxhdGl2ZU5vdGlvbmFsQWZ0ZXIxASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BBBfb2xkUG9zaXRpb25TaXplEl9vbGRQb3NpdGlvbk1hcmdpbiVfb2xkUG9zaXRpb25DdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uDF9tYXJnaW5EZWx0YQQOZnVuZGluZ1BheW1lbnQDCQECIT0CBRBfb2xkUG9zaXRpb25TaXplAAAEIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uCQEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEFEF9vbGRQb3NpdGlvblNpemUJAQRtdWxkAgkAZQIFIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBSVfb2xkUG9zaXRpb25DdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBRBfb2xkUG9zaXRpb25TaXplAAAEDHNpZ25lZE1hcmdpbgkAZAIJAGUCBQxfbWFyZ2luRGVsdGEFDmZ1bmRpbmdQYXltZW50BRJfb2xkUG9zaXRpb25NYXJnaW4EDSR0MDE4MDQ1MTgxNzIDCQBmAgAABQxzaWduZWRNYXJnaW4JAJQKAgAACQEDYWJzAQUMc2lnbmVkTWFyZ2luCQCUCgIJAQNhYnMBBQxzaWduZWRNYXJnaW4AAAQMcmVtYWluTWFyZ2luCAUNJHQwMTgwNDUxODE3MgJfMQQHYmFkRGVidAgFDSR0MDE4MDQ1MTgxNzICXzIJAJUKAwUMcmVtYWluTWFyZ2luBQdiYWREZWJ0BQ5mdW5kaW5nUGF5bWVudAEWc3dhcE91dHB1dFdpdGhSZXNlcnZlcwcGX2lzQWRkEF9iYXNlQXNzZXRBbW91bnQUX2NoZWNrTWF4UHJpY2VJbXBhY3QSX3F1b3RlQXNzZXRSZXNlcnZlEV9xdW90ZUFzc2V0V2VpZ2h0EV9iYXNlQXNzZXRSZXNlcnZlEF9iYXNlQXNzZXRXZWlnaHQEC3ByaWNlQmVmb3JlCQEEZGl2ZAIJAQRtdWxkAgUSX3F1b3RlQXNzZXRSZXNlcnZlBRFfcXVvdGVBc3NldFdlaWdodAkBBG11bGQCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldFdlaWdodAMJAAACBRBfYmFzZUFzc2V0QW1vdW50AAAJAAIBAhlJbnZhbGlkIGJhc2UgYXNzZXQgYW1vdW50BAFrCQENY2FsY0ludmFyaWFudAQFEl9xdW90ZUFzc2V0UmVzZXJ2ZQURX3F1b3RlQXNzZXRXZWlnaHQFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0V2VpZ2h0BBhiYXNlQXNzZXRQb29sQW1vdW50QWZ0ZXIDBQZfaXNBZGQJAGQCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldEFtb3VudAkAZQIFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0QW1vdW50BA9xdW90ZUFzc2V0QWZ0ZXIJAQRkaXZkAgUBawkBBG11bGQCBRhiYXNlQXNzZXRQb29sQW1vdW50QWZ0ZXIFEF9iYXNlQXNzZXRXZWlnaHQEDnF1b3RlQXNzZXRTb2xkCQEDYWJzAQkAZQIFD3F1b3RlQXNzZXRBZnRlcgkBBG11bGQCBRJfcXVvdGVBc3NldFJlc2VydmUFEV9xdW90ZUFzc2V0V2VpZ2h0BBNtYXhQcmljZUltcGFjdFZhbHVlCQEObWF4UHJpY2VJbXBhY3QABA0kdDAxOTM0MDE5NTMzCQENdXBkYXRlUmVzZXJ2ZQMJAQEhAQUGX2lzQWRkBQ5xdW90ZUFzc2V0U29sZAUQX2Jhc2VBc3NldEFtb3VudAQXcXVvdGVBc3NldFJlc2VydmVBZnRlcjEIBQ0kdDAxOTM0MDE5NTMzAl8xBBZiYXNlQXNzZXRSZXNlcnZlQWZ0ZXIxCAUNJHQwMTkzNDAxOTUzMwJfMgQXdG90YWxQb3NpdGlvblNpemVBZnRlcjEIBQ0kdDAxOTM0MDE5NTMzAl8zBBhjdW11bGF0aXZlTm90aW9uYWxBZnRlcjEIBQ0kdDAxOTM0MDE5NTMzAl80BAttYXJrZXRQcmljZQkBBGRpdmQCBQ5xdW90ZUFzc2V0U29sZAUQX2Jhc2VBc3NldEFtb3VudAQJcHJpY2VEaWZmCQEDYWJzAQkAZQIFC3ByaWNlQmVmb3JlBQttYXJrZXRQcmljZQQLcHJpY2VJbXBhY3QJAGUCBQxERUNJTUFMX1VOSVQJAQRkaXZkAgULcHJpY2VCZWZvcmUJAGQCBQtwcmljZUJlZm9yZQUJcHJpY2VEaWZmAwMJAGYCBQtwcmljZUltcGFjdAUTbWF4UHJpY2VJbXBhY3RWYWx1ZQUUX2NoZWNrTWF4UHJpY2VJbXBhY3QHCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAg1QcmljZSBpbXBhY3QgCQCkAwEFC3ByaWNlSW1wYWN0AhQgPiBtYXggcHJpY2UgaW1wYWN0IAkApAMBBRNtYXhQcmljZUltcGFjdFZhbHVlAhUgYmVmb3JlIHF1b3RlIGFzc2V0OiAJAKQDAQUSX3F1b3RlQXNzZXRSZXNlcnZlAhQgYmVmb3JlIGJhc2UgYXNzZXQ6IAkApAMBBRFfYmFzZUFzc2V0UmVzZXJ2ZQIgIGJhc2UgYXNzZXQgYW1vdW50IHRvIGV4Y2hhbmdlOiAJAKQDAQUQX2Jhc2VBc3NldEFtb3VudAIPIHByaWNlIGJlZm9yZTogCQCkAwEFC3ByaWNlQmVmb3JlAg8gbWFya2V0IHByaWNlOiAJAKQDAQULbWFya2V0UHJpY2UJAJoKCAUOcXVvdGVBc3NldFNvbGQFF3F1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIxBRZiYXNlQXNzZXRSZXNlcnZlQWZ0ZXIxBRd0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyMQUYY3VtdWxhdGl2ZU5vdGlvbmFsQWZ0ZXIxCQBlAgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQADBQZfaXNBZGQJAQNhYnMBBRBfYmFzZUFzc2V0QW1vdW50AAAJAGUCCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQADCQEBIQEFBl9pc0FkZAkBA2FicwEFEF9iYXNlQXNzZXRBbW91bnQAAAULcHJpY2VJbXBhY3QBCnN3YXBPdXRwdXQDBl9pc0FkZBBfYmFzZUFzc2V0QW1vdW50FF9jaGVja01heFByaWNlSW1wYWN0CQEWc3dhcE91dHB1dFdpdGhSZXNlcnZlcwcFBl9pc0FkZAUQX2Jhc2VBc3NldEFtb3VudAUUX2NoZWNrTWF4UHJpY2VJbXBhY3QJAQZxdEFzdFIACQEGcXRBc3RXAAkBBmJzQXN0UgAJAQZic0FzdFcAARJnZXRPcmFjbGVUd2FwUHJpY2UABAZvcmFjbGUJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCBQR0aGlzBQVrX29yYQIABAhwcmljZUtleQkBEUBleHRyTmF0aXZlKDEwNTMpAgUEdGhpcwUJa19vcmFfa2V5BAhibG9ja0tleQkBEUBleHRyTmF0aXZlKDEwNTMpAgUEdGhpcwUPa19vcmFfYmxvY2tfa2V5BAlsYXN0VmFsdWUJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQZvcmFjbGUFCHByaWNlS2V5CQCsAgIJAKwCAgkArAICAiJDYW4gbm90IGdldCBvcmFjbGUgcHJpY2UuIE9yYWNsZTogCQClCAEFBm9yYWNsZQIGIGtleTogBQhwcmljZUtleQUJbGFzdFZhbHVlARlyZXF1aXJlTm90T3ZlclNwcmVhZExpbWl0AhJfcXVvdGVBc3NldFJlc2VydmURX2Jhc2VBc3NldFJlc2VydmUEC29yYWNsZVByaWNlCQESZ2V0T3JhY2xlVHdhcFByaWNlAAQKcHJpY2VBZnRlcgkBBGRpdmQCBRJfcXVvdGVBc3NldFJlc2VydmUFEV9iYXNlQXNzZXRSZXNlcnZlBAxhdmVyYWdlUHJpY2UJAQRkaXZkAgkAZAIFC29yYWNsZVByaWNlBQpwcmljZUFmdGVyCQBoAgACBQxERUNJTUFMX1VOSVQEDGFic1ByaWNlRGlmZgkBBGRpdmQCCQEDYWJzAQkAZQIFC29yYWNsZVByaWNlBQpwcmljZUFmdGVyBQxhdmVyYWdlUHJpY2UDCQBmAgUMYWJzUHJpY2VEaWZmCQEObWF4UHJpY2VTcHJlYWQACQACAQkArAICCQCsAgIJAKwCAgINUHJpY2Ugc3ByZWFkIAkApAMBBQxhYnNQcmljZURpZmYCFCA+IG1heCBwcmljZSBzcHJlYWQgCQCkAwEJAQ5tYXhQcmljZVNwcmVhZAAGAQxnZXRTcG90UHJpY2UABBJfcXVvdGVBc3NldFJlc2VydmUJAQZxdEFzdFIABBFfYmFzZUFzc2V0UmVzZXJ2ZQkBBmJzQXN0UgAEB19xdEFzdFcJAQZxdEFzdFcABAdfYnNBc3RXCQEGYnNBc3RXAAkBBGRpdmQCCQEEbXVsZAIFEl9xdW90ZUFzc2V0UmVzZXJ2ZQUHX3F0QXN0VwkBBG11bGQCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUHX2JzQXN0VwEWaXNPdmVyRmx1Y3R1YXRpb25MaW1pdAAEC29yYWNsZVByaWNlCQESZ2V0T3JhY2xlVHdhcFByaWNlAAQMY3VycmVudFByaWNlCQEMZ2V0U3BvdFByaWNlAAkAZgIJAQRkaXZkAgkBA2FicwEJAGUCBQtvcmFjbGVQcmljZQUMY3VycmVudFByaWNlBQtvcmFjbGVQcmljZQkBC3NwcmVhZExpbWl0AAEfZ2V0UG9zaXRpb25BZGp1c3RlZE9wZW5Ob3Rpb25hbAYNX3Bvc2l0aW9uU2l6ZQdfb3B0aW9uEl9xdW90ZUFzc2V0UmVzZXJ2ZRFfcXVvdGVBc3NldFdlaWdodBFfYmFzZUFzc2V0UmVzZXJ2ZRBfYmFzZUFzc2V0V2VpZ2h0BA9wb3NpdGlvblNpemVBYnMJAQNhYnMBBQ1fcG9zaXRpb25TaXplBAdpc1Nob3J0CQBmAgAABQ1fcG9zaXRpb25TaXplBBBwb3NpdGlvbk5vdGlvbmFsAwkAAAIFB19vcHRpb24FD1BOTF9PUFRJT05fU1BPVAQNJHQwMjI5MDgyMzEyOAkBFnN3YXBPdXRwdXRXaXRoUmVzZXJ2ZXMHCQEBIQEFB2lzU2hvcnQFD3Bvc2l0aW9uU2l6ZUFicwcFEl9xdW90ZUFzc2V0UmVzZXJ2ZQURX3F1b3RlQXNzZXRXZWlnaHQFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0V2VpZ2h0BBNvdXRQb3NpdGlvbk5vdGlvbmFsCAUNJHQwMjI5MDgyMzEyOAJfMQQCeDEIBQ0kdDAyMjkwODIzMTI4Al8yBAJ4MggFDSR0MDIyOTA4MjMxMjgCXzMEAngzCAUNJHQwMjI5MDgyMzEyOAJfNAUTb3V0UG9zaXRpb25Ob3Rpb25hbAkBBG11bGQCBQ9wb3NpdGlvblNpemVBYnMJARJnZXRPcmFjbGVUd2FwUHJpY2UABRBwb3NpdGlvbk5vdGlvbmFsAStnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubEJ5VmFsdWVzBw1fcG9zaXRpb25TaXplFV9wb3NpdGlvbk9wZW5Ob3Rpb25hbBJfcXVvdGVBc3NldFJlc2VydmURX3F1b3RlQXNzZXRXZWlnaHQRX2Jhc2VBc3NldFJlc2VydmUQX2Jhc2VBc3NldFdlaWdodAdfb3B0aW9uAwkAAAIFDV9wb3NpdGlvblNpemUAAAkAAgECFUludmFsaWQgcG9zaXRpb24gc2l6ZQQHaXNTaG9ydAkAZgIAAAUNX3Bvc2l0aW9uU2l6ZQQQcG9zaXRpb25Ob3Rpb25hbAkBH2dldFBvc2l0aW9uQWRqdXN0ZWRPcGVuTm90aW9uYWwGBQ1fcG9zaXRpb25TaXplBQdfb3B0aW9uBRJfcXVvdGVBc3NldFJlc2VydmUFEV9xdW90ZUFzc2V0V2VpZ2h0BRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldFdlaWdodAQNdW5yZWFsaXplZFBubAMFB2lzU2hvcnQJAGUCBRVfcG9zaXRpb25PcGVuTm90aW9uYWwFEHBvc2l0aW9uTm90aW9uYWwJAGUCBRBwb3NpdGlvbk5vdGlvbmFsBRVfcG9zaXRpb25PcGVuTm90aW9uYWwJAJQKAgUQcG9zaXRpb25Ob3Rpb25hbAUNdW5yZWFsaXplZFBubAEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCB190cmFkZXIHX29wdGlvbgQNJHQwMjQ1NTMyNDY4MQkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQMcG9zaXRpb25TaXplCAUNJHQwMjQ1NTMyNDY4MQJfMQQOcG9zaXRpb25NYXJnaW4IBQ0kdDAyNDU1MzI0NjgxAl8yBBRwb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDI0NTUzMjQ2ODECXzMEEXBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwMjQ1NTMyNDY4MQJfNAkBK2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sQnlWYWx1ZXMHBQxwb3NpdGlvblNpemUFFHBvc2l0aW9uT3Blbk5vdGlvbmFsCQEGcXRBc3RSAAkBBnF0QXN0VwAJAQZic0FzdFIACQEGYnNBc3RXAAUHX29wdGlvbgEPY2FsY01hcmdpblJhdGlvAw1fcmVtYWluTWFyZ2luCF9iYWREZWJ0EV9wb3NpdGlvbk5vdGlvbmFsCQEEZGl2ZAIJAGUCBQ1fcmVtYWluTWFyZ2luBQhfYmFkRGVidAURX3Bvc2l0aW9uTm90aW9uYWwBFmdldE1hcmdpblJhdGlvQnlPcHRpb24CB190cmFkZXIHX29wdGlvbgQNJHQwMjUxOTQyNTMwNQkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQMcG9zaXRpb25TaXplCAUNJHQwMjUxOTQyNTMwNQJfMQQOcG9zaXRpb25NYXJnaW4IBQ0kdDAyNTE5NDI1MzA1Al8yBANwb24IBQ0kdDAyNTE5NDI1MzA1Al8zBBFwb3NpdGlvbkxzdFVwZENQRggFDSR0MDI1MTk0MjUzMDUCXzQEDSR0MDI1MzExMjU0MDQJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIFB190cmFkZXIFB19vcHRpb24EEHBvc2l0aW9uTm90aW9uYWwIBQ0kdDAyNTMxMTI1NDA0Al8xBA11bnJlYWxpemVkUG5sCAUNJHQwMjUzMTEyNTQwNAJfMgQNJHQwMjU0MDkyNTU3NQkBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEBQxwb3NpdGlvblNpemUFDnBvc2l0aW9uTWFyZ2luBRFwb3NpdGlvbkxzdFVwZENQRgUNdW5yZWFsaXplZFBubAQMcmVtYWluTWFyZ2luCAUNJHQwMjU0MDkyNTU3NQJfMQQHYmFkRGVidAgFDSR0MDI1NDA5MjU1NzUCXzIJAQ9jYWxjTWFyZ2luUmF0aW8DBQxyZW1haW5NYXJnaW4FB2JhZERlYnQFEHBvc2l0aW9uTm90aW9uYWwBDmdldE1hcmdpblJhdGlvAQdfdHJhZGVyCQEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAEbZ2V0UGFydGlhbExpcXVpZGF0aW9uQW1vdW50AgdfdHJhZGVyDV9wb3NpdGlvblNpemUEDG1heGltdW1SYXRpbwkBBHZtYXgCCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8ACQBlAgUMREVDSU1BTF9VTklUCQEEZGl2ZAIJAQ5nZXRNYXJnaW5SYXRpbwEFB190cmFkZXIJARZtYWludGVuYW5jZU1hcmdpblJhdGlvAAQYbWF4RXhjaGFuZ2VkUG9zaXRpb25TaXplCQEEbXVsZAIJAQNhYnMBBQ1fcG9zaXRpb25TaXplBQxtYXhpbXVtUmF0aW8ECnN3YXBSZXN1bHQJAQpzd2FwT3V0cHV0AwkAZgIFDV9wb3NpdGlvblNpemUAAAUYbWF4RXhjaGFuZ2VkUG9zaXRpb25TaXplBwQcbWF4RXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAgFCnN3YXBSZXN1bHQCXzEEC3ByaWNlSW1wYWN0CAUKc3dhcFJlc3VsdAJfOAMJAGYCCQEObWF4UHJpY2VJbXBhY3QABQtwcmljZUltcGFjdAUcbWF4RXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAQVZXhjaGFuZ2VkUG9zaXRpb25TaXplCQEEbXVsZAIJAQNhYnMBBQ1fcG9zaXRpb25TaXplCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8ABBlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CAkBCnN3YXBPdXRwdXQDCQBmAgUNX3Bvc2l0aW9uU2l6ZQAABRVleGNoYW5nZWRQb3NpdGlvblNpemUHAl8xBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50ARVpbnRlcm5hbENsb3NlUG9zaXRpb24CB190cmFkZXIUX2NoZWNrTWF4UHJpY2VJbXBhY3QEDSR0MDI2ODA4MjY5MzYJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIEDHBvc2l0aW9uU2l6ZQgFDSR0MDI2ODA4MjY5MzYCXzEEDnBvc2l0aW9uTWFyZ2luCAUNJHQwMjY4MDgyNjkzNgJfMgQUcG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDAyNjgwODI2OTM2Al8zBBFwb3NpdGlvbkxzdFVwZENQRggFDSR0MDI2ODA4MjY5MzYCXzQEDXVucmVhbGl6ZWRQbmwICQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QCXzIEDSR0MDI3MDMxMjcxOTkJASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BAUMcG9zaXRpb25TaXplBQ5wb3NpdGlvbk1hcmdpbgURcG9zaXRpb25Mc3RVcGRDUEYFDXVucmVhbGl6ZWRQbmwEDHJlbWFpbk1hcmdpbggFDSR0MDI3MDMxMjcxOTkCXzEEB2JhZERlYnQIBQ0kdDAyNzAzMTI3MTk5Al8yBBVleGNoYW5nZWRQb3NpdGlvblNpemUJAQEtAQUMcG9zaXRpb25TaXplBAtyZWFsaXplZFBubAUNdW5yZWFsaXplZFBubAQNbWFyZ2luVG9WYXVsdAkBAS0BBQxyZW1haW5NYXJnaW4EDSR0MDI3MzI2Mjc2MzEJAQpzd2FwT3V0cHV0AwkAZgIFDHBvc2l0aW9uU2l6ZQAACQEDYWJzAQUMcG9zaXRpb25TaXplBRRfY2hlY2tNYXhQcmljZUltcGFjdAQZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAgFDSR0MDI3MzI2Mjc2MzECXzEEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDAyNzMyNjI3NjMxAl8yBBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDAyNzMyNjI3NjMxAl8zBBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwMjczMjYyNzYzMQJfNAQXY3VtdWxhdGl2ZU5vdGlvbmFsQWZ0ZXIIBQ0kdDAyNzMyNjI3NjMxAl81BA50b3RhbExvbmdBZnRlcggFDSR0MDI3MzI2Mjc2MzECXzYED3RvdGFsU2hvcnRBZnRlcggFDSR0MDI3MzI2Mjc2MzECXzcEGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIJAGUCCQEUb3BlbkludGVyZXN0Tm90aW9uYWwABRRwb3NpdGlvbk9wZW5Ob3Rpb25hbAkAngoMBRVleGNoYW5nZWRQb3NpdGlvblNpemUFB2JhZERlYnQFC3JlYWxpemVkUG5sBQ1tYXJnaW5Ub1ZhdWx0BRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFF2N1bXVsYXRpdmVOb3Rpb25hbEFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyARBnZXRUd2FwU3BvdFByaWNlAAQIbWludXRlSWQJAGkCCQBpAggFCWxhc3RCbG9jawl0aW1lc3RhbXAA6AcAPAQNc3RhcnRNaW51dGVJZAkAZQIFCG1pbnV0ZUlkBQ1UV0FQX0lOVEVSVkFMBAdsaXN0U3RyCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMFDWtfbGFzdERhdGFTdHICAAQEbGlzdAkAtQkCBQdsaXN0U3RyAgEsCgEIZmlsdGVyRm4CC2FjY3VtdWxhdG9yBG5leHQDCQBnAgUNc3RhcnRNaW51dGVJZAkBDXBhcnNlSW50VmFsdWUBBQRuZXh0CQDNCAIFC2FjY3VtdWxhdG9yCQENcGFyc2VJbnRWYWx1ZQEFBG5leHQFC2FjY3VtdWxhdG9yBAVsaXN0RgoAAiRsBQRsaXN0CgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQhmaWx0ZXJGbgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMjAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUBAhtYXhJbmRleAMJAGYCCQCQAwEFBWxpc3RGAAAJAJYDAQUFbGlzdEYJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQRsaXN0AAAEDGxhc3RNaW51dGVJZAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQ5rX2xhc3RNaW51dGVJZAAABBZlbmRMYXN0Q3VtdWxhdGl2ZVByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAKwCAgkArAICBR1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQIBXwkApAMBBQxsYXN0TWludXRlSWQAAAQMZW5kTGFzdFByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAKwCAgkArAICBRNrX3R3YXBEYXRhTGFzdFByaWNlAgFfCQCkAwEFDGxhc3RNaW51dGVJZAAABBJub3dDdW11bGF0aXZlUHJpY2UJAGQCBRZlbmRMYXN0Q3VtdWxhdGl2ZVByaWNlCQBoAgkAZQIFCG1pbnV0ZUlkBQxsYXN0TWludXRlSWQFDGVuZExhc3RQcmljZQQYc3RhcnRMYXN0Q3VtdWxhdGl2ZVByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAKwCAgkArAICBR1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQIBXwkApAMBBQhtYXhJbmRleAAABA5zdGFydExhc3RQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUTa190d2FwRGF0YUxhc3RQcmljZQIBXwkApAMBBQhtYXhJbmRleAAABBRzdGFydEN1bXVsYXRpdmVQcmljZQkAZAIFGHN0YXJ0TGFzdEN1bXVsYXRpdmVQcmljZQkAaAIJAGUCBQ1zdGFydE1pbnV0ZUlkBQhtYXhJbmRleAUOc3RhcnRMYXN0UHJpY2UJAGkCCQBlAgUSbm93Q3VtdWxhdGl2ZVByaWNlBRRzdGFydEN1bXVsYXRpdmVQcmljZQUNVFdBUF9JTlRFUlZBTAETZ2V0VGVybWluYWxBbW1TdGF0ZQAEDV9wb3NpdGlvblNpemUJARF0b3RhbFBvc2l0aW9uU2l6ZQADCQAAAgUNX3Bvc2l0aW9uU2l6ZQAACQCUCgIJAQZxdEFzdFIACQEGYnNBc3RSAAQJZGlyZWN0aW9uCQBmAgUNX3Bvc2l0aW9uU2l6ZQAABA0kdDAyOTYxODI5Nzk3CQEKc3dhcE91dHB1dAMFCWRpcmVjdGlvbgkBA2FicwEFDV9wb3NpdGlvblNpemUHBBVjdXJyZW50TmV0TWFya2V0VmFsdWUIBQ0kdDAyOTYxODI5Nzk3Al8xBBl0ZXJtaW5hbFF1b3RlQXNzZXRSZXNlcnZlCAUNJHQwMjk2MTgyOTc5NwJfMgQYdGVybWluYWxCYXNlQXNzZXRSZXNlcnZlCAUNJHQwMjk2MTgyOTc5NwJfMwkAlAoCBRl0ZXJtaW5hbFF1b3RlQXNzZXRSZXNlcnZlBRh0ZXJtaW5hbEJhc2VBc3NldFJlc2VydmUBE2dldFF1b3RlQXNzZXRXZWlnaHQEEGJhc2VBc3NldFJlc2VydmURdG90YWxQb3NpdGlvblNpemURcXVvdGVBc3NldFJlc2VydmULdGFyZ2V0UHJpY2UEAWIJALYCAQUQYmFzZUFzc2V0UmVzZXJ2ZQQCc3oJALYCAQURdG90YWxQb3NpdGlvblNpemUEAXEJALYCAQURcXVvdGVBc3NldFJlc2VydmUEAXAJALYCAQULdGFyZ2V0UHJpY2UEA2JzMgkBBWJwb3dkAgkAtwICBQFiBQJzegkAtgIBCQBoAgACBQxERUNJTUFMX1VOSVQEBHFiczIJAQVibXVsZAIFAXEFA2JzMgQDcHM0CQC5AgIJALYCAQAECQEFYm11bGQCBQFwBQJzegQDc3FyCQEGYnNxcnRkAQkBBWJtdWxkAgUEcWJzMgkAuAICBQFxBQNwczQEAmJxCQEFYm11bGQCBQFiBQFxBAJxcwkBBWJtdWxkAgUBcQUCc3oEA3RvcAkAtwICCQC3AgIJAL4CAQUDc3FyBQJicQUCcXMEA2JvdAkAuQICCQC2AgEAAgkBBWJtdWxkAgUBcQUCc3oEBnJlc3VsdAkBBWJkaXZkAgUDdG9wBQNib3QJAKADAQUGcmVzdWx0ARRnZXRTeW5jVGVybWluYWxQcmljZQEOX3Rlcm1pbmFsUHJpY2UEDV9wb3NpdGlvblNpemUJARF0b3RhbFBvc2l0aW9uU2l6ZQADCQAAAgUNX3Bvc2l0aW9uU2l6ZQAABAdfcXRBc3RSCQEGcXRBc3RSAAQHX2JzQXN0UgkBBmJzQXN0UgAECW5ld1F0QXN0VwkBBGRpdmQCCQEEbXVsZAIFDl90ZXJtaW5hbFByaWNlBQdfYnNBc3RSBQdfcXRBc3RSCQCVCgMFCW5ld1F0QXN0VwUMREVDSU1BTF9VTklUAAAECWRpcmVjdGlvbgkAZgIFDV9wb3NpdGlvblNpemUAAAQVY3VycmVudE5ldE1hcmtldFZhbHVlCAkBCnN3YXBPdXRwdXQDBQlkaXJlY3Rpb24JAQNhYnMBBQ1fcG9zaXRpb25TaXplBwJfMQQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABAluZXdRdEFzdFcJARNnZXRRdW90ZUFzc2V0V2VpZ2h0BAUHX2JzQXN0UgUNX3Bvc2l0aW9uU2l6ZQUHX3F0QXN0UgUOX3Rlcm1pbmFsUHJpY2UECW5ld0JzQXN0VwUMREVDSU1BTF9VTklUBA1tYXJnaW5Ub1ZhdWx0CAkBK2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sQnlWYWx1ZXMHBQ1fcG9zaXRpb25TaXplBRVjdXJyZW50TmV0TWFya2V0VmFsdWUFB19xdEFzdFIFCW5ld1F0QXN0VwUHX2JzQXN0UgUJbmV3QnNBc3RXBQ9QTkxfT1BUSU9OX1NQT1QCXzIJAJUKAwUJbmV3UXRBc3RXBQluZXdCc0FzdFcFDW1hcmdpblRvVmF1bHQBCmdldEZ1bmRpbmcABA91bmRlcmx5aW5nUHJpY2UJARJnZXRPcmFjbGVUd2FwUHJpY2UABA1zcG90VHdhcFByaWNlCQEQZ2V0VHdhcFNwb3RQcmljZQAEB3ByZW1pdW0JAGUCBQ1zcG90VHdhcFByaWNlBQ91bmRlcmx5aW5nUHJpY2UDAwkAAAIJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAAABgkAAAIJARV0b3RhbExvbmdQb3NpdGlvblNpemUAAAAJAJQKAgAAAAADCQBmAgAABQdwcmVtaXVtBBRzaG9ydFByZW1pdW1GcmFjdGlvbgkBBGRpdmQCCQEEbXVsZAIFB3ByZW1pdW0JARRmdW5kaW5nUGVyaW9kRGVjaW1hbAAFB09ORV9EQVkEE2xvbmdQcmVtaXVtRnJhY3Rpb24JAQRkaXZkAgkBBG11bGQCBRRzaG9ydFByZW1pdW1GcmFjdGlvbgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUACQEVdG90YWxMb25nUG9zaXRpb25TaXplAAkAlAoCBRRzaG9ydFByZW1pdW1GcmFjdGlvbgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgQTbG9uZ1ByZW1pdW1GcmFjdGlvbgkBBGRpdmQCCQEEbXVsZAIFB3ByZW1pdW0JARRmdW5kaW5nUGVyaW9kRGVjaW1hbAAFB09ORV9EQVkEFHNob3J0UHJlbWl1bUZyYWN0aW9uCQEEZGl2ZAIJAQRtdWxkAgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQAJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAkAlAoCBRRzaG9ydFByZW1pdW1GcmFjdGlvbgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgEOZ2V0QWRqdXN0ZWRGZWUCAWkQX2Jhc2VGZWVEaXNjb3VudAQKYmFzZUZlZVJhdwkBA2ZlZQAEB2Jhc2VGZWUJAQRtdWxkAgUKYmFzZUZlZVJhdwUQX2Jhc2VGZWVEaXNjb3VudAQNJHQwMzI4OTAzMzQ5OAMJAGYCCQCQAwEIBQFpCHBheW1lbnRzAAEECmFydGlmYWN0SWQJANgEAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCAkAkQMCCAUBaQhwYXltZW50cwABB2Fzc2V0SWQCGUludmFsaWQgYXR0YWNoZWQgYXJ0aWZhY3QEDGFydGlmYWN0S2luZAkBBHN0ckECCQERbmZ0TWFuYWdlckFkZHJlc3MACQEOdG9Db21wb3NpdGVLZXkCBQxrX3Rva2VuX3R5cGUFCmFydGlmYWN0SWQDCQAAAgUMYXJ0aWZhY3RLaW5kBRhGRUVfUkVEVUNUSU9OX1RPS0VOX1RZUEUECXJlZHVjdGlvbgkBBGludEECCQERbmZ0TWFuYWdlckFkZHJlc3MACQEOdG9Db21wb3NpdGVLZXkCBQ1rX3Rva2VuX3BhcmFtBQphcnRpZmFjdElkBAthZGp1c3RlZEZlZQkBBG11bGQCBQdiYXNlRmVlBQlyZWR1Y3Rpb24JAJQKAgULYWRqdXN0ZWRGZWUGCQACAQIZSW52YWxpZCBhdHRhY2hlZCBhcnRpZmFjdAkAlAoCBQdiYXNlRmVlBwQLYWRqdXN0ZWRGZWUIBQ0kdDAzMjg5MDMzNDk4Al8xBAxidXJuQXJ0aWZhY3QIBQ0kdDAzMjg5MDMzNDk4Al8yCQCUCgIFC2FkanVzdGVkRmVlBQxidXJuQXJ0aWZhY3QBDnVwZGF0ZVNldHRpbmdzCRBfaW5pdE1hcmdpblJhdGlvBF9tbXIUX2xpcXVpZGF0aW9uRmVlUmF0aW8OX2Z1bmRpbmdQZXJpb2QEX2ZlZQxfc3ByZWFkTGltaXQPX21heFByaWNlSW1wYWN0GF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbw9fbWF4UHJpY2VTcHJlYWQJAMwIAgkBDEludGVnZXJFbnRyeQIFEWtfaW5pdE1hcmdpblJhdGlvBRBfaW5pdE1hcmdpblJhdGlvCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRhrX21haW50ZW5hbmNlTWFyZ2luUmF0aW8FBF9tbXIJAMwIAgkBDEludGVnZXJFbnRyeQIFFWtfbGlxdWlkYXRpb25GZWVSYXRpbwUUX2xpcXVpZGF0aW9uRmVlUmF0aW8JAMwIAgkBDEludGVnZXJFbnRyeQIFD2tfZnVuZGluZ1BlcmlvZAUOX2Z1bmRpbmdQZXJpb2QJAMwIAgkBDEludGVnZXJFbnRyeQIFBWtfZmVlBQRfZmVlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ1rX3NwcmVhZExpbWl0BQxfc3ByZWFkTGltaXQJAMwIAgkBDEludGVnZXJFbnRyeQIFEGtfbWF4UHJpY2VJbXBhY3QFD19tYXhQcmljZUltcGFjdAkAzAgCCQEMSW50ZWdlckVudHJ5AgUZa19wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwUYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRBrX21heFByaWNlU3ByZWFkBQ9fbWF4UHJpY2VTcHJlYWQFA25pbAENdXBkYXRlRnVuZGluZwURX25leHRGdW5kaW5nQmxvY2skX2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uJV9sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24QX2xvbmdGdW5kaW5nUmF0ZRFfc2hvcnRGdW5kaW5nUmF0ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUSa19uZXh0RnVuZGluZ0Jsb2NrBRFfbmV4dEZ1bmRpbmdCbG9jawkAzAgCCQEMSW50ZWdlckVudHJ5AgUla19sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUkX2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uCQDMCAIJAQxJbnRlZ2VyRW50cnkCBSZrX2xhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUlX2xhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgURa19sb25nRnVuZGluZ1JhdGUFEF9sb25nRnVuZGluZ1JhdGUJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfc2hvcnRGdW5kaW5nUmF0ZQURX3Nob3J0RnVuZGluZ1JhdGUFA25pbAETdXBkYXRlUG9zaXRpb25Bc3NldAIIX2FkZHJlc3MIX2Fzc2V0SWQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUPa19wb3NpdGlvbkFzc2V0BQhfYWRkcmVzcwUIX2Fzc2V0SWQFA25pbAEOdXBkYXRlUG9zaXRpb24FCF9hZGRyZXNzBV9zaXplB19tYXJnaW4NX29wZW5Ob3Rpb25hbCBfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUOa19wb3NpdGlvblNpemUFCF9hZGRyZXNzBQVfc2l6ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUQa19wb3NpdGlvbk1hcmdpbgUIX2FkZHJlc3MFB19tYXJnaW4JAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFFmtfcG9zaXRpb25PcGVuTm90aW9uYWwFCF9hZGRyZXNzBQ1fb3Blbk5vdGlvbmFsCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBS5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBQhfYWRkcmVzcwUgX2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FA25pbAEKYXBwZW5kVHdhcAEFcHJpY2UECG1pbnV0ZUlkCQBpAgkAaQIIBQlsYXN0QmxvY2sJdGltZXN0YW1wAOgHADwEEHByZXZpb3VzTWludXRlSWQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUOa19sYXN0TWludXRlSWQAAAMJAGYCBRBwcmV2aW91c01pbnV0ZUlkBQhtaW51dGVJZAkAAgECEVRXQVAgb3V0LW9mLW9yZGVyBAxsYXN0TWludXRlSWQDCQAAAgUQcHJldmlvdXNNaW51dGVJZAAABQhtaW51dGVJZAUQcHJldmlvdXNNaW51dGVJZAMJAGYCBQhtaW51dGVJZAUQcHJldmlvdXNNaW51dGVJZAQTcHJldkN1bXVsYXRpdmVQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UCAV8JAKQDAQUQcHJldmlvdXNNaW51dGVJZAAABAlwcmV2UHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkArAICCQCsAgIFE2tfdHdhcERhdGFMYXN0UHJpY2UCAV8JAKQDAQUQcHJldmlvdXNNaW51dGVJZAUFcHJpY2UEE2xhc3RDdW11bGF0aXZlUHJpY2UJAGQCBRNwcmV2Q3VtdWxhdGl2ZVByaWNlCQBoAgkAZQIFCG1pbnV0ZUlkBQxsYXN0TWludXRlSWQFCXByZXZQcmljZQQEbGlzdAkBC3B1c2hUb1F1ZXVlAwkBCXN0clRvTGlzdAEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwUNa19sYXN0RGF0YVN0cgIABQ1UV0FQX0lOVEVSVkFMCQCkAwEFCG1pbnV0ZUlkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBR1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQkApAMBBQhtaW51dGVJZAUTbGFzdEN1bXVsYXRpdmVQcmljZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUTa190d2FwRGF0YUxhc3RQcmljZQkApAMBBQhtaW51dGVJZAUFcHJpY2UJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFGmtfdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkCQCkAwEFCG1pbnV0ZUlkBRBwcmV2aW91c01pbnV0ZUlkCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ5rX2xhc3RNaW51dGVJZAUIbWludXRlSWQJAMwIAgkBC1N0cmluZ0VudHJ5AgUNa19sYXN0RGF0YVN0cgkBCWxpc3RUb1N0cgEFBGxpc3QFA25pbAQYdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFGmtfdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkCQCkAwEFCG1pbnV0ZUlkAAAEE3ByZXZDdW11bGF0aXZlUHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UJAKQDAQUYdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkAAAECXByZXZQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBRNrX3R3YXBEYXRhTGFzdFByaWNlCQCkAwEFGHR3YXBEYXRhUHJldmlvdXNNaW51dGVJZAUFcHJpY2UEE2xhc3RDdW11bGF0aXZlUHJpY2UJAGQCBRNwcmV2Q3VtdWxhdGl2ZVByaWNlCQBoAgkAZQIFCG1pbnV0ZUlkBRh0d2FwRGF0YVByZXZpb3VzTWludXRlSWQFCXByZXZQcmljZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UJAKQDAQUIbWludXRlSWQFE2xhc3RDdW11bGF0aXZlUHJpY2UJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFE2tfdHdhcERhdGFMYXN0UHJpY2UJAKQDAQUIbWludXRlSWQFBXByaWNlBQNuaWwBEXVwZGF0ZUFtbVJlc2VydmVzAgdfcXRBc3RSB19ic0FzdFIJAMwIAgkBDEludGVnZXJFbnRyeQIFE2tfcXVvdGVBc3NldFJlc2VydmUFB19xdEFzdFIJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfYmFzZUFzc2V0UmVzZXJ2ZQUHX2JzQXN0UgUDbmlsARB1cGRhdGVBbW1XZWlnaHRzAgdfcXRBc3RXB19ic0FzdFcJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfcXVvdGVBc3NldFdlaWdodAUHX3F0QXN0VwkAzAgCCQEMSW50ZWdlckVudHJ5AgURa19iYXNlQXNzZXRXZWlnaHQFB19ic0FzdFcFA25pbAEJdXBkYXRlQW1tBwdfcXRBc3RSB19ic0FzdFIXX3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIYX2N1bXVsYXRpdmVOb3Rpb25hbEFmdGVyFV9vcGVuSW50ZXJlc3ROb3Rpb25hbBZfdG90YWxMb25nUG9zaXRpb25TaXplF190b3RhbFNob3J0UG9zaXRpb25TaXplBAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwADCQECIT0CCQBlAgUWX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQUXX3RvdGFsU2hvcnRQb3NpdGlvblNpemUFF190b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgICGEludmFsaWQgQU1NIHN0YXRlIGRhdGE6IAkApAMBBRZfdG90YWxMb25nUG9zaXRpb25TaXplAgQgKyAgCQCkAwEFF190b3RhbFNob3J0UG9zaXRpb25TaXplAgQgIT0gCQCkAwEFF190b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCQDOCAIJAM4IAgkBEXVwZGF0ZUFtbVJlc2VydmVzAgUHX3F0QXN0UgUHX2JzQXN0UgkAzAgCCQEMSW50ZWdlckVudHJ5AgUTa190b3RhbFBvc2l0aW9uU2l6ZQUXX3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIJAMwIAgkBDEludGVnZXJFbnRyeQIFFGtfY3VtdWxhdGl2ZU5vdGlvbmFsBRhfY3VtdWxhdGl2ZU5vdGlvbmFsQWZ0ZXIJAMwIAgkBDEludGVnZXJFbnRyeQIFFmtfb3BlbkludGVyZXN0Tm90aW9uYWwFFV9vcGVuSW50ZXJlc3ROb3Rpb25hbAkAzAgCCQEMSW50ZWdlckVudHJ5AgUXa190b3RhbExvbmdQb3NpdGlvblNpemUFFl90b3RhbExvbmdQb3NpdGlvblNpemUJAMwIAgkBDEludGVnZXJFbnRyeQIFGGtfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQUXX3RvdGFsU2hvcnRQb3NpdGlvblNpemUFA25pbAkBCmFwcGVuZFR3YXABCQEEZGl2ZAIJAQRtdWxkAgUHX3F0QXN0UgUHX3F0QXN0VwkBBG11bGQCBQdfYnNBc3RSBQdfYnNBc3RXAQ5kZWxldGVQb3NpdGlvbgEIX2FkZHJlc3MJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBDnRvQ29tcG9zaXRlS2V5AgUOa19wb3NpdGlvblNpemUFCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFEGtfcG9zaXRpb25NYXJnaW4FCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFFmtfcG9zaXRpb25PcGVuTm90aW9uYWwFCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFLmtfcG9zaXRpb25MYXN0VXBkYXRlZEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFD2tfcG9zaXRpb25Bc3NldAUIX2FkZHJlc3MJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFFGtfcG9zaXRpb25DbG9zZWREYXRlBQhfYWRkcmVzcwgFCWxhc3RCbG9jawl0aW1lc3RhbXAFA25pbAEId2l0aGRyYXcCCF9hZGRyZXNzB19hbW91bnQEB2JhbGFuY2UJAPAHAgUEdGhpcwkBCnF1b3RlQXNzZXQAAwkAZgIFB19hbW91bnQFB2JhbGFuY2UJAAIBCQCsAgIJAKwCAgkArAICAhNVbmFibGUgdG8gd2l0aGRyYXcgCQCkAwEFB19hbW91bnQCFyBmcm9tIGNvbnRyYWN0IGJhbGFuY2UgCQCkAwEFB2JhbGFuY2UJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUIX2FkZHJlc3MFB19hbW91bnQJAQpxdW90ZUFzc2V0AAUDbmlsAQ11cGRhdGVCYWxhbmNlAQFpAwkAZgIAAAUBaQkAAgECB0JhbGFuY2UJAMwIAgkBDEludGVnZXJFbnRyeQIFCWtfYmFsYW5jZQUBaQUDbmlsAQt0cmFuc2ZlckZlZQEBaQkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCQEOc3Rha2luZ0FkZHJlc3MABQFpCQEKcXVvdGVBc3NldAAFA25pbAEOZG9CdXJuQXJ0aWZhY3QCDV9idXJuQXJ0aWZhY3QBaQMFDV9idXJuQXJ0aWZhY3QJAMwIAgkBBEJ1cm4CCQETdmFsdWVPckVycm9yTWVzc2FnZQIICQCRAwIIBQFpCHBheW1lbnRzAAEHYXNzZXRJZAIQSW52YWxpZCBhcnRpZmFjdAABBQNuaWwFA25pbAEXaXNTYW1lQXNzZXRPck5vUG9zaXRpb24CB190cmFkZXIIX2Fzc2V0SWQED29sZFBvc2l0aW9uU2l6ZQgJAQtnZXRQb3NpdGlvbgEFB190cmFkZXICXzEDCQAAAgUPb2xkUG9zaXRpb25TaXplAAAGCQAAAgkBEGdldFBvc2l0aW9uQXNzZXQBBQdfdHJhZGVyBQhfYXNzZXRJZAELaXNTYW1lQXNzZXQCB190cmFkZXIIX2Fzc2V0SWQJAAACCQEQZ2V0UG9zaXRpb25Bc3NldAEFB190cmFkZXIFCF9hc3NldElkAR5nZXRCb3Jyb3dlZEJ5VHJhZGVySW5NYXJrZXRLZXkDBF9hbW0IX2Fzc2V0SWQHX3RyYWRlcgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgUga190cmFkZXJfbWFya2V0X2Fzc2V0X2NvbGxhdGVyYWwCAV8FBF9hbW0CAV8FCF9hc3NldElkAgFfBQdfdHJhZGVyARNnZXRCb3Jyb3dlZEJ5VHJhZGVyAQdfdHJhZGVyBA1wb3NpdGlvbkFzc2V0CQEQZ2V0UG9zaXRpb25Bc3NldAEFB190cmFkZXIDCQAAAgUNcG9zaXRpb25Bc3NldAkA2AQBCQEKcXVvdGVBc3NldAAJAJQKAgAABQ1wb3NpdGlvbkFzc2V0BANrZXkJAR5nZXRCb3Jyb3dlZEJ5VHJhZGVySW5NYXJrZXRLZXkDCQClCAEFBHRoaXMFDXBvc2l0aW9uQXNzZXQFB190cmFkZXIEBmJvcnJvdwkBC3ZhbHVlT3JFbHNlAgkAmggCCQERY29sbGF0ZXJhbEFkZHJlc3MABQNrZXkAAAkAlAoCBQZib3Jyb3cFDXBvc2l0aW9uQXNzZXQVAWkBBXBhdXNlAAMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAhpJbnZhbGlkIHRvZ2dsZVBhdXNlIHBhcmFtcwkAzAgCCQEMQm9vbGVhbkVudHJ5AgUIa19wYXVzZWQGBQNuaWwBaQEHdW5wYXVzZQADCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MACQACAQIaSW52YWxpZCB0b2dnbGVQYXVzZSBwYXJhbXMJAMwIAgkBDEJvb2xlYW5FbnRyeQIFCGtfcGF1c2VkBwUDbmlsAWkBDGFkZExpcXVpZGl0eQERX3F1b3RlQXNzZXRBbW91bnQDAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAYJAGcCAAAFEV9xdW90ZUFzc2V0QW1vdW50CQACAQIbSW52YWxpZCBhZGRMaXF1aWRpdHkgcGFyYW1zBAdfcXRBc3RSCQEGcXRBc3RSAAQHX2JzQXN0UgkBBmJzQXN0UgAEB19xdEFzdFcJAQZxdEFzdFcABAdfYnNBc3RXCQEGYnNBc3RXAAQFcHJpY2UJAQRkaXZkAgkBBG11bGQCBQdfcXRBc3RSBQdfcXRBc3RXCQEEbXVsZAIFB19ic0FzdFIFB19ic0FzdFcEFGJhc2VBc3NldEFtb3VudFRvQWRkCQEEZGl2ZAIFEV9xdW90ZUFzc2V0QW1vdW50BQVwcmljZQQLcXRBc3RSQWZ0ZXIJAGQCBQdfcXRBc3RSBRFfcXVvdGVBc3NldEFtb3VudAQLYnNBc3RSQWZ0ZXIJAGQCBQdfYnNBc3RSBRRiYXNlQXNzZXRBbW91bnRUb0FkZAkBEXVwZGF0ZUFtbVJlc2VydmVzAgULcXRBc3RSQWZ0ZXIFC2JzQXN0UkFmdGVyAWkBD3JlbW92ZUxpcXVpZGl0eQERX3F1b3RlQXNzZXRBbW91bnQDAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAYJAGcCAAAFEV9xdW90ZUFzc2V0QW1vdW50CQACAQIeSW52YWxpZCByZW1vdmVMaXF1aWRpdHkgcGFyYW1zBAdfcXRBc3RSCQEGcXRBc3RSAAQHX2JzQXN0UgkBBmJzQXN0UgAEB19xdEFzdFcJAQZxdEFzdFcABAdfYnNBc3RXCQEGYnNBc3RXAAQFcHJpY2UJAQRkaXZkAgkBBG11bGQCBQdfcXRBc3RSBQdfcXRBc3RXCQEEbXVsZAIFB19ic0FzdFIFB19ic0FzdFcEF2Jhc2VBc3NldEFtb3VudFRvUmVtb3ZlCQEEZGl2ZAIFEV9xdW90ZUFzc2V0QW1vdW50BQVwcmljZQQLcXRBc3RSQWZ0ZXIJAGUCBQdfcXRBc3RSBRFfcXVvdGVBc3NldEFtb3VudAQLYnNBc3RSQWZ0ZXIJAGUCBQdfYnNBc3RSBRdiYXNlQXNzZXRBbW91bnRUb1JlbW92ZQkBEXVwZGF0ZUFtbVJlc2VydmVzAgULcXRBc3RSQWZ0ZXIFC2JzQXN0UkFmdGVyAWkBDmNoYW5nZVNldHRpbmdzCRBfaW5pdE1hcmdpblJhdGlvBF9tbXIUX2xpcXVpZGF0aW9uRmVlUmF0aW8OX2Z1bmRpbmdQZXJpb2QEX2ZlZQxfc3ByZWFkTGltaXQPX21heFByaWNlSW1wYWN0GF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbw9fbWF4UHJpY2VTcHJlYWQDCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MACQACAQIdSW52YWxpZCBjaGFuZ2VTZXR0aW5ncyBwYXJhbXMJAQ51cGRhdGVTZXR0aW5ncwkFEF9pbml0TWFyZ2luUmF0aW8FBF9tbXIFFF9saXF1aWRhdGlvbkZlZVJhdGlvBQ5fZnVuZGluZ1BlcmlvZAUEX2ZlZQUMX3NwcmVhZExpbWl0BQ9fbWF4UHJpY2VJbXBhY3QFGF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwUPX21heFByaWNlU3ByZWFkAWkBCmluaXRpYWxpemUOB19xdEFzdFIHX2JzQXN0Ug5fZnVuZGluZ1BlcmlvZBBfaW5pdE1hcmdpblJhdGlvBF9tbXIUX2xpcXVpZGF0aW9uRmVlUmF0aW8EX2ZlZQdfb3JhY2xlCl9vcmFjbGVLZXkMX2Nvb3JkaW5hdG9yDF9zcHJlYWRMaW1pdA9fbWF4UHJpY2VJbXBhY3QYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvD19tYXhQcmljZVNwcmVhZAMDAwMDAwMDAwMDAwkAZwIAAAUHX3F0QXN0UgYJAGcCAAAFB19ic0FzdFIGCQBnAgAABQ5fZnVuZGluZ1BlcmlvZAYJAGcCAAAFEF9pbml0TWFyZ2luUmF0aW8GCQBnAgAABQRfbW1yBgkAZwIAAAUUX2xpcXVpZGF0aW9uRmVlUmF0aW8GCQBnAgAABQRfZmVlBgkAZwIAAAUMX3NwcmVhZExpbWl0BgkAZwIAAAUPX21heFByaWNlSW1wYWN0BgkAZwIAAAUYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvBgkAZwIAAAUPX21heFByaWNlU3ByZWFkBgkBC2luaXRpYWxpemVkAAkAAgECHUludmFsaWQgaW5pdGlhbGl6ZSBwYXJhbWV0ZXJzCQDOCAIJAM4IAgkAzggCCQDOCAIJAQl1cGRhdGVBbW0HBQdfcXRBc3RSBQdfYnNBc3RSAAAAAAAAAAAAAAkBDnVwZGF0ZVNldHRpbmdzCQUQX2luaXRNYXJnaW5SYXRpbwUEX21tcgUUX2xpcXVpZGF0aW9uRmVlUmF0aW8FDl9mdW5kaW5nUGVyaW9kBQRfZmVlBQxfc3ByZWFkTGltaXQFD19tYXhQcmljZUltcGFjdAUYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvBQ9fbWF4UHJpY2VTcHJlYWQJAQ11cGRhdGVGdW5kaW5nBQkAZAIIBQlsYXN0QmxvY2sJdGltZXN0YW1wBQ5fZnVuZGluZ1BlcmlvZAAAAAAAAAAACQENdXBkYXRlQmFsYW5jZQEAAAkAzAgCCQEMQm9vbGVhbkVudHJ5AgUNa19pbml0aWFsaXplZAYJAMwIAgkBC1N0cmluZ0VudHJ5AgUFa19vcmEFB19vcmFjbGUJAMwIAgkBC1N0cmluZ0VudHJ5AgUJa19vcmFfa2V5BQpfb3JhY2xlS2V5CQDMCAIJAQtTdHJpbmdFbnRyeQIFFGtfY29vcmRpbmF0b3JBZGRyZXNzBQxfY29vcmRpbmF0b3IFA25pbAFpARJzZXRJbml0TWFyZ2luUmF0aW8BEF9pbml0TWFyZ2luUmF0aW8DAwkAZwIAAAUQX2luaXRNYXJnaW5SYXRpbwYJAQEhAQkBC2luaXRpYWxpemVkAAkAAgECJUludmFsaWQgc2V0SW5pdE1hcmdpblJhdGlvIHBhcmFtZXRlcnMJAQ51cGRhdGVTZXR0aW5ncwkFEF9pbml0TWFyZ2luUmF0aW8JARZtYWludGVuYW5jZU1hcmdpblJhdGlvAAkBE2xpcXVpZGF0aW9uRmVlUmF0aW8ACQEQZnVuZGluZ1BlcmlvZFJhdwAJAQNmZWUACQELc3ByZWFkTGltaXQACQEObWF4UHJpY2VJbXBhY3QACQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8ACQEObWF4UHJpY2VTcHJlYWQAAWkBEGRlY3JlYXNlUG9zaXRpb24DB19hbW91bnQJX2xldmVyYWdlE19taW5CYXNlQXNzZXRBbW91bnQEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwMDAwMDCQBnAgAABQdfYW1vdW50BgkBASEBCQELaW5pdGlhbGl6ZWQABgkBASEBCQEWcmVxdWlyZU1vcmVNYXJnaW5SYXRpbwMJAQRkaXZkAgUMREVDSU1BTF9VTklUBQlfbGV2ZXJhZ2UJAQ9pbml0TWFyZ2luUmF0aW8ABgYJAQEhAQkBE3JlcXVpcmVPcGVuUG9zaXRpb24BCQClCAEIBQFpBmNhbGxlcgYJAQZwYXVzZWQACQACAQIjSW52YWxpZCBkZWNyZWFzZVBvc2l0aW9uIHBhcmFtZXRlcnMEDSR0MDQ1NDc4NDU2MzAJAQtnZXRQb3NpdGlvbgEJAKUIAQgFAWkGY2FsbGVyBA9vbGRQb3NpdGlvblNpemUIBQ0kdDA0NTQ3ODQ1NjMwAl8xBBFvbGRQb3NpdGlvbk1hcmdpbggFDSR0MDQ1NDc4NDU2MzACXzIEF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNDU0Nzg0NTYzMAJfMwQUb2xkUG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA0NTQ3ODQ1NjMwAl80BApfZGlyZWN0aW9uAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAABQlESVJfU0hPUlQFCERJUl9MT05HBAVpc0FkZAkAAAIFCl9kaXJlY3Rpb24FCERJUl9MT05HBAxvcGVuTm90aW9uYWwJAQRtdWxkAgUHX2Ftb3VudAUJX2xldmVyYWdlBA0kdDA0NTgwMzQ1OTE5CQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCCQClCAEIBQFpBmNhbGxlcgUPUE5MX09QVElPTl9TUE9UBBNvbGRQb3NpdGlvbk5vdGlvbmFsCAUNJHQwNDU4MDM0NTkxOQJfMQQNdW5yZWFsaXplZFBubAgFDSR0MDQ1ODAzNDU5MTkCXzIEDSR0MDQ1OTI1NDg0NzQDCQBmAgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUMb3Blbk5vdGlvbmFsBA0kdDA0NjMwMjQ2NTIxCQEJc3dhcElucHV0AgUFaXNBZGQFDG9wZW5Ob3Rpb25hbAQVZXhjaGFuZ2VkUG9zaXRpb25TaXplCAUNJHQwNDYzMDI0NjUyMQJfMQQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDQ2MzAyNDY1MjECXzIEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDQ2MzAyNDY1MjECXzMEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA0NjMwMjQ2NTIxAl80BBdjdW11bGF0aXZlTm90aW9uYWxBZnRlcggFDSR0MDQ2MzAyNDY1MjECXzUEGGV4Y2hhbmdlZFBvc2l0aW9uU2l6ZUFicwkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQMDCQECIT0CBRNfbWluQmFzZUFzc2V0QW1vdW50AAAJAGYCBRNfbWluQmFzZUFzc2V0QW1vdW50BRhleGNoYW5nZWRQb3NpdGlvblNpemVBYnMHCQACAQkArAICCQCsAgIJAKwCAgIlVG9vIGxpdHRsZSBiYXNlIGFzc2V0IGV4Y2hhbmdlZCwgZ290IAkApAMBBRhleGNoYW5nZWRQb3NpdGlvblNpemVBYnMCCiBleHBlY3RlZCAJAKQDAQUTX21pbkJhc2VBc3NldEFtb3VudAQLcmVhbGl6ZWRQbmwJAQRkaXZkAgkBBG11bGQCBQ11bnJlYWxpemVkUG5sBRhleGNoYW5nZWRQb3NpdGlvblNpemVBYnMJAQNhYnMBBQ9vbGRQb3NpdGlvblNpemUEDSR0MDQ2OTU4NDcyMDMJASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BAUPb2xkUG9zaXRpb25TaXplBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25Mc3RVcGRDUEYFC3JlYWxpemVkUG5sBAxyZW1haW5NYXJnaW4IBQ0kdDA0Njk1ODQ3MjAzAl8xBAdiYWREZWJ0CAUNJHQwNDY5NTg0NzIwMwJfMgQOZnVuZGluZ1BheW1lbnQIBQ0kdDA0Njk1ODQ3MjAzAl8zBBlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BQxvcGVuTm90aW9uYWwEEnVucmVhbGl6ZWRQbmxBZnRlcgkAZQIFDXVucmVhbGl6ZWRQbmwFC3JlYWxpemVkUG5sBBJyZW1haW5PcGVuTm90aW9uYWwDCQBmAgUPb2xkUG9zaXRpb25TaXplAAAJAGUCCQBlAgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAUSdW5yZWFsaXplZFBubEFmdGVyCQBlAgkAZAIFEnVucmVhbGl6ZWRQbmxBZnRlcgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAQPbmV3UG9zaXRpb25TaXplCQBkAgUPb2xkUG9zaXRpb25TaXplBRVleGNoYW5nZWRQb3NpdGlvblNpemUJAJ0KCwUPbmV3UG9zaXRpb25TaXplBQxyZW1haW5NYXJnaW4JAQNhYnMBBRJyZW1haW5PcGVuTm90aW9uYWwJAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUPbmV3UG9zaXRpb25TaXplBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFF2N1bXVsYXRpdmVOb3Rpb25hbEFmdGVyCQBlAgkBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAAUMb3Blbk5vdGlvbmFsCQBlAgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQADCQBmAgUPbmV3UG9zaXRpb25TaXplAAAJAQNhYnMBBRVleGNoYW5nZWRQb3NpdGlvblNpemUAAAkAZQIJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAMJAGYCAAAFD25ld1Bvc2l0aW9uU2l6ZQkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQAACQACAQIUQ2xvc2UgcG9zaXRpb24gZmlyc3QED25ld1Bvc2l0aW9uU2l6ZQgFDSR0MDQ1OTI1NDg0NzQCXzEEF25ld1Bvc2l0aW9uUmVtYWluTWFyZ2luCAUNJHQwNDU5MjU0ODQ3NAJfMgQXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA0NTkyNTQ4NDc0Al8zBBRuZXdQb3NpdGlvbkxhdGVzdENQRggFDSR0MDQ1OTI1NDg0NzQCXzQEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDQ1OTI1NDg0NzQCXzUEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA0NTkyNTQ4NDc0Al82BBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNDU5MjU0ODQ3NAJfNwQXY3VtdWxhdGl2ZU5vdGlvbmFsQWZ0ZXIIBQ0kdDA0NTkyNTQ4NDc0Al84BBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCAUNJHQwNDU5MjU0ODQ3NAJfOQQOdG90YWxMb25nQWZ0ZXIIBQ0kdDA0NTkyNTQ4NDc0A18xMAQPdG90YWxTaG9ydEFmdGVyCAUNJHQwNDU5MjU0ODQ3NANfMTEEDm5vdGlmeU5vdGlvbmFsCQD8BwQJAQxtaW5lckFkZHJlc3MAAg5ub3RpZnlOb3Rpb25hbAkAzAgCCQClCAEIBQFpBmNhbGxlcgkAzAgCBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUDbmlsBQNuaWwDCQAAAgUObm90aWZ5Tm90aW9uYWwFDm5vdGlmeU5vdGlvbmFsCQDOCAIJAQ51cGRhdGVQb3NpdGlvbgUJAKUIAQgFAWkGY2FsbGVyBQ9uZXdQb3NpdGlvblNpemUFF25ld1Bvc2l0aW9uUmVtYWluTWFyZ2luBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUUbmV3UG9zaXRpb25MYXRlc3RDUEYJAQl1cGRhdGVBbW0HBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFF2N1bXVsYXRpdmVOb3Rpb25hbEFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBEGluY3JlYXNlUG9zaXRpb24ECl9kaXJlY3Rpb24JX2xldmVyYWdlE19taW5CYXNlQXNzZXRBbW91bnQIX3JlZkxpbmsEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQHX3RyYWRlcgkApQgBCAUBaQZjYWxsZXIECl9yYXdBbW91bnQICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50BAhfYXNzZXRJZAgJAJEDAggFAWkIcGF5bWVudHMAAAdhc3NldElkBAtfYXNzZXRJZFN0cgkA2AQBCQEFdmFsdWUBBQhfYXNzZXRJZAQMaXNRdW90ZUFzc2V0CQAAAgUIX2Fzc2V0SWQJAQpxdW90ZUFzc2V0AAQRaXNDb2xsYXRlcmFsQXNzZXQJARBpc1doaXRlbGlzdEFzc2V0AQULX2Fzc2V0SWRTdHIDAwMDAwMDAwkBAiE9AgUKX2RpcmVjdGlvbgUIRElSX0xPTkcJAQIhPQIFCl9kaXJlY3Rpb24FCURJUl9TSE9SVAcGCQBnAgAABQpfcmF3QW1vdW50BgkBASEBCQELaW5pdGlhbGl6ZWQABgMJAQEhAQUMaXNRdW90ZUFzc2V0CQEBIQEFEWlzQ29sbGF0ZXJhbEFzc2V0BwYJAQEhAQkBF2lzU2FtZUFzc2V0T3JOb1Bvc2l0aW9uAgUHX3RyYWRlcgULX2Fzc2V0SWRTdHIGCQEBIQEJARZyZXF1aXJlTW9yZU1hcmdpblJhdGlvAwkBBGRpdmQCBQxERUNJTUFMX1VOSVQFCV9sZXZlcmFnZQkBD2luaXRNYXJnaW5SYXRpbwAGBgkBBnBhdXNlZAAJAAIBAiNJbnZhbGlkIGluY3JlYXNlUG9zaXRpb24gcGFyYW1ldGVycwQQZG9HZXRGZWVEaXNjb3VudAkA/AcECQEMbWluZXJBZGRyZXNzAAISY29tcHV0ZUZlZURpc2NvdW50CQDMCAIFB190cmFkZXIFA25pbAUDbmlsAwkAAAIFEGRvR2V0RmVlRGlzY291bnQFEGRvR2V0RmVlRGlzY291bnQEC2ZlZURpc2NvdW50BAckbWF0Y2gwBRBkb0dldEZlZURpc2NvdW50AwkAAQIFByRtYXRjaDACA0ludAQBeAUHJG1hdGNoMAUBeAkAAgECIUludmFsaWQgY29tcHV0ZUZlZURpc2NvdW50IHJlc3VsdAQNJHQwNTAxMzc1MDIwMQkBDmdldEFkanVzdGVkRmVlAgUBaQULZmVlRGlzY291bnQEC2FkanVzdGVkRmVlCAUNJHQwNTAxMzc1MDIwMQJfMQQMYnVybkFydGlmYWN0CAUNJHQwNTAxMzc1MDIwMQJfMgQMcmF3RmVlQW1vdW50CQEEbXVsZAIFCl9yYXdBbW91bnQFC2FkanVzdGVkRmVlBAdfYW1vdW50CQBlAgUKX3Jhd0Ftb3VudAUMcmF3RmVlQW1vdW50BBNkaXN0cmlidXRlRmVlQW1vdW50AwURaXNDb2xsYXRlcmFsQXNzZXQECGRvQm9ycm93CQD8BwQJARFjb2xsYXRlcmFsQWRkcmVzcwACBmJvcnJvdwkAzAgCBQdfdHJhZGVyBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFCF9hc3NldElkBQdfYW1vdW50BQNuaWwDCQAAAgUIZG9Cb3Jyb3cFCGRvQm9ycm93BA1iYWxhbmNlQmVmb3JlCQDwBwIFBHRoaXMJAQpxdW90ZUFzc2V0AAMJAAACBQ1iYWxhbmNlQmVmb3JlBQ1iYWxhbmNlQmVmb3JlBAZkb1N3YXAJAPwHBAkBC3N3YXBBZGRyZXNzAAIEc3dhcAkAzAgCCQDYBAEJAQpxdW90ZUFzc2V0AAkAzAgCAAAFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUIX2Fzc2V0SWQFDHJhd0ZlZUFtb3VudAUDbmlsAwkAAAIFBmRvU3dhcAUGZG9Td2FwBAxiYWxhbmNlQWZ0ZXIJAPAHAgUEdGhpcwkBCnF1b3RlQXNzZXQAAwkAAAIFDGJhbGFuY2VBZnRlcgUMYmFsYW5jZUFmdGVyBA9leGNoYW5nZWRBbW91bnQJAGUCBQxiYWxhbmNlQWZ0ZXIFDWJhbGFuY2VCZWZvcmUDCQAAAgUPZXhjaGFuZ2VkQW1vdW50BQ9leGNoYW5nZWRBbW91bnQFD2V4Y2hhbmdlZEFtb3VudAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUMcmF3RmVlQW1vdW50AwkAAAIFE2Rpc3RyaWJ1dGVGZWVBbW91bnQFE2Rpc3RyaWJ1dGVGZWVBbW91bnQEDnJlZmVycmVyRmVlQW55CQD8BwQJAQ9yZWZlcnJhbEFkZHJlc3MAAhVhY2NlcHRQYXltZW50V2l0aExpbmsJAMwIAgUHX3RyYWRlcgkAzAgCBQhfcmVmTGluawUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFE2Rpc3RyaWJ1dGVGZWVBbW91bnQFA25pbAMJAAACBQ5yZWZlcnJlckZlZUFueQUOcmVmZXJyZXJGZWVBbnkEC3JlZmVycmVyRmVlBAckbWF0Y2gwBQ5yZWZlcnJlckZlZUFueQMJAAECBQckbWF0Y2gwAgNJbnQEAXgFByRtYXRjaDAFAXgJAAIBAhNJbnZhbGlkIHJlZmVycmVyRmVlBAlmZWVBbW91bnQJAGUCBRNkaXN0cmlidXRlRmVlQW1vdW50BQtyZWZlcnJlckZlZQQNJHQwNTE1MTc1MTY1NwkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQPb2xkUG9zaXRpb25TaXplCAUNJHQwNTE1MTc1MTY1NwJfMQQRb2xkUG9zaXRpb25NYXJnaW4IBQ0kdDA1MTUxNzUxNjU3Al8yBBdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDUxNTE3NTE2NTcCXzMEFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwNTE1MTc1MTY1NwJfNAQNaXNOZXdQb3NpdGlvbgkAAAIFD29sZFBvc2l0aW9uU2l6ZQAABA9pc1NhbWVEaXJlY3Rpb24DCQBmAgUPb2xkUG9zaXRpb25TaXplAAAJAAACBQpfZGlyZWN0aW9uBQhESVJfTE9ORwkAAAIFCl9kaXJlY3Rpb24FCURJUl9TSE9SVAQOZXhwYW5kRXhpc3RpbmcDCQEBIQEFDWlzTmV3UG9zaXRpb24FD2lzU2FtZURpcmVjdGlvbgcEBWlzQWRkCQAAAgUKX2RpcmVjdGlvbgUIRElSX0xPTkcEDSR0MDUxOTQ2NTQ1MzEDAwUNaXNOZXdQb3NpdGlvbgYFDmV4cGFuZEV4aXN0aW5nBAxvcGVuTm90aW9uYWwJAQRtdWxkAgUHX2Ftb3VudAUJX2xldmVyYWdlBA0kdDA1MjM3MDUyNTc2CQEJc3dhcElucHV0AgUFaXNBZGQFDG9wZW5Ob3Rpb25hbAQVYW1vdW50QmFzZUFzc2V0Qm91Z2h0CAUNJHQwNTIzNzA1MjU3NgJfMQQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDUyMzcwNTI1NzYCXzIEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDUyMzcwNTI1NzYCXzMEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA1MjM3MDUyNTc2Al80BBdjdW11bGF0aXZlTm90aW9uYWxBZnRlcggFDSR0MDUyMzcwNTI1NzYCXzUDAwkBAiE9AgUTX21pbkJhc2VBc3NldEFtb3VudAAACQBmAgUTX21pbkJhc2VBc3NldEFtb3VudAkBA2FicwEFFWFtb3VudEJhc2VBc3NldEJvdWdodAcJAAIBCQCsAgIJAKwCAgkArAICAg1MaW1pdCBlcnJvcjogCQCkAwEJAQNhYnMBBRVhbW91bnRCYXNlQXNzZXRCb3VnaHQCAyA8IAkApAMBBRNfbWluQmFzZUFzc2V0QW1vdW50BA9uZXdQb3NpdGlvblNpemUJAGQCBQ9vbGRQb3NpdGlvblNpemUFFWFtb3VudEJhc2VBc3NldEJvdWdodAQZaW5jcmVhc2VNYXJnaW5SZXF1aXJlbWVudAkBBGRpdmQCBQxvcGVuTm90aW9uYWwFCV9sZXZlcmFnZQQNJHQwNTI5NTc1MzE5NgkBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEBQ9vbGRQb3NpdGlvblNpemUFEW9sZFBvc2l0aW9uTWFyZ2luBRRvbGRQb3NpdGlvbkxzdFVwZENQRgUZaW5jcmVhc2VNYXJnaW5SZXF1aXJlbWVudAQMcmVtYWluTWFyZ2luCAUNJHQwNTI5NTc1MzE5NgJfMQQCeDEIBQ0kdDA1Mjk1NzUzMTk2Al8yBAJ4MggFDSR0MDUyOTU3NTMxOTYCXzMDCQEBIQEJARlyZXF1aXJlTm90T3ZlclNwcmVhZExpbWl0AgUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCQACAQIVT3ZlciBtYXggc3ByZWFkIGxpbWl0CQCdCgsFD25ld1Bvc2l0aW9uU2l6ZQUMcmVtYWluTWFyZ2luCQBkAgUXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwFDG9wZW5Ob3Rpb25hbAkBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BBQ9uZXdQb3NpdGlvblNpemUFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgUXY3VtdWxhdGl2ZU5vdGlvbmFsQWZ0ZXIJAGQCCQEUb3BlbkludGVyZXN0Tm90aW9uYWwABQxvcGVuTm90aW9uYWwJAGQCCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAMJAGYCBQ9uZXdQb3NpdGlvblNpemUAAAkBA2FicwEFFWFtb3VudEJhc2VBc3NldEJvdWdodAAACQBkAgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUAAwkAZgIAAAUPbmV3UG9zaXRpb25TaXplCQEDYWJzAQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0AAAEDG9wZW5Ob3Rpb25hbAkBBG11bGQCBQdfYW1vdW50BQlfbGV2ZXJhZ2UEDSR0MDU0MjI0NTQzNDAJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIJAKUIAQgFAWkGY2FsbGVyBQ9QTkxfT1BUSU9OX1NQT1QEE29sZFBvc2l0aW9uTm90aW9uYWwIBQ0kdDA1NDIyNDU0MzQwAl8xBA11bnJlYWxpemVkUG5sCAUNJHQwNTQyMjQ1NDM0MAJfMgMJAGYCBRNvbGRQb3NpdGlvbk5vdGlvbmFsBQxvcGVuTm90aW9uYWwJAAIBAi5Vc2UgZGVjcmVhc2VQb3NpdGlvbiB0byBkZWNyZWFzZSBwb3NpdGlvbiBzaXplCQACAQIUQ2xvc2UgcG9zaXRpb24gZmlyc3QED25ld1Bvc2l0aW9uU2l6ZQgFDSR0MDUxOTQ2NTQ1MzECXzEEF25ld1Bvc2l0aW9uUmVtYWluTWFyZ2luCAUNJHQwNTE5NDY1NDUzMQJfMgQXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA1MTk0NjU0NTMxAl8zBBRuZXdQb3NpdGlvbkxhdGVzdENQRggFDSR0MDUxOTQ2NTQ1MzECXzQEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDUxOTQ2NTQ1MzECXzUEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA1MTk0NjU0NTMxAl82BBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNTE5NDY1NDUzMQJfNwQXY3VtdWxhdGl2ZU5vdGlvbmFsQWZ0ZXIIBQ0kdDA1MTk0NjU0NTMxAl84BBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCAUNJHQwNTE5NDY1NDUzMQJfOQQOdG90YWxMb25nQWZ0ZXIIBQ0kdDA1MTk0NjU0NTMxA18xMAQPdG90YWxTaG9ydEFmdGVyCAUNJHQwNTE5NDY1NDUzMQNfMTEEDGZlZVRvU3Rha2VycwkAaQIFCWZlZUFtb3VudAACBA5mZWVUb0luc3VyYW5jZQkAZQIFCWZlZUFtb3VudAUMZmVlVG9TdGFrZXJzBAVzdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIJYWRkTG9ja2VkBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUHX2Ftb3VudAUDbmlsAwkAAAIFBXN0YWtlBQVzdGFrZQQQZGVwb3NpdEluc3VyYW5jZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIHYWRkRnJlZQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFDmZlZVRvSW5zdXJhbmNlBQNuaWwDCQAAAgUQZGVwb3NpdEluc3VyYW5jZQUQZGVwb3NpdEluc3VyYW5jZQQJbm90aWZ5RmVlCQD8BwQJAQxtaW5lckFkZHJlc3MAAgpub3RpZnlGZWVzCQDMCAIFB190cmFkZXIJAMwIAgUJZmVlQW1vdW50BQNuaWwFA25pbAMJAAACBQlub3RpZnlGZWUFCW5vdGlmeUZlZQQObm90aWZ5Tm90aW9uYWwJAPwHBAkBDG1pbmVyQWRkcmVzcwACDm5vdGlmeU5vdGlvbmFsCQDMCAIFB190cmFkZXIJAMwIAgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFA25pbAUDbmlsAwkAAAIFDm5vdGlmeU5vdGlvbmFsBQ5ub3RpZnlOb3Rpb25hbAkAzggCCQDOCAIJAM4IAgkAzggCCQDOCAIJAQ51cGRhdGVQb3NpdGlvbgUFB190cmFkZXIFD25ld1Bvc2l0aW9uU2l6ZQUXbmV3UG9zaXRpb25SZW1haW5NYXJnaW4FF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBRRuZXdQb3NpdGlvbkxhdGVzdENQRgkBE3VwZGF0ZVBvc2l0aW9uQXNzZXQCBQdfdHJhZGVyBQtfYXNzZXRJZFN0cgkBCXVwZGF0ZUFtbQcFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgUXY3VtdWxhdGl2ZU5vdGlvbmFsQWZ0ZXIFGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIFDnRvdGFsTG9uZ0FmdGVyBQ90b3RhbFNob3J0QWZ0ZXIJAQt0cmFuc2ZlckZlZQEFDGZlZVRvU3Rha2VycwkBDXVwZGF0ZUJhbGFuY2UBCQBkAgkBCGNiYWxhbmNlAAUHX2Ftb3VudAkBDmRvQnVybkFydGlmYWN0AgUMYnVybkFydGlmYWN0BQFpCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCWFkZE1hcmdpbgAEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQHX3RyYWRlcgkApQgBCAUBaQZjYWxsZXIECl9yYXdBbW91bnQICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50BAhfYXNzZXRJZAgJAJEDAggFAWkIcGF5bWVudHMAAAdhc3NldElkBAtfYXNzZXRJZFN0cgkA2AQBCQEFdmFsdWUBBQhfYXNzZXRJZAQMaXNRdW90ZUFzc2V0CQAAAgUIX2Fzc2V0SWQJAQpxdW90ZUFzc2V0AAQRaXNDb2xsYXRlcmFsQXNzZXQJARBpc1doaXRlbGlzdEFzc2V0AQULX2Fzc2V0SWRTdHIDAwMDAwMJAQEhAQUMaXNRdW90ZUFzc2V0CQEBIQEFEWlzQ29sbGF0ZXJhbEFzc2V0BwYJAQEhAQkBE3JlcXVpcmVPcGVuUG9zaXRpb24BCQClCAEIBQFpBmNhbGxlcgYJAQEhAQkBC2lzU2FtZUFzc2V0AgUHX3RyYWRlcgULX2Fzc2V0SWRTdHIGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAkAAgECHEludmFsaWQgYWRkTWFyZ2luIHBhcmFtZXRlcnMEEGRvR2V0RmVlRGlzY291bnQJAPwHBAkBDG1pbmVyQWRkcmVzcwACEmNvbXB1dGVGZWVEaXNjb3VudAkAzAgCBQdfdHJhZGVyBQNuaWwFA25pbAMJAAACBRBkb0dldEZlZURpc2NvdW50BRBkb0dldEZlZURpc2NvdW50BAtmZWVEaXNjb3VudAQHJG1hdGNoMAUQZG9HZXRGZWVEaXNjb3VudAMJAAECBQckbWF0Y2gwAgNJbnQEAXgFByRtYXRjaDAFAXgJAAIBAiFJbnZhbGlkIGNvbXB1dGVGZWVEaXNjb3VudCByZXN1bHQEDSR0MDU2NjA4NTY2NzIJAQ5nZXRBZGp1c3RlZEZlZQIFAWkFC2ZlZURpc2NvdW50BAthZGp1c3RlZEZlZQgFDSR0MDU2NjA4NTY2NzICXzEEDGJ1cm5BcnRpZmFjdAgFDSR0MDU2NjA4NTY2NzICXzIEDHJhd0ZlZUFtb3VudAkBBG11bGQCBQpfcmF3QW1vdW50BQthZGp1c3RlZEZlZQQHX2Ftb3VudAkAZQIFCl9yYXdBbW91bnQFDHJhd0ZlZUFtb3VudAQTZGlzdHJpYnV0ZUZlZUFtb3VudAMFEWlzQ29sbGF0ZXJhbEFzc2V0BAhkb0JvcnJvdwkA/AcECQERY29sbGF0ZXJhbEFkZHJlc3MAAgZib3Jyb3cJAMwIAgUHX3RyYWRlcgUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQhfYXNzZXRJZAUHX2Ftb3VudAUDbmlsAwkAAAIFCGRvQm9ycm93BQhkb0JvcnJvdwQNYmFsYW5jZUJlZm9yZQkA8AcCBQR0aGlzCQEKcXVvdGVBc3NldAADCQAAAgUNYmFsYW5jZUJlZm9yZQUNYmFsYW5jZUJlZm9yZQQGZG9Td2FwCQD8BwQJAQtzd2FwQWRkcmVzcwACBHN3YXAJAMwIAgkA2AQBCQEKcXVvdGVBc3NldAAJAMwIAgAABQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFCF9hc3NldElkBQxyYXdGZWVBbW91bnQFA25pbAMJAAACBQZkb1N3YXAFBmRvU3dhcAQMYmFsYW5jZUFmdGVyCQDwBwIFBHRoaXMJAQpxdW90ZUFzc2V0AAMJAAACBQxiYWxhbmNlQWZ0ZXIFDGJhbGFuY2VBZnRlcgQPZXhjaGFuZ2VkQW1vdW50CQBlAgUMYmFsYW5jZUFmdGVyBQ1iYWxhbmNlQmVmb3JlAwkAAAIFD2V4Y2hhbmdlZEFtb3VudAUPZXhjaGFuZ2VkQW1vdW50BQ9leGNoYW5nZWRBbW91bnQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FDHJhd0ZlZUFtb3VudAMJAAACBRNkaXN0cmlidXRlRmVlQW1vdW50BRNkaXN0cmlidXRlRmVlQW1vdW50BA5yZWZlcnJlckZlZUFueQkA/AcECQEPcmVmZXJyYWxBZGRyZXNzAAINYWNjZXB0UGF5bWVudAkAzAgCBQdfdHJhZGVyBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUTZGlzdHJpYnV0ZUZlZUFtb3VudAUDbmlsAwkAAAIFDnJlZmVycmVyRmVlQW55BQ5yZWZlcnJlckZlZUFueQQLcmVmZXJyZXJGZWUEByRtYXRjaDAFDnJlZmVycmVyRmVlQW55AwkAAQIFByRtYXRjaDACA0ludAQBeAUHJG1hdGNoMAUBeAkAAgECE0ludmFsaWQgcmVmZXJyZXJGZWUECWZlZUFtb3VudAkAZQIFE2Rpc3RyaWJ1dGVGZWVBbW91bnQFC3JlZmVycmVyRmVlBA0kdDA1Nzk3MTU4MTExCQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBA9vbGRQb3NpdGlvblNpemUIBQ0kdDA1Nzk3MTU4MTExAl8xBBFvbGRQb3NpdGlvbk1hcmdpbggFDSR0MDU3OTcxNTgxMTECXzIEF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNTc5NzE1ODExMQJfMwQUb2xkUG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA1Nzk3MTU4MTExAl80BAxmZWVUb1N0YWtlcnMJAGkCBQlmZWVBbW91bnQAAgQOZmVlVG9JbnN1cmFuY2UJAGUCBQlmZWVBbW91bnQFDGZlZVRvU3Rha2VycwQFc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACCWFkZExvY2tlZAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFB19hbW91bnQFA25pbAMJAAACBQVzdGFrZQUFc3Rha2UEEGRlcG9zaXRJbnN1cmFuY2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACB2FkZEZyZWUFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABQ5mZWVUb0luc3VyYW5jZQUDbmlsAwkAAAIFEGRlcG9zaXRJbnN1cmFuY2UFEGRlcG9zaXRJbnN1cmFuY2UECW5vdGlmeUZlZQkA/AcECQEMbWluZXJBZGRyZXNzAAIKbm90aWZ5RmVlcwkAzAgCBQdfdHJhZGVyCQDMCAIFCWZlZUFtb3VudAUDbmlsBQNuaWwDCQAAAgUJbm90aWZ5RmVlBQlub3RpZnlGZWUJAM4IAgkAzggCCQDOCAIJAQ51cGRhdGVQb3NpdGlvbgUFB190cmFkZXIFD29sZFBvc2l0aW9uU2l6ZQkAZAIFEW9sZFBvc2l0aW9uTWFyZ2luBQdfYW1vdW50BRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAUUb2xkUG9zaXRpb25Mc3RVcGRDUEYJAQt0cmFuc2ZlckZlZQEFDGZlZVRvU3Rha2VycwkBDXVwZGF0ZUJhbGFuY2UBCQBkAgkBCGNiYWxhbmNlAAUHX2Ftb3VudAkBDmRvQnVybkFydGlmYWN0AgUMYnVybkFydGlmYWN0BQFpCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDHJlbW92ZU1hcmdpbgEHX2Ftb3VudAQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBAdfdHJhZGVyCQClCAEIBQFpBmNhbGxlcgMDAwMJAGcCAAAFB19hbW91bnQGCQEBIQEJARNyZXF1aXJlT3BlblBvc2l0aW9uAQUHX3RyYWRlcgYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQZwYXVzZWQACQACAQIfSW52YWxpZCByZW1vdmVNYXJnaW4gcGFyYW1ldGVycwQNJHQwNTkyMTc1OTM1NwkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQPb2xkUG9zaXRpb25TaXplCAUNJHQwNTkyMTc1OTM1NwJfMQQRb2xkUG9zaXRpb25NYXJnaW4IBQ0kdDA1OTIxNzU5MzU3Al8yBBdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDU5MjE3NTkzNTcCXzMEFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwNTkyMTc1OTM1NwJfNAQLbWFyZ2luRGVsdGEJAQEtAQUHX2Ftb3VudAQNJHQwNTkzOTQ1OTU3MwkBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEBQ9vbGRQb3NpdGlvblNpemUFEW9sZFBvc2l0aW9uTWFyZ2luBRRvbGRQb3NpdGlvbkxzdFVwZENQRgULbWFyZ2luRGVsdGEEDHJlbWFpbk1hcmdpbggFDSR0MDU5Mzk0NTk1NzMCXzEEB2JhZERlYnQIBQ0kdDA1OTM5NDU5NTczAl8yAwkBAiE9AgUHYmFkRGVidAAACQACAQIdSW52YWxpZCByZW1vdmVkIG1hcmdpbiBhbW91bnQEC21hcmdpblJhdGlvCQEPY2FsY01hcmdpblJhdGlvAwUMcmVtYWluTWFyZ2luBQdiYWREZWJ0BRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAMJAQEhAQkBFnJlcXVpcmVNb3JlTWFyZ2luUmF0aW8DBQttYXJnaW5SYXRpbwkBD2luaXRNYXJnaW5SYXRpbwAGCQACAQkArAICCQCsAgIJAKwCAgIZVG9vIG11Y2ggbWFyZ2luIHJlbW92ZWQ6IAkApAMBBQttYXJnaW5SYXRpbwIDIDwgCQCkAwEJAQ9pbml0TWFyZ2luUmF0aW8ABA1xdW90ZUFzc2V0U3RyCQDYBAEJAQpxdW90ZUFzc2V0AAQNJHQwNjAwMTc2MDA3MQkBE2dldEJvcnJvd2VkQnlUcmFkZXIBBQdfdHJhZGVyBAhib3Jyb3dlZAgFDSR0MDYwMDE3NjAwNzECXzEEB2Fzc2V0SWQIBQ0kdDA2MDAxNzYwMDcxAl8yBAd0b1JlcGF5AwkAZgIFB19hbW91bnQFCGJvcnJvd2VkBQhib3Jyb3dlZAUHX2Ftb3VudAQKdG9XaXRoZHJhdwMJAGYCBQhib3Jyb3dlZAUHX2Ftb3VudAAACQBlAgUHX2Ftb3VudAUIYm9ycm93ZWQEC2ZpbmFsQm9ycm93CQBlAgUIYm9ycm93ZWQFB3RvUmVwYXkEFXN3aXRjaFBvc2l0aW9uVG9RdW90ZQMJAGYCBQtmaW5hbEJvcnJvdwAABQNuaWwJARN1cGRhdGVQb3NpdGlvbkFzc2V0AgUHX3RyYWRlcgUNcXVvdGVBc3NldFN0cgQNZG9TYW5pdHlDaGVjawMJAQIhPQIJAGQCBQd0b1JlcGF5BQp0b1dpdGhkcmF3BQdfYW1vdW50CQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgICCHRvUmVwYXk9CQCkAwEFB3RvUmVwYXkCDiArIHRvV2l0aGRyYXc9CQCkAwEFCnRvV2l0aGRyYXcCBCAhPSAJAKQDAQUHX2Ftb3VudAUDbmlsAwkAAAIFDWRvU2FuaXR5Q2hlY2sFDWRvU2FuaXR5Q2hlY2sECWRvVW5zdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIOd2l0aGRyYXdMb2NrZWQJAMwIAgUHX2Ftb3VudAUDbmlsBQNuaWwDCQAAAgUJZG9VbnN0YWtlBQlkb1Vuc3Rha2UEFnJldHVybkNvbGxhdGVyYWxBY3Rpb24DCQBmAgUHdG9SZXBheQAABAdkb1JlcGF5CQD8BwQJARFjb2xsYXRlcmFsQWRkcmVzcwACBXJlcGF5CQDMCAIFB190cmFkZXIJAMwIAgUHYXNzZXRJZAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFB3RvUmVwYXkFA25pbAMJAAACBQdkb1JlcGF5BQdkb1JlcGF5CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgUHdG9SZXBheQkA2QQBBQdhc3NldElkBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBRZyZXR1cm5Db2xsYXRlcmFsQWN0aW9uBRZyZXR1cm5Db2xsYXRlcmFsQWN0aW9uCQDOCAIJAM4IAgkAzggCCQDOCAIJAQ51cGRhdGVQb3NpdGlvbgUFB190cmFkZXIFD29sZFBvc2l0aW9uU2l6ZQUMcmVtYWluTWFyZ2luBRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAkBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BBQ9vbGRQb3NpdGlvblNpemUDCQBmAgUKdG9XaXRoZHJhdwAACQEId2l0aGRyYXcCCAUBaQZjYWxsZXIFCnRvV2l0aGRyYXcFA25pbAkBDXVwZGF0ZUJhbGFuY2UBCQBlAgkBCGNiYWxhbmNlAAUHX2Ftb3VudAUVc3dpdGNoUG9zaXRpb25Ub1F1b3RlBRZyZXR1cm5Db2xsYXRlcmFsQWN0aW9uCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDWNsb3NlUG9zaXRpb24ABARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEB190cmFkZXIJAQ9nZXRBY3R1YWxDYWxsZXIBBQFpBA5fdHJhZGVyQWRkcmVzcwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEFB190cmFkZXICDkludmFsaWQgY2FsbGVyAwMDCQEBIQEJARNyZXF1aXJlT3BlblBvc2l0aW9uAQUHX3RyYWRlcgYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQZwYXVzZWQACQACAQIgSW52YWxpZCBjbG9zZVBvc2l0aW9uIHBhcmFtZXRlcnMEDSR0MDYyMzIxNjI2OTkJARVpbnRlcm5hbENsb3NlUG9zaXRpb24CBQdfdHJhZGVyBgQCeDEIBQ0kdDA2MjMyMTYyNjk5Al8xBA9wb3NpdGlvbkJhZERlYnQIBQ0kdDA2MjMyMTYyNjk5Al8yBAtyZWFsaXplZFBubAgFDSR0MDYyMzIxNjI2OTkCXzMEDW1hcmdpblRvVmF1bHQIBQ0kdDA2MjMyMTYyNjk5Al80BBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNjIzMjE2MjY5OQJfNQQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNjIzMjE2MjY5OQJfNgQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDYyMzIxNjI2OTkCXzcEF2N1bXVsYXRpdmVOb3Rpb25hbEFmdGVyCAUNJHQwNjIzMjE2MjY5OQJfOAQZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcggFDSR0MDYyMzIxNjI2OTkCXzkEAngyCAUNJHQwNjIzMjE2MjY5OQNfMTAEDnRvdGFsTG9uZ0FmdGVyCAUNJHQwNjIzMjE2MjY5OQNfMTEED3RvdGFsU2hvcnRBZnRlcggFDSR0MDYyMzIxNjI2OTkDXzEyAwkAZgIFD3Bvc2l0aW9uQmFkRGVidAAACQACAQImVW5hYmxlIHRvIGNsb3NlIHBvc2l0aW9uIHdpdGggYmFkIGRlYnQEDndpdGhkcmF3QW1vdW50CQEDYWJzAQUNbWFyZ2luVG9WYXVsdAQKYW1tQmFsYW5jZQkAZQIJAQhjYmFsYW5jZQAFDndpdGhkcmF3QW1vdW50BA0kdDA2MzAyMzYzNTM4AwkAZgIAAAUKYW1tQmFsYW5jZQkAlAoCAAAJAQNhYnMBBQphbW1CYWxhbmNlCQCUCgIFCmFtbUJhbGFuY2UAAAQNYW1tTmV3QmFsYW5jZQgFDSR0MDYzMDIzNjM1MzgCXzEEA3gxMQgFDSR0MDYzMDIzNjM1MzgCXzIEB3Vuc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACDndpdGhkcmF3TG9ja2VkCQDMCAIFDndpdGhkcmF3QW1vdW50BQNuaWwFA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlBA0kdDA2Mzc1MDYzODA0CQETZ2V0Qm9ycm93ZWRCeVRyYWRlcgEFB190cmFkZXIECGJvcnJvd2VkCAUNJHQwNjM3NTA2MzgwNAJfMQQHYXNzZXRJZAgFDSR0MDYzNzUwNjM4MDQCXzIEDSR0MDYzODE5NjQ3MzYDCQBmAgUIYm9ycm93ZWQAAAMJAGcCBQ53aXRoZHJhd0Ftb3VudAUIYm9ycm93ZWQEB2RvUmVwYXkJAPwHBAkBEWNvbGxhdGVyYWxBZGRyZXNzAAIFcmVwYXkJAMwIAgUHX3RyYWRlcgkAzAgCBQdhc3NldElkBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUIYm9ycm93ZWQFA25pbAMJAAACBQdkb1JlcGF5BQdkb1JlcGF5CQCUCgIJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUOX3RyYWRlckFkZHJlc3MFCGJvcnJvd2VkCQDZBAEFB2Fzc2V0SWQFA25pbAkAZQIFDndpdGhkcmF3QW1vdW50BQhib3Jyb3dlZAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgQPcmVhbGl6ZUFuZENsb3NlCQD8BwQJARFjb2xsYXRlcmFsQWRkcmVzcwACGHJlYWxpemVQYXJ0aWFsbHlBbmRDbG9zZQkAzAgCBQdfdHJhZGVyCQDMCAIFB2Fzc2V0SWQFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABQ53aXRoZHJhd0Ftb3VudAUDbmlsAwkAAAIFD3JlYWxpemVBbmRDbG9zZQUPcmVhbGl6ZUFuZENsb3NlCQCUCgIJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUOX3RyYWRlckFkZHJlc3MFDndpdGhkcmF3QW1vdW50CQDZBAEFB2Fzc2V0SWQFA25pbAAACQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQCUCgIFA25pbAUOd2l0aGRyYXdBbW91bnQDCQAAAgUNJHQwNjM4MTk2NDczNgUNJHQwNjM4MTk2NDczNgQTcXVvdGVXaXRoZHJhd0Ftb3VudAgFDSR0MDYzODE5NjQ3MzYCXzIEFHNlbmRDb2xsYXRlcmFsQWN0aW9uCAUNJHQwNjM4MTk2NDczNgJfMQQObm90aWZ5Tm90aW9uYWwJAPwHBAkBDG1pbmVyQWRkcmVzcwACDm5vdGlmeU5vdGlvbmFsCQDMCAIFB190cmFkZXIJAMwIAgAABQNuaWwFA25pbAMJAAACBQ5ub3RpZnlOb3Rpb25hbAUObm90aWZ5Tm90aW9uYWwJAM4IAgkAzggCCQDOCAIJAM4IAgkBDmRlbGV0ZVBvc2l0aW9uAQUHX3RyYWRlcgkBCXVwZGF0ZUFtbQcFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgUXY3VtdWxhdGl2ZU5vdGlvbmFsQWZ0ZXIFGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIFDnRvdGFsTG9uZ0FmdGVyBQ90b3RhbFNob3J0QWZ0ZXIDCQBmAgUTcXVvdGVXaXRoZHJhd0Ftb3VudAAACQEId2l0aGRyYXcCBQ5fdHJhZGVyQWRkcmVzcwUTcXVvdGVXaXRoZHJhd0Ftb3VudAUDbmlsCQENdXBkYXRlQmFsYW5jZQEFDWFtbU5ld0JhbGFuY2UFFHNlbmRDb2xsYXRlcmFsQWN0aW9uCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCWxpcXVpZGF0ZQEHX3RyYWRlcgQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBA9zcG90TWFyZ2luUmF0aW8JARZnZXRNYXJnaW5SYXRpb0J5T3B0aW9uAgUHX3RyYWRlcgUPUE5MX09QVElPTl9TUE9UBAttYXJnaW5SYXRpbwMJARZpc092ZXJGbHVjdHVhdGlvbkxpbWl0AAQRb3JhY2xlTWFyZ2luUmF0aW8JARZnZXRNYXJnaW5SYXRpb0J5T3B0aW9uAgUHX3RyYWRlcgURUE5MX09QVElPTl9PUkFDTEUJAQR2bWF4AgUPc3BvdE1hcmdpblJhdGlvBRFvcmFjbGVNYXJnaW5SYXRpbwUPc3BvdE1hcmdpblJhdGlvAwMDAwkBASEBCQEWcmVxdWlyZU1vcmVNYXJnaW5SYXRpbwMFC21hcmdpblJhdGlvCQEWbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwAHBgkBASEBCQETcmVxdWlyZU9wZW5Qb3NpdGlvbgEFB190cmFkZXIGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAkAAgECE1VuYWJsZSB0byBsaXF1aWRhdGUDAwMJAGYCBQ9zcG90TWFyZ2luUmF0aW8JARNsaXF1aWRhdGlvbkZlZVJhdGlvAAkAZgIJARdwYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwAAAAcJAGYCBQxERUNJTUFMX1VOSVQJARdwYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwAHBA0kdDA2NjUwNDY2NjU0CQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBA9vbGRQb3NpdGlvblNpemUIBQ0kdDA2NjUwNDY2NjU0Al8xBBFvbGRQb3NpdGlvbk1hcmdpbggFDSR0MDY2NTA0NjY2NTQCXzIEF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNjY1MDQ2NjY1NAJfMwQUb2xkUG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA2NjUwNDY2NjU0Al80BApfZGlyZWN0aW9uAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAABQlESVJfU0hPUlQFCERJUl9MT05HBAVpc0FkZAkAAAIFCl9kaXJlY3Rpb24FCERJUl9MT05HBBlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CQEbZ2V0UGFydGlhbExpcXVpZGF0aW9uQW1vdW50AgUHX3RyYWRlcgUPb2xkUG9zaXRpb25TaXplBA0kdDA2Njg3OTY2OTgzCQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QEE29sZFBvc2l0aW9uTm90aW9uYWwIBQ0kdDA2Njg3OTY2OTgzAl8xBA11bnJlYWxpemVkUG5sCAUNJHQwNjY4Nzk2Njk4MwJfMgQNJHQwNjY5OTE2NzIyMwkBCXN3YXBJbnB1dAIFBWlzQWRkBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BBVleGNoYW5nZWRQb3NpdGlvblNpemUIBQ0kdDA2Njk5MTY3MjIzAl8xBBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNjY5OTE2NzIyMwJfMgQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNjY5OTE2NzIyMwJfMwQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDY2OTkxNjcyMjMCXzQEF2N1bXVsYXRpdmVOb3Rpb25hbEFmdGVyCAUNJHQwNjY5OTE2NzIyMwJfNQQQbGlxdWlkYXRpb25SYXRpbwkBBGRpdmQCCQEDYWJzAQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplCQEDYWJzAQUPb2xkUG9zaXRpb25TaXplBAtyZWFsaXplZFBubAkBBG11bGQCBQ11bnJlYWxpemVkUG5sBRBsaXF1aWRhdGlvblJhdGlvBA0kdDA2NzUxMjY3NzQ1CQEiY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudAQFD29sZFBvc2l0aW9uU2l6ZQURb2xkUG9zaXRpb25NYXJnaW4FFG9sZFBvc2l0aW9uTHN0VXBkQ1BGBQtyZWFsaXplZFBubAQMcmVtYWluTWFyZ2luCAUNJHQwNjc1MTI2Nzc0NQJfMQQHYmFkRGVidAgFDSR0MDY3NTEyNjc3NDUCXzIEDmZ1bmRpbmdQYXltZW50CAUNJHQwNjc1MTI2Nzc0NQJfMwQSdW5yZWFsaXplZFBubEFmdGVyCQBlAgUNdW5yZWFsaXplZFBubAULcmVhbGl6ZWRQbmwEEnJlbWFpbk9wZW5Ob3Rpb25hbAMJAGYCBQ9vbGRQb3NpdGlvblNpemUAAAkAZQIJAGUCBRNvbGRQb3NpdGlvbk5vdGlvbmFsBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BRJ1bnJlYWxpemVkUG5sQWZ0ZXIJAGUCCQBkAgUSdW5yZWFsaXplZFBubEFmdGVyBRNvbGRQb3NpdGlvbk5vdGlvbmFsBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BBJsaXF1aWRhdGlvblBlbmFsdHkJAQRtdWxkAgUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAkBE2xpcXVpZGF0aW9uRmVlUmF0aW8ABA9mZWVUb0xpcXVpZGF0b3IJAGkCBRJsaXF1aWRhdGlvblBlbmFsdHkAAgQOZmVlVG9JbnN1cmFuY2UJAGUCBRJsaXF1aWRhdGlvblBlbmFsdHkFD2ZlZVRvTGlxdWlkYXRvcgQRbmV3UG9zaXRpb25NYXJnaW4JAGUCBQxyZW1haW5NYXJnaW4FEmxpcXVpZGF0aW9uUGVuYWx0eQQPbmV3UG9zaXRpb25TaXplCQBkAgUPb2xkUG9zaXRpb25TaXplBRVleGNoYW5nZWRQb3NpdGlvblNpemUEF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsCQEDYWJzAQUScmVtYWluT3Blbk5vdGlvbmFsBBRuZXdQb3NpdGlvbkxzdFVwZENQRgkBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BBQ9uZXdQb3NpdGlvblNpemUEGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIJAGUCCQEUb3BlbkludGVyZXN0Tm90aW9uYWwABRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BAphbW1CYWxhbmNlCQBlAgkBCGNiYWxhbmNlAAUSbGlxdWlkYXRpb25QZW5hbHR5BA0kdDA2ODkxODY5MDQ3AwkAZgIAAAUKYW1tQmFsYW5jZQkAlAoCAAAJAQNhYnMBBQphbW1CYWxhbmNlCQCUCgIFCmFtbUJhbGFuY2UAAAQNbmV3QW1tQmFsYW5jZQgFDSR0MDY4OTE4NjkwNDcCXzEEA3gxMQgFDSR0MDY4OTE4NjkwNDcCXzIEDSR0MDY5MDU1NjkxMDkJARNnZXRCb3Jyb3dlZEJ5VHJhZGVyAQUHX3RyYWRlcgQIYm9ycm93ZWQIBQ0kdDA2OTA1NTY5MTA5Al8xBAdhc3NldElkCAUNJHQwNjkwNTU2OTEwOQJfMgQVZG9MaXF1aWRhdGVDb2xsYXRlcmFsAwkAZgIFCGJvcnJvd2VkAAAEEGNvbGxhdGVyYWxUb1NlbGwJAQRtdWxkAgUIYm9ycm93ZWQFEGxpcXVpZGF0aW9uUmF0aW8ED3JlYWxpemVBbmRDbG9zZQkA/AcECQERY29sbGF0ZXJhbEFkZHJlc3MAAhByZWFsaXplUGFydGlhbGx5CQDMCAIFB190cmFkZXIJAMwIAgUHYXNzZXRJZAkAzAgCBRBjb2xsYXRlcmFsVG9TZWxsBQNuaWwFA25pbAMJAAACBQ9yZWFsaXplQW5kQ2xvc2UFD3JlYWxpemVBbmRDbG9zZQUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUVZG9MaXF1aWRhdGVDb2xsYXRlcmFsBRVkb0xpcXVpZGF0ZUNvbGxhdGVyYWwEB3Vuc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACDndpdGhkcmF3TG9ja2VkCQDMCAIFEmxpcXVpZGF0aW9uUGVuYWx0eQUDbmlsBQNuaWwDCQAAAgUHdW5zdGFrZQUHdW5zdGFrZQQQZGVwb3NpdEluc3VyYW5jZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIHYWRkRnJlZQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFDmZlZVRvSW5zdXJhbmNlBQNuaWwDCQAAAgUQZGVwb3NpdEluc3VyYW5jZQUQZGVwb3NpdEluc3VyYW5jZQQObm90aWZ5Tm90aW9uYWwJAPwHBAkBDG1pbmVyQWRkcmVzcwACDm5vdGlmeU5vdGlvbmFsCQDMCAIFB190cmFkZXIJAMwIAgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFA25pbAUDbmlsAwkAAAIFDm5vdGlmeU5vdGlvbmFsBQ5ub3RpZnlOb3Rpb25hbAkAzggCCQDOCAIJAM4IAgkBDnVwZGF0ZVBvc2l0aW9uBQUHX3RyYWRlcgUPbmV3UG9zaXRpb25TaXplBRFuZXdQb3NpdGlvbk1hcmdpbgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFFG5ld1Bvc2l0aW9uTHN0VXBkQ1BGCQEJdXBkYXRlQW1tBwUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRdjdW11bGF0aXZlTm90aW9uYWxBZnRlcgUZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcgkAZQIJARV0b3RhbExvbmdQb3NpdGlvblNpemUAAwkAZgIFD25ld1Bvc2l0aW9uU2l6ZQAACQEDYWJzAQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplAAAJAGUCCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQADCQBmAgAABQ9uZXdQb3NpdGlvblNpemUJAQNhYnMBBRVleGNoYW5nZWRQb3NpdGlvblNpemUAAAkBCHdpdGhkcmF3AggFAWkGY2FsbGVyBQ9mZWVUb0xpcXVpZGF0b3IJAQ11cGRhdGVCYWxhbmNlAQUNbmV3QW1tQmFsYW5jZQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgQNJHQwNzA5MTQ3MTM2OQkBFWludGVybmFsQ2xvc2VQb3NpdGlvbgIFB190cmFkZXIHBAJ4MQgFDSR0MDcwOTE0NzEzNjkCXzEEB2JhZERlYnQIBQ0kdDA3MDkxNDcxMzY5Al8yBAJ4MggFDSR0MDcwOTE0NzEzNjkCXzMEAngzCAUNJHQwNzA5MTQ3MTM2OQJfNAQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDcwOTE0NzEzNjkCXzUEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDcwOTE0NzEzNjkCXzYEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA3MDkxNDcxMzY5Al83BBdjdW11bGF0aXZlTm90aW9uYWxBZnRlcggFDSR0MDcwOTE0NzEzNjkCXzgEGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIIBQ0kdDA3MDkxNDcxMzY5Al85BBlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CAUNJHQwNzA5MTQ3MTM2OQNfMTAEDnRvdGFsTG9uZ0FmdGVyCAUNJHQwNzA5MTQ3MTM2OQNfMTEED3RvdGFsU2hvcnRBZnRlcggFDSR0MDcwOTE0NzEzNjkDXzEyBBJsaXF1aWRhdGlvblBlbmFsdHkJAQRtdWxkAgUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAkBE2xpcXVpZGF0aW9uRmVlUmF0aW8ABA9mZWVUb0xpcXVpZGF0b3IJAGkCBRJsaXF1aWRhdGlvblBlbmFsdHkAAgQOZmVlVG9JbnN1cmFuY2UJAGUCBRJsaXF1aWRhdGlvblBlbmFsdHkFD2ZlZVRvTGlxdWlkYXRvcgQKYW1tQmFsYW5jZQkAZQIJAQhjYmFsYW5jZQAFEmxpcXVpZGF0aW9uUGVuYWx0eQQNJHQwNzE3ODE3MTkxMAMJAGYCAAAFCmFtbUJhbGFuY2UJAJQKAgAACQEDYWJzAQUKYW1tQmFsYW5jZQkAlAoCBQphbW1CYWxhbmNlAAAEDW5ld0FtbUJhbGFuY2UIBQ0kdDA3MTc4MTcxOTEwAl8xBAN4MTEIBQ0kdDA3MTc4MTcxOTEwAl8yBA0kdDA3MTkxODcxOTcyCQETZ2V0Qm9ycm93ZWRCeVRyYWRlcgEFB190cmFkZXIECGJvcnJvd2VkCAUNJHQwNzE5MTg3MTk3MgJfMQQHYXNzZXRJZAgFDSR0MDcxOTE4NzE5NzICXzIEFWRvTGlxdWlkYXRlQ29sbGF0ZXJhbAMJAGYCBQhib3Jyb3dlZAAABA9yZWFsaXplQW5kQ2xvc2UJAPwHBAkBEWNvbGxhdGVyYWxBZGRyZXNzAAIYcmVhbGl6ZVBhcnRpYWxseUFuZENsb3NlCQDMCAIFB190cmFkZXIJAMwIAgUHYXNzZXRJZAUDbmlsBQNuaWwDCQAAAgUPcmVhbGl6ZUFuZENsb3NlBQ9yZWFsaXplQW5kQ2xvc2UFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFFWRvTGlxdWlkYXRlQ29sbGF0ZXJhbAUVZG9MaXF1aWRhdGVDb2xsYXRlcmFsBAF4AwkAZgIFB2JhZERlYnQAAAQLbG9ja0JhZERlYnQJAPwHBAkBDHZhdWx0QWRkcmVzcwACFWV4Y2hhbmdlRnJlZUFuZExvY2tlZAkAzAgCBQdiYWREZWJ0BQNuaWwFA25pbAMJAAACBQtsb2NrQmFkRGVidAULbG9ja0JhZERlYnQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFAXgFAXgEB3Vuc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACDndpdGhkcmF3TG9ja2VkCQDMCAIFEmxpcXVpZGF0aW9uUGVuYWx0eQUDbmlsBQNuaWwDCQAAAgUHdW5zdGFrZQUHdW5zdGFrZQQQZGVwb3NpdEluc3VyYW5jZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIHYWRkRnJlZQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFDmZlZVRvSW5zdXJhbmNlBQNuaWwDCQAAAgUQZGVwb3NpdEluc3VyYW5jZQUQZGVwb3NpdEluc3VyYW5jZQQObm90aWZ5Tm90aW9uYWwJAPwHBAkBDG1pbmVyQWRkcmVzcwACDm5vdGlmeU5vdGlvbmFsCQDMCAIFB190cmFkZXIJAMwIAgAABQNuaWwFA25pbAMJAAACBQ5ub3RpZnlOb3Rpb25hbAUObm90aWZ5Tm90aW9uYWwJAM4IAgkAzggCCQDOCAIJAQ5kZWxldGVQb3NpdGlvbgEFB190cmFkZXIJAQl1cGRhdGVBbW0HBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFF2N1bXVsYXRpdmVOb3Rpb25hbEFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyCQEId2l0aGRyYXcCCAUBaQZjYWxsZXIFD2ZlZVRvTGlxdWlkYXRvcgkBDXVwZGF0ZUJhbGFuY2UBBQ1uZXdBbW1CYWxhbmNlCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCnBheUZ1bmRpbmcABBVmdW5kaW5nQmxvY2tUaW1lc3RhbXAJARluZXh0RnVuZGluZ0Jsb2NrVGltZXN0YW1wAAMDAwkAZgIFFWZ1bmRpbmdCbG9ja1RpbWVzdGFtcAgFCWxhc3RCbG9jawl0aW1lc3RhbXAGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAkAAgEJAKwCAgkArAICCQCsAgICIUludmFsaWQgZnVuZGluZyBibG9jayB0aW1lc3RhbXA6IAkApAMBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAIDIDwgCQCkAwEFFWZ1bmRpbmdCbG9ja1RpbWVzdGFtcAQPdW5kZXJseWluZ1ByaWNlCQESZ2V0T3JhY2xlVHdhcFByaWNlAAQNJHQwNzM5OTk3NDA2MQkBCmdldEZ1bmRpbmcABBRzaG9ydFByZW1pdW1GcmFjdGlvbggFDSR0MDczOTk5NzQwNjECXzEEE2xvbmdQcmVtaXVtRnJhY3Rpb24IBQ0kdDA3Mzk5OTc0MDYxAl8yCQENdXBkYXRlRnVuZGluZwUJAGQCBRVmdW5kaW5nQmxvY2tUaW1lc3RhbXAJARRmdW5kaW5nUGVyaW9kU2Vjb25kcwAJAGQCCQEjbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24ABRNsb25nUHJlbWl1bUZyYWN0aW9uCQBkAgkBJGxhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAFFHNob3J0UHJlbWl1bUZyYWN0aW9uCQEEZGl2ZAIFE2xvbmdQcmVtaXVtRnJhY3Rpb24FD3VuZGVybHlpbmdQcmljZQkBBGRpdmQCBRRzaG9ydFByZW1pdW1GcmFjdGlvbgUPdW5kZXJseWluZ1ByaWNlAWkBGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUABA0kdDA3NDQ0Mzc0NTY0CQEUZ2V0U3luY1Rlcm1pbmFsUHJpY2UBCQESZ2V0T3JhY2xlVHdhcFByaWNlAAQTbmV3UXVvdGVBc3NldFdlaWdodAgFDSR0MDc0NDQzNzQ1NjQCXzEEEm5ld0Jhc2VBc3NldFdlaWdodAgFDSR0MDc0NDQzNzQ1NjQCXzIEDW1hcmdpblRvVmF1bHQIBQ0kdDA3NDQ0Mzc0NTY0Al8zCQEQdXBkYXRlQW1tV2VpZ2h0cwIFE25ld1F1b3RlQXNzZXRXZWlnaHQFEm5ld0Jhc2VBc3NldFdlaWdodAFpAQV2X2dldAEHX3RyYWRlcgQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBA0kdDA3NDc0Mjc0ODAyCQEVaW50ZXJuYWxDbG9zZVBvc2l0aW9uAgUHX3RyYWRlcgcEAngxCAUNJHQwNzQ3NDI3NDgwMgJfMQQCeDIIBQ0kdDA3NDc0Mjc0ODAyAl8yBAJ4MwgFDSR0MDc0NzQyNzQ4MDICXzMEAng0CAUNJHQwNzQ3NDI3NDgwMgJfNAkAAgEJAKwCAgkArAICCQCsAgIJAQFzAQUCeDIJAQFzAQUCeDMJAQFzAQUCeDQJAQFzAQkBDmdldE1hcmdpblJhdGlvAQUHX3RyYWRlcgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpASd2aWV3X2NhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQBB190cmFkZXIEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQNJHQwNzUwMTM3NTExNAkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQMcG9zaXRpb25TaXplCAUNJHQwNzUwMTM3NTExNAJfMQQOcG9zaXRpb25NYXJnaW4IBQ0kdDA3NTAxMzc1MTE0Al8yBANwb24IBQ0kdDA3NTAxMzc1MTE0Al8zBBFwb3NpdGlvbkxzdFVwZENQRggFDSR0MDc1MDEzNzUxMTQCXzQEDSR0MDc1MTE3NzUyMTgJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAQQcG9zaXRpb25Ob3Rpb25hbAgFDSR0MDc1MTE3NzUyMTgCXzEEDXVucmVhbGl6ZWRQbmwIBQ0kdDA3NTExNzc1MjE4Al8yBA0kdDA3NTIyMTc1MzkzCQEiY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudAQFDHBvc2l0aW9uU2l6ZQUOcG9zaXRpb25NYXJnaW4FEXBvc2l0aW9uTHN0VXBkQ1BGBQ11bnJlYWxpemVkUG5sBAxyZW1haW5NYXJnaW4IBQ0kdDA3NTIyMTc1MzkzAl8xBAdiYWREZWJ0CAUNJHQwNzUyMjE3NTM5MwJfMgQOZnVuZGluZ1BheW1lbnQIBQ0kdDA3NTIyMTc1MzkzAl8zCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAQFzAQUMcmVtYWluTWFyZ2luCQEBcwEFDmZ1bmRpbmdQYXltZW50CQEBcwEJAQ5nZXRNYXJnaW5SYXRpbwEFB190cmFkZXIJAQFzAQUNdW5yZWFsaXplZFBubAkBAXMBBQdiYWREZWJ0CQEBcwEFEHBvc2l0aW9uTm90aW9uYWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEVdmlld19nZXRQZWdBZGp1c3RDb3N0AQZfcHJpY2UEBnJlc3VsdAkBFGdldFN5bmNUZXJtaW5hbFByaWNlAQUGX3ByaWNlCQACAQkApAMBCAUGcmVzdWx0Al8zAWkBGHZpZXdfZ2V0VGVybWluYWxBbW1QcmljZQAEDSR0MDc1NzQwNzU4MjEJARNnZXRUZXJtaW5hbEFtbVN0YXRlAAQZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQgFDSR0MDc1NzQwNzU4MjECXzEEGHRlcm1pbmFsQmFzZUFzc2V0UmVzZXJ2ZQgFDSR0MDc1NzQwNzU4MjECXzIEBXByaWNlCQEEZGl2ZAIJAQRtdWxkAgUZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQkBBnF0QXN0VwAJAQRtdWxkAgUYdGVybWluYWxCYXNlQXNzZXRSZXNlcnZlCQEGYnNBc3RXAAkAAgEJAKQDAQUFcHJpY2UBaQEPdmlld19nZXRGdW5kaW5nAAQPdW5kZXJseWluZ1ByaWNlCQESZ2V0T3JhY2xlVHdhcFByaWNlAAQNJHQwNzYwNDA3NjEwMgkBCmdldEZ1bmRpbmcABBRzaG9ydFByZW1pdW1GcmFjdGlvbggFDSR0MDc2MDQwNzYxMDICXzEEE2xvbmdQcmVtaXVtRnJhY3Rpb24IBQ0kdDA3NjA0MDc2MTAyAl8yBAtsb25nRnVuZGluZwkBBGRpdmQCBRNsb25nUHJlbWl1bUZyYWN0aW9uBQ91bmRlcmx5aW5nUHJpY2UEDHNob3J0RnVuZGluZwkBBGRpdmQCBRRzaG9ydFByZW1pdW1GcmFjdGlvbgUPdW5kZXJseWluZ1ByaWNlCQACAQkArAICCQCsAgIJAKwCAgkBAXMBBQtsb25nRnVuZGluZwkBAXMBBQxzaG9ydEZ1bmRpbmcJAQFzAQkBEGdldFR3YXBTcG90UHJpY2UACQEBcwEJARJnZXRPcmFjbGVUd2FwUHJpY2UAAWkBGHZpZXdfZ2V0Qm9ycm93ZWRCeVRyYWRlcgEHX3RyYWRlcgQNJHQwNzYzOTI3NjQ0NgkBE2dldEJvcnJvd2VkQnlUcmFkZXIBBQdfdHJhZGVyBAhib3Jyb3dlZAgFDSR0MDc2MzkyNzY0NDYCXzEEB2Fzc2V0SWQIBQ0kdDA3NjM5Mjc2NDQ2Al8yCQACAQkArAICCQEBcwEFCGJvcnJvd2VkBQdhc3NldElkAQJ0eAEGdmVyaWZ5AAkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAkBDmFkbWluUHVibGljS2V5AOSlq+E=", "height": 2350176, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: none Next: none Full:
OldNewDifferences
1-# no script
1+{-# STDLIB_VERSION 6 #-}
2+{-# SCRIPT_TYPE ACCOUNT #-}
3+{-# CONTENT_TYPE DAPP #-}
4+let k_ora_key = "k_ora_key"
5+
6+let k_ora_block_key = "k_ora_block_key"
7+
8+let k_ora = "k_ora"
9+
10+let k_balance = "k_balance"
11+
12+let k_positionSize = "k_positionSize"
13+
14+let k_positionMargin = "k_positionMargin"
15+
16+let k_positionOpenNotional = "k_positionOpenNotional"
17+
18+let k_positionLastUpdatedCumulativePremiumFraction = "k_positionFraction"
19+
20+let k_positionClosedDate = "k_positionClosedDate"
21+
22+let k_positionAsset = "k_positionAsset"
23+
24+let k_initialized = "k_initialized"
25+
26+let k_paused = "k_paused"
27+
28+let k_fee = "k_fee"
29+
30+let k_fundingPeriod = "k_fundingPeriod"
31+
32+let k_initMarginRatio = "k_initMarginRatio"
33+
34+let k_maintenanceMarginRatio = "k_mmr"
35+
36+let k_liquidationFeeRatio = "k_liquidationFeeRatio"
37+
38+let k_partialLiquidationRatio = "k_partLiquidationRatio"
39+
40+let k_spreadLimit = "k_spreadLimit"
41+
42+let k_maxPriceImpact = "k_maxPriceImpact"
43+
44+let k_maxPriceSpread = "k_maxPriceSpread"
45+
46+let k_lastDataStr = "k_lastDataStr"
47+
48+let k_lastMinuteId = "k_lastMinuteId"
49+
50+let k_twapDataLastCumulativePrice = "k_twapDataLastCumulativePrice"
51+
52+let k_twapDataLastPrice = "k_twapDataLastPrice"
53+
54+let k_twapDataPreviousMinuteId = "k_twapDataPreviousMinuteId"
55+
56+let k_latestLongCumulativePremiumFraction = "k_latestLongPremiumFraction"
57+
58+let k_latestShortCumulativePremiumFraction = "k_latestShortPremiumFraction"
59+
60+let k_nextFundingBlock = "k_nextFundingBlockMinTimestamp"
61+
62+let k_longFundingRate = "k_longFundingRate"
63+
64+let k_shortFundingRate = "k_shortFundingRate"
65+
66+let k_quoteAssetReserve = "k_qtAstR"
67+
68+let k_baseAssetReserve = "k_bsAstR"
69+
70+let k_quoteAssetWeight = "k_qtAstW"
71+
72+let k_baseAssetWeight = "k_bsAstW"
73+
74+let k_totalPositionSize = "k_totalPositionSize"
75+
76+let k_totalLongPositionSize = "k_totalLongPositionSize"
77+
78+let k_totalShortPositionSize = "k_totalShortPositionSize"
79+
80+let k_cumulativeNotional = "k_cumulativeNotional"
81+
82+let k_openInterestNotional = "k_openInterestNotional"
83+
84+let k_coordinatorAddress = "k_coordinatorAddress"
85+
86+let k_vault_address = "k_vault_address"
87+
88+let k_admin_address = "k_admin_address"
89+
90+let k_admin_public_key = "k_admin_public_key"
91+
92+let k_quote_asset = "k_quote_asset"
93+
94+let k_quote_staking = "k_quote_staking"
95+
96+let k_staking_address = "k_staking_address"
97+
98+let k_miner_address = "k_miner_address"
99+
100+let k_orders_address = "k_orders_address"
101+
102+let k_referral_address = "k_referral_address"
103+
104+let k_manager_address = "k_manager_address"
105+
106+let k_collateral_address = "k_collateral_address"
107+
108+let k_exchange_address = "k_exchange_address"
109+
110+let k_nft_manager_address = "k_nft_manager_address"
111+
112+let k_trader_market_asset_collateral = "k_trader_market_asset_collateral"
113+
114+func toCompositeKey (_key,_address) = ((_key + "_") + _address)
115+
116+
117+func coordinator () = valueOrErrorMessage(addressFromString(getStringValue(this, k_coordinatorAddress)), "Coordinator not set")
118+
119+
120+func adminAddress () = addressFromString(getStringValue(coordinator(), k_admin_address))
121+
122+
123+func adminPublicKey () = fromBase58String(getStringValue(coordinator(), k_admin_public_key))
124+
125+
126+func quoteAsset () = fromBase58String(getStringValue(coordinator(), k_quote_asset))
127+
128+
129+func quoteAssetStaking () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_quote_staking)), "Quote asset staking not set")
130+
131+
132+func stakingAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_staking_address)), "Staking not set")
133+
134+
135+func vaultAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_vault_address)), "Vault not set")
136+
137+
138+func minerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_miner_address)), "Miner not set")
139+
140+
141+func ordersAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_orders_address)), "Orders not set")
142+
143+
144+func referralAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_referral_address)), "Referral not set")
145+
146+
147+func nftManagerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_nft_manager_address)), "NFT Manager not set")
148+
149+
150+func collateralAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_collateral_address)), "Collateral Manager not set")
151+
152+
153+func swapAddress () = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(coordinator(), k_exchange_address), "No swap address")), "Invalid swap address")
154+
155+
156+let k_whitelist_asset = "k_whitelist_asset"
157+
158+func isWhitelistAsset (_assetId) = valueOrElse(getBoolean(collateralAddress(), toCompositeKey(k_whitelist_asset, _assetId)), false)
159+
160+
161+let k_token_param = "k_token_param"
162+
163+let k_token_type = "k_token_type"
164+
165+let FEE_REDUCTION_TOKEN_TYPE = "fee_reduction"
166+
167+let DIR_LONG = 1
168+
169+let DIR_SHORT = 2
170+
171+let TWAP_INTERVAL = 15
172+
173+let ORACLE_INTERVAL = 15
174+
175+let SECONDS = 1000
176+
177+let DECIMAL_NUMBERS = 6
178+
179+let DECIMAL_UNIT = (1 * (((((10 * 10) * 10) * 10) * 10) * 10))
180+
181+let ONE_DAY = (86400 * DECIMAL_UNIT)
182+
183+let ALL_FEES = 100
184+
185+let PNL_OPTION_SPOT = 1
186+
187+let PNL_OPTION_ORACLE = 2
188+
189+func s (_x) = (toString(_x) + ",")
190+
191+
192+func divd (_x,_y) = fraction(_x, DECIMAL_UNIT, _y, HALFEVEN)
193+
194+
195+func muld (_x,_y) = fraction(_x, _y, DECIMAL_UNIT, HALFEVEN)
196+
197+
198+func sqrtd (_x) = sqrt(_x, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
199+
200+
201+func powd (_x,_y) = pow(_x, DECIMAL_NUMBERS, _y, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
202+
203+
204+func bdivd (_x,_y) = fraction(_x, toBigInt(DECIMAL_UNIT), _y, HALFEVEN)
205+
206+
207+func bmuld (_x,_y) = fraction(_x, _y, toBigInt(DECIMAL_UNIT), HALFEVEN)
208+
209+
210+func bsqrtd (_x) = sqrtBigInt(_x, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
211+
212+
213+func bpowd (_x,_y) = pow(_x, DECIMAL_NUMBERS, _y, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
214+
215+
216+func abs (_x) = if ((_x > 0))
217+ then _x
218+ else -(_x)
219+
220+
221+func vmax (_x,_y) = if ((_x >= _y))
222+ then _x
223+ else _y
224+
225+
226+func listToStr (_list) = {
227+ func _join (accumulator,val) = ((accumulator + val) + ",")
228+
229+ let newListStr = {
230+ let $l = _list
231+ let $s = size($l)
232+ let $acc0 = ""
233+ func $f0_1 ($a,$i) = if (($i >= $s))
234+ then $a
235+ else _join($a, $l[$i])
236+
237+ func $f0_2 ($a,$i) = if (($i >= $s))
238+ then $a
239+ else throw("List size exceeds 20")
240+
241+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20)
242+ }
243+ let newListStrU = dropRight(newListStr, 1)
244+ let newListStrR = if ((take(newListStrU, 1) == ","))
245+ then drop(newListStrU, 1)
246+ else newListStrU
247+ newListStrR
248+ }
249+
250+
251+func strToList (_str) = split(_str, ",")
252+
253+
254+func pushToQueue (_list,_maxSize,_value) = if ((size(_list) > _maxSize))
255+ then (removeByIndex(_list, 0) :+ _value)
256+ else (_list :+ _value)
257+
258+
259+func int (k) = valueOrErrorMessage(getInteger(this, k), ("no value for " + k))
260+
261+
262+func intOr (k,def) = valueOrElse(getInteger(this, k), def)
263+
264+
265+func strA (_address,_key) = {
266+ let val = valueOrErrorMessage(getString(_address, _key), ("No value for key " + _key))
267+ val
268+ }
269+
270+
271+func intA (_address,_key) = {
272+ let val = valueOrErrorMessage(getInteger(_address, _key), ("No value for key " + _key))
273+ val
274+ }
275+
276+
277+func cbalance () = int(k_balance)
278+
279+
280+func fee () = int(k_fee)
281+
282+
283+func initMarginRatio () = int(k_initMarginRatio)
284+
285+
286+func qtAstR () = int(k_quoteAssetReserve)
287+
288+
289+func bsAstR () = int(k_baseAssetReserve)
290+
291+
292+func qtAstW () = intOr(k_quoteAssetWeight, DECIMAL_UNIT)
293+
294+
295+func bsAstW () = intOr(k_baseAssetWeight, DECIMAL_UNIT)
296+
297+
298+func totalPositionSize () = int(k_totalPositionSize)
299+
300+
301+func cumulativeNotional () = int(k_cumulativeNotional)
302+
303+
304+func openInterestNotional () = int(k_openInterestNotional)
305+
306+
307+func nextFundingBlockTimestamp () = int(k_nextFundingBlock)
308+
309+
310+func fundingPeriodRaw () = int(k_fundingPeriod)
311+
312+
313+func fundingPeriodDecimal () = (fundingPeriodRaw() * DECIMAL_UNIT)
314+
315+
316+func fundingPeriodSeconds () = (fundingPeriodRaw() * SECONDS)
317+
318+
319+func maintenanceMarginRatio () = int(k_maintenanceMarginRatio)
320+
321+
322+func liquidationFeeRatio () = int(k_liquidationFeeRatio)
323+
324+
325+func partialLiquidationRatio () = int(k_partialLiquidationRatio)
326+
327+
328+func spreadLimit () = int(k_spreadLimit)
329+
330+
331+func maxPriceImpact () = int(k_maxPriceImpact)
332+
333+
334+func maxPriceSpread () = int(k_maxPriceSpread)
335+
336+
337+func latestLongCumulativePremiumFraction () = int(k_latestLongCumulativePremiumFraction)
338+
339+
340+func latestShortCumulativePremiumFraction () = int(k_latestShortCumulativePremiumFraction)
341+
342+
343+func totalShortPositionSize () = int(k_totalShortPositionSize)
344+
345+
346+func totalLongPositionSize () = int(k_totalLongPositionSize)
347+
348+
349+func getActualCaller (i) = valueOrElse(getString(ordersAddress(), "k_sender"), toString(i.caller))
350+
351+
352+func requireMoreMarginRatio (_marginRatio,_baseMarginRatio,_largerThanOrEqualTo) = {
353+ let remainingMarginRatio = (_marginRatio - _baseMarginRatio)
354+ if (if (_largerThanOrEqualTo)
355+ then (0 > remainingMarginRatio)
356+ else false)
357+ then throw("Invalid margin")
358+ else if (if (!(_largerThanOrEqualTo))
359+ then (remainingMarginRatio >= 0)
360+ else false)
361+ then throw("Invalid margin")
362+ else true
363+ }
364+
365+
366+func latestCumulativePremiumFraction (_positionSize) = if ((_positionSize == 0))
367+ then throw("Should not be called with _positionSize == 0")
368+ else if ((_positionSize > 0))
369+ then latestLongCumulativePremiumFraction()
370+ else latestShortCumulativePremiumFraction()
371+
372+
373+func getPosition (_trader) = {
374+ let positionSizeOpt = getInteger(this, toCompositeKey(k_positionSize, _trader))
375+ match positionSizeOpt {
376+ case positionSize: Int =>
377+ $Tuple4(positionSize, getIntegerValue(this, toCompositeKey(k_positionMargin, _trader)), getIntegerValue(this, toCompositeKey(k_positionOpenNotional, _trader)), getIntegerValue(this, toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, _trader)))
378+ case _ =>
379+ $Tuple4(0, 0, 0, 0)
380+ }
381+ }
382+
383+
384+func getPositionAsset (_trader) = {
385+ let positionAssetOpt = getString(this, toCompositeKey(k_positionAsset, _trader))
386+ match positionAssetOpt {
387+ case positionAsset: String =>
388+ positionAsset
389+ case _ =>
390+ toBase58String(quoteAsset())
391+ }
392+ }
393+
394+
395+func requireOpenPosition (_trader) = if ((getPosition(_trader)._1 == 0))
396+ then throw("No open position")
397+ else true
398+
399+
400+func initialized () = valueOrElse(getBoolean(this, k_initialized), false)
401+
402+
403+func paused () = valueOrElse(getBoolean(this, k_paused), false)
404+
405+
406+func updateReserve (_isAdd,_quoteAssetAmount,_baseAssetAmount) = if (_isAdd)
407+ then {
408+ let newBase = (bsAstR() - _baseAssetAmount)
409+ if ((0 >= newBase))
410+ then throw("Tx lead to base asset reserve <= 0, revert")
411+ else $Tuple4((qtAstR() + _quoteAssetAmount), newBase, (totalPositionSize() + _baseAssetAmount), (cumulativeNotional() + _quoteAssetAmount))
412+ }
413+ else {
414+ let newQuote = (qtAstR() - _quoteAssetAmount)
415+ if ((0 >= newQuote))
416+ then throw("Tx lead to base quote reserve <= 0, revert")
417+ else $Tuple4(newQuote, (bsAstR() + _baseAssetAmount), (totalPositionSize() - _baseAssetAmount), (cumulativeNotional() - _quoteAssetAmount))
418+ }
419+
420+
421+func calcInvariant (_qtAstR,_qtAstW,_bsAstR,_bsAstW) = muld(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
422+
423+
424+func swapInput (_isAdd,_quoteAssetAmount) = {
425+ let _qtAstR = qtAstR()
426+ let _bsAstR = bsAstR()
427+ let _qtAstW = qtAstW()
428+ let _bsAstW = bsAstW()
429+ let k = calcInvariant(_qtAstR, _qtAstW, _bsAstR, _bsAstW)
430+ let quoteAssetReserveAfter = if (_isAdd)
431+ then (_qtAstR + _quoteAssetAmount)
432+ else (_qtAstR - _quoteAssetAmount)
433+ let baseAssetReserveAfter = divd(k, muld(quoteAssetReserveAfter, _qtAstW))
434+ let amountBaseAssetBoughtAbs = divd(abs((baseAssetReserveAfter - _bsAstR)), _qtAstW)
435+ let amountBaseAssetBought = if (_isAdd)
436+ then amountBaseAssetBoughtAbs
437+ else -(amountBaseAssetBoughtAbs)
438+ let $t01633316526 = updateReserve(_isAdd, _quoteAssetAmount, amountBaseAssetBoughtAbs)
439+ let quoteAssetReserveAfter1 = $t01633316526._1
440+ let baseAssetReserveAfter1 = $t01633316526._2
441+ let totalPositionSizeAfter1 = $t01633316526._3
442+ let cumulativeNotionalAfter1 = $t01633316526._4
443+ let priceBefore = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
444+ let marketPrice = divd(_quoteAssetAmount, amountBaseAssetBoughtAbs)
445+ let priceDiff = abs((priceBefore - marketPrice))
446+ let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
447+ let maxPriceImpactValue = maxPriceImpact()
448+ if ((priceImpact > maxPriceImpactValue))
449+ then throw(((((((((((((("Price impact " + toString(priceImpact)) + " > max price impact ") + toString(maxPriceImpactValue)) + " before quote asset: ") + toString(_qtAstR)) + " before base asset: ") + toString(_bsAstR)) + " quote asset amount to exchange: ") + toString(_quoteAssetAmount)) + " price before: ") + toString(priceBefore)) + " marketPrice: ") + toString(marketPrice)))
450+ else $Tuple5(amountBaseAssetBought, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1, cumulativeNotionalAfter1)
451+ }
452+
453+
454+func calcRemainMarginWithFundingPayment (_oldPositionSize,_oldPositionMargin,_oldPositionCumulativePremiumFraction,_marginDelta) = {
455+ let fundingPayment = if ((_oldPositionSize != 0))
456+ then {
457+ let _latestCumulativePremiumFraction = latestCumulativePremiumFraction(_oldPositionSize)
458+ muld((_latestCumulativePremiumFraction - _oldPositionCumulativePremiumFraction), _oldPositionSize)
459+ }
460+ else 0
461+ let signedMargin = ((_marginDelta - fundingPayment) + _oldPositionMargin)
462+ let $t01804518172 = if ((0 > signedMargin))
463+ then $Tuple2(0, abs(signedMargin))
464+ else $Tuple2(abs(signedMargin), 0)
465+ let remainMargin = $t01804518172._1
466+ let badDebt = $t01804518172._2
467+ $Tuple3(remainMargin, badDebt, fundingPayment)
468+ }
469+
470+
471+func swapOutputWithReserves (_isAdd,_baseAssetAmount,_checkMaxPriceImpact,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
472+ let priceBefore = divd(muld(_quoteAssetReserve, _quoteAssetWeight), muld(_baseAssetReserve, _baseAssetWeight))
473+ if ((_baseAssetAmount == 0))
474+ then throw("Invalid base asset amount")
475+ else {
476+ let k = calcInvariant(_quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
477+ let baseAssetPoolAmountAfter = if (_isAdd)
478+ then (_baseAssetReserve + _baseAssetAmount)
479+ else (_baseAssetReserve - _baseAssetAmount)
480+ let quoteAssetAfter = divd(k, muld(baseAssetPoolAmountAfter, _baseAssetWeight))
481+ let quoteAssetSold = abs((quoteAssetAfter - muld(_quoteAssetReserve, _quoteAssetWeight)))
482+ let maxPriceImpactValue = maxPriceImpact()
483+ let $t01934019533 = updateReserve(!(_isAdd), quoteAssetSold, _baseAssetAmount)
484+ let quoteAssetReserveAfter1 = $t01934019533._1
485+ let baseAssetReserveAfter1 = $t01934019533._2
486+ let totalPositionSizeAfter1 = $t01934019533._3
487+ let cumulativeNotionalAfter1 = $t01934019533._4
488+ let marketPrice = divd(quoteAssetSold, _baseAssetAmount)
489+ let priceDiff = abs((priceBefore - marketPrice))
490+ let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
491+ if (if ((priceImpact > maxPriceImpactValue))
492+ then _checkMaxPriceImpact
493+ else false)
494+ then throw(((((((((((((("Price impact " + toString(priceImpact)) + " > max price impact ") + toString(maxPriceImpactValue)) + " before quote asset: ") + toString(_quoteAssetReserve)) + " before base asset: ") + toString(_baseAssetReserve)) + " base asset amount to exchange: ") + toString(_baseAssetAmount)) + " price before: ") + toString(priceBefore)) + " market price: ") + toString(marketPrice)))
495+ else $Tuple8(quoteAssetSold, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1, cumulativeNotionalAfter1, (totalLongPositionSize() - (if (_isAdd)
496+ then abs(_baseAssetAmount)
497+ else 0)), (totalShortPositionSize() - (if (!(_isAdd))
498+ then abs(_baseAssetAmount)
499+ else 0)), priceImpact)
500+ }
501+ }
502+
503+
504+func swapOutput (_isAdd,_baseAssetAmount,_checkMaxPriceImpact) = swapOutputWithReserves(_isAdd, _baseAssetAmount, _checkMaxPriceImpact, qtAstR(), qtAstW(), bsAstR(), bsAstW())
505+
506+
507+func getOracleTwapPrice () = {
508+ let oracle = valueOrErrorMessage(addressFromString(getStringValue(this, k_ora)), "")
509+ let priceKey = getStringValue(this, k_ora_key)
510+ let blockKey = getStringValue(this, k_ora_block_key)
511+ let lastValue = valueOrErrorMessage(getInteger(oracle, priceKey), ((("Can not get oracle price. Oracle: " + toString(oracle)) + " key: ") + priceKey))
512+ lastValue
513+ }
514+
515+
516+func requireNotOverSpreadLimit (_quoteAssetReserve,_baseAssetReserve) = {
517+ let oraclePrice = getOracleTwapPrice()
518+ let priceAfter = divd(_quoteAssetReserve, _baseAssetReserve)
519+ let averagePrice = divd((oraclePrice + priceAfter), (2 * DECIMAL_UNIT))
520+ let absPriceDiff = divd(abs((oraclePrice - priceAfter)), averagePrice)
521+ if ((absPriceDiff > maxPriceSpread()))
522+ then throw(((("Price spread " + toString(absPriceDiff)) + " > max price spread ") + toString(maxPriceSpread())))
523+ else true
524+ }
525+
526+
527+func getSpotPrice () = {
528+ let _quoteAssetReserve = qtAstR()
529+ let _baseAssetReserve = bsAstR()
530+ let _qtAstW = qtAstW()
531+ let _bsAstW = bsAstW()
532+ divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
533+ }
534+
535+
536+func isOverFluctuationLimit () = {
537+ let oraclePrice = getOracleTwapPrice()
538+ let currentPrice = getSpotPrice()
539+ (divd(abs((oraclePrice - currentPrice)), oraclePrice) > spreadLimit())
540+ }
541+
542+
543+func getPositionAdjustedOpenNotional (_positionSize,_option,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
544+ let positionSizeAbs = abs(_positionSize)
545+ let isShort = (0 > _positionSize)
546+ let positionNotional = if ((_option == PNL_OPTION_SPOT))
547+ then {
548+ let $t02290823128 = swapOutputWithReserves(!(isShort), positionSizeAbs, false, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
549+ let outPositionNotional = $t02290823128._1
550+ let x1 = $t02290823128._2
551+ let x2 = $t02290823128._3
552+ let x3 = $t02290823128._4
553+ outPositionNotional
554+ }
555+ else muld(positionSizeAbs, getOracleTwapPrice())
556+ positionNotional
557+ }
558+
559+
560+func getPositionNotionalAndUnrealizedPnlByValues (_positionSize,_positionOpenNotional,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight,_option) = if ((_positionSize == 0))
561+ then throw("Invalid position size")
562+ else {
563+ let isShort = (0 > _positionSize)
564+ let positionNotional = getPositionAdjustedOpenNotional(_positionSize, _option, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
565+ let unrealizedPnl = if (isShort)
566+ then (_positionOpenNotional - positionNotional)
567+ else (positionNotional - _positionOpenNotional)
568+ $Tuple2(positionNotional, unrealizedPnl)
569+ }
570+
571+
572+func getPositionNotionalAndUnrealizedPnl (_trader,_option) = {
573+ let $t02455324681 = getPosition(_trader)
574+ let positionSize = $t02455324681._1
575+ let positionMargin = $t02455324681._2
576+ let positionOpenNotional = $t02455324681._3
577+ let positionLstUpdCPF = $t02455324681._4
578+ getPositionNotionalAndUnrealizedPnlByValues(positionSize, positionOpenNotional, qtAstR(), qtAstW(), bsAstR(), bsAstW(), _option)
579+ }
580+
581+
582+func calcMarginRatio (_remainMargin,_badDebt,_positionNotional) = divd((_remainMargin - _badDebt), _positionNotional)
583+
584+
585+func getMarginRatioByOption (_trader,_option) = {
586+ let $t02519425305 = getPosition(_trader)
587+ let positionSize = $t02519425305._1
588+ let positionMargin = $t02519425305._2
589+ let pon = $t02519425305._3
590+ let positionLstUpdCPF = $t02519425305._4
591+ let $t02531125404 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
592+ let positionNotional = $t02531125404._1
593+ let unrealizedPnl = $t02531125404._2
594+ let $t02540925575 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
595+ let remainMargin = $t02540925575._1
596+ let badDebt = $t02540925575._2
597+ calcMarginRatio(remainMargin, badDebt, positionNotional)
598+ }
599+
600+
601+func getMarginRatio (_trader) = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
602+
603+
604+func getPartialLiquidationAmount (_trader,_positionSize) = {
605+ let maximumRatio = vmax(partialLiquidationRatio(), (DECIMAL_UNIT - divd(getMarginRatio(_trader), maintenanceMarginRatio())))
606+ let maxExchangedPositionSize = muld(abs(_positionSize), maximumRatio)
607+ let swapResult = swapOutput((_positionSize > 0), maxExchangedPositionSize, false)
608+ let maxExchangedQuoteAssetAmount = swapResult._1
609+ let priceImpact = swapResult._8
610+ if ((maxPriceImpact() > priceImpact))
611+ then maxExchangedQuoteAssetAmount
612+ else {
613+ let exchangedPositionSize = muld(abs(_positionSize), partialLiquidationRatio())
614+ let exchangedQuoteAssetAmount = swapOutput((_positionSize > 0), exchangedPositionSize, false)._1
615+ exchangedQuoteAssetAmount
616+ }
617+ }
618+
619+
620+func internalClosePosition (_trader,_checkMaxPriceImpact) = {
621+ let $t02680826936 = getPosition(_trader)
622+ let positionSize = $t02680826936._1
623+ let positionMargin = $t02680826936._2
624+ let positionOpenNotional = $t02680826936._3
625+ let positionLstUpdCPF = $t02680826936._4
626+ let unrealizedPnl = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)._2
627+ let $t02703127199 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
628+ let remainMargin = $t02703127199._1
629+ let badDebt = $t02703127199._2
630+ let exchangedPositionSize = -(positionSize)
631+ let realizedPnl = unrealizedPnl
632+ let marginToVault = -(remainMargin)
633+ let $t02732627631 = swapOutput((positionSize > 0), abs(positionSize), _checkMaxPriceImpact)
634+ let exchangedQuoteAssetAmount = $t02732627631._1
635+ let quoteAssetReserveAfter = $t02732627631._2
636+ let baseAssetReserveAfter = $t02732627631._3
637+ let totalPositionSizeAfter = $t02732627631._4
638+ let cumulativeNotionalAfter = $t02732627631._5
639+ let totalLongAfter = $t02732627631._6
640+ let totalShortAfter = $t02732627631._7
641+ let openInterestNotionalAfter = (openInterestNotional() - positionOpenNotional)
642+ $Tuple12(exchangedPositionSize, badDebt, realizedPnl, marginToVault, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, openInterestNotionalAfter, exchangedQuoteAssetAmount, totalLongAfter, totalShortAfter)
643+ }
644+
645+
646+func getTwapSpotPrice () = {
647+ let minuteId = ((lastBlock.timestamp / 1000) / 60)
648+ let startMinuteId = (minuteId - TWAP_INTERVAL)
649+ let listStr = valueOrElse(getString(this, k_lastDataStr), "")
650+ let list = split(listStr, ",")
651+ func filterFn (accumulator,next) = if ((startMinuteId >= parseIntValue(next)))
652+ then (accumulator :+ parseIntValue(next))
653+ else accumulator
654+
655+ let listF = {
656+ let $l = list
657+ let $s = size($l)
658+ let $acc0 = nil
659+ func $f0_1 ($a,$i) = if (($i >= $s))
660+ then $a
661+ else filterFn($a, $l[$i])
662+
663+ func $f0_2 ($a,$i) = if (($i >= $s))
664+ then $a
665+ else throw("List size exceeds 20")
666+
667+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20)
668+ }
669+ let maxIndex = if ((size(listF) > 0))
670+ then max(listF)
671+ else parseIntValue(list[0])
672+ let lastMinuteId = valueOrElse(getInteger(this, k_lastMinuteId), 0)
673+ let endLastCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(lastMinuteId))), 0)
674+ let endLastPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(lastMinuteId))), 0)
675+ let nowCumulativePrice = (endLastCumulativePrice + ((minuteId - lastMinuteId) * endLastPrice))
676+ let startLastCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(maxIndex))), 0)
677+ let startLastPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(maxIndex))), 0)
678+ let startCumulativePrice = (startLastCumulativePrice + ((startMinuteId - maxIndex) * startLastPrice))
679+ ((nowCumulativePrice - startCumulativePrice) / TWAP_INTERVAL)
680+ }
681+
682+
683+func getTerminalAmmState () = {
684+ let _positionSize = totalPositionSize()
685+ if ((_positionSize == 0))
686+ then $Tuple2(qtAstR(), bsAstR())
687+ else {
688+ let direction = (_positionSize > 0)
689+ let $t02961829797 = swapOutput(direction, abs(_positionSize), false)
690+ let currentNetMarketValue = $t02961829797._1
691+ let terminalQuoteAssetReserve = $t02961829797._2
692+ let terminalBaseAssetReserve = $t02961829797._3
693+ $Tuple2(terminalQuoteAssetReserve, terminalBaseAssetReserve)
694+ }
695+ }
696+
697+
698+func getQuoteAssetWeight (baseAssetReserve,totalPositionSize,quoteAssetReserve,targetPrice) = {
699+ let b = toBigInt(baseAssetReserve)
700+ let sz = toBigInt(totalPositionSize)
701+ let q = toBigInt(quoteAssetReserve)
702+ let p = toBigInt(targetPrice)
703+ let bs2 = bpowd((b + sz), toBigInt((2 * DECIMAL_UNIT)))
704+ let qbs2 = bmuld(q, bs2)
705+ let ps4 = (toBigInt(4) * bmuld(p, sz))
706+ let sqr = bsqrtd(bmuld(qbs2, (q - ps4)))
707+ let bq = bmuld(b, q)
708+ let qs = bmuld(q, sz)
709+ let top = ((-(sqr) + bq) + qs)
710+ let bot = (toBigInt(2) * bmuld(q, sz))
711+ let result = bdivd(top, bot)
712+ toInt(result)
713+ }
714+
715+
716+func getSyncTerminalPrice (_terminalPrice) = {
717+ let _positionSize = totalPositionSize()
718+ if ((_positionSize == 0))
719+ then {
720+ let _qtAstR = qtAstR()
721+ let _bsAstR = bsAstR()
722+ let newQtAstW = divd(muld(_terminalPrice, _bsAstR), _qtAstR)
723+ $Tuple3(newQtAstW, DECIMAL_UNIT, 0)
724+ }
725+ else {
726+ let direction = (_positionSize > 0)
727+ let currentNetMarketValue = swapOutput(direction, abs(_positionSize), false)._1
728+ let _qtAstR = qtAstR()
729+ let _bsAstR = bsAstR()
730+ let newQtAstW = getQuoteAssetWeight(_bsAstR, _positionSize, _qtAstR, _terminalPrice)
731+ let newBsAstW = DECIMAL_UNIT
732+ let marginToVault = getPositionNotionalAndUnrealizedPnlByValues(_positionSize, currentNetMarketValue, _qtAstR, newQtAstW, _bsAstR, newBsAstW, PNL_OPTION_SPOT)._2
733+ $Tuple3(newQtAstW, newBsAstW, marginToVault)
734+ }
735+ }
736+
737+
738+func getFunding () = {
739+ let underlyingPrice = getOracleTwapPrice()
740+ let spotTwapPrice = getTwapSpotPrice()
741+ let premium = (spotTwapPrice - underlyingPrice)
742+ if (if ((totalShortPositionSize() == 0))
743+ then true
744+ else (totalLongPositionSize() == 0))
745+ then $Tuple2(0, 0)
746+ else if ((0 > premium))
747+ then {
748+ let shortPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
749+ let longPremiumFraction = divd(muld(shortPremiumFraction, totalShortPositionSize()), totalLongPositionSize())
750+ $Tuple2(shortPremiumFraction, longPremiumFraction)
751+ }
752+ else {
753+ let longPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
754+ let shortPremiumFraction = divd(muld(longPremiumFraction, totalLongPositionSize()), totalShortPositionSize())
755+ $Tuple2(shortPremiumFraction, longPremiumFraction)
756+ }
757+ }
758+
759+
760+func getAdjustedFee (i,_baseFeeDiscount) = {
761+ let baseFeeRaw = fee()
762+ let baseFee = muld(baseFeeRaw, _baseFeeDiscount)
763+ let $t03289033498 = if ((size(i.payments) > 1))
764+ then {
765+ let artifactId = toBase58String(valueOrErrorMessage(i.payments[1].assetId, "Invalid attached artifact"))
766+ let artifactKind = strA(nftManagerAddress(), toCompositeKey(k_token_type, artifactId))
767+ if ((artifactKind == FEE_REDUCTION_TOKEN_TYPE))
768+ then {
769+ let reduction = intA(nftManagerAddress(), toCompositeKey(k_token_param, artifactId))
770+ let adjustedFee = muld(baseFee, reduction)
771+ $Tuple2(adjustedFee, true)
772+ }
773+ else throw("Invalid attached artifact")
774+ }
775+ else $Tuple2(baseFee, false)
776+ let adjustedFee = $t03289033498._1
777+ let burnArtifact = $t03289033498._2
778+ $Tuple2(adjustedFee, burnArtifact)
779+ }
780+
781+
782+func updateSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread) = [IntegerEntry(k_initMarginRatio, _initMarginRatio), IntegerEntry(k_maintenanceMarginRatio, _mmr), IntegerEntry(k_liquidationFeeRatio, _liquidationFeeRatio), IntegerEntry(k_fundingPeriod, _fundingPeriod), IntegerEntry(k_fee, _fee), IntegerEntry(k_spreadLimit, _spreadLimit), IntegerEntry(k_maxPriceImpact, _maxPriceImpact), IntegerEntry(k_partialLiquidationRatio, _partialLiquidationRatio), IntegerEntry(k_maxPriceSpread, _maxPriceSpread)]
783+
784+
785+func updateFunding (_nextFundingBlock,_latestLongCumulativePremiumFraction,_latestShortCumulativePremiumFraction,_longFundingRate,_shortFundingRate) = [IntegerEntry(k_nextFundingBlock, _nextFundingBlock), IntegerEntry(k_latestLongCumulativePremiumFraction, _latestLongCumulativePremiumFraction), IntegerEntry(k_latestShortCumulativePremiumFraction, _latestShortCumulativePremiumFraction), IntegerEntry(k_longFundingRate, _longFundingRate), IntegerEntry(k_shortFundingRate, _shortFundingRate)]
786+
787+
788+func updatePositionAsset (_address,_assetId) = [StringEntry(toCompositeKey(k_positionAsset, _address), _assetId)]
789+
790+
791+func updatePosition (_address,_size,_margin,_openNotional,_latestCumulativePremiumFraction) = [IntegerEntry(toCompositeKey(k_positionSize, _address), _size), IntegerEntry(toCompositeKey(k_positionMargin, _address), _margin), IntegerEntry(toCompositeKey(k_positionOpenNotional, _address), _openNotional), IntegerEntry(toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, _address), _latestCumulativePremiumFraction)]
792+
793+
794+func appendTwap (price) = {
795+ let minuteId = ((lastBlock.timestamp / 1000) / 60)
796+ let previousMinuteId = valueOrElse(getInteger(this, k_lastMinuteId), 0)
797+ if ((previousMinuteId > minuteId))
798+ then throw("TWAP out-of-order")
799+ else {
800+ let lastMinuteId = if ((previousMinuteId == 0))
801+ then minuteId
802+ else previousMinuteId
803+ if ((minuteId > previousMinuteId))
804+ then {
805+ let prevCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(previousMinuteId))), 0)
806+ let prevPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(previousMinuteId))), price)
807+ let lastCumulativePrice = (prevCumulativePrice + ((minuteId - lastMinuteId) * prevPrice))
808+ let list = pushToQueue(strToList(valueOrElse(getString(this, k_lastDataStr), "")), TWAP_INTERVAL, toString(minuteId))
809+[IntegerEntry(toCompositeKey(k_twapDataLastCumulativePrice, toString(minuteId)), lastCumulativePrice), IntegerEntry(toCompositeKey(k_twapDataLastPrice, toString(minuteId)), price), IntegerEntry(toCompositeKey(k_twapDataPreviousMinuteId, toString(minuteId)), previousMinuteId), IntegerEntry(k_lastMinuteId, minuteId), StringEntry(k_lastDataStr, listToStr(list))]
810+ }
811+ else {
812+ let twapDataPreviousMinuteId = valueOrElse(getInteger(this, toCompositeKey(k_twapDataPreviousMinuteId, toString(minuteId))), 0)
813+ let prevCumulativePrice = valueOrElse(getInteger(this, toCompositeKey(k_twapDataLastCumulativePrice, toString(twapDataPreviousMinuteId))), 0)
814+ let prevPrice = valueOrElse(getInteger(this, toCompositeKey(k_twapDataLastPrice, toString(twapDataPreviousMinuteId))), price)
815+ let lastCumulativePrice = (prevCumulativePrice + ((minuteId - twapDataPreviousMinuteId) * prevPrice))
816+[IntegerEntry(toCompositeKey(k_twapDataLastCumulativePrice, toString(minuteId)), lastCumulativePrice), IntegerEntry(toCompositeKey(k_twapDataLastPrice, toString(minuteId)), price)]
817+ }
818+ }
819+ }
820+
821+
822+func updateAmmReserves (_qtAstR,_bsAstR) = [IntegerEntry(k_quoteAssetReserve, _qtAstR), IntegerEntry(k_baseAssetReserve, _bsAstR)]
823+
824+
825+func updateAmmWeights (_qtAstW,_bsAstW) = [IntegerEntry(k_quoteAssetWeight, _qtAstW), IntegerEntry(k_baseAssetWeight, _bsAstW)]
826+
827+
828+func updateAmm (_qtAstR,_bsAstR,_totalPositionSizeAfter,_cumulativeNotionalAfter,_openInterestNotional,_totalLongPositionSize,_totalShortPositionSize) = {
829+ let _qtAstW = qtAstW()
830+ let _bsAstW = bsAstW()
831+ if (((_totalLongPositionSize - _totalShortPositionSize) != _totalPositionSizeAfter))
832+ then throw(((((("Invalid AMM state data: " + toString(_totalLongPositionSize)) + " + ") + toString(_totalShortPositionSize)) + " != ") + toString(_totalPositionSizeAfter)))
833+ else ((updateAmmReserves(_qtAstR, _bsAstR) ++ [IntegerEntry(k_totalPositionSize, _totalPositionSizeAfter), IntegerEntry(k_cumulativeNotional, _cumulativeNotionalAfter), IntegerEntry(k_openInterestNotional, _openInterestNotional), IntegerEntry(k_totalLongPositionSize, _totalLongPositionSize), IntegerEntry(k_totalShortPositionSize, _totalShortPositionSize)]) ++ appendTwap(divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))))
834+ }
835+
836+
837+func deletePosition (_address) = [DeleteEntry(toCompositeKey(k_positionSize, _address)), DeleteEntry(toCompositeKey(k_positionMargin, _address)), DeleteEntry(toCompositeKey(k_positionOpenNotional, _address)), DeleteEntry(toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, _address)), DeleteEntry(toCompositeKey(k_positionAsset, _address)), IntegerEntry(toCompositeKey(k_positionClosedDate, _address), lastBlock.timestamp)]
838+
839+
840+func withdraw (_address,_amount) = {
841+ let balance = assetBalance(this, quoteAsset())
842+ if ((_amount > balance))
843+ then throw(((("Unable to withdraw " + toString(_amount)) + " from contract balance ") + toString(balance)))
844+ else [ScriptTransfer(_address, _amount, quoteAsset())]
845+ }
846+
847+
848+func updateBalance (i) = if ((0 > i))
849+ then throw("Balance")
850+ else [IntegerEntry(k_balance, i)]
851+
852+
853+func transferFee (i) = [ScriptTransfer(stakingAddress(), i, quoteAsset())]
854+
855+
856+func doBurnArtifact (_burnArtifact,i) = if (_burnArtifact)
857+ then [Burn(valueOrErrorMessage(i.payments[1].assetId, "Invalid artifact"), 1)]
858+ else nil
859+
860+
861+func isSameAssetOrNoPosition (_trader,_assetId) = {
862+ let oldPositionSize = getPosition(_trader)._1
863+ if ((oldPositionSize == 0))
864+ then true
865+ else (getPositionAsset(_trader) == _assetId)
866+ }
867+
868+
869+func isSameAsset (_trader,_assetId) = (getPositionAsset(_trader) == _assetId)
870+
871+
872+func getBorrowedByTraderInMarketKey (_amm,_assetId,_trader) = ((((((k_trader_market_asset_collateral + "_") + _amm) + "_") + _assetId) + "_") + _trader)
873+
874+
875+func getBorrowedByTrader (_trader) = {
876+ let positionAsset = getPositionAsset(_trader)
877+ if ((positionAsset == toBase58String(quoteAsset())))
878+ then $Tuple2(0, positionAsset)
879+ else {
880+ let key = getBorrowedByTraderInMarketKey(toString(this), positionAsset, _trader)
881+ let borrow = valueOrElse(getInteger(collateralAddress(), key), 0)
882+ $Tuple2(borrow, positionAsset)
883+ }
884+ }
885+
886+
887+@Callable(i)
888+func pause () = if ((i.caller != adminAddress()))
889+ then throw("Invalid togglePause params")
890+ else [BooleanEntry(k_paused, true)]
891+
892+
893+
894+@Callable(i)
895+func unpause () = if ((i.caller != adminAddress()))
896+ then throw("Invalid togglePause params")
897+ else [BooleanEntry(k_paused, false)]
898+
899+
900+
901+@Callable(i)
902+func addLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
903+ then true
904+ else (0 >= _quoteAssetAmount))
905+ then throw("Invalid addLiquidity params")
906+ else {
907+ let _qtAstR = qtAstR()
908+ let _bsAstR = bsAstR()
909+ let _qtAstW = qtAstW()
910+ let _bsAstW = bsAstW()
911+ let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
912+ let baseAssetAmountToAdd = divd(_quoteAssetAmount, price)
913+ let qtAstRAfter = (_qtAstR + _quoteAssetAmount)
914+ let bsAstRAfter = (_bsAstR + baseAssetAmountToAdd)
915+ updateAmmReserves(qtAstRAfter, bsAstRAfter)
916+ }
917+
918+
919+
920+@Callable(i)
921+func removeLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
922+ then true
923+ else (0 >= _quoteAssetAmount))
924+ then throw("Invalid removeLiquidity params")
925+ else {
926+ let _qtAstR = qtAstR()
927+ let _bsAstR = bsAstR()
928+ let _qtAstW = qtAstW()
929+ let _bsAstW = bsAstW()
930+ let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
931+ let baseAssetAmountToRemove = divd(_quoteAssetAmount, price)
932+ let qtAstRAfter = (_qtAstR - _quoteAssetAmount)
933+ let bsAstRAfter = (_bsAstR - baseAssetAmountToRemove)
934+ updateAmmReserves(qtAstRAfter, bsAstRAfter)
935+ }
936+
937+
938+
939+@Callable(i)
940+func changeSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread) = if ((i.caller != adminAddress()))
941+ then throw("Invalid changeSettings params")
942+ else updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact, _partialLiquidationRatio, _maxPriceSpread)
943+
944+
945+
946+@Callable(i)
947+func initialize (_qtAstR,_bsAstR,_fundingPeriod,_initMarginRatio,_mmr,_liquidationFeeRatio,_fee,_oracle,_oracleKey,_coordinator,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread) = if (if (if (if (if (if (if (if (if (if (if (if ((0 >= _qtAstR))
948+ then true
949+ else (0 >= _bsAstR))
950+ then true
951+ else (0 >= _fundingPeriod))
952+ then true
953+ else (0 >= _initMarginRatio))
954+ then true
955+ else (0 >= _mmr))
956+ then true
957+ else (0 >= _liquidationFeeRatio))
958+ then true
959+ else (0 >= _fee))
960+ then true
961+ else (0 >= _spreadLimit))
962+ then true
963+ else (0 >= _maxPriceImpact))
964+ then true
965+ else (0 >= _partialLiquidationRatio))
966+ then true
967+ else (0 >= _maxPriceSpread))
968+ then true
969+ else initialized())
970+ then throw("Invalid initialize parameters")
971+ else ((((updateAmm(_qtAstR, _bsAstR, 0, 0, 0, 0, 0) ++ updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact, _partialLiquidationRatio, _maxPriceSpread)) ++ updateFunding((lastBlock.timestamp + _fundingPeriod), 0, 0, 0, 0)) ++ updateBalance(0)) ++ [BooleanEntry(k_initialized, true), StringEntry(k_ora, _oracle), StringEntry(k_ora_key, _oracleKey), StringEntry(k_coordinatorAddress, _coordinator)])
972+
973+
974+
975+@Callable(i)
976+func setInitMarginRatio (_initMarginRatio) = if (if ((0 >= _initMarginRatio))
977+ then true
978+ else !(initialized()))
979+ then throw("Invalid setInitMarginRatio parameters")
980+ else updateSettings(_initMarginRatio, maintenanceMarginRatio(), liquidationFeeRatio(), fundingPeriodRaw(), fee(), spreadLimit(), maxPriceImpact(), partialLiquidationRatio(), maxPriceSpread())
981+
982+
983+
984+@Callable(i)
985+func decreasePosition (_amount,_leverage,_minBaseAssetAmount) = {
986+ let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
987+ if ((sync == sync))
988+ then if (if (if (if (if ((0 >= _amount))
989+ then true
990+ else !(initialized()))
991+ then true
992+ else !(requireMoreMarginRatio(divd(DECIMAL_UNIT, _leverage), initMarginRatio(), true)))
993+ then true
994+ else !(requireOpenPosition(toString(i.caller))))
995+ then true
996+ else paused())
997+ then throw("Invalid decreasePosition parameters")
998+ else {
999+ let $t04547845630 = getPosition(toString(i.caller))
1000+ let oldPositionSize = $t04547845630._1
1001+ let oldPositionMargin = $t04547845630._2
1002+ let oldPositionOpenNotional = $t04547845630._3
1003+ let oldPositionLstUpdCPF = $t04547845630._4
1004+ let _direction = if ((oldPositionSize > 0))
1005+ then DIR_SHORT
1006+ else DIR_LONG
1007+ let isAdd = (_direction == DIR_LONG)
1008+ let openNotional = muld(_amount, _leverage)
1009+ let $t04580345919 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1010+ let oldPositionNotional = $t04580345919._1
1011+ let unrealizedPnl = $t04580345919._2
1012+ let $t04592548474 = if ((oldPositionNotional > openNotional))
1013+ then {
1014+ let $t04630246521 = swapInput(isAdd, openNotional)
1015+ let exchangedPositionSize = $t04630246521._1
1016+ let quoteAssetReserveAfter = $t04630246521._2
1017+ let baseAssetReserveAfter = $t04630246521._3
1018+ let totalPositionSizeAfter = $t04630246521._4
1019+ let cumulativeNotionalAfter = $t04630246521._5
1020+ let exchangedPositionSizeAbs = abs(exchangedPositionSize)
1021+ if (if ((_minBaseAssetAmount != 0))
1022+ then (_minBaseAssetAmount > exchangedPositionSizeAbs)
1023+ else false)
1024+ then throw(((("Too little base asset exchanged, got " + toString(exchangedPositionSizeAbs)) + " expected ") + toString(_minBaseAssetAmount)))
1025+ else {
1026+ let realizedPnl = divd(muld(unrealizedPnl, exchangedPositionSizeAbs), abs(oldPositionSize))
1027+ let $t04695847203 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1028+ let remainMargin = $t04695847203._1
1029+ let badDebt = $t04695847203._2
1030+ let fundingPayment = $t04695847203._3
1031+ let exchangedQuoteAssetAmount = openNotional
1032+ let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
1033+ let remainOpenNotional = if ((oldPositionSize > 0))
1034+ then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
1035+ else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
1036+ let newPositionSize = (oldPositionSize + exchangedPositionSize)
1037+ $Tuple11(newPositionSize, remainMargin, abs(remainOpenNotional), latestCumulativePremiumFraction(newPositionSize), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, (openInterestNotional() - openNotional), (totalLongPositionSize() - (if ((newPositionSize > 0))
1038+ then abs(exchangedPositionSize)
1039+ else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
1040+ then abs(exchangedPositionSize)
1041+ else 0)))
1042+ }
1043+ }
1044+ else throw("Close position first")
1045+ let newPositionSize = $t04592548474._1
1046+ let newPositionRemainMargin = $t04592548474._2
1047+ let newPositionOpenNotional = $t04592548474._3
1048+ let newPositionLatestCPF = $t04592548474._4
1049+ let baseAssetReserveAfter = $t04592548474._5
1050+ let quoteAssetReserveAfter = $t04592548474._6
1051+ let totalPositionSizeAfter = $t04592548474._7
1052+ let cumulativeNotionalAfter = $t04592548474._8
1053+ let openInterestNotionalAfter = $t04592548474._9
1054+ let totalLongAfter = $t04592548474._10
1055+ let totalShortAfter = $t04592548474._11
1056+ let notifyNotional = invoke(minerAddress(), "notifyNotional", [toString(i.caller), newPositionOpenNotional], nil)
1057+ if ((notifyNotional == notifyNotional))
1058+ then (updatePosition(toString(i.caller), newPositionSize, newPositionRemainMargin, newPositionOpenNotional, newPositionLatestCPF) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter))
1059+ else throw("Strict value is not equal to itself.")
1060+ }
1061+ else throw("Strict value is not equal to itself.")
1062+ }
1063+
1064+
1065+
1066+@Callable(i)
1067+func increasePosition (_direction,_leverage,_minBaseAssetAmount,_refLink) = {
1068+ let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
1069+ if ((sync == sync))
1070+ then {
1071+ let _trader = toString(i.caller)
1072+ let _rawAmount = i.payments[0].amount
1073+ let _assetId = i.payments[0].assetId
1074+ let _assetIdStr = toBase58String(value(_assetId))
1075+ let isQuoteAsset = (_assetId == quoteAsset())
1076+ let isCollateralAsset = isWhitelistAsset(_assetIdStr)
1077+ if (if (if (if (if (if (if (if ((_direction != DIR_LONG))
1078+ then (_direction != DIR_SHORT)
1079+ else false)
1080+ then true
1081+ else (0 >= _rawAmount))
1082+ then true
1083+ else !(initialized()))
1084+ then true
1085+ else if (!(isQuoteAsset))
1086+ then !(isCollateralAsset)
1087+ else false)
1088+ then true
1089+ else !(isSameAssetOrNoPosition(_trader, _assetIdStr)))
1090+ then true
1091+ else !(requireMoreMarginRatio(divd(DECIMAL_UNIT, _leverage), initMarginRatio(), true)))
1092+ then true
1093+ else paused())
1094+ then throw("Invalid increasePosition parameters")
1095+ else {
1096+ let doGetFeeDiscount = invoke(minerAddress(), "computeFeeDiscount", [_trader], nil)
1097+ if ((doGetFeeDiscount == doGetFeeDiscount))
1098+ then {
1099+ let feeDiscount = match doGetFeeDiscount {
1100+ case x: Int =>
1101+ x
1102+ case _ =>
1103+ throw("Invalid computeFeeDiscount result")
1104+ }
1105+ let $t05013750201 = getAdjustedFee(i, feeDiscount)
1106+ let adjustedFee = $t05013750201._1
1107+ let burnArtifact = $t05013750201._2
1108+ let rawFeeAmount = muld(_rawAmount, adjustedFee)
1109+ let _amount = (_rawAmount - rawFeeAmount)
1110+ let distributeFeeAmount = if (isCollateralAsset)
1111+ then {
1112+ let doBorrow = invoke(collateralAddress(), "borrow", [_trader], [AttachedPayment(_assetId, _amount)])
1113+ if ((doBorrow == doBorrow))
1114+ then {
1115+ let balanceBefore = assetBalance(this, quoteAsset())
1116+ if ((balanceBefore == balanceBefore))
1117+ then {
1118+ let doSwap = invoke(swapAddress(), "swap", [toBase58String(quoteAsset()), 0], [AttachedPayment(_assetId, rawFeeAmount)])
1119+ if ((doSwap == doSwap))
1120+ then {
1121+ let balanceAfter = assetBalance(this, quoteAsset())
1122+ if ((balanceAfter == balanceAfter))
1123+ then {
1124+ let exchangedAmount = (balanceAfter - balanceBefore)
1125+ if ((exchangedAmount == exchangedAmount))
1126+ then exchangedAmount
1127+ else throw("Strict value is not equal to itself.")
1128+ }
1129+ else throw("Strict value is not equal to itself.")
1130+ }
1131+ else throw("Strict value is not equal to itself.")
1132+ }
1133+ else throw("Strict value is not equal to itself.")
1134+ }
1135+ else throw("Strict value is not equal to itself.")
1136+ }
1137+ else rawFeeAmount
1138+ if ((distributeFeeAmount == distributeFeeAmount))
1139+ then {
1140+ let referrerFeeAny = invoke(referralAddress(), "acceptPaymentWithLink", [_trader, _refLink], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
1141+ if ((referrerFeeAny == referrerFeeAny))
1142+ then {
1143+ let referrerFee = match referrerFeeAny {
1144+ case x: Int =>
1145+ x
1146+ case _ =>
1147+ throw("Invalid referrerFee")
1148+ }
1149+ let feeAmount = (distributeFeeAmount - referrerFee)
1150+ let $t05151751657 = getPosition(_trader)
1151+ let oldPositionSize = $t05151751657._1
1152+ let oldPositionMargin = $t05151751657._2
1153+ let oldPositionOpenNotional = $t05151751657._3
1154+ let oldPositionLstUpdCPF = $t05151751657._4
1155+ let isNewPosition = (oldPositionSize == 0)
1156+ let isSameDirection = if ((oldPositionSize > 0))
1157+ then (_direction == DIR_LONG)
1158+ else (_direction == DIR_SHORT)
1159+ let expandExisting = if (!(isNewPosition))
1160+ then isSameDirection
1161+ else false
1162+ let isAdd = (_direction == DIR_LONG)
1163+ let $t05194654531 = if (if (isNewPosition)
1164+ then true
1165+ else expandExisting)
1166+ then {
1167+ let openNotional = muld(_amount, _leverage)
1168+ let $t05237052576 = swapInput(isAdd, openNotional)
1169+ let amountBaseAssetBought = $t05237052576._1
1170+ let quoteAssetReserveAfter = $t05237052576._2
1171+ let baseAssetReserveAfter = $t05237052576._3
1172+ let totalPositionSizeAfter = $t05237052576._4
1173+ let cumulativeNotionalAfter = $t05237052576._5
1174+ if (if ((_minBaseAssetAmount != 0))
1175+ then (_minBaseAssetAmount > abs(amountBaseAssetBought))
1176+ else false)
1177+ then throw(((("Limit error: " + toString(abs(amountBaseAssetBought))) + " < ") + toString(_minBaseAssetAmount)))
1178+ else {
1179+ let newPositionSize = (oldPositionSize + amountBaseAssetBought)
1180+ let increaseMarginRequirement = divd(openNotional, _leverage)
1181+ let $t05295753196 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, increaseMarginRequirement)
1182+ let remainMargin = $t05295753196._1
1183+ let x1 = $t05295753196._2
1184+ let x2 = $t05295753196._3
1185+ if (!(requireNotOverSpreadLimit(quoteAssetReserveAfter, baseAssetReserveAfter)))
1186+ then throw("Over max spread limit")
1187+ else $Tuple11(newPositionSize, remainMargin, (oldPositionOpenNotional + openNotional), latestCumulativePremiumFraction(newPositionSize), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, (openInterestNotional() + openNotional), (totalLongPositionSize() + (if ((newPositionSize > 0))
1188+ then abs(amountBaseAssetBought)
1189+ else 0)), (totalShortPositionSize() + (if ((0 > newPositionSize))
1190+ then abs(amountBaseAssetBought)
1191+ else 0)))
1192+ }
1193+ }
1194+ else {
1195+ let openNotional = muld(_amount, _leverage)
1196+ let $t05422454340 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1197+ let oldPositionNotional = $t05422454340._1
1198+ let unrealizedPnl = $t05422454340._2
1199+ if ((oldPositionNotional > openNotional))
1200+ then throw("Use decreasePosition to decrease position size")
1201+ else throw("Close position first")
1202+ }
1203+ let newPositionSize = $t05194654531._1
1204+ let newPositionRemainMargin = $t05194654531._2
1205+ let newPositionOpenNotional = $t05194654531._3
1206+ let newPositionLatestCPF = $t05194654531._4
1207+ let baseAssetReserveAfter = $t05194654531._5
1208+ let quoteAssetReserveAfter = $t05194654531._6
1209+ let totalPositionSizeAfter = $t05194654531._7
1210+ let cumulativeNotionalAfter = $t05194654531._8
1211+ let openInterestNotionalAfter = $t05194654531._9
1212+ let totalLongAfter = $t05194654531._10
1213+ let totalShortAfter = $t05194654531._11
1214+ let feeToStakers = (feeAmount / 2)
1215+ let feeToInsurance = (feeAmount - feeToStakers)
1216+ let stake = invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), _amount)])
1217+ if ((stake == stake))
1218+ then {
1219+ let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToInsurance)])
1220+ if ((depositInsurance == depositInsurance))
1221+ then {
1222+ let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, feeAmount], nil)
1223+ if ((notifyFee == notifyFee))
1224+ then {
1225+ let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
1226+ if ((notifyNotional == notifyNotional))
1227+ then (((((updatePosition(_trader, newPositionSize, newPositionRemainMargin, newPositionOpenNotional, newPositionLatestCPF) ++ updatePositionAsset(_trader, _assetIdStr)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter)) ++ transferFee(feeToStakers)) ++ updateBalance((cbalance() + _amount))) ++ doBurnArtifact(burnArtifact, i))
1228+ else throw("Strict value is not equal to itself.")
1229+ }
1230+ else throw("Strict value is not equal to itself.")
1231+ }
1232+ else throw("Strict value is not equal to itself.")
1233+ }
1234+ else throw("Strict value is not equal to itself.")
1235+ }
1236+ else throw("Strict value is not equal to itself.")
1237+ }
1238+ else throw("Strict value is not equal to itself.")
1239+ }
1240+ else throw("Strict value is not equal to itself.")
1241+ }
1242+ }
1243+ else throw("Strict value is not equal to itself.")
1244+ }
1245+
1246+
1247+
1248+@Callable(i)
1249+func addMargin () = {
1250+ let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
1251+ if ((sync == sync))
1252+ then {
1253+ let _trader = toString(i.caller)
1254+ let _rawAmount = i.payments[0].amount
1255+ let _assetId = i.payments[0].assetId
1256+ let _assetIdStr = toBase58String(value(_assetId))
1257+ let isQuoteAsset = (_assetId == quoteAsset())
1258+ let isCollateralAsset = isWhitelistAsset(_assetIdStr)
1259+ if (if (if (if (if (if (!(isQuoteAsset))
1260+ then !(isCollateralAsset)
1261+ else false)
1262+ then true
1263+ else !(requireOpenPosition(toString(i.caller))))
1264+ then true
1265+ else !(isSameAsset(_trader, _assetIdStr)))
1266+ then true
1267+ else !(initialized()))
1268+ then true
1269+ else paused())
1270+ then throw("Invalid addMargin parameters")
1271+ else {
1272+ let doGetFeeDiscount = invoke(minerAddress(), "computeFeeDiscount", [_trader], nil)
1273+ if ((doGetFeeDiscount == doGetFeeDiscount))
1274+ then {
1275+ let feeDiscount = match doGetFeeDiscount {
1276+ case x: Int =>
1277+ x
1278+ case _ =>
1279+ throw("Invalid computeFeeDiscount result")
1280+ }
1281+ let $t05660856672 = getAdjustedFee(i, feeDiscount)
1282+ let adjustedFee = $t05660856672._1
1283+ let burnArtifact = $t05660856672._2
1284+ let rawFeeAmount = muld(_rawAmount, adjustedFee)
1285+ let _amount = (_rawAmount - rawFeeAmount)
1286+ let distributeFeeAmount = if (isCollateralAsset)
1287+ then {
1288+ let doBorrow = invoke(collateralAddress(), "borrow", [_trader], [AttachedPayment(_assetId, _amount)])
1289+ if ((doBorrow == doBorrow))
1290+ then {
1291+ let balanceBefore = assetBalance(this, quoteAsset())
1292+ if ((balanceBefore == balanceBefore))
1293+ then {
1294+ let doSwap = invoke(swapAddress(), "swap", [toBase58String(quoteAsset()), 0], [AttachedPayment(_assetId, rawFeeAmount)])
1295+ if ((doSwap == doSwap))
1296+ then {
1297+ let balanceAfter = assetBalance(this, quoteAsset())
1298+ if ((balanceAfter == balanceAfter))
1299+ then {
1300+ let exchangedAmount = (balanceAfter - balanceBefore)
1301+ if ((exchangedAmount == exchangedAmount))
1302+ then exchangedAmount
1303+ else throw("Strict value is not equal to itself.")
1304+ }
1305+ else throw("Strict value is not equal to itself.")
1306+ }
1307+ else throw("Strict value is not equal to itself.")
1308+ }
1309+ else throw("Strict value is not equal to itself.")
1310+ }
1311+ else throw("Strict value is not equal to itself.")
1312+ }
1313+ else rawFeeAmount
1314+ if ((distributeFeeAmount == distributeFeeAmount))
1315+ then {
1316+ let referrerFeeAny = invoke(referralAddress(), "acceptPayment", [_trader], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
1317+ if ((referrerFeeAny == referrerFeeAny))
1318+ then {
1319+ let referrerFee = match referrerFeeAny {
1320+ case x: Int =>
1321+ x
1322+ case _ =>
1323+ throw("Invalid referrerFee")
1324+ }
1325+ let feeAmount = (distributeFeeAmount - referrerFee)
1326+ let $t05797158111 = getPosition(_trader)
1327+ let oldPositionSize = $t05797158111._1
1328+ let oldPositionMargin = $t05797158111._2
1329+ let oldPositionOpenNotional = $t05797158111._3
1330+ let oldPositionLstUpdCPF = $t05797158111._4
1331+ let feeToStakers = (feeAmount / 2)
1332+ let feeToInsurance = (feeAmount - feeToStakers)
1333+ let stake = invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), _amount)])
1334+ if ((stake == stake))
1335+ then {
1336+ let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToInsurance)])
1337+ if ((depositInsurance == depositInsurance))
1338+ then {
1339+ let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, feeAmount], nil)
1340+ if ((notifyFee == notifyFee))
1341+ then (((updatePosition(_trader, oldPositionSize, (oldPositionMargin + _amount), oldPositionOpenNotional, oldPositionLstUpdCPF) ++ transferFee(feeToStakers)) ++ updateBalance((cbalance() + _amount))) ++ doBurnArtifact(burnArtifact, i))
1342+ else throw("Strict value is not equal to itself.")
1343+ }
1344+ else throw("Strict value is not equal to itself.")
1345+ }
1346+ else throw("Strict value is not equal to itself.")
1347+ }
1348+ else throw("Strict value is not equal to itself.")
1349+ }
1350+ else throw("Strict value is not equal to itself.")
1351+ }
1352+ else throw("Strict value is not equal to itself.")
1353+ }
1354+ }
1355+ else throw("Strict value is not equal to itself.")
1356+ }
1357+
1358+
1359+
1360+@Callable(i)
1361+func removeMargin (_amount) = {
1362+ let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
1363+ if ((sync == sync))
1364+ then {
1365+ let _trader = toString(i.caller)
1366+ if (if (if (if ((0 >= _amount))
1367+ then true
1368+ else !(requireOpenPosition(_trader)))
1369+ then true
1370+ else !(initialized()))
1371+ then true
1372+ else paused())
1373+ then throw("Invalid removeMargin parameters")
1374+ else {
1375+ let $t05921759357 = getPosition(_trader)
1376+ let oldPositionSize = $t05921759357._1
1377+ let oldPositionMargin = $t05921759357._2
1378+ let oldPositionOpenNotional = $t05921759357._3
1379+ let oldPositionLstUpdCPF = $t05921759357._4
1380+ let marginDelta = -(_amount)
1381+ let $t05939459573 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, marginDelta)
1382+ let remainMargin = $t05939459573._1
1383+ let badDebt = $t05939459573._2
1384+ if ((badDebt != 0))
1385+ then throw("Invalid removed margin amount")
1386+ else {
1387+ let marginRatio = calcMarginRatio(remainMargin, badDebt, oldPositionOpenNotional)
1388+ if (!(requireMoreMarginRatio(marginRatio, initMarginRatio(), true)))
1389+ then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
1390+ else {
1391+ let quoteAssetStr = toBase58String(quoteAsset())
1392+ let $t06001760071 = getBorrowedByTrader(_trader)
1393+ let borrowed = $t06001760071._1
1394+ let assetId = $t06001760071._2
1395+ let toRepay = if ((_amount > borrowed))
1396+ then borrowed
1397+ else _amount
1398+ let toWithdraw = if ((borrowed > _amount))
1399+ then 0
1400+ else (_amount - borrowed)
1401+ let finalBorrow = (borrowed - toRepay)
1402+ let switchPositionToQuote = if ((finalBorrow > 0))
1403+ then nil
1404+ else updatePositionAsset(_trader, quoteAssetStr)
1405+ let doSanityCheck = if (((toRepay + toWithdraw) != _amount))
1406+ then throw(((((("toRepay=" + toString(toRepay)) + " + toWithdraw=") + toString(toWithdraw)) + " != ") + toString(_amount)))
1407+ else nil
1408+ if ((doSanityCheck == doSanityCheck))
1409+ then {
1410+ let doUnstake = invoke(vaultAddress(), "withdrawLocked", [_amount], nil)
1411+ if ((doUnstake == doUnstake))
1412+ then {
1413+ let returnCollateralAction = if ((toRepay > 0))
1414+ then {
1415+ let doRepay = invoke(collateralAddress(), "repay", [_trader, assetId], [AttachedPayment(quoteAsset(), toRepay)])
1416+ if ((doRepay == doRepay))
1417+ then [ScriptTransfer(i.caller, toRepay, fromBase58String(assetId))]
1418+ else throw("Strict value is not equal to itself.")
1419+ }
1420+ else nil
1421+ if ((returnCollateralAction == returnCollateralAction))
1422+ then ((((updatePosition(_trader, oldPositionSize, remainMargin, oldPositionOpenNotional, latestCumulativePremiumFraction(oldPositionSize)) ++ (if ((toWithdraw > 0))
1423+ then withdraw(i.caller, toWithdraw)
1424+ else nil)) ++ updateBalance((cbalance() - _amount))) ++ switchPositionToQuote) ++ returnCollateralAction)
1425+ else throw("Strict value is not equal to itself.")
1426+ }
1427+ else throw("Strict value is not equal to itself.")
1428+ }
1429+ else throw("Strict value is not equal to itself.")
1430+ }
1431+ }
1432+ }
1433+ }
1434+ else throw("Strict value is not equal to itself.")
1435+ }
1436+
1437+
1438+
1439+@Callable(i)
1440+func closePosition () = {
1441+ let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
1442+ if ((sync == sync))
1443+ then {
1444+ let _trader = getActualCaller(i)
1445+ let _traderAddress = valueOrErrorMessage(addressFromString(_trader), "Invalid caller")
1446+ if (if (if (!(requireOpenPosition(_trader)))
1447+ then true
1448+ else !(initialized()))
1449+ then true
1450+ else paused())
1451+ then throw("Invalid closePosition parameters")
1452+ else {
1453+ let $t06232162699 = internalClosePosition(_trader, true)
1454+ let x1 = $t06232162699._1
1455+ let positionBadDebt = $t06232162699._2
1456+ let realizedPnl = $t06232162699._3
1457+ let marginToVault = $t06232162699._4
1458+ let quoteAssetReserveAfter = $t06232162699._5
1459+ let baseAssetReserveAfter = $t06232162699._6
1460+ let totalPositionSizeAfter = $t06232162699._7
1461+ let cumulativeNotionalAfter = $t06232162699._8
1462+ let openInterestNotionalAfter = $t06232162699._9
1463+ let x2 = $t06232162699._10
1464+ let totalLongAfter = $t06232162699._11
1465+ let totalShortAfter = $t06232162699._12
1466+ if ((positionBadDebt > 0))
1467+ then throw("Unable to close position with bad debt")
1468+ else {
1469+ let withdrawAmount = abs(marginToVault)
1470+ let ammBalance = (cbalance() - withdrawAmount)
1471+ let $t06302363538 = if ((0 > ammBalance))
1472+ then $Tuple2(0, abs(ammBalance))
1473+ else $Tuple2(ammBalance, 0)
1474+ let ammNewBalance = $t06302363538._1
1475+ let x11 = $t06302363538._2
1476+ let unstake = invoke(vaultAddress(), "withdrawLocked", [withdrawAmount], nil)
1477+ if ((unstake == unstake))
1478+ then {
1479+ let $t06375063804 = getBorrowedByTrader(_trader)
1480+ let borrowed = $t06375063804._1
1481+ let assetId = $t06375063804._2
1482+ let $t06381964736 = if ((borrowed > 0))
1483+ then if ((withdrawAmount >= borrowed))
1484+ then {
1485+ let doRepay = invoke(collateralAddress(), "repay", [_trader, assetId], [AttachedPayment(quoteAsset(), borrowed)])
1486+ if ((doRepay == doRepay))
1487+ then $Tuple2([ScriptTransfer(_traderAddress, borrowed, fromBase58String(assetId))], (withdrawAmount - borrowed))
1488+ else throw("Strict value is not equal to itself.")
1489+ }
1490+ else {
1491+ let realizeAndClose = invoke(collateralAddress(), "realizePartiallyAndClose", [_trader, assetId], [AttachedPayment(quoteAsset(), withdrawAmount)])
1492+ if ((realizeAndClose == realizeAndClose))
1493+ then $Tuple2([ScriptTransfer(_traderAddress, withdrawAmount, fromBase58String(assetId))], 0)
1494+ else throw("Strict value is not equal to itself.")
1495+ }
1496+ else $Tuple2(nil, withdrawAmount)
1497+ if (($t06381964736 == $t06381964736))
1498+ then {
1499+ let quoteWithdrawAmount = $t06381964736._2
1500+ let sendCollateralAction = $t06381964736._1
1501+ let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, 0], nil)
1502+ if ((notifyNotional == notifyNotional))
1503+ then ((((deletePosition(_trader) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter)) ++ (if ((quoteWithdrawAmount > 0))
1504+ then withdraw(_traderAddress, quoteWithdrawAmount)
1505+ else nil)) ++ updateBalance(ammNewBalance)) ++ sendCollateralAction)
1506+ else throw("Strict value is not equal to itself.")
1507+ }
1508+ else throw("Strict value is not equal to itself.")
1509+ }
1510+ else throw("Strict value is not equal to itself.")
1511+ }
1512+ }
1513+ }
1514+ else throw("Strict value is not equal to itself.")
1515+ }
1516+
1517+
1518+
1519+@Callable(i)
1520+func liquidate (_trader) = {
1521+ let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
1522+ if ((sync == sync))
1523+ then {
1524+ let spotMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
1525+ let marginRatio = if (isOverFluctuationLimit())
1526+ then {
1527+ let oracleMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_ORACLE)
1528+ vmax(spotMarginRatio, oracleMarginRatio)
1529+ }
1530+ else spotMarginRatio
1531+ if (if (if (if (!(requireMoreMarginRatio(marginRatio, maintenanceMarginRatio(), false)))
1532+ then true
1533+ else !(requireOpenPosition(_trader)))
1534+ then true
1535+ else !(initialized()))
1536+ then true
1537+ else paused())
1538+ then throw("Unable to liquidate")
1539+ else if (if (if ((spotMarginRatio > liquidationFeeRatio()))
1540+ then (partialLiquidationRatio() > 0)
1541+ else false)
1542+ then (DECIMAL_UNIT > partialLiquidationRatio())
1543+ else false)
1544+ then {
1545+ let $t06650466654 = getPosition(_trader)
1546+ let oldPositionSize = $t06650466654._1
1547+ let oldPositionMargin = $t06650466654._2
1548+ let oldPositionOpenNotional = $t06650466654._3
1549+ let oldPositionLstUpdCPF = $t06650466654._4
1550+ let _direction = if ((oldPositionSize > 0))
1551+ then DIR_SHORT
1552+ else DIR_LONG
1553+ let isAdd = (_direction == DIR_LONG)
1554+ let exchangedQuoteAssetAmount = getPartialLiquidationAmount(_trader, oldPositionSize)
1555+ let $t06687966983 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1556+ let oldPositionNotional = $t06687966983._1
1557+ let unrealizedPnl = $t06687966983._2
1558+ let $t06699167223 = swapInput(isAdd, exchangedQuoteAssetAmount)
1559+ let exchangedPositionSize = $t06699167223._1
1560+ let quoteAssetReserveAfter = $t06699167223._2
1561+ let baseAssetReserveAfter = $t06699167223._3
1562+ let totalPositionSizeAfter = $t06699167223._4
1563+ let cumulativeNotionalAfter = $t06699167223._5
1564+ let liquidationRatio = divd(abs(exchangedPositionSize), abs(oldPositionSize))
1565+ let realizedPnl = muld(unrealizedPnl, liquidationRatio)
1566+ let $t06751267745 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1567+ let remainMargin = $t06751267745._1
1568+ let badDebt = $t06751267745._2
1569+ let fundingPayment = $t06751267745._3
1570+ let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
1571+ let remainOpenNotional = if ((oldPositionSize > 0))
1572+ then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
1573+ else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
1574+ let liquidationPenalty = muld(exchangedQuoteAssetAmount, liquidationFeeRatio())
1575+ let feeToLiquidator = (liquidationPenalty / 2)
1576+ let feeToInsurance = (liquidationPenalty - feeToLiquidator)
1577+ let newPositionMargin = (remainMargin - liquidationPenalty)
1578+ let newPositionSize = (oldPositionSize + exchangedPositionSize)
1579+ let newPositionOpenNotional = abs(remainOpenNotional)
1580+ let newPositionLstUpdCPF = latestCumulativePremiumFraction(newPositionSize)
1581+ let openInterestNotionalAfter = (openInterestNotional() - exchangedQuoteAssetAmount)
1582+ let ammBalance = (cbalance() - liquidationPenalty)
1583+ let $t06891869047 = if ((0 > ammBalance))
1584+ then $Tuple2(0, abs(ammBalance))
1585+ else $Tuple2(ammBalance, 0)
1586+ let newAmmBalance = $t06891869047._1
1587+ let x11 = $t06891869047._2
1588+ let $t06905569109 = getBorrowedByTrader(_trader)
1589+ let borrowed = $t06905569109._1
1590+ let assetId = $t06905569109._2
1591+ let doLiquidateCollateral = if ((borrowed > 0))
1592+ then {
1593+ let collateralToSell = muld(borrowed, liquidationRatio)
1594+ let realizeAndClose = invoke(collateralAddress(), "realizePartially", [_trader, assetId, collateralToSell], nil)
1595+ if ((realizeAndClose == realizeAndClose))
1596+ then nil
1597+ else throw("Strict value is not equal to itself.")
1598+ }
1599+ else nil
1600+ if ((doLiquidateCollateral == doLiquidateCollateral))
1601+ then {
1602+ let unstake = invoke(vaultAddress(), "withdrawLocked", [liquidationPenalty], nil)
1603+ if ((unstake == unstake))
1604+ then {
1605+ let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToInsurance)])
1606+ if ((depositInsurance == depositInsurance))
1607+ then {
1608+ let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
1609+ if ((notifyNotional == notifyNotional))
1610+ then (((updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, openInterestNotionalAfter, (totalLongPositionSize() - (if ((newPositionSize > 0))
1611+ then abs(exchangedPositionSize)
1612+ else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
1613+ then abs(exchangedPositionSize)
1614+ else 0)))) ++ withdraw(i.caller, feeToLiquidator)) ++ updateBalance(newAmmBalance))
1615+ else throw("Strict value is not equal to itself.")
1616+ }
1617+ else throw("Strict value is not equal to itself.")
1618+ }
1619+ else throw("Strict value is not equal to itself.")
1620+ }
1621+ else throw("Strict value is not equal to itself.")
1622+ }
1623+ else {
1624+ let $t07091471369 = internalClosePosition(_trader, false)
1625+ let x1 = $t07091471369._1
1626+ let badDebt = $t07091471369._2
1627+ let x2 = $t07091471369._3
1628+ let x3 = $t07091471369._4
1629+ let quoteAssetReserveAfter = $t07091471369._5
1630+ let baseAssetReserveAfter = $t07091471369._6
1631+ let totalPositionSizeAfter = $t07091471369._7
1632+ let cumulativeNotionalAfter = $t07091471369._8
1633+ let openInterestNotionalAfter = $t07091471369._9
1634+ let exchangedQuoteAssetAmount = $t07091471369._10
1635+ let totalLongAfter = $t07091471369._11
1636+ let totalShortAfter = $t07091471369._12
1637+ let liquidationPenalty = muld(exchangedQuoteAssetAmount, liquidationFeeRatio())
1638+ let feeToLiquidator = (liquidationPenalty / 2)
1639+ let feeToInsurance = (liquidationPenalty - feeToLiquidator)
1640+ let ammBalance = (cbalance() - liquidationPenalty)
1641+ let $t07178171910 = if ((0 > ammBalance))
1642+ then $Tuple2(0, abs(ammBalance))
1643+ else $Tuple2(ammBalance, 0)
1644+ let newAmmBalance = $t07178171910._1
1645+ let x11 = $t07178171910._2
1646+ let $t07191871972 = getBorrowedByTrader(_trader)
1647+ let borrowed = $t07191871972._1
1648+ let assetId = $t07191871972._2
1649+ let doLiquidateCollateral = if ((borrowed > 0))
1650+ then {
1651+ let realizeAndClose = invoke(collateralAddress(), "realizePartiallyAndClose", [_trader, assetId], nil)
1652+ if ((realizeAndClose == realizeAndClose))
1653+ then nil
1654+ else throw("Strict value is not equal to itself.")
1655+ }
1656+ else nil
1657+ if ((doLiquidateCollateral == doLiquidateCollateral))
1658+ then {
1659+ let x = if ((badDebt > 0))
1660+ then {
1661+ let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [badDebt], nil)
1662+ if ((lockBadDebt == lockBadDebt))
1663+ then nil
1664+ else throw("Strict value is not equal to itself.")
1665+ }
1666+ else nil
1667+ if ((x == x))
1668+ then {
1669+ let unstake = invoke(vaultAddress(), "withdrawLocked", [liquidationPenalty], nil)
1670+ if ((unstake == unstake))
1671+ then {
1672+ let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToInsurance)])
1673+ if ((depositInsurance == depositInsurance))
1674+ then {
1675+ let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, 0], nil)
1676+ if ((notifyNotional == notifyNotional))
1677+ then (((deletePosition(_trader) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter)) ++ withdraw(i.caller, feeToLiquidator)) ++ updateBalance(newAmmBalance))
1678+ else throw("Strict value is not equal to itself.")
1679+ }
1680+ else throw("Strict value is not equal to itself.")
1681+ }
1682+ else throw("Strict value is not equal to itself.")
1683+ }
1684+ else throw("Strict value is not equal to itself.")
1685+ }
1686+ else throw("Strict value is not equal to itself.")
1687+ }
1688+ }
1689+ else throw("Strict value is not equal to itself.")
1690+ }
1691+
1692+
1693+
1694+@Callable(i)
1695+func payFunding () = {
1696+ let fundingBlockTimestamp = nextFundingBlockTimestamp()
1697+ if (if (if ((fundingBlockTimestamp > lastBlock.timestamp))
1698+ then true
1699+ else !(initialized()))
1700+ then true
1701+ else paused())
1702+ then throw(((("Invalid funding block timestamp: " + toString(lastBlock.timestamp)) + " < ") + toString(fundingBlockTimestamp)))
1703+ else {
1704+ let underlyingPrice = getOracleTwapPrice()
1705+ let $t07399974061 = getFunding()
1706+ let shortPremiumFraction = $t07399974061._1
1707+ let longPremiumFraction = $t07399974061._2
1708+ updateFunding((fundingBlockTimestamp + fundingPeriodSeconds()), (latestLongCumulativePremiumFraction() + longPremiumFraction), (latestShortCumulativePremiumFraction() + shortPremiumFraction), divd(longPremiumFraction, underlyingPrice), divd(shortPremiumFraction, underlyingPrice))
1709+ }
1710+ }
1711+
1712+
1713+
1714+@Callable(i)
1715+func syncTerminalPriceToOracle () = {
1716+ let $t07444374564 = getSyncTerminalPrice(getOracleTwapPrice())
1717+ let newQuoteAssetWeight = $t07444374564._1
1718+ let newBaseAssetWeight = $t07444374564._2
1719+ let marginToVault = $t07444374564._3
1720+ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight)
1721+ }
1722+
1723+
1724+
1725+@Callable(i)
1726+func v_get (_trader) = {
1727+ let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
1728+ if ((sync == sync))
1729+ then {
1730+ let $t07474274802 = internalClosePosition(_trader, false)
1731+ let x1 = $t07474274802._1
1732+ let x2 = $t07474274802._2
1733+ let x3 = $t07474274802._3
1734+ let x4 = $t07474274802._4
1735+ throw((((s(x2) + s(x3)) + s(x4)) + s(getMarginRatio(_trader))))
1736+ }
1737+ else throw("Strict value is not equal to itself.")
1738+ }
1739+
1740+
1741+
1742+@Callable(i)
1743+func view_calcRemainMarginWithFundingPayment (_trader) = {
1744+ let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
1745+ if ((sync == sync))
1746+ then {
1747+ let $t07501375114 = getPosition(_trader)
1748+ let positionSize = $t07501375114._1
1749+ let positionMargin = $t07501375114._2
1750+ let pon = $t07501375114._3
1751+ let positionLstUpdCPF = $t07501375114._4
1752+ let $t07511775218 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1753+ let positionNotional = $t07511775218._1
1754+ let unrealizedPnl = $t07511775218._2
1755+ let $t07522175393 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
1756+ let remainMargin = $t07522175393._1
1757+ let badDebt = $t07522175393._2
1758+ let fundingPayment = $t07522175393._3
1759+ throw((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)))
1760+ }
1761+ else throw("Strict value is not equal to itself.")
1762+ }
1763+
1764+
1765+
1766+@Callable(i)
1767+func view_getPegAdjustCost (_price) = {
1768+ let result = getSyncTerminalPrice(_price)
1769+ throw(toString(result._3))
1770+ }
1771+
1772+
1773+
1774+@Callable(i)
1775+func view_getTerminalAmmPrice () = {
1776+ let $t07574075821 = getTerminalAmmState()
1777+ let terminalQuoteAssetReserve = $t07574075821._1
1778+ let terminalBaseAssetReserve = $t07574075821._2
1779+ let price = divd(muld(terminalQuoteAssetReserve, qtAstW()), muld(terminalBaseAssetReserve, bsAstW()))
1780+ throw(toString(price))
1781+ }
1782+
1783+
1784+
1785+@Callable(i)
1786+func view_getFunding () = {
1787+ let underlyingPrice = getOracleTwapPrice()
1788+ let $t07604076102 = getFunding()
1789+ let shortPremiumFraction = $t07604076102._1
1790+ let longPremiumFraction = $t07604076102._2
1791+ let longFunding = divd(longPremiumFraction, underlyingPrice)
1792+ let shortFunding = divd(shortPremiumFraction, underlyingPrice)
1793+ throw((((s(longFunding) + s(shortFunding)) + s(getTwapSpotPrice())) + s(getOracleTwapPrice())))
1794+ }
1795+
1796+
1797+
1798+@Callable(i)
1799+func view_getBorrowedByTrader (_trader) = {
1800+ let $t07639276446 = getBorrowedByTrader(_trader)
1801+ let borrowed = $t07639276446._1
1802+ let assetId = $t07639276446._2
1803+ throw((s(borrowed) + assetId))
1804+ }
1805+
1806+
1807+@Verifier(tx)
1808+func verify () = sigVerify(tx.bodyBytes, tx.proofs[0], adminPublicKey())
1809+

github/deemru/w8io/169f3d6 
98.58 ms