tx · Fo3wdcp4gScXnME2j6XVsx1y4sVBAKHC3LsRkL2dGe6y

3Mv3TjtJoM2fLFJmFGgmzCf1WzMB8WSWYGZ:  -0.07500000 Waves

2022.12.27 17:00 [2378780] smart account 3Mv3TjtJoM2fLFJmFGgmzCf1WzMB8WSWYGZ > SELF 0.00000000 Waves

{ "type": 13, "id": "Fo3wdcp4gScXnME2j6XVsx1y4sVBAKHC3LsRkL2dGe6y", "fee": 7500000, "feeAssetId": null, "timestamp": 1672149675107, "version": 2, "chainId": 84, "sender": "3Mv3TjtJoM2fLFJmFGgmzCf1WzMB8WSWYGZ", "senderPublicKey": "1ZXm7wYgbmAedS6NMwGc15jk7ttDEwKKXrVcn4gopCZ", "proofs": [ "6RhDGDztBfxfnWkqBzDiBC2Zc4NLYD3gkpjKrBQqbNz5K3T1JHeRxia5ibw9yyjQnuwZxnt7rDkVFt6JZqjuoSY" ], "script": "base64:BgJ6CAISABIAEgASABIDCgEBEgMKAQESDgoMAQEBAQEBAQEBAQEBEhQKEgEBAQEBAQEICAgIAQEBAQEBARIFCgMBAQESBgoEAQEBCBIAEgMKAQESBAoCAQESAwoBCBIAEgASAwoBCBIDCgEBEgASABIDCgEIEgASBAoCCAjDAQAJa19vcmFfa2V5AglrX29yYV9rZXkAD2tfb3JhX2Jsb2NrX2tleQIPa19vcmFfYmxvY2tfa2V5AA5rX29yYV9vcGVuX2tleQIOa19vcmFfb3Blbl9rZXkABWtfb3JhAgVrX29yYQAJa19iYWxhbmNlAglrX2JhbGFuY2UACmtfc2VxdWVuY2UCCmtfc2VxdWVuY2UADmtfcG9zaXRpb25TaXplAg5rX3Bvc2l0aW9uU2l6ZQAQa19wb3NpdGlvbk1hcmdpbgIQa19wb3NpdGlvbk1hcmdpbgAWa19wb3NpdGlvbk9wZW5Ob3Rpb25hbAIWa19wb3NpdGlvbk9wZW5Ob3Rpb25hbAAua19wb3NpdGlvbkxhc3RVcGRhdGVkQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgISa19wb3NpdGlvbkZyYWN0aW9uABJrX3Bvc2l0aW9uU2VxdWVuY2UCEmtfcG9zaXRpb25TZXF1ZW5jZQAPa19wb3NpdGlvbkFzc2V0Ag9rX3Bvc2l0aW9uQXNzZXQADWtfaW5pdGlhbGl6ZWQCDWtfaW5pdGlhbGl6ZWQACGtfcGF1c2VkAghrX3BhdXNlZAALa19jbG9zZU9ubHkCC2tfY2xvc2VPbmx5AAVrX2ZlZQIFa19mZWUAD2tfZnVuZGluZ1BlcmlvZAIPa19mdW5kaW5nUGVyaW9kABFrX2luaXRNYXJnaW5SYXRpbwIRa19pbml0TWFyZ2luUmF0aW8AGGtfbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwIFa19tbXIAFWtfbGlxdWlkYXRpb25GZWVSYXRpbwIVa19saXF1aWRhdGlvbkZlZVJhdGlvABlrX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAhZrX3BhcnRMaXF1aWRhdGlvblJhdGlvAA1rX3NwcmVhZExpbWl0Ag1rX3NwcmVhZExpbWl0ABBrX21heFByaWNlSW1wYWN0AhBrX21heFByaWNlSW1wYWN0ABBrX21heFByaWNlU3ByZWFkAhBrX21heFByaWNlU3ByZWFkABFrX21heE9wZW5Ob3Rpb25hbAIRa19tYXhPcGVuTm90aW9uYWwAFWtfZmVlVG9TdGFrZXJzUGVyY2VudAIVa19mZWVUb1N0YWtlcnNQZXJjZW50ABBrX21heE9yYWNsZURlbGF5AhBrX21heE9yYWNsZURlbGF5AA1rX2xhc3REYXRhU3RyAg1rX2xhc3REYXRhU3RyAA5rX2xhc3RNaW51dGVJZAIOa19sYXN0TWludXRlSWQAHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlAh1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQATa190d2FwRGF0YUxhc3RQcmljZQITa190d2FwRGF0YUxhc3RQcmljZQAaa190d2FwRGF0YVByZXZpb3VzTWludXRlSWQCGmtfdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkACVrX2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAhtrX2xhdGVzdExvbmdQcmVtaXVtRnJhY3Rpb24AJmtfbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAhxrX2xhdGVzdFNob3J0UHJlbWl1bUZyYWN0aW9uABJrX25leHRGdW5kaW5nQmxvY2sCHmtfbmV4dEZ1bmRpbmdCbG9ja01pblRpbWVzdGFtcAARa19sb25nRnVuZGluZ1JhdGUCEWtfbG9uZ0Z1bmRpbmdSYXRlABJrX3Nob3J0RnVuZGluZ1JhdGUCEmtfc2hvcnRGdW5kaW5nUmF0ZQATa19xdW90ZUFzc2V0UmVzZXJ2ZQIIa19xdEFzdFIAEmtfYmFzZUFzc2V0UmVzZXJ2ZQIIa19ic0FzdFIAEmtfcXVvdGVBc3NldFdlaWdodAIIa19xdEFzdFcAEWtfYmFzZUFzc2V0V2VpZ2h0AghrX2JzQXN0VwATa190b3RhbFBvc2l0aW9uU2l6ZQITa190b3RhbFBvc2l0aW9uU2l6ZQAXa190b3RhbExvbmdQb3NpdGlvblNpemUCF2tfdG90YWxMb25nUG9zaXRpb25TaXplABhrX3RvdGFsU2hvcnRQb3NpdGlvblNpemUCGGtfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAWa19vcGVuSW50ZXJlc3ROb3Rpb25hbAIWa19vcGVuSW50ZXJlc3ROb3Rpb25hbAATa19vcGVuSW50ZXJlc3RTaG9ydAITa19vcGVuSW50ZXJlc3RTaG9ydAASa19vcGVuSW50ZXJlc3RMb25nAhJrX29wZW5JbnRlcmVzdExvbmcAFGtfY29vcmRpbmF0b3JBZGRyZXNzAhRrX2Nvb3JkaW5hdG9yQWRkcmVzcwAPa192YXVsdF9hZGRyZXNzAg9rX3ZhdWx0X2FkZHJlc3MAD2tfYWRtaW5fYWRkcmVzcwIPa19hZG1pbl9hZGRyZXNzABJrX2FkbWluX3B1YmxpY19rZXkCEmtfYWRtaW5fcHVibGljX2tleQANa19xdW90ZV9hc3NldAINa19xdW90ZV9hc3NldAAPa19xdW90ZV9zdGFraW5nAg9rX3F1b3RlX3N0YWtpbmcAEWtfc3Rha2luZ19hZGRyZXNzAhFrX3N0YWtpbmdfYWRkcmVzcwAPa19taW5lcl9hZGRyZXNzAg9rX21pbmVyX2FkZHJlc3MAEGtfb3JkZXJzX2FkZHJlc3MCEGtfb3JkZXJzX2FkZHJlc3MAEmtfcmVmZXJyYWxfYWRkcmVzcwISa19yZWZlcnJhbF9hZGRyZXNzABRrX2NvbGxhdGVyYWxfYWRkcmVzcwIUa19jb2xsYXRlcmFsX2FkZHJlc3MAEmtfZXhjaGFuZ2VfYWRkcmVzcwISa19leGNoYW5nZV9hZGRyZXNzABVrX25mdF9tYW5hZ2VyX2FkZHJlc3MCFWtfbmZ0X21hbmFnZXJfYWRkcmVzcwAga190cmFkZXJfbWFya2V0X2Fzc2V0X2NvbGxhdGVyYWwCIGtfdHJhZGVyX21hcmtldF9hc3NldF9jb2xsYXRlcmFsAQ50b0NvbXBvc2l0ZUtleQIEX2tleQhfYWRkcmVzcwkArAICCQCsAgIFBF9rZXkCAV8FCF9hZGRyZXNzAQtjb29yZGluYXRvcgAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCBQR0aGlzBRRrX2Nvb3JkaW5hdG9yQWRkcmVzcwITQ29vcmRpbmF0b3Igbm90IHNldAEMYWRtaW5BZGRyZXNzAAkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABQ9rX2FkbWluX2FkZHJlc3MBDmFkbWluUHVibGljS2V5AAkA2QQBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABRJrX2FkbWluX3B1YmxpY19rZXkBCnF1b3RlQXNzZXQACQDZBAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFDWtfcXVvdGVfYXNzZXQBEXF1b3RlQXNzZXRTdGFraW5nAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFD2tfcXVvdGVfc3Rha2luZwIbUXVvdGUgYXNzZXQgc3Rha2luZyBub3Qgc2V0AQ5zdGFraW5nQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABRFrX3N0YWtpbmdfYWRkcmVzcwIPU3Rha2luZyBub3Qgc2V0AQx2YXVsdEFkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUPa192YXVsdF9hZGRyZXNzAg1WYXVsdCBub3Qgc2V0AQxtaW5lckFkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUPa19taW5lcl9hZGRyZXNzAg1NaW5lciBub3Qgc2V0AQ1vcmRlcnNBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFEGtfb3JkZXJzX2FkZHJlc3MCDk9yZGVycyBub3Qgc2V0AQ9yZWZlcnJhbEFkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUSa19yZWZlcnJhbF9hZGRyZXNzAhBSZWZlcnJhbCBub3Qgc2V0ARFuZnRNYW5hZ2VyQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABRVrX25mdF9tYW5hZ2VyX2FkZHJlc3MCE05GVCBNYW5hZ2VyIG5vdCBzZXQBEWNvbGxhdGVyYWxBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFFGtfY29sbGF0ZXJhbF9hZGRyZXNzAhpDb2xsYXRlcmFsIE1hbmFnZXIgbm90IHNldAELc3dhcEFkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIJAQtjb29yZGluYXRvcgAFEmtfZXhjaGFuZ2VfYWRkcmVzcwIPTm8gc3dhcCBhZGRyZXNzAhRJbnZhbGlkIHN3YXAgYWRkcmVzcwARa193aGl0ZWxpc3RfYXNzZXQCEWtfd2hpdGVsaXN0X2Fzc2V0ARBpc1doaXRlbGlzdEFzc2V0AQhfYXNzZXRJZAkBC3ZhbHVlT3JFbHNlAgkAmwgCCQERY29sbGF0ZXJhbEFkZHJlc3MACQEOdG9Db21wb3NpdGVLZXkCBRFrX3doaXRlbGlzdF9hc3NldAUIX2Fzc2V0SWQHAA1rX3Rva2VuX3BhcmFtAg1rX3Rva2VuX3BhcmFtAAxrX3Rva2VuX3R5cGUCDGtfdG9rZW5fdHlwZQAYRkVFX1JFRFVDVElPTl9UT0tFTl9UWVBFAg1mZWVfcmVkdWN0aW9uAAhESVJfTE9ORwABAAlESVJfU0hPUlQAAgANVFdBUF9JTlRFUlZBTAAPAA9PUkFDTEVfSU5URVJWQUwADwAHU0VDT05EUwDoBwAPREVDSU1BTF9OVU1CRVJTAAYADERFQ0lNQUxfVU5JVAkAaAIAAQkAaAIJAGgCCQBoAgkAaAIJAGgCAAoACgAKAAoACgAKAAdPTkVfREFZCQBoAgCAowUFDERFQ0lNQUxfVU5JVAAIQUxMX0ZFRVMAZAAPUE5MX09QVElPTl9TUE9UAAEAEVBOTF9PUFRJT05fT1JBQ0xFAAIBAXMBAl94CQCsAgIJAKQDAQUCX3gCASwBBGRpdmQCAl94Al95CQBuBAUCX3gFDERFQ0lNQUxfVU5JVAUCX3kFCEhBTEZFVkVOAQRtdWxkAgJfeAJfeQkAbgQFAl94BQJfeQUMREVDSU1BTF9VTklUBQhIQUxGRVZFTgEFc3FydGQBAl94CQEEc3FydAQFAl94BQ9ERUNJTUFMX05VTUJFUlMFD0RFQ0lNQUxfTlVNQkVSUwUISEFMRkVWRU4BBHBvd2QCAl94Al95CQBsBgUCX3gFD0RFQ0lNQUxfTlVNQkVSUwUCX3kFD0RFQ0lNQUxfTlVNQkVSUwUPREVDSU1BTF9OVU1CRVJTBQhIQUxGRVZFTgEFYmRpdmQCAl94Al95CQC9AgQFAl94CQC2AgEFDERFQ0lNQUxfVU5JVAUCX3kFCEhBTEZFVkVOAQVibXVsZAICX3gCX3kJAL0CBAUCX3gFAl95CQC2AgEFDERFQ0lNQUxfVU5JVAUISEFMRkVWRU4BBmJzcXJ0ZAECX3gJAQpzcXJ0QmlnSW50BAUCX3gFD0RFQ0lNQUxfTlVNQkVSUwUPREVDSU1BTF9OVU1CRVJTBQhIQUxGRVZFTgEFYnBvd2QCAl94Al95CQB2BgUCX3gFD0RFQ0lNQUxfTlVNQkVSUwUCX3kFD0RFQ0lNQUxfTlVNQkVSUwUPREVDSU1BTF9OVU1CRVJTBQhIQUxGRVZFTgEDYWJzAQJfeAMJAGYCBQJfeAAABQJfeAkBAS0BBQJfeAEEdm1heAICX3gCX3kDCQBnAgUCX3gFAl95BQJfeAUCX3kBCWxpc3RUb1N0cgEFX2xpc3QKAQVfam9pbgILYWNjdW11bGF0b3IDdmFsCQCsAgIJAKwCAgULYWNjdW11bGF0b3IFA3ZhbAIBLAQKbmV3TGlzdFN0cgoAAiRsBQVfbGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzACAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEFX2pvaW4CBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDIwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAA0ADgAPABAAEQASABMAFAQLbmV3TGlzdFN0clUJALMCAgUKbmV3TGlzdFN0cgABBAtuZXdMaXN0U3RyUgMJAAACCQCvAgIFC25ld0xpc3RTdHJVAAECASwJALACAgULbmV3TGlzdFN0clUAAQULbmV3TGlzdFN0clUFC25ld0xpc3RTdHJSAQlzdHJUb0xpc3QBBF9zdHIJALUJAgUEX3N0cgIBLAELcHVzaFRvUXVldWUDBV9saXN0CF9tYXhTaXplBl92YWx1ZQMJAGYCCQCQAwEFBV9saXN0BQhfbWF4U2l6ZQkAzQgCCQDRCAIFBV9saXN0AAAFBl92YWx1ZQkAzQgCBQVfbGlzdAUGX3ZhbHVlAQNpbnQBAWsJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQR0aGlzBQFrCQCsAgICDW5vIHZhbHVlIGZvciAFAWsBBWludE9yAgFrA2RlZgkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQFrBQNkZWYBBHN0ckECCF9hZGRyZXNzBF9rZXkEA3ZhbAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFCF9hZGRyZXNzBQRfa2V5CQCsAgICEU5vIHZhbHVlIGZvciBrZXkgBQRfa2V5BQN2YWwBBGludEECCF9hZGRyZXNzBF9rZXkEA3ZhbAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFCF9hZGRyZXNzBQRfa2V5CQCsAgICEU5vIHZhbHVlIGZvciBrZXkgBQRfa2V5BQN2YWwBCGNiYWxhbmNlAAkBA2ludAEFCWtfYmFsYW5jZQEDZmVlAAkBA2ludAEFBWtfZmVlAQ9pbml0TWFyZ2luUmF0aW8ACQEDaW50AQURa19pbml0TWFyZ2luUmF0aW8BBnF0QXN0UgAJAQNpbnQBBRNrX3F1b3RlQXNzZXRSZXNlcnZlAQZic0FzdFIACQEDaW50AQUSa19iYXNlQXNzZXRSZXNlcnZlAQZxdEFzdFcACQEFaW50T3ICBRJrX3F1b3RlQXNzZXRXZWlnaHQFDERFQ0lNQUxfVU5JVAEGYnNBc3RXAAkBBWludE9yAgURa19iYXNlQXNzZXRXZWlnaHQFDERFQ0lNQUxfVU5JVAERdG90YWxQb3NpdGlvblNpemUACQEDaW50AQUTa190b3RhbFBvc2l0aW9uU2l6ZQEUb3BlbkludGVyZXN0Tm90aW9uYWwACQEDaW50AQUWa19vcGVuSW50ZXJlc3ROb3Rpb25hbAERb3BlbkludGVyZXN0U2hvcnQACQEDaW50AQUTa19vcGVuSW50ZXJlc3RTaG9ydAEQb3BlbkludGVyZXN0TG9uZwAJAQNpbnQBBRJrX29wZW5JbnRlcmVzdExvbmcBGW5leHRGdW5kaW5nQmxvY2tUaW1lc3RhbXAACQEDaW50AQUSa19uZXh0RnVuZGluZ0Jsb2NrARBmdW5kaW5nUGVyaW9kUmF3AAkBA2ludAEFD2tfZnVuZGluZ1BlcmlvZAEUZnVuZGluZ1BlcmlvZERlY2ltYWwACQBoAgkBEGZ1bmRpbmdQZXJpb2RSYXcABQxERUNJTUFMX1VOSVQBFGZ1bmRpbmdQZXJpb2RTZWNvbmRzAAkAaAIJARBmdW5kaW5nUGVyaW9kUmF3AAUHU0VDT05EUwEWbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwAJAQNpbnQBBRhrX21haW50ZW5hbmNlTWFyZ2luUmF0aW8BE2xpcXVpZGF0aW9uRmVlUmF0aW8ACQEDaW50AQUVa19saXF1aWRhdGlvbkZlZVJhdGlvARdwYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwAJAQNpbnQBBRlrX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAQtzcHJlYWRMaW1pdAAJAQNpbnQBBQ1rX3NwcmVhZExpbWl0AQ5tYXhQcmljZUltcGFjdAAJAQNpbnQBBRBrX21heFByaWNlSW1wYWN0AQ5tYXhQcmljZVNwcmVhZAAJAQNpbnQBBRBrX21heFByaWNlU3ByZWFkAQ9tYXhPcGVuTm90aW9uYWwACQEDaW50AQURa19tYXhPcGVuTm90aW9uYWwBI2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAkBA2ludAEFJWtfbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BJGxhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAJAQNpbnQBBSZrX2xhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAJAQNpbnQBBRhrX3RvdGFsU2hvcnRQb3NpdGlvblNpemUBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQAJAQNpbnQBBRdrX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQEMbGFzdFNlcXVlbmNlAAkBBWludE9yAgUKa19zZXF1ZW5jZQAAARNmZWVUb1N0YWtlcnNQZXJjZW50AAkBA2ludAEFFWtfZmVlVG9TdGFrZXJzUGVyY2VudAEObWF4T3JhY2xlRGVsYXkACQEDaW50AQUQa19tYXhPcmFjbGVEZWxheQEPZ2V0QWN0dWFsQ2FsbGVyAQFpCQELdmFsdWVPckVsc2UCCQCdCAIJAQ1vcmRlcnNBZGRyZXNzAAIIa19zZW5kZXIJAKUIAQgFAWkGY2FsbGVyARZyZXF1aXJlTW9yZU1hcmdpblJhdGlvAwxfbWFyZ2luUmF0aW8QX2Jhc2VNYXJnaW5SYXRpbxRfbGFyZ2VyVGhhbk9yRXF1YWxUbwQUcmVtYWluaW5nTWFyZ2luUmF0aW8JAGUCBQxfbWFyZ2luUmF0aW8FEF9iYXNlTWFyZ2luUmF0aW8DAwUUX2xhcmdlclRoYW5PckVxdWFsVG8JAGYCAAAFFHJlbWFpbmluZ01hcmdpblJhdGlvBwkAAgECDkludmFsaWQgbWFyZ2luAwMJAQEhAQUUX2xhcmdlclRoYW5PckVxdWFsVG8JAGcCBRRyZW1haW5pbmdNYXJnaW5SYXRpbwAABwkAAgECDkludmFsaWQgbWFyZ2luBgEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgENX3Bvc2l0aW9uU2l6ZQMJAAACBQ1fcG9zaXRpb25TaXplAAAJAAIBAixTaG91bGQgbm90IGJlIGNhbGxlZCB3aXRoIF9wb3NpdGlvblNpemUgPT0gMAMJAGYCBQ1fcG9zaXRpb25TaXplAAAJASNsYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAJASRsYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24AAQtnZXRQb3NpdGlvbgEHX3RyYWRlcgQPcG9zaXRpb25TaXplT3B0CQCaCAIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFDmtfcG9zaXRpb25TaXplBQdfdHJhZGVyBAckbWF0Y2gwBQ9wb3NpdGlvblNpemVPcHQDCQABAgUHJG1hdGNoMAIDSW50BAxwb3NpdGlvblNpemUFByRtYXRjaDAJAJYKBAUMcG9zaXRpb25TaXplCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBRBrX3Bvc2l0aW9uTWFyZ2luBQdfdHJhZGVyCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBRZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBQdfdHJhZGVyCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBS5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBQdfdHJhZGVyCQCWCgQAAAAAAAAAAAEQZ2V0UG9zaXRpb25Bc3NldAEHX3RyYWRlcgQQcG9zaXRpb25Bc3NldE9wdAkAnQgCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBQ9rX3Bvc2l0aW9uQXNzZXQFB190cmFkZXIEByRtYXRjaDAFEHBvc2l0aW9uQXNzZXRPcHQDCQABAgUHJG1hdGNoMAIGU3RyaW5nBA1wb3NpdGlvbkFzc2V0BQckbWF0Y2gwBQ1wb3NpdGlvbkFzc2V0CQDYBAEJAQpxdW90ZUFzc2V0AAETcmVxdWlyZU9wZW5Qb3NpdGlvbgEHX3RyYWRlcgMJAAACCAkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgJfMQAACQACAQIQTm8gb3BlbiBwb3NpdGlvbgYBC2luaXRpYWxpemVkAAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzBQ1rX2luaXRpYWxpemVkBwEGcGF1c2VkAAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzBQhrX3BhdXNlZAcBCWNsb3NlT25seQAJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhpcwULa19jbG9zZU9ubHkHAQ11cGRhdGVSZXNlcnZlAwZfaXNBZGQRX3F1b3RlQXNzZXRBbW91bnQQX2Jhc2VBc3NldEFtb3VudAMFBl9pc0FkZAQHbmV3QmFzZQkAZQIJAQZic0FzdFIABRBfYmFzZUFzc2V0QW1vdW50AwkAZwIAAAUHbmV3QmFzZQkAAgECKlR4IGxlYWQgdG8gYmFzZSBhc3NldCByZXNlcnZlIDw9IDAsIHJldmVydAkAlQoDCQBkAgkBBnF0QXN0UgAFEV9xdW90ZUFzc2V0QW1vdW50BQduZXdCYXNlCQBkAgkBEXRvdGFsUG9zaXRpb25TaXplAAUQX2Jhc2VBc3NldEFtb3VudAQIbmV3UXVvdGUJAGUCCQEGcXRBc3RSAAURX3F1b3RlQXNzZXRBbW91bnQDCQBnAgAABQhuZXdRdW90ZQkAAgECKlR4IGxlYWQgdG8gYmFzZSBxdW90ZSByZXNlcnZlIDw9IDAsIHJldmVydAkAlQoDBQhuZXdRdW90ZQkAZAIJAQZic0FzdFIABRBfYmFzZUFzc2V0QW1vdW50CQBlAgkBEXRvdGFsUG9zaXRpb25TaXplAAUQX2Jhc2VBc3NldEFtb3VudAENY2FsY0ludmFyaWFudAQHX3F0QXN0UgdfcXRBc3RXB19ic0FzdFIHX2JzQXN0VwQHYnF0QXN0UgkAtgIBBQdfcXRBc3RSBAdicXRBc3RXCQC2AgEFB19xdEFzdFcEB2Jic0FzdFIJALYCAQUHX2JzQXN0UgQHYmJzQXN0VwkAtgIBBQdfYnNBc3RXCQEFYm11bGQCCQEFYm11bGQCBQdicXRBc3RSBQdicXRBc3RXCQEFYm11bGQCBQdiYnNBc3RSBQdiYnNBc3RXAQlzd2FwSW5wdXQCBl9pc0FkZBFfcXVvdGVBc3NldEFtb3VudAQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwAEAWsJAQ1jYWxjSW52YXJpYW50BAUHX3F0QXN0UgUHX3F0QXN0VwUHX2JzQXN0UgUHX2JzQXN0VwQWcXVvdGVBc3NldFJlc2VydmVBZnRlcgMFBl9pc0FkZAkAZAIFB19xdEFzdFIFEV9xdW90ZUFzc2V0QW1vdW50CQBlAgUHX3F0QXN0UgURX3F1b3RlQXNzZXRBbW91bnQEFWJhc2VBc3NldFJlc2VydmVBZnRlcgkAoAMBCQEFYmRpdmQCBQFrCQC2AgEJAQRtdWxkAgUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUHX3F0QXN0VwQYYW1vdW50QmFzZUFzc2V0Qm91Z2h0QWJzCQEEZGl2ZAIJAQNhYnMBCQBlAgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBQdfYnNBc3RSBQdfcXRBc3RXBBVhbW91bnRCYXNlQXNzZXRCb3VnaHQDBQZfaXNBZGQFGGFtb3VudEJhc2VBc3NldEJvdWdodEFicwkBAS0BBRhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMEDSR0MDE2ODA1MTY5NjgJAQ11cGRhdGVSZXNlcnZlAwUGX2lzQWRkBRFfcXVvdGVBc3NldEFtb3VudAUYYW1vdW50QmFzZUFzc2V0Qm91Z2h0QWJzBBdxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyMQgFDSR0MDE2ODA1MTY5NjgCXzEEFmJhc2VBc3NldFJlc2VydmVBZnRlcjEIBQ0kdDAxNjgwNTE2OTY4Al8yBBd0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyMQgFDSR0MDE2ODA1MTY5NjgCXzMEC3ByaWNlQmVmb3JlCQEEZGl2ZAIJAQRtdWxkAgUHX3F0QXN0UgUHX3F0QXN0VwkBBG11bGQCBQdfYnNBc3RSBQdfYnNBc3RXBAttYXJrZXRQcmljZQkBBGRpdmQCBRFfcXVvdGVBc3NldEFtb3VudAUYYW1vdW50QmFzZUFzc2V0Qm91Z2h0QWJzBAlwcmljZURpZmYJAQNhYnMBCQBlAgULcHJpY2VCZWZvcmUFC21hcmtldFByaWNlBAtwcmljZUltcGFjdAkAZQIFDERFQ0lNQUxfVU5JVAkBBGRpdmQCBQtwcmljZUJlZm9yZQkAZAIFC3ByaWNlQmVmb3JlBQlwcmljZURpZmYEE21heFByaWNlSW1wYWN0VmFsdWUJAQ5tYXhQcmljZUltcGFjdAADCQBmAgULcHJpY2VJbXBhY3QFE21heFByaWNlSW1wYWN0VmFsdWUJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICDVByaWNlIGltcGFjdCAJAKQDAQULcHJpY2VJbXBhY3QCFCA+IG1heCBwcmljZSBpbXBhY3QgCQCkAwEFE21heFByaWNlSW1wYWN0VmFsdWUCFSBiZWZvcmUgcXVvdGUgYXNzZXQ6IAkApAMBBQdfcXRBc3RSAhQgYmVmb3JlIGJhc2UgYXNzZXQ6IAkApAMBBQdfYnNBc3RSAiEgcXVvdGUgYXNzZXQgYW1vdW50IHRvIGV4Y2hhbmdlOiAJAKQDAQURX3F1b3RlQXNzZXRBbW91bnQCDyBwcmljZSBiZWZvcmU6IAkApAMBBQtwcmljZUJlZm9yZQIOIG1hcmtldFByaWNlOiAJAKQDAQULbWFya2V0UHJpY2UJAJYKBAUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0BRdxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyMQUWYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyMQUXdG90YWxQb3NpdGlvblNpemVBZnRlcjEBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEEF9vbGRQb3NpdGlvblNpemUSX29sZFBvc2l0aW9uTWFyZ2luJV9vbGRQb3NpdGlvbkN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24MX21hcmdpbkRlbHRhBA5mdW5kaW5nUGF5bWVudAMJAQIhPQIFEF9vbGRQb3NpdGlvblNpemUAAAQgX2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24JAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUQX29sZFBvc2l0aW9uU2l6ZQkBBG11bGQCCQBlAgUgX2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FJV9vbGRQb3NpdGlvbkN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FEF9vbGRQb3NpdGlvblNpemUAAAQMc2lnbmVkTWFyZ2luCQBkAgkAZQIFDF9tYXJnaW5EZWx0YQUOZnVuZGluZ1BheW1lbnQFEl9vbGRQb3NpdGlvbk1hcmdpbgQNJHQwMTg0NTUxODU4MgMJAGYCAAAFDHNpZ25lZE1hcmdpbgkAlAoCAAAJAQNhYnMBBQxzaWduZWRNYXJnaW4JAJQKAgkBA2FicwEFDHNpZ25lZE1hcmdpbgAABAxyZW1haW5NYXJnaW4IBQ0kdDAxODQ1NTE4NTgyAl8xBAdiYWREZWJ0CAUNJHQwMTg0NTUxODU4MgJfMgkAlQoDBQxyZW1haW5NYXJnaW4FB2JhZERlYnQFDmZ1bmRpbmdQYXltZW50ARZzd2FwT3V0cHV0V2l0aFJlc2VydmVzBwZfaXNBZGQQX2Jhc2VBc3NldEFtb3VudBRfY2hlY2tNYXhQcmljZUltcGFjdBJfcXVvdGVBc3NldFJlc2VydmURX3F1b3RlQXNzZXRXZWlnaHQRX2Jhc2VBc3NldFJlc2VydmUQX2Jhc2VBc3NldFdlaWdodAQLcHJpY2VCZWZvcmUJAQRkaXZkAgkBBG11bGQCBRJfcXVvdGVBc3NldFJlc2VydmUFEV9xdW90ZUFzc2V0V2VpZ2h0CQEEbXVsZAIFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0V2VpZ2h0AwkAAAIFEF9iYXNlQXNzZXRBbW91bnQAAAkAAgECGUludmFsaWQgYmFzZSBhc3NldCBhbW91bnQEAWsJAQ1jYWxjSW52YXJpYW50BAUSX3F1b3RlQXNzZXRSZXNlcnZlBRFfcXVvdGVBc3NldFdlaWdodAURX2Jhc2VBc3NldFJlc2VydmUFEF9iYXNlQXNzZXRXZWlnaHQEGGJhc2VBc3NldFBvb2xBbW91bnRBZnRlcgMFBl9pc0FkZAkAZAIFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0QW1vdW50CQBlAgURX2Jhc2VBc3NldFJlc2VydmUFEF9iYXNlQXNzZXRBbW91bnQED3F1b3RlQXNzZXRBZnRlcgkAoAMBCQEFYmRpdmQCBQFrCQC2AgEJAQRtdWxkAgUYYmFzZUFzc2V0UG9vbEFtb3VudEFmdGVyBRBfYmFzZUFzc2V0V2VpZ2h0BA5xdW90ZUFzc2V0U29sZAkBA2FicwEJAGUCBQ9xdW90ZUFzc2V0QWZ0ZXIJAQRtdWxkAgUSX3F1b3RlQXNzZXRSZXNlcnZlBRFfcXVvdGVBc3NldFdlaWdodAQTbWF4UHJpY2VJbXBhY3RWYWx1ZQkBDm1heFByaWNlSW1wYWN0AAQNJHQwMTk3NzAxOTkzMQkBDXVwZGF0ZVJlc2VydmUDCQEBIQEFBl9pc0FkZAUOcXVvdGVBc3NldFNvbGQFEF9iYXNlQXNzZXRBbW91bnQEF3F1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIxCAUNJHQwMTk3NzAxOTkzMQJfMQQWYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyMQgFDSR0MDE5NzcwMTk5MzECXzIEF3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIxCAUNJHQwMTk3NzAxOTkzMQJfMwQLbWFya2V0UHJpY2UJAQRkaXZkAgUOcXVvdGVBc3NldFNvbGQFEF9iYXNlQXNzZXRBbW91bnQECXByaWNlRGlmZgkBA2FicwEJAGUCBQtwcmljZUJlZm9yZQULbWFya2V0UHJpY2UEC3ByaWNlSW1wYWN0CQBlAgUMREVDSU1BTF9VTklUCQEEZGl2ZAIFC3ByaWNlQmVmb3JlCQBkAgULcHJpY2VCZWZvcmUFCXByaWNlRGlmZgMDCQBmAgULcHJpY2VJbXBhY3QFE21heFByaWNlSW1wYWN0VmFsdWUFFF9jaGVja01heFByaWNlSW1wYWN0BwkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgINUHJpY2UgaW1wYWN0IAkApAMBBQtwcmljZUltcGFjdAIUID4gbWF4IHByaWNlIGltcGFjdCAJAKQDAQUTbWF4UHJpY2VJbXBhY3RWYWx1ZQIVIGJlZm9yZSBxdW90ZSBhc3NldDogCQCkAwEFEl9xdW90ZUFzc2V0UmVzZXJ2ZQIUIGJlZm9yZSBiYXNlIGFzc2V0OiAJAKQDAQURX2Jhc2VBc3NldFJlc2VydmUCICBiYXNlIGFzc2V0IGFtb3VudCB0byBleGNoYW5nZTogCQCkAwEFEF9iYXNlQXNzZXRBbW91bnQCDyBwcmljZSBiZWZvcmU6IAkApAMBBQtwcmljZUJlZm9yZQIPIG1hcmtldCBwcmljZTogCQCkAwEFC21hcmtldFByaWNlCQCZCgcFDnF1b3RlQXNzZXRTb2xkBRdxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyMQUWYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyMQUXdG90YWxQb3NpdGlvblNpemVBZnRlcjEJAGUCCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAMFBl9pc0FkZAkBA2FicwEFEF9iYXNlQXNzZXRBbW91bnQAAAkAZQIJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAMJAQEhAQUGX2lzQWRkCQEDYWJzAQUQX2Jhc2VBc3NldEFtb3VudAAABQtwcmljZUltcGFjdAEKc3dhcE91dHB1dAMGX2lzQWRkEF9iYXNlQXNzZXRBbW91bnQUX2NoZWNrTWF4UHJpY2VJbXBhY3QJARZzd2FwT3V0cHV0V2l0aFJlc2VydmVzBwUGX2lzQWRkBRBfYmFzZUFzc2V0QW1vdW50BRRfY2hlY2tNYXhQcmljZUltcGFjdAkBBnF0QXN0UgAJAQZxdEFzdFcACQEGYnNBc3RSAAkBBmJzQXN0VwABDmdldE9yYWNsZVByaWNlAAQGb3JhY2xlCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgUEdGhpcwUFa19vcmECAAQIcHJpY2VLZXkJARFAZXh0ck5hdGl2ZSgxMDUzKQIFBHRoaXMFCWtfb3JhX2tleQQJbGFzdFZhbHVlCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUGb3JhY2xlBQhwcmljZUtleQkArAICCQCsAgIJAKwCAgIiQ2FuIG5vdCBnZXQgb3JhY2xlIHByaWNlLiBPcmFjbGU6IAkApQgBBQZvcmFjbGUCBiBrZXk6IAUIcHJpY2VLZXkECGJsb2NrS2V5CQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMFD2tfb3JhX2Jsb2NrX2tleQIAAwkBAiE9AgUIYmxvY2tLZXkCAAQMY3VycmVudEJsb2NrCAUJbGFzdEJsb2NrBmhlaWdodAQPbGFzdE9yYWNsZUJsb2NrCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUGb3JhY2xlBQhibG9ja0tleQkArAICCQCsAgIJAKwCAgIiQ2FuIG5vdCBnZXQgb3JhY2xlIGJsb2NrLiBPcmFjbGU6IAkApQgBBQZvcmFjbGUCBiBrZXk6IAUIYmxvY2tLZXkDCQBmAgkAZQIFDGN1cnJlbnRCbG9jawUPbGFzdE9yYWNsZUJsb2NrCQEObWF4T3JhY2xlRGVsYXkACQACAQkArAICCQCsAgIJAKwCAgImT3JhY2xlIHN0YWxlIGRhdGEuIExhc3Qgb3JhY2xlIGJsb2NrOiAJAKQDAQUPbGFzdE9yYWNsZUJsb2NrAhAgY3VycmVudCBibG9jazogCQCkAwEFDGN1cnJlbnRCbG9jawUJbGFzdFZhbHVlBQlsYXN0VmFsdWUBDmlzTWFya2V0Q2xvc2VkAAQGb3JhY2xlCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgUEdGhpcwUFa19vcmECAAQHb3BlbktleQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzBQ5rX29yYV9vcGVuX2tleQIAAwkBAiE9AgUHb3BlbktleQIABAZpc09wZW4JARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmwgCBQZvcmFjbGUFB29wZW5LZXkJAKwCAgkArAICCQCsAgICK0NhbiBub3QgZ2V0IG9yYWNsZSBpcyBvcGVuL2Nsb3NlZC4gT3JhY2xlOiAJAKUIAQUGb3JhY2xlAgYga2V5OiAFB29wZW5LZXkJAQEhAQUGaXNPcGVuBwEMYWJzUHJpY2VEaWZmBQxfb3JhY2xlUHJpY2USX3F1b3RlQXNzZXRSZXNlcnZlEV9iYXNlQXNzZXRSZXNlcnZlB19xdEFzdFcHX2JzQXN0VwQKcHJpY2VBZnRlcgkBBGRpdmQCCQEEbXVsZAIFEl9xdW90ZUFzc2V0UmVzZXJ2ZQUHX3F0QXN0VwkBBG11bGQCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUHX2JzQXN0VwQMYXZlcmFnZVByaWNlCQEEZGl2ZAIJAGQCBQxfb3JhY2xlUHJpY2UFCnByaWNlQWZ0ZXIJAGgCAAIFDERFQ0lNQUxfVU5JVAQMYWJzUHJpY2VEaWZmCQEEZGl2ZAIJAQNhYnMBCQBlAgUMX29yYWNsZVByaWNlBQpwcmljZUFmdGVyBQxhdmVyYWdlUHJpY2UFDGFic1ByaWNlRGlmZgEZcmVxdWlyZU5vdE92ZXJTcHJlYWRMaW1pdAISX3F1b3RlQXNzZXRSZXNlcnZlEV9iYXNlQXNzZXRSZXNlcnZlBAtvcmFjbGVQcmljZQkBDmdldE9yYWNsZVByaWNlAAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcABBJhYnNQcmljZURpZmZCZWZvcmUJAQxhYnNQcmljZURpZmYFBQtvcmFjbGVQcmljZQkBBnF0QXN0UgAJAQZic0FzdFIABQdfcXRBc3RXBQdfYnNBc3RXBBFhYnNQcmljZURpZmZBZnRlcgkBDGFic1ByaWNlRGlmZgUFC29yYWNsZVByaWNlBRJfcXVvdGVBc3NldFJlc2VydmUFEV9iYXNlQXNzZXRSZXNlcnZlBQdfcXRBc3RXBQdfYnNBc3RXAwMJAGYCBRFhYnNQcmljZURpZmZBZnRlcgkBDm1heFByaWNlU3ByZWFkAAkAZgIFEWFic1ByaWNlRGlmZkFmdGVyBRJhYnNQcmljZURpZmZCZWZvcmUHCQACAQkArAICCQCsAgIJAKwCAgINUHJpY2Ugc3ByZWFkIAkApAMBBRFhYnNQcmljZURpZmZBZnRlcgIUID4gbWF4IHByaWNlIHNwcmVhZCAJAKQDAQkBDm1heFByaWNlU3ByZWFkAAYBHXJlcXVpcmVOb3RPdmVyTWF4T3Blbk5vdGlvbmFsAhFfbG9uZ09wZW5Ob3Rpb25hbBJfc2hvcnRPcGVuTm90aW9uYWwEEF9tYXhPcGVuTm90aW9uYWwJAQ9tYXhPcGVuTm90aW9uYWwAAwkAZgIFEV9sb25nT3Blbk5vdGlvbmFsBRBfbWF4T3Blbk5vdGlvbmFsCQACAQkArAICCQCsAgIJAKwCAgITTG9uZyBvcGVuIG5vdGlvbmFsIAkApAMBBRFfbG9uZ09wZW5Ob3Rpb25hbAIVID4gbWF4IG9wZW4gbm90aW9uYWwgCQCkAwEFEF9tYXhPcGVuTm90aW9uYWwDCQBmAgUSX3Nob3J0T3Blbk5vdGlvbmFsBRBfbWF4T3Blbk5vdGlvbmFsCQACAQkArAICCQCsAgIJAKwCAgIUU2hvcnQgb3BlbiBub3Rpb25hbCAJAKQDAQUSX3Nob3J0T3Blbk5vdGlvbmFsAhUgPiBtYXggb3BlbiBub3Rpb25hbCAJAKQDAQUQX21heE9wZW5Ob3Rpb25hbAYBDGdldFNwb3RQcmljZQAEEl9xdW90ZUFzc2V0UmVzZXJ2ZQkBBnF0QXN0UgAEEV9iYXNlQXNzZXRSZXNlcnZlCQEGYnNBc3RSAAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcACQEEZGl2ZAIJAQRtdWxkAgUSX3F1b3RlQXNzZXRSZXNlcnZlBQdfcXRBc3RXCQEEbXVsZAIFEV9iYXNlQXNzZXRSZXNlcnZlBQdfYnNBc3RXARZpc092ZXJGbHVjdHVhdGlvbkxpbWl0AAQLb3JhY2xlUHJpY2UJAQ5nZXRPcmFjbGVQcmljZQAEDGN1cnJlbnRQcmljZQkBDGdldFNwb3RQcmljZQAJAGYCCQEEZGl2ZAIJAQNhYnMBCQBlAgULb3JhY2xlUHJpY2UFDGN1cnJlbnRQcmljZQULb3JhY2xlUHJpY2UJAQtzcHJlYWRMaW1pdAABH2dldFBvc2l0aW9uQWRqdXN0ZWRPcGVuTm90aW9uYWwGDV9wb3NpdGlvblNpemUHX29wdGlvbhJfcXVvdGVBc3NldFJlc2VydmURX3F1b3RlQXNzZXRXZWlnaHQRX2Jhc2VBc3NldFJlc2VydmUQX2Jhc2VBc3NldFdlaWdodAQPcG9zaXRpb25TaXplQWJzCQEDYWJzAQUNX3Bvc2l0aW9uU2l6ZQQHaXNTaG9ydAkAZgIAAAUNX3Bvc2l0aW9uU2l6ZQQQcG9zaXRpb25Ob3Rpb25hbAMJAAACBQdfb3B0aW9uBQ9QTkxfT1BUSU9OX1NQT1QEDSR0MDI0ODgyMjUxMDIJARZzd2FwT3V0cHV0V2l0aFJlc2VydmVzBwkBASEBBQdpc1Nob3J0BQ9wb3NpdGlvblNpemVBYnMHBRJfcXVvdGVBc3NldFJlc2VydmUFEV9xdW90ZUFzc2V0V2VpZ2h0BRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldFdlaWdodAQTb3V0UG9zaXRpb25Ob3Rpb25hbAgFDSR0MDI0ODgyMjUxMDICXzEEAngxCAUNJHQwMjQ4ODIyNTEwMgJfMgQCeDIIBQ0kdDAyNDg4MjI1MTAyAl8zBAJ4MwgFDSR0MDI0ODgyMjUxMDICXzQFE291dFBvc2l0aW9uTm90aW9uYWwJAQRtdWxkAgUPcG9zaXRpb25TaXplQWJzCQEOZ2V0T3JhY2xlUHJpY2UABRBwb3NpdGlvbk5vdGlvbmFsAStnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubEJ5VmFsdWVzBw1fcG9zaXRpb25TaXplFV9wb3NpdGlvbk9wZW5Ob3Rpb25hbBJfcXVvdGVBc3NldFJlc2VydmURX3F1b3RlQXNzZXRXZWlnaHQRX2Jhc2VBc3NldFJlc2VydmUQX2Jhc2VBc3NldFdlaWdodAdfb3B0aW9uAwkAAAIFDV9wb3NpdGlvblNpemUAAAkAAgECFUludmFsaWQgcG9zaXRpb24gc2l6ZQQHaXNTaG9ydAkAZgIAAAUNX3Bvc2l0aW9uU2l6ZQQQcG9zaXRpb25Ob3Rpb25hbAkBH2dldFBvc2l0aW9uQWRqdXN0ZWRPcGVuTm90aW9uYWwGBQ1fcG9zaXRpb25TaXplBQdfb3B0aW9uBRJfcXVvdGVBc3NldFJlc2VydmUFEV9xdW90ZUFzc2V0V2VpZ2h0BRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldFdlaWdodAQNdW5yZWFsaXplZFBubAMFB2lzU2hvcnQJAGUCBRVfcG9zaXRpb25PcGVuTm90aW9uYWwFEHBvc2l0aW9uTm90aW9uYWwJAGUCBRBwb3NpdGlvbk5vdGlvbmFsBRVfcG9zaXRpb25PcGVuTm90aW9uYWwJAJQKAgUQcG9zaXRpb25Ob3Rpb25hbAUNdW5yZWFsaXplZFBubAEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCB190cmFkZXIHX29wdGlvbgQNJHQwMjY1MjMyNjY1MQkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQMcG9zaXRpb25TaXplCAUNJHQwMjY1MjMyNjY1MQJfMQQOcG9zaXRpb25NYXJnaW4IBQ0kdDAyNjUyMzI2NjUxAl8yBBRwb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDI2NTIzMjY2NTECXzMEEXBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwMjY1MjMyNjY1MQJfNAkBK2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sQnlWYWx1ZXMHBQxwb3NpdGlvblNpemUFFHBvc2l0aW9uT3Blbk5vdGlvbmFsCQEGcXRBc3RSAAkBBnF0QXN0VwAJAQZic0FzdFIACQEGYnNBc3RXAAUHX29wdGlvbgEPY2FsY01hcmdpblJhdGlvAw1fcmVtYWluTWFyZ2luCF9iYWREZWJ0EV9wb3NpdGlvbk5vdGlvbmFsCQEEZGl2ZAIJAGUCBQ1fcmVtYWluTWFyZ2luBQhfYmFkRGVidAURX3Bvc2l0aW9uTm90aW9uYWwBFmdldE1hcmdpblJhdGlvQnlPcHRpb24CB190cmFkZXIHX29wdGlvbgQNJHQwMjcxNjQyNzI3NQkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQMcG9zaXRpb25TaXplCAUNJHQwMjcxNjQyNzI3NQJfMQQOcG9zaXRpb25NYXJnaW4IBQ0kdDAyNzE2NDI3Mjc1Al8yBANwb24IBQ0kdDAyNzE2NDI3Mjc1Al8zBBFwb3NpdGlvbkxzdFVwZENQRggFDSR0MDI3MTY0MjcyNzUCXzQEDSR0MDI3MjgxMjczNzQJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIFB190cmFkZXIFB19vcHRpb24EEHBvc2l0aW9uTm90aW9uYWwIBQ0kdDAyNzI4MTI3Mzc0Al8xBA11bnJlYWxpemVkUG5sCAUNJHQwMjcyODEyNzM3NAJfMgQNJHQwMjczNzkyNzU0NQkBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEBQxwb3NpdGlvblNpemUFDnBvc2l0aW9uTWFyZ2luBRFwb3NpdGlvbkxzdFVwZENQRgUNdW5yZWFsaXplZFBubAQMcmVtYWluTWFyZ2luCAUNJHQwMjczNzkyNzU0NQJfMQQHYmFkRGVidAgFDSR0MDI3Mzc5Mjc1NDUCXzIJAQ9jYWxjTWFyZ2luUmF0aW8DBQxyZW1haW5NYXJnaW4FB2JhZERlYnQFEHBvc2l0aW9uTm90aW9uYWwBDmdldE1hcmdpblJhdGlvAQdfdHJhZGVyCQEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAEbZ2V0UGFydGlhbExpcXVpZGF0aW9uQW1vdW50AgdfdHJhZGVyDV9wb3NpdGlvblNpemUEDG1heGltdW1SYXRpbwkBBHZtYXgCCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8ACQBlAgUMREVDSU1BTF9VTklUCQEEZGl2ZAIJAQ5nZXRNYXJnaW5SYXRpbwEFB190cmFkZXIJARZtYWludGVuYW5jZU1hcmdpblJhdGlvAAQYbWF4RXhjaGFuZ2VkUG9zaXRpb25TaXplCQEEbXVsZAIJAQNhYnMBBQ1fcG9zaXRpb25TaXplBQxtYXhpbXVtUmF0aW8ECnN3YXBSZXN1bHQJAQpzd2FwT3V0cHV0AwkAZgIFDV9wb3NpdGlvblNpemUAAAUYbWF4RXhjaGFuZ2VkUG9zaXRpb25TaXplBwQcbWF4RXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAgFCnN3YXBSZXN1bHQCXzEEC3ByaWNlSW1wYWN0CAUKc3dhcFJlc3VsdAJfNwMJAGYCCQEObWF4UHJpY2VJbXBhY3QABQtwcmljZUltcGFjdAUcbWF4RXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAQVZXhjaGFuZ2VkUG9zaXRpb25TaXplCQEEbXVsZAIJAQNhYnMBBQ1fcG9zaXRpb25TaXplCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8ABBlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CAkBCnN3YXBPdXRwdXQDCQBmAgUNX3Bvc2l0aW9uU2l6ZQAABRVleGNoYW5nZWRQb3NpdGlvblNpemUHAl8xBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50ARVpbnRlcm5hbENsb3NlUG9zaXRpb24CB190cmFkZXIUX2NoZWNrTWF4UHJpY2VJbXBhY3QEDSR0MDI4Nzg1Mjg5MTMJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIEDHBvc2l0aW9uU2l6ZQgFDSR0MDI4Nzg1Mjg5MTMCXzEEDnBvc2l0aW9uTWFyZ2luCAUNJHQwMjg3ODUyODkxMwJfMgQUcG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDAyODc4NTI4OTEzAl8zBBFwb3NpdGlvbkxzdFVwZENQRggFDSR0MDI4Nzg1Mjg5MTMCXzQEDXVucmVhbGl6ZWRQbmwICQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QCXzIEDSR0MDI5MDA4MjkxNzYJASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BAUMcG9zaXRpb25TaXplBQ5wb3NpdGlvbk1hcmdpbgURcG9zaXRpb25Mc3RVcGRDUEYFDXVucmVhbGl6ZWRQbmwEDHJlbWFpbk1hcmdpbggFDSR0MDI5MDA4MjkxNzYCXzEEB2JhZERlYnQIBQ0kdDAyOTAwODI5MTc2Al8yBBVleGNoYW5nZWRQb3NpdGlvblNpemUJAQEtAQUMcG9zaXRpb25TaXplBAtyZWFsaXplZFBubAUNdW5yZWFsaXplZFBubAQNbWFyZ2luVG9WYXVsdAkBAS0BBQxyZW1haW5NYXJnaW4EDSR0MDI5MzAzMjk1NzcJAQpzd2FwT3V0cHV0AwkAZgIFDHBvc2l0aW9uU2l6ZQAACQEDYWJzAQUMcG9zaXRpb25TaXplBRRfY2hlY2tNYXhQcmljZUltcGFjdAQZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAgFDSR0MDI5MzAzMjk1NzcCXzEEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDAyOTMwMzI5NTc3Al8yBBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDAyOTMwMzI5NTc3Al8zBBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwMjkzMDMyOTU3NwJfNAQOdG90YWxMb25nQWZ0ZXIIBQ0kdDAyOTMwMzI5NTc3Al81BA90b3RhbFNob3J0QWZ0ZXIIBQ0kdDAyOTMwMzI5NTc3Al82BBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCQBlAgkBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAAUUcG9zaXRpb25PcGVuTm90aW9uYWwJAJ8KDQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplBQdiYWREZWJ0BQtyZWFsaXplZFBubAUNbWFyZ2luVG9WYXVsdAUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyCQBlAgkBEG9wZW5JbnRlcmVzdExvbmcAAwkAZgIFDHBvc2l0aW9uU2l6ZQAABRRwb3NpdGlvbk9wZW5Ob3Rpb25hbAAACQBlAgkBEW9wZW5JbnRlcmVzdFNob3J0AAMJAGYCAAAFDHBvc2l0aW9uU2l6ZQUUcG9zaXRpb25PcGVuTm90aW9uYWwAAAEQZ2V0VHdhcFNwb3RQcmljZQAECG1pbnV0ZUlkCQBpAgkAaQIIBQlsYXN0QmxvY2sJdGltZXN0YW1wAOgHADwEDXN0YXJ0TWludXRlSWQJAGUCBQhtaW51dGVJZAUNVFdBUF9JTlRFUlZBTAQHbGlzdFN0cgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzBQ1rX2xhc3REYXRhU3RyAgAEBGxpc3QJALUJAgUHbGlzdFN0cgIBLAoBCGZpbHRlckZuAgthY2N1bXVsYXRvcgRuZXh0AwkAZwIFDXN0YXJ0TWludXRlSWQJAQ1wYXJzZUludFZhbHVlAQUEbmV4dAkAzQgCBQthY2N1bXVsYXRvcgkBDXBhcnNlSW50VmFsdWUBBQRuZXh0BQthY2N1bXVsYXRvcgQFbGlzdEYKAAIkbAUEbGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEIZmlsdGVyRm4CBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDIwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAA0ADgAPABAAEQASABMAFAQIbWF4SW5kZXgDCQBmAgkAkAMBBQVsaXN0RgAACQCWAwEFBWxpc3RGCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUEbGlzdAAABAxsYXN0TWludXRlSWQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUOa19sYXN0TWludXRlSWQAAAQWZW5kTGFzdEN1bXVsYXRpdmVQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UCAV8JAKQDAQUMbGFzdE1pbnV0ZUlkAAAEDGVuZExhc3RQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUTa190d2FwRGF0YUxhc3RQcmljZQIBXwkApAMBBQxsYXN0TWludXRlSWQAAAQSbm93Q3VtdWxhdGl2ZVByaWNlCQBkAgUWZW5kTGFzdEN1bXVsYXRpdmVQcmljZQkAaAIJAGUCBQhtaW51dGVJZAUMbGFzdE1pbnV0ZUlkBQxlbmRMYXN0UHJpY2UEGHN0YXJ0TGFzdEN1bXVsYXRpdmVQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UCAV8JAKQDAQUIbWF4SW5kZXgAAAQOc3RhcnRMYXN0UHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkArAICCQCsAgIFE2tfdHdhcERhdGFMYXN0UHJpY2UCAV8JAKQDAQUIbWF4SW5kZXgAAAQUc3RhcnRDdW11bGF0aXZlUHJpY2UJAGQCBRhzdGFydExhc3RDdW11bGF0aXZlUHJpY2UJAGgCCQBlAgUNc3RhcnRNaW51dGVJZAUIbWF4SW5kZXgFDnN0YXJ0TGFzdFByaWNlCQBpAgkAZQIFEm5vd0N1bXVsYXRpdmVQcmljZQUUc3RhcnRDdW11bGF0aXZlUHJpY2UFDVRXQVBfSU5URVJWQUwBE2dldFRlcm1pbmFsQW1tU3RhdGUABA1fcG9zaXRpb25TaXplCQERdG90YWxQb3NpdGlvblNpemUAAwkAAAIFDV9wb3NpdGlvblNpemUAAAkAlAoCCQEGcXRBc3RSAAkBBmJzQXN0UgAECWRpcmVjdGlvbgkAZgIFDV9wb3NpdGlvblNpemUAAAQNJHQwMzE3MDAzMTg3OQkBCnN3YXBPdXRwdXQDBQlkaXJlY3Rpb24JAQNhYnMBBQ1fcG9zaXRpb25TaXplBwQVY3VycmVudE5ldE1hcmtldFZhbHVlCAUNJHQwMzE3MDAzMTg3OQJfMQQZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQgFDSR0MDMxNzAwMzE4NzkCXzIEGHRlcm1pbmFsQmFzZUFzc2V0UmVzZXJ2ZQgFDSR0MDMxNzAwMzE4NzkCXzMJAJQKAgUZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQUYdGVybWluYWxCYXNlQXNzZXRSZXNlcnZlARNnZXRRdW90ZUFzc2V0V2VpZ2h0BBBiYXNlQXNzZXRSZXNlcnZlEXRvdGFsUG9zaXRpb25TaXplEXF1b3RlQXNzZXRSZXNlcnZlC3RhcmdldFByaWNlBAFiCQC2AgEFEGJhc2VBc3NldFJlc2VydmUEAnN6CQC2AgEFEXRvdGFsUG9zaXRpb25TaXplBAFxCQC2AgEFEXF1b3RlQXNzZXRSZXNlcnZlBAFwCQC2AgEFC3RhcmdldFByaWNlBANiczIJAQVicG93ZAIJALcCAgUBYgUCc3oJALYCAQkAaAIAAgUMREVDSU1BTF9VTklUBARxYnMyCQEFYm11bGQCBQFxBQNiczIEA3BzNAkAuQICCQC2AgEABAkBBWJtdWxkAgUBcAUCc3oEA3NxcgkBBmJzcXJ0ZAEJAQVibXVsZAIFBHFiczIJALgCAgUBcQUDcHM0BAJicQkBBWJtdWxkAgUBYgUBcQQCcXMJAQVibXVsZAIFAXEFAnN6BAN0b3AJALcCAgkAtwICCQC+AgEFA3NxcgUCYnEFAnFzBANib3QJALkCAgkAtgIBAAIJAQVibXVsZAIFAXEFAnN6BAZyZXN1bHQJAQViZGl2ZAIFA3RvcAUDYm90CQCgAwEFBnJlc3VsdAEUZ2V0U3luY1Rlcm1pbmFsUHJpY2UDDl90ZXJtaW5hbFByaWNlB19xdEFzdFIHX2JzQXN0UgQNX3Bvc2l0aW9uU2l6ZQkBEXRvdGFsUG9zaXRpb25TaXplAAMJAAACBQ1fcG9zaXRpb25TaXplAAAECW5ld1F0QXN0VwkBBGRpdmQCCQEEbXVsZAIFDl90ZXJtaW5hbFByaWNlBQdfYnNBc3RSBQdfcXRBc3RSCQCVCgMFCW5ld1F0QXN0VwUMREVDSU1BTF9VTklUAAAECWRpcmVjdGlvbgkAZgIFDV9wb3NpdGlvblNpemUAAAQVY3VycmVudE5ldE1hcmtldFZhbHVlCAkBCnN3YXBPdXRwdXQDBQlkaXJlY3Rpb24JAQNhYnMBBQ1fcG9zaXRpb25TaXplBwJfMQQJbmV3UXRBc3RXCQETZ2V0UXVvdGVBc3NldFdlaWdodAQFB19ic0FzdFIFDV9wb3NpdGlvblNpemUFB19xdEFzdFIFDl90ZXJtaW5hbFByaWNlBAluZXdCc0FzdFcFDERFQ0lNQUxfVU5JVAQNbWFyZ2luVG9WYXVsdAgJAStnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubEJ5VmFsdWVzBwUNX3Bvc2l0aW9uU2l6ZQUVY3VycmVudE5ldE1hcmtldFZhbHVlBQdfcXRBc3RSBQluZXdRdEFzdFcFB19ic0FzdFIFCW5ld0JzQXN0VwUPUE5MX09QVElPTl9TUE9UAl8yCQCVCgMFCW5ld1F0QXN0VwUJbmV3QnNBc3RXBQ1tYXJnaW5Ub1ZhdWx0AQpnZXRGdW5kaW5nAAQPdW5kZXJseWluZ1ByaWNlCQEOZ2V0T3JhY2xlUHJpY2UABA1zcG90VHdhcFByaWNlCQEQZ2V0VHdhcFNwb3RQcmljZQAEB3ByZW1pdW0JAGUCBQ1zcG90VHdhcFByaWNlBQ91bmRlcmx5aW5nUHJpY2UDAwMJAAACCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAAAAYJAAACCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAAABgkBDmlzTWFya2V0Q2xvc2VkAAkAlAoCAAAAAAMJAGYCAAAFB3ByZW1pdW0EFHNob3J0UHJlbWl1bUZyYWN0aW9uCQEEZGl2ZAIJAQRtdWxkAgUHcHJlbWl1bQkBFGZ1bmRpbmdQZXJpb2REZWNpbWFsAAUHT05FX0RBWQQTbG9uZ1ByZW1pdW1GcmFjdGlvbgkBBGRpdmQCCQEEbXVsZAIFFHNob3J0UHJlbWl1bUZyYWN0aW9uCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAJARV0b3RhbExvbmdQb3NpdGlvblNpemUACQCUCgIFFHNob3J0UHJlbWl1bUZyYWN0aW9uBRNsb25nUHJlbWl1bUZyYWN0aW9uBBNsb25nUHJlbWl1bUZyYWN0aW9uCQEEZGl2ZAIJAQRtdWxkAgUHcHJlbWl1bQkBFGZ1bmRpbmdQZXJpb2REZWNpbWFsAAUHT05FX0RBWQQUc2hvcnRQcmVtaXVtRnJhY3Rpb24JAQRkaXZkAgkBBG11bGQCBRNsb25nUHJlbWl1bUZyYWN0aW9uCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUACQCUCgIFFHNob3J0UHJlbWl1bUZyYWN0aW9uBRNsb25nUHJlbWl1bUZyYWN0aW9uAQ5nZXRBZGp1c3RlZEZlZQILX2FydGlmYWN0SWQQX2Jhc2VGZWVEaXNjb3VudAQKYmFzZUZlZVJhdwkBA2ZlZQAEB2Jhc2VGZWUJAQRtdWxkAgUKYmFzZUZlZVJhdwUQX2Jhc2VGZWVEaXNjb3VudAQNJHQwMzQ5MjczNTQyMgMJAQIhPQIFC19hcnRpZmFjdElkAgAEDGFydGlmYWN0S2luZAkBBHN0ckECCQERbmZ0TWFuYWdlckFkZHJlc3MACQEOdG9Db21wb3NpdGVLZXkCBQxrX3Rva2VuX3R5cGUFC19hcnRpZmFjdElkAwkAAAIFDGFydGlmYWN0S2luZAUYRkVFX1JFRFVDVElPTl9UT0tFTl9UWVBFBAlyZWR1Y3Rpb24JAQRpbnRBAgkBEW5mdE1hbmFnZXJBZGRyZXNzAAkBDnRvQ29tcG9zaXRlS2V5AgUNa190b2tlbl9wYXJhbQULX2FydGlmYWN0SWQEC2FkanVzdGVkRmVlCQEEbXVsZAIFB2Jhc2VGZWUFCXJlZHVjdGlvbgkAlAoCBQthZGp1c3RlZEZlZQYJAAIBAhlJbnZhbGlkIGF0dGFjaGVkIGFydGlmYWN0CQCUCgIFB2Jhc2VGZWUHBAthZGp1c3RlZEZlZQgFDSR0MDM0OTI3MzU0MjICXzEEDGJ1cm5BcnRpZmFjdAgFDSR0MDM0OTI3MzU0MjICXzIJAJQKAgULYWRqdXN0ZWRGZWUFDGJ1cm5BcnRpZmFjdAEXaXNTYW1lQXNzZXRPck5vUG9zaXRpb24CB190cmFkZXIIX2Fzc2V0SWQED29sZFBvc2l0aW9uU2l6ZQgJAQtnZXRQb3NpdGlvbgEFB190cmFkZXICXzEDCQAAAgUPb2xkUG9zaXRpb25TaXplAAAGCQAAAgkBEGdldFBvc2l0aW9uQXNzZXQBBQdfdHJhZGVyBQhfYXNzZXRJZAELaXNTYW1lQXNzZXQCB190cmFkZXIIX2Fzc2V0SWQJAAACCQEQZ2V0UG9zaXRpb25Bc3NldAEFB190cmFkZXIFCF9hc3NldElkAR5nZXRCb3Jyb3dlZEJ5VHJhZGVySW5NYXJrZXRLZXkDBF9hbW0IX2Fzc2V0SWQHX3RyYWRlcgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgUga190cmFkZXJfbWFya2V0X2Fzc2V0X2NvbGxhdGVyYWwCAV8FBF9hbW0CAV8FCF9hc3NldElkAgFfBQdfdHJhZGVyARNnZXRCb3Jyb3dlZEJ5VHJhZGVyAQdfdHJhZGVyBA1wb3NpdGlvbkFzc2V0CQEQZ2V0UG9zaXRpb25Bc3NldAEFB190cmFkZXIDCQAAAgUNcG9zaXRpb25Bc3NldAkA2AQBCQEKcXVvdGVBc3NldAAJAJQKAgAABQ1wb3NpdGlvbkFzc2V0BANrZXkJAR5nZXRCb3Jyb3dlZEJ5VHJhZGVySW5NYXJrZXRLZXkDCQClCAEFBHRoaXMFDXBvc2l0aW9uQXNzZXQFB190cmFkZXIEBmJvcnJvdwkBC3ZhbHVlT3JFbHNlAgkAmggCCQERY29sbGF0ZXJhbEFkZHJlc3MABQNrZXkAAAkAlAoCBQZib3Jyb3cFDXBvc2l0aW9uQXNzZXQBGGdldEZvclRyYWRlcldpdGhBcnRpZmFjdAIHX3RyYWRlcgtfYXJ0aWZhY3RJZAQQZG9HZXRGZWVEaXNjb3VudAkA/AcECQEMbWluZXJBZGRyZXNzAAISY29tcHV0ZUZlZURpc2NvdW50CQDMCAIFB190cmFkZXIFA25pbAUDbmlsAwkAAAIFEGRvR2V0RmVlRGlzY291bnQFEGRvR2V0RmVlRGlzY291bnQEC2ZlZURpc2NvdW50BAckbWF0Y2gwBRBkb0dldEZlZURpc2NvdW50AwkAAQIFByRtYXRjaDACA0ludAQBeAUHJG1hdGNoMAUBeAkAAgECIUludmFsaWQgY29tcHV0ZUZlZURpc2NvdW50IHJlc3VsdAQNJHQwMzY2NTMzNjcyNwkBDmdldEFkanVzdGVkRmVlAgULX2FydGlmYWN0SWQFC2ZlZURpc2NvdW50BAthZGp1c3RlZEZlZQgFDSR0MDM2NjUzMzY3MjcCXzEEDGJ1cm5BcnRpZmFjdAgFDSR0MDM2NjUzMzY3MjcCXzIJAJQKAgULYWRqdXN0ZWRGZWUFDGJ1cm5BcnRpZmFjdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgENZ2V0QXJ0aWZhY3RJZAEBaQQKYXJ0aWZhY3RJZAMJAGYCCQCQAwEIBQFpCHBheW1lbnRzAAEJANgEAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCAkAkQMCCAUBaQhwYXltZW50cwABB2Fzc2V0SWQCEkludmFsaWQgYXJ0aWZhY3RJZAIABQphcnRpZmFjdElkAQ1kaXN0cmlidXRlRmVlAQpfZmVlQW1vdW50BAxmZWVUb1N0YWtlcnMJAQRtdWxkAgUKX2ZlZUFtb3VudAkBE2ZlZVRvU3Rha2Vyc1BlcmNlbnQABApmZWVUb1ZhdWx0CQBlAgUKX2ZlZUFtb3VudAUMZmVlVG9TdGFrZXJzCQCUCgIFDGZlZVRvU3Rha2VycwUKZmVlVG9WYXVsdAEOdXBkYXRlU2V0dGluZ3MMEF9pbml0TWFyZ2luUmF0aW8EX21tchRfbGlxdWlkYXRpb25GZWVSYXRpbw5fZnVuZGluZ1BlcmlvZARfZmVlDF9zcHJlYWRMaW1pdA9fbWF4UHJpY2VJbXBhY3QYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvD19tYXhQcmljZVNwcmVhZBBfbWF4T3Blbk5vdGlvbmFsFF9mZWVUb1N0YWtlcnNQZXJjZW50D19tYXhPcmFjbGVEZWxheQkAzAgCCQEMSW50ZWdlckVudHJ5AgURa19pbml0TWFyZ2luUmF0aW8FEF9pbml0TWFyZ2luUmF0aW8JAMwIAgkBDEludGVnZXJFbnRyeQIFGGtfbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwUEX21tcgkAzAgCCQEMSW50ZWdlckVudHJ5AgUVa19saXF1aWRhdGlvbkZlZVJhdGlvBRRfbGlxdWlkYXRpb25GZWVSYXRpbwkAzAgCCQEMSW50ZWdlckVudHJ5AgUPa19mdW5kaW5nUGVyaW9kBQ5fZnVuZGluZ1BlcmlvZAkAzAgCCQEMSW50ZWdlckVudHJ5AgUFa19mZWUFBF9mZWUJAMwIAgkBDEludGVnZXJFbnRyeQIFDWtfc3ByZWFkTGltaXQFDF9zcHJlYWRMaW1pdAkAzAgCCQEMSW50ZWdlckVudHJ5AgUQa19tYXhQcmljZUltcGFjdAUPX21heFByaWNlSW1wYWN0CQDMCAIJAQxJbnRlZ2VyRW50cnkCBRlrX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvBRhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8JAMwIAgkBDEludGVnZXJFbnRyeQIFEGtfbWF4UHJpY2VTcHJlYWQFD19tYXhQcmljZVNwcmVhZAkAzAgCCQEMSW50ZWdlckVudHJ5AgURa19tYXhPcGVuTm90aW9uYWwFEF9tYXhPcGVuTm90aW9uYWwJAMwIAgkBDEludGVnZXJFbnRyeQIFFWtfZmVlVG9TdGFrZXJzUGVyY2VudAUUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQJAMwIAgkBDEludGVnZXJFbnRyeQIFEGtfbWF4T3JhY2xlRGVsYXkFFF9mZWVUb1N0YWtlcnNQZXJjZW50BQNuaWwBDXVwZGF0ZUZ1bmRpbmcFEV9uZXh0RnVuZGluZ0Jsb2NrJF9sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbiVfbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uEF9sb25nRnVuZGluZ1JhdGURX3Nob3J0RnVuZGluZ1JhdGUJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfbmV4dEZ1bmRpbmdCbG9jawURX25leHRGdW5kaW5nQmxvY2sJAMwIAgkBDEludGVnZXJFbnRyeQIFJWtfbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FJF9sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgUma19sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FJV9sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24JAMwIAgkBDEludGVnZXJFbnRyeQIFEWtfbG9uZ0Z1bmRpbmdSYXRlBRBfbG9uZ0Z1bmRpbmdSYXRlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJrX3Nob3J0RnVuZGluZ1JhdGUFEV9zaG9ydEZ1bmRpbmdSYXRlBQNuaWwBE3VwZGF0ZVBvc2l0aW9uQXNzZXQCCF9hZGRyZXNzCF9hc3NldElkCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFD2tfcG9zaXRpb25Bc3NldAUIX2FkZHJlc3MFCF9hc3NldElkBQNuaWwBH2luY3JlbWVudFBvc2l0aW9uU2VxdWVuY2VOdW1iZXICDWlzTmV3UG9zaXRpb24IX2FkZHJlc3MDBQ1pc05ld1Bvc2l0aW9uBA9jdXJyZW50U2VxdWVuY2UJAQxsYXN0U2VxdWVuY2UACQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRJrX3Bvc2l0aW9uU2VxdWVuY2UFCF9hZGRyZXNzCQBkAgUPY3VycmVudFNlcXVlbmNlAAEJAMwIAgkBDEludGVnZXJFbnRyeQIFCmtfc2VxdWVuY2UJAGQCBQ9jdXJyZW50U2VxdWVuY2UAAQUDbmlsBQNuaWwBDnVwZGF0ZVBvc2l0aW9uBQhfYWRkcmVzcwVfc2l6ZQdfbWFyZ2luDV9vcGVuTm90aW9uYWwgX2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24JAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFDmtfcG9zaXRpb25TaXplBQhfYWRkcmVzcwUFX3NpemUJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFEGtfcG9zaXRpb25NYXJnaW4FCF9hZGRyZXNzBQdfbWFyZ2luCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBQhfYWRkcmVzcwUNX29wZW5Ob3Rpb25hbAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUua19wb3NpdGlvbkxhc3RVcGRhdGVkQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUIX2FkZHJlc3MFIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBQNuaWwBCmFwcGVuZFR3YXABBl9wcmljZQQIbWludXRlSWQJAGkCCQBpAggFCWxhc3RCbG9jawl0aW1lc3RhbXAA6AcAPAQQcHJldmlvdXNNaW51dGVJZAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQ5rX2xhc3RNaW51dGVJZAAAAwkAZgIFEHByZXZpb3VzTWludXRlSWQFCG1pbnV0ZUlkCQACAQIRVFdBUCBvdXQtb2Ytb3JkZXIEDGxhc3RNaW51dGVJZAMJAAACBRBwcmV2aW91c01pbnV0ZUlkAAAFCG1pbnV0ZUlkBRBwcmV2aW91c01pbnV0ZUlkAwkAZgIFCG1pbnV0ZUlkBRBwcmV2aW91c01pbnV0ZUlkBBNwcmV2Q3VtdWxhdGl2ZVByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAKwCAgkArAICBR1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQIBXwkApAMBBRBwcmV2aW91c01pbnV0ZUlkAAAECXByZXZQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUTa190d2FwRGF0YUxhc3RQcmljZQIBXwkApAMBBRBwcmV2aW91c01pbnV0ZUlkBQZfcHJpY2UEE2xhc3RDdW11bGF0aXZlUHJpY2UJAGQCBRNwcmV2Q3VtdWxhdGl2ZVByaWNlCQBoAgkAZQIFCG1pbnV0ZUlkBQxsYXN0TWludXRlSWQFCXByZXZQcmljZQQEbGlzdAkBC3B1c2hUb1F1ZXVlAwkBCXN0clRvTGlzdAEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwUNa19sYXN0RGF0YVN0cgIABQ1UV0FQX0lOVEVSVkFMCQCkAwEFCG1pbnV0ZUlkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBR1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQkApAMBBQhtaW51dGVJZAUTbGFzdEN1bXVsYXRpdmVQcmljZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUTa190d2FwRGF0YUxhc3RQcmljZQkApAMBBQhtaW51dGVJZAUGX3ByaWNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRprX3R3YXBEYXRhUHJldmlvdXNNaW51dGVJZAkApAMBBQhtaW51dGVJZAUQcHJldmlvdXNNaW51dGVJZAkAzAgCCQEMSW50ZWdlckVudHJ5AgUOa19sYXN0TWludXRlSWQFCG1pbnV0ZUlkCQDMCAIJAQtTdHJpbmdFbnRyeQIFDWtfbGFzdERhdGFTdHIJAQlsaXN0VG9TdHIBBQRsaXN0BQNuaWwEGHR3YXBEYXRhUHJldmlvdXNNaW51dGVJZAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBRprX3R3YXBEYXRhUHJldmlvdXNNaW51dGVJZAkApAMBBQhtaW51dGVJZAAABBNwcmV2Q3VtdWxhdGl2ZVByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlCQCkAwEFGHR3YXBEYXRhUHJldmlvdXNNaW51dGVJZAAABAlwcmV2UHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUTa190d2FwRGF0YUxhc3RQcmljZQkApAMBBRh0d2FwRGF0YVByZXZpb3VzTWludXRlSWQFBl9wcmljZQQTbGFzdEN1bXVsYXRpdmVQcmljZQkAZAIFE3ByZXZDdW11bGF0aXZlUHJpY2UJAGgCCQBlAgUIbWludXRlSWQFGHR3YXBEYXRhUHJldmlvdXNNaW51dGVJZAUJcHJldlByaWNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBR1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQkApAMBBQhtaW51dGVJZAUTbGFzdEN1bXVsYXRpdmVQcmljZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUTa190d2FwRGF0YUxhc3RQcmljZQkApAMBBQhtaW51dGVJZAUGX3ByaWNlBQNuaWwBEXVwZGF0ZUFtbVJlc2VydmVzAgdfcXRBc3RSB19ic0FzdFIJAMwIAgkBDEludGVnZXJFbnRyeQIFE2tfcXVvdGVBc3NldFJlc2VydmUFB19xdEFzdFIJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfYmFzZUFzc2V0UmVzZXJ2ZQUHX2JzQXN0UgUDbmlsARB1cGRhdGVBbW1XZWlnaHRzAgdfcXRBc3RXB19ic0FzdFcJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfcXVvdGVBc3NldFdlaWdodAUHX3F0QXN0VwkAzAgCCQEMSW50ZWdlckVudHJ5AgURa19iYXNlQXNzZXRXZWlnaHQFB19ic0FzdFcFA25pbAEJdXBkYXRlQW1tCAdfcXRBc3RSB19ic0FzdFIXX3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIVX29wZW5JbnRlcmVzdE5vdGlvbmFsFl90b3RhbExvbmdQb3NpdGlvblNpemUXX3RvdGFsU2hvcnRQb3NpdGlvblNpemUWX3RvdGFsTG9uZ09wZW5Ob3Rpb25hbBdfdG90YWxTaG9ydE9wZW5Ob3Rpb25hbAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcAAwkBAiE9AgkAZQIFFl90b3RhbExvbmdQb3NpdGlvblNpemUFF190b3RhbFNob3J0UG9zaXRpb25TaXplBRdfdG90YWxQb3NpdGlvblNpemVBZnRlcgkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAhhJbnZhbGlkIEFNTSBzdGF0ZSBkYXRhOiAJAKQDAQUWX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQIEICsgIAkApAMBBRdfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQIEICE9IAkApAMBBRdfdG90YWxQb3NpdGlvblNpemVBZnRlcgkAzggCCQDOCAIJARF1cGRhdGVBbW1SZXNlcnZlcwIFB19xdEFzdFIFB19ic0FzdFIJAMwIAgkBDEludGVnZXJFbnRyeQIFE2tfdG90YWxQb3NpdGlvblNpemUFF190b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRZrX29wZW5JbnRlcmVzdE5vdGlvbmFsBRVfb3BlbkludGVyZXN0Tm90aW9uYWwJAMwIAgkBDEludGVnZXJFbnRyeQIFF2tfdG90YWxMb25nUG9zaXRpb25TaXplBRZfdG90YWxMb25nUG9zaXRpb25TaXplCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRhrX3RvdGFsU2hvcnRQb3NpdGlvblNpemUFF190b3RhbFNob3J0UG9zaXRpb25TaXplCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJrX29wZW5JbnRlcmVzdExvbmcFFl90b3RhbExvbmdPcGVuTm90aW9uYWwJAMwIAgkBDEludGVnZXJFbnRyeQIFE2tfb3BlbkludGVyZXN0U2hvcnQFF190b3RhbFNob3J0T3Blbk5vdGlvbmFsBQNuaWwJAQphcHBlbmRUd2FwAQkBBGRpdmQCCQEEbXVsZAIFB19xdEFzdFIFB19xdEFzdFcJAQRtdWxkAgUHX2JzQXN0UgUHX2JzQXN0VwEOZGVsZXRlUG9zaXRpb24BCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFDmtfcG9zaXRpb25TaXplBQhfYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBRBrX3Bvc2l0aW9uTWFyZ2luBQhfYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBRZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBQhfYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBS5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBQhfYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBQ9rX3Bvc2l0aW9uQXNzZXQFCF9hZGRyZXNzBQNuaWwBCHdpdGhkcmF3AghfYWRkcmVzcwdfYW1vdW50BAdiYWxhbmNlCQDwBwIFBHRoaXMJAQpxdW90ZUFzc2V0AAMJAGYCBQdfYW1vdW50BQdiYWxhbmNlCQACAQkArAICCQCsAgIJAKwCAgITVW5hYmxlIHRvIHdpdGhkcmF3IAkApAMBBQdfYW1vdW50AhcgZnJvbSBjb250cmFjdCBiYWxhbmNlIAkApAMBBQdiYWxhbmNlCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFCF9hZGRyZXNzBQdfYW1vdW50CQEKcXVvdGVBc3NldAAFA25pbAENdXBkYXRlQmFsYW5jZQEBaQMJAGYCAAAFAWkJAAIBAgdCYWxhbmNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQlrX2JhbGFuY2UFAWkFA25pbAELdHJhbnNmZXJGZWUBAWkJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwkBDnN0YWtpbmdBZGRyZXNzAAUBaQkBCnF1b3RlQXNzZXQABQNuaWwBDmRvQnVybkFydGlmYWN0Ag1fYnVybkFydGlmYWN0AWkDBQ1fYnVybkFydGlmYWN0CQDMCAIJAQRCdXJuAgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCAkAkQMCCAUBaQhwYXltZW50cwABB2Fzc2V0SWQCEEludmFsaWQgYXJ0aWZhY3QAAQUDbmlsBQNuaWwXAWkBBXBhdXNlAAMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAhRJbnZhbGlkIHBhdXNlIHBhcmFtcwkAzAgCCQEMQm9vbGVhbkVudHJ5AgUIa19wYXVzZWQGBQNuaWwBaQEHdW5wYXVzZQADCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MACQACAQIWSW52YWxpZCB1bnBhdXNlIHBhcmFtcwkAzAgCCQEMQm9vbGVhbkVudHJ5AgUIa19wYXVzZWQHBQNuaWwBaQEMc2V0Q2xvc2VPbmx5AAMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAhtJbnZhbGlkIHNldENsb3NlT25seSBwYXJhbXMJAMwIAgkBDEJvb2xlYW5FbnRyeQIFC2tfY2xvc2VPbmx5BgUDbmlsAWkBDnVuc2V0Q2xvc2VPbmx5AAMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAh1JbnZhbGlkIHVuc2V0Q2xvc2VPbmx5IHBhcmFtcwkAzAgCCQEMQm9vbGVhbkVudHJ5AgULa19jbG9zZU9ubHkHBQNuaWwBaQEMYWRkTGlxdWlkaXR5ARFfcXVvdGVBc3NldEFtb3VudAMDCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MABgkAZwIAAAURX3F1b3RlQXNzZXRBbW91bnQJAAIBAhtJbnZhbGlkIGFkZExpcXVpZGl0eSBwYXJhbXMEB19xdEFzdFIJAQZxdEFzdFIABAdfYnNBc3RSCQEGYnNBc3RSAAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcABAVwcmljZQkBBGRpdmQCCQEEbXVsZAIFB19xdEFzdFIFB19xdEFzdFcJAQRtdWxkAgUHX2JzQXN0UgUHX2JzQXN0VwQLcXRBc3RSQWZ0ZXIJAGQCBQdfcXRBc3RSBRFfcXVvdGVBc3NldEFtb3VudAQUYmFzZUFzc2V0QW1vdW50VG9BZGQJAGUCCQEEZGl2ZAIJAQRtdWxkAgULcXRBc3RSQWZ0ZXIFB19xdEFzdFcFBXByaWNlBQdfYnNBc3RSBAtic0FzdFJBZnRlcgkAZAIFB19ic0FzdFIFFGJhc2VBc3NldEFtb3VudFRvQWRkBA0kdDA0NTc0OTQ1OTAwCQEUZ2V0U3luY1Rlcm1pbmFsUHJpY2UDCQEOZ2V0T3JhY2xlUHJpY2UABQtxdEFzdFJBZnRlcgULYnNBc3RSQWZ0ZXIEE25ld1F1b3RlQXNzZXRXZWlnaHQIBQ0kdDA0NTc0OTQ1OTAwAl8xBBJuZXdCYXNlQXNzZXRXZWlnaHQIBQ0kdDA0NTc0OTQ1OTAwAl8yBA1tYXJnaW5Ub1ZhdWx0CAUNJHQwNDU3NDk0NTkwMAJfMwQNZG9FeGNoYW5nZVBuTAMJAQIhPQIFDW1hcmdpblRvVmF1bHQAAAQNZG9FeGNoYW5nZVBuTAkA/AcECQEMdmF1bHRBZGRyZXNzAAIVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkCQDMCAIFDW1hcmdpblRvVmF1bHQFA25pbAUDbmlsAwkAAAIFDWRvRXhjaGFuZ2VQbkwFDWRvRXhjaGFuZ2VQbkwFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFDWRvRXhjaGFuZ2VQbkwFDWRvRXhjaGFuZ2VQbkwJAM4IAgkBEXVwZGF0ZUFtbVJlc2VydmVzAgULcXRBc3RSQWZ0ZXIFC2JzQXN0UkFmdGVyCQEQdXBkYXRlQW1tV2VpZ2h0cwIFE25ld1F1b3RlQXNzZXRXZWlnaHQFEm5ld0Jhc2VBc3NldFdlaWdodAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ9yZW1vdmVMaXF1aWRpdHkBEV9xdW90ZUFzc2V0QW1vdW50AwMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAGCQBnAgAABRFfcXVvdGVBc3NldEFtb3VudAkAAgECHkludmFsaWQgcmVtb3ZlTGlxdWlkaXR5IHBhcmFtcwQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwAEBXByaWNlCQEEZGl2ZAIJAQRtdWxkAgUHX3F0QXN0UgUHX3F0QXN0VwkBBG11bGQCBQdfYnNBc3RSBQdfYnNBc3RXBBdiYXNlQXNzZXRBbW91bnRUb1JlbW92ZQkBBGRpdmQCBRFfcXVvdGVBc3NldEFtb3VudAUFcHJpY2UEC3F0QXN0UkFmdGVyCQBlAgUHX3F0QXN0UgURX3F1b3RlQXNzZXRBbW91bnQEC2JzQXN0UkFmdGVyCQBlAgUHX2JzQXN0UgUXYmFzZUFzc2V0QW1vdW50VG9SZW1vdmUJARF1cGRhdGVBbW1SZXNlcnZlcwIFC3F0QXN0UkFmdGVyBQtic0FzdFJBZnRlcgFpAQ5jaGFuZ2VTZXR0aW5ncwwQX2luaXRNYXJnaW5SYXRpbwRfbW1yFF9saXF1aWRhdGlvbkZlZVJhdGlvDl9mdW5kaW5nUGVyaW9kBF9mZWUMX3NwcmVhZExpbWl0D19tYXhQcmljZUltcGFjdBhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8PX21heFByaWNlU3ByZWFkEF9tYXhPcGVuTm90aW9uYWwUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQPX21heE9yYWNsZURlbGF5AwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECHUludmFsaWQgY2hhbmdlU2V0dGluZ3MgcGFyYW1zCQEOdXBkYXRlU2V0dGluZ3MMBRBfaW5pdE1hcmdpblJhdGlvBQRfbW1yBRRfbGlxdWlkYXRpb25GZWVSYXRpbwUOX2Z1bmRpbmdQZXJpb2QFBF9mZWUFDF9zcHJlYWRMaW1pdAUPX21heFByaWNlSW1wYWN0BRhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8FD19tYXhQcmljZVNwcmVhZAUQX21heE9wZW5Ob3Rpb25hbAUUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQFD19tYXhPcmFjbGVEZWxheQFpAQppbml0aWFsaXplEgdfcXRBc3RSB19ic0FzdFIOX2Z1bmRpbmdQZXJpb2QQX2luaXRNYXJnaW5SYXRpbwRfbW1yFF9saXF1aWRhdGlvbkZlZVJhdGlvBF9mZWUHX29yYWNsZQpfb3JhY2xlS2V5D19vcmFjbGVCbG9ja0tleQxfY29vcmRpbmF0b3IMX3NwcmVhZExpbWl0D19tYXhQcmljZUltcGFjdBhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8PX21heFByaWNlU3ByZWFkEF9tYXhPcGVuTm90aW9uYWwUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQPX21heE9yYWNsZURlbGF5AwMDAwMDAwMDAwMDAwMDAwkAZwIAAAUHX3F0QXN0UgYJAGcCAAAFB19ic0FzdFIGCQBnAgAABQ5fZnVuZGluZ1BlcmlvZAYJAGcCAAAFEF9pbml0TWFyZ2luUmF0aW8GCQBnAgAABQRfbW1yBgkAZwIAAAUUX2xpcXVpZGF0aW9uRmVlUmF0aW8GCQBnAgAABQRfZmVlBgkAZwIAAAUMX3NwcmVhZExpbWl0BgkAZwIAAAUPX21heFByaWNlSW1wYWN0BgkAZwIAAAUYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvBgkAZwIAAAUPX21heFByaWNlU3ByZWFkBgkAZwIAAAUQX21heE9wZW5Ob3Rpb25hbAYJAGcCAAAFFF9mZWVUb1N0YWtlcnNQZXJjZW50BgkAZgIFFF9mZWVUb1N0YWtlcnNQZXJjZW50BQxERUNJTUFMX1VOSVQGCQBnAgAABQ9fbWF4T3JhY2xlRGVsYXkGCQELaW5pdGlhbGl6ZWQACQACAQIdSW52YWxpZCBpbml0aWFsaXplIHBhcmFtZXRlcnMJAM4IAgkAzggCCQDOCAIJAM4IAgkBCXVwZGF0ZUFtbQgFB19xdEFzdFIFB19ic0FzdFIAAAAAAAAAAAAAAAAJAQ51cGRhdGVTZXR0aW5ncwwFEF9pbml0TWFyZ2luUmF0aW8FBF9tbXIFFF9saXF1aWRhdGlvbkZlZVJhdGlvBQ5fZnVuZGluZ1BlcmlvZAUEX2ZlZQUMX3NwcmVhZExpbWl0BQ9fbWF4UHJpY2VJbXBhY3QFGF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwUPX21heFByaWNlU3ByZWFkBRBfbWF4T3Blbk5vdGlvbmFsBRRfZmVlVG9TdGFrZXJzUGVyY2VudAUPX21heE9yYWNsZURlbGF5CQENdXBkYXRlRnVuZGluZwUJAGQCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAUOX2Z1bmRpbmdQZXJpb2QAAAAAAAAAAAkBDXVwZGF0ZUJhbGFuY2UBAAAJAMwIAgkBDEJvb2xlYW5FbnRyeQIFDWtfaW5pdGlhbGl6ZWQGCQDMCAIJAQtTdHJpbmdFbnRyeQIFBWtfb3JhBQdfb3JhY2xlCQDMCAIJAQtTdHJpbmdFbnRyeQIFCWtfb3JhX2tleQUKX29yYWNsZUtleQkAzAgCCQELU3RyaW5nRW50cnkCBQ9rX29yYV9ibG9ja19rZXkFD19vcmFjbGVCbG9ja0tleQkAzAgCCQELU3RyaW5nRW50cnkCBRRrX2Nvb3JkaW5hdG9yQWRkcmVzcwUMX2Nvb3JkaW5hdG9yBQNuaWwBaQEQZGVjcmVhc2VQb3NpdGlvbgMHX2Ftb3VudAlfbGV2ZXJhZ2UTX21pbkJhc2VBc3NldEFtb3VudAQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBAdfdHJhZGVyCQEPZ2V0QWN0dWFsQ2FsbGVyAQUBaQMDAwMDAwkAZwIAAAUHX2Ftb3VudAYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQEhAQkBFnJlcXVpcmVNb3JlTWFyZ2luUmF0aW8DCQEEZGl2ZAIFDERFQ0lNQUxfVU5JVAUJX2xldmVyYWdlCQEPaW5pdE1hcmdpblJhdGlvAAYGCQEBIQEJARNyZXF1aXJlT3BlblBvc2l0aW9uAQUHX3RyYWRlcgYJAQZwYXVzZWQABgkBDmlzTWFya2V0Q2xvc2VkAAkAAgECI0ludmFsaWQgZGVjcmVhc2VQb3NpdGlvbiBwYXJhbWV0ZXJzBA0kdDA0OTc2NzQ5OTA3CQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBA9vbGRQb3NpdGlvblNpemUIBQ0kdDA0OTc2NzQ5OTA3Al8xBBFvbGRQb3NpdGlvbk1hcmdpbggFDSR0MDQ5NzY3NDk5MDcCXzIEF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNDk3Njc0OTkwNwJfMwQUb2xkUG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA0OTc2NzQ5OTA3Al80BApfZGlyZWN0aW9uAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAABQlESVJfU0hPUlQFCERJUl9MT05HBAVpc0FkZAkAAAIFCl9kaXJlY3Rpb24FCERJUl9MT05HBAxvcGVuTm90aW9uYWwJAQRtdWxkAgUHX2Ftb3VudAUJX2xldmVyYWdlBA0kdDA1MDA4MDUwMTg0CQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QEE29sZFBvc2l0aW9uTm90aW9uYWwIBQ0kdDA1MDA4MDUwMTg0Al8xBA11bnJlYWxpemVkUG5sCAUNJHQwNTAwODA1MDE4NAJfMgQNJHQwNTAxOTA1Mjg0OAMJAGYCBRNvbGRQb3NpdGlvbk5vdGlvbmFsBQxvcGVuTm90aW9uYWwEDSR0MDUwNjA1NTA3ODkJAQlzd2FwSW5wdXQCBQVpc0FkZAUMb3Blbk5vdGlvbmFsBBVleGNoYW5nZWRQb3NpdGlvblNpemUIBQ0kdDA1MDYwNTUwNzg5Al8xBBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNTA2MDU1MDc4OQJfMgQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNTA2MDU1MDc4OQJfMwQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDUwNjA1NTA3ODkCXzQEGGV4Y2hhbmdlZFBvc2l0aW9uU2l6ZUFicwkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQMDCQECIT0CBRNfbWluQmFzZUFzc2V0QW1vdW50AAAJAGYCBRNfbWluQmFzZUFzc2V0QW1vdW50BRhleGNoYW5nZWRQb3NpdGlvblNpemVBYnMHCQACAQkArAICCQCsAgIJAKwCAgIlVG9vIGxpdHRsZSBiYXNlIGFzc2V0IGV4Y2hhbmdlZCwgZ290IAkApAMBBRhleGNoYW5nZWRQb3NpdGlvblNpemVBYnMCCiBleHBlY3RlZCAJAKQDAQUTX21pbkJhc2VBc3NldEFtb3VudAQLcmVhbGl6ZWRQbmwJAQRkaXZkAgkBBG11bGQCBQ11bnJlYWxpemVkUG5sBRhleGNoYW5nZWRQb3NpdGlvblNpemVBYnMJAQNhYnMBBQ9vbGRQb3NpdGlvblNpemUEDSR0MDUxMjI2NTE0NzEJASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BAUPb2xkUG9zaXRpb25TaXplBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25Mc3RVcGRDUEYFC3JlYWxpemVkUG5sBAxyZW1haW5NYXJnaW4IBQ0kdDA1MTIyNjUxNDcxAl8xBAdiYWREZWJ0CAUNJHQwNTEyMjY1MTQ3MQJfMgQOZnVuZGluZ1BheW1lbnQIBQ0kdDA1MTIyNjUxNDcxAl8zBBlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BQxvcGVuTm90aW9uYWwEEnVucmVhbGl6ZWRQbmxBZnRlcgkAZQIFDXVucmVhbGl6ZWRQbmwFC3JlYWxpemVkUG5sBBJyZW1haW5PcGVuTm90aW9uYWwDCQBmAgUPb2xkUG9zaXRpb25TaXplAAAJAGUCCQBlAgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAUSdW5yZWFsaXplZFBubEFmdGVyCQBlAgkAZAIFEnVucmVhbGl6ZWRQbmxBZnRlcgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAQPbmV3UG9zaXRpb25TaXplCQBkAgUPb2xkUG9zaXRpb25TaXplBRVleGNoYW5nZWRQb3NpdGlvblNpemUJAJ4KDAUPbmV3UG9zaXRpb25TaXplBQxyZW1haW5NYXJnaW4JAQNhYnMBBRJyZW1haW5PcGVuTm90aW9uYWwJAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUPbmV3UG9zaXRpb25TaXplBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIJAGUCCQEUb3BlbkludGVyZXN0Tm90aW9uYWwABQxvcGVuTm90aW9uYWwJAGUCCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAMJAGYCBQ9uZXdQb3NpdGlvblNpemUAAAkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQAACQBlAgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUAAwkAZgIAAAUPbmV3UG9zaXRpb25TaXplCQEDYWJzAQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplAAAJAGUCCQEQb3BlbkludGVyZXN0TG9uZwADCQBmAgUPbmV3UG9zaXRpb25TaXplAAAFDG9wZW5Ob3Rpb25hbAAACQBlAgkBEW9wZW5JbnRlcmVzdFNob3J0AAMJAGYCAAAFD25ld1Bvc2l0aW9uU2l6ZQUMb3Blbk5vdGlvbmFsAAAJAAIBAhRDbG9zZSBwb3NpdGlvbiBmaXJzdAQPbmV3UG9zaXRpb25TaXplCAUNJHQwNTAxOTA1Mjg0OAJfMQQXbmV3UG9zaXRpb25SZW1haW5NYXJnaW4IBQ0kdDA1MDE5MDUyODQ4Al8yBBduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDUwMTkwNTI4NDgCXzMEFG5ld1Bvc2l0aW9uTGF0ZXN0Q1BGCAUNJHQwNTAxOTA1Mjg0OAJfNAQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNTAxOTA1Mjg0OAJfNQQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDUwMTkwNTI4NDgCXzYEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA1MDE5MDUyODQ4Al83BBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCAUNJHQwNTAxOTA1Mjg0OAJfOAQOdG90YWxMb25nQWZ0ZXIIBQ0kdDA1MDE5MDUyODQ4Al85BA90b3RhbFNob3J0QWZ0ZXIIBQ0kdDA1MDE5MDUyODQ4A18xMAQadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA1MDE5MDUyODQ4A18xMQQbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNTAxOTA1Mjg0OANfMTIEDm5vdGlmeU5vdGlvbmFsCQD8BwQJAQxtaW5lckFkZHJlc3MAAg5ub3RpZnlOb3Rpb25hbAkAzAgCBQdfdHJhZGVyCQDMCAIFF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBQNuaWwFA25pbAMJAAACBQ5ub3RpZnlOb3Rpb25hbAUObm90aWZ5Tm90aW9uYWwJAM4IAgkBDnVwZGF0ZVBvc2l0aW9uBQUHX3RyYWRlcgUPbmV3UG9zaXRpb25TaXplBRduZXdQb3NpdGlvblJlbWFpbk1hcmdpbgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFFG5ld1Bvc2l0aW9uTGF0ZXN0Q1BGCQEJdXBkYXRlQW1tCAUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyBRp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgUbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBEGluY3JlYXNlUG9zaXRpb24ECl9kaXJlY3Rpb24JX2xldmVyYWdlE19taW5CYXNlQXNzZXRBbW91bnQIX3JlZkxpbmsEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQHX3RyYWRlcgkBD2dldEFjdHVhbENhbGxlcgEFAWkECl9yYXdBbW91bnQICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50BAhfYXNzZXRJZAgJAJEDAggFAWkIcGF5bWVudHMAAAdhc3NldElkBAtfYXNzZXRJZFN0cgkA2AQBCQEFdmFsdWUBBQhfYXNzZXRJZAQMaXNRdW90ZUFzc2V0CQAAAgUIX2Fzc2V0SWQJAQpxdW90ZUFzc2V0AAQRaXNDb2xsYXRlcmFsQXNzZXQJARBpc1doaXRlbGlzdEFzc2V0AQULX2Fzc2V0SWRTdHIDAwMDAwMDAwMDCQECIT0CBQpfZGlyZWN0aW9uBQhESVJfTE9ORwkBAiE9AgUKX2RpcmVjdGlvbgUJRElSX1NIT1JUBwYJAGcCAAAFCl9yYXdBbW91bnQGCQEBIQEJAQtpbml0aWFsaXplZAAGAwkBASEBBQxpc1F1b3RlQXNzZXQJAQEhAQURaXNDb2xsYXRlcmFsQXNzZXQHBgkBASEBCQEXaXNTYW1lQXNzZXRPck5vUG9zaXRpb24CBQdfdHJhZGVyBQtfYXNzZXRJZFN0cgYJAQEhAQkBFnJlcXVpcmVNb3JlTWFyZ2luUmF0aW8DCQEEZGl2ZAIFDERFQ0lNQUxfVU5JVAUJX2xldmVyYWdlCQEPaW5pdE1hcmdpblJhdGlvAAYGCQEGcGF1c2VkAAYJAQljbG9zZU9ubHkABgkBDmlzTWFya2V0Q2xvc2VkAAkAAgECI0ludmFsaWQgaW5jcmVhc2VQb3NpdGlvbiBwYXJhbWV0ZXJzBA0kdDA1NDMxMDU0Mzk1CQEYZ2V0Rm9yVHJhZGVyV2l0aEFydGlmYWN0AgUHX3RyYWRlcgkBDWdldEFydGlmYWN0SWQBBQFpBAthZGp1c3RlZEZlZQgFDSR0MDU0MzEwNTQzOTUCXzEEDGJ1cm5BcnRpZmFjdAgFDSR0MDU0MzEwNTQzOTUCXzIEDHJhd0ZlZUFtb3VudAkBBG11bGQCBQpfcmF3QW1vdW50BQthZGp1c3RlZEZlZQQHX2Ftb3VudAkAZQIFCl9yYXdBbW91bnQFDHJhd0ZlZUFtb3VudAQTZGlzdHJpYnV0ZUZlZUFtb3VudAMFEWlzQ29sbGF0ZXJhbEFzc2V0BAhkb0JvcnJvdwkA/AcECQERY29sbGF0ZXJhbEFkZHJlc3MAAgZib3Jyb3cJAMwIAgUHX3RyYWRlcgUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQhfYXNzZXRJZAUHX2Ftb3VudAUDbmlsAwkAAAIFCGRvQm9ycm93BQhkb0JvcnJvdwQNYmFsYW5jZUJlZm9yZQkA8AcCBQR0aGlzCQEKcXVvdGVBc3NldAADCQAAAgUNYmFsYW5jZUJlZm9yZQUNYmFsYW5jZUJlZm9yZQQGZG9Td2FwCQD8BwQJAQtzd2FwQWRkcmVzcwACBHN3YXAJAMwIAgkA2AQBCQEKcXVvdGVBc3NldAAJAMwIAgAABQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFCF9hc3NldElkBQxyYXdGZWVBbW91bnQFA25pbAMJAAACBQZkb1N3YXAFBmRvU3dhcAQMYmFsYW5jZUFmdGVyCQDwBwIFBHRoaXMJAQpxdW90ZUFzc2V0AAMJAAACBQxiYWxhbmNlQWZ0ZXIFDGJhbGFuY2VBZnRlcgQPZXhjaGFuZ2VkQW1vdW50CQBlAgUMYmFsYW5jZUFmdGVyBQ1iYWxhbmNlQmVmb3JlAwkAAAIFD2V4Y2hhbmdlZEFtb3VudAUPZXhjaGFuZ2VkQW1vdW50BQ9leGNoYW5nZWRBbW91bnQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FDHJhd0ZlZUFtb3VudAMJAAACBRNkaXN0cmlidXRlRmVlQW1vdW50BRNkaXN0cmlidXRlRmVlQW1vdW50BA5yZWZlcnJlckZlZUFueQkA/AcECQEPcmVmZXJyYWxBZGRyZXNzAAIVYWNjZXB0UGF5bWVudFdpdGhMaW5rCQDMCAIFB190cmFkZXIJAMwIAgUIX3JlZkxpbmsFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABRNkaXN0cmlidXRlRmVlQW1vdW50BQNuaWwDCQAAAgUOcmVmZXJyZXJGZWVBbnkFDnJlZmVycmVyRmVlQW55BAtyZWZlcnJlckZlZQQHJG1hdGNoMAUOcmVmZXJyZXJGZWVBbnkDCQABAgUHJG1hdGNoMAIDSW50BAF4BQckbWF0Y2gwBQF4CQACAQITSW52YWxpZCByZWZlcnJlckZlZQQJZmVlQW1vdW50CQBlAgUTZGlzdHJpYnV0ZUZlZUFtb3VudAULcmVmZXJyZXJGZWUEDSR0MDU1NzExNTU4NTEJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIED29sZFBvc2l0aW9uU2l6ZQgFDSR0MDU1NzExNTU4NTECXzEEEW9sZFBvc2l0aW9uTWFyZ2luCAUNJHQwNTU3MTE1NTg1MQJfMgQXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA1NTcxMTU1ODUxAl8zBBRvbGRQb3NpdGlvbkxzdFVwZENQRggFDSR0MDU1NzExNTU4NTECXzQEDWlzTmV3UG9zaXRpb24JAAACBQ9vbGRQb3NpdGlvblNpemUAAAQPaXNTYW1lRGlyZWN0aW9uAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAACQAAAgUKX2RpcmVjdGlvbgUIRElSX0xPTkcJAAACBQpfZGlyZWN0aW9uBQlESVJfU0hPUlQEDmV4cGFuZEV4aXN0aW5nAwkBASEBBQ1pc05ld1Bvc2l0aW9uBQ9pc1NhbWVEaXJlY3Rpb24HBAVpc0FkZAkAAAIFCl9kaXJlY3Rpb24FCERJUl9MT05HBA0kdDA1NjE0MDU5MTgxAwMFDWlzTmV3UG9zaXRpb24GBQ5leHBhbmRFeGlzdGluZwQMb3Blbk5vdGlvbmFsCQEEbXVsZAIFB19hbW91bnQFCV9sZXZlcmFnZQQNJHQwNTY2MDI1Njc3NQkBCXN3YXBJbnB1dAIFBWlzQWRkBQxvcGVuTm90aW9uYWwEFWFtb3VudEJhc2VBc3NldEJvdWdodAgFDSR0MDU2NjAyNTY3NzUCXzEEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA1NjYwMjU2Nzc1Al8yBBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA1NjYwMjU2Nzc1Al8zBBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNTY2MDI1Njc3NQJfNAMDCQECIT0CBRNfbWluQmFzZUFzc2V0QW1vdW50AAAJAGYCBRNfbWluQmFzZUFzc2V0QW1vdW50CQEDYWJzAQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0BwkAAgEJAKwCAgkArAICCQCsAgICDUxpbWl0IGVycm9yOiAJAKQDAQkBA2FicwEFFWFtb3VudEJhc2VBc3NldEJvdWdodAIDIDwgCQCkAwEFE19taW5CYXNlQXNzZXRBbW91bnQED25ld1Bvc2l0aW9uU2l6ZQkAZAIFD29sZFBvc2l0aW9uU2l6ZQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0BBp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgkAZAIJARBvcGVuSW50ZXJlc3RMb25nAAMJAGYCBQ9uZXdQb3NpdGlvblNpemUAAAUMb3Blbk5vdGlvbmFsAAAEG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgkAZAIJARFvcGVuSW50ZXJlc3RTaG9ydAADCQBmAgAABQ9uZXdQb3NpdGlvblNpemUFDG9wZW5Ob3Rpb25hbAAABBlpbmNyZWFzZU1hcmdpblJlcXVpcmVtZW50CQEEZGl2ZAIFDG9wZW5Ob3Rpb25hbAUJX2xldmVyYWdlBA0kdDA1NzM4MzU3NjIyCQEiY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudAQFD29sZFBvc2l0aW9uU2l6ZQURb2xkUG9zaXRpb25NYXJnaW4FFG9sZFBvc2l0aW9uTHN0VXBkQ1BGBRlpbmNyZWFzZU1hcmdpblJlcXVpcmVtZW50BAxyZW1haW5NYXJnaW4IBQ0kdDA1NzM4MzU3NjIyAl8xBAJ4MQgFDSR0MDU3MzgzNTc2MjICXzIEAngyCAUNJHQwNTczODM1NzYyMgJfMwMJAQEhAQkBGXJlcXVpcmVOb3RPdmVyU3ByZWFkTGltaXQCBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIJAAIBAhVPdmVyIG1heCBzcHJlYWQgbGltaXQDCQEBIQEJAR1yZXF1aXJlTm90T3Zlck1heE9wZW5Ob3Rpb25hbAIFGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyBRt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIJAAIBAhZPdmVyIG1heCBvcGVuIG5vdGlvbmFsCQCeCgwFD25ld1Bvc2l0aW9uU2l6ZQUMcmVtYWluTWFyZ2luCQBkAgUXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwFDG9wZW5Ob3Rpb25hbAkBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BBQ9uZXdQb3NpdGlvblNpemUFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgkAZAIJARRvcGVuSW50ZXJlc3ROb3Rpb25hbAAFDG9wZW5Ob3Rpb25hbAkAZAIJARV0b3RhbExvbmdQb3NpdGlvblNpemUAAwkAZgIFD25ld1Bvc2l0aW9uU2l6ZQAACQEDYWJzAQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0AAAJAGQCCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQADCQBmAgAABQ9uZXdQb3NpdGlvblNpemUJAQNhYnMBBRVhbW91bnRCYXNlQXNzZXRCb3VnaHQAAAUadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIFG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgQMb3Blbk5vdGlvbmFsCQEEbXVsZAIFB19hbW91bnQFCV9sZXZlcmFnZQQNJHQwNTg4ODE1ODk5NwkBI2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sAgkApQgBCAUBaQZjYWxsZXIFD1BOTF9PUFRJT05fU1BPVAQTb2xkUG9zaXRpb25Ob3Rpb25hbAgFDSR0MDU4ODgxNTg5OTcCXzEEDXVucmVhbGl6ZWRQbmwIBQ0kdDA1ODg4MTU4OTk3Al8yAwkAZgIFE29sZFBvc2l0aW9uTm90aW9uYWwFDG9wZW5Ob3Rpb25hbAkAAgECLlVzZSBkZWNyZWFzZVBvc2l0aW9uIHRvIGRlY3JlYXNlIHBvc2l0aW9uIHNpemUJAAIBAhRDbG9zZSBwb3NpdGlvbiBmaXJzdAQPbmV3UG9zaXRpb25TaXplCAUNJHQwNTYxNDA1OTE4MQJfMQQXbmV3UG9zaXRpb25SZW1haW5NYXJnaW4IBQ0kdDA1NjE0MDU5MTgxAl8yBBduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDU2MTQwNTkxODECXzMEFG5ld1Bvc2l0aW9uTGF0ZXN0Q1BGCAUNJHQwNTYxNDA1OTE4MQJfNAQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNTYxNDA1OTE4MQJfNQQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDU2MTQwNTkxODECXzYEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA1NjE0MDU5MTgxAl83BBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCAUNJHQwNTYxNDA1OTE4MQJfOAQOdG90YWxMb25nQWZ0ZXIIBQ0kdDA1NjE0MDU5MTgxAl85BA90b3RhbFNob3J0QWZ0ZXIIBQ0kdDA1NjE0MDU5MTgxA18xMAQadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA1NjE0MDU5MTgxA18xMQQbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNTYxNDA1OTE4MQNfMTIEDSR0MDU5MTg3NTkyNDQJAQ1kaXN0cmlidXRlRmVlAQUJZmVlQW1vdW50BAxmZWVUb1N0YWtlcnMIBQ0kdDA1OTE4NzU5MjQ0Al8xBApmZWVUb1ZhdWx0CAUNJHQwNTkxODc1OTI0NAJfMgQFc3Rha2UDBQxpc1F1b3RlQXNzZXQEBXN0YWtlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAglhZGRMb2NrZWQJAMwIAgcFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABQdfYW1vdW50BQNuaWwDCQAAAgUFc3Rha2UFBXN0YWtlBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBQVzdGFrZQUFc3Rha2UEEGRlcG9zaXRJbnN1cmFuY2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACB2FkZEZyZWUFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABQpmZWVUb1ZhdWx0BQNuaWwDCQAAAgUQZGVwb3NpdEluc3VyYW5jZQUQZGVwb3NpdEluc3VyYW5jZQQJbm90aWZ5RmVlCQD8BwQJAQxtaW5lckFkZHJlc3MAAgpub3RpZnlGZWVzCQDMCAIFB190cmFkZXIJAMwIAgUJZmVlQW1vdW50BQNuaWwFA25pbAMJAAACBQlub3RpZnlGZWUFCW5vdGlmeUZlZQQObm90aWZ5Tm90aW9uYWwJAPwHBAkBDG1pbmVyQWRkcmVzcwACDm5vdGlmeU5vdGlvbmFsCQDMCAIFB190cmFkZXIJAMwIAgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFA25pbAUDbmlsAwkAAAIFDm5vdGlmeU5vdGlvbmFsBQ5ub3RpZnlOb3Rpb25hbAkAzggCCQDOCAIJAM4IAgkAzggCCQDOCAIJAM4IAgkBDnVwZGF0ZVBvc2l0aW9uBQUHX3RyYWRlcgUPbmV3UG9zaXRpb25TaXplBRduZXdQb3NpdGlvblJlbWFpbk1hcmdpbgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFFG5ld1Bvc2l0aW9uTGF0ZXN0Q1BGCQEfaW5jcmVtZW50UG9zaXRpb25TZXF1ZW5jZU51bWJlcgIFDWlzTmV3UG9zaXRpb24FB190cmFkZXIJARN1cGRhdGVQb3NpdGlvbkFzc2V0AgUHX3RyYWRlcgULX2Fzc2V0SWRTdHIJAQl1cGRhdGVBbW0IBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIFDnRvdGFsTG9uZ0FmdGVyBQ90b3RhbFNob3J0QWZ0ZXIFGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyBRt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIJAQt0cmFuc2ZlckZlZQEFDGZlZVRvU3Rha2VycwkBDXVwZGF0ZUJhbGFuY2UBCQBkAgkBCGNiYWxhbmNlAAUHX2Ftb3VudAkBDmRvQnVybkFydGlmYWN0AgUMYnVybkFydGlmYWN0BQFpCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCWFkZE1hcmdpbgAEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQHX3RyYWRlcgkApQgBCAUBaQZjYWxsZXIECl9yYXdBbW91bnQICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50BAhfYXNzZXRJZAgJAJEDAggFAWkIcGF5bWVudHMAAAdhc3NldElkBAtfYXNzZXRJZFN0cgkA2AQBCQEFdmFsdWUBBQhfYXNzZXRJZAQMaXNRdW90ZUFzc2V0CQAAAgUIX2Fzc2V0SWQJAQpxdW90ZUFzc2V0AAQRaXNDb2xsYXRlcmFsQXNzZXQJARBpc1doaXRlbGlzdEFzc2V0AQULX2Fzc2V0SWRTdHIDAwMDAwMDAwkBASEBBQxpc1F1b3RlQXNzZXQJAQEhAQURaXNDb2xsYXRlcmFsQXNzZXQHBgkBASEBCQETcmVxdWlyZU9wZW5Qb3NpdGlvbgEJAKUIAQgFAWkGY2FsbGVyBgkBASEBCQELaXNTYW1lQXNzZXQCBQdfdHJhZGVyBQtfYXNzZXRJZFN0cgYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQZwYXVzZWQABgkBCWNsb3NlT25seQAGCQEOaXNNYXJrZXRDbG9zZWQACQACAQIcSW52YWxpZCBhZGRNYXJnaW4gcGFyYW1ldGVycwQNJHQwNjEyMTY2MTMwMQkBGGdldEZvclRyYWRlcldpdGhBcnRpZmFjdAIFB190cmFkZXIJAQ1nZXRBcnRpZmFjdElkAQUBaQQLYWRqdXN0ZWRGZWUIBQ0kdDA2MTIxNjYxMzAxAl8xBAxidXJuQXJ0aWZhY3QIBQ0kdDA2MTIxNjYxMzAxAl8yBAxyYXdGZWVBbW91bnQJAQRtdWxkAgUKX3Jhd0Ftb3VudAULYWRqdXN0ZWRGZWUEB19hbW91bnQJAGUCBQpfcmF3QW1vdW50BQxyYXdGZWVBbW91bnQEE2Rpc3RyaWJ1dGVGZWVBbW91bnQDBRFpc0NvbGxhdGVyYWxBc3NldAQIZG9Cb3Jyb3cJAPwHBAkBEWNvbGxhdGVyYWxBZGRyZXNzAAIGYm9ycm93CQDMCAIFB190cmFkZXIFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUIX2Fzc2V0SWQFB19hbW91bnQFA25pbAMJAAACBQhkb0JvcnJvdwUIZG9Cb3Jyb3cEDWJhbGFuY2VCZWZvcmUJAPAHAgUEdGhpcwkBCnF1b3RlQXNzZXQAAwkAAAIFDWJhbGFuY2VCZWZvcmUFDWJhbGFuY2VCZWZvcmUEBmRvU3dhcAkA/AcECQELc3dhcEFkZHJlc3MAAgRzd2FwCQDMCAIJANgEAQkBCnF1b3RlQXNzZXQACQDMCAIAAAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQhfYXNzZXRJZAUMcmF3RmVlQW1vdW50BQNuaWwDCQAAAgUGZG9Td2FwBQZkb1N3YXAEDGJhbGFuY2VBZnRlcgkA8AcCBQR0aGlzCQEKcXVvdGVBc3NldAADCQAAAgUMYmFsYW5jZUFmdGVyBQxiYWxhbmNlQWZ0ZXIED2V4Y2hhbmdlZEFtb3VudAkAZQIFDGJhbGFuY2VBZnRlcgUNYmFsYW5jZUJlZm9yZQMJAAACBQ9leGNoYW5nZWRBbW91bnQFD2V4Y2hhbmdlZEFtb3VudAUPZXhjaGFuZ2VkQW1vdW50CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQxyYXdGZWVBbW91bnQDCQAAAgUTZGlzdHJpYnV0ZUZlZUFtb3VudAUTZGlzdHJpYnV0ZUZlZUFtb3VudAQOcmVmZXJyZXJGZWVBbnkJAPwHBAkBD3JlZmVycmFsQWRkcmVzcwACDWFjY2VwdFBheW1lbnQJAMwIAgUHX3RyYWRlcgUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFE2Rpc3RyaWJ1dGVGZWVBbW91bnQFA25pbAMJAAACBQ5yZWZlcnJlckZlZUFueQUOcmVmZXJyZXJGZWVBbnkEC3JlZmVycmVyRmVlBAckbWF0Y2gwBQ5yZWZlcnJlckZlZUFueQMJAAECBQckbWF0Y2gwAgNJbnQEAXgFByRtYXRjaDAFAXgJAAIBAhNJbnZhbGlkIHJlZmVycmVyRmVlBAlmZWVBbW91bnQJAGUCBRNkaXN0cmlidXRlRmVlQW1vdW50BQtyZWZlcnJlckZlZQQNJHQwNjI2MDA2Mjc0MAkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQPb2xkUG9zaXRpb25TaXplCAUNJHQwNjI2MDA2Mjc0MAJfMQQRb2xkUG9zaXRpb25NYXJnaW4IBQ0kdDA2MjYwMDYyNzQwAl8yBBdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDYyNjAwNjI3NDACXzMEFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwNjI2MDA2Mjc0MAJfNAQNJHQwNjI3NDY2MjgwMwkBDWRpc3RyaWJ1dGVGZWUBBQlmZWVBbW91bnQEDGZlZVRvU3Rha2VycwgFDSR0MDYyNzQ2NjI4MDMCXzEECmZlZVRvVmF1bHQIBQ0kdDA2Mjc0NjYyODAzAl8yBAVzdGFrZQMFDGlzUXVvdGVBc3NldAQFc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACCWFkZExvY2tlZAkAzAgCBwUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFB19hbW91bnQFA25pbAMJAAACBQVzdGFrZQUFc3Rha2UFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFBXN0YWtlBQVzdGFrZQQQZGVwb3NpdEluc3VyYW5jZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIHYWRkRnJlZQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFCmZlZVRvVmF1bHQFA25pbAMJAAACBRBkZXBvc2l0SW5zdXJhbmNlBRBkZXBvc2l0SW5zdXJhbmNlBAlub3RpZnlGZWUJAPwHBAkBDG1pbmVyQWRkcmVzcwACCm5vdGlmeUZlZXMJAMwIAgUHX3RyYWRlcgkAzAgCBQlmZWVBbW91bnQFA25pbAUDbmlsAwkAAAIFCW5vdGlmeUZlZQUJbm90aWZ5RmVlCQDOCAIJAM4IAgkAzggCCQEOdXBkYXRlUG9zaXRpb24FBQdfdHJhZGVyBQ9vbGRQb3NpdGlvblNpemUJAGQCBRFvbGRQb3NpdGlvbk1hcmdpbgUHX2Ftb3VudAUXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwFFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCQELdHJhbnNmZXJGZWUBBQxmZWVUb1N0YWtlcnMJAQ11cGRhdGVCYWxhbmNlAQkAZAIJAQhjYmFsYW5jZQAFB19hbW91bnQJAQ5kb0J1cm5BcnRpZmFjdAIFDGJ1cm5BcnRpZmFjdAUBaQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQxyZW1vdmVNYXJnaW4BB19hbW91bnQEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQHX3RyYWRlcgkApQgBCAUBaQZjYWxsZXIDAwMDAwkAZwIAAAUHX2Ftb3VudAYJAQEhAQkBE3JlcXVpcmVPcGVuUG9zaXRpb24BBQdfdHJhZGVyBgkBASEBCQELaW5pdGlhbGl6ZWQABgkBBnBhdXNlZAAGCQEOaXNNYXJrZXRDbG9zZWQACQACAQIfSW52YWxpZCByZW1vdmVNYXJnaW4gcGFyYW1ldGVycwQNJHQwNjM5Mzk2NDA3OQkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQPb2xkUG9zaXRpb25TaXplCAUNJHQwNjM5Mzk2NDA3OQJfMQQRb2xkUG9zaXRpb25NYXJnaW4IBQ0kdDA2MzkzOTY0MDc5Al8yBBdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDYzOTM5NjQwNzkCXzMEFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwNjM5Mzk2NDA3OQJfNAQLbWFyZ2luRGVsdGEJAQEtAQUHX2Ftb3VudAQNJHQwNjQxMTY2NDI5NQkBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEBQ9vbGRQb3NpdGlvblNpemUFEW9sZFBvc2l0aW9uTWFyZ2luBRRvbGRQb3NpdGlvbkxzdFVwZENQRgULbWFyZ2luRGVsdGEEDHJlbWFpbk1hcmdpbggFDSR0MDY0MTE2NjQyOTUCXzEEB2JhZERlYnQIBQ0kdDA2NDExNjY0Mjk1Al8yAwkBAiE9AgUHYmFkRGVidAAACQACAQIdSW52YWxpZCByZW1vdmVkIG1hcmdpbiBhbW91bnQEC21hcmdpblJhdGlvCQEPY2FsY01hcmdpblJhdGlvAwUMcmVtYWluTWFyZ2luBQdiYWREZWJ0BRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAMJAQEhAQkBFnJlcXVpcmVNb3JlTWFyZ2luUmF0aW8DBQttYXJnaW5SYXRpbwkBD2luaXRNYXJnaW5SYXRpbwAGCQACAQkArAICCQCsAgIJAKwCAgIZVG9vIG11Y2ggbWFyZ2luIHJlbW92ZWQ6IAkApAMBBQttYXJnaW5SYXRpbwIDIDwgCQCkAwEJAQ9pbml0TWFyZ2luUmF0aW8ABA1xdW90ZUFzc2V0U3RyCQDYBAEJAQpxdW90ZUFzc2V0AAQNJHQwNjQ3Mzk2NDc5MwkBE2dldEJvcnJvd2VkQnlUcmFkZXIBBQdfdHJhZGVyBAhib3Jyb3dlZAgFDSR0MDY0NzM5NjQ3OTMCXzEEB2Fzc2V0SWQIBQ0kdDA2NDczOTY0NzkzAl8yBAd0b1JlcGF5AwkAZgIFB19hbW91bnQFCGJvcnJvd2VkBQhib3Jyb3dlZAUHX2Ftb3VudAQKdG9XaXRoZHJhdwMJAGYCBQhib3Jyb3dlZAUHX2Ftb3VudAAACQBlAgUHX2Ftb3VudAUIYm9ycm93ZWQEC2ZpbmFsQm9ycm93CQBlAgUIYm9ycm93ZWQFB3RvUmVwYXkEFXN3aXRjaFBvc2l0aW9uVG9RdW90ZQMJAGYCBQtmaW5hbEJvcnJvdwAABQNuaWwJARN1cGRhdGVQb3NpdGlvbkFzc2V0AgUHX3RyYWRlcgUNcXVvdGVBc3NldFN0cgQNZG9TYW5pdHlDaGVjawMJAQIhPQIJAGQCBQd0b1JlcGF5BQp0b1dpdGhkcmF3BQdfYW1vdW50CQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgICCHRvUmVwYXk9CQCkAwEFB3RvUmVwYXkCDiArIHRvV2l0aGRyYXc9CQCkAwEFCnRvV2l0aGRyYXcCBCAhPSAJAKQDAQUHX2Ftb3VudAUDbmlsAwkAAAIFDWRvU2FuaXR5Q2hlY2sFDWRvU2FuaXR5Q2hlY2sECWRvVW5zdGFrZQMJAGYCBQp0b1dpdGhkcmF3AAAECWRvVW5zdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIOd2l0aGRyYXdMb2NrZWQJAMwIAgUKdG9XaXRoZHJhdwUDbmlsBQNuaWwDCQAAAgUJZG9VbnN0YWtlBQlkb1Vuc3Rha2UFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFCWRvVW5zdGFrZQUJZG9VbnN0YWtlBBZyZXR1cm5Db2xsYXRlcmFsQWN0aW9uAwkAZgIFB3RvUmVwYXkAAAQHZG9SZXBheQkA/AcECQERY29sbGF0ZXJhbEFkZHJlc3MAAgVyZXBheQkAzAgCBQdfdHJhZGVyCQDMCAIFB3RvUmVwYXkJAMwIAgUHYXNzZXRJZAUDbmlsBQNuaWwDCQAAAgUHZG9SZXBheQUHZG9SZXBheQkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIFB3RvUmVwYXkJANkEAQUHYXNzZXRJZAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUWcmV0dXJuQ29sbGF0ZXJhbEFjdGlvbgUWcmV0dXJuQ29sbGF0ZXJhbEFjdGlvbgkAzggCCQDOCAIJAM4IAgkAzggCCQEOdXBkYXRlUG9zaXRpb24FBQdfdHJhZGVyBQ9vbGRQb3NpdGlvblNpemUFDHJlbWFpbk1hcmdpbgUXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwJAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUPb2xkUG9zaXRpb25TaXplAwkAZgIFCnRvV2l0aGRyYXcAAAkBCHdpdGhkcmF3AggFAWkGY2FsbGVyBQp0b1dpdGhkcmF3BQNuaWwJAQ11cGRhdGVCYWxhbmNlAQkAZQIJAQhjYmFsYW5jZQAFB19hbW91bnQFFXN3aXRjaFBvc2l0aW9uVG9RdW90ZQUWcmV0dXJuQ29sbGF0ZXJhbEFjdGlvbgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ1jbG9zZVBvc2l0aW9uAgVfc2l6ZRRfbWluUXVvdGVBc3NldEFtb3VudAQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBAdfdHJhZGVyCQEPZ2V0QWN0dWFsQ2FsbGVyAQUBaQQOX3RyYWRlckFkZHJlc3MJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBBQdfdHJhZGVyAg5JbnZhbGlkIGNhbGxlcgMDAwMDAwkBASEBCQETcmVxdWlyZU9wZW5Qb3NpdGlvbgEFB190cmFkZXIGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAYJAGcCAAAFBV9zaXplBgkAZgIAAAUUX21pblF1b3RlQXNzZXRBbW91bnQGCQEOaXNNYXJrZXRDbG9zZWQACQACAQIgSW52YWxpZCBjbG9zZVBvc2l0aW9uIHBhcmFtZXRlcnMEDSR0MDY2OTc3NjcxMTcJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIED29sZFBvc2l0aW9uU2l6ZQgFDSR0MDY2OTc3NjcxMTcCXzEEEW9sZFBvc2l0aW9uTWFyZ2luCAUNJHQwNjY5Nzc2NzExNwJfMgQXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA2Njk3NzY3MTE3Al8zBBRvbGRQb3NpdGlvbkxzdFVwZENQRggFDSR0MDY2OTc3NjcxMTcCXzQEDSR0MDY3MTIzNzE3NjkDCQBmAgkBA2FicwEFD29sZFBvc2l0aW9uU2l6ZQUFX3NpemUECl9kaXJlY3Rpb24DCQBmAgUPb2xkUG9zaXRpb25TaXplAAAFCURJUl9TSE9SVAUIRElSX0xPTkcEBWlzQWRkCQAAAgUKX2RpcmVjdGlvbgUIRElSX0xPTkcEDSR0MDY3NzE0Njc5MzYJAQpzd2FwT3V0cHV0AwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAABQVfc2l6ZQYEGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQIBQ0kdDA2NzcxNDY3OTM2Al8xBBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNjc3MTQ2NzkzNgJfMgQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNjc3MTQ2NzkzNgJfMwQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDY3NzE0Njc5MzYCXzQEFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQMJAGYCBQ9vbGRQb3NpdGlvblNpemUAAAkBAS0BBQVfc2l6ZQUFX3NpemUEDSR0MDY4MDI3NjgxODEJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAQTb2xkUG9zaXRpb25Ob3Rpb25hbAgFDSR0MDY4MDI3NjgxODECXzEEDXVucmVhbGl6ZWRQbmwIBQ0kdDA2ODAyNzY4MTgxAl8yBAJtcgkBFmdldE1hcmdpblJhdGlvQnlPcHRpb24CBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QEDXJlYWxpemVkUmF0aW8JAQRkaXZkAgkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQkBA2FicwEFD29sZFBvc2l0aW9uU2l6ZQQLcmVhbGl6ZWRQbmwJAQRtdWxkAgUNdW5yZWFsaXplZFBubAUNcmVhbGl6ZWRSYXRpbwQScmVtYWluTWFyZ2luQmVmb3JlCAkBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEBQ9vbGRQb3NpdGlvblNpemUFEW9sZFBvc2l0aW9uTWFyZ2luBRRvbGRQb3NpdGlvbkxzdFVwZENQRgUNdW5yZWFsaXplZFBubAJfMQQNJHQwNjg2ODI2ODkyMAkBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEBQ9vbGRQb3NpdGlvblNpemUFEW9sZFBvc2l0aW9uTWFyZ2luBRRvbGRQb3NpdGlvbkxzdFVwZENQRgULcmVhbGl6ZWRQbmwEDHJlbWFpbk1hcmdpbggFDSR0MDY4NjgyNjg5MjACXzEED3Bvc2l0aW9uQmFkRGVidAgFDSR0MDY4NjgyNjg5MjACXzIEDmZ1bmRpbmdQYXltZW50CAUNJHQwNjg2ODI2ODkyMAJfMwQSdW5yZWFsaXplZFBubEFmdGVyCQBlAgUNdW5yZWFsaXplZFBubAULcmVhbGl6ZWRQbmwEEnJlbWFpbk9wZW5Ob3Rpb25hbAMJAGYCBQ9vbGRQb3NpdGlvblNpemUAAAkAZQIJAGUCBRNvbGRQb3NpdGlvbk5vdGlvbmFsBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BRJ1bnJlYWxpemVkUG5sQWZ0ZXIJAGUCCQBkAgUSdW5yZWFsaXplZFBubEFmdGVyBRNvbGRQb3NpdGlvbk5vdGlvbmFsBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BBduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAkBA2FicwEFEnJlbWFpbk9wZW5Ob3Rpb25hbAQRbmV3UG9zaXRpb25NYXJnaW4JAQRtdWxkAgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFAm1yBA9uZXdQb3NpdGlvblNpemUJAGQCBQ9vbGRQb3NpdGlvblNpemUFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQQUbmV3UG9zaXRpb25Mc3RVcGRDUEYJAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUPbmV3UG9zaXRpb25TaXplBBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCQBlAgkBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAMDCQECIT0CBRRfbWluUXVvdGVBc3NldEFtb3VudAAACQBmAgUUX21pblF1b3RlQXNzZXRBbW91bnQFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQHCQACAQkArAICCQCsAgIJAKwCAgINTGltaXQgZXJyb3I6IAkApAMBBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50AgMgPCAJAKQDAQUUX21pblF1b3RlQXNzZXRBbW91bnQJAKEKDwUPbmV3UG9zaXRpb25TaXplBRFuZXdQb3NpdGlvbk1hcmdpbgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFFG5ld1Bvc2l0aW9uTHN0VXBkQ1BGBQ9wb3NpdGlvbkJhZERlYnQFC3JlYWxpemVkUG5sCQBlAgUScmVtYWluTWFyZ2luQmVmb3JlBRFuZXdQb3NpdGlvbk1hcmdpbgUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCQBlAgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQADCQBmAgUPbmV3UG9zaXRpb25TaXplAAAJAQNhYnMBBRVleGNoYW5nZWRQb3NpdGlvblNpemUAAAkAZQIJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAMJAGYCAAAFD25ld1Bvc2l0aW9uU2l6ZQkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQAACQBlAgkBEG9wZW5JbnRlcmVzdExvbmcAAwkAZgIFD25ld1Bvc2l0aW9uU2l6ZQAABRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50AAAJAGUCCQERb3BlbkludGVyZXN0U2hvcnQAAwkAZgIAAAUPbmV3UG9zaXRpb25TaXplBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50AAADCQBmAgUFX3NpemUJAQNhYnMBBQ9vbGRQb3NpdGlvblNpemUJAAIBAiBJbnZhbGlkIGNsb3NlUG9zaXRpb24gcGFyYW1ldGVycwQNJHQwNzA3MTA3MTEyOQkBFWludGVybmFsQ2xvc2VQb3NpdGlvbgIFB190cmFkZXIGBBlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CAUNJHQwNzA3MTA3MTEyOQJfMQQPcG9zaXRpb25CYWREZWJ0CAUNJHQwNzA3MTA3MTEyOQJfMgQLcmVhbGl6ZWRQbmwIBQ0kdDA3MDcxMDcxMTI5Al8zBA1tYXJnaW5Ub1ZhdWx0CAUNJHQwNzA3MTA3MTEyOQJfNAQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDcwNzEwNzExMjkCXzUEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDcwNzEwNzExMjkCXzYEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA3MDcxMDcxMTI5Al83BBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCAUNJHQwNzA3MTA3MTEyOQJfOAQCeDIIBQ0kdDA3MDcxMDcxMTI5Al85BA50b3RhbExvbmdBZnRlcggFDSR0MDcwNzEwNzExMjkDXzEwBA90b3RhbFNob3J0QWZ0ZXIIBQ0kdDA3MDcxMDcxMTI5A18xMQQadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA3MDcxMDcxMTI5A18xMgQbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNzA3MTA3MTEyOQNfMTMDAwkBAiE9AgUUX21pblF1b3RlQXNzZXRBbW91bnQAAAkAZgIFFF9taW5RdW90ZUFzc2V0QW1vdW50BRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BwkAAgEJAKwCAgkArAICCQCsAgICDUxpbWl0IGVycm9yOiAJAKQDAQUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAIDIDwgCQCkAwEFFF9taW5RdW90ZUFzc2V0QW1vdW50CQChCg8AAAAAAAAAAAUPcG9zaXRpb25CYWREZWJ0BQtyZWFsaXplZFBubAUNbWFyZ2luVG9WYXVsdAUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyBRp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgUbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyBA9uZXdQb3NpdGlvblNpemUIBQ0kdDA2NzEyMzcxNzY5Al8xBBFuZXdQb3NpdGlvbk1hcmdpbggFDSR0MDY3MTIzNzE3NjkCXzIEF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNjcxMjM3MTc2OQJfMwQUbmV3UG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA2NzEyMzcxNzY5Al80BA9wb3NpdGlvbkJhZERlYnQIBQ0kdDA2NzEyMzcxNzY5Al81BAtyZWFsaXplZFBubAgFDSR0MDY3MTIzNzE3NjkCXzYEDW1hcmdpblRvVmF1bHQIBQ0kdDA2NzEyMzcxNzY5Al83BBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNjcxMjM3MTc2OQJfOAQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNjcxMjM3MTc2OQJfOQQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDY3MTIzNzE3NjkDXzEwBBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCAUNJHQwNjcxMjM3MTc2OQNfMTEEDnRvdGFsTG9uZ0FmdGVyCAUNJHQwNjcxMjM3MTc2OQNfMTIED3RvdGFsU2hvcnRBZnRlcggFDSR0MDY3MTIzNzE3NjkDXzEzBBp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDY3MTIzNzE3NjkDXzE0BBt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA2NzEyMzcxNzY5A18xNQMJAGYCBQ9wb3NpdGlvbkJhZERlYnQAAAkAAgECJlVuYWJsZSB0byBjbG9zZSBwb3NpdGlvbiB3aXRoIGJhZCBkZWJ0BA53aXRoZHJhd0Ftb3VudAkBA2FicwEFDW1hcmdpblRvVmF1bHQECmFtbUJhbGFuY2UJAGUCCQEIY2JhbGFuY2UABQ53aXRoZHJhd0Ftb3VudAQNJHQwNzE5Nzg3MjE4NQMJAGYCAAAFCmFtbUJhbGFuY2UJAJQKAgAACQEDYWJzAQUKYW1tQmFsYW5jZQkAlAoCBQphbW1CYWxhbmNlAAAEDWFtbU5ld0JhbGFuY2UIBQ0kdDA3MTk3ODcyMTg1Al8xBAN4MTEIBQ0kdDA3MTk3ODcyMTg1Al8yBA0kdDA3MjE5MjcyMjQ2CQETZ2V0Qm9ycm93ZWRCeVRyYWRlcgEFB190cmFkZXIECGJvcnJvd2VkCAUNJHQwNzIxOTI3MjI0NgJfMQQHYXNzZXRJZAgFDSR0MDcyMTkyNzIyNDYCXzIEDSR0MDcyMjYxNzMxMjADCQBmAgUIYm9ycm93ZWQAAAMJAGcCBQ53aXRoZHJhd0Ftb3VudAUIYm9ycm93ZWQEB2RvUmVwYXkJAPwHBAkBEWNvbGxhdGVyYWxBZGRyZXNzAAIFcmVwYXkJAMwIAgUHX3RyYWRlcgkAzAgCBQhib3Jyb3dlZAkAzAgCBQdhc3NldElkBQNuaWwFA25pbAMJAAACBQdkb1JlcGF5BQdkb1JlcGF5CQCUCgIJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUOX3RyYWRlckFkZHJlc3MFCGJvcnJvd2VkCQDZBAEFB2Fzc2V0SWQFA25pbAkAZQIFDndpdGhkcmF3QW1vdW50BQhib3Jyb3dlZAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgQPcmVhbGl6ZUFuZENsb3NlCQD8BwQJARFjb2xsYXRlcmFsQWRkcmVzcwACGHJlYWxpemVQYXJ0aWFsbHlBbmRDbG9zZQkAzAgCBQdfdHJhZGVyCQDMCAIFDndpdGhkcmF3QW1vdW50CQDMCAIFB2Fzc2V0SWQFA25pbAUDbmlsAwkAAAIFD3JlYWxpemVBbmRDbG9zZQUPcmVhbGl6ZUFuZENsb3NlCQCUCgIJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUOX3RyYWRlckFkZHJlc3MFDndpdGhkcmF3QW1vdW50CQDZBAEFB2Fzc2V0SWQFA25pbAAACQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQCUCgIFA25pbAUOd2l0aGRyYXdBbW91bnQDCQAAAgUNJHQwNzIyNjE3MzEyMAUNJHQwNzIyNjE3MzEyMAQTcXVvdGVXaXRoZHJhd0Ftb3VudAgFDSR0MDcyMjYxNzMxMjACXzIEFHNlbmRDb2xsYXRlcmFsQWN0aW9uCAUNJHQwNzIyNjE3MzEyMAJfMQQHdW5zdGFrZQMJAGYCBRNxdW90ZVdpdGhkcmF3QW1vdW50AAAEB3Vuc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACDndpdGhkcmF3TG9ja2VkCQDMCAIFE3F1b3RlV2l0aGRyYXdBbW91bnQFA25pbAUDbmlsAwkAAAIFB3Vuc3Rha2UFB3Vuc3Rha2UFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFB3Vuc3Rha2UFB3Vuc3Rha2UEDm5vdGlmeU5vdGlvbmFsCQD8BwQJAQxtaW5lckFkZHJlc3MAAg5ub3RpZnlOb3Rpb25hbAkAzAgCBQdfdHJhZGVyCQDMCAIAAAUDbmlsBQNuaWwDCQAAAgUObm90aWZ5Tm90aW9uYWwFDm5vdGlmeU5vdGlvbmFsCQDOCAIJAM4IAgkAzggCCQDOCAIDCQAAAgUPbmV3UG9zaXRpb25TaXplAAAJAQ5kZWxldGVQb3NpdGlvbgEFB190cmFkZXIJAQ51cGRhdGVQb3NpdGlvbgUFB190cmFkZXIFD25ld1Bvc2l0aW9uU2l6ZQURbmV3UG9zaXRpb25NYXJnaW4FF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBRRuZXdQb3NpdGlvbkxzdFVwZENQRgkBCXVwZGF0ZUFtbQgFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgUZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcgUOdG90YWxMb25nQWZ0ZXIFD3RvdGFsU2hvcnRBZnRlcgUadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIFG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgMJAGYCBRNxdW90ZVdpdGhkcmF3QW1vdW50AAAJAQh3aXRoZHJhdwIFDl90cmFkZXJBZGRyZXNzBRNxdW90ZVdpdGhkcmF3QW1vdW50BQNuaWwJAQ11cGRhdGVCYWxhbmNlAQUNYW1tTmV3QmFsYW5jZQUUc2VuZENvbGxhdGVyYWxBY3Rpb24JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEJbGlxdWlkYXRlAQdfdHJhZGVyBARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMED3Nwb3RNYXJnaW5SYXRpbwkBFmdldE1hcmdpblJhdGlvQnlPcHRpb24CBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QEC21hcmdpblJhdGlvAwkBFmlzT3ZlckZsdWN0dWF0aW9uTGltaXQABBFvcmFjbGVNYXJnaW5SYXRpbwkBFmdldE1hcmdpblJhdGlvQnlPcHRpb24CBQdfdHJhZGVyBRFQTkxfT1BUSU9OX09SQUNMRQkBBHZtYXgCBQ9zcG90TWFyZ2luUmF0aW8FEW9yYWNsZU1hcmdpblJhdGlvBQ9zcG90TWFyZ2luUmF0aW8DAwMDAwkBASEBCQEWcmVxdWlyZU1vcmVNYXJnaW5SYXRpbwMFC21hcmdpblJhdGlvCQEWbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwAHBgkBASEBCQETcmVxdWlyZU9wZW5Qb3NpdGlvbgEFB190cmFkZXIGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAYJAQ5pc01hcmtldENsb3NlZAAJAAIBAhNVbmFibGUgdG8gbGlxdWlkYXRlAwMDCQBmAgUPc3BvdE1hcmdpblJhdGlvCQETbGlxdWlkYXRpb25GZWVSYXRpbwAJAGYCCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8AAAAHCQBmAgUMREVDSU1BTF9VTklUCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8ABwQNJHQwNzU0NDE3NTU5MQkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQPb2xkUG9zaXRpb25TaXplCAUNJHQwNzU0NDE3NTU5MQJfMQQRb2xkUG9zaXRpb25NYXJnaW4IBQ0kdDA3NTQ0MTc1NTkxAl8yBBdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDc1NDQxNzU1OTECXzMEFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwNzU0NDE3NTU5MQJfNAQKX2RpcmVjdGlvbgMJAGYCBQ9vbGRQb3NpdGlvblNpemUAAAUJRElSX1NIT1JUBQhESVJfTE9ORwQFaXNBZGQJAAACBQpfZGlyZWN0aW9uBQhESVJfTE9ORwQZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAkBG2dldFBhcnRpYWxMaXF1aWRhdGlvbkFtb3VudAIFB190cmFkZXIFD29sZFBvc2l0aW9uU2l6ZQQNJHQwNzU4MTY3NTkyMAkBI2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sAgUHX3RyYWRlcgUPUE5MX09QVElPTl9TUE9UBBNvbGRQb3NpdGlvbk5vdGlvbmFsCAUNJHQwNzU4MTY3NTkyMAJfMQQNdW5yZWFsaXplZFBubAgFDSR0MDc1ODE2NzU5MjACXzIEDSR0MDc1OTI4NzYxMTUJAQlzd2FwSW5wdXQCBQVpc0FkZAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAQVZXhjaGFuZ2VkUG9zaXRpb25TaXplCAUNJHQwNzU5Mjg3NjExNQJfMQQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDc1OTI4NzYxMTUCXzIEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDc1OTI4NzYxMTUCXzMEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA3NTkyODc2MTE1Al80BBBsaXF1aWRhdGlvblJhdGlvCQEEZGl2ZAIJAQNhYnMBBRVleGNoYW5nZWRQb3NpdGlvblNpemUJAQNhYnMBBQ9vbGRQb3NpdGlvblNpemUEC3JlYWxpemVkUG5sCQEEbXVsZAIFDXVucmVhbGl6ZWRQbmwFEGxpcXVpZGF0aW9uUmF0aW8EDSR0MDc2NDA0NzY2MzcJASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BAUPb2xkUG9zaXRpb25TaXplBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25Mc3RVcGRDUEYFC3JlYWxpemVkUG5sBAxyZW1haW5NYXJnaW4IBQ0kdDA3NjQwNDc2NjM3Al8xBAdiYWREZWJ0CAUNJHQwNzY0MDQ3NjYzNwJfMgQOZnVuZGluZ1BheW1lbnQIBQ0kdDA3NjQwNDc2NjM3Al8zBBJ1bnJlYWxpemVkUG5sQWZ0ZXIJAGUCBQ11bnJlYWxpemVkUG5sBQtyZWFsaXplZFBubAQScmVtYWluT3Blbk5vdGlvbmFsAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAACQBlAgkAZQIFE29sZFBvc2l0aW9uTm90aW9uYWwFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQFEnVucmVhbGl6ZWRQbmxBZnRlcgkAZQIJAGQCBRJ1bnJlYWxpemVkUG5sQWZ0ZXIFE29sZFBvc2l0aW9uTm90aW9uYWwFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQEEmxpcXVpZGF0aW9uUGVuYWx0eQkBBG11bGQCBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CQETbGlxdWlkYXRpb25GZWVSYXRpbwAED2ZlZVRvTGlxdWlkYXRvcgkAaQIFEmxpcXVpZGF0aW9uUGVuYWx0eQACBApmZWVUb1ZhdWx0CQBlAgUSbGlxdWlkYXRpb25QZW5hbHR5BQ9mZWVUb0xpcXVpZGF0b3IEEW5ld1Bvc2l0aW9uTWFyZ2luCQBlAgUMcmVtYWluTWFyZ2luBRJsaXF1aWRhdGlvblBlbmFsdHkED25ld1Bvc2l0aW9uU2l6ZQkAZAIFD29sZFBvc2l0aW9uU2l6ZQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplBBduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAkBA2FicwEFEnJlbWFpbk9wZW5Ob3Rpb25hbAQUbmV3UG9zaXRpb25Mc3RVcGRDUEYJAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUPbmV3UG9zaXRpb25TaXplBBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCQBlAgkBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAQKYW1tQmFsYW5jZQkAZQIJAQhjYmFsYW5jZQAFEmxpcXVpZGF0aW9uUGVuYWx0eQQNJHQwNzc4MDY3NzkzNQMJAGYCAAAFCmFtbUJhbGFuY2UJAJQKAgAACQEDYWJzAQUKYW1tQmFsYW5jZQkAlAoCBQphbW1CYWxhbmNlAAAEDW5ld0FtbUJhbGFuY2UIBQ0kdDA3NzgwNjc3OTM1Al8xBAN4MTEIBQ0kdDA3NzgwNjc3OTM1Al8yBA0kdDA3Nzk0Mzc3OTk3CQETZ2V0Qm9ycm93ZWRCeVRyYWRlcgEFB190cmFkZXIECGJvcnJvd2VkCAUNJHQwNzc5NDM3Nzk5NwJfMQQHYXNzZXRJZAgFDSR0MDc3OTQzNzc5OTcCXzIEFWRvTGlxdWlkYXRlQ29sbGF0ZXJhbAMJAGYCBQhib3Jyb3dlZAAABBBjb2xsYXRlcmFsVG9TZWxsCQEEbXVsZAIFCGJvcnJvd2VkBRBsaXF1aWRhdGlvblJhdGlvBA9yZWFsaXplQW5kQ2xvc2UJAPwHBAkBEWNvbGxhdGVyYWxBZGRyZXNzAAIQcmVhbGl6ZVBhcnRpYWxseQkAzAgCBQdfdHJhZGVyCQDMCAIFB2Fzc2V0SWQJAMwIAgUQY29sbGF0ZXJhbFRvU2VsbAUDbmlsBQNuaWwDCQAAAgUPcmVhbGl6ZUFuZENsb3NlBQ9yZWFsaXplQW5kQ2xvc2UFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFFWRvTGlxdWlkYXRlQ29sbGF0ZXJhbAUVZG9MaXF1aWRhdGVDb2xsYXRlcmFsBAd1bnN0YWtlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAg53aXRoZHJhd0xvY2tlZAkAzAgCBRJsaXF1aWRhdGlvblBlbmFsdHkFA25pbAUDbmlsAwkAAAIFB3Vuc3Rha2UFB3Vuc3Rha2UEEGRlcG9zaXRJbnN1cmFuY2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACB2FkZEZyZWUFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABQpmZWVUb1ZhdWx0BQNuaWwDCQAAAgUQZGVwb3NpdEluc3VyYW5jZQUQZGVwb3NpdEluc3VyYW5jZQQObm90aWZ5Tm90aW9uYWwJAPwHBAkBDG1pbmVyQWRkcmVzcwACDm5vdGlmeU5vdGlvbmFsCQDMCAIFB190cmFkZXIJAMwIAgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFA25pbAUDbmlsAwkAAAIFDm5vdGlmeU5vdGlvbmFsBQ5ub3RpZnlOb3Rpb25hbAkAzggCCQDOCAIJAM4IAgkBDnVwZGF0ZVBvc2l0aW9uBQUHX3RyYWRlcgUPbmV3UG9zaXRpb25TaXplBRFuZXdQb3NpdGlvbk1hcmdpbgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFFG5ld1Bvc2l0aW9uTHN0VXBkQ1BGCQEJdXBkYXRlQW1tCAUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCQBlAgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQADCQBmAgUPbmV3UG9zaXRpb25TaXplAAAJAQNhYnMBBRVleGNoYW5nZWRQb3NpdGlvblNpemUAAAkAZQIJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAMJAGYCAAAFD25ld1Bvc2l0aW9uU2l6ZQkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQAACQBlAgkBEG9wZW5JbnRlcmVzdExvbmcAAwkAZgIFD25ld1Bvc2l0aW9uU2l6ZQAABRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50AAAJAGUCCQERb3BlbkludGVyZXN0U2hvcnQAAwkAZgIAAAUPbmV3UG9zaXRpb25TaXplBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50AAAJAQh3aXRoZHJhdwIIBQFpBmNhbGxlcgUPZmVlVG9MaXF1aWRhdG9yCQENdXBkYXRlQmFsYW5jZQEFDW5ld0FtbUJhbGFuY2UJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4EDSR0MDc5NjkyODAxODcJARVpbnRlcm5hbENsb3NlUG9zaXRpb24CBQdfdHJhZGVyBwQCeDEIBQ0kdDA3OTY5MjgwMTg3Al8xBAdiYWREZWJ0CAUNJHQwNzk2OTI4MDE4NwJfMgQCeDIIBQ0kdDA3OTY5MjgwMTg3Al8zBAJ4MwgFDSR0MDc5NjkyODAxODcCXzQEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA3OTY5MjgwMTg3Al81BBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA3OTY5MjgwMTg3Al82BBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNzk2OTI4MDE4NwJfNwQZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcggFDSR0MDc5NjkyODAxODcCXzgEGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQIBQ0kdDA3OTY5MjgwMTg3Al85BA50b3RhbExvbmdBZnRlcggFDSR0MDc5NjkyODAxODcDXzEwBA90b3RhbFNob3J0QWZ0ZXIIBQ0kdDA3OTY5MjgwMTg3A18xMQQadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA3OTY5MjgwMTg3A18xMgQbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNzk2OTI4MDE4NwNfMTMEEmxpcXVpZGF0aW9uUGVuYWx0eQkBBG11bGQCBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CQETbGlxdWlkYXRpb25GZWVSYXRpbwAED2ZlZVRvTGlxdWlkYXRvcgkAaQIFEmxpcXVpZGF0aW9uUGVuYWx0eQACBApmZWVUb1ZhdWx0CQBlAgUSbGlxdWlkYXRpb25QZW5hbHR5BQ9mZWVUb0xpcXVpZGF0b3IECmFtbUJhbGFuY2UJAGUCCQEIY2JhbGFuY2UABRJsaXF1aWRhdGlvblBlbmFsdHkEDSR0MDgwNTk1ODA3MjQDCQBmAgAABQphbW1CYWxhbmNlCQCUCgIAAAkBA2FicwEFCmFtbUJhbGFuY2UJAJQKAgUKYW1tQmFsYW5jZQAABA1uZXdBbW1CYWxhbmNlCAUNJHQwODA1OTU4MDcyNAJfMQQDeDExCAUNJHQwODA1OTU4MDcyNAJfMgQNJHQwODA3MzI4MDc4NgkBE2dldEJvcnJvd2VkQnlUcmFkZXIBBQdfdHJhZGVyBAhib3Jyb3dlZAgFDSR0MDgwNzMyODA3ODYCXzEEB2Fzc2V0SWQIBQ0kdDA4MDczMjgwNzg2Al8yBBVkb0xpcXVpZGF0ZUNvbGxhdGVyYWwDCQBmAgUIYm9ycm93ZWQAAAQPcmVhbGl6ZUFuZENsb3NlCQD8BwQJARFjb2xsYXRlcmFsQWRkcmVzcwACGHJlYWxpemVQYXJ0aWFsbHlBbmRDbG9zZQkAzAgCBQdfdHJhZGVyCQDMCAIAAAkAzAgCBQdhc3NldElkBQNuaWwFA25pbAMJAAACBQ9yZWFsaXplQW5kQ2xvc2UFD3JlYWxpemVBbmRDbG9zZQUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUVZG9MaXF1aWRhdGVDb2xsYXRlcmFsBRVkb0xpcXVpZGF0ZUNvbGxhdGVyYWwEAXgDCQBmAgUHYmFkRGVidAAABAtsb2NrQmFkRGVidAkA/AcECQEMdmF1bHRBZGRyZXNzAAIVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkCQDMCAIFB2JhZERlYnQFA25pbAUDbmlsAwkAAAIFC2xvY2tCYWREZWJ0BQtsb2NrQmFkRGVidAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUBeAUBeAQHdW5zdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIOd2l0aGRyYXdMb2NrZWQJAMwIAgUSbGlxdWlkYXRpb25QZW5hbHR5BQNuaWwFA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlBBBkZXBvc2l0SW5zdXJhbmNlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAgdhZGRGcmVlBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUKZmVlVG9WYXVsdAUDbmlsAwkAAAIFEGRlcG9zaXRJbnN1cmFuY2UFEGRlcG9zaXRJbnN1cmFuY2UEDm5vdGlmeU5vdGlvbmFsCQD8BwQJAQxtaW5lckFkZHJlc3MAAg5ub3RpZnlOb3Rpb25hbAkAzAgCBQdfdHJhZGVyCQDMCAIAAAUDbmlsBQNuaWwDCQAAAgUObm90aWZ5Tm90aW9uYWwFDm5vdGlmeU5vdGlvbmFsCQDOCAIJAM4IAgkAzggCCQEOZGVsZXRlUG9zaXRpb24BBQdfdHJhZGVyCQEJdXBkYXRlQW1tCAUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyBRp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgUbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCQEId2l0aGRyYXcCCAUBaQZjYWxsZXIFD2ZlZVRvTGlxdWlkYXRvcgkBDXVwZGF0ZUJhbGFuY2UBBQ1uZXdBbW1CYWxhbmNlCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCnBheUZ1bmRpbmcABARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEFWZ1bmRpbmdCbG9ja1RpbWVzdGFtcAkBGW5leHRGdW5kaW5nQmxvY2tUaW1lc3RhbXAAAwMDCQBmAgUVZnVuZGluZ0Jsb2NrVGltZXN0YW1wCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQZwYXVzZWQACQACAQkArAICCQCsAgIJAKwCAgIhSW52YWxpZCBmdW5kaW5nIGJsb2NrIHRpbWVzdGFtcDogCQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wAgMgPCAJAKQDAQUVZnVuZGluZ0Jsb2NrVGltZXN0YW1wBA91bmRlcmx5aW5nUHJpY2UJAQ5nZXRPcmFjbGVQcmljZQAEDSR0MDgyNjU4ODI3MjAJAQpnZXRGdW5kaW5nAAQUc2hvcnRQcmVtaXVtRnJhY3Rpb24IBQ0kdDA4MjY1ODgyNzIwAl8xBBNsb25nUHJlbWl1bUZyYWN0aW9uCAUNJHQwODI2NTg4MjcyMAJfMgkBDXVwZGF0ZUZ1bmRpbmcFCQBkAgUVZnVuZGluZ0Jsb2NrVGltZXN0YW1wCQEUZnVuZGluZ1BlcmlvZFNlY29uZHMACQBkAgkBI2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAUTbG9uZ1ByZW1pdW1GcmFjdGlvbgkAZAIJASRsYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24ABRRzaG9ydFByZW1pdW1GcmFjdGlvbgkBBGRpdmQCBRNsb25nUHJlbWl1bUZyYWN0aW9uBQ91bmRlcmx5aW5nUHJpY2UJAQRkaXZkAgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24FD3VuZGVybHlpbmdQcmljZQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlAAQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABA0kdDA4MzE1MjgzMjg3CQEUZ2V0U3luY1Rlcm1pbmFsUHJpY2UDCQEOZ2V0T3JhY2xlUHJpY2UABQdfcXRBc3RSBQdfYnNBc3RSBBNuZXdRdW90ZUFzc2V0V2VpZ2h0CAUNJHQwODMxNTI4MzI4NwJfMQQSbmV3QmFzZUFzc2V0V2VpZ2h0CAUNJHQwODMxNTI4MzI4NwJfMgQNbWFyZ2luVG9WYXVsdAgFDSR0MDgzMTUyODMyODcCXzMEDWRvRXhjaGFuZ2VQbkwDCQECIT0CBQ1tYXJnaW5Ub1ZhdWx0AAAEDWRvRXhjaGFuZ2VQbkwJAPwHBAkBDHZhdWx0QWRkcmVzcwACFWV4Y2hhbmdlRnJlZUFuZExvY2tlZAkAzAgCBQ1tYXJnaW5Ub1ZhdWx0BQNuaWwFA25pbAMJAAACBQ1kb0V4Y2hhbmdlUG5MBQ1kb0V4Y2hhbmdlUG5MBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBQ1kb0V4Y2hhbmdlUG5MBQ1kb0V4Y2hhbmdlUG5MCQDOCAIJARB1cGRhdGVBbW1XZWlnaHRzAgUTbmV3UXVvdGVBc3NldFdlaWdodAUSbmV3QmFzZUFzc2V0V2VpZ2h0CQEKYXBwZW5kVHdhcAEJAQRkaXZkAgkBBG11bGQCBQdfcXRBc3RSBRNuZXdRdW90ZUFzc2V0V2VpZ2h0CQEEbXVsZAIFB19ic0FzdFIFEm5ld0Jhc2VBc3NldFdlaWdodAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpASd2aWV3X2NhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQBB190cmFkZXIEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQNJHQwODM4NTY4Mzk1NwkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQMcG9zaXRpb25TaXplCAUNJHQwODM4NTY4Mzk1NwJfMQQOcG9zaXRpb25NYXJnaW4IBQ0kdDA4Mzg1NjgzOTU3Al8yBANwb24IBQ0kdDA4Mzg1NjgzOTU3Al8zBBFwb3NpdGlvbkxzdFVwZENQRggFDSR0MDgzODU2ODM5NTcCXzQEDSR0MDgzOTYwODQwNjEJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAQQcG9zaXRpb25Ob3Rpb25hbAgFDSR0MDgzOTYwODQwNjECXzEEDXVucmVhbGl6ZWRQbmwIBQ0kdDA4Mzk2MDg0MDYxAl8yBA0kdDA4NDA2NDg0MjM2CQEiY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudAQFDHBvc2l0aW9uU2l6ZQUOcG9zaXRpb25NYXJnaW4FEXBvc2l0aW9uTHN0VXBkQ1BGBQ11bnJlYWxpemVkUG5sBAxyZW1haW5NYXJnaW4IBQ0kdDA4NDA2NDg0MjM2Al8xBAdiYWREZWJ0CAUNJHQwODQwNjQ4NDIzNgJfMgQOZnVuZGluZ1BheW1lbnQIBQ0kdDA4NDA2NDg0MjM2Al8zCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAQFzAQUMcmVtYWluTWFyZ2luCQEBcwEFDmZ1bmRpbmdQYXltZW50CQEBcwEJAQ5nZXRNYXJnaW5SYXRpbwEFB190cmFkZXIJAQFzAQUNdW5yZWFsaXplZFBubAkBAXMBBQdiYWREZWJ0CQEBcwEFEHBvc2l0aW9uTm90aW9uYWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEVdmlld19nZXRQZWdBZGp1c3RDb3N0AQZfcHJpY2UEB19xdEFzdFIJAQZxdEFzdFIABAdfYnNBc3RSCQEGYnNBc3RSAAQGcmVzdWx0CQEUZ2V0U3luY1Rlcm1pbmFsUHJpY2UDBQZfcHJpY2UFB19xdEFzdFIFB19ic0FzdFIJAAIBCQCkAwEIBQZyZXN1bHQCXzMBaQEYdmlld19nZXRUZXJtaW5hbEFtbVByaWNlAAQNJHQwODQ2NTI4NDczMwkBE2dldFRlcm1pbmFsQW1tU3RhdGUABBl0ZXJtaW5hbFF1b3RlQXNzZXRSZXNlcnZlCAUNJHQwODQ2NTI4NDczMwJfMQQYdGVybWluYWxCYXNlQXNzZXRSZXNlcnZlCAUNJHQwODQ2NTI4NDczMwJfMgQFcHJpY2UJAQRkaXZkAgkBBG11bGQCBRl0ZXJtaW5hbFF1b3RlQXNzZXRSZXNlcnZlCQEGcXRBc3RXAAkBBG11bGQCBRh0ZXJtaW5hbEJhc2VBc3NldFJlc2VydmUJAQZic0FzdFcACQACAQkApAMBBQVwcmljZQFpAQ92aWV3X2dldEZ1bmRpbmcABA91bmRlcmx5aW5nUHJpY2UJAQ5nZXRPcmFjbGVQcmljZQAEDSR0MDg0OTQ4ODUwMTAJAQpnZXRGdW5kaW5nAAQUc2hvcnRQcmVtaXVtRnJhY3Rpb24IBQ0kdDA4NDk0ODg1MDEwAl8xBBNsb25nUHJlbWl1bUZyYWN0aW9uCAUNJHQwODQ5NDg4NTAxMAJfMgQLbG9uZ0Z1bmRpbmcJAQRkaXZkAgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgUPdW5kZXJseWluZ1ByaWNlBAxzaG9ydEZ1bmRpbmcJAQRkaXZkAgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24FD3VuZGVybHlpbmdQcmljZQkAAgEJAKwCAgkArAICCQCsAgIJAQFzAQULbG9uZ0Z1bmRpbmcJAQFzAQUMc2hvcnRGdW5kaW5nCQEBcwEJARBnZXRUd2FwU3BvdFByaWNlAAkBAXMBCQEOZ2V0T3JhY2xlUHJpY2UAAWkBGHZpZXdfZ2V0Qm9ycm93ZWRCeVRyYWRlcgEHX3RyYWRlcgQNJHQwODUyOTY4NTM1MAkBE2dldEJvcnJvd2VkQnlUcmFkZXIBBQdfdHJhZGVyBAhib3Jyb3dlZAgFDSR0MDg1Mjk2ODUzNTACXzEEB2Fzc2V0SWQIBQ0kdDA4NTI5Njg1MzUwAl8yCQACAQkArAICCQEBcwEFCGJvcnJvd2VkBQdhc3NldElkAWkBEGNvbXB1dGVTcG90UHJpY2UABAZyZXN1bHQJAQxnZXRTcG90UHJpY2UACQCUCgIFA25pbAUGcmVzdWx0AWkBH2NvbXB1dGVGZWVGb3JUcmFkZXJXaXRoQXJ0aWZhY3QCB190cmFkZXILX2FydGlmYWN0SWQEBnJlc3VsdAkBGGdldEZvclRyYWRlcldpdGhBcnRpZmFjdAIFB190cmFkZXIFC19hcnRpZmFjdElkCQCUCgIFA25pbAUGcmVzdWx0AQJ0eAEGdmVyaWZ5AAkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAkBDmFkbWluUHVibGljS2V5ADckzyo=", "height": 2378780, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: DHmHiZefu9QT1WSMDPdRJ1RpuYXYoV7vAzae6p58sTyT Next: FUxiehA3kYkae3wke4Wi9FcuEbjKs12tDfpqsmdg7noR Diff:
OldNewDifferences
44 let k_ora_key = "k_ora_key"
55
66 let k_ora_block_key = "k_ora_block_key"
7+
8+let k_ora_open_key = "k_ora_open_key"
79
810 let k_ora = "k_ora"
911
469471 let amountBaseAssetBought = if (_isAdd)
470472 then amountBaseAssetBoughtAbs
471473 else -(amountBaseAssetBoughtAbs)
472- let $t01694617109 = updateReserve(_isAdd, _quoteAssetAmount, amountBaseAssetBoughtAbs)
473- let quoteAssetReserveAfter1 = $t01694617109._1
474- let baseAssetReserveAfter1 = $t01694617109._2
475- let totalPositionSizeAfter1 = $t01694617109._3
474+ let $t01680516968 = updateReserve(_isAdd, _quoteAssetAmount, amountBaseAssetBoughtAbs)
475+ let quoteAssetReserveAfter1 = $t01680516968._1
476+ let baseAssetReserveAfter1 = $t01680516968._2
477+ let totalPositionSizeAfter1 = $t01680516968._3
476478 let priceBefore = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
477479 let marketPrice = divd(_quoteAssetAmount, amountBaseAssetBoughtAbs)
478480 let priceDiff = abs((priceBefore - marketPrice))
492494 }
493495 else 0
494496 let signedMargin = ((_marginDelta - fundingPayment) + _oldPositionMargin)
495- let $t01859618723 = if ((0 > signedMargin))
497+ let $t01845518582 = if ((0 > signedMargin))
496498 then $Tuple2(0, abs(signedMargin))
497499 else $Tuple2(abs(signedMargin), 0)
498- let remainMargin = $t01859618723._1
499- let badDebt = $t01859618723._2
500+ let remainMargin = $t01845518582._1
501+ let badDebt = $t01845518582._2
500502 $Tuple3(remainMargin, badDebt, fundingPayment)
501503 }
502504
513515 let quoteAssetAfter = toInt(bdivd(k, toBigInt(muld(baseAssetPoolAmountAfter, _baseAssetWeight))))
514516 let quoteAssetSold = abs((quoteAssetAfter - muld(_quoteAssetReserve, _quoteAssetWeight)))
515517 let maxPriceImpactValue = maxPriceImpact()
516- let $t01991120072 = updateReserve(!(_isAdd), quoteAssetSold, _baseAssetAmount)
517- let quoteAssetReserveAfter1 = $t01991120072._1
518- let baseAssetReserveAfter1 = $t01991120072._2
519- let totalPositionSizeAfter1 = $t01991120072._3
518+ let $t01977019931 = updateReserve(!(_isAdd), quoteAssetSold, _baseAssetAmount)
519+ let quoteAssetReserveAfter1 = $t01977019931._1
520+ let baseAssetReserveAfter1 = $t01977019931._2
521+ let totalPositionSizeAfter1 = $t01977019931._3
520522 let marketPrice = divd(quoteAssetSold, _baseAssetAmount)
521523 let priceDiff = abs((priceBefore - marketPrice))
522524 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
536538 func swapOutput (_isAdd,_baseAssetAmount,_checkMaxPriceImpact) = swapOutputWithReserves(_isAdd, _baseAssetAmount, _checkMaxPriceImpact, qtAstR(), qtAstW(), bsAstR(), bsAstW())
537539
538540
539-func getOracleTwapPrice () = {
541+func getOraclePrice () = {
540542 let oracle = valueOrErrorMessage(addressFromString(getStringValue(this, k_ora)), "")
541543 let priceKey = getStringValue(this, k_ora_key)
542544 let lastValue = valueOrErrorMessage(getInteger(oracle, priceKey), ((("Can not get oracle price. Oracle: " + toString(oracle)) + " key: ") + priceKey))
553555 }
554556
555557
558+func isMarketClosed () = {
559+ let oracle = valueOrErrorMessage(addressFromString(getStringValue(this, k_ora)), "")
560+ let openKey = valueOrElse(getString(this, k_ora_open_key), "")
561+ if ((openKey != ""))
562+ then {
563+ let isOpen = valueOrErrorMessage(getBoolean(oracle, openKey), ((("Can not get oracle is open/closed. Oracle: " + toString(oracle)) + " key: ") + openKey))
564+ !(isOpen)
565+ }
566+ else false
567+ }
568+
569+
556570 func absPriceDiff (_oraclePrice,_quoteAssetReserve,_baseAssetReserve,_qtAstW,_bsAstW) = {
557571 let priceAfter = divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
558572 let averagePrice = divd((_oraclePrice + priceAfter), (2 * DECIMAL_UNIT))
562576
563577
564578 func requireNotOverSpreadLimit (_quoteAssetReserve,_baseAssetReserve) = {
565- let oraclePrice = getOracleTwapPrice()
579+ let oraclePrice = getOraclePrice()
566580 let _qtAstW = qtAstW()
567581 let _bsAstW = bsAstW()
568582 let absPriceDiffBefore = absPriceDiff(oraclePrice, qtAstR(), bsAstR(), _qtAstW, _bsAstW)
595609
596610
597611 func isOverFluctuationLimit () = {
598- let oraclePrice = getOracleTwapPrice()
612+ let oraclePrice = getOraclePrice()
599613 let currentPrice = getSpotPrice()
600614 (divd(abs((oraclePrice - currentPrice)), oraclePrice) > spreadLimit())
601615 }
606620 let isShort = (0 > _positionSize)
607621 let positionNotional = if ((_option == PNL_OPTION_SPOT))
608622 then {
609- let $t02463524855 = swapOutputWithReserves(!(isShort), positionSizeAbs, false, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
610- let outPositionNotional = $t02463524855._1
611- let x1 = $t02463524855._2
612- let x2 = $t02463524855._3
613- let x3 = $t02463524855._4
623+ let $t02488225102 = swapOutputWithReserves(!(isShort), positionSizeAbs, false, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
624+ let outPositionNotional = $t02488225102._1
625+ let x1 = $t02488225102._2
626+ let x2 = $t02488225102._3
627+ let x3 = $t02488225102._4
614628 outPositionNotional
615629 }
616- else muld(positionSizeAbs, getOracleTwapPrice())
630+ else muld(positionSizeAbs, getOraclePrice())
617631 positionNotional
618632 }
619633
631645
632646
633647 func getPositionNotionalAndUnrealizedPnl (_trader,_option) = {
634- let $t02628026408 = getPosition(_trader)
635- let positionSize = $t02628026408._1
636- let positionMargin = $t02628026408._2
637- let positionOpenNotional = $t02628026408._3
638- let positionLstUpdCPF = $t02628026408._4
648+ let $t02652326651 = getPosition(_trader)
649+ let positionSize = $t02652326651._1
650+ let positionMargin = $t02652326651._2
651+ let positionOpenNotional = $t02652326651._3
652+ let positionLstUpdCPF = $t02652326651._4
639653 getPositionNotionalAndUnrealizedPnlByValues(positionSize, positionOpenNotional, qtAstR(), qtAstW(), bsAstR(), bsAstW(), _option)
640654 }
641655
644658
645659
646660 func getMarginRatioByOption (_trader,_option) = {
647- let $t02692127032 = getPosition(_trader)
648- let positionSize = $t02692127032._1
649- let positionMargin = $t02692127032._2
650- let pon = $t02692127032._3
651- let positionLstUpdCPF = $t02692127032._4
652- let $t02703827131 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
653- let positionNotional = $t02703827131._1
654- let unrealizedPnl = $t02703827131._2
655- let $t02713627302 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
656- let remainMargin = $t02713627302._1
657- let badDebt = $t02713627302._2
661+ let $t02716427275 = getPosition(_trader)
662+ let positionSize = $t02716427275._1
663+ let positionMargin = $t02716427275._2
664+ let pon = $t02716427275._3
665+ let positionLstUpdCPF = $t02716427275._4
666+ let $t02728127374 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
667+ let positionNotional = $t02728127374._1
668+ let unrealizedPnl = $t02728127374._2
669+ let $t02737927545 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
670+ let remainMargin = $t02737927545._1
671+ let badDebt = $t02737927545._2
658672 calcMarginRatio(remainMargin, badDebt, positionNotional)
659673 }
660674
679693
680694
681695 func internalClosePosition (_trader,_checkMaxPriceImpact) = {
682- let $t02854228670 = getPosition(_trader)
683- let positionSize = $t02854228670._1
684- let positionMargin = $t02854228670._2
685- let positionOpenNotional = $t02854228670._3
686- let positionLstUpdCPF = $t02854228670._4
696+ let $t02878528913 = getPosition(_trader)
697+ let positionSize = $t02878528913._1
698+ let positionMargin = $t02878528913._2
699+ let positionOpenNotional = $t02878528913._3
700+ let positionLstUpdCPF = $t02878528913._4
687701 let unrealizedPnl = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)._2
688- let $t02876528933 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
689- let remainMargin = $t02876528933._1
690- let badDebt = $t02876528933._2
702+ let $t02900829176 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
703+ let remainMargin = $t02900829176._1
704+ let badDebt = $t02900829176._2
691705 let exchangedPositionSize = -(positionSize)
692706 let realizedPnl = unrealizedPnl
693707 let marginToVault = -(remainMargin)
694- let $t02906029334 = swapOutput((positionSize > 0), abs(positionSize), _checkMaxPriceImpact)
695- let exchangedQuoteAssetAmount = $t02906029334._1
696- let quoteAssetReserveAfter = $t02906029334._2
697- let baseAssetReserveAfter = $t02906029334._3
698- let totalPositionSizeAfter = $t02906029334._4
699- let totalLongAfter = $t02906029334._5
700- let totalShortAfter = $t02906029334._6
708+ let $t02930329577 = swapOutput((positionSize > 0), abs(positionSize), _checkMaxPriceImpact)
709+ let exchangedQuoteAssetAmount = $t02930329577._1
710+ let quoteAssetReserveAfter = $t02930329577._2
711+ let baseAssetReserveAfter = $t02930329577._3
712+ let totalPositionSizeAfter = $t02930329577._4
713+ let totalLongAfter = $t02930329577._5
714+ let totalShortAfter = $t02930329577._6
701715 let openInterestNotionalAfter = (openInterestNotional() - positionOpenNotional)
702716 $Tuple13(exchangedPositionSize, badDebt, realizedPnl, marginToVault, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, exchangedQuoteAssetAmount, totalLongAfter, totalShortAfter, (openInterestLong() - (if ((positionSize > 0))
703717 then positionOpenNotional
750764 then $Tuple2(qtAstR(), bsAstR())
751765 else {
752766 let direction = (_positionSize > 0)
753- let $t03145731636 = swapOutput(direction, abs(_positionSize), false)
754- let currentNetMarketValue = $t03145731636._1
755- let terminalQuoteAssetReserve = $t03145731636._2
756- let terminalBaseAssetReserve = $t03145731636._3
767+ let $t03170031879 = swapOutput(direction, abs(_positionSize), false)
768+ let currentNetMarketValue = $t03170031879._1
769+ let terminalQuoteAssetReserve = $t03170031879._2
770+ let terminalBaseAssetReserve = $t03170031879._3
757771 $Tuple2(terminalQuoteAssetReserve, terminalBaseAssetReserve)
758772 }
759773 }
796810
797811
798812 func getFunding () = {
799- let underlyingPrice = getOracleTwapPrice()
813+ let underlyingPrice = getOraclePrice()
800814 let spotTwapPrice = getTwapSpotPrice()
801815 let premium = (spotTwapPrice - underlyingPrice)
802- if (if ((totalShortPositionSize() == 0))
816+ if (if (if ((totalShortPositionSize() == 0))
803817 then true
804818 else (totalLongPositionSize() == 0))
819+ then true
820+ else isMarketClosed())
805821 then $Tuple2(0, 0)
806822 else if ((0 > premium))
807823 then {
820836 func getAdjustedFee (_artifactId,_baseFeeDiscount) = {
821837 let baseFeeRaw = fee()
822838 let baseFee = muld(baseFeeRaw, _baseFeeDiscount)
823- let $t03465535150 = if ((_artifactId != ""))
839+ let $t03492735422 = if ((_artifactId != ""))
824840 then {
825841 let artifactKind = strA(nftManagerAddress(), toCompositeKey(k_token_type, _artifactId))
826842 if ((artifactKind == FEE_REDUCTION_TOKEN_TYPE))
832848 else throw("Invalid attached artifact")
833849 }
834850 else $Tuple2(baseFee, false)
835- let adjustedFee = $t03465535150._1
836- let burnArtifact = $t03465535150._2
851+ let adjustedFee = $t03492735422._1
852+ let burnArtifact = $t03492735422._2
837853 $Tuple2(adjustedFee, burnArtifact)
838854 }
839855
874890 case _ =>
875891 throw("Invalid computeFeeDiscount result")
876892 }
877- let $t03638136455 = getAdjustedFee(_artifactId, feeDiscount)
878- let adjustedFee = $t03638136455._1
879- let burnArtifact = $t03638136455._2
893+ let $t03665336727 = getAdjustedFee(_artifactId, feeDiscount)
894+ let adjustedFee = $t03665336727._1
895+ let burnArtifact = $t03665336727._2
880896 $Tuple2(adjustedFee, burnArtifact)
881897 }
882898 else throw("Strict value is not equal to itself.")
10271043 let qtAstRAfter = (_qtAstR + _quoteAssetAmount)
10281044 let baseAssetAmountToAdd = (divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR)
10291045 let bsAstRAfter = (_bsAstR + baseAssetAmountToAdd)
1030- let $t04547745632 = getSyncTerminalPrice(getOracleTwapPrice(), qtAstRAfter, bsAstRAfter)
1031- let newQuoteAssetWeight = $t04547745632._1
1032- let newBaseAssetWeight = $t04547745632._2
1033- let marginToVault = $t04547745632._3
1046+ let $t04574945900 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1047+ let newQuoteAssetWeight = $t04574945900._1
1048+ let newBaseAssetWeight = $t04574945900._2
1049+ let marginToVault = $t04574945900._3
10341050 let doExchangePnL = if ((marginToVault != 0))
10351051 then {
10361052 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
11151131 if ((sync == sync))
11161132 then {
11171133 let _trader = getActualCaller(i)
1118- if (if (if (if (if ((0 >= _amount))
1134+ if (if (if (if (if (if ((0 >= _amount))
11191135 then true
11201136 else !(initialized()))
11211137 then true
11241140 else !(requireOpenPosition(_trader)))
11251141 then true
11261142 else paused())
1143+ then true
1144+ else isMarketClosed())
11271145 then throw("Invalid decreasePosition parameters")
11281146 else {
1129- let $t04947549615 = getPosition(_trader)
1130- let oldPositionSize = $t04947549615._1
1131- let oldPositionMargin = $t04947549615._2
1132- let oldPositionOpenNotional = $t04947549615._3
1133- let oldPositionLstUpdCPF = $t04947549615._4
1147+ let $t04976749907 = getPosition(_trader)
1148+ let oldPositionSize = $t04976749907._1
1149+ let oldPositionMargin = $t04976749907._2
1150+ let oldPositionOpenNotional = $t04976749907._3
1151+ let oldPositionLstUpdCPF = $t04976749907._4
11341152 let _direction = if ((oldPositionSize > 0))
11351153 then DIR_SHORT
11361154 else DIR_LONG
11371155 let isAdd = (_direction == DIR_LONG)
11381156 let openNotional = muld(_amount, _leverage)
1139- let $t04978849892 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1140- let oldPositionNotional = $t04978849892._1
1141- let unrealizedPnl = $t04978849892._2
1142- let $t04989852556 = if ((oldPositionNotional > openNotional))
1157+ let $t05008050184 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1158+ let oldPositionNotional = $t05008050184._1
1159+ let unrealizedPnl = $t05008050184._2
1160+ let $t05019052848 = if ((oldPositionNotional > openNotional))
11431161 then {
1144- let $t05031350497 = swapInput(isAdd, openNotional)
1145- let exchangedPositionSize = $t05031350497._1
1146- let quoteAssetReserveAfter = $t05031350497._2
1147- let baseAssetReserveAfter = $t05031350497._3
1148- let totalPositionSizeAfter = $t05031350497._4
1162+ let $t05060550789 = swapInput(isAdd, openNotional)
1163+ let exchangedPositionSize = $t05060550789._1
1164+ let quoteAssetReserveAfter = $t05060550789._2
1165+ let baseAssetReserveAfter = $t05060550789._3
1166+ let totalPositionSizeAfter = $t05060550789._4
11491167 let exchangedPositionSizeAbs = abs(exchangedPositionSize)
11501168 if (if ((_minBaseAssetAmount != 0))
11511169 then (_minBaseAssetAmount > exchangedPositionSizeAbs)
11531171 then throw(((("Too little base asset exchanged, got " + toString(exchangedPositionSizeAbs)) + " expected ") + toString(_minBaseAssetAmount)))
11541172 else {
11551173 let realizedPnl = divd(muld(unrealizedPnl, exchangedPositionSizeAbs), abs(oldPositionSize))
1156- let $t05093451179 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1157- let remainMargin = $t05093451179._1
1158- let badDebt = $t05093451179._2
1159- let fundingPayment = $t05093451179._3
1174+ let $t05122651471 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1175+ let remainMargin = $t05122651471._1
1176+ let badDebt = $t05122651471._2
1177+ let fundingPayment = $t05122651471._3
11601178 let exchangedQuoteAssetAmount = openNotional
11611179 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
11621180 let remainOpenNotional = if ((oldPositionSize > 0))
11751193 }
11761194 }
11771195 else throw("Close position first")
1178- let newPositionSize = $t04989852556._1
1179- let newPositionRemainMargin = $t04989852556._2
1180- let newPositionOpenNotional = $t04989852556._3
1181- let newPositionLatestCPF = $t04989852556._4
1182- let baseAssetReserveAfter = $t04989852556._5
1183- let quoteAssetReserveAfter = $t04989852556._6
1184- let totalPositionSizeAfter = $t04989852556._7
1185- let openInterestNotionalAfter = $t04989852556._8
1186- let totalLongAfter = $t04989852556._9
1187- let totalShortAfter = $t04989852556._10
1188- let totalLongOpenInterestAfter = $t04989852556._11
1189- let totalShortOpenInterestAfter = $t04989852556._12
1196+ let newPositionSize = $t05019052848._1
1197+ let newPositionRemainMargin = $t05019052848._2
1198+ let newPositionOpenNotional = $t05019052848._3
1199+ let newPositionLatestCPF = $t05019052848._4
1200+ let baseAssetReserveAfter = $t05019052848._5
1201+ let quoteAssetReserveAfter = $t05019052848._6
1202+ let totalPositionSizeAfter = $t05019052848._7
1203+ let openInterestNotionalAfter = $t05019052848._8
1204+ let totalLongAfter = $t05019052848._9
1205+ let totalShortAfter = $t05019052848._10
1206+ let totalLongOpenInterestAfter = $t05019052848._11
1207+ let totalShortOpenInterestAfter = $t05019052848._12
11901208 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
11911209 if ((notifyNotional == notifyNotional))
11921210 then (updatePosition(_trader, newPositionSize, newPositionRemainMargin, newPositionOpenNotional, newPositionLatestCPF) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter))
12091227 let _assetIdStr = toBase58String(value(_assetId))
12101228 let isQuoteAsset = (_assetId == quoteAsset())
12111229 let isCollateralAsset = isWhitelistAsset(_assetIdStr)
1212- if (if (if (if (if (if (if (if (if ((_direction != DIR_LONG))
1230+ if (if (if (if (if (if (if (if (if (if ((_direction != DIR_LONG))
12131231 then (_direction != DIR_SHORT)
12141232 else false)
12151233 then true
12281246 else paused())
12291247 then true
12301248 else closeOnly())
1249+ then true
1250+ else isMarketClosed())
12311251 then throw("Invalid increasePosition parameters")
12321252 else {
1233- let $t05399454079 = getForTraderWithArtifact(_trader, getArtifactId(i))
1234- let adjustedFee = $t05399454079._1
1235- let burnArtifact = $t05399454079._2
1253+ let $t05431054395 = getForTraderWithArtifact(_trader, getArtifactId(i))
1254+ let adjustedFee = $t05431054395._1
1255+ let burnArtifact = $t05431054395._2
12361256 let rawFeeAmount = muld(_rawAmount, adjustedFee)
12371257 let _amount = (_rawAmount - rawFeeAmount)
12381258 let distributeFeeAmount = if (isCollateralAsset)
12751295 throw("Invalid referrerFee")
12761296 }
12771297 let feeAmount = (distributeFeeAmount - referrerFee)
1278- let $t05539555535 = getPosition(_trader)
1279- let oldPositionSize = $t05539555535._1
1280- let oldPositionMargin = $t05539555535._2
1281- let oldPositionOpenNotional = $t05539555535._3
1282- let oldPositionLstUpdCPF = $t05539555535._4
1298+ let $t05571155851 = getPosition(_trader)
1299+ let oldPositionSize = $t05571155851._1
1300+ let oldPositionMargin = $t05571155851._2
1301+ let oldPositionOpenNotional = $t05571155851._3
1302+ let oldPositionLstUpdCPF = $t05571155851._4
12831303 let isNewPosition = (oldPositionSize == 0)
12841304 let isSameDirection = if ((oldPositionSize > 0))
12851305 then (_direction == DIR_LONG)
12881308 then isSameDirection
12891309 else false
12901310 let isAdd = (_direction == DIR_LONG)
1291- let $t05582458865 = if (if (isNewPosition)
1311+ let $t05614059181 = if (if (isNewPosition)
12921312 then true
12931313 else expandExisting)
12941314 then {
12951315 let openNotional = muld(_amount, _leverage)
1296- let $t05628656459 = swapInput(isAdd, openNotional)
1297- let amountBaseAssetBought = $t05628656459._1
1298- let quoteAssetReserveAfter = $t05628656459._2
1299- let baseAssetReserveAfter = $t05628656459._3
1300- let totalPositionSizeAfter = $t05628656459._4
1316+ let $t05660256775 = swapInput(isAdd, openNotional)
1317+ let amountBaseAssetBought = $t05660256775._1
1318+ let quoteAssetReserveAfter = $t05660256775._2
1319+ let baseAssetReserveAfter = $t05660256775._3
1320+ let totalPositionSizeAfter = $t05660256775._4
13011321 if (if ((_minBaseAssetAmount != 0))
13021322 then (_minBaseAssetAmount > abs(amountBaseAssetBought))
13031323 else false)
13111331 then openNotional
13121332 else 0))
13131333 let increaseMarginRequirement = divd(openNotional, _leverage)
1314- let $t05706757306 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, increaseMarginRequirement)
1315- let remainMargin = $t05706757306._1
1316- let x1 = $t05706757306._2
1317- let x2 = $t05706757306._3
1334+ let $t05738357622 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, increaseMarginRequirement)
1335+ let remainMargin = $t05738357622._1
1336+ let x1 = $t05738357622._2
1337+ let x2 = $t05738357622._3
13181338 if (!(requireNotOverSpreadLimit(quoteAssetReserveAfter, baseAssetReserveAfter)))
13191339 then throw("Over max spread limit")
13201340 else if (!(requireNotOverMaxOpenNotional(totalLongOpenInterestAfter, totalShortOpenInterestAfter)))
13281348 }
13291349 else {
13301350 let openNotional = muld(_amount, _leverage)
1331- let $t05856558681 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1332- let oldPositionNotional = $t05856558681._1
1333- let unrealizedPnl = $t05856558681._2
1351+ let $t05888158997 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1352+ let oldPositionNotional = $t05888158997._1
1353+ let unrealizedPnl = $t05888158997._2
13341354 if ((oldPositionNotional > openNotional))
13351355 then throw("Use decreasePosition to decrease position size")
13361356 else throw("Close position first")
13371357 }
1338- let newPositionSize = $t05582458865._1
1339- let newPositionRemainMargin = $t05582458865._2
1340- let newPositionOpenNotional = $t05582458865._3
1341- let newPositionLatestCPF = $t05582458865._4
1342- let baseAssetReserveAfter = $t05582458865._5
1343- let quoteAssetReserveAfter = $t05582458865._6
1344- let totalPositionSizeAfter = $t05582458865._7
1345- let openInterestNotionalAfter = $t05582458865._8
1346- let totalLongAfter = $t05582458865._9
1347- let totalShortAfter = $t05582458865._10
1348- let totalLongOpenInterestAfter = $t05582458865._11
1349- let totalShortOpenInterestAfter = $t05582458865._12
1350- let $t05887158928 = distributeFee(feeAmount)
1351- let feeToStakers = $t05887158928._1
1352- let feeToVault = $t05887158928._2
1358+ let newPositionSize = $t05614059181._1
1359+ let newPositionRemainMargin = $t05614059181._2
1360+ let newPositionOpenNotional = $t05614059181._3
1361+ let newPositionLatestCPF = $t05614059181._4
1362+ let baseAssetReserveAfter = $t05614059181._5
1363+ let quoteAssetReserveAfter = $t05614059181._6
1364+ let totalPositionSizeAfter = $t05614059181._7
1365+ let openInterestNotionalAfter = $t05614059181._8
1366+ let totalLongAfter = $t05614059181._9
1367+ let totalShortAfter = $t05614059181._10
1368+ let totalLongOpenInterestAfter = $t05614059181._11
1369+ let totalShortOpenInterestAfter = $t05614059181._12
1370+ let $t05918759244 = distributeFee(feeAmount)
1371+ let feeToStakers = $t05918759244._1
1372+ let feeToVault = $t05918759244._2
13531373 let stake = if (isQuoteAsset)
13541374 then {
13551375 let stake = invoke(vaultAddress(), "addLocked", [false], [AttachedPayment(quoteAsset(), _amount)])
13981418 let _assetIdStr = toBase58String(value(_assetId))
13991419 let isQuoteAsset = (_assetId == quoteAsset())
14001420 let isCollateralAsset = isWhitelistAsset(_assetIdStr)
1401- if (if (if (if (if (if (if (!(isQuoteAsset))
1421+ if (if (if (if (if (if (if (if (!(isQuoteAsset))
14021422 then !(isCollateralAsset)
14031423 else false)
14041424 then true
14111431 else paused())
14121432 then true
14131433 else closeOnly())
1434+ then true
1435+ else isMarketClosed())
14141436 then throw("Invalid addMargin parameters")
14151437 else {
1416- let $t06087660961 = getForTraderWithArtifact(_trader, getArtifactId(i))
1417- let adjustedFee = $t06087660961._1
1418- let burnArtifact = $t06087660961._2
1438+ let $t06121661301 = getForTraderWithArtifact(_trader, getArtifactId(i))
1439+ let adjustedFee = $t06121661301._1
1440+ let burnArtifact = $t06121661301._2
14191441 let rawFeeAmount = muld(_rawAmount, adjustedFee)
14201442 let _amount = (_rawAmount - rawFeeAmount)
14211443 let distributeFeeAmount = if (isCollateralAsset)
14581480 throw("Invalid referrerFee")
14591481 }
14601482 let feeAmount = (distributeFeeAmount - referrerFee)
1461- let $t06226062400 = getPosition(_trader)
1462- let oldPositionSize = $t06226062400._1
1463- let oldPositionMargin = $t06226062400._2
1464- let oldPositionOpenNotional = $t06226062400._3
1465- let oldPositionLstUpdCPF = $t06226062400._4
1466- let $t06240662463 = distributeFee(feeAmount)
1467- let feeToStakers = $t06240662463._1
1468- let feeToVault = $t06240662463._2
1483+ let $t06260062740 = getPosition(_trader)
1484+ let oldPositionSize = $t06260062740._1
1485+ let oldPositionMargin = $t06260062740._2
1486+ let oldPositionOpenNotional = $t06260062740._3
1487+ let oldPositionLstUpdCPF = $t06260062740._4
1488+ let $t06274662803 = distributeFee(feeAmount)
1489+ let feeToStakers = $t06274662803._1
1490+ let feeToVault = $t06274662803._2
14691491 let stake = if (isQuoteAsset)
14701492 then {
14711493 let stake = invoke(vaultAddress(), "addLocked", [false], [AttachedPayment(quoteAsset(), _amount)])
15041526 if ((sync == sync))
15051527 then {
15061528 let _trader = toString(i.caller)
1507- if (if (if (if ((0 >= _amount))
1529+ if (if (if (if (if ((0 >= _amount))
15081530 then true
15091531 else !(requireOpenPosition(_trader)))
15101532 then true
15111533 else !(initialized()))
15121534 then true
15131535 else paused())
1536+ then true
1537+ else isMarketClosed())
15141538 then throw("Invalid removeMargin parameters")
15151539 else {
1516- let $t06357563715 = getPosition(_trader)
1517- let oldPositionSize = $t06357563715._1
1518- let oldPositionMargin = $t06357563715._2
1519- let oldPositionOpenNotional = $t06357563715._3
1520- let oldPositionLstUpdCPF = $t06357563715._4
1540+ let $t06393964079 = getPosition(_trader)
1541+ let oldPositionSize = $t06393964079._1
1542+ let oldPositionMargin = $t06393964079._2
1543+ let oldPositionOpenNotional = $t06393964079._3
1544+ let oldPositionLstUpdCPF = $t06393964079._4
15211545 let marginDelta = -(_amount)
1522- let $t06375263931 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, marginDelta)
1523- let remainMargin = $t06375263931._1
1524- let badDebt = $t06375263931._2
1546+ let $t06411664295 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, marginDelta)
1547+ let remainMargin = $t06411664295._1
1548+ let badDebt = $t06411664295._2
15251549 if ((badDebt != 0))
15261550 then throw("Invalid removed margin amount")
15271551 else {
15301554 then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
15311555 else {
15321556 let quoteAssetStr = toBase58String(quoteAsset())
1533- let $t06437564429 = getBorrowedByTrader(_trader)
1534- let borrowed = $t06437564429._1
1535- let assetId = $t06437564429._2
1557+ let $t06473964793 = getBorrowedByTrader(_trader)
1558+ let borrowed = $t06473964793._1
1559+ let assetId = $t06473964793._2
15361560 let toRepay = if ((_amount > borrowed))
15371561 then borrowed
15381562 else _amount
15911615 then {
15921616 let _trader = getActualCaller(i)
15931617 let _traderAddress = valueOrErrorMessage(addressFromString(_trader), "Invalid caller")
1594- if (if (if (if (if (!(requireOpenPosition(_trader)))
1618+ if (if (if (if (if (if (!(requireOpenPosition(_trader)))
15951619 then true
15961620 else !(initialized()))
15971621 then true
16001624 else (0 >= _size))
16011625 then true
16021626 else (0 > _minQuoteAssetAmount))
1627+ then true
1628+ else isMarketClosed())
16031629 then throw("Invalid closePosition parameters")
16041630 else {
1605- let $t06658766727 = getPosition(_trader)
1606- let oldPositionSize = $t06658766727._1
1607- let oldPositionMargin = $t06658766727._2
1608- let oldPositionOpenNotional = $t06658766727._3
1609- let oldPositionLstUpdCPF = $t06658766727._4
1610- let $t06673371170 = if ((abs(oldPositionSize) > _size))
1631+ let $t06697767117 = getPosition(_trader)
1632+ let oldPositionSize = $t06697767117._1
1633+ let oldPositionMargin = $t06697767117._2
1634+ let oldPositionOpenNotional = $t06697767117._3
1635+ let oldPositionLstUpdCPF = $t06697767117._4
1636+ let $t06712371769 = if ((abs(oldPositionSize) > _size))
16111637 then {
16121638 let _direction = if ((oldPositionSize > 0))
16131639 then DIR_SHORT
16141640 else DIR_LONG
16151641 let isAdd = (_direction == DIR_LONG)
1616- let $t06732467546 = swapOutput((oldPositionSize > 0), _size, true)
1617- let exchangedQuoteAssetAmount = $t06732467546._1
1618- let quoteAssetReserveAfter = $t06732467546._2
1619- let baseAssetReserveAfter = $t06732467546._3
1620- let totalPositionSizeAfter = $t06732467546._4
1642+ let $t06771467936 = swapOutput((oldPositionSize > 0), _size, true)
1643+ let exchangedQuoteAssetAmount = $t06771467936._1
1644+ let quoteAssetReserveAfter = $t06771467936._2
1645+ let baseAssetReserveAfter = $t06771467936._3
1646+ let totalPositionSizeAfter = $t06771467936._4
16211647 let exchangedPositionSize = if ((oldPositionSize > 0))
16221648 then -(_size)
16231649 else _size
1624- let $t06763767791 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1625- let oldPositionNotional = $t06763767791._1
1626- let unrealizedPnl = $t06763767791._2
1650+ let $t06802768181 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1651+ let oldPositionNotional = $t06802768181._1
1652+ let unrealizedPnl = $t06802768181._2
16271653 let mr = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
16281654 let realizedRatio = divd(abs(exchangedPositionSize), abs(oldPositionSize))
16291655 let realizedPnl = muld(unrealizedPnl, realizedRatio)
1630- let $t06807068308 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1631- let remainMargin = $t06807068308._1
1632- let positionBadDebt = $t06807068308._2
1633- let fundingPayment = $t06807068308._3
1656+ let remainMarginBefore = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, unrealizedPnl)._1
1657+ let $t06868268920 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1658+ let remainMargin = $t06868268920._1
1659+ let positionBadDebt = $t06868268920._2
1660+ let fundingPayment = $t06868268920._3
16341661 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
16351662 let remainOpenNotional = if ((oldPositionSize > 0))
16361663 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
16441671 then (_minQuoteAssetAmount > exchangedQuoteAssetAmount)
16451672 else false)
16461673 then throw(((("Limit error: " + toString(exchangedQuoteAssetAmount)) + " < ") + toString(_minQuoteAssetAmount)))
1647- else $Tuple15(newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, positionBadDebt, realizedPnl, (abs((remainMargin - newPositionMargin)) + realizedPnl), quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, (totalLongPositionSize() - (if ((newPositionSize > 0))
1674+ else $Tuple15(newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, positionBadDebt, realizedPnl, (remainMarginBefore - newPositionMargin), quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, (totalLongPositionSize() - (if ((newPositionSize > 0))
16481675 then abs(exchangedPositionSize)
16491676 else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
16501677 then abs(exchangedPositionSize)
16571684 else if ((_size > abs(oldPositionSize)))
16581685 then throw("Invalid closePosition parameters")
16591686 else {
1660- let $t07011170530 = internalClosePosition(_trader, true)
1661- let exchangedQuoteAssetAmount = $t07011170530._1
1662- let positionBadDebt = $t07011170530._2
1663- let realizedPnl = $t07011170530._3
1664- let marginToVault = $t07011170530._4
1665- let quoteAssetReserveAfter = $t07011170530._5
1666- let baseAssetReserveAfter = $t07011170530._6
1667- let totalPositionSizeAfter = $t07011170530._7
1668- let openInterestNotionalAfter = $t07011170530._8
1669- let x2 = $t07011170530._9
1670- let totalLongAfter = $t07011170530._10
1671- let totalShortAfter = $t07011170530._11
1672- let totalLongOpenInterestAfter = $t07011170530._12
1673- let totalShortOpenInterestAfter = $t07011170530._13
1687+ let $t07071071129 = internalClosePosition(_trader, true)
1688+ let exchangedQuoteAssetAmount = $t07071071129._1
1689+ let positionBadDebt = $t07071071129._2
1690+ let realizedPnl = $t07071071129._3
1691+ let marginToVault = $t07071071129._4
1692+ let quoteAssetReserveAfter = $t07071071129._5
1693+ let baseAssetReserveAfter = $t07071071129._6
1694+ let totalPositionSizeAfter = $t07071071129._7
1695+ let openInterestNotionalAfter = $t07071071129._8
1696+ let x2 = $t07071071129._9
1697+ let totalLongAfter = $t07071071129._10
1698+ let totalShortAfter = $t07071071129._11
1699+ let totalLongOpenInterestAfter = $t07071071129._12
1700+ let totalShortOpenInterestAfter = $t07071071129._13
16741701 if (if ((_minQuoteAssetAmount != 0))
16751702 then (_minQuoteAssetAmount > exchangedQuoteAssetAmount)
16761703 else false)
16771704 then throw(((("Limit error: " + toString(exchangedQuoteAssetAmount)) + " < ") + toString(_minQuoteAssetAmount)))
16781705 else $Tuple15(0, 0, 0, 0, positionBadDebt, realizedPnl, marginToVault, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)
16791706 }
1680- let newPositionSize = $t06673371170._1
1681- let newPositionMargin = $t06673371170._2
1682- let newPositionOpenNotional = $t06673371170._3
1683- let newPositionLstUpdCPF = $t06673371170._4
1684- let positionBadDebt = $t06673371170._5
1685- let realizedPnl = $t06673371170._6
1686- let marginToVault = $t06673371170._7
1687- let quoteAssetReserveAfter = $t06673371170._8
1688- let baseAssetReserveAfter = $t06673371170._9
1689- let totalPositionSizeAfter = $t06673371170._10
1690- let openInterestNotionalAfter = $t06673371170._11
1691- let totalLongAfter = $t06673371170._12
1692- let totalShortAfter = $t06673371170._13
1693- let totalLongOpenInterestAfter = $t06673371170._14
1694- let totalShortOpenInterestAfter = $t06673371170._15
1707+ let newPositionSize = $t06712371769._1
1708+ let newPositionMargin = $t06712371769._2
1709+ let newPositionOpenNotional = $t06712371769._3
1710+ let newPositionLstUpdCPF = $t06712371769._4
1711+ let positionBadDebt = $t06712371769._5
1712+ let realizedPnl = $t06712371769._6
1713+ let marginToVault = $t06712371769._7
1714+ let quoteAssetReserveAfter = $t06712371769._8
1715+ let baseAssetReserveAfter = $t06712371769._9
1716+ let totalPositionSizeAfter = $t06712371769._10
1717+ let openInterestNotionalAfter = $t06712371769._11
1718+ let totalLongAfter = $t06712371769._12
1719+ let totalShortAfter = $t06712371769._13
1720+ let totalLongOpenInterestAfter = $t06712371769._14
1721+ let totalShortOpenInterestAfter = $t06712371769._15
16951722 if ((positionBadDebt > 0))
16961723 then throw("Unable to close position with bad debt")
16971724 else {
16981725 let withdrawAmount = abs(marginToVault)
16991726 let ammBalance = (cbalance() - withdrawAmount)
1700- let $t07137971586 = if ((0 > ammBalance))
1727+ let $t07197872185 = if ((0 > ammBalance))
17011728 then $Tuple2(0, abs(ammBalance))
17021729 else $Tuple2(ammBalance, 0)
1703- let ammNewBalance = $t07137971586._1
1704- let x11 = $t07137971586._2
1705- let $t07159371647 = getBorrowedByTrader(_trader)
1706- let borrowed = $t07159371647._1
1707- let assetId = $t07159371647._2
1708- let $t07166272521 = if ((borrowed > 0))
1730+ let ammNewBalance = $t07197872185._1
1731+ let x11 = $t07197872185._2
1732+ let $t07219272246 = getBorrowedByTrader(_trader)
1733+ let borrowed = $t07219272246._1
1734+ let assetId = $t07219272246._2
1735+ let $t07226173120 = if ((borrowed > 0))
17091736 then if ((withdrawAmount >= borrowed))
17101737 then {
17111738 let doRepay = invoke(collateralAddress(), "repay", [_trader, borrowed, assetId], nil)
17201747 else throw("Strict value is not equal to itself.")
17211748 }
17221749 else $Tuple2(nil, withdrawAmount)
1723- if (($t07166272521 == $t07166272521))
1750+ if (($t07226173120 == $t07226173120))
17241751 then {
1725- let quoteWithdrawAmount = $t07166272521._2
1726- let sendCollateralAction = $t07166272521._1
1752+ let quoteWithdrawAmount = $t07226173120._2
1753+ let sendCollateralAction = $t07226173120._1
17271754 let unstake = if ((quoteWithdrawAmount > 0))
17281755 then {
17291756 let unstake = invoke(vaultAddress(), "withdrawLocked", [quoteWithdrawAmount], nil)
17661793 vmax(spotMarginRatio, oracleMarginRatio)
17671794 }
17681795 else spotMarginRatio
1769- if (if (if (if (!(requireMoreMarginRatio(marginRatio, maintenanceMarginRatio(), false)))
1796+ if (if (if (if (if (!(requireMoreMarginRatio(marginRatio, maintenanceMarginRatio(), false)))
17701797 then true
17711798 else !(requireOpenPosition(_trader)))
17721799 then true
17731800 else !(initialized()))
17741801 then true
17751802 else paused())
1803+ then true
1804+ else isMarketClosed())
17761805 then throw("Unable to liquidate")
17771806 else if (if (if ((spotMarginRatio > liquidationFeeRatio()))
17781807 then (partialLiquidationRatio() > 0)
17801809 then (DECIMAL_UNIT > partialLiquidationRatio())
17811810 else false)
17821811 then {
1783- let $t07481874968 = getPosition(_trader)
1784- let oldPositionSize = $t07481874968._1
1785- let oldPositionMargin = $t07481874968._2
1786- let oldPositionOpenNotional = $t07481874968._3
1787- let oldPositionLstUpdCPF = $t07481874968._4
1812+ let $t07544175591 = getPosition(_trader)
1813+ let oldPositionSize = $t07544175591._1
1814+ let oldPositionMargin = $t07544175591._2
1815+ let oldPositionOpenNotional = $t07544175591._3
1816+ let oldPositionLstUpdCPF = $t07544175591._4
17881817 let _direction = if ((oldPositionSize > 0))
17891818 then DIR_SHORT
17901819 else DIR_LONG
17911820 let isAdd = (_direction == DIR_LONG)
17921821 let exchangedQuoteAssetAmount = getPartialLiquidationAmount(_trader, oldPositionSize)
1793- let $t07519375297 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1794- let oldPositionNotional = $t07519375297._1
1795- let unrealizedPnl = $t07519375297._2
1796- let $t07530575492 = swapInput(isAdd, exchangedQuoteAssetAmount)
1797- let exchangedPositionSize = $t07530575492._1
1798- let quoteAssetReserveAfter = $t07530575492._2
1799- let baseAssetReserveAfter = $t07530575492._3
1800- let totalPositionSizeAfter = $t07530575492._4
1822+ let $t07581675920 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1823+ let oldPositionNotional = $t07581675920._1
1824+ let unrealizedPnl = $t07581675920._2
1825+ let $t07592876115 = swapInput(isAdd, exchangedQuoteAssetAmount)
1826+ let exchangedPositionSize = $t07592876115._1
1827+ let quoteAssetReserveAfter = $t07592876115._2
1828+ let baseAssetReserveAfter = $t07592876115._3
1829+ let totalPositionSizeAfter = $t07592876115._4
18011830 let liquidationRatio = divd(abs(exchangedPositionSize), abs(oldPositionSize))
18021831 let realizedPnl = muld(unrealizedPnl, liquidationRatio)
1803- let $t07578176014 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1804- let remainMargin = $t07578176014._1
1805- let badDebt = $t07578176014._2
1806- let fundingPayment = $t07578176014._3
1832+ let $t07640476637 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1833+ let remainMargin = $t07640476637._1
1834+ let badDebt = $t07640476637._2
1835+ let fundingPayment = $t07640476637._3
18071836 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
18081837 let remainOpenNotional = if ((oldPositionSize > 0))
18091838 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
18171846 let newPositionLstUpdCPF = latestCumulativePremiumFraction(newPositionSize)
18181847 let openInterestNotionalAfter = (openInterestNotional() - exchangedQuoteAssetAmount)
18191848 let ammBalance = (cbalance() - liquidationPenalty)
1820- let $t07718377312 = if ((0 > ammBalance))
1849+ let $t07780677935 = if ((0 > ammBalance))
18211850 then $Tuple2(0, abs(ammBalance))
18221851 else $Tuple2(ammBalance, 0)
1823- let newAmmBalance = $t07718377312._1
1824- let x11 = $t07718377312._2
1825- let $t07732077374 = getBorrowedByTrader(_trader)
1826- let borrowed = $t07732077374._1
1827- let assetId = $t07732077374._2
1852+ let newAmmBalance = $t07780677935._1
1853+ let x11 = $t07780677935._2
1854+ let $t07794377997 = getBorrowedByTrader(_trader)
1855+ let borrowed = $t07794377997._1
1856+ let assetId = $t07794377997._2
18281857 let doLiquidateCollateral = if ((borrowed > 0))
18291858 then {
18301859 let collateralToSell = muld(borrowed, liquidationRatio)
18621891 else throw("Strict value is not equal to itself.")
18631892 }
18641893 else {
1865- let $t07906979564 = internalClosePosition(_trader, false)
1866- let x1 = $t07906979564._1
1867- let badDebt = $t07906979564._2
1868- let x2 = $t07906979564._3
1869- let x3 = $t07906979564._4
1870- let quoteAssetReserveAfter = $t07906979564._5
1871- let baseAssetReserveAfter = $t07906979564._6
1872- let totalPositionSizeAfter = $t07906979564._7
1873- let openInterestNotionalAfter = $t07906979564._8
1874- let exchangedQuoteAssetAmount = $t07906979564._9
1875- let totalLongAfter = $t07906979564._10
1876- let totalShortAfter = $t07906979564._11
1877- let totalLongOpenInterestAfter = $t07906979564._12
1878- let totalShortOpenInterestAfter = $t07906979564._13
1894+ let $t07969280187 = internalClosePosition(_trader, false)
1895+ let x1 = $t07969280187._1
1896+ let badDebt = $t07969280187._2
1897+ let x2 = $t07969280187._3
1898+ let x3 = $t07969280187._4
1899+ let quoteAssetReserveAfter = $t07969280187._5
1900+ let baseAssetReserveAfter = $t07969280187._6
1901+ let totalPositionSizeAfter = $t07969280187._7
1902+ let openInterestNotionalAfter = $t07969280187._8
1903+ let exchangedQuoteAssetAmount = $t07969280187._9
1904+ let totalLongAfter = $t07969280187._10
1905+ let totalShortAfter = $t07969280187._11
1906+ let totalLongOpenInterestAfter = $t07969280187._12
1907+ let totalShortOpenInterestAfter = $t07969280187._13
18791908 let liquidationPenalty = muld(exchangedQuoteAssetAmount, liquidationFeeRatio())
18801909 let feeToLiquidator = (liquidationPenalty / 2)
18811910 let feeToVault = (liquidationPenalty - feeToLiquidator)
18821911 let ammBalance = (cbalance() - liquidationPenalty)
1883- let $t07997280101 = if ((0 > ammBalance))
1912+ let $t08059580724 = if ((0 > ammBalance))
18841913 then $Tuple2(0, abs(ammBalance))
18851914 else $Tuple2(ammBalance, 0)
1886- let newAmmBalance = $t07997280101._1
1887- let x11 = $t07997280101._2
1888- let $t08010980163 = getBorrowedByTrader(_trader)
1889- let borrowed = $t08010980163._1
1890- let assetId = $t08010980163._2
1915+ let newAmmBalance = $t08059580724._1
1916+ let x11 = $t08059580724._2
1917+ let $t08073280786 = getBorrowedByTrader(_trader)
1918+ let borrowed = $t08073280786._1
1919+ let assetId = $t08073280786._2
18911920 let doLiquidateCollateral = if ((borrowed > 0))
18921921 then {
18931922 let realizeAndClose = invoke(collateralAddress(), "realizePartiallyAndClose", [_trader, 0, assetId], nil)
19461975 else paused())
19471976 then throw(((("Invalid funding block timestamp: " + toString(lastBlock.timestamp)) + " < ") + toString(fundingBlockTimestamp)))
19481977 else {
1949- let underlyingPrice = getOracleTwapPrice()
1950- let $t08203982101 = getFunding()
1951- let shortPremiumFraction = $t08203982101._1
1952- let longPremiumFraction = $t08203982101._2
1978+ let underlyingPrice = getOraclePrice()
1979+ let $t08265882720 = getFunding()
1980+ let shortPremiumFraction = $t08265882720._1
1981+ let longPremiumFraction = $t08265882720._2
19531982 updateFunding((fundingBlockTimestamp + fundingPeriodSeconds()), (latestLongCumulativePremiumFraction() + longPremiumFraction), (latestShortCumulativePremiumFraction() + shortPremiumFraction), divd(longPremiumFraction, underlyingPrice), divd(shortPremiumFraction, underlyingPrice))
19541983 }
19551984 }
19621991 func syncTerminalPriceToOracle () = {
19631992 let _qtAstR = qtAstR()
19641993 let _bsAstR = bsAstR()
1965- let $t08253382672 = getSyncTerminalPrice(getOracleTwapPrice(), _qtAstR, _bsAstR)
1966- let newQuoteAssetWeight = $t08253382672._1
1967- let newBaseAssetWeight = $t08253382672._2
1968- let marginToVault = $t08253382672._3
1994+ let $t08315283287 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1995+ let newQuoteAssetWeight = $t08315283287._1
1996+ let newBaseAssetWeight = $t08315283287._2
1997+ let marginToVault = $t08315283287._3
19691998 let doExchangePnL = if ((marginToVault != 0))
19701999 then {
19712000 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
19862015 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
19872016 if ((sync == sync))
19882017 then {
1989- let $t08324183342 = getPosition(_trader)
1990- let positionSize = $t08324183342._1
1991- let positionMargin = $t08324183342._2
1992- let pon = $t08324183342._3
1993- let positionLstUpdCPF = $t08324183342._4
1994- let $t08334583446 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1995- let positionNotional = $t08334583446._1
1996- let unrealizedPnl = $t08334583446._2
1997- let $t08344983621 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
1998- let remainMargin = $t08344983621._1
1999- let badDebt = $t08344983621._2
2000- let fundingPayment = $t08344983621._3
2018+ let $t08385683957 = getPosition(_trader)
2019+ let positionSize = $t08385683957._1
2020+ let positionMargin = $t08385683957._2
2021+ let pon = $t08385683957._3
2022+ let positionLstUpdCPF = $t08385683957._4
2023+ let $t08396084061 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
2024+ let positionNotional = $t08396084061._1
2025+ let unrealizedPnl = $t08396084061._2
2026+ let $t08406484236 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
2027+ let remainMargin = $t08406484236._1
2028+ let badDebt = $t08406484236._2
2029+ let fundingPayment = $t08406484236._3
20012030 throw((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)))
20022031 }
20032032 else throw("Strict value is not equal to itself.")
20172046
20182047 @Callable(i)
20192048 func view_getTerminalAmmPrice () = {
2020- let $t08403784118 = getTerminalAmmState()
2021- let terminalQuoteAssetReserve = $t08403784118._1
2022- let terminalBaseAssetReserve = $t08403784118._2
2049+ let $t08465284733 = getTerminalAmmState()
2050+ let terminalQuoteAssetReserve = $t08465284733._1
2051+ let terminalBaseAssetReserve = $t08465284733._2
20232052 let price = divd(muld(terminalQuoteAssetReserve, qtAstW()), muld(terminalBaseAssetReserve, bsAstW()))
20242053 throw(toString(price))
20252054 }
20282057
20292058 @Callable(i)
20302059 func view_getFunding () = {
2031- let underlyingPrice = getOracleTwapPrice()
2032- let $t08433784399 = getFunding()
2033- let shortPremiumFraction = $t08433784399._1
2034- let longPremiumFraction = $t08433784399._2
2060+ let underlyingPrice = getOraclePrice()
2061+ let $t08494885010 = getFunding()
2062+ let shortPremiumFraction = $t08494885010._1
2063+ let longPremiumFraction = $t08494885010._2
20352064 let longFunding = divd(longPremiumFraction, underlyingPrice)
20362065 let shortFunding = divd(shortPremiumFraction, underlyingPrice)
2037- throw((((s(longFunding) + s(shortFunding)) + s(getTwapSpotPrice())) + s(getOracleTwapPrice())))
2066+ throw((((s(longFunding) + s(shortFunding)) + s(getTwapSpotPrice())) + s(getOraclePrice())))
20382067 }
20392068
20402069
20412070
20422071 @Callable(i)
20432072 func view_getBorrowedByTrader (_trader) = {
2044- let $t08468984743 = getBorrowedByTrader(_trader)
2045- let borrowed = $t08468984743._1
2046- let assetId = $t08468984743._2
2073+ let $t08529685350 = getBorrowedByTrader(_trader)
2074+ let borrowed = $t08529685350._1
2075+ let assetId = $t08529685350._2
20472076 throw((s(borrowed) + assetId))
20482077 }
20492078
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let k_ora_key = "k_ora_key"
55
66 let k_ora_block_key = "k_ora_block_key"
7+
8+let k_ora_open_key = "k_ora_open_key"
79
810 let k_ora = "k_ora"
911
1012 let k_balance = "k_balance"
1113
1214 let k_sequence = "k_sequence"
1315
1416 let k_positionSize = "k_positionSize"
1517
1618 let k_positionMargin = "k_positionMargin"
1719
1820 let k_positionOpenNotional = "k_positionOpenNotional"
1921
2022 let k_positionLastUpdatedCumulativePremiumFraction = "k_positionFraction"
2123
2224 let k_positionSequence = "k_positionSequence"
2325
2426 let k_positionAsset = "k_positionAsset"
2527
2628 let k_initialized = "k_initialized"
2729
2830 let k_paused = "k_paused"
2931
3032 let k_closeOnly = "k_closeOnly"
3133
3234 let k_fee = "k_fee"
3335
3436 let k_fundingPeriod = "k_fundingPeriod"
3537
3638 let k_initMarginRatio = "k_initMarginRatio"
3739
3840 let k_maintenanceMarginRatio = "k_mmr"
3941
4042 let k_liquidationFeeRatio = "k_liquidationFeeRatio"
4143
4244 let k_partialLiquidationRatio = "k_partLiquidationRatio"
4345
4446 let k_spreadLimit = "k_spreadLimit"
4547
4648 let k_maxPriceImpact = "k_maxPriceImpact"
4749
4850 let k_maxPriceSpread = "k_maxPriceSpread"
4951
5052 let k_maxOpenNotional = "k_maxOpenNotional"
5153
5254 let k_feeToStakersPercent = "k_feeToStakersPercent"
5355
5456 let k_maxOracleDelay = "k_maxOracleDelay"
5557
5658 let k_lastDataStr = "k_lastDataStr"
5759
5860 let k_lastMinuteId = "k_lastMinuteId"
5961
6062 let k_twapDataLastCumulativePrice = "k_twapDataLastCumulativePrice"
6163
6264 let k_twapDataLastPrice = "k_twapDataLastPrice"
6365
6466 let k_twapDataPreviousMinuteId = "k_twapDataPreviousMinuteId"
6567
6668 let k_latestLongCumulativePremiumFraction = "k_latestLongPremiumFraction"
6769
6870 let k_latestShortCumulativePremiumFraction = "k_latestShortPremiumFraction"
6971
7072 let k_nextFundingBlock = "k_nextFundingBlockMinTimestamp"
7173
7274 let k_longFundingRate = "k_longFundingRate"
7375
7476 let k_shortFundingRate = "k_shortFundingRate"
7577
7678 let k_quoteAssetReserve = "k_qtAstR"
7779
7880 let k_baseAssetReserve = "k_bsAstR"
7981
8082 let k_quoteAssetWeight = "k_qtAstW"
8183
8284 let k_baseAssetWeight = "k_bsAstW"
8385
8486 let k_totalPositionSize = "k_totalPositionSize"
8587
8688 let k_totalLongPositionSize = "k_totalLongPositionSize"
8789
8890 let k_totalShortPositionSize = "k_totalShortPositionSize"
8991
9092 let k_openInterestNotional = "k_openInterestNotional"
9193
9294 let k_openInterestShort = "k_openInterestShort"
9395
9496 let k_openInterestLong = "k_openInterestLong"
9597
9698 let k_coordinatorAddress = "k_coordinatorAddress"
9799
98100 let k_vault_address = "k_vault_address"
99101
100102 let k_admin_address = "k_admin_address"
101103
102104 let k_admin_public_key = "k_admin_public_key"
103105
104106 let k_quote_asset = "k_quote_asset"
105107
106108 let k_quote_staking = "k_quote_staking"
107109
108110 let k_staking_address = "k_staking_address"
109111
110112 let k_miner_address = "k_miner_address"
111113
112114 let k_orders_address = "k_orders_address"
113115
114116 let k_referral_address = "k_referral_address"
115117
116118 let k_collateral_address = "k_collateral_address"
117119
118120 let k_exchange_address = "k_exchange_address"
119121
120122 let k_nft_manager_address = "k_nft_manager_address"
121123
122124 let k_trader_market_asset_collateral = "k_trader_market_asset_collateral"
123125
124126 func toCompositeKey (_key,_address) = ((_key + "_") + _address)
125127
126128
127129 func coordinator () = valueOrErrorMessage(addressFromString(getStringValue(this, k_coordinatorAddress)), "Coordinator not set")
128130
129131
130132 func adminAddress () = addressFromString(getStringValue(coordinator(), k_admin_address))
131133
132134
133135 func adminPublicKey () = fromBase58String(getStringValue(coordinator(), k_admin_public_key))
134136
135137
136138 func quoteAsset () = fromBase58String(getStringValue(coordinator(), k_quote_asset))
137139
138140
139141 func quoteAssetStaking () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_quote_staking)), "Quote asset staking not set")
140142
141143
142144 func stakingAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_staking_address)), "Staking not set")
143145
144146
145147 func vaultAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_vault_address)), "Vault not set")
146148
147149
148150 func minerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_miner_address)), "Miner not set")
149151
150152
151153 func ordersAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_orders_address)), "Orders not set")
152154
153155
154156 func referralAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_referral_address)), "Referral not set")
155157
156158
157159 func nftManagerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_nft_manager_address)), "NFT Manager not set")
158160
159161
160162 func collateralAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_collateral_address)), "Collateral Manager not set")
161163
162164
163165 func swapAddress () = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(coordinator(), k_exchange_address), "No swap address")), "Invalid swap address")
164166
165167
166168 let k_whitelist_asset = "k_whitelist_asset"
167169
168170 func isWhitelistAsset (_assetId) = valueOrElse(getBoolean(collateralAddress(), toCompositeKey(k_whitelist_asset, _assetId)), false)
169171
170172
171173 let k_token_param = "k_token_param"
172174
173175 let k_token_type = "k_token_type"
174176
175177 let FEE_REDUCTION_TOKEN_TYPE = "fee_reduction"
176178
177179 let DIR_LONG = 1
178180
179181 let DIR_SHORT = 2
180182
181183 let TWAP_INTERVAL = 15
182184
183185 let ORACLE_INTERVAL = 15
184186
185187 let SECONDS = 1000
186188
187189 let DECIMAL_NUMBERS = 6
188190
189191 let DECIMAL_UNIT = (1 * (((((10 * 10) * 10) * 10) * 10) * 10))
190192
191193 let ONE_DAY = (86400 * DECIMAL_UNIT)
192194
193195 let ALL_FEES = 100
194196
195197 let PNL_OPTION_SPOT = 1
196198
197199 let PNL_OPTION_ORACLE = 2
198200
199201 func s (_x) = (toString(_x) + ",")
200202
201203
202204 func divd (_x,_y) = fraction(_x, DECIMAL_UNIT, _y, HALFEVEN)
203205
204206
205207 func muld (_x,_y) = fraction(_x, _y, DECIMAL_UNIT, HALFEVEN)
206208
207209
208210 func sqrtd (_x) = sqrt(_x, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
209211
210212
211213 func powd (_x,_y) = pow(_x, DECIMAL_NUMBERS, _y, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
212214
213215
214216 func bdivd (_x,_y) = fraction(_x, toBigInt(DECIMAL_UNIT), _y, HALFEVEN)
215217
216218
217219 func bmuld (_x,_y) = fraction(_x, _y, toBigInt(DECIMAL_UNIT), HALFEVEN)
218220
219221
220222 func bsqrtd (_x) = sqrtBigInt(_x, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
221223
222224
223225 func bpowd (_x,_y) = pow(_x, DECIMAL_NUMBERS, _y, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
224226
225227
226228 func abs (_x) = if ((_x > 0))
227229 then _x
228230 else -(_x)
229231
230232
231233 func vmax (_x,_y) = if ((_x >= _y))
232234 then _x
233235 else _y
234236
235237
236238 func listToStr (_list) = {
237239 func _join (accumulator,val) = ((accumulator + val) + ",")
238240
239241 let newListStr = {
240242 let $l = _list
241243 let $s = size($l)
242244 let $acc0 = ""
243245 func $f0_1 ($a,$i) = if (($i >= $s))
244246 then $a
245247 else _join($a, $l[$i])
246248
247249 func $f0_2 ($a,$i) = if (($i >= $s))
248250 then $a
249251 else throw("List size exceeds 20")
250252
251253 $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)
252254 }
253255 let newListStrU = dropRight(newListStr, 1)
254256 let newListStrR = if ((take(newListStrU, 1) == ","))
255257 then drop(newListStrU, 1)
256258 else newListStrU
257259 newListStrR
258260 }
259261
260262
261263 func strToList (_str) = split(_str, ",")
262264
263265
264266 func pushToQueue (_list,_maxSize,_value) = if ((size(_list) > _maxSize))
265267 then (removeByIndex(_list, 0) :+ _value)
266268 else (_list :+ _value)
267269
268270
269271 func int (k) = valueOrErrorMessage(getInteger(this, k), ("no value for " + k))
270272
271273
272274 func intOr (k,def) = valueOrElse(getInteger(this, k), def)
273275
274276
275277 func strA (_address,_key) = {
276278 let val = valueOrErrorMessage(getString(_address, _key), ("No value for key " + _key))
277279 val
278280 }
279281
280282
281283 func intA (_address,_key) = {
282284 let val = valueOrErrorMessage(getInteger(_address, _key), ("No value for key " + _key))
283285 val
284286 }
285287
286288
287289 func cbalance () = int(k_balance)
288290
289291
290292 func fee () = int(k_fee)
291293
292294
293295 func initMarginRatio () = int(k_initMarginRatio)
294296
295297
296298 func qtAstR () = int(k_quoteAssetReserve)
297299
298300
299301 func bsAstR () = int(k_baseAssetReserve)
300302
301303
302304 func qtAstW () = intOr(k_quoteAssetWeight, DECIMAL_UNIT)
303305
304306
305307 func bsAstW () = intOr(k_baseAssetWeight, DECIMAL_UNIT)
306308
307309
308310 func totalPositionSize () = int(k_totalPositionSize)
309311
310312
311313 func openInterestNotional () = int(k_openInterestNotional)
312314
313315
314316 func openInterestShort () = int(k_openInterestShort)
315317
316318
317319 func openInterestLong () = int(k_openInterestLong)
318320
319321
320322 func nextFundingBlockTimestamp () = int(k_nextFundingBlock)
321323
322324
323325 func fundingPeriodRaw () = int(k_fundingPeriod)
324326
325327
326328 func fundingPeriodDecimal () = (fundingPeriodRaw() * DECIMAL_UNIT)
327329
328330
329331 func fundingPeriodSeconds () = (fundingPeriodRaw() * SECONDS)
330332
331333
332334 func maintenanceMarginRatio () = int(k_maintenanceMarginRatio)
333335
334336
335337 func liquidationFeeRatio () = int(k_liquidationFeeRatio)
336338
337339
338340 func partialLiquidationRatio () = int(k_partialLiquidationRatio)
339341
340342
341343 func spreadLimit () = int(k_spreadLimit)
342344
343345
344346 func maxPriceImpact () = int(k_maxPriceImpact)
345347
346348
347349 func maxPriceSpread () = int(k_maxPriceSpread)
348350
349351
350352 func maxOpenNotional () = int(k_maxOpenNotional)
351353
352354
353355 func latestLongCumulativePremiumFraction () = int(k_latestLongCumulativePremiumFraction)
354356
355357
356358 func latestShortCumulativePremiumFraction () = int(k_latestShortCumulativePremiumFraction)
357359
358360
359361 func totalShortPositionSize () = int(k_totalShortPositionSize)
360362
361363
362364 func totalLongPositionSize () = int(k_totalLongPositionSize)
363365
364366
365367 func lastSequence () = intOr(k_sequence, 0)
366368
367369
368370 func feeToStakersPercent () = int(k_feeToStakersPercent)
369371
370372
371373 func maxOracleDelay () = int(k_maxOracleDelay)
372374
373375
374376 func getActualCaller (i) = valueOrElse(getString(ordersAddress(), "k_sender"), toString(i.caller))
375377
376378
377379 func requireMoreMarginRatio (_marginRatio,_baseMarginRatio,_largerThanOrEqualTo) = {
378380 let remainingMarginRatio = (_marginRatio - _baseMarginRatio)
379381 if (if (_largerThanOrEqualTo)
380382 then (0 > remainingMarginRatio)
381383 else false)
382384 then throw("Invalid margin")
383385 else if (if (!(_largerThanOrEqualTo))
384386 then (remainingMarginRatio >= 0)
385387 else false)
386388 then throw("Invalid margin")
387389 else true
388390 }
389391
390392
391393 func latestCumulativePremiumFraction (_positionSize) = if ((_positionSize == 0))
392394 then throw("Should not be called with _positionSize == 0")
393395 else if ((_positionSize > 0))
394396 then latestLongCumulativePremiumFraction()
395397 else latestShortCumulativePremiumFraction()
396398
397399
398400 func getPosition (_trader) = {
399401 let positionSizeOpt = getInteger(this, toCompositeKey(k_positionSize, _trader))
400402 match positionSizeOpt {
401403 case positionSize: Int =>
402404 $Tuple4(positionSize, getIntegerValue(this, toCompositeKey(k_positionMargin, _trader)), getIntegerValue(this, toCompositeKey(k_positionOpenNotional, _trader)), getIntegerValue(this, toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, _trader)))
403405 case _ =>
404406 $Tuple4(0, 0, 0, 0)
405407 }
406408 }
407409
408410
409411 func getPositionAsset (_trader) = {
410412 let positionAssetOpt = getString(this, toCompositeKey(k_positionAsset, _trader))
411413 match positionAssetOpt {
412414 case positionAsset: String =>
413415 positionAsset
414416 case _ =>
415417 toBase58String(quoteAsset())
416418 }
417419 }
418420
419421
420422 func requireOpenPosition (_trader) = if ((getPosition(_trader)._1 == 0))
421423 then throw("No open position")
422424 else true
423425
424426
425427 func initialized () = valueOrElse(getBoolean(this, k_initialized), false)
426428
427429
428430 func paused () = valueOrElse(getBoolean(this, k_paused), false)
429431
430432
431433 func closeOnly () = valueOrElse(getBoolean(this, k_closeOnly), false)
432434
433435
434436 func updateReserve (_isAdd,_quoteAssetAmount,_baseAssetAmount) = if (_isAdd)
435437 then {
436438 let newBase = (bsAstR() - _baseAssetAmount)
437439 if ((0 >= newBase))
438440 then throw("Tx lead to base asset reserve <= 0, revert")
439441 else $Tuple3((qtAstR() + _quoteAssetAmount), newBase, (totalPositionSize() + _baseAssetAmount))
440442 }
441443 else {
442444 let newQuote = (qtAstR() - _quoteAssetAmount)
443445 if ((0 >= newQuote))
444446 then throw("Tx lead to base quote reserve <= 0, revert")
445447 else $Tuple3(newQuote, (bsAstR() + _baseAssetAmount), (totalPositionSize() - _baseAssetAmount))
446448 }
447449
448450
449451 func calcInvariant (_qtAstR,_qtAstW,_bsAstR,_bsAstW) = {
450452 let bqtAstR = toBigInt(_qtAstR)
451453 let bqtAstW = toBigInt(_qtAstW)
452454 let bbsAstR = toBigInt(_bsAstR)
453455 let bbsAstW = toBigInt(_bsAstW)
454456 bmuld(bmuld(bqtAstR, bqtAstW), bmuld(bbsAstR, bbsAstW))
455457 }
456458
457459
458460 func swapInput (_isAdd,_quoteAssetAmount) = {
459461 let _qtAstR = qtAstR()
460462 let _bsAstR = bsAstR()
461463 let _qtAstW = qtAstW()
462464 let _bsAstW = bsAstW()
463465 let k = calcInvariant(_qtAstR, _qtAstW, _bsAstR, _bsAstW)
464466 let quoteAssetReserveAfter = if (_isAdd)
465467 then (_qtAstR + _quoteAssetAmount)
466468 else (_qtAstR - _quoteAssetAmount)
467469 let baseAssetReserveAfter = toInt(bdivd(k, toBigInt(muld(quoteAssetReserveAfter, _qtAstW))))
468470 let amountBaseAssetBoughtAbs = divd(abs((baseAssetReserveAfter - _bsAstR)), _qtAstW)
469471 let amountBaseAssetBought = if (_isAdd)
470472 then amountBaseAssetBoughtAbs
471473 else -(amountBaseAssetBoughtAbs)
472- let $t01694617109 = updateReserve(_isAdd, _quoteAssetAmount, amountBaseAssetBoughtAbs)
473- let quoteAssetReserveAfter1 = $t01694617109._1
474- let baseAssetReserveAfter1 = $t01694617109._2
475- let totalPositionSizeAfter1 = $t01694617109._3
474+ let $t01680516968 = updateReserve(_isAdd, _quoteAssetAmount, amountBaseAssetBoughtAbs)
475+ let quoteAssetReserveAfter1 = $t01680516968._1
476+ let baseAssetReserveAfter1 = $t01680516968._2
477+ let totalPositionSizeAfter1 = $t01680516968._3
476478 let priceBefore = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
477479 let marketPrice = divd(_quoteAssetAmount, amountBaseAssetBoughtAbs)
478480 let priceDiff = abs((priceBefore - marketPrice))
479481 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
480482 let maxPriceImpactValue = maxPriceImpact()
481483 if ((priceImpact > maxPriceImpactValue))
482484 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)))
483485 else $Tuple4(amountBaseAssetBought, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1)
484486 }
485487
486488
487489 func calcRemainMarginWithFundingPayment (_oldPositionSize,_oldPositionMargin,_oldPositionCumulativePremiumFraction,_marginDelta) = {
488490 let fundingPayment = if ((_oldPositionSize != 0))
489491 then {
490492 let _latestCumulativePremiumFraction = latestCumulativePremiumFraction(_oldPositionSize)
491493 muld((_latestCumulativePremiumFraction - _oldPositionCumulativePremiumFraction), _oldPositionSize)
492494 }
493495 else 0
494496 let signedMargin = ((_marginDelta - fundingPayment) + _oldPositionMargin)
495- let $t01859618723 = if ((0 > signedMargin))
497+ let $t01845518582 = if ((0 > signedMargin))
496498 then $Tuple2(0, abs(signedMargin))
497499 else $Tuple2(abs(signedMargin), 0)
498- let remainMargin = $t01859618723._1
499- let badDebt = $t01859618723._2
500+ let remainMargin = $t01845518582._1
501+ let badDebt = $t01845518582._2
500502 $Tuple3(remainMargin, badDebt, fundingPayment)
501503 }
502504
503505
504506 func swapOutputWithReserves (_isAdd,_baseAssetAmount,_checkMaxPriceImpact,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
505507 let priceBefore = divd(muld(_quoteAssetReserve, _quoteAssetWeight), muld(_baseAssetReserve, _baseAssetWeight))
506508 if ((_baseAssetAmount == 0))
507509 then throw("Invalid base asset amount")
508510 else {
509511 let k = calcInvariant(_quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
510512 let baseAssetPoolAmountAfter = if (_isAdd)
511513 then (_baseAssetReserve + _baseAssetAmount)
512514 else (_baseAssetReserve - _baseAssetAmount)
513515 let quoteAssetAfter = toInt(bdivd(k, toBigInt(muld(baseAssetPoolAmountAfter, _baseAssetWeight))))
514516 let quoteAssetSold = abs((quoteAssetAfter - muld(_quoteAssetReserve, _quoteAssetWeight)))
515517 let maxPriceImpactValue = maxPriceImpact()
516- let $t01991120072 = updateReserve(!(_isAdd), quoteAssetSold, _baseAssetAmount)
517- let quoteAssetReserveAfter1 = $t01991120072._1
518- let baseAssetReserveAfter1 = $t01991120072._2
519- let totalPositionSizeAfter1 = $t01991120072._3
518+ let $t01977019931 = updateReserve(!(_isAdd), quoteAssetSold, _baseAssetAmount)
519+ let quoteAssetReserveAfter1 = $t01977019931._1
520+ let baseAssetReserveAfter1 = $t01977019931._2
521+ let totalPositionSizeAfter1 = $t01977019931._3
520522 let marketPrice = divd(quoteAssetSold, _baseAssetAmount)
521523 let priceDiff = abs((priceBefore - marketPrice))
522524 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
523525 if (if ((priceImpact > maxPriceImpactValue))
524526 then _checkMaxPriceImpact
525527 else false)
526528 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)))
527529 else $Tuple7(quoteAssetSold, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1, (totalLongPositionSize() - (if (_isAdd)
528530 then abs(_baseAssetAmount)
529531 else 0)), (totalShortPositionSize() - (if (!(_isAdd))
530532 then abs(_baseAssetAmount)
531533 else 0)), priceImpact)
532534 }
533535 }
534536
535537
536538 func swapOutput (_isAdd,_baseAssetAmount,_checkMaxPriceImpact) = swapOutputWithReserves(_isAdd, _baseAssetAmount, _checkMaxPriceImpact, qtAstR(), qtAstW(), bsAstR(), bsAstW())
537539
538540
539-func getOracleTwapPrice () = {
541+func getOraclePrice () = {
540542 let oracle = valueOrErrorMessage(addressFromString(getStringValue(this, k_ora)), "")
541543 let priceKey = getStringValue(this, k_ora_key)
542544 let lastValue = valueOrErrorMessage(getInteger(oracle, priceKey), ((("Can not get oracle price. Oracle: " + toString(oracle)) + " key: ") + priceKey))
543545 let blockKey = valueOrElse(getString(this, k_ora_block_key), "")
544546 if ((blockKey != ""))
545547 then {
546548 let currentBlock = lastBlock.height
547549 let lastOracleBlock = valueOrErrorMessage(getInteger(oracle, blockKey), ((("Can not get oracle block. Oracle: " + toString(oracle)) + " key: ") + blockKey))
548550 if (((currentBlock - lastOracleBlock) > maxOracleDelay()))
549551 then throw(((("Oracle stale data. Last oracle block: " + toString(lastOracleBlock)) + " current block: ") + toString(currentBlock)))
550552 else lastValue
551553 }
552554 else lastValue
553555 }
554556
555557
558+func isMarketClosed () = {
559+ let oracle = valueOrErrorMessage(addressFromString(getStringValue(this, k_ora)), "")
560+ let openKey = valueOrElse(getString(this, k_ora_open_key), "")
561+ if ((openKey != ""))
562+ then {
563+ let isOpen = valueOrErrorMessage(getBoolean(oracle, openKey), ((("Can not get oracle is open/closed. Oracle: " + toString(oracle)) + " key: ") + openKey))
564+ !(isOpen)
565+ }
566+ else false
567+ }
568+
569+
556570 func absPriceDiff (_oraclePrice,_quoteAssetReserve,_baseAssetReserve,_qtAstW,_bsAstW) = {
557571 let priceAfter = divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
558572 let averagePrice = divd((_oraclePrice + priceAfter), (2 * DECIMAL_UNIT))
559573 let absPriceDiff = divd(abs((_oraclePrice - priceAfter)), averagePrice)
560574 absPriceDiff
561575 }
562576
563577
564578 func requireNotOverSpreadLimit (_quoteAssetReserve,_baseAssetReserve) = {
565- let oraclePrice = getOracleTwapPrice()
579+ let oraclePrice = getOraclePrice()
566580 let _qtAstW = qtAstW()
567581 let _bsAstW = bsAstW()
568582 let absPriceDiffBefore = absPriceDiff(oraclePrice, qtAstR(), bsAstR(), _qtAstW, _bsAstW)
569583 let absPriceDiffAfter = absPriceDiff(oraclePrice, _quoteAssetReserve, _baseAssetReserve, _qtAstW, _bsAstW)
570584 if (if ((absPriceDiffAfter > maxPriceSpread()))
571585 then (absPriceDiffAfter > absPriceDiffBefore)
572586 else false)
573587 then throw(((("Price spread " + toString(absPriceDiffAfter)) + " > max price spread ") + toString(maxPriceSpread())))
574588 else true
575589 }
576590
577591
578592 func requireNotOverMaxOpenNotional (_longOpenNotional,_shortOpenNotional) = {
579593 let _maxOpenNotional = maxOpenNotional()
580594 if ((_longOpenNotional > _maxOpenNotional))
581595 then throw(((("Long open notional " + toString(_longOpenNotional)) + " > max open notional ") + toString(_maxOpenNotional)))
582596 else if ((_shortOpenNotional > _maxOpenNotional))
583597 then throw(((("Short open notional " + toString(_shortOpenNotional)) + " > max open notional ") + toString(_maxOpenNotional)))
584598 else true
585599 }
586600
587601
588602 func getSpotPrice () = {
589603 let _quoteAssetReserve = qtAstR()
590604 let _baseAssetReserve = bsAstR()
591605 let _qtAstW = qtAstW()
592606 let _bsAstW = bsAstW()
593607 divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
594608 }
595609
596610
597611 func isOverFluctuationLimit () = {
598- let oraclePrice = getOracleTwapPrice()
612+ let oraclePrice = getOraclePrice()
599613 let currentPrice = getSpotPrice()
600614 (divd(abs((oraclePrice - currentPrice)), oraclePrice) > spreadLimit())
601615 }
602616
603617
604618 func getPositionAdjustedOpenNotional (_positionSize,_option,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
605619 let positionSizeAbs = abs(_positionSize)
606620 let isShort = (0 > _positionSize)
607621 let positionNotional = if ((_option == PNL_OPTION_SPOT))
608622 then {
609- let $t02463524855 = swapOutputWithReserves(!(isShort), positionSizeAbs, false, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
610- let outPositionNotional = $t02463524855._1
611- let x1 = $t02463524855._2
612- let x2 = $t02463524855._3
613- let x3 = $t02463524855._4
623+ let $t02488225102 = swapOutputWithReserves(!(isShort), positionSizeAbs, false, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
624+ let outPositionNotional = $t02488225102._1
625+ let x1 = $t02488225102._2
626+ let x2 = $t02488225102._3
627+ let x3 = $t02488225102._4
614628 outPositionNotional
615629 }
616- else muld(positionSizeAbs, getOracleTwapPrice())
630+ else muld(positionSizeAbs, getOraclePrice())
617631 positionNotional
618632 }
619633
620634
621635 func getPositionNotionalAndUnrealizedPnlByValues (_positionSize,_positionOpenNotional,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight,_option) = if ((_positionSize == 0))
622636 then throw("Invalid position size")
623637 else {
624638 let isShort = (0 > _positionSize)
625639 let positionNotional = getPositionAdjustedOpenNotional(_positionSize, _option, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
626640 let unrealizedPnl = if (isShort)
627641 then (_positionOpenNotional - positionNotional)
628642 else (positionNotional - _positionOpenNotional)
629643 $Tuple2(positionNotional, unrealizedPnl)
630644 }
631645
632646
633647 func getPositionNotionalAndUnrealizedPnl (_trader,_option) = {
634- let $t02628026408 = getPosition(_trader)
635- let positionSize = $t02628026408._1
636- let positionMargin = $t02628026408._2
637- let positionOpenNotional = $t02628026408._3
638- let positionLstUpdCPF = $t02628026408._4
648+ let $t02652326651 = getPosition(_trader)
649+ let positionSize = $t02652326651._1
650+ let positionMargin = $t02652326651._2
651+ let positionOpenNotional = $t02652326651._3
652+ let positionLstUpdCPF = $t02652326651._4
639653 getPositionNotionalAndUnrealizedPnlByValues(positionSize, positionOpenNotional, qtAstR(), qtAstW(), bsAstR(), bsAstW(), _option)
640654 }
641655
642656
643657 func calcMarginRatio (_remainMargin,_badDebt,_positionNotional) = divd((_remainMargin - _badDebt), _positionNotional)
644658
645659
646660 func getMarginRatioByOption (_trader,_option) = {
647- let $t02692127032 = getPosition(_trader)
648- let positionSize = $t02692127032._1
649- let positionMargin = $t02692127032._2
650- let pon = $t02692127032._3
651- let positionLstUpdCPF = $t02692127032._4
652- let $t02703827131 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
653- let positionNotional = $t02703827131._1
654- let unrealizedPnl = $t02703827131._2
655- let $t02713627302 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
656- let remainMargin = $t02713627302._1
657- let badDebt = $t02713627302._2
661+ let $t02716427275 = getPosition(_trader)
662+ let positionSize = $t02716427275._1
663+ let positionMargin = $t02716427275._2
664+ let pon = $t02716427275._3
665+ let positionLstUpdCPF = $t02716427275._4
666+ let $t02728127374 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
667+ let positionNotional = $t02728127374._1
668+ let unrealizedPnl = $t02728127374._2
669+ let $t02737927545 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
670+ let remainMargin = $t02737927545._1
671+ let badDebt = $t02737927545._2
658672 calcMarginRatio(remainMargin, badDebt, positionNotional)
659673 }
660674
661675
662676 func getMarginRatio (_trader) = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
663677
664678
665679 func getPartialLiquidationAmount (_trader,_positionSize) = {
666680 let maximumRatio = vmax(partialLiquidationRatio(), (DECIMAL_UNIT - divd(getMarginRatio(_trader), maintenanceMarginRatio())))
667681 let maxExchangedPositionSize = muld(abs(_positionSize), maximumRatio)
668682 let swapResult = swapOutput((_positionSize > 0), maxExchangedPositionSize, false)
669683 let maxExchangedQuoteAssetAmount = swapResult._1
670684 let priceImpact = swapResult._7
671685 if ((maxPriceImpact() > priceImpact))
672686 then maxExchangedQuoteAssetAmount
673687 else {
674688 let exchangedPositionSize = muld(abs(_positionSize), partialLiquidationRatio())
675689 let exchangedQuoteAssetAmount = swapOutput((_positionSize > 0), exchangedPositionSize, false)._1
676690 exchangedQuoteAssetAmount
677691 }
678692 }
679693
680694
681695 func internalClosePosition (_trader,_checkMaxPriceImpact) = {
682- let $t02854228670 = getPosition(_trader)
683- let positionSize = $t02854228670._1
684- let positionMargin = $t02854228670._2
685- let positionOpenNotional = $t02854228670._3
686- let positionLstUpdCPF = $t02854228670._4
696+ let $t02878528913 = getPosition(_trader)
697+ let positionSize = $t02878528913._1
698+ let positionMargin = $t02878528913._2
699+ let positionOpenNotional = $t02878528913._3
700+ let positionLstUpdCPF = $t02878528913._4
687701 let unrealizedPnl = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)._2
688- let $t02876528933 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
689- let remainMargin = $t02876528933._1
690- let badDebt = $t02876528933._2
702+ let $t02900829176 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
703+ let remainMargin = $t02900829176._1
704+ let badDebt = $t02900829176._2
691705 let exchangedPositionSize = -(positionSize)
692706 let realizedPnl = unrealizedPnl
693707 let marginToVault = -(remainMargin)
694- let $t02906029334 = swapOutput((positionSize > 0), abs(positionSize), _checkMaxPriceImpact)
695- let exchangedQuoteAssetAmount = $t02906029334._1
696- let quoteAssetReserveAfter = $t02906029334._2
697- let baseAssetReserveAfter = $t02906029334._3
698- let totalPositionSizeAfter = $t02906029334._4
699- let totalLongAfter = $t02906029334._5
700- let totalShortAfter = $t02906029334._6
708+ let $t02930329577 = swapOutput((positionSize > 0), abs(positionSize), _checkMaxPriceImpact)
709+ let exchangedQuoteAssetAmount = $t02930329577._1
710+ let quoteAssetReserveAfter = $t02930329577._2
711+ let baseAssetReserveAfter = $t02930329577._3
712+ let totalPositionSizeAfter = $t02930329577._4
713+ let totalLongAfter = $t02930329577._5
714+ let totalShortAfter = $t02930329577._6
701715 let openInterestNotionalAfter = (openInterestNotional() - positionOpenNotional)
702716 $Tuple13(exchangedPositionSize, badDebt, realizedPnl, marginToVault, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, exchangedQuoteAssetAmount, totalLongAfter, totalShortAfter, (openInterestLong() - (if ((positionSize > 0))
703717 then positionOpenNotional
704718 else 0)), (openInterestShort() - (if ((0 > positionSize))
705719 then positionOpenNotional
706720 else 0)))
707721 }
708722
709723
710724 func getTwapSpotPrice () = {
711725 let minuteId = ((lastBlock.timestamp / 1000) / 60)
712726 let startMinuteId = (minuteId - TWAP_INTERVAL)
713727 let listStr = valueOrElse(getString(this, k_lastDataStr), "")
714728 let list = split(listStr, ",")
715729 func filterFn (accumulator,next) = if ((startMinuteId >= parseIntValue(next)))
716730 then (accumulator :+ parseIntValue(next))
717731 else accumulator
718732
719733 let listF = {
720734 let $l = list
721735 let $s = size($l)
722736 let $acc0 = nil
723737 func $f0_1 ($a,$i) = if (($i >= $s))
724738 then $a
725739 else filterFn($a, $l[$i])
726740
727741 func $f0_2 ($a,$i) = if (($i >= $s))
728742 then $a
729743 else throw("List size exceeds 20")
730744
731745 $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)
732746 }
733747 let maxIndex = if ((size(listF) > 0))
734748 then max(listF)
735749 else parseIntValue(list[0])
736750 let lastMinuteId = valueOrElse(getInteger(this, k_lastMinuteId), 0)
737751 let endLastCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(lastMinuteId))), 0)
738752 let endLastPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(lastMinuteId))), 0)
739753 let nowCumulativePrice = (endLastCumulativePrice + ((minuteId - lastMinuteId) * endLastPrice))
740754 let startLastCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(maxIndex))), 0)
741755 let startLastPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(maxIndex))), 0)
742756 let startCumulativePrice = (startLastCumulativePrice + ((startMinuteId - maxIndex) * startLastPrice))
743757 ((nowCumulativePrice - startCumulativePrice) / TWAP_INTERVAL)
744758 }
745759
746760
747761 func getTerminalAmmState () = {
748762 let _positionSize = totalPositionSize()
749763 if ((_positionSize == 0))
750764 then $Tuple2(qtAstR(), bsAstR())
751765 else {
752766 let direction = (_positionSize > 0)
753- let $t03145731636 = swapOutput(direction, abs(_positionSize), false)
754- let currentNetMarketValue = $t03145731636._1
755- let terminalQuoteAssetReserve = $t03145731636._2
756- let terminalBaseAssetReserve = $t03145731636._3
767+ let $t03170031879 = swapOutput(direction, abs(_positionSize), false)
768+ let currentNetMarketValue = $t03170031879._1
769+ let terminalQuoteAssetReserve = $t03170031879._2
770+ let terminalBaseAssetReserve = $t03170031879._3
757771 $Tuple2(terminalQuoteAssetReserve, terminalBaseAssetReserve)
758772 }
759773 }
760774
761775
762776 func getQuoteAssetWeight (baseAssetReserve,totalPositionSize,quoteAssetReserve,targetPrice) = {
763777 let b = toBigInt(baseAssetReserve)
764778 let sz = toBigInt(totalPositionSize)
765779 let q = toBigInt(quoteAssetReserve)
766780 let p = toBigInt(targetPrice)
767781 let bs2 = bpowd((b + sz), toBigInt((2 * DECIMAL_UNIT)))
768782 let qbs2 = bmuld(q, bs2)
769783 let ps4 = (toBigInt(4) * bmuld(p, sz))
770784 let sqr = bsqrtd(bmuld(qbs2, (q - ps4)))
771785 let bq = bmuld(b, q)
772786 let qs = bmuld(q, sz)
773787 let top = ((-(sqr) + bq) + qs)
774788 let bot = (toBigInt(2) * bmuld(q, sz))
775789 let result = bdivd(top, bot)
776790 toInt(result)
777791 }
778792
779793
780794 func getSyncTerminalPrice (_terminalPrice,_qtAstR,_bsAstR) = {
781795 let _positionSize = totalPositionSize()
782796 if ((_positionSize == 0))
783797 then {
784798 let newQtAstW = divd(muld(_terminalPrice, _bsAstR), _qtAstR)
785799 $Tuple3(newQtAstW, DECIMAL_UNIT, 0)
786800 }
787801 else {
788802 let direction = (_positionSize > 0)
789803 let currentNetMarketValue = swapOutput(direction, abs(_positionSize), false)._1
790804 let newQtAstW = getQuoteAssetWeight(_bsAstR, _positionSize, _qtAstR, _terminalPrice)
791805 let newBsAstW = DECIMAL_UNIT
792806 let marginToVault = getPositionNotionalAndUnrealizedPnlByValues(_positionSize, currentNetMarketValue, _qtAstR, newQtAstW, _bsAstR, newBsAstW, PNL_OPTION_SPOT)._2
793807 $Tuple3(newQtAstW, newBsAstW, marginToVault)
794808 }
795809 }
796810
797811
798812 func getFunding () = {
799- let underlyingPrice = getOracleTwapPrice()
813+ let underlyingPrice = getOraclePrice()
800814 let spotTwapPrice = getTwapSpotPrice()
801815 let premium = (spotTwapPrice - underlyingPrice)
802- if (if ((totalShortPositionSize() == 0))
816+ if (if (if ((totalShortPositionSize() == 0))
803817 then true
804818 else (totalLongPositionSize() == 0))
819+ then true
820+ else isMarketClosed())
805821 then $Tuple2(0, 0)
806822 else if ((0 > premium))
807823 then {
808824 let shortPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
809825 let longPremiumFraction = divd(muld(shortPremiumFraction, totalShortPositionSize()), totalLongPositionSize())
810826 $Tuple2(shortPremiumFraction, longPremiumFraction)
811827 }
812828 else {
813829 let longPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
814830 let shortPremiumFraction = divd(muld(longPremiumFraction, totalLongPositionSize()), totalShortPositionSize())
815831 $Tuple2(shortPremiumFraction, longPremiumFraction)
816832 }
817833 }
818834
819835
820836 func getAdjustedFee (_artifactId,_baseFeeDiscount) = {
821837 let baseFeeRaw = fee()
822838 let baseFee = muld(baseFeeRaw, _baseFeeDiscount)
823- let $t03465535150 = if ((_artifactId != ""))
839+ let $t03492735422 = if ((_artifactId != ""))
824840 then {
825841 let artifactKind = strA(nftManagerAddress(), toCompositeKey(k_token_type, _artifactId))
826842 if ((artifactKind == FEE_REDUCTION_TOKEN_TYPE))
827843 then {
828844 let reduction = intA(nftManagerAddress(), toCompositeKey(k_token_param, _artifactId))
829845 let adjustedFee = muld(baseFee, reduction)
830846 $Tuple2(adjustedFee, true)
831847 }
832848 else throw("Invalid attached artifact")
833849 }
834850 else $Tuple2(baseFee, false)
835- let adjustedFee = $t03465535150._1
836- let burnArtifact = $t03465535150._2
851+ let adjustedFee = $t03492735422._1
852+ let burnArtifact = $t03492735422._2
837853 $Tuple2(adjustedFee, burnArtifact)
838854 }
839855
840856
841857 func isSameAssetOrNoPosition (_trader,_assetId) = {
842858 let oldPositionSize = getPosition(_trader)._1
843859 if ((oldPositionSize == 0))
844860 then true
845861 else (getPositionAsset(_trader) == _assetId)
846862 }
847863
848864
849865 func isSameAsset (_trader,_assetId) = (getPositionAsset(_trader) == _assetId)
850866
851867
852868 func getBorrowedByTraderInMarketKey (_amm,_assetId,_trader) = ((((((k_trader_market_asset_collateral + "_") + _amm) + "_") + _assetId) + "_") + _trader)
853869
854870
855871 func getBorrowedByTrader (_trader) = {
856872 let positionAsset = getPositionAsset(_trader)
857873 if ((positionAsset == toBase58String(quoteAsset())))
858874 then $Tuple2(0, positionAsset)
859875 else {
860876 let key = getBorrowedByTraderInMarketKey(toString(this), positionAsset, _trader)
861877 let borrow = valueOrElse(getInteger(collateralAddress(), key), 0)
862878 $Tuple2(borrow, positionAsset)
863879 }
864880 }
865881
866882
867883 func getForTraderWithArtifact (_trader,_artifactId) = {
868884 let doGetFeeDiscount = invoke(minerAddress(), "computeFeeDiscount", [_trader], nil)
869885 if ((doGetFeeDiscount == doGetFeeDiscount))
870886 then {
871887 let feeDiscount = match doGetFeeDiscount {
872888 case x: Int =>
873889 x
874890 case _ =>
875891 throw("Invalid computeFeeDiscount result")
876892 }
877- let $t03638136455 = getAdjustedFee(_artifactId, feeDiscount)
878- let adjustedFee = $t03638136455._1
879- let burnArtifact = $t03638136455._2
893+ let $t03665336727 = getAdjustedFee(_artifactId, feeDiscount)
894+ let adjustedFee = $t03665336727._1
895+ let burnArtifact = $t03665336727._2
880896 $Tuple2(adjustedFee, burnArtifact)
881897 }
882898 else throw("Strict value is not equal to itself.")
883899 }
884900
885901
886902 func getArtifactId (i) = {
887903 let artifactId = if ((size(i.payments) > 1))
888904 then toBase58String(valueOrErrorMessage(i.payments[1].assetId, "Invalid artifactId"))
889905 else ""
890906 artifactId
891907 }
892908
893909
894910 func distributeFee (_feeAmount) = {
895911 let feeToStakers = muld(_feeAmount, feeToStakersPercent())
896912 let feeToVault = (_feeAmount - feeToStakers)
897913 $Tuple2(feeToStakers, feeToVault)
898914 }
899915
900916
901917 func updateSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay) = [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)]
902918
903919
904920 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)]
905921
906922
907923 func updatePositionAsset (_address,_assetId) = [StringEntry(toCompositeKey(k_positionAsset, _address), _assetId)]
908924
909925
910926 func incrementPositionSequenceNumber (isNewPosition,_address) = if (isNewPosition)
911927 then {
912928 let currentSequence = lastSequence()
913929 [IntegerEntry(toCompositeKey(k_positionSequence, _address), (currentSequence + 1)), IntegerEntry(k_sequence, (currentSequence + 1))]
914930 }
915931 else nil
916932
917933
918934 func updatePosition (_address,_size,_margin,_openNotional,_latestCumulativePremiumFraction) = [IntegerEntry(toCompositeKey(k_positionSize, _address), _size), IntegerEntry(toCompositeKey(k_positionMargin, _address), _margin), IntegerEntry(toCompositeKey(k_positionOpenNotional, _address), _openNotional), IntegerEntry(toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, _address), _latestCumulativePremiumFraction)]
919935
920936
921937 func appendTwap (_price) = {
922938 let minuteId = ((lastBlock.timestamp / 1000) / 60)
923939 let previousMinuteId = valueOrElse(getInteger(this, k_lastMinuteId), 0)
924940 if ((previousMinuteId > minuteId))
925941 then throw("TWAP out-of-order")
926942 else {
927943 let lastMinuteId = if ((previousMinuteId == 0))
928944 then minuteId
929945 else previousMinuteId
930946 if ((minuteId > previousMinuteId))
931947 then {
932948 let prevCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(previousMinuteId))), 0)
933949 let prevPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(previousMinuteId))), _price)
934950 let lastCumulativePrice = (prevCumulativePrice + ((minuteId - lastMinuteId) * prevPrice))
935951 let list = pushToQueue(strToList(valueOrElse(getString(this, k_lastDataStr), "")), TWAP_INTERVAL, toString(minuteId))
936952 [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))]
937953 }
938954 else {
939955 let twapDataPreviousMinuteId = valueOrElse(getInteger(this, toCompositeKey(k_twapDataPreviousMinuteId, toString(minuteId))), 0)
940956 let prevCumulativePrice = valueOrElse(getInteger(this, toCompositeKey(k_twapDataLastCumulativePrice, toString(twapDataPreviousMinuteId))), 0)
941957 let prevPrice = valueOrElse(getInteger(this, toCompositeKey(k_twapDataLastPrice, toString(twapDataPreviousMinuteId))), _price)
942958 let lastCumulativePrice = (prevCumulativePrice + ((minuteId - twapDataPreviousMinuteId) * prevPrice))
943959 [IntegerEntry(toCompositeKey(k_twapDataLastCumulativePrice, toString(minuteId)), lastCumulativePrice), IntegerEntry(toCompositeKey(k_twapDataLastPrice, toString(minuteId)), _price)]
944960 }
945961 }
946962 }
947963
948964
949965 func updateAmmReserves (_qtAstR,_bsAstR) = [IntegerEntry(k_quoteAssetReserve, _qtAstR), IntegerEntry(k_baseAssetReserve, _bsAstR)]
950966
951967
952968 func updateAmmWeights (_qtAstW,_bsAstW) = [IntegerEntry(k_quoteAssetWeight, _qtAstW), IntegerEntry(k_baseAssetWeight, _bsAstW)]
953969
954970
955971 func updateAmm (_qtAstR,_bsAstR,_totalPositionSizeAfter,_openInterestNotional,_totalLongPositionSize,_totalShortPositionSize,_totalLongOpenNotional,_totalShortOpenNotional) = {
956972 let _qtAstW = qtAstW()
957973 let _bsAstW = bsAstW()
958974 if (((_totalLongPositionSize - _totalShortPositionSize) != _totalPositionSizeAfter))
959975 then throw(((((("Invalid AMM state data: " + toString(_totalLongPositionSize)) + " + ") + toString(_totalShortPositionSize)) + " != ") + toString(_totalPositionSizeAfter)))
960976 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))))
961977 }
962978
963979
964980 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))]
965981
966982
967983 func withdraw (_address,_amount) = {
968984 let balance = assetBalance(this, quoteAsset())
969985 if ((_amount > balance))
970986 then throw(((("Unable to withdraw " + toString(_amount)) + " from contract balance ") + toString(balance)))
971987 else [ScriptTransfer(_address, _amount, quoteAsset())]
972988 }
973989
974990
975991 func updateBalance (i) = if ((0 > i))
976992 then throw("Balance")
977993 else [IntegerEntry(k_balance, i)]
978994
979995
980996 func transferFee (i) = [ScriptTransfer(stakingAddress(), i, quoteAsset())]
981997
982998
983999 func doBurnArtifact (_burnArtifact,i) = if (_burnArtifact)
9841000 then [Burn(valueOrErrorMessage(i.payments[1].assetId, "Invalid artifact"), 1)]
9851001 else nil
9861002
9871003
9881004 @Callable(i)
9891005 func pause () = if ((i.caller != adminAddress()))
9901006 then throw("Invalid pause params")
9911007 else [BooleanEntry(k_paused, true)]
9921008
9931009
9941010
9951011 @Callable(i)
9961012 func unpause () = if ((i.caller != adminAddress()))
9971013 then throw("Invalid unpause params")
9981014 else [BooleanEntry(k_paused, false)]
9991015
10001016
10011017
10021018 @Callable(i)
10031019 func setCloseOnly () = if ((i.caller != adminAddress()))
10041020 then throw("Invalid setCloseOnly params")
10051021 else [BooleanEntry(k_closeOnly, true)]
10061022
10071023
10081024
10091025 @Callable(i)
10101026 func unsetCloseOnly () = if ((i.caller != adminAddress()))
10111027 then throw("Invalid unsetCloseOnly params")
10121028 else [BooleanEntry(k_closeOnly, false)]
10131029
10141030
10151031
10161032 @Callable(i)
10171033 func addLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
10181034 then true
10191035 else (0 >= _quoteAssetAmount))
10201036 then throw("Invalid addLiquidity params")
10211037 else {
10221038 let _qtAstR = qtAstR()
10231039 let _bsAstR = bsAstR()
10241040 let _qtAstW = qtAstW()
10251041 let _bsAstW = bsAstW()
10261042 let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
10271043 let qtAstRAfter = (_qtAstR + _quoteAssetAmount)
10281044 let baseAssetAmountToAdd = (divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR)
10291045 let bsAstRAfter = (_bsAstR + baseAssetAmountToAdd)
1030- let $t04547745632 = getSyncTerminalPrice(getOracleTwapPrice(), qtAstRAfter, bsAstRAfter)
1031- let newQuoteAssetWeight = $t04547745632._1
1032- let newBaseAssetWeight = $t04547745632._2
1033- let marginToVault = $t04547745632._3
1046+ let $t04574945900 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1047+ let newQuoteAssetWeight = $t04574945900._1
1048+ let newBaseAssetWeight = $t04574945900._2
1049+ let marginToVault = $t04574945900._3
10341050 let doExchangePnL = if ((marginToVault != 0))
10351051 then {
10361052 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
10371053 if ((doExchangePnL == doExchangePnL))
10381054 then nil
10391055 else throw("Strict value is not equal to itself.")
10401056 }
10411057 else nil
10421058 if ((doExchangePnL == doExchangePnL))
10431059 then (updateAmmReserves(qtAstRAfter, bsAstRAfter) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
10441060 else throw("Strict value is not equal to itself.")
10451061 }
10461062
10471063
10481064
10491065 @Callable(i)
10501066 func removeLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
10511067 then true
10521068 else (0 >= _quoteAssetAmount))
10531069 then throw("Invalid removeLiquidity params")
10541070 else {
10551071 let _qtAstR = qtAstR()
10561072 let _bsAstR = bsAstR()
10571073 let _qtAstW = qtAstW()
10581074 let _bsAstW = bsAstW()
10591075 let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
10601076 let baseAssetAmountToRemove = divd(_quoteAssetAmount, price)
10611077 let qtAstRAfter = (_qtAstR - _quoteAssetAmount)
10621078 let bsAstRAfter = (_bsAstR - baseAssetAmountToRemove)
10631079 updateAmmReserves(qtAstRAfter, bsAstRAfter)
10641080 }
10651081
10661082
10671083
10681084 @Callable(i)
10691085 func changeSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay) = if ((i.caller != adminAddress()))
10701086 then throw("Invalid changeSettings params")
10711087 else updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact, _partialLiquidationRatio, _maxPriceSpread, _maxOpenNotional, _feeToStakersPercent, _maxOracleDelay)
10721088
10731089
10741090
10751091 @Callable(i)
10761092 func initialize (_qtAstR,_bsAstR,_fundingPeriod,_initMarginRatio,_mmr,_liquidationFeeRatio,_fee,_oracle,_oracleKey,_oracleBlockKey,_coordinator,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay) = if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if ((0 >= _qtAstR))
10771093 then true
10781094 else (0 >= _bsAstR))
10791095 then true
10801096 else (0 >= _fundingPeriod))
10811097 then true
10821098 else (0 >= _initMarginRatio))
10831099 then true
10841100 else (0 >= _mmr))
10851101 then true
10861102 else (0 >= _liquidationFeeRatio))
10871103 then true
10881104 else (0 >= _fee))
10891105 then true
10901106 else (0 >= _spreadLimit))
10911107 then true
10921108 else (0 >= _maxPriceImpact))
10931109 then true
10941110 else (0 >= _partialLiquidationRatio))
10951111 then true
10961112 else (0 >= _maxPriceSpread))
10971113 then true
10981114 else (0 >= _maxOpenNotional))
10991115 then true
11001116 else (0 >= _feeToStakersPercent))
11011117 then true
11021118 else (_feeToStakersPercent > DECIMAL_UNIT))
11031119 then true
11041120 else (0 >= _maxOracleDelay))
11051121 then true
11061122 else initialized())
11071123 then throw("Invalid initialize parameters")
11081124 else ((((updateAmm(_qtAstR, _bsAstR, 0, 0, 0, 0, 0, 0) ++ updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact, _partialLiquidationRatio, _maxPriceSpread, _maxOpenNotional, _feeToStakersPercent, _maxOracleDelay)) ++ updateFunding((lastBlock.timestamp + _fundingPeriod), 0, 0, 0, 0)) ++ updateBalance(0)) ++ [BooleanEntry(k_initialized, true), StringEntry(k_ora, _oracle), StringEntry(k_ora_key, _oracleKey), StringEntry(k_ora_block_key, _oracleBlockKey), StringEntry(k_coordinatorAddress, _coordinator)])
11091125
11101126
11111127
11121128 @Callable(i)
11131129 func decreasePosition (_amount,_leverage,_minBaseAssetAmount) = {
11141130 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
11151131 if ((sync == sync))
11161132 then {
11171133 let _trader = getActualCaller(i)
1118- if (if (if (if (if ((0 >= _amount))
1134+ if (if (if (if (if (if ((0 >= _amount))
11191135 then true
11201136 else !(initialized()))
11211137 then true
11221138 else !(requireMoreMarginRatio(divd(DECIMAL_UNIT, _leverage), initMarginRatio(), true)))
11231139 then true
11241140 else !(requireOpenPosition(_trader)))
11251141 then true
11261142 else paused())
1143+ then true
1144+ else isMarketClosed())
11271145 then throw("Invalid decreasePosition parameters")
11281146 else {
1129- let $t04947549615 = getPosition(_trader)
1130- let oldPositionSize = $t04947549615._1
1131- let oldPositionMargin = $t04947549615._2
1132- let oldPositionOpenNotional = $t04947549615._3
1133- let oldPositionLstUpdCPF = $t04947549615._4
1147+ let $t04976749907 = getPosition(_trader)
1148+ let oldPositionSize = $t04976749907._1
1149+ let oldPositionMargin = $t04976749907._2
1150+ let oldPositionOpenNotional = $t04976749907._3
1151+ let oldPositionLstUpdCPF = $t04976749907._4
11341152 let _direction = if ((oldPositionSize > 0))
11351153 then DIR_SHORT
11361154 else DIR_LONG
11371155 let isAdd = (_direction == DIR_LONG)
11381156 let openNotional = muld(_amount, _leverage)
1139- let $t04978849892 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1140- let oldPositionNotional = $t04978849892._1
1141- let unrealizedPnl = $t04978849892._2
1142- let $t04989852556 = if ((oldPositionNotional > openNotional))
1157+ let $t05008050184 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1158+ let oldPositionNotional = $t05008050184._1
1159+ let unrealizedPnl = $t05008050184._2
1160+ let $t05019052848 = if ((oldPositionNotional > openNotional))
11431161 then {
1144- let $t05031350497 = swapInput(isAdd, openNotional)
1145- let exchangedPositionSize = $t05031350497._1
1146- let quoteAssetReserveAfter = $t05031350497._2
1147- let baseAssetReserveAfter = $t05031350497._3
1148- let totalPositionSizeAfter = $t05031350497._4
1162+ let $t05060550789 = swapInput(isAdd, openNotional)
1163+ let exchangedPositionSize = $t05060550789._1
1164+ let quoteAssetReserveAfter = $t05060550789._2
1165+ let baseAssetReserveAfter = $t05060550789._3
1166+ let totalPositionSizeAfter = $t05060550789._4
11491167 let exchangedPositionSizeAbs = abs(exchangedPositionSize)
11501168 if (if ((_minBaseAssetAmount != 0))
11511169 then (_minBaseAssetAmount > exchangedPositionSizeAbs)
11521170 else false)
11531171 then throw(((("Too little base asset exchanged, got " + toString(exchangedPositionSizeAbs)) + " expected ") + toString(_minBaseAssetAmount)))
11541172 else {
11551173 let realizedPnl = divd(muld(unrealizedPnl, exchangedPositionSizeAbs), abs(oldPositionSize))
1156- let $t05093451179 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1157- let remainMargin = $t05093451179._1
1158- let badDebt = $t05093451179._2
1159- let fundingPayment = $t05093451179._3
1174+ let $t05122651471 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1175+ let remainMargin = $t05122651471._1
1176+ let badDebt = $t05122651471._2
1177+ let fundingPayment = $t05122651471._3
11601178 let exchangedQuoteAssetAmount = openNotional
11611179 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
11621180 let remainOpenNotional = if ((oldPositionSize > 0))
11631181 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
11641182 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
11651183 let newPositionSize = (oldPositionSize + exchangedPositionSize)
11661184 $Tuple12(newPositionSize, remainMargin, abs(remainOpenNotional), latestCumulativePremiumFraction(newPositionSize), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, (openInterestNotional() - openNotional), (totalLongPositionSize() - (if ((newPositionSize > 0))
11671185 then abs(exchangedPositionSize)
11681186 else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
11691187 then abs(exchangedPositionSize)
11701188 else 0)), (openInterestLong() - (if ((newPositionSize > 0))
11711189 then openNotional
11721190 else 0)), (openInterestShort() - (if ((0 > newPositionSize))
11731191 then openNotional
11741192 else 0)))
11751193 }
11761194 }
11771195 else throw("Close position first")
1178- let newPositionSize = $t04989852556._1
1179- let newPositionRemainMargin = $t04989852556._2
1180- let newPositionOpenNotional = $t04989852556._3
1181- let newPositionLatestCPF = $t04989852556._4
1182- let baseAssetReserveAfter = $t04989852556._5
1183- let quoteAssetReserveAfter = $t04989852556._6
1184- let totalPositionSizeAfter = $t04989852556._7
1185- let openInterestNotionalAfter = $t04989852556._8
1186- let totalLongAfter = $t04989852556._9
1187- let totalShortAfter = $t04989852556._10
1188- let totalLongOpenInterestAfter = $t04989852556._11
1189- let totalShortOpenInterestAfter = $t04989852556._12
1196+ let newPositionSize = $t05019052848._1
1197+ let newPositionRemainMargin = $t05019052848._2
1198+ let newPositionOpenNotional = $t05019052848._3
1199+ let newPositionLatestCPF = $t05019052848._4
1200+ let baseAssetReserveAfter = $t05019052848._5
1201+ let quoteAssetReserveAfter = $t05019052848._6
1202+ let totalPositionSizeAfter = $t05019052848._7
1203+ let openInterestNotionalAfter = $t05019052848._8
1204+ let totalLongAfter = $t05019052848._9
1205+ let totalShortAfter = $t05019052848._10
1206+ let totalLongOpenInterestAfter = $t05019052848._11
1207+ let totalShortOpenInterestAfter = $t05019052848._12
11901208 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
11911209 if ((notifyNotional == notifyNotional))
11921210 then (updatePosition(_trader, newPositionSize, newPositionRemainMargin, newPositionOpenNotional, newPositionLatestCPF) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter))
11931211 else throw("Strict value is not equal to itself.")
11941212 }
11951213 }
11961214 else throw("Strict value is not equal to itself.")
11971215 }
11981216
11991217
12001218
12011219 @Callable(i)
12021220 func increasePosition (_direction,_leverage,_minBaseAssetAmount,_refLink) = {
12031221 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
12041222 if ((sync == sync))
12051223 then {
12061224 let _trader = getActualCaller(i)
12071225 let _rawAmount = i.payments[0].amount
12081226 let _assetId = i.payments[0].assetId
12091227 let _assetIdStr = toBase58String(value(_assetId))
12101228 let isQuoteAsset = (_assetId == quoteAsset())
12111229 let isCollateralAsset = isWhitelistAsset(_assetIdStr)
1212- if (if (if (if (if (if (if (if (if ((_direction != DIR_LONG))
1230+ if (if (if (if (if (if (if (if (if (if ((_direction != DIR_LONG))
12131231 then (_direction != DIR_SHORT)
12141232 else false)
12151233 then true
12161234 else (0 >= _rawAmount))
12171235 then true
12181236 else !(initialized()))
12191237 then true
12201238 else if (!(isQuoteAsset))
12211239 then !(isCollateralAsset)
12221240 else false)
12231241 then true
12241242 else !(isSameAssetOrNoPosition(_trader, _assetIdStr)))
12251243 then true
12261244 else !(requireMoreMarginRatio(divd(DECIMAL_UNIT, _leverage), initMarginRatio(), true)))
12271245 then true
12281246 else paused())
12291247 then true
12301248 else closeOnly())
1249+ then true
1250+ else isMarketClosed())
12311251 then throw("Invalid increasePosition parameters")
12321252 else {
1233- let $t05399454079 = getForTraderWithArtifact(_trader, getArtifactId(i))
1234- let adjustedFee = $t05399454079._1
1235- let burnArtifact = $t05399454079._2
1253+ let $t05431054395 = getForTraderWithArtifact(_trader, getArtifactId(i))
1254+ let adjustedFee = $t05431054395._1
1255+ let burnArtifact = $t05431054395._2
12361256 let rawFeeAmount = muld(_rawAmount, adjustedFee)
12371257 let _amount = (_rawAmount - rawFeeAmount)
12381258 let distributeFeeAmount = if (isCollateralAsset)
12391259 then {
12401260 let doBorrow = invoke(collateralAddress(), "borrow", [_trader], [AttachedPayment(_assetId, _amount)])
12411261 if ((doBorrow == doBorrow))
12421262 then {
12431263 let balanceBefore = assetBalance(this, quoteAsset())
12441264 if ((balanceBefore == balanceBefore))
12451265 then {
12461266 let doSwap = invoke(swapAddress(), "swap", [toBase58String(quoteAsset()), 0], [AttachedPayment(_assetId, rawFeeAmount)])
12471267 if ((doSwap == doSwap))
12481268 then {
12491269 let balanceAfter = assetBalance(this, quoteAsset())
12501270 if ((balanceAfter == balanceAfter))
12511271 then {
12521272 let exchangedAmount = (balanceAfter - balanceBefore)
12531273 if ((exchangedAmount == exchangedAmount))
12541274 then exchangedAmount
12551275 else throw("Strict value is not equal to itself.")
12561276 }
12571277 else throw("Strict value is not equal to itself.")
12581278 }
12591279 else throw("Strict value is not equal to itself.")
12601280 }
12611281 else throw("Strict value is not equal to itself.")
12621282 }
12631283 else throw("Strict value is not equal to itself.")
12641284 }
12651285 else rawFeeAmount
12661286 if ((distributeFeeAmount == distributeFeeAmount))
12671287 then {
12681288 let referrerFeeAny = invoke(referralAddress(), "acceptPaymentWithLink", [_trader, _refLink], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
12691289 if ((referrerFeeAny == referrerFeeAny))
12701290 then {
12711291 let referrerFee = match referrerFeeAny {
12721292 case x: Int =>
12731293 x
12741294 case _ =>
12751295 throw("Invalid referrerFee")
12761296 }
12771297 let feeAmount = (distributeFeeAmount - referrerFee)
1278- let $t05539555535 = getPosition(_trader)
1279- let oldPositionSize = $t05539555535._1
1280- let oldPositionMargin = $t05539555535._2
1281- let oldPositionOpenNotional = $t05539555535._3
1282- let oldPositionLstUpdCPF = $t05539555535._4
1298+ let $t05571155851 = getPosition(_trader)
1299+ let oldPositionSize = $t05571155851._1
1300+ let oldPositionMargin = $t05571155851._2
1301+ let oldPositionOpenNotional = $t05571155851._3
1302+ let oldPositionLstUpdCPF = $t05571155851._4
12831303 let isNewPosition = (oldPositionSize == 0)
12841304 let isSameDirection = if ((oldPositionSize > 0))
12851305 then (_direction == DIR_LONG)
12861306 else (_direction == DIR_SHORT)
12871307 let expandExisting = if (!(isNewPosition))
12881308 then isSameDirection
12891309 else false
12901310 let isAdd = (_direction == DIR_LONG)
1291- let $t05582458865 = if (if (isNewPosition)
1311+ let $t05614059181 = if (if (isNewPosition)
12921312 then true
12931313 else expandExisting)
12941314 then {
12951315 let openNotional = muld(_amount, _leverage)
1296- let $t05628656459 = swapInput(isAdd, openNotional)
1297- let amountBaseAssetBought = $t05628656459._1
1298- let quoteAssetReserveAfter = $t05628656459._2
1299- let baseAssetReserveAfter = $t05628656459._3
1300- let totalPositionSizeAfter = $t05628656459._4
1316+ let $t05660256775 = swapInput(isAdd, openNotional)
1317+ let amountBaseAssetBought = $t05660256775._1
1318+ let quoteAssetReserveAfter = $t05660256775._2
1319+ let baseAssetReserveAfter = $t05660256775._3
1320+ let totalPositionSizeAfter = $t05660256775._4
13011321 if (if ((_minBaseAssetAmount != 0))
13021322 then (_minBaseAssetAmount > abs(amountBaseAssetBought))
13031323 else false)
13041324 then throw(((("Limit error: " + toString(abs(amountBaseAssetBought))) + " < ") + toString(_minBaseAssetAmount)))
13051325 else {
13061326 let newPositionSize = (oldPositionSize + amountBaseAssetBought)
13071327 let totalLongOpenInterestAfter = (openInterestLong() + (if ((newPositionSize > 0))
13081328 then openNotional
13091329 else 0))
13101330 let totalShortOpenInterestAfter = (openInterestShort() + (if ((0 > newPositionSize))
13111331 then openNotional
13121332 else 0))
13131333 let increaseMarginRequirement = divd(openNotional, _leverage)
1314- let $t05706757306 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, increaseMarginRequirement)
1315- let remainMargin = $t05706757306._1
1316- let x1 = $t05706757306._2
1317- let x2 = $t05706757306._3
1334+ let $t05738357622 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, increaseMarginRequirement)
1335+ let remainMargin = $t05738357622._1
1336+ let x1 = $t05738357622._2
1337+ let x2 = $t05738357622._3
13181338 if (!(requireNotOverSpreadLimit(quoteAssetReserveAfter, baseAssetReserveAfter)))
13191339 then throw("Over max spread limit")
13201340 else if (!(requireNotOverMaxOpenNotional(totalLongOpenInterestAfter, totalShortOpenInterestAfter)))
13211341 then throw("Over max open notional")
13221342 else $Tuple12(newPositionSize, remainMargin, (oldPositionOpenNotional + openNotional), latestCumulativePremiumFraction(newPositionSize), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, (openInterestNotional() + openNotional), (totalLongPositionSize() + (if ((newPositionSize > 0))
13231343 then abs(amountBaseAssetBought)
13241344 else 0)), (totalShortPositionSize() + (if ((0 > newPositionSize))
13251345 then abs(amountBaseAssetBought)
13261346 else 0)), totalLongOpenInterestAfter, totalShortOpenInterestAfter)
13271347 }
13281348 }
13291349 else {
13301350 let openNotional = muld(_amount, _leverage)
1331- let $t05856558681 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1332- let oldPositionNotional = $t05856558681._1
1333- let unrealizedPnl = $t05856558681._2
1351+ let $t05888158997 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1352+ let oldPositionNotional = $t05888158997._1
1353+ let unrealizedPnl = $t05888158997._2
13341354 if ((oldPositionNotional > openNotional))
13351355 then throw("Use decreasePosition to decrease position size")
13361356 else throw("Close position first")
13371357 }
1338- let newPositionSize = $t05582458865._1
1339- let newPositionRemainMargin = $t05582458865._2
1340- let newPositionOpenNotional = $t05582458865._3
1341- let newPositionLatestCPF = $t05582458865._4
1342- let baseAssetReserveAfter = $t05582458865._5
1343- let quoteAssetReserveAfter = $t05582458865._6
1344- let totalPositionSizeAfter = $t05582458865._7
1345- let openInterestNotionalAfter = $t05582458865._8
1346- let totalLongAfter = $t05582458865._9
1347- let totalShortAfter = $t05582458865._10
1348- let totalLongOpenInterestAfter = $t05582458865._11
1349- let totalShortOpenInterestAfter = $t05582458865._12
1350- let $t05887158928 = distributeFee(feeAmount)
1351- let feeToStakers = $t05887158928._1
1352- let feeToVault = $t05887158928._2
1358+ let newPositionSize = $t05614059181._1
1359+ let newPositionRemainMargin = $t05614059181._2
1360+ let newPositionOpenNotional = $t05614059181._3
1361+ let newPositionLatestCPF = $t05614059181._4
1362+ let baseAssetReserveAfter = $t05614059181._5
1363+ let quoteAssetReserveAfter = $t05614059181._6
1364+ let totalPositionSizeAfter = $t05614059181._7
1365+ let openInterestNotionalAfter = $t05614059181._8
1366+ let totalLongAfter = $t05614059181._9
1367+ let totalShortAfter = $t05614059181._10
1368+ let totalLongOpenInterestAfter = $t05614059181._11
1369+ let totalShortOpenInterestAfter = $t05614059181._12
1370+ let $t05918759244 = distributeFee(feeAmount)
1371+ let feeToStakers = $t05918759244._1
1372+ let feeToVault = $t05918759244._2
13531373 let stake = if (isQuoteAsset)
13541374 then {
13551375 let stake = invoke(vaultAddress(), "addLocked", [false], [AttachedPayment(quoteAsset(), _amount)])
13561376 if ((stake == stake))
13571377 then nil
13581378 else throw("Strict value is not equal to itself.")
13591379 }
13601380 else nil
13611381 if ((stake == stake))
13621382 then {
13631383 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
13641384 if ((depositInsurance == depositInsurance))
13651385 then {
13661386 let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, feeAmount], nil)
13671387 if ((notifyFee == notifyFee))
13681388 then {
13691389 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
13701390 if ((notifyNotional == notifyNotional))
13711391 then ((((((updatePosition(_trader, newPositionSize, newPositionRemainMargin, newPositionOpenNotional, newPositionLatestCPF) ++ incrementPositionSequenceNumber(isNewPosition, _trader)) ++ updatePositionAsset(_trader, _assetIdStr)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ transferFee(feeToStakers)) ++ updateBalance((cbalance() + _amount))) ++ doBurnArtifact(burnArtifact, i))
13721392 else throw("Strict value is not equal to itself.")
13731393 }
13741394 else throw("Strict value is not equal to itself.")
13751395 }
13761396 else throw("Strict value is not equal to itself.")
13771397 }
13781398 else throw("Strict value is not equal to itself.")
13791399 }
13801400 else throw("Strict value is not equal to itself.")
13811401 }
13821402 else throw("Strict value is not equal to itself.")
13831403 }
13841404 }
13851405 else throw("Strict value is not equal to itself.")
13861406 }
13871407
13881408
13891409
13901410 @Callable(i)
13911411 func addMargin () = {
13921412 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
13931413 if ((sync == sync))
13941414 then {
13951415 let _trader = toString(i.caller)
13961416 let _rawAmount = i.payments[0].amount
13971417 let _assetId = i.payments[0].assetId
13981418 let _assetIdStr = toBase58String(value(_assetId))
13991419 let isQuoteAsset = (_assetId == quoteAsset())
14001420 let isCollateralAsset = isWhitelistAsset(_assetIdStr)
1401- if (if (if (if (if (if (if (!(isQuoteAsset))
1421+ if (if (if (if (if (if (if (if (!(isQuoteAsset))
14021422 then !(isCollateralAsset)
14031423 else false)
14041424 then true
14051425 else !(requireOpenPosition(toString(i.caller))))
14061426 then true
14071427 else !(isSameAsset(_trader, _assetIdStr)))
14081428 then true
14091429 else !(initialized()))
14101430 then true
14111431 else paused())
14121432 then true
14131433 else closeOnly())
1434+ then true
1435+ else isMarketClosed())
14141436 then throw("Invalid addMargin parameters")
14151437 else {
1416- let $t06087660961 = getForTraderWithArtifact(_trader, getArtifactId(i))
1417- let adjustedFee = $t06087660961._1
1418- let burnArtifact = $t06087660961._2
1438+ let $t06121661301 = getForTraderWithArtifact(_trader, getArtifactId(i))
1439+ let adjustedFee = $t06121661301._1
1440+ let burnArtifact = $t06121661301._2
14191441 let rawFeeAmount = muld(_rawAmount, adjustedFee)
14201442 let _amount = (_rawAmount - rawFeeAmount)
14211443 let distributeFeeAmount = if (isCollateralAsset)
14221444 then {
14231445 let doBorrow = invoke(collateralAddress(), "borrow", [_trader], [AttachedPayment(_assetId, _amount)])
14241446 if ((doBorrow == doBorrow))
14251447 then {
14261448 let balanceBefore = assetBalance(this, quoteAsset())
14271449 if ((balanceBefore == balanceBefore))
14281450 then {
14291451 let doSwap = invoke(swapAddress(), "swap", [toBase58String(quoteAsset()), 0], [AttachedPayment(_assetId, rawFeeAmount)])
14301452 if ((doSwap == doSwap))
14311453 then {
14321454 let balanceAfter = assetBalance(this, quoteAsset())
14331455 if ((balanceAfter == balanceAfter))
14341456 then {
14351457 let exchangedAmount = (balanceAfter - balanceBefore)
14361458 if ((exchangedAmount == exchangedAmount))
14371459 then exchangedAmount
14381460 else throw("Strict value is not equal to itself.")
14391461 }
14401462 else throw("Strict value is not equal to itself.")
14411463 }
14421464 else throw("Strict value is not equal to itself.")
14431465 }
14441466 else throw("Strict value is not equal to itself.")
14451467 }
14461468 else throw("Strict value is not equal to itself.")
14471469 }
14481470 else rawFeeAmount
14491471 if ((distributeFeeAmount == distributeFeeAmount))
14501472 then {
14511473 let referrerFeeAny = invoke(referralAddress(), "acceptPayment", [_trader], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
14521474 if ((referrerFeeAny == referrerFeeAny))
14531475 then {
14541476 let referrerFee = match referrerFeeAny {
14551477 case x: Int =>
14561478 x
14571479 case _ =>
14581480 throw("Invalid referrerFee")
14591481 }
14601482 let feeAmount = (distributeFeeAmount - referrerFee)
1461- let $t06226062400 = getPosition(_trader)
1462- let oldPositionSize = $t06226062400._1
1463- let oldPositionMargin = $t06226062400._2
1464- let oldPositionOpenNotional = $t06226062400._3
1465- let oldPositionLstUpdCPF = $t06226062400._4
1466- let $t06240662463 = distributeFee(feeAmount)
1467- let feeToStakers = $t06240662463._1
1468- let feeToVault = $t06240662463._2
1483+ let $t06260062740 = getPosition(_trader)
1484+ let oldPositionSize = $t06260062740._1
1485+ let oldPositionMargin = $t06260062740._2
1486+ let oldPositionOpenNotional = $t06260062740._3
1487+ let oldPositionLstUpdCPF = $t06260062740._4
1488+ let $t06274662803 = distributeFee(feeAmount)
1489+ let feeToStakers = $t06274662803._1
1490+ let feeToVault = $t06274662803._2
14691491 let stake = if (isQuoteAsset)
14701492 then {
14711493 let stake = invoke(vaultAddress(), "addLocked", [false], [AttachedPayment(quoteAsset(), _amount)])
14721494 if ((stake == stake))
14731495 then nil
14741496 else throw("Strict value is not equal to itself.")
14751497 }
14761498 else nil
14771499 if ((stake == stake))
14781500 then {
14791501 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
14801502 if ((depositInsurance == depositInsurance))
14811503 then {
14821504 let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, feeAmount], nil)
14831505 if ((notifyFee == notifyFee))
14841506 then (((updatePosition(_trader, oldPositionSize, (oldPositionMargin + _amount), oldPositionOpenNotional, oldPositionLstUpdCPF) ++ transferFee(feeToStakers)) ++ updateBalance((cbalance() + _amount))) ++ doBurnArtifact(burnArtifact, i))
14851507 else throw("Strict value is not equal to itself.")
14861508 }
14871509 else throw("Strict value is not equal to itself.")
14881510 }
14891511 else throw("Strict value is not equal to itself.")
14901512 }
14911513 else throw("Strict value is not equal to itself.")
14921514 }
14931515 else throw("Strict value is not equal to itself.")
14941516 }
14951517 }
14961518 else throw("Strict value is not equal to itself.")
14971519 }
14981520
14991521
15001522
15011523 @Callable(i)
15021524 func removeMargin (_amount) = {
15031525 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
15041526 if ((sync == sync))
15051527 then {
15061528 let _trader = toString(i.caller)
1507- if (if (if (if ((0 >= _amount))
1529+ if (if (if (if (if ((0 >= _amount))
15081530 then true
15091531 else !(requireOpenPosition(_trader)))
15101532 then true
15111533 else !(initialized()))
15121534 then true
15131535 else paused())
1536+ then true
1537+ else isMarketClosed())
15141538 then throw("Invalid removeMargin parameters")
15151539 else {
1516- let $t06357563715 = getPosition(_trader)
1517- let oldPositionSize = $t06357563715._1
1518- let oldPositionMargin = $t06357563715._2
1519- let oldPositionOpenNotional = $t06357563715._3
1520- let oldPositionLstUpdCPF = $t06357563715._4
1540+ let $t06393964079 = getPosition(_trader)
1541+ let oldPositionSize = $t06393964079._1
1542+ let oldPositionMargin = $t06393964079._2
1543+ let oldPositionOpenNotional = $t06393964079._3
1544+ let oldPositionLstUpdCPF = $t06393964079._4
15211545 let marginDelta = -(_amount)
1522- let $t06375263931 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, marginDelta)
1523- let remainMargin = $t06375263931._1
1524- let badDebt = $t06375263931._2
1546+ let $t06411664295 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, marginDelta)
1547+ let remainMargin = $t06411664295._1
1548+ let badDebt = $t06411664295._2
15251549 if ((badDebt != 0))
15261550 then throw("Invalid removed margin amount")
15271551 else {
15281552 let marginRatio = calcMarginRatio(remainMargin, badDebt, oldPositionOpenNotional)
15291553 if (!(requireMoreMarginRatio(marginRatio, initMarginRatio(), true)))
15301554 then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
15311555 else {
15321556 let quoteAssetStr = toBase58String(quoteAsset())
1533- let $t06437564429 = getBorrowedByTrader(_trader)
1534- let borrowed = $t06437564429._1
1535- let assetId = $t06437564429._2
1557+ let $t06473964793 = getBorrowedByTrader(_trader)
1558+ let borrowed = $t06473964793._1
1559+ let assetId = $t06473964793._2
15361560 let toRepay = if ((_amount > borrowed))
15371561 then borrowed
15381562 else _amount
15391563 let toWithdraw = if ((borrowed > _amount))
15401564 then 0
15411565 else (_amount - borrowed)
15421566 let finalBorrow = (borrowed - toRepay)
15431567 let switchPositionToQuote = if ((finalBorrow > 0))
15441568 then nil
15451569 else updatePositionAsset(_trader, quoteAssetStr)
15461570 let doSanityCheck = if (((toRepay + toWithdraw) != _amount))
15471571 then throw(((((("toRepay=" + toString(toRepay)) + " + toWithdraw=") + toString(toWithdraw)) + " != ") + toString(_amount)))
15481572 else nil
15491573 if ((doSanityCheck == doSanityCheck))
15501574 then {
15511575 let doUnstake = if ((toWithdraw > 0))
15521576 then {
15531577 let doUnstake = invoke(vaultAddress(), "withdrawLocked", [toWithdraw], nil)
15541578 if ((doUnstake == doUnstake))
15551579 then nil
15561580 else throw("Strict value is not equal to itself.")
15571581 }
15581582 else nil
15591583 if ((doUnstake == doUnstake))
15601584 then {
15611585 let returnCollateralAction = if ((toRepay > 0))
15621586 then {
15631587 let doRepay = invoke(collateralAddress(), "repay", [_trader, toRepay, assetId], nil)
15641588 if ((doRepay == doRepay))
15651589 then [ScriptTransfer(i.caller, toRepay, fromBase58String(assetId))]
15661590 else throw("Strict value is not equal to itself.")
15671591 }
15681592 else nil
15691593 if ((returnCollateralAction == returnCollateralAction))
15701594 then ((((updatePosition(_trader, oldPositionSize, remainMargin, oldPositionOpenNotional, latestCumulativePremiumFraction(oldPositionSize)) ++ (if ((toWithdraw > 0))
15711595 then withdraw(i.caller, toWithdraw)
15721596 else nil)) ++ updateBalance((cbalance() - _amount))) ++ switchPositionToQuote) ++ returnCollateralAction)
15731597 else throw("Strict value is not equal to itself.")
15741598 }
15751599 else throw("Strict value is not equal to itself.")
15761600 }
15771601 else throw("Strict value is not equal to itself.")
15781602 }
15791603 }
15801604 }
15811605 }
15821606 else throw("Strict value is not equal to itself.")
15831607 }
15841608
15851609
15861610
15871611 @Callable(i)
15881612 func closePosition (_size,_minQuoteAssetAmount) = {
15891613 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
15901614 if ((sync == sync))
15911615 then {
15921616 let _trader = getActualCaller(i)
15931617 let _traderAddress = valueOrErrorMessage(addressFromString(_trader), "Invalid caller")
1594- if (if (if (if (if (!(requireOpenPosition(_trader)))
1618+ if (if (if (if (if (if (!(requireOpenPosition(_trader)))
15951619 then true
15961620 else !(initialized()))
15971621 then true
15981622 else paused())
15991623 then true
16001624 else (0 >= _size))
16011625 then true
16021626 else (0 > _minQuoteAssetAmount))
1627+ then true
1628+ else isMarketClosed())
16031629 then throw("Invalid closePosition parameters")
16041630 else {
1605- let $t06658766727 = getPosition(_trader)
1606- let oldPositionSize = $t06658766727._1
1607- let oldPositionMargin = $t06658766727._2
1608- let oldPositionOpenNotional = $t06658766727._3
1609- let oldPositionLstUpdCPF = $t06658766727._4
1610- let $t06673371170 = if ((abs(oldPositionSize) > _size))
1631+ let $t06697767117 = getPosition(_trader)
1632+ let oldPositionSize = $t06697767117._1
1633+ let oldPositionMargin = $t06697767117._2
1634+ let oldPositionOpenNotional = $t06697767117._3
1635+ let oldPositionLstUpdCPF = $t06697767117._4
1636+ let $t06712371769 = if ((abs(oldPositionSize) > _size))
16111637 then {
16121638 let _direction = if ((oldPositionSize > 0))
16131639 then DIR_SHORT
16141640 else DIR_LONG
16151641 let isAdd = (_direction == DIR_LONG)
1616- let $t06732467546 = swapOutput((oldPositionSize > 0), _size, true)
1617- let exchangedQuoteAssetAmount = $t06732467546._1
1618- let quoteAssetReserveAfter = $t06732467546._2
1619- let baseAssetReserveAfter = $t06732467546._3
1620- let totalPositionSizeAfter = $t06732467546._4
1642+ let $t06771467936 = swapOutput((oldPositionSize > 0), _size, true)
1643+ let exchangedQuoteAssetAmount = $t06771467936._1
1644+ let quoteAssetReserveAfter = $t06771467936._2
1645+ let baseAssetReserveAfter = $t06771467936._3
1646+ let totalPositionSizeAfter = $t06771467936._4
16211647 let exchangedPositionSize = if ((oldPositionSize > 0))
16221648 then -(_size)
16231649 else _size
1624- let $t06763767791 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1625- let oldPositionNotional = $t06763767791._1
1626- let unrealizedPnl = $t06763767791._2
1650+ let $t06802768181 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1651+ let oldPositionNotional = $t06802768181._1
1652+ let unrealizedPnl = $t06802768181._2
16271653 let mr = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
16281654 let realizedRatio = divd(abs(exchangedPositionSize), abs(oldPositionSize))
16291655 let realizedPnl = muld(unrealizedPnl, realizedRatio)
1630- let $t06807068308 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1631- let remainMargin = $t06807068308._1
1632- let positionBadDebt = $t06807068308._2
1633- let fundingPayment = $t06807068308._3
1656+ let remainMarginBefore = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, unrealizedPnl)._1
1657+ let $t06868268920 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1658+ let remainMargin = $t06868268920._1
1659+ let positionBadDebt = $t06868268920._2
1660+ let fundingPayment = $t06868268920._3
16341661 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
16351662 let remainOpenNotional = if ((oldPositionSize > 0))
16361663 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
16371664 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
16381665 let newPositionOpenNotional = abs(remainOpenNotional)
16391666 let newPositionMargin = muld(newPositionOpenNotional, mr)
16401667 let newPositionSize = (oldPositionSize + exchangedPositionSize)
16411668 let newPositionLstUpdCPF = latestCumulativePremiumFraction(newPositionSize)
16421669 let openInterestNotionalAfter = (openInterestNotional() - exchangedQuoteAssetAmount)
16431670 if (if ((_minQuoteAssetAmount != 0))
16441671 then (_minQuoteAssetAmount > exchangedQuoteAssetAmount)
16451672 else false)
16461673 then throw(((("Limit error: " + toString(exchangedQuoteAssetAmount)) + " < ") + toString(_minQuoteAssetAmount)))
1647- else $Tuple15(newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, positionBadDebt, realizedPnl, (abs((remainMargin - newPositionMargin)) + realizedPnl), quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, (totalLongPositionSize() - (if ((newPositionSize > 0))
1674+ else $Tuple15(newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, positionBadDebt, realizedPnl, (remainMarginBefore - newPositionMargin), quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, (totalLongPositionSize() - (if ((newPositionSize > 0))
16481675 then abs(exchangedPositionSize)
16491676 else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
16501677 then abs(exchangedPositionSize)
16511678 else 0)), (openInterestLong() - (if ((newPositionSize > 0))
16521679 then exchangedQuoteAssetAmount
16531680 else 0)), (openInterestShort() - (if ((0 > newPositionSize))
16541681 then exchangedQuoteAssetAmount
16551682 else 0)))
16561683 }
16571684 else if ((_size > abs(oldPositionSize)))
16581685 then throw("Invalid closePosition parameters")
16591686 else {
1660- let $t07011170530 = internalClosePosition(_trader, true)
1661- let exchangedQuoteAssetAmount = $t07011170530._1
1662- let positionBadDebt = $t07011170530._2
1663- let realizedPnl = $t07011170530._3
1664- let marginToVault = $t07011170530._4
1665- let quoteAssetReserveAfter = $t07011170530._5
1666- let baseAssetReserveAfter = $t07011170530._6
1667- let totalPositionSizeAfter = $t07011170530._7
1668- let openInterestNotionalAfter = $t07011170530._8
1669- let x2 = $t07011170530._9
1670- let totalLongAfter = $t07011170530._10
1671- let totalShortAfter = $t07011170530._11
1672- let totalLongOpenInterestAfter = $t07011170530._12
1673- let totalShortOpenInterestAfter = $t07011170530._13
1687+ let $t07071071129 = internalClosePosition(_trader, true)
1688+ let exchangedQuoteAssetAmount = $t07071071129._1
1689+ let positionBadDebt = $t07071071129._2
1690+ let realizedPnl = $t07071071129._3
1691+ let marginToVault = $t07071071129._4
1692+ let quoteAssetReserveAfter = $t07071071129._5
1693+ let baseAssetReserveAfter = $t07071071129._6
1694+ let totalPositionSizeAfter = $t07071071129._7
1695+ let openInterestNotionalAfter = $t07071071129._8
1696+ let x2 = $t07071071129._9
1697+ let totalLongAfter = $t07071071129._10
1698+ let totalShortAfter = $t07071071129._11
1699+ let totalLongOpenInterestAfter = $t07071071129._12
1700+ let totalShortOpenInterestAfter = $t07071071129._13
16741701 if (if ((_minQuoteAssetAmount != 0))
16751702 then (_minQuoteAssetAmount > exchangedQuoteAssetAmount)
16761703 else false)
16771704 then throw(((("Limit error: " + toString(exchangedQuoteAssetAmount)) + " < ") + toString(_minQuoteAssetAmount)))
16781705 else $Tuple15(0, 0, 0, 0, positionBadDebt, realizedPnl, marginToVault, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)
16791706 }
1680- let newPositionSize = $t06673371170._1
1681- let newPositionMargin = $t06673371170._2
1682- let newPositionOpenNotional = $t06673371170._3
1683- let newPositionLstUpdCPF = $t06673371170._4
1684- let positionBadDebt = $t06673371170._5
1685- let realizedPnl = $t06673371170._6
1686- let marginToVault = $t06673371170._7
1687- let quoteAssetReserveAfter = $t06673371170._8
1688- let baseAssetReserveAfter = $t06673371170._9
1689- let totalPositionSizeAfter = $t06673371170._10
1690- let openInterestNotionalAfter = $t06673371170._11
1691- let totalLongAfter = $t06673371170._12
1692- let totalShortAfter = $t06673371170._13
1693- let totalLongOpenInterestAfter = $t06673371170._14
1694- let totalShortOpenInterestAfter = $t06673371170._15
1707+ let newPositionSize = $t06712371769._1
1708+ let newPositionMargin = $t06712371769._2
1709+ let newPositionOpenNotional = $t06712371769._3
1710+ let newPositionLstUpdCPF = $t06712371769._4
1711+ let positionBadDebt = $t06712371769._5
1712+ let realizedPnl = $t06712371769._6
1713+ let marginToVault = $t06712371769._7
1714+ let quoteAssetReserveAfter = $t06712371769._8
1715+ let baseAssetReserveAfter = $t06712371769._9
1716+ let totalPositionSizeAfter = $t06712371769._10
1717+ let openInterestNotionalAfter = $t06712371769._11
1718+ let totalLongAfter = $t06712371769._12
1719+ let totalShortAfter = $t06712371769._13
1720+ let totalLongOpenInterestAfter = $t06712371769._14
1721+ let totalShortOpenInterestAfter = $t06712371769._15
16951722 if ((positionBadDebt > 0))
16961723 then throw("Unable to close position with bad debt")
16971724 else {
16981725 let withdrawAmount = abs(marginToVault)
16991726 let ammBalance = (cbalance() - withdrawAmount)
1700- let $t07137971586 = if ((0 > ammBalance))
1727+ let $t07197872185 = if ((0 > ammBalance))
17011728 then $Tuple2(0, abs(ammBalance))
17021729 else $Tuple2(ammBalance, 0)
1703- let ammNewBalance = $t07137971586._1
1704- let x11 = $t07137971586._2
1705- let $t07159371647 = getBorrowedByTrader(_trader)
1706- let borrowed = $t07159371647._1
1707- let assetId = $t07159371647._2
1708- let $t07166272521 = if ((borrowed > 0))
1730+ let ammNewBalance = $t07197872185._1
1731+ let x11 = $t07197872185._2
1732+ let $t07219272246 = getBorrowedByTrader(_trader)
1733+ let borrowed = $t07219272246._1
1734+ let assetId = $t07219272246._2
1735+ let $t07226173120 = if ((borrowed > 0))
17091736 then if ((withdrawAmount >= borrowed))
17101737 then {
17111738 let doRepay = invoke(collateralAddress(), "repay", [_trader, borrowed, assetId], nil)
17121739 if ((doRepay == doRepay))
17131740 then $Tuple2([ScriptTransfer(_traderAddress, borrowed, fromBase58String(assetId))], (withdrawAmount - borrowed))
17141741 else throw("Strict value is not equal to itself.")
17151742 }
17161743 else {
17171744 let realizeAndClose = invoke(collateralAddress(), "realizePartiallyAndClose", [_trader, withdrawAmount, assetId], nil)
17181745 if ((realizeAndClose == realizeAndClose))
17191746 then $Tuple2([ScriptTransfer(_traderAddress, withdrawAmount, fromBase58String(assetId))], 0)
17201747 else throw("Strict value is not equal to itself.")
17211748 }
17221749 else $Tuple2(nil, withdrawAmount)
1723- if (($t07166272521 == $t07166272521))
1750+ if (($t07226173120 == $t07226173120))
17241751 then {
1725- let quoteWithdrawAmount = $t07166272521._2
1726- let sendCollateralAction = $t07166272521._1
1752+ let quoteWithdrawAmount = $t07226173120._2
1753+ let sendCollateralAction = $t07226173120._1
17271754 let unstake = if ((quoteWithdrawAmount > 0))
17281755 then {
17291756 let unstake = invoke(vaultAddress(), "withdrawLocked", [quoteWithdrawAmount], nil)
17301757 if ((unstake == unstake))
17311758 then nil
17321759 else throw("Strict value is not equal to itself.")
17331760 }
17341761 else nil
17351762 if ((unstake == unstake))
17361763 then {
17371764 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, 0], nil)
17381765 if ((notifyNotional == notifyNotional))
17391766 then (((((if ((newPositionSize == 0))
17401767 then deletePosition(_trader)
17411768 else updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ (if ((quoteWithdrawAmount > 0))
17421769 then withdraw(_traderAddress, quoteWithdrawAmount)
17431770 else nil)) ++ updateBalance(ammNewBalance)) ++ sendCollateralAction)
17441771 else throw("Strict value is not equal to itself.")
17451772 }
17461773 else throw("Strict value is not equal to itself.")
17471774 }
17481775 else throw("Strict value is not equal to itself.")
17491776 }
17501777 }
17511778 }
17521779 else throw("Strict value is not equal to itself.")
17531780 }
17541781
17551782
17561783
17571784 @Callable(i)
17581785 func liquidate (_trader) = {
17591786 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
17601787 if ((sync == sync))
17611788 then {
17621789 let spotMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
17631790 let marginRatio = if (isOverFluctuationLimit())
17641791 then {
17651792 let oracleMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_ORACLE)
17661793 vmax(spotMarginRatio, oracleMarginRatio)
17671794 }
17681795 else spotMarginRatio
1769- if (if (if (if (!(requireMoreMarginRatio(marginRatio, maintenanceMarginRatio(), false)))
1796+ if (if (if (if (if (!(requireMoreMarginRatio(marginRatio, maintenanceMarginRatio(), false)))
17701797 then true
17711798 else !(requireOpenPosition(_trader)))
17721799 then true
17731800 else !(initialized()))
17741801 then true
17751802 else paused())
1803+ then true
1804+ else isMarketClosed())
17761805 then throw("Unable to liquidate")
17771806 else if (if (if ((spotMarginRatio > liquidationFeeRatio()))
17781807 then (partialLiquidationRatio() > 0)
17791808 else false)
17801809 then (DECIMAL_UNIT > partialLiquidationRatio())
17811810 else false)
17821811 then {
1783- let $t07481874968 = getPosition(_trader)
1784- let oldPositionSize = $t07481874968._1
1785- let oldPositionMargin = $t07481874968._2
1786- let oldPositionOpenNotional = $t07481874968._3
1787- let oldPositionLstUpdCPF = $t07481874968._4
1812+ let $t07544175591 = getPosition(_trader)
1813+ let oldPositionSize = $t07544175591._1
1814+ let oldPositionMargin = $t07544175591._2
1815+ let oldPositionOpenNotional = $t07544175591._3
1816+ let oldPositionLstUpdCPF = $t07544175591._4
17881817 let _direction = if ((oldPositionSize > 0))
17891818 then DIR_SHORT
17901819 else DIR_LONG
17911820 let isAdd = (_direction == DIR_LONG)
17921821 let exchangedQuoteAssetAmount = getPartialLiquidationAmount(_trader, oldPositionSize)
1793- let $t07519375297 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1794- let oldPositionNotional = $t07519375297._1
1795- let unrealizedPnl = $t07519375297._2
1796- let $t07530575492 = swapInput(isAdd, exchangedQuoteAssetAmount)
1797- let exchangedPositionSize = $t07530575492._1
1798- let quoteAssetReserveAfter = $t07530575492._2
1799- let baseAssetReserveAfter = $t07530575492._3
1800- let totalPositionSizeAfter = $t07530575492._4
1822+ let $t07581675920 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1823+ let oldPositionNotional = $t07581675920._1
1824+ let unrealizedPnl = $t07581675920._2
1825+ let $t07592876115 = swapInput(isAdd, exchangedQuoteAssetAmount)
1826+ let exchangedPositionSize = $t07592876115._1
1827+ let quoteAssetReserveAfter = $t07592876115._2
1828+ let baseAssetReserveAfter = $t07592876115._3
1829+ let totalPositionSizeAfter = $t07592876115._4
18011830 let liquidationRatio = divd(abs(exchangedPositionSize), abs(oldPositionSize))
18021831 let realizedPnl = muld(unrealizedPnl, liquidationRatio)
1803- let $t07578176014 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1804- let remainMargin = $t07578176014._1
1805- let badDebt = $t07578176014._2
1806- let fundingPayment = $t07578176014._3
1832+ let $t07640476637 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1833+ let remainMargin = $t07640476637._1
1834+ let badDebt = $t07640476637._2
1835+ let fundingPayment = $t07640476637._3
18071836 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
18081837 let remainOpenNotional = if ((oldPositionSize > 0))
18091838 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
18101839 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
18111840 let liquidationPenalty = muld(exchangedQuoteAssetAmount, liquidationFeeRatio())
18121841 let feeToLiquidator = (liquidationPenalty / 2)
18131842 let feeToVault = (liquidationPenalty - feeToLiquidator)
18141843 let newPositionMargin = (remainMargin - liquidationPenalty)
18151844 let newPositionSize = (oldPositionSize + exchangedPositionSize)
18161845 let newPositionOpenNotional = abs(remainOpenNotional)
18171846 let newPositionLstUpdCPF = latestCumulativePremiumFraction(newPositionSize)
18181847 let openInterestNotionalAfter = (openInterestNotional() - exchangedQuoteAssetAmount)
18191848 let ammBalance = (cbalance() - liquidationPenalty)
1820- let $t07718377312 = if ((0 > ammBalance))
1849+ let $t07780677935 = if ((0 > ammBalance))
18211850 then $Tuple2(0, abs(ammBalance))
18221851 else $Tuple2(ammBalance, 0)
1823- let newAmmBalance = $t07718377312._1
1824- let x11 = $t07718377312._2
1825- let $t07732077374 = getBorrowedByTrader(_trader)
1826- let borrowed = $t07732077374._1
1827- let assetId = $t07732077374._2
1852+ let newAmmBalance = $t07780677935._1
1853+ let x11 = $t07780677935._2
1854+ let $t07794377997 = getBorrowedByTrader(_trader)
1855+ let borrowed = $t07794377997._1
1856+ let assetId = $t07794377997._2
18281857 let doLiquidateCollateral = if ((borrowed > 0))
18291858 then {
18301859 let collateralToSell = muld(borrowed, liquidationRatio)
18311860 let realizeAndClose = invoke(collateralAddress(), "realizePartially", [_trader, assetId, collateralToSell], nil)
18321861 if ((realizeAndClose == realizeAndClose))
18331862 then nil
18341863 else throw("Strict value is not equal to itself.")
18351864 }
18361865 else nil
18371866 if ((doLiquidateCollateral == doLiquidateCollateral))
18381867 then {
18391868 let unstake = invoke(vaultAddress(), "withdrawLocked", [liquidationPenalty], nil)
18401869 if ((unstake == unstake))
18411870 then {
18421871 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
18431872 if ((depositInsurance == depositInsurance))
18441873 then {
18451874 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
18461875 if ((notifyNotional == notifyNotional))
18471876 then (((updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, (totalLongPositionSize() - (if ((newPositionSize > 0))
18481877 then abs(exchangedPositionSize)
18491878 else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
18501879 then abs(exchangedPositionSize)
18511880 else 0)), (openInterestLong() - (if ((newPositionSize > 0))
18521881 then exchangedQuoteAssetAmount
18531882 else 0)), (openInterestShort() - (if ((0 > newPositionSize))
18541883 then exchangedQuoteAssetAmount
18551884 else 0)))) ++ withdraw(i.caller, feeToLiquidator)) ++ updateBalance(newAmmBalance))
18561885 else throw("Strict value is not equal to itself.")
18571886 }
18581887 else throw("Strict value is not equal to itself.")
18591888 }
18601889 else throw("Strict value is not equal to itself.")
18611890 }
18621891 else throw("Strict value is not equal to itself.")
18631892 }
18641893 else {
1865- let $t07906979564 = internalClosePosition(_trader, false)
1866- let x1 = $t07906979564._1
1867- let badDebt = $t07906979564._2
1868- let x2 = $t07906979564._3
1869- let x3 = $t07906979564._4
1870- let quoteAssetReserveAfter = $t07906979564._5
1871- let baseAssetReserveAfter = $t07906979564._6
1872- let totalPositionSizeAfter = $t07906979564._7
1873- let openInterestNotionalAfter = $t07906979564._8
1874- let exchangedQuoteAssetAmount = $t07906979564._9
1875- let totalLongAfter = $t07906979564._10
1876- let totalShortAfter = $t07906979564._11
1877- let totalLongOpenInterestAfter = $t07906979564._12
1878- let totalShortOpenInterestAfter = $t07906979564._13
1894+ let $t07969280187 = internalClosePosition(_trader, false)
1895+ let x1 = $t07969280187._1
1896+ let badDebt = $t07969280187._2
1897+ let x2 = $t07969280187._3
1898+ let x3 = $t07969280187._4
1899+ let quoteAssetReserveAfter = $t07969280187._5
1900+ let baseAssetReserveAfter = $t07969280187._6
1901+ let totalPositionSizeAfter = $t07969280187._7
1902+ let openInterestNotionalAfter = $t07969280187._8
1903+ let exchangedQuoteAssetAmount = $t07969280187._9
1904+ let totalLongAfter = $t07969280187._10
1905+ let totalShortAfter = $t07969280187._11
1906+ let totalLongOpenInterestAfter = $t07969280187._12
1907+ let totalShortOpenInterestAfter = $t07969280187._13
18791908 let liquidationPenalty = muld(exchangedQuoteAssetAmount, liquidationFeeRatio())
18801909 let feeToLiquidator = (liquidationPenalty / 2)
18811910 let feeToVault = (liquidationPenalty - feeToLiquidator)
18821911 let ammBalance = (cbalance() - liquidationPenalty)
1883- let $t07997280101 = if ((0 > ammBalance))
1912+ let $t08059580724 = if ((0 > ammBalance))
18841913 then $Tuple2(0, abs(ammBalance))
18851914 else $Tuple2(ammBalance, 0)
1886- let newAmmBalance = $t07997280101._1
1887- let x11 = $t07997280101._2
1888- let $t08010980163 = getBorrowedByTrader(_trader)
1889- let borrowed = $t08010980163._1
1890- let assetId = $t08010980163._2
1915+ let newAmmBalance = $t08059580724._1
1916+ let x11 = $t08059580724._2
1917+ let $t08073280786 = getBorrowedByTrader(_trader)
1918+ let borrowed = $t08073280786._1
1919+ let assetId = $t08073280786._2
18911920 let doLiquidateCollateral = if ((borrowed > 0))
18921921 then {
18931922 let realizeAndClose = invoke(collateralAddress(), "realizePartiallyAndClose", [_trader, 0, assetId], nil)
18941923 if ((realizeAndClose == realizeAndClose))
18951924 then nil
18961925 else throw("Strict value is not equal to itself.")
18971926 }
18981927 else nil
18991928 if ((doLiquidateCollateral == doLiquidateCollateral))
19001929 then {
19011930 let x = if ((badDebt > 0))
19021931 then {
19031932 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [badDebt], nil)
19041933 if ((lockBadDebt == lockBadDebt))
19051934 then nil
19061935 else throw("Strict value is not equal to itself.")
19071936 }
19081937 else nil
19091938 if ((x == x))
19101939 then {
19111940 let unstake = invoke(vaultAddress(), "withdrawLocked", [liquidationPenalty], nil)
19121941 if ((unstake == unstake))
19131942 then {
19141943 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
19151944 if ((depositInsurance == depositInsurance))
19161945 then {
19171946 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, 0], nil)
19181947 if ((notifyNotional == notifyNotional))
19191948 then (((deletePosition(_trader) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ withdraw(i.caller, feeToLiquidator)) ++ updateBalance(newAmmBalance))
19201949 else throw("Strict value is not equal to itself.")
19211950 }
19221951 else throw("Strict value is not equal to itself.")
19231952 }
19241953 else throw("Strict value is not equal to itself.")
19251954 }
19261955 else throw("Strict value is not equal to itself.")
19271956 }
19281957 else throw("Strict value is not equal to itself.")
19291958 }
19301959 }
19311960 else throw("Strict value is not equal to itself.")
19321961 }
19331962
19341963
19351964
19361965 @Callable(i)
19371966 func payFunding () = {
19381967 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
19391968 if ((sync == sync))
19401969 then {
19411970 let fundingBlockTimestamp = nextFundingBlockTimestamp()
19421971 if (if (if ((fundingBlockTimestamp > lastBlock.timestamp))
19431972 then true
19441973 else !(initialized()))
19451974 then true
19461975 else paused())
19471976 then throw(((("Invalid funding block timestamp: " + toString(lastBlock.timestamp)) + " < ") + toString(fundingBlockTimestamp)))
19481977 else {
1949- let underlyingPrice = getOracleTwapPrice()
1950- let $t08203982101 = getFunding()
1951- let shortPremiumFraction = $t08203982101._1
1952- let longPremiumFraction = $t08203982101._2
1978+ let underlyingPrice = getOraclePrice()
1979+ let $t08265882720 = getFunding()
1980+ let shortPremiumFraction = $t08265882720._1
1981+ let longPremiumFraction = $t08265882720._2
19531982 updateFunding((fundingBlockTimestamp + fundingPeriodSeconds()), (latestLongCumulativePremiumFraction() + longPremiumFraction), (latestShortCumulativePremiumFraction() + shortPremiumFraction), divd(longPremiumFraction, underlyingPrice), divd(shortPremiumFraction, underlyingPrice))
19541983 }
19551984 }
19561985 else throw("Strict value is not equal to itself.")
19571986 }
19581987
19591988
19601989
19611990 @Callable(i)
19621991 func syncTerminalPriceToOracle () = {
19631992 let _qtAstR = qtAstR()
19641993 let _bsAstR = bsAstR()
1965- let $t08253382672 = getSyncTerminalPrice(getOracleTwapPrice(), _qtAstR, _bsAstR)
1966- let newQuoteAssetWeight = $t08253382672._1
1967- let newBaseAssetWeight = $t08253382672._2
1968- let marginToVault = $t08253382672._3
1994+ let $t08315283287 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1995+ let newQuoteAssetWeight = $t08315283287._1
1996+ let newBaseAssetWeight = $t08315283287._2
1997+ let marginToVault = $t08315283287._3
19691998 let doExchangePnL = if ((marginToVault != 0))
19701999 then {
19712000 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
19722001 if ((doExchangePnL == doExchangePnL))
19732002 then nil
19742003 else throw("Strict value is not equal to itself.")
19752004 }
19762005 else nil
19772006 if ((doExchangePnL == doExchangePnL))
19782007 then (updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight) ++ appendTwap(divd(muld(_qtAstR, newQuoteAssetWeight), muld(_bsAstR, newBaseAssetWeight))))
19792008 else throw("Strict value is not equal to itself.")
19802009 }
19812010
19822011
19832012
19842013 @Callable(i)
19852014 func view_calcRemainMarginWithFundingPayment (_trader) = {
19862015 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
19872016 if ((sync == sync))
19882017 then {
1989- let $t08324183342 = getPosition(_trader)
1990- let positionSize = $t08324183342._1
1991- let positionMargin = $t08324183342._2
1992- let pon = $t08324183342._3
1993- let positionLstUpdCPF = $t08324183342._4
1994- let $t08334583446 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1995- let positionNotional = $t08334583446._1
1996- let unrealizedPnl = $t08334583446._2
1997- let $t08344983621 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
1998- let remainMargin = $t08344983621._1
1999- let badDebt = $t08344983621._2
2000- let fundingPayment = $t08344983621._3
2018+ let $t08385683957 = getPosition(_trader)
2019+ let positionSize = $t08385683957._1
2020+ let positionMargin = $t08385683957._2
2021+ let pon = $t08385683957._3
2022+ let positionLstUpdCPF = $t08385683957._4
2023+ let $t08396084061 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
2024+ let positionNotional = $t08396084061._1
2025+ let unrealizedPnl = $t08396084061._2
2026+ let $t08406484236 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
2027+ let remainMargin = $t08406484236._1
2028+ let badDebt = $t08406484236._2
2029+ let fundingPayment = $t08406484236._3
20012030 throw((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)))
20022031 }
20032032 else throw("Strict value is not equal to itself.")
20042033 }
20052034
20062035
20072036
20082037 @Callable(i)
20092038 func view_getPegAdjustCost (_price) = {
20102039 let _qtAstR = qtAstR()
20112040 let _bsAstR = bsAstR()
20122041 let result = getSyncTerminalPrice(_price, _qtAstR, _bsAstR)
20132042 throw(toString(result._3))
20142043 }
20152044
20162045
20172046
20182047 @Callable(i)
20192048 func view_getTerminalAmmPrice () = {
2020- let $t08403784118 = getTerminalAmmState()
2021- let terminalQuoteAssetReserve = $t08403784118._1
2022- let terminalBaseAssetReserve = $t08403784118._2
2049+ let $t08465284733 = getTerminalAmmState()
2050+ let terminalQuoteAssetReserve = $t08465284733._1
2051+ let terminalBaseAssetReserve = $t08465284733._2
20232052 let price = divd(muld(terminalQuoteAssetReserve, qtAstW()), muld(terminalBaseAssetReserve, bsAstW()))
20242053 throw(toString(price))
20252054 }
20262055
20272056
20282057
20292058 @Callable(i)
20302059 func view_getFunding () = {
2031- let underlyingPrice = getOracleTwapPrice()
2032- let $t08433784399 = getFunding()
2033- let shortPremiumFraction = $t08433784399._1
2034- let longPremiumFraction = $t08433784399._2
2060+ let underlyingPrice = getOraclePrice()
2061+ let $t08494885010 = getFunding()
2062+ let shortPremiumFraction = $t08494885010._1
2063+ let longPremiumFraction = $t08494885010._2
20352064 let longFunding = divd(longPremiumFraction, underlyingPrice)
20362065 let shortFunding = divd(shortPremiumFraction, underlyingPrice)
2037- throw((((s(longFunding) + s(shortFunding)) + s(getTwapSpotPrice())) + s(getOracleTwapPrice())))
2066+ throw((((s(longFunding) + s(shortFunding)) + s(getTwapSpotPrice())) + s(getOraclePrice())))
20382067 }
20392068
20402069
20412070
20422071 @Callable(i)
20432072 func view_getBorrowedByTrader (_trader) = {
2044- let $t08468984743 = getBorrowedByTrader(_trader)
2045- let borrowed = $t08468984743._1
2046- let assetId = $t08468984743._2
2073+ let $t08529685350 = getBorrowedByTrader(_trader)
2074+ let borrowed = $t08529685350._1
2075+ let assetId = $t08529685350._2
20472076 throw((s(borrowed) + assetId))
20482077 }
20492078
20502079
20512080
20522081 @Callable(i)
20532082 func computeSpotPrice () = {
20542083 let result = getSpotPrice()
20552084 $Tuple2(nil, result)
20562085 }
20572086
20582087
20592088
20602089 @Callable(i)
20612090 func computeFeeForTraderWithArtifact (_trader,_artifactId) = {
20622091 let result = getForTraderWithArtifact(_trader, _artifactId)
20632092 $Tuple2(nil, result)
20642093 }
20652094
20662095
20672096 @Verifier(tx)
20682097 func verify () = sigVerify(tx.bodyBytes, tx.proofs[0], adminPublicKey())
20692098

github/deemru/w8io/026f985 
283.86 ms