tx · BqgcsxZFQspmbhFxhzRiwzy2x6TAYis5Se4XQJEGK7pL

3N4SpfepyNLLb4Uc8e3xvkZew64HMcZ23oX:  -0.07500000 Waves

2023.02.11 09:49 [2444617] smart account 3N4SpfepyNLLb4Uc8e3xvkZew64HMcZ23oX > SELF 0.00000000 Waves

{ "type": 13, "id": "BqgcsxZFQspmbhFxhzRiwzy2x6TAYis5Se4XQJEGK7pL", "fee": 7500000, "feeAssetId": null, "timestamp": 1676098180697, "version": 2, "chainId": 84, "sender": "3N4SpfepyNLLb4Uc8e3xvkZew64HMcZ23oX", "senderPublicKey": "Gqr4yqnGvyo3GmKz59Qs1qfyDm5XhT134DCjiBhmD8jW", "proofs": [ "53vZNXvbtg44QSuruPg6qRDyxWxQKuNYdSYWX2wnLYL6j9sehEWeuAxmHYAAXtDMbVHgMcJEeAkH6K6mmPLD3u4K" ], "script": "base64:BgJyCAISABIAEgASABIDCgEBEgMKAQESDwoNAQEBAQEBAQEBAQEBARIUChIBAQEBAQEBCAgIAQEBAQEBAQESBgoEAQEBCBIAEgMKAQESBQoDAQEEEgMKAQgSABIAEgASAwoBCBIDCgEBEgASABIAEgQKAggIvAEADGtfYmFzZU9yYWNsZQIMa19iYXNlT3JhY2xlAA1rX3F1b3RlT3JhY2xlAg1rX3F1b3RlT3JhY2xlAAlrX2JhbGFuY2UCCWtfYmFsYW5jZQAKa19zZXF1ZW5jZQIKa19zZXF1ZW5jZQAOa19wb3NpdGlvblNpemUCDmtfcG9zaXRpb25TaXplABBrX3Bvc2l0aW9uTWFyZ2luAhBrX3Bvc2l0aW9uTWFyZ2luABZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsAhZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsAC5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAhJrX3Bvc2l0aW9uRnJhY3Rpb24AEmtfcG9zaXRpb25TZXF1ZW5jZQISa19wb3NpdGlvblNlcXVlbmNlAA9rX3Bvc2l0aW9uQXNzZXQCD2tfcG9zaXRpb25Bc3NldAANa19wb3NpdGlvbkZlZQINa19wb3NpdGlvbkZlZQAea19wb3NpdGlvbkxhc3RVcGRhdGVkVGltZXN0YW1wAhNrX3Bvc2l0aW9uVGltZXN0YW1wAA1rX2luaXRpYWxpemVkAg1rX2luaXRpYWxpemVkAAhrX3BhdXNlZAIIa19wYXVzZWQAC2tfY2xvc2VPbmx5AgtrX2Nsb3NlT25seQAFa19mZWUCBWtfZmVlAA1rX3JvbGxvdmVyRmVlAg5rX3JvbGxvdmVyX2ZlZQAPa19mdW5kaW5nUGVyaW9kAg9rX2Z1bmRpbmdQZXJpb2QAEWtfaW5pdE1hcmdpblJhdGlvAhFrX2luaXRNYXJnaW5SYXRpbwAYa19tYWludGVuYW5jZU1hcmdpblJhdGlvAgVrX21tcgAVa19saXF1aWRhdGlvbkZlZVJhdGlvAhVrX2xpcXVpZGF0aW9uRmVlUmF0aW8AGWtfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8CFmtfcGFydExpcXVpZGF0aW9uUmF0aW8ADWtfc3ByZWFkTGltaXQCDWtfc3ByZWFkTGltaXQAEGtfbWF4UHJpY2VJbXBhY3QCEGtfbWF4UHJpY2VJbXBhY3QAEGtfbWF4UHJpY2VTcHJlYWQCEGtfbWF4UHJpY2VTcHJlYWQAEWtfbWF4T3Blbk5vdGlvbmFsAhFrX21heE9wZW5Ob3Rpb25hbAAVa19mZWVUb1N0YWtlcnNQZXJjZW50AhVrX2ZlZVRvU3Rha2Vyc1BlcmNlbnQAEGtfbWF4T3JhY2xlRGVsYXkCEGtfbWF4T3JhY2xlRGVsYXkADWtfbGFzdERhdGFTdHICDWtfbGFzdERhdGFTdHIADmtfbGFzdE1pbnV0ZUlkAg5rX2xhc3RNaW51dGVJZAAda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UCHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlABNrX3R3YXBEYXRhTGFzdFByaWNlAhNrX3R3YXBEYXRhTGFzdFByaWNlABprX3R3YXBEYXRhUHJldmlvdXNNaW51dGVJZAIaa190d2FwRGF0YVByZXZpb3VzTWludXRlSWQAJWtfbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24CG2tfbGF0ZXN0TG9uZ1ByZW1pdW1GcmFjdGlvbgAma19sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24CHGtfbGF0ZXN0U2hvcnRQcmVtaXVtRnJhY3Rpb24AEmtfbmV4dEZ1bmRpbmdCbG9jawIea19uZXh0RnVuZGluZ0Jsb2NrTWluVGltZXN0YW1wABFrX2xvbmdGdW5kaW5nUmF0ZQIRa19sb25nRnVuZGluZ1JhdGUAEmtfc2hvcnRGdW5kaW5nUmF0ZQISa19zaG9ydEZ1bmRpbmdSYXRlABNrX3F1b3RlQXNzZXRSZXNlcnZlAghrX3F0QXN0UgASa19iYXNlQXNzZXRSZXNlcnZlAghrX2JzQXN0UgASa19xdW90ZUFzc2V0V2VpZ2h0AghrX3F0QXN0VwARa19iYXNlQXNzZXRXZWlnaHQCCGtfYnNBc3RXABNrX3RvdGFsUG9zaXRpb25TaXplAhNrX3RvdGFsUG9zaXRpb25TaXplABdrX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQIXa190b3RhbExvbmdQb3NpdGlvblNpemUAGGtfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQIYa190b3RhbFNob3J0UG9zaXRpb25TaXplABZrX29wZW5JbnRlcmVzdE5vdGlvbmFsAhZrX29wZW5JbnRlcmVzdE5vdGlvbmFsABNrX29wZW5JbnRlcmVzdFNob3J0AhNrX29wZW5JbnRlcmVzdFNob3J0ABJrX29wZW5JbnRlcmVzdExvbmcCEmtfb3BlbkludGVyZXN0TG9uZwAIa19sYXN0VHgCCGtfbGFzdFR4ABRrX2Nvb3JkaW5hdG9yQWRkcmVzcwIUa19jb29yZGluYXRvckFkZHJlc3MAD2tfdmF1bHRfYWRkcmVzcwIPa192YXVsdF9hZGRyZXNzAA9rX2FkbWluX2FkZHJlc3MCD2tfYWRtaW5fYWRkcmVzcwANa19xdW90ZV9hc3NldAINa19xdW90ZV9hc3NldAAPa19xdW90ZV9zdGFraW5nAg9rX3F1b3RlX3N0YWtpbmcAEWtfc3Rha2luZ19hZGRyZXNzAhFrX3N0YWtpbmdfYWRkcmVzcwAPa19taW5lcl9hZGRyZXNzAg9rX21pbmVyX2FkZHJlc3MAEGtfb3JkZXJzX2FkZHJlc3MCEGtfb3JkZXJzX2FkZHJlc3MAEmtfcmVmZXJyYWxfYWRkcmVzcwISa19yZWZlcnJhbF9hZGRyZXNzABJrX2V4Y2hhbmdlX2FkZHJlc3MCEmtfZXhjaGFuZ2VfYWRkcmVzcwAVa19uZnRfbWFuYWdlcl9hZGRyZXNzAhVrX25mdF9tYW5hZ2VyX2FkZHJlc3MBDnRvQ29tcG9zaXRlS2V5AgRfa2V5CF9hZGRyZXNzCQCsAgIJAKwCAgUEX2tleQIBXwUIX2FkZHJlc3MBC2Nvb3JkaW5hdG9yAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIFBHRoaXMFFGtfY29vcmRpbmF0b3JBZGRyZXNzAhNDb29yZGluYXRvciBub3Qgc2V0AQxhZG1pbkFkZHJlc3MACQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFD2tfYWRtaW5fYWRkcmVzcwEKcXVvdGVBc3NldAAJANkEAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUNa19xdW90ZV9hc3NldAERcXVvdGVBc3NldFN0YWtpbmcACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUPa19xdW90ZV9zdGFraW5nAhtRdW90ZSBhc3NldCBzdGFraW5nIG5vdCBzZXQBDnN0YWtpbmdBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFEWtfc3Rha2luZ19hZGRyZXNzAg9TdGFraW5nIG5vdCBzZXQBDHZhdWx0QWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABQ9rX3ZhdWx0X2FkZHJlc3MCDVZhdWx0IG5vdCBzZXQBDG1pbmVyQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABQ9rX21pbmVyX2FkZHJlc3MCDU1pbmVyIG5vdCBzZXQBDW9yZGVyc0FkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUQa19vcmRlcnNfYWRkcmVzcwIOT3JkZXJzIG5vdCBzZXQBD3JlZmVycmFsQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABRJrX3JlZmVycmFsX2FkZHJlc3MCEFJlZmVycmFsIG5vdCBzZXQBEW5mdE1hbmFnZXJBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFFWtfbmZ0X21hbmFnZXJfYWRkcmVzcwITTkZUIE1hbmFnZXIgbm90IHNldAANa190b2tlbl9wYXJhbQINa190b2tlbl9wYXJhbQAMa190b2tlbl90eXBlAgxrX3Rva2VuX3R5cGUAGEZFRV9SRURVQ1RJT05fVE9LRU5fVFlQRQINZmVlX3JlZHVjdGlvbgAIRElSX0xPTkcAAQAJRElSX1NIT1JUAAIADVRXQVBfSU5URVJWQUwADwAHU0VDT05EUwDoBwAPREVDSU1BTF9OVU1CRVJTAAYADERFQ0lNQUxfVU5JVAkAaAIAAQkAaAIJAGgCCQBoAgkAaAIJAGgCAAoACgAKAAoACgAKAA9NSU5VVEVTX0lOX1lFQVIJAGgCAKCKIAUMREVDSU1BTF9VTklUAAdPTkVfREFZCQBoAgCAowUFDERFQ0lNQUxfVU5JVAAPUE5MX09QVElPTl9TUE9UAAEAEVBOTF9PUFRJT05fT1JBQ0xFAAIBAXMBAl94CQCsAgIJAKQDAQUCX3gCASwBBGRpdmQCAl94Al95CQBuBAUCX3gFDERFQ0lNQUxfVU5JVAUCX3kFCEhBTEZFVkVOAQRtdWxkAgJfeAJfeQkAbgQFAl94BQJfeQUMREVDSU1BTF9VTklUBQhIQUxGRVZFTgEFYmRpdmQCAl94Al95CQC9AgQFAl94CQC2AgEFDERFQ0lNQUxfVU5JVAUCX3kFCEhBTEZFVkVOAQVibXVsZAICX3gCX3kJAL0CBAUCX3gFAl95CQC2AgEFDERFQ0lNQUxfVU5JVAUISEFMRkVWRU4BA2FicwECX3gDCQBmAgUCX3gAAAUCX3gJAQEtAQUCX3gBBHZtYXgCAl94Al95AwkAZwIFAl94BQJfeQUCX3gFAl95AQlsaXN0VG9TdHIBBV9saXN0AwkAAAIJAJADAQUFX2xpc3QAAAIACQC5CQIFBV9saXN0AgEsAQlzdHJUb0xpc3QBBF9zdHIDCQAAAgUEX3N0cgIABQNuaWwJALUJAgUEX3N0cgIBLAELcHVzaFRvUXVldWUDBV9saXN0CF9tYXhTaXplBl92YWx1ZQMJAGYCCQCQAwEFBV9saXN0BQhfbWF4U2l6ZQkAzQgCCQDRCAIFBV9saXN0AAAFBl92YWx1ZQkAzQgCBQVfbGlzdAUGX3ZhbHVlAQNpbnQBAWsJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQR0aGlzBQFrCQCsAgICDW5vIHZhbHVlIGZvciAFAWsBBWludE9yAgFrA2RlZgkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQFrBQNkZWYBBHN0ckECCF9hZGRyZXNzBF9rZXkEA3ZhbAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFCF9hZGRyZXNzBQRfa2V5CQCsAgICEU5vIHZhbHVlIGZvciBrZXkgBQRfa2V5BQN2YWwBBGludEECCF9hZGRyZXNzBF9rZXkEA3ZhbAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFCF9hZGRyZXNzBQRfa2V5CQCsAgICEU5vIHZhbHVlIGZvciBrZXkgBQRfa2V5BQN2YWwBCGNiYWxhbmNlAAkBA2ludAEFCWtfYmFsYW5jZQEDZmVlAAkBA2ludAEFBWtfZmVlAQ9yb2xsb3ZlckZlZVJhdGUACQEDaW50AQUNa19yb2xsb3ZlckZlZQEPaW5pdE1hcmdpblJhdGlvAAkBA2ludAEFEWtfaW5pdE1hcmdpblJhdGlvAQZxdEFzdFIACQEDaW50AQUTa19xdW90ZUFzc2V0UmVzZXJ2ZQEGYnNBc3RSAAkBA2ludAEFEmtfYmFzZUFzc2V0UmVzZXJ2ZQEGcXRBc3RXAAkBBWludE9yAgUSa19xdW90ZUFzc2V0V2VpZ2h0BQxERUNJTUFMX1VOSVQBBmJzQXN0VwAJAQVpbnRPcgIFEWtfYmFzZUFzc2V0V2VpZ2h0BQxERUNJTUFMX1VOSVQBEXRvdGFsUG9zaXRpb25TaXplAAkBA2ludAEFE2tfdG90YWxQb3NpdGlvblNpemUBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAAkBA2ludAEFFmtfb3BlbkludGVyZXN0Tm90aW9uYWwBEW9wZW5JbnRlcmVzdFNob3J0AAkBA2ludAEFE2tfb3BlbkludGVyZXN0U2hvcnQBEG9wZW5JbnRlcmVzdExvbmcACQEDaW50AQUSa19vcGVuSW50ZXJlc3RMb25nARluZXh0RnVuZGluZ0Jsb2NrVGltZXN0YW1wAAkBA2ludAEFEmtfbmV4dEZ1bmRpbmdCbG9jawEQZnVuZGluZ1BlcmlvZFJhdwAJAQNpbnQBBQ9rX2Z1bmRpbmdQZXJpb2QBFGZ1bmRpbmdQZXJpb2REZWNpbWFsAAkAaAIJARBmdW5kaW5nUGVyaW9kUmF3AAUMREVDSU1BTF9VTklUARRmdW5kaW5nUGVyaW9kU2Vjb25kcwAJAGgCCQEQZnVuZGluZ1BlcmlvZFJhdwAFB1NFQ09ORFMBFm1haW50ZW5hbmNlTWFyZ2luUmF0aW8ACQEDaW50AQUYa19tYWludGVuYW5jZU1hcmdpblJhdGlvARNsaXF1aWRhdGlvbkZlZVJhdGlvAAkBA2ludAEFFWtfbGlxdWlkYXRpb25GZWVSYXRpbwEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8ACQEDaW50AQUZa19wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwELc3ByZWFkTGltaXQACQEDaW50AQUNa19zcHJlYWRMaW1pdAEObWF4UHJpY2VJbXBhY3QACQEDaW50AQUQa19tYXhQcmljZUltcGFjdAEObWF4UHJpY2VTcHJlYWQACQEDaW50AQUQa19tYXhQcmljZVNwcmVhZAEPbWF4T3Blbk5vdGlvbmFsAAkBA2ludAEFEWtfbWF4T3Blbk5vdGlvbmFsASNsYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAJAQNpbnQBBSVrX2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uASRsYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24ACQEDaW50AQUma19sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BFnRvdGFsU2hvcnRQb3NpdGlvblNpemUACQEDaW50AQUYa190b3RhbFNob3J0UG9zaXRpb25TaXplARV0b3RhbExvbmdQb3NpdGlvblNpemUACQEDaW50AQUXa190b3RhbExvbmdQb3NpdGlvblNpemUBDGxhc3RTZXF1ZW5jZQAJAQVpbnRPcgIFCmtfc2VxdWVuY2UAAAETZmVlVG9TdGFrZXJzUGVyY2VudAAJAQNpbnQBBRVrX2ZlZVRvU3Rha2Vyc1BlcmNlbnQBDm1heE9yYWNsZURlbGF5AAkBA2ludAEFEGtfbWF4T3JhY2xlRGVsYXkBDWxhc3RUaW1lc3RhbXAACAUJbGFzdEJsb2NrCXRpbWVzdGFtcAEPZ2V0QWN0dWFsQ2FsbGVyAQFpCQELdmFsdWVPckVsc2UCCQCdCAIJAQ1vcmRlcnNBZGRyZXNzAAIIa19zZW5kZXIJAKUIAQgFAWkGY2FsbGVyARZyZXF1aXJlTW9yZU1hcmdpblJhdGlvAwxfbWFyZ2luUmF0aW8QX2Jhc2VNYXJnaW5SYXRpbxRfbGFyZ2VyVGhhbk9yRXF1YWxUbwQUcmVtYWluaW5nTWFyZ2luUmF0aW8JAGUCBQxfbWFyZ2luUmF0aW8FEF9iYXNlTWFyZ2luUmF0aW8DAwUUX2xhcmdlclRoYW5PckVxdWFsVG8JAGYCAAAFFHJlbWFpbmluZ01hcmdpblJhdGlvBwkAAgEJAKwCAgkArAICCQCsAgICEEludmFsaWQgbWFyZ2luOiAJAKQDAQUMX21hcmdpblJhdGlvAgMgPCAJAKQDAQUQX2Jhc2VNYXJnaW5SYXRpbwMDCQEBIQEFFF9sYXJnZXJUaGFuT3JFcXVhbFRvCQBnAgUUcmVtYWluaW5nTWFyZ2luUmF0aW8AAAcJAAIBCQCsAgIJAKwCAgkArAICAhBJbnZhbGlkIG1hcmdpbjogCQCkAwEFDF9tYXJnaW5SYXRpbwIDID4gCQCkAwEFEF9iYXNlTWFyZ2luUmF0aW8GAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQ1fcG9zaXRpb25TaXplAwkAAAIFDV9wb3NpdGlvblNpemUAAAkAAgECLFNob3VsZCBub3QgYmUgY2FsbGVkIHdpdGggX3Bvc2l0aW9uU2l6ZSA9PSAwAwkAZgIFDV9wb3NpdGlvblNpemUAAAkBI2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAkBJGxhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgABC2dldFBvc2l0aW9uAQdfdHJhZGVyBA9wb3NpdGlvblNpemVPcHQJAJoIAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUOa19wb3NpdGlvblNpemUFB190cmFkZXIEByRtYXRjaDAFD3Bvc2l0aW9uU2l6ZU9wdAMJAAECBQckbWF0Y2gwAgNJbnQEDHBvc2l0aW9uU2l6ZQUHJG1hdGNoMAkAlwoFBQxwb3NpdGlvblNpemUJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFEGtfcG9zaXRpb25NYXJnaW4FB190cmFkZXIJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFFmtfcG9zaXRpb25PcGVuTm90aW9uYWwFB190cmFkZXIJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFLmtfcG9zaXRpb25MYXN0VXBkYXRlZEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FB190cmFkZXIJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFHmtfcG9zaXRpb25MYXN0VXBkYXRlZFRpbWVzdGFtcAUHX3RyYWRlcgkAlwoFAAAAAAAAAAAAAAEQZ2V0UG9zaXRpb25Bc3NldAEHX3RyYWRlcgQQcG9zaXRpb25Bc3NldE9wdAkAnQgCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBQ9rX3Bvc2l0aW9uQXNzZXQFB190cmFkZXIEByRtYXRjaDAFEHBvc2l0aW9uQXNzZXRPcHQDCQABAgUHJG1hdGNoMAIGU3RyaW5nBA1wb3NpdGlvbkFzc2V0BQckbWF0Y2gwBQ1wb3NpdGlvbkFzc2V0CQDYBAEJAQpxdW90ZUFzc2V0AAEOZ2V0UG9zaXRpb25GZWUBB190cmFkZXIEDnBvc2l0aW9uRmVlT3B0CQCaCAIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFDWtfcG9zaXRpb25GZWUFB190cmFkZXIEByRtYXRjaDAFDnBvc2l0aW9uRmVlT3B0AwkAAQIFByRtYXRjaDACA0ludAQLcG9zaXRpb25GZWUFByRtYXRjaDAFC3Bvc2l0aW9uRmVlCQEDZmVlAAETcmVxdWlyZU9wZW5Qb3NpdGlvbgEHX3RyYWRlcgMJAAACCAkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgJfMQAACQACAQIQTm8gb3BlbiBwb3NpdGlvbgYBDWdldE9yYWNsZURhdGEBA2tleQQNb3JhY2xlRGF0YVN0cgkAnQgCBQR0aGlzBQNrZXkDAwkBCWlzRGVmaW5lZAEFDW9yYWNsZURhdGFTdHIJAQIhPQIJAQV2YWx1ZQEFDW9yYWNsZURhdGFTdHICAAcECm9yYWNsZURhdGEJALUJAgkBBXZhbHVlAQUNb3JhY2xlRGF0YVN0cgIBLAQNb3JhY2xlQWRkcmVzcwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJAJEDAgUKb3JhY2xlRGF0YQAACQCsAgICG0ludmFsaWQgb3JhY2xlIGFkZHJlc3MgaW46IAkBBXZhbHVlAQUNb3JhY2xlRGF0YVN0cgQIcHJpY2VLZXkJAJEDAgUKb3JhY2xlRGF0YQABBAhibG9ja0tleQkAkQMCBQpvcmFjbGVEYXRhAAIEB29wZW5LZXkJAJEDAgUKb3JhY2xlRGF0YQADCQCWCgQFDW9yYWNsZUFkZHJlc3MFCHByaWNlS2V5BQhibG9ja0tleQUHb3BlbktleQUEdW5pdAELaW5pdGlhbGl6ZWQACQELdmFsdWVPckVsc2UCCQCbCAIFBHRoaXMFDWtfaW5pdGlhbGl6ZWQHAQZwYXVzZWQACQELdmFsdWVPckVsc2UCCQCbCAIFBHRoaXMFCGtfcGF1c2VkBwEJY2xvc2VPbmx5AAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzBQtrX2Nsb3NlT25seQcBDXVwZGF0ZVJlc2VydmUDBl9pc0FkZBFfcXVvdGVBc3NldEFtb3VudBBfYmFzZUFzc2V0QW1vdW50AwUGX2lzQWRkBAduZXdCYXNlCQBlAgkBBmJzQXN0UgAFEF9iYXNlQXNzZXRBbW91bnQDCQBnAgAABQduZXdCYXNlCQACAQIqVHggbGVhZCB0byBiYXNlIGFzc2V0IHJlc2VydmUgPD0gMCwgcmV2ZXJ0CQCVCgMJAGQCCQEGcXRBc3RSAAURX3F1b3RlQXNzZXRBbW91bnQFB25ld0Jhc2UJAGQCCQERdG90YWxQb3NpdGlvblNpemUABRBfYmFzZUFzc2V0QW1vdW50BAhuZXdRdW90ZQkAZQIJAQZxdEFzdFIABRFfcXVvdGVBc3NldEFtb3VudAMJAGcCAAAFCG5ld1F1b3RlCQACAQIqVHggbGVhZCB0byBiYXNlIHF1b3RlIHJlc2VydmUgPD0gMCwgcmV2ZXJ0CQCVCgMFCG5ld1F1b3RlCQBkAgkBBmJzQXN0UgAFEF9iYXNlQXNzZXRBbW91bnQJAGUCCQERdG90YWxQb3NpdGlvblNpemUABRBfYmFzZUFzc2V0QW1vdW50AQ1jYWxjSW52YXJpYW50AgdfcXRBc3RSB19ic0FzdFIEB2JxdEFzdFIJALYCAQUHX3F0QXN0UgQHYmJzQXN0UgkAtgIBBQdfYnNBc3RSCQEFYm11bGQCBQdicXRBc3RSBQdiYnNBc3RSAQlzd2FwSW5wdXQCBl9pc0FkZBFfcXVvdGVBc3NldEFtb3VudAQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwAEGHF1b3RlQXNzZXRBbW91bnRBZGp1c3RlZAkBBGRpdmQCBRFfcXVvdGVBc3NldEFtb3VudAUHX3F0QXN0VwQBawkBDWNhbGNJbnZhcmlhbnQCBQdfcXRBc3RSBQdfYnNBc3RSBBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyAwUGX2lzQWRkCQBkAgUHX3F0QXN0UgUYcXVvdGVBc3NldEFtb3VudEFkanVzdGVkCQBlAgUHX3F0QXN0UgUYcXVvdGVBc3NldEFtb3VudEFkanVzdGVkBBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIJAKADAQkBBWJkaXZkAgUBawkAtgIBBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBBhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMJAQNhYnMBCQBlAgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBQdfYnNBc3RSBBVhbW91bnRCYXNlQXNzZXRCb3VnaHQDBQZfaXNBZGQFGGFtb3VudEJhc2VBc3NldEJvdWdodEFicwkBAS0BBRhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMEDSR0MDE2NzIyMTY4OTIJAQ11cGRhdGVSZXNlcnZlAwUGX2lzQWRkBRhxdW90ZUFzc2V0QW1vdW50QWRqdXN0ZWQFGGFtb3VudEJhc2VBc3NldEJvdWdodEFicwQXcXVvdGVBc3NldFJlc2VydmVBZnRlcjEIBQ0kdDAxNjcyMjE2ODkyAl8xBBZiYXNlQXNzZXRSZXNlcnZlQWZ0ZXIxCAUNJHQwMTY3MjIxNjg5MgJfMgQXdG90YWxQb3NpdGlvblNpemVBZnRlcjEIBQ0kdDAxNjcyMjE2ODkyAl8zBAtwcmljZUJlZm9yZQkBBGRpdmQCCQEEbXVsZAIFB19xdEFzdFIFB19xdEFzdFcJAQRtdWxkAgUHX2JzQXN0UgUHX2JzQXN0VwQLbWFya2V0UHJpY2UJAQRkaXZkAgURX3F1b3RlQXNzZXRBbW91bnQFGGFtb3VudEJhc2VBc3NldEJvdWdodEFicwQJcHJpY2VEaWZmCQEDYWJzAQkAZQIFC3ByaWNlQmVmb3JlBQttYXJrZXRQcmljZQQLcHJpY2VJbXBhY3QJAGUCBQxERUNJTUFMX1VOSVQJAQRkaXZkAgULcHJpY2VCZWZvcmUJAGQCBQtwcmljZUJlZm9yZQUJcHJpY2VEaWZmBBNtYXhQcmljZUltcGFjdFZhbHVlCQEObWF4UHJpY2VJbXBhY3QAAwkAZgIFC3ByaWNlSW1wYWN0BRNtYXhQcmljZUltcGFjdFZhbHVlCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAg1QcmljZSBpbXBhY3QgCQCkAwEFC3ByaWNlSW1wYWN0AhQgPiBtYXggcHJpY2UgaW1wYWN0IAkApAMBBRNtYXhQcmljZUltcGFjdFZhbHVlAhUgYmVmb3JlIHF1b3RlIGFzc2V0OiAJAKQDAQUHX3F0QXN0UgIUIGJlZm9yZSBiYXNlIGFzc2V0OiAJAKQDAQUHX2JzQXN0UgIhIHF1b3RlIGFzc2V0IGFtb3VudCB0byBleGNoYW5nZTogCQCkAwEFEV9xdW90ZUFzc2V0QW1vdW50Ag8gcHJpY2UgYmVmb3JlOiAJAKQDAQULcHJpY2VCZWZvcmUCDiBtYXJrZXRQcmljZTogCQCkAwEFC21hcmtldFByaWNlCQCWCgQFFWFtb3VudEJhc2VBc3NldEJvdWdodAUXcXVvdGVBc3NldFJlc2VydmVBZnRlcjEFFmJhc2VBc3NldFJlc2VydmVBZnRlcjEFF3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIxAQ9jYWxjUm9sbG92ZXJGZWUCEl9vbGRQb3NpdGlvbk1hcmdpbiBfb2xkUG9zaXRpb25MYXN0VXBkYXRlZFRpbWVzdGFtcAQPcG9zaXRpb25NaW51dGVzCQBoAgkAaQIJAGkCCQBlAgkBDWxhc3RUaW1lc3RhbXAABSBfb2xkUG9zaXRpb25MYXN0VXBkYXRlZFRpbWVzdGFtcADoBwA8BQxERUNJTUFMX1VOSVQEC3JvbGxvdmVyRmVlCQEEZGl2ZAIJAQRtdWxkAgkBBG11bGQCBRJfb2xkUG9zaXRpb25NYXJnaW4FD3Bvc2l0aW9uTWludXRlcwkBD3JvbGxvdmVyRmVlUmF0ZQAFD01JTlVURVNfSU5fWUVBUgULcm9sbG92ZXJGZWUBMGNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnRBbmRSb2xsb3ZlckZlZQUQX29sZFBvc2l0aW9uU2l6ZRJfb2xkUG9zaXRpb25NYXJnaW4lX29sZFBvc2l0aW9uQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbiBfb2xkUG9zaXRpb25MYXN0VXBkYXRlZFRpbWVzdGFtcAxfbWFyZ2luRGVsdGEEDmZ1bmRpbmdQYXltZW50AwkBAiE9AgUQX29sZFBvc2l0aW9uU2l6ZQAABCBfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgkBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BBRBfb2xkUG9zaXRpb25TaXplCQEEbXVsZAIJAGUCBSBfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUlX29sZFBvc2l0aW9uQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUQX29sZFBvc2l0aW9uU2l6ZQAABAtyb2xsb3ZlckZlZQkBD2NhbGNSb2xsb3ZlckZlZQIFEl9vbGRQb3NpdGlvbk1hcmdpbgUgX29sZFBvc2l0aW9uTGFzdFVwZGF0ZWRUaW1lc3RhbXAEDHNpZ25lZE1hcmdpbgkAZAIJAGUCCQBlAgUMX21hcmdpbkRlbHRhBQtyb2xsb3ZlckZlZQUOZnVuZGluZ1BheW1lbnQFEl9vbGRQb3NpdGlvbk1hcmdpbgQNJHQwMTkxNDcxOTI3NAMJAGYCAAAFDHNpZ25lZE1hcmdpbgkAlAoCAAAJAQNhYnMBBQxzaWduZWRNYXJnaW4JAJQKAgkBA2FicwEFDHNpZ25lZE1hcmdpbgAABAxyZW1haW5NYXJnaW4IBQ0kdDAxOTE0NzE5Mjc0Al8xBAdiYWREZWJ0CAUNJHQwMTkxNDcxOTI3NAJfMgkAlgoEBQxyZW1haW5NYXJnaW4FB2JhZERlYnQFDmZ1bmRpbmdQYXltZW50BQtyb2xsb3ZlckZlZQEWc3dhcE91dHB1dFdpdGhSZXNlcnZlcwcGX2lzQWRkEF9iYXNlQXNzZXRBbW91bnQUX2NoZWNrTWF4UHJpY2VJbXBhY3QSX3F1b3RlQXNzZXRSZXNlcnZlEV9xdW90ZUFzc2V0V2VpZ2h0EV9iYXNlQXNzZXRSZXNlcnZlEF9iYXNlQXNzZXRXZWlnaHQEC3ByaWNlQmVmb3JlCQEEZGl2ZAIJAQRtdWxkAgUSX3F1b3RlQXNzZXRSZXNlcnZlBRFfcXVvdGVBc3NldFdlaWdodAkBBG11bGQCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldFdlaWdodAMJAAACBRBfYmFzZUFzc2V0QW1vdW50AAAJAAIBAhlJbnZhbGlkIGJhc2UgYXNzZXQgYW1vdW50BAFrCQENY2FsY0ludmFyaWFudAIFEl9xdW90ZUFzc2V0UmVzZXJ2ZQURX2Jhc2VBc3NldFJlc2VydmUEGGJhc2VBc3NldFBvb2xBbW91bnRBZnRlcgMFBl9pc0FkZAkAZAIFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0QW1vdW50CQBlAgURX2Jhc2VBc3NldFJlc2VydmUFEF9iYXNlQXNzZXRBbW91bnQED3F1b3RlQXNzZXRBZnRlcgkAoAMBCQEFYmRpdmQCBQFrCQC2AgEFGGJhc2VBc3NldFBvb2xBbW91bnRBZnRlcgQPcXVvdGVBc3NldERlbHRhCQEDYWJzAQkAZQIFD3F1b3RlQXNzZXRBZnRlcgUSX3F1b3RlQXNzZXRSZXNlcnZlBA5xdW90ZUFzc2V0U29sZAkBBG11bGQCBQ9xdW90ZUFzc2V0RGVsdGEFEV9xdW90ZUFzc2V0V2VpZ2h0BBNtYXhQcmljZUltcGFjdFZhbHVlCQEObWF4UHJpY2VJbXBhY3QABA0kdDAyMDUzNjIwNjk4CQENdXBkYXRlUmVzZXJ2ZQMJAQEhAQUGX2lzQWRkBQ9xdW90ZUFzc2V0RGVsdGEFEF9iYXNlQXNzZXRBbW91bnQEF3F1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIxCAUNJHQwMjA1MzYyMDY5OAJfMQQWYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyMQgFDSR0MDIwNTM2MjA2OTgCXzIEF3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIxCAUNJHQwMjA1MzYyMDY5OAJfMwQLbWFya2V0UHJpY2UJAQRkaXZkAgUOcXVvdGVBc3NldFNvbGQFEF9iYXNlQXNzZXRBbW91bnQECXByaWNlRGlmZgkBA2FicwEJAGUCBQtwcmljZUJlZm9yZQULbWFya2V0UHJpY2UEC3ByaWNlSW1wYWN0CQBlAgUMREVDSU1BTF9VTklUCQEEZGl2ZAIFC3ByaWNlQmVmb3JlCQBkAgULcHJpY2VCZWZvcmUFCXByaWNlRGlmZgMDCQBmAgULcHJpY2VJbXBhY3QFE21heFByaWNlSW1wYWN0VmFsdWUFFF9jaGVja01heFByaWNlSW1wYWN0BwkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgINUHJpY2UgaW1wYWN0IAkApAMBBQtwcmljZUltcGFjdAIUID4gbWF4IHByaWNlIGltcGFjdCAJAKQDAQUTbWF4UHJpY2VJbXBhY3RWYWx1ZQIVIGJlZm9yZSBxdW90ZSBhc3NldDogCQCkAwEFEl9xdW90ZUFzc2V0UmVzZXJ2ZQIUIGJlZm9yZSBiYXNlIGFzc2V0OiAJAKQDAQURX2Jhc2VBc3NldFJlc2VydmUCICBiYXNlIGFzc2V0IGFtb3VudCB0byBleGNoYW5nZTogCQCkAwEFEF9iYXNlQXNzZXRBbW91bnQCDyBwcmljZSBiZWZvcmU6IAkApAMBBQtwcmljZUJlZm9yZQIPIG1hcmtldCBwcmljZTogCQCkAwEFC21hcmtldFByaWNlCQCZCgcFDnF1b3RlQXNzZXRTb2xkBRdxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyMQUWYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyMQUXdG90YWxQb3NpdGlvblNpemVBZnRlcjEJAGUCCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAMFBl9pc0FkZAkBA2FicwEFEF9iYXNlQXNzZXRBbW91bnQAAAkAZQIJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAMJAQEhAQUGX2lzQWRkCQEDYWJzAQUQX2Jhc2VBc3NldEFtb3VudAAABQtwcmljZUltcGFjdAEKc3dhcE91dHB1dAMGX2lzQWRkEF9iYXNlQXNzZXRBbW91bnQUX2NoZWNrTWF4UHJpY2VJbXBhY3QJARZzd2FwT3V0cHV0V2l0aFJlc2VydmVzBwUGX2lzQWRkBRBfYmFzZUFzc2V0QW1vdW50BRRfY2hlY2tNYXhQcmljZUltcGFjdAkBBnF0QXN0UgAJAQZxdEFzdFcACQEGYnNBc3RSAAkBBmJzQXN0VwABE2dldE9yYWNsZVByaWNlVmFsdWUDBm9yYWNsZQhwcmljZUtleQhibG9ja0tleQQJbGFzdFZhbHVlCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUGb3JhY2xlBQhwcmljZUtleQkArAICCQCsAgIJAKwCAgIiQ2FuIG5vdCBnZXQgb3JhY2xlIHByaWNlLiBPcmFjbGU6IAkApQgBBQZvcmFjbGUCBiBrZXk6IAUIcHJpY2VLZXkDCQECIT0CBQhibG9ja0tleQIABAxjdXJyZW50QmxvY2sIBQlsYXN0QmxvY2sGaGVpZ2h0BA9sYXN0T3JhY2xlQmxvY2sJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQZvcmFjbGUFCGJsb2NrS2V5CQCsAgIJAKwCAgkArAICAiJDYW4gbm90IGdldCBvcmFjbGUgYmxvY2suIE9yYWNsZTogCQClCAEFBm9yYWNsZQIGIGtleTogBQhibG9ja0tleQMJAGYCCQBlAgUMY3VycmVudEJsb2NrBQ9sYXN0T3JhY2xlQmxvY2sJAQ5tYXhPcmFjbGVEZWxheQAJAAIBCQCsAgIJAKwCAgkArAICAiZPcmFjbGUgc3RhbGUgZGF0YS4gTGFzdCBvcmFjbGUgYmxvY2s6IAkApAMBBQ9sYXN0T3JhY2xlQmxvY2sCECBjdXJyZW50IGJsb2NrOiAJAKQDAQUMY3VycmVudEJsb2NrBQlsYXN0VmFsdWUFCWxhc3RWYWx1ZQEOZ2V0T3JhY2xlUHJpY2UABApiYXNlT3JhY2xlCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAQ1nZXRPcmFjbGVEYXRhAQUMa19iYXNlT3JhY2xlAhlObyBiYXNlIGFzc2V0IG9yYWNsZSBkYXRhBA9iYXNlT3JhY2xlUHJpY2UJARNnZXRPcmFjbGVQcmljZVZhbHVlAwgFCmJhc2VPcmFjbGUCXzEIBQpiYXNlT3JhY2xlAl8yCAUKYmFzZU9yYWNsZQJfMwQLcXVvdGVPcmFjbGUJAQ1nZXRPcmFjbGVEYXRhAQUNa19xdW90ZU9yYWNsZQQQcXVvdGVPcmFjbGVQcmljZQMJAQlpc0RlZmluZWQBBQtxdW90ZU9yYWNsZQQMcXVvdGVPcmFjbGVWCQEFdmFsdWUBBQtxdW90ZU9yYWNsZQkBE2dldE9yYWNsZVByaWNlVmFsdWUDCAUMcXVvdGVPcmFjbGVWAl8xCAUMcXVvdGVPcmFjbGVWAl8yCAUMcXVvdGVPcmFjbGVWAl8zBQxERUNJTUFMX1VOSVQJAQRkaXZkAgUPYmFzZU9yYWNsZVByaWNlBRBxdW90ZU9yYWNsZVByaWNlAQ5pc01hcmtldENsb3NlZAAECmJhc2VPcmFjbGUJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkBDWdldE9yYWNsZURhdGEBBQxrX2Jhc2VPcmFjbGUCGU5vIGJhc2UgYXNzZXQgb3JhY2xlIGRhdGEEBm9yYWNsZQgFCmJhc2VPcmFjbGUCXzEEB29wZW5LZXkIBQpiYXNlT3JhY2xlAl80AwkBAiE9AgUHb3BlbktleQIABAZpc09wZW4JARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmwgCBQZvcmFjbGUFB29wZW5LZXkJAKwCAgkArAICCQCsAgICK0NhbiBub3QgZ2V0IG9yYWNsZSBpcyBvcGVuL2Nsb3NlZC4gT3JhY2xlOiAJAKUIAQUGb3JhY2xlAgYga2V5OiAFB29wZW5LZXkJAQEhAQUGaXNPcGVuBwEMYWJzUHJpY2VEaWZmBQxfb3JhY2xlUHJpY2USX3F1b3RlQXNzZXRSZXNlcnZlEV9iYXNlQXNzZXRSZXNlcnZlB19xdEFzdFcHX2JzQXN0VwQKcHJpY2VBZnRlcgkBBGRpdmQCCQEEbXVsZAIFEl9xdW90ZUFzc2V0UmVzZXJ2ZQUHX3F0QXN0VwkBBG11bGQCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUHX2JzQXN0VwQMYXZlcmFnZVByaWNlCQEEZGl2ZAIJAGQCBQxfb3JhY2xlUHJpY2UFCnByaWNlQWZ0ZXIJAGgCAAIFDERFQ0lNQUxfVU5JVAQMYWJzUHJpY2VEaWZmCQEEZGl2ZAIJAQNhYnMBCQBlAgUMX29yYWNsZVByaWNlBQpwcmljZUFmdGVyBQxhdmVyYWdlUHJpY2UFDGFic1ByaWNlRGlmZgEZcmVxdWlyZU5vdE92ZXJTcHJlYWRMaW1pdAISX3F1b3RlQXNzZXRSZXNlcnZlEV9iYXNlQXNzZXRSZXNlcnZlBAtvcmFjbGVQcmljZQkBDmdldE9yYWNsZVByaWNlAAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcABBJhYnNQcmljZURpZmZCZWZvcmUJAQxhYnNQcmljZURpZmYFBQtvcmFjbGVQcmljZQkBBnF0QXN0UgAJAQZic0FzdFIABQdfcXRBc3RXBQdfYnNBc3RXBBFhYnNQcmljZURpZmZBZnRlcgkBDGFic1ByaWNlRGlmZgUFC29yYWNsZVByaWNlBRJfcXVvdGVBc3NldFJlc2VydmUFEV9iYXNlQXNzZXRSZXNlcnZlBQdfcXRBc3RXBQdfYnNBc3RXAwMJAGYCBRFhYnNQcmljZURpZmZBZnRlcgkBDm1heFByaWNlU3ByZWFkAAkAZgIFEWFic1ByaWNlRGlmZkFmdGVyBRJhYnNQcmljZURpZmZCZWZvcmUHCQACAQkArAICCQCsAgIJAKwCAgINUHJpY2Ugc3ByZWFkIAkApAMBBRFhYnNQcmljZURpZmZBZnRlcgIUID4gbWF4IHByaWNlIHNwcmVhZCAJAKQDAQkBDm1heFByaWNlU3ByZWFkAAYBHXJlcXVpcmVOb3RPdmVyTWF4T3Blbk5vdGlvbmFsAhFfbG9uZ09wZW5Ob3Rpb25hbBJfc2hvcnRPcGVuTm90aW9uYWwEEF9tYXhPcGVuTm90aW9uYWwJAQ9tYXhPcGVuTm90aW9uYWwAAwkAZgIFEV9sb25nT3Blbk5vdGlvbmFsBRBfbWF4T3Blbk5vdGlvbmFsCQACAQkArAICCQCsAgIJAKwCAgITTG9uZyBvcGVuIG5vdGlvbmFsIAkApAMBBRFfbG9uZ09wZW5Ob3Rpb25hbAIVID4gbWF4IG9wZW4gbm90aW9uYWwgCQCkAwEFEF9tYXhPcGVuTm90aW9uYWwDCQBmAgUSX3Nob3J0T3Blbk5vdGlvbmFsBRBfbWF4T3Blbk5vdGlvbmFsCQACAQkArAICCQCsAgIJAKwCAgIUU2hvcnQgb3BlbiBub3Rpb25hbCAJAKQDAQUSX3Nob3J0T3Blbk5vdGlvbmFsAhUgPiBtYXggb3BlbiBub3Rpb25hbCAJAKQDAQUQX21heE9wZW5Ob3Rpb25hbAYBDGdldFNwb3RQcmljZQAEEl9xdW90ZUFzc2V0UmVzZXJ2ZQkBBnF0QXN0UgAEEV9iYXNlQXNzZXRSZXNlcnZlCQEGYnNBc3RSAAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcACQEEZGl2ZAIJAQRtdWxkAgUSX3F1b3RlQXNzZXRSZXNlcnZlBQdfcXRBc3RXCQEEbXVsZAIFEV9iYXNlQXNzZXRSZXNlcnZlBQdfYnNBc3RXARZpc092ZXJGbHVjdHVhdGlvbkxpbWl0AAQLb3JhY2xlUHJpY2UJAQ5nZXRPcmFjbGVQcmljZQAEDGN1cnJlbnRQcmljZQkBDGdldFNwb3RQcmljZQAJAGYCCQEEZGl2ZAIJAQNhYnMBCQBlAgULb3JhY2xlUHJpY2UFDGN1cnJlbnRQcmljZQULb3JhY2xlUHJpY2UJAQtzcHJlYWRMaW1pdAABH2dldFBvc2l0aW9uQWRqdXN0ZWRPcGVuTm90aW9uYWwGDV9wb3NpdGlvblNpemUHX29wdGlvbhJfcXVvdGVBc3NldFJlc2VydmURX3F1b3RlQXNzZXRXZWlnaHQRX2Jhc2VBc3NldFJlc2VydmUQX2Jhc2VBc3NldFdlaWdodAQPcG9zaXRpb25TaXplQWJzCQEDYWJzAQUNX3Bvc2l0aW9uU2l6ZQQHaXNTaG9ydAkAZgIAAAUNX3Bvc2l0aW9uU2l6ZQQQcG9zaXRpb25Ob3Rpb25hbAMJAAACBQdfb3B0aW9uBQ9QTkxfT1BUSU9OX1NQT1QEE291dFBvc2l0aW9uTm90aW9uYWwICQEWc3dhcE91dHB1dFdpdGhSZXNlcnZlcwcJAQEhAQUHaXNTaG9ydAUPcG9zaXRpb25TaXplQWJzBwUSX3F1b3RlQXNzZXRSZXNlcnZlBRFfcXVvdGVBc3NldFdlaWdodAURX2Jhc2VBc3NldFJlc2VydmUFEF9iYXNlQXNzZXRXZWlnaHQCXzEFE291dFBvc2l0aW9uTm90aW9uYWwJAQRtdWxkAgUPcG9zaXRpb25TaXplQWJzCQEOZ2V0T3JhY2xlUHJpY2UABRBwb3NpdGlvbk5vdGlvbmFsAStnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubEJ5VmFsdWVzBw1fcG9zaXRpb25TaXplFV9wb3NpdGlvbk9wZW5Ob3Rpb25hbBJfcXVvdGVBc3NldFJlc2VydmURX3F1b3RlQXNzZXRXZWlnaHQRX2Jhc2VBc3NldFJlc2VydmUQX2Jhc2VBc3NldFdlaWdodAdfb3B0aW9uAwkAAAIFDV9wb3NpdGlvblNpemUAAAkAAgECFUludmFsaWQgcG9zaXRpb24gc2l6ZQQHaXNTaG9ydAkAZgIAAAUNX3Bvc2l0aW9uU2l6ZQQQcG9zaXRpb25Ob3Rpb25hbAkBH2dldFBvc2l0aW9uQWRqdXN0ZWRPcGVuTm90aW9uYWwGBQ1fcG9zaXRpb25TaXplBQdfb3B0aW9uBRJfcXVvdGVBc3NldFJlc2VydmUFEV9xdW90ZUFzc2V0V2VpZ2h0BRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldFdlaWdodAQNdW5yZWFsaXplZFBubAMFB2lzU2hvcnQJAGUCBRVfcG9zaXRpb25PcGVuTm90aW9uYWwFEHBvc2l0aW9uTm90aW9uYWwJAGUCBRBwb3NpdGlvbk5vdGlvbmFsBRVfcG9zaXRpb25PcGVuTm90aW9uYWwJAJQKAgUQcG9zaXRpb25Ob3Rpb25hbAUNdW5yZWFsaXplZFBubAEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCB190cmFkZXIHX29wdGlvbgQNJHQwMjg1NzYyODcwNAkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQMcG9zaXRpb25TaXplCAUNJHQwMjg1NzYyODcwNAJfMQQOcG9zaXRpb25NYXJnaW4IBQ0kdDAyODU3NjI4NzA0Al8yBBRwb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDI4NTc2Mjg3MDQCXzMEEXBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwMjg1NzYyODcwNAJfNAkBK2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sQnlWYWx1ZXMHBQxwb3NpdGlvblNpemUFFHBvc2l0aW9uT3Blbk5vdGlvbmFsCQEGcXRBc3RSAAkBBnF0QXN0VwAJAQZic0FzdFIACQEGYnNBc3RXAAUHX29wdGlvbgEPY2FsY01hcmdpblJhdGlvAw1fcmVtYWluTWFyZ2luCF9iYWREZWJ0EV9wb3NpdGlvbk5vdGlvbmFsCQEEZGl2ZAIJAGUCBQ1fcmVtYWluTWFyZ2luBQhfYmFkRGVidAURX3Bvc2l0aW9uTm90aW9uYWwBFmdldE1hcmdpblJhdGlvQnlPcHRpb24CB190cmFkZXIHX29wdGlvbgQNJHQwMjkyMTkyOTM2MAkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQMcG9zaXRpb25TaXplCAUNJHQwMjkyMTkyOTM2MAJfMQQOcG9zaXRpb25NYXJnaW4IBQ0kdDAyOTIxOTI5MzYwAl8yBANwb24IBQ0kdDAyOTIxOTI5MzYwAl8zBBZwb3NpdGlvbkxhc3RVcGRhdGVkQ1BGCAUNJHQwMjkyMTkyOTM2MAJfNAQRcG9zaXRpb25UaW1lc3RhbXAIBQ0kdDAyOTIxOTI5MzYwAl81BA0kdDAyOTM2NjI5NDU5CQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCBQdfdHJhZGVyBQdfb3B0aW9uBBBwb3NpdGlvbk5vdGlvbmFsCAUNJHQwMjkzNjYyOTQ1OQJfMQQNdW5yZWFsaXplZFBubAgFDSR0MDI5MzY2Mjk0NTkCXzIEDSR0MDI5NDY0Mjk2NzYJATBjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50QW5kUm9sbG92ZXJGZWUFBQxwb3NpdGlvblNpemUFDnBvc2l0aW9uTWFyZ2luBRZwb3NpdGlvbkxhc3RVcGRhdGVkQ1BGBRFwb3NpdGlvblRpbWVzdGFtcAUNdW5yZWFsaXplZFBubAQMcmVtYWluTWFyZ2luCAUNJHQwMjk0NjQyOTY3NgJfMQQHYmFkRGVidAgFDSR0MDI5NDY0Mjk2NzYCXzIJAQ9jYWxjTWFyZ2luUmF0aW8DBQxyZW1haW5NYXJnaW4FB2JhZERlYnQFEHBvc2l0aW9uTm90aW9uYWwBDmdldE1hcmdpblJhdGlvAQdfdHJhZGVyCQEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAEbZ2V0UGFydGlhbExpcXVpZGF0aW9uQW1vdW50AgdfdHJhZGVyDV9wb3NpdGlvblNpemUEDG1heGltdW1SYXRpbwkBBHZtYXgCCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8ACQBlAgUMREVDSU1BTF9VTklUCQEEZGl2ZAIJAQ5nZXRNYXJnaW5SYXRpbwEFB190cmFkZXIJARZtYWludGVuYW5jZU1hcmdpblJhdGlvAAQYbWF4RXhjaGFuZ2VkUG9zaXRpb25TaXplCQEEbXVsZAIJAQNhYnMBBQ1fcG9zaXRpb25TaXplBQxtYXhpbXVtUmF0aW8ECnN3YXBSZXN1bHQJAQpzd2FwT3V0cHV0AwkAZgIFDV9wb3NpdGlvblNpemUAAAUYbWF4RXhjaGFuZ2VkUG9zaXRpb25TaXplBwQcbWF4RXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAgFCnN3YXBSZXN1bHQCXzEEC3ByaWNlSW1wYWN0CAUKc3dhcFJlc3VsdAJfNwMJAGYCCQEObWF4UHJpY2VJbXBhY3QABQtwcmljZUltcGFjdAUYbWF4RXhjaGFuZ2VkUG9zaXRpb25TaXplCQEEbXVsZAIJAQNhYnMBBQ1fcG9zaXRpb25TaXplCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8AARVpbnRlcm5hbENsb3NlUG9zaXRpb24HB190cmFkZXIFX3NpemUEX2ZlZRRfbWluUXVvdGVBc3NldEFtb3VudAxfYWRkVG9NYXJnaW4UX2NoZWNrTWF4UHJpY2VJbXBhY3QKX2xpcXVpZGF0ZQQNJHQwMzA3NDMzMDg5OQkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQPb2xkUG9zaXRpb25TaXplCAUNJHQwMzA3NDMzMDg5OQJfMQQRb2xkUG9zaXRpb25NYXJnaW4IBQ0kdDAzMDc0MzMwODk5Al8yBBdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDMwNzQzMzA4OTkCXzMEFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwMzA3NDMzMDg5OQJfNAQUb2xkUG9zaXRpb25UaW1lc3RhbXAIBQ0kdDAzMDc0MzMwODk5Al81BA5pc0xvbmdQb3NpdGlvbgkAZgIFD29sZFBvc2l0aW9uU2l6ZQAABBJhYnNPbGRQb3NpdGlvblNpemUJAQNhYnMBBQ9vbGRQb3NpdGlvblNpemUDAwkAZwIFEmFic09sZFBvc2l0aW9uU2l6ZQUFX3NpemUJAGYCBQVfc2l6ZQAABwQOaXNQYXJ0aWFsQ2xvc2UJAGYCBRJhYnNPbGRQb3NpdGlvblNpemUFBV9zaXplBA0kdDAzMTE5MTMxNjQyCQEKc3dhcE91dHB1dAMJAGYCBQ9vbGRQb3NpdGlvblNpemUAAAUFX3NpemUFFF9jaGVja01heFByaWNlSW1wYWN0BBlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CAUNJHQwMzExOTEzMTY0MgJfMQQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDMxMTkxMzE2NDICXzIEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDMxMTkxMzE2NDICXzMEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDAzMTE5MTMxNjQyAl80BBVleGNoYW5nZWRQb3NpdGlvblNpemUDCQBmAgUPb2xkUG9zaXRpb25TaXplAAAJAQEtAQUFX3NpemUFBV9zaXplBA0kdDAzMTg1NzMyMDY0CQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QEE29sZFBvc2l0aW9uTm90aW9uYWwIBQ0kdDAzMTg1NzMyMDY0Al8xBA11bnJlYWxpemVkUG5sCAUNJHQwMzE4NTczMjA2NAJfMgQNcmVhbGl6ZWRSYXRpbwkBBGRpdmQCCQEDYWJzAQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplBRJhYnNPbGRQb3NpdGlvblNpemUEC3JlYWxpemVkUG5sCQEEbXVsZAIFDXVucmVhbGl6ZWRQbmwFDXJlYWxpemVkUmF0aW8EDSR0MDMyNDA1MzI2NTEJATBjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50QW5kUm9sbG92ZXJGZWUFBQ9vbGRQb3NpdGlvblNpemUFEW9sZFBvc2l0aW9uTWFyZ2luBRRvbGRQb3NpdGlvbkxzdFVwZENQRgUUb2xkUG9zaXRpb25UaW1lc3RhbXAFDXVucmVhbGl6ZWRQbmwEEnJlbWFpbk1hcmdpbkJlZm9yZQgFDSR0MDMyNDA1MzI2NTECXzEEAngxCAUNJHQwMzI0MDUzMjY1MQJfMgQCeDIIBQ0kdDAzMjQwNTMyNjUxAl8zBAtyb2xsb3ZlckZlZQgFDSR0MDMyNDA1MzI2NTECXzQED3Bvc2l0aW9uQmFkRGVidAgJATBjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50QW5kUm9sbG92ZXJGZWUFBQ9vbGRQb3NpdGlvblNpemUFEW9sZFBvc2l0aW9uTWFyZ2luBRRvbGRQb3NpdGlvbkxzdFVwZENQRgUUb2xkUG9zaXRpb25UaW1lc3RhbXAFC3JlYWxpemVkUG5sAl8yBBByZWFsaXplZENsb3NlRmVlCQEEbXVsZAIJAQRtdWxkAgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUNcmVhbGl6ZWRSYXRpbwUEX2ZlZQQSdW5yZWFsaXplZFBubEFmdGVyCQBlAgUNdW5yZWFsaXplZFBubAULcmVhbGl6ZWRQbmwEEnJlbWFpbk9wZW5Ob3Rpb25hbAMJAGYCBQ9vbGRQb3NpdGlvblNpemUAAAkAZQIJAGUCBRNvbGRQb3NpdGlvbk5vdGlvbmFsBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BRJ1bnJlYWxpemVkUG5sQWZ0ZXIJAGUCCQBkAgUSdW5yZWFsaXplZFBubEFmdGVyBRNvbGRQb3NpdGlvbk5vdGlvbmFsBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BA9uZXdQb3NpdGlvblNpemUJAGQCBQ9vbGRQb3NpdGlvblNpemUFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQQNJHQwMzQwNTczNDQ0MwMJAAACBQ9uZXdQb3NpdGlvblNpemUAAAkAlAoCAAAAAAkAlAoCCQEDYWJzAQUScmVtYWluT3Blbk5vdGlvbmFsCQEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEFD25ld1Bvc2l0aW9uU2l6ZQQXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDAzNDA1NzM0NDQzAl8xBBRuZXdQb3NpdGlvbkxzdFVwZENQRggFDSR0MDM0MDU3MzQ0NDMCXzIEEW9wZW5Ob3Rpb25hbERlbHRhCQBlAgUXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwFF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBAttYXJnaW5SYXRpbwkBFmdldE1hcmdpblJhdGlvQnlPcHRpb24CBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QEHm5ld1Bvc2l0aW9uTWFyZ2luV2l0aFNhbWVSYXRpbwMJAGYCBQ9vbGRQb3NpdGlvblNpemUAAAkAZQIJAQRtdWxkAgkAZAIFF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBRJ1bnJlYWxpemVkUG5sQWZ0ZXIFC21hcmdpblJhdGlvBRJ1bnJlYWxpemVkUG5sQWZ0ZXIJAGUCCQEEbXVsZAIJAGUCBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUSdW5yZWFsaXplZFBubEFmdGVyBQttYXJnaW5SYXRpbwUSdW5yZWFsaXplZFBubEFmdGVyBBFtYXJnaW5Ub1RyYWRlclJhdwkAZQIJAGUCBRJyZW1haW5NYXJnaW5CZWZvcmUJAGQCBR5uZXdQb3NpdGlvbk1hcmdpbldpdGhTYW1lUmF0aW8FEnVucmVhbGl6ZWRQbmxBZnRlcgUQcmVhbGl6ZWRDbG9zZUZlZQQObWFyZ2luVG9UcmFkZXIDCQBmAgAABRFtYXJnaW5Ub1RyYWRlclJhdwMFCl9saXF1aWRhdGUAAAkAAgECN0ludmFsaWQgaW50ZXJuYWxDbG9zZVBvc2l0aW9uIHBhcmFtczogdW5hYmxlIHRvIHBheSBmZWUFEW1hcmdpblRvVHJhZGVyUmF3BBFuZXdQb3NpdGlvbk1hcmdpbgMFDF9hZGRUb01hcmdpbgkAZAIFHm5ld1Bvc2l0aW9uTWFyZ2luV2l0aFNhbWVSYXRpbwUObWFyZ2luVG9UcmFkZXIFHm5ld1Bvc2l0aW9uTWFyZ2luV2l0aFNhbWVSYXRpbwMDCQECIT0CBRRfbWluUXVvdGVBc3NldEFtb3VudAAACQBmAgUUX21pblF1b3RlQXNzZXRBbW91bnQFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQHCQACAQkArAICCQCsAgIJAKwCAgINTGltaXQgZXJyb3I6IAkApAMBBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50AgMgPCAJAKQDAQUUX21pblF1b3RlQXNzZXRBbW91bnQJAKMKEQUPbmV3UG9zaXRpb25TaXplBRFuZXdQb3NpdGlvbk1hcmdpbgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFFG5ld1Bvc2l0aW9uTHN0VXBkQ1BGBQ9wb3NpdGlvbkJhZERlYnQFC3JlYWxpemVkUG5sAwMFDF9hZGRUb01hcmdpbgUOaXNQYXJ0aWFsQ2xvc2UHAAAFDm1hcmdpblRvVHJhZGVyBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIJAGUCCQEUb3BlbkludGVyZXN0Tm90aW9uYWwABRFvcGVuTm90aW9uYWxEZWx0YQkAZQIJARV0b3RhbExvbmdQb3NpdGlvblNpemUAAwUOaXNMb25nUG9zaXRpb24JAQNhYnMBBRVleGNoYW5nZWRQb3NpdGlvblNpemUAAAkAZQIJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAMJAQEhAQUOaXNMb25nUG9zaXRpb24JAQNhYnMBBRVleGNoYW5nZWRQb3NpdGlvblNpemUAAAkAZQIJARBvcGVuSW50ZXJlc3RMb25nAAMFDmlzTG9uZ1Bvc2l0aW9uBRFvcGVuTm90aW9uYWxEZWx0YQAACQBlAgkBEW9wZW5JbnRlcmVzdFNob3J0AAMJAQEhAQUOaXNMb25nUG9zaXRpb24FEW9wZW5Ob3Rpb25hbERlbHRhAAAJAGQCBRByZWFsaXplZENsb3NlRmVlBQtyb2xsb3ZlckZlZQUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAkAAgEJAKwCAgkArAICCQCsAgICPUludmFsaWQgaW50ZXJuYWxDbG9zZVBvc2l0aW9uIHBhcmFtczogaW52YWxpZCBwb3NpdGlvbiBzaXplOiAJAKQDAQUFX3NpemUCBiBtYXg6IAkApAMBBRJhYnNPbGRQb3NpdGlvblNpemUBEGdldFR3YXBTcG90UHJpY2UABAhtaW51dGVJZAkAaQIJAGkCCQENbGFzdFRpbWVzdGFtcAAA6AcAPAQNc3RhcnRNaW51dGVJZAkAZQIFCG1pbnV0ZUlkBQ1UV0FQX0lOVEVSVkFMBAdsaXN0U3RyCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMFDWtfbGFzdERhdGFTdHICAAQEbGlzdAkAtQkCBQdsaXN0U3RyAgEsCgEIZmlsdGVyRm4CC2FjY3VtdWxhdG9yBG5leHQDCQBnAgUNc3RhcnRNaW51dGVJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQC2CQEFBG5leHQJAKwCAgIfZ2V0VHdhcFNwb3RQcmljZTogaW52YWxpZCBpbnQ6IAUHbGlzdFN0cgkAzQgCBQthY2N1bXVsYXRvcgkBDXBhcnNlSW50VmFsdWUBBQRuZXh0BQthY2N1bXVsYXRvcgQFbGlzdEYKAAIkbAUEbGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEIZmlsdGVyRm4CBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDIwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAA0ADgAPABAAEQASABMAFAQIbWF4SW5kZXgDCQBmAgkAkAMBBQVsaXN0RgAACQCWAwEFBWxpc3RGCQETdmFsdWVPckVycm9yTWVzc2FnZQIJALYJAQkAkQMCBQRsaXN0AAAJAKwCAgIfZ2V0VHdhcFNwb3RQcmljZTogaW52YWxpZCBpbnQ6IAUHbGlzdFN0cgQMbGFzdE1pbnV0ZUlkCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFDmtfbGFzdE1pbnV0ZUlkAAAEFmVuZExhc3RDdW11bGF0aXZlUHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkArAICCQCsAgIFHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlAgFfCQCkAwEFDGxhc3RNaW51dGVJZAAABAxlbmRMYXN0UHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkArAICCQCsAgIFE2tfdHdhcERhdGFMYXN0UHJpY2UCAV8JAKQDAQUMbGFzdE1pbnV0ZUlkAAAEEm5vd0N1bXVsYXRpdmVQcmljZQkAZAIFFmVuZExhc3RDdW11bGF0aXZlUHJpY2UJAGgCCQBlAgUIbWludXRlSWQFDGxhc3RNaW51dGVJZAUMZW5kTGFzdFByaWNlBBhzdGFydExhc3RDdW11bGF0aXZlUHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkArAICCQCsAgIFHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlAgFfCQCkAwEFCG1heEluZGV4AAAEDnN0YXJ0TGFzdFByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAKwCAgkArAICBRNrX3R3YXBEYXRhTGFzdFByaWNlAgFfCQCkAwEFCG1heEluZGV4AAAEFHN0YXJ0Q3VtdWxhdGl2ZVByaWNlCQBkAgUYc3RhcnRMYXN0Q3VtdWxhdGl2ZVByaWNlCQBoAgkAZQIFDXN0YXJ0TWludXRlSWQFCG1heEluZGV4BQ5zdGFydExhc3RQcmljZQkAaQIJAGUCBRJub3dDdW11bGF0aXZlUHJpY2UFFHN0YXJ0Q3VtdWxhdGl2ZVByaWNlBQ1UV0FQX0lOVEVSVkFMARNnZXRUZXJtaW5hbEFtbVN0YXRlAAQNX3Bvc2l0aW9uU2l6ZQkBEXRvdGFsUG9zaXRpb25TaXplAAMJAAACBQ1fcG9zaXRpb25TaXplAAAJAJQKAgkBBnF0QXN0UgAJAQZic0FzdFIABAlkaXJlY3Rpb24JAGYCBQ1fcG9zaXRpb25TaXplAAAEDSR0MDM5MTgwMzkzNTkJAQpzd2FwT3V0cHV0AwUJZGlyZWN0aW9uCQEDYWJzAQUNX3Bvc2l0aW9uU2l6ZQcEFWN1cnJlbnROZXRNYXJrZXRWYWx1ZQgFDSR0MDM5MTgwMzkzNTkCXzEEGXRlcm1pbmFsUXVvdGVBc3NldFJlc2VydmUIBQ0kdDAzOTE4MDM5MzU5Al8yBBh0ZXJtaW5hbEJhc2VBc3NldFJlc2VydmUIBQ0kdDAzOTE4MDM5MzU5Al8zCQCUCgIFGXRlcm1pbmFsUXVvdGVBc3NldFJlc2VydmUFGHRlcm1pbmFsQmFzZUFzc2V0UmVzZXJ2ZQETZ2V0UXVvdGVBc3NldFdlaWdodAQQYmFzZUFzc2V0UmVzZXJ2ZRF0b3RhbFBvc2l0aW9uU2l6ZRFxdW90ZUFzc2V0UmVzZXJ2ZQt0YXJnZXRQcmljZQQBYgkAtgIBBRBiYXNlQXNzZXRSZXNlcnZlBAJzegkAtgIBBRF0b3RhbFBvc2l0aW9uU2l6ZQQBcQkAtgIBBRFxdW90ZUFzc2V0UmVzZXJ2ZQQBcAkAtgIBBQt0YXJnZXRQcmljZQQBawkBBWJtdWxkAgUBcQUBYgQEbmV3QgkAtwICBQFiBQJzegQEbmV3UQkBBWJkaXZkAgUBawUEbmV3QgQBegkBBWJkaXZkAgUEbmV3UQUEbmV3QgQGcmVzdWx0CQEFYmRpdmQCBQFwBQF6CQCgAwEFBnJlc3VsdAEUZ2V0U3luY1Rlcm1pbmFsUHJpY2UDDl90ZXJtaW5hbFByaWNlB19xdEFzdFIHX2JzQXN0UgQNX3Bvc2l0aW9uU2l6ZQkBEXRvdGFsUG9zaXRpb25TaXplAAMJAAACBQ1fcG9zaXRpb25TaXplAAAECW5ld1F0QXN0VwkBBGRpdmQCCQEEbXVsZAIFDl90ZXJtaW5hbFByaWNlBQdfYnNBc3RSBQdfcXRBc3RSCQCVCgMFCW5ld1F0QXN0VwUMREVDSU1BTF9VTklUAAAECWRpcmVjdGlvbgkAZgIFDV9wb3NpdGlvblNpemUAAAQVY3VycmVudE5ldE1hcmtldFZhbHVlCAkBCnN3YXBPdXRwdXQDBQlkaXJlY3Rpb24JAQNhYnMBBQ1fcG9zaXRpb25TaXplBwJfMQQJbmV3UXRBc3RXCQETZ2V0UXVvdGVBc3NldFdlaWdodAQFB19ic0FzdFIFDV9wb3NpdGlvblNpemUFB19xdEFzdFIFDl90ZXJtaW5hbFByaWNlBAluZXdCc0FzdFcFDERFQ0lNQUxfVU5JVAQNbWFyZ2luVG9WYXVsdAgJAStnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubEJ5VmFsdWVzBwUNX3Bvc2l0aW9uU2l6ZQUVY3VycmVudE5ldE1hcmtldFZhbHVlBQdfcXRBc3RSBQluZXdRdEFzdFcFB19ic0FzdFIFCW5ld0JzQXN0VwUPUE5MX09QVElPTl9TUE9UAl8yCQCVCgMFCW5ld1F0QXN0VwUJbmV3QnNBc3RXBQ1tYXJnaW5Ub1ZhdWx0AQpnZXRGdW5kaW5nAAQPdW5kZXJseWluZ1ByaWNlCQEOZ2V0T3JhY2xlUHJpY2UABA1zcG90VHdhcFByaWNlCQEQZ2V0VHdhcFNwb3RQcmljZQAEB3ByZW1pdW0JAGUCBQ1zcG90VHdhcFByaWNlBQ91bmRlcmx5aW5nUHJpY2UDAwMJAAACCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAAAAYJAAACCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAAABgkBDmlzTWFya2V0Q2xvc2VkAAkAlAoCAAAAAAMJAGYCAAAFB3ByZW1pdW0EFHNob3J0UHJlbWl1bUZyYWN0aW9uCQEEZGl2ZAIJAQRtdWxkAgUHcHJlbWl1bQkBFGZ1bmRpbmdQZXJpb2REZWNpbWFsAAUHT05FX0RBWQQTbG9uZ1ByZW1pdW1GcmFjdGlvbgkBBGRpdmQCCQEEbXVsZAIFFHNob3J0UHJlbWl1bUZyYWN0aW9uCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAJARV0b3RhbExvbmdQb3NpdGlvblNpemUACQCUCgIFFHNob3J0UHJlbWl1bUZyYWN0aW9uBRNsb25nUHJlbWl1bUZyYWN0aW9uBBNsb25nUHJlbWl1bUZyYWN0aW9uCQEEZGl2ZAIJAQRtdWxkAgUHcHJlbWl1bQkBFGZ1bmRpbmdQZXJpb2REZWNpbWFsAAUHT05FX0RBWQQUc2hvcnRQcmVtaXVtRnJhY3Rpb24JAQRkaXZkAgkBBG11bGQCBRNsb25nUHJlbWl1bUZyYWN0aW9uCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUACQCUCgIFFHNob3J0UHJlbWl1bUZyYWN0aW9uBRNsb25nUHJlbWl1bUZyYWN0aW9uAQ5nZXRBZGp1c3RlZEZlZQILX2FydGlmYWN0SWQQX2Jhc2VGZWVEaXNjb3VudAQKYmFzZUZlZVJhdwkBA2ZlZQAEB2Jhc2VGZWUJAQRtdWxkAgUKYmFzZUZlZVJhdwUQX2Jhc2VGZWVEaXNjb3VudAQNJHQwNDIyMjA0MjcxNQMJAQIhPQIFC19hcnRpZmFjdElkAgAEDGFydGlmYWN0S2luZAkBBHN0ckECCQERbmZ0TWFuYWdlckFkZHJlc3MACQEOdG9Db21wb3NpdGVLZXkCBQxrX3Rva2VuX3R5cGUFC19hcnRpZmFjdElkAwkAAAIFDGFydGlmYWN0S2luZAUYRkVFX1JFRFVDVElPTl9UT0tFTl9UWVBFBAlyZWR1Y3Rpb24JAQRpbnRBAgkBEW5mdE1hbmFnZXJBZGRyZXNzAAkBDnRvQ29tcG9zaXRlS2V5AgUNa190b2tlbl9wYXJhbQULX2FydGlmYWN0SWQEC2FkanVzdGVkRmVlCQEEbXVsZAIFB2Jhc2VGZWUFCXJlZHVjdGlvbgkAlAoCBQthZGp1c3RlZEZlZQYJAAIBAhlJbnZhbGlkIGF0dGFjaGVkIGFydGlmYWN0CQCUCgIFB2Jhc2VGZWUHBAthZGp1c3RlZEZlZQgFDSR0MDQyMjIwNDI3MTUCXzEEDGJ1cm5BcnRpZmFjdAgFDSR0MDQyMjIwNDI3MTUCXzIJAJQKAgULYWRqdXN0ZWRGZWUFDGJ1cm5BcnRpZmFjdAEXaXNTYW1lQXNzZXRPck5vUG9zaXRpb24CB190cmFkZXIIX2Fzc2V0SWQED29sZFBvc2l0aW9uU2l6ZQgJAQtnZXRQb3NpdGlvbgEFB190cmFkZXICXzEDCQAAAgUPb2xkUG9zaXRpb25TaXplAAAGCQAAAgkBEGdldFBvc2l0aW9uQXNzZXQBBQdfdHJhZGVyBQhfYXNzZXRJZAELaXNTYW1lQXNzZXQCB190cmFkZXIIX2Fzc2V0SWQJAAACCQEQZ2V0UG9zaXRpb25Bc3NldAEFB190cmFkZXIFCF9hc3NldElkARhnZXRGb3JUcmFkZXJXaXRoQXJ0aWZhY3QCB190cmFkZXILX2FydGlmYWN0SWQEEGRvR2V0RmVlRGlzY291bnQJAPwHBAkBDG1pbmVyQWRkcmVzcwACEmNvbXB1dGVGZWVEaXNjb3VudAkAzAgCBQdfdHJhZGVyBQNuaWwFA25pbAMJAAACBRBkb0dldEZlZURpc2NvdW50BRBkb0dldEZlZURpc2NvdW50BAtmZWVEaXNjb3VudAQHJG1hdGNoMAUQZG9HZXRGZWVEaXNjb3VudAMJAAECBQckbWF0Y2gwAgNJbnQEAXgFByRtYXRjaDAFAXgJAAIBAiFJbnZhbGlkIGNvbXB1dGVGZWVEaXNjb3VudCByZXN1bHQEDSR0MDQzMzk1NDM0NjkJAQ5nZXRBZGp1c3RlZEZlZQIFC19hcnRpZmFjdElkBQtmZWVEaXNjb3VudAQLYWRqdXN0ZWRGZWUIBQ0kdDA0MzM5NTQzNDY5Al8xBAxidXJuQXJ0aWZhY3QIBQ0kdDA0MzM5NTQzNDY5Al8yCQCUCgIFC2FkanVzdGVkRmVlBQxidXJuQXJ0aWZhY3QJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BDWdldEFydGlmYWN0SWQBAWkECmFydGlmYWN0SWQDCQBmAgkAkAMBCAUBaQhwYXltZW50cwABCQDYBAEJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAggJAJEDAggFAWkIcGF5bWVudHMAAQdhc3NldElkAhJJbnZhbGlkIGFydGlmYWN0SWQCAAUKYXJ0aWZhY3RJZAENZGlzdHJpYnV0ZUZlZQEKX2ZlZUFtb3VudAQMZmVlVG9TdGFrZXJzCQEEbXVsZAIFCl9mZWVBbW91bnQJARNmZWVUb1N0YWtlcnNQZXJjZW50AAQKZmVlVG9WYXVsdAkAZQIFCl9mZWVBbW91bnQFDGZlZVRvU3Rha2VycwkAlAoCBQxmZWVUb1N0YWtlcnMFCmZlZVRvVmF1bHQBDnVwZGF0ZVNldHRpbmdzDRBfaW5pdE1hcmdpblJhdGlvBF9tbXIUX2xpcXVpZGF0aW9uRmVlUmF0aW8OX2Z1bmRpbmdQZXJpb2QEX2ZlZQxfc3ByZWFkTGltaXQPX21heFByaWNlSW1wYWN0GF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbw9fbWF4UHJpY2VTcHJlYWQQX21heE9wZW5Ob3Rpb25hbBRfZmVlVG9TdGFrZXJzUGVyY2VudA9fbWF4T3JhY2xlRGVsYXkMX3JvbGxvdmVyRmVlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRFrX2luaXRNYXJnaW5SYXRpbwUQX2luaXRNYXJnaW5SYXRpbwkAzAgCCQEMSW50ZWdlckVudHJ5AgUYa19tYWludGVuYW5jZU1hcmdpblJhdGlvBQRfbW1yCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRVrX2xpcXVpZGF0aW9uRmVlUmF0aW8FFF9saXF1aWRhdGlvbkZlZVJhdGlvCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ9rX2Z1bmRpbmdQZXJpb2QFDl9mdW5kaW5nUGVyaW9kCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQVrX2ZlZQUEX2ZlZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUNa19zcHJlYWRMaW1pdAUMX3NwcmVhZExpbWl0CQDMCAIJAQxJbnRlZ2VyRW50cnkCBRBrX21heFByaWNlSW1wYWN0BQ9fbWF4UHJpY2VJbXBhY3QJAMwIAgkBDEludGVnZXJFbnRyeQIFGWtfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8FGF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwkAzAgCCQEMSW50ZWdlckVudHJ5AgUQa19tYXhQcmljZVNwcmVhZAUPX21heFByaWNlU3ByZWFkCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRFrX21heE9wZW5Ob3Rpb25hbAUQX21heE9wZW5Ob3Rpb25hbAkAzAgCCQEMSW50ZWdlckVudHJ5AgUVa19mZWVUb1N0YWtlcnNQZXJjZW50BRRfZmVlVG9TdGFrZXJzUGVyY2VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgUQa19tYXhPcmFjbGVEZWxheQUUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQJAMwIAgkBDEludGVnZXJFbnRyeQIFDWtfcm9sbG92ZXJGZWUFDF9yb2xsb3ZlckZlZQUDbmlsAQ11cGRhdGVGdW5kaW5nBRFfbmV4dEZ1bmRpbmdCbG9jayRfbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24lX2xhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbhBfbG9uZ0Z1bmRpbmdSYXRlEV9zaG9ydEZ1bmRpbmdSYXRlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJrX25leHRGdW5kaW5nQmxvY2sFEV9uZXh0RnVuZGluZ0Jsb2NrCQDMCAIJAQxJbnRlZ2VyRW50cnkCBSVrX2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBSRfbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24JAMwIAgkBDEludGVnZXJFbnRyeQIFJmtfbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBSVfbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRFrX2xvbmdGdW5kaW5nUmF0ZQUQX2xvbmdGdW5kaW5nUmF0ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUSa19zaG9ydEZ1bmRpbmdSYXRlBRFfc2hvcnRGdW5kaW5nUmF0ZQUDbmlsAR9pbmNyZW1lbnRQb3NpdGlvblNlcXVlbmNlTnVtYmVyAg5faXNOZXdQb3NpdGlvbghfYWRkcmVzcwMFDl9pc05ld1Bvc2l0aW9uBA9jdXJyZW50U2VxdWVuY2UJAQxsYXN0U2VxdWVuY2UACQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRJrX3Bvc2l0aW9uU2VxdWVuY2UFCF9hZGRyZXNzCQBkAgUPY3VycmVudFNlcXVlbmNlAAEJAMwIAgkBDEludGVnZXJFbnRyeQIFCmtfc2VxdWVuY2UJAGQCBQ9jdXJyZW50U2VxdWVuY2UAAQUDbmlsBQNuaWwBEXVwZGF0ZVBvc2l0aW9uRmVlAw5faXNOZXdQb3NpdGlvbghfYWRkcmVzcwRfZmVlAwUOX2lzTmV3UG9zaXRpb24JAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFDWtfcG9zaXRpb25GZWUFCF9hZGRyZXNzBQRfZmVlBQNuaWwFA25pbAEOdXBkYXRlUG9zaXRpb24GCF9hZGRyZXNzBV9zaXplB19tYXJnaW4NX29wZW5Ob3Rpb25hbCBfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbhBfbGF0ZXN0VGltZXN0YW1wCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBQ5rX3Bvc2l0aW9uU2l6ZQUIX2FkZHJlc3MFBV9zaXplCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRBrX3Bvc2l0aW9uTWFyZ2luBQhfYWRkcmVzcwUHX21hcmdpbgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUWa19wb3NpdGlvbk9wZW5Ob3Rpb25hbAUIX2FkZHJlc3MFDV9vcGVuTm90aW9uYWwJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFLmtfcG9zaXRpb25MYXN0VXBkYXRlZEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FCF9hZGRyZXNzBSBfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUea19wb3NpdGlvbkxhc3RVcGRhdGVkVGltZXN0YW1wBQhfYWRkcmVzcwUQX2xhdGVzdFRpbWVzdGFtcAUDbmlsAQphcHBlbmRUd2FwAQZfcHJpY2UECG1pbnV0ZUlkCQBpAgkAaQIJAQ1sYXN0VGltZXN0YW1wAADoBwA8BBBwcmV2aW91c01pbnV0ZUlkCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFDmtfbGFzdE1pbnV0ZUlkAAADCQBmAgUQcHJldmlvdXNNaW51dGVJZAUIbWludXRlSWQJAAIBAhFUV0FQIG91dC1vZi1vcmRlcgQMbGFzdE1pbnV0ZUlkAwkAAAIFEHByZXZpb3VzTWludXRlSWQAAAUIbWludXRlSWQFEHByZXZpb3VzTWludXRlSWQDCQBmAgUIbWludXRlSWQFEHByZXZpb3VzTWludXRlSWQEE3ByZXZDdW11bGF0aXZlUHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkArAICCQCsAgIFHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlAgFfCQCkAwEFEHByZXZpb3VzTWludXRlSWQAAAQJcHJldlByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAKwCAgkArAICBRNrX3R3YXBEYXRhTGFzdFByaWNlAgFfCQCkAwEFEHByZXZpb3VzTWludXRlSWQFBl9wcmljZQQTbGFzdEN1bXVsYXRpdmVQcmljZQkAZAIFE3ByZXZDdW11bGF0aXZlUHJpY2UJAGgCCQBlAgUIbWludXRlSWQFDGxhc3RNaW51dGVJZAUJcHJldlByaWNlBARsaXN0CQELcHVzaFRvUXVldWUDCQEJc3RyVG9MaXN0AQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzBQ1rX2xhc3REYXRhU3RyAgAFDVRXQVBfSU5URVJWQUwJAKQDAQUIbWludXRlSWQJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlCQCkAwEFCG1pbnV0ZUlkBRNsYXN0Q3VtdWxhdGl2ZVByaWNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRNrX3R3YXBEYXRhTGFzdFByaWNlCQCkAwEFCG1pbnV0ZUlkBQZfcHJpY2UJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFGmtfdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkCQCkAwEFCG1pbnV0ZUlkBRBwcmV2aW91c01pbnV0ZUlkCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ5rX2xhc3RNaW51dGVJZAUIbWludXRlSWQJAMwIAgkBC1N0cmluZ0VudHJ5AgUNa19sYXN0RGF0YVN0cgkBCWxpc3RUb1N0cgEFBGxpc3QFA25pbAQYdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFGmtfdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkCQCkAwEFCG1pbnV0ZUlkAAAEE3ByZXZDdW11bGF0aXZlUHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UJAKQDAQUYdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkAAAECXByZXZQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBRNrX3R3YXBEYXRhTGFzdFByaWNlCQCkAwEFGHR3YXBEYXRhUHJldmlvdXNNaW51dGVJZAUGX3ByaWNlBBNsYXN0Q3VtdWxhdGl2ZVByaWNlCQBkAgUTcHJldkN1bXVsYXRpdmVQcmljZQkAaAIJAGUCBQhtaW51dGVJZAUYdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkBQlwcmV2UHJpY2UJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlCQCkAwEFCG1pbnV0ZUlkBRNsYXN0Q3VtdWxhdGl2ZVByaWNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRNrX3R3YXBEYXRhTGFzdFByaWNlCQCkAwEFCG1pbnV0ZUlkBQZfcHJpY2UFA25pbAERdXBkYXRlQW1tUmVzZXJ2ZXMCB19xdEFzdFIHX2JzQXN0UgkAzAgCCQEMSW50ZWdlckVudHJ5AgUTa19xdW90ZUFzc2V0UmVzZXJ2ZQUHX3F0QXN0UgkAzAgCCQEMSW50ZWdlckVudHJ5AgUSa19iYXNlQXNzZXRSZXNlcnZlBQdfYnNBc3RSBQNuaWwBEHVwZGF0ZUFtbVdlaWdodHMCB19xdEFzdFcHX2JzQXN0VwkAzAgCCQEMSW50ZWdlckVudHJ5AgUSa19xdW90ZUFzc2V0V2VpZ2h0BQdfcXRBc3RXCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRFrX2Jhc2VBc3NldFdlaWdodAUHX2JzQXN0VwUDbmlsAQl1cGRhdGVBbW0IB19xdEFzdFIHX2JzQXN0UhdfdG90YWxQb3NpdGlvblNpemVBZnRlchVfb3BlbkludGVyZXN0Tm90aW9uYWwWX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZRdfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZRZfdG90YWxMb25nT3Blbk5vdGlvbmFsF190b3RhbFNob3J0T3Blbk5vdGlvbmFsBAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwADCQECIT0CCQBlAgUWX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQUXX3RvdGFsU2hvcnRQb3NpdGlvblNpemUFF190b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgICGEludmFsaWQgQU1NIHN0YXRlIGRhdGE6IAkApAMBBRZfdG90YWxMb25nUG9zaXRpb25TaXplAgQgKyAgCQCkAwEFF190b3RhbFNob3J0UG9zaXRpb25TaXplAgQgIT0gCQCkAwEFF190b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCQDOCAIJAM4IAgkBEXVwZGF0ZUFtbVJlc2VydmVzAgUHX3F0QXN0UgUHX2JzQXN0UgkAzAgCCQEMSW50ZWdlckVudHJ5AgUTa190b3RhbFBvc2l0aW9uU2l6ZQUXX3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIJAMwIAgkBDEludGVnZXJFbnRyeQIFFmtfb3BlbkludGVyZXN0Tm90aW9uYWwFFV9vcGVuSW50ZXJlc3ROb3Rpb25hbAkAzAgCCQEMSW50ZWdlckVudHJ5AgUXa190b3RhbExvbmdQb3NpdGlvblNpemUFFl90b3RhbExvbmdQb3NpdGlvblNpemUJAMwIAgkBDEludGVnZXJFbnRyeQIFGGtfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQUXX3RvdGFsU2hvcnRQb3NpdGlvblNpemUJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfb3BlbkludGVyZXN0TG9uZwUWX3RvdGFsTG9uZ09wZW5Ob3Rpb25hbAkAzAgCCQEMSW50ZWdlckVudHJ5AgUTa19vcGVuSW50ZXJlc3RTaG9ydAUXX3RvdGFsU2hvcnRPcGVuTm90aW9uYWwFA25pbAkBCmFwcGVuZFR3YXABCQEEZGl2ZAIJAQRtdWxkAgUHX3F0QXN0UgUHX3F0QXN0VwkBBG11bGQCBQdfYnNBc3RSBQdfYnNBc3RXAQ5kZWxldGVQb3NpdGlvbgEIX2FkZHJlc3MJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBDnRvQ29tcG9zaXRlS2V5AgUOa19wb3NpdGlvblNpemUFCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFEGtfcG9zaXRpb25NYXJnaW4FCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFFmtfcG9zaXRpb25PcGVuTm90aW9uYWwFCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFLmtfcG9zaXRpb25MYXN0VXBkYXRlZEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFD2tfcG9zaXRpb25Bc3NldAUIX2FkZHJlc3MJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBDnRvQ29tcG9zaXRlS2V5AgUNa19wb3NpdGlvbkZlZQUIX2FkZHJlc3MJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBDnRvQ29tcG9zaXRlS2V5AgUea19wb3NpdGlvbkxhc3RVcGRhdGVkVGltZXN0YW1wBQhfYWRkcmVzcwUDbmlsAQh3aXRoZHJhdwIIX2FkZHJlc3MHX2Ftb3VudAQHYmFsYW5jZQkA8AcCBQR0aGlzCQEKcXVvdGVBc3NldAADCQBmAgUHX2Ftb3VudAUHYmFsYW5jZQkAAgEJAKwCAgkArAICCQCsAgICE1VuYWJsZSB0byB3aXRoZHJhdyAJAKQDAQUHX2Ftb3VudAIXIGZyb20gY29udHJhY3QgYmFsYW5jZSAJAKQDAQUHYmFsYW5jZQkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQhfYWRkcmVzcwUHX2Ftb3VudAkBCnF1b3RlQXNzZXQABQNuaWwBDXVwZGF0ZUJhbGFuY2UBAWkDCQBmAgAABQFpCQACAQIHQmFsYW5jZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUJa19iYWxhbmNlBQFpBQNuaWwBC3RyYW5zZmVyRmVlAQFpCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMJAQ5zdGFraW5nQWRkcmVzcwAFAWkJAQpxdW90ZUFzc2V0AAUDbmlsAQ5kb0J1cm5BcnRpZmFjdAINX2J1cm5BcnRpZmFjdAFpAwUNX2J1cm5BcnRpZmFjdAkAzAgCCQEEQnVybgIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAggJAJEDAggFAWkIcGF5bWVudHMAAQdhc3NldElkAhBJbnZhbGlkIGFydGlmYWN0AAEFA25pbAUDbmlsFgFpAQVwYXVzZQADCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MACQACAQIUSW52YWxpZCBwYXVzZSBwYXJhbXMJAMwIAgkBDEJvb2xlYW5FbnRyeQIFCGtfcGF1c2VkBgUDbmlsAWkBB3VucGF1c2UAAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECFkludmFsaWQgdW5wYXVzZSBwYXJhbXMJAMwIAgkBDEJvb2xlYW5FbnRyeQIFCGtfcGF1c2VkBwUDbmlsAWkBDHNldENsb3NlT25seQADCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MACQACAQIbSW52YWxpZCBzZXRDbG9zZU9ubHkgcGFyYW1zCQDMCAIJAQxCb29sZWFuRW50cnkCBQtrX2Nsb3NlT25seQYFA25pbAFpAQ51bnNldENsb3NlT25seQADCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MACQACAQIdSW52YWxpZCB1bnNldENsb3NlT25seSBwYXJhbXMJAMwIAgkBDEJvb2xlYW5FbnRyeQIFC2tfY2xvc2VPbmx5BwUDbmlsAWkBDGFkZExpcXVpZGl0eQERX3F1b3RlQXNzZXRBbW91bnQDAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAYJAGcCAAAFEV9xdW90ZUFzc2V0QW1vdW50CQACAQIbSW52YWxpZCBhZGRMaXF1aWRpdHkgcGFyYW1zBAdfcXRBc3RSCQEGcXRBc3RSAAQHX2JzQXN0UgkBBmJzQXN0UgAEB19xdEFzdFcJAQZxdEFzdFcABAdfYnNBc3RXCQEGYnNBc3RXAAQFcHJpY2UJAQRkaXZkAgkBBG11bGQCBQdfcXRBc3RSBQdfcXRBc3RXCQEEbXVsZAIFB19ic0FzdFIFB19ic0FzdFcEC3F0QXN0UkFmdGVyCQBkAgUHX3F0QXN0UgURX3F1b3RlQXNzZXRBbW91bnQEFGJhc2VBc3NldEFtb3VudFRvQWRkCQBlAgkBBGRpdmQCCQEEbXVsZAIFC3F0QXN0UkFmdGVyBQdfcXRBc3RXBQVwcmljZQUHX2JzQXN0UgQLYnNBc3RSQWZ0ZXIJAGQCBQdfYnNBc3RSBRRiYXNlQXNzZXRBbW91bnRUb0FkZAQNJHQwNTI4NzY1MzAyNwkBFGdldFN5bmNUZXJtaW5hbFByaWNlAwkBDmdldE9yYWNsZVByaWNlAAULcXRBc3RSQWZ0ZXIFC2JzQXN0UkFmdGVyBBNuZXdRdW90ZUFzc2V0V2VpZ2h0CAUNJHQwNTI4NzY1MzAyNwJfMQQSbmV3QmFzZUFzc2V0V2VpZ2h0CAUNJHQwNTI4NzY1MzAyNwJfMgQNbWFyZ2luVG9WYXVsdAgFDSR0MDUyODc2NTMwMjcCXzMEDWRvRXhjaGFuZ2VQbkwDCQECIT0CBQ1tYXJnaW5Ub1ZhdWx0AAAEDWRvRXhjaGFuZ2VQbkwJAPwHBAkBDHZhdWx0QWRkcmVzcwACFWV4Y2hhbmdlRnJlZUFuZExvY2tlZAkAzAgCBQ1tYXJnaW5Ub1ZhdWx0BQNuaWwFA25pbAMJAAACBQ1kb0V4Y2hhbmdlUG5MBQ1kb0V4Y2hhbmdlUG5MBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBQ1kb0V4Y2hhbmdlUG5MBQ1kb0V4Y2hhbmdlUG5MCQDOCAIJARF1cGRhdGVBbW1SZXNlcnZlcwIFC3F0QXN0UkFmdGVyBQtic0FzdFJBZnRlcgkBEHVwZGF0ZUFtbVdlaWdodHMCBRNuZXdRdW90ZUFzc2V0V2VpZ2h0BRJuZXdCYXNlQXNzZXRXZWlnaHQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEPcmVtb3ZlTGlxdWlkaXR5ARFfcXVvdGVBc3NldEFtb3VudAMDCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MABgkAZwIFEV9xdW90ZUFzc2V0QW1vdW50AAAJAAIBAh5JbnZhbGlkIHJlbW92ZUxpcXVpZGl0eSBwYXJhbXMEB19xdEFzdFIJAQZxdEFzdFIABAdfYnNBc3RSCQEGYnNBc3RSAAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcABAVwcmljZQkBBGRpdmQCCQEEbXVsZAIFB19xdEFzdFIFB19xdEFzdFcJAQRtdWxkAgUHX2JzQXN0UgUHX2JzQXN0VwQLcXRBc3RSQWZ0ZXIJAGUCBQdfcXRBc3RSBRFfcXVvdGVBc3NldEFtb3VudAQXYmFzZUFzc2V0QW1vdW50VG9SZW1vdmUJAQNhYnMBCQBlAgkBBGRpdmQCCQEEbXVsZAIFC3F0QXN0UkFmdGVyBQdfcXRBc3RXBQVwcmljZQUHX2JzQXN0UgQLYnNBc3RSQWZ0ZXIJAGUCBQdfYnNBc3RSBRdiYXNlQXNzZXRBbW91bnRUb1JlbW92ZQQNJHQwNTM5NTk1NDExMAkBFGdldFN5bmNUZXJtaW5hbFByaWNlAwkBDmdldE9yYWNsZVByaWNlAAULcXRBc3RSQWZ0ZXIFC2JzQXN0UkFmdGVyBBNuZXdRdW90ZUFzc2V0V2VpZ2h0CAUNJHQwNTM5NTk1NDExMAJfMQQSbmV3QmFzZUFzc2V0V2VpZ2h0CAUNJHQwNTM5NTk1NDExMAJfMgQNbWFyZ2luVG9WYXVsdAgFDSR0MDUzOTU5NTQxMTACXzMEDWRvRXhjaGFuZ2VQbkwDCQECIT0CBQ1tYXJnaW5Ub1ZhdWx0AAAEDWRvRXhjaGFuZ2VQbkwJAPwHBAkBDHZhdWx0QWRkcmVzcwACFWV4Y2hhbmdlRnJlZUFuZExvY2tlZAkAzAgCBQ1tYXJnaW5Ub1ZhdWx0BQNuaWwFA25pbAMJAAACBQ1kb0V4Y2hhbmdlUG5MBQ1kb0V4Y2hhbmdlUG5MBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBQ1kb0V4Y2hhbmdlUG5MBQ1kb0V4Y2hhbmdlUG5MCQDOCAIJARF1cGRhdGVBbW1SZXNlcnZlcwIFC3F0QXN0UkFmdGVyBQtic0FzdFJBZnRlcgkBEHVwZGF0ZUFtbVdlaWdodHMCBRNuZXdRdW90ZUFzc2V0V2VpZ2h0BRJuZXdCYXNlQXNzZXRXZWlnaHQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEOY2hhbmdlU2V0dGluZ3MNEF9pbml0TWFyZ2luUmF0aW8EX21tchRfbGlxdWlkYXRpb25GZWVSYXRpbw5fZnVuZGluZ1BlcmlvZARfZmVlDF9zcHJlYWRMaW1pdA9fbWF4UHJpY2VJbXBhY3QYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvD19tYXhQcmljZVNwcmVhZBBfbWF4T3Blbk5vdGlvbmFsFF9mZWVUb1N0YWtlcnNQZXJjZW50D19tYXhPcmFjbGVEZWxheQxfcm9sbG92ZXJGZWUDCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MACQACAQIdSW52YWxpZCBjaGFuZ2VTZXR0aW5ncyBwYXJhbXMJAQ51cGRhdGVTZXR0aW5ncw0FEF9pbml0TWFyZ2luUmF0aW8FBF9tbXIFFF9saXF1aWRhdGlvbkZlZVJhdGlvBQ5fZnVuZGluZ1BlcmlvZAUEX2ZlZQUMX3NwcmVhZExpbWl0BQ9fbWF4UHJpY2VJbXBhY3QFGF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwUPX21heFByaWNlU3ByZWFkBRBfbWF4T3Blbk5vdGlvbmFsBRRfZmVlVG9TdGFrZXJzUGVyY2VudAUPX21heE9yYWNsZURlbGF5BQxfcm9sbG92ZXJGZWUBaQEKaW5pdGlhbGl6ZRIHX3F0QXN0UgdfYnNBc3RSDl9mdW5kaW5nUGVyaW9kEF9pbml0TWFyZ2luUmF0aW8EX21tchRfbGlxdWlkYXRpb25GZWVSYXRpbwRfZmVlD19iYXNlT3JhY2xlRGF0YRBfcXVvdGVPcmFjbGVEYXRhDF9jb29yZGluYXRvcgxfc3ByZWFkTGltaXQPX21heFByaWNlSW1wYWN0GF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbw9fbWF4UHJpY2VTcHJlYWQQX21heE9wZW5Ob3Rpb25hbBRfZmVlVG9TdGFrZXJzUGVyY2VudA9fbWF4T3JhY2xlRGVsYXkMX3JvbGxvdmVyRmVlAwMDAwMDAwMDAwMDAwMDAwMDCQBnAgAABQdfcXRBc3RSBgkAZwIAAAUHX2JzQXN0UgYJAGcCAAAFDl9mdW5kaW5nUGVyaW9kBgkAZwIAAAUQX2luaXRNYXJnaW5SYXRpbwYJAGcCAAAFBF9tbXIGCQBnAgAABRRfbGlxdWlkYXRpb25GZWVSYXRpbwYJAGcCAAAFBF9mZWUGCQBnAgAABQxfc3ByZWFkTGltaXQGCQBnAgAABQ9fbWF4UHJpY2VJbXBhY3QGCQBnAgAABRhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8GCQBnAgAABQ9fbWF4UHJpY2VTcHJlYWQGCQBnAgAABRBfbWF4T3Blbk5vdGlvbmFsBgkAZwIAAAUUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQGCQBmAgUUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQFDERFQ0lNQUxfVU5JVAYJAGcCAAAFD19tYXhPcmFjbGVEZWxheQYJAGcCAAAFDF9yb2xsb3ZlckZlZQYJAQtpbml0aWFsaXplZAAGCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAh1JbnZhbGlkIGluaXRpYWxpemUgcGFyYW1ldGVycwkAzggCCQDOCAIJAM4IAgkAzggCCQEJdXBkYXRlQW1tCAUHX3F0QXN0UgUHX2JzQXN0UgAAAAAAAAAAAAAAAAkBDnVwZGF0ZVNldHRpbmdzDQUQX2luaXRNYXJnaW5SYXRpbwUEX21tcgUUX2xpcXVpZGF0aW9uRmVlUmF0aW8FDl9mdW5kaW5nUGVyaW9kBQRfZmVlBQxfc3ByZWFkTGltaXQFD19tYXhQcmljZUltcGFjdAUYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvBQ9fbWF4UHJpY2VTcHJlYWQFEF9tYXhPcGVuTm90aW9uYWwFFF9mZWVUb1N0YWtlcnNQZXJjZW50BQ9fbWF4T3JhY2xlRGVsYXkFDF9yb2xsb3ZlckZlZQkBDXVwZGF0ZUZ1bmRpbmcFCQBkAgkBDWxhc3RUaW1lc3RhbXAABQ5fZnVuZGluZ1BlcmlvZAAAAAAAAAAACQENdXBkYXRlQmFsYW5jZQEAAAkAzAgCCQEMQm9vbGVhbkVudHJ5AgUNa19pbml0aWFsaXplZAYJAMwIAgkBC1N0cmluZ0VudHJ5AgUMa19iYXNlT3JhY2xlBQ9fYmFzZU9yYWNsZURhdGEJAMwIAgkBC1N0cmluZ0VudHJ5AgUNa19xdW90ZU9yYWNsZQUQX3F1b3RlT3JhY2xlRGF0YQkAzAgCCQELU3RyaW5nRW50cnkCBRRrX2Nvb3JkaW5hdG9yQWRkcmVzcwkApQgBCQERQGV4dHJOYXRpdmUoMTA2MikBBQxfY29vcmRpbmF0b3IFA25pbAFpARBpbmNyZWFzZVBvc2l0aW9uBApfZGlyZWN0aW9uCV9sZXZlcmFnZRNfbWluQmFzZUFzc2V0QW1vdW50CF9yZWZMaW5rBARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEEGVuc3VyZUNhbGxlZE9uY2UJAPwHBAUEdGhpcwIQZW5zdXJlQ2FsbGVkT25jZQUDbmlsBQNuaWwDCQAAAgUQZW5zdXJlQ2FsbGVkT25jZQUQZW5zdXJlQ2FsbGVkT25jZQQHX3RyYWRlcgkBD2dldEFjdHVhbENhbGxlcgEFAWkECl9yYXdBbW91bnQICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50BAhfYXNzZXRJZAgJAJEDAggFAWkIcGF5bWVudHMAAAdhc3NldElkBAtfYXNzZXRJZFN0cgkA2AQBCQEFdmFsdWUBBQhfYXNzZXRJZAQMaXNRdW90ZUFzc2V0CQAAAgUIX2Fzc2V0SWQJAQpxdW90ZUFzc2V0AAMDAwMDAwMDAwMJAQIhPQIFCl9kaXJlY3Rpb24FCERJUl9MT05HCQECIT0CBQpfZGlyZWN0aW9uBQlESVJfU0hPUlQHBgkAZwIAAAUKX3Jhd0Ftb3VudAYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQEhAQUMaXNRdW90ZUFzc2V0BgkBASEBCQEXaXNTYW1lQXNzZXRPck5vUG9zaXRpb24CBQdfdHJhZGVyBQtfYXNzZXRJZFN0cgYJAQEhAQkBFnJlcXVpcmVNb3JlTWFyZ2luUmF0aW8DCQEEZGl2ZAIFDERFQ0lNQUxfVU5JVAUJX2xldmVyYWdlCQEPaW5pdE1hcmdpblJhdGlvAAYGCQEGcGF1c2VkAAYJAQljbG9zZU9ubHkABgkBDmlzTWFya2V0Q2xvc2VkAAkAAgECI0ludmFsaWQgaW5jcmVhc2VQb3NpdGlvbiBwYXJhbWV0ZXJzBA0kdDA1Nzg4ODU4MDM3CQEYZ2V0Rm9yVHJhZGVyV2l0aEFydGlmYWN0AgUHX3RyYWRlcgkBDWdldEFydGlmYWN0SWQBBQFpBAthZGp1c3RlZEZlZQgFDSR0MDU3ODg4NTgwMzcCXzEEDGJ1cm5BcnRpZmFjdAgFDSR0MDU3ODg4NTgwMzcCXzIEB19hbW91bnQJAQRkaXZkAgUKX3Jhd0Ftb3VudAkAZAIJAQRtdWxkAgULYWRqdXN0ZWRGZWUFCV9sZXZlcmFnZQUMREVDSU1BTF9VTklUBBNkaXN0cmlidXRlRmVlQW1vdW50CQBlAgUKX3Jhd0Ftb3VudAUHX2Ftb3VudAQOcmVmZXJyZXJGZWVBbnkJAPwHBAkBD3JlZmVycmFsQWRkcmVzcwACFWFjY2VwdFBheW1lbnRXaXRoTGluawkAzAgCBQdfdHJhZGVyCQDMCAIFCF9yZWZMaW5rBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUTZGlzdHJpYnV0ZUZlZUFtb3VudAUDbmlsAwkAAAIFDnJlZmVycmVyRmVlQW55BQ5yZWZlcnJlckZlZUFueQQLcmVmZXJyZXJGZWUEByRtYXRjaDAFDnJlZmVycmVyRmVlQW55AwkAAQIFByRtYXRjaDACA0ludAQBeAUHJG1hdGNoMAUBeAkAAgECE0ludmFsaWQgcmVmZXJyZXJGZWUECWZlZUFtb3VudAkAZQIFE2Rpc3RyaWJ1dGVGZWVBbW91bnQFC3JlZmVycmVyRmVlBA0kdDA1ODUzMzU4NzAxCQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBA9vbGRQb3NpdGlvblNpemUIBQ0kdDA1ODUzMzU4NzAxAl8xBBFvbGRQb3NpdGlvbk1hcmdpbggFDSR0MDU4NTMzNTg3MDECXzIEF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNTg1MzM1ODcwMQJfMwQUb2xkUG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA1ODUzMzU4NzAxAl80BBRvbGRQb3NpdGlvblRpbWVzdGFtcAgFDSR0MDU4NTMzNTg3MDECXzUEDWlzTmV3UG9zaXRpb24JAAACBQ9vbGRQb3NpdGlvblNpemUAAAQPaXNTYW1lRGlyZWN0aW9uAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAACQAAAgUKX2RpcmVjdGlvbgUIRElSX0xPTkcJAAACBQpfZGlyZWN0aW9uBQlESVJfU0hPUlQEDmV4cGFuZEV4aXN0aW5nAwkBASEBBQ1pc05ld1Bvc2l0aW9uBQ9pc1NhbWVEaXJlY3Rpb24HBAVpc0FkZAkAAAIFCl9kaXJlY3Rpb24FCERJUl9MT05HBA0kdDA1ODk5MDYyMTExAwMFDWlzTmV3UG9zaXRpb24GBQ5leHBhbmRFeGlzdGluZwQMb3Blbk5vdGlvbmFsCQEEbXVsZAIFB19hbW91bnQFCV9sZXZlcmFnZQQNJHQwNTk0OTk1OTY3MgkBCXN3YXBJbnB1dAIFBWlzQWRkBQxvcGVuTm90aW9uYWwEFWFtb3VudEJhc2VBc3NldEJvdWdodAgFDSR0MDU5NDk5NTk2NzICXzEEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA1OTQ5OTU5NjcyAl8yBBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA1OTQ5OTU5NjcyAl8zBBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNTk0OTk1OTY3MgJfNAMDCQECIT0CBRNfbWluQmFzZUFzc2V0QW1vdW50AAAJAGYCBRNfbWluQmFzZUFzc2V0QW1vdW50CQEDYWJzAQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0BwkAAgEJAKwCAgkArAICCQCsAgICDUxpbWl0IGVycm9yOiAJAKQDAQkBA2FicwEFFWFtb3VudEJhc2VBc3NldEJvdWdodAIDIDwgCQCkAwEFE19taW5CYXNlQXNzZXRBbW91bnQED25ld1Bvc2l0aW9uU2l6ZQkAZAIFD29sZFBvc2l0aW9uU2l6ZQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0BBp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgkAZAIJARBvcGVuSW50ZXJlc3RMb25nAAMJAGYCBQ9uZXdQb3NpdGlvblNpemUAAAUMb3Blbk5vdGlvbmFsAAAEG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgkAZAIJARFvcGVuSW50ZXJlc3RTaG9ydAADCQBmAgAABQ9uZXdQb3NpdGlvblNpemUFDG9wZW5Ob3Rpb25hbAAABA0kdDA2MDIxODYwNDkzCQEwY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudEFuZFJvbGxvdmVyRmVlBQUPb2xkUG9zaXRpb25TaXplBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25Mc3RVcGRDUEYFFG9sZFBvc2l0aW9uVGltZXN0YW1wBQdfYW1vdW50BAxyZW1haW5NYXJnaW4IBQ0kdDA2MDIxODYwNDkzAl8xBAJ4MQgFDSR0MDYwMjE4NjA0OTMCXzIEAngyCAUNJHQwNjAyMTg2MDQ5MwJfMwQLcm9sbG92ZXJGZWUIBQ0kdDA2MDIxODYwNDkzAl80AwkBASEBCQEZcmVxdWlyZU5vdE92ZXJTcHJlYWRMaW1pdAIFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgkAAgECFU92ZXIgbWF4IHNwcmVhZCBsaW1pdAMJAQEhAQkBHXJlcXVpcmVOb3RPdmVyTWF4T3Blbk5vdGlvbmFsAgUadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIFG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgkAAgECFk92ZXIgbWF4IG9wZW4gbm90aW9uYWwJAKAKDgUPbmV3UG9zaXRpb25TaXplBQxyZW1haW5NYXJnaW4JAGQCBRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAUMb3Blbk5vdGlvbmFsCQEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEFD25ld1Bvc2l0aW9uU2l6ZQkBDWxhc3RUaW1lc3RhbXAABRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIJAGQCCQEUb3BlbkludGVyZXN0Tm90aW9uYWwABQxvcGVuTm90aW9uYWwJAGQCCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAMJAGYCBQ9uZXdQb3NpdGlvblNpemUAAAkBA2FicwEFFWFtb3VudEJhc2VBc3NldEJvdWdodAAACQBkAgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUAAwkAZgIAAAUPbmV3UG9zaXRpb25TaXplCQEDYWJzAQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0AAAFGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyBRt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIFC3JvbGxvdmVyRmVlBAxvcGVuTm90aW9uYWwJAQRtdWxkAgUHX2Ftb3VudAUJX2xldmVyYWdlBA0kdDA2MTgxMTYxOTI3CQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCCQClCAEIBQFpBmNhbGxlcgUPUE5MX09QVElPTl9TUE9UBBNvbGRQb3NpdGlvbk5vdGlvbmFsCAUNJHQwNjE4MTE2MTkyNwJfMQQNdW5yZWFsaXplZFBubAgFDSR0MDYxODExNjE5MjcCXzIDCQBmAgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUMb3Blbk5vdGlvbmFsCQACAQIuVXNlIGRlY3JlYXNlUG9zaXRpb24gdG8gZGVjcmVhc2UgcG9zaXRpb24gc2l6ZQkAAgECFENsb3NlIHBvc2l0aW9uIGZpcnN0BA9uZXdQb3NpdGlvblNpemUIBQ0kdDA1ODk5MDYyMTExAl8xBBduZXdQb3NpdGlvblJlbWFpbk1hcmdpbggFDSR0MDU4OTkwNjIxMTECXzIEF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNTg5OTA2MjExMQJfMwQUbmV3UG9zaXRpb25MYXRlc3RDUEYIBQ0kdDA1ODk5MDYyMTExAl80BBRuZXdQb3NpdGlvblRpbWVzdGFtcAgFDSR0MDU4OTkwNjIxMTECXzUEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDU4OTkwNjIxMTECXzYEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA1ODk5MDYyMTExAl83BBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNTg5OTA2MjExMQJfOAQZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcggFDSR0MDU4OTkwNjIxMTECXzkEDnRvdGFsTG9uZ0FmdGVyCAUNJHQwNTg5OTA2MjExMQNfMTAED3RvdGFsU2hvcnRBZnRlcggFDSR0MDU4OTkwNjIxMTEDXzExBBp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDU4OTkwNjIxMTEDXzEyBBt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA1ODk5MDYyMTExA18xMwQLcm9sbG92ZXJGZWUIBQ0kdDA1ODk5MDYyMTExA18xNAQNJHQwNjIxMTc2MjE4OAkBDWRpc3RyaWJ1dGVGZWUBCQBkAgUJZmVlQW1vdW50BQtyb2xsb3ZlckZlZQQMZmVlVG9TdGFrZXJzCAUNJHQwNjIxMTc2MjE4OAJfMQQKZmVlVG9WYXVsdAgFDSR0MDYyMTE3NjIxODgCXzIEBXN0YWtlAwkAZwIFB19hbW91bnQFC3JvbGxvdmVyRmVlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAglhZGRMb2NrZWQFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQACQBlAgUHX2Ftb3VudAULcm9sbG92ZXJGZWUFA25pbAkA/AcECQEMdmF1bHRBZGRyZXNzAAIOd2l0aGRyYXdMb2NrZWQJAMwIAgkAZQIFC3JvbGxvdmVyRmVlBQdfYW1vdW50BQNuaWwFA25pbAMJAAACBQVzdGFrZQUFc3Rha2UEDGRlcG9zaXRWYXVsdAkA/AcECQEMdmF1bHRBZGRyZXNzAAIHYWRkRnJlZQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFCmZlZVRvVmF1bHQFA25pbAMJAAACBQxkZXBvc2l0VmF1bHQFDGRlcG9zaXRWYXVsdAQJbm90aWZ5RmVlCQD8BwQJAQxtaW5lckFkZHJlc3MAAgpub3RpZnlGZWVzCQDMCAIFB190cmFkZXIJAMwIAgUJZmVlQW1vdW50BQNuaWwFA25pbAMJAAACBQlub3RpZnlGZWUFCW5vdGlmeUZlZQQObm90aWZ5Tm90aW9uYWwJAPwHBAkBDG1pbmVyQWRkcmVzcwACDm5vdGlmeU5vdGlvbmFsCQDMCAIFB190cmFkZXIJAMwIAgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFA25pbAUDbmlsAwkAAAIFDm5vdGlmeU5vdGlvbmFsBQ5ub3RpZnlOb3Rpb25hbAkAzggCCQDOCAIJAM4IAgkAzggCCQDOCAIJAM4IAgkBDnVwZGF0ZVBvc2l0aW9uBgUHX3RyYWRlcgUPbmV3UG9zaXRpb25TaXplBRduZXdQb3NpdGlvblJlbWFpbk1hcmdpbgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFFG5ld1Bvc2l0aW9uTGF0ZXN0Q1BGBRRuZXdQb3NpdGlvblRpbWVzdGFtcAkBH2luY3JlbWVudFBvc2l0aW9uU2VxdWVuY2VOdW1iZXICBQ1pc05ld1Bvc2l0aW9uBQdfdHJhZGVyCQERdXBkYXRlUG9zaXRpb25GZWUDBQ1pc05ld1Bvc2l0aW9uBQdfdHJhZGVyBQthZGp1c3RlZEZlZQkBCXVwZGF0ZUFtbQgFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgUZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcgUOdG90YWxMb25nQWZ0ZXIFD3RvdGFsU2hvcnRBZnRlcgUadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIFG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgkBC3RyYW5zZmVyRmVlAQUMZmVlVG9TdGFrZXJzCQENdXBkYXRlQmFsYW5jZQEJAGUCCQBkAgkBCGNiYWxhbmNlAAUHX2Ftb3VudAULcm9sbG92ZXJGZWUJAQ5kb0J1cm5BcnRpZmFjdAIFDGJ1cm5BcnRpZmFjdAUBaQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQlhZGRNYXJnaW4ABARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEEGVuc3VyZUNhbGxlZE9uY2UJAPwHBAUEdGhpcwIQZW5zdXJlQ2FsbGVkT25jZQUDbmlsBQNuaWwDCQAAAgUQZW5zdXJlQ2FsbGVkT25jZQUQZW5zdXJlQ2FsbGVkT25jZQQHX3RyYWRlcgkApQgBCAUBaQZjYWxsZXIEB19hbW91bnQICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50BAhfYXNzZXRJZAgJAJEDAggFAWkIcGF5bWVudHMAAAdhc3NldElkBAtfYXNzZXRJZFN0cgkA2AQBCQEFdmFsdWUBBQhfYXNzZXRJZAQMaXNRdW90ZUFzc2V0CQAAAgUIX2Fzc2V0SWQJAQpxdW90ZUFzc2V0AAMDAwMDAwMJAQEhAQUMaXNRdW90ZUFzc2V0BgkBASEBCQETcmVxdWlyZU9wZW5Qb3NpdGlvbgEJAKUIAQgFAWkGY2FsbGVyBgkBASEBCQELaXNTYW1lQXNzZXQCBQdfdHJhZGVyBQtfYXNzZXRJZFN0cgYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQZwYXVzZWQABgkBCWNsb3NlT25seQAGCQEOaXNNYXJrZXRDbG9zZWQACQACAQIcSW52YWxpZCBhZGRNYXJnaW4gcGFyYW1ldGVycwQNJHQwNjQyOTk2NDQ2NwkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQPb2xkUG9zaXRpb25TaXplCAUNJHQwNjQyOTk2NDQ2NwJfMQQRb2xkUG9zaXRpb25NYXJnaW4IBQ0kdDA2NDI5OTY0NDY3Al8yBBdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDY0Mjk5NjQ0NjcCXzMEFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwNjQyOTk2NDQ2NwJfNAQUb2xkUG9zaXRpb25UaW1lc3RhbXAIBQ0kdDA2NDI5OTY0NDY3Al81BAVzdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIJYWRkTG9ja2VkBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUHX2Ftb3VudAUDbmlsAwkAAAIFBXN0YWtlBQVzdGFrZQQLcm9sbG92ZXJGZWUJAQ9jYWxjUm9sbG92ZXJGZWUCBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25UaW1lc3RhbXAEFmRvVHJhbnNmZXJGZWVUb1N0YWtlcnMDCQBmAgULcm9sbG92ZXJGZWUAAAQNJHQwNjQ3NTI2NDgxMQkBDWRpc3RyaWJ1dGVGZWUBBQtyb2xsb3ZlckZlZQQMZmVlVG9TdGFrZXJzCAUNJHQwNjQ3NTI2NDgxMQJfMQQKZmVlVG9WYXVsdAgFDSR0MDY0NzUyNjQ4MTECXzIEB3Vuc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACDndpdGhkcmF3TG9ja2VkCQDMCAIFDGZlZVRvU3Rha2VycwUDbmlsBQNuaWwDCQAAAgUHdW5zdGFrZQUHdW5zdGFrZQQLbG9ja0JhZERlYnQJAPwHBAkBDHZhdWx0QWRkcmVzcwACFWV4Y2hhbmdlRnJlZUFuZExvY2tlZAkAzAgCCQEBLQEFCmZlZVRvVmF1bHQFA25pbAUDbmlsAwkAAAIFC2xvY2tCYWREZWJ0BQtsb2NrQmFkRGVidAkBC3RyYW5zZmVyRmVlAQUMZmVlVG9TdGFrZXJzCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUWZG9UcmFuc2ZlckZlZVRvU3Rha2VycwUWZG9UcmFuc2ZlckZlZVRvU3Rha2VycwkAzggCCQDOCAIJAQ51cGRhdGVQb3NpdGlvbgYFB190cmFkZXIFD29sZFBvc2l0aW9uU2l6ZQkAZAIJAGUCBRFvbGRQb3NpdGlvbk1hcmdpbgULcm9sbG92ZXJGZWUFB19hbW91bnQFF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsBRRvbGRQb3NpdGlvbkxzdFVwZENQRgkBDWxhc3RUaW1lc3RhbXAACQENdXBkYXRlQmFsYW5jZQEJAGUCCQBkAgkBCGNiYWxhbmNlAAUHX2Ftb3VudAULcm9sbG92ZXJGZWUFFmRvVHJhbnNmZXJGZWVUb1N0YWtlcnMJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEMcmVtb3ZlTWFyZ2luAQdfYW1vdW50BARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEEGVuc3VyZUNhbGxlZE9uY2UJAPwHBAUEdGhpcwIQZW5zdXJlQ2FsbGVkT25jZQUDbmlsBQNuaWwDCQAAAgUQZW5zdXJlQ2FsbGVkT25jZQUQZW5zdXJlQ2FsbGVkT25jZQQHX3RyYWRlcgkApQgBCAUBaQZjYWxsZXIDAwMDAwkAZwIAAAUHX2Ftb3VudAYJAQEhAQkBE3JlcXVpcmVPcGVuUG9zaXRpb24BBQdfdHJhZGVyBgkBASEBCQELaW5pdGlhbGl6ZWQABgkBBnBhdXNlZAAGCQEOaXNNYXJrZXRDbG9zZWQACQACAQIfSW52YWxpZCByZW1vdmVNYXJnaW4gcGFyYW1ldGVycwQNJHQwNjU5MjM2NjA5MQkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQPb2xkUG9zaXRpb25TaXplCAUNJHQwNjU5MjM2NjA5MQJfMQQRb2xkUG9zaXRpb25NYXJnaW4IBQ0kdDA2NTkyMzY2MDkxAl8yBBdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDY1OTIzNjYwOTECXzMEFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwNjU5MjM2NjA5MQJfNAQUb2xkUG9zaXRpb25UaW1lc3RhbXAIBQ0kdDA2NTkyMzY2MDkxAl81BA0kdDA2NjA5NzY2MzQ2CQEwY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudEFuZFJvbGxvdmVyRmVlBQUPb2xkUG9zaXRpb25TaXplBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25Mc3RVcGRDUEYFFG9sZFBvc2l0aW9uVGltZXN0YW1wCQEBLQEFB19hbW91bnQEDHJlbWFpbk1hcmdpbggFDSR0MDY2MDk3NjYzNDYCXzEEB2JhZERlYnQIBQ0kdDA2NjA5NzY2MzQ2Al8yBA5mdW5kaW5nUGF5bWVudAgFDSR0MDY2MDk3NjYzNDYCXzMEC3JvbGxvdmVyRmVlCAUNJHQwNjYwOTc2NjM0NgJfNAMJAQIhPQIFB2JhZERlYnQAAAkAAgECHUludmFsaWQgcmVtb3ZlZCBtYXJnaW4gYW1vdW50BAttYXJnaW5SYXRpbwkBD2NhbGNNYXJnaW5SYXRpbwMFDHJlbWFpbk1hcmdpbgUHYmFkRGVidAUXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwDCQEBIQEJARZyZXF1aXJlTW9yZU1hcmdpblJhdGlvAwULbWFyZ2luUmF0aW8JAQ9pbml0TWFyZ2luUmF0aW8ABgkAAgEJAKwCAgkArAICCQCsAgICGVRvbyBtdWNoIG1hcmdpbiByZW1vdmVkOiAJAKQDAQULbWFyZ2luUmF0aW8CAyA8IAkApAMBCQEPaW5pdE1hcmdpblJhdGlvAAQNJHQwNjY3MzI2Njc5MQkBDWRpc3RyaWJ1dGVGZWUBBQtyb2xsb3ZlckZlZQQMZmVlVG9TdGFrZXJzCAUNJHQwNjY3MzI2Njc5MQJfMQQKZmVlVG9WYXVsdAgFDSR0MDY2NzMyNjY3OTECXzIEFmRvVHJhbnNmZXJGZWVUb1N0YWtlcnMDCQBmAgULcm9sbG92ZXJGZWUAAAQLbG9ja0JhZERlYnQJAPwHBAkBDHZhdWx0QWRkcmVzcwACFWV4Y2hhbmdlRnJlZUFuZExvY2tlZAkAzAgCCQEBLQEFCmZlZVRvVmF1bHQFA25pbAUDbmlsAwkAAAIFC2xvY2tCYWREZWJ0BQtsb2NrQmFkRGVidAkBC3RyYW5zZmVyRmVlAQUMZmVlVG9TdGFrZXJzCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUWZG9UcmFuc2ZlckZlZVRvU3Rha2VycwUWZG9UcmFuc2ZlckZlZVRvU3Rha2VycwQHdW5zdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIOd2l0aGRyYXdMb2NrZWQJAMwIAgkAZAIFB19hbW91bnQFDGZlZVRvU3Rha2VycwUDbmlsBQNuaWwDCQAAAgUHdW5zdGFrZQUHdW5zdGFrZQkAzggCCQDOCAIJAM4IAgkBDnVwZGF0ZVBvc2l0aW9uBgUHX3RyYWRlcgUPb2xkUG9zaXRpb25TaXplBQxyZW1haW5NYXJnaW4FF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCQEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEFD29sZFBvc2l0aW9uU2l6ZQkBDWxhc3RUaW1lc3RhbXAACQEId2l0aGRyYXcCCAUBaQZjYWxsZXIFB19hbW91bnQJAQ11cGRhdGVCYWxhbmNlAQkAZQIJAGUCCQEIY2JhbGFuY2UABQdfYW1vdW50BQtyb2xsb3ZlckZlZQUWZG9UcmFuc2ZlckZlZVRvU3Rha2VycwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ1jbG9zZVBvc2l0aW9uAwVfc2l6ZRRfbWluUXVvdGVBc3NldEFtb3VudAxfYWRkVG9NYXJnaW4EBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQQZW5zdXJlQ2FsbGVkT25jZQkA/AcEBQR0aGlzAhBlbnN1cmVDYWxsZWRPbmNlBQNuaWwFA25pbAMJAAACBRBlbnN1cmVDYWxsZWRPbmNlBRBlbnN1cmVDYWxsZWRPbmNlBAdfdHJhZGVyCQEPZ2V0QWN0dWFsQ2FsbGVyAQUBaQQOX3RyYWRlckFkZHJlc3MJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBBQdfdHJhZGVyAg5JbnZhbGlkIGNhbGxlcgQLcG9zaXRpb25GZWUJAQ5nZXRQb3NpdGlvbkZlZQEFB190cmFkZXIDAwMDAwMJAQEhAQkBE3JlcXVpcmVPcGVuUG9zaXRpb24BBQdfdHJhZGVyBgkBASEBCQELaW5pdGlhbGl6ZWQABgkBBnBhdXNlZAAGCQBnAgAABQVfc2l6ZQYJAGYCAAAFFF9taW5RdW90ZUFzc2V0QW1vdW50BgkBDmlzTWFya2V0Q2xvc2VkAAkAAgECIEludmFsaWQgY2xvc2VQb3NpdGlvbiBwYXJhbWV0ZXJzBBRvbGRQb3NpdGlvblRpbWVzdGFtcAgJAQtnZXRQb3NpdGlvbgEFB190cmFkZXICXzUEDSR0MDY4NDQ4NjkwMzMJARVpbnRlcm5hbENsb3NlUG9zaXRpb24HBQdfdHJhZGVyBQVfc2l6ZQULcG9zaXRpb25GZWUFFF9taW5RdW90ZUFzc2V0QW1vdW50BQxfYWRkVG9NYXJnaW4GBgQPbmV3UG9zaXRpb25TaXplCAUNJHQwNjg0NDg2OTAzMwJfMQQRbmV3UG9zaXRpb25NYXJnaW4IBQ0kdDA2ODQ0ODY5MDMzAl8yBBduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDY4NDQ4NjkwMzMCXzMEFG5ld1Bvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwNjg0NDg2OTAzMwJfNAQPcG9zaXRpb25CYWREZWJ0CAUNJHQwNjg0NDg2OTAzMwJfNQQLcmVhbGl6ZWRQbmwIBQ0kdDA2ODQ0ODY5MDMzAl82BA5tYXJnaW5Ub1RyYWRlcggFDSR0MDY4NDQ4NjkwMzMCXzcEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA2ODQ0ODY5MDMzAl84BBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA2ODQ0ODY5MDMzAl85BBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNjg0NDg2OTAzMwNfMTAEGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIIBQ0kdDA2ODQ0ODY5MDMzA18xMQQOdG90YWxMb25nQWZ0ZXIIBQ0kdDA2ODQ0ODY5MDMzA18xMgQPdG90YWxTaG9ydEFmdGVyCAUNJHQwNjg0NDg2OTAzMwNfMTMEGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNjg0NDg2OTAzMwNfMTQEG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDY4NDQ4NjkwMzMDXzE1BAtyZWFsaXplZEZlZQgFDSR0MDY4NDQ4NjkwMzMDXzE2AwkAZgIFD3Bvc2l0aW9uQmFkRGVidAAACQACAQIqSW52YWxpZCBjbG9zZVBvc2l0aW9uIHBhcmFtZXRlcnM6IGJhZCBkZWJ0AwkAZwIFFG9sZFBvc2l0aW9uVGltZXN0YW1wCQENbGFzdFRpbWVzdGFtcAAJAAIBAlNJbnZhbGlkIGNsb3NlUG9zaXRpb24gcGFyYW1ldGVyczogd2FpdCBhdCBsZWFzdCAxIGJsb2NrIGJlZm9yZSBjbG9zaW5nIHRoZSBwb3NpdGlvbgQOaXNQYXJ0aWFsQ2xvc2UJAQIhPQIFD25ld1Bvc2l0aW9uU2l6ZQAABA53aXRoZHJhd0Ftb3VudAkAZAIFDm1hcmdpblRvVHJhZGVyBQtyZWFsaXplZEZlZQQKYW1tQmFsYW5jZQkAZQIJAQhjYmFsYW5jZQAFDndpdGhkcmF3QW1vdW50BA1hbW1OZXdCYWxhbmNlAwkAZgIAAAUKYW1tQmFsYW5jZQAABQphbW1CYWxhbmNlBAd1bnN0YWtlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAg53aXRoZHJhd0xvY2tlZAkAzAgCBQ53aXRoZHJhd0Ftb3VudAUDbmlsBQNuaWwDCQAAAgUHdW5zdGFrZQUHdW5zdGFrZQQNJHQwNjk3MDU2OTc2NAkBDWRpc3RyaWJ1dGVGZWUBBQtyZWFsaXplZEZlZQQMZmVlVG9TdGFrZXJzCAUNJHQwNjk3MDU2OTc2NAJfMQQKZmVlVG9WYXVsdAgFDSR0MDY5NzA1Njk3NjQCXzIEDGRlcG9zaXRWYXVsdAkA/AcECQEMdmF1bHRBZGRyZXNzAAIHYWRkRnJlZQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFCmZlZVRvVmF1bHQFA25pbAMJAAACBQxkZXBvc2l0VmF1bHQFDGRlcG9zaXRWYXVsdAQJbm90aWZ5RmVlCQD8BwQJAQxtaW5lckFkZHJlc3MAAgpub3RpZnlGZWVzCQDMCAIFB190cmFkZXIJAMwIAgULcmVhbGl6ZWRGZWUFA25pbAUDbmlsAwkAAAIFCW5vdGlmeUZlZQUJbm90aWZ5RmVlBA5ub3RpZnlOb3Rpb25hbAkA/AcECQEMbWluZXJBZGRyZXNzAAIObm90aWZ5Tm90aW9uYWwJAMwIAgUHX3RyYWRlcgkAzAgCBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUDbmlsBQNuaWwDCQAAAgUObm90aWZ5Tm90aW9uYWwFDm5vdGlmeU5vdGlvbmFsCQDOCAIJAM4IAgkAzggCCQDOCAIDBQ5pc1BhcnRpYWxDbG9zZQkBDnVwZGF0ZVBvc2l0aW9uBgUHX3RyYWRlcgUPbmV3UG9zaXRpb25TaXplBRFuZXdQb3NpdGlvbk1hcmdpbgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFFG5ld1Bvc2l0aW9uTHN0VXBkQ1BGCQENbGFzdFRpbWVzdGFtcAAJAQ5kZWxldGVQb3NpdGlvbgEFB190cmFkZXIJAQl1cGRhdGVBbW0IBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIFDnRvdGFsTG9uZ0FmdGVyBQ90b3RhbFNob3J0QWZ0ZXIFGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyBRt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIDCQBmAgUObWFyZ2luVG9UcmFkZXIAAAkBCHdpdGhkcmF3AgUOX3RyYWRlckFkZHJlc3MFDm1hcmdpblRvVHJhZGVyBQNuaWwJAQ11cGRhdGVCYWxhbmNlAQUNYW1tTmV3QmFsYW5jZQkBC3RyYW5zZmVyRmVlAQUMZmVlVG9TdGFrZXJzCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCWxpcXVpZGF0ZQEHX3RyYWRlcgQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBA9zcG90TWFyZ2luUmF0aW8JARZnZXRNYXJnaW5SYXRpb0J5T3B0aW9uAgUHX3RyYWRlcgUPUE5MX09QVElPTl9TUE9UBBZsaXF1aWRhdGlvbk1hcmdpblJhdGlvAwkBFmlzT3ZlckZsdWN0dWF0aW9uTGltaXQABBFvcmFjbGVNYXJnaW5SYXRpbwkBFmdldE1hcmdpblJhdGlvQnlPcHRpb24CBQdfdHJhZGVyBRFQTkxfT1BUSU9OX09SQUNMRQkBBHZtYXgCBQ9zcG90TWFyZ2luUmF0aW8FEW9yYWNsZU1hcmdpblJhdGlvBQ9zcG90TWFyZ2luUmF0aW8DAwMDAwkBASEBCQEWcmVxdWlyZU1vcmVNYXJnaW5SYXRpbwMFFmxpcXVpZGF0aW9uTWFyZ2luUmF0aW8JARZtYWludGVuYW5jZU1hcmdpblJhdGlvAAcGCQEBIQEJARNyZXF1aXJlT3BlblBvc2l0aW9uAQUHX3RyYWRlcgYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQZwYXVzZWQABgkBDmlzTWFya2V0Q2xvc2VkAAkAAgECE1VuYWJsZSB0byBsaXF1aWRhdGUEFGlzUGFydGlhbExpcXVpZGF0aW9uAwMJAGYCBQ9zcG90TWFyZ2luUmF0aW8JARNsaXF1aWRhdGlvbkZlZVJhdGlvAAkAZgIJARdwYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwAAAAcJAGYCBQxERUNJTUFMX1VOSVQJARdwYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwAHBA9vbGRQb3NpdGlvblNpemUICQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyAl8xBA9wb3NpdGlvblNpemVBYnMJAQNhYnMBBQ9vbGRQb3NpdGlvblNpemUEDSR0MDcyMDc3NzI0MDADBRRpc1BhcnRpYWxMaXF1aWRhdGlvbgQPbGlxdWlkYXRpb25TaXplCQEbZ2V0UGFydGlhbExpcXVpZGF0aW9uQW1vdW50AgUHX3RyYWRlcgUPb2xkUG9zaXRpb25TaXplBBBsaXF1aWRhdGlvblJhdGlvCQEEZGl2ZAIJAQNhYnMBBQ9saXF1aWRhdGlvblNpemUFD3Bvc2l0aW9uU2l6ZUFicwkAlAoCBRBsaXF1aWRhdGlvblJhdGlvCQEDYWJzAQUPbGlxdWlkYXRpb25TaXplCQCUCgIAAAUPcG9zaXRpb25TaXplQWJzBBBsaXF1aWRhdGlvblJhdGlvCAUNJHQwNzIwNzc3MjQwMAJfMQQPbGlxdWlkYXRpb25TaXplCAUNJHQwNzIwNzc3MjQwMAJfMgQNJHQwNzI0MDY3MzA0NAkBFWludGVybmFsQ2xvc2VQb3NpdGlvbgcFB190cmFkZXIDBRRpc1BhcnRpYWxMaXF1aWRhdGlvbgUPbGlxdWlkYXRpb25TaXplBQ9wb3NpdGlvblNpemVBYnMJARNsaXF1aWRhdGlvbkZlZVJhdGlvAAAABgcGBA9uZXdQb3NpdGlvblNpemUIBQ0kdDA3MjQwNjczMDQ0Al8xBBFuZXdQb3NpdGlvbk1hcmdpbggFDSR0MDcyNDA2NzMwNDQCXzIEF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNzI0MDY3MzA0NAJfMwQUbmV3UG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA3MjQwNjczMDQ0Al80BA9wb3NpdGlvbkJhZERlYnQIBQ0kdDA3MjQwNjczMDQ0Al81BAtyZWFsaXplZFBubAgFDSR0MDcyNDA2NzMwNDQCXzYEDm1hcmdpblRvVHJhZGVyCAUNJHQwNzI0MDY3MzA0NAJfNwQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDcyNDA2NzMwNDQCXzgEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDcyNDA2NzMwNDQCXzkEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA3MjQwNjczMDQ0A18xMAQZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcggFDSR0MDcyNDA2NzMwNDQDXzExBA50b3RhbExvbmdBZnRlcggFDSR0MDcyNDA2NzMwNDQDXzEyBA90b3RhbFNob3J0QWZ0ZXIIBQ0kdDA3MjQwNjczMDQ0A18xMwQadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA3MjQwNjczMDQ0A18xNAQbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNzI0MDY3MzA0NANfMTUEEmxpcXVpZGF0aW9uUGVuYWx0eQgFDSR0MDcyNDA2NzMwNDQDXzE2BA9mZWVUb0xpcXVpZGF0b3IJAGkCBRJsaXF1aWRhdGlvblBlbmFsdHkAAgQKZmVlVG9WYXVsdAkAZQIFEmxpcXVpZGF0aW9uUGVuYWx0eQUPZmVlVG9MaXF1aWRhdG9yBAphbW1CYWxhbmNlCQBlAgkBCGNiYWxhbmNlAAUSbGlxdWlkYXRpb25QZW5hbHR5BA1uZXdBbW1CYWxhbmNlAwkAZgIAAAUKYW1tQmFsYW5jZQAABQphbW1CYWxhbmNlBAtsb2NrQmFkRGVidAMJAGYCBQ9wb3NpdGlvbkJhZERlYnQAAAQLbG9ja0JhZERlYnQJAPwHBAkBDHZhdWx0QWRkcmVzcwACFWV4Y2hhbmdlRnJlZUFuZExvY2tlZAkAzAgCCQBkAgUPcG9zaXRpb25CYWREZWJ0BRJsaXF1aWRhdGlvblBlbmFsdHkFA25pbAUDbmlsAwkAAAIFC2xvY2tCYWREZWJ0BQtsb2NrQmFkRGVidAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgULbG9ja0JhZERlYnQFC2xvY2tCYWREZWJ0BAd1bnN0YWtlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAg53aXRoZHJhd0xvY2tlZAkAzAgCBRJsaXF1aWRhdGlvblBlbmFsdHkFA25pbAUDbmlsAwkAAAIFB3Vuc3Rha2UFB3Vuc3Rha2UEEGRlcG9zaXRJbnN1cmFuY2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACB2FkZEZyZWUFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABQpmZWVUb1ZhdWx0BQNuaWwDCQAAAgUQZGVwb3NpdEluc3VyYW5jZQUQZGVwb3NpdEluc3VyYW5jZQQObm90aWZ5Tm90aW9uYWwJAPwHBAkBDG1pbmVyQWRkcmVzcwACDm5vdGlmeU5vdGlvbmFsCQDMCAIFB190cmFkZXIJAMwIAgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFA25pbAUDbmlsAwkAAAIFDm5vdGlmeU5vdGlvbmFsBQ5ub3RpZnlOb3Rpb25hbAkAzggCCQDOCAIJAM4IAgMFFGlzUGFydGlhbExpcXVpZGF0aW9uCQEOdXBkYXRlUG9zaXRpb24GBQdfdHJhZGVyBQ9uZXdQb3NpdGlvblNpemUFEW5ld1Bvc2l0aW9uTWFyZ2luBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUUbmV3UG9zaXRpb25Mc3RVcGRDUEYJAQ1sYXN0VGltZXN0YW1wAAkBDmRlbGV0ZVBvc2l0aW9uAQUHX3RyYWRlcgkBCXVwZGF0ZUFtbQgFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgUZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcgUOdG90YWxMb25nQWZ0ZXIFD3RvdGFsU2hvcnRBZnRlcgUadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIFG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgkBCHdpdGhkcmF3AggFAWkGY2FsbGVyBQ9mZWVUb0xpcXVpZGF0b3IJAQ11cGRhdGVCYWxhbmNlAQUNbmV3QW1tQmFsYW5jZQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQpwYXlGdW5kaW5nAAQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBBVmdW5kaW5nQmxvY2tUaW1lc3RhbXAJARluZXh0RnVuZGluZ0Jsb2NrVGltZXN0YW1wAAMDAwkAZgIFFWZ1bmRpbmdCbG9ja1RpbWVzdGFtcAkBDWxhc3RUaW1lc3RhbXAABgkBASEBCQELaW5pdGlhbGl6ZWQABgkBBnBhdXNlZAAJAAIBCQCsAgIJAKwCAgkArAICAiFJbnZhbGlkIGZ1bmRpbmcgYmxvY2sgdGltZXN0YW1wOiAJAKQDAQkBDWxhc3RUaW1lc3RhbXAAAgMgPCAJAKQDAQUVZnVuZGluZ0Jsb2NrVGltZXN0YW1wBA91bmRlcmx5aW5nUHJpY2UJAQ5nZXRPcmFjbGVQcmljZQAEDSR0MDc1MDMxNzUwOTMJAQpnZXRGdW5kaW5nAAQUc2hvcnRQcmVtaXVtRnJhY3Rpb24IBQ0kdDA3NTAzMTc1MDkzAl8xBBNsb25nUHJlbWl1bUZyYWN0aW9uCAUNJHQwNzUwMzE3NTA5MwJfMgkBDXVwZGF0ZUZ1bmRpbmcFCQBkAgUVZnVuZGluZ0Jsb2NrVGltZXN0YW1wCQEUZnVuZGluZ1BlcmlvZFNlY29uZHMACQBkAgkBI2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAUTbG9uZ1ByZW1pdW1GcmFjdGlvbgkAZAIJASRsYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24ABRRzaG9ydFByZW1pdW1GcmFjdGlvbgkBBGRpdmQCBRNsb25nUHJlbWl1bUZyYWN0aW9uBQ91bmRlcmx5aW5nUHJpY2UJAQRkaXZkAgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24FD3VuZGVybHlpbmdQcmljZQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlAAQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABA0kdDA3NTUyNTc1ODkxCQEUZ2V0U3luY1Rlcm1pbmFsUHJpY2UDCQEOZ2V0T3JhY2xlUHJpY2UABQdfcXRBc3RSBQdfYnNBc3RSBBNuZXdRdW90ZUFzc2V0V2VpZ2h0CAUNJHQwNzU1MjU3NTg5MQJfMQQSbmV3QmFzZUFzc2V0V2VpZ2h0CAUNJHQwNzU1MjU3NTg5MQJfMgQNbWFyZ2luVG9WYXVsdAgFDSR0MDc1NTI1NzU4OTECXzMEEG1hcmdpblRvVmF1bHRBZGoDAwkAZgIAAAUNbWFyZ2luVG9WYXVsdAkAZgIJAQNhYnMBBQ1tYXJnaW5Ub1ZhdWx0CQEIY2JhbGFuY2UABwkBAS0BCQEIY2JhbGFuY2UABQ1tYXJnaW5Ub1ZhdWx0BA1kb0V4Y2hhbmdlUG5MAwkBAiE9AgUQbWFyZ2luVG9WYXVsdEFkagAABA1kb0V4Y2hhbmdlUG5MCQD8BwQJAQx2YXVsdEFkZHJlc3MAAhVleGNoYW5nZUZyZWVBbmRMb2NrZWQJAMwIAgUQbWFyZ2luVG9WYXVsdEFkagUDbmlsBQNuaWwDCQAAAgUNZG9FeGNoYW5nZVBuTAUNZG9FeGNoYW5nZVBuTAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUNZG9FeGNoYW5nZVBuTAUNZG9FeGNoYW5nZVBuTAkAzggCCQDOCAIJAQ11cGRhdGVCYWxhbmNlAQkAZAIJAQhjYmFsYW5jZQAFEG1hcmdpblRvVmF1bHRBZGoJARB1cGRhdGVBbW1XZWlnaHRzAgUTbmV3UXVvdGVBc3NldFdlaWdodAUSbmV3QmFzZUFzc2V0V2VpZ2h0CQEKYXBwZW5kVHdhcAEJAQRkaXZkAgkBBG11bGQCBQdfcXRBc3RSBRNuZXdRdW90ZUFzc2V0V2VpZ2h0CQEEbXVsZAIFB19ic0FzdFIFEm5ld0Jhc2VBc3NldFdlaWdodAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARBlbnN1cmVDYWxsZWRPbmNlAAMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECIkludmFsaWQgc2F2ZUN1cnJlbnRUeElkIHBhcmFtZXRlcnMEBmxhc3RUeAkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzBQhrX2xhc3RUeAIAAwkBAiE9AgUGbGFzdFR4CQDYBAEIBQFpDXRyYW5zYWN0aW9uSWQJAMwIAgkBC1N0cmluZ0VudHJ5AgUIa19sYXN0VHgFBmxhc3RUeAUDbmlsCQACAQIpQ2FuIG5vdCBjYWxsIHZBTU0gbWV0aG9kcyB0d2ljZSBpbiBvbmUgdHgBaQEndmlld19jYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50AQdfdHJhZGVyBARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEDSR0MDc3MDUwNzcxNzQJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIEDHBvc2l0aW9uU2l6ZQgFDSR0MDc3MDUwNzcxNzQCXzEEDnBvc2l0aW9uTWFyZ2luCAUNJHQwNzcwNTA3NzE3NAJfMgQDcG9uCAUNJHQwNzcwNTA3NzE3NAJfMwQRcG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA3NzA1MDc3MTc0Al80BBFwb3NpdGlvblRpbWVzdGFtcAgFDSR0MDc3MDUwNzcxNzQCXzUEDSR0MDc3MTc3NzcyNzgJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAQQcG9zaXRpb25Ob3Rpb25hbAgFDSR0MDc3MTc3NzcyNzgCXzEEDXVucmVhbGl6ZWRQbmwIBQ0kdDA3NzE3Nzc3Mjc4Al8yBA0kdDA3NzI4MTc3NTA1CQEwY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudEFuZFJvbGxvdmVyRmVlBQUMcG9zaXRpb25TaXplBQ5wb3NpdGlvbk1hcmdpbgURcG9zaXRpb25Mc3RVcGRDUEYFEXBvc2l0aW9uVGltZXN0YW1wBQ11bnJlYWxpemVkUG5sBAxyZW1haW5NYXJnaW4IBQ0kdDA3NzI4MTc3NTA1Al8xBAdiYWREZWJ0CAUNJHQwNzcyODE3NzUwNQJfMgQOZnVuZGluZ1BheW1lbnQIBQ0kdDA3NzI4MTc3NTA1Al8zBAtyb2xsb3ZlckZlZQgFDSR0MDc3MjgxNzc1MDUCXzQJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQEBcwEFDHJlbWFpbk1hcmdpbgkBAXMBBQ5mdW5kaW5nUGF5bWVudAkBAXMBCQEOZ2V0TWFyZ2luUmF0aW8BBQdfdHJhZGVyCQEBcwEFDXVucmVhbGl6ZWRQbmwJAQFzAQUHYmFkRGVidAkBAXMBBRBwb3NpdGlvbk5vdGlvbmFsCQEBcwEFC3JvbGxvdmVyRmVlCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBFXZpZXdfZ2V0UGVnQWRqdXN0Q29zdAEGX3ByaWNlBAdfcXRBc3RSCQEGcXRBc3RSAAQHX2JzQXN0UgkBBmJzQXN0UgAEBnJlc3VsdAkBFGdldFN5bmNUZXJtaW5hbFByaWNlAwUGX3ByaWNlBQdfcXRBc3RSBQdfYnNBc3RSCQACAQkApAMBCAUGcmVzdWx0Al8zAWkBGHZpZXdfZ2V0VGVybWluYWxBbW1QcmljZQAEDSR0MDc3OTQxNzgwMjIJARNnZXRUZXJtaW5hbEFtbVN0YXRlAAQZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQgFDSR0MDc3OTQxNzgwMjICXzEEGHRlcm1pbmFsQmFzZUFzc2V0UmVzZXJ2ZQgFDSR0MDc3OTQxNzgwMjICXzIEBXByaWNlCQEEZGl2ZAIJAQRtdWxkAgUZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQkBBnF0QXN0VwAJAQRtdWxkAgUYdGVybWluYWxCYXNlQXNzZXRSZXNlcnZlCQEGYnNBc3RXAAkAAgEJAKQDAQUFcHJpY2UBaQEPdmlld19nZXRGdW5kaW5nAAQPdW5kZXJseWluZ1ByaWNlCQEOZ2V0T3JhY2xlUHJpY2UABA0kdDA3ODIzNzc4Mjk5CQEKZ2V0RnVuZGluZwAEFHNob3J0UHJlbWl1bUZyYWN0aW9uCAUNJHQwNzgyMzc3ODI5OQJfMQQTbG9uZ1ByZW1pdW1GcmFjdGlvbggFDSR0MDc4MjM3NzgyOTkCXzIEC2xvbmdGdW5kaW5nCQEEZGl2ZAIFE2xvbmdQcmVtaXVtRnJhY3Rpb24FD3VuZGVybHlpbmdQcmljZQQMc2hvcnRGdW5kaW5nCQEEZGl2ZAIFFHNob3J0UHJlbWl1bUZyYWN0aW9uBQ91bmRlcmx5aW5nUHJpY2UJAAIBCQCsAgIJAKwCAgkArAICCQEBcwEFC2xvbmdGdW5kaW5nCQEBcwEFDHNob3J0RnVuZGluZwkBAXMBCQEQZ2V0VHdhcFNwb3RQcmljZQAJAQFzAQkBDmdldE9yYWNsZVByaWNlAAFpARBjb21wdXRlU3BvdFByaWNlAAQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBAZyZXN1bHQJAQxnZXRTcG90UHJpY2UACQCUCgIFA25pbAUGcmVzdWx0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBH2NvbXB1dGVGZWVGb3JUcmFkZXJXaXRoQXJ0aWZhY3QCB190cmFkZXILX2FydGlmYWN0SWQEBnJlc3VsdAkBGGdldEZvclRyYWRlcldpdGhBcnRpZmFjdAIFB190cmFkZXIFC19hcnRpZmFjdElkCQCUCgIFA25pbAUGcmVzdWx0AQJ0eAEGdmVyaWZ5AAQOY29vcmRpbmF0b3JTdHIJAJ0IAgUEdGhpcwUUa19jb29yZGluYXRvckFkZHJlc3MDCQEJaXNEZWZpbmVkAQUOY29vcmRpbmF0b3JTdHIEBWFkbWluCQCdCAIJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQV2YWx1ZQEFDmNvb3JkaW5hdG9yU3RyBQ9rX2FkbWluX2FkZHJlc3MDCQEJaXNEZWZpbmVkAQUFYWRtaW4JAQt2YWx1ZU9yRWxzZQIJAJsIAgkBEUBleHRyTmF0aXZlKDEwNjIpAQkBBXZhbHVlAQUFYWRtaW4JAKwCAgkArAICCQCsAgICB3N0YXR1c18JAKUIAQUEdGhpcwIBXwkA2AQBCAUCdHgCaWQHCQACAQIudW5hYmxlIHRvIHZlcmlmeTogYWRtaW4gbm90IHNldCBpbiBjb29yZGluYXRvcgkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAgFAnR4D3NlbmRlclB1YmxpY0tlecpxFRg=", "height": 2444617, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 9MixQyr5Dye6NW9tcxNU1nY1vtKnxuy2Hi33F1tCREjQ Next: EkLdrDWgBoRuetmSZjeJb7uPdybZE4eF9vcNspxndVbx Diff:
OldNewDifferences
105105
106106 let k_admin_address = "k_admin_address"
107107
108-let k_admin_public_key = "k_admin_public_key"
109-
110108 let k_quote_asset = "k_quote_asset"
111109
112110 let k_quote_staking = "k_quote_staking"
130128
131129
132130 func adminAddress () = addressFromString(getStringValue(coordinator(), k_admin_address))
133-
134-
135-func adminPublicKey () = fromBase58String(getStringValue(coordinator(), k_admin_public_key))
136131
137132
138133 func quoteAsset () = fromBase58String(getStringValue(coordinator(), k_quote_asset))
194189 func muld (_x,_y) = fraction(_x, _y, DECIMAL_UNIT, HALFEVEN)
195190
196191
197-func sqrtd (_x) = sqrt(_x, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
198-
199-
200-func powd (_x,_y) = pow(_x, DECIMAL_NUMBERS, _y, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
201-
202-
203192 func bdivd (_x,_y) = fraction(_x, toBigInt(DECIMAL_UNIT), _y, HALFEVEN)
204193
205194
206195 func bmuld (_x,_y) = fraction(_x, _y, toBigInt(DECIMAL_UNIT), HALFEVEN)
207-
208-
209-func bsqrtd (_x) = sqrtBigInt(_x, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
210-
211-
212-func bpowd (_x,_y) = pow(_x, DECIMAL_NUMBERS, _y, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
213196
214197
215198 func abs (_x) = if ((_x > 0))
473456 let amountBaseAssetBought = if (_isAdd)
474457 then amountBaseAssetBoughtAbs
475458 else -(amountBaseAssetBoughtAbs)
476- let $t01725917429 = updateReserve(_isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
477- let quoteAssetReserveAfter1 = $t01725917429._1
478- let baseAssetReserveAfter1 = $t01725917429._2
479- let totalPositionSizeAfter1 = $t01725917429._3
459+ let $t01672216892 = updateReserve(_isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
460+ let quoteAssetReserveAfter1 = $t01672216892._1
461+ let baseAssetReserveAfter1 = $t01672216892._2
462+ let totalPositionSizeAfter1 = $t01672216892._3
480463 let priceBefore = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
481464 let marketPrice = divd(_quoteAssetAmount, amountBaseAssetBoughtAbs)
482465 let priceDiff = abs((priceBefore - marketPrice))
504487 else 0
505488 let rolloverFee = calcRolloverFee(_oldPositionMargin, _oldPositionLastUpdatedTimestamp)
506489 let signedMargin = (((_marginDelta - rolloverFee) - fundingPayment) + _oldPositionMargin)
507- let $t01968419811 = if ((0 > signedMargin))
490+ let $t01914719274 = if ((0 > signedMargin))
508491 then $Tuple2(0, abs(signedMargin))
509492 else $Tuple2(abs(signedMargin), 0)
510- let remainMargin = $t01968419811._1
511- let badDebt = $t01968419811._2
493+ let remainMargin = $t01914719274._1
494+ let badDebt = $t01914719274._2
512495 $Tuple4(remainMargin, badDebt, fundingPayment, rolloverFee)
513496 }
514497
526509 let quoteAssetDelta = abs((quoteAssetAfter - _quoteAssetReserve))
527510 let quoteAssetSold = muld(quoteAssetDelta, _quoteAssetWeight)
528511 let maxPriceImpactValue = maxPriceImpact()
529- let $t02107321235 = updateReserve(!(_isAdd), quoteAssetDelta, _baseAssetAmount)
530- let quoteAssetReserveAfter1 = $t02107321235._1
531- let baseAssetReserveAfter1 = $t02107321235._2
532- let totalPositionSizeAfter1 = $t02107321235._3
512+ let $t02053620698 = updateReserve(!(_isAdd), quoteAssetDelta, _baseAssetAmount)
513+ let quoteAssetReserveAfter1 = $t02053620698._1
514+ let baseAssetReserveAfter1 = $t02053620698._2
515+ let totalPositionSizeAfter1 = $t02053620698._3
533516 let marketPrice = divd(quoteAssetSold, _baseAssetAmount)
534517 let priceDiff = abs((priceBefore - marketPrice))
535518 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
664647
665648
666649 func getPositionNotionalAndUnrealizedPnl (_trader,_option) = {
667- let $t02911329241 = getPosition(_trader)
668- let positionSize = $t02911329241._1
669- let positionMargin = $t02911329241._2
670- let positionOpenNotional = $t02911329241._3
671- let positionLstUpdCPF = $t02911329241._4
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
672655 getPositionNotionalAndUnrealizedPnlByValues(positionSize, positionOpenNotional, qtAstR(), qtAstW(), bsAstR(), bsAstW(), _option)
673656 }
674657
677660
678661
679662 func getMarginRatioByOption (_trader,_option) = {
680- let $t02975629897 = getPosition(_trader)
681- let positionSize = $t02975629897._1
682- let positionMargin = $t02975629897._2
683- let pon = $t02975629897._3
684- let positionLastUpdatedCPF = $t02975629897._4
685- let positionTimestamp = $t02975629897._5
686- let $t02990329996 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
687- let positionNotional = $t02990329996._1
688- let unrealizedPnl = $t02990329996._2
689- let $t03000130213 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLastUpdatedCPF, positionTimestamp, unrealizedPnl)
690- let remainMargin = $t03000130213._1
691- let badDebt = $t03000130213._2
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
692675 calcMarginRatio(remainMargin, badDebt, positionNotional)
693676 }
694677
708691 }
709692
710693
711-func internalClosePosition (_trader,_size,_fee,_minQuoteAssetAmount,_addToMargin,_checkMaxPriceImpact) = {
712- let $t03125731413 = getPosition(_trader)
713- let oldPositionSize = $t03125731413._1
714- let oldPositionMargin = $t03125731413._2
715- let oldPositionOpenNotional = $t03125731413._3
716- let oldPositionLstUpdCPF = $t03125731413._4
717- let oldPositionTimestamp = $t03125731413._5
694+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
718701 let isLongPosition = (oldPositionSize > 0)
719702 let absOldPositionSize = abs(oldPositionSize)
720703 if (if ((absOldPositionSize >= _size))
722705 else false)
723706 then {
724707 let isPartialClose = (absOldPositionSize > _size)
725- let $t03170532156 = swapOutput((oldPositionSize > 0), _size, _checkMaxPriceImpact)
726- let exchangedQuoteAssetAmount = $t03170532156._1
727- let quoteAssetReserveAfter = $t03170532156._2
728- let baseAssetReserveAfter = $t03170532156._3
729- let totalPositionSizeAfter = $t03170532156._4
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
730713 let exchangedPositionSize = if ((oldPositionSize > 0))
731714 then -(_size)
732715 else _size
733- let $t03237132578 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
734- let oldPositionNotional = $t03237132578._1
735- let unrealizedPnl = $t03237132578._2
716+ let $t03185732064 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
717+ let oldPositionNotional = $t03185732064._1
718+ let unrealizedPnl = $t03185732064._2
736719 let realizedRatio = divd(abs(exchangedPositionSize), absOldPositionSize)
737720 let realizedPnl = muld(unrealizedPnl, realizedRatio)
738- let $t03291933165 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, unrealizedPnl)
739- let remainMarginBefore = $t03291933165._1
740- let x1 = $t03291933165._2
741- let x2 = $t03291933165._3
742- let rolloverFee = $t03291933165._4
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
743726 let positionBadDebt = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, realizedPnl)._2
744727 let realizedCloseFee = muld(muld(oldPositionNotional, realizedRatio), _fee)
745728 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
747730 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
748731 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
749732 let newPositionSize = (oldPositionSize + exchangedPositionSize)
750- let $t03457134957 = if ((newPositionSize == 0))
733+ let $t03405734443 = if ((newPositionSize == 0))
751734 then $Tuple2(0, 0)
752735 else $Tuple2(abs(remainOpenNotional), latestCumulativePremiumFraction(newPositionSize))
753- let newPositionOpenNotional = $t03457134957._1
754- let newPositionLstUpdCPF = $t03457134957._2
736+ let newPositionOpenNotional = $t03405734443._1
737+ let newPositionLstUpdCPF = $t03405734443._2
755738 let openNotionalDelta = (oldPositionOpenNotional - newPositionOpenNotional)
756739 let marginRatio = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
757740 let newPositionMarginWithSameRatio = if ((oldPositionSize > 0))
759742 else (muld((newPositionOpenNotional - unrealizedPnlAfter), marginRatio) - unrealizedPnlAfter)
760743 let marginToTraderRaw = ((remainMarginBefore - (newPositionMarginWithSameRatio + unrealizedPnlAfter)) - realizedCloseFee)
761744 let marginToTrader = if ((0 > marginToTraderRaw))
762- then throw("Invalid internalClosePosition params: unable to pay fee")
745+ then if (_liquidate)
746+ then 0
747+ else throw("Invalid internalClosePosition params: unable to pay fee")
763748 else marginToTraderRaw
764749 let newPositionMargin = if (_addToMargin)
765750 then (newPositionMarginWithSameRatio + marginToTrader)
782767 then openNotionalDelta
783768 else 0)), (realizedCloseFee + rolloverFee), exchangedQuoteAssetAmount)
784769 }
785- else throw("Invalid internalClosePosition params: invalid position size")
770+ else throw(((("Invalid internalClosePosition params: invalid position size: " + toString(_size)) + " max: ") + toString(absOldPositionSize)))
786771 }
787772
788773
829814 then $Tuple2(qtAstR(), bsAstR())
830815 else {
831816 let direction = (_positionSize > 0)
832- let $t03956039739 = swapOutput(direction, abs(_positionSize), false)
833- let currentNetMarketValue = $t03956039739._1
834- let terminalQuoteAssetReserve = $t03956039739._2
835- let terminalBaseAssetReserve = $t03956039739._3
817+ let $t03918039359 = swapOutput(direction, abs(_positionSize), false)
818+ let currentNetMarketValue = $t03918039359._1
819+ let terminalQuoteAssetReserve = $t03918039359._2
820+ let terminalBaseAssetReserve = $t03918039359._3
836821 $Tuple2(terminalQuoteAssetReserve, terminalBaseAssetReserve)
837822 }
838823 }
897882 func getAdjustedFee (_artifactId,_baseFeeDiscount) = {
898883 let baseFeeRaw = fee()
899884 let baseFee = muld(baseFeeRaw, _baseFeeDiscount)
900- let $t04260043095 = if ((_artifactId != ""))
885+ let $t04222042715 = if ((_artifactId != ""))
901886 then {
902887 let artifactKind = strA(nftManagerAddress(), toCompositeKey(k_token_type, _artifactId))
903888 if ((artifactKind == FEE_REDUCTION_TOKEN_TYPE))
909894 else throw("Invalid attached artifact")
910895 }
911896 else $Tuple2(baseFee, false)
912- let adjustedFee = $t04260043095._1
913- let burnArtifact = $t04260043095._2
897+ let adjustedFee = $t04222042715._1
898+ let burnArtifact = $t04222042715._2
914899 $Tuple2(adjustedFee, burnArtifact)
915900 }
916901
936921 case _ =>
937922 throw("Invalid computeFeeDiscount result")
938923 }
939- let $t04377543849 = getAdjustedFee(_artifactId, feeDiscount)
940- let adjustedFee = $t04377543849._1
941- let burnArtifact = $t04377543849._2
924+ let $t04339543469 = getAdjustedFee(_artifactId, feeDiscount)
925+ let adjustedFee = $t04339543469._1
926+ let burnArtifact = $t04339543469._2
942927 $Tuple2(adjustedFee, burnArtifact)
943928 }
944929 else throw("Strict value is not equal to itself.")
10911076 let qtAstRAfter = (_qtAstR + _quoteAssetAmount)
10921077 let baseAssetAmountToAdd = (divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR)
10931078 let bsAstRAfter = (_bsAstR + baseAssetAmountToAdd)
1094- let $t05325653407 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1095- let newQuoteAssetWeight = $t05325653407._1
1096- let newBaseAssetWeight = $t05325653407._2
1097- let marginToVault = $t05325653407._3
1079+ let $t05287653027 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1080+ let newQuoteAssetWeight = $t05287653027._1
1081+ let newBaseAssetWeight = $t05287653027._2
1082+ let marginToVault = $t05287653027._3
10981083 let doExchangePnL = if ((marginToVault != 0))
10991084 then {
11001085 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
11241109 let qtAstRAfter = (_qtAstR - _quoteAssetAmount)
11251110 let baseAssetAmountToRemove = abs((divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR))
11261111 let bsAstRAfter = (_bsAstR - baseAssetAmountToRemove)
1127- let $t05433954490 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1128- let newQuoteAssetWeight = $t05433954490._1
1129- let newBaseAssetWeight = $t05433954490._2
1130- let marginToVault = $t05433954490._3
1112+ let $t05395954110 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1113+ let newQuoteAssetWeight = $t05395954110._1
1114+ let newBaseAssetWeight = $t05395954110._2
1115+ let marginToVault = $t05395954110._3
11311116 let doExchangePnL = if ((marginToVault != 0))
11321117 then {
11331118 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
11511136
11521137
11531138 @Callable(i)
1154-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 ((0 >= _qtAstR))
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))
11551140 then true
11561141 else (0 >= _bsAstR))
11571142 then true
11841169 else (0 >= _rolloverFee))
11851170 then true
11861171 else initialized())
1172+ then true
1173+ else (i.caller != this))
11871174 then throw("Invalid initialize parameters")
1188- 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, _coordinator)])
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)))])
11891176
11901177
11911178
12231210 else isMarketClosed())
12241211 then throw("Invalid increasePosition parameters")
12251212 else {
1226- let $t05820958358 = getForTraderWithArtifact(_trader, getArtifactId(i))
1227- let adjustedFee = $t05820958358._1
1228- let burnArtifact = $t05820958358._2
1213+ let $t05788858037 = getForTraderWithArtifact(_trader, getArtifactId(i))
1214+ let adjustedFee = $t05788858037._1
1215+ let burnArtifact = $t05788858037._2
12291216 let _amount = divd(_rawAmount, (muld(adjustedFee, _leverage) + DECIMAL_UNIT))
12301217 let distributeFeeAmount = (_rawAmount - _amount)
12311218 let referrerFeeAny = invoke(referralAddress(), "acceptPaymentWithLink", [_trader, _refLink], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
12381225 throw("Invalid referrerFee")
12391226 }
12401227 let feeAmount = (distributeFeeAmount - referrerFee)
1241- let $t05885459022 = getPosition(_trader)
1242- let oldPositionSize = $t05885459022._1
1243- let oldPositionMargin = $t05885459022._2
1244- let oldPositionOpenNotional = $t05885459022._3
1245- let oldPositionLstUpdCPF = $t05885459022._4
1246- let oldPositionTimestamp = $t05885459022._5
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
12471234 let isNewPosition = (oldPositionSize == 0)
12481235 let isSameDirection = if ((oldPositionSize > 0))
12491236 then (_direction == DIR_LONG)
12521239 then isSameDirection
12531240 else false
12541241 let isAdd = (_direction == DIR_LONG)
1255- let $t05931162432 = if (if (isNewPosition)
1242+ let $t05899062111 = if (if (isNewPosition)
12561243 then true
12571244 else expandExisting)
12581245 then {
12591246 let openNotional = muld(_amount, _leverage)
1260- let $t05982059993 = swapInput(isAdd, openNotional)
1261- let amountBaseAssetBought = $t05982059993._1
1262- let quoteAssetReserveAfter = $t05982059993._2
1263- let baseAssetReserveAfter = $t05982059993._3
1264- let totalPositionSizeAfter = $t05982059993._4
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
12651252 if (if ((_minBaseAssetAmount != 0))
12661253 then (_minBaseAssetAmount > abs(amountBaseAssetBought))
12671254 else false)
12741261 let totalShortOpenInterestAfter = (openInterestShort() + (if ((0 > newPositionSize))
12751262 then openNotional
12761263 else 0))
1277- let $t06053960814 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, _amount)
1278- let remainMargin = $t06053960814._1
1279- let x1 = $t06053960814._2
1280- let x2 = $t06053960814._3
1281- let rolloverFee = $t06053960814._4
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
12821269 if (!(requireNotOverSpreadLimit(quoteAssetReserveAfter, baseAssetReserveAfter)))
12831270 then throw("Over max spread limit")
12841271 else if (!(requireNotOverMaxOpenNotional(totalLongOpenInterestAfter, totalShortOpenInterestAfter)))
12921279 }
12931280 else {
12941281 let openNotional = muld(_amount, _leverage)
1295- let $t06213262248 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1296- let oldPositionNotional = $t06213262248._1
1297- let unrealizedPnl = $t06213262248._2
1282+ let $t06181161927 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1283+ let oldPositionNotional = $t06181161927._1
1284+ let unrealizedPnl = $t06181161927._2
12981285 if ((oldPositionNotional > openNotional))
12991286 then throw("Use decreasePosition to decrease position size")
13001287 else throw("Close position first")
13011288 }
1302- let newPositionSize = $t05931162432._1
1303- let newPositionRemainMargin = $t05931162432._2
1304- let newPositionOpenNotional = $t05931162432._3
1305- let newPositionLatestCPF = $t05931162432._4
1306- let newPositionTimestamp = $t05931162432._5
1307- let baseAssetReserveAfter = $t05931162432._6
1308- let quoteAssetReserveAfter = $t05931162432._7
1309- let totalPositionSizeAfter = $t05931162432._8
1310- let openInterestNotionalAfter = $t05931162432._9
1311- let totalLongAfter = $t05931162432._10
1312- let totalShortAfter = $t05931162432._11
1313- let totalLongOpenInterestAfter = $t05931162432._12
1314- let totalShortOpenInterestAfter = $t05931162432._13
1315- let rolloverFee = $t05931162432._14
1316- let $t06243862509 = distributeFee((feeAmount + rolloverFee))
1317- let feeToStakers = $t06243862509._1
1318- let feeToVault = $t06243862509._2
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
13191306 let stake = if ((_amount >= rolloverFee))
13201307 then invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), (_amount - rolloverFee))])
13211308 else invoke(vaultAddress(), "withdrawLocked", [(rolloverFee - _amount)], nil)
13761363 else isMarketClosed())
13771364 then throw("Invalid addMargin parameters")
13781365 else {
1379- let $t06462064788 = getPosition(_trader)
1380- let oldPositionSize = $t06462064788._1
1381- let oldPositionMargin = $t06462064788._2
1382- let oldPositionOpenNotional = $t06462064788._3
1383- let oldPositionLstUpdCPF = $t06462064788._4
1384- let oldPositionTimestamp = $t06462064788._5
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
13851372 let stake = invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), _amount)])
13861373 if ((stake == stake))
13871374 then {
13881375 let rolloverFee = calcRolloverFee(oldPositionMargin, oldPositionTimestamp)
13891376 let doTransferFeeToStakers = if ((rolloverFee > 0))
13901377 then {
1391- let $t06507365132 = distributeFee(rolloverFee)
1392- let feeToStakers = $t06507365132._1
1393- let feeToVault = $t06507365132._2
1378+ let $t06475264811 = distributeFee(rolloverFee)
1379+ let feeToStakers = $t06475264811._1
1380+ let feeToVault = $t06475264811._2
13941381 let unstake = invoke(vaultAddress(), "withdrawLocked", [feeToStakers], nil)
13951382 if ((unstake == unstake))
13961383 then {
14361423 else isMarketClosed())
14371424 then throw("Invalid removeMargin parameters")
14381425 else {
1439- let $t06624466412 = getPosition(_trader)
1440- let oldPositionSize = $t06624466412._1
1441- let oldPositionMargin = $t06624466412._2
1442- let oldPositionOpenNotional = $t06624466412._3
1443- let oldPositionLstUpdCPF = $t06624466412._4
1444- let oldPositionTimestamp = $t06624466412._5
1445- let $t06641866667 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, -(_amount))
1446- let remainMargin = $t06641866667._1
1447- let badDebt = $t06641866667._2
1448- let fundingPayment = $t06641866667._3
1449- let rolloverFee = $t06641866667._4
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
14501437 if ((badDebt != 0))
14511438 then throw("Invalid removed margin amount")
14521439 else {
14541441 if (!(requireMoreMarginRatio(marginRatio, initMarginRatio(), true)))
14551442 then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
14561443 else {
1457- let $t06705367112 = distributeFee(rolloverFee)
1458- let feeToStakers = $t06705367112._1
1459- let feeToVault = $t06705367112._2
1444+ let $t06673266791 = distributeFee(rolloverFee)
1445+ let feeToStakers = $t06673266791._1
1446+ let feeToVault = $t06673266791._2
14601447 let doTransferFeeToStakers = if ((rolloverFee > 0))
14611448 then {
14621449 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(feeToVault)], nil)
15091496 then throw("Invalid closePosition parameters")
15101497 else {
15111498 let oldPositionTimestamp = getPosition(_trader)._5
1512- let $t06876969342 = internalClosePosition(_trader, _size, positionFee, _minQuoteAssetAmount, _addToMargin, true)
1513- let newPositionSize = $t06876969342._1
1514- let newPositionMargin = $t06876969342._2
1515- let newPositionOpenNotional = $t06876969342._3
1516- let newPositionLstUpdCPF = $t06876969342._4
1517- let positionBadDebt = $t06876969342._5
1518- let realizedPnl = $t06876969342._6
1519- let marginToTrader = $t06876969342._7
1520- let quoteAssetReserveAfter = $t06876969342._8
1521- let baseAssetReserveAfter = $t06876969342._9
1522- let totalPositionSizeAfter = $t06876969342._10
1523- let openInterestNotionalAfter = $t06876969342._11
1524- let totalLongAfter = $t06876969342._12
1525- let totalShortAfter = $t06876969342._13
1526- let totalLongOpenInterestAfter = $t06876969342._14
1527- let totalShortOpenInterestAfter = $t06876969342._15
1528- let realizedFee = $t06876969342._16
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
15291516 if ((positionBadDebt > 0))
15301517 then throw("Invalid closePosition parameters: bad debt")
15311518 else if ((oldPositionTimestamp >= lastTimestamp()))
15401527 let unstake = invoke(vaultAddress(), "withdrawLocked", [withdrawAmount], nil)
15411528 if ((unstake == unstake))
15421529 then {
1543- let $t07001470073 = distributeFee(realizedFee)
1544- let feeToStakers = $t07001470073._1
1545- let feeToVault = $t07001470073._2
1530+ let $t06970569764 = distributeFee(realizedFee)
1531+ let feeToStakers = $t06970569764._1
1532+ let feeToVault = $t06970569764._2
15461533 let depositVault = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
15471534 if ((depositVault == depositVault))
15481535 then {
15971584 then throw("Unable to liquidate")
15981585 else {
15991586 let isPartialLiquidation = if (if ((spotMarginRatio > liquidationFeeRatio()))
1600- then true
1601- else (partialLiquidationRatio() > 0))
1602- then true
1603- else (DECIMAL_UNIT > partialLiquidationRatio())
1587+ then (partialLiquidationRatio() > 0)
1588+ else false)
1589+ then (DECIMAL_UNIT > partialLiquidationRatio())
1590+ else false
16041591 let oldPositionSize = getPosition(_trader)._1
16051592 let positionSizeAbs = abs(oldPositionSize)
1606- let $t07238672709 = if (isPartialLiquidation)
1593+ let $t07207772400 = if (isPartialLiquidation)
16071594 then {
16081595 let liquidationSize = getPartialLiquidationAmount(_trader, oldPositionSize)
16091596 let liquidationRatio = divd(abs(liquidationSize), positionSizeAbs)
16101597 $Tuple2(liquidationRatio, abs(liquidationSize))
16111598 }
16121599 else $Tuple2(0, positionSizeAbs)
1613- let liquidationRatio = $t07238672709._1
1614- let liquidationSize = $t07238672709._2
1615- let $t07271573341 = internalClosePosition(_trader, if (isPartialLiquidation)
1600+ let liquidationRatio = $t07207772400._1
1601+ let liquidationSize = $t07207772400._2
1602+ let $t07240673044 = internalClosePosition(_trader, if (isPartialLiquidation)
16161603 then liquidationSize
1617- else positionSizeAbs, liquidationFeeRatio(), 0, true, false)
1618- let newPositionSize = $t07271573341._1
1619- let newPositionMargin = $t07271573341._2
1620- let newPositionOpenNotional = $t07271573341._3
1621- let newPositionLstUpdCPF = $t07271573341._4
1622- let positionBadDebt = $t07271573341._5
1623- let realizedPnl = $t07271573341._6
1624- let marginToTrader = $t07271573341._7
1625- let quoteAssetReserveAfter = $t07271573341._8
1626- let baseAssetReserveAfter = $t07271573341._9
1627- let totalPositionSizeAfter = $t07271573341._10
1628- let openInterestNotionalAfter = $t07271573341._11
1629- let totalLongAfter = $t07271573341._12
1630- let totalShortAfter = $t07271573341._13
1631- let totalLongOpenInterestAfter = $t07271573341._14
1632- let totalShortOpenInterestAfter = $t07271573341._15
1633- let liquidationPenalty = $t07271573341._16
1604+ 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
16341621 let feeToLiquidator = (liquidationPenalty / 2)
16351622 let feeToVault = (liquidationPenalty - feeToLiquidator)
16361623 let ammBalance = (cbalance() - liquidationPenalty)
16391626 else ammBalance
16401627 let lockBadDebt = if ((positionBadDebt > 0))
16411628 then {
1642- let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [positionBadDebt], nil)
1629+ let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [(positionBadDebt + liquidationPenalty)], nil)
16431630 if ((lockBadDebt == lockBadDebt))
16441631 then nil
16451632 else throw("Strict value is not equal to itself.")
16861673 then throw(((("Invalid funding block timestamp: " + toString(lastTimestamp())) + " < ") + toString(fundingBlockTimestamp)))
16871674 else {
16881675 let underlyingPrice = getOraclePrice()
1689- let $t07530775369 = getFunding()
1690- let shortPremiumFraction = $t07530775369._1
1691- let longPremiumFraction = $t07530775369._2
1676+ let $t07503175093 = getFunding()
1677+ let shortPremiumFraction = $t07503175093._1
1678+ let longPremiumFraction = $t07503175093._2
16921679 updateFunding((fundingBlockTimestamp + fundingPeriodSeconds()), (latestLongCumulativePremiumFraction() + longPremiumFraction), (latestShortCumulativePremiumFraction() + shortPremiumFraction), divd(longPremiumFraction, underlyingPrice), divd(shortPremiumFraction, underlyingPrice))
16931680 }
16941681 }
17011688 func syncTerminalPriceToOracle () = {
17021689 let _qtAstR = qtAstR()
17031690 let _bsAstR = bsAstR()
1704- let $t07580175936 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1705- let newQuoteAssetWeight = $t07580175936._1
1706- let newBaseAssetWeight = $t07580175936._2
1707- let marginToVault = $t07580175936._3
1708- let doExchangePnL = if ((marginToVault != 0))
1691+ let $t07552575891 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1692+ let newQuoteAssetWeight = $t07552575891._1
1693+ let newBaseAssetWeight = $t07552575891._2
1694+ let marginToVault = $t07552575891._3
1695+ let marginToVaultAdj = if (if ((0 > marginToVault))
1696+ then (abs(marginToVault) > cbalance())
1697+ else false)
1698+ then -(cbalance())
1699+ else marginToVault
1700+ let doExchangePnL = if ((marginToVaultAdj != 0))
17091701 then {
1710- let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
1702+ let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVaultAdj], nil)
17111703 if ((doExchangePnL == doExchangePnL))
17121704 then nil
17131705 else throw("Strict value is not equal to itself.")
17141706 }
17151707 else nil
17161708 if ((doExchangePnL == doExchangePnL))
1717- then ((updateBalance((cbalance() + marginToVault)) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight)) ++ appendTwap(divd(muld(_qtAstR, newQuoteAssetWeight), muld(_bsAstR, newBaseAssetWeight))))
1709+ then ((updateBalance((cbalance() + marginToVaultAdj)) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight)) ++ appendTwap(divd(muld(_qtAstR, newQuoteAssetWeight), muld(_bsAstR, newBaseAssetWeight))))
17181710 else throw("Strict value is not equal to itself.")
17191711 }
17201712
17371729 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
17381730 if ((sync == sync))
17391731 then {
1740- let $t07694177065 = getPosition(_trader)
1741- let positionSize = $t07694177065._1
1742- let positionMargin = $t07694177065._2
1743- let pon = $t07694177065._3
1744- let positionLstUpdCPF = $t07694177065._4
1745- let positionTimestamp = $t07694177065._5
1746- let $t07706877169 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1747- let positionNotional = $t07706877169._1
1748- let unrealizedPnl = $t07706877169._2
1749- let $t07717277396 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLstUpdCPF, positionTimestamp, unrealizedPnl)
1750- let remainMargin = $t07717277396._1
1751- let badDebt = $t07717277396._2
1752- let fundingPayment = $t07717277396._3
1753- let rolloverFee = $t07717277396._4
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
17541746 throw(((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)) + s(rolloverFee)))
17551747 }
17561748 else throw("Strict value is not equal to itself.")
17701762
17711763 @Callable(i)
17721764 func view_getTerminalAmmPrice () = {
1773- let $t07783277913 = getTerminalAmmState()
1774- let terminalQuoteAssetReserve = $t07783277913._1
1775- let terminalBaseAssetReserve = $t07783277913._2
1765+ let $t07794178022 = getTerminalAmmState()
1766+ let terminalQuoteAssetReserve = $t07794178022._1
1767+ let terminalBaseAssetReserve = $t07794178022._2
17761768 let price = divd(muld(terminalQuoteAssetReserve, qtAstW()), muld(terminalBaseAssetReserve, bsAstW()))
17771769 throw(toString(price))
17781770 }
17821774 @Callable(i)
17831775 func view_getFunding () = {
17841776 let underlyingPrice = getOraclePrice()
1785- let $t07812878190 = getFunding()
1786- let shortPremiumFraction = $t07812878190._1
1787- let longPremiumFraction = $t07812878190._2
1777+ let $t07823778299 = getFunding()
1778+ let shortPremiumFraction = $t07823778299._1
1779+ let longPremiumFraction = $t07823778299._2
17881780 let longFunding = divd(longPremiumFraction, underlyingPrice)
17891781 let shortFunding = divd(shortPremiumFraction, underlyingPrice)
17901782 throw((((s(longFunding) + s(shortFunding)) + s(getTwapSpotPrice())) + s(getOraclePrice())))
18131805
18141806
18151807 @Verifier(tx)
1816-func verify () = sigVerify(tx.bodyBytes, tx.proofs[0], adminPublicKey())
1808+func verify () = {
1809+ let coordinatorStr = getString(this, k_coordinatorAddress)
1810+ if (isDefined(coordinatorStr))
1811+ then {
1812+ let admin = getString(addressFromStringValue(value(coordinatorStr)), k_admin_address)
1813+ if (isDefined(admin))
1814+ then valueOrElse(getBoolean(addressFromStringValue(value(admin)), ((("status_" + toString(this)) + "_") + toBase58String(tx.id))), false)
1815+ else throw("unable to verify: admin not set in coordinator")
1816+ }
1817+ else sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
1818+ }
18171819
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let k_baseOracle = "k_baseOracle"
55
66 let k_quoteOracle = "k_quoteOracle"
77
88 let k_balance = "k_balance"
99
1010 let k_sequence = "k_sequence"
1111
1212 let k_positionSize = "k_positionSize"
1313
1414 let k_positionMargin = "k_positionMargin"
1515
1616 let k_positionOpenNotional = "k_positionOpenNotional"
1717
1818 let k_positionLastUpdatedCumulativePremiumFraction = "k_positionFraction"
1919
2020 let k_positionSequence = "k_positionSequence"
2121
2222 let k_positionAsset = "k_positionAsset"
2323
2424 let k_positionFee = "k_positionFee"
2525
2626 let k_positionLastUpdatedTimestamp = "k_positionTimestamp"
2727
2828 let k_initialized = "k_initialized"
2929
3030 let k_paused = "k_paused"
3131
3232 let k_closeOnly = "k_closeOnly"
3333
3434 let k_fee = "k_fee"
3535
3636 let k_rolloverFee = "k_rollover_fee"
3737
3838 let k_fundingPeriod = "k_fundingPeriod"
3939
4040 let k_initMarginRatio = "k_initMarginRatio"
4141
4242 let k_maintenanceMarginRatio = "k_mmr"
4343
4444 let k_liquidationFeeRatio = "k_liquidationFeeRatio"
4545
4646 let k_partialLiquidationRatio = "k_partLiquidationRatio"
4747
4848 let k_spreadLimit = "k_spreadLimit"
4949
5050 let k_maxPriceImpact = "k_maxPriceImpact"
5151
5252 let k_maxPriceSpread = "k_maxPriceSpread"
5353
5454 let k_maxOpenNotional = "k_maxOpenNotional"
5555
5656 let k_feeToStakersPercent = "k_feeToStakersPercent"
5757
5858 let k_maxOracleDelay = "k_maxOracleDelay"
5959
6060 let k_lastDataStr = "k_lastDataStr"
6161
6262 let k_lastMinuteId = "k_lastMinuteId"
6363
6464 let k_twapDataLastCumulativePrice = "k_twapDataLastCumulativePrice"
6565
6666 let k_twapDataLastPrice = "k_twapDataLastPrice"
6767
6868 let k_twapDataPreviousMinuteId = "k_twapDataPreviousMinuteId"
6969
7070 let k_latestLongCumulativePremiumFraction = "k_latestLongPremiumFraction"
7171
7272 let k_latestShortCumulativePremiumFraction = "k_latestShortPremiumFraction"
7373
7474 let k_nextFundingBlock = "k_nextFundingBlockMinTimestamp"
7575
7676 let k_longFundingRate = "k_longFundingRate"
7777
7878 let k_shortFundingRate = "k_shortFundingRate"
7979
8080 let k_quoteAssetReserve = "k_qtAstR"
8181
8282 let k_baseAssetReserve = "k_bsAstR"
8383
8484 let k_quoteAssetWeight = "k_qtAstW"
8585
8686 let k_baseAssetWeight = "k_bsAstW"
8787
8888 let k_totalPositionSize = "k_totalPositionSize"
8989
9090 let k_totalLongPositionSize = "k_totalLongPositionSize"
9191
9292 let k_totalShortPositionSize = "k_totalShortPositionSize"
9393
9494 let k_openInterestNotional = "k_openInterestNotional"
9595
9696 let k_openInterestShort = "k_openInterestShort"
9797
9898 let k_openInterestLong = "k_openInterestLong"
9999
100100 let k_lastTx = "k_lastTx"
101101
102102 let k_coordinatorAddress = "k_coordinatorAddress"
103103
104104 let k_vault_address = "k_vault_address"
105105
106106 let k_admin_address = "k_admin_address"
107107
108-let k_admin_public_key = "k_admin_public_key"
109-
110108 let k_quote_asset = "k_quote_asset"
111109
112110 let k_quote_staking = "k_quote_staking"
113111
114112 let k_staking_address = "k_staking_address"
115113
116114 let k_miner_address = "k_miner_address"
117115
118116 let k_orders_address = "k_orders_address"
119117
120118 let k_referral_address = "k_referral_address"
121119
122120 let k_exchange_address = "k_exchange_address"
123121
124122 let k_nft_manager_address = "k_nft_manager_address"
125123
126124 func toCompositeKey (_key,_address) = ((_key + "_") + _address)
127125
128126
129127 func coordinator () = valueOrErrorMessage(addressFromString(getStringValue(this, k_coordinatorAddress)), "Coordinator not set")
130128
131129
132130 func adminAddress () = addressFromString(getStringValue(coordinator(), k_admin_address))
133-
134-
135-func adminPublicKey () = fromBase58String(getStringValue(coordinator(), k_admin_public_key))
136131
137132
138133 func quoteAsset () = fromBase58String(getStringValue(coordinator(), k_quote_asset))
139134
140135
141136 func quoteAssetStaking () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_quote_staking)), "Quote asset staking not set")
142137
143138
144139 func stakingAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_staking_address)), "Staking not set")
145140
146141
147142 func vaultAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_vault_address)), "Vault not set")
148143
149144
150145 func minerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_miner_address)), "Miner not set")
151146
152147
153148 func ordersAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_orders_address)), "Orders not set")
154149
155150
156151 func referralAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_referral_address)), "Referral not set")
157152
158153
159154 func nftManagerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_nft_manager_address)), "NFT Manager not set")
160155
161156
162157 let k_token_param = "k_token_param"
163158
164159 let k_token_type = "k_token_type"
165160
166161 let FEE_REDUCTION_TOKEN_TYPE = "fee_reduction"
167162
168163 let DIR_LONG = 1
169164
170165 let DIR_SHORT = 2
171166
172167 let TWAP_INTERVAL = 15
173168
174169 let SECONDS = 1000
175170
176171 let DECIMAL_NUMBERS = 6
177172
178173 let DECIMAL_UNIT = (1 * (((((10 * 10) * 10) * 10) * 10) * 10))
179174
180175 let MINUTES_IN_YEAR = (525600 * DECIMAL_UNIT)
181176
182177 let ONE_DAY = (86400 * DECIMAL_UNIT)
183178
184179 let PNL_OPTION_SPOT = 1
185180
186181 let PNL_OPTION_ORACLE = 2
187182
188183 func s (_x) = (toString(_x) + ",")
189184
190185
191186 func divd (_x,_y) = fraction(_x, DECIMAL_UNIT, _y, HALFEVEN)
192187
193188
194189 func muld (_x,_y) = fraction(_x, _y, DECIMAL_UNIT, HALFEVEN)
195190
196191
197-func sqrtd (_x) = sqrt(_x, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
198-
199-
200-func powd (_x,_y) = pow(_x, DECIMAL_NUMBERS, _y, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
201-
202-
203192 func bdivd (_x,_y) = fraction(_x, toBigInt(DECIMAL_UNIT), _y, HALFEVEN)
204193
205194
206195 func bmuld (_x,_y) = fraction(_x, _y, toBigInt(DECIMAL_UNIT), HALFEVEN)
207-
208-
209-func bsqrtd (_x) = sqrtBigInt(_x, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
210-
211-
212-func bpowd (_x,_y) = pow(_x, DECIMAL_NUMBERS, _y, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
213196
214197
215198 func abs (_x) = if ((_x > 0))
216199 then _x
217200 else -(_x)
218201
219202
220203 func vmax (_x,_y) = if ((_x >= _y))
221204 then _x
222205 else _y
223206
224207
225208 func listToStr (_list) = if ((size(_list) == 0))
226209 then ""
227210 else makeString(_list, ",")
228211
229212
230213 func strToList (_str) = if ((_str == ""))
231214 then nil
232215 else split(_str, ",")
233216
234217
235218 func pushToQueue (_list,_maxSize,_value) = if ((size(_list) > _maxSize))
236219 then (removeByIndex(_list, 0) :+ _value)
237220 else (_list :+ _value)
238221
239222
240223 func int (k) = valueOrErrorMessage(getInteger(this, k), ("no value for " + k))
241224
242225
243226 func intOr (k,def) = valueOrElse(getInteger(this, k), def)
244227
245228
246229 func strA (_address,_key) = {
247230 let val = valueOrErrorMessage(getString(_address, _key), ("No value for key " + _key))
248231 val
249232 }
250233
251234
252235 func intA (_address,_key) = {
253236 let val = valueOrErrorMessage(getInteger(_address, _key), ("No value for key " + _key))
254237 val
255238 }
256239
257240
258241 func cbalance () = int(k_balance)
259242
260243
261244 func fee () = int(k_fee)
262245
263246
264247 func rolloverFeeRate () = int(k_rolloverFee)
265248
266249
267250 func initMarginRatio () = int(k_initMarginRatio)
268251
269252
270253 func qtAstR () = int(k_quoteAssetReserve)
271254
272255
273256 func bsAstR () = int(k_baseAssetReserve)
274257
275258
276259 func qtAstW () = intOr(k_quoteAssetWeight, DECIMAL_UNIT)
277260
278261
279262 func bsAstW () = intOr(k_baseAssetWeight, DECIMAL_UNIT)
280263
281264
282265 func totalPositionSize () = int(k_totalPositionSize)
283266
284267
285268 func openInterestNotional () = int(k_openInterestNotional)
286269
287270
288271 func openInterestShort () = int(k_openInterestShort)
289272
290273
291274 func openInterestLong () = int(k_openInterestLong)
292275
293276
294277 func nextFundingBlockTimestamp () = int(k_nextFundingBlock)
295278
296279
297280 func fundingPeriodRaw () = int(k_fundingPeriod)
298281
299282
300283 func fundingPeriodDecimal () = (fundingPeriodRaw() * DECIMAL_UNIT)
301284
302285
303286 func fundingPeriodSeconds () = (fundingPeriodRaw() * SECONDS)
304287
305288
306289 func maintenanceMarginRatio () = int(k_maintenanceMarginRatio)
307290
308291
309292 func liquidationFeeRatio () = int(k_liquidationFeeRatio)
310293
311294
312295 func partialLiquidationRatio () = int(k_partialLiquidationRatio)
313296
314297
315298 func spreadLimit () = int(k_spreadLimit)
316299
317300
318301 func maxPriceImpact () = int(k_maxPriceImpact)
319302
320303
321304 func maxPriceSpread () = int(k_maxPriceSpread)
322305
323306
324307 func maxOpenNotional () = int(k_maxOpenNotional)
325308
326309
327310 func latestLongCumulativePremiumFraction () = int(k_latestLongCumulativePremiumFraction)
328311
329312
330313 func latestShortCumulativePremiumFraction () = int(k_latestShortCumulativePremiumFraction)
331314
332315
333316 func totalShortPositionSize () = int(k_totalShortPositionSize)
334317
335318
336319 func totalLongPositionSize () = int(k_totalLongPositionSize)
337320
338321
339322 func lastSequence () = intOr(k_sequence, 0)
340323
341324
342325 func feeToStakersPercent () = int(k_feeToStakersPercent)
343326
344327
345328 func maxOracleDelay () = int(k_maxOracleDelay)
346329
347330
348331 func lastTimestamp () = lastBlock.timestamp
349332
350333
351334 func getActualCaller (i) = valueOrElse(getString(ordersAddress(), "k_sender"), toString(i.caller))
352335
353336
354337 func requireMoreMarginRatio (_marginRatio,_baseMarginRatio,_largerThanOrEqualTo) = {
355338 let remainingMarginRatio = (_marginRatio - _baseMarginRatio)
356339 if (if (_largerThanOrEqualTo)
357340 then (0 > remainingMarginRatio)
358341 else false)
359342 then throw(((("Invalid margin: " + toString(_marginRatio)) + " < ") + toString(_baseMarginRatio)))
360343 else if (if (!(_largerThanOrEqualTo))
361344 then (remainingMarginRatio >= 0)
362345 else false)
363346 then throw(((("Invalid margin: " + toString(_marginRatio)) + " > ") + toString(_baseMarginRatio)))
364347 else true
365348 }
366349
367350
368351 func latestCumulativePremiumFraction (_positionSize) = if ((_positionSize == 0))
369352 then throw("Should not be called with _positionSize == 0")
370353 else if ((_positionSize > 0))
371354 then latestLongCumulativePremiumFraction()
372355 else latestShortCumulativePremiumFraction()
373356
374357
375358 func getPosition (_trader) = {
376359 let positionSizeOpt = getInteger(this, toCompositeKey(k_positionSize, _trader))
377360 match positionSizeOpt {
378361 case positionSize: Int =>
379362 $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)))
380363 case _ =>
381364 $Tuple5(0, 0, 0, 0, 0)
382365 }
383366 }
384367
385368
386369 func getPositionAsset (_trader) = {
387370 let positionAssetOpt = getString(this, toCompositeKey(k_positionAsset, _trader))
388371 match positionAssetOpt {
389372 case positionAsset: String =>
390373 positionAsset
391374 case _ =>
392375 toBase58String(quoteAsset())
393376 }
394377 }
395378
396379
397380 func getPositionFee (_trader) = {
398381 let positionFeeOpt = getInteger(this, toCompositeKey(k_positionFee, _trader))
399382 match positionFeeOpt {
400383 case positionFee: Int =>
401384 positionFee
402385 case _ =>
403386 fee()
404387 }
405388 }
406389
407390
408391 func requireOpenPosition (_trader) = if ((getPosition(_trader)._1 == 0))
409392 then throw("No open position")
410393 else true
411394
412395
413396 func getOracleData (key) = {
414397 let oracleDataStr = getString(this, key)
415398 if (if (isDefined(oracleDataStr))
416399 then (value(oracleDataStr) != "")
417400 else false)
418401 then {
419402 let oracleData = split(value(oracleDataStr), ",")
420403 let oracleAddress = valueOrErrorMessage(addressFromString(oracleData[0]), ("Invalid oracle address in: " + value(oracleDataStr)))
421404 let priceKey = oracleData[1]
422405 let blockKey = oracleData[2]
423406 let openKey = oracleData[3]
424407 $Tuple4(oracleAddress, priceKey, blockKey, openKey)
425408 }
426409 else unit
427410 }
428411
429412
430413 func initialized () = valueOrElse(getBoolean(this, k_initialized), false)
431414
432415
433416 func paused () = valueOrElse(getBoolean(this, k_paused), false)
434417
435418
436419 func closeOnly () = valueOrElse(getBoolean(this, k_closeOnly), false)
437420
438421
439422 func updateReserve (_isAdd,_quoteAssetAmount,_baseAssetAmount) = if (_isAdd)
440423 then {
441424 let newBase = (bsAstR() - _baseAssetAmount)
442425 if ((0 >= newBase))
443426 then throw("Tx lead to base asset reserve <= 0, revert")
444427 else $Tuple3((qtAstR() + _quoteAssetAmount), newBase, (totalPositionSize() + _baseAssetAmount))
445428 }
446429 else {
447430 let newQuote = (qtAstR() - _quoteAssetAmount)
448431 if ((0 >= newQuote))
449432 then throw("Tx lead to base quote reserve <= 0, revert")
450433 else $Tuple3(newQuote, (bsAstR() + _baseAssetAmount), (totalPositionSize() - _baseAssetAmount))
451434 }
452435
453436
454437 func calcInvariant (_qtAstR,_bsAstR) = {
455438 let bqtAstR = toBigInt(_qtAstR)
456439 let bbsAstR = toBigInt(_bsAstR)
457440 bmuld(bqtAstR, bbsAstR)
458441 }
459442
460443
461444 func swapInput (_isAdd,_quoteAssetAmount) = {
462445 let _qtAstR = qtAstR()
463446 let _bsAstR = bsAstR()
464447 let _qtAstW = qtAstW()
465448 let _bsAstW = bsAstW()
466449 let quoteAssetAmountAdjusted = divd(_quoteAssetAmount, _qtAstW)
467450 let k = calcInvariant(_qtAstR, _bsAstR)
468451 let quoteAssetReserveAfter = if (_isAdd)
469452 then (_qtAstR + quoteAssetAmountAdjusted)
470453 else (_qtAstR - quoteAssetAmountAdjusted)
471454 let baseAssetReserveAfter = toInt(bdivd(k, toBigInt(quoteAssetReserveAfter)))
472455 let amountBaseAssetBoughtAbs = abs((baseAssetReserveAfter - _bsAstR))
473456 let amountBaseAssetBought = if (_isAdd)
474457 then amountBaseAssetBoughtAbs
475458 else -(amountBaseAssetBoughtAbs)
476- let $t01725917429 = updateReserve(_isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
477- let quoteAssetReserveAfter1 = $t01725917429._1
478- let baseAssetReserveAfter1 = $t01725917429._2
479- let totalPositionSizeAfter1 = $t01725917429._3
459+ let $t01672216892 = updateReserve(_isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
460+ let quoteAssetReserveAfter1 = $t01672216892._1
461+ let baseAssetReserveAfter1 = $t01672216892._2
462+ let totalPositionSizeAfter1 = $t01672216892._3
480463 let priceBefore = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
481464 let marketPrice = divd(_quoteAssetAmount, amountBaseAssetBoughtAbs)
482465 let priceDiff = abs((priceBefore - marketPrice))
483466 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
484467 let maxPriceImpactValue = maxPriceImpact()
485468 if ((priceImpact > maxPriceImpactValue))
486469 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)))
487470 else $Tuple4(amountBaseAssetBought, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1)
488471 }
489472
490473
491474 func calcRolloverFee (_oldPositionMargin,_oldPositionLastUpdatedTimestamp) = {
492475 let positionMinutes = ((((lastTimestamp() - _oldPositionLastUpdatedTimestamp) / 1000) / 60) * DECIMAL_UNIT)
493476 let rolloverFee = divd(muld(muld(_oldPositionMargin, positionMinutes), rolloverFeeRate()), MINUTES_IN_YEAR)
494477 rolloverFee
495478 }
496479
497480
498481 func calcRemainMarginWithFundingPaymentAndRolloverFee (_oldPositionSize,_oldPositionMargin,_oldPositionCumulativePremiumFraction,_oldPositionLastUpdatedTimestamp,_marginDelta) = {
499482 let fundingPayment = if ((_oldPositionSize != 0))
500483 then {
501484 let _latestCumulativePremiumFraction = latestCumulativePremiumFraction(_oldPositionSize)
502485 muld((_latestCumulativePremiumFraction - _oldPositionCumulativePremiumFraction), _oldPositionSize)
503486 }
504487 else 0
505488 let rolloverFee = calcRolloverFee(_oldPositionMargin, _oldPositionLastUpdatedTimestamp)
506489 let signedMargin = (((_marginDelta - rolloverFee) - fundingPayment) + _oldPositionMargin)
507- let $t01968419811 = if ((0 > signedMargin))
490+ let $t01914719274 = if ((0 > signedMargin))
508491 then $Tuple2(0, abs(signedMargin))
509492 else $Tuple2(abs(signedMargin), 0)
510- let remainMargin = $t01968419811._1
511- let badDebt = $t01968419811._2
493+ let remainMargin = $t01914719274._1
494+ let badDebt = $t01914719274._2
512495 $Tuple4(remainMargin, badDebt, fundingPayment, rolloverFee)
513496 }
514497
515498
516499 func swapOutputWithReserves (_isAdd,_baseAssetAmount,_checkMaxPriceImpact,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
517500 let priceBefore = divd(muld(_quoteAssetReserve, _quoteAssetWeight), muld(_baseAssetReserve, _baseAssetWeight))
518501 if ((_baseAssetAmount == 0))
519502 then throw("Invalid base asset amount")
520503 else {
521504 let k = calcInvariant(_quoteAssetReserve, _baseAssetReserve)
522505 let baseAssetPoolAmountAfter = if (_isAdd)
523506 then (_baseAssetReserve + _baseAssetAmount)
524507 else (_baseAssetReserve - _baseAssetAmount)
525508 let quoteAssetAfter = toInt(bdivd(k, toBigInt(baseAssetPoolAmountAfter)))
526509 let quoteAssetDelta = abs((quoteAssetAfter - _quoteAssetReserve))
527510 let quoteAssetSold = muld(quoteAssetDelta, _quoteAssetWeight)
528511 let maxPriceImpactValue = maxPriceImpact()
529- let $t02107321235 = updateReserve(!(_isAdd), quoteAssetDelta, _baseAssetAmount)
530- let quoteAssetReserveAfter1 = $t02107321235._1
531- let baseAssetReserveAfter1 = $t02107321235._2
532- let totalPositionSizeAfter1 = $t02107321235._3
512+ let $t02053620698 = updateReserve(!(_isAdd), quoteAssetDelta, _baseAssetAmount)
513+ let quoteAssetReserveAfter1 = $t02053620698._1
514+ let baseAssetReserveAfter1 = $t02053620698._2
515+ let totalPositionSizeAfter1 = $t02053620698._3
533516 let marketPrice = divd(quoteAssetSold, _baseAssetAmount)
534517 let priceDiff = abs((priceBefore - marketPrice))
535518 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
536519 if (if ((priceImpact > maxPriceImpactValue))
537520 then _checkMaxPriceImpact
538521 else false)
539522 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)))
540523 else $Tuple7(quoteAssetSold, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1, (totalLongPositionSize() - (if (_isAdd)
541524 then abs(_baseAssetAmount)
542525 else 0)), (totalShortPositionSize() - (if (!(_isAdd))
543526 then abs(_baseAssetAmount)
544527 else 0)), priceImpact)
545528 }
546529 }
547530
548531
549532 func swapOutput (_isAdd,_baseAssetAmount,_checkMaxPriceImpact) = swapOutputWithReserves(_isAdd, _baseAssetAmount, _checkMaxPriceImpact, qtAstR(), qtAstW(), bsAstR(), bsAstW())
550533
551534
552535 func getOraclePriceValue (oracle,priceKey,blockKey) = {
553536 let lastValue = valueOrErrorMessage(getInteger(oracle, priceKey), ((("Can not get oracle price. Oracle: " + toString(oracle)) + " key: ") + priceKey))
554537 if ((blockKey != ""))
555538 then {
556539 let currentBlock = lastBlock.height
557540 let lastOracleBlock = valueOrErrorMessage(getInteger(oracle, blockKey), ((("Can not get oracle block. Oracle: " + toString(oracle)) + " key: ") + blockKey))
558541 if (((currentBlock - lastOracleBlock) > maxOracleDelay()))
559542 then throw(((("Oracle stale data. Last oracle block: " + toString(lastOracleBlock)) + " current block: ") + toString(currentBlock)))
560543 else lastValue
561544 }
562545 else lastValue
563546 }
564547
565548
566549 func getOraclePrice () = {
567550 let baseOracle = valueOrErrorMessage(getOracleData(k_baseOracle), "No base asset oracle data")
568551 let baseOraclePrice = getOraclePriceValue(baseOracle._1, baseOracle._2, baseOracle._3)
569552 let quoteOracle = getOracleData(k_quoteOracle)
570553 let quoteOraclePrice = if (isDefined(quoteOracle))
571554 then {
572555 let quoteOracleV = value(quoteOracle)
573556 getOraclePriceValue(quoteOracleV._1, quoteOracleV._2, quoteOracleV._3)
574557 }
575558 else DECIMAL_UNIT
576559 divd(baseOraclePrice, quoteOraclePrice)
577560 }
578561
579562
580563 func isMarketClosed () = {
581564 let baseOracle = valueOrErrorMessage(getOracleData(k_baseOracle), "No base asset oracle data")
582565 let oracle = baseOracle._1
583566 let openKey = baseOracle._4
584567 if ((openKey != ""))
585568 then {
586569 let isOpen = valueOrErrorMessage(getBoolean(oracle, openKey), ((("Can not get oracle is open/closed. Oracle: " + toString(oracle)) + " key: ") + openKey))
587570 !(isOpen)
588571 }
589572 else false
590573 }
591574
592575
593576 func absPriceDiff (_oraclePrice,_quoteAssetReserve,_baseAssetReserve,_qtAstW,_bsAstW) = {
594577 let priceAfter = divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
595578 let averagePrice = divd((_oraclePrice + priceAfter), (2 * DECIMAL_UNIT))
596579 let absPriceDiff = divd(abs((_oraclePrice - priceAfter)), averagePrice)
597580 absPriceDiff
598581 }
599582
600583
601584 func requireNotOverSpreadLimit (_quoteAssetReserve,_baseAssetReserve) = {
602585 let oraclePrice = getOraclePrice()
603586 let _qtAstW = qtAstW()
604587 let _bsAstW = bsAstW()
605588 let absPriceDiffBefore = absPriceDiff(oraclePrice, qtAstR(), bsAstR(), _qtAstW, _bsAstW)
606589 let absPriceDiffAfter = absPriceDiff(oraclePrice, _quoteAssetReserve, _baseAssetReserve, _qtAstW, _bsAstW)
607590 if (if ((absPriceDiffAfter > maxPriceSpread()))
608591 then (absPriceDiffAfter > absPriceDiffBefore)
609592 else false)
610593 then throw(((("Price spread " + toString(absPriceDiffAfter)) + " > max price spread ") + toString(maxPriceSpread())))
611594 else true
612595 }
613596
614597
615598 func requireNotOverMaxOpenNotional (_longOpenNotional,_shortOpenNotional) = {
616599 let _maxOpenNotional = maxOpenNotional()
617600 if ((_longOpenNotional > _maxOpenNotional))
618601 then throw(((("Long open notional " + toString(_longOpenNotional)) + " > max open notional ") + toString(_maxOpenNotional)))
619602 else if ((_shortOpenNotional > _maxOpenNotional))
620603 then throw(((("Short open notional " + toString(_shortOpenNotional)) + " > max open notional ") + toString(_maxOpenNotional)))
621604 else true
622605 }
623606
624607
625608 func getSpotPrice () = {
626609 let _quoteAssetReserve = qtAstR()
627610 let _baseAssetReserve = bsAstR()
628611 let _qtAstW = qtAstW()
629612 let _bsAstW = bsAstW()
630613 divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
631614 }
632615
633616
634617 func isOverFluctuationLimit () = {
635618 let oraclePrice = getOraclePrice()
636619 let currentPrice = getSpotPrice()
637620 (divd(abs((oraclePrice - currentPrice)), oraclePrice) > spreadLimit())
638621 }
639622
640623
641624 func getPositionAdjustedOpenNotional (_positionSize,_option,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
642625 let positionSizeAbs = abs(_positionSize)
643626 let isShort = (0 > _positionSize)
644627 let positionNotional = if ((_option == PNL_OPTION_SPOT))
645628 then {
646629 let outPositionNotional = swapOutputWithReserves(!(isShort), positionSizeAbs, false, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)._1
647630 outPositionNotional
648631 }
649632 else muld(positionSizeAbs, getOraclePrice())
650633 positionNotional
651634 }
652635
653636
654637 func getPositionNotionalAndUnrealizedPnlByValues (_positionSize,_positionOpenNotional,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight,_option) = if ((_positionSize == 0))
655638 then throw("Invalid position size")
656639 else {
657640 let isShort = (0 > _positionSize)
658641 let positionNotional = getPositionAdjustedOpenNotional(_positionSize, _option, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
659642 let unrealizedPnl = if (isShort)
660643 then (_positionOpenNotional - positionNotional)
661644 else (positionNotional - _positionOpenNotional)
662645 $Tuple2(positionNotional, unrealizedPnl)
663646 }
664647
665648
666649 func getPositionNotionalAndUnrealizedPnl (_trader,_option) = {
667- let $t02911329241 = getPosition(_trader)
668- let positionSize = $t02911329241._1
669- let positionMargin = $t02911329241._2
670- let positionOpenNotional = $t02911329241._3
671- let positionLstUpdCPF = $t02911329241._4
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
672655 getPositionNotionalAndUnrealizedPnlByValues(positionSize, positionOpenNotional, qtAstR(), qtAstW(), bsAstR(), bsAstW(), _option)
673656 }
674657
675658
676659 func calcMarginRatio (_remainMargin,_badDebt,_positionNotional) = divd((_remainMargin - _badDebt), _positionNotional)
677660
678661
679662 func getMarginRatioByOption (_trader,_option) = {
680- let $t02975629897 = getPosition(_trader)
681- let positionSize = $t02975629897._1
682- let positionMargin = $t02975629897._2
683- let pon = $t02975629897._3
684- let positionLastUpdatedCPF = $t02975629897._4
685- let positionTimestamp = $t02975629897._5
686- let $t02990329996 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
687- let positionNotional = $t02990329996._1
688- let unrealizedPnl = $t02990329996._2
689- let $t03000130213 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLastUpdatedCPF, positionTimestamp, unrealizedPnl)
690- let remainMargin = $t03000130213._1
691- let badDebt = $t03000130213._2
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
692675 calcMarginRatio(remainMargin, badDebt, positionNotional)
693676 }
694677
695678
696679 func getMarginRatio (_trader) = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
697680
698681
699682 func getPartialLiquidationAmount (_trader,_positionSize) = {
700683 let maximumRatio = vmax(partialLiquidationRatio(), (DECIMAL_UNIT - divd(getMarginRatio(_trader), maintenanceMarginRatio())))
701684 let maxExchangedPositionSize = muld(abs(_positionSize), maximumRatio)
702685 let swapResult = swapOutput((_positionSize > 0), maxExchangedPositionSize, false)
703686 let maxExchangedQuoteAssetAmount = swapResult._1
704687 let priceImpact = swapResult._7
705688 if ((maxPriceImpact() > priceImpact))
706689 then maxExchangedPositionSize
707690 else muld(abs(_positionSize), partialLiquidationRatio())
708691 }
709692
710693
711-func internalClosePosition (_trader,_size,_fee,_minQuoteAssetAmount,_addToMargin,_checkMaxPriceImpact) = {
712- let $t03125731413 = getPosition(_trader)
713- let oldPositionSize = $t03125731413._1
714- let oldPositionMargin = $t03125731413._2
715- let oldPositionOpenNotional = $t03125731413._3
716- let oldPositionLstUpdCPF = $t03125731413._4
717- let oldPositionTimestamp = $t03125731413._5
694+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
718701 let isLongPosition = (oldPositionSize > 0)
719702 let absOldPositionSize = abs(oldPositionSize)
720703 if (if ((absOldPositionSize >= _size))
721704 then (_size > 0)
722705 else false)
723706 then {
724707 let isPartialClose = (absOldPositionSize > _size)
725- let $t03170532156 = swapOutput((oldPositionSize > 0), _size, _checkMaxPriceImpact)
726- let exchangedQuoteAssetAmount = $t03170532156._1
727- let quoteAssetReserveAfter = $t03170532156._2
728- let baseAssetReserveAfter = $t03170532156._3
729- let totalPositionSizeAfter = $t03170532156._4
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
730713 let exchangedPositionSize = if ((oldPositionSize > 0))
731714 then -(_size)
732715 else _size
733- let $t03237132578 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
734- let oldPositionNotional = $t03237132578._1
735- let unrealizedPnl = $t03237132578._2
716+ let $t03185732064 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
717+ let oldPositionNotional = $t03185732064._1
718+ let unrealizedPnl = $t03185732064._2
736719 let realizedRatio = divd(abs(exchangedPositionSize), absOldPositionSize)
737720 let realizedPnl = muld(unrealizedPnl, realizedRatio)
738- let $t03291933165 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, unrealizedPnl)
739- let remainMarginBefore = $t03291933165._1
740- let x1 = $t03291933165._2
741- let x2 = $t03291933165._3
742- let rolloverFee = $t03291933165._4
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
743726 let positionBadDebt = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, realizedPnl)._2
744727 let realizedCloseFee = muld(muld(oldPositionNotional, realizedRatio), _fee)
745728 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
746729 let remainOpenNotional = if ((oldPositionSize > 0))
747730 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
748731 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
749732 let newPositionSize = (oldPositionSize + exchangedPositionSize)
750- let $t03457134957 = if ((newPositionSize == 0))
733+ let $t03405734443 = if ((newPositionSize == 0))
751734 then $Tuple2(0, 0)
752735 else $Tuple2(abs(remainOpenNotional), latestCumulativePremiumFraction(newPositionSize))
753- let newPositionOpenNotional = $t03457134957._1
754- let newPositionLstUpdCPF = $t03457134957._2
736+ let newPositionOpenNotional = $t03405734443._1
737+ let newPositionLstUpdCPF = $t03405734443._2
755738 let openNotionalDelta = (oldPositionOpenNotional - newPositionOpenNotional)
756739 let marginRatio = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
757740 let newPositionMarginWithSameRatio = if ((oldPositionSize > 0))
758741 then (muld((newPositionOpenNotional + unrealizedPnlAfter), marginRatio) - unrealizedPnlAfter)
759742 else (muld((newPositionOpenNotional - unrealizedPnlAfter), marginRatio) - unrealizedPnlAfter)
760743 let marginToTraderRaw = ((remainMarginBefore - (newPositionMarginWithSameRatio + unrealizedPnlAfter)) - realizedCloseFee)
761744 let marginToTrader = if ((0 > marginToTraderRaw))
762- then throw("Invalid internalClosePosition params: unable to pay fee")
745+ then if (_liquidate)
746+ then 0
747+ else throw("Invalid internalClosePosition params: unable to pay fee")
763748 else marginToTraderRaw
764749 let newPositionMargin = if (_addToMargin)
765750 then (newPositionMarginWithSameRatio + marginToTrader)
766751 else newPositionMarginWithSameRatio
767752 if (if ((_minQuoteAssetAmount != 0))
768753 then (_minQuoteAssetAmount > exchangedQuoteAssetAmount)
769754 else false)
770755 then throw(((("Limit error: " + toString(exchangedQuoteAssetAmount)) + " < ") + toString(_minQuoteAssetAmount)))
771756 else $Tuple17(newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, positionBadDebt, realizedPnl, if (if (_addToMargin)
772757 then isPartialClose
773758 else false)
774759 then 0
775760 else marginToTrader, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, (openInterestNotional() - openNotionalDelta), (totalLongPositionSize() - (if (isLongPosition)
776761 then abs(exchangedPositionSize)
777762 else 0)), (totalShortPositionSize() - (if (!(isLongPosition))
778763 then abs(exchangedPositionSize)
779764 else 0)), (openInterestLong() - (if (isLongPosition)
780765 then openNotionalDelta
781766 else 0)), (openInterestShort() - (if (!(isLongPosition))
782767 then openNotionalDelta
783768 else 0)), (realizedCloseFee + rolloverFee), exchangedQuoteAssetAmount)
784769 }
785- else throw("Invalid internalClosePosition params: invalid position size")
770+ else throw(((("Invalid internalClosePosition params: invalid position size: " + toString(_size)) + " max: ") + toString(absOldPositionSize)))
786771 }
787772
788773
789774 func getTwapSpotPrice () = {
790775 let minuteId = ((lastTimestamp() / 1000) / 60)
791776 let startMinuteId = (minuteId - TWAP_INTERVAL)
792777 let listStr = valueOrElse(getString(this, k_lastDataStr), "")
793778 let list = split(listStr, ",")
794779 func filterFn (accumulator,next) = if ((startMinuteId >= valueOrErrorMessage(parseInt(next), ("getTwapSpotPrice: invalid int: " + listStr))))
795780 then (accumulator :+ parseIntValue(next))
796781 else accumulator
797782
798783 let listF = {
799784 let $l = list
800785 let $s = size($l)
801786 let $acc0 = nil
802787 func $f0_1 ($a,$i) = if (($i >= $s))
803788 then $a
804789 else filterFn($a, $l[$i])
805790
806791 func $f0_2 ($a,$i) = if (($i >= $s))
807792 then $a
808793 else throw("List size exceeds 20")
809794
810795 $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)
811796 }
812797 let maxIndex = if ((size(listF) > 0))
813798 then max(listF)
814799 else valueOrErrorMessage(parseInt(list[0]), ("getTwapSpotPrice: invalid int: " + listStr))
815800 let lastMinuteId = valueOrElse(getInteger(this, k_lastMinuteId), 0)
816801 let endLastCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(lastMinuteId))), 0)
817802 let endLastPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(lastMinuteId))), 0)
818803 let nowCumulativePrice = (endLastCumulativePrice + ((minuteId - lastMinuteId) * endLastPrice))
819804 let startLastCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(maxIndex))), 0)
820805 let startLastPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(maxIndex))), 0)
821806 let startCumulativePrice = (startLastCumulativePrice + ((startMinuteId - maxIndex) * startLastPrice))
822807 ((nowCumulativePrice - startCumulativePrice) / TWAP_INTERVAL)
823808 }
824809
825810
826811 func getTerminalAmmState () = {
827812 let _positionSize = totalPositionSize()
828813 if ((_positionSize == 0))
829814 then $Tuple2(qtAstR(), bsAstR())
830815 else {
831816 let direction = (_positionSize > 0)
832- let $t03956039739 = swapOutput(direction, abs(_positionSize), false)
833- let currentNetMarketValue = $t03956039739._1
834- let terminalQuoteAssetReserve = $t03956039739._2
835- let terminalBaseAssetReserve = $t03956039739._3
817+ let $t03918039359 = swapOutput(direction, abs(_positionSize), false)
818+ let currentNetMarketValue = $t03918039359._1
819+ let terminalQuoteAssetReserve = $t03918039359._2
820+ let terminalBaseAssetReserve = $t03918039359._3
836821 $Tuple2(terminalQuoteAssetReserve, terminalBaseAssetReserve)
837822 }
838823 }
839824
840825
841826 func getQuoteAssetWeight (baseAssetReserve,totalPositionSize,quoteAssetReserve,targetPrice) = {
842827 let b = toBigInt(baseAssetReserve)
843828 let sz = toBigInt(totalPositionSize)
844829 let q = toBigInt(quoteAssetReserve)
845830 let p = toBigInt(targetPrice)
846831 let k = bmuld(q, b)
847832 let newB = (b + sz)
848833 let newQ = bdivd(k, newB)
849834 let z = bdivd(newQ, newB)
850835 let result = bdivd(p, z)
851836 toInt(result)
852837 }
853838
854839
855840 func getSyncTerminalPrice (_terminalPrice,_qtAstR,_bsAstR) = {
856841 let _positionSize = totalPositionSize()
857842 if ((_positionSize == 0))
858843 then {
859844 let newQtAstW = divd(muld(_terminalPrice, _bsAstR), _qtAstR)
860845 $Tuple3(newQtAstW, DECIMAL_UNIT, 0)
861846 }
862847 else {
863848 let direction = (_positionSize > 0)
864849 let currentNetMarketValue = swapOutput(direction, abs(_positionSize), false)._1
865850 let newQtAstW = getQuoteAssetWeight(_bsAstR, _positionSize, _qtAstR, _terminalPrice)
866851 let newBsAstW = DECIMAL_UNIT
867852 let marginToVault = getPositionNotionalAndUnrealizedPnlByValues(_positionSize, currentNetMarketValue, _qtAstR, newQtAstW, _bsAstR, newBsAstW, PNL_OPTION_SPOT)._2
868853 $Tuple3(newQtAstW, newBsAstW, marginToVault)
869854 }
870855 }
871856
872857
873858 func getFunding () = {
874859 let underlyingPrice = getOraclePrice()
875860 let spotTwapPrice = getTwapSpotPrice()
876861 let premium = (spotTwapPrice - underlyingPrice)
877862 if (if (if ((totalShortPositionSize() == 0))
878863 then true
879864 else (totalLongPositionSize() == 0))
880865 then true
881866 else isMarketClosed())
882867 then $Tuple2(0, 0)
883868 else if ((0 > premium))
884869 then {
885870 let shortPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
886871 let longPremiumFraction = divd(muld(shortPremiumFraction, totalShortPositionSize()), totalLongPositionSize())
887872 $Tuple2(shortPremiumFraction, longPremiumFraction)
888873 }
889874 else {
890875 let longPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
891876 let shortPremiumFraction = divd(muld(longPremiumFraction, totalLongPositionSize()), totalShortPositionSize())
892877 $Tuple2(shortPremiumFraction, longPremiumFraction)
893878 }
894879 }
895880
896881
897882 func getAdjustedFee (_artifactId,_baseFeeDiscount) = {
898883 let baseFeeRaw = fee()
899884 let baseFee = muld(baseFeeRaw, _baseFeeDiscount)
900- let $t04260043095 = if ((_artifactId != ""))
885+ let $t04222042715 = if ((_artifactId != ""))
901886 then {
902887 let artifactKind = strA(nftManagerAddress(), toCompositeKey(k_token_type, _artifactId))
903888 if ((artifactKind == FEE_REDUCTION_TOKEN_TYPE))
904889 then {
905890 let reduction = intA(nftManagerAddress(), toCompositeKey(k_token_param, _artifactId))
906891 let adjustedFee = muld(baseFee, reduction)
907892 $Tuple2(adjustedFee, true)
908893 }
909894 else throw("Invalid attached artifact")
910895 }
911896 else $Tuple2(baseFee, false)
912- let adjustedFee = $t04260043095._1
913- let burnArtifact = $t04260043095._2
897+ let adjustedFee = $t04222042715._1
898+ let burnArtifact = $t04222042715._2
914899 $Tuple2(adjustedFee, burnArtifact)
915900 }
916901
917902
918903 func isSameAssetOrNoPosition (_trader,_assetId) = {
919904 let oldPositionSize = getPosition(_trader)._1
920905 if ((oldPositionSize == 0))
921906 then true
922907 else (getPositionAsset(_trader) == _assetId)
923908 }
924909
925910
926911 func isSameAsset (_trader,_assetId) = (getPositionAsset(_trader) == _assetId)
927912
928913
929914 func getForTraderWithArtifact (_trader,_artifactId) = {
930915 let doGetFeeDiscount = invoke(minerAddress(), "computeFeeDiscount", [_trader], nil)
931916 if ((doGetFeeDiscount == doGetFeeDiscount))
932917 then {
933918 let feeDiscount = match doGetFeeDiscount {
934919 case x: Int =>
935920 x
936921 case _ =>
937922 throw("Invalid computeFeeDiscount result")
938923 }
939- let $t04377543849 = getAdjustedFee(_artifactId, feeDiscount)
940- let adjustedFee = $t04377543849._1
941- let burnArtifact = $t04377543849._2
924+ let $t04339543469 = getAdjustedFee(_artifactId, feeDiscount)
925+ let adjustedFee = $t04339543469._1
926+ let burnArtifact = $t04339543469._2
942927 $Tuple2(adjustedFee, burnArtifact)
943928 }
944929 else throw("Strict value is not equal to itself.")
945930 }
946931
947932
948933 func getArtifactId (i) = {
949934 let artifactId = if ((size(i.payments) > 1))
950935 then toBase58String(valueOrErrorMessage(i.payments[1].assetId, "Invalid artifactId"))
951936 else ""
952937 artifactId
953938 }
954939
955940
956941 func distributeFee (_feeAmount) = {
957942 let feeToStakers = muld(_feeAmount, feeToStakersPercent())
958943 let feeToVault = (_feeAmount - feeToStakers)
959944 $Tuple2(feeToStakers, feeToVault)
960945 }
961946
962947
963948 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)]
964949
965950
966951 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)]
967952
968953
969954 func incrementPositionSequenceNumber (_isNewPosition,_address) = if (_isNewPosition)
970955 then {
971956 let currentSequence = lastSequence()
972957 [IntegerEntry(toCompositeKey(k_positionSequence, _address), (currentSequence + 1)), IntegerEntry(k_sequence, (currentSequence + 1))]
973958 }
974959 else nil
975960
976961
977962 func updatePositionFee (_isNewPosition,_address,_fee) = if (_isNewPosition)
978963 then [IntegerEntry(toCompositeKey(k_positionFee, _address), _fee)]
979964 else nil
980965
981966
982967 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)]
983968
984969
985970 func appendTwap (_price) = {
986971 let minuteId = ((lastTimestamp() / 1000) / 60)
987972 let previousMinuteId = valueOrElse(getInteger(this, k_lastMinuteId), 0)
988973 if ((previousMinuteId > minuteId))
989974 then throw("TWAP out-of-order")
990975 else {
991976 let lastMinuteId = if ((previousMinuteId == 0))
992977 then minuteId
993978 else previousMinuteId
994979 if ((minuteId > previousMinuteId))
995980 then {
996981 let prevCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(previousMinuteId))), 0)
997982 let prevPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(previousMinuteId))), _price)
998983 let lastCumulativePrice = (prevCumulativePrice + ((minuteId - lastMinuteId) * prevPrice))
999984 let list = pushToQueue(strToList(valueOrElse(getString(this, k_lastDataStr), "")), TWAP_INTERVAL, toString(minuteId))
1000985 [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))]
1001986 }
1002987 else {
1003988 let twapDataPreviousMinuteId = valueOrElse(getInteger(this, toCompositeKey(k_twapDataPreviousMinuteId, toString(minuteId))), 0)
1004989 let prevCumulativePrice = valueOrElse(getInteger(this, toCompositeKey(k_twapDataLastCumulativePrice, toString(twapDataPreviousMinuteId))), 0)
1005990 let prevPrice = valueOrElse(getInteger(this, toCompositeKey(k_twapDataLastPrice, toString(twapDataPreviousMinuteId))), _price)
1006991 let lastCumulativePrice = (prevCumulativePrice + ((minuteId - twapDataPreviousMinuteId) * prevPrice))
1007992 [IntegerEntry(toCompositeKey(k_twapDataLastCumulativePrice, toString(minuteId)), lastCumulativePrice), IntegerEntry(toCompositeKey(k_twapDataLastPrice, toString(minuteId)), _price)]
1008993 }
1009994 }
1010995 }
1011996
1012997
1013998 func updateAmmReserves (_qtAstR,_bsAstR) = [IntegerEntry(k_quoteAssetReserve, _qtAstR), IntegerEntry(k_baseAssetReserve, _bsAstR)]
1014999
10151000
10161001 func updateAmmWeights (_qtAstW,_bsAstW) = [IntegerEntry(k_quoteAssetWeight, _qtAstW), IntegerEntry(k_baseAssetWeight, _bsAstW)]
10171002
10181003
10191004 func updateAmm (_qtAstR,_bsAstR,_totalPositionSizeAfter,_openInterestNotional,_totalLongPositionSize,_totalShortPositionSize,_totalLongOpenNotional,_totalShortOpenNotional) = {
10201005 let _qtAstW = qtAstW()
10211006 let _bsAstW = bsAstW()
10221007 if (((_totalLongPositionSize - _totalShortPositionSize) != _totalPositionSizeAfter))
10231008 then throw(((((("Invalid AMM state data: " + toString(_totalLongPositionSize)) + " + ") + toString(_totalShortPositionSize)) + " != ") + toString(_totalPositionSizeAfter)))
10241009 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))))
10251010 }
10261011
10271012
10281013 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))]
10291014
10301015
10311016 func withdraw (_address,_amount) = {
10321017 let balance = assetBalance(this, quoteAsset())
10331018 if ((_amount > balance))
10341019 then throw(((("Unable to withdraw " + toString(_amount)) + " from contract balance ") + toString(balance)))
10351020 else [ScriptTransfer(_address, _amount, quoteAsset())]
10361021 }
10371022
10381023
10391024 func updateBalance (i) = if ((0 > i))
10401025 then throw("Balance")
10411026 else [IntegerEntry(k_balance, i)]
10421027
10431028
10441029 func transferFee (i) = [ScriptTransfer(stakingAddress(), i, quoteAsset())]
10451030
10461031
10471032 func doBurnArtifact (_burnArtifact,i) = if (_burnArtifact)
10481033 then [Burn(valueOrErrorMessage(i.payments[1].assetId, "Invalid artifact"), 1)]
10491034 else nil
10501035
10511036
10521037 @Callable(i)
10531038 func pause () = if ((i.caller != adminAddress()))
10541039 then throw("Invalid pause params")
10551040 else [BooleanEntry(k_paused, true)]
10561041
10571042
10581043
10591044 @Callable(i)
10601045 func unpause () = if ((i.caller != adminAddress()))
10611046 then throw("Invalid unpause params")
10621047 else [BooleanEntry(k_paused, false)]
10631048
10641049
10651050
10661051 @Callable(i)
10671052 func setCloseOnly () = if ((i.caller != adminAddress()))
10681053 then throw("Invalid setCloseOnly params")
10691054 else [BooleanEntry(k_closeOnly, true)]
10701055
10711056
10721057
10731058 @Callable(i)
10741059 func unsetCloseOnly () = if ((i.caller != adminAddress()))
10751060 then throw("Invalid unsetCloseOnly params")
10761061 else [BooleanEntry(k_closeOnly, false)]
10771062
10781063
10791064
10801065 @Callable(i)
10811066 func addLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
10821067 then true
10831068 else (0 >= _quoteAssetAmount))
10841069 then throw("Invalid addLiquidity params")
10851070 else {
10861071 let _qtAstR = qtAstR()
10871072 let _bsAstR = bsAstR()
10881073 let _qtAstW = qtAstW()
10891074 let _bsAstW = bsAstW()
10901075 let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
10911076 let qtAstRAfter = (_qtAstR + _quoteAssetAmount)
10921077 let baseAssetAmountToAdd = (divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR)
10931078 let bsAstRAfter = (_bsAstR + baseAssetAmountToAdd)
1094- let $t05325653407 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1095- let newQuoteAssetWeight = $t05325653407._1
1096- let newBaseAssetWeight = $t05325653407._2
1097- let marginToVault = $t05325653407._3
1079+ let $t05287653027 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1080+ let newQuoteAssetWeight = $t05287653027._1
1081+ let newBaseAssetWeight = $t05287653027._2
1082+ let marginToVault = $t05287653027._3
10981083 let doExchangePnL = if ((marginToVault != 0))
10991084 then {
11001085 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
11011086 if ((doExchangePnL == doExchangePnL))
11021087 then nil
11031088 else throw("Strict value is not equal to itself.")
11041089 }
11051090 else nil
11061091 if ((doExchangePnL == doExchangePnL))
11071092 then (updateAmmReserves(qtAstRAfter, bsAstRAfter) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
11081093 else throw("Strict value is not equal to itself.")
11091094 }
11101095
11111096
11121097
11131098 @Callable(i)
11141099 func removeLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
11151100 then true
11161101 else (_quoteAssetAmount >= 0))
11171102 then throw("Invalid removeLiquidity params")
11181103 else {
11191104 let _qtAstR = qtAstR()
11201105 let _bsAstR = bsAstR()
11211106 let _qtAstW = qtAstW()
11221107 let _bsAstW = bsAstW()
11231108 let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
11241109 let qtAstRAfter = (_qtAstR - _quoteAssetAmount)
11251110 let baseAssetAmountToRemove = abs((divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR))
11261111 let bsAstRAfter = (_bsAstR - baseAssetAmountToRemove)
1127- let $t05433954490 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1128- let newQuoteAssetWeight = $t05433954490._1
1129- let newBaseAssetWeight = $t05433954490._2
1130- let marginToVault = $t05433954490._3
1112+ let $t05395954110 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1113+ let newQuoteAssetWeight = $t05395954110._1
1114+ let newBaseAssetWeight = $t05395954110._2
1115+ let marginToVault = $t05395954110._3
11311116 let doExchangePnL = if ((marginToVault != 0))
11321117 then {
11331118 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
11341119 if ((doExchangePnL == doExchangePnL))
11351120 then nil
11361121 else throw("Strict value is not equal to itself.")
11371122 }
11381123 else nil
11391124 if ((doExchangePnL == doExchangePnL))
11401125 then (updateAmmReserves(qtAstRAfter, bsAstRAfter) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
11411126 else throw("Strict value is not equal to itself.")
11421127 }
11431128
11441129
11451130
11461131 @Callable(i)
11471132 func changeSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay,_rolloverFee) = if ((i.caller != adminAddress()))
11481133 then throw("Invalid changeSettings params")
11491134 else updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact, _partialLiquidationRatio, _maxPriceSpread, _maxOpenNotional, _feeToStakersPercent, _maxOracleDelay, _rolloverFee)
11501135
11511136
11521137
11531138 @Callable(i)
1154-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 ((0 >= _qtAstR))
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))
11551140 then true
11561141 else (0 >= _bsAstR))
11571142 then true
11581143 else (0 >= _fundingPeriod))
11591144 then true
11601145 else (0 >= _initMarginRatio))
11611146 then true
11621147 else (0 >= _mmr))
11631148 then true
11641149 else (0 >= _liquidationFeeRatio))
11651150 then true
11661151 else (0 >= _fee))
11671152 then true
11681153 else (0 >= _spreadLimit))
11691154 then true
11701155 else (0 >= _maxPriceImpact))
11711156 then true
11721157 else (0 >= _partialLiquidationRatio))
11731158 then true
11741159 else (0 >= _maxPriceSpread))
11751160 then true
11761161 else (0 >= _maxOpenNotional))
11771162 then true
11781163 else (0 >= _feeToStakersPercent))
11791164 then true
11801165 else (_feeToStakersPercent > DECIMAL_UNIT))
11811166 then true
11821167 else (0 >= _maxOracleDelay))
11831168 then true
11841169 else (0 >= _rolloverFee))
11851170 then true
11861171 else initialized())
1172+ then true
1173+ else (i.caller != this))
11871174 then throw("Invalid initialize parameters")
1188- 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, _coordinator)])
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)))])
11891176
11901177
11911178
11921179 @Callable(i)
11931180 func increasePosition (_direction,_leverage,_minBaseAssetAmount,_refLink) = {
11941181 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
11951182 if ((sync == sync))
11961183 then {
11971184 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
11981185 if ((ensureCalledOnce == ensureCalledOnce))
11991186 then {
12001187 let _trader = getActualCaller(i)
12011188 let _rawAmount = i.payments[0].amount
12021189 let _assetId = i.payments[0].assetId
12031190 let _assetIdStr = toBase58String(value(_assetId))
12041191 let isQuoteAsset = (_assetId == quoteAsset())
12051192 if (if (if (if (if (if (if (if (if (if ((_direction != DIR_LONG))
12061193 then (_direction != DIR_SHORT)
12071194 else false)
12081195 then true
12091196 else (0 >= _rawAmount))
12101197 then true
12111198 else !(initialized()))
12121199 then true
12131200 else !(isQuoteAsset))
12141201 then true
12151202 else !(isSameAssetOrNoPosition(_trader, _assetIdStr)))
12161203 then true
12171204 else !(requireMoreMarginRatio(divd(DECIMAL_UNIT, _leverage), initMarginRatio(), true)))
12181205 then true
12191206 else paused())
12201207 then true
12211208 else closeOnly())
12221209 then true
12231210 else isMarketClosed())
12241211 then throw("Invalid increasePosition parameters")
12251212 else {
1226- let $t05820958358 = getForTraderWithArtifact(_trader, getArtifactId(i))
1227- let adjustedFee = $t05820958358._1
1228- let burnArtifact = $t05820958358._2
1213+ let $t05788858037 = getForTraderWithArtifact(_trader, getArtifactId(i))
1214+ let adjustedFee = $t05788858037._1
1215+ let burnArtifact = $t05788858037._2
12291216 let _amount = divd(_rawAmount, (muld(adjustedFee, _leverage) + DECIMAL_UNIT))
12301217 let distributeFeeAmount = (_rawAmount - _amount)
12311218 let referrerFeeAny = invoke(referralAddress(), "acceptPaymentWithLink", [_trader, _refLink], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
12321219 if ((referrerFeeAny == referrerFeeAny))
12331220 then {
12341221 let referrerFee = match referrerFeeAny {
12351222 case x: Int =>
12361223 x
12371224 case _ =>
12381225 throw("Invalid referrerFee")
12391226 }
12401227 let feeAmount = (distributeFeeAmount - referrerFee)
1241- let $t05885459022 = getPosition(_trader)
1242- let oldPositionSize = $t05885459022._1
1243- let oldPositionMargin = $t05885459022._2
1244- let oldPositionOpenNotional = $t05885459022._3
1245- let oldPositionLstUpdCPF = $t05885459022._4
1246- let oldPositionTimestamp = $t05885459022._5
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
12471234 let isNewPosition = (oldPositionSize == 0)
12481235 let isSameDirection = if ((oldPositionSize > 0))
12491236 then (_direction == DIR_LONG)
12501237 else (_direction == DIR_SHORT)
12511238 let expandExisting = if (!(isNewPosition))
12521239 then isSameDirection
12531240 else false
12541241 let isAdd = (_direction == DIR_LONG)
1255- let $t05931162432 = if (if (isNewPosition)
1242+ let $t05899062111 = if (if (isNewPosition)
12561243 then true
12571244 else expandExisting)
12581245 then {
12591246 let openNotional = muld(_amount, _leverage)
1260- let $t05982059993 = swapInput(isAdd, openNotional)
1261- let amountBaseAssetBought = $t05982059993._1
1262- let quoteAssetReserveAfter = $t05982059993._2
1263- let baseAssetReserveAfter = $t05982059993._3
1264- let totalPositionSizeAfter = $t05982059993._4
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
12651252 if (if ((_minBaseAssetAmount != 0))
12661253 then (_minBaseAssetAmount > abs(amountBaseAssetBought))
12671254 else false)
12681255 then throw(((("Limit error: " + toString(abs(amountBaseAssetBought))) + " < ") + toString(_minBaseAssetAmount)))
12691256 else {
12701257 let newPositionSize = (oldPositionSize + amountBaseAssetBought)
12711258 let totalLongOpenInterestAfter = (openInterestLong() + (if ((newPositionSize > 0))
12721259 then openNotional
12731260 else 0))
12741261 let totalShortOpenInterestAfter = (openInterestShort() + (if ((0 > newPositionSize))
12751262 then openNotional
12761263 else 0))
1277- let $t06053960814 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, _amount)
1278- let remainMargin = $t06053960814._1
1279- let x1 = $t06053960814._2
1280- let x2 = $t06053960814._3
1281- let rolloverFee = $t06053960814._4
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
12821269 if (!(requireNotOverSpreadLimit(quoteAssetReserveAfter, baseAssetReserveAfter)))
12831270 then throw("Over max spread limit")
12841271 else if (!(requireNotOverMaxOpenNotional(totalLongOpenInterestAfter, totalShortOpenInterestAfter)))
12851272 then throw("Over max open notional")
12861273 else $Tuple14(newPositionSize, remainMargin, (oldPositionOpenNotional + openNotional), latestCumulativePremiumFraction(newPositionSize), lastTimestamp(), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, (openInterestNotional() + openNotional), (totalLongPositionSize() + (if ((newPositionSize > 0))
12871274 then abs(amountBaseAssetBought)
12881275 else 0)), (totalShortPositionSize() + (if ((0 > newPositionSize))
12891276 then abs(amountBaseAssetBought)
12901277 else 0)), totalLongOpenInterestAfter, totalShortOpenInterestAfter, rolloverFee)
12911278 }
12921279 }
12931280 else {
12941281 let openNotional = muld(_amount, _leverage)
1295- let $t06213262248 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1296- let oldPositionNotional = $t06213262248._1
1297- let unrealizedPnl = $t06213262248._2
1282+ let $t06181161927 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1283+ let oldPositionNotional = $t06181161927._1
1284+ let unrealizedPnl = $t06181161927._2
12981285 if ((oldPositionNotional > openNotional))
12991286 then throw("Use decreasePosition to decrease position size")
13001287 else throw("Close position first")
13011288 }
1302- let newPositionSize = $t05931162432._1
1303- let newPositionRemainMargin = $t05931162432._2
1304- let newPositionOpenNotional = $t05931162432._3
1305- let newPositionLatestCPF = $t05931162432._4
1306- let newPositionTimestamp = $t05931162432._5
1307- let baseAssetReserveAfter = $t05931162432._6
1308- let quoteAssetReserveAfter = $t05931162432._7
1309- let totalPositionSizeAfter = $t05931162432._8
1310- let openInterestNotionalAfter = $t05931162432._9
1311- let totalLongAfter = $t05931162432._10
1312- let totalShortAfter = $t05931162432._11
1313- let totalLongOpenInterestAfter = $t05931162432._12
1314- let totalShortOpenInterestAfter = $t05931162432._13
1315- let rolloverFee = $t05931162432._14
1316- let $t06243862509 = distributeFee((feeAmount + rolloverFee))
1317- let feeToStakers = $t06243862509._1
1318- let feeToVault = $t06243862509._2
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
13191306 let stake = if ((_amount >= rolloverFee))
13201307 then invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), (_amount - rolloverFee))])
13211308 else invoke(vaultAddress(), "withdrawLocked", [(rolloverFee - _amount)], nil)
13221309 if ((stake == stake))
13231310 then {
13241311 let depositVault = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
13251312 if ((depositVault == depositVault))
13261313 then {
13271314 let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, feeAmount], nil)
13281315 if ((notifyFee == notifyFee))
13291316 then {
13301317 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
13311318 if ((notifyNotional == notifyNotional))
13321319 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))
13331320 else throw("Strict value is not equal to itself.")
13341321 }
13351322 else throw("Strict value is not equal to itself.")
13361323 }
13371324 else throw("Strict value is not equal to itself.")
13381325 }
13391326 else throw("Strict value is not equal to itself.")
13401327 }
13411328 else throw("Strict value is not equal to itself.")
13421329 }
13431330 }
13441331 else throw("Strict value is not equal to itself.")
13451332 }
13461333 else throw("Strict value is not equal to itself.")
13471334 }
13481335
13491336
13501337
13511338 @Callable(i)
13521339 func addMargin () = {
13531340 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
13541341 if ((sync == sync))
13551342 then {
13561343 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
13571344 if ((ensureCalledOnce == ensureCalledOnce))
13581345 then {
13591346 let _trader = toString(i.caller)
13601347 let _amount = i.payments[0].amount
13611348 let _assetId = i.payments[0].assetId
13621349 let _assetIdStr = toBase58String(value(_assetId))
13631350 let isQuoteAsset = (_assetId == quoteAsset())
13641351 if (if (if (if (if (if (if (!(isQuoteAsset))
13651352 then true
13661353 else !(requireOpenPosition(toString(i.caller))))
13671354 then true
13681355 else !(isSameAsset(_trader, _assetIdStr)))
13691356 then true
13701357 else !(initialized()))
13711358 then true
13721359 else paused())
13731360 then true
13741361 else closeOnly())
13751362 then true
13761363 else isMarketClosed())
13771364 then throw("Invalid addMargin parameters")
13781365 else {
1379- let $t06462064788 = getPosition(_trader)
1380- let oldPositionSize = $t06462064788._1
1381- let oldPositionMargin = $t06462064788._2
1382- let oldPositionOpenNotional = $t06462064788._3
1383- let oldPositionLstUpdCPF = $t06462064788._4
1384- let oldPositionTimestamp = $t06462064788._5
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
13851372 let stake = invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), _amount)])
13861373 if ((stake == stake))
13871374 then {
13881375 let rolloverFee = calcRolloverFee(oldPositionMargin, oldPositionTimestamp)
13891376 let doTransferFeeToStakers = if ((rolloverFee > 0))
13901377 then {
1391- let $t06507365132 = distributeFee(rolloverFee)
1392- let feeToStakers = $t06507365132._1
1393- let feeToVault = $t06507365132._2
1378+ let $t06475264811 = distributeFee(rolloverFee)
1379+ let feeToStakers = $t06475264811._1
1380+ let feeToVault = $t06475264811._2
13941381 let unstake = invoke(vaultAddress(), "withdrawLocked", [feeToStakers], nil)
13951382 if ((unstake == unstake))
13961383 then {
13971384 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(feeToVault)], nil)
13981385 if ((lockBadDebt == lockBadDebt))
13991386 then transferFee(feeToStakers)
14001387 else throw("Strict value is not equal to itself.")
14011388 }
14021389 else throw("Strict value is not equal to itself.")
14031390 }
14041391 else nil
14051392 if ((doTransferFeeToStakers == doTransferFeeToStakers))
14061393 then ((updatePosition(_trader, oldPositionSize, ((oldPositionMargin - rolloverFee) + _amount), oldPositionOpenNotional, oldPositionLstUpdCPF, lastTimestamp()) ++ updateBalance(((cbalance() + _amount) - rolloverFee))) ++ doTransferFeeToStakers)
14071394 else throw("Strict value is not equal to itself.")
14081395 }
14091396 else throw("Strict value is not equal to itself.")
14101397 }
14111398 }
14121399 else throw("Strict value is not equal to itself.")
14131400 }
14141401 else throw("Strict value is not equal to itself.")
14151402 }
14161403
14171404
14181405
14191406 @Callable(i)
14201407 func removeMargin (_amount) = {
14211408 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
14221409 if ((sync == sync))
14231410 then {
14241411 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
14251412 if ((ensureCalledOnce == ensureCalledOnce))
14261413 then {
14271414 let _trader = toString(i.caller)
14281415 if (if (if (if (if ((0 >= _amount))
14291416 then true
14301417 else !(requireOpenPosition(_trader)))
14311418 then true
14321419 else !(initialized()))
14331420 then true
14341421 else paused())
14351422 then true
14361423 else isMarketClosed())
14371424 then throw("Invalid removeMargin parameters")
14381425 else {
1439- let $t06624466412 = getPosition(_trader)
1440- let oldPositionSize = $t06624466412._1
1441- let oldPositionMargin = $t06624466412._2
1442- let oldPositionOpenNotional = $t06624466412._3
1443- let oldPositionLstUpdCPF = $t06624466412._4
1444- let oldPositionTimestamp = $t06624466412._5
1445- let $t06641866667 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, -(_amount))
1446- let remainMargin = $t06641866667._1
1447- let badDebt = $t06641866667._2
1448- let fundingPayment = $t06641866667._3
1449- let rolloverFee = $t06641866667._4
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
14501437 if ((badDebt != 0))
14511438 then throw("Invalid removed margin amount")
14521439 else {
14531440 let marginRatio = calcMarginRatio(remainMargin, badDebt, oldPositionOpenNotional)
14541441 if (!(requireMoreMarginRatio(marginRatio, initMarginRatio(), true)))
14551442 then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
14561443 else {
1457- let $t06705367112 = distributeFee(rolloverFee)
1458- let feeToStakers = $t06705367112._1
1459- let feeToVault = $t06705367112._2
1444+ let $t06673266791 = distributeFee(rolloverFee)
1445+ let feeToStakers = $t06673266791._1
1446+ let feeToVault = $t06673266791._2
14601447 let doTransferFeeToStakers = if ((rolloverFee > 0))
14611448 then {
14621449 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(feeToVault)], nil)
14631450 if ((lockBadDebt == lockBadDebt))
14641451 then transferFee(feeToStakers)
14651452 else throw("Strict value is not equal to itself.")
14661453 }
14671454 else nil
14681455 if ((doTransferFeeToStakers == doTransferFeeToStakers))
14691456 then {
14701457 let unstake = invoke(vaultAddress(), "withdrawLocked", [(_amount + feeToStakers)], nil)
14711458 if ((unstake == unstake))
14721459 then (((updatePosition(_trader, oldPositionSize, remainMargin, oldPositionOpenNotional, latestCumulativePremiumFraction(oldPositionSize), lastTimestamp()) ++ withdraw(i.caller, _amount)) ++ updateBalance(((cbalance() - _amount) - rolloverFee))) ++ doTransferFeeToStakers)
14731460 else throw("Strict value is not equal to itself.")
14741461 }
14751462 else throw("Strict value is not equal to itself.")
14761463 }
14771464 }
14781465 }
14791466 }
14801467 else throw("Strict value is not equal to itself.")
14811468 }
14821469 else throw("Strict value is not equal to itself.")
14831470 }
14841471
14851472
14861473
14871474 @Callable(i)
14881475 func closePosition (_size,_minQuoteAssetAmount,_addToMargin) = {
14891476 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
14901477 if ((sync == sync))
14911478 then {
14921479 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
14931480 if ((ensureCalledOnce == ensureCalledOnce))
14941481 then {
14951482 let _trader = getActualCaller(i)
14961483 let _traderAddress = valueOrErrorMessage(addressFromString(_trader), "Invalid caller")
14971484 let positionFee = getPositionFee(_trader)
14981485 if (if (if (if (if (if (!(requireOpenPosition(_trader)))
14991486 then true
15001487 else !(initialized()))
15011488 then true
15021489 else paused())
15031490 then true
15041491 else (0 >= _size))
15051492 then true
15061493 else (0 > _minQuoteAssetAmount))
15071494 then true
15081495 else isMarketClosed())
15091496 then throw("Invalid closePosition parameters")
15101497 else {
15111498 let oldPositionTimestamp = getPosition(_trader)._5
1512- let $t06876969342 = internalClosePosition(_trader, _size, positionFee, _minQuoteAssetAmount, _addToMargin, true)
1513- let newPositionSize = $t06876969342._1
1514- let newPositionMargin = $t06876969342._2
1515- let newPositionOpenNotional = $t06876969342._3
1516- let newPositionLstUpdCPF = $t06876969342._4
1517- let positionBadDebt = $t06876969342._5
1518- let realizedPnl = $t06876969342._6
1519- let marginToTrader = $t06876969342._7
1520- let quoteAssetReserveAfter = $t06876969342._8
1521- let baseAssetReserveAfter = $t06876969342._9
1522- let totalPositionSizeAfter = $t06876969342._10
1523- let openInterestNotionalAfter = $t06876969342._11
1524- let totalLongAfter = $t06876969342._12
1525- let totalShortAfter = $t06876969342._13
1526- let totalLongOpenInterestAfter = $t06876969342._14
1527- let totalShortOpenInterestAfter = $t06876969342._15
1528- let realizedFee = $t06876969342._16
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
15291516 if ((positionBadDebt > 0))
15301517 then throw("Invalid closePosition parameters: bad debt")
15311518 else if ((oldPositionTimestamp >= lastTimestamp()))
15321519 then throw("Invalid closePosition parameters: wait at least 1 block before closing the position")
15331520 else {
15341521 let isPartialClose = (newPositionSize != 0)
15351522 let withdrawAmount = (marginToTrader + realizedFee)
15361523 let ammBalance = (cbalance() - withdrawAmount)
15371524 let ammNewBalance = if ((0 > ammBalance))
15381525 then 0
15391526 else ammBalance
15401527 let unstake = invoke(vaultAddress(), "withdrawLocked", [withdrawAmount], nil)
15411528 if ((unstake == unstake))
15421529 then {
1543- let $t07001470073 = distributeFee(realizedFee)
1544- let feeToStakers = $t07001470073._1
1545- let feeToVault = $t07001470073._2
1530+ let $t06970569764 = distributeFee(realizedFee)
1531+ let feeToStakers = $t06970569764._1
1532+ let feeToVault = $t06970569764._2
15461533 let depositVault = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
15471534 if ((depositVault == depositVault))
15481535 then {
15491536 let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, realizedFee], nil)
15501537 if ((notifyFee == notifyFee))
15511538 then {
15521539 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
15531540 if ((notifyNotional == notifyNotional))
15541541 then (((((if (isPartialClose)
15551542 then updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, lastTimestamp())
15561543 else deletePosition(_trader)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ (if ((marginToTrader > 0))
15571544 then withdraw(_traderAddress, marginToTrader)
15581545 else nil)) ++ updateBalance(ammNewBalance)) ++ transferFee(feeToStakers))
15591546 else throw("Strict value is not equal to itself.")
15601547 }
15611548 else throw("Strict value is not equal to itself.")
15621549 }
15631550 else throw("Strict value is not equal to itself.")
15641551 }
15651552 else throw("Strict value is not equal to itself.")
15661553 }
15671554 }
15681555 }
15691556 else throw("Strict value is not equal to itself.")
15701557 }
15711558 else throw("Strict value is not equal to itself.")
15721559 }
15731560
15741561
15751562
15761563 @Callable(i)
15771564 func liquidate (_trader) = {
15781565 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
15791566 if ((sync == sync))
15801567 then {
15811568 let spotMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
15821569 let liquidationMarginRatio = if (isOverFluctuationLimit())
15831570 then {
15841571 let oracleMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_ORACLE)
15851572 vmax(spotMarginRatio, oracleMarginRatio)
15861573 }
15871574 else spotMarginRatio
15881575 if (if (if (if (if (!(requireMoreMarginRatio(liquidationMarginRatio, maintenanceMarginRatio(), false)))
15891576 then true
15901577 else !(requireOpenPosition(_trader)))
15911578 then true
15921579 else !(initialized()))
15931580 then true
15941581 else paused())
15951582 then true
15961583 else isMarketClosed())
15971584 then throw("Unable to liquidate")
15981585 else {
15991586 let isPartialLiquidation = if (if ((spotMarginRatio > liquidationFeeRatio()))
1600- then true
1601- else (partialLiquidationRatio() > 0))
1602- then true
1603- else (DECIMAL_UNIT > partialLiquidationRatio())
1587+ then (partialLiquidationRatio() > 0)
1588+ else false)
1589+ then (DECIMAL_UNIT > partialLiquidationRatio())
1590+ else false
16041591 let oldPositionSize = getPosition(_trader)._1
16051592 let positionSizeAbs = abs(oldPositionSize)
1606- let $t07238672709 = if (isPartialLiquidation)
1593+ let $t07207772400 = if (isPartialLiquidation)
16071594 then {
16081595 let liquidationSize = getPartialLiquidationAmount(_trader, oldPositionSize)
16091596 let liquidationRatio = divd(abs(liquidationSize), positionSizeAbs)
16101597 $Tuple2(liquidationRatio, abs(liquidationSize))
16111598 }
16121599 else $Tuple2(0, positionSizeAbs)
1613- let liquidationRatio = $t07238672709._1
1614- let liquidationSize = $t07238672709._2
1615- let $t07271573341 = internalClosePosition(_trader, if (isPartialLiquidation)
1600+ let liquidationRatio = $t07207772400._1
1601+ let liquidationSize = $t07207772400._2
1602+ let $t07240673044 = internalClosePosition(_trader, if (isPartialLiquidation)
16161603 then liquidationSize
1617- else positionSizeAbs, liquidationFeeRatio(), 0, true, false)
1618- let newPositionSize = $t07271573341._1
1619- let newPositionMargin = $t07271573341._2
1620- let newPositionOpenNotional = $t07271573341._3
1621- let newPositionLstUpdCPF = $t07271573341._4
1622- let positionBadDebt = $t07271573341._5
1623- let realizedPnl = $t07271573341._6
1624- let marginToTrader = $t07271573341._7
1625- let quoteAssetReserveAfter = $t07271573341._8
1626- let baseAssetReserveAfter = $t07271573341._9
1627- let totalPositionSizeAfter = $t07271573341._10
1628- let openInterestNotionalAfter = $t07271573341._11
1629- let totalLongAfter = $t07271573341._12
1630- let totalShortAfter = $t07271573341._13
1631- let totalLongOpenInterestAfter = $t07271573341._14
1632- let totalShortOpenInterestAfter = $t07271573341._15
1633- let liquidationPenalty = $t07271573341._16
1604+ 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
16341621 let feeToLiquidator = (liquidationPenalty / 2)
16351622 let feeToVault = (liquidationPenalty - feeToLiquidator)
16361623 let ammBalance = (cbalance() - liquidationPenalty)
16371624 let newAmmBalance = if ((0 > ammBalance))
16381625 then 0
16391626 else ammBalance
16401627 let lockBadDebt = if ((positionBadDebt > 0))
16411628 then {
1642- let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [positionBadDebt], nil)
1629+ let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [(positionBadDebt + liquidationPenalty)], nil)
16431630 if ((lockBadDebt == lockBadDebt))
16441631 then nil
16451632 else throw("Strict value is not equal to itself.")
16461633 }
16471634 else nil
16481635 if ((lockBadDebt == lockBadDebt))
16491636 then {
16501637 let unstake = invoke(vaultAddress(), "withdrawLocked", [liquidationPenalty], nil)
16511638 if ((unstake == unstake))
16521639 then {
16531640 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
16541641 if ((depositInsurance == depositInsurance))
16551642 then {
16561643 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
16571644 if ((notifyNotional == notifyNotional))
16581645 then ((((if (isPartialLiquidation)
16591646 then updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, lastTimestamp())
16601647 else deletePosition(_trader)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ withdraw(i.caller, feeToLiquidator)) ++ updateBalance(newAmmBalance))
16611648 else throw("Strict value is not equal to itself.")
16621649 }
16631650 else throw("Strict value is not equal to itself.")
16641651 }
16651652 else throw("Strict value is not equal to itself.")
16661653 }
16671654 else throw("Strict value is not equal to itself.")
16681655 }
16691656 }
16701657 else throw("Strict value is not equal to itself.")
16711658 }
16721659
16731660
16741661
16751662 @Callable(i)
16761663 func payFunding () = {
16771664 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
16781665 if ((sync == sync))
16791666 then {
16801667 let fundingBlockTimestamp = nextFundingBlockTimestamp()
16811668 if (if (if ((fundingBlockTimestamp > lastTimestamp()))
16821669 then true
16831670 else !(initialized()))
16841671 then true
16851672 else paused())
16861673 then throw(((("Invalid funding block timestamp: " + toString(lastTimestamp())) + " < ") + toString(fundingBlockTimestamp)))
16871674 else {
16881675 let underlyingPrice = getOraclePrice()
1689- let $t07530775369 = getFunding()
1690- let shortPremiumFraction = $t07530775369._1
1691- let longPremiumFraction = $t07530775369._2
1676+ let $t07503175093 = getFunding()
1677+ let shortPremiumFraction = $t07503175093._1
1678+ let longPremiumFraction = $t07503175093._2
16921679 updateFunding((fundingBlockTimestamp + fundingPeriodSeconds()), (latestLongCumulativePremiumFraction() + longPremiumFraction), (latestShortCumulativePremiumFraction() + shortPremiumFraction), divd(longPremiumFraction, underlyingPrice), divd(shortPremiumFraction, underlyingPrice))
16931680 }
16941681 }
16951682 else throw("Strict value is not equal to itself.")
16961683 }
16971684
16981685
16991686
17001687 @Callable(i)
17011688 func syncTerminalPriceToOracle () = {
17021689 let _qtAstR = qtAstR()
17031690 let _bsAstR = bsAstR()
1704- let $t07580175936 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1705- let newQuoteAssetWeight = $t07580175936._1
1706- let newBaseAssetWeight = $t07580175936._2
1707- let marginToVault = $t07580175936._3
1708- let doExchangePnL = if ((marginToVault != 0))
1691+ let $t07552575891 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1692+ let newQuoteAssetWeight = $t07552575891._1
1693+ let newBaseAssetWeight = $t07552575891._2
1694+ let marginToVault = $t07552575891._3
1695+ let marginToVaultAdj = if (if ((0 > marginToVault))
1696+ then (abs(marginToVault) > cbalance())
1697+ else false)
1698+ then -(cbalance())
1699+ else marginToVault
1700+ let doExchangePnL = if ((marginToVaultAdj != 0))
17091701 then {
1710- let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
1702+ let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVaultAdj], nil)
17111703 if ((doExchangePnL == doExchangePnL))
17121704 then nil
17131705 else throw("Strict value is not equal to itself.")
17141706 }
17151707 else nil
17161708 if ((doExchangePnL == doExchangePnL))
1717- then ((updateBalance((cbalance() + marginToVault)) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight)) ++ appendTwap(divd(muld(_qtAstR, newQuoteAssetWeight), muld(_bsAstR, newBaseAssetWeight))))
1709+ then ((updateBalance((cbalance() + marginToVaultAdj)) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight)) ++ appendTwap(divd(muld(_qtAstR, newQuoteAssetWeight), muld(_bsAstR, newBaseAssetWeight))))
17181710 else throw("Strict value is not equal to itself.")
17191711 }
17201712
17211713
17221714
17231715 @Callable(i)
17241716 func ensureCalledOnce () = if ((i.caller != this))
17251717 then throw("Invalid saveCurrentTxId parameters")
17261718 else {
17271719 let lastTx = valueOrElse(getString(this, k_lastTx), "")
17281720 if ((lastTx != toBase58String(i.transactionId)))
17291721 then [StringEntry(k_lastTx, lastTx)]
17301722 else throw("Can not call vAMM methods twice in one tx")
17311723 }
17321724
17331725
17341726
17351727 @Callable(i)
17361728 func view_calcRemainMarginWithFundingPayment (_trader) = {
17371729 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
17381730 if ((sync == sync))
17391731 then {
1740- let $t07694177065 = getPosition(_trader)
1741- let positionSize = $t07694177065._1
1742- let positionMargin = $t07694177065._2
1743- let pon = $t07694177065._3
1744- let positionLstUpdCPF = $t07694177065._4
1745- let positionTimestamp = $t07694177065._5
1746- let $t07706877169 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1747- let positionNotional = $t07706877169._1
1748- let unrealizedPnl = $t07706877169._2
1749- let $t07717277396 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLstUpdCPF, positionTimestamp, unrealizedPnl)
1750- let remainMargin = $t07717277396._1
1751- let badDebt = $t07717277396._2
1752- let fundingPayment = $t07717277396._3
1753- let rolloverFee = $t07717277396._4
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
17541746 throw(((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)) + s(rolloverFee)))
17551747 }
17561748 else throw("Strict value is not equal to itself.")
17571749 }
17581750
17591751
17601752
17611753 @Callable(i)
17621754 func view_getPegAdjustCost (_price) = {
17631755 let _qtAstR = qtAstR()
17641756 let _bsAstR = bsAstR()
17651757 let result = getSyncTerminalPrice(_price, _qtAstR, _bsAstR)
17661758 throw(toString(result._3))
17671759 }
17681760
17691761
17701762
17711763 @Callable(i)
17721764 func view_getTerminalAmmPrice () = {
1773- let $t07783277913 = getTerminalAmmState()
1774- let terminalQuoteAssetReserve = $t07783277913._1
1775- let terminalBaseAssetReserve = $t07783277913._2
1765+ let $t07794178022 = getTerminalAmmState()
1766+ let terminalQuoteAssetReserve = $t07794178022._1
1767+ let terminalBaseAssetReserve = $t07794178022._2
17761768 let price = divd(muld(terminalQuoteAssetReserve, qtAstW()), muld(terminalBaseAssetReserve, bsAstW()))
17771769 throw(toString(price))
17781770 }
17791771
17801772
17811773
17821774 @Callable(i)
17831775 func view_getFunding () = {
17841776 let underlyingPrice = getOraclePrice()
1785- let $t07812878190 = getFunding()
1786- let shortPremiumFraction = $t07812878190._1
1787- let longPremiumFraction = $t07812878190._2
1777+ let $t07823778299 = getFunding()
1778+ let shortPremiumFraction = $t07823778299._1
1779+ let longPremiumFraction = $t07823778299._2
17881780 let longFunding = divd(longPremiumFraction, underlyingPrice)
17891781 let shortFunding = divd(shortPremiumFraction, underlyingPrice)
17901782 throw((((s(longFunding) + s(shortFunding)) + s(getTwapSpotPrice())) + s(getOraclePrice())))
17911783 }
17921784
17931785
17941786
17951787 @Callable(i)
17961788 func computeSpotPrice () = {
17971789 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
17981790 if ((sync == sync))
17991791 then {
18001792 let result = getSpotPrice()
18011793 $Tuple2(nil, result)
18021794 }
18031795 else throw("Strict value is not equal to itself.")
18041796 }
18051797
18061798
18071799
18081800 @Callable(i)
18091801 func computeFeeForTraderWithArtifact (_trader,_artifactId) = {
18101802 let result = getForTraderWithArtifact(_trader, _artifactId)
18111803 $Tuple2(nil, result)
18121804 }
18131805
18141806
18151807 @Verifier(tx)
1816-func verify () = sigVerify(tx.bodyBytes, tx.proofs[0], adminPublicKey())
1808+func verify () = {
1809+ let coordinatorStr = getString(this, k_coordinatorAddress)
1810+ if (isDefined(coordinatorStr))
1811+ then {
1812+ let admin = getString(addressFromStringValue(value(coordinatorStr)), k_admin_address)
1813+ if (isDefined(admin))
1814+ then valueOrElse(getBoolean(addressFromStringValue(value(admin)), ((("status_" + toString(this)) + "_") + toBase58String(tx.id))), false)
1815+ else throw("unable to verify: admin not set in coordinator")
1816+ }
1817+ else sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
1818+ }
18171819

github/deemru/w8io/169f3d6 
307.52 ms