tx · HTfirUBuhiK3P4VTMJ4s56n5tovnXV4K5jvfuyarxoB7

3NBeJWgTz9QJrsC3rzuhVtRpXVD21oCsWgT:  -0.07500000 Waves

2023.02.15 19:40 [2450982] smart account 3NBeJWgTz9QJrsC3rzuhVtRpXVD21oCsWgT > SELF 0.00000000 Waves

{ "type": 13, "id": "HTfirUBuhiK3P4VTMJ4s56n5tovnXV4K5jvfuyarxoB7", "fee": 7500000, "feeAssetId": null, "timestamp": 1676479234735, "version": 2, "chainId": 84, "sender": "3NBeJWgTz9QJrsC3rzuhVtRpXVD21oCsWgT", "senderPublicKey": "8fXX7iuB1dSAMSCqCZTqJNBUmZmKB6oamJwom9WrvTvs", "proofs": [ "2XM79KyDrYGTJPFEerkfvLGCzxC6TCMSi4aT2ajQDT8kwMS6SXZwTNvq1Hz681EvKaKZ3KcHEmf9WZ5ey6GPGmTR" ], "script": "base64:BgJ0CAISABIAEgASABIDCgEBEgMKAQESEAoOAQEBAQEBAQEBAQEBAQESFQoTAQEBAQEBAQgICAEBAQEBAQEBARIGCgQBAQEIEgASAwoBARIFCgMBAQQSAwoBCBIAEgASABIDCgEIEgMKAQESABIAEgASBAoCCAjAAQAMa19iYXNlT3JhY2xlAgxrX2Jhc2VPcmFjbGUADWtfcXVvdGVPcmFjbGUCDWtfcXVvdGVPcmFjbGUACWtfYmFsYW5jZQIJa19iYWxhbmNlAAprX3NlcXVlbmNlAgprX3NlcXVlbmNlAA5rX3Bvc2l0aW9uU2l6ZQIOa19wb3NpdGlvblNpemUAEGtfcG9zaXRpb25NYXJnaW4CEGtfcG9zaXRpb25NYXJnaW4AFmtfcG9zaXRpb25PcGVuTm90aW9uYWwCFmtfcG9zaXRpb25PcGVuTm90aW9uYWwALmtfcG9zaXRpb25MYXN0VXBkYXRlZEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24CEmtfcG9zaXRpb25GcmFjdGlvbgASa19wb3NpdGlvblNlcXVlbmNlAhJrX3Bvc2l0aW9uU2VxdWVuY2UAD2tfcG9zaXRpb25Bc3NldAIPa19wb3NpdGlvbkFzc2V0AA1rX3Bvc2l0aW9uRmVlAg1rX3Bvc2l0aW9uRmVlAB5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRUaW1lc3RhbXACE2tfcG9zaXRpb25UaW1lc3RhbXAADWtfaW5pdGlhbGl6ZWQCDWtfaW5pdGlhbGl6ZWQACGtfcGF1c2VkAghrX3BhdXNlZAALa19jbG9zZU9ubHkCC2tfY2xvc2VPbmx5AAVrX2ZlZQIFa19mZWUADWtfcm9sbG92ZXJGZWUCDmtfcm9sbG92ZXJfZmVlAA9rX2Z1bmRpbmdQZXJpb2QCD2tfZnVuZGluZ1BlcmlvZAARa19pbml0TWFyZ2luUmF0aW8CEWtfaW5pdE1hcmdpblJhdGlvABhrX21haW50ZW5hbmNlTWFyZ2luUmF0aW8CBWtfbW1yABVrX2xpcXVpZGF0aW9uRmVlUmF0aW8CFWtfbGlxdWlkYXRpb25GZWVSYXRpbwAZa19wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwIWa19wYXJ0TGlxdWlkYXRpb25SYXRpbwANa19zcHJlYWRMaW1pdAINa19zcHJlYWRMaW1pdAAQa19tYXhQcmljZUltcGFjdAIQa19tYXhQcmljZUltcGFjdAAQa19tYXhQcmljZVNwcmVhZAIQa19tYXhQcmljZVNwcmVhZAARa19tYXhPcGVuTm90aW9uYWwCEWtfbWF4T3Blbk5vdGlvbmFsABVrX2ZlZVRvU3Rha2Vyc1BlcmNlbnQCFWtfZmVlVG9TdGFrZXJzUGVyY2VudAAQa19tYXhPcmFjbGVEZWxheQIQa19tYXhPcmFjbGVEZWxheQANa19mdW5kaW5nTW9kZQINa19mdW5kaW5nTW9kZQANa19sYXN0RGF0YVN0cgINa19sYXN0RGF0YVN0cgAOa19sYXN0TWludXRlSWQCDmtfbGFzdE1pbnV0ZUlkAB1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQIda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UAE2tfdHdhcERhdGFMYXN0UHJpY2UCE2tfdHdhcERhdGFMYXN0UHJpY2UAGmtfdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkAhprX3R3YXBEYXRhUHJldmlvdXNNaW51dGVJZAAla19sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgIba19sYXRlc3RMb25nUHJlbWl1bUZyYWN0aW9uACZrX2xhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgIca19sYXRlc3RTaG9ydFByZW1pdW1GcmFjdGlvbgASa19uZXh0RnVuZGluZ0Jsb2NrAh5rX25leHRGdW5kaW5nQmxvY2tNaW5UaW1lc3RhbXAAEWtfbG9uZ0Z1bmRpbmdSYXRlAhFrX2xvbmdGdW5kaW5nUmF0ZQASa19zaG9ydEZ1bmRpbmdSYXRlAhJrX3Nob3J0RnVuZGluZ1JhdGUAE2tfcXVvdGVBc3NldFJlc2VydmUCCGtfcXRBc3RSABJrX2Jhc2VBc3NldFJlc2VydmUCCGtfYnNBc3RSABJrX3F1b3RlQXNzZXRXZWlnaHQCCGtfcXRBc3RXABFrX2Jhc2VBc3NldFdlaWdodAIIa19ic0FzdFcAE2tfdG90YWxQb3NpdGlvblNpemUCE2tfdG90YWxQb3NpdGlvblNpemUAF2tfdG90YWxMb25nUG9zaXRpb25TaXplAhdrX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQAYa190b3RhbFNob3J0UG9zaXRpb25TaXplAhhrX3RvdGFsU2hvcnRQb3NpdGlvblNpemUAFmtfb3BlbkludGVyZXN0Tm90aW9uYWwCFmtfb3BlbkludGVyZXN0Tm90aW9uYWwAE2tfb3BlbkludGVyZXN0U2hvcnQCE2tfb3BlbkludGVyZXN0U2hvcnQAEmtfb3BlbkludGVyZXN0TG9uZwISa19vcGVuSW50ZXJlc3RMb25nAAhrX2xhc3RUeAIIa19sYXN0VHgAFGtfY29vcmRpbmF0b3JBZGRyZXNzAhRrX2Nvb3JkaW5hdG9yQWRkcmVzcwAPa192YXVsdF9hZGRyZXNzAg9rX3ZhdWx0X2FkZHJlc3MAD2tfYWRtaW5fYWRkcmVzcwIPa19hZG1pbl9hZGRyZXNzAA1rX3F1b3RlX2Fzc2V0Ag1rX3F1b3RlX2Fzc2V0AA9rX3F1b3RlX3N0YWtpbmcCD2tfcXVvdGVfc3Rha2luZwARa19zdGFraW5nX2FkZHJlc3MCEWtfc3Rha2luZ19hZGRyZXNzAA9rX21pbmVyX2FkZHJlc3MCD2tfbWluZXJfYWRkcmVzcwAQa19vcmRlcnNfYWRkcmVzcwIQa19vcmRlcnNfYWRkcmVzcwASa19yZWZlcnJhbF9hZGRyZXNzAhJrX3JlZmVycmFsX2FkZHJlc3MAEmtfZXhjaGFuZ2VfYWRkcmVzcwISa19leGNoYW5nZV9hZGRyZXNzABVrX25mdF9tYW5hZ2VyX2FkZHJlc3MCFWtfbmZ0X21hbmFnZXJfYWRkcmVzcwEOdG9Db21wb3NpdGVLZXkCBF9rZXkIX2FkZHJlc3MJAKwCAgkArAICBQRfa2V5AgFfBQhfYWRkcmVzcwELY29vcmRpbmF0b3IACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgUEdGhpcwUUa19jb29yZGluYXRvckFkZHJlc3MCE0Nvb3JkaW5hdG9yIG5vdCBzZXQBDGFkbWluQWRkcmVzcwAJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUPa19hZG1pbl9hZGRyZXNzAQpxdW90ZUFzc2V0AAkA2QQBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABQ1rX3F1b3RlX2Fzc2V0ARFxdW90ZUFzc2V0U3Rha2luZwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABQ9rX3F1b3RlX3N0YWtpbmcCG1F1b3RlIGFzc2V0IHN0YWtpbmcgbm90IHNldAEOc3Rha2luZ0FkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAURa19zdGFraW5nX2FkZHJlc3MCD1N0YWtpbmcgbm90IHNldAEMdmF1bHRBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFD2tfdmF1bHRfYWRkcmVzcwINVmF1bHQgbm90IHNldAEMbWluZXJBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFD2tfbWluZXJfYWRkcmVzcwINTWluZXIgbm90IHNldAENb3JkZXJzQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABRBrX29yZGVyc19hZGRyZXNzAg5PcmRlcnMgbm90IHNldAEPcmVmZXJyYWxBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFEmtfcmVmZXJyYWxfYWRkcmVzcwIQUmVmZXJyYWwgbm90IHNldAERbmZ0TWFuYWdlckFkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUVa19uZnRfbWFuYWdlcl9hZGRyZXNzAhNORlQgTWFuYWdlciBub3Qgc2V0AA1rX3Rva2VuX3BhcmFtAg1rX3Rva2VuX3BhcmFtAAxrX3Rva2VuX3R5cGUCDGtfdG9rZW5fdHlwZQAYRkVFX1JFRFVDVElPTl9UT0tFTl9UWVBFAg1mZWVfcmVkdWN0aW9uAAhESVJfTE9ORwABAAlESVJfU0hPUlQAAgANVFdBUF9JTlRFUlZBTAAPAAdTRUNPTkRTAOgHAA9ERUNJTUFMX05VTUJFUlMABgAMREVDSU1BTF9VTklUCQBoAgABCQBoAgkAaAIJAGgCCQBoAgkAaAIACgAKAAoACgAKAAoAD01JTlVURVNfSU5fWUVBUgkAaAIAoIogBQxERUNJTUFMX1VOSVQAB09ORV9EQVkJAGgCAICjBQUMREVDSU1BTF9VTklUAA9QTkxfT1BUSU9OX1NQT1QAAQARUE5MX09QVElPTl9PUkFDTEUAAgASRlVORElOR19BU1lNTUVUUklDAAEAEUZVTkRJTkdfU1lNTUVUUklDAAIBAXMBAl94CQCsAgIJAKQDAQUCX3gCASwBBGRpdmQCAl94Al95CQBuBAUCX3gFDERFQ0lNQUxfVU5JVAUCX3kFCEhBTEZFVkVOAQRtdWxkAgJfeAJfeQkAbgQFAl94BQJfeQUMREVDSU1BTF9VTklUBQhIQUxGRVZFTgEFYmRpdmQCAl94Al95CQC9AgQFAl94CQC2AgEFDERFQ0lNQUxfVU5JVAUCX3kFCEhBTEZFVkVOAQVibXVsZAICX3gCX3kJAL0CBAUCX3gFAl95CQC2AgEFDERFQ0lNQUxfVU5JVAUISEFMRkVWRU4BA2FicwECX3gDCQBmAgUCX3gAAAUCX3gJAQEtAQUCX3gBBHZtYXgCAl94Al95AwkAZwIFAl94BQJfeQUCX3gFAl95AQlsaXN0VG9TdHIBBV9saXN0AwkAAAIJAJADAQUFX2xpc3QAAAIACQC5CQIFBV9saXN0AgEsAQlzdHJUb0xpc3QBBF9zdHIDCQAAAgUEX3N0cgIABQNuaWwJALUJAgUEX3N0cgIBLAELcHVzaFRvUXVldWUDBV9saXN0CF9tYXhTaXplBl92YWx1ZQMJAGYCCQCQAwEFBV9saXN0BQhfbWF4U2l6ZQkAzQgCCQDRCAIFBV9saXN0AAAFBl92YWx1ZQkAzQgCBQVfbGlzdAUGX3ZhbHVlAQNpbnQBAWsJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQR0aGlzBQFrCQCsAgICDW5vIHZhbHVlIGZvciAFAWsBBWludE9yAgFrA2RlZgkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQFrBQNkZWYBBHN0ckECCF9hZGRyZXNzBF9rZXkEA3ZhbAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFCF9hZGRyZXNzBQRfa2V5CQCsAgICEU5vIHZhbHVlIGZvciBrZXkgBQRfa2V5BQN2YWwBBGludEECCF9hZGRyZXNzBF9rZXkEA3ZhbAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFCF9hZGRyZXNzBQRfa2V5CQCsAgICEU5vIHZhbHVlIGZvciBrZXkgBQRfa2V5BQN2YWwBCGNiYWxhbmNlAAkBA2ludAEFCWtfYmFsYW5jZQEDZmVlAAkBA2ludAEFBWtfZmVlAQ9yb2xsb3ZlckZlZVJhdGUACQEDaW50AQUNa19yb2xsb3ZlckZlZQEPaW5pdE1hcmdpblJhdGlvAAkBA2ludAEFEWtfaW5pdE1hcmdpblJhdGlvAQZxdEFzdFIACQEDaW50AQUTa19xdW90ZUFzc2V0UmVzZXJ2ZQEGYnNBc3RSAAkBA2ludAEFEmtfYmFzZUFzc2V0UmVzZXJ2ZQEGcXRBc3RXAAkBBWludE9yAgUSa19xdW90ZUFzc2V0V2VpZ2h0BQxERUNJTUFMX1VOSVQBBmJzQXN0VwAJAQVpbnRPcgIFEWtfYmFzZUFzc2V0V2VpZ2h0BQxERUNJTUFMX1VOSVQBEXRvdGFsUG9zaXRpb25TaXplAAkBA2ludAEFE2tfdG90YWxQb3NpdGlvblNpemUBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAAkBA2ludAEFFmtfb3BlbkludGVyZXN0Tm90aW9uYWwBEW9wZW5JbnRlcmVzdFNob3J0AAkBA2ludAEFE2tfb3BlbkludGVyZXN0U2hvcnQBEG9wZW5JbnRlcmVzdExvbmcACQEDaW50AQUSa19vcGVuSW50ZXJlc3RMb25nARluZXh0RnVuZGluZ0Jsb2NrVGltZXN0YW1wAAkBA2ludAEFEmtfbmV4dEZ1bmRpbmdCbG9jawEQZnVuZGluZ1BlcmlvZFJhdwAJAQNpbnQBBQ9rX2Z1bmRpbmdQZXJpb2QBFGZ1bmRpbmdQZXJpb2REZWNpbWFsAAkAaAIJARBmdW5kaW5nUGVyaW9kUmF3AAUMREVDSU1BTF9VTklUARRmdW5kaW5nUGVyaW9kU2Vjb25kcwAJAGgCCQEQZnVuZGluZ1BlcmlvZFJhdwAFB1NFQ09ORFMBFm1haW50ZW5hbmNlTWFyZ2luUmF0aW8ACQEDaW50AQUYa19tYWludGVuYW5jZU1hcmdpblJhdGlvARNsaXF1aWRhdGlvbkZlZVJhdGlvAAkBA2ludAEFFWtfbGlxdWlkYXRpb25GZWVSYXRpbwEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8ACQEDaW50AQUZa19wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwELc3ByZWFkTGltaXQACQEDaW50AQUNa19zcHJlYWRMaW1pdAEObWF4UHJpY2VJbXBhY3QACQEDaW50AQUQa19tYXhQcmljZUltcGFjdAEObWF4UHJpY2VTcHJlYWQACQEDaW50AQUQa19tYXhQcmljZVNwcmVhZAEPbWF4T3Blbk5vdGlvbmFsAAkBA2ludAEFEWtfbWF4T3Blbk5vdGlvbmFsASNsYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAJAQNpbnQBBSVrX2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uASRsYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24ACQEDaW50AQUma19sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BFnRvdGFsU2hvcnRQb3NpdGlvblNpemUACQEDaW50AQUYa190b3RhbFNob3J0UG9zaXRpb25TaXplARV0b3RhbExvbmdQb3NpdGlvblNpemUACQEDaW50AQUXa190b3RhbExvbmdQb3NpdGlvblNpemUBDGxhc3RTZXF1ZW5jZQAJAQVpbnRPcgIFCmtfc2VxdWVuY2UAAAETZmVlVG9TdGFrZXJzUGVyY2VudAAJAQNpbnQBBRVrX2ZlZVRvU3Rha2Vyc1BlcmNlbnQBDm1heE9yYWNsZURlbGF5AAkBA2ludAEFEGtfbWF4T3JhY2xlRGVsYXkBC2Z1bmRpbmdNb2RlAAkBBWludE9yAgUNa19mdW5kaW5nTW9kZQUSRlVORElOR19BU1lNTUVUUklDAQ1sYXN0VGltZXN0YW1wAAgFCWxhc3RCbG9jawl0aW1lc3RhbXABD2dldEFjdHVhbENhbGxlcgEBaQkBC3ZhbHVlT3JFbHNlAgkAnQgCCQENb3JkZXJzQWRkcmVzcwACCGtfc2VuZGVyCQClCAEIBQFpBmNhbGxlcgEWcmVxdWlyZU1vcmVNYXJnaW5SYXRpbwMMX21hcmdpblJhdGlvEF9iYXNlTWFyZ2luUmF0aW8UX2xhcmdlclRoYW5PckVxdWFsVG8EFHJlbWFpbmluZ01hcmdpblJhdGlvCQBlAgUMX21hcmdpblJhdGlvBRBfYmFzZU1hcmdpblJhdGlvAwMFFF9sYXJnZXJUaGFuT3JFcXVhbFRvCQBmAgAABRRyZW1haW5pbmdNYXJnaW5SYXRpbwcJAAIBCQCsAgIJAKwCAgkArAICAhBJbnZhbGlkIG1hcmdpbjogCQCkAwEFDF9tYXJnaW5SYXRpbwIDIDwgCQCkAwEFEF9iYXNlTWFyZ2luUmF0aW8DAwkBASEBBRRfbGFyZ2VyVGhhbk9yRXF1YWxUbwkAZwIFFHJlbWFpbmluZ01hcmdpblJhdGlvAAAHCQACAQkArAICCQCsAgIJAKwCAgIQSW52YWxpZCBtYXJnaW46IAkApAMBBQxfbWFyZ2luUmF0aW8CAyA+IAkApAMBBRBfYmFzZU1hcmdpblJhdGlvBgEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgENX3Bvc2l0aW9uU2l6ZQMJAAACBQ1fcG9zaXRpb25TaXplAAAJAAIBAixTaG91bGQgbm90IGJlIGNhbGxlZCB3aXRoIF9wb3NpdGlvblNpemUgPT0gMAMJAGYCBQ1fcG9zaXRpb25TaXplAAAJASNsYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAJASRsYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24AAQtnZXRQb3NpdGlvbgEHX3RyYWRlcgQPcG9zaXRpb25TaXplT3B0CQCaCAIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFDmtfcG9zaXRpb25TaXplBQdfdHJhZGVyBAckbWF0Y2gwBQ9wb3NpdGlvblNpemVPcHQDCQABAgUHJG1hdGNoMAIDSW50BAxwb3NpdGlvblNpemUFByRtYXRjaDAJAJcKBQUMcG9zaXRpb25TaXplCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBRBrX3Bvc2l0aW9uTWFyZ2luBQdfdHJhZGVyCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBRZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBQdfdHJhZGVyCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBS5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBQdfdHJhZGVyCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBR5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRUaW1lc3RhbXAFB190cmFkZXIJAJcKBQAAAAAAAAAAAAABEGdldFBvc2l0aW9uQXNzZXQBB190cmFkZXIEEHBvc2l0aW9uQXNzZXRPcHQJAJ0IAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUPa19wb3NpdGlvbkFzc2V0BQdfdHJhZGVyBAckbWF0Y2gwBRBwb3NpdGlvbkFzc2V0T3B0AwkAAQIFByRtYXRjaDACBlN0cmluZwQNcG9zaXRpb25Bc3NldAUHJG1hdGNoMAUNcG9zaXRpb25Bc3NldAkA2AQBCQEKcXVvdGVBc3NldAABDmdldFBvc2l0aW9uRmVlAQdfdHJhZGVyBA5wb3NpdGlvbkZlZU9wdAkAmggCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBQ1rX3Bvc2l0aW9uRmVlBQdfdHJhZGVyBAckbWF0Y2gwBQ5wb3NpdGlvbkZlZU9wdAMJAAECBQckbWF0Y2gwAgNJbnQEC3Bvc2l0aW9uRmVlBQckbWF0Y2gwBQtwb3NpdGlvbkZlZQkBA2ZlZQABE3JlcXVpcmVPcGVuUG9zaXRpb24BB190cmFkZXIDCQAAAggJAQtnZXRQb3NpdGlvbgEFB190cmFkZXICXzEAAAkAAgECEE5vIG9wZW4gcG9zaXRpb24GAQ1nZXRPcmFjbGVEYXRhAQNrZXkEDW9yYWNsZURhdGFTdHIJAJ0IAgUEdGhpcwUDa2V5AwMJAQlpc0RlZmluZWQBBQ1vcmFjbGVEYXRhU3RyCQECIT0CCQEFdmFsdWUBBQ1vcmFjbGVEYXRhU3RyAgAHBApvcmFjbGVEYXRhCQC1CQIJAQV2YWx1ZQEFDW9yYWNsZURhdGFTdHICASwEDW9yYWNsZUFkZHJlc3MJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQCRAwIFCm9yYWNsZURhdGEAAAkArAICAhtJbnZhbGlkIG9yYWNsZSBhZGRyZXNzIGluOiAJAQV2YWx1ZQEFDW9yYWNsZURhdGFTdHIECHByaWNlS2V5CQCRAwIFCm9yYWNsZURhdGEAAQQIYmxvY2tLZXkJAJEDAgUKb3JhY2xlRGF0YQACBAdvcGVuS2V5CQCRAwIFCm9yYWNsZURhdGEAAwkAlgoEBQ1vcmFjbGVBZGRyZXNzBQhwcmljZUtleQUIYmxvY2tLZXkFB29wZW5LZXkFBHVuaXQBC2luaXRpYWxpemVkAAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzBQ1rX2luaXRpYWxpemVkBwEGcGF1c2VkAAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzBQhrX3BhdXNlZAcBCWNsb3NlT25seQAJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhpcwULa19jbG9zZU9ubHkHAQ11cGRhdGVSZXNlcnZlAwZfaXNBZGQRX3F1b3RlQXNzZXRBbW91bnQQX2Jhc2VBc3NldEFtb3VudAMFBl9pc0FkZAQHbmV3QmFzZQkAZQIJAQZic0FzdFIABRBfYmFzZUFzc2V0QW1vdW50AwkAZwIAAAUHbmV3QmFzZQkAAgECKlR4IGxlYWQgdG8gYmFzZSBhc3NldCByZXNlcnZlIDw9IDAsIHJldmVydAkAlQoDCQBkAgkBBnF0QXN0UgAFEV9xdW90ZUFzc2V0QW1vdW50BQduZXdCYXNlCQBkAgkBEXRvdGFsUG9zaXRpb25TaXplAAUQX2Jhc2VBc3NldEFtb3VudAQIbmV3UXVvdGUJAGUCCQEGcXRBc3RSAAURX3F1b3RlQXNzZXRBbW91bnQDCQBnAgAABQhuZXdRdW90ZQkAAgECKlR4IGxlYWQgdG8gYmFzZSBxdW90ZSByZXNlcnZlIDw9IDAsIHJldmVydAkAlQoDBQhuZXdRdW90ZQkAZAIJAQZic0FzdFIABRBfYmFzZUFzc2V0QW1vdW50CQBlAgkBEXRvdGFsUG9zaXRpb25TaXplAAUQX2Jhc2VBc3NldEFtb3VudAENY2FsY0ludmFyaWFudAIHX3F0QXN0UgdfYnNBc3RSBAdicXRBc3RSCQC2AgEFB19xdEFzdFIEB2Jic0FzdFIJALYCAQUHX2JzQXN0UgkBBWJtdWxkAgUHYnF0QXN0UgUHYmJzQXN0UgEJc3dhcElucHV0AgZfaXNBZGQRX3F1b3RlQXNzZXRBbW91bnQEB19xdEFzdFIJAQZxdEFzdFIABAdfYnNBc3RSCQEGYnNBc3RSAAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcABBhxdW90ZUFzc2V0QW1vdW50QWRqdXN0ZWQJAQRkaXZkAgURX3F1b3RlQXNzZXRBbW91bnQFB19xdEFzdFcEAWsJAQ1jYWxjSW52YXJpYW50AgUHX3F0QXN0UgUHX2JzQXN0UgQWcXVvdGVBc3NldFJlc2VydmVBZnRlcgMFBl9pc0FkZAkAZAIFB19xdEFzdFIFGHF1b3RlQXNzZXRBbW91bnRBZGp1c3RlZAkAZQIFB19xdEFzdFIFGHF1b3RlQXNzZXRBbW91bnRBZGp1c3RlZAQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCQCgAwEJAQViZGl2ZAIFAWsJALYCAQUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgQYYW1vdW50QmFzZUFzc2V0Qm91Z2h0QWJzCQEDYWJzAQkAZQIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUHX2JzQXN0UgQVYW1vdW50QmFzZUFzc2V0Qm91Z2h0AwUGX2lzQWRkBRhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMJAQEtAQUYYW1vdW50QmFzZUFzc2V0Qm91Z2h0QWJzBA0kdDAxNjk0MzE3MTEzCQENdXBkYXRlUmVzZXJ2ZQMFBl9pc0FkZAUYcXVvdGVBc3NldEFtb3VudEFkanVzdGVkBRhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMEF3F1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIxCAUNJHQwMTY5NDMxNzExMwJfMQQWYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyMQgFDSR0MDE2OTQzMTcxMTMCXzIEF3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIxCAUNJHQwMTY5NDMxNzExMwJfMwQLcHJpY2VCZWZvcmUJAQRkaXZkAgkBBG11bGQCBQdfcXRBc3RSBQdfcXRBc3RXCQEEbXVsZAIFB19ic0FzdFIFB19ic0FzdFcEC21hcmtldFByaWNlCQEEZGl2ZAIFEV9xdW90ZUFzc2V0QW1vdW50BRhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMECXByaWNlRGlmZgkBA2FicwEJAGUCBQtwcmljZUJlZm9yZQULbWFya2V0UHJpY2UEC3ByaWNlSW1wYWN0CQBlAgUMREVDSU1BTF9VTklUCQEEZGl2ZAIFC3ByaWNlQmVmb3JlCQBkAgULcHJpY2VCZWZvcmUFCXByaWNlRGlmZgQTbWF4UHJpY2VJbXBhY3RWYWx1ZQkBDm1heFByaWNlSW1wYWN0AAMJAGYCBQtwcmljZUltcGFjdAUTbWF4UHJpY2VJbXBhY3RWYWx1ZQkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgINUHJpY2UgaW1wYWN0IAkApAMBBQtwcmljZUltcGFjdAIUID4gbWF4IHByaWNlIGltcGFjdCAJAKQDAQUTbWF4UHJpY2VJbXBhY3RWYWx1ZQIVIGJlZm9yZSBxdW90ZSBhc3NldDogCQCkAwEFB19xdEFzdFICFCBiZWZvcmUgYmFzZSBhc3NldDogCQCkAwEFB19ic0FzdFICISBxdW90ZSBhc3NldCBhbW91bnQgdG8gZXhjaGFuZ2U6IAkApAMBBRFfcXVvdGVBc3NldEFtb3VudAIPIHByaWNlIGJlZm9yZTogCQCkAwEFC3ByaWNlQmVmb3JlAg4gbWFya2V0UHJpY2U6IAkApAMBBQttYXJrZXRQcmljZQkAlgoEBRVhbW91bnRCYXNlQXNzZXRCb3VnaHQFF3F1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIxBRZiYXNlQXNzZXRSZXNlcnZlQWZ0ZXIxBRd0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyMQEPY2FsY1JvbGxvdmVyRmVlAhJfb2xkUG9zaXRpb25NYXJnaW4gX29sZFBvc2l0aW9uTGFzdFVwZGF0ZWRUaW1lc3RhbXAED3Bvc2l0aW9uTWludXRlcwkAaAIJAGkCCQBpAgkAZQIJAQ1sYXN0VGltZXN0YW1wAAUgX29sZFBvc2l0aW9uTGFzdFVwZGF0ZWRUaW1lc3RhbXAA6AcAPAUMREVDSU1BTF9VTklUBAtyb2xsb3ZlckZlZQkBBGRpdmQCCQEEbXVsZAIJAQRtdWxkAgUSX29sZFBvc2l0aW9uTWFyZ2luBQ9wb3NpdGlvbk1pbnV0ZXMJAQ9yb2xsb3ZlckZlZVJhdGUABQ9NSU5VVEVTX0lOX1lFQVIFC3JvbGxvdmVyRmVlATBjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50QW5kUm9sbG92ZXJGZWUFEF9vbGRQb3NpdGlvblNpemUSX29sZFBvc2l0aW9uTWFyZ2luJV9vbGRQb3NpdGlvbkN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24gX29sZFBvc2l0aW9uTGFzdFVwZGF0ZWRUaW1lc3RhbXAMX21hcmdpbkRlbHRhBA5mdW5kaW5nUGF5bWVudAMJAQIhPQIFEF9vbGRQb3NpdGlvblNpemUAAAQgX2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24JAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUQX29sZFBvc2l0aW9uU2l6ZQkBBG11bGQCCQBlAgUgX2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FJV9vbGRQb3NpdGlvbkN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FEF9vbGRQb3NpdGlvblNpemUAAAQLcm9sbG92ZXJGZWUJAQ9jYWxjUm9sbG92ZXJGZWUCBRJfb2xkUG9zaXRpb25NYXJnaW4FIF9vbGRQb3NpdGlvbkxhc3RVcGRhdGVkVGltZXN0YW1wBAxzaWduZWRNYXJnaW4JAGQCCQBlAgkAZQIFDF9tYXJnaW5EZWx0YQULcm9sbG92ZXJGZWUFDmZ1bmRpbmdQYXltZW50BRJfb2xkUG9zaXRpb25NYXJnaW4EDSR0MDE5MzY4MTk0OTUDCQBmAgAABQxzaWduZWRNYXJnaW4JAJQKAgAACQEDYWJzAQUMc2lnbmVkTWFyZ2luCQCUCgIJAQNhYnMBBQxzaWduZWRNYXJnaW4AAAQMcmVtYWluTWFyZ2luCAUNJHQwMTkzNjgxOTQ5NQJfMQQHYmFkRGVidAgFDSR0MDE5MzY4MTk0OTUCXzIJAJYKBAUMcmVtYWluTWFyZ2luBQdiYWREZWJ0BQ5mdW5kaW5nUGF5bWVudAULcm9sbG92ZXJGZWUBFnN3YXBPdXRwdXRXaXRoUmVzZXJ2ZXMHBl9pc0FkZBBfYmFzZUFzc2V0QW1vdW50FF9jaGVja01heFByaWNlSW1wYWN0El9xdW90ZUFzc2V0UmVzZXJ2ZRFfcXVvdGVBc3NldFdlaWdodBFfYmFzZUFzc2V0UmVzZXJ2ZRBfYmFzZUFzc2V0V2VpZ2h0BAtwcmljZUJlZm9yZQkBBGRpdmQCCQEEbXVsZAIFEl9xdW90ZUFzc2V0UmVzZXJ2ZQURX3F1b3RlQXNzZXRXZWlnaHQJAQRtdWxkAgURX2Jhc2VBc3NldFJlc2VydmUFEF9iYXNlQXNzZXRXZWlnaHQDCQAAAgUQX2Jhc2VBc3NldEFtb3VudAAACQACAQIZSW52YWxpZCBiYXNlIGFzc2V0IGFtb3VudAQBawkBDWNhbGNJbnZhcmlhbnQCBRJfcXVvdGVBc3NldFJlc2VydmUFEV9iYXNlQXNzZXRSZXNlcnZlBBhiYXNlQXNzZXRQb29sQW1vdW50QWZ0ZXIDBQZfaXNBZGQJAGQCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldEFtb3VudAkAZQIFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0QW1vdW50BA9xdW90ZUFzc2V0QWZ0ZXIJAKADAQkBBWJkaXZkAgUBawkAtgIBBRhiYXNlQXNzZXRQb29sQW1vdW50QWZ0ZXIED3F1b3RlQXNzZXREZWx0YQkBA2FicwEJAGUCBQ9xdW90ZUFzc2V0QWZ0ZXIFEl9xdW90ZUFzc2V0UmVzZXJ2ZQQOcXVvdGVBc3NldFNvbGQJAQRtdWxkAgUPcXVvdGVBc3NldERlbHRhBRFfcXVvdGVBc3NldFdlaWdodAQTbWF4UHJpY2VJbXBhY3RWYWx1ZQkBDm1heFByaWNlSW1wYWN0AAQNJHQwMjA3NTcyMDkxOQkBDXVwZGF0ZVJlc2VydmUDCQEBIQEFBl9pc0FkZAUPcXVvdGVBc3NldERlbHRhBRBfYmFzZUFzc2V0QW1vdW50BBdxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyMQgFDSR0MDIwNzU3MjA5MTkCXzEEFmJhc2VBc3NldFJlc2VydmVBZnRlcjEIBQ0kdDAyMDc1NzIwOTE5Al8yBBd0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyMQgFDSR0MDIwNzU3MjA5MTkCXzMEC21hcmtldFByaWNlCQEEZGl2ZAIFDnF1b3RlQXNzZXRTb2xkBRBfYmFzZUFzc2V0QW1vdW50BAlwcmljZURpZmYJAQNhYnMBCQBlAgULcHJpY2VCZWZvcmUFC21hcmtldFByaWNlBAtwcmljZUltcGFjdAkAZQIFDERFQ0lNQUxfVU5JVAkBBGRpdmQCBQtwcmljZUJlZm9yZQkAZAIFC3ByaWNlQmVmb3JlBQlwcmljZURpZmYDAwkAZgIFC3ByaWNlSW1wYWN0BRNtYXhQcmljZUltcGFjdFZhbHVlBRRfY2hlY2tNYXhQcmljZUltcGFjdAcJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICDVByaWNlIGltcGFjdCAJAKQDAQULcHJpY2VJbXBhY3QCFCA+IG1heCBwcmljZSBpbXBhY3QgCQCkAwEFE21heFByaWNlSW1wYWN0VmFsdWUCFSBiZWZvcmUgcXVvdGUgYXNzZXQ6IAkApAMBBRJfcXVvdGVBc3NldFJlc2VydmUCFCBiZWZvcmUgYmFzZSBhc3NldDogCQCkAwEFEV9iYXNlQXNzZXRSZXNlcnZlAiAgYmFzZSBhc3NldCBhbW91bnQgdG8gZXhjaGFuZ2U6IAkApAMBBRBfYmFzZUFzc2V0QW1vdW50Ag8gcHJpY2UgYmVmb3JlOiAJAKQDAQULcHJpY2VCZWZvcmUCDyBtYXJrZXQgcHJpY2U6IAkApAMBBQttYXJrZXRQcmljZQkAmQoHBQ5xdW90ZUFzc2V0U29sZAUXcXVvdGVBc3NldFJlc2VydmVBZnRlcjEFFmJhc2VBc3NldFJlc2VydmVBZnRlcjEFF3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIxCQBlAgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQADBQZfaXNBZGQJAQNhYnMBBRBfYmFzZUFzc2V0QW1vdW50AAAJAGUCCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQADCQEBIQEFBl9pc0FkZAkBA2FicwEFEF9iYXNlQXNzZXRBbW91bnQAAAULcHJpY2VJbXBhY3QBCnN3YXBPdXRwdXQDBl9pc0FkZBBfYmFzZUFzc2V0QW1vdW50FF9jaGVja01heFByaWNlSW1wYWN0CQEWc3dhcE91dHB1dFdpdGhSZXNlcnZlcwcFBl9pc0FkZAUQX2Jhc2VBc3NldEFtb3VudAUUX2NoZWNrTWF4UHJpY2VJbXBhY3QJAQZxdEFzdFIACQEGcXRBc3RXAAkBBmJzQXN0UgAJAQZic0FzdFcAARNnZXRPcmFjbGVQcmljZVZhbHVlAwZvcmFjbGUIcHJpY2VLZXkIYmxvY2tLZXkECWxhc3RWYWx1ZQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFBm9yYWNsZQUIcHJpY2VLZXkJAKwCAgkArAICCQCsAgICIkNhbiBub3QgZ2V0IG9yYWNsZSBwcmljZS4gT3JhY2xlOiAJAKUIAQUGb3JhY2xlAgYga2V5OiAFCHByaWNlS2V5AwkBAiE9AgUIYmxvY2tLZXkCAAQMY3VycmVudEJsb2NrCAUJbGFzdEJsb2NrBmhlaWdodAQPbGFzdE9yYWNsZUJsb2NrCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUGb3JhY2xlBQhibG9ja0tleQkArAICCQCsAgIJAKwCAgIiQ2FuIG5vdCBnZXQgb3JhY2xlIGJsb2NrLiBPcmFjbGU6IAkApQgBBQZvcmFjbGUCBiBrZXk6IAUIYmxvY2tLZXkDCQBmAgkAZQIFDGN1cnJlbnRCbG9jawUPbGFzdE9yYWNsZUJsb2NrCQEObWF4T3JhY2xlRGVsYXkACQACAQkArAICCQCsAgIJAKwCAgImT3JhY2xlIHN0YWxlIGRhdGEuIExhc3Qgb3JhY2xlIGJsb2NrOiAJAKQDAQUPbGFzdE9yYWNsZUJsb2NrAhAgY3VycmVudCBibG9jazogCQCkAwEFDGN1cnJlbnRCbG9jawUJbGFzdFZhbHVlBQlsYXN0VmFsdWUBDmdldE9yYWNsZVByaWNlAAQKYmFzZU9yYWNsZQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQENZ2V0T3JhY2xlRGF0YQEFDGtfYmFzZU9yYWNsZQIZTm8gYmFzZSBhc3NldCBvcmFjbGUgZGF0YQQPYmFzZU9yYWNsZVByaWNlCQETZ2V0T3JhY2xlUHJpY2VWYWx1ZQMIBQpiYXNlT3JhY2xlAl8xCAUKYmFzZU9yYWNsZQJfMggFCmJhc2VPcmFjbGUCXzMEC3F1b3RlT3JhY2xlCQENZ2V0T3JhY2xlRGF0YQEFDWtfcXVvdGVPcmFjbGUEEHF1b3RlT3JhY2xlUHJpY2UDCQEJaXNEZWZpbmVkAQULcXVvdGVPcmFjbGUEDHF1b3RlT3JhY2xlVgkBBXZhbHVlAQULcXVvdGVPcmFjbGUJARNnZXRPcmFjbGVQcmljZVZhbHVlAwgFDHF1b3RlT3JhY2xlVgJfMQgFDHF1b3RlT3JhY2xlVgJfMggFDHF1b3RlT3JhY2xlVgJfMwUMREVDSU1BTF9VTklUCQEEZGl2ZAIFD2Jhc2VPcmFjbGVQcmljZQUQcXVvdGVPcmFjbGVQcmljZQEOaXNNYXJrZXRDbG9zZWQABApiYXNlT3JhY2xlCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAQ1nZXRPcmFjbGVEYXRhAQUMa19iYXNlT3JhY2xlAhlObyBiYXNlIGFzc2V0IG9yYWNsZSBkYXRhBAZvcmFjbGUIBQpiYXNlT3JhY2xlAl8xBAdvcGVuS2V5CAUKYmFzZU9yYWNsZQJfNAMJAQIhPQIFB29wZW5LZXkCAAQGaXNPcGVuCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJsIAgUGb3JhY2xlBQdvcGVuS2V5CQCsAgIJAKwCAgkArAICAitDYW4gbm90IGdldCBvcmFjbGUgaXMgb3Blbi9jbG9zZWQuIE9yYWNsZTogCQClCAEFBm9yYWNsZQIGIGtleTogBQdvcGVuS2V5CQEBIQEFBmlzT3BlbgcBDGFic1ByaWNlRGlmZgUMX29yYWNsZVByaWNlEl9xdW90ZUFzc2V0UmVzZXJ2ZRFfYmFzZUFzc2V0UmVzZXJ2ZQdfcXRBc3RXB19ic0FzdFcECnByaWNlQWZ0ZXIJAQRkaXZkAgkBBG11bGQCBRJfcXVvdGVBc3NldFJlc2VydmUFB19xdEFzdFcJAQRtdWxkAgURX2Jhc2VBc3NldFJlc2VydmUFB19ic0FzdFcEDGF2ZXJhZ2VQcmljZQkBBGRpdmQCCQBkAgUMX29yYWNsZVByaWNlBQpwcmljZUFmdGVyCQBoAgACBQxERUNJTUFMX1VOSVQEDGFic1ByaWNlRGlmZgkBBGRpdmQCCQEDYWJzAQkAZQIFDF9vcmFjbGVQcmljZQUKcHJpY2VBZnRlcgUMYXZlcmFnZVByaWNlBQxhYnNQcmljZURpZmYBGXJlcXVpcmVOb3RPdmVyU3ByZWFkTGltaXQCEl9xdW90ZUFzc2V0UmVzZXJ2ZRFfYmFzZUFzc2V0UmVzZXJ2ZQQLb3JhY2xlUHJpY2UJAQ5nZXRPcmFjbGVQcmljZQAEB19xdEFzdFcJAQZxdEFzdFcABAdfYnNBc3RXCQEGYnNBc3RXAAQSYWJzUHJpY2VEaWZmQmVmb3JlCQEMYWJzUHJpY2VEaWZmBQULb3JhY2xlUHJpY2UJAQZxdEFzdFIACQEGYnNBc3RSAAUHX3F0QXN0VwUHX2JzQXN0VwQRYWJzUHJpY2VEaWZmQWZ0ZXIJAQxhYnNQcmljZURpZmYFBQtvcmFjbGVQcmljZQUSX3F1b3RlQXNzZXRSZXNlcnZlBRFfYmFzZUFzc2V0UmVzZXJ2ZQUHX3F0QXN0VwUHX2JzQXN0VwMDCQBmAgURYWJzUHJpY2VEaWZmQWZ0ZXIJAQ5tYXhQcmljZVNwcmVhZAAJAGYCBRFhYnNQcmljZURpZmZBZnRlcgUSYWJzUHJpY2VEaWZmQmVmb3JlBwkAAgEJAKwCAgkArAICCQCsAgICDVByaWNlIHNwcmVhZCAJAKQDAQURYWJzUHJpY2VEaWZmQWZ0ZXICFCA+IG1heCBwcmljZSBzcHJlYWQgCQCkAwEJAQ5tYXhQcmljZVNwcmVhZAAGAR1yZXF1aXJlTm90T3Zlck1heE9wZW5Ob3Rpb25hbAIRX2xvbmdPcGVuTm90aW9uYWwSX3Nob3J0T3Blbk5vdGlvbmFsBBBfbWF4T3Blbk5vdGlvbmFsCQEPbWF4T3Blbk5vdGlvbmFsAAMJAGYCBRFfbG9uZ09wZW5Ob3Rpb25hbAUQX21heE9wZW5Ob3Rpb25hbAkAAgEJAKwCAgkArAICCQCsAgICE0xvbmcgb3BlbiBub3Rpb25hbCAJAKQDAQURX2xvbmdPcGVuTm90aW9uYWwCFSA+IG1heCBvcGVuIG5vdGlvbmFsIAkApAMBBRBfbWF4T3Blbk5vdGlvbmFsAwkAZgIFEl9zaG9ydE9wZW5Ob3Rpb25hbAUQX21heE9wZW5Ob3Rpb25hbAkAAgEJAKwCAgkArAICCQCsAgICFFNob3J0IG9wZW4gbm90aW9uYWwgCQCkAwEFEl9zaG9ydE9wZW5Ob3Rpb25hbAIVID4gbWF4IG9wZW4gbm90aW9uYWwgCQCkAwEFEF9tYXhPcGVuTm90aW9uYWwGAQxnZXRTcG90UHJpY2UABBJfcXVvdGVBc3NldFJlc2VydmUJAQZxdEFzdFIABBFfYmFzZUFzc2V0UmVzZXJ2ZQkBBmJzQXN0UgAEB19xdEFzdFcJAQZxdEFzdFcABAdfYnNBc3RXCQEGYnNBc3RXAAkBBGRpdmQCCQEEbXVsZAIFEl9xdW90ZUFzc2V0UmVzZXJ2ZQUHX3F0QXN0VwkBBG11bGQCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUHX2JzQXN0VwEWaXNPdmVyRmx1Y3R1YXRpb25MaW1pdAAEC29yYWNsZVByaWNlCQEOZ2V0T3JhY2xlUHJpY2UABAxjdXJyZW50UHJpY2UJAQxnZXRTcG90UHJpY2UACQBmAgkBBGRpdmQCCQEDYWJzAQkAZQIFC29yYWNsZVByaWNlBQxjdXJyZW50UHJpY2UFC29yYWNsZVByaWNlCQELc3ByZWFkTGltaXQAAR9nZXRQb3NpdGlvbkFkanVzdGVkT3Blbk5vdGlvbmFsBg1fcG9zaXRpb25TaXplB19vcHRpb24SX3F1b3RlQXNzZXRSZXNlcnZlEV9xdW90ZUFzc2V0V2VpZ2h0EV9iYXNlQXNzZXRSZXNlcnZlEF9iYXNlQXNzZXRXZWlnaHQED3Bvc2l0aW9uU2l6ZUFicwkBA2FicwEFDV9wb3NpdGlvblNpemUEB2lzU2hvcnQJAGYCAAAFDV9wb3NpdGlvblNpemUEEHBvc2l0aW9uTm90aW9uYWwDCQAAAgUHX29wdGlvbgUPUE5MX09QVElPTl9TUE9UBBNvdXRQb3NpdGlvbk5vdGlvbmFsCAkBFnN3YXBPdXRwdXRXaXRoUmVzZXJ2ZXMHCQEBIQEFB2lzU2hvcnQFD3Bvc2l0aW9uU2l6ZUFicwcFEl9xdW90ZUFzc2V0UmVzZXJ2ZQURX3F1b3RlQXNzZXRXZWlnaHQFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0V2VpZ2h0Al8xBRNvdXRQb3NpdGlvbk5vdGlvbmFsCQEEbXVsZAIFD3Bvc2l0aW9uU2l6ZUFicwkBDmdldE9yYWNsZVByaWNlAAUQcG9zaXRpb25Ob3Rpb25hbAErZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmxCeVZhbHVlcwcNX3Bvc2l0aW9uU2l6ZRVfcG9zaXRpb25PcGVuTm90aW9uYWwSX3F1b3RlQXNzZXRSZXNlcnZlEV9xdW90ZUFzc2V0V2VpZ2h0EV9iYXNlQXNzZXRSZXNlcnZlEF9iYXNlQXNzZXRXZWlnaHQHX29wdGlvbgMJAAACBQ1fcG9zaXRpb25TaXplAAAJAAIBAhVJbnZhbGlkIHBvc2l0aW9uIHNpemUEB2lzU2hvcnQJAGYCAAAFDV9wb3NpdGlvblNpemUEEHBvc2l0aW9uTm90aW9uYWwJAR9nZXRQb3NpdGlvbkFkanVzdGVkT3Blbk5vdGlvbmFsBgUNX3Bvc2l0aW9uU2l6ZQUHX29wdGlvbgUSX3F1b3RlQXNzZXRSZXNlcnZlBRFfcXVvdGVBc3NldFdlaWdodAURX2Jhc2VBc3NldFJlc2VydmUFEF9iYXNlQXNzZXRXZWlnaHQEDXVucmVhbGl6ZWRQbmwDBQdpc1Nob3J0CQBlAgUVX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBRBwb3NpdGlvbk5vdGlvbmFsCQBlAgUQcG9zaXRpb25Ob3Rpb25hbAUVX3Bvc2l0aW9uT3Blbk5vdGlvbmFsCQCUCgIFEHBvc2l0aW9uTm90aW9uYWwFDXVucmVhbGl6ZWRQbmwBI2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sAgdfdHJhZGVyB19vcHRpb24EDSR0MDI4Nzk3Mjg5MjUJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIEDHBvc2l0aW9uU2l6ZQgFDSR0MDI4Nzk3Mjg5MjUCXzEEDnBvc2l0aW9uTWFyZ2luCAUNJHQwMjg3OTcyODkyNQJfMgQUcG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDAyODc5NzI4OTI1Al8zBBFwb3NpdGlvbkxzdFVwZENQRggFDSR0MDI4Nzk3Mjg5MjUCXzQJAStnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubEJ5VmFsdWVzBwUMcG9zaXRpb25TaXplBRRwb3NpdGlvbk9wZW5Ob3Rpb25hbAkBBnF0QXN0UgAJAQZxdEFzdFcACQEGYnNBc3RSAAkBBmJzQXN0VwAFB19vcHRpb24BD2NhbGNNYXJnaW5SYXRpbwMNX3JlbWFpbk1hcmdpbghfYmFkRGVidBFfcG9zaXRpb25Ob3Rpb25hbAkBBGRpdmQCCQBlAgUNX3JlbWFpbk1hcmdpbgUIX2JhZERlYnQFEV9wb3NpdGlvbk5vdGlvbmFsARZnZXRNYXJnaW5SYXRpb0J5T3B0aW9uAgdfdHJhZGVyB19vcHRpb24EDSR0MDI5NDQwMjk1ODEJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIEDHBvc2l0aW9uU2l6ZQgFDSR0MDI5NDQwMjk1ODECXzEEDnBvc2l0aW9uTWFyZ2luCAUNJHQwMjk0NDAyOTU4MQJfMgQDcG9uCAUNJHQwMjk0NDAyOTU4MQJfMwQWcG9zaXRpb25MYXN0VXBkYXRlZENQRggFDSR0MDI5NDQwMjk1ODECXzQEEXBvc2l0aW9uVGltZXN0YW1wCAUNJHQwMjk0NDAyOTU4MQJfNQQNJHQwMjk1ODcyOTY4MAkBI2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sAgUHX3RyYWRlcgUHX29wdGlvbgQQcG9zaXRpb25Ob3Rpb25hbAgFDSR0MDI5NTg3Mjk2ODACXzEEDXVucmVhbGl6ZWRQbmwIBQ0kdDAyOTU4NzI5NjgwAl8yBA0kdDAyOTY4NTI5ODk3CQEwY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudEFuZFJvbGxvdmVyRmVlBQUMcG9zaXRpb25TaXplBQ5wb3NpdGlvbk1hcmdpbgUWcG9zaXRpb25MYXN0VXBkYXRlZENQRgURcG9zaXRpb25UaW1lc3RhbXAFDXVucmVhbGl6ZWRQbmwEDHJlbWFpbk1hcmdpbggFDSR0MDI5Njg1Mjk4OTcCXzEEB2JhZERlYnQIBQ0kdDAyOTY4NTI5ODk3Al8yCQEPY2FsY01hcmdpblJhdGlvAwUMcmVtYWluTWFyZ2luBQdiYWREZWJ0BRBwb3NpdGlvbk5vdGlvbmFsAQ5nZXRNYXJnaW5SYXRpbwEHX3RyYWRlcgkBFmdldE1hcmdpblJhdGlvQnlPcHRpb24CBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QBG2dldFBhcnRpYWxMaXF1aWRhdGlvbkFtb3VudAIHX3RyYWRlcg1fcG9zaXRpb25TaXplBAxtYXhpbXVtUmF0aW8JAQR2bWF4AgkBF3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAAkAZQIFDERFQ0lNQUxfVU5JVAkBBGRpdmQCCQEOZ2V0TWFyZ2luUmF0aW8BBQdfdHJhZGVyCQEWbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwAEGG1heEV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQkBBG11bGQCCQEDYWJzAQUNX3Bvc2l0aW9uU2l6ZQUMbWF4aW11bVJhdGlvBApzd2FwUmVzdWx0CQEKc3dhcE91dHB1dAMJAGYCBQ1fcG9zaXRpb25TaXplAAAFGG1heEV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQcEHG1heEV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQIBQpzd2FwUmVzdWx0Al8xBAtwcmljZUltcGFjdAgFCnN3YXBSZXN1bHQCXzcDCQBmAgkBDm1heFByaWNlSW1wYWN0AAULcHJpY2VJbXBhY3QFGG1heEV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQkBBG11bGQCCQEDYWJzAQUNX3Bvc2l0aW9uU2l6ZQkBF3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAAEVaW50ZXJuYWxDbG9zZVBvc2l0aW9uBwdfdHJhZGVyBV9zaXplBF9mZWUUX21pblF1b3RlQXNzZXRBbW91bnQMX2FkZFRvTWFyZ2luFF9jaGVja01heFByaWNlSW1wYWN0Cl9saXF1aWRhdGUEDSR0MDMwOTY0MzExMjAJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIED29sZFBvc2l0aW9uU2l6ZQgFDSR0MDMwOTY0MzExMjACXzEEEW9sZFBvc2l0aW9uTWFyZ2luCAUNJHQwMzA5NjQzMTEyMAJfMgQXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDAzMDk2NDMxMTIwAl8zBBRvbGRQb3NpdGlvbkxzdFVwZENQRggFDSR0MDMwOTY0MzExMjACXzQEFG9sZFBvc2l0aW9uVGltZXN0YW1wCAUNJHQwMzA5NjQzMTEyMAJfNQQOaXNMb25nUG9zaXRpb24JAGYCBQ9vbGRQb3NpdGlvblNpemUAAAQSYWJzT2xkUG9zaXRpb25TaXplCQEDYWJzAQUPb2xkUG9zaXRpb25TaXplAwMJAGcCBRJhYnNPbGRQb3NpdGlvblNpemUFBV9zaXplCQBmAgUFX3NpemUAAAcEDmlzUGFydGlhbENsb3NlCQBmAgUSYWJzT2xkUG9zaXRpb25TaXplBQVfc2l6ZQQNJHQwMzE0MTIzMTg2MwkBCnN3YXBPdXRwdXQDCQBmAgUPb2xkUG9zaXRpb25TaXplAAAFBV9zaXplBRRfY2hlY2tNYXhQcmljZUltcGFjdAQZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAgFDSR0MDMxNDEyMzE4NjMCXzEEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDAzMTQxMjMxODYzAl8yBBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDAzMTQxMjMxODYzAl8zBBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwMzE0MTIzMTg2MwJfNAQVZXhjaGFuZ2VkUG9zaXRpb25TaXplAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAACQEBLQEFBV9zaXplBQVfc2l6ZQQNJHQwMzIwNzgzMjI4NQkBI2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sAgUHX3RyYWRlcgUPUE5MX09QVElPTl9TUE9UBBNvbGRQb3NpdGlvbk5vdGlvbmFsCAUNJHQwMzIwNzgzMjI4NQJfMQQNdW5yZWFsaXplZFBubAgFDSR0MDMyMDc4MzIyODUCXzIEDXJlYWxpemVkUmF0aW8JAQRkaXZkAgkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQUSYWJzT2xkUG9zaXRpb25TaXplBAtyZWFsaXplZFBubAkBBG11bGQCBQ11bnJlYWxpemVkUG5sBQ1yZWFsaXplZFJhdGlvBA0kdDAzMjYyNjMyODcyCQEwY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudEFuZFJvbGxvdmVyRmVlBQUPb2xkUG9zaXRpb25TaXplBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25Mc3RVcGRDUEYFFG9sZFBvc2l0aW9uVGltZXN0YW1wBQ11bnJlYWxpemVkUG5sBBJyZW1haW5NYXJnaW5CZWZvcmUIBQ0kdDAzMjYyNjMyODcyAl8xBAJ4MQgFDSR0MDMyNjI2MzI4NzICXzIEAngyCAUNJHQwMzI2MjYzMjg3MgJfMwQLcm9sbG92ZXJGZWUIBQ0kdDAzMjYyNjMyODcyAl80BA9wb3NpdGlvbkJhZERlYnQICQEwY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudEFuZFJvbGxvdmVyRmVlBQUPb2xkUG9zaXRpb25TaXplBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25Mc3RVcGRDUEYFFG9sZFBvc2l0aW9uVGltZXN0YW1wBQtyZWFsaXplZFBubAJfMgQQcmVhbGl6ZWRDbG9zZUZlZQkBBG11bGQCCQEEbXVsZAIFE29sZFBvc2l0aW9uTm90aW9uYWwFDXJlYWxpemVkUmF0aW8FBF9mZWUEEnVucmVhbGl6ZWRQbmxBZnRlcgkAZQIFDXVucmVhbGl6ZWRQbmwFC3JlYWxpemVkUG5sBBJyZW1haW5PcGVuTm90aW9uYWwDCQBmAgUPb2xkUG9zaXRpb25TaXplAAAJAGUCCQBlAgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAUSdW5yZWFsaXplZFBubEFmdGVyCQBlAgkAZAIFEnVucmVhbGl6ZWRQbmxBZnRlcgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAQPbmV3UG9zaXRpb25TaXplCQBkAgUPb2xkUG9zaXRpb25TaXplBRVleGNoYW5nZWRQb3NpdGlvblNpemUEDSR0MDM0Mjc4MzQ2NjQDCQAAAgUPbmV3UG9zaXRpb25TaXplAAAJAJQKAgAAAAAJAJQKAgkBA2FicwEFEnJlbWFpbk9wZW5Ob3Rpb25hbAkBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BBQ9uZXdQb3NpdGlvblNpemUEF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwMzQyNzgzNDY2NAJfMQQUbmV3UG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDAzNDI3ODM0NjY0Al8yBBFvcGVuTm90aW9uYWxEZWx0YQkAZQIFF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAQLbWFyZ2luUmF0aW8JARZnZXRNYXJnaW5SYXRpb0J5T3B0aW9uAgUHX3RyYWRlcgUPUE5MX09QVElPTl9TUE9UBB5uZXdQb3NpdGlvbk1hcmdpbldpdGhTYW1lUmF0aW8DCQBmAgUPb2xkUG9zaXRpb25TaXplAAAJAGUCCQEEbXVsZAIJAGQCBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUSdW5yZWFsaXplZFBubEFmdGVyBQttYXJnaW5SYXRpbwUSdW5yZWFsaXplZFBubEFmdGVyCQBlAgkBBG11bGQCCQBlAgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFEnVucmVhbGl6ZWRQbmxBZnRlcgULbWFyZ2luUmF0aW8FEnVucmVhbGl6ZWRQbmxBZnRlcgQRbWFyZ2luVG9UcmFkZXJSYXcJAGUCCQBlAgUScmVtYWluTWFyZ2luQmVmb3JlCQBkAgUebmV3UG9zaXRpb25NYXJnaW5XaXRoU2FtZVJhdGlvBRJ1bnJlYWxpemVkUG5sQWZ0ZXIFEHJlYWxpemVkQ2xvc2VGZWUEDm1hcmdpblRvVHJhZGVyAwkAZgIAAAURbWFyZ2luVG9UcmFkZXJSYXcDBQpfbGlxdWlkYXRlAAAJAAIBAjdJbnZhbGlkIGludGVybmFsQ2xvc2VQb3NpdGlvbiBwYXJhbXM6IHVuYWJsZSB0byBwYXkgZmVlBRFtYXJnaW5Ub1RyYWRlclJhdwQRbmV3UG9zaXRpb25NYXJnaW4DBQxfYWRkVG9NYXJnaW4JAGQCBR5uZXdQb3NpdGlvbk1hcmdpbldpdGhTYW1lUmF0aW8FDm1hcmdpblRvVHJhZGVyBR5uZXdQb3NpdGlvbk1hcmdpbldpdGhTYW1lUmF0aW8DAwkBAiE9AgUUX21pblF1b3RlQXNzZXRBbW91bnQAAAkAZgIFFF9taW5RdW90ZUFzc2V0QW1vdW50BRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BwkAAgEJAKwCAgkArAICCQCsAgICDUxpbWl0IGVycm9yOiAJAKQDAQUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAIDIDwgCQCkAwEFFF9taW5RdW90ZUFzc2V0QW1vdW50CQCjChEFD25ld1Bvc2l0aW9uU2l6ZQURbmV3UG9zaXRpb25NYXJnaW4FF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBRRuZXdQb3NpdGlvbkxzdFVwZENQRgUPcG9zaXRpb25CYWREZWJ0BQtyZWFsaXplZFBubAMDBQxfYWRkVG9NYXJnaW4FDmlzUGFydGlhbENsb3NlBwAABQ5tYXJnaW5Ub1RyYWRlcgUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCQBlAgkBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAAURb3Blbk5vdGlvbmFsRGVsdGEJAGUCCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAMFDmlzTG9uZ1Bvc2l0aW9uCQEDYWJzAQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplAAAJAGUCCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQADCQEBIQEFDmlzTG9uZ1Bvc2l0aW9uCQEDYWJzAQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplAAAJAGUCCQEQb3BlbkludGVyZXN0TG9uZwADBQ5pc0xvbmdQb3NpdGlvbgURb3Blbk5vdGlvbmFsRGVsdGEAAAkAZQIJARFvcGVuSW50ZXJlc3RTaG9ydAADCQEBIQEFDmlzTG9uZ1Bvc2l0aW9uBRFvcGVuTm90aW9uYWxEZWx0YQAACQBkAgUQcmVhbGl6ZWRDbG9zZUZlZQULcm9sbG92ZXJGZWUFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQJAAIBCQCsAgIJAKwCAgkArAICAj1JbnZhbGlkIGludGVybmFsQ2xvc2VQb3NpdGlvbiBwYXJhbXM6IGludmFsaWQgcG9zaXRpb24gc2l6ZTogCQCkAwEFBV9zaXplAgYgbWF4OiAJAKQDAQUSYWJzT2xkUG9zaXRpb25TaXplARBnZXRUd2FwU3BvdFByaWNlAAQIbWludXRlSWQJAGkCCQBpAgkBDWxhc3RUaW1lc3RhbXAAAOgHADwEDXN0YXJ0TWludXRlSWQJAGUCBQhtaW51dGVJZAUNVFdBUF9JTlRFUlZBTAQHbGlzdFN0cgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzBQ1rX2xhc3REYXRhU3RyAgAEBGxpc3QJALUJAgUHbGlzdFN0cgIBLAoBCGZpbHRlckZuAgthY2N1bXVsYXRvcgRuZXh0AwkAZwIFDXN0YXJ0TWludXRlSWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAtgkBBQRuZXh0CQCsAgICH2dldFR3YXBTcG90UHJpY2U6IGludmFsaWQgaW50OiAFB2xpc3RTdHIJAM0IAgULYWNjdW11bGF0b3IJAQ1wYXJzZUludFZhbHVlAQUEbmV4dAULYWNjdW11bGF0b3IEBWxpc3RGCgACJGwFBGxpc3QKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBCGZpbHRlckZuAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAyMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATABQECG1heEluZGV4AwkAZgIJAJADAQUFbGlzdEYAAAkAlgMBBQVsaXN0RgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQC2CQEJAJEDAgUEbGlzdAAACQCsAgICH2dldFR3YXBTcG90UHJpY2U6IGludmFsaWQgaW50OiAFB2xpc3RTdHIEDGxhc3RNaW51dGVJZAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQ5rX2xhc3RNaW51dGVJZAAABBZlbmRMYXN0Q3VtdWxhdGl2ZVByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAKwCAgkArAICBR1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQIBXwkApAMBBQxsYXN0TWludXRlSWQAAAQMZW5kTGFzdFByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAKwCAgkArAICBRNrX3R3YXBEYXRhTGFzdFByaWNlAgFfCQCkAwEFDGxhc3RNaW51dGVJZAAABBJub3dDdW11bGF0aXZlUHJpY2UJAGQCBRZlbmRMYXN0Q3VtdWxhdGl2ZVByaWNlCQBoAgkAZQIFCG1pbnV0ZUlkBQxsYXN0TWludXRlSWQFDGVuZExhc3RQcmljZQQYc3RhcnRMYXN0Q3VtdWxhdGl2ZVByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAKwCAgkArAICBR1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQIBXwkApAMBBQhtYXhJbmRleAAABA5zdGFydExhc3RQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUTa190d2FwRGF0YUxhc3RQcmljZQIBXwkApAMBBQhtYXhJbmRleAAABBRzdGFydEN1bXVsYXRpdmVQcmljZQkAZAIFGHN0YXJ0TGFzdEN1bXVsYXRpdmVQcmljZQkAaAIJAGUCBQ1zdGFydE1pbnV0ZUlkBQhtYXhJbmRleAUOc3RhcnRMYXN0UHJpY2UJAGkCCQBlAgUSbm93Q3VtdWxhdGl2ZVByaWNlBRRzdGFydEN1bXVsYXRpdmVQcmljZQUNVFdBUF9JTlRFUlZBTAETZ2V0VGVybWluYWxBbW1TdGF0ZQAEDV9wb3NpdGlvblNpemUJARF0b3RhbFBvc2l0aW9uU2l6ZQADCQAAAgUNX3Bvc2l0aW9uU2l6ZQAACQCUCgIJAQZxdEFzdFIACQEGYnNBc3RSAAQJZGlyZWN0aW9uCQBmAgUNX3Bvc2l0aW9uU2l6ZQAABA0kdDAzOTQwMTM5NTgwCQEKc3dhcE91dHB1dAMFCWRpcmVjdGlvbgkBA2FicwEFDV9wb3NpdGlvblNpemUHBBVjdXJyZW50TmV0TWFya2V0VmFsdWUIBQ0kdDAzOTQwMTM5NTgwAl8xBBl0ZXJtaW5hbFF1b3RlQXNzZXRSZXNlcnZlCAUNJHQwMzk0MDEzOTU4MAJfMgQYdGVybWluYWxCYXNlQXNzZXRSZXNlcnZlCAUNJHQwMzk0MDEzOTU4MAJfMwkAlAoCBRl0ZXJtaW5hbFF1b3RlQXNzZXRSZXNlcnZlBRh0ZXJtaW5hbEJhc2VBc3NldFJlc2VydmUBE2dldFF1b3RlQXNzZXRXZWlnaHQEEGJhc2VBc3NldFJlc2VydmURdG90YWxQb3NpdGlvblNpemURcXVvdGVBc3NldFJlc2VydmULdGFyZ2V0UHJpY2UEAWIJALYCAQUQYmFzZUFzc2V0UmVzZXJ2ZQQCc3oJALYCAQURdG90YWxQb3NpdGlvblNpemUEAXEJALYCAQURcXVvdGVBc3NldFJlc2VydmUEAXAJALYCAQULdGFyZ2V0UHJpY2UEAWsJAQVibXVsZAIFAXEFAWIEBG5ld0IJALcCAgUBYgUCc3oEBG5ld1EJAQViZGl2ZAIFAWsFBG5ld0IEAXoJAQViZGl2ZAIFBG5ld1EFBG5ld0IEBnJlc3VsdAkBBWJkaXZkAgUBcAUBegkAoAMBBQZyZXN1bHQBFGdldFN5bmNUZXJtaW5hbFByaWNlAw5fdGVybWluYWxQcmljZQdfcXRBc3RSB19ic0FzdFIEDV9wb3NpdGlvblNpemUJARF0b3RhbFBvc2l0aW9uU2l6ZQADCQAAAgUNX3Bvc2l0aW9uU2l6ZQAABAluZXdRdEFzdFcJAQRkaXZkAgkBBG11bGQCBQ5fdGVybWluYWxQcmljZQUHX2JzQXN0UgUHX3F0QXN0UgkAlQoDBQluZXdRdEFzdFcFDERFQ0lNQUxfVU5JVAAABAlkaXJlY3Rpb24JAGYCBQ1fcG9zaXRpb25TaXplAAAEFWN1cnJlbnROZXRNYXJrZXRWYWx1ZQgJAQpzd2FwT3V0cHV0AwUJZGlyZWN0aW9uCQEDYWJzAQUNX3Bvc2l0aW9uU2l6ZQcCXzEECW5ld1F0QXN0VwkBE2dldFF1b3RlQXNzZXRXZWlnaHQEBQdfYnNBc3RSBQ1fcG9zaXRpb25TaXplBQdfcXRBc3RSBQ5fdGVybWluYWxQcmljZQQJbmV3QnNBc3RXBQxERUNJTUFMX1VOSVQEDW1hcmdpblRvVmF1bHQICQErZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmxCeVZhbHVlcwcFDV9wb3NpdGlvblNpemUFFWN1cnJlbnROZXRNYXJrZXRWYWx1ZQUHX3F0QXN0UgUJbmV3UXRBc3RXBQdfYnNBc3RSBQluZXdCc0FzdFcFD1BOTF9PUFRJT05fU1BPVAJfMgkAlQoDBQluZXdRdEFzdFcFCW5ld0JzQXN0VwUNbWFyZ2luVG9WYXVsdAEKZ2V0RnVuZGluZwAED3VuZGVybHlpbmdQcmljZQkBDmdldE9yYWNsZVByaWNlAAQNc3BvdFR3YXBQcmljZQkBEGdldFR3YXBTcG90UHJpY2UABAdwcmVtaXVtCQBlAgUNc3BvdFR3YXBQcmljZQUPdW5kZXJseWluZ1ByaWNlAwMDCQAAAgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUAAAAGCQAAAgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQAAAAYJAQ5pc01hcmtldENsb3NlZAAJAJUKAwAAAAAAAAMJAGYCAAAFB3ByZW1pdW0EFHNob3J0UHJlbWl1bUZyYWN0aW9uCQEEZGl2ZAIJAQRtdWxkAgUHcHJlbWl1bQkBFGZ1bmRpbmdQZXJpb2REZWNpbWFsAAUHT05FX0RBWQMJAAACCQELZnVuZGluZ01vZGUABRJGVU5ESU5HX0FTWU1NRVRSSUMEE2xvbmdQcmVtaXVtRnJhY3Rpb24JAQRkaXZkAgkBBG11bGQCBRRzaG9ydFByZW1pdW1GcmFjdGlvbgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUACQEVdG90YWxMb25nUG9zaXRpb25TaXplAAkAlQoDBRRzaG9ydFByZW1pdW1GcmFjdGlvbgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgAABBlzaG9ydFRvdGFsUHJlbWl1bUZyYWN0aW9uCQEDYWJzAQkBBG11bGQCBRRzaG9ydFByZW1pdW1GcmFjdGlvbgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUABBhsb25nVG90YWxQcmVtaXVtRnJhY3Rpb24JAQNhYnMBCQEEbXVsZAIFFHNob3J0UHJlbWl1bUZyYWN0aW9uCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAQOcHJlbWl1bVRvVmF1bHQJAGUCBRlzaG9ydFRvdGFsUHJlbWl1bUZyYWN0aW9uBRhsb25nVG90YWxQcmVtaXVtRnJhY3Rpb24JAJUKAwUUc2hvcnRQcmVtaXVtRnJhY3Rpb24FFHNob3J0UHJlbWl1bUZyYWN0aW9uBQ5wcmVtaXVtVG9WYXVsdAQTbG9uZ1ByZW1pdW1GcmFjdGlvbgkBBGRpdmQCCQEEbXVsZAIFB3ByZW1pdW0JARRmdW5kaW5nUGVyaW9kRGVjaW1hbAAFB09ORV9EQVkDCQAAAgkBC2Z1bmRpbmdNb2RlAAUSRlVORElOR19BU1lNTUVUUklDBBRzaG9ydFByZW1pdW1GcmFjdGlvbgkBBGRpdmQCCQEEbXVsZAIFE2xvbmdQcmVtaXVtRnJhY3Rpb24JARV0b3RhbExvbmdQb3NpdGlvblNpemUACQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAJAJUKAwUUc2hvcnRQcmVtaXVtRnJhY3Rpb24FE2xvbmdQcmVtaXVtRnJhY3Rpb24AAAQYbG9uZ1RvdGFsUHJlbWl1bUZyYWN0aW9uCQEDYWJzAQkBBG11bGQCBRNsb25nUHJlbWl1bUZyYWN0aW9uCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAQZc2hvcnRUb3RhbFByZW1pdW1GcmFjdGlvbgkBA2FicwEJAQRtdWxkAgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUABA5wcmVtaXVtVG9WYXVsdAkAZQIFGGxvbmdUb3RhbFByZW1pdW1GcmFjdGlvbgUZc2hvcnRUb3RhbFByZW1pdW1GcmFjdGlvbgkAlQoDBRNsb25nUHJlbWl1bUZyYWN0aW9uBRNsb25nUHJlbWl1bUZyYWN0aW9uBQ5wcmVtaXVtVG9WYXVsdAEOZ2V0QWRqdXN0ZWRGZWUCC19hcnRpZmFjdElkEF9iYXNlRmVlRGlzY291bnQECmJhc2VGZWVSYXcJAQNmZWUABAdiYXNlRmVlCQEEbXVsZAIFCmJhc2VGZWVSYXcFEF9iYXNlRmVlRGlzY291bnQEDSR0MDQzMzI2NDM4MjEDCQECIT0CBQtfYXJ0aWZhY3RJZAIABAxhcnRpZmFjdEtpbmQJAQRzdHJBAgkBEW5mdE1hbmFnZXJBZGRyZXNzAAkBDnRvQ29tcG9zaXRlS2V5AgUMa190b2tlbl90eXBlBQtfYXJ0aWZhY3RJZAMJAAACBQxhcnRpZmFjdEtpbmQFGEZFRV9SRURVQ1RJT05fVE9LRU5fVFlQRQQJcmVkdWN0aW9uCQEEaW50QQIJARFuZnRNYW5hZ2VyQWRkcmVzcwAJAQ50b0NvbXBvc2l0ZUtleQIFDWtfdG9rZW5fcGFyYW0FC19hcnRpZmFjdElkBAthZGp1c3RlZEZlZQkBBG11bGQCBQdiYXNlRmVlBQlyZWR1Y3Rpb24JAJQKAgULYWRqdXN0ZWRGZWUGCQACAQIZSW52YWxpZCBhdHRhY2hlZCBhcnRpZmFjdAkAlAoCBQdiYXNlRmVlBwQLYWRqdXN0ZWRGZWUIBQ0kdDA0MzMyNjQzODIxAl8xBAxidXJuQXJ0aWZhY3QIBQ0kdDA0MzMyNjQzODIxAl8yCQCUCgIFC2FkanVzdGVkRmVlBQxidXJuQXJ0aWZhY3QBF2lzU2FtZUFzc2V0T3JOb1Bvc2l0aW9uAgdfdHJhZGVyCF9hc3NldElkBA9vbGRQb3NpdGlvblNpemUICQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyAl8xAwkAAAIFD29sZFBvc2l0aW9uU2l6ZQAABgkAAAIJARBnZXRQb3NpdGlvbkFzc2V0AQUHX3RyYWRlcgUIX2Fzc2V0SWQBC2lzU2FtZUFzc2V0AgdfdHJhZGVyCF9hc3NldElkCQAAAgkBEGdldFBvc2l0aW9uQXNzZXQBBQdfdHJhZGVyBQhfYXNzZXRJZAEYZ2V0Rm9yVHJhZGVyV2l0aEFydGlmYWN0AgdfdHJhZGVyC19hcnRpZmFjdElkBBBkb0dldEZlZURpc2NvdW50CQD8BwQJAQxtaW5lckFkZHJlc3MAAhJjb21wdXRlRmVlRGlzY291bnQJAMwIAgUHX3RyYWRlcgUDbmlsBQNuaWwDCQAAAgUQZG9HZXRGZWVEaXNjb3VudAUQZG9HZXRGZWVEaXNjb3VudAQLZmVlRGlzY291bnQEByRtYXRjaDAFEGRvR2V0RmVlRGlzY291bnQDCQABAgUHJG1hdGNoMAIDSW50BAF4BQckbWF0Y2gwBQF4CQACAQIhSW52YWxpZCBjb21wdXRlRmVlRGlzY291bnQgcmVzdWx0BA0kdDA0NDUwMTQ0NTc1CQEOZ2V0QWRqdXN0ZWRGZWUCBQtfYXJ0aWZhY3RJZAULZmVlRGlzY291bnQEC2FkanVzdGVkRmVlCAUNJHQwNDQ1MDE0NDU3NQJfMQQMYnVybkFydGlmYWN0CAUNJHQwNDQ1MDE0NDU3NQJfMgkAlAoCBQthZGp1c3RlZEZlZQUMYnVybkFydGlmYWN0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQ1nZXRBcnRpZmFjdElkAQFpBAphcnRpZmFjdElkAwkAZgIJAJADAQgFAWkIcGF5bWVudHMAAQkA2AQBCQETdmFsdWVPckVycm9yTWVzc2FnZQIICQCRAwIIBQFpCHBheW1lbnRzAAEHYXNzZXRJZAISSW52YWxpZCBhcnRpZmFjdElkAgAFCmFydGlmYWN0SWQBDWRpc3RyaWJ1dGVGZWUBCl9mZWVBbW91bnQEDGZlZVRvU3Rha2VycwkBBG11bGQCBQpfZmVlQW1vdW50CQETZmVlVG9TdGFrZXJzUGVyY2VudAAECmZlZVRvVmF1bHQJAGUCBQpfZmVlQW1vdW50BQxmZWVUb1N0YWtlcnMJAJQKAgUMZmVlVG9TdGFrZXJzBQpmZWVUb1ZhdWx0AQ51cGRhdGVTZXR0aW5ncw4QX2luaXRNYXJnaW5SYXRpbwRfbW1yFF9saXF1aWRhdGlvbkZlZVJhdGlvDl9mdW5kaW5nUGVyaW9kBF9mZWUMX3NwcmVhZExpbWl0D19tYXhQcmljZUltcGFjdBhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8PX21heFByaWNlU3ByZWFkEF9tYXhPcGVuTm90aW9uYWwUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQPX21heE9yYWNsZURlbGF5DF9yb2xsb3ZlckZlZQxfZnVuZGluZ01vZGUJAMwIAgkBDEludGVnZXJFbnRyeQIFEWtfaW5pdE1hcmdpblJhdGlvBRBfaW5pdE1hcmdpblJhdGlvCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRhrX21haW50ZW5hbmNlTWFyZ2luUmF0aW8FBF9tbXIJAMwIAgkBDEludGVnZXJFbnRyeQIFFWtfbGlxdWlkYXRpb25GZWVSYXRpbwUUX2xpcXVpZGF0aW9uRmVlUmF0aW8JAMwIAgkBDEludGVnZXJFbnRyeQIFD2tfZnVuZGluZ1BlcmlvZAUOX2Z1bmRpbmdQZXJpb2QJAMwIAgkBDEludGVnZXJFbnRyeQIFBWtfZmVlBQRfZmVlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ1rX3NwcmVhZExpbWl0BQxfc3ByZWFkTGltaXQJAMwIAgkBDEludGVnZXJFbnRyeQIFEGtfbWF4UHJpY2VJbXBhY3QFD19tYXhQcmljZUltcGFjdAkAzAgCCQEMSW50ZWdlckVudHJ5AgUZa19wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwUYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRBrX21heFByaWNlU3ByZWFkBQ9fbWF4UHJpY2VTcHJlYWQJAMwIAgkBDEludGVnZXJFbnRyeQIFEWtfbWF4T3Blbk5vdGlvbmFsBRBfbWF4T3Blbk5vdGlvbmFsCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRVrX2ZlZVRvU3Rha2Vyc1BlcmNlbnQFFF9mZWVUb1N0YWtlcnNQZXJjZW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCBRBrX21heE9yYWNsZURlbGF5BRRfZmVlVG9TdGFrZXJzUGVyY2VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgUNa19yb2xsb3ZlckZlZQUMX3JvbGxvdmVyRmVlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ1rX2Z1bmRpbmdNb2RlBQxfZnVuZGluZ01vZGUFA25pbAENdXBkYXRlRnVuZGluZwURX25leHRGdW5kaW5nQmxvY2skX2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uJV9sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24QX2xvbmdGdW5kaW5nUmF0ZRFfc2hvcnRGdW5kaW5nUmF0ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUSa19uZXh0RnVuZGluZ0Jsb2NrBRFfbmV4dEZ1bmRpbmdCbG9jawkAzAgCCQEMSW50ZWdlckVudHJ5AgUla19sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUkX2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uCQDMCAIJAQxJbnRlZ2VyRW50cnkCBSZrX2xhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUlX2xhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgURa19sb25nRnVuZGluZ1JhdGUFEF9sb25nRnVuZGluZ1JhdGUJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfc2hvcnRGdW5kaW5nUmF0ZQURX3Nob3J0RnVuZGluZ1JhdGUFA25pbAEfaW5jcmVtZW50UG9zaXRpb25TZXF1ZW5jZU51bWJlcgIOX2lzTmV3UG9zaXRpb24IX2FkZHJlc3MDBQ5faXNOZXdQb3NpdGlvbgQPY3VycmVudFNlcXVlbmNlCQEMbGFzdFNlcXVlbmNlAAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUSa19wb3NpdGlvblNlcXVlbmNlBQhfYWRkcmVzcwkAZAIFD2N1cnJlbnRTZXF1ZW5jZQABCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQprX3NlcXVlbmNlCQBkAgUPY3VycmVudFNlcXVlbmNlAAEFA25pbAUDbmlsARF1cGRhdGVQb3NpdGlvbkZlZQMOX2lzTmV3UG9zaXRpb24IX2FkZHJlc3MEX2ZlZQMFDl9pc05ld1Bvc2l0aW9uCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBQ1rX3Bvc2l0aW9uRmVlBQhfYWRkcmVzcwUEX2ZlZQUDbmlsBQNuaWwBDnVwZGF0ZVBvc2l0aW9uBghfYWRkcmVzcwVfc2l6ZQdfbWFyZ2luDV9vcGVuTm90aW9uYWwgX2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24QX2xhdGVzdFRpbWVzdGFtcAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUOa19wb3NpdGlvblNpemUFCF9hZGRyZXNzBQVfc2l6ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUQa19wb3NpdGlvbk1hcmdpbgUIX2FkZHJlc3MFB19tYXJnaW4JAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFFmtfcG9zaXRpb25PcGVuTm90aW9uYWwFCF9hZGRyZXNzBQ1fb3Blbk5vdGlvbmFsCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBS5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBQhfYWRkcmVzcwUgX2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24JAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFHmtfcG9zaXRpb25MYXN0VXBkYXRlZFRpbWVzdGFtcAUIX2FkZHJlc3MFEF9sYXRlc3RUaW1lc3RhbXAFA25pbAEKYXBwZW5kVHdhcAEGX3ByaWNlBAhtaW51dGVJZAkAaQIJAGkCCQENbGFzdFRpbWVzdGFtcAAA6AcAPAQQcHJldmlvdXNNaW51dGVJZAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQ5rX2xhc3RNaW51dGVJZAAAAwkAZgIFEHByZXZpb3VzTWludXRlSWQFCG1pbnV0ZUlkCQACAQIRVFdBUCBvdXQtb2Ytb3JkZXIEDGxhc3RNaW51dGVJZAMJAAACBRBwcmV2aW91c01pbnV0ZUlkAAAFCG1pbnV0ZUlkBRBwcmV2aW91c01pbnV0ZUlkAwkAZgIFCG1pbnV0ZUlkBRBwcmV2aW91c01pbnV0ZUlkBBNwcmV2Q3VtdWxhdGl2ZVByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAKwCAgkArAICBR1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQIBXwkApAMBBRBwcmV2aW91c01pbnV0ZUlkAAAECXByZXZQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUTa190d2FwRGF0YUxhc3RQcmljZQIBXwkApAMBBRBwcmV2aW91c01pbnV0ZUlkBQZfcHJpY2UEE2xhc3RDdW11bGF0aXZlUHJpY2UJAGQCBRNwcmV2Q3VtdWxhdGl2ZVByaWNlCQBoAgkAZQIFCG1pbnV0ZUlkBQxsYXN0TWludXRlSWQFCXByZXZQcmljZQQEbGlzdAkBC3B1c2hUb1F1ZXVlAwkBCXN0clRvTGlzdAEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwUNa19sYXN0RGF0YVN0cgIABQ1UV0FQX0lOVEVSVkFMCQCkAwEFCG1pbnV0ZUlkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBR1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQkApAMBBQhtaW51dGVJZAUTbGFzdEN1bXVsYXRpdmVQcmljZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUTa190d2FwRGF0YUxhc3RQcmljZQkApAMBBQhtaW51dGVJZAUGX3ByaWNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRprX3R3YXBEYXRhUHJldmlvdXNNaW51dGVJZAkApAMBBQhtaW51dGVJZAUQcHJldmlvdXNNaW51dGVJZAkAzAgCCQEMSW50ZWdlckVudHJ5AgUOa19sYXN0TWludXRlSWQFCG1pbnV0ZUlkCQDMCAIJAQtTdHJpbmdFbnRyeQIFDWtfbGFzdERhdGFTdHIJAQlsaXN0VG9TdHIBBQRsaXN0BQNuaWwEGHR3YXBEYXRhUHJldmlvdXNNaW51dGVJZAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBRprX3R3YXBEYXRhUHJldmlvdXNNaW51dGVJZAkApAMBBQhtaW51dGVJZAAABBNwcmV2Q3VtdWxhdGl2ZVByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlCQCkAwEFGHR3YXBEYXRhUHJldmlvdXNNaW51dGVJZAAABAlwcmV2UHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUTa190d2FwRGF0YUxhc3RQcmljZQkApAMBBRh0d2FwRGF0YVByZXZpb3VzTWludXRlSWQFBl9wcmljZQQTbGFzdEN1bXVsYXRpdmVQcmljZQkAZAIFE3ByZXZDdW11bGF0aXZlUHJpY2UJAGgCCQBlAgUIbWludXRlSWQFGHR3YXBEYXRhUHJldmlvdXNNaW51dGVJZAUJcHJldlByaWNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBR1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQkApAMBBQhtaW51dGVJZAUTbGFzdEN1bXVsYXRpdmVQcmljZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUTa190d2FwRGF0YUxhc3RQcmljZQkApAMBBQhtaW51dGVJZAUGX3ByaWNlBQNuaWwBEXVwZGF0ZUFtbVJlc2VydmVzAgdfcXRBc3RSB19ic0FzdFIJAMwIAgkBDEludGVnZXJFbnRyeQIFE2tfcXVvdGVBc3NldFJlc2VydmUFB19xdEFzdFIJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfYmFzZUFzc2V0UmVzZXJ2ZQUHX2JzQXN0UgUDbmlsARB1cGRhdGVBbW1XZWlnaHRzAgdfcXRBc3RXB19ic0FzdFcJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfcXVvdGVBc3NldFdlaWdodAUHX3F0QXN0VwkAzAgCCQEMSW50ZWdlckVudHJ5AgURa19iYXNlQXNzZXRXZWlnaHQFB19ic0FzdFcFA25pbAEJdXBkYXRlQW1tCAdfcXRBc3RSB19ic0FzdFIXX3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIVX29wZW5JbnRlcmVzdE5vdGlvbmFsFl90b3RhbExvbmdQb3NpdGlvblNpemUXX3RvdGFsU2hvcnRQb3NpdGlvblNpemUWX3RvdGFsTG9uZ09wZW5Ob3Rpb25hbBdfdG90YWxTaG9ydE9wZW5Ob3Rpb25hbAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcAAwkBAiE9AgkAZQIFFl90b3RhbExvbmdQb3NpdGlvblNpemUFF190b3RhbFNob3J0UG9zaXRpb25TaXplBRdfdG90YWxQb3NpdGlvblNpemVBZnRlcgkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAhhJbnZhbGlkIEFNTSBzdGF0ZSBkYXRhOiAJAKQDAQUWX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQIEICsgIAkApAMBBRdfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQIEICE9IAkApAMBBRdfdG90YWxQb3NpdGlvblNpemVBZnRlcgkAzggCCQDOCAIJARF1cGRhdGVBbW1SZXNlcnZlcwIFB19xdEFzdFIFB19ic0FzdFIJAMwIAgkBDEludGVnZXJFbnRyeQIFE2tfdG90YWxQb3NpdGlvblNpemUFF190b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRZrX29wZW5JbnRlcmVzdE5vdGlvbmFsBRVfb3BlbkludGVyZXN0Tm90aW9uYWwJAMwIAgkBDEludGVnZXJFbnRyeQIFF2tfdG90YWxMb25nUG9zaXRpb25TaXplBRZfdG90YWxMb25nUG9zaXRpb25TaXplCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRhrX3RvdGFsU2hvcnRQb3NpdGlvblNpemUFF190b3RhbFNob3J0UG9zaXRpb25TaXplCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJrX29wZW5JbnRlcmVzdExvbmcFFl90b3RhbExvbmdPcGVuTm90aW9uYWwJAMwIAgkBDEludGVnZXJFbnRyeQIFE2tfb3BlbkludGVyZXN0U2hvcnQFF190b3RhbFNob3J0T3Blbk5vdGlvbmFsBQNuaWwJAQphcHBlbmRUd2FwAQkBBGRpdmQCCQEEbXVsZAIFB19xdEFzdFIFB19xdEFzdFcJAQRtdWxkAgUHX2JzQXN0UgUHX2JzQXN0VwEOZGVsZXRlUG9zaXRpb24BCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFDmtfcG9zaXRpb25TaXplBQhfYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBRBrX3Bvc2l0aW9uTWFyZ2luBQhfYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBRZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBQhfYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBS5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBQhfYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBQ9rX3Bvc2l0aW9uQXNzZXQFCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFDWtfcG9zaXRpb25GZWUFCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFHmtfcG9zaXRpb25MYXN0VXBkYXRlZFRpbWVzdGFtcAUIX2FkZHJlc3MFA25pbAEId2l0aGRyYXcCCF9hZGRyZXNzB19hbW91bnQEB2JhbGFuY2UJAPAHAgUEdGhpcwkBCnF1b3RlQXNzZXQAAwkAZgIFB19hbW91bnQFB2JhbGFuY2UJAAIBCQCsAgIJAKwCAgkArAICAhNVbmFibGUgdG8gd2l0aGRyYXcgCQCkAwEFB19hbW91bnQCFyBmcm9tIGNvbnRyYWN0IGJhbGFuY2UgCQCkAwEFB2JhbGFuY2UJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUIX2FkZHJlc3MFB19hbW91bnQJAQpxdW90ZUFzc2V0AAUDbmlsAQ11cGRhdGVCYWxhbmNlAQFpAwkAZgIAAAUBaQkAAgECB0JhbGFuY2UJAMwIAgkBDEludGVnZXJFbnRyeQIFCWtfYmFsYW5jZQUBaQUDbmlsAQt0cmFuc2ZlckZlZQEBaQkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCQEOc3Rha2luZ0FkZHJlc3MABQFpCQEKcXVvdGVBc3NldAAFA25pbAEOZG9CdXJuQXJ0aWZhY3QCDV9idXJuQXJ0aWZhY3QBaQMFDV9idXJuQXJ0aWZhY3QJAMwIAgkBBEJ1cm4CCQETdmFsdWVPckVycm9yTWVzc2FnZQIICQCRAwIIBQFpCHBheW1lbnRzAAEHYXNzZXRJZAIQSW52YWxpZCBhcnRpZmFjdAABBQNuaWwFA25pbBYBaQEFcGF1c2UAAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECFEludmFsaWQgcGF1c2UgcGFyYW1zCQDMCAIJAQxCb29sZWFuRW50cnkCBQhrX3BhdXNlZAYFA25pbAFpAQd1bnBhdXNlAAMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAhZJbnZhbGlkIHVucGF1c2UgcGFyYW1zCQDMCAIJAQxCb29sZWFuRW50cnkCBQhrX3BhdXNlZAcFA25pbAFpAQxzZXRDbG9zZU9ubHkAAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECG0ludmFsaWQgc2V0Q2xvc2VPbmx5IHBhcmFtcwkAzAgCCQEMQm9vbGVhbkVudHJ5AgULa19jbG9zZU9ubHkGBQNuaWwBaQEOdW5zZXRDbG9zZU9ubHkAAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECHUludmFsaWQgdW5zZXRDbG9zZU9ubHkgcGFyYW1zCQDMCAIJAQxCb29sZWFuRW50cnkCBQtrX2Nsb3NlT25seQcFA25pbAFpAQxhZGRMaXF1aWRpdHkBEV9xdW90ZUFzc2V0QW1vdW50AwMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAGCQBnAgAABRFfcXVvdGVBc3NldEFtb3VudAkAAgECG0ludmFsaWQgYWRkTGlxdWlkaXR5IHBhcmFtcwQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwAEBXByaWNlCQEEZGl2ZAIJAQRtdWxkAgUHX3F0QXN0UgUHX3F0QXN0VwkBBG11bGQCBQdfYnNBc3RSBQdfYnNBc3RXBAtxdEFzdFJBZnRlcgkAZAIFB19xdEFzdFIFEV9xdW90ZUFzc2V0QW1vdW50BBRiYXNlQXNzZXRBbW91bnRUb0FkZAkAZQIJAQRkaXZkAgkBBG11bGQCBQtxdEFzdFJBZnRlcgUHX3F0QXN0VwUFcHJpY2UFB19ic0FzdFIEC2JzQXN0UkFmdGVyCQBkAgUHX2JzQXN0UgUUYmFzZUFzc2V0QW1vdW50VG9BZGQEDSR0MDU0Nzk0NTQ5NDUJARRnZXRTeW5jVGVybWluYWxQcmljZQMJAQ5nZXRPcmFjbGVQcmljZQAFC3F0QXN0UkFmdGVyBQtic0FzdFJBZnRlcgQTbmV3UXVvdGVBc3NldFdlaWdodAgFDSR0MDU0Nzk0NTQ5NDUCXzEEEm5ld0Jhc2VBc3NldFdlaWdodAgFDSR0MDU0Nzk0NTQ5NDUCXzIEDW1hcmdpblRvVmF1bHQIBQ0kdDA1NDc5NDU0OTQ1Al8zBA1kb0V4Y2hhbmdlUG5MAwkBAiE9AgUNbWFyZ2luVG9WYXVsdAAABA1kb0V4Y2hhbmdlUG5MCQD8BwQJAQx2YXVsdEFkZHJlc3MAAhVleGNoYW5nZUZyZWVBbmRMb2NrZWQJAMwIAgUNbWFyZ2luVG9WYXVsdAUDbmlsBQNuaWwDCQAAAgUNZG9FeGNoYW5nZVBuTAUNZG9FeGNoYW5nZVBuTAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUNZG9FeGNoYW5nZVBuTAUNZG9FeGNoYW5nZVBuTAkAzggCCQERdXBkYXRlQW1tUmVzZXJ2ZXMCBQtxdEFzdFJBZnRlcgULYnNBc3RSQWZ0ZXIJARB1cGRhdGVBbW1XZWlnaHRzAgUTbmV3UXVvdGVBc3NldFdlaWdodAUSbmV3QmFzZUFzc2V0V2VpZ2h0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBD3JlbW92ZUxpcXVpZGl0eQERX3F1b3RlQXNzZXRBbW91bnQDAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAYJAGcCBRFfcXVvdGVBc3NldEFtb3VudAAACQACAQIeSW52YWxpZCByZW1vdmVMaXF1aWRpdHkgcGFyYW1zBAdfcXRBc3RSCQEGcXRBc3RSAAQHX2JzQXN0UgkBBmJzQXN0UgAEB19xdEFzdFcJAQZxdEFzdFcABAdfYnNBc3RXCQEGYnNBc3RXAAQFcHJpY2UJAQRkaXZkAgkBBG11bGQCBQdfcXRBc3RSBQdfcXRBc3RXCQEEbXVsZAIFB19ic0FzdFIFB19ic0FzdFcEC3F0QXN0UkFmdGVyCQBlAgUHX3F0QXN0UgURX3F1b3RlQXNzZXRBbW91bnQEF2Jhc2VBc3NldEFtb3VudFRvUmVtb3ZlCQEDYWJzAQkAZQIJAQRkaXZkAgkBBG11bGQCBQtxdEFzdFJBZnRlcgUHX3F0QXN0VwUFcHJpY2UFB19ic0FzdFIEC2JzQXN0UkFmdGVyCQBlAgUHX2JzQXN0UgUXYmFzZUFzc2V0QW1vdW50VG9SZW1vdmUEDSR0MDU2MDQxNTYxOTIJARRnZXRTeW5jVGVybWluYWxQcmljZQMJAQ5nZXRPcmFjbGVQcmljZQAFC3F0QXN0UkFmdGVyBQtic0FzdFJBZnRlcgQTbmV3UXVvdGVBc3NldFdlaWdodAgFDSR0MDU2MDQxNTYxOTICXzEEEm5ld0Jhc2VBc3NldFdlaWdodAgFDSR0MDU2MDQxNTYxOTICXzIEDW1hcmdpblRvVmF1bHQIBQ0kdDA1NjA0MTU2MTkyAl8zBA1kb0V4Y2hhbmdlUG5MAwkBAiE9AgUNbWFyZ2luVG9WYXVsdAAABA1kb0V4Y2hhbmdlUG5MCQD8BwQJAQx2YXVsdEFkZHJlc3MAAhVleGNoYW5nZUZyZWVBbmRMb2NrZWQJAMwIAgUNbWFyZ2luVG9WYXVsdAUDbmlsBQNuaWwDCQAAAgUNZG9FeGNoYW5nZVBuTAUNZG9FeGNoYW5nZVBuTAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUNZG9FeGNoYW5nZVBuTAUNZG9FeGNoYW5nZVBuTAkAzggCCQERdXBkYXRlQW1tUmVzZXJ2ZXMCBQtxdEFzdFJBZnRlcgULYnNBc3RSQWZ0ZXIJARB1cGRhdGVBbW1XZWlnaHRzAgUTbmV3UXVvdGVBc3NldFdlaWdodAUSbmV3QmFzZUFzc2V0V2VpZ2h0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDmNoYW5nZVNldHRpbmdzDhBfaW5pdE1hcmdpblJhdGlvBF9tbXIUX2xpcXVpZGF0aW9uRmVlUmF0aW8OX2Z1bmRpbmdQZXJpb2QEX2ZlZQxfc3ByZWFkTGltaXQPX21heFByaWNlSW1wYWN0GF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbw9fbWF4UHJpY2VTcHJlYWQQX21heE9wZW5Ob3Rpb25hbBRfZmVlVG9TdGFrZXJzUGVyY2VudA9fbWF4T3JhY2xlRGVsYXkMX3JvbGxvdmVyRmVlDF9mdW5kaW5nTW9kZQMDAwMDAwMDAwMDAwMDAwMDCQBnAgAABQ5fZnVuZGluZ1BlcmlvZAYJAGcCAAAFEF9pbml0TWFyZ2luUmF0aW8GCQBnAgAABQRfbW1yBgkAZwIAAAUUX2xpcXVpZGF0aW9uRmVlUmF0aW8GCQBnAgAABQRfZmVlBgkAZwIAAAUMX3NwcmVhZExpbWl0BgkAZwIAAAUPX21heFByaWNlSW1wYWN0BgkAZwIAAAUYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvBgkAZwIAAAUPX21heFByaWNlU3ByZWFkBgkAZwIAAAUQX21heE9wZW5Ob3Rpb25hbAYJAGcCAAAFFF9mZWVUb1N0YWtlcnNQZXJjZW50BgkAZgIFFF9mZWVUb1N0YWtlcnNQZXJjZW50BQxERUNJTUFMX1VOSVQGCQBnAgAABQ9fbWF4T3JhY2xlRGVsYXkGCQBnAgAABQxfcm9sbG92ZXJGZWUGAwkBAiE9AgUMX2Z1bmRpbmdNb2RlBRFGVU5ESU5HX1NZTU1FVFJJQwkBAiE9AgUMX2Z1bmRpbmdNb2RlBRJGVU5ESU5HX0FTWU1NRVRSSUMHBgkBASEBCQELaW5pdGlhbGl6ZWQABgkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECHUludmFsaWQgY2hhbmdlU2V0dGluZ3MgcGFyYW1zCQEOdXBkYXRlU2V0dGluZ3MOBRBfaW5pdE1hcmdpblJhdGlvBQRfbW1yBRRfbGlxdWlkYXRpb25GZWVSYXRpbwUOX2Z1bmRpbmdQZXJpb2QFBF9mZWUFDF9zcHJlYWRMaW1pdAUPX21heFByaWNlSW1wYWN0BRhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8FD19tYXhQcmljZVNwcmVhZAUQX21heE9wZW5Ob3Rpb25hbAUUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQFD19tYXhPcmFjbGVEZWxheQUMX3JvbGxvdmVyRmVlBQxfZnVuZGluZ01vZGUBaQEKaW5pdGlhbGl6ZRMHX3F0QXN0UgdfYnNBc3RSDl9mdW5kaW5nUGVyaW9kEF9pbml0TWFyZ2luUmF0aW8EX21tchRfbGlxdWlkYXRpb25GZWVSYXRpbwRfZmVlD19iYXNlT3JhY2xlRGF0YRBfcXVvdGVPcmFjbGVEYXRhDF9jb29yZGluYXRvcgxfc3ByZWFkTGltaXQPX21heFByaWNlSW1wYWN0GF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbw9fbWF4UHJpY2VTcHJlYWQQX21heE9wZW5Ob3Rpb25hbBRfZmVlVG9TdGFrZXJzUGVyY2VudA9fbWF4T3JhY2xlRGVsYXkMX3JvbGxvdmVyRmVlDF9mdW5kaW5nTW9kZQMDAwMDAwMDAwMDAwMDAwMDAwMJAGcCAAAFB19xdEFzdFIGCQBnAgAABQdfYnNBc3RSBgkAZwIAAAUOX2Z1bmRpbmdQZXJpb2QGCQBnAgAABRBfaW5pdE1hcmdpblJhdGlvBgkAZwIAAAUEX21tcgYJAGcCAAAFFF9saXF1aWRhdGlvbkZlZVJhdGlvBgkAZwIAAAUEX2ZlZQYJAGcCAAAFDF9zcHJlYWRMaW1pdAYJAGcCAAAFD19tYXhQcmljZUltcGFjdAYJAGcCAAAFGF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwYJAGcCAAAFD19tYXhQcmljZVNwcmVhZAYJAGcCAAAFEF9tYXhPcGVuTm90aW9uYWwGCQBnAgAABRRfZmVlVG9TdGFrZXJzUGVyY2VudAYJAGYCBRRfZmVlVG9TdGFrZXJzUGVyY2VudAUMREVDSU1BTF9VTklUBgkAZwIAAAUPX21heE9yYWNsZURlbGF5BgkAZwIAAAUMX3JvbGxvdmVyRmVlBgMJAQIhPQIFDF9mdW5kaW5nTW9kZQURRlVORElOR19TWU1NRVRSSUMJAQIhPQIFDF9mdW5kaW5nTW9kZQUSRlVORElOR19BU1lNTUVUUklDBwYJAQtpbml0aWFsaXplZAAGCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAh1JbnZhbGlkIGluaXRpYWxpemUgcGFyYW1ldGVycwkAzggCCQDOCAIJAM4IAgkAzggCCQEJdXBkYXRlQW1tCAUHX3F0QXN0UgUHX2JzQXN0UgAAAAAAAAAAAAAAAAkBDnVwZGF0ZVNldHRpbmdzDgUQX2luaXRNYXJnaW5SYXRpbwUEX21tcgUUX2xpcXVpZGF0aW9uRmVlUmF0aW8FDl9mdW5kaW5nUGVyaW9kBQRfZmVlBQxfc3ByZWFkTGltaXQFD19tYXhQcmljZUltcGFjdAUYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvBQ9fbWF4UHJpY2VTcHJlYWQFEF9tYXhPcGVuTm90aW9uYWwFFF9mZWVUb1N0YWtlcnNQZXJjZW50BQ9fbWF4T3JhY2xlRGVsYXkFDF9yb2xsb3ZlckZlZQUMX2Z1bmRpbmdNb2RlCQENdXBkYXRlRnVuZGluZwUJAGQCCQENbGFzdFRpbWVzdGFtcAAFDl9mdW5kaW5nUGVyaW9kAAAAAAAAAAAJAQ11cGRhdGVCYWxhbmNlAQAACQDMCAIJAQxCb29sZWFuRW50cnkCBQ1rX2luaXRpYWxpemVkBgkAzAgCCQELU3RyaW5nRW50cnkCBQxrX2Jhc2VPcmFjbGUFD19iYXNlT3JhY2xlRGF0YQkAzAgCCQELU3RyaW5nRW50cnkCBQ1rX3F1b3RlT3JhY2xlBRBfcXVvdGVPcmFjbGVEYXRhCQDMCAIJAQtTdHJpbmdFbnRyeQIFFGtfY29vcmRpbmF0b3JBZGRyZXNzCQClCAEJARFAZXh0ck5hdGl2ZSgxMDYyKQEFDF9jb29yZGluYXRvcgUDbmlsAWkBEGluY3JlYXNlUG9zaXRpb24ECl9kaXJlY3Rpb24JX2xldmVyYWdlE19taW5CYXNlQXNzZXRBbW91bnQIX3JlZkxpbmsEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQQZW5zdXJlQ2FsbGVkT25jZQkA/AcEBQR0aGlzAhBlbnN1cmVDYWxsZWRPbmNlBQNuaWwFA25pbAMJAAACBRBlbnN1cmVDYWxsZWRPbmNlBRBlbnN1cmVDYWxsZWRPbmNlBAdfdHJhZGVyCQEPZ2V0QWN0dWFsQ2FsbGVyAQUBaQQKX3Jhd0Ftb3VudAgJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQECF9hc3NldElkCAkAkQMCCAUBaQhwYXltZW50cwAAB2Fzc2V0SWQEC19hc3NldElkU3RyCQDYBAEJAQV2YWx1ZQEFCF9hc3NldElkBAxpc1F1b3RlQXNzZXQJAAACBQhfYXNzZXRJZAkBCnF1b3RlQXNzZXQAAwMDAwMDAwMDAwkBAiE9AgUKX2RpcmVjdGlvbgUIRElSX0xPTkcJAQIhPQIFCl9kaXJlY3Rpb24FCURJUl9TSE9SVAcGCQBnAgAABQpfcmF3QW1vdW50BgkBASEBCQELaW5pdGlhbGl6ZWQABgkBASEBBQxpc1F1b3RlQXNzZXQGCQEBIQEJARdpc1NhbWVBc3NldE9yTm9Qb3NpdGlvbgIFB190cmFkZXIFC19hc3NldElkU3RyBgkBASEBCQEWcmVxdWlyZU1vcmVNYXJnaW5SYXRpbwMJAQRkaXZkAgUMREVDSU1BTF9VTklUBQlfbGV2ZXJhZ2UJAQ9pbml0TWFyZ2luUmF0aW8ABgYJAQZwYXVzZWQABgkBCWNsb3NlT25seQAGCQEOaXNNYXJrZXRDbG9zZWQACQACAQIjSW52YWxpZCBpbmNyZWFzZVBvc2l0aW9uIHBhcmFtZXRlcnMEDSR0MDYyMzE2NjI0NjUJARhnZXRGb3JUcmFkZXJXaXRoQXJ0aWZhY3QCBQdfdHJhZGVyCQENZ2V0QXJ0aWZhY3RJZAEFAWkEC2FkanVzdGVkRmVlCAUNJHQwNjIzMTY2MjQ2NQJfMQQMYnVybkFydGlmYWN0CAUNJHQwNjIzMTY2MjQ2NQJfMgQHX2Ftb3VudAkBBGRpdmQCBQpfcmF3QW1vdW50CQBkAgkBBG11bGQCBQthZGp1c3RlZEZlZQUJX2xldmVyYWdlBQxERUNJTUFMX1VOSVQEE2Rpc3RyaWJ1dGVGZWVBbW91bnQJAGUCBQpfcmF3QW1vdW50BQdfYW1vdW50BA5yZWZlcnJlckZlZUFueQkA/AcECQEPcmVmZXJyYWxBZGRyZXNzAAIVYWNjZXB0UGF5bWVudFdpdGhMaW5rCQDMCAIFB190cmFkZXIJAMwIAgUIX3JlZkxpbmsFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABRNkaXN0cmlidXRlRmVlQW1vdW50BQNuaWwDCQAAAgUOcmVmZXJyZXJGZWVBbnkFDnJlZmVycmVyRmVlQW55BAtyZWZlcnJlckZlZQQHJG1hdGNoMAUOcmVmZXJyZXJGZWVBbnkDCQABAgUHJG1hdGNoMAIDSW50BAF4BQckbWF0Y2gwBQF4CQACAQITSW52YWxpZCByZWZlcnJlckZlZQQJZmVlQW1vdW50CQBlAgUTZGlzdHJpYnV0ZUZlZUFtb3VudAULcmVmZXJyZXJGZWUEDSR0MDYyOTYxNjMxMjkJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIED29sZFBvc2l0aW9uU2l6ZQgFDSR0MDYyOTYxNjMxMjkCXzEEEW9sZFBvc2l0aW9uTWFyZ2luCAUNJHQwNjI5NjE2MzEyOQJfMgQXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA2Mjk2MTYzMTI5Al8zBBRvbGRQb3NpdGlvbkxzdFVwZENQRggFDSR0MDYyOTYxNjMxMjkCXzQEFG9sZFBvc2l0aW9uVGltZXN0YW1wCAUNJHQwNjI5NjE2MzEyOQJfNQQNaXNOZXdQb3NpdGlvbgkAAAIFD29sZFBvc2l0aW9uU2l6ZQAABA9pc1NhbWVEaXJlY3Rpb24DCQBmAgUPb2xkUG9zaXRpb25TaXplAAAJAAACBQpfZGlyZWN0aW9uBQhESVJfTE9ORwkAAAIFCl9kaXJlY3Rpb24FCURJUl9TSE9SVAQOZXhwYW5kRXhpc3RpbmcDCQEBIQEFDWlzTmV3UG9zaXRpb24FD2lzU2FtZURpcmVjdGlvbgcEBWlzQWRkCQAAAgUKX2RpcmVjdGlvbgUIRElSX0xPTkcEDSR0MDYzNDE4NjY1MzkDAwUNaXNOZXdQb3NpdGlvbgYFDmV4cGFuZEV4aXN0aW5nBAxvcGVuTm90aW9uYWwJAQRtdWxkAgUHX2Ftb3VudAUJX2xldmVyYWdlBA0kdDA2MzkyNzY0MTAwCQEJc3dhcElucHV0AgUFaXNBZGQFDG9wZW5Ob3Rpb25hbAQVYW1vdW50QmFzZUFzc2V0Qm91Z2h0CAUNJHQwNjM5Mjc2NDEwMAJfMQQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDYzOTI3NjQxMDACXzIEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDYzOTI3NjQxMDACXzMEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA2MzkyNzY0MTAwAl80AwMJAQIhPQIFE19taW5CYXNlQXNzZXRBbW91bnQAAAkAZgIFE19taW5CYXNlQXNzZXRBbW91bnQJAQNhYnMBBRVhbW91bnRCYXNlQXNzZXRCb3VnaHQHCQACAQkArAICCQCsAgIJAKwCAgINTGltaXQgZXJyb3I6IAkApAMBCQEDYWJzAQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0AgMgPCAJAKQDAQUTX21pbkJhc2VBc3NldEFtb3VudAQPbmV3UG9zaXRpb25TaXplCQBkAgUPb2xkUG9zaXRpb25TaXplBRVhbW91bnRCYXNlQXNzZXRCb3VnaHQEGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyCQBkAgkBEG9wZW5JbnRlcmVzdExvbmcAAwkAZgIFD25ld1Bvc2l0aW9uU2l6ZQAABQxvcGVuTm90aW9uYWwAAAQbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCQBkAgkBEW9wZW5JbnRlcmVzdFNob3J0AAMJAGYCAAAFD25ld1Bvc2l0aW9uU2l6ZQUMb3Blbk5vdGlvbmFsAAAEDSR0MDY0NjQ2NjQ5MjEJATBjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50QW5kUm9sbG92ZXJGZWUFBQ9vbGRQb3NpdGlvblNpemUFEW9sZFBvc2l0aW9uTWFyZ2luBRRvbGRQb3NpdGlvbkxzdFVwZENQRgUUb2xkUG9zaXRpb25UaW1lc3RhbXAFB19hbW91bnQEDHJlbWFpbk1hcmdpbggFDSR0MDY0NjQ2NjQ5MjECXzEEAngxCAUNJHQwNjQ2NDY2NDkyMQJfMgQCeDIIBQ0kdDA2NDY0NjY0OTIxAl8zBAtyb2xsb3ZlckZlZQgFDSR0MDY0NjQ2NjQ5MjECXzQDCQEBIQEJARlyZXF1aXJlTm90T3ZlclNwcmVhZExpbWl0AgUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCQACAQIVT3ZlciBtYXggc3ByZWFkIGxpbWl0AwkBASEBCQEdcmVxdWlyZU5vdE92ZXJNYXhPcGVuTm90aW9uYWwCBRp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgUbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCQACAQIWT3ZlciBtYXggb3BlbiBub3Rpb25hbAkAoAoOBQ9uZXdQb3NpdGlvblNpemUFDHJlbWFpbk1hcmdpbgkAZAIFF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsBQxvcGVuTm90aW9uYWwJAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUPbmV3UG9zaXRpb25TaXplCQENbGFzdFRpbWVzdGFtcAAFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgkAZAIJARRvcGVuSW50ZXJlc3ROb3Rpb25hbAAFDG9wZW5Ob3Rpb25hbAkAZAIJARV0b3RhbExvbmdQb3NpdGlvblNpemUAAwkAZgIFD25ld1Bvc2l0aW9uU2l6ZQAACQEDYWJzAQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0AAAJAGQCCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQADCQBmAgAABQ9uZXdQb3NpdGlvblNpemUJAQNhYnMBBRVhbW91bnRCYXNlQXNzZXRCb3VnaHQAAAUadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIFG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgULcm9sbG92ZXJGZWUEDG9wZW5Ob3Rpb25hbAkBBG11bGQCBQdfYW1vdW50BQlfbGV2ZXJhZ2UEDSR0MDY2MjM5NjYzNTUJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIJAKUIAQgFAWkGY2FsbGVyBQ9QTkxfT1BUSU9OX1NQT1QEE29sZFBvc2l0aW9uTm90aW9uYWwIBQ0kdDA2NjIzOTY2MzU1Al8xBA11bnJlYWxpemVkUG5sCAUNJHQwNjYyMzk2NjM1NQJfMgMJAGYCBRNvbGRQb3NpdGlvbk5vdGlvbmFsBQxvcGVuTm90aW9uYWwJAAIBAi5Vc2UgZGVjcmVhc2VQb3NpdGlvbiB0byBkZWNyZWFzZSBwb3NpdGlvbiBzaXplCQACAQIUQ2xvc2UgcG9zaXRpb24gZmlyc3QED25ld1Bvc2l0aW9uU2l6ZQgFDSR0MDYzNDE4NjY1MzkCXzEEF25ld1Bvc2l0aW9uUmVtYWluTWFyZ2luCAUNJHQwNjM0MTg2NjUzOQJfMgQXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA2MzQxODY2NTM5Al8zBBRuZXdQb3NpdGlvbkxhdGVzdENQRggFDSR0MDYzNDE4NjY1MzkCXzQEFG5ld1Bvc2l0aW9uVGltZXN0YW1wCAUNJHQwNjM0MTg2NjUzOQJfNQQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNjM0MTg2NjUzOQJfNgQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDYzNDE4NjY1MzkCXzcEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA2MzQxODY2NTM5Al84BBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCAUNJHQwNjM0MTg2NjUzOQJfOQQOdG90YWxMb25nQWZ0ZXIIBQ0kdDA2MzQxODY2NTM5A18xMAQPdG90YWxTaG9ydEFmdGVyCAUNJHQwNjM0MTg2NjUzOQNfMTEEGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNjM0MTg2NjUzOQNfMTIEG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDYzNDE4NjY1MzkDXzEzBAtyb2xsb3ZlckZlZQgFDSR0MDYzNDE4NjY1MzkDXzE0BA0kdDA2NjU0NTY2NjE2CQENZGlzdHJpYnV0ZUZlZQEJAGQCBQlmZWVBbW91bnQFC3JvbGxvdmVyRmVlBAxmZWVUb1N0YWtlcnMIBQ0kdDA2NjU0NTY2NjE2Al8xBApmZWVUb1ZhdWx0CAUNJHQwNjY1NDU2NjYxNgJfMgQFc3Rha2UDCQBnAgUHX2Ftb3VudAULcm9sbG92ZXJGZWUJAPwHBAkBDHZhdWx0QWRkcmVzcwACCWFkZExvY2tlZAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAJAGUCBQdfYW1vdW50BQtyb2xsb3ZlckZlZQUDbmlsCQD8BwQJAQx2YXVsdEFkZHJlc3MAAg53aXRoZHJhd0xvY2tlZAkAzAgCCQBlAgULcm9sbG92ZXJGZWUFB19hbW91bnQFA25pbAUDbmlsAwkAAAIFBXN0YWtlBQVzdGFrZQQMZGVwb3NpdFZhdWx0CQD8BwQJAQx2YXVsdEFkZHJlc3MAAgdhZGRGcmVlBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUKZmVlVG9WYXVsdAUDbmlsAwkAAAIFDGRlcG9zaXRWYXVsdAUMZGVwb3NpdFZhdWx0BAlub3RpZnlGZWUJAPwHBAkBDG1pbmVyQWRkcmVzcwACCm5vdGlmeUZlZXMJAMwIAgUHX3RyYWRlcgkAzAgCBQlmZWVBbW91bnQFA25pbAUDbmlsAwkAAAIFCW5vdGlmeUZlZQUJbm90aWZ5RmVlBA5ub3RpZnlOb3Rpb25hbAkA/AcECQEMbWluZXJBZGRyZXNzAAIObm90aWZ5Tm90aW9uYWwJAMwIAgUHX3RyYWRlcgkAzAgCBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUDbmlsBQNuaWwDCQAAAgUObm90aWZ5Tm90aW9uYWwFDm5vdGlmeU5vdGlvbmFsCQDOCAIJAM4IAgkAzggCCQDOCAIJAM4IAgkAzggCCQEOdXBkYXRlUG9zaXRpb24GBQdfdHJhZGVyBQ9uZXdQb3NpdGlvblNpemUFF25ld1Bvc2l0aW9uUmVtYWluTWFyZ2luBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUUbmV3UG9zaXRpb25MYXRlc3RDUEYFFG5ld1Bvc2l0aW9uVGltZXN0YW1wCQEfaW5jcmVtZW50UG9zaXRpb25TZXF1ZW5jZU51bWJlcgIFDWlzTmV3UG9zaXRpb24FB190cmFkZXIJARF1cGRhdGVQb3NpdGlvbkZlZQMFDWlzTmV3UG9zaXRpb24FB190cmFkZXIFC2FkanVzdGVkRmVlCQEJdXBkYXRlQW1tCAUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyBRp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgUbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCQELdHJhbnNmZXJGZWUBBQxmZWVUb1N0YWtlcnMJAQ11cGRhdGVCYWxhbmNlAQkAZQIJAGQCCQEIY2JhbGFuY2UABQdfYW1vdW50BQtyb2xsb3ZlckZlZQkBDmRvQnVybkFydGlmYWN0AgUMYnVybkFydGlmYWN0BQFpCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCWFkZE1hcmdpbgAEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQQZW5zdXJlQ2FsbGVkT25jZQkA/AcEBQR0aGlzAhBlbnN1cmVDYWxsZWRPbmNlBQNuaWwFA25pbAMJAAACBRBlbnN1cmVDYWxsZWRPbmNlBRBlbnN1cmVDYWxsZWRPbmNlBAdfdHJhZGVyCQClCAEIBQFpBmNhbGxlcgQHX2Ftb3VudAgJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQECF9hc3NldElkCAkAkQMCCAUBaQhwYXltZW50cwAAB2Fzc2V0SWQEC19hc3NldElkU3RyCQDYBAEJAQV2YWx1ZQEFCF9hc3NldElkBAxpc1F1b3RlQXNzZXQJAAACBQhfYXNzZXRJZAkBCnF1b3RlQXNzZXQAAwMDAwMDAwkBASEBBQxpc1F1b3RlQXNzZXQGCQEBIQEJARNyZXF1aXJlT3BlblBvc2l0aW9uAQkApQgBCAUBaQZjYWxsZXIGCQEBIQEJAQtpc1NhbWVBc3NldAIFB190cmFkZXIFC19hc3NldElkU3RyBgkBASEBCQELaW5pdGlhbGl6ZWQABgkBBnBhdXNlZAAGCQEJY2xvc2VPbmx5AAYJAQ5pc01hcmtldENsb3NlZAAJAAIBAhxJbnZhbGlkIGFkZE1hcmdpbiBwYXJhbWV0ZXJzBA0kdDA2ODg3MzY5MDQxCQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBA9vbGRQb3NpdGlvblNpemUIBQ0kdDA2ODg3MzY5MDQxAl8xBBFvbGRQb3NpdGlvbk1hcmdpbggFDSR0MDY4ODczNjkwNDECXzIEF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNjg4NzM2OTA0MQJfMwQUb2xkUG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA2ODg3MzY5MDQxAl80BBRvbGRQb3NpdGlvblRpbWVzdGFtcAgFDSR0MDY4ODczNjkwNDECXzUEBXN0YWtlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAglhZGRMb2NrZWQFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABQdfYW1vdW50BQNuaWwDCQAAAgUFc3Rha2UFBXN0YWtlBAtyb2xsb3ZlckZlZQkBD2NhbGNSb2xsb3ZlckZlZQIFEW9sZFBvc2l0aW9uTWFyZ2luBRRvbGRQb3NpdGlvblRpbWVzdGFtcAQWZG9UcmFuc2ZlckZlZVRvU3Rha2VycwMJAGYCBQtyb2xsb3ZlckZlZQAABA0kdDA2OTMyNjY5Mzg1CQENZGlzdHJpYnV0ZUZlZQEFC3JvbGxvdmVyRmVlBAxmZWVUb1N0YWtlcnMIBQ0kdDA2OTMyNjY5Mzg1Al8xBApmZWVUb1ZhdWx0CAUNJHQwNjkzMjY2OTM4NQJfMgQHdW5zdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIOd2l0aGRyYXdMb2NrZWQJAMwIAgUMZmVlVG9TdGFrZXJzBQNuaWwFA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlBAtsb2NrQmFkRGVidAkA/AcECQEMdmF1bHRBZGRyZXNzAAIVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkCQDMCAIJAQEtAQUKZmVlVG9WYXVsdAUDbmlsBQNuaWwDCQAAAgULbG9ja0JhZERlYnQFC2xvY2tCYWREZWJ0CQELdHJhbnNmZXJGZWUBBQxmZWVUb1N0YWtlcnMJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBRZkb1RyYW5zZmVyRmVlVG9TdGFrZXJzBRZkb1RyYW5zZmVyRmVlVG9TdGFrZXJzCQDOCAIJAM4IAgkBDnVwZGF0ZVBvc2l0aW9uBgUHX3RyYWRlcgUPb2xkUG9zaXRpb25TaXplCQBkAgkAZQIFEW9sZFBvc2l0aW9uTWFyZ2luBQtyb2xsb3ZlckZlZQUHX2Ftb3VudAUXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwFFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCQENbGFzdFRpbWVzdGFtcAAJAQ11cGRhdGVCYWxhbmNlAQkAZQIJAGQCCQEIY2JhbGFuY2UABQdfYW1vdW50BQtyb2xsb3ZlckZlZQUWZG9UcmFuc2ZlckZlZVRvU3Rha2VycwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQxyZW1vdmVNYXJnaW4BB19hbW91bnQEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQQZW5zdXJlQ2FsbGVkT25jZQkA/AcEBQR0aGlzAhBlbnN1cmVDYWxsZWRPbmNlBQNuaWwFA25pbAMJAAACBRBlbnN1cmVDYWxsZWRPbmNlBRBlbnN1cmVDYWxsZWRPbmNlBAdfdHJhZGVyCQClCAEIBQFpBmNhbGxlcgMDAwMDCQBnAgAABQdfYW1vdW50BgkBASEBCQETcmVxdWlyZU9wZW5Qb3NpdGlvbgEFB190cmFkZXIGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAYJAQ5pc01hcmtldENsb3NlZAAJAAIBAh9JbnZhbGlkIHJlbW92ZU1hcmdpbiBwYXJhbWV0ZXJzBA0kdDA3MDc1ODcwOTI2CQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBA9vbGRQb3NpdGlvblNpemUIBQ0kdDA3MDc1ODcwOTI2Al8xBBFvbGRQb3NpdGlvbk1hcmdpbggFDSR0MDcwNzU4NzA5MjYCXzIEF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNzA3NTg3MDkyNgJfMwQUb2xkUG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA3MDc1ODcwOTI2Al80BBRvbGRQb3NpdGlvblRpbWVzdGFtcAgFDSR0MDcwNzU4NzA5MjYCXzUEDSR0MDcwOTMyNzExODEJATBjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50QW5kUm9sbG92ZXJGZWUFBQ9vbGRQb3NpdGlvblNpemUFEW9sZFBvc2l0aW9uTWFyZ2luBRRvbGRQb3NpdGlvbkxzdFVwZENQRgUUb2xkUG9zaXRpb25UaW1lc3RhbXAJAQEtAQUHX2Ftb3VudAQMcmVtYWluTWFyZ2luCAUNJHQwNzA5MzI3MTE4MQJfMQQHYmFkRGVidAgFDSR0MDcwOTMyNzExODECXzIEDmZ1bmRpbmdQYXltZW50CAUNJHQwNzA5MzI3MTE4MQJfMwQLcm9sbG92ZXJGZWUIBQ0kdDA3MDkzMjcxMTgxAl80AwkBAiE9AgUHYmFkRGVidAAACQACAQIdSW52YWxpZCByZW1vdmVkIG1hcmdpbiBhbW91bnQEC21hcmdpblJhdGlvCQEPY2FsY01hcmdpblJhdGlvAwUMcmVtYWluTWFyZ2luBQdiYWREZWJ0BRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAMJAQEhAQkBFnJlcXVpcmVNb3JlTWFyZ2luUmF0aW8DBQttYXJnaW5SYXRpbwkBD2luaXRNYXJnaW5SYXRpbwAGCQACAQkArAICCQCsAgIJAKwCAgIZVG9vIG11Y2ggbWFyZ2luIHJlbW92ZWQ6IAkApAMBBQttYXJnaW5SYXRpbwIDIDwgCQCkAwEJAQ9pbml0TWFyZ2luUmF0aW8ABA0kdDA3MTU2NzcxNjI2CQENZGlzdHJpYnV0ZUZlZQEFC3JvbGxvdmVyRmVlBAxmZWVUb1N0YWtlcnMIBQ0kdDA3MTU2NzcxNjI2Al8xBApmZWVUb1ZhdWx0CAUNJHQwNzE1Njc3MTYyNgJfMgQWZG9UcmFuc2ZlckZlZVRvU3Rha2VycwMJAGYCBQtyb2xsb3ZlckZlZQAABAtsb2NrQmFkRGVidAkA/AcECQEMdmF1bHRBZGRyZXNzAAIVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkCQDMCAIJAQEtAQUKZmVlVG9WYXVsdAUDbmlsBQNuaWwDCQAAAgULbG9ja0JhZERlYnQFC2xvY2tCYWREZWJ0CQELdHJhbnNmZXJGZWUBBQxmZWVUb1N0YWtlcnMJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBRZkb1RyYW5zZmVyRmVlVG9TdGFrZXJzBRZkb1RyYW5zZmVyRmVlVG9TdGFrZXJzBAd1bnN0YWtlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAg53aXRoZHJhd0xvY2tlZAkAzAgCCQBkAgUHX2Ftb3VudAUMZmVlVG9TdGFrZXJzBQNuaWwFA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlCQDOCAIJAM4IAgkAzggCCQEOdXBkYXRlUG9zaXRpb24GBQdfdHJhZGVyBQ9vbGRQb3NpdGlvblNpemUFDHJlbWFpbk1hcmdpbgUXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwJAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUPb2xkUG9zaXRpb25TaXplCQENbGFzdFRpbWVzdGFtcAAJAQh3aXRoZHJhdwIIBQFpBmNhbGxlcgUHX2Ftb3VudAkBDXVwZGF0ZUJhbGFuY2UBCQBlAgkAZQIJAQhjYmFsYW5jZQAFB19hbW91bnQFC3JvbGxvdmVyRmVlBRZkb1RyYW5zZmVyRmVlVG9TdGFrZXJzCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDWNsb3NlUG9zaXRpb24DBV9zaXplFF9taW5RdW90ZUFzc2V0QW1vdW50DF9hZGRUb01hcmdpbgQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBBBlbnN1cmVDYWxsZWRPbmNlCQD8BwQFBHRoaXMCEGVuc3VyZUNhbGxlZE9uY2UFA25pbAUDbmlsAwkAAAIFEGVuc3VyZUNhbGxlZE9uY2UFEGVuc3VyZUNhbGxlZE9uY2UEB190cmFkZXIJAQ9nZXRBY3R1YWxDYWxsZXIBBQFpBA5fdHJhZGVyQWRkcmVzcwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEFB190cmFkZXICDkludmFsaWQgY2FsbGVyBAtwb3NpdGlvbkZlZQkBDmdldFBvc2l0aW9uRmVlAQUHX3RyYWRlcgMDAwMDAwkBASEBCQETcmVxdWlyZU9wZW5Qb3NpdGlvbgEFB190cmFkZXIGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAYJAGcCAAAFBV9zaXplBgkAZgIAAAUUX21pblF1b3RlQXNzZXRBbW91bnQGCQEOaXNNYXJrZXRDbG9zZWQACQACAQIgSW52YWxpZCBjbG9zZVBvc2l0aW9uIHBhcmFtZXRlcnMEFG9sZFBvc2l0aW9uVGltZXN0YW1wCAkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgJfNQQNJHQwNzM4MDE3NDM4NgkBFWludGVybmFsQ2xvc2VQb3NpdGlvbgcFB190cmFkZXIFBV9zaXplBQtwb3NpdGlvbkZlZQUUX21pblF1b3RlQXNzZXRBbW91bnQFDF9hZGRUb01hcmdpbgYGBA9uZXdQb3NpdGlvblNpemUIBQ0kdDA3MzgwMTc0Mzg2Al8xBBFuZXdQb3NpdGlvbk1hcmdpbggFDSR0MDczODAxNzQzODYCXzIEF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNzM4MDE3NDM4NgJfMwQUbmV3UG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA3MzgwMTc0Mzg2Al80BA9wb3NpdGlvbkJhZERlYnQIBQ0kdDA3MzgwMTc0Mzg2Al81BAtyZWFsaXplZFBubAgFDSR0MDczODAxNzQzODYCXzYEDm1hcmdpblRvVHJhZGVyCAUNJHQwNzM4MDE3NDM4NgJfNwQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDczODAxNzQzODYCXzgEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDczODAxNzQzODYCXzkEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA3MzgwMTc0Mzg2A18xMAQZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcggFDSR0MDczODAxNzQzODYDXzExBA50b3RhbExvbmdBZnRlcggFDSR0MDczODAxNzQzODYDXzEyBA90b3RhbFNob3J0QWZ0ZXIIBQ0kdDA3MzgwMTc0Mzg2A18xMwQadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA3MzgwMTc0Mzg2A18xNAQbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNzM4MDE3NDM4NgNfMTUEC3JlYWxpemVkRmVlCAUNJHQwNzM4MDE3NDM4NgNfMTYDCQBmAgUPcG9zaXRpb25CYWREZWJ0AAAJAAIBAipJbnZhbGlkIGNsb3NlUG9zaXRpb24gcGFyYW1ldGVyczogYmFkIGRlYnQDCQBnAgUUb2xkUG9zaXRpb25UaW1lc3RhbXAJAQ1sYXN0VGltZXN0YW1wAAkAAgECU0ludmFsaWQgY2xvc2VQb3NpdGlvbiBwYXJhbWV0ZXJzOiB3YWl0IGF0IGxlYXN0IDEgYmxvY2sgYmVmb3JlIGNsb3NpbmcgdGhlIHBvc2l0aW9uBA5pc1BhcnRpYWxDbG9zZQkBAiE9AgUPbmV3UG9zaXRpb25TaXplAAAEDndpdGhkcmF3QW1vdW50CQBkAgUObWFyZ2luVG9UcmFkZXIFC3JlYWxpemVkRmVlBAphbW1CYWxhbmNlCQBlAgkBCGNiYWxhbmNlAAUOd2l0aGRyYXdBbW91bnQEDWFtbU5ld0JhbGFuY2UDCQBmAgAABQphbW1CYWxhbmNlAAAFCmFtbUJhbGFuY2UEB3Vuc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACDndpdGhkcmF3TG9ja2VkCQDMCAIFDndpdGhkcmF3QW1vdW50BQNuaWwFA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlBA0kdDA3NTA1ODc1MTE3CQENZGlzdHJpYnV0ZUZlZQEFC3JlYWxpemVkRmVlBAxmZWVUb1N0YWtlcnMIBQ0kdDA3NTA1ODc1MTE3Al8xBApmZWVUb1ZhdWx0CAUNJHQwNzUwNTg3NTExNwJfMgQMZGVwb3NpdFZhdWx0CQD8BwQJAQx2YXVsdEFkZHJlc3MAAgdhZGRGcmVlBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUKZmVlVG9WYXVsdAUDbmlsAwkAAAIFDGRlcG9zaXRWYXVsdAUMZGVwb3NpdFZhdWx0BAlub3RpZnlGZWUJAPwHBAkBDG1pbmVyQWRkcmVzcwACCm5vdGlmeUZlZXMJAMwIAgUHX3RyYWRlcgkAzAgCBQtyZWFsaXplZEZlZQUDbmlsBQNuaWwDCQAAAgUJbm90aWZ5RmVlBQlub3RpZnlGZWUEDm5vdGlmeU5vdGlvbmFsCQD8BwQJAQxtaW5lckFkZHJlc3MAAg5ub3RpZnlOb3Rpb25hbAkAzAgCBQdfdHJhZGVyCQDMCAIFF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBQNuaWwFA25pbAMJAAACBQ5ub3RpZnlOb3Rpb25hbAUObm90aWZ5Tm90aW9uYWwJAM4IAgkAzggCCQDOCAIJAM4IAgMFDmlzUGFydGlhbENsb3NlCQEOdXBkYXRlUG9zaXRpb24GBQdfdHJhZGVyBQ9uZXdQb3NpdGlvblNpemUFEW5ld1Bvc2l0aW9uTWFyZ2luBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUUbmV3UG9zaXRpb25Mc3RVcGRDUEYJAQ1sYXN0VGltZXN0YW1wAAkBDmRlbGV0ZVBvc2l0aW9uAQUHX3RyYWRlcgkBCXVwZGF0ZUFtbQgFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgUZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcgUOdG90YWxMb25nQWZ0ZXIFD3RvdGFsU2hvcnRBZnRlcgUadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIFG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgMJAGYCBQ5tYXJnaW5Ub1RyYWRlcgAACQEId2l0aGRyYXcCBQ5fdHJhZGVyQWRkcmVzcwUObWFyZ2luVG9UcmFkZXIFA25pbAkBDXVwZGF0ZUJhbGFuY2UBBQ1hbW1OZXdCYWxhbmNlCQELdHJhbnNmZXJGZWUBBQxmZWVUb1N0YWtlcnMJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEJbGlxdWlkYXRlAQdfdHJhZGVyBARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMED3Nwb3RNYXJnaW5SYXRpbwkBFmdldE1hcmdpblJhdGlvQnlPcHRpb24CBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QEFmxpcXVpZGF0aW9uTWFyZ2luUmF0aW8DCQEWaXNPdmVyRmx1Y3R1YXRpb25MaW1pdAAEEW9yYWNsZU1hcmdpblJhdGlvCQEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgIFB190cmFkZXIFEVBOTF9PUFRJT05fT1JBQ0xFCQEEdm1heAIFD3Nwb3RNYXJnaW5SYXRpbwURb3JhY2xlTWFyZ2luUmF0aW8FD3Nwb3RNYXJnaW5SYXRpbwMDAwMDCQEBIQEJARZyZXF1aXJlTW9yZU1hcmdpblJhdGlvAwUWbGlxdWlkYXRpb25NYXJnaW5SYXRpbwkBFm1haW50ZW5hbmNlTWFyZ2luUmF0aW8ABwYJAQEhAQkBE3JlcXVpcmVPcGVuUG9zaXRpb24BBQdfdHJhZGVyBgkBASEBCQELaW5pdGlhbGl6ZWQABgkBBnBhdXNlZAAGCQEOaXNNYXJrZXRDbG9zZWQACQACAQITVW5hYmxlIHRvIGxpcXVpZGF0ZQQUaXNQYXJ0aWFsTGlxdWlkYXRpb24DAwkAZgIFD3Nwb3RNYXJnaW5SYXRpbwkBE2xpcXVpZGF0aW9uRmVlUmF0aW8ACQBmAgkBF3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAAAABwkAZgIFDERFQ0lNQUxfVU5JVAkBF3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAAcED29sZFBvc2l0aW9uU2l6ZQgJAQtnZXRQb3NpdGlvbgEFB190cmFkZXICXzEED3Bvc2l0aW9uU2l6ZUFicwkBA2FicwEFD29sZFBvc2l0aW9uU2l6ZQQNJHQwNzc1Mzg3Nzg2MQMFFGlzUGFydGlhbExpcXVpZGF0aW9uBA9saXF1aWRhdGlvblNpemUJARtnZXRQYXJ0aWFsTGlxdWlkYXRpb25BbW91bnQCBQdfdHJhZGVyBQ9vbGRQb3NpdGlvblNpemUEEGxpcXVpZGF0aW9uUmF0aW8JAQRkaXZkAgkBA2FicwEFD2xpcXVpZGF0aW9uU2l6ZQUPcG9zaXRpb25TaXplQWJzCQCUCgIFEGxpcXVpZGF0aW9uUmF0aW8JAQNhYnMBBQ9saXF1aWRhdGlvblNpemUJAJQKAgAABQ9wb3NpdGlvblNpemVBYnMEEGxpcXVpZGF0aW9uUmF0aW8IBQ0kdDA3NzUzODc3ODYxAl8xBA9saXF1aWRhdGlvblNpemUIBQ0kdDA3NzUzODc3ODYxAl8yBA0kdDA3Nzg2Nzc4NTA1CQEVaW50ZXJuYWxDbG9zZVBvc2l0aW9uBwUHX3RyYWRlcgMFFGlzUGFydGlhbExpcXVpZGF0aW9uBQ9saXF1aWRhdGlvblNpemUFD3Bvc2l0aW9uU2l6ZUFicwkBE2xpcXVpZGF0aW9uRmVlUmF0aW8AAAAGBwYED25ld1Bvc2l0aW9uU2l6ZQgFDSR0MDc3ODY3Nzg1MDUCXzEEEW5ld1Bvc2l0aW9uTWFyZ2luCAUNJHQwNzc4Njc3ODUwNQJfMgQXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA3Nzg2Nzc4NTA1Al8zBBRuZXdQb3NpdGlvbkxzdFVwZENQRggFDSR0MDc3ODY3Nzg1MDUCXzQED3Bvc2l0aW9uQmFkRGVidAgFDSR0MDc3ODY3Nzg1MDUCXzUEC3JlYWxpemVkUG5sCAUNJHQwNzc4Njc3ODUwNQJfNgQObWFyZ2luVG9UcmFkZXIIBQ0kdDA3Nzg2Nzc4NTA1Al83BBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNzc4Njc3ODUwNQJfOAQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNzc4Njc3ODUwNQJfOQQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDc3ODY3Nzg1MDUDXzEwBBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCAUNJHQwNzc4Njc3ODUwNQNfMTEEDnRvdGFsTG9uZ0FmdGVyCAUNJHQwNzc4Njc3ODUwNQNfMTIED3RvdGFsU2hvcnRBZnRlcggFDSR0MDc3ODY3Nzg1MDUDXzEzBBp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDc3ODY3Nzg1MDUDXzE0BBt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA3Nzg2Nzc4NTA1A18xNQQSbGlxdWlkYXRpb25QZW5hbHR5CAUNJHQwNzc4Njc3ODUwNQNfMTYED2ZlZVRvTGlxdWlkYXRvcgkAaQIFEmxpcXVpZGF0aW9uUGVuYWx0eQACBApmZWVUb1ZhdWx0CQBlAgUSbGlxdWlkYXRpb25QZW5hbHR5BQ9mZWVUb0xpcXVpZGF0b3IECmFtbUJhbGFuY2UJAGUCCQEIY2JhbGFuY2UABRJsaXF1aWRhdGlvblBlbmFsdHkEDW5ld0FtbUJhbGFuY2UDCQBmAgAABQphbW1CYWxhbmNlAAAFCmFtbUJhbGFuY2UEC2xvY2tCYWREZWJ0AwkAZgIFD3Bvc2l0aW9uQmFkRGVidAAABAtsb2NrQmFkRGVidAkA/AcECQEMdmF1bHRBZGRyZXNzAAIVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkCQDMCAIJAGQCBQ9wb3NpdGlvbkJhZERlYnQFEmxpcXVpZGF0aW9uUGVuYWx0eQUDbmlsBQNuaWwDCQAAAgULbG9ja0JhZERlYnQFC2xvY2tCYWREZWJ0BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBQtsb2NrQmFkRGVidAULbG9ja0JhZERlYnQEB3Vuc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACDndpdGhkcmF3TG9ja2VkCQDMCAIFEmxpcXVpZGF0aW9uUGVuYWx0eQUDbmlsBQNuaWwDCQAAAgUHdW5zdGFrZQUHdW5zdGFrZQQQZGVwb3NpdEluc3VyYW5jZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIHYWRkRnJlZQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFCmZlZVRvVmF1bHQFA25pbAMJAAACBRBkZXBvc2l0SW5zdXJhbmNlBRBkZXBvc2l0SW5zdXJhbmNlBA5ub3RpZnlOb3Rpb25hbAkA/AcECQEMbWluZXJBZGRyZXNzAAIObm90aWZ5Tm90aW9uYWwJAMwIAgUHX3RyYWRlcgkAzAgCBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUDbmlsBQNuaWwDCQAAAgUObm90aWZ5Tm90aW9uYWwFDm5vdGlmeU5vdGlvbmFsCQDOCAIJAM4IAgkAzggCAwUUaXNQYXJ0aWFsTGlxdWlkYXRpb24JAQ51cGRhdGVQb3NpdGlvbgYFB190cmFkZXIFD25ld1Bvc2l0aW9uU2l6ZQURbmV3UG9zaXRpb25NYXJnaW4FF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBRRuZXdQb3NpdGlvbkxzdFVwZENQRgkBDWxhc3RUaW1lc3RhbXAACQEOZGVsZXRlUG9zaXRpb24BBQdfdHJhZGVyCQEJdXBkYXRlQW1tCAUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyBRp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgUbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCQEId2l0aGRyYXcCCAUBaQZjYWxsZXIFD2ZlZVRvTGlxdWlkYXRvcgkBDXVwZGF0ZUJhbGFuY2UBBQ1uZXdBbW1CYWxhbmNlCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCnBheUZ1bmRpbmcABARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEFWZ1bmRpbmdCbG9ja1RpbWVzdGFtcAkBGW5leHRGdW5kaW5nQmxvY2tUaW1lc3RhbXAAAwMDCQBmAgUVZnVuZGluZ0Jsb2NrVGltZXN0YW1wCQENbGFzdFRpbWVzdGFtcAAGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAkAAgEJAKwCAgkArAICCQCsAgICIUludmFsaWQgZnVuZGluZyBibG9jayB0aW1lc3RhbXA6IAkApAMBCQENbGFzdFRpbWVzdGFtcAACAyA8IAkApAMBBRVmdW5kaW5nQmxvY2tUaW1lc3RhbXAED3VuZGVybHlpbmdQcmljZQkBDmdldE9yYWNsZVByaWNlAAQNJHQwODA2MTg4MDY5NgkBCmdldEZ1bmRpbmcABBRzaG9ydFByZW1pdW1GcmFjdGlvbggFDSR0MDgwNjE4ODA2OTYCXzEEE2xvbmdQcmVtaXVtRnJhY3Rpb24IBQ0kdDA4MDYxODgwNjk2Al8yBA5wcmVtaXVtVG9WYXVsdAgFDSR0MDgwNjE4ODA2OTYCXzMEE2RvUGF5RnVuZGluZ1RvVmF1bHQDCQBmAgUOcHJlbWl1bVRvVmF1bHQAAAQTZG9QYXlGdW5kaW5nVG9WYXVsdAkA/AcECQEMdmF1bHRBZGRyZXNzAAIVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkCQDMCAIJAQEtAQUOcHJlbWl1bVRvVmF1bHQFA25pbAUDbmlsAwkAAAIFE2RvUGF5RnVuZGluZ1RvVmF1bHQFE2RvUGF5RnVuZGluZ1RvVmF1bHQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFE2RvUGF5RnVuZGluZ1RvVmF1bHQFE2RvUGF5RnVuZGluZ1RvVmF1bHQJAQ11cGRhdGVGdW5kaW5nBQkAZAIFFWZ1bmRpbmdCbG9ja1RpbWVzdGFtcAkBFGZ1bmRpbmdQZXJpb2RTZWNvbmRzAAkAZAIJASNsYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAFE2xvbmdQcmVtaXVtRnJhY3Rpb24JAGQCCQEkbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAUUc2hvcnRQcmVtaXVtRnJhY3Rpb24JAQRkaXZkAgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgUPdW5kZXJseWluZ1ByaWNlCQEEZGl2ZAIFFHNob3J0UHJlbWl1bUZyYWN0aW9uBQ91bmRlcmx5aW5nUHJpY2UJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQAEB19xdEFzdFIJAQZxdEFzdFIABAdfYnNBc3RSCQEGYnNBc3RSAAQNJHQwODE3NDc4MjExMwkBFGdldFN5bmNUZXJtaW5hbFByaWNlAwkBDmdldE9yYWNsZVByaWNlAAUHX3F0QXN0UgUHX2JzQXN0UgQTbmV3UXVvdGVBc3NldFdlaWdodAgFDSR0MDgxNzQ3ODIxMTMCXzEEEm5ld0Jhc2VBc3NldFdlaWdodAgFDSR0MDgxNzQ3ODIxMTMCXzIEDW1hcmdpblRvVmF1bHQIBQ0kdDA4MTc0NzgyMTEzAl8zBBBtYXJnaW5Ub1ZhdWx0QWRqAwMJAGYCAAAFDW1hcmdpblRvVmF1bHQJAGYCCQEDYWJzAQUNbWFyZ2luVG9WYXVsdAkBCGNiYWxhbmNlAAcJAQEtAQkBCGNiYWxhbmNlAAUNbWFyZ2luVG9WYXVsdAQNZG9FeGNoYW5nZVBuTAMJAQIhPQIFEG1hcmdpblRvVmF1bHRBZGoAAAQNZG9FeGNoYW5nZVBuTAkA/AcECQEMdmF1bHRBZGRyZXNzAAIVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkCQDMCAIFEG1hcmdpblRvVmF1bHRBZGoFA25pbAUDbmlsAwkAAAIFDWRvRXhjaGFuZ2VQbkwFDWRvRXhjaGFuZ2VQbkwFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFDWRvRXhjaGFuZ2VQbkwFDWRvRXhjaGFuZ2VQbkwJAM4IAgkAzggCCQENdXBkYXRlQmFsYW5jZQEJAGQCCQEIY2JhbGFuY2UABRBtYXJnaW5Ub1ZhdWx0QWRqCQEQdXBkYXRlQW1tV2VpZ2h0cwIFE25ld1F1b3RlQXNzZXRXZWlnaHQFEm5ld0Jhc2VBc3NldFdlaWdodAkBCmFwcGVuZFR3YXABCQEEZGl2ZAIJAQRtdWxkAgUHX3F0QXN0UgUTbmV3UXVvdGVBc3NldFdlaWdodAkBBG11bGQCBQdfYnNBc3RSBRJuZXdCYXNlQXNzZXRXZWlnaHQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEQZW5zdXJlQ2FsbGVkT25jZQADCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAiJJbnZhbGlkIHNhdmVDdXJyZW50VHhJZCBwYXJhbWV0ZXJzBAZsYXN0VHgJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwUIa19sYXN0VHgCAAMJAQIhPQIFBmxhc3RUeAkA2AQBCAUBaQ10cmFuc2FjdGlvbklkCQDMCAIJAQtTdHJpbmdFbnRyeQIFCGtfbGFzdFR4BQZsYXN0VHgFA25pbAkAAgECKUNhbiBub3QgY2FsbCB2QU1NIG1ldGhvZHMgdHdpY2UgaW4gb25lIHR4AWkBJ3ZpZXdfY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudAEHX3RyYWRlcgQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBA0kdDA4Mzc1NTgzODc5CQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBAxwb3NpdGlvblNpemUIBQ0kdDA4Mzc1NTgzODc5Al8xBA5wb3NpdGlvbk1hcmdpbggFDSR0MDgzNzU1ODM4NzkCXzIEA3BvbggFDSR0MDgzNzU1ODM4NzkCXzMEEXBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwODM3NTU4Mzg3OQJfNAQRcG9zaXRpb25UaW1lc3RhbXAIBQ0kdDA4Mzc1NTgzODc5Al81BA0kdDA4Mzg4MjgzOTgzCQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QEEHBvc2l0aW9uTm90aW9uYWwIBQ0kdDA4Mzg4MjgzOTgzAl8xBA11bnJlYWxpemVkUG5sCAUNJHQwODM4ODI4Mzk4MwJfMgQNJHQwODM5ODY4NDIxMAkBMGNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnRBbmRSb2xsb3ZlckZlZQUFDHBvc2l0aW9uU2l6ZQUOcG9zaXRpb25NYXJnaW4FEXBvc2l0aW9uTHN0VXBkQ1BGBRFwb3NpdGlvblRpbWVzdGFtcAUNdW5yZWFsaXplZFBubAQMcmVtYWluTWFyZ2luCAUNJHQwODM5ODY4NDIxMAJfMQQHYmFkRGVidAgFDSR0MDgzOTg2ODQyMTACXzIEDmZ1bmRpbmdQYXltZW50CAUNJHQwODM5ODY4NDIxMAJfMwQLcm9sbG92ZXJGZWUIBQ0kdDA4Mzk4Njg0MjEwAl80CQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkBAXMBBQxyZW1haW5NYXJnaW4JAQFzAQUOZnVuZGluZ1BheW1lbnQJAQFzAQkBDmdldE1hcmdpblJhdGlvAQUHX3RyYWRlcgkBAXMBBQ11bnJlYWxpemVkUG5sCQEBcwEFB2JhZERlYnQJAQFzAQUQcG9zaXRpb25Ob3Rpb25hbAkBAXMBBQtyb2xsb3ZlckZlZQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARV2aWV3X2dldFBlZ0FkanVzdENvc3QBBl9wcmljZQQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABAZyZXN1bHQJARRnZXRTeW5jVGVybWluYWxQcmljZQMFBl9wcmljZQUHX3F0QXN0UgUHX2JzQXN0UgkAAgEJAKQDAQgFBnJlc3VsdAJfMwFpARh2aWV3X2dldFRlcm1pbmFsQW1tUHJpY2UABA0kdDA4NDkzMzg1MDE0CQETZ2V0VGVybWluYWxBbW1TdGF0ZQAEGXRlcm1pbmFsUXVvdGVBc3NldFJlc2VydmUIBQ0kdDA4NDkzMzg1MDE0Al8xBBh0ZXJtaW5hbEJhc2VBc3NldFJlc2VydmUIBQ0kdDA4NDkzMzg1MDE0Al8yBAVwcmljZQkBBGRpdmQCCQEEbXVsZAIFGXRlcm1pbmFsUXVvdGVBc3NldFJlc2VydmUJAQZxdEFzdFcACQEEbXVsZAIFGHRlcm1pbmFsQmFzZUFzc2V0UmVzZXJ2ZQkBBmJzQXN0VwAJAAIBCQCkAwEFBXByaWNlAWkBD3ZpZXdfZ2V0RnVuZGluZwAED3VuZGVybHlpbmdQcmljZQkBDmdldE9yYWNsZVByaWNlAAQNJHQwODU1MjM4NTYwMQkBCmdldEZ1bmRpbmcABBRzaG9ydFByZW1pdW1GcmFjdGlvbggFDSR0MDg1NTIzODU2MDECXzEEE2xvbmdQcmVtaXVtRnJhY3Rpb24IBQ0kdDA4NTUyMzg1NjAxAl8yBA5wcmVtaXVtVG9WYXVsdAgFDSR0MDg1NTIzODU2MDECXzMEC2xvbmdGdW5kaW5nCQEEZGl2ZAIFE2xvbmdQcmVtaXVtRnJhY3Rpb24FD3VuZGVybHlpbmdQcmljZQQMc2hvcnRGdW5kaW5nCQEEZGl2ZAIFFHNob3J0UHJlbWl1bUZyYWN0aW9uBQ91bmRlcmx5aW5nUHJpY2UJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAQFzAQULbG9uZ0Z1bmRpbmcJAQFzAQUMc2hvcnRGdW5kaW5nCQEBcwEJARBnZXRUd2FwU3BvdFByaWNlAAkBAXMBCQEOZ2V0T3JhY2xlUHJpY2UACQEBcwEFDnByZW1pdW1Ub1ZhdWx0AWkBEGNvbXB1dGVTcG90UHJpY2UABARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEBnJlc3VsdAkBDGdldFNwb3RQcmljZQAJAJQKAgUDbmlsBQZyZXN1bHQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEfY29tcHV0ZUZlZUZvclRyYWRlcldpdGhBcnRpZmFjdAIHX3RyYWRlcgtfYXJ0aWZhY3RJZAQGcmVzdWx0CQEYZ2V0Rm9yVHJhZGVyV2l0aEFydGlmYWN0AgUHX3RyYWRlcgULX2FydGlmYWN0SWQJAJQKAgUDbmlsBQZyZXN1bHQBAnR4AQZ2ZXJpZnkABA5jb29yZGluYXRvclN0cgkAnQgCBQR0aGlzBRRrX2Nvb3JkaW5hdG9yQWRkcmVzcwMJAQlpc0RlZmluZWQBBQ5jb29yZGluYXRvclN0cgQFYWRtaW4JAJ0IAgkBEUBleHRyTmF0aXZlKDEwNjIpAQkBBXZhbHVlAQUOY29vcmRpbmF0b3JTdHIFD2tfYWRtaW5fYWRkcmVzcwMJAQlpc0RlZmluZWQBBQVhZG1pbgkBC3ZhbHVlT3JFbHNlAgkAmwgCCQERQGV4dHJOYXRpdmUoMTA2MikBCQEFdmFsdWUBBQVhZG1pbgkArAICCQCsAgIJAKwCAgIHc3RhdHVzXwkApQgBBQR0aGlzAgFfCQDYBAEIBQJ0eAJpZAcJAAIBAi51bmFibGUgdG8gdmVyaWZ5OiBhZG1pbiBub3Qgc2V0IGluIGNvb3JkaW5hdG9yCQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwAACAUCdHgPc2VuZGVyUHVibGljS2V5SQEktA==", "height": 2450982, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: DFBTvyspz39zgYeE2ywPeUWyC4yHf2dfcee1Q5yG9vLH Next: J3LsNexS9DQqNrKQLHVSu4Qv8raN2bYPZhgHbASwZoAy Diff:
OldNewDifferences
5656 let k_feeToStakersPercent = "k_feeToStakersPercent"
5757
5858 let k_maxOracleDelay = "k_maxOracleDelay"
59+
60+let k_fundingMode = "k_fundingMode"
5961
6062 let k_lastDataStr = "k_lastDataStr"
6163
179181 let PNL_OPTION_SPOT = 1
180182
181183 let PNL_OPTION_ORACLE = 2
184+
185+let FUNDING_ASYMMETRIC = 1
186+
187+let FUNDING_SYMMETRIC = 2
182188
183189 func s (_x) = (toString(_x) + ",")
184190
328334 func maxOracleDelay () = int(k_maxOracleDelay)
329335
330336
337+func fundingMode () = intOr(k_fundingMode, FUNDING_ASYMMETRIC)
338+
339+
331340 func lastTimestamp () = lastBlock.timestamp
332341
333342
456465 let amountBaseAssetBought = if (_isAdd)
457466 then amountBaseAssetBoughtAbs
458467 else -(amountBaseAssetBoughtAbs)
459- let $t01672216892 = updateReserve(_isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
460- let quoteAssetReserveAfter1 = $t01672216892._1
461- let baseAssetReserveAfter1 = $t01672216892._2
462- let totalPositionSizeAfter1 = $t01672216892._3
468+ let $t01694317113 = updateReserve(_isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
469+ let quoteAssetReserveAfter1 = $t01694317113._1
470+ let baseAssetReserveAfter1 = $t01694317113._2
471+ let totalPositionSizeAfter1 = $t01694317113._3
463472 let priceBefore = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
464473 let marketPrice = divd(_quoteAssetAmount, amountBaseAssetBoughtAbs)
465474 let priceDiff = abs((priceBefore - marketPrice))
487496 else 0
488497 let rolloverFee = calcRolloverFee(_oldPositionMargin, _oldPositionLastUpdatedTimestamp)
489498 let signedMargin = (((_marginDelta - rolloverFee) - fundingPayment) + _oldPositionMargin)
490- let $t01914719274 = if ((0 > signedMargin))
499+ let $t01936819495 = if ((0 > signedMargin))
491500 then $Tuple2(0, abs(signedMargin))
492501 else $Tuple2(abs(signedMargin), 0)
493- let remainMargin = $t01914719274._1
494- let badDebt = $t01914719274._2
502+ let remainMargin = $t01936819495._1
503+ let badDebt = $t01936819495._2
495504 $Tuple4(remainMargin, badDebt, fundingPayment, rolloverFee)
496505 }
497506
509518 let quoteAssetDelta = abs((quoteAssetAfter - _quoteAssetReserve))
510519 let quoteAssetSold = muld(quoteAssetDelta, _quoteAssetWeight)
511520 let maxPriceImpactValue = maxPriceImpact()
512- let $t02053620698 = updateReserve(!(_isAdd), quoteAssetDelta, _baseAssetAmount)
513- let quoteAssetReserveAfter1 = $t02053620698._1
514- let baseAssetReserveAfter1 = $t02053620698._2
515- let totalPositionSizeAfter1 = $t02053620698._3
521+ let $t02075720919 = updateReserve(!(_isAdd), quoteAssetDelta, _baseAssetAmount)
522+ let quoteAssetReserveAfter1 = $t02075720919._1
523+ let baseAssetReserveAfter1 = $t02075720919._2
524+ let totalPositionSizeAfter1 = $t02075720919._3
516525 let marketPrice = divd(quoteAssetSold, _baseAssetAmount)
517526 let priceDiff = abs((priceBefore - marketPrice))
518527 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
647656
648657
649658 func getPositionNotionalAndUnrealizedPnl (_trader,_option) = {
650- let $t02857628704 = getPosition(_trader)
651- let positionSize = $t02857628704._1
652- let positionMargin = $t02857628704._2
653- let positionOpenNotional = $t02857628704._3
654- let positionLstUpdCPF = $t02857628704._4
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
655664 getPositionNotionalAndUnrealizedPnlByValues(positionSize, positionOpenNotional, qtAstR(), qtAstW(), bsAstR(), bsAstW(), _option)
656665 }
657666
660669
661670
662671 func getMarginRatioByOption (_trader,_option) = {
663- let $t02921929360 = getPosition(_trader)
664- let positionSize = $t02921929360._1
665- let positionMargin = $t02921929360._2
666- let pon = $t02921929360._3
667- let positionLastUpdatedCPF = $t02921929360._4
668- let positionTimestamp = $t02921929360._5
669- let $t02936629459 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
670- let positionNotional = $t02936629459._1
671- let unrealizedPnl = $t02936629459._2
672- let $t02946429676 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLastUpdatedCPF, positionTimestamp, unrealizedPnl)
673- let remainMargin = $t02946429676._1
674- let badDebt = $t02946429676._2
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
675684 calcMarginRatio(remainMargin, badDebt, positionNotional)
676685 }
677686
692701
693702
694703 func internalClosePosition (_trader,_size,_fee,_minQuoteAssetAmount,_addToMargin,_checkMaxPriceImpact,_liquidate) = {
695- let $t03074330899 = getPosition(_trader)
696- let oldPositionSize = $t03074330899._1
697- let oldPositionMargin = $t03074330899._2
698- let oldPositionOpenNotional = $t03074330899._3
699- let oldPositionLstUpdCPF = $t03074330899._4
700- let oldPositionTimestamp = $t03074330899._5
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
701710 let isLongPosition = (oldPositionSize > 0)
702711 let absOldPositionSize = abs(oldPositionSize)
703712 if (if ((absOldPositionSize >= _size))
705714 else false)
706715 then {
707716 let isPartialClose = (absOldPositionSize > _size)
708- let $t03119131642 = swapOutput((oldPositionSize > 0), _size, _checkMaxPriceImpact)
709- let exchangedQuoteAssetAmount = $t03119131642._1
710- let quoteAssetReserveAfter = $t03119131642._2
711- let baseAssetReserveAfter = $t03119131642._3
712- let totalPositionSizeAfter = $t03119131642._4
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
713722 let exchangedPositionSize = if ((oldPositionSize > 0))
714723 then -(_size)
715724 else _size
716- let $t03185732064 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
717- let oldPositionNotional = $t03185732064._1
718- let unrealizedPnl = $t03185732064._2
725+ let $t03207832285 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
726+ let oldPositionNotional = $t03207832285._1
727+ let unrealizedPnl = $t03207832285._2
719728 let realizedRatio = divd(abs(exchangedPositionSize), absOldPositionSize)
720729 let realizedPnl = muld(unrealizedPnl, realizedRatio)
721- let $t03240532651 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, unrealizedPnl)
722- let remainMarginBefore = $t03240532651._1
723- let x1 = $t03240532651._2
724- let x2 = $t03240532651._3
725- let rolloverFee = $t03240532651._4
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
726735 let positionBadDebt = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, realizedPnl)._2
727736 let realizedCloseFee = muld(muld(oldPositionNotional, realizedRatio), _fee)
728737 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
730739 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
731740 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
732741 let newPositionSize = (oldPositionSize + exchangedPositionSize)
733- let $t03405734443 = if ((newPositionSize == 0))
742+ let $t03427834664 = if ((newPositionSize == 0))
734743 then $Tuple2(0, 0)
735744 else $Tuple2(abs(remainOpenNotional), latestCumulativePremiumFraction(newPositionSize))
736- let newPositionOpenNotional = $t03405734443._1
737- let newPositionLstUpdCPF = $t03405734443._2
745+ let newPositionOpenNotional = $t03427834664._1
746+ let newPositionLstUpdCPF = $t03427834664._2
738747 let openNotionalDelta = (oldPositionOpenNotional - newPositionOpenNotional)
739748 let marginRatio = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
740749 let newPositionMarginWithSameRatio = if ((oldPositionSize > 0))
814823 then $Tuple2(qtAstR(), bsAstR())
815824 else {
816825 let direction = (_positionSize > 0)
817- let $t03918039359 = swapOutput(direction, abs(_positionSize), false)
818- let currentNetMarketValue = $t03918039359._1
819- let terminalQuoteAssetReserve = $t03918039359._2
820- let terminalBaseAssetReserve = $t03918039359._3
826+ let $t03940139580 = swapOutput(direction, abs(_positionSize), false)
827+ let currentNetMarketValue = $t03940139580._1
828+ let terminalQuoteAssetReserve = $t03940139580._2
829+ let terminalBaseAssetReserve = $t03940139580._3
821830 $Tuple2(terminalQuoteAssetReserve, terminalBaseAssetReserve)
822831 }
823832 }
864873 else (totalLongPositionSize() == 0))
865874 then true
866875 else isMarketClosed())
867- then $Tuple2(0, 0)
876+ then $Tuple3(0, 0, 0)
868877 else if ((0 > premium))
869878 then {
870879 let shortPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
871- let longPremiumFraction = divd(muld(shortPremiumFraction, totalShortPositionSize()), totalLongPositionSize())
872- $Tuple2(shortPremiumFraction, longPremiumFraction)
880+ if ((fundingMode() == FUNDING_ASYMMETRIC))
881+ then {
882+ let longPremiumFraction = divd(muld(shortPremiumFraction, totalShortPositionSize()), totalLongPositionSize())
883+ $Tuple3(shortPremiumFraction, longPremiumFraction, 0)
884+ }
885+ else {
886+ let shortTotalPremiumFraction = abs(muld(shortPremiumFraction, totalShortPositionSize()))
887+ let longTotalPremiumFraction = abs(muld(shortPremiumFraction, totalLongPositionSize()))
888+ let premiumToVault = (shortTotalPremiumFraction - longTotalPremiumFraction)
889+ $Tuple3(shortPremiumFraction, shortPremiumFraction, premiumToVault)
890+ }
873891 }
874892 else {
875893 let longPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
876- let shortPremiumFraction = divd(muld(longPremiumFraction, totalLongPositionSize()), totalShortPositionSize())
877- $Tuple2(shortPremiumFraction, longPremiumFraction)
894+ if ((fundingMode() == FUNDING_ASYMMETRIC))
895+ then {
896+ let shortPremiumFraction = divd(muld(longPremiumFraction, totalLongPositionSize()), totalShortPositionSize())
897+ $Tuple3(shortPremiumFraction, longPremiumFraction, 0)
898+ }
899+ else {
900+ let longTotalPremiumFraction = abs(muld(longPremiumFraction, totalLongPositionSize()))
901+ let shortTotalPremiumFraction = abs(muld(longPremiumFraction, totalShortPositionSize()))
902+ let premiumToVault = (longTotalPremiumFraction - shortTotalPremiumFraction)
903+ $Tuple3(longPremiumFraction, longPremiumFraction, premiumToVault)
904+ }
878905 }
879906 }
880907
882909 func getAdjustedFee (_artifactId,_baseFeeDiscount) = {
883910 let baseFeeRaw = fee()
884911 let baseFee = muld(baseFeeRaw, _baseFeeDiscount)
885- let $t04222042715 = if ((_artifactId != ""))
912+ let $t04332643821 = if ((_artifactId != ""))
886913 then {
887914 let artifactKind = strA(nftManagerAddress(), toCompositeKey(k_token_type, _artifactId))
888915 if ((artifactKind == FEE_REDUCTION_TOKEN_TYPE))
894921 else throw("Invalid attached artifact")
895922 }
896923 else $Tuple2(baseFee, false)
897- let adjustedFee = $t04222042715._1
898- let burnArtifact = $t04222042715._2
924+ let adjustedFee = $t04332643821._1
925+ let burnArtifact = $t04332643821._2
899926 $Tuple2(adjustedFee, burnArtifact)
900927 }
901928
921948 case _ =>
922949 throw("Invalid computeFeeDiscount result")
923950 }
924- let $t04339543469 = getAdjustedFee(_artifactId, feeDiscount)
925- let adjustedFee = $t04339543469._1
926- let burnArtifact = $t04339543469._2
951+ let $t04450144575 = getAdjustedFee(_artifactId, feeDiscount)
952+ let adjustedFee = $t04450144575._1
953+ let burnArtifact = $t04450144575._2
927954 $Tuple2(adjustedFee, burnArtifact)
928955 }
929956 else throw("Strict value is not equal to itself.")
945972 }
946973
947974
948-func updateSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay,_rolloverFee) = [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)]
975+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)]
949976
950977
951978 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)]
10761103 let qtAstRAfter = (_qtAstR + _quoteAssetAmount)
10771104 let baseAssetAmountToAdd = (divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR)
10781105 let bsAstRAfter = (_bsAstR + baseAssetAmountToAdd)
1079- let $t05287653027 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1080- let newQuoteAssetWeight = $t05287653027._1
1081- let newBaseAssetWeight = $t05287653027._2
1082- let marginToVault = $t05287653027._3
1106+ let $t05479454945 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1107+ let newQuoteAssetWeight = $t05479454945._1
1108+ let newBaseAssetWeight = $t05479454945._2
1109+ let marginToVault = $t05479454945._3
10831110 let doExchangePnL = if ((marginToVault != 0))
10841111 then {
10851112 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
11091136 let qtAstRAfter = (_qtAstR - _quoteAssetAmount)
11101137 let baseAssetAmountToRemove = abs((divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR))
11111138 let bsAstRAfter = (_bsAstR - baseAssetAmountToRemove)
1112- let $t05395954110 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1113- let newQuoteAssetWeight = $t05395954110._1
1114- let newBaseAssetWeight = $t05395954110._2
1115- let marginToVault = $t05395954110._3
1139+ let $t05604156192 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1140+ let newQuoteAssetWeight = $t05604156192._1
1141+ let newBaseAssetWeight = $t05604156192._2
1142+ let marginToVault = $t05604156192._3
11161143 let doExchangePnL = if ((marginToVault != 0))
11171144 then {
11181145 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
11291156
11301157
11311158 @Callable(i)
1132-func changeSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay,_rolloverFee) = if ((i.caller != adminAddress()))
1159+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))
1160+ then true
1161+ else (0 >= _initMarginRatio))
1162+ then true
1163+ else (0 >= _mmr))
1164+ then true
1165+ else (0 >= _liquidationFeeRatio))
1166+ then true
1167+ else (0 >= _fee))
1168+ then true
1169+ else (0 >= _spreadLimit))
1170+ then true
1171+ else (0 >= _maxPriceImpact))
1172+ then true
1173+ else (0 >= _partialLiquidationRatio))
1174+ then true
1175+ else (0 >= _maxPriceSpread))
1176+ then true
1177+ else (0 >= _maxOpenNotional))
1178+ then true
1179+ else (0 >= _feeToStakersPercent))
1180+ then true
1181+ else (_feeToStakersPercent > DECIMAL_UNIT))
1182+ then true
1183+ else (0 >= _maxOracleDelay))
1184+ then true
1185+ else (0 >= _rolloverFee))
1186+ then true
1187+ else if ((_fundingMode != FUNDING_SYMMETRIC))
1188+ then (_fundingMode != FUNDING_ASYMMETRIC)
1189+ else false)
1190+ then true
1191+ else !(initialized()))
1192+ then true
1193+ else (i.caller != adminAddress()))
11331194 then throw("Invalid changeSettings params")
1134- else updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact, _partialLiquidationRatio, _maxPriceSpread, _maxOpenNotional, _feeToStakersPercent, _maxOracleDelay, _rolloverFee)
1195+ else updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact, _partialLiquidationRatio, _maxPriceSpread, _maxOpenNotional, _feeToStakersPercent, _maxOracleDelay, _rolloverFee, _fundingMode)
11351196
11361197
11371198
11381199 @Callable(i)
1139-func initialize (_qtAstR,_bsAstR,_fundingPeriod,_initMarginRatio,_mmr,_liquidationFeeRatio,_fee,_baseOracleData,_quoteOracleData,_coordinator,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay,_rolloverFee) = if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if ((0 >= _qtAstR))
1200+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))
11401201 then true
11411202 else (0 >= _bsAstR))
11421203 then true
11681229 then true
11691230 else (0 >= _rolloverFee))
11701231 then true
1232+ else if ((_fundingMode != FUNDING_SYMMETRIC))
1233+ then (_fundingMode != FUNDING_ASYMMETRIC)
1234+ else false)
1235+ then true
11711236 else initialized())
11721237 then true
11731238 else (i.caller != this))
11741239 then throw("Invalid initialize parameters")
1175- else ((((updateAmm(_qtAstR, _bsAstR, 0, 0, 0, 0, 0, 0) ++ updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact, _partialLiquidationRatio, _maxPriceSpread, _maxOpenNotional, _feeToStakersPercent, _maxOracleDelay, _rolloverFee)) ++ 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)))])
1240+ 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)))])
11761241
11771242
11781243
12101275 else isMarketClosed())
12111276 then throw("Invalid increasePosition parameters")
12121277 else {
1213- let $t05788858037 = getForTraderWithArtifact(_trader, getArtifactId(i))
1214- let adjustedFee = $t05788858037._1
1215- let burnArtifact = $t05788858037._2
1278+ let $t06231662465 = getForTraderWithArtifact(_trader, getArtifactId(i))
1279+ let adjustedFee = $t06231662465._1
1280+ let burnArtifact = $t06231662465._2
12161281 let _amount = divd(_rawAmount, (muld(adjustedFee, _leverage) + DECIMAL_UNIT))
12171282 let distributeFeeAmount = (_rawAmount - _amount)
12181283 let referrerFeeAny = invoke(referralAddress(), "acceptPaymentWithLink", [_trader, _refLink], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
12251290 throw("Invalid referrerFee")
12261291 }
12271292 let feeAmount = (distributeFeeAmount - referrerFee)
1228- let $t05853358701 = getPosition(_trader)
1229- let oldPositionSize = $t05853358701._1
1230- let oldPositionMargin = $t05853358701._2
1231- let oldPositionOpenNotional = $t05853358701._3
1232- let oldPositionLstUpdCPF = $t05853358701._4
1233- let oldPositionTimestamp = $t05853358701._5
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
12341299 let isNewPosition = (oldPositionSize == 0)
12351300 let isSameDirection = if ((oldPositionSize > 0))
12361301 then (_direction == DIR_LONG)
12391304 then isSameDirection
12401305 else false
12411306 let isAdd = (_direction == DIR_LONG)
1242- let $t05899062111 = if (if (isNewPosition)
1307+ let $t06341866539 = if (if (isNewPosition)
12431308 then true
12441309 else expandExisting)
12451310 then {
12461311 let openNotional = muld(_amount, _leverage)
1247- let $t05949959672 = swapInput(isAdd, openNotional)
1248- let amountBaseAssetBought = $t05949959672._1
1249- let quoteAssetReserveAfter = $t05949959672._2
1250- let baseAssetReserveAfter = $t05949959672._3
1251- let totalPositionSizeAfter = $t05949959672._4
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
12521317 if (if ((_minBaseAssetAmount != 0))
12531318 then (_minBaseAssetAmount > abs(amountBaseAssetBought))
12541319 else false)
12611326 let totalShortOpenInterestAfter = (openInterestShort() + (if ((0 > newPositionSize))
12621327 then openNotional
12631328 else 0))
1264- let $t06021860493 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, _amount)
1265- let remainMargin = $t06021860493._1
1266- let x1 = $t06021860493._2
1267- let x2 = $t06021860493._3
1268- let rolloverFee = $t06021860493._4
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
12691334 if (!(requireNotOverSpreadLimit(quoteAssetReserveAfter, baseAssetReserveAfter)))
12701335 then throw("Over max spread limit")
12711336 else if (!(requireNotOverMaxOpenNotional(totalLongOpenInterestAfter, totalShortOpenInterestAfter)))
12791344 }
12801345 else {
12811346 let openNotional = muld(_amount, _leverage)
1282- let $t06181161927 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1283- let oldPositionNotional = $t06181161927._1
1284- let unrealizedPnl = $t06181161927._2
1347+ let $t06623966355 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1348+ let oldPositionNotional = $t06623966355._1
1349+ let unrealizedPnl = $t06623966355._2
12851350 if ((oldPositionNotional > openNotional))
12861351 then throw("Use decreasePosition to decrease position size")
12871352 else throw("Close position first")
12881353 }
1289- let newPositionSize = $t05899062111._1
1290- let newPositionRemainMargin = $t05899062111._2
1291- let newPositionOpenNotional = $t05899062111._3
1292- let newPositionLatestCPF = $t05899062111._4
1293- let newPositionTimestamp = $t05899062111._5
1294- let baseAssetReserveAfter = $t05899062111._6
1295- let quoteAssetReserveAfter = $t05899062111._7
1296- let totalPositionSizeAfter = $t05899062111._8
1297- let openInterestNotionalAfter = $t05899062111._9
1298- let totalLongAfter = $t05899062111._10
1299- let totalShortAfter = $t05899062111._11
1300- let totalLongOpenInterestAfter = $t05899062111._12
1301- let totalShortOpenInterestAfter = $t05899062111._13
1302- let rolloverFee = $t05899062111._14
1303- let $t06211762188 = distributeFee((feeAmount + rolloverFee))
1304- let feeToStakers = $t06211762188._1
1305- let feeToVault = $t06211762188._2
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
13061371 let stake = if ((_amount >= rolloverFee))
13071372 then invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), (_amount - rolloverFee))])
13081373 else invoke(vaultAddress(), "withdrawLocked", [(rolloverFee - _amount)], nil)
13631428 else isMarketClosed())
13641429 then throw("Invalid addMargin parameters")
13651430 else {
1366- let $t06429964467 = getPosition(_trader)
1367- let oldPositionSize = $t06429964467._1
1368- let oldPositionMargin = $t06429964467._2
1369- let oldPositionOpenNotional = $t06429964467._3
1370- let oldPositionLstUpdCPF = $t06429964467._4
1371- let oldPositionTimestamp = $t06429964467._5
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
13721437 let stake = invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), _amount)])
13731438 if ((stake == stake))
13741439 then {
13751440 let rolloverFee = calcRolloverFee(oldPositionMargin, oldPositionTimestamp)
13761441 let doTransferFeeToStakers = if ((rolloverFee > 0))
13771442 then {
1378- let $t06475264811 = distributeFee(rolloverFee)
1379- let feeToStakers = $t06475264811._1
1380- let feeToVault = $t06475264811._2
1443+ let $t06932669385 = distributeFee(rolloverFee)
1444+ let feeToStakers = $t06932669385._1
1445+ let feeToVault = $t06932669385._2
13811446 let unstake = invoke(vaultAddress(), "withdrawLocked", [feeToStakers], nil)
13821447 if ((unstake == unstake))
13831448 then {
14231488 else isMarketClosed())
14241489 then throw("Invalid removeMargin parameters")
14251490 else {
1426- let $t06592366091 = getPosition(_trader)
1427- let oldPositionSize = $t06592366091._1
1428- let oldPositionMargin = $t06592366091._2
1429- let oldPositionOpenNotional = $t06592366091._3
1430- let oldPositionLstUpdCPF = $t06592366091._4
1431- let oldPositionTimestamp = $t06592366091._5
1432- let $t06609766346 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, -(_amount))
1433- let remainMargin = $t06609766346._1
1434- let badDebt = $t06609766346._2
1435- let fundingPayment = $t06609766346._3
1436- let rolloverFee = $t06609766346._4
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
14371502 if ((badDebt != 0))
14381503 then throw("Invalid removed margin amount")
14391504 else {
14411506 if (!(requireMoreMarginRatio(marginRatio, initMarginRatio(), true)))
14421507 then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
14431508 else {
1444- let $t06673266791 = distributeFee(rolloverFee)
1445- let feeToStakers = $t06673266791._1
1446- let feeToVault = $t06673266791._2
1509+ let $t07156771626 = distributeFee(rolloverFee)
1510+ let feeToStakers = $t07156771626._1
1511+ let feeToVault = $t07156771626._2
14471512 let doTransferFeeToStakers = if ((rolloverFee > 0))
14481513 then {
14491514 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(feeToVault)], nil)
14961561 then throw("Invalid closePosition parameters")
14971562 else {
14981563 let oldPositionTimestamp = getPosition(_trader)._5
1499- let $t06844869033 = internalClosePosition(_trader, _size, positionFee, _minQuoteAssetAmount, _addToMargin, true, true)
1500- let newPositionSize = $t06844869033._1
1501- let newPositionMargin = $t06844869033._2
1502- let newPositionOpenNotional = $t06844869033._3
1503- let newPositionLstUpdCPF = $t06844869033._4
1504- let positionBadDebt = $t06844869033._5
1505- let realizedPnl = $t06844869033._6
1506- let marginToTrader = $t06844869033._7
1507- let quoteAssetReserveAfter = $t06844869033._8
1508- let baseAssetReserveAfter = $t06844869033._9
1509- let totalPositionSizeAfter = $t06844869033._10
1510- let openInterestNotionalAfter = $t06844869033._11
1511- let totalLongAfter = $t06844869033._12
1512- let totalShortAfter = $t06844869033._13
1513- let totalLongOpenInterestAfter = $t06844869033._14
1514- let totalShortOpenInterestAfter = $t06844869033._15
1515- let realizedFee = $t06844869033._16
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
15161581 if ((positionBadDebt > 0))
15171582 then throw("Invalid closePosition parameters: bad debt")
15181583 else if ((oldPositionTimestamp >= lastTimestamp()))
15271592 let unstake = invoke(vaultAddress(), "withdrawLocked", [withdrawAmount], nil)
15281593 if ((unstake == unstake))
15291594 then {
1530- let $t06970569764 = distributeFee(realizedFee)
1531- let feeToStakers = $t06970569764._1
1532- let feeToVault = $t06970569764._2
1595+ let $t07505875117 = distributeFee(realizedFee)
1596+ let feeToStakers = $t07505875117._1
1597+ let feeToVault = $t07505875117._2
15331598 let depositVault = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
15341599 if ((depositVault == depositVault))
15351600 then {
15901655 else false
15911656 let oldPositionSize = getPosition(_trader)._1
15921657 let positionSizeAbs = abs(oldPositionSize)
1593- let $t07207772400 = if (isPartialLiquidation)
1658+ let $t07753877861 = if (isPartialLiquidation)
15941659 then {
15951660 let liquidationSize = getPartialLiquidationAmount(_trader, oldPositionSize)
15961661 let liquidationRatio = divd(abs(liquidationSize), positionSizeAbs)
15971662 $Tuple2(liquidationRatio, abs(liquidationSize))
15981663 }
15991664 else $Tuple2(0, positionSizeAbs)
1600- let liquidationRatio = $t07207772400._1
1601- let liquidationSize = $t07207772400._2
1602- let $t07240673044 = internalClosePosition(_trader, if (isPartialLiquidation)
1665+ let liquidationRatio = $t07753877861._1
1666+ let liquidationSize = $t07753877861._2
1667+ let $t07786778505 = internalClosePosition(_trader, if (isPartialLiquidation)
16031668 then liquidationSize
16041669 else positionSizeAbs, liquidationFeeRatio(), 0, true, false, true)
1605- let newPositionSize = $t07240673044._1
1606- let newPositionMargin = $t07240673044._2
1607- let newPositionOpenNotional = $t07240673044._3
1608- let newPositionLstUpdCPF = $t07240673044._4
1609- let positionBadDebt = $t07240673044._5
1610- let realizedPnl = $t07240673044._6
1611- let marginToTrader = $t07240673044._7
1612- let quoteAssetReserveAfter = $t07240673044._8
1613- let baseAssetReserveAfter = $t07240673044._9
1614- let totalPositionSizeAfter = $t07240673044._10
1615- let openInterestNotionalAfter = $t07240673044._11
1616- let totalLongAfter = $t07240673044._12
1617- let totalShortAfter = $t07240673044._13
1618- let totalLongOpenInterestAfter = $t07240673044._14
1619- let totalShortOpenInterestAfter = $t07240673044._15
1620- let liquidationPenalty = $t07240673044._16
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
16211686 let feeToLiquidator = (liquidationPenalty / 2)
16221687 let feeToVault = (liquidationPenalty - feeToLiquidator)
16231688 let ammBalance = (cbalance() - liquidationPenalty)
16731738 then throw(((("Invalid funding block timestamp: " + toString(lastTimestamp())) + " < ") + toString(fundingBlockTimestamp)))
16741739 else {
16751740 let underlyingPrice = getOraclePrice()
1676- let $t07503175093 = getFunding()
1677- let shortPremiumFraction = $t07503175093._1
1678- let longPremiumFraction = $t07503175093._2
1679- updateFunding((fundingBlockTimestamp + fundingPeriodSeconds()), (latestLongCumulativePremiumFraction() + longPremiumFraction), (latestShortCumulativePremiumFraction() + shortPremiumFraction), divd(longPremiumFraction, underlyingPrice), divd(shortPremiumFraction, underlyingPrice))
1741+ let $t08061880696 = getFunding()
1742+ let shortPremiumFraction = $t08061880696._1
1743+ let longPremiumFraction = $t08061880696._2
1744+ let premiumToVault = $t08061880696._3
1745+ let doPayFundingToVault = if ((premiumToVault > 0))
1746+ then {
1747+ let doPayFundingToVault = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(premiumToVault)], nil)
1748+ if ((doPayFundingToVault == doPayFundingToVault))
1749+ then nil
1750+ else throw("Strict value is not equal to itself.")
1751+ }
1752+ else nil
1753+ if ((doPayFundingToVault == doPayFundingToVault))
1754+ then updateFunding((fundingBlockTimestamp + fundingPeriodSeconds()), (latestLongCumulativePremiumFraction() + longPremiumFraction), (latestShortCumulativePremiumFraction() + shortPremiumFraction), divd(longPremiumFraction, underlyingPrice), divd(shortPremiumFraction, underlyingPrice))
1755+ else throw("Strict value is not equal to itself.")
16801756 }
16811757 }
16821758 else throw("Strict value is not equal to itself.")
16881764 func syncTerminalPriceToOracle () = {
16891765 let _qtAstR = qtAstR()
16901766 let _bsAstR = bsAstR()
1691- let $t07552575891 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1692- let newQuoteAssetWeight = $t07552575891._1
1693- let newBaseAssetWeight = $t07552575891._2
1694- let marginToVault = $t07552575891._3
1767+ let $t08174782113 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1768+ let newQuoteAssetWeight = $t08174782113._1
1769+ let newBaseAssetWeight = $t08174782113._2
1770+ let marginToVault = $t08174782113._3
16951771 let marginToVaultAdj = if (if ((0 > marginToVault))
16961772 then (abs(marginToVault) > cbalance())
16971773 else false)
17291805 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
17301806 if ((sync == sync))
17311807 then {
1732- let $t07705077174 = getPosition(_trader)
1733- let positionSize = $t07705077174._1
1734- let positionMargin = $t07705077174._2
1735- let pon = $t07705077174._3
1736- let positionLstUpdCPF = $t07705077174._4
1737- let positionTimestamp = $t07705077174._5
1738- let $t07717777278 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1739- let positionNotional = $t07717777278._1
1740- let unrealizedPnl = $t07717777278._2
1741- let $t07728177505 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLstUpdCPF, positionTimestamp, unrealizedPnl)
1742- let remainMargin = $t07728177505._1
1743- let badDebt = $t07728177505._2
1744- let fundingPayment = $t07728177505._3
1745- let rolloverFee = $t07728177505._4
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
17461822 throw(((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)) + s(rolloverFee)))
17471823 }
17481824 else throw("Strict value is not equal to itself.")
17621838
17631839 @Callable(i)
17641840 func view_getTerminalAmmPrice () = {
1765- let $t07794178022 = getTerminalAmmState()
1766- let terminalQuoteAssetReserve = $t07794178022._1
1767- let terminalBaseAssetReserve = $t07794178022._2
1841+ let $t08493385014 = getTerminalAmmState()
1842+ let terminalQuoteAssetReserve = $t08493385014._1
1843+ let terminalBaseAssetReserve = $t08493385014._2
17681844 let price = divd(muld(terminalQuoteAssetReserve, qtAstW()), muld(terminalBaseAssetReserve, bsAstW()))
17691845 throw(toString(price))
17701846 }
17741850 @Callable(i)
17751851 func view_getFunding () = {
17761852 let underlyingPrice = getOraclePrice()
1777- let $t07823778299 = getFunding()
1778- let shortPremiumFraction = $t07823778299._1
1779- let longPremiumFraction = $t07823778299._2
1853+ let $t08552385601 = getFunding()
1854+ let shortPremiumFraction = $t08552385601._1
1855+ let longPremiumFraction = $t08552385601._2
1856+ let premiumToVault = $t08552385601._3
17801857 let longFunding = divd(longPremiumFraction, underlyingPrice)
17811858 let shortFunding = divd(shortPremiumFraction, underlyingPrice)
1782- throw((((s(longFunding) + s(shortFunding)) + s(getTwapSpotPrice())) + s(getOraclePrice())))
1859+ throw(((((s(longFunding) + s(shortFunding)) + s(getTwapSpotPrice())) + s(getOraclePrice())) + s(premiumToVault)))
17831860 }
17841861
17851862
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"
59+
60+let k_fundingMode = "k_fundingMode"
5961
6062 let k_lastDataStr = "k_lastDataStr"
6163
6264 let k_lastMinuteId = "k_lastMinuteId"
6365
6466 let k_twapDataLastCumulativePrice = "k_twapDataLastCumulativePrice"
6567
6668 let k_twapDataLastPrice = "k_twapDataLastPrice"
6769
6870 let k_twapDataPreviousMinuteId = "k_twapDataPreviousMinuteId"
6971
7072 let k_latestLongCumulativePremiumFraction = "k_latestLongPremiumFraction"
7173
7274 let k_latestShortCumulativePremiumFraction = "k_latestShortPremiumFraction"
7375
7476 let k_nextFundingBlock = "k_nextFundingBlockMinTimestamp"
7577
7678 let k_longFundingRate = "k_longFundingRate"
7779
7880 let k_shortFundingRate = "k_shortFundingRate"
7981
8082 let k_quoteAssetReserve = "k_qtAstR"
8183
8284 let k_baseAssetReserve = "k_bsAstR"
8385
8486 let k_quoteAssetWeight = "k_qtAstW"
8587
8688 let k_baseAssetWeight = "k_bsAstW"
8789
8890 let k_totalPositionSize = "k_totalPositionSize"
8991
9092 let k_totalLongPositionSize = "k_totalLongPositionSize"
9193
9294 let k_totalShortPositionSize = "k_totalShortPositionSize"
9395
9496 let k_openInterestNotional = "k_openInterestNotional"
9597
9698 let k_openInterestShort = "k_openInterestShort"
9799
98100 let k_openInterestLong = "k_openInterestLong"
99101
100102 let k_lastTx = "k_lastTx"
101103
102104 let k_coordinatorAddress = "k_coordinatorAddress"
103105
104106 let k_vault_address = "k_vault_address"
105107
106108 let k_admin_address = "k_admin_address"
107109
108110 let k_quote_asset = "k_quote_asset"
109111
110112 let k_quote_staking = "k_quote_staking"
111113
112114 let k_staking_address = "k_staking_address"
113115
114116 let k_miner_address = "k_miner_address"
115117
116118 let k_orders_address = "k_orders_address"
117119
118120 let k_referral_address = "k_referral_address"
119121
120122 let k_exchange_address = "k_exchange_address"
121123
122124 let k_nft_manager_address = "k_nft_manager_address"
123125
124126 func toCompositeKey (_key,_address) = ((_key + "_") + _address)
125127
126128
127129 func coordinator () = valueOrErrorMessage(addressFromString(getStringValue(this, k_coordinatorAddress)), "Coordinator not set")
128130
129131
130132 func adminAddress () = addressFromString(getStringValue(coordinator(), k_admin_address))
131133
132134
133135 func quoteAsset () = fromBase58String(getStringValue(coordinator(), k_quote_asset))
134136
135137
136138 func quoteAssetStaking () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_quote_staking)), "Quote asset staking not set")
137139
138140
139141 func stakingAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_staking_address)), "Staking not set")
140142
141143
142144 func vaultAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_vault_address)), "Vault not set")
143145
144146
145147 func minerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_miner_address)), "Miner not set")
146148
147149
148150 func ordersAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_orders_address)), "Orders not set")
149151
150152
151153 func referralAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_referral_address)), "Referral not set")
152154
153155
154156 func nftManagerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_nft_manager_address)), "NFT Manager not set")
155157
156158
157159 let k_token_param = "k_token_param"
158160
159161 let k_token_type = "k_token_type"
160162
161163 let FEE_REDUCTION_TOKEN_TYPE = "fee_reduction"
162164
163165 let DIR_LONG = 1
164166
165167 let DIR_SHORT = 2
166168
167169 let TWAP_INTERVAL = 15
168170
169171 let SECONDS = 1000
170172
171173 let DECIMAL_NUMBERS = 6
172174
173175 let DECIMAL_UNIT = (1 * (((((10 * 10) * 10) * 10) * 10) * 10))
174176
175177 let MINUTES_IN_YEAR = (525600 * DECIMAL_UNIT)
176178
177179 let ONE_DAY = (86400 * DECIMAL_UNIT)
178180
179181 let PNL_OPTION_SPOT = 1
180182
181183 let PNL_OPTION_ORACLE = 2
184+
185+let FUNDING_ASYMMETRIC = 1
186+
187+let FUNDING_SYMMETRIC = 2
182188
183189 func s (_x) = (toString(_x) + ",")
184190
185191
186192 func divd (_x,_y) = fraction(_x, DECIMAL_UNIT, _y, HALFEVEN)
187193
188194
189195 func muld (_x,_y) = fraction(_x, _y, DECIMAL_UNIT, HALFEVEN)
190196
191197
192198 func bdivd (_x,_y) = fraction(_x, toBigInt(DECIMAL_UNIT), _y, HALFEVEN)
193199
194200
195201 func bmuld (_x,_y) = fraction(_x, _y, toBigInt(DECIMAL_UNIT), HALFEVEN)
196202
197203
198204 func abs (_x) = if ((_x > 0))
199205 then _x
200206 else -(_x)
201207
202208
203209 func vmax (_x,_y) = if ((_x >= _y))
204210 then _x
205211 else _y
206212
207213
208214 func listToStr (_list) = if ((size(_list) == 0))
209215 then ""
210216 else makeString(_list, ",")
211217
212218
213219 func strToList (_str) = if ((_str == ""))
214220 then nil
215221 else split(_str, ",")
216222
217223
218224 func pushToQueue (_list,_maxSize,_value) = if ((size(_list) > _maxSize))
219225 then (removeByIndex(_list, 0) :+ _value)
220226 else (_list :+ _value)
221227
222228
223229 func int (k) = valueOrErrorMessage(getInteger(this, k), ("no value for " + k))
224230
225231
226232 func intOr (k,def) = valueOrElse(getInteger(this, k), def)
227233
228234
229235 func strA (_address,_key) = {
230236 let val = valueOrErrorMessage(getString(_address, _key), ("No value for key " + _key))
231237 val
232238 }
233239
234240
235241 func intA (_address,_key) = {
236242 let val = valueOrErrorMessage(getInteger(_address, _key), ("No value for key " + _key))
237243 val
238244 }
239245
240246
241247 func cbalance () = int(k_balance)
242248
243249
244250 func fee () = int(k_fee)
245251
246252
247253 func rolloverFeeRate () = int(k_rolloverFee)
248254
249255
250256 func initMarginRatio () = int(k_initMarginRatio)
251257
252258
253259 func qtAstR () = int(k_quoteAssetReserve)
254260
255261
256262 func bsAstR () = int(k_baseAssetReserve)
257263
258264
259265 func qtAstW () = intOr(k_quoteAssetWeight, DECIMAL_UNIT)
260266
261267
262268 func bsAstW () = intOr(k_baseAssetWeight, DECIMAL_UNIT)
263269
264270
265271 func totalPositionSize () = int(k_totalPositionSize)
266272
267273
268274 func openInterestNotional () = int(k_openInterestNotional)
269275
270276
271277 func openInterestShort () = int(k_openInterestShort)
272278
273279
274280 func openInterestLong () = int(k_openInterestLong)
275281
276282
277283 func nextFundingBlockTimestamp () = int(k_nextFundingBlock)
278284
279285
280286 func fundingPeriodRaw () = int(k_fundingPeriod)
281287
282288
283289 func fundingPeriodDecimal () = (fundingPeriodRaw() * DECIMAL_UNIT)
284290
285291
286292 func fundingPeriodSeconds () = (fundingPeriodRaw() * SECONDS)
287293
288294
289295 func maintenanceMarginRatio () = int(k_maintenanceMarginRatio)
290296
291297
292298 func liquidationFeeRatio () = int(k_liquidationFeeRatio)
293299
294300
295301 func partialLiquidationRatio () = int(k_partialLiquidationRatio)
296302
297303
298304 func spreadLimit () = int(k_spreadLimit)
299305
300306
301307 func maxPriceImpact () = int(k_maxPriceImpact)
302308
303309
304310 func maxPriceSpread () = int(k_maxPriceSpread)
305311
306312
307313 func maxOpenNotional () = int(k_maxOpenNotional)
308314
309315
310316 func latestLongCumulativePremiumFraction () = int(k_latestLongCumulativePremiumFraction)
311317
312318
313319 func latestShortCumulativePremiumFraction () = int(k_latestShortCumulativePremiumFraction)
314320
315321
316322 func totalShortPositionSize () = int(k_totalShortPositionSize)
317323
318324
319325 func totalLongPositionSize () = int(k_totalLongPositionSize)
320326
321327
322328 func lastSequence () = intOr(k_sequence, 0)
323329
324330
325331 func feeToStakersPercent () = int(k_feeToStakersPercent)
326332
327333
328334 func maxOracleDelay () = int(k_maxOracleDelay)
329335
330336
337+func fundingMode () = intOr(k_fundingMode, FUNDING_ASYMMETRIC)
338+
339+
331340 func lastTimestamp () = lastBlock.timestamp
332341
333342
334343 func getActualCaller (i) = valueOrElse(getString(ordersAddress(), "k_sender"), toString(i.caller))
335344
336345
337346 func requireMoreMarginRatio (_marginRatio,_baseMarginRatio,_largerThanOrEqualTo) = {
338347 let remainingMarginRatio = (_marginRatio - _baseMarginRatio)
339348 if (if (_largerThanOrEqualTo)
340349 then (0 > remainingMarginRatio)
341350 else false)
342351 then throw(((("Invalid margin: " + toString(_marginRatio)) + " < ") + toString(_baseMarginRatio)))
343352 else if (if (!(_largerThanOrEqualTo))
344353 then (remainingMarginRatio >= 0)
345354 else false)
346355 then throw(((("Invalid margin: " + toString(_marginRatio)) + " > ") + toString(_baseMarginRatio)))
347356 else true
348357 }
349358
350359
351360 func latestCumulativePremiumFraction (_positionSize) = if ((_positionSize == 0))
352361 then throw("Should not be called with _positionSize == 0")
353362 else if ((_positionSize > 0))
354363 then latestLongCumulativePremiumFraction()
355364 else latestShortCumulativePremiumFraction()
356365
357366
358367 func getPosition (_trader) = {
359368 let positionSizeOpt = getInteger(this, toCompositeKey(k_positionSize, _trader))
360369 match positionSizeOpt {
361370 case positionSize: Int =>
362371 $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)))
363372 case _ =>
364373 $Tuple5(0, 0, 0, 0, 0)
365374 }
366375 }
367376
368377
369378 func getPositionAsset (_trader) = {
370379 let positionAssetOpt = getString(this, toCompositeKey(k_positionAsset, _trader))
371380 match positionAssetOpt {
372381 case positionAsset: String =>
373382 positionAsset
374383 case _ =>
375384 toBase58String(quoteAsset())
376385 }
377386 }
378387
379388
380389 func getPositionFee (_trader) = {
381390 let positionFeeOpt = getInteger(this, toCompositeKey(k_positionFee, _trader))
382391 match positionFeeOpt {
383392 case positionFee: Int =>
384393 positionFee
385394 case _ =>
386395 fee()
387396 }
388397 }
389398
390399
391400 func requireOpenPosition (_trader) = if ((getPosition(_trader)._1 == 0))
392401 then throw("No open position")
393402 else true
394403
395404
396405 func getOracleData (key) = {
397406 let oracleDataStr = getString(this, key)
398407 if (if (isDefined(oracleDataStr))
399408 then (value(oracleDataStr) != "")
400409 else false)
401410 then {
402411 let oracleData = split(value(oracleDataStr), ",")
403412 let oracleAddress = valueOrErrorMessage(addressFromString(oracleData[0]), ("Invalid oracle address in: " + value(oracleDataStr)))
404413 let priceKey = oracleData[1]
405414 let blockKey = oracleData[2]
406415 let openKey = oracleData[3]
407416 $Tuple4(oracleAddress, priceKey, blockKey, openKey)
408417 }
409418 else unit
410419 }
411420
412421
413422 func initialized () = valueOrElse(getBoolean(this, k_initialized), false)
414423
415424
416425 func paused () = valueOrElse(getBoolean(this, k_paused), false)
417426
418427
419428 func closeOnly () = valueOrElse(getBoolean(this, k_closeOnly), false)
420429
421430
422431 func updateReserve (_isAdd,_quoteAssetAmount,_baseAssetAmount) = if (_isAdd)
423432 then {
424433 let newBase = (bsAstR() - _baseAssetAmount)
425434 if ((0 >= newBase))
426435 then throw("Tx lead to base asset reserve <= 0, revert")
427436 else $Tuple3((qtAstR() + _quoteAssetAmount), newBase, (totalPositionSize() + _baseAssetAmount))
428437 }
429438 else {
430439 let newQuote = (qtAstR() - _quoteAssetAmount)
431440 if ((0 >= newQuote))
432441 then throw("Tx lead to base quote reserve <= 0, revert")
433442 else $Tuple3(newQuote, (bsAstR() + _baseAssetAmount), (totalPositionSize() - _baseAssetAmount))
434443 }
435444
436445
437446 func calcInvariant (_qtAstR,_bsAstR) = {
438447 let bqtAstR = toBigInt(_qtAstR)
439448 let bbsAstR = toBigInt(_bsAstR)
440449 bmuld(bqtAstR, bbsAstR)
441450 }
442451
443452
444453 func swapInput (_isAdd,_quoteAssetAmount) = {
445454 let _qtAstR = qtAstR()
446455 let _bsAstR = bsAstR()
447456 let _qtAstW = qtAstW()
448457 let _bsAstW = bsAstW()
449458 let quoteAssetAmountAdjusted = divd(_quoteAssetAmount, _qtAstW)
450459 let k = calcInvariant(_qtAstR, _bsAstR)
451460 let quoteAssetReserveAfter = if (_isAdd)
452461 then (_qtAstR + quoteAssetAmountAdjusted)
453462 else (_qtAstR - quoteAssetAmountAdjusted)
454463 let baseAssetReserveAfter = toInt(bdivd(k, toBigInt(quoteAssetReserveAfter)))
455464 let amountBaseAssetBoughtAbs = abs((baseAssetReserveAfter - _bsAstR))
456465 let amountBaseAssetBought = if (_isAdd)
457466 then amountBaseAssetBoughtAbs
458467 else -(amountBaseAssetBoughtAbs)
459- let $t01672216892 = updateReserve(_isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
460- let quoteAssetReserveAfter1 = $t01672216892._1
461- let baseAssetReserveAfter1 = $t01672216892._2
462- let totalPositionSizeAfter1 = $t01672216892._3
468+ let $t01694317113 = updateReserve(_isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
469+ let quoteAssetReserveAfter1 = $t01694317113._1
470+ let baseAssetReserveAfter1 = $t01694317113._2
471+ let totalPositionSizeAfter1 = $t01694317113._3
463472 let priceBefore = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
464473 let marketPrice = divd(_quoteAssetAmount, amountBaseAssetBoughtAbs)
465474 let priceDiff = abs((priceBefore - marketPrice))
466475 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
467476 let maxPriceImpactValue = maxPriceImpact()
468477 if ((priceImpact > maxPriceImpactValue))
469478 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)))
470479 else $Tuple4(amountBaseAssetBought, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1)
471480 }
472481
473482
474483 func calcRolloverFee (_oldPositionMargin,_oldPositionLastUpdatedTimestamp) = {
475484 let positionMinutes = ((((lastTimestamp() - _oldPositionLastUpdatedTimestamp) / 1000) / 60) * DECIMAL_UNIT)
476485 let rolloverFee = divd(muld(muld(_oldPositionMargin, positionMinutes), rolloverFeeRate()), MINUTES_IN_YEAR)
477486 rolloverFee
478487 }
479488
480489
481490 func calcRemainMarginWithFundingPaymentAndRolloverFee (_oldPositionSize,_oldPositionMargin,_oldPositionCumulativePremiumFraction,_oldPositionLastUpdatedTimestamp,_marginDelta) = {
482491 let fundingPayment = if ((_oldPositionSize != 0))
483492 then {
484493 let _latestCumulativePremiumFraction = latestCumulativePremiumFraction(_oldPositionSize)
485494 muld((_latestCumulativePremiumFraction - _oldPositionCumulativePremiumFraction), _oldPositionSize)
486495 }
487496 else 0
488497 let rolloverFee = calcRolloverFee(_oldPositionMargin, _oldPositionLastUpdatedTimestamp)
489498 let signedMargin = (((_marginDelta - rolloverFee) - fundingPayment) + _oldPositionMargin)
490- let $t01914719274 = if ((0 > signedMargin))
499+ let $t01936819495 = if ((0 > signedMargin))
491500 then $Tuple2(0, abs(signedMargin))
492501 else $Tuple2(abs(signedMargin), 0)
493- let remainMargin = $t01914719274._1
494- let badDebt = $t01914719274._2
502+ let remainMargin = $t01936819495._1
503+ let badDebt = $t01936819495._2
495504 $Tuple4(remainMargin, badDebt, fundingPayment, rolloverFee)
496505 }
497506
498507
499508 func swapOutputWithReserves (_isAdd,_baseAssetAmount,_checkMaxPriceImpact,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
500509 let priceBefore = divd(muld(_quoteAssetReserve, _quoteAssetWeight), muld(_baseAssetReserve, _baseAssetWeight))
501510 if ((_baseAssetAmount == 0))
502511 then throw("Invalid base asset amount")
503512 else {
504513 let k = calcInvariant(_quoteAssetReserve, _baseAssetReserve)
505514 let baseAssetPoolAmountAfter = if (_isAdd)
506515 then (_baseAssetReserve + _baseAssetAmount)
507516 else (_baseAssetReserve - _baseAssetAmount)
508517 let quoteAssetAfter = toInt(bdivd(k, toBigInt(baseAssetPoolAmountAfter)))
509518 let quoteAssetDelta = abs((quoteAssetAfter - _quoteAssetReserve))
510519 let quoteAssetSold = muld(quoteAssetDelta, _quoteAssetWeight)
511520 let maxPriceImpactValue = maxPriceImpact()
512- let $t02053620698 = updateReserve(!(_isAdd), quoteAssetDelta, _baseAssetAmount)
513- let quoteAssetReserveAfter1 = $t02053620698._1
514- let baseAssetReserveAfter1 = $t02053620698._2
515- let totalPositionSizeAfter1 = $t02053620698._3
521+ let $t02075720919 = updateReserve(!(_isAdd), quoteAssetDelta, _baseAssetAmount)
522+ let quoteAssetReserveAfter1 = $t02075720919._1
523+ let baseAssetReserveAfter1 = $t02075720919._2
524+ let totalPositionSizeAfter1 = $t02075720919._3
516525 let marketPrice = divd(quoteAssetSold, _baseAssetAmount)
517526 let priceDiff = abs((priceBefore - marketPrice))
518527 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
519528 if (if ((priceImpact > maxPriceImpactValue))
520529 then _checkMaxPriceImpact
521530 else false)
522531 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)))
523532 else $Tuple7(quoteAssetSold, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1, (totalLongPositionSize() - (if (_isAdd)
524533 then abs(_baseAssetAmount)
525534 else 0)), (totalShortPositionSize() - (if (!(_isAdd))
526535 then abs(_baseAssetAmount)
527536 else 0)), priceImpact)
528537 }
529538 }
530539
531540
532541 func swapOutput (_isAdd,_baseAssetAmount,_checkMaxPriceImpact) = swapOutputWithReserves(_isAdd, _baseAssetAmount, _checkMaxPriceImpact, qtAstR(), qtAstW(), bsAstR(), bsAstW())
533542
534543
535544 func getOraclePriceValue (oracle,priceKey,blockKey) = {
536545 let lastValue = valueOrErrorMessage(getInteger(oracle, priceKey), ((("Can not get oracle price. Oracle: " + toString(oracle)) + " key: ") + priceKey))
537546 if ((blockKey != ""))
538547 then {
539548 let currentBlock = lastBlock.height
540549 let lastOracleBlock = valueOrErrorMessage(getInteger(oracle, blockKey), ((("Can not get oracle block. Oracle: " + toString(oracle)) + " key: ") + blockKey))
541550 if (((currentBlock - lastOracleBlock) > maxOracleDelay()))
542551 then throw(((("Oracle stale data. Last oracle block: " + toString(lastOracleBlock)) + " current block: ") + toString(currentBlock)))
543552 else lastValue
544553 }
545554 else lastValue
546555 }
547556
548557
549558 func getOraclePrice () = {
550559 let baseOracle = valueOrErrorMessage(getOracleData(k_baseOracle), "No base asset oracle data")
551560 let baseOraclePrice = getOraclePriceValue(baseOracle._1, baseOracle._2, baseOracle._3)
552561 let quoteOracle = getOracleData(k_quoteOracle)
553562 let quoteOraclePrice = if (isDefined(quoteOracle))
554563 then {
555564 let quoteOracleV = value(quoteOracle)
556565 getOraclePriceValue(quoteOracleV._1, quoteOracleV._2, quoteOracleV._3)
557566 }
558567 else DECIMAL_UNIT
559568 divd(baseOraclePrice, quoteOraclePrice)
560569 }
561570
562571
563572 func isMarketClosed () = {
564573 let baseOracle = valueOrErrorMessage(getOracleData(k_baseOracle), "No base asset oracle data")
565574 let oracle = baseOracle._1
566575 let openKey = baseOracle._4
567576 if ((openKey != ""))
568577 then {
569578 let isOpen = valueOrErrorMessage(getBoolean(oracle, openKey), ((("Can not get oracle is open/closed. Oracle: " + toString(oracle)) + " key: ") + openKey))
570579 !(isOpen)
571580 }
572581 else false
573582 }
574583
575584
576585 func absPriceDiff (_oraclePrice,_quoteAssetReserve,_baseAssetReserve,_qtAstW,_bsAstW) = {
577586 let priceAfter = divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
578587 let averagePrice = divd((_oraclePrice + priceAfter), (2 * DECIMAL_UNIT))
579588 let absPriceDiff = divd(abs((_oraclePrice - priceAfter)), averagePrice)
580589 absPriceDiff
581590 }
582591
583592
584593 func requireNotOverSpreadLimit (_quoteAssetReserve,_baseAssetReserve) = {
585594 let oraclePrice = getOraclePrice()
586595 let _qtAstW = qtAstW()
587596 let _bsAstW = bsAstW()
588597 let absPriceDiffBefore = absPriceDiff(oraclePrice, qtAstR(), bsAstR(), _qtAstW, _bsAstW)
589598 let absPriceDiffAfter = absPriceDiff(oraclePrice, _quoteAssetReserve, _baseAssetReserve, _qtAstW, _bsAstW)
590599 if (if ((absPriceDiffAfter > maxPriceSpread()))
591600 then (absPriceDiffAfter > absPriceDiffBefore)
592601 else false)
593602 then throw(((("Price spread " + toString(absPriceDiffAfter)) + " > max price spread ") + toString(maxPriceSpread())))
594603 else true
595604 }
596605
597606
598607 func requireNotOverMaxOpenNotional (_longOpenNotional,_shortOpenNotional) = {
599608 let _maxOpenNotional = maxOpenNotional()
600609 if ((_longOpenNotional > _maxOpenNotional))
601610 then throw(((("Long open notional " + toString(_longOpenNotional)) + " > max open notional ") + toString(_maxOpenNotional)))
602611 else if ((_shortOpenNotional > _maxOpenNotional))
603612 then throw(((("Short open notional " + toString(_shortOpenNotional)) + " > max open notional ") + toString(_maxOpenNotional)))
604613 else true
605614 }
606615
607616
608617 func getSpotPrice () = {
609618 let _quoteAssetReserve = qtAstR()
610619 let _baseAssetReserve = bsAstR()
611620 let _qtAstW = qtAstW()
612621 let _bsAstW = bsAstW()
613622 divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
614623 }
615624
616625
617626 func isOverFluctuationLimit () = {
618627 let oraclePrice = getOraclePrice()
619628 let currentPrice = getSpotPrice()
620629 (divd(abs((oraclePrice - currentPrice)), oraclePrice) > spreadLimit())
621630 }
622631
623632
624633 func getPositionAdjustedOpenNotional (_positionSize,_option,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
625634 let positionSizeAbs = abs(_positionSize)
626635 let isShort = (0 > _positionSize)
627636 let positionNotional = if ((_option == PNL_OPTION_SPOT))
628637 then {
629638 let outPositionNotional = swapOutputWithReserves(!(isShort), positionSizeAbs, false, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)._1
630639 outPositionNotional
631640 }
632641 else muld(positionSizeAbs, getOraclePrice())
633642 positionNotional
634643 }
635644
636645
637646 func getPositionNotionalAndUnrealizedPnlByValues (_positionSize,_positionOpenNotional,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight,_option) = if ((_positionSize == 0))
638647 then throw("Invalid position size")
639648 else {
640649 let isShort = (0 > _positionSize)
641650 let positionNotional = getPositionAdjustedOpenNotional(_positionSize, _option, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
642651 let unrealizedPnl = if (isShort)
643652 then (_positionOpenNotional - positionNotional)
644653 else (positionNotional - _positionOpenNotional)
645654 $Tuple2(positionNotional, unrealizedPnl)
646655 }
647656
648657
649658 func getPositionNotionalAndUnrealizedPnl (_trader,_option) = {
650- let $t02857628704 = getPosition(_trader)
651- let positionSize = $t02857628704._1
652- let positionMargin = $t02857628704._2
653- let positionOpenNotional = $t02857628704._3
654- let positionLstUpdCPF = $t02857628704._4
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
655664 getPositionNotionalAndUnrealizedPnlByValues(positionSize, positionOpenNotional, qtAstR(), qtAstW(), bsAstR(), bsAstW(), _option)
656665 }
657666
658667
659668 func calcMarginRatio (_remainMargin,_badDebt,_positionNotional) = divd((_remainMargin - _badDebt), _positionNotional)
660669
661670
662671 func getMarginRatioByOption (_trader,_option) = {
663- let $t02921929360 = getPosition(_trader)
664- let positionSize = $t02921929360._1
665- let positionMargin = $t02921929360._2
666- let pon = $t02921929360._3
667- let positionLastUpdatedCPF = $t02921929360._4
668- let positionTimestamp = $t02921929360._5
669- let $t02936629459 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
670- let positionNotional = $t02936629459._1
671- let unrealizedPnl = $t02936629459._2
672- let $t02946429676 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLastUpdatedCPF, positionTimestamp, unrealizedPnl)
673- let remainMargin = $t02946429676._1
674- let badDebt = $t02946429676._2
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
675684 calcMarginRatio(remainMargin, badDebt, positionNotional)
676685 }
677686
678687
679688 func getMarginRatio (_trader) = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
680689
681690
682691 func getPartialLiquidationAmount (_trader,_positionSize) = {
683692 let maximumRatio = vmax(partialLiquidationRatio(), (DECIMAL_UNIT - divd(getMarginRatio(_trader), maintenanceMarginRatio())))
684693 let maxExchangedPositionSize = muld(abs(_positionSize), maximumRatio)
685694 let swapResult = swapOutput((_positionSize > 0), maxExchangedPositionSize, false)
686695 let maxExchangedQuoteAssetAmount = swapResult._1
687696 let priceImpact = swapResult._7
688697 if ((maxPriceImpact() > priceImpact))
689698 then maxExchangedPositionSize
690699 else muld(abs(_positionSize), partialLiquidationRatio())
691700 }
692701
693702
694703 func internalClosePosition (_trader,_size,_fee,_minQuoteAssetAmount,_addToMargin,_checkMaxPriceImpact,_liquidate) = {
695- let $t03074330899 = getPosition(_trader)
696- let oldPositionSize = $t03074330899._1
697- let oldPositionMargin = $t03074330899._2
698- let oldPositionOpenNotional = $t03074330899._3
699- let oldPositionLstUpdCPF = $t03074330899._4
700- let oldPositionTimestamp = $t03074330899._5
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
701710 let isLongPosition = (oldPositionSize > 0)
702711 let absOldPositionSize = abs(oldPositionSize)
703712 if (if ((absOldPositionSize >= _size))
704713 then (_size > 0)
705714 else false)
706715 then {
707716 let isPartialClose = (absOldPositionSize > _size)
708- let $t03119131642 = swapOutput((oldPositionSize > 0), _size, _checkMaxPriceImpact)
709- let exchangedQuoteAssetAmount = $t03119131642._1
710- let quoteAssetReserveAfter = $t03119131642._2
711- let baseAssetReserveAfter = $t03119131642._3
712- let totalPositionSizeAfter = $t03119131642._4
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
713722 let exchangedPositionSize = if ((oldPositionSize > 0))
714723 then -(_size)
715724 else _size
716- let $t03185732064 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
717- let oldPositionNotional = $t03185732064._1
718- let unrealizedPnl = $t03185732064._2
725+ let $t03207832285 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
726+ let oldPositionNotional = $t03207832285._1
727+ let unrealizedPnl = $t03207832285._2
719728 let realizedRatio = divd(abs(exchangedPositionSize), absOldPositionSize)
720729 let realizedPnl = muld(unrealizedPnl, realizedRatio)
721- let $t03240532651 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, unrealizedPnl)
722- let remainMarginBefore = $t03240532651._1
723- let x1 = $t03240532651._2
724- let x2 = $t03240532651._3
725- let rolloverFee = $t03240532651._4
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
726735 let positionBadDebt = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, realizedPnl)._2
727736 let realizedCloseFee = muld(muld(oldPositionNotional, realizedRatio), _fee)
728737 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
729738 let remainOpenNotional = if ((oldPositionSize > 0))
730739 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
731740 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
732741 let newPositionSize = (oldPositionSize + exchangedPositionSize)
733- let $t03405734443 = if ((newPositionSize == 0))
742+ let $t03427834664 = if ((newPositionSize == 0))
734743 then $Tuple2(0, 0)
735744 else $Tuple2(abs(remainOpenNotional), latestCumulativePremiumFraction(newPositionSize))
736- let newPositionOpenNotional = $t03405734443._1
737- let newPositionLstUpdCPF = $t03405734443._2
745+ let newPositionOpenNotional = $t03427834664._1
746+ let newPositionLstUpdCPF = $t03427834664._2
738747 let openNotionalDelta = (oldPositionOpenNotional - newPositionOpenNotional)
739748 let marginRatio = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
740749 let newPositionMarginWithSameRatio = if ((oldPositionSize > 0))
741750 then (muld((newPositionOpenNotional + unrealizedPnlAfter), marginRatio) - unrealizedPnlAfter)
742751 else (muld((newPositionOpenNotional - unrealizedPnlAfter), marginRatio) - unrealizedPnlAfter)
743752 let marginToTraderRaw = ((remainMarginBefore - (newPositionMarginWithSameRatio + unrealizedPnlAfter)) - realizedCloseFee)
744753 let marginToTrader = if ((0 > marginToTraderRaw))
745754 then if (_liquidate)
746755 then 0
747756 else throw("Invalid internalClosePosition params: unable to pay fee")
748757 else marginToTraderRaw
749758 let newPositionMargin = if (_addToMargin)
750759 then (newPositionMarginWithSameRatio + marginToTrader)
751760 else newPositionMarginWithSameRatio
752761 if (if ((_minQuoteAssetAmount != 0))
753762 then (_minQuoteAssetAmount > exchangedQuoteAssetAmount)
754763 else false)
755764 then throw(((("Limit error: " + toString(exchangedQuoteAssetAmount)) + " < ") + toString(_minQuoteAssetAmount)))
756765 else $Tuple17(newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, positionBadDebt, realizedPnl, if (if (_addToMargin)
757766 then isPartialClose
758767 else false)
759768 then 0
760769 else marginToTrader, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, (openInterestNotional() - openNotionalDelta), (totalLongPositionSize() - (if (isLongPosition)
761770 then abs(exchangedPositionSize)
762771 else 0)), (totalShortPositionSize() - (if (!(isLongPosition))
763772 then abs(exchangedPositionSize)
764773 else 0)), (openInterestLong() - (if (isLongPosition)
765774 then openNotionalDelta
766775 else 0)), (openInterestShort() - (if (!(isLongPosition))
767776 then openNotionalDelta
768777 else 0)), (realizedCloseFee + rolloverFee), exchangedQuoteAssetAmount)
769778 }
770779 else throw(((("Invalid internalClosePosition params: invalid position size: " + toString(_size)) + " max: ") + toString(absOldPositionSize)))
771780 }
772781
773782
774783 func getTwapSpotPrice () = {
775784 let minuteId = ((lastTimestamp() / 1000) / 60)
776785 let startMinuteId = (minuteId - TWAP_INTERVAL)
777786 let listStr = valueOrElse(getString(this, k_lastDataStr), "")
778787 let list = split(listStr, ",")
779788 func filterFn (accumulator,next) = if ((startMinuteId >= valueOrErrorMessage(parseInt(next), ("getTwapSpotPrice: invalid int: " + listStr))))
780789 then (accumulator :+ parseIntValue(next))
781790 else accumulator
782791
783792 let listF = {
784793 let $l = list
785794 let $s = size($l)
786795 let $acc0 = nil
787796 func $f0_1 ($a,$i) = if (($i >= $s))
788797 then $a
789798 else filterFn($a, $l[$i])
790799
791800 func $f0_2 ($a,$i) = if (($i >= $s))
792801 then $a
793802 else throw("List size exceeds 20")
794803
795804 $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)
796805 }
797806 let maxIndex = if ((size(listF) > 0))
798807 then max(listF)
799808 else valueOrErrorMessage(parseInt(list[0]), ("getTwapSpotPrice: invalid int: " + listStr))
800809 let lastMinuteId = valueOrElse(getInteger(this, k_lastMinuteId), 0)
801810 let endLastCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(lastMinuteId))), 0)
802811 let endLastPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(lastMinuteId))), 0)
803812 let nowCumulativePrice = (endLastCumulativePrice + ((minuteId - lastMinuteId) * endLastPrice))
804813 let startLastCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(maxIndex))), 0)
805814 let startLastPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(maxIndex))), 0)
806815 let startCumulativePrice = (startLastCumulativePrice + ((startMinuteId - maxIndex) * startLastPrice))
807816 ((nowCumulativePrice - startCumulativePrice) / TWAP_INTERVAL)
808817 }
809818
810819
811820 func getTerminalAmmState () = {
812821 let _positionSize = totalPositionSize()
813822 if ((_positionSize == 0))
814823 then $Tuple2(qtAstR(), bsAstR())
815824 else {
816825 let direction = (_positionSize > 0)
817- let $t03918039359 = swapOutput(direction, abs(_positionSize), false)
818- let currentNetMarketValue = $t03918039359._1
819- let terminalQuoteAssetReserve = $t03918039359._2
820- let terminalBaseAssetReserve = $t03918039359._3
826+ let $t03940139580 = swapOutput(direction, abs(_positionSize), false)
827+ let currentNetMarketValue = $t03940139580._1
828+ let terminalQuoteAssetReserve = $t03940139580._2
829+ let terminalBaseAssetReserve = $t03940139580._3
821830 $Tuple2(terminalQuoteAssetReserve, terminalBaseAssetReserve)
822831 }
823832 }
824833
825834
826835 func getQuoteAssetWeight (baseAssetReserve,totalPositionSize,quoteAssetReserve,targetPrice) = {
827836 let b = toBigInt(baseAssetReserve)
828837 let sz = toBigInt(totalPositionSize)
829838 let q = toBigInt(quoteAssetReserve)
830839 let p = toBigInt(targetPrice)
831840 let k = bmuld(q, b)
832841 let newB = (b + sz)
833842 let newQ = bdivd(k, newB)
834843 let z = bdivd(newQ, newB)
835844 let result = bdivd(p, z)
836845 toInt(result)
837846 }
838847
839848
840849 func getSyncTerminalPrice (_terminalPrice,_qtAstR,_bsAstR) = {
841850 let _positionSize = totalPositionSize()
842851 if ((_positionSize == 0))
843852 then {
844853 let newQtAstW = divd(muld(_terminalPrice, _bsAstR), _qtAstR)
845854 $Tuple3(newQtAstW, DECIMAL_UNIT, 0)
846855 }
847856 else {
848857 let direction = (_positionSize > 0)
849858 let currentNetMarketValue = swapOutput(direction, abs(_positionSize), false)._1
850859 let newQtAstW = getQuoteAssetWeight(_bsAstR, _positionSize, _qtAstR, _terminalPrice)
851860 let newBsAstW = DECIMAL_UNIT
852861 let marginToVault = getPositionNotionalAndUnrealizedPnlByValues(_positionSize, currentNetMarketValue, _qtAstR, newQtAstW, _bsAstR, newBsAstW, PNL_OPTION_SPOT)._2
853862 $Tuple3(newQtAstW, newBsAstW, marginToVault)
854863 }
855864 }
856865
857866
858867 func getFunding () = {
859868 let underlyingPrice = getOraclePrice()
860869 let spotTwapPrice = getTwapSpotPrice()
861870 let premium = (spotTwapPrice - underlyingPrice)
862871 if (if (if ((totalShortPositionSize() == 0))
863872 then true
864873 else (totalLongPositionSize() == 0))
865874 then true
866875 else isMarketClosed())
867- then $Tuple2(0, 0)
876+ then $Tuple3(0, 0, 0)
868877 else if ((0 > premium))
869878 then {
870879 let shortPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
871- let longPremiumFraction = divd(muld(shortPremiumFraction, totalShortPositionSize()), totalLongPositionSize())
872- $Tuple2(shortPremiumFraction, longPremiumFraction)
880+ if ((fundingMode() == FUNDING_ASYMMETRIC))
881+ then {
882+ let longPremiumFraction = divd(muld(shortPremiumFraction, totalShortPositionSize()), totalLongPositionSize())
883+ $Tuple3(shortPremiumFraction, longPremiumFraction, 0)
884+ }
885+ else {
886+ let shortTotalPremiumFraction = abs(muld(shortPremiumFraction, totalShortPositionSize()))
887+ let longTotalPremiumFraction = abs(muld(shortPremiumFraction, totalLongPositionSize()))
888+ let premiumToVault = (shortTotalPremiumFraction - longTotalPremiumFraction)
889+ $Tuple3(shortPremiumFraction, shortPremiumFraction, premiumToVault)
890+ }
873891 }
874892 else {
875893 let longPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
876- let shortPremiumFraction = divd(muld(longPremiumFraction, totalLongPositionSize()), totalShortPositionSize())
877- $Tuple2(shortPremiumFraction, longPremiumFraction)
894+ if ((fundingMode() == FUNDING_ASYMMETRIC))
895+ then {
896+ let shortPremiumFraction = divd(muld(longPremiumFraction, totalLongPositionSize()), totalShortPositionSize())
897+ $Tuple3(shortPremiumFraction, longPremiumFraction, 0)
898+ }
899+ else {
900+ let longTotalPremiumFraction = abs(muld(longPremiumFraction, totalLongPositionSize()))
901+ let shortTotalPremiumFraction = abs(muld(longPremiumFraction, totalShortPositionSize()))
902+ let premiumToVault = (longTotalPremiumFraction - shortTotalPremiumFraction)
903+ $Tuple3(longPremiumFraction, longPremiumFraction, premiumToVault)
904+ }
878905 }
879906 }
880907
881908
882909 func getAdjustedFee (_artifactId,_baseFeeDiscount) = {
883910 let baseFeeRaw = fee()
884911 let baseFee = muld(baseFeeRaw, _baseFeeDiscount)
885- let $t04222042715 = if ((_artifactId != ""))
912+ let $t04332643821 = if ((_artifactId != ""))
886913 then {
887914 let artifactKind = strA(nftManagerAddress(), toCompositeKey(k_token_type, _artifactId))
888915 if ((artifactKind == FEE_REDUCTION_TOKEN_TYPE))
889916 then {
890917 let reduction = intA(nftManagerAddress(), toCompositeKey(k_token_param, _artifactId))
891918 let adjustedFee = muld(baseFee, reduction)
892919 $Tuple2(adjustedFee, true)
893920 }
894921 else throw("Invalid attached artifact")
895922 }
896923 else $Tuple2(baseFee, false)
897- let adjustedFee = $t04222042715._1
898- let burnArtifact = $t04222042715._2
924+ let adjustedFee = $t04332643821._1
925+ let burnArtifact = $t04332643821._2
899926 $Tuple2(adjustedFee, burnArtifact)
900927 }
901928
902929
903930 func isSameAssetOrNoPosition (_trader,_assetId) = {
904931 let oldPositionSize = getPosition(_trader)._1
905932 if ((oldPositionSize == 0))
906933 then true
907934 else (getPositionAsset(_trader) == _assetId)
908935 }
909936
910937
911938 func isSameAsset (_trader,_assetId) = (getPositionAsset(_trader) == _assetId)
912939
913940
914941 func getForTraderWithArtifact (_trader,_artifactId) = {
915942 let doGetFeeDiscount = invoke(minerAddress(), "computeFeeDiscount", [_trader], nil)
916943 if ((doGetFeeDiscount == doGetFeeDiscount))
917944 then {
918945 let feeDiscount = match doGetFeeDiscount {
919946 case x: Int =>
920947 x
921948 case _ =>
922949 throw("Invalid computeFeeDiscount result")
923950 }
924- let $t04339543469 = getAdjustedFee(_artifactId, feeDiscount)
925- let adjustedFee = $t04339543469._1
926- let burnArtifact = $t04339543469._2
951+ let $t04450144575 = getAdjustedFee(_artifactId, feeDiscount)
952+ let adjustedFee = $t04450144575._1
953+ let burnArtifact = $t04450144575._2
927954 $Tuple2(adjustedFee, burnArtifact)
928955 }
929956 else throw("Strict value is not equal to itself.")
930957 }
931958
932959
933960 func getArtifactId (i) = {
934961 let artifactId = if ((size(i.payments) > 1))
935962 then toBase58String(valueOrErrorMessage(i.payments[1].assetId, "Invalid artifactId"))
936963 else ""
937964 artifactId
938965 }
939966
940967
941968 func distributeFee (_feeAmount) = {
942969 let feeToStakers = muld(_feeAmount, feeToStakersPercent())
943970 let feeToVault = (_feeAmount - feeToStakers)
944971 $Tuple2(feeToStakers, feeToVault)
945972 }
946973
947974
948-func updateSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay,_rolloverFee) = [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)]
975+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)]
949976
950977
951978 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)]
952979
953980
954981 func incrementPositionSequenceNumber (_isNewPosition,_address) = if (_isNewPosition)
955982 then {
956983 let currentSequence = lastSequence()
957984 [IntegerEntry(toCompositeKey(k_positionSequence, _address), (currentSequence + 1)), IntegerEntry(k_sequence, (currentSequence + 1))]
958985 }
959986 else nil
960987
961988
962989 func updatePositionFee (_isNewPosition,_address,_fee) = if (_isNewPosition)
963990 then [IntegerEntry(toCompositeKey(k_positionFee, _address), _fee)]
964991 else nil
965992
966993
967994 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)]
968995
969996
970997 func appendTwap (_price) = {
971998 let minuteId = ((lastTimestamp() / 1000) / 60)
972999 let previousMinuteId = valueOrElse(getInteger(this, k_lastMinuteId), 0)
9731000 if ((previousMinuteId > minuteId))
9741001 then throw("TWAP out-of-order")
9751002 else {
9761003 let lastMinuteId = if ((previousMinuteId == 0))
9771004 then minuteId
9781005 else previousMinuteId
9791006 if ((minuteId > previousMinuteId))
9801007 then {
9811008 let prevCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(previousMinuteId))), 0)
9821009 let prevPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(previousMinuteId))), _price)
9831010 let lastCumulativePrice = (prevCumulativePrice + ((minuteId - lastMinuteId) * prevPrice))
9841011 let list = pushToQueue(strToList(valueOrElse(getString(this, k_lastDataStr), "")), TWAP_INTERVAL, toString(minuteId))
9851012 [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))]
9861013 }
9871014 else {
9881015 let twapDataPreviousMinuteId = valueOrElse(getInteger(this, toCompositeKey(k_twapDataPreviousMinuteId, toString(minuteId))), 0)
9891016 let prevCumulativePrice = valueOrElse(getInteger(this, toCompositeKey(k_twapDataLastCumulativePrice, toString(twapDataPreviousMinuteId))), 0)
9901017 let prevPrice = valueOrElse(getInteger(this, toCompositeKey(k_twapDataLastPrice, toString(twapDataPreviousMinuteId))), _price)
9911018 let lastCumulativePrice = (prevCumulativePrice + ((minuteId - twapDataPreviousMinuteId) * prevPrice))
9921019 [IntegerEntry(toCompositeKey(k_twapDataLastCumulativePrice, toString(minuteId)), lastCumulativePrice), IntegerEntry(toCompositeKey(k_twapDataLastPrice, toString(minuteId)), _price)]
9931020 }
9941021 }
9951022 }
9961023
9971024
9981025 func updateAmmReserves (_qtAstR,_bsAstR) = [IntegerEntry(k_quoteAssetReserve, _qtAstR), IntegerEntry(k_baseAssetReserve, _bsAstR)]
9991026
10001027
10011028 func updateAmmWeights (_qtAstW,_bsAstW) = [IntegerEntry(k_quoteAssetWeight, _qtAstW), IntegerEntry(k_baseAssetWeight, _bsAstW)]
10021029
10031030
10041031 func updateAmm (_qtAstR,_bsAstR,_totalPositionSizeAfter,_openInterestNotional,_totalLongPositionSize,_totalShortPositionSize,_totalLongOpenNotional,_totalShortOpenNotional) = {
10051032 let _qtAstW = qtAstW()
10061033 let _bsAstW = bsAstW()
10071034 if (((_totalLongPositionSize - _totalShortPositionSize) != _totalPositionSizeAfter))
10081035 then throw(((((("Invalid AMM state data: " + toString(_totalLongPositionSize)) + " + ") + toString(_totalShortPositionSize)) + " != ") + toString(_totalPositionSizeAfter)))
10091036 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))))
10101037 }
10111038
10121039
10131040 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))]
10141041
10151042
10161043 func withdraw (_address,_amount) = {
10171044 let balance = assetBalance(this, quoteAsset())
10181045 if ((_amount > balance))
10191046 then throw(((("Unable to withdraw " + toString(_amount)) + " from contract balance ") + toString(balance)))
10201047 else [ScriptTransfer(_address, _amount, quoteAsset())]
10211048 }
10221049
10231050
10241051 func updateBalance (i) = if ((0 > i))
10251052 then throw("Balance")
10261053 else [IntegerEntry(k_balance, i)]
10271054
10281055
10291056 func transferFee (i) = [ScriptTransfer(stakingAddress(), i, quoteAsset())]
10301057
10311058
10321059 func doBurnArtifact (_burnArtifact,i) = if (_burnArtifact)
10331060 then [Burn(valueOrErrorMessage(i.payments[1].assetId, "Invalid artifact"), 1)]
10341061 else nil
10351062
10361063
10371064 @Callable(i)
10381065 func pause () = if ((i.caller != adminAddress()))
10391066 then throw("Invalid pause params")
10401067 else [BooleanEntry(k_paused, true)]
10411068
10421069
10431070
10441071 @Callable(i)
10451072 func unpause () = if ((i.caller != adminAddress()))
10461073 then throw("Invalid unpause params")
10471074 else [BooleanEntry(k_paused, false)]
10481075
10491076
10501077
10511078 @Callable(i)
10521079 func setCloseOnly () = if ((i.caller != adminAddress()))
10531080 then throw("Invalid setCloseOnly params")
10541081 else [BooleanEntry(k_closeOnly, true)]
10551082
10561083
10571084
10581085 @Callable(i)
10591086 func unsetCloseOnly () = if ((i.caller != adminAddress()))
10601087 then throw("Invalid unsetCloseOnly params")
10611088 else [BooleanEntry(k_closeOnly, false)]
10621089
10631090
10641091
10651092 @Callable(i)
10661093 func addLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
10671094 then true
10681095 else (0 >= _quoteAssetAmount))
10691096 then throw("Invalid addLiquidity params")
10701097 else {
10711098 let _qtAstR = qtAstR()
10721099 let _bsAstR = bsAstR()
10731100 let _qtAstW = qtAstW()
10741101 let _bsAstW = bsAstW()
10751102 let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
10761103 let qtAstRAfter = (_qtAstR + _quoteAssetAmount)
10771104 let baseAssetAmountToAdd = (divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR)
10781105 let bsAstRAfter = (_bsAstR + baseAssetAmountToAdd)
1079- let $t05287653027 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1080- let newQuoteAssetWeight = $t05287653027._1
1081- let newBaseAssetWeight = $t05287653027._2
1082- let marginToVault = $t05287653027._3
1106+ let $t05479454945 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1107+ let newQuoteAssetWeight = $t05479454945._1
1108+ let newBaseAssetWeight = $t05479454945._2
1109+ let marginToVault = $t05479454945._3
10831110 let doExchangePnL = if ((marginToVault != 0))
10841111 then {
10851112 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
10861113 if ((doExchangePnL == doExchangePnL))
10871114 then nil
10881115 else throw("Strict value is not equal to itself.")
10891116 }
10901117 else nil
10911118 if ((doExchangePnL == doExchangePnL))
10921119 then (updateAmmReserves(qtAstRAfter, bsAstRAfter) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
10931120 else throw("Strict value is not equal to itself.")
10941121 }
10951122
10961123
10971124
10981125 @Callable(i)
10991126 func removeLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
11001127 then true
11011128 else (_quoteAssetAmount >= 0))
11021129 then throw("Invalid removeLiquidity params")
11031130 else {
11041131 let _qtAstR = qtAstR()
11051132 let _bsAstR = bsAstR()
11061133 let _qtAstW = qtAstW()
11071134 let _bsAstW = bsAstW()
11081135 let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
11091136 let qtAstRAfter = (_qtAstR - _quoteAssetAmount)
11101137 let baseAssetAmountToRemove = abs((divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR))
11111138 let bsAstRAfter = (_bsAstR - baseAssetAmountToRemove)
1112- let $t05395954110 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1113- let newQuoteAssetWeight = $t05395954110._1
1114- let newBaseAssetWeight = $t05395954110._2
1115- let marginToVault = $t05395954110._3
1139+ let $t05604156192 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1140+ let newQuoteAssetWeight = $t05604156192._1
1141+ let newBaseAssetWeight = $t05604156192._2
1142+ let marginToVault = $t05604156192._3
11161143 let doExchangePnL = if ((marginToVault != 0))
11171144 then {
11181145 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
11191146 if ((doExchangePnL == doExchangePnL))
11201147 then nil
11211148 else throw("Strict value is not equal to itself.")
11221149 }
11231150 else nil
11241151 if ((doExchangePnL == doExchangePnL))
11251152 then (updateAmmReserves(qtAstRAfter, bsAstRAfter) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
11261153 else throw("Strict value is not equal to itself.")
11271154 }
11281155
11291156
11301157
11311158 @Callable(i)
1132-func changeSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay,_rolloverFee) = if ((i.caller != adminAddress()))
1159+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))
1160+ then true
1161+ else (0 >= _initMarginRatio))
1162+ then true
1163+ else (0 >= _mmr))
1164+ then true
1165+ else (0 >= _liquidationFeeRatio))
1166+ then true
1167+ else (0 >= _fee))
1168+ then true
1169+ else (0 >= _spreadLimit))
1170+ then true
1171+ else (0 >= _maxPriceImpact))
1172+ then true
1173+ else (0 >= _partialLiquidationRatio))
1174+ then true
1175+ else (0 >= _maxPriceSpread))
1176+ then true
1177+ else (0 >= _maxOpenNotional))
1178+ then true
1179+ else (0 >= _feeToStakersPercent))
1180+ then true
1181+ else (_feeToStakersPercent > DECIMAL_UNIT))
1182+ then true
1183+ else (0 >= _maxOracleDelay))
1184+ then true
1185+ else (0 >= _rolloverFee))
1186+ then true
1187+ else if ((_fundingMode != FUNDING_SYMMETRIC))
1188+ then (_fundingMode != FUNDING_ASYMMETRIC)
1189+ else false)
1190+ then true
1191+ else !(initialized()))
1192+ then true
1193+ else (i.caller != adminAddress()))
11331194 then throw("Invalid changeSettings params")
1134- else updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact, _partialLiquidationRatio, _maxPriceSpread, _maxOpenNotional, _feeToStakersPercent, _maxOracleDelay, _rolloverFee)
1195+ else updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact, _partialLiquidationRatio, _maxPriceSpread, _maxOpenNotional, _feeToStakersPercent, _maxOracleDelay, _rolloverFee, _fundingMode)
11351196
11361197
11371198
11381199 @Callable(i)
1139-func initialize (_qtAstR,_bsAstR,_fundingPeriod,_initMarginRatio,_mmr,_liquidationFeeRatio,_fee,_baseOracleData,_quoteOracleData,_coordinator,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay,_rolloverFee) = if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if ((0 >= _qtAstR))
1200+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))
11401201 then true
11411202 else (0 >= _bsAstR))
11421203 then true
11431204 else (0 >= _fundingPeriod))
11441205 then true
11451206 else (0 >= _initMarginRatio))
11461207 then true
11471208 else (0 >= _mmr))
11481209 then true
11491210 else (0 >= _liquidationFeeRatio))
11501211 then true
11511212 else (0 >= _fee))
11521213 then true
11531214 else (0 >= _spreadLimit))
11541215 then true
11551216 else (0 >= _maxPriceImpact))
11561217 then true
11571218 else (0 >= _partialLiquidationRatio))
11581219 then true
11591220 else (0 >= _maxPriceSpread))
11601221 then true
11611222 else (0 >= _maxOpenNotional))
11621223 then true
11631224 else (0 >= _feeToStakersPercent))
11641225 then true
11651226 else (_feeToStakersPercent > DECIMAL_UNIT))
11661227 then true
11671228 else (0 >= _maxOracleDelay))
11681229 then true
11691230 else (0 >= _rolloverFee))
11701231 then true
1232+ else if ((_fundingMode != FUNDING_SYMMETRIC))
1233+ then (_fundingMode != FUNDING_ASYMMETRIC)
1234+ else false)
1235+ then true
11711236 else initialized())
11721237 then true
11731238 else (i.caller != this))
11741239 then throw("Invalid initialize parameters")
1175- else ((((updateAmm(_qtAstR, _bsAstR, 0, 0, 0, 0, 0, 0) ++ updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact, _partialLiquidationRatio, _maxPriceSpread, _maxOpenNotional, _feeToStakersPercent, _maxOracleDelay, _rolloverFee)) ++ 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)))])
1240+ 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)))])
11761241
11771242
11781243
11791244 @Callable(i)
11801245 func increasePosition (_direction,_leverage,_minBaseAssetAmount,_refLink) = {
11811246 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
11821247 if ((sync == sync))
11831248 then {
11841249 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
11851250 if ((ensureCalledOnce == ensureCalledOnce))
11861251 then {
11871252 let _trader = getActualCaller(i)
11881253 let _rawAmount = i.payments[0].amount
11891254 let _assetId = i.payments[0].assetId
11901255 let _assetIdStr = toBase58String(value(_assetId))
11911256 let isQuoteAsset = (_assetId == quoteAsset())
11921257 if (if (if (if (if (if (if (if (if (if ((_direction != DIR_LONG))
11931258 then (_direction != DIR_SHORT)
11941259 else false)
11951260 then true
11961261 else (0 >= _rawAmount))
11971262 then true
11981263 else !(initialized()))
11991264 then true
12001265 else !(isQuoteAsset))
12011266 then true
12021267 else !(isSameAssetOrNoPosition(_trader, _assetIdStr)))
12031268 then true
12041269 else !(requireMoreMarginRatio(divd(DECIMAL_UNIT, _leverage), initMarginRatio(), true)))
12051270 then true
12061271 else paused())
12071272 then true
12081273 else closeOnly())
12091274 then true
12101275 else isMarketClosed())
12111276 then throw("Invalid increasePosition parameters")
12121277 else {
1213- let $t05788858037 = getForTraderWithArtifact(_trader, getArtifactId(i))
1214- let adjustedFee = $t05788858037._1
1215- let burnArtifact = $t05788858037._2
1278+ let $t06231662465 = getForTraderWithArtifact(_trader, getArtifactId(i))
1279+ let adjustedFee = $t06231662465._1
1280+ let burnArtifact = $t06231662465._2
12161281 let _amount = divd(_rawAmount, (muld(adjustedFee, _leverage) + DECIMAL_UNIT))
12171282 let distributeFeeAmount = (_rawAmount - _amount)
12181283 let referrerFeeAny = invoke(referralAddress(), "acceptPaymentWithLink", [_trader, _refLink], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
12191284 if ((referrerFeeAny == referrerFeeAny))
12201285 then {
12211286 let referrerFee = match referrerFeeAny {
12221287 case x: Int =>
12231288 x
12241289 case _ =>
12251290 throw("Invalid referrerFee")
12261291 }
12271292 let feeAmount = (distributeFeeAmount - referrerFee)
1228- let $t05853358701 = getPosition(_trader)
1229- let oldPositionSize = $t05853358701._1
1230- let oldPositionMargin = $t05853358701._2
1231- let oldPositionOpenNotional = $t05853358701._3
1232- let oldPositionLstUpdCPF = $t05853358701._4
1233- let oldPositionTimestamp = $t05853358701._5
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
12341299 let isNewPosition = (oldPositionSize == 0)
12351300 let isSameDirection = if ((oldPositionSize > 0))
12361301 then (_direction == DIR_LONG)
12371302 else (_direction == DIR_SHORT)
12381303 let expandExisting = if (!(isNewPosition))
12391304 then isSameDirection
12401305 else false
12411306 let isAdd = (_direction == DIR_LONG)
1242- let $t05899062111 = if (if (isNewPosition)
1307+ let $t06341866539 = if (if (isNewPosition)
12431308 then true
12441309 else expandExisting)
12451310 then {
12461311 let openNotional = muld(_amount, _leverage)
1247- let $t05949959672 = swapInput(isAdd, openNotional)
1248- let amountBaseAssetBought = $t05949959672._1
1249- let quoteAssetReserveAfter = $t05949959672._2
1250- let baseAssetReserveAfter = $t05949959672._3
1251- let totalPositionSizeAfter = $t05949959672._4
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
12521317 if (if ((_minBaseAssetAmount != 0))
12531318 then (_minBaseAssetAmount > abs(amountBaseAssetBought))
12541319 else false)
12551320 then throw(((("Limit error: " + toString(abs(amountBaseAssetBought))) + " < ") + toString(_minBaseAssetAmount)))
12561321 else {
12571322 let newPositionSize = (oldPositionSize + amountBaseAssetBought)
12581323 let totalLongOpenInterestAfter = (openInterestLong() + (if ((newPositionSize > 0))
12591324 then openNotional
12601325 else 0))
12611326 let totalShortOpenInterestAfter = (openInterestShort() + (if ((0 > newPositionSize))
12621327 then openNotional
12631328 else 0))
1264- let $t06021860493 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, _amount)
1265- let remainMargin = $t06021860493._1
1266- let x1 = $t06021860493._2
1267- let x2 = $t06021860493._3
1268- let rolloverFee = $t06021860493._4
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
12691334 if (!(requireNotOverSpreadLimit(quoteAssetReserveAfter, baseAssetReserveAfter)))
12701335 then throw("Over max spread limit")
12711336 else if (!(requireNotOverMaxOpenNotional(totalLongOpenInterestAfter, totalShortOpenInterestAfter)))
12721337 then throw("Over max open notional")
12731338 else $Tuple14(newPositionSize, remainMargin, (oldPositionOpenNotional + openNotional), latestCumulativePremiumFraction(newPositionSize), lastTimestamp(), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, (openInterestNotional() + openNotional), (totalLongPositionSize() + (if ((newPositionSize > 0))
12741339 then abs(amountBaseAssetBought)
12751340 else 0)), (totalShortPositionSize() + (if ((0 > newPositionSize))
12761341 then abs(amountBaseAssetBought)
12771342 else 0)), totalLongOpenInterestAfter, totalShortOpenInterestAfter, rolloverFee)
12781343 }
12791344 }
12801345 else {
12811346 let openNotional = muld(_amount, _leverage)
1282- let $t06181161927 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1283- let oldPositionNotional = $t06181161927._1
1284- let unrealizedPnl = $t06181161927._2
1347+ let $t06623966355 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1348+ let oldPositionNotional = $t06623966355._1
1349+ let unrealizedPnl = $t06623966355._2
12851350 if ((oldPositionNotional > openNotional))
12861351 then throw("Use decreasePosition to decrease position size")
12871352 else throw("Close position first")
12881353 }
1289- let newPositionSize = $t05899062111._1
1290- let newPositionRemainMargin = $t05899062111._2
1291- let newPositionOpenNotional = $t05899062111._3
1292- let newPositionLatestCPF = $t05899062111._4
1293- let newPositionTimestamp = $t05899062111._5
1294- let baseAssetReserveAfter = $t05899062111._6
1295- let quoteAssetReserveAfter = $t05899062111._7
1296- let totalPositionSizeAfter = $t05899062111._8
1297- let openInterestNotionalAfter = $t05899062111._9
1298- let totalLongAfter = $t05899062111._10
1299- let totalShortAfter = $t05899062111._11
1300- let totalLongOpenInterestAfter = $t05899062111._12
1301- let totalShortOpenInterestAfter = $t05899062111._13
1302- let rolloverFee = $t05899062111._14
1303- let $t06211762188 = distributeFee((feeAmount + rolloverFee))
1304- let feeToStakers = $t06211762188._1
1305- let feeToVault = $t06211762188._2
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
13061371 let stake = if ((_amount >= rolloverFee))
13071372 then invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), (_amount - rolloverFee))])
13081373 else invoke(vaultAddress(), "withdrawLocked", [(rolloverFee - _amount)], nil)
13091374 if ((stake == stake))
13101375 then {
13111376 let depositVault = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
13121377 if ((depositVault == depositVault))
13131378 then {
13141379 let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, feeAmount], nil)
13151380 if ((notifyFee == notifyFee))
13161381 then {
13171382 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
13181383 if ((notifyNotional == notifyNotional))
13191384 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))
13201385 else throw("Strict value is not equal to itself.")
13211386 }
13221387 else throw("Strict value is not equal to itself.")
13231388 }
13241389 else throw("Strict value is not equal to itself.")
13251390 }
13261391 else throw("Strict value is not equal to itself.")
13271392 }
13281393 else throw("Strict value is not equal to itself.")
13291394 }
13301395 }
13311396 else throw("Strict value is not equal to itself.")
13321397 }
13331398 else throw("Strict value is not equal to itself.")
13341399 }
13351400
13361401
13371402
13381403 @Callable(i)
13391404 func addMargin () = {
13401405 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
13411406 if ((sync == sync))
13421407 then {
13431408 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
13441409 if ((ensureCalledOnce == ensureCalledOnce))
13451410 then {
13461411 let _trader = toString(i.caller)
13471412 let _amount = i.payments[0].amount
13481413 let _assetId = i.payments[0].assetId
13491414 let _assetIdStr = toBase58String(value(_assetId))
13501415 let isQuoteAsset = (_assetId == quoteAsset())
13511416 if (if (if (if (if (if (if (!(isQuoteAsset))
13521417 then true
13531418 else !(requireOpenPosition(toString(i.caller))))
13541419 then true
13551420 else !(isSameAsset(_trader, _assetIdStr)))
13561421 then true
13571422 else !(initialized()))
13581423 then true
13591424 else paused())
13601425 then true
13611426 else closeOnly())
13621427 then true
13631428 else isMarketClosed())
13641429 then throw("Invalid addMargin parameters")
13651430 else {
1366- let $t06429964467 = getPosition(_trader)
1367- let oldPositionSize = $t06429964467._1
1368- let oldPositionMargin = $t06429964467._2
1369- let oldPositionOpenNotional = $t06429964467._3
1370- let oldPositionLstUpdCPF = $t06429964467._4
1371- let oldPositionTimestamp = $t06429964467._5
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
13721437 let stake = invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), _amount)])
13731438 if ((stake == stake))
13741439 then {
13751440 let rolloverFee = calcRolloverFee(oldPositionMargin, oldPositionTimestamp)
13761441 let doTransferFeeToStakers = if ((rolloverFee > 0))
13771442 then {
1378- let $t06475264811 = distributeFee(rolloverFee)
1379- let feeToStakers = $t06475264811._1
1380- let feeToVault = $t06475264811._2
1443+ let $t06932669385 = distributeFee(rolloverFee)
1444+ let feeToStakers = $t06932669385._1
1445+ let feeToVault = $t06932669385._2
13811446 let unstake = invoke(vaultAddress(), "withdrawLocked", [feeToStakers], nil)
13821447 if ((unstake == unstake))
13831448 then {
13841449 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(feeToVault)], nil)
13851450 if ((lockBadDebt == lockBadDebt))
13861451 then transferFee(feeToStakers)
13871452 else throw("Strict value is not equal to itself.")
13881453 }
13891454 else throw("Strict value is not equal to itself.")
13901455 }
13911456 else nil
13921457 if ((doTransferFeeToStakers == doTransferFeeToStakers))
13931458 then ((updatePosition(_trader, oldPositionSize, ((oldPositionMargin - rolloverFee) + _amount), oldPositionOpenNotional, oldPositionLstUpdCPF, lastTimestamp()) ++ updateBalance(((cbalance() + _amount) - rolloverFee))) ++ doTransferFeeToStakers)
13941459 else throw("Strict value is not equal to itself.")
13951460 }
13961461 else throw("Strict value is not equal to itself.")
13971462 }
13981463 }
13991464 else throw("Strict value is not equal to itself.")
14001465 }
14011466 else throw("Strict value is not equal to itself.")
14021467 }
14031468
14041469
14051470
14061471 @Callable(i)
14071472 func removeMargin (_amount) = {
14081473 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
14091474 if ((sync == sync))
14101475 then {
14111476 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
14121477 if ((ensureCalledOnce == ensureCalledOnce))
14131478 then {
14141479 let _trader = toString(i.caller)
14151480 if (if (if (if (if ((0 >= _amount))
14161481 then true
14171482 else !(requireOpenPosition(_trader)))
14181483 then true
14191484 else !(initialized()))
14201485 then true
14211486 else paused())
14221487 then true
14231488 else isMarketClosed())
14241489 then throw("Invalid removeMargin parameters")
14251490 else {
1426- let $t06592366091 = getPosition(_trader)
1427- let oldPositionSize = $t06592366091._1
1428- let oldPositionMargin = $t06592366091._2
1429- let oldPositionOpenNotional = $t06592366091._3
1430- let oldPositionLstUpdCPF = $t06592366091._4
1431- let oldPositionTimestamp = $t06592366091._5
1432- let $t06609766346 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, -(_amount))
1433- let remainMargin = $t06609766346._1
1434- let badDebt = $t06609766346._2
1435- let fundingPayment = $t06609766346._3
1436- let rolloverFee = $t06609766346._4
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
14371502 if ((badDebt != 0))
14381503 then throw("Invalid removed margin amount")
14391504 else {
14401505 let marginRatio = calcMarginRatio(remainMargin, badDebt, oldPositionOpenNotional)
14411506 if (!(requireMoreMarginRatio(marginRatio, initMarginRatio(), true)))
14421507 then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
14431508 else {
1444- let $t06673266791 = distributeFee(rolloverFee)
1445- let feeToStakers = $t06673266791._1
1446- let feeToVault = $t06673266791._2
1509+ let $t07156771626 = distributeFee(rolloverFee)
1510+ let feeToStakers = $t07156771626._1
1511+ let feeToVault = $t07156771626._2
14471512 let doTransferFeeToStakers = if ((rolloverFee > 0))
14481513 then {
14491514 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(feeToVault)], nil)
14501515 if ((lockBadDebt == lockBadDebt))
14511516 then transferFee(feeToStakers)
14521517 else throw("Strict value is not equal to itself.")
14531518 }
14541519 else nil
14551520 if ((doTransferFeeToStakers == doTransferFeeToStakers))
14561521 then {
14571522 let unstake = invoke(vaultAddress(), "withdrawLocked", [(_amount + feeToStakers)], nil)
14581523 if ((unstake == unstake))
14591524 then (((updatePosition(_trader, oldPositionSize, remainMargin, oldPositionOpenNotional, latestCumulativePremiumFraction(oldPositionSize), lastTimestamp()) ++ withdraw(i.caller, _amount)) ++ updateBalance(((cbalance() - _amount) - rolloverFee))) ++ doTransferFeeToStakers)
14601525 else throw("Strict value is not equal to itself.")
14611526 }
14621527 else throw("Strict value is not equal to itself.")
14631528 }
14641529 }
14651530 }
14661531 }
14671532 else throw("Strict value is not equal to itself.")
14681533 }
14691534 else throw("Strict value is not equal to itself.")
14701535 }
14711536
14721537
14731538
14741539 @Callable(i)
14751540 func closePosition (_size,_minQuoteAssetAmount,_addToMargin) = {
14761541 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
14771542 if ((sync == sync))
14781543 then {
14791544 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
14801545 if ((ensureCalledOnce == ensureCalledOnce))
14811546 then {
14821547 let _trader = getActualCaller(i)
14831548 let _traderAddress = valueOrErrorMessage(addressFromString(_trader), "Invalid caller")
14841549 let positionFee = getPositionFee(_trader)
14851550 if (if (if (if (if (if (!(requireOpenPosition(_trader)))
14861551 then true
14871552 else !(initialized()))
14881553 then true
14891554 else paused())
14901555 then true
14911556 else (0 >= _size))
14921557 then true
14931558 else (0 > _minQuoteAssetAmount))
14941559 then true
14951560 else isMarketClosed())
14961561 then throw("Invalid closePosition parameters")
14971562 else {
14981563 let oldPositionTimestamp = getPosition(_trader)._5
1499- let $t06844869033 = internalClosePosition(_trader, _size, positionFee, _minQuoteAssetAmount, _addToMargin, true, true)
1500- let newPositionSize = $t06844869033._1
1501- let newPositionMargin = $t06844869033._2
1502- let newPositionOpenNotional = $t06844869033._3
1503- let newPositionLstUpdCPF = $t06844869033._4
1504- let positionBadDebt = $t06844869033._5
1505- let realizedPnl = $t06844869033._6
1506- let marginToTrader = $t06844869033._7
1507- let quoteAssetReserveAfter = $t06844869033._8
1508- let baseAssetReserveAfter = $t06844869033._9
1509- let totalPositionSizeAfter = $t06844869033._10
1510- let openInterestNotionalAfter = $t06844869033._11
1511- let totalLongAfter = $t06844869033._12
1512- let totalShortAfter = $t06844869033._13
1513- let totalLongOpenInterestAfter = $t06844869033._14
1514- let totalShortOpenInterestAfter = $t06844869033._15
1515- let realizedFee = $t06844869033._16
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
15161581 if ((positionBadDebt > 0))
15171582 then throw("Invalid closePosition parameters: bad debt")
15181583 else if ((oldPositionTimestamp >= lastTimestamp()))
15191584 then throw("Invalid closePosition parameters: wait at least 1 block before closing the position")
15201585 else {
15211586 let isPartialClose = (newPositionSize != 0)
15221587 let withdrawAmount = (marginToTrader + realizedFee)
15231588 let ammBalance = (cbalance() - withdrawAmount)
15241589 let ammNewBalance = if ((0 > ammBalance))
15251590 then 0
15261591 else ammBalance
15271592 let unstake = invoke(vaultAddress(), "withdrawLocked", [withdrawAmount], nil)
15281593 if ((unstake == unstake))
15291594 then {
1530- let $t06970569764 = distributeFee(realizedFee)
1531- let feeToStakers = $t06970569764._1
1532- let feeToVault = $t06970569764._2
1595+ let $t07505875117 = distributeFee(realizedFee)
1596+ let feeToStakers = $t07505875117._1
1597+ let feeToVault = $t07505875117._2
15331598 let depositVault = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
15341599 if ((depositVault == depositVault))
15351600 then {
15361601 let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, realizedFee], nil)
15371602 if ((notifyFee == notifyFee))
15381603 then {
15391604 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
15401605 if ((notifyNotional == notifyNotional))
15411606 then (((((if (isPartialClose)
15421607 then updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, lastTimestamp())
15431608 else deletePosition(_trader)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ (if ((marginToTrader > 0))
15441609 then withdraw(_traderAddress, marginToTrader)
15451610 else nil)) ++ updateBalance(ammNewBalance)) ++ transferFee(feeToStakers))
15461611 else throw("Strict value is not equal to itself.")
15471612 }
15481613 else throw("Strict value is not equal to itself.")
15491614 }
15501615 else throw("Strict value is not equal to itself.")
15511616 }
15521617 else throw("Strict value is not equal to itself.")
15531618 }
15541619 }
15551620 }
15561621 else throw("Strict value is not equal to itself.")
15571622 }
15581623 else throw("Strict value is not equal to itself.")
15591624 }
15601625
15611626
15621627
15631628 @Callable(i)
15641629 func liquidate (_trader) = {
15651630 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
15661631 if ((sync == sync))
15671632 then {
15681633 let spotMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
15691634 let liquidationMarginRatio = if (isOverFluctuationLimit())
15701635 then {
15711636 let oracleMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_ORACLE)
15721637 vmax(spotMarginRatio, oracleMarginRatio)
15731638 }
15741639 else spotMarginRatio
15751640 if (if (if (if (if (!(requireMoreMarginRatio(liquidationMarginRatio, maintenanceMarginRatio(), false)))
15761641 then true
15771642 else !(requireOpenPosition(_trader)))
15781643 then true
15791644 else !(initialized()))
15801645 then true
15811646 else paused())
15821647 then true
15831648 else isMarketClosed())
15841649 then throw("Unable to liquidate")
15851650 else {
15861651 let isPartialLiquidation = if (if ((spotMarginRatio > liquidationFeeRatio()))
15871652 then (partialLiquidationRatio() > 0)
15881653 else false)
15891654 then (DECIMAL_UNIT > partialLiquidationRatio())
15901655 else false
15911656 let oldPositionSize = getPosition(_trader)._1
15921657 let positionSizeAbs = abs(oldPositionSize)
1593- let $t07207772400 = if (isPartialLiquidation)
1658+ let $t07753877861 = if (isPartialLiquidation)
15941659 then {
15951660 let liquidationSize = getPartialLiquidationAmount(_trader, oldPositionSize)
15961661 let liquidationRatio = divd(abs(liquidationSize), positionSizeAbs)
15971662 $Tuple2(liquidationRatio, abs(liquidationSize))
15981663 }
15991664 else $Tuple2(0, positionSizeAbs)
1600- let liquidationRatio = $t07207772400._1
1601- let liquidationSize = $t07207772400._2
1602- let $t07240673044 = internalClosePosition(_trader, if (isPartialLiquidation)
1665+ let liquidationRatio = $t07753877861._1
1666+ let liquidationSize = $t07753877861._2
1667+ let $t07786778505 = internalClosePosition(_trader, if (isPartialLiquidation)
16031668 then liquidationSize
16041669 else positionSizeAbs, liquidationFeeRatio(), 0, true, false, true)
1605- let newPositionSize = $t07240673044._1
1606- let newPositionMargin = $t07240673044._2
1607- let newPositionOpenNotional = $t07240673044._3
1608- let newPositionLstUpdCPF = $t07240673044._4
1609- let positionBadDebt = $t07240673044._5
1610- let realizedPnl = $t07240673044._6
1611- let marginToTrader = $t07240673044._7
1612- let quoteAssetReserveAfter = $t07240673044._8
1613- let baseAssetReserveAfter = $t07240673044._9
1614- let totalPositionSizeAfter = $t07240673044._10
1615- let openInterestNotionalAfter = $t07240673044._11
1616- let totalLongAfter = $t07240673044._12
1617- let totalShortAfter = $t07240673044._13
1618- let totalLongOpenInterestAfter = $t07240673044._14
1619- let totalShortOpenInterestAfter = $t07240673044._15
1620- let liquidationPenalty = $t07240673044._16
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
16211686 let feeToLiquidator = (liquidationPenalty / 2)
16221687 let feeToVault = (liquidationPenalty - feeToLiquidator)
16231688 let ammBalance = (cbalance() - liquidationPenalty)
16241689 let newAmmBalance = if ((0 > ammBalance))
16251690 then 0
16261691 else ammBalance
16271692 let lockBadDebt = if ((positionBadDebt > 0))
16281693 then {
16291694 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [(positionBadDebt + liquidationPenalty)], nil)
16301695 if ((lockBadDebt == lockBadDebt))
16311696 then nil
16321697 else throw("Strict value is not equal to itself.")
16331698 }
16341699 else nil
16351700 if ((lockBadDebt == lockBadDebt))
16361701 then {
16371702 let unstake = invoke(vaultAddress(), "withdrawLocked", [liquidationPenalty], nil)
16381703 if ((unstake == unstake))
16391704 then {
16401705 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
16411706 if ((depositInsurance == depositInsurance))
16421707 then {
16431708 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
16441709 if ((notifyNotional == notifyNotional))
16451710 then ((((if (isPartialLiquidation)
16461711 then updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, lastTimestamp())
16471712 else deletePosition(_trader)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ withdraw(i.caller, feeToLiquidator)) ++ updateBalance(newAmmBalance))
16481713 else throw("Strict value is not equal to itself.")
16491714 }
16501715 else throw("Strict value is not equal to itself.")
16511716 }
16521717 else throw("Strict value is not equal to itself.")
16531718 }
16541719 else throw("Strict value is not equal to itself.")
16551720 }
16561721 }
16571722 else throw("Strict value is not equal to itself.")
16581723 }
16591724
16601725
16611726
16621727 @Callable(i)
16631728 func payFunding () = {
16641729 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
16651730 if ((sync == sync))
16661731 then {
16671732 let fundingBlockTimestamp = nextFundingBlockTimestamp()
16681733 if (if (if ((fundingBlockTimestamp > lastTimestamp()))
16691734 then true
16701735 else !(initialized()))
16711736 then true
16721737 else paused())
16731738 then throw(((("Invalid funding block timestamp: " + toString(lastTimestamp())) + " < ") + toString(fundingBlockTimestamp)))
16741739 else {
16751740 let underlyingPrice = getOraclePrice()
1676- let $t07503175093 = getFunding()
1677- let shortPremiumFraction = $t07503175093._1
1678- let longPremiumFraction = $t07503175093._2
1679- updateFunding((fundingBlockTimestamp + fundingPeriodSeconds()), (latestLongCumulativePremiumFraction() + longPremiumFraction), (latestShortCumulativePremiumFraction() + shortPremiumFraction), divd(longPremiumFraction, underlyingPrice), divd(shortPremiumFraction, underlyingPrice))
1741+ let $t08061880696 = getFunding()
1742+ let shortPremiumFraction = $t08061880696._1
1743+ let longPremiumFraction = $t08061880696._2
1744+ let premiumToVault = $t08061880696._3
1745+ let doPayFundingToVault = if ((premiumToVault > 0))
1746+ then {
1747+ let doPayFundingToVault = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(premiumToVault)], nil)
1748+ if ((doPayFundingToVault == doPayFundingToVault))
1749+ then nil
1750+ else throw("Strict value is not equal to itself.")
1751+ }
1752+ else nil
1753+ if ((doPayFundingToVault == doPayFundingToVault))
1754+ then updateFunding((fundingBlockTimestamp + fundingPeriodSeconds()), (latestLongCumulativePremiumFraction() + longPremiumFraction), (latestShortCumulativePremiumFraction() + shortPremiumFraction), divd(longPremiumFraction, underlyingPrice), divd(shortPremiumFraction, underlyingPrice))
1755+ else throw("Strict value is not equal to itself.")
16801756 }
16811757 }
16821758 else throw("Strict value is not equal to itself.")
16831759 }
16841760
16851761
16861762
16871763 @Callable(i)
16881764 func syncTerminalPriceToOracle () = {
16891765 let _qtAstR = qtAstR()
16901766 let _bsAstR = bsAstR()
1691- let $t07552575891 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1692- let newQuoteAssetWeight = $t07552575891._1
1693- let newBaseAssetWeight = $t07552575891._2
1694- let marginToVault = $t07552575891._3
1767+ let $t08174782113 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1768+ let newQuoteAssetWeight = $t08174782113._1
1769+ let newBaseAssetWeight = $t08174782113._2
1770+ let marginToVault = $t08174782113._3
16951771 let marginToVaultAdj = if (if ((0 > marginToVault))
16961772 then (abs(marginToVault) > cbalance())
16971773 else false)
16981774 then -(cbalance())
16991775 else marginToVault
17001776 let doExchangePnL = if ((marginToVaultAdj != 0))
17011777 then {
17021778 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVaultAdj], nil)
17031779 if ((doExchangePnL == doExchangePnL))
17041780 then nil
17051781 else throw("Strict value is not equal to itself.")
17061782 }
17071783 else nil
17081784 if ((doExchangePnL == doExchangePnL))
17091785 then ((updateBalance((cbalance() + marginToVaultAdj)) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight)) ++ appendTwap(divd(muld(_qtAstR, newQuoteAssetWeight), muld(_bsAstR, newBaseAssetWeight))))
17101786 else throw("Strict value is not equal to itself.")
17111787 }
17121788
17131789
17141790
17151791 @Callable(i)
17161792 func ensureCalledOnce () = if ((i.caller != this))
17171793 then throw("Invalid saveCurrentTxId parameters")
17181794 else {
17191795 let lastTx = valueOrElse(getString(this, k_lastTx), "")
17201796 if ((lastTx != toBase58String(i.transactionId)))
17211797 then [StringEntry(k_lastTx, lastTx)]
17221798 else throw("Can not call vAMM methods twice in one tx")
17231799 }
17241800
17251801
17261802
17271803 @Callable(i)
17281804 func view_calcRemainMarginWithFundingPayment (_trader) = {
17291805 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
17301806 if ((sync == sync))
17311807 then {
1732- let $t07705077174 = getPosition(_trader)
1733- let positionSize = $t07705077174._1
1734- let positionMargin = $t07705077174._2
1735- let pon = $t07705077174._3
1736- let positionLstUpdCPF = $t07705077174._4
1737- let positionTimestamp = $t07705077174._5
1738- let $t07717777278 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1739- let positionNotional = $t07717777278._1
1740- let unrealizedPnl = $t07717777278._2
1741- let $t07728177505 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLstUpdCPF, positionTimestamp, unrealizedPnl)
1742- let remainMargin = $t07728177505._1
1743- let badDebt = $t07728177505._2
1744- let fundingPayment = $t07728177505._3
1745- let rolloverFee = $t07728177505._4
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
17461822 throw(((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)) + s(rolloverFee)))
17471823 }
17481824 else throw("Strict value is not equal to itself.")
17491825 }
17501826
17511827
17521828
17531829 @Callable(i)
17541830 func view_getPegAdjustCost (_price) = {
17551831 let _qtAstR = qtAstR()
17561832 let _bsAstR = bsAstR()
17571833 let result = getSyncTerminalPrice(_price, _qtAstR, _bsAstR)
17581834 throw(toString(result._3))
17591835 }
17601836
17611837
17621838
17631839 @Callable(i)
17641840 func view_getTerminalAmmPrice () = {
1765- let $t07794178022 = getTerminalAmmState()
1766- let terminalQuoteAssetReserve = $t07794178022._1
1767- let terminalBaseAssetReserve = $t07794178022._2
1841+ let $t08493385014 = getTerminalAmmState()
1842+ let terminalQuoteAssetReserve = $t08493385014._1
1843+ let terminalBaseAssetReserve = $t08493385014._2
17681844 let price = divd(muld(terminalQuoteAssetReserve, qtAstW()), muld(terminalBaseAssetReserve, bsAstW()))
17691845 throw(toString(price))
17701846 }
17711847
17721848
17731849
17741850 @Callable(i)
17751851 func view_getFunding () = {
17761852 let underlyingPrice = getOraclePrice()
1777- let $t07823778299 = getFunding()
1778- let shortPremiumFraction = $t07823778299._1
1779- let longPremiumFraction = $t07823778299._2
1853+ let $t08552385601 = getFunding()
1854+ let shortPremiumFraction = $t08552385601._1
1855+ let longPremiumFraction = $t08552385601._2
1856+ let premiumToVault = $t08552385601._3
17801857 let longFunding = divd(longPremiumFraction, underlyingPrice)
17811858 let shortFunding = divd(shortPremiumFraction, underlyingPrice)
1782- throw((((s(longFunding) + s(shortFunding)) + s(getTwapSpotPrice())) + s(getOraclePrice())))
1859+ throw(((((s(longFunding) + s(shortFunding)) + s(getTwapSpotPrice())) + s(getOraclePrice())) + s(premiumToVault)))
17831860 }
17841861
17851862
17861863
17871864 @Callable(i)
17881865 func computeSpotPrice () = {
17891866 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
17901867 if ((sync == sync))
17911868 then {
17921869 let result = getSpotPrice()
17931870 $Tuple2(nil, result)
17941871 }
17951872 else throw("Strict value is not equal to itself.")
17961873 }
17971874
17981875
17991876
18001877 @Callable(i)
18011878 func computeFeeForTraderWithArtifact (_trader,_artifactId) = {
18021879 let result = getForTraderWithArtifact(_trader, _artifactId)
18031880 $Tuple2(nil, result)
18041881 }
18051882
18061883
18071884 @Verifier(tx)
18081885 func verify () = {
18091886 let coordinatorStr = getString(this, k_coordinatorAddress)
18101887 if (isDefined(coordinatorStr))
18111888 then {
18121889 let admin = getString(addressFromStringValue(value(coordinatorStr)), k_admin_address)
18131890 if (isDefined(admin))
18141891 then valueOrElse(getBoolean(addressFromStringValue(value(admin)), ((("status_" + toString(this)) + "_") + toBase58String(tx.id))), false)
18151892 else throw("unable to verify: admin not set in coordinator")
18161893 }
18171894 else sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
18181895 }
18191896

github/deemru/w8io/873ac7e 
362.81 ms