tx · 445QpJqbK2UXvSBxJUQwL1hYHgVqBCYXhGs8aU9Mo72s

3N4SpfepyNLLb4Uc8e3xvkZew64HMcZ23oX:  -0.07500000 Waves

2022.12.29 12:40 [2381400] smart account 3N4SpfepyNLLb4Uc8e3xvkZew64HMcZ23oX > SELF 0.00000000 Waves

{ "type": 13, "id": "445QpJqbK2UXvSBxJUQwL1hYHgVqBCYXhGs8aU9Mo72s", "fee": 7500000, "feeAssetId": null, "timestamp": 1672306810407, "version": 2, "chainId": 84, "sender": "3N4SpfepyNLLb4Uc8e3xvkZew64HMcZ23oX", "senderPublicKey": "Gqr4yqnGvyo3GmKz59Qs1qfyDm5XhT134DCjiBhmD8jW", "proofs": [ "4zs4o8dQJaMv9T3RuBnyz7DLdt66ECLrJqhWkcTmfivaEJjDWarpZg7ugKE7qhptULzkpCKoBQX6KAACvCiKWkkq" ], "script": "base64:BgJ6CAISABIAEgASABIDCgEBEgMKAQESDgoMAQEBAQEBAQEBAQEBEhQKEgEBAQEBAQEICAgIAQEBAQEBARIFCgMBAQESBgoEAQEBCBIAEgMKAQESBAoCAQESAwoBCBIAEgASAwoBCBIDCgEBEgASABIDCgEIEgASBAoCCAjDAQAJa19vcmFfa2V5AglrX29yYV9rZXkAD2tfb3JhX2Jsb2NrX2tleQIPa19vcmFfYmxvY2tfa2V5AA5rX29yYV9vcGVuX2tleQIOa19vcmFfb3Blbl9rZXkABWtfb3JhAgVrX29yYQAJa19iYWxhbmNlAglrX2JhbGFuY2UACmtfc2VxdWVuY2UCCmtfc2VxdWVuY2UADmtfcG9zaXRpb25TaXplAg5rX3Bvc2l0aW9uU2l6ZQAQa19wb3NpdGlvbk1hcmdpbgIQa19wb3NpdGlvbk1hcmdpbgAWa19wb3NpdGlvbk9wZW5Ob3Rpb25hbAIWa19wb3NpdGlvbk9wZW5Ob3Rpb25hbAAua19wb3NpdGlvbkxhc3RVcGRhdGVkQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgISa19wb3NpdGlvbkZyYWN0aW9uABJrX3Bvc2l0aW9uU2VxdWVuY2UCEmtfcG9zaXRpb25TZXF1ZW5jZQAPa19wb3NpdGlvbkFzc2V0Ag9rX3Bvc2l0aW9uQXNzZXQADWtfaW5pdGlhbGl6ZWQCDWtfaW5pdGlhbGl6ZWQACGtfcGF1c2VkAghrX3BhdXNlZAALa19jbG9zZU9ubHkCC2tfY2xvc2VPbmx5AAVrX2ZlZQIFa19mZWUAD2tfZnVuZGluZ1BlcmlvZAIPa19mdW5kaW5nUGVyaW9kABFrX2luaXRNYXJnaW5SYXRpbwIRa19pbml0TWFyZ2luUmF0aW8AGGtfbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwIFa19tbXIAFWtfbGlxdWlkYXRpb25GZWVSYXRpbwIVa19saXF1aWRhdGlvbkZlZVJhdGlvABlrX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAhZrX3BhcnRMaXF1aWRhdGlvblJhdGlvAA1rX3NwcmVhZExpbWl0Ag1rX3NwcmVhZExpbWl0ABBrX21heFByaWNlSW1wYWN0AhBrX21heFByaWNlSW1wYWN0ABBrX21heFByaWNlU3ByZWFkAhBrX21heFByaWNlU3ByZWFkABFrX21heE9wZW5Ob3Rpb25hbAIRa19tYXhPcGVuTm90aW9uYWwAFWtfZmVlVG9TdGFrZXJzUGVyY2VudAIVa19mZWVUb1N0YWtlcnNQZXJjZW50ABBrX21heE9yYWNsZURlbGF5AhBrX21heE9yYWNsZURlbGF5AA1rX2xhc3REYXRhU3RyAg1rX2xhc3REYXRhU3RyAA5rX2xhc3RNaW51dGVJZAIOa19sYXN0TWludXRlSWQAHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlAh1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQATa190d2FwRGF0YUxhc3RQcmljZQITa190d2FwRGF0YUxhc3RQcmljZQAaa190d2FwRGF0YVByZXZpb3VzTWludXRlSWQCGmtfdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkACVrX2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAhtrX2xhdGVzdExvbmdQcmVtaXVtRnJhY3Rpb24AJmtfbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAhxrX2xhdGVzdFNob3J0UHJlbWl1bUZyYWN0aW9uABJrX25leHRGdW5kaW5nQmxvY2sCHmtfbmV4dEZ1bmRpbmdCbG9ja01pblRpbWVzdGFtcAARa19sb25nRnVuZGluZ1JhdGUCEWtfbG9uZ0Z1bmRpbmdSYXRlABJrX3Nob3J0RnVuZGluZ1JhdGUCEmtfc2hvcnRGdW5kaW5nUmF0ZQATa19xdW90ZUFzc2V0UmVzZXJ2ZQIIa19xdEFzdFIAEmtfYmFzZUFzc2V0UmVzZXJ2ZQIIa19ic0FzdFIAEmtfcXVvdGVBc3NldFdlaWdodAIIa19xdEFzdFcAEWtfYmFzZUFzc2V0V2VpZ2h0AghrX2JzQXN0VwATa190b3RhbFBvc2l0aW9uU2l6ZQITa190b3RhbFBvc2l0aW9uU2l6ZQAXa190b3RhbExvbmdQb3NpdGlvblNpemUCF2tfdG90YWxMb25nUG9zaXRpb25TaXplABhrX3RvdGFsU2hvcnRQb3NpdGlvblNpemUCGGtfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAWa19vcGVuSW50ZXJlc3ROb3Rpb25hbAIWa19vcGVuSW50ZXJlc3ROb3Rpb25hbAATa19vcGVuSW50ZXJlc3RTaG9ydAITa19vcGVuSW50ZXJlc3RTaG9ydAASa19vcGVuSW50ZXJlc3RMb25nAhJrX29wZW5JbnRlcmVzdExvbmcAFGtfY29vcmRpbmF0b3JBZGRyZXNzAhRrX2Nvb3JkaW5hdG9yQWRkcmVzcwAPa192YXVsdF9hZGRyZXNzAg9rX3ZhdWx0X2FkZHJlc3MAD2tfYWRtaW5fYWRkcmVzcwIPa19hZG1pbl9hZGRyZXNzABJrX2FkbWluX3B1YmxpY19rZXkCEmtfYWRtaW5fcHVibGljX2tleQANa19xdW90ZV9hc3NldAINa19xdW90ZV9hc3NldAAPa19xdW90ZV9zdGFraW5nAg9rX3F1b3RlX3N0YWtpbmcAEWtfc3Rha2luZ19hZGRyZXNzAhFrX3N0YWtpbmdfYWRkcmVzcwAPa19taW5lcl9hZGRyZXNzAg9rX21pbmVyX2FkZHJlc3MAEGtfb3JkZXJzX2FkZHJlc3MCEGtfb3JkZXJzX2FkZHJlc3MAEmtfcmVmZXJyYWxfYWRkcmVzcwISa19yZWZlcnJhbF9hZGRyZXNzABRrX2NvbGxhdGVyYWxfYWRkcmVzcwIUa19jb2xsYXRlcmFsX2FkZHJlc3MAEmtfZXhjaGFuZ2VfYWRkcmVzcwISa19leGNoYW5nZV9hZGRyZXNzABVrX25mdF9tYW5hZ2VyX2FkZHJlc3MCFWtfbmZ0X21hbmFnZXJfYWRkcmVzcwAga190cmFkZXJfbWFya2V0X2Fzc2V0X2NvbGxhdGVyYWwCIGtfdHJhZGVyX21hcmtldF9hc3NldF9jb2xsYXRlcmFsAQ50b0NvbXBvc2l0ZUtleQIEX2tleQhfYWRkcmVzcwkArAICCQCsAgIFBF9rZXkCAV8FCF9hZGRyZXNzAQtjb29yZGluYXRvcgAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCBQR0aGlzBRRrX2Nvb3JkaW5hdG9yQWRkcmVzcwITQ29vcmRpbmF0b3Igbm90IHNldAEMYWRtaW5BZGRyZXNzAAkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABQ9rX2FkbWluX2FkZHJlc3MBDmFkbWluUHVibGljS2V5AAkA2QQBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABRJrX2FkbWluX3B1YmxpY19rZXkBCnF1b3RlQXNzZXQACQDZBAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFDWtfcXVvdGVfYXNzZXQBEXF1b3RlQXNzZXRTdGFraW5nAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFD2tfcXVvdGVfc3Rha2luZwIbUXVvdGUgYXNzZXQgc3Rha2luZyBub3Qgc2V0AQ5zdGFraW5nQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABRFrX3N0YWtpbmdfYWRkcmVzcwIPU3Rha2luZyBub3Qgc2V0AQx2YXVsdEFkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUPa192YXVsdF9hZGRyZXNzAg1WYXVsdCBub3Qgc2V0AQxtaW5lckFkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUPa19taW5lcl9hZGRyZXNzAg1NaW5lciBub3Qgc2V0AQ1vcmRlcnNBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFEGtfb3JkZXJzX2FkZHJlc3MCDk9yZGVycyBub3Qgc2V0AQ9yZWZlcnJhbEFkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUSa19yZWZlcnJhbF9hZGRyZXNzAhBSZWZlcnJhbCBub3Qgc2V0ARFuZnRNYW5hZ2VyQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABRVrX25mdF9tYW5hZ2VyX2FkZHJlc3MCE05GVCBNYW5hZ2VyIG5vdCBzZXQBEWNvbGxhdGVyYWxBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFFGtfY29sbGF0ZXJhbF9hZGRyZXNzAhpDb2xsYXRlcmFsIE1hbmFnZXIgbm90IHNldAELc3dhcEFkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIJAQtjb29yZGluYXRvcgAFEmtfZXhjaGFuZ2VfYWRkcmVzcwIPTm8gc3dhcCBhZGRyZXNzAhRJbnZhbGlkIHN3YXAgYWRkcmVzcwARa193aGl0ZWxpc3RfYXNzZXQCEWtfd2hpdGVsaXN0X2Fzc2V0ARBpc1doaXRlbGlzdEFzc2V0AQhfYXNzZXRJZAkBC3ZhbHVlT3JFbHNlAgkAmwgCCQERY29sbGF0ZXJhbEFkZHJlc3MACQEOdG9Db21wb3NpdGVLZXkCBRFrX3doaXRlbGlzdF9hc3NldAUIX2Fzc2V0SWQHAA1rX3Rva2VuX3BhcmFtAg1rX3Rva2VuX3BhcmFtAAxrX3Rva2VuX3R5cGUCDGtfdG9rZW5fdHlwZQAYRkVFX1JFRFVDVElPTl9UT0tFTl9UWVBFAg1mZWVfcmVkdWN0aW9uAAhESVJfTE9ORwABAAlESVJfU0hPUlQAAgANVFdBUF9JTlRFUlZBTAAPAA9PUkFDTEVfSU5URVJWQUwADwAHU0VDT05EUwDoBwAPREVDSU1BTF9OVU1CRVJTAAYADERFQ0lNQUxfVU5JVAkAaAIAAQkAaAIJAGgCCQBoAgkAaAIJAGgCAAoACgAKAAoACgAKAAdPTkVfREFZCQBoAgCAowUFDERFQ0lNQUxfVU5JVAAIQUxMX0ZFRVMAZAAPUE5MX09QVElPTl9TUE9UAAEAEVBOTF9PUFRJT05fT1JBQ0xFAAIBAXMBAl94CQCsAgIJAKQDAQUCX3gCASwBBGRpdmQCAl94Al95CQBuBAUCX3gFDERFQ0lNQUxfVU5JVAUCX3kFCEhBTEZFVkVOAQRtdWxkAgJfeAJfeQkAbgQFAl94BQJfeQUMREVDSU1BTF9VTklUBQhIQUxGRVZFTgEFc3FydGQBAl94CQEEc3FydAQFAl94BQ9ERUNJTUFMX05VTUJFUlMFD0RFQ0lNQUxfTlVNQkVSUwUISEFMRkVWRU4BBHBvd2QCAl94Al95CQBsBgUCX3gFD0RFQ0lNQUxfTlVNQkVSUwUCX3kFD0RFQ0lNQUxfTlVNQkVSUwUPREVDSU1BTF9OVU1CRVJTBQhIQUxGRVZFTgEFYmRpdmQCAl94Al95CQC9AgQFAl94CQC2AgEFDERFQ0lNQUxfVU5JVAUCX3kFCEhBTEZFVkVOAQVibXVsZAICX3gCX3kJAL0CBAUCX3gFAl95CQC2AgEFDERFQ0lNQUxfVU5JVAUISEFMRkVWRU4BBmJzcXJ0ZAECX3gJAQpzcXJ0QmlnSW50BAUCX3gFD0RFQ0lNQUxfTlVNQkVSUwUPREVDSU1BTF9OVU1CRVJTBQhIQUxGRVZFTgEFYnBvd2QCAl94Al95CQB2BgUCX3gFD0RFQ0lNQUxfTlVNQkVSUwUCX3kFD0RFQ0lNQUxfTlVNQkVSUwUPREVDSU1BTF9OVU1CRVJTBQhIQUxGRVZFTgEDYWJzAQJfeAMJAGYCBQJfeAAABQJfeAkBAS0BBQJfeAEEdm1heAICX3gCX3kDCQBnAgUCX3gFAl95BQJfeAUCX3kBCWxpc3RUb1N0cgEFX2xpc3QKAQVfam9pbgILYWNjdW11bGF0b3IDdmFsCQCsAgIJAKwCAgULYWNjdW11bGF0b3IFA3ZhbAIBLAQKbmV3TGlzdFN0cgoAAiRsBQVfbGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzACAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEFX2pvaW4CBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDIwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAA0ADgAPABAAEQASABMAFAQLbmV3TGlzdFN0clUJALMCAgUKbmV3TGlzdFN0cgABBAtuZXdMaXN0U3RyUgMJAAACCQCvAgIFC25ld0xpc3RTdHJVAAECASwJALACAgULbmV3TGlzdFN0clUAAQULbmV3TGlzdFN0clUFC25ld0xpc3RTdHJSAQlzdHJUb0xpc3QBBF9zdHIJALUJAgUEX3N0cgIBLAELcHVzaFRvUXVldWUDBV9saXN0CF9tYXhTaXplBl92YWx1ZQMJAGYCCQCQAwEFBV9saXN0BQhfbWF4U2l6ZQkAzQgCCQDRCAIFBV9saXN0AAAFBl92YWx1ZQkAzQgCBQVfbGlzdAUGX3ZhbHVlAQNpbnQBAWsJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQR0aGlzBQFrCQCsAgICDW5vIHZhbHVlIGZvciAFAWsBBWludE9yAgFrA2RlZgkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQFrBQNkZWYBBHN0ckECCF9hZGRyZXNzBF9rZXkEA3ZhbAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFCF9hZGRyZXNzBQRfa2V5CQCsAgICEU5vIHZhbHVlIGZvciBrZXkgBQRfa2V5BQN2YWwBBGludEECCF9hZGRyZXNzBF9rZXkEA3ZhbAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFCF9hZGRyZXNzBQRfa2V5CQCsAgICEU5vIHZhbHVlIGZvciBrZXkgBQRfa2V5BQN2YWwBCGNiYWxhbmNlAAkBA2ludAEFCWtfYmFsYW5jZQEDZmVlAAkBA2ludAEFBWtfZmVlAQ9pbml0TWFyZ2luUmF0aW8ACQEDaW50AQURa19pbml0TWFyZ2luUmF0aW8BBnF0QXN0UgAJAQNpbnQBBRNrX3F1b3RlQXNzZXRSZXNlcnZlAQZic0FzdFIACQEDaW50AQUSa19iYXNlQXNzZXRSZXNlcnZlAQZxdEFzdFcACQEFaW50T3ICBRJrX3F1b3RlQXNzZXRXZWlnaHQFDERFQ0lNQUxfVU5JVAEGYnNBc3RXAAkBBWludE9yAgURa19iYXNlQXNzZXRXZWlnaHQFDERFQ0lNQUxfVU5JVAERdG90YWxQb3NpdGlvblNpemUACQEDaW50AQUTa190b3RhbFBvc2l0aW9uU2l6ZQEUb3BlbkludGVyZXN0Tm90aW9uYWwACQEDaW50AQUWa19vcGVuSW50ZXJlc3ROb3Rpb25hbAERb3BlbkludGVyZXN0U2hvcnQACQEDaW50AQUTa19vcGVuSW50ZXJlc3RTaG9ydAEQb3BlbkludGVyZXN0TG9uZwAJAQNpbnQBBRJrX29wZW5JbnRlcmVzdExvbmcBGW5leHRGdW5kaW5nQmxvY2tUaW1lc3RhbXAACQEDaW50AQUSa19uZXh0RnVuZGluZ0Jsb2NrARBmdW5kaW5nUGVyaW9kUmF3AAkBA2ludAEFD2tfZnVuZGluZ1BlcmlvZAEUZnVuZGluZ1BlcmlvZERlY2ltYWwACQBoAgkBEGZ1bmRpbmdQZXJpb2RSYXcABQxERUNJTUFMX1VOSVQBFGZ1bmRpbmdQZXJpb2RTZWNvbmRzAAkAaAIJARBmdW5kaW5nUGVyaW9kUmF3AAUHU0VDT05EUwEWbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwAJAQNpbnQBBRhrX21haW50ZW5hbmNlTWFyZ2luUmF0aW8BE2xpcXVpZGF0aW9uRmVlUmF0aW8ACQEDaW50AQUVa19saXF1aWRhdGlvbkZlZVJhdGlvARdwYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwAJAQNpbnQBBRlrX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAQtzcHJlYWRMaW1pdAAJAQNpbnQBBQ1rX3NwcmVhZExpbWl0AQ5tYXhQcmljZUltcGFjdAAJAQNpbnQBBRBrX21heFByaWNlSW1wYWN0AQ5tYXhQcmljZVNwcmVhZAAJAQNpbnQBBRBrX21heFByaWNlU3ByZWFkAQ9tYXhPcGVuTm90aW9uYWwACQEDaW50AQURa19tYXhPcGVuTm90aW9uYWwBI2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAkBA2ludAEFJWtfbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BJGxhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAJAQNpbnQBBSZrX2xhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAJAQNpbnQBBRhrX3RvdGFsU2hvcnRQb3NpdGlvblNpemUBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQAJAQNpbnQBBRdrX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQEMbGFzdFNlcXVlbmNlAAkBBWludE9yAgUKa19zZXF1ZW5jZQAAARNmZWVUb1N0YWtlcnNQZXJjZW50AAkBA2ludAEFFWtfZmVlVG9TdGFrZXJzUGVyY2VudAEObWF4T3JhY2xlRGVsYXkACQEDaW50AQUQa19tYXhPcmFjbGVEZWxheQEPZ2V0QWN0dWFsQ2FsbGVyAQFpCQELdmFsdWVPckVsc2UCCQCdCAIJAQ1vcmRlcnNBZGRyZXNzAAIIa19zZW5kZXIJAKUIAQgFAWkGY2FsbGVyARZyZXF1aXJlTW9yZU1hcmdpblJhdGlvAwxfbWFyZ2luUmF0aW8QX2Jhc2VNYXJnaW5SYXRpbxRfbGFyZ2VyVGhhbk9yRXF1YWxUbwQUcmVtYWluaW5nTWFyZ2luUmF0aW8JAGUCBQxfbWFyZ2luUmF0aW8FEF9iYXNlTWFyZ2luUmF0aW8DAwUUX2xhcmdlclRoYW5PckVxdWFsVG8JAGYCAAAFFHJlbWFpbmluZ01hcmdpblJhdGlvBwkAAgECDkludmFsaWQgbWFyZ2luAwMJAQEhAQUUX2xhcmdlclRoYW5PckVxdWFsVG8JAGcCBRRyZW1haW5pbmdNYXJnaW5SYXRpbwAABwkAAgECDkludmFsaWQgbWFyZ2luBgEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgENX3Bvc2l0aW9uU2l6ZQMJAAACBQ1fcG9zaXRpb25TaXplAAAJAAIBAixTaG91bGQgbm90IGJlIGNhbGxlZCB3aXRoIF9wb3NpdGlvblNpemUgPT0gMAMJAGYCBQ1fcG9zaXRpb25TaXplAAAJASNsYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAJASRsYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24AAQtnZXRQb3NpdGlvbgEHX3RyYWRlcgQPcG9zaXRpb25TaXplT3B0CQCaCAIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFDmtfcG9zaXRpb25TaXplBQdfdHJhZGVyBAckbWF0Y2gwBQ9wb3NpdGlvblNpemVPcHQDCQABAgUHJG1hdGNoMAIDSW50BAxwb3NpdGlvblNpemUFByRtYXRjaDAJAJYKBAUMcG9zaXRpb25TaXplCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBRBrX3Bvc2l0aW9uTWFyZ2luBQdfdHJhZGVyCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBRZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBQdfdHJhZGVyCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBS5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBQdfdHJhZGVyCQCWCgQAAAAAAAAAAAEQZ2V0UG9zaXRpb25Bc3NldAEHX3RyYWRlcgQQcG9zaXRpb25Bc3NldE9wdAkAnQgCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBQ9rX3Bvc2l0aW9uQXNzZXQFB190cmFkZXIEByRtYXRjaDAFEHBvc2l0aW9uQXNzZXRPcHQDCQABAgUHJG1hdGNoMAIGU3RyaW5nBA1wb3NpdGlvbkFzc2V0BQckbWF0Y2gwBQ1wb3NpdGlvbkFzc2V0CQDYBAEJAQpxdW90ZUFzc2V0AAETcmVxdWlyZU9wZW5Qb3NpdGlvbgEHX3RyYWRlcgMJAAACCAkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgJfMQAACQACAQIQTm8gb3BlbiBwb3NpdGlvbgYBC2luaXRpYWxpemVkAAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzBQ1rX2luaXRpYWxpemVkBwEGcGF1c2VkAAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzBQhrX3BhdXNlZAcBCWNsb3NlT25seQAJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhpcwULa19jbG9zZU9ubHkHAQ11cGRhdGVSZXNlcnZlAwZfaXNBZGQRX3F1b3RlQXNzZXRBbW91bnQQX2Jhc2VBc3NldEFtb3VudAMFBl9pc0FkZAQHbmV3QmFzZQkAZQIJAQZic0FzdFIABRBfYmFzZUFzc2V0QW1vdW50AwkAZwIAAAUHbmV3QmFzZQkAAgECKlR4IGxlYWQgdG8gYmFzZSBhc3NldCByZXNlcnZlIDw9IDAsIHJldmVydAkAlQoDCQBkAgkBBnF0QXN0UgAFEV9xdW90ZUFzc2V0QW1vdW50BQduZXdCYXNlCQBkAgkBEXRvdGFsUG9zaXRpb25TaXplAAUQX2Jhc2VBc3NldEFtb3VudAQIbmV3UXVvdGUJAGUCCQEGcXRBc3RSAAURX3F1b3RlQXNzZXRBbW91bnQDCQBnAgAABQhuZXdRdW90ZQkAAgECKlR4IGxlYWQgdG8gYmFzZSBxdW90ZSByZXNlcnZlIDw9IDAsIHJldmVydAkAlQoDBQhuZXdRdW90ZQkAZAIJAQZic0FzdFIABRBfYmFzZUFzc2V0QW1vdW50CQBlAgkBEXRvdGFsUG9zaXRpb25TaXplAAUQX2Jhc2VBc3NldEFtb3VudAENY2FsY0ludmFyaWFudAQHX3F0QXN0UgdfcXRBc3RXB19ic0FzdFIHX2JzQXN0VwQHYnF0QXN0UgkAtgIBBQdfcXRBc3RSBAdicXRBc3RXCQC2AgEFB19xdEFzdFcEB2Jic0FzdFIJALYCAQUHX2JzQXN0UgQHYmJzQXN0VwkAtgIBBQdfYnNBc3RXCQEFYm11bGQCCQEFYm11bGQCBQdicXRBc3RSBQdicXRBc3RXCQEFYm11bGQCBQdiYnNBc3RSBQdiYnNBc3RXAQlzd2FwSW5wdXQCBl9pc0FkZBFfcXVvdGVBc3NldEFtb3VudAQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwAEAWsJAQ1jYWxjSW52YXJpYW50BAUHX3F0QXN0UgUHX3F0QXN0VwUHX2JzQXN0UgUHX2JzQXN0VwQWcXVvdGVBc3NldFJlc2VydmVBZnRlcgMFBl9pc0FkZAkAZAIFB19xdEFzdFIFEV9xdW90ZUFzc2V0QW1vdW50CQBlAgUHX3F0QXN0UgURX3F1b3RlQXNzZXRBbW91bnQEFWJhc2VBc3NldFJlc2VydmVBZnRlcgkAoAMBCQEFYmRpdmQCBQFrCQC2AgEJAQRtdWxkAgUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUHX3F0QXN0VwQYYW1vdW50QmFzZUFzc2V0Qm91Z2h0QWJzCQEEZGl2ZAIJAQNhYnMBCQBlAgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBQdfYnNBc3RSBQdfcXRBc3RXBBVhbW91bnRCYXNlQXNzZXRCb3VnaHQDBQZfaXNBZGQFGGFtb3VudEJhc2VBc3NldEJvdWdodEFicwkBAS0BBRhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMEDSR0MDE2ODA1MTY5NjgJAQ11cGRhdGVSZXNlcnZlAwUGX2lzQWRkBRFfcXVvdGVBc3NldEFtb3VudAUYYW1vdW50QmFzZUFzc2V0Qm91Z2h0QWJzBBdxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyMQgFDSR0MDE2ODA1MTY5NjgCXzEEFmJhc2VBc3NldFJlc2VydmVBZnRlcjEIBQ0kdDAxNjgwNTE2OTY4Al8yBBd0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyMQgFDSR0MDE2ODA1MTY5NjgCXzMEC3ByaWNlQmVmb3JlCQEEZGl2ZAIJAQRtdWxkAgUHX3F0QXN0UgUHX3F0QXN0VwkBBG11bGQCBQdfYnNBc3RSBQdfYnNBc3RXBAttYXJrZXRQcmljZQkBBGRpdmQCBRFfcXVvdGVBc3NldEFtb3VudAUYYW1vdW50QmFzZUFzc2V0Qm91Z2h0QWJzBAlwcmljZURpZmYJAQNhYnMBCQBlAgULcHJpY2VCZWZvcmUFC21hcmtldFByaWNlBAtwcmljZUltcGFjdAkAZQIFDERFQ0lNQUxfVU5JVAkBBGRpdmQCBQtwcmljZUJlZm9yZQkAZAIFC3ByaWNlQmVmb3JlBQlwcmljZURpZmYEE21heFByaWNlSW1wYWN0VmFsdWUJAQ5tYXhQcmljZUltcGFjdAADCQBmAgULcHJpY2VJbXBhY3QFE21heFByaWNlSW1wYWN0VmFsdWUJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICDVByaWNlIGltcGFjdCAJAKQDAQULcHJpY2VJbXBhY3QCFCA+IG1heCBwcmljZSBpbXBhY3QgCQCkAwEFE21heFByaWNlSW1wYWN0VmFsdWUCFSBiZWZvcmUgcXVvdGUgYXNzZXQ6IAkApAMBBQdfcXRBc3RSAhQgYmVmb3JlIGJhc2UgYXNzZXQ6IAkApAMBBQdfYnNBc3RSAiEgcXVvdGUgYXNzZXQgYW1vdW50IHRvIGV4Y2hhbmdlOiAJAKQDAQURX3F1b3RlQXNzZXRBbW91bnQCDyBwcmljZSBiZWZvcmU6IAkApAMBBQtwcmljZUJlZm9yZQIOIG1hcmtldFByaWNlOiAJAKQDAQULbWFya2V0UHJpY2UJAJYKBAUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0BRdxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyMQUWYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyMQUXdG90YWxQb3NpdGlvblNpemVBZnRlcjEBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEEF9vbGRQb3NpdGlvblNpemUSX29sZFBvc2l0aW9uTWFyZ2luJV9vbGRQb3NpdGlvbkN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24MX21hcmdpbkRlbHRhBA5mdW5kaW5nUGF5bWVudAMJAQIhPQIFEF9vbGRQb3NpdGlvblNpemUAAAQgX2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24JAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUQX29sZFBvc2l0aW9uU2l6ZQkBBG11bGQCCQBlAgUgX2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FJV9vbGRQb3NpdGlvbkN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FEF9vbGRQb3NpdGlvblNpemUAAAQMc2lnbmVkTWFyZ2luCQBkAgkAZQIFDF9tYXJnaW5EZWx0YQUOZnVuZGluZ1BheW1lbnQFEl9vbGRQb3NpdGlvbk1hcmdpbgQNJHQwMTg0NTUxODU4MgMJAGYCAAAFDHNpZ25lZE1hcmdpbgkAlAoCAAAJAQNhYnMBBQxzaWduZWRNYXJnaW4JAJQKAgkBA2FicwEFDHNpZ25lZE1hcmdpbgAABAxyZW1haW5NYXJnaW4IBQ0kdDAxODQ1NTE4NTgyAl8xBAdiYWREZWJ0CAUNJHQwMTg0NTUxODU4MgJfMgkAlQoDBQxyZW1haW5NYXJnaW4FB2JhZERlYnQFDmZ1bmRpbmdQYXltZW50ARZzd2FwT3V0cHV0V2l0aFJlc2VydmVzBwZfaXNBZGQQX2Jhc2VBc3NldEFtb3VudBRfY2hlY2tNYXhQcmljZUltcGFjdBJfcXVvdGVBc3NldFJlc2VydmURX3F1b3RlQXNzZXRXZWlnaHQRX2Jhc2VBc3NldFJlc2VydmUQX2Jhc2VBc3NldFdlaWdodAQLcHJpY2VCZWZvcmUJAQRkaXZkAgkBBG11bGQCBRJfcXVvdGVBc3NldFJlc2VydmUFEV9xdW90ZUFzc2V0V2VpZ2h0CQEEbXVsZAIFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0V2VpZ2h0AwkAAAIFEF9iYXNlQXNzZXRBbW91bnQAAAkAAgECGUludmFsaWQgYmFzZSBhc3NldCBhbW91bnQEAWsJAQ1jYWxjSW52YXJpYW50BAUSX3F1b3RlQXNzZXRSZXNlcnZlBRFfcXVvdGVBc3NldFdlaWdodAURX2Jhc2VBc3NldFJlc2VydmUFEF9iYXNlQXNzZXRXZWlnaHQEGGJhc2VBc3NldFBvb2xBbW91bnRBZnRlcgMFBl9pc0FkZAkAZAIFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0QW1vdW50CQBlAgURX2Jhc2VBc3NldFJlc2VydmUFEF9iYXNlQXNzZXRBbW91bnQED3F1b3RlQXNzZXRBZnRlcgkAoAMBCQEFYmRpdmQCBQFrCQC2AgEJAQRtdWxkAgUYYmFzZUFzc2V0UG9vbEFtb3VudEFmdGVyBRBfYmFzZUFzc2V0V2VpZ2h0BA5xdW90ZUFzc2V0U29sZAkBA2FicwEJAGUCBQ9xdW90ZUFzc2V0QWZ0ZXIJAQRtdWxkAgUSX3F1b3RlQXNzZXRSZXNlcnZlBRFfcXVvdGVBc3NldFdlaWdodAQTbWF4UHJpY2VJbXBhY3RWYWx1ZQkBDm1heFByaWNlSW1wYWN0AAQNJHQwMTk3NzAxOTkzMQkBDXVwZGF0ZVJlc2VydmUDCQEBIQEFBl9pc0FkZAUOcXVvdGVBc3NldFNvbGQFEF9iYXNlQXNzZXRBbW91bnQEF3F1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIxCAUNJHQwMTk3NzAxOTkzMQJfMQQWYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyMQgFDSR0MDE5NzcwMTk5MzECXzIEF3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIxCAUNJHQwMTk3NzAxOTkzMQJfMwQLbWFya2V0UHJpY2UJAQRkaXZkAgUOcXVvdGVBc3NldFNvbGQFEF9iYXNlQXNzZXRBbW91bnQECXByaWNlRGlmZgkBA2FicwEJAGUCBQtwcmljZUJlZm9yZQULbWFya2V0UHJpY2UEC3ByaWNlSW1wYWN0CQBlAgUMREVDSU1BTF9VTklUCQEEZGl2ZAIFC3ByaWNlQmVmb3JlCQBkAgULcHJpY2VCZWZvcmUFCXByaWNlRGlmZgMDCQBmAgULcHJpY2VJbXBhY3QFE21heFByaWNlSW1wYWN0VmFsdWUFFF9jaGVja01heFByaWNlSW1wYWN0BwkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgINUHJpY2UgaW1wYWN0IAkApAMBBQtwcmljZUltcGFjdAIUID4gbWF4IHByaWNlIGltcGFjdCAJAKQDAQUTbWF4UHJpY2VJbXBhY3RWYWx1ZQIVIGJlZm9yZSBxdW90ZSBhc3NldDogCQCkAwEFEl9xdW90ZUFzc2V0UmVzZXJ2ZQIUIGJlZm9yZSBiYXNlIGFzc2V0OiAJAKQDAQURX2Jhc2VBc3NldFJlc2VydmUCICBiYXNlIGFzc2V0IGFtb3VudCB0byBleGNoYW5nZTogCQCkAwEFEF9iYXNlQXNzZXRBbW91bnQCDyBwcmljZSBiZWZvcmU6IAkApAMBBQtwcmljZUJlZm9yZQIPIG1hcmtldCBwcmljZTogCQCkAwEFC21hcmtldFByaWNlCQCZCgcFDnF1b3RlQXNzZXRTb2xkBRdxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyMQUWYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyMQUXdG90YWxQb3NpdGlvblNpemVBZnRlcjEJAGUCCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAMFBl9pc0FkZAkBA2FicwEFEF9iYXNlQXNzZXRBbW91bnQAAAkAZQIJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAMJAQEhAQUGX2lzQWRkCQEDYWJzAQUQX2Jhc2VBc3NldEFtb3VudAAABQtwcmljZUltcGFjdAEKc3dhcE91dHB1dAMGX2lzQWRkEF9iYXNlQXNzZXRBbW91bnQUX2NoZWNrTWF4UHJpY2VJbXBhY3QJARZzd2FwT3V0cHV0V2l0aFJlc2VydmVzBwUGX2lzQWRkBRBfYmFzZUFzc2V0QW1vdW50BRRfY2hlY2tNYXhQcmljZUltcGFjdAkBBnF0QXN0UgAJAQZxdEFzdFcACQEGYnNBc3RSAAkBBmJzQXN0VwABDmdldE9yYWNsZVByaWNlAAQGb3JhY2xlCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgUEdGhpcwUFa19vcmECAAQIcHJpY2VLZXkJARFAZXh0ck5hdGl2ZSgxMDUzKQIFBHRoaXMFCWtfb3JhX2tleQQJbGFzdFZhbHVlCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUGb3JhY2xlBQhwcmljZUtleQkArAICCQCsAgIJAKwCAgIiQ2FuIG5vdCBnZXQgb3JhY2xlIHByaWNlLiBPcmFjbGU6IAkApQgBBQZvcmFjbGUCBiBrZXk6IAUIcHJpY2VLZXkECGJsb2NrS2V5CQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMFD2tfb3JhX2Jsb2NrX2tleQIAAwkBAiE9AgUIYmxvY2tLZXkCAAQMY3VycmVudEJsb2NrCAUJbGFzdEJsb2NrBmhlaWdodAQPbGFzdE9yYWNsZUJsb2NrCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUGb3JhY2xlBQhibG9ja0tleQkArAICCQCsAgIJAKwCAgIiQ2FuIG5vdCBnZXQgb3JhY2xlIGJsb2NrLiBPcmFjbGU6IAkApQgBBQZvcmFjbGUCBiBrZXk6IAUIYmxvY2tLZXkDCQBmAgkAZQIFDGN1cnJlbnRCbG9jawUPbGFzdE9yYWNsZUJsb2NrCQEObWF4T3JhY2xlRGVsYXkACQACAQkArAICCQCsAgIJAKwCAgImT3JhY2xlIHN0YWxlIGRhdGEuIExhc3Qgb3JhY2xlIGJsb2NrOiAJAKQDAQUPbGFzdE9yYWNsZUJsb2NrAhAgY3VycmVudCBibG9jazogCQCkAwEFDGN1cnJlbnRCbG9jawUJbGFzdFZhbHVlBQlsYXN0VmFsdWUBDmlzTWFya2V0Q2xvc2VkAAQGb3JhY2xlCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgUEdGhpcwUFa19vcmECAAQHb3BlbktleQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzBQ5rX29yYV9vcGVuX2tleQIAAwkBAiE9AgUHb3BlbktleQIABAZpc09wZW4JARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmwgCBQZvcmFjbGUFB29wZW5LZXkJAKwCAgkArAICCQCsAgICK0NhbiBub3QgZ2V0IG9yYWNsZSBpcyBvcGVuL2Nsb3NlZC4gT3JhY2xlOiAJAKUIAQUGb3JhY2xlAgYga2V5OiAFB29wZW5LZXkJAQEhAQUGaXNPcGVuBwEMYWJzUHJpY2VEaWZmBQxfb3JhY2xlUHJpY2USX3F1b3RlQXNzZXRSZXNlcnZlEV9iYXNlQXNzZXRSZXNlcnZlB19xdEFzdFcHX2JzQXN0VwQKcHJpY2VBZnRlcgkBBGRpdmQCCQEEbXVsZAIFEl9xdW90ZUFzc2V0UmVzZXJ2ZQUHX3F0QXN0VwkBBG11bGQCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUHX2JzQXN0VwQMYXZlcmFnZVByaWNlCQEEZGl2ZAIJAGQCBQxfb3JhY2xlUHJpY2UFCnByaWNlQWZ0ZXIJAGgCAAIFDERFQ0lNQUxfVU5JVAQMYWJzUHJpY2VEaWZmCQEEZGl2ZAIJAQNhYnMBCQBlAgUMX29yYWNsZVByaWNlBQpwcmljZUFmdGVyBQxhdmVyYWdlUHJpY2UFDGFic1ByaWNlRGlmZgEZcmVxdWlyZU5vdE92ZXJTcHJlYWRMaW1pdAISX3F1b3RlQXNzZXRSZXNlcnZlEV9iYXNlQXNzZXRSZXNlcnZlBAtvcmFjbGVQcmljZQkBDmdldE9yYWNsZVByaWNlAAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcABBJhYnNQcmljZURpZmZCZWZvcmUJAQxhYnNQcmljZURpZmYFBQtvcmFjbGVQcmljZQkBBnF0QXN0UgAJAQZic0FzdFIABQdfcXRBc3RXBQdfYnNBc3RXBBFhYnNQcmljZURpZmZBZnRlcgkBDGFic1ByaWNlRGlmZgUFC29yYWNsZVByaWNlBRJfcXVvdGVBc3NldFJlc2VydmUFEV9iYXNlQXNzZXRSZXNlcnZlBQdfcXRBc3RXBQdfYnNBc3RXAwMJAGYCBRFhYnNQcmljZURpZmZBZnRlcgkBDm1heFByaWNlU3ByZWFkAAkAZgIFEWFic1ByaWNlRGlmZkFmdGVyBRJhYnNQcmljZURpZmZCZWZvcmUHCQACAQkArAICCQCsAgIJAKwCAgINUHJpY2Ugc3ByZWFkIAkApAMBBRFhYnNQcmljZURpZmZBZnRlcgIUID4gbWF4IHByaWNlIHNwcmVhZCAJAKQDAQkBDm1heFByaWNlU3ByZWFkAAYBHXJlcXVpcmVOb3RPdmVyTWF4T3Blbk5vdGlvbmFsAhFfbG9uZ09wZW5Ob3Rpb25hbBJfc2hvcnRPcGVuTm90aW9uYWwEEF9tYXhPcGVuTm90aW9uYWwJAQ9tYXhPcGVuTm90aW9uYWwAAwkAZgIFEV9sb25nT3Blbk5vdGlvbmFsBRBfbWF4T3Blbk5vdGlvbmFsCQACAQkArAICCQCsAgIJAKwCAgITTG9uZyBvcGVuIG5vdGlvbmFsIAkApAMBBRFfbG9uZ09wZW5Ob3Rpb25hbAIVID4gbWF4IG9wZW4gbm90aW9uYWwgCQCkAwEFEF9tYXhPcGVuTm90aW9uYWwDCQBmAgUSX3Nob3J0T3Blbk5vdGlvbmFsBRBfbWF4T3Blbk5vdGlvbmFsCQACAQkArAICCQCsAgIJAKwCAgIUU2hvcnQgb3BlbiBub3Rpb25hbCAJAKQDAQUSX3Nob3J0T3Blbk5vdGlvbmFsAhUgPiBtYXggb3BlbiBub3Rpb25hbCAJAKQDAQUQX21heE9wZW5Ob3Rpb25hbAYBDGdldFNwb3RQcmljZQAEEl9xdW90ZUFzc2V0UmVzZXJ2ZQkBBnF0QXN0UgAEEV9iYXNlQXNzZXRSZXNlcnZlCQEGYnNBc3RSAAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcACQEEZGl2ZAIJAQRtdWxkAgUSX3F1b3RlQXNzZXRSZXNlcnZlBQdfcXRBc3RXCQEEbXVsZAIFEV9iYXNlQXNzZXRSZXNlcnZlBQdfYnNBc3RXARZpc092ZXJGbHVjdHVhdGlvbkxpbWl0AAQLb3JhY2xlUHJpY2UJAQ5nZXRPcmFjbGVQcmljZQAEDGN1cnJlbnRQcmljZQkBDGdldFNwb3RQcmljZQAJAGYCCQEEZGl2ZAIJAQNhYnMBCQBlAgULb3JhY2xlUHJpY2UFDGN1cnJlbnRQcmljZQULb3JhY2xlUHJpY2UJAQtzcHJlYWRMaW1pdAABH2dldFBvc2l0aW9uQWRqdXN0ZWRPcGVuTm90aW9uYWwGDV9wb3NpdGlvblNpemUHX29wdGlvbhJfcXVvdGVBc3NldFJlc2VydmURX3F1b3RlQXNzZXRXZWlnaHQRX2Jhc2VBc3NldFJlc2VydmUQX2Jhc2VBc3NldFdlaWdodAQPcG9zaXRpb25TaXplQWJzCQEDYWJzAQUNX3Bvc2l0aW9uU2l6ZQQHaXNTaG9ydAkAZgIAAAUNX3Bvc2l0aW9uU2l6ZQQQcG9zaXRpb25Ob3Rpb25hbAMJAAACBQdfb3B0aW9uBQ9QTkxfT1BUSU9OX1NQT1QEDSR0MDI0ODgyMjUxMDIJARZzd2FwT3V0cHV0V2l0aFJlc2VydmVzBwkBASEBBQdpc1Nob3J0BQ9wb3NpdGlvblNpemVBYnMHBRJfcXVvdGVBc3NldFJlc2VydmUFEV9xdW90ZUFzc2V0V2VpZ2h0BRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldFdlaWdodAQTb3V0UG9zaXRpb25Ob3Rpb25hbAgFDSR0MDI0ODgyMjUxMDICXzEEAngxCAUNJHQwMjQ4ODIyNTEwMgJfMgQCeDIIBQ0kdDAyNDg4MjI1MTAyAl8zBAJ4MwgFDSR0MDI0ODgyMjUxMDICXzQFE291dFBvc2l0aW9uTm90aW9uYWwJAQRtdWxkAgUPcG9zaXRpb25TaXplQWJzCQEOZ2V0T3JhY2xlUHJpY2UABRBwb3NpdGlvbk5vdGlvbmFsAStnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubEJ5VmFsdWVzBw1fcG9zaXRpb25TaXplFV9wb3NpdGlvbk9wZW5Ob3Rpb25hbBJfcXVvdGVBc3NldFJlc2VydmURX3F1b3RlQXNzZXRXZWlnaHQRX2Jhc2VBc3NldFJlc2VydmUQX2Jhc2VBc3NldFdlaWdodAdfb3B0aW9uAwkAAAIFDV9wb3NpdGlvblNpemUAAAkAAgECFUludmFsaWQgcG9zaXRpb24gc2l6ZQQHaXNTaG9ydAkAZgIAAAUNX3Bvc2l0aW9uU2l6ZQQQcG9zaXRpb25Ob3Rpb25hbAkBH2dldFBvc2l0aW9uQWRqdXN0ZWRPcGVuTm90aW9uYWwGBQ1fcG9zaXRpb25TaXplBQdfb3B0aW9uBRJfcXVvdGVBc3NldFJlc2VydmUFEV9xdW90ZUFzc2V0V2VpZ2h0BRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldFdlaWdodAQNdW5yZWFsaXplZFBubAMFB2lzU2hvcnQJAGUCBRVfcG9zaXRpb25PcGVuTm90aW9uYWwFEHBvc2l0aW9uTm90aW9uYWwJAGUCBRBwb3NpdGlvbk5vdGlvbmFsBRVfcG9zaXRpb25PcGVuTm90aW9uYWwJAJQKAgUQcG9zaXRpb25Ob3Rpb25hbAUNdW5yZWFsaXplZFBubAEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCB190cmFkZXIHX29wdGlvbgQNJHQwMjY1MjMyNjY1MQkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQMcG9zaXRpb25TaXplCAUNJHQwMjY1MjMyNjY1MQJfMQQOcG9zaXRpb25NYXJnaW4IBQ0kdDAyNjUyMzI2NjUxAl8yBBRwb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDI2NTIzMjY2NTECXzMEEXBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwMjY1MjMyNjY1MQJfNAkBK2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sQnlWYWx1ZXMHBQxwb3NpdGlvblNpemUFFHBvc2l0aW9uT3Blbk5vdGlvbmFsCQEGcXRBc3RSAAkBBnF0QXN0VwAJAQZic0FzdFIACQEGYnNBc3RXAAUHX29wdGlvbgEPY2FsY01hcmdpblJhdGlvAw1fcmVtYWluTWFyZ2luCF9iYWREZWJ0EV9wb3NpdGlvbk5vdGlvbmFsCQEEZGl2ZAIJAGUCBQ1fcmVtYWluTWFyZ2luBQhfYmFkRGVidAURX3Bvc2l0aW9uTm90aW9uYWwBFmdldE1hcmdpblJhdGlvQnlPcHRpb24CB190cmFkZXIHX29wdGlvbgQNJHQwMjcxNjQyNzI3NQkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQMcG9zaXRpb25TaXplCAUNJHQwMjcxNjQyNzI3NQJfMQQOcG9zaXRpb25NYXJnaW4IBQ0kdDAyNzE2NDI3Mjc1Al8yBANwb24IBQ0kdDAyNzE2NDI3Mjc1Al8zBBFwb3NpdGlvbkxzdFVwZENQRggFDSR0MDI3MTY0MjcyNzUCXzQEDSR0MDI3MjgxMjczNzQJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIFB190cmFkZXIFB19vcHRpb24EEHBvc2l0aW9uTm90aW9uYWwIBQ0kdDAyNzI4MTI3Mzc0Al8xBA11bnJlYWxpemVkUG5sCAUNJHQwMjcyODEyNzM3NAJfMgQNJHQwMjczNzkyNzU0NQkBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEBQxwb3NpdGlvblNpemUFDnBvc2l0aW9uTWFyZ2luBRFwb3NpdGlvbkxzdFVwZENQRgUNdW5yZWFsaXplZFBubAQMcmVtYWluTWFyZ2luCAUNJHQwMjczNzkyNzU0NQJfMQQHYmFkRGVidAgFDSR0MDI3Mzc5Mjc1NDUCXzIJAQ9jYWxjTWFyZ2luUmF0aW8DBQxyZW1haW5NYXJnaW4FB2JhZERlYnQFEHBvc2l0aW9uTm90aW9uYWwBDmdldE1hcmdpblJhdGlvAQdfdHJhZGVyCQEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAEbZ2V0UGFydGlhbExpcXVpZGF0aW9uQW1vdW50AgdfdHJhZGVyDV9wb3NpdGlvblNpemUEDG1heGltdW1SYXRpbwkBBHZtYXgCCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8ACQBlAgUMREVDSU1BTF9VTklUCQEEZGl2ZAIJAQ5nZXRNYXJnaW5SYXRpbwEFB190cmFkZXIJARZtYWludGVuYW5jZU1hcmdpblJhdGlvAAQYbWF4RXhjaGFuZ2VkUG9zaXRpb25TaXplCQEEbXVsZAIJAQNhYnMBBQ1fcG9zaXRpb25TaXplBQxtYXhpbXVtUmF0aW8ECnN3YXBSZXN1bHQJAQpzd2FwT3V0cHV0AwkAZgIFDV9wb3NpdGlvblNpemUAAAUYbWF4RXhjaGFuZ2VkUG9zaXRpb25TaXplBwQcbWF4RXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAgFCnN3YXBSZXN1bHQCXzEEC3ByaWNlSW1wYWN0CAUKc3dhcFJlc3VsdAJfNwMJAGYCCQEObWF4UHJpY2VJbXBhY3QABQtwcmljZUltcGFjdAUcbWF4RXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAQVZXhjaGFuZ2VkUG9zaXRpb25TaXplCQEEbXVsZAIJAQNhYnMBBQ1fcG9zaXRpb25TaXplCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8ABBlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CAkBCnN3YXBPdXRwdXQDCQBmAgUNX3Bvc2l0aW9uU2l6ZQAABRVleGNoYW5nZWRQb3NpdGlvblNpemUHAl8xBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50ARVpbnRlcm5hbENsb3NlUG9zaXRpb24CB190cmFkZXIUX2NoZWNrTWF4UHJpY2VJbXBhY3QEDSR0MDI4Nzg1Mjg5MTMJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIEDHBvc2l0aW9uU2l6ZQgFDSR0MDI4Nzg1Mjg5MTMCXzEEDnBvc2l0aW9uTWFyZ2luCAUNJHQwMjg3ODUyODkxMwJfMgQUcG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDAyODc4NTI4OTEzAl8zBBFwb3NpdGlvbkxzdFVwZENQRggFDSR0MDI4Nzg1Mjg5MTMCXzQEDXVucmVhbGl6ZWRQbmwICQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QCXzIEDSR0MDI5MDA4MjkxNzYJASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BAUMcG9zaXRpb25TaXplBQ5wb3NpdGlvbk1hcmdpbgURcG9zaXRpb25Mc3RVcGRDUEYFDXVucmVhbGl6ZWRQbmwEDHJlbWFpbk1hcmdpbggFDSR0MDI5MDA4MjkxNzYCXzEEB2JhZERlYnQIBQ0kdDAyOTAwODI5MTc2Al8yBBVleGNoYW5nZWRQb3NpdGlvblNpemUJAQEtAQUMcG9zaXRpb25TaXplBAtyZWFsaXplZFBubAUNdW5yZWFsaXplZFBubAQNbWFyZ2luVG9WYXVsdAkBAS0BBQxyZW1haW5NYXJnaW4EDSR0MDI5MzAzMjk1NzcJAQpzd2FwT3V0cHV0AwkAZgIFDHBvc2l0aW9uU2l6ZQAACQEDYWJzAQUMcG9zaXRpb25TaXplBRRfY2hlY2tNYXhQcmljZUltcGFjdAQZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAgFDSR0MDI5MzAzMjk1NzcCXzEEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDAyOTMwMzI5NTc3Al8yBBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDAyOTMwMzI5NTc3Al8zBBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwMjkzMDMyOTU3NwJfNAQOdG90YWxMb25nQWZ0ZXIIBQ0kdDAyOTMwMzI5NTc3Al81BA90b3RhbFNob3J0QWZ0ZXIIBQ0kdDAyOTMwMzI5NTc3Al82BBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCQBlAgkBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAAUUcG9zaXRpb25PcGVuTm90aW9uYWwJAJ8KDQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplBQdiYWREZWJ0BQtyZWFsaXplZFBubAUNbWFyZ2luVG9WYXVsdAUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyCQBlAgkBEG9wZW5JbnRlcmVzdExvbmcAAwkAZgIFDHBvc2l0aW9uU2l6ZQAABRRwb3NpdGlvbk9wZW5Ob3Rpb25hbAAACQBlAgkBEW9wZW5JbnRlcmVzdFNob3J0AAMJAGYCAAAFDHBvc2l0aW9uU2l6ZQUUcG9zaXRpb25PcGVuTm90aW9uYWwAAAEQZ2V0VHdhcFNwb3RQcmljZQAECG1pbnV0ZUlkCQBpAgkAaQIIBQlsYXN0QmxvY2sJdGltZXN0YW1wAOgHADwEDXN0YXJ0TWludXRlSWQJAGUCBQhtaW51dGVJZAUNVFdBUF9JTlRFUlZBTAQHbGlzdFN0cgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzBQ1rX2xhc3REYXRhU3RyAgAEBGxpc3QJALUJAgUHbGlzdFN0cgIBLAoBCGZpbHRlckZuAgthY2N1bXVsYXRvcgRuZXh0AwkAZwIFDXN0YXJ0TWludXRlSWQJAQ1wYXJzZUludFZhbHVlAQUEbmV4dAkAzQgCBQthY2N1bXVsYXRvcgkBDXBhcnNlSW50VmFsdWUBBQRuZXh0BQthY2N1bXVsYXRvcgQFbGlzdEYKAAIkbAUEbGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEIZmlsdGVyRm4CBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDIwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAA0ADgAPABAAEQASABMAFAQIbWF4SW5kZXgDCQBmAgkAkAMBBQVsaXN0RgAACQCWAwEFBWxpc3RGCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUEbGlzdAAABAxsYXN0TWludXRlSWQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUOa19sYXN0TWludXRlSWQAAAQWZW5kTGFzdEN1bXVsYXRpdmVQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UCAV8JAKQDAQUMbGFzdE1pbnV0ZUlkAAAEDGVuZExhc3RQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUTa190d2FwRGF0YUxhc3RQcmljZQIBXwkApAMBBQxsYXN0TWludXRlSWQAAAQSbm93Q3VtdWxhdGl2ZVByaWNlCQBkAgUWZW5kTGFzdEN1bXVsYXRpdmVQcmljZQkAaAIJAGUCBQhtaW51dGVJZAUMbGFzdE1pbnV0ZUlkBQxlbmRMYXN0UHJpY2UEGHN0YXJ0TGFzdEN1bXVsYXRpdmVQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UCAV8JAKQDAQUIbWF4SW5kZXgAAAQOc3RhcnRMYXN0UHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkArAICCQCsAgIFE2tfdHdhcERhdGFMYXN0UHJpY2UCAV8JAKQDAQUIbWF4SW5kZXgAAAQUc3RhcnRDdW11bGF0aXZlUHJpY2UJAGQCBRhzdGFydExhc3RDdW11bGF0aXZlUHJpY2UJAGgCCQBlAgUNc3RhcnRNaW51dGVJZAUIbWF4SW5kZXgFDnN0YXJ0TGFzdFByaWNlCQBpAgkAZQIFEm5vd0N1bXVsYXRpdmVQcmljZQUUc3RhcnRDdW11bGF0aXZlUHJpY2UFDVRXQVBfSU5URVJWQUwBE2dldFRlcm1pbmFsQW1tU3RhdGUABA1fcG9zaXRpb25TaXplCQERdG90YWxQb3NpdGlvblNpemUAAwkAAAIFDV9wb3NpdGlvblNpemUAAAkAlAoCCQEGcXRBc3RSAAkBBmJzQXN0UgAECWRpcmVjdGlvbgkAZgIFDV9wb3NpdGlvblNpemUAAAQNJHQwMzE3MDAzMTg3OQkBCnN3YXBPdXRwdXQDBQlkaXJlY3Rpb24JAQNhYnMBBQ1fcG9zaXRpb25TaXplBwQVY3VycmVudE5ldE1hcmtldFZhbHVlCAUNJHQwMzE3MDAzMTg3OQJfMQQZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQgFDSR0MDMxNzAwMzE4NzkCXzIEGHRlcm1pbmFsQmFzZUFzc2V0UmVzZXJ2ZQgFDSR0MDMxNzAwMzE4NzkCXzMJAJQKAgUZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQUYdGVybWluYWxCYXNlQXNzZXRSZXNlcnZlARNnZXRRdW90ZUFzc2V0V2VpZ2h0BBBiYXNlQXNzZXRSZXNlcnZlEXRvdGFsUG9zaXRpb25TaXplEXF1b3RlQXNzZXRSZXNlcnZlC3RhcmdldFByaWNlBAFiCQC2AgEFEGJhc2VBc3NldFJlc2VydmUEAnN6CQC2AgEFEXRvdGFsUG9zaXRpb25TaXplBAFxCQC2AgEFEXF1b3RlQXNzZXRSZXNlcnZlBAFwCQC2AgEFC3RhcmdldFByaWNlBANiczIJAQVicG93ZAIJALcCAgUBYgUCc3oJALYCAQkAaAIAAgUMREVDSU1BTF9VTklUBARxYnMyCQEFYm11bGQCBQFxBQNiczIEA3BzNAkAuQICCQC2AgEABAkBBWJtdWxkAgUBcAUCc3oEA3NxcgkBBmJzcXJ0ZAEJAQVibXVsZAIFBHFiczIJALgCAgUBcQUDcHM0BAJicQkBBWJtdWxkAgUBYgUBcQQCcXMJAQVibXVsZAIFAXEFAnN6BAN0b3AJALcCAgkAtwICCQC+AgEFA3NxcgUCYnEFAnFzBANib3QJALkCAgkAtgIBAAIJAQVibXVsZAIFAXEFAnN6BAZyZXN1bHQJAQViZGl2ZAIFA3RvcAUDYm90CQCgAwEFBnJlc3VsdAEUZ2V0U3luY1Rlcm1pbmFsUHJpY2UDDl90ZXJtaW5hbFByaWNlB19xdEFzdFIHX2JzQXN0UgQNX3Bvc2l0aW9uU2l6ZQkBEXRvdGFsUG9zaXRpb25TaXplAAMJAAACBQ1fcG9zaXRpb25TaXplAAAECW5ld1F0QXN0VwkBBGRpdmQCCQEEbXVsZAIFDl90ZXJtaW5hbFByaWNlBQdfYnNBc3RSBQdfcXRBc3RSCQCVCgMFCW5ld1F0QXN0VwUMREVDSU1BTF9VTklUAAAECWRpcmVjdGlvbgkAZgIFDV9wb3NpdGlvblNpemUAAAQVY3VycmVudE5ldE1hcmtldFZhbHVlCAkBCnN3YXBPdXRwdXQDBQlkaXJlY3Rpb24JAQNhYnMBBQ1fcG9zaXRpb25TaXplBwJfMQQJbmV3UXRBc3RXCQETZ2V0UXVvdGVBc3NldFdlaWdodAQFB19ic0FzdFIFDV9wb3NpdGlvblNpemUFB19xdEFzdFIFDl90ZXJtaW5hbFByaWNlBAluZXdCc0FzdFcFDERFQ0lNQUxfVU5JVAQNbWFyZ2luVG9WYXVsdAgJAStnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubEJ5VmFsdWVzBwUNX3Bvc2l0aW9uU2l6ZQUVY3VycmVudE5ldE1hcmtldFZhbHVlBQdfcXRBc3RSBQluZXdRdEFzdFcFB19ic0FzdFIFCW5ld0JzQXN0VwUPUE5MX09QVElPTl9TUE9UAl8yCQCVCgMFCW5ld1F0QXN0VwUJbmV3QnNBc3RXBQ1tYXJnaW5Ub1ZhdWx0AQpnZXRGdW5kaW5nAAQPdW5kZXJseWluZ1ByaWNlCQEOZ2V0T3JhY2xlUHJpY2UABA1zcG90VHdhcFByaWNlCQEQZ2V0VHdhcFNwb3RQcmljZQAEB3ByZW1pdW0JAGUCBQ1zcG90VHdhcFByaWNlBQ91bmRlcmx5aW5nUHJpY2UDAwMJAAACCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAAAAYJAAACCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAAABgkBDmlzTWFya2V0Q2xvc2VkAAkAlAoCAAAAAAMJAGYCAAAFB3ByZW1pdW0EFHNob3J0UHJlbWl1bUZyYWN0aW9uCQEEZGl2ZAIJAQRtdWxkAgUHcHJlbWl1bQkBFGZ1bmRpbmdQZXJpb2REZWNpbWFsAAUHT05FX0RBWQQTbG9uZ1ByZW1pdW1GcmFjdGlvbgkBBGRpdmQCCQEEbXVsZAIFFHNob3J0UHJlbWl1bUZyYWN0aW9uCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAJARV0b3RhbExvbmdQb3NpdGlvblNpemUACQCUCgIFFHNob3J0UHJlbWl1bUZyYWN0aW9uBRNsb25nUHJlbWl1bUZyYWN0aW9uBBNsb25nUHJlbWl1bUZyYWN0aW9uCQEEZGl2ZAIJAQRtdWxkAgUHcHJlbWl1bQkBFGZ1bmRpbmdQZXJpb2REZWNpbWFsAAUHT05FX0RBWQQUc2hvcnRQcmVtaXVtRnJhY3Rpb24JAQRkaXZkAgkBBG11bGQCBRNsb25nUHJlbWl1bUZyYWN0aW9uCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUACQCUCgIFFHNob3J0UHJlbWl1bUZyYWN0aW9uBRNsb25nUHJlbWl1bUZyYWN0aW9uAQ5nZXRBZGp1c3RlZEZlZQILX2FydGlmYWN0SWQQX2Jhc2VGZWVEaXNjb3VudAQKYmFzZUZlZVJhdwkBA2ZlZQAEB2Jhc2VGZWUJAQRtdWxkAgUKYmFzZUZlZVJhdwUQX2Jhc2VGZWVEaXNjb3VudAQNJHQwMzQ5MjczNTQyMgMJAQIhPQIFC19hcnRpZmFjdElkAgAEDGFydGlmYWN0S2luZAkBBHN0ckECCQERbmZ0TWFuYWdlckFkZHJlc3MACQEOdG9Db21wb3NpdGVLZXkCBQxrX3Rva2VuX3R5cGUFC19hcnRpZmFjdElkAwkAAAIFDGFydGlmYWN0S2luZAUYRkVFX1JFRFVDVElPTl9UT0tFTl9UWVBFBAlyZWR1Y3Rpb24JAQRpbnRBAgkBEW5mdE1hbmFnZXJBZGRyZXNzAAkBDnRvQ29tcG9zaXRlS2V5AgUNa190b2tlbl9wYXJhbQULX2FydGlmYWN0SWQEC2FkanVzdGVkRmVlCQEEbXVsZAIFB2Jhc2VGZWUFCXJlZHVjdGlvbgkAlAoCBQthZGp1c3RlZEZlZQYJAAIBAhlJbnZhbGlkIGF0dGFjaGVkIGFydGlmYWN0CQCUCgIFB2Jhc2VGZWUHBAthZGp1c3RlZEZlZQgFDSR0MDM0OTI3MzU0MjICXzEEDGJ1cm5BcnRpZmFjdAgFDSR0MDM0OTI3MzU0MjICXzIJAJQKAgULYWRqdXN0ZWRGZWUFDGJ1cm5BcnRpZmFjdAEXaXNTYW1lQXNzZXRPck5vUG9zaXRpb24CB190cmFkZXIIX2Fzc2V0SWQED29sZFBvc2l0aW9uU2l6ZQgJAQtnZXRQb3NpdGlvbgEFB190cmFkZXICXzEDCQAAAgUPb2xkUG9zaXRpb25TaXplAAAGCQAAAgkBEGdldFBvc2l0aW9uQXNzZXQBBQdfdHJhZGVyBQhfYXNzZXRJZAELaXNTYW1lQXNzZXQCB190cmFkZXIIX2Fzc2V0SWQJAAACCQEQZ2V0UG9zaXRpb25Bc3NldAEFB190cmFkZXIFCF9hc3NldElkAR5nZXRCb3Jyb3dlZEJ5VHJhZGVySW5NYXJrZXRLZXkDBF9hbW0IX2Fzc2V0SWQHX3RyYWRlcgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgUga190cmFkZXJfbWFya2V0X2Fzc2V0X2NvbGxhdGVyYWwCAV8FBF9hbW0CAV8FCF9hc3NldElkAgFfBQdfdHJhZGVyARNnZXRCb3Jyb3dlZEJ5VHJhZGVyAQdfdHJhZGVyBA1wb3NpdGlvbkFzc2V0CQEQZ2V0UG9zaXRpb25Bc3NldAEFB190cmFkZXIDCQAAAgUNcG9zaXRpb25Bc3NldAkA2AQBCQEKcXVvdGVBc3NldAAJAJQKAgAABQ1wb3NpdGlvbkFzc2V0BANrZXkJAR5nZXRCb3Jyb3dlZEJ5VHJhZGVySW5NYXJrZXRLZXkDCQClCAEFBHRoaXMFDXBvc2l0aW9uQXNzZXQFB190cmFkZXIEBmJvcnJvdwkBC3ZhbHVlT3JFbHNlAgkAmggCCQERY29sbGF0ZXJhbEFkZHJlc3MABQNrZXkAAAkAlAoCBQZib3Jyb3cFDXBvc2l0aW9uQXNzZXQBGGdldEZvclRyYWRlcldpdGhBcnRpZmFjdAIHX3RyYWRlcgtfYXJ0aWZhY3RJZAQQZG9HZXRGZWVEaXNjb3VudAkA/AcECQEMbWluZXJBZGRyZXNzAAISY29tcHV0ZUZlZURpc2NvdW50CQDMCAIFB190cmFkZXIFA25pbAUDbmlsAwkAAAIFEGRvR2V0RmVlRGlzY291bnQFEGRvR2V0RmVlRGlzY291bnQEC2ZlZURpc2NvdW50BAckbWF0Y2gwBRBkb0dldEZlZURpc2NvdW50AwkAAQIFByRtYXRjaDACA0ludAQBeAUHJG1hdGNoMAUBeAkAAgECIUludmFsaWQgY29tcHV0ZUZlZURpc2NvdW50IHJlc3VsdAQNJHQwMzY2NTMzNjcyNwkBDmdldEFkanVzdGVkRmVlAgULX2FydGlmYWN0SWQFC2ZlZURpc2NvdW50BAthZGp1c3RlZEZlZQgFDSR0MDM2NjUzMzY3MjcCXzEEDGJ1cm5BcnRpZmFjdAgFDSR0MDM2NjUzMzY3MjcCXzIJAJQKAgULYWRqdXN0ZWRGZWUFDGJ1cm5BcnRpZmFjdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgENZ2V0QXJ0aWZhY3RJZAEBaQQKYXJ0aWZhY3RJZAMJAGYCCQCQAwEIBQFpCHBheW1lbnRzAAEJANgEAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCAkAkQMCCAUBaQhwYXltZW50cwABB2Fzc2V0SWQCEkludmFsaWQgYXJ0aWZhY3RJZAIABQphcnRpZmFjdElkAQ1kaXN0cmlidXRlRmVlAQpfZmVlQW1vdW50BAxmZWVUb1N0YWtlcnMJAQRtdWxkAgUKX2ZlZUFtb3VudAkBE2ZlZVRvU3Rha2Vyc1BlcmNlbnQABApmZWVUb1ZhdWx0CQBlAgUKX2ZlZUFtb3VudAUMZmVlVG9TdGFrZXJzCQCUCgIFDGZlZVRvU3Rha2VycwUKZmVlVG9WYXVsdAEOdXBkYXRlU2V0dGluZ3MMEF9pbml0TWFyZ2luUmF0aW8EX21tchRfbGlxdWlkYXRpb25GZWVSYXRpbw5fZnVuZGluZ1BlcmlvZARfZmVlDF9zcHJlYWRMaW1pdA9fbWF4UHJpY2VJbXBhY3QYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvD19tYXhQcmljZVNwcmVhZBBfbWF4T3Blbk5vdGlvbmFsFF9mZWVUb1N0YWtlcnNQZXJjZW50D19tYXhPcmFjbGVEZWxheQkAzAgCCQEMSW50ZWdlckVudHJ5AgURa19pbml0TWFyZ2luUmF0aW8FEF9pbml0TWFyZ2luUmF0aW8JAMwIAgkBDEludGVnZXJFbnRyeQIFGGtfbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwUEX21tcgkAzAgCCQEMSW50ZWdlckVudHJ5AgUVa19saXF1aWRhdGlvbkZlZVJhdGlvBRRfbGlxdWlkYXRpb25GZWVSYXRpbwkAzAgCCQEMSW50ZWdlckVudHJ5AgUPa19mdW5kaW5nUGVyaW9kBQ5fZnVuZGluZ1BlcmlvZAkAzAgCCQEMSW50ZWdlckVudHJ5AgUFa19mZWUFBF9mZWUJAMwIAgkBDEludGVnZXJFbnRyeQIFDWtfc3ByZWFkTGltaXQFDF9zcHJlYWRMaW1pdAkAzAgCCQEMSW50ZWdlckVudHJ5AgUQa19tYXhQcmljZUltcGFjdAUPX21heFByaWNlSW1wYWN0CQDMCAIJAQxJbnRlZ2VyRW50cnkCBRlrX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvBRhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8JAMwIAgkBDEludGVnZXJFbnRyeQIFEGtfbWF4UHJpY2VTcHJlYWQFD19tYXhQcmljZVNwcmVhZAkAzAgCCQEMSW50ZWdlckVudHJ5AgURa19tYXhPcGVuTm90aW9uYWwFEF9tYXhPcGVuTm90aW9uYWwJAMwIAgkBDEludGVnZXJFbnRyeQIFFWtfZmVlVG9TdGFrZXJzUGVyY2VudAUUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQJAMwIAgkBDEludGVnZXJFbnRyeQIFEGtfbWF4T3JhY2xlRGVsYXkFFF9mZWVUb1N0YWtlcnNQZXJjZW50BQNuaWwBDXVwZGF0ZUZ1bmRpbmcFEV9uZXh0RnVuZGluZ0Jsb2NrJF9sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbiVfbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uEF9sb25nRnVuZGluZ1JhdGURX3Nob3J0RnVuZGluZ1JhdGUJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfbmV4dEZ1bmRpbmdCbG9jawURX25leHRGdW5kaW5nQmxvY2sJAMwIAgkBDEludGVnZXJFbnRyeQIFJWtfbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FJF9sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgUma19sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FJV9sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24JAMwIAgkBDEludGVnZXJFbnRyeQIFEWtfbG9uZ0Z1bmRpbmdSYXRlBRBfbG9uZ0Z1bmRpbmdSYXRlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJrX3Nob3J0RnVuZGluZ1JhdGUFEV9zaG9ydEZ1bmRpbmdSYXRlBQNuaWwBE3VwZGF0ZVBvc2l0aW9uQXNzZXQCCF9hZGRyZXNzCF9hc3NldElkCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFD2tfcG9zaXRpb25Bc3NldAUIX2FkZHJlc3MFCF9hc3NldElkBQNuaWwBH2luY3JlbWVudFBvc2l0aW9uU2VxdWVuY2VOdW1iZXICDWlzTmV3UG9zaXRpb24IX2FkZHJlc3MDBQ1pc05ld1Bvc2l0aW9uBA9jdXJyZW50U2VxdWVuY2UJAQxsYXN0U2VxdWVuY2UACQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRJrX3Bvc2l0aW9uU2VxdWVuY2UFCF9hZGRyZXNzCQBkAgUPY3VycmVudFNlcXVlbmNlAAEJAMwIAgkBDEludGVnZXJFbnRyeQIFCmtfc2VxdWVuY2UJAGQCBQ9jdXJyZW50U2VxdWVuY2UAAQUDbmlsBQNuaWwBDnVwZGF0ZVBvc2l0aW9uBQhfYWRkcmVzcwVfc2l6ZQdfbWFyZ2luDV9vcGVuTm90aW9uYWwgX2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24JAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFDmtfcG9zaXRpb25TaXplBQhfYWRkcmVzcwUFX3NpemUJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFEGtfcG9zaXRpb25NYXJnaW4FCF9hZGRyZXNzBQdfbWFyZ2luCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBQhfYWRkcmVzcwUNX29wZW5Ob3Rpb25hbAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUua19wb3NpdGlvbkxhc3RVcGRhdGVkQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUIX2FkZHJlc3MFIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBQNuaWwBCmFwcGVuZFR3YXABBl9wcmljZQQIbWludXRlSWQJAGkCCQBpAggFCWxhc3RCbG9jawl0aW1lc3RhbXAA6AcAPAQQcHJldmlvdXNNaW51dGVJZAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQ5rX2xhc3RNaW51dGVJZAAAAwkAZgIFEHByZXZpb3VzTWludXRlSWQFCG1pbnV0ZUlkCQACAQIRVFdBUCBvdXQtb2Ytb3JkZXIEDGxhc3RNaW51dGVJZAMJAAACBRBwcmV2aW91c01pbnV0ZUlkAAAFCG1pbnV0ZUlkBRBwcmV2aW91c01pbnV0ZUlkAwkAZgIFCG1pbnV0ZUlkBRBwcmV2aW91c01pbnV0ZUlkBBNwcmV2Q3VtdWxhdGl2ZVByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAKwCAgkArAICBR1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQIBXwkApAMBBRBwcmV2aW91c01pbnV0ZUlkAAAECXByZXZQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUTa190d2FwRGF0YUxhc3RQcmljZQIBXwkApAMBBRBwcmV2aW91c01pbnV0ZUlkBQZfcHJpY2UEE2xhc3RDdW11bGF0aXZlUHJpY2UJAGQCBRNwcmV2Q3VtdWxhdGl2ZVByaWNlCQBoAgkAZQIFCG1pbnV0ZUlkBQxsYXN0TWludXRlSWQFCXByZXZQcmljZQQEbGlzdAkBC3B1c2hUb1F1ZXVlAwkBCXN0clRvTGlzdAEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwUNa19sYXN0RGF0YVN0cgIABQ1UV0FQX0lOVEVSVkFMCQCkAwEFCG1pbnV0ZUlkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBR1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQkApAMBBQhtaW51dGVJZAUTbGFzdEN1bXVsYXRpdmVQcmljZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUTa190d2FwRGF0YUxhc3RQcmljZQkApAMBBQhtaW51dGVJZAUGX3ByaWNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRprX3R3YXBEYXRhUHJldmlvdXNNaW51dGVJZAkApAMBBQhtaW51dGVJZAUQcHJldmlvdXNNaW51dGVJZAkAzAgCCQEMSW50ZWdlckVudHJ5AgUOa19sYXN0TWludXRlSWQFCG1pbnV0ZUlkCQDMCAIJAQtTdHJpbmdFbnRyeQIFDWtfbGFzdERhdGFTdHIJAQlsaXN0VG9TdHIBBQRsaXN0BQNuaWwEGHR3YXBEYXRhUHJldmlvdXNNaW51dGVJZAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBRprX3R3YXBEYXRhUHJldmlvdXNNaW51dGVJZAkApAMBBQhtaW51dGVJZAAABBNwcmV2Q3VtdWxhdGl2ZVByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlCQCkAwEFGHR3YXBEYXRhUHJldmlvdXNNaW51dGVJZAAABAlwcmV2UHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUTa190d2FwRGF0YUxhc3RQcmljZQkApAMBBRh0d2FwRGF0YVByZXZpb3VzTWludXRlSWQFBl9wcmljZQQTbGFzdEN1bXVsYXRpdmVQcmljZQkAZAIFE3ByZXZDdW11bGF0aXZlUHJpY2UJAGgCCQBlAgUIbWludXRlSWQFGHR3YXBEYXRhUHJldmlvdXNNaW51dGVJZAUJcHJldlByaWNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBR1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQkApAMBBQhtaW51dGVJZAUTbGFzdEN1bXVsYXRpdmVQcmljZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUTa190d2FwRGF0YUxhc3RQcmljZQkApAMBBQhtaW51dGVJZAUGX3ByaWNlBQNuaWwBEXVwZGF0ZUFtbVJlc2VydmVzAgdfcXRBc3RSB19ic0FzdFIJAMwIAgkBDEludGVnZXJFbnRyeQIFE2tfcXVvdGVBc3NldFJlc2VydmUFB19xdEFzdFIJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfYmFzZUFzc2V0UmVzZXJ2ZQUHX2JzQXN0UgUDbmlsARB1cGRhdGVBbW1XZWlnaHRzAgdfcXRBc3RXB19ic0FzdFcJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfcXVvdGVBc3NldFdlaWdodAUHX3F0QXN0VwkAzAgCCQEMSW50ZWdlckVudHJ5AgURa19iYXNlQXNzZXRXZWlnaHQFB19ic0FzdFcFA25pbAEJdXBkYXRlQW1tCAdfcXRBc3RSB19ic0FzdFIXX3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIVX29wZW5JbnRlcmVzdE5vdGlvbmFsFl90b3RhbExvbmdQb3NpdGlvblNpemUXX3RvdGFsU2hvcnRQb3NpdGlvblNpemUWX3RvdGFsTG9uZ09wZW5Ob3Rpb25hbBdfdG90YWxTaG9ydE9wZW5Ob3Rpb25hbAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcAAwkBAiE9AgkAZQIFFl90b3RhbExvbmdQb3NpdGlvblNpemUFF190b3RhbFNob3J0UG9zaXRpb25TaXplBRdfdG90YWxQb3NpdGlvblNpemVBZnRlcgkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAhhJbnZhbGlkIEFNTSBzdGF0ZSBkYXRhOiAJAKQDAQUWX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQIEICsgIAkApAMBBRdfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQIEICE9IAkApAMBBRdfdG90YWxQb3NpdGlvblNpemVBZnRlcgkAzggCCQDOCAIJARF1cGRhdGVBbW1SZXNlcnZlcwIFB19xdEFzdFIFB19ic0FzdFIJAMwIAgkBDEludGVnZXJFbnRyeQIFE2tfdG90YWxQb3NpdGlvblNpemUFF190b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRZrX29wZW5JbnRlcmVzdE5vdGlvbmFsBRVfb3BlbkludGVyZXN0Tm90aW9uYWwJAMwIAgkBDEludGVnZXJFbnRyeQIFF2tfdG90YWxMb25nUG9zaXRpb25TaXplBRZfdG90YWxMb25nUG9zaXRpb25TaXplCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRhrX3RvdGFsU2hvcnRQb3NpdGlvblNpemUFF190b3RhbFNob3J0UG9zaXRpb25TaXplCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJrX29wZW5JbnRlcmVzdExvbmcFFl90b3RhbExvbmdPcGVuTm90aW9uYWwJAMwIAgkBDEludGVnZXJFbnRyeQIFE2tfb3BlbkludGVyZXN0U2hvcnQFF190b3RhbFNob3J0T3Blbk5vdGlvbmFsBQNuaWwJAQphcHBlbmRUd2FwAQkBBGRpdmQCCQEEbXVsZAIFB19xdEFzdFIFB19xdEFzdFcJAQRtdWxkAgUHX2JzQXN0UgUHX2JzQXN0VwEOZGVsZXRlUG9zaXRpb24BCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFDmtfcG9zaXRpb25TaXplBQhfYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBRBrX3Bvc2l0aW9uTWFyZ2luBQhfYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBRZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBQhfYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBS5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBQhfYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBQ9rX3Bvc2l0aW9uQXNzZXQFCF9hZGRyZXNzBQNuaWwBCHdpdGhkcmF3AghfYWRkcmVzcwdfYW1vdW50BAdiYWxhbmNlCQDwBwIFBHRoaXMJAQpxdW90ZUFzc2V0AAMJAGYCBQdfYW1vdW50BQdiYWxhbmNlCQACAQkArAICCQCsAgIJAKwCAgITVW5hYmxlIHRvIHdpdGhkcmF3IAkApAMBBQdfYW1vdW50AhcgZnJvbSBjb250cmFjdCBiYWxhbmNlIAkApAMBBQdiYWxhbmNlCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFCF9hZGRyZXNzBQdfYW1vdW50CQEKcXVvdGVBc3NldAAFA25pbAENdXBkYXRlQmFsYW5jZQEBaQMJAGYCAAAFAWkJAAIBAgdCYWxhbmNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQlrX2JhbGFuY2UFAWkFA25pbAELdHJhbnNmZXJGZWUBAWkJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwkBDnN0YWtpbmdBZGRyZXNzAAUBaQkBCnF1b3RlQXNzZXQABQNuaWwBDmRvQnVybkFydGlmYWN0Ag1fYnVybkFydGlmYWN0AWkDBQ1fYnVybkFydGlmYWN0CQDMCAIJAQRCdXJuAgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCAkAkQMCCAUBaQhwYXltZW50cwABB2Fzc2V0SWQCEEludmFsaWQgYXJ0aWZhY3QAAQUDbmlsBQNuaWwXAWkBBXBhdXNlAAMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAhRJbnZhbGlkIHBhdXNlIHBhcmFtcwkAzAgCCQEMQm9vbGVhbkVudHJ5AgUIa19wYXVzZWQGBQNuaWwBaQEHdW5wYXVzZQADCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MACQACAQIWSW52YWxpZCB1bnBhdXNlIHBhcmFtcwkAzAgCCQEMQm9vbGVhbkVudHJ5AgUIa19wYXVzZWQHBQNuaWwBaQEMc2V0Q2xvc2VPbmx5AAMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAhtJbnZhbGlkIHNldENsb3NlT25seSBwYXJhbXMJAMwIAgkBDEJvb2xlYW5FbnRyeQIFC2tfY2xvc2VPbmx5BgUDbmlsAWkBDnVuc2V0Q2xvc2VPbmx5AAMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAh1JbnZhbGlkIHVuc2V0Q2xvc2VPbmx5IHBhcmFtcwkAzAgCCQEMQm9vbGVhbkVudHJ5AgULa19jbG9zZU9ubHkHBQNuaWwBaQEMYWRkTGlxdWlkaXR5ARFfcXVvdGVBc3NldEFtb3VudAMDCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MABgkAZwIAAAURX3F1b3RlQXNzZXRBbW91bnQJAAIBAhtJbnZhbGlkIGFkZExpcXVpZGl0eSBwYXJhbXMEB19xdEFzdFIJAQZxdEFzdFIABAdfYnNBc3RSCQEGYnNBc3RSAAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcABAVwcmljZQkBBGRpdmQCCQEEbXVsZAIFB19xdEFzdFIFB19xdEFzdFcJAQRtdWxkAgUHX2JzQXN0UgUHX2JzQXN0VwQLcXRBc3RSQWZ0ZXIJAGQCBQdfcXRBc3RSBRFfcXVvdGVBc3NldEFtb3VudAQUYmFzZUFzc2V0QW1vdW50VG9BZGQJAGUCCQEEZGl2ZAIJAQRtdWxkAgULcXRBc3RSQWZ0ZXIFB19xdEFzdFcFBXByaWNlBQdfYnNBc3RSBAtic0FzdFJBZnRlcgkAZAIFB19ic0FzdFIFFGJhc2VBc3NldEFtb3VudFRvQWRkBA0kdDA0NTc0OTQ1OTAwCQEUZ2V0U3luY1Rlcm1pbmFsUHJpY2UDCQEOZ2V0T3JhY2xlUHJpY2UABQtxdEFzdFJBZnRlcgULYnNBc3RSQWZ0ZXIEE25ld1F1b3RlQXNzZXRXZWlnaHQIBQ0kdDA0NTc0OTQ1OTAwAl8xBBJuZXdCYXNlQXNzZXRXZWlnaHQIBQ0kdDA0NTc0OTQ1OTAwAl8yBA1tYXJnaW5Ub1ZhdWx0CAUNJHQwNDU3NDk0NTkwMAJfMwQNZG9FeGNoYW5nZVBuTAMJAQIhPQIFDW1hcmdpblRvVmF1bHQAAAQNZG9FeGNoYW5nZVBuTAkA/AcECQEMdmF1bHRBZGRyZXNzAAIVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkCQDMCAIFDW1hcmdpblRvVmF1bHQFA25pbAUDbmlsAwkAAAIFDWRvRXhjaGFuZ2VQbkwFDWRvRXhjaGFuZ2VQbkwFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFDWRvRXhjaGFuZ2VQbkwFDWRvRXhjaGFuZ2VQbkwJAM4IAgkBEXVwZGF0ZUFtbVJlc2VydmVzAgULcXRBc3RSQWZ0ZXIFC2JzQXN0UkFmdGVyCQEQdXBkYXRlQW1tV2VpZ2h0cwIFE25ld1F1b3RlQXNzZXRXZWlnaHQFEm5ld0Jhc2VBc3NldFdlaWdodAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ9yZW1vdmVMaXF1aWRpdHkBEV9xdW90ZUFzc2V0QW1vdW50AwMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAGCQBnAgAABRFfcXVvdGVBc3NldEFtb3VudAkAAgECHkludmFsaWQgcmVtb3ZlTGlxdWlkaXR5IHBhcmFtcwQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwAEBXByaWNlCQEEZGl2ZAIJAQRtdWxkAgUHX3F0QXN0UgUHX3F0QXN0VwkBBG11bGQCBQdfYnNBc3RSBQdfYnNBc3RXBBdiYXNlQXNzZXRBbW91bnRUb1JlbW92ZQkBBGRpdmQCBRFfcXVvdGVBc3NldEFtb3VudAUFcHJpY2UEC3F0QXN0UkFmdGVyCQBlAgUHX3F0QXN0UgURX3F1b3RlQXNzZXRBbW91bnQEC2JzQXN0UkFmdGVyCQBlAgUHX2JzQXN0UgUXYmFzZUFzc2V0QW1vdW50VG9SZW1vdmUJARF1cGRhdGVBbW1SZXNlcnZlcwIFC3F0QXN0UkFmdGVyBQtic0FzdFJBZnRlcgFpAQ5jaGFuZ2VTZXR0aW5ncwwQX2luaXRNYXJnaW5SYXRpbwRfbW1yFF9saXF1aWRhdGlvbkZlZVJhdGlvDl9mdW5kaW5nUGVyaW9kBF9mZWUMX3NwcmVhZExpbWl0D19tYXhQcmljZUltcGFjdBhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8PX21heFByaWNlU3ByZWFkEF9tYXhPcGVuTm90aW9uYWwUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQPX21heE9yYWNsZURlbGF5AwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECHUludmFsaWQgY2hhbmdlU2V0dGluZ3MgcGFyYW1zCQEOdXBkYXRlU2V0dGluZ3MMBRBfaW5pdE1hcmdpblJhdGlvBQRfbW1yBRRfbGlxdWlkYXRpb25GZWVSYXRpbwUOX2Z1bmRpbmdQZXJpb2QFBF9mZWUFDF9zcHJlYWRMaW1pdAUPX21heFByaWNlSW1wYWN0BRhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8FD19tYXhQcmljZVNwcmVhZAUQX21heE9wZW5Ob3Rpb25hbAUUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQFD19tYXhPcmFjbGVEZWxheQFpAQppbml0aWFsaXplEgdfcXRBc3RSB19ic0FzdFIOX2Z1bmRpbmdQZXJpb2QQX2luaXRNYXJnaW5SYXRpbwRfbW1yFF9saXF1aWRhdGlvbkZlZVJhdGlvBF9mZWUHX29yYWNsZQpfb3JhY2xlS2V5D19vcmFjbGVCbG9ja0tleQxfY29vcmRpbmF0b3IMX3NwcmVhZExpbWl0D19tYXhQcmljZUltcGFjdBhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8PX21heFByaWNlU3ByZWFkEF9tYXhPcGVuTm90aW9uYWwUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQPX21heE9yYWNsZURlbGF5AwMDAwMDAwMDAwMDAwMDAwkAZwIAAAUHX3F0QXN0UgYJAGcCAAAFB19ic0FzdFIGCQBnAgAABQ5fZnVuZGluZ1BlcmlvZAYJAGcCAAAFEF9pbml0TWFyZ2luUmF0aW8GCQBnAgAABQRfbW1yBgkAZwIAAAUUX2xpcXVpZGF0aW9uRmVlUmF0aW8GCQBnAgAABQRfZmVlBgkAZwIAAAUMX3NwcmVhZExpbWl0BgkAZwIAAAUPX21heFByaWNlSW1wYWN0BgkAZwIAAAUYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvBgkAZwIAAAUPX21heFByaWNlU3ByZWFkBgkAZwIAAAUQX21heE9wZW5Ob3Rpb25hbAYJAGcCAAAFFF9mZWVUb1N0YWtlcnNQZXJjZW50BgkAZgIFFF9mZWVUb1N0YWtlcnNQZXJjZW50BQxERUNJTUFMX1VOSVQGCQBnAgAABQ9fbWF4T3JhY2xlRGVsYXkGCQELaW5pdGlhbGl6ZWQACQACAQIdSW52YWxpZCBpbml0aWFsaXplIHBhcmFtZXRlcnMJAM4IAgkAzggCCQDOCAIJAM4IAgkBCXVwZGF0ZUFtbQgFB19xdEFzdFIFB19ic0FzdFIAAAAAAAAAAAAAAAAJAQ51cGRhdGVTZXR0aW5ncwwFEF9pbml0TWFyZ2luUmF0aW8FBF9tbXIFFF9saXF1aWRhdGlvbkZlZVJhdGlvBQ5fZnVuZGluZ1BlcmlvZAUEX2ZlZQUMX3NwcmVhZExpbWl0BQ9fbWF4UHJpY2VJbXBhY3QFGF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwUPX21heFByaWNlU3ByZWFkBRBfbWF4T3Blbk5vdGlvbmFsBRRfZmVlVG9TdGFrZXJzUGVyY2VudAUPX21heE9yYWNsZURlbGF5CQENdXBkYXRlRnVuZGluZwUJAGQCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAUOX2Z1bmRpbmdQZXJpb2QAAAAAAAAAAAkBDXVwZGF0ZUJhbGFuY2UBAAAJAMwIAgkBDEJvb2xlYW5FbnRyeQIFDWtfaW5pdGlhbGl6ZWQGCQDMCAIJAQtTdHJpbmdFbnRyeQIFBWtfb3JhBQdfb3JhY2xlCQDMCAIJAQtTdHJpbmdFbnRyeQIFCWtfb3JhX2tleQUKX29yYWNsZUtleQkAzAgCCQELU3RyaW5nRW50cnkCBQ9rX29yYV9ibG9ja19rZXkFD19vcmFjbGVCbG9ja0tleQkAzAgCCQELU3RyaW5nRW50cnkCBRRrX2Nvb3JkaW5hdG9yQWRkcmVzcwUMX2Nvb3JkaW5hdG9yBQNuaWwBaQEQZGVjcmVhc2VQb3NpdGlvbgMHX2Ftb3VudAlfbGV2ZXJhZ2UTX21pbkJhc2VBc3NldEFtb3VudAQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBAdfdHJhZGVyCQEPZ2V0QWN0dWFsQ2FsbGVyAQUBaQMDAwMDAwkAZwIAAAUHX2Ftb3VudAYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQEhAQkBFnJlcXVpcmVNb3JlTWFyZ2luUmF0aW8DCQEEZGl2ZAIFDERFQ0lNQUxfVU5JVAUJX2xldmVyYWdlCQEPaW5pdE1hcmdpblJhdGlvAAYGCQEBIQEJARNyZXF1aXJlT3BlblBvc2l0aW9uAQUHX3RyYWRlcgYJAQZwYXVzZWQABgkBDmlzTWFya2V0Q2xvc2VkAAkAAgECI0ludmFsaWQgZGVjcmVhc2VQb3NpdGlvbiBwYXJhbWV0ZXJzBA0kdDA0OTc2NzQ5OTA3CQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBA9vbGRQb3NpdGlvblNpemUIBQ0kdDA0OTc2NzQ5OTA3Al8xBBFvbGRQb3NpdGlvbk1hcmdpbggFDSR0MDQ5NzY3NDk5MDcCXzIEF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNDk3Njc0OTkwNwJfMwQUb2xkUG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA0OTc2NzQ5OTA3Al80BApfZGlyZWN0aW9uAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAABQlESVJfU0hPUlQFCERJUl9MT05HBAVpc0FkZAkAAAIFCl9kaXJlY3Rpb24FCERJUl9MT05HBAxvcGVuTm90aW9uYWwJAQRtdWxkAgUHX2Ftb3VudAUJX2xldmVyYWdlBA0kdDA1MDA4MDUwMTg0CQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QEE29sZFBvc2l0aW9uTm90aW9uYWwIBQ0kdDA1MDA4MDUwMTg0Al8xBA11bnJlYWxpemVkUG5sCAUNJHQwNTAwODA1MDE4NAJfMgQNJHQwNTAxOTA1MjgzMgMJAGYCBRNvbGRQb3NpdGlvbk5vdGlvbmFsBQxvcGVuTm90aW9uYWwEDSR0MDUwNjA1NTA3ODkJAQlzd2FwSW5wdXQCBQVpc0FkZAUMb3Blbk5vdGlvbmFsBBVleGNoYW5nZWRQb3NpdGlvblNpemUIBQ0kdDA1MDYwNTUwNzg5Al8xBBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNTA2MDU1MDc4OQJfMgQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNTA2MDU1MDc4OQJfMwQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDUwNjA1NTA3ODkCXzQEGGV4Y2hhbmdlZFBvc2l0aW9uU2l6ZUFicwkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQMDCQECIT0CBRNfbWluQmFzZUFzc2V0QW1vdW50AAAJAGYCBRNfbWluQmFzZUFzc2V0QW1vdW50BRhleGNoYW5nZWRQb3NpdGlvblNpemVBYnMHCQACAQkArAICCQCsAgIJAKwCAgIlVG9vIGxpdHRsZSBiYXNlIGFzc2V0IGV4Y2hhbmdlZCwgZ290IAkApAMBBRhleGNoYW5nZWRQb3NpdGlvblNpemVBYnMCCiBleHBlY3RlZCAJAKQDAQUTX21pbkJhc2VBc3NldEFtb3VudAQLcmVhbGl6ZWRQbmwJAQRkaXZkAgkBBG11bGQCBQ11bnJlYWxpemVkUG5sBRhleGNoYW5nZWRQb3NpdGlvblNpemVBYnMJAQNhYnMBBQ9vbGRQb3NpdGlvblNpemUEDSR0MDUxMjI2NTE0NTUJASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BAUPb2xkUG9zaXRpb25TaXplBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25Mc3RVcGRDUEYFC3JlYWxpemVkUG5sBAxyZW1haW5NYXJnaW4IBQ0kdDA1MTIyNjUxNDU1Al8xBAdiYWREZWJ0CAUNJHQwNTEyMjY1MTQ1NQJfMgQZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAUMb3Blbk5vdGlvbmFsBBJ1bnJlYWxpemVkUG5sQWZ0ZXIJAGUCBQ11bnJlYWxpemVkUG5sBQtyZWFsaXplZFBubAQScmVtYWluT3Blbk5vdGlvbmFsAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAACQBlAgkAZQIFE29sZFBvc2l0aW9uTm90aW9uYWwFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQFEnVucmVhbGl6ZWRQbmxBZnRlcgkAZQIJAGQCBRJ1bnJlYWxpemVkUG5sQWZ0ZXIFE29sZFBvc2l0aW9uTm90aW9uYWwFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQED25ld1Bvc2l0aW9uU2l6ZQkAZAIFD29sZFBvc2l0aW9uU2l6ZQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplCQCeCgwFD25ld1Bvc2l0aW9uU2l6ZQUMcmVtYWluTWFyZ2luCQEDYWJzAQUScmVtYWluT3Blbk5vdGlvbmFsCQEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEFD25ld1Bvc2l0aW9uU2l6ZQUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCQBlAgkBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAAUMb3Blbk5vdGlvbmFsCQBlAgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQADCQBmAgUPbmV3UG9zaXRpb25TaXplAAAJAQNhYnMBBRVleGNoYW5nZWRQb3NpdGlvblNpemUAAAkAZQIJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAMJAGYCAAAFD25ld1Bvc2l0aW9uU2l6ZQkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQAACQBlAgkBEG9wZW5JbnRlcmVzdExvbmcAAwkAZgIFD25ld1Bvc2l0aW9uU2l6ZQAABQxvcGVuTm90aW9uYWwAAAkAZQIJARFvcGVuSW50ZXJlc3RTaG9ydAADCQBmAgAABQ9uZXdQb3NpdGlvblNpemUFDG9wZW5Ob3Rpb25hbAAACQACAQIUQ2xvc2UgcG9zaXRpb24gZmlyc3QED25ld1Bvc2l0aW9uU2l6ZQgFDSR0MDUwMTkwNTI4MzICXzEEF25ld1Bvc2l0aW9uUmVtYWluTWFyZ2luCAUNJHQwNTAxOTA1MjgzMgJfMgQXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA1MDE5MDUyODMyAl8zBBRuZXdQb3NpdGlvbkxhdGVzdENQRggFDSR0MDUwMTkwNTI4MzICXzQEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDUwMTkwNTI4MzICXzUEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA1MDE5MDUyODMyAl82BBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNTAxOTA1MjgzMgJfNwQZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcggFDSR0MDUwMTkwNTI4MzICXzgEDnRvdGFsTG9uZ0FmdGVyCAUNJHQwNTAxOTA1MjgzMgJfOQQPdG90YWxTaG9ydEFmdGVyCAUNJHQwNTAxOTA1MjgzMgNfMTAEGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNTAxOTA1MjgzMgNfMTEEG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDUwMTkwNTI4MzIDXzEyBA5ub3RpZnlOb3Rpb25hbAkA/AcECQEMbWluZXJBZGRyZXNzAAIObm90aWZ5Tm90aW9uYWwJAMwIAgUHX3RyYWRlcgkAzAgCBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUDbmlsBQNuaWwDCQAAAgUObm90aWZ5Tm90aW9uYWwFDm5vdGlmeU5vdGlvbmFsCQDOCAIJAQ51cGRhdGVQb3NpdGlvbgUFB190cmFkZXIFD25ld1Bvc2l0aW9uU2l6ZQUXbmV3UG9zaXRpb25SZW1haW5NYXJnaW4FF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBRRuZXdQb3NpdGlvbkxhdGVzdENQRgkBCXVwZGF0ZUFtbQgFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgUZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcgUOdG90YWxMb25nQWZ0ZXIFD3RvdGFsU2hvcnRBZnRlcgUadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIFG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARBpbmNyZWFzZVBvc2l0aW9uBApfZGlyZWN0aW9uCV9sZXZlcmFnZRNfbWluQmFzZUFzc2V0QW1vdW50CF9yZWZMaW5rBARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEB190cmFkZXIJAQ9nZXRBY3R1YWxDYWxsZXIBBQFpBApfcmF3QW1vdW50CAkAkQMCCAUBaQhwYXltZW50cwAABmFtb3VudAQIX2Fzc2V0SWQICQCRAwIIBQFpCHBheW1lbnRzAAAHYXNzZXRJZAQLX2Fzc2V0SWRTdHIJANgEAQkBBXZhbHVlAQUIX2Fzc2V0SWQEDGlzUXVvdGVBc3NldAkAAAIFCF9hc3NldElkCQEKcXVvdGVBc3NldAAEEWlzQ29sbGF0ZXJhbEFzc2V0CQEQaXNXaGl0ZWxpc3RBc3NldAEFC19hc3NldElkU3RyAwMDAwMDAwMDAwkBAiE9AgUKX2RpcmVjdGlvbgUIRElSX0xPTkcJAQIhPQIFCl9kaXJlY3Rpb24FCURJUl9TSE9SVAcGCQBnAgAABQpfcmF3QW1vdW50BgkBASEBCQELaW5pdGlhbGl6ZWQABgMJAQEhAQUMaXNRdW90ZUFzc2V0CQEBIQEFEWlzQ29sbGF0ZXJhbEFzc2V0BwYJAQEhAQkBF2lzU2FtZUFzc2V0T3JOb1Bvc2l0aW9uAgUHX3RyYWRlcgULX2Fzc2V0SWRTdHIGCQEBIQEJARZyZXF1aXJlTW9yZU1hcmdpblJhdGlvAwkBBGRpdmQCBQxERUNJTUFMX1VOSVQFCV9sZXZlcmFnZQkBD2luaXRNYXJnaW5SYXRpbwAGBgkBBnBhdXNlZAAGCQEJY2xvc2VPbmx5AAYJAQ5pc01hcmtldENsb3NlZAAJAAIBAiNJbnZhbGlkIGluY3JlYXNlUG9zaXRpb24gcGFyYW1ldGVycwQNJHQwNTQyOTQ1NDM3OQkBGGdldEZvclRyYWRlcldpdGhBcnRpZmFjdAIFB190cmFkZXIJAQ1nZXRBcnRpZmFjdElkAQUBaQQLYWRqdXN0ZWRGZWUIBQ0kdDA1NDI5NDU0Mzc5Al8xBAxidXJuQXJ0aWZhY3QIBQ0kdDA1NDI5NDU0Mzc5Al8yBAxyYXdGZWVBbW91bnQJAQRtdWxkAgUKX3Jhd0Ftb3VudAULYWRqdXN0ZWRGZWUEB19hbW91bnQJAGUCBQpfcmF3QW1vdW50BQxyYXdGZWVBbW91bnQEE2Rpc3RyaWJ1dGVGZWVBbW91bnQDBRFpc0NvbGxhdGVyYWxBc3NldAQIZG9Cb3Jyb3cJAPwHBAkBEWNvbGxhdGVyYWxBZGRyZXNzAAIGYm9ycm93CQDMCAIFB190cmFkZXIFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUIX2Fzc2V0SWQFB19hbW91bnQFA25pbAMJAAACBQhkb0JvcnJvdwUIZG9Cb3Jyb3cEDWJhbGFuY2VCZWZvcmUJAPAHAgUEdGhpcwkBCnF1b3RlQXNzZXQAAwkAAAIFDWJhbGFuY2VCZWZvcmUFDWJhbGFuY2VCZWZvcmUEBmRvU3dhcAkA/AcECQELc3dhcEFkZHJlc3MAAgRzd2FwCQDMCAIJANgEAQkBCnF1b3RlQXNzZXQACQDMCAIAAAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQhfYXNzZXRJZAUMcmF3RmVlQW1vdW50BQNuaWwDCQAAAgUGZG9Td2FwBQZkb1N3YXAEDGJhbGFuY2VBZnRlcgkA8AcCBQR0aGlzCQEKcXVvdGVBc3NldAADCQAAAgUMYmFsYW5jZUFmdGVyBQxiYWxhbmNlQWZ0ZXIED2V4Y2hhbmdlZEFtb3VudAkAZQIFDGJhbGFuY2VBZnRlcgUNYmFsYW5jZUJlZm9yZQMJAAACBQ9leGNoYW5nZWRBbW91bnQFD2V4Y2hhbmdlZEFtb3VudAUPZXhjaGFuZ2VkQW1vdW50CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQxyYXdGZWVBbW91bnQDCQAAAgUTZGlzdHJpYnV0ZUZlZUFtb3VudAUTZGlzdHJpYnV0ZUZlZUFtb3VudAQOcmVmZXJyZXJGZWVBbnkJAPwHBAkBD3JlZmVycmFsQWRkcmVzcwACFWFjY2VwdFBheW1lbnRXaXRoTGluawkAzAgCBQdfdHJhZGVyCQDMCAIFCF9yZWZMaW5rBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUTZGlzdHJpYnV0ZUZlZUFtb3VudAUDbmlsAwkAAAIFDnJlZmVycmVyRmVlQW55BQ5yZWZlcnJlckZlZUFueQQLcmVmZXJyZXJGZWUEByRtYXRjaDAFDnJlZmVycmVyRmVlQW55AwkAAQIFByRtYXRjaDACA0ludAQBeAUHJG1hdGNoMAUBeAkAAgECE0ludmFsaWQgcmVmZXJyZXJGZWUECWZlZUFtb3VudAkAZQIFE2Rpc3RyaWJ1dGVGZWVBbW91bnQFC3JlZmVycmVyRmVlBA0kdDA1NTY5NTU1ODM1CQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBA9vbGRQb3NpdGlvblNpemUIBQ0kdDA1NTY5NTU1ODM1Al8xBBFvbGRQb3NpdGlvbk1hcmdpbggFDSR0MDU1Njk1NTU4MzUCXzIEF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNTU2OTU1NTgzNQJfMwQUb2xkUG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA1NTY5NTU1ODM1Al80BA1pc05ld1Bvc2l0aW9uCQAAAgUPb2xkUG9zaXRpb25TaXplAAAED2lzU2FtZURpcmVjdGlvbgMJAGYCBQ9vbGRQb3NpdGlvblNpemUAAAkAAAIFCl9kaXJlY3Rpb24FCERJUl9MT05HCQAAAgUKX2RpcmVjdGlvbgUJRElSX1NIT1JUBA5leHBhbmRFeGlzdGluZwMJAQEhAQUNaXNOZXdQb3NpdGlvbgUPaXNTYW1lRGlyZWN0aW9uBwQFaXNBZGQJAAACBQpfZGlyZWN0aW9uBQhESVJfTE9ORwQNJHQwNTYxMjQ1OTE2NQMDBQ1pc05ld1Bvc2l0aW9uBgUOZXhwYW5kRXhpc3RpbmcEDG9wZW5Ob3Rpb25hbAkBBG11bGQCBQdfYW1vdW50BQlfbGV2ZXJhZ2UEDSR0MDU2NTg2NTY3NTkJAQlzd2FwSW5wdXQCBQVpc0FkZAUMb3Blbk5vdGlvbmFsBBVhbW91bnRCYXNlQXNzZXRCb3VnaHQIBQ0kdDA1NjU4NjU2NzU5Al8xBBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNTY1ODY1Njc1OQJfMgQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNTY1ODY1Njc1OQJfMwQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDU2NTg2NTY3NTkCXzQDAwkBAiE9AgUTX21pbkJhc2VBc3NldEFtb3VudAAACQBmAgUTX21pbkJhc2VBc3NldEFtb3VudAkBA2FicwEFFWFtb3VudEJhc2VBc3NldEJvdWdodAcJAAIBCQCsAgIJAKwCAgkArAICAg1MaW1pdCBlcnJvcjogCQCkAwEJAQNhYnMBBRVhbW91bnRCYXNlQXNzZXRCb3VnaHQCAyA8IAkApAMBBRNfbWluQmFzZUFzc2V0QW1vdW50BA9uZXdQb3NpdGlvblNpemUJAGQCBQ9vbGRQb3NpdGlvblNpemUFFWFtb3VudEJhc2VBc3NldEJvdWdodAQadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIJAGQCCQEQb3BlbkludGVyZXN0TG9uZwADCQBmAgUPbmV3UG9zaXRpb25TaXplAAAFDG9wZW5Ob3Rpb25hbAAABBt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIJAGQCCQERb3BlbkludGVyZXN0U2hvcnQAAwkAZgIAAAUPbmV3UG9zaXRpb25TaXplBQxvcGVuTm90aW9uYWwAAAQZaW5jcmVhc2VNYXJnaW5SZXF1aXJlbWVudAkBBGRpdmQCBQxvcGVuTm90aW9uYWwFCV9sZXZlcmFnZQQNJHQwNTczNjc1NzYwNgkBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEBQ9vbGRQb3NpdGlvblNpemUFEW9sZFBvc2l0aW9uTWFyZ2luBRRvbGRQb3NpdGlvbkxzdFVwZENQRgUZaW5jcmVhc2VNYXJnaW5SZXF1aXJlbWVudAQMcmVtYWluTWFyZ2luCAUNJHQwNTczNjc1NzYwNgJfMQQCeDEIBQ0kdDA1NzM2NzU3NjA2Al8yBAJ4MggFDSR0MDU3MzY3NTc2MDYCXzMDCQEBIQEJARlyZXF1aXJlTm90T3ZlclNwcmVhZExpbWl0AgUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCQACAQIVT3ZlciBtYXggc3ByZWFkIGxpbWl0AwkBASEBCQEdcmVxdWlyZU5vdE92ZXJNYXhPcGVuTm90aW9uYWwCBRp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgUbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCQACAQIWT3ZlciBtYXggb3BlbiBub3Rpb25hbAkAngoMBQ9uZXdQb3NpdGlvblNpemUFDHJlbWFpbk1hcmdpbgkAZAIFF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsBQxvcGVuTm90aW9uYWwJAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUPbmV3UG9zaXRpb25TaXplBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIJAGQCCQEUb3BlbkludGVyZXN0Tm90aW9uYWwABQxvcGVuTm90aW9uYWwJAGQCCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAMJAGYCBQ9uZXdQb3NpdGlvblNpemUAAAkBA2FicwEFFWFtb3VudEJhc2VBc3NldEJvdWdodAAACQBkAgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUAAwkAZgIAAAUPbmV3UG9zaXRpb25TaXplCQEDYWJzAQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0AAAFGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyBRt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIEDG9wZW5Ob3Rpb25hbAkBBG11bGQCBQdfYW1vdW50BQlfbGV2ZXJhZ2UEDSR0MDU4ODY1NTg5ODEJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIJAKUIAQgFAWkGY2FsbGVyBQ9QTkxfT1BUSU9OX1NQT1QEE29sZFBvc2l0aW9uTm90aW9uYWwIBQ0kdDA1ODg2NTU4OTgxAl8xBA11bnJlYWxpemVkUG5sCAUNJHQwNTg4NjU1ODk4MQJfMgMJAGYCBRNvbGRQb3NpdGlvbk5vdGlvbmFsBQxvcGVuTm90aW9uYWwJAAIBAi5Vc2UgZGVjcmVhc2VQb3NpdGlvbiB0byBkZWNyZWFzZSBwb3NpdGlvbiBzaXplCQACAQIUQ2xvc2UgcG9zaXRpb24gZmlyc3QED25ld1Bvc2l0aW9uU2l6ZQgFDSR0MDU2MTI0NTkxNjUCXzEEF25ld1Bvc2l0aW9uUmVtYWluTWFyZ2luCAUNJHQwNTYxMjQ1OTE2NQJfMgQXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA1NjEyNDU5MTY1Al8zBBRuZXdQb3NpdGlvbkxhdGVzdENQRggFDSR0MDU2MTI0NTkxNjUCXzQEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDU2MTI0NTkxNjUCXzUEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA1NjEyNDU5MTY1Al82BBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNTYxMjQ1OTE2NQJfNwQZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcggFDSR0MDU2MTI0NTkxNjUCXzgEDnRvdGFsTG9uZ0FmdGVyCAUNJHQwNTYxMjQ1OTE2NQJfOQQPdG90YWxTaG9ydEFmdGVyCAUNJHQwNTYxMjQ1OTE2NQNfMTAEGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNTYxMjQ1OTE2NQNfMTEEG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDU2MTI0NTkxNjUDXzEyBA0kdDA1OTE3MTU5MjI4CQENZGlzdHJpYnV0ZUZlZQEFCWZlZUFtb3VudAQMZmVlVG9TdGFrZXJzCAUNJHQwNTkxNzE1OTIyOAJfMQQKZmVlVG9WYXVsdAgFDSR0MDU5MTcxNTkyMjgCXzIEBXN0YWtlAwUMaXNRdW90ZUFzc2V0BAVzdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIJYWRkTG9ja2VkCQDMCAIHBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUHX2Ftb3VudAUDbmlsAwkAAAIFBXN0YWtlBQVzdGFrZQUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUFc3Rha2UFBXN0YWtlBBBkZXBvc2l0SW5zdXJhbmNlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAgdhZGRGcmVlBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUKZmVlVG9WYXVsdAUDbmlsAwkAAAIFEGRlcG9zaXRJbnN1cmFuY2UFEGRlcG9zaXRJbnN1cmFuY2UECW5vdGlmeUZlZQkA/AcECQEMbWluZXJBZGRyZXNzAAIKbm90aWZ5RmVlcwkAzAgCBQdfdHJhZGVyCQDMCAIFCWZlZUFtb3VudAUDbmlsBQNuaWwDCQAAAgUJbm90aWZ5RmVlBQlub3RpZnlGZWUEDm5vdGlmeU5vdGlvbmFsCQD8BwQJAQxtaW5lckFkZHJlc3MAAg5ub3RpZnlOb3Rpb25hbAkAzAgCBQdfdHJhZGVyCQDMCAIFF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBQNuaWwFA25pbAMJAAACBQ5ub3RpZnlOb3Rpb25hbAUObm90aWZ5Tm90aW9uYWwJAM4IAgkAzggCCQDOCAIJAM4IAgkAzggCCQDOCAIJAQ51cGRhdGVQb3NpdGlvbgUFB190cmFkZXIFD25ld1Bvc2l0aW9uU2l6ZQUXbmV3UG9zaXRpb25SZW1haW5NYXJnaW4FF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBRRuZXdQb3NpdGlvbkxhdGVzdENQRgkBH2luY3JlbWVudFBvc2l0aW9uU2VxdWVuY2VOdW1iZXICBQ1pc05ld1Bvc2l0aW9uBQdfdHJhZGVyCQETdXBkYXRlUG9zaXRpb25Bc3NldAIFB190cmFkZXIFC19hc3NldElkU3RyCQEJdXBkYXRlQW1tCAUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyBRp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgUbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCQELdHJhbnNmZXJGZWUBBQxmZWVUb1N0YWtlcnMJAQ11cGRhdGVCYWxhbmNlAQkAZAIJAQhjYmFsYW5jZQAFB19hbW91bnQJAQ5kb0J1cm5BcnRpZmFjdAIFDGJ1cm5BcnRpZmFjdAUBaQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQlhZGRNYXJnaW4ABARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEB190cmFkZXIJAKUIAQgFAWkGY2FsbGVyBApfcmF3QW1vdW50CAkAkQMCCAUBaQhwYXltZW50cwAABmFtb3VudAQIX2Fzc2V0SWQICQCRAwIIBQFpCHBheW1lbnRzAAAHYXNzZXRJZAQLX2Fzc2V0SWRTdHIJANgEAQkBBXZhbHVlAQUIX2Fzc2V0SWQEDGlzUXVvdGVBc3NldAkAAAIFCF9hc3NldElkCQEKcXVvdGVBc3NldAAEEWlzQ29sbGF0ZXJhbEFzc2V0CQEQaXNXaGl0ZWxpc3RBc3NldAEFC19hc3NldElkU3RyAwMDAwMDAwMJAQEhAQUMaXNRdW90ZUFzc2V0CQEBIQEFEWlzQ29sbGF0ZXJhbEFzc2V0BwYJAQEhAQkBE3JlcXVpcmVPcGVuUG9zaXRpb24BCQClCAEIBQFpBmNhbGxlcgYJAQEhAQkBC2lzU2FtZUFzc2V0AgUHX3RyYWRlcgULX2Fzc2V0SWRTdHIGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAYJAQljbG9zZU9ubHkABgkBDmlzTWFya2V0Q2xvc2VkAAkAAgECHEludmFsaWQgYWRkTWFyZ2luIHBhcmFtZXRlcnMEDSR0MDYxMjAwNjEyODUJARhnZXRGb3JUcmFkZXJXaXRoQXJ0aWZhY3QCBQdfdHJhZGVyCQENZ2V0QXJ0aWZhY3RJZAEFAWkEC2FkanVzdGVkRmVlCAUNJHQwNjEyMDA2MTI4NQJfMQQMYnVybkFydGlmYWN0CAUNJHQwNjEyMDA2MTI4NQJfMgQMcmF3RmVlQW1vdW50CQEEbXVsZAIFCl9yYXdBbW91bnQFC2FkanVzdGVkRmVlBAdfYW1vdW50CQBlAgUKX3Jhd0Ftb3VudAUMcmF3RmVlQW1vdW50BBNkaXN0cmlidXRlRmVlQW1vdW50AwURaXNDb2xsYXRlcmFsQXNzZXQECGRvQm9ycm93CQD8BwQJARFjb2xsYXRlcmFsQWRkcmVzcwACBmJvcnJvdwkAzAgCBQdfdHJhZGVyBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFCF9hc3NldElkBQdfYW1vdW50BQNuaWwDCQAAAgUIZG9Cb3Jyb3cFCGRvQm9ycm93BA1iYWxhbmNlQmVmb3JlCQDwBwIFBHRoaXMJAQpxdW90ZUFzc2V0AAMJAAACBQ1iYWxhbmNlQmVmb3JlBQ1iYWxhbmNlQmVmb3JlBAZkb1N3YXAJAPwHBAkBC3N3YXBBZGRyZXNzAAIEc3dhcAkAzAgCCQDYBAEJAQpxdW90ZUFzc2V0AAkAzAgCAAAFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUIX2Fzc2V0SWQFDHJhd0ZlZUFtb3VudAUDbmlsAwkAAAIFBmRvU3dhcAUGZG9Td2FwBAxiYWxhbmNlQWZ0ZXIJAPAHAgUEdGhpcwkBCnF1b3RlQXNzZXQAAwkAAAIFDGJhbGFuY2VBZnRlcgUMYmFsYW5jZUFmdGVyBA9leGNoYW5nZWRBbW91bnQJAGUCBQxiYWxhbmNlQWZ0ZXIFDWJhbGFuY2VCZWZvcmUDCQAAAgUPZXhjaGFuZ2VkQW1vdW50BQ9leGNoYW5nZWRBbW91bnQFD2V4Y2hhbmdlZEFtb3VudAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUMcmF3RmVlQW1vdW50AwkAAAIFE2Rpc3RyaWJ1dGVGZWVBbW91bnQFE2Rpc3RyaWJ1dGVGZWVBbW91bnQEDnJlZmVycmVyRmVlQW55CQD8BwQJAQ9yZWZlcnJhbEFkZHJlc3MAAg1hY2NlcHRQYXltZW50CQDMCAIFB190cmFkZXIFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABRNkaXN0cmlidXRlRmVlQW1vdW50BQNuaWwDCQAAAgUOcmVmZXJyZXJGZWVBbnkFDnJlZmVycmVyRmVlQW55BAtyZWZlcnJlckZlZQQHJG1hdGNoMAUOcmVmZXJyZXJGZWVBbnkDCQABAgUHJG1hdGNoMAIDSW50BAF4BQckbWF0Y2gwBQF4CQACAQITSW52YWxpZCByZWZlcnJlckZlZQQJZmVlQW1vdW50CQBlAgUTZGlzdHJpYnV0ZUZlZUFtb3VudAULcmVmZXJyZXJGZWUEDSR0MDYyNTg0NjI3MjQJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIED29sZFBvc2l0aW9uU2l6ZQgFDSR0MDYyNTg0NjI3MjQCXzEEEW9sZFBvc2l0aW9uTWFyZ2luCAUNJHQwNjI1ODQ2MjcyNAJfMgQXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA2MjU4NDYyNzI0Al8zBBRvbGRQb3NpdGlvbkxzdFVwZENQRggFDSR0MDYyNTg0NjI3MjQCXzQEDSR0MDYyNzMwNjI3ODcJAQ1kaXN0cmlidXRlRmVlAQUJZmVlQW1vdW50BAxmZWVUb1N0YWtlcnMIBQ0kdDA2MjczMDYyNzg3Al8xBApmZWVUb1ZhdWx0CAUNJHQwNjI3MzA2Mjc4NwJfMgQFc3Rha2UDBQxpc1F1b3RlQXNzZXQEBXN0YWtlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAglhZGRMb2NrZWQJAMwIAgcFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABQdfYW1vdW50BQNuaWwDCQAAAgUFc3Rha2UFBXN0YWtlBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBQVzdGFrZQUFc3Rha2UEEGRlcG9zaXRJbnN1cmFuY2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACB2FkZEZyZWUFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABQpmZWVUb1ZhdWx0BQNuaWwDCQAAAgUQZGVwb3NpdEluc3VyYW5jZQUQZGVwb3NpdEluc3VyYW5jZQQJbm90aWZ5RmVlCQD8BwQJAQxtaW5lckFkZHJlc3MAAgpub3RpZnlGZWVzCQDMCAIFB190cmFkZXIJAMwIAgUJZmVlQW1vdW50BQNuaWwFA25pbAMJAAACBQlub3RpZnlGZWUFCW5vdGlmeUZlZQkAzggCCQDOCAIJAM4IAgkBDnVwZGF0ZVBvc2l0aW9uBQUHX3RyYWRlcgUPb2xkUG9zaXRpb25TaXplCQBkAgURb2xkUG9zaXRpb25NYXJnaW4FB19hbW91bnQFF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsBRRvbGRQb3NpdGlvbkxzdFVwZENQRgkBC3RyYW5zZmVyRmVlAQUMZmVlVG9TdGFrZXJzCQENdXBkYXRlQmFsYW5jZQEJAGQCCQEIY2JhbGFuY2UABQdfYW1vdW50CQEOZG9CdXJuQXJ0aWZhY3QCBQxidXJuQXJ0aWZhY3QFAWkJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEMcmVtb3ZlTWFyZ2luAQdfYW1vdW50BARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEB190cmFkZXIJAKUIAQgFAWkGY2FsbGVyAwMDAwMJAGcCAAAFB19hbW91bnQGCQEBIQEJARNyZXF1aXJlT3BlblBvc2l0aW9uAQUHX3RyYWRlcgYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQZwYXVzZWQABgkBDmlzTWFya2V0Q2xvc2VkAAkAAgECH0ludmFsaWQgcmVtb3ZlTWFyZ2luIHBhcmFtZXRlcnMEDSR0MDYzOTIzNjQwNjMJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIED29sZFBvc2l0aW9uU2l6ZQgFDSR0MDYzOTIzNjQwNjMCXzEEEW9sZFBvc2l0aW9uTWFyZ2luCAUNJHQwNjM5MjM2NDA2MwJfMgQXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA2MzkyMzY0MDYzAl8zBBRvbGRQb3NpdGlvbkxzdFVwZENQRggFDSR0MDYzOTIzNjQwNjMCXzQEC21hcmdpbkRlbHRhCQEBLQEFB19hbW91bnQEDSR0MDY0MTAwNjQyNzkJASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BAUPb2xkUG9zaXRpb25TaXplBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25Mc3RVcGRDUEYFC21hcmdpbkRlbHRhBAxyZW1haW5NYXJnaW4IBQ0kdDA2NDEwMDY0Mjc5Al8xBAdiYWREZWJ0CAUNJHQwNjQxMDA2NDI3OQJfMgMJAQIhPQIFB2JhZERlYnQAAAkAAgECHUludmFsaWQgcmVtb3ZlZCBtYXJnaW4gYW1vdW50BAttYXJnaW5SYXRpbwkBD2NhbGNNYXJnaW5SYXRpbwMFDHJlbWFpbk1hcmdpbgUHYmFkRGVidAUXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwDCQEBIQEJARZyZXF1aXJlTW9yZU1hcmdpblJhdGlvAwULbWFyZ2luUmF0aW8JAQ9pbml0TWFyZ2luUmF0aW8ABgkAAgEJAKwCAgkArAICCQCsAgICGVRvbyBtdWNoIG1hcmdpbiByZW1vdmVkOiAJAKQDAQULbWFyZ2luUmF0aW8CAyA8IAkApAMBCQEPaW5pdE1hcmdpblJhdGlvAAQNcXVvdGVBc3NldFN0cgkA2AQBCQEKcXVvdGVBc3NldAAEDSR0MDY0NzIzNjQ3NzcJARNnZXRCb3Jyb3dlZEJ5VHJhZGVyAQUHX3RyYWRlcgQIYm9ycm93ZWQIBQ0kdDA2NDcyMzY0Nzc3Al8xBAdhc3NldElkCAUNJHQwNjQ3MjM2NDc3NwJfMgQHdG9SZXBheQMJAGYCBQdfYW1vdW50BQhib3Jyb3dlZAUIYm9ycm93ZWQFB19hbW91bnQECnRvV2l0aGRyYXcDCQBmAgUIYm9ycm93ZWQFB19hbW91bnQAAAkAZQIFB19hbW91bnQFCGJvcnJvd2VkBAtmaW5hbEJvcnJvdwkAZQIFCGJvcnJvd2VkBQd0b1JlcGF5BBVzd2l0Y2hQb3NpdGlvblRvUXVvdGUDCQBmAgULZmluYWxCb3Jyb3cAAAUDbmlsCQETdXBkYXRlUG9zaXRpb25Bc3NldAIFB190cmFkZXIFDXF1b3RlQXNzZXRTdHIEDWRvU2FuaXR5Q2hlY2sDCQECIT0CCQBkAgUHdG9SZXBheQUKdG9XaXRoZHJhdwUHX2Ftb3VudAkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAgh0b1JlcGF5PQkApAMBBQd0b1JlcGF5Ag4gKyB0b1dpdGhkcmF3PQkApAMBBQp0b1dpdGhkcmF3AgQgIT0gCQCkAwEFB19hbW91bnQFA25pbAMJAAACBQ1kb1Nhbml0eUNoZWNrBQ1kb1Nhbml0eUNoZWNrBAlkb1Vuc3Rha2UDCQBmAgUKdG9XaXRoZHJhdwAABAlkb1Vuc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACDndpdGhkcmF3TG9ja2VkCQDMCAIFCnRvV2l0aGRyYXcFA25pbAUDbmlsAwkAAAIFCWRvVW5zdGFrZQUJZG9VbnN0YWtlBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBQlkb1Vuc3Rha2UFCWRvVW5zdGFrZQQWcmV0dXJuQ29sbGF0ZXJhbEFjdGlvbgMJAGYCBQd0b1JlcGF5AAAEB2RvUmVwYXkJAPwHBAkBEWNvbGxhdGVyYWxBZGRyZXNzAAIFcmVwYXkJAMwIAgUHX3RyYWRlcgkAzAgCBQd0b1JlcGF5CQDMCAIFB2Fzc2V0SWQFA25pbAUDbmlsAwkAAAIFB2RvUmVwYXkFB2RvUmVwYXkJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyBQd0b1JlcGF5CQDZBAEFB2Fzc2V0SWQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFFnJldHVybkNvbGxhdGVyYWxBY3Rpb24FFnJldHVybkNvbGxhdGVyYWxBY3Rpb24JAM4IAgkAzggCCQDOCAIJAM4IAgkBDnVwZGF0ZVBvc2l0aW9uBQUHX3RyYWRlcgUPb2xkUG9zaXRpb25TaXplBQxyZW1haW5NYXJnaW4FF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCQEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEFD29sZFBvc2l0aW9uU2l6ZQMJAGYCBQp0b1dpdGhkcmF3AAAJAQh3aXRoZHJhdwIIBQFpBmNhbGxlcgUKdG9XaXRoZHJhdwUDbmlsCQENdXBkYXRlQmFsYW5jZQEJAGUCCQEIY2JhbGFuY2UABQdfYW1vdW50BRVzd2l0Y2hQb3NpdGlvblRvUXVvdGUFFnJldHVybkNvbGxhdGVyYWxBY3Rpb24JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQENY2xvc2VQb3NpdGlvbgIFX3NpemUUX21pblF1b3RlQXNzZXRBbW91bnQEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQHX3RyYWRlcgkBD2dldEFjdHVhbENhbGxlcgEFAWkEDl90cmFkZXJBZGRyZXNzCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQUHX3RyYWRlcgIOSW52YWxpZCBjYWxsZXIDAwMDAwMJAQEhAQkBE3JlcXVpcmVPcGVuUG9zaXRpb24BBQdfdHJhZGVyBgkBASEBCQELaW5pdGlhbGl6ZWQABgkBBnBhdXNlZAAGCQBnAgAABQVfc2l6ZQYJAGYCAAAFFF9taW5RdW90ZUFzc2V0QW1vdW50BgkBDmlzTWFya2V0Q2xvc2VkAAkAAgECIEludmFsaWQgY2xvc2VQb3NpdGlvbiBwYXJhbWV0ZXJzBA0kdDA2Njk2MTY3MTAxCQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBA9vbGRQb3NpdGlvblNpemUIBQ0kdDA2Njk2MTY3MTAxAl8xBBFvbGRQb3NpdGlvbk1hcmdpbggFDSR0MDY2OTYxNjcxMDECXzIEF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNjY5NjE2NzEwMQJfMwQUb2xkUG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA2Njk2MTY3MTAxAl80BA0kdDA2NzEwNzcyMjM3AwkAZgIJAQNhYnMBBQ9vbGRQb3NpdGlvblNpemUFBV9zaXplBApfZGlyZWN0aW9uAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAABQlESVJfU0hPUlQFCERJUl9MT05HBAVpc0FkZAkAAAIFCl9kaXJlY3Rpb24FCERJUl9MT05HBA0kdDA2NzY5ODY3OTIwCQEKc3dhcE91dHB1dAMJAGYCBQ9vbGRQb3NpdGlvblNpemUAAAUFX3NpemUGBBlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CAUNJHQwNjc2OTg2NzkyMAJfMQQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDY3Njk4Njc5MjACXzIEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDY3Njk4Njc5MjACXzMEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA2NzY5ODY3OTIwAl80BBVleGNoYW5nZWRQb3NpdGlvblNpemUDCQBmAgUPb2xkUG9zaXRpb25TaXplAAAJAQEtAQUFX3NpemUFBV9zaXplBA0kdDA2ODAxMTY4MTY1CQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QEE29sZFBvc2l0aW9uTm90aW9uYWwIBQ0kdDA2ODAxMTY4MTY1Al8xBA11bnJlYWxpemVkUG5sCAUNJHQwNjgwMTE2ODE2NQJfMgQCbXIJARZnZXRNYXJnaW5SYXRpb0J5T3B0aW9uAgUHX3RyYWRlcgUPUE5MX09QVElPTl9TUE9UBA1yZWFsaXplZFJhdGlvCQEEZGl2ZAIJAQNhYnMBBRVleGNoYW5nZWRQb3NpdGlvblNpemUJAQNhYnMBBQ9vbGRQb3NpdGlvblNpemUEC3JlYWxpemVkUG5sCQEEbXVsZAIFDXVucmVhbGl6ZWRQbmwFDXJlYWxpemVkUmF0aW8EEnJlbWFpbk1hcmdpbkJlZm9yZQgJASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BAUPb2xkUG9zaXRpb25TaXplBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25Mc3RVcGRDUEYFDXVucmVhbGl6ZWRQbmwCXzEEDSR0MDY4NjY2Njg4OTQJASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BAUPb2xkUG9zaXRpb25TaXplBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25Mc3RVcGRDUEYFC3JlYWxpemVkUG5sBAJ4MQgFDSR0MDY4NjY2Njg4OTQCXzEED3Bvc2l0aW9uQmFkRGVidAgFDSR0MDY4NjY2Njg4OTQCXzIEDmZ1bmRpbmdQYXltZW50CAUNJHQwNjg2NjY2ODg5NAJfMwQSdW5yZWFsaXplZFBubEFmdGVyCQBlAgUNdW5yZWFsaXplZFBubAULcmVhbGl6ZWRQbmwEEnJlbWFpbk9wZW5Ob3Rpb25hbAMJAGYCBQ9vbGRQb3NpdGlvblNpemUAAAkAZQIJAGUCBRNvbGRQb3NpdGlvbk5vdGlvbmFsBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BRJ1bnJlYWxpemVkUG5sQWZ0ZXIJAGUCCQBkAgUSdW5yZWFsaXplZFBubEFmdGVyBRNvbGRQb3NpdGlvbk5vdGlvbmFsBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BBduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAkBA2FicwEFEnJlbWFpbk9wZW5Ob3Rpb25hbAQRbmV3UG9zaXRpb25NYXJnaW4DCQBmAgUPb2xkUG9zaXRpb25TaXplAAAJAGUCCQEEbXVsZAIJAGQCBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUSdW5yZWFsaXplZFBubEFmdGVyBQJtcgUSdW5yZWFsaXplZFBubEFmdGVyCQBlAgkBBG11bGQCCQBlAgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFEnVucmVhbGl6ZWRQbmxBZnRlcgUCbXIFEnVucmVhbGl6ZWRQbmxBZnRlcgQRb3Blbk5vdGlvbmFsRGVsdGEJAGUCBRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwED25ld1Bvc2l0aW9uU2l6ZQkAZAIFD29sZFBvc2l0aW9uU2l6ZQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplBBRuZXdQb3NpdGlvbkxzdFVwZENQRgkBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BBQ9uZXdQb3NpdGlvblNpemUEGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIJAGUCCQEUb3BlbkludGVyZXN0Tm90aW9uYWwABRFvcGVuTm90aW9uYWxEZWx0YQMDCQECIT0CBRRfbWluUXVvdGVBc3NldEFtb3VudAAACQBmAgUUX21pblF1b3RlQXNzZXRBbW91bnQFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQHCQACAQkArAICCQCsAgIJAKwCAgINTGltaXQgZXJyb3I6IAkApAMBBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50AgMgPCAJAKQDAQUUX21pblF1b3RlQXNzZXRBbW91bnQJAKEKDwUPbmV3UG9zaXRpb25TaXplBRFuZXdQb3NpdGlvbk1hcmdpbgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFFG5ld1Bvc2l0aW9uTHN0VXBkQ1BGBQ9wb3NpdGlvbkJhZERlYnQFC3JlYWxpemVkUG5sCQBlAgUScmVtYWluTWFyZ2luQmVmb3JlCQBkAgURbmV3UG9zaXRpb25NYXJnaW4FEnVucmVhbGl6ZWRQbmxBZnRlcgUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCQBlAgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQADCQBmAgUPbmV3UG9zaXRpb25TaXplAAAJAQNhYnMBBRVleGNoYW5nZWRQb3NpdGlvblNpemUAAAkAZQIJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAMJAGYCAAAFD25ld1Bvc2l0aW9uU2l6ZQkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQAACQBlAgkBEG9wZW5JbnRlcmVzdExvbmcAAwkAZgIFD25ld1Bvc2l0aW9uU2l6ZQAABRFvcGVuTm90aW9uYWxEZWx0YQAACQBlAgkBEW9wZW5JbnRlcmVzdFNob3J0AAMJAGYCAAAFD25ld1Bvc2l0aW9uU2l6ZQURb3Blbk5vdGlvbmFsRGVsdGEAAAMJAGYCBQVfc2l6ZQkBA2FicwEFD29sZFBvc2l0aW9uU2l6ZQkAAgECIEludmFsaWQgY2xvc2VQb3NpdGlvbiBwYXJhbWV0ZXJzBA0kdDA3MTE3ODcxNTk3CQEVaW50ZXJuYWxDbG9zZVBvc2l0aW9uAgUHX3RyYWRlcgYEGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQIBQ0kdDA3MTE3ODcxNTk3Al8xBA9wb3NpdGlvbkJhZERlYnQIBQ0kdDA3MTE3ODcxNTk3Al8yBAtyZWFsaXplZFBubAgFDSR0MDcxMTc4NzE1OTcCXzMEDW1hcmdpblRvVmF1bHQIBQ0kdDA3MTE3ODcxNTk3Al80BBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNzExNzg3MTU5NwJfNQQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNzExNzg3MTU5NwJfNgQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDcxMTc4NzE1OTcCXzcEGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIIBQ0kdDA3MTE3ODcxNTk3Al84BAJ4MggFDSR0MDcxMTc4NzE1OTcCXzkEDnRvdGFsTG9uZ0FmdGVyCAUNJHQwNzExNzg3MTU5NwNfMTAED3RvdGFsU2hvcnRBZnRlcggFDSR0MDcxMTc4NzE1OTcDXzExBBp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDcxMTc4NzE1OTcDXzEyBBt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA3MTE3ODcxNTk3A18xMwMDCQECIT0CBRRfbWluUXVvdGVBc3NldEFtb3VudAAACQBmAgUUX21pblF1b3RlQXNzZXRBbW91bnQFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQHCQACAQkArAICCQCsAgIJAKwCAgINTGltaXQgZXJyb3I6IAkApAMBBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50AgMgPCAJAKQDAQUUX21pblF1b3RlQXNzZXRBbW91bnQJAKEKDwAAAAAAAAAABQ9wb3NpdGlvbkJhZERlYnQFC3JlYWxpemVkUG5sBQ1tYXJnaW5Ub1ZhdWx0BRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIFDnRvdGFsTG9uZ0FmdGVyBQ90b3RhbFNob3J0QWZ0ZXIFGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyBRt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIED25ld1Bvc2l0aW9uU2l6ZQgFDSR0MDY3MTA3NzIyMzcCXzEEEW5ld1Bvc2l0aW9uTWFyZ2luCAUNJHQwNjcxMDc3MjIzNwJfMgQXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA2NzEwNzcyMjM3Al8zBBRuZXdQb3NpdGlvbkxzdFVwZENQRggFDSR0MDY3MTA3NzIyMzcCXzQED3Bvc2l0aW9uQmFkRGVidAgFDSR0MDY3MTA3NzIyMzcCXzUEC3JlYWxpemVkUG5sCAUNJHQwNjcxMDc3MjIzNwJfNgQNbWFyZ2luVG9WYXVsdAgFDSR0MDY3MTA3NzIyMzcCXzcEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA2NzEwNzcyMjM3Al84BBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA2NzEwNzcyMjM3Al85BBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNjcxMDc3MjIzNwNfMTAEGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIIBQ0kdDA2NzEwNzcyMjM3A18xMQQOdG90YWxMb25nQWZ0ZXIIBQ0kdDA2NzEwNzcyMjM3A18xMgQPdG90YWxTaG9ydEFmdGVyCAUNJHQwNjcxMDc3MjIzNwNfMTMEGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNjcxMDc3MjIzNwNfMTQEG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDY3MTA3NzIyMzcDXzE1AwkAZgIFD3Bvc2l0aW9uQmFkRGVidAAACQACAQImVW5hYmxlIHRvIGNsb3NlIHBvc2l0aW9uIHdpdGggYmFkIGRlYnQEDndpdGhkcmF3QW1vdW50CQEDYWJzAQUNbWFyZ2luVG9WYXVsdAQKYW1tQmFsYW5jZQkAZQIJAQhjYmFsYW5jZQAFDndpdGhkcmF3QW1vdW50BA0kdDA3MjQ0NjcyNjUzAwkAZgIAAAUKYW1tQmFsYW5jZQkAlAoCAAAJAQNhYnMBBQphbW1CYWxhbmNlCQCUCgIFCmFtbUJhbGFuY2UAAAQNYW1tTmV3QmFsYW5jZQgFDSR0MDcyNDQ2NzI2NTMCXzEEA3gxMQgFDSR0MDcyNDQ2NzI2NTMCXzIEDSR0MDcyNjYwNzI3MTQJARNnZXRCb3Jyb3dlZEJ5VHJhZGVyAQUHX3RyYWRlcgQIYm9ycm93ZWQIBQ0kdDA3MjY2MDcyNzE0Al8xBAdhc3NldElkCAUNJHQwNzI2NjA3MjcxNAJfMgQNJHQwNzI3Mjk3MzU4OAMJAGYCBQhib3Jyb3dlZAAAAwkAZwIFDndpdGhkcmF3QW1vdW50BQhib3Jyb3dlZAQHZG9SZXBheQkA/AcECQERY29sbGF0ZXJhbEFkZHJlc3MAAgVyZXBheQkAzAgCBQdfdHJhZGVyCQDMCAIFCGJvcnJvd2VkCQDMCAIFB2Fzc2V0SWQFA25pbAUDbmlsAwkAAAIFB2RvUmVwYXkFB2RvUmVwYXkJAJQKAgkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQ5fdHJhZGVyQWRkcmVzcwUIYm9ycm93ZWQJANkEAQUHYXNzZXRJZAUDbmlsCQBlAgUOd2l0aGRyYXdBbW91bnQFCGJvcnJvd2VkCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBA9yZWFsaXplQW5kQ2xvc2UJAPwHBAkBEWNvbGxhdGVyYWxBZGRyZXNzAAIYcmVhbGl6ZVBhcnRpYWxseUFuZENsb3NlCQDMCAIFB190cmFkZXIJAMwIAgUOd2l0aGRyYXdBbW91bnQJAMwIAgUHYXNzZXRJZAUDbmlsBQNuaWwDCQAAAgUPcmVhbGl6ZUFuZENsb3NlBQ9yZWFsaXplQW5kQ2xvc2UJAJQKAgkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQ5fdHJhZGVyQWRkcmVzcwUOd2l0aGRyYXdBbW91bnQJANkEAQUHYXNzZXRJZAUDbmlsAAAJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAJQKAgUDbmlsBQ53aXRoZHJhd0Ftb3VudAMJAAACBQ0kdDA3MjcyOTczNTg4BQ0kdDA3MjcyOTczNTg4BBNxdW90ZVdpdGhkcmF3QW1vdW50CAUNJHQwNzI3Mjk3MzU4OAJfMgQUc2VuZENvbGxhdGVyYWxBY3Rpb24IBQ0kdDA3MjcyOTczNTg4Al8xBAd1bnN0YWtlAwkAZgIFE3F1b3RlV2l0aGRyYXdBbW91bnQAAAQHdW5zdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIOd2l0aGRyYXdMb2NrZWQJAMwIAgUTcXVvdGVXaXRoZHJhd0Ftb3VudAUDbmlsBQNuaWwDCQAAAgUHdW5zdGFrZQUHdW5zdGFrZQUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUHdW5zdGFrZQUHdW5zdGFrZQQObm90aWZ5Tm90aW9uYWwJAPwHBAkBDG1pbmVyQWRkcmVzcwACDm5vdGlmeU5vdGlvbmFsCQDMCAIFB190cmFkZXIJAMwIAgAABQNuaWwFA25pbAMJAAACBQ5ub3RpZnlOb3Rpb25hbAUObm90aWZ5Tm90aW9uYWwJAM4IAgkAzggCCQDOCAIJAM4IAgMJAAACBQ9uZXdQb3NpdGlvblNpemUAAAkBDmRlbGV0ZVBvc2l0aW9uAQUHX3RyYWRlcgkBDnVwZGF0ZVBvc2l0aW9uBQUHX3RyYWRlcgUPbmV3UG9zaXRpb25TaXplBRFuZXdQb3NpdGlvbk1hcmdpbgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFFG5ld1Bvc2l0aW9uTHN0VXBkQ1BGCQEJdXBkYXRlQW1tCAUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyBRp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgUbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyAwkAZgIFE3F1b3RlV2l0aGRyYXdBbW91bnQAAAkBCHdpdGhkcmF3AgUOX3RyYWRlckFkZHJlc3MFE3F1b3RlV2l0aGRyYXdBbW91bnQFA25pbAkBDXVwZGF0ZUJhbGFuY2UBBQ1hbW1OZXdCYWxhbmNlBRRzZW5kQ29sbGF0ZXJhbEFjdGlvbgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQlsaXF1aWRhdGUBB190cmFkZXIEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQPc3BvdE1hcmdpblJhdGlvCQEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAQLbWFyZ2luUmF0aW8DCQEWaXNPdmVyRmx1Y3R1YXRpb25MaW1pdAAEEW9yYWNsZU1hcmdpblJhdGlvCQEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgIFB190cmFkZXIFEVBOTF9PUFRJT05fT1JBQ0xFCQEEdm1heAIFD3Nwb3RNYXJnaW5SYXRpbwURb3JhY2xlTWFyZ2luUmF0aW8FD3Nwb3RNYXJnaW5SYXRpbwMDAwMDCQEBIQEJARZyZXF1aXJlTW9yZU1hcmdpblJhdGlvAwULbWFyZ2luUmF0aW8JARZtYWludGVuYW5jZU1hcmdpblJhdGlvAAcGCQEBIQEJARNyZXF1aXJlT3BlblBvc2l0aW9uAQUHX3RyYWRlcgYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQZwYXVzZWQABgkBDmlzTWFya2V0Q2xvc2VkAAkAAgECE1VuYWJsZSB0byBsaXF1aWRhdGUDAwMJAGYCBQ9zcG90TWFyZ2luUmF0aW8JARNsaXF1aWRhdGlvbkZlZVJhdGlvAAkAZgIJARdwYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwAAAAcJAGYCBQxERUNJTUFMX1VOSVQJARdwYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwAHBA0kdDA3NTkwOTc2MDU5CQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBA9vbGRQb3NpdGlvblNpemUIBQ0kdDA3NTkwOTc2MDU5Al8xBBFvbGRQb3NpdGlvbk1hcmdpbggFDSR0MDc1OTA5NzYwNTkCXzIEF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNzU5MDk3NjA1OQJfMwQUb2xkUG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA3NTkwOTc2MDU5Al80BApfZGlyZWN0aW9uAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAABQlESVJfU0hPUlQFCERJUl9MT05HBAVpc0FkZAkAAAIFCl9kaXJlY3Rpb24FCERJUl9MT05HBBlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CQEbZ2V0UGFydGlhbExpcXVpZGF0aW9uQW1vdW50AgUHX3RyYWRlcgUPb2xkUG9zaXRpb25TaXplBA0kdDA3NjI4NDc2Mzg4CQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QEE29sZFBvc2l0aW9uTm90aW9uYWwIBQ0kdDA3NjI4NDc2Mzg4Al8xBA11bnJlYWxpemVkUG5sCAUNJHQwNzYyODQ3NjM4OAJfMgQNJHQwNzYzOTY3NjU4MwkBCXN3YXBJbnB1dAIFBWlzQWRkBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BBVleGNoYW5nZWRQb3NpdGlvblNpemUIBQ0kdDA3NjM5Njc2NTgzAl8xBBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNzYzOTY3NjU4MwJfMgQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNzYzOTY3NjU4MwJfMwQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDc2Mzk2NzY1ODMCXzQEEGxpcXVpZGF0aW9uUmF0aW8JAQRkaXZkAgkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQkBA2FicwEFD29sZFBvc2l0aW9uU2l6ZQQLcmVhbGl6ZWRQbmwJAQRtdWxkAgUNdW5yZWFsaXplZFBubAUQbGlxdWlkYXRpb25SYXRpbwQNJHQwNzY4NzI3NzEwNQkBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEBQ9vbGRQb3NpdGlvblNpemUFEW9sZFBvc2l0aW9uTWFyZ2luBRRvbGRQb3NpdGlvbkxzdFVwZENQRgULcmVhbGl6ZWRQbmwEDHJlbWFpbk1hcmdpbggFDSR0MDc2ODcyNzcxMDUCXzEEB2JhZERlYnQIBQ0kdDA3Njg3Mjc3MTA1Al8yBA5mdW5kaW5nUGF5bWVudAgFDSR0MDc2ODcyNzcxMDUCXzMEEnVucmVhbGl6ZWRQbmxBZnRlcgkAZQIFDXVucmVhbGl6ZWRQbmwFC3JlYWxpemVkUG5sBBJyZW1haW5PcGVuTm90aW9uYWwDCQBmAgUPb2xkUG9zaXRpb25TaXplAAAJAGUCCQBlAgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAUSdW5yZWFsaXplZFBubEFmdGVyCQBlAgkAZAIFEnVucmVhbGl6ZWRQbmxBZnRlcgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAQSbGlxdWlkYXRpb25QZW5hbHR5CQEEbXVsZAIFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQJARNsaXF1aWRhdGlvbkZlZVJhdGlvAAQPZmVlVG9MaXF1aWRhdG9yCQBpAgUSbGlxdWlkYXRpb25QZW5hbHR5AAIECmZlZVRvVmF1bHQJAGUCBRJsaXF1aWRhdGlvblBlbmFsdHkFD2ZlZVRvTGlxdWlkYXRvcgQRbmV3UG9zaXRpb25NYXJnaW4JAGUCBQxyZW1haW5NYXJnaW4FEmxpcXVpZGF0aW9uUGVuYWx0eQQPbmV3UG9zaXRpb25TaXplCQBkAgUPb2xkUG9zaXRpb25TaXplBRVleGNoYW5nZWRQb3NpdGlvblNpemUEF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsCQEDYWJzAQUScmVtYWluT3Blbk5vdGlvbmFsBBFvcGVuTm90aW9uYWxEZWx0YQkAZQIFF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAQUbmV3UG9zaXRpb25Mc3RVcGRDUEYJAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUPbmV3UG9zaXRpb25TaXplBBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCQBlAgkBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAAURb3Blbk5vdGlvbmFsRGVsdGEECmFtbUJhbGFuY2UJAGUCCQEIY2JhbGFuY2UABRJsaXF1aWRhdGlvblBlbmFsdHkEDSR0MDc4MzQ2Nzg0NzUDCQBmAgAABQphbW1CYWxhbmNlCQCUCgIAAAkBA2FicwEFCmFtbUJhbGFuY2UJAJQKAgUKYW1tQmFsYW5jZQAABA1uZXdBbW1CYWxhbmNlCAUNJHQwNzgzNDY3ODQ3NQJfMQQDeDExCAUNJHQwNzgzNDY3ODQ3NQJfMgQNJHQwNzg0ODM3ODUzNwkBE2dldEJvcnJvd2VkQnlUcmFkZXIBBQdfdHJhZGVyBAhib3Jyb3dlZAgFDSR0MDc4NDgzNzg1MzcCXzEEB2Fzc2V0SWQIBQ0kdDA3ODQ4Mzc4NTM3Al8yBBVkb0xpcXVpZGF0ZUNvbGxhdGVyYWwDCQBmAgUIYm9ycm93ZWQAAAQQY29sbGF0ZXJhbFRvU2VsbAkBBG11bGQCBQhib3Jyb3dlZAUQbGlxdWlkYXRpb25SYXRpbwQPcmVhbGl6ZUFuZENsb3NlCQD8BwQJARFjb2xsYXRlcmFsQWRkcmVzcwACEHJlYWxpemVQYXJ0aWFsbHkJAMwIAgUHX3RyYWRlcgkAzAgCBQdhc3NldElkCQDMCAIFEGNvbGxhdGVyYWxUb1NlbGwFA25pbAUDbmlsAwkAAAIFD3JlYWxpemVBbmRDbG9zZQUPcmVhbGl6ZUFuZENsb3NlBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBRVkb0xpcXVpZGF0ZUNvbGxhdGVyYWwFFWRvTGlxdWlkYXRlQ29sbGF0ZXJhbAQHdW5zdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIOd2l0aGRyYXdMb2NrZWQJAMwIAgUSbGlxdWlkYXRpb25QZW5hbHR5BQNuaWwFA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlBBBkZXBvc2l0SW5zdXJhbmNlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAgdhZGRGcmVlBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUKZmVlVG9WYXVsdAUDbmlsAwkAAAIFEGRlcG9zaXRJbnN1cmFuY2UFEGRlcG9zaXRJbnN1cmFuY2UEDm5vdGlmeU5vdGlvbmFsCQD8BwQJAQxtaW5lckFkZHJlc3MAAg5ub3RpZnlOb3Rpb25hbAkAzAgCBQdfdHJhZGVyCQDMCAIFF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBQNuaWwFA25pbAMJAAACBQ5ub3RpZnlOb3Rpb25hbAUObm90aWZ5Tm90aW9uYWwJAM4IAgkAzggCCQDOCAIJAQ51cGRhdGVQb3NpdGlvbgUFB190cmFkZXIFD25ld1Bvc2l0aW9uU2l6ZQURbmV3UG9zaXRpb25NYXJnaW4FF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBRRuZXdQb3NpdGlvbkxzdFVwZENQRgkBCXVwZGF0ZUFtbQgFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgUZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcgkAZQIJARV0b3RhbExvbmdQb3NpdGlvblNpemUAAwkAZgIFD25ld1Bvc2l0aW9uU2l6ZQAACQEDYWJzAQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplAAAJAGUCCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQADCQBmAgAABQ9uZXdQb3NpdGlvblNpemUJAQNhYnMBBRVleGNoYW5nZWRQb3NpdGlvblNpemUAAAkAZQIJARBvcGVuSW50ZXJlc3RMb25nAAMJAGYCBQ9uZXdQb3NpdGlvblNpemUAAAURb3Blbk5vdGlvbmFsRGVsdGEAAAkAZQIJARFvcGVuSW50ZXJlc3RTaG9ydAADCQBmAgAABQ9uZXdQb3NpdGlvblNpemUFEW9wZW5Ob3Rpb25hbERlbHRhAAAJAQh3aXRoZHJhdwIIBQFpBmNhbGxlcgUPZmVlVG9MaXF1aWRhdG9yCQENdXBkYXRlQmFsYW5jZQEFDW5ld0FtbUJhbGFuY2UJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4EDSR0MDgwMjE2ODA3MTEJARVpbnRlcm5hbENsb3NlUG9zaXRpb24CBQdfdHJhZGVyBwQCeDEIBQ0kdDA4MDIxNjgwNzExAl8xBAdiYWREZWJ0CAUNJHQwODAyMTY4MDcxMQJfMgQCeDIIBQ0kdDA4MDIxNjgwNzExAl8zBAJ4MwgFDSR0MDgwMjE2ODA3MTECXzQEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA4MDIxNjgwNzExAl81BBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA4MDIxNjgwNzExAl82BBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwODAyMTY4MDcxMQJfNwQZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcggFDSR0MDgwMjE2ODA3MTECXzgEGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQIBQ0kdDA4MDIxNjgwNzExAl85BA50b3RhbExvbmdBZnRlcggFDSR0MDgwMjE2ODA3MTEDXzEwBA90b3RhbFNob3J0QWZ0ZXIIBQ0kdDA4MDIxNjgwNzExA18xMQQadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA4MDIxNjgwNzExA18xMgQbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCAUNJHQwODAyMTY4MDcxMQNfMTMEEmxpcXVpZGF0aW9uUGVuYWx0eQkBBG11bGQCBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CQETbGlxdWlkYXRpb25GZWVSYXRpbwAED2ZlZVRvTGlxdWlkYXRvcgkAaQIFEmxpcXVpZGF0aW9uUGVuYWx0eQACBApmZWVUb1ZhdWx0CQBlAgUSbGlxdWlkYXRpb25QZW5hbHR5BQ9mZWVUb0xpcXVpZGF0b3IECmFtbUJhbGFuY2UJAGUCCQEIY2JhbGFuY2UABRJsaXF1aWRhdGlvblBlbmFsdHkEDSR0MDgxMTE5ODEyNDgDCQBmAgAABQphbW1CYWxhbmNlCQCUCgIAAAkBA2FicwEFCmFtbUJhbGFuY2UJAJQKAgUKYW1tQmFsYW5jZQAABA1uZXdBbW1CYWxhbmNlCAUNJHQwODExMTk4MTI0OAJfMQQDeDExCAUNJHQwODExMTk4MTI0OAJfMgQNJHQwODEyNTY4MTMxMAkBE2dldEJvcnJvd2VkQnlUcmFkZXIBBQdfdHJhZGVyBAhib3Jyb3dlZAgFDSR0MDgxMjU2ODEzMTACXzEEB2Fzc2V0SWQIBQ0kdDA4MTI1NjgxMzEwAl8yBBVkb0xpcXVpZGF0ZUNvbGxhdGVyYWwDCQBmAgUIYm9ycm93ZWQAAAQPcmVhbGl6ZUFuZENsb3NlCQD8BwQJARFjb2xsYXRlcmFsQWRkcmVzcwACGHJlYWxpemVQYXJ0aWFsbHlBbmRDbG9zZQkAzAgCBQdfdHJhZGVyCQDMCAIAAAkAzAgCBQdhc3NldElkBQNuaWwFA25pbAMJAAACBQ9yZWFsaXplQW5kQ2xvc2UFD3JlYWxpemVBbmRDbG9zZQUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUVZG9MaXF1aWRhdGVDb2xsYXRlcmFsBRVkb0xpcXVpZGF0ZUNvbGxhdGVyYWwEAXgDCQBmAgUHYmFkRGVidAAABAtsb2NrQmFkRGVidAkA/AcECQEMdmF1bHRBZGRyZXNzAAIVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkCQDMCAIFB2JhZERlYnQFA25pbAUDbmlsAwkAAAIFC2xvY2tCYWREZWJ0BQtsb2NrQmFkRGVidAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUBeAUBeAQHdW5zdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIOd2l0aGRyYXdMb2NrZWQJAMwIAgUSbGlxdWlkYXRpb25QZW5hbHR5BQNuaWwFA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlBBBkZXBvc2l0SW5zdXJhbmNlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAgdhZGRGcmVlBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUKZmVlVG9WYXVsdAUDbmlsAwkAAAIFEGRlcG9zaXRJbnN1cmFuY2UFEGRlcG9zaXRJbnN1cmFuY2UEDm5vdGlmeU5vdGlvbmFsCQD8BwQJAQxtaW5lckFkZHJlc3MAAg5ub3RpZnlOb3Rpb25hbAkAzAgCBQdfdHJhZGVyCQDMCAIAAAUDbmlsBQNuaWwDCQAAAgUObm90aWZ5Tm90aW9uYWwFDm5vdGlmeU5vdGlvbmFsCQDOCAIJAM4IAgkAzggCCQEOZGVsZXRlUG9zaXRpb24BBQdfdHJhZGVyCQEJdXBkYXRlQW1tCAUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyBRp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgUbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCQEId2l0aGRyYXcCCAUBaQZjYWxsZXIFD2ZlZVRvTGlxdWlkYXRvcgkBDXVwZGF0ZUJhbGFuY2UBBQ1uZXdBbW1CYWxhbmNlCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCnBheUZ1bmRpbmcABARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEFWZ1bmRpbmdCbG9ja1RpbWVzdGFtcAkBGW5leHRGdW5kaW5nQmxvY2tUaW1lc3RhbXAAAwMDCQBmAgUVZnVuZGluZ0Jsb2NrVGltZXN0YW1wCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQZwYXVzZWQACQACAQkArAICCQCsAgIJAKwCAgIhSW52YWxpZCBmdW5kaW5nIGJsb2NrIHRpbWVzdGFtcDogCQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wAgMgPCAJAKQDAQUVZnVuZGluZ0Jsb2NrVGltZXN0YW1wBA91bmRlcmx5aW5nUHJpY2UJAQ5nZXRPcmFjbGVQcmljZQAEDSR0MDgzMTgyODMyNDQJAQpnZXRGdW5kaW5nAAQUc2hvcnRQcmVtaXVtRnJhY3Rpb24IBQ0kdDA4MzE4MjgzMjQ0Al8xBBNsb25nUHJlbWl1bUZyYWN0aW9uCAUNJHQwODMxODI4MzI0NAJfMgkBDXVwZGF0ZUZ1bmRpbmcFCQBkAgUVZnVuZGluZ0Jsb2NrVGltZXN0YW1wCQEUZnVuZGluZ1BlcmlvZFNlY29uZHMACQBkAgkBI2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAUTbG9uZ1ByZW1pdW1GcmFjdGlvbgkAZAIJASRsYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24ABRRzaG9ydFByZW1pdW1GcmFjdGlvbgkBBGRpdmQCBRNsb25nUHJlbWl1bUZyYWN0aW9uBQ91bmRlcmx5aW5nUHJpY2UJAQRkaXZkAgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24FD3VuZGVybHlpbmdQcmljZQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlAAQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABA0kdDA4MzY3NjgzODExCQEUZ2V0U3luY1Rlcm1pbmFsUHJpY2UDCQEOZ2V0T3JhY2xlUHJpY2UABQdfcXRBc3RSBQdfYnNBc3RSBBNuZXdRdW90ZUFzc2V0V2VpZ2h0CAUNJHQwODM2NzY4MzgxMQJfMQQSbmV3QmFzZUFzc2V0V2VpZ2h0CAUNJHQwODM2NzY4MzgxMQJfMgQNbWFyZ2luVG9WYXVsdAgFDSR0MDgzNjc2ODM4MTECXzMEDWRvRXhjaGFuZ2VQbkwDCQECIT0CBQ1tYXJnaW5Ub1ZhdWx0AAAEDWRvRXhjaGFuZ2VQbkwJAPwHBAkBDHZhdWx0QWRkcmVzcwACFWV4Y2hhbmdlRnJlZUFuZExvY2tlZAkAzAgCBQ1tYXJnaW5Ub1ZhdWx0BQNuaWwFA25pbAMJAAACBQ1kb0V4Y2hhbmdlUG5MBQ1kb0V4Y2hhbmdlUG5MBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBQ1kb0V4Y2hhbmdlUG5MBQ1kb0V4Y2hhbmdlUG5MCQDOCAIJARB1cGRhdGVBbW1XZWlnaHRzAgUTbmV3UXVvdGVBc3NldFdlaWdodAUSbmV3QmFzZUFzc2V0V2VpZ2h0CQEKYXBwZW5kVHdhcAEJAQRkaXZkAgkBBG11bGQCBQdfcXRBc3RSBRNuZXdRdW90ZUFzc2V0V2VpZ2h0CQEEbXVsZAIFB19ic0FzdFIFEm5ld0Jhc2VBc3NldFdlaWdodAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpASd2aWV3X2NhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQBB190cmFkZXIEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQNJHQwODQzODA4NDQ4MQkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQMcG9zaXRpb25TaXplCAUNJHQwODQzODA4NDQ4MQJfMQQOcG9zaXRpb25NYXJnaW4IBQ0kdDA4NDM4MDg0NDgxAl8yBANwb24IBQ0kdDA4NDM4MDg0NDgxAl8zBBFwb3NpdGlvbkxzdFVwZENQRggFDSR0MDg0MzgwODQ0ODECXzQEDSR0MDg0NDg0ODQ1ODUJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAQQcG9zaXRpb25Ob3Rpb25hbAgFDSR0MDg0NDg0ODQ1ODUCXzEEDXVucmVhbGl6ZWRQbmwIBQ0kdDA4NDQ4NDg0NTg1Al8yBA0kdDA4NDU4ODg0NzYwCQEiY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudAQFDHBvc2l0aW9uU2l6ZQUOcG9zaXRpb25NYXJnaW4FEXBvc2l0aW9uTHN0VXBkQ1BGBQ11bnJlYWxpemVkUG5sBAxyZW1haW5NYXJnaW4IBQ0kdDA4NDU4ODg0NzYwAl8xBAdiYWREZWJ0CAUNJHQwODQ1ODg4NDc2MAJfMgQOZnVuZGluZ1BheW1lbnQIBQ0kdDA4NDU4ODg0NzYwAl8zCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAQFzAQUMcmVtYWluTWFyZ2luCQEBcwEFDmZ1bmRpbmdQYXltZW50CQEBcwEJAQ5nZXRNYXJnaW5SYXRpbwEFB190cmFkZXIJAQFzAQUNdW5yZWFsaXplZFBubAkBAXMBBQdiYWREZWJ0CQEBcwEFEHBvc2l0aW9uTm90aW9uYWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEVdmlld19nZXRQZWdBZGp1c3RDb3N0AQZfcHJpY2UEB19xdEFzdFIJAQZxdEFzdFIABAdfYnNBc3RSCQEGYnNBc3RSAAQGcmVzdWx0CQEUZ2V0U3luY1Rlcm1pbmFsUHJpY2UDBQZfcHJpY2UFB19xdEFzdFIFB19ic0FzdFIJAAIBCQCkAwEIBQZyZXN1bHQCXzMBaQEYdmlld19nZXRUZXJtaW5hbEFtbVByaWNlAAQNJHQwODUxNzY4NTI1NwkBE2dldFRlcm1pbmFsQW1tU3RhdGUABBl0ZXJtaW5hbFF1b3RlQXNzZXRSZXNlcnZlCAUNJHQwODUxNzY4NTI1NwJfMQQYdGVybWluYWxCYXNlQXNzZXRSZXNlcnZlCAUNJHQwODUxNzY4NTI1NwJfMgQFcHJpY2UJAQRkaXZkAgkBBG11bGQCBRl0ZXJtaW5hbFF1b3RlQXNzZXRSZXNlcnZlCQEGcXRBc3RXAAkBBG11bGQCBRh0ZXJtaW5hbEJhc2VBc3NldFJlc2VydmUJAQZic0FzdFcACQACAQkApAMBBQVwcmljZQFpAQ92aWV3X2dldEZ1bmRpbmcABA91bmRlcmx5aW5nUHJpY2UJAQ5nZXRPcmFjbGVQcmljZQAEDSR0MDg1NDcyODU1MzQJAQpnZXRGdW5kaW5nAAQUc2hvcnRQcmVtaXVtRnJhY3Rpb24IBQ0kdDA4NTQ3Mjg1NTM0Al8xBBNsb25nUHJlbWl1bUZyYWN0aW9uCAUNJHQwODU0NzI4NTUzNAJfMgQLbG9uZ0Z1bmRpbmcJAQRkaXZkAgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgUPdW5kZXJseWluZ1ByaWNlBAxzaG9ydEZ1bmRpbmcJAQRkaXZkAgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24FD3VuZGVybHlpbmdQcmljZQkAAgEJAKwCAgkArAICCQCsAgIJAQFzAQULbG9uZ0Z1bmRpbmcJAQFzAQUMc2hvcnRGdW5kaW5nCQEBcwEJARBnZXRUd2FwU3BvdFByaWNlAAkBAXMBCQEOZ2V0T3JhY2xlUHJpY2UAAWkBGHZpZXdfZ2V0Qm9ycm93ZWRCeVRyYWRlcgEHX3RyYWRlcgQNJHQwODU4MjA4NTg3NAkBE2dldEJvcnJvd2VkQnlUcmFkZXIBBQdfdHJhZGVyBAhib3Jyb3dlZAgFDSR0MDg1ODIwODU4NzQCXzEEB2Fzc2V0SWQIBQ0kdDA4NTgyMDg1ODc0Al8yCQACAQkArAICCQEBcwEFCGJvcnJvd2VkBQdhc3NldElkAWkBEGNvbXB1dGVTcG90UHJpY2UABAZyZXN1bHQJAQxnZXRTcG90UHJpY2UACQCUCgIFA25pbAUGcmVzdWx0AWkBH2NvbXB1dGVGZWVGb3JUcmFkZXJXaXRoQXJ0aWZhY3QCB190cmFkZXILX2FydGlmYWN0SWQEBnJlc3VsdAkBGGdldEZvclRyYWRlcldpdGhBcnRpZmFjdAIFB190cmFkZXIFC19hcnRpZmFjdElkCQCUCgIFA25pbAUGcmVzdWx0AQJ0eAEGdmVyaWZ5AAkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAkBDmFkbWluUHVibGljS2V5AHqiZSg=", "height": 2381400, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: HnbS3TnpLquq3XcycqHuNLnfBSfWEqz5e3dVREcWxhBU Next: 5LKvTSH76LxRz3oKWL61zSii1nngsWqFndasbF5wgAbU Diff:
OldNewDifferences
11571157 let $t05008050184 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
11581158 let oldPositionNotional = $t05008050184._1
11591159 let unrealizedPnl = $t05008050184._2
1160- let $t05019052848 = if ((oldPositionNotional > openNotional))
1160+ let $t05019052832 = if ((oldPositionNotional > openNotional))
11611161 then {
11621162 let $t05060550789 = swapInput(isAdd, openNotional)
11631163 let exchangedPositionSize = $t05060550789._1
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))
1174- let $t05122651471 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1175- let remainMargin = $t05122651471._1
1176- let badDebt = $t05122651471._2
1177- let fundingPayment = $t05122651471._3
1174+ let $t05122651455 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1175+ let remainMargin = $t05122651455._1
1176+ let badDebt = $t05122651455._2
11781177 let exchangedQuoteAssetAmount = openNotional
11791178 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
11801179 let remainOpenNotional = if ((oldPositionSize > 0))
11931192 }
11941193 }
11951194 else throw("Close position first")
1196- let newPositionSize = $t05019052848._1
1197- let newPositionRemainMargin = $t05019052848._2
1198- let newPositionOpenNotional = $t05019052848._3
1199- let newPositionLatestCPF = $t05019052848._4
1200- let baseAssetReserveAfter = $t05019052848._5
1201- let quoteAssetReserveAfter = $t05019052848._6
1202- let totalPositionSizeAfter = $t05019052848._7
1203- let openInterestNotionalAfter = $t05019052848._8
1204- let totalLongAfter = $t05019052848._9
1205- let totalShortAfter = $t05019052848._10
1206- let totalLongOpenInterestAfter = $t05019052848._11
1207- let totalShortOpenInterestAfter = $t05019052848._12
1195+ let newPositionSize = $t05019052832._1
1196+ let newPositionRemainMargin = $t05019052832._2
1197+ let newPositionOpenNotional = $t05019052832._3
1198+ let newPositionLatestCPF = $t05019052832._4
1199+ let baseAssetReserveAfter = $t05019052832._5
1200+ let quoteAssetReserveAfter = $t05019052832._6
1201+ let totalPositionSizeAfter = $t05019052832._7
1202+ let openInterestNotionalAfter = $t05019052832._8
1203+ let totalLongAfter = $t05019052832._9
1204+ let totalShortAfter = $t05019052832._10
1205+ let totalLongOpenInterestAfter = $t05019052832._11
1206+ let totalShortOpenInterestAfter = $t05019052832._12
12081207 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
12091208 if ((notifyNotional == notifyNotional))
12101209 then (updatePosition(_trader, newPositionSize, newPositionRemainMargin, newPositionOpenNotional, newPositionLatestCPF) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter))
12501249 else isMarketClosed())
12511250 then throw("Invalid increasePosition parameters")
12521251 else {
1253- let $t05431054395 = getForTraderWithArtifact(_trader, getArtifactId(i))
1254- let adjustedFee = $t05431054395._1
1255- let burnArtifact = $t05431054395._2
1252+ let $t05429454379 = getForTraderWithArtifact(_trader, getArtifactId(i))
1253+ let adjustedFee = $t05429454379._1
1254+ let burnArtifact = $t05429454379._2
12561255 let rawFeeAmount = muld(_rawAmount, adjustedFee)
12571256 let _amount = (_rawAmount - rawFeeAmount)
12581257 let distributeFeeAmount = if (isCollateralAsset)
12951294 throw("Invalid referrerFee")
12961295 }
12971296 let feeAmount = (distributeFeeAmount - referrerFee)
1298- let $t05571155851 = getPosition(_trader)
1299- let oldPositionSize = $t05571155851._1
1300- let oldPositionMargin = $t05571155851._2
1301- let oldPositionOpenNotional = $t05571155851._3
1302- let oldPositionLstUpdCPF = $t05571155851._4
1297+ let $t05569555835 = getPosition(_trader)
1298+ let oldPositionSize = $t05569555835._1
1299+ let oldPositionMargin = $t05569555835._2
1300+ let oldPositionOpenNotional = $t05569555835._3
1301+ let oldPositionLstUpdCPF = $t05569555835._4
13031302 let isNewPosition = (oldPositionSize == 0)
13041303 let isSameDirection = if ((oldPositionSize > 0))
13051304 then (_direction == DIR_LONG)
13081307 then isSameDirection
13091308 else false
13101309 let isAdd = (_direction == DIR_LONG)
1311- let $t05614059181 = if (if (isNewPosition)
1310+ let $t05612459165 = if (if (isNewPosition)
13121311 then true
13131312 else expandExisting)
13141313 then {
13151314 let openNotional = muld(_amount, _leverage)
1316- let $t05660256775 = swapInput(isAdd, openNotional)
1317- let amountBaseAssetBought = $t05660256775._1
1318- let quoteAssetReserveAfter = $t05660256775._2
1319- let baseAssetReserveAfter = $t05660256775._3
1320- let totalPositionSizeAfter = $t05660256775._4
1315+ let $t05658656759 = swapInput(isAdd, openNotional)
1316+ let amountBaseAssetBought = $t05658656759._1
1317+ let quoteAssetReserveAfter = $t05658656759._2
1318+ let baseAssetReserveAfter = $t05658656759._3
1319+ let totalPositionSizeAfter = $t05658656759._4
13211320 if (if ((_minBaseAssetAmount != 0))
13221321 then (_minBaseAssetAmount > abs(amountBaseAssetBought))
13231322 else false)
13311330 then openNotional
13321331 else 0))
13331332 let increaseMarginRequirement = divd(openNotional, _leverage)
1334- let $t05738357622 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, increaseMarginRequirement)
1335- let remainMargin = $t05738357622._1
1336- let x1 = $t05738357622._2
1337- let x2 = $t05738357622._3
1333+ let $t05736757606 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, increaseMarginRequirement)
1334+ let remainMargin = $t05736757606._1
1335+ let x1 = $t05736757606._2
1336+ let x2 = $t05736757606._3
13381337 if (!(requireNotOverSpreadLimit(quoteAssetReserveAfter, baseAssetReserveAfter)))
13391338 then throw("Over max spread limit")
13401339 else if (!(requireNotOverMaxOpenNotional(totalLongOpenInterestAfter, totalShortOpenInterestAfter)))
13481347 }
13491348 else {
13501349 let openNotional = muld(_amount, _leverage)
1351- let $t05888158997 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1352- let oldPositionNotional = $t05888158997._1
1353- let unrealizedPnl = $t05888158997._2
1350+ let $t05886558981 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1351+ let oldPositionNotional = $t05886558981._1
1352+ let unrealizedPnl = $t05886558981._2
13541353 if ((oldPositionNotional > openNotional))
13551354 then throw("Use decreasePosition to decrease position size")
13561355 else throw("Close position first")
13571356 }
1358- let newPositionSize = $t05614059181._1
1359- let newPositionRemainMargin = $t05614059181._2
1360- let newPositionOpenNotional = $t05614059181._3
1361- let newPositionLatestCPF = $t05614059181._4
1362- let baseAssetReserveAfter = $t05614059181._5
1363- let quoteAssetReserveAfter = $t05614059181._6
1364- let totalPositionSizeAfter = $t05614059181._7
1365- let openInterestNotionalAfter = $t05614059181._8
1366- let totalLongAfter = $t05614059181._9
1367- let totalShortAfter = $t05614059181._10
1368- let totalLongOpenInterestAfter = $t05614059181._11
1369- let totalShortOpenInterestAfter = $t05614059181._12
1370- let $t05918759244 = distributeFee(feeAmount)
1371- let feeToStakers = $t05918759244._1
1372- let feeToVault = $t05918759244._2
1357+ let newPositionSize = $t05612459165._1
1358+ let newPositionRemainMargin = $t05612459165._2
1359+ let newPositionOpenNotional = $t05612459165._3
1360+ let newPositionLatestCPF = $t05612459165._4
1361+ let baseAssetReserveAfter = $t05612459165._5
1362+ let quoteAssetReserveAfter = $t05612459165._6
1363+ let totalPositionSizeAfter = $t05612459165._7
1364+ let openInterestNotionalAfter = $t05612459165._8
1365+ let totalLongAfter = $t05612459165._9
1366+ let totalShortAfter = $t05612459165._10
1367+ let totalLongOpenInterestAfter = $t05612459165._11
1368+ let totalShortOpenInterestAfter = $t05612459165._12
1369+ let $t05917159228 = distributeFee(feeAmount)
1370+ let feeToStakers = $t05917159228._1
1371+ let feeToVault = $t05917159228._2
13731372 let stake = if (isQuoteAsset)
13741373 then {
13751374 let stake = invoke(vaultAddress(), "addLocked", [false], [AttachedPayment(quoteAsset(), _amount)])
14351434 else isMarketClosed())
14361435 then throw("Invalid addMargin parameters")
14371436 else {
1438- let $t06121661301 = getForTraderWithArtifact(_trader, getArtifactId(i))
1439- let adjustedFee = $t06121661301._1
1440- let burnArtifact = $t06121661301._2
1437+ let $t06120061285 = getForTraderWithArtifact(_trader, getArtifactId(i))
1438+ let adjustedFee = $t06120061285._1
1439+ let burnArtifact = $t06120061285._2
14411440 let rawFeeAmount = muld(_rawAmount, adjustedFee)
14421441 let _amount = (_rawAmount - rawFeeAmount)
14431442 let distributeFeeAmount = if (isCollateralAsset)
14801479 throw("Invalid referrerFee")
14811480 }
14821481 let feeAmount = (distributeFeeAmount - referrerFee)
1483- let $t06260062740 = getPosition(_trader)
1484- let oldPositionSize = $t06260062740._1
1485- let oldPositionMargin = $t06260062740._2
1486- let oldPositionOpenNotional = $t06260062740._3
1487- let oldPositionLstUpdCPF = $t06260062740._4
1488- let $t06274662803 = distributeFee(feeAmount)
1489- let feeToStakers = $t06274662803._1
1490- let feeToVault = $t06274662803._2
1482+ let $t06258462724 = getPosition(_trader)
1483+ let oldPositionSize = $t06258462724._1
1484+ let oldPositionMargin = $t06258462724._2
1485+ let oldPositionOpenNotional = $t06258462724._3
1486+ let oldPositionLstUpdCPF = $t06258462724._4
1487+ let $t06273062787 = distributeFee(feeAmount)
1488+ let feeToStakers = $t06273062787._1
1489+ let feeToVault = $t06273062787._2
14911490 let stake = if (isQuoteAsset)
14921491 then {
14931492 let stake = invoke(vaultAddress(), "addLocked", [false], [AttachedPayment(quoteAsset(), _amount)])
15371536 else isMarketClosed())
15381537 then throw("Invalid removeMargin parameters")
15391538 else {
1540- let $t06393964079 = getPosition(_trader)
1541- let oldPositionSize = $t06393964079._1
1542- let oldPositionMargin = $t06393964079._2
1543- let oldPositionOpenNotional = $t06393964079._3
1544- let oldPositionLstUpdCPF = $t06393964079._4
1539+ let $t06392364063 = getPosition(_trader)
1540+ let oldPositionSize = $t06392364063._1
1541+ let oldPositionMargin = $t06392364063._2
1542+ let oldPositionOpenNotional = $t06392364063._3
1543+ let oldPositionLstUpdCPF = $t06392364063._4
15451544 let marginDelta = -(_amount)
1546- let $t06411664295 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, marginDelta)
1547- let remainMargin = $t06411664295._1
1548- let badDebt = $t06411664295._2
1545+ let $t06410064279 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, marginDelta)
1546+ let remainMargin = $t06410064279._1
1547+ let badDebt = $t06410064279._2
15491548 if ((badDebt != 0))
15501549 then throw("Invalid removed margin amount")
15511550 else {
15541553 then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
15551554 else {
15561555 let quoteAssetStr = toBase58String(quoteAsset())
1557- let $t06473964793 = getBorrowedByTrader(_trader)
1558- let borrowed = $t06473964793._1
1559- let assetId = $t06473964793._2
1556+ let $t06472364777 = getBorrowedByTrader(_trader)
1557+ let borrowed = $t06472364777._1
1558+ let assetId = $t06472364777._2
15601559 let toRepay = if ((_amount > borrowed))
15611560 then borrowed
15621561 else _amount
16281627 else isMarketClosed())
16291628 then throw("Invalid closePosition parameters")
16301629 else {
1631- let $t06697767117 = getPosition(_trader)
1632- let oldPositionSize = $t06697767117._1
1633- let oldPositionMargin = $t06697767117._2
1634- let oldPositionOpenNotional = $t06697767117._3
1635- let oldPositionLstUpdCPF = $t06697767117._4
1636- let $t06712372201 = if ((abs(oldPositionSize) > _size))
1630+ let $t06696167101 = getPosition(_trader)
1631+ let oldPositionSize = $t06696167101._1
1632+ let oldPositionMargin = $t06696167101._2
1633+ let oldPositionOpenNotional = $t06696167101._3
1634+ let oldPositionLstUpdCPF = $t06696167101._4
1635+ let $t06710772237 = if ((abs(oldPositionSize) > _size))
16371636 then {
16381637 let _direction = if ((oldPositionSize > 0))
16391638 then DIR_SHORT
16401639 else DIR_LONG
16411640 let isAdd = (_direction == DIR_LONG)
1642- let $t06771467936 = swapOutput((oldPositionSize > 0), _size, true)
1643- let exchangedQuoteAssetAmount = $t06771467936._1
1644- let quoteAssetReserveAfter = $t06771467936._2
1645- let baseAssetReserveAfter = $t06771467936._3
1646- let totalPositionSizeAfter = $t06771467936._4
1641+ let $t06769867920 = swapOutput((oldPositionSize > 0), _size, true)
1642+ let exchangedQuoteAssetAmount = $t06769867920._1
1643+ let quoteAssetReserveAfter = $t06769867920._2
1644+ let baseAssetReserveAfter = $t06769867920._3
1645+ let totalPositionSizeAfter = $t06769867920._4
16471646 let exchangedPositionSize = if ((oldPositionSize > 0))
16481647 then -(_size)
16491648 else _size
1650- let $t06802768181 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1651- let oldPositionNotional = $t06802768181._1
1652- let unrealizedPnl = $t06802768181._2
1649+ let $t06801168165 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1650+ let oldPositionNotional = $t06801168165._1
1651+ let unrealizedPnl = $t06801168165._2
16531652 let mr = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
16541653 let realizedRatio = divd(abs(exchangedPositionSize), abs(oldPositionSize))
16551654 let realizedPnl = muld(unrealizedPnl, realizedRatio)
16561655 let remainMarginBefore = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, unrealizedPnl)._1
1657- let $t06868268920 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1658- let remainMargin = $t06868268920._1
1659- let positionBadDebt = $t06868268920._2
1660- let fundingPayment = $t06868268920._3
1656+ let $t06866668894 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1657+ let x1 = $t06866668894._1
1658+ let positionBadDebt = $t06866668894._2
1659+ let fundingPayment = $t06866668894._3
16611660 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
16621661 let remainOpenNotional = if ((oldPositionSize > 0))
16631662 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
16661665 let newPositionMargin = if ((oldPositionSize > 0))
16671666 then (muld((newPositionOpenNotional + unrealizedPnlAfter), mr) - unrealizedPnlAfter)
16681667 else (muld((newPositionOpenNotional - unrealizedPnlAfter), mr) - unrealizedPnlAfter)
1668+ let openNotionalDelta = (oldPositionOpenNotional - newPositionOpenNotional)
16691669 let newPositionSize = (oldPositionSize + exchangedPositionSize)
16701670 let newPositionLstUpdCPF = latestCumulativePremiumFraction(newPositionSize)
1671- let openInterestNotionalAfter = (openInterestNotional() - exchangedQuoteAssetAmount)
1671+ let openInterestNotionalAfter = (openInterestNotional() - openNotionalDelta)
16721672 if (if ((_minQuoteAssetAmount != 0))
16731673 then (_minQuoteAssetAmount > exchangedQuoteAssetAmount)
16741674 else false)
16781678 else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
16791679 then abs(exchangedPositionSize)
16801680 else 0)), (openInterestLong() - (if ((newPositionSize > 0))
1681- then exchangedQuoteAssetAmount
1681+ then openNotionalDelta
16821682 else 0)), (openInterestShort() - (if ((0 > newPositionSize))
1683- then exchangedQuoteAssetAmount
1683+ then openNotionalDelta
16841684 else 0)))
16851685 }
16861686 else if ((_size > abs(oldPositionSize)))
16871687 then throw("Invalid closePosition parameters")
16881688 else {
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
1689+ let $t07117871597 = internalClosePosition(_trader, true)
1690+ let exchangedQuoteAssetAmount = $t07117871597._1
1691+ let positionBadDebt = $t07117871597._2
1692+ let realizedPnl = $t07117871597._3
1693+ let marginToVault = $t07117871597._4
1694+ let quoteAssetReserveAfter = $t07117871597._5
1695+ let baseAssetReserveAfter = $t07117871597._6
1696+ let totalPositionSizeAfter = $t07117871597._7
1697+ let openInterestNotionalAfter = $t07117871597._8
1698+ let x2 = $t07117871597._9
1699+ let totalLongAfter = $t07117871597._10
1700+ let totalShortAfter = $t07117871597._11
1701+ let totalLongOpenInterestAfter = $t07117871597._12
1702+ let totalShortOpenInterestAfter = $t07117871597._13
17031703 if (if ((_minQuoteAssetAmount != 0))
17041704 then (_minQuoteAssetAmount > exchangedQuoteAssetAmount)
17051705 else false)
17061706 then throw(((("Limit error: " + toString(exchangedQuoteAssetAmount)) + " < ") + toString(_minQuoteAssetAmount)))
17071707 else $Tuple15(0, 0, 0, 0, positionBadDebt, realizedPnl, marginToVault, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)
17081708 }
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
1709+ let newPositionSize = $t06710772237._1
1710+ let newPositionMargin = $t06710772237._2
1711+ let newPositionOpenNotional = $t06710772237._3
1712+ let newPositionLstUpdCPF = $t06710772237._4
1713+ let positionBadDebt = $t06710772237._5
1714+ let realizedPnl = $t06710772237._6
1715+ let marginToVault = $t06710772237._7
1716+ let quoteAssetReserveAfter = $t06710772237._8
1717+ let baseAssetReserveAfter = $t06710772237._9
1718+ let totalPositionSizeAfter = $t06710772237._10
1719+ let openInterestNotionalAfter = $t06710772237._11
1720+ let totalLongAfter = $t06710772237._12
1721+ let totalShortAfter = $t06710772237._13
1722+ let totalLongOpenInterestAfter = $t06710772237._14
1723+ let totalShortOpenInterestAfter = $t06710772237._15
17241724 if ((positionBadDebt > 0))
17251725 then throw("Unable to close position with bad debt")
17261726 else {
17271727 let withdrawAmount = abs(marginToVault)
17281728 let ammBalance = (cbalance() - withdrawAmount)
1729- let $t07241072617 = if ((0 > ammBalance))
1729+ let $t07244672653 = if ((0 > ammBalance))
17301730 then $Tuple2(0, abs(ammBalance))
17311731 else $Tuple2(ammBalance, 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))
1732+ let ammNewBalance = $t07244672653._1
1733+ let x11 = $t07244672653._2
1734+ let $t07266072714 = getBorrowedByTrader(_trader)
1735+ let borrowed = $t07266072714._1
1736+ let assetId = $t07266072714._2
1737+ let $t07272973588 = if ((borrowed > 0))
17381738 then if ((withdrawAmount >= borrowed))
17391739 then {
17401740 let doRepay = invoke(collateralAddress(), "repay", [_trader, borrowed, assetId], nil)
17491749 else throw("Strict value is not equal to itself.")
17501750 }
17511751 else $Tuple2(nil, withdrawAmount)
1752- if (($t07269373552 == $t07269373552))
1752+ if (($t07272973588 == $t07272973588))
17531753 then {
1754- let quoteWithdrawAmount = $t07269373552._2
1755- let sendCollateralAction = $t07269373552._1
1754+ let quoteWithdrawAmount = $t07272973588._2
1755+ let sendCollateralAction = $t07272973588._1
17561756 let unstake = if ((quoteWithdrawAmount > 0))
17571757 then {
17581758 let unstake = invoke(vaultAddress(), "withdrawLocked", [quoteWithdrawAmount], nil)
18111811 then (DECIMAL_UNIT > partialLiquidationRatio())
18121812 else false)
18131813 then {
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
1814+ let $t07590976059 = getPosition(_trader)
1815+ let oldPositionSize = $t07590976059._1
1816+ let oldPositionMargin = $t07590976059._2
1817+ let oldPositionOpenNotional = $t07590976059._3
1818+ let oldPositionLstUpdCPF = $t07590976059._4
18191819 let _direction = if ((oldPositionSize > 0))
18201820 then DIR_SHORT
18211821 else DIR_LONG
18221822 let isAdd = (_direction == DIR_LONG)
18231823 let exchangedQuoteAssetAmount = getPartialLiquidationAmount(_trader, oldPositionSize)
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
1824+ let $t07628476388 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1825+ let oldPositionNotional = $t07628476388._1
1826+ let unrealizedPnl = $t07628476388._2
1827+ let $t07639676583 = swapInput(isAdd, exchangedQuoteAssetAmount)
1828+ let exchangedPositionSize = $t07639676583._1
1829+ let quoteAssetReserveAfter = $t07639676583._2
1830+ let baseAssetReserveAfter = $t07639676583._3
1831+ let totalPositionSizeAfter = $t07639676583._4
18321832 let liquidationRatio = divd(abs(exchangedPositionSize), abs(oldPositionSize))
18331833 let realizedPnl = muld(unrealizedPnl, liquidationRatio)
1834- let $t07683677069 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1835- let remainMargin = $t07683677069._1
1836- let badDebt = $t07683677069._2
1837- let fundingPayment = $t07683677069._3
1834+ let $t07687277105 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1835+ let remainMargin = $t07687277105._1
1836+ let badDebt = $t07687277105._2
1837+ let fundingPayment = $t07687277105._3
18381838 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
18391839 let remainOpenNotional = if ((oldPositionSize > 0))
18401840 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
18451845 let newPositionMargin = (remainMargin - liquidationPenalty)
18461846 let newPositionSize = (oldPositionSize + exchangedPositionSize)
18471847 let newPositionOpenNotional = abs(remainOpenNotional)
1848+ let openNotionalDelta = (oldPositionOpenNotional - newPositionOpenNotional)
18481849 let newPositionLstUpdCPF = latestCumulativePremiumFraction(newPositionSize)
1849- let openInterestNotionalAfter = (openInterestNotional() - exchangedQuoteAssetAmount)
1850+ let openInterestNotionalAfter = (openInterestNotional() - openNotionalDelta)
18501851 let ammBalance = (cbalance() - liquidationPenalty)
1851- let $t07823878367 = if ((0 > ammBalance))
1852+ let $t07834678475 = if ((0 > ammBalance))
18521853 then $Tuple2(0, abs(ammBalance))
18531854 else $Tuple2(ammBalance, 0)
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
1855+ let newAmmBalance = $t07834678475._1
1856+ let x11 = $t07834678475._2
1857+ let $t07848378537 = getBorrowedByTrader(_trader)
1858+ let borrowed = $t07848378537._1
1859+ let assetId = $t07848378537._2
18591860 let doLiquidateCollateral = if ((borrowed > 0))
18601861 then {
18611862 let collateralToSell = muld(borrowed, liquidationRatio)
18801881 else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
18811882 then abs(exchangedPositionSize)
18821883 else 0)), (openInterestLong() - (if ((newPositionSize > 0))
1883- then exchangedQuoteAssetAmount
1884+ then openNotionalDelta
18841885 else 0)), (openInterestShort() - (if ((0 > newPositionSize))
1885- then exchangedQuoteAssetAmount
1886+ then openNotionalDelta
18861887 else 0)))) ++ withdraw(i.caller, feeToLiquidator)) ++ updateBalance(newAmmBalance))
18871888 else throw("Strict value is not equal to itself.")
18881889 }
18931894 else throw("Strict value is not equal to itself.")
18941895 }
18951896 else {
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
1897+ let $t08021680711 = internalClosePosition(_trader, false)
1898+ let x1 = $t08021680711._1
1899+ let badDebt = $t08021680711._2
1900+ let x2 = $t08021680711._3
1901+ let x3 = $t08021680711._4
1902+ let quoteAssetReserveAfter = $t08021680711._5
1903+ let baseAssetReserveAfter = $t08021680711._6
1904+ let totalPositionSizeAfter = $t08021680711._7
1905+ let openInterestNotionalAfter = $t08021680711._8
1906+ let exchangedQuoteAssetAmount = $t08021680711._9
1907+ let totalLongAfter = $t08021680711._10
1908+ let totalShortAfter = $t08021680711._11
1909+ let totalLongOpenInterestAfter = $t08021680711._12
1910+ let totalShortOpenInterestAfter = $t08021680711._13
19101911 let liquidationPenalty = muld(exchangedQuoteAssetAmount, liquidationFeeRatio())
19111912 let feeToLiquidator = (liquidationPenalty / 2)
19121913 let feeToVault = (liquidationPenalty - feeToLiquidator)
19131914 let ammBalance = (cbalance() - liquidationPenalty)
1914- let $t08102781156 = if ((0 > ammBalance))
1915+ let $t08111981248 = if ((0 > ammBalance))
19151916 then $Tuple2(0, abs(ammBalance))
19161917 else $Tuple2(ammBalance, 0)
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
1918+ let newAmmBalance = $t08111981248._1
1919+ let x11 = $t08111981248._2
1920+ let $t08125681310 = getBorrowedByTrader(_trader)
1921+ let borrowed = $t08125681310._1
1922+ let assetId = $t08125681310._2
19221923 let doLiquidateCollateral = if ((borrowed > 0))
19231924 then {
19241925 let realizeAndClose = invoke(collateralAddress(), "realizePartiallyAndClose", [_trader, 0, assetId], nil)
19781979 then throw(((("Invalid funding block timestamp: " + toString(lastBlock.timestamp)) + " < ") + toString(fundingBlockTimestamp)))
19791980 else {
19801981 let underlyingPrice = getOraclePrice()
1981- let $t08309083152 = getFunding()
1982- let shortPremiumFraction = $t08309083152._1
1983- let longPremiumFraction = $t08309083152._2
1982+ let $t08318283244 = getFunding()
1983+ let shortPremiumFraction = $t08318283244._1
1984+ let longPremiumFraction = $t08318283244._2
19841985 updateFunding((fundingBlockTimestamp + fundingPeriodSeconds()), (latestLongCumulativePremiumFraction() + longPremiumFraction), (latestShortCumulativePremiumFraction() + shortPremiumFraction), divd(longPremiumFraction, underlyingPrice), divd(shortPremiumFraction, underlyingPrice))
19851986 }
19861987 }
19931994 func syncTerminalPriceToOracle () = {
19941995 let _qtAstR = qtAstR()
19951996 let _bsAstR = bsAstR()
1996- let $t08358483719 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1997- let newQuoteAssetWeight = $t08358483719._1
1998- let newBaseAssetWeight = $t08358483719._2
1999- let marginToVault = $t08358483719._3
1997+ let $t08367683811 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1998+ let newQuoteAssetWeight = $t08367683811._1
1999+ let newBaseAssetWeight = $t08367683811._2
2000+ let marginToVault = $t08367683811._3
20002001 let doExchangePnL = if ((marginToVault != 0))
20012002 then {
20022003 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
20172018 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
20182019 if ((sync == sync))
20192020 then {
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
2021+ let $t08438084481 = getPosition(_trader)
2022+ let positionSize = $t08438084481._1
2023+ let positionMargin = $t08438084481._2
2024+ let pon = $t08438084481._3
2025+ let positionLstUpdCPF = $t08438084481._4
2026+ let $t08448484585 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
2027+ let positionNotional = $t08448484585._1
2028+ let unrealizedPnl = $t08448484585._2
2029+ let $t08458884760 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
2030+ let remainMargin = $t08458884760._1
2031+ let badDebt = $t08458884760._2
2032+ let fundingPayment = $t08458884760._3
20322033 throw((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)))
20332034 }
20342035 else throw("Strict value is not equal to itself.")
20482049
20492050 @Callable(i)
20502051 func view_getTerminalAmmPrice () = {
2051- let $t08508485165 = getTerminalAmmState()
2052- let terminalQuoteAssetReserve = $t08508485165._1
2053- let terminalBaseAssetReserve = $t08508485165._2
2052+ let $t08517685257 = getTerminalAmmState()
2053+ let terminalQuoteAssetReserve = $t08517685257._1
2054+ let terminalBaseAssetReserve = $t08517685257._2
20542055 let price = divd(muld(terminalQuoteAssetReserve, qtAstW()), muld(terminalBaseAssetReserve, bsAstW()))
20552056 throw(toString(price))
20562057 }
20602061 @Callable(i)
20612062 func view_getFunding () = {
20622063 let underlyingPrice = getOraclePrice()
2063- let $t08538085442 = getFunding()
2064- let shortPremiumFraction = $t08538085442._1
2065- let longPremiumFraction = $t08538085442._2
2064+ let $t08547285534 = getFunding()
2065+ let shortPremiumFraction = $t08547285534._1
2066+ let longPremiumFraction = $t08547285534._2
20662067 let longFunding = divd(longPremiumFraction, underlyingPrice)
20672068 let shortFunding = divd(shortPremiumFraction, underlyingPrice)
20682069 throw((((s(longFunding) + s(shortFunding)) + s(getTwapSpotPrice())) + s(getOraclePrice())))
20722073
20732074 @Callable(i)
20742075 func view_getBorrowedByTrader (_trader) = {
2075- let $t08572885782 = getBorrowedByTrader(_trader)
2076- let borrowed = $t08572885782._1
2077- let assetId = $t08572885782._2
2076+ let $t08582085874 = getBorrowedByTrader(_trader)
2077+ let borrowed = $t08582085874._1
2078+ let assetId = $t08582085874._2
20782079 throw((s(borrowed) + assetId))
20792080 }
20802081
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
1160- let $t05019052848 = if ((oldPositionNotional > openNotional))
1160+ let $t05019052832 = 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))
1174- let $t05122651471 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1175- let remainMargin = $t05122651471._1
1176- let badDebt = $t05122651471._2
1177- let fundingPayment = $t05122651471._3
1174+ let $t05122651455 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1175+ let remainMargin = $t05122651455._1
1176+ let badDebt = $t05122651455._2
11781177 let exchangedQuoteAssetAmount = openNotional
11791178 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
11801179 let remainOpenNotional = if ((oldPositionSize > 0))
11811180 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
11821181 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
11831182 let newPositionSize = (oldPositionSize + exchangedPositionSize)
11841183 $Tuple12(newPositionSize, remainMargin, abs(remainOpenNotional), latestCumulativePremiumFraction(newPositionSize), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, (openInterestNotional() - openNotional), (totalLongPositionSize() - (if ((newPositionSize > 0))
11851184 then abs(exchangedPositionSize)
11861185 else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
11871186 then abs(exchangedPositionSize)
11881187 else 0)), (openInterestLong() - (if ((newPositionSize > 0))
11891188 then openNotional
11901189 else 0)), (openInterestShort() - (if ((0 > newPositionSize))
11911190 then openNotional
11921191 else 0)))
11931192 }
11941193 }
11951194 else throw("Close position first")
1196- let newPositionSize = $t05019052848._1
1197- let newPositionRemainMargin = $t05019052848._2
1198- let newPositionOpenNotional = $t05019052848._3
1199- let newPositionLatestCPF = $t05019052848._4
1200- let baseAssetReserveAfter = $t05019052848._5
1201- let quoteAssetReserveAfter = $t05019052848._6
1202- let totalPositionSizeAfter = $t05019052848._7
1203- let openInterestNotionalAfter = $t05019052848._8
1204- let totalLongAfter = $t05019052848._9
1205- let totalShortAfter = $t05019052848._10
1206- let totalLongOpenInterestAfter = $t05019052848._11
1207- let totalShortOpenInterestAfter = $t05019052848._12
1195+ let newPositionSize = $t05019052832._1
1196+ let newPositionRemainMargin = $t05019052832._2
1197+ let newPositionOpenNotional = $t05019052832._3
1198+ let newPositionLatestCPF = $t05019052832._4
1199+ let baseAssetReserveAfter = $t05019052832._5
1200+ let quoteAssetReserveAfter = $t05019052832._6
1201+ let totalPositionSizeAfter = $t05019052832._7
1202+ let openInterestNotionalAfter = $t05019052832._8
1203+ let totalLongAfter = $t05019052832._9
1204+ let totalShortAfter = $t05019052832._10
1205+ let totalLongOpenInterestAfter = $t05019052832._11
1206+ let totalShortOpenInterestAfter = $t05019052832._12
12081207 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
12091208 if ((notifyNotional == notifyNotional))
12101209 then (updatePosition(_trader, newPositionSize, newPositionRemainMargin, newPositionOpenNotional, newPositionLatestCPF) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter))
12111210 else throw("Strict value is not equal to itself.")
12121211 }
12131212 }
12141213 else throw("Strict value is not equal to itself.")
12151214 }
12161215
12171216
12181217
12191218 @Callable(i)
12201219 func increasePosition (_direction,_leverage,_minBaseAssetAmount,_refLink) = {
12211220 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
12221221 if ((sync == sync))
12231222 then {
12241223 let _trader = getActualCaller(i)
12251224 let _rawAmount = i.payments[0].amount
12261225 let _assetId = i.payments[0].assetId
12271226 let _assetIdStr = toBase58String(value(_assetId))
12281227 let isQuoteAsset = (_assetId == quoteAsset())
12291228 let isCollateralAsset = isWhitelistAsset(_assetIdStr)
12301229 if (if (if (if (if (if (if (if (if (if ((_direction != DIR_LONG))
12311230 then (_direction != DIR_SHORT)
12321231 else false)
12331232 then true
12341233 else (0 >= _rawAmount))
12351234 then true
12361235 else !(initialized()))
12371236 then true
12381237 else if (!(isQuoteAsset))
12391238 then !(isCollateralAsset)
12401239 else false)
12411240 then true
12421241 else !(isSameAssetOrNoPosition(_trader, _assetIdStr)))
12431242 then true
12441243 else !(requireMoreMarginRatio(divd(DECIMAL_UNIT, _leverage), initMarginRatio(), true)))
12451244 then true
12461245 else paused())
12471246 then true
12481247 else closeOnly())
12491248 then true
12501249 else isMarketClosed())
12511250 then throw("Invalid increasePosition parameters")
12521251 else {
1253- let $t05431054395 = getForTraderWithArtifact(_trader, getArtifactId(i))
1254- let adjustedFee = $t05431054395._1
1255- let burnArtifact = $t05431054395._2
1252+ let $t05429454379 = getForTraderWithArtifact(_trader, getArtifactId(i))
1253+ let adjustedFee = $t05429454379._1
1254+ let burnArtifact = $t05429454379._2
12561255 let rawFeeAmount = muld(_rawAmount, adjustedFee)
12571256 let _amount = (_rawAmount - rawFeeAmount)
12581257 let distributeFeeAmount = if (isCollateralAsset)
12591258 then {
12601259 let doBorrow = invoke(collateralAddress(), "borrow", [_trader], [AttachedPayment(_assetId, _amount)])
12611260 if ((doBorrow == doBorrow))
12621261 then {
12631262 let balanceBefore = assetBalance(this, quoteAsset())
12641263 if ((balanceBefore == balanceBefore))
12651264 then {
12661265 let doSwap = invoke(swapAddress(), "swap", [toBase58String(quoteAsset()), 0], [AttachedPayment(_assetId, rawFeeAmount)])
12671266 if ((doSwap == doSwap))
12681267 then {
12691268 let balanceAfter = assetBalance(this, quoteAsset())
12701269 if ((balanceAfter == balanceAfter))
12711270 then {
12721271 let exchangedAmount = (balanceAfter - balanceBefore)
12731272 if ((exchangedAmount == exchangedAmount))
12741273 then exchangedAmount
12751274 else throw("Strict value is not equal to itself.")
12761275 }
12771276 else throw("Strict value is not equal to itself.")
12781277 }
12791278 else throw("Strict value is not equal to itself.")
12801279 }
12811280 else throw("Strict value is not equal to itself.")
12821281 }
12831282 else throw("Strict value is not equal to itself.")
12841283 }
12851284 else rawFeeAmount
12861285 if ((distributeFeeAmount == distributeFeeAmount))
12871286 then {
12881287 let referrerFeeAny = invoke(referralAddress(), "acceptPaymentWithLink", [_trader, _refLink], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
12891288 if ((referrerFeeAny == referrerFeeAny))
12901289 then {
12911290 let referrerFee = match referrerFeeAny {
12921291 case x: Int =>
12931292 x
12941293 case _ =>
12951294 throw("Invalid referrerFee")
12961295 }
12971296 let feeAmount = (distributeFeeAmount - referrerFee)
1298- let $t05571155851 = getPosition(_trader)
1299- let oldPositionSize = $t05571155851._1
1300- let oldPositionMargin = $t05571155851._2
1301- let oldPositionOpenNotional = $t05571155851._3
1302- let oldPositionLstUpdCPF = $t05571155851._4
1297+ let $t05569555835 = getPosition(_trader)
1298+ let oldPositionSize = $t05569555835._1
1299+ let oldPositionMargin = $t05569555835._2
1300+ let oldPositionOpenNotional = $t05569555835._3
1301+ let oldPositionLstUpdCPF = $t05569555835._4
13031302 let isNewPosition = (oldPositionSize == 0)
13041303 let isSameDirection = if ((oldPositionSize > 0))
13051304 then (_direction == DIR_LONG)
13061305 else (_direction == DIR_SHORT)
13071306 let expandExisting = if (!(isNewPosition))
13081307 then isSameDirection
13091308 else false
13101309 let isAdd = (_direction == DIR_LONG)
1311- let $t05614059181 = if (if (isNewPosition)
1310+ let $t05612459165 = if (if (isNewPosition)
13121311 then true
13131312 else expandExisting)
13141313 then {
13151314 let openNotional = muld(_amount, _leverage)
1316- let $t05660256775 = swapInput(isAdd, openNotional)
1317- let amountBaseAssetBought = $t05660256775._1
1318- let quoteAssetReserveAfter = $t05660256775._2
1319- let baseAssetReserveAfter = $t05660256775._3
1320- let totalPositionSizeAfter = $t05660256775._4
1315+ let $t05658656759 = swapInput(isAdd, openNotional)
1316+ let amountBaseAssetBought = $t05658656759._1
1317+ let quoteAssetReserveAfter = $t05658656759._2
1318+ let baseAssetReserveAfter = $t05658656759._3
1319+ let totalPositionSizeAfter = $t05658656759._4
13211320 if (if ((_minBaseAssetAmount != 0))
13221321 then (_minBaseAssetAmount > abs(amountBaseAssetBought))
13231322 else false)
13241323 then throw(((("Limit error: " + toString(abs(amountBaseAssetBought))) + " < ") + toString(_minBaseAssetAmount)))
13251324 else {
13261325 let newPositionSize = (oldPositionSize + amountBaseAssetBought)
13271326 let totalLongOpenInterestAfter = (openInterestLong() + (if ((newPositionSize > 0))
13281327 then openNotional
13291328 else 0))
13301329 let totalShortOpenInterestAfter = (openInterestShort() + (if ((0 > newPositionSize))
13311330 then openNotional
13321331 else 0))
13331332 let increaseMarginRequirement = divd(openNotional, _leverage)
1334- let $t05738357622 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, increaseMarginRequirement)
1335- let remainMargin = $t05738357622._1
1336- let x1 = $t05738357622._2
1337- let x2 = $t05738357622._3
1333+ let $t05736757606 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, increaseMarginRequirement)
1334+ let remainMargin = $t05736757606._1
1335+ let x1 = $t05736757606._2
1336+ let x2 = $t05736757606._3
13381337 if (!(requireNotOverSpreadLimit(quoteAssetReserveAfter, baseAssetReserveAfter)))
13391338 then throw("Over max spread limit")
13401339 else if (!(requireNotOverMaxOpenNotional(totalLongOpenInterestAfter, totalShortOpenInterestAfter)))
13411340 then throw("Over max open notional")
13421341 else $Tuple12(newPositionSize, remainMargin, (oldPositionOpenNotional + openNotional), latestCumulativePremiumFraction(newPositionSize), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, (openInterestNotional() + openNotional), (totalLongPositionSize() + (if ((newPositionSize > 0))
13431342 then abs(amountBaseAssetBought)
13441343 else 0)), (totalShortPositionSize() + (if ((0 > newPositionSize))
13451344 then abs(amountBaseAssetBought)
13461345 else 0)), totalLongOpenInterestAfter, totalShortOpenInterestAfter)
13471346 }
13481347 }
13491348 else {
13501349 let openNotional = muld(_amount, _leverage)
1351- let $t05888158997 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1352- let oldPositionNotional = $t05888158997._1
1353- let unrealizedPnl = $t05888158997._2
1350+ let $t05886558981 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1351+ let oldPositionNotional = $t05886558981._1
1352+ let unrealizedPnl = $t05886558981._2
13541353 if ((oldPositionNotional > openNotional))
13551354 then throw("Use decreasePosition to decrease position size")
13561355 else throw("Close position first")
13571356 }
1358- let newPositionSize = $t05614059181._1
1359- let newPositionRemainMargin = $t05614059181._2
1360- let newPositionOpenNotional = $t05614059181._3
1361- let newPositionLatestCPF = $t05614059181._4
1362- let baseAssetReserveAfter = $t05614059181._5
1363- let quoteAssetReserveAfter = $t05614059181._6
1364- let totalPositionSizeAfter = $t05614059181._7
1365- let openInterestNotionalAfter = $t05614059181._8
1366- let totalLongAfter = $t05614059181._9
1367- let totalShortAfter = $t05614059181._10
1368- let totalLongOpenInterestAfter = $t05614059181._11
1369- let totalShortOpenInterestAfter = $t05614059181._12
1370- let $t05918759244 = distributeFee(feeAmount)
1371- let feeToStakers = $t05918759244._1
1372- let feeToVault = $t05918759244._2
1357+ let newPositionSize = $t05612459165._1
1358+ let newPositionRemainMargin = $t05612459165._2
1359+ let newPositionOpenNotional = $t05612459165._3
1360+ let newPositionLatestCPF = $t05612459165._4
1361+ let baseAssetReserveAfter = $t05612459165._5
1362+ let quoteAssetReserveAfter = $t05612459165._6
1363+ let totalPositionSizeAfter = $t05612459165._7
1364+ let openInterestNotionalAfter = $t05612459165._8
1365+ let totalLongAfter = $t05612459165._9
1366+ let totalShortAfter = $t05612459165._10
1367+ let totalLongOpenInterestAfter = $t05612459165._11
1368+ let totalShortOpenInterestAfter = $t05612459165._12
1369+ let $t05917159228 = distributeFee(feeAmount)
1370+ let feeToStakers = $t05917159228._1
1371+ let feeToVault = $t05917159228._2
13731372 let stake = if (isQuoteAsset)
13741373 then {
13751374 let stake = invoke(vaultAddress(), "addLocked", [false], [AttachedPayment(quoteAsset(), _amount)])
13761375 if ((stake == stake))
13771376 then nil
13781377 else throw("Strict value is not equal to itself.")
13791378 }
13801379 else nil
13811380 if ((stake == stake))
13821381 then {
13831382 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
13841383 if ((depositInsurance == depositInsurance))
13851384 then {
13861385 let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, feeAmount], nil)
13871386 if ((notifyFee == notifyFee))
13881387 then {
13891388 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
13901389 if ((notifyNotional == notifyNotional))
13911390 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))
13921391 else throw("Strict value is not equal to itself.")
13931392 }
13941393 else throw("Strict value is not equal to itself.")
13951394 }
13961395 else throw("Strict value is not equal to itself.")
13971396 }
13981397 else throw("Strict value is not equal to itself.")
13991398 }
14001399 else throw("Strict value is not equal to itself.")
14011400 }
14021401 else throw("Strict value is not equal to itself.")
14031402 }
14041403 }
14051404 else throw("Strict value is not equal to itself.")
14061405 }
14071406
14081407
14091408
14101409 @Callable(i)
14111410 func addMargin () = {
14121411 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
14131412 if ((sync == sync))
14141413 then {
14151414 let _trader = toString(i.caller)
14161415 let _rawAmount = i.payments[0].amount
14171416 let _assetId = i.payments[0].assetId
14181417 let _assetIdStr = toBase58String(value(_assetId))
14191418 let isQuoteAsset = (_assetId == quoteAsset())
14201419 let isCollateralAsset = isWhitelistAsset(_assetIdStr)
14211420 if (if (if (if (if (if (if (if (!(isQuoteAsset))
14221421 then !(isCollateralAsset)
14231422 else false)
14241423 then true
14251424 else !(requireOpenPosition(toString(i.caller))))
14261425 then true
14271426 else !(isSameAsset(_trader, _assetIdStr)))
14281427 then true
14291428 else !(initialized()))
14301429 then true
14311430 else paused())
14321431 then true
14331432 else closeOnly())
14341433 then true
14351434 else isMarketClosed())
14361435 then throw("Invalid addMargin parameters")
14371436 else {
1438- let $t06121661301 = getForTraderWithArtifact(_trader, getArtifactId(i))
1439- let adjustedFee = $t06121661301._1
1440- let burnArtifact = $t06121661301._2
1437+ let $t06120061285 = getForTraderWithArtifact(_trader, getArtifactId(i))
1438+ let adjustedFee = $t06120061285._1
1439+ let burnArtifact = $t06120061285._2
14411440 let rawFeeAmount = muld(_rawAmount, adjustedFee)
14421441 let _amount = (_rawAmount - rawFeeAmount)
14431442 let distributeFeeAmount = if (isCollateralAsset)
14441443 then {
14451444 let doBorrow = invoke(collateralAddress(), "borrow", [_trader], [AttachedPayment(_assetId, _amount)])
14461445 if ((doBorrow == doBorrow))
14471446 then {
14481447 let balanceBefore = assetBalance(this, quoteAsset())
14491448 if ((balanceBefore == balanceBefore))
14501449 then {
14511450 let doSwap = invoke(swapAddress(), "swap", [toBase58String(quoteAsset()), 0], [AttachedPayment(_assetId, rawFeeAmount)])
14521451 if ((doSwap == doSwap))
14531452 then {
14541453 let balanceAfter = assetBalance(this, quoteAsset())
14551454 if ((balanceAfter == balanceAfter))
14561455 then {
14571456 let exchangedAmount = (balanceAfter - balanceBefore)
14581457 if ((exchangedAmount == exchangedAmount))
14591458 then exchangedAmount
14601459 else throw("Strict value is not equal to itself.")
14611460 }
14621461 else throw("Strict value is not equal to itself.")
14631462 }
14641463 else throw("Strict value is not equal to itself.")
14651464 }
14661465 else throw("Strict value is not equal to itself.")
14671466 }
14681467 else throw("Strict value is not equal to itself.")
14691468 }
14701469 else rawFeeAmount
14711470 if ((distributeFeeAmount == distributeFeeAmount))
14721471 then {
14731472 let referrerFeeAny = invoke(referralAddress(), "acceptPayment", [_trader], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
14741473 if ((referrerFeeAny == referrerFeeAny))
14751474 then {
14761475 let referrerFee = match referrerFeeAny {
14771476 case x: Int =>
14781477 x
14791478 case _ =>
14801479 throw("Invalid referrerFee")
14811480 }
14821481 let feeAmount = (distributeFeeAmount - referrerFee)
1483- let $t06260062740 = getPosition(_trader)
1484- let oldPositionSize = $t06260062740._1
1485- let oldPositionMargin = $t06260062740._2
1486- let oldPositionOpenNotional = $t06260062740._3
1487- let oldPositionLstUpdCPF = $t06260062740._4
1488- let $t06274662803 = distributeFee(feeAmount)
1489- let feeToStakers = $t06274662803._1
1490- let feeToVault = $t06274662803._2
1482+ let $t06258462724 = getPosition(_trader)
1483+ let oldPositionSize = $t06258462724._1
1484+ let oldPositionMargin = $t06258462724._2
1485+ let oldPositionOpenNotional = $t06258462724._3
1486+ let oldPositionLstUpdCPF = $t06258462724._4
1487+ let $t06273062787 = distributeFee(feeAmount)
1488+ let feeToStakers = $t06273062787._1
1489+ let feeToVault = $t06273062787._2
14911490 let stake = if (isQuoteAsset)
14921491 then {
14931492 let stake = invoke(vaultAddress(), "addLocked", [false], [AttachedPayment(quoteAsset(), _amount)])
14941493 if ((stake == stake))
14951494 then nil
14961495 else throw("Strict value is not equal to itself.")
14971496 }
14981497 else nil
14991498 if ((stake == stake))
15001499 then {
15011500 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
15021501 if ((depositInsurance == depositInsurance))
15031502 then {
15041503 let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, feeAmount], nil)
15051504 if ((notifyFee == notifyFee))
15061505 then (((updatePosition(_trader, oldPositionSize, (oldPositionMargin + _amount), oldPositionOpenNotional, oldPositionLstUpdCPF) ++ transferFee(feeToStakers)) ++ updateBalance((cbalance() + _amount))) ++ doBurnArtifact(burnArtifact, i))
15071506 else throw("Strict value is not equal to itself.")
15081507 }
15091508 else throw("Strict value is not equal to itself.")
15101509 }
15111510 else throw("Strict value is not equal to itself.")
15121511 }
15131512 else throw("Strict value is not equal to itself.")
15141513 }
15151514 else throw("Strict value is not equal to itself.")
15161515 }
15171516 }
15181517 else throw("Strict value is not equal to itself.")
15191518 }
15201519
15211520
15221521
15231522 @Callable(i)
15241523 func removeMargin (_amount) = {
15251524 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
15261525 if ((sync == sync))
15271526 then {
15281527 let _trader = toString(i.caller)
15291528 if (if (if (if (if ((0 >= _amount))
15301529 then true
15311530 else !(requireOpenPosition(_trader)))
15321531 then true
15331532 else !(initialized()))
15341533 then true
15351534 else paused())
15361535 then true
15371536 else isMarketClosed())
15381537 then throw("Invalid removeMargin parameters")
15391538 else {
1540- let $t06393964079 = getPosition(_trader)
1541- let oldPositionSize = $t06393964079._1
1542- let oldPositionMargin = $t06393964079._2
1543- let oldPositionOpenNotional = $t06393964079._3
1544- let oldPositionLstUpdCPF = $t06393964079._4
1539+ let $t06392364063 = getPosition(_trader)
1540+ let oldPositionSize = $t06392364063._1
1541+ let oldPositionMargin = $t06392364063._2
1542+ let oldPositionOpenNotional = $t06392364063._3
1543+ let oldPositionLstUpdCPF = $t06392364063._4
15451544 let marginDelta = -(_amount)
1546- let $t06411664295 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, marginDelta)
1547- let remainMargin = $t06411664295._1
1548- let badDebt = $t06411664295._2
1545+ let $t06410064279 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, marginDelta)
1546+ let remainMargin = $t06410064279._1
1547+ let badDebt = $t06410064279._2
15491548 if ((badDebt != 0))
15501549 then throw("Invalid removed margin amount")
15511550 else {
15521551 let marginRatio = calcMarginRatio(remainMargin, badDebt, oldPositionOpenNotional)
15531552 if (!(requireMoreMarginRatio(marginRatio, initMarginRatio(), true)))
15541553 then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
15551554 else {
15561555 let quoteAssetStr = toBase58String(quoteAsset())
1557- let $t06473964793 = getBorrowedByTrader(_trader)
1558- let borrowed = $t06473964793._1
1559- let assetId = $t06473964793._2
1556+ let $t06472364777 = getBorrowedByTrader(_trader)
1557+ let borrowed = $t06472364777._1
1558+ let assetId = $t06472364777._2
15601559 let toRepay = if ((_amount > borrowed))
15611560 then borrowed
15621561 else _amount
15631562 let toWithdraw = if ((borrowed > _amount))
15641563 then 0
15651564 else (_amount - borrowed)
15661565 let finalBorrow = (borrowed - toRepay)
15671566 let switchPositionToQuote = if ((finalBorrow > 0))
15681567 then nil
15691568 else updatePositionAsset(_trader, quoteAssetStr)
15701569 let doSanityCheck = if (((toRepay + toWithdraw) != _amount))
15711570 then throw(((((("toRepay=" + toString(toRepay)) + " + toWithdraw=") + toString(toWithdraw)) + " != ") + toString(_amount)))
15721571 else nil
15731572 if ((doSanityCheck == doSanityCheck))
15741573 then {
15751574 let doUnstake = if ((toWithdraw > 0))
15761575 then {
15771576 let doUnstake = invoke(vaultAddress(), "withdrawLocked", [toWithdraw], nil)
15781577 if ((doUnstake == doUnstake))
15791578 then nil
15801579 else throw("Strict value is not equal to itself.")
15811580 }
15821581 else nil
15831582 if ((doUnstake == doUnstake))
15841583 then {
15851584 let returnCollateralAction = if ((toRepay > 0))
15861585 then {
15871586 let doRepay = invoke(collateralAddress(), "repay", [_trader, toRepay, assetId], nil)
15881587 if ((doRepay == doRepay))
15891588 then [ScriptTransfer(i.caller, toRepay, fromBase58String(assetId))]
15901589 else throw("Strict value is not equal to itself.")
15911590 }
15921591 else nil
15931592 if ((returnCollateralAction == returnCollateralAction))
15941593 then ((((updatePosition(_trader, oldPositionSize, remainMargin, oldPositionOpenNotional, latestCumulativePremiumFraction(oldPositionSize)) ++ (if ((toWithdraw > 0))
15951594 then withdraw(i.caller, toWithdraw)
15961595 else nil)) ++ updateBalance((cbalance() - _amount))) ++ switchPositionToQuote) ++ returnCollateralAction)
15971596 else throw("Strict value is not equal to itself.")
15981597 }
15991598 else throw("Strict value is not equal to itself.")
16001599 }
16011600 else throw("Strict value is not equal to itself.")
16021601 }
16031602 }
16041603 }
16051604 }
16061605 else throw("Strict value is not equal to itself.")
16071606 }
16081607
16091608
16101609
16111610 @Callable(i)
16121611 func closePosition (_size,_minQuoteAssetAmount) = {
16131612 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
16141613 if ((sync == sync))
16151614 then {
16161615 let _trader = getActualCaller(i)
16171616 let _traderAddress = valueOrErrorMessage(addressFromString(_trader), "Invalid caller")
16181617 if (if (if (if (if (if (!(requireOpenPosition(_trader)))
16191618 then true
16201619 else !(initialized()))
16211620 then true
16221621 else paused())
16231622 then true
16241623 else (0 >= _size))
16251624 then true
16261625 else (0 > _minQuoteAssetAmount))
16271626 then true
16281627 else isMarketClosed())
16291628 then throw("Invalid closePosition parameters")
16301629 else {
1631- let $t06697767117 = getPosition(_trader)
1632- let oldPositionSize = $t06697767117._1
1633- let oldPositionMargin = $t06697767117._2
1634- let oldPositionOpenNotional = $t06697767117._3
1635- let oldPositionLstUpdCPF = $t06697767117._4
1636- let $t06712372201 = if ((abs(oldPositionSize) > _size))
1630+ let $t06696167101 = getPosition(_trader)
1631+ let oldPositionSize = $t06696167101._1
1632+ let oldPositionMargin = $t06696167101._2
1633+ let oldPositionOpenNotional = $t06696167101._3
1634+ let oldPositionLstUpdCPF = $t06696167101._4
1635+ let $t06710772237 = if ((abs(oldPositionSize) > _size))
16371636 then {
16381637 let _direction = if ((oldPositionSize > 0))
16391638 then DIR_SHORT
16401639 else DIR_LONG
16411640 let isAdd = (_direction == DIR_LONG)
1642- let $t06771467936 = swapOutput((oldPositionSize > 0), _size, true)
1643- let exchangedQuoteAssetAmount = $t06771467936._1
1644- let quoteAssetReserveAfter = $t06771467936._2
1645- let baseAssetReserveAfter = $t06771467936._3
1646- let totalPositionSizeAfter = $t06771467936._4
1641+ let $t06769867920 = swapOutput((oldPositionSize > 0), _size, true)
1642+ let exchangedQuoteAssetAmount = $t06769867920._1
1643+ let quoteAssetReserveAfter = $t06769867920._2
1644+ let baseAssetReserveAfter = $t06769867920._3
1645+ let totalPositionSizeAfter = $t06769867920._4
16471646 let exchangedPositionSize = if ((oldPositionSize > 0))
16481647 then -(_size)
16491648 else _size
1650- let $t06802768181 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1651- let oldPositionNotional = $t06802768181._1
1652- let unrealizedPnl = $t06802768181._2
1649+ let $t06801168165 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1650+ let oldPositionNotional = $t06801168165._1
1651+ let unrealizedPnl = $t06801168165._2
16531652 let mr = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
16541653 let realizedRatio = divd(abs(exchangedPositionSize), abs(oldPositionSize))
16551654 let realizedPnl = muld(unrealizedPnl, realizedRatio)
16561655 let remainMarginBefore = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, unrealizedPnl)._1
1657- let $t06868268920 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1658- let remainMargin = $t06868268920._1
1659- let positionBadDebt = $t06868268920._2
1660- let fundingPayment = $t06868268920._3
1656+ let $t06866668894 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1657+ let x1 = $t06866668894._1
1658+ let positionBadDebt = $t06866668894._2
1659+ let fundingPayment = $t06866668894._3
16611660 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
16621661 let remainOpenNotional = if ((oldPositionSize > 0))
16631662 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
16641663 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
16651664 let newPositionOpenNotional = abs(remainOpenNotional)
16661665 let newPositionMargin = if ((oldPositionSize > 0))
16671666 then (muld((newPositionOpenNotional + unrealizedPnlAfter), mr) - unrealizedPnlAfter)
16681667 else (muld((newPositionOpenNotional - unrealizedPnlAfter), mr) - unrealizedPnlAfter)
1668+ let openNotionalDelta = (oldPositionOpenNotional - newPositionOpenNotional)
16691669 let newPositionSize = (oldPositionSize + exchangedPositionSize)
16701670 let newPositionLstUpdCPF = latestCumulativePremiumFraction(newPositionSize)
1671- let openInterestNotionalAfter = (openInterestNotional() - exchangedQuoteAssetAmount)
1671+ let openInterestNotionalAfter = (openInterestNotional() - openNotionalDelta)
16721672 if (if ((_minQuoteAssetAmount != 0))
16731673 then (_minQuoteAssetAmount > exchangedQuoteAssetAmount)
16741674 else false)
16751675 then throw(((("Limit error: " + toString(exchangedQuoteAssetAmount)) + " < ") + toString(_minQuoteAssetAmount)))
16761676 else $Tuple15(newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, positionBadDebt, realizedPnl, (remainMarginBefore - (newPositionMargin + unrealizedPnlAfter)), quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, (totalLongPositionSize() - (if ((newPositionSize > 0))
16771677 then abs(exchangedPositionSize)
16781678 else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
16791679 then abs(exchangedPositionSize)
16801680 else 0)), (openInterestLong() - (if ((newPositionSize > 0))
1681- then exchangedQuoteAssetAmount
1681+ then openNotionalDelta
16821682 else 0)), (openInterestShort() - (if ((0 > newPositionSize))
1683- then exchangedQuoteAssetAmount
1683+ then openNotionalDelta
16841684 else 0)))
16851685 }
16861686 else if ((_size > abs(oldPositionSize)))
16871687 then throw("Invalid closePosition parameters")
16881688 else {
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
1689+ let $t07117871597 = internalClosePosition(_trader, true)
1690+ let exchangedQuoteAssetAmount = $t07117871597._1
1691+ let positionBadDebt = $t07117871597._2
1692+ let realizedPnl = $t07117871597._3
1693+ let marginToVault = $t07117871597._4
1694+ let quoteAssetReserveAfter = $t07117871597._5
1695+ let baseAssetReserveAfter = $t07117871597._6
1696+ let totalPositionSizeAfter = $t07117871597._7
1697+ let openInterestNotionalAfter = $t07117871597._8
1698+ let x2 = $t07117871597._9
1699+ let totalLongAfter = $t07117871597._10
1700+ let totalShortAfter = $t07117871597._11
1701+ let totalLongOpenInterestAfter = $t07117871597._12
1702+ let totalShortOpenInterestAfter = $t07117871597._13
17031703 if (if ((_minQuoteAssetAmount != 0))
17041704 then (_minQuoteAssetAmount > exchangedQuoteAssetAmount)
17051705 else false)
17061706 then throw(((("Limit error: " + toString(exchangedQuoteAssetAmount)) + " < ") + toString(_minQuoteAssetAmount)))
17071707 else $Tuple15(0, 0, 0, 0, positionBadDebt, realizedPnl, marginToVault, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)
17081708 }
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
1709+ let newPositionSize = $t06710772237._1
1710+ let newPositionMargin = $t06710772237._2
1711+ let newPositionOpenNotional = $t06710772237._3
1712+ let newPositionLstUpdCPF = $t06710772237._4
1713+ let positionBadDebt = $t06710772237._5
1714+ let realizedPnl = $t06710772237._6
1715+ let marginToVault = $t06710772237._7
1716+ let quoteAssetReserveAfter = $t06710772237._8
1717+ let baseAssetReserveAfter = $t06710772237._9
1718+ let totalPositionSizeAfter = $t06710772237._10
1719+ let openInterestNotionalAfter = $t06710772237._11
1720+ let totalLongAfter = $t06710772237._12
1721+ let totalShortAfter = $t06710772237._13
1722+ let totalLongOpenInterestAfter = $t06710772237._14
1723+ let totalShortOpenInterestAfter = $t06710772237._15
17241724 if ((positionBadDebt > 0))
17251725 then throw("Unable to close position with bad debt")
17261726 else {
17271727 let withdrawAmount = abs(marginToVault)
17281728 let ammBalance = (cbalance() - withdrawAmount)
1729- let $t07241072617 = if ((0 > ammBalance))
1729+ let $t07244672653 = if ((0 > ammBalance))
17301730 then $Tuple2(0, abs(ammBalance))
17311731 else $Tuple2(ammBalance, 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))
1732+ let ammNewBalance = $t07244672653._1
1733+ let x11 = $t07244672653._2
1734+ let $t07266072714 = getBorrowedByTrader(_trader)
1735+ let borrowed = $t07266072714._1
1736+ let assetId = $t07266072714._2
1737+ let $t07272973588 = if ((borrowed > 0))
17381738 then if ((withdrawAmount >= borrowed))
17391739 then {
17401740 let doRepay = invoke(collateralAddress(), "repay", [_trader, borrowed, assetId], nil)
17411741 if ((doRepay == doRepay))
17421742 then $Tuple2([ScriptTransfer(_traderAddress, borrowed, fromBase58String(assetId))], (withdrawAmount - borrowed))
17431743 else throw("Strict value is not equal to itself.")
17441744 }
17451745 else {
17461746 let realizeAndClose = invoke(collateralAddress(), "realizePartiallyAndClose", [_trader, withdrawAmount, assetId], nil)
17471747 if ((realizeAndClose == realizeAndClose))
17481748 then $Tuple2([ScriptTransfer(_traderAddress, withdrawAmount, fromBase58String(assetId))], 0)
17491749 else throw("Strict value is not equal to itself.")
17501750 }
17511751 else $Tuple2(nil, withdrawAmount)
1752- if (($t07269373552 == $t07269373552))
1752+ if (($t07272973588 == $t07272973588))
17531753 then {
1754- let quoteWithdrawAmount = $t07269373552._2
1755- let sendCollateralAction = $t07269373552._1
1754+ let quoteWithdrawAmount = $t07272973588._2
1755+ let sendCollateralAction = $t07272973588._1
17561756 let unstake = if ((quoteWithdrawAmount > 0))
17571757 then {
17581758 let unstake = invoke(vaultAddress(), "withdrawLocked", [quoteWithdrawAmount], nil)
17591759 if ((unstake == unstake))
17601760 then nil
17611761 else throw("Strict value is not equal to itself.")
17621762 }
17631763 else nil
17641764 if ((unstake == unstake))
17651765 then {
17661766 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, 0], nil)
17671767 if ((notifyNotional == notifyNotional))
17681768 then (((((if ((newPositionSize == 0))
17691769 then deletePosition(_trader)
17701770 else updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ (if ((quoteWithdrawAmount > 0))
17711771 then withdraw(_traderAddress, quoteWithdrawAmount)
17721772 else nil)) ++ updateBalance(ammNewBalance)) ++ sendCollateralAction)
17731773 else throw("Strict value is not equal to itself.")
17741774 }
17751775 else throw("Strict value is not equal to itself.")
17761776 }
17771777 else throw("Strict value is not equal to itself.")
17781778 }
17791779 }
17801780 }
17811781 else throw("Strict value is not equal to itself.")
17821782 }
17831783
17841784
17851785
17861786 @Callable(i)
17871787 func liquidate (_trader) = {
17881788 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
17891789 if ((sync == sync))
17901790 then {
17911791 let spotMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
17921792 let marginRatio = if (isOverFluctuationLimit())
17931793 then {
17941794 let oracleMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_ORACLE)
17951795 vmax(spotMarginRatio, oracleMarginRatio)
17961796 }
17971797 else spotMarginRatio
17981798 if (if (if (if (if (!(requireMoreMarginRatio(marginRatio, maintenanceMarginRatio(), false)))
17991799 then true
18001800 else !(requireOpenPosition(_trader)))
18011801 then true
18021802 else !(initialized()))
18031803 then true
18041804 else paused())
18051805 then true
18061806 else isMarketClosed())
18071807 then throw("Unable to liquidate")
18081808 else if (if (if ((spotMarginRatio > liquidationFeeRatio()))
18091809 then (partialLiquidationRatio() > 0)
18101810 else false)
18111811 then (DECIMAL_UNIT > partialLiquidationRatio())
18121812 else false)
18131813 then {
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
1814+ let $t07590976059 = getPosition(_trader)
1815+ let oldPositionSize = $t07590976059._1
1816+ let oldPositionMargin = $t07590976059._2
1817+ let oldPositionOpenNotional = $t07590976059._3
1818+ let oldPositionLstUpdCPF = $t07590976059._4
18191819 let _direction = if ((oldPositionSize > 0))
18201820 then DIR_SHORT
18211821 else DIR_LONG
18221822 let isAdd = (_direction == DIR_LONG)
18231823 let exchangedQuoteAssetAmount = getPartialLiquidationAmount(_trader, oldPositionSize)
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
1824+ let $t07628476388 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1825+ let oldPositionNotional = $t07628476388._1
1826+ let unrealizedPnl = $t07628476388._2
1827+ let $t07639676583 = swapInput(isAdd, exchangedQuoteAssetAmount)
1828+ let exchangedPositionSize = $t07639676583._1
1829+ let quoteAssetReserveAfter = $t07639676583._2
1830+ let baseAssetReserveAfter = $t07639676583._3
1831+ let totalPositionSizeAfter = $t07639676583._4
18321832 let liquidationRatio = divd(abs(exchangedPositionSize), abs(oldPositionSize))
18331833 let realizedPnl = muld(unrealizedPnl, liquidationRatio)
1834- let $t07683677069 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1835- let remainMargin = $t07683677069._1
1836- let badDebt = $t07683677069._2
1837- let fundingPayment = $t07683677069._3
1834+ let $t07687277105 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1835+ let remainMargin = $t07687277105._1
1836+ let badDebt = $t07687277105._2
1837+ let fundingPayment = $t07687277105._3
18381838 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
18391839 let remainOpenNotional = if ((oldPositionSize > 0))
18401840 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
18411841 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
18421842 let liquidationPenalty = muld(exchangedQuoteAssetAmount, liquidationFeeRatio())
18431843 let feeToLiquidator = (liquidationPenalty / 2)
18441844 let feeToVault = (liquidationPenalty - feeToLiquidator)
18451845 let newPositionMargin = (remainMargin - liquidationPenalty)
18461846 let newPositionSize = (oldPositionSize + exchangedPositionSize)
18471847 let newPositionOpenNotional = abs(remainOpenNotional)
1848+ let openNotionalDelta = (oldPositionOpenNotional - newPositionOpenNotional)
18481849 let newPositionLstUpdCPF = latestCumulativePremiumFraction(newPositionSize)
1849- let openInterestNotionalAfter = (openInterestNotional() - exchangedQuoteAssetAmount)
1850+ let openInterestNotionalAfter = (openInterestNotional() - openNotionalDelta)
18501851 let ammBalance = (cbalance() - liquidationPenalty)
1851- let $t07823878367 = if ((0 > ammBalance))
1852+ let $t07834678475 = if ((0 > ammBalance))
18521853 then $Tuple2(0, abs(ammBalance))
18531854 else $Tuple2(ammBalance, 0)
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
1855+ let newAmmBalance = $t07834678475._1
1856+ let x11 = $t07834678475._2
1857+ let $t07848378537 = getBorrowedByTrader(_trader)
1858+ let borrowed = $t07848378537._1
1859+ let assetId = $t07848378537._2
18591860 let doLiquidateCollateral = if ((borrowed > 0))
18601861 then {
18611862 let collateralToSell = muld(borrowed, liquidationRatio)
18621863 let realizeAndClose = invoke(collateralAddress(), "realizePartially", [_trader, assetId, collateralToSell], nil)
18631864 if ((realizeAndClose == realizeAndClose))
18641865 then nil
18651866 else throw("Strict value is not equal to itself.")
18661867 }
18671868 else nil
18681869 if ((doLiquidateCollateral == doLiquidateCollateral))
18691870 then {
18701871 let unstake = invoke(vaultAddress(), "withdrawLocked", [liquidationPenalty], nil)
18711872 if ((unstake == unstake))
18721873 then {
18731874 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
18741875 if ((depositInsurance == depositInsurance))
18751876 then {
18761877 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
18771878 if ((notifyNotional == notifyNotional))
18781879 then (((updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, (totalLongPositionSize() - (if ((newPositionSize > 0))
18791880 then abs(exchangedPositionSize)
18801881 else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
18811882 then abs(exchangedPositionSize)
18821883 else 0)), (openInterestLong() - (if ((newPositionSize > 0))
1883- then exchangedQuoteAssetAmount
1884+ then openNotionalDelta
18841885 else 0)), (openInterestShort() - (if ((0 > newPositionSize))
1885- then exchangedQuoteAssetAmount
1886+ then openNotionalDelta
18861887 else 0)))) ++ withdraw(i.caller, feeToLiquidator)) ++ updateBalance(newAmmBalance))
18871888 else throw("Strict value is not equal to itself.")
18881889 }
18891890 else throw("Strict value is not equal to itself.")
18901891 }
18911892 else throw("Strict value is not equal to itself.")
18921893 }
18931894 else throw("Strict value is not equal to itself.")
18941895 }
18951896 else {
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
1897+ let $t08021680711 = internalClosePosition(_trader, false)
1898+ let x1 = $t08021680711._1
1899+ let badDebt = $t08021680711._2
1900+ let x2 = $t08021680711._3
1901+ let x3 = $t08021680711._4
1902+ let quoteAssetReserveAfter = $t08021680711._5
1903+ let baseAssetReserveAfter = $t08021680711._6
1904+ let totalPositionSizeAfter = $t08021680711._7
1905+ let openInterestNotionalAfter = $t08021680711._8
1906+ let exchangedQuoteAssetAmount = $t08021680711._9
1907+ let totalLongAfter = $t08021680711._10
1908+ let totalShortAfter = $t08021680711._11
1909+ let totalLongOpenInterestAfter = $t08021680711._12
1910+ let totalShortOpenInterestAfter = $t08021680711._13
19101911 let liquidationPenalty = muld(exchangedQuoteAssetAmount, liquidationFeeRatio())
19111912 let feeToLiquidator = (liquidationPenalty / 2)
19121913 let feeToVault = (liquidationPenalty - feeToLiquidator)
19131914 let ammBalance = (cbalance() - liquidationPenalty)
1914- let $t08102781156 = if ((0 > ammBalance))
1915+ let $t08111981248 = if ((0 > ammBalance))
19151916 then $Tuple2(0, abs(ammBalance))
19161917 else $Tuple2(ammBalance, 0)
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
1918+ let newAmmBalance = $t08111981248._1
1919+ let x11 = $t08111981248._2
1920+ let $t08125681310 = getBorrowedByTrader(_trader)
1921+ let borrowed = $t08125681310._1
1922+ let assetId = $t08125681310._2
19221923 let doLiquidateCollateral = if ((borrowed > 0))
19231924 then {
19241925 let realizeAndClose = invoke(collateralAddress(), "realizePartiallyAndClose", [_trader, 0, assetId], nil)
19251926 if ((realizeAndClose == realizeAndClose))
19261927 then nil
19271928 else throw("Strict value is not equal to itself.")
19281929 }
19291930 else nil
19301931 if ((doLiquidateCollateral == doLiquidateCollateral))
19311932 then {
19321933 let x = if ((badDebt > 0))
19331934 then {
19341935 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [badDebt], nil)
19351936 if ((lockBadDebt == lockBadDebt))
19361937 then nil
19371938 else throw("Strict value is not equal to itself.")
19381939 }
19391940 else nil
19401941 if ((x == x))
19411942 then {
19421943 let unstake = invoke(vaultAddress(), "withdrawLocked", [liquidationPenalty], nil)
19431944 if ((unstake == unstake))
19441945 then {
19451946 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
19461947 if ((depositInsurance == depositInsurance))
19471948 then {
19481949 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, 0], nil)
19491950 if ((notifyNotional == notifyNotional))
19501951 then (((deletePosition(_trader) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ withdraw(i.caller, feeToLiquidator)) ++ updateBalance(newAmmBalance))
19511952 else throw("Strict value is not equal to itself.")
19521953 }
19531954 else throw("Strict value is not equal to itself.")
19541955 }
19551956 else throw("Strict value is not equal to itself.")
19561957 }
19571958 else throw("Strict value is not equal to itself.")
19581959 }
19591960 else throw("Strict value is not equal to itself.")
19601961 }
19611962 }
19621963 else throw("Strict value is not equal to itself.")
19631964 }
19641965
19651966
19661967
19671968 @Callable(i)
19681969 func payFunding () = {
19691970 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
19701971 if ((sync == sync))
19711972 then {
19721973 let fundingBlockTimestamp = nextFundingBlockTimestamp()
19731974 if (if (if ((fundingBlockTimestamp > lastBlock.timestamp))
19741975 then true
19751976 else !(initialized()))
19761977 then true
19771978 else paused())
19781979 then throw(((("Invalid funding block timestamp: " + toString(lastBlock.timestamp)) + " < ") + toString(fundingBlockTimestamp)))
19791980 else {
19801981 let underlyingPrice = getOraclePrice()
1981- let $t08309083152 = getFunding()
1982- let shortPremiumFraction = $t08309083152._1
1983- let longPremiumFraction = $t08309083152._2
1982+ let $t08318283244 = getFunding()
1983+ let shortPremiumFraction = $t08318283244._1
1984+ let longPremiumFraction = $t08318283244._2
19841985 updateFunding((fundingBlockTimestamp + fundingPeriodSeconds()), (latestLongCumulativePremiumFraction() + longPremiumFraction), (latestShortCumulativePremiumFraction() + shortPremiumFraction), divd(longPremiumFraction, underlyingPrice), divd(shortPremiumFraction, underlyingPrice))
19851986 }
19861987 }
19871988 else throw("Strict value is not equal to itself.")
19881989 }
19891990
19901991
19911992
19921993 @Callable(i)
19931994 func syncTerminalPriceToOracle () = {
19941995 let _qtAstR = qtAstR()
19951996 let _bsAstR = bsAstR()
1996- let $t08358483719 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1997- let newQuoteAssetWeight = $t08358483719._1
1998- let newBaseAssetWeight = $t08358483719._2
1999- let marginToVault = $t08358483719._3
1997+ let $t08367683811 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1998+ let newQuoteAssetWeight = $t08367683811._1
1999+ let newBaseAssetWeight = $t08367683811._2
2000+ let marginToVault = $t08367683811._3
20002001 let doExchangePnL = if ((marginToVault != 0))
20012002 then {
20022003 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
20032004 if ((doExchangePnL == doExchangePnL))
20042005 then nil
20052006 else throw("Strict value is not equal to itself.")
20062007 }
20072008 else nil
20082009 if ((doExchangePnL == doExchangePnL))
20092010 then (updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight) ++ appendTwap(divd(muld(_qtAstR, newQuoteAssetWeight), muld(_bsAstR, newBaseAssetWeight))))
20102011 else throw("Strict value is not equal to itself.")
20112012 }
20122013
20132014
20142015
20152016 @Callable(i)
20162017 func view_calcRemainMarginWithFundingPayment (_trader) = {
20172018 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
20182019 if ((sync == sync))
20192020 then {
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
2021+ let $t08438084481 = getPosition(_trader)
2022+ let positionSize = $t08438084481._1
2023+ let positionMargin = $t08438084481._2
2024+ let pon = $t08438084481._3
2025+ let positionLstUpdCPF = $t08438084481._4
2026+ let $t08448484585 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
2027+ let positionNotional = $t08448484585._1
2028+ let unrealizedPnl = $t08448484585._2
2029+ let $t08458884760 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
2030+ let remainMargin = $t08458884760._1
2031+ let badDebt = $t08458884760._2
2032+ let fundingPayment = $t08458884760._3
20322033 throw((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)))
20332034 }
20342035 else throw("Strict value is not equal to itself.")
20352036 }
20362037
20372038
20382039
20392040 @Callable(i)
20402041 func view_getPegAdjustCost (_price) = {
20412042 let _qtAstR = qtAstR()
20422043 let _bsAstR = bsAstR()
20432044 let result = getSyncTerminalPrice(_price, _qtAstR, _bsAstR)
20442045 throw(toString(result._3))
20452046 }
20462047
20472048
20482049
20492050 @Callable(i)
20502051 func view_getTerminalAmmPrice () = {
2051- let $t08508485165 = getTerminalAmmState()
2052- let terminalQuoteAssetReserve = $t08508485165._1
2053- let terminalBaseAssetReserve = $t08508485165._2
2052+ let $t08517685257 = getTerminalAmmState()
2053+ let terminalQuoteAssetReserve = $t08517685257._1
2054+ let terminalBaseAssetReserve = $t08517685257._2
20542055 let price = divd(muld(terminalQuoteAssetReserve, qtAstW()), muld(terminalBaseAssetReserve, bsAstW()))
20552056 throw(toString(price))
20562057 }
20572058
20582059
20592060
20602061 @Callable(i)
20612062 func view_getFunding () = {
20622063 let underlyingPrice = getOraclePrice()
2063- let $t08538085442 = getFunding()
2064- let shortPremiumFraction = $t08538085442._1
2065- let longPremiumFraction = $t08538085442._2
2064+ let $t08547285534 = getFunding()
2065+ let shortPremiumFraction = $t08547285534._1
2066+ let longPremiumFraction = $t08547285534._2
20662067 let longFunding = divd(longPremiumFraction, underlyingPrice)
20672068 let shortFunding = divd(shortPremiumFraction, underlyingPrice)
20682069 throw((((s(longFunding) + s(shortFunding)) + s(getTwapSpotPrice())) + s(getOraclePrice())))
20692070 }
20702071
20712072
20722073
20732074 @Callable(i)
20742075 func view_getBorrowedByTrader (_trader) = {
2075- let $t08572885782 = getBorrowedByTrader(_trader)
2076- let borrowed = $t08572885782._1
2077- let assetId = $t08572885782._2
2076+ let $t08582085874 = getBorrowedByTrader(_trader)
2077+ let borrowed = $t08582085874._1
2078+ let assetId = $t08582085874._2
20782079 throw((s(borrowed) + assetId))
20792080 }
20802081
20812082
20822083
20832084 @Callable(i)
20842085 func computeSpotPrice () = {
20852086 let result = getSpotPrice()
20862087 $Tuple2(nil, result)
20872088 }
20882089
20892090
20902091
20912092 @Callable(i)
20922093 func computeFeeForTraderWithArtifact (_trader,_artifactId) = {
20932094 let result = getForTraderWithArtifact(_trader, _artifactId)
20942095 $Tuple2(nil, result)
20952096 }
20962097
20972098
20982099 @Verifier(tx)
20992100 func verify () = sigVerify(tx.bodyBytes, tx.proofs[0], adminPublicKey())
21002101

github/deemru/w8io/169f3d6 
264.86 ms