tx · CtTyx7f42fq1fAHuSKUwqHeFgcPoeBMNREdZevigc8mF

3P9mFc9Zn9bsk9McUXECybF4imt7691VM1F:  -0.09000000 Waves

2023.02.19 14:21 [3522005] smart account 3P9mFc9Zn9bsk9McUXECybF4imt7691VM1F > SELF 0.00000000 Waves

{ "type": 13, "id": "CtTyx7f42fq1fAHuSKUwqHeFgcPoeBMNREdZevigc8mF", "fee": 9000000, "feeAssetId": null, "timestamp": 1676805707055, "version": 2, "chainId": 87, "sender": "3P9mFc9Zn9bsk9McUXECybF4imt7691VM1F", "senderPublicKey": "GnSvg7p6roYfV6Pwx258DRQR4MkivrfWrHtiRiGRKAY7", "proofs": [ "4jmrRvqkk1Rnq2bL5GRsqkuCMxnWr2ZhW7sLFHPGq3HwhkPZm8XqkEt2A1upv9KLX73cad5Ny1L9ca5qEgp48esN" ], "script": "base64:BgJ0CAISABIAEgASABIDCgEBEgMKAQESEAoOAQEBAQEBAQEBAQEBAQESFQoTAQEBAQEBAQgICAEBAQEBAQEBARIGCgQBAQEIEgASAwoBARIFCgMBAQQSAwoBCBIAEgASABIDCgEIEgMKAQESABIAEgASBAoCCAi5AQAMa19iYXNlT3JhY2xlAgxrX2Jhc2VPcmFjbGUADWtfcXVvdGVPcmFjbGUCDWtfcXVvdGVPcmFjbGUACWtfYmFsYW5jZQIJa19iYWxhbmNlAAprX3NlcXVlbmNlAgprX3NlcXVlbmNlAA5rX3Bvc2l0aW9uU2l6ZQIOa19wb3NpdGlvblNpemUAEGtfcG9zaXRpb25NYXJnaW4CEGtfcG9zaXRpb25NYXJnaW4AFmtfcG9zaXRpb25PcGVuTm90aW9uYWwCFmtfcG9zaXRpb25PcGVuTm90aW9uYWwALmtfcG9zaXRpb25MYXN0VXBkYXRlZEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24CEmtfcG9zaXRpb25GcmFjdGlvbgASa19wb3NpdGlvblNlcXVlbmNlAhJrX3Bvc2l0aW9uU2VxdWVuY2UAD2tfcG9zaXRpb25Bc3NldAIPa19wb3NpdGlvbkFzc2V0AA1rX3Bvc2l0aW9uRmVlAg1rX3Bvc2l0aW9uRmVlAB5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRUaW1lc3RhbXACE2tfcG9zaXRpb25UaW1lc3RhbXAADWtfaW5pdGlhbGl6ZWQCDWtfaW5pdGlhbGl6ZWQACGtfcGF1c2VkAghrX3BhdXNlZAALa19jbG9zZU9ubHkCC2tfY2xvc2VPbmx5AAVrX2ZlZQIFa19mZWUADWtfcm9sbG92ZXJGZWUCDmtfcm9sbG92ZXJfZmVlAA9rX2Z1bmRpbmdQZXJpb2QCD2tfZnVuZGluZ1BlcmlvZAARa19pbml0TWFyZ2luUmF0aW8CEWtfaW5pdE1hcmdpblJhdGlvABhrX21haW50ZW5hbmNlTWFyZ2luUmF0aW8CBWtfbW1yABVrX2xpcXVpZGF0aW9uRmVlUmF0aW8CFWtfbGlxdWlkYXRpb25GZWVSYXRpbwAZa19wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwIWa19wYXJ0TGlxdWlkYXRpb25SYXRpbwANa19zcHJlYWRMaW1pdAINa19zcHJlYWRMaW1pdAAQa19tYXhQcmljZUltcGFjdAIQa19tYXhQcmljZUltcGFjdAAQa19tYXhQcmljZVNwcmVhZAIQa19tYXhQcmljZVNwcmVhZAARa19tYXhPcGVuTm90aW9uYWwCEWtfbWF4T3Blbk5vdGlvbmFsABVrX2ZlZVRvU3Rha2Vyc1BlcmNlbnQCFWtfZmVlVG9TdGFrZXJzUGVyY2VudAAQa19tYXhPcmFjbGVEZWxheQIQa19tYXhPcmFjbGVEZWxheQANa19mdW5kaW5nTW9kZQINa19mdW5kaW5nTW9kZQAla19sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgIba19sYXRlc3RMb25nUHJlbWl1bUZyYWN0aW9uACZrX2xhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgIca19sYXRlc3RTaG9ydFByZW1pdW1GcmFjdGlvbgASa19uZXh0RnVuZGluZ0Jsb2NrAh5rX25leHRGdW5kaW5nQmxvY2tNaW5UaW1lc3RhbXAAEWtfbG9uZ0Z1bmRpbmdSYXRlAhFrX2xvbmdGdW5kaW5nUmF0ZQASa19zaG9ydEZ1bmRpbmdSYXRlAhJrX3Nob3J0RnVuZGluZ1JhdGUAE2tfcXVvdGVBc3NldFJlc2VydmUCCGtfcXRBc3RSABJrX2Jhc2VBc3NldFJlc2VydmUCCGtfYnNBc3RSABJrX3F1b3RlQXNzZXRXZWlnaHQCCGtfcXRBc3RXABFrX2Jhc2VBc3NldFdlaWdodAIIa19ic0FzdFcAE2tfdG90YWxQb3NpdGlvblNpemUCE2tfdG90YWxQb3NpdGlvblNpemUAF2tfdG90YWxMb25nUG9zaXRpb25TaXplAhdrX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQAYa190b3RhbFNob3J0UG9zaXRpb25TaXplAhhrX3RvdGFsU2hvcnRQb3NpdGlvblNpemUAFmtfb3BlbkludGVyZXN0Tm90aW9uYWwCFmtfb3BlbkludGVyZXN0Tm90aW9uYWwAE2tfb3BlbkludGVyZXN0U2hvcnQCE2tfb3BlbkludGVyZXN0U2hvcnQAEmtfb3BlbkludGVyZXN0TG9uZwISa19vcGVuSW50ZXJlc3RMb25nAAhrX2xhc3RUeAIIa19sYXN0VHgAFGtfY29vcmRpbmF0b3JBZGRyZXNzAhRrX2Nvb3JkaW5hdG9yQWRkcmVzcwAPa192YXVsdF9hZGRyZXNzAg9rX3ZhdWx0X2FkZHJlc3MAD2tfYWRtaW5fYWRkcmVzcwIPa19hZG1pbl9hZGRyZXNzAA1rX3F1b3RlX2Fzc2V0Ag1rX3F1b3RlX2Fzc2V0AA9rX3F1b3RlX3N0YWtpbmcCD2tfcXVvdGVfc3Rha2luZwARa19zdGFraW5nX2FkZHJlc3MCEWtfc3Rha2luZ19hZGRyZXNzAA9rX21pbmVyX2FkZHJlc3MCD2tfbWluZXJfYWRkcmVzcwAQa19vcmRlcnNfYWRkcmVzcwIQa19vcmRlcnNfYWRkcmVzcwASa19yZWZlcnJhbF9hZGRyZXNzAhJrX3JlZmVycmFsX2FkZHJlc3MAEmtfZXhjaGFuZ2VfYWRkcmVzcwISa19leGNoYW5nZV9hZGRyZXNzABVrX25mdF9tYW5hZ2VyX2FkZHJlc3MCFWtfbmZ0X21hbmFnZXJfYWRkcmVzcwEOdG9Db21wb3NpdGVLZXkCBF9rZXkIX2FkZHJlc3MJAKwCAgkArAICBQRfa2V5AgFfBQhfYWRkcmVzcwELY29vcmRpbmF0b3IACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgUEdGhpcwUUa19jb29yZGluYXRvckFkZHJlc3MCE0Nvb3JkaW5hdG9yIG5vdCBzZXQBDGFkbWluQWRkcmVzcwAJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUPa19hZG1pbl9hZGRyZXNzAQpxdW90ZUFzc2V0AAkA2QQBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABQ1rX3F1b3RlX2Fzc2V0ARFxdW90ZUFzc2V0U3Rha2luZwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABQ9rX3F1b3RlX3N0YWtpbmcCG1F1b3RlIGFzc2V0IHN0YWtpbmcgbm90IHNldAEOc3Rha2luZ0FkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAURa19zdGFraW5nX2FkZHJlc3MCD1N0YWtpbmcgbm90IHNldAEMdmF1bHRBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFD2tfdmF1bHRfYWRkcmVzcwINVmF1bHQgbm90IHNldAEMbWluZXJBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFD2tfbWluZXJfYWRkcmVzcwINTWluZXIgbm90IHNldAENb3JkZXJzQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABRBrX29yZGVyc19hZGRyZXNzAg5PcmRlcnMgbm90IHNldAEPcmVmZXJyYWxBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFEmtfcmVmZXJyYWxfYWRkcmVzcwIQUmVmZXJyYWwgbm90IHNldAERbmZ0TWFuYWdlckFkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUVa19uZnRfbWFuYWdlcl9hZGRyZXNzAhNORlQgTWFuYWdlciBub3Qgc2V0AA1rX3Rva2VuX3BhcmFtAg1rX3Rva2VuX3BhcmFtAAxrX3Rva2VuX3R5cGUCDGtfdG9rZW5fdHlwZQAYRkVFX1JFRFVDVElPTl9UT0tFTl9UWVBFAg1mZWVfcmVkdWN0aW9uAAhESVJfTE9ORwABAAlESVJfU0hPUlQAAgANVFdBUF9JTlRFUlZBTAAPAAdTRUNPTkRTAOgHAA9ERUNJTUFMX05VTUJFUlMABgAMREVDSU1BTF9VTklUCQBoAgABCQBoAgkAaAIJAGgCCQBoAgkAaAIACgAKAAoACgAKAAoAD01JTlVURVNfSU5fWUVBUgkAaAIAoIogBQxERUNJTUFMX1VOSVQAB09ORV9EQVkJAGgCAICjBQUMREVDSU1BTF9VTklUAA9QTkxfT1BUSU9OX1NQT1QAAQARUE5MX09QVElPTl9PUkFDTEUAAgASRlVORElOR19BU1lNTUVUUklDAAEAEUZVTkRJTkdfU1lNTUVUUklDAAIBAXMBAl94CQCsAgIJAKQDAQUCX3gCASwBBGRpdmQCAl94Al95CQBuBAUCX3gFDERFQ0lNQUxfVU5JVAUCX3kFCEhBTEZFVkVOAQRtdWxkAgJfeAJfeQkAbgQFAl94BQJfeQUMREVDSU1BTF9VTklUBQhIQUxGRVZFTgEFYmRpdmQCAl94Al95CQC9AgQFAl94CQC2AgEFDERFQ0lNQUxfVU5JVAUCX3kFCEhBTEZFVkVOAQVibXVsZAICX3gCX3kJAL0CBAUCX3gFAl95CQC2AgEFDERFQ0lNQUxfVU5JVAUISEFMRkVWRU4BA2FicwECX3gDCQBmAgUCX3gAAAUCX3gJAQEtAQUCX3gBBHZtYXgCAl94Al95AwkAZwIFAl94BQJfeQUCX3gFAl95AQlsaXN0VG9TdHIBBV9saXN0AwkAAAIJAJADAQUFX2xpc3QAAAIACQC5CQIFBV9saXN0AgEsAQlzdHJUb0xpc3QBBF9zdHIDCQAAAgUEX3N0cgIABQNuaWwJALUJAgUEX3N0cgIBLAELcHVzaFRvUXVldWUDBV9saXN0CF9tYXhTaXplBl92YWx1ZQMJAGYCCQCQAwEFBV9saXN0BQhfbWF4U2l6ZQkAzQgCCQDRCAIFBV9saXN0AAAFBl92YWx1ZQkAzQgCBQVfbGlzdAUGX3ZhbHVlAQNpbnQBAWsJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQR0aGlzBQFrCQCsAgICDW5vIHZhbHVlIGZvciAFAWsBBWludE9yAgFrA2RlZgkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQFrBQNkZWYBBHN0ckECCF9hZGRyZXNzBF9rZXkEA3ZhbAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFCF9hZGRyZXNzBQRfa2V5CQCsAgICEU5vIHZhbHVlIGZvciBrZXkgBQRfa2V5BQN2YWwBBGludEECCF9hZGRyZXNzBF9rZXkEA3ZhbAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFCF9hZGRyZXNzBQRfa2V5CQCsAgICEU5vIHZhbHVlIGZvciBrZXkgBQRfa2V5BQN2YWwBCGNiYWxhbmNlAAkBA2ludAEFCWtfYmFsYW5jZQEDZmVlAAkBA2ludAEFBWtfZmVlAQ9yb2xsb3ZlckZlZVJhdGUACQEDaW50AQUNa19yb2xsb3ZlckZlZQEPaW5pdE1hcmdpblJhdGlvAAkBA2ludAEFEWtfaW5pdE1hcmdpblJhdGlvAQZxdEFzdFIACQEDaW50AQUTa19xdW90ZUFzc2V0UmVzZXJ2ZQEGYnNBc3RSAAkBA2ludAEFEmtfYmFzZUFzc2V0UmVzZXJ2ZQEGcXRBc3RXAAkBBWludE9yAgUSa19xdW90ZUFzc2V0V2VpZ2h0BQxERUNJTUFMX1VOSVQBBmJzQXN0VwAJAQVpbnRPcgIFEWtfYmFzZUFzc2V0V2VpZ2h0BQxERUNJTUFMX1VOSVQBEXRvdGFsUG9zaXRpb25TaXplAAkBA2ludAEFE2tfdG90YWxQb3NpdGlvblNpemUBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAAkBA2ludAEFFmtfb3BlbkludGVyZXN0Tm90aW9uYWwBEW9wZW5JbnRlcmVzdFNob3J0AAkBA2ludAEFE2tfb3BlbkludGVyZXN0U2hvcnQBEG9wZW5JbnRlcmVzdExvbmcACQEDaW50AQUSa19vcGVuSW50ZXJlc3RMb25nARluZXh0RnVuZGluZ0Jsb2NrVGltZXN0YW1wAAkBA2ludAEFEmtfbmV4dEZ1bmRpbmdCbG9jawEQZnVuZGluZ1BlcmlvZFJhdwAJAQNpbnQBBQ9rX2Z1bmRpbmdQZXJpb2QBFGZ1bmRpbmdQZXJpb2REZWNpbWFsAAkAaAIJARBmdW5kaW5nUGVyaW9kUmF3AAUMREVDSU1BTF9VTklUARRmdW5kaW5nUGVyaW9kU2Vjb25kcwAJAGgCCQEQZnVuZGluZ1BlcmlvZFJhdwAFB1NFQ09ORFMBFm1haW50ZW5hbmNlTWFyZ2luUmF0aW8ACQEDaW50AQUYa19tYWludGVuYW5jZU1hcmdpblJhdGlvARNsaXF1aWRhdGlvbkZlZVJhdGlvAAkBA2ludAEFFWtfbGlxdWlkYXRpb25GZWVSYXRpbwEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8ACQEDaW50AQUZa19wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwELc3ByZWFkTGltaXQACQEDaW50AQUNa19zcHJlYWRMaW1pdAEObWF4UHJpY2VJbXBhY3QACQEDaW50AQUQa19tYXhQcmljZUltcGFjdAEObWF4UHJpY2VTcHJlYWQACQEDaW50AQUQa19tYXhQcmljZVNwcmVhZAEPbWF4T3Blbk5vdGlvbmFsAAkBA2ludAEFEWtfbWF4T3Blbk5vdGlvbmFsASNsYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAJAQNpbnQBBSVrX2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uASRsYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24ACQEDaW50AQUma19sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BFnRvdGFsU2hvcnRQb3NpdGlvblNpemUACQEDaW50AQUYa190b3RhbFNob3J0UG9zaXRpb25TaXplARV0b3RhbExvbmdQb3NpdGlvblNpemUACQEDaW50AQUXa190b3RhbExvbmdQb3NpdGlvblNpemUBDGxhc3RTZXF1ZW5jZQAJAQVpbnRPcgIFCmtfc2VxdWVuY2UAAAETZmVlVG9TdGFrZXJzUGVyY2VudAAJAQNpbnQBBRVrX2ZlZVRvU3Rha2Vyc1BlcmNlbnQBDm1heE9yYWNsZURlbGF5AAkBA2ludAEFEGtfbWF4T3JhY2xlRGVsYXkBC2Z1bmRpbmdNb2RlAAkBBWludE9yAgUNa19mdW5kaW5nTW9kZQUSRlVORElOR19BU1lNTUVUUklDAQ1sYXN0VGltZXN0YW1wAAgFCWxhc3RCbG9jawl0aW1lc3RhbXABD2dldEFjdHVhbENhbGxlcgEBaQkBC3ZhbHVlT3JFbHNlAgkAnQgCCQENb3JkZXJzQWRkcmVzcwACCGtfc2VuZGVyCQClCAEIBQFpBmNhbGxlcgEWcmVxdWlyZU1vcmVNYXJnaW5SYXRpbwMMX21hcmdpblJhdGlvEF9iYXNlTWFyZ2luUmF0aW8UX2xhcmdlclRoYW5PckVxdWFsVG8EFHJlbWFpbmluZ01hcmdpblJhdGlvCQBlAgUMX21hcmdpblJhdGlvBRBfYmFzZU1hcmdpblJhdGlvAwMFFF9sYXJnZXJUaGFuT3JFcXVhbFRvCQBmAgAABRRyZW1haW5pbmdNYXJnaW5SYXRpbwcJAAIBCQCsAgIJAKwCAgkArAICAhBJbnZhbGlkIG1hcmdpbjogCQCkAwEFDF9tYXJnaW5SYXRpbwIDIDwgCQCkAwEFEF9iYXNlTWFyZ2luUmF0aW8DAwkBASEBBRRfbGFyZ2VyVGhhbk9yRXF1YWxUbwkAZwIFFHJlbWFpbmluZ01hcmdpblJhdGlvAAAHCQACAQkArAICCQCsAgIJAKwCAgIQSW52YWxpZCBtYXJnaW46IAkApAMBBQxfbWFyZ2luUmF0aW8CAyA+IAkApAMBBRBfYmFzZU1hcmdpblJhdGlvBgEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgENX3Bvc2l0aW9uU2l6ZQMJAAACBQ1fcG9zaXRpb25TaXplAAAJAAIBAixTaG91bGQgbm90IGJlIGNhbGxlZCB3aXRoIF9wb3NpdGlvblNpemUgPT0gMAMJAGYCBQ1fcG9zaXRpb25TaXplAAAJASNsYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAJASRsYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24AAQtnZXRQb3NpdGlvbgEHX3RyYWRlcgQPcG9zaXRpb25TaXplT3B0CQCaCAIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFDmtfcG9zaXRpb25TaXplBQdfdHJhZGVyBAckbWF0Y2gwBQ9wb3NpdGlvblNpemVPcHQDCQABAgUHJG1hdGNoMAIDSW50BAxwb3NpdGlvblNpemUFByRtYXRjaDAJAJcKBQUMcG9zaXRpb25TaXplCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBRBrX3Bvc2l0aW9uTWFyZ2luBQdfdHJhZGVyCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBRZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBQdfdHJhZGVyCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBS5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBQdfdHJhZGVyCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBR5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRUaW1lc3RhbXAFB190cmFkZXIJAJcKBQAAAAAAAAAAAAABEGdldFBvc2l0aW9uQXNzZXQBB190cmFkZXIEEHBvc2l0aW9uQXNzZXRPcHQJAJ0IAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUPa19wb3NpdGlvbkFzc2V0BQdfdHJhZGVyBAckbWF0Y2gwBRBwb3NpdGlvbkFzc2V0T3B0AwkAAQIFByRtYXRjaDACBlN0cmluZwQNcG9zaXRpb25Bc3NldAUHJG1hdGNoMAUNcG9zaXRpb25Bc3NldAkA2AQBCQEKcXVvdGVBc3NldAABDmdldFBvc2l0aW9uRmVlAQdfdHJhZGVyBA5wb3NpdGlvbkZlZU9wdAkAmggCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBQ1rX3Bvc2l0aW9uRmVlBQdfdHJhZGVyBAckbWF0Y2gwBQ5wb3NpdGlvbkZlZU9wdAMJAAECBQckbWF0Y2gwAgNJbnQEC3Bvc2l0aW9uRmVlBQckbWF0Y2gwBQtwb3NpdGlvbkZlZQkBA2ZlZQABE3JlcXVpcmVPcGVuUG9zaXRpb24BB190cmFkZXIDCQAAAggJAQtnZXRQb3NpdGlvbgEFB190cmFkZXICXzEAAAkAAgECEE5vIG9wZW4gcG9zaXRpb24GAQ1nZXRPcmFjbGVEYXRhAQNrZXkEDW9yYWNsZURhdGFTdHIJAJ0IAgUEdGhpcwUDa2V5AwMJAQlpc0RlZmluZWQBBQ1vcmFjbGVEYXRhU3RyCQECIT0CCQEFdmFsdWUBBQ1vcmFjbGVEYXRhU3RyAgAHBApvcmFjbGVEYXRhCQC1CQIJAQV2YWx1ZQEFDW9yYWNsZURhdGFTdHICASwEDW9yYWNsZUFkZHJlc3MJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQCRAwIFCm9yYWNsZURhdGEAAAkArAICAhtJbnZhbGlkIG9yYWNsZSBhZGRyZXNzIGluOiAJAQV2YWx1ZQEFDW9yYWNsZURhdGFTdHIECHByaWNlS2V5CQCRAwIFCm9yYWNsZURhdGEAAQQIYmxvY2tLZXkJAJEDAgUKb3JhY2xlRGF0YQACBAdvcGVuS2V5CQCRAwIFCm9yYWNsZURhdGEAAwkAlgoEBQ1vcmFjbGVBZGRyZXNzBQhwcmljZUtleQUIYmxvY2tLZXkFB29wZW5LZXkFBHVuaXQBC2luaXRpYWxpemVkAAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzBQ1rX2luaXRpYWxpemVkBwEGcGF1c2VkAAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzBQhrX3BhdXNlZAcBCWNsb3NlT25seQAJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhpcwULa19jbG9zZU9ubHkHAQ11cGRhdGVSZXNlcnZlAwZfaXNBZGQRX3F1b3RlQXNzZXRBbW91bnQQX2Jhc2VBc3NldEFtb3VudAMFBl9pc0FkZAQHbmV3QmFzZQkAZQIJAQZic0FzdFIABRBfYmFzZUFzc2V0QW1vdW50AwkAZwIAAAUHbmV3QmFzZQkAAgECKlR4IGxlYWQgdG8gYmFzZSBhc3NldCByZXNlcnZlIDw9IDAsIHJldmVydAkAlQoDCQBkAgkBBnF0QXN0UgAFEV9xdW90ZUFzc2V0QW1vdW50BQduZXdCYXNlCQBkAgkBEXRvdGFsUG9zaXRpb25TaXplAAUQX2Jhc2VBc3NldEFtb3VudAQIbmV3UXVvdGUJAGUCCQEGcXRBc3RSAAURX3F1b3RlQXNzZXRBbW91bnQDCQBnAgAABQhuZXdRdW90ZQkAAgECKlR4IGxlYWQgdG8gYmFzZSBxdW90ZSByZXNlcnZlIDw9IDAsIHJldmVydAkAlQoDBQhuZXdRdW90ZQkAZAIJAQZic0FzdFIABRBfYmFzZUFzc2V0QW1vdW50CQBlAgkBEXRvdGFsUG9zaXRpb25TaXplAAUQX2Jhc2VBc3NldEFtb3VudAENY2FsY0ludmFyaWFudAIHX3F0QXN0UgdfYnNBc3RSBAdicXRBc3RSCQC2AgEFB19xdEFzdFIEB2Jic0FzdFIJALYCAQUHX2JzQXN0UgkBBWJtdWxkAgUHYnF0QXN0UgUHYmJzQXN0UgEJc3dhcElucHV0AgZfaXNBZGQRX3F1b3RlQXNzZXRBbW91bnQEB19xdEFzdFIJAQZxdEFzdFIABAdfYnNBc3RSCQEGYnNBc3RSAAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcABBhxdW90ZUFzc2V0QW1vdW50QWRqdXN0ZWQJAQRkaXZkAgURX3F1b3RlQXNzZXRBbW91bnQFB19xdEFzdFcEAWsJAQ1jYWxjSW52YXJpYW50AgUHX3F0QXN0UgUHX2JzQXN0UgQWcXVvdGVBc3NldFJlc2VydmVBZnRlcgMFBl9pc0FkZAkAZAIFB19xdEFzdFIFGHF1b3RlQXNzZXRBbW91bnRBZGp1c3RlZAkAZQIFB19xdEFzdFIFGHF1b3RlQXNzZXRBbW91bnRBZGp1c3RlZAQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCQCgAwEJAQViZGl2ZAIFAWsJALYCAQUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgQYYW1vdW50QmFzZUFzc2V0Qm91Z2h0QWJzCQEDYWJzAQkAZQIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUHX2JzQXN0UgQVYW1vdW50QmFzZUFzc2V0Qm91Z2h0AwUGX2lzQWRkBRhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMJAQEtAQUYYW1vdW50QmFzZUFzc2V0Qm91Z2h0QWJzBA0kdDAxNjM1MjE2NTIyCQENdXBkYXRlUmVzZXJ2ZQMFBl9pc0FkZAUYcXVvdGVBc3NldEFtb3VudEFkanVzdGVkBRhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMEF3F1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIxCAUNJHQwMTYzNTIxNjUyMgJfMQQWYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyMQgFDSR0MDE2MzUyMTY1MjICXzIEF3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIxCAUNJHQwMTYzNTIxNjUyMgJfMwQLcHJpY2VCZWZvcmUJAQRkaXZkAgkBBG11bGQCBQdfcXRBc3RSBQdfcXRBc3RXCQEEbXVsZAIFB19ic0FzdFIFB19ic0FzdFcEC21hcmtldFByaWNlCQEEZGl2ZAIFEV9xdW90ZUFzc2V0QW1vdW50BRhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMECXByaWNlRGlmZgkBA2FicwEJAGUCBQtwcmljZUJlZm9yZQULbWFya2V0UHJpY2UEC3ByaWNlSW1wYWN0CQBlAgUMREVDSU1BTF9VTklUCQEEZGl2ZAIFC3ByaWNlQmVmb3JlCQBkAgULcHJpY2VCZWZvcmUFCXByaWNlRGlmZgQTbWF4UHJpY2VJbXBhY3RWYWx1ZQkBDm1heFByaWNlSW1wYWN0AAMJAGYCBQtwcmljZUltcGFjdAUTbWF4UHJpY2VJbXBhY3RWYWx1ZQkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgINUHJpY2UgaW1wYWN0IAkApAMBBQtwcmljZUltcGFjdAIUID4gbWF4IHByaWNlIGltcGFjdCAJAKQDAQUTbWF4UHJpY2VJbXBhY3RWYWx1ZQIVIGJlZm9yZSBxdW90ZSBhc3NldDogCQCkAwEFB19xdEFzdFICFCBiZWZvcmUgYmFzZSBhc3NldDogCQCkAwEFB19ic0FzdFICISBxdW90ZSBhc3NldCBhbW91bnQgdG8gZXhjaGFuZ2U6IAkApAMBBRFfcXVvdGVBc3NldEFtb3VudAIPIHByaWNlIGJlZm9yZTogCQCkAwEFC3ByaWNlQmVmb3JlAg4gbWFya2V0UHJpY2U6IAkApAMBBQttYXJrZXRQcmljZQkAlgoEBRVhbW91bnRCYXNlQXNzZXRCb3VnaHQFF3F1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIxBRZiYXNlQXNzZXRSZXNlcnZlQWZ0ZXIxBRd0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyMQEPY2FsY1JvbGxvdmVyRmVlAhJfb2xkUG9zaXRpb25NYXJnaW4gX29sZFBvc2l0aW9uTGFzdFVwZGF0ZWRUaW1lc3RhbXAED3Bvc2l0aW9uTWludXRlcwkAaAIJAGkCCQBpAgkAZQIJAQ1sYXN0VGltZXN0YW1wAAUgX29sZFBvc2l0aW9uTGFzdFVwZGF0ZWRUaW1lc3RhbXAA6AcAPAUMREVDSU1BTF9VTklUBAtyb2xsb3ZlckZlZQkBBGRpdmQCCQEEbXVsZAIJAQRtdWxkAgUSX29sZFBvc2l0aW9uTWFyZ2luBQ9wb3NpdGlvbk1pbnV0ZXMJAQ9yb2xsb3ZlckZlZVJhdGUABQ9NSU5VVEVTX0lOX1lFQVIFC3JvbGxvdmVyRmVlATBjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50QW5kUm9sbG92ZXJGZWUFEF9vbGRQb3NpdGlvblNpemUSX29sZFBvc2l0aW9uTWFyZ2luJV9vbGRQb3NpdGlvbkN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24gX29sZFBvc2l0aW9uTGFzdFVwZGF0ZWRUaW1lc3RhbXAMX21hcmdpbkRlbHRhBA5mdW5kaW5nUGF5bWVudAMJAQIhPQIFEF9vbGRQb3NpdGlvblNpemUAAAQgX2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24JAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUQX29sZFBvc2l0aW9uU2l6ZQkBBG11bGQCCQBlAgUgX2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FJV9vbGRQb3NpdGlvbkN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FEF9vbGRQb3NpdGlvblNpemUAAAQLcm9sbG92ZXJGZWUJAQ9jYWxjUm9sbG92ZXJGZWUCBRJfb2xkUG9zaXRpb25NYXJnaW4FIF9vbGRQb3NpdGlvbkxhc3RVcGRhdGVkVGltZXN0YW1wBAxzaWduZWRNYXJnaW4JAGQCCQBlAgkAZQIFDF9tYXJnaW5EZWx0YQULcm9sbG92ZXJGZWUFDmZ1bmRpbmdQYXltZW50BRJfb2xkUG9zaXRpb25NYXJnaW4EDSR0MDE4Nzc3MTg5MDQDCQBmAgAABQxzaWduZWRNYXJnaW4JAJQKAgAACQEDYWJzAQUMc2lnbmVkTWFyZ2luCQCUCgIJAQNhYnMBBQxzaWduZWRNYXJnaW4AAAQMcmVtYWluTWFyZ2luCAUNJHQwMTg3NzcxODkwNAJfMQQHYmFkRGVidAgFDSR0MDE4Nzc3MTg5MDQCXzIJAJYKBAUMcmVtYWluTWFyZ2luBQdiYWREZWJ0BQ5mdW5kaW5nUGF5bWVudAULcm9sbG92ZXJGZWUBFnN3YXBPdXRwdXRXaXRoUmVzZXJ2ZXMHBl9pc0FkZBBfYmFzZUFzc2V0QW1vdW50FF9jaGVja01heFByaWNlSW1wYWN0El9xdW90ZUFzc2V0UmVzZXJ2ZRFfcXVvdGVBc3NldFdlaWdodBFfYmFzZUFzc2V0UmVzZXJ2ZRBfYmFzZUFzc2V0V2VpZ2h0BAtwcmljZUJlZm9yZQkBBGRpdmQCCQEEbXVsZAIFEl9xdW90ZUFzc2V0UmVzZXJ2ZQURX3F1b3RlQXNzZXRXZWlnaHQJAQRtdWxkAgURX2Jhc2VBc3NldFJlc2VydmUFEF9iYXNlQXNzZXRXZWlnaHQDCQAAAgUQX2Jhc2VBc3NldEFtb3VudAAACQACAQIZSW52YWxpZCBiYXNlIGFzc2V0IGFtb3VudAQBawkBDWNhbGNJbnZhcmlhbnQCBRJfcXVvdGVBc3NldFJlc2VydmUFEV9iYXNlQXNzZXRSZXNlcnZlBBhiYXNlQXNzZXRQb29sQW1vdW50QWZ0ZXIDBQZfaXNBZGQJAGQCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldEFtb3VudAkAZQIFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0QW1vdW50BA9xdW90ZUFzc2V0QWZ0ZXIJAKADAQkBBWJkaXZkAgUBawkAtgIBBRhiYXNlQXNzZXRQb29sQW1vdW50QWZ0ZXIED3F1b3RlQXNzZXREZWx0YQkBA2FicwEJAGUCBQ9xdW90ZUFzc2V0QWZ0ZXIFEl9xdW90ZUFzc2V0UmVzZXJ2ZQQOcXVvdGVBc3NldFNvbGQJAQRtdWxkAgUPcXVvdGVBc3NldERlbHRhBRFfcXVvdGVBc3NldFdlaWdodAQTbWF4UHJpY2VJbXBhY3RWYWx1ZQkBDm1heFByaWNlSW1wYWN0AAQNJHQwMjAxNjYyMDMyOAkBDXVwZGF0ZVJlc2VydmUDCQEBIQEFBl9pc0FkZAUPcXVvdGVBc3NldERlbHRhBRBfYmFzZUFzc2V0QW1vdW50BBdxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyMQgFDSR0MDIwMTY2MjAzMjgCXzEEFmJhc2VBc3NldFJlc2VydmVBZnRlcjEIBQ0kdDAyMDE2NjIwMzI4Al8yBBd0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyMQgFDSR0MDIwMTY2MjAzMjgCXzMEC21hcmtldFByaWNlCQEEZGl2ZAIFDnF1b3RlQXNzZXRTb2xkBRBfYmFzZUFzc2V0QW1vdW50BAlwcmljZURpZmYJAQNhYnMBCQBlAgULcHJpY2VCZWZvcmUFC21hcmtldFByaWNlBAtwcmljZUltcGFjdAkAZQIFDERFQ0lNQUxfVU5JVAkBBGRpdmQCBQtwcmljZUJlZm9yZQkAZAIFC3ByaWNlQmVmb3JlBQlwcmljZURpZmYDAwkAZgIFC3ByaWNlSW1wYWN0BRNtYXhQcmljZUltcGFjdFZhbHVlBRRfY2hlY2tNYXhQcmljZUltcGFjdAcJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICDVByaWNlIGltcGFjdCAJAKQDAQULcHJpY2VJbXBhY3QCFCA+IG1heCBwcmljZSBpbXBhY3QgCQCkAwEFE21heFByaWNlSW1wYWN0VmFsdWUCFSBiZWZvcmUgcXVvdGUgYXNzZXQ6IAkApAMBBRJfcXVvdGVBc3NldFJlc2VydmUCFCBiZWZvcmUgYmFzZSBhc3NldDogCQCkAwEFEV9iYXNlQXNzZXRSZXNlcnZlAiAgYmFzZSBhc3NldCBhbW91bnQgdG8gZXhjaGFuZ2U6IAkApAMBBRBfYmFzZUFzc2V0QW1vdW50Ag8gcHJpY2UgYmVmb3JlOiAJAKQDAQULcHJpY2VCZWZvcmUCDyBtYXJrZXQgcHJpY2U6IAkApAMBBQttYXJrZXRQcmljZQkAmQoHBQ5xdW90ZUFzc2V0U29sZAUXcXVvdGVBc3NldFJlc2VydmVBZnRlcjEFFmJhc2VBc3NldFJlc2VydmVBZnRlcjEFF3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIxCQBlAgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQADBQZfaXNBZGQJAQNhYnMBBRBfYmFzZUFzc2V0QW1vdW50AAAJAGUCCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQADCQEBIQEFBl9pc0FkZAkBA2FicwEFEF9iYXNlQXNzZXRBbW91bnQAAAULcHJpY2VJbXBhY3QBCnN3YXBPdXRwdXQDBl9pc0FkZBBfYmFzZUFzc2V0QW1vdW50FF9jaGVja01heFByaWNlSW1wYWN0CQEWc3dhcE91dHB1dFdpdGhSZXNlcnZlcwcFBl9pc0FkZAUQX2Jhc2VBc3NldEFtb3VudAUUX2NoZWNrTWF4UHJpY2VJbXBhY3QJAQZxdEFzdFIACQEGcXRBc3RXAAkBBmJzQXN0UgAJAQZic0FzdFcAARNnZXRPcmFjbGVQcmljZVZhbHVlAwZvcmFjbGUIcHJpY2VLZXkIYmxvY2tLZXkECWxhc3RWYWx1ZQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFBm9yYWNsZQUIcHJpY2VLZXkJAKwCAgkArAICCQCsAgICIkNhbiBub3QgZ2V0IG9yYWNsZSBwcmljZS4gT3JhY2xlOiAJAKUIAQUGb3JhY2xlAgYga2V5OiAFCHByaWNlS2V5AwkBAiE9AgUIYmxvY2tLZXkCAAQMY3VycmVudEJsb2NrCAUJbGFzdEJsb2NrBmhlaWdodAQPbGFzdE9yYWNsZUJsb2NrCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUGb3JhY2xlBQhibG9ja0tleQkArAICCQCsAgIJAKwCAgIiQ2FuIG5vdCBnZXQgb3JhY2xlIGJsb2NrLiBPcmFjbGU6IAkApQgBBQZvcmFjbGUCBiBrZXk6IAUIYmxvY2tLZXkDCQBmAgkAZQIFDGN1cnJlbnRCbG9jawUPbGFzdE9yYWNsZUJsb2NrCQEObWF4T3JhY2xlRGVsYXkACQACAQkArAICCQCsAgIJAKwCAgImT3JhY2xlIHN0YWxlIGRhdGEuIExhc3Qgb3JhY2xlIGJsb2NrOiAJAKQDAQUPbGFzdE9yYWNsZUJsb2NrAhAgY3VycmVudCBibG9jazogCQCkAwEFDGN1cnJlbnRCbG9jawUJbGFzdFZhbHVlBQlsYXN0VmFsdWUBDmdldE9yYWNsZVByaWNlAAQKYmFzZU9yYWNsZQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQENZ2V0T3JhY2xlRGF0YQEFDGtfYmFzZU9yYWNsZQIZTm8gYmFzZSBhc3NldCBvcmFjbGUgZGF0YQQPYmFzZU9yYWNsZVByaWNlCQETZ2V0T3JhY2xlUHJpY2VWYWx1ZQMIBQpiYXNlT3JhY2xlAl8xCAUKYmFzZU9yYWNsZQJfMggFCmJhc2VPcmFjbGUCXzMEC3F1b3RlT3JhY2xlCQENZ2V0T3JhY2xlRGF0YQEFDWtfcXVvdGVPcmFjbGUEEHF1b3RlT3JhY2xlUHJpY2UDCQEJaXNEZWZpbmVkAQULcXVvdGVPcmFjbGUEDHF1b3RlT3JhY2xlVgkBBXZhbHVlAQULcXVvdGVPcmFjbGUJARNnZXRPcmFjbGVQcmljZVZhbHVlAwgFDHF1b3RlT3JhY2xlVgJfMQgFDHF1b3RlT3JhY2xlVgJfMggFDHF1b3RlT3JhY2xlVgJfMwUMREVDSU1BTF9VTklUCQEEZGl2ZAIFD2Jhc2VPcmFjbGVQcmljZQUQcXVvdGVPcmFjbGVQcmljZQEOaXNNYXJrZXRDbG9zZWQABApiYXNlT3JhY2xlCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAQ1nZXRPcmFjbGVEYXRhAQUMa19iYXNlT3JhY2xlAhlObyBiYXNlIGFzc2V0IG9yYWNsZSBkYXRhBAZvcmFjbGUIBQpiYXNlT3JhY2xlAl8xBAdvcGVuS2V5CAUKYmFzZU9yYWNsZQJfNAMJAQIhPQIFB29wZW5LZXkCAAQGaXNPcGVuCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJsIAgUGb3JhY2xlBQdvcGVuS2V5CQCsAgIJAKwCAgkArAICAitDYW4gbm90IGdldCBvcmFjbGUgaXMgb3Blbi9jbG9zZWQuIE9yYWNsZTogCQClCAEFBm9yYWNsZQIGIGtleTogBQdvcGVuS2V5CQEBIQEFBmlzT3BlbgcBDGFic1ByaWNlRGlmZgUMX29yYWNsZVByaWNlEl9xdW90ZUFzc2V0UmVzZXJ2ZRFfYmFzZUFzc2V0UmVzZXJ2ZQdfcXRBc3RXB19ic0FzdFcECnByaWNlQWZ0ZXIJAQRkaXZkAgkBBG11bGQCBRJfcXVvdGVBc3NldFJlc2VydmUFB19xdEFzdFcJAQRtdWxkAgURX2Jhc2VBc3NldFJlc2VydmUFB19ic0FzdFcEDGF2ZXJhZ2VQcmljZQkBBGRpdmQCCQBkAgUMX29yYWNsZVByaWNlBQpwcmljZUFmdGVyCQBoAgACBQxERUNJTUFMX1VOSVQEDGFic1ByaWNlRGlmZgkBBGRpdmQCCQEDYWJzAQkAZQIFDF9vcmFjbGVQcmljZQUKcHJpY2VBZnRlcgUMYXZlcmFnZVByaWNlBQxhYnNQcmljZURpZmYBGXJlcXVpcmVOb3RPdmVyU3ByZWFkTGltaXQCEl9xdW90ZUFzc2V0UmVzZXJ2ZRFfYmFzZUFzc2V0UmVzZXJ2ZQQLb3JhY2xlUHJpY2UJAQ5nZXRPcmFjbGVQcmljZQAEB19xdEFzdFcJAQZxdEFzdFcABAdfYnNBc3RXCQEGYnNBc3RXAAQSYWJzUHJpY2VEaWZmQmVmb3JlCQEMYWJzUHJpY2VEaWZmBQULb3JhY2xlUHJpY2UJAQZxdEFzdFIACQEGYnNBc3RSAAUHX3F0QXN0VwUHX2JzQXN0VwQRYWJzUHJpY2VEaWZmQWZ0ZXIJAQxhYnNQcmljZURpZmYFBQtvcmFjbGVQcmljZQUSX3F1b3RlQXNzZXRSZXNlcnZlBRFfYmFzZUFzc2V0UmVzZXJ2ZQUHX3F0QXN0VwUHX2JzQXN0VwMDCQBmAgURYWJzUHJpY2VEaWZmQWZ0ZXIJAQ5tYXhQcmljZVNwcmVhZAAJAGYCBRFhYnNQcmljZURpZmZBZnRlcgUSYWJzUHJpY2VEaWZmQmVmb3JlBwkAAgEJAKwCAgkArAICCQCsAgICDVByaWNlIHNwcmVhZCAJAKQDAQURYWJzUHJpY2VEaWZmQWZ0ZXICFCA+IG1heCBwcmljZSBzcHJlYWQgCQCkAwEJAQ5tYXhQcmljZVNwcmVhZAAGAR1yZXF1aXJlTm90T3Zlck1heE9wZW5Ob3Rpb25hbAIRX2xvbmdPcGVuTm90aW9uYWwSX3Nob3J0T3Blbk5vdGlvbmFsBBBfbWF4T3Blbk5vdGlvbmFsCQEPbWF4T3Blbk5vdGlvbmFsAAMJAGYCBRFfbG9uZ09wZW5Ob3Rpb25hbAUQX21heE9wZW5Ob3Rpb25hbAkAAgEJAKwCAgkArAICCQCsAgICE0xvbmcgb3BlbiBub3Rpb25hbCAJAKQDAQURX2xvbmdPcGVuTm90aW9uYWwCFSA+IG1heCBvcGVuIG5vdGlvbmFsIAkApAMBBRBfbWF4T3Blbk5vdGlvbmFsAwkAZgIFEl9zaG9ydE9wZW5Ob3Rpb25hbAUQX21heE9wZW5Ob3Rpb25hbAkAAgEJAKwCAgkArAICCQCsAgICFFNob3J0IG9wZW4gbm90aW9uYWwgCQCkAwEFEl9zaG9ydE9wZW5Ob3Rpb25hbAIVID4gbWF4IG9wZW4gbm90aW9uYWwgCQCkAwEFEF9tYXhPcGVuTm90aW9uYWwGAQxnZXRTcG90UHJpY2UABBJfcXVvdGVBc3NldFJlc2VydmUJAQZxdEFzdFIABBFfYmFzZUFzc2V0UmVzZXJ2ZQkBBmJzQXN0UgAEB19xdEFzdFcJAQZxdEFzdFcABAdfYnNBc3RXCQEGYnNBc3RXAAkBBGRpdmQCCQEEbXVsZAIFEl9xdW90ZUFzc2V0UmVzZXJ2ZQUHX3F0QXN0VwkBBG11bGQCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUHX2JzQXN0VwEWaXNPdmVyRmx1Y3R1YXRpb25MaW1pdAAEC29yYWNsZVByaWNlCQEOZ2V0T3JhY2xlUHJpY2UABAxjdXJyZW50UHJpY2UJAQxnZXRTcG90UHJpY2UACQBmAgkBBGRpdmQCCQEDYWJzAQkAZQIFC29yYWNsZVByaWNlBQxjdXJyZW50UHJpY2UFC29yYWNsZVByaWNlCQELc3ByZWFkTGltaXQAAR9nZXRQb3NpdGlvbkFkanVzdGVkT3Blbk5vdGlvbmFsBg1fcG9zaXRpb25TaXplB19vcHRpb24SX3F1b3RlQXNzZXRSZXNlcnZlEV9xdW90ZUFzc2V0V2VpZ2h0EV9iYXNlQXNzZXRSZXNlcnZlEF9iYXNlQXNzZXRXZWlnaHQED3Bvc2l0aW9uU2l6ZUFicwkBA2FicwEFDV9wb3NpdGlvblNpemUEB2lzU2hvcnQJAGYCAAAFDV9wb3NpdGlvblNpemUEEHBvc2l0aW9uTm90aW9uYWwDCQAAAgUHX29wdGlvbgUPUE5MX09QVElPTl9TUE9UBBNvdXRQb3NpdGlvbk5vdGlvbmFsCAkBFnN3YXBPdXRwdXRXaXRoUmVzZXJ2ZXMHCQEBIQEFB2lzU2hvcnQFD3Bvc2l0aW9uU2l6ZUFicwcFEl9xdW90ZUFzc2V0UmVzZXJ2ZQURX3F1b3RlQXNzZXRXZWlnaHQFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0V2VpZ2h0Al8xBRNvdXRQb3NpdGlvbk5vdGlvbmFsCQEEbXVsZAIFD3Bvc2l0aW9uU2l6ZUFicwkBDmdldE9yYWNsZVByaWNlAAUQcG9zaXRpb25Ob3Rpb25hbAErZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmxCeVZhbHVlcwcNX3Bvc2l0aW9uU2l6ZRVfcG9zaXRpb25PcGVuTm90aW9uYWwSX3F1b3RlQXNzZXRSZXNlcnZlEV9xdW90ZUFzc2V0V2VpZ2h0EV9iYXNlQXNzZXRSZXNlcnZlEF9iYXNlQXNzZXRXZWlnaHQHX29wdGlvbgMJAAACBQ1fcG9zaXRpb25TaXplAAAJAAIBAhVJbnZhbGlkIHBvc2l0aW9uIHNpemUEB2lzU2hvcnQJAGYCAAAFDV9wb3NpdGlvblNpemUEEHBvc2l0aW9uTm90aW9uYWwJAR9nZXRQb3NpdGlvbkFkanVzdGVkT3Blbk5vdGlvbmFsBgUNX3Bvc2l0aW9uU2l6ZQUHX29wdGlvbgUSX3F1b3RlQXNzZXRSZXNlcnZlBRFfcXVvdGVBc3NldFdlaWdodAURX2Jhc2VBc3NldFJlc2VydmUFEF9iYXNlQXNzZXRXZWlnaHQEDXVucmVhbGl6ZWRQbmwDBQdpc1Nob3J0CQBlAgUVX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBRBwb3NpdGlvbk5vdGlvbmFsCQBlAgUQcG9zaXRpb25Ob3Rpb25hbAUVX3Bvc2l0aW9uT3Blbk5vdGlvbmFsCQCUCgIFEHBvc2l0aW9uTm90aW9uYWwFDXVucmVhbGl6ZWRQbmwBI2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sAgdfdHJhZGVyB19vcHRpb24EDSR0MDI4MjA2MjgzMzQJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIEDHBvc2l0aW9uU2l6ZQgFDSR0MDI4MjA2MjgzMzQCXzEEDnBvc2l0aW9uTWFyZ2luCAUNJHQwMjgyMDYyODMzNAJfMgQUcG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDAyODIwNjI4MzM0Al8zBBFwb3NpdGlvbkxzdFVwZENQRggFDSR0MDI4MjA2MjgzMzQCXzQJAStnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubEJ5VmFsdWVzBwUMcG9zaXRpb25TaXplBRRwb3NpdGlvbk9wZW5Ob3Rpb25hbAkBBnF0QXN0UgAJAQZxdEFzdFcACQEGYnNBc3RSAAkBBmJzQXN0VwAFB19vcHRpb24BD2NhbGNNYXJnaW5SYXRpbwMNX3JlbWFpbk1hcmdpbghfYmFkRGVidBFfcG9zaXRpb25Ob3Rpb25hbAkBBGRpdmQCCQBlAgUNX3JlbWFpbk1hcmdpbgUIX2JhZERlYnQFEV9wb3NpdGlvbk5vdGlvbmFsARZnZXRNYXJnaW5SYXRpb0J5T3B0aW9uAgdfdHJhZGVyB19vcHRpb24EDSR0MDI4ODQ5Mjg5OTAJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIEDHBvc2l0aW9uU2l6ZQgFDSR0MDI4ODQ5Mjg5OTACXzEEDnBvc2l0aW9uTWFyZ2luCAUNJHQwMjg4NDkyODk5MAJfMgQDcG9uCAUNJHQwMjg4NDkyODk5MAJfMwQWcG9zaXRpb25MYXN0VXBkYXRlZENQRggFDSR0MDI4ODQ5Mjg5OTACXzQEEXBvc2l0aW9uVGltZXN0YW1wCAUNJHQwMjg4NDkyODk5MAJfNQQNJHQwMjg5OTYyOTA4OQkBI2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sAgUHX3RyYWRlcgUHX29wdGlvbgQQcG9zaXRpb25Ob3Rpb25hbAgFDSR0MDI4OTk2MjkwODkCXzEEDXVucmVhbGl6ZWRQbmwIBQ0kdDAyODk5NjI5MDg5Al8yBA0kdDAyOTA5NDI5MzA2CQEwY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudEFuZFJvbGxvdmVyRmVlBQUMcG9zaXRpb25TaXplBQ5wb3NpdGlvbk1hcmdpbgUWcG9zaXRpb25MYXN0VXBkYXRlZENQRgURcG9zaXRpb25UaW1lc3RhbXAFDXVucmVhbGl6ZWRQbmwEDHJlbWFpbk1hcmdpbggFDSR0MDI5MDk0MjkzMDYCXzEEB2JhZERlYnQIBQ0kdDAyOTA5NDI5MzA2Al8yCQEPY2FsY01hcmdpblJhdGlvAwUMcmVtYWluTWFyZ2luBQdiYWREZWJ0BRBwb3NpdGlvbk5vdGlvbmFsAQ5nZXRNYXJnaW5SYXRpbwEHX3RyYWRlcgkBFmdldE1hcmdpblJhdGlvQnlPcHRpb24CBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QBG2dldFBhcnRpYWxMaXF1aWRhdGlvbkFtb3VudAIHX3RyYWRlcg1fcG9zaXRpb25TaXplBAxtYXhpbXVtUmF0aW8JAQR2bWF4AgkBF3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAAkAZQIFDERFQ0lNQUxfVU5JVAkBBGRpdmQCCQEOZ2V0TWFyZ2luUmF0aW8BBQdfdHJhZGVyCQEWbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwAEGG1heEV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQkBBG11bGQCCQEDYWJzAQUNX3Bvc2l0aW9uU2l6ZQUMbWF4aW11bVJhdGlvBApzd2FwUmVzdWx0CQEKc3dhcE91dHB1dAMJAGYCBQ1fcG9zaXRpb25TaXplAAAFGG1heEV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQcEHG1heEV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQIBQpzd2FwUmVzdWx0Al8xBAtwcmljZUltcGFjdAgFCnN3YXBSZXN1bHQCXzcDCQBmAgkBDm1heFByaWNlSW1wYWN0AAULcHJpY2VJbXBhY3QFGG1heEV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQkBBG11bGQCCQEDYWJzAQUNX3Bvc2l0aW9uU2l6ZQkBF3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAAEVaW50ZXJuYWxDbG9zZVBvc2l0aW9uBwdfdHJhZGVyBV9zaXplBF9mZWUUX21pblF1b3RlQXNzZXRBbW91bnQMX2FkZFRvTWFyZ2luFF9jaGVja01heFByaWNlSW1wYWN0Cl9saXF1aWRhdGUEDSR0MDMwMzczMzA1MjkJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIED29sZFBvc2l0aW9uU2l6ZQgFDSR0MDMwMzczMzA1MjkCXzEEEW9sZFBvc2l0aW9uTWFyZ2luCAUNJHQwMzAzNzMzMDUyOQJfMgQXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDAzMDM3MzMwNTI5Al8zBBRvbGRQb3NpdGlvbkxzdFVwZENQRggFDSR0MDMwMzczMzA1MjkCXzQEFG9sZFBvc2l0aW9uVGltZXN0YW1wCAUNJHQwMzAzNzMzMDUyOQJfNQQOaXNMb25nUG9zaXRpb24JAGYCBQ9vbGRQb3NpdGlvblNpemUAAAQSYWJzT2xkUG9zaXRpb25TaXplCQEDYWJzAQUPb2xkUG9zaXRpb25TaXplAwMJAGcCBRJhYnNPbGRQb3NpdGlvblNpemUFBV9zaXplCQBmAgUFX3NpemUAAAcEDmlzUGFydGlhbENsb3NlCQBmAgUSYWJzT2xkUG9zaXRpb25TaXplBQVfc2l6ZQQNJHQwMzA4MjEzMTI3MgkBCnN3YXBPdXRwdXQDCQBmAgUPb2xkUG9zaXRpb25TaXplAAAFBV9zaXplBRRfY2hlY2tNYXhQcmljZUltcGFjdAQZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAgFDSR0MDMwODIxMzEyNzICXzEEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDAzMDgyMTMxMjcyAl8yBBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDAzMDgyMTMxMjcyAl8zBBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwMzA4MjEzMTI3MgJfNAQVZXhjaGFuZ2VkUG9zaXRpb25TaXplAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAACQEBLQEFBV9zaXplBQVfc2l6ZQQNJHQwMzE0ODczMTY5NAkBI2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sAgUHX3RyYWRlcgUPUE5MX09QVElPTl9TUE9UBBNvbGRQb3NpdGlvbk5vdGlvbmFsCAUNJHQwMzE0ODczMTY5NAJfMQQNdW5yZWFsaXplZFBubAgFDSR0MDMxNDg3MzE2OTQCXzIEDXJlYWxpemVkUmF0aW8JAQRkaXZkAgkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQUSYWJzT2xkUG9zaXRpb25TaXplBAtyZWFsaXplZFBubAkBBG11bGQCBQ11bnJlYWxpemVkUG5sBQ1yZWFsaXplZFJhdGlvBA0kdDAzMjAzNTMyMjgxCQEwY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudEFuZFJvbGxvdmVyRmVlBQUPb2xkUG9zaXRpb25TaXplBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25Mc3RVcGRDUEYFFG9sZFBvc2l0aW9uVGltZXN0YW1wBQ11bnJlYWxpemVkUG5sBBJyZW1haW5NYXJnaW5CZWZvcmUIBQ0kdDAzMjAzNTMyMjgxAl8xBAJ4MQgFDSR0MDMyMDM1MzIyODECXzIEAngyCAUNJHQwMzIwMzUzMjI4MQJfMwQLcm9sbG92ZXJGZWUIBQ0kdDAzMjAzNTMyMjgxAl80BA9wb3NpdGlvbkJhZERlYnQICQEwY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudEFuZFJvbGxvdmVyRmVlBQUPb2xkUG9zaXRpb25TaXplBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25Mc3RVcGRDUEYFFG9sZFBvc2l0aW9uVGltZXN0YW1wBQtyZWFsaXplZFBubAJfMgQQcmVhbGl6ZWRDbG9zZUZlZQkBBG11bGQCCQEEbXVsZAIFE29sZFBvc2l0aW9uTm90aW9uYWwFDXJlYWxpemVkUmF0aW8FBF9mZWUEEnVucmVhbGl6ZWRQbmxBZnRlcgkAZQIFDXVucmVhbGl6ZWRQbmwFC3JlYWxpemVkUG5sBBJyZW1haW5PcGVuTm90aW9uYWwDCQBmAgUPb2xkUG9zaXRpb25TaXplAAAJAGUCCQBlAgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAUSdW5yZWFsaXplZFBubEFmdGVyCQBlAgkAZAIFEnVucmVhbGl6ZWRQbmxBZnRlcgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAQPbmV3UG9zaXRpb25TaXplCQBkAgUPb2xkUG9zaXRpb25TaXplBRVleGNoYW5nZWRQb3NpdGlvblNpemUEDSR0MDMzNjg3MzQwNzMDCQAAAgUPbmV3UG9zaXRpb25TaXplAAAJAJQKAgAAAAAJAJQKAgkBA2FicwEFEnJlbWFpbk9wZW5Ob3Rpb25hbAkBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BBQ9uZXdQb3NpdGlvblNpemUEF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwMzM2ODczNDA3MwJfMQQUbmV3UG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDAzMzY4NzM0MDczAl8yBBFvcGVuTm90aW9uYWxEZWx0YQkAZQIFF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAQLbWFyZ2luUmF0aW8JARZnZXRNYXJnaW5SYXRpb0J5T3B0aW9uAgUHX3RyYWRlcgUPUE5MX09QVElPTl9TUE9UBB5uZXdQb3NpdGlvbk1hcmdpbldpdGhTYW1lUmF0aW8DCQBmAgUPb2xkUG9zaXRpb25TaXplAAAJAGUCCQEEbXVsZAIJAGQCBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUSdW5yZWFsaXplZFBubEFmdGVyBQttYXJnaW5SYXRpbwUSdW5yZWFsaXplZFBubEFmdGVyCQBlAgkBBG11bGQCCQBlAgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFEnVucmVhbGl6ZWRQbmxBZnRlcgULbWFyZ2luUmF0aW8FEnVucmVhbGl6ZWRQbmxBZnRlcgQRbWFyZ2luVG9UcmFkZXJSYXcJAGUCCQBlAgUScmVtYWluTWFyZ2luQmVmb3JlCQBkAgUebmV3UG9zaXRpb25NYXJnaW5XaXRoU2FtZVJhdGlvBRJ1bnJlYWxpemVkUG5sQWZ0ZXIFEHJlYWxpemVkQ2xvc2VGZWUEDm1hcmdpblRvVHJhZGVyAwkAZgIAAAURbWFyZ2luVG9UcmFkZXJSYXcDBQpfbGlxdWlkYXRlAAAJAAIBAjdJbnZhbGlkIGludGVybmFsQ2xvc2VQb3NpdGlvbiBwYXJhbXM6IHVuYWJsZSB0byBwYXkgZmVlBRFtYXJnaW5Ub1RyYWRlclJhdwQRbmV3UG9zaXRpb25NYXJnaW4DBQxfYWRkVG9NYXJnaW4JAGQCBR5uZXdQb3NpdGlvbk1hcmdpbldpdGhTYW1lUmF0aW8FDm1hcmdpblRvVHJhZGVyBR5uZXdQb3NpdGlvbk1hcmdpbldpdGhTYW1lUmF0aW8DAwkBAiE9AgUUX21pblF1b3RlQXNzZXRBbW91bnQAAAkAZgIFFF9taW5RdW90ZUFzc2V0QW1vdW50BRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BwkAAgEJAKwCAgkArAICCQCsAgICDUxpbWl0IGVycm9yOiAJAKQDAQUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAIDIDwgCQCkAwEFFF9taW5RdW90ZUFzc2V0QW1vdW50CQCjChEFD25ld1Bvc2l0aW9uU2l6ZQURbmV3UG9zaXRpb25NYXJnaW4FF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBRRuZXdQb3NpdGlvbkxzdFVwZENQRgUPcG9zaXRpb25CYWREZWJ0BQtyZWFsaXplZFBubAMDBQxfYWRkVG9NYXJnaW4FDmlzUGFydGlhbENsb3NlBwAABQ5tYXJnaW5Ub1RyYWRlcgUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCQBlAgkBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAAURb3Blbk5vdGlvbmFsRGVsdGEJAGUCCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAMFDmlzTG9uZ1Bvc2l0aW9uCQEDYWJzAQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplAAAJAGUCCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQADCQEBIQEFDmlzTG9uZ1Bvc2l0aW9uCQEDYWJzAQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplAAAJAGUCCQEQb3BlbkludGVyZXN0TG9uZwADBQ5pc0xvbmdQb3NpdGlvbgURb3Blbk5vdGlvbmFsRGVsdGEAAAkAZQIJARFvcGVuSW50ZXJlc3RTaG9ydAADCQEBIQEFDmlzTG9uZ1Bvc2l0aW9uBRFvcGVuTm90aW9uYWxEZWx0YQAACQBkAgUQcmVhbGl6ZWRDbG9zZUZlZQULcm9sbG92ZXJGZWUFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQJAAIBCQCsAgIJAKwCAgkArAICAj1JbnZhbGlkIGludGVybmFsQ2xvc2VQb3NpdGlvbiBwYXJhbXM6IGludmFsaWQgcG9zaXRpb24gc2l6ZTogCQCkAwEFBV9zaXplAgYgbWF4OiAJAKQDAQUSYWJzT2xkUG9zaXRpb25TaXplARNnZXRUZXJtaW5hbEFtbVN0YXRlAAQNX3Bvc2l0aW9uU2l6ZQkBEXRvdGFsUG9zaXRpb25TaXplAAMJAAACBQ1fcG9zaXRpb25TaXplAAAJAJQKAgkBBnF0QXN0UgAJAQZic0FzdFIABAlkaXJlY3Rpb24JAGYCBQ1fcG9zaXRpb25TaXplAAAEDSR0MDM3MzA4Mzc0ODcJAQpzd2FwT3V0cHV0AwUJZGlyZWN0aW9uCQEDYWJzAQUNX3Bvc2l0aW9uU2l6ZQcEFWN1cnJlbnROZXRNYXJrZXRWYWx1ZQgFDSR0MDM3MzA4Mzc0ODcCXzEEGXRlcm1pbmFsUXVvdGVBc3NldFJlc2VydmUIBQ0kdDAzNzMwODM3NDg3Al8yBBh0ZXJtaW5hbEJhc2VBc3NldFJlc2VydmUIBQ0kdDAzNzMwODM3NDg3Al8zCQCUCgIFGXRlcm1pbmFsUXVvdGVBc3NldFJlc2VydmUFGHRlcm1pbmFsQmFzZUFzc2V0UmVzZXJ2ZQETZ2V0UXVvdGVBc3NldFdlaWdodAQQYmFzZUFzc2V0UmVzZXJ2ZRF0b3RhbFBvc2l0aW9uU2l6ZRFxdW90ZUFzc2V0UmVzZXJ2ZQt0YXJnZXRQcmljZQQBYgkAtgIBBRBiYXNlQXNzZXRSZXNlcnZlBAJzegkAtgIBBRF0b3RhbFBvc2l0aW9uU2l6ZQQBcQkAtgIBBRFxdW90ZUFzc2V0UmVzZXJ2ZQQBcAkAtgIBBQt0YXJnZXRQcmljZQQBawkBBWJtdWxkAgUBcQUBYgQEbmV3QgkAtwICBQFiBQJzegQEbmV3UQkBBWJkaXZkAgUBawUEbmV3QgQBegkBBWJkaXZkAgUEbmV3UQUEbmV3QgQGcmVzdWx0CQEFYmRpdmQCBQFwBQF6CQCgAwEFBnJlc3VsdAEUZ2V0U3luY1Rlcm1pbmFsUHJpY2UDDl90ZXJtaW5hbFByaWNlB19xdEFzdFIHX2JzQXN0UgQNX3Bvc2l0aW9uU2l6ZQkBEXRvdGFsUG9zaXRpb25TaXplAAMJAAACBQ1fcG9zaXRpb25TaXplAAAECW5ld1F0QXN0VwkBBGRpdmQCCQEEbXVsZAIFDl90ZXJtaW5hbFByaWNlBQdfYnNBc3RSBQdfcXRBc3RSCQCVCgMFCW5ld1F0QXN0VwUMREVDSU1BTF9VTklUAAAECWRpcmVjdGlvbgkAZgIFDV9wb3NpdGlvblNpemUAAAQVY3VycmVudE5ldE1hcmtldFZhbHVlCAkBCnN3YXBPdXRwdXQDBQlkaXJlY3Rpb24JAQNhYnMBBQ1fcG9zaXRpb25TaXplBwJfMQQJbmV3UXRBc3RXCQETZ2V0UXVvdGVBc3NldFdlaWdodAQFB19ic0FzdFIFDV9wb3NpdGlvblNpemUFB19xdEFzdFIFDl90ZXJtaW5hbFByaWNlBAluZXdCc0FzdFcFDERFQ0lNQUxfVU5JVAQNbWFyZ2luVG9WYXVsdAgJAStnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubEJ5VmFsdWVzBwUNX3Bvc2l0aW9uU2l6ZQUVY3VycmVudE5ldE1hcmtldFZhbHVlBQdfcXRBc3RSBQluZXdRdEFzdFcFB19ic0FzdFIFCW5ld0JzQXN0VwUPUE5MX09QVElPTl9TUE9UAl8yCQCVCgMFCW5ld1F0QXN0VwUJbmV3QnNBc3RXBQ1tYXJnaW5Ub1ZhdWx0AQpnZXRGdW5kaW5nAAQPdW5kZXJseWluZ1ByaWNlCQEOZ2V0T3JhY2xlUHJpY2UABA1zcG90VHdhcFByaWNlCQEMZ2V0U3BvdFByaWNlAAQHcHJlbWl1bQkAZQIFDXNwb3RUd2FwUHJpY2UFD3VuZGVybHlpbmdQcmljZQMDAwkAAAIJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAAABgkAAAIJARV0b3RhbExvbmdQb3NpdGlvblNpemUAAAAGCQEOaXNNYXJrZXRDbG9zZWQACQCVCgMAAAAAAAADCQBmAgAABQdwcmVtaXVtBBRzaG9ydFByZW1pdW1GcmFjdGlvbgkBBGRpdmQCCQEEbXVsZAIFB3ByZW1pdW0JARRmdW5kaW5nUGVyaW9kRGVjaW1hbAAFB09ORV9EQVkDCQAAAgkBC2Z1bmRpbmdNb2RlAAUSRlVORElOR19BU1lNTUVUUklDBBNsb25nUHJlbWl1bUZyYWN0aW9uCQEEZGl2ZAIJAQRtdWxkAgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24JARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQAJAJUKAwUUc2hvcnRQcmVtaXVtRnJhY3Rpb24FE2xvbmdQcmVtaXVtRnJhY3Rpb24AAAQZc2hvcnRUb3RhbFByZW1pdW1GcmFjdGlvbgkBA2FicwEJAQRtdWxkAgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24JARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAQYbG9uZ1RvdGFsUHJlbWl1bUZyYWN0aW9uCQEDYWJzAQkBBG11bGQCBRRzaG9ydFByZW1pdW1GcmFjdGlvbgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQAEDnByZW1pdW1Ub1ZhdWx0CQBlAgUZc2hvcnRUb3RhbFByZW1pdW1GcmFjdGlvbgUYbG9uZ1RvdGFsUHJlbWl1bUZyYWN0aW9uCQCVCgMFFHNob3J0UHJlbWl1bUZyYWN0aW9uBRRzaG9ydFByZW1pdW1GcmFjdGlvbgUOcHJlbWl1bVRvVmF1bHQEE2xvbmdQcmVtaXVtRnJhY3Rpb24JAQRkaXZkAgkBBG11bGQCBQdwcmVtaXVtCQEUZnVuZGluZ1BlcmlvZERlY2ltYWwABQdPTkVfREFZAwkAAAIJAQtmdW5kaW5nTW9kZQAFEkZVTkRJTkdfQVNZTU1FVFJJQwQUc2hvcnRQcmVtaXVtRnJhY3Rpb24JAQRkaXZkAgkBBG11bGQCBRNsb25nUHJlbWl1bUZyYWN0aW9uCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUACQCVCgMFFHNob3J0UHJlbWl1bUZyYWN0aW9uBRNsb25nUHJlbWl1bUZyYWN0aW9uAAAEGGxvbmdUb3RhbFByZW1pdW1GcmFjdGlvbgkBA2FicwEJAQRtdWxkAgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQAEGXNob3J0VG90YWxQcmVtaXVtRnJhY3Rpb24JAQNhYnMBCQEEbXVsZAIFE2xvbmdQcmVtaXVtRnJhY3Rpb24JARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAQOcHJlbWl1bVRvVmF1bHQJAGUCBRhsb25nVG90YWxQcmVtaXVtRnJhY3Rpb24FGXNob3J0VG90YWxQcmVtaXVtRnJhY3Rpb24JAJUKAwUTbG9uZ1ByZW1pdW1GcmFjdGlvbgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgUOcHJlbWl1bVRvVmF1bHQBDmdldEFkanVzdGVkRmVlAgtfYXJ0aWZhY3RJZBBfYmFzZUZlZURpc2NvdW50BApiYXNlRmVlUmF3CQEDZmVlAAQHYmFzZUZlZQkBBG11bGQCBQpiYXNlRmVlUmF3BRBfYmFzZUZlZURpc2NvdW50BA0kdDA0MTIyOTQxNzI0AwkBAiE9AgULX2FydGlmYWN0SWQCAAQMYXJ0aWZhY3RLaW5kCQEEc3RyQQIJARFuZnRNYW5hZ2VyQWRkcmVzcwAJAQ50b0NvbXBvc2l0ZUtleQIFDGtfdG9rZW5fdHlwZQULX2FydGlmYWN0SWQDCQAAAgUMYXJ0aWZhY3RLaW5kBRhGRUVfUkVEVUNUSU9OX1RPS0VOX1RZUEUECXJlZHVjdGlvbgkBBGludEECCQERbmZ0TWFuYWdlckFkZHJlc3MACQEOdG9Db21wb3NpdGVLZXkCBQ1rX3Rva2VuX3BhcmFtBQtfYXJ0aWZhY3RJZAQLYWRqdXN0ZWRGZWUJAQRtdWxkAgUHYmFzZUZlZQUJcmVkdWN0aW9uCQCUCgIFC2FkanVzdGVkRmVlBgkAAgECGUludmFsaWQgYXR0YWNoZWQgYXJ0aWZhY3QJAJQKAgUHYmFzZUZlZQcEC2FkanVzdGVkRmVlCAUNJHQwNDEyMjk0MTcyNAJfMQQMYnVybkFydGlmYWN0CAUNJHQwNDEyMjk0MTcyNAJfMgkAlAoCBQthZGp1c3RlZEZlZQUMYnVybkFydGlmYWN0ARdpc1NhbWVBc3NldE9yTm9Qb3NpdGlvbgIHX3RyYWRlcghfYXNzZXRJZAQPb2xkUG9zaXRpb25TaXplCAkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgJfMQMJAAACBQ9vbGRQb3NpdGlvblNpemUAAAYJAAACCQEQZ2V0UG9zaXRpb25Bc3NldAEFB190cmFkZXIFCF9hc3NldElkAQtpc1NhbWVBc3NldAIHX3RyYWRlcghfYXNzZXRJZAkAAAIJARBnZXRQb3NpdGlvbkFzc2V0AQUHX3RyYWRlcgUIX2Fzc2V0SWQBGGdldEZvclRyYWRlcldpdGhBcnRpZmFjdAIHX3RyYWRlcgtfYXJ0aWZhY3RJZAQQZG9HZXRGZWVEaXNjb3VudAkA/AcECQEMbWluZXJBZGRyZXNzAAISY29tcHV0ZUZlZURpc2NvdW50CQDMCAIFB190cmFkZXIFA25pbAUDbmlsAwkAAAIFEGRvR2V0RmVlRGlzY291bnQFEGRvR2V0RmVlRGlzY291bnQEC2ZlZURpc2NvdW50BAckbWF0Y2gwBRBkb0dldEZlZURpc2NvdW50AwkAAQIFByRtYXRjaDACA0ludAQBeAUHJG1hdGNoMAUBeAkAAgECIUludmFsaWQgY29tcHV0ZUZlZURpc2NvdW50IHJlc3VsdAQNJHQwNDI0MDQ0MjQ3OAkBDmdldEFkanVzdGVkRmVlAgULX2FydGlmYWN0SWQFC2ZlZURpc2NvdW50BAthZGp1c3RlZEZlZQgFDSR0MDQyNDA0NDI0NzgCXzEEDGJ1cm5BcnRpZmFjdAgFDSR0MDQyNDA0NDI0NzgCXzIJAJQKAgULYWRqdXN0ZWRGZWUFDGJ1cm5BcnRpZmFjdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgENZ2V0QXJ0aWZhY3RJZAEBaQQKYXJ0aWZhY3RJZAMJAGYCCQCQAwEIBQFpCHBheW1lbnRzAAEJANgEAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCAkAkQMCCAUBaQhwYXltZW50cwABB2Fzc2V0SWQCEkludmFsaWQgYXJ0aWZhY3RJZAIABQphcnRpZmFjdElkAQ1kaXN0cmlidXRlRmVlAQpfZmVlQW1vdW50BAxmZWVUb1N0YWtlcnMJAQRtdWxkAgUKX2ZlZUFtb3VudAkBE2ZlZVRvU3Rha2Vyc1BlcmNlbnQABApmZWVUb1ZhdWx0CQBlAgUKX2ZlZUFtb3VudAUMZmVlVG9TdGFrZXJzCQCUCgIFDGZlZVRvU3Rha2VycwUKZmVlVG9WYXVsdAEOdXBkYXRlU2V0dGluZ3MOEF9pbml0TWFyZ2luUmF0aW8EX21tchRfbGlxdWlkYXRpb25GZWVSYXRpbw5fZnVuZGluZ1BlcmlvZARfZmVlDF9zcHJlYWRMaW1pdA9fbWF4UHJpY2VJbXBhY3QYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvD19tYXhQcmljZVNwcmVhZBBfbWF4T3Blbk5vdGlvbmFsFF9mZWVUb1N0YWtlcnNQZXJjZW50D19tYXhPcmFjbGVEZWxheQxfcm9sbG92ZXJGZWUMX2Z1bmRpbmdNb2RlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRFrX2luaXRNYXJnaW5SYXRpbwUQX2luaXRNYXJnaW5SYXRpbwkAzAgCCQEMSW50ZWdlckVudHJ5AgUYa19tYWludGVuYW5jZU1hcmdpblJhdGlvBQRfbW1yCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRVrX2xpcXVpZGF0aW9uRmVlUmF0aW8FFF9saXF1aWRhdGlvbkZlZVJhdGlvCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ9rX2Z1bmRpbmdQZXJpb2QFDl9mdW5kaW5nUGVyaW9kCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQVrX2ZlZQUEX2ZlZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUNa19zcHJlYWRMaW1pdAUMX3NwcmVhZExpbWl0CQDMCAIJAQxJbnRlZ2VyRW50cnkCBRBrX21heFByaWNlSW1wYWN0BQ9fbWF4UHJpY2VJbXBhY3QJAMwIAgkBDEludGVnZXJFbnRyeQIFGWtfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8FGF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwkAzAgCCQEMSW50ZWdlckVudHJ5AgUQa19tYXhQcmljZVNwcmVhZAUPX21heFByaWNlU3ByZWFkCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRFrX21heE9wZW5Ob3Rpb25hbAUQX21heE9wZW5Ob3Rpb25hbAkAzAgCCQEMSW50ZWdlckVudHJ5AgUVa19mZWVUb1N0YWtlcnNQZXJjZW50BRRfZmVlVG9TdGFrZXJzUGVyY2VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgUQa19tYXhPcmFjbGVEZWxheQUUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQJAMwIAgkBDEludGVnZXJFbnRyeQIFDWtfcm9sbG92ZXJGZWUFDF9yb2xsb3ZlckZlZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUNa19mdW5kaW5nTW9kZQUMX2Z1bmRpbmdNb2RlBQNuaWwBDXVwZGF0ZUZ1bmRpbmcFEV9uZXh0RnVuZGluZ0Jsb2NrJF9sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbiVfbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uEF9sb25nRnVuZGluZ1JhdGURX3Nob3J0RnVuZGluZ1JhdGUJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfbmV4dEZ1bmRpbmdCbG9jawURX25leHRGdW5kaW5nQmxvY2sJAMwIAgkBDEludGVnZXJFbnRyeQIFJWtfbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FJF9sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgUma19sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FJV9sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24JAMwIAgkBDEludGVnZXJFbnRyeQIFEWtfbG9uZ0Z1bmRpbmdSYXRlBRBfbG9uZ0Z1bmRpbmdSYXRlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJrX3Nob3J0RnVuZGluZ1JhdGUFEV9zaG9ydEZ1bmRpbmdSYXRlBQNuaWwBH2luY3JlbWVudFBvc2l0aW9uU2VxdWVuY2VOdW1iZXICDl9pc05ld1Bvc2l0aW9uCF9hZGRyZXNzAwUOX2lzTmV3UG9zaXRpb24ED2N1cnJlbnRTZXF1ZW5jZQkBDGxhc3RTZXF1ZW5jZQAJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFEmtfcG9zaXRpb25TZXF1ZW5jZQUIX2FkZHJlc3MJAGQCBQ9jdXJyZW50U2VxdWVuY2UAAQkAzAgCCQEMSW50ZWdlckVudHJ5AgUKa19zZXF1ZW5jZQkAZAIFD2N1cnJlbnRTZXF1ZW5jZQABBQNuaWwFA25pbAERdXBkYXRlUG9zaXRpb25GZWUDDl9pc05ld1Bvc2l0aW9uCF9hZGRyZXNzBF9mZWUDBQ5faXNOZXdQb3NpdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUNa19wb3NpdGlvbkZlZQUIX2FkZHJlc3MFBF9mZWUFA25pbAUDbmlsAQ51cGRhdGVQb3NpdGlvbgYIX2FkZHJlc3MFX3NpemUHX21hcmdpbg1fb3Blbk5vdGlvbmFsIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uEF9sYXRlc3RUaW1lc3RhbXAJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFDmtfcG9zaXRpb25TaXplBQhfYWRkcmVzcwUFX3NpemUJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFEGtfcG9zaXRpb25NYXJnaW4FCF9hZGRyZXNzBQdfbWFyZ2luCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBQhfYWRkcmVzcwUNX29wZW5Ob3Rpb25hbAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUua19wb3NpdGlvbkxhc3RVcGRhdGVkQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUIX2FkZHJlc3MFIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBR5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRUaW1lc3RhbXAFCF9hZGRyZXNzBRBfbGF0ZXN0VGltZXN0YW1wBQNuaWwBEXVwZGF0ZUFtbVJlc2VydmVzAgdfcXRBc3RSB19ic0FzdFIJAMwIAgkBDEludGVnZXJFbnRyeQIFE2tfcXVvdGVBc3NldFJlc2VydmUFB19xdEFzdFIJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfYmFzZUFzc2V0UmVzZXJ2ZQUHX2JzQXN0UgUDbmlsARB1cGRhdGVBbW1XZWlnaHRzAgdfcXRBc3RXB19ic0FzdFcJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfcXVvdGVBc3NldFdlaWdodAUHX3F0QXN0VwkAzAgCCQEMSW50ZWdlckVudHJ5AgURa19iYXNlQXNzZXRXZWlnaHQFB19ic0FzdFcFA25pbAEJdXBkYXRlQW1tCAdfcXRBc3RSB19ic0FzdFIXX3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIVX29wZW5JbnRlcmVzdE5vdGlvbmFsFl90b3RhbExvbmdQb3NpdGlvblNpemUXX3RvdGFsU2hvcnRQb3NpdGlvblNpemUWX3RvdGFsTG9uZ09wZW5Ob3Rpb25hbBdfdG90YWxTaG9ydE9wZW5Ob3Rpb25hbAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcAAwkBAiE9AgkAZQIFFl90b3RhbExvbmdQb3NpdGlvblNpemUFF190b3RhbFNob3J0UG9zaXRpb25TaXplBRdfdG90YWxQb3NpdGlvblNpemVBZnRlcgkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAhhJbnZhbGlkIEFNTSBzdGF0ZSBkYXRhOiAJAKQDAQUWX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQIEICsgIAkApAMBBRdfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQIEICE9IAkApAMBBRdfdG90YWxQb3NpdGlvblNpemVBZnRlcgkAzggCCQERdXBkYXRlQW1tUmVzZXJ2ZXMCBQdfcXRBc3RSBQdfYnNBc3RSCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRNrX3RvdGFsUG9zaXRpb25TaXplBRdfdG90YWxQb3NpdGlvblNpemVBZnRlcgkAzAgCCQEMSW50ZWdlckVudHJ5AgUWa19vcGVuSW50ZXJlc3ROb3Rpb25hbAUVX29wZW5JbnRlcmVzdE5vdGlvbmFsCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRdrX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQUWX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUYa190b3RhbFNob3J0UG9zaXRpb25TaXplBRdfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUSa19vcGVuSW50ZXJlc3RMb25nBRZfdG90YWxMb25nT3Blbk5vdGlvbmFsCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRNrX29wZW5JbnRlcmVzdFNob3J0BRdfdG90YWxTaG9ydE9wZW5Ob3Rpb25hbAUDbmlsAQ5kZWxldGVQb3NpdGlvbgEIX2FkZHJlc3MJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBDnRvQ29tcG9zaXRlS2V5AgUOa19wb3NpdGlvblNpemUFCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFEGtfcG9zaXRpb25NYXJnaW4FCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFFmtfcG9zaXRpb25PcGVuTm90aW9uYWwFCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFLmtfcG9zaXRpb25MYXN0VXBkYXRlZEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFD2tfcG9zaXRpb25Bc3NldAUIX2FkZHJlc3MJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBDnRvQ29tcG9zaXRlS2V5AgUNa19wb3NpdGlvbkZlZQUIX2FkZHJlc3MJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBDnRvQ29tcG9zaXRlS2V5AgUea19wb3NpdGlvbkxhc3RVcGRhdGVkVGltZXN0YW1wBQhfYWRkcmVzcwUDbmlsAQh3aXRoZHJhdwIIX2FkZHJlc3MHX2Ftb3VudAQHYmFsYW5jZQkA8AcCBQR0aGlzCQEKcXVvdGVBc3NldAADCQBmAgUHX2Ftb3VudAUHYmFsYW5jZQkAAgEJAKwCAgkArAICCQCsAgICE1VuYWJsZSB0byB3aXRoZHJhdyAJAKQDAQUHX2Ftb3VudAIXIGZyb20gY29udHJhY3QgYmFsYW5jZSAJAKQDAQUHYmFsYW5jZQkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQhfYWRkcmVzcwUHX2Ftb3VudAkBCnF1b3RlQXNzZXQABQNuaWwBDXVwZGF0ZUJhbGFuY2UBAWkDCQBmAgAABQFpCQACAQIHQmFsYW5jZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUJa19iYWxhbmNlBQFpBQNuaWwBC3RyYW5zZmVyRmVlAQFpCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMJAQ5zdGFraW5nQWRkcmVzcwAFAWkJAQpxdW90ZUFzc2V0AAUDbmlsAQ5kb0J1cm5BcnRpZmFjdAINX2J1cm5BcnRpZmFjdAFpAwUNX2J1cm5BcnRpZmFjdAkAzAgCCQEEQnVybgIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAggJAJEDAggFAWkIcGF5bWVudHMAAQdhc3NldElkAhBJbnZhbGlkIGFydGlmYWN0AAEFA25pbAUDbmlsFgFpAQVwYXVzZQADCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MACQACAQIUSW52YWxpZCBwYXVzZSBwYXJhbXMJAMwIAgkBDEJvb2xlYW5FbnRyeQIFCGtfcGF1c2VkBgUDbmlsAWkBB3VucGF1c2UAAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECFkludmFsaWQgdW5wYXVzZSBwYXJhbXMJAMwIAgkBDEJvb2xlYW5FbnRyeQIFCGtfcGF1c2VkBwUDbmlsAWkBDHNldENsb3NlT25seQADCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MACQACAQIbSW52YWxpZCBzZXRDbG9zZU9ubHkgcGFyYW1zCQDMCAIJAQxCb29sZWFuRW50cnkCBQtrX2Nsb3NlT25seQYFA25pbAFpAQ51bnNldENsb3NlT25seQADCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MACQACAQIdSW52YWxpZCB1bnNldENsb3NlT25seSBwYXJhbXMJAMwIAgkBDEJvb2xlYW5FbnRyeQIFC2tfY2xvc2VPbmx5BwUDbmlsAWkBDGFkZExpcXVpZGl0eQERX3F1b3RlQXNzZXRBbW91bnQDAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAYJAGcCAAAFEV9xdW90ZUFzc2V0QW1vdW50CQACAQIbSW52YWxpZCBhZGRMaXF1aWRpdHkgcGFyYW1zBAdfcXRBc3RSCQEGcXRBc3RSAAQHX2JzQXN0UgkBBmJzQXN0UgAEB19xdEFzdFcJAQZxdEFzdFcABAdfYnNBc3RXCQEGYnNBc3RXAAQFcHJpY2UJAQRkaXZkAgkBBG11bGQCBQdfcXRBc3RSBQdfcXRBc3RXCQEEbXVsZAIFB19ic0FzdFIFB19ic0FzdFcEC3F0QXN0UkFmdGVyCQBkAgUHX3F0QXN0UgURX3F1b3RlQXNzZXRBbW91bnQEFGJhc2VBc3NldEFtb3VudFRvQWRkCQBlAgkBBGRpdmQCCQEEbXVsZAIFC3F0QXN0UkFmdGVyBQdfcXRBc3RXBQVwcmljZQUHX2JzQXN0UgQLYnNBc3RSQWZ0ZXIJAGQCBQdfYnNBc3RSBRRiYXNlQXNzZXRBbW91bnRUb0FkZAQNJHQwNTA0MzE1MDU4MgkBFGdldFN5bmNUZXJtaW5hbFByaWNlAwkBDmdldE9yYWNsZVByaWNlAAULcXRBc3RSQWZ0ZXIFC2JzQXN0UkFmdGVyBBNuZXdRdW90ZUFzc2V0V2VpZ2h0CAUNJHQwNTA0MzE1MDU4MgJfMQQSbmV3QmFzZUFzc2V0V2VpZ2h0CAUNJHQwNTA0MzE1MDU4MgJfMgQNbWFyZ2luVG9WYXVsdAgFDSR0MDUwNDMxNTA1ODICXzMEDWRvRXhjaGFuZ2VQbkwDCQECIT0CBQ1tYXJnaW5Ub1ZhdWx0AAAEDWRvRXhjaGFuZ2VQbkwJAPwHBAkBDHZhdWx0QWRkcmVzcwACFWV4Y2hhbmdlRnJlZUFuZExvY2tlZAkAzAgCBQ1tYXJnaW5Ub1ZhdWx0BQNuaWwFA25pbAMJAAACBQ1kb0V4Y2hhbmdlUG5MBQ1kb0V4Y2hhbmdlUG5MBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBQ1kb0V4Y2hhbmdlUG5MBQ1kb0V4Y2hhbmdlUG5MCQDOCAIJARF1cGRhdGVBbW1SZXNlcnZlcwIFC3F0QXN0UkFmdGVyBQtic0FzdFJBZnRlcgkBEHVwZGF0ZUFtbVdlaWdodHMCBRNuZXdRdW90ZUFzc2V0V2VpZ2h0BRJuZXdCYXNlQXNzZXRXZWlnaHQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEPcmVtb3ZlTGlxdWlkaXR5ARFfcXVvdGVBc3NldEFtb3VudAMDCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MABgkAZwIFEV9xdW90ZUFzc2V0QW1vdW50AAAJAAIBAh5JbnZhbGlkIHJlbW92ZUxpcXVpZGl0eSBwYXJhbXMEB19xdEFzdFIJAQZxdEFzdFIABAdfYnNBc3RSCQEGYnNBc3RSAAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcABAVwcmljZQkBBGRpdmQCCQEEbXVsZAIFB19xdEFzdFIFB19xdEFzdFcJAQRtdWxkAgUHX2JzQXN0UgUHX2JzQXN0VwQLcXRBc3RSQWZ0ZXIJAGUCBQdfcXRBc3RSBRFfcXVvdGVBc3NldEFtb3VudAQXYmFzZUFzc2V0QW1vdW50VG9SZW1vdmUJAQNhYnMBCQBlAgkBBGRpdmQCCQEEbXVsZAIFC3F0QXN0UkFmdGVyBQdfcXRBc3RXBQVwcmljZQUHX2JzQXN0UgQLYnNBc3RSQWZ0ZXIJAGUCBQdfYnNBc3RSBRdiYXNlQXNzZXRBbW91bnRUb1JlbW92ZQQNJHQwNTE2Nzg1MTgyOQkBFGdldFN5bmNUZXJtaW5hbFByaWNlAwkBDmdldE9yYWNsZVByaWNlAAULcXRBc3RSQWZ0ZXIFC2JzQXN0UkFmdGVyBBNuZXdRdW90ZUFzc2V0V2VpZ2h0CAUNJHQwNTE2Nzg1MTgyOQJfMQQSbmV3QmFzZUFzc2V0V2VpZ2h0CAUNJHQwNTE2Nzg1MTgyOQJfMgQNbWFyZ2luVG9WYXVsdAgFDSR0MDUxNjc4NTE4MjkCXzMEDWRvRXhjaGFuZ2VQbkwDCQECIT0CBQ1tYXJnaW5Ub1ZhdWx0AAAEDWRvRXhjaGFuZ2VQbkwJAPwHBAkBDHZhdWx0QWRkcmVzcwACFWV4Y2hhbmdlRnJlZUFuZExvY2tlZAkAzAgCBQ1tYXJnaW5Ub1ZhdWx0BQNuaWwFA25pbAMJAAACBQ1kb0V4Y2hhbmdlUG5MBQ1kb0V4Y2hhbmdlUG5MBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBQ1kb0V4Y2hhbmdlUG5MBQ1kb0V4Y2hhbmdlUG5MCQDOCAIJARF1cGRhdGVBbW1SZXNlcnZlcwIFC3F0QXN0UkFmdGVyBQtic0FzdFJBZnRlcgkBEHVwZGF0ZUFtbVdlaWdodHMCBRNuZXdRdW90ZUFzc2V0V2VpZ2h0BRJuZXdCYXNlQXNzZXRXZWlnaHQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEOY2hhbmdlU2V0dGluZ3MOEF9pbml0TWFyZ2luUmF0aW8EX21tchRfbGlxdWlkYXRpb25GZWVSYXRpbw5fZnVuZGluZ1BlcmlvZARfZmVlDF9zcHJlYWRMaW1pdA9fbWF4UHJpY2VJbXBhY3QYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvD19tYXhQcmljZVNwcmVhZBBfbWF4T3Blbk5vdGlvbmFsFF9mZWVUb1N0YWtlcnNQZXJjZW50D19tYXhPcmFjbGVEZWxheQxfcm9sbG92ZXJGZWUMX2Z1bmRpbmdNb2RlAwMDAwMDAwMDAwMDAwMDAwMJAGcCAAAFDl9mdW5kaW5nUGVyaW9kBgkAZwIAAAUQX2luaXRNYXJnaW5SYXRpbwYJAGcCAAAFBF9tbXIGCQBnAgAABRRfbGlxdWlkYXRpb25GZWVSYXRpbwYJAGcCAAAFBF9mZWUGCQBnAgAABQxfc3ByZWFkTGltaXQGCQBnAgAABQ9fbWF4UHJpY2VJbXBhY3QGCQBnAgAABRhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8GCQBnAgAABQ9fbWF4UHJpY2VTcHJlYWQGCQBnAgAABRBfbWF4T3Blbk5vdGlvbmFsBgkAZwIAAAUUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQGCQBmAgUUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQFDERFQ0lNQUxfVU5JVAYJAGcCAAAFD19tYXhPcmFjbGVEZWxheQYJAGcCAAAFDF9yb2xsb3ZlckZlZQYDCQECIT0CBQxfZnVuZGluZ01vZGUFEUZVTkRJTkdfU1lNTUVUUklDCQECIT0CBQxfZnVuZGluZ01vZGUFEkZVTkRJTkdfQVNZTU1FVFJJQwcGCQEBIQEJAQtpbml0aWFsaXplZAAGCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MACQACAQIdSW52YWxpZCBjaGFuZ2VTZXR0aW5ncyBwYXJhbXMJAQ51cGRhdGVTZXR0aW5ncw4FEF9pbml0TWFyZ2luUmF0aW8FBF9tbXIFFF9saXF1aWRhdGlvbkZlZVJhdGlvBQ5fZnVuZGluZ1BlcmlvZAUEX2ZlZQUMX3NwcmVhZExpbWl0BQ9fbWF4UHJpY2VJbXBhY3QFGF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwUPX21heFByaWNlU3ByZWFkBRBfbWF4T3Blbk5vdGlvbmFsBRRfZmVlVG9TdGFrZXJzUGVyY2VudAUPX21heE9yYWNsZURlbGF5BQxfcm9sbG92ZXJGZWUFDF9mdW5kaW5nTW9kZQFpAQppbml0aWFsaXplEwdfcXRBc3RSB19ic0FzdFIOX2Z1bmRpbmdQZXJpb2QQX2luaXRNYXJnaW5SYXRpbwRfbW1yFF9saXF1aWRhdGlvbkZlZVJhdGlvBF9mZWUPX2Jhc2VPcmFjbGVEYXRhEF9xdW90ZU9yYWNsZURhdGEMX2Nvb3JkaW5hdG9yDF9zcHJlYWRMaW1pdA9fbWF4UHJpY2VJbXBhY3QYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvD19tYXhQcmljZVNwcmVhZBBfbWF4T3Blbk5vdGlvbmFsFF9mZWVUb1N0YWtlcnNQZXJjZW50D19tYXhPcmFjbGVEZWxheQxfcm9sbG92ZXJGZWUMX2Z1bmRpbmdNb2RlAwMDAwMDAwMDAwMDAwMDAwMDAwkAZwIAAAUHX3F0QXN0UgYJAGcCAAAFB19ic0FzdFIGCQBnAgAABQ5fZnVuZGluZ1BlcmlvZAYJAGcCAAAFEF9pbml0TWFyZ2luUmF0aW8GCQBnAgAABQRfbW1yBgkAZwIAAAUUX2xpcXVpZGF0aW9uRmVlUmF0aW8GCQBnAgAABQRfZmVlBgkAZwIAAAUMX3NwcmVhZExpbWl0BgkAZwIAAAUPX21heFByaWNlSW1wYWN0BgkAZwIAAAUYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvBgkAZwIAAAUPX21heFByaWNlU3ByZWFkBgkAZwIAAAUQX21heE9wZW5Ob3Rpb25hbAYJAGcCAAAFFF9mZWVUb1N0YWtlcnNQZXJjZW50BgkAZgIFFF9mZWVUb1N0YWtlcnNQZXJjZW50BQxERUNJTUFMX1VOSVQGCQBnAgAABQ9fbWF4T3JhY2xlRGVsYXkGCQBnAgAABQxfcm9sbG92ZXJGZWUGAwkBAiE9AgUMX2Z1bmRpbmdNb2RlBRFGVU5ESU5HX1NZTU1FVFJJQwkBAiE9AgUMX2Z1bmRpbmdNb2RlBRJGVU5ESU5HX0FTWU1NRVRSSUMHBgkBC2luaXRpYWxpemVkAAYJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECHUludmFsaWQgaW5pdGlhbGl6ZSBwYXJhbWV0ZXJzCQDOCAIJAM4IAgkAzggCCQDOCAIJAQl1cGRhdGVBbW0IBQdfcXRBc3RSBQdfYnNBc3RSAAAAAAAAAAAAAAAACQEOdXBkYXRlU2V0dGluZ3MOBRBfaW5pdE1hcmdpblJhdGlvBQRfbW1yBRRfbGlxdWlkYXRpb25GZWVSYXRpbwUOX2Z1bmRpbmdQZXJpb2QFBF9mZWUFDF9zcHJlYWRMaW1pdAUPX21heFByaWNlSW1wYWN0BRhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8FD19tYXhQcmljZVNwcmVhZAUQX21heE9wZW5Ob3Rpb25hbAUUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQFD19tYXhPcmFjbGVEZWxheQUMX3JvbGxvdmVyRmVlBQxfZnVuZGluZ01vZGUJAQ11cGRhdGVGdW5kaW5nBQkAZAIJAQ1sYXN0VGltZXN0YW1wAAUOX2Z1bmRpbmdQZXJpb2QAAAAAAAAAAAkBDXVwZGF0ZUJhbGFuY2UBAAAJAMwIAgkBDEJvb2xlYW5FbnRyeQIFDWtfaW5pdGlhbGl6ZWQGCQDMCAIJAQtTdHJpbmdFbnRyeQIFDGtfYmFzZU9yYWNsZQUPX2Jhc2VPcmFjbGVEYXRhCQDMCAIJAQtTdHJpbmdFbnRyeQIFDWtfcXVvdGVPcmFjbGUFEF9xdW90ZU9yYWNsZURhdGEJAMwIAgkBC1N0cmluZ0VudHJ5AgUUa19jb29yZGluYXRvckFkZHJlc3MJAKUIAQkBEUBleHRyTmF0aXZlKDEwNjIpAQUMX2Nvb3JkaW5hdG9yBQNuaWwBaQEQaW5jcmVhc2VQb3NpdGlvbgQKX2RpcmVjdGlvbglfbGV2ZXJhZ2UTX21pbkJhc2VBc3NldEFtb3VudAhfcmVmTGluawQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBBBlbnN1cmVDYWxsZWRPbmNlCQD8BwQFBHRoaXMCEGVuc3VyZUNhbGxlZE9uY2UFA25pbAUDbmlsAwkAAAIFEGVuc3VyZUNhbGxlZE9uY2UFEGVuc3VyZUNhbGxlZE9uY2UEB190cmFkZXIJAQ9nZXRBY3R1YWxDYWxsZXIBBQFpBApfcmF3QW1vdW50CAkAkQMCCAUBaQhwYXltZW50cwAABmFtb3VudAQIX2Fzc2V0SWQICQCRAwIIBQFpCHBheW1lbnRzAAAHYXNzZXRJZAQLX2Fzc2V0SWRTdHIJANgEAQkBBXZhbHVlAQUIX2Fzc2V0SWQEDGlzUXVvdGVBc3NldAkAAAIFCF9hc3NldElkCQEKcXVvdGVBc3NldAADAwMDAwMDAwMDCQECIT0CBQpfZGlyZWN0aW9uBQhESVJfTE9ORwkBAiE9AgUKX2RpcmVjdGlvbgUJRElSX1NIT1JUBwYJAGcCAAAFCl9yYXdBbW91bnQGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEBIQEFDGlzUXVvdGVBc3NldAYJAQEhAQkBF2lzU2FtZUFzc2V0T3JOb1Bvc2l0aW9uAgUHX3RyYWRlcgULX2Fzc2V0SWRTdHIGCQEBIQEJARZyZXF1aXJlTW9yZU1hcmdpblJhdGlvAwkBBGRpdmQCBQxERUNJTUFMX1VOSVQFCV9sZXZlcmFnZQkBD2luaXRNYXJnaW5SYXRpbwAGBgkBBnBhdXNlZAAGCQEJY2xvc2VPbmx5AAYJAQ5pc01hcmtldENsb3NlZAAJAAIBAiNJbnZhbGlkIGluY3JlYXNlUG9zaXRpb24gcGFyYW1ldGVycwQNJHQwNTc5NTM1ODEwMgkBGGdldEZvclRyYWRlcldpdGhBcnRpZmFjdAIFB190cmFkZXIJAQ1nZXRBcnRpZmFjdElkAQUBaQQLYWRqdXN0ZWRGZWUIBQ0kdDA1Nzk1MzU4MTAyAl8xBAxidXJuQXJ0aWZhY3QIBQ0kdDA1Nzk1MzU4MTAyAl8yBAdfYW1vdW50CQEEZGl2ZAIFCl9yYXdBbW91bnQJAGQCCQEEbXVsZAIFC2FkanVzdGVkRmVlBQlfbGV2ZXJhZ2UFDERFQ0lNQUxfVU5JVAQTZGlzdHJpYnV0ZUZlZUFtb3VudAkAZQIFCl9yYXdBbW91bnQFB19hbW91bnQEDnJlZmVycmVyRmVlQW55CQD8BwQJAQ9yZWZlcnJhbEFkZHJlc3MAAhVhY2NlcHRQYXltZW50V2l0aExpbmsJAMwIAgUHX3RyYWRlcgkAzAgCBQhfcmVmTGluawUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFE2Rpc3RyaWJ1dGVGZWVBbW91bnQFA25pbAMJAAACBQ5yZWZlcnJlckZlZUFueQUOcmVmZXJyZXJGZWVBbnkEC3JlZmVycmVyRmVlBAckbWF0Y2gwBQ5yZWZlcnJlckZlZUFueQMJAAECBQckbWF0Y2gwAgNJbnQEAXgFByRtYXRjaDAFAXgJAAIBAhNJbnZhbGlkIHJlZmVycmVyRmVlBAlmZWVBbW91bnQJAGUCBRNkaXN0cmlidXRlRmVlQW1vdW50BQtyZWZlcnJlckZlZQQNJHQwNTg1OTg1ODc2NgkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQPb2xkUG9zaXRpb25TaXplCAUNJHQwNTg1OTg1ODc2NgJfMQQRb2xkUG9zaXRpb25NYXJnaW4IBQ0kdDA1ODU5ODU4NzY2Al8yBBdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDU4NTk4NTg3NjYCXzMEFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwNTg1OTg1ODc2NgJfNAQUb2xkUG9zaXRpb25UaW1lc3RhbXAIBQ0kdDA1ODU5ODU4NzY2Al81BA1pc05ld1Bvc2l0aW9uCQAAAgUPb2xkUG9zaXRpb25TaXplAAAED2lzU2FtZURpcmVjdGlvbgMJAGYCBQ9vbGRQb3NpdGlvblNpemUAAAkAAAIFCl9kaXJlY3Rpb24FCERJUl9MT05HCQAAAgUKX2RpcmVjdGlvbgUJRElSX1NIT1JUBA5leHBhbmRFeGlzdGluZwMJAQEhAQUNaXNOZXdQb3NpdGlvbgUPaXNTYW1lRGlyZWN0aW9uBwQFaXNBZGQJAAACBQpfZGlyZWN0aW9uBQhESVJfTE9ORwQNJHQwNTkwNTU2MjE3NgMDBQ1pc05ld1Bvc2l0aW9uBgUOZXhwYW5kRXhpc3RpbmcEDG9wZW5Ob3Rpb25hbAkBBG11bGQCBQdfYW1vdW50BQlfbGV2ZXJhZ2UEDSR0MDU5NTY0NTk3MzcJAQlzd2FwSW5wdXQCBQVpc0FkZAUMb3Blbk5vdGlvbmFsBBVhbW91bnRCYXNlQXNzZXRCb3VnaHQIBQ0kdDA1OTU2NDU5NzM3Al8xBBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNTk1NjQ1OTczNwJfMgQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNTk1NjQ1OTczNwJfMwQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDU5NTY0NTk3MzcCXzQDAwkBAiE9AgUTX21pbkJhc2VBc3NldEFtb3VudAAACQBmAgUTX21pbkJhc2VBc3NldEFtb3VudAkBA2FicwEFFWFtb3VudEJhc2VBc3NldEJvdWdodAcJAAIBCQCsAgIJAKwCAgkArAICAg1MaW1pdCBlcnJvcjogCQCkAwEJAQNhYnMBBRVhbW91bnRCYXNlQXNzZXRCb3VnaHQCAyA8IAkApAMBBRNfbWluQmFzZUFzc2V0QW1vdW50BA9uZXdQb3NpdGlvblNpemUJAGQCBQ9vbGRQb3NpdGlvblNpemUFFWFtb3VudEJhc2VBc3NldEJvdWdodAQadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIJAGQCCQEQb3BlbkludGVyZXN0TG9uZwADCQBmAgUPbmV3UG9zaXRpb25TaXplAAAFDG9wZW5Ob3Rpb25hbAAABBt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIJAGQCCQERb3BlbkludGVyZXN0U2hvcnQAAwkAZgIAAAUPbmV3UG9zaXRpb25TaXplBQxvcGVuTm90aW9uYWwAAAQNJHQwNjAyODM2MDU1OAkBMGNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnRBbmRSb2xsb3ZlckZlZQUFD29sZFBvc2l0aW9uU2l6ZQURb2xkUG9zaXRpb25NYXJnaW4FFG9sZFBvc2l0aW9uTHN0VXBkQ1BGBRRvbGRQb3NpdGlvblRpbWVzdGFtcAUHX2Ftb3VudAQMcmVtYWluTWFyZ2luCAUNJHQwNjAyODM2MDU1OAJfMQQCeDEIBQ0kdDA2MDI4MzYwNTU4Al8yBAJ4MggFDSR0MDYwMjgzNjA1NTgCXzMEC3JvbGxvdmVyRmVlCAUNJHQwNjAyODM2MDU1OAJfNAMJAQEhAQkBGXJlcXVpcmVOb3RPdmVyU3ByZWFkTGltaXQCBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIJAAIBAhVPdmVyIG1heCBzcHJlYWQgbGltaXQDCQEBIQEJAR1yZXF1aXJlTm90T3Zlck1heE9wZW5Ob3Rpb25hbAIFGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyBRt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIJAAIBAhZPdmVyIG1heCBvcGVuIG5vdGlvbmFsCQCgCg4FD25ld1Bvc2l0aW9uU2l6ZQUMcmVtYWluTWFyZ2luCQBkAgUXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwFDG9wZW5Ob3Rpb25hbAkBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BBQ9uZXdQb3NpdGlvblNpemUJAQ1sYXN0VGltZXN0YW1wAAUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCQBkAgkBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAAUMb3Blbk5vdGlvbmFsCQBkAgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQADCQBmAgUPbmV3UG9zaXRpb25TaXplAAAJAQNhYnMBBRVhbW91bnRCYXNlQXNzZXRCb3VnaHQAAAkAZAIJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAMJAGYCAAAFD25ld1Bvc2l0aW9uU2l6ZQkBA2FicwEFFWFtb3VudEJhc2VBc3NldEJvdWdodAAABRp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgUbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyBQtyb2xsb3ZlckZlZQQMb3Blbk5vdGlvbmFsCQEEbXVsZAIFB19hbW91bnQFCV9sZXZlcmFnZQQNJHQwNjE4NzY2MTk5MgkBI2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sAgkApQgBCAUBaQZjYWxsZXIFD1BOTF9PUFRJT05fU1BPVAQTb2xkUG9zaXRpb25Ob3Rpb25hbAgFDSR0MDYxODc2NjE5OTICXzEEDXVucmVhbGl6ZWRQbmwIBQ0kdDA2MTg3NjYxOTkyAl8yAwkAZgIFE29sZFBvc2l0aW9uTm90aW9uYWwFDG9wZW5Ob3Rpb25hbAkAAgECLlVzZSBkZWNyZWFzZVBvc2l0aW9uIHRvIGRlY3JlYXNlIHBvc2l0aW9uIHNpemUJAAIBAhRDbG9zZSBwb3NpdGlvbiBmaXJzdAQPbmV3UG9zaXRpb25TaXplCAUNJHQwNTkwNTU2MjE3NgJfMQQXbmV3UG9zaXRpb25SZW1haW5NYXJnaW4IBQ0kdDA1OTA1NTYyMTc2Al8yBBduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDU5MDU1NjIxNzYCXzMEFG5ld1Bvc2l0aW9uTGF0ZXN0Q1BGCAUNJHQwNTkwNTU2MjE3NgJfNAQUbmV3UG9zaXRpb25UaW1lc3RhbXAIBQ0kdDA1OTA1NTYyMTc2Al81BBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA1OTA1NTYyMTc2Al82BBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNTkwNTU2MjE3NgJfNwQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDU5MDU1NjIxNzYCXzgEGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIIBQ0kdDA1OTA1NTYyMTc2Al85BA50b3RhbExvbmdBZnRlcggFDSR0MDU5MDU1NjIxNzYDXzEwBA90b3RhbFNob3J0QWZ0ZXIIBQ0kdDA1OTA1NTYyMTc2A18xMQQadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA1OTA1NTYyMTc2A18xMgQbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNTkwNTU2MjE3NgNfMTMEC3JvbGxvdmVyRmVlCAUNJHQwNTkwNTU2MjE3NgNfMTQEDSR0MDYyMTgyNjIyNTMJAQ1kaXN0cmlidXRlRmVlAQkAZAIFCWZlZUFtb3VudAULcm9sbG92ZXJGZWUEDGZlZVRvU3Rha2VycwgFDSR0MDYyMTgyNjIyNTMCXzEECmZlZVRvVmF1bHQIBQ0kdDA2MjE4MjYyMjUzAl8yBAVzdGFrZQMJAGcCBQdfYW1vdW50BQtyb2xsb3ZlckZlZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIJYWRkTG9ja2VkBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAkAZQIFB19hbW91bnQFC3JvbGxvdmVyRmVlBQNuaWwJAPwHBAkBDHZhdWx0QWRkcmVzcwACDndpdGhkcmF3TG9ja2VkCQDMCAIJAGUCBQtyb2xsb3ZlckZlZQUHX2Ftb3VudAUDbmlsBQNuaWwDCQAAAgUFc3Rha2UFBXN0YWtlBAxkZXBvc2l0VmF1bHQJAPwHBAkBDHZhdWx0QWRkcmVzcwACB2FkZEZyZWUFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABQpmZWVUb1ZhdWx0BQNuaWwDCQAAAgUMZGVwb3NpdFZhdWx0BQxkZXBvc2l0VmF1bHQECW5vdGlmeUZlZQkA/AcECQEMbWluZXJBZGRyZXNzAAIKbm90aWZ5RmVlcwkAzAgCBQdfdHJhZGVyCQDMCAIFCWZlZUFtb3VudAUDbmlsBQNuaWwDCQAAAgUJbm90aWZ5RmVlBQlub3RpZnlGZWUEDm5vdGlmeU5vdGlvbmFsCQD8BwQJAQxtaW5lckFkZHJlc3MAAg5ub3RpZnlOb3Rpb25hbAkAzAgCBQdfdHJhZGVyCQDMCAIFF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBQNuaWwFA25pbAMJAAACBQ5ub3RpZnlOb3Rpb25hbAUObm90aWZ5Tm90aW9uYWwJAM4IAgkAzggCCQDOCAIJAM4IAgkAzggCCQDOCAIJAQ51cGRhdGVQb3NpdGlvbgYFB190cmFkZXIFD25ld1Bvc2l0aW9uU2l6ZQUXbmV3UG9zaXRpb25SZW1haW5NYXJnaW4FF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBRRuZXdQb3NpdGlvbkxhdGVzdENQRgUUbmV3UG9zaXRpb25UaW1lc3RhbXAJAR9pbmNyZW1lbnRQb3NpdGlvblNlcXVlbmNlTnVtYmVyAgUNaXNOZXdQb3NpdGlvbgUHX3RyYWRlcgkBEXVwZGF0ZVBvc2l0aW9uRmVlAwUNaXNOZXdQb3NpdGlvbgUHX3RyYWRlcgULYWRqdXN0ZWRGZWUJAQl1cGRhdGVBbW0IBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIFDnRvdGFsTG9uZ0FmdGVyBQ90b3RhbFNob3J0QWZ0ZXIFGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyBRt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIJAQt0cmFuc2ZlckZlZQEFDGZlZVRvU3Rha2VycwkBDXVwZGF0ZUJhbGFuY2UBCQBlAgkAZAIJAQhjYmFsYW5jZQAFB19hbW91bnQFC3JvbGxvdmVyRmVlCQEOZG9CdXJuQXJ0aWZhY3QCBQxidXJuQXJ0aWZhY3QFAWkJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEJYWRkTWFyZ2luAAQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBBBlbnN1cmVDYWxsZWRPbmNlCQD8BwQFBHRoaXMCEGVuc3VyZUNhbGxlZE9uY2UFA25pbAUDbmlsAwkAAAIFEGVuc3VyZUNhbGxlZE9uY2UFEGVuc3VyZUNhbGxlZE9uY2UEB190cmFkZXIJAKUIAQgFAWkGY2FsbGVyBAdfYW1vdW50CAkAkQMCCAUBaQhwYXltZW50cwAABmFtb3VudAQIX2Fzc2V0SWQICQCRAwIIBQFpCHBheW1lbnRzAAAHYXNzZXRJZAQLX2Fzc2V0SWRTdHIJANgEAQkBBXZhbHVlAQUIX2Fzc2V0SWQEDGlzUXVvdGVBc3NldAkAAAIFCF9hc3NldElkCQEKcXVvdGVBc3NldAADAwMDAwMDCQEBIQEFDGlzUXVvdGVBc3NldAYJAQEhAQkBE3JlcXVpcmVPcGVuUG9zaXRpb24BCQClCAEIBQFpBmNhbGxlcgYJAQEhAQkBC2lzU2FtZUFzc2V0AgUHX3RyYWRlcgULX2Fzc2V0SWRTdHIGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAYJAQljbG9zZU9ubHkABgkBDmlzTWFya2V0Q2xvc2VkAAkAAgECHEludmFsaWQgYWRkTWFyZ2luIHBhcmFtZXRlcnMEDSR0MDY0NTEwNjQ2NzgJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIED29sZFBvc2l0aW9uU2l6ZQgFDSR0MDY0NTEwNjQ2NzgCXzEEEW9sZFBvc2l0aW9uTWFyZ2luCAUNJHQwNjQ1MTA2NDY3OAJfMgQXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA2NDUxMDY0Njc4Al8zBBRvbGRQb3NpdGlvbkxzdFVwZENQRggFDSR0MDY0NTEwNjQ2NzgCXzQEFG9sZFBvc2l0aW9uVGltZXN0YW1wCAUNJHQwNjQ1MTA2NDY3OAJfNQQFc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACCWFkZExvY2tlZAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFB19hbW91bnQFA25pbAMJAAACBQVzdGFrZQUFc3Rha2UEC3JvbGxvdmVyRmVlCQEPY2FsY1JvbGxvdmVyRmVlAgURb2xkUG9zaXRpb25NYXJnaW4FFG9sZFBvc2l0aW9uVGltZXN0YW1wBBZkb1RyYW5zZmVyRmVlVG9TdGFrZXJzAwkAZgIFC3JvbGxvdmVyRmVlAAAEDSR0MDY0OTYzNjUwMjIJAQ1kaXN0cmlidXRlRmVlAQULcm9sbG92ZXJGZWUEDGZlZVRvU3Rha2VycwgFDSR0MDY0OTYzNjUwMjICXzEECmZlZVRvVmF1bHQIBQ0kdDA2NDk2MzY1MDIyAl8yBAd1bnN0YWtlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAg53aXRoZHJhd0xvY2tlZAkAzAgCBQxmZWVUb1N0YWtlcnMFA25pbAUDbmlsAwkAAAIFB3Vuc3Rha2UFB3Vuc3Rha2UEC2xvY2tCYWREZWJ0CQD8BwQJAQx2YXVsdEFkZHJlc3MAAhVleGNoYW5nZUZyZWVBbmRMb2NrZWQJAMwIAgkBAS0BBQpmZWVUb1ZhdWx0BQNuaWwFA25pbAMJAAACBQtsb2NrQmFkRGVidAULbG9ja0JhZERlYnQJAQt0cmFuc2ZlckZlZQEFDGZlZVRvU3Rha2VycwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFFmRvVHJhbnNmZXJGZWVUb1N0YWtlcnMFFmRvVHJhbnNmZXJGZWVUb1N0YWtlcnMJAM4IAgkAzggCCQEOdXBkYXRlUG9zaXRpb24GBQdfdHJhZGVyBQ9vbGRQb3NpdGlvblNpemUJAGQCCQBlAgURb2xkUG9zaXRpb25NYXJnaW4FC3JvbGxvdmVyRmVlBQdfYW1vdW50BRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAUUb2xkUG9zaXRpb25Mc3RVcGRDUEYJAQ1sYXN0VGltZXN0YW1wAAkBDXVwZGF0ZUJhbGFuY2UBCQBlAgkAZAIJAQhjYmFsYW5jZQAFB19hbW91bnQFC3JvbGxvdmVyRmVlBRZkb1RyYW5zZmVyRmVlVG9TdGFrZXJzCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDHJlbW92ZU1hcmdpbgEHX2Ftb3VudAQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBBBlbnN1cmVDYWxsZWRPbmNlCQD8BwQFBHRoaXMCEGVuc3VyZUNhbGxlZE9uY2UFA25pbAUDbmlsAwkAAAIFEGVuc3VyZUNhbGxlZE9uY2UFEGVuc3VyZUNhbGxlZE9uY2UEB190cmFkZXIJAKUIAQgFAWkGY2FsbGVyAwMDAwMJAGcCAAAFB19hbW91bnQGCQEBIQEJARNyZXF1aXJlT3BlblBvc2l0aW9uAQUHX3RyYWRlcgYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQZwYXVzZWQABgkBDmlzTWFya2V0Q2xvc2VkAAkAAgECH0ludmFsaWQgcmVtb3ZlTWFyZ2luIHBhcmFtZXRlcnMEDSR0MDY2Mzk1NjY1NjMJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIED29sZFBvc2l0aW9uU2l6ZQgFDSR0MDY2Mzk1NjY1NjMCXzEEEW9sZFBvc2l0aW9uTWFyZ2luCAUNJHQwNjYzOTU2NjU2MwJfMgQXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA2NjM5NTY2NTYzAl8zBBRvbGRQb3NpdGlvbkxzdFVwZENQRggFDSR0MDY2Mzk1NjY1NjMCXzQEFG9sZFBvc2l0aW9uVGltZXN0YW1wCAUNJHQwNjYzOTU2NjU2MwJfNQQNJHQwNjY1Njk2NjgxOAkBMGNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnRBbmRSb2xsb3ZlckZlZQUFD29sZFBvc2l0aW9uU2l6ZQURb2xkUG9zaXRpb25NYXJnaW4FFG9sZFBvc2l0aW9uTHN0VXBkQ1BGBRRvbGRQb3NpdGlvblRpbWVzdGFtcAkBAS0BBQdfYW1vdW50BAxyZW1haW5NYXJnaW4IBQ0kdDA2NjU2OTY2ODE4Al8xBAdiYWREZWJ0CAUNJHQwNjY1Njk2NjgxOAJfMgQOZnVuZGluZ1BheW1lbnQIBQ0kdDA2NjU2OTY2ODE4Al8zBAtyb2xsb3ZlckZlZQgFDSR0MDY2NTY5NjY4MTgCXzQDCQECIT0CBQdiYWREZWJ0AAAJAAIBAh1JbnZhbGlkIHJlbW92ZWQgbWFyZ2luIGFtb3VudAQLbWFyZ2luUmF0aW8JAQ9jYWxjTWFyZ2luUmF0aW8DBQxyZW1haW5NYXJnaW4FB2JhZERlYnQFF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsAwkBASEBCQEWcmVxdWlyZU1vcmVNYXJnaW5SYXRpbwMFC21hcmdpblJhdGlvCQEPaW5pdE1hcmdpblJhdGlvAAYJAAIBCQCsAgIJAKwCAgkArAICAhlUb28gbXVjaCBtYXJnaW4gcmVtb3ZlZDogCQCkAwEFC21hcmdpblJhdGlvAgMgPCAJAKQDAQkBD2luaXRNYXJnaW5SYXRpbwAEDSR0MDY3MjA0NjcyNjMJAQ1kaXN0cmlidXRlRmVlAQULcm9sbG92ZXJGZWUEDGZlZVRvU3Rha2VycwgFDSR0MDY3MjA0NjcyNjMCXzEECmZlZVRvVmF1bHQIBQ0kdDA2NzIwNDY3MjYzAl8yBBZkb1RyYW5zZmVyRmVlVG9TdGFrZXJzAwkAZgIFC3JvbGxvdmVyRmVlAAAEC2xvY2tCYWREZWJ0CQD8BwQJAQx2YXVsdEFkZHJlc3MAAhVleGNoYW5nZUZyZWVBbmRMb2NrZWQJAMwIAgkBAS0BBQpmZWVUb1ZhdWx0BQNuaWwFA25pbAMJAAACBQtsb2NrQmFkRGVidAULbG9ja0JhZERlYnQJAQt0cmFuc2ZlckZlZQEFDGZlZVRvU3Rha2VycwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFFmRvVHJhbnNmZXJGZWVUb1N0YWtlcnMFFmRvVHJhbnNmZXJGZWVUb1N0YWtlcnMEB3Vuc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACDndpdGhkcmF3TG9ja2VkCQDMCAIJAGQCBQdfYW1vdW50BQxmZWVUb1N0YWtlcnMFA25pbAUDbmlsAwkAAAIFB3Vuc3Rha2UFB3Vuc3Rha2UJAM4IAgkAzggCCQDOCAIJAQ51cGRhdGVQb3NpdGlvbgYFB190cmFkZXIFD29sZFBvc2l0aW9uU2l6ZQUMcmVtYWluTWFyZ2luBRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAkBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BBQ9vbGRQb3NpdGlvblNpemUJAQ1sYXN0VGltZXN0YW1wAAkBCHdpdGhkcmF3AggFAWkGY2FsbGVyBQdfYW1vdW50CQENdXBkYXRlQmFsYW5jZQEJAGUCCQBlAgkBCGNiYWxhbmNlAAUHX2Ftb3VudAULcm9sbG92ZXJGZWUFFmRvVHJhbnNmZXJGZWVUb1N0YWtlcnMJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQENY2xvc2VQb3NpdGlvbgMFX3NpemUUX21pblF1b3RlQXNzZXRBbW91bnQMX2FkZFRvTWFyZ2luBARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEEGVuc3VyZUNhbGxlZE9uY2UJAPwHBAUEdGhpcwIQZW5zdXJlQ2FsbGVkT25jZQUDbmlsBQNuaWwDCQAAAgUQZW5zdXJlQ2FsbGVkT25jZQUQZW5zdXJlQ2FsbGVkT25jZQQHX3RyYWRlcgkBD2dldEFjdHVhbENhbGxlcgEFAWkEDl90cmFkZXJBZGRyZXNzCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQUHX3RyYWRlcgIOSW52YWxpZCBjYWxsZXIEC3Bvc2l0aW9uRmVlCQEOZ2V0UG9zaXRpb25GZWUBBQdfdHJhZGVyAwMDAwMDCQEBIQEJARNyZXF1aXJlT3BlblBvc2l0aW9uAQUHX3RyYWRlcgYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQZwYXVzZWQABgkAZwIAAAUFX3NpemUGCQBmAgAABRRfbWluUXVvdGVBc3NldEFtb3VudAYJAQ5pc01hcmtldENsb3NlZAAJAAIBAiBJbnZhbGlkIGNsb3NlUG9zaXRpb24gcGFyYW1ldGVycwQUb2xkUG9zaXRpb25UaW1lc3RhbXAICQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyAl81BA0kdDA2OTQzODcwMDIzCQEVaW50ZXJuYWxDbG9zZVBvc2l0aW9uBwUHX3RyYWRlcgUFX3NpemUFC3Bvc2l0aW9uRmVlBRRfbWluUXVvdGVBc3NldEFtb3VudAUMX2FkZFRvTWFyZ2luBgYED25ld1Bvc2l0aW9uU2l6ZQgFDSR0MDY5NDM4NzAwMjMCXzEEEW5ld1Bvc2l0aW9uTWFyZ2luCAUNJHQwNjk0Mzg3MDAyMwJfMgQXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA2OTQzODcwMDIzAl8zBBRuZXdQb3NpdGlvbkxzdFVwZENQRggFDSR0MDY5NDM4NzAwMjMCXzQED3Bvc2l0aW9uQmFkRGVidAgFDSR0MDY5NDM4NzAwMjMCXzUEC3JlYWxpemVkUG5sCAUNJHQwNjk0Mzg3MDAyMwJfNgQObWFyZ2luVG9UcmFkZXIIBQ0kdDA2OTQzODcwMDIzAl83BBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNjk0Mzg3MDAyMwJfOAQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNjk0Mzg3MDAyMwJfOQQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDY5NDM4NzAwMjMDXzEwBBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCAUNJHQwNjk0Mzg3MDAyMwNfMTEEDnRvdGFsTG9uZ0FmdGVyCAUNJHQwNjk0Mzg3MDAyMwNfMTIED3RvdGFsU2hvcnRBZnRlcggFDSR0MDY5NDM4NzAwMjMDXzEzBBp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDY5NDM4NzAwMjMDXzE0BBt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA2OTQzODcwMDIzA18xNQQLcmVhbGl6ZWRGZWUIBQ0kdDA2OTQzODcwMDIzA18xNgMJAGYCBQ9wb3NpdGlvbkJhZERlYnQAAAkAAgECKkludmFsaWQgY2xvc2VQb3NpdGlvbiBwYXJhbWV0ZXJzOiBiYWQgZGVidAMJAGcCBRRvbGRQb3NpdGlvblRpbWVzdGFtcAkBDWxhc3RUaW1lc3RhbXAACQACAQJTSW52YWxpZCBjbG9zZVBvc2l0aW9uIHBhcmFtZXRlcnM6IHdhaXQgYXQgbGVhc3QgMSBibG9jayBiZWZvcmUgY2xvc2luZyB0aGUgcG9zaXRpb24EDmlzUGFydGlhbENsb3NlCQECIT0CBQ9uZXdQb3NpdGlvblNpemUAAAQOd2l0aGRyYXdBbW91bnQJAGQCBQ5tYXJnaW5Ub1RyYWRlcgULcmVhbGl6ZWRGZWUECmFtbUJhbGFuY2UJAGUCCQEIY2JhbGFuY2UABQ53aXRoZHJhd0Ftb3VudAQNYW1tTmV3QmFsYW5jZQMJAGYCAAAFCmFtbUJhbGFuY2UAAAUKYW1tQmFsYW5jZQQHdW5zdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIOd2l0aGRyYXdMb2NrZWQJAMwIAgUOd2l0aGRyYXdBbW91bnQFA25pbAUDbmlsAwkAAAIFB3Vuc3Rha2UFB3Vuc3Rha2UEDSR0MDcwNjk1NzA3NTQJAQ1kaXN0cmlidXRlRmVlAQULcmVhbGl6ZWRGZWUEDGZlZVRvU3Rha2VycwgFDSR0MDcwNjk1NzA3NTQCXzEECmZlZVRvVmF1bHQIBQ0kdDA3MDY5NTcwNzU0Al8yBAxkZXBvc2l0VmF1bHQJAPwHBAkBDHZhdWx0QWRkcmVzcwACB2FkZEZyZWUFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABQpmZWVUb1ZhdWx0BQNuaWwDCQAAAgUMZGVwb3NpdFZhdWx0BQxkZXBvc2l0VmF1bHQECW5vdGlmeUZlZQkA/AcECQEMbWluZXJBZGRyZXNzAAIKbm90aWZ5RmVlcwkAzAgCBQdfdHJhZGVyCQDMCAIFC3JlYWxpemVkRmVlBQNuaWwFA25pbAMJAAACBQlub3RpZnlGZWUFCW5vdGlmeUZlZQQObm90aWZ5Tm90aW9uYWwJAPwHBAkBDG1pbmVyQWRkcmVzcwACDm5vdGlmeU5vdGlvbmFsCQDMCAIFB190cmFkZXIJAMwIAgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFA25pbAUDbmlsAwkAAAIFDm5vdGlmeU5vdGlvbmFsBQ5ub3RpZnlOb3Rpb25hbAkAzggCCQDOCAIJAM4IAgkAzggCAwUOaXNQYXJ0aWFsQ2xvc2UJAQ51cGRhdGVQb3NpdGlvbgYFB190cmFkZXIFD25ld1Bvc2l0aW9uU2l6ZQURbmV3UG9zaXRpb25NYXJnaW4FF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBRRuZXdQb3NpdGlvbkxzdFVwZENQRgkBDWxhc3RUaW1lc3RhbXAACQEOZGVsZXRlUG9zaXRpb24BBQdfdHJhZGVyCQEJdXBkYXRlQW1tCAUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyBRp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgUbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyAwkAZgIFDm1hcmdpblRvVHJhZGVyAAAJAQh3aXRoZHJhdwIFDl90cmFkZXJBZGRyZXNzBQ5tYXJnaW5Ub1RyYWRlcgUDbmlsCQENdXBkYXRlQmFsYW5jZQEFDWFtbU5ld0JhbGFuY2UJAQt0cmFuc2ZlckZlZQEFDGZlZVRvU3Rha2VycwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQlsaXF1aWRhdGUBB190cmFkZXIEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQPc3BvdE1hcmdpblJhdGlvCQEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAQWbGlxdWlkYXRpb25NYXJnaW5SYXRpbwMJARZpc092ZXJGbHVjdHVhdGlvbkxpbWl0AAQRb3JhY2xlTWFyZ2luUmF0aW8JARZnZXRNYXJnaW5SYXRpb0J5T3B0aW9uAgUHX3RyYWRlcgURUE5MX09QVElPTl9PUkFDTEUJAQR2bWF4AgUPc3BvdE1hcmdpblJhdGlvBRFvcmFjbGVNYXJnaW5SYXRpbwUPc3BvdE1hcmdpblJhdGlvAwMDAwMJAQEhAQkBFnJlcXVpcmVNb3JlTWFyZ2luUmF0aW8DBRZsaXF1aWRhdGlvbk1hcmdpblJhdGlvCQEWbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwAHBgkBASEBCQETcmVxdWlyZU9wZW5Qb3NpdGlvbgEFB190cmFkZXIGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAYJAQ5pc01hcmtldENsb3NlZAAJAAIBAhNVbmFibGUgdG8gbGlxdWlkYXRlBBRpc1BhcnRpYWxMaXF1aWRhdGlvbgMDCQBmAgUPc3BvdE1hcmdpblJhdGlvCQETbGlxdWlkYXRpb25GZWVSYXRpbwAJAGYCCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8AAAAHCQBmAgUMREVDSU1BTF9VTklUCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8ABwQPb2xkUG9zaXRpb25TaXplCAkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgJfMQQPcG9zaXRpb25TaXplQWJzCQEDYWJzAQUPb2xkUG9zaXRpb25TaXplBA0kdDA3MzE3NTczNDk4AwUUaXNQYXJ0aWFsTGlxdWlkYXRpb24ED2xpcXVpZGF0aW9uU2l6ZQkBG2dldFBhcnRpYWxMaXF1aWRhdGlvbkFtb3VudAIFB190cmFkZXIFD29sZFBvc2l0aW9uU2l6ZQQQbGlxdWlkYXRpb25SYXRpbwkBBGRpdmQCCQEDYWJzAQUPbGlxdWlkYXRpb25TaXplBQ9wb3NpdGlvblNpemVBYnMJAJQKAgUQbGlxdWlkYXRpb25SYXRpbwkBA2FicwEFD2xpcXVpZGF0aW9uU2l6ZQkAlAoCAAAFD3Bvc2l0aW9uU2l6ZUFicwQQbGlxdWlkYXRpb25SYXRpbwgFDSR0MDczMTc1NzM0OTgCXzEED2xpcXVpZGF0aW9uU2l6ZQgFDSR0MDczMTc1NzM0OTgCXzIEDSR0MDczNTA0NzQxNDIJARVpbnRlcm5hbENsb3NlUG9zaXRpb24HBQdfdHJhZGVyAwUUaXNQYXJ0aWFsTGlxdWlkYXRpb24FD2xpcXVpZGF0aW9uU2l6ZQUPcG9zaXRpb25TaXplQWJzCQETbGlxdWlkYXRpb25GZWVSYXRpbwAAAAYHBgQPbmV3UG9zaXRpb25TaXplCAUNJHQwNzM1MDQ3NDE0MgJfMQQRbmV3UG9zaXRpb25NYXJnaW4IBQ0kdDA3MzUwNDc0MTQyAl8yBBduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDczNTA0NzQxNDICXzMEFG5ld1Bvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwNzM1MDQ3NDE0MgJfNAQPcG9zaXRpb25CYWREZWJ0CAUNJHQwNzM1MDQ3NDE0MgJfNQQLcmVhbGl6ZWRQbmwIBQ0kdDA3MzUwNDc0MTQyAl82BA5tYXJnaW5Ub1RyYWRlcggFDSR0MDczNTA0NzQxNDICXzcEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA3MzUwNDc0MTQyAl84BBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA3MzUwNDc0MTQyAl85BBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNzM1MDQ3NDE0MgNfMTAEGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIIBQ0kdDA3MzUwNDc0MTQyA18xMQQOdG90YWxMb25nQWZ0ZXIIBQ0kdDA3MzUwNDc0MTQyA18xMgQPdG90YWxTaG9ydEFmdGVyCAUNJHQwNzM1MDQ3NDE0MgNfMTMEGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNzM1MDQ3NDE0MgNfMTQEG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDczNTA0NzQxNDIDXzE1BBJsaXF1aWRhdGlvblBlbmFsdHkIBQ0kdDA3MzUwNDc0MTQyA18xNgQPZmVlVG9MaXF1aWRhdG9yCQBpAgUSbGlxdWlkYXRpb25QZW5hbHR5AAIECmZlZVRvVmF1bHQJAGUCBRJsaXF1aWRhdGlvblBlbmFsdHkFD2ZlZVRvTGlxdWlkYXRvcgQKYW1tQmFsYW5jZQkAZQIJAQhjYmFsYW5jZQAFEmxpcXVpZGF0aW9uUGVuYWx0eQQNbmV3QW1tQmFsYW5jZQMJAGYCAAAFCmFtbUJhbGFuY2UAAAUKYW1tQmFsYW5jZQQLbG9ja0JhZERlYnQDCQBmAgUPcG9zaXRpb25CYWREZWJ0AAAEC2xvY2tCYWREZWJ0CQD8BwQJAQx2YXVsdEFkZHJlc3MAAhVleGNoYW5nZUZyZWVBbmRMb2NrZWQJAMwIAgkAZAIFD3Bvc2l0aW9uQmFkRGVidAUSbGlxdWlkYXRpb25QZW5hbHR5BQNuaWwFA25pbAMJAAACBQtsb2NrQmFkRGVidAULbG9ja0JhZERlYnQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFC2xvY2tCYWREZWJ0BQtsb2NrQmFkRGVidAQHdW5zdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIOd2l0aGRyYXdMb2NrZWQJAMwIAgUSbGlxdWlkYXRpb25QZW5hbHR5BQNuaWwFA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlBBBkZXBvc2l0SW5zdXJhbmNlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAgdhZGRGcmVlBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUKZmVlVG9WYXVsdAUDbmlsAwkAAAIFEGRlcG9zaXRJbnN1cmFuY2UFEGRlcG9zaXRJbnN1cmFuY2UEDm5vdGlmeU5vdGlvbmFsCQD8BwQJAQxtaW5lckFkZHJlc3MAAg5ub3RpZnlOb3Rpb25hbAkAzAgCBQdfdHJhZGVyCQDMCAIFF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBQNuaWwFA25pbAMJAAACBQ5ub3RpZnlOb3Rpb25hbAUObm90aWZ5Tm90aW9uYWwJAM4IAgkAzggCCQDOCAIDBRRpc1BhcnRpYWxMaXF1aWRhdGlvbgkBDnVwZGF0ZVBvc2l0aW9uBgUHX3RyYWRlcgUPbmV3UG9zaXRpb25TaXplBRFuZXdQb3NpdGlvbk1hcmdpbgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFFG5ld1Bvc2l0aW9uTHN0VXBkQ1BGCQENbGFzdFRpbWVzdGFtcAAJAQ5kZWxldGVQb3NpdGlvbgEFB190cmFkZXIJAQl1cGRhdGVBbW0IBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIFDnRvdGFsTG9uZ0FmdGVyBQ90b3RhbFNob3J0QWZ0ZXIFGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyBRt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIJAQh3aXRoZHJhdwIIBQFpBmNhbGxlcgUPZmVlVG9MaXF1aWRhdG9yCQENdXBkYXRlQmFsYW5jZQEFDW5ld0FtbUJhbGFuY2UJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEKcGF5RnVuZGluZwAEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQVZnVuZGluZ0Jsb2NrVGltZXN0YW1wCQEZbmV4dEZ1bmRpbmdCbG9ja1RpbWVzdGFtcAADAwMJAGYCBRVmdW5kaW5nQmxvY2tUaW1lc3RhbXAJAQ1sYXN0VGltZXN0YW1wAAYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQZwYXVzZWQACQACAQkArAICCQCsAgIJAKwCAgIhSW52YWxpZCBmdW5kaW5nIGJsb2NrIHRpbWVzdGFtcDogCQCkAwEJAQ1sYXN0VGltZXN0YW1wAAIDIDwgCQCkAwEFFWZ1bmRpbmdCbG9ja1RpbWVzdGFtcAQPdW5kZXJseWluZ1ByaWNlCQEOZ2V0T3JhY2xlUHJpY2UABA0kdDA3NjI1NTc2MzMzCQEKZ2V0RnVuZGluZwAEFHNob3J0UHJlbWl1bUZyYWN0aW9uCAUNJHQwNzYyNTU3NjMzMwJfMQQTbG9uZ1ByZW1pdW1GcmFjdGlvbggFDSR0MDc2MjU1NzYzMzMCXzIEDnByZW1pdW1Ub1ZhdWx0CAUNJHQwNzYyNTU3NjMzMwJfMwQTZG9QYXlGdW5kaW5nVG9WYXVsdAMJAGYCBQ5wcmVtaXVtVG9WYXVsdAAABBNkb1BheUZ1bmRpbmdUb1ZhdWx0CQD8BwQJAQx2YXVsdEFkZHJlc3MAAhVleGNoYW5nZUZyZWVBbmRMb2NrZWQJAMwIAgkBAS0BBQ5wcmVtaXVtVG9WYXVsdAUDbmlsBQNuaWwDCQAAAgUTZG9QYXlGdW5kaW5nVG9WYXVsdAUTZG9QYXlGdW5kaW5nVG9WYXVsdAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUTZG9QYXlGdW5kaW5nVG9WYXVsdAUTZG9QYXlGdW5kaW5nVG9WYXVsdAkBDXVwZGF0ZUZ1bmRpbmcFCQBkAgUVZnVuZGluZ0Jsb2NrVGltZXN0YW1wCQEUZnVuZGluZ1BlcmlvZFNlY29uZHMACQBkAgkBI2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAUTbG9uZ1ByZW1pdW1GcmFjdGlvbgkAZAIJASRsYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24ABRRzaG9ydFByZW1pdW1GcmFjdGlvbgkBBGRpdmQCBRNsb25nUHJlbWl1bUZyYWN0aW9uBQ91bmRlcmx5aW5nUHJpY2UJAQRkaXZkAgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24FD3VuZGVybHlpbmdQcmljZQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlAAQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABA0kdDA3NzM4NDc3NzUwCQEUZ2V0U3luY1Rlcm1pbmFsUHJpY2UDCQEOZ2V0T3JhY2xlUHJpY2UABQdfcXRBc3RSBQdfYnNBc3RSBBNuZXdRdW90ZUFzc2V0V2VpZ2h0CAUNJHQwNzczODQ3Nzc1MAJfMQQSbmV3QmFzZUFzc2V0V2VpZ2h0CAUNJHQwNzczODQ3Nzc1MAJfMgQNbWFyZ2luVG9WYXVsdAgFDSR0MDc3Mzg0Nzc3NTACXzMEEG1hcmdpblRvVmF1bHRBZGoDAwkAZgIAAAUNbWFyZ2luVG9WYXVsdAkAZgIJAQNhYnMBBQ1tYXJnaW5Ub1ZhdWx0CQEIY2JhbGFuY2UABwkBAS0BCQEIY2JhbGFuY2UABQ1tYXJnaW5Ub1ZhdWx0BA1kb0V4Y2hhbmdlUG5MAwkBAiE9AgUQbWFyZ2luVG9WYXVsdEFkagAABA1kb0V4Y2hhbmdlUG5MCQD8BwQJAQx2YXVsdEFkZHJlc3MAAhVleGNoYW5nZUZyZWVBbmRMb2NrZWQJAMwIAgUQbWFyZ2luVG9WYXVsdEFkagUDbmlsBQNuaWwDCQAAAgUNZG9FeGNoYW5nZVBuTAUNZG9FeGNoYW5nZVBuTAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUNZG9FeGNoYW5nZVBuTAUNZG9FeGNoYW5nZVBuTAkAzggCCQENdXBkYXRlQmFsYW5jZQEJAGQCCQEIY2JhbGFuY2UABRBtYXJnaW5Ub1ZhdWx0QWRqCQEQdXBkYXRlQW1tV2VpZ2h0cwIFE25ld1F1b3RlQXNzZXRXZWlnaHQFEm5ld0Jhc2VBc3NldFdlaWdodAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARBlbnN1cmVDYWxsZWRPbmNlAAMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECIkludmFsaWQgc2F2ZUN1cnJlbnRUeElkIHBhcmFtZXRlcnMEBmxhc3RUeAkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzBQhrX2xhc3RUeAIAAwkBAiE9AgUGbGFzdFR4CQDYBAEIBQFpDXRyYW5zYWN0aW9uSWQJAMwIAgkBC1N0cmluZ0VudHJ5AgUIa19sYXN0VHgFBmxhc3RUeAUDbmlsCQACAQIpQ2FuIG5vdCBjYWxsIHZBTU0gbWV0aG9kcyB0d2ljZSBpbiBvbmUgdHgBaQEndmlld19jYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50AQdfdHJhZGVyBARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEDSR0MDc5Mjk5Nzk0MjMJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIEDHBvc2l0aW9uU2l6ZQgFDSR0MDc5Mjk5Nzk0MjMCXzEEDnBvc2l0aW9uTWFyZ2luCAUNJHQwNzkyOTk3OTQyMwJfMgQDcG9uCAUNJHQwNzkyOTk3OTQyMwJfMwQRcG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA3OTI5OTc5NDIzAl80BBFwb3NpdGlvblRpbWVzdGFtcAgFDSR0MDc5Mjk5Nzk0MjMCXzUEDSR0MDc5NDI2Nzk1MjcJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAQQcG9zaXRpb25Ob3Rpb25hbAgFDSR0MDc5NDI2Nzk1MjcCXzEEDXVucmVhbGl6ZWRQbmwIBQ0kdDA3OTQyNjc5NTI3Al8yBA0kdDA3OTUzMDc5NzU0CQEwY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudEFuZFJvbGxvdmVyRmVlBQUMcG9zaXRpb25TaXplBQ5wb3NpdGlvbk1hcmdpbgURcG9zaXRpb25Mc3RVcGRDUEYFEXBvc2l0aW9uVGltZXN0YW1wBQ11bnJlYWxpemVkUG5sBAxyZW1haW5NYXJnaW4IBQ0kdDA3OTUzMDc5NzU0Al8xBAdiYWREZWJ0CAUNJHQwNzk1MzA3OTc1NAJfMgQOZnVuZGluZ1BheW1lbnQIBQ0kdDA3OTUzMDc5NzU0Al8zBAtyb2xsb3ZlckZlZQgFDSR0MDc5NTMwNzk3NTQCXzQJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQEBcwEFDHJlbWFpbk1hcmdpbgkBAXMBBQ5mdW5kaW5nUGF5bWVudAkBAXMBCQEOZ2V0TWFyZ2luUmF0aW8BBQdfdHJhZGVyCQEBcwEFDXVucmVhbGl6ZWRQbmwJAQFzAQUHYmFkRGVidAkBAXMBBRBwb3NpdGlvbk5vdGlvbmFsCQEBcwEFC3JvbGxvdmVyRmVlCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBFXZpZXdfZ2V0UGVnQWRqdXN0Q29zdAEGX3ByaWNlBAdfcXRBc3RSCQEGcXRBc3RSAAQHX2JzQXN0UgkBBmJzQXN0UgAEBnJlc3VsdAkBFGdldFN5bmNUZXJtaW5hbFByaWNlAwUGX3ByaWNlBQdfcXRBc3RSBQdfYnNBc3RSCQACAQkApAMBCAUGcmVzdWx0Al8zAWkBGHZpZXdfZ2V0VGVybWluYWxBbW1QcmljZQAEDSR0MDgwNDc3ODA1NTgJARNnZXRUZXJtaW5hbEFtbVN0YXRlAAQZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQgFDSR0MDgwNDc3ODA1NTgCXzEEGHRlcm1pbmFsQmFzZUFzc2V0UmVzZXJ2ZQgFDSR0MDgwNDc3ODA1NTgCXzIEBXByaWNlCQEEZGl2ZAIJAQRtdWxkAgUZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQkBBnF0QXN0VwAJAQRtdWxkAgUYdGVybWluYWxCYXNlQXNzZXRSZXNlcnZlCQEGYnNBc3RXAAkAAgEJAKQDAQUFcHJpY2UBaQEPdmlld19nZXRGdW5kaW5nAAQPdW5kZXJseWluZ1ByaWNlCQEOZ2V0T3JhY2xlUHJpY2UABA0kdDA4MTA2NzgxMTQ1CQEKZ2V0RnVuZGluZwAEFHNob3J0UHJlbWl1bUZyYWN0aW9uCAUNJHQwODEwNjc4MTE0NQJfMQQTbG9uZ1ByZW1pdW1GcmFjdGlvbggFDSR0MDgxMDY3ODExNDUCXzIEDnByZW1pdW1Ub1ZhdWx0CAUNJHQwODEwNjc4MTE0NQJfMwQLbG9uZ0Z1bmRpbmcJAQRkaXZkAgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgUPdW5kZXJseWluZ1ByaWNlBAxzaG9ydEZ1bmRpbmcJAQRkaXZkAgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24FD3VuZGVybHlpbmdQcmljZQkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkBAXMBBQtsb25nRnVuZGluZwkBAXMBBQxzaG9ydEZ1bmRpbmcJAQFzAQkBDGdldFNwb3RQcmljZQAJAQFzAQkBDmdldE9yYWNsZVByaWNlAAkBAXMBBQ5wcmVtaXVtVG9WYXVsdAFpARBjb21wdXRlU3BvdFByaWNlAAQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBAZyZXN1bHQJAQxnZXRTcG90UHJpY2UACQCUCgIFA25pbAUGcmVzdWx0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBH2NvbXB1dGVGZWVGb3JUcmFkZXJXaXRoQXJ0aWZhY3QCB190cmFkZXILX2FydGlmYWN0SWQEBnJlc3VsdAkBGGdldEZvclRyYWRlcldpdGhBcnRpZmFjdAIFB190cmFkZXIFC19hcnRpZmFjdElkCQCUCgIFA25pbAUGcmVzdWx0AQJ0eAEGdmVyaWZ5AAQOY29vcmRpbmF0b3JTdHIJAJ0IAgUEdGhpcwUUa19jb29yZGluYXRvckFkZHJlc3MDCQEJaXNEZWZpbmVkAQUOY29vcmRpbmF0b3JTdHIEBWFkbWluCQCdCAIJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQV2YWx1ZQEFDmNvb3JkaW5hdG9yU3RyBQ9rX2FkbWluX2FkZHJlc3MDCQEJaXNEZWZpbmVkAQUFYWRtaW4JAQt2YWx1ZU9yRWxzZQIJAJsIAgkBEUBleHRyTmF0aXZlKDEwNjIpAQkBBXZhbHVlAQUFYWRtaW4JAKwCAgkArAICCQCsAgICB3N0YXR1c18JAKUIAQUEdGhpcwIBXwkA2AQBCAUCdHgCaWQHCQACAQIudW5hYmxlIHRvIHZlcmlmeTogYWRtaW4gbm90IHNldCBpbiBjb29yZGluYXRvcgkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAgFAnR4D3NlbmRlclB1YmxpY0tleWuClq8=", "height": 3522005, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 6oyZkWv6X64TquwgupLg8v5M4D5pnLKsMkmzuxhgECqA Next: 8Yh9T1szbjqTtyABoj2MjSd8RNkAmnxQ7XoKH27cBqTU Diff:
OldNewDifferences
5858 let k_maxOracleDelay = "k_maxOracleDelay"
5959
6060 let k_fundingMode = "k_fundingMode"
61-
62-let k_lastDataStr = "k_lastDataStr"
63-
64-let k_lastMinuteId = "k_lastMinuteId"
65-
66-let k_twapDataLastCumulativePrice = "k_twapDataLastCumulativePrice"
67-
68-let k_twapDataLastPrice = "k_twapDataLastPrice"
69-
70-let k_twapDataPreviousMinuteId = "k_twapDataPreviousMinuteId"
7161
7262 let k_latestLongCumulativePremiumFraction = "k_latestLongPremiumFraction"
7363
465455 let amountBaseAssetBought = if (_isAdd)
466456 then amountBaseAssetBoughtAbs
467457 else -(amountBaseAssetBoughtAbs)
468- let $t01694317113 = updateReserve(_isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
469- let quoteAssetReserveAfter1 = $t01694317113._1
470- let baseAssetReserveAfter1 = $t01694317113._2
471- let totalPositionSizeAfter1 = $t01694317113._3
458+ let $t01635216522 = updateReserve(_isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
459+ let quoteAssetReserveAfter1 = $t01635216522._1
460+ let baseAssetReserveAfter1 = $t01635216522._2
461+ let totalPositionSizeAfter1 = $t01635216522._3
472462 let priceBefore = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
473463 let marketPrice = divd(_quoteAssetAmount, amountBaseAssetBoughtAbs)
474464 let priceDiff = abs((priceBefore - marketPrice))
496486 else 0
497487 let rolloverFee = calcRolloverFee(_oldPositionMargin, _oldPositionLastUpdatedTimestamp)
498488 let signedMargin = (((_marginDelta - rolloverFee) - fundingPayment) + _oldPositionMargin)
499- let $t01936819495 = if ((0 > signedMargin))
489+ let $t01877718904 = if ((0 > signedMargin))
500490 then $Tuple2(0, abs(signedMargin))
501491 else $Tuple2(abs(signedMargin), 0)
502- let remainMargin = $t01936819495._1
503- let badDebt = $t01936819495._2
492+ let remainMargin = $t01877718904._1
493+ let badDebt = $t01877718904._2
504494 $Tuple4(remainMargin, badDebt, fundingPayment, rolloverFee)
505495 }
506496
518508 let quoteAssetDelta = abs((quoteAssetAfter - _quoteAssetReserve))
519509 let quoteAssetSold = muld(quoteAssetDelta, _quoteAssetWeight)
520510 let maxPriceImpactValue = maxPriceImpact()
521- let $t02075720919 = updateReserve(!(_isAdd), quoteAssetDelta, _baseAssetAmount)
522- let quoteAssetReserveAfter1 = $t02075720919._1
523- let baseAssetReserveAfter1 = $t02075720919._2
524- let totalPositionSizeAfter1 = $t02075720919._3
511+ let $t02016620328 = updateReserve(!(_isAdd), quoteAssetDelta, _baseAssetAmount)
512+ let quoteAssetReserveAfter1 = $t02016620328._1
513+ let baseAssetReserveAfter1 = $t02016620328._2
514+ let totalPositionSizeAfter1 = $t02016620328._3
525515 let marketPrice = divd(quoteAssetSold, _baseAssetAmount)
526516 let priceDiff = abs((priceBefore - marketPrice))
527517 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
656646
657647
658648 func getPositionNotionalAndUnrealizedPnl (_trader,_option) = {
659- let $t02879728925 = getPosition(_trader)
660- let positionSize = $t02879728925._1
661- let positionMargin = $t02879728925._2
662- let positionOpenNotional = $t02879728925._3
663- let positionLstUpdCPF = $t02879728925._4
649+ let $t02820628334 = getPosition(_trader)
650+ let positionSize = $t02820628334._1
651+ let positionMargin = $t02820628334._2
652+ let positionOpenNotional = $t02820628334._3
653+ let positionLstUpdCPF = $t02820628334._4
664654 getPositionNotionalAndUnrealizedPnlByValues(positionSize, positionOpenNotional, qtAstR(), qtAstW(), bsAstR(), bsAstW(), _option)
665655 }
666656
669659
670660
671661 func getMarginRatioByOption (_trader,_option) = {
672- let $t02944029581 = getPosition(_trader)
673- let positionSize = $t02944029581._1
674- let positionMargin = $t02944029581._2
675- let pon = $t02944029581._3
676- let positionLastUpdatedCPF = $t02944029581._4
677- let positionTimestamp = $t02944029581._5
678- let $t02958729680 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
679- let positionNotional = $t02958729680._1
680- let unrealizedPnl = $t02958729680._2
681- let $t02968529897 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLastUpdatedCPF, positionTimestamp, unrealizedPnl)
682- let remainMargin = $t02968529897._1
683- let badDebt = $t02968529897._2
662+ let $t02884928990 = getPosition(_trader)
663+ let positionSize = $t02884928990._1
664+ let positionMargin = $t02884928990._2
665+ let pon = $t02884928990._3
666+ let positionLastUpdatedCPF = $t02884928990._4
667+ let positionTimestamp = $t02884928990._5
668+ let $t02899629089 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
669+ let positionNotional = $t02899629089._1
670+ let unrealizedPnl = $t02899629089._2
671+ let $t02909429306 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLastUpdatedCPF, positionTimestamp, unrealizedPnl)
672+ let remainMargin = $t02909429306._1
673+ let badDebt = $t02909429306._2
684674 calcMarginRatio(remainMargin, badDebt, positionNotional)
685675 }
686676
701691
702692
703693 func internalClosePosition (_trader,_size,_fee,_minQuoteAssetAmount,_addToMargin,_checkMaxPriceImpact,_liquidate) = {
704- let $t03096431120 = getPosition(_trader)
705- let oldPositionSize = $t03096431120._1
706- let oldPositionMargin = $t03096431120._2
707- let oldPositionOpenNotional = $t03096431120._3
708- let oldPositionLstUpdCPF = $t03096431120._4
709- let oldPositionTimestamp = $t03096431120._5
694+ let $t03037330529 = getPosition(_trader)
695+ let oldPositionSize = $t03037330529._1
696+ let oldPositionMargin = $t03037330529._2
697+ let oldPositionOpenNotional = $t03037330529._3
698+ let oldPositionLstUpdCPF = $t03037330529._4
699+ let oldPositionTimestamp = $t03037330529._5
710700 let isLongPosition = (oldPositionSize > 0)
711701 let absOldPositionSize = abs(oldPositionSize)
712702 if (if ((absOldPositionSize >= _size))
714704 else false)
715705 then {
716706 let isPartialClose = (absOldPositionSize > _size)
717- let $t03141231863 = swapOutput((oldPositionSize > 0), _size, _checkMaxPriceImpact)
718- let exchangedQuoteAssetAmount = $t03141231863._1
719- let quoteAssetReserveAfter = $t03141231863._2
720- let baseAssetReserveAfter = $t03141231863._3
721- let totalPositionSizeAfter = $t03141231863._4
707+ let $t03082131272 = swapOutput((oldPositionSize > 0), _size, _checkMaxPriceImpact)
708+ let exchangedQuoteAssetAmount = $t03082131272._1
709+ let quoteAssetReserveAfter = $t03082131272._2
710+ let baseAssetReserveAfter = $t03082131272._3
711+ let totalPositionSizeAfter = $t03082131272._4
722712 let exchangedPositionSize = if ((oldPositionSize > 0))
723713 then -(_size)
724714 else _size
725- let $t03207832285 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
726- let oldPositionNotional = $t03207832285._1
727- let unrealizedPnl = $t03207832285._2
715+ let $t03148731694 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
716+ let oldPositionNotional = $t03148731694._1
717+ let unrealizedPnl = $t03148731694._2
728718 let realizedRatio = divd(abs(exchangedPositionSize), absOldPositionSize)
729719 let realizedPnl = muld(unrealizedPnl, realizedRatio)
730- let $t03262632872 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, unrealizedPnl)
731- let remainMarginBefore = $t03262632872._1
732- let x1 = $t03262632872._2
733- let x2 = $t03262632872._3
734- let rolloverFee = $t03262632872._4
720+ let $t03203532281 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, unrealizedPnl)
721+ let remainMarginBefore = $t03203532281._1
722+ let x1 = $t03203532281._2
723+ let x2 = $t03203532281._3
724+ let rolloverFee = $t03203532281._4
735725 let positionBadDebt = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, realizedPnl)._2
736726 let realizedCloseFee = muld(muld(oldPositionNotional, realizedRatio), _fee)
737727 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
739729 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
740730 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
741731 let newPositionSize = (oldPositionSize + exchangedPositionSize)
742- let $t03427834664 = if ((newPositionSize == 0))
732+ let $t03368734073 = if ((newPositionSize == 0))
743733 then $Tuple2(0, 0)
744734 else $Tuple2(abs(remainOpenNotional), latestCumulativePremiumFraction(newPositionSize))
745- let newPositionOpenNotional = $t03427834664._1
746- let newPositionLstUpdCPF = $t03427834664._2
735+ let newPositionOpenNotional = $t03368734073._1
736+ let newPositionLstUpdCPF = $t03368734073._2
747737 let openNotionalDelta = (oldPositionOpenNotional - newPositionOpenNotional)
748738 let marginRatio = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
749739 let newPositionMarginWithSameRatio = if ((oldPositionSize > 0))
780770 }
781771
782772
783-func getTwapSpotPrice () = {
784- let minuteId = ((lastTimestamp() / 1000) / 60)
785- let startMinuteId = (minuteId - TWAP_INTERVAL)
786- let listStr = valueOrElse(getString(this, k_lastDataStr), "")
787- let list = split(listStr, ",")
788- func filterFn (accumulator,next) = if ((startMinuteId >= valueOrErrorMessage(parseInt(next), ("getTwapSpotPrice: invalid int: " + listStr))))
789- then (accumulator :+ parseIntValue(next))
790- else accumulator
791-
792- let listF = {
793- let $l = list
794- let $s = size($l)
795- let $acc0 = nil
796- func $f0_1 ($a,$i) = if (($i >= $s))
797- then $a
798- else filterFn($a, $l[$i])
799-
800- func $f0_2 ($a,$i) = if (($i >= $s))
801- then $a
802- else throw("List size exceeds 20")
803-
804- $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20)
805- }
806- let maxIndex = if ((size(listF) > 0))
807- then max(listF)
808- else valueOrErrorMessage(parseInt(list[0]), ("getTwapSpotPrice: invalid int: " + listStr))
809- let lastMinuteId = valueOrElse(getInteger(this, k_lastMinuteId), 0)
810- let endLastCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(lastMinuteId))), 0)
811- let endLastPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(lastMinuteId))), 0)
812- let nowCumulativePrice = (endLastCumulativePrice + ((minuteId - lastMinuteId) * endLastPrice))
813- let startLastCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(maxIndex))), 0)
814- let startLastPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(maxIndex))), 0)
815- let startCumulativePrice = (startLastCumulativePrice + ((startMinuteId - maxIndex) * startLastPrice))
816- ((nowCumulativePrice - startCumulativePrice) / TWAP_INTERVAL)
817- }
818-
819-
820773 func getTerminalAmmState () = {
821774 let _positionSize = totalPositionSize()
822775 if ((_positionSize == 0))
823776 then $Tuple2(qtAstR(), bsAstR())
824777 else {
825778 let direction = (_positionSize > 0)
826- let $t03940139580 = swapOutput(direction, abs(_positionSize), false)
827- let currentNetMarketValue = $t03940139580._1
828- let terminalQuoteAssetReserve = $t03940139580._2
829- let terminalBaseAssetReserve = $t03940139580._3
779+ let $t03730837487 = swapOutput(direction, abs(_positionSize), false)
780+ let currentNetMarketValue = $t03730837487._1
781+ let terminalQuoteAssetReserve = $t03730837487._2
782+ let terminalBaseAssetReserve = $t03730837487._3
830783 $Tuple2(terminalQuoteAssetReserve, terminalBaseAssetReserve)
831784 }
832785 }
866819
867820 func getFunding () = {
868821 let underlyingPrice = getOraclePrice()
869- let spotTwapPrice = getTwapSpotPrice()
822+ let spotTwapPrice = getSpotPrice()
870823 let premium = (spotTwapPrice - underlyingPrice)
871824 if (if (if ((totalShortPositionSize() == 0))
872825 then true
909862 func getAdjustedFee (_artifactId,_baseFeeDiscount) = {
910863 let baseFeeRaw = fee()
911864 let baseFee = muld(baseFeeRaw, _baseFeeDiscount)
912- let $t04332643821 = if ((_artifactId != ""))
865+ let $t04122941724 = if ((_artifactId != ""))
913866 then {
914867 let artifactKind = strA(nftManagerAddress(), toCompositeKey(k_token_type, _artifactId))
915868 if ((artifactKind == FEE_REDUCTION_TOKEN_TYPE))
921874 else throw("Invalid attached artifact")
922875 }
923876 else $Tuple2(baseFee, false)
924- let adjustedFee = $t04332643821._1
925- let burnArtifact = $t04332643821._2
877+ let adjustedFee = $t04122941724._1
878+ let burnArtifact = $t04122941724._2
926879 $Tuple2(adjustedFee, burnArtifact)
927880 }
928881
948901 case _ =>
949902 throw("Invalid computeFeeDiscount result")
950903 }
951- let $t04450144575 = getAdjustedFee(_artifactId, feeDiscount)
952- let adjustedFee = $t04450144575._1
953- let burnArtifact = $t04450144575._2
904+ let $t04240442478 = getAdjustedFee(_artifactId, feeDiscount)
905+ let adjustedFee = $t04240442478._1
906+ let burnArtifact = $t04240442478._2
954907 $Tuple2(adjustedFee, burnArtifact)
955908 }
956909 else throw("Strict value is not equal to itself.")
994947 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)]
995948
996949
997-func appendTwap (_price) = {
998- let minuteId = ((lastTimestamp() / 1000) / 60)
999- let previousMinuteId = valueOrElse(getInteger(this, k_lastMinuteId), 0)
1000- if ((previousMinuteId > minuteId))
1001- then throw("TWAP out-of-order")
1002- else {
1003- let lastMinuteId = if ((previousMinuteId == 0))
1004- then minuteId
1005- else previousMinuteId
1006- if ((minuteId > previousMinuteId))
1007- then {
1008- let prevCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(previousMinuteId))), 0)
1009- let prevPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(previousMinuteId))), _price)
1010- let lastCumulativePrice = (prevCumulativePrice + ((minuteId - lastMinuteId) * prevPrice))
1011- let list = pushToQueue(strToList(valueOrElse(getString(this, k_lastDataStr), "")), TWAP_INTERVAL, toString(minuteId))
1012-[IntegerEntry(toCompositeKey(k_twapDataLastCumulativePrice, toString(minuteId)), lastCumulativePrice), IntegerEntry(toCompositeKey(k_twapDataLastPrice, toString(minuteId)), _price), IntegerEntry(toCompositeKey(k_twapDataPreviousMinuteId, toString(minuteId)), previousMinuteId), IntegerEntry(k_lastMinuteId, minuteId), StringEntry(k_lastDataStr, listToStr(list))]
1013- }
1014- else {
1015- let twapDataPreviousMinuteId = valueOrElse(getInteger(this, toCompositeKey(k_twapDataPreviousMinuteId, toString(minuteId))), 0)
1016- let prevCumulativePrice = valueOrElse(getInteger(this, toCompositeKey(k_twapDataLastCumulativePrice, toString(twapDataPreviousMinuteId))), 0)
1017- let prevPrice = valueOrElse(getInteger(this, toCompositeKey(k_twapDataLastPrice, toString(twapDataPreviousMinuteId))), _price)
1018- let lastCumulativePrice = (prevCumulativePrice + ((minuteId - twapDataPreviousMinuteId) * prevPrice))
1019-[IntegerEntry(toCompositeKey(k_twapDataLastCumulativePrice, toString(minuteId)), lastCumulativePrice), IntegerEntry(toCompositeKey(k_twapDataLastPrice, toString(minuteId)), _price)]
1020- }
1021- }
1022- }
1023-
1024-
1025950 func updateAmmReserves (_qtAstR,_bsAstR) = [IntegerEntry(k_quoteAssetReserve, _qtAstR), IntegerEntry(k_baseAssetReserve, _bsAstR)]
1026951
1027952
1033958 let _bsAstW = bsAstW()
1034959 if (((_totalLongPositionSize - _totalShortPositionSize) != _totalPositionSizeAfter))
1035960 then throw(((((("Invalid AMM state data: " + toString(_totalLongPositionSize)) + " + ") + toString(_totalShortPositionSize)) + " != ") + toString(_totalPositionSizeAfter)))
1036- 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)]) ++ appendTwap(divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))))
961+ 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)])
1037962 }
1038963
1039964
11031028 let qtAstRAfter = (_qtAstR + _quoteAssetAmount)
11041029 let baseAssetAmountToAdd = (divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR)
11051030 let bsAstRAfter = (_bsAstR + baseAssetAmountToAdd)
1106- let $t05479454945 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1107- let newQuoteAssetWeight = $t05479454945._1
1108- let newBaseAssetWeight = $t05479454945._2
1109- let marginToVault = $t05479454945._3
1031+ let $t05043150582 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1032+ let newQuoteAssetWeight = $t05043150582._1
1033+ let newBaseAssetWeight = $t05043150582._2
1034+ let marginToVault = $t05043150582._3
11101035 let doExchangePnL = if ((marginToVault != 0))
11111036 then {
11121037 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
11361061 let qtAstRAfter = (_qtAstR - _quoteAssetAmount)
11371062 let baseAssetAmountToRemove = abs((divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR))
11381063 let bsAstRAfter = (_bsAstR - baseAssetAmountToRemove)
1139- let $t05604156192 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1140- let newQuoteAssetWeight = $t05604156192._1
1141- let newBaseAssetWeight = $t05604156192._2
1142- let marginToVault = $t05604156192._3
1064+ let $t05167851829 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1065+ let newQuoteAssetWeight = $t05167851829._1
1066+ let newBaseAssetWeight = $t05167851829._2
1067+ let marginToVault = $t05167851829._3
11431068 let doExchangePnL = if ((marginToVault != 0))
11441069 then {
11451070 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
12751200 else isMarketClosed())
12761201 then throw("Invalid increasePosition parameters")
12771202 else {
1278- let $t06231662465 = getForTraderWithArtifact(_trader, getArtifactId(i))
1279- let adjustedFee = $t06231662465._1
1280- let burnArtifact = $t06231662465._2
1203+ let $t05795358102 = getForTraderWithArtifact(_trader, getArtifactId(i))
1204+ let adjustedFee = $t05795358102._1
1205+ let burnArtifact = $t05795358102._2
12811206 let _amount = divd(_rawAmount, (muld(adjustedFee, _leverage) + DECIMAL_UNIT))
12821207 let distributeFeeAmount = (_rawAmount - _amount)
12831208 let referrerFeeAny = invoke(referralAddress(), "acceptPaymentWithLink", [_trader, _refLink], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
12901215 throw("Invalid referrerFee")
12911216 }
12921217 let feeAmount = (distributeFeeAmount - referrerFee)
1293- let $t06296163129 = getPosition(_trader)
1294- let oldPositionSize = $t06296163129._1
1295- let oldPositionMargin = $t06296163129._2
1296- let oldPositionOpenNotional = $t06296163129._3
1297- let oldPositionLstUpdCPF = $t06296163129._4
1298- let oldPositionTimestamp = $t06296163129._5
1218+ let $t05859858766 = getPosition(_trader)
1219+ let oldPositionSize = $t05859858766._1
1220+ let oldPositionMargin = $t05859858766._2
1221+ let oldPositionOpenNotional = $t05859858766._3
1222+ let oldPositionLstUpdCPF = $t05859858766._4
1223+ let oldPositionTimestamp = $t05859858766._5
12991224 let isNewPosition = (oldPositionSize == 0)
13001225 let isSameDirection = if ((oldPositionSize > 0))
13011226 then (_direction == DIR_LONG)
13041229 then isSameDirection
13051230 else false
13061231 let isAdd = (_direction == DIR_LONG)
1307- let $t06341866539 = if (if (isNewPosition)
1232+ let $t05905562176 = if (if (isNewPosition)
13081233 then true
13091234 else expandExisting)
13101235 then {
13111236 let openNotional = muld(_amount, _leverage)
1312- let $t06392764100 = swapInput(isAdd, openNotional)
1313- let amountBaseAssetBought = $t06392764100._1
1314- let quoteAssetReserveAfter = $t06392764100._2
1315- let baseAssetReserveAfter = $t06392764100._3
1316- let totalPositionSizeAfter = $t06392764100._4
1237+ let $t05956459737 = swapInput(isAdd, openNotional)
1238+ let amountBaseAssetBought = $t05956459737._1
1239+ let quoteAssetReserveAfter = $t05956459737._2
1240+ let baseAssetReserveAfter = $t05956459737._3
1241+ let totalPositionSizeAfter = $t05956459737._4
13171242 if (if ((_minBaseAssetAmount != 0))
13181243 then (_minBaseAssetAmount > abs(amountBaseAssetBought))
13191244 else false)
13261251 let totalShortOpenInterestAfter = (openInterestShort() + (if ((0 > newPositionSize))
13271252 then openNotional
13281253 else 0))
1329- let $t06464664921 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, _amount)
1330- let remainMargin = $t06464664921._1
1331- let x1 = $t06464664921._2
1332- let x2 = $t06464664921._3
1333- let rolloverFee = $t06464664921._4
1254+ let $t06028360558 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, _amount)
1255+ let remainMargin = $t06028360558._1
1256+ let x1 = $t06028360558._2
1257+ let x2 = $t06028360558._3
1258+ let rolloverFee = $t06028360558._4
13341259 if (!(requireNotOverSpreadLimit(quoteAssetReserveAfter, baseAssetReserveAfter)))
13351260 then throw("Over max spread limit")
13361261 else if (!(requireNotOverMaxOpenNotional(totalLongOpenInterestAfter, totalShortOpenInterestAfter)))
13441269 }
13451270 else {
13461271 let openNotional = muld(_amount, _leverage)
1347- let $t06623966355 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1348- let oldPositionNotional = $t06623966355._1
1349- let unrealizedPnl = $t06623966355._2
1272+ let $t06187661992 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1273+ let oldPositionNotional = $t06187661992._1
1274+ let unrealizedPnl = $t06187661992._2
13501275 if ((oldPositionNotional > openNotional))
13511276 then throw("Use decreasePosition to decrease position size")
13521277 else throw("Close position first")
13531278 }
1354- let newPositionSize = $t06341866539._1
1355- let newPositionRemainMargin = $t06341866539._2
1356- let newPositionOpenNotional = $t06341866539._3
1357- let newPositionLatestCPF = $t06341866539._4
1358- let newPositionTimestamp = $t06341866539._5
1359- let baseAssetReserveAfter = $t06341866539._6
1360- let quoteAssetReserveAfter = $t06341866539._7
1361- let totalPositionSizeAfter = $t06341866539._8
1362- let openInterestNotionalAfter = $t06341866539._9
1363- let totalLongAfter = $t06341866539._10
1364- let totalShortAfter = $t06341866539._11
1365- let totalLongOpenInterestAfter = $t06341866539._12
1366- let totalShortOpenInterestAfter = $t06341866539._13
1367- let rolloverFee = $t06341866539._14
1368- let $t06654566616 = distributeFee((feeAmount + rolloverFee))
1369- let feeToStakers = $t06654566616._1
1370- let feeToVault = $t06654566616._2
1279+ let newPositionSize = $t05905562176._1
1280+ let newPositionRemainMargin = $t05905562176._2
1281+ let newPositionOpenNotional = $t05905562176._3
1282+ let newPositionLatestCPF = $t05905562176._4
1283+ let newPositionTimestamp = $t05905562176._5
1284+ let baseAssetReserveAfter = $t05905562176._6
1285+ let quoteAssetReserveAfter = $t05905562176._7
1286+ let totalPositionSizeAfter = $t05905562176._8
1287+ let openInterestNotionalAfter = $t05905562176._9
1288+ let totalLongAfter = $t05905562176._10
1289+ let totalShortAfter = $t05905562176._11
1290+ let totalLongOpenInterestAfter = $t05905562176._12
1291+ let totalShortOpenInterestAfter = $t05905562176._13
1292+ let rolloverFee = $t05905562176._14
1293+ let $t06218262253 = distributeFee((feeAmount + rolloverFee))
1294+ let feeToStakers = $t06218262253._1
1295+ let feeToVault = $t06218262253._2
13711296 let stake = if ((_amount >= rolloverFee))
13721297 then invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), (_amount - rolloverFee))])
13731298 else invoke(vaultAddress(), "withdrawLocked", [(rolloverFee - _amount)], nil)
14281353 else isMarketClosed())
14291354 then throw("Invalid addMargin parameters")
14301355 else {
1431- let $t06887369041 = getPosition(_trader)
1432- let oldPositionSize = $t06887369041._1
1433- let oldPositionMargin = $t06887369041._2
1434- let oldPositionOpenNotional = $t06887369041._3
1435- let oldPositionLstUpdCPF = $t06887369041._4
1436- let oldPositionTimestamp = $t06887369041._5
1356+ let $t06451064678 = getPosition(_trader)
1357+ let oldPositionSize = $t06451064678._1
1358+ let oldPositionMargin = $t06451064678._2
1359+ let oldPositionOpenNotional = $t06451064678._3
1360+ let oldPositionLstUpdCPF = $t06451064678._4
1361+ let oldPositionTimestamp = $t06451064678._5
14371362 let stake = invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), _amount)])
14381363 if ((stake == stake))
14391364 then {
14401365 let rolloverFee = calcRolloverFee(oldPositionMargin, oldPositionTimestamp)
14411366 let doTransferFeeToStakers = if ((rolloverFee > 0))
14421367 then {
1443- let $t06932669385 = distributeFee(rolloverFee)
1444- let feeToStakers = $t06932669385._1
1445- let feeToVault = $t06932669385._2
1368+ let $t06496365022 = distributeFee(rolloverFee)
1369+ let feeToStakers = $t06496365022._1
1370+ let feeToVault = $t06496365022._2
14461371 let unstake = invoke(vaultAddress(), "withdrawLocked", [feeToStakers], nil)
14471372 if ((unstake == unstake))
14481373 then {
14881413 else isMarketClosed())
14891414 then throw("Invalid removeMargin parameters")
14901415 else {
1491- let $t07075870926 = getPosition(_trader)
1492- let oldPositionSize = $t07075870926._1
1493- let oldPositionMargin = $t07075870926._2
1494- let oldPositionOpenNotional = $t07075870926._3
1495- let oldPositionLstUpdCPF = $t07075870926._4
1496- let oldPositionTimestamp = $t07075870926._5
1497- let $t07093271181 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, -(_amount))
1498- let remainMargin = $t07093271181._1
1499- let badDebt = $t07093271181._2
1500- let fundingPayment = $t07093271181._3
1501- let rolloverFee = $t07093271181._4
1416+ let $t06639566563 = getPosition(_trader)
1417+ let oldPositionSize = $t06639566563._1
1418+ let oldPositionMargin = $t06639566563._2
1419+ let oldPositionOpenNotional = $t06639566563._3
1420+ let oldPositionLstUpdCPF = $t06639566563._4
1421+ let oldPositionTimestamp = $t06639566563._5
1422+ let $t06656966818 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, -(_amount))
1423+ let remainMargin = $t06656966818._1
1424+ let badDebt = $t06656966818._2
1425+ let fundingPayment = $t06656966818._3
1426+ let rolloverFee = $t06656966818._4
15021427 if ((badDebt != 0))
15031428 then throw("Invalid removed margin amount")
15041429 else {
15061431 if (!(requireMoreMarginRatio(marginRatio, initMarginRatio(), true)))
15071432 then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
15081433 else {
1509- let $t07156771626 = distributeFee(rolloverFee)
1510- let feeToStakers = $t07156771626._1
1511- let feeToVault = $t07156771626._2
1434+ let $t06720467263 = distributeFee(rolloverFee)
1435+ let feeToStakers = $t06720467263._1
1436+ let feeToVault = $t06720467263._2
15121437 let doTransferFeeToStakers = if ((rolloverFee > 0))
15131438 then {
15141439 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(feeToVault)], nil)
15611486 then throw("Invalid closePosition parameters")
15621487 else {
15631488 let oldPositionTimestamp = getPosition(_trader)._5
1564- let $t07380174386 = internalClosePosition(_trader, _size, positionFee, _minQuoteAssetAmount, _addToMargin, true, true)
1565- let newPositionSize = $t07380174386._1
1566- let newPositionMargin = $t07380174386._2
1567- let newPositionOpenNotional = $t07380174386._3
1568- let newPositionLstUpdCPF = $t07380174386._4
1569- let positionBadDebt = $t07380174386._5
1570- let realizedPnl = $t07380174386._6
1571- let marginToTrader = $t07380174386._7
1572- let quoteAssetReserveAfter = $t07380174386._8
1573- let baseAssetReserveAfter = $t07380174386._9
1574- let totalPositionSizeAfter = $t07380174386._10
1575- let openInterestNotionalAfter = $t07380174386._11
1576- let totalLongAfter = $t07380174386._12
1577- let totalShortAfter = $t07380174386._13
1578- let totalLongOpenInterestAfter = $t07380174386._14
1579- let totalShortOpenInterestAfter = $t07380174386._15
1580- let realizedFee = $t07380174386._16
1489+ let $t06943870023 = internalClosePosition(_trader, _size, positionFee, _minQuoteAssetAmount, _addToMargin, true, true)
1490+ let newPositionSize = $t06943870023._1
1491+ let newPositionMargin = $t06943870023._2
1492+ let newPositionOpenNotional = $t06943870023._3
1493+ let newPositionLstUpdCPF = $t06943870023._4
1494+ let positionBadDebt = $t06943870023._5
1495+ let realizedPnl = $t06943870023._6
1496+ let marginToTrader = $t06943870023._7
1497+ let quoteAssetReserveAfter = $t06943870023._8
1498+ let baseAssetReserveAfter = $t06943870023._9
1499+ let totalPositionSizeAfter = $t06943870023._10
1500+ let openInterestNotionalAfter = $t06943870023._11
1501+ let totalLongAfter = $t06943870023._12
1502+ let totalShortAfter = $t06943870023._13
1503+ let totalLongOpenInterestAfter = $t06943870023._14
1504+ let totalShortOpenInterestAfter = $t06943870023._15
1505+ let realizedFee = $t06943870023._16
15811506 if ((positionBadDebt > 0))
15821507 then throw("Invalid closePosition parameters: bad debt")
15831508 else if ((oldPositionTimestamp >= lastTimestamp()))
15921517 let unstake = invoke(vaultAddress(), "withdrawLocked", [withdrawAmount], nil)
15931518 if ((unstake == unstake))
15941519 then {
1595- let $t07505875117 = distributeFee(realizedFee)
1596- let feeToStakers = $t07505875117._1
1597- let feeToVault = $t07505875117._2
1520+ let $t07069570754 = distributeFee(realizedFee)
1521+ let feeToStakers = $t07069570754._1
1522+ let feeToVault = $t07069570754._2
15981523 let depositVault = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
15991524 if ((depositVault == depositVault))
16001525 then {
16551580 else false
16561581 let oldPositionSize = getPosition(_trader)._1
16571582 let positionSizeAbs = abs(oldPositionSize)
1658- let $t07753877861 = if (isPartialLiquidation)
1583+ let $t07317573498 = if (isPartialLiquidation)
16591584 then {
16601585 let liquidationSize = getPartialLiquidationAmount(_trader, oldPositionSize)
16611586 let liquidationRatio = divd(abs(liquidationSize), positionSizeAbs)
16621587 $Tuple2(liquidationRatio, abs(liquidationSize))
16631588 }
16641589 else $Tuple2(0, positionSizeAbs)
1665- let liquidationRatio = $t07753877861._1
1666- let liquidationSize = $t07753877861._2
1667- let $t07786778505 = internalClosePosition(_trader, if (isPartialLiquidation)
1590+ let liquidationRatio = $t07317573498._1
1591+ let liquidationSize = $t07317573498._2
1592+ let $t07350474142 = internalClosePosition(_trader, if (isPartialLiquidation)
16681593 then liquidationSize
16691594 else positionSizeAbs, liquidationFeeRatio(), 0, true, false, true)
1670- let newPositionSize = $t07786778505._1
1671- let newPositionMargin = $t07786778505._2
1672- let newPositionOpenNotional = $t07786778505._3
1673- let newPositionLstUpdCPF = $t07786778505._4
1674- let positionBadDebt = $t07786778505._5
1675- let realizedPnl = $t07786778505._6
1676- let marginToTrader = $t07786778505._7
1677- let quoteAssetReserveAfter = $t07786778505._8
1678- let baseAssetReserveAfter = $t07786778505._9
1679- let totalPositionSizeAfter = $t07786778505._10
1680- let openInterestNotionalAfter = $t07786778505._11
1681- let totalLongAfter = $t07786778505._12
1682- let totalShortAfter = $t07786778505._13
1683- let totalLongOpenInterestAfter = $t07786778505._14
1684- let totalShortOpenInterestAfter = $t07786778505._15
1685- let liquidationPenalty = $t07786778505._16
1595+ let newPositionSize = $t07350474142._1
1596+ let newPositionMargin = $t07350474142._2
1597+ let newPositionOpenNotional = $t07350474142._3
1598+ let newPositionLstUpdCPF = $t07350474142._4
1599+ let positionBadDebt = $t07350474142._5
1600+ let realizedPnl = $t07350474142._6
1601+ let marginToTrader = $t07350474142._7
1602+ let quoteAssetReserveAfter = $t07350474142._8
1603+ let baseAssetReserveAfter = $t07350474142._9
1604+ let totalPositionSizeAfter = $t07350474142._10
1605+ let openInterestNotionalAfter = $t07350474142._11
1606+ let totalLongAfter = $t07350474142._12
1607+ let totalShortAfter = $t07350474142._13
1608+ let totalLongOpenInterestAfter = $t07350474142._14
1609+ let totalShortOpenInterestAfter = $t07350474142._15
1610+ let liquidationPenalty = $t07350474142._16
16861611 let feeToLiquidator = (liquidationPenalty / 2)
16871612 let feeToVault = (liquidationPenalty - feeToLiquidator)
16881613 let ammBalance = (cbalance() - liquidationPenalty)
17381663 then throw(((("Invalid funding block timestamp: " + toString(lastTimestamp())) + " < ") + toString(fundingBlockTimestamp)))
17391664 else {
17401665 let underlyingPrice = getOraclePrice()
1741- let $t08061880696 = getFunding()
1742- let shortPremiumFraction = $t08061880696._1
1743- let longPremiumFraction = $t08061880696._2
1744- let premiumToVault = $t08061880696._3
1666+ let $t07625576333 = getFunding()
1667+ let shortPremiumFraction = $t07625576333._1
1668+ let longPremiumFraction = $t07625576333._2
1669+ let premiumToVault = $t07625576333._3
17451670 let doPayFundingToVault = if ((premiumToVault > 0))
17461671 then {
17471672 let doPayFundingToVault = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(premiumToVault)], nil)
17641689 func syncTerminalPriceToOracle () = {
17651690 let _qtAstR = qtAstR()
17661691 let _bsAstR = bsAstR()
1767- let $t08174782113 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1768- let newQuoteAssetWeight = $t08174782113._1
1769- let newBaseAssetWeight = $t08174782113._2
1770- let marginToVault = $t08174782113._3
1692+ let $t07738477750 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1693+ let newQuoteAssetWeight = $t07738477750._1
1694+ let newBaseAssetWeight = $t07738477750._2
1695+ let marginToVault = $t07738477750._3
17711696 let marginToVaultAdj = if (if ((0 > marginToVault))
17721697 then (abs(marginToVault) > cbalance())
17731698 else false)
17821707 }
17831708 else nil
17841709 if ((doExchangePnL == doExchangePnL))
1785- then ((updateBalance((cbalance() + marginToVaultAdj)) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight)) ++ appendTwap(divd(muld(_qtAstR, newQuoteAssetWeight), muld(_bsAstR, newBaseAssetWeight))))
1710+ then (updateBalance((cbalance() + marginToVaultAdj)) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
17861711 else throw("Strict value is not equal to itself.")
17871712 }
17881713
18051730 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
18061731 if ((sync == sync))
18071732 then {
1808- let $t08375583879 = getPosition(_trader)
1809- let positionSize = $t08375583879._1
1810- let positionMargin = $t08375583879._2
1811- let pon = $t08375583879._3
1812- let positionLstUpdCPF = $t08375583879._4
1813- let positionTimestamp = $t08375583879._5
1814- let $t08388283983 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1815- let positionNotional = $t08388283983._1
1816- let unrealizedPnl = $t08388283983._2
1817- let $t08398684210 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLstUpdCPF, positionTimestamp, unrealizedPnl)
1818- let remainMargin = $t08398684210._1
1819- let badDebt = $t08398684210._2
1820- let fundingPayment = $t08398684210._3
1821- let rolloverFee = $t08398684210._4
1733+ let $t07929979423 = getPosition(_trader)
1734+ let positionSize = $t07929979423._1
1735+ let positionMargin = $t07929979423._2
1736+ let pon = $t07929979423._3
1737+ let positionLstUpdCPF = $t07929979423._4
1738+ let positionTimestamp = $t07929979423._5
1739+ let $t07942679527 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1740+ let positionNotional = $t07942679527._1
1741+ let unrealizedPnl = $t07942679527._2
1742+ let $t07953079754 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLstUpdCPF, positionTimestamp, unrealizedPnl)
1743+ let remainMargin = $t07953079754._1
1744+ let badDebt = $t07953079754._2
1745+ let fundingPayment = $t07953079754._3
1746+ let rolloverFee = $t07953079754._4
18221747 throw(((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)) + s(rolloverFee)))
18231748 }
18241749 else throw("Strict value is not equal to itself.")
18381763
18391764 @Callable(i)
18401765 func view_getTerminalAmmPrice () = {
1841- let $t08493385014 = getTerminalAmmState()
1842- let terminalQuoteAssetReserve = $t08493385014._1
1843- let terminalBaseAssetReserve = $t08493385014._2
1766+ let $t08047780558 = getTerminalAmmState()
1767+ let terminalQuoteAssetReserve = $t08047780558._1
1768+ let terminalBaseAssetReserve = $t08047780558._2
18441769 let price = divd(muld(terminalQuoteAssetReserve, qtAstW()), muld(terminalBaseAssetReserve, bsAstW()))
18451770 throw(toString(price))
18461771 }
18501775 @Callable(i)
18511776 func view_getFunding () = {
18521777 let underlyingPrice = getOraclePrice()
1853- let $t08552385601 = getFunding()
1854- let shortPremiumFraction = $t08552385601._1
1855- let longPremiumFraction = $t08552385601._2
1856- let premiumToVault = $t08552385601._3
1778+ let $t08106781145 = getFunding()
1779+ let shortPremiumFraction = $t08106781145._1
1780+ let longPremiumFraction = $t08106781145._2
1781+ let premiumToVault = $t08106781145._3
18571782 let longFunding = divd(longPremiumFraction, underlyingPrice)
18581783 let shortFunding = divd(shortPremiumFraction, underlyingPrice)
1859- throw(((((s(longFunding) + s(shortFunding)) + s(getTwapSpotPrice())) + s(getOraclePrice())) + s(premiumToVault)))
1784+ throw(((((s(longFunding) + s(shortFunding)) + s(getSpotPrice())) + s(getOraclePrice())) + s(premiumToVault)))
18601785 }
18611786
18621787
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_positionAsset = "k_positionAsset"
2323
2424 let k_positionFee = "k_positionFee"
2525
2626 let k_positionLastUpdatedTimestamp = "k_positionTimestamp"
2727
2828 let k_initialized = "k_initialized"
2929
3030 let k_paused = "k_paused"
3131
3232 let k_closeOnly = "k_closeOnly"
3333
3434 let k_fee = "k_fee"
3535
3636 let k_rolloverFee = "k_rollover_fee"
3737
3838 let k_fundingPeriod = "k_fundingPeriod"
3939
4040 let k_initMarginRatio = "k_initMarginRatio"
4141
4242 let k_maintenanceMarginRatio = "k_mmr"
4343
4444 let k_liquidationFeeRatio = "k_liquidationFeeRatio"
4545
4646 let k_partialLiquidationRatio = "k_partLiquidationRatio"
4747
4848 let k_spreadLimit = "k_spreadLimit"
4949
5050 let k_maxPriceImpact = "k_maxPriceImpact"
5151
5252 let k_maxPriceSpread = "k_maxPriceSpread"
5353
5454 let k_maxOpenNotional = "k_maxOpenNotional"
5555
5656 let k_feeToStakersPercent = "k_feeToStakersPercent"
5757
5858 let k_maxOracleDelay = "k_maxOracleDelay"
5959
6060 let k_fundingMode = "k_fundingMode"
61-
62-let k_lastDataStr = "k_lastDataStr"
63-
64-let k_lastMinuteId = "k_lastMinuteId"
65-
66-let k_twapDataLastCumulativePrice = "k_twapDataLastCumulativePrice"
67-
68-let k_twapDataLastPrice = "k_twapDataLastPrice"
69-
70-let k_twapDataPreviousMinuteId = "k_twapDataPreviousMinuteId"
7161
7262 let k_latestLongCumulativePremiumFraction = "k_latestLongPremiumFraction"
7363
7464 let k_latestShortCumulativePremiumFraction = "k_latestShortPremiumFraction"
7565
7666 let k_nextFundingBlock = "k_nextFundingBlockMinTimestamp"
7767
7868 let k_longFundingRate = "k_longFundingRate"
7969
8070 let k_shortFundingRate = "k_shortFundingRate"
8171
8272 let k_quoteAssetReserve = "k_qtAstR"
8373
8474 let k_baseAssetReserve = "k_bsAstR"
8575
8676 let k_quoteAssetWeight = "k_qtAstW"
8777
8878 let k_baseAssetWeight = "k_bsAstW"
8979
9080 let k_totalPositionSize = "k_totalPositionSize"
9181
9282 let k_totalLongPositionSize = "k_totalLongPositionSize"
9383
9484 let k_totalShortPositionSize = "k_totalShortPositionSize"
9585
9686 let k_openInterestNotional = "k_openInterestNotional"
9787
9888 let k_openInterestShort = "k_openInterestShort"
9989
10090 let k_openInterestLong = "k_openInterestLong"
10191
10292 let k_lastTx = "k_lastTx"
10393
10494 let k_coordinatorAddress = "k_coordinatorAddress"
10595
10696 let k_vault_address = "k_vault_address"
10797
10898 let k_admin_address = "k_admin_address"
10999
110100 let k_quote_asset = "k_quote_asset"
111101
112102 let k_quote_staking = "k_quote_staking"
113103
114104 let k_staking_address = "k_staking_address"
115105
116106 let k_miner_address = "k_miner_address"
117107
118108 let k_orders_address = "k_orders_address"
119109
120110 let k_referral_address = "k_referral_address"
121111
122112 let k_exchange_address = "k_exchange_address"
123113
124114 let k_nft_manager_address = "k_nft_manager_address"
125115
126116 func toCompositeKey (_key,_address) = ((_key + "_") + _address)
127117
128118
129119 func coordinator () = valueOrErrorMessage(addressFromString(getStringValue(this, k_coordinatorAddress)), "Coordinator not set")
130120
131121
132122 func adminAddress () = addressFromString(getStringValue(coordinator(), k_admin_address))
133123
134124
135125 func quoteAsset () = fromBase58String(getStringValue(coordinator(), k_quote_asset))
136126
137127
138128 func quoteAssetStaking () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_quote_staking)), "Quote asset staking not set")
139129
140130
141131 func stakingAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_staking_address)), "Staking not set")
142132
143133
144134 func vaultAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_vault_address)), "Vault not set")
145135
146136
147137 func minerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_miner_address)), "Miner not set")
148138
149139
150140 func ordersAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_orders_address)), "Orders not set")
151141
152142
153143 func referralAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_referral_address)), "Referral not set")
154144
155145
156146 func nftManagerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_nft_manager_address)), "NFT Manager not set")
157147
158148
159149 let k_token_param = "k_token_param"
160150
161151 let k_token_type = "k_token_type"
162152
163153 let FEE_REDUCTION_TOKEN_TYPE = "fee_reduction"
164154
165155 let DIR_LONG = 1
166156
167157 let DIR_SHORT = 2
168158
169159 let TWAP_INTERVAL = 15
170160
171161 let SECONDS = 1000
172162
173163 let DECIMAL_NUMBERS = 6
174164
175165 let DECIMAL_UNIT = (1 * (((((10 * 10) * 10) * 10) * 10) * 10))
176166
177167 let MINUTES_IN_YEAR = (525600 * DECIMAL_UNIT)
178168
179169 let ONE_DAY = (86400 * DECIMAL_UNIT)
180170
181171 let PNL_OPTION_SPOT = 1
182172
183173 let PNL_OPTION_ORACLE = 2
184174
185175 let FUNDING_ASYMMETRIC = 1
186176
187177 let FUNDING_SYMMETRIC = 2
188178
189179 func s (_x) = (toString(_x) + ",")
190180
191181
192182 func divd (_x,_y) = fraction(_x, DECIMAL_UNIT, _y, HALFEVEN)
193183
194184
195185 func muld (_x,_y) = fraction(_x, _y, DECIMAL_UNIT, HALFEVEN)
196186
197187
198188 func bdivd (_x,_y) = fraction(_x, toBigInt(DECIMAL_UNIT), _y, HALFEVEN)
199189
200190
201191 func bmuld (_x,_y) = fraction(_x, _y, toBigInt(DECIMAL_UNIT), HALFEVEN)
202192
203193
204194 func abs (_x) = if ((_x > 0))
205195 then _x
206196 else -(_x)
207197
208198
209199 func vmax (_x,_y) = if ((_x >= _y))
210200 then _x
211201 else _y
212202
213203
214204 func listToStr (_list) = if ((size(_list) == 0))
215205 then ""
216206 else makeString(_list, ",")
217207
218208
219209 func strToList (_str) = if ((_str == ""))
220210 then nil
221211 else split(_str, ",")
222212
223213
224214 func pushToQueue (_list,_maxSize,_value) = if ((size(_list) > _maxSize))
225215 then (removeByIndex(_list, 0) :+ _value)
226216 else (_list :+ _value)
227217
228218
229219 func int (k) = valueOrErrorMessage(getInteger(this, k), ("no value for " + k))
230220
231221
232222 func intOr (k,def) = valueOrElse(getInteger(this, k), def)
233223
234224
235225 func strA (_address,_key) = {
236226 let val = valueOrErrorMessage(getString(_address, _key), ("No value for key " + _key))
237227 val
238228 }
239229
240230
241231 func intA (_address,_key) = {
242232 let val = valueOrErrorMessage(getInteger(_address, _key), ("No value for key " + _key))
243233 val
244234 }
245235
246236
247237 func cbalance () = int(k_balance)
248238
249239
250240 func fee () = int(k_fee)
251241
252242
253243 func rolloverFeeRate () = int(k_rolloverFee)
254244
255245
256246 func initMarginRatio () = int(k_initMarginRatio)
257247
258248
259249 func qtAstR () = int(k_quoteAssetReserve)
260250
261251
262252 func bsAstR () = int(k_baseAssetReserve)
263253
264254
265255 func qtAstW () = intOr(k_quoteAssetWeight, DECIMAL_UNIT)
266256
267257
268258 func bsAstW () = intOr(k_baseAssetWeight, DECIMAL_UNIT)
269259
270260
271261 func totalPositionSize () = int(k_totalPositionSize)
272262
273263
274264 func openInterestNotional () = int(k_openInterestNotional)
275265
276266
277267 func openInterestShort () = int(k_openInterestShort)
278268
279269
280270 func openInterestLong () = int(k_openInterestLong)
281271
282272
283273 func nextFundingBlockTimestamp () = int(k_nextFundingBlock)
284274
285275
286276 func fundingPeriodRaw () = int(k_fundingPeriod)
287277
288278
289279 func fundingPeriodDecimal () = (fundingPeriodRaw() * DECIMAL_UNIT)
290280
291281
292282 func fundingPeriodSeconds () = (fundingPeriodRaw() * SECONDS)
293283
294284
295285 func maintenanceMarginRatio () = int(k_maintenanceMarginRatio)
296286
297287
298288 func liquidationFeeRatio () = int(k_liquidationFeeRatio)
299289
300290
301291 func partialLiquidationRatio () = int(k_partialLiquidationRatio)
302292
303293
304294 func spreadLimit () = int(k_spreadLimit)
305295
306296
307297 func maxPriceImpact () = int(k_maxPriceImpact)
308298
309299
310300 func maxPriceSpread () = int(k_maxPriceSpread)
311301
312302
313303 func maxOpenNotional () = int(k_maxOpenNotional)
314304
315305
316306 func latestLongCumulativePremiumFraction () = int(k_latestLongCumulativePremiumFraction)
317307
318308
319309 func latestShortCumulativePremiumFraction () = int(k_latestShortCumulativePremiumFraction)
320310
321311
322312 func totalShortPositionSize () = int(k_totalShortPositionSize)
323313
324314
325315 func totalLongPositionSize () = int(k_totalLongPositionSize)
326316
327317
328318 func lastSequence () = intOr(k_sequence, 0)
329319
330320
331321 func feeToStakersPercent () = int(k_feeToStakersPercent)
332322
333323
334324 func maxOracleDelay () = int(k_maxOracleDelay)
335325
336326
337327 func fundingMode () = intOr(k_fundingMode, FUNDING_ASYMMETRIC)
338328
339329
340330 func lastTimestamp () = lastBlock.timestamp
341331
342332
343333 func getActualCaller (i) = valueOrElse(getString(ordersAddress(), "k_sender"), toString(i.caller))
344334
345335
346336 func requireMoreMarginRatio (_marginRatio,_baseMarginRatio,_largerThanOrEqualTo) = {
347337 let remainingMarginRatio = (_marginRatio - _baseMarginRatio)
348338 if (if (_largerThanOrEqualTo)
349339 then (0 > remainingMarginRatio)
350340 else false)
351341 then throw(((("Invalid margin: " + toString(_marginRatio)) + " < ") + toString(_baseMarginRatio)))
352342 else if (if (!(_largerThanOrEqualTo))
353343 then (remainingMarginRatio >= 0)
354344 else false)
355345 then throw(((("Invalid margin: " + toString(_marginRatio)) + " > ") + toString(_baseMarginRatio)))
356346 else true
357347 }
358348
359349
360350 func latestCumulativePremiumFraction (_positionSize) = if ((_positionSize == 0))
361351 then throw("Should not be called with _positionSize == 0")
362352 else if ((_positionSize > 0))
363353 then latestLongCumulativePremiumFraction()
364354 else latestShortCumulativePremiumFraction()
365355
366356
367357 func getPosition (_trader) = {
368358 let positionSizeOpt = getInteger(this, toCompositeKey(k_positionSize, _trader))
369359 match positionSizeOpt {
370360 case positionSize: Int =>
371361 $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)))
372362 case _ =>
373363 $Tuple5(0, 0, 0, 0, 0)
374364 }
375365 }
376366
377367
378368 func getPositionAsset (_trader) = {
379369 let positionAssetOpt = getString(this, toCompositeKey(k_positionAsset, _trader))
380370 match positionAssetOpt {
381371 case positionAsset: String =>
382372 positionAsset
383373 case _ =>
384374 toBase58String(quoteAsset())
385375 }
386376 }
387377
388378
389379 func getPositionFee (_trader) = {
390380 let positionFeeOpt = getInteger(this, toCompositeKey(k_positionFee, _trader))
391381 match positionFeeOpt {
392382 case positionFee: Int =>
393383 positionFee
394384 case _ =>
395385 fee()
396386 }
397387 }
398388
399389
400390 func requireOpenPosition (_trader) = if ((getPosition(_trader)._1 == 0))
401391 then throw("No open position")
402392 else true
403393
404394
405395 func getOracleData (key) = {
406396 let oracleDataStr = getString(this, key)
407397 if (if (isDefined(oracleDataStr))
408398 then (value(oracleDataStr) != "")
409399 else false)
410400 then {
411401 let oracleData = split(value(oracleDataStr), ",")
412402 let oracleAddress = valueOrErrorMessage(addressFromString(oracleData[0]), ("Invalid oracle address in: " + value(oracleDataStr)))
413403 let priceKey = oracleData[1]
414404 let blockKey = oracleData[2]
415405 let openKey = oracleData[3]
416406 $Tuple4(oracleAddress, priceKey, blockKey, openKey)
417407 }
418408 else unit
419409 }
420410
421411
422412 func initialized () = valueOrElse(getBoolean(this, k_initialized), false)
423413
424414
425415 func paused () = valueOrElse(getBoolean(this, k_paused), false)
426416
427417
428418 func closeOnly () = valueOrElse(getBoolean(this, k_closeOnly), false)
429419
430420
431421 func updateReserve (_isAdd,_quoteAssetAmount,_baseAssetAmount) = if (_isAdd)
432422 then {
433423 let newBase = (bsAstR() - _baseAssetAmount)
434424 if ((0 >= newBase))
435425 then throw("Tx lead to base asset reserve <= 0, revert")
436426 else $Tuple3((qtAstR() + _quoteAssetAmount), newBase, (totalPositionSize() + _baseAssetAmount))
437427 }
438428 else {
439429 let newQuote = (qtAstR() - _quoteAssetAmount)
440430 if ((0 >= newQuote))
441431 then throw("Tx lead to base quote reserve <= 0, revert")
442432 else $Tuple3(newQuote, (bsAstR() + _baseAssetAmount), (totalPositionSize() - _baseAssetAmount))
443433 }
444434
445435
446436 func calcInvariant (_qtAstR,_bsAstR) = {
447437 let bqtAstR = toBigInt(_qtAstR)
448438 let bbsAstR = toBigInt(_bsAstR)
449439 bmuld(bqtAstR, bbsAstR)
450440 }
451441
452442
453443 func swapInput (_isAdd,_quoteAssetAmount) = {
454444 let _qtAstR = qtAstR()
455445 let _bsAstR = bsAstR()
456446 let _qtAstW = qtAstW()
457447 let _bsAstW = bsAstW()
458448 let quoteAssetAmountAdjusted = divd(_quoteAssetAmount, _qtAstW)
459449 let k = calcInvariant(_qtAstR, _bsAstR)
460450 let quoteAssetReserveAfter = if (_isAdd)
461451 then (_qtAstR + quoteAssetAmountAdjusted)
462452 else (_qtAstR - quoteAssetAmountAdjusted)
463453 let baseAssetReserveAfter = toInt(bdivd(k, toBigInt(quoteAssetReserveAfter)))
464454 let amountBaseAssetBoughtAbs = abs((baseAssetReserveAfter - _bsAstR))
465455 let amountBaseAssetBought = if (_isAdd)
466456 then amountBaseAssetBoughtAbs
467457 else -(amountBaseAssetBoughtAbs)
468- let $t01694317113 = updateReserve(_isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
469- let quoteAssetReserveAfter1 = $t01694317113._1
470- let baseAssetReserveAfter1 = $t01694317113._2
471- let totalPositionSizeAfter1 = $t01694317113._3
458+ let $t01635216522 = updateReserve(_isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
459+ let quoteAssetReserveAfter1 = $t01635216522._1
460+ let baseAssetReserveAfter1 = $t01635216522._2
461+ let totalPositionSizeAfter1 = $t01635216522._3
472462 let priceBefore = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
473463 let marketPrice = divd(_quoteAssetAmount, amountBaseAssetBoughtAbs)
474464 let priceDiff = abs((priceBefore - marketPrice))
475465 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
476466 let maxPriceImpactValue = maxPriceImpact()
477467 if ((priceImpact > maxPriceImpactValue))
478468 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)))
479469 else $Tuple4(amountBaseAssetBought, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1)
480470 }
481471
482472
483473 func calcRolloverFee (_oldPositionMargin,_oldPositionLastUpdatedTimestamp) = {
484474 let positionMinutes = ((((lastTimestamp() - _oldPositionLastUpdatedTimestamp) / 1000) / 60) * DECIMAL_UNIT)
485475 let rolloverFee = divd(muld(muld(_oldPositionMargin, positionMinutes), rolloverFeeRate()), MINUTES_IN_YEAR)
486476 rolloverFee
487477 }
488478
489479
490480 func calcRemainMarginWithFundingPaymentAndRolloverFee (_oldPositionSize,_oldPositionMargin,_oldPositionCumulativePremiumFraction,_oldPositionLastUpdatedTimestamp,_marginDelta) = {
491481 let fundingPayment = if ((_oldPositionSize != 0))
492482 then {
493483 let _latestCumulativePremiumFraction = latestCumulativePremiumFraction(_oldPositionSize)
494484 muld((_latestCumulativePremiumFraction - _oldPositionCumulativePremiumFraction), _oldPositionSize)
495485 }
496486 else 0
497487 let rolloverFee = calcRolloverFee(_oldPositionMargin, _oldPositionLastUpdatedTimestamp)
498488 let signedMargin = (((_marginDelta - rolloverFee) - fundingPayment) + _oldPositionMargin)
499- let $t01936819495 = if ((0 > signedMargin))
489+ let $t01877718904 = if ((0 > signedMargin))
500490 then $Tuple2(0, abs(signedMargin))
501491 else $Tuple2(abs(signedMargin), 0)
502- let remainMargin = $t01936819495._1
503- let badDebt = $t01936819495._2
492+ let remainMargin = $t01877718904._1
493+ let badDebt = $t01877718904._2
504494 $Tuple4(remainMargin, badDebt, fundingPayment, rolloverFee)
505495 }
506496
507497
508498 func swapOutputWithReserves (_isAdd,_baseAssetAmount,_checkMaxPriceImpact,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
509499 let priceBefore = divd(muld(_quoteAssetReserve, _quoteAssetWeight), muld(_baseAssetReserve, _baseAssetWeight))
510500 if ((_baseAssetAmount == 0))
511501 then throw("Invalid base asset amount")
512502 else {
513503 let k = calcInvariant(_quoteAssetReserve, _baseAssetReserve)
514504 let baseAssetPoolAmountAfter = if (_isAdd)
515505 then (_baseAssetReserve + _baseAssetAmount)
516506 else (_baseAssetReserve - _baseAssetAmount)
517507 let quoteAssetAfter = toInt(bdivd(k, toBigInt(baseAssetPoolAmountAfter)))
518508 let quoteAssetDelta = abs((quoteAssetAfter - _quoteAssetReserve))
519509 let quoteAssetSold = muld(quoteAssetDelta, _quoteAssetWeight)
520510 let maxPriceImpactValue = maxPriceImpact()
521- let $t02075720919 = updateReserve(!(_isAdd), quoteAssetDelta, _baseAssetAmount)
522- let quoteAssetReserveAfter1 = $t02075720919._1
523- let baseAssetReserveAfter1 = $t02075720919._2
524- let totalPositionSizeAfter1 = $t02075720919._3
511+ let $t02016620328 = updateReserve(!(_isAdd), quoteAssetDelta, _baseAssetAmount)
512+ let quoteAssetReserveAfter1 = $t02016620328._1
513+ let baseAssetReserveAfter1 = $t02016620328._2
514+ let totalPositionSizeAfter1 = $t02016620328._3
525515 let marketPrice = divd(quoteAssetSold, _baseAssetAmount)
526516 let priceDiff = abs((priceBefore - marketPrice))
527517 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
528518 if (if ((priceImpact > maxPriceImpactValue))
529519 then _checkMaxPriceImpact
530520 else false)
531521 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)))
532522 else $Tuple7(quoteAssetSold, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1, (totalLongPositionSize() - (if (_isAdd)
533523 then abs(_baseAssetAmount)
534524 else 0)), (totalShortPositionSize() - (if (!(_isAdd))
535525 then abs(_baseAssetAmount)
536526 else 0)), priceImpact)
537527 }
538528 }
539529
540530
541531 func swapOutput (_isAdd,_baseAssetAmount,_checkMaxPriceImpact) = swapOutputWithReserves(_isAdd, _baseAssetAmount, _checkMaxPriceImpact, qtAstR(), qtAstW(), bsAstR(), bsAstW())
542532
543533
544534 func getOraclePriceValue (oracle,priceKey,blockKey) = {
545535 let lastValue = valueOrErrorMessage(getInteger(oracle, priceKey), ((("Can not get oracle price. Oracle: " + toString(oracle)) + " key: ") + priceKey))
546536 if ((blockKey != ""))
547537 then {
548538 let currentBlock = lastBlock.height
549539 let lastOracleBlock = valueOrErrorMessage(getInteger(oracle, blockKey), ((("Can not get oracle block. Oracle: " + toString(oracle)) + " key: ") + blockKey))
550540 if (((currentBlock - lastOracleBlock) > maxOracleDelay()))
551541 then throw(((("Oracle stale data. Last oracle block: " + toString(lastOracleBlock)) + " current block: ") + toString(currentBlock)))
552542 else lastValue
553543 }
554544 else lastValue
555545 }
556546
557547
558548 func getOraclePrice () = {
559549 let baseOracle = valueOrErrorMessage(getOracleData(k_baseOracle), "No base asset oracle data")
560550 let baseOraclePrice = getOraclePriceValue(baseOracle._1, baseOracle._2, baseOracle._3)
561551 let quoteOracle = getOracleData(k_quoteOracle)
562552 let quoteOraclePrice = if (isDefined(quoteOracle))
563553 then {
564554 let quoteOracleV = value(quoteOracle)
565555 getOraclePriceValue(quoteOracleV._1, quoteOracleV._2, quoteOracleV._3)
566556 }
567557 else DECIMAL_UNIT
568558 divd(baseOraclePrice, quoteOraclePrice)
569559 }
570560
571561
572562 func isMarketClosed () = {
573563 let baseOracle = valueOrErrorMessage(getOracleData(k_baseOracle), "No base asset oracle data")
574564 let oracle = baseOracle._1
575565 let openKey = baseOracle._4
576566 if ((openKey != ""))
577567 then {
578568 let isOpen = valueOrErrorMessage(getBoolean(oracle, openKey), ((("Can not get oracle is open/closed. Oracle: " + toString(oracle)) + " key: ") + openKey))
579569 !(isOpen)
580570 }
581571 else false
582572 }
583573
584574
585575 func absPriceDiff (_oraclePrice,_quoteAssetReserve,_baseAssetReserve,_qtAstW,_bsAstW) = {
586576 let priceAfter = divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
587577 let averagePrice = divd((_oraclePrice + priceAfter), (2 * DECIMAL_UNIT))
588578 let absPriceDiff = divd(abs((_oraclePrice - priceAfter)), averagePrice)
589579 absPriceDiff
590580 }
591581
592582
593583 func requireNotOverSpreadLimit (_quoteAssetReserve,_baseAssetReserve) = {
594584 let oraclePrice = getOraclePrice()
595585 let _qtAstW = qtAstW()
596586 let _bsAstW = bsAstW()
597587 let absPriceDiffBefore = absPriceDiff(oraclePrice, qtAstR(), bsAstR(), _qtAstW, _bsAstW)
598588 let absPriceDiffAfter = absPriceDiff(oraclePrice, _quoteAssetReserve, _baseAssetReserve, _qtAstW, _bsAstW)
599589 if (if ((absPriceDiffAfter > maxPriceSpread()))
600590 then (absPriceDiffAfter > absPriceDiffBefore)
601591 else false)
602592 then throw(((("Price spread " + toString(absPriceDiffAfter)) + " > max price spread ") + toString(maxPriceSpread())))
603593 else true
604594 }
605595
606596
607597 func requireNotOverMaxOpenNotional (_longOpenNotional,_shortOpenNotional) = {
608598 let _maxOpenNotional = maxOpenNotional()
609599 if ((_longOpenNotional > _maxOpenNotional))
610600 then throw(((("Long open notional " + toString(_longOpenNotional)) + " > max open notional ") + toString(_maxOpenNotional)))
611601 else if ((_shortOpenNotional > _maxOpenNotional))
612602 then throw(((("Short open notional " + toString(_shortOpenNotional)) + " > max open notional ") + toString(_maxOpenNotional)))
613603 else true
614604 }
615605
616606
617607 func getSpotPrice () = {
618608 let _quoteAssetReserve = qtAstR()
619609 let _baseAssetReserve = bsAstR()
620610 let _qtAstW = qtAstW()
621611 let _bsAstW = bsAstW()
622612 divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
623613 }
624614
625615
626616 func isOverFluctuationLimit () = {
627617 let oraclePrice = getOraclePrice()
628618 let currentPrice = getSpotPrice()
629619 (divd(abs((oraclePrice - currentPrice)), oraclePrice) > spreadLimit())
630620 }
631621
632622
633623 func getPositionAdjustedOpenNotional (_positionSize,_option,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
634624 let positionSizeAbs = abs(_positionSize)
635625 let isShort = (0 > _positionSize)
636626 let positionNotional = if ((_option == PNL_OPTION_SPOT))
637627 then {
638628 let outPositionNotional = swapOutputWithReserves(!(isShort), positionSizeAbs, false, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)._1
639629 outPositionNotional
640630 }
641631 else muld(positionSizeAbs, getOraclePrice())
642632 positionNotional
643633 }
644634
645635
646636 func getPositionNotionalAndUnrealizedPnlByValues (_positionSize,_positionOpenNotional,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight,_option) = if ((_positionSize == 0))
647637 then throw("Invalid position size")
648638 else {
649639 let isShort = (0 > _positionSize)
650640 let positionNotional = getPositionAdjustedOpenNotional(_positionSize, _option, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
651641 let unrealizedPnl = if (isShort)
652642 then (_positionOpenNotional - positionNotional)
653643 else (positionNotional - _positionOpenNotional)
654644 $Tuple2(positionNotional, unrealizedPnl)
655645 }
656646
657647
658648 func getPositionNotionalAndUnrealizedPnl (_trader,_option) = {
659- let $t02879728925 = getPosition(_trader)
660- let positionSize = $t02879728925._1
661- let positionMargin = $t02879728925._2
662- let positionOpenNotional = $t02879728925._3
663- let positionLstUpdCPF = $t02879728925._4
649+ let $t02820628334 = getPosition(_trader)
650+ let positionSize = $t02820628334._1
651+ let positionMargin = $t02820628334._2
652+ let positionOpenNotional = $t02820628334._3
653+ let positionLstUpdCPF = $t02820628334._4
664654 getPositionNotionalAndUnrealizedPnlByValues(positionSize, positionOpenNotional, qtAstR(), qtAstW(), bsAstR(), bsAstW(), _option)
665655 }
666656
667657
668658 func calcMarginRatio (_remainMargin,_badDebt,_positionNotional) = divd((_remainMargin - _badDebt), _positionNotional)
669659
670660
671661 func getMarginRatioByOption (_trader,_option) = {
672- let $t02944029581 = getPosition(_trader)
673- let positionSize = $t02944029581._1
674- let positionMargin = $t02944029581._2
675- let pon = $t02944029581._3
676- let positionLastUpdatedCPF = $t02944029581._4
677- let positionTimestamp = $t02944029581._5
678- let $t02958729680 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
679- let positionNotional = $t02958729680._1
680- let unrealizedPnl = $t02958729680._2
681- let $t02968529897 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLastUpdatedCPF, positionTimestamp, unrealizedPnl)
682- let remainMargin = $t02968529897._1
683- let badDebt = $t02968529897._2
662+ let $t02884928990 = getPosition(_trader)
663+ let positionSize = $t02884928990._1
664+ let positionMargin = $t02884928990._2
665+ let pon = $t02884928990._3
666+ let positionLastUpdatedCPF = $t02884928990._4
667+ let positionTimestamp = $t02884928990._5
668+ let $t02899629089 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
669+ let positionNotional = $t02899629089._1
670+ let unrealizedPnl = $t02899629089._2
671+ let $t02909429306 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLastUpdatedCPF, positionTimestamp, unrealizedPnl)
672+ let remainMargin = $t02909429306._1
673+ let badDebt = $t02909429306._2
684674 calcMarginRatio(remainMargin, badDebt, positionNotional)
685675 }
686676
687677
688678 func getMarginRatio (_trader) = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
689679
690680
691681 func getPartialLiquidationAmount (_trader,_positionSize) = {
692682 let maximumRatio = vmax(partialLiquidationRatio(), (DECIMAL_UNIT - divd(getMarginRatio(_trader), maintenanceMarginRatio())))
693683 let maxExchangedPositionSize = muld(abs(_positionSize), maximumRatio)
694684 let swapResult = swapOutput((_positionSize > 0), maxExchangedPositionSize, false)
695685 let maxExchangedQuoteAssetAmount = swapResult._1
696686 let priceImpact = swapResult._7
697687 if ((maxPriceImpact() > priceImpact))
698688 then maxExchangedPositionSize
699689 else muld(abs(_positionSize), partialLiquidationRatio())
700690 }
701691
702692
703693 func internalClosePosition (_trader,_size,_fee,_minQuoteAssetAmount,_addToMargin,_checkMaxPriceImpact,_liquidate) = {
704- let $t03096431120 = getPosition(_trader)
705- let oldPositionSize = $t03096431120._1
706- let oldPositionMargin = $t03096431120._2
707- let oldPositionOpenNotional = $t03096431120._3
708- let oldPositionLstUpdCPF = $t03096431120._4
709- let oldPositionTimestamp = $t03096431120._5
694+ let $t03037330529 = getPosition(_trader)
695+ let oldPositionSize = $t03037330529._1
696+ let oldPositionMargin = $t03037330529._2
697+ let oldPositionOpenNotional = $t03037330529._3
698+ let oldPositionLstUpdCPF = $t03037330529._4
699+ let oldPositionTimestamp = $t03037330529._5
710700 let isLongPosition = (oldPositionSize > 0)
711701 let absOldPositionSize = abs(oldPositionSize)
712702 if (if ((absOldPositionSize >= _size))
713703 then (_size > 0)
714704 else false)
715705 then {
716706 let isPartialClose = (absOldPositionSize > _size)
717- let $t03141231863 = swapOutput((oldPositionSize > 0), _size, _checkMaxPriceImpact)
718- let exchangedQuoteAssetAmount = $t03141231863._1
719- let quoteAssetReserveAfter = $t03141231863._2
720- let baseAssetReserveAfter = $t03141231863._3
721- let totalPositionSizeAfter = $t03141231863._4
707+ let $t03082131272 = swapOutput((oldPositionSize > 0), _size, _checkMaxPriceImpact)
708+ let exchangedQuoteAssetAmount = $t03082131272._1
709+ let quoteAssetReserveAfter = $t03082131272._2
710+ let baseAssetReserveAfter = $t03082131272._3
711+ let totalPositionSizeAfter = $t03082131272._4
722712 let exchangedPositionSize = if ((oldPositionSize > 0))
723713 then -(_size)
724714 else _size
725- let $t03207832285 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
726- let oldPositionNotional = $t03207832285._1
727- let unrealizedPnl = $t03207832285._2
715+ let $t03148731694 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
716+ let oldPositionNotional = $t03148731694._1
717+ let unrealizedPnl = $t03148731694._2
728718 let realizedRatio = divd(abs(exchangedPositionSize), absOldPositionSize)
729719 let realizedPnl = muld(unrealizedPnl, realizedRatio)
730- let $t03262632872 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, unrealizedPnl)
731- let remainMarginBefore = $t03262632872._1
732- let x1 = $t03262632872._2
733- let x2 = $t03262632872._3
734- let rolloverFee = $t03262632872._4
720+ let $t03203532281 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, unrealizedPnl)
721+ let remainMarginBefore = $t03203532281._1
722+ let x1 = $t03203532281._2
723+ let x2 = $t03203532281._3
724+ let rolloverFee = $t03203532281._4
735725 let positionBadDebt = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, realizedPnl)._2
736726 let realizedCloseFee = muld(muld(oldPositionNotional, realizedRatio), _fee)
737727 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
738728 let remainOpenNotional = if ((oldPositionSize > 0))
739729 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
740730 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
741731 let newPositionSize = (oldPositionSize + exchangedPositionSize)
742- let $t03427834664 = if ((newPositionSize == 0))
732+ let $t03368734073 = if ((newPositionSize == 0))
743733 then $Tuple2(0, 0)
744734 else $Tuple2(abs(remainOpenNotional), latestCumulativePremiumFraction(newPositionSize))
745- let newPositionOpenNotional = $t03427834664._1
746- let newPositionLstUpdCPF = $t03427834664._2
735+ let newPositionOpenNotional = $t03368734073._1
736+ let newPositionLstUpdCPF = $t03368734073._2
747737 let openNotionalDelta = (oldPositionOpenNotional - newPositionOpenNotional)
748738 let marginRatio = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
749739 let newPositionMarginWithSameRatio = if ((oldPositionSize > 0))
750740 then (muld((newPositionOpenNotional + unrealizedPnlAfter), marginRatio) - unrealizedPnlAfter)
751741 else (muld((newPositionOpenNotional - unrealizedPnlAfter), marginRatio) - unrealizedPnlAfter)
752742 let marginToTraderRaw = ((remainMarginBefore - (newPositionMarginWithSameRatio + unrealizedPnlAfter)) - realizedCloseFee)
753743 let marginToTrader = if ((0 > marginToTraderRaw))
754744 then if (_liquidate)
755745 then 0
756746 else throw("Invalid internalClosePosition params: unable to pay fee")
757747 else marginToTraderRaw
758748 let newPositionMargin = if (_addToMargin)
759749 then (newPositionMarginWithSameRatio + marginToTrader)
760750 else newPositionMarginWithSameRatio
761751 if (if ((_minQuoteAssetAmount != 0))
762752 then (_minQuoteAssetAmount > exchangedQuoteAssetAmount)
763753 else false)
764754 then throw(((("Limit error: " + toString(exchangedQuoteAssetAmount)) + " < ") + toString(_minQuoteAssetAmount)))
765755 else $Tuple17(newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, positionBadDebt, realizedPnl, if (if (_addToMargin)
766756 then isPartialClose
767757 else false)
768758 then 0
769759 else marginToTrader, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, (openInterestNotional() - openNotionalDelta), (totalLongPositionSize() - (if (isLongPosition)
770760 then abs(exchangedPositionSize)
771761 else 0)), (totalShortPositionSize() - (if (!(isLongPosition))
772762 then abs(exchangedPositionSize)
773763 else 0)), (openInterestLong() - (if (isLongPosition)
774764 then openNotionalDelta
775765 else 0)), (openInterestShort() - (if (!(isLongPosition))
776766 then openNotionalDelta
777767 else 0)), (realizedCloseFee + rolloverFee), exchangedQuoteAssetAmount)
778768 }
779769 else throw(((("Invalid internalClosePosition params: invalid position size: " + toString(_size)) + " max: ") + toString(absOldPositionSize)))
780770 }
781771
782772
783-func getTwapSpotPrice () = {
784- let minuteId = ((lastTimestamp() / 1000) / 60)
785- let startMinuteId = (minuteId - TWAP_INTERVAL)
786- let listStr = valueOrElse(getString(this, k_lastDataStr), "")
787- let list = split(listStr, ",")
788- func filterFn (accumulator,next) = if ((startMinuteId >= valueOrErrorMessage(parseInt(next), ("getTwapSpotPrice: invalid int: " + listStr))))
789- then (accumulator :+ parseIntValue(next))
790- else accumulator
791-
792- let listF = {
793- let $l = list
794- let $s = size($l)
795- let $acc0 = nil
796- func $f0_1 ($a,$i) = if (($i >= $s))
797- then $a
798- else filterFn($a, $l[$i])
799-
800- func $f0_2 ($a,$i) = if (($i >= $s))
801- then $a
802- else throw("List size exceeds 20")
803-
804- $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20)
805- }
806- let maxIndex = if ((size(listF) > 0))
807- then max(listF)
808- else valueOrErrorMessage(parseInt(list[0]), ("getTwapSpotPrice: invalid int: " + listStr))
809- let lastMinuteId = valueOrElse(getInteger(this, k_lastMinuteId), 0)
810- let endLastCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(lastMinuteId))), 0)
811- let endLastPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(lastMinuteId))), 0)
812- let nowCumulativePrice = (endLastCumulativePrice + ((minuteId - lastMinuteId) * endLastPrice))
813- let startLastCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(maxIndex))), 0)
814- let startLastPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(maxIndex))), 0)
815- let startCumulativePrice = (startLastCumulativePrice + ((startMinuteId - maxIndex) * startLastPrice))
816- ((nowCumulativePrice - startCumulativePrice) / TWAP_INTERVAL)
817- }
818-
819-
820773 func getTerminalAmmState () = {
821774 let _positionSize = totalPositionSize()
822775 if ((_positionSize == 0))
823776 then $Tuple2(qtAstR(), bsAstR())
824777 else {
825778 let direction = (_positionSize > 0)
826- let $t03940139580 = swapOutput(direction, abs(_positionSize), false)
827- let currentNetMarketValue = $t03940139580._1
828- let terminalQuoteAssetReserve = $t03940139580._2
829- let terminalBaseAssetReserve = $t03940139580._3
779+ let $t03730837487 = swapOutput(direction, abs(_positionSize), false)
780+ let currentNetMarketValue = $t03730837487._1
781+ let terminalQuoteAssetReserve = $t03730837487._2
782+ let terminalBaseAssetReserve = $t03730837487._3
830783 $Tuple2(terminalQuoteAssetReserve, terminalBaseAssetReserve)
831784 }
832785 }
833786
834787
835788 func getQuoteAssetWeight (baseAssetReserve,totalPositionSize,quoteAssetReserve,targetPrice) = {
836789 let b = toBigInt(baseAssetReserve)
837790 let sz = toBigInt(totalPositionSize)
838791 let q = toBigInt(quoteAssetReserve)
839792 let p = toBigInt(targetPrice)
840793 let k = bmuld(q, b)
841794 let newB = (b + sz)
842795 let newQ = bdivd(k, newB)
843796 let z = bdivd(newQ, newB)
844797 let result = bdivd(p, z)
845798 toInt(result)
846799 }
847800
848801
849802 func getSyncTerminalPrice (_terminalPrice,_qtAstR,_bsAstR) = {
850803 let _positionSize = totalPositionSize()
851804 if ((_positionSize == 0))
852805 then {
853806 let newQtAstW = divd(muld(_terminalPrice, _bsAstR), _qtAstR)
854807 $Tuple3(newQtAstW, DECIMAL_UNIT, 0)
855808 }
856809 else {
857810 let direction = (_positionSize > 0)
858811 let currentNetMarketValue = swapOutput(direction, abs(_positionSize), false)._1
859812 let newQtAstW = getQuoteAssetWeight(_bsAstR, _positionSize, _qtAstR, _terminalPrice)
860813 let newBsAstW = DECIMAL_UNIT
861814 let marginToVault = getPositionNotionalAndUnrealizedPnlByValues(_positionSize, currentNetMarketValue, _qtAstR, newQtAstW, _bsAstR, newBsAstW, PNL_OPTION_SPOT)._2
862815 $Tuple3(newQtAstW, newBsAstW, marginToVault)
863816 }
864817 }
865818
866819
867820 func getFunding () = {
868821 let underlyingPrice = getOraclePrice()
869- let spotTwapPrice = getTwapSpotPrice()
822+ let spotTwapPrice = getSpotPrice()
870823 let premium = (spotTwapPrice - underlyingPrice)
871824 if (if (if ((totalShortPositionSize() == 0))
872825 then true
873826 else (totalLongPositionSize() == 0))
874827 then true
875828 else isMarketClosed())
876829 then $Tuple3(0, 0, 0)
877830 else if ((0 > premium))
878831 then {
879832 let shortPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
880833 if ((fundingMode() == FUNDING_ASYMMETRIC))
881834 then {
882835 let longPremiumFraction = divd(muld(shortPremiumFraction, totalShortPositionSize()), totalLongPositionSize())
883836 $Tuple3(shortPremiumFraction, longPremiumFraction, 0)
884837 }
885838 else {
886839 let shortTotalPremiumFraction = abs(muld(shortPremiumFraction, totalShortPositionSize()))
887840 let longTotalPremiumFraction = abs(muld(shortPremiumFraction, totalLongPositionSize()))
888841 let premiumToVault = (shortTotalPremiumFraction - longTotalPremiumFraction)
889842 $Tuple3(shortPremiumFraction, shortPremiumFraction, premiumToVault)
890843 }
891844 }
892845 else {
893846 let longPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
894847 if ((fundingMode() == FUNDING_ASYMMETRIC))
895848 then {
896849 let shortPremiumFraction = divd(muld(longPremiumFraction, totalLongPositionSize()), totalShortPositionSize())
897850 $Tuple3(shortPremiumFraction, longPremiumFraction, 0)
898851 }
899852 else {
900853 let longTotalPremiumFraction = abs(muld(longPremiumFraction, totalLongPositionSize()))
901854 let shortTotalPremiumFraction = abs(muld(longPremiumFraction, totalShortPositionSize()))
902855 let premiumToVault = (longTotalPremiumFraction - shortTotalPremiumFraction)
903856 $Tuple3(longPremiumFraction, longPremiumFraction, premiumToVault)
904857 }
905858 }
906859 }
907860
908861
909862 func getAdjustedFee (_artifactId,_baseFeeDiscount) = {
910863 let baseFeeRaw = fee()
911864 let baseFee = muld(baseFeeRaw, _baseFeeDiscount)
912- let $t04332643821 = if ((_artifactId != ""))
865+ let $t04122941724 = if ((_artifactId != ""))
913866 then {
914867 let artifactKind = strA(nftManagerAddress(), toCompositeKey(k_token_type, _artifactId))
915868 if ((artifactKind == FEE_REDUCTION_TOKEN_TYPE))
916869 then {
917870 let reduction = intA(nftManagerAddress(), toCompositeKey(k_token_param, _artifactId))
918871 let adjustedFee = muld(baseFee, reduction)
919872 $Tuple2(adjustedFee, true)
920873 }
921874 else throw("Invalid attached artifact")
922875 }
923876 else $Tuple2(baseFee, false)
924- let adjustedFee = $t04332643821._1
925- let burnArtifact = $t04332643821._2
877+ let adjustedFee = $t04122941724._1
878+ let burnArtifact = $t04122941724._2
926879 $Tuple2(adjustedFee, burnArtifact)
927880 }
928881
929882
930883 func isSameAssetOrNoPosition (_trader,_assetId) = {
931884 let oldPositionSize = getPosition(_trader)._1
932885 if ((oldPositionSize == 0))
933886 then true
934887 else (getPositionAsset(_trader) == _assetId)
935888 }
936889
937890
938891 func isSameAsset (_trader,_assetId) = (getPositionAsset(_trader) == _assetId)
939892
940893
941894 func getForTraderWithArtifact (_trader,_artifactId) = {
942895 let doGetFeeDiscount = invoke(minerAddress(), "computeFeeDiscount", [_trader], nil)
943896 if ((doGetFeeDiscount == doGetFeeDiscount))
944897 then {
945898 let feeDiscount = match doGetFeeDiscount {
946899 case x: Int =>
947900 x
948901 case _ =>
949902 throw("Invalid computeFeeDiscount result")
950903 }
951- let $t04450144575 = getAdjustedFee(_artifactId, feeDiscount)
952- let adjustedFee = $t04450144575._1
953- let burnArtifact = $t04450144575._2
904+ let $t04240442478 = getAdjustedFee(_artifactId, feeDiscount)
905+ let adjustedFee = $t04240442478._1
906+ let burnArtifact = $t04240442478._2
954907 $Tuple2(adjustedFee, burnArtifact)
955908 }
956909 else throw("Strict value is not equal to itself.")
957910 }
958911
959912
960913 func getArtifactId (i) = {
961914 let artifactId = if ((size(i.payments) > 1))
962915 then toBase58String(valueOrErrorMessage(i.payments[1].assetId, "Invalid artifactId"))
963916 else ""
964917 artifactId
965918 }
966919
967920
968921 func distributeFee (_feeAmount) = {
969922 let feeToStakers = muld(_feeAmount, feeToStakersPercent())
970923 let feeToVault = (_feeAmount - feeToStakers)
971924 $Tuple2(feeToStakers, feeToVault)
972925 }
973926
974927
975928 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)]
976929
977930
978931 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)]
979932
980933
981934 func incrementPositionSequenceNumber (_isNewPosition,_address) = if (_isNewPosition)
982935 then {
983936 let currentSequence = lastSequence()
984937 [IntegerEntry(toCompositeKey(k_positionSequence, _address), (currentSequence + 1)), IntegerEntry(k_sequence, (currentSequence + 1))]
985938 }
986939 else nil
987940
988941
989942 func updatePositionFee (_isNewPosition,_address,_fee) = if (_isNewPosition)
990943 then [IntegerEntry(toCompositeKey(k_positionFee, _address), _fee)]
991944 else nil
992945
993946
994947 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)]
995948
996949
997-func appendTwap (_price) = {
998- let minuteId = ((lastTimestamp() / 1000) / 60)
999- let previousMinuteId = valueOrElse(getInteger(this, k_lastMinuteId), 0)
1000- if ((previousMinuteId > minuteId))
1001- then throw("TWAP out-of-order")
1002- else {
1003- let lastMinuteId = if ((previousMinuteId == 0))
1004- then minuteId
1005- else previousMinuteId
1006- if ((minuteId > previousMinuteId))
1007- then {
1008- let prevCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(previousMinuteId))), 0)
1009- let prevPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(previousMinuteId))), _price)
1010- let lastCumulativePrice = (prevCumulativePrice + ((minuteId - lastMinuteId) * prevPrice))
1011- let list = pushToQueue(strToList(valueOrElse(getString(this, k_lastDataStr), "")), TWAP_INTERVAL, toString(minuteId))
1012-[IntegerEntry(toCompositeKey(k_twapDataLastCumulativePrice, toString(minuteId)), lastCumulativePrice), IntegerEntry(toCompositeKey(k_twapDataLastPrice, toString(minuteId)), _price), IntegerEntry(toCompositeKey(k_twapDataPreviousMinuteId, toString(minuteId)), previousMinuteId), IntegerEntry(k_lastMinuteId, minuteId), StringEntry(k_lastDataStr, listToStr(list))]
1013- }
1014- else {
1015- let twapDataPreviousMinuteId = valueOrElse(getInteger(this, toCompositeKey(k_twapDataPreviousMinuteId, toString(minuteId))), 0)
1016- let prevCumulativePrice = valueOrElse(getInteger(this, toCompositeKey(k_twapDataLastCumulativePrice, toString(twapDataPreviousMinuteId))), 0)
1017- let prevPrice = valueOrElse(getInteger(this, toCompositeKey(k_twapDataLastPrice, toString(twapDataPreviousMinuteId))), _price)
1018- let lastCumulativePrice = (prevCumulativePrice + ((minuteId - twapDataPreviousMinuteId) * prevPrice))
1019-[IntegerEntry(toCompositeKey(k_twapDataLastCumulativePrice, toString(minuteId)), lastCumulativePrice), IntegerEntry(toCompositeKey(k_twapDataLastPrice, toString(minuteId)), _price)]
1020- }
1021- }
1022- }
1023-
1024-
1025950 func updateAmmReserves (_qtAstR,_bsAstR) = [IntegerEntry(k_quoteAssetReserve, _qtAstR), IntegerEntry(k_baseAssetReserve, _bsAstR)]
1026951
1027952
1028953 func updateAmmWeights (_qtAstW,_bsAstW) = [IntegerEntry(k_quoteAssetWeight, _qtAstW), IntegerEntry(k_baseAssetWeight, _bsAstW)]
1029954
1030955
1031956 func updateAmm (_qtAstR,_bsAstR,_totalPositionSizeAfter,_openInterestNotional,_totalLongPositionSize,_totalShortPositionSize,_totalLongOpenNotional,_totalShortOpenNotional) = {
1032957 let _qtAstW = qtAstW()
1033958 let _bsAstW = bsAstW()
1034959 if (((_totalLongPositionSize - _totalShortPositionSize) != _totalPositionSizeAfter))
1035960 then throw(((((("Invalid AMM state data: " + toString(_totalLongPositionSize)) + " + ") + toString(_totalShortPositionSize)) + " != ") + toString(_totalPositionSizeAfter)))
1036- 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)]) ++ appendTwap(divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))))
961+ 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)])
1037962 }
1038963
1039964
1040965 func deletePosition (_address) = [DeleteEntry(toCompositeKey(k_positionSize, _address)), DeleteEntry(toCompositeKey(k_positionMargin, _address)), DeleteEntry(toCompositeKey(k_positionOpenNotional, _address)), DeleteEntry(toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, _address)), DeleteEntry(toCompositeKey(k_positionAsset, _address)), DeleteEntry(toCompositeKey(k_positionFee, _address)), DeleteEntry(toCompositeKey(k_positionLastUpdatedTimestamp, _address))]
1041966
1042967
1043968 func withdraw (_address,_amount) = {
1044969 let balance = assetBalance(this, quoteAsset())
1045970 if ((_amount > balance))
1046971 then throw(((("Unable to withdraw " + toString(_amount)) + " from contract balance ") + toString(balance)))
1047972 else [ScriptTransfer(_address, _amount, quoteAsset())]
1048973 }
1049974
1050975
1051976 func updateBalance (i) = if ((0 > i))
1052977 then throw("Balance")
1053978 else [IntegerEntry(k_balance, i)]
1054979
1055980
1056981 func transferFee (i) = [ScriptTransfer(stakingAddress(), i, quoteAsset())]
1057982
1058983
1059984 func doBurnArtifact (_burnArtifact,i) = if (_burnArtifact)
1060985 then [Burn(valueOrErrorMessage(i.payments[1].assetId, "Invalid artifact"), 1)]
1061986 else nil
1062987
1063988
1064989 @Callable(i)
1065990 func pause () = if ((i.caller != adminAddress()))
1066991 then throw("Invalid pause params")
1067992 else [BooleanEntry(k_paused, true)]
1068993
1069994
1070995
1071996 @Callable(i)
1072997 func unpause () = if ((i.caller != adminAddress()))
1073998 then throw("Invalid unpause params")
1074999 else [BooleanEntry(k_paused, false)]
10751000
10761001
10771002
10781003 @Callable(i)
10791004 func setCloseOnly () = if ((i.caller != adminAddress()))
10801005 then throw("Invalid setCloseOnly params")
10811006 else [BooleanEntry(k_closeOnly, true)]
10821007
10831008
10841009
10851010 @Callable(i)
10861011 func unsetCloseOnly () = if ((i.caller != adminAddress()))
10871012 then throw("Invalid unsetCloseOnly params")
10881013 else [BooleanEntry(k_closeOnly, false)]
10891014
10901015
10911016
10921017 @Callable(i)
10931018 func addLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
10941019 then true
10951020 else (0 >= _quoteAssetAmount))
10961021 then throw("Invalid addLiquidity params")
10971022 else {
10981023 let _qtAstR = qtAstR()
10991024 let _bsAstR = bsAstR()
11001025 let _qtAstW = qtAstW()
11011026 let _bsAstW = bsAstW()
11021027 let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
11031028 let qtAstRAfter = (_qtAstR + _quoteAssetAmount)
11041029 let baseAssetAmountToAdd = (divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR)
11051030 let bsAstRAfter = (_bsAstR + baseAssetAmountToAdd)
1106- let $t05479454945 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1107- let newQuoteAssetWeight = $t05479454945._1
1108- let newBaseAssetWeight = $t05479454945._2
1109- let marginToVault = $t05479454945._3
1031+ let $t05043150582 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1032+ let newQuoteAssetWeight = $t05043150582._1
1033+ let newBaseAssetWeight = $t05043150582._2
1034+ let marginToVault = $t05043150582._3
11101035 let doExchangePnL = if ((marginToVault != 0))
11111036 then {
11121037 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
11131038 if ((doExchangePnL == doExchangePnL))
11141039 then nil
11151040 else throw("Strict value is not equal to itself.")
11161041 }
11171042 else nil
11181043 if ((doExchangePnL == doExchangePnL))
11191044 then (updateAmmReserves(qtAstRAfter, bsAstRAfter) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
11201045 else throw("Strict value is not equal to itself.")
11211046 }
11221047
11231048
11241049
11251050 @Callable(i)
11261051 func removeLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
11271052 then true
11281053 else (_quoteAssetAmount >= 0))
11291054 then throw("Invalid removeLiquidity params")
11301055 else {
11311056 let _qtAstR = qtAstR()
11321057 let _bsAstR = bsAstR()
11331058 let _qtAstW = qtAstW()
11341059 let _bsAstW = bsAstW()
11351060 let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
11361061 let qtAstRAfter = (_qtAstR - _quoteAssetAmount)
11371062 let baseAssetAmountToRemove = abs((divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR))
11381063 let bsAstRAfter = (_bsAstR - baseAssetAmountToRemove)
1139- let $t05604156192 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1140- let newQuoteAssetWeight = $t05604156192._1
1141- let newBaseAssetWeight = $t05604156192._2
1142- let marginToVault = $t05604156192._3
1064+ let $t05167851829 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1065+ let newQuoteAssetWeight = $t05167851829._1
1066+ let newBaseAssetWeight = $t05167851829._2
1067+ let marginToVault = $t05167851829._3
11431068 let doExchangePnL = if ((marginToVault != 0))
11441069 then {
11451070 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
11461071 if ((doExchangePnL == doExchangePnL))
11471072 then nil
11481073 else throw("Strict value is not equal to itself.")
11491074 }
11501075 else nil
11511076 if ((doExchangePnL == doExchangePnL))
11521077 then (updateAmmReserves(qtAstRAfter, bsAstRAfter) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
11531078 else throw("Strict value is not equal to itself.")
11541079 }
11551080
11561081
11571082
11581083 @Callable(i)
11591084 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))
11601085 then true
11611086 else (0 >= _initMarginRatio))
11621087 then true
11631088 else (0 >= _mmr))
11641089 then true
11651090 else (0 >= _liquidationFeeRatio))
11661091 then true
11671092 else (0 >= _fee))
11681093 then true
11691094 else (0 >= _spreadLimit))
11701095 then true
11711096 else (0 >= _maxPriceImpact))
11721097 then true
11731098 else (0 >= _partialLiquidationRatio))
11741099 then true
11751100 else (0 >= _maxPriceSpread))
11761101 then true
11771102 else (0 >= _maxOpenNotional))
11781103 then true
11791104 else (0 >= _feeToStakersPercent))
11801105 then true
11811106 else (_feeToStakersPercent > DECIMAL_UNIT))
11821107 then true
11831108 else (0 >= _maxOracleDelay))
11841109 then true
11851110 else (0 >= _rolloverFee))
11861111 then true
11871112 else if ((_fundingMode != FUNDING_SYMMETRIC))
11881113 then (_fundingMode != FUNDING_ASYMMETRIC)
11891114 else false)
11901115 then true
11911116 else !(initialized()))
11921117 then true
11931118 else (i.caller != adminAddress()))
11941119 then throw("Invalid changeSettings params")
11951120 else updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact, _partialLiquidationRatio, _maxPriceSpread, _maxOpenNotional, _feeToStakersPercent, _maxOracleDelay, _rolloverFee, _fundingMode)
11961121
11971122
11981123
11991124 @Callable(i)
12001125 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))
12011126 then true
12021127 else (0 >= _bsAstR))
12031128 then true
12041129 else (0 >= _fundingPeriod))
12051130 then true
12061131 else (0 >= _initMarginRatio))
12071132 then true
12081133 else (0 >= _mmr))
12091134 then true
12101135 else (0 >= _liquidationFeeRatio))
12111136 then true
12121137 else (0 >= _fee))
12131138 then true
12141139 else (0 >= _spreadLimit))
12151140 then true
12161141 else (0 >= _maxPriceImpact))
12171142 then true
12181143 else (0 >= _partialLiquidationRatio))
12191144 then true
12201145 else (0 >= _maxPriceSpread))
12211146 then true
12221147 else (0 >= _maxOpenNotional))
12231148 then true
12241149 else (0 >= _feeToStakersPercent))
12251150 then true
12261151 else (_feeToStakersPercent > DECIMAL_UNIT))
12271152 then true
12281153 else (0 >= _maxOracleDelay))
12291154 then true
12301155 else (0 >= _rolloverFee))
12311156 then true
12321157 else if ((_fundingMode != FUNDING_SYMMETRIC))
12331158 then (_fundingMode != FUNDING_ASYMMETRIC)
12341159 else false)
12351160 then true
12361161 else initialized())
12371162 then true
12381163 else (i.caller != this))
12391164 then throw("Invalid initialize parameters")
12401165 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)))])
12411166
12421167
12431168
12441169 @Callable(i)
12451170 func increasePosition (_direction,_leverage,_minBaseAssetAmount,_refLink) = {
12461171 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
12471172 if ((sync == sync))
12481173 then {
12491174 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
12501175 if ((ensureCalledOnce == ensureCalledOnce))
12511176 then {
12521177 let _trader = getActualCaller(i)
12531178 let _rawAmount = i.payments[0].amount
12541179 let _assetId = i.payments[0].assetId
12551180 let _assetIdStr = toBase58String(value(_assetId))
12561181 let isQuoteAsset = (_assetId == quoteAsset())
12571182 if (if (if (if (if (if (if (if (if (if ((_direction != DIR_LONG))
12581183 then (_direction != DIR_SHORT)
12591184 else false)
12601185 then true
12611186 else (0 >= _rawAmount))
12621187 then true
12631188 else !(initialized()))
12641189 then true
12651190 else !(isQuoteAsset))
12661191 then true
12671192 else !(isSameAssetOrNoPosition(_trader, _assetIdStr)))
12681193 then true
12691194 else !(requireMoreMarginRatio(divd(DECIMAL_UNIT, _leverage), initMarginRatio(), true)))
12701195 then true
12711196 else paused())
12721197 then true
12731198 else closeOnly())
12741199 then true
12751200 else isMarketClosed())
12761201 then throw("Invalid increasePosition parameters")
12771202 else {
1278- let $t06231662465 = getForTraderWithArtifact(_trader, getArtifactId(i))
1279- let adjustedFee = $t06231662465._1
1280- let burnArtifact = $t06231662465._2
1203+ let $t05795358102 = getForTraderWithArtifact(_trader, getArtifactId(i))
1204+ let adjustedFee = $t05795358102._1
1205+ let burnArtifact = $t05795358102._2
12811206 let _amount = divd(_rawAmount, (muld(adjustedFee, _leverage) + DECIMAL_UNIT))
12821207 let distributeFeeAmount = (_rawAmount - _amount)
12831208 let referrerFeeAny = invoke(referralAddress(), "acceptPaymentWithLink", [_trader, _refLink], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
12841209 if ((referrerFeeAny == referrerFeeAny))
12851210 then {
12861211 let referrerFee = match referrerFeeAny {
12871212 case x: Int =>
12881213 x
12891214 case _ =>
12901215 throw("Invalid referrerFee")
12911216 }
12921217 let feeAmount = (distributeFeeAmount - referrerFee)
1293- let $t06296163129 = getPosition(_trader)
1294- let oldPositionSize = $t06296163129._1
1295- let oldPositionMargin = $t06296163129._2
1296- let oldPositionOpenNotional = $t06296163129._3
1297- let oldPositionLstUpdCPF = $t06296163129._4
1298- let oldPositionTimestamp = $t06296163129._5
1218+ let $t05859858766 = getPosition(_trader)
1219+ let oldPositionSize = $t05859858766._1
1220+ let oldPositionMargin = $t05859858766._2
1221+ let oldPositionOpenNotional = $t05859858766._3
1222+ let oldPositionLstUpdCPF = $t05859858766._4
1223+ let oldPositionTimestamp = $t05859858766._5
12991224 let isNewPosition = (oldPositionSize == 0)
13001225 let isSameDirection = if ((oldPositionSize > 0))
13011226 then (_direction == DIR_LONG)
13021227 else (_direction == DIR_SHORT)
13031228 let expandExisting = if (!(isNewPosition))
13041229 then isSameDirection
13051230 else false
13061231 let isAdd = (_direction == DIR_LONG)
1307- let $t06341866539 = if (if (isNewPosition)
1232+ let $t05905562176 = if (if (isNewPosition)
13081233 then true
13091234 else expandExisting)
13101235 then {
13111236 let openNotional = muld(_amount, _leverage)
1312- let $t06392764100 = swapInput(isAdd, openNotional)
1313- let amountBaseAssetBought = $t06392764100._1
1314- let quoteAssetReserveAfter = $t06392764100._2
1315- let baseAssetReserveAfter = $t06392764100._3
1316- let totalPositionSizeAfter = $t06392764100._4
1237+ let $t05956459737 = swapInput(isAdd, openNotional)
1238+ let amountBaseAssetBought = $t05956459737._1
1239+ let quoteAssetReserveAfter = $t05956459737._2
1240+ let baseAssetReserveAfter = $t05956459737._3
1241+ let totalPositionSizeAfter = $t05956459737._4
13171242 if (if ((_minBaseAssetAmount != 0))
13181243 then (_minBaseAssetAmount > abs(amountBaseAssetBought))
13191244 else false)
13201245 then throw(((("Limit error: " + toString(abs(amountBaseAssetBought))) + " < ") + toString(_minBaseAssetAmount)))
13211246 else {
13221247 let newPositionSize = (oldPositionSize + amountBaseAssetBought)
13231248 let totalLongOpenInterestAfter = (openInterestLong() + (if ((newPositionSize > 0))
13241249 then openNotional
13251250 else 0))
13261251 let totalShortOpenInterestAfter = (openInterestShort() + (if ((0 > newPositionSize))
13271252 then openNotional
13281253 else 0))
1329- let $t06464664921 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, _amount)
1330- let remainMargin = $t06464664921._1
1331- let x1 = $t06464664921._2
1332- let x2 = $t06464664921._3
1333- let rolloverFee = $t06464664921._4
1254+ let $t06028360558 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, _amount)
1255+ let remainMargin = $t06028360558._1
1256+ let x1 = $t06028360558._2
1257+ let x2 = $t06028360558._3
1258+ let rolloverFee = $t06028360558._4
13341259 if (!(requireNotOverSpreadLimit(quoteAssetReserveAfter, baseAssetReserveAfter)))
13351260 then throw("Over max spread limit")
13361261 else if (!(requireNotOverMaxOpenNotional(totalLongOpenInterestAfter, totalShortOpenInterestAfter)))
13371262 then throw("Over max open notional")
13381263 else $Tuple14(newPositionSize, remainMargin, (oldPositionOpenNotional + openNotional), latestCumulativePremiumFraction(newPositionSize), lastTimestamp(), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, (openInterestNotional() + openNotional), (totalLongPositionSize() + (if ((newPositionSize > 0))
13391264 then abs(amountBaseAssetBought)
13401265 else 0)), (totalShortPositionSize() + (if ((0 > newPositionSize))
13411266 then abs(amountBaseAssetBought)
13421267 else 0)), totalLongOpenInterestAfter, totalShortOpenInterestAfter, rolloverFee)
13431268 }
13441269 }
13451270 else {
13461271 let openNotional = muld(_amount, _leverage)
1347- let $t06623966355 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1348- let oldPositionNotional = $t06623966355._1
1349- let unrealizedPnl = $t06623966355._2
1272+ let $t06187661992 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1273+ let oldPositionNotional = $t06187661992._1
1274+ let unrealizedPnl = $t06187661992._2
13501275 if ((oldPositionNotional > openNotional))
13511276 then throw("Use decreasePosition to decrease position size")
13521277 else throw("Close position first")
13531278 }
1354- let newPositionSize = $t06341866539._1
1355- let newPositionRemainMargin = $t06341866539._2
1356- let newPositionOpenNotional = $t06341866539._3
1357- let newPositionLatestCPF = $t06341866539._4
1358- let newPositionTimestamp = $t06341866539._5
1359- let baseAssetReserveAfter = $t06341866539._6
1360- let quoteAssetReserveAfter = $t06341866539._7
1361- let totalPositionSizeAfter = $t06341866539._8
1362- let openInterestNotionalAfter = $t06341866539._9
1363- let totalLongAfter = $t06341866539._10
1364- let totalShortAfter = $t06341866539._11
1365- let totalLongOpenInterestAfter = $t06341866539._12
1366- let totalShortOpenInterestAfter = $t06341866539._13
1367- let rolloverFee = $t06341866539._14
1368- let $t06654566616 = distributeFee((feeAmount + rolloverFee))
1369- let feeToStakers = $t06654566616._1
1370- let feeToVault = $t06654566616._2
1279+ let newPositionSize = $t05905562176._1
1280+ let newPositionRemainMargin = $t05905562176._2
1281+ let newPositionOpenNotional = $t05905562176._3
1282+ let newPositionLatestCPF = $t05905562176._4
1283+ let newPositionTimestamp = $t05905562176._5
1284+ let baseAssetReserveAfter = $t05905562176._6
1285+ let quoteAssetReserveAfter = $t05905562176._7
1286+ let totalPositionSizeAfter = $t05905562176._8
1287+ let openInterestNotionalAfter = $t05905562176._9
1288+ let totalLongAfter = $t05905562176._10
1289+ let totalShortAfter = $t05905562176._11
1290+ let totalLongOpenInterestAfter = $t05905562176._12
1291+ let totalShortOpenInterestAfter = $t05905562176._13
1292+ let rolloverFee = $t05905562176._14
1293+ let $t06218262253 = distributeFee((feeAmount + rolloverFee))
1294+ let feeToStakers = $t06218262253._1
1295+ let feeToVault = $t06218262253._2
13711296 let stake = if ((_amount >= rolloverFee))
13721297 then invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), (_amount - rolloverFee))])
13731298 else invoke(vaultAddress(), "withdrawLocked", [(rolloverFee - _amount)], nil)
13741299 if ((stake == stake))
13751300 then {
13761301 let depositVault = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
13771302 if ((depositVault == depositVault))
13781303 then {
13791304 let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, feeAmount], nil)
13801305 if ((notifyFee == notifyFee))
13811306 then {
13821307 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
13831308 if ((notifyNotional == notifyNotional))
13841309 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))
13851310 else throw("Strict value is not equal to itself.")
13861311 }
13871312 else throw("Strict value is not equal to itself.")
13881313 }
13891314 else throw("Strict value is not equal to itself.")
13901315 }
13911316 else throw("Strict value is not equal to itself.")
13921317 }
13931318 else throw("Strict value is not equal to itself.")
13941319 }
13951320 }
13961321 else throw("Strict value is not equal to itself.")
13971322 }
13981323 else throw("Strict value is not equal to itself.")
13991324 }
14001325
14011326
14021327
14031328 @Callable(i)
14041329 func addMargin () = {
14051330 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
14061331 if ((sync == sync))
14071332 then {
14081333 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
14091334 if ((ensureCalledOnce == ensureCalledOnce))
14101335 then {
14111336 let _trader = toString(i.caller)
14121337 let _amount = i.payments[0].amount
14131338 let _assetId = i.payments[0].assetId
14141339 let _assetIdStr = toBase58String(value(_assetId))
14151340 let isQuoteAsset = (_assetId == quoteAsset())
14161341 if (if (if (if (if (if (if (!(isQuoteAsset))
14171342 then true
14181343 else !(requireOpenPosition(toString(i.caller))))
14191344 then true
14201345 else !(isSameAsset(_trader, _assetIdStr)))
14211346 then true
14221347 else !(initialized()))
14231348 then true
14241349 else paused())
14251350 then true
14261351 else closeOnly())
14271352 then true
14281353 else isMarketClosed())
14291354 then throw("Invalid addMargin parameters")
14301355 else {
1431- let $t06887369041 = getPosition(_trader)
1432- let oldPositionSize = $t06887369041._1
1433- let oldPositionMargin = $t06887369041._2
1434- let oldPositionOpenNotional = $t06887369041._3
1435- let oldPositionLstUpdCPF = $t06887369041._4
1436- let oldPositionTimestamp = $t06887369041._5
1356+ let $t06451064678 = getPosition(_trader)
1357+ let oldPositionSize = $t06451064678._1
1358+ let oldPositionMargin = $t06451064678._2
1359+ let oldPositionOpenNotional = $t06451064678._3
1360+ let oldPositionLstUpdCPF = $t06451064678._4
1361+ let oldPositionTimestamp = $t06451064678._5
14371362 let stake = invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), _amount)])
14381363 if ((stake == stake))
14391364 then {
14401365 let rolloverFee = calcRolloverFee(oldPositionMargin, oldPositionTimestamp)
14411366 let doTransferFeeToStakers = if ((rolloverFee > 0))
14421367 then {
1443- let $t06932669385 = distributeFee(rolloverFee)
1444- let feeToStakers = $t06932669385._1
1445- let feeToVault = $t06932669385._2
1368+ let $t06496365022 = distributeFee(rolloverFee)
1369+ let feeToStakers = $t06496365022._1
1370+ let feeToVault = $t06496365022._2
14461371 let unstake = invoke(vaultAddress(), "withdrawLocked", [feeToStakers], nil)
14471372 if ((unstake == unstake))
14481373 then {
14491374 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(feeToVault)], nil)
14501375 if ((lockBadDebt == lockBadDebt))
14511376 then transferFee(feeToStakers)
14521377 else throw("Strict value is not equal to itself.")
14531378 }
14541379 else throw("Strict value is not equal to itself.")
14551380 }
14561381 else nil
14571382 if ((doTransferFeeToStakers == doTransferFeeToStakers))
14581383 then ((updatePosition(_trader, oldPositionSize, ((oldPositionMargin - rolloverFee) + _amount), oldPositionOpenNotional, oldPositionLstUpdCPF, lastTimestamp()) ++ updateBalance(((cbalance() + _amount) - rolloverFee))) ++ doTransferFeeToStakers)
14591384 else throw("Strict value is not equal to itself.")
14601385 }
14611386 else throw("Strict value is not equal to itself.")
14621387 }
14631388 }
14641389 else throw("Strict value is not equal to itself.")
14651390 }
14661391 else throw("Strict value is not equal to itself.")
14671392 }
14681393
14691394
14701395
14711396 @Callable(i)
14721397 func removeMargin (_amount) = {
14731398 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
14741399 if ((sync == sync))
14751400 then {
14761401 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
14771402 if ((ensureCalledOnce == ensureCalledOnce))
14781403 then {
14791404 let _trader = toString(i.caller)
14801405 if (if (if (if (if ((0 >= _amount))
14811406 then true
14821407 else !(requireOpenPosition(_trader)))
14831408 then true
14841409 else !(initialized()))
14851410 then true
14861411 else paused())
14871412 then true
14881413 else isMarketClosed())
14891414 then throw("Invalid removeMargin parameters")
14901415 else {
1491- let $t07075870926 = getPosition(_trader)
1492- let oldPositionSize = $t07075870926._1
1493- let oldPositionMargin = $t07075870926._2
1494- let oldPositionOpenNotional = $t07075870926._3
1495- let oldPositionLstUpdCPF = $t07075870926._4
1496- let oldPositionTimestamp = $t07075870926._5
1497- let $t07093271181 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, -(_amount))
1498- let remainMargin = $t07093271181._1
1499- let badDebt = $t07093271181._2
1500- let fundingPayment = $t07093271181._3
1501- let rolloverFee = $t07093271181._4
1416+ let $t06639566563 = getPosition(_trader)
1417+ let oldPositionSize = $t06639566563._1
1418+ let oldPositionMargin = $t06639566563._2
1419+ let oldPositionOpenNotional = $t06639566563._3
1420+ let oldPositionLstUpdCPF = $t06639566563._4
1421+ let oldPositionTimestamp = $t06639566563._5
1422+ let $t06656966818 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, -(_amount))
1423+ let remainMargin = $t06656966818._1
1424+ let badDebt = $t06656966818._2
1425+ let fundingPayment = $t06656966818._3
1426+ let rolloverFee = $t06656966818._4
15021427 if ((badDebt != 0))
15031428 then throw("Invalid removed margin amount")
15041429 else {
15051430 let marginRatio = calcMarginRatio(remainMargin, badDebt, oldPositionOpenNotional)
15061431 if (!(requireMoreMarginRatio(marginRatio, initMarginRatio(), true)))
15071432 then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
15081433 else {
1509- let $t07156771626 = distributeFee(rolloverFee)
1510- let feeToStakers = $t07156771626._1
1511- let feeToVault = $t07156771626._2
1434+ let $t06720467263 = distributeFee(rolloverFee)
1435+ let feeToStakers = $t06720467263._1
1436+ let feeToVault = $t06720467263._2
15121437 let doTransferFeeToStakers = if ((rolloverFee > 0))
15131438 then {
15141439 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(feeToVault)], nil)
15151440 if ((lockBadDebt == lockBadDebt))
15161441 then transferFee(feeToStakers)
15171442 else throw("Strict value is not equal to itself.")
15181443 }
15191444 else nil
15201445 if ((doTransferFeeToStakers == doTransferFeeToStakers))
15211446 then {
15221447 let unstake = invoke(vaultAddress(), "withdrawLocked", [(_amount + feeToStakers)], nil)
15231448 if ((unstake == unstake))
15241449 then (((updatePosition(_trader, oldPositionSize, remainMargin, oldPositionOpenNotional, latestCumulativePremiumFraction(oldPositionSize), lastTimestamp()) ++ withdraw(i.caller, _amount)) ++ updateBalance(((cbalance() - _amount) - rolloverFee))) ++ doTransferFeeToStakers)
15251450 else throw("Strict value is not equal to itself.")
15261451 }
15271452 else throw("Strict value is not equal to itself.")
15281453 }
15291454 }
15301455 }
15311456 }
15321457 else throw("Strict value is not equal to itself.")
15331458 }
15341459 else throw("Strict value is not equal to itself.")
15351460 }
15361461
15371462
15381463
15391464 @Callable(i)
15401465 func closePosition (_size,_minQuoteAssetAmount,_addToMargin) = {
15411466 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
15421467 if ((sync == sync))
15431468 then {
15441469 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
15451470 if ((ensureCalledOnce == ensureCalledOnce))
15461471 then {
15471472 let _trader = getActualCaller(i)
15481473 let _traderAddress = valueOrErrorMessage(addressFromString(_trader), "Invalid caller")
15491474 let positionFee = getPositionFee(_trader)
15501475 if (if (if (if (if (if (!(requireOpenPosition(_trader)))
15511476 then true
15521477 else !(initialized()))
15531478 then true
15541479 else paused())
15551480 then true
15561481 else (0 >= _size))
15571482 then true
15581483 else (0 > _minQuoteAssetAmount))
15591484 then true
15601485 else isMarketClosed())
15611486 then throw("Invalid closePosition parameters")
15621487 else {
15631488 let oldPositionTimestamp = getPosition(_trader)._5
1564- let $t07380174386 = internalClosePosition(_trader, _size, positionFee, _minQuoteAssetAmount, _addToMargin, true, true)
1565- let newPositionSize = $t07380174386._1
1566- let newPositionMargin = $t07380174386._2
1567- let newPositionOpenNotional = $t07380174386._3
1568- let newPositionLstUpdCPF = $t07380174386._4
1569- let positionBadDebt = $t07380174386._5
1570- let realizedPnl = $t07380174386._6
1571- let marginToTrader = $t07380174386._7
1572- let quoteAssetReserveAfter = $t07380174386._8
1573- let baseAssetReserveAfter = $t07380174386._9
1574- let totalPositionSizeAfter = $t07380174386._10
1575- let openInterestNotionalAfter = $t07380174386._11
1576- let totalLongAfter = $t07380174386._12
1577- let totalShortAfter = $t07380174386._13
1578- let totalLongOpenInterestAfter = $t07380174386._14
1579- let totalShortOpenInterestAfter = $t07380174386._15
1580- let realizedFee = $t07380174386._16
1489+ let $t06943870023 = internalClosePosition(_trader, _size, positionFee, _minQuoteAssetAmount, _addToMargin, true, true)
1490+ let newPositionSize = $t06943870023._1
1491+ let newPositionMargin = $t06943870023._2
1492+ let newPositionOpenNotional = $t06943870023._3
1493+ let newPositionLstUpdCPF = $t06943870023._4
1494+ let positionBadDebt = $t06943870023._5
1495+ let realizedPnl = $t06943870023._6
1496+ let marginToTrader = $t06943870023._7
1497+ let quoteAssetReserveAfter = $t06943870023._8
1498+ let baseAssetReserveAfter = $t06943870023._9
1499+ let totalPositionSizeAfter = $t06943870023._10
1500+ let openInterestNotionalAfter = $t06943870023._11
1501+ let totalLongAfter = $t06943870023._12
1502+ let totalShortAfter = $t06943870023._13
1503+ let totalLongOpenInterestAfter = $t06943870023._14
1504+ let totalShortOpenInterestAfter = $t06943870023._15
1505+ let realizedFee = $t06943870023._16
15811506 if ((positionBadDebt > 0))
15821507 then throw("Invalid closePosition parameters: bad debt")
15831508 else if ((oldPositionTimestamp >= lastTimestamp()))
15841509 then throw("Invalid closePosition parameters: wait at least 1 block before closing the position")
15851510 else {
15861511 let isPartialClose = (newPositionSize != 0)
15871512 let withdrawAmount = (marginToTrader + realizedFee)
15881513 let ammBalance = (cbalance() - withdrawAmount)
15891514 let ammNewBalance = if ((0 > ammBalance))
15901515 then 0
15911516 else ammBalance
15921517 let unstake = invoke(vaultAddress(), "withdrawLocked", [withdrawAmount], nil)
15931518 if ((unstake == unstake))
15941519 then {
1595- let $t07505875117 = distributeFee(realizedFee)
1596- let feeToStakers = $t07505875117._1
1597- let feeToVault = $t07505875117._2
1520+ let $t07069570754 = distributeFee(realizedFee)
1521+ let feeToStakers = $t07069570754._1
1522+ let feeToVault = $t07069570754._2
15981523 let depositVault = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
15991524 if ((depositVault == depositVault))
16001525 then {
16011526 let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, realizedFee], nil)
16021527 if ((notifyFee == notifyFee))
16031528 then {
16041529 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
16051530 if ((notifyNotional == notifyNotional))
16061531 then (((((if (isPartialClose)
16071532 then updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, lastTimestamp())
16081533 else deletePosition(_trader)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ (if ((marginToTrader > 0))
16091534 then withdraw(_traderAddress, marginToTrader)
16101535 else nil)) ++ updateBalance(ammNewBalance)) ++ transferFee(feeToStakers))
16111536 else throw("Strict value is not equal to itself.")
16121537 }
16131538 else throw("Strict value is not equal to itself.")
16141539 }
16151540 else throw("Strict value is not equal to itself.")
16161541 }
16171542 else throw("Strict value is not equal to itself.")
16181543 }
16191544 }
16201545 }
16211546 else throw("Strict value is not equal to itself.")
16221547 }
16231548 else throw("Strict value is not equal to itself.")
16241549 }
16251550
16261551
16271552
16281553 @Callable(i)
16291554 func liquidate (_trader) = {
16301555 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
16311556 if ((sync == sync))
16321557 then {
16331558 let spotMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
16341559 let liquidationMarginRatio = if (isOverFluctuationLimit())
16351560 then {
16361561 let oracleMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_ORACLE)
16371562 vmax(spotMarginRatio, oracleMarginRatio)
16381563 }
16391564 else spotMarginRatio
16401565 if (if (if (if (if (!(requireMoreMarginRatio(liquidationMarginRatio, maintenanceMarginRatio(), false)))
16411566 then true
16421567 else !(requireOpenPosition(_trader)))
16431568 then true
16441569 else !(initialized()))
16451570 then true
16461571 else paused())
16471572 then true
16481573 else isMarketClosed())
16491574 then throw("Unable to liquidate")
16501575 else {
16511576 let isPartialLiquidation = if (if ((spotMarginRatio > liquidationFeeRatio()))
16521577 then (partialLiquidationRatio() > 0)
16531578 else false)
16541579 then (DECIMAL_UNIT > partialLiquidationRatio())
16551580 else false
16561581 let oldPositionSize = getPosition(_trader)._1
16571582 let positionSizeAbs = abs(oldPositionSize)
1658- let $t07753877861 = if (isPartialLiquidation)
1583+ let $t07317573498 = if (isPartialLiquidation)
16591584 then {
16601585 let liquidationSize = getPartialLiquidationAmount(_trader, oldPositionSize)
16611586 let liquidationRatio = divd(abs(liquidationSize), positionSizeAbs)
16621587 $Tuple2(liquidationRatio, abs(liquidationSize))
16631588 }
16641589 else $Tuple2(0, positionSizeAbs)
1665- let liquidationRatio = $t07753877861._1
1666- let liquidationSize = $t07753877861._2
1667- let $t07786778505 = internalClosePosition(_trader, if (isPartialLiquidation)
1590+ let liquidationRatio = $t07317573498._1
1591+ let liquidationSize = $t07317573498._2
1592+ let $t07350474142 = internalClosePosition(_trader, if (isPartialLiquidation)
16681593 then liquidationSize
16691594 else positionSizeAbs, liquidationFeeRatio(), 0, true, false, true)
1670- let newPositionSize = $t07786778505._1
1671- let newPositionMargin = $t07786778505._2
1672- let newPositionOpenNotional = $t07786778505._3
1673- let newPositionLstUpdCPF = $t07786778505._4
1674- let positionBadDebt = $t07786778505._5
1675- let realizedPnl = $t07786778505._6
1676- let marginToTrader = $t07786778505._7
1677- let quoteAssetReserveAfter = $t07786778505._8
1678- let baseAssetReserveAfter = $t07786778505._9
1679- let totalPositionSizeAfter = $t07786778505._10
1680- let openInterestNotionalAfter = $t07786778505._11
1681- let totalLongAfter = $t07786778505._12
1682- let totalShortAfter = $t07786778505._13
1683- let totalLongOpenInterestAfter = $t07786778505._14
1684- let totalShortOpenInterestAfter = $t07786778505._15
1685- let liquidationPenalty = $t07786778505._16
1595+ let newPositionSize = $t07350474142._1
1596+ let newPositionMargin = $t07350474142._2
1597+ let newPositionOpenNotional = $t07350474142._3
1598+ let newPositionLstUpdCPF = $t07350474142._4
1599+ let positionBadDebt = $t07350474142._5
1600+ let realizedPnl = $t07350474142._6
1601+ let marginToTrader = $t07350474142._7
1602+ let quoteAssetReserveAfter = $t07350474142._8
1603+ let baseAssetReserveAfter = $t07350474142._9
1604+ let totalPositionSizeAfter = $t07350474142._10
1605+ let openInterestNotionalAfter = $t07350474142._11
1606+ let totalLongAfter = $t07350474142._12
1607+ let totalShortAfter = $t07350474142._13
1608+ let totalLongOpenInterestAfter = $t07350474142._14
1609+ let totalShortOpenInterestAfter = $t07350474142._15
1610+ let liquidationPenalty = $t07350474142._16
16861611 let feeToLiquidator = (liquidationPenalty / 2)
16871612 let feeToVault = (liquidationPenalty - feeToLiquidator)
16881613 let ammBalance = (cbalance() - liquidationPenalty)
16891614 let newAmmBalance = if ((0 > ammBalance))
16901615 then 0
16911616 else ammBalance
16921617 let lockBadDebt = if ((positionBadDebt > 0))
16931618 then {
16941619 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [(positionBadDebt + liquidationPenalty)], nil)
16951620 if ((lockBadDebt == lockBadDebt))
16961621 then nil
16971622 else throw("Strict value is not equal to itself.")
16981623 }
16991624 else nil
17001625 if ((lockBadDebt == lockBadDebt))
17011626 then {
17021627 let unstake = invoke(vaultAddress(), "withdrawLocked", [liquidationPenalty], nil)
17031628 if ((unstake == unstake))
17041629 then {
17051630 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
17061631 if ((depositInsurance == depositInsurance))
17071632 then {
17081633 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
17091634 if ((notifyNotional == notifyNotional))
17101635 then ((((if (isPartialLiquidation)
17111636 then updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, lastTimestamp())
17121637 else deletePosition(_trader)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ withdraw(i.caller, feeToLiquidator)) ++ updateBalance(newAmmBalance))
17131638 else throw("Strict value is not equal to itself.")
17141639 }
17151640 else throw("Strict value is not equal to itself.")
17161641 }
17171642 else throw("Strict value is not equal to itself.")
17181643 }
17191644 else throw("Strict value is not equal to itself.")
17201645 }
17211646 }
17221647 else throw("Strict value is not equal to itself.")
17231648 }
17241649
17251650
17261651
17271652 @Callable(i)
17281653 func payFunding () = {
17291654 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
17301655 if ((sync == sync))
17311656 then {
17321657 let fundingBlockTimestamp = nextFundingBlockTimestamp()
17331658 if (if (if ((fundingBlockTimestamp > lastTimestamp()))
17341659 then true
17351660 else !(initialized()))
17361661 then true
17371662 else paused())
17381663 then throw(((("Invalid funding block timestamp: " + toString(lastTimestamp())) + " < ") + toString(fundingBlockTimestamp)))
17391664 else {
17401665 let underlyingPrice = getOraclePrice()
1741- let $t08061880696 = getFunding()
1742- let shortPremiumFraction = $t08061880696._1
1743- let longPremiumFraction = $t08061880696._2
1744- let premiumToVault = $t08061880696._3
1666+ let $t07625576333 = getFunding()
1667+ let shortPremiumFraction = $t07625576333._1
1668+ let longPremiumFraction = $t07625576333._2
1669+ let premiumToVault = $t07625576333._3
17451670 let doPayFundingToVault = if ((premiumToVault > 0))
17461671 then {
17471672 let doPayFundingToVault = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(premiumToVault)], nil)
17481673 if ((doPayFundingToVault == doPayFundingToVault))
17491674 then nil
17501675 else throw("Strict value is not equal to itself.")
17511676 }
17521677 else nil
17531678 if ((doPayFundingToVault == doPayFundingToVault))
17541679 then updateFunding((fundingBlockTimestamp + fundingPeriodSeconds()), (latestLongCumulativePremiumFraction() + longPremiumFraction), (latestShortCumulativePremiumFraction() + shortPremiumFraction), divd(longPremiumFraction, underlyingPrice), divd(shortPremiumFraction, underlyingPrice))
17551680 else throw("Strict value is not equal to itself.")
17561681 }
17571682 }
17581683 else throw("Strict value is not equal to itself.")
17591684 }
17601685
17611686
17621687
17631688 @Callable(i)
17641689 func syncTerminalPriceToOracle () = {
17651690 let _qtAstR = qtAstR()
17661691 let _bsAstR = bsAstR()
1767- let $t08174782113 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1768- let newQuoteAssetWeight = $t08174782113._1
1769- let newBaseAssetWeight = $t08174782113._2
1770- let marginToVault = $t08174782113._3
1692+ let $t07738477750 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1693+ let newQuoteAssetWeight = $t07738477750._1
1694+ let newBaseAssetWeight = $t07738477750._2
1695+ let marginToVault = $t07738477750._3
17711696 let marginToVaultAdj = if (if ((0 > marginToVault))
17721697 then (abs(marginToVault) > cbalance())
17731698 else false)
17741699 then -(cbalance())
17751700 else marginToVault
17761701 let doExchangePnL = if ((marginToVaultAdj != 0))
17771702 then {
17781703 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVaultAdj], nil)
17791704 if ((doExchangePnL == doExchangePnL))
17801705 then nil
17811706 else throw("Strict value is not equal to itself.")
17821707 }
17831708 else nil
17841709 if ((doExchangePnL == doExchangePnL))
1785- then ((updateBalance((cbalance() + marginToVaultAdj)) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight)) ++ appendTwap(divd(muld(_qtAstR, newQuoteAssetWeight), muld(_bsAstR, newBaseAssetWeight))))
1710+ then (updateBalance((cbalance() + marginToVaultAdj)) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
17861711 else throw("Strict value is not equal to itself.")
17871712 }
17881713
17891714
17901715
17911716 @Callable(i)
17921717 func ensureCalledOnce () = if ((i.caller != this))
17931718 then throw("Invalid saveCurrentTxId parameters")
17941719 else {
17951720 let lastTx = valueOrElse(getString(this, k_lastTx), "")
17961721 if ((lastTx != toBase58String(i.transactionId)))
17971722 then [StringEntry(k_lastTx, lastTx)]
17981723 else throw("Can not call vAMM methods twice in one tx")
17991724 }
18001725
18011726
18021727
18031728 @Callable(i)
18041729 func view_calcRemainMarginWithFundingPayment (_trader) = {
18051730 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
18061731 if ((sync == sync))
18071732 then {
1808- let $t08375583879 = getPosition(_trader)
1809- let positionSize = $t08375583879._1
1810- let positionMargin = $t08375583879._2
1811- let pon = $t08375583879._3
1812- let positionLstUpdCPF = $t08375583879._4
1813- let positionTimestamp = $t08375583879._5
1814- let $t08388283983 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1815- let positionNotional = $t08388283983._1
1816- let unrealizedPnl = $t08388283983._2
1817- let $t08398684210 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLstUpdCPF, positionTimestamp, unrealizedPnl)
1818- let remainMargin = $t08398684210._1
1819- let badDebt = $t08398684210._2
1820- let fundingPayment = $t08398684210._3
1821- let rolloverFee = $t08398684210._4
1733+ let $t07929979423 = getPosition(_trader)
1734+ let positionSize = $t07929979423._1
1735+ let positionMargin = $t07929979423._2
1736+ let pon = $t07929979423._3
1737+ let positionLstUpdCPF = $t07929979423._4
1738+ let positionTimestamp = $t07929979423._5
1739+ let $t07942679527 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1740+ let positionNotional = $t07942679527._1
1741+ let unrealizedPnl = $t07942679527._2
1742+ let $t07953079754 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLstUpdCPF, positionTimestamp, unrealizedPnl)
1743+ let remainMargin = $t07953079754._1
1744+ let badDebt = $t07953079754._2
1745+ let fundingPayment = $t07953079754._3
1746+ let rolloverFee = $t07953079754._4
18221747 throw(((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)) + s(rolloverFee)))
18231748 }
18241749 else throw("Strict value is not equal to itself.")
18251750 }
18261751
18271752
18281753
18291754 @Callable(i)
18301755 func view_getPegAdjustCost (_price) = {
18311756 let _qtAstR = qtAstR()
18321757 let _bsAstR = bsAstR()
18331758 let result = getSyncTerminalPrice(_price, _qtAstR, _bsAstR)
18341759 throw(toString(result._3))
18351760 }
18361761
18371762
18381763
18391764 @Callable(i)
18401765 func view_getTerminalAmmPrice () = {
1841- let $t08493385014 = getTerminalAmmState()
1842- let terminalQuoteAssetReserve = $t08493385014._1
1843- let terminalBaseAssetReserve = $t08493385014._2
1766+ let $t08047780558 = getTerminalAmmState()
1767+ let terminalQuoteAssetReserve = $t08047780558._1
1768+ let terminalBaseAssetReserve = $t08047780558._2
18441769 let price = divd(muld(terminalQuoteAssetReserve, qtAstW()), muld(terminalBaseAssetReserve, bsAstW()))
18451770 throw(toString(price))
18461771 }
18471772
18481773
18491774
18501775 @Callable(i)
18511776 func view_getFunding () = {
18521777 let underlyingPrice = getOraclePrice()
1853- let $t08552385601 = getFunding()
1854- let shortPremiumFraction = $t08552385601._1
1855- let longPremiumFraction = $t08552385601._2
1856- let premiumToVault = $t08552385601._3
1778+ let $t08106781145 = getFunding()
1779+ let shortPremiumFraction = $t08106781145._1
1780+ let longPremiumFraction = $t08106781145._2
1781+ let premiumToVault = $t08106781145._3
18571782 let longFunding = divd(longPremiumFraction, underlyingPrice)
18581783 let shortFunding = divd(shortPremiumFraction, underlyingPrice)
1859- throw(((((s(longFunding) + s(shortFunding)) + s(getTwapSpotPrice())) + s(getOraclePrice())) + s(premiumToVault)))
1784+ throw(((((s(longFunding) + s(shortFunding)) + s(getSpotPrice())) + s(getOraclePrice())) + s(premiumToVault)))
18601785 }
18611786
18621787
18631788
18641789 @Callable(i)
18651790 func computeSpotPrice () = {
18661791 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
18671792 if ((sync == sync))
18681793 then {
18691794 let result = getSpotPrice()
18701795 $Tuple2(nil, result)
18711796 }
18721797 else throw("Strict value is not equal to itself.")
18731798 }
18741799
18751800
18761801
18771802 @Callable(i)
18781803 func computeFeeForTraderWithArtifact (_trader,_artifactId) = {
18791804 let result = getForTraderWithArtifact(_trader, _artifactId)
18801805 $Tuple2(nil, result)
18811806 }
18821807
18831808
18841809 @Verifier(tx)
18851810 func verify () = {
18861811 let coordinatorStr = getString(this, k_coordinatorAddress)
18871812 if (isDefined(coordinatorStr))
18881813 then {
18891814 let admin = getString(addressFromStringValue(value(coordinatorStr)), k_admin_address)
18901815 if (isDefined(admin))
18911816 then valueOrElse(getBoolean(addressFromStringValue(value(admin)), ((("status_" + toString(this)) + "_") + toBase58String(tx.id))), false)
18921817 else throw("unable to verify: admin not set in coordinator")
18931818 }
18941819 else sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
18951820 }
18961821

github/deemru/w8io/3ef1775 
292.84 ms