2023.03.22 18:27 [3566985] smart account 3PGZUh4Tk4uJswbJ9VHvSNGReyvoUV4yEuy > SELF 0.00000000 Waves

{ "type": 13, "id": "Gixy4wxZiNFtE5pHYY91MLzTgg39fpeHJ37dP2PVJnvD", "fee": 9000000, "feeAssetId": null, "timestamp": 1679498851739, "version": 2, "chainId": 87, "sender": "3PGZUh4Tk4uJswbJ9VHvSNGReyvoUV4yEuy", "senderPublicKey": "CxF1fBNj3x3GwTEkvfRLPFH48PjguPmPKo8DdXQtbGjX", "proofs": [ "5rW4THF58is6S77BJgfyYRocAQEbrs7eiCzFPry2QtuZYW1aFLJcMe2aUA1v8S1WvUdTvKxPQ4nqu3Fd4uvvfuNK" ], "script": "base64:BgJ2CAISABIAEgASABIAEgMKAQESAwoBARIQCg4BAQEBAQEBAQEBAQEBARIVChMBAQEBAQEBCAgIAQEBAQEBAQEBEgYKBAEBAQgSABIDCgEBEgUKAwEBBBIDCgEIEgASABIAEgMKAQgSAwoBARIAEgASABIECgIICLMBAAxrX2Jhc2VPcmFjbGUCDGtfYmFzZU9yYWNsZQANa19xdW90ZU9yYWNsZQINa19xdW90ZU9yYWNsZQAJa19iYWxhbmNlAglrX2JhbGFuY2UACmtfc2VxdWVuY2UCCmtfc2VxdWVuY2UADmtfcG9zaXRpb25TaXplAg5rX3Bvc2l0aW9uU2l6ZQAQa19wb3NpdGlvbk1hcmdpbgIQa19wb3NpdGlvbk1hcmdpbgAWa19wb3NpdGlvbk9wZW5Ob3Rpb25hbAIWa19wb3NpdGlvbk9wZW5Ob3Rpb25hbAAua19wb3NpdGlvbkxhc3RVcGRhdGVkQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgISa19wb3NpdGlvbkZyYWN0aW9uABJrX3Bvc2l0aW9uU2VxdWVuY2UCEmtfcG9zaXRpb25TZXF1ZW5jZQANa19wb3NpdGlvbkZlZQINa19wb3NpdGlvbkZlZQAea19wb3NpdGlvbkxhc3RVcGRhdGVkVGltZXN0YW1wAhNrX3Bvc2l0aW9uVGltZXN0YW1wAA1rX2luaXRpYWxpemVkAg1rX2luaXRpYWxpemVkAAhrX3BhdXNlZAIIa19wYXVzZWQACmtfZGVsaXN0ZWQCCmtfZGVsaXN0ZWQAC2tfY2xvc2VPbmx5AgtrX2Nsb3NlT25seQAFa19mZWUCBWtfZmVlAA1rX3JvbGxvdmVyRmVlAg5rX3JvbGxvdmVyX2ZlZQAPa19mdW5kaW5nUGVyaW9kAg9rX2Z1bmRpbmdQZXJpb2QAEWtfaW5pdE1hcmdpblJhdGlvAhFrX2luaXRNYXJnaW5SYXRpbwAYa19tYWludGVuYW5jZU1hcmdpblJhdGlvAgVrX21tcgAVa19saXF1aWRhdGlvbkZlZVJhdGlvAhVrX2xpcXVpZGF0aW9uRmVlUmF0aW8AGWtfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8CFmtfcGFydExpcXVpZGF0aW9uUmF0aW8ADWtfc3ByZWFkTGltaXQCDWtfc3ByZWFkTGltaXQAEGtfbWF4UHJpY2VJbXBhY3QCEGtfbWF4UHJpY2VJbXBhY3QAEGtfbWF4UHJpY2VTcHJlYWQCEGtfbWF4UHJpY2VTcHJlYWQAEWtfbWF4T3Blbk5vdGlvbmFsAhFrX21heE9wZW5Ob3Rpb25hbAAVa19mZWVUb1N0YWtlcnNQZXJjZW50AhVrX2ZlZVRvU3Rha2Vyc1BlcmNlbnQAEGtfbWF4T3JhY2xlRGVsYXkCEGtfbWF4T3JhY2xlRGVsYXkADWtfZnVuZGluZ01vZGUCDWtfZnVuZGluZ01vZGUAJWtfbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24CG2tfbGF0ZXN0TG9uZ1ByZW1pdW1GcmFjdGlvbgAma19sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24CHGtfbGF0ZXN0U2hvcnRQcmVtaXVtRnJhY3Rpb24AEmtfbmV4dEZ1bmRpbmdCbG9jawIea19uZXh0RnVuZGluZ0Jsb2NrTWluVGltZXN0YW1wABFrX2xvbmdGdW5kaW5nUmF0ZQIRa19sb25nRnVuZGluZ1JhdGUAEmtfc2hvcnRGdW5kaW5nUmF0ZQISa19zaG9ydEZ1bmRpbmdSYXRlABNrX3F1b3RlQXNzZXRSZXNlcnZlAghrX3F0QXN0UgASa19iYXNlQXNzZXRSZXNlcnZlAghrX2JzQXN0UgASa19xdW90ZUFzc2V0V2VpZ2h0AghrX3F0QXN0VwARa19iYXNlQXNzZXRXZWlnaHQCCGtfYnNBc3RXABNrX3RvdGFsUG9zaXRpb25TaXplAhNrX3RvdGFsUG9zaXRpb25TaXplABdrX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQIXa190b3RhbExvbmdQb3NpdGlvblNpemUAGGtfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQIYa190b3RhbFNob3J0UG9zaXRpb25TaXplABZrX29wZW5JbnRlcmVzdE5vdGlvbmFsAhZrX29wZW5JbnRlcmVzdE5vdGlvbmFsABNrX29wZW5JbnRlcmVzdFNob3J0AhNrX29wZW5JbnRlcmVzdFNob3J0ABJrX29wZW5JbnRlcmVzdExvbmcCEmtfb3BlbkludGVyZXN0TG9uZwAIa19sYXN0VHgCCGtfbGFzdFR4ABRrX2Nvb3JkaW5hdG9yQWRkcmVzcwIUa19jb29yZGluYXRvckFkZHJlc3MAD2tfdmF1bHRfYWRkcmVzcwIPa192YXVsdF9hZGRyZXNzAA9rX2FkbWluX2FkZHJlc3MCD2tfYWRtaW5fYWRkcmVzcwANa19xdW90ZV9hc3NldAINa19xdW90ZV9hc3NldAAPa19xdW90ZV9zdGFraW5nAg9rX3F1b3RlX3N0YWtpbmcAEWtfc3Rha2luZ19hZGRyZXNzAhFrX3N0YWtpbmdfYWRkcmVzcwAPa19taW5lcl9hZGRyZXNzAg9rX21pbmVyX2FkZHJlc3MAEGtfb3JkZXJzX2FkZHJlc3MCEGtfb3JkZXJzX2FkZHJlc3MAEmtfcmVmZXJyYWxfYWRkcmVzcwISa19yZWZlcnJhbF9hZGRyZXNzABJrX2V4Y2hhbmdlX2FkZHJlc3MCEmtfZXhjaGFuZ2VfYWRkcmVzcwAVa19uZnRfbWFuYWdlcl9hZGRyZXNzAhVrX25mdF9tYW5hZ2VyX2FkZHJlc3MBDnRvQ29tcG9zaXRlS2V5AgRfa2V5CF9hZGRyZXNzCQCsAgIJAKwCAgUEX2tleQIBXwUIX2FkZHJlc3MBC2Nvb3JkaW5hdG9yAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIFBHRoaXMFFGtfY29vcmRpbmF0b3JBZGRyZXNzAhNDb29yZGluYXRvciBub3Qgc2V0AQxhZG1pbkFkZHJlc3MACQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFD2tfYWRtaW5fYWRkcmVzcwEKcXVvdGVBc3NldAAJANkEAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUNa19xdW90ZV9hc3NldAERcXVvdGVBc3NldFN0YWtpbmcACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUPa19xdW90ZV9zdGFraW5nAhtRdW90ZSBhc3NldCBzdGFraW5nIG5vdCBzZXQBDnN0YWtpbmdBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFEWtfc3Rha2luZ19hZGRyZXNzAg9TdGFraW5nIG5vdCBzZXQBDHZhdWx0QWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABQ9rX3ZhdWx0X2FkZHJlc3MCDVZhdWx0IG5vdCBzZXQBDG1pbmVyQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABQ9rX21pbmVyX2FkZHJlc3MCDU1pbmVyIG5vdCBzZXQBDW9yZGVyc0FkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUQa19vcmRlcnNfYWRkcmVzcwIOT3JkZXJzIG5vdCBzZXQBD3JlZmVycmFsQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABRJrX3JlZmVycmFsX2FkZHJlc3MCEFJlZmVycmFsIG5vdCBzZXQBEW5mdE1hbmFnZXJBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFFWtfbmZ0X21hbmFnZXJfYWRkcmVzcwITTkZUIE1hbmFnZXIgbm90IHNldAANa190b2tlbl9wYXJhbQINa190b2tlbl9wYXJhbQAMa190b2tlbl90eXBlAgxrX3Rva2VuX3R5cGUAGEZFRV9SRURVQ1RJT05fVE9LRU5fVFlQRQINZmVlX3JlZHVjdGlvbgAIRElSX0xPTkcAAQAJRElSX1NIT1JUAAIAB1NFQ09ORFMA6AcAD0RFQ0lNQUxfTlVNQkVSUwAGAAxERUNJTUFMX1VOSVQJAGgCAAEJAGgCCQBoAgkAaAIJAGgCCQBoAgAKAAoACgAKAAoACgAPTUlOVVRFU19JTl9ZRUFSCQBoAgCgiiAFDERFQ0lNQUxfVU5JVAAHT05FX0RBWQkAaAIAgKMFBQxERUNJTUFMX1VOSVQAD1BOTF9PUFRJT05fU1BPVAABABFQTkxfT1BUSU9OX09SQUNMRQACABJGVU5ESU5HX0FTWU1NRVRSSUMAAQARRlVORElOR19TWU1NRVRSSUMAAgEBcwECX3gJAKwCAgkApAMBBQJfeAIBLAEEZGl2ZAICX3gCX3kJAG4EBQJfeAUMREVDSU1BTF9VTklUBQJfeQUISEFMRkVWRU4BBG11bGQCAl94Al95CQBuBAUCX3gFAl95BQxERUNJTUFMX1VOSVQFCEhBTEZFVkVOAQViZGl2ZAICX3gCX3kJAL0CBAUCX3gJALYCAQUMREVDSU1BTF9VTklUBQJfeQUISEFMRkVWRU4BBWJtdWxkAgJfeAJfeQkAvQIEBQJfeAUCX3kJALYCAQUMREVDSU1BTF9VTklUBQhIQUxGRVZFTgEDYWJzAQJfeAMJAGYCBQJfeAAABQJfeAkBAS0BBQJfeAEEdm1heAICX3gCX3kDCQBnAgUCX3gFAl95BQJfeAUCX3kBA2ludAEBawkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFBHRoaXMFAWsJAKwCAgINbm8gdmFsdWUgZm9yIAUBawEFaW50T3ICAWsDZGVmCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFAWsFA2RlZgEEc3RyQQIIX2FkZHJlc3MEX2tleQQDdmFsCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUIX2FkZHJlc3MFBF9rZXkJAKwCAgIRTm8gdmFsdWUgZm9yIGtleSAFBF9rZXkFA3ZhbAEEaW50QQIIX2FkZHJlc3MEX2tleQQDdmFsCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUIX2FkZHJlc3MFBF9rZXkJAKwCAgIRTm8gdmFsdWUgZm9yIGtleSAFBF9rZXkFA3ZhbAEIY2JhbGFuY2UACQEDaW50AQUJa19iYWxhbmNlAQNmZWUACQEDaW50AQUFa19mZWUBD3JvbGxvdmVyRmVlUmF0ZQAJAQNpbnQBBQ1rX3JvbGxvdmVyRmVlAQ9pbml0TWFyZ2luUmF0aW8ACQEDaW50AQURa19pbml0TWFyZ2luUmF0aW8BBnF0QXN0UgAJAQNpbnQBBRNrX3F1b3RlQXNzZXRSZXNlcnZlAQZic0FzdFIACQEDaW50AQUSa19iYXNlQXNzZXRSZXNlcnZlAQZxdEFzdFcACQEFaW50T3ICBRJrX3F1b3RlQXNzZXRXZWlnaHQFDERFQ0lNQUxfVU5JVAEGYnNBc3RXAAkBBWludE9yAgURa19iYXNlQXNzZXRXZWlnaHQFDERFQ0lNQUxfVU5JVAERdG90YWxQb3NpdGlvblNpemUACQEDaW50AQUTa190b3RhbFBvc2l0aW9uU2l6ZQEUb3BlbkludGVyZXN0Tm90aW9uYWwACQEDaW50AQUWa19vcGVuSW50ZXJlc3ROb3Rpb25hbAERb3BlbkludGVyZXN0U2hvcnQACQEDaW50AQUTa19vcGVuSW50ZXJlc3RTaG9ydAEQb3BlbkludGVyZXN0TG9uZwAJAQNpbnQBBRJrX29wZW5JbnRlcmVzdExvbmcBGW5leHRGdW5kaW5nQmxvY2tUaW1lc3RhbXAACQEDaW50AQUSa19uZXh0RnVuZGluZ0Jsb2NrARBmdW5kaW5nUGVyaW9kUmF3AAkBA2ludAEFD2tfZnVuZGluZ1BlcmlvZAEUZnVuZGluZ1BlcmlvZERlY2ltYWwACQBoAgkBEGZ1bmRpbmdQZXJpb2RSYXcABQxERUNJTUFMX1VOSVQBFGZ1bmRpbmdQZXJpb2RTZWNvbmRzAAkAaAIJARBmdW5kaW5nUGVyaW9kUmF3AAUHU0VDT05EUwEWbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwAJAQNpbnQBBRhrX21haW50ZW5hbmNlTWFyZ2luUmF0aW8BE2xpcXVpZGF0aW9uRmVlUmF0aW8ACQEDaW50AQUVa19saXF1aWRhdGlvbkZlZVJhdGlvARdwYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwAJAQNpbnQBBRlrX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAQtzcHJlYWRMaW1pdAAJAQNpbnQBBQ1rX3NwcmVhZExpbWl0AQ5tYXhQcmljZUltcGFjdAAJAQNpbnQBBRBrX21heFByaWNlSW1wYWN0AQ5tYXhQcmljZVNwcmVhZAAJAQNpbnQBBRBrX21heFByaWNlU3ByZWFkAQ9tYXhPcGVuTm90aW9uYWwACQEDaW50AQURa19tYXhPcGVuTm90aW9uYWwBI2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAkBA2ludAEFJWtfbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BJGxhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAJAQNpbnQBBSZrX2xhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAJAQNpbnQBBRhrX3RvdGFsU2hvcnRQb3NpdGlvblNpemUBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQAJAQNpbnQBBRdrX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQEMbGFzdFNlcXVlbmNlAAkBBWludE9yAgUKa19zZXF1ZW5jZQAAARNmZWVUb1N0YWtlcnNQZXJjZW50AAkBA2ludAEFFWtfZmVlVG9TdGFrZXJzUGVyY2VudAEObWF4T3JhY2xlRGVsYXkACQEDaW50AQUQa19tYXhPcmFjbGVEZWxheQELZnVuZGluZ01vZGUACQEFaW50T3ICBQ1rX2Z1bmRpbmdNb2RlBRJGVU5ESU5HX0FTWU1NRVRSSUMBDWxhc3RUaW1lc3RhbXAACAUJbGFzdEJsb2NrCXRpbWVzdGFtcAEPZ2V0QWN0dWFsQ2FsbGVyAQFpCQELdmFsdWVPckVsc2UCCQCdCAIJAQ1vcmRlcnNBZGRyZXNzAAIIa19zZW5kZXIJAKUIAQgFAWkGY2FsbGVyARZyZXF1aXJlTW9yZU1hcmdpblJhdGlvAwxfbWFyZ2luUmF0aW8QX2Jhc2VNYXJnaW5SYXRpbxRfbGFyZ2VyVGhhbk9yRXF1YWxUbwQUcmVtYWluaW5nTWFyZ2luUmF0aW8JAGUCBQxfbWFyZ2luUmF0aW8FEF9iYXNlTWFyZ2luUmF0aW8DAwUUX2xhcmdlclRoYW5PckVxdWFsVG8JAGYCAAAFFHJlbWFpbmluZ01hcmdpblJhdGlvBwkAAgEJAKwCAgkArAICCQCsAgICEEludmFsaWQgbWFyZ2luOiAJAKQDAQUMX21hcmdpblJhdGlvAgMgPCAJAKQDAQUQX2Jhc2VNYXJnaW5SYXRpbwMDCQEBIQEFFF9sYXJnZXJUaGFuT3JFcXVhbFRvCQBnAgUUcmVtYWluaW5nTWFyZ2luUmF0aW8AAAcJAAIBCQCsAgIJAKwCAgkArAICAhBJbnZhbGlkIG1hcmdpbjogCQCkAwEFDF9tYXJnaW5SYXRpbwIDID4gCQCkAwEFEF9iYXNlTWFyZ2luUmF0aW8GAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQ1fcG9zaXRpb25TaXplAwkAAAIFDV9wb3NpdGlvblNpemUAAAkAAgECLFNob3VsZCBub3QgYmUgY2FsbGVkIHdpdGggX3Bvc2l0aW9uU2l6ZSA9PSAwAwkAZgIFDV9wb3NpdGlvblNpemUAAAkBI2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAkBJGxhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgABC2dldFBvc2l0aW9uAQdfdHJhZGVyBA9wb3NpdGlvblNpemVPcHQJAJoIAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUOa19wb3NpdGlvblNpemUFB190cmFkZXIEByRtYXRjaDAFD3Bvc2l0aW9uU2l6ZU9wdAMJAAECBQckbWF0Y2gwAgNJbnQEDHBvc2l0aW9uU2l6ZQUHJG1hdGNoMAkAlwoFBQxwb3NpdGlvblNpemUJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFEGtfcG9zaXRpb25NYXJnaW4FB190cmFkZXIJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFFmtfcG9zaXRpb25PcGVuTm90aW9uYWwFB190cmFkZXIJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFLmtfcG9zaXRpb25MYXN0VXBkYXRlZEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FB190cmFkZXIJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFHmtfcG9zaXRpb25MYXN0VXBkYXRlZFRpbWVzdGFtcAUHX3RyYWRlcgkAlwoFAAAAAAAAAAAAAAEOZ2V0UG9zaXRpb25GZWUBB190cmFkZXIEDnBvc2l0aW9uRmVlT3B0CQCaCAIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFDWtfcG9zaXRpb25GZWUFB190cmFkZXIEByRtYXRjaDAFDnBvc2l0aW9uRmVlT3B0AwkAAQIFByRtYXRjaDACA0ludAQLcG9zaXRpb25GZWUFByRtYXRjaDAFC3Bvc2l0aW9uRmVlCQEDZmVlAAETcmVxdWlyZU9wZW5Qb3NpdGlvbgEHX3RyYWRlcgMJAAACCAkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgJfMQAACQACAQIQTm8gb3BlbiBwb3NpdGlvbgYBDWdldE9yYWNsZURhdGEBA2tleQQNb3JhY2xlRGF0YVN0cgkAnQgCBQR0aGlzBQNrZXkDAwkBCWlzRGVmaW5lZAEFDW9yYWNsZURhdGFTdHIJAQIhPQIJAQV2YWx1ZQEFDW9yYWNsZURhdGFTdHICAAcECm9yYWNsZURhdGEJALUJAgkBBXZhbHVlAQUNb3JhY2xlRGF0YVN0cgIBLAQNb3JhY2xlQWRkcmVzcwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJAJEDAgUKb3JhY2xlRGF0YQAACQCsAgICG0ludmFsaWQgb3JhY2xlIGFkZHJlc3MgaW46IAkBBXZhbHVlAQUNb3JhY2xlRGF0YVN0cgQIcHJpY2VLZXkJAJEDAgUKb3JhY2xlRGF0YQABBAhibG9ja0tleQkAkQMCBQpvcmFjbGVEYXRhAAIEB29wZW5LZXkJAJEDAgUKb3JhY2xlRGF0YQADCQCWCgQFDW9yYWNsZUFkZHJlc3MFCHByaWNlS2V5BQhibG9ja0tleQUHb3BlbktleQUEdW5pdAELaW5pdGlhbGl6ZWQACQELdmFsdWVPckVsc2UCCQCbCAIFBHRoaXMFDWtfaW5pdGlhbGl6ZWQHAQZwYXVzZWQACQELdmFsdWVPckVsc2UCCQCbCAIFBHRoaXMFCGtfcGF1c2VkBwEIZGVsaXN0ZWQACQELdmFsdWVPckVsc2UCCQCbCAIFBHRoaXMFCmtfZGVsaXN0ZWQHAQljbG9zZU9ubHkACQELdmFsdWVPckVsc2UCCQCbCAIFBHRoaXMFC2tfY2xvc2VPbmx5BwENdXBkYXRlUmVzZXJ2ZQMGX2lzQWRkEV9xdW90ZUFzc2V0QW1vdW50EF9iYXNlQXNzZXRBbW91bnQDBQZfaXNBZGQEB25ld0Jhc2UJAGUCCQEGYnNBc3RSAAUQX2Jhc2VBc3NldEFtb3VudAMJAGcCAAAFB25ld0Jhc2UJAAIBAipUeCBsZWFkIHRvIGJhc2UgYXNzZXQgcmVzZXJ2ZSA8PSAwLCByZXZlcnQJAJUKAwkAZAIJAQZxdEFzdFIABRFfcXVvdGVBc3NldEFtb3VudAUHbmV3QmFzZQkAZAIJARF0b3RhbFBvc2l0aW9uU2l6ZQAFEF9iYXNlQXNzZXRBbW91bnQECG5ld1F1b3RlCQBlAgkBBnF0QXN0UgAFEV9xdW90ZUFzc2V0QW1vdW50AwkAZwIAAAUIbmV3UXVvdGUJAAIBAipUeCBsZWFkIHRvIGJhc2UgcXVvdGUgcmVzZXJ2ZSA8PSAwLCByZXZlcnQJAJUKAwUIbmV3UXVvdGUJAGQCCQEGYnNBc3RSAAUQX2Jhc2VBc3NldEFtb3VudAkAZQIJARF0b3RhbFBvc2l0aW9uU2l6ZQAFEF9iYXNlQXNzZXRBbW91bnQBDWNhbGNJbnZhcmlhbnQCB19xdEFzdFIHX2JzQXN0UgQHYnF0QXN0UgkAtgIBBQdfcXRBc3RSBAdiYnNBc3RSCQC2AgEFB19ic0FzdFIJAQVibXVsZAIFB2JxdEFzdFIFB2Jic0FzdFIBCXN3YXBJbnB1dAIGX2lzQWRkEV9xdW90ZUFzc2V0QW1vdW50BAdfcXRBc3RSCQEGcXRBc3RSAAQHX2JzQXN0UgkBBmJzQXN0UgAEB19xdEFzdFcJAQZxdEFzdFcABAdfYnNBc3RXCQEGYnNBc3RXAAQYcXVvdGVBc3NldEFtb3VudEFkanVzdGVkCQEEZGl2ZAIFEV9xdW90ZUFzc2V0QW1vdW50BQdfcXRBc3RXBAFrCQENY2FsY0ludmFyaWFudAIFB19xdEFzdFIFB19ic0FzdFIEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIDBQZfaXNBZGQJAGQCBQdfcXRBc3RSBRhxdW90ZUFzc2V0QW1vdW50QWRqdXN0ZWQJAGUCBQdfcXRBc3RSBRhxdW90ZUFzc2V0QW1vdW50QWRqdXN0ZWQEFWJhc2VBc3NldFJlc2VydmVBZnRlcgkAoAMBCQEFYmRpdmQCBQFrCQC2AgEFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIEGGFtb3VudEJhc2VBc3NldEJvdWdodEFicwkBA2FicwEJAGUCBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFB19ic0FzdFIEFWFtb3VudEJhc2VBc3NldEJvdWdodAMFBl9pc0FkZAUYYW1vdW50QmFzZUFzc2V0Qm91Z2h0QWJzCQEBLQEFGGFtb3VudEJhc2VBc3NldEJvdWdodEFicwQNJHQwMTU3NzkxNTk0OQkBDXVwZGF0ZVJlc2VydmUDBQZfaXNBZGQFGHF1b3RlQXNzZXRBbW91bnRBZGp1c3RlZAUYYW1vdW50QmFzZUFzc2V0Qm91Z2h0QWJzBBdxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyMQgFDSR0MDE1Nzc5MTU5NDkCXzEEFmJhc2VBc3NldFJlc2VydmVBZnRlcjEIBQ0kdDAxNTc3OTE1OTQ5Al8yBBd0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyMQgFDSR0MDE1Nzc5MTU5NDkCXzMEC3ByaWNlQmVmb3JlCQEEZGl2ZAIJAQRtdWxkAgUHX3F0QXN0UgUHX3F0QXN0VwkBBG11bGQCBQdfYnNBc3RSBQdfYnNBc3RXBAttYXJrZXRQcmljZQkBBGRpdmQCBRFfcXVvdGVBc3NldEFtb3VudAUYYW1vdW50QmFzZUFzc2V0Qm91Z2h0QWJzBAlwcmljZURpZmYJAQNhYnMBCQBlAgULcHJpY2VCZWZvcmUFC21hcmtldFByaWNlBAtwcmljZUltcGFjdAkAZQIFDERFQ0lNQUxfVU5JVAkBBGRpdmQCBQtwcmljZUJlZm9yZQkAZAIFC3ByaWNlQmVmb3JlBQlwcmljZURpZmYEE21heFByaWNlSW1wYWN0VmFsdWUJAQ5tYXhQcmljZUltcGFjdAADCQBmAgULcHJpY2VJbXBhY3QFE21heFByaWNlSW1wYWN0VmFsdWUJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICDVByaWNlIGltcGFjdCAJAKQDAQULcHJpY2VJbXBhY3QCFCA+IG1heCBwcmljZSBpbXBhY3QgCQCkAwEFE21heFByaWNlSW1wYWN0VmFsdWUCFSBiZWZvcmUgcXVvdGUgYXNzZXQ6IAkApAMBBQdfcXRBc3RSAhQgYmVmb3JlIGJhc2UgYXNzZXQ6IAkApAMBBQdfYnNBc3RSAiEgcXVvdGUgYXNzZXQgYW1vdW50IHRvIGV4Y2hhbmdlOiAJAKQDAQURX3F1b3RlQXNzZXRBbW91bnQCDyBwcmljZSBiZWZvcmU6IAkApAMBBQtwcmljZUJlZm9yZQIOIG1hcmtldFByaWNlOiAJAKQDAQULbWFya2V0UHJpY2UJAJYKBAUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0BRdxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyMQUWYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyMQUXdG90YWxQb3NpdGlvblNpemVBZnRlcjEBD2NhbGNSb2xsb3ZlckZlZQISX29sZFBvc2l0aW9uTWFyZ2luIF9vbGRQb3NpdGlvbkxhc3RVcGRhdGVkVGltZXN0YW1wBA9wb3NpdGlvbk1pbnV0ZXMJAGgCCQBpAgkAaQIJAGUCCQENbGFzdFRpbWVzdGFtcAAFIF9vbGRQb3NpdGlvbkxhc3RVcGRhdGVkVGltZXN0YW1wAOgHADwFDERFQ0lNQUxfVU5JVAQLcm9sbG92ZXJGZWUJAQRkaXZkAgkBBG11bGQCCQEEbXVsZAIFEl9vbGRQb3NpdGlvbk1hcmdpbgUPcG9zaXRpb25NaW51dGVzCQEPcm9sbG92ZXJGZWVSYXRlAAUPTUlOVVRFU19JTl9ZRUFSBQtyb2xsb3ZlckZlZQEwY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudEFuZFJvbGxvdmVyRmVlBRBfb2xkUG9zaXRpb25TaXplEl9vbGRQb3NpdGlvbk1hcmdpbiVfb2xkUG9zaXRpb25DdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uIF9vbGRQb3NpdGlvbkxhc3RVcGRhdGVkVGltZXN0YW1wDF9tYXJnaW5EZWx0YQQOZnVuZGluZ1BheW1lbnQDCQECIT0CBRBfb2xkUG9zaXRpb25TaXplAAAEIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uCQEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEFEF9vbGRQb3NpdGlvblNpemUJAQRtdWxkAgkAZQIFIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBSVfb2xkUG9zaXRpb25DdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBRBfb2xkUG9zaXRpb25TaXplAAAEC3JvbGxvdmVyRmVlCQEPY2FsY1JvbGxvdmVyRmVlAgUSX29sZFBvc2l0aW9uTWFyZ2luBSBfb2xkUG9zaXRpb25MYXN0VXBkYXRlZFRpbWVzdGFtcAQMc2lnbmVkTWFyZ2luCQBkAgkAZQIJAGUCBQxfbWFyZ2luRGVsdGEFC3JvbGxvdmVyRmVlBQ5mdW5kaW5nUGF5bWVudAUSX29sZFBvc2l0aW9uTWFyZ2luBA0kdDAxODIwNDE4MzMxAwkAZgIAAAUMc2lnbmVkTWFyZ2luCQCUCgIAAAkBA2FicwEFDHNpZ25lZE1hcmdpbgkAlAoCCQEDYWJzAQUMc2lnbmVkTWFyZ2luAAAEDHJlbWFpbk1hcmdpbggFDSR0MDE4MjA0MTgzMzECXzEEB2JhZERlYnQIBQ0kdDAxODIwNDE4MzMxAl8yCQCWCgQFDHJlbWFpbk1hcmdpbgUHYmFkRGVidAUOZnVuZGluZ1BheW1lbnQFC3JvbGxvdmVyRmVlARZzd2FwT3V0cHV0V2l0aFJlc2VydmVzBwZfaXNBZGQQX2Jhc2VBc3NldEFtb3VudBRfY2hlY2tNYXhQcmljZUltcGFjdBJfcXVvdGVBc3NldFJlc2VydmURX3F1b3RlQXNzZXRXZWlnaHQRX2Jhc2VBc3NldFJlc2VydmUQX2Jhc2VBc3NldFdlaWdodAQLcHJpY2VCZWZvcmUJAQRkaXZkAgkBBG11bGQCBRJfcXVvdGVBc3NldFJlc2VydmUFEV9xdW90ZUFzc2V0V2VpZ2h0CQEEbXVsZAIFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0V2VpZ2h0AwkAAAIFEF9iYXNlQXNzZXRBbW91bnQAAAkAAgECGUludmFsaWQgYmFzZSBhc3NldCBhbW91bnQEAWsJAQ1jYWxjSW52YXJpYW50AgUSX3F1b3RlQXNzZXRSZXNlcnZlBRFfYmFzZUFzc2V0UmVzZXJ2ZQQYYmFzZUFzc2V0UG9vbEFtb3VudEFmdGVyAwUGX2lzQWRkCQBkAgURX2Jhc2VBc3NldFJlc2VydmUFEF9iYXNlQXNzZXRBbW91bnQJAGUCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldEFtb3VudAQPcXVvdGVBc3NldEFmdGVyCQCgAwEJAQViZGl2ZAIFAWsJALYCAQUYYmFzZUFzc2V0UG9vbEFtb3VudEFmdGVyBA9xdW90ZUFzc2V0RGVsdGEJAQNhYnMBCQBlAgUPcXVvdGVBc3NldEFmdGVyBRJfcXVvdGVBc3NldFJlc2VydmUEDnF1b3RlQXNzZXRTb2xkCQEEbXVsZAIFD3F1b3RlQXNzZXREZWx0YQURX3F1b3RlQXNzZXRXZWlnaHQEE21heFByaWNlSW1wYWN0VmFsdWUJAQ5tYXhQcmljZUltcGFjdAAEDSR0MDE5NTkzMTk3NTUJAQ11cGRhdGVSZXNlcnZlAwkBASEBBQZfaXNBZGQFD3F1b3RlQXNzZXREZWx0YQUQX2Jhc2VBc3NldEFtb3VudAQXcXVvdGVBc3NldFJlc2VydmVBZnRlcjEIBQ0kdDAxOTU5MzE5NzU1Al8xBBZiYXNlQXNzZXRSZXNlcnZlQWZ0ZXIxCAUNJHQwMTk1OTMxOTc1NQJfMgQXdG90YWxQb3NpdGlvblNpemVBZnRlcjEIBQ0kdDAxOTU5MzE5NzU1Al8zBAttYXJrZXRQcmljZQkBBGRpdmQCBQ5xdW90ZUFzc2V0U29sZAUQX2Jhc2VBc3NldEFtb3VudAQJcHJpY2VEaWZmCQEDYWJzAQkAZQIFC3ByaWNlQmVmb3JlBQttYXJrZXRQcmljZQQLcHJpY2VJbXBhY3QJAGUCBQxERUNJTUFMX1VOSVQJAQRkaXZkAgULcHJpY2VCZWZvcmUJAGQCBQtwcmljZUJlZm9yZQUJcHJpY2VEaWZmAwMJAGYCBQtwcmljZUltcGFjdAUTbWF4UHJpY2VJbXBhY3RWYWx1ZQUUX2NoZWNrTWF4UHJpY2VJbXBhY3QHCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAg1QcmljZSBpbXBhY3QgCQCkAwEFC3ByaWNlSW1wYWN0AhQgPiBtYXggcHJpY2UgaW1wYWN0IAkApAMBBRNtYXhQcmljZUltcGFjdFZhbHVlAhUgYmVmb3JlIHF1b3RlIGFzc2V0OiAJAKQDAQUSX3F1b3RlQXNzZXRSZXNlcnZlAhQgYmVmb3JlIGJhc2UgYXNzZXQ6IAkApAMBBRFfYmFzZUFzc2V0UmVzZXJ2ZQIgIGJhc2UgYXNzZXQgYW1vdW50IHRvIGV4Y2hhbmdlOiAJAKQDAQUQX2Jhc2VBc3NldEFtb3VudAIPIHByaWNlIGJlZm9yZTogCQCkAwEFC3ByaWNlQmVmb3JlAg8gbWFya2V0IHByaWNlOiAJAKQDAQULbWFya2V0UHJpY2UJAJkKBwUOcXVvdGVBc3NldFNvbGQFF3F1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIxBRZiYXNlQXNzZXRSZXNlcnZlQWZ0ZXIxBRd0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyMQkAZQIJARV0b3RhbExvbmdQb3NpdGlvblNpemUAAwUGX2lzQWRkCQEDYWJzAQUQX2Jhc2VBc3NldEFtb3VudAAACQBlAgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUAAwkBASEBBQZfaXNBZGQJAQNhYnMBBRBfYmFzZUFzc2V0QW1vdW50AAAFC3ByaWNlSW1wYWN0AQpzd2FwT3V0cHV0AwZfaXNBZGQQX2Jhc2VBc3NldEFtb3VudBRfY2hlY2tNYXhQcmljZUltcGFjdAkBFnN3YXBPdXRwdXRXaXRoUmVzZXJ2ZXMHBQZfaXNBZGQFEF9iYXNlQXNzZXRBbW91bnQFFF9jaGVja01heFByaWNlSW1wYWN0CQEGcXRBc3RSAAkBBnF0QXN0VwAJAQZic0FzdFIACQEGYnNBc3RXAAETZ2V0T3JhY2xlUHJpY2VWYWx1ZQMGb3JhY2xlCHByaWNlS2V5CGJsb2NrS2V5BAlsYXN0VmFsdWUJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQZvcmFjbGUFCHByaWNlS2V5CQCsAgIJAKwCAgkArAICAiJDYW4gbm90IGdldCBvcmFjbGUgcHJpY2UuIE9yYWNsZTogCQClCAEFBm9yYWNsZQIGIGtleTogBQhwcmljZUtleQMJAQIhPQIFCGJsb2NrS2V5AgAEDGN1cnJlbnRCbG9jawgFCWxhc3RCbG9jawZoZWlnaHQED2xhc3RPcmFjbGVCbG9jawkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFBm9yYWNsZQUIYmxvY2tLZXkJAKwCAgkArAICCQCsAgICIkNhbiBub3QgZ2V0IG9yYWNsZSBibG9jay4gT3JhY2xlOiAJAKUIAQUGb3JhY2xlAgYga2V5OiAFCGJsb2NrS2V5AwkAZgIJAGUCBQxjdXJyZW50QmxvY2sFD2xhc3RPcmFjbGVCbG9jawkBDm1heE9yYWNsZURlbGF5AAkAAgEJAKwCAgkArAICCQCsAgICJk9yYWNsZSBzdGFsZSBkYXRhLiBMYXN0IG9yYWNsZSBibG9jazogCQCkAwEFD2xhc3RPcmFjbGVCbG9jawIQIGN1cnJlbnQgYmxvY2s6IAkApAMBBQxjdXJyZW50QmxvY2sFCWxhc3RWYWx1ZQUJbGFzdFZhbHVlAQ5nZXRPcmFjbGVQcmljZQAECmJhc2VPcmFjbGUJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkBDWdldE9yYWNsZURhdGEBBQxrX2Jhc2VPcmFjbGUCGU5vIGJhc2UgYXNzZXQgb3JhY2xlIGRhdGEED2Jhc2VPcmFjbGVQcmljZQkBE2dldE9yYWNsZVByaWNlVmFsdWUDCAUKYmFzZU9yYWNsZQJfMQgFCmJhc2VPcmFjbGUCXzIIBQpiYXNlT3JhY2xlAl8zBAtxdW90ZU9yYWNsZQkBDWdldE9yYWNsZURhdGEBBQ1rX3F1b3RlT3JhY2xlBBBxdW90ZU9yYWNsZVByaWNlAwkBCWlzRGVmaW5lZAEFC3F1b3RlT3JhY2xlBAxxdW90ZU9yYWNsZVYJAQV2YWx1ZQEFC3F1b3RlT3JhY2xlCQETZ2V0T3JhY2xlUHJpY2VWYWx1ZQMIBQxxdW90ZU9yYWNsZVYCXzEIBQxxdW90ZU9yYWNsZVYCXzIIBQxxdW90ZU9yYWNsZVYCXzMFDERFQ0lNQUxfVU5JVAkBBGRpdmQCBQ9iYXNlT3JhY2xlUHJpY2UFEHF1b3RlT3JhY2xlUHJpY2UBDmlzTWFya2V0Q2xvc2VkAAQKYmFzZU9yYWNsZQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQENZ2V0T3JhY2xlRGF0YQEFDGtfYmFzZU9yYWNsZQIZTm8gYmFzZSBhc3NldCBvcmFjbGUgZGF0YQQGb3JhY2xlCAUKYmFzZU9yYWNsZQJfMQQHb3BlbktleQgFCmJhc2VPcmFjbGUCXzQDCQECIT0CBQdvcGVuS2V5AgAEBmlzT3BlbgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCbCAIFBm9yYWNsZQUHb3BlbktleQkArAICCQCsAgIJAKwCAgIrQ2FuIG5vdCBnZXQgb3JhY2xlIGlzIG9wZW4vY2xvc2VkLiBPcmFjbGU6IAkApQgBBQZvcmFjbGUCBiBrZXk6IAUHb3BlbktleQkBASEBBQZpc09wZW4HAQxhYnNQcmljZURpZmYFDF9vcmFjbGVQcmljZRJfcXVvdGVBc3NldFJlc2VydmURX2Jhc2VBc3NldFJlc2VydmUHX3F0QXN0VwdfYnNBc3RXBApwcmljZUFmdGVyCQEEZGl2ZAIJAQRtdWxkAgUSX3F1b3RlQXNzZXRSZXNlcnZlBQdfcXRBc3RXCQEEbXVsZAIFEV9iYXNlQXNzZXRSZXNlcnZlBQdfYnNBc3RXBAxhdmVyYWdlUHJpY2UJAQRkaXZkAgkAZAIFDF9vcmFjbGVQcmljZQUKcHJpY2VBZnRlcgkAaAIAAgUMREVDSU1BTF9VTklUBAxhYnNQcmljZURpZmYJAQRkaXZkAgkBA2FicwEJAGUCBQxfb3JhY2xlUHJpY2UFCnByaWNlQWZ0ZXIFDGF2ZXJhZ2VQcmljZQUMYWJzUHJpY2VEaWZmARlyZXF1aXJlTm90T3ZlclNwcmVhZExpbWl0AhJfcXVvdGVBc3NldFJlc2VydmURX2Jhc2VBc3NldFJlc2VydmUEC29yYWNsZVByaWNlCQEOZ2V0T3JhY2xlUHJpY2UABAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwAEEmFic1ByaWNlRGlmZkJlZm9yZQkBDGFic1ByaWNlRGlmZgUFC29yYWNsZVByaWNlCQEGcXRBc3RSAAkBBmJzQXN0UgAFB19xdEFzdFcFB19ic0FzdFcEEWFic1ByaWNlRGlmZkFmdGVyCQEMYWJzUHJpY2VEaWZmBQULb3JhY2xlUHJpY2UFEl9xdW90ZUFzc2V0UmVzZXJ2ZQURX2Jhc2VBc3NldFJlc2VydmUFB19xdEFzdFcFB19ic0FzdFcDAwkAZgIFEWFic1ByaWNlRGlmZkFmdGVyCQEObWF4UHJpY2VTcHJlYWQACQBmAgURYWJzUHJpY2VEaWZmQWZ0ZXIFEmFic1ByaWNlRGlmZkJlZm9yZQcJAAIBCQCsAgIJAKwCAgkArAICAg1QcmljZSBzcHJlYWQgCQCkAwEFEWFic1ByaWNlRGlmZkFmdGVyAhQgPiBtYXggcHJpY2Ugc3ByZWFkIAkApAMBCQEObWF4UHJpY2VTcHJlYWQABgEdcmVxdWlyZU5vdE92ZXJNYXhPcGVuTm90aW9uYWwCEV9sb25nT3Blbk5vdGlvbmFsEl9zaG9ydE9wZW5Ob3Rpb25hbAQQX21heE9wZW5Ob3Rpb25hbAkBD21heE9wZW5Ob3Rpb25hbAADCQBmAgURX2xvbmdPcGVuTm90aW9uYWwFEF9tYXhPcGVuTm90aW9uYWwJAAIBCQCsAgIJAKwCAgkArAICAhNMb25nIG9wZW4gbm90aW9uYWwgCQCkAwEFEV9sb25nT3Blbk5vdGlvbmFsAhUgPiBtYXggb3BlbiBub3Rpb25hbCAJAKQDAQUQX21heE9wZW5Ob3Rpb25hbAMJAGYCBRJfc2hvcnRPcGVuTm90aW9uYWwFEF9tYXhPcGVuTm90aW9uYWwJAAIBCQCsAgIJAKwCAgkArAICAhRTaG9ydCBvcGVuIG5vdGlvbmFsIAkApAMBBRJfc2hvcnRPcGVuTm90aW9uYWwCFSA+IG1heCBvcGVuIG5vdGlvbmFsIAkApAMBBRBfbWF4T3Blbk5vdGlvbmFsBgEMZ2V0U3BvdFByaWNlAAQSX3F1b3RlQXNzZXRSZXNlcnZlCQEGcXRBc3RSAAQRX2Jhc2VBc3NldFJlc2VydmUJAQZic0FzdFIABAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwAJAQRkaXZkAgkBBG11bGQCBRJfcXVvdGVBc3NldFJlc2VydmUFB19xdEFzdFcJAQRtdWxkAgURX2Jhc2VBc3NldFJlc2VydmUFB19ic0FzdFcBFmlzT3ZlckZsdWN0dWF0aW9uTGltaXQABAtvcmFjbGVQcmljZQkBDmdldE9yYWNsZVByaWNlAAQMY3VycmVudFByaWNlCQEMZ2V0U3BvdFByaWNlAAkAZgIJAQRkaXZkAgkBA2FicwEJAGUCBQtvcmFjbGVQcmljZQUMY3VycmVudFByaWNlBQtvcmFjbGVQcmljZQkBC3NwcmVhZExpbWl0AAEfZ2V0UG9zaXRpb25BZGp1c3RlZE9wZW5Ob3Rpb25hbAYNX3Bvc2l0aW9uU2l6ZQdfb3B0aW9uEl9xdW90ZUFzc2V0UmVzZXJ2ZRFfcXVvdGVBc3NldFdlaWdodBFfYmFzZUFzc2V0UmVzZXJ2ZRBfYmFzZUFzc2V0V2VpZ2h0BA9wb3NpdGlvblNpemVBYnMJAQNhYnMBBQ1fcG9zaXRpb25TaXplBAdpc1Nob3J0CQBmAgAABQ1fcG9zaXRpb25TaXplBBBwb3NpdGlvbk5vdGlvbmFsAwkAAAIFB19vcHRpb24FD1BOTF9PUFRJT05fU1BPVAQTb3V0UG9zaXRpb25Ob3Rpb25hbAgJARZzd2FwT3V0cHV0V2l0aFJlc2VydmVzBwkBASEBBQdpc1Nob3J0BQ9wb3NpdGlvblNpemVBYnMHBRJfcXVvdGVBc3NldFJlc2VydmUFEV9xdW90ZUFzc2V0V2VpZ2h0BRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldFdlaWdodAJfMQUTb3V0UG9zaXRpb25Ob3Rpb25hbAkBBG11bGQCBQ9wb3NpdGlvblNpemVBYnMJAQ5nZXRPcmFjbGVQcmljZQAFEHBvc2l0aW9uTm90aW9uYWwBK2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sQnlWYWx1ZXMHDV9wb3NpdGlvblNpemUVX3Bvc2l0aW9uT3Blbk5vdGlvbmFsEl9xdW90ZUFzc2V0UmVzZXJ2ZRFfcXVvdGVBc3NldFdlaWdodBFfYmFzZUFzc2V0UmVzZXJ2ZRBfYmFzZUFzc2V0V2VpZ2h0B19vcHRpb24DCQAAAgUNX3Bvc2l0aW9uU2l6ZQAACQACAQIVSW52YWxpZCBwb3NpdGlvbiBzaXplBAdpc1Nob3J0CQBmAgAABQ1fcG9zaXRpb25TaXplBBBwb3NpdGlvbk5vdGlvbmFsCQEfZ2V0UG9zaXRpb25BZGp1c3RlZE9wZW5Ob3Rpb25hbAYFDV9wb3NpdGlvblNpemUFB19vcHRpb24FEl9xdW90ZUFzc2V0UmVzZXJ2ZQURX3F1b3RlQXNzZXRXZWlnaHQFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0V2VpZ2h0BA11bnJlYWxpemVkUG5sAwUHaXNTaG9ydAkAZQIFFV9wb3NpdGlvbk9wZW5Ob3Rpb25hbAUQcG9zaXRpb25Ob3Rpb25hbAkAZQIFEHBvc2l0aW9uTm90aW9uYWwFFV9wb3NpdGlvbk9wZW5Ob3Rpb25hbAkAlAoCBRBwb3NpdGlvbk5vdGlvbmFsBQ11bnJlYWxpemVkUG5sASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIHX3RyYWRlcgdfb3B0aW9uBA0kdDAyNzYzMzI3NzYxCQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBAxwb3NpdGlvblNpemUIBQ0kdDAyNzYzMzI3NzYxAl8xBA5wb3NpdGlvbk1hcmdpbggFDSR0MDI3NjMzMjc3NjECXzIEFHBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwMjc2MzMyNzc2MQJfMwQRcG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDAyNzYzMzI3NzYxAl80CQErZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmxCeVZhbHVlcwcFDHBvc2l0aW9uU2l6ZQUUcG9zaXRpb25PcGVuTm90aW9uYWwJAQZxdEFzdFIACQEGcXRBc3RXAAkBBmJzQXN0UgAJAQZic0FzdFcABQdfb3B0aW9uAQ9jYWxjTWFyZ2luUmF0aW8DDV9yZW1haW5NYXJnaW4IX2JhZERlYnQRX3Bvc2l0aW9uTm90aW9uYWwJAQRkaXZkAgkAZQIFDV9yZW1haW5NYXJnaW4FCF9iYWREZWJ0BRFfcG9zaXRpb25Ob3Rpb25hbAEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgIHX3RyYWRlcgdfb3B0aW9uBA0kdDAyODI3NjI4NDE3CQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBAxwb3NpdGlvblNpemUIBQ0kdDAyODI3NjI4NDE3Al8xBA5wb3NpdGlvbk1hcmdpbggFDSR0MDI4Mjc2Mjg0MTcCXzIEA3BvbggFDSR0MDI4Mjc2Mjg0MTcCXzMEFnBvc2l0aW9uTGFzdFVwZGF0ZWRDUEYIBQ0kdDAyODI3NjI4NDE3Al80BBFwb3NpdGlvblRpbWVzdGFtcAgFDSR0MDI4Mjc2Mjg0MTcCXzUEDSR0MDI4NDIzMjg1MTYJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIFB190cmFkZXIFB19vcHRpb24EEHBvc2l0aW9uTm90aW9uYWwIBQ0kdDAyODQyMzI4NTE2Al8xBA11bnJlYWxpemVkUG5sCAUNJHQwMjg0MjMyODUxNgJfMgQNJHQwMjg1MjEyODczMwkBMGNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnRBbmRSb2xsb3ZlckZlZQUFDHBvc2l0aW9uU2l6ZQUOcG9zaXRpb25NYXJnaW4FFnBvc2l0aW9uTGFzdFVwZGF0ZWRDUEYFEXBvc2l0aW9uVGltZXN0YW1wBQ11bnJlYWxpemVkUG5sBAxyZW1haW5NYXJnaW4IBQ0kdDAyODUyMTI4NzMzAl8xBAdiYWREZWJ0CAUNJHQwMjg1MjEyODczMwJfMgkBD2NhbGNNYXJnaW5SYXRpbwMFDHJlbWFpbk1hcmdpbgUHYmFkRGVidAUQcG9zaXRpb25Ob3Rpb25hbAEOZ2V0TWFyZ2luUmF0aW8BB190cmFkZXIJARZnZXRNYXJnaW5SYXRpb0J5T3B0aW9uAgUHX3RyYWRlcgUPUE5MX09QVElPTl9TUE9UARtnZXRQYXJ0aWFsTGlxdWlkYXRpb25BbW91bnQCB190cmFkZXINX3Bvc2l0aW9uU2l6ZQQMbWF4aW11bVJhdGlvCQEEdm1heAIJARdwYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwAJAGUCBQxERUNJTUFMX1VOSVQJAQRkaXZkAgkBDmdldE1hcmdpblJhdGlvAQUHX3RyYWRlcgkBFm1haW50ZW5hbmNlTWFyZ2luUmF0aW8ABBhtYXhFeGNoYW5nZWRQb3NpdGlvblNpemUJAQRtdWxkAgkBA2FicwEFDV9wb3NpdGlvblNpemUFDG1heGltdW1SYXRpbwQKc3dhcFJlc3VsdAkBCnN3YXBPdXRwdXQDCQBmAgUNX3Bvc2l0aW9uU2l6ZQAABRhtYXhFeGNoYW5nZWRQb3NpdGlvblNpemUHBBxtYXhFeGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CAUKc3dhcFJlc3VsdAJfMQQLcHJpY2VJbXBhY3QIBQpzd2FwUmVzdWx0Al83AwkAZgIJAQ5tYXhQcmljZUltcGFjdAAFC3ByaWNlSW1wYWN0BRhtYXhFeGNoYW5nZWRQb3NpdGlvblNpemUJAQRtdWxkAgkBA2FicwEFDV9wb3NpdGlvblNpemUJARdwYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwABFWludGVybmFsQ2xvc2VQb3NpdGlvbgcHX3RyYWRlcgVfc2l6ZQRfZmVlFF9taW5RdW90ZUFzc2V0QW1vdW50DF9hZGRUb01hcmdpbhRfY2hlY2tNYXhQcmljZUltcGFjdApfbGlxdWlkYXRlBA0kdDAyOTgwMDI5OTU2CQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBA9vbGRQb3NpdGlvblNpemUIBQ0kdDAyOTgwMDI5OTU2Al8xBBFvbGRQb3NpdGlvbk1hcmdpbggFDSR0MDI5ODAwMjk5NTYCXzIEF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwMjk4MDAyOTk1NgJfMwQUb2xkUG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDAyOTgwMDI5OTU2Al80BBRvbGRQb3NpdGlvblRpbWVzdGFtcAgFDSR0MDI5ODAwMjk5NTYCXzUEDmlzTG9uZ1Bvc2l0aW9uCQBmAgUPb2xkUG9zaXRpb25TaXplAAAEEmFic09sZFBvc2l0aW9uU2l6ZQkBA2FicwEFD29sZFBvc2l0aW9uU2l6ZQMDCQBnAgUSYWJzT2xkUG9zaXRpb25TaXplBQVfc2l6ZQkAZgIFBV9zaXplAAAHBA5pc1BhcnRpYWxDbG9zZQkAZgIFEmFic09sZFBvc2l0aW9uU2l6ZQUFX3NpemUEDSR0MDMwMjQ4MzA2OTkJAQpzd2FwT3V0cHV0AwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAABQVfc2l6ZQUUX2NoZWNrTWF4UHJpY2VJbXBhY3QEGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQIBQ0kdDAzMDI0ODMwNjk5Al8xBBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwMzAyNDgzMDY5OQJfMgQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwMzAyNDgzMDY5OQJfMwQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDMwMjQ4MzA2OTkCXzQEFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQMJAGYCBQ9vbGRQb3NpdGlvblNpemUAAAkBAS0BBQVfc2l6ZQUFX3NpemUEDSR0MDMwOTE0MzExMjEJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAQTb2xkUG9zaXRpb25Ob3Rpb25hbAgFDSR0MDMwOTE0MzExMjECXzEEDXVucmVhbGl6ZWRQbmwIBQ0kdDAzMDkxNDMxMTIxAl8yBA1yZWFsaXplZFJhdGlvCQEEZGl2ZAIJAQNhYnMBBRVleGNoYW5nZWRQb3NpdGlvblNpemUFEmFic09sZFBvc2l0aW9uU2l6ZQQLcmVhbGl6ZWRQbmwJAQRtdWxkAgUNdW5yZWFsaXplZFBubAUNcmVhbGl6ZWRSYXRpbwQNJHQwMzE0NjIzMTcwOAkBMGNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnRBbmRSb2xsb3ZlckZlZQUFD29sZFBvc2l0aW9uU2l6ZQURb2xkUG9zaXRpb25NYXJnaW4FFG9sZFBvc2l0aW9uTHN0VXBkQ1BGBRRvbGRQb3NpdGlvblRpbWVzdGFtcAUNdW5yZWFsaXplZFBubAQScmVtYWluTWFyZ2luQmVmb3JlCAUNJHQwMzE0NjIzMTcwOAJfMQQCeDEIBQ0kdDAzMTQ2MjMxNzA4Al8yBAJ4MggFDSR0MDMxNDYyMzE3MDgCXzMEC3JvbGxvdmVyRmVlCAUNJHQwMzE0NjIzMTcwOAJfNAQPcG9zaXRpb25CYWREZWJ0CAkBMGNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnRBbmRSb2xsb3ZlckZlZQUFD29sZFBvc2l0aW9uU2l6ZQURb2xkUG9zaXRpb25NYXJnaW4FFG9sZFBvc2l0aW9uTHN0VXBkQ1BGBRRvbGRQb3NpdGlvblRpbWVzdGFtcAULcmVhbGl6ZWRQbmwCXzIEEHJlYWxpemVkQ2xvc2VGZWUJAQRtdWxkAgkBBG11bGQCBRNvbGRQb3NpdGlvbk5vdGlvbmFsBQ1yZWFsaXplZFJhdGlvBQRfZmVlBBJ1bnJlYWxpemVkUG5sQWZ0ZXIJAGUCBQ11bnJlYWxpemVkUG5sBQtyZWFsaXplZFBubAQScmVtYWluT3Blbk5vdGlvbmFsAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAACQBlAgkAZQIFE29sZFBvc2l0aW9uTm90aW9uYWwFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQFEnVucmVhbGl6ZWRQbmxBZnRlcgkAZQIJAGQCBRJ1bnJlYWxpemVkUG5sQWZ0ZXIFE29sZFBvc2l0aW9uTm90aW9uYWwFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQED25ld1Bvc2l0aW9uU2l6ZQkAZAIFD29sZFBvc2l0aW9uU2l6ZQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplBA0kdDAzMzExNDMzNTAwAwkAAAIFD25ld1Bvc2l0aW9uU2l6ZQAACQCUCgIAAAAACQCUCgIJAQNhYnMBBRJyZW1haW5PcGVuTm90aW9uYWwJAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUPbmV3UG9zaXRpb25TaXplBBduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDMzMTE0MzM1MDACXzEEFG5ld1Bvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwMzMxMTQzMzUwMAJfMgQRb3Blbk5vdGlvbmFsRGVsdGEJAGUCBRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwEC21hcmdpblJhdGlvCQEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAQebmV3UG9zaXRpb25NYXJnaW5XaXRoU2FtZVJhdGlvAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAACQBlAgkBBG11bGQCCQBkAgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFEnVucmVhbGl6ZWRQbmxBZnRlcgULbWFyZ2luUmF0aW8FEnVucmVhbGl6ZWRQbmxBZnRlcgkAZQIJAQRtdWxkAgkAZQIFF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBRJ1bnJlYWxpemVkUG5sQWZ0ZXIFC21hcmdpblJhdGlvBRJ1bnJlYWxpemVkUG5sQWZ0ZXIEEW1hcmdpblRvVHJhZGVyUmF3CQBlAgkAZQIFEnJlbWFpbk1hcmdpbkJlZm9yZQkAZAIFHm5ld1Bvc2l0aW9uTWFyZ2luV2l0aFNhbWVSYXRpbwUSdW5yZWFsaXplZFBubEFmdGVyBRByZWFsaXplZENsb3NlRmVlBA5tYXJnaW5Ub1RyYWRlcgMJAGYCAAAFEW1hcmdpblRvVHJhZGVyUmF3AwUKX2xpcXVpZGF0ZQAACQACAQI3SW52YWxpZCBpbnRlcm5hbENsb3NlUG9zaXRpb24gcGFyYW1zOiB1bmFibGUgdG8gcGF5IGZlZQURbWFyZ2luVG9UcmFkZXJSYXcEEW5ld1Bvc2l0aW9uTWFyZ2luAwUMX2FkZFRvTWFyZ2luCQBkAgUebmV3UG9zaXRpb25NYXJnaW5XaXRoU2FtZVJhdGlvBQ5tYXJnaW5Ub1RyYWRlcgUebmV3UG9zaXRpb25NYXJnaW5XaXRoU2FtZVJhdGlvAwMJAQIhPQIFFF9taW5RdW90ZUFzc2V0QW1vdW50AAAJAGYCBRRfbWluUXVvdGVBc3NldEFtb3VudAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAcJAAIBCQCsAgIJAKwCAgkArAICAg1MaW1pdCBlcnJvcjogCQCkAwEFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQCAyA8IAkApAMBBRRfbWluUXVvdGVBc3NldEFtb3VudAkAowoRBQ9uZXdQb3NpdGlvblNpemUFEW5ld1Bvc2l0aW9uTWFyZ2luBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUUbmV3UG9zaXRpb25Mc3RVcGRDUEYFD3Bvc2l0aW9uQmFkRGVidAULcmVhbGl6ZWRQbmwDAwUMX2FkZFRvTWFyZ2luBQ5pc1BhcnRpYWxDbG9zZQcAAAUObWFyZ2luVG9UcmFkZXIFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgkAZQIJARRvcGVuSW50ZXJlc3ROb3Rpb25hbAAFEW9wZW5Ob3Rpb25hbERlbHRhCQBlAgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQADBQ5pc0xvbmdQb3NpdGlvbgkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQAACQBlAgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUAAwkBASEBBQ5pc0xvbmdQb3NpdGlvbgkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQAACQBlAgkBEG9wZW5JbnRlcmVzdExvbmcAAwUOaXNMb25nUG9zaXRpb24FEW9wZW5Ob3Rpb25hbERlbHRhAAAJAGUCCQERb3BlbkludGVyZXN0U2hvcnQAAwkBASEBBQ5pc0xvbmdQb3NpdGlvbgURb3Blbk5vdGlvbmFsRGVsdGEAAAkAZAIFEHJlYWxpemVkQ2xvc2VGZWUFC3JvbGxvdmVyRmVlBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CQACAQkArAICCQCsAgIJAKwCAgI9SW52YWxpZCBpbnRlcm5hbENsb3NlUG9zaXRpb24gcGFyYW1zOiBpbnZhbGlkIHBvc2l0aW9uIHNpemU6IAkApAMBBQVfc2l6ZQIGIG1heDogCQCkAwEFEmFic09sZFBvc2l0aW9uU2l6ZQETZ2V0VGVybWluYWxBbW1TdGF0ZQAEDV9wb3NpdGlvblNpemUJARF0b3RhbFBvc2l0aW9uU2l6ZQADCQAAAgUNX3Bvc2l0aW9uU2l6ZQAACQCUCgIJAQZxdEFzdFIACQEGYnNBc3RSAAQJZGlyZWN0aW9uCQBmAgUNX3Bvc2l0aW9uU2l6ZQAABA0kdDAzNjczNTM2OTE0CQEKc3dhcE91dHB1dAMFCWRpcmVjdGlvbgkBA2FicwEFDV9wb3NpdGlvblNpemUHBBVjdXJyZW50TmV0TWFya2V0VmFsdWUIBQ0kdDAzNjczNTM2OTE0Al8xBBl0ZXJtaW5hbFF1b3RlQXNzZXRSZXNlcnZlCAUNJHQwMzY3MzUzNjkxNAJfMgQYdGVybWluYWxCYXNlQXNzZXRSZXNlcnZlCAUNJHQwMzY3MzUzNjkxNAJfMwkAlAoCBRl0ZXJtaW5hbFF1b3RlQXNzZXRSZXNlcnZlBRh0ZXJtaW5hbEJhc2VBc3NldFJlc2VydmUBE2dldFF1b3RlQXNzZXRXZWlnaHQEEGJhc2VBc3NldFJlc2VydmURdG90YWxQb3NpdGlvblNpemURcXVvdGVBc3NldFJlc2VydmULdGFyZ2V0UHJpY2UEAWIJALYCAQUQYmFzZUFzc2V0UmVzZXJ2ZQQCc3oJALYCAQURdG90YWxQb3NpdGlvblNpemUEAXEJALYCAQURcXVvdGVBc3NldFJlc2VydmUEAXAJALYCAQULdGFyZ2V0UHJpY2UEAWsJAQVibXVsZAIFAXEFAWIEBG5ld0IJALcCAgUBYgUCc3oEBG5ld1EJAQViZGl2ZAIFAWsFBG5ld0IEAXoJAQViZGl2ZAIFBG5ld1EFBG5ld0IEBnJlc3VsdAkBBWJkaXZkAgUBcAUBegkAoAMBBQZyZXN1bHQBFGdldFN5bmNUZXJtaW5hbFByaWNlAw5fdGVybWluYWxQcmljZQdfcXRBc3RSB19ic0FzdFIEDV9wb3NpdGlvblNpemUJARF0b3RhbFBvc2l0aW9uU2l6ZQADCQAAAgUNX3Bvc2l0aW9uU2l6ZQAABAluZXdRdEFzdFcJAQRkaXZkAgkBBG11bGQCBQ5fdGVybWluYWxQcmljZQUHX2JzQXN0UgUHX3F0QXN0UgkAlQoDBQluZXdRdEFzdFcFDERFQ0lNQUxfVU5JVAAABAlkaXJlY3Rpb24JAGYCBQ1fcG9zaXRpb25TaXplAAAEFWN1cnJlbnROZXRNYXJrZXRWYWx1ZQgJAQpzd2FwT3V0cHV0AwUJZGlyZWN0aW9uCQEDYWJzAQUNX3Bvc2l0aW9uU2l6ZQcCXzEECW5ld1F0QXN0VwkBE2dldFF1b3RlQXNzZXRXZWlnaHQEBQdfYnNBc3RSBQ1fcG9zaXRpb25TaXplBQdfcXRBc3RSBQ5fdGVybWluYWxQcmljZQQJbmV3QnNBc3RXBQxERUNJTUFMX1VOSVQEDW1hcmdpblRvVmF1bHQICQErZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmxCeVZhbHVlcwcFDV9wb3NpdGlvblNpemUFFWN1cnJlbnROZXRNYXJrZXRWYWx1ZQUHX3F0QXN0UgUJbmV3UXRBc3RXBQdfYnNBc3RSBQluZXdCc0FzdFcFD1BOTF9PUFRJT05fU1BPVAJfMgkAlQoDBQluZXdRdEFzdFcFCW5ld0JzQXN0VwUNbWFyZ2luVG9WYXVsdAEKZ2V0RnVuZGluZwAED3VuZGVybHlpbmdQcmljZQkBDmdldE9yYWNsZVByaWNlAAQJc3BvdFByaWNlCQEMZ2V0U3BvdFByaWNlAAQHcHJlbWl1bQkAZQIFCXNwb3RQcmljZQUPdW5kZXJseWluZ1ByaWNlAwMDCQAAAgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUAAAAGCQAAAgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQAAAAYJAQ5pc01hcmtldENsb3NlZAAJAJUKAwAAAAAAAAMJAGYCAAAFB3ByZW1pdW0EFHNob3J0UHJlbWl1bUZyYWN0aW9uCQEEZGl2ZAIJAQRtdWxkAgUHcHJlbWl1bQkBFGZ1bmRpbmdQZXJpb2REZWNpbWFsAAUHT05FX0RBWQMJAAACCQELZnVuZGluZ01vZGUABRJGVU5ESU5HX0FTWU1NRVRSSUMEE2xvbmdQcmVtaXVtRnJhY3Rpb24JAQRkaXZkAgkBBG11bGQCBRRzaG9ydFByZW1pdW1GcmFjdGlvbgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUACQEVdG90YWxMb25nUG9zaXRpb25TaXplAAkAlQoDBRRzaG9ydFByZW1pdW1GcmFjdGlvbgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgAABBlzaG9ydFRvdGFsUHJlbWl1bUZyYWN0aW9uCQEDYWJzAQkBBG11bGQCBRRzaG9ydFByZW1pdW1GcmFjdGlvbgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUABBhsb25nVG90YWxQcmVtaXVtRnJhY3Rpb24JAQNhYnMBCQEEbXVsZAIFFHNob3J0UHJlbWl1bUZyYWN0aW9uCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAQOcHJlbWl1bVRvVmF1bHQJAGUCBRlzaG9ydFRvdGFsUHJlbWl1bUZyYWN0aW9uBRhsb25nVG90YWxQcmVtaXVtRnJhY3Rpb24JAJUKAwUUc2hvcnRQcmVtaXVtRnJhY3Rpb24FFHNob3J0UHJlbWl1bUZyYWN0aW9uBQ5wcmVtaXVtVG9WYXVsdAQTbG9uZ1ByZW1pdW1GcmFjdGlvbgkBBGRpdmQCCQEEbXVsZAIFB3ByZW1pdW0JARRmdW5kaW5nUGVyaW9kRGVjaW1hbAAFB09ORV9EQVkDCQAAAgkBC2Z1bmRpbmdNb2RlAAUSRlVORElOR19BU1lNTUVUUklDBBRzaG9ydFByZW1pdW1GcmFjdGlvbgkBBGRpdmQCCQEEbXVsZAIFE2xvbmdQcmVtaXVtRnJhY3Rpb24JARV0b3RhbExvbmdQb3NpdGlvblNpemUACQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAJAJUKAwUUc2hvcnRQcmVtaXVtRnJhY3Rpb24FE2xvbmdQcmVtaXVtRnJhY3Rpb24AAAQYbG9uZ1RvdGFsUHJlbWl1bUZyYWN0aW9uCQEDYWJzAQkBBG11bGQCBRNsb25nUHJlbWl1bUZyYWN0aW9uCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAQZc2hvcnRUb3RhbFByZW1pdW1GcmFjdGlvbgkBA2FicwEJAQRtdWxkAgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUABA5wcmVtaXVtVG9WYXVsdAkAZQIFGGxvbmdUb3RhbFByZW1pdW1GcmFjdGlvbgUZc2hvcnRUb3RhbFByZW1pdW1GcmFjdGlvbgkAlQoDBRNsb25nUHJlbWl1bUZyYWN0aW9uBRNsb25nUHJlbWl1bUZyYWN0aW9uBQ5wcmVtaXVtVG9WYXVsdAEOZ2V0QWRqdXN0ZWRGZWUCC19hcnRpZmFjdElkEF9iYXNlRmVlRGlzY291bnQECmJhc2VGZWVSYXcJAQNmZWUABAdiYXNlRmVlCQEEbXVsZAIFCmJhc2VGZWVSYXcFEF9iYXNlRmVlRGlzY291bnQEDSR0MDQwNjMyNDExMjcDCQECIT0CBQtfYXJ0aWZhY3RJZAIABAxhcnRpZmFjdEtpbmQJAQRzdHJBAgkBEW5mdE1hbmFnZXJBZGRyZXNzAAkBDnRvQ29tcG9zaXRlS2V5AgUMa190b2tlbl90eXBlBQtfYXJ0aWZhY3RJZAMJAAACBQxhcnRpZmFjdEtpbmQFGEZFRV9SRURVQ1RJT05fVE9LRU5fVFlQRQQJcmVkdWN0aW9uCQEEaW50QQIJARFuZnRNYW5hZ2VyQWRkcmVzcwAJAQ50b0NvbXBvc2l0ZUtleQIFDWtfdG9rZW5fcGFyYW0FC19hcnRpZmFjdElkBAthZGp1c3RlZEZlZQkBBG11bGQCBQdiYXNlRmVlBQlyZWR1Y3Rpb24JAJQKAgULYWRqdXN0ZWRGZWUGCQACAQIZSW52YWxpZCBhdHRhY2hlZCBhcnRpZmFjdAkAlAoCBQdiYXNlRmVlBwQLYWRqdXN0ZWRGZWUIBQ0kdDA0MDYzMjQxMTI3Al8xBAxidXJuQXJ0aWZhY3QIBQ0kdDA0MDYzMjQxMTI3Al8yCQCUCgIFC2FkanVzdGVkRmVlBQxidXJuQXJ0aWZhY3QBGGdldEZvclRyYWRlcldpdGhBcnRpZmFjdAIHX3RyYWRlcgtfYXJ0aWZhY3RJZAQQZG9HZXRGZWVEaXNjb3VudAkA/AcECQEMbWluZXJBZGRyZXNzAAISY29tcHV0ZUZlZURpc2NvdW50CQDMCAIFB190cmFkZXIFA25pbAUDbmlsAwkAAAIFEGRvR2V0RmVlRGlzY291bnQFEGRvR2V0RmVlRGlzY291bnQEC2ZlZURpc2NvdW50BAckbWF0Y2gwBRBkb0dldEZlZURpc2NvdW50AwkAAQIFByRtYXRjaDACA0ludAQBeAUHJG1hdGNoMAUBeAkAAgECIUludmFsaWQgY29tcHV0ZUZlZURpc2NvdW50IHJlc3VsdAQNJHQwNDE0NzM0MTU0NwkBDmdldEFkanVzdGVkRmVlAgULX2FydGlmYWN0SWQFC2ZlZURpc2NvdW50BAthZGp1c3RlZEZlZQgFDSR0MDQxNDczNDE1NDcCXzEEDGJ1cm5BcnRpZmFjdAgFDSR0MDQxNDczNDE1NDcCXzIJAJQKAgULYWRqdXN0ZWRGZWUFDGJ1cm5BcnRpZmFjdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgENZ2V0QXJ0aWZhY3RJZAEBaQQKYXJ0aWZhY3RJZAMJAGYCCQCQAwEIBQFpCHBheW1lbnRzAAEJANgEAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCAkAkQMCCAUBaQhwYXltZW50cwABB2Fzc2V0SWQCEkludmFsaWQgYXJ0aWZhY3RJZAIABQphcnRpZmFjdElkAQ1kaXN0cmlidXRlRmVlAQpfZmVlQW1vdW50BAxmZWVUb1N0YWtlcnMJAQRtdWxkAgUKX2ZlZUFtb3VudAkBE2ZlZVRvU3Rha2Vyc1BlcmNlbnQABApmZWVUb1ZhdWx0CQBlAgUKX2ZlZUFtb3VudAUMZmVlVG9TdGFrZXJzCQCUCgIFDGZlZVRvU3Rha2VycwUKZmVlVG9WYXVsdAEOdXBkYXRlU2V0dGluZ3MOEF9pbml0TWFyZ2luUmF0aW8EX21tchRfbGlxdWlkYXRpb25GZWVSYXRpbw5fZnVuZGluZ1BlcmlvZARfZmVlDF9zcHJlYWRMaW1pdA9fbWF4UHJpY2VJbXBhY3QYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvD19tYXhQcmljZVNwcmVhZBBfbWF4T3Blbk5vdGlvbmFsFF9mZWVUb1N0YWtlcnNQZXJjZW50D19tYXhPcmFjbGVEZWxheQxfcm9sbG92ZXJGZWUMX2Z1bmRpbmdNb2RlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRFrX2luaXRNYXJnaW5SYXRpbwUQX2luaXRNYXJnaW5SYXRpbwkAzAgCCQEMSW50ZWdlckVudHJ5AgUYa19tYWludGVuYW5jZU1hcmdpblJhdGlvBQRfbW1yCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRVrX2xpcXVpZGF0aW9uRmVlUmF0aW8FFF9saXF1aWRhdGlvbkZlZVJhdGlvCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ9rX2Z1bmRpbmdQZXJpb2QFDl9mdW5kaW5nUGVyaW9kCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQVrX2ZlZQUEX2ZlZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUNa19zcHJlYWRMaW1pdAUMX3NwcmVhZExpbWl0CQDMCAIJAQxJbnRlZ2VyRW50cnkCBRBrX21heFByaWNlSW1wYWN0BQ9fbWF4UHJpY2VJbXBhY3QJAMwIAgkBDEludGVnZXJFbnRyeQIFGWtfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8FGF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwkAzAgCCQEMSW50ZWdlckVudHJ5AgUQa19tYXhQcmljZVNwcmVhZAUPX21heFByaWNlU3ByZWFkCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRFrX21heE9wZW5Ob3Rpb25hbAUQX21heE9wZW5Ob3Rpb25hbAkAzAgCCQEMSW50ZWdlckVudHJ5AgUVa19mZWVUb1N0YWtlcnNQZXJjZW50BRRfZmVlVG9TdGFrZXJzUGVyY2VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgUQa19tYXhPcmFjbGVEZWxheQUUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQJAMwIAgkBDEludGVnZXJFbnRyeQIFDWtfcm9sbG92ZXJGZWUFDF9yb2xsb3ZlckZlZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUNa19mdW5kaW5nTW9kZQUMX2Z1bmRpbmdNb2RlBQNuaWwBDXVwZGF0ZUZ1bmRpbmcFEV9uZXh0RnVuZGluZ0Jsb2NrJF9sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbiVfbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uEF9sb25nRnVuZGluZ1JhdGURX3Nob3J0RnVuZGluZ1JhdGUJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfbmV4dEZ1bmRpbmdCbG9jawURX25leHRGdW5kaW5nQmxvY2sJAMwIAgkBDEludGVnZXJFbnRyeQIFJWtfbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FJF9sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgUma19sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FJV9sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24JAMwIAgkBDEludGVnZXJFbnRyeQIFEWtfbG9uZ0Z1bmRpbmdSYXRlBRBfbG9uZ0Z1bmRpbmdSYXRlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJrX3Nob3J0RnVuZGluZ1JhdGUFEV9zaG9ydEZ1bmRpbmdSYXRlBQNuaWwBH2luY3JlbWVudFBvc2l0aW9uU2VxdWVuY2VOdW1iZXICDl9pc05ld1Bvc2l0aW9uCF9hZGRyZXNzAwUOX2lzTmV3UG9zaXRpb24ED2N1cnJlbnRTZXF1ZW5jZQkBDGxhc3RTZXF1ZW5jZQAJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFEmtfcG9zaXRpb25TZXF1ZW5jZQUIX2FkZHJlc3MJAGQCBQ9jdXJyZW50U2VxdWVuY2UAAQkAzAgCCQEMSW50ZWdlckVudHJ5AgUKa19zZXF1ZW5jZQkAZAIFD2N1cnJlbnRTZXF1ZW5jZQABBQNuaWwFA25pbAERdXBkYXRlUG9zaXRpb25GZWUDDl9pc05ld1Bvc2l0aW9uCF9hZGRyZXNzBF9mZWUDBQ5faXNOZXdQb3NpdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUNa19wb3NpdGlvbkZlZQUIX2FkZHJlc3MFBF9mZWUFA25pbAUDbmlsAQ51cGRhdGVQb3NpdGlvbgYIX2FkZHJlc3MFX3NpemUHX21hcmdpbg1fb3Blbk5vdGlvbmFsIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uEF9sYXRlc3RUaW1lc3RhbXAJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFDmtfcG9zaXRpb25TaXplBQhfYWRkcmVzcwUFX3NpemUJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFEGtfcG9zaXRpb25NYXJnaW4FCF9hZGRyZXNzBQdfbWFyZ2luCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBQhfYWRkcmVzcwUNX29wZW5Ob3Rpb25hbAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUua19wb3NpdGlvbkxhc3RVcGRhdGVkQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUIX2FkZHJlc3MFIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBR5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRUaW1lc3RhbXAFCF9hZGRyZXNzBRBfbGF0ZXN0VGltZXN0YW1wBQNuaWwBEXVwZGF0ZUFtbVJlc2VydmVzAgdfcXRBc3RSB19ic0FzdFIJAMwIAgkBDEludGVnZXJFbnRyeQIFE2tfcXVvdGVBc3NldFJlc2VydmUFB19xdEFzdFIJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfYmFzZUFzc2V0UmVzZXJ2ZQUHX2JzQXN0UgUDbmlsARB1cGRhdGVBbW1XZWlnaHRzAgdfcXRBc3RXB19ic0FzdFcJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfcXVvdGVBc3NldFdlaWdodAUHX3F0QXN0VwkAzAgCCQEMSW50ZWdlckVudHJ5AgURa19iYXNlQXNzZXRXZWlnaHQFB19ic0FzdFcFA25pbAEJdXBkYXRlQW1tCAdfcXRBc3RSB19ic0FzdFIXX3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIVX29wZW5JbnRlcmVzdE5vdGlvbmFsFl90b3RhbExvbmdQb3NpdGlvblNpemUXX3RvdGFsU2hvcnRQb3NpdGlvblNpemUWX3RvdGFsTG9uZ09wZW5Ob3Rpb25hbBdfdG90YWxTaG9ydE9wZW5Ob3Rpb25hbAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcAAwkBAiE9AgkAZQIFFl90b3RhbExvbmdQb3NpdGlvblNpemUFF190b3RhbFNob3J0UG9zaXRpb25TaXplBRdfdG90YWxQb3NpdGlvblNpemVBZnRlcgkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAhhJbnZhbGlkIEFNTSBzdGF0ZSBkYXRhOiAJAKQDAQUWX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQIEICsgIAkApAMBBRdfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQIEICE9IAkApAMBBRdfdG90YWxQb3NpdGlvblNpemVBZnRlcgkAzggCCQERdXBkYXRlQW1tUmVzZXJ2ZXMCBQdfcXRBc3RSBQdfYnNBc3RSCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRNrX3RvdGFsUG9zaXRpb25TaXplBRdfdG90YWxQb3NpdGlvblNpemVBZnRlcgkAzAgCCQEMSW50ZWdlckVudHJ5AgUWa19vcGVuSW50ZXJlc3ROb3Rpb25hbAUVX29wZW5JbnRlcmVzdE5vdGlvbmFsCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRdrX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQUWX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUYa190b3RhbFNob3J0UG9zaXRpb25TaXplBRdfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUSa19vcGVuSW50ZXJlc3RMb25nBRZfdG90YWxMb25nT3Blbk5vdGlvbmFsCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRNrX29wZW5JbnRlcmVzdFNob3J0BRdfdG90YWxTaG9ydE9wZW5Ob3Rpb25hbAUDbmlsAQ5kZWxldGVQb3NpdGlvbgEIX2FkZHJlc3MJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBDnRvQ29tcG9zaXRlS2V5AgUOa19wb3NpdGlvblNpemUFCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFEGtfcG9zaXRpb25NYXJnaW4FCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFFmtfcG9zaXRpb25PcGVuTm90aW9uYWwFCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFLmtfcG9zaXRpb25MYXN0VXBkYXRlZEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFDWtfcG9zaXRpb25GZWUFCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFHmtfcG9zaXRpb25MYXN0VXBkYXRlZFRpbWVzdGFtcAUIX2FkZHJlc3MFA25pbAEId2l0aGRyYXcCCF9hZGRyZXNzB19hbW91bnQEB2JhbGFuY2UJAPAHAgUEdGhpcwkBCnF1b3RlQXNzZXQAAwkAZgIFB19hbW91bnQFB2JhbGFuY2UJAAIBCQCsAgIJAKwCAgkArAICAhNVbmFibGUgdG8gd2l0aGRyYXcgCQCkAwEFB19hbW91bnQCFyBmcm9tIGNvbnRyYWN0IGJhbGFuY2UgCQCkAwEFB2JhbGFuY2UJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUIX2FkZHJlc3MFB19hbW91bnQJAQpxdW90ZUFzc2V0AAUDbmlsAQ11cGRhdGVCYWxhbmNlAQFpAwkAZgIAAAUBaQkAAgECB0JhbGFuY2UJAMwIAgkBDEludGVnZXJFbnRyeQIFCWtfYmFsYW5jZQUBaQUDbmlsAQt0cmFuc2ZlckZlZQEBaQkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCQEOc3Rha2luZ0FkZHJlc3MABQFpCQEKcXVvdGVBc3NldAAFA25pbAEOZG9CdXJuQXJ0aWZhY3QCDV9idXJuQXJ0aWZhY3QBaQMFDV9idXJuQXJ0aWZhY3QJAMwIAgkBBEJ1cm4CCQETdmFsdWVPckVycm9yTWVzc2FnZQIICQCRAwIIBQFpCHBheW1lbnRzAAEHYXNzZXRJZAIQSW52YWxpZCBhcnRpZmFjdAABBQNuaWwFA25pbBcBaQEFcGF1c2UAAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECFEludmFsaWQgcGF1c2UgcGFyYW1zCQDMCAIJAQxCb29sZWFuRW50cnkCBQhrX3BhdXNlZAYFA25pbAFpAQZkZWxpc3QAAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECFUludmFsaWQgZGVsaXN0IHBhcmFtcwkAzAgCCQEMQm9vbGVhbkVudHJ5AgUKa19kZWxpc3RlZAYFA25pbAFpAQd1bnBhdXNlAAMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAhZJbnZhbGlkIHVucGF1c2UgcGFyYW1zCQDMCAIJAQxCb29sZWFuRW50cnkCBQhrX3BhdXNlZAcFA25pbAFpAQxzZXRDbG9zZU9ubHkAAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECG0ludmFsaWQgc2V0Q2xvc2VPbmx5IHBhcmFtcwkAzAgCCQEMQm9vbGVhbkVudHJ5AgULa19jbG9zZU9ubHkGBQNuaWwBaQEOdW5zZXRDbG9zZU9ubHkAAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECHUludmFsaWQgdW5zZXRDbG9zZU9ubHkgcGFyYW1zCQDMCAIJAQxCb29sZWFuRW50cnkCBQtrX2Nsb3NlT25seQcFA25pbAFpAQxhZGRMaXF1aWRpdHkBEV9xdW90ZUFzc2V0QW1vdW50AwMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAGCQBnAgAABRFfcXVvdGVBc3NldEFtb3VudAkAAgECG0ludmFsaWQgYWRkTGlxdWlkaXR5IHBhcmFtcwQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwAEBXByaWNlCQEEZGl2ZAIJAQRtdWxkAgUHX3F0QXN0UgUHX3F0QXN0VwkBBG11bGQCBQdfYnNBc3RSBQdfYnNBc3RXBAtxdEFzdFJBZnRlcgkAZAIFB19xdEFzdFIFEV9xdW90ZUFzc2V0QW1vdW50BBRiYXNlQXNzZXRBbW91bnRUb0FkZAkAZQIJAQRkaXZkAgkBBG11bGQCBQtxdEFzdFJBZnRlcgUHX3F0QXN0VwUFcHJpY2UFB19ic0FzdFIEC2JzQXN0UkFmdGVyCQBkAgUHX2JzQXN0UgUUYmFzZUFzc2V0QW1vdW50VG9BZGQEDSR0MDQ5NjE1NDk3NjYJARRnZXRTeW5jVGVybWluYWxQcmljZQMJAQ5nZXRPcmFjbGVQcmljZQAFC3F0QXN0UkFmdGVyBQtic0FzdFJBZnRlcgQTbmV3UXVvdGVBc3NldFdlaWdodAgFDSR0MDQ5NjE1NDk3NjYCXzEEEm5ld0Jhc2VBc3NldFdlaWdodAgFDSR0MDQ5NjE1NDk3NjYCXzIEDW1hcmdpblRvVmF1bHQIBQ0kdDA0OTYxNTQ5NzY2Al8zBA1kb0V4Y2hhbmdlUG5MAwkBAiE9AgUNbWFyZ2luVG9WYXVsdAAABA1kb0V4Y2hhbmdlUG5MCQD8BwQJAQx2YXVsdEFkZHJlc3MAAhVleGNoYW5nZUZyZWVBbmRMb2NrZWQJAMwIAgUNbWFyZ2luVG9WYXVsdAUDbmlsBQNuaWwDCQAAAgUNZG9FeGNoYW5nZVBuTAUNZG9FeGNoYW5nZVBuTAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUNZG9FeGNoYW5nZVBuTAUNZG9FeGNoYW5nZVBuTAkAzggCCQERdXBkYXRlQW1tUmVzZXJ2ZXMCBQtxdEFzdFJBZnRlcgULYnNBc3RSQWZ0ZXIJARB1cGRhdGVBbW1XZWlnaHRzAgUTbmV3UXVvdGVBc3NldFdlaWdodAUSbmV3QmFzZUFzc2V0V2VpZ2h0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBD3JlbW92ZUxpcXVpZGl0eQERX3F1b3RlQXNzZXRBbW91bnQDAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAYJAGcCBRFfcXVvdGVBc3NldEFtb3VudAAACQACAQIeSW52YWxpZCByZW1vdmVMaXF1aWRpdHkgcGFyYW1zBAdfcXRBc3RSCQEGcXRBc3RSAAQHX2JzQXN0UgkBBmJzQXN0UgAEB19xdEFzdFcJAQZxdEFzdFcABAdfYnNBc3RXCQEGYnNBc3RXAAQFcHJpY2UJAQRkaXZkAgkBBG11bGQCBQdfcXRBc3RSBQdfcXRBc3RXCQEEbXVsZAIFB19ic0FzdFIFB19ic0FzdFcEC3F0QXN0UkFmdGVyCQBlAgUHX3F0QXN0UgURX3F1b3RlQXNzZXRBbW91bnQEF2Jhc2VBc3NldEFtb3VudFRvUmVtb3ZlCQEDYWJzAQkAZQIJAQRkaXZkAgkBBG11bGQCBQtxdEFzdFJBZnRlcgUHX3F0QXN0VwUFcHJpY2UFB19ic0FzdFIEC2JzQXN0UkFmdGVyCQBlAgUHX2JzQXN0UgUXYmFzZUFzc2V0QW1vdW50VG9SZW1vdmUEDSR0MDUwODYyNTEwMTMJARRnZXRTeW5jVGVybWluYWxQcmljZQMJAQ5nZXRPcmFjbGVQcmljZQAFC3F0QXN0UkFmdGVyBQtic0FzdFJBZnRlcgQTbmV3UXVvdGVBc3NldFdlaWdodAgFDSR0MDUwODYyNTEwMTMCXzEEEm5ld0Jhc2VBc3NldFdlaWdodAgFDSR0MDUwODYyNTEwMTMCXzIEDW1hcmdpblRvVmF1bHQIBQ0kdDA1MDg2MjUxMDEzAl8zBA1kb0V4Y2hhbmdlUG5MAwkBAiE9AgUNbWFyZ2luVG9WYXVsdAAABA1kb0V4Y2hhbmdlUG5MCQD8BwQJAQx2YXVsdEFkZHJlc3MAAhVleGNoYW5nZUZyZWVBbmRMb2NrZWQJAMwIAgUNbWFyZ2luVG9WYXVsdAUDbmlsBQNuaWwDCQAAAgUNZG9FeGNoYW5nZVBuTAUNZG9FeGNoYW5nZVBuTAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUNZG9FeGNoYW5nZVBuTAUNZG9FeGNoYW5nZVBuTAkAzggCCQERdXBkYXRlQW1tUmVzZXJ2ZXMCBQtxdEFzdFJBZnRlcgULYnNBc3RSQWZ0ZXIJARB1cGRhdGVBbW1XZWlnaHRzAgUTbmV3UXVvdGVBc3NldFdlaWdodAUSbmV3QmFzZUFzc2V0V2VpZ2h0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDmNoYW5nZVNldHRpbmdzDhBfaW5pdE1hcmdpblJhdGlvBF9tbXIUX2xpcXVpZGF0aW9uRmVlUmF0aW8OX2Z1bmRpbmdQZXJpb2QEX2ZlZQxfc3ByZWFkTGltaXQPX21heFByaWNlSW1wYWN0GF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbw9fbWF4UHJpY2VTcHJlYWQQX21heE9wZW5Ob3Rpb25hbBRfZmVlVG9TdGFrZXJzUGVyY2VudA9fbWF4T3JhY2xlRGVsYXkMX3JvbGxvdmVyRmVlDF9mdW5kaW5nTW9kZQMDAwMDAwMDAwMDAwMDAwMDCQBnAgAABQ5fZnVuZGluZ1BlcmlvZAYJAGcCAAAFEF9pbml0TWFyZ2luUmF0aW8GCQBnAgAABQRfbW1yBgkAZwIAAAUUX2xpcXVpZGF0aW9uRmVlUmF0aW8GCQBnAgAABQRfZmVlBgkAZwIAAAUMX3NwcmVhZExpbWl0BgkAZwIAAAUPX21heFByaWNlSW1wYWN0BgkAZwIAAAUYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvBgkAZwIAAAUPX21heFByaWNlU3ByZWFkBgkAZwIAAAUQX21heE9wZW5Ob3Rpb25hbAYJAGcCAAAFFF9mZWVUb1N0YWtlcnNQZXJjZW50BgkAZgIFFF9mZWVUb1N0YWtlcnNQZXJjZW50BQxERUNJTUFMX1VOSVQGCQBnAgAABQ9fbWF4T3JhY2xlRGVsYXkGCQBnAgAABQxfcm9sbG92ZXJGZWUGAwkBAiE9AgUMX2Z1bmRpbmdNb2RlBRFGVU5ESU5HX1NZTU1FVFJJQwkBAiE9AgUMX2Z1bmRpbmdNb2RlBRJGVU5ESU5HX0FTWU1NRVRSSUMHBgkBASEBCQELaW5pdGlhbGl6ZWQABgkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECHUludmFsaWQgY2hhbmdlU2V0dGluZ3MgcGFyYW1zCQEOdXBkYXRlU2V0dGluZ3MOBRBfaW5pdE1hcmdpblJhdGlvBQRfbW1yBRRfbGlxdWlkYXRpb25GZWVSYXRpbwUOX2Z1bmRpbmdQZXJpb2QFBF9mZWUFDF9zcHJlYWRMaW1pdAUPX21heFByaWNlSW1wYWN0BRhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8FD19tYXhQcmljZVNwcmVhZAUQX21heE9wZW5Ob3Rpb25hbAUUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQFD19tYXhPcmFjbGVEZWxheQUMX3JvbGxvdmVyRmVlBQxfZnVuZGluZ01vZGUBaQEKaW5pdGlhbGl6ZRMHX3F0QXN0UgdfYnNBc3RSDl9mdW5kaW5nUGVyaW9kEF9pbml0TWFyZ2luUmF0aW8EX21tchRfbGlxdWlkYXRpb25GZWVSYXRpbwRfZmVlD19iYXNlT3JhY2xlRGF0YRBfcXVvdGVPcmFjbGVEYXRhDF9jb29yZGluYXRvcgxfc3ByZWFkTGltaXQPX21heFByaWNlSW1wYWN0GF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbw9fbWF4UHJpY2VTcHJlYWQQX21heE9wZW5Ob3Rpb25hbBRfZmVlVG9TdGFrZXJzUGVyY2VudA9fbWF4T3JhY2xlRGVsYXkMX3JvbGxvdmVyRmVlDF9mdW5kaW5nTW9kZQMDAwMDAwMDAwMDAwMDAwMDAwMJAGcCAAAFB19xdEFzdFIGCQBnAgAABQdfYnNBc3RSBgkAZwIAAAUOX2Z1bmRpbmdQZXJpb2QGCQBnAgAABRBfaW5pdE1hcmdpblJhdGlvBgkAZwIAAAUEX21tcgYJAGcCAAAFFF9saXF1aWRhdGlvbkZlZVJhdGlvBgkAZwIAAAUEX2ZlZQYJAGcCAAAFDF9zcHJlYWRMaW1pdAYJAGcCAAAFD19tYXhQcmljZUltcGFjdAYJAGcCAAAFGF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwYJAGcCAAAFD19tYXhQcmljZVNwcmVhZAYJAGcCAAAFEF9tYXhPcGVuTm90aW9uYWwGCQBnAgAABRRfZmVlVG9TdGFrZXJzUGVyY2VudAYJAGYCBRRfZmVlVG9TdGFrZXJzUGVyY2VudAUMREVDSU1BTF9VTklUBgkAZwIAAAUPX21heE9yYWNsZURlbGF5BgkAZwIAAAUMX3JvbGxvdmVyRmVlBgMJAQIhPQIFDF9mdW5kaW5nTW9kZQURRlVORElOR19TWU1NRVRSSUMJAQIhPQIFDF9mdW5kaW5nTW9kZQUSRlVORElOR19BU1lNTUVUUklDBwYJAQtpbml0aWFsaXplZAAGCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAh1JbnZhbGlkIGluaXRpYWxpemUgcGFyYW1ldGVycwkAzggCCQDOCAIJAM4IAgkAzggCCQEJdXBkYXRlQW1tCAUHX3F0QXN0UgUHX2JzQXN0UgAAAAAAAAAAAAAAAAkBDnVwZGF0ZVNldHRpbmdzDgUQX2luaXRNYXJnaW5SYXRpbwUEX21tcgUUX2xpcXVpZGF0aW9uRmVlUmF0aW8FDl9mdW5kaW5nUGVyaW9kBQRfZmVlBQxfc3ByZWFkTGltaXQFD19tYXhQcmljZUltcGFjdAUYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvBQ9fbWF4UHJpY2VTcHJlYWQFEF9tYXhPcGVuTm90aW9uYWwFFF9mZWVUb1N0YWtlcnNQZXJjZW50BQ9fbWF4T3JhY2xlRGVsYXkFDF9yb2xsb3ZlckZlZQUMX2Z1bmRpbmdNb2RlCQENdXBkYXRlRnVuZGluZwUJAGQCCQENbGFzdFRpbWVzdGFtcAAFDl9mdW5kaW5nUGVyaW9kAAAAAAAAAAAJAQ11cGRhdGVCYWxhbmNlAQAACQDMCAIJAQxCb29sZWFuRW50cnkCBQ1rX2luaXRpYWxpemVkBgkAzAgCCQELU3RyaW5nRW50cnkCBQxrX2Jhc2VPcmFjbGUFD19iYXNlT3JhY2xlRGF0YQkAzAgCCQELU3RyaW5nRW50cnkCBQ1rX3F1b3RlT3JhY2xlBRBfcXVvdGVPcmFjbGVEYXRhCQDMCAIJAQtTdHJpbmdFbnRyeQIFFGtfY29vcmRpbmF0b3JBZGRyZXNzCQClCAEJARFAZXh0ck5hdGl2ZSgxMDYyKQEFDF9jb29yZGluYXRvcgUDbmlsAWkBEGluY3JlYXNlUG9zaXRpb24ECl9kaXJlY3Rpb24JX2xldmVyYWdlE19taW5CYXNlQXNzZXRBbW91bnQIX3JlZkxpbmsEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQQZW5zdXJlQ2FsbGVkT25jZQkA/AcEBQR0aGlzAhBlbnN1cmVDYWxsZWRPbmNlBQNuaWwFA25pbAMJAAACBRBlbnN1cmVDYWxsZWRPbmNlBRBlbnN1cmVDYWxsZWRPbmNlBAdfdHJhZGVyCQEPZ2V0QWN0dWFsQ2FsbGVyAQUBaQQKX3Jhd0Ftb3VudAgJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQECF9hc3NldElkCAkAkQMCCAUBaQhwYXltZW50cwAAB2Fzc2V0SWQEC19hc3NldElkU3RyCQDYBAEJAQV2YWx1ZQEFCF9hc3NldElkBAxpc1F1b3RlQXNzZXQJAAACBQhfYXNzZXRJZAkBCnF1b3RlQXNzZXQAAwMDAwMDAwMDCQECIT0CBQpfZGlyZWN0aW9uBQhESVJfTE9ORwkBAiE9AgUKX2RpcmVjdGlvbgUJRElSX1NIT1JUBwYJAGcCAAAFCl9yYXdBbW91bnQGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEBIQEFDGlzUXVvdGVBc3NldAYJAQEhAQkBFnJlcXVpcmVNb3JlTWFyZ2luUmF0aW8DCQEEZGl2ZAIFDERFQ0lNQUxfVU5JVAUJX2xldmVyYWdlCQEPaW5pdE1hcmdpblJhdGlvAAYGCQEGcGF1c2VkAAYJAQljbG9zZU9ubHkABgkBDmlzTWFya2V0Q2xvc2VkAAkAAgECI0ludmFsaWQgaW5jcmVhc2VQb3NpdGlvbiBwYXJhbWV0ZXJzBA0kdDA1NzA4MzU3MjMyCQEYZ2V0Rm9yVHJhZGVyV2l0aEFydGlmYWN0AgUHX3RyYWRlcgkBDWdldEFydGlmYWN0SWQBBQFpBAthZGp1c3RlZEZlZQgFDSR0MDU3MDgzNTcyMzICXzEEDGJ1cm5BcnRpZmFjdAgFDSR0MDU3MDgzNTcyMzICXzIEB19hbW91bnQJAQRkaXZkAgUKX3Jhd0Ftb3VudAkAZAIJAQRtdWxkAgULYWRqdXN0ZWRGZWUFCV9sZXZlcmFnZQUMREVDSU1BTF9VTklUBBNkaXN0cmlidXRlRmVlQW1vdW50CQBlAgUKX3Jhd0Ftb3VudAUHX2Ftb3VudAQOcmVmZXJyZXJGZWVBbnkJAPwHBAkBD3JlZmVycmFsQWRkcmVzcwACFWFjY2VwdFBheW1lbnRXaXRoTGluawkAzAgCBQdfdHJhZGVyCQDMCAIFCF9yZWZMaW5rBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUTZGlzdHJpYnV0ZUZlZUFtb3VudAUDbmlsAwkAAAIFDnJlZmVycmVyRmVlQW55BQ5yZWZlcnJlckZlZUFueQQLcmVmZXJyZXJGZWUEByRtYXRjaDAFDnJlZmVycmVyRmVlQW55AwkAAQIFByRtYXRjaDACA0ludAQBeAUHJG1hdGNoMAUBeAkAAgECE0ludmFsaWQgcmVmZXJyZXJGZWUECWZlZUFtb3VudAkAZQIFE2Rpc3RyaWJ1dGVGZWVBbW91bnQFC3JlZmVycmVyRmVlBA0kdDA1NzcyODU3ODk2CQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBA9vbGRQb3NpdGlvblNpemUIBQ0kdDA1NzcyODU3ODk2Al8xBBFvbGRQb3NpdGlvbk1hcmdpbggFDSR0MDU3NzI4NTc4OTYCXzIEF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNTc3Mjg1Nzg5NgJfMwQUb2xkUG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA1NzcyODU3ODk2Al80BBRvbGRQb3NpdGlvblRpbWVzdGFtcAgFDSR0MDU3NzI4NTc4OTYCXzUEDWlzTmV3UG9zaXRpb24JAAACBQ9vbGRQb3NpdGlvblNpemUAAAQPaXNTYW1lRGlyZWN0aW9uAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAACQAAAgUKX2RpcmVjdGlvbgUIRElSX0xPTkcJAAACBQpfZGlyZWN0aW9uBQlESVJfU0hPUlQEDmV4cGFuZEV4aXN0aW5nAwkBASEBBQ1pc05ld1Bvc2l0aW9uBQ9pc1NhbWVEaXJlY3Rpb24HBAVpc0FkZAkAAAIFCl9kaXJlY3Rpb24FCERJUl9MT05HBA0kdDA1ODE4NTYxMzA2AwMFDWlzTmV3UG9zaXRpb24GBQ5leHBhbmRFeGlzdGluZwQMb3Blbk5vdGlvbmFsCQEEbXVsZAIFB19hbW91bnQFCV9sZXZlcmFnZQQNJHQwNTg2OTQ1ODg2NwkBCXN3YXBJbnB1dAIFBWlzQWRkBQxvcGVuTm90aW9uYWwEFWFtb3VudEJhc2VBc3NldEJvdWdodAgFDSR0MDU4Njk0NTg4NjcCXzEEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA1ODY5NDU4ODY3Al8yBBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA1ODY5NDU4ODY3Al8zBBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNTg2OTQ1ODg2NwJfNAMDCQECIT0CBRNfbWluQmFzZUFzc2V0QW1vdW50AAAJAGYCBRNfbWluQmFzZUFzc2V0QW1vdW50CQEDYWJzAQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0BwkAAgEJAKwCAgkArAICCQCsAgICDUxpbWl0IGVycm9yOiAJAKQDAQkBA2FicwEFFWFtb3VudEJhc2VBc3NldEJvdWdodAIDIDwgCQCkAwEFE19taW5CYXNlQXNzZXRBbW91bnQED25ld1Bvc2l0aW9uU2l6ZQkAZAIFD29sZFBvc2l0aW9uU2l6ZQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0BBp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgkAZAIJARBvcGVuSW50ZXJlc3RMb25nAAMJAGYCBQ9uZXdQb3NpdGlvblNpemUAAAUMb3Blbk5vdGlvbmFsAAAEG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgkAZAIJARFvcGVuSW50ZXJlc3RTaG9ydAADCQBmAgAABQ9uZXdQb3NpdGlvblNpemUFDG9wZW5Ob3Rpb25hbAAABA0kdDA1OTQxMzU5Njg4CQEwY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudEFuZFJvbGxvdmVyRmVlBQUPb2xkUG9zaXRpb25TaXplBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25Mc3RVcGRDUEYFFG9sZFBvc2l0aW9uVGltZXN0YW1wBQdfYW1vdW50BAxyZW1haW5NYXJnaW4IBQ0kdDA1OTQxMzU5Njg4Al8xBAJ4MQgFDSR0MDU5NDEzNTk2ODgCXzIEAngyCAUNJHQwNTk0MTM1OTY4OAJfMwQLcm9sbG92ZXJGZWUIBQ0kdDA1OTQxMzU5Njg4Al80AwkBASEBCQEZcmVxdWlyZU5vdE92ZXJTcHJlYWRMaW1pdAIFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgkAAgECFU92ZXIgbWF4IHNwcmVhZCBsaW1pdAMJAQEhAQkBHXJlcXVpcmVOb3RPdmVyTWF4T3Blbk5vdGlvbmFsAgUadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIFG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgkAAgECFk92ZXIgbWF4IG9wZW4gbm90aW9uYWwJAKAKDgUPbmV3UG9zaXRpb25TaXplBQxyZW1haW5NYXJnaW4JAGQCBRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAUMb3Blbk5vdGlvbmFsCQEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEFD25ld1Bvc2l0aW9uU2l6ZQkBDWxhc3RUaW1lc3RhbXAABRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIJAGQCCQEUb3BlbkludGVyZXN0Tm90aW9uYWwABQxvcGVuTm90aW9uYWwJAGQCCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAMJAGYCBQ9uZXdQb3NpdGlvblNpemUAAAkBA2FicwEFFWFtb3VudEJhc2VBc3NldEJvdWdodAAACQBkAgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUAAwkAZgIAAAUPbmV3UG9zaXRpb25TaXplCQEDYWJzAQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0AAAFGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyBRt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIFC3JvbGxvdmVyRmVlBAxvcGVuTm90aW9uYWwJAQRtdWxkAgUHX2Ftb3VudAUJX2xldmVyYWdlBA0kdDA2MTAwNjYxMTIyCQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCCQClCAEIBQFpBmNhbGxlcgUPUE5MX09QVElPTl9TUE9UBBNvbGRQb3NpdGlvbk5vdGlvbmFsCAUNJHQwNjEwMDY2MTEyMgJfMQQNdW5yZWFsaXplZFBubAgFDSR0MDYxMDA2NjExMjICXzIDCQBmAgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUMb3Blbk5vdGlvbmFsCQACAQIuVXNlIGRlY3JlYXNlUG9zaXRpb24gdG8gZGVjcmVhc2UgcG9zaXRpb24gc2l6ZQkAAgECFENsb3NlIHBvc2l0aW9uIGZpcnN0BA9uZXdQb3NpdGlvblNpemUIBQ0kdDA1ODE4NTYxMzA2Al8xBBduZXdQb3NpdGlvblJlbWFpbk1hcmdpbggFDSR0MDU4MTg1NjEzMDYCXzIEF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNTgxODU2MTMwNgJfMwQUbmV3UG9zaXRpb25MYXRlc3RDUEYIBQ0kdDA1ODE4NTYxMzA2Al80BBRuZXdQb3NpdGlvblRpbWVzdGFtcAgFDSR0MDU4MTg1NjEzMDYCXzUEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDU4MTg1NjEzMDYCXzYEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA1ODE4NTYxMzA2Al83BBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNTgxODU2MTMwNgJfOAQZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcggFDSR0MDU4MTg1NjEzMDYCXzkEDnRvdGFsTG9uZ0FmdGVyCAUNJHQwNTgxODU2MTMwNgNfMTAED3RvdGFsU2hvcnRBZnRlcggFDSR0MDU4MTg1NjEzMDYDXzExBBp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDU4MTg1NjEzMDYDXzEyBBt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA1ODE4NTYxMzA2A18xMwQLcm9sbG92ZXJGZWUIBQ0kdDA1ODE4NTYxMzA2A18xNAQNJHQwNjEzMTI2MTM4MwkBDWRpc3RyaWJ1dGVGZWUBCQBkAgUJZmVlQW1vdW50BQtyb2xsb3ZlckZlZQQMZmVlVG9TdGFrZXJzCAUNJHQwNjEzMTI2MTM4MwJfMQQKZmVlVG9WYXVsdAgFDSR0MDYxMzEyNjEzODMCXzIEBXN0YWtlAwkAZwIFB19hbW91bnQFC3JvbGxvdmVyRmVlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAglhZGRMb2NrZWQFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQACQBlAgUHX2Ftb3VudAULcm9sbG92ZXJGZWUFA25pbAkA/AcECQEMdmF1bHRBZGRyZXNzAAIOd2l0aGRyYXdMb2NrZWQJAMwIAgkAZQIFC3JvbGxvdmVyRmVlBQdfYW1vdW50BQNuaWwFA25pbAMJAAACBQVzdGFrZQUFc3Rha2UEDGRlcG9zaXRWYXVsdAkA/AcECQEMdmF1bHRBZGRyZXNzAAIHYWRkRnJlZQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFCmZlZVRvVmF1bHQFA25pbAMJAAACBQxkZXBvc2l0VmF1bHQFDGRlcG9zaXRWYXVsdAQJbm90aWZ5RmVlCQD8BwQJAQxtaW5lckFkZHJlc3MAAgpub3RpZnlGZWVzCQDMCAIFB190cmFkZXIJAMwIAgUJZmVlQW1vdW50BQNuaWwFA25pbAMJAAACBQlub3RpZnlGZWUFCW5vdGlmeUZlZQQObm90aWZ5Tm90aW9uYWwJAPwHBAkBDG1pbmVyQWRkcmVzcwACDm5vdGlmeU5vdGlvbmFsCQDMCAIFB190cmFkZXIJAMwIAgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFA25pbAUDbmlsAwkAAAIFDm5vdGlmeU5vdGlvbmFsBQ5ub3RpZnlOb3Rpb25hbAkAzggCCQDOCAIJAM4IAgkAzggCCQDOCAIJAM4IAgkBDnVwZGF0ZVBvc2l0aW9uBgUHX3RyYWRlcgUPbmV3UG9zaXRpb25TaXplBRduZXdQb3NpdGlvblJlbWFpbk1hcmdpbgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFFG5ld1Bvc2l0aW9uTGF0ZXN0Q1BGBRRuZXdQb3NpdGlvblRpbWVzdGFtcAkBH2luY3JlbWVudFBvc2l0aW9uU2VxdWVuY2VOdW1iZXICBQ1pc05ld1Bvc2l0aW9uBQdfdHJhZGVyCQERdXBkYXRlUG9zaXRpb25GZWUDBQ1pc05ld1Bvc2l0aW9uBQdfdHJhZGVyBQthZGp1c3RlZEZlZQkBCXVwZGF0ZUFtbQgFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgUZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcgUOdG90YWxMb25nQWZ0ZXIFD3RvdGFsU2hvcnRBZnRlcgUadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIFG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgkBC3RyYW5zZmVyRmVlAQUMZmVlVG9TdGFrZXJzCQENdXBkYXRlQmFsYW5jZQEJAGUCCQBkAgkBCGNiYWxhbmNlAAUHX2Ftb3VudAULcm9sbG92ZXJGZWUJAQ5kb0J1cm5BcnRpZmFjdAIFDGJ1cm5BcnRpZmFjdAUBaQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQlhZGRNYXJnaW4ABARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEEGVuc3VyZUNhbGxlZE9uY2UJAPwHBAUEdGhpcwIQZW5zdXJlQ2FsbGVkT25jZQUDbmlsBQNuaWwDCQAAAgUQZW5zdXJlQ2FsbGVkT25jZQUQZW5zdXJlQ2FsbGVkT25jZQQHX3RyYWRlcgkApQgBCAUBaQZjYWxsZXIEB19hbW91bnQICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50BAhfYXNzZXRJZAgJAJEDAggFAWkIcGF5bWVudHMAAAdhc3NldElkBAtfYXNzZXRJZFN0cgkA2AQBCQEFdmFsdWUBBQhfYXNzZXRJZAQMaXNRdW90ZUFzc2V0CQAAAgUIX2Fzc2V0SWQJAQpxdW90ZUFzc2V0AAMDAwMDAwkBASEBBQxpc1F1b3RlQXNzZXQGCQEBIQEJARNyZXF1aXJlT3BlblBvc2l0aW9uAQkApQgBCAUBaQZjYWxsZXIGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAYJAQljbG9zZU9ubHkABgkBDmlzTWFya2V0Q2xvc2VkAAkAAgECHEludmFsaWQgYWRkTWFyZ2luIHBhcmFtZXRlcnMEDSR0MDYzNTk4NjM3NjYJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIED29sZFBvc2l0aW9uU2l6ZQgFDSR0MDYzNTk4NjM3NjYCXzEEEW9sZFBvc2l0aW9uTWFyZ2luCAUNJHQwNjM1OTg2Mzc2NgJfMgQXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA2MzU5ODYzNzY2Al8zBBRvbGRQb3NpdGlvbkxzdFVwZENQRggFDSR0MDYzNTk4NjM3NjYCXzQEFG9sZFBvc2l0aW9uVGltZXN0YW1wCAUNJHQwNjM1OTg2Mzc2NgJfNQQFc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACCWFkZExvY2tlZAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFB19hbW91bnQFA25pbAMJAAACBQVzdGFrZQUFc3Rha2UEC3JvbGxvdmVyRmVlCQEPY2FsY1JvbGxvdmVyRmVlAgURb2xkUG9zaXRpb25NYXJnaW4FFG9sZFBvc2l0aW9uVGltZXN0YW1wBBZkb1RyYW5zZmVyRmVlVG9TdGFrZXJzAwkAZgIFC3JvbGxvdmVyRmVlAAAEDSR0MDY0MDUxNjQxMTAJAQ1kaXN0cmlidXRlRmVlAQULcm9sbG92ZXJGZWUEDGZlZVRvU3Rha2VycwgFDSR0MDY0MDUxNjQxMTACXzEECmZlZVRvVmF1bHQIBQ0kdDA2NDA1MTY0MTEwAl8yBAd1bnN0YWtlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAg53aXRoZHJhd0xvY2tlZAkAzAgCBQxmZWVUb1N0YWtlcnMFA25pbAUDbmlsAwkAAAIFB3Vuc3Rha2UFB3Vuc3Rha2UEC2xvY2tCYWREZWJ0CQD8BwQJAQx2YXVsdEFkZHJlc3MAAhVleGNoYW5nZUZyZWVBbmRMb2NrZWQJAMwIAgkBAS0BBQpmZWVUb1ZhdWx0BQNuaWwFA25pbAMJAAACBQtsb2NrQmFkRGVidAULbG9ja0JhZERlYnQJAQt0cmFuc2ZlckZlZQEFDGZlZVRvU3Rha2VycwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFFmRvVHJhbnNmZXJGZWVUb1N0YWtlcnMFFmRvVHJhbnNmZXJGZWVUb1N0YWtlcnMJAM4IAgkAzggCCQEOdXBkYXRlUG9zaXRpb24GBQdfdHJhZGVyBQ9vbGRQb3NpdGlvblNpemUJAGQCCQBlAgURb2xkUG9zaXRpb25NYXJnaW4FC3JvbGxvdmVyRmVlBQdfYW1vdW50BRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAUUb2xkUG9zaXRpb25Mc3RVcGRDUEYJAQ1sYXN0VGltZXN0YW1wAAkBDXVwZGF0ZUJhbGFuY2UBCQBlAgkAZAIJAQhjYmFsYW5jZQAFB19hbW91bnQFC3JvbGxvdmVyRmVlBRZkb1RyYW5zZmVyRmVlVG9TdGFrZXJzCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDHJlbW92ZU1hcmdpbgEHX2Ftb3VudAQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBBBlbnN1cmVDYWxsZWRPbmNlCQD8BwQFBHRoaXMCEGVuc3VyZUNhbGxlZE9uY2UFA25pbAUDbmlsAwkAAAIFEGVuc3VyZUNhbGxlZE9uY2UFEGVuc3VyZUNhbGxlZE9uY2UEB190cmFkZXIJAKUIAQgFAWkGY2FsbGVyAwMDAwMJAGcCAAAFB19hbW91bnQGCQEBIQEJARNyZXF1aXJlT3BlblBvc2l0aW9uAQUHX3RyYWRlcgYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQZwYXVzZWQABgkBDmlzTWFya2V0Q2xvc2VkAAkAAgECH0ludmFsaWQgcmVtb3ZlTWFyZ2luIHBhcmFtZXRlcnMEDSR0MDY1NDgzNjU2NTEJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIED29sZFBvc2l0aW9uU2l6ZQgFDSR0MDY1NDgzNjU2NTECXzEEEW9sZFBvc2l0aW9uTWFyZ2luCAUNJHQwNjU0ODM2NTY1MQJfMgQXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA2NTQ4MzY1NjUxAl8zBBRvbGRQb3NpdGlvbkxzdFVwZENQRggFDSR0MDY1NDgzNjU2NTECXzQEFG9sZFBvc2l0aW9uVGltZXN0YW1wCAUNJHQwNjU0ODM2NTY1MQJfNQQNJHQwNjU2NTc2NTkwNgkBMGNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnRBbmRSb2xsb3ZlckZlZQUFD29sZFBvc2l0aW9uU2l6ZQURb2xkUG9zaXRpb25NYXJnaW4FFG9sZFBvc2l0aW9uTHN0VXBkQ1BGBRRvbGRQb3NpdGlvblRpbWVzdGFtcAkBAS0BBQdfYW1vdW50BAxyZW1haW5NYXJnaW4IBQ0kdDA2NTY1NzY1OTA2Al8xBAdiYWREZWJ0CAUNJHQwNjU2NTc2NTkwNgJfMgQOZnVuZGluZ1BheW1lbnQIBQ0kdDA2NTY1NzY1OTA2Al8zBAtyb2xsb3ZlckZlZQgFDSR0MDY1NjU3NjU5MDYCXzQDCQECIT0CBQdiYWREZWJ0AAAJAAIBAh1JbnZhbGlkIHJlbW92ZWQgbWFyZ2luIGFtb3VudAQLbWFyZ2luUmF0aW8JAQ9jYWxjTWFyZ2luUmF0aW8DBQxyZW1haW5NYXJnaW4FB2JhZERlYnQFF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsAwkBASEBCQEWcmVxdWlyZU1vcmVNYXJnaW5SYXRpbwMFC21hcmdpblJhdGlvCQEPaW5pdE1hcmdpblJhdGlvAAYJAAIBCQCsAgIJAKwCAgkArAICAhlUb28gbXVjaCBtYXJnaW4gcmVtb3ZlZDogCQCkAwEFC21hcmdpblJhdGlvAgMgPCAJAKQDAQkBD2luaXRNYXJnaW5SYXRpbwAEDSR0MDY2MjkyNjYzNTEJAQ1kaXN0cmlidXRlRmVlAQULcm9sbG92ZXJGZWUEDGZlZVRvU3Rha2VycwgFDSR0MDY2MjkyNjYzNTECXzEECmZlZVRvVmF1bHQIBQ0kdDA2NjI5MjY2MzUxAl8yBBZkb1RyYW5zZmVyRmVlVG9TdGFrZXJzAwkAZgIFC3JvbGxvdmVyRmVlAAAEC2xvY2tCYWREZWJ0CQD8BwQJAQx2YXVsdEFkZHJlc3MAAhVleGNoYW5nZUZyZWVBbmRMb2NrZWQJAMwIAgkBAS0BBQpmZWVUb1ZhdWx0BQNuaWwFA25pbAMJAAACBQtsb2NrQmFkRGVidAULbG9ja0JhZERlYnQJAQt0cmFuc2ZlckZlZQEFDGZlZVRvU3Rha2VycwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFFmRvVHJhbnNmZXJGZWVUb1N0YWtlcnMFFmRvVHJhbnNmZXJGZWVUb1N0YWtlcnMEB3Vuc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACDndpdGhkcmF3TG9ja2VkCQDMCAIJAGQCBQdfYW1vdW50BQxmZWVUb1N0YWtlcnMFA25pbAUDbmlsAwkAAAIFB3Vuc3Rha2UFB3Vuc3Rha2UJAM4IAgkAzggCCQDOCAIJAQ51cGRhdGVQb3NpdGlvbgYFB190cmFkZXIFD29sZFBvc2l0aW9uU2l6ZQUMcmVtYWluTWFyZ2luBRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAkBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BBQ9vbGRQb3NpdGlvblNpemUJAQ1sYXN0VGltZXN0YW1wAAkBCHdpdGhkcmF3AggFAWkGY2FsbGVyBQdfYW1vdW50CQENdXBkYXRlQmFsYW5jZQEJAGUCCQBlAgkBCGNiYWxhbmNlAAUHX2Ftb3VudAULcm9sbG92ZXJGZWUFFmRvVHJhbnNmZXJGZWVUb1N0YWtlcnMJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQENY2xvc2VQb3NpdGlvbgMFX3NpemUUX21pblF1b3RlQXNzZXRBbW91bnQMX2FkZFRvTWFyZ2luBARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEEGVuc3VyZUNhbGxlZE9uY2UJAPwHBAUEdGhpcwIQZW5zdXJlQ2FsbGVkT25jZQUDbmlsBQNuaWwDCQAAAgUQZW5zdXJlQ2FsbGVkT25jZQUQZW5zdXJlQ2FsbGVkT25jZQQHX3RyYWRlcgkBD2dldEFjdHVhbENhbGxlcgEFAWkEDl90cmFkZXJBZGRyZXNzCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQUHX3RyYWRlcgIOSW52YWxpZCBjYWxsZXIEC3Bvc2l0aW9uRmVlCQEOZ2V0UG9zaXRpb25GZWUBBQdfdHJhZGVyAwMDAwMDCQEBIQEJARNyZXF1aXJlT3BlblBvc2l0aW9uAQUHX3RyYWRlcgYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQZwYXVzZWQABgkAZwIAAAUFX3NpemUGCQBmAgAABRRfbWluUXVvdGVBc3NldEFtb3VudAYJAQ5pc01hcmtldENsb3NlZAAJAAIBAiBJbnZhbGlkIGNsb3NlUG9zaXRpb24gcGFyYW1ldGVycwQUb2xkUG9zaXRpb25UaW1lc3RhbXAICQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyAl81BA0kdDA2ODUyNjY5MTExCQEVaW50ZXJuYWxDbG9zZVBvc2l0aW9uBwUHX3RyYWRlcgUFX3NpemUFC3Bvc2l0aW9uRmVlBRRfbWluUXVvdGVBc3NldEFtb3VudAUMX2FkZFRvTWFyZ2luBgYED25ld1Bvc2l0aW9uU2l6ZQgFDSR0MDY4NTI2NjkxMTECXzEEEW5ld1Bvc2l0aW9uTWFyZ2luCAUNJHQwNjg1MjY2OTExMQJfMgQXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA2ODUyNjY5MTExAl8zBBRuZXdQb3NpdGlvbkxzdFVwZENQRggFDSR0MDY4NTI2NjkxMTECXzQED3Bvc2l0aW9uQmFkRGVidAgFDSR0MDY4NTI2NjkxMTECXzUEC3JlYWxpemVkUG5sCAUNJHQwNjg1MjY2OTExMQJfNgQObWFyZ2luVG9UcmFkZXIIBQ0kdDA2ODUyNjY5MTExAl83BBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNjg1MjY2OTExMQJfOAQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNjg1MjY2OTExMQJfOQQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDY4NTI2NjkxMTEDXzEwBBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCAUNJHQwNjg1MjY2OTExMQNfMTEEDnRvdGFsTG9uZ0FmdGVyCAUNJHQwNjg1MjY2OTExMQNfMTIED3RvdGFsU2hvcnRBZnRlcggFDSR0MDY4NTI2NjkxMTEDXzEzBBp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDY4NTI2NjkxMTEDXzE0BBt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA2ODUyNjY5MTExA18xNQQLcmVhbGl6ZWRGZWUIBQ0kdDA2ODUyNjY5MTExA18xNgMJAGYCBQ9wb3NpdGlvbkJhZERlYnQAAAkAAgECKkludmFsaWQgY2xvc2VQb3NpdGlvbiBwYXJhbWV0ZXJzOiBiYWQgZGVidAMJAGcCBRRvbGRQb3NpdGlvblRpbWVzdGFtcAkBDWxhc3RUaW1lc3RhbXAACQACAQJTSW52YWxpZCBjbG9zZVBvc2l0aW9uIHBhcmFtZXRlcnM6IHdhaXQgYXQgbGVhc3QgMSBibG9jayBiZWZvcmUgY2xvc2luZyB0aGUgcG9zaXRpb24EDmlzUGFydGlhbENsb3NlCQECIT0CBQ9uZXdQb3NpdGlvblNpemUAAAQOd2l0aGRyYXdBbW91bnQJAGQCBQ5tYXJnaW5Ub1RyYWRlcgULcmVhbGl6ZWRGZWUECmFtbUJhbGFuY2UJAGUCCQEIY2JhbGFuY2UABQ53aXRoZHJhd0Ftb3VudAQNYW1tTmV3QmFsYW5jZQMJAGYCAAAFCmFtbUJhbGFuY2UAAAUKYW1tQmFsYW5jZQQHdW5zdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIOd2l0aGRyYXdMb2NrZWQJAMwIAgUOd2l0aGRyYXdBbW91bnQFA25pbAUDbmlsAwkAAAIFB3Vuc3Rha2UFB3Vuc3Rha2UEDSR0MDY5NzgzNjk4NDIJAQ1kaXN0cmlidXRlRmVlAQULcmVhbGl6ZWRGZWUEDGZlZVRvU3Rha2VycwgFDSR0MDY5NzgzNjk4NDICXzEECmZlZVRvVmF1bHQIBQ0kdDA2OTc4MzY5ODQyAl8yBAxkZXBvc2l0VmF1bHQJAPwHBAkBDHZhdWx0QWRkcmVzcwACB2FkZEZyZWUFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABQpmZWVUb1ZhdWx0BQNuaWwDCQAAAgUMZGVwb3NpdFZhdWx0BQxkZXBvc2l0VmF1bHQECW5vdGlmeUZlZQkA/AcECQEMbWluZXJBZGRyZXNzAAIKbm90aWZ5RmVlcwkAzAgCBQdfdHJhZGVyCQDMCAIFC3JlYWxpemVkRmVlBQNuaWwFA25pbAMJAAACBQlub3RpZnlGZWUFCW5vdGlmeUZlZQQObm90aWZ5Tm90aW9uYWwJAPwHBAkBDG1pbmVyQWRkcmVzcwACDm5vdGlmeU5vdGlvbmFsCQDMCAIFB190cmFkZXIJAMwIAgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFA25pbAUDbmlsAwkAAAIFDm5vdGlmeU5vdGlvbmFsBQ5ub3RpZnlOb3Rpb25hbAkAzggCCQDOCAIJAM4IAgkAzggCAwUOaXNQYXJ0aWFsQ2xvc2UJAQ51cGRhdGVQb3NpdGlvbgYFB190cmFkZXIFD25ld1Bvc2l0aW9uU2l6ZQURbmV3UG9zaXRpb25NYXJnaW4FF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBRRuZXdQb3NpdGlvbkxzdFVwZENQRgkBDWxhc3RUaW1lc3RhbXAACQEOZGVsZXRlUG9zaXRpb24BBQdfdHJhZGVyCQEJdXBkYXRlQW1tCAUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyBRp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgUbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyAwkAZgIFDm1hcmdpblRvVHJhZGVyAAAJAQh3aXRoZHJhdwIFDl90cmFkZXJBZGRyZXNzBQ5tYXJnaW5Ub1RyYWRlcgUDbmlsCQENdXBkYXRlQmFsYW5jZQEFDWFtbU5ld0JhbGFuY2UJAQt0cmFuc2ZlckZlZQEFDGZlZVRvU3Rha2VycwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQlsaXF1aWRhdGUBB190cmFkZXIEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQPc3BvdE1hcmdpblJhdGlvCQEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAQWbGlxdWlkYXRpb25NYXJnaW5SYXRpbwMJARZpc092ZXJGbHVjdHVhdGlvbkxpbWl0AAQRb3JhY2xlTWFyZ2luUmF0aW8JARZnZXRNYXJnaW5SYXRpb0J5T3B0aW9uAgUHX3RyYWRlcgURUE5MX09QVElPTl9PUkFDTEUJAQR2bWF4AgUPc3BvdE1hcmdpblJhdGlvBRFvcmFjbGVNYXJnaW5SYXRpbwUPc3BvdE1hcmdpblJhdGlvAwMDAwMJAQEhAQkBFnJlcXVpcmVNb3JlTWFyZ2luUmF0aW8DBRZsaXF1aWRhdGlvbk1hcmdpblJhdGlvCQEWbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwAHBgkBASEBCQETcmVxdWlyZU9wZW5Qb3NpdGlvbgEFB190cmFkZXIGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAYJAQ5pc01hcmtldENsb3NlZAAJAAIBAhNVbmFibGUgdG8gbGlxdWlkYXRlBBRpc1BhcnRpYWxMaXF1aWRhdGlvbgMDCQBmAgUPc3BvdE1hcmdpblJhdGlvCQETbGlxdWlkYXRpb25GZWVSYXRpbwAJAGYCCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8AAAAHCQBmAgUMREVDSU1BTF9VTklUCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8ABwQPb2xkUG9zaXRpb25TaXplCAkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgJfMQQPcG9zaXRpb25TaXplQWJzCQEDYWJzAQUPb2xkUG9zaXRpb25TaXplBA0kdDA3MjI2MzcyNTg2AwUUaXNQYXJ0aWFsTGlxdWlkYXRpb24ED2xpcXVpZGF0aW9uU2l6ZQkBG2dldFBhcnRpYWxMaXF1aWRhdGlvbkFtb3VudAIFB190cmFkZXIFD29sZFBvc2l0aW9uU2l6ZQQQbGlxdWlkYXRpb25SYXRpbwkBBGRpdmQCCQEDYWJzAQUPbGlxdWlkYXRpb25TaXplBQ9wb3NpdGlvblNpemVBYnMJAJQKAgUQbGlxdWlkYXRpb25SYXRpbwkBA2FicwEFD2xpcXVpZGF0aW9uU2l6ZQkAlAoCAAAFD3Bvc2l0aW9uU2l6ZUFicwQQbGlxdWlkYXRpb25SYXRpbwgFDSR0MDcyMjYzNzI1ODYCXzEED2xpcXVpZGF0aW9uU2l6ZQgFDSR0MDcyMjYzNzI1ODYCXzIEDSR0MDcyNTkyNzMyMzAJARVpbnRlcm5hbENsb3NlUG9zaXRpb24HBQdfdHJhZGVyAwUUaXNQYXJ0aWFsTGlxdWlkYXRpb24FD2xpcXVpZGF0aW9uU2l6ZQUPcG9zaXRpb25TaXplQWJzCQETbGlxdWlkYXRpb25GZWVSYXRpbwAAAAYHBgQPbmV3UG9zaXRpb25TaXplCAUNJHQwNzI1OTI3MzIzMAJfMQQRbmV3UG9zaXRpb25NYXJnaW4IBQ0kdDA3MjU5MjczMjMwAl8yBBduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDcyNTkyNzMyMzACXzMEFG5ld1Bvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwNzI1OTI3MzIzMAJfNAQPcG9zaXRpb25CYWREZWJ0CAUNJHQwNzI1OTI3MzIzMAJfNQQLcmVhbGl6ZWRQbmwIBQ0kdDA3MjU5MjczMjMwAl82BA5tYXJnaW5Ub1RyYWRlcggFDSR0MDcyNTkyNzMyMzACXzcEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA3MjU5MjczMjMwAl84BBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA3MjU5MjczMjMwAl85BBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNzI1OTI3MzIzMANfMTAEGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIIBQ0kdDA3MjU5MjczMjMwA18xMQQOdG90YWxMb25nQWZ0ZXIIBQ0kdDA3MjU5MjczMjMwA18xMgQPdG90YWxTaG9ydEFmdGVyCAUNJHQwNzI1OTI3MzIzMANfMTMEGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNzI1OTI3MzIzMANfMTQEG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDcyNTkyNzMyMzADXzE1BBJsaXF1aWRhdGlvblBlbmFsdHkIBQ0kdDA3MjU5MjczMjMwA18xNgQPZmVlVG9MaXF1aWRhdG9yCQBpAgUSbGlxdWlkYXRpb25QZW5hbHR5AAIECmZlZVRvVmF1bHQJAGUCBRJsaXF1aWRhdGlvblBlbmFsdHkFD2ZlZVRvTGlxdWlkYXRvcgQKYW1tQmFsYW5jZQkAZQIJAQhjYmFsYW5jZQAFEmxpcXVpZGF0aW9uUGVuYWx0eQQNbmV3QW1tQmFsYW5jZQMJAGYCAAAFCmFtbUJhbGFuY2UAAAUKYW1tQmFsYW5jZQQLbG9ja0JhZERlYnQDCQBmAgUPcG9zaXRpb25CYWREZWJ0AAAEC2xvY2tCYWREZWJ0CQD8BwQJAQx2YXVsdEFkZHJlc3MAAhVleGNoYW5nZUZyZWVBbmRMb2NrZWQJAMwIAgkAZAIFD3Bvc2l0aW9uQmFkRGVidAUSbGlxdWlkYXRpb25QZW5hbHR5BQNuaWwFA25pbAMJAAACBQtsb2NrQmFkRGVidAULbG9ja0JhZERlYnQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFC2xvY2tCYWREZWJ0BQtsb2NrQmFkRGVidAQHdW5zdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIOd2l0aGRyYXdMb2NrZWQJAMwIAgUSbGlxdWlkYXRpb25QZW5hbHR5BQNuaWwFA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlBBBkZXBvc2l0SW5zdXJhbmNlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAgdhZGRGcmVlBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUKZmVlVG9WYXVsdAUDbmlsAwkAAAIFEGRlcG9zaXRJbnN1cmFuY2UFEGRlcG9zaXRJbnN1cmFuY2UEDm5vdGlmeU5vdGlvbmFsCQD8BwQJAQxtaW5lckFkZHJlc3MAAg5ub3RpZnlOb3Rpb25hbAkAzAgCBQdfdHJhZGVyCQDMCAIFF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBQNuaWwFA25pbAMJAAACBQ5ub3RpZnlOb3Rpb25hbAUObm90aWZ5Tm90aW9uYWwJAM4IAgkAzggCCQDOCAIDBRRpc1BhcnRpYWxMaXF1aWRhdGlvbgkBDnVwZGF0ZVBvc2l0aW9uBgUHX3RyYWRlcgUPbmV3UG9zaXRpb25TaXplBRFuZXdQb3NpdGlvbk1hcmdpbgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFFG5ld1Bvc2l0aW9uTHN0VXBkQ1BGCQENbGFzdFRpbWVzdGFtcAAJAQ5kZWxldGVQb3NpdGlvbgEFB190cmFkZXIJAQl1cGRhdGVBbW0IBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIFDnRvdGFsTG9uZ0FmdGVyBQ90b3RhbFNob3J0QWZ0ZXIFGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyBRt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIJAQh3aXRoZHJhdwIIBQFpBmNhbGxlcgUPZmVlVG9MaXF1aWRhdG9yCQENdXBkYXRlQmFsYW5jZQEFDW5ld0FtbUJhbGFuY2UJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEKcGF5RnVuZGluZwAEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQVZnVuZGluZ0Jsb2NrVGltZXN0YW1wCQEZbmV4dEZ1bmRpbmdCbG9ja1RpbWVzdGFtcAADAwMJAGYCBRVmdW5kaW5nQmxvY2tUaW1lc3RhbXAJAQ1sYXN0VGltZXN0YW1wAAYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQZwYXVzZWQACQACAQkArAICCQCsAgIJAKwCAgIhSW52YWxpZCBmdW5kaW5nIGJsb2NrIHRpbWVzdGFtcDogCQCkAwEJAQ1sYXN0VGltZXN0YW1wAAIDIDwgCQCkAwEFFWZ1bmRpbmdCbG9ja1RpbWVzdGFtcAQPdW5kZXJseWluZ1ByaWNlCQEOZ2V0T3JhY2xlUHJpY2UABA0kdDA3NTM0Mzc1NDIxCQEKZ2V0RnVuZGluZwAEFHNob3J0UHJlbWl1bUZyYWN0aW9uCAUNJHQwNzUzNDM3NTQyMQJfMQQTbG9uZ1ByZW1pdW1GcmFjdGlvbggFDSR0MDc1MzQzNzU0MjECXzIEDnByZW1pdW1Ub1ZhdWx0CAUNJHQwNzUzNDM3NTQyMQJfMwQTZG9QYXlGdW5kaW5nVG9WYXVsdAMJAGYCBQ5wcmVtaXVtVG9WYXVsdAAABBNkb1BheUZ1bmRpbmdUb1ZhdWx0CQD8BwQJAQx2YXVsdEFkZHJlc3MAAhVleGNoYW5nZUZyZWVBbmRMb2NrZWQJAMwIAgkBAS0BBQ5wcmVtaXVtVG9WYXVsdAUDbmlsBQNuaWwDCQAAAgUTZG9QYXlGdW5kaW5nVG9WYXVsdAUTZG9QYXlGdW5kaW5nVG9WYXVsdAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUTZG9QYXlGdW5kaW5nVG9WYXVsdAUTZG9QYXlGdW5kaW5nVG9WYXVsdAkBDXVwZGF0ZUZ1bmRpbmcFCQBkAgUVZnVuZGluZ0Jsb2NrVGltZXN0YW1wCQEUZnVuZGluZ1BlcmlvZFNlY29uZHMACQBkAgkBI2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAUTbG9uZ1ByZW1pdW1GcmFjdGlvbgkAZAIJASRsYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24ABRRzaG9ydFByZW1pdW1GcmFjdGlvbgkBBGRpdmQCBRNsb25nUHJlbWl1bUZyYWN0aW9uBQ91bmRlcmx5aW5nUHJpY2UJAQRkaXZkAgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24FD3VuZGVybHlpbmdQcmljZQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlAAMJAQhkZWxpc3RlZAAFA25pbAQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABA0kdDA3NjUxMTc2ODk1CQEUZ2V0U3luY1Rlcm1pbmFsUHJpY2UDCQEOZ2V0T3JhY2xlUHJpY2UABQdfcXRBc3RSBQdfYnNBc3RSBBNuZXdRdW90ZUFzc2V0V2VpZ2h0CAUNJHQwNzY1MTE3Njg5NQJfMQQSbmV3QmFzZUFzc2V0V2VpZ2h0CAUNJHQwNzY1MTE3Njg5NQJfMgQNbWFyZ2luVG9WYXVsdAgFDSR0MDc2NTExNzY4OTUCXzMEEG1hcmdpblRvVmF1bHRBZGoDAwkAZgIAAAUNbWFyZ2luVG9WYXVsdAkAZgIJAQNhYnMBBQ1tYXJnaW5Ub1ZhdWx0CQEIY2JhbGFuY2UABwkBAS0BCQEIY2JhbGFuY2UABQ1tYXJnaW5Ub1ZhdWx0BA1kb0V4Y2hhbmdlUG5MAwkBAiE9AgUQbWFyZ2luVG9WYXVsdEFkagAABA1kb0V4Y2hhbmdlUG5MCQD8BwQJAQx2YXVsdEFkZHJlc3MAAhVleGNoYW5nZUZyZWVBbmRMb2NrZWQJAMwIAgUQbWFyZ2luVG9WYXVsdEFkagUDbmlsBQNuaWwDCQAAAgUNZG9FeGNoYW5nZVBuTAUNZG9FeGNoYW5nZVBuTAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUNZG9FeGNoYW5nZVBuTAUNZG9FeGNoYW5nZVBuTAkAzggCCQENdXBkYXRlQmFsYW5jZQEJAGQCCQEIY2JhbGFuY2UABRBtYXJnaW5Ub1ZhdWx0QWRqCQEQdXBkYXRlQW1tV2VpZ2h0cwIFE25ld1F1b3RlQXNzZXRXZWlnaHQFEm5ld0Jhc2VBc3NldFdlaWdodAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARBlbnN1cmVDYWxsZWRPbmNlAAMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECIkludmFsaWQgc2F2ZUN1cnJlbnRUeElkIHBhcmFtZXRlcnMEBmxhc3RUeAkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzBQhrX2xhc3RUeAIAAwkBAiE9AgUGbGFzdFR4CQDYBAEIBQFpDXRyYW5zYWN0aW9uSWQJAMwIAgkBC1N0cmluZ0VudHJ5AgUIa19sYXN0VHgFBmxhc3RUeAUDbmlsCQACAQIpQ2FuIG5vdCBjYWxsIHZBTU0gbWV0aG9kcyB0d2ljZSBpbiBvbmUgdHgBaQEndmlld19jYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50AQdfdHJhZGVyBARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEDSR0MDc4NDkwNzg2MTQJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIEDHBvc2l0aW9uU2l6ZQgFDSR0MDc4NDkwNzg2MTQCXzEEDnBvc2l0aW9uTWFyZ2luCAUNJHQwNzg0OTA3ODYxNAJfMgQDcG9uCAUNJHQwNzg0OTA3ODYxNAJfMwQRcG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA3ODQ5MDc4NjE0Al80BBFwb3NpdGlvblRpbWVzdGFtcAgFDSR0MDc4NDkwNzg2MTQCXzUEDSR0MDc4NjE3Nzg3MTgJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAQQcG9zaXRpb25Ob3Rpb25hbAgFDSR0MDc4NjE3Nzg3MTgCXzEEDXVucmVhbGl6ZWRQbmwIBQ0kdDA3ODYxNzc4NzE4Al8yBA0kdDA3ODcyMTc4OTQ1CQEwY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudEFuZFJvbGxvdmVyRmVlBQUMcG9zaXRpb25TaXplBQ5wb3NpdGlvbk1hcmdpbgURcG9zaXRpb25Mc3RVcGRDUEYFEXBvc2l0aW9uVGltZXN0YW1wBQ11bnJlYWxpemVkUG5sBAxyZW1haW5NYXJnaW4IBQ0kdDA3ODcyMTc4OTQ1Al8xBAdiYWREZWJ0CAUNJHQwNzg3MjE3ODk0NQJfMgQOZnVuZGluZ1BheW1lbnQIBQ0kdDA3ODcyMTc4OTQ1Al8zBAtyb2xsb3ZlckZlZQgFDSR0MDc4NzIxNzg5NDUCXzQJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQEBcwEFDHJlbWFpbk1hcmdpbgkBAXMBBQ5mdW5kaW5nUGF5bWVudAkBAXMBCQEOZ2V0TWFyZ2luUmF0aW8BBQdfdHJhZGVyCQEBcwEFDXVucmVhbGl6ZWRQbmwJAQFzAQUHYmFkRGVidAkBAXMBBRBwb3NpdGlvbk5vdGlvbmFsCQEBcwEFC3JvbGxvdmVyRmVlCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBFXZpZXdfZ2V0UGVnQWRqdXN0Q29zdAEGX3ByaWNlBAdfcXRBc3RSCQEGcXRBc3RSAAQHX2JzQXN0UgkBBmJzQXN0UgAEBnJlc3VsdAkBFGdldFN5bmNUZXJtaW5hbFByaWNlAwUGX3ByaWNlBQdfcXRBc3RSBQdfYnNBc3RSCQACAQkApAMBCAUGcmVzdWx0Al8zAWkBGHZpZXdfZ2V0VGVybWluYWxBbW1QcmljZQAEDSR0MDc5NjY4Nzk3NDkJARNnZXRUZXJtaW5hbEFtbVN0YXRlAAQZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQgFDSR0MDc5NjY4Nzk3NDkCXzEEGHRlcm1pbmFsQmFzZUFzc2V0UmVzZXJ2ZQgFDSR0MDc5NjY4Nzk3NDkCXzIEBXByaWNlCQEEZGl2ZAIJAQRtdWxkAgUZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQkBBnF0QXN0VwAJAQRtdWxkAgUYdGVybWluYWxCYXNlQXNzZXRSZXNlcnZlCQEGYnNBc3RXAAkAAgEJAKQDAQUFcHJpY2UBaQEPdmlld19nZXRGdW5kaW5nAAQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBA91bmRlcmx5aW5nUHJpY2UJAQ5nZXRPcmFjbGVQcmljZQAEDSR0MDgwMzA4ODAzODYJAQpnZXRGdW5kaW5nAAQUc2hvcnRQcmVtaXVtRnJhY3Rpb24IBQ0kdDA4MDMwODgwMzg2Al8xBBNsb25nUHJlbWl1bUZyYWN0aW9uCAUNJHQwODAzMDg4MDM4NgJfMgQOcHJlbWl1bVRvVmF1bHQIBQ0kdDA4MDMwODgwMzg2Al8zBAtsb25nRnVuZGluZwkBBGRpdmQCBRNsb25nUHJlbWl1bUZyYWN0aW9uBQ91bmRlcmx5aW5nUHJpY2UEDHNob3J0RnVuZGluZwkBBGRpdmQCBRRzaG9ydFByZW1pdW1GcmFjdGlvbgUPdW5kZXJseWluZ1ByaWNlCQACAQkArAICCQCsAgIJAKwCAgkArAICCQEBcwEFC2xvbmdGdW5kaW5nCQEBcwEFDHNob3J0RnVuZGluZwkBAXMBCQEMZ2V0U3BvdFByaWNlAAkBAXMBCQEOZ2V0T3JhY2xlUHJpY2UACQEBcwEFDnByZW1pdW1Ub1ZhdWx0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBEGNvbXB1dGVTcG90UHJpY2UABARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEBnJlc3VsdAkBDGdldFNwb3RQcmljZQAJAJQKAgUDbmlsBQZyZXN1bHQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEfY29tcHV0ZUZlZUZvclRyYWRlcldpdGhBcnRpZmFjdAIHX3RyYWRlcgtfYXJ0aWZhY3RJZAQGcmVzdWx0CQEYZ2V0Rm9yVHJhZGVyV2l0aEFydGlmYWN0AgUHX3RyYWRlcgULX2FydGlmYWN0SWQJAJQKAgUDbmlsBQZyZXN1bHQBAnR4AQZ2ZXJpZnkABA5jb29yZGluYXRvclN0cgkAnQgCBQR0aGlzBRRrX2Nvb3JkaW5hdG9yQWRkcmVzcwMJAQlpc0RlZmluZWQBBQ5jb29yZGluYXRvclN0cgQFYWRtaW4JAJ0IAgkBEUBleHRyTmF0aXZlKDEwNjIpAQkBBXZhbHVlAQUOY29vcmRpbmF0b3JTdHIFD2tfYWRtaW5fYWRkcmVzcwMJAQlpc0RlZmluZWQBBQVhZG1pbgkBC3ZhbHVlT3JFbHNlAgkAmwgCCQERQGV4dHJOYXRpdmUoMTA2MikBCQEFdmFsdWUBBQVhZG1pbgkArAICCQCsAgIJAKwCAgIHc3RhdHVzXwkApQgBBQR0aGlzAgFfCQDYBAEIBQJ0eAJpZAcJAAIBAi51bmFibGUgdG8gdmVyaWZ5OiBhZG1pbiBub3Qgc2V0IGluIGNvb3JkaW5hdG9yCQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwAACAUCdHgPc2VuZGVyUHVibGljS2V5EdpIZQ==", "height": 3566985, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: H9f9qXoy3U1GPtwWNduVpJzu4Xt8LUBYtRtAs8hUx2nU Next: DAPVmYcwYrEgXXLKoYspS8ppZXy1UCZ3Bb7zCjVHqtS6 Diff:
OldNewDifferences
2626 let k_initialized = "k_initialized"
2727
2828 let k_paused = "k_paused"
29+
30+let k_delisted = "k_delisted"
2931
3032 let k_closeOnly = "k_closeOnly"
3133
385387 func paused () = valueOrElse(getBoolean(this, k_paused), false)
386388
387389
390+func delisted () = valueOrElse(getBoolean(this, k_delisted), false)
391+
392+
388393 func closeOnly () = valueOrElse(getBoolean(this, k_closeOnly), false)
389394
390395
425430 let amountBaseAssetBought = if (_isAdd)
426431 then amountBaseAssetBoughtAbs
427432 else -(amountBaseAssetBoughtAbs)
428- let $t01560115771 = updateReserve(_isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
429- let quoteAssetReserveAfter1 = $t01560115771._1
430- let baseAssetReserveAfter1 = $t01560115771._2
431- let totalPositionSizeAfter1 = $t01560115771._3
433+ let $t01577915949 = updateReserve(_isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
434+ let quoteAssetReserveAfter1 = $t01577915949._1
435+ let baseAssetReserveAfter1 = $t01577915949._2
436+ let totalPositionSizeAfter1 = $t01577915949._3
432437 let priceBefore = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
433438 let marketPrice = divd(_quoteAssetAmount, amountBaseAssetBoughtAbs)
434439 let priceDiff = abs((priceBefore - marketPrice))
456461 else 0
457462 let rolloverFee = calcRolloverFee(_oldPositionMargin, _oldPositionLastUpdatedTimestamp)
458463 let signedMargin = (((_marginDelta - rolloverFee) - fundingPayment) + _oldPositionMargin)
459- let $t01802618153 = if ((0 > signedMargin))
464+ let $t01820418331 = if ((0 > signedMargin))
460465 then $Tuple2(0, abs(signedMargin))
461466 else $Tuple2(abs(signedMargin), 0)
462- let remainMargin = $t01802618153._1
463- let badDebt = $t01802618153._2
467+ let remainMargin = $t01820418331._1
468+ let badDebt = $t01820418331._2
464469 $Tuple4(remainMargin, badDebt, fundingPayment, rolloverFee)
465470 }
466471
478483 let quoteAssetDelta = abs((quoteAssetAfter - _quoteAssetReserve))
479484 let quoteAssetSold = muld(quoteAssetDelta, _quoteAssetWeight)
480485 let maxPriceImpactValue = maxPriceImpact()
481- let $t01941519577 = updateReserve(!(_isAdd), quoteAssetDelta, _baseAssetAmount)
482- let quoteAssetReserveAfter1 = $t01941519577._1
483- let baseAssetReserveAfter1 = $t01941519577._2
484- let totalPositionSizeAfter1 = $t01941519577._3
486+ let $t01959319755 = updateReserve(!(_isAdd), quoteAssetDelta, _baseAssetAmount)
487+ let quoteAssetReserveAfter1 = $t01959319755._1
488+ let baseAssetReserveAfter1 = $t01959319755._2
489+ let totalPositionSizeAfter1 = $t01959319755._3
485490 let marketPrice = divd(quoteAssetSold, _baseAssetAmount)
486491 let priceDiff = abs((priceBefore - marketPrice))
487492 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
616621
617622
618623 func getPositionNotionalAndUnrealizedPnl (_trader,_option) = {
619- let $t02745527583 = getPosition(_trader)
620- let positionSize = $t02745527583._1
621- let positionMargin = $t02745527583._2
622- let positionOpenNotional = $t02745527583._3
623- let positionLstUpdCPF = $t02745527583._4
624+ let $t02763327761 = getPosition(_trader)
625+ let positionSize = $t02763327761._1
626+ let positionMargin = $t02763327761._2
627+ let positionOpenNotional = $t02763327761._3
628+ let positionLstUpdCPF = $t02763327761._4
624629 getPositionNotionalAndUnrealizedPnlByValues(positionSize, positionOpenNotional, qtAstR(), qtAstW(), bsAstR(), bsAstW(), _option)
625630 }
626631
629634
630635
631636 func getMarginRatioByOption (_trader,_option) = {
632- let $t02809828239 = getPosition(_trader)
633- let positionSize = $t02809828239._1
634- let positionMargin = $t02809828239._2
635- let pon = $t02809828239._3
636- let positionLastUpdatedCPF = $t02809828239._4
637- let positionTimestamp = $t02809828239._5
638- let $t02824528338 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
639- let positionNotional = $t02824528338._1
640- let unrealizedPnl = $t02824528338._2
641- let $t02834328555 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLastUpdatedCPF, positionTimestamp, unrealizedPnl)
642- let remainMargin = $t02834328555._1
643- let badDebt = $t02834328555._2
637+ let $t02827628417 = getPosition(_trader)
638+ let positionSize = $t02827628417._1
639+ let positionMargin = $t02827628417._2
640+ let pon = $t02827628417._3
641+ let positionLastUpdatedCPF = $t02827628417._4
642+ let positionTimestamp = $t02827628417._5
643+ let $t02842328516 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
644+ let positionNotional = $t02842328516._1
645+ let unrealizedPnl = $t02842328516._2
646+ let $t02852128733 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLastUpdatedCPF, positionTimestamp, unrealizedPnl)
647+ let remainMargin = $t02852128733._1
648+ let badDebt = $t02852128733._2
644649 calcMarginRatio(remainMargin, badDebt, positionNotional)
645650 }
646651
661666
662667
663668 func internalClosePosition (_trader,_size,_fee,_minQuoteAssetAmount,_addToMargin,_checkMaxPriceImpact,_liquidate) = {
664- let $t02962229778 = getPosition(_trader)
665- let oldPositionSize = $t02962229778._1
666- let oldPositionMargin = $t02962229778._2
667- let oldPositionOpenNotional = $t02962229778._3
668- let oldPositionLstUpdCPF = $t02962229778._4
669- let oldPositionTimestamp = $t02962229778._5
669+ let $t02980029956 = getPosition(_trader)
670+ let oldPositionSize = $t02980029956._1
671+ let oldPositionMargin = $t02980029956._2
672+ let oldPositionOpenNotional = $t02980029956._3
673+ let oldPositionLstUpdCPF = $t02980029956._4
674+ let oldPositionTimestamp = $t02980029956._5
670675 let isLongPosition = (oldPositionSize > 0)
671676 let absOldPositionSize = abs(oldPositionSize)
672677 if (if ((absOldPositionSize >= _size))
674679 else false)
675680 then {
676681 let isPartialClose = (absOldPositionSize > _size)
677- let $t03007030521 = swapOutput((oldPositionSize > 0), _size, _checkMaxPriceImpact)
678- let exchangedQuoteAssetAmount = $t03007030521._1
679- let quoteAssetReserveAfter = $t03007030521._2
680- let baseAssetReserveAfter = $t03007030521._3
681- let totalPositionSizeAfter = $t03007030521._4
682+ let $t03024830699 = swapOutput((oldPositionSize > 0), _size, _checkMaxPriceImpact)
683+ let exchangedQuoteAssetAmount = $t03024830699._1
684+ let quoteAssetReserveAfter = $t03024830699._2
685+ let baseAssetReserveAfter = $t03024830699._3
686+ let totalPositionSizeAfter = $t03024830699._4
682687 let exchangedPositionSize = if ((oldPositionSize > 0))
683688 then -(_size)
684689 else _size
685- let $t03073630943 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
686- let oldPositionNotional = $t03073630943._1
687- let unrealizedPnl = $t03073630943._2
690+ let $t03091431121 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
691+ let oldPositionNotional = $t03091431121._1
692+ let unrealizedPnl = $t03091431121._2
688693 let realizedRatio = divd(abs(exchangedPositionSize), absOldPositionSize)
689694 let realizedPnl = muld(unrealizedPnl, realizedRatio)
690- let $t03128431530 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, unrealizedPnl)
691- let remainMarginBefore = $t03128431530._1
692- let x1 = $t03128431530._2
693- let x2 = $t03128431530._3
694- let rolloverFee = $t03128431530._4
695+ let $t03146231708 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, unrealizedPnl)
696+ let remainMarginBefore = $t03146231708._1
697+ let x1 = $t03146231708._2
698+ let x2 = $t03146231708._3
699+ let rolloverFee = $t03146231708._4
695700 let positionBadDebt = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, realizedPnl)._2
696701 let realizedCloseFee = muld(muld(oldPositionNotional, realizedRatio), _fee)
697702 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
699704 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
700705 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
701706 let newPositionSize = (oldPositionSize + exchangedPositionSize)
702- let $t03293633322 = if ((newPositionSize == 0))
707+ let $t03311433500 = if ((newPositionSize == 0))
703708 then $Tuple2(0, 0)
704709 else $Tuple2(abs(remainOpenNotional), latestCumulativePremiumFraction(newPositionSize))
705- let newPositionOpenNotional = $t03293633322._1
706- let newPositionLstUpdCPF = $t03293633322._2
710+ let newPositionOpenNotional = $t03311433500._1
711+ let newPositionLstUpdCPF = $t03311433500._2
707712 let openNotionalDelta = (oldPositionOpenNotional - newPositionOpenNotional)
708713 let marginRatio = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
709714 let newPositionMarginWithSameRatio = if ((oldPositionSize > 0))
746751 then $Tuple2(qtAstR(), bsAstR())
747752 else {
748753 let direction = (_positionSize > 0)
749- let $t03655736736 = swapOutput(direction, abs(_positionSize), false)
750- let currentNetMarketValue = $t03655736736._1
751- let terminalQuoteAssetReserve = $t03655736736._2
752- let terminalBaseAssetReserve = $t03655736736._3
754+ let $t03673536914 = swapOutput(direction, abs(_positionSize), false)
755+ let currentNetMarketValue = $t03673536914._1
756+ let terminalQuoteAssetReserve = $t03673536914._2
757+ let terminalBaseAssetReserve = $t03673536914._3
753758 $Tuple2(terminalQuoteAssetReserve, terminalBaseAssetReserve)
754759 }
755760 }
832837 func getAdjustedFee (_artifactId,_baseFeeDiscount) = {
833838 let baseFeeRaw = fee()
834839 let baseFee = muld(baseFeeRaw, _baseFeeDiscount)
835- let $t04045440949 = if ((_artifactId != ""))
840+ let $t04063241127 = if ((_artifactId != ""))
836841 then {
837842 let artifactKind = strA(nftManagerAddress(), toCompositeKey(k_token_type, _artifactId))
838843 if ((artifactKind == FEE_REDUCTION_TOKEN_TYPE))
844849 else throw("Invalid attached artifact")
845850 }
846851 else $Tuple2(baseFee, false)
847- let adjustedFee = $t04045440949._1
848- let burnArtifact = $t04045440949._2
852+ let adjustedFee = $t04063241127._1
853+ let burnArtifact = $t04063241127._2
849854 $Tuple2(adjustedFee, burnArtifact)
850855 }
851856
860865 case _ =>
861866 throw("Invalid computeFeeDiscount result")
862867 }
863- let $t04129541369 = getAdjustedFee(_artifactId, feeDiscount)
864- let adjustedFee = $t04129541369._1
865- let burnArtifact = $t04129541369._2
868+ let $t04147341547 = getAdjustedFee(_artifactId, feeDiscount)
869+ let adjustedFee = $t04147341547._1
870+ let burnArtifact = $t04147341547._2
866871 $Tuple2(adjustedFee, burnArtifact)
867872 }
868873 else throw("Strict value is not equal to itself.")
953958
954959
955960 @Callable(i)
961+func delist () = if ((i.caller != adminAddress()))
962+ then throw("Invalid delist params")
963+ else [BooleanEntry(k_delisted, true)]
964+
965+
966+
967+@Callable(i)
956968 func unpause () = if ((i.caller != adminAddress()))
957969 then throw("Invalid unpause params")
958970 else [BooleanEntry(k_paused, false)]
987999 let qtAstRAfter = (_qtAstR + _quoteAssetAmount)
9881000 let baseAssetAmountToAdd = (divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR)
9891001 let bsAstRAfter = (_bsAstR + baseAssetAmountToAdd)
990- let $t04926349414 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
991- let newQuoteAssetWeight = $t04926349414._1
992- let newBaseAssetWeight = $t04926349414._2
993- let marginToVault = $t04926349414._3
1002+ let $t04961549766 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1003+ let newQuoteAssetWeight = $t04961549766._1
1004+ let newBaseAssetWeight = $t04961549766._2
1005+ let marginToVault = $t04961549766._3
9941006 let doExchangePnL = if ((marginToVault != 0))
9951007 then {
9961008 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
10201032 let qtAstRAfter = (_qtAstR - _quoteAssetAmount)
10211033 let baseAssetAmountToRemove = abs((divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR))
10221034 let bsAstRAfter = (_bsAstR - baseAssetAmountToRemove)
1023- let $t05051050661 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1024- let newQuoteAssetWeight = $t05051050661._1
1025- let newBaseAssetWeight = $t05051050661._2
1026- let marginToVault = $t05051050661._3
1035+ let $t05086251013 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1036+ let newQuoteAssetWeight = $t05086251013._1
1037+ let newBaseAssetWeight = $t05086251013._2
1038+ let marginToVault = $t05086251013._3
10271039 let doExchangePnL = if ((marginToVault != 0))
10281040 then {
10291041 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
11571169 else isMarketClosed())
11581170 then throw("Invalid increasePosition parameters")
11591171 else {
1160- let $t05673156880 = getForTraderWithArtifact(_trader, getArtifactId(i))
1161- let adjustedFee = $t05673156880._1
1162- let burnArtifact = $t05673156880._2
1172+ let $t05708357232 = getForTraderWithArtifact(_trader, getArtifactId(i))
1173+ let adjustedFee = $t05708357232._1
1174+ let burnArtifact = $t05708357232._2
11631175 let _amount = divd(_rawAmount, (muld(adjustedFee, _leverage) + DECIMAL_UNIT))
11641176 let distributeFeeAmount = (_rawAmount - _amount)
11651177 let referrerFeeAny = invoke(referralAddress(), "acceptPaymentWithLink", [_trader, _refLink], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
11721184 throw("Invalid referrerFee")
11731185 }
11741186 let feeAmount = (distributeFeeAmount - referrerFee)
1175- let $t05737657544 = getPosition(_trader)
1176- let oldPositionSize = $t05737657544._1
1177- let oldPositionMargin = $t05737657544._2
1178- let oldPositionOpenNotional = $t05737657544._3
1179- let oldPositionLstUpdCPF = $t05737657544._4
1180- let oldPositionTimestamp = $t05737657544._5
1187+ let $t05772857896 = getPosition(_trader)
1188+ let oldPositionSize = $t05772857896._1
1189+ let oldPositionMargin = $t05772857896._2
1190+ let oldPositionOpenNotional = $t05772857896._3
1191+ let oldPositionLstUpdCPF = $t05772857896._4
1192+ let oldPositionTimestamp = $t05772857896._5
11811193 let isNewPosition = (oldPositionSize == 0)
11821194 let isSameDirection = if ((oldPositionSize > 0))
11831195 then (_direction == DIR_LONG)
11861198 then isSameDirection
11871199 else false
11881200 let isAdd = (_direction == DIR_LONG)
1189- let $t05783360954 = if (if (isNewPosition)
1201+ let $t05818561306 = if (if (isNewPosition)
11901202 then true
11911203 else expandExisting)
11921204 then {
11931205 let openNotional = muld(_amount, _leverage)
1194- let $t05834258515 = swapInput(isAdd, openNotional)
1195- let amountBaseAssetBought = $t05834258515._1
1196- let quoteAssetReserveAfter = $t05834258515._2
1197- let baseAssetReserveAfter = $t05834258515._3
1198- let totalPositionSizeAfter = $t05834258515._4
1206+ let $t05869458867 = swapInput(isAdd, openNotional)
1207+ let amountBaseAssetBought = $t05869458867._1
1208+ let quoteAssetReserveAfter = $t05869458867._2
1209+ let baseAssetReserveAfter = $t05869458867._3
1210+ let totalPositionSizeAfter = $t05869458867._4
11991211 if (if ((_minBaseAssetAmount != 0))
12001212 then (_minBaseAssetAmount > abs(amountBaseAssetBought))
12011213 else false)
12081220 let totalShortOpenInterestAfter = (openInterestShort() + (if ((0 > newPositionSize))
12091221 then openNotional
12101222 else 0))
1211- let $t05906159336 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, _amount)
1212- let remainMargin = $t05906159336._1
1213- let x1 = $t05906159336._2
1214- let x2 = $t05906159336._3
1215- let rolloverFee = $t05906159336._4
1223+ let $t05941359688 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, _amount)
1224+ let remainMargin = $t05941359688._1
1225+ let x1 = $t05941359688._2
1226+ let x2 = $t05941359688._3
1227+ let rolloverFee = $t05941359688._4
12161228 if (!(requireNotOverSpreadLimit(quoteAssetReserveAfter, baseAssetReserveAfter)))
12171229 then throw("Over max spread limit")
12181230 else if (!(requireNotOverMaxOpenNotional(totalLongOpenInterestAfter, totalShortOpenInterestAfter)))
12261238 }
12271239 else {
12281240 let openNotional = muld(_amount, _leverage)
1229- let $t06065460770 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1230- let oldPositionNotional = $t06065460770._1
1231- let unrealizedPnl = $t06065460770._2
1241+ let $t06100661122 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1242+ let oldPositionNotional = $t06100661122._1
1243+ let unrealizedPnl = $t06100661122._2
12321244 if ((oldPositionNotional > openNotional))
12331245 then throw("Use decreasePosition to decrease position size")
12341246 else throw("Close position first")
12351247 }
1236- let newPositionSize = $t05783360954._1
1237- let newPositionRemainMargin = $t05783360954._2
1238- let newPositionOpenNotional = $t05783360954._3
1239- let newPositionLatestCPF = $t05783360954._4
1240- let newPositionTimestamp = $t05783360954._5
1241- let baseAssetReserveAfter = $t05783360954._6
1242- let quoteAssetReserveAfter = $t05783360954._7
1243- let totalPositionSizeAfter = $t05783360954._8
1244- let openInterestNotionalAfter = $t05783360954._9
1245- let totalLongAfter = $t05783360954._10
1246- let totalShortAfter = $t05783360954._11
1247- let totalLongOpenInterestAfter = $t05783360954._12
1248- let totalShortOpenInterestAfter = $t05783360954._13
1249- let rolloverFee = $t05783360954._14
1250- let $t06096061031 = distributeFee((feeAmount + rolloverFee))
1251- let feeToStakers = $t06096061031._1
1252- let feeToVault = $t06096061031._2
1248+ let newPositionSize = $t05818561306._1
1249+ let newPositionRemainMargin = $t05818561306._2
1250+ let newPositionOpenNotional = $t05818561306._3
1251+ let newPositionLatestCPF = $t05818561306._4
1252+ let newPositionTimestamp = $t05818561306._5
1253+ let baseAssetReserveAfter = $t05818561306._6
1254+ let quoteAssetReserveAfter = $t05818561306._7
1255+ let totalPositionSizeAfter = $t05818561306._8
1256+ let openInterestNotionalAfter = $t05818561306._9
1257+ let totalLongAfter = $t05818561306._10
1258+ let totalShortAfter = $t05818561306._11
1259+ let totalLongOpenInterestAfter = $t05818561306._12
1260+ let totalShortOpenInterestAfter = $t05818561306._13
1261+ let rolloverFee = $t05818561306._14
1262+ let $t06131261383 = distributeFee((feeAmount + rolloverFee))
1263+ let feeToStakers = $t06131261383._1
1264+ let feeToVault = $t06131261383._2
12531265 let stake = if ((_amount >= rolloverFee))
12541266 then invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), (_amount - rolloverFee))])
12551267 else invoke(vaultAddress(), "withdrawLocked", [(rolloverFee - _amount)], nil)
13081320 else isMarketClosed())
13091321 then throw("Invalid addMargin parameters")
13101322 else {
1311- let $t06324663414 = getPosition(_trader)
1312- let oldPositionSize = $t06324663414._1
1313- let oldPositionMargin = $t06324663414._2
1314- let oldPositionOpenNotional = $t06324663414._3
1315- let oldPositionLstUpdCPF = $t06324663414._4
1316- let oldPositionTimestamp = $t06324663414._5
1323+ let $t06359863766 = getPosition(_trader)
1324+ let oldPositionSize = $t06359863766._1
1325+ let oldPositionMargin = $t06359863766._2
1326+ let oldPositionOpenNotional = $t06359863766._3
1327+ let oldPositionLstUpdCPF = $t06359863766._4
1328+ let oldPositionTimestamp = $t06359863766._5
13171329 let stake = invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), _amount)])
13181330 if ((stake == stake))
13191331 then {
13201332 let rolloverFee = calcRolloverFee(oldPositionMargin, oldPositionTimestamp)
13211333 let doTransferFeeToStakers = if ((rolloverFee > 0))
13221334 then {
1323- let $t06369963758 = distributeFee(rolloverFee)
1324- let feeToStakers = $t06369963758._1
1325- let feeToVault = $t06369963758._2
1335+ let $t06405164110 = distributeFee(rolloverFee)
1336+ let feeToStakers = $t06405164110._1
1337+ let feeToVault = $t06405164110._2
13261338 let unstake = invoke(vaultAddress(), "withdrawLocked", [feeToStakers], nil)
13271339 if ((unstake == unstake))
13281340 then {
13681380 else isMarketClosed())
13691381 then throw("Invalid removeMargin parameters")
13701382 else {
1371- let $t06513165299 = getPosition(_trader)
1372- let oldPositionSize = $t06513165299._1
1373- let oldPositionMargin = $t06513165299._2
1374- let oldPositionOpenNotional = $t06513165299._3
1375- let oldPositionLstUpdCPF = $t06513165299._4
1376- let oldPositionTimestamp = $t06513165299._5
1377- let $t06530565554 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, -(_amount))
1378- let remainMargin = $t06530565554._1
1379- let badDebt = $t06530565554._2
1380- let fundingPayment = $t06530565554._3
1381- let rolloverFee = $t06530565554._4
1383+ let $t06548365651 = getPosition(_trader)
1384+ let oldPositionSize = $t06548365651._1
1385+ let oldPositionMargin = $t06548365651._2
1386+ let oldPositionOpenNotional = $t06548365651._3
1387+ let oldPositionLstUpdCPF = $t06548365651._4
1388+ let oldPositionTimestamp = $t06548365651._5
1389+ let $t06565765906 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, -(_amount))
1390+ let remainMargin = $t06565765906._1
1391+ let badDebt = $t06565765906._2
1392+ let fundingPayment = $t06565765906._3
1393+ let rolloverFee = $t06565765906._4
13821394 if ((badDebt != 0))
13831395 then throw("Invalid removed margin amount")
13841396 else {
13861398 if (!(requireMoreMarginRatio(marginRatio, initMarginRatio(), true)))
13871399 then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
13881400 else {
1389- let $t06594065999 = distributeFee(rolloverFee)
1390- let feeToStakers = $t06594065999._1
1391- let feeToVault = $t06594065999._2
1401+ let $t06629266351 = distributeFee(rolloverFee)
1402+ let feeToStakers = $t06629266351._1
1403+ let feeToVault = $t06629266351._2
13921404 let doTransferFeeToStakers = if ((rolloverFee > 0))
13931405 then {
13941406 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(feeToVault)], nil)
14411453 then throw("Invalid closePosition parameters")
14421454 else {
14431455 let oldPositionTimestamp = getPosition(_trader)._5
1444- let $t06817468759 = internalClosePosition(_trader, _size, positionFee, _minQuoteAssetAmount, _addToMargin, true, true)
1445- let newPositionSize = $t06817468759._1
1446- let newPositionMargin = $t06817468759._2
1447- let newPositionOpenNotional = $t06817468759._3
1448- let newPositionLstUpdCPF = $t06817468759._4
1449- let positionBadDebt = $t06817468759._5
1450- let realizedPnl = $t06817468759._6
1451- let marginToTrader = $t06817468759._7
1452- let quoteAssetReserveAfter = $t06817468759._8
1453- let baseAssetReserveAfter = $t06817468759._9
1454- let totalPositionSizeAfter = $t06817468759._10
1455- let openInterestNotionalAfter = $t06817468759._11
1456- let totalLongAfter = $t06817468759._12
1457- let totalShortAfter = $t06817468759._13
1458- let totalLongOpenInterestAfter = $t06817468759._14
1459- let totalShortOpenInterestAfter = $t06817468759._15
1460- let realizedFee = $t06817468759._16
1456+ let $t06852669111 = internalClosePosition(_trader, _size, positionFee, _minQuoteAssetAmount, _addToMargin, true, true)
1457+ let newPositionSize = $t06852669111._1
1458+ let newPositionMargin = $t06852669111._2
1459+ let newPositionOpenNotional = $t06852669111._3
1460+ let newPositionLstUpdCPF = $t06852669111._4
1461+ let positionBadDebt = $t06852669111._5
1462+ let realizedPnl = $t06852669111._6
1463+ let marginToTrader = $t06852669111._7
1464+ let quoteAssetReserveAfter = $t06852669111._8
1465+ let baseAssetReserveAfter = $t06852669111._9
1466+ let totalPositionSizeAfter = $t06852669111._10
1467+ let openInterestNotionalAfter = $t06852669111._11
1468+ let totalLongAfter = $t06852669111._12
1469+ let totalShortAfter = $t06852669111._13
1470+ let totalLongOpenInterestAfter = $t06852669111._14
1471+ let totalShortOpenInterestAfter = $t06852669111._15
1472+ let realizedFee = $t06852669111._16
14611473 if ((positionBadDebt > 0))
14621474 then throw("Invalid closePosition parameters: bad debt")
14631475 else if ((oldPositionTimestamp >= lastTimestamp()))
14721484 let unstake = invoke(vaultAddress(), "withdrawLocked", [withdrawAmount], nil)
14731485 if ((unstake == unstake))
14741486 then {
1475- let $t06943169490 = distributeFee(realizedFee)
1476- let feeToStakers = $t06943169490._1
1477- let feeToVault = $t06943169490._2
1487+ let $t06978369842 = distributeFee(realizedFee)
1488+ let feeToStakers = $t06978369842._1
1489+ let feeToVault = $t06978369842._2
14781490 let depositVault = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
14791491 if ((depositVault == depositVault))
14801492 then {
15351547 else false
15361548 let oldPositionSize = getPosition(_trader)._1
15371549 let positionSizeAbs = abs(oldPositionSize)
1538- let $t07191172234 = if (isPartialLiquidation)
1550+ let $t07226372586 = if (isPartialLiquidation)
15391551 then {
15401552 let liquidationSize = getPartialLiquidationAmount(_trader, oldPositionSize)
15411553 let liquidationRatio = divd(abs(liquidationSize), positionSizeAbs)
15421554 $Tuple2(liquidationRatio, abs(liquidationSize))
15431555 }
15441556 else $Tuple2(0, positionSizeAbs)
1545- let liquidationRatio = $t07191172234._1
1546- let liquidationSize = $t07191172234._2
1547- let $t07224072878 = internalClosePosition(_trader, if (isPartialLiquidation)
1557+ let liquidationRatio = $t07226372586._1
1558+ let liquidationSize = $t07226372586._2
1559+ let $t07259273230 = internalClosePosition(_trader, if (isPartialLiquidation)
15481560 then liquidationSize
15491561 else positionSizeAbs, liquidationFeeRatio(), 0, true, false, true)
1550- let newPositionSize = $t07224072878._1
1551- let newPositionMargin = $t07224072878._2
1552- let newPositionOpenNotional = $t07224072878._3
1553- let newPositionLstUpdCPF = $t07224072878._4
1554- let positionBadDebt = $t07224072878._5
1555- let realizedPnl = $t07224072878._6
1556- let marginToTrader = $t07224072878._7
1557- let quoteAssetReserveAfter = $t07224072878._8
1558- let baseAssetReserveAfter = $t07224072878._9
1559- let totalPositionSizeAfter = $t07224072878._10
1560- let openInterestNotionalAfter = $t07224072878._11
1561- let totalLongAfter = $t07224072878._12
1562- let totalShortAfter = $t07224072878._13
1563- let totalLongOpenInterestAfter = $t07224072878._14
1564- let totalShortOpenInterestAfter = $t07224072878._15
1565- let liquidationPenalty = $t07224072878._16
1562+ let newPositionSize = $t07259273230._1
1563+ let newPositionMargin = $t07259273230._2
1564+ let newPositionOpenNotional = $t07259273230._3
1565+ let newPositionLstUpdCPF = $t07259273230._4
1566+ let positionBadDebt = $t07259273230._5
1567+ let realizedPnl = $t07259273230._6
1568+ let marginToTrader = $t07259273230._7
1569+ let quoteAssetReserveAfter = $t07259273230._8
1570+ let baseAssetReserveAfter = $t07259273230._9
1571+ let totalPositionSizeAfter = $t07259273230._10
1572+ let openInterestNotionalAfter = $t07259273230._11
1573+ let totalLongAfter = $t07259273230._12
1574+ let totalShortAfter = $t07259273230._13
1575+ let totalLongOpenInterestAfter = $t07259273230._14
1576+ let totalShortOpenInterestAfter = $t07259273230._15
1577+ let liquidationPenalty = $t07259273230._16
15661578 let feeToLiquidator = (liquidationPenalty / 2)
15671579 let feeToVault = (liquidationPenalty - feeToLiquidator)
15681580 let ammBalance = (cbalance() - liquidationPenalty)
16181630 then throw(((("Invalid funding block timestamp: " + toString(lastTimestamp())) + " < ") + toString(fundingBlockTimestamp)))
16191631 else {
16201632 let underlyingPrice = getOraclePrice()
1621- let $t07499175069 = getFunding()
1622- let shortPremiumFraction = $t07499175069._1
1623- let longPremiumFraction = $t07499175069._2
1624- let premiumToVault = $t07499175069._3
1633+ let $t07534375421 = getFunding()
1634+ let shortPremiumFraction = $t07534375421._1
1635+ let longPremiumFraction = $t07534375421._2
1636+ let premiumToVault = $t07534375421._3
16251637 let doPayFundingToVault = if ((premiumToVault > 0))
16261638 then {
16271639 let doPayFundingToVault = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(premiumToVault)], nil)
16411653
16421654
16431655 @Callable(i)
1644-func syncTerminalPriceToOracle () = {
1645- let _qtAstR = qtAstR()
1646- let _bsAstR = bsAstR()
1647- let $t07612076486 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1648- let newQuoteAssetWeight = $t07612076486._1
1649- let newBaseAssetWeight = $t07612076486._2
1650- let marginToVault = $t07612076486._3
1651- let marginToVaultAdj = if (if ((0 > marginToVault))
1652- then (abs(marginToVault) > cbalance())
1653- else false)
1654- then -(cbalance())
1655- else marginToVault
1656- let doExchangePnL = if ((marginToVaultAdj != 0))
1657- then {
1658- let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVaultAdj], nil)
1659- if ((doExchangePnL == doExchangePnL))
1660- then nil
1661- else throw("Strict value is not equal to itself.")
1662- }
1663- else nil
1664- if ((doExchangePnL == doExchangePnL))
1665- then (updateBalance((cbalance() + marginToVaultAdj)) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
1666- else throw("Strict value is not equal to itself.")
1667- }
1656+func syncTerminalPriceToOracle () = if (delisted())
1657+ then nil
1658+ else {
1659+ let _qtAstR = qtAstR()
1660+ let _bsAstR = bsAstR()
1661+ let $t07651176895 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1662+ let newQuoteAssetWeight = $t07651176895._1
1663+ let newBaseAssetWeight = $t07651176895._2
1664+ let marginToVault = $t07651176895._3
1665+ let marginToVaultAdj = if (if ((0 > marginToVault))
1666+ then (abs(marginToVault) > cbalance())
1667+ else false)
1668+ then -(cbalance())
1669+ else marginToVault
1670+ let doExchangePnL = if ((marginToVaultAdj != 0))
1671+ then {
1672+ let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVaultAdj], nil)
1673+ if ((doExchangePnL == doExchangePnL))
1674+ then nil
1675+ else throw("Strict value is not equal to itself.")
1676+ }
1677+ else nil
1678+ if ((doExchangePnL == doExchangePnL))
1679+ then (updateBalance((cbalance() + marginToVaultAdj)) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
1680+ else throw("Strict value is not equal to itself.")
1681+ }
16681682
16691683
16701684
16851699 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
16861700 if ((sync == sync))
16871701 then {
1688- let $t07803578159 = getPosition(_trader)
1689- let positionSize = $t07803578159._1
1690- let positionMargin = $t07803578159._2
1691- let pon = $t07803578159._3
1692- let positionLstUpdCPF = $t07803578159._4
1693- let positionTimestamp = $t07803578159._5
1694- let $t07816278263 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1695- let positionNotional = $t07816278263._1
1696- let unrealizedPnl = $t07816278263._2
1697- let $t07826678490 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLstUpdCPF, positionTimestamp, unrealizedPnl)
1698- let remainMargin = $t07826678490._1
1699- let badDebt = $t07826678490._2
1700- let fundingPayment = $t07826678490._3
1701- let rolloverFee = $t07826678490._4
1702+ let $t07849078614 = getPosition(_trader)
1703+ let positionSize = $t07849078614._1
1704+ let positionMargin = $t07849078614._2
1705+ let pon = $t07849078614._3
1706+ let positionLstUpdCPF = $t07849078614._4
1707+ let positionTimestamp = $t07849078614._5
1708+ let $t07861778718 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1709+ let positionNotional = $t07861778718._1
1710+ let unrealizedPnl = $t07861778718._2
1711+ let $t07872178945 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLstUpdCPF, positionTimestamp, unrealizedPnl)
1712+ let remainMargin = $t07872178945._1
1713+ let badDebt = $t07872178945._2
1714+ let fundingPayment = $t07872178945._3
1715+ let rolloverFee = $t07872178945._4
17021716 throw(((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)) + s(rolloverFee)))
17031717 }
17041718 else throw("Strict value is not equal to itself.")
17181732
17191733 @Callable(i)
17201734 func view_getTerminalAmmPrice () = {
1721- let $t07921379294 = getTerminalAmmState()
1722- let terminalQuoteAssetReserve = $t07921379294._1
1723- let terminalBaseAssetReserve = $t07921379294._2
1735+ let $t07966879749 = getTerminalAmmState()
1736+ let terminalQuoteAssetReserve = $t07966879749._1
1737+ let terminalBaseAssetReserve = $t07966879749._2
17241738 let price = divd(muld(terminalQuoteAssetReserve, qtAstW()), muld(terminalBaseAssetReserve, bsAstW()))
17251739 throw(toString(price))
17261740 }
17331747 if ((sync == sync))
17341748 then {
17351749 let underlyingPrice = getOraclePrice()
1736- let $t07985379931 = getFunding()
1737- let shortPremiumFraction = $t07985379931._1
1738- let longPremiumFraction = $t07985379931._2
1739- let premiumToVault = $t07985379931._3
1750+ let $t08030880386 = getFunding()
1751+ let shortPremiumFraction = $t08030880386._1
1752+ let longPremiumFraction = $t08030880386._2
1753+ let premiumToVault = $t08030880386._3
17401754 let longFunding = divd(longPremiumFraction, underlyingPrice)
17411755 let shortFunding = divd(shortPremiumFraction, underlyingPrice)
17421756 throw(((((s(longFunding) + s(shortFunding)) + s(getSpotPrice())) + s(getOraclePrice())) + s(premiumToVault)))
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let k_baseOracle = "k_baseOracle"
55
66 let k_quoteOracle = "k_quoteOracle"
77
88 let k_balance = "k_balance"
99
1010 let k_sequence = "k_sequence"
1111
1212 let k_positionSize = "k_positionSize"
1313
1414 let k_positionMargin = "k_positionMargin"
1515
1616 let k_positionOpenNotional = "k_positionOpenNotional"
1717
1818 let k_positionLastUpdatedCumulativePremiumFraction = "k_positionFraction"
1919
2020 let k_positionSequence = "k_positionSequence"
2121
2222 let k_positionFee = "k_positionFee"
2323
2424 let k_positionLastUpdatedTimestamp = "k_positionTimestamp"
2525
2626 let k_initialized = "k_initialized"
2727
2828 let k_paused = "k_paused"
29+
30+let k_delisted = "k_delisted"
2931
3032 let k_closeOnly = "k_closeOnly"
3133
3234 let k_fee = "k_fee"
3335
3436 let k_rolloverFee = "k_rollover_fee"
3537
3638 let k_fundingPeriod = "k_fundingPeriod"
3739
3840 let k_initMarginRatio = "k_initMarginRatio"
3941
4042 let k_maintenanceMarginRatio = "k_mmr"
4143
4244 let k_liquidationFeeRatio = "k_liquidationFeeRatio"
4345
4446 let k_partialLiquidationRatio = "k_partLiquidationRatio"
4547
4648 let k_spreadLimit = "k_spreadLimit"
4749
4850 let k_maxPriceImpact = "k_maxPriceImpact"
4951
5052 let k_maxPriceSpread = "k_maxPriceSpread"
5153
5254 let k_maxOpenNotional = "k_maxOpenNotional"
5355
5456 let k_feeToStakersPercent = "k_feeToStakersPercent"
5557
5658 let k_maxOracleDelay = "k_maxOracleDelay"
5759
5860 let k_fundingMode = "k_fundingMode"
5961
6062 let k_latestLongCumulativePremiumFraction = "k_latestLongPremiumFraction"
6163
6264 let k_latestShortCumulativePremiumFraction = "k_latestShortPremiumFraction"
6365
6466 let k_nextFundingBlock = "k_nextFundingBlockMinTimestamp"
6567
6668 let k_longFundingRate = "k_longFundingRate"
6769
6870 let k_shortFundingRate = "k_shortFundingRate"
6971
7072 let k_quoteAssetReserve = "k_qtAstR"
7173
7274 let k_baseAssetReserve = "k_bsAstR"
7375
7476 let k_quoteAssetWeight = "k_qtAstW"
7577
7678 let k_baseAssetWeight = "k_bsAstW"
7779
7880 let k_totalPositionSize = "k_totalPositionSize"
7981
8082 let k_totalLongPositionSize = "k_totalLongPositionSize"
8183
8284 let k_totalShortPositionSize = "k_totalShortPositionSize"
8385
8486 let k_openInterestNotional = "k_openInterestNotional"
8587
8688 let k_openInterestShort = "k_openInterestShort"
8789
8890 let k_openInterestLong = "k_openInterestLong"
8991
9092 let k_lastTx = "k_lastTx"
9193
9294 let k_coordinatorAddress = "k_coordinatorAddress"
9395
9496 let k_vault_address = "k_vault_address"
9597
9698 let k_admin_address = "k_admin_address"
9799
98100 let k_quote_asset = "k_quote_asset"
99101
100102 let k_quote_staking = "k_quote_staking"
101103
102104 let k_staking_address = "k_staking_address"
103105
104106 let k_miner_address = "k_miner_address"
105107
106108 let k_orders_address = "k_orders_address"
107109
108110 let k_referral_address = "k_referral_address"
109111
110112 let k_exchange_address = "k_exchange_address"
111113
112114 let k_nft_manager_address = "k_nft_manager_address"
113115
114116 func toCompositeKey (_key,_address) = ((_key + "_") + _address)
115117
116118
117119 func coordinator () = valueOrErrorMessage(addressFromString(getStringValue(this, k_coordinatorAddress)), "Coordinator not set")
118120
119121
120122 func adminAddress () = addressFromString(getStringValue(coordinator(), k_admin_address))
121123
122124
123125 func quoteAsset () = fromBase58String(getStringValue(coordinator(), k_quote_asset))
124126
125127
126128 func quoteAssetStaking () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_quote_staking)), "Quote asset staking not set")
127129
128130
129131 func stakingAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_staking_address)), "Staking not set")
130132
131133
132134 func vaultAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_vault_address)), "Vault not set")
133135
134136
135137 func minerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_miner_address)), "Miner not set")
136138
137139
138140 func ordersAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_orders_address)), "Orders not set")
139141
140142
141143 func referralAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_referral_address)), "Referral not set")
142144
143145
144146 func nftManagerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_nft_manager_address)), "NFT Manager not set")
145147
146148
147149 let k_token_param = "k_token_param"
148150
149151 let k_token_type = "k_token_type"
150152
151153 let FEE_REDUCTION_TOKEN_TYPE = "fee_reduction"
152154
153155 let DIR_LONG = 1
154156
155157 let DIR_SHORT = 2
156158
157159 let SECONDS = 1000
158160
159161 let DECIMAL_NUMBERS = 6
160162
161163 let DECIMAL_UNIT = (1 * (((((10 * 10) * 10) * 10) * 10) * 10))
162164
163165 let MINUTES_IN_YEAR = (525600 * DECIMAL_UNIT)
164166
165167 let ONE_DAY = (86400 * DECIMAL_UNIT)
166168
167169 let PNL_OPTION_SPOT = 1
168170
169171 let PNL_OPTION_ORACLE = 2
170172
171173 let FUNDING_ASYMMETRIC = 1
172174
173175 let FUNDING_SYMMETRIC = 2
174176
175177 func s (_x) = (toString(_x) + ",")
176178
177179
178180 func divd (_x,_y) = fraction(_x, DECIMAL_UNIT, _y, HALFEVEN)
179181
180182
181183 func muld (_x,_y) = fraction(_x, _y, DECIMAL_UNIT, HALFEVEN)
182184
183185
184186 func bdivd (_x,_y) = fraction(_x, toBigInt(DECIMAL_UNIT), _y, HALFEVEN)
185187
186188
187189 func bmuld (_x,_y) = fraction(_x, _y, toBigInt(DECIMAL_UNIT), HALFEVEN)
188190
189191
190192 func abs (_x) = if ((_x > 0))
191193 then _x
192194 else -(_x)
193195
194196
195197 func vmax (_x,_y) = if ((_x >= _y))
196198 then _x
197199 else _y
198200
199201
200202 func int (k) = valueOrErrorMessage(getInteger(this, k), ("no value for " + k))
201203
202204
203205 func intOr (k,def) = valueOrElse(getInteger(this, k), def)
204206
205207
206208 func strA (_address,_key) = {
207209 let val = valueOrErrorMessage(getString(_address, _key), ("No value for key " + _key))
208210 val
209211 }
210212
211213
212214 func intA (_address,_key) = {
213215 let val = valueOrErrorMessage(getInteger(_address, _key), ("No value for key " + _key))
214216 val
215217 }
216218
217219
218220 func cbalance () = int(k_balance)
219221
220222
221223 func fee () = int(k_fee)
222224
223225
224226 func rolloverFeeRate () = int(k_rolloverFee)
225227
226228
227229 func initMarginRatio () = int(k_initMarginRatio)
228230
229231
230232 func qtAstR () = int(k_quoteAssetReserve)
231233
232234
233235 func bsAstR () = int(k_baseAssetReserve)
234236
235237
236238 func qtAstW () = intOr(k_quoteAssetWeight, DECIMAL_UNIT)
237239
238240
239241 func bsAstW () = intOr(k_baseAssetWeight, DECIMAL_UNIT)
240242
241243
242244 func totalPositionSize () = int(k_totalPositionSize)
243245
244246
245247 func openInterestNotional () = int(k_openInterestNotional)
246248
247249
248250 func openInterestShort () = int(k_openInterestShort)
249251
250252
251253 func openInterestLong () = int(k_openInterestLong)
252254
253255
254256 func nextFundingBlockTimestamp () = int(k_nextFundingBlock)
255257
256258
257259 func fundingPeriodRaw () = int(k_fundingPeriod)
258260
259261
260262 func fundingPeriodDecimal () = (fundingPeriodRaw() * DECIMAL_UNIT)
261263
262264
263265 func fundingPeriodSeconds () = (fundingPeriodRaw() * SECONDS)
264266
265267
266268 func maintenanceMarginRatio () = int(k_maintenanceMarginRatio)
267269
268270
269271 func liquidationFeeRatio () = int(k_liquidationFeeRatio)
270272
271273
272274 func partialLiquidationRatio () = int(k_partialLiquidationRatio)
273275
274276
275277 func spreadLimit () = int(k_spreadLimit)
276278
277279
278280 func maxPriceImpact () = int(k_maxPriceImpact)
279281
280282
281283 func maxPriceSpread () = int(k_maxPriceSpread)
282284
283285
284286 func maxOpenNotional () = int(k_maxOpenNotional)
285287
286288
287289 func latestLongCumulativePremiumFraction () = int(k_latestLongCumulativePremiumFraction)
288290
289291
290292 func latestShortCumulativePremiumFraction () = int(k_latestShortCumulativePremiumFraction)
291293
292294
293295 func totalShortPositionSize () = int(k_totalShortPositionSize)
294296
295297
296298 func totalLongPositionSize () = int(k_totalLongPositionSize)
297299
298300
299301 func lastSequence () = intOr(k_sequence, 0)
300302
301303
302304 func feeToStakersPercent () = int(k_feeToStakersPercent)
303305
304306
305307 func maxOracleDelay () = int(k_maxOracleDelay)
306308
307309
308310 func fundingMode () = intOr(k_fundingMode, FUNDING_ASYMMETRIC)
309311
310312
311313 func lastTimestamp () = lastBlock.timestamp
312314
313315
314316 func getActualCaller (i) = valueOrElse(getString(ordersAddress(), "k_sender"), toString(i.caller))
315317
316318
317319 func requireMoreMarginRatio (_marginRatio,_baseMarginRatio,_largerThanOrEqualTo) = {
318320 let remainingMarginRatio = (_marginRatio - _baseMarginRatio)
319321 if (if (_largerThanOrEqualTo)
320322 then (0 > remainingMarginRatio)
321323 else false)
322324 then throw(((("Invalid margin: " + toString(_marginRatio)) + " < ") + toString(_baseMarginRatio)))
323325 else if (if (!(_largerThanOrEqualTo))
324326 then (remainingMarginRatio >= 0)
325327 else false)
326328 then throw(((("Invalid margin: " + toString(_marginRatio)) + " > ") + toString(_baseMarginRatio)))
327329 else true
328330 }
329331
330332
331333 func latestCumulativePremiumFraction (_positionSize) = if ((_positionSize == 0))
332334 then throw("Should not be called with _positionSize == 0")
333335 else if ((_positionSize > 0))
334336 then latestLongCumulativePremiumFraction()
335337 else latestShortCumulativePremiumFraction()
336338
337339
338340 func getPosition (_trader) = {
339341 let positionSizeOpt = getInteger(this, toCompositeKey(k_positionSize, _trader))
340342 match positionSizeOpt {
341343 case positionSize: Int =>
342344 $Tuple5(positionSize, getIntegerValue(this, toCompositeKey(k_positionMargin, _trader)), getIntegerValue(this, toCompositeKey(k_positionOpenNotional, _trader)), getIntegerValue(this, toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, _trader)), getIntegerValue(this, toCompositeKey(k_positionLastUpdatedTimestamp, _trader)))
343345 case _ =>
344346 $Tuple5(0, 0, 0, 0, 0)
345347 }
346348 }
347349
348350
349351 func getPositionFee (_trader) = {
350352 let positionFeeOpt = getInteger(this, toCompositeKey(k_positionFee, _trader))
351353 match positionFeeOpt {
352354 case positionFee: Int =>
353355 positionFee
354356 case _ =>
355357 fee()
356358 }
357359 }
358360
359361
360362 func requireOpenPosition (_trader) = if ((getPosition(_trader)._1 == 0))
361363 then throw("No open position")
362364 else true
363365
364366
365367 func getOracleData (key) = {
366368 let oracleDataStr = getString(this, key)
367369 if (if (isDefined(oracleDataStr))
368370 then (value(oracleDataStr) != "")
369371 else false)
370372 then {
371373 let oracleData = split(value(oracleDataStr), ",")
372374 let oracleAddress = valueOrErrorMessage(addressFromString(oracleData[0]), ("Invalid oracle address in: " + value(oracleDataStr)))
373375 let priceKey = oracleData[1]
374376 let blockKey = oracleData[2]
375377 let openKey = oracleData[3]
376378 $Tuple4(oracleAddress, priceKey, blockKey, openKey)
377379 }
378380 else unit
379381 }
380382
381383
382384 func initialized () = valueOrElse(getBoolean(this, k_initialized), false)
383385
384386
385387 func paused () = valueOrElse(getBoolean(this, k_paused), false)
386388
387389
390+func delisted () = valueOrElse(getBoolean(this, k_delisted), false)
391+
392+
388393 func closeOnly () = valueOrElse(getBoolean(this, k_closeOnly), false)
389394
390395
391396 func updateReserve (_isAdd,_quoteAssetAmount,_baseAssetAmount) = if (_isAdd)
392397 then {
393398 let newBase = (bsAstR() - _baseAssetAmount)
394399 if ((0 >= newBase))
395400 then throw("Tx lead to base asset reserve <= 0, revert")
396401 else $Tuple3((qtAstR() + _quoteAssetAmount), newBase, (totalPositionSize() + _baseAssetAmount))
397402 }
398403 else {
399404 let newQuote = (qtAstR() - _quoteAssetAmount)
400405 if ((0 >= newQuote))
401406 then throw("Tx lead to base quote reserve <= 0, revert")
402407 else $Tuple3(newQuote, (bsAstR() + _baseAssetAmount), (totalPositionSize() - _baseAssetAmount))
403408 }
404409
405410
406411 func calcInvariant (_qtAstR,_bsAstR) = {
407412 let bqtAstR = toBigInt(_qtAstR)
408413 let bbsAstR = toBigInt(_bsAstR)
409414 bmuld(bqtAstR, bbsAstR)
410415 }
411416
412417
413418 func swapInput (_isAdd,_quoteAssetAmount) = {
414419 let _qtAstR = qtAstR()
415420 let _bsAstR = bsAstR()
416421 let _qtAstW = qtAstW()
417422 let _bsAstW = bsAstW()
418423 let quoteAssetAmountAdjusted = divd(_quoteAssetAmount, _qtAstW)
419424 let k = calcInvariant(_qtAstR, _bsAstR)
420425 let quoteAssetReserveAfter = if (_isAdd)
421426 then (_qtAstR + quoteAssetAmountAdjusted)
422427 else (_qtAstR - quoteAssetAmountAdjusted)
423428 let baseAssetReserveAfter = toInt(bdivd(k, toBigInt(quoteAssetReserveAfter)))
424429 let amountBaseAssetBoughtAbs = abs((baseAssetReserveAfter - _bsAstR))
425430 let amountBaseAssetBought = if (_isAdd)
426431 then amountBaseAssetBoughtAbs
427432 else -(amountBaseAssetBoughtAbs)
428- let $t01560115771 = updateReserve(_isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
429- let quoteAssetReserveAfter1 = $t01560115771._1
430- let baseAssetReserveAfter1 = $t01560115771._2
431- let totalPositionSizeAfter1 = $t01560115771._3
433+ let $t01577915949 = updateReserve(_isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
434+ let quoteAssetReserveAfter1 = $t01577915949._1
435+ let baseAssetReserveAfter1 = $t01577915949._2
436+ let totalPositionSizeAfter1 = $t01577915949._3
432437 let priceBefore = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
433438 let marketPrice = divd(_quoteAssetAmount, amountBaseAssetBoughtAbs)
434439 let priceDiff = abs((priceBefore - marketPrice))
435440 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
436441 let maxPriceImpactValue = maxPriceImpact()
437442 if ((priceImpact > maxPriceImpactValue))
438443 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)))
439444 else $Tuple4(amountBaseAssetBought, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1)
440445 }
441446
442447
443448 func calcRolloverFee (_oldPositionMargin,_oldPositionLastUpdatedTimestamp) = {
444449 let positionMinutes = ((((lastTimestamp() - _oldPositionLastUpdatedTimestamp) / 1000) / 60) * DECIMAL_UNIT)
445450 let rolloverFee = divd(muld(muld(_oldPositionMargin, positionMinutes), rolloverFeeRate()), MINUTES_IN_YEAR)
446451 rolloverFee
447452 }
448453
449454
450455 func calcRemainMarginWithFundingPaymentAndRolloverFee (_oldPositionSize,_oldPositionMargin,_oldPositionCumulativePremiumFraction,_oldPositionLastUpdatedTimestamp,_marginDelta) = {
451456 let fundingPayment = if ((_oldPositionSize != 0))
452457 then {
453458 let _latestCumulativePremiumFraction = latestCumulativePremiumFraction(_oldPositionSize)
454459 muld((_latestCumulativePremiumFraction - _oldPositionCumulativePremiumFraction), _oldPositionSize)
455460 }
456461 else 0
457462 let rolloverFee = calcRolloverFee(_oldPositionMargin, _oldPositionLastUpdatedTimestamp)
458463 let signedMargin = (((_marginDelta - rolloverFee) - fundingPayment) + _oldPositionMargin)
459- let $t01802618153 = if ((0 > signedMargin))
464+ let $t01820418331 = if ((0 > signedMargin))
460465 then $Tuple2(0, abs(signedMargin))
461466 else $Tuple2(abs(signedMargin), 0)
462- let remainMargin = $t01802618153._1
463- let badDebt = $t01802618153._2
467+ let remainMargin = $t01820418331._1
468+ let badDebt = $t01820418331._2
464469 $Tuple4(remainMargin, badDebt, fundingPayment, rolloverFee)
465470 }
466471
467472
468473 func swapOutputWithReserves (_isAdd,_baseAssetAmount,_checkMaxPriceImpact,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
469474 let priceBefore = divd(muld(_quoteAssetReserve, _quoteAssetWeight), muld(_baseAssetReserve, _baseAssetWeight))
470475 if ((_baseAssetAmount == 0))
471476 then throw("Invalid base asset amount")
472477 else {
473478 let k = calcInvariant(_quoteAssetReserve, _baseAssetReserve)
474479 let baseAssetPoolAmountAfter = if (_isAdd)
475480 then (_baseAssetReserve + _baseAssetAmount)
476481 else (_baseAssetReserve - _baseAssetAmount)
477482 let quoteAssetAfter = toInt(bdivd(k, toBigInt(baseAssetPoolAmountAfter)))
478483 let quoteAssetDelta = abs((quoteAssetAfter - _quoteAssetReserve))
479484 let quoteAssetSold = muld(quoteAssetDelta, _quoteAssetWeight)
480485 let maxPriceImpactValue = maxPriceImpact()
481- let $t01941519577 = updateReserve(!(_isAdd), quoteAssetDelta, _baseAssetAmount)
482- let quoteAssetReserveAfter1 = $t01941519577._1
483- let baseAssetReserveAfter1 = $t01941519577._2
484- let totalPositionSizeAfter1 = $t01941519577._3
486+ let $t01959319755 = updateReserve(!(_isAdd), quoteAssetDelta, _baseAssetAmount)
487+ let quoteAssetReserveAfter1 = $t01959319755._1
488+ let baseAssetReserveAfter1 = $t01959319755._2
489+ let totalPositionSizeAfter1 = $t01959319755._3
485490 let marketPrice = divd(quoteAssetSold, _baseAssetAmount)
486491 let priceDiff = abs((priceBefore - marketPrice))
487492 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
488493 if (if ((priceImpact > maxPriceImpactValue))
489494 then _checkMaxPriceImpact
490495 else false)
491496 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)))
492497 else $Tuple7(quoteAssetSold, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1, (totalLongPositionSize() - (if (_isAdd)
493498 then abs(_baseAssetAmount)
494499 else 0)), (totalShortPositionSize() - (if (!(_isAdd))
495500 then abs(_baseAssetAmount)
496501 else 0)), priceImpact)
497502 }
498503 }
499504
500505
501506 func swapOutput (_isAdd,_baseAssetAmount,_checkMaxPriceImpact) = swapOutputWithReserves(_isAdd, _baseAssetAmount, _checkMaxPriceImpact, qtAstR(), qtAstW(), bsAstR(), bsAstW())
502507
503508
504509 func getOraclePriceValue (oracle,priceKey,blockKey) = {
505510 let lastValue = valueOrErrorMessage(getInteger(oracle, priceKey), ((("Can not get oracle price. Oracle: " + toString(oracle)) + " key: ") + priceKey))
506511 if ((blockKey != ""))
507512 then {
508513 let currentBlock = lastBlock.height
509514 let lastOracleBlock = valueOrErrorMessage(getInteger(oracle, blockKey), ((("Can not get oracle block. Oracle: " + toString(oracle)) + " key: ") + blockKey))
510515 if (((currentBlock - lastOracleBlock) > maxOracleDelay()))
511516 then throw(((("Oracle stale data. Last oracle block: " + toString(lastOracleBlock)) + " current block: ") + toString(currentBlock)))
512517 else lastValue
513518 }
514519 else lastValue
515520 }
516521
517522
518523 func getOraclePrice () = {
519524 let baseOracle = valueOrErrorMessage(getOracleData(k_baseOracle), "No base asset oracle data")
520525 let baseOraclePrice = getOraclePriceValue(baseOracle._1, baseOracle._2, baseOracle._3)
521526 let quoteOracle = getOracleData(k_quoteOracle)
522527 let quoteOraclePrice = if (isDefined(quoteOracle))
523528 then {
524529 let quoteOracleV = value(quoteOracle)
525530 getOraclePriceValue(quoteOracleV._1, quoteOracleV._2, quoteOracleV._3)
526531 }
527532 else DECIMAL_UNIT
528533 divd(baseOraclePrice, quoteOraclePrice)
529534 }
530535
531536
532537 func isMarketClosed () = {
533538 let baseOracle = valueOrErrorMessage(getOracleData(k_baseOracle), "No base asset oracle data")
534539 let oracle = baseOracle._1
535540 let openKey = baseOracle._4
536541 if ((openKey != ""))
537542 then {
538543 let isOpen = valueOrErrorMessage(getBoolean(oracle, openKey), ((("Can not get oracle is open/closed. Oracle: " + toString(oracle)) + " key: ") + openKey))
539544 !(isOpen)
540545 }
541546 else false
542547 }
543548
544549
545550 func absPriceDiff (_oraclePrice,_quoteAssetReserve,_baseAssetReserve,_qtAstW,_bsAstW) = {
546551 let priceAfter = divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
547552 let averagePrice = divd((_oraclePrice + priceAfter), (2 * DECIMAL_UNIT))
548553 let absPriceDiff = divd(abs((_oraclePrice - priceAfter)), averagePrice)
549554 absPriceDiff
550555 }
551556
552557
553558 func requireNotOverSpreadLimit (_quoteAssetReserve,_baseAssetReserve) = {
554559 let oraclePrice = getOraclePrice()
555560 let _qtAstW = qtAstW()
556561 let _bsAstW = bsAstW()
557562 let absPriceDiffBefore = absPriceDiff(oraclePrice, qtAstR(), bsAstR(), _qtAstW, _bsAstW)
558563 let absPriceDiffAfter = absPriceDiff(oraclePrice, _quoteAssetReserve, _baseAssetReserve, _qtAstW, _bsAstW)
559564 if (if ((absPriceDiffAfter > maxPriceSpread()))
560565 then (absPriceDiffAfter > absPriceDiffBefore)
561566 else false)
562567 then throw(((("Price spread " + toString(absPriceDiffAfter)) + " > max price spread ") + toString(maxPriceSpread())))
563568 else true
564569 }
565570
566571
567572 func requireNotOverMaxOpenNotional (_longOpenNotional,_shortOpenNotional) = {
568573 let _maxOpenNotional = maxOpenNotional()
569574 if ((_longOpenNotional > _maxOpenNotional))
570575 then throw(((("Long open notional " + toString(_longOpenNotional)) + " > max open notional ") + toString(_maxOpenNotional)))
571576 else if ((_shortOpenNotional > _maxOpenNotional))
572577 then throw(((("Short open notional " + toString(_shortOpenNotional)) + " > max open notional ") + toString(_maxOpenNotional)))
573578 else true
574579 }
575580
576581
577582 func getSpotPrice () = {
578583 let _quoteAssetReserve = qtAstR()
579584 let _baseAssetReserve = bsAstR()
580585 let _qtAstW = qtAstW()
581586 let _bsAstW = bsAstW()
582587 divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
583588 }
584589
585590
586591 func isOverFluctuationLimit () = {
587592 let oraclePrice = getOraclePrice()
588593 let currentPrice = getSpotPrice()
589594 (divd(abs((oraclePrice - currentPrice)), oraclePrice) > spreadLimit())
590595 }
591596
592597
593598 func getPositionAdjustedOpenNotional (_positionSize,_option,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
594599 let positionSizeAbs = abs(_positionSize)
595600 let isShort = (0 > _positionSize)
596601 let positionNotional = if ((_option == PNL_OPTION_SPOT))
597602 then {
598603 let outPositionNotional = swapOutputWithReserves(!(isShort), positionSizeAbs, false, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)._1
599604 outPositionNotional
600605 }
601606 else muld(positionSizeAbs, getOraclePrice())
602607 positionNotional
603608 }
604609
605610
606611 func getPositionNotionalAndUnrealizedPnlByValues (_positionSize,_positionOpenNotional,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight,_option) = if ((_positionSize == 0))
607612 then throw("Invalid position size")
608613 else {
609614 let isShort = (0 > _positionSize)
610615 let positionNotional = getPositionAdjustedOpenNotional(_positionSize, _option, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
611616 let unrealizedPnl = if (isShort)
612617 then (_positionOpenNotional - positionNotional)
613618 else (positionNotional - _positionOpenNotional)
614619 $Tuple2(positionNotional, unrealizedPnl)
615620 }
616621
617622
618623 func getPositionNotionalAndUnrealizedPnl (_trader,_option) = {
619- let $t02745527583 = getPosition(_trader)
620- let positionSize = $t02745527583._1
621- let positionMargin = $t02745527583._2
622- let positionOpenNotional = $t02745527583._3
623- let positionLstUpdCPF = $t02745527583._4
624+ let $t02763327761 = getPosition(_trader)
625+ let positionSize = $t02763327761._1
626+ let positionMargin = $t02763327761._2
627+ let positionOpenNotional = $t02763327761._3
628+ let positionLstUpdCPF = $t02763327761._4
624629 getPositionNotionalAndUnrealizedPnlByValues(positionSize, positionOpenNotional, qtAstR(), qtAstW(), bsAstR(), bsAstW(), _option)
625630 }
626631
627632
628633 func calcMarginRatio (_remainMargin,_badDebt,_positionNotional) = divd((_remainMargin - _badDebt), _positionNotional)
629634
630635
631636 func getMarginRatioByOption (_trader,_option) = {
632- let $t02809828239 = getPosition(_trader)
633- let positionSize = $t02809828239._1
634- let positionMargin = $t02809828239._2
635- let pon = $t02809828239._3
636- let positionLastUpdatedCPF = $t02809828239._4
637- let positionTimestamp = $t02809828239._5
638- let $t02824528338 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
639- let positionNotional = $t02824528338._1
640- let unrealizedPnl = $t02824528338._2
641- let $t02834328555 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLastUpdatedCPF, positionTimestamp, unrealizedPnl)
642- let remainMargin = $t02834328555._1
643- let badDebt = $t02834328555._2
637+ let $t02827628417 = getPosition(_trader)
638+ let positionSize = $t02827628417._1
639+ let positionMargin = $t02827628417._2
640+ let pon = $t02827628417._3
641+ let positionLastUpdatedCPF = $t02827628417._4
642+ let positionTimestamp = $t02827628417._5
643+ let $t02842328516 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
644+ let positionNotional = $t02842328516._1
645+ let unrealizedPnl = $t02842328516._2
646+ let $t02852128733 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLastUpdatedCPF, positionTimestamp, unrealizedPnl)
647+ let remainMargin = $t02852128733._1
648+ let badDebt = $t02852128733._2
644649 calcMarginRatio(remainMargin, badDebt, positionNotional)
645650 }
646651
647652
648653 func getMarginRatio (_trader) = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
649654
650655
651656 func getPartialLiquidationAmount (_trader,_positionSize) = {
652657 let maximumRatio = vmax(partialLiquidationRatio(), (DECIMAL_UNIT - divd(getMarginRatio(_trader), maintenanceMarginRatio())))
653658 let maxExchangedPositionSize = muld(abs(_positionSize), maximumRatio)
654659 let swapResult = swapOutput((_positionSize > 0), maxExchangedPositionSize, false)
655660 let maxExchangedQuoteAssetAmount = swapResult._1
656661 let priceImpact = swapResult._7
657662 if ((maxPriceImpact() > priceImpact))
658663 then maxExchangedPositionSize
659664 else muld(abs(_positionSize), partialLiquidationRatio())
660665 }
661666
662667
663668 func internalClosePosition (_trader,_size,_fee,_minQuoteAssetAmount,_addToMargin,_checkMaxPriceImpact,_liquidate) = {
664- let $t02962229778 = getPosition(_trader)
665- let oldPositionSize = $t02962229778._1
666- let oldPositionMargin = $t02962229778._2
667- let oldPositionOpenNotional = $t02962229778._3
668- let oldPositionLstUpdCPF = $t02962229778._4
669- let oldPositionTimestamp = $t02962229778._5
669+ let $t02980029956 = getPosition(_trader)
670+ let oldPositionSize = $t02980029956._1
671+ let oldPositionMargin = $t02980029956._2
672+ let oldPositionOpenNotional = $t02980029956._3
673+ let oldPositionLstUpdCPF = $t02980029956._4
674+ let oldPositionTimestamp = $t02980029956._5
670675 let isLongPosition = (oldPositionSize > 0)
671676 let absOldPositionSize = abs(oldPositionSize)
672677 if (if ((absOldPositionSize >= _size))
673678 then (_size > 0)
674679 else false)
675680 then {
676681 let isPartialClose = (absOldPositionSize > _size)
677- let $t03007030521 = swapOutput((oldPositionSize > 0), _size, _checkMaxPriceImpact)
678- let exchangedQuoteAssetAmount = $t03007030521._1
679- let quoteAssetReserveAfter = $t03007030521._2
680- let baseAssetReserveAfter = $t03007030521._3
681- let totalPositionSizeAfter = $t03007030521._4
682+ let $t03024830699 = swapOutput((oldPositionSize > 0), _size, _checkMaxPriceImpact)
683+ let exchangedQuoteAssetAmount = $t03024830699._1
684+ let quoteAssetReserveAfter = $t03024830699._2
685+ let baseAssetReserveAfter = $t03024830699._3
686+ let totalPositionSizeAfter = $t03024830699._4
682687 let exchangedPositionSize = if ((oldPositionSize > 0))
683688 then -(_size)
684689 else _size
685- let $t03073630943 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
686- let oldPositionNotional = $t03073630943._1
687- let unrealizedPnl = $t03073630943._2
690+ let $t03091431121 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
691+ let oldPositionNotional = $t03091431121._1
692+ let unrealizedPnl = $t03091431121._2
688693 let realizedRatio = divd(abs(exchangedPositionSize), absOldPositionSize)
689694 let realizedPnl = muld(unrealizedPnl, realizedRatio)
690- let $t03128431530 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, unrealizedPnl)
691- let remainMarginBefore = $t03128431530._1
692- let x1 = $t03128431530._2
693- let x2 = $t03128431530._3
694- let rolloverFee = $t03128431530._4
695+ let $t03146231708 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, unrealizedPnl)
696+ let remainMarginBefore = $t03146231708._1
697+ let x1 = $t03146231708._2
698+ let x2 = $t03146231708._3
699+ let rolloverFee = $t03146231708._4
695700 let positionBadDebt = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, realizedPnl)._2
696701 let realizedCloseFee = muld(muld(oldPositionNotional, realizedRatio), _fee)
697702 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
698703 let remainOpenNotional = if ((oldPositionSize > 0))
699704 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
700705 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
701706 let newPositionSize = (oldPositionSize + exchangedPositionSize)
702- let $t03293633322 = if ((newPositionSize == 0))
707+ let $t03311433500 = if ((newPositionSize == 0))
703708 then $Tuple2(0, 0)
704709 else $Tuple2(abs(remainOpenNotional), latestCumulativePremiumFraction(newPositionSize))
705- let newPositionOpenNotional = $t03293633322._1
706- let newPositionLstUpdCPF = $t03293633322._2
710+ let newPositionOpenNotional = $t03311433500._1
711+ let newPositionLstUpdCPF = $t03311433500._2
707712 let openNotionalDelta = (oldPositionOpenNotional - newPositionOpenNotional)
708713 let marginRatio = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
709714 let newPositionMarginWithSameRatio = if ((oldPositionSize > 0))
710715 then (muld((newPositionOpenNotional + unrealizedPnlAfter), marginRatio) - unrealizedPnlAfter)
711716 else (muld((newPositionOpenNotional - unrealizedPnlAfter), marginRatio) - unrealizedPnlAfter)
712717 let marginToTraderRaw = ((remainMarginBefore - (newPositionMarginWithSameRatio + unrealizedPnlAfter)) - realizedCloseFee)
713718 let marginToTrader = if ((0 > marginToTraderRaw))
714719 then if (_liquidate)
715720 then 0
716721 else throw("Invalid internalClosePosition params: unable to pay fee")
717722 else marginToTraderRaw
718723 let newPositionMargin = if (_addToMargin)
719724 then (newPositionMarginWithSameRatio + marginToTrader)
720725 else newPositionMarginWithSameRatio
721726 if (if ((_minQuoteAssetAmount != 0))
722727 then (_minQuoteAssetAmount > exchangedQuoteAssetAmount)
723728 else false)
724729 then throw(((("Limit error: " + toString(exchangedQuoteAssetAmount)) + " < ") + toString(_minQuoteAssetAmount)))
725730 else $Tuple17(newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, positionBadDebt, realizedPnl, if (if (_addToMargin)
726731 then isPartialClose
727732 else false)
728733 then 0
729734 else marginToTrader, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, (openInterestNotional() - openNotionalDelta), (totalLongPositionSize() - (if (isLongPosition)
730735 then abs(exchangedPositionSize)
731736 else 0)), (totalShortPositionSize() - (if (!(isLongPosition))
732737 then abs(exchangedPositionSize)
733738 else 0)), (openInterestLong() - (if (isLongPosition)
734739 then openNotionalDelta
735740 else 0)), (openInterestShort() - (if (!(isLongPosition))
736741 then openNotionalDelta
737742 else 0)), (realizedCloseFee + rolloverFee), exchangedQuoteAssetAmount)
738743 }
739744 else throw(((("Invalid internalClosePosition params: invalid position size: " + toString(_size)) + " max: ") + toString(absOldPositionSize)))
740745 }
741746
742747
743748 func getTerminalAmmState () = {
744749 let _positionSize = totalPositionSize()
745750 if ((_positionSize == 0))
746751 then $Tuple2(qtAstR(), bsAstR())
747752 else {
748753 let direction = (_positionSize > 0)
749- let $t03655736736 = swapOutput(direction, abs(_positionSize), false)
750- let currentNetMarketValue = $t03655736736._1
751- let terminalQuoteAssetReserve = $t03655736736._2
752- let terminalBaseAssetReserve = $t03655736736._3
754+ let $t03673536914 = swapOutput(direction, abs(_positionSize), false)
755+ let currentNetMarketValue = $t03673536914._1
756+ let terminalQuoteAssetReserve = $t03673536914._2
757+ let terminalBaseAssetReserve = $t03673536914._3
753758 $Tuple2(terminalQuoteAssetReserve, terminalBaseAssetReserve)
754759 }
755760 }
756761
757762
758763 func getQuoteAssetWeight (baseAssetReserve,totalPositionSize,quoteAssetReserve,targetPrice) = {
759764 let b = toBigInt(baseAssetReserve)
760765 let sz = toBigInt(totalPositionSize)
761766 let q = toBigInt(quoteAssetReserve)
762767 let p = toBigInt(targetPrice)
763768 let k = bmuld(q, b)
764769 let newB = (b + sz)
765770 let newQ = bdivd(k, newB)
766771 let z = bdivd(newQ, newB)
767772 let result = bdivd(p, z)
768773 toInt(result)
769774 }
770775
771776
772777 func getSyncTerminalPrice (_terminalPrice,_qtAstR,_bsAstR) = {
773778 let _positionSize = totalPositionSize()
774779 if ((_positionSize == 0))
775780 then {
776781 let newQtAstW = divd(muld(_terminalPrice, _bsAstR), _qtAstR)
777782 $Tuple3(newQtAstW, DECIMAL_UNIT, 0)
778783 }
779784 else {
780785 let direction = (_positionSize > 0)
781786 let currentNetMarketValue = swapOutput(direction, abs(_positionSize), false)._1
782787 let newQtAstW = getQuoteAssetWeight(_bsAstR, _positionSize, _qtAstR, _terminalPrice)
783788 let newBsAstW = DECIMAL_UNIT
784789 let marginToVault = getPositionNotionalAndUnrealizedPnlByValues(_positionSize, currentNetMarketValue, _qtAstR, newQtAstW, _bsAstR, newBsAstW, PNL_OPTION_SPOT)._2
785790 $Tuple3(newQtAstW, newBsAstW, marginToVault)
786791 }
787792 }
788793
789794
790795 func getFunding () = {
791796 let underlyingPrice = getOraclePrice()
792797 let spotPrice = getSpotPrice()
793798 let premium = (spotPrice - underlyingPrice)
794799 if (if (if ((totalShortPositionSize() == 0))
795800 then true
796801 else (totalLongPositionSize() == 0))
797802 then true
798803 else isMarketClosed())
799804 then $Tuple3(0, 0, 0)
800805 else if ((0 > premium))
801806 then {
802807 let shortPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
803808 if ((fundingMode() == FUNDING_ASYMMETRIC))
804809 then {
805810 let longPremiumFraction = divd(muld(shortPremiumFraction, totalShortPositionSize()), totalLongPositionSize())
806811 $Tuple3(shortPremiumFraction, longPremiumFraction, 0)
807812 }
808813 else {
809814 let shortTotalPremiumFraction = abs(muld(shortPremiumFraction, totalShortPositionSize()))
810815 let longTotalPremiumFraction = abs(muld(shortPremiumFraction, totalLongPositionSize()))
811816 let premiumToVault = (shortTotalPremiumFraction - longTotalPremiumFraction)
812817 $Tuple3(shortPremiumFraction, shortPremiumFraction, premiumToVault)
813818 }
814819 }
815820 else {
816821 let longPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
817822 if ((fundingMode() == FUNDING_ASYMMETRIC))
818823 then {
819824 let shortPremiumFraction = divd(muld(longPremiumFraction, totalLongPositionSize()), totalShortPositionSize())
820825 $Tuple3(shortPremiumFraction, longPremiumFraction, 0)
821826 }
822827 else {
823828 let longTotalPremiumFraction = abs(muld(longPremiumFraction, totalLongPositionSize()))
824829 let shortTotalPremiumFraction = abs(muld(longPremiumFraction, totalShortPositionSize()))
825830 let premiumToVault = (longTotalPremiumFraction - shortTotalPremiumFraction)
826831 $Tuple3(longPremiumFraction, longPremiumFraction, premiumToVault)
827832 }
828833 }
829834 }
830835
831836
832837 func getAdjustedFee (_artifactId,_baseFeeDiscount) = {
833838 let baseFeeRaw = fee()
834839 let baseFee = muld(baseFeeRaw, _baseFeeDiscount)
835- let $t04045440949 = if ((_artifactId != ""))
840+ let $t04063241127 = if ((_artifactId != ""))
836841 then {
837842 let artifactKind = strA(nftManagerAddress(), toCompositeKey(k_token_type, _artifactId))
838843 if ((artifactKind == FEE_REDUCTION_TOKEN_TYPE))
839844 then {
840845 let reduction = intA(nftManagerAddress(), toCompositeKey(k_token_param, _artifactId))
841846 let adjustedFee = muld(baseFee, reduction)
842847 $Tuple2(adjustedFee, true)
843848 }
844849 else throw("Invalid attached artifact")
845850 }
846851 else $Tuple2(baseFee, false)
847- let adjustedFee = $t04045440949._1
848- let burnArtifact = $t04045440949._2
852+ let adjustedFee = $t04063241127._1
853+ let burnArtifact = $t04063241127._2
849854 $Tuple2(adjustedFee, burnArtifact)
850855 }
851856
852857
853858 func getForTraderWithArtifact (_trader,_artifactId) = {
854859 let doGetFeeDiscount = invoke(minerAddress(), "computeFeeDiscount", [_trader], nil)
855860 if ((doGetFeeDiscount == doGetFeeDiscount))
856861 then {
857862 let feeDiscount = match doGetFeeDiscount {
858863 case x: Int =>
859864 x
860865 case _ =>
861866 throw("Invalid computeFeeDiscount result")
862867 }
863- let $t04129541369 = getAdjustedFee(_artifactId, feeDiscount)
864- let adjustedFee = $t04129541369._1
865- let burnArtifact = $t04129541369._2
868+ let $t04147341547 = getAdjustedFee(_artifactId, feeDiscount)
869+ let adjustedFee = $t04147341547._1
870+ let burnArtifact = $t04147341547._2
866871 $Tuple2(adjustedFee, burnArtifact)
867872 }
868873 else throw("Strict value is not equal to itself.")
869874 }
870875
871876
872877 func getArtifactId (i) = {
873878 let artifactId = if ((size(i.payments) > 1))
874879 then toBase58String(valueOrErrorMessage(i.payments[1].assetId, "Invalid artifactId"))
875880 else ""
876881 artifactId
877882 }
878883
879884
880885 func distributeFee (_feeAmount) = {
881886 let feeToStakers = muld(_feeAmount, feeToStakersPercent())
882887 let feeToVault = (_feeAmount - feeToStakers)
883888 $Tuple2(feeToStakers, feeToVault)
884889 }
885890
886891
887892 func updateSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay,_rolloverFee,_fundingMode) = [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), IntegerEntry(k_maxOpenNotional, _maxOpenNotional), IntegerEntry(k_feeToStakersPercent, _feeToStakersPercent), IntegerEntry(k_maxOracleDelay, _feeToStakersPercent), IntegerEntry(k_rolloverFee, _rolloverFee), IntegerEntry(k_fundingMode, _fundingMode)]
888893
889894
890895 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)]
891896
892897
893898 func incrementPositionSequenceNumber (_isNewPosition,_address) = if (_isNewPosition)
894899 then {
895900 let currentSequence = lastSequence()
896901 [IntegerEntry(toCompositeKey(k_positionSequence, _address), (currentSequence + 1)), IntegerEntry(k_sequence, (currentSequence + 1))]
897902 }
898903 else nil
899904
900905
901906 func updatePositionFee (_isNewPosition,_address,_fee) = if (_isNewPosition)
902907 then [IntegerEntry(toCompositeKey(k_positionFee, _address), _fee)]
903908 else nil
904909
905910
906911 func updatePosition (_address,_size,_margin,_openNotional,_latestCumulativePremiumFraction,_latestTimestamp) = [IntegerEntry(toCompositeKey(k_positionSize, _address), _size), IntegerEntry(toCompositeKey(k_positionMargin, _address), _margin), IntegerEntry(toCompositeKey(k_positionOpenNotional, _address), _openNotional), IntegerEntry(toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, _address), _latestCumulativePremiumFraction), IntegerEntry(toCompositeKey(k_positionLastUpdatedTimestamp, _address), _latestTimestamp)]
907912
908913
909914 func updateAmmReserves (_qtAstR,_bsAstR) = [IntegerEntry(k_quoteAssetReserve, _qtAstR), IntegerEntry(k_baseAssetReserve, _bsAstR)]
910915
911916
912917 func updateAmmWeights (_qtAstW,_bsAstW) = [IntegerEntry(k_quoteAssetWeight, _qtAstW), IntegerEntry(k_baseAssetWeight, _bsAstW)]
913918
914919
915920 func updateAmm (_qtAstR,_bsAstR,_totalPositionSizeAfter,_openInterestNotional,_totalLongPositionSize,_totalShortPositionSize,_totalLongOpenNotional,_totalShortOpenNotional) = {
916921 let _qtAstW = qtAstW()
917922 let _bsAstW = bsAstW()
918923 if (((_totalLongPositionSize - _totalShortPositionSize) != _totalPositionSizeAfter))
919924 then throw(((((("Invalid AMM state data: " + toString(_totalLongPositionSize)) + " + ") + toString(_totalShortPositionSize)) + " != ") + toString(_totalPositionSizeAfter)))
920925 else (updateAmmReserves(_qtAstR, _bsAstR) ++ [IntegerEntry(k_totalPositionSize, _totalPositionSizeAfter), IntegerEntry(k_openInterestNotional, _openInterestNotional), IntegerEntry(k_totalLongPositionSize, _totalLongPositionSize), IntegerEntry(k_totalShortPositionSize, _totalShortPositionSize), IntegerEntry(k_openInterestLong, _totalLongOpenNotional), IntegerEntry(k_openInterestShort, _totalShortOpenNotional)])
921926 }
922927
923928
924929 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_positionFee, _address)), DeleteEntry(toCompositeKey(k_positionLastUpdatedTimestamp, _address))]
925930
926931
927932 func withdraw (_address,_amount) = {
928933 let balance = assetBalance(this, quoteAsset())
929934 if ((_amount > balance))
930935 then throw(((("Unable to withdraw " + toString(_amount)) + " from contract balance ") + toString(balance)))
931936 else [ScriptTransfer(_address, _amount, quoteAsset())]
932937 }
933938
934939
935940 func updateBalance (i) = if ((0 > i))
936941 then throw("Balance")
937942 else [IntegerEntry(k_balance, i)]
938943
939944
940945 func transferFee (i) = [ScriptTransfer(stakingAddress(), i, quoteAsset())]
941946
942947
943948 func doBurnArtifact (_burnArtifact,i) = if (_burnArtifact)
944949 then [Burn(valueOrErrorMessage(i.payments[1].assetId, "Invalid artifact"), 1)]
945950 else nil
946951
947952
948953 @Callable(i)
949954 func pause () = if ((i.caller != adminAddress()))
950955 then throw("Invalid pause params")
951956 else [BooleanEntry(k_paused, true)]
952957
953958
954959
955960 @Callable(i)
961+func delist () = if ((i.caller != adminAddress()))
962+ then throw("Invalid delist params")
963+ else [BooleanEntry(k_delisted, true)]
964+
965+
966+
967+@Callable(i)
956968 func unpause () = if ((i.caller != adminAddress()))
957969 then throw("Invalid unpause params")
958970 else [BooleanEntry(k_paused, false)]
959971
960972
961973
962974 @Callable(i)
963975 func setCloseOnly () = if ((i.caller != adminAddress()))
964976 then throw("Invalid setCloseOnly params")
965977 else [BooleanEntry(k_closeOnly, true)]
966978
967979
968980
969981 @Callable(i)
970982 func unsetCloseOnly () = if ((i.caller != adminAddress()))
971983 then throw("Invalid unsetCloseOnly params")
972984 else [BooleanEntry(k_closeOnly, false)]
973985
974986
975987
976988 @Callable(i)
977989 func addLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
978990 then true
979991 else (0 >= _quoteAssetAmount))
980992 then throw("Invalid addLiquidity params")
981993 else {
982994 let _qtAstR = qtAstR()
983995 let _bsAstR = bsAstR()
984996 let _qtAstW = qtAstW()
985997 let _bsAstW = bsAstW()
986998 let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
987999 let qtAstRAfter = (_qtAstR + _quoteAssetAmount)
9881000 let baseAssetAmountToAdd = (divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR)
9891001 let bsAstRAfter = (_bsAstR + baseAssetAmountToAdd)
990- let $t04926349414 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
991- let newQuoteAssetWeight = $t04926349414._1
992- let newBaseAssetWeight = $t04926349414._2
993- let marginToVault = $t04926349414._3
1002+ let $t04961549766 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1003+ let newQuoteAssetWeight = $t04961549766._1
1004+ let newBaseAssetWeight = $t04961549766._2
1005+ let marginToVault = $t04961549766._3
9941006 let doExchangePnL = if ((marginToVault != 0))
9951007 then {
9961008 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
9971009 if ((doExchangePnL == doExchangePnL))
9981010 then nil
9991011 else throw("Strict value is not equal to itself.")
10001012 }
10011013 else nil
10021014 if ((doExchangePnL == doExchangePnL))
10031015 then (updateAmmReserves(qtAstRAfter, bsAstRAfter) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
10041016 else throw("Strict value is not equal to itself.")
10051017 }
10061018
10071019
10081020
10091021 @Callable(i)
10101022 func removeLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
10111023 then true
10121024 else (_quoteAssetAmount >= 0))
10131025 then throw("Invalid removeLiquidity params")
10141026 else {
10151027 let _qtAstR = qtAstR()
10161028 let _bsAstR = bsAstR()
10171029 let _qtAstW = qtAstW()
10181030 let _bsAstW = bsAstW()
10191031 let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
10201032 let qtAstRAfter = (_qtAstR - _quoteAssetAmount)
10211033 let baseAssetAmountToRemove = abs((divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR))
10221034 let bsAstRAfter = (_bsAstR - baseAssetAmountToRemove)
1023- let $t05051050661 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1024- let newQuoteAssetWeight = $t05051050661._1
1025- let newBaseAssetWeight = $t05051050661._2
1026- let marginToVault = $t05051050661._3
1035+ let $t05086251013 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1036+ let newQuoteAssetWeight = $t05086251013._1
1037+ let newBaseAssetWeight = $t05086251013._2
1038+ let marginToVault = $t05086251013._3
10271039 let doExchangePnL = if ((marginToVault != 0))
10281040 then {
10291041 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
10301042 if ((doExchangePnL == doExchangePnL))
10311043 then nil
10321044 else throw("Strict value is not equal to itself.")
10331045 }
10341046 else nil
10351047 if ((doExchangePnL == doExchangePnL))
10361048 then (updateAmmReserves(qtAstRAfter, bsAstRAfter) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
10371049 else throw("Strict value is not equal to itself.")
10381050 }
10391051
10401052
10411053
10421054 @Callable(i)
10431055 func changeSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay,_rolloverFee,_fundingMode) = if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if ((0 >= _fundingPeriod))
10441056 then true
10451057 else (0 >= _initMarginRatio))
10461058 then true
10471059 else (0 >= _mmr))
10481060 then true
10491061 else (0 >= _liquidationFeeRatio))
10501062 then true
10511063 else (0 >= _fee))
10521064 then true
10531065 else (0 >= _spreadLimit))
10541066 then true
10551067 else (0 >= _maxPriceImpact))
10561068 then true
10571069 else (0 >= _partialLiquidationRatio))
10581070 then true
10591071 else (0 >= _maxPriceSpread))
10601072 then true
10611073 else (0 >= _maxOpenNotional))
10621074 then true
10631075 else (0 >= _feeToStakersPercent))
10641076 then true
10651077 else (_feeToStakersPercent > DECIMAL_UNIT))
10661078 then true
10671079 else (0 >= _maxOracleDelay))
10681080 then true
10691081 else (0 >= _rolloverFee))
10701082 then true
10711083 else if ((_fundingMode != FUNDING_SYMMETRIC))
10721084 then (_fundingMode != FUNDING_ASYMMETRIC)
10731085 else false)
10741086 then true
10751087 else !(initialized()))
10761088 then true
10771089 else (i.caller != adminAddress()))
10781090 then throw("Invalid changeSettings params")
10791091 else updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact, _partialLiquidationRatio, _maxPriceSpread, _maxOpenNotional, _feeToStakersPercent, _maxOracleDelay, _rolloverFee, _fundingMode)
10801092
10811093
10821094
10831095 @Callable(i)
10841096 func initialize (_qtAstR,_bsAstR,_fundingPeriod,_initMarginRatio,_mmr,_liquidationFeeRatio,_fee,_baseOracleData,_quoteOracleData,_coordinator,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay,_rolloverFee,_fundingMode) = if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if ((0 >= _qtAstR))
10851097 then true
10861098 else (0 >= _bsAstR))
10871099 then true
10881100 else (0 >= _fundingPeriod))
10891101 then true
10901102 else (0 >= _initMarginRatio))
10911103 then true
10921104 else (0 >= _mmr))
10931105 then true
10941106 else (0 >= _liquidationFeeRatio))
10951107 then true
10961108 else (0 >= _fee))
10971109 then true
10981110 else (0 >= _spreadLimit))
10991111 then true
11001112 else (0 >= _maxPriceImpact))
11011113 then true
11021114 else (0 >= _partialLiquidationRatio))
11031115 then true
11041116 else (0 >= _maxPriceSpread))
11051117 then true
11061118 else (0 >= _maxOpenNotional))
11071119 then true
11081120 else (0 >= _feeToStakersPercent))
11091121 then true
11101122 else (_feeToStakersPercent > DECIMAL_UNIT))
11111123 then true
11121124 else (0 >= _maxOracleDelay))
11131125 then true
11141126 else (0 >= _rolloverFee))
11151127 then true
11161128 else if ((_fundingMode != FUNDING_SYMMETRIC))
11171129 then (_fundingMode != FUNDING_ASYMMETRIC)
11181130 else false)
11191131 then true
11201132 else initialized())
11211133 then true
11221134 else (i.caller != this))
11231135 then throw("Invalid initialize parameters")
11241136 else ((((updateAmm(_qtAstR, _bsAstR, 0, 0, 0, 0, 0, 0) ++ updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact, _partialLiquidationRatio, _maxPriceSpread, _maxOpenNotional, _feeToStakersPercent, _maxOracleDelay, _rolloverFee, _fundingMode)) ++ updateFunding((lastTimestamp() + _fundingPeriod), 0, 0, 0, 0)) ++ updateBalance(0)) ++ [BooleanEntry(k_initialized, true), StringEntry(k_baseOracle, _baseOracleData), StringEntry(k_quoteOracle, _quoteOracleData), StringEntry(k_coordinatorAddress, toString(addressFromStringValue(_coordinator)))])
11251137
11261138
11271139
11281140 @Callable(i)
11291141 func increasePosition (_direction,_leverage,_minBaseAssetAmount,_refLink) = {
11301142 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
11311143 if ((sync == sync))
11321144 then {
11331145 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
11341146 if ((ensureCalledOnce == ensureCalledOnce))
11351147 then {
11361148 let _trader = getActualCaller(i)
11371149 let _rawAmount = i.payments[0].amount
11381150 let _assetId = i.payments[0].assetId
11391151 let _assetIdStr = toBase58String(value(_assetId))
11401152 let isQuoteAsset = (_assetId == quoteAsset())
11411153 if (if (if (if (if (if (if (if (if ((_direction != DIR_LONG))
11421154 then (_direction != DIR_SHORT)
11431155 else false)
11441156 then true
11451157 else (0 >= _rawAmount))
11461158 then true
11471159 else !(initialized()))
11481160 then true
11491161 else !(isQuoteAsset))
11501162 then true
11511163 else !(requireMoreMarginRatio(divd(DECIMAL_UNIT, _leverage), initMarginRatio(), true)))
11521164 then true
11531165 else paused())
11541166 then true
11551167 else closeOnly())
11561168 then true
11571169 else isMarketClosed())
11581170 then throw("Invalid increasePosition parameters")
11591171 else {
1160- let $t05673156880 = getForTraderWithArtifact(_trader, getArtifactId(i))
1161- let adjustedFee = $t05673156880._1
1162- let burnArtifact = $t05673156880._2
1172+ let $t05708357232 = getForTraderWithArtifact(_trader, getArtifactId(i))
1173+ let adjustedFee = $t05708357232._1
1174+ let burnArtifact = $t05708357232._2
11631175 let _amount = divd(_rawAmount, (muld(adjustedFee, _leverage) + DECIMAL_UNIT))
11641176 let distributeFeeAmount = (_rawAmount - _amount)
11651177 let referrerFeeAny = invoke(referralAddress(), "acceptPaymentWithLink", [_trader, _refLink], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
11661178 if ((referrerFeeAny == referrerFeeAny))
11671179 then {
11681180 let referrerFee = match referrerFeeAny {
11691181 case x: Int =>
11701182 x
11711183 case _ =>
11721184 throw("Invalid referrerFee")
11731185 }
11741186 let feeAmount = (distributeFeeAmount - referrerFee)
1175- let $t05737657544 = getPosition(_trader)
1176- let oldPositionSize = $t05737657544._1
1177- let oldPositionMargin = $t05737657544._2
1178- let oldPositionOpenNotional = $t05737657544._3
1179- let oldPositionLstUpdCPF = $t05737657544._4
1180- let oldPositionTimestamp = $t05737657544._5
1187+ let $t05772857896 = getPosition(_trader)
1188+ let oldPositionSize = $t05772857896._1
1189+ let oldPositionMargin = $t05772857896._2
1190+ let oldPositionOpenNotional = $t05772857896._3
1191+ let oldPositionLstUpdCPF = $t05772857896._4
1192+ let oldPositionTimestamp = $t05772857896._5
11811193 let isNewPosition = (oldPositionSize == 0)
11821194 let isSameDirection = if ((oldPositionSize > 0))
11831195 then (_direction == DIR_LONG)
11841196 else (_direction == DIR_SHORT)
11851197 let expandExisting = if (!(isNewPosition))
11861198 then isSameDirection
11871199 else false
11881200 let isAdd = (_direction == DIR_LONG)
1189- let $t05783360954 = if (if (isNewPosition)
1201+ let $t05818561306 = if (if (isNewPosition)
11901202 then true
11911203 else expandExisting)
11921204 then {
11931205 let openNotional = muld(_amount, _leverage)
1194- let $t05834258515 = swapInput(isAdd, openNotional)
1195- let amountBaseAssetBought = $t05834258515._1
1196- let quoteAssetReserveAfter = $t05834258515._2
1197- let baseAssetReserveAfter = $t05834258515._3
1198- let totalPositionSizeAfter = $t05834258515._4
1206+ let $t05869458867 = swapInput(isAdd, openNotional)
1207+ let amountBaseAssetBought = $t05869458867._1
1208+ let quoteAssetReserveAfter = $t05869458867._2
1209+ let baseAssetReserveAfter = $t05869458867._3
1210+ let totalPositionSizeAfter = $t05869458867._4
11991211 if (if ((_minBaseAssetAmount != 0))
12001212 then (_minBaseAssetAmount > abs(amountBaseAssetBought))
12011213 else false)
12021214 then throw(((("Limit error: " + toString(abs(amountBaseAssetBought))) + " < ") + toString(_minBaseAssetAmount)))
12031215 else {
12041216 let newPositionSize = (oldPositionSize + amountBaseAssetBought)
12051217 let totalLongOpenInterestAfter = (openInterestLong() + (if ((newPositionSize > 0))
12061218 then openNotional
12071219 else 0))
12081220 let totalShortOpenInterestAfter = (openInterestShort() + (if ((0 > newPositionSize))
12091221 then openNotional
12101222 else 0))
1211- let $t05906159336 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, _amount)
1212- let remainMargin = $t05906159336._1
1213- let x1 = $t05906159336._2
1214- let x2 = $t05906159336._3
1215- let rolloverFee = $t05906159336._4
1223+ let $t05941359688 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, _amount)
1224+ let remainMargin = $t05941359688._1
1225+ let x1 = $t05941359688._2
1226+ let x2 = $t05941359688._3
1227+ let rolloverFee = $t05941359688._4
12161228 if (!(requireNotOverSpreadLimit(quoteAssetReserveAfter, baseAssetReserveAfter)))
12171229 then throw("Over max spread limit")
12181230 else if (!(requireNotOverMaxOpenNotional(totalLongOpenInterestAfter, totalShortOpenInterestAfter)))
12191231 then throw("Over max open notional")
12201232 else $Tuple14(newPositionSize, remainMargin, (oldPositionOpenNotional + openNotional), latestCumulativePremiumFraction(newPositionSize), lastTimestamp(), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, (openInterestNotional() + openNotional), (totalLongPositionSize() + (if ((newPositionSize > 0))
12211233 then abs(amountBaseAssetBought)
12221234 else 0)), (totalShortPositionSize() + (if ((0 > newPositionSize))
12231235 then abs(amountBaseAssetBought)
12241236 else 0)), totalLongOpenInterestAfter, totalShortOpenInterestAfter, rolloverFee)
12251237 }
12261238 }
12271239 else {
12281240 let openNotional = muld(_amount, _leverage)
1229- let $t06065460770 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1230- let oldPositionNotional = $t06065460770._1
1231- let unrealizedPnl = $t06065460770._2
1241+ let $t06100661122 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1242+ let oldPositionNotional = $t06100661122._1
1243+ let unrealizedPnl = $t06100661122._2
12321244 if ((oldPositionNotional > openNotional))
12331245 then throw("Use decreasePosition to decrease position size")
12341246 else throw("Close position first")
12351247 }
1236- let newPositionSize = $t05783360954._1
1237- let newPositionRemainMargin = $t05783360954._2
1238- let newPositionOpenNotional = $t05783360954._3
1239- let newPositionLatestCPF = $t05783360954._4
1240- let newPositionTimestamp = $t05783360954._5
1241- let baseAssetReserveAfter = $t05783360954._6
1242- let quoteAssetReserveAfter = $t05783360954._7
1243- let totalPositionSizeAfter = $t05783360954._8
1244- let openInterestNotionalAfter = $t05783360954._9
1245- let totalLongAfter = $t05783360954._10
1246- let totalShortAfter = $t05783360954._11
1247- let totalLongOpenInterestAfter = $t05783360954._12
1248- let totalShortOpenInterestAfter = $t05783360954._13
1249- let rolloverFee = $t05783360954._14
1250- let $t06096061031 = distributeFee((feeAmount + rolloverFee))
1251- let feeToStakers = $t06096061031._1
1252- let feeToVault = $t06096061031._2
1248+ let newPositionSize = $t05818561306._1
1249+ let newPositionRemainMargin = $t05818561306._2
1250+ let newPositionOpenNotional = $t05818561306._3
1251+ let newPositionLatestCPF = $t05818561306._4
1252+ let newPositionTimestamp = $t05818561306._5
1253+ let baseAssetReserveAfter = $t05818561306._6
1254+ let quoteAssetReserveAfter = $t05818561306._7
1255+ let totalPositionSizeAfter = $t05818561306._8
1256+ let openInterestNotionalAfter = $t05818561306._9
1257+ let totalLongAfter = $t05818561306._10
1258+ let totalShortAfter = $t05818561306._11
1259+ let totalLongOpenInterestAfter = $t05818561306._12
1260+ let totalShortOpenInterestAfter = $t05818561306._13
1261+ let rolloverFee = $t05818561306._14
1262+ let $t06131261383 = distributeFee((feeAmount + rolloverFee))
1263+ let feeToStakers = $t06131261383._1
1264+ let feeToVault = $t06131261383._2
12531265 let stake = if ((_amount >= rolloverFee))
12541266 then invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), (_amount - rolloverFee))])
12551267 else invoke(vaultAddress(), "withdrawLocked", [(rolloverFee - _amount)], nil)
12561268 if ((stake == stake))
12571269 then {
12581270 let depositVault = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
12591271 if ((depositVault == depositVault))
12601272 then {
12611273 let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, feeAmount], nil)
12621274 if ((notifyFee == notifyFee))
12631275 then {
12641276 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
12651277 if ((notifyNotional == notifyNotional))
12661278 then ((((((updatePosition(_trader, newPositionSize, newPositionRemainMargin, newPositionOpenNotional, newPositionLatestCPF, newPositionTimestamp) ++ incrementPositionSequenceNumber(isNewPosition, _trader)) ++ updatePositionFee(isNewPosition, _trader, adjustedFee)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ transferFee(feeToStakers)) ++ updateBalance(((cbalance() + _amount) - rolloverFee))) ++ doBurnArtifact(burnArtifact, i))
12671279 else throw("Strict value is not equal to itself.")
12681280 }
12691281 else throw("Strict value is not equal to itself.")
12701282 }
12711283 else throw("Strict value is not equal to itself.")
12721284 }
12731285 else throw("Strict value is not equal to itself.")
12741286 }
12751287 else throw("Strict value is not equal to itself.")
12761288 }
12771289 }
12781290 else throw("Strict value is not equal to itself.")
12791291 }
12801292 else throw("Strict value is not equal to itself.")
12811293 }
12821294
12831295
12841296
12851297 @Callable(i)
12861298 func addMargin () = {
12871299 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
12881300 if ((sync == sync))
12891301 then {
12901302 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
12911303 if ((ensureCalledOnce == ensureCalledOnce))
12921304 then {
12931305 let _trader = toString(i.caller)
12941306 let _amount = i.payments[0].amount
12951307 let _assetId = i.payments[0].assetId
12961308 let _assetIdStr = toBase58String(value(_assetId))
12971309 let isQuoteAsset = (_assetId == quoteAsset())
12981310 if (if (if (if (if (if (!(isQuoteAsset))
12991311 then true
13001312 else !(requireOpenPosition(toString(i.caller))))
13011313 then true
13021314 else !(initialized()))
13031315 then true
13041316 else paused())
13051317 then true
13061318 else closeOnly())
13071319 then true
13081320 else isMarketClosed())
13091321 then throw("Invalid addMargin parameters")
13101322 else {
1311- let $t06324663414 = getPosition(_trader)
1312- let oldPositionSize = $t06324663414._1
1313- let oldPositionMargin = $t06324663414._2
1314- let oldPositionOpenNotional = $t06324663414._3
1315- let oldPositionLstUpdCPF = $t06324663414._4
1316- let oldPositionTimestamp = $t06324663414._5
1323+ let $t06359863766 = getPosition(_trader)
1324+ let oldPositionSize = $t06359863766._1
1325+ let oldPositionMargin = $t06359863766._2
1326+ let oldPositionOpenNotional = $t06359863766._3
1327+ let oldPositionLstUpdCPF = $t06359863766._4
1328+ let oldPositionTimestamp = $t06359863766._5
13171329 let stake = invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), _amount)])
13181330 if ((stake == stake))
13191331 then {
13201332 let rolloverFee = calcRolloverFee(oldPositionMargin, oldPositionTimestamp)
13211333 let doTransferFeeToStakers = if ((rolloverFee > 0))
13221334 then {
1323- let $t06369963758 = distributeFee(rolloverFee)
1324- let feeToStakers = $t06369963758._1
1325- let feeToVault = $t06369963758._2
1335+ let $t06405164110 = distributeFee(rolloverFee)
1336+ let feeToStakers = $t06405164110._1
1337+ let feeToVault = $t06405164110._2
13261338 let unstake = invoke(vaultAddress(), "withdrawLocked", [feeToStakers], nil)
13271339 if ((unstake == unstake))
13281340 then {
13291341 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(feeToVault)], nil)
13301342 if ((lockBadDebt == lockBadDebt))
13311343 then transferFee(feeToStakers)
13321344 else throw("Strict value is not equal to itself.")
13331345 }
13341346 else throw("Strict value is not equal to itself.")
13351347 }
13361348 else nil
13371349 if ((doTransferFeeToStakers == doTransferFeeToStakers))
13381350 then ((updatePosition(_trader, oldPositionSize, ((oldPositionMargin - rolloverFee) + _amount), oldPositionOpenNotional, oldPositionLstUpdCPF, lastTimestamp()) ++ updateBalance(((cbalance() + _amount) - rolloverFee))) ++ doTransferFeeToStakers)
13391351 else throw("Strict value is not equal to itself.")
13401352 }
13411353 else throw("Strict value is not equal to itself.")
13421354 }
13431355 }
13441356 else throw("Strict value is not equal to itself.")
13451357 }
13461358 else throw("Strict value is not equal to itself.")
13471359 }
13481360
13491361
13501362
13511363 @Callable(i)
13521364 func removeMargin (_amount) = {
13531365 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
13541366 if ((sync == sync))
13551367 then {
13561368 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
13571369 if ((ensureCalledOnce == ensureCalledOnce))
13581370 then {
13591371 let _trader = toString(i.caller)
13601372 if (if (if (if (if ((0 >= _amount))
13611373 then true
13621374 else !(requireOpenPosition(_trader)))
13631375 then true
13641376 else !(initialized()))
13651377 then true
13661378 else paused())
13671379 then true
13681380 else isMarketClosed())
13691381 then throw("Invalid removeMargin parameters")
13701382 else {
1371- let $t06513165299 = getPosition(_trader)
1372- let oldPositionSize = $t06513165299._1
1373- let oldPositionMargin = $t06513165299._2
1374- let oldPositionOpenNotional = $t06513165299._3
1375- let oldPositionLstUpdCPF = $t06513165299._4
1376- let oldPositionTimestamp = $t06513165299._5
1377- let $t06530565554 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, -(_amount))
1378- let remainMargin = $t06530565554._1
1379- let badDebt = $t06530565554._2
1380- let fundingPayment = $t06530565554._3
1381- let rolloverFee = $t06530565554._4
1383+ let $t06548365651 = getPosition(_trader)
1384+ let oldPositionSize = $t06548365651._1
1385+ let oldPositionMargin = $t06548365651._2
1386+ let oldPositionOpenNotional = $t06548365651._3
1387+ let oldPositionLstUpdCPF = $t06548365651._4
1388+ let oldPositionTimestamp = $t06548365651._5
1389+ let $t06565765906 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, -(_amount))
1390+ let remainMargin = $t06565765906._1
1391+ let badDebt = $t06565765906._2
1392+ let fundingPayment = $t06565765906._3
1393+ let rolloverFee = $t06565765906._4
13821394 if ((badDebt != 0))
13831395 then throw("Invalid removed margin amount")
13841396 else {
13851397 let marginRatio = calcMarginRatio(remainMargin, badDebt, oldPositionOpenNotional)
13861398 if (!(requireMoreMarginRatio(marginRatio, initMarginRatio(), true)))
13871399 then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
13881400 else {
1389- let $t06594065999 = distributeFee(rolloverFee)
1390- let feeToStakers = $t06594065999._1
1391- let feeToVault = $t06594065999._2
1401+ let $t06629266351 = distributeFee(rolloverFee)
1402+ let feeToStakers = $t06629266351._1
1403+ let feeToVault = $t06629266351._2
13921404 let doTransferFeeToStakers = if ((rolloverFee > 0))
13931405 then {
13941406 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(feeToVault)], nil)
13951407 if ((lockBadDebt == lockBadDebt))
13961408 then transferFee(feeToStakers)
13971409 else throw("Strict value is not equal to itself.")
13981410 }
13991411 else nil
14001412 if ((doTransferFeeToStakers == doTransferFeeToStakers))
14011413 then {
14021414 let unstake = invoke(vaultAddress(), "withdrawLocked", [(_amount + feeToStakers)], nil)
14031415 if ((unstake == unstake))
14041416 then (((updatePosition(_trader, oldPositionSize, remainMargin, oldPositionOpenNotional, latestCumulativePremiumFraction(oldPositionSize), lastTimestamp()) ++ withdraw(i.caller, _amount)) ++ updateBalance(((cbalance() - _amount) - rolloverFee))) ++ doTransferFeeToStakers)
14051417 else throw("Strict value is not equal to itself.")
14061418 }
14071419 else throw("Strict value is not equal to itself.")
14081420 }
14091421 }
14101422 }
14111423 }
14121424 else throw("Strict value is not equal to itself.")
14131425 }
14141426 else throw("Strict value is not equal to itself.")
14151427 }
14161428
14171429
14181430
14191431 @Callable(i)
14201432 func closePosition (_size,_minQuoteAssetAmount,_addToMargin) = {
14211433 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
14221434 if ((sync == sync))
14231435 then {
14241436 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
14251437 if ((ensureCalledOnce == ensureCalledOnce))
14261438 then {
14271439 let _trader = getActualCaller(i)
14281440 let _traderAddress = valueOrErrorMessage(addressFromString(_trader), "Invalid caller")
14291441 let positionFee = getPositionFee(_trader)
14301442 if (if (if (if (if (if (!(requireOpenPosition(_trader)))
14311443 then true
14321444 else !(initialized()))
14331445 then true
14341446 else paused())
14351447 then true
14361448 else (0 >= _size))
14371449 then true
14381450 else (0 > _minQuoteAssetAmount))
14391451 then true
14401452 else isMarketClosed())
14411453 then throw("Invalid closePosition parameters")
14421454 else {
14431455 let oldPositionTimestamp = getPosition(_trader)._5
1444- let $t06817468759 = internalClosePosition(_trader, _size, positionFee, _minQuoteAssetAmount, _addToMargin, true, true)
1445- let newPositionSize = $t06817468759._1
1446- let newPositionMargin = $t06817468759._2
1447- let newPositionOpenNotional = $t06817468759._3
1448- let newPositionLstUpdCPF = $t06817468759._4
1449- let positionBadDebt = $t06817468759._5
1450- let realizedPnl = $t06817468759._6
1451- let marginToTrader = $t06817468759._7
1452- let quoteAssetReserveAfter = $t06817468759._8
1453- let baseAssetReserveAfter = $t06817468759._9
1454- let totalPositionSizeAfter = $t06817468759._10
1455- let openInterestNotionalAfter = $t06817468759._11
1456- let totalLongAfter = $t06817468759._12
1457- let totalShortAfter = $t06817468759._13
1458- let totalLongOpenInterestAfter = $t06817468759._14
1459- let totalShortOpenInterestAfter = $t06817468759._15
1460- let realizedFee = $t06817468759._16
1456+ let $t06852669111 = internalClosePosition(_trader, _size, positionFee, _minQuoteAssetAmount, _addToMargin, true, true)
1457+ let newPositionSize = $t06852669111._1
1458+ let newPositionMargin = $t06852669111._2
1459+ let newPositionOpenNotional = $t06852669111._3
1460+ let newPositionLstUpdCPF = $t06852669111._4
1461+ let positionBadDebt = $t06852669111._5
1462+ let realizedPnl = $t06852669111._6
1463+ let marginToTrader = $t06852669111._7
1464+ let quoteAssetReserveAfter = $t06852669111._8
1465+ let baseAssetReserveAfter = $t06852669111._9
1466+ let totalPositionSizeAfter = $t06852669111._10
1467+ let openInterestNotionalAfter = $t06852669111._11
1468+ let totalLongAfter = $t06852669111._12
1469+ let totalShortAfter = $t06852669111._13
1470+ let totalLongOpenInterestAfter = $t06852669111._14
1471+ let totalShortOpenInterestAfter = $t06852669111._15
1472+ let realizedFee = $t06852669111._16
14611473 if ((positionBadDebt > 0))
14621474 then throw("Invalid closePosition parameters: bad debt")
14631475 else if ((oldPositionTimestamp >= lastTimestamp()))
14641476 then throw("Invalid closePosition parameters: wait at least 1 block before closing the position")
14651477 else {
14661478 let isPartialClose = (newPositionSize != 0)
14671479 let withdrawAmount = (marginToTrader + realizedFee)
14681480 let ammBalance = (cbalance() - withdrawAmount)
14691481 let ammNewBalance = if ((0 > ammBalance))
14701482 then 0
14711483 else ammBalance
14721484 let unstake = invoke(vaultAddress(), "withdrawLocked", [withdrawAmount], nil)
14731485 if ((unstake == unstake))
14741486 then {
1475- let $t06943169490 = distributeFee(realizedFee)
1476- let feeToStakers = $t06943169490._1
1477- let feeToVault = $t06943169490._2
1487+ let $t06978369842 = distributeFee(realizedFee)
1488+ let feeToStakers = $t06978369842._1
1489+ let feeToVault = $t06978369842._2
14781490 let depositVault = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
14791491 if ((depositVault == depositVault))
14801492 then {
14811493 let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, realizedFee], nil)
14821494 if ((notifyFee == notifyFee))
14831495 then {
14841496 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
14851497 if ((notifyNotional == notifyNotional))
14861498 then (((((if (isPartialClose)
14871499 then updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, lastTimestamp())
14881500 else deletePosition(_trader)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ (if ((marginToTrader > 0))
14891501 then withdraw(_traderAddress, marginToTrader)
14901502 else nil)) ++ updateBalance(ammNewBalance)) ++ transferFee(feeToStakers))
14911503 else throw("Strict value is not equal to itself.")
14921504 }
14931505 else throw("Strict value is not equal to itself.")
14941506 }
14951507 else throw("Strict value is not equal to itself.")
14961508 }
14971509 else throw("Strict value is not equal to itself.")
14981510 }
14991511 }
15001512 }
15011513 else throw("Strict value is not equal to itself.")
15021514 }
15031515 else throw("Strict value is not equal to itself.")
15041516 }
15051517
15061518
15071519
15081520 @Callable(i)
15091521 func liquidate (_trader) = {
15101522 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
15111523 if ((sync == sync))
15121524 then {
15131525 let spotMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
15141526 let liquidationMarginRatio = if (isOverFluctuationLimit())
15151527 then {
15161528 let oracleMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_ORACLE)
15171529 vmax(spotMarginRatio, oracleMarginRatio)
15181530 }
15191531 else spotMarginRatio
15201532 if (if (if (if (if (!(requireMoreMarginRatio(liquidationMarginRatio, maintenanceMarginRatio(), false)))
15211533 then true
15221534 else !(requireOpenPosition(_trader)))
15231535 then true
15241536 else !(initialized()))
15251537 then true
15261538 else paused())
15271539 then true
15281540 else isMarketClosed())
15291541 then throw("Unable to liquidate")
15301542 else {
15311543 let isPartialLiquidation = if (if ((spotMarginRatio > liquidationFeeRatio()))
15321544 then (partialLiquidationRatio() > 0)
15331545 else false)
15341546 then (DECIMAL_UNIT > partialLiquidationRatio())
15351547 else false
15361548 let oldPositionSize = getPosition(_trader)._1
15371549 let positionSizeAbs = abs(oldPositionSize)
1538- let $t07191172234 = if (isPartialLiquidation)
1550+ let $t07226372586 = if (isPartialLiquidation)
15391551 then {
15401552 let liquidationSize = getPartialLiquidationAmount(_trader, oldPositionSize)
15411553 let liquidationRatio = divd(abs(liquidationSize), positionSizeAbs)
15421554 $Tuple2(liquidationRatio, abs(liquidationSize))
15431555 }
15441556 else $Tuple2(0, positionSizeAbs)
1545- let liquidationRatio = $t07191172234._1
1546- let liquidationSize = $t07191172234._2
1547- let $t07224072878 = internalClosePosition(_trader, if (isPartialLiquidation)
1557+ let liquidationRatio = $t07226372586._1
1558+ let liquidationSize = $t07226372586._2
1559+ let $t07259273230 = internalClosePosition(_trader, if (isPartialLiquidation)
15481560 then liquidationSize
15491561 else positionSizeAbs, liquidationFeeRatio(), 0, true, false, true)
1550- let newPositionSize = $t07224072878._1
1551- let newPositionMargin = $t07224072878._2
1552- let newPositionOpenNotional = $t07224072878._3
1553- let newPositionLstUpdCPF = $t07224072878._4
1554- let positionBadDebt = $t07224072878._5
1555- let realizedPnl = $t07224072878._6
1556- let marginToTrader = $t07224072878._7
1557- let quoteAssetReserveAfter = $t07224072878._8
1558- let baseAssetReserveAfter = $t07224072878._9
1559- let totalPositionSizeAfter = $t07224072878._10
1560- let openInterestNotionalAfter = $t07224072878._11
1561- let totalLongAfter = $t07224072878._12
1562- let totalShortAfter = $t07224072878._13
1563- let totalLongOpenInterestAfter = $t07224072878._14
1564- let totalShortOpenInterestAfter = $t07224072878._15
1565- let liquidationPenalty = $t07224072878._16
1562+ let newPositionSize = $t07259273230._1
1563+ let newPositionMargin = $t07259273230._2
1564+ let newPositionOpenNotional = $t07259273230._3
1565+ let newPositionLstUpdCPF = $t07259273230._4
1566+ let positionBadDebt = $t07259273230._5
1567+ let realizedPnl = $t07259273230._6
1568+ let marginToTrader = $t07259273230._7
1569+ let quoteAssetReserveAfter = $t07259273230._8
1570+ let baseAssetReserveAfter = $t07259273230._9
1571+ let totalPositionSizeAfter = $t07259273230._10
1572+ let openInterestNotionalAfter = $t07259273230._11
1573+ let totalLongAfter = $t07259273230._12
1574+ let totalShortAfter = $t07259273230._13
1575+ let totalLongOpenInterestAfter = $t07259273230._14
1576+ let totalShortOpenInterestAfter = $t07259273230._15
1577+ let liquidationPenalty = $t07259273230._16
15661578 let feeToLiquidator = (liquidationPenalty / 2)
15671579 let feeToVault = (liquidationPenalty - feeToLiquidator)
15681580 let ammBalance = (cbalance() - liquidationPenalty)
15691581 let newAmmBalance = if ((0 > ammBalance))
15701582 then 0
15711583 else ammBalance
15721584 let lockBadDebt = if ((positionBadDebt > 0))
15731585 then {
15741586 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [(positionBadDebt + liquidationPenalty)], nil)
15751587 if ((lockBadDebt == lockBadDebt))
15761588 then nil
15771589 else throw("Strict value is not equal to itself.")
15781590 }
15791591 else nil
15801592 if ((lockBadDebt == lockBadDebt))
15811593 then {
15821594 let unstake = invoke(vaultAddress(), "withdrawLocked", [liquidationPenalty], nil)
15831595 if ((unstake == unstake))
15841596 then {
15851597 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
15861598 if ((depositInsurance == depositInsurance))
15871599 then {
15881600 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
15891601 if ((notifyNotional == notifyNotional))
15901602 then ((((if (isPartialLiquidation)
15911603 then updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, lastTimestamp())
15921604 else deletePosition(_trader)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ withdraw(i.caller, feeToLiquidator)) ++ updateBalance(newAmmBalance))
15931605 else throw("Strict value is not equal to itself.")
15941606 }
15951607 else throw("Strict value is not equal to itself.")
15961608 }
15971609 else throw("Strict value is not equal to itself.")
15981610 }
15991611 else throw("Strict value is not equal to itself.")
16001612 }
16011613 }
16021614 else throw("Strict value is not equal to itself.")
16031615 }
16041616
16051617
16061618
16071619 @Callable(i)
16081620 func payFunding () = {
16091621 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
16101622 if ((sync == sync))
16111623 then {
16121624 let fundingBlockTimestamp = nextFundingBlockTimestamp()
16131625 if (if (if ((fundingBlockTimestamp > lastTimestamp()))
16141626 then true
16151627 else !(initialized()))
16161628 then true
16171629 else paused())
16181630 then throw(((("Invalid funding block timestamp: " + toString(lastTimestamp())) + " < ") + toString(fundingBlockTimestamp)))
16191631 else {
16201632 let underlyingPrice = getOraclePrice()
1621- let $t07499175069 = getFunding()
1622- let shortPremiumFraction = $t07499175069._1
1623- let longPremiumFraction = $t07499175069._2
1624- let premiumToVault = $t07499175069._3
1633+ let $t07534375421 = getFunding()
1634+ let shortPremiumFraction = $t07534375421._1
1635+ let longPremiumFraction = $t07534375421._2
1636+ let premiumToVault = $t07534375421._3
16251637 let doPayFundingToVault = if ((premiumToVault > 0))
16261638 then {
16271639 let doPayFundingToVault = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(premiumToVault)], nil)
16281640 if ((doPayFundingToVault == doPayFundingToVault))
16291641 then nil
16301642 else throw("Strict value is not equal to itself.")
16311643 }
16321644 else nil
16331645 if ((doPayFundingToVault == doPayFundingToVault))
16341646 then updateFunding((fundingBlockTimestamp + fundingPeriodSeconds()), (latestLongCumulativePremiumFraction() + longPremiumFraction), (latestShortCumulativePremiumFraction() + shortPremiumFraction), divd(longPremiumFraction, underlyingPrice), divd(shortPremiumFraction, underlyingPrice))
16351647 else throw("Strict value is not equal to itself.")
16361648 }
16371649 }
16381650 else throw("Strict value is not equal to itself.")
16391651 }
16401652
16411653
16421654
16431655 @Callable(i)
1644-func syncTerminalPriceToOracle () = {
1645- let _qtAstR = qtAstR()
1646- let _bsAstR = bsAstR()
1647- let $t07612076486 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1648- let newQuoteAssetWeight = $t07612076486._1
1649- let newBaseAssetWeight = $t07612076486._2
1650- let marginToVault = $t07612076486._3
1651- let marginToVaultAdj = if (if ((0 > marginToVault))
1652- then (abs(marginToVault) > cbalance())
1653- else false)
1654- then -(cbalance())
1655- else marginToVault
1656- let doExchangePnL = if ((marginToVaultAdj != 0))
1657- then {
1658- let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVaultAdj], nil)
1659- if ((doExchangePnL == doExchangePnL))
1660- then nil
1661- else throw("Strict value is not equal to itself.")
1662- }
1663- else nil
1664- if ((doExchangePnL == doExchangePnL))
1665- then (updateBalance((cbalance() + marginToVaultAdj)) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
1666- else throw("Strict value is not equal to itself.")
1667- }
1656+func syncTerminalPriceToOracle () = if (delisted())
1657+ then nil
1658+ else {
1659+ let _qtAstR = qtAstR()
1660+ let _bsAstR = bsAstR()
1661+ let $t07651176895 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1662+ let newQuoteAssetWeight = $t07651176895._1
1663+ let newBaseAssetWeight = $t07651176895._2
1664+ let marginToVault = $t07651176895._3
1665+ let marginToVaultAdj = if (if ((0 > marginToVault))
1666+ then (abs(marginToVault) > cbalance())
1667+ else false)
1668+ then -(cbalance())
1669+ else marginToVault
1670+ let doExchangePnL = if ((marginToVaultAdj != 0))
1671+ then {
1672+ let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVaultAdj], nil)
1673+ if ((doExchangePnL == doExchangePnL))
1674+ then nil
1675+ else throw("Strict value is not equal to itself.")
1676+ }
1677+ else nil
1678+ if ((doExchangePnL == doExchangePnL))
1679+ then (updateBalance((cbalance() + marginToVaultAdj)) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
1680+ else throw("Strict value is not equal to itself.")
1681+ }
16681682
16691683
16701684
16711685 @Callable(i)
16721686 func ensureCalledOnce () = if ((i.caller != this))
16731687 then throw("Invalid saveCurrentTxId parameters")
16741688 else {
16751689 let lastTx = valueOrElse(getString(this, k_lastTx), "")
16761690 if ((lastTx != toBase58String(i.transactionId)))
16771691 then [StringEntry(k_lastTx, lastTx)]
16781692 else throw("Can not call vAMM methods twice in one tx")
16791693 }
16801694
16811695
16821696
16831697 @Callable(i)
16841698 func view_calcRemainMarginWithFundingPayment (_trader) = {
16851699 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
16861700 if ((sync == sync))
16871701 then {
1688- let $t07803578159 = getPosition(_trader)
1689- let positionSize = $t07803578159._1
1690- let positionMargin = $t07803578159._2
1691- let pon = $t07803578159._3
1692- let positionLstUpdCPF = $t07803578159._4
1693- let positionTimestamp = $t07803578159._5
1694- let $t07816278263 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1695- let positionNotional = $t07816278263._1
1696- let unrealizedPnl = $t07816278263._2
1697- let $t07826678490 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLstUpdCPF, positionTimestamp, unrealizedPnl)
1698- let remainMargin = $t07826678490._1
1699- let badDebt = $t07826678490._2
1700- let fundingPayment = $t07826678490._3
1701- let rolloverFee = $t07826678490._4
1702+ let $t07849078614 = getPosition(_trader)
1703+ let positionSize = $t07849078614._1
1704+ let positionMargin = $t07849078614._2
1705+ let pon = $t07849078614._3
1706+ let positionLstUpdCPF = $t07849078614._4
1707+ let positionTimestamp = $t07849078614._5
1708+ let $t07861778718 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1709+ let positionNotional = $t07861778718._1
1710+ let unrealizedPnl = $t07861778718._2
1711+ let $t07872178945 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLstUpdCPF, positionTimestamp, unrealizedPnl)
1712+ let remainMargin = $t07872178945._1
1713+ let badDebt = $t07872178945._2
1714+ let fundingPayment = $t07872178945._3
1715+ let rolloverFee = $t07872178945._4
17021716 throw(((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)) + s(rolloverFee)))
17031717 }
17041718 else throw("Strict value is not equal to itself.")
17051719 }
17061720
17071721
17081722
17091723 @Callable(i)
17101724 func view_getPegAdjustCost (_price) = {
17111725 let _qtAstR = qtAstR()
17121726 let _bsAstR = bsAstR()
17131727 let result = getSyncTerminalPrice(_price, _qtAstR, _bsAstR)
17141728 throw(toString(result._3))
17151729 }
17161730
17171731
17181732
17191733 @Callable(i)
17201734 func view_getTerminalAmmPrice () = {
1721- let $t07921379294 = getTerminalAmmState()
1722- let terminalQuoteAssetReserve = $t07921379294._1
1723- let terminalBaseAssetReserve = $t07921379294._2
1735+ let $t07966879749 = getTerminalAmmState()
1736+ let terminalQuoteAssetReserve = $t07966879749._1
1737+ let terminalBaseAssetReserve = $t07966879749._2
17241738 let price = divd(muld(terminalQuoteAssetReserve, qtAstW()), muld(terminalBaseAssetReserve, bsAstW()))
17251739 throw(toString(price))
17261740 }
17271741
17281742
17291743
17301744 @Callable(i)
17311745 func view_getFunding () = {
17321746 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
17331747 if ((sync == sync))
17341748 then {
17351749 let underlyingPrice = getOraclePrice()
1736- let $t07985379931 = getFunding()
1737- let shortPremiumFraction = $t07985379931._1
1738- let longPremiumFraction = $t07985379931._2
1739- let premiumToVault = $t07985379931._3
1750+ let $t08030880386 = getFunding()
1751+ let shortPremiumFraction = $t08030880386._1
1752+ let longPremiumFraction = $t08030880386._2
1753+ let premiumToVault = $t08030880386._3
17401754 let longFunding = divd(longPremiumFraction, underlyingPrice)
17411755 let shortFunding = divd(shortPremiumFraction, underlyingPrice)
17421756 throw(((((s(longFunding) + s(shortFunding)) + s(getSpotPrice())) + s(getOraclePrice())) + s(premiumToVault)))
17431757 }
17441758 else throw("Strict value is not equal to itself.")
17451759 }
17461760
17471761
17481762
17491763 @Callable(i)
17501764 func computeSpotPrice () = {
17511765 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
17521766 if ((sync == sync))
17531767 then {
17541768 let result = getSpotPrice()
17551769 $Tuple2(nil, result)
17561770 }
17571771 else throw("Strict value is not equal to itself.")
17581772 }
17591773
17601774
17611775
17621776 @Callable(i)
17631777 func computeFeeForTraderWithArtifact (_trader,_artifactId) = {
17641778 let result = getForTraderWithArtifact(_trader, _artifactId)
17651779 $Tuple2(nil, result)
17661780 }
17671781
17681782
17691783 @Verifier(tx)
17701784 func verify () = {
17711785 let coordinatorStr = getString(this, k_coordinatorAddress)
17721786 if (isDefined(coordinatorStr))
17731787 then {
17741788 let admin = getString(addressFromStringValue(value(coordinatorStr)), k_admin_address)
17751789 if (isDefined(admin))
17761790 then valueOrElse(getBoolean(addressFromStringValue(value(admin)), ((("status_" + toString(this)) + "_") + toBase58String(tx.id))), false)
17771791 else throw("unable to verify: admin not set in coordinator")
17781792 }
17791793 else sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
17801794 }
17811795

github/deemru/w8io/786bc32 
284.58 ms