tx · HnbS3TnpLquq3XcycqHuNLnfBSfWEqz5e3dVREcWxhBU

3N4SpfepyNLLb4Uc8e3xvkZew64HMcZ23oX:  -0.07500000 Waves

2022.12.28 16:10 [2380172] smart account 3N4SpfepyNLLb4Uc8e3xvkZew64HMcZ23oX > SELF 0.00000000 Waves

{ "type": 13, "id": "HnbS3TnpLquq3XcycqHuNLnfBSfWEqz5e3dVREcWxhBU", "fee": 7500000, "feeAssetId": null, "timestamp": 1672233018104, "version": 2, "chainId": 84, "sender": "3N4SpfepyNLLb4Uc8e3xvkZew64HMcZ23oX", "senderPublicKey": "Gqr4yqnGvyo3GmKz59Qs1qfyDm5XhT134DCjiBhmD8jW", "proofs": [ "5VyZy3P1rPHFZPGwAXX4gYs8qxgCaA5uapxoyuhouCYNUzTeUcafLuBAz9N7ByEwdHxdt37Rd5oRNKqMTbR1BfU4" ], "script": "base64:BgJ6CAISABIAEgASABIDCgEBEgMKAQESDgoMAQEBAQEBAQEBAQEBEhQKEgEBAQEBAQEICAgIAQEBAQEBARIFCgMBAQESBgoEAQEBCBIAEgMKAQESBAoCAQESAwoBCBIAEgASAwoBCBIDCgEBEgASABIDCgEIEgASBAoCCAjDAQAJa19vcmFfa2V5AglrX29yYV9rZXkAD2tfb3JhX2Jsb2NrX2tleQIPa19vcmFfYmxvY2tfa2V5AA5rX29yYV9vcGVuX2tleQIOa19vcmFfb3Blbl9rZXkABWtfb3JhAgVrX29yYQAJa19iYWxhbmNlAglrX2JhbGFuY2UACmtfc2VxdWVuY2UCCmtfc2VxdWVuY2UADmtfcG9zaXRpb25TaXplAg5rX3Bvc2l0aW9uU2l6ZQAQa19wb3NpdGlvbk1hcmdpbgIQa19wb3NpdGlvbk1hcmdpbgAWa19wb3NpdGlvbk9wZW5Ob3Rpb25hbAIWa19wb3NpdGlvbk9wZW5Ob3Rpb25hbAAua19wb3NpdGlvbkxhc3RVcGRhdGVkQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgISa19wb3NpdGlvbkZyYWN0aW9uABJrX3Bvc2l0aW9uU2VxdWVuY2UCEmtfcG9zaXRpb25TZXF1ZW5jZQAPa19wb3NpdGlvbkFzc2V0Ag9rX3Bvc2l0aW9uQXNzZXQADWtfaW5pdGlhbGl6ZWQCDWtfaW5pdGlhbGl6ZWQACGtfcGF1c2VkAghrX3BhdXNlZAALa19jbG9zZU9ubHkCC2tfY2xvc2VPbmx5AAVrX2ZlZQIFa19mZWUAD2tfZnVuZGluZ1BlcmlvZAIPa19mdW5kaW5nUGVyaW9kABFrX2luaXRNYXJnaW5SYXRpbwIRa19pbml0TWFyZ2luUmF0aW8AGGtfbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwIFa19tbXIAFWtfbGlxdWlkYXRpb25GZWVSYXRpbwIVa19saXF1aWRhdGlvbkZlZVJhdGlvABlrX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAhZrX3BhcnRMaXF1aWRhdGlvblJhdGlvAA1rX3NwcmVhZExpbWl0Ag1rX3NwcmVhZExpbWl0ABBrX21heFByaWNlSW1wYWN0AhBrX21heFByaWNlSW1wYWN0ABBrX21heFByaWNlU3ByZWFkAhBrX21heFByaWNlU3ByZWFkABFrX21heE9wZW5Ob3Rpb25hbAIRa19tYXhPcGVuTm90aW9uYWwAFWtfZmVlVG9TdGFrZXJzUGVyY2VudAIVa19mZWVUb1N0YWtlcnNQZXJjZW50ABBrX21heE9yYWNsZURlbGF5AhBrX21heE9yYWNsZURlbGF5AA1rX2xhc3REYXRhU3RyAg1rX2xhc3REYXRhU3RyAA5rX2xhc3RNaW51dGVJZAIOa19sYXN0TWludXRlSWQAHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlAh1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQATa190d2FwRGF0YUxhc3RQcmljZQITa190d2FwRGF0YUxhc3RQcmljZQAaa190d2FwRGF0YVByZXZpb3VzTWludXRlSWQCGmtfdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkACVrX2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAhtrX2xhdGVzdExvbmdQcmVtaXVtRnJhY3Rpb24AJmtfbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAhxrX2xhdGVzdFNob3J0UHJlbWl1bUZyYWN0aW9uABJrX25leHRGdW5kaW5nQmxvY2sCHmtfbmV4dEZ1bmRpbmdCbG9ja01pblRpbWVzdGFtcAARa19sb25nRnVuZGluZ1JhdGUCEWtfbG9uZ0Z1bmRpbmdSYXRlABJrX3Nob3J0RnVuZGluZ1JhdGUCEmtfc2hvcnRGdW5kaW5nUmF0ZQATa19xdW90ZUFzc2V0UmVzZXJ2ZQIIa19xdEFzdFIAEmtfYmFzZUFzc2V0UmVzZXJ2ZQIIa19ic0FzdFIAEmtfcXVvdGVBc3NldFdlaWdodAIIa19xdEFzdFcAEWtfYmFzZUFzc2V0V2VpZ2h0AghrX2JzQXN0VwATa190b3RhbFBvc2l0aW9uU2l6ZQITa190b3RhbFBvc2l0aW9uU2l6ZQAXa190b3RhbExvbmdQb3NpdGlvblNpemUCF2tfdG90YWxMb25nUG9zaXRpb25TaXplABhrX3RvdGFsU2hvcnRQb3NpdGlvblNpemUCGGtfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAWa19vcGVuSW50ZXJlc3ROb3Rpb25hbAIWa19vcGVuSW50ZXJlc3ROb3Rpb25hbAATa19vcGVuSW50ZXJlc3RTaG9ydAITa19vcGVuSW50ZXJlc3RTaG9ydAASa19vcGVuSW50ZXJlc3RMb25nAhJrX29wZW5JbnRlcmVzdExvbmcAFGtfY29vcmRpbmF0b3JBZGRyZXNzAhRrX2Nvb3JkaW5hdG9yQWRkcmVzcwAPa192YXVsdF9hZGRyZXNzAg9rX3ZhdWx0X2FkZHJlc3MAD2tfYWRtaW5fYWRkcmVzcwIPa19hZG1pbl9hZGRyZXNzABJrX2FkbWluX3B1YmxpY19rZXkCEmtfYWRtaW5fcHVibGljX2tleQANa19xdW90ZV9hc3NldAINa19xdW90ZV9hc3NldAAPa19xdW90ZV9zdGFraW5nAg9rX3F1b3RlX3N0YWtpbmcAEWtfc3Rha2luZ19hZGRyZXNzAhFrX3N0YWtpbmdfYWRkcmVzcwAPa19taW5lcl9hZGRyZXNzAg9rX21pbmVyX2FkZHJlc3MAEGtfb3JkZXJzX2FkZHJlc3MCEGtfb3JkZXJzX2FkZHJlc3MAEmtfcmVmZXJyYWxfYWRkcmVzcwISa19yZWZlcnJhbF9hZGRyZXNzABRrX2NvbGxhdGVyYWxfYWRkcmVzcwIUa19jb2xsYXRlcmFsX2FkZHJlc3MAEmtfZXhjaGFuZ2VfYWRkcmVzcwISa19leGNoYW5nZV9hZGRyZXNzABVrX25mdF9tYW5hZ2VyX2FkZHJlc3MCFWtfbmZ0X21hbmFnZXJfYWRkcmVzcwAga190cmFkZXJfbWFya2V0X2Fzc2V0X2NvbGxhdGVyYWwCIGtfdHJhZGVyX21hcmtldF9hc3NldF9jb2xsYXRlcmFsAQ50b0NvbXBvc2l0ZUtleQIEX2tleQhfYWRkcmVzcwkArAICCQCsAgIFBF9rZXkCAV8FCF9hZGRyZXNzAQtjb29yZGluYXRvcgAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCBQR0aGlzBRRrX2Nvb3JkaW5hdG9yQWRkcmVzcwITQ29vcmRpbmF0b3Igbm90IHNldAEMYWRtaW5BZGRyZXNzAAkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABQ9rX2FkbWluX2FkZHJlc3MBDmFkbWluUHVibGljS2V5AAkA2QQBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABRJrX2FkbWluX3B1YmxpY19rZXkBCnF1b3RlQXNzZXQACQDZBAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFDWtfcXVvdGVfYXNzZXQBEXF1b3RlQXNzZXRTdGFraW5nAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFD2tfcXVvdGVfc3Rha2luZwIbUXVvdGUgYXNzZXQgc3Rha2luZyBub3Qgc2V0AQ5zdGFraW5nQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABRFrX3N0YWtpbmdfYWRkcmVzcwIPU3Rha2luZyBub3Qgc2V0AQx2YXVsdEFkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUPa192YXVsdF9hZGRyZXNzAg1WYXVsdCBub3Qgc2V0AQxtaW5lckFkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUPa19taW5lcl9hZGRyZXNzAg1NaW5lciBub3Qgc2V0AQ1vcmRlcnNBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFEGtfb3JkZXJzX2FkZHJlc3MCDk9yZGVycyBub3Qgc2V0AQ9yZWZlcnJhbEFkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUSa19yZWZlcnJhbF9hZGRyZXNzAhBSZWZlcnJhbCBub3Qgc2V0ARFuZnRNYW5hZ2VyQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABRVrX25mdF9tYW5hZ2VyX2FkZHJlc3MCE05GVCBNYW5hZ2VyIG5vdCBzZXQBEWNvbGxhdGVyYWxBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFFGtfY29sbGF0ZXJhbF9hZGRyZXNzAhpDb2xsYXRlcmFsIE1hbmFnZXIgbm90IHNldAELc3dhcEFkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIJAQtjb29yZGluYXRvcgAFEmtfZXhjaGFuZ2VfYWRkcmVzcwIPTm8gc3dhcCBhZGRyZXNzAhRJbnZhbGlkIHN3YXAgYWRkcmVzcwARa193aGl0ZWxpc3RfYXNzZXQCEWtfd2hpdGVsaXN0X2Fzc2V0ARBpc1doaXRlbGlzdEFzc2V0AQhfYXNzZXRJZAkBC3ZhbHVlT3JFbHNlAgkAmwgCCQERY29sbGF0ZXJhbEFkZHJlc3MACQEOdG9Db21wb3NpdGVLZXkCBRFrX3doaXRlbGlzdF9hc3NldAUIX2Fzc2V0SWQHAA1rX3Rva2VuX3BhcmFtAg1rX3Rva2VuX3BhcmFtAAxrX3Rva2VuX3R5cGUCDGtfdG9rZW5fdHlwZQAYRkVFX1JFRFVDVElPTl9UT0tFTl9UWVBFAg1mZWVfcmVkdWN0aW9uAAhESVJfTE9ORwABAAlESVJfU0hPUlQAAgANVFdBUF9JTlRFUlZBTAAPAA9PUkFDTEVfSU5URVJWQUwADwAHU0VDT05EUwDoBwAPREVDSU1BTF9OVU1CRVJTAAYADERFQ0lNQUxfVU5JVAkAaAIAAQkAaAIJAGgCCQBoAgkAaAIJAGgCAAoACgAKAAoACgAKAAdPTkVfREFZCQBoAgCAowUFDERFQ0lNQUxfVU5JVAAIQUxMX0ZFRVMAZAAPUE5MX09QVElPTl9TUE9UAAEAEVBOTF9PUFRJT05fT1JBQ0xFAAIBAXMBAl94CQCsAgIJAKQDAQUCX3gCASwBBGRpdmQCAl94Al95CQBuBAUCX3gFDERFQ0lNQUxfVU5JVAUCX3kFCEhBTEZFVkVOAQRtdWxkAgJfeAJfeQkAbgQFAl94BQJfeQUMREVDSU1BTF9VTklUBQhIQUxGRVZFTgEFc3FydGQBAl94CQEEc3FydAQFAl94BQ9ERUNJTUFMX05VTUJFUlMFD0RFQ0lNQUxfTlVNQkVSUwUISEFMRkVWRU4BBHBvd2QCAl94Al95CQBsBgUCX3gFD0RFQ0lNQUxfTlVNQkVSUwUCX3kFD0RFQ0lNQUxfTlVNQkVSUwUPREVDSU1BTF9OVU1CRVJTBQhIQUxGRVZFTgEFYmRpdmQCAl94Al95CQC9AgQFAl94CQC2AgEFDERFQ0lNQUxfVU5JVAUCX3kFCEhBTEZFVkVOAQVibXVsZAICX3gCX3kJAL0CBAUCX3gFAl95CQC2AgEFDERFQ0lNQUxfVU5JVAUISEFMRkVWRU4BBmJzcXJ0ZAECX3gJAQpzcXJ0QmlnSW50BAUCX3gFD0RFQ0lNQUxfTlVNQkVSUwUPREVDSU1BTF9OVU1CRVJTBQhIQUxGRVZFTgEFYnBvd2QCAl94Al95CQB2BgUCX3gFD0RFQ0lNQUxfTlVNQkVSUwUCX3kFD0RFQ0lNQUxfTlVNQkVSUwUPREVDSU1BTF9OVU1CRVJTBQhIQUxGRVZFTgEDYWJzAQJfeAMJAGYCBQJfeAAABQJfeAkBAS0BBQJfeAEEdm1heAICX3gCX3kDCQBnAgUCX3gFAl95BQJfeAUCX3kBCWxpc3RUb1N0cgEFX2xpc3QKAQVfam9pbgILYWNjdW11bGF0b3IDdmFsCQCsAgIJAKwCAgULYWNjdW11bGF0b3IFA3ZhbAIBLAQKbmV3TGlzdFN0cgoAAiRsBQVfbGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzACAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEFX2pvaW4CBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDIwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAA0ADgAPABAAEQASABMAFAQLbmV3TGlzdFN0clUJALMCAgUKbmV3TGlzdFN0cgABBAtuZXdMaXN0U3RyUgMJAAACCQCvAgIFC25ld0xpc3RTdHJVAAECASwJALACAgULbmV3TGlzdFN0clUAAQULbmV3TGlzdFN0clUFC25ld0xpc3RTdHJSAQlzdHJUb0xpc3QBBF9zdHIJALUJAgUEX3N0cgIBLAELcHVzaFRvUXVldWUDBV9saXN0CF9tYXhTaXplBl92YWx1ZQMJAGYCCQCQAwEFBV9saXN0BQhfbWF4U2l6ZQkAzQgCCQDRCAIFBV9saXN0AAAFBl92YWx1ZQkAzQgCBQVfbGlzdAUGX3ZhbHVlAQNpbnQBAWsJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQR0aGlzBQFrCQCsAgICDW5vIHZhbHVlIGZvciAFAWsBBWludE9yAgFrA2RlZgkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQFrBQNkZWYBBHN0ckECCF9hZGRyZXNzBF9rZXkEA3ZhbAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFCF9hZGRyZXNzBQRfa2V5CQCsAgICEU5vIHZhbHVlIGZvciBrZXkgBQRfa2V5BQN2YWwBBGludEECCF9hZGRyZXNzBF9rZXkEA3ZhbAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFCF9hZGRyZXNzBQRfa2V5CQCsAgICEU5vIHZhbHVlIGZvciBrZXkgBQRfa2V5BQN2YWwBCGNiYWxhbmNlAAkBA2ludAEFCWtfYmFsYW5jZQEDZmVlAAkBA2ludAEFBWtfZmVlAQ9pbml0TWFyZ2luUmF0aW8ACQEDaW50AQURa19pbml0TWFyZ2luUmF0aW8BBnF0QXN0UgAJAQNpbnQBBRNrX3F1b3RlQXNzZXRSZXNlcnZlAQZic0FzdFIACQEDaW50AQUSa19iYXNlQXNzZXRSZXNlcnZlAQZxdEFzdFcACQEFaW50T3ICBRJrX3F1b3RlQXNzZXRXZWlnaHQFDERFQ0lNQUxfVU5JVAEGYnNBc3RXAAkBBWludE9yAgURa19iYXNlQXNzZXRXZWlnaHQFDERFQ0lNQUxfVU5JVAERdG90YWxQb3NpdGlvblNpemUACQEDaW50AQUTa190b3RhbFBvc2l0aW9uU2l6ZQEUb3BlbkludGVyZXN0Tm90aW9uYWwACQEDaW50AQUWa19vcGVuSW50ZXJlc3ROb3Rpb25hbAERb3BlbkludGVyZXN0U2hvcnQACQEDaW50AQUTa19vcGVuSW50ZXJlc3RTaG9ydAEQb3BlbkludGVyZXN0TG9uZwAJAQNpbnQBBRJrX29wZW5JbnRlcmVzdExvbmcBGW5leHRGdW5kaW5nQmxvY2tUaW1lc3RhbXAACQEDaW50AQUSa19uZXh0RnVuZGluZ0Jsb2NrARBmdW5kaW5nUGVyaW9kUmF3AAkBA2ludAEFD2tfZnVuZGluZ1BlcmlvZAEUZnVuZGluZ1BlcmlvZERlY2ltYWwACQBoAgkBEGZ1bmRpbmdQZXJpb2RSYXcABQxERUNJTUFMX1VOSVQBFGZ1bmRpbmdQZXJpb2RTZWNvbmRzAAkAaAIJARBmdW5kaW5nUGVyaW9kUmF3AAUHU0VDT05EUwEWbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwAJAQNpbnQBBRhrX21haW50ZW5hbmNlTWFyZ2luUmF0aW8BE2xpcXVpZGF0aW9uRmVlUmF0aW8ACQEDaW50AQUVa19saXF1aWRhdGlvbkZlZVJhdGlvARdwYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwAJAQNpbnQBBRlrX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAQtzcHJlYWRMaW1pdAAJAQNpbnQBBQ1rX3NwcmVhZExpbWl0AQ5tYXhQcmljZUltcGFjdAAJAQNpbnQBBRBrX21heFByaWNlSW1wYWN0AQ5tYXhQcmljZVNwcmVhZAAJAQNpbnQBBRBrX21heFByaWNlU3ByZWFkAQ9tYXhPcGVuTm90aW9uYWwACQEDaW50AQURa19tYXhPcGVuTm90aW9uYWwBI2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAkBA2ludAEFJWtfbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BJGxhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAJAQNpbnQBBSZrX2xhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAJAQNpbnQBBRhrX3RvdGFsU2hvcnRQb3NpdGlvblNpemUBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQAJAQNpbnQBBRdrX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQEMbGFzdFNlcXVlbmNlAAkBBWludE9yAgUKa19zZXF1ZW5jZQAAARNmZWVUb1N0YWtlcnNQZXJjZW50AAkBA2ludAEFFWtfZmVlVG9TdGFrZXJzUGVyY2VudAEObWF4T3JhY2xlRGVsYXkACQEDaW50AQUQa19tYXhPcmFjbGVEZWxheQEPZ2V0QWN0dWFsQ2FsbGVyAQFpCQELdmFsdWVPckVsc2UCCQCdCAIJAQ1vcmRlcnNBZGRyZXNzAAIIa19zZW5kZXIJAKUIAQgFAWkGY2FsbGVyARZyZXF1aXJlTW9yZU1hcmdpblJhdGlvAwxfbWFyZ2luUmF0aW8QX2Jhc2VNYXJnaW5SYXRpbxRfbGFyZ2VyVGhhbk9yRXF1YWxUbwQUcmVtYWluaW5nTWFyZ2luUmF0aW8JAGUCBQxfbWFyZ2luUmF0aW8FEF9iYXNlTWFyZ2luUmF0aW8DAwUUX2xhcmdlclRoYW5PckVxdWFsVG8JAGYCAAAFFHJlbWFpbmluZ01hcmdpblJhdGlvBwkAAgECDkludmFsaWQgbWFyZ2luAwMJAQEhAQUUX2xhcmdlclRoYW5PckVxdWFsVG8JAGcCBRRyZW1haW5pbmdNYXJnaW5SYXRpbwAABwkAAgECDkludmFsaWQgbWFyZ2luBgEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgENX3Bvc2l0aW9uU2l6ZQMJAAACBQ1fcG9zaXRpb25TaXplAAAJAAIBAixTaG91bGQgbm90IGJlIGNhbGxlZCB3aXRoIF9wb3NpdGlvblNpemUgPT0gMAMJAGYCBQ1fcG9zaXRpb25TaXplAAAJASNsYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAJASRsYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24AAQtnZXRQb3NpdGlvbgEHX3RyYWRlcgQPcG9zaXRpb25TaXplT3B0CQCaCAIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFDmtfcG9zaXRpb25TaXplBQdfdHJhZGVyBAckbWF0Y2gwBQ9wb3NpdGlvblNpemVPcHQDCQABAgUHJG1hdGNoMAIDSW50BAxwb3NpdGlvblNpemUFByRtYXRjaDAJAJYKBAUMcG9zaXRpb25TaXplCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBRBrX3Bvc2l0aW9uTWFyZ2luBQdfdHJhZGVyCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBRZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBQdfdHJhZGVyCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBS5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBQdfdHJhZGVyCQCWCgQAAAAAAAAAAAEQZ2V0UG9zaXRpb25Bc3NldAEHX3RyYWRlcgQQcG9zaXRpb25Bc3NldE9wdAkAnQgCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBQ9rX3Bvc2l0aW9uQXNzZXQFB190cmFkZXIEByRtYXRjaDAFEHBvc2l0aW9uQXNzZXRPcHQDCQABAgUHJG1hdGNoMAIGU3RyaW5nBA1wb3NpdGlvbkFzc2V0BQckbWF0Y2gwBQ1wb3NpdGlvbkFzc2V0CQDYBAEJAQpxdW90ZUFzc2V0AAETcmVxdWlyZU9wZW5Qb3NpdGlvbgEHX3RyYWRlcgMJAAACCAkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgJfMQAACQACAQIQTm8gb3BlbiBwb3NpdGlvbgYBC2luaXRpYWxpemVkAAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzBQ1rX2luaXRpYWxpemVkBwEGcGF1c2VkAAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzBQhrX3BhdXNlZAcBCWNsb3NlT25seQAJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhpcwULa19jbG9zZU9ubHkHAQ11cGRhdGVSZXNlcnZlAwZfaXNBZGQRX3F1b3RlQXNzZXRBbW91bnQQX2Jhc2VBc3NldEFtb3VudAMFBl9pc0FkZAQHbmV3QmFzZQkAZQIJAQZic0FzdFIABRBfYmFzZUFzc2V0QW1vdW50AwkAZwIAAAUHbmV3QmFzZQkAAgECKlR4IGxlYWQgdG8gYmFzZSBhc3NldCByZXNlcnZlIDw9IDAsIHJldmVydAkAlQoDCQBkAgkBBnF0QXN0UgAFEV9xdW90ZUFzc2V0QW1vdW50BQduZXdCYXNlCQBkAgkBEXRvdGFsUG9zaXRpb25TaXplAAUQX2Jhc2VBc3NldEFtb3VudAQIbmV3UXVvdGUJAGUCCQEGcXRBc3RSAAURX3F1b3RlQXNzZXRBbW91bnQDCQBnAgAABQhuZXdRdW90ZQkAAgECKlR4IGxlYWQgdG8gYmFzZSBxdW90ZSByZXNlcnZlIDw9IDAsIHJldmVydAkAlQoDBQhuZXdRdW90ZQkAZAIJAQZic0FzdFIABRBfYmFzZUFzc2V0QW1vdW50CQBlAgkBEXRvdGFsUG9zaXRpb25TaXplAAUQX2Jhc2VBc3NldEFtb3VudAENY2FsY0ludmFyaWFudAQHX3F0QXN0UgdfcXRBc3RXB19ic0FzdFIHX2JzQXN0VwQHYnF0QXN0UgkAtgIBBQdfcXRBc3RSBAdicXRBc3RXCQC2AgEFB19xdEFzdFcEB2Jic0FzdFIJALYCAQUHX2JzQXN0UgQHYmJzQXN0VwkAtgIBBQdfYnNBc3RXCQEFYm11bGQCCQEFYm11bGQCBQdicXRBc3RSBQdicXRBc3RXCQEFYm11bGQCBQdiYnNBc3RSBQdiYnNBc3RXAQlzd2FwSW5wdXQCBl9pc0FkZBFfcXVvdGVBc3NldEFtb3VudAQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwAEAWsJAQ1jYWxjSW52YXJpYW50BAUHX3F0QXN0UgUHX3F0QXN0VwUHX2JzQXN0UgUHX2JzQXN0VwQWcXVvdGVBc3NldFJlc2VydmVBZnRlcgMFBl9pc0FkZAkAZAIFB19xdEFzdFIFEV9xdW90ZUFzc2V0QW1vdW50CQBlAgUHX3F0QXN0UgURX3F1b3RlQXNzZXRBbW91bnQEFWJhc2VBc3NldFJlc2VydmVBZnRlcgkAoAMBCQEFYmRpdmQCBQFrCQC2AgEJAQRtdWxkAgUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUHX3F0QXN0VwQYYW1vdW50QmFzZUFzc2V0Qm91Z2h0QWJzCQEEZGl2ZAIJAQNhYnMBCQBlAgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBQdfYnNBc3RSBQdfcXRBc3RXBBVhbW91bnRCYXNlQXNzZXRCb3VnaHQDBQZfaXNBZGQFGGFtb3VudEJhc2VBc3NldEJvdWdodEFicwkBAS0BBRhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMEDSR0MDE2ODA1MTY5NjgJAQ11cGRhdGVSZXNlcnZlAwUGX2lzQWRkBRFfcXVvdGVBc3NldEFtb3VudAUYYW1vdW50QmFzZUFzc2V0Qm91Z2h0QWJzBBdxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyMQgFDSR0MDE2ODA1MTY5NjgCXzEEFmJhc2VBc3NldFJlc2VydmVBZnRlcjEIBQ0kdDAxNjgwNTE2OTY4Al8yBBd0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyMQgFDSR0MDE2ODA1MTY5NjgCXzMEC3ByaWNlQmVmb3JlCQEEZGl2ZAIJAQRtdWxkAgUHX3F0QXN0UgUHX3F0QXN0VwkBBG11bGQCBQdfYnNBc3RSBQdfYnNBc3RXBAttYXJrZXRQcmljZQkBBGRpdmQCBRFfcXVvdGVBc3NldEFtb3VudAUYYW1vdW50QmFzZUFzc2V0Qm91Z2h0QWJzBAlwcmljZURpZmYJAQNhYnMBCQBlAgULcHJpY2VCZWZvcmUFC21hcmtldFByaWNlBAtwcmljZUltcGFjdAkAZQIFDERFQ0lNQUxfVU5JVAkBBGRpdmQCBQtwcmljZUJlZm9yZQkAZAIFC3ByaWNlQmVmb3JlBQlwcmljZURpZmYEE21heFByaWNlSW1wYWN0VmFsdWUJAQ5tYXhQcmljZUltcGFjdAADCQBmAgULcHJpY2VJbXBhY3QFE21heFByaWNlSW1wYWN0VmFsdWUJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICDVByaWNlIGltcGFjdCAJAKQDAQULcHJpY2VJbXBhY3QCFCA+IG1heCBwcmljZSBpbXBhY3QgCQCkAwEFE21heFByaWNlSW1wYWN0VmFsdWUCFSBiZWZvcmUgcXVvdGUgYXNzZXQ6IAkApAMBBQdfcXRBc3RSAhQgYmVmb3JlIGJhc2UgYXNzZXQ6IAkApAMBBQdfYnNBc3RSAiEgcXVvdGUgYXNzZXQgYW1vdW50IHRvIGV4Y2hhbmdlOiAJAKQDAQURX3F1b3RlQXNzZXRBbW91bnQCDyBwcmljZSBiZWZvcmU6IAkApAMBBQtwcmljZUJlZm9yZQIOIG1hcmtldFByaWNlOiAJAKQDAQULbWFya2V0UHJpY2UJAJYKBAUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0BRdxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyMQUWYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyMQUXdG90YWxQb3NpdGlvblNpemVBZnRlcjEBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEEF9vbGRQb3NpdGlvblNpemUSX29sZFBvc2l0aW9uTWFyZ2luJV9vbGRQb3NpdGlvbkN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24MX21hcmdpbkRlbHRhBA5mdW5kaW5nUGF5bWVudAMJAQIhPQIFEF9vbGRQb3NpdGlvblNpemUAAAQgX2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24JAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUQX29sZFBvc2l0aW9uU2l6ZQkBBG11bGQCCQBlAgUgX2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FJV9vbGRQb3NpdGlvbkN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FEF9vbGRQb3NpdGlvblNpemUAAAQMc2lnbmVkTWFyZ2luCQBkAgkAZQIFDF9tYXJnaW5EZWx0YQUOZnVuZGluZ1BheW1lbnQFEl9vbGRQb3NpdGlvbk1hcmdpbgQNJHQwMTg0NTUxODU4MgMJAGYCAAAFDHNpZ25lZE1hcmdpbgkAlAoCAAAJAQNhYnMBBQxzaWduZWRNYXJnaW4JAJQKAgkBA2FicwEFDHNpZ25lZE1hcmdpbgAABAxyZW1haW5NYXJnaW4IBQ0kdDAxODQ1NTE4NTgyAl8xBAdiYWREZWJ0CAUNJHQwMTg0NTUxODU4MgJfMgkAlQoDBQxyZW1haW5NYXJnaW4FB2JhZERlYnQFDmZ1bmRpbmdQYXltZW50ARZzd2FwT3V0cHV0V2l0aFJlc2VydmVzBwZfaXNBZGQQX2Jhc2VBc3NldEFtb3VudBRfY2hlY2tNYXhQcmljZUltcGFjdBJfcXVvdGVBc3NldFJlc2VydmURX3F1b3RlQXNzZXRXZWlnaHQRX2Jhc2VBc3NldFJlc2VydmUQX2Jhc2VBc3NldFdlaWdodAQLcHJpY2VCZWZvcmUJAQRkaXZkAgkBBG11bGQCBRJfcXVvdGVBc3NldFJlc2VydmUFEV9xdW90ZUFzc2V0V2VpZ2h0CQEEbXVsZAIFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0V2VpZ2h0AwkAAAIFEF9iYXNlQXNzZXRBbW91bnQAAAkAAgECGUludmFsaWQgYmFzZSBhc3NldCBhbW91bnQEAWsJAQ1jYWxjSW52YXJpYW50BAUSX3F1b3RlQXNzZXRSZXNlcnZlBRFfcXVvdGVBc3NldFdlaWdodAURX2Jhc2VBc3NldFJlc2VydmUFEF9iYXNlQXNzZXRXZWlnaHQEGGJhc2VBc3NldFBvb2xBbW91bnRBZnRlcgMFBl9pc0FkZAkAZAIFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0QW1vdW50CQBlAgURX2Jhc2VBc3NldFJlc2VydmUFEF9iYXNlQXNzZXRBbW91bnQED3F1b3RlQXNzZXRBZnRlcgkAoAMBCQEFYmRpdmQCBQFrCQC2AgEJAQRtdWxkAgUYYmFzZUFzc2V0UG9vbEFtb3VudEFmdGVyBRBfYmFzZUFzc2V0V2VpZ2h0BA5xdW90ZUFzc2V0U29sZAkBA2FicwEJAGUCBQ9xdW90ZUFzc2V0QWZ0ZXIJAQRtdWxkAgUSX3F1b3RlQXNzZXRSZXNlcnZlBRFfcXVvdGVBc3NldFdlaWdodAQTbWF4UHJpY2VJbXBhY3RWYWx1ZQkBDm1heFByaWNlSW1wYWN0AAQNJHQwMTk3NzAxOTkzMQkBDXVwZGF0ZVJlc2VydmUDCQEBIQEFBl9pc0FkZAUOcXVvdGVBc3NldFNvbGQFEF9iYXNlQXNzZXRBbW91bnQEF3F1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIxCAUNJHQwMTk3NzAxOTkzMQJfMQQWYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyMQgFDSR0MDE5NzcwMTk5MzECXzIEF3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIxCAUNJHQwMTk3NzAxOTkzMQJfMwQLbWFya2V0UHJpY2UJAQRkaXZkAgUOcXVvdGVBc3NldFNvbGQFEF9iYXNlQXNzZXRBbW91bnQECXByaWNlRGlmZgkBA2FicwEJAGUCBQtwcmljZUJlZm9yZQULbWFya2V0UHJpY2UEC3ByaWNlSW1wYWN0CQBlAgUMREVDSU1BTF9VTklUCQEEZGl2ZAIFC3ByaWNlQmVmb3JlCQBkAgULcHJpY2VCZWZvcmUFCXByaWNlRGlmZgMDCQBmAgULcHJpY2VJbXBhY3QFE21heFByaWNlSW1wYWN0VmFsdWUFFF9jaGVja01heFByaWNlSW1wYWN0BwkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgINUHJpY2UgaW1wYWN0IAkApAMBBQtwcmljZUltcGFjdAIUID4gbWF4IHByaWNlIGltcGFjdCAJAKQDAQUTbWF4UHJpY2VJbXBhY3RWYWx1ZQIVIGJlZm9yZSBxdW90ZSBhc3NldDogCQCkAwEFEl9xdW90ZUFzc2V0UmVzZXJ2ZQIUIGJlZm9yZSBiYXNlIGFzc2V0OiAJAKQDAQURX2Jhc2VBc3NldFJlc2VydmUCICBiYXNlIGFzc2V0IGFtb3VudCB0byBleGNoYW5nZTogCQCkAwEFEF9iYXNlQXNzZXRBbW91bnQCDyBwcmljZSBiZWZvcmU6IAkApAMBBQtwcmljZUJlZm9yZQIPIG1hcmtldCBwcmljZTogCQCkAwEFC21hcmtldFByaWNlCQCZCgcFDnF1b3RlQXNzZXRTb2xkBRdxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyMQUWYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyMQUXdG90YWxQb3NpdGlvblNpemVBZnRlcjEJAGUCCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAMFBl9pc0FkZAkBA2FicwEFEF9iYXNlQXNzZXRBbW91bnQAAAkAZQIJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAMJAQEhAQUGX2lzQWRkCQEDYWJzAQUQX2Jhc2VBc3NldEFtb3VudAAABQtwcmljZUltcGFjdAEKc3dhcE91dHB1dAMGX2lzQWRkEF9iYXNlQXNzZXRBbW91bnQUX2NoZWNrTWF4UHJpY2VJbXBhY3QJARZzd2FwT3V0cHV0V2l0aFJlc2VydmVzBwUGX2lzQWRkBRBfYmFzZUFzc2V0QW1vdW50BRRfY2hlY2tNYXhQcmljZUltcGFjdAkBBnF0QXN0UgAJAQZxdEFzdFcACQEGYnNBc3RSAAkBBmJzQXN0VwABDmdldE9yYWNsZVByaWNlAAQGb3JhY2xlCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgUEdGhpcwUFa19vcmECAAQIcHJpY2VLZXkJARFAZXh0ck5hdGl2ZSgxMDUzKQIFBHRoaXMFCWtfb3JhX2tleQQJbGFzdFZhbHVlCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUGb3JhY2xlBQhwcmljZUtleQkArAICCQCsAgIJAKwCAgIiQ2FuIG5vdCBnZXQgb3JhY2xlIHByaWNlLiBPcmFjbGU6IAkApQgBBQZvcmFjbGUCBiBrZXk6IAUIcHJpY2VLZXkECGJsb2NrS2V5CQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMFD2tfb3JhX2Jsb2NrX2tleQIAAwkBAiE9AgUIYmxvY2tLZXkCAAQMY3VycmVudEJsb2NrCAUJbGFzdEJsb2NrBmhlaWdodAQPbGFzdE9yYWNsZUJsb2NrCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUGb3JhY2xlBQhibG9ja0tleQkArAICCQCsAgIJAKwCAgIiQ2FuIG5vdCBnZXQgb3JhY2xlIGJsb2NrLiBPcmFjbGU6IAkApQgBBQZvcmFjbGUCBiBrZXk6IAUIYmxvY2tLZXkDCQBmAgkAZQIFDGN1cnJlbnRCbG9jawUPbGFzdE9yYWNsZUJsb2NrCQEObWF4T3JhY2xlRGVsYXkACQACAQkArAICCQCsAgIJAKwCAgImT3JhY2xlIHN0YWxlIGRhdGEuIExhc3Qgb3JhY2xlIGJsb2NrOiAJAKQDAQUPbGFzdE9yYWNsZUJsb2NrAhAgY3VycmVudCBibG9jazogCQCkAwEFDGN1cnJlbnRCbG9jawUJbGFzdFZhbHVlBQlsYXN0VmFsdWUBDmlzTWFya2V0Q2xvc2VkAAQGb3JhY2xlCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgUEdGhpcwUFa19vcmECAAQHb3BlbktleQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzBQ5rX29yYV9vcGVuX2tleQIAAwkBAiE9AgUHb3BlbktleQIABAZpc09wZW4JARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmwgCBQZvcmFjbGUFB29wZW5LZXkJAKwCAgkArAICCQCsAgICK0NhbiBub3QgZ2V0IG9yYWNsZSBpcyBvcGVuL2Nsb3NlZC4gT3JhY2xlOiAJAKUIAQUGb3JhY2xlAgYga2V5OiAFB29wZW5LZXkJAQEhAQUGaXNPcGVuBwEMYWJzUHJpY2VEaWZmBQxfb3JhY2xlUHJpY2USX3F1b3RlQXNzZXRSZXNlcnZlEV9iYXNlQXNzZXRSZXNlcnZlB19xdEFzdFcHX2JzQXN0VwQKcHJpY2VBZnRlcgkBBGRpdmQCCQEEbXVsZAIFEl9xdW90ZUFzc2V0UmVzZXJ2ZQUHX3F0QXN0VwkBBG11bGQCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUHX2JzQXN0VwQMYXZlcmFnZVByaWNlCQEEZGl2ZAIJAGQCBQxfb3JhY2xlUHJpY2UFCnByaWNlQWZ0ZXIJAGgCAAIFDERFQ0lNQUxfVU5JVAQMYWJzUHJpY2VEaWZmCQEEZGl2ZAIJAQNhYnMBCQBlAgUMX29yYWNsZVByaWNlBQpwcmljZUFmdGVyBQxhdmVyYWdlUHJpY2UFDGFic1ByaWNlRGlmZgEZcmVxdWlyZU5vdE92ZXJTcHJlYWRMaW1pdAISX3F1b3RlQXNzZXRSZXNlcnZlEV9iYXNlQXNzZXRSZXNlcnZlBAtvcmFjbGVQcmljZQkBDmdldE9yYWNsZVByaWNlAAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcABBJhYnNQcmljZURpZmZCZWZvcmUJAQxhYnNQcmljZURpZmYFBQtvcmFjbGVQcmljZQkBBnF0QXN0UgAJAQZic0FzdFIABQdfcXRBc3RXBQdfYnNBc3RXBBFhYnNQcmljZURpZmZBZnRlcgkBDGFic1ByaWNlRGlmZgUFC29yYWNsZVByaWNlBRJfcXVvdGVBc3NldFJlc2VydmUFEV9iYXNlQXNzZXRSZXNlcnZlBQdfcXRBc3RXBQdfYnNBc3RXAwMJAGYCBRFhYnNQcmljZURpZmZBZnRlcgkBDm1heFByaWNlU3ByZWFkAAkAZgIFEWFic1ByaWNlRGlmZkFmdGVyBRJhYnNQcmljZURpZmZCZWZvcmUHCQACAQkArAICCQCsAgIJAKwCAgINUHJpY2Ugc3ByZWFkIAkApAMBBRFhYnNQcmljZURpZmZBZnRlcgIUID4gbWF4IHByaWNlIHNwcmVhZCAJAKQDAQkBDm1heFByaWNlU3ByZWFkAAYBHXJlcXVpcmVOb3RPdmVyTWF4T3Blbk5vdGlvbmFsAhFfbG9uZ09wZW5Ob3Rpb25hbBJfc2hvcnRPcGVuTm90aW9uYWwEEF9tYXhPcGVuTm90aW9uYWwJAQ9tYXhPcGVuTm90aW9uYWwAAwkAZgIFEV9sb25nT3Blbk5vdGlvbmFsBRBfbWF4T3Blbk5vdGlvbmFsCQACAQkArAICCQCsAgIJAKwCAgITTG9uZyBvcGVuIG5vdGlvbmFsIAkApAMBBRFfbG9uZ09wZW5Ob3Rpb25hbAIVID4gbWF4IG9wZW4gbm90aW9uYWwgCQCkAwEFEF9tYXhPcGVuTm90aW9uYWwDCQBmAgUSX3Nob3J0T3Blbk5vdGlvbmFsBRBfbWF4T3Blbk5vdGlvbmFsCQACAQkArAICCQCsAgIJAKwCAgIUU2hvcnQgb3BlbiBub3Rpb25hbCAJAKQDAQUSX3Nob3J0T3Blbk5vdGlvbmFsAhUgPiBtYXggb3BlbiBub3Rpb25hbCAJAKQDAQUQX21heE9wZW5Ob3Rpb25hbAYBDGdldFNwb3RQcmljZQAEEl9xdW90ZUFzc2V0UmVzZXJ2ZQkBBnF0QXN0UgAEEV9iYXNlQXNzZXRSZXNlcnZlCQEGYnNBc3RSAAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcACQEEZGl2ZAIJAQRtdWxkAgUSX3F1b3RlQXNzZXRSZXNlcnZlBQdfcXRBc3RXCQEEbXVsZAIFEV9iYXNlQXNzZXRSZXNlcnZlBQdfYnNBc3RXARZpc092ZXJGbHVjdHVhdGlvbkxpbWl0AAQLb3JhY2xlUHJpY2UJAQ5nZXRPcmFjbGVQcmljZQAEDGN1cnJlbnRQcmljZQkBDGdldFNwb3RQcmljZQAJAGYCCQEEZGl2ZAIJAQNhYnMBCQBlAgULb3JhY2xlUHJpY2UFDGN1cnJlbnRQcmljZQULb3JhY2xlUHJpY2UJAQtzcHJlYWRMaW1pdAABH2dldFBvc2l0aW9uQWRqdXN0ZWRPcGVuTm90aW9uYWwGDV9wb3NpdGlvblNpemUHX29wdGlvbhJfcXVvdGVBc3NldFJlc2VydmURX3F1b3RlQXNzZXRXZWlnaHQRX2Jhc2VBc3NldFJlc2VydmUQX2Jhc2VBc3NldFdlaWdodAQPcG9zaXRpb25TaXplQWJzCQEDYWJzAQUNX3Bvc2l0aW9uU2l6ZQQHaXNTaG9ydAkAZgIAAAUNX3Bvc2l0aW9uU2l6ZQQQcG9zaXRpb25Ob3Rpb25hbAMJAAACBQdfb3B0aW9uBQ9QTkxfT1BUSU9OX1NQT1QEDSR0MDI0ODgyMjUxMDIJARZzd2FwT3V0cHV0V2l0aFJlc2VydmVzBwkBASEBBQdpc1Nob3J0BQ9wb3NpdGlvblNpemVBYnMHBRJfcXVvdGVBc3NldFJlc2VydmUFEV9xdW90ZUFzc2V0V2VpZ2h0BRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldFdlaWdodAQTb3V0UG9zaXRpb25Ob3Rpb25hbAgFDSR0MDI0ODgyMjUxMDICXzEEAngxCAUNJHQwMjQ4ODIyNTEwMgJfMgQCeDIIBQ0kdDAyNDg4MjI1MTAyAl8zBAJ4MwgFDSR0MDI0ODgyMjUxMDICXzQFE291dFBvc2l0aW9uTm90aW9uYWwJAQRtdWxkAgUPcG9zaXRpb25TaXplQWJzCQEOZ2V0T3JhY2xlUHJpY2UABRBwb3NpdGlvbk5vdGlvbmFsAStnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubEJ5VmFsdWVzBw1fcG9zaXRpb25TaXplFV9wb3NpdGlvbk9wZW5Ob3Rpb25hbBJfcXVvdGVBc3NldFJlc2VydmURX3F1b3RlQXNzZXRXZWlnaHQRX2Jhc2VBc3NldFJlc2VydmUQX2Jhc2VBc3NldFdlaWdodAdfb3B0aW9uAwkAAAIFDV9wb3NpdGlvblNpemUAAAkAAgECFUludmFsaWQgcG9zaXRpb24gc2l6ZQQHaXNTaG9ydAkAZgIAAAUNX3Bvc2l0aW9uU2l6ZQQQcG9zaXRpb25Ob3Rpb25hbAkBH2dldFBvc2l0aW9uQWRqdXN0ZWRPcGVuTm90aW9uYWwGBQ1fcG9zaXRpb25TaXplBQdfb3B0aW9uBRJfcXVvdGVBc3NldFJlc2VydmUFEV9xdW90ZUFzc2V0V2VpZ2h0BRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldFdlaWdodAQNdW5yZWFsaXplZFBubAMFB2lzU2hvcnQJAGUCBRVfcG9zaXRpb25PcGVuTm90aW9uYWwFEHBvc2l0aW9uTm90aW9uYWwJAGUCBRBwb3NpdGlvbk5vdGlvbmFsBRVfcG9zaXRpb25PcGVuTm90aW9uYWwJAJQKAgUQcG9zaXRpb25Ob3Rpb25hbAUNdW5yZWFsaXplZFBubAEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCB190cmFkZXIHX29wdGlvbgQNJHQwMjY1MjMyNjY1MQkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQMcG9zaXRpb25TaXplCAUNJHQwMjY1MjMyNjY1MQJfMQQOcG9zaXRpb25NYXJnaW4IBQ0kdDAyNjUyMzI2NjUxAl8yBBRwb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDI2NTIzMjY2NTECXzMEEXBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwMjY1MjMyNjY1MQJfNAkBK2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sQnlWYWx1ZXMHBQxwb3NpdGlvblNpemUFFHBvc2l0aW9uT3Blbk5vdGlvbmFsCQEGcXRBc3RSAAkBBnF0QXN0VwAJAQZic0FzdFIACQEGYnNBc3RXAAUHX29wdGlvbgEPY2FsY01hcmdpblJhdGlvAw1fcmVtYWluTWFyZ2luCF9iYWREZWJ0EV9wb3NpdGlvbk5vdGlvbmFsCQEEZGl2ZAIJAGUCBQ1fcmVtYWluTWFyZ2luBQhfYmFkRGVidAURX3Bvc2l0aW9uTm90aW9uYWwBFmdldE1hcmdpblJhdGlvQnlPcHRpb24CB190cmFkZXIHX29wdGlvbgQNJHQwMjcxNjQyNzI3NQkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQMcG9zaXRpb25TaXplCAUNJHQwMjcxNjQyNzI3NQJfMQQOcG9zaXRpb25NYXJnaW4IBQ0kdDAyNzE2NDI3Mjc1Al8yBANwb24IBQ0kdDAyNzE2NDI3Mjc1Al8zBBFwb3NpdGlvbkxzdFVwZENQRggFDSR0MDI3MTY0MjcyNzUCXzQEDSR0MDI3MjgxMjczNzQJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIFB190cmFkZXIFB19vcHRpb24EEHBvc2l0aW9uTm90aW9uYWwIBQ0kdDAyNzI4MTI3Mzc0Al8xBA11bnJlYWxpemVkUG5sCAUNJHQwMjcyODEyNzM3NAJfMgQNJHQwMjczNzkyNzU0NQkBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEBQxwb3NpdGlvblNpemUFDnBvc2l0aW9uTWFyZ2luBRFwb3NpdGlvbkxzdFVwZENQRgUNdW5yZWFsaXplZFBubAQMcmVtYWluTWFyZ2luCAUNJHQwMjczNzkyNzU0NQJfMQQHYmFkRGVidAgFDSR0MDI3Mzc5Mjc1NDUCXzIJAQ9jYWxjTWFyZ2luUmF0aW8DBQxyZW1haW5NYXJnaW4FB2JhZERlYnQFEHBvc2l0aW9uTm90aW9uYWwBDmdldE1hcmdpblJhdGlvAQdfdHJhZGVyCQEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAEbZ2V0UGFydGlhbExpcXVpZGF0aW9uQW1vdW50AgdfdHJhZGVyDV9wb3NpdGlvblNpemUEDG1heGltdW1SYXRpbwkBBHZtYXgCCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8ACQBlAgUMREVDSU1BTF9VTklUCQEEZGl2ZAIJAQ5nZXRNYXJnaW5SYXRpbwEFB190cmFkZXIJARZtYWludGVuYW5jZU1hcmdpblJhdGlvAAQYbWF4RXhjaGFuZ2VkUG9zaXRpb25TaXplCQEEbXVsZAIJAQNhYnMBBQ1fcG9zaXRpb25TaXplBQxtYXhpbXVtUmF0aW8ECnN3YXBSZXN1bHQJAQpzd2FwT3V0cHV0AwkAZgIFDV9wb3NpdGlvblNpemUAAAUYbWF4RXhjaGFuZ2VkUG9zaXRpb25TaXplBwQcbWF4RXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAgFCnN3YXBSZXN1bHQCXzEEC3ByaWNlSW1wYWN0CAUKc3dhcFJlc3VsdAJfNwMJAGYCCQEObWF4UHJpY2VJbXBhY3QABQtwcmljZUltcGFjdAUcbWF4RXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAQVZXhjaGFuZ2VkUG9zaXRpb25TaXplCQEEbXVsZAIJAQNhYnMBBQ1fcG9zaXRpb25TaXplCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8ABBlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CAkBCnN3YXBPdXRwdXQDCQBmAgUNX3Bvc2l0aW9uU2l6ZQAABRVleGNoYW5nZWRQb3NpdGlvblNpemUHAl8xBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50ARVpbnRlcm5hbENsb3NlUG9zaXRpb24CB190cmFkZXIUX2NoZWNrTWF4UHJpY2VJbXBhY3QEDSR0MDI4Nzg1Mjg5MTMJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIEDHBvc2l0aW9uU2l6ZQgFDSR0MDI4Nzg1Mjg5MTMCXzEEDnBvc2l0aW9uTWFyZ2luCAUNJHQwMjg3ODUyODkxMwJfMgQUcG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDAyODc4NTI4OTEzAl8zBBFwb3NpdGlvbkxzdFVwZENQRggFDSR0MDI4Nzg1Mjg5MTMCXzQEDXVucmVhbGl6ZWRQbmwICQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QCXzIEDSR0MDI5MDA4MjkxNzYJASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BAUMcG9zaXRpb25TaXplBQ5wb3NpdGlvbk1hcmdpbgURcG9zaXRpb25Mc3RVcGRDUEYFDXVucmVhbGl6ZWRQbmwEDHJlbWFpbk1hcmdpbggFDSR0MDI5MDA4MjkxNzYCXzEEB2JhZERlYnQIBQ0kdDAyOTAwODI5MTc2Al8yBBVleGNoYW5nZWRQb3NpdGlvblNpemUJAQEtAQUMcG9zaXRpb25TaXplBAtyZWFsaXplZFBubAUNdW5yZWFsaXplZFBubAQNbWFyZ2luVG9WYXVsdAkBAS0BBQxyZW1haW5NYXJnaW4EDSR0MDI5MzAzMjk1NzcJAQpzd2FwT3V0cHV0AwkAZgIFDHBvc2l0aW9uU2l6ZQAACQEDYWJzAQUMcG9zaXRpb25TaXplBRRfY2hlY2tNYXhQcmljZUltcGFjdAQZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAgFDSR0MDI5MzAzMjk1NzcCXzEEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDAyOTMwMzI5NTc3Al8yBBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDAyOTMwMzI5NTc3Al8zBBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwMjkzMDMyOTU3NwJfNAQOdG90YWxMb25nQWZ0ZXIIBQ0kdDAyOTMwMzI5NTc3Al81BA90b3RhbFNob3J0QWZ0ZXIIBQ0kdDAyOTMwMzI5NTc3Al82BBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCQBlAgkBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAAUUcG9zaXRpb25PcGVuTm90aW9uYWwJAJ8KDQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplBQdiYWREZWJ0BQtyZWFsaXplZFBubAUNbWFyZ2luVG9WYXVsdAUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyCQBlAgkBEG9wZW5JbnRlcmVzdExvbmcAAwkAZgIFDHBvc2l0aW9uU2l6ZQAABRRwb3NpdGlvbk9wZW5Ob3Rpb25hbAAACQBlAgkBEW9wZW5JbnRlcmVzdFNob3J0AAMJAGYCAAAFDHBvc2l0aW9uU2l6ZQUUcG9zaXRpb25PcGVuTm90aW9uYWwAAAEQZ2V0VHdhcFNwb3RQcmljZQAECG1pbnV0ZUlkCQBpAgkAaQIIBQlsYXN0QmxvY2sJdGltZXN0YW1wAOgHADwEDXN0YXJ0TWludXRlSWQJAGUCBQhtaW51dGVJZAUNVFdBUF9JTlRFUlZBTAQHbGlzdFN0cgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzBQ1rX2xhc3REYXRhU3RyAgAEBGxpc3QJALUJAgUHbGlzdFN0cgIBLAoBCGZpbHRlckZuAgthY2N1bXVsYXRvcgRuZXh0AwkAZwIFDXN0YXJ0TWludXRlSWQJAQ1wYXJzZUludFZhbHVlAQUEbmV4dAkAzQgCBQthY2N1bXVsYXRvcgkBDXBhcnNlSW50VmFsdWUBBQRuZXh0BQthY2N1bXVsYXRvcgQFbGlzdEYKAAIkbAUEbGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEIZmlsdGVyRm4CBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDIwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAA0ADgAPABAAEQASABMAFAQIbWF4SW5kZXgDCQBmAgkAkAMBBQVsaXN0RgAACQCWAwEFBWxpc3RGCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUEbGlzdAAABAxsYXN0TWludXRlSWQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUOa19sYXN0TWludXRlSWQAAAQWZW5kTGFzdEN1bXVsYXRpdmVQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UCAV8JAKQDAQUMbGFzdE1pbnV0ZUlkAAAEDGVuZExhc3RQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUTa190d2FwRGF0YUxhc3RQcmljZQIBXwkApAMBBQxsYXN0TWludXRlSWQAAAQSbm93Q3VtdWxhdGl2ZVByaWNlCQBkAgUWZW5kTGFzdEN1bXVsYXRpdmVQcmljZQkAaAIJAGUCBQhtaW51dGVJZAUMbGFzdE1pbnV0ZUlkBQxlbmRMYXN0UHJpY2UEGHN0YXJ0TGFzdEN1bXVsYXRpdmVQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UCAV8JAKQDAQUIbWF4SW5kZXgAAAQOc3RhcnRMYXN0UHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkArAICCQCsAgIFE2tfdHdhcERhdGFMYXN0UHJpY2UCAV8JAKQDAQUIbWF4SW5kZXgAAAQUc3RhcnRDdW11bGF0aXZlUHJpY2UJAGQCBRhzdGFydExhc3RDdW11bGF0aXZlUHJpY2UJAGgCCQBlAgUNc3RhcnRNaW51dGVJZAUIbWF4SW5kZXgFDnN0YXJ0TGFzdFByaWNlCQBpAgkAZQIFEm5vd0N1bXVsYXRpdmVQcmljZQUUc3RhcnRDdW11bGF0aXZlUHJpY2UFDVRXQVBfSU5URVJWQUwBE2dldFRlcm1pbmFsQW1tU3RhdGUABA1fcG9zaXRpb25TaXplCQERdG90YWxQb3NpdGlvblNpemUAAwkAAAIFDV9wb3NpdGlvblNpemUAAAkAlAoCCQEGcXRBc3RSAAkBBmJzQXN0UgAECWRpcmVjdGlvbgkAZgIFDV9wb3NpdGlvblNpemUAAAQNJHQwMzE3MDAzMTg3OQkBCnN3YXBPdXRwdXQDBQlkaXJlY3Rpb24JAQNhYnMBBQ1fcG9zaXRpb25TaXplBwQVY3VycmVudE5ldE1hcmtldFZhbHVlCAUNJHQwMzE3MDAzMTg3OQJfMQQZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQgFDSR0MDMxNzAwMzE4NzkCXzIEGHRlcm1pbmFsQmFzZUFzc2V0UmVzZXJ2ZQgFDSR0MDMxNzAwMzE4NzkCXzMJAJQKAgUZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQUYdGVybWluYWxCYXNlQXNzZXRSZXNlcnZlARNnZXRRdW90ZUFzc2V0V2VpZ2h0BBBiYXNlQXNzZXRSZXNlcnZlEXRvdGFsUG9zaXRpb25TaXplEXF1b3RlQXNzZXRSZXNlcnZlC3RhcmdldFByaWNlBAFiCQC2AgEFEGJhc2VBc3NldFJlc2VydmUEAnN6CQC2AgEFEXRvdGFsUG9zaXRpb25TaXplBAFxCQC2AgEFEXF1b3RlQXNzZXRSZXNlcnZlBAFwCQC2AgEFC3RhcmdldFByaWNlBANiczIJAQVicG93ZAIJALcCAgUBYgUCc3oJALYCAQkAaAIAAgUMREVDSU1BTF9VTklUBARxYnMyCQEFYm11bGQCBQFxBQNiczIEA3BzNAkAuQICCQC2AgEABAkBBWJtdWxkAgUBcAUCc3oEA3NxcgkBBmJzcXJ0ZAEJAQVibXVsZAIFBHFiczIJALgCAgUBcQUDcHM0BAJicQkBBWJtdWxkAgUBYgUBcQQCcXMJAQVibXVsZAIFAXEFAnN6BAN0b3AJALcCAgkAtwICCQC+AgEFA3NxcgUCYnEFAnFzBANib3QJALkCAgkAtgIBAAIJAQVibXVsZAIFAXEFAnN6BAZyZXN1bHQJAQViZGl2ZAIFA3RvcAUDYm90CQCgAwEFBnJlc3VsdAEUZ2V0U3luY1Rlcm1pbmFsUHJpY2UDDl90ZXJtaW5hbFByaWNlB19xdEFzdFIHX2JzQXN0UgQNX3Bvc2l0aW9uU2l6ZQkBEXRvdGFsUG9zaXRpb25TaXplAAMJAAACBQ1fcG9zaXRpb25TaXplAAAECW5ld1F0QXN0VwkBBGRpdmQCCQEEbXVsZAIFDl90ZXJtaW5hbFByaWNlBQdfYnNBc3RSBQdfcXRBc3RSCQCVCgMFCW5ld1F0QXN0VwUMREVDSU1BTF9VTklUAAAECWRpcmVjdGlvbgkAZgIFDV9wb3NpdGlvblNpemUAAAQVY3VycmVudE5ldE1hcmtldFZhbHVlCAkBCnN3YXBPdXRwdXQDBQlkaXJlY3Rpb24JAQNhYnMBBQ1fcG9zaXRpb25TaXplBwJfMQQJbmV3UXRBc3RXCQETZ2V0UXVvdGVBc3NldFdlaWdodAQFB19ic0FzdFIFDV9wb3NpdGlvblNpemUFB19xdEFzdFIFDl90ZXJtaW5hbFByaWNlBAluZXdCc0FzdFcFDERFQ0lNQUxfVU5JVAQNbWFyZ2luVG9WYXVsdAgJAStnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubEJ5VmFsdWVzBwUNX3Bvc2l0aW9uU2l6ZQUVY3VycmVudE5ldE1hcmtldFZhbHVlBQdfcXRBc3RSBQluZXdRdEFzdFcFB19ic0FzdFIFCW5ld0JzQXN0VwUPUE5MX09QVElPTl9TUE9UAl8yCQCVCgMFCW5ld1F0QXN0VwUJbmV3QnNBc3RXBQ1tYXJnaW5Ub1ZhdWx0AQpnZXRGdW5kaW5nAAQPdW5kZXJseWluZ1ByaWNlCQEOZ2V0T3JhY2xlUHJpY2UABA1zcG90VHdhcFByaWNlCQEQZ2V0VHdhcFNwb3RQcmljZQAEB3ByZW1pdW0JAGUCBQ1zcG90VHdhcFByaWNlBQ91bmRlcmx5aW5nUHJpY2UDAwMJAAACCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAAAAYJAAACCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAAABgkBDmlzTWFya2V0Q2xvc2VkAAkAlAoCAAAAAAMJAGYCAAAFB3ByZW1pdW0EFHNob3J0UHJlbWl1bUZyYWN0aW9uCQEEZGl2ZAIJAQRtdWxkAgUHcHJlbWl1bQkBFGZ1bmRpbmdQZXJpb2REZWNpbWFsAAUHT05FX0RBWQQTbG9uZ1ByZW1pdW1GcmFjdGlvbgkBBGRpdmQCCQEEbXVsZAIFFHNob3J0UHJlbWl1bUZyYWN0aW9uCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAJARV0b3RhbExvbmdQb3NpdGlvblNpemUACQCUCgIFFHNob3J0UHJlbWl1bUZyYWN0aW9uBRNsb25nUHJlbWl1bUZyYWN0aW9uBBNsb25nUHJlbWl1bUZyYWN0aW9uCQEEZGl2ZAIJAQRtdWxkAgUHcHJlbWl1bQkBFGZ1bmRpbmdQZXJpb2REZWNpbWFsAAUHT05FX0RBWQQUc2hvcnRQcmVtaXVtRnJhY3Rpb24JAQRkaXZkAgkBBG11bGQCBRNsb25nUHJlbWl1bUZyYWN0aW9uCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUACQCUCgIFFHNob3J0UHJlbWl1bUZyYWN0aW9uBRNsb25nUHJlbWl1bUZyYWN0aW9uAQ5nZXRBZGp1c3RlZEZlZQILX2FydGlmYWN0SWQQX2Jhc2VGZWVEaXNjb3VudAQKYmFzZUZlZVJhdwkBA2ZlZQAEB2Jhc2VGZWUJAQRtdWxkAgUKYmFzZUZlZVJhdwUQX2Jhc2VGZWVEaXNjb3VudAQNJHQwMzQ5MjczNTQyMgMJAQIhPQIFC19hcnRpZmFjdElkAgAEDGFydGlmYWN0S2luZAkBBHN0ckECCQERbmZ0TWFuYWdlckFkZHJlc3MACQEOdG9Db21wb3NpdGVLZXkCBQxrX3Rva2VuX3R5cGUFC19hcnRpZmFjdElkAwkAAAIFDGFydGlmYWN0S2luZAUYRkVFX1JFRFVDVElPTl9UT0tFTl9UWVBFBAlyZWR1Y3Rpb24JAQRpbnRBAgkBEW5mdE1hbmFnZXJBZGRyZXNzAAkBDnRvQ29tcG9zaXRlS2V5AgUNa190b2tlbl9wYXJhbQULX2FydGlmYWN0SWQEC2FkanVzdGVkRmVlCQEEbXVsZAIFB2Jhc2VGZWUFCXJlZHVjdGlvbgkAlAoCBQthZGp1c3RlZEZlZQYJAAIBAhlJbnZhbGlkIGF0dGFjaGVkIGFydGlmYWN0CQCUCgIFB2Jhc2VGZWUHBAthZGp1c3RlZEZlZQgFDSR0MDM0OTI3MzU0MjICXzEEDGJ1cm5BcnRpZmFjdAgFDSR0MDM0OTI3MzU0MjICXzIJAJQKAgULYWRqdXN0ZWRGZWUFDGJ1cm5BcnRpZmFjdAEXaXNTYW1lQXNzZXRPck5vUG9zaXRpb24CB190cmFkZXIIX2Fzc2V0SWQED29sZFBvc2l0aW9uU2l6ZQgJAQtnZXRQb3NpdGlvbgEFB190cmFkZXICXzEDCQAAAgUPb2xkUG9zaXRpb25TaXplAAAGCQAAAgkBEGdldFBvc2l0aW9uQXNzZXQBBQdfdHJhZGVyBQhfYXNzZXRJZAELaXNTYW1lQXNzZXQCB190cmFkZXIIX2Fzc2V0SWQJAAACCQEQZ2V0UG9zaXRpb25Bc3NldAEFB190cmFkZXIFCF9hc3NldElkAR5nZXRCb3Jyb3dlZEJ5VHJhZGVySW5NYXJrZXRLZXkDBF9hbW0IX2Fzc2V0SWQHX3RyYWRlcgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgUga190cmFkZXJfbWFya2V0X2Fzc2V0X2NvbGxhdGVyYWwCAV8FBF9hbW0CAV8FCF9hc3NldElkAgFfBQdfdHJhZGVyARNnZXRCb3Jyb3dlZEJ5VHJhZGVyAQdfdHJhZGVyBA1wb3NpdGlvbkFzc2V0CQEQZ2V0UG9zaXRpb25Bc3NldAEFB190cmFkZXIDCQAAAgUNcG9zaXRpb25Bc3NldAkA2AQBCQEKcXVvdGVBc3NldAAJAJQKAgAABQ1wb3NpdGlvbkFzc2V0BANrZXkJAR5nZXRCb3Jyb3dlZEJ5VHJhZGVySW5NYXJrZXRLZXkDCQClCAEFBHRoaXMFDXBvc2l0aW9uQXNzZXQFB190cmFkZXIEBmJvcnJvdwkBC3ZhbHVlT3JFbHNlAgkAmggCCQERY29sbGF0ZXJhbEFkZHJlc3MABQNrZXkAAAkAlAoCBQZib3Jyb3cFDXBvc2l0aW9uQXNzZXQBGGdldEZvclRyYWRlcldpdGhBcnRpZmFjdAIHX3RyYWRlcgtfYXJ0aWZhY3RJZAQQZG9HZXRGZWVEaXNjb3VudAkA/AcECQEMbWluZXJBZGRyZXNzAAISY29tcHV0ZUZlZURpc2NvdW50CQDMCAIFB190cmFkZXIFA25pbAUDbmlsAwkAAAIFEGRvR2V0RmVlRGlzY291bnQFEGRvR2V0RmVlRGlzY291bnQEC2ZlZURpc2NvdW50BAckbWF0Y2gwBRBkb0dldEZlZURpc2NvdW50AwkAAQIFByRtYXRjaDACA0ludAQBeAUHJG1hdGNoMAUBeAkAAgECIUludmFsaWQgY29tcHV0ZUZlZURpc2NvdW50IHJlc3VsdAQNJHQwMzY2NTMzNjcyNwkBDmdldEFkanVzdGVkRmVlAgULX2FydGlmYWN0SWQFC2ZlZURpc2NvdW50BAthZGp1c3RlZEZlZQgFDSR0MDM2NjUzMzY3MjcCXzEEDGJ1cm5BcnRpZmFjdAgFDSR0MDM2NjUzMzY3MjcCXzIJAJQKAgULYWRqdXN0ZWRGZWUFDGJ1cm5BcnRpZmFjdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgENZ2V0QXJ0aWZhY3RJZAEBaQQKYXJ0aWZhY3RJZAMJAGYCCQCQAwEIBQFpCHBheW1lbnRzAAEJANgEAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCAkAkQMCCAUBaQhwYXltZW50cwABB2Fzc2V0SWQCEkludmFsaWQgYXJ0aWZhY3RJZAIABQphcnRpZmFjdElkAQ1kaXN0cmlidXRlRmVlAQpfZmVlQW1vdW50BAxmZWVUb1N0YWtlcnMJAQRtdWxkAgUKX2ZlZUFtb3VudAkBE2ZlZVRvU3Rha2Vyc1BlcmNlbnQABApmZWVUb1ZhdWx0CQBlAgUKX2ZlZUFtb3VudAUMZmVlVG9TdGFrZXJzCQCUCgIFDGZlZVRvU3Rha2VycwUKZmVlVG9WYXVsdAEOdXBkYXRlU2V0dGluZ3MMEF9pbml0TWFyZ2luUmF0aW8EX21tchRfbGlxdWlkYXRpb25GZWVSYXRpbw5fZnVuZGluZ1BlcmlvZARfZmVlDF9zcHJlYWRMaW1pdA9fbWF4UHJpY2VJbXBhY3QYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvD19tYXhQcmljZVNwcmVhZBBfbWF4T3Blbk5vdGlvbmFsFF9mZWVUb1N0YWtlcnNQZXJjZW50D19tYXhPcmFjbGVEZWxheQkAzAgCCQEMSW50ZWdlckVudHJ5AgURa19pbml0TWFyZ2luUmF0aW8FEF9pbml0TWFyZ2luUmF0aW8JAMwIAgkBDEludGVnZXJFbnRyeQIFGGtfbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwUEX21tcgkAzAgCCQEMSW50ZWdlckVudHJ5AgUVa19saXF1aWRhdGlvbkZlZVJhdGlvBRRfbGlxdWlkYXRpb25GZWVSYXRpbwkAzAgCCQEMSW50ZWdlckVudHJ5AgUPa19mdW5kaW5nUGVyaW9kBQ5fZnVuZGluZ1BlcmlvZAkAzAgCCQEMSW50ZWdlckVudHJ5AgUFa19mZWUFBF9mZWUJAMwIAgkBDEludGVnZXJFbnRyeQIFDWtfc3ByZWFkTGltaXQFDF9zcHJlYWRMaW1pdAkAzAgCCQEMSW50ZWdlckVudHJ5AgUQa19tYXhQcmljZUltcGFjdAUPX21heFByaWNlSW1wYWN0CQDMCAIJAQxJbnRlZ2VyRW50cnkCBRlrX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvBRhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8JAMwIAgkBDEludGVnZXJFbnRyeQIFEGtfbWF4UHJpY2VTcHJlYWQFD19tYXhQcmljZVNwcmVhZAkAzAgCCQEMSW50ZWdlckVudHJ5AgURa19tYXhPcGVuTm90aW9uYWwFEF9tYXhPcGVuTm90aW9uYWwJAMwIAgkBDEludGVnZXJFbnRyeQIFFWtfZmVlVG9TdGFrZXJzUGVyY2VudAUUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQJAMwIAgkBDEludGVnZXJFbnRyeQIFEGtfbWF4T3JhY2xlRGVsYXkFFF9mZWVUb1N0YWtlcnNQZXJjZW50BQNuaWwBDXVwZGF0ZUZ1bmRpbmcFEV9uZXh0RnVuZGluZ0Jsb2NrJF9sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbiVfbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uEF9sb25nRnVuZGluZ1JhdGURX3Nob3J0RnVuZGluZ1JhdGUJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfbmV4dEZ1bmRpbmdCbG9jawURX25leHRGdW5kaW5nQmxvY2sJAMwIAgkBDEludGVnZXJFbnRyeQIFJWtfbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FJF9sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgUma19sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FJV9sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24JAMwIAgkBDEludGVnZXJFbnRyeQIFEWtfbG9uZ0Z1bmRpbmdSYXRlBRBfbG9uZ0Z1bmRpbmdSYXRlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJrX3Nob3J0RnVuZGluZ1JhdGUFEV9zaG9ydEZ1bmRpbmdSYXRlBQNuaWwBE3VwZGF0ZVBvc2l0aW9uQXNzZXQCCF9hZGRyZXNzCF9hc3NldElkCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFD2tfcG9zaXRpb25Bc3NldAUIX2FkZHJlc3MFCF9hc3NldElkBQNuaWwBH2luY3JlbWVudFBvc2l0aW9uU2VxdWVuY2VOdW1iZXICDWlzTmV3UG9zaXRpb24IX2FkZHJlc3MDBQ1pc05ld1Bvc2l0aW9uBA9jdXJyZW50U2VxdWVuY2UJAQxsYXN0U2VxdWVuY2UACQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRJrX3Bvc2l0aW9uU2VxdWVuY2UFCF9hZGRyZXNzCQBkAgUPY3VycmVudFNlcXVlbmNlAAEJAMwIAgkBDEludGVnZXJFbnRyeQIFCmtfc2VxdWVuY2UJAGQCBQ9jdXJyZW50U2VxdWVuY2UAAQUDbmlsBQNuaWwBDnVwZGF0ZVBvc2l0aW9uBQhfYWRkcmVzcwVfc2l6ZQdfbWFyZ2luDV9vcGVuTm90aW9uYWwgX2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24JAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFDmtfcG9zaXRpb25TaXplBQhfYWRkcmVzcwUFX3NpemUJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFEGtfcG9zaXRpb25NYXJnaW4FCF9hZGRyZXNzBQdfbWFyZ2luCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBQhfYWRkcmVzcwUNX29wZW5Ob3Rpb25hbAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUua19wb3NpdGlvbkxhc3RVcGRhdGVkQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUIX2FkZHJlc3MFIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBQNuaWwBCmFwcGVuZFR3YXABBl9wcmljZQQIbWludXRlSWQJAGkCCQBpAggFCWxhc3RCbG9jawl0aW1lc3RhbXAA6AcAPAQQcHJldmlvdXNNaW51dGVJZAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQ5rX2xhc3RNaW51dGVJZAAAAwkAZgIFEHByZXZpb3VzTWludXRlSWQFCG1pbnV0ZUlkCQACAQIRVFdBUCBvdXQtb2Ytb3JkZXIEDGxhc3RNaW51dGVJZAMJAAACBRBwcmV2aW91c01pbnV0ZUlkAAAFCG1pbnV0ZUlkBRBwcmV2aW91c01pbnV0ZUlkAwkAZgIFCG1pbnV0ZUlkBRBwcmV2aW91c01pbnV0ZUlkBBNwcmV2Q3VtdWxhdGl2ZVByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAKwCAgkArAICBR1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQIBXwkApAMBBRBwcmV2aW91c01pbnV0ZUlkAAAECXByZXZQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUTa190d2FwRGF0YUxhc3RQcmljZQIBXwkApAMBBRBwcmV2aW91c01pbnV0ZUlkBQZfcHJpY2UEE2xhc3RDdW11bGF0aXZlUHJpY2UJAGQCBRNwcmV2Q3VtdWxhdGl2ZVByaWNlCQBoAgkAZQIFCG1pbnV0ZUlkBQxsYXN0TWludXRlSWQFCXByZXZQcmljZQQEbGlzdAkBC3B1c2hUb1F1ZXVlAwkBCXN0clRvTGlzdAEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwUNa19sYXN0RGF0YVN0cgIABQ1UV0FQX0lOVEVSVkFMCQCkAwEFCG1pbnV0ZUlkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBR1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQkApAMBBQhtaW51dGVJZAUTbGFzdEN1bXVsYXRpdmVQcmljZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUTa190d2FwRGF0YUxhc3RQcmljZQkApAMBBQhtaW51dGVJZAUGX3ByaWNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRprX3R3YXBEYXRhUHJldmlvdXNNaW51dGVJZAkApAMBBQhtaW51dGVJZAUQcHJldmlvdXNNaW51dGVJZAkAzAgCCQEMSW50ZWdlckVudHJ5AgUOa19sYXN0TWludXRlSWQFCG1pbnV0ZUlkCQDMCAIJAQtTdHJpbmdFbnRyeQIFDWtfbGFzdERhdGFTdHIJAQlsaXN0VG9TdHIBBQRsaXN0BQNuaWwEGHR3YXBEYXRhUHJldmlvdXNNaW51dGVJZAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBRprX3R3YXBEYXRhUHJldmlvdXNNaW51dGVJZAkApAMBBQhtaW51dGVJZAAABBNwcmV2Q3VtdWxhdGl2ZVByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlCQCkAwEFGHR3YXBEYXRhUHJldmlvdXNNaW51dGVJZAAABAlwcmV2UHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUTa190d2FwRGF0YUxhc3RQcmljZQkApAMBBRh0d2FwRGF0YVByZXZpb3VzTWludXRlSWQFBl9wcmljZQQTbGFzdEN1bXVsYXRpdmVQcmljZQkAZAIFE3ByZXZDdW11bGF0aXZlUHJpY2UJAGgCCQBlAgUIbWludXRlSWQFGHR3YXBEYXRhUHJldmlvdXNNaW51dGVJZAUJcHJldlByaWNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBR1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQkApAMBBQhtaW51dGVJZAUTbGFzdEN1bXVsYXRpdmVQcmljZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUTa190d2FwRGF0YUxhc3RQcmljZQkApAMBBQhtaW51dGVJZAUGX3ByaWNlBQNuaWwBEXVwZGF0ZUFtbVJlc2VydmVzAgdfcXRBc3RSB19ic0FzdFIJAMwIAgkBDEludGVnZXJFbnRyeQIFE2tfcXVvdGVBc3NldFJlc2VydmUFB19xdEFzdFIJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfYmFzZUFzc2V0UmVzZXJ2ZQUHX2JzQXN0UgUDbmlsARB1cGRhdGVBbW1XZWlnaHRzAgdfcXRBc3RXB19ic0FzdFcJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfcXVvdGVBc3NldFdlaWdodAUHX3F0QXN0VwkAzAgCCQEMSW50ZWdlckVudHJ5AgURa19iYXNlQXNzZXRXZWlnaHQFB19ic0FzdFcFA25pbAEJdXBkYXRlQW1tCAdfcXRBc3RSB19ic0FzdFIXX3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIVX29wZW5JbnRlcmVzdE5vdGlvbmFsFl90b3RhbExvbmdQb3NpdGlvblNpemUXX3RvdGFsU2hvcnRQb3NpdGlvblNpemUWX3RvdGFsTG9uZ09wZW5Ob3Rpb25hbBdfdG90YWxTaG9ydE9wZW5Ob3Rpb25hbAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcAAwkBAiE9AgkAZQIFFl90b3RhbExvbmdQb3NpdGlvblNpemUFF190b3RhbFNob3J0UG9zaXRpb25TaXplBRdfdG90YWxQb3NpdGlvblNpemVBZnRlcgkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAhhJbnZhbGlkIEFNTSBzdGF0ZSBkYXRhOiAJAKQDAQUWX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQIEICsgIAkApAMBBRdfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQIEICE9IAkApAMBBRdfdG90YWxQb3NpdGlvblNpemVBZnRlcgkAzggCCQDOCAIJARF1cGRhdGVBbW1SZXNlcnZlcwIFB19xdEFzdFIFB19ic0FzdFIJAMwIAgkBDEludGVnZXJFbnRyeQIFE2tfdG90YWxQb3NpdGlvblNpemUFF190b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRZrX29wZW5JbnRlcmVzdE5vdGlvbmFsBRVfb3BlbkludGVyZXN0Tm90aW9uYWwJAMwIAgkBDEludGVnZXJFbnRyeQIFF2tfdG90YWxMb25nUG9zaXRpb25TaXplBRZfdG90YWxMb25nUG9zaXRpb25TaXplCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRhrX3RvdGFsU2hvcnRQb3NpdGlvblNpemUFF190b3RhbFNob3J0UG9zaXRpb25TaXplCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJrX29wZW5JbnRlcmVzdExvbmcFFl90b3RhbExvbmdPcGVuTm90aW9uYWwJAMwIAgkBDEludGVnZXJFbnRyeQIFE2tfb3BlbkludGVyZXN0U2hvcnQFF190b3RhbFNob3J0T3Blbk5vdGlvbmFsBQNuaWwJAQphcHBlbmRUd2FwAQkBBGRpdmQCCQEEbXVsZAIFB19xdEFzdFIFB19xdEFzdFcJAQRtdWxkAgUHX2JzQXN0UgUHX2JzQXN0VwEOZGVsZXRlUG9zaXRpb24BCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFDmtfcG9zaXRpb25TaXplBQhfYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBRBrX3Bvc2l0aW9uTWFyZ2luBQhfYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBRZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBQhfYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBS5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBQhfYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBQ9rX3Bvc2l0aW9uQXNzZXQFCF9hZGRyZXNzBQNuaWwBCHdpdGhkcmF3AghfYWRkcmVzcwdfYW1vdW50BAdiYWxhbmNlCQDwBwIFBHRoaXMJAQpxdW90ZUFzc2V0AAMJAGYCBQdfYW1vdW50BQdiYWxhbmNlCQACAQkArAICCQCsAgIJAKwCAgITVW5hYmxlIHRvIHdpdGhkcmF3IAkApAMBBQdfYW1vdW50AhcgZnJvbSBjb250cmFjdCBiYWxhbmNlIAkApAMBBQdiYWxhbmNlCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFCF9hZGRyZXNzBQdfYW1vdW50CQEKcXVvdGVBc3NldAAFA25pbAENdXBkYXRlQmFsYW5jZQEBaQMJAGYCAAAFAWkJAAIBAgdCYWxhbmNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQlrX2JhbGFuY2UFAWkFA25pbAELdHJhbnNmZXJGZWUBAWkJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwkBDnN0YWtpbmdBZGRyZXNzAAUBaQkBCnF1b3RlQXNzZXQABQNuaWwBDmRvQnVybkFydGlmYWN0Ag1fYnVybkFydGlmYWN0AWkDBQ1fYnVybkFydGlmYWN0CQDMCAIJAQRCdXJuAgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCAkAkQMCCAUBaQhwYXltZW50cwABB2Fzc2V0SWQCEEludmFsaWQgYXJ0aWZhY3QAAQUDbmlsBQNuaWwXAWkBBXBhdXNlAAMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAhRJbnZhbGlkIHBhdXNlIHBhcmFtcwkAzAgCCQEMQm9vbGVhbkVudHJ5AgUIa19wYXVzZWQGBQNuaWwBaQEHdW5wYXVzZQADCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MACQACAQIWSW52YWxpZCB1bnBhdXNlIHBhcmFtcwkAzAgCCQEMQm9vbGVhbkVudHJ5AgUIa19wYXVzZWQHBQNuaWwBaQEMc2V0Q2xvc2VPbmx5AAMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAhtJbnZhbGlkIHNldENsb3NlT25seSBwYXJhbXMJAMwIAgkBDEJvb2xlYW5FbnRyeQIFC2tfY2xvc2VPbmx5BgUDbmlsAWkBDnVuc2V0Q2xvc2VPbmx5AAMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAh1JbnZhbGlkIHVuc2V0Q2xvc2VPbmx5IHBhcmFtcwkAzAgCCQEMQm9vbGVhbkVudHJ5AgULa19jbG9zZU9ubHkHBQNuaWwBaQEMYWRkTGlxdWlkaXR5ARFfcXVvdGVBc3NldEFtb3VudAMDCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MABgkAZwIAAAURX3F1b3RlQXNzZXRBbW91bnQJAAIBAhtJbnZhbGlkIGFkZExpcXVpZGl0eSBwYXJhbXMEB19xdEFzdFIJAQZxdEFzdFIABAdfYnNBc3RSCQEGYnNBc3RSAAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcABAVwcmljZQkBBGRpdmQCCQEEbXVsZAIFB19xdEFzdFIFB19xdEFzdFcJAQRtdWxkAgUHX2JzQXN0UgUHX2JzQXN0VwQLcXRBc3RSQWZ0ZXIJAGQCBQdfcXRBc3RSBRFfcXVvdGVBc3NldEFtb3VudAQUYmFzZUFzc2V0QW1vdW50VG9BZGQJAGUCCQEEZGl2ZAIJAQRtdWxkAgULcXRBc3RSQWZ0ZXIFB19xdEFzdFcFBXByaWNlBQdfYnNBc3RSBAtic0FzdFJBZnRlcgkAZAIFB19ic0FzdFIFFGJhc2VBc3NldEFtb3VudFRvQWRkBA0kdDA0NTc0OTQ1OTAwCQEUZ2V0U3luY1Rlcm1pbmFsUHJpY2UDCQEOZ2V0T3JhY2xlUHJpY2UABQtxdEFzdFJBZnRlcgULYnNBc3RSQWZ0ZXIEE25ld1F1b3RlQXNzZXRXZWlnaHQIBQ0kdDA0NTc0OTQ1OTAwAl8xBBJuZXdCYXNlQXNzZXRXZWlnaHQIBQ0kdDA0NTc0OTQ1OTAwAl8yBA1tYXJnaW5Ub1ZhdWx0CAUNJHQwNDU3NDk0NTkwMAJfMwQNZG9FeGNoYW5nZVBuTAMJAQIhPQIFDW1hcmdpblRvVmF1bHQAAAQNZG9FeGNoYW5nZVBuTAkA/AcECQEMdmF1bHRBZGRyZXNzAAIVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkCQDMCAIFDW1hcmdpblRvVmF1bHQFA25pbAUDbmlsAwkAAAIFDWRvRXhjaGFuZ2VQbkwFDWRvRXhjaGFuZ2VQbkwFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFDWRvRXhjaGFuZ2VQbkwFDWRvRXhjaGFuZ2VQbkwJAM4IAgkBEXVwZGF0ZUFtbVJlc2VydmVzAgULcXRBc3RSQWZ0ZXIFC2JzQXN0UkFmdGVyCQEQdXBkYXRlQW1tV2VpZ2h0cwIFE25ld1F1b3RlQXNzZXRXZWlnaHQFEm5ld0Jhc2VBc3NldFdlaWdodAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ9yZW1vdmVMaXF1aWRpdHkBEV9xdW90ZUFzc2V0QW1vdW50AwMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAGCQBnAgAABRFfcXVvdGVBc3NldEFtb3VudAkAAgECHkludmFsaWQgcmVtb3ZlTGlxdWlkaXR5IHBhcmFtcwQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwAEBXByaWNlCQEEZGl2ZAIJAQRtdWxkAgUHX3F0QXN0UgUHX3F0QXN0VwkBBG11bGQCBQdfYnNBc3RSBQdfYnNBc3RXBBdiYXNlQXNzZXRBbW91bnRUb1JlbW92ZQkBBGRpdmQCBRFfcXVvdGVBc3NldEFtb3VudAUFcHJpY2UEC3F0QXN0UkFmdGVyCQBlAgUHX3F0QXN0UgURX3F1b3RlQXNzZXRBbW91bnQEC2JzQXN0UkFmdGVyCQBlAgUHX2JzQXN0UgUXYmFzZUFzc2V0QW1vdW50VG9SZW1vdmUJARF1cGRhdGVBbW1SZXNlcnZlcwIFC3F0QXN0UkFmdGVyBQtic0FzdFJBZnRlcgFpAQ5jaGFuZ2VTZXR0aW5ncwwQX2luaXRNYXJnaW5SYXRpbwRfbW1yFF9saXF1aWRhdGlvbkZlZVJhdGlvDl9mdW5kaW5nUGVyaW9kBF9mZWUMX3NwcmVhZExpbWl0D19tYXhQcmljZUltcGFjdBhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8PX21heFByaWNlU3ByZWFkEF9tYXhPcGVuTm90aW9uYWwUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQPX21heE9yYWNsZURlbGF5AwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECHUludmFsaWQgY2hhbmdlU2V0dGluZ3MgcGFyYW1zCQEOdXBkYXRlU2V0dGluZ3MMBRBfaW5pdE1hcmdpblJhdGlvBQRfbW1yBRRfbGlxdWlkYXRpb25GZWVSYXRpbwUOX2Z1bmRpbmdQZXJpb2QFBF9mZWUFDF9zcHJlYWRMaW1pdAUPX21heFByaWNlSW1wYWN0BRhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8FD19tYXhQcmljZVNwcmVhZAUQX21heE9wZW5Ob3Rpb25hbAUUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQFD19tYXhPcmFjbGVEZWxheQFpAQppbml0aWFsaXplEgdfcXRBc3RSB19ic0FzdFIOX2Z1bmRpbmdQZXJpb2QQX2luaXRNYXJnaW5SYXRpbwRfbW1yFF9saXF1aWRhdGlvbkZlZVJhdGlvBF9mZWUHX29yYWNsZQpfb3JhY2xlS2V5D19vcmFjbGVCbG9ja0tleQxfY29vcmRpbmF0b3IMX3NwcmVhZExpbWl0D19tYXhQcmljZUltcGFjdBhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8PX21heFByaWNlU3ByZWFkEF9tYXhPcGVuTm90aW9uYWwUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQPX21heE9yYWNsZURlbGF5AwMDAwMDAwMDAwMDAwMDAwkAZwIAAAUHX3F0QXN0UgYJAGcCAAAFB19ic0FzdFIGCQBnAgAABQ5fZnVuZGluZ1BlcmlvZAYJAGcCAAAFEF9pbml0TWFyZ2luUmF0aW8GCQBnAgAABQRfbW1yBgkAZwIAAAUUX2xpcXVpZGF0aW9uRmVlUmF0aW8GCQBnAgAABQRfZmVlBgkAZwIAAAUMX3NwcmVhZExpbWl0BgkAZwIAAAUPX21heFByaWNlSW1wYWN0BgkAZwIAAAUYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvBgkAZwIAAAUPX21heFByaWNlU3ByZWFkBgkAZwIAAAUQX21heE9wZW5Ob3Rpb25hbAYJAGcCAAAFFF9mZWVUb1N0YWtlcnNQZXJjZW50BgkAZgIFFF9mZWVUb1N0YWtlcnNQZXJjZW50BQxERUNJTUFMX1VOSVQGCQBnAgAABQ9fbWF4T3JhY2xlRGVsYXkGCQELaW5pdGlhbGl6ZWQACQACAQIdSW52YWxpZCBpbml0aWFsaXplIHBhcmFtZXRlcnMJAM4IAgkAzggCCQDOCAIJAM4IAgkBCXVwZGF0ZUFtbQgFB19xdEFzdFIFB19ic0FzdFIAAAAAAAAAAAAAAAAJAQ51cGRhdGVTZXR0aW5ncwwFEF9pbml0TWFyZ2luUmF0aW8FBF9tbXIFFF9saXF1aWRhdGlvbkZlZVJhdGlvBQ5fZnVuZGluZ1BlcmlvZAUEX2ZlZQUMX3NwcmVhZExpbWl0BQ9fbWF4UHJpY2VJbXBhY3QFGF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwUPX21heFByaWNlU3ByZWFkBRBfbWF4T3Blbk5vdGlvbmFsBRRfZmVlVG9TdGFrZXJzUGVyY2VudAUPX21heE9yYWNsZURlbGF5CQENdXBkYXRlRnVuZGluZwUJAGQCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAUOX2Z1bmRpbmdQZXJpb2QAAAAAAAAAAAkBDXVwZGF0ZUJhbGFuY2UBAAAJAMwIAgkBDEJvb2xlYW5FbnRyeQIFDWtfaW5pdGlhbGl6ZWQGCQDMCAIJAQtTdHJpbmdFbnRyeQIFBWtfb3JhBQdfb3JhY2xlCQDMCAIJAQtTdHJpbmdFbnRyeQIFCWtfb3JhX2tleQUKX29yYWNsZUtleQkAzAgCCQELU3RyaW5nRW50cnkCBQ9rX29yYV9ibG9ja19rZXkFD19vcmFjbGVCbG9ja0tleQkAzAgCCQELU3RyaW5nRW50cnkCBRRrX2Nvb3JkaW5hdG9yQWRkcmVzcwUMX2Nvb3JkaW5hdG9yBQNuaWwBaQEQZGVjcmVhc2VQb3NpdGlvbgMHX2Ftb3VudAlfbGV2ZXJhZ2UTX21pbkJhc2VBc3NldEFtb3VudAQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBAdfdHJhZGVyCQEPZ2V0QWN0dWFsQ2FsbGVyAQUBaQMDAwMDAwkAZwIAAAUHX2Ftb3VudAYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQEhAQkBFnJlcXVpcmVNb3JlTWFyZ2luUmF0aW8DCQEEZGl2ZAIFDERFQ0lNQUxfVU5JVAUJX2xldmVyYWdlCQEPaW5pdE1hcmdpblJhdGlvAAYGCQEBIQEJARNyZXF1aXJlT3BlblBvc2l0aW9uAQUHX3RyYWRlcgYJAQZwYXVzZWQABgkBDmlzTWFya2V0Q2xvc2VkAAkAAgECI0ludmFsaWQgZGVjcmVhc2VQb3NpdGlvbiBwYXJhbWV0ZXJzBA0kdDA0OTc2NzQ5OTA3CQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBA9vbGRQb3NpdGlvblNpemUIBQ0kdDA0OTc2NzQ5OTA3Al8xBBFvbGRQb3NpdGlvbk1hcmdpbggFDSR0MDQ5NzY3NDk5MDcCXzIEF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNDk3Njc0OTkwNwJfMwQUb2xkUG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA0OTc2NzQ5OTA3Al80BApfZGlyZWN0aW9uAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAABQlESVJfU0hPUlQFCERJUl9MT05HBAVpc0FkZAkAAAIFCl9kaXJlY3Rpb24FCERJUl9MT05HBAxvcGVuTm90aW9uYWwJAQRtdWxkAgUHX2Ftb3VudAUJX2xldmVyYWdlBA0kdDA1MDA4MDUwMTg0CQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QEE29sZFBvc2l0aW9uTm90aW9uYWwIBQ0kdDA1MDA4MDUwMTg0Al8xBA11bnJlYWxpemVkUG5sCAUNJHQwNTAwODA1MDE4NAJfMgQNJHQwNTAxOTA1Mjg0OAMJAGYCBRNvbGRQb3NpdGlvbk5vdGlvbmFsBQxvcGVuTm90aW9uYWwEDSR0MDUwNjA1NTA3ODkJAQlzd2FwSW5wdXQCBQVpc0FkZAUMb3Blbk5vdGlvbmFsBBVleGNoYW5nZWRQb3NpdGlvblNpemUIBQ0kdDA1MDYwNTUwNzg5Al8xBBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNTA2MDU1MDc4OQJfMgQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNTA2MDU1MDc4OQJfMwQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDUwNjA1NTA3ODkCXzQEGGV4Y2hhbmdlZFBvc2l0aW9uU2l6ZUFicwkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQMDCQECIT0CBRNfbWluQmFzZUFzc2V0QW1vdW50AAAJAGYCBRNfbWluQmFzZUFzc2V0QW1vdW50BRhleGNoYW5nZWRQb3NpdGlvblNpemVBYnMHCQACAQkArAICCQCsAgIJAKwCAgIlVG9vIGxpdHRsZSBiYXNlIGFzc2V0IGV4Y2hhbmdlZCwgZ290IAkApAMBBRhleGNoYW5nZWRQb3NpdGlvblNpemVBYnMCCiBleHBlY3RlZCAJAKQDAQUTX21pbkJhc2VBc3NldEFtb3VudAQLcmVhbGl6ZWRQbmwJAQRkaXZkAgkBBG11bGQCBQ11bnJlYWxpemVkUG5sBRhleGNoYW5nZWRQb3NpdGlvblNpemVBYnMJAQNhYnMBBQ9vbGRQb3NpdGlvblNpemUEDSR0MDUxMjI2NTE0NzEJASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BAUPb2xkUG9zaXRpb25TaXplBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25Mc3RVcGRDUEYFC3JlYWxpemVkUG5sBAxyZW1haW5NYXJnaW4IBQ0kdDA1MTIyNjUxNDcxAl8xBAdiYWREZWJ0CAUNJHQwNTEyMjY1MTQ3MQJfMgQOZnVuZGluZ1BheW1lbnQIBQ0kdDA1MTIyNjUxNDcxAl8zBBlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BQxvcGVuTm90aW9uYWwEEnVucmVhbGl6ZWRQbmxBZnRlcgkAZQIFDXVucmVhbGl6ZWRQbmwFC3JlYWxpemVkUG5sBBJyZW1haW5PcGVuTm90aW9uYWwDCQBmAgUPb2xkUG9zaXRpb25TaXplAAAJAGUCCQBlAgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAUSdW5yZWFsaXplZFBubEFmdGVyCQBlAgkAZAIFEnVucmVhbGl6ZWRQbmxBZnRlcgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAQPbmV3UG9zaXRpb25TaXplCQBkAgUPb2xkUG9zaXRpb25TaXplBRVleGNoYW5nZWRQb3NpdGlvblNpemUJAJ4KDAUPbmV3UG9zaXRpb25TaXplBQxyZW1haW5NYXJnaW4JAQNhYnMBBRJyZW1haW5PcGVuTm90aW9uYWwJAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUPbmV3UG9zaXRpb25TaXplBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIJAGUCCQEUb3BlbkludGVyZXN0Tm90aW9uYWwABQxvcGVuTm90aW9uYWwJAGUCCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAMJAGYCBQ9uZXdQb3NpdGlvblNpemUAAAkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQAACQBlAgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUAAwkAZgIAAAUPbmV3UG9zaXRpb25TaXplCQEDYWJzAQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplAAAJAGUCCQEQb3BlbkludGVyZXN0TG9uZwADCQBmAgUPbmV3UG9zaXRpb25TaXplAAAFDG9wZW5Ob3Rpb25hbAAACQBlAgkBEW9wZW5JbnRlcmVzdFNob3J0AAMJAGYCAAAFD25ld1Bvc2l0aW9uU2l6ZQUMb3Blbk5vdGlvbmFsAAAJAAIBAhRDbG9zZSBwb3NpdGlvbiBmaXJzdAQPbmV3UG9zaXRpb25TaXplCAUNJHQwNTAxOTA1Mjg0OAJfMQQXbmV3UG9zaXRpb25SZW1haW5NYXJnaW4IBQ0kdDA1MDE5MDUyODQ4Al8yBBduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDUwMTkwNTI4NDgCXzMEFG5ld1Bvc2l0aW9uTGF0ZXN0Q1BGCAUNJHQwNTAxOTA1Mjg0OAJfNAQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNTAxOTA1Mjg0OAJfNQQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDUwMTkwNTI4NDgCXzYEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA1MDE5MDUyODQ4Al83BBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCAUNJHQwNTAxOTA1Mjg0OAJfOAQOdG90YWxMb25nQWZ0ZXIIBQ0kdDA1MDE5MDUyODQ4Al85BA90b3RhbFNob3J0QWZ0ZXIIBQ0kdDA1MDE5MDUyODQ4A18xMAQadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA1MDE5MDUyODQ4A18xMQQbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNTAxOTA1Mjg0OANfMTIEDm5vdGlmeU5vdGlvbmFsCQD8BwQJAQxtaW5lckFkZHJlc3MAAg5ub3RpZnlOb3Rpb25hbAkAzAgCBQdfdHJhZGVyCQDMCAIFF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBQNuaWwFA25pbAMJAAACBQ5ub3RpZnlOb3Rpb25hbAUObm90aWZ5Tm90aW9uYWwJAM4IAgkBDnVwZGF0ZVBvc2l0aW9uBQUHX3RyYWRlcgUPbmV3UG9zaXRpb25TaXplBRduZXdQb3NpdGlvblJlbWFpbk1hcmdpbgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFFG5ld1Bvc2l0aW9uTGF0ZXN0Q1BGCQEJdXBkYXRlQW1tCAUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyBRp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgUbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBEGluY3JlYXNlUG9zaXRpb24ECl9kaXJlY3Rpb24JX2xldmVyYWdlE19taW5CYXNlQXNzZXRBbW91bnQIX3JlZkxpbmsEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQHX3RyYWRlcgkBD2dldEFjdHVhbENhbGxlcgEFAWkECl9yYXdBbW91bnQICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50BAhfYXNzZXRJZAgJAJEDAggFAWkIcGF5bWVudHMAAAdhc3NldElkBAtfYXNzZXRJZFN0cgkA2AQBCQEFdmFsdWUBBQhfYXNzZXRJZAQMaXNRdW90ZUFzc2V0CQAAAgUIX2Fzc2V0SWQJAQpxdW90ZUFzc2V0AAQRaXNDb2xsYXRlcmFsQXNzZXQJARBpc1doaXRlbGlzdEFzc2V0AQULX2Fzc2V0SWRTdHIDAwMDAwMDAwMDCQECIT0CBQpfZGlyZWN0aW9uBQhESVJfTE9ORwkBAiE9AgUKX2RpcmVjdGlvbgUJRElSX1NIT1JUBwYJAGcCAAAFCl9yYXdBbW91bnQGCQEBIQEJAQtpbml0aWFsaXplZAAGAwkBASEBBQxpc1F1b3RlQXNzZXQJAQEhAQURaXNDb2xsYXRlcmFsQXNzZXQHBgkBASEBCQEXaXNTYW1lQXNzZXRPck5vUG9zaXRpb24CBQdfdHJhZGVyBQtfYXNzZXRJZFN0cgYJAQEhAQkBFnJlcXVpcmVNb3JlTWFyZ2luUmF0aW8DCQEEZGl2ZAIFDERFQ0lNQUxfVU5JVAUJX2xldmVyYWdlCQEPaW5pdE1hcmdpblJhdGlvAAYGCQEGcGF1c2VkAAYJAQljbG9zZU9ubHkABgkBDmlzTWFya2V0Q2xvc2VkAAkAAgECI0ludmFsaWQgaW5jcmVhc2VQb3NpdGlvbiBwYXJhbWV0ZXJzBA0kdDA1NDMxMDU0Mzk1CQEYZ2V0Rm9yVHJhZGVyV2l0aEFydGlmYWN0AgUHX3RyYWRlcgkBDWdldEFydGlmYWN0SWQBBQFpBAthZGp1c3RlZEZlZQgFDSR0MDU0MzEwNTQzOTUCXzEEDGJ1cm5BcnRpZmFjdAgFDSR0MDU0MzEwNTQzOTUCXzIEDHJhd0ZlZUFtb3VudAkBBG11bGQCBQpfcmF3QW1vdW50BQthZGp1c3RlZEZlZQQHX2Ftb3VudAkAZQIFCl9yYXdBbW91bnQFDHJhd0ZlZUFtb3VudAQTZGlzdHJpYnV0ZUZlZUFtb3VudAMFEWlzQ29sbGF0ZXJhbEFzc2V0BAhkb0JvcnJvdwkA/AcECQERY29sbGF0ZXJhbEFkZHJlc3MAAgZib3Jyb3cJAMwIAgUHX3RyYWRlcgUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQhfYXNzZXRJZAUHX2Ftb3VudAUDbmlsAwkAAAIFCGRvQm9ycm93BQhkb0JvcnJvdwQNYmFsYW5jZUJlZm9yZQkA8AcCBQR0aGlzCQEKcXVvdGVBc3NldAADCQAAAgUNYmFsYW5jZUJlZm9yZQUNYmFsYW5jZUJlZm9yZQQGZG9Td2FwCQD8BwQJAQtzd2FwQWRkcmVzcwACBHN3YXAJAMwIAgkA2AQBCQEKcXVvdGVBc3NldAAJAMwIAgAABQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFCF9hc3NldElkBQxyYXdGZWVBbW91bnQFA25pbAMJAAACBQZkb1N3YXAFBmRvU3dhcAQMYmFsYW5jZUFmdGVyCQDwBwIFBHRoaXMJAQpxdW90ZUFzc2V0AAMJAAACBQxiYWxhbmNlQWZ0ZXIFDGJhbGFuY2VBZnRlcgQPZXhjaGFuZ2VkQW1vdW50CQBlAgUMYmFsYW5jZUFmdGVyBQ1iYWxhbmNlQmVmb3JlAwkAAAIFD2V4Y2hhbmdlZEFtb3VudAUPZXhjaGFuZ2VkQW1vdW50BQ9leGNoYW5nZWRBbW91bnQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FDHJhd0ZlZUFtb3VudAMJAAACBRNkaXN0cmlidXRlRmVlQW1vdW50BRNkaXN0cmlidXRlRmVlQW1vdW50BA5yZWZlcnJlckZlZUFueQkA/AcECQEPcmVmZXJyYWxBZGRyZXNzAAIVYWNjZXB0UGF5bWVudFdpdGhMaW5rCQDMCAIFB190cmFkZXIJAMwIAgUIX3JlZkxpbmsFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABRNkaXN0cmlidXRlRmVlQW1vdW50BQNuaWwDCQAAAgUOcmVmZXJyZXJGZWVBbnkFDnJlZmVycmVyRmVlQW55BAtyZWZlcnJlckZlZQQHJG1hdGNoMAUOcmVmZXJyZXJGZWVBbnkDCQABAgUHJG1hdGNoMAIDSW50BAF4BQckbWF0Y2gwBQF4CQACAQITSW52YWxpZCByZWZlcnJlckZlZQQJZmVlQW1vdW50CQBlAgUTZGlzdHJpYnV0ZUZlZUFtb3VudAULcmVmZXJyZXJGZWUEDSR0MDU1NzExNTU4NTEJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIED29sZFBvc2l0aW9uU2l6ZQgFDSR0MDU1NzExNTU4NTECXzEEEW9sZFBvc2l0aW9uTWFyZ2luCAUNJHQwNTU3MTE1NTg1MQJfMgQXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA1NTcxMTU1ODUxAl8zBBRvbGRQb3NpdGlvbkxzdFVwZENQRggFDSR0MDU1NzExNTU4NTECXzQEDWlzTmV3UG9zaXRpb24JAAACBQ9vbGRQb3NpdGlvblNpemUAAAQPaXNTYW1lRGlyZWN0aW9uAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAACQAAAgUKX2RpcmVjdGlvbgUIRElSX0xPTkcJAAACBQpfZGlyZWN0aW9uBQlESVJfU0hPUlQEDmV4cGFuZEV4aXN0aW5nAwkBASEBBQ1pc05ld1Bvc2l0aW9uBQ9pc1NhbWVEaXJlY3Rpb24HBAVpc0FkZAkAAAIFCl9kaXJlY3Rpb24FCERJUl9MT05HBA0kdDA1NjE0MDU5MTgxAwMFDWlzTmV3UG9zaXRpb24GBQ5leHBhbmRFeGlzdGluZwQMb3Blbk5vdGlvbmFsCQEEbXVsZAIFB19hbW91bnQFCV9sZXZlcmFnZQQNJHQwNTY2MDI1Njc3NQkBCXN3YXBJbnB1dAIFBWlzQWRkBQxvcGVuTm90aW9uYWwEFWFtb3VudEJhc2VBc3NldEJvdWdodAgFDSR0MDU2NjAyNTY3NzUCXzEEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA1NjYwMjU2Nzc1Al8yBBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA1NjYwMjU2Nzc1Al8zBBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNTY2MDI1Njc3NQJfNAMDCQECIT0CBRNfbWluQmFzZUFzc2V0QW1vdW50AAAJAGYCBRNfbWluQmFzZUFzc2V0QW1vdW50CQEDYWJzAQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0BwkAAgEJAKwCAgkArAICCQCsAgICDUxpbWl0IGVycm9yOiAJAKQDAQkBA2FicwEFFWFtb3VudEJhc2VBc3NldEJvdWdodAIDIDwgCQCkAwEFE19taW5CYXNlQXNzZXRBbW91bnQED25ld1Bvc2l0aW9uU2l6ZQkAZAIFD29sZFBvc2l0aW9uU2l6ZQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0BBp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgkAZAIJARBvcGVuSW50ZXJlc3RMb25nAAMJAGYCBQ9uZXdQb3NpdGlvblNpemUAAAUMb3Blbk5vdGlvbmFsAAAEG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgkAZAIJARFvcGVuSW50ZXJlc3RTaG9ydAADCQBmAgAABQ9uZXdQb3NpdGlvblNpemUFDG9wZW5Ob3Rpb25hbAAABBlpbmNyZWFzZU1hcmdpblJlcXVpcmVtZW50CQEEZGl2ZAIFDG9wZW5Ob3Rpb25hbAUJX2xldmVyYWdlBA0kdDA1NzM4MzU3NjIyCQEiY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudAQFD29sZFBvc2l0aW9uU2l6ZQURb2xkUG9zaXRpb25NYXJnaW4FFG9sZFBvc2l0aW9uTHN0VXBkQ1BGBRlpbmNyZWFzZU1hcmdpblJlcXVpcmVtZW50BAxyZW1haW5NYXJnaW4IBQ0kdDA1NzM4MzU3NjIyAl8xBAJ4MQgFDSR0MDU3MzgzNTc2MjICXzIEAngyCAUNJHQwNTczODM1NzYyMgJfMwMJAQEhAQkBGXJlcXVpcmVOb3RPdmVyU3ByZWFkTGltaXQCBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIJAAIBAhVPdmVyIG1heCBzcHJlYWQgbGltaXQDCQEBIQEJAR1yZXF1aXJlTm90T3Zlck1heE9wZW5Ob3Rpb25hbAIFGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyBRt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIJAAIBAhZPdmVyIG1heCBvcGVuIG5vdGlvbmFsCQCeCgwFD25ld1Bvc2l0aW9uU2l6ZQUMcmVtYWluTWFyZ2luCQBkAgUXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwFDG9wZW5Ob3Rpb25hbAkBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BBQ9uZXdQb3NpdGlvblNpemUFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgkAZAIJARRvcGVuSW50ZXJlc3ROb3Rpb25hbAAFDG9wZW5Ob3Rpb25hbAkAZAIJARV0b3RhbExvbmdQb3NpdGlvblNpemUAAwkAZgIFD25ld1Bvc2l0aW9uU2l6ZQAACQEDYWJzAQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0AAAJAGQCCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQADCQBmAgAABQ9uZXdQb3NpdGlvblNpemUJAQNhYnMBBRVhbW91bnRCYXNlQXNzZXRCb3VnaHQAAAUadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIFG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgQMb3Blbk5vdGlvbmFsCQEEbXVsZAIFB19hbW91bnQFCV9sZXZlcmFnZQQNJHQwNTg4ODE1ODk5NwkBI2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sAgkApQgBCAUBaQZjYWxsZXIFD1BOTF9PUFRJT05fU1BPVAQTb2xkUG9zaXRpb25Ob3Rpb25hbAgFDSR0MDU4ODgxNTg5OTcCXzEEDXVucmVhbGl6ZWRQbmwIBQ0kdDA1ODg4MTU4OTk3Al8yAwkAZgIFE29sZFBvc2l0aW9uTm90aW9uYWwFDG9wZW5Ob3Rpb25hbAkAAgECLlVzZSBkZWNyZWFzZVBvc2l0aW9uIHRvIGRlY3JlYXNlIHBvc2l0aW9uIHNpemUJAAIBAhRDbG9zZSBwb3NpdGlvbiBmaXJzdAQPbmV3UG9zaXRpb25TaXplCAUNJHQwNTYxNDA1OTE4MQJfMQQXbmV3UG9zaXRpb25SZW1haW5NYXJnaW4IBQ0kdDA1NjE0MDU5MTgxAl8yBBduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDU2MTQwNTkxODECXzMEFG5ld1Bvc2l0aW9uTGF0ZXN0Q1BGCAUNJHQwNTYxNDA1OTE4MQJfNAQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNTYxNDA1OTE4MQJfNQQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDU2MTQwNTkxODECXzYEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA1NjE0MDU5MTgxAl83BBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCAUNJHQwNTYxNDA1OTE4MQJfOAQOdG90YWxMb25nQWZ0ZXIIBQ0kdDA1NjE0MDU5MTgxAl85BA90b3RhbFNob3J0QWZ0ZXIIBQ0kdDA1NjE0MDU5MTgxA18xMAQadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA1NjE0MDU5MTgxA18xMQQbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNTYxNDA1OTE4MQNfMTIEDSR0MDU5MTg3NTkyNDQJAQ1kaXN0cmlidXRlRmVlAQUJZmVlQW1vdW50BAxmZWVUb1N0YWtlcnMIBQ0kdDA1OTE4NzU5MjQ0Al8xBApmZWVUb1ZhdWx0CAUNJHQwNTkxODc1OTI0NAJfMgQFc3Rha2UDBQxpc1F1b3RlQXNzZXQEBXN0YWtlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAglhZGRMb2NrZWQJAMwIAgcFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABQdfYW1vdW50BQNuaWwDCQAAAgUFc3Rha2UFBXN0YWtlBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBQVzdGFrZQUFc3Rha2UEEGRlcG9zaXRJbnN1cmFuY2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACB2FkZEZyZWUFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABQpmZWVUb1ZhdWx0BQNuaWwDCQAAAgUQZGVwb3NpdEluc3VyYW5jZQUQZGVwb3NpdEluc3VyYW5jZQQJbm90aWZ5RmVlCQD8BwQJAQxtaW5lckFkZHJlc3MAAgpub3RpZnlGZWVzCQDMCAIFB190cmFkZXIJAMwIAgUJZmVlQW1vdW50BQNuaWwFA25pbAMJAAACBQlub3RpZnlGZWUFCW5vdGlmeUZlZQQObm90aWZ5Tm90aW9uYWwJAPwHBAkBDG1pbmVyQWRkcmVzcwACDm5vdGlmeU5vdGlvbmFsCQDMCAIFB190cmFkZXIJAMwIAgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFA25pbAUDbmlsAwkAAAIFDm5vdGlmeU5vdGlvbmFsBQ5ub3RpZnlOb3Rpb25hbAkAzggCCQDOCAIJAM4IAgkAzggCCQDOCAIJAM4IAgkBDnVwZGF0ZVBvc2l0aW9uBQUHX3RyYWRlcgUPbmV3UG9zaXRpb25TaXplBRduZXdQb3NpdGlvblJlbWFpbk1hcmdpbgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFFG5ld1Bvc2l0aW9uTGF0ZXN0Q1BGCQEfaW5jcmVtZW50UG9zaXRpb25TZXF1ZW5jZU51bWJlcgIFDWlzTmV3UG9zaXRpb24FB190cmFkZXIJARN1cGRhdGVQb3NpdGlvbkFzc2V0AgUHX3RyYWRlcgULX2Fzc2V0SWRTdHIJAQl1cGRhdGVBbW0IBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIFDnRvdGFsTG9uZ0FmdGVyBQ90b3RhbFNob3J0QWZ0ZXIFGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyBRt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIJAQt0cmFuc2ZlckZlZQEFDGZlZVRvU3Rha2VycwkBDXVwZGF0ZUJhbGFuY2UBCQBkAgkBCGNiYWxhbmNlAAUHX2Ftb3VudAkBDmRvQnVybkFydGlmYWN0AgUMYnVybkFydGlmYWN0BQFpCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCWFkZE1hcmdpbgAEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQHX3RyYWRlcgkApQgBCAUBaQZjYWxsZXIECl9yYXdBbW91bnQICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50BAhfYXNzZXRJZAgJAJEDAggFAWkIcGF5bWVudHMAAAdhc3NldElkBAtfYXNzZXRJZFN0cgkA2AQBCQEFdmFsdWUBBQhfYXNzZXRJZAQMaXNRdW90ZUFzc2V0CQAAAgUIX2Fzc2V0SWQJAQpxdW90ZUFzc2V0AAQRaXNDb2xsYXRlcmFsQXNzZXQJARBpc1doaXRlbGlzdEFzc2V0AQULX2Fzc2V0SWRTdHIDAwMDAwMDAwkBASEBBQxpc1F1b3RlQXNzZXQJAQEhAQURaXNDb2xsYXRlcmFsQXNzZXQHBgkBASEBCQETcmVxdWlyZU9wZW5Qb3NpdGlvbgEJAKUIAQgFAWkGY2FsbGVyBgkBASEBCQELaXNTYW1lQXNzZXQCBQdfdHJhZGVyBQtfYXNzZXRJZFN0cgYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQZwYXVzZWQABgkBCWNsb3NlT25seQAGCQEOaXNNYXJrZXRDbG9zZWQACQACAQIcSW52YWxpZCBhZGRNYXJnaW4gcGFyYW1ldGVycwQNJHQwNjEyMTY2MTMwMQkBGGdldEZvclRyYWRlcldpdGhBcnRpZmFjdAIFB190cmFkZXIJAQ1nZXRBcnRpZmFjdElkAQUBaQQLYWRqdXN0ZWRGZWUIBQ0kdDA2MTIxNjYxMzAxAl8xBAxidXJuQXJ0aWZhY3QIBQ0kdDA2MTIxNjYxMzAxAl8yBAxyYXdGZWVBbW91bnQJAQRtdWxkAgUKX3Jhd0Ftb3VudAULYWRqdXN0ZWRGZWUEB19hbW91bnQJAGUCBQpfcmF3QW1vdW50BQxyYXdGZWVBbW91bnQEE2Rpc3RyaWJ1dGVGZWVBbW91bnQDBRFpc0NvbGxhdGVyYWxBc3NldAQIZG9Cb3Jyb3cJAPwHBAkBEWNvbGxhdGVyYWxBZGRyZXNzAAIGYm9ycm93CQDMCAIFB190cmFkZXIFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUIX2Fzc2V0SWQFB19hbW91bnQFA25pbAMJAAACBQhkb0JvcnJvdwUIZG9Cb3Jyb3cEDWJhbGFuY2VCZWZvcmUJAPAHAgUEdGhpcwkBCnF1b3RlQXNzZXQAAwkAAAIFDWJhbGFuY2VCZWZvcmUFDWJhbGFuY2VCZWZvcmUEBmRvU3dhcAkA/AcECQELc3dhcEFkZHJlc3MAAgRzd2FwCQDMCAIJANgEAQkBCnF1b3RlQXNzZXQACQDMCAIAAAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQhfYXNzZXRJZAUMcmF3RmVlQW1vdW50BQNuaWwDCQAAAgUGZG9Td2FwBQZkb1N3YXAEDGJhbGFuY2VBZnRlcgkA8AcCBQR0aGlzCQEKcXVvdGVBc3NldAADCQAAAgUMYmFsYW5jZUFmdGVyBQxiYWxhbmNlQWZ0ZXIED2V4Y2hhbmdlZEFtb3VudAkAZQIFDGJhbGFuY2VBZnRlcgUNYmFsYW5jZUJlZm9yZQMJAAACBQ9leGNoYW5nZWRBbW91bnQFD2V4Y2hhbmdlZEFtb3VudAUPZXhjaGFuZ2VkQW1vdW50CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQxyYXdGZWVBbW91bnQDCQAAAgUTZGlzdHJpYnV0ZUZlZUFtb3VudAUTZGlzdHJpYnV0ZUZlZUFtb3VudAQOcmVmZXJyZXJGZWVBbnkJAPwHBAkBD3JlZmVycmFsQWRkcmVzcwACDWFjY2VwdFBheW1lbnQJAMwIAgUHX3RyYWRlcgUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFE2Rpc3RyaWJ1dGVGZWVBbW91bnQFA25pbAMJAAACBQ5yZWZlcnJlckZlZUFueQUOcmVmZXJyZXJGZWVBbnkEC3JlZmVycmVyRmVlBAckbWF0Y2gwBQ5yZWZlcnJlckZlZUFueQMJAAECBQckbWF0Y2gwAgNJbnQEAXgFByRtYXRjaDAFAXgJAAIBAhNJbnZhbGlkIHJlZmVycmVyRmVlBAlmZWVBbW91bnQJAGUCBRNkaXN0cmlidXRlRmVlQW1vdW50BQtyZWZlcnJlckZlZQQNJHQwNjI2MDA2Mjc0MAkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQPb2xkUG9zaXRpb25TaXplCAUNJHQwNjI2MDA2Mjc0MAJfMQQRb2xkUG9zaXRpb25NYXJnaW4IBQ0kdDA2MjYwMDYyNzQwAl8yBBdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDYyNjAwNjI3NDACXzMEFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwNjI2MDA2Mjc0MAJfNAQNJHQwNjI3NDY2MjgwMwkBDWRpc3RyaWJ1dGVGZWUBBQlmZWVBbW91bnQEDGZlZVRvU3Rha2VycwgFDSR0MDYyNzQ2NjI4MDMCXzEECmZlZVRvVmF1bHQIBQ0kdDA2Mjc0NjYyODAzAl8yBAVzdGFrZQMFDGlzUXVvdGVBc3NldAQFc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACCWFkZExvY2tlZAkAzAgCBwUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFB19hbW91bnQFA25pbAMJAAACBQVzdGFrZQUFc3Rha2UFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFBXN0YWtlBQVzdGFrZQQQZGVwb3NpdEluc3VyYW5jZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIHYWRkRnJlZQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFCmZlZVRvVmF1bHQFA25pbAMJAAACBRBkZXBvc2l0SW5zdXJhbmNlBRBkZXBvc2l0SW5zdXJhbmNlBAlub3RpZnlGZWUJAPwHBAkBDG1pbmVyQWRkcmVzcwACCm5vdGlmeUZlZXMJAMwIAgUHX3RyYWRlcgkAzAgCBQlmZWVBbW91bnQFA25pbAUDbmlsAwkAAAIFCW5vdGlmeUZlZQUJbm90aWZ5RmVlCQDOCAIJAM4IAgkAzggCCQEOdXBkYXRlUG9zaXRpb24FBQdfdHJhZGVyBQ9vbGRQb3NpdGlvblNpemUJAGQCBRFvbGRQb3NpdGlvbk1hcmdpbgUHX2Ftb3VudAUXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwFFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCQELdHJhbnNmZXJGZWUBBQxmZWVUb1N0YWtlcnMJAQ11cGRhdGVCYWxhbmNlAQkAZAIJAQhjYmFsYW5jZQAFB19hbW91bnQJAQ5kb0J1cm5BcnRpZmFjdAIFDGJ1cm5BcnRpZmFjdAUBaQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQxyZW1vdmVNYXJnaW4BB19hbW91bnQEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQHX3RyYWRlcgkApQgBCAUBaQZjYWxsZXIDAwMDAwkAZwIAAAUHX2Ftb3VudAYJAQEhAQkBE3JlcXVpcmVPcGVuUG9zaXRpb24BBQdfdHJhZGVyBgkBASEBCQELaW5pdGlhbGl6ZWQABgkBBnBhdXNlZAAGCQEOaXNNYXJrZXRDbG9zZWQACQACAQIfSW52YWxpZCByZW1vdmVNYXJnaW4gcGFyYW1ldGVycwQNJHQwNjM5Mzk2NDA3OQkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQPb2xkUG9zaXRpb25TaXplCAUNJHQwNjM5Mzk2NDA3OQJfMQQRb2xkUG9zaXRpb25NYXJnaW4IBQ0kdDA2MzkzOTY0MDc5Al8yBBdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDYzOTM5NjQwNzkCXzMEFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwNjM5Mzk2NDA3OQJfNAQLbWFyZ2luRGVsdGEJAQEtAQUHX2Ftb3VudAQNJHQwNjQxMTY2NDI5NQkBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEBQ9vbGRQb3NpdGlvblNpemUFEW9sZFBvc2l0aW9uTWFyZ2luBRRvbGRQb3NpdGlvbkxzdFVwZENQRgULbWFyZ2luRGVsdGEEDHJlbWFpbk1hcmdpbggFDSR0MDY0MTE2NjQyOTUCXzEEB2JhZERlYnQIBQ0kdDA2NDExNjY0Mjk1Al8yAwkBAiE9AgUHYmFkRGVidAAACQACAQIdSW52YWxpZCByZW1vdmVkIG1hcmdpbiBhbW91bnQEC21hcmdpblJhdGlvCQEPY2FsY01hcmdpblJhdGlvAwUMcmVtYWluTWFyZ2luBQdiYWREZWJ0BRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAMJAQEhAQkBFnJlcXVpcmVNb3JlTWFyZ2luUmF0aW8DBQttYXJnaW5SYXRpbwkBD2luaXRNYXJnaW5SYXRpbwAGCQACAQkArAICCQCsAgIJAKwCAgIZVG9vIG11Y2ggbWFyZ2luIHJlbW92ZWQ6IAkApAMBBQttYXJnaW5SYXRpbwIDIDwgCQCkAwEJAQ9pbml0TWFyZ2luUmF0aW8ABA1xdW90ZUFzc2V0U3RyCQDYBAEJAQpxdW90ZUFzc2V0AAQNJHQwNjQ3Mzk2NDc5MwkBE2dldEJvcnJvd2VkQnlUcmFkZXIBBQdfdHJhZGVyBAhib3Jyb3dlZAgFDSR0MDY0NzM5NjQ3OTMCXzEEB2Fzc2V0SWQIBQ0kdDA2NDczOTY0NzkzAl8yBAd0b1JlcGF5AwkAZgIFB19hbW91bnQFCGJvcnJvd2VkBQhib3Jyb3dlZAUHX2Ftb3VudAQKdG9XaXRoZHJhdwMJAGYCBQhib3Jyb3dlZAUHX2Ftb3VudAAACQBlAgUHX2Ftb3VudAUIYm9ycm93ZWQEC2ZpbmFsQm9ycm93CQBlAgUIYm9ycm93ZWQFB3RvUmVwYXkEFXN3aXRjaFBvc2l0aW9uVG9RdW90ZQMJAGYCBQtmaW5hbEJvcnJvdwAABQNuaWwJARN1cGRhdGVQb3NpdGlvbkFzc2V0AgUHX3RyYWRlcgUNcXVvdGVBc3NldFN0cgQNZG9TYW5pdHlDaGVjawMJAQIhPQIJAGQCBQd0b1JlcGF5BQp0b1dpdGhkcmF3BQdfYW1vdW50CQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgICCHRvUmVwYXk9CQCkAwEFB3RvUmVwYXkCDiArIHRvV2l0aGRyYXc9CQCkAwEFCnRvV2l0aGRyYXcCBCAhPSAJAKQDAQUHX2Ftb3VudAUDbmlsAwkAAAIFDWRvU2FuaXR5Q2hlY2sFDWRvU2FuaXR5Q2hlY2sECWRvVW5zdGFrZQMJAGYCBQp0b1dpdGhkcmF3AAAECWRvVW5zdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIOd2l0aGRyYXdMb2NrZWQJAMwIAgUKdG9XaXRoZHJhdwUDbmlsBQNuaWwDCQAAAgUJZG9VbnN0YWtlBQlkb1Vuc3Rha2UFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFCWRvVW5zdGFrZQUJZG9VbnN0YWtlBBZyZXR1cm5Db2xsYXRlcmFsQWN0aW9uAwkAZgIFB3RvUmVwYXkAAAQHZG9SZXBheQkA/AcECQERY29sbGF0ZXJhbEFkZHJlc3MAAgVyZXBheQkAzAgCBQdfdHJhZGVyCQDMCAIFB3RvUmVwYXkJAMwIAgUHYXNzZXRJZAUDbmlsBQNuaWwDCQAAAgUHZG9SZXBheQUHZG9SZXBheQkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIFB3RvUmVwYXkJANkEAQUHYXNzZXRJZAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUWcmV0dXJuQ29sbGF0ZXJhbEFjdGlvbgUWcmV0dXJuQ29sbGF0ZXJhbEFjdGlvbgkAzggCCQDOCAIJAM4IAgkAzggCCQEOdXBkYXRlUG9zaXRpb24FBQdfdHJhZGVyBQ9vbGRQb3NpdGlvblNpemUFDHJlbWFpbk1hcmdpbgUXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwJAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUPb2xkUG9zaXRpb25TaXplAwkAZgIFCnRvV2l0aGRyYXcAAAkBCHdpdGhkcmF3AggFAWkGY2FsbGVyBQp0b1dpdGhkcmF3BQNuaWwJAQ11cGRhdGVCYWxhbmNlAQkAZQIJAQhjYmFsYW5jZQAFB19hbW91bnQFFXN3aXRjaFBvc2l0aW9uVG9RdW90ZQUWcmV0dXJuQ29sbGF0ZXJhbEFjdGlvbgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ1jbG9zZVBvc2l0aW9uAgVfc2l6ZRRfbWluUXVvdGVBc3NldEFtb3VudAQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBAdfdHJhZGVyCQEPZ2V0QWN0dWFsQ2FsbGVyAQUBaQQOX3RyYWRlckFkZHJlc3MJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBBQdfdHJhZGVyAg5JbnZhbGlkIGNhbGxlcgMDAwMDAwkBASEBCQETcmVxdWlyZU9wZW5Qb3NpdGlvbgEFB190cmFkZXIGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAYJAGcCAAAFBV9zaXplBgkAZgIAAAUUX21pblF1b3RlQXNzZXRBbW91bnQGCQEOaXNNYXJrZXRDbG9zZWQACQACAQIgSW52YWxpZCBjbG9zZVBvc2l0aW9uIHBhcmFtZXRlcnMEDSR0MDY2OTc3NjcxMTcJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIED29sZFBvc2l0aW9uU2l6ZQgFDSR0MDY2OTc3NjcxMTcCXzEEEW9sZFBvc2l0aW9uTWFyZ2luCAUNJHQwNjY5Nzc2NzExNwJfMgQXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA2Njk3NzY3MTE3Al8zBBRvbGRQb3NpdGlvbkxzdFVwZENQRggFDSR0MDY2OTc3NjcxMTcCXzQEDSR0MDY3MTIzNzIyMDEDCQBmAgkBA2FicwEFD29sZFBvc2l0aW9uU2l6ZQUFX3NpemUECl9kaXJlY3Rpb24DCQBmAgUPb2xkUG9zaXRpb25TaXplAAAFCURJUl9TSE9SVAUIRElSX0xPTkcEBWlzQWRkCQAAAgUKX2RpcmVjdGlvbgUIRElSX0xPTkcEDSR0MDY3NzE0Njc5MzYJAQpzd2FwT3V0cHV0AwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAABQVfc2l6ZQYEGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQIBQ0kdDA2NzcxNDY3OTM2Al8xBBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNjc3MTQ2NzkzNgJfMgQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNjc3MTQ2NzkzNgJfMwQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDY3NzE0Njc5MzYCXzQEFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQMJAGYCBQ9vbGRQb3NpdGlvblNpemUAAAkBAS0BBQVfc2l6ZQUFX3NpemUEDSR0MDY4MDI3NjgxODEJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAQTb2xkUG9zaXRpb25Ob3Rpb25hbAgFDSR0MDY4MDI3NjgxODECXzEEDXVucmVhbGl6ZWRQbmwIBQ0kdDA2ODAyNzY4MTgxAl8yBAJtcgkBFmdldE1hcmdpblJhdGlvQnlPcHRpb24CBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QEDXJlYWxpemVkUmF0aW8JAQRkaXZkAgkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQkBA2FicwEFD29sZFBvc2l0aW9uU2l6ZQQLcmVhbGl6ZWRQbmwJAQRtdWxkAgUNdW5yZWFsaXplZFBubAUNcmVhbGl6ZWRSYXRpbwQScmVtYWluTWFyZ2luQmVmb3JlCAkBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEBQ9vbGRQb3NpdGlvblNpemUFEW9sZFBvc2l0aW9uTWFyZ2luBRRvbGRQb3NpdGlvbkxzdFVwZENQRgUNdW5yZWFsaXplZFBubAJfMQQNJHQwNjg2ODI2ODkyMAkBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEBQ9vbGRQb3NpdGlvblNpemUFEW9sZFBvc2l0aW9uTWFyZ2luBRRvbGRQb3NpdGlvbkxzdFVwZENQRgULcmVhbGl6ZWRQbmwEDHJlbWFpbk1hcmdpbggFDSR0MDY4NjgyNjg5MjACXzEED3Bvc2l0aW9uQmFkRGVidAgFDSR0MDY4NjgyNjg5MjACXzIEDmZ1bmRpbmdQYXltZW50CAUNJHQwNjg2ODI2ODkyMAJfMwQSdW5yZWFsaXplZFBubEFmdGVyCQBlAgUNdW5yZWFsaXplZFBubAULcmVhbGl6ZWRQbmwEEnJlbWFpbk9wZW5Ob3Rpb25hbAMJAGYCBQ9vbGRQb3NpdGlvblNpemUAAAkAZQIJAGUCBRNvbGRQb3NpdGlvbk5vdGlvbmFsBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BRJ1bnJlYWxpemVkUG5sQWZ0ZXIJAGUCCQBkAgUSdW5yZWFsaXplZFBubEFmdGVyBRNvbGRQb3NpdGlvbk5vdGlvbmFsBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BBduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAkBA2FicwEFEnJlbWFpbk9wZW5Ob3Rpb25hbAQRbmV3UG9zaXRpb25NYXJnaW4DCQBmAgUPb2xkUG9zaXRpb25TaXplAAAJAGUCCQEEbXVsZAIJAGQCBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUSdW5yZWFsaXplZFBubEFmdGVyBQJtcgUSdW5yZWFsaXplZFBubEFmdGVyCQBlAgkBBG11bGQCCQBlAgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFEnVucmVhbGl6ZWRQbmxBZnRlcgUCbXIFEnVucmVhbGl6ZWRQbmxBZnRlcgQPbmV3UG9zaXRpb25TaXplCQBkAgUPb2xkUG9zaXRpb25TaXplBRVleGNoYW5nZWRQb3NpdGlvblNpemUEFG5ld1Bvc2l0aW9uTHN0VXBkQ1BGCQEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEFD25ld1Bvc2l0aW9uU2l6ZQQZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcgkAZQIJARRvcGVuSW50ZXJlc3ROb3Rpb25hbAAFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQDAwkBAiE9AgUUX21pblF1b3RlQXNzZXRBbW91bnQAAAkAZgIFFF9taW5RdW90ZUFzc2V0QW1vdW50BRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BwkAAgEJAKwCAgkArAICCQCsAgICDUxpbWl0IGVycm9yOiAJAKQDAQUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAIDIDwgCQCkAwEFFF9taW5RdW90ZUFzc2V0QW1vdW50CQChCg8FD25ld1Bvc2l0aW9uU2l6ZQURbmV3UG9zaXRpb25NYXJnaW4FF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBRRuZXdQb3NpdGlvbkxzdFVwZENQRgUPcG9zaXRpb25CYWREZWJ0BQtyZWFsaXplZFBubAkAZQIFEnJlbWFpbk1hcmdpbkJlZm9yZQkAZAIFEW5ld1Bvc2l0aW9uTWFyZ2luBRJ1bnJlYWxpemVkUG5sQWZ0ZXIFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgUZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcgkAZQIJARV0b3RhbExvbmdQb3NpdGlvblNpemUAAwkAZgIFD25ld1Bvc2l0aW9uU2l6ZQAACQEDYWJzAQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplAAAJAGUCCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQADCQBmAgAABQ9uZXdQb3NpdGlvblNpemUJAQNhYnMBBRVleGNoYW5nZWRQb3NpdGlvblNpemUAAAkAZQIJARBvcGVuSW50ZXJlc3RMb25nAAMJAGYCBQ9uZXdQb3NpdGlvblNpemUAAAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAAACQBlAgkBEW9wZW5JbnRlcmVzdFNob3J0AAMJAGYCAAAFD25ld1Bvc2l0aW9uU2l6ZQUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAAAAwkAZgIFBV9zaXplCQEDYWJzAQUPb2xkUG9zaXRpb25TaXplCQACAQIgSW52YWxpZCBjbG9zZVBvc2l0aW9uIHBhcmFtZXRlcnMEDSR0MDcxMTQyNzE1NjEJARVpbnRlcm5hbENsb3NlUG9zaXRpb24CBQdfdHJhZGVyBgQZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAgFDSR0MDcxMTQyNzE1NjECXzEED3Bvc2l0aW9uQmFkRGVidAgFDSR0MDcxMTQyNzE1NjECXzIEC3JlYWxpemVkUG5sCAUNJHQwNzExNDI3MTU2MQJfMwQNbWFyZ2luVG9WYXVsdAgFDSR0MDcxMTQyNzE1NjECXzQEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA3MTE0MjcxNTYxAl81BBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA3MTE0MjcxNTYxAl82BBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNzExNDI3MTU2MQJfNwQZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcggFDSR0MDcxMTQyNzE1NjECXzgEAngyCAUNJHQwNzExNDI3MTU2MQJfOQQOdG90YWxMb25nQWZ0ZXIIBQ0kdDA3MTE0MjcxNTYxA18xMAQPdG90YWxTaG9ydEFmdGVyCAUNJHQwNzExNDI3MTU2MQNfMTEEGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNzExNDI3MTU2MQNfMTIEG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDcxMTQyNzE1NjEDXzEzAwMJAQIhPQIFFF9taW5RdW90ZUFzc2V0QW1vdW50AAAJAGYCBRRfbWluUXVvdGVBc3NldEFtb3VudAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAcJAAIBCQCsAgIJAKwCAgkArAICAg1MaW1pdCBlcnJvcjogCQCkAwEFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQCAyA8IAkApAMBBRRfbWluUXVvdGVBc3NldEFtb3VudAkAoQoPAAAAAAAAAAAFD3Bvc2l0aW9uQmFkRGVidAULcmVhbGl6ZWRQbmwFDW1hcmdpblRvVmF1bHQFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgUZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcgUOdG90YWxMb25nQWZ0ZXIFD3RvdGFsU2hvcnRBZnRlcgUadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIFG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgQPbmV3UG9zaXRpb25TaXplCAUNJHQwNjcxMjM3MjIwMQJfMQQRbmV3UG9zaXRpb25NYXJnaW4IBQ0kdDA2NzEyMzcyMjAxAl8yBBduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDY3MTIzNzIyMDECXzMEFG5ld1Bvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwNjcxMjM3MjIwMQJfNAQPcG9zaXRpb25CYWREZWJ0CAUNJHQwNjcxMjM3MjIwMQJfNQQLcmVhbGl6ZWRQbmwIBQ0kdDA2NzEyMzcyMjAxAl82BA1tYXJnaW5Ub1ZhdWx0CAUNJHQwNjcxMjM3MjIwMQJfNwQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDY3MTIzNzIyMDECXzgEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDY3MTIzNzIyMDECXzkEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA2NzEyMzcyMjAxA18xMAQZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcggFDSR0MDY3MTIzNzIyMDEDXzExBA50b3RhbExvbmdBZnRlcggFDSR0MDY3MTIzNzIyMDEDXzEyBA90b3RhbFNob3J0QWZ0ZXIIBQ0kdDA2NzEyMzcyMjAxA18xMwQadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA2NzEyMzcyMjAxA18xNAQbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNjcxMjM3MjIwMQNfMTUDCQBmAgUPcG9zaXRpb25CYWREZWJ0AAAJAAIBAiZVbmFibGUgdG8gY2xvc2UgcG9zaXRpb24gd2l0aCBiYWQgZGVidAQOd2l0aGRyYXdBbW91bnQJAQNhYnMBBQ1tYXJnaW5Ub1ZhdWx0BAphbW1CYWxhbmNlCQBlAgkBCGNiYWxhbmNlAAUOd2l0aGRyYXdBbW91bnQEDSR0MDcyNDEwNzI2MTcDCQBmAgAABQphbW1CYWxhbmNlCQCUCgIAAAkBA2FicwEFCmFtbUJhbGFuY2UJAJQKAgUKYW1tQmFsYW5jZQAABA1hbW1OZXdCYWxhbmNlCAUNJHQwNzI0MTA3MjYxNwJfMQQDeDExCAUNJHQwNzI0MTA3MjYxNwJfMgQNJHQwNzI2MjQ3MjY3OAkBE2dldEJvcnJvd2VkQnlUcmFkZXIBBQdfdHJhZGVyBAhib3Jyb3dlZAgFDSR0MDcyNjI0NzI2NzgCXzEEB2Fzc2V0SWQIBQ0kdDA3MjYyNDcyNjc4Al8yBA0kdDA3MjY5MzczNTUyAwkAZgIFCGJvcnJvd2VkAAADCQBnAgUOd2l0aGRyYXdBbW91bnQFCGJvcnJvd2VkBAdkb1JlcGF5CQD8BwQJARFjb2xsYXRlcmFsQWRkcmVzcwACBXJlcGF5CQDMCAIFB190cmFkZXIJAMwIAgUIYm9ycm93ZWQJAMwIAgUHYXNzZXRJZAUDbmlsBQNuaWwDCQAAAgUHZG9SZXBheQUHZG9SZXBheQkAlAoCCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFDl90cmFkZXJBZGRyZXNzBQhib3Jyb3dlZAkA2QQBBQdhc3NldElkBQNuaWwJAGUCBQ53aXRoZHJhd0Ftb3VudAUIYm9ycm93ZWQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4ED3JlYWxpemVBbmRDbG9zZQkA/AcECQERY29sbGF0ZXJhbEFkZHJlc3MAAhhyZWFsaXplUGFydGlhbGx5QW5kQ2xvc2UJAMwIAgUHX3RyYWRlcgkAzAgCBQ53aXRoZHJhd0Ftb3VudAkAzAgCBQdhc3NldElkBQNuaWwFA25pbAMJAAACBQ9yZWFsaXplQW5kQ2xvc2UFD3JlYWxpemVBbmRDbG9zZQkAlAoCCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFDl90cmFkZXJBZGRyZXNzBQ53aXRoZHJhd0Ftb3VudAkA2QQBBQdhc3NldElkBQNuaWwAAAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAlAoCBQNuaWwFDndpdGhkcmF3QW1vdW50AwkAAAIFDSR0MDcyNjkzNzM1NTIFDSR0MDcyNjkzNzM1NTIEE3F1b3RlV2l0aGRyYXdBbW91bnQIBQ0kdDA3MjY5MzczNTUyAl8yBBRzZW5kQ29sbGF0ZXJhbEFjdGlvbggFDSR0MDcyNjkzNzM1NTICXzEEB3Vuc3Rha2UDCQBmAgUTcXVvdGVXaXRoZHJhd0Ftb3VudAAABAd1bnN0YWtlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAg53aXRoZHJhd0xvY2tlZAkAzAgCBRNxdW90ZVdpdGhkcmF3QW1vdW50BQNuaWwFA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlBA5ub3RpZnlOb3Rpb25hbAkA/AcECQEMbWluZXJBZGRyZXNzAAIObm90aWZ5Tm90aW9uYWwJAMwIAgUHX3RyYWRlcgkAzAgCAAAFA25pbAUDbmlsAwkAAAIFDm5vdGlmeU5vdGlvbmFsBQ5ub3RpZnlOb3Rpb25hbAkAzggCCQDOCAIJAM4IAgkAzggCAwkAAAIFD25ld1Bvc2l0aW9uU2l6ZQAACQEOZGVsZXRlUG9zaXRpb24BBQdfdHJhZGVyCQEOdXBkYXRlUG9zaXRpb24FBQdfdHJhZGVyBQ9uZXdQb3NpdGlvblNpemUFEW5ld1Bvc2l0aW9uTWFyZ2luBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUUbmV3UG9zaXRpb25Mc3RVcGRDUEYJAQl1cGRhdGVBbW0IBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIFDnRvdGFsTG9uZ0FmdGVyBQ90b3RhbFNob3J0QWZ0ZXIFGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyBRt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIDCQBmAgUTcXVvdGVXaXRoZHJhd0Ftb3VudAAACQEId2l0aGRyYXcCBQ5fdHJhZGVyQWRkcmVzcwUTcXVvdGVXaXRoZHJhd0Ftb3VudAUDbmlsCQENdXBkYXRlQmFsYW5jZQEFDWFtbU5ld0JhbGFuY2UFFHNlbmRDb2xsYXRlcmFsQWN0aW9uCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCWxpcXVpZGF0ZQEHX3RyYWRlcgQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBA9zcG90TWFyZ2luUmF0aW8JARZnZXRNYXJnaW5SYXRpb0J5T3B0aW9uAgUHX3RyYWRlcgUPUE5MX09QVElPTl9TUE9UBAttYXJnaW5SYXRpbwMJARZpc092ZXJGbHVjdHVhdGlvbkxpbWl0AAQRb3JhY2xlTWFyZ2luUmF0aW8JARZnZXRNYXJnaW5SYXRpb0J5T3B0aW9uAgUHX3RyYWRlcgURUE5MX09QVElPTl9PUkFDTEUJAQR2bWF4AgUPc3BvdE1hcmdpblJhdGlvBRFvcmFjbGVNYXJnaW5SYXRpbwUPc3BvdE1hcmdpblJhdGlvAwMDAwMJAQEhAQkBFnJlcXVpcmVNb3JlTWFyZ2luUmF0aW8DBQttYXJnaW5SYXRpbwkBFm1haW50ZW5hbmNlTWFyZ2luUmF0aW8ABwYJAQEhAQkBE3JlcXVpcmVPcGVuUG9zaXRpb24BBQdfdHJhZGVyBgkBASEBCQELaW5pdGlhbGl6ZWQABgkBBnBhdXNlZAAGCQEOaXNNYXJrZXRDbG9zZWQACQACAQITVW5hYmxlIHRvIGxpcXVpZGF0ZQMDAwkAZgIFD3Nwb3RNYXJnaW5SYXRpbwkBE2xpcXVpZGF0aW9uRmVlUmF0aW8ACQBmAgkBF3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAAAABwkAZgIFDERFQ0lNQUxfVU5JVAkBF3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAAcEDSR0MDc1ODczNzYwMjMJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIED29sZFBvc2l0aW9uU2l6ZQgFDSR0MDc1ODczNzYwMjMCXzEEEW9sZFBvc2l0aW9uTWFyZ2luCAUNJHQwNzU4NzM3NjAyMwJfMgQXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA3NTg3Mzc2MDIzAl8zBBRvbGRQb3NpdGlvbkxzdFVwZENQRggFDSR0MDc1ODczNzYwMjMCXzQECl9kaXJlY3Rpb24DCQBmAgUPb2xkUG9zaXRpb25TaXplAAAFCURJUl9TSE9SVAUIRElSX0xPTkcEBWlzQWRkCQAAAgUKX2RpcmVjdGlvbgUIRElSX0xPTkcEGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQJARtnZXRQYXJ0aWFsTGlxdWlkYXRpb25BbW91bnQCBQdfdHJhZGVyBQ9vbGRQb3NpdGlvblNpemUEDSR0MDc2MjQ4NzYzNTIJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAQTb2xkUG9zaXRpb25Ob3Rpb25hbAgFDSR0MDc2MjQ4NzYzNTICXzEEDXVucmVhbGl6ZWRQbmwIBQ0kdDA3NjI0ODc2MzUyAl8yBA0kdDA3NjM2MDc2NTQ3CQEJc3dhcElucHV0AgUFaXNBZGQFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQEFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQgFDSR0MDc2MzYwNzY1NDcCXzEEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA3NjM2MDc2NTQ3Al8yBBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA3NjM2MDc2NTQ3Al8zBBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNzYzNjA3NjU0NwJfNAQQbGlxdWlkYXRpb25SYXRpbwkBBGRpdmQCCQEDYWJzAQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplCQEDYWJzAQUPb2xkUG9zaXRpb25TaXplBAtyZWFsaXplZFBubAkBBG11bGQCBQ11bnJlYWxpemVkUG5sBRBsaXF1aWRhdGlvblJhdGlvBA0kdDA3NjgzNjc3MDY5CQEiY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudAQFD29sZFBvc2l0aW9uU2l6ZQURb2xkUG9zaXRpb25NYXJnaW4FFG9sZFBvc2l0aW9uTHN0VXBkQ1BGBQtyZWFsaXplZFBubAQMcmVtYWluTWFyZ2luCAUNJHQwNzY4MzY3NzA2OQJfMQQHYmFkRGVidAgFDSR0MDc2ODM2NzcwNjkCXzIEDmZ1bmRpbmdQYXltZW50CAUNJHQwNzY4MzY3NzA2OQJfMwQSdW5yZWFsaXplZFBubEFmdGVyCQBlAgUNdW5yZWFsaXplZFBubAULcmVhbGl6ZWRQbmwEEnJlbWFpbk9wZW5Ob3Rpb25hbAMJAGYCBQ9vbGRQb3NpdGlvblNpemUAAAkAZQIJAGUCBRNvbGRQb3NpdGlvbk5vdGlvbmFsBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BRJ1bnJlYWxpemVkUG5sQWZ0ZXIJAGUCCQBkAgUSdW5yZWFsaXplZFBubEFmdGVyBRNvbGRQb3NpdGlvbk5vdGlvbmFsBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BBJsaXF1aWRhdGlvblBlbmFsdHkJAQRtdWxkAgUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAkBE2xpcXVpZGF0aW9uRmVlUmF0aW8ABA9mZWVUb0xpcXVpZGF0b3IJAGkCBRJsaXF1aWRhdGlvblBlbmFsdHkAAgQKZmVlVG9WYXVsdAkAZQIFEmxpcXVpZGF0aW9uUGVuYWx0eQUPZmVlVG9MaXF1aWRhdG9yBBFuZXdQb3NpdGlvbk1hcmdpbgkAZQIFDHJlbWFpbk1hcmdpbgUSbGlxdWlkYXRpb25QZW5hbHR5BA9uZXdQb3NpdGlvblNpemUJAGQCBQ9vbGRQb3NpdGlvblNpemUFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQQXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwJAQNhYnMBBRJyZW1haW5PcGVuTm90aW9uYWwEFG5ld1Bvc2l0aW9uTHN0VXBkQ1BGCQEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEFD25ld1Bvc2l0aW9uU2l6ZQQZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcgkAZQIJARRvcGVuSW50ZXJlc3ROb3Rpb25hbAAFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQECmFtbUJhbGFuY2UJAGUCCQEIY2JhbGFuY2UABRJsaXF1aWRhdGlvblBlbmFsdHkEDSR0MDc4MjM4NzgzNjcDCQBmAgAABQphbW1CYWxhbmNlCQCUCgIAAAkBA2FicwEFCmFtbUJhbGFuY2UJAJQKAgUKYW1tQmFsYW5jZQAABA1uZXdBbW1CYWxhbmNlCAUNJHQwNzgyMzg3ODM2NwJfMQQDeDExCAUNJHQwNzgyMzg3ODM2NwJfMgQNJHQwNzgzNzU3ODQyOQkBE2dldEJvcnJvd2VkQnlUcmFkZXIBBQdfdHJhZGVyBAhib3Jyb3dlZAgFDSR0MDc4Mzc1Nzg0MjkCXzEEB2Fzc2V0SWQIBQ0kdDA3ODM3NTc4NDI5Al8yBBVkb0xpcXVpZGF0ZUNvbGxhdGVyYWwDCQBmAgUIYm9ycm93ZWQAAAQQY29sbGF0ZXJhbFRvU2VsbAkBBG11bGQCBQhib3Jyb3dlZAUQbGlxdWlkYXRpb25SYXRpbwQPcmVhbGl6ZUFuZENsb3NlCQD8BwQJARFjb2xsYXRlcmFsQWRkcmVzcwACEHJlYWxpemVQYXJ0aWFsbHkJAMwIAgUHX3RyYWRlcgkAzAgCBQdhc3NldElkCQDMCAIFEGNvbGxhdGVyYWxUb1NlbGwFA25pbAUDbmlsAwkAAAIFD3JlYWxpemVBbmRDbG9zZQUPcmVhbGl6ZUFuZENsb3NlBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBRVkb0xpcXVpZGF0ZUNvbGxhdGVyYWwFFWRvTGlxdWlkYXRlQ29sbGF0ZXJhbAQHdW5zdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIOd2l0aGRyYXdMb2NrZWQJAMwIAgUSbGlxdWlkYXRpb25QZW5hbHR5BQNuaWwFA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlBBBkZXBvc2l0SW5zdXJhbmNlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAgdhZGRGcmVlBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUKZmVlVG9WYXVsdAUDbmlsAwkAAAIFEGRlcG9zaXRJbnN1cmFuY2UFEGRlcG9zaXRJbnN1cmFuY2UEDm5vdGlmeU5vdGlvbmFsCQD8BwQJAQxtaW5lckFkZHJlc3MAAg5ub3RpZnlOb3Rpb25hbAkAzAgCBQdfdHJhZGVyCQDMCAIFF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBQNuaWwFA25pbAMJAAACBQ5ub3RpZnlOb3Rpb25hbAUObm90aWZ5Tm90aW9uYWwJAM4IAgkAzggCCQDOCAIJAQ51cGRhdGVQb3NpdGlvbgUFB190cmFkZXIFD25ld1Bvc2l0aW9uU2l6ZQURbmV3UG9zaXRpb25NYXJnaW4FF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBRRuZXdQb3NpdGlvbkxzdFVwZENQRgkBCXVwZGF0ZUFtbQgFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgUZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcgkAZQIJARV0b3RhbExvbmdQb3NpdGlvblNpemUAAwkAZgIFD25ld1Bvc2l0aW9uU2l6ZQAACQEDYWJzAQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplAAAJAGUCCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQADCQBmAgAABQ9uZXdQb3NpdGlvblNpemUJAQNhYnMBBRVleGNoYW5nZWRQb3NpdGlvblNpemUAAAkAZQIJARBvcGVuSW50ZXJlc3RMb25nAAMJAGYCBQ9uZXdQb3NpdGlvblNpemUAAAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAAACQBlAgkBEW9wZW5JbnRlcmVzdFNob3J0AAMJAGYCAAAFD25ld1Bvc2l0aW9uU2l6ZQUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAAACQEId2l0aGRyYXcCCAUBaQZjYWxsZXIFD2ZlZVRvTGlxdWlkYXRvcgkBDXVwZGF0ZUJhbGFuY2UBBQ1uZXdBbW1CYWxhbmNlCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBA0kdDA4MDEyNDgwNjE5CQEVaW50ZXJuYWxDbG9zZVBvc2l0aW9uAgUHX3RyYWRlcgcEAngxCAUNJHQwODAxMjQ4MDYxOQJfMQQHYmFkRGVidAgFDSR0MDgwMTI0ODA2MTkCXzIEAngyCAUNJHQwODAxMjQ4MDYxOQJfMwQCeDMIBQ0kdDA4MDEyNDgwNjE5Al80BBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwODAxMjQ4MDYxOQJfNQQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwODAxMjQ4MDYxOQJfNgQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDgwMTI0ODA2MTkCXzcEGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIIBQ0kdDA4MDEyNDgwNjE5Al84BBlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CAUNJHQwODAxMjQ4MDYxOQJfOQQOdG90YWxMb25nQWZ0ZXIIBQ0kdDA4MDEyNDgwNjE5A18xMAQPdG90YWxTaG9ydEFmdGVyCAUNJHQwODAxMjQ4MDYxOQNfMTEEGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyCAUNJHQwODAxMjQ4MDYxOQNfMTIEG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDgwMTI0ODA2MTkDXzEzBBJsaXF1aWRhdGlvblBlbmFsdHkJAQRtdWxkAgUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAkBE2xpcXVpZGF0aW9uRmVlUmF0aW8ABA9mZWVUb0xpcXVpZGF0b3IJAGkCBRJsaXF1aWRhdGlvblBlbmFsdHkAAgQKZmVlVG9WYXVsdAkAZQIFEmxpcXVpZGF0aW9uUGVuYWx0eQUPZmVlVG9MaXF1aWRhdG9yBAphbW1CYWxhbmNlCQBlAgkBCGNiYWxhbmNlAAUSbGlxdWlkYXRpb25QZW5hbHR5BA0kdDA4MTAyNzgxMTU2AwkAZgIAAAUKYW1tQmFsYW5jZQkAlAoCAAAJAQNhYnMBBQphbW1CYWxhbmNlCQCUCgIFCmFtbUJhbGFuY2UAAAQNbmV3QW1tQmFsYW5jZQgFDSR0MDgxMDI3ODExNTYCXzEEA3gxMQgFDSR0MDgxMDI3ODExNTYCXzIEDSR0MDgxMTY0ODEyMTgJARNnZXRCb3Jyb3dlZEJ5VHJhZGVyAQUHX3RyYWRlcgQIYm9ycm93ZWQIBQ0kdDA4MTE2NDgxMjE4Al8xBAdhc3NldElkCAUNJHQwODExNjQ4MTIxOAJfMgQVZG9MaXF1aWRhdGVDb2xsYXRlcmFsAwkAZgIFCGJvcnJvd2VkAAAED3JlYWxpemVBbmRDbG9zZQkA/AcECQERY29sbGF0ZXJhbEFkZHJlc3MAAhhyZWFsaXplUGFydGlhbGx5QW5kQ2xvc2UJAMwIAgUHX3RyYWRlcgkAzAgCAAAJAMwIAgUHYXNzZXRJZAUDbmlsBQNuaWwDCQAAAgUPcmVhbGl6ZUFuZENsb3NlBQ9yZWFsaXplQW5kQ2xvc2UFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFFWRvTGlxdWlkYXRlQ29sbGF0ZXJhbAUVZG9MaXF1aWRhdGVDb2xsYXRlcmFsBAF4AwkAZgIFB2JhZERlYnQAAAQLbG9ja0JhZERlYnQJAPwHBAkBDHZhdWx0QWRkcmVzcwACFWV4Y2hhbmdlRnJlZUFuZExvY2tlZAkAzAgCBQdiYWREZWJ0BQNuaWwFA25pbAMJAAACBQtsb2NrQmFkRGVidAULbG9ja0JhZERlYnQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFAXgFAXgEB3Vuc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACDndpdGhkcmF3TG9ja2VkCQDMCAIFEmxpcXVpZGF0aW9uUGVuYWx0eQUDbmlsBQNuaWwDCQAAAgUHdW5zdGFrZQUHdW5zdGFrZQQQZGVwb3NpdEluc3VyYW5jZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIHYWRkRnJlZQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFCmZlZVRvVmF1bHQFA25pbAMJAAACBRBkZXBvc2l0SW5zdXJhbmNlBRBkZXBvc2l0SW5zdXJhbmNlBA5ub3RpZnlOb3Rpb25hbAkA/AcECQEMbWluZXJBZGRyZXNzAAIObm90aWZ5Tm90aW9uYWwJAMwIAgUHX3RyYWRlcgkAzAgCAAAFA25pbAUDbmlsAwkAAAIFDm5vdGlmeU5vdGlvbmFsBQ5ub3RpZnlOb3Rpb25hbAkAzggCCQDOCAIJAM4IAgkBDmRlbGV0ZVBvc2l0aW9uAQUHX3RyYWRlcgkBCXVwZGF0ZUFtbQgFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgUZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcgUOdG90YWxMb25nQWZ0ZXIFD3RvdGFsU2hvcnRBZnRlcgUadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIFG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgkBCHdpdGhkcmF3AggFAWkGY2FsbGVyBQ9mZWVUb0xpcXVpZGF0b3IJAQ11cGRhdGVCYWxhbmNlAQUNbmV3QW1tQmFsYW5jZQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQpwYXlGdW5kaW5nAAQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBBVmdW5kaW5nQmxvY2tUaW1lc3RhbXAJARluZXh0RnVuZGluZ0Jsb2NrVGltZXN0YW1wAAMDAwkAZgIFFWZ1bmRpbmdCbG9ja1RpbWVzdGFtcAgFCWxhc3RCbG9jawl0aW1lc3RhbXAGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAkAAgEJAKwCAgkArAICCQCsAgICIUludmFsaWQgZnVuZGluZyBibG9jayB0aW1lc3RhbXA6IAkApAMBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAIDIDwgCQCkAwEFFWZ1bmRpbmdCbG9ja1RpbWVzdGFtcAQPdW5kZXJseWluZ1ByaWNlCQEOZ2V0T3JhY2xlUHJpY2UABA0kdDA4MzA5MDgzMTUyCQEKZ2V0RnVuZGluZwAEFHNob3J0UHJlbWl1bUZyYWN0aW9uCAUNJHQwODMwOTA4MzE1MgJfMQQTbG9uZ1ByZW1pdW1GcmFjdGlvbggFDSR0MDgzMDkwODMxNTICXzIJAQ11cGRhdGVGdW5kaW5nBQkAZAIFFWZ1bmRpbmdCbG9ja1RpbWVzdGFtcAkBFGZ1bmRpbmdQZXJpb2RTZWNvbmRzAAkAZAIJASNsYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAFE2xvbmdQcmVtaXVtRnJhY3Rpb24JAGQCCQEkbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAUUc2hvcnRQcmVtaXVtRnJhY3Rpb24JAQRkaXZkAgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgUPdW5kZXJseWluZ1ByaWNlCQEEZGl2ZAIFFHNob3J0UHJlbWl1bUZyYWN0aW9uBQ91bmRlcmx5aW5nUHJpY2UJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQAEB19xdEFzdFIJAQZxdEFzdFIABAdfYnNBc3RSCQEGYnNBc3RSAAQNJHQwODM1ODQ4MzcxOQkBFGdldFN5bmNUZXJtaW5hbFByaWNlAwkBDmdldE9yYWNsZVByaWNlAAUHX3F0QXN0UgUHX2JzQXN0UgQTbmV3UXVvdGVBc3NldFdlaWdodAgFDSR0MDgzNTg0ODM3MTkCXzEEEm5ld0Jhc2VBc3NldFdlaWdodAgFDSR0MDgzNTg0ODM3MTkCXzIEDW1hcmdpblRvVmF1bHQIBQ0kdDA4MzU4NDgzNzE5Al8zBA1kb0V4Y2hhbmdlUG5MAwkBAiE9AgUNbWFyZ2luVG9WYXVsdAAABA1kb0V4Y2hhbmdlUG5MCQD8BwQJAQx2YXVsdEFkZHJlc3MAAhVleGNoYW5nZUZyZWVBbmRMb2NrZWQJAMwIAgUNbWFyZ2luVG9WYXVsdAUDbmlsBQNuaWwDCQAAAgUNZG9FeGNoYW5nZVBuTAUNZG9FeGNoYW5nZVBuTAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUNZG9FeGNoYW5nZVBuTAUNZG9FeGNoYW5nZVBuTAkAzggCCQEQdXBkYXRlQW1tV2VpZ2h0cwIFE25ld1F1b3RlQXNzZXRXZWlnaHQFEm5ld0Jhc2VBc3NldFdlaWdodAkBCmFwcGVuZFR3YXABCQEEZGl2ZAIJAQRtdWxkAgUHX3F0QXN0UgUTbmV3UXVvdGVBc3NldFdlaWdodAkBBG11bGQCBQdfYnNBc3RSBRJuZXdCYXNlQXNzZXRXZWlnaHQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEndmlld19jYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50AQdfdHJhZGVyBARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEDSR0MDg0Mjg4ODQzODkJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIEDHBvc2l0aW9uU2l6ZQgFDSR0MDg0Mjg4ODQzODkCXzEEDnBvc2l0aW9uTWFyZ2luCAUNJHQwODQyODg4NDM4OQJfMgQDcG9uCAUNJHQwODQyODg4NDM4OQJfMwQRcG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA4NDI4ODg0Mzg5Al80BA0kdDA4NDM5Mjg0NDkzCQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QEEHBvc2l0aW9uTm90aW9uYWwIBQ0kdDA4NDM5Mjg0NDkzAl8xBA11bnJlYWxpemVkUG5sCAUNJHQwODQzOTI4NDQ5MwJfMgQNJHQwODQ0OTY4NDY2OAkBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEBQxwb3NpdGlvblNpemUFDnBvc2l0aW9uTWFyZ2luBRFwb3NpdGlvbkxzdFVwZENQRgUNdW5yZWFsaXplZFBubAQMcmVtYWluTWFyZ2luCAUNJHQwODQ0OTY4NDY2OAJfMQQHYmFkRGVidAgFDSR0MDg0NDk2ODQ2NjgCXzIEDmZ1bmRpbmdQYXltZW50CAUNJHQwODQ0OTY4NDY2OAJfMwkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQEBcwEFDHJlbWFpbk1hcmdpbgkBAXMBBQ5mdW5kaW5nUGF5bWVudAkBAXMBCQEOZ2V0TWFyZ2luUmF0aW8BBQdfdHJhZGVyCQEBcwEFDXVucmVhbGl6ZWRQbmwJAQFzAQUHYmFkRGVidAkBAXMBBRBwb3NpdGlvbk5vdGlvbmFsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBFXZpZXdfZ2V0UGVnQWRqdXN0Q29zdAEGX3ByaWNlBAdfcXRBc3RSCQEGcXRBc3RSAAQHX2JzQXN0UgkBBmJzQXN0UgAEBnJlc3VsdAkBFGdldFN5bmNUZXJtaW5hbFByaWNlAwUGX3ByaWNlBQdfcXRBc3RSBQdfYnNBc3RSCQACAQkApAMBCAUGcmVzdWx0Al8zAWkBGHZpZXdfZ2V0VGVybWluYWxBbW1QcmljZQAEDSR0MDg1MDg0ODUxNjUJARNnZXRUZXJtaW5hbEFtbVN0YXRlAAQZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQgFDSR0MDg1MDg0ODUxNjUCXzEEGHRlcm1pbmFsQmFzZUFzc2V0UmVzZXJ2ZQgFDSR0MDg1MDg0ODUxNjUCXzIEBXByaWNlCQEEZGl2ZAIJAQRtdWxkAgUZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQkBBnF0QXN0VwAJAQRtdWxkAgUYdGVybWluYWxCYXNlQXNzZXRSZXNlcnZlCQEGYnNBc3RXAAkAAgEJAKQDAQUFcHJpY2UBaQEPdmlld19nZXRGdW5kaW5nAAQPdW5kZXJseWluZ1ByaWNlCQEOZ2V0T3JhY2xlUHJpY2UABA0kdDA4NTM4MDg1NDQyCQEKZ2V0RnVuZGluZwAEFHNob3J0UHJlbWl1bUZyYWN0aW9uCAUNJHQwODUzODA4NTQ0MgJfMQQTbG9uZ1ByZW1pdW1GcmFjdGlvbggFDSR0MDg1MzgwODU0NDICXzIEC2xvbmdGdW5kaW5nCQEEZGl2ZAIFE2xvbmdQcmVtaXVtRnJhY3Rpb24FD3VuZGVybHlpbmdQcmljZQQMc2hvcnRGdW5kaW5nCQEEZGl2ZAIFFHNob3J0UHJlbWl1bUZyYWN0aW9uBQ91bmRlcmx5aW5nUHJpY2UJAAIBCQCsAgIJAKwCAgkArAICCQEBcwEFC2xvbmdGdW5kaW5nCQEBcwEFDHNob3J0RnVuZGluZwkBAXMBCQEQZ2V0VHdhcFNwb3RQcmljZQAJAQFzAQkBDmdldE9yYWNsZVByaWNlAAFpARh2aWV3X2dldEJvcnJvd2VkQnlUcmFkZXIBB190cmFkZXIEDSR0MDg1NzI4ODU3ODIJARNnZXRCb3Jyb3dlZEJ5VHJhZGVyAQUHX3RyYWRlcgQIYm9ycm93ZWQIBQ0kdDA4NTcyODg1NzgyAl8xBAdhc3NldElkCAUNJHQwODU3Mjg4NTc4MgJfMgkAAgEJAKwCAgkBAXMBBQhib3Jyb3dlZAUHYXNzZXRJZAFpARBjb21wdXRlU3BvdFByaWNlAAQGcmVzdWx0CQEMZ2V0U3BvdFByaWNlAAkAlAoCBQNuaWwFBnJlc3VsdAFpAR9jb21wdXRlRmVlRm9yVHJhZGVyV2l0aEFydGlmYWN0AgdfdHJhZGVyC19hcnRpZmFjdElkBAZyZXN1bHQJARhnZXRGb3JUcmFkZXJXaXRoQXJ0aWZhY3QCBQdfdHJhZGVyBQtfYXJ0aWZhY3RJZAkAlAoCBQNuaWwFBnJlc3VsdAECdHgBBnZlcmlmeQAJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAAJAQ5hZG1pblB1YmxpY0tleQCaWBGv", "height": 2380172, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 3P9LgxZY2s4s5K1sk6gUoHuLcf7XcNWvmamrLTBZ5YYf Next: 445QpJqbK2UXvSBxJUQwL1hYHgVqBCYXhGs8aU9Mo72s Diff:
OldNewDifferences
16331633 let oldPositionMargin = $t06697767117._2
16341634 let oldPositionOpenNotional = $t06697767117._3
16351635 let oldPositionLstUpdCPF = $t06697767117._4
1636- let $t06712371769 = if ((abs(oldPositionSize) > _size))
1636+ let $t06712372201 = if ((abs(oldPositionSize) > _size))
16371637 then {
16381638 let _direction = if ((oldPositionSize > 0))
16391639 then DIR_SHORT
16631663 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
16641664 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
16651665 let newPositionOpenNotional = abs(remainOpenNotional)
1666- let newPositionMargin = muld(newPositionOpenNotional, mr)
1666+ let newPositionMargin = if ((oldPositionSize > 0))
1667+ then (muld((newPositionOpenNotional + unrealizedPnlAfter), mr) - unrealizedPnlAfter)
1668+ else (muld((newPositionOpenNotional - unrealizedPnlAfter), mr) - unrealizedPnlAfter)
16671669 let newPositionSize = (oldPositionSize + exchangedPositionSize)
16681670 let newPositionLstUpdCPF = latestCumulativePremiumFraction(newPositionSize)
16691671 let openInterestNotionalAfter = (openInterestNotional() - exchangedQuoteAssetAmount)
16711673 then (_minQuoteAssetAmount > exchangedQuoteAssetAmount)
16721674 else false)
16731675 then throw(((("Limit error: " + toString(exchangedQuoteAssetAmount)) + " < ") + toString(_minQuoteAssetAmount)))
1674- else $Tuple15(newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, positionBadDebt, realizedPnl, (remainMarginBefore - newPositionMargin), quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, (totalLongPositionSize() - (if ((newPositionSize > 0))
1676+ else $Tuple15(newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, positionBadDebt, realizedPnl, (remainMarginBefore - (newPositionMargin + unrealizedPnlAfter)), quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, (totalLongPositionSize() - (if ((newPositionSize > 0))
16751677 then abs(exchangedPositionSize)
16761678 else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
16771679 then abs(exchangedPositionSize)
16841686 else if ((_size > abs(oldPositionSize)))
16851687 then throw("Invalid closePosition parameters")
16861688 else {
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
1689+ let $t07114271561 = internalClosePosition(_trader, true)
1690+ let exchangedQuoteAssetAmount = $t07114271561._1
1691+ let positionBadDebt = $t07114271561._2
1692+ let realizedPnl = $t07114271561._3
1693+ let marginToVault = $t07114271561._4
1694+ let quoteAssetReserveAfter = $t07114271561._5
1695+ let baseAssetReserveAfter = $t07114271561._6
1696+ let totalPositionSizeAfter = $t07114271561._7
1697+ let openInterestNotionalAfter = $t07114271561._8
1698+ let x2 = $t07114271561._9
1699+ let totalLongAfter = $t07114271561._10
1700+ let totalShortAfter = $t07114271561._11
1701+ let totalLongOpenInterestAfter = $t07114271561._12
1702+ let totalShortOpenInterestAfter = $t07114271561._13
17011703 if (if ((_minQuoteAssetAmount != 0))
17021704 then (_minQuoteAssetAmount > exchangedQuoteAssetAmount)
17031705 else false)
17041706 then throw(((("Limit error: " + toString(exchangedQuoteAssetAmount)) + " < ") + toString(_minQuoteAssetAmount)))
17051707 else $Tuple15(0, 0, 0, 0, positionBadDebt, realizedPnl, marginToVault, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)
17061708 }
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
1709+ let newPositionSize = $t06712372201._1
1710+ let newPositionMargin = $t06712372201._2
1711+ let newPositionOpenNotional = $t06712372201._3
1712+ let newPositionLstUpdCPF = $t06712372201._4
1713+ let positionBadDebt = $t06712372201._5
1714+ let realizedPnl = $t06712372201._6
1715+ let marginToVault = $t06712372201._7
1716+ let quoteAssetReserveAfter = $t06712372201._8
1717+ let baseAssetReserveAfter = $t06712372201._9
1718+ let totalPositionSizeAfter = $t06712372201._10
1719+ let openInterestNotionalAfter = $t06712372201._11
1720+ let totalLongAfter = $t06712372201._12
1721+ let totalShortAfter = $t06712372201._13
1722+ let totalLongOpenInterestAfter = $t06712372201._14
1723+ let totalShortOpenInterestAfter = $t06712372201._15
17221724 if ((positionBadDebt > 0))
17231725 then throw("Unable to close position with bad debt")
17241726 else {
17251727 let withdrawAmount = abs(marginToVault)
17261728 let ammBalance = (cbalance() - withdrawAmount)
1727- let $t07197872185 = if ((0 > ammBalance))
1729+ let $t07241072617 = if ((0 > ammBalance))
17281730 then $Tuple2(0, abs(ammBalance))
17291731 else $Tuple2(ammBalance, 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))
1732+ let ammNewBalance = $t07241072617._1
1733+ let x11 = $t07241072617._2
1734+ let $t07262472678 = getBorrowedByTrader(_trader)
1735+ let borrowed = $t07262472678._1
1736+ let assetId = $t07262472678._2
1737+ let $t07269373552 = if ((borrowed > 0))
17361738 then if ((withdrawAmount >= borrowed))
17371739 then {
17381740 let doRepay = invoke(collateralAddress(), "repay", [_trader, borrowed, assetId], nil)
17471749 else throw("Strict value is not equal to itself.")
17481750 }
17491751 else $Tuple2(nil, withdrawAmount)
1750- if (($t07226173120 == $t07226173120))
1752+ if (($t07269373552 == $t07269373552))
17511753 then {
1752- let quoteWithdrawAmount = $t07226173120._2
1753- let sendCollateralAction = $t07226173120._1
1754+ let quoteWithdrawAmount = $t07269373552._2
1755+ let sendCollateralAction = $t07269373552._1
17541756 let unstake = if ((quoteWithdrawAmount > 0))
17551757 then {
17561758 let unstake = invoke(vaultAddress(), "withdrawLocked", [quoteWithdrawAmount], nil)
18091811 then (DECIMAL_UNIT > partialLiquidationRatio())
18101812 else false)
18111813 then {
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
1814+ let $t07587376023 = getPosition(_trader)
1815+ let oldPositionSize = $t07587376023._1
1816+ let oldPositionMargin = $t07587376023._2
1817+ let oldPositionOpenNotional = $t07587376023._3
1818+ let oldPositionLstUpdCPF = $t07587376023._4
18171819 let _direction = if ((oldPositionSize > 0))
18181820 then DIR_SHORT
18191821 else DIR_LONG
18201822 let isAdd = (_direction == DIR_LONG)
18211823 let exchangedQuoteAssetAmount = getPartialLiquidationAmount(_trader, oldPositionSize)
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
1824+ let $t07624876352 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1825+ let oldPositionNotional = $t07624876352._1
1826+ let unrealizedPnl = $t07624876352._2
1827+ let $t07636076547 = swapInput(isAdd, exchangedQuoteAssetAmount)
1828+ let exchangedPositionSize = $t07636076547._1
1829+ let quoteAssetReserveAfter = $t07636076547._2
1830+ let baseAssetReserveAfter = $t07636076547._3
1831+ let totalPositionSizeAfter = $t07636076547._4
18301832 let liquidationRatio = divd(abs(exchangedPositionSize), abs(oldPositionSize))
18311833 let realizedPnl = muld(unrealizedPnl, liquidationRatio)
1832- let $t07640476637 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1833- let remainMargin = $t07640476637._1
1834- let badDebt = $t07640476637._2
1835- let fundingPayment = $t07640476637._3
1834+ let $t07683677069 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1835+ let remainMargin = $t07683677069._1
1836+ let badDebt = $t07683677069._2
1837+ let fundingPayment = $t07683677069._3
18361838 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
18371839 let remainOpenNotional = if ((oldPositionSize > 0))
18381840 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
18461848 let newPositionLstUpdCPF = latestCumulativePremiumFraction(newPositionSize)
18471849 let openInterestNotionalAfter = (openInterestNotional() - exchangedQuoteAssetAmount)
18481850 let ammBalance = (cbalance() - liquidationPenalty)
1849- let $t07780677935 = if ((0 > ammBalance))
1851+ let $t07823878367 = if ((0 > ammBalance))
18501852 then $Tuple2(0, abs(ammBalance))
18511853 else $Tuple2(ammBalance, 0)
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
1854+ let newAmmBalance = $t07823878367._1
1855+ let x11 = $t07823878367._2
1856+ let $t07837578429 = getBorrowedByTrader(_trader)
1857+ let borrowed = $t07837578429._1
1858+ let assetId = $t07837578429._2
18571859 let doLiquidateCollateral = if ((borrowed > 0))
18581860 then {
18591861 let collateralToSell = muld(borrowed, liquidationRatio)
18911893 else throw("Strict value is not equal to itself.")
18921894 }
18931895 else {
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
1896+ let $t08012480619 = internalClosePosition(_trader, false)
1897+ let x1 = $t08012480619._1
1898+ let badDebt = $t08012480619._2
1899+ let x2 = $t08012480619._3
1900+ let x3 = $t08012480619._4
1901+ let quoteAssetReserveAfter = $t08012480619._5
1902+ let baseAssetReserveAfter = $t08012480619._6
1903+ let totalPositionSizeAfter = $t08012480619._7
1904+ let openInterestNotionalAfter = $t08012480619._8
1905+ let exchangedQuoteAssetAmount = $t08012480619._9
1906+ let totalLongAfter = $t08012480619._10
1907+ let totalShortAfter = $t08012480619._11
1908+ let totalLongOpenInterestAfter = $t08012480619._12
1909+ let totalShortOpenInterestAfter = $t08012480619._13
19081910 let liquidationPenalty = muld(exchangedQuoteAssetAmount, liquidationFeeRatio())
19091911 let feeToLiquidator = (liquidationPenalty / 2)
19101912 let feeToVault = (liquidationPenalty - feeToLiquidator)
19111913 let ammBalance = (cbalance() - liquidationPenalty)
1912- let $t08059580724 = if ((0 > ammBalance))
1914+ let $t08102781156 = if ((0 > ammBalance))
19131915 then $Tuple2(0, abs(ammBalance))
19141916 else $Tuple2(ammBalance, 0)
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
1917+ let newAmmBalance = $t08102781156._1
1918+ let x11 = $t08102781156._2
1919+ let $t08116481218 = getBorrowedByTrader(_trader)
1920+ let borrowed = $t08116481218._1
1921+ let assetId = $t08116481218._2
19201922 let doLiquidateCollateral = if ((borrowed > 0))
19211923 then {
19221924 let realizeAndClose = invoke(collateralAddress(), "realizePartiallyAndClose", [_trader, 0, assetId], nil)
19761978 then throw(((("Invalid funding block timestamp: " + toString(lastBlock.timestamp)) + " < ") + toString(fundingBlockTimestamp)))
19771979 else {
19781980 let underlyingPrice = getOraclePrice()
1979- let $t08265882720 = getFunding()
1980- let shortPremiumFraction = $t08265882720._1
1981- let longPremiumFraction = $t08265882720._2
1981+ let $t08309083152 = getFunding()
1982+ let shortPremiumFraction = $t08309083152._1
1983+ let longPremiumFraction = $t08309083152._2
19821984 updateFunding((fundingBlockTimestamp + fundingPeriodSeconds()), (latestLongCumulativePremiumFraction() + longPremiumFraction), (latestShortCumulativePremiumFraction() + shortPremiumFraction), divd(longPremiumFraction, underlyingPrice), divd(shortPremiumFraction, underlyingPrice))
19831985 }
19841986 }
19911993 func syncTerminalPriceToOracle () = {
19921994 let _qtAstR = qtAstR()
19931995 let _bsAstR = bsAstR()
1994- let $t08315283287 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1995- let newQuoteAssetWeight = $t08315283287._1
1996- let newBaseAssetWeight = $t08315283287._2
1997- let marginToVault = $t08315283287._3
1996+ let $t08358483719 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1997+ let newQuoteAssetWeight = $t08358483719._1
1998+ let newBaseAssetWeight = $t08358483719._2
1999+ let marginToVault = $t08358483719._3
19982000 let doExchangePnL = if ((marginToVault != 0))
19992001 then {
20002002 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
20152017 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
20162018 if ((sync == sync))
20172019 then {
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
2020+ let $t08428884389 = getPosition(_trader)
2021+ let positionSize = $t08428884389._1
2022+ let positionMargin = $t08428884389._2
2023+ let pon = $t08428884389._3
2024+ let positionLstUpdCPF = $t08428884389._4
2025+ let $t08439284493 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
2026+ let positionNotional = $t08439284493._1
2027+ let unrealizedPnl = $t08439284493._2
2028+ let $t08449684668 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
2029+ let remainMargin = $t08449684668._1
2030+ let badDebt = $t08449684668._2
2031+ let fundingPayment = $t08449684668._3
20302032 throw((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)))
20312033 }
20322034 else throw("Strict value is not equal to itself.")
20462048
20472049 @Callable(i)
20482050 func view_getTerminalAmmPrice () = {
2049- let $t08465284733 = getTerminalAmmState()
2050- let terminalQuoteAssetReserve = $t08465284733._1
2051- let terminalBaseAssetReserve = $t08465284733._2
2051+ let $t08508485165 = getTerminalAmmState()
2052+ let terminalQuoteAssetReserve = $t08508485165._1
2053+ let terminalBaseAssetReserve = $t08508485165._2
20522054 let price = divd(muld(terminalQuoteAssetReserve, qtAstW()), muld(terminalBaseAssetReserve, bsAstW()))
20532055 throw(toString(price))
20542056 }
20582060 @Callable(i)
20592061 func view_getFunding () = {
20602062 let underlyingPrice = getOraclePrice()
2061- let $t08494885010 = getFunding()
2062- let shortPremiumFraction = $t08494885010._1
2063- let longPremiumFraction = $t08494885010._2
2063+ let $t08538085442 = getFunding()
2064+ let shortPremiumFraction = $t08538085442._1
2065+ let longPremiumFraction = $t08538085442._2
20642066 let longFunding = divd(longPremiumFraction, underlyingPrice)
20652067 let shortFunding = divd(shortPremiumFraction, underlyingPrice)
20662068 throw((((s(longFunding) + s(shortFunding)) + s(getTwapSpotPrice())) + s(getOraclePrice())))
20702072
20712073 @Callable(i)
20722074 func view_getBorrowedByTrader (_trader) = {
2073- let $t08529685350 = getBorrowedByTrader(_trader)
2074- let borrowed = $t08529685350._1
2075- let assetId = $t08529685350._2
2075+ let $t08572885782 = getBorrowedByTrader(_trader)
2076+ let borrowed = $t08572885782._1
2077+ let assetId = $t08572885782._2
20762078 throw((s(borrowed) + assetId))
20772079 }
20782080
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"
77
88 let k_ora_open_key = "k_ora_open_key"
99
1010 let k_ora = "k_ora"
1111
1212 let k_balance = "k_balance"
1313
1414 let k_sequence = "k_sequence"
1515
1616 let k_positionSize = "k_positionSize"
1717
1818 let k_positionMargin = "k_positionMargin"
1919
2020 let k_positionOpenNotional = "k_positionOpenNotional"
2121
2222 let k_positionLastUpdatedCumulativePremiumFraction = "k_positionFraction"
2323
2424 let k_positionSequence = "k_positionSequence"
2525
2626 let k_positionAsset = "k_positionAsset"
2727
2828 let k_initialized = "k_initialized"
2929
3030 let k_paused = "k_paused"
3131
3232 let k_closeOnly = "k_closeOnly"
3333
3434 let k_fee = "k_fee"
3535
3636 let k_fundingPeriod = "k_fundingPeriod"
3737
3838 let k_initMarginRatio = "k_initMarginRatio"
3939
4040 let k_maintenanceMarginRatio = "k_mmr"
4141
4242 let k_liquidationFeeRatio = "k_liquidationFeeRatio"
4343
4444 let k_partialLiquidationRatio = "k_partLiquidationRatio"
4545
4646 let k_spreadLimit = "k_spreadLimit"
4747
4848 let k_maxPriceImpact = "k_maxPriceImpact"
4949
5050 let k_maxPriceSpread = "k_maxPriceSpread"
5151
5252 let k_maxOpenNotional = "k_maxOpenNotional"
5353
5454 let k_feeToStakersPercent = "k_feeToStakersPercent"
5555
5656 let k_maxOracleDelay = "k_maxOracleDelay"
5757
5858 let k_lastDataStr = "k_lastDataStr"
5959
6060 let k_lastMinuteId = "k_lastMinuteId"
6161
6262 let k_twapDataLastCumulativePrice = "k_twapDataLastCumulativePrice"
6363
6464 let k_twapDataLastPrice = "k_twapDataLastPrice"
6565
6666 let k_twapDataPreviousMinuteId = "k_twapDataPreviousMinuteId"
6767
6868 let k_latestLongCumulativePremiumFraction = "k_latestLongPremiumFraction"
6969
7070 let k_latestShortCumulativePremiumFraction = "k_latestShortPremiumFraction"
7171
7272 let k_nextFundingBlock = "k_nextFundingBlockMinTimestamp"
7373
7474 let k_longFundingRate = "k_longFundingRate"
7575
7676 let k_shortFundingRate = "k_shortFundingRate"
7777
7878 let k_quoteAssetReserve = "k_qtAstR"
7979
8080 let k_baseAssetReserve = "k_bsAstR"
8181
8282 let k_quoteAssetWeight = "k_qtAstW"
8383
8484 let k_baseAssetWeight = "k_bsAstW"
8585
8686 let k_totalPositionSize = "k_totalPositionSize"
8787
8888 let k_totalLongPositionSize = "k_totalLongPositionSize"
8989
9090 let k_totalShortPositionSize = "k_totalShortPositionSize"
9191
9292 let k_openInterestNotional = "k_openInterestNotional"
9393
9494 let k_openInterestShort = "k_openInterestShort"
9595
9696 let k_openInterestLong = "k_openInterestLong"
9797
9898 let k_coordinatorAddress = "k_coordinatorAddress"
9999
100100 let k_vault_address = "k_vault_address"
101101
102102 let k_admin_address = "k_admin_address"
103103
104104 let k_admin_public_key = "k_admin_public_key"
105105
106106 let k_quote_asset = "k_quote_asset"
107107
108108 let k_quote_staking = "k_quote_staking"
109109
110110 let k_staking_address = "k_staking_address"
111111
112112 let k_miner_address = "k_miner_address"
113113
114114 let k_orders_address = "k_orders_address"
115115
116116 let k_referral_address = "k_referral_address"
117117
118118 let k_collateral_address = "k_collateral_address"
119119
120120 let k_exchange_address = "k_exchange_address"
121121
122122 let k_nft_manager_address = "k_nft_manager_address"
123123
124124 let k_trader_market_asset_collateral = "k_trader_market_asset_collateral"
125125
126126 func toCompositeKey (_key,_address) = ((_key + "_") + _address)
127127
128128
129129 func coordinator () = valueOrErrorMessage(addressFromString(getStringValue(this, k_coordinatorAddress)), "Coordinator not set")
130130
131131
132132 func adminAddress () = addressFromString(getStringValue(coordinator(), k_admin_address))
133133
134134
135135 func adminPublicKey () = fromBase58String(getStringValue(coordinator(), k_admin_public_key))
136136
137137
138138 func quoteAsset () = fromBase58String(getStringValue(coordinator(), k_quote_asset))
139139
140140
141141 func quoteAssetStaking () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_quote_staking)), "Quote asset staking not set")
142142
143143
144144 func stakingAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_staking_address)), "Staking not set")
145145
146146
147147 func vaultAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_vault_address)), "Vault not set")
148148
149149
150150 func minerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_miner_address)), "Miner not set")
151151
152152
153153 func ordersAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_orders_address)), "Orders not set")
154154
155155
156156 func referralAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_referral_address)), "Referral not set")
157157
158158
159159 func nftManagerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_nft_manager_address)), "NFT Manager not set")
160160
161161
162162 func collateralAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_collateral_address)), "Collateral Manager not set")
163163
164164
165165 func swapAddress () = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(coordinator(), k_exchange_address), "No swap address")), "Invalid swap address")
166166
167167
168168 let k_whitelist_asset = "k_whitelist_asset"
169169
170170 func isWhitelistAsset (_assetId) = valueOrElse(getBoolean(collateralAddress(), toCompositeKey(k_whitelist_asset, _assetId)), false)
171171
172172
173173 let k_token_param = "k_token_param"
174174
175175 let k_token_type = "k_token_type"
176176
177177 let FEE_REDUCTION_TOKEN_TYPE = "fee_reduction"
178178
179179 let DIR_LONG = 1
180180
181181 let DIR_SHORT = 2
182182
183183 let TWAP_INTERVAL = 15
184184
185185 let ORACLE_INTERVAL = 15
186186
187187 let SECONDS = 1000
188188
189189 let DECIMAL_NUMBERS = 6
190190
191191 let DECIMAL_UNIT = (1 * (((((10 * 10) * 10) * 10) * 10) * 10))
192192
193193 let ONE_DAY = (86400 * DECIMAL_UNIT)
194194
195195 let ALL_FEES = 100
196196
197197 let PNL_OPTION_SPOT = 1
198198
199199 let PNL_OPTION_ORACLE = 2
200200
201201 func s (_x) = (toString(_x) + ",")
202202
203203
204204 func divd (_x,_y) = fraction(_x, DECIMAL_UNIT, _y, HALFEVEN)
205205
206206
207207 func muld (_x,_y) = fraction(_x, _y, DECIMAL_UNIT, HALFEVEN)
208208
209209
210210 func sqrtd (_x) = sqrt(_x, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
211211
212212
213213 func powd (_x,_y) = pow(_x, DECIMAL_NUMBERS, _y, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
214214
215215
216216 func bdivd (_x,_y) = fraction(_x, toBigInt(DECIMAL_UNIT), _y, HALFEVEN)
217217
218218
219219 func bmuld (_x,_y) = fraction(_x, _y, toBigInt(DECIMAL_UNIT), HALFEVEN)
220220
221221
222222 func bsqrtd (_x) = sqrtBigInt(_x, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
223223
224224
225225 func bpowd (_x,_y) = pow(_x, DECIMAL_NUMBERS, _y, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
226226
227227
228228 func abs (_x) = if ((_x > 0))
229229 then _x
230230 else -(_x)
231231
232232
233233 func vmax (_x,_y) = if ((_x >= _y))
234234 then _x
235235 else _y
236236
237237
238238 func listToStr (_list) = {
239239 func _join (accumulator,val) = ((accumulator + val) + ",")
240240
241241 let newListStr = {
242242 let $l = _list
243243 let $s = size($l)
244244 let $acc0 = ""
245245 func $f0_1 ($a,$i) = if (($i >= $s))
246246 then $a
247247 else _join($a, $l[$i])
248248
249249 func $f0_2 ($a,$i) = if (($i >= $s))
250250 then $a
251251 else throw("List size exceeds 20")
252252
253253 $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)
254254 }
255255 let newListStrU = dropRight(newListStr, 1)
256256 let newListStrR = if ((take(newListStrU, 1) == ","))
257257 then drop(newListStrU, 1)
258258 else newListStrU
259259 newListStrR
260260 }
261261
262262
263263 func strToList (_str) = split(_str, ",")
264264
265265
266266 func pushToQueue (_list,_maxSize,_value) = if ((size(_list) > _maxSize))
267267 then (removeByIndex(_list, 0) :+ _value)
268268 else (_list :+ _value)
269269
270270
271271 func int (k) = valueOrErrorMessage(getInteger(this, k), ("no value for " + k))
272272
273273
274274 func intOr (k,def) = valueOrElse(getInteger(this, k), def)
275275
276276
277277 func strA (_address,_key) = {
278278 let val = valueOrErrorMessage(getString(_address, _key), ("No value for key " + _key))
279279 val
280280 }
281281
282282
283283 func intA (_address,_key) = {
284284 let val = valueOrErrorMessage(getInteger(_address, _key), ("No value for key " + _key))
285285 val
286286 }
287287
288288
289289 func cbalance () = int(k_balance)
290290
291291
292292 func fee () = int(k_fee)
293293
294294
295295 func initMarginRatio () = int(k_initMarginRatio)
296296
297297
298298 func qtAstR () = int(k_quoteAssetReserve)
299299
300300
301301 func bsAstR () = int(k_baseAssetReserve)
302302
303303
304304 func qtAstW () = intOr(k_quoteAssetWeight, DECIMAL_UNIT)
305305
306306
307307 func bsAstW () = intOr(k_baseAssetWeight, DECIMAL_UNIT)
308308
309309
310310 func totalPositionSize () = int(k_totalPositionSize)
311311
312312
313313 func openInterestNotional () = int(k_openInterestNotional)
314314
315315
316316 func openInterestShort () = int(k_openInterestShort)
317317
318318
319319 func openInterestLong () = int(k_openInterestLong)
320320
321321
322322 func nextFundingBlockTimestamp () = int(k_nextFundingBlock)
323323
324324
325325 func fundingPeriodRaw () = int(k_fundingPeriod)
326326
327327
328328 func fundingPeriodDecimal () = (fundingPeriodRaw() * DECIMAL_UNIT)
329329
330330
331331 func fundingPeriodSeconds () = (fundingPeriodRaw() * SECONDS)
332332
333333
334334 func maintenanceMarginRatio () = int(k_maintenanceMarginRatio)
335335
336336
337337 func liquidationFeeRatio () = int(k_liquidationFeeRatio)
338338
339339
340340 func partialLiquidationRatio () = int(k_partialLiquidationRatio)
341341
342342
343343 func spreadLimit () = int(k_spreadLimit)
344344
345345
346346 func maxPriceImpact () = int(k_maxPriceImpact)
347347
348348
349349 func maxPriceSpread () = int(k_maxPriceSpread)
350350
351351
352352 func maxOpenNotional () = int(k_maxOpenNotional)
353353
354354
355355 func latestLongCumulativePremiumFraction () = int(k_latestLongCumulativePremiumFraction)
356356
357357
358358 func latestShortCumulativePremiumFraction () = int(k_latestShortCumulativePremiumFraction)
359359
360360
361361 func totalShortPositionSize () = int(k_totalShortPositionSize)
362362
363363
364364 func totalLongPositionSize () = int(k_totalLongPositionSize)
365365
366366
367367 func lastSequence () = intOr(k_sequence, 0)
368368
369369
370370 func feeToStakersPercent () = int(k_feeToStakersPercent)
371371
372372
373373 func maxOracleDelay () = int(k_maxOracleDelay)
374374
375375
376376 func getActualCaller (i) = valueOrElse(getString(ordersAddress(), "k_sender"), toString(i.caller))
377377
378378
379379 func requireMoreMarginRatio (_marginRatio,_baseMarginRatio,_largerThanOrEqualTo) = {
380380 let remainingMarginRatio = (_marginRatio - _baseMarginRatio)
381381 if (if (_largerThanOrEqualTo)
382382 then (0 > remainingMarginRatio)
383383 else false)
384384 then throw("Invalid margin")
385385 else if (if (!(_largerThanOrEqualTo))
386386 then (remainingMarginRatio >= 0)
387387 else false)
388388 then throw("Invalid margin")
389389 else true
390390 }
391391
392392
393393 func latestCumulativePremiumFraction (_positionSize) = if ((_positionSize == 0))
394394 then throw("Should not be called with _positionSize == 0")
395395 else if ((_positionSize > 0))
396396 then latestLongCumulativePremiumFraction()
397397 else latestShortCumulativePremiumFraction()
398398
399399
400400 func getPosition (_trader) = {
401401 let positionSizeOpt = getInteger(this, toCompositeKey(k_positionSize, _trader))
402402 match positionSizeOpt {
403403 case positionSize: Int =>
404404 $Tuple4(positionSize, getIntegerValue(this, toCompositeKey(k_positionMargin, _trader)), getIntegerValue(this, toCompositeKey(k_positionOpenNotional, _trader)), getIntegerValue(this, toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, _trader)))
405405 case _ =>
406406 $Tuple4(0, 0, 0, 0)
407407 }
408408 }
409409
410410
411411 func getPositionAsset (_trader) = {
412412 let positionAssetOpt = getString(this, toCompositeKey(k_positionAsset, _trader))
413413 match positionAssetOpt {
414414 case positionAsset: String =>
415415 positionAsset
416416 case _ =>
417417 toBase58String(quoteAsset())
418418 }
419419 }
420420
421421
422422 func requireOpenPosition (_trader) = if ((getPosition(_trader)._1 == 0))
423423 then throw("No open position")
424424 else true
425425
426426
427427 func initialized () = valueOrElse(getBoolean(this, k_initialized), false)
428428
429429
430430 func paused () = valueOrElse(getBoolean(this, k_paused), false)
431431
432432
433433 func closeOnly () = valueOrElse(getBoolean(this, k_closeOnly), false)
434434
435435
436436 func updateReserve (_isAdd,_quoteAssetAmount,_baseAssetAmount) = if (_isAdd)
437437 then {
438438 let newBase = (bsAstR() - _baseAssetAmount)
439439 if ((0 >= newBase))
440440 then throw("Tx lead to base asset reserve <= 0, revert")
441441 else $Tuple3((qtAstR() + _quoteAssetAmount), newBase, (totalPositionSize() + _baseAssetAmount))
442442 }
443443 else {
444444 let newQuote = (qtAstR() - _quoteAssetAmount)
445445 if ((0 >= newQuote))
446446 then throw("Tx lead to base quote reserve <= 0, revert")
447447 else $Tuple3(newQuote, (bsAstR() + _baseAssetAmount), (totalPositionSize() - _baseAssetAmount))
448448 }
449449
450450
451451 func calcInvariant (_qtAstR,_qtAstW,_bsAstR,_bsAstW) = {
452452 let bqtAstR = toBigInt(_qtAstR)
453453 let bqtAstW = toBigInt(_qtAstW)
454454 let bbsAstR = toBigInt(_bsAstR)
455455 let bbsAstW = toBigInt(_bsAstW)
456456 bmuld(bmuld(bqtAstR, bqtAstW), bmuld(bbsAstR, bbsAstW))
457457 }
458458
459459
460460 func swapInput (_isAdd,_quoteAssetAmount) = {
461461 let _qtAstR = qtAstR()
462462 let _bsAstR = bsAstR()
463463 let _qtAstW = qtAstW()
464464 let _bsAstW = bsAstW()
465465 let k = calcInvariant(_qtAstR, _qtAstW, _bsAstR, _bsAstW)
466466 let quoteAssetReserveAfter = if (_isAdd)
467467 then (_qtAstR + _quoteAssetAmount)
468468 else (_qtAstR - _quoteAssetAmount)
469469 let baseAssetReserveAfter = toInt(bdivd(k, toBigInt(muld(quoteAssetReserveAfter, _qtAstW))))
470470 let amountBaseAssetBoughtAbs = divd(abs((baseAssetReserveAfter - _bsAstR)), _qtAstW)
471471 let amountBaseAssetBought = if (_isAdd)
472472 then amountBaseAssetBoughtAbs
473473 else -(amountBaseAssetBoughtAbs)
474474 let $t01680516968 = updateReserve(_isAdd, _quoteAssetAmount, amountBaseAssetBoughtAbs)
475475 let quoteAssetReserveAfter1 = $t01680516968._1
476476 let baseAssetReserveAfter1 = $t01680516968._2
477477 let totalPositionSizeAfter1 = $t01680516968._3
478478 let priceBefore = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
479479 let marketPrice = divd(_quoteAssetAmount, amountBaseAssetBoughtAbs)
480480 let priceDiff = abs((priceBefore - marketPrice))
481481 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
482482 let maxPriceImpactValue = maxPriceImpact()
483483 if ((priceImpact > maxPriceImpactValue))
484484 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)))
485485 else $Tuple4(amountBaseAssetBought, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1)
486486 }
487487
488488
489489 func calcRemainMarginWithFundingPayment (_oldPositionSize,_oldPositionMargin,_oldPositionCumulativePremiumFraction,_marginDelta) = {
490490 let fundingPayment = if ((_oldPositionSize != 0))
491491 then {
492492 let _latestCumulativePremiumFraction = latestCumulativePremiumFraction(_oldPositionSize)
493493 muld((_latestCumulativePremiumFraction - _oldPositionCumulativePremiumFraction), _oldPositionSize)
494494 }
495495 else 0
496496 let signedMargin = ((_marginDelta - fundingPayment) + _oldPositionMargin)
497497 let $t01845518582 = if ((0 > signedMargin))
498498 then $Tuple2(0, abs(signedMargin))
499499 else $Tuple2(abs(signedMargin), 0)
500500 let remainMargin = $t01845518582._1
501501 let badDebt = $t01845518582._2
502502 $Tuple3(remainMargin, badDebt, fundingPayment)
503503 }
504504
505505
506506 func swapOutputWithReserves (_isAdd,_baseAssetAmount,_checkMaxPriceImpact,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
507507 let priceBefore = divd(muld(_quoteAssetReserve, _quoteAssetWeight), muld(_baseAssetReserve, _baseAssetWeight))
508508 if ((_baseAssetAmount == 0))
509509 then throw("Invalid base asset amount")
510510 else {
511511 let k = calcInvariant(_quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
512512 let baseAssetPoolAmountAfter = if (_isAdd)
513513 then (_baseAssetReserve + _baseAssetAmount)
514514 else (_baseAssetReserve - _baseAssetAmount)
515515 let quoteAssetAfter = toInt(bdivd(k, toBigInt(muld(baseAssetPoolAmountAfter, _baseAssetWeight))))
516516 let quoteAssetSold = abs((quoteAssetAfter - muld(_quoteAssetReserve, _quoteAssetWeight)))
517517 let maxPriceImpactValue = maxPriceImpact()
518518 let $t01977019931 = updateReserve(!(_isAdd), quoteAssetSold, _baseAssetAmount)
519519 let quoteAssetReserveAfter1 = $t01977019931._1
520520 let baseAssetReserveAfter1 = $t01977019931._2
521521 let totalPositionSizeAfter1 = $t01977019931._3
522522 let marketPrice = divd(quoteAssetSold, _baseAssetAmount)
523523 let priceDiff = abs((priceBefore - marketPrice))
524524 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
525525 if (if ((priceImpact > maxPriceImpactValue))
526526 then _checkMaxPriceImpact
527527 else false)
528528 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)))
529529 else $Tuple7(quoteAssetSold, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1, (totalLongPositionSize() - (if (_isAdd)
530530 then abs(_baseAssetAmount)
531531 else 0)), (totalShortPositionSize() - (if (!(_isAdd))
532532 then abs(_baseAssetAmount)
533533 else 0)), priceImpact)
534534 }
535535 }
536536
537537
538538 func swapOutput (_isAdd,_baseAssetAmount,_checkMaxPriceImpact) = swapOutputWithReserves(_isAdd, _baseAssetAmount, _checkMaxPriceImpact, qtAstR(), qtAstW(), bsAstR(), bsAstW())
539539
540540
541541 func getOraclePrice () = {
542542 let oracle = valueOrErrorMessage(addressFromString(getStringValue(this, k_ora)), "")
543543 let priceKey = getStringValue(this, k_ora_key)
544544 let lastValue = valueOrErrorMessage(getInteger(oracle, priceKey), ((("Can not get oracle price. Oracle: " + toString(oracle)) + " key: ") + priceKey))
545545 let blockKey = valueOrElse(getString(this, k_ora_block_key), "")
546546 if ((blockKey != ""))
547547 then {
548548 let currentBlock = lastBlock.height
549549 let lastOracleBlock = valueOrErrorMessage(getInteger(oracle, blockKey), ((("Can not get oracle block. Oracle: " + toString(oracle)) + " key: ") + blockKey))
550550 if (((currentBlock - lastOracleBlock) > maxOracleDelay()))
551551 then throw(((("Oracle stale data. Last oracle block: " + toString(lastOracleBlock)) + " current block: ") + toString(currentBlock)))
552552 else lastValue
553553 }
554554 else lastValue
555555 }
556556
557557
558558 func isMarketClosed () = {
559559 let oracle = valueOrErrorMessage(addressFromString(getStringValue(this, k_ora)), "")
560560 let openKey = valueOrElse(getString(this, k_ora_open_key), "")
561561 if ((openKey != ""))
562562 then {
563563 let isOpen = valueOrErrorMessage(getBoolean(oracle, openKey), ((("Can not get oracle is open/closed. Oracle: " + toString(oracle)) + " key: ") + openKey))
564564 !(isOpen)
565565 }
566566 else false
567567 }
568568
569569
570570 func absPriceDiff (_oraclePrice,_quoteAssetReserve,_baseAssetReserve,_qtAstW,_bsAstW) = {
571571 let priceAfter = divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
572572 let averagePrice = divd((_oraclePrice + priceAfter), (2 * DECIMAL_UNIT))
573573 let absPriceDiff = divd(abs((_oraclePrice - priceAfter)), averagePrice)
574574 absPriceDiff
575575 }
576576
577577
578578 func requireNotOverSpreadLimit (_quoteAssetReserve,_baseAssetReserve) = {
579579 let oraclePrice = getOraclePrice()
580580 let _qtAstW = qtAstW()
581581 let _bsAstW = bsAstW()
582582 let absPriceDiffBefore = absPriceDiff(oraclePrice, qtAstR(), bsAstR(), _qtAstW, _bsAstW)
583583 let absPriceDiffAfter = absPriceDiff(oraclePrice, _quoteAssetReserve, _baseAssetReserve, _qtAstW, _bsAstW)
584584 if (if ((absPriceDiffAfter > maxPriceSpread()))
585585 then (absPriceDiffAfter > absPriceDiffBefore)
586586 else false)
587587 then throw(((("Price spread " + toString(absPriceDiffAfter)) + " > max price spread ") + toString(maxPriceSpread())))
588588 else true
589589 }
590590
591591
592592 func requireNotOverMaxOpenNotional (_longOpenNotional,_shortOpenNotional) = {
593593 let _maxOpenNotional = maxOpenNotional()
594594 if ((_longOpenNotional > _maxOpenNotional))
595595 then throw(((("Long open notional " + toString(_longOpenNotional)) + " > max open notional ") + toString(_maxOpenNotional)))
596596 else if ((_shortOpenNotional > _maxOpenNotional))
597597 then throw(((("Short open notional " + toString(_shortOpenNotional)) + " > max open notional ") + toString(_maxOpenNotional)))
598598 else true
599599 }
600600
601601
602602 func getSpotPrice () = {
603603 let _quoteAssetReserve = qtAstR()
604604 let _baseAssetReserve = bsAstR()
605605 let _qtAstW = qtAstW()
606606 let _bsAstW = bsAstW()
607607 divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
608608 }
609609
610610
611611 func isOverFluctuationLimit () = {
612612 let oraclePrice = getOraclePrice()
613613 let currentPrice = getSpotPrice()
614614 (divd(abs((oraclePrice - currentPrice)), oraclePrice) > spreadLimit())
615615 }
616616
617617
618618 func getPositionAdjustedOpenNotional (_positionSize,_option,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
619619 let positionSizeAbs = abs(_positionSize)
620620 let isShort = (0 > _positionSize)
621621 let positionNotional = if ((_option == PNL_OPTION_SPOT))
622622 then {
623623 let $t02488225102 = swapOutputWithReserves(!(isShort), positionSizeAbs, false, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
624624 let outPositionNotional = $t02488225102._1
625625 let x1 = $t02488225102._2
626626 let x2 = $t02488225102._3
627627 let x3 = $t02488225102._4
628628 outPositionNotional
629629 }
630630 else muld(positionSizeAbs, getOraclePrice())
631631 positionNotional
632632 }
633633
634634
635635 func getPositionNotionalAndUnrealizedPnlByValues (_positionSize,_positionOpenNotional,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight,_option) = if ((_positionSize == 0))
636636 then throw("Invalid position size")
637637 else {
638638 let isShort = (0 > _positionSize)
639639 let positionNotional = getPositionAdjustedOpenNotional(_positionSize, _option, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
640640 let unrealizedPnl = if (isShort)
641641 then (_positionOpenNotional - positionNotional)
642642 else (positionNotional - _positionOpenNotional)
643643 $Tuple2(positionNotional, unrealizedPnl)
644644 }
645645
646646
647647 func getPositionNotionalAndUnrealizedPnl (_trader,_option) = {
648648 let $t02652326651 = getPosition(_trader)
649649 let positionSize = $t02652326651._1
650650 let positionMargin = $t02652326651._2
651651 let positionOpenNotional = $t02652326651._3
652652 let positionLstUpdCPF = $t02652326651._4
653653 getPositionNotionalAndUnrealizedPnlByValues(positionSize, positionOpenNotional, qtAstR(), qtAstW(), bsAstR(), bsAstW(), _option)
654654 }
655655
656656
657657 func calcMarginRatio (_remainMargin,_badDebt,_positionNotional) = divd((_remainMargin - _badDebt), _positionNotional)
658658
659659
660660 func getMarginRatioByOption (_trader,_option) = {
661661 let $t02716427275 = getPosition(_trader)
662662 let positionSize = $t02716427275._1
663663 let positionMargin = $t02716427275._2
664664 let pon = $t02716427275._3
665665 let positionLstUpdCPF = $t02716427275._4
666666 let $t02728127374 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
667667 let positionNotional = $t02728127374._1
668668 let unrealizedPnl = $t02728127374._2
669669 let $t02737927545 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
670670 let remainMargin = $t02737927545._1
671671 let badDebt = $t02737927545._2
672672 calcMarginRatio(remainMargin, badDebt, positionNotional)
673673 }
674674
675675
676676 func getMarginRatio (_trader) = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
677677
678678
679679 func getPartialLiquidationAmount (_trader,_positionSize) = {
680680 let maximumRatio = vmax(partialLiquidationRatio(), (DECIMAL_UNIT - divd(getMarginRatio(_trader), maintenanceMarginRatio())))
681681 let maxExchangedPositionSize = muld(abs(_positionSize), maximumRatio)
682682 let swapResult = swapOutput((_positionSize > 0), maxExchangedPositionSize, false)
683683 let maxExchangedQuoteAssetAmount = swapResult._1
684684 let priceImpact = swapResult._7
685685 if ((maxPriceImpact() > priceImpact))
686686 then maxExchangedQuoteAssetAmount
687687 else {
688688 let exchangedPositionSize = muld(abs(_positionSize), partialLiquidationRatio())
689689 let exchangedQuoteAssetAmount = swapOutput((_positionSize > 0), exchangedPositionSize, false)._1
690690 exchangedQuoteAssetAmount
691691 }
692692 }
693693
694694
695695 func internalClosePosition (_trader,_checkMaxPriceImpact) = {
696696 let $t02878528913 = getPosition(_trader)
697697 let positionSize = $t02878528913._1
698698 let positionMargin = $t02878528913._2
699699 let positionOpenNotional = $t02878528913._3
700700 let positionLstUpdCPF = $t02878528913._4
701701 let unrealizedPnl = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)._2
702702 let $t02900829176 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
703703 let remainMargin = $t02900829176._1
704704 let badDebt = $t02900829176._2
705705 let exchangedPositionSize = -(positionSize)
706706 let realizedPnl = unrealizedPnl
707707 let marginToVault = -(remainMargin)
708708 let $t02930329577 = swapOutput((positionSize > 0), abs(positionSize), _checkMaxPriceImpact)
709709 let exchangedQuoteAssetAmount = $t02930329577._1
710710 let quoteAssetReserveAfter = $t02930329577._2
711711 let baseAssetReserveAfter = $t02930329577._3
712712 let totalPositionSizeAfter = $t02930329577._4
713713 let totalLongAfter = $t02930329577._5
714714 let totalShortAfter = $t02930329577._6
715715 let openInterestNotionalAfter = (openInterestNotional() - positionOpenNotional)
716716 $Tuple13(exchangedPositionSize, badDebt, realizedPnl, marginToVault, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, exchangedQuoteAssetAmount, totalLongAfter, totalShortAfter, (openInterestLong() - (if ((positionSize > 0))
717717 then positionOpenNotional
718718 else 0)), (openInterestShort() - (if ((0 > positionSize))
719719 then positionOpenNotional
720720 else 0)))
721721 }
722722
723723
724724 func getTwapSpotPrice () = {
725725 let minuteId = ((lastBlock.timestamp / 1000) / 60)
726726 let startMinuteId = (minuteId - TWAP_INTERVAL)
727727 let listStr = valueOrElse(getString(this, k_lastDataStr), "")
728728 let list = split(listStr, ",")
729729 func filterFn (accumulator,next) = if ((startMinuteId >= parseIntValue(next)))
730730 then (accumulator :+ parseIntValue(next))
731731 else accumulator
732732
733733 let listF = {
734734 let $l = list
735735 let $s = size($l)
736736 let $acc0 = nil
737737 func $f0_1 ($a,$i) = if (($i >= $s))
738738 then $a
739739 else filterFn($a, $l[$i])
740740
741741 func $f0_2 ($a,$i) = if (($i >= $s))
742742 then $a
743743 else throw("List size exceeds 20")
744744
745745 $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)
746746 }
747747 let maxIndex = if ((size(listF) > 0))
748748 then max(listF)
749749 else parseIntValue(list[0])
750750 let lastMinuteId = valueOrElse(getInteger(this, k_lastMinuteId), 0)
751751 let endLastCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(lastMinuteId))), 0)
752752 let endLastPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(lastMinuteId))), 0)
753753 let nowCumulativePrice = (endLastCumulativePrice + ((minuteId - lastMinuteId) * endLastPrice))
754754 let startLastCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(maxIndex))), 0)
755755 let startLastPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(maxIndex))), 0)
756756 let startCumulativePrice = (startLastCumulativePrice + ((startMinuteId - maxIndex) * startLastPrice))
757757 ((nowCumulativePrice - startCumulativePrice) / TWAP_INTERVAL)
758758 }
759759
760760
761761 func getTerminalAmmState () = {
762762 let _positionSize = totalPositionSize()
763763 if ((_positionSize == 0))
764764 then $Tuple2(qtAstR(), bsAstR())
765765 else {
766766 let direction = (_positionSize > 0)
767767 let $t03170031879 = swapOutput(direction, abs(_positionSize), false)
768768 let currentNetMarketValue = $t03170031879._1
769769 let terminalQuoteAssetReserve = $t03170031879._2
770770 let terminalBaseAssetReserve = $t03170031879._3
771771 $Tuple2(terminalQuoteAssetReserve, terminalBaseAssetReserve)
772772 }
773773 }
774774
775775
776776 func getQuoteAssetWeight (baseAssetReserve,totalPositionSize,quoteAssetReserve,targetPrice) = {
777777 let b = toBigInt(baseAssetReserve)
778778 let sz = toBigInt(totalPositionSize)
779779 let q = toBigInt(quoteAssetReserve)
780780 let p = toBigInt(targetPrice)
781781 let bs2 = bpowd((b + sz), toBigInt((2 * DECIMAL_UNIT)))
782782 let qbs2 = bmuld(q, bs2)
783783 let ps4 = (toBigInt(4) * bmuld(p, sz))
784784 let sqr = bsqrtd(bmuld(qbs2, (q - ps4)))
785785 let bq = bmuld(b, q)
786786 let qs = bmuld(q, sz)
787787 let top = ((-(sqr) + bq) + qs)
788788 let bot = (toBigInt(2) * bmuld(q, sz))
789789 let result = bdivd(top, bot)
790790 toInt(result)
791791 }
792792
793793
794794 func getSyncTerminalPrice (_terminalPrice,_qtAstR,_bsAstR) = {
795795 let _positionSize = totalPositionSize()
796796 if ((_positionSize == 0))
797797 then {
798798 let newQtAstW = divd(muld(_terminalPrice, _bsAstR), _qtAstR)
799799 $Tuple3(newQtAstW, DECIMAL_UNIT, 0)
800800 }
801801 else {
802802 let direction = (_positionSize > 0)
803803 let currentNetMarketValue = swapOutput(direction, abs(_positionSize), false)._1
804804 let newQtAstW = getQuoteAssetWeight(_bsAstR, _positionSize, _qtAstR, _terminalPrice)
805805 let newBsAstW = DECIMAL_UNIT
806806 let marginToVault = getPositionNotionalAndUnrealizedPnlByValues(_positionSize, currentNetMarketValue, _qtAstR, newQtAstW, _bsAstR, newBsAstW, PNL_OPTION_SPOT)._2
807807 $Tuple3(newQtAstW, newBsAstW, marginToVault)
808808 }
809809 }
810810
811811
812812 func getFunding () = {
813813 let underlyingPrice = getOraclePrice()
814814 let spotTwapPrice = getTwapSpotPrice()
815815 let premium = (spotTwapPrice - underlyingPrice)
816816 if (if (if ((totalShortPositionSize() == 0))
817817 then true
818818 else (totalLongPositionSize() == 0))
819819 then true
820820 else isMarketClosed())
821821 then $Tuple2(0, 0)
822822 else if ((0 > premium))
823823 then {
824824 let shortPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
825825 let longPremiumFraction = divd(muld(shortPremiumFraction, totalShortPositionSize()), totalLongPositionSize())
826826 $Tuple2(shortPremiumFraction, longPremiumFraction)
827827 }
828828 else {
829829 let longPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
830830 let shortPremiumFraction = divd(muld(longPremiumFraction, totalLongPositionSize()), totalShortPositionSize())
831831 $Tuple2(shortPremiumFraction, longPremiumFraction)
832832 }
833833 }
834834
835835
836836 func getAdjustedFee (_artifactId,_baseFeeDiscount) = {
837837 let baseFeeRaw = fee()
838838 let baseFee = muld(baseFeeRaw, _baseFeeDiscount)
839839 let $t03492735422 = if ((_artifactId != ""))
840840 then {
841841 let artifactKind = strA(nftManagerAddress(), toCompositeKey(k_token_type, _artifactId))
842842 if ((artifactKind == FEE_REDUCTION_TOKEN_TYPE))
843843 then {
844844 let reduction = intA(nftManagerAddress(), toCompositeKey(k_token_param, _artifactId))
845845 let adjustedFee = muld(baseFee, reduction)
846846 $Tuple2(adjustedFee, true)
847847 }
848848 else throw("Invalid attached artifact")
849849 }
850850 else $Tuple2(baseFee, false)
851851 let adjustedFee = $t03492735422._1
852852 let burnArtifact = $t03492735422._2
853853 $Tuple2(adjustedFee, burnArtifact)
854854 }
855855
856856
857857 func isSameAssetOrNoPosition (_trader,_assetId) = {
858858 let oldPositionSize = getPosition(_trader)._1
859859 if ((oldPositionSize == 0))
860860 then true
861861 else (getPositionAsset(_trader) == _assetId)
862862 }
863863
864864
865865 func isSameAsset (_trader,_assetId) = (getPositionAsset(_trader) == _assetId)
866866
867867
868868 func getBorrowedByTraderInMarketKey (_amm,_assetId,_trader) = ((((((k_trader_market_asset_collateral + "_") + _amm) + "_") + _assetId) + "_") + _trader)
869869
870870
871871 func getBorrowedByTrader (_trader) = {
872872 let positionAsset = getPositionAsset(_trader)
873873 if ((positionAsset == toBase58String(quoteAsset())))
874874 then $Tuple2(0, positionAsset)
875875 else {
876876 let key = getBorrowedByTraderInMarketKey(toString(this), positionAsset, _trader)
877877 let borrow = valueOrElse(getInteger(collateralAddress(), key), 0)
878878 $Tuple2(borrow, positionAsset)
879879 }
880880 }
881881
882882
883883 func getForTraderWithArtifact (_trader,_artifactId) = {
884884 let doGetFeeDiscount = invoke(minerAddress(), "computeFeeDiscount", [_trader], nil)
885885 if ((doGetFeeDiscount == doGetFeeDiscount))
886886 then {
887887 let feeDiscount = match doGetFeeDiscount {
888888 case x: Int =>
889889 x
890890 case _ =>
891891 throw("Invalid computeFeeDiscount result")
892892 }
893893 let $t03665336727 = getAdjustedFee(_artifactId, feeDiscount)
894894 let adjustedFee = $t03665336727._1
895895 let burnArtifact = $t03665336727._2
896896 $Tuple2(adjustedFee, burnArtifact)
897897 }
898898 else throw("Strict value is not equal to itself.")
899899 }
900900
901901
902902 func getArtifactId (i) = {
903903 let artifactId = if ((size(i.payments) > 1))
904904 then toBase58String(valueOrErrorMessage(i.payments[1].assetId, "Invalid artifactId"))
905905 else ""
906906 artifactId
907907 }
908908
909909
910910 func distributeFee (_feeAmount) = {
911911 let feeToStakers = muld(_feeAmount, feeToStakersPercent())
912912 let feeToVault = (_feeAmount - feeToStakers)
913913 $Tuple2(feeToStakers, feeToVault)
914914 }
915915
916916
917917 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)]
918918
919919
920920 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)]
921921
922922
923923 func updatePositionAsset (_address,_assetId) = [StringEntry(toCompositeKey(k_positionAsset, _address), _assetId)]
924924
925925
926926 func incrementPositionSequenceNumber (isNewPosition,_address) = if (isNewPosition)
927927 then {
928928 let currentSequence = lastSequence()
929929 [IntegerEntry(toCompositeKey(k_positionSequence, _address), (currentSequence + 1)), IntegerEntry(k_sequence, (currentSequence + 1))]
930930 }
931931 else nil
932932
933933
934934 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)]
935935
936936
937937 func appendTwap (_price) = {
938938 let minuteId = ((lastBlock.timestamp / 1000) / 60)
939939 let previousMinuteId = valueOrElse(getInteger(this, k_lastMinuteId), 0)
940940 if ((previousMinuteId > minuteId))
941941 then throw("TWAP out-of-order")
942942 else {
943943 let lastMinuteId = if ((previousMinuteId == 0))
944944 then minuteId
945945 else previousMinuteId
946946 if ((minuteId > previousMinuteId))
947947 then {
948948 let prevCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(previousMinuteId))), 0)
949949 let prevPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(previousMinuteId))), _price)
950950 let lastCumulativePrice = (prevCumulativePrice + ((minuteId - lastMinuteId) * prevPrice))
951951 let list = pushToQueue(strToList(valueOrElse(getString(this, k_lastDataStr), "")), TWAP_INTERVAL, toString(minuteId))
952952 [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))]
953953 }
954954 else {
955955 let twapDataPreviousMinuteId = valueOrElse(getInteger(this, toCompositeKey(k_twapDataPreviousMinuteId, toString(minuteId))), 0)
956956 let prevCumulativePrice = valueOrElse(getInteger(this, toCompositeKey(k_twapDataLastCumulativePrice, toString(twapDataPreviousMinuteId))), 0)
957957 let prevPrice = valueOrElse(getInteger(this, toCompositeKey(k_twapDataLastPrice, toString(twapDataPreviousMinuteId))), _price)
958958 let lastCumulativePrice = (prevCumulativePrice + ((minuteId - twapDataPreviousMinuteId) * prevPrice))
959959 [IntegerEntry(toCompositeKey(k_twapDataLastCumulativePrice, toString(minuteId)), lastCumulativePrice), IntegerEntry(toCompositeKey(k_twapDataLastPrice, toString(minuteId)), _price)]
960960 }
961961 }
962962 }
963963
964964
965965 func updateAmmReserves (_qtAstR,_bsAstR) = [IntegerEntry(k_quoteAssetReserve, _qtAstR), IntegerEntry(k_baseAssetReserve, _bsAstR)]
966966
967967
968968 func updateAmmWeights (_qtAstW,_bsAstW) = [IntegerEntry(k_quoteAssetWeight, _qtAstW), IntegerEntry(k_baseAssetWeight, _bsAstW)]
969969
970970
971971 func updateAmm (_qtAstR,_bsAstR,_totalPositionSizeAfter,_openInterestNotional,_totalLongPositionSize,_totalShortPositionSize,_totalLongOpenNotional,_totalShortOpenNotional) = {
972972 let _qtAstW = qtAstW()
973973 let _bsAstW = bsAstW()
974974 if (((_totalLongPositionSize - _totalShortPositionSize) != _totalPositionSizeAfter))
975975 then throw(((((("Invalid AMM state data: " + toString(_totalLongPositionSize)) + " + ") + toString(_totalShortPositionSize)) + " != ") + toString(_totalPositionSizeAfter)))
976976 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))))
977977 }
978978
979979
980980 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))]
981981
982982
983983 func withdraw (_address,_amount) = {
984984 let balance = assetBalance(this, quoteAsset())
985985 if ((_amount > balance))
986986 then throw(((("Unable to withdraw " + toString(_amount)) + " from contract balance ") + toString(balance)))
987987 else [ScriptTransfer(_address, _amount, quoteAsset())]
988988 }
989989
990990
991991 func updateBalance (i) = if ((0 > i))
992992 then throw("Balance")
993993 else [IntegerEntry(k_balance, i)]
994994
995995
996996 func transferFee (i) = [ScriptTransfer(stakingAddress(), i, quoteAsset())]
997997
998998
999999 func doBurnArtifact (_burnArtifact,i) = if (_burnArtifact)
10001000 then [Burn(valueOrErrorMessage(i.payments[1].assetId, "Invalid artifact"), 1)]
10011001 else nil
10021002
10031003
10041004 @Callable(i)
10051005 func pause () = if ((i.caller != adminAddress()))
10061006 then throw("Invalid pause params")
10071007 else [BooleanEntry(k_paused, true)]
10081008
10091009
10101010
10111011 @Callable(i)
10121012 func unpause () = if ((i.caller != adminAddress()))
10131013 then throw("Invalid unpause params")
10141014 else [BooleanEntry(k_paused, false)]
10151015
10161016
10171017
10181018 @Callable(i)
10191019 func setCloseOnly () = if ((i.caller != adminAddress()))
10201020 then throw("Invalid setCloseOnly params")
10211021 else [BooleanEntry(k_closeOnly, true)]
10221022
10231023
10241024
10251025 @Callable(i)
10261026 func unsetCloseOnly () = if ((i.caller != adminAddress()))
10271027 then throw("Invalid unsetCloseOnly params")
10281028 else [BooleanEntry(k_closeOnly, false)]
10291029
10301030
10311031
10321032 @Callable(i)
10331033 func addLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
10341034 then true
10351035 else (0 >= _quoteAssetAmount))
10361036 then throw("Invalid addLiquidity params")
10371037 else {
10381038 let _qtAstR = qtAstR()
10391039 let _bsAstR = bsAstR()
10401040 let _qtAstW = qtAstW()
10411041 let _bsAstW = bsAstW()
10421042 let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
10431043 let qtAstRAfter = (_qtAstR + _quoteAssetAmount)
10441044 let baseAssetAmountToAdd = (divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR)
10451045 let bsAstRAfter = (_bsAstR + baseAssetAmountToAdd)
10461046 let $t04574945900 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
10471047 let newQuoteAssetWeight = $t04574945900._1
10481048 let newBaseAssetWeight = $t04574945900._2
10491049 let marginToVault = $t04574945900._3
10501050 let doExchangePnL = if ((marginToVault != 0))
10511051 then {
10521052 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
10531053 if ((doExchangePnL == doExchangePnL))
10541054 then nil
10551055 else throw("Strict value is not equal to itself.")
10561056 }
10571057 else nil
10581058 if ((doExchangePnL == doExchangePnL))
10591059 then (updateAmmReserves(qtAstRAfter, bsAstRAfter) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
10601060 else throw("Strict value is not equal to itself.")
10611061 }
10621062
10631063
10641064
10651065 @Callable(i)
10661066 func removeLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
10671067 then true
10681068 else (0 >= _quoteAssetAmount))
10691069 then throw("Invalid removeLiquidity params")
10701070 else {
10711071 let _qtAstR = qtAstR()
10721072 let _bsAstR = bsAstR()
10731073 let _qtAstW = qtAstW()
10741074 let _bsAstW = bsAstW()
10751075 let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
10761076 let baseAssetAmountToRemove = divd(_quoteAssetAmount, price)
10771077 let qtAstRAfter = (_qtAstR - _quoteAssetAmount)
10781078 let bsAstRAfter = (_bsAstR - baseAssetAmountToRemove)
10791079 updateAmmReserves(qtAstRAfter, bsAstRAfter)
10801080 }
10811081
10821082
10831083
10841084 @Callable(i)
10851085 func changeSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay) = if ((i.caller != adminAddress()))
10861086 then throw("Invalid changeSettings params")
10871087 else updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact, _partialLiquidationRatio, _maxPriceSpread, _maxOpenNotional, _feeToStakersPercent, _maxOracleDelay)
10881088
10891089
10901090
10911091 @Callable(i)
10921092 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))
10931093 then true
10941094 else (0 >= _bsAstR))
10951095 then true
10961096 else (0 >= _fundingPeriod))
10971097 then true
10981098 else (0 >= _initMarginRatio))
10991099 then true
11001100 else (0 >= _mmr))
11011101 then true
11021102 else (0 >= _liquidationFeeRatio))
11031103 then true
11041104 else (0 >= _fee))
11051105 then true
11061106 else (0 >= _spreadLimit))
11071107 then true
11081108 else (0 >= _maxPriceImpact))
11091109 then true
11101110 else (0 >= _partialLiquidationRatio))
11111111 then true
11121112 else (0 >= _maxPriceSpread))
11131113 then true
11141114 else (0 >= _maxOpenNotional))
11151115 then true
11161116 else (0 >= _feeToStakersPercent))
11171117 then true
11181118 else (_feeToStakersPercent > DECIMAL_UNIT))
11191119 then true
11201120 else (0 >= _maxOracleDelay))
11211121 then true
11221122 else initialized())
11231123 then throw("Invalid initialize parameters")
11241124 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)])
11251125
11261126
11271127
11281128 @Callable(i)
11291129 func decreasePosition (_amount,_leverage,_minBaseAssetAmount) = {
11301130 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
11311131 if ((sync == sync))
11321132 then {
11331133 let _trader = getActualCaller(i)
11341134 if (if (if (if (if (if ((0 >= _amount))
11351135 then true
11361136 else !(initialized()))
11371137 then true
11381138 else !(requireMoreMarginRatio(divd(DECIMAL_UNIT, _leverage), initMarginRatio(), true)))
11391139 then true
11401140 else !(requireOpenPosition(_trader)))
11411141 then true
11421142 else paused())
11431143 then true
11441144 else isMarketClosed())
11451145 then throw("Invalid decreasePosition parameters")
11461146 else {
11471147 let $t04976749907 = getPosition(_trader)
11481148 let oldPositionSize = $t04976749907._1
11491149 let oldPositionMargin = $t04976749907._2
11501150 let oldPositionOpenNotional = $t04976749907._3
11511151 let oldPositionLstUpdCPF = $t04976749907._4
11521152 let _direction = if ((oldPositionSize > 0))
11531153 then DIR_SHORT
11541154 else DIR_LONG
11551155 let isAdd = (_direction == DIR_LONG)
11561156 let openNotional = muld(_amount, _leverage)
11571157 let $t05008050184 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
11581158 let oldPositionNotional = $t05008050184._1
11591159 let unrealizedPnl = $t05008050184._2
11601160 let $t05019052848 = if ((oldPositionNotional > openNotional))
11611161 then {
11621162 let $t05060550789 = swapInput(isAdd, openNotional)
11631163 let exchangedPositionSize = $t05060550789._1
11641164 let quoteAssetReserveAfter = $t05060550789._2
11651165 let baseAssetReserveAfter = $t05060550789._3
11661166 let totalPositionSizeAfter = $t05060550789._4
11671167 let exchangedPositionSizeAbs = abs(exchangedPositionSize)
11681168 if (if ((_minBaseAssetAmount != 0))
11691169 then (_minBaseAssetAmount > exchangedPositionSizeAbs)
11701170 else false)
11711171 then throw(((("Too little base asset exchanged, got " + toString(exchangedPositionSizeAbs)) + " expected ") + toString(_minBaseAssetAmount)))
11721172 else {
11731173 let realizedPnl = divd(muld(unrealizedPnl, exchangedPositionSizeAbs), abs(oldPositionSize))
11741174 let $t05122651471 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
11751175 let remainMargin = $t05122651471._1
11761176 let badDebt = $t05122651471._2
11771177 let fundingPayment = $t05122651471._3
11781178 let exchangedQuoteAssetAmount = openNotional
11791179 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
11801180 let remainOpenNotional = if ((oldPositionSize > 0))
11811181 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
11821182 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
11831183 let newPositionSize = (oldPositionSize + exchangedPositionSize)
11841184 $Tuple12(newPositionSize, remainMargin, abs(remainOpenNotional), latestCumulativePremiumFraction(newPositionSize), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, (openInterestNotional() - openNotional), (totalLongPositionSize() - (if ((newPositionSize > 0))
11851185 then abs(exchangedPositionSize)
11861186 else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
11871187 then abs(exchangedPositionSize)
11881188 else 0)), (openInterestLong() - (if ((newPositionSize > 0))
11891189 then openNotional
11901190 else 0)), (openInterestShort() - (if ((0 > newPositionSize))
11911191 then openNotional
11921192 else 0)))
11931193 }
11941194 }
11951195 else throw("Close position first")
11961196 let newPositionSize = $t05019052848._1
11971197 let newPositionRemainMargin = $t05019052848._2
11981198 let newPositionOpenNotional = $t05019052848._3
11991199 let newPositionLatestCPF = $t05019052848._4
12001200 let baseAssetReserveAfter = $t05019052848._5
12011201 let quoteAssetReserveAfter = $t05019052848._6
12021202 let totalPositionSizeAfter = $t05019052848._7
12031203 let openInterestNotionalAfter = $t05019052848._8
12041204 let totalLongAfter = $t05019052848._9
12051205 let totalShortAfter = $t05019052848._10
12061206 let totalLongOpenInterestAfter = $t05019052848._11
12071207 let totalShortOpenInterestAfter = $t05019052848._12
12081208 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
12091209 if ((notifyNotional == notifyNotional))
12101210 then (updatePosition(_trader, newPositionSize, newPositionRemainMargin, newPositionOpenNotional, newPositionLatestCPF) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter))
12111211 else throw("Strict value is not equal to itself.")
12121212 }
12131213 }
12141214 else throw("Strict value is not equal to itself.")
12151215 }
12161216
12171217
12181218
12191219 @Callable(i)
12201220 func increasePosition (_direction,_leverage,_minBaseAssetAmount,_refLink) = {
12211221 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
12221222 if ((sync == sync))
12231223 then {
12241224 let _trader = getActualCaller(i)
12251225 let _rawAmount = i.payments[0].amount
12261226 let _assetId = i.payments[0].assetId
12271227 let _assetIdStr = toBase58String(value(_assetId))
12281228 let isQuoteAsset = (_assetId == quoteAsset())
12291229 let isCollateralAsset = isWhitelistAsset(_assetIdStr)
12301230 if (if (if (if (if (if (if (if (if (if ((_direction != DIR_LONG))
12311231 then (_direction != DIR_SHORT)
12321232 else false)
12331233 then true
12341234 else (0 >= _rawAmount))
12351235 then true
12361236 else !(initialized()))
12371237 then true
12381238 else if (!(isQuoteAsset))
12391239 then !(isCollateralAsset)
12401240 else false)
12411241 then true
12421242 else !(isSameAssetOrNoPosition(_trader, _assetIdStr)))
12431243 then true
12441244 else !(requireMoreMarginRatio(divd(DECIMAL_UNIT, _leverage), initMarginRatio(), true)))
12451245 then true
12461246 else paused())
12471247 then true
12481248 else closeOnly())
12491249 then true
12501250 else isMarketClosed())
12511251 then throw("Invalid increasePosition parameters")
12521252 else {
12531253 let $t05431054395 = getForTraderWithArtifact(_trader, getArtifactId(i))
12541254 let adjustedFee = $t05431054395._1
12551255 let burnArtifact = $t05431054395._2
12561256 let rawFeeAmount = muld(_rawAmount, adjustedFee)
12571257 let _amount = (_rawAmount - rawFeeAmount)
12581258 let distributeFeeAmount = if (isCollateralAsset)
12591259 then {
12601260 let doBorrow = invoke(collateralAddress(), "borrow", [_trader], [AttachedPayment(_assetId, _amount)])
12611261 if ((doBorrow == doBorrow))
12621262 then {
12631263 let balanceBefore = assetBalance(this, quoteAsset())
12641264 if ((balanceBefore == balanceBefore))
12651265 then {
12661266 let doSwap = invoke(swapAddress(), "swap", [toBase58String(quoteAsset()), 0], [AttachedPayment(_assetId, rawFeeAmount)])
12671267 if ((doSwap == doSwap))
12681268 then {
12691269 let balanceAfter = assetBalance(this, quoteAsset())
12701270 if ((balanceAfter == balanceAfter))
12711271 then {
12721272 let exchangedAmount = (balanceAfter - balanceBefore)
12731273 if ((exchangedAmount == exchangedAmount))
12741274 then exchangedAmount
12751275 else throw("Strict value is not equal to itself.")
12761276 }
12771277 else throw("Strict value is not equal to itself.")
12781278 }
12791279 else throw("Strict value is not equal to itself.")
12801280 }
12811281 else throw("Strict value is not equal to itself.")
12821282 }
12831283 else throw("Strict value is not equal to itself.")
12841284 }
12851285 else rawFeeAmount
12861286 if ((distributeFeeAmount == distributeFeeAmount))
12871287 then {
12881288 let referrerFeeAny = invoke(referralAddress(), "acceptPaymentWithLink", [_trader, _refLink], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
12891289 if ((referrerFeeAny == referrerFeeAny))
12901290 then {
12911291 let referrerFee = match referrerFeeAny {
12921292 case x: Int =>
12931293 x
12941294 case _ =>
12951295 throw("Invalid referrerFee")
12961296 }
12971297 let feeAmount = (distributeFeeAmount - referrerFee)
12981298 let $t05571155851 = getPosition(_trader)
12991299 let oldPositionSize = $t05571155851._1
13001300 let oldPositionMargin = $t05571155851._2
13011301 let oldPositionOpenNotional = $t05571155851._3
13021302 let oldPositionLstUpdCPF = $t05571155851._4
13031303 let isNewPosition = (oldPositionSize == 0)
13041304 let isSameDirection = if ((oldPositionSize > 0))
13051305 then (_direction == DIR_LONG)
13061306 else (_direction == DIR_SHORT)
13071307 let expandExisting = if (!(isNewPosition))
13081308 then isSameDirection
13091309 else false
13101310 let isAdd = (_direction == DIR_LONG)
13111311 let $t05614059181 = if (if (isNewPosition)
13121312 then true
13131313 else expandExisting)
13141314 then {
13151315 let openNotional = muld(_amount, _leverage)
13161316 let $t05660256775 = swapInput(isAdd, openNotional)
13171317 let amountBaseAssetBought = $t05660256775._1
13181318 let quoteAssetReserveAfter = $t05660256775._2
13191319 let baseAssetReserveAfter = $t05660256775._3
13201320 let totalPositionSizeAfter = $t05660256775._4
13211321 if (if ((_minBaseAssetAmount != 0))
13221322 then (_minBaseAssetAmount > abs(amountBaseAssetBought))
13231323 else false)
13241324 then throw(((("Limit error: " + toString(abs(amountBaseAssetBought))) + " < ") + toString(_minBaseAssetAmount)))
13251325 else {
13261326 let newPositionSize = (oldPositionSize + amountBaseAssetBought)
13271327 let totalLongOpenInterestAfter = (openInterestLong() + (if ((newPositionSize > 0))
13281328 then openNotional
13291329 else 0))
13301330 let totalShortOpenInterestAfter = (openInterestShort() + (if ((0 > newPositionSize))
13311331 then openNotional
13321332 else 0))
13331333 let increaseMarginRequirement = divd(openNotional, _leverage)
13341334 let $t05738357622 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, increaseMarginRequirement)
13351335 let remainMargin = $t05738357622._1
13361336 let x1 = $t05738357622._2
13371337 let x2 = $t05738357622._3
13381338 if (!(requireNotOverSpreadLimit(quoteAssetReserveAfter, baseAssetReserveAfter)))
13391339 then throw("Over max spread limit")
13401340 else if (!(requireNotOverMaxOpenNotional(totalLongOpenInterestAfter, totalShortOpenInterestAfter)))
13411341 then throw("Over max open notional")
13421342 else $Tuple12(newPositionSize, remainMargin, (oldPositionOpenNotional + openNotional), latestCumulativePremiumFraction(newPositionSize), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, (openInterestNotional() + openNotional), (totalLongPositionSize() + (if ((newPositionSize > 0))
13431343 then abs(amountBaseAssetBought)
13441344 else 0)), (totalShortPositionSize() + (if ((0 > newPositionSize))
13451345 then abs(amountBaseAssetBought)
13461346 else 0)), totalLongOpenInterestAfter, totalShortOpenInterestAfter)
13471347 }
13481348 }
13491349 else {
13501350 let openNotional = muld(_amount, _leverage)
13511351 let $t05888158997 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
13521352 let oldPositionNotional = $t05888158997._1
13531353 let unrealizedPnl = $t05888158997._2
13541354 if ((oldPositionNotional > openNotional))
13551355 then throw("Use decreasePosition to decrease position size")
13561356 else throw("Close position first")
13571357 }
13581358 let newPositionSize = $t05614059181._1
13591359 let newPositionRemainMargin = $t05614059181._2
13601360 let newPositionOpenNotional = $t05614059181._3
13611361 let newPositionLatestCPF = $t05614059181._4
13621362 let baseAssetReserveAfter = $t05614059181._5
13631363 let quoteAssetReserveAfter = $t05614059181._6
13641364 let totalPositionSizeAfter = $t05614059181._7
13651365 let openInterestNotionalAfter = $t05614059181._8
13661366 let totalLongAfter = $t05614059181._9
13671367 let totalShortAfter = $t05614059181._10
13681368 let totalLongOpenInterestAfter = $t05614059181._11
13691369 let totalShortOpenInterestAfter = $t05614059181._12
13701370 let $t05918759244 = distributeFee(feeAmount)
13711371 let feeToStakers = $t05918759244._1
13721372 let feeToVault = $t05918759244._2
13731373 let stake = if (isQuoteAsset)
13741374 then {
13751375 let stake = invoke(vaultAddress(), "addLocked", [false], [AttachedPayment(quoteAsset(), _amount)])
13761376 if ((stake == stake))
13771377 then nil
13781378 else throw("Strict value is not equal to itself.")
13791379 }
13801380 else nil
13811381 if ((stake == stake))
13821382 then {
13831383 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
13841384 if ((depositInsurance == depositInsurance))
13851385 then {
13861386 let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, feeAmount], nil)
13871387 if ((notifyFee == notifyFee))
13881388 then {
13891389 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
13901390 if ((notifyNotional == notifyNotional))
13911391 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))
13921392 else throw("Strict value is not equal to itself.")
13931393 }
13941394 else throw("Strict value is not equal to itself.")
13951395 }
13961396 else throw("Strict value is not equal to itself.")
13971397 }
13981398 else throw("Strict value is not equal to itself.")
13991399 }
14001400 else throw("Strict value is not equal to itself.")
14011401 }
14021402 else throw("Strict value is not equal to itself.")
14031403 }
14041404 }
14051405 else throw("Strict value is not equal to itself.")
14061406 }
14071407
14081408
14091409
14101410 @Callable(i)
14111411 func addMargin () = {
14121412 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
14131413 if ((sync == sync))
14141414 then {
14151415 let _trader = toString(i.caller)
14161416 let _rawAmount = i.payments[0].amount
14171417 let _assetId = i.payments[0].assetId
14181418 let _assetIdStr = toBase58String(value(_assetId))
14191419 let isQuoteAsset = (_assetId == quoteAsset())
14201420 let isCollateralAsset = isWhitelistAsset(_assetIdStr)
14211421 if (if (if (if (if (if (if (if (!(isQuoteAsset))
14221422 then !(isCollateralAsset)
14231423 else false)
14241424 then true
14251425 else !(requireOpenPosition(toString(i.caller))))
14261426 then true
14271427 else !(isSameAsset(_trader, _assetIdStr)))
14281428 then true
14291429 else !(initialized()))
14301430 then true
14311431 else paused())
14321432 then true
14331433 else closeOnly())
14341434 then true
14351435 else isMarketClosed())
14361436 then throw("Invalid addMargin parameters")
14371437 else {
14381438 let $t06121661301 = getForTraderWithArtifact(_trader, getArtifactId(i))
14391439 let adjustedFee = $t06121661301._1
14401440 let burnArtifact = $t06121661301._2
14411441 let rawFeeAmount = muld(_rawAmount, adjustedFee)
14421442 let _amount = (_rawAmount - rawFeeAmount)
14431443 let distributeFeeAmount = if (isCollateralAsset)
14441444 then {
14451445 let doBorrow = invoke(collateralAddress(), "borrow", [_trader], [AttachedPayment(_assetId, _amount)])
14461446 if ((doBorrow == doBorrow))
14471447 then {
14481448 let balanceBefore = assetBalance(this, quoteAsset())
14491449 if ((balanceBefore == balanceBefore))
14501450 then {
14511451 let doSwap = invoke(swapAddress(), "swap", [toBase58String(quoteAsset()), 0], [AttachedPayment(_assetId, rawFeeAmount)])
14521452 if ((doSwap == doSwap))
14531453 then {
14541454 let balanceAfter = assetBalance(this, quoteAsset())
14551455 if ((balanceAfter == balanceAfter))
14561456 then {
14571457 let exchangedAmount = (balanceAfter - balanceBefore)
14581458 if ((exchangedAmount == exchangedAmount))
14591459 then exchangedAmount
14601460 else throw("Strict value is not equal to itself.")
14611461 }
14621462 else throw("Strict value is not equal to itself.")
14631463 }
14641464 else throw("Strict value is not equal to itself.")
14651465 }
14661466 else throw("Strict value is not equal to itself.")
14671467 }
14681468 else throw("Strict value is not equal to itself.")
14691469 }
14701470 else rawFeeAmount
14711471 if ((distributeFeeAmount == distributeFeeAmount))
14721472 then {
14731473 let referrerFeeAny = invoke(referralAddress(), "acceptPayment", [_trader], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
14741474 if ((referrerFeeAny == referrerFeeAny))
14751475 then {
14761476 let referrerFee = match referrerFeeAny {
14771477 case x: Int =>
14781478 x
14791479 case _ =>
14801480 throw("Invalid referrerFee")
14811481 }
14821482 let feeAmount = (distributeFeeAmount - referrerFee)
14831483 let $t06260062740 = getPosition(_trader)
14841484 let oldPositionSize = $t06260062740._1
14851485 let oldPositionMargin = $t06260062740._2
14861486 let oldPositionOpenNotional = $t06260062740._3
14871487 let oldPositionLstUpdCPF = $t06260062740._4
14881488 let $t06274662803 = distributeFee(feeAmount)
14891489 let feeToStakers = $t06274662803._1
14901490 let feeToVault = $t06274662803._2
14911491 let stake = if (isQuoteAsset)
14921492 then {
14931493 let stake = invoke(vaultAddress(), "addLocked", [false], [AttachedPayment(quoteAsset(), _amount)])
14941494 if ((stake == stake))
14951495 then nil
14961496 else throw("Strict value is not equal to itself.")
14971497 }
14981498 else nil
14991499 if ((stake == stake))
15001500 then {
15011501 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
15021502 if ((depositInsurance == depositInsurance))
15031503 then {
15041504 let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, feeAmount], nil)
15051505 if ((notifyFee == notifyFee))
15061506 then (((updatePosition(_trader, oldPositionSize, (oldPositionMargin + _amount), oldPositionOpenNotional, oldPositionLstUpdCPF) ++ transferFee(feeToStakers)) ++ updateBalance((cbalance() + _amount))) ++ doBurnArtifact(burnArtifact, i))
15071507 else throw("Strict value is not equal to itself.")
15081508 }
15091509 else throw("Strict value is not equal to itself.")
15101510 }
15111511 else throw("Strict value is not equal to itself.")
15121512 }
15131513 else throw("Strict value is not equal to itself.")
15141514 }
15151515 else throw("Strict value is not equal to itself.")
15161516 }
15171517 }
15181518 else throw("Strict value is not equal to itself.")
15191519 }
15201520
15211521
15221522
15231523 @Callable(i)
15241524 func removeMargin (_amount) = {
15251525 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
15261526 if ((sync == sync))
15271527 then {
15281528 let _trader = toString(i.caller)
15291529 if (if (if (if (if ((0 >= _amount))
15301530 then true
15311531 else !(requireOpenPosition(_trader)))
15321532 then true
15331533 else !(initialized()))
15341534 then true
15351535 else paused())
15361536 then true
15371537 else isMarketClosed())
15381538 then throw("Invalid removeMargin parameters")
15391539 else {
15401540 let $t06393964079 = getPosition(_trader)
15411541 let oldPositionSize = $t06393964079._1
15421542 let oldPositionMargin = $t06393964079._2
15431543 let oldPositionOpenNotional = $t06393964079._3
15441544 let oldPositionLstUpdCPF = $t06393964079._4
15451545 let marginDelta = -(_amount)
15461546 let $t06411664295 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, marginDelta)
15471547 let remainMargin = $t06411664295._1
15481548 let badDebt = $t06411664295._2
15491549 if ((badDebt != 0))
15501550 then throw("Invalid removed margin amount")
15511551 else {
15521552 let marginRatio = calcMarginRatio(remainMargin, badDebt, oldPositionOpenNotional)
15531553 if (!(requireMoreMarginRatio(marginRatio, initMarginRatio(), true)))
15541554 then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
15551555 else {
15561556 let quoteAssetStr = toBase58String(quoteAsset())
15571557 let $t06473964793 = getBorrowedByTrader(_trader)
15581558 let borrowed = $t06473964793._1
15591559 let assetId = $t06473964793._2
15601560 let toRepay = if ((_amount > borrowed))
15611561 then borrowed
15621562 else _amount
15631563 let toWithdraw = if ((borrowed > _amount))
15641564 then 0
15651565 else (_amount - borrowed)
15661566 let finalBorrow = (borrowed - toRepay)
15671567 let switchPositionToQuote = if ((finalBorrow > 0))
15681568 then nil
15691569 else updatePositionAsset(_trader, quoteAssetStr)
15701570 let doSanityCheck = if (((toRepay + toWithdraw) != _amount))
15711571 then throw(((((("toRepay=" + toString(toRepay)) + " + toWithdraw=") + toString(toWithdraw)) + " != ") + toString(_amount)))
15721572 else nil
15731573 if ((doSanityCheck == doSanityCheck))
15741574 then {
15751575 let doUnstake = if ((toWithdraw > 0))
15761576 then {
15771577 let doUnstake = invoke(vaultAddress(), "withdrawLocked", [toWithdraw], nil)
15781578 if ((doUnstake == doUnstake))
15791579 then nil
15801580 else throw("Strict value is not equal to itself.")
15811581 }
15821582 else nil
15831583 if ((doUnstake == doUnstake))
15841584 then {
15851585 let returnCollateralAction = if ((toRepay > 0))
15861586 then {
15871587 let doRepay = invoke(collateralAddress(), "repay", [_trader, toRepay, assetId], nil)
15881588 if ((doRepay == doRepay))
15891589 then [ScriptTransfer(i.caller, toRepay, fromBase58String(assetId))]
15901590 else throw("Strict value is not equal to itself.")
15911591 }
15921592 else nil
15931593 if ((returnCollateralAction == returnCollateralAction))
15941594 then ((((updatePosition(_trader, oldPositionSize, remainMargin, oldPositionOpenNotional, latestCumulativePremiumFraction(oldPositionSize)) ++ (if ((toWithdraw > 0))
15951595 then withdraw(i.caller, toWithdraw)
15961596 else nil)) ++ updateBalance((cbalance() - _amount))) ++ switchPositionToQuote) ++ returnCollateralAction)
15971597 else throw("Strict value is not equal to itself.")
15981598 }
15991599 else throw("Strict value is not equal to itself.")
16001600 }
16011601 else throw("Strict value is not equal to itself.")
16021602 }
16031603 }
16041604 }
16051605 }
16061606 else throw("Strict value is not equal to itself.")
16071607 }
16081608
16091609
16101610
16111611 @Callable(i)
16121612 func closePosition (_size,_minQuoteAssetAmount) = {
16131613 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
16141614 if ((sync == sync))
16151615 then {
16161616 let _trader = getActualCaller(i)
16171617 let _traderAddress = valueOrErrorMessage(addressFromString(_trader), "Invalid caller")
16181618 if (if (if (if (if (if (!(requireOpenPosition(_trader)))
16191619 then true
16201620 else !(initialized()))
16211621 then true
16221622 else paused())
16231623 then true
16241624 else (0 >= _size))
16251625 then true
16261626 else (0 > _minQuoteAssetAmount))
16271627 then true
16281628 else isMarketClosed())
16291629 then throw("Invalid closePosition parameters")
16301630 else {
16311631 let $t06697767117 = getPosition(_trader)
16321632 let oldPositionSize = $t06697767117._1
16331633 let oldPositionMargin = $t06697767117._2
16341634 let oldPositionOpenNotional = $t06697767117._3
16351635 let oldPositionLstUpdCPF = $t06697767117._4
1636- let $t06712371769 = if ((abs(oldPositionSize) > _size))
1636+ let $t06712372201 = if ((abs(oldPositionSize) > _size))
16371637 then {
16381638 let _direction = if ((oldPositionSize > 0))
16391639 then DIR_SHORT
16401640 else DIR_LONG
16411641 let isAdd = (_direction == DIR_LONG)
16421642 let $t06771467936 = swapOutput((oldPositionSize > 0), _size, true)
16431643 let exchangedQuoteAssetAmount = $t06771467936._1
16441644 let quoteAssetReserveAfter = $t06771467936._2
16451645 let baseAssetReserveAfter = $t06771467936._3
16461646 let totalPositionSizeAfter = $t06771467936._4
16471647 let exchangedPositionSize = if ((oldPositionSize > 0))
16481648 then -(_size)
16491649 else _size
16501650 let $t06802768181 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
16511651 let oldPositionNotional = $t06802768181._1
16521652 let unrealizedPnl = $t06802768181._2
16531653 let mr = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
16541654 let realizedRatio = divd(abs(exchangedPositionSize), abs(oldPositionSize))
16551655 let realizedPnl = muld(unrealizedPnl, realizedRatio)
16561656 let remainMarginBefore = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, unrealizedPnl)._1
16571657 let $t06868268920 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
16581658 let remainMargin = $t06868268920._1
16591659 let positionBadDebt = $t06868268920._2
16601660 let fundingPayment = $t06868268920._3
16611661 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
16621662 let remainOpenNotional = if ((oldPositionSize > 0))
16631663 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
16641664 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
16651665 let newPositionOpenNotional = abs(remainOpenNotional)
1666- let newPositionMargin = muld(newPositionOpenNotional, mr)
1666+ let newPositionMargin = if ((oldPositionSize > 0))
1667+ then (muld((newPositionOpenNotional + unrealizedPnlAfter), mr) - unrealizedPnlAfter)
1668+ else (muld((newPositionOpenNotional - unrealizedPnlAfter), mr) - unrealizedPnlAfter)
16671669 let newPositionSize = (oldPositionSize + exchangedPositionSize)
16681670 let newPositionLstUpdCPF = latestCumulativePremiumFraction(newPositionSize)
16691671 let openInterestNotionalAfter = (openInterestNotional() - exchangedQuoteAssetAmount)
16701672 if (if ((_minQuoteAssetAmount != 0))
16711673 then (_minQuoteAssetAmount > exchangedQuoteAssetAmount)
16721674 else false)
16731675 then throw(((("Limit error: " + toString(exchangedQuoteAssetAmount)) + " < ") + toString(_minQuoteAssetAmount)))
1674- else $Tuple15(newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, positionBadDebt, realizedPnl, (remainMarginBefore - newPositionMargin), quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, (totalLongPositionSize() - (if ((newPositionSize > 0))
1676+ else $Tuple15(newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, positionBadDebt, realizedPnl, (remainMarginBefore - (newPositionMargin + unrealizedPnlAfter)), quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, (totalLongPositionSize() - (if ((newPositionSize > 0))
16751677 then abs(exchangedPositionSize)
16761678 else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
16771679 then abs(exchangedPositionSize)
16781680 else 0)), (openInterestLong() - (if ((newPositionSize > 0))
16791681 then exchangedQuoteAssetAmount
16801682 else 0)), (openInterestShort() - (if ((0 > newPositionSize))
16811683 then exchangedQuoteAssetAmount
16821684 else 0)))
16831685 }
16841686 else if ((_size > abs(oldPositionSize)))
16851687 then throw("Invalid closePosition parameters")
16861688 else {
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
1689+ let $t07114271561 = internalClosePosition(_trader, true)
1690+ let exchangedQuoteAssetAmount = $t07114271561._1
1691+ let positionBadDebt = $t07114271561._2
1692+ let realizedPnl = $t07114271561._3
1693+ let marginToVault = $t07114271561._4
1694+ let quoteAssetReserveAfter = $t07114271561._5
1695+ let baseAssetReserveAfter = $t07114271561._6
1696+ let totalPositionSizeAfter = $t07114271561._7
1697+ let openInterestNotionalAfter = $t07114271561._8
1698+ let x2 = $t07114271561._9
1699+ let totalLongAfter = $t07114271561._10
1700+ let totalShortAfter = $t07114271561._11
1701+ let totalLongOpenInterestAfter = $t07114271561._12
1702+ let totalShortOpenInterestAfter = $t07114271561._13
17011703 if (if ((_minQuoteAssetAmount != 0))
17021704 then (_minQuoteAssetAmount > exchangedQuoteAssetAmount)
17031705 else false)
17041706 then throw(((("Limit error: " + toString(exchangedQuoteAssetAmount)) + " < ") + toString(_minQuoteAssetAmount)))
17051707 else $Tuple15(0, 0, 0, 0, positionBadDebt, realizedPnl, marginToVault, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)
17061708 }
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
1709+ let newPositionSize = $t06712372201._1
1710+ let newPositionMargin = $t06712372201._2
1711+ let newPositionOpenNotional = $t06712372201._3
1712+ let newPositionLstUpdCPF = $t06712372201._4
1713+ let positionBadDebt = $t06712372201._5
1714+ let realizedPnl = $t06712372201._6
1715+ let marginToVault = $t06712372201._7
1716+ let quoteAssetReserveAfter = $t06712372201._8
1717+ let baseAssetReserveAfter = $t06712372201._9
1718+ let totalPositionSizeAfter = $t06712372201._10
1719+ let openInterestNotionalAfter = $t06712372201._11
1720+ let totalLongAfter = $t06712372201._12
1721+ let totalShortAfter = $t06712372201._13
1722+ let totalLongOpenInterestAfter = $t06712372201._14
1723+ let totalShortOpenInterestAfter = $t06712372201._15
17221724 if ((positionBadDebt > 0))
17231725 then throw("Unable to close position with bad debt")
17241726 else {
17251727 let withdrawAmount = abs(marginToVault)
17261728 let ammBalance = (cbalance() - withdrawAmount)
1727- let $t07197872185 = if ((0 > ammBalance))
1729+ let $t07241072617 = if ((0 > ammBalance))
17281730 then $Tuple2(0, abs(ammBalance))
17291731 else $Tuple2(ammBalance, 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))
1732+ let ammNewBalance = $t07241072617._1
1733+ let x11 = $t07241072617._2
1734+ let $t07262472678 = getBorrowedByTrader(_trader)
1735+ let borrowed = $t07262472678._1
1736+ let assetId = $t07262472678._2
1737+ let $t07269373552 = if ((borrowed > 0))
17361738 then if ((withdrawAmount >= borrowed))
17371739 then {
17381740 let doRepay = invoke(collateralAddress(), "repay", [_trader, borrowed, assetId], nil)
17391741 if ((doRepay == doRepay))
17401742 then $Tuple2([ScriptTransfer(_traderAddress, borrowed, fromBase58String(assetId))], (withdrawAmount - borrowed))
17411743 else throw("Strict value is not equal to itself.")
17421744 }
17431745 else {
17441746 let realizeAndClose = invoke(collateralAddress(), "realizePartiallyAndClose", [_trader, withdrawAmount, assetId], nil)
17451747 if ((realizeAndClose == realizeAndClose))
17461748 then $Tuple2([ScriptTransfer(_traderAddress, withdrawAmount, fromBase58String(assetId))], 0)
17471749 else throw("Strict value is not equal to itself.")
17481750 }
17491751 else $Tuple2(nil, withdrawAmount)
1750- if (($t07226173120 == $t07226173120))
1752+ if (($t07269373552 == $t07269373552))
17511753 then {
1752- let quoteWithdrawAmount = $t07226173120._2
1753- let sendCollateralAction = $t07226173120._1
1754+ let quoteWithdrawAmount = $t07269373552._2
1755+ let sendCollateralAction = $t07269373552._1
17541756 let unstake = if ((quoteWithdrawAmount > 0))
17551757 then {
17561758 let unstake = invoke(vaultAddress(), "withdrawLocked", [quoteWithdrawAmount], nil)
17571759 if ((unstake == unstake))
17581760 then nil
17591761 else throw("Strict value is not equal to itself.")
17601762 }
17611763 else nil
17621764 if ((unstake == unstake))
17631765 then {
17641766 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, 0], nil)
17651767 if ((notifyNotional == notifyNotional))
17661768 then (((((if ((newPositionSize == 0))
17671769 then deletePosition(_trader)
17681770 else updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ (if ((quoteWithdrawAmount > 0))
17691771 then withdraw(_traderAddress, quoteWithdrawAmount)
17701772 else nil)) ++ updateBalance(ammNewBalance)) ++ sendCollateralAction)
17711773 else throw("Strict value is not equal to itself.")
17721774 }
17731775 else throw("Strict value is not equal to itself.")
17741776 }
17751777 else throw("Strict value is not equal to itself.")
17761778 }
17771779 }
17781780 }
17791781 else throw("Strict value is not equal to itself.")
17801782 }
17811783
17821784
17831785
17841786 @Callable(i)
17851787 func liquidate (_trader) = {
17861788 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
17871789 if ((sync == sync))
17881790 then {
17891791 let spotMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
17901792 let marginRatio = if (isOverFluctuationLimit())
17911793 then {
17921794 let oracleMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_ORACLE)
17931795 vmax(spotMarginRatio, oracleMarginRatio)
17941796 }
17951797 else spotMarginRatio
17961798 if (if (if (if (if (!(requireMoreMarginRatio(marginRatio, maintenanceMarginRatio(), false)))
17971799 then true
17981800 else !(requireOpenPosition(_trader)))
17991801 then true
18001802 else !(initialized()))
18011803 then true
18021804 else paused())
18031805 then true
18041806 else isMarketClosed())
18051807 then throw("Unable to liquidate")
18061808 else if (if (if ((spotMarginRatio > liquidationFeeRatio()))
18071809 then (partialLiquidationRatio() > 0)
18081810 else false)
18091811 then (DECIMAL_UNIT > partialLiquidationRatio())
18101812 else false)
18111813 then {
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
1814+ let $t07587376023 = getPosition(_trader)
1815+ let oldPositionSize = $t07587376023._1
1816+ let oldPositionMargin = $t07587376023._2
1817+ let oldPositionOpenNotional = $t07587376023._3
1818+ let oldPositionLstUpdCPF = $t07587376023._4
18171819 let _direction = if ((oldPositionSize > 0))
18181820 then DIR_SHORT
18191821 else DIR_LONG
18201822 let isAdd = (_direction == DIR_LONG)
18211823 let exchangedQuoteAssetAmount = getPartialLiquidationAmount(_trader, oldPositionSize)
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
1824+ let $t07624876352 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1825+ let oldPositionNotional = $t07624876352._1
1826+ let unrealizedPnl = $t07624876352._2
1827+ let $t07636076547 = swapInput(isAdd, exchangedQuoteAssetAmount)
1828+ let exchangedPositionSize = $t07636076547._1
1829+ let quoteAssetReserveAfter = $t07636076547._2
1830+ let baseAssetReserveAfter = $t07636076547._3
1831+ let totalPositionSizeAfter = $t07636076547._4
18301832 let liquidationRatio = divd(abs(exchangedPositionSize), abs(oldPositionSize))
18311833 let realizedPnl = muld(unrealizedPnl, liquidationRatio)
1832- let $t07640476637 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1833- let remainMargin = $t07640476637._1
1834- let badDebt = $t07640476637._2
1835- let fundingPayment = $t07640476637._3
1834+ let $t07683677069 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1835+ let remainMargin = $t07683677069._1
1836+ let badDebt = $t07683677069._2
1837+ let fundingPayment = $t07683677069._3
18361838 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
18371839 let remainOpenNotional = if ((oldPositionSize > 0))
18381840 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
18391841 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
18401842 let liquidationPenalty = muld(exchangedQuoteAssetAmount, liquidationFeeRatio())
18411843 let feeToLiquidator = (liquidationPenalty / 2)
18421844 let feeToVault = (liquidationPenalty - feeToLiquidator)
18431845 let newPositionMargin = (remainMargin - liquidationPenalty)
18441846 let newPositionSize = (oldPositionSize + exchangedPositionSize)
18451847 let newPositionOpenNotional = abs(remainOpenNotional)
18461848 let newPositionLstUpdCPF = latestCumulativePremiumFraction(newPositionSize)
18471849 let openInterestNotionalAfter = (openInterestNotional() - exchangedQuoteAssetAmount)
18481850 let ammBalance = (cbalance() - liquidationPenalty)
1849- let $t07780677935 = if ((0 > ammBalance))
1851+ let $t07823878367 = if ((0 > ammBalance))
18501852 then $Tuple2(0, abs(ammBalance))
18511853 else $Tuple2(ammBalance, 0)
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
1854+ let newAmmBalance = $t07823878367._1
1855+ let x11 = $t07823878367._2
1856+ let $t07837578429 = getBorrowedByTrader(_trader)
1857+ let borrowed = $t07837578429._1
1858+ let assetId = $t07837578429._2
18571859 let doLiquidateCollateral = if ((borrowed > 0))
18581860 then {
18591861 let collateralToSell = muld(borrowed, liquidationRatio)
18601862 let realizeAndClose = invoke(collateralAddress(), "realizePartially", [_trader, assetId, collateralToSell], nil)
18611863 if ((realizeAndClose == realizeAndClose))
18621864 then nil
18631865 else throw("Strict value is not equal to itself.")
18641866 }
18651867 else nil
18661868 if ((doLiquidateCollateral == doLiquidateCollateral))
18671869 then {
18681870 let unstake = invoke(vaultAddress(), "withdrawLocked", [liquidationPenalty], nil)
18691871 if ((unstake == unstake))
18701872 then {
18711873 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
18721874 if ((depositInsurance == depositInsurance))
18731875 then {
18741876 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
18751877 if ((notifyNotional == notifyNotional))
18761878 then (((updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, (totalLongPositionSize() - (if ((newPositionSize > 0))
18771879 then abs(exchangedPositionSize)
18781880 else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
18791881 then abs(exchangedPositionSize)
18801882 else 0)), (openInterestLong() - (if ((newPositionSize > 0))
18811883 then exchangedQuoteAssetAmount
18821884 else 0)), (openInterestShort() - (if ((0 > newPositionSize))
18831885 then exchangedQuoteAssetAmount
18841886 else 0)))) ++ withdraw(i.caller, feeToLiquidator)) ++ updateBalance(newAmmBalance))
18851887 else throw("Strict value is not equal to itself.")
18861888 }
18871889 else throw("Strict value is not equal to itself.")
18881890 }
18891891 else throw("Strict value is not equal to itself.")
18901892 }
18911893 else throw("Strict value is not equal to itself.")
18921894 }
18931895 else {
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
1896+ let $t08012480619 = internalClosePosition(_trader, false)
1897+ let x1 = $t08012480619._1
1898+ let badDebt = $t08012480619._2
1899+ let x2 = $t08012480619._3
1900+ let x3 = $t08012480619._4
1901+ let quoteAssetReserveAfter = $t08012480619._5
1902+ let baseAssetReserveAfter = $t08012480619._6
1903+ let totalPositionSizeAfter = $t08012480619._7
1904+ let openInterestNotionalAfter = $t08012480619._8
1905+ let exchangedQuoteAssetAmount = $t08012480619._9
1906+ let totalLongAfter = $t08012480619._10
1907+ let totalShortAfter = $t08012480619._11
1908+ let totalLongOpenInterestAfter = $t08012480619._12
1909+ let totalShortOpenInterestAfter = $t08012480619._13
19081910 let liquidationPenalty = muld(exchangedQuoteAssetAmount, liquidationFeeRatio())
19091911 let feeToLiquidator = (liquidationPenalty / 2)
19101912 let feeToVault = (liquidationPenalty - feeToLiquidator)
19111913 let ammBalance = (cbalance() - liquidationPenalty)
1912- let $t08059580724 = if ((0 > ammBalance))
1914+ let $t08102781156 = if ((0 > ammBalance))
19131915 then $Tuple2(0, abs(ammBalance))
19141916 else $Tuple2(ammBalance, 0)
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
1917+ let newAmmBalance = $t08102781156._1
1918+ let x11 = $t08102781156._2
1919+ let $t08116481218 = getBorrowedByTrader(_trader)
1920+ let borrowed = $t08116481218._1
1921+ let assetId = $t08116481218._2
19201922 let doLiquidateCollateral = if ((borrowed > 0))
19211923 then {
19221924 let realizeAndClose = invoke(collateralAddress(), "realizePartiallyAndClose", [_trader, 0, assetId], nil)
19231925 if ((realizeAndClose == realizeAndClose))
19241926 then nil
19251927 else throw("Strict value is not equal to itself.")
19261928 }
19271929 else nil
19281930 if ((doLiquidateCollateral == doLiquidateCollateral))
19291931 then {
19301932 let x = if ((badDebt > 0))
19311933 then {
19321934 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [badDebt], nil)
19331935 if ((lockBadDebt == lockBadDebt))
19341936 then nil
19351937 else throw("Strict value is not equal to itself.")
19361938 }
19371939 else nil
19381940 if ((x == x))
19391941 then {
19401942 let unstake = invoke(vaultAddress(), "withdrawLocked", [liquidationPenalty], nil)
19411943 if ((unstake == unstake))
19421944 then {
19431945 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
19441946 if ((depositInsurance == depositInsurance))
19451947 then {
19461948 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, 0], nil)
19471949 if ((notifyNotional == notifyNotional))
19481950 then (((deletePosition(_trader) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ withdraw(i.caller, feeToLiquidator)) ++ updateBalance(newAmmBalance))
19491951 else throw("Strict value is not equal to itself.")
19501952 }
19511953 else throw("Strict value is not equal to itself.")
19521954 }
19531955 else throw("Strict value is not equal to itself.")
19541956 }
19551957 else throw("Strict value is not equal to itself.")
19561958 }
19571959 else throw("Strict value is not equal to itself.")
19581960 }
19591961 }
19601962 else throw("Strict value is not equal to itself.")
19611963 }
19621964
19631965
19641966
19651967 @Callable(i)
19661968 func payFunding () = {
19671969 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
19681970 if ((sync == sync))
19691971 then {
19701972 let fundingBlockTimestamp = nextFundingBlockTimestamp()
19711973 if (if (if ((fundingBlockTimestamp > lastBlock.timestamp))
19721974 then true
19731975 else !(initialized()))
19741976 then true
19751977 else paused())
19761978 then throw(((("Invalid funding block timestamp: " + toString(lastBlock.timestamp)) + " < ") + toString(fundingBlockTimestamp)))
19771979 else {
19781980 let underlyingPrice = getOraclePrice()
1979- let $t08265882720 = getFunding()
1980- let shortPremiumFraction = $t08265882720._1
1981- let longPremiumFraction = $t08265882720._2
1981+ let $t08309083152 = getFunding()
1982+ let shortPremiumFraction = $t08309083152._1
1983+ let longPremiumFraction = $t08309083152._2
19821984 updateFunding((fundingBlockTimestamp + fundingPeriodSeconds()), (latestLongCumulativePremiumFraction() + longPremiumFraction), (latestShortCumulativePremiumFraction() + shortPremiumFraction), divd(longPremiumFraction, underlyingPrice), divd(shortPremiumFraction, underlyingPrice))
19831985 }
19841986 }
19851987 else throw("Strict value is not equal to itself.")
19861988 }
19871989
19881990
19891991
19901992 @Callable(i)
19911993 func syncTerminalPriceToOracle () = {
19921994 let _qtAstR = qtAstR()
19931995 let _bsAstR = bsAstR()
1994- let $t08315283287 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1995- let newQuoteAssetWeight = $t08315283287._1
1996- let newBaseAssetWeight = $t08315283287._2
1997- let marginToVault = $t08315283287._3
1996+ let $t08358483719 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1997+ let newQuoteAssetWeight = $t08358483719._1
1998+ let newBaseAssetWeight = $t08358483719._2
1999+ let marginToVault = $t08358483719._3
19982000 let doExchangePnL = if ((marginToVault != 0))
19992001 then {
20002002 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
20012003 if ((doExchangePnL == doExchangePnL))
20022004 then nil
20032005 else throw("Strict value is not equal to itself.")
20042006 }
20052007 else nil
20062008 if ((doExchangePnL == doExchangePnL))
20072009 then (updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight) ++ appendTwap(divd(muld(_qtAstR, newQuoteAssetWeight), muld(_bsAstR, newBaseAssetWeight))))
20082010 else throw("Strict value is not equal to itself.")
20092011 }
20102012
20112013
20122014
20132015 @Callable(i)
20142016 func view_calcRemainMarginWithFundingPayment (_trader) = {
20152017 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
20162018 if ((sync == sync))
20172019 then {
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
2020+ let $t08428884389 = getPosition(_trader)
2021+ let positionSize = $t08428884389._1
2022+ let positionMargin = $t08428884389._2
2023+ let pon = $t08428884389._3
2024+ let positionLstUpdCPF = $t08428884389._4
2025+ let $t08439284493 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
2026+ let positionNotional = $t08439284493._1
2027+ let unrealizedPnl = $t08439284493._2
2028+ let $t08449684668 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
2029+ let remainMargin = $t08449684668._1
2030+ let badDebt = $t08449684668._2
2031+ let fundingPayment = $t08449684668._3
20302032 throw((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)))
20312033 }
20322034 else throw("Strict value is not equal to itself.")
20332035 }
20342036
20352037
20362038
20372039 @Callable(i)
20382040 func view_getPegAdjustCost (_price) = {
20392041 let _qtAstR = qtAstR()
20402042 let _bsAstR = bsAstR()
20412043 let result = getSyncTerminalPrice(_price, _qtAstR, _bsAstR)
20422044 throw(toString(result._3))
20432045 }
20442046
20452047
20462048
20472049 @Callable(i)
20482050 func view_getTerminalAmmPrice () = {
2049- let $t08465284733 = getTerminalAmmState()
2050- let terminalQuoteAssetReserve = $t08465284733._1
2051- let terminalBaseAssetReserve = $t08465284733._2
2051+ let $t08508485165 = getTerminalAmmState()
2052+ let terminalQuoteAssetReserve = $t08508485165._1
2053+ let terminalBaseAssetReserve = $t08508485165._2
20522054 let price = divd(muld(terminalQuoteAssetReserve, qtAstW()), muld(terminalBaseAssetReserve, bsAstW()))
20532055 throw(toString(price))
20542056 }
20552057
20562058
20572059
20582060 @Callable(i)
20592061 func view_getFunding () = {
20602062 let underlyingPrice = getOraclePrice()
2061- let $t08494885010 = getFunding()
2062- let shortPremiumFraction = $t08494885010._1
2063- let longPremiumFraction = $t08494885010._2
2063+ let $t08538085442 = getFunding()
2064+ let shortPremiumFraction = $t08538085442._1
2065+ let longPremiumFraction = $t08538085442._2
20642066 let longFunding = divd(longPremiumFraction, underlyingPrice)
20652067 let shortFunding = divd(shortPremiumFraction, underlyingPrice)
20662068 throw((((s(longFunding) + s(shortFunding)) + s(getTwapSpotPrice())) + s(getOraclePrice())))
20672069 }
20682070
20692071
20702072
20712073 @Callable(i)
20722074 func view_getBorrowedByTrader (_trader) = {
2073- let $t08529685350 = getBorrowedByTrader(_trader)
2074- let borrowed = $t08529685350._1
2075- let assetId = $t08529685350._2
2075+ let $t08572885782 = getBorrowedByTrader(_trader)
2076+ let borrowed = $t08572885782._1
2077+ let assetId = $t08572885782._2
20762078 throw((s(borrowed) + assetId))
20772079 }
20782080
20792081
20802082
20812083 @Callable(i)
20822084 func computeSpotPrice () = {
20832085 let result = getSpotPrice()
20842086 $Tuple2(nil, result)
20852087 }
20862088
20872089
20882090
20892091 @Callable(i)
20902092 func computeFeeForTraderWithArtifact (_trader,_artifactId) = {
20912093 let result = getForTraderWithArtifact(_trader, _artifactId)
20922094 $Tuple2(nil, result)
20932095 }
20942096
20952097
20962098 @Verifier(tx)
20972099 func verify () = sigVerify(tx.bodyBytes, tx.proofs[0], adminPublicKey())
20982100

github/deemru/w8io/873ac7e 
205.61 ms