tx · HeGCV1eDjNHk3XcpZYYzYJNjDwzePLTBBb4FpFxdra4a

3Mpd4hwQJJqyvqeE3ukACWYuUonjAQcmQxo:  -0.08000000 Waves

2023.05.15 20:46 [2579401] smart account 3Mpd4hwQJJqyvqeE3ukACWYuUonjAQcmQxo > SELF 0.00000000 Waves

{ "type": 13, "id": "HeGCV1eDjNHk3XcpZYYzYJNjDwzePLTBBb4FpFxdra4a", "fee": 8000000, "feeAssetId": null, "timestamp": 1684172804908, "version": 2, "chainId": 84, "sender": "3Mpd4hwQJJqyvqeE3ukACWYuUonjAQcmQxo", "senderPublicKey": "HjuaYzrXzh6phGZx1AmjeuZNPCQjDSGQgpwcNAH48Fv7", "proofs": [ "KPx2XfQzbH7Bnex6rSM8iRU9NcwFWpYGT1ECjb5JUBxu9PgnGPGm84jCTkDNefSn9e94omwnWmLNk1fNk6qLxNy" ], "script": "base64:BgJyCAISABIAEgASABIDCgEBEgMKAQESDwoNAQEBAQEBAQEBAQEBARIUChIBAQEBAQEBCAgIAQEBAQEBAQESBgoEAQEBCBIAEgMKAQESBQoDAQEEEgMKAQgSABIAEgASAwoBCBIDCgEBEgASABIAEgQKAggIwAEADGtfYmFzZU9yYWNsZQIMa19iYXNlT3JhY2xlAA1rX3F1b3RlT3JhY2xlAg1rX3F1b3RlT3JhY2xlAAlrX2JhbGFuY2UCCWtfYmFsYW5jZQAKa19zZXF1ZW5jZQIKa19zZXF1ZW5jZQAOa19wb3NpdGlvblNpemUCDmtfcG9zaXRpb25TaXplABBrX3Bvc2l0aW9uTWFyZ2luAhBrX3Bvc2l0aW9uTWFyZ2luABZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsAhZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsAC5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAhJrX3Bvc2l0aW9uRnJhY3Rpb24AEmtfcG9zaXRpb25TZXF1ZW5jZQISa19wb3NpdGlvblNlcXVlbmNlAA9rX3Bvc2l0aW9uQXNzZXQCD2tfcG9zaXRpb25Bc3NldAANa19wb3NpdGlvbkZlZQINa19wb3NpdGlvbkZlZQAea19wb3NpdGlvbkxhc3RVcGRhdGVkVGltZXN0YW1wAhNrX3Bvc2l0aW9uVGltZXN0YW1wAA1rX2luaXRpYWxpemVkAg1rX2luaXRpYWxpemVkAAhrX3BhdXNlZAIIa19wYXVzZWQAC2tfY2xvc2VPbmx5AgtrX2Nsb3NlT25seQAFa19mZWUCBWtfZmVlAA1rX3JvbGxvdmVyRmVlAg5rX3JvbGxvdmVyX2ZlZQAPa19mdW5kaW5nUGVyaW9kAg9rX2Z1bmRpbmdQZXJpb2QAEWtfaW5pdE1hcmdpblJhdGlvAhFrX2luaXRNYXJnaW5SYXRpbwAYa19tYWludGVuYW5jZU1hcmdpblJhdGlvAgVrX21tcgAVa19saXF1aWRhdGlvbkZlZVJhdGlvAhVrX2xpcXVpZGF0aW9uRmVlUmF0aW8AGWtfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8CFmtfcGFydExpcXVpZGF0aW9uUmF0aW8ADWtfc3ByZWFkTGltaXQCDWtfc3ByZWFkTGltaXQAEGtfbWF4UHJpY2VJbXBhY3QCEGtfbWF4UHJpY2VJbXBhY3QAEGtfbWF4UHJpY2VTcHJlYWQCEGtfbWF4UHJpY2VTcHJlYWQAEWtfbWF4T3Blbk5vdGlvbmFsAhFrX21heE9wZW5Ob3Rpb25hbAAVa19mZWVUb1N0YWtlcnNQZXJjZW50AhVrX2ZlZVRvU3Rha2Vyc1BlcmNlbnQAEGtfbWF4T3JhY2xlRGVsYXkCEGtfbWF4T3JhY2xlRGVsYXkADWtfZnVuZGluZ01vZGUCDWtfZnVuZGluZ01vZGUADWtfbGFzdERhdGFTdHICDWtfbGFzdERhdGFTdHIADmtfbGFzdE1pbnV0ZUlkAg5rX2xhc3RNaW51dGVJZAAda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UCHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlABNrX3R3YXBEYXRhTGFzdFByaWNlAhNrX3R3YXBEYXRhTGFzdFByaWNlABprX3R3YXBEYXRhUHJldmlvdXNNaW51dGVJZAIaa190d2FwRGF0YVByZXZpb3VzTWludXRlSWQAJWtfbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24CG2tfbGF0ZXN0TG9uZ1ByZW1pdW1GcmFjdGlvbgAma19sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24CHGtfbGF0ZXN0U2hvcnRQcmVtaXVtRnJhY3Rpb24AEmtfbmV4dEZ1bmRpbmdCbG9jawIea19uZXh0RnVuZGluZ0Jsb2NrTWluVGltZXN0YW1wABFrX2xvbmdGdW5kaW5nUmF0ZQIRa19sb25nRnVuZGluZ1JhdGUAEmtfc2hvcnRGdW5kaW5nUmF0ZQISa19zaG9ydEZ1bmRpbmdSYXRlABNrX3F1b3RlQXNzZXRSZXNlcnZlAghrX3F0QXN0UgASa19iYXNlQXNzZXRSZXNlcnZlAghrX2JzQXN0UgASa19xdW90ZUFzc2V0V2VpZ2h0AghrX3F0QXN0VwARa19iYXNlQXNzZXRXZWlnaHQCCGtfYnNBc3RXABNrX3RvdGFsUG9zaXRpb25TaXplAhNrX3RvdGFsUG9zaXRpb25TaXplABdrX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQIXa190b3RhbExvbmdQb3NpdGlvblNpemUAGGtfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQIYa190b3RhbFNob3J0UG9zaXRpb25TaXplABZrX29wZW5JbnRlcmVzdE5vdGlvbmFsAhZrX29wZW5JbnRlcmVzdE5vdGlvbmFsABNrX29wZW5JbnRlcmVzdFNob3J0AhNrX29wZW5JbnRlcmVzdFNob3J0ABJrX29wZW5JbnRlcmVzdExvbmcCEmtfb3BlbkludGVyZXN0TG9uZwAIa19sYXN0VHgCCGtfbGFzdFR4ABRrX2Nvb3JkaW5hdG9yQWRkcmVzcwIUa19jb29yZGluYXRvckFkZHJlc3MAD2tfdmF1bHRfYWRkcmVzcwIPa192YXVsdF9hZGRyZXNzAA9rX2FkbWluX2FkZHJlc3MCD2tfYWRtaW5fYWRkcmVzcwANa19xdW90ZV9hc3NldAINa19xdW90ZV9hc3NldAAPa19xdW90ZV9zdGFraW5nAg9rX3F1b3RlX3N0YWtpbmcAEWtfc3Rha2luZ19hZGRyZXNzAhFrX3N0YWtpbmdfYWRkcmVzcwAPa19taW5lcl9hZGRyZXNzAg9rX21pbmVyX2FkZHJlc3MAEGtfb3JkZXJzX2FkZHJlc3MCEGtfb3JkZXJzX2FkZHJlc3MAEmtfcmVmZXJyYWxfYWRkcmVzcwISa19yZWZlcnJhbF9hZGRyZXNzABJrX2V4Y2hhbmdlX2FkZHJlc3MCEmtfZXhjaGFuZ2VfYWRkcmVzcwAVa19uZnRfbWFuYWdlcl9hZGRyZXNzAhVrX25mdF9tYW5hZ2VyX2FkZHJlc3MBDnRvQ29tcG9zaXRlS2V5AgRfa2V5CF9hZGRyZXNzCQCsAgIJAKwCAgUEX2tleQIBXwUIX2FkZHJlc3MBC2Nvb3JkaW5hdG9yAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIFBHRoaXMFFGtfY29vcmRpbmF0b3JBZGRyZXNzAhNDb29yZGluYXRvciBub3Qgc2V0AQxhZG1pbkFkZHJlc3MACQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFD2tfYWRtaW5fYWRkcmVzcwEKcXVvdGVBc3NldAAJANkEAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUNa19xdW90ZV9hc3NldAERcXVvdGVBc3NldFN0YWtpbmcACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUPa19xdW90ZV9zdGFraW5nAhtRdW90ZSBhc3NldCBzdGFraW5nIG5vdCBzZXQBDnN0YWtpbmdBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFEWtfc3Rha2luZ19hZGRyZXNzAg9TdGFraW5nIG5vdCBzZXQBDHZhdWx0QWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABQ9rX3ZhdWx0X2FkZHJlc3MCDVZhdWx0IG5vdCBzZXQBDG1pbmVyQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABQ9rX21pbmVyX2FkZHJlc3MCDU1pbmVyIG5vdCBzZXQBDW9yZGVyc0FkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUQa19vcmRlcnNfYWRkcmVzcwIOT3JkZXJzIG5vdCBzZXQBD3JlZmVycmFsQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABRJrX3JlZmVycmFsX2FkZHJlc3MCEFJlZmVycmFsIG5vdCBzZXQBEW5mdE1hbmFnZXJBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFFWtfbmZ0X21hbmFnZXJfYWRkcmVzcwITTkZUIE1hbmFnZXIgbm90IHNldAANa190b2tlbl9wYXJhbQINa190b2tlbl9wYXJhbQAMa190b2tlbl90eXBlAgxrX3Rva2VuX3R5cGUAGEZFRV9SRURVQ1RJT05fVE9LRU5fVFlQRQINZmVlX3JlZHVjdGlvbgAIRElSX0xPTkcAAQAJRElSX1NIT1JUAAIADVRXQVBfSU5URVJWQUwADwAHU0VDT05EUwDoBwAPREVDSU1BTF9OVU1CRVJTAAYADERFQ0lNQUxfVU5JVAkAaAIAAQkAaAIJAGgCCQBoAgkAaAIJAGgCAAoACgAKAAoACgAKAA9NSU5VVEVTX0lOX1lFQVIJAGgCAKCKIAUMREVDSU1BTF9VTklUAAdPTkVfREFZCQBoAgCAowUFDERFQ0lNQUxfVU5JVAAPUE5MX09QVElPTl9TUE9UAAEAEVBOTF9PUFRJT05fT1JBQ0xFAAIBAXMBAl94CQCsAgIJAKQDAQUCX3gCASwBBGRpdmQCAl94Al95CQBuBAUCX3gFDERFQ0lNQUxfVU5JVAUCX3kFCEhBTEZFVkVOAQRtdWxkAgJfeAJfeQkAbgQFAl94BQJfeQUMREVDSU1BTF9VTklUBQhIQUxGRVZFTgEFYmRpdmQCAl94Al95CQC9AgQFAl94CQC2AgEFDERFQ0lNQUxfVU5JVAUCX3kFCEhBTEZFVkVOAQVibXVsZAICX3gCX3kJAL0CBAUCX3gFAl95CQC2AgEFDERFQ0lNQUxfVU5JVAUISEFMRkVWRU4BA2FicwECX3gDCQBmAgUCX3gAAAUCX3gJAQEtAQUCX3gBBHZtYXgCAl94Al95AwkAZwIFAl94BQJfeQUCX3gFAl95AQlsaXN0VG9TdHIBBV9saXN0AwkAAAIJAJADAQUFX2xpc3QAAAIACQC5CQIFBV9saXN0AgEsAQlzdHJUb0xpc3QBBF9zdHIDCQAAAgUEX3N0cgIABQNuaWwJALUJAgUEX3N0cgIBLAELcHVzaFRvUXVldWUDBV9saXN0CF9tYXhTaXplBl92YWx1ZQMJAGYCCQCQAwEFBV9saXN0BQhfbWF4U2l6ZQkAzQgCCQDRCAIFBV9saXN0AAAFBl92YWx1ZQkAzQgCBQVfbGlzdAUGX3ZhbHVlAQNpbnQBAWsJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQR0aGlzBQFrCQCsAgICDW5vIHZhbHVlIGZvciAFAWsBBWludE9yAgFrA2RlZgkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQFrBQNkZWYBBHN0ckECCF9hZGRyZXNzBF9rZXkEA3ZhbAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFCF9hZGRyZXNzBQRfa2V5CQCsAgICEU5vIHZhbHVlIGZvciBrZXkgBQRfa2V5BQN2YWwBBGludEECCF9hZGRyZXNzBF9rZXkEA3ZhbAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFCF9hZGRyZXNzBQRfa2V5CQCsAgICEU5vIHZhbHVlIGZvciBrZXkgBQRfa2V5BQN2YWwAEkZVTkRJTkdfQVNZTU1FVFJJQwABABFGVU5ESU5HX1NZTU1FVFJJQwACAQhjYmFsYW5jZQAJAQNpbnQBBQlrX2JhbGFuY2UBA2ZlZQAJAQNpbnQBBQVrX2ZlZQEPcm9sbG92ZXJGZWVSYXRlAAkBA2ludAEFDWtfcm9sbG92ZXJGZWUBD2luaXRNYXJnaW5SYXRpbwAJAQNpbnQBBRFrX2luaXRNYXJnaW5SYXRpbwEGcXRBc3RSAAkBA2ludAEFE2tfcXVvdGVBc3NldFJlc2VydmUBBmJzQXN0UgAJAQNpbnQBBRJrX2Jhc2VBc3NldFJlc2VydmUBBnF0QXN0VwAJAQVpbnRPcgIFEmtfcXVvdGVBc3NldFdlaWdodAUMREVDSU1BTF9VTklUAQZic0FzdFcACQEFaW50T3ICBRFrX2Jhc2VBc3NldFdlaWdodAUMREVDSU1BTF9VTklUARF0b3RhbFBvc2l0aW9uU2l6ZQAJAQNpbnQBBRNrX3RvdGFsUG9zaXRpb25TaXplARRvcGVuSW50ZXJlc3ROb3Rpb25hbAAJAQNpbnQBBRZrX29wZW5JbnRlcmVzdE5vdGlvbmFsARFvcGVuSW50ZXJlc3RTaG9ydAAJAQNpbnQBBRNrX29wZW5JbnRlcmVzdFNob3J0ARBvcGVuSW50ZXJlc3RMb25nAAkBA2ludAEFEmtfb3BlbkludGVyZXN0TG9uZwEZbmV4dEZ1bmRpbmdCbG9ja1RpbWVzdGFtcAAJAQNpbnQBBRJrX25leHRGdW5kaW5nQmxvY2sBEGZ1bmRpbmdQZXJpb2RSYXcACQEDaW50AQUPa19mdW5kaW5nUGVyaW9kARRmdW5kaW5nUGVyaW9kRGVjaW1hbAAJAGgCCQEQZnVuZGluZ1BlcmlvZFJhdwAFDERFQ0lNQUxfVU5JVAEUZnVuZGluZ1BlcmlvZFNlY29uZHMACQBoAgkBEGZ1bmRpbmdQZXJpb2RSYXcABQdTRUNPTkRTARZtYWludGVuYW5jZU1hcmdpblJhdGlvAAkBA2ludAEFGGtfbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwETbGlxdWlkYXRpb25GZWVSYXRpbwAJAQNpbnQBBRVrX2xpcXVpZGF0aW9uRmVlUmF0aW8BF3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAAkBA2ludAEFGWtfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8BC3NwcmVhZExpbWl0AAkBA2ludAEFDWtfc3ByZWFkTGltaXQBDm1heFByaWNlSW1wYWN0AAkBA2ludAEFEGtfbWF4UHJpY2VJbXBhY3QBDm1heFByaWNlU3ByZWFkAAkBA2ludAEFEGtfbWF4UHJpY2VTcHJlYWQBD21heE9wZW5Ob3Rpb25hbAAJAQNpbnQBBRFrX21heE9wZW5Ob3Rpb25hbAEjbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24ACQEDaW50AQUla19sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEkbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAkBA2ludAEFJmtfbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAkBA2ludAEFGGtfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQEVdG90YWxMb25nUG9zaXRpb25TaXplAAkBA2ludAEFF2tfdG90YWxMb25nUG9zaXRpb25TaXplAQxsYXN0U2VxdWVuY2UACQEFaW50T3ICBQprX3NlcXVlbmNlAAABE2ZlZVRvU3Rha2Vyc1BlcmNlbnQACQEDaW50AQUVa19mZWVUb1N0YWtlcnNQZXJjZW50AQ5tYXhPcmFjbGVEZWxheQAJAQNpbnQBBRBrX21heE9yYWNsZURlbGF5AQtmdW5kaW5nTW9kZQAJAQVpbnRPcgIFDWtfZnVuZGluZ01vZGUFEkZVTkRJTkdfQVNZTU1FVFJJQwENbGFzdFRpbWVzdGFtcAAIBQlsYXN0QmxvY2sJdGltZXN0YW1wAQ9nZXRBY3R1YWxDYWxsZXIBAWkJAQt2YWx1ZU9yRWxzZQIJAJ0IAgkBDW9yZGVyc0FkZHJlc3MAAghrX3NlbmRlcgkApQgBCAUBaQZjYWxsZXIBFnJlcXVpcmVNb3JlTWFyZ2luUmF0aW8DDF9tYXJnaW5SYXRpbxBfYmFzZU1hcmdpblJhdGlvFF9sYXJnZXJUaGFuT3JFcXVhbFRvBBRyZW1haW5pbmdNYXJnaW5SYXRpbwkAZQIFDF9tYXJnaW5SYXRpbwUQX2Jhc2VNYXJnaW5SYXRpbwMDBRRfbGFyZ2VyVGhhbk9yRXF1YWxUbwkAZgIAAAUUcmVtYWluaW5nTWFyZ2luUmF0aW8HCQACAQkArAICCQCsAgIJAKwCAgIQSW52YWxpZCBtYXJnaW46IAkApAMBBQxfbWFyZ2luUmF0aW8CAyA8IAkApAMBBRBfYmFzZU1hcmdpblJhdGlvAwMJAQEhAQUUX2xhcmdlclRoYW5PckVxdWFsVG8JAGcCBRRyZW1haW5pbmdNYXJnaW5SYXRpbwAABwkAAgEJAKwCAgkArAICCQCsAgICEEludmFsaWQgbWFyZ2luOiAJAKQDAQUMX21hcmdpblJhdGlvAgMgPiAJAKQDAQUQX2Jhc2VNYXJnaW5SYXRpbwYBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BDV9wb3NpdGlvblNpemUDCQAAAgUNX3Bvc2l0aW9uU2l6ZQAACQACAQIsU2hvdWxkIG5vdCBiZSBjYWxsZWQgd2l0aCBfcG9zaXRpb25TaXplID09IDADCQBmAgUNX3Bvc2l0aW9uU2l6ZQAACQEjbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24ACQEkbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAELZ2V0UG9zaXRpb24BB190cmFkZXIED3Bvc2l0aW9uU2l6ZU9wdAkAmggCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBQ5rX3Bvc2l0aW9uU2l6ZQUHX3RyYWRlcgQHJG1hdGNoMAUPcG9zaXRpb25TaXplT3B0AwkAAQIFByRtYXRjaDACA0ludAQMcG9zaXRpb25TaXplBQckbWF0Y2gwCQCXCgUFDHBvc2l0aW9uU2l6ZQkBEUBleHRyTmF0aXZlKDEwNTApAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUQa19wb3NpdGlvbk1hcmdpbgUHX3RyYWRlcgkBEUBleHRyTmF0aXZlKDEwNTApAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUWa19wb3NpdGlvbk9wZW5Ob3Rpb25hbAUHX3RyYWRlcgkBEUBleHRyTmF0aXZlKDEwNTApAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUua19wb3NpdGlvbkxhc3RVcGRhdGVkQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUHX3RyYWRlcgkBEUBleHRyTmF0aXZlKDEwNTApAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUea19wb3NpdGlvbkxhc3RVcGRhdGVkVGltZXN0YW1wBQdfdHJhZGVyCQCXCgUAAAAAAAAAAAAAARBnZXRQb3NpdGlvbkFzc2V0AQdfdHJhZGVyBBBwb3NpdGlvbkFzc2V0T3B0CQCdCAIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFD2tfcG9zaXRpb25Bc3NldAUHX3RyYWRlcgQHJG1hdGNoMAUQcG9zaXRpb25Bc3NldE9wdAMJAAECBQckbWF0Y2gwAgZTdHJpbmcEDXBvc2l0aW9uQXNzZXQFByRtYXRjaDAFDXBvc2l0aW9uQXNzZXQJANgEAQkBCnF1b3RlQXNzZXQAAQ5nZXRQb3NpdGlvbkZlZQEHX3RyYWRlcgQOcG9zaXRpb25GZWVPcHQJAJoIAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUNa19wb3NpdGlvbkZlZQUHX3RyYWRlcgQHJG1hdGNoMAUOcG9zaXRpb25GZWVPcHQDCQABAgUHJG1hdGNoMAIDSW50BAtwb3NpdGlvbkZlZQUHJG1hdGNoMAULcG9zaXRpb25GZWUJAQNmZWUAARNyZXF1aXJlT3BlblBvc2l0aW9uAQdfdHJhZGVyAwkAAAIICQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyAl8xAAAJAAIBAhBObyBvcGVuIHBvc2l0aW9uBgENZ2V0T3JhY2xlRGF0YQEDa2V5BA1vcmFjbGVEYXRhU3RyCQCdCAIFBHRoaXMFA2tleQMDCQEJaXNEZWZpbmVkAQUNb3JhY2xlRGF0YVN0cgkBAiE9AgkBBXZhbHVlAQUNb3JhY2xlRGF0YVN0cgIABwQKb3JhY2xlRGF0YQkAtQkCCQEFdmFsdWUBBQ1vcmFjbGVEYXRhU3RyAgEsBA1vcmFjbGVBZGRyZXNzCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkAkQMCBQpvcmFjbGVEYXRhAAAJAKwCAgIbSW52YWxpZCBvcmFjbGUgYWRkcmVzcyBpbjogCQEFdmFsdWUBBQ1vcmFjbGVEYXRhU3RyBAhwcmljZUtleQkAkQMCBQpvcmFjbGVEYXRhAAEECGJsb2NrS2V5CQCRAwIFCm9yYWNsZURhdGEAAgQHb3BlbktleQkAkQMCBQpvcmFjbGVEYXRhAAMJAJYKBAUNb3JhY2xlQWRkcmVzcwUIcHJpY2VLZXkFCGJsb2NrS2V5BQdvcGVuS2V5BQR1bml0AQtpbml0aWFsaXplZAAJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhpcwUNa19pbml0aWFsaXplZAcBBnBhdXNlZAAJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhpcwUIa19wYXVzZWQHAQljbG9zZU9ubHkACQELdmFsdWVPckVsc2UCCQCbCAIFBHRoaXMFC2tfY2xvc2VPbmx5BwENdXBkYXRlUmVzZXJ2ZQMGX2lzQWRkEV9xdW90ZUFzc2V0QW1vdW50EF9iYXNlQXNzZXRBbW91bnQDBQZfaXNBZGQEB25ld0Jhc2UJAGUCCQEGYnNBc3RSAAUQX2Jhc2VBc3NldEFtb3VudAMJAGcCAAAFB25ld0Jhc2UJAAIBAipUeCBsZWFkIHRvIGJhc2UgYXNzZXQgcmVzZXJ2ZSA8PSAwLCByZXZlcnQJAJUKAwkAZAIJAQZxdEFzdFIABRFfcXVvdGVBc3NldEFtb3VudAUHbmV3QmFzZQkAZAIJARF0b3RhbFBvc2l0aW9uU2l6ZQAFEF9iYXNlQXNzZXRBbW91bnQECG5ld1F1b3RlCQBlAgkBBnF0QXN0UgAFEV9xdW90ZUFzc2V0QW1vdW50AwkAZwIAAAUIbmV3UXVvdGUJAAIBAipUeCBsZWFkIHRvIGJhc2UgcXVvdGUgcmVzZXJ2ZSA8PSAwLCByZXZlcnQJAJUKAwUIbmV3UXVvdGUJAGQCCQEGYnNBc3RSAAUQX2Jhc2VBc3NldEFtb3VudAkAZQIJARF0b3RhbFBvc2l0aW9uU2l6ZQAFEF9iYXNlQXNzZXRBbW91bnQBDWNhbGNJbnZhcmlhbnQCB19xdEFzdFIHX2JzQXN0UgQHYnF0QXN0UgkAtgIBBQdfcXRBc3RSBAdiYnNBc3RSCQC2AgEFB19ic0FzdFIJAQVibXVsZAIFB2JxdEFzdFIFB2Jic0FzdFIBCXN3YXBJbnB1dAIGX2lzQWRkEV9xdW90ZUFzc2V0QW1vdW50BAdfcXRBc3RSCQEGcXRBc3RSAAQHX2JzQXN0UgkBBmJzQXN0UgAEB19xdEFzdFcJAQZxdEFzdFcABAdfYnNBc3RXCQEGYnNBc3RXAAQYcXVvdGVBc3NldEFtb3VudEFkanVzdGVkCQEEZGl2ZAIFEV9xdW90ZUFzc2V0QW1vdW50BQdfcXRBc3RXBAFrCQENY2FsY0ludmFyaWFudAIFB19xdEFzdFIFB19ic0FzdFIEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIDBQZfaXNBZGQJAGQCBQdfcXRBc3RSBRhxdW90ZUFzc2V0QW1vdW50QWRqdXN0ZWQJAGUCBQdfcXRBc3RSBRhxdW90ZUFzc2V0QW1vdW50QWRqdXN0ZWQEFWJhc2VBc3NldFJlc2VydmVBZnRlcgkAoAMBCQEFYmRpdmQCBQFrCQC2AgEFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIEGGFtb3VudEJhc2VBc3NldEJvdWdodEFicwkBA2FicwEJAGUCBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFB19ic0FzdFIEFWFtb3VudEJhc2VBc3NldEJvdWdodAMFBl9pc0FkZAUYYW1vdW50QmFzZUFzc2V0Qm91Z2h0QWJzCQEBLQEFGGFtb3VudEJhc2VBc3NldEJvdWdodEFicwQNJHQwMTY4NzcxNzA0NwkBDXVwZGF0ZVJlc2VydmUDBQZfaXNBZGQFGHF1b3RlQXNzZXRBbW91bnRBZGp1c3RlZAUYYW1vdW50QmFzZUFzc2V0Qm91Z2h0QWJzBBdxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyMQgFDSR0MDE2ODc3MTcwNDcCXzEEFmJhc2VBc3NldFJlc2VydmVBZnRlcjEIBQ0kdDAxNjg3NzE3MDQ3Al8yBBd0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyMQgFDSR0MDE2ODc3MTcwNDcCXzMEC3ByaWNlQmVmb3JlCQEEZGl2ZAIJAQRtdWxkAgUHX3F0QXN0UgUHX3F0QXN0VwkBBG11bGQCBQdfYnNBc3RSBQdfYnNBc3RXBAttYXJrZXRQcmljZQkBBGRpdmQCBRFfcXVvdGVBc3NldEFtb3VudAUYYW1vdW50QmFzZUFzc2V0Qm91Z2h0QWJzBAlwcmljZURpZmYJAQNhYnMBCQBlAgULcHJpY2VCZWZvcmUFC21hcmtldFByaWNlBAtwcmljZUltcGFjdAkAZQIFDERFQ0lNQUxfVU5JVAkBBGRpdmQCBQtwcmljZUJlZm9yZQkAZAIFC3ByaWNlQmVmb3JlBQlwcmljZURpZmYEE21heFByaWNlSW1wYWN0VmFsdWUJAQ5tYXhQcmljZUltcGFjdAADCQBmAgULcHJpY2VJbXBhY3QFE21heFByaWNlSW1wYWN0VmFsdWUJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICDVByaWNlIGltcGFjdCAJAKQDAQULcHJpY2VJbXBhY3QCFCA+IG1heCBwcmljZSBpbXBhY3QgCQCkAwEFE21heFByaWNlSW1wYWN0VmFsdWUCFSBiZWZvcmUgcXVvdGUgYXNzZXQ6IAkApAMBBQdfcXRBc3RSAhQgYmVmb3JlIGJhc2UgYXNzZXQ6IAkApAMBBQdfYnNBc3RSAiEgcXVvdGUgYXNzZXQgYW1vdW50IHRvIGV4Y2hhbmdlOiAJAKQDAQURX3F1b3RlQXNzZXRBbW91bnQCDyBwcmljZSBiZWZvcmU6IAkApAMBBQtwcmljZUJlZm9yZQIOIG1hcmtldFByaWNlOiAJAKQDAQULbWFya2V0UHJpY2UJAJYKBAUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0BRdxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyMQUWYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyMQUXdG90YWxQb3NpdGlvblNpemVBZnRlcjEBD2NhbGNSb2xsb3ZlckZlZQISX29sZFBvc2l0aW9uTWFyZ2luIF9vbGRQb3NpdGlvbkxhc3RVcGRhdGVkVGltZXN0YW1wBA9wb3NpdGlvbk1pbnV0ZXMJAGgCCQBpAgkAaQIJAGUCCQENbGFzdFRpbWVzdGFtcAAFIF9vbGRQb3NpdGlvbkxhc3RVcGRhdGVkVGltZXN0YW1wAOgHADwFDERFQ0lNQUxfVU5JVAQLcm9sbG92ZXJGZWUJAQRkaXZkAgkBBG11bGQCCQEEbXVsZAIFEl9vbGRQb3NpdGlvbk1hcmdpbgUPcG9zaXRpb25NaW51dGVzCQEPcm9sbG92ZXJGZWVSYXRlAAUPTUlOVVRFU19JTl9ZRUFSBQtyb2xsb3ZlckZlZQEwY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudEFuZFJvbGxvdmVyRmVlBRBfb2xkUG9zaXRpb25TaXplEl9vbGRQb3NpdGlvbk1hcmdpbiVfb2xkUG9zaXRpb25DdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uIF9vbGRQb3NpdGlvbkxhc3RVcGRhdGVkVGltZXN0YW1wDF9tYXJnaW5EZWx0YQQOZnVuZGluZ1BheW1lbnQDCQECIT0CBRBfb2xkUG9zaXRpb25TaXplAAAEIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uCQEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEFEF9vbGRQb3NpdGlvblNpemUJAQRtdWxkAgkAZQIFIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBSVfb2xkUG9zaXRpb25DdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBRBfb2xkUG9zaXRpb25TaXplAAAEC3JvbGxvdmVyRmVlCQEPY2FsY1JvbGxvdmVyRmVlAgUSX29sZFBvc2l0aW9uTWFyZ2luBSBfb2xkUG9zaXRpb25MYXN0VXBkYXRlZFRpbWVzdGFtcAQMc2lnbmVkTWFyZ2luCQBkAgkAZQIJAGUCBQxfbWFyZ2luRGVsdGEFC3JvbGxvdmVyRmVlBQ5mdW5kaW5nUGF5bWVudAUSX29sZFBvc2l0aW9uTWFyZ2luBA0kdDAxOTMwMjE5NDI5AwkAZgIAAAUMc2lnbmVkTWFyZ2luCQCUCgIAAAkBA2FicwEFDHNpZ25lZE1hcmdpbgkAlAoCCQEDYWJzAQUMc2lnbmVkTWFyZ2luAAAEDHJlbWFpbk1hcmdpbggFDSR0MDE5MzAyMTk0MjkCXzEEB2JhZERlYnQIBQ0kdDAxOTMwMjE5NDI5Al8yCQCWCgQFDHJlbWFpbk1hcmdpbgUHYmFkRGVidAUOZnVuZGluZ1BheW1lbnQFC3JvbGxvdmVyRmVlARZzd2FwT3V0cHV0V2l0aFJlc2VydmVzBwZfaXNBZGQQX2Jhc2VBc3NldEFtb3VudBRfY2hlY2tNYXhQcmljZUltcGFjdBJfcXVvdGVBc3NldFJlc2VydmURX3F1b3RlQXNzZXRXZWlnaHQRX2Jhc2VBc3NldFJlc2VydmUQX2Jhc2VBc3NldFdlaWdodAQLcHJpY2VCZWZvcmUJAQRkaXZkAgkBBG11bGQCBRJfcXVvdGVBc3NldFJlc2VydmUFEV9xdW90ZUFzc2V0V2VpZ2h0CQEEbXVsZAIFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0V2VpZ2h0AwkAAAIFEF9iYXNlQXNzZXRBbW91bnQAAAkAAgECGUludmFsaWQgYmFzZSBhc3NldCBhbW91bnQEAWsJAQ1jYWxjSW52YXJpYW50AgUSX3F1b3RlQXNzZXRSZXNlcnZlBRFfYmFzZUFzc2V0UmVzZXJ2ZQQYYmFzZUFzc2V0UG9vbEFtb3VudEFmdGVyAwUGX2lzQWRkCQBkAgURX2Jhc2VBc3NldFJlc2VydmUFEF9iYXNlQXNzZXRBbW91bnQJAGUCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldEFtb3VudAQPcXVvdGVBc3NldEFmdGVyCQCgAwEJAQViZGl2ZAIFAWsJALYCAQUYYmFzZUFzc2V0UG9vbEFtb3VudEFmdGVyBA9xdW90ZUFzc2V0RGVsdGEJAQNhYnMBCQBlAgUPcXVvdGVBc3NldEFmdGVyBRJfcXVvdGVBc3NldFJlc2VydmUEDnF1b3RlQXNzZXRTb2xkCQEEbXVsZAIFD3F1b3RlQXNzZXREZWx0YQURX3F1b3RlQXNzZXRXZWlnaHQEE21heFByaWNlSW1wYWN0VmFsdWUJAQ5tYXhQcmljZUltcGFjdAAEDSR0MDIwNjkxMjA4NTMJAQ11cGRhdGVSZXNlcnZlAwkBASEBBQZfaXNBZGQFD3F1b3RlQXNzZXREZWx0YQUQX2Jhc2VBc3NldEFtb3VudAQXcXVvdGVBc3NldFJlc2VydmVBZnRlcjEIBQ0kdDAyMDY5MTIwODUzAl8xBBZiYXNlQXNzZXRSZXNlcnZlQWZ0ZXIxCAUNJHQwMjA2OTEyMDg1MwJfMgQXdG90YWxQb3NpdGlvblNpemVBZnRlcjEIBQ0kdDAyMDY5MTIwODUzAl8zBAttYXJrZXRQcmljZQkBBGRpdmQCBQ5xdW90ZUFzc2V0U29sZAUQX2Jhc2VBc3NldEFtb3VudAQJcHJpY2VEaWZmCQEDYWJzAQkAZQIFC3ByaWNlQmVmb3JlBQttYXJrZXRQcmljZQQLcHJpY2VJbXBhY3QJAGUCBQxERUNJTUFMX1VOSVQJAQRkaXZkAgULcHJpY2VCZWZvcmUJAGQCBQtwcmljZUJlZm9yZQUJcHJpY2VEaWZmAwMJAGYCBQtwcmljZUltcGFjdAUTbWF4UHJpY2VJbXBhY3RWYWx1ZQUUX2NoZWNrTWF4UHJpY2VJbXBhY3QHCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAg1QcmljZSBpbXBhY3QgCQCkAwEFC3ByaWNlSW1wYWN0AhQgPiBtYXggcHJpY2UgaW1wYWN0IAkApAMBBRNtYXhQcmljZUltcGFjdFZhbHVlAhUgYmVmb3JlIHF1b3RlIGFzc2V0OiAJAKQDAQUSX3F1b3RlQXNzZXRSZXNlcnZlAhQgYmVmb3JlIGJhc2UgYXNzZXQ6IAkApAMBBRFfYmFzZUFzc2V0UmVzZXJ2ZQIgIGJhc2UgYXNzZXQgYW1vdW50IHRvIGV4Y2hhbmdlOiAJAKQDAQUQX2Jhc2VBc3NldEFtb3VudAIPIHByaWNlIGJlZm9yZTogCQCkAwEFC3ByaWNlQmVmb3JlAg8gbWFya2V0IHByaWNlOiAJAKQDAQULbWFya2V0UHJpY2UJAJkKBwUOcXVvdGVBc3NldFNvbGQFF3F1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIxBRZiYXNlQXNzZXRSZXNlcnZlQWZ0ZXIxBRd0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyMQkAZQIJARV0b3RhbExvbmdQb3NpdGlvblNpemUAAwUGX2lzQWRkCQEDYWJzAQUQX2Jhc2VBc3NldEFtb3VudAAACQBlAgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUAAwkBASEBBQZfaXNBZGQJAQNhYnMBBRBfYmFzZUFzc2V0QW1vdW50AAAFC3ByaWNlSW1wYWN0AQpzd2FwT3V0cHV0AwZfaXNBZGQQX2Jhc2VBc3NldEFtb3VudBRfY2hlY2tNYXhQcmljZUltcGFjdAkBFnN3YXBPdXRwdXRXaXRoUmVzZXJ2ZXMHBQZfaXNBZGQFEF9iYXNlQXNzZXRBbW91bnQFFF9jaGVja01heFByaWNlSW1wYWN0CQEGcXRBc3RSAAkBBnF0QXN0VwAJAQZic0FzdFIACQEGYnNBc3RXAAETZ2V0T3JhY2xlUHJpY2VWYWx1ZQMGb3JhY2xlCHByaWNlS2V5CGJsb2NrS2V5BAlsYXN0VmFsdWUJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQZvcmFjbGUFCHByaWNlS2V5CQCsAgIJAKwCAgkArAICAiJDYW4gbm90IGdldCBvcmFjbGUgcHJpY2UuIE9yYWNsZTogCQClCAEFBm9yYWNsZQIGIGtleTogBQhwcmljZUtleQMJAQIhPQIFCGJsb2NrS2V5AgAEDGN1cnJlbnRCbG9jawgFCWxhc3RCbG9jawZoZWlnaHQED2xhc3RPcmFjbGVCbG9jawkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFBm9yYWNsZQUIYmxvY2tLZXkJAKwCAgkArAICCQCsAgICIkNhbiBub3QgZ2V0IG9yYWNsZSBibG9jay4gT3JhY2xlOiAJAKUIAQUGb3JhY2xlAgYga2V5OiAFCGJsb2NrS2V5AwkAZgIJAGUCBQxjdXJyZW50QmxvY2sFD2xhc3RPcmFjbGVCbG9jawkBDm1heE9yYWNsZURlbGF5AAkAAgEJAKwCAgkArAICCQCsAgICJk9yYWNsZSBzdGFsZSBkYXRhLiBMYXN0IG9yYWNsZSBibG9jazogCQCkAwEFD2xhc3RPcmFjbGVCbG9jawIQIGN1cnJlbnQgYmxvY2s6IAkApAMBBQxjdXJyZW50QmxvY2sFCWxhc3RWYWx1ZQUJbGFzdFZhbHVlAQ5nZXRPcmFjbGVQcmljZQAECmJhc2VPcmFjbGUJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkBDWdldE9yYWNsZURhdGEBBQxrX2Jhc2VPcmFjbGUCGU5vIGJhc2UgYXNzZXQgb3JhY2xlIGRhdGEED2Jhc2VPcmFjbGVQcmljZQkBE2dldE9yYWNsZVByaWNlVmFsdWUDCAUKYmFzZU9yYWNsZQJfMQgFCmJhc2VPcmFjbGUCXzIIBQpiYXNlT3JhY2xlAl8zBAtxdW90ZU9yYWNsZQkBDWdldE9yYWNsZURhdGEBBQ1rX3F1b3RlT3JhY2xlBBBxdW90ZU9yYWNsZVByaWNlAwkBCWlzRGVmaW5lZAEFC3F1b3RlT3JhY2xlBAxxdW90ZU9yYWNsZVYJAQV2YWx1ZQEFC3F1b3RlT3JhY2xlCQETZ2V0T3JhY2xlUHJpY2VWYWx1ZQMIBQxxdW90ZU9yYWNsZVYCXzEIBQxxdW90ZU9yYWNsZVYCXzIIBQxxdW90ZU9yYWNsZVYCXzMFDERFQ0lNQUxfVU5JVAkBBGRpdmQCBQ9iYXNlT3JhY2xlUHJpY2UFEHF1b3RlT3JhY2xlUHJpY2UBDmlzTWFya2V0Q2xvc2VkAAQKYmFzZU9yYWNsZQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQENZ2V0T3JhY2xlRGF0YQEFDGtfYmFzZU9yYWNsZQIZTm8gYmFzZSBhc3NldCBvcmFjbGUgZGF0YQQGb3JhY2xlCAUKYmFzZU9yYWNsZQJfMQQHb3BlbktleQgFCmJhc2VPcmFjbGUCXzQDCQECIT0CBQdvcGVuS2V5AgAEBmlzT3BlbgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCbCAIFBm9yYWNsZQUHb3BlbktleQkArAICCQCsAgIJAKwCAgIrQ2FuIG5vdCBnZXQgb3JhY2xlIGlzIG9wZW4vY2xvc2VkLiBPcmFjbGU6IAkApQgBBQZvcmFjbGUCBiBrZXk6IAUHb3BlbktleQkBASEBBQZpc09wZW4HAQxhYnNQcmljZURpZmYFDF9vcmFjbGVQcmljZRJfcXVvdGVBc3NldFJlc2VydmURX2Jhc2VBc3NldFJlc2VydmUHX3F0QXN0VwdfYnNBc3RXBApwcmljZUFmdGVyCQEEZGl2ZAIJAQRtdWxkAgUSX3F1b3RlQXNzZXRSZXNlcnZlBQdfcXRBc3RXCQEEbXVsZAIFEV9iYXNlQXNzZXRSZXNlcnZlBQdfYnNBc3RXBAxhdmVyYWdlUHJpY2UJAQRkaXZkAgkAZAIFDF9vcmFjbGVQcmljZQUKcHJpY2VBZnRlcgkAaAIAAgUMREVDSU1BTF9VTklUBAxhYnNQcmljZURpZmYJAQRkaXZkAgkBA2FicwEJAGUCBQxfb3JhY2xlUHJpY2UFCnByaWNlQWZ0ZXIFDGF2ZXJhZ2VQcmljZQUMYWJzUHJpY2VEaWZmARlyZXF1aXJlTm90T3ZlclNwcmVhZExpbWl0AhJfcXVvdGVBc3NldFJlc2VydmURX2Jhc2VBc3NldFJlc2VydmUEC29yYWNsZVByaWNlCQEOZ2V0T3JhY2xlUHJpY2UABAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwAEEmFic1ByaWNlRGlmZkJlZm9yZQkBDGFic1ByaWNlRGlmZgUFC29yYWNsZVByaWNlCQEGcXRBc3RSAAkBBmJzQXN0UgAFB19xdEFzdFcFB19ic0FzdFcEEWFic1ByaWNlRGlmZkFmdGVyCQEMYWJzUHJpY2VEaWZmBQULb3JhY2xlUHJpY2UFEl9xdW90ZUFzc2V0UmVzZXJ2ZQURX2Jhc2VBc3NldFJlc2VydmUFB19xdEFzdFcFB19ic0FzdFcDAwkAZgIFEWFic1ByaWNlRGlmZkFmdGVyCQEObWF4UHJpY2VTcHJlYWQACQBmAgURYWJzUHJpY2VEaWZmQWZ0ZXIFEmFic1ByaWNlRGlmZkJlZm9yZQcJAAIBCQCsAgIJAKwCAgkArAICAg1QcmljZSBzcHJlYWQgCQCkAwEFEWFic1ByaWNlRGlmZkFmdGVyAhQgPiBtYXggcHJpY2Ugc3ByZWFkIAkApAMBCQEObWF4UHJpY2VTcHJlYWQABgEdcmVxdWlyZU5vdE92ZXJNYXhPcGVuTm90aW9uYWwCEV9sb25nT3Blbk5vdGlvbmFsEl9zaG9ydE9wZW5Ob3Rpb25hbAQQX21heE9wZW5Ob3Rpb25hbAkBD21heE9wZW5Ob3Rpb25hbAADCQBmAgURX2xvbmdPcGVuTm90aW9uYWwFEF9tYXhPcGVuTm90aW9uYWwJAAIBCQCsAgIJAKwCAgkArAICAhNMb25nIG9wZW4gbm90aW9uYWwgCQCkAwEFEV9sb25nT3Blbk5vdGlvbmFsAhUgPiBtYXggb3BlbiBub3Rpb25hbCAJAKQDAQUQX21heE9wZW5Ob3Rpb25hbAMJAGYCBRJfc2hvcnRPcGVuTm90aW9uYWwFEF9tYXhPcGVuTm90aW9uYWwJAAIBCQCsAgIJAKwCAgkArAICAhRTaG9ydCBvcGVuIG5vdGlvbmFsIAkApAMBBRJfc2hvcnRPcGVuTm90aW9uYWwCFSA+IG1heCBvcGVuIG5vdGlvbmFsIAkApAMBBRBfbWF4T3Blbk5vdGlvbmFsBgEMZ2V0U3BvdFByaWNlAAQSX3F1b3RlQXNzZXRSZXNlcnZlCQEGcXRBc3RSAAQRX2Jhc2VBc3NldFJlc2VydmUJAQZic0FzdFIABAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwAJAQRkaXZkAgkBBG11bGQCBRJfcXVvdGVBc3NldFJlc2VydmUFB19xdEFzdFcJAQRtdWxkAgURX2Jhc2VBc3NldFJlc2VydmUFB19ic0FzdFcBFmlzT3ZlckZsdWN0dWF0aW9uTGltaXQABAtvcmFjbGVQcmljZQkBDmdldE9yYWNsZVByaWNlAAQMY3VycmVudFByaWNlCQEMZ2V0U3BvdFByaWNlAAkAZgIJAQRkaXZkAgkBA2FicwEJAGUCBQtvcmFjbGVQcmljZQUMY3VycmVudFByaWNlBQtvcmFjbGVQcmljZQkBC3NwcmVhZExpbWl0AAEfZ2V0UG9zaXRpb25BZGp1c3RlZE9wZW5Ob3Rpb25hbAYNX3Bvc2l0aW9uU2l6ZQdfb3B0aW9uEl9xdW90ZUFzc2V0UmVzZXJ2ZRFfcXVvdGVBc3NldFdlaWdodBFfYmFzZUFzc2V0UmVzZXJ2ZRBfYmFzZUFzc2V0V2VpZ2h0BA9wb3NpdGlvblNpemVBYnMJAQNhYnMBBQ1fcG9zaXRpb25TaXplBAdpc1Nob3J0CQBmAgAABQ1fcG9zaXRpb25TaXplBBBwb3NpdGlvbk5vdGlvbmFsAwkAAAIFB19vcHRpb24FD1BOTF9PUFRJT05fU1BPVAQTb3V0UG9zaXRpb25Ob3Rpb25hbAgJARZzd2FwT3V0cHV0V2l0aFJlc2VydmVzBwkBASEBBQdpc1Nob3J0BQ9wb3NpdGlvblNpemVBYnMHBRJfcXVvdGVBc3NldFJlc2VydmUFEV9xdW90ZUFzc2V0V2VpZ2h0BRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldFdlaWdodAJfMQUTb3V0UG9zaXRpb25Ob3Rpb25hbAkBBG11bGQCBQ9wb3NpdGlvblNpemVBYnMJAQ5nZXRPcmFjbGVQcmljZQAFEHBvc2l0aW9uTm90aW9uYWwBK2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sQnlWYWx1ZXMHDV9wb3NpdGlvblNpemUVX3Bvc2l0aW9uT3Blbk5vdGlvbmFsEl9xdW90ZUFzc2V0UmVzZXJ2ZRFfcXVvdGVBc3NldFdlaWdodBFfYmFzZUFzc2V0UmVzZXJ2ZRBfYmFzZUFzc2V0V2VpZ2h0B19vcHRpb24DCQAAAgUNX3Bvc2l0aW9uU2l6ZQAACQACAQIVSW52YWxpZCBwb3NpdGlvbiBzaXplBAdpc1Nob3J0CQBmAgAABQ1fcG9zaXRpb25TaXplBBBwb3NpdGlvbk5vdGlvbmFsCQEfZ2V0UG9zaXRpb25BZGp1c3RlZE9wZW5Ob3Rpb25hbAYFDV9wb3NpdGlvblNpemUFB19vcHRpb24FEl9xdW90ZUFzc2V0UmVzZXJ2ZQURX3F1b3RlQXNzZXRXZWlnaHQFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0V2VpZ2h0BA11bnJlYWxpemVkUG5sAwUHaXNTaG9ydAkAZQIFFV9wb3NpdGlvbk9wZW5Ob3Rpb25hbAUQcG9zaXRpb25Ob3Rpb25hbAkAZQIFEHBvc2l0aW9uTm90aW9uYWwFFV9wb3NpdGlvbk9wZW5Ob3Rpb25hbAkAlAoCBRBwb3NpdGlvbk5vdGlvbmFsBQ11bnJlYWxpemVkUG5sASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIHX3RyYWRlcgdfb3B0aW9uBA0kdDAyODczMTI4ODU5CQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBAxwb3NpdGlvblNpemUIBQ0kdDAyODczMTI4ODU5Al8xBA5wb3NpdGlvbk1hcmdpbggFDSR0MDI4NzMxMjg4NTkCXzIEFHBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwMjg3MzEyODg1OQJfMwQRcG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDAyODczMTI4ODU5Al80CQErZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmxCeVZhbHVlcwcFDHBvc2l0aW9uU2l6ZQUUcG9zaXRpb25PcGVuTm90aW9uYWwJAQZxdEFzdFIACQEGcXRBc3RXAAkBBmJzQXN0UgAJAQZic0FzdFcABQdfb3B0aW9uAQ9jYWxjTWFyZ2luUmF0aW8DDV9yZW1haW5NYXJnaW4IX2JhZERlYnQRX3Bvc2l0aW9uTm90aW9uYWwJAQRkaXZkAgkAZQIFDV9yZW1haW5NYXJnaW4FCF9iYWREZWJ0BRFfcG9zaXRpb25Ob3Rpb25hbAEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgIHX3RyYWRlcgdfb3B0aW9uBA0kdDAyOTM3NDI5NTE1CQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBAxwb3NpdGlvblNpemUIBQ0kdDAyOTM3NDI5NTE1Al8xBA5wb3NpdGlvbk1hcmdpbggFDSR0MDI5Mzc0Mjk1MTUCXzIEA3BvbggFDSR0MDI5Mzc0Mjk1MTUCXzMEFnBvc2l0aW9uTGFzdFVwZGF0ZWRDUEYIBQ0kdDAyOTM3NDI5NTE1Al80BBFwb3NpdGlvblRpbWVzdGFtcAgFDSR0MDI5Mzc0Mjk1MTUCXzUEDSR0MDI5NTIxMjk2MTQJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIFB190cmFkZXIFB19vcHRpb24EEHBvc2l0aW9uTm90aW9uYWwIBQ0kdDAyOTUyMTI5NjE0Al8xBA11bnJlYWxpemVkUG5sCAUNJHQwMjk1MjEyOTYxNAJfMgQNJHQwMjk2MTkyOTgzMQkBMGNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnRBbmRSb2xsb3ZlckZlZQUFDHBvc2l0aW9uU2l6ZQUOcG9zaXRpb25NYXJnaW4FFnBvc2l0aW9uTGFzdFVwZGF0ZWRDUEYFEXBvc2l0aW9uVGltZXN0YW1wBQ11bnJlYWxpemVkUG5sBAxyZW1haW5NYXJnaW4IBQ0kdDAyOTYxOTI5ODMxAl8xBAdiYWREZWJ0CAUNJHQwMjk2MTkyOTgzMQJfMgkBD2NhbGNNYXJnaW5SYXRpbwMFDHJlbWFpbk1hcmdpbgUHYmFkRGVidAUQcG9zaXRpb25Ob3Rpb25hbAEOZ2V0TWFyZ2luUmF0aW8BB190cmFkZXIJARZnZXRNYXJnaW5SYXRpb0J5T3B0aW9uAgUHX3RyYWRlcgUPUE5MX09QVElPTl9TUE9UARtnZXRQYXJ0aWFsTGlxdWlkYXRpb25BbW91bnQCB190cmFkZXINX3Bvc2l0aW9uU2l6ZQQMbWF4aW11bVJhdGlvCQEEdm1heAIJARdwYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwAJAGUCBQxERUNJTUFMX1VOSVQJAQRkaXZkAgkBDmdldE1hcmdpblJhdGlvAQUHX3RyYWRlcgkBFm1haW50ZW5hbmNlTWFyZ2luUmF0aW8ABBhtYXhFeGNoYW5nZWRQb3NpdGlvblNpemUJAQRtdWxkAgkBA2FicwEFDV9wb3NpdGlvblNpemUFDG1heGltdW1SYXRpbwQKc3dhcFJlc3VsdAkBCnN3YXBPdXRwdXQDCQBmAgUNX3Bvc2l0aW9uU2l6ZQAABRhtYXhFeGNoYW5nZWRQb3NpdGlvblNpemUHBBxtYXhFeGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CAUKc3dhcFJlc3VsdAJfMQQLcHJpY2VJbXBhY3QIBQpzd2FwUmVzdWx0Al83AwkAZgIJAQ5tYXhQcmljZUltcGFjdAAFC3ByaWNlSW1wYWN0BRhtYXhFeGNoYW5nZWRQb3NpdGlvblNpemUJAQRtdWxkAgkBA2FicwEFDV9wb3NpdGlvblNpemUJARdwYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwABFWludGVybmFsQ2xvc2VQb3NpdGlvbgcHX3RyYWRlcgVfc2l6ZQRfZmVlFF9taW5RdW90ZUFzc2V0QW1vdW50DF9hZGRUb01hcmdpbhRfY2hlY2tNYXhQcmljZUltcGFjdApfbGlxdWlkYXRlBA0kdDAzMDg5ODMxMDU0CQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBA9vbGRQb3NpdGlvblNpemUIBQ0kdDAzMDg5ODMxMDU0Al8xBBFvbGRQb3NpdGlvbk1hcmdpbggFDSR0MDMwODk4MzEwNTQCXzIEF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwMzA4OTgzMTA1NAJfMwQUb2xkUG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDAzMDg5ODMxMDU0Al80BBRvbGRQb3NpdGlvblRpbWVzdGFtcAgFDSR0MDMwODk4MzEwNTQCXzUEDmlzTG9uZ1Bvc2l0aW9uCQBmAgUPb2xkUG9zaXRpb25TaXplAAAEEmFic09sZFBvc2l0aW9uU2l6ZQkBA2FicwEFD29sZFBvc2l0aW9uU2l6ZQMDCQBnAgUSYWJzT2xkUG9zaXRpb25TaXplBQVfc2l6ZQkAZgIFBV9zaXplAAAHBA5pc1BhcnRpYWxDbG9zZQkAZgIFEmFic09sZFBvc2l0aW9uU2l6ZQUFX3NpemUEDSR0MDMxMzQ2MzE3OTcJAQpzd2FwT3V0cHV0AwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAABQVfc2l6ZQUUX2NoZWNrTWF4UHJpY2VJbXBhY3QEGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQIBQ0kdDAzMTM0NjMxNzk3Al8xBBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwMzEzNDYzMTc5NwJfMgQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwMzEzNDYzMTc5NwJfMwQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDMxMzQ2MzE3OTcCXzQEFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQMJAGYCBQ9vbGRQb3NpdGlvblNpemUAAAkBAS0BBQVfc2l6ZQUFX3NpemUEDSR0MDMyMDEyMzIyMTkJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAQTb2xkUG9zaXRpb25Ob3Rpb25hbAgFDSR0MDMyMDEyMzIyMTkCXzEEDXVucmVhbGl6ZWRQbmwIBQ0kdDAzMjAxMjMyMjE5Al8yBA1yZWFsaXplZFJhdGlvCQEEZGl2ZAIJAQNhYnMBBRVleGNoYW5nZWRQb3NpdGlvblNpemUFEmFic09sZFBvc2l0aW9uU2l6ZQQLcmVhbGl6ZWRQbmwJAQRtdWxkAgUNdW5yZWFsaXplZFBubAUNcmVhbGl6ZWRSYXRpbwQNJHQwMzI1NjAzMjgwNgkBMGNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnRBbmRSb2xsb3ZlckZlZQUFD29sZFBvc2l0aW9uU2l6ZQURb2xkUG9zaXRpb25NYXJnaW4FFG9sZFBvc2l0aW9uTHN0VXBkQ1BGBRRvbGRQb3NpdGlvblRpbWVzdGFtcAUNdW5yZWFsaXplZFBubAQScmVtYWluTWFyZ2luQmVmb3JlCAUNJHQwMzI1NjAzMjgwNgJfMQQCeDEIBQ0kdDAzMjU2MDMyODA2Al8yBAJ4MggFDSR0MDMyNTYwMzI4MDYCXzMEC3JvbGxvdmVyRmVlCAUNJHQwMzI1NjAzMjgwNgJfNAQPcG9zaXRpb25CYWREZWJ0CAkBMGNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnRBbmRSb2xsb3ZlckZlZQUFD29sZFBvc2l0aW9uU2l6ZQURb2xkUG9zaXRpb25NYXJnaW4FFG9sZFBvc2l0aW9uTHN0VXBkQ1BGBRRvbGRQb3NpdGlvblRpbWVzdGFtcAULcmVhbGl6ZWRQbmwCXzIEEHJlYWxpemVkQ2xvc2VGZWUJAQRtdWxkAgkBBG11bGQCBRNvbGRQb3NpdGlvbk5vdGlvbmFsBQ1yZWFsaXplZFJhdGlvBQRfZmVlBBJ1bnJlYWxpemVkUG5sQWZ0ZXIJAGUCBQ11bnJlYWxpemVkUG5sBQtyZWFsaXplZFBubAQScmVtYWluT3Blbk5vdGlvbmFsAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAACQBlAgkAZQIFE29sZFBvc2l0aW9uTm90aW9uYWwFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQFEnVucmVhbGl6ZWRQbmxBZnRlcgkAZQIJAGQCBRJ1bnJlYWxpemVkUG5sQWZ0ZXIFE29sZFBvc2l0aW9uTm90aW9uYWwFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQED25ld1Bvc2l0aW9uU2l6ZQkAZAIFD29sZFBvc2l0aW9uU2l6ZQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplBA0kdDAzNDIxMjM0NTk4AwkAAAIFD25ld1Bvc2l0aW9uU2l6ZQAACQCUCgIAAAAACQCUCgIJAQNhYnMBBRJyZW1haW5PcGVuTm90aW9uYWwJAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUPbmV3UG9zaXRpb25TaXplBBduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDM0MjEyMzQ1OTgCXzEEFG5ld1Bvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwMzQyMTIzNDU5OAJfMgQRb3Blbk5vdGlvbmFsRGVsdGEJAGUCBRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwEC21hcmdpblJhdGlvCQEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAQebmV3UG9zaXRpb25NYXJnaW5XaXRoU2FtZVJhdGlvAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAACQBlAgkBBG11bGQCCQBkAgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFEnVucmVhbGl6ZWRQbmxBZnRlcgULbWFyZ2luUmF0aW8FEnVucmVhbGl6ZWRQbmxBZnRlcgkAZQIJAQRtdWxkAgkAZQIFF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBRJ1bnJlYWxpemVkUG5sQWZ0ZXIFC21hcmdpblJhdGlvBRJ1bnJlYWxpemVkUG5sQWZ0ZXIEEW1hcmdpblRvVHJhZGVyUmF3CQBlAgkAZQIFEnJlbWFpbk1hcmdpbkJlZm9yZQkAZAIFHm5ld1Bvc2l0aW9uTWFyZ2luV2l0aFNhbWVSYXRpbwUSdW5yZWFsaXplZFBubEFmdGVyBRByZWFsaXplZENsb3NlRmVlBA5tYXJnaW5Ub1RyYWRlcgMJAGYCAAAFEW1hcmdpblRvVHJhZGVyUmF3AwUKX2xpcXVpZGF0ZQAACQACAQI3SW52YWxpZCBpbnRlcm5hbENsb3NlUG9zaXRpb24gcGFyYW1zOiB1bmFibGUgdG8gcGF5IGZlZQURbWFyZ2luVG9UcmFkZXJSYXcEEW5ld1Bvc2l0aW9uTWFyZ2luAwUMX2FkZFRvTWFyZ2luCQBkAgUebmV3UG9zaXRpb25NYXJnaW5XaXRoU2FtZVJhdGlvBQ5tYXJnaW5Ub1RyYWRlcgUebmV3UG9zaXRpb25NYXJnaW5XaXRoU2FtZVJhdGlvAwMJAQIhPQIFFF9taW5RdW90ZUFzc2V0QW1vdW50AAAJAGYCBRRfbWluUXVvdGVBc3NldEFtb3VudAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAcJAAIBCQCsAgIJAKwCAgkArAICAg1MaW1pdCBlcnJvcjogCQCkAwEFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQCAyA8IAkApAMBBRRfbWluUXVvdGVBc3NldEFtb3VudAkAowoRBQ9uZXdQb3NpdGlvblNpemUFEW5ld1Bvc2l0aW9uTWFyZ2luBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUUbmV3UG9zaXRpb25Mc3RVcGRDUEYFD3Bvc2l0aW9uQmFkRGVidAULcmVhbGl6ZWRQbmwDAwUMX2FkZFRvTWFyZ2luBQ5pc1BhcnRpYWxDbG9zZQcAAAUObWFyZ2luVG9UcmFkZXIFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgkAZQIJARRvcGVuSW50ZXJlc3ROb3Rpb25hbAAFEW9wZW5Ob3Rpb25hbERlbHRhCQBlAgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQADBQ5pc0xvbmdQb3NpdGlvbgkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQAACQBlAgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUAAwkBASEBBQ5pc0xvbmdQb3NpdGlvbgkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQAACQBlAgkBEG9wZW5JbnRlcmVzdExvbmcAAwUOaXNMb25nUG9zaXRpb24FEW9wZW5Ob3Rpb25hbERlbHRhAAAJAGUCCQERb3BlbkludGVyZXN0U2hvcnQAAwkBASEBBQ5pc0xvbmdQb3NpdGlvbgURb3Blbk5vdGlvbmFsRGVsdGEAAAkAZAIFEHJlYWxpemVkQ2xvc2VGZWUFC3JvbGxvdmVyRmVlBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CQACAQkArAICCQCsAgIJAKwCAgI9SW52YWxpZCBpbnRlcm5hbENsb3NlUG9zaXRpb24gcGFyYW1zOiBpbnZhbGlkIHBvc2l0aW9uIHNpemU6IAkApAMBBQVfc2l6ZQIGIG1heDogCQCkAwEFEmFic09sZFBvc2l0aW9uU2l6ZQEQZ2V0VHdhcFNwb3RQcmljZQAECG1pbnV0ZUlkCQBpAgkAaQIJAQ1sYXN0VGltZXN0YW1wAADoBwA8BA1zdGFydE1pbnV0ZUlkCQBlAgUIbWludXRlSWQFDVRXQVBfSU5URVJWQUwEB2xpc3RTdHIJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwUNa19sYXN0RGF0YVN0cgIABARsaXN0CQC1CQIFB2xpc3RTdHICASwKAQhmaWx0ZXJGbgILYWNjdW11bGF0b3IEbmV4dAMJAGcCBQ1zdGFydE1pbnV0ZUlkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJALYJAQUEbmV4dAkArAICAh9nZXRUd2FwU3BvdFByaWNlOiBpbnZhbGlkIGludDogBQdsaXN0U3RyCQDNCAIFC2FjY3VtdWxhdG9yCQENcGFyc2VJbnRWYWx1ZQEFBG5leHQFC2FjY3VtdWxhdG9yBAVsaXN0RgoAAiRsBQRsaXN0CgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQhmaWx0ZXJGbgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMjAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUBAhtYXhJbmRleAMJAGYCCQCQAwEFBWxpc3RGAAAJAJYDAQUFbGlzdEYJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAtgkBCQCRAwIFBGxpc3QAAAkArAICAh9nZXRUd2FwU3BvdFByaWNlOiBpbnZhbGlkIGludDogBQdsaXN0U3RyBAxsYXN0TWludXRlSWQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUOa19sYXN0TWludXRlSWQAAAQWZW5kTGFzdEN1bXVsYXRpdmVQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UCAV8JAKQDAQUMbGFzdE1pbnV0ZUlkAAAEDGVuZExhc3RQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUTa190d2FwRGF0YUxhc3RQcmljZQIBXwkApAMBBQxsYXN0TWludXRlSWQAAAQSbm93Q3VtdWxhdGl2ZVByaWNlCQBkAgUWZW5kTGFzdEN1bXVsYXRpdmVQcmljZQkAaAIJAGUCBQhtaW51dGVJZAUMbGFzdE1pbnV0ZUlkBQxlbmRMYXN0UHJpY2UEGHN0YXJ0TGFzdEN1bXVsYXRpdmVQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UCAV8JAKQDAQUIbWF4SW5kZXgAAAQOc3RhcnRMYXN0UHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkArAICCQCsAgIFE2tfdHdhcERhdGFMYXN0UHJpY2UCAV8JAKQDAQUIbWF4SW5kZXgAAAQUc3RhcnRDdW11bGF0aXZlUHJpY2UJAGQCBRhzdGFydExhc3RDdW11bGF0aXZlUHJpY2UJAGgCCQBlAgUNc3RhcnRNaW51dGVJZAUIbWF4SW5kZXgFDnN0YXJ0TGFzdFByaWNlCQBpAgkAZQIFEm5vd0N1bXVsYXRpdmVQcmljZQUUc3RhcnRDdW11bGF0aXZlUHJpY2UFDVRXQVBfSU5URVJWQUwBE2dldFRlcm1pbmFsQW1tU3RhdGUABA1fcG9zaXRpb25TaXplCQERdG90YWxQb3NpdGlvblNpemUAAwkAAAIFDV9wb3NpdGlvblNpemUAAAkAlAoCCQEGcXRBc3RSAAkBBmJzQXN0UgAECWRpcmVjdGlvbgkAZgIFDV9wb3NpdGlvblNpemUAAAQNJHQwMzkzMzUzOTUxNAkBCnN3YXBPdXRwdXQDBQlkaXJlY3Rpb24JAQNhYnMBBQ1fcG9zaXRpb25TaXplBwQVY3VycmVudE5ldE1hcmtldFZhbHVlCAUNJHQwMzkzMzUzOTUxNAJfMQQZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQgFDSR0MDM5MzM1Mzk1MTQCXzIEGHRlcm1pbmFsQmFzZUFzc2V0UmVzZXJ2ZQgFDSR0MDM5MzM1Mzk1MTQCXzMJAJQKAgUZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQUYdGVybWluYWxCYXNlQXNzZXRSZXNlcnZlARNnZXRRdW90ZUFzc2V0V2VpZ2h0BBBiYXNlQXNzZXRSZXNlcnZlEXRvdGFsUG9zaXRpb25TaXplEXF1b3RlQXNzZXRSZXNlcnZlC3RhcmdldFByaWNlBAFiCQC2AgEFEGJhc2VBc3NldFJlc2VydmUEAnN6CQC2AgEFEXRvdGFsUG9zaXRpb25TaXplBAFxCQC2AgEFEXF1b3RlQXNzZXRSZXNlcnZlBAFwCQC2AgEFC3RhcmdldFByaWNlBAFrCQEFYm11bGQCBQFxBQFiBARuZXdCCQC3AgIFAWIFAnN6BARuZXdRCQEFYmRpdmQCBQFrBQRuZXdCBAF6CQEFYmRpdmQCBQRuZXdRBQRuZXdCBAZyZXN1bHQJAQViZGl2ZAIFAXAFAXoJAKADAQUGcmVzdWx0ARRnZXRTeW5jVGVybWluYWxQcmljZQMOX3Rlcm1pbmFsUHJpY2UHX3F0QXN0UgdfYnNBc3RSBA1fcG9zaXRpb25TaXplCQERdG90YWxQb3NpdGlvblNpemUAAwkAAAIFDV9wb3NpdGlvblNpemUAAAQJbmV3UXRBc3RXCQEEZGl2ZAIJAQRtdWxkAgUOX3Rlcm1pbmFsUHJpY2UFB19ic0FzdFIFB19xdEFzdFIJAJUKAwUJbmV3UXRBc3RXBQxERUNJTUFMX1VOSVQAAAQJZGlyZWN0aW9uCQBmAgUNX3Bvc2l0aW9uU2l6ZQAABBVjdXJyZW50TmV0TWFya2V0VmFsdWUICQEKc3dhcE91dHB1dAMFCWRpcmVjdGlvbgkBA2FicwEFDV9wb3NpdGlvblNpemUHAl8xBAluZXdRdEFzdFcJARNnZXRRdW90ZUFzc2V0V2VpZ2h0BAUHX2JzQXN0UgUNX3Bvc2l0aW9uU2l6ZQUHX3F0QXN0UgUOX3Rlcm1pbmFsUHJpY2UECW5ld0JzQXN0VwUMREVDSU1BTF9VTklUBA1tYXJnaW5Ub1ZhdWx0CAkBK2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sQnlWYWx1ZXMHBQ1fcG9zaXRpb25TaXplBRVjdXJyZW50TmV0TWFya2V0VmFsdWUFB19xdEFzdFIFCW5ld1F0QXN0VwUHX2JzQXN0UgUJbmV3QnNBc3RXBQ9QTkxfT1BUSU9OX1NQT1QCXzIJAJUKAwUJbmV3UXRBc3RXBQluZXdCc0FzdFcFDW1hcmdpblRvVmF1bHQBCmdldEZ1bmRpbmcABA91bmRlcmx5aW5nUHJpY2UJAQ5nZXRPcmFjbGVQcmljZQAECXNwb3RQcmljZQkBDGdldFNwb3RQcmljZQAEB3ByZW1pdW0JAGUCBQlzcG90UHJpY2UFD3VuZGVybHlpbmdQcmljZQMDAwkAAAIJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAAABgkAAAIJARV0b3RhbExvbmdQb3NpdGlvblNpemUAAAAGCQEOaXNNYXJrZXRDbG9zZWQACQCVCgMAAAAAAAADCQBmAgAABQdwcmVtaXVtBBRzaG9ydFByZW1pdW1GcmFjdGlvbgkBBGRpdmQCCQEEbXVsZAIFB3ByZW1pdW0JARRmdW5kaW5nUGVyaW9kRGVjaW1hbAAFB09ORV9EQVkDCQAAAgkBC2Z1bmRpbmdNb2RlAAUSRlVORElOR19BU1lNTUVUUklDBBNsb25nUHJlbWl1bUZyYWN0aW9uCQEEZGl2ZAIJAQRtdWxkAgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24JARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQAJAJUKAwUUc2hvcnRQcmVtaXVtRnJhY3Rpb24FE2xvbmdQcmVtaXVtRnJhY3Rpb24AAAQZc2hvcnRUb3RhbFByZW1pdW1GcmFjdGlvbgkBA2FicwEJAQRtdWxkAgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24JARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAQYbG9uZ1RvdGFsUHJlbWl1bUZyYWN0aW9uCQEDYWJzAQkBBG11bGQCBRRzaG9ydFByZW1pdW1GcmFjdGlvbgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQAEDnByZW1pdW1Ub1ZhdWx0CQBlAgUZc2hvcnRUb3RhbFByZW1pdW1GcmFjdGlvbgUYbG9uZ1RvdGFsUHJlbWl1bUZyYWN0aW9uCQCVCgMFFHNob3J0UHJlbWl1bUZyYWN0aW9uBRRzaG9ydFByZW1pdW1GcmFjdGlvbgUOcHJlbWl1bVRvVmF1bHQEE2xvbmdQcmVtaXVtRnJhY3Rpb24JAQRkaXZkAgkBBG11bGQCBQdwcmVtaXVtCQEUZnVuZGluZ1BlcmlvZERlY2ltYWwABQdPTkVfREFZAwkAAAIJAQtmdW5kaW5nTW9kZQAFEkZVTkRJTkdfQVNZTU1FVFJJQwQUc2hvcnRQcmVtaXVtRnJhY3Rpb24JAQRkaXZkAgkBBG11bGQCBRNsb25nUHJlbWl1bUZyYWN0aW9uCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUACQCVCgMFFHNob3J0UHJlbWl1bUZyYWN0aW9uBRNsb25nUHJlbWl1bUZyYWN0aW9uAAAEGGxvbmdUb3RhbFByZW1pdW1GcmFjdGlvbgkBA2FicwEJAQRtdWxkAgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQAEGXNob3J0VG90YWxQcmVtaXVtRnJhY3Rpb24JAQNhYnMBCQEEbXVsZAIFE2xvbmdQcmVtaXVtRnJhY3Rpb24JARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAQOcHJlbWl1bVRvVmF1bHQJAGUCBRhsb25nVG90YWxQcmVtaXVtRnJhY3Rpb24FGXNob3J0VG90YWxQcmVtaXVtRnJhY3Rpb24JAJUKAwUTbG9uZ1ByZW1pdW1GcmFjdGlvbgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgUOcHJlbWl1bVRvVmF1bHQBDmdldEFkanVzdGVkRmVlAgtfYXJ0aWZhY3RJZBBfYmFzZUZlZURpc2NvdW50BApiYXNlRmVlUmF3CQEDZmVlAAQHYmFzZUZlZQkBBG11bGQCBQpiYXNlRmVlUmF3BRBfYmFzZUZlZURpc2NvdW50BA0kdDA0NDA4OTQ0NTg0AwkBAiE9AgULX2FydGlmYWN0SWQCAAQMYXJ0aWZhY3RLaW5kCQEEc3RyQQIJARFuZnRNYW5hZ2VyQWRkcmVzcwAJAQ50b0NvbXBvc2l0ZUtleQIFDGtfdG9rZW5fdHlwZQULX2FydGlmYWN0SWQDCQAAAgUMYXJ0aWZhY3RLaW5kBRhGRUVfUkVEVUNUSU9OX1RPS0VOX1RZUEUECXJlZHVjdGlvbgkBBGludEECCQERbmZ0TWFuYWdlckFkZHJlc3MACQEOdG9Db21wb3NpdGVLZXkCBQ1rX3Rva2VuX3BhcmFtBQtfYXJ0aWZhY3RJZAQLYWRqdXN0ZWRGZWUJAQRtdWxkAgUHYmFzZUZlZQUJcmVkdWN0aW9uCQCUCgIFC2FkanVzdGVkRmVlBgkAAgECGUludmFsaWQgYXR0YWNoZWQgYXJ0aWZhY3QJAJQKAgUHYmFzZUZlZQcEC2FkanVzdGVkRmVlCAUNJHQwNDQwODk0NDU4NAJfMQQMYnVybkFydGlmYWN0CAUNJHQwNDQwODk0NDU4NAJfMgkAlAoCBQthZGp1c3RlZEZlZQUMYnVybkFydGlmYWN0ARdpc1NhbWVBc3NldE9yTm9Qb3NpdGlvbgIHX3RyYWRlcghfYXNzZXRJZAQPb2xkUG9zaXRpb25TaXplCAkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgJfMQMJAAACBQ9vbGRQb3NpdGlvblNpemUAAAYJAAACCQEQZ2V0UG9zaXRpb25Bc3NldAEFB190cmFkZXIFCF9hc3NldElkAQtpc1NhbWVBc3NldAIHX3RyYWRlcghfYXNzZXRJZAkAAAIJARBnZXRQb3NpdGlvbkFzc2V0AQUHX3RyYWRlcgUIX2Fzc2V0SWQBGGdldEZvclRyYWRlcldpdGhBcnRpZmFjdAIHX3RyYWRlcgtfYXJ0aWZhY3RJZAQQZG9HZXRGZWVEaXNjb3VudAkA/AcECQEMbWluZXJBZGRyZXNzAAISY29tcHV0ZUZlZURpc2NvdW50CQDMCAIFB190cmFkZXIFA25pbAUDbmlsAwkAAAIFEGRvR2V0RmVlRGlzY291bnQFEGRvR2V0RmVlRGlzY291bnQEC2ZlZURpc2NvdW50BAckbWF0Y2gwBRBkb0dldEZlZURpc2NvdW50AwkAAQIFByRtYXRjaDACA0ludAQBeAUHJG1hdGNoMAUBeAkAAgECIUludmFsaWQgY29tcHV0ZUZlZURpc2NvdW50IHJlc3VsdAQNJHQwNDUyNjQ0NTMzOAkBDmdldEFkanVzdGVkRmVlAgULX2FydGlmYWN0SWQFC2ZlZURpc2NvdW50BAthZGp1c3RlZEZlZQgFDSR0MDQ1MjY0NDUzMzgCXzEEDGJ1cm5BcnRpZmFjdAgFDSR0MDQ1MjY0NDUzMzgCXzIJAJQKAgULYWRqdXN0ZWRGZWUFDGJ1cm5BcnRpZmFjdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgENZ2V0QXJ0aWZhY3RJZAEBaQQKYXJ0aWZhY3RJZAMJAGYCCQCQAwEIBQFpCHBheW1lbnRzAAEJANgEAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCAkAkQMCCAUBaQhwYXltZW50cwABB2Fzc2V0SWQCEkludmFsaWQgYXJ0aWZhY3RJZAIABQphcnRpZmFjdElkAQ1kaXN0cmlidXRlRmVlAQpfZmVlQW1vdW50BAxmZWVUb1N0YWtlcnMJAQRtdWxkAgUKX2ZlZUFtb3VudAkBE2ZlZVRvU3Rha2Vyc1BlcmNlbnQABApmZWVUb1ZhdWx0CQBlAgUKX2ZlZUFtb3VudAUMZmVlVG9TdGFrZXJzCQCUCgIFDGZlZVRvU3Rha2VycwUKZmVlVG9WYXVsdAEOdXBkYXRlU2V0dGluZ3MNEF9pbml0TWFyZ2luUmF0aW8EX21tchRfbGlxdWlkYXRpb25GZWVSYXRpbw5fZnVuZGluZ1BlcmlvZARfZmVlDF9zcHJlYWRMaW1pdA9fbWF4UHJpY2VJbXBhY3QYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvD19tYXhQcmljZVNwcmVhZBBfbWF4T3Blbk5vdGlvbmFsFF9mZWVUb1N0YWtlcnNQZXJjZW50D19tYXhPcmFjbGVEZWxheQxfcm9sbG92ZXJGZWUJAMwIAgkBDEludGVnZXJFbnRyeQIFEWtfaW5pdE1hcmdpblJhdGlvBRBfaW5pdE1hcmdpblJhdGlvCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRhrX21haW50ZW5hbmNlTWFyZ2luUmF0aW8FBF9tbXIJAMwIAgkBDEludGVnZXJFbnRyeQIFFWtfbGlxdWlkYXRpb25GZWVSYXRpbwUUX2xpcXVpZGF0aW9uRmVlUmF0aW8JAMwIAgkBDEludGVnZXJFbnRyeQIFD2tfZnVuZGluZ1BlcmlvZAUOX2Z1bmRpbmdQZXJpb2QJAMwIAgkBDEludGVnZXJFbnRyeQIFBWtfZmVlBQRfZmVlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ1rX3NwcmVhZExpbWl0BQxfc3ByZWFkTGltaXQJAMwIAgkBDEludGVnZXJFbnRyeQIFEGtfbWF4UHJpY2VJbXBhY3QFD19tYXhQcmljZUltcGFjdAkAzAgCCQEMSW50ZWdlckVudHJ5AgUZa19wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwUYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRBrX21heFByaWNlU3ByZWFkBQ9fbWF4UHJpY2VTcHJlYWQJAMwIAgkBDEludGVnZXJFbnRyeQIFEWtfbWF4T3Blbk5vdGlvbmFsBRBfbWF4T3Blbk5vdGlvbmFsCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRVrX2ZlZVRvU3Rha2Vyc1BlcmNlbnQFFF9mZWVUb1N0YWtlcnNQZXJjZW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCBRBrX21heE9yYWNsZURlbGF5BRRfZmVlVG9TdGFrZXJzUGVyY2VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgUNa19yb2xsb3ZlckZlZQUMX3JvbGxvdmVyRmVlBQNuaWwBDXVwZGF0ZUZ1bmRpbmcFEV9uZXh0RnVuZGluZ0Jsb2NrJF9sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbiVfbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uEF9sb25nRnVuZGluZ1JhdGURX3Nob3J0RnVuZGluZ1JhdGUJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfbmV4dEZ1bmRpbmdCbG9jawURX25leHRGdW5kaW5nQmxvY2sJAMwIAgkBDEludGVnZXJFbnRyeQIFJWtfbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FJF9sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgUma19sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FJV9sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24JAMwIAgkBDEludGVnZXJFbnRyeQIFEWtfbG9uZ0Z1bmRpbmdSYXRlBRBfbG9uZ0Z1bmRpbmdSYXRlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJrX3Nob3J0RnVuZGluZ1JhdGUFEV9zaG9ydEZ1bmRpbmdSYXRlBQNuaWwBH2luY3JlbWVudFBvc2l0aW9uU2VxdWVuY2VOdW1iZXICDl9pc05ld1Bvc2l0aW9uCF9hZGRyZXNzAwUOX2lzTmV3UG9zaXRpb24ED2N1cnJlbnRTZXF1ZW5jZQkBDGxhc3RTZXF1ZW5jZQAJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFEmtfcG9zaXRpb25TZXF1ZW5jZQUIX2FkZHJlc3MJAGQCBQ9jdXJyZW50U2VxdWVuY2UAAQkAzAgCCQEMSW50ZWdlckVudHJ5AgUKa19zZXF1ZW5jZQkAZAIFD2N1cnJlbnRTZXF1ZW5jZQABBQNuaWwFA25pbAERdXBkYXRlUG9zaXRpb25GZWUDDl9pc05ld1Bvc2l0aW9uCF9hZGRyZXNzBF9mZWUDBQ5faXNOZXdQb3NpdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUNa19wb3NpdGlvbkZlZQUIX2FkZHJlc3MFBF9mZWUFA25pbAUDbmlsAQ51cGRhdGVQb3NpdGlvbgYIX2FkZHJlc3MFX3NpemUHX21hcmdpbg1fb3Blbk5vdGlvbmFsIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uEF9sYXRlc3RUaW1lc3RhbXAJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFDmtfcG9zaXRpb25TaXplBQhfYWRkcmVzcwUFX3NpemUJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFEGtfcG9zaXRpb25NYXJnaW4FCF9hZGRyZXNzBQdfbWFyZ2luCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBQhfYWRkcmVzcwUNX29wZW5Ob3Rpb25hbAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUua19wb3NpdGlvbkxhc3RVcGRhdGVkQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUIX2FkZHJlc3MFIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBR5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRUaW1lc3RhbXAFCF9hZGRyZXNzBRBfbGF0ZXN0VGltZXN0YW1wBQNuaWwBCmFwcGVuZFR3YXABBl9wcmljZQQIbWludXRlSWQJAGkCCQBpAgkBDWxhc3RUaW1lc3RhbXAAAOgHADwEEHByZXZpb3VzTWludXRlSWQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUOa19sYXN0TWludXRlSWQAAAMJAGYCBRBwcmV2aW91c01pbnV0ZUlkBQhtaW51dGVJZAkAAgECEVRXQVAgb3V0LW9mLW9yZGVyBAxsYXN0TWludXRlSWQDCQAAAgUQcHJldmlvdXNNaW51dGVJZAAABQhtaW51dGVJZAUQcHJldmlvdXNNaW51dGVJZAMJAGYCBQhtaW51dGVJZAUQcHJldmlvdXNNaW51dGVJZAQTcHJldkN1bXVsYXRpdmVQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UCAV8JAKQDAQUQcHJldmlvdXNNaW51dGVJZAAABAlwcmV2UHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkArAICCQCsAgIFE2tfdHdhcERhdGFMYXN0UHJpY2UCAV8JAKQDAQUQcHJldmlvdXNNaW51dGVJZAUGX3ByaWNlBBNsYXN0Q3VtdWxhdGl2ZVByaWNlCQBkAgUTcHJldkN1bXVsYXRpdmVQcmljZQkAaAIJAGUCBQhtaW51dGVJZAUMbGFzdE1pbnV0ZUlkBQlwcmV2UHJpY2UEBGxpc3QJAQtwdXNoVG9RdWV1ZQMJAQlzdHJUb0xpc3QBCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMFDWtfbGFzdERhdGFTdHICAAUNVFdBUF9JTlRFUlZBTAkApAMBBQhtaW51dGVJZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UJAKQDAQUIbWludXRlSWQFE2xhc3RDdW11bGF0aXZlUHJpY2UJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFE2tfdHdhcERhdGFMYXN0UHJpY2UJAKQDAQUIbWludXRlSWQFBl9wcmljZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUaa190d2FwRGF0YVByZXZpb3VzTWludXRlSWQJAKQDAQUIbWludXRlSWQFEHByZXZpb3VzTWludXRlSWQJAMwIAgkBDEludGVnZXJFbnRyeQIFDmtfbGFzdE1pbnV0ZUlkBQhtaW51dGVJZAkAzAgCCQELU3RyaW5nRW50cnkCBQ1rX2xhc3REYXRhU3RyCQEJbGlzdFRvU3RyAQUEbGlzdAUDbmlsBBh0d2FwRGF0YVByZXZpb3VzTWludXRlSWQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUaa190d2FwRGF0YVByZXZpb3VzTWludXRlSWQJAKQDAQUIbWludXRlSWQAAAQTcHJldkN1bXVsYXRpdmVQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBR1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQkApAMBBRh0d2FwRGF0YVByZXZpb3VzTWludXRlSWQAAAQJcHJldlByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFE2tfdHdhcERhdGFMYXN0UHJpY2UJAKQDAQUYdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkBQZfcHJpY2UEE2xhc3RDdW11bGF0aXZlUHJpY2UJAGQCBRNwcmV2Q3VtdWxhdGl2ZVByaWNlCQBoAgkAZQIFCG1pbnV0ZUlkBRh0d2FwRGF0YVByZXZpb3VzTWludXRlSWQFCXByZXZQcmljZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UJAKQDAQUIbWludXRlSWQFE2xhc3RDdW11bGF0aXZlUHJpY2UJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFE2tfdHdhcERhdGFMYXN0UHJpY2UJAKQDAQUIbWludXRlSWQFBl9wcmljZQUDbmlsARF1cGRhdGVBbW1SZXNlcnZlcwIHX3F0QXN0UgdfYnNBc3RSCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRNrX3F1b3RlQXNzZXRSZXNlcnZlBQdfcXRBc3RSCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJrX2Jhc2VBc3NldFJlc2VydmUFB19ic0FzdFIFA25pbAEQdXBkYXRlQW1tV2VpZ2h0cwIHX3F0QXN0VwdfYnNBc3RXCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJrX3F1b3RlQXNzZXRXZWlnaHQFB19xdEFzdFcJAMwIAgkBDEludGVnZXJFbnRyeQIFEWtfYmFzZUFzc2V0V2VpZ2h0BQdfYnNBc3RXBQNuaWwBCXVwZGF0ZUFtbQgHX3F0QXN0UgdfYnNBc3RSF190b3RhbFBvc2l0aW9uU2l6ZUFmdGVyFV9vcGVuSW50ZXJlc3ROb3Rpb25hbBZfdG90YWxMb25nUG9zaXRpb25TaXplF190b3RhbFNob3J0UG9zaXRpb25TaXplFl90b3RhbExvbmdPcGVuTm90aW9uYWwXX3RvdGFsU2hvcnRPcGVuTm90aW9uYWwEB19xdEFzdFcJAQZxdEFzdFcABAdfYnNBc3RXCQEGYnNBc3RXAAMJAQIhPQIJAGUCBRZfdG90YWxMb25nUG9zaXRpb25TaXplBRdfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQUXX3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIYSW52YWxpZCBBTU0gc3RhdGUgZGF0YTogCQCkAwEFFl90b3RhbExvbmdQb3NpdGlvblNpemUCBCArICAJAKQDAQUXX3RvdGFsU2hvcnRQb3NpdGlvblNpemUCBCAhPSAJAKQDAQUXX3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIJAM4IAgkAzggCCQERdXBkYXRlQW1tUmVzZXJ2ZXMCBQdfcXRBc3RSBQdfYnNBc3RSCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRNrX3RvdGFsUG9zaXRpb25TaXplBRdfdG90YWxQb3NpdGlvblNpemVBZnRlcgkAzAgCCQEMSW50ZWdlckVudHJ5AgUWa19vcGVuSW50ZXJlc3ROb3Rpb25hbAUVX29wZW5JbnRlcmVzdE5vdGlvbmFsCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRdrX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQUWX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUYa190b3RhbFNob3J0UG9zaXRpb25TaXplBRdfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUSa19vcGVuSW50ZXJlc3RMb25nBRZfdG90YWxMb25nT3Blbk5vdGlvbmFsCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRNrX29wZW5JbnRlcmVzdFNob3J0BRdfdG90YWxTaG9ydE9wZW5Ob3Rpb25hbAUDbmlsCQEKYXBwZW5kVHdhcAEJAQRkaXZkAgkBBG11bGQCBQdfcXRBc3RSBQdfcXRBc3RXCQEEbXVsZAIFB19ic0FzdFIFB19ic0FzdFcBDmRlbGV0ZVBvc2l0aW9uAQhfYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBQ5rX3Bvc2l0aW9uU2l6ZQUIX2FkZHJlc3MJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBDnRvQ29tcG9zaXRlS2V5AgUQa19wb3NpdGlvbk1hcmdpbgUIX2FkZHJlc3MJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBDnRvQ29tcG9zaXRlS2V5AgUWa19wb3NpdGlvbk9wZW5Ob3Rpb25hbAUIX2FkZHJlc3MJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBDnRvQ29tcG9zaXRlS2V5AgUua19wb3NpdGlvbkxhc3RVcGRhdGVkQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUIX2FkZHJlc3MJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBDnRvQ29tcG9zaXRlS2V5AgUPa19wb3NpdGlvbkFzc2V0BQhfYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBQ1rX3Bvc2l0aW9uRmVlBQhfYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBR5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRUaW1lc3RhbXAFCF9hZGRyZXNzBQNuaWwBCHdpdGhkcmF3AghfYWRkcmVzcwdfYW1vdW50BAdiYWxhbmNlCQDwBwIFBHRoaXMJAQpxdW90ZUFzc2V0AAMJAGYCBQdfYW1vdW50BQdiYWxhbmNlCQACAQkArAICCQCsAgIJAKwCAgITVW5hYmxlIHRvIHdpdGhkcmF3IAkApAMBBQdfYW1vdW50AhcgZnJvbSBjb250cmFjdCBiYWxhbmNlIAkApAMBBQdiYWxhbmNlCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFCF9hZGRyZXNzBQdfYW1vdW50CQEKcXVvdGVBc3NldAAFA25pbAENdXBkYXRlQmFsYW5jZQEBaQMJAGYCAAAFAWkJAAIBAgdCYWxhbmNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQlrX2JhbGFuY2UFAWkFA25pbAELdHJhbnNmZXJGZWUBAWkJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwkBDnN0YWtpbmdBZGRyZXNzAAUBaQkBCnF1b3RlQXNzZXQABQNuaWwBDmRvQnVybkFydGlmYWN0Ag1fYnVybkFydGlmYWN0AWkDBQ1fYnVybkFydGlmYWN0CQDMCAIJAQRCdXJuAgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCAkAkQMCCAUBaQhwYXltZW50cwABB2Fzc2V0SWQCEEludmFsaWQgYXJ0aWZhY3QAAQUDbmlsBQNuaWwWAWkBBXBhdXNlAAMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAhRJbnZhbGlkIHBhdXNlIHBhcmFtcwkAzAgCCQEMQm9vbGVhbkVudHJ5AgUIa19wYXVzZWQGBQNuaWwBaQEHdW5wYXVzZQADCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MACQACAQIWSW52YWxpZCB1bnBhdXNlIHBhcmFtcwkAzAgCCQEMQm9vbGVhbkVudHJ5AgUIa19wYXVzZWQHBQNuaWwBaQEMc2V0Q2xvc2VPbmx5AAMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAhtJbnZhbGlkIHNldENsb3NlT25seSBwYXJhbXMJAMwIAgkBDEJvb2xlYW5FbnRyeQIFC2tfY2xvc2VPbmx5BgUDbmlsAWkBDnVuc2V0Q2xvc2VPbmx5AAMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAh1JbnZhbGlkIHVuc2V0Q2xvc2VPbmx5IHBhcmFtcwkAzAgCCQEMQm9vbGVhbkVudHJ5AgULa19jbG9zZU9ubHkHBQNuaWwBaQEMYWRkTGlxdWlkaXR5ARFfcXVvdGVBc3NldEFtb3VudAMDCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MABgkAZwIAAAURX3F1b3RlQXNzZXRBbW91bnQJAAIBAhtJbnZhbGlkIGFkZExpcXVpZGl0eSBwYXJhbXMEB19xdEFzdFIJAQZxdEFzdFIABAdfYnNBc3RSCQEGYnNBc3RSAAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcABAVwcmljZQkBBGRpdmQCCQEEbXVsZAIFB19xdEFzdFIFB19xdEFzdFcJAQRtdWxkAgUHX2JzQXN0UgUHX2JzQXN0VwQLcXRBc3RSQWZ0ZXIJAGQCBQdfcXRBc3RSBRFfcXVvdGVBc3NldEFtb3VudAQUYmFzZUFzc2V0QW1vdW50VG9BZGQJAGUCCQEEZGl2ZAIJAQRtdWxkAgULcXRBc3RSQWZ0ZXIFB19xdEFzdFcFBXByaWNlBQdfYnNBc3RSBAtic0FzdFJBZnRlcgkAZAIFB19ic0FzdFIFFGJhc2VBc3NldEFtb3VudFRvQWRkBA0kdDA1NDc0NTU0ODk2CQEUZ2V0U3luY1Rlcm1pbmFsUHJpY2UDCQEOZ2V0T3JhY2xlUHJpY2UABQtxdEFzdFJBZnRlcgULYnNBc3RSQWZ0ZXIEE25ld1F1b3RlQXNzZXRXZWlnaHQIBQ0kdDA1NDc0NTU0ODk2Al8xBBJuZXdCYXNlQXNzZXRXZWlnaHQIBQ0kdDA1NDc0NTU0ODk2Al8yBA1tYXJnaW5Ub1ZhdWx0CAUNJHQwNTQ3NDU1NDg5NgJfMwQNZG9FeGNoYW5nZVBuTAMJAQIhPQIFDW1hcmdpblRvVmF1bHQAAAQNZG9FeGNoYW5nZVBuTAkA/AcECQEMdmF1bHRBZGRyZXNzAAIVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkCQDMCAIFDW1hcmdpblRvVmF1bHQFA25pbAUDbmlsAwkAAAIFDWRvRXhjaGFuZ2VQbkwFDWRvRXhjaGFuZ2VQbkwFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFDWRvRXhjaGFuZ2VQbkwFDWRvRXhjaGFuZ2VQbkwJAM4IAgkBEXVwZGF0ZUFtbVJlc2VydmVzAgULcXRBc3RSQWZ0ZXIFC2JzQXN0UkFmdGVyCQEQdXBkYXRlQW1tV2VpZ2h0cwIFE25ld1F1b3RlQXNzZXRXZWlnaHQFEm5ld0Jhc2VBc3NldFdlaWdodAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ9yZW1vdmVMaXF1aWRpdHkBEV9xdW90ZUFzc2V0QW1vdW50AwMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAGCQBnAgURX3F1b3RlQXNzZXRBbW91bnQAAAkAAgECHkludmFsaWQgcmVtb3ZlTGlxdWlkaXR5IHBhcmFtcwQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwAEBXByaWNlCQEEZGl2ZAIJAQRtdWxkAgUHX3F0QXN0UgUHX3F0QXN0VwkBBG11bGQCBQdfYnNBc3RSBQdfYnNBc3RXBAtxdEFzdFJBZnRlcgkAZQIFB19xdEFzdFIFEV9xdW90ZUFzc2V0QW1vdW50BBdiYXNlQXNzZXRBbW91bnRUb1JlbW92ZQkBA2FicwEJAGUCCQEEZGl2ZAIJAQRtdWxkAgULcXRBc3RSQWZ0ZXIFB19xdEFzdFcFBXByaWNlBQdfYnNBc3RSBAtic0FzdFJBZnRlcgkAZQIFB19ic0FzdFIFF2Jhc2VBc3NldEFtb3VudFRvUmVtb3ZlBA0kdDA1NTgyODU1OTc5CQEUZ2V0U3luY1Rlcm1pbmFsUHJpY2UDCQEOZ2V0T3JhY2xlUHJpY2UABQtxdEFzdFJBZnRlcgULYnNBc3RSQWZ0ZXIEE25ld1F1b3RlQXNzZXRXZWlnaHQIBQ0kdDA1NTgyODU1OTc5Al8xBBJuZXdCYXNlQXNzZXRXZWlnaHQIBQ0kdDA1NTgyODU1OTc5Al8yBA1tYXJnaW5Ub1ZhdWx0CAUNJHQwNTU4Mjg1NTk3OQJfMwQNZG9FeGNoYW5nZVBuTAMJAQIhPQIFDW1hcmdpblRvVmF1bHQAAAQNZG9FeGNoYW5nZVBuTAkA/AcECQEMdmF1bHRBZGRyZXNzAAIVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkCQDMCAIFDW1hcmdpblRvVmF1bHQFA25pbAUDbmlsAwkAAAIFDWRvRXhjaGFuZ2VQbkwFDWRvRXhjaGFuZ2VQbkwFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFDWRvRXhjaGFuZ2VQbkwFDWRvRXhjaGFuZ2VQbkwJAM4IAgkBEXVwZGF0ZUFtbVJlc2VydmVzAgULcXRBc3RSQWZ0ZXIFC2JzQXN0UkFmdGVyCQEQdXBkYXRlQW1tV2VpZ2h0cwIFE25ld1F1b3RlQXNzZXRXZWlnaHQFEm5ld0Jhc2VBc3NldFdlaWdodAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ5jaGFuZ2VTZXR0aW5ncw0QX2luaXRNYXJnaW5SYXRpbwRfbW1yFF9saXF1aWRhdGlvbkZlZVJhdGlvDl9mdW5kaW5nUGVyaW9kBF9mZWUMX3NwcmVhZExpbWl0D19tYXhQcmljZUltcGFjdBhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8PX21heFByaWNlU3ByZWFkEF9tYXhPcGVuTm90aW9uYWwUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQPX21heE9yYWNsZURlbGF5DF9yb2xsb3ZlckZlZQMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAh1JbnZhbGlkIGNoYW5nZVNldHRpbmdzIHBhcmFtcwkBDnVwZGF0ZVNldHRpbmdzDQUQX2luaXRNYXJnaW5SYXRpbwUEX21tcgUUX2xpcXVpZGF0aW9uRmVlUmF0aW8FDl9mdW5kaW5nUGVyaW9kBQRfZmVlBQxfc3ByZWFkTGltaXQFD19tYXhQcmljZUltcGFjdAUYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvBQ9fbWF4UHJpY2VTcHJlYWQFEF9tYXhPcGVuTm90aW9uYWwFFF9mZWVUb1N0YWtlcnNQZXJjZW50BQ9fbWF4T3JhY2xlRGVsYXkFDF9yb2xsb3ZlckZlZQFpAQppbml0aWFsaXplEgdfcXRBc3RSB19ic0FzdFIOX2Z1bmRpbmdQZXJpb2QQX2luaXRNYXJnaW5SYXRpbwRfbW1yFF9saXF1aWRhdGlvbkZlZVJhdGlvBF9mZWUPX2Jhc2VPcmFjbGVEYXRhEF9xdW90ZU9yYWNsZURhdGEMX2Nvb3JkaW5hdG9yDF9zcHJlYWRMaW1pdA9fbWF4UHJpY2VJbXBhY3QYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvD19tYXhQcmljZVNwcmVhZBBfbWF4T3Blbk5vdGlvbmFsFF9mZWVUb1N0YWtlcnNQZXJjZW50D19tYXhPcmFjbGVEZWxheQxfcm9sbG92ZXJGZWUDAwMDAwMDAwMDAwMDAwMDAwMJAGcCAAAFB19xdEFzdFIGCQBnAgAABQdfYnNBc3RSBgkAZwIAAAUOX2Z1bmRpbmdQZXJpb2QGCQBnAgAABRBfaW5pdE1hcmdpblJhdGlvBgkAZwIAAAUEX21tcgYJAGcCAAAFFF9saXF1aWRhdGlvbkZlZVJhdGlvBgkAZwIAAAUEX2ZlZQYJAGcCAAAFDF9zcHJlYWRMaW1pdAYJAGcCAAAFD19tYXhQcmljZUltcGFjdAYJAGcCAAAFGF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwYJAGcCAAAFD19tYXhQcmljZVNwcmVhZAYJAGcCAAAFEF9tYXhPcGVuTm90aW9uYWwGCQBnAgAABRRfZmVlVG9TdGFrZXJzUGVyY2VudAYJAGYCBRRfZmVlVG9TdGFrZXJzUGVyY2VudAUMREVDSU1BTF9VTklUBgkAZwIAAAUPX21heE9yYWNsZURlbGF5BgkAZwIAAAUMX3JvbGxvdmVyRmVlBgkBC2luaXRpYWxpemVkAAYJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECHUludmFsaWQgaW5pdGlhbGl6ZSBwYXJhbWV0ZXJzCQDOCAIJAM4IAgkAzggCCQDOCAIJAQl1cGRhdGVBbW0IBQdfcXRBc3RSBQdfYnNBc3RSAAAAAAAAAAAAAAAACQEOdXBkYXRlU2V0dGluZ3MNBRBfaW5pdE1hcmdpblJhdGlvBQRfbW1yBRRfbGlxdWlkYXRpb25GZWVSYXRpbwUOX2Z1bmRpbmdQZXJpb2QFBF9mZWUFDF9zcHJlYWRMaW1pdAUPX21heFByaWNlSW1wYWN0BRhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8FD19tYXhQcmljZVNwcmVhZAUQX21heE9wZW5Ob3Rpb25hbAUUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQFD19tYXhPcmFjbGVEZWxheQUMX3JvbGxvdmVyRmVlCQENdXBkYXRlRnVuZGluZwUJAGQCCQENbGFzdFRpbWVzdGFtcAAFDl9mdW5kaW5nUGVyaW9kAAAAAAAAAAAJAQ11cGRhdGVCYWxhbmNlAQAACQDMCAIJAQxCb29sZWFuRW50cnkCBQ1rX2luaXRpYWxpemVkBgkAzAgCCQELU3RyaW5nRW50cnkCBQxrX2Jhc2VPcmFjbGUFD19iYXNlT3JhY2xlRGF0YQkAzAgCCQELU3RyaW5nRW50cnkCBQ1rX3F1b3RlT3JhY2xlBRBfcXVvdGVPcmFjbGVEYXRhCQDMCAIJAQtTdHJpbmdFbnRyeQIFFGtfY29vcmRpbmF0b3JBZGRyZXNzCQClCAEJARFAZXh0ck5hdGl2ZSgxMDYyKQEFDF9jb29yZGluYXRvcgUDbmlsAWkBEGluY3JlYXNlUG9zaXRpb24ECl9kaXJlY3Rpb24JX2xldmVyYWdlE19taW5CYXNlQXNzZXRBbW91bnQIX3JlZkxpbmsEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQQZW5zdXJlQ2FsbGVkT25jZQkA/AcEBQR0aGlzAhBlbnN1cmVDYWxsZWRPbmNlBQNuaWwFA25pbAMJAAACBRBlbnN1cmVDYWxsZWRPbmNlBRBlbnN1cmVDYWxsZWRPbmNlBAdfdHJhZGVyCQEPZ2V0QWN0dWFsQ2FsbGVyAQUBaQQKX3Jhd0Ftb3VudAgJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQECF9hc3NldElkCAkAkQMCCAUBaQhwYXltZW50cwAAB2Fzc2V0SWQEC19hc3NldElkU3RyCQDYBAEJAQV2YWx1ZQEFCF9hc3NldElkBAxpc1F1b3RlQXNzZXQJAAACBQhfYXNzZXRJZAkBCnF1b3RlQXNzZXQAAwMDAwMDAwMDAwkBAiE9AgUKX2RpcmVjdGlvbgUIRElSX0xPTkcJAQIhPQIFCl9kaXJlY3Rpb24FCURJUl9TSE9SVAcGCQBnAgAABQpfcmF3QW1vdW50BgkBASEBCQELaW5pdGlhbGl6ZWQABgkBASEBBQxpc1F1b3RlQXNzZXQGCQEBIQEJARdpc1NhbWVBc3NldE9yTm9Qb3NpdGlvbgIFB190cmFkZXIFC19hc3NldElkU3RyBgkBASEBCQEWcmVxdWlyZU1vcmVNYXJnaW5SYXRpbwMJAQRkaXZkAgUMREVDSU1BTF9VTklUBQlfbGV2ZXJhZ2UJAQ9pbml0TWFyZ2luUmF0aW8ABgYJAQZwYXVzZWQABgkBCWNsb3NlT25seQAGCQEOaXNNYXJrZXRDbG9zZWQACQACAQIjSW52YWxpZCBpbmNyZWFzZVBvc2l0aW9uIHBhcmFtZXRlcnMEDSR0MDU5NzU3NTk5MDYJARhnZXRGb3JUcmFkZXJXaXRoQXJ0aWZhY3QCBQdfdHJhZGVyCQENZ2V0QXJ0aWZhY3RJZAEFAWkEC2FkanVzdGVkRmVlCAUNJHQwNTk3NTc1OTkwNgJfMQQMYnVybkFydGlmYWN0CAUNJHQwNTk3NTc1OTkwNgJfMgQHX2Ftb3VudAkBBGRpdmQCBQpfcmF3QW1vdW50CQBkAgkBBG11bGQCBQthZGp1c3RlZEZlZQUJX2xldmVyYWdlBQxERUNJTUFMX1VOSVQEE2Rpc3RyaWJ1dGVGZWVBbW91bnQJAGUCBQpfcmF3QW1vdW50BQdfYW1vdW50BA5yZWZlcnJlckZlZUFueQkA/AcECQEPcmVmZXJyYWxBZGRyZXNzAAIVYWNjZXB0UGF5bWVudFdpdGhMaW5rCQDMCAIFB190cmFkZXIJAMwIAgUIX3JlZkxpbmsFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABRNkaXN0cmlidXRlRmVlQW1vdW50BQNuaWwDCQAAAgUOcmVmZXJyZXJGZWVBbnkFDnJlZmVycmVyRmVlQW55BAtyZWZlcnJlckZlZQQHJG1hdGNoMAUOcmVmZXJyZXJGZWVBbnkDCQABAgUHJG1hdGNoMAIDSW50BAF4BQckbWF0Y2gwBQF4CQACAQITSW52YWxpZCByZWZlcnJlckZlZQQJZmVlQW1vdW50CQBlAgUTZGlzdHJpYnV0ZUZlZUFtb3VudAULcmVmZXJyZXJGZWUEDSR0MDYwNDAyNjA1NzAJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIED29sZFBvc2l0aW9uU2l6ZQgFDSR0MDYwNDAyNjA1NzACXzEEEW9sZFBvc2l0aW9uTWFyZ2luCAUNJHQwNjA0MDI2MDU3MAJfMgQXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA2MDQwMjYwNTcwAl8zBBRvbGRQb3NpdGlvbkxzdFVwZENQRggFDSR0MDYwNDAyNjA1NzACXzQEFG9sZFBvc2l0aW9uVGltZXN0YW1wCAUNJHQwNjA0MDI2MDU3MAJfNQQNaXNOZXdQb3NpdGlvbgkAAAIFD29sZFBvc2l0aW9uU2l6ZQAABA9pc1NhbWVEaXJlY3Rpb24DCQBmAgUPb2xkUG9zaXRpb25TaXplAAAJAAACBQpfZGlyZWN0aW9uBQhESVJfTE9ORwkAAAIFCl9kaXJlY3Rpb24FCURJUl9TSE9SVAQOZXhwYW5kRXhpc3RpbmcDCQEBIQEFDWlzTmV3UG9zaXRpb24FD2lzU2FtZURpcmVjdGlvbgcEBWlzQWRkCQAAAgUKX2RpcmVjdGlvbgUIRElSX0xPTkcEDSR0MDYwODU5NjM5ODADAwUNaXNOZXdQb3NpdGlvbgYFDmV4cGFuZEV4aXN0aW5nBAxvcGVuTm90aW9uYWwJAQRtdWxkAgUHX2Ftb3VudAUJX2xldmVyYWdlBA0kdDA2MTM2ODYxNTQxCQEJc3dhcElucHV0AgUFaXNBZGQFDG9wZW5Ob3Rpb25hbAQVYW1vdW50QmFzZUFzc2V0Qm91Z2h0CAUNJHQwNjEzNjg2MTU0MQJfMQQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDYxMzY4NjE1NDECXzIEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDYxMzY4NjE1NDECXzMEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA2MTM2ODYxNTQxAl80AwMJAQIhPQIFE19taW5CYXNlQXNzZXRBbW91bnQAAAkAZgIFE19taW5CYXNlQXNzZXRBbW91bnQJAQNhYnMBBRVhbW91bnRCYXNlQXNzZXRCb3VnaHQHCQACAQkArAICCQCsAgIJAKwCAgINTGltaXQgZXJyb3I6IAkApAMBCQEDYWJzAQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0AgMgPCAJAKQDAQUTX21pbkJhc2VBc3NldEFtb3VudAQPbmV3UG9zaXRpb25TaXplCQBkAgUPb2xkUG9zaXRpb25TaXplBRVhbW91bnRCYXNlQXNzZXRCb3VnaHQEGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyCQBkAgkBEG9wZW5JbnRlcmVzdExvbmcAAwkAZgIFD25ld1Bvc2l0aW9uU2l6ZQAABQxvcGVuTm90aW9uYWwAAAQbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCQBkAgkBEW9wZW5JbnRlcmVzdFNob3J0AAMJAGYCAAAFD25ld1Bvc2l0aW9uU2l6ZQUMb3Blbk5vdGlvbmFsAAAEDSR0MDYyMDg3NjIzNjIJATBjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50QW5kUm9sbG92ZXJGZWUFBQ9vbGRQb3NpdGlvblNpemUFEW9sZFBvc2l0aW9uTWFyZ2luBRRvbGRQb3NpdGlvbkxzdFVwZENQRgUUb2xkUG9zaXRpb25UaW1lc3RhbXAFB19hbW91bnQEDHJlbWFpbk1hcmdpbggFDSR0MDYyMDg3NjIzNjICXzEEAngxCAUNJHQwNjIwODc2MjM2MgJfMgQCeDIIBQ0kdDA2MjA4NzYyMzYyAl8zBAtyb2xsb3ZlckZlZQgFDSR0MDYyMDg3NjIzNjICXzQDCQEBIQEJARlyZXF1aXJlTm90T3ZlclNwcmVhZExpbWl0AgUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCQACAQIVT3ZlciBtYXggc3ByZWFkIGxpbWl0AwkBASEBCQEdcmVxdWlyZU5vdE92ZXJNYXhPcGVuTm90aW9uYWwCBRp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgUbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCQACAQIWT3ZlciBtYXggb3BlbiBub3Rpb25hbAkAoAoOBQ9uZXdQb3NpdGlvblNpemUFDHJlbWFpbk1hcmdpbgkAZAIFF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsBQxvcGVuTm90aW9uYWwJAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUPbmV3UG9zaXRpb25TaXplCQENbGFzdFRpbWVzdGFtcAAFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgkAZAIJARRvcGVuSW50ZXJlc3ROb3Rpb25hbAAFDG9wZW5Ob3Rpb25hbAkAZAIJARV0b3RhbExvbmdQb3NpdGlvblNpemUAAwkAZgIFD25ld1Bvc2l0aW9uU2l6ZQAACQEDYWJzAQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0AAAJAGQCCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQADCQBmAgAABQ9uZXdQb3NpdGlvblNpemUJAQNhYnMBBRVhbW91bnRCYXNlQXNzZXRCb3VnaHQAAAUadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIFG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgULcm9sbG92ZXJGZWUEDG9wZW5Ob3Rpb25hbAkBBG11bGQCBQdfYW1vdW50BQlfbGV2ZXJhZ2UEDSR0MDYzNjgwNjM3OTYJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIJAKUIAQgFAWkGY2FsbGVyBQ9QTkxfT1BUSU9OX1NQT1QEE29sZFBvc2l0aW9uTm90aW9uYWwIBQ0kdDA2MzY4MDYzNzk2Al8xBA11bnJlYWxpemVkUG5sCAUNJHQwNjM2ODA2Mzc5NgJfMgMJAGYCBRNvbGRQb3NpdGlvbk5vdGlvbmFsBQxvcGVuTm90aW9uYWwJAAIBAi5Vc2UgZGVjcmVhc2VQb3NpdGlvbiB0byBkZWNyZWFzZSBwb3NpdGlvbiBzaXplCQACAQIUQ2xvc2UgcG9zaXRpb24gZmlyc3QED25ld1Bvc2l0aW9uU2l6ZQgFDSR0MDYwODU5NjM5ODACXzEEF25ld1Bvc2l0aW9uUmVtYWluTWFyZ2luCAUNJHQwNjA4NTk2Mzk4MAJfMgQXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA2MDg1OTYzOTgwAl8zBBRuZXdQb3NpdGlvbkxhdGVzdENQRggFDSR0MDYwODU5NjM5ODACXzQEFG5ld1Bvc2l0aW9uVGltZXN0YW1wCAUNJHQwNjA4NTk2Mzk4MAJfNQQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNjA4NTk2Mzk4MAJfNgQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDYwODU5NjM5ODACXzcEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA2MDg1OTYzOTgwAl84BBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCAUNJHQwNjA4NTk2Mzk4MAJfOQQOdG90YWxMb25nQWZ0ZXIIBQ0kdDA2MDg1OTYzOTgwA18xMAQPdG90YWxTaG9ydEFmdGVyCAUNJHQwNjA4NTk2Mzk4MANfMTEEGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNjA4NTk2Mzk4MANfMTIEG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDYwODU5NjM5ODADXzEzBAtyb2xsb3ZlckZlZQgFDSR0MDYwODU5NjM5ODADXzE0BA0kdDA2Mzk4NjY0MDU3CQENZGlzdHJpYnV0ZUZlZQEJAGQCBQlmZWVBbW91bnQFC3JvbGxvdmVyRmVlBAxmZWVUb1N0YWtlcnMIBQ0kdDA2Mzk4NjY0MDU3Al8xBApmZWVUb1ZhdWx0CAUNJHQwNjM5ODY2NDA1NwJfMgQFc3Rha2UDCQBnAgUHX2Ftb3VudAULcm9sbG92ZXJGZWUJAPwHBAkBDHZhdWx0QWRkcmVzcwACCWFkZExvY2tlZAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAJAGUCBQdfYW1vdW50BQtyb2xsb3ZlckZlZQUDbmlsCQD8BwQJAQx2YXVsdEFkZHJlc3MAAg53aXRoZHJhd0xvY2tlZAkAzAgCCQBlAgULcm9sbG92ZXJGZWUFB19hbW91bnQFA25pbAUDbmlsAwkAAAIFBXN0YWtlBQVzdGFrZQQMZGVwb3NpdFZhdWx0CQD8BwQJAQx2YXVsdEFkZHJlc3MAAgdhZGRGcmVlBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUKZmVlVG9WYXVsdAUDbmlsAwkAAAIFDGRlcG9zaXRWYXVsdAUMZGVwb3NpdFZhdWx0BAlub3RpZnlGZWUJAPwHBAkBDG1pbmVyQWRkcmVzcwACCm5vdGlmeUZlZXMJAMwIAgUHX3RyYWRlcgkAzAgCBQlmZWVBbW91bnQFA25pbAUDbmlsAwkAAAIFCW5vdGlmeUZlZQUJbm90aWZ5RmVlBA5ub3RpZnlOb3Rpb25hbAkA/AcECQEMbWluZXJBZGRyZXNzAAIObm90aWZ5Tm90aW9uYWwJAMwIAgUHX3RyYWRlcgkAzAgCBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUDbmlsBQNuaWwDCQAAAgUObm90aWZ5Tm90aW9uYWwFDm5vdGlmeU5vdGlvbmFsCQDOCAIJAM4IAgkAzggCCQDOCAIJAM4IAgkAzggCCQEOdXBkYXRlUG9zaXRpb24GBQdfdHJhZGVyBQ9uZXdQb3NpdGlvblNpemUFF25ld1Bvc2l0aW9uUmVtYWluTWFyZ2luBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUUbmV3UG9zaXRpb25MYXRlc3RDUEYFFG5ld1Bvc2l0aW9uVGltZXN0YW1wCQEfaW5jcmVtZW50UG9zaXRpb25TZXF1ZW5jZU51bWJlcgIFDWlzTmV3UG9zaXRpb24FB190cmFkZXIJARF1cGRhdGVQb3NpdGlvbkZlZQMFDWlzTmV3UG9zaXRpb24FB190cmFkZXIFC2FkanVzdGVkRmVlCQEJdXBkYXRlQW1tCAUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyBRp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgUbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCQELdHJhbnNmZXJGZWUBBQxmZWVUb1N0YWtlcnMJAQ11cGRhdGVCYWxhbmNlAQkAZQIJAGQCCQEIY2JhbGFuY2UABQdfYW1vdW50BQtyb2xsb3ZlckZlZQkBDmRvQnVybkFydGlmYWN0AgUMYnVybkFydGlmYWN0BQFpCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCWFkZE1hcmdpbgAEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQQZW5zdXJlQ2FsbGVkT25jZQkA/AcEBQR0aGlzAhBlbnN1cmVDYWxsZWRPbmNlBQNuaWwFA25pbAMJAAACBRBlbnN1cmVDYWxsZWRPbmNlBRBlbnN1cmVDYWxsZWRPbmNlBAdfdHJhZGVyCQClCAEIBQFpBmNhbGxlcgQHX2Ftb3VudAgJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQECF9hc3NldElkCAkAkQMCCAUBaQhwYXltZW50cwAAB2Fzc2V0SWQEC19hc3NldElkU3RyCQDYBAEJAQV2YWx1ZQEFCF9hc3NldElkBAxpc1F1b3RlQXNzZXQJAAACBQhfYXNzZXRJZAkBCnF1b3RlQXNzZXQAAwMDAwMDAwkBASEBBQxpc1F1b3RlQXNzZXQGCQEBIQEJARNyZXF1aXJlT3BlblBvc2l0aW9uAQkApQgBCAUBaQZjYWxsZXIGCQEBIQEJAQtpc1NhbWVBc3NldAIFB190cmFkZXIFC19hc3NldElkU3RyBgkBASEBCQELaW5pdGlhbGl6ZWQABgkBBnBhdXNlZAAGCQEJY2xvc2VPbmx5AAYJAQ5pc01hcmtldENsb3NlZAAJAAIBAhxJbnZhbGlkIGFkZE1hcmdpbiBwYXJhbWV0ZXJzBA0kdDA2NjE2ODY2MzM2CQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBA9vbGRQb3NpdGlvblNpemUIBQ0kdDA2NjE2ODY2MzM2Al8xBBFvbGRQb3NpdGlvbk1hcmdpbggFDSR0MDY2MTY4NjYzMzYCXzIEF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNjYxNjg2NjMzNgJfMwQUb2xkUG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA2NjE2ODY2MzM2Al80BBRvbGRQb3NpdGlvblRpbWVzdGFtcAgFDSR0MDY2MTY4NjYzMzYCXzUEBXN0YWtlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAglhZGRMb2NrZWQFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABQdfYW1vdW50BQNuaWwDCQAAAgUFc3Rha2UFBXN0YWtlBAtyb2xsb3ZlckZlZQkBD2NhbGNSb2xsb3ZlckZlZQIFEW9sZFBvc2l0aW9uTWFyZ2luBRRvbGRQb3NpdGlvblRpbWVzdGFtcAQWZG9UcmFuc2ZlckZlZVRvU3Rha2VycwMJAGYCBQtyb2xsb3ZlckZlZQAABA0kdDA2NjYyMTY2NjgwCQENZGlzdHJpYnV0ZUZlZQEFC3JvbGxvdmVyRmVlBAxmZWVUb1N0YWtlcnMIBQ0kdDA2NjYyMTY2NjgwAl8xBApmZWVUb1ZhdWx0CAUNJHQwNjY2MjE2NjY4MAJfMgQHdW5zdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIOd2l0aGRyYXdMb2NrZWQJAMwIAgUMZmVlVG9TdGFrZXJzBQNuaWwFA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlBAtsb2NrQmFkRGVidAkA/AcECQEMdmF1bHRBZGRyZXNzAAIVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkCQDMCAIJAQEtAQUKZmVlVG9WYXVsdAUDbmlsBQNuaWwDCQAAAgULbG9ja0JhZERlYnQFC2xvY2tCYWREZWJ0CQELdHJhbnNmZXJGZWUBBQxmZWVUb1N0YWtlcnMJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBRZkb1RyYW5zZmVyRmVlVG9TdGFrZXJzBRZkb1RyYW5zZmVyRmVlVG9TdGFrZXJzCQDOCAIJAM4IAgkBDnVwZGF0ZVBvc2l0aW9uBgUHX3RyYWRlcgUPb2xkUG9zaXRpb25TaXplCQBkAgkAZQIFEW9sZFBvc2l0aW9uTWFyZ2luBQtyb2xsb3ZlckZlZQUHX2Ftb3VudAUXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwFFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCQENbGFzdFRpbWVzdGFtcAAJAQ11cGRhdGVCYWxhbmNlAQkAZQIJAGQCCQEIY2JhbGFuY2UABQdfYW1vdW50BQtyb2xsb3ZlckZlZQUWZG9UcmFuc2ZlckZlZVRvU3Rha2VycwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQxyZW1vdmVNYXJnaW4BB19hbW91bnQEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQQZW5zdXJlQ2FsbGVkT25jZQkA/AcEBQR0aGlzAhBlbnN1cmVDYWxsZWRPbmNlBQNuaWwFA25pbAMJAAACBRBlbnN1cmVDYWxsZWRPbmNlBRBlbnN1cmVDYWxsZWRPbmNlBAdfdHJhZGVyCQClCAEIBQFpBmNhbGxlcgMDAwMDCQBnAgAABQdfYW1vdW50BgkBASEBCQETcmVxdWlyZU9wZW5Qb3NpdGlvbgEFB190cmFkZXIGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAYJAQ5pc01hcmtldENsb3NlZAAJAAIBAh9JbnZhbGlkIHJlbW92ZU1hcmdpbiBwYXJhbWV0ZXJzBA0kdDA2Nzc5MjY3OTYwCQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBA9vbGRQb3NpdGlvblNpemUIBQ0kdDA2Nzc5MjY3OTYwAl8xBBFvbGRQb3NpdGlvbk1hcmdpbggFDSR0MDY3NzkyNjc5NjACXzIEF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNjc3OTI2Nzk2MAJfMwQUb2xkUG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA2Nzc5MjY3OTYwAl80BBRvbGRQb3NpdGlvblRpbWVzdGFtcAgFDSR0MDY3NzkyNjc5NjACXzUEDSR0MDY3OTY2NjgyMTUJATBjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50QW5kUm9sbG92ZXJGZWUFBQ9vbGRQb3NpdGlvblNpemUFEW9sZFBvc2l0aW9uTWFyZ2luBRRvbGRQb3NpdGlvbkxzdFVwZENQRgUUb2xkUG9zaXRpb25UaW1lc3RhbXAJAQEtAQUHX2Ftb3VudAQMcmVtYWluTWFyZ2luCAUNJHQwNjc5NjY2ODIxNQJfMQQHYmFkRGVidAgFDSR0MDY3OTY2NjgyMTUCXzIEDmZ1bmRpbmdQYXltZW50CAUNJHQwNjc5NjY2ODIxNQJfMwQLcm9sbG92ZXJGZWUIBQ0kdDA2Nzk2NjY4MjE1Al80AwkBAiE9AgUHYmFkRGVidAAACQACAQIdSW52YWxpZCByZW1vdmVkIG1hcmdpbiBhbW91bnQEC21hcmdpblJhdGlvCQEPY2FsY01hcmdpblJhdGlvAwUMcmVtYWluTWFyZ2luBQdiYWREZWJ0BRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAMJAQEhAQkBFnJlcXVpcmVNb3JlTWFyZ2luUmF0aW8DBQttYXJnaW5SYXRpbwkBD2luaXRNYXJnaW5SYXRpbwAGCQACAQkArAICCQCsAgIJAKwCAgIZVG9vIG11Y2ggbWFyZ2luIHJlbW92ZWQ6IAkApAMBBQttYXJnaW5SYXRpbwIDIDwgCQCkAwEJAQ9pbml0TWFyZ2luUmF0aW8ABA0kdDA2ODYwMTY4NjYwCQENZGlzdHJpYnV0ZUZlZQEFC3JvbGxvdmVyRmVlBAxmZWVUb1N0YWtlcnMIBQ0kdDA2ODYwMTY4NjYwAl8xBApmZWVUb1ZhdWx0CAUNJHQwNjg2MDE2ODY2MAJfMgQWZG9UcmFuc2ZlckZlZVRvU3Rha2VycwMJAGYCBQtyb2xsb3ZlckZlZQAABAtsb2NrQmFkRGVidAkA/AcECQEMdmF1bHRBZGRyZXNzAAIVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkCQDMCAIJAQEtAQUKZmVlVG9WYXVsdAUDbmlsBQNuaWwDCQAAAgULbG9ja0JhZERlYnQFC2xvY2tCYWREZWJ0CQELdHJhbnNmZXJGZWUBBQxmZWVUb1N0YWtlcnMJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBRZkb1RyYW5zZmVyRmVlVG9TdGFrZXJzBRZkb1RyYW5zZmVyRmVlVG9TdGFrZXJzBAd1bnN0YWtlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAg53aXRoZHJhd0xvY2tlZAkAzAgCCQBkAgUHX2Ftb3VudAUMZmVlVG9TdGFrZXJzBQNuaWwFA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlCQDOCAIJAM4IAgkAzggCCQEOdXBkYXRlUG9zaXRpb24GBQdfdHJhZGVyBQ9vbGRQb3NpdGlvblNpemUFDHJlbWFpbk1hcmdpbgUXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwJAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUPb2xkUG9zaXRpb25TaXplCQENbGFzdFRpbWVzdGFtcAAJAQh3aXRoZHJhdwIIBQFpBmNhbGxlcgUHX2Ftb3VudAkBDXVwZGF0ZUJhbGFuY2UBCQBlAgkAZQIJAQhjYmFsYW5jZQAFB19hbW91bnQFC3JvbGxvdmVyRmVlBRZkb1RyYW5zZmVyRmVlVG9TdGFrZXJzCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDWNsb3NlUG9zaXRpb24DBV9zaXplFF9taW5RdW90ZUFzc2V0QW1vdW50DF9hZGRUb01hcmdpbgQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBBBlbnN1cmVDYWxsZWRPbmNlCQD8BwQFBHRoaXMCEGVuc3VyZUNhbGxlZE9uY2UFA25pbAUDbmlsAwkAAAIFEGVuc3VyZUNhbGxlZE9uY2UFEGVuc3VyZUNhbGxlZE9uY2UEB190cmFkZXIJAQ9nZXRBY3R1YWxDYWxsZXIBBQFpBA5fdHJhZGVyQWRkcmVzcwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEFB190cmFkZXICDkludmFsaWQgY2FsbGVyBAtwb3NpdGlvbkZlZQkBDmdldFBvc2l0aW9uRmVlAQUHX3RyYWRlcgMDAwMDAwkBASEBCQETcmVxdWlyZU9wZW5Qb3NpdGlvbgEFB190cmFkZXIGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAYJAGcCAAAFBV9zaXplBgkAZgIAAAUUX21pblF1b3RlQXNzZXRBbW91bnQGCQEOaXNNYXJrZXRDbG9zZWQACQACAQIgSW52YWxpZCBjbG9zZVBvc2l0aW9uIHBhcmFtZXRlcnMEFG9sZFBvc2l0aW9uVGltZXN0YW1wCAkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgJfNQQNJHQwNzAzMTc3MDkwMgkBFWludGVybmFsQ2xvc2VQb3NpdGlvbgcFB190cmFkZXIFBV9zaXplBQtwb3NpdGlvbkZlZQUUX21pblF1b3RlQXNzZXRBbW91bnQFDF9hZGRUb01hcmdpbgYGBA9uZXdQb3NpdGlvblNpemUIBQ0kdDA3MDMxNzcwOTAyAl8xBBFuZXdQb3NpdGlvbk1hcmdpbggFDSR0MDcwMzE3NzA5MDICXzIEF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNzAzMTc3MDkwMgJfMwQUbmV3UG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA3MDMxNzcwOTAyAl80BA9wb3NpdGlvbkJhZERlYnQIBQ0kdDA3MDMxNzcwOTAyAl81BAtyZWFsaXplZFBubAgFDSR0MDcwMzE3NzA5MDICXzYEDm1hcmdpblRvVHJhZGVyCAUNJHQwNzAzMTc3MDkwMgJfNwQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDcwMzE3NzA5MDICXzgEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDcwMzE3NzA5MDICXzkEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA3MDMxNzcwOTAyA18xMAQZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcggFDSR0MDcwMzE3NzA5MDIDXzExBA50b3RhbExvbmdBZnRlcggFDSR0MDcwMzE3NzA5MDIDXzEyBA90b3RhbFNob3J0QWZ0ZXIIBQ0kdDA3MDMxNzcwOTAyA18xMwQadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA3MDMxNzcwOTAyA18xNAQbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNzAzMTc3MDkwMgNfMTUEC3JlYWxpemVkRmVlCAUNJHQwNzAzMTc3MDkwMgNfMTYDCQBmAgUPcG9zaXRpb25CYWREZWJ0AAAJAAIBAipJbnZhbGlkIGNsb3NlUG9zaXRpb24gcGFyYW1ldGVyczogYmFkIGRlYnQDCQBnAgUUb2xkUG9zaXRpb25UaW1lc3RhbXAJAQ1sYXN0VGltZXN0YW1wAAkAAgECU0ludmFsaWQgY2xvc2VQb3NpdGlvbiBwYXJhbWV0ZXJzOiB3YWl0IGF0IGxlYXN0IDEgYmxvY2sgYmVmb3JlIGNsb3NpbmcgdGhlIHBvc2l0aW9uBA5pc1BhcnRpYWxDbG9zZQkBAiE9AgUPbmV3UG9zaXRpb25TaXplAAAEDndpdGhkcmF3QW1vdW50CQBkAgUObWFyZ2luVG9UcmFkZXIFC3JlYWxpemVkRmVlBAphbW1CYWxhbmNlCQBlAgkBCGNiYWxhbmNlAAUOd2l0aGRyYXdBbW91bnQEDWFtbU5ld0JhbGFuY2UDCQBmAgAABQphbW1CYWxhbmNlAAAFCmFtbUJhbGFuY2UEB3Vuc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACDndpdGhkcmF3TG9ja2VkCQDMCAIFDndpdGhkcmF3QW1vdW50BQNuaWwFA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlBA0kdDA3MTU3NDcxNjMzCQENZGlzdHJpYnV0ZUZlZQEFC3JlYWxpemVkRmVlBAxmZWVUb1N0YWtlcnMIBQ0kdDA3MTU3NDcxNjMzAl8xBApmZWVUb1ZhdWx0CAUNJHQwNzE1NzQ3MTYzMwJfMgQMZGVwb3NpdFZhdWx0CQD8BwQJAQx2YXVsdEFkZHJlc3MAAgdhZGRGcmVlBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUKZmVlVG9WYXVsdAUDbmlsAwkAAAIFDGRlcG9zaXRWYXVsdAUMZGVwb3NpdFZhdWx0BAlub3RpZnlGZWUJAPwHBAkBDG1pbmVyQWRkcmVzcwACCm5vdGlmeUZlZXMJAMwIAgUHX3RyYWRlcgkAzAgCBQtyZWFsaXplZEZlZQUDbmlsBQNuaWwDCQAAAgUJbm90aWZ5RmVlBQlub3RpZnlGZWUEDm5vdGlmeU5vdGlvbmFsCQD8BwQJAQxtaW5lckFkZHJlc3MAAg5ub3RpZnlOb3Rpb25hbAkAzAgCBQdfdHJhZGVyCQDMCAIFF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBQNuaWwFA25pbAMJAAACBQ5ub3RpZnlOb3Rpb25hbAUObm90aWZ5Tm90aW9uYWwJAM4IAgkAzggCCQDOCAIJAM4IAgMFDmlzUGFydGlhbENsb3NlCQEOdXBkYXRlUG9zaXRpb24GBQdfdHJhZGVyBQ9uZXdQb3NpdGlvblNpemUFEW5ld1Bvc2l0aW9uTWFyZ2luBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUUbmV3UG9zaXRpb25Mc3RVcGRDUEYJAQ1sYXN0VGltZXN0YW1wAAkBDmRlbGV0ZVBvc2l0aW9uAQUHX3RyYWRlcgkBCXVwZGF0ZUFtbQgFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgUZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcgUOdG90YWxMb25nQWZ0ZXIFD3RvdGFsU2hvcnRBZnRlcgUadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIFG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgMJAGYCBQ5tYXJnaW5Ub1RyYWRlcgAACQEId2l0aGRyYXcCBQ5fdHJhZGVyQWRkcmVzcwUObWFyZ2luVG9UcmFkZXIFA25pbAkBDXVwZGF0ZUJhbGFuY2UBBQ1hbW1OZXdCYWxhbmNlCQELdHJhbnNmZXJGZWUBBQxmZWVUb1N0YWtlcnMJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEJbGlxdWlkYXRlAQdfdHJhZGVyBARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMED3Nwb3RNYXJnaW5SYXRpbwkBFmdldE1hcmdpblJhdGlvQnlPcHRpb24CBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QEFmxpcXVpZGF0aW9uTWFyZ2luUmF0aW8DCQEWaXNPdmVyRmx1Y3R1YXRpb25MaW1pdAAEEW9yYWNsZU1hcmdpblJhdGlvCQEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgIFB190cmFkZXIFEVBOTF9PUFRJT05fT1JBQ0xFCQEEdm1heAIFD3Nwb3RNYXJnaW5SYXRpbwURb3JhY2xlTWFyZ2luUmF0aW8FD3Nwb3RNYXJnaW5SYXRpbwMDAwMDCQEBIQEJARZyZXF1aXJlTW9yZU1hcmdpblJhdGlvAwUWbGlxdWlkYXRpb25NYXJnaW5SYXRpbwkBFm1haW50ZW5hbmNlTWFyZ2luUmF0aW8ABwYJAQEhAQkBE3JlcXVpcmVPcGVuUG9zaXRpb24BBQdfdHJhZGVyBgkBASEBCQELaW5pdGlhbGl6ZWQABgkBBnBhdXNlZAAGCQEOaXNNYXJrZXRDbG9zZWQACQACAQITVW5hYmxlIHRvIGxpcXVpZGF0ZQQUaXNQYXJ0aWFsTGlxdWlkYXRpb24DAwkAZgIFD3Nwb3RNYXJnaW5SYXRpbwkBE2xpcXVpZGF0aW9uRmVlUmF0aW8ACQBmAgkBF3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAAAABwkAZgIFDERFQ0lNQUxfVU5JVAkBF3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAAcED29sZFBvc2l0aW9uU2l6ZQgJAQtnZXRQb3NpdGlvbgEFB190cmFkZXICXzEED3Bvc2l0aW9uU2l6ZUFicwkBA2FicwEFD29sZFBvc2l0aW9uU2l6ZQQNJHQwNzM5NDY3NDI2OQMFFGlzUGFydGlhbExpcXVpZGF0aW9uBA9saXF1aWRhdGlvblNpemUJARtnZXRQYXJ0aWFsTGlxdWlkYXRpb25BbW91bnQCBQdfdHJhZGVyBQ9vbGRQb3NpdGlvblNpemUEEGxpcXVpZGF0aW9uUmF0aW8JAQRkaXZkAgkBA2FicwEFD2xpcXVpZGF0aW9uU2l6ZQUPcG9zaXRpb25TaXplQWJzCQCUCgIFEGxpcXVpZGF0aW9uUmF0aW8JAQNhYnMBBQ9saXF1aWRhdGlvblNpemUJAJQKAgAABQ9wb3NpdGlvblNpemVBYnMEEGxpcXVpZGF0aW9uUmF0aW8IBQ0kdDA3Mzk0Njc0MjY5Al8xBA9saXF1aWRhdGlvblNpemUIBQ0kdDA3Mzk0Njc0MjY5Al8yBA0kdDA3NDI3NTc0OTEzCQEVaW50ZXJuYWxDbG9zZVBvc2l0aW9uBwUHX3RyYWRlcgMFFGlzUGFydGlhbExpcXVpZGF0aW9uBQ9saXF1aWRhdGlvblNpemUFD3Bvc2l0aW9uU2l6ZUFicwkBE2xpcXVpZGF0aW9uRmVlUmF0aW8AAAAGBwYED25ld1Bvc2l0aW9uU2l6ZQgFDSR0MDc0Mjc1NzQ5MTMCXzEEEW5ld1Bvc2l0aW9uTWFyZ2luCAUNJHQwNzQyNzU3NDkxMwJfMgQXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA3NDI3NTc0OTEzAl8zBBRuZXdQb3NpdGlvbkxzdFVwZENQRggFDSR0MDc0Mjc1NzQ5MTMCXzQED3Bvc2l0aW9uQmFkRGVidAgFDSR0MDc0Mjc1NzQ5MTMCXzUEC3JlYWxpemVkUG5sCAUNJHQwNzQyNzU3NDkxMwJfNgQObWFyZ2luVG9UcmFkZXIIBQ0kdDA3NDI3NTc0OTEzAl83BBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNzQyNzU3NDkxMwJfOAQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNzQyNzU3NDkxMwJfOQQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDc0Mjc1NzQ5MTMDXzEwBBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCAUNJHQwNzQyNzU3NDkxMwNfMTEEDnRvdGFsTG9uZ0FmdGVyCAUNJHQwNzQyNzU3NDkxMwNfMTIED3RvdGFsU2hvcnRBZnRlcggFDSR0MDc0Mjc1NzQ5MTMDXzEzBBp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDc0Mjc1NzQ5MTMDXzE0BBt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA3NDI3NTc0OTEzA18xNQQSbGlxdWlkYXRpb25QZW5hbHR5CAUNJHQwNzQyNzU3NDkxMwNfMTYED2ZlZVRvTGlxdWlkYXRvcgkAaQIFEmxpcXVpZGF0aW9uUGVuYWx0eQACBApmZWVUb1ZhdWx0CQBlAgUSbGlxdWlkYXRpb25QZW5hbHR5BQ9mZWVUb0xpcXVpZGF0b3IECmFtbUJhbGFuY2UJAGUCCQEIY2JhbGFuY2UABRJsaXF1aWRhdGlvblBlbmFsdHkEDW5ld0FtbUJhbGFuY2UDCQBmAgAABQphbW1CYWxhbmNlAAAFCmFtbUJhbGFuY2UEC2xvY2tCYWREZWJ0AwkAZgIFD3Bvc2l0aW9uQmFkRGVidAAABAtsb2NrQmFkRGVidAkA/AcECQEMdmF1bHRBZGRyZXNzAAIVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkCQDMCAIJAGQCBQ9wb3NpdGlvbkJhZERlYnQFEmxpcXVpZGF0aW9uUGVuYWx0eQUDbmlsBQNuaWwDCQAAAgULbG9ja0JhZERlYnQFC2xvY2tCYWREZWJ0BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBQtsb2NrQmFkRGVidAULbG9ja0JhZERlYnQEB3Vuc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACDndpdGhkcmF3TG9ja2VkCQDMCAIFEmxpcXVpZGF0aW9uUGVuYWx0eQUDbmlsBQNuaWwDCQAAAgUHdW5zdGFrZQUHdW5zdGFrZQQQZGVwb3NpdEluc3VyYW5jZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIHYWRkRnJlZQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFCmZlZVRvVmF1bHQFA25pbAMJAAACBRBkZXBvc2l0SW5zdXJhbmNlBRBkZXBvc2l0SW5zdXJhbmNlBA5ub3RpZnlOb3Rpb25hbAkA/AcECQEMbWluZXJBZGRyZXNzAAIObm90aWZ5Tm90aW9uYWwJAMwIAgUHX3RyYWRlcgkAzAgCBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUDbmlsBQNuaWwDCQAAAgUObm90aWZ5Tm90aW9uYWwFDm5vdGlmeU5vdGlvbmFsCQDOCAIJAM4IAgkAzggCAwUUaXNQYXJ0aWFsTGlxdWlkYXRpb24JAQ51cGRhdGVQb3NpdGlvbgYFB190cmFkZXIFD25ld1Bvc2l0aW9uU2l6ZQURbmV3UG9zaXRpb25NYXJnaW4FF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBRRuZXdQb3NpdGlvbkxzdFVwZENQRgkBDWxhc3RUaW1lc3RhbXAACQEOZGVsZXRlUG9zaXRpb24BBQdfdHJhZGVyCQEJdXBkYXRlQW1tCAUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyBRp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgUbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCQEId2l0aGRyYXcCCAUBaQZjYWxsZXIFD2ZlZVRvTGlxdWlkYXRvcgkBDXVwZGF0ZUJhbGFuY2UBBQ1uZXdBbW1CYWxhbmNlCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCnBheUZ1bmRpbmcABARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEFWZ1bmRpbmdCbG9ja1RpbWVzdGFtcAkBGW5leHRGdW5kaW5nQmxvY2tUaW1lc3RhbXAAAwMDCQBmAgUVZnVuZGluZ0Jsb2NrVGltZXN0YW1wCQENbGFzdFRpbWVzdGFtcAAGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAkAAgEJAKwCAgkArAICCQCsAgICIUludmFsaWQgZnVuZGluZyBibG9jayB0aW1lc3RhbXA6IAkApAMBCQENbGFzdFRpbWVzdGFtcAACAyA8IAkApAMBBRVmdW5kaW5nQmxvY2tUaW1lc3RhbXAED3VuZGVybHlpbmdQcmljZQkBDmdldE9yYWNsZVByaWNlAAQNJHQwNzY5MDA3Njk2MgkBCmdldEZ1bmRpbmcABBRzaG9ydFByZW1pdW1GcmFjdGlvbggFDSR0MDc2OTAwNzY5NjICXzEEE2xvbmdQcmVtaXVtRnJhY3Rpb24IBQ0kdDA3NjkwMDc2OTYyAl8yCQENdXBkYXRlRnVuZGluZwUJAGQCBRVmdW5kaW5nQmxvY2tUaW1lc3RhbXAJARRmdW5kaW5nUGVyaW9kU2Vjb25kcwAJAGQCCQEjbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24ABRNsb25nUHJlbWl1bUZyYWN0aW9uCQBkAgkBJGxhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAFFHNob3J0UHJlbWl1bUZyYWN0aW9uCQEEZGl2ZAIFE2xvbmdQcmVtaXVtRnJhY3Rpb24FD3VuZGVybHlpbmdQcmljZQkBBGRpdmQCBRRzaG9ydFByZW1pdW1GcmFjdGlvbgUPdW5kZXJseWluZ1ByaWNlCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUABAdfcXRBc3RSCQEGcXRBc3RSAAQHX2JzQXN0UgkBBmJzQXN0UgAEDSR0MDc3Mzk0Nzc3NjAJARRnZXRTeW5jVGVybWluYWxQcmljZQMJAQ5nZXRPcmFjbGVQcmljZQAFB19xdEFzdFIFB19ic0FzdFIEE25ld1F1b3RlQXNzZXRXZWlnaHQIBQ0kdDA3NzM5NDc3NzYwAl8xBBJuZXdCYXNlQXNzZXRXZWlnaHQIBQ0kdDA3NzM5NDc3NzYwAl8yBA1tYXJnaW5Ub1ZhdWx0CAUNJHQwNzczOTQ3Nzc2MAJfMwQQbWFyZ2luVG9WYXVsdEFkagMDCQBmAgAABQ1tYXJnaW5Ub1ZhdWx0CQBmAgkBA2FicwEFDW1hcmdpblRvVmF1bHQJAQhjYmFsYW5jZQAHCQEBLQEJAQhjYmFsYW5jZQAFDW1hcmdpblRvVmF1bHQEDWRvRXhjaGFuZ2VQbkwDCQECIT0CBRBtYXJnaW5Ub1ZhdWx0QWRqAAAEDWRvRXhjaGFuZ2VQbkwJAPwHBAkBDHZhdWx0QWRkcmVzcwACFWV4Y2hhbmdlRnJlZUFuZExvY2tlZAkAzAgCBRBtYXJnaW5Ub1ZhdWx0QWRqBQNuaWwFA25pbAMJAAACBQ1kb0V4Y2hhbmdlUG5MBQ1kb0V4Y2hhbmdlUG5MBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBQ1kb0V4Y2hhbmdlUG5MBQ1kb0V4Y2hhbmdlUG5MCQDOCAIJAM4IAgkBDXVwZGF0ZUJhbGFuY2UBCQBkAgkBCGNiYWxhbmNlAAUQbWFyZ2luVG9WYXVsdEFkagkBEHVwZGF0ZUFtbVdlaWdodHMCBRNuZXdRdW90ZUFzc2V0V2VpZ2h0BRJuZXdCYXNlQXNzZXRXZWlnaHQJAQphcHBlbmRUd2FwAQkBBGRpdmQCCQEEbXVsZAIFB19xdEFzdFIFE25ld1F1b3RlQXNzZXRXZWlnaHQJAQRtdWxkAgUHX2JzQXN0UgUSbmV3QmFzZUFzc2V0V2VpZ2h0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBEGVuc3VyZUNhbGxlZE9uY2UAAwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQIiSW52YWxpZCBzYXZlQ3VycmVudFR4SWQgcGFyYW1ldGVycwQGbGFzdFR4CQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMFCGtfbGFzdFR4AgADCQECIT0CBQZsYXN0VHgJANgEAQgFAWkNdHJhbnNhY3Rpb25JZAkAzAgCCQELU3RyaW5nRW50cnkCBQhrX2xhc3RUeAUGbGFzdFR4BQNuaWwJAAIBAilDYW4gbm90IGNhbGwgdkFNTSBtZXRob2RzIHR3aWNlIGluIG9uZSB0eAFpASd2aWV3X2NhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQBB190cmFkZXIEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQNJHQwNzg5MTk3OTA0MwkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQMcG9zaXRpb25TaXplCAUNJHQwNzg5MTk3OTA0MwJfMQQOcG9zaXRpb25NYXJnaW4IBQ0kdDA3ODkxOTc5MDQzAl8yBANwb24IBQ0kdDA3ODkxOTc5MDQzAl8zBBFwb3NpdGlvbkxzdFVwZENQRggFDSR0MDc4OTE5NzkwNDMCXzQEEXBvc2l0aW9uVGltZXN0YW1wCAUNJHQwNzg5MTk3OTA0MwJfNQQNJHQwNzkwNDY3OTE0NwkBI2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sAgUHX3RyYWRlcgUPUE5MX09QVElPTl9TUE9UBBBwb3NpdGlvbk5vdGlvbmFsCAUNJHQwNzkwNDY3OTE0NwJfMQQNdW5yZWFsaXplZFBubAgFDSR0MDc5MDQ2NzkxNDcCXzIEDSR0MDc5MTUwNzkzNzQJATBjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50QW5kUm9sbG92ZXJGZWUFBQxwb3NpdGlvblNpemUFDnBvc2l0aW9uTWFyZ2luBRFwb3NpdGlvbkxzdFVwZENQRgURcG9zaXRpb25UaW1lc3RhbXAFDXVucmVhbGl6ZWRQbmwEDHJlbWFpbk1hcmdpbggFDSR0MDc5MTUwNzkzNzQCXzEEB2JhZERlYnQIBQ0kdDA3OTE1MDc5Mzc0Al8yBA5mdW5kaW5nUGF5bWVudAgFDSR0MDc5MTUwNzkzNzQCXzMEC3JvbGxvdmVyRmVlCAUNJHQwNzkxNTA3OTM3NAJfNAkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAQFzAQUMcmVtYWluTWFyZ2luCQEBcwEFDmZ1bmRpbmdQYXltZW50CQEBcwEJAQ5nZXRNYXJnaW5SYXRpbwEFB190cmFkZXIJAQFzAQUNdW5yZWFsaXplZFBubAkBAXMBBQdiYWREZWJ0CQEBcwEFEHBvc2l0aW9uTm90aW9uYWwJAQFzAQULcm9sbG92ZXJGZWUJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEVdmlld19nZXRQZWdBZGp1c3RDb3N0AQZfcHJpY2UEB19xdEFzdFIJAQZxdEFzdFIABAdfYnNBc3RSCQEGYnNBc3RSAAQGcmVzdWx0CQEUZ2V0U3luY1Rlcm1pbmFsUHJpY2UDBQZfcHJpY2UFB19xdEFzdFIFB19ic0FzdFIJAAIBCQCkAwEIBQZyZXN1bHQCXzMBaQEYdmlld19nZXRUZXJtaW5hbEFtbVByaWNlAAQNJHQwNzk4MTA3OTg5MQkBE2dldFRlcm1pbmFsQW1tU3RhdGUABBl0ZXJtaW5hbFF1b3RlQXNzZXRSZXNlcnZlCAUNJHQwNzk4MTA3OTg5MQJfMQQYdGVybWluYWxCYXNlQXNzZXRSZXNlcnZlCAUNJHQwNzk4MTA3OTg5MQJfMgQFcHJpY2UJAQRkaXZkAgkBBG11bGQCBRl0ZXJtaW5hbFF1b3RlQXNzZXRSZXNlcnZlCQEGcXRBc3RXAAkBBG11bGQCBRh0ZXJtaW5hbEJhc2VBc3NldFJlc2VydmUJAQZic0FzdFcACQACAQkApAMBBQVwcmljZQFpAQ92aWV3X2dldEZ1bmRpbmcABA91bmRlcmx5aW5nUHJpY2UJAQ5nZXRPcmFjbGVQcmljZQAEDSR0MDgwMTA2ODAxNjgJAQpnZXRGdW5kaW5nAAQUc2hvcnRQcmVtaXVtRnJhY3Rpb24IBQ0kdDA4MDEwNjgwMTY4Al8xBBNsb25nUHJlbWl1bUZyYWN0aW9uCAUNJHQwODAxMDY4MDE2OAJfMgQLbG9uZ0Z1bmRpbmcJAQRkaXZkAgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgUPdW5kZXJseWluZ1ByaWNlBAxzaG9ydEZ1bmRpbmcJAQRkaXZkAgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24FD3VuZGVybHlpbmdQcmljZQkAAgEJAKwCAgkArAICCQCsAgIJAQFzAQULbG9uZ0Z1bmRpbmcJAQFzAQUMc2hvcnRGdW5kaW5nCQEBcwEJARBnZXRUd2FwU3BvdFByaWNlAAkBAXMBCQEOZ2V0T3JhY2xlUHJpY2UAAWkBEGNvbXB1dGVTcG90UHJpY2UABARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEBnJlc3VsdAkBDGdldFNwb3RQcmljZQAJAJQKAgUDbmlsBQZyZXN1bHQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEfY29tcHV0ZUZlZUZvclRyYWRlcldpdGhBcnRpZmFjdAIHX3RyYWRlcgtfYXJ0aWZhY3RJZAQGcmVzdWx0CQEYZ2V0Rm9yVHJhZGVyV2l0aEFydGlmYWN0AgUHX3RyYWRlcgULX2FydGlmYWN0SWQJAJQKAgUDbmlsBQZyZXN1bHQBAnR4AQZ2ZXJpZnkABA5jb29yZGluYXRvclN0cgkAnQgCBQR0aGlzBRRrX2Nvb3JkaW5hdG9yQWRkcmVzcwMJAQlpc0RlZmluZWQBBQ5jb29yZGluYXRvclN0cgQFYWRtaW4JAJ0IAgkBEUBleHRyTmF0aXZlKDEwNjIpAQkBBXZhbHVlAQUOY29vcmRpbmF0b3JTdHIFD2tfYWRtaW5fYWRkcmVzcwMJAQlpc0RlZmluZWQBBQVhZG1pbgkBC3ZhbHVlT3JFbHNlAgkAmwgCCQERQGV4dHJOYXRpdmUoMTA2MikBCQEFdmFsdWUBBQVhZG1pbgkArAICCQCsAgIJAKwCAgIHc3RhdHVzXwkApQgBBQR0aGlzAgFfCQDYBAEIBQJ0eAJpZAcJAAIBAi51bmFibGUgdG8gdmVyaWZ5OiBhZG1pbiBub3Qgc2V0IGluIGNvb3JkaW5hdG9yCQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwAACAUCdHgPc2VuZGVyUHVibGljS2V5sx+Ksw==", "height": 2579401, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: EYHV7ZiDCAZQKS3uEHm5SaxFywZ9ECjFmQLRuBGZmnym Next: C3uNvt6wbSrYbmQQdmGrSnGM7Bh1vcbirJjBL9nuhX6G Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let k_baseOracle = "k_baseOracle"
55
66 let k_quoteOracle = "k_quoteOracle"
77
88 let k_balance = "k_balance"
99
1010 let k_sequence = "k_sequence"
1111
1212 let k_positionSize = "k_positionSize"
1313
1414 let k_positionMargin = "k_positionMargin"
1515
1616 let k_positionOpenNotional = "k_positionOpenNotional"
1717
1818 let k_positionLastUpdatedCumulativePremiumFraction = "k_positionFraction"
1919
2020 let k_positionSequence = "k_positionSequence"
2121
2222 let k_positionAsset = "k_positionAsset"
2323
2424 let k_positionFee = "k_positionFee"
2525
2626 let k_positionLastUpdatedTimestamp = "k_positionTimestamp"
2727
2828 let k_initialized = "k_initialized"
2929
3030 let k_paused = "k_paused"
3131
3232 let k_closeOnly = "k_closeOnly"
3333
3434 let k_fee = "k_fee"
3535
3636 let k_rolloverFee = "k_rollover_fee"
3737
3838 let k_fundingPeriod = "k_fundingPeriod"
3939
4040 let k_initMarginRatio = "k_initMarginRatio"
4141
4242 let k_maintenanceMarginRatio = "k_mmr"
4343
4444 let k_liquidationFeeRatio = "k_liquidationFeeRatio"
4545
4646 let k_partialLiquidationRatio = "k_partLiquidationRatio"
4747
4848 let k_spreadLimit = "k_spreadLimit"
4949
5050 let k_maxPriceImpact = "k_maxPriceImpact"
5151
5252 let k_maxPriceSpread = "k_maxPriceSpread"
5353
5454 let k_maxOpenNotional = "k_maxOpenNotional"
5555
5656 let k_feeToStakersPercent = "k_feeToStakersPercent"
5757
5858 let k_maxOracleDelay = "k_maxOracleDelay"
5959
6060 let k_fundingMode = "k_fundingMode"
6161
6262 let k_lastDataStr = "k_lastDataStr"
6363
6464 let k_lastMinuteId = "k_lastMinuteId"
6565
6666 let k_twapDataLastCumulativePrice = "k_twapDataLastCumulativePrice"
6767
6868 let k_twapDataLastPrice = "k_twapDataLastPrice"
6969
7070 let k_twapDataPreviousMinuteId = "k_twapDataPreviousMinuteId"
7171
7272 let k_latestLongCumulativePremiumFraction = "k_latestLongPremiumFraction"
7373
7474 let k_latestShortCumulativePremiumFraction = "k_latestShortPremiumFraction"
7575
7676 let k_nextFundingBlock = "k_nextFundingBlockMinTimestamp"
7777
7878 let k_longFundingRate = "k_longFundingRate"
7979
8080 let k_shortFundingRate = "k_shortFundingRate"
8181
8282 let k_quoteAssetReserve = "k_qtAstR"
8383
8484 let k_baseAssetReserve = "k_bsAstR"
8585
8686 let k_quoteAssetWeight = "k_qtAstW"
8787
8888 let k_baseAssetWeight = "k_bsAstW"
8989
9090 let k_totalPositionSize = "k_totalPositionSize"
9191
9292 let k_totalLongPositionSize = "k_totalLongPositionSize"
9393
9494 let k_totalShortPositionSize = "k_totalShortPositionSize"
9595
9696 let k_openInterestNotional = "k_openInterestNotional"
9797
9898 let k_openInterestShort = "k_openInterestShort"
9999
100100 let k_openInterestLong = "k_openInterestLong"
101101
102102 let k_lastTx = "k_lastTx"
103103
104104 let k_coordinatorAddress = "k_coordinatorAddress"
105105
106106 let k_vault_address = "k_vault_address"
107107
108108 let k_admin_address = "k_admin_address"
109109
110110 let k_quote_asset = "k_quote_asset"
111111
112112 let k_quote_staking = "k_quote_staking"
113113
114114 let k_staking_address = "k_staking_address"
115115
116116 let k_miner_address = "k_miner_address"
117117
118118 let k_orders_address = "k_orders_address"
119119
120120 let k_referral_address = "k_referral_address"
121121
122122 let k_exchange_address = "k_exchange_address"
123123
124124 let k_nft_manager_address = "k_nft_manager_address"
125125
126126 func toCompositeKey (_key,_address) = ((_key + "_") + _address)
127127
128128
129129 func coordinator () = valueOrErrorMessage(addressFromString(getStringValue(this, k_coordinatorAddress)), "Coordinator not set")
130130
131131
132132 func adminAddress () = addressFromString(getStringValue(coordinator(), k_admin_address))
133133
134134
135135 func quoteAsset () = fromBase58String(getStringValue(coordinator(), k_quote_asset))
136136
137137
138138 func quoteAssetStaking () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_quote_staking)), "Quote asset staking not set")
139139
140140
141141 func stakingAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_staking_address)), "Staking not set")
142142
143143
144144 func vaultAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_vault_address)), "Vault not set")
145145
146146
147147 func minerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_miner_address)), "Miner not set")
148148
149149
150150 func ordersAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_orders_address)), "Orders not set")
151151
152152
153153 func referralAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_referral_address)), "Referral not set")
154154
155155
156156 func nftManagerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_nft_manager_address)), "NFT Manager not set")
157157
158158
159159 let k_token_param = "k_token_param"
160160
161161 let k_token_type = "k_token_type"
162162
163163 let FEE_REDUCTION_TOKEN_TYPE = "fee_reduction"
164164
165165 let DIR_LONG = 1
166166
167167 let DIR_SHORT = 2
168168
169169 let TWAP_INTERVAL = 15
170170
171171 let SECONDS = 1000
172172
173173 let DECIMAL_NUMBERS = 6
174174
175175 let DECIMAL_UNIT = (1 * (((((10 * 10) * 10) * 10) * 10) * 10))
176176
177177 let MINUTES_IN_YEAR = (525600 * DECIMAL_UNIT)
178178
179179 let ONE_DAY = (86400 * DECIMAL_UNIT)
180180
181181 let PNL_OPTION_SPOT = 1
182182
183183 let PNL_OPTION_ORACLE = 2
184184
185185 func s (_x) = (toString(_x) + ",")
186186
187187
188188 func divd (_x,_y) = fraction(_x, DECIMAL_UNIT, _y, HALFEVEN)
189189
190190
191191 func muld (_x,_y) = fraction(_x, _y, DECIMAL_UNIT, HALFEVEN)
192192
193193
194194 func bdivd (_x,_y) = fraction(_x, toBigInt(DECIMAL_UNIT), _y, HALFEVEN)
195195
196196
197197 func bmuld (_x,_y) = fraction(_x, _y, toBigInt(DECIMAL_UNIT), HALFEVEN)
198198
199199
200200 func abs (_x) = if ((_x > 0))
201201 then _x
202202 else -(_x)
203203
204204
205205 func vmax (_x,_y) = if ((_x >= _y))
206206 then _x
207207 else _y
208208
209209
210210 func listToStr (_list) = if ((size(_list) == 0))
211211 then ""
212212 else makeString(_list, ",")
213213
214214
215215 func strToList (_str) = if ((_str == ""))
216216 then nil
217217 else split(_str, ",")
218218
219219
220220 func pushToQueue (_list,_maxSize,_value) = if ((size(_list) > _maxSize))
221221 then (removeByIndex(_list, 0) :+ _value)
222222 else (_list :+ _value)
223223
224224
225225 func int (k) = valueOrErrorMessage(getInteger(this, k), ("no value for " + k))
226226
227227
228228 func intOr (k,def) = valueOrElse(getInteger(this, k), def)
229229
230230
231231 func strA (_address,_key) = {
232232 let val = valueOrErrorMessage(getString(_address, _key), ("No value for key " + _key))
233233 val
234234 }
235235
236236
237237 func intA (_address,_key) = {
238238 let val = valueOrErrorMessage(getInteger(_address, _key), ("No value for key " + _key))
239239 val
240240 }
241241
242242
243243 let FUNDING_ASYMMETRIC = 1
244244
245245 let FUNDING_SYMMETRIC = 2
246246
247247 func cbalance () = int(k_balance)
248248
249249
250250 func fee () = int(k_fee)
251251
252252
253253 func rolloverFeeRate () = int(k_rolloverFee)
254254
255255
256256 func initMarginRatio () = int(k_initMarginRatio)
257257
258258
259259 func qtAstR () = int(k_quoteAssetReserve)
260260
261261
262262 func bsAstR () = int(k_baseAssetReserve)
263263
264264
265265 func qtAstW () = intOr(k_quoteAssetWeight, DECIMAL_UNIT)
266266
267267
268268 func bsAstW () = intOr(k_baseAssetWeight, DECIMAL_UNIT)
269269
270270
271271 func totalPositionSize () = int(k_totalPositionSize)
272272
273273
274274 func openInterestNotional () = int(k_openInterestNotional)
275275
276276
277277 func openInterestShort () = int(k_openInterestShort)
278278
279279
280280 func openInterestLong () = int(k_openInterestLong)
281281
282282
283283 func nextFundingBlockTimestamp () = int(k_nextFundingBlock)
284284
285285
286286 func fundingPeriodRaw () = int(k_fundingPeriod)
287287
288288
289289 func fundingPeriodDecimal () = (fundingPeriodRaw() * DECIMAL_UNIT)
290290
291291
292292 func fundingPeriodSeconds () = (fundingPeriodRaw() * SECONDS)
293293
294294
295295 func maintenanceMarginRatio () = int(k_maintenanceMarginRatio)
296296
297297
298298 func liquidationFeeRatio () = int(k_liquidationFeeRatio)
299299
300300
301301 func partialLiquidationRatio () = int(k_partialLiquidationRatio)
302302
303303
304304 func spreadLimit () = int(k_spreadLimit)
305305
306306
307307 func maxPriceImpact () = int(k_maxPriceImpact)
308308
309309
310310 func maxPriceSpread () = int(k_maxPriceSpread)
311311
312312
313313 func maxOpenNotional () = int(k_maxOpenNotional)
314314
315315
316316 func latestLongCumulativePremiumFraction () = int(k_latestLongCumulativePremiumFraction)
317317
318318
319319 func latestShortCumulativePremiumFraction () = int(k_latestShortCumulativePremiumFraction)
320320
321321
322322 func totalShortPositionSize () = int(k_totalShortPositionSize)
323323
324324
325325 func totalLongPositionSize () = int(k_totalLongPositionSize)
326326
327327
328328 func lastSequence () = intOr(k_sequence, 0)
329329
330330
331331 func feeToStakersPercent () = int(k_feeToStakersPercent)
332332
333333
334334 func maxOracleDelay () = int(k_maxOracleDelay)
335335
336336
337337 func fundingMode () = intOr(k_fundingMode, FUNDING_ASYMMETRIC)
338338
339339
340340 func lastTimestamp () = lastBlock.timestamp
341341
342342
343343 func getActualCaller (i) = valueOrElse(getString(ordersAddress(), "k_sender"), toString(i.caller))
344344
345345
346346 func requireMoreMarginRatio (_marginRatio,_baseMarginRatio,_largerThanOrEqualTo) = {
347347 let remainingMarginRatio = (_marginRatio - _baseMarginRatio)
348348 if (if (_largerThanOrEqualTo)
349349 then (0 > remainingMarginRatio)
350350 else false)
351351 then throw(((("Invalid margin: " + toString(_marginRatio)) + " < ") + toString(_baseMarginRatio)))
352352 else if (if (!(_largerThanOrEqualTo))
353353 then (remainingMarginRatio >= 0)
354354 else false)
355355 then throw(((("Invalid margin: " + toString(_marginRatio)) + " > ") + toString(_baseMarginRatio)))
356356 else true
357357 }
358358
359359
360360 func latestCumulativePremiumFraction (_positionSize) = if ((_positionSize == 0))
361361 then throw("Should not be called with _positionSize == 0")
362362 else if ((_positionSize > 0))
363363 then latestLongCumulativePremiumFraction()
364364 else latestShortCumulativePremiumFraction()
365365
366366
367367 func getPosition (_trader) = {
368368 let positionSizeOpt = getInteger(this, toCompositeKey(k_positionSize, _trader))
369369 match positionSizeOpt {
370370 case positionSize: Int =>
371371 $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)))
372372 case _ =>
373373 $Tuple5(0, 0, 0, 0, 0)
374374 }
375375 }
376376
377377
378378 func getPositionAsset (_trader) = {
379379 let positionAssetOpt = getString(this, toCompositeKey(k_positionAsset, _trader))
380380 match positionAssetOpt {
381381 case positionAsset: String =>
382382 positionAsset
383383 case _ =>
384384 toBase58String(quoteAsset())
385385 }
386386 }
387387
388388
389389 func getPositionFee (_trader) = {
390390 let positionFeeOpt = getInteger(this, toCompositeKey(k_positionFee, _trader))
391391 match positionFeeOpt {
392392 case positionFee: Int =>
393393 positionFee
394394 case _ =>
395395 fee()
396396 }
397397 }
398398
399399
400400 func requireOpenPosition (_trader) = if ((getPosition(_trader)._1 == 0))
401401 then throw("No open position")
402402 else true
403403
404404
405405 func getOracleData (key) = {
406406 let oracleDataStr = getString(this, key)
407407 if (if (isDefined(oracleDataStr))
408408 then (value(oracleDataStr) != "")
409409 else false)
410410 then {
411411 let oracleData = split(value(oracleDataStr), ",")
412412 let oracleAddress = valueOrErrorMessage(addressFromString(oracleData[0]), ("Invalid oracle address in: " + value(oracleDataStr)))
413413 let priceKey = oracleData[1]
414414 let blockKey = oracleData[2]
415415 let openKey = oracleData[3]
416416 $Tuple4(oracleAddress, priceKey, blockKey, openKey)
417417 }
418418 else unit
419419 }
420420
421421
422422 func initialized () = valueOrElse(getBoolean(this, k_initialized), false)
423423
424424
425425 func paused () = valueOrElse(getBoolean(this, k_paused), false)
426426
427427
428428 func closeOnly () = valueOrElse(getBoolean(this, k_closeOnly), false)
429429
430430
431431 func updateReserve (_isAdd,_quoteAssetAmount,_baseAssetAmount) = if (_isAdd)
432432 then {
433433 let newBase = (bsAstR() - _baseAssetAmount)
434434 if ((0 >= newBase))
435435 then throw("Tx lead to base asset reserve <= 0, revert")
436436 else $Tuple3((qtAstR() + _quoteAssetAmount), newBase, (totalPositionSize() + _baseAssetAmount))
437437 }
438438 else {
439439 let newQuote = (qtAstR() - _quoteAssetAmount)
440440 if ((0 >= newQuote))
441441 then throw("Tx lead to base quote reserve <= 0, revert")
442442 else $Tuple3(newQuote, (bsAstR() + _baseAssetAmount), (totalPositionSize() - _baseAssetAmount))
443443 }
444444
445445
446446 func calcInvariant (_qtAstR,_bsAstR) = {
447447 let bqtAstR = toBigInt(_qtAstR)
448448 let bbsAstR = toBigInt(_bsAstR)
449449 bmuld(bqtAstR, bbsAstR)
450450 }
451451
452452
453453 func swapInput (_isAdd,_quoteAssetAmount) = {
454454 let _qtAstR = qtAstR()
455455 let _bsAstR = bsAstR()
456456 let _qtAstW = qtAstW()
457457 let _bsAstW = bsAstW()
458458 let quoteAssetAmountAdjusted = divd(_quoteAssetAmount, _qtAstW)
459459 let k = calcInvariant(_qtAstR, _bsAstR)
460460 let quoteAssetReserveAfter = if (_isAdd)
461461 then (_qtAstR + quoteAssetAmountAdjusted)
462462 else (_qtAstR - quoteAssetAmountAdjusted)
463463 let baseAssetReserveAfter = toInt(bdivd(k, toBigInt(quoteAssetReserveAfter)))
464464 let amountBaseAssetBoughtAbs = abs((baseAssetReserveAfter - _bsAstR))
465465 let amountBaseAssetBought = if (_isAdd)
466466 then amountBaseAssetBoughtAbs
467467 else -(amountBaseAssetBoughtAbs)
468468 let $t01687717047 = updateReserve(_isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
469469 let quoteAssetReserveAfter1 = $t01687717047._1
470470 let baseAssetReserveAfter1 = $t01687717047._2
471471 let totalPositionSizeAfter1 = $t01687717047._3
472472 let priceBefore = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
473473 let marketPrice = divd(_quoteAssetAmount, amountBaseAssetBoughtAbs)
474474 let priceDiff = abs((priceBefore - marketPrice))
475475 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
476476 let maxPriceImpactValue = maxPriceImpact()
477477 if ((priceImpact > maxPriceImpactValue))
478478 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)))
479479 else $Tuple4(amountBaseAssetBought, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1)
480480 }
481481
482482
483483 func calcRolloverFee (_oldPositionMargin,_oldPositionLastUpdatedTimestamp) = {
484484 let positionMinutes = ((((lastTimestamp() - _oldPositionLastUpdatedTimestamp) / 1000) / 60) * DECIMAL_UNIT)
485485 let rolloverFee = divd(muld(muld(_oldPositionMargin, positionMinutes), rolloverFeeRate()), MINUTES_IN_YEAR)
486486 rolloverFee
487487 }
488488
489489
490490 func calcRemainMarginWithFundingPaymentAndRolloverFee (_oldPositionSize,_oldPositionMargin,_oldPositionCumulativePremiumFraction,_oldPositionLastUpdatedTimestamp,_marginDelta) = {
491491 let fundingPayment = if ((_oldPositionSize != 0))
492492 then {
493493 let _latestCumulativePremiumFraction = latestCumulativePremiumFraction(_oldPositionSize)
494494 muld((_latestCumulativePremiumFraction - _oldPositionCumulativePremiumFraction), _oldPositionSize)
495495 }
496496 else 0
497497 let rolloverFee = calcRolloverFee(_oldPositionMargin, _oldPositionLastUpdatedTimestamp)
498498 let signedMargin = (((_marginDelta - rolloverFee) - fundingPayment) + _oldPositionMargin)
499499 let $t01930219429 = if ((0 > signedMargin))
500500 then $Tuple2(0, abs(signedMargin))
501501 else $Tuple2(abs(signedMargin), 0)
502502 let remainMargin = $t01930219429._1
503503 let badDebt = $t01930219429._2
504504 $Tuple4(remainMargin, badDebt, fundingPayment, rolloverFee)
505505 }
506506
507507
508508 func swapOutputWithReserves (_isAdd,_baseAssetAmount,_checkMaxPriceImpact,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
509509 let priceBefore = divd(muld(_quoteAssetReserve, _quoteAssetWeight), muld(_baseAssetReserve, _baseAssetWeight))
510510 if ((_baseAssetAmount == 0))
511511 then throw("Invalid base asset amount")
512512 else {
513513 let k = calcInvariant(_quoteAssetReserve, _baseAssetReserve)
514514 let baseAssetPoolAmountAfter = if (_isAdd)
515515 then (_baseAssetReserve + _baseAssetAmount)
516516 else (_baseAssetReserve - _baseAssetAmount)
517517 let quoteAssetAfter = toInt(bdivd(k, toBigInt(baseAssetPoolAmountAfter)))
518518 let quoteAssetDelta = abs((quoteAssetAfter - _quoteAssetReserve))
519519 let quoteAssetSold = muld(quoteAssetDelta, _quoteAssetWeight)
520520 let maxPriceImpactValue = maxPriceImpact()
521521 let $t02069120853 = updateReserve(!(_isAdd), quoteAssetDelta, _baseAssetAmount)
522522 let quoteAssetReserveAfter1 = $t02069120853._1
523523 let baseAssetReserveAfter1 = $t02069120853._2
524524 let totalPositionSizeAfter1 = $t02069120853._3
525525 let marketPrice = divd(quoteAssetSold, _baseAssetAmount)
526526 let priceDiff = abs((priceBefore - marketPrice))
527527 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
528528 if (if ((priceImpact > maxPriceImpactValue))
529529 then _checkMaxPriceImpact
530530 else false)
531531 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)))
532532 else $Tuple7(quoteAssetSold, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1, (totalLongPositionSize() - (if (_isAdd)
533533 then abs(_baseAssetAmount)
534534 else 0)), (totalShortPositionSize() - (if (!(_isAdd))
535535 then abs(_baseAssetAmount)
536536 else 0)), priceImpact)
537537 }
538538 }
539539
540540
541541 func swapOutput (_isAdd,_baseAssetAmount,_checkMaxPriceImpact) = swapOutputWithReserves(_isAdd, _baseAssetAmount, _checkMaxPriceImpact, qtAstR(), qtAstW(), bsAstR(), bsAstW())
542542
543543
544544 func getOraclePriceValue (oracle,priceKey,blockKey) = {
545545 let lastValue = valueOrErrorMessage(getInteger(oracle, priceKey), ((("Can not get oracle price. Oracle: " + toString(oracle)) + " key: ") + priceKey))
546546 if ((blockKey != ""))
547547 then {
548548 let currentBlock = lastBlock.height
549549 let lastOracleBlock = valueOrErrorMessage(getInteger(oracle, blockKey), ((("Can not get oracle block. Oracle: " + toString(oracle)) + " key: ") + blockKey))
550550 if (((currentBlock - lastOracleBlock) > maxOracleDelay()))
551551 then throw(((("Oracle stale data. Last oracle block: " + toString(lastOracleBlock)) + " current block: ") + toString(currentBlock)))
552552 else lastValue
553553 }
554554 else lastValue
555555 }
556556
557557
558558 func getOraclePrice () = {
559559 let baseOracle = valueOrErrorMessage(getOracleData(k_baseOracle), "No base asset oracle data")
560560 let baseOraclePrice = getOraclePriceValue(baseOracle._1, baseOracle._2, baseOracle._3)
561561 let quoteOracle = getOracleData(k_quoteOracle)
562562 let quoteOraclePrice = if (isDefined(quoteOracle))
563563 then {
564564 let quoteOracleV = value(quoteOracle)
565565 getOraclePriceValue(quoteOracleV._1, quoteOracleV._2, quoteOracleV._3)
566566 }
567567 else DECIMAL_UNIT
568568 divd(baseOraclePrice, quoteOraclePrice)
569569 }
570570
571571
572572 func isMarketClosed () = {
573573 let baseOracle = valueOrErrorMessage(getOracleData(k_baseOracle), "No base asset oracle data")
574574 let oracle = baseOracle._1
575575 let openKey = baseOracle._4
576576 if ((openKey != ""))
577577 then {
578578 let isOpen = valueOrErrorMessage(getBoolean(oracle, openKey), ((("Can not get oracle is open/closed. Oracle: " + toString(oracle)) + " key: ") + openKey))
579579 !(isOpen)
580580 }
581581 else false
582582 }
583583
584584
585585 func absPriceDiff (_oraclePrice,_quoteAssetReserve,_baseAssetReserve,_qtAstW,_bsAstW) = {
586586 let priceAfter = divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
587587 let averagePrice = divd((_oraclePrice + priceAfter), (2 * DECIMAL_UNIT))
588588 let absPriceDiff = divd(abs((_oraclePrice - priceAfter)), averagePrice)
589589 absPriceDiff
590590 }
591591
592592
593593 func requireNotOverSpreadLimit (_quoteAssetReserve,_baseAssetReserve) = {
594594 let oraclePrice = getOraclePrice()
595595 let _qtAstW = qtAstW()
596596 let _bsAstW = bsAstW()
597597 let absPriceDiffBefore = absPriceDiff(oraclePrice, qtAstR(), bsAstR(), _qtAstW, _bsAstW)
598598 let absPriceDiffAfter = absPriceDiff(oraclePrice, _quoteAssetReserve, _baseAssetReserve, _qtAstW, _bsAstW)
599599 if (if ((absPriceDiffAfter > maxPriceSpread()))
600600 then (absPriceDiffAfter > absPriceDiffBefore)
601601 else false)
602602 then throw(((("Price spread " + toString(absPriceDiffAfter)) + " > max price spread ") + toString(maxPriceSpread())))
603603 else true
604604 }
605605
606606
607607 func requireNotOverMaxOpenNotional (_longOpenNotional,_shortOpenNotional) = {
608608 let _maxOpenNotional = maxOpenNotional()
609609 if ((_longOpenNotional > _maxOpenNotional))
610610 then throw(((("Long open notional " + toString(_longOpenNotional)) + " > max open notional ") + toString(_maxOpenNotional)))
611611 else if ((_shortOpenNotional > _maxOpenNotional))
612612 then throw(((("Short open notional " + toString(_shortOpenNotional)) + " > max open notional ") + toString(_maxOpenNotional)))
613613 else true
614614 }
615615
616616
617617 func getSpotPrice () = {
618618 let _quoteAssetReserve = qtAstR()
619619 let _baseAssetReserve = bsAstR()
620620 let _qtAstW = qtAstW()
621621 let _bsAstW = bsAstW()
622622 divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
623623 }
624624
625625
626626 func isOverFluctuationLimit () = {
627627 let oraclePrice = getOraclePrice()
628628 let currentPrice = getSpotPrice()
629629 (divd(abs((oraclePrice - currentPrice)), oraclePrice) > spreadLimit())
630630 }
631631
632632
633633 func getPositionAdjustedOpenNotional (_positionSize,_option,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
634634 let positionSizeAbs = abs(_positionSize)
635635 let isShort = (0 > _positionSize)
636636 let positionNotional = if ((_option == PNL_OPTION_SPOT))
637637 then {
638638 let outPositionNotional = swapOutputWithReserves(!(isShort), positionSizeAbs, false, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)._1
639639 outPositionNotional
640640 }
641641 else muld(positionSizeAbs, getOraclePrice())
642642 positionNotional
643643 }
644644
645645
646646 func getPositionNotionalAndUnrealizedPnlByValues (_positionSize,_positionOpenNotional,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight,_option) = if ((_positionSize == 0))
647647 then throw("Invalid position size")
648648 else {
649649 let isShort = (0 > _positionSize)
650650 let positionNotional = getPositionAdjustedOpenNotional(_positionSize, _option, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
651651 let unrealizedPnl = if (isShort)
652652 then (_positionOpenNotional - positionNotional)
653653 else (positionNotional - _positionOpenNotional)
654654 $Tuple2(positionNotional, unrealizedPnl)
655655 }
656656
657657
658658 func getPositionNotionalAndUnrealizedPnl (_trader,_option) = {
659659 let $t02873128859 = getPosition(_trader)
660660 let positionSize = $t02873128859._1
661661 let positionMargin = $t02873128859._2
662662 let positionOpenNotional = $t02873128859._3
663663 let positionLstUpdCPF = $t02873128859._4
664664 getPositionNotionalAndUnrealizedPnlByValues(positionSize, positionOpenNotional, qtAstR(), qtAstW(), bsAstR(), bsAstW(), _option)
665665 }
666666
667667
668668 func calcMarginRatio (_remainMargin,_badDebt,_positionNotional) = divd((_remainMargin - _badDebt), _positionNotional)
669669
670670
671671 func getMarginRatioByOption (_trader,_option) = {
672672 let $t02937429515 = getPosition(_trader)
673673 let positionSize = $t02937429515._1
674674 let positionMargin = $t02937429515._2
675675 let pon = $t02937429515._3
676676 let positionLastUpdatedCPF = $t02937429515._4
677677 let positionTimestamp = $t02937429515._5
678678 let $t02952129614 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
679679 let positionNotional = $t02952129614._1
680680 let unrealizedPnl = $t02952129614._2
681681 let $t02961929831 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLastUpdatedCPF, positionTimestamp, unrealizedPnl)
682682 let remainMargin = $t02961929831._1
683683 let badDebt = $t02961929831._2
684684 calcMarginRatio(remainMargin, badDebt, positionNotional)
685685 }
686686
687687
688688 func getMarginRatio (_trader) = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
689689
690690
691691 func getPartialLiquidationAmount (_trader,_positionSize) = {
692692 let maximumRatio = vmax(partialLiquidationRatio(), (DECIMAL_UNIT - divd(getMarginRatio(_trader), maintenanceMarginRatio())))
693693 let maxExchangedPositionSize = muld(abs(_positionSize), maximumRatio)
694694 let swapResult = swapOutput((_positionSize > 0), maxExchangedPositionSize, false)
695695 let maxExchangedQuoteAssetAmount = swapResult._1
696696 let priceImpact = swapResult._7
697697 if ((maxPriceImpact() > priceImpact))
698698 then maxExchangedPositionSize
699699 else muld(abs(_positionSize), partialLiquidationRatio())
700700 }
701701
702702
703703 func internalClosePosition (_trader,_size,_fee,_minQuoteAssetAmount,_addToMargin,_checkMaxPriceImpact,_liquidate) = {
704704 let $t03089831054 = getPosition(_trader)
705705 let oldPositionSize = $t03089831054._1
706706 let oldPositionMargin = $t03089831054._2
707707 let oldPositionOpenNotional = $t03089831054._3
708708 let oldPositionLstUpdCPF = $t03089831054._4
709709 let oldPositionTimestamp = $t03089831054._5
710710 let isLongPosition = (oldPositionSize > 0)
711711 let absOldPositionSize = abs(oldPositionSize)
712712 if (if ((absOldPositionSize >= _size))
713713 then (_size > 0)
714714 else false)
715715 then {
716716 let isPartialClose = (absOldPositionSize > _size)
717717 let $t03134631797 = swapOutput((oldPositionSize > 0), _size, _checkMaxPriceImpact)
718718 let exchangedQuoteAssetAmount = $t03134631797._1
719719 let quoteAssetReserveAfter = $t03134631797._2
720720 let baseAssetReserveAfter = $t03134631797._3
721721 let totalPositionSizeAfter = $t03134631797._4
722722 let exchangedPositionSize = if ((oldPositionSize > 0))
723723 then -(_size)
724724 else _size
725725 let $t03201232219 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
726726 let oldPositionNotional = $t03201232219._1
727727 let unrealizedPnl = $t03201232219._2
728728 let realizedRatio = divd(abs(exchangedPositionSize), absOldPositionSize)
729729 let realizedPnl = muld(unrealizedPnl, realizedRatio)
730730 let $t03256032806 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, unrealizedPnl)
731731 let remainMarginBefore = $t03256032806._1
732732 let x1 = $t03256032806._2
733733 let x2 = $t03256032806._3
734734 let rolloverFee = $t03256032806._4
735735 let positionBadDebt = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, realizedPnl)._2
736736 let realizedCloseFee = muld(muld(oldPositionNotional, realizedRatio), _fee)
737737 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
738738 let remainOpenNotional = if ((oldPositionSize > 0))
739739 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
740740 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
741741 let newPositionSize = (oldPositionSize + exchangedPositionSize)
742742 let $t03421234598 = if ((newPositionSize == 0))
743743 then $Tuple2(0, 0)
744744 else $Tuple2(abs(remainOpenNotional), latestCumulativePremiumFraction(newPositionSize))
745745 let newPositionOpenNotional = $t03421234598._1
746746 let newPositionLstUpdCPF = $t03421234598._2
747747 let openNotionalDelta = (oldPositionOpenNotional - newPositionOpenNotional)
748748 let marginRatio = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
749749 let newPositionMarginWithSameRatio = if ((oldPositionSize > 0))
750750 then (muld((newPositionOpenNotional + unrealizedPnlAfter), marginRatio) - unrealizedPnlAfter)
751751 else (muld((newPositionOpenNotional - unrealizedPnlAfter), marginRatio) - unrealizedPnlAfter)
752752 let marginToTraderRaw = ((remainMarginBefore - (newPositionMarginWithSameRatio + unrealizedPnlAfter)) - realizedCloseFee)
753753 let marginToTrader = if ((0 > marginToTraderRaw))
754754 then if (_liquidate)
755755 then 0
756756 else throw("Invalid internalClosePosition params: unable to pay fee")
757757 else marginToTraderRaw
758758 let newPositionMargin = if (_addToMargin)
759759 then (newPositionMarginWithSameRatio + marginToTrader)
760760 else newPositionMarginWithSameRatio
761761 if (if ((_minQuoteAssetAmount != 0))
762762 then (_minQuoteAssetAmount > exchangedQuoteAssetAmount)
763763 else false)
764764 then throw(((("Limit error: " + toString(exchangedQuoteAssetAmount)) + " < ") + toString(_minQuoteAssetAmount)))
765765 else $Tuple17(newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, positionBadDebt, realizedPnl, if (if (_addToMargin)
766766 then isPartialClose
767767 else false)
768768 then 0
769769 else marginToTrader, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, (openInterestNotional() - openNotionalDelta), (totalLongPositionSize() - (if (isLongPosition)
770770 then abs(exchangedPositionSize)
771771 else 0)), (totalShortPositionSize() - (if (!(isLongPosition))
772772 then abs(exchangedPositionSize)
773773 else 0)), (openInterestLong() - (if (isLongPosition)
774774 then openNotionalDelta
775775 else 0)), (openInterestShort() - (if (!(isLongPosition))
776776 then openNotionalDelta
777777 else 0)), (realizedCloseFee + rolloverFee), exchangedQuoteAssetAmount)
778778 }
779779 else throw(((("Invalid internalClosePosition params: invalid position size: " + toString(_size)) + " max: ") + toString(absOldPositionSize)))
780780 }
781781
782782
783783 func getTwapSpotPrice () = {
784784 let minuteId = ((lastTimestamp() / 1000) / 60)
785785 let startMinuteId = (minuteId - TWAP_INTERVAL)
786786 let listStr = valueOrElse(getString(this, k_lastDataStr), "")
787787 let list = split(listStr, ",")
788788 func filterFn (accumulator,next) = if ((startMinuteId >= valueOrErrorMessage(parseInt(next), ("getTwapSpotPrice: invalid int: " + listStr))))
789789 then (accumulator :+ parseIntValue(next))
790790 else accumulator
791791
792792 let listF = {
793793 let $l = list
794794 let $s = size($l)
795795 let $acc0 = nil
796796 func $f0_1 ($a,$i) = if (($i >= $s))
797797 then $a
798798 else filterFn($a, $l[$i])
799799
800800 func $f0_2 ($a,$i) = if (($i >= $s))
801801 then $a
802802 else throw("List size exceeds 20")
803803
804804 $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)
805805 }
806806 let maxIndex = if ((size(listF) > 0))
807807 then max(listF)
808808 else valueOrErrorMessage(parseInt(list[0]), ("getTwapSpotPrice: invalid int: " + listStr))
809809 let lastMinuteId = valueOrElse(getInteger(this, k_lastMinuteId), 0)
810810 let endLastCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(lastMinuteId))), 0)
811811 let endLastPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(lastMinuteId))), 0)
812812 let nowCumulativePrice = (endLastCumulativePrice + ((minuteId - lastMinuteId) * endLastPrice))
813813 let startLastCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(maxIndex))), 0)
814814 let startLastPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(maxIndex))), 0)
815815 let startCumulativePrice = (startLastCumulativePrice + ((startMinuteId - maxIndex) * startLastPrice))
816816 ((nowCumulativePrice - startCumulativePrice) / TWAP_INTERVAL)
817817 }
818818
819819
820820 func getTerminalAmmState () = {
821821 let _positionSize = totalPositionSize()
822822 if ((_positionSize == 0))
823823 then $Tuple2(qtAstR(), bsAstR())
824824 else {
825825 let direction = (_positionSize > 0)
826826 let $t03933539514 = swapOutput(direction, abs(_positionSize), false)
827827 let currentNetMarketValue = $t03933539514._1
828828 let terminalQuoteAssetReserve = $t03933539514._2
829829 let terminalBaseAssetReserve = $t03933539514._3
830830 $Tuple2(terminalQuoteAssetReserve, terminalBaseAssetReserve)
831831 }
832832 }
833833
834834
835835 func getQuoteAssetWeight (baseAssetReserve,totalPositionSize,quoteAssetReserve,targetPrice) = {
836836 let b = toBigInt(baseAssetReserve)
837837 let sz = toBigInt(totalPositionSize)
838838 let q = toBigInt(quoteAssetReserve)
839839 let p = toBigInt(targetPrice)
840840 let k = bmuld(q, b)
841841 let newB = (b + sz)
842842 let newQ = bdivd(k, newB)
843843 let z = bdivd(newQ, newB)
844844 let result = bdivd(p, z)
845845 toInt(result)
846846 }
847847
848848
849849 func getSyncTerminalPrice (_terminalPrice,_qtAstR,_bsAstR) = {
850850 let _positionSize = totalPositionSize()
851851 if ((_positionSize == 0))
852852 then {
853853 let newQtAstW = divd(muld(_terminalPrice, _bsAstR), _qtAstR)
854854 $Tuple3(newQtAstW, DECIMAL_UNIT, 0)
855855 }
856856 else {
857857 let direction = (_positionSize > 0)
858858 let currentNetMarketValue = swapOutput(direction, abs(_positionSize), false)._1
859859 let newQtAstW = getQuoteAssetWeight(_bsAstR, _positionSize, _qtAstR, _terminalPrice)
860860 let newBsAstW = DECIMAL_UNIT
861861 let marginToVault = getPositionNotionalAndUnrealizedPnlByValues(_positionSize, currentNetMarketValue, _qtAstR, newQtAstW, _bsAstR, newBsAstW, PNL_OPTION_SPOT)._2
862862 $Tuple3(newQtAstW, newBsAstW, marginToVault)
863863 }
864864 }
865865
866866
867867 func getFunding () = {
868868 let underlyingPrice = getOraclePrice()
869869 let spotPrice = getSpotPrice()
870870 let premium = (spotPrice - underlyingPrice)
871871 if (if (if ((totalShortPositionSize() == 0))
872872 then true
873873 else (totalLongPositionSize() == 0))
874874 then true
875875 else isMarketClosed())
876876 then $Tuple3(0, 0, 0)
877877 else if ((0 > premium))
878878 then {
879879 let shortPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
880880 if ((fundingMode() == FUNDING_ASYMMETRIC))
881881 then {
882882 let longPremiumFraction = divd(muld(shortPremiumFraction, totalShortPositionSize()), totalLongPositionSize())
883883 $Tuple3(shortPremiumFraction, longPremiumFraction, 0)
884884 }
885885 else {
886886 let shortTotalPremiumFraction = abs(muld(shortPremiumFraction, totalShortPositionSize()))
887887 let longTotalPremiumFraction = abs(muld(shortPremiumFraction, totalLongPositionSize()))
888888 let premiumToVault = (shortTotalPremiumFraction - longTotalPremiumFraction)
889889 $Tuple3(shortPremiumFraction, shortPremiumFraction, premiumToVault)
890890 }
891891 }
892892 else {
893893 let longPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
894894 if ((fundingMode() == FUNDING_ASYMMETRIC))
895895 then {
896896 let shortPremiumFraction = divd(muld(longPremiumFraction, totalLongPositionSize()), totalShortPositionSize())
897897 $Tuple3(shortPremiumFraction, longPremiumFraction, 0)
898898 }
899899 else {
900900 let longTotalPremiumFraction = abs(muld(longPremiumFraction, totalLongPositionSize()))
901901 let shortTotalPremiumFraction = abs(muld(longPremiumFraction, totalShortPositionSize()))
902902 let premiumToVault = (longTotalPremiumFraction - shortTotalPremiumFraction)
903903 $Tuple3(longPremiumFraction, longPremiumFraction, premiumToVault)
904904 }
905905 }
906906 }
907907
908908
909909 func getAdjustedFee (_artifactId,_baseFeeDiscount) = {
910910 let baseFeeRaw = fee()
911911 let baseFee = muld(baseFeeRaw, _baseFeeDiscount)
912912 let $t04408944584 = if ((_artifactId != ""))
913913 then {
914914 let artifactKind = strA(nftManagerAddress(), toCompositeKey(k_token_type, _artifactId))
915915 if ((artifactKind == FEE_REDUCTION_TOKEN_TYPE))
916916 then {
917917 let reduction = intA(nftManagerAddress(), toCompositeKey(k_token_param, _artifactId))
918918 let adjustedFee = muld(baseFee, reduction)
919919 $Tuple2(adjustedFee, true)
920920 }
921921 else throw("Invalid attached artifact")
922922 }
923923 else $Tuple2(baseFee, false)
924924 let adjustedFee = $t04408944584._1
925925 let burnArtifact = $t04408944584._2
926926 $Tuple2(adjustedFee, burnArtifact)
927927 }
928928
929929
930930 func isSameAssetOrNoPosition (_trader,_assetId) = {
931931 let oldPositionSize = getPosition(_trader)._1
932932 if ((oldPositionSize == 0))
933933 then true
934934 else (getPositionAsset(_trader) == _assetId)
935935 }
936936
937937
938938 func isSameAsset (_trader,_assetId) = (getPositionAsset(_trader) == _assetId)
939939
940940
941941 func getForTraderWithArtifact (_trader,_artifactId) = {
942942 let doGetFeeDiscount = invoke(minerAddress(), "computeFeeDiscount", [_trader], nil)
943943 if ((doGetFeeDiscount == doGetFeeDiscount))
944944 then {
945945 let feeDiscount = match doGetFeeDiscount {
946946 case x: Int =>
947947 x
948948 case _ =>
949949 throw("Invalid computeFeeDiscount result")
950950 }
951951 let $t04526445338 = getAdjustedFee(_artifactId, feeDiscount)
952952 let adjustedFee = $t04526445338._1
953953 let burnArtifact = $t04526445338._2
954954 $Tuple2(adjustedFee, burnArtifact)
955955 }
956956 else throw("Strict value is not equal to itself.")
957957 }
958958
959959
960960 func getArtifactId (i) = {
961961 let artifactId = if ((size(i.payments) > 1))
962962 then toBase58String(valueOrErrorMessage(i.payments[1].assetId, "Invalid artifactId"))
963963 else ""
964964 artifactId
965965 }
966966
967967
968968 func distributeFee (_feeAmount) = {
969969 let feeToStakers = muld(_feeAmount, feeToStakersPercent())
970970 let feeToVault = (_feeAmount - feeToStakers)
971971 $Tuple2(feeToStakers, feeToVault)
972972 }
973973
974974
975975 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)]
976976
977977
978978 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)]
979979
980980
981981 func incrementPositionSequenceNumber (_isNewPosition,_address) = if (_isNewPosition)
982982 then {
983983 let currentSequence = lastSequence()
984984 [IntegerEntry(toCompositeKey(k_positionSequence, _address), (currentSequence + 1)), IntegerEntry(k_sequence, (currentSequence + 1))]
985985 }
986986 else nil
987987
988988
989989 func updatePositionFee (_isNewPosition,_address,_fee) = if (_isNewPosition)
990990 then [IntegerEntry(toCompositeKey(k_positionFee, _address), _fee)]
991991 else nil
992992
993993
994994 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)]
995995
996996
997997 func appendTwap (_price) = {
998998 let minuteId = ((lastTimestamp() / 1000) / 60)
999999 let previousMinuteId = valueOrElse(getInteger(this, k_lastMinuteId), 0)
10001000 if ((previousMinuteId > minuteId))
10011001 then throw("TWAP out-of-order")
10021002 else {
10031003 let lastMinuteId = if ((previousMinuteId == 0))
10041004 then minuteId
10051005 else previousMinuteId
10061006 if ((minuteId > previousMinuteId))
10071007 then {
10081008 let prevCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(previousMinuteId))), 0)
10091009 let prevPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(previousMinuteId))), _price)
10101010 let lastCumulativePrice = (prevCumulativePrice + ((minuteId - lastMinuteId) * prevPrice))
10111011 let list = pushToQueue(strToList(valueOrElse(getString(this, k_lastDataStr), "")), TWAP_INTERVAL, toString(minuteId))
10121012 [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))]
10131013 }
10141014 else {
10151015 let twapDataPreviousMinuteId = valueOrElse(getInteger(this, toCompositeKey(k_twapDataPreviousMinuteId, toString(minuteId))), 0)
10161016 let prevCumulativePrice = valueOrElse(getInteger(this, toCompositeKey(k_twapDataLastCumulativePrice, toString(twapDataPreviousMinuteId))), 0)
10171017 let prevPrice = valueOrElse(getInteger(this, toCompositeKey(k_twapDataLastPrice, toString(twapDataPreviousMinuteId))), _price)
10181018 let lastCumulativePrice = (prevCumulativePrice + ((minuteId - twapDataPreviousMinuteId) * prevPrice))
10191019 [IntegerEntry(toCompositeKey(k_twapDataLastCumulativePrice, toString(minuteId)), lastCumulativePrice), IntegerEntry(toCompositeKey(k_twapDataLastPrice, toString(minuteId)), _price)]
10201020 }
10211021 }
10221022 }
10231023
10241024
10251025 func updateAmmReserves (_qtAstR,_bsAstR) = [IntegerEntry(k_quoteAssetReserve, _qtAstR), IntegerEntry(k_baseAssetReserve, _bsAstR)]
10261026
10271027
10281028 func updateAmmWeights (_qtAstW,_bsAstW) = [IntegerEntry(k_quoteAssetWeight, _qtAstW), IntegerEntry(k_baseAssetWeight, _bsAstW)]
10291029
10301030
10311031 func updateAmm (_qtAstR,_bsAstR,_totalPositionSizeAfter,_openInterestNotional,_totalLongPositionSize,_totalShortPositionSize,_totalLongOpenNotional,_totalShortOpenNotional) = {
10321032 let _qtAstW = qtAstW()
10331033 let _bsAstW = bsAstW()
10341034 if (((_totalLongPositionSize - _totalShortPositionSize) != _totalPositionSizeAfter))
10351035 then throw(((((("Invalid AMM state data: " + toString(_totalLongPositionSize)) + " + ") + toString(_totalShortPositionSize)) + " != ") + toString(_totalPositionSizeAfter)))
10361036 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))))
10371037 }
10381038
10391039
10401040 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))]
10411041
10421042
10431043 func withdraw (_address,_amount) = {
10441044 let balance = assetBalance(this, quoteAsset())
10451045 if ((_amount > balance))
10461046 then throw(((("Unable to withdraw " + toString(_amount)) + " from contract balance ") + toString(balance)))
10471047 else [ScriptTransfer(_address, _amount, quoteAsset())]
10481048 }
10491049
10501050
10511051 func updateBalance (i) = if ((0 > i))
10521052 then throw("Balance")
10531053 else [IntegerEntry(k_balance, i)]
10541054
10551055
10561056 func transferFee (i) = [ScriptTransfer(stakingAddress(), i, quoteAsset())]
10571057
10581058
10591059 func doBurnArtifact (_burnArtifact,i) = if (_burnArtifact)
10601060 then [Burn(valueOrErrorMessage(i.payments[1].assetId, "Invalid artifact"), 1)]
10611061 else nil
10621062
10631063
10641064 @Callable(i)
10651065 func pause () = if ((i.caller != adminAddress()))
10661066 then throw("Invalid pause params")
10671067 else [BooleanEntry(k_paused, true)]
10681068
10691069
10701070
10711071 @Callable(i)
10721072 func unpause () = if ((i.caller != adminAddress()))
10731073 then throw("Invalid unpause params")
10741074 else [BooleanEntry(k_paused, false)]
10751075
10761076
10771077
10781078 @Callable(i)
10791079 func setCloseOnly () = if ((i.caller != adminAddress()))
10801080 then throw("Invalid setCloseOnly params")
10811081 else [BooleanEntry(k_closeOnly, true)]
10821082
10831083
10841084
10851085 @Callable(i)
10861086 func unsetCloseOnly () = if ((i.caller != adminAddress()))
10871087 then throw("Invalid unsetCloseOnly params")
10881088 else [BooleanEntry(k_closeOnly, false)]
10891089
10901090
10911091
10921092 @Callable(i)
10931093 func addLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
10941094 then true
10951095 else (0 >= _quoteAssetAmount))
10961096 then throw("Invalid addLiquidity params")
10971097 else {
10981098 let _qtAstR = qtAstR()
10991099 let _bsAstR = bsAstR()
11001100 let _qtAstW = qtAstW()
11011101 let _bsAstW = bsAstW()
11021102 let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
11031103 let qtAstRAfter = (_qtAstR + _quoteAssetAmount)
11041104 let baseAssetAmountToAdd = (divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR)
11051105 let bsAstRAfter = (_bsAstR + baseAssetAmountToAdd)
11061106 let $t05474554896 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
11071107 let newQuoteAssetWeight = $t05474554896._1
11081108 let newBaseAssetWeight = $t05474554896._2
11091109 let marginToVault = $t05474554896._3
11101110 let doExchangePnL = if ((marginToVault != 0))
11111111 then {
11121112 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
11131113 if ((doExchangePnL == doExchangePnL))
11141114 then nil
11151115 else throw("Strict value is not equal to itself.")
11161116 }
11171117 else nil
11181118 if ((doExchangePnL == doExchangePnL))
11191119 then (updateAmmReserves(qtAstRAfter, bsAstRAfter) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
11201120 else throw("Strict value is not equal to itself.")
11211121 }
11221122
11231123
11241124
11251125 @Callable(i)
11261126 func removeLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
11271127 then true
11281128 else (_quoteAssetAmount >= 0))
11291129 then throw("Invalid removeLiquidity params")
11301130 else {
11311131 let _qtAstR = qtAstR()
11321132 let _bsAstR = bsAstR()
11331133 let _qtAstW = qtAstW()
11341134 let _bsAstW = bsAstW()
11351135 let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
11361136 let qtAstRAfter = (_qtAstR - _quoteAssetAmount)
11371137 let baseAssetAmountToRemove = abs((divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR))
11381138 let bsAstRAfter = (_bsAstR - baseAssetAmountToRemove)
11391139 let $t05582855979 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
11401140 let newQuoteAssetWeight = $t05582855979._1
11411141 let newBaseAssetWeight = $t05582855979._2
11421142 let marginToVault = $t05582855979._3
11431143 let doExchangePnL = if ((marginToVault != 0))
11441144 then {
11451145 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
11461146 if ((doExchangePnL == doExchangePnL))
11471147 then nil
11481148 else throw("Strict value is not equal to itself.")
11491149 }
11501150 else nil
11511151 if ((doExchangePnL == doExchangePnL))
11521152 then (updateAmmReserves(qtAstRAfter, bsAstRAfter) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
11531153 else throw("Strict value is not equal to itself.")
11541154 }
11551155
11561156
11571157
11581158 @Callable(i)
11591159 func changeSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay,_rolloverFee) = if ((i.caller != adminAddress()))
11601160 then throw("Invalid changeSettings params")
11611161 else updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact, _partialLiquidationRatio, _maxPriceSpread, _maxOpenNotional, _feeToStakersPercent, _maxOracleDelay, _rolloverFee)
11621162
11631163
11641164
11651165 @Callable(i)
11661166 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))
11671167 then true
11681168 else (0 >= _bsAstR))
11691169 then true
11701170 else (0 >= _fundingPeriod))
11711171 then true
11721172 else (0 >= _initMarginRatio))
11731173 then true
11741174 else (0 >= _mmr))
11751175 then true
11761176 else (0 >= _liquidationFeeRatio))
11771177 then true
11781178 else (0 >= _fee))
11791179 then true
11801180 else (0 >= _spreadLimit))
11811181 then true
11821182 else (0 >= _maxPriceImpact))
11831183 then true
11841184 else (0 >= _partialLiquidationRatio))
11851185 then true
11861186 else (0 >= _maxPriceSpread))
11871187 then true
11881188 else (0 >= _maxOpenNotional))
11891189 then true
11901190 else (0 >= _feeToStakersPercent))
11911191 then true
11921192 else (_feeToStakersPercent > DECIMAL_UNIT))
11931193 then true
11941194 else (0 >= _maxOracleDelay))
11951195 then true
11961196 else (0 >= _rolloverFee))
11971197 then true
11981198 else initialized())
11991199 then true
12001200 else (i.caller != this))
12011201 then throw("Invalid initialize parameters")
12021202 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)))])
12031203
12041204
12051205
12061206 @Callable(i)
12071207 func increasePosition (_direction,_leverage,_minBaseAssetAmount,_refLink) = {
12081208 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
12091209 if ((sync == sync))
12101210 then {
12111211 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
12121212 if ((ensureCalledOnce == ensureCalledOnce))
12131213 then {
12141214 let _trader = getActualCaller(i)
12151215 let _rawAmount = i.payments[0].amount
12161216 let _assetId = i.payments[0].assetId
12171217 let _assetIdStr = toBase58String(value(_assetId))
12181218 let isQuoteAsset = (_assetId == quoteAsset())
12191219 if (if (if (if (if (if (if (if (if (if ((_direction != DIR_LONG))
12201220 then (_direction != DIR_SHORT)
12211221 else false)
12221222 then true
12231223 else (0 >= _rawAmount))
12241224 then true
12251225 else !(initialized()))
12261226 then true
12271227 else !(isQuoteAsset))
12281228 then true
12291229 else !(isSameAssetOrNoPosition(_trader, _assetIdStr)))
12301230 then true
12311231 else !(requireMoreMarginRatio(divd(DECIMAL_UNIT, _leverage), initMarginRatio(), true)))
12321232 then true
12331233 else paused())
12341234 then true
12351235 else closeOnly())
12361236 then true
12371237 else isMarketClosed())
12381238 then throw("Invalid increasePosition parameters")
12391239 else {
12401240 let $t05975759906 = getForTraderWithArtifact(_trader, getArtifactId(i))
12411241 let adjustedFee = $t05975759906._1
12421242 let burnArtifact = $t05975759906._2
12431243 let _amount = divd(_rawAmount, (muld(adjustedFee, _leverage) + DECIMAL_UNIT))
12441244 let distributeFeeAmount = (_rawAmount - _amount)
12451245 let referrerFeeAny = invoke(referralAddress(), "acceptPaymentWithLink", [_trader, _refLink], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
12461246 if ((referrerFeeAny == referrerFeeAny))
12471247 then {
12481248 let referrerFee = match referrerFeeAny {
12491249 case x: Int =>
12501250 x
12511251 case _ =>
12521252 throw("Invalid referrerFee")
12531253 }
12541254 let feeAmount = (distributeFeeAmount - referrerFee)
12551255 let $t06040260570 = getPosition(_trader)
12561256 let oldPositionSize = $t06040260570._1
12571257 let oldPositionMargin = $t06040260570._2
12581258 let oldPositionOpenNotional = $t06040260570._3
12591259 let oldPositionLstUpdCPF = $t06040260570._4
12601260 let oldPositionTimestamp = $t06040260570._5
12611261 let isNewPosition = (oldPositionSize == 0)
12621262 let isSameDirection = if ((oldPositionSize > 0))
12631263 then (_direction == DIR_LONG)
12641264 else (_direction == DIR_SHORT)
12651265 let expandExisting = if (!(isNewPosition))
12661266 then isSameDirection
12671267 else false
12681268 let isAdd = (_direction == DIR_LONG)
12691269 let $t06085963980 = if (if (isNewPosition)
12701270 then true
12711271 else expandExisting)
12721272 then {
12731273 let openNotional = muld(_amount, _leverage)
12741274 let $t06136861541 = swapInput(isAdd, openNotional)
12751275 let amountBaseAssetBought = $t06136861541._1
12761276 let quoteAssetReserveAfter = $t06136861541._2
12771277 let baseAssetReserveAfter = $t06136861541._3
12781278 let totalPositionSizeAfter = $t06136861541._4
12791279 if (if ((_minBaseAssetAmount != 0))
12801280 then (_minBaseAssetAmount > abs(amountBaseAssetBought))
12811281 else false)
12821282 then throw(((("Limit error: " + toString(abs(amountBaseAssetBought))) + " < ") + toString(_minBaseAssetAmount)))
12831283 else {
12841284 let newPositionSize = (oldPositionSize + amountBaseAssetBought)
12851285 let totalLongOpenInterestAfter = (openInterestLong() + (if ((newPositionSize > 0))
12861286 then openNotional
12871287 else 0))
12881288 let totalShortOpenInterestAfter = (openInterestShort() + (if ((0 > newPositionSize))
12891289 then openNotional
12901290 else 0))
12911291 let $t06208762362 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, _amount)
12921292 let remainMargin = $t06208762362._1
12931293 let x1 = $t06208762362._2
12941294 let x2 = $t06208762362._3
12951295 let rolloverFee = $t06208762362._4
12961296 if (!(requireNotOverSpreadLimit(quoteAssetReserveAfter, baseAssetReserveAfter)))
12971297 then throw("Over max spread limit")
12981298 else if (!(requireNotOverMaxOpenNotional(totalLongOpenInterestAfter, totalShortOpenInterestAfter)))
12991299 then throw("Over max open notional")
13001300 else $Tuple14(newPositionSize, remainMargin, (oldPositionOpenNotional + openNotional), latestCumulativePremiumFraction(newPositionSize), lastTimestamp(), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, (openInterestNotional() + openNotional), (totalLongPositionSize() + (if ((newPositionSize > 0))
13011301 then abs(amountBaseAssetBought)
13021302 else 0)), (totalShortPositionSize() + (if ((0 > newPositionSize))
13031303 then abs(amountBaseAssetBought)
13041304 else 0)), totalLongOpenInterestAfter, totalShortOpenInterestAfter, rolloverFee)
13051305 }
13061306 }
13071307 else {
13081308 let openNotional = muld(_amount, _leverage)
13091309 let $t06368063796 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
13101310 let oldPositionNotional = $t06368063796._1
13111311 let unrealizedPnl = $t06368063796._2
13121312 if ((oldPositionNotional > openNotional))
13131313 then throw("Use decreasePosition to decrease position size")
13141314 else throw("Close position first")
13151315 }
13161316 let newPositionSize = $t06085963980._1
13171317 let newPositionRemainMargin = $t06085963980._2
13181318 let newPositionOpenNotional = $t06085963980._3
13191319 let newPositionLatestCPF = $t06085963980._4
13201320 let newPositionTimestamp = $t06085963980._5
13211321 let baseAssetReserveAfter = $t06085963980._6
13221322 let quoteAssetReserveAfter = $t06085963980._7
13231323 let totalPositionSizeAfter = $t06085963980._8
13241324 let openInterestNotionalAfter = $t06085963980._9
13251325 let totalLongAfter = $t06085963980._10
13261326 let totalShortAfter = $t06085963980._11
13271327 let totalLongOpenInterestAfter = $t06085963980._12
13281328 let totalShortOpenInterestAfter = $t06085963980._13
13291329 let rolloverFee = $t06085963980._14
13301330 let $t06398664057 = distributeFee((feeAmount + rolloverFee))
13311331 let feeToStakers = $t06398664057._1
13321332 let feeToVault = $t06398664057._2
13331333 let stake = if ((_amount >= rolloverFee))
13341334 then invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), (_amount - rolloverFee))])
13351335 else invoke(vaultAddress(), "withdrawLocked", [(rolloverFee - _amount)], nil)
13361336 if ((stake == stake))
13371337 then {
13381338 let depositVault = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
13391339 if ((depositVault == depositVault))
13401340 then {
13411341 let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, feeAmount], nil)
13421342 if ((notifyFee == notifyFee))
13431343 then {
13441344 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
13451345 if ((notifyNotional == notifyNotional))
13461346 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))
13471347 else throw("Strict value is not equal to itself.")
13481348 }
13491349 else throw("Strict value is not equal to itself.")
13501350 }
13511351 else throw("Strict value is not equal to itself.")
13521352 }
13531353 else throw("Strict value is not equal to itself.")
13541354 }
13551355 else throw("Strict value is not equal to itself.")
13561356 }
13571357 }
13581358 else throw("Strict value is not equal to itself.")
13591359 }
13601360 else throw("Strict value is not equal to itself.")
13611361 }
13621362
13631363
13641364
13651365 @Callable(i)
13661366 func addMargin () = {
13671367 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
13681368 if ((sync == sync))
13691369 then {
13701370 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
13711371 if ((ensureCalledOnce == ensureCalledOnce))
13721372 then {
13731373 let _trader = toString(i.caller)
13741374 let _amount = i.payments[0].amount
13751375 let _assetId = i.payments[0].assetId
13761376 let _assetIdStr = toBase58String(value(_assetId))
13771377 let isQuoteAsset = (_assetId == quoteAsset())
13781378 if (if (if (if (if (if (if (!(isQuoteAsset))
13791379 then true
13801380 else !(requireOpenPosition(toString(i.caller))))
13811381 then true
13821382 else !(isSameAsset(_trader, _assetIdStr)))
13831383 then true
13841384 else !(initialized()))
13851385 then true
13861386 else paused())
13871387 then true
13881388 else closeOnly())
13891389 then true
13901390 else isMarketClosed())
13911391 then throw("Invalid addMargin parameters")
13921392 else {
13931393 let $t06616866336 = getPosition(_trader)
13941394 let oldPositionSize = $t06616866336._1
13951395 let oldPositionMargin = $t06616866336._2
13961396 let oldPositionOpenNotional = $t06616866336._3
13971397 let oldPositionLstUpdCPF = $t06616866336._4
13981398 let oldPositionTimestamp = $t06616866336._5
13991399 let stake = invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), _amount)])
14001400 if ((stake == stake))
14011401 then {
14021402 let rolloverFee = calcRolloverFee(oldPositionMargin, oldPositionTimestamp)
14031403 let doTransferFeeToStakers = if ((rolloverFee > 0))
14041404 then {
14051405 let $t06662166680 = distributeFee(rolloverFee)
14061406 let feeToStakers = $t06662166680._1
14071407 let feeToVault = $t06662166680._2
14081408 let unstake = invoke(vaultAddress(), "withdrawLocked", [feeToStakers], nil)
14091409 if ((unstake == unstake))
14101410 then {
14111411 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(feeToVault)], nil)
14121412 if ((lockBadDebt == lockBadDebt))
14131413 then transferFee(feeToStakers)
14141414 else throw("Strict value is not equal to itself.")
14151415 }
14161416 else throw("Strict value is not equal to itself.")
14171417 }
14181418 else nil
14191419 if ((doTransferFeeToStakers == doTransferFeeToStakers))
14201420 then ((updatePosition(_trader, oldPositionSize, ((oldPositionMargin - rolloverFee) + _amount), oldPositionOpenNotional, oldPositionLstUpdCPF, lastTimestamp()) ++ updateBalance(((cbalance() + _amount) - rolloverFee))) ++ doTransferFeeToStakers)
14211421 else throw("Strict value is not equal to itself.")
14221422 }
14231423 else throw("Strict value is not equal to itself.")
14241424 }
14251425 }
14261426 else throw("Strict value is not equal to itself.")
14271427 }
14281428 else throw("Strict value is not equal to itself.")
14291429 }
14301430
14311431
14321432
14331433 @Callable(i)
14341434 func removeMargin (_amount) = {
14351435 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
14361436 if ((sync == sync))
14371437 then {
14381438 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
14391439 if ((ensureCalledOnce == ensureCalledOnce))
14401440 then {
14411441 let _trader = toString(i.caller)
14421442 if (if (if (if (if ((0 >= _amount))
14431443 then true
14441444 else !(requireOpenPosition(_trader)))
14451445 then true
14461446 else !(initialized()))
14471447 then true
14481448 else paused())
14491449 then true
14501450 else isMarketClosed())
14511451 then throw("Invalid removeMargin parameters")
14521452 else {
14531453 let $t06779267960 = getPosition(_trader)
14541454 let oldPositionSize = $t06779267960._1
14551455 let oldPositionMargin = $t06779267960._2
14561456 let oldPositionOpenNotional = $t06779267960._3
14571457 let oldPositionLstUpdCPF = $t06779267960._4
14581458 let oldPositionTimestamp = $t06779267960._5
14591459 let $t06796668215 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, -(_amount))
14601460 let remainMargin = $t06796668215._1
14611461 let badDebt = $t06796668215._2
14621462 let fundingPayment = $t06796668215._3
14631463 let rolloverFee = $t06796668215._4
14641464 if ((badDebt != 0))
14651465 then throw("Invalid removed margin amount")
14661466 else {
14671467 let marginRatio = calcMarginRatio(remainMargin, badDebt, oldPositionOpenNotional)
14681468 if (!(requireMoreMarginRatio(marginRatio, initMarginRatio(), true)))
14691469 then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
14701470 else {
14711471 let $t06860168660 = distributeFee(rolloverFee)
14721472 let feeToStakers = $t06860168660._1
14731473 let feeToVault = $t06860168660._2
14741474 let doTransferFeeToStakers = if ((rolloverFee > 0))
14751475 then {
14761476 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(feeToVault)], nil)
14771477 if ((lockBadDebt == lockBadDebt))
14781478 then transferFee(feeToStakers)
14791479 else throw("Strict value is not equal to itself.")
14801480 }
14811481 else nil
14821482 if ((doTransferFeeToStakers == doTransferFeeToStakers))
14831483 then {
14841484 let unstake = invoke(vaultAddress(), "withdrawLocked", [(_amount + feeToStakers)], nil)
14851485 if ((unstake == unstake))
14861486 then (((updatePosition(_trader, oldPositionSize, remainMargin, oldPositionOpenNotional, latestCumulativePremiumFraction(oldPositionSize), lastTimestamp()) ++ withdraw(i.caller, _amount)) ++ updateBalance(((cbalance() - _amount) - rolloverFee))) ++ doTransferFeeToStakers)
14871487 else throw("Strict value is not equal to itself.")
14881488 }
14891489 else throw("Strict value is not equal to itself.")
14901490 }
14911491 }
14921492 }
14931493 }
14941494 else throw("Strict value is not equal to itself.")
14951495 }
14961496 else throw("Strict value is not equal to itself.")
14971497 }
14981498
14991499
15001500
15011501 @Callable(i)
15021502 func closePosition (_size,_minQuoteAssetAmount,_addToMargin) = {
15031503 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
15041504 if ((sync == sync))
15051505 then {
15061506 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
15071507 if ((ensureCalledOnce == ensureCalledOnce))
15081508 then {
15091509 let _trader = getActualCaller(i)
15101510 let _traderAddress = valueOrErrorMessage(addressFromString(_trader), "Invalid caller")
15111511 let positionFee = getPositionFee(_trader)
15121512 if (if (if (if (if (if (!(requireOpenPosition(_trader)))
15131513 then true
15141514 else !(initialized()))
15151515 then true
15161516 else paused())
15171517 then true
15181518 else (0 >= _size))
15191519 then true
15201520 else (0 > _minQuoteAssetAmount))
15211521 then true
15221522 else isMarketClosed())
15231523 then throw("Invalid closePosition parameters")
15241524 else {
15251525 let oldPositionTimestamp = getPosition(_trader)._5
15261526 let $t07031770902 = internalClosePosition(_trader, _size, positionFee, _minQuoteAssetAmount, _addToMargin, true, true)
15271527 let newPositionSize = $t07031770902._1
15281528 let newPositionMargin = $t07031770902._2
15291529 let newPositionOpenNotional = $t07031770902._3
15301530 let newPositionLstUpdCPF = $t07031770902._4
15311531 let positionBadDebt = $t07031770902._5
15321532 let realizedPnl = $t07031770902._6
15331533 let marginToTrader = $t07031770902._7
15341534 let quoteAssetReserveAfter = $t07031770902._8
15351535 let baseAssetReserveAfter = $t07031770902._9
15361536 let totalPositionSizeAfter = $t07031770902._10
15371537 let openInterestNotionalAfter = $t07031770902._11
15381538 let totalLongAfter = $t07031770902._12
15391539 let totalShortAfter = $t07031770902._13
15401540 let totalLongOpenInterestAfter = $t07031770902._14
15411541 let totalShortOpenInterestAfter = $t07031770902._15
15421542 let realizedFee = $t07031770902._16
15431543 if ((positionBadDebt > 0))
15441544 then throw("Invalid closePosition parameters: bad debt")
15451545 else if ((oldPositionTimestamp >= lastTimestamp()))
15461546 then throw("Invalid closePosition parameters: wait at least 1 block before closing the position")
15471547 else {
15481548 let isPartialClose = (newPositionSize != 0)
15491549 let withdrawAmount = (marginToTrader + realizedFee)
15501550 let ammBalance = (cbalance() - withdrawAmount)
15511551 let ammNewBalance = if ((0 > ammBalance))
15521552 then 0
15531553 else ammBalance
15541554 let unstake = invoke(vaultAddress(), "withdrawLocked", [withdrawAmount], nil)
15551555 if ((unstake == unstake))
15561556 then {
15571557 let $t07157471633 = distributeFee(realizedFee)
15581558 let feeToStakers = $t07157471633._1
15591559 let feeToVault = $t07157471633._2
15601560 let depositVault = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
15611561 if ((depositVault == depositVault))
15621562 then {
15631563 let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, realizedFee], nil)
15641564 if ((notifyFee == notifyFee))
15651565 then {
15661566 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
15671567 if ((notifyNotional == notifyNotional))
15681568 then (((((if (isPartialClose)
15691569 then updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, lastTimestamp())
15701570 else deletePosition(_trader)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ (if ((marginToTrader > 0))
15711571 then withdraw(_traderAddress, marginToTrader)
15721572 else nil)) ++ updateBalance(ammNewBalance)) ++ transferFee(feeToStakers))
15731573 else throw("Strict value is not equal to itself.")
15741574 }
15751575 else throw("Strict value is not equal to itself.")
15761576 }
15771577 else throw("Strict value is not equal to itself.")
15781578 }
15791579 else throw("Strict value is not equal to itself.")
15801580 }
15811581 }
15821582 }
15831583 else throw("Strict value is not equal to itself.")
15841584 }
15851585 else throw("Strict value is not equal to itself.")
15861586 }
15871587
15881588
15891589
15901590 @Callable(i)
15911591 func liquidate (_trader) = {
15921592 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
15931593 if ((sync == sync))
15941594 then {
15951595 let spotMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
15961596 let liquidationMarginRatio = if (isOverFluctuationLimit())
15971597 then {
15981598 let oracleMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_ORACLE)
15991599 vmax(spotMarginRatio, oracleMarginRatio)
16001600 }
16011601 else spotMarginRatio
16021602 if (if (if (if (if (!(requireMoreMarginRatio(liquidationMarginRatio, maintenanceMarginRatio(), false)))
16031603 then true
16041604 else !(requireOpenPosition(_trader)))
16051605 then true
16061606 else !(initialized()))
16071607 then true
16081608 else paused())
16091609 then true
16101610 else isMarketClosed())
16111611 then throw("Unable to liquidate")
16121612 else {
16131613 let isPartialLiquidation = if (if ((spotMarginRatio > liquidationFeeRatio()))
16141614 then (partialLiquidationRatio() > 0)
16151615 else false)
16161616 then (DECIMAL_UNIT > partialLiquidationRatio())
16171617 else false
16181618 let oldPositionSize = getPosition(_trader)._1
16191619 let positionSizeAbs = abs(oldPositionSize)
16201620 let $t07394674269 = if (isPartialLiquidation)
16211621 then {
16221622 let liquidationSize = getPartialLiquidationAmount(_trader, oldPositionSize)
16231623 let liquidationRatio = divd(abs(liquidationSize), positionSizeAbs)
16241624 $Tuple2(liquidationRatio, abs(liquidationSize))
16251625 }
16261626 else $Tuple2(0, positionSizeAbs)
16271627 let liquidationRatio = $t07394674269._1
16281628 let liquidationSize = $t07394674269._2
16291629 let $t07427574913 = internalClosePosition(_trader, if (isPartialLiquidation)
16301630 then liquidationSize
16311631 else positionSizeAbs, liquidationFeeRatio(), 0, true, false, true)
16321632 let newPositionSize = $t07427574913._1
16331633 let newPositionMargin = $t07427574913._2
16341634 let newPositionOpenNotional = $t07427574913._3
16351635 let newPositionLstUpdCPF = $t07427574913._4
16361636 let positionBadDebt = $t07427574913._5
16371637 let realizedPnl = $t07427574913._6
16381638 let marginToTrader = $t07427574913._7
16391639 let quoteAssetReserveAfter = $t07427574913._8
16401640 let baseAssetReserveAfter = $t07427574913._9
16411641 let totalPositionSizeAfter = $t07427574913._10
16421642 let openInterestNotionalAfter = $t07427574913._11
16431643 let totalLongAfter = $t07427574913._12
16441644 let totalShortAfter = $t07427574913._13
16451645 let totalLongOpenInterestAfter = $t07427574913._14
16461646 let totalShortOpenInterestAfter = $t07427574913._15
16471647 let liquidationPenalty = $t07427574913._16
16481648 let feeToLiquidator = (liquidationPenalty / 2)
16491649 let feeToVault = (liquidationPenalty - feeToLiquidator)
16501650 let ammBalance = (cbalance() - liquidationPenalty)
16511651 let newAmmBalance = if ((0 > ammBalance))
16521652 then 0
16531653 else ammBalance
16541654 let lockBadDebt = if ((positionBadDebt > 0))
16551655 then {
16561656 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [(positionBadDebt + liquidationPenalty)], nil)
16571657 if ((lockBadDebt == lockBadDebt))
16581658 then nil
16591659 else throw("Strict value is not equal to itself.")
16601660 }
16611661 else nil
16621662 if ((lockBadDebt == lockBadDebt))
16631663 then {
16641664 let unstake = invoke(vaultAddress(), "withdrawLocked", [liquidationPenalty], nil)
16651665 if ((unstake == unstake))
16661666 then {
16671667 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
16681668 if ((depositInsurance == depositInsurance))
16691669 then {
16701670 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
16711671 if ((notifyNotional == notifyNotional))
16721672 then ((((if (isPartialLiquidation)
16731673 then updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, lastTimestamp())
16741674 else deletePosition(_trader)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ withdraw(i.caller, feeToLiquidator)) ++ updateBalance(newAmmBalance))
16751675 else throw("Strict value is not equal to itself.")
16761676 }
16771677 else throw("Strict value is not equal to itself.")
16781678 }
16791679 else throw("Strict value is not equal to itself.")
16801680 }
16811681 else throw("Strict value is not equal to itself.")
16821682 }
16831683 }
16841684 else throw("Strict value is not equal to itself.")
16851685 }
16861686
16871687
16881688
16891689 @Callable(i)
16901690 func payFunding () = {
16911691 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
16921692 if ((sync == sync))
16931693 then {
16941694 let fundingBlockTimestamp = nextFundingBlockTimestamp()
16951695 if (if (if ((fundingBlockTimestamp > lastTimestamp()))
16961696 then true
16971697 else !(initialized()))
16981698 then true
16991699 else paused())
17001700 then throw(((("Invalid funding block timestamp: " + toString(lastTimestamp())) + " < ") + toString(fundingBlockTimestamp)))
17011701 else {
17021702 let underlyingPrice = getOraclePrice()
17031703 let $t07690076962 = getFunding()
17041704 let shortPremiumFraction = $t07690076962._1
17051705 let longPremiumFraction = $t07690076962._2
17061706 updateFunding((fundingBlockTimestamp + fundingPeriodSeconds()), (latestLongCumulativePremiumFraction() + longPremiumFraction), (latestShortCumulativePremiumFraction() + shortPremiumFraction), divd(longPremiumFraction, underlyingPrice), divd(shortPremiumFraction, underlyingPrice))
17071707 }
17081708 }
17091709 else throw("Strict value is not equal to itself.")
17101710 }
17111711
17121712
17131713
17141714 @Callable(i)
17151715 func syncTerminalPriceToOracle () = {
17161716 let _qtAstR = qtAstR()
17171717 let _bsAstR = bsAstR()
17181718 let $t07739477760 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
17191719 let newQuoteAssetWeight = $t07739477760._1
17201720 let newBaseAssetWeight = $t07739477760._2
17211721 let marginToVault = $t07739477760._3
17221722 let marginToVaultAdj = if (if ((0 > marginToVault))
17231723 then (abs(marginToVault) > cbalance())
17241724 else false)
17251725 then -(cbalance())
17261726 else marginToVault
17271727 let doExchangePnL = if ((marginToVaultAdj != 0))
17281728 then {
17291729 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVaultAdj], nil)
17301730 if ((doExchangePnL == doExchangePnL))
17311731 then nil
17321732 else throw("Strict value is not equal to itself.")
17331733 }
17341734 else nil
17351735 if ((doExchangePnL == doExchangePnL))
17361736 then ((updateBalance((cbalance() + marginToVaultAdj)) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight)) ++ appendTwap(divd(muld(_qtAstR, newQuoteAssetWeight), muld(_bsAstR, newBaseAssetWeight))))
17371737 else throw("Strict value is not equal to itself.")
17381738 }
17391739
17401740
17411741
17421742 @Callable(i)
17431743 func ensureCalledOnce () = if ((i.caller != this))
17441744 then throw("Invalid saveCurrentTxId parameters")
17451745 else {
17461746 let lastTx = valueOrElse(getString(this, k_lastTx), "")
17471747 if ((lastTx != toBase58String(i.transactionId)))
17481748 then [StringEntry(k_lastTx, lastTx)]
17491749 else throw("Can not call vAMM methods twice in one tx")
17501750 }
17511751
17521752
17531753
17541754 @Callable(i)
17551755 func view_calcRemainMarginWithFundingPayment (_trader) = {
17561756 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
17571757 if ((sync == sync))
17581758 then {
17591759 let $t07891979043 = getPosition(_trader)
17601760 let positionSize = $t07891979043._1
17611761 let positionMargin = $t07891979043._2
17621762 let pon = $t07891979043._3
17631763 let positionLstUpdCPF = $t07891979043._4
17641764 let positionTimestamp = $t07891979043._5
17651765 let $t07904679147 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
17661766 let positionNotional = $t07904679147._1
17671767 let unrealizedPnl = $t07904679147._2
17681768 let $t07915079374 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLstUpdCPF, positionTimestamp, unrealizedPnl)
17691769 let remainMargin = $t07915079374._1
17701770 let badDebt = $t07915079374._2
17711771 let fundingPayment = $t07915079374._3
17721772 let rolloverFee = $t07915079374._4
17731773 throw(((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)) + s(rolloverFee)))
17741774 }
17751775 else throw("Strict value is not equal to itself.")
17761776 }
17771777
17781778
17791779
17801780 @Callable(i)
17811781 func view_getPegAdjustCost (_price) = {
17821782 let _qtAstR = qtAstR()
17831783 let _bsAstR = bsAstR()
17841784 let result = getSyncTerminalPrice(_price, _qtAstR, _bsAstR)
17851785 throw(toString(result._3))
17861786 }
17871787
17881788
17891789
17901790 @Callable(i)
17911791 func view_getTerminalAmmPrice () = {
17921792 let $t07981079891 = getTerminalAmmState()
17931793 let terminalQuoteAssetReserve = $t07981079891._1
17941794 let terminalBaseAssetReserve = $t07981079891._2
17951795 let price = divd(muld(terminalQuoteAssetReserve, qtAstW()), muld(terminalBaseAssetReserve, bsAstW()))
17961796 throw(toString(price))
17971797 }
17981798
17991799
18001800
18011801 @Callable(i)
18021802 func view_getFunding () = {
18031803 let underlyingPrice = getOraclePrice()
18041804 let $t08010680168 = getFunding()
18051805 let shortPremiumFraction = $t08010680168._1
18061806 let longPremiumFraction = $t08010680168._2
18071807 let longFunding = divd(longPremiumFraction, underlyingPrice)
18081808 let shortFunding = divd(shortPremiumFraction, underlyingPrice)
18091809 throw((((s(longFunding) + s(shortFunding)) + s(getTwapSpotPrice())) + s(getOraclePrice())))
18101810 }
18111811
18121812
18131813
18141814 @Callable(i)
18151815 func computeSpotPrice () = {
18161816 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
18171817 if ((sync == sync))
18181818 then {
18191819 let result = getSpotPrice()
18201820 $Tuple2(nil, result)
18211821 }
18221822 else throw("Strict value is not equal to itself.")
18231823 }
18241824
18251825
18261826
18271827 @Callable(i)
18281828 func computeFeeForTraderWithArtifact (_trader,_artifactId) = {
18291829 let result = getForTraderWithArtifact(_trader, _artifactId)
18301830 $Tuple2(nil, result)
18311831 }
18321832
18331833
18341834 @Verifier(tx)
18351835 func verify () = {
18361836 let coordinatorStr = getString(this, k_coordinatorAddress)
18371837 if (isDefined(coordinatorStr))
18381838 then {
18391839 let admin = getString(addressFromStringValue(value(coordinatorStr)), k_admin_address)
18401840 if (isDefined(admin))
18411841 then valueOrElse(getBoolean(addressFromStringValue(value(admin)), ((("status_" + toString(this)) + "_") + toBase58String(tx.id))), false)
18421842 else throw("unable to verify: admin not set in coordinator")
18431843 }
18441844 else sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
18451845 }
18461846

github/deemru/w8io/3ef1775 
187.22 ms