tx · 5sAxK9E6eeWSH1smdpNSnzEY7hX9U8sCRTdcie9jCMPu

3Mtg8z9QJeGjk6hjLivdwzxVzCfnULGtp3Y:  -0.07500000 Waves

2023.01.18 17:17 [2410474] smart account 3Mtg8z9QJeGjk6hjLivdwzxVzCfnULGtp3Y > SELF 0.00000000 Waves

{ "type": 13, "id": "5sAxK9E6eeWSH1smdpNSnzEY7hX9U8sCRTdcie9jCMPu", "fee": 7500000, "feeAssetId": null, "timestamp": 1674051439425, "version": 2, "chainId": 84, "sender": "3Mtg8z9QJeGjk6hjLivdwzxVzCfnULGtp3Y", "senderPublicKey": "3h2hHv7JAw2DgpQ7ivzx2roiMRtLXrmseSUyS6H6ihZ5", "proofs": [ "3GqnBAAn7ingk7u9mLZkDmKeYY27VRp86w9itFZeVpKbnxqpGZYavo1czjb4vHqFposKP9J35s9ZTEZXP9C42X5o" ], "script": "base64:BgJ0CAISABIAEgASABIDCgEBEgMKAQESDgoMAQEBAQEBAQEBAQEBEhQKEgEBAQEBAQEICAgIAQEBAQEBARIGCgQBAQEIEgASAwoBARIFCgMBAQQSAwoBCBIAEgASAwoBCBIDCgEBEgASABIDCgEIEgASBAoCCAjGAQAJa19vcmFfa2V5AglrX29yYV9rZXkAD2tfb3JhX2Jsb2NrX2tleQIPa19vcmFfYmxvY2tfa2V5AA5rX29yYV9vcGVuX2tleQIOa19vcmFfb3Blbl9rZXkABWtfb3JhAgVrX29yYQAJa19iYWxhbmNlAglrX2JhbGFuY2UACmtfc2VxdWVuY2UCCmtfc2VxdWVuY2UADmtfcG9zaXRpb25TaXplAg5rX3Bvc2l0aW9uU2l6ZQAQa19wb3NpdGlvbk1hcmdpbgIQa19wb3NpdGlvbk1hcmdpbgAWa19wb3NpdGlvbk9wZW5Ob3Rpb25hbAIWa19wb3NpdGlvbk9wZW5Ob3Rpb25hbAAua19wb3NpdGlvbkxhc3RVcGRhdGVkQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgISa19wb3NpdGlvbkZyYWN0aW9uABJrX3Bvc2l0aW9uU2VxdWVuY2UCEmtfcG9zaXRpb25TZXF1ZW5jZQAPa19wb3NpdGlvbkFzc2V0Ag9rX3Bvc2l0aW9uQXNzZXQADWtfcG9zaXRpb25GZWUCDWtfcG9zaXRpb25GZWUADWtfaW5pdGlhbGl6ZWQCDWtfaW5pdGlhbGl6ZWQACGtfcGF1c2VkAghrX3BhdXNlZAALa19jbG9zZU9ubHkCC2tfY2xvc2VPbmx5AAVrX2ZlZQIFa19mZWUAD2tfZnVuZGluZ1BlcmlvZAIPa19mdW5kaW5nUGVyaW9kABFrX2luaXRNYXJnaW5SYXRpbwIRa19pbml0TWFyZ2luUmF0aW8AGGtfbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwIFa19tbXIAFWtfbGlxdWlkYXRpb25GZWVSYXRpbwIVa19saXF1aWRhdGlvbkZlZVJhdGlvABlrX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAhZrX3BhcnRMaXF1aWRhdGlvblJhdGlvAA1rX3NwcmVhZExpbWl0Ag1rX3NwcmVhZExpbWl0ABBrX21heFByaWNlSW1wYWN0AhBrX21heFByaWNlSW1wYWN0ABBrX21heFByaWNlU3ByZWFkAhBrX21heFByaWNlU3ByZWFkABFrX21heE9wZW5Ob3Rpb25hbAIRa19tYXhPcGVuTm90aW9uYWwAFWtfZmVlVG9TdGFrZXJzUGVyY2VudAIVa19mZWVUb1N0YWtlcnNQZXJjZW50ABBrX21heE9yYWNsZURlbGF5AhBrX21heE9yYWNsZURlbGF5AA1rX2xhc3REYXRhU3RyAg1rX2xhc3REYXRhU3RyAA5rX2xhc3RNaW51dGVJZAIOa19sYXN0TWludXRlSWQAHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlAh1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQATa190d2FwRGF0YUxhc3RQcmljZQITa190d2FwRGF0YUxhc3RQcmljZQAaa190d2FwRGF0YVByZXZpb3VzTWludXRlSWQCGmtfdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkACVrX2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAhtrX2xhdGVzdExvbmdQcmVtaXVtRnJhY3Rpb24AJmtfbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAhxrX2xhdGVzdFNob3J0UHJlbWl1bUZyYWN0aW9uABJrX25leHRGdW5kaW5nQmxvY2sCHmtfbmV4dEZ1bmRpbmdCbG9ja01pblRpbWVzdGFtcAARa19sb25nRnVuZGluZ1JhdGUCEWtfbG9uZ0Z1bmRpbmdSYXRlABJrX3Nob3J0RnVuZGluZ1JhdGUCEmtfc2hvcnRGdW5kaW5nUmF0ZQATa19xdW90ZUFzc2V0UmVzZXJ2ZQIIa19xdEFzdFIAEmtfYmFzZUFzc2V0UmVzZXJ2ZQIIa19ic0FzdFIAEmtfcXVvdGVBc3NldFdlaWdodAIIa19xdEFzdFcAEWtfYmFzZUFzc2V0V2VpZ2h0AghrX2JzQXN0VwATa190b3RhbFBvc2l0aW9uU2l6ZQITa190b3RhbFBvc2l0aW9uU2l6ZQAXa190b3RhbExvbmdQb3NpdGlvblNpemUCF2tfdG90YWxMb25nUG9zaXRpb25TaXplABhrX3RvdGFsU2hvcnRQb3NpdGlvblNpemUCGGtfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAWa19vcGVuSW50ZXJlc3ROb3Rpb25hbAIWa19vcGVuSW50ZXJlc3ROb3Rpb25hbAATa19vcGVuSW50ZXJlc3RTaG9ydAITa19vcGVuSW50ZXJlc3RTaG9ydAASa19vcGVuSW50ZXJlc3RMb25nAhJrX29wZW5JbnRlcmVzdExvbmcAFGtfY29vcmRpbmF0b3JBZGRyZXNzAhRrX2Nvb3JkaW5hdG9yQWRkcmVzcwAPa192YXVsdF9hZGRyZXNzAg9rX3ZhdWx0X2FkZHJlc3MAD2tfYWRtaW5fYWRkcmVzcwIPa19hZG1pbl9hZGRyZXNzABJrX2FkbWluX3B1YmxpY19rZXkCEmtfYWRtaW5fcHVibGljX2tleQANa19xdW90ZV9hc3NldAINa19xdW90ZV9hc3NldAAPa19xdW90ZV9zdGFraW5nAg9rX3F1b3RlX3N0YWtpbmcAEWtfc3Rha2luZ19hZGRyZXNzAhFrX3N0YWtpbmdfYWRkcmVzcwAPa19taW5lcl9hZGRyZXNzAg9rX21pbmVyX2FkZHJlc3MAEGtfb3JkZXJzX2FkZHJlc3MCEGtfb3JkZXJzX2FkZHJlc3MAEmtfcmVmZXJyYWxfYWRkcmVzcwISa19yZWZlcnJhbF9hZGRyZXNzABRrX2NvbGxhdGVyYWxfYWRkcmVzcwIUa19jb2xsYXRlcmFsX2FkZHJlc3MAEmtfZXhjaGFuZ2VfYWRkcmVzcwISa19leGNoYW5nZV9hZGRyZXNzABVrX25mdF9tYW5hZ2VyX2FkZHJlc3MCFWtfbmZ0X21hbmFnZXJfYWRkcmVzcwAga190cmFkZXJfbWFya2V0X2Fzc2V0X2NvbGxhdGVyYWwCIGtfdHJhZGVyX21hcmtldF9hc3NldF9jb2xsYXRlcmFsAQ50b0NvbXBvc2l0ZUtleQIEX2tleQhfYWRkcmVzcwkArAICCQCsAgIFBF9rZXkCAV8FCF9hZGRyZXNzAQtjb29yZGluYXRvcgAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCBQR0aGlzBRRrX2Nvb3JkaW5hdG9yQWRkcmVzcwITQ29vcmRpbmF0b3Igbm90IHNldAEMYWRtaW5BZGRyZXNzAAkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABQ9rX2FkbWluX2FkZHJlc3MBDmFkbWluUHVibGljS2V5AAkA2QQBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABRJrX2FkbWluX3B1YmxpY19rZXkBCnF1b3RlQXNzZXQACQDZBAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFDWtfcXVvdGVfYXNzZXQBEXF1b3RlQXNzZXRTdGFraW5nAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFD2tfcXVvdGVfc3Rha2luZwIbUXVvdGUgYXNzZXQgc3Rha2luZyBub3Qgc2V0AQ5zdGFraW5nQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABRFrX3N0YWtpbmdfYWRkcmVzcwIPU3Rha2luZyBub3Qgc2V0AQx2YXVsdEFkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUPa192YXVsdF9hZGRyZXNzAg1WYXVsdCBub3Qgc2V0AQxtaW5lckFkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUPa19taW5lcl9hZGRyZXNzAg1NaW5lciBub3Qgc2V0AQ1vcmRlcnNBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFEGtfb3JkZXJzX2FkZHJlc3MCDk9yZGVycyBub3Qgc2V0AQ9yZWZlcnJhbEFkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUSa19yZWZlcnJhbF9hZGRyZXNzAhBSZWZlcnJhbCBub3Qgc2V0ARFuZnRNYW5hZ2VyQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABRVrX25mdF9tYW5hZ2VyX2FkZHJlc3MCE05GVCBNYW5hZ2VyIG5vdCBzZXQBEWNvbGxhdGVyYWxBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFFGtfY29sbGF0ZXJhbF9hZGRyZXNzAhpDb2xsYXRlcmFsIE1hbmFnZXIgbm90IHNldAELc3dhcEFkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIJAQtjb29yZGluYXRvcgAFEmtfZXhjaGFuZ2VfYWRkcmVzcwIPTm8gc3dhcCBhZGRyZXNzAhRJbnZhbGlkIHN3YXAgYWRkcmVzcwARa193aGl0ZWxpc3RfYXNzZXQCEWtfd2hpdGVsaXN0X2Fzc2V0ARBpc1doaXRlbGlzdEFzc2V0AQhfYXNzZXRJZAkBC3ZhbHVlT3JFbHNlAgkAmwgCCQERY29sbGF0ZXJhbEFkZHJlc3MACQEOdG9Db21wb3NpdGVLZXkCBRFrX3doaXRlbGlzdF9hc3NldAUIX2Fzc2V0SWQHAA1rX3Rva2VuX3BhcmFtAg1rX3Rva2VuX3BhcmFtAAxrX3Rva2VuX3R5cGUCDGtfdG9rZW5fdHlwZQAYRkVFX1JFRFVDVElPTl9UT0tFTl9UWVBFAg1mZWVfcmVkdWN0aW9uAAhESVJfTE9ORwABAAlESVJfU0hPUlQAAgANVFdBUF9JTlRFUlZBTAAPAA9PUkFDTEVfSU5URVJWQUwADwAHU0VDT05EUwDoBwAPREVDSU1BTF9OVU1CRVJTAAYADERFQ0lNQUxfVU5JVAkAaAIAAQkAaAIJAGgCCQBoAgkAaAIJAGgCAAoACgAKAAoACgAKAAdPTkVfREFZCQBoAgCAowUFDERFQ0lNQUxfVU5JVAAIQUxMX0ZFRVMAZAAPUE5MX09QVElPTl9TUE9UAAEAEVBOTF9PUFRJT05fT1JBQ0xFAAIBAXMBAl94CQCsAgIJAKQDAQUCX3gCASwBBGRpdmQCAl94Al95CQBuBAUCX3gFDERFQ0lNQUxfVU5JVAUCX3kFCEhBTEZFVkVOAQRtdWxkAgJfeAJfeQkAbgQFAl94BQJfeQUMREVDSU1BTF9VTklUBQhIQUxGRVZFTgEFc3FydGQBAl94CQEEc3FydAQFAl94BQ9ERUNJTUFMX05VTUJFUlMFD0RFQ0lNQUxfTlVNQkVSUwUISEFMRkVWRU4BBHBvd2QCAl94Al95CQBsBgUCX3gFD0RFQ0lNQUxfTlVNQkVSUwUCX3kFD0RFQ0lNQUxfTlVNQkVSUwUPREVDSU1BTF9OVU1CRVJTBQhIQUxGRVZFTgEFYmRpdmQCAl94Al95CQC9AgQFAl94CQC2AgEFDERFQ0lNQUxfVU5JVAUCX3kFCEhBTEZFVkVOAQVibXVsZAICX3gCX3kJAL0CBAUCX3gFAl95CQC2AgEFDERFQ0lNQUxfVU5JVAUISEFMRkVWRU4BBmJzcXJ0ZAECX3gJAQpzcXJ0QmlnSW50BAUCX3gFD0RFQ0lNQUxfTlVNQkVSUwUPREVDSU1BTF9OVU1CRVJTBQhIQUxGRVZFTgEFYnBvd2QCAl94Al95CQB2BgUCX3gFD0RFQ0lNQUxfTlVNQkVSUwUCX3kFD0RFQ0lNQUxfTlVNQkVSUwUPREVDSU1BTF9OVU1CRVJTBQhIQUxGRVZFTgEDYWJzAQJfeAMJAGYCBQJfeAAABQJfeAkBAS0BBQJfeAEEdm1heAICX3gCX3kDCQBnAgUCX3gFAl95BQJfeAUCX3kBCWxpc3RUb1N0cgEFX2xpc3QKAQVfam9pbgILYWNjdW11bGF0b3IDdmFsCQCsAgIJAKwCAgULYWNjdW11bGF0b3IFA3ZhbAIBLAQKbmV3TGlzdFN0cgoAAiRsBQVfbGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzACAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEFX2pvaW4CBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDIwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAA0ADgAPABAAEQASABMAFAQLbmV3TGlzdFN0clUJALMCAgUKbmV3TGlzdFN0cgABBAtuZXdMaXN0U3RyUgMJAAACCQCvAgIFC25ld0xpc3RTdHJVAAECASwJALACAgULbmV3TGlzdFN0clUAAQULbmV3TGlzdFN0clUFC25ld0xpc3RTdHJSAQlzdHJUb0xpc3QBBF9zdHIJALUJAgUEX3N0cgIBLAELcHVzaFRvUXVldWUDBV9saXN0CF9tYXhTaXplBl92YWx1ZQMJAGYCCQCQAwEFBV9saXN0BQhfbWF4U2l6ZQkAzQgCCQDRCAIFBV9saXN0AAAFBl92YWx1ZQkAzQgCBQVfbGlzdAUGX3ZhbHVlAQNpbnQBAWsJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQR0aGlzBQFrCQCsAgICDW5vIHZhbHVlIGZvciAFAWsBBWludE9yAgFrA2RlZgkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQFrBQNkZWYBBHN0ckECCF9hZGRyZXNzBF9rZXkEA3ZhbAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFCF9hZGRyZXNzBQRfa2V5CQCsAgICEU5vIHZhbHVlIGZvciBrZXkgBQRfa2V5BQN2YWwBBGludEECCF9hZGRyZXNzBF9rZXkEA3ZhbAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFCF9hZGRyZXNzBQRfa2V5CQCsAgICEU5vIHZhbHVlIGZvciBrZXkgBQRfa2V5BQN2YWwBCGNiYWxhbmNlAAkBA2ludAEFCWtfYmFsYW5jZQEDZmVlAAkBA2ludAEFBWtfZmVlAQ9pbml0TWFyZ2luUmF0aW8ACQEDaW50AQURa19pbml0TWFyZ2luUmF0aW8BBnF0QXN0UgAJAQNpbnQBBRNrX3F1b3RlQXNzZXRSZXNlcnZlAQZic0FzdFIACQEDaW50AQUSa19iYXNlQXNzZXRSZXNlcnZlAQZxdEFzdFcACQEFaW50T3ICBRJrX3F1b3RlQXNzZXRXZWlnaHQFDERFQ0lNQUxfVU5JVAEGYnNBc3RXAAkBBWludE9yAgURa19iYXNlQXNzZXRXZWlnaHQFDERFQ0lNQUxfVU5JVAERdG90YWxQb3NpdGlvblNpemUACQEDaW50AQUTa190b3RhbFBvc2l0aW9uU2l6ZQEUb3BlbkludGVyZXN0Tm90aW9uYWwACQEDaW50AQUWa19vcGVuSW50ZXJlc3ROb3Rpb25hbAERb3BlbkludGVyZXN0U2hvcnQACQEDaW50AQUTa19vcGVuSW50ZXJlc3RTaG9ydAEQb3BlbkludGVyZXN0TG9uZwAJAQNpbnQBBRJrX29wZW5JbnRlcmVzdExvbmcBGW5leHRGdW5kaW5nQmxvY2tUaW1lc3RhbXAACQEDaW50AQUSa19uZXh0RnVuZGluZ0Jsb2NrARBmdW5kaW5nUGVyaW9kUmF3AAkBA2ludAEFD2tfZnVuZGluZ1BlcmlvZAEUZnVuZGluZ1BlcmlvZERlY2ltYWwACQBoAgkBEGZ1bmRpbmdQZXJpb2RSYXcABQxERUNJTUFMX1VOSVQBFGZ1bmRpbmdQZXJpb2RTZWNvbmRzAAkAaAIJARBmdW5kaW5nUGVyaW9kUmF3AAUHU0VDT05EUwEWbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwAJAQNpbnQBBRhrX21haW50ZW5hbmNlTWFyZ2luUmF0aW8BE2xpcXVpZGF0aW9uRmVlUmF0aW8ACQEDaW50AQUVa19saXF1aWRhdGlvbkZlZVJhdGlvARdwYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwAJAQNpbnQBBRlrX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAQtzcHJlYWRMaW1pdAAJAQNpbnQBBQ1rX3NwcmVhZExpbWl0AQ5tYXhQcmljZUltcGFjdAAJAQNpbnQBBRBrX21heFByaWNlSW1wYWN0AQ5tYXhQcmljZVNwcmVhZAAJAQNpbnQBBRBrX21heFByaWNlU3ByZWFkAQ9tYXhPcGVuTm90aW9uYWwACQEDaW50AQURa19tYXhPcGVuTm90aW9uYWwBI2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAkBA2ludAEFJWtfbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BJGxhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAJAQNpbnQBBSZrX2xhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAJAQNpbnQBBRhrX3RvdGFsU2hvcnRQb3NpdGlvblNpemUBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQAJAQNpbnQBBRdrX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQEMbGFzdFNlcXVlbmNlAAkBBWludE9yAgUKa19zZXF1ZW5jZQAAARNmZWVUb1N0YWtlcnNQZXJjZW50AAkBA2ludAEFFWtfZmVlVG9TdGFrZXJzUGVyY2VudAEObWF4T3JhY2xlRGVsYXkACQEDaW50AQUQa19tYXhPcmFjbGVEZWxheQEPZ2V0QWN0dWFsQ2FsbGVyAQFpCQELdmFsdWVPckVsc2UCCQCdCAIJAQ1vcmRlcnNBZGRyZXNzAAIIa19zZW5kZXIJAKUIAQgFAWkGY2FsbGVyARZyZXF1aXJlTW9yZU1hcmdpblJhdGlvAwxfbWFyZ2luUmF0aW8QX2Jhc2VNYXJnaW5SYXRpbxRfbGFyZ2VyVGhhbk9yRXF1YWxUbwQUcmVtYWluaW5nTWFyZ2luUmF0aW8JAGUCBQxfbWFyZ2luUmF0aW8FEF9iYXNlTWFyZ2luUmF0aW8DAwUUX2xhcmdlclRoYW5PckVxdWFsVG8JAGYCAAAFFHJlbWFpbmluZ01hcmdpblJhdGlvBwkAAgEJAKwCAgkArAICCQCsAgICEEludmFsaWQgbWFyZ2luOiAJAKQDAQUMX21hcmdpblJhdGlvAgMgPCAJAKQDAQUQX2Jhc2VNYXJnaW5SYXRpbwMDCQEBIQEFFF9sYXJnZXJUaGFuT3JFcXVhbFRvCQBnAgUUcmVtYWluaW5nTWFyZ2luUmF0aW8AAAcJAAIBCQCsAgIJAKwCAgkArAICAhBJbnZhbGlkIG1hcmdpbjogCQCkAwEFDF9tYXJnaW5SYXRpbwIDID4gCQCkAwEFEF9iYXNlTWFyZ2luUmF0aW8GAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQ1fcG9zaXRpb25TaXplAwkAAAIFDV9wb3NpdGlvblNpemUAAAkAAgECLFNob3VsZCBub3QgYmUgY2FsbGVkIHdpdGggX3Bvc2l0aW9uU2l6ZSA9PSAwAwkAZgIFDV9wb3NpdGlvblNpemUAAAkBI2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAkBJGxhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgABC2dldFBvc2l0aW9uAQdfdHJhZGVyBA9wb3NpdGlvblNpemVPcHQJAJoIAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUOa19wb3NpdGlvblNpemUFB190cmFkZXIEByRtYXRjaDAFD3Bvc2l0aW9uU2l6ZU9wdAMJAAECBQckbWF0Y2gwAgNJbnQEDHBvc2l0aW9uU2l6ZQUHJG1hdGNoMAkAlgoEBQxwb3NpdGlvblNpemUJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFEGtfcG9zaXRpb25NYXJnaW4FB190cmFkZXIJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFFmtfcG9zaXRpb25PcGVuTm90aW9uYWwFB190cmFkZXIJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFLmtfcG9zaXRpb25MYXN0VXBkYXRlZEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FB190cmFkZXIJAJYKBAAAAAAAAAAAARBnZXRQb3NpdGlvbkFzc2V0AQdfdHJhZGVyBBBwb3NpdGlvbkFzc2V0T3B0CQCdCAIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFD2tfcG9zaXRpb25Bc3NldAUHX3RyYWRlcgQHJG1hdGNoMAUQcG9zaXRpb25Bc3NldE9wdAMJAAECBQckbWF0Y2gwAgZTdHJpbmcEDXBvc2l0aW9uQXNzZXQFByRtYXRjaDAFDXBvc2l0aW9uQXNzZXQJANgEAQkBCnF1b3RlQXNzZXQAAQ5nZXRQb3NpdGlvbkZlZQEHX3RyYWRlcgQOcG9zaXRpb25GZWVPcHQJAJoIAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUNa19wb3NpdGlvbkZlZQUHX3RyYWRlcgQHJG1hdGNoMAUOcG9zaXRpb25GZWVPcHQDCQABAgUHJG1hdGNoMAIDSW50BAtwb3NpdGlvbkZlZQUHJG1hdGNoMAULcG9zaXRpb25GZWUJAQNmZWUAARNyZXF1aXJlT3BlblBvc2l0aW9uAQdfdHJhZGVyAwkAAAIICQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyAl8xAAAJAAIBAhBObyBvcGVuIHBvc2l0aW9uBgELaW5pdGlhbGl6ZWQACQELdmFsdWVPckVsc2UCCQCbCAIFBHRoaXMFDWtfaW5pdGlhbGl6ZWQHAQZwYXVzZWQACQELdmFsdWVPckVsc2UCCQCbCAIFBHRoaXMFCGtfcGF1c2VkBwEJY2xvc2VPbmx5AAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzBQtrX2Nsb3NlT25seQcBDXVwZGF0ZVJlc2VydmUDBl9pc0FkZBFfcXVvdGVBc3NldEFtb3VudBBfYmFzZUFzc2V0QW1vdW50AwUGX2lzQWRkBAduZXdCYXNlCQBlAgkBBmJzQXN0UgAFEF9iYXNlQXNzZXRBbW91bnQDCQBnAgAABQduZXdCYXNlCQACAQIqVHggbGVhZCB0byBiYXNlIGFzc2V0IHJlc2VydmUgPD0gMCwgcmV2ZXJ0CQCVCgMJAGQCCQEGcXRBc3RSAAURX3F1b3RlQXNzZXRBbW91bnQFB25ld0Jhc2UJAGQCCQERdG90YWxQb3NpdGlvblNpemUABRBfYmFzZUFzc2V0QW1vdW50BAhuZXdRdW90ZQkAZQIJAQZxdEFzdFIABRFfcXVvdGVBc3NldEFtb3VudAMJAGcCAAAFCG5ld1F1b3RlCQACAQIqVHggbGVhZCB0byBiYXNlIHF1b3RlIHJlc2VydmUgPD0gMCwgcmV2ZXJ0CQCVCgMFCG5ld1F1b3RlCQBkAgkBBmJzQXN0UgAFEF9iYXNlQXNzZXRBbW91bnQJAGUCCQERdG90YWxQb3NpdGlvblNpemUABRBfYmFzZUFzc2V0QW1vdW50AQ1jYWxjSW52YXJpYW50AgdfcXRBc3RSB19ic0FzdFIEB2JxdEFzdFIJALYCAQUHX3F0QXN0UgQHYmJzQXN0UgkAtgIBBQdfYnNBc3RSCQEFYm11bGQCBQdicXRBc3RSBQdiYnNBc3RSAQlzd2FwSW5wdXQCBl9pc0FkZBFfcXVvdGVBc3NldEFtb3VudAQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwAEGHF1b3RlQXNzZXRBbW91bnRBZGp1c3RlZAkBBGRpdmQCBRFfcXVvdGVBc3NldEFtb3VudAUHX3F0QXN0VwQBawkBDWNhbGNJbnZhcmlhbnQCBQdfcXRBc3RSBQdfYnNBc3RSBBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyAwUGX2lzQWRkCQBkAgUHX3F0QXN0UgUYcXVvdGVBc3NldEFtb3VudEFkanVzdGVkCQBlAgUHX3F0QXN0UgUYcXVvdGVBc3NldEFtb3VudEFkanVzdGVkBBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIJAKADAQkBBWJkaXZkAgUBawkAtgIBBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBBhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMJAQNhYnMBCQBlAgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBQdfYnNBc3RSBBVhbW91bnRCYXNlQXNzZXRCb3VnaHQDBQZfaXNBZGQFGGFtb3VudEJhc2VBc3NldEJvdWdodEFicwkBAS0BBRhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMEDSR0MDE3MTM4MTczMDgJAQ11cGRhdGVSZXNlcnZlAwUGX2lzQWRkBRhxdW90ZUFzc2V0QW1vdW50QWRqdXN0ZWQFGGFtb3VudEJhc2VBc3NldEJvdWdodEFicwQXcXVvdGVBc3NldFJlc2VydmVBZnRlcjEIBQ0kdDAxNzEzODE3MzA4Al8xBBZiYXNlQXNzZXRSZXNlcnZlQWZ0ZXIxCAUNJHQwMTcxMzgxNzMwOAJfMgQXdG90YWxQb3NpdGlvblNpemVBZnRlcjEIBQ0kdDAxNzEzODE3MzA4Al8zBAtwcmljZUJlZm9yZQkBBGRpdmQCCQEEbXVsZAIFB19xdEFzdFIFB19xdEFzdFcJAQRtdWxkAgUHX2JzQXN0UgUHX2JzQXN0VwQLbWFya2V0UHJpY2UJAQRkaXZkAgURX3F1b3RlQXNzZXRBbW91bnQFGGFtb3VudEJhc2VBc3NldEJvdWdodEFicwQJcHJpY2VEaWZmCQEDYWJzAQkAZQIFC3ByaWNlQmVmb3JlBQttYXJrZXRQcmljZQQLcHJpY2VJbXBhY3QJAGUCBQxERUNJTUFMX1VOSVQJAQRkaXZkAgULcHJpY2VCZWZvcmUJAGQCBQtwcmljZUJlZm9yZQUJcHJpY2VEaWZmBBNtYXhQcmljZUltcGFjdFZhbHVlCQEObWF4UHJpY2VJbXBhY3QAAwkAZgIFC3ByaWNlSW1wYWN0BRNtYXhQcmljZUltcGFjdFZhbHVlCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAg1QcmljZSBpbXBhY3QgCQCkAwEFC3ByaWNlSW1wYWN0AhQgPiBtYXggcHJpY2UgaW1wYWN0IAkApAMBBRNtYXhQcmljZUltcGFjdFZhbHVlAhUgYmVmb3JlIHF1b3RlIGFzc2V0OiAJAKQDAQUHX3F0QXN0UgIUIGJlZm9yZSBiYXNlIGFzc2V0OiAJAKQDAQUHX2JzQXN0UgIhIHF1b3RlIGFzc2V0IGFtb3VudCB0byBleGNoYW5nZTogCQCkAwEFEV9xdW90ZUFzc2V0QW1vdW50Ag8gcHJpY2UgYmVmb3JlOiAJAKQDAQULcHJpY2VCZWZvcmUCDiBtYXJrZXRQcmljZTogCQCkAwEFC21hcmtldFByaWNlCQCWCgQFFWFtb3VudEJhc2VBc3NldEJvdWdodAUXcXVvdGVBc3NldFJlc2VydmVBZnRlcjEFFmJhc2VBc3NldFJlc2VydmVBZnRlcjEFF3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIxASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BBBfb2xkUG9zaXRpb25TaXplEl9vbGRQb3NpdGlvbk1hcmdpbiVfb2xkUG9zaXRpb25DdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uDF9tYXJnaW5EZWx0YQQOZnVuZGluZ1BheW1lbnQDCQECIT0CBRBfb2xkUG9zaXRpb25TaXplAAAEIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uCQEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEFEF9vbGRQb3NpdGlvblNpemUJAQRtdWxkAgkAZQIFIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBSVfb2xkUG9zaXRpb25DdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBRBfb2xkUG9zaXRpb25TaXplAAAEDHNpZ25lZE1hcmdpbgkAZAIJAGUCBQxfbWFyZ2luRGVsdGEFDmZ1bmRpbmdQYXltZW50BRJfb2xkUG9zaXRpb25NYXJnaW4EDSR0MDE4Nzk1MTg5MjIDCQBmAgAABQxzaWduZWRNYXJnaW4JAJQKAgAACQEDYWJzAQUMc2lnbmVkTWFyZ2luCQCUCgIJAQNhYnMBBQxzaWduZWRNYXJnaW4AAAQMcmVtYWluTWFyZ2luCAUNJHQwMTg3OTUxODkyMgJfMQQHYmFkRGVidAgFDSR0MDE4Nzk1MTg5MjICXzIJAJUKAwUMcmVtYWluTWFyZ2luBQdiYWREZWJ0BQ5mdW5kaW5nUGF5bWVudAEWc3dhcE91dHB1dFdpdGhSZXNlcnZlcwcGX2lzQWRkEF9iYXNlQXNzZXRBbW91bnQUX2NoZWNrTWF4UHJpY2VJbXBhY3QSX3F1b3RlQXNzZXRSZXNlcnZlEV9xdW90ZUFzc2V0V2VpZ2h0EV9iYXNlQXNzZXRSZXNlcnZlEF9iYXNlQXNzZXRXZWlnaHQEC3ByaWNlQmVmb3JlCQEEZGl2ZAIJAQRtdWxkAgUSX3F1b3RlQXNzZXRSZXNlcnZlBRFfcXVvdGVBc3NldFdlaWdodAkBBG11bGQCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldFdlaWdodAMJAAACBRBfYmFzZUFzc2V0QW1vdW50AAAJAAIBAhlJbnZhbGlkIGJhc2UgYXNzZXQgYW1vdW50BAFrCQENY2FsY0ludmFyaWFudAIFEl9xdW90ZUFzc2V0UmVzZXJ2ZQURX2Jhc2VBc3NldFJlc2VydmUEGGJhc2VBc3NldFBvb2xBbW91bnRBZnRlcgMFBl9pc0FkZAkAZAIFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0QW1vdW50CQBlAgURX2Jhc2VBc3NldFJlc2VydmUFEF9iYXNlQXNzZXRBbW91bnQED3F1b3RlQXNzZXRBZnRlcgkAoAMBCQEFYmRpdmQCBQFrCQC2AgEFGGJhc2VBc3NldFBvb2xBbW91bnRBZnRlcgQPcXVvdGVBc3NldERlbHRhCQEDYWJzAQkAZQIFD3F1b3RlQXNzZXRBZnRlcgUSX3F1b3RlQXNzZXRSZXNlcnZlBA5xdW90ZUFzc2V0U29sZAkBBG11bGQCBQ9xdW90ZUFzc2V0RGVsdGEFEV9xdW90ZUFzc2V0V2VpZ2h0BBNtYXhQcmljZUltcGFjdFZhbHVlCQEObWF4UHJpY2VJbXBhY3QABA0kdDAyMDA5MjIwMjU0CQENdXBkYXRlUmVzZXJ2ZQMJAQEhAQUGX2lzQWRkBQ9xdW90ZUFzc2V0RGVsdGEFEF9iYXNlQXNzZXRBbW91bnQEF3F1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIxCAUNJHQwMjAwOTIyMDI1NAJfMQQWYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyMQgFDSR0MDIwMDkyMjAyNTQCXzIEF3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIxCAUNJHQwMjAwOTIyMDI1NAJfMwQLbWFya2V0UHJpY2UJAQRkaXZkAgUOcXVvdGVBc3NldFNvbGQFEF9iYXNlQXNzZXRBbW91bnQECXByaWNlRGlmZgkBA2FicwEJAGUCBQtwcmljZUJlZm9yZQULbWFya2V0UHJpY2UEC3ByaWNlSW1wYWN0CQBlAgUMREVDSU1BTF9VTklUCQEEZGl2ZAIFC3ByaWNlQmVmb3JlCQBkAgULcHJpY2VCZWZvcmUFCXByaWNlRGlmZgMDCQBmAgULcHJpY2VJbXBhY3QFE21heFByaWNlSW1wYWN0VmFsdWUFFF9jaGVja01heFByaWNlSW1wYWN0BwkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgINUHJpY2UgaW1wYWN0IAkApAMBBQtwcmljZUltcGFjdAIUID4gbWF4IHByaWNlIGltcGFjdCAJAKQDAQUTbWF4UHJpY2VJbXBhY3RWYWx1ZQIVIGJlZm9yZSBxdW90ZSBhc3NldDogCQCkAwEFEl9xdW90ZUFzc2V0UmVzZXJ2ZQIUIGJlZm9yZSBiYXNlIGFzc2V0OiAJAKQDAQURX2Jhc2VBc3NldFJlc2VydmUCICBiYXNlIGFzc2V0IGFtb3VudCB0byBleGNoYW5nZTogCQCkAwEFEF9iYXNlQXNzZXRBbW91bnQCDyBwcmljZSBiZWZvcmU6IAkApAMBBQtwcmljZUJlZm9yZQIPIG1hcmtldCBwcmljZTogCQCkAwEFC21hcmtldFByaWNlCQCZCgcFDnF1b3RlQXNzZXRTb2xkBRdxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyMQUWYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyMQUXdG90YWxQb3NpdGlvblNpemVBZnRlcjEJAGUCCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAMFBl9pc0FkZAkBA2FicwEFEF9iYXNlQXNzZXRBbW91bnQAAAkAZQIJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAMJAQEhAQUGX2lzQWRkCQEDYWJzAQUQX2Jhc2VBc3NldEFtb3VudAAABQtwcmljZUltcGFjdAEKc3dhcE91dHB1dAMGX2lzQWRkEF9iYXNlQXNzZXRBbW91bnQUX2NoZWNrTWF4UHJpY2VJbXBhY3QJARZzd2FwT3V0cHV0V2l0aFJlc2VydmVzBwUGX2lzQWRkBRBfYmFzZUFzc2V0QW1vdW50BRRfY2hlY2tNYXhQcmljZUltcGFjdAkBBnF0QXN0UgAJAQZxdEFzdFcACQEGYnNBc3RSAAkBBmJzQXN0VwABDmdldE9yYWNsZVByaWNlAAQGb3JhY2xlCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgUEdGhpcwUFa19vcmECAAQIcHJpY2VLZXkJARFAZXh0ck5hdGl2ZSgxMDUzKQIFBHRoaXMFCWtfb3JhX2tleQQJbGFzdFZhbHVlCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUGb3JhY2xlBQhwcmljZUtleQkArAICCQCsAgIJAKwCAgIiQ2FuIG5vdCBnZXQgb3JhY2xlIHByaWNlLiBPcmFjbGU6IAkApQgBBQZvcmFjbGUCBiBrZXk6IAUIcHJpY2VLZXkECGJsb2NrS2V5CQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMFD2tfb3JhX2Jsb2NrX2tleQIAAwkBAiE9AgUIYmxvY2tLZXkCAAQMY3VycmVudEJsb2NrCAUJbGFzdEJsb2NrBmhlaWdodAQPbGFzdE9yYWNsZUJsb2NrCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUGb3JhY2xlBQhibG9ja0tleQkArAICCQCsAgIJAKwCAgIiQ2FuIG5vdCBnZXQgb3JhY2xlIGJsb2NrLiBPcmFjbGU6IAkApQgBBQZvcmFjbGUCBiBrZXk6IAUIYmxvY2tLZXkDCQBmAgkAZQIFDGN1cnJlbnRCbG9jawUPbGFzdE9yYWNsZUJsb2NrCQEObWF4T3JhY2xlRGVsYXkACQACAQkArAICCQCsAgIJAKwCAgImT3JhY2xlIHN0YWxlIGRhdGEuIExhc3Qgb3JhY2xlIGJsb2NrOiAJAKQDAQUPbGFzdE9yYWNsZUJsb2NrAhAgY3VycmVudCBibG9jazogCQCkAwEFDGN1cnJlbnRCbG9jawUJbGFzdFZhbHVlBQlsYXN0VmFsdWUBDmlzTWFya2V0Q2xvc2VkAAQGb3JhY2xlCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgUEdGhpcwUFa19vcmECAAQHb3BlbktleQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzBQ5rX29yYV9vcGVuX2tleQIAAwkBAiE9AgUHb3BlbktleQIABAZpc09wZW4JARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmwgCBQZvcmFjbGUFB29wZW5LZXkJAKwCAgkArAICCQCsAgICK0NhbiBub3QgZ2V0IG9yYWNsZSBpcyBvcGVuL2Nsb3NlZC4gT3JhY2xlOiAJAKUIAQUGb3JhY2xlAgYga2V5OiAFB29wZW5LZXkJAQEhAQUGaXNPcGVuBwEMYWJzUHJpY2VEaWZmBQxfb3JhY2xlUHJpY2USX3F1b3RlQXNzZXRSZXNlcnZlEV9iYXNlQXNzZXRSZXNlcnZlB19xdEFzdFcHX2JzQXN0VwQKcHJpY2VBZnRlcgkBBGRpdmQCCQEEbXVsZAIFEl9xdW90ZUFzc2V0UmVzZXJ2ZQUHX3F0QXN0VwkBBG11bGQCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUHX2JzQXN0VwQMYXZlcmFnZVByaWNlCQEEZGl2ZAIJAGQCBQxfb3JhY2xlUHJpY2UFCnByaWNlQWZ0ZXIJAGgCAAIFDERFQ0lNQUxfVU5JVAQMYWJzUHJpY2VEaWZmCQEEZGl2ZAIJAQNhYnMBCQBlAgUMX29yYWNsZVByaWNlBQpwcmljZUFmdGVyBQxhdmVyYWdlUHJpY2UFDGFic1ByaWNlRGlmZgEZcmVxdWlyZU5vdE92ZXJTcHJlYWRMaW1pdAISX3F1b3RlQXNzZXRSZXNlcnZlEV9iYXNlQXNzZXRSZXNlcnZlBAtvcmFjbGVQcmljZQkBDmdldE9yYWNsZVByaWNlAAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcABBJhYnNQcmljZURpZmZCZWZvcmUJAQxhYnNQcmljZURpZmYFBQtvcmFjbGVQcmljZQkBBnF0QXN0UgAJAQZic0FzdFIABQdfcXRBc3RXBQdfYnNBc3RXBBFhYnNQcmljZURpZmZBZnRlcgkBDGFic1ByaWNlRGlmZgUFC29yYWNsZVByaWNlBRJfcXVvdGVBc3NldFJlc2VydmUFEV9iYXNlQXNzZXRSZXNlcnZlBQdfcXRBc3RXBQdfYnNBc3RXAwMJAGYCBRFhYnNQcmljZURpZmZBZnRlcgkBDm1heFByaWNlU3ByZWFkAAkAZgIFEWFic1ByaWNlRGlmZkFmdGVyBRJhYnNQcmljZURpZmZCZWZvcmUHCQACAQkArAICCQCsAgIJAKwCAgINUHJpY2Ugc3ByZWFkIAkApAMBBRFhYnNQcmljZURpZmZBZnRlcgIUID4gbWF4IHByaWNlIHNwcmVhZCAJAKQDAQkBDm1heFByaWNlU3ByZWFkAAYBHXJlcXVpcmVOb3RPdmVyTWF4T3Blbk5vdGlvbmFsAhFfbG9uZ09wZW5Ob3Rpb25hbBJfc2hvcnRPcGVuTm90aW9uYWwEEF9tYXhPcGVuTm90aW9uYWwJAQ9tYXhPcGVuTm90aW9uYWwAAwkAZgIFEV9sb25nT3Blbk5vdGlvbmFsBRBfbWF4T3Blbk5vdGlvbmFsCQACAQkArAICCQCsAgIJAKwCAgITTG9uZyBvcGVuIG5vdGlvbmFsIAkApAMBBRFfbG9uZ09wZW5Ob3Rpb25hbAIVID4gbWF4IG9wZW4gbm90aW9uYWwgCQCkAwEFEF9tYXhPcGVuTm90aW9uYWwDCQBmAgUSX3Nob3J0T3Blbk5vdGlvbmFsBRBfbWF4T3Blbk5vdGlvbmFsCQACAQkArAICCQCsAgIJAKwCAgIUU2hvcnQgb3BlbiBub3Rpb25hbCAJAKQDAQUSX3Nob3J0T3Blbk5vdGlvbmFsAhUgPiBtYXggb3BlbiBub3Rpb25hbCAJAKQDAQUQX21heE9wZW5Ob3Rpb25hbAYBDGdldFNwb3RQcmljZQAEEl9xdW90ZUFzc2V0UmVzZXJ2ZQkBBnF0QXN0UgAEEV9iYXNlQXNzZXRSZXNlcnZlCQEGYnNBc3RSAAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcACQEEZGl2ZAIJAQRtdWxkAgUSX3F1b3RlQXNzZXRSZXNlcnZlBQdfcXRBc3RXCQEEbXVsZAIFEV9iYXNlQXNzZXRSZXNlcnZlBQdfYnNBc3RXARZpc092ZXJGbHVjdHVhdGlvbkxpbWl0AAQLb3JhY2xlUHJpY2UJAQ5nZXRPcmFjbGVQcmljZQAEDGN1cnJlbnRQcmljZQkBDGdldFNwb3RQcmljZQAJAGYCCQEEZGl2ZAIJAQNhYnMBCQBlAgULb3JhY2xlUHJpY2UFDGN1cnJlbnRQcmljZQULb3JhY2xlUHJpY2UJAQtzcHJlYWRMaW1pdAABH2dldFBvc2l0aW9uQWRqdXN0ZWRPcGVuTm90aW9uYWwGDV9wb3NpdGlvblNpemUHX29wdGlvbhJfcXVvdGVBc3NldFJlc2VydmURX3F1b3RlQXNzZXRXZWlnaHQRX2Jhc2VBc3NldFJlc2VydmUQX2Jhc2VBc3NldFdlaWdodAQPcG9zaXRpb25TaXplQWJzCQEDYWJzAQUNX3Bvc2l0aW9uU2l6ZQQHaXNTaG9ydAkAZgIAAAUNX3Bvc2l0aW9uU2l6ZQQQcG9zaXRpb25Ob3Rpb25hbAMJAAACBQdfb3B0aW9uBQ9QTkxfT1BUSU9OX1NQT1QEDSR0MDI1MjA1MjU0MjUJARZzd2FwT3V0cHV0V2l0aFJlc2VydmVzBwkBASEBBQdpc1Nob3J0BQ9wb3NpdGlvblNpemVBYnMHBRJfcXVvdGVBc3NldFJlc2VydmUFEV9xdW90ZUFzc2V0V2VpZ2h0BRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldFdlaWdodAQTb3V0UG9zaXRpb25Ob3Rpb25hbAgFDSR0MDI1MjA1MjU0MjUCXzEEAngxCAUNJHQwMjUyMDUyNTQyNQJfMgQCeDIIBQ0kdDAyNTIwNTI1NDI1Al8zBAJ4MwgFDSR0MDI1MjA1MjU0MjUCXzQFE291dFBvc2l0aW9uTm90aW9uYWwJAQRtdWxkAgUPcG9zaXRpb25TaXplQWJzCQEOZ2V0T3JhY2xlUHJpY2UABRBwb3NpdGlvbk5vdGlvbmFsAStnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubEJ5VmFsdWVzBw1fcG9zaXRpb25TaXplFV9wb3NpdGlvbk9wZW5Ob3Rpb25hbBJfcXVvdGVBc3NldFJlc2VydmURX3F1b3RlQXNzZXRXZWlnaHQRX2Jhc2VBc3NldFJlc2VydmUQX2Jhc2VBc3NldFdlaWdodAdfb3B0aW9uAwkAAAIFDV9wb3NpdGlvblNpemUAAAkAAgECFUludmFsaWQgcG9zaXRpb24gc2l6ZQQHaXNTaG9ydAkAZgIAAAUNX3Bvc2l0aW9uU2l6ZQQQcG9zaXRpb25Ob3Rpb25hbAkBH2dldFBvc2l0aW9uQWRqdXN0ZWRPcGVuTm90aW9uYWwGBQ1fcG9zaXRpb25TaXplBQdfb3B0aW9uBRJfcXVvdGVBc3NldFJlc2VydmUFEV9xdW90ZUFzc2V0V2VpZ2h0BRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldFdlaWdodAQNdW5yZWFsaXplZFBubAMFB2lzU2hvcnQJAGUCBRVfcG9zaXRpb25PcGVuTm90aW9uYWwFEHBvc2l0aW9uTm90aW9uYWwJAGUCBRBwb3NpdGlvbk5vdGlvbmFsBRVfcG9zaXRpb25PcGVuTm90aW9uYWwJAJQKAgUQcG9zaXRpb25Ob3Rpb25hbAUNdW5yZWFsaXplZFBubAEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCB190cmFkZXIHX29wdGlvbgQNJHQwMjY4NDYyNjk3NAkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQMcG9zaXRpb25TaXplCAUNJHQwMjY4NDYyNjk3NAJfMQQOcG9zaXRpb25NYXJnaW4IBQ0kdDAyNjg0NjI2OTc0Al8yBBRwb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDI2ODQ2MjY5NzQCXzMEEXBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwMjY4NDYyNjk3NAJfNAkBK2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sQnlWYWx1ZXMHBQxwb3NpdGlvblNpemUFFHBvc2l0aW9uT3Blbk5vdGlvbmFsCQEGcXRBc3RSAAkBBnF0QXN0VwAJAQZic0FzdFIACQEGYnNBc3RXAAUHX29wdGlvbgEPY2FsY01hcmdpblJhdGlvAw1fcmVtYWluTWFyZ2luCF9iYWREZWJ0EV9wb3NpdGlvbk5vdGlvbmFsCQEEZGl2ZAIJAGUCBQ1fcmVtYWluTWFyZ2luBQhfYmFkRGVidAURX3Bvc2l0aW9uTm90aW9uYWwBFmdldE1hcmdpblJhdGlvQnlPcHRpb24CB190cmFkZXIHX29wdGlvbgQNJHQwMjc0ODcyNzU5OAkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQMcG9zaXRpb25TaXplCAUNJHQwMjc0ODcyNzU5OAJfMQQOcG9zaXRpb25NYXJnaW4IBQ0kdDAyNzQ4NzI3NTk4Al8yBANwb24IBQ0kdDAyNzQ4NzI3NTk4Al8zBBFwb3NpdGlvbkxzdFVwZENQRggFDSR0MDI3NDg3Mjc1OTgCXzQEDSR0MDI3NjA0Mjc2OTcJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIFB190cmFkZXIFB19vcHRpb24EEHBvc2l0aW9uTm90aW9uYWwIBQ0kdDAyNzYwNDI3Njk3Al8xBA11bnJlYWxpemVkUG5sCAUNJHQwMjc2MDQyNzY5NwJfMgQNJHQwMjc3MDIyNzg2OAkBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEBQxwb3NpdGlvblNpemUFDnBvc2l0aW9uTWFyZ2luBRFwb3NpdGlvbkxzdFVwZENQRgUNdW5yZWFsaXplZFBubAQMcmVtYWluTWFyZ2luCAUNJHQwMjc3MDIyNzg2OAJfMQQHYmFkRGVidAgFDSR0MDI3NzAyMjc4NjgCXzIJAQ9jYWxjTWFyZ2luUmF0aW8DBQxyZW1haW5NYXJnaW4FB2JhZERlYnQFEHBvc2l0aW9uTm90aW9uYWwBDmdldE1hcmdpblJhdGlvAQdfdHJhZGVyCQEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAEbZ2V0UGFydGlhbExpcXVpZGF0aW9uQW1vdW50AgdfdHJhZGVyDV9wb3NpdGlvblNpemUEDG1heGltdW1SYXRpbwkBBHZtYXgCCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8ACQBlAgUMREVDSU1BTF9VTklUCQEEZGl2ZAIJAQ5nZXRNYXJnaW5SYXRpbwEFB190cmFkZXIJARZtYWludGVuYW5jZU1hcmdpblJhdGlvAAQYbWF4RXhjaGFuZ2VkUG9zaXRpb25TaXplCQEEbXVsZAIJAQNhYnMBBQ1fcG9zaXRpb25TaXplBQxtYXhpbXVtUmF0aW8ECnN3YXBSZXN1bHQJAQpzd2FwT3V0cHV0AwkAZgIFDV9wb3NpdGlvblNpemUAAAUYbWF4RXhjaGFuZ2VkUG9zaXRpb25TaXplBwQcbWF4RXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAgFCnN3YXBSZXN1bHQCXzEEC3ByaWNlSW1wYWN0CAUKc3dhcFJlc3VsdAJfNwMJAGYCCQEObWF4UHJpY2VJbXBhY3QABQtwcmljZUltcGFjdAUcbWF4RXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAQVZXhjaGFuZ2VkUG9zaXRpb25TaXplCQEEbXVsZAIJAQNhYnMBBQ1fcG9zaXRpb25TaXplCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8ABBlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CAkBCnN3YXBPdXRwdXQDCQBmAgUNX3Bvc2l0aW9uU2l6ZQAABRVleGNoYW5nZWRQb3NpdGlvblNpemUHAl8xBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50ARVpbnRlcm5hbENsb3NlUG9zaXRpb24CB190cmFkZXIUX2NoZWNrTWF4UHJpY2VJbXBhY3QEDSR0MDI5MTA4MjkyMzYJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIEDHBvc2l0aW9uU2l6ZQgFDSR0MDI5MTA4MjkyMzYCXzEEDnBvc2l0aW9uTWFyZ2luCAUNJHQwMjkxMDgyOTIzNgJfMgQUcG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDAyOTEwODI5MjM2Al8zBBFwb3NpdGlvbkxzdFVwZENQRggFDSR0MDI5MTA4MjkyMzYCXzQEDXVucmVhbGl6ZWRQbmwICQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QCXzIEDSR0MDI5MzMxMjk0OTkJASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BAUMcG9zaXRpb25TaXplBQ5wb3NpdGlvbk1hcmdpbgURcG9zaXRpb25Mc3RVcGRDUEYFDXVucmVhbGl6ZWRQbmwEDHJlbWFpbk1hcmdpbggFDSR0MDI5MzMxMjk0OTkCXzEEB2JhZERlYnQIBQ0kdDAyOTMzMTI5NDk5Al8yBBVleGNoYW5nZWRQb3NpdGlvblNpemUJAQEtAQUMcG9zaXRpb25TaXplBAtyZWFsaXplZFBubAUNdW5yZWFsaXplZFBubAQNbWFyZ2luVG9WYXVsdAkBAS0BBQxyZW1haW5NYXJnaW4EDSR0MDI5NjI2Mjk5MDAJAQpzd2FwT3V0cHV0AwkAZgIFDHBvc2l0aW9uU2l6ZQAACQEDYWJzAQUMcG9zaXRpb25TaXplBRRfY2hlY2tNYXhQcmljZUltcGFjdAQZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAgFDSR0MDI5NjI2Mjk5MDACXzEEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDAyOTYyNjI5OTAwAl8yBBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDAyOTYyNjI5OTAwAl8zBBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwMjk2MjYyOTkwMAJfNAQOdG90YWxMb25nQWZ0ZXIIBQ0kdDAyOTYyNjI5OTAwAl81BA90b3RhbFNob3J0QWZ0ZXIIBQ0kdDAyOTYyNjI5OTAwAl82BBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCQBlAgkBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAAUUcG9zaXRpb25PcGVuTm90aW9uYWwJAJ8KDQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplBQdiYWREZWJ0BQtyZWFsaXplZFBubAUNbWFyZ2luVG9WYXVsdAUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyCQBlAgkBEG9wZW5JbnRlcmVzdExvbmcAAwkAZgIFDHBvc2l0aW9uU2l6ZQAABRRwb3NpdGlvbk9wZW5Ob3Rpb25hbAAACQBlAgkBEW9wZW5JbnRlcmVzdFNob3J0AAMJAGYCAAAFDHBvc2l0aW9uU2l6ZQUUcG9zaXRpb25PcGVuTm90aW9uYWwAAAEQZ2V0VHdhcFNwb3RQcmljZQAECG1pbnV0ZUlkCQBpAgkAaQIIBQlsYXN0QmxvY2sJdGltZXN0YW1wAOgHADwEDXN0YXJ0TWludXRlSWQJAGUCBQhtaW51dGVJZAUNVFdBUF9JTlRFUlZBTAQHbGlzdFN0cgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzBQ1rX2xhc3REYXRhU3RyAgAEBGxpc3QJALUJAgUHbGlzdFN0cgIBLAoBCGZpbHRlckZuAgthY2N1bXVsYXRvcgRuZXh0AwkAZwIFDXN0YXJ0TWludXRlSWQJAQ1wYXJzZUludFZhbHVlAQUEbmV4dAkAzQgCBQthY2N1bXVsYXRvcgkBDXBhcnNlSW50VmFsdWUBBQRuZXh0BQthY2N1bXVsYXRvcgQFbGlzdEYKAAIkbAUEbGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEIZmlsdGVyRm4CBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDIwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAA0ADgAPABAAEQASABMAFAQIbWF4SW5kZXgDCQBmAgkAkAMBBQVsaXN0RgAACQCWAwEFBWxpc3RGCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUEbGlzdAAABAxsYXN0TWludXRlSWQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUOa19sYXN0TWludXRlSWQAAAQWZW5kTGFzdEN1bXVsYXRpdmVQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UCAV8JAKQDAQUMbGFzdE1pbnV0ZUlkAAAEDGVuZExhc3RQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUTa190d2FwRGF0YUxhc3RQcmljZQIBXwkApAMBBQxsYXN0TWludXRlSWQAAAQSbm93Q3VtdWxhdGl2ZVByaWNlCQBkAgUWZW5kTGFzdEN1bXVsYXRpdmVQcmljZQkAaAIJAGUCBQhtaW51dGVJZAUMbGFzdE1pbnV0ZUlkBQxlbmRMYXN0UHJpY2UEGHN0YXJ0TGFzdEN1bXVsYXRpdmVQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UCAV8JAKQDAQUIbWF4SW5kZXgAAAQOc3RhcnRMYXN0UHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkArAICCQCsAgIFE2tfdHdhcERhdGFMYXN0UHJpY2UCAV8JAKQDAQUIbWF4SW5kZXgAAAQUc3RhcnRDdW11bGF0aXZlUHJpY2UJAGQCBRhzdGFydExhc3RDdW11bGF0aXZlUHJpY2UJAGgCCQBlAgUNc3RhcnRNaW51dGVJZAUIbWF4SW5kZXgFDnN0YXJ0TGFzdFByaWNlCQBpAgkAZQIFEm5vd0N1bXVsYXRpdmVQcmljZQUUc3RhcnRDdW11bGF0aXZlUHJpY2UFDVRXQVBfSU5URVJWQUwBE2dldFRlcm1pbmFsQW1tU3RhdGUABA1fcG9zaXRpb25TaXplCQERdG90YWxQb3NpdGlvblNpemUAAwkAAAIFDV9wb3NpdGlvblNpemUAAAkAlAoCCQEGcXRBc3RSAAkBBmJzQXN0UgAECWRpcmVjdGlvbgkAZgIFDV9wb3NpdGlvblNpemUAAAQNJHQwMzIwMjMzMjIwMgkBCnN3YXBPdXRwdXQDBQlkaXJlY3Rpb24JAQNhYnMBBQ1fcG9zaXRpb25TaXplBwQVY3VycmVudE5ldE1hcmtldFZhbHVlCAUNJHQwMzIwMjMzMjIwMgJfMQQZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQgFDSR0MDMyMDIzMzIyMDICXzIEGHRlcm1pbmFsQmFzZUFzc2V0UmVzZXJ2ZQgFDSR0MDMyMDIzMzIyMDICXzMJAJQKAgUZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQUYdGVybWluYWxCYXNlQXNzZXRSZXNlcnZlARNnZXRRdW90ZUFzc2V0V2VpZ2h0BBBiYXNlQXNzZXRSZXNlcnZlEXRvdGFsUG9zaXRpb25TaXplEXF1b3RlQXNzZXRSZXNlcnZlC3RhcmdldFByaWNlBAFiCQC2AgEFEGJhc2VBc3NldFJlc2VydmUEAnN6CQC2AgEFEXRvdGFsUG9zaXRpb25TaXplBAFxCQC2AgEFEXF1b3RlQXNzZXRSZXNlcnZlBAFwCQC2AgEFC3RhcmdldFByaWNlBAFrCQEFYm11bGQCBQFxBQFiBARuZXdCCQC3AgIFAWIFAnN6BARuZXdRCQEFYmRpdmQCBQFrBQRuZXdCBAF6CQEFYmRpdmQCBQRuZXdRBQRuZXdCBAZyZXN1bHQJAQViZGl2ZAIFAXAFAXoJAKADAQUGcmVzdWx0ARRnZXRTeW5jVGVybWluYWxQcmljZQMOX3Rlcm1pbmFsUHJpY2UHX3F0QXN0UgdfYnNBc3RSBA1fcG9zaXRpb25TaXplCQERdG90YWxQb3NpdGlvblNpemUAAwkAAAIFDV9wb3NpdGlvblNpemUAAAQJbmV3UXRBc3RXCQEEZGl2ZAIJAQRtdWxkAgUOX3Rlcm1pbmFsUHJpY2UFB19ic0FzdFIFB19xdEFzdFIJAJUKAwUJbmV3UXRBc3RXBQxERUNJTUFMX1VOSVQAAAQJZGlyZWN0aW9uCQBmAgUNX3Bvc2l0aW9uU2l6ZQAABBVjdXJyZW50TmV0TWFya2V0VmFsdWUICQEKc3dhcE91dHB1dAMFCWRpcmVjdGlvbgkBA2FicwEFDV9wb3NpdGlvblNpemUHAl8xBAluZXdRdEFzdFcJARNnZXRRdW90ZUFzc2V0V2VpZ2h0BAUHX2JzQXN0UgUNX3Bvc2l0aW9uU2l6ZQUHX3F0QXN0UgUOX3Rlcm1pbmFsUHJpY2UECW5ld0JzQXN0VwUMREVDSU1BTF9VTklUBA1tYXJnaW5Ub1ZhdWx0CAkBK2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sQnlWYWx1ZXMHBQ1fcG9zaXRpb25TaXplBRVjdXJyZW50TmV0TWFya2V0VmFsdWUFB19xdEFzdFIFCW5ld1F0QXN0VwUHX2JzQXN0UgUJbmV3QnNBc3RXBQ9QTkxfT1BUSU9OX1NQT1QCXzIJAJUKAwUJbmV3UXRBc3RXBQluZXdCc0FzdFcFDW1hcmdpblRvVmF1bHQBCmdldEZ1bmRpbmcABA91bmRlcmx5aW5nUHJpY2UJAQ5nZXRPcmFjbGVQcmljZQAEDXNwb3RUd2FwUHJpY2UJARBnZXRUd2FwU3BvdFByaWNlAAQHcHJlbWl1bQkAZQIFDXNwb3RUd2FwUHJpY2UFD3VuZGVybHlpbmdQcmljZQMDAwkAAAIJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAAABgkAAAIJARV0b3RhbExvbmdQb3NpdGlvblNpemUAAAAGCQEOaXNNYXJrZXRDbG9zZWQACQCUCgIAAAAAAwkAZgIAAAUHcHJlbWl1bQQUc2hvcnRQcmVtaXVtRnJhY3Rpb24JAQRkaXZkAgkBBG11bGQCBQdwcmVtaXVtCQEUZnVuZGluZ1BlcmlvZERlY2ltYWwABQdPTkVfREFZBBNsb25nUHJlbWl1bUZyYWN0aW9uCQEEZGl2ZAIJAQRtdWxkAgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24JARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQAJAJQKAgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24FE2xvbmdQcmVtaXVtRnJhY3Rpb24EE2xvbmdQcmVtaXVtRnJhY3Rpb24JAQRkaXZkAgkBBG11bGQCBQdwcmVtaXVtCQEUZnVuZGluZ1BlcmlvZERlY2ltYWwABQdPTkVfREFZBBRzaG9ydFByZW1pdW1GcmFjdGlvbgkBBGRpdmQCCQEEbXVsZAIFE2xvbmdQcmVtaXVtRnJhY3Rpb24JARV0b3RhbExvbmdQb3NpdGlvblNpemUACQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAJAJQKAgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24FE2xvbmdQcmVtaXVtRnJhY3Rpb24BDmdldEFkanVzdGVkRmVlAgtfYXJ0aWZhY3RJZBBfYmFzZUZlZURpc2NvdW50BApiYXNlRmVlUmF3CQEDZmVlAAQHYmFzZUZlZQkBBG11bGQCBQpiYXNlRmVlUmF3BRBfYmFzZUZlZURpc2NvdW50BA0kdDAzNTA2MzM1NTU4AwkBAiE9AgULX2FydGlmYWN0SWQCAAQMYXJ0aWZhY3RLaW5kCQEEc3RyQQIJARFuZnRNYW5hZ2VyQWRkcmVzcwAJAQ50b0NvbXBvc2l0ZUtleQIFDGtfdG9rZW5fdHlwZQULX2FydGlmYWN0SWQDCQAAAgUMYXJ0aWZhY3RLaW5kBRhGRUVfUkVEVUNUSU9OX1RPS0VOX1RZUEUECXJlZHVjdGlvbgkBBGludEECCQERbmZ0TWFuYWdlckFkZHJlc3MACQEOdG9Db21wb3NpdGVLZXkCBQ1rX3Rva2VuX3BhcmFtBQtfYXJ0aWZhY3RJZAQLYWRqdXN0ZWRGZWUJAQRtdWxkAgUHYmFzZUZlZQUJcmVkdWN0aW9uCQCUCgIFC2FkanVzdGVkRmVlBgkAAgECGUludmFsaWQgYXR0YWNoZWQgYXJ0aWZhY3QJAJQKAgUHYmFzZUZlZQcEC2FkanVzdGVkRmVlCAUNJHQwMzUwNjMzNTU1OAJfMQQMYnVybkFydGlmYWN0CAUNJHQwMzUwNjMzNTU1OAJfMgkAlAoCBQthZGp1c3RlZEZlZQUMYnVybkFydGlmYWN0ARdpc1NhbWVBc3NldE9yTm9Qb3NpdGlvbgIHX3RyYWRlcghfYXNzZXRJZAQPb2xkUG9zaXRpb25TaXplCAkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgJfMQMJAAACBQ9vbGRQb3NpdGlvblNpemUAAAYJAAACCQEQZ2V0UG9zaXRpb25Bc3NldAEFB190cmFkZXIFCF9hc3NldElkAQtpc1NhbWVBc3NldAIHX3RyYWRlcghfYXNzZXRJZAkAAAIJARBnZXRQb3NpdGlvbkFzc2V0AQUHX3RyYWRlcgUIX2Fzc2V0SWQBHmdldEJvcnJvd2VkQnlUcmFkZXJJbk1hcmtldEtleQMEX2FtbQhfYXNzZXRJZAdfdHJhZGVyCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICBSBrX3RyYWRlcl9tYXJrZXRfYXNzZXRfY29sbGF0ZXJhbAIBXwUEX2FtbQIBXwUIX2Fzc2V0SWQCAV8FB190cmFkZXIBE2dldEJvcnJvd2VkQnlUcmFkZXIBB190cmFkZXIEDXBvc2l0aW9uQXNzZXQJARBnZXRQb3NpdGlvbkFzc2V0AQUHX3RyYWRlcgMJAAACBQ1wb3NpdGlvbkFzc2V0CQDYBAEJAQpxdW90ZUFzc2V0AAkAlAoCAAAFDXBvc2l0aW9uQXNzZXQEA2tleQkBHmdldEJvcnJvd2VkQnlUcmFkZXJJbk1hcmtldEtleQMJAKUIAQUEdGhpcwUNcG9zaXRpb25Bc3NldAUHX3RyYWRlcgQGYm9ycm93CQELdmFsdWVPckVsc2UCCQCaCAIJARFjb2xsYXRlcmFsQWRkcmVzcwAFA2tleQAACQCUCgIFBmJvcnJvdwUNcG9zaXRpb25Bc3NldAEYZ2V0Rm9yVHJhZGVyV2l0aEFydGlmYWN0AgdfdHJhZGVyC19hcnRpZmFjdElkBBBkb0dldEZlZURpc2NvdW50CQD8BwQJAQxtaW5lckFkZHJlc3MAAhJjb21wdXRlRmVlRGlzY291bnQJAMwIAgUHX3RyYWRlcgUDbmlsBQNuaWwDCQAAAgUQZG9HZXRGZWVEaXNjb3VudAUQZG9HZXRGZWVEaXNjb3VudAQLZmVlRGlzY291bnQEByRtYXRjaDAFEGRvR2V0RmVlRGlzY291bnQDCQABAgUHJG1hdGNoMAIDSW50BAF4BQckbWF0Y2gwBQF4CQACAQIhSW52YWxpZCBjb21wdXRlRmVlRGlzY291bnQgcmVzdWx0BA0kdDAzNjc4OTM2ODYzCQEOZ2V0QWRqdXN0ZWRGZWUCBQtfYXJ0aWZhY3RJZAULZmVlRGlzY291bnQEC2FkanVzdGVkRmVlCAUNJHQwMzY3ODkzNjg2MwJfMQQMYnVybkFydGlmYWN0CAUNJHQwMzY3ODkzNjg2MwJfMgkAlAoCBQthZGp1c3RlZEZlZQUMYnVybkFydGlmYWN0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQ1nZXRBcnRpZmFjdElkAQFpBAphcnRpZmFjdElkAwkAZgIJAJADAQgFAWkIcGF5bWVudHMAAQkA2AQBCQETdmFsdWVPckVycm9yTWVzc2FnZQIICQCRAwIIBQFpCHBheW1lbnRzAAEHYXNzZXRJZAISSW52YWxpZCBhcnRpZmFjdElkAgAFCmFydGlmYWN0SWQBDWRpc3RyaWJ1dGVGZWUBCl9mZWVBbW91bnQEDGZlZVRvU3Rha2VycwkBBG11bGQCBQpfZmVlQW1vdW50CQETZmVlVG9TdGFrZXJzUGVyY2VudAAECmZlZVRvVmF1bHQJAGUCBQpfZmVlQW1vdW50BQxmZWVUb1N0YWtlcnMJAJQKAgUMZmVlVG9TdGFrZXJzBQpmZWVUb1ZhdWx0AQ51cGRhdGVTZXR0aW5ncwwQX2luaXRNYXJnaW5SYXRpbwRfbW1yFF9saXF1aWRhdGlvbkZlZVJhdGlvDl9mdW5kaW5nUGVyaW9kBF9mZWUMX3NwcmVhZExpbWl0D19tYXhQcmljZUltcGFjdBhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8PX21heFByaWNlU3ByZWFkEF9tYXhPcGVuTm90aW9uYWwUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQPX21heE9yYWNsZURlbGF5CQDMCAIJAQxJbnRlZ2VyRW50cnkCBRFrX2luaXRNYXJnaW5SYXRpbwUQX2luaXRNYXJnaW5SYXRpbwkAzAgCCQEMSW50ZWdlckVudHJ5AgUYa19tYWludGVuYW5jZU1hcmdpblJhdGlvBQRfbW1yCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRVrX2xpcXVpZGF0aW9uRmVlUmF0aW8FFF9saXF1aWRhdGlvbkZlZVJhdGlvCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ9rX2Z1bmRpbmdQZXJpb2QFDl9mdW5kaW5nUGVyaW9kCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQVrX2ZlZQUEX2ZlZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUNa19zcHJlYWRMaW1pdAUMX3NwcmVhZExpbWl0CQDMCAIJAQxJbnRlZ2VyRW50cnkCBRBrX21heFByaWNlSW1wYWN0BQ9fbWF4UHJpY2VJbXBhY3QJAMwIAgkBDEludGVnZXJFbnRyeQIFGWtfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8FGF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwkAzAgCCQEMSW50ZWdlckVudHJ5AgUQa19tYXhQcmljZVNwcmVhZAUPX21heFByaWNlU3ByZWFkCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRFrX21heE9wZW5Ob3Rpb25hbAUQX21heE9wZW5Ob3Rpb25hbAkAzAgCCQEMSW50ZWdlckVudHJ5AgUVa19mZWVUb1N0YWtlcnNQZXJjZW50BRRfZmVlVG9TdGFrZXJzUGVyY2VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgUQa19tYXhPcmFjbGVEZWxheQUUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQFA25pbAENdXBkYXRlRnVuZGluZwURX25leHRGdW5kaW5nQmxvY2skX2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uJV9sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24QX2xvbmdGdW5kaW5nUmF0ZRFfc2hvcnRGdW5kaW5nUmF0ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUSa19uZXh0RnVuZGluZ0Jsb2NrBRFfbmV4dEZ1bmRpbmdCbG9jawkAzAgCCQEMSW50ZWdlckVudHJ5AgUla19sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUkX2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uCQDMCAIJAQxJbnRlZ2VyRW50cnkCBSZrX2xhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUlX2xhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgURa19sb25nRnVuZGluZ1JhdGUFEF9sb25nRnVuZGluZ1JhdGUJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfc2hvcnRGdW5kaW5nUmF0ZQURX3Nob3J0RnVuZGluZ1JhdGUFA25pbAETdXBkYXRlUG9zaXRpb25Bc3NldAIIX2FkZHJlc3MIX2Fzc2V0SWQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUPa19wb3NpdGlvbkFzc2V0BQhfYWRkcmVzcwUIX2Fzc2V0SWQFA25pbAEfaW5jcmVtZW50UG9zaXRpb25TZXF1ZW5jZU51bWJlcgIOX2lzTmV3UG9zaXRpb24IX2FkZHJlc3MDBQ5faXNOZXdQb3NpdGlvbgQPY3VycmVudFNlcXVlbmNlCQEMbGFzdFNlcXVlbmNlAAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUSa19wb3NpdGlvblNlcXVlbmNlBQhfYWRkcmVzcwkAZAIFD2N1cnJlbnRTZXF1ZW5jZQABCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQprX3NlcXVlbmNlCQBkAgUPY3VycmVudFNlcXVlbmNlAAEFA25pbAUDbmlsARF1cGRhdGVQb3NpdGlvbkZlZQMOX2lzTmV3UG9zaXRpb24IX2FkZHJlc3MEX2ZlZQMFDl9pc05ld1Bvc2l0aW9uCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBQ1rX3Bvc2l0aW9uRmVlBQhfYWRkcmVzcwUEX2ZlZQUDbmlsBQNuaWwBDnVwZGF0ZVBvc2l0aW9uBQhfYWRkcmVzcwVfc2l6ZQdfbWFyZ2luDV9vcGVuTm90aW9uYWwgX2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24JAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFDmtfcG9zaXRpb25TaXplBQhfYWRkcmVzcwUFX3NpemUJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFEGtfcG9zaXRpb25NYXJnaW4FCF9hZGRyZXNzBQdfbWFyZ2luCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBQhfYWRkcmVzcwUNX29wZW5Ob3Rpb25hbAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUua19wb3NpdGlvbkxhc3RVcGRhdGVkQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUIX2FkZHJlc3MFIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBQNuaWwBCmFwcGVuZFR3YXABBl9wcmljZQQIbWludXRlSWQJAGkCCQBpAggFCWxhc3RCbG9jawl0aW1lc3RhbXAA6AcAPAQQcHJldmlvdXNNaW51dGVJZAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQ5rX2xhc3RNaW51dGVJZAAAAwkAZgIFEHByZXZpb3VzTWludXRlSWQFCG1pbnV0ZUlkCQACAQIRVFdBUCBvdXQtb2Ytb3JkZXIEDGxhc3RNaW51dGVJZAMJAAACBRBwcmV2aW91c01pbnV0ZUlkAAAFCG1pbnV0ZUlkBRBwcmV2aW91c01pbnV0ZUlkAwkAZgIFCG1pbnV0ZUlkBRBwcmV2aW91c01pbnV0ZUlkBBNwcmV2Q3VtdWxhdGl2ZVByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAKwCAgkArAICBR1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQIBXwkApAMBBRBwcmV2aW91c01pbnV0ZUlkAAAECXByZXZQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUTa190d2FwRGF0YUxhc3RQcmljZQIBXwkApAMBBRBwcmV2aW91c01pbnV0ZUlkBQZfcHJpY2UEE2xhc3RDdW11bGF0aXZlUHJpY2UJAGQCBRNwcmV2Q3VtdWxhdGl2ZVByaWNlCQBoAgkAZQIFCG1pbnV0ZUlkBQxsYXN0TWludXRlSWQFCXByZXZQcmljZQQEbGlzdAkBC3B1c2hUb1F1ZXVlAwkBCXN0clRvTGlzdAEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwUNa19sYXN0RGF0YVN0cgIABQ1UV0FQX0lOVEVSVkFMCQCkAwEFCG1pbnV0ZUlkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBR1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQkApAMBBQhtaW51dGVJZAUTbGFzdEN1bXVsYXRpdmVQcmljZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUTa190d2FwRGF0YUxhc3RQcmljZQkApAMBBQhtaW51dGVJZAUGX3ByaWNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRprX3R3YXBEYXRhUHJldmlvdXNNaW51dGVJZAkApAMBBQhtaW51dGVJZAUQcHJldmlvdXNNaW51dGVJZAkAzAgCCQEMSW50ZWdlckVudHJ5AgUOa19sYXN0TWludXRlSWQFCG1pbnV0ZUlkCQDMCAIJAQtTdHJpbmdFbnRyeQIFDWtfbGFzdERhdGFTdHIJAQlsaXN0VG9TdHIBBQRsaXN0BQNuaWwEGHR3YXBEYXRhUHJldmlvdXNNaW51dGVJZAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBRprX3R3YXBEYXRhUHJldmlvdXNNaW51dGVJZAkApAMBBQhtaW51dGVJZAAABBNwcmV2Q3VtdWxhdGl2ZVByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlCQCkAwEFGHR3YXBEYXRhUHJldmlvdXNNaW51dGVJZAAABAlwcmV2UHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUTa190d2FwRGF0YUxhc3RQcmljZQkApAMBBRh0d2FwRGF0YVByZXZpb3VzTWludXRlSWQFBl9wcmljZQQTbGFzdEN1bXVsYXRpdmVQcmljZQkAZAIFE3ByZXZDdW11bGF0aXZlUHJpY2UJAGgCCQBlAgUIbWludXRlSWQFGHR3YXBEYXRhUHJldmlvdXNNaW51dGVJZAUJcHJldlByaWNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBR1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQkApAMBBQhtaW51dGVJZAUTbGFzdEN1bXVsYXRpdmVQcmljZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUTa190d2FwRGF0YUxhc3RQcmljZQkApAMBBQhtaW51dGVJZAUGX3ByaWNlBQNuaWwBEXVwZGF0ZUFtbVJlc2VydmVzAgdfcXRBc3RSB19ic0FzdFIJAMwIAgkBDEludGVnZXJFbnRyeQIFE2tfcXVvdGVBc3NldFJlc2VydmUFB19xdEFzdFIJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfYmFzZUFzc2V0UmVzZXJ2ZQUHX2JzQXN0UgUDbmlsARB1cGRhdGVBbW1XZWlnaHRzAgdfcXRBc3RXB19ic0FzdFcJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfcXVvdGVBc3NldFdlaWdodAUHX3F0QXN0VwkAzAgCCQEMSW50ZWdlckVudHJ5AgURa19iYXNlQXNzZXRXZWlnaHQFB19ic0FzdFcFA25pbAEJdXBkYXRlQW1tCAdfcXRBc3RSB19ic0FzdFIXX3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIVX29wZW5JbnRlcmVzdE5vdGlvbmFsFl90b3RhbExvbmdQb3NpdGlvblNpemUXX3RvdGFsU2hvcnRQb3NpdGlvblNpemUWX3RvdGFsTG9uZ09wZW5Ob3Rpb25hbBdfdG90YWxTaG9ydE9wZW5Ob3Rpb25hbAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcAAwkBAiE9AgkAZQIFFl90b3RhbExvbmdQb3NpdGlvblNpemUFF190b3RhbFNob3J0UG9zaXRpb25TaXplBRdfdG90YWxQb3NpdGlvblNpemVBZnRlcgkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAhhJbnZhbGlkIEFNTSBzdGF0ZSBkYXRhOiAJAKQDAQUWX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQIEICsgIAkApAMBBRdfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQIEICE9IAkApAMBBRdfdG90YWxQb3NpdGlvblNpemVBZnRlcgkAzggCCQDOCAIJARF1cGRhdGVBbW1SZXNlcnZlcwIFB19xdEFzdFIFB19ic0FzdFIJAMwIAgkBDEludGVnZXJFbnRyeQIFE2tfdG90YWxQb3NpdGlvblNpemUFF190b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRZrX29wZW5JbnRlcmVzdE5vdGlvbmFsBRVfb3BlbkludGVyZXN0Tm90aW9uYWwJAMwIAgkBDEludGVnZXJFbnRyeQIFF2tfdG90YWxMb25nUG9zaXRpb25TaXplBRZfdG90YWxMb25nUG9zaXRpb25TaXplCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRhrX3RvdGFsU2hvcnRQb3NpdGlvblNpemUFF190b3RhbFNob3J0UG9zaXRpb25TaXplCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJrX29wZW5JbnRlcmVzdExvbmcFFl90b3RhbExvbmdPcGVuTm90aW9uYWwJAMwIAgkBDEludGVnZXJFbnRyeQIFE2tfb3BlbkludGVyZXN0U2hvcnQFF190b3RhbFNob3J0T3Blbk5vdGlvbmFsBQNuaWwJAQphcHBlbmRUd2FwAQkBBGRpdmQCCQEEbXVsZAIFB19xdEFzdFIFB19xdEFzdFcJAQRtdWxkAgUHX2JzQXN0UgUHX2JzQXN0VwEOZGVsZXRlUG9zaXRpb24BCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFDmtfcG9zaXRpb25TaXplBQhfYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBRBrX3Bvc2l0aW9uTWFyZ2luBQhfYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBRZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBQhfYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBS5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBQhfYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBQ9rX3Bvc2l0aW9uQXNzZXQFCF9hZGRyZXNzBQNuaWwBCHdpdGhkcmF3AghfYWRkcmVzcwdfYW1vdW50BAdiYWxhbmNlCQDwBwIFBHRoaXMJAQpxdW90ZUFzc2V0AAMJAGYCBQdfYW1vdW50BQdiYWxhbmNlCQACAQkArAICCQCsAgIJAKwCAgITVW5hYmxlIHRvIHdpdGhkcmF3IAkApAMBBQdfYW1vdW50AhcgZnJvbSBjb250cmFjdCBiYWxhbmNlIAkApAMBBQdiYWxhbmNlCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFCF9hZGRyZXNzBQdfYW1vdW50CQEKcXVvdGVBc3NldAAFA25pbAENdXBkYXRlQmFsYW5jZQEBaQMJAGYCAAAFAWkJAAIBAgdCYWxhbmNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQlrX2JhbGFuY2UFAWkFA25pbAELdHJhbnNmZXJGZWUBAWkJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwkBDnN0YWtpbmdBZGRyZXNzAAUBaQkBCnF1b3RlQXNzZXQABQNuaWwBDmRvQnVybkFydGlmYWN0Ag1fYnVybkFydGlmYWN0AWkDBQ1fYnVybkFydGlmYWN0CQDMCAIJAQRCdXJuAgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCAkAkQMCCAUBaQhwYXltZW50cwABB2Fzc2V0SWQCEEludmFsaWQgYXJ0aWZhY3QAAQUDbmlsBQNuaWwWAWkBBXBhdXNlAAMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAhRJbnZhbGlkIHBhdXNlIHBhcmFtcwkAzAgCCQEMQm9vbGVhbkVudHJ5AgUIa19wYXVzZWQGBQNuaWwBaQEHdW5wYXVzZQADCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MACQACAQIWSW52YWxpZCB1bnBhdXNlIHBhcmFtcwkAzAgCCQEMQm9vbGVhbkVudHJ5AgUIa19wYXVzZWQHBQNuaWwBaQEMc2V0Q2xvc2VPbmx5AAMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAhtJbnZhbGlkIHNldENsb3NlT25seSBwYXJhbXMJAMwIAgkBDEJvb2xlYW5FbnRyeQIFC2tfY2xvc2VPbmx5BgUDbmlsAWkBDnVuc2V0Q2xvc2VPbmx5AAMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAh1JbnZhbGlkIHVuc2V0Q2xvc2VPbmx5IHBhcmFtcwkAzAgCCQEMQm9vbGVhbkVudHJ5AgULa19jbG9zZU9ubHkHBQNuaWwBaQEMYWRkTGlxdWlkaXR5ARFfcXVvdGVBc3NldEFtb3VudAMDCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MABgkAZwIAAAURX3F1b3RlQXNzZXRBbW91bnQJAAIBAhtJbnZhbGlkIGFkZExpcXVpZGl0eSBwYXJhbXMEB19xdEFzdFIJAQZxdEFzdFIABAdfYnNBc3RSCQEGYnNBc3RSAAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcABAVwcmljZQkBBGRpdmQCCQEEbXVsZAIFB19xdEFzdFIFB19xdEFzdFcJAQRtdWxkAgUHX2JzQXN0UgUHX2JzQXN0VwQLcXRBc3RSQWZ0ZXIJAGQCBQdfcXRBc3RSBRFfcXVvdGVBc3NldEFtb3VudAQUYmFzZUFzc2V0QW1vdW50VG9BZGQJAGUCCQEEZGl2ZAIJAQRtdWxkAgULcXRBc3RSQWZ0ZXIFB19xdEFzdFcFBXByaWNlBQdfYnNBc3RSBAtic0FzdFJBZnRlcgkAZAIFB19ic0FzdFIFFGJhc2VBc3NldEFtb3VudFRvQWRkBA0kdDA0NjEwNzQ2MjU4CQEUZ2V0U3luY1Rlcm1pbmFsUHJpY2UDCQEOZ2V0T3JhY2xlUHJpY2UABQtxdEFzdFJBZnRlcgULYnNBc3RSQWZ0ZXIEE25ld1F1b3RlQXNzZXRXZWlnaHQIBQ0kdDA0NjEwNzQ2MjU4Al8xBBJuZXdCYXNlQXNzZXRXZWlnaHQIBQ0kdDA0NjEwNzQ2MjU4Al8yBA1tYXJnaW5Ub1ZhdWx0CAUNJHQwNDYxMDc0NjI1OAJfMwQNZG9FeGNoYW5nZVBuTAMJAQIhPQIFDW1hcmdpblRvVmF1bHQAAAQNZG9FeGNoYW5nZVBuTAkA/AcECQEMdmF1bHRBZGRyZXNzAAIVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkCQDMCAIFDW1hcmdpblRvVmF1bHQFA25pbAUDbmlsAwkAAAIFDWRvRXhjaGFuZ2VQbkwFDWRvRXhjaGFuZ2VQbkwFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFDWRvRXhjaGFuZ2VQbkwFDWRvRXhjaGFuZ2VQbkwJAM4IAgkBEXVwZGF0ZUFtbVJlc2VydmVzAgULcXRBc3RSQWZ0ZXIFC2JzQXN0UkFmdGVyCQEQdXBkYXRlQW1tV2VpZ2h0cwIFE25ld1F1b3RlQXNzZXRXZWlnaHQFEm5ld0Jhc2VBc3NldFdlaWdodAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ9yZW1vdmVMaXF1aWRpdHkBEV9xdW90ZUFzc2V0QW1vdW50AwMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAGCQBnAgURX3F1b3RlQXNzZXRBbW91bnQAAAkAAgECHkludmFsaWQgcmVtb3ZlTGlxdWlkaXR5IHBhcmFtcwQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwAEBXByaWNlCQEEZGl2ZAIJAQRtdWxkAgUHX3F0QXN0UgUHX3F0QXN0VwkBBG11bGQCBQdfYnNBc3RSBQdfYnNBc3RXBAtxdEFzdFJBZnRlcgkAZQIFB19xdEFzdFIFEV9xdW90ZUFzc2V0QW1vdW50BBdiYXNlQXNzZXRBbW91bnRUb1JlbW92ZQkBA2FicwEJAGUCCQEEZGl2ZAIJAQRtdWxkAgULcXRBc3RSQWZ0ZXIFB19xdEFzdFcFBXByaWNlBQdfYnNBc3RSBAtic0FzdFJBZnRlcgkAZQIFB19ic0FzdFIFF2Jhc2VBc3NldEFtb3VudFRvUmVtb3ZlBA0kdDA0NzE5MDQ3MzQxCQEUZ2V0U3luY1Rlcm1pbmFsUHJpY2UDCQEOZ2V0T3JhY2xlUHJpY2UABQtxdEFzdFJBZnRlcgULYnNBc3RSQWZ0ZXIEE25ld1F1b3RlQXNzZXRXZWlnaHQIBQ0kdDA0NzE5MDQ3MzQxAl8xBBJuZXdCYXNlQXNzZXRXZWlnaHQIBQ0kdDA0NzE5MDQ3MzQxAl8yBA1tYXJnaW5Ub1ZhdWx0CAUNJHQwNDcxOTA0NzM0MQJfMwQNZG9FeGNoYW5nZVBuTAMJAQIhPQIFDW1hcmdpblRvVmF1bHQAAAQNZG9FeGNoYW5nZVBuTAkA/AcECQEMdmF1bHRBZGRyZXNzAAIVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkCQDMCAIFDW1hcmdpblRvVmF1bHQFA25pbAUDbmlsAwkAAAIFDWRvRXhjaGFuZ2VQbkwFDWRvRXhjaGFuZ2VQbkwFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFDWRvRXhjaGFuZ2VQbkwFDWRvRXhjaGFuZ2VQbkwJAM4IAgkBEXVwZGF0ZUFtbVJlc2VydmVzAgULcXRBc3RSQWZ0ZXIFC2JzQXN0UkFmdGVyCQEQdXBkYXRlQW1tV2VpZ2h0cwIFE25ld1F1b3RlQXNzZXRXZWlnaHQFEm5ld0Jhc2VBc3NldFdlaWdodAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ5jaGFuZ2VTZXR0aW5ncwwQX2luaXRNYXJnaW5SYXRpbwRfbW1yFF9saXF1aWRhdGlvbkZlZVJhdGlvDl9mdW5kaW5nUGVyaW9kBF9mZWUMX3NwcmVhZExpbWl0D19tYXhQcmljZUltcGFjdBhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8PX21heFByaWNlU3ByZWFkEF9tYXhPcGVuTm90aW9uYWwUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQPX21heE9yYWNsZURlbGF5AwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECHUludmFsaWQgY2hhbmdlU2V0dGluZ3MgcGFyYW1zCQEOdXBkYXRlU2V0dGluZ3MMBRBfaW5pdE1hcmdpblJhdGlvBQRfbW1yBRRfbGlxdWlkYXRpb25GZWVSYXRpbwUOX2Z1bmRpbmdQZXJpb2QFBF9mZWUFDF9zcHJlYWRMaW1pdAUPX21heFByaWNlSW1wYWN0BRhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8FD19tYXhQcmljZVNwcmVhZAUQX21heE9wZW5Ob3Rpb25hbAUUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQFD19tYXhPcmFjbGVEZWxheQFpAQppbml0aWFsaXplEgdfcXRBc3RSB19ic0FzdFIOX2Z1bmRpbmdQZXJpb2QQX2luaXRNYXJnaW5SYXRpbwRfbW1yFF9saXF1aWRhdGlvbkZlZVJhdGlvBF9mZWUHX29yYWNsZQpfb3JhY2xlS2V5D19vcmFjbGVCbG9ja0tleQxfY29vcmRpbmF0b3IMX3NwcmVhZExpbWl0D19tYXhQcmljZUltcGFjdBhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8PX21heFByaWNlU3ByZWFkEF9tYXhPcGVuTm90aW9uYWwUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQPX21heE9yYWNsZURlbGF5AwMDAwMDAwMDAwMDAwMDAwkAZwIAAAUHX3F0QXN0UgYJAGcCAAAFB19ic0FzdFIGCQBnAgAABQ5fZnVuZGluZ1BlcmlvZAYJAGcCAAAFEF9pbml0TWFyZ2luUmF0aW8GCQBnAgAABQRfbW1yBgkAZwIAAAUUX2xpcXVpZGF0aW9uRmVlUmF0aW8GCQBnAgAABQRfZmVlBgkAZwIAAAUMX3NwcmVhZExpbWl0BgkAZwIAAAUPX21heFByaWNlSW1wYWN0BgkAZwIAAAUYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvBgkAZwIAAAUPX21heFByaWNlU3ByZWFkBgkAZwIAAAUQX21heE9wZW5Ob3Rpb25hbAYJAGcCAAAFFF9mZWVUb1N0YWtlcnNQZXJjZW50BgkAZgIFFF9mZWVUb1N0YWtlcnNQZXJjZW50BQxERUNJTUFMX1VOSVQGCQBnAgAABQ9fbWF4T3JhY2xlRGVsYXkGCQELaW5pdGlhbGl6ZWQACQACAQIdSW52YWxpZCBpbml0aWFsaXplIHBhcmFtZXRlcnMJAM4IAgkAzggCCQDOCAIJAM4IAgkBCXVwZGF0ZUFtbQgFB19xdEFzdFIFB19ic0FzdFIAAAAAAAAAAAAAAAAJAQ51cGRhdGVTZXR0aW5ncwwFEF9pbml0TWFyZ2luUmF0aW8FBF9tbXIFFF9saXF1aWRhdGlvbkZlZVJhdGlvBQ5fZnVuZGluZ1BlcmlvZAUEX2ZlZQUMX3NwcmVhZExpbWl0BQ9fbWF4UHJpY2VJbXBhY3QFGF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwUPX21heFByaWNlU3ByZWFkBRBfbWF4T3Blbk5vdGlvbmFsBRRfZmVlVG9TdGFrZXJzUGVyY2VudAUPX21heE9yYWNsZURlbGF5CQENdXBkYXRlRnVuZGluZwUJAGQCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAUOX2Z1bmRpbmdQZXJpb2QAAAAAAAAAAAkBDXVwZGF0ZUJhbGFuY2UBAAAJAMwIAgkBDEJvb2xlYW5FbnRyeQIFDWtfaW5pdGlhbGl6ZWQGCQDMCAIJAQtTdHJpbmdFbnRyeQIFBWtfb3JhBQdfb3JhY2xlCQDMCAIJAQtTdHJpbmdFbnRyeQIFCWtfb3JhX2tleQUKX29yYWNsZUtleQkAzAgCCQELU3RyaW5nRW50cnkCBQ9rX29yYV9ibG9ja19rZXkFD19vcmFjbGVCbG9ja0tleQkAzAgCCQELU3RyaW5nRW50cnkCBRRrX2Nvb3JkaW5hdG9yQWRkcmVzcwUMX2Nvb3JkaW5hdG9yBQNuaWwBaQEQaW5jcmVhc2VQb3NpdGlvbgQKX2RpcmVjdGlvbglfbGV2ZXJhZ2UTX21pbkJhc2VBc3NldEFtb3VudAhfcmVmTGluawQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBAdfdHJhZGVyCQEPZ2V0QWN0dWFsQ2FsbGVyAQUBaQQKX3Jhd0Ftb3VudAgJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQECF9hc3NldElkCAkAkQMCCAUBaQhwYXltZW50cwAAB2Fzc2V0SWQEC19hc3NldElkU3RyCQDYBAEJAQV2YWx1ZQEFCF9hc3NldElkBAxpc1F1b3RlQXNzZXQJAAACBQhfYXNzZXRJZAkBCnF1b3RlQXNzZXQABBFpc0NvbGxhdGVyYWxBc3NldAkBEGlzV2hpdGVsaXN0QXNzZXQBBQtfYXNzZXRJZFN0cgMDAwMDAwMDAwMJAQIhPQIFCl9kaXJlY3Rpb24FCERJUl9MT05HCQECIT0CBQpfZGlyZWN0aW9uBQlESVJfU0hPUlQHBgkAZwIAAAUKX3Jhd0Ftb3VudAYJAQEhAQkBC2luaXRpYWxpemVkAAYDCQEBIQEFDGlzUXVvdGVBc3NldAkBASEBBRFpc0NvbGxhdGVyYWxBc3NldAcGCQEBIQEJARdpc1NhbWVBc3NldE9yTm9Qb3NpdGlvbgIFB190cmFkZXIFC19hc3NldElkU3RyBgkBASEBCQEWcmVxdWlyZU1vcmVNYXJnaW5SYXRpbwMJAQRkaXZkAgUMREVDSU1BTF9VTklUBQlfbGV2ZXJhZ2UJAQ9pbml0TWFyZ2luUmF0aW8ABgYJAQZwYXVzZWQABgkBCWNsb3NlT25seQAGCQEOaXNNYXJrZXRDbG9zZWQACQACAQIjSW52YWxpZCBpbmNyZWFzZVBvc2l0aW9uIHBhcmFtZXRlcnMEDSR0MDUxMDA5NTExNTgJARhnZXRGb3JUcmFkZXJXaXRoQXJ0aWZhY3QCBQdfdHJhZGVyCQENZ2V0QXJ0aWZhY3RJZAEFAWkEC2FkanVzdGVkRmVlCAUNJHQwNTEwMDk1MTE1OAJfMQQMYnVybkFydGlmYWN0CAUNJHQwNTEwMDk1MTE1OAJfMgQHX2Ftb3VudAkBBGRpdmQCBQpfcmF3QW1vdW50CQBkAgkBBG11bGQCBQthZGp1c3RlZEZlZQUJX2xldmVyYWdlBQxERUNJTUFMX1VOSVQEDHJhd0ZlZUFtb3VudAkAZQIFCl9yYXdBbW91bnQFB19hbW91bnQEE2Rpc3RyaWJ1dGVGZWVBbW91bnQDBRFpc0NvbGxhdGVyYWxBc3NldAQIZG9Cb3Jyb3cJAPwHBAkBEWNvbGxhdGVyYWxBZGRyZXNzAAIGYm9ycm93CQDMCAIFB190cmFkZXIFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUIX2Fzc2V0SWQFB19hbW91bnQFA25pbAMJAAACBQhkb0JvcnJvdwUIZG9Cb3Jyb3cEDWJhbGFuY2VCZWZvcmUJAPAHAgUEdGhpcwkBCnF1b3RlQXNzZXQAAwkAAAIFDWJhbGFuY2VCZWZvcmUFDWJhbGFuY2VCZWZvcmUEBmRvU3dhcAkA/AcECQELc3dhcEFkZHJlc3MAAgRzd2FwCQDMCAIJANgEAQkBCnF1b3RlQXNzZXQACQDMCAIAAAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQhfYXNzZXRJZAUMcmF3RmVlQW1vdW50BQNuaWwDCQAAAgUGZG9Td2FwBQZkb1N3YXAEDGJhbGFuY2VBZnRlcgkA8AcCBQR0aGlzCQEKcXVvdGVBc3NldAADCQAAAgUMYmFsYW5jZUFmdGVyBQxiYWxhbmNlQWZ0ZXIED2V4Y2hhbmdlZEFtb3VudAkAZQIFDGJhbGFuY2VBZnRlcgUNYmFsYW5jZUJlZm9yZQMJAAACBQ9leGNoYW5nZWRBbW91bnQFD2V4Y2hhbmdlZEFtb3VudAUPZXhjaGFuZ2VkQW1vdW50CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQxyYXdGZWVBbW91bnQDCQAAAgUTZGlzdHJpYnV0ZUZlZUFtb3VudAUTZGlzdHJpYnV0ZUZlZUFtb3VudAQOcmVmZXJyZXJGZWVBbnkJAPwHBAkBD3JlZmVycmFsQWRkcmVzcwACFWFjY2VwdFBheW1lbnRXaXRoTGluawkAzAgCBQdfdHJhZGVyCQDMCAIFCF9yZWZMaW5rBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUTZGlzdHJpYnV0ZUZlZUFtb3VudAUDbmlsAwkAAAIFDnJlZmVycmVyRmVlQW55BQ5yZWZlcnJlckZlZUFueQQLcmVmZXJyZXJGZWUEByRtYXRjaDAFDnJlZmVycmVyRmVlQW55AwkAAQIFByRtYXRjaDACA0ludAQBeAUHJG1hdGNoMAUBeAkAAgECE0ludmFsaWQgcmVmZXJyZXJGZWUECWZlZUFtb3VudAkAZQIFE2Rpc3RyaWJ1dGVGZWVBbW91bnQFC3JlZmVycmVyRmVlBA0kdDA1MjUwMDUyNjQwCQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBA9vbGRQb3NpdGlvblNpemUIBQ0kdDA1MjUwMDUyNjQwAl8xBBFvbGRQb3NpdGlvbk1hcmdpbggFDSR0MDUyNTAwNTI2NDACXzIEF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNTI1MDA1MjY0MAJfMwQUb2xkUG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA1MjUwMDUyNjQwAl80BA1pc05ld1Bvc2l0aW9uCQAAAgUPb2xkUG9zaXRpb25TaXplAAAED2lzU2FtZURpcmVjdGlvbgMJAGYCBQ9vbGRQb3NpdGlvblNpemUAAAkAAAIFCl9kaXJlY3Rpb24FCERJUl9MT05HCQAAAgUKX2RpcmVjdGlvbgUJRElSX1NIT1JUBA5leHBhbmRFeGlzdGluZwMJAQEhAQUNaXNOZXdQb3NpdGlvbgUPaXNTYW1lRGlyZWN0aW9uBwQFaXNBZGQJAAACBQpfZGlyZWN0aW9uBQhESVJfTE9ORwQNJHQwNTI5Mjk1NTg5MQMDBQ1pc05ld1Bvc2l0aW9uBgUOZXhwYW5kRXhpc3RpbmcEDG9wZW5Ob3Rpb25hbAkBBG11bGQCBQdfYW1vdW50BQlfbGV2ZXJhZ2UEDSR0MDUzMzkxNTM1NjQJAQlzd2FwSW5wdXQCBQVpc0FkZAUMb3Blbk5vdGlvbmFsBBVhbW91bnRCYXNlQXNzZXRCb3VnaHQIBQ0kdDA1MzM5MTUzNTY0Al8xBBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNTMzOTE1MzU2NAJfMgQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNTMzOTE1MzU2NAJfMwQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDUzMzkxNTM1NjQCXzQDAwkBAiE9AgUTX21pbkJhc2VBc3NldEFtb3VudAAACQBmAgUTX21pbkJhc2VBc3NldEFtb3VudAkBA2FicwEFFWFtb3VudEJhc2VBc3NldEJvdWdodAcJAAIBCQCsAgIJAKwCAgkArAICAg1MaW1pdCBlcnJvcjogCQCkAwEJAQNhYnMBBRVhbW91bnRCYXNlQXNzZXRCb3VnaHQCAyA8IAkApAMBBRNfbWluQmFzZUFzc2V0QW1vdW50BA9uZXdQb3NpdGlvblNpemUJAGQCBQ9vbGRQb3NpdGlvblNpemUFFWFtb3VudEJhc2VBc3NldEJvdWdodAQadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIJAGQCCQEQb3BlbkludGVyZXN0TG9uZwADCQBmAgUPbmV3UG9zaXRpb25TaXplAAAFDG9wZW5Ob3Rpb25hbAAABBt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIJAGQCCQERb3BlbkludGVyZXN0U2hvcnQAAwkAZgIAAAUPbmV3UG9zaXRpb25TaXplBQxvcGVuTm90aW9uYWwAAAQNJHQwNTQxMTA1NDMzMQkBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEBQ9vbGRQb3NpdGlvblNpemUFEW9sZFBvc2l0aW9uTWFyZ2luBRRvbGRQb3NpdGlvbkxzdFVwZENQRgUHX2Ftb3VudAQMcmVtYWluTWFyZ2luCAUNJHQwNTQxMTA1NDMzMQJfMQQCeDEIBQ0kdDA1NDExMDU0MzMxAl8yBAJ4MggFDSR0MDU0MTEwNTQzMzECXzMDCQEBIQEJARlyZXF1aXJlTm90T3ZlclNwcmVhZExpbWl0AgUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCQACAQIVT3ZlciBtYXggc3ByZWFkIGxpbWl0AwkBASEBCQEdcmVxdWlyZU5vdE92ZXJNYXhPcGVuTm90aW9uYWwCBRp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgUbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCQACAQIWT3ZlciBtYXggb3BlbiBub3Rpb25hbAkAngoMBQ9uZXdQb3NpdGlvblNpemUFDHJlbWFpbk1hcmdpbgkAZAIFF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsBQxvcGVuTm90aW9uYWwJAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUPbmV3UG9zaXRpb25TaXplBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIJAGQCCQEUb3BlbkludGVyZXN0Tm90aW9uYWwABQxvcGVuTm90aW9uYWwJAGQCCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAMJAGYCBQ9uZXdQb3NpdGlvblNpemUAAAkBA2FicwEFFWFtb3VudEJhc2VBc3NldEJvdWdodAAACQBkAgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUAAwkAZgIAAAUPbmV3UG9zaXRpb25TaXplCQEDYWJzAQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0AAAFGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyBRt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIEDG9wZW5Ob3Rpb25hbAkBBG11bGQCBQdfYW1vdW50BQlfbGV2ZXJhZ2UEDSR0MDU1NTkxNTU3MDcJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIJAKUIAQgFAWkGY2FsbGVyBQ9QTkxfT1BUSU9OX1NQT1QEE29sZFBvc2l0aW9uTm90aW9uYWwIBQ0kdDA1NTU5MTU1NzA3Al8xBA11bnJlYWxpemVkUG5sCAUNJHQwNTU1OTE1NTcwNwJfMgMJAGYCBRNvbGRQb3NpdGlvbk5vdGlvbmFsBQxvcGVuTm90aW9uYWwJAAIBAi5Vc2UgZGVjcmVhc2VQb3NpdGlvbiB0byBkZWNyZWFzZSBwb3NpdGlvbiBzaXplCQACAQIUQ2xvc2UgcG9zaXRpb24gZmlyc3QED25ld1Bvc2l0aW9uU2l6ZQgFDSR0MDUyOTI5NTU4OTECXzEEF25ld1Bvc2l0aW9uUmVtYWluTWFyZ2luCAUNJHQwNTI5Mjk1NTg5MQJfMgQXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA1MjkyOTU1ODkxAl8zBBRuZXdQb3NpdGlvbkxhdGVzdENQRggFDSR0MDUyOTI5NTU4OTECXzQEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDUyOTI5NTU4OTECXzUEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA1MjkyOTU1ODkxAl82BBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNTI5Mjk1NTg5MQJfNwQZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcggFDSR0MDUyOTI5NTU4OTECXzgEDnRvdGFsTG9uZ0FmdGVyCAUNJHQwNTI5Mjk1NTg5MQJfOQQPdG90YWxTaG9ydEFmdGVyCAUNJHQwNTI5Mjk1NTg5MQNfMTAEGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNTI5Mjk1NTg5MQNfMTEEG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDUyOTI5NTU4OTEDXzEyBA0kdDA1NTg5NzU1OTU0CQENZGlzdHJpYnV0ZUZlZQEFCWZlZUFtb3VudAQMZmVlVG9TdGFrZXJzCAUNJHQwNTU4OTc1NTk1NAJfMQQKZmVlVG9WYXVsdAgFDSR0MDU1ODk3NTU5NTQCXzIEBXN0YWtlAwUMaXNRdW90ZUFzc2V0BAVzdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIJYWRkTG9ja2VkCQDMCAIHBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUHX2Ftb3VudAUDbmlsAwkAAAIFBXN0YWtlBQVzdGFrZQUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUFc3Rha2UFBXN0YWtlBAxkZXBvc2l0VmF1bHQJAPwHBAkBDHZhdWx0QWRkcmVzcwACB2FkZEZyZWUFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABQpmZWVUb1ZhdWx0BQNuaWwDCQAAAgUMZGVwb3NpdFZhdWx0BQxkZXBvc2l0VmF1bHQECW5vdGlmeUZlZQkA/AcECQEMbWluZXJBZGRyZXNzAAIKbm90aWZ5RmVlcwkAzAgCBQdfdHJhZGVyCQDMCAIFCWZlZUFtb3VudAUDbmlsBQNuaWwDCQAAAgUJbm90aWZ5RmVlBQlub3RpZnlGZWUEDm5vdGlmeU5vdGlvbmFsCQD8BwQJAQxtaW5lckFkZHJlc3MAAg5ub3RpZnlOb3Rpb25hbAkAzAgCBQdfdHJhZGVyCQDMCAIFF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBQNuaWwFA25pbAMJAAACBQ5ub3RpZnlOb3Rpb25hbAUObm90aWZ5Tm90aW9uYWwJAM4IAgkAzggCCQDOCAIJAM4IAgkAzggCCQDOCAIJAM4IAgkBDnVwZGF0ZVBvc2l0aW9uBQUHX3RyYWRlcgUPbmV3UG9zaXRpb25TaXplBRduZXdQb3NpdGlvblJlbWFpbk1hcmdpbgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFFG5ld1Bvc2l0aW9uTGF0ZXN0Q1BGCQEfaW5jcmVtZW50UG9zaXRpb25TZXF1ZW5jZU51bWJlcgIFDWlzTmV3UG9zaXRpb24FB190cmFkZXIJARF1cGRhdGVQb3NpdGlvbkZlZQMFDWlzTmV3UG9zaXRpb24FB190cmFkZXIFC2FkanVzdGVkRmVlCQETdXBkYXRlUG9zaXRpb25Bc3NldAIFB190cmFkZXIFC19hc3NldElkU3RyCQEJdXBkYXRlQW1tCAUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyBRp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgUbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCQELdHJhbnNmZXJGZWUBBQxmZWVUb1N0YWtlcnMJAQ11cGRhdGVCYWxhbmNlAQkAZAIJAQhjYmFsYW5jZQAFB19hbW91bnQJAQ5kb0J1cm5BcnRpZmFjdAIFDGJ1cm5BcnRpZmFjdAUBaQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQlhZGRNYXJnaW4ABARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEB190cmFkZXIJAKUIAQgFAWkGY2FsbGVyBAdfYW1vdW50CAkAkQMCCAUBaQhwYXltZW50cwAABmFtb3VudAQIX2Fzc2V0SWQICQCRAwIIBQFpCHBheW1lbnRzAAAHYXNzZXRJZAQLX2Fzc2V0SWRTdHIJANgEAQkBBXZhbHVlAQUIX2Fzc2V0SWQEDGlzUXVvdGVBc3NldAkAAAIFCF9hc3NldElkCQEKcXVvdGVBc3NldAAEEWlzQ29sbGF0ZXJhbEFzc2V0CQEQaXNXaGl0ZWxpc3RBc3NldAEFC19hc3NldElkU3RyAwMDAwMDAwMJAQEhAQUMaXNRdW90ZUFzc2V0CQEBIQEFEWlzQ29sbGF0ZXJhbEFzc2V0BwYJAQEhAQkBE3JlcXVpcmVPcGVuUG9zaXRpb24BCQClCAEIBQFpBmNhbGxlcgYJAQEhAQkBC2lzU2FtZUFzc2V0AgUHX3RyYWRlcgULX2Fzc2V0SWRTdHIGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAYJAQljbG9zZU9ubHkABgkBDmlzTWFya2V0Q2xvc2VkAAkAAgECHEludmFsaWQgYWRkTWFyZ2luIHBhcmFtZXRlcnMEDSR0MDU3OTg1NTgxMjUJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIED29sZFBvc2l0aW9uU2l6ZQgFDSR0MDU3OTg1NTgxMjUCXzEEEW9sZFBvc2l0aW9uTWFyZ2luCAUNJHQwNTc5ODU1ODEyNQJfMgQXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA1Nzk4NTU4MTI1Al8zBBRvbGRQb3NpdGlvbkxzdFVwZENQRggFDSR0MDU3OTg1NTgxMjUCXzQEBXN0YWtlAwUMaXNRdW90ZUFzc2V0BAVzdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIJYWRkTG9ja2VkCQDMCAIHBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUHX2Ftb3VudAUDbmlsAwkAAAIFBXN0YWtlBQVzdGFrZQUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUFc3Rha2UFBXN0YWtlCQDOCAIJAQ51cGRhdGVQb3NpdGlvbgUFB190cmFkZXIFD29sZFBvc2l0aW9uU2l6ZQkAZAIFEW9sZFBvc2l0aW9uTWFyZ2luBQdfYW1vdW50BRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAUUb2xkUG9zaXRpb25Mc3RVcGRDUEYJAQ11cGRhdGVCYWxhbmNlAQkAZAIJAQhjYmFsYW5jZQAFB19hbW91bnQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEMcmVtb3ZlTWFyZ2luAQdfYW1vdW50BARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEB190cmFkZXIJAKUIAQgFAWkGY2FsbGVyAwMDAwMJAGcCAAAFB19hbW91bnQGCQEBIQEJARNyZXF1aXJlT3BlblBvc2l0aW9uAQUHX3RyYWRlcgYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQZwYXVzZWQABgkBDmlzTWFya2V0Q2xvc2VkAAkAAgECH0ludmFsaWQgcmVtb3ZlTWFyZ2luIHBhcmFtZXRlcnMEDSR0MDU4OTIwNTkwNjAJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIED29sZFBvc2l0aW9uU2l6ZQgFDSR0MDU4OTIwNTkwNjACXzEEEW9sZFBvc2l0aW9uTWFyZ2luCAUNJHQwNTg5MjA1OTA2MAJfMgQXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA1ODkyMDU5MDYwAl8zBBRvbGRQb3NpdGlvbkxzdFVwZENQRggFDSR0MDU4OTIwNTkwNjACXzQEC21hcmdpbkRlbHRhCQEBLQEFB19hbW91bnQEDSR0MDU5MDk3NTkyNzYJASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BAUPb2xkUG9zaXRpb25TaXplBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25Mc3RVcGRDUEYFC21hcmdpbkRlbHRhBAxyZW1haW5NYXJnaW4IBQ0kdDA1OTA5NzU5Mjc2Al8xBAdiYWREZWJ0CAUNJHQwNTkwOTc1OTI3NgJfMgMJAQIhPQIFB2JhZERlYnQAAAkAAgECHUludmFsaWQgcmVtb3ZlZCBtYXJnaW4gYW1vdW50BAttYXJnaW5SYXRpbwkBD2NhbGNNYXJnaW5SYXRpbwMFDHJlbWFpbk1hcmdpbgUHYmFkRGVidAUXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwDCQEBIQEJARZyZXF1aXJlTW9yZU1hcmdpblJhdGlvAwULbWFyZ2luUmF0aW8JAQ9pbml0TWFyZ2luUmF0aW8ABgkAAgEJAKwCAgkArAICCQCsAgICGVRvbyBtdWNoIG1hcmdpbiByZW1vdmVkOiAJAKQDAQULbWFyZ2luUmF0aW8CAyA8IAkApAMBCQEPaW5pdE1hcmdpblJhdGlvAAQNcXVvdGVBc3NldFN0cgkA2AQBCQEKcXVvdGVBc3NldAAEDSR0MDU5NzIwNTk3NzQJARNnZXRCb3Jyb3dlZEJ5VHJhZGVyAQUHX3RyYWRlcgQIYm9ycm93ZWQIBQ0kdDA1OTcyMDU5Nzc0Al8xBAdhc3NldElkCAUNJHQwNTk3MjA1OTc3NAJfMgQHdG9SZXBheQMJAGYCBQdfYW1vdW50BQhib3Jyb3dlZAUIYm9ycm93ZWQFB19hbW91bnQECnRvV2l0aGRyYXcDCQBmAgUIYm9ycm93ZWQFB19hbW91bnQAAAkAZQIFB19hbW91bnQFCGJvcnJvd2VkBAtmaW5hbEJvcnJvdwkAZQIFCGJvcnJvd2VkBQd0b1JlcGF5BBVzd2l0Y2hQb3NpdGlvblRvUXVvdGUDCQBmAgULZmluYWxCb3Jyb3cAAAUDbmlsCQETdXBkYXRlUG9zaXRpb25Bc3NldAIFB190cmFkZXIFDXF1b3RlQXNzZXRTdHIEDWRvU2FuaXR5Q2hlY2sDCQECIT0CCQBkAgUHdG9SZXBheQUKdG9XaXRoZHJhdwUHX2Ftb3VudAkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAgh0b1JlcGF5PQkApAMBBQd0b1JlcGF5Ag4gKyB0b1dpdGhkcmF3PQkApAMBBQp0b1dpdGhkcmF3AgQgIT0gCQCkAwEFB19hbW91bnQFA25pbAMJAAACBQ1kb1Nhbml0eUNoZWNrBQ1kb1Nhbml0eUNoZWNrBAlkb1Vuc3Rha2UDCQBmAgUKdG9XaXRoZHJhdwAABAlkb1Vuc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACDndpdGhkcmF3TG9ja2VkCQDMCAIFCnRvV2l0aGRyYXcFA25pbAUDbmlsAwkAAAIFCWRvVW5zdGFrZQUJZG9VbnN0YWtlBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBQlkb1Vuc3Rha2UFCWRvVW5zdGFrZQQWcmV0dXJuQ29sbGF0ZXJhbEFjdGlvbgMJAGYCBQd0b1JlcGF5AAAEB2RvUmVwYXkJAPwHBAkBEWNvbGxhdGVyYWxBZGRyZXNzAAIFcmVwYXkJAMwIAgUHX3RyYWRlcgkAzAgCBQd0b1JlcGF5CQDMCAIFB2Fzc2V0SWQFA25pbAUDbmlsAwkAAAIFB2RvUmVwYXkFB2RvUmVwYXkJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyBQd0b1JlcGF5CQDZBAEFB2Fzc2V0SWQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFFnJldHVybkNvbGxhdGVyYWxBY3Rpb24FFnJldHVybkNvbGxhdGVyYWxBY3Rpb24JAM4IAgkAzggCCQDOCAIJAM4IAgkBDnVwZGF0ZVBvc2l0aW9uBQUHX3RyYWRlcgUPb2xkUG9zaXRpb25TaXplBQxyZW1haW5NYXJnaW4FF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCQEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEFD29sZFBvc2l0aW9uU2l6ZQMJAGYCBQp0b1dpdGhkcmF3AAAJAQh3aXRoZHJhdwIIBQFpBmNhbGxlcgUKdG9XaXRoZHJhdwUDbmlsCQENdXBkYXRlQmFsYW5jZQEJAGUCCQEIY2JhbGFuY2UABQdfYW1vdW50BRVzd2l0Y2hQb3NpdGlvblRvUXVvdGUFFnJldHVybkNvbGxhdGVyYWxBY3Rpb24JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQENY2xvc2VQb3NpdGlvbgMFX3NpemUUX21pblF1b3RlQXNzZXRBbW91bnQMX2FkZFRvTWFyZ2luBARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEB190cmFkZXIJAQ9nZXRBY3R1YWxDYWxsZXIBBQFpBA5fdHJhZGVyQWRkcmVzcwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEFB190cmFkZXICDkludmFsaWQgY2FsbGVyBAtwb3NpdGlvbkZlZQkBDmdldFBvc2l0aW9uRmVlAQUHX3RyYWRlcgMDAwMDAwkBASEBCQETcmVxdWlyZU9wZW5Qb3NpdGlvbgEFB190cmFkZXIGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAYJAGcCAAAFBV9zaXplBgkAZgIAAAUUX21pblF1b3RlQXNzZXRBbW91bnQGCQEOaXNNYXJrZXRDbG9zZWQACQACAQIgSW52YWxpZCBjbG9zZVBvc2l0aW9uIHBhcmFtZXRlcnMEDSR0MDYyMDExNjIxNTEJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIED29sZFBvc2l0aW9uU2l6ZQgFDSR0MDYyMDExNjIxNTECXzEEEW9sZFBvc2l0aW9uTWFyZ2luCAUNJHQwNjIwMTE2MjE1MQJfMgQXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA2MjAxMTYyMTUxAl8zBBRvbGRQb3NpdGlvbkxzdFVwZENQRggFDSR0MDYyMDExNjIxNTECXzQEDSR0MDYyMTU3NjgwMzUDCQBmAgkBA2FicwEFD29sZFBvc2l0aW9uU2l6ZQUFX3NpemUECl9kaXJlY3Rpb24DCQBmAgUPb2xkUG9zaXRpb25TaXplAAAFCURJUl9TSE9SVAUIRElSX0xPTkcEBWlzQWRkCQAAAgUKX2RpcmVjdGlvbgUIRElSX0xPTkcEDSR0MDYyNzY4NjI5OTAJAQpzd2FwT3V0cHV0AwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAABQVfc2l6ZQYEGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQIBQ0kdDA2Mjc2ODYyOTkwAl8xBBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNjI3Njg2Mjk5MAJfMgQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNjI3Njg2Mjk5MAJfMwQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDYyNzY4NjI5OTACXzQEFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQMJAGYCBQ9vbGRQb3NpdGlvblNpemUAAAkBAS0BBQVfc2l6ZQUFX3NpemUEDSR0MDYzMDgxNjMyMzUJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAQTb2xkUG9zaXRpb25Ob3Rpb25hbAgFDSR0MDYzMDgxNjMyMzUCXzEEDXVucmVhbGl6ZWRQbmwIBQ0kdDA2MzA4MTYzMjM1Al8yBAJtcgkBFmdldE1hcmdpblJhdGlvQnlPcHRpb24CBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QEDXJlYWxpemVkUmF0aW8JAQRkaXZkAgkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQkBA2FicwEFD29sZFBvc2l0aW9uU2l6ZQQLcmVhbGl6ZWRQbmwJAQRtdWxkAgUNdW5yZWFsaXplZFBubAUNcmVhbGl6ZWRSYXRpbwQLcmVhbGl6ZWRGZWUJAQRtdWxkAgkBBG11bGQCBRNvbGRQb3NpdGlvbk5vdGlvbmFsBQ1yZWFsaXplZFJhdGlvBQtwb3NpdGlvbkZlZQQScmVtYWluTWFyZ2luQmVmb3JlCAkBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEBQ9vbGRQb3NpdGlvblNpemUFEW9sZFBvc2l0aW9uTWFyZ2luBRRvbGRQb3NpdGlvbkxzdFVwZENQRgUNdW5yZWFsaXplZFBubAJfMQQPcG9zaXRpb25CYWREZWJ0CAkBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEBQ9vbGRQb3NpdGlvblNpemUFEW9sZFBvc2l0aW9uTWFyZ2luBRRvbGRQb3NpdGlvbkxzdFVwZENQRgULcmVhbGl6ZWRQbmwCXzIEEnVucmVhbGl6ZWRQbmxBZnRlcgkAZQIFDXVucmVhbGl6ZWRQbmwFC3JlYWxpemVkUG5sBBJyZW1haW5PcGVuTm90aW9uYWwDCQBmAgUPb2xkUG9zaXRpb25TaXplAAAJAGUCCQBlAgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAUSdW5yZWFsaXplZFBubEFmdGVyCQBlAgkAZAIFEnVucmVhbGl6ZWRQbmxBZnRlcgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAQXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwJAQNhYnMBBRJyZW1haW5PcGVuTm90aW9uYWwED25ld1Bvc2l0aW9uU2l6ZQkAZAIFD29sZFBvc2l0aW9uU2l6ZQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplBBRuZXdQb3NpdGlvbkxzdFVwZENQRgkBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BBQ9uZXdQb3NpdGlvblNpemUEEW9wZW5Ob3Rpb25hbERlbHRhCQBlAgUXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwFF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCQBlAgkBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAAURb3Blbk5vdGlvbmFsRGVsdGEEEW5ld1Bvc2l0aW9uTWFyZ2luAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAACQBlAgkBBG11bGQCCQBkAgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFEnVucmVhbGl6ZWRQbmxBZnRlcgUCbXIFEnVucmVhbGl6ZWRQbmxBZnRlcgkAZQIJAQRtdWxkAgkAZQIFF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBRJ1bnJlYWxpemVkUG5sQWZ0ZXIFAm1yBRJ1bnJlYWxpemVkUG5sQWZ0ZXIEEW1hcmdpblRvVHJhZGVyUmF3CQBlAgkAZQIFEnJlbWFpbk1hcmdpbkJlZm9yZQkAZAIFEW5ld1Bvc2l0aW9uTWFyZ2luBRJ1bnJlYWxpemVkUG5sQWZ0ZXIFC3JlYWxpemVkRmVlBA5tYXJnaW5Ub1RyYWRlcgMJAGYCAAAFEW1hcmdpblRvVHJhZGVyUmF3CQACAQIlTWFyZ2luIGVycm9yOiB1bmFibGUgdG8gcGF5IGNsb3NlIGZlZQURbWFyZ2luVG9UcmFkZXJSYXcDAwkBAiE9AgUUX21pblF1b3RlQXNzZXRBbW91bnQAAAkAZgIFFF9taW5RdW90ZUFzc2V0QW1vdW50BRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BwkAAgEJAKwCAgkArAICCQCsAgICDUxpbWl0IGVycm9yOiAJAKQDAQUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAIDIDwgCQCkAwEFFF9taW5RdW90ZUFzc2V0QW1vdW50CQCiChAFD25ld1Bvc2l0aW9uU2l6ZQMFDF9hZGRUb01hcmdpbgkAZAIFEW5ld1Bvc2l0aW9uTWFyZ2luBQ5tYXJnaW5Ub1RyYWRlcgURbmV3UG9zaXRpb25NYXJnaW4FF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBRRuZXdQb3NpdGlvbkxzdFVwZENQRgUPcG9zaXRpb25CYWREZWJ0BQtyZWFsaXplZFBubAMFDF9hZGRUb01hcmdpbgAABQ5tYXJnaW5Ub1RyYWRlcgUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCQBlAgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQADCQBmAgUPbmV3UG9zaXRpb25TaXplAAAJAQNhYnMBBRVleGNoYW5nZWRQb3NpdGlvblNpemUAAAkAZQIJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAMJAGYCAAAFD25ld1Bvc2l0aW9uU2l6ZQkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQAACQBlAgkBEG9wZW5JbnRlcmVzdExvbmcAAwkAZgIFD25ld1Bvc2l0aW9uU2l6ZQAABRFvcGVuTm90aW9uYWxEZWx0YQAACQBlAgkBEW9wZW5JbnRlcmVzdFNob3J0AAMJAGYCAAAFD25ld1Bvc2l0aW9uU2l6ZQURb3Blbk5vdGlvbmFsRGVsdGEAAAULcmVhbGl6ZWRGZWUDCQBmAgUFX3NpemUJAQNhYnMBBQ9vbGRQb3NpdGlvblNpemUJAAIBAiBJbnZhbGlkIGNsb3NlUG9zaXRpb24gcGFyYW1ldGVycwQNJHQwNjY0NTQ2Njg4NAkBFWludGVybmFsQ2xvc2VQb3NpdGlvbgIFB190cmFkZXIGBAJ4MggFDSR0MDY2NDU0NjY4ODQCXzEED3Bvc2l0aW9uQmFkRGVidAgFDSR0MDY2NDU0NjY4ODQCXzIEC3JlYWxpemVkUG5sCAUNJHQwNjY0NTQ2Njg4NAJfMwQYbWFyZ2luVG9UcmFkZXJXaXRob3V0RmVlCAUNJHQwNjY0NTQ2Njg4NAJfNAQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDY2NDU0NjY4ODQCXzUEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDY2NDU0NjY4ODQCXzYEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA2NjQ1NDY2ODg0Al83BBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCAUNJHQwNjY0NTQ2Njg4NAJfOAQZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAgFDSR0MDY2NDU0NjY4ODQCXzkEDnRvdGFsTG9uZ0FmdGVyCAUNJHQwNjY0NTQ2Njg4NANfMTAED3RvdGFsU2hvcnRBZnRlcggFDSR0MDY2NDU0NjY4ODQDXzExBBp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDY2NDU0NjY4ODQDXzEyBBt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA2NjQ1NDY2ODg0A18xMwQLcmVhbGl6ZWRGZWUJAQRtdWxkAgUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAULcG9zaXRpb25GZWUEEW1hcmdpblRvVHJhZGVyUmF3CQBlAgkBA2FicwEFGG1hcmdpblRvVHJhZGVyV2l0aG91dEZlZQULcmVhbGl6ZWRGZWUEDm1hcmdpblRvVHJhZGVyAwkAZgIAAAURbWFyZ2luVG9UcmFkZXJSYXcJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICJ01hcmdpbiBlcnJvcjogdW5hYmxlIHRvIHBheSBjbG9zZSBmZWU6IAkApAMBBQtyZWFsaXplZEZlZQIJIG1hcmdpbjogCQCkAwEFGG1hcmdpblRvVHJhZGVyV2l0aG91dEZlZQIOIGZlZSBwZXJjZW50OiAJAKQDAQULcG9zaXRpb25GZWUCCyBub3Rpb25hbDogCQCkAwEFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQFEW1hcmdpblRvVHJhZGVyUmF3AwMJAQIhPQIFFF9taW5RdW90ZUFzc2V0QW1vdW50AAAJAGYCBRRfbWluUXVvdGVBc3NldEFtb3VudAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAcJAAIBCQCsAgIJAKwCAgkArAICAg1MaW1pdCBlcnJvcjogCQCkAwEFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQCAyA8IAkApAMBBRRfbWluUXVvdGVBc3NldEFtb3VudAkAogoQAAAAAAAAAAAFD3Bvc2l0aW9uQmFkRGVidAULcmVhbGl6ZWRQbmwFDm1hcmdpblRvVHJhZGVyBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIFDnRvdGFsTG9uZ0FmdGVyBQ90b3RhbFNob3J0QWZ0ZXIFGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyBRt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIFC3JlYWxpemVkRmVlBA9uZXdQb3NpdGlvblNpemUIBQ0kdDA2MjE1NzY4MDM1Al8xBBFuZXdQb3NpdGlvbk1hcmdpbggFDSR0MDYyMTU3NjgwMzUCXzIEF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNjIxNTc2ODAzNQJfMwQUbmV3UG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA2MjE1NzY4MDM1Al80BA9wb3NpdGlvbkJhZERlYnQIBQ0kdDA2MjE1NzY4MDM1Al81BAtyZWFsaXplZFBubAgFDSR0MDYyMTU3NjgwMzUCXzYEDm1hcmdpblRvVHJhZGVyCAUNJHQwNjIxNTc2ODAzNQJfNwQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDYyMTU3NjgwMzUCXzgEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDYyMTU3NjgwMzUCXzkEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA2MjE1NzY4MDM1A18xMAQZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcggFDSR0MDYyMTU3NjgwMzUDXzExBA50b3RhbExvbmdBZnRlcggFDSR0MDYyMTU3NjgwMzUDXzEyBA90b3RhbFNob3J0QWZ0ZXIIBQ0kdDA2MjE1NzY4MDM1A18xMwQadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA2MjE1NzY4MDM1A18xNAQbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNjIxNTc2ODAzNQNfMTUEC3JlYWxpemVkRmVlCAUNJHQwNjIxNTc2ODAzNQNfMTYDCQBmAgUPcG9zaXRpb25CYWREZWJ0AAAJAAIBAiZVbmFibGUgdG8gY2xvc2UgcG9zaXRpb24gd2l0aCBiYWQgZGVidAQOaXNQYXJ0aWFsQ2xvc2UJAQIhPQIFD25ld1Bvc2l0aW9uU2l6ZQAABA53aXRoZHJhd0Ftb3VudAkAZAIFDm1hcmdpblRvVHJhZGVyBQtyZWFsaXplZEZlZQQKYW1tQmFsYW5jZQkAZQIJAQhjYmFsYW5jZQAFDndpdGhkcmF3QW1vdW50BA0kdDA2ODMwMjY4NTA5AwkAZgIAAAUKYW1tQmFsYW5jZQkAlAoCAAAJAQNhYnMBBQphbW1CYWxhbmNlCQCUCgIFCmFtbUJhbGFuY2UAAAQNYW1tTmV3QmFsYW5jZQgFDSR0MDY4MzAyNjg1MDkCXzEEA3gxMQgFDSR0MDY4MzAyNjg1MDkCXzIEDSR0MDY4NTE2Njg1NzAJARNnZXRCb3Jyb3dlZEJ5VHJhZGVyAQUHX3RyYWRlcgQIYm9ycm93ZWQIBQ0kdDA2ODUxNjY4NTcwAl8xBAdhc3NldElkCAUNJHQwNjg1MTY2ODU3MAJfMgQNJHQwNjg1Nzg2OTQzOAMJAGYCBQhib3Jyb3dlZAAAAwkAZwIFDndpdGhkcmF3QW1vdW50BQhib3Jyb3dlZAQHZG9SZXBheQkA/AcECQERY29sbGF0ZXJhbEFkZHJlc3MAAgVyZXBheQkAzAgCBQdfdHJhZGVyCQDMCAIFCGJvcnJvd2VkCQDMCAIFB2Fzc2V0SWQFA25pbAUDbmlsAwkAAAIFB2RvUmVwYXkFB2RvUmVwYXkJAJUKAwUIYm9ycm93ZWQJAGUCBQ53aXRoZHJhd0Ftb3VudAUIYm9ycm93ZWQFDmlzUGFydGlhbENsb3NlCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBA9yZWFsaXplQW5kQ2xvc2UJAPwHBAkBEWNvbGxhdGVyYWxBZGRyZXNzAAMFDmlzUGFydGlhbENsb3NlAgVyZXBheQIYcmVhbGl6ZVBhcnRpYWxseUFuZENsb3NlCQDMCAIFB190cmFkZXIJAMwIAgUOd2l0aGRyYXdBbW91bnQJAMwIAgUHYXNzZXRJZAUDbmlsBQNuaWwDCQAAAgUPcmVhbGl6ZUFuZENsb3NlBQ9yZWFsaXplQW5kQ2xvc2UJAJUKAwUOd2l0aGRyYXdBbW91bnQAAAcJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAJUKAwAABQ53aXRoZHJhd0Ftb3VudAcDCQAAAgUNJHQwNjg1Nzg2OTQzOAUNJHQwNjg1Nzg2OTQzOAQNc3dpdGNoVG9RdW90ZQgFDSR0MDY4NTc4Njk0MzgCXzMEHHF1b3RlV2l0aGRyYXdBbW91bnRCZWZvcmVGZWUIBQ0kdDA2ODU3ODY5NDM4Al8yBBxhc3NldFdpdGhkcmF3QW1vdW50QmVmb3JlRmVlCAUNJHQwNjg1Nzg2OTQzOAJfMQQNJHQwNjk0NDY3MDUxMwMJAGcCBRxxdW90ZVdpdGhkcmF3QW1vdW50QmVmb3JlRmVlBQtyZWFsaXplZEZlZQkAlQoDBRxhc3NldFdpdGhkcmF3QW1vdW50QmVmb3JlRmVlCQBlAgUccXVvdGVXaXRoZHJhd0Ftb3VudEJlZm9yZUZlZQULcmVhbGl6ZWRGZWUFC3JlYWxpemVkRmVlBBpmZWVMZWZ0VG9XaXRoZHJhd0Zyb21Bc3NldAkAZQIFC3JlYWxpemVkRmVlBRxxdW90ZVdpdGhkcmF3QW1vdW50QmVmb3JlRmVlBBthc3NldFdpdGhkcmF3QW1vdW50QWZ0ZXJGZWUJAGUCBRxhc3NldFdpdGhkcmF3QW1vdW50QmVmb3JlRmVlBRpmZWVMZWZ0VG9XaXRoZHJhd0Zyb21Bc3NldAQNYmFsYW5jZUJlZm9yZQkA8AcCBQR0aGlzCQEKcXVvdGVBc3NldAADCQAAAgUNYmFsYW5jZUJlZm9yZQUNYmFsYW5jZUJlZm9yZQQGZG9Td2FwCQD8BwQJAQtzd2FwQWRkcmVzcwACBHN3YXAJAMwIAgkA2AQBCQEKcXVvdGVBc3NldAAJAMwIAgAABQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJANkEAQUHYXNzZXRJZAUaZmVlTGVmdFRvV2l0aGRyYXdGcm9tQXNzZXQFA25pbAMJAAACBQZkb1N3YXAFBmRvU3dhcAQMYmFsYW5jZUFmdGVyCQDwBwIFBHRoaXMJAQpxdW90ZUFzc2V0AAMJAAACBQxiYWxhbmNlQWZ0ZXIFDGJhbGFuY2VBZnRlcgQPZXhjaGFuZ2VkQW1vdW50CQBlAgUMYmFsYW5jZUFmdGVyBQ1iYWxhbmNlQmVmb3JlAwkAAAIFD2V4Y2hhbmdlZEFtb3VudAUPZXhjaGFuZ2VkQW1vdW50CQCVCgMFG2Fzc2V0V2l0aGRyYXdBbW91bnRBZnRlckZlZQAACQBkAgUccXVvdGVXaXRoZHJhd0Ftb3VudEJlZm9yZUZlZQUPZXhjaGFuZ2VkQW1vdW50CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAwkAAAIFDSR0MDY5NDQ2NzA1MTMFDSR0MDY5NDQ2NzA1MTMEFWFjdHVhbEZlZUluUXVvdGVBc3NldAgFDSR0MDY5NDQ2NzA1MTMCXzMEG3F1b3RlV2l0aGRyYXdBbW91bnRBZnRlckZlZQgFDSR0MDY5NDQ2NzA1MTMCXzIEG2Fzc2V0V2l0aGRyYXdBbW91bnRBZnRlckZlZQgFDSR0MDY5NDQ2NzA1MTMCXzEEB3Vuc3Rha2UDCQBmAgUccXVvdGVXaXRoZHJhd0Ftb3VudEJlZm9yZUZlZQAABAd1bnN0YWtlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAg53aXRoZHJhd0xvY2tlZAkAzAgCBRxxdW90ZVdpdGhkcmF3QW1vdW50QmVmb3JlRmVlBQNuaWwFA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlBA0kdDA3MDc4NzcwODU2CQENZGlzdHJpYnV0ZUZlZQEFFWFjdHVhbEZlZUluUXVvdGVBc3NldAQMZmVlVG9TdGFrZXJzCAUNJHQwNzA3ODc3MDg1NgJfMQQKZmVlVG9WYXVsdAgFDSR0MDcwNzg3NzA4NTYCXzIEDGRlcG9zaXRWYXVsdAkA/AcECQEMdmF1bHRBZGRyZXNzAAIHYWRkRnJlZQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFCmZlZVRvVmF1bHQFA25pbAMJAAACBQxkZXBvc2l0VmF1bHQFDGRlcG9zaXRWYXVsdAQJbm90aWZ5RmVlCQD8BwQJAQxtaW5lckFkZHJlc3MAAgpub3RpZnlGZWVzCQDMCAIFB190cmFkZXIJAMwIAgULcmVhbGl6ZWRGZWUFA25pbAUDbmlsAwkAAAIFCW5vdGlmeUZlZQUJbm90aWZ5RmVlBA5ub3RpZnlOb3Rpb25hbAkA/AcECQEMbWluZXJBZGRyZXNzAAIObm90aWZ5Tm90aW9uYWwJAMwIAgUHX3RyYWRlcgkAzAgCBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUDbmlsBQNuaWwDCQAAAgUObm90aWZ5Tm90aW9uYWwFDm5vdGlmeU5vdGlvbmFsCQDOCAIJAM4IAgkAzggCCQDOCAIJAM4IAgkAzggCAwUOaXNQYXJ0aWFsQ2xvc2UJAQ51cGRhdGVQb3NpdGlvbgUFB190cmFkZXIFD25ld1Bvc2l0aW9uU2l6ZQURbmV3UG9zaXRpb25NYXJnaW4FF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBRRuZXdQb3NpdGlvbkxzdFVwZENQRgkBDmRlbGV0ZVBvc2l0aW9uAQUHX3RyYWRlcgMFDXN3aXRjaFRvUXVvdGUEDXF1b3RlQXNzZXRTdHIJANgEAQkBCnF1b3RlQXNzZXQACQETdXBkYXRlUG9zaXRpb25Bc3NldAIFB190cmFkZXIFDXF1b3RlQXNzZXRTdHIFA25pbAkBCXVwZGF0ZUFtbQgFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgUZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcgUOdG90YWxMb25nQWZ0ZXIFD3RvdGFsU2hvcnRBZnRlcgUadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIFG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgkBC3RyYW5zZmVyRmVlAQUMZmVlVG9TdGFrZXJzAwkAZgIFG3F1b3RlV2l0aGRyYXdBbW91bnRBZnRlckZlZQAACQEId2l0aGRyYXcCBQ5fdHJhZGVyQWRkcmVzcwUbcXVvdGVXaXRoZHJhd0Ftb3VudEFmdGVyRmVlBQNuaWwJAQ11cGRhdGVCYWxhbmNlAQUNYW1tTmV3QmFsYW5jZQMJAGYCBRthc3NldFdpdGhkcmF3QW1vdW50QWZ0ZXJGZWUAAAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQ5fdHJhZGVyQWRkcmVzcwUbYXNzZXRXaXRoZHJhd0Ftb3VudEFmdGVyRmVlCQDZBAEFB2Fzc2V0SWQFA25pbAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCWxpcXVpZGF0ZQEHX3RyYWRlcgQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBA9zcG90TWFyZ2luUmF0aW8JARZnZXRNYXJnaW5SYXRpb0J5T3B0aW9uAgUHX3RyYWRlcgUPUE5MX09QVElPTl9TUE9UBAttYXJnaW5SYXRpbwMJARZpc092ZXJGbHVjdHVhdGlvbkxpbWl0AAQRb3JhY2xlTWFyZ2luUmF0aW8JARZnZXRNYXJnaW5SYXRpb0J5T3B0aW9uAgUHX3RyYWRlcgURUE5MX09QVElPTl9PUkFDTEUJAQR2bWF4AgUPc3BvdE1hcmdpblJhdGlvBRFvcmFjbGVNYXJnaW5SYXRpbwUPc3BvdE1hcmdpblJhdGlvAwMDAwMJAQEhAQkBFnJlcXVpcmVNb3JlTWFyZ2luUmF0aW8DBQttYXJnaW5SYXRpbwkBFm1haW50ZW5hbmNlTWFyZ2luUmF0aW8ABwYJAQEhAQkBE3JlcXVpcmVPcGVuUG9zaXRpb24BBQdfdHJhZGVyBgkBASEBCQELaW5pdGlhbGl6ZWQABgkBBnBhdXNlZAAGCQEOaXNNYXJrZXRDbG9zZWQACQACAQITVW5hYmxlIHRvIGxpcXVpZGF0ZQMDAwkAZgIFD3Nwb3RNYXJnaW5SYXRpbwkBE2xpcXVpZGF0aW9uRmVlUmF0aW8ACQBmAgkBF3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAAAABwkAZgIFDERFQ0lNQUxfVU5JVAkBF3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAAcEDSR0MDczNjA5NzM3NTkJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIED29sZFBvc2l0aW9uU2l6ZQgFDSR0MDczNjA5NzM3NTkCXzEEEW9sZFBvc2l0aW9uTWFyZ2luCAUNJHQwNzM2MDk3Mzc1OQJfMgQXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA3MzYwOTczNzU5Al8zBBRvbGRQb3NpdGlvbkxzdFVwZENQRggFDSR0MDczNjA5NzM3NTkCXzQECl9kaXJlY3Rpb24DCQBmAgUPb2xkUG9zaXRpb25TaXplAAAFCURJUl9TSE9SVAUIRElSX0xPTkcEBWlzQWRkCQAAAgUKX2RpcmVjdGlvbgUIRElSX0xPTkcEGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQJARtnZXRQYXJ0aWFsTGlxdWlkYXRpb25BbW91bnQCBQdfdHJhZGVyBQ9vbGRQb3NpdGlvblNpemUEDSR0MDczOTg0NzQwODgJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAQTb2xkUG9zaXRpb25Ob3Rpb25hbAgFDSR0MDczOTg0NzQwODgCXzEEDXVucmVhbGl6ZWRQbmwIBQ0kdDA3Mzk4NDc0MDg4Al8yBA0kdDA3NDA5Njc0MjgzCQEJc3dhcElucHV0AgUFaXNBZGQFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQEFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQgFDSR0MDc0MDk2NzQyODMCXzEEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA3NDA5Njc0MjgzAl8yBBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA3NDA5Njc0MjgzAl8zBBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNzQwOTY3NDI4MwJfNAQQbGlxdWlkYXRpb25SYXRpbwkBBGRpdmQCCQEDYWJzAQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplCQEDYWJzAQUPb2xkUG9zaXRpb25TaXplBAtyZWFsaXplZFBubAkBBG11bGQCBQ11bnJlYWxpemVkUG5sBRBsaXF1aWRhdGlvblJhdGlvBA0kdDA3NDU3Mjc0ODA1CQEiY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudAQFD29sZFBvc2l0aW9uU2l6ZQURb2xkUG9zaXRpb25NYXJnaW4FFG9sZFBvc2l0aW9uTHN0VXBkQ1BGBQtyZWFsaXplZFBubAQMcmVtYWluTWFyZ2luCAUNJHQwNzQ1NzI3NDgwNQJfMQQHYmFkRGVidAgFDSR0MDc0NTcyNzQ4MDUCXzIEDmZ1bmRpbmdQYXltZW50CAUNJHQwNzQ1NzI3NDgwNQJfMwQSdW5yZWFsaXplZFBubEFmdGVyCQBlAgUNdW5yZWFsaXplZFBubAULcmVhbGl6ZWRQbmwEEnJlbWFpbk9wZW5Ob3Rpb25hbAMJAGYCBQ9vbGRQb3NpdGlvblNpemUAAAkAZQIJAGUCBRNvbGRQb3NpdGlvbk5vdGlvbmFsBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BRJ1bnJlYWxpemVkUG5sQWZ0ZXIJAGUCCQBkAgUSdW5yZWFsaXplZFBubEFmdGVyBRNvbGRQb3NpdGlvbk5vdGlvbmFsBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BBJsaXF1aWRhdGlvblBlbmFsdHkJAQRtdWxkAgUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAkBE2xpcXVpZGF0aW9uRmVlUmF0aW8ABA9mZWVUb0xpcXVpZGF0b3IJAGkCBRJsaXF1aWRhdGlvblBlbmFsdHkAAgQKZmVlVG9WYXVsdAkAZQIFEmxpcXVpZGF0aW9uUGVuYWx0eQUPZmVlVG9MaXF1aWRhdG9yBBFuZXdQb3NpdGlvbk1hcmdpbgkAZQIFDHJlbWFpbk1hcmdpbgUSbGlxdWlkYXRpb25QZW5hbHR5BA9uZXdQb3NpdGlvblNpemUJAGQCBQ9vbGRQb3NpdGlvblNpemUFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQQXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwJAQNhYnMBBRJyZW1haW5PcGVuTm90aW9uYWwEEW9wZW5Ob3Rpb25hbERlbHRhCQBlAgUXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwFF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBBRuZXdQb3NpdGlvbkxzdFVwZENQRgkBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BBQ9uZXdQb3NpdGlvblNpemUEGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIJAGUCCQEUb3BlbkludGVyZXN0Tm90aW9uYWwABRFvcGVuTm90aW9uYWxEZWx0YQQKYW1tQmFsYW5jZQkAZQIJAQhjYmFsYW5jZQAFEmxpcXVpZGF0aW9uUGVuYWx0eQQNJHQwNzYwNDY3NjE3NQMJAGYCAAAFCmFtbUJhbGFuY2UJAJQKAgAACQEDYWJzAQUKYW1tQmFsYW5jZQkAlAoCBQphbW1CYWxhbmNlAAAEDW5ld0FtbUJhbGFuY2UIBQ0kdDA3NjA0Njc2MTc1Al8xBAN4MTEIBQ0kdDA3NjA0Njc2MTc1Al8yBA0kdDA3NjE4Mzc2MjM3CQETZ2V0Qm9ycm93ZWRCeVRyYWRlcgEFB190cmFkZXIECGJvcnJvd2VkCAUNJHQwNzYxODM3NjIzNwJfMQQHYXNzZXRJZAgFDSR0MDc2MTgzNzYyMzcCXzIEFWRvTGlxdWlkYXRlQ29sbGF0ZXJhbAMJAGYCBQhib3Jyb3dlZAAABBBjb2xsYXRlcmFsVG9TZWxsCQEEbXVsZAIFCGJvcnJvd2VkBRBsaXF1aWRhdGlvblJhdGlvBA9yZWFsaXplQW5kQ2xvc2UJAPwHBAkBEWNvbGxhdGVyYWxBZGRyZXNzAAIQcmVhbGl6ZVBhcnRpYWxseQkAzAgCBQdfdHJhZGVyCQDMCAIFB2Fzc2V0SWQJAMwIAgUQY29sbGF0ZXJhbFRvU2VsbAUDbmlsBQNuaWwDCQAAAgUPcmVhbGl6ZUFuZENsb3NlBQ9yZWFsaXplQW5kQ2xvc2UFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFFWRvTGlxdWlkYXRlQ29sbGF0ZXJhbAUVZG9MaXF1aWRhdGVDb2xsYXRlcmFsBAd1bnN0YWtlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAg53aXRoZHJhd0xvY2tlZAkAzAgCBRJsaXF1aWRhdGlvblBlbmFsdHkFA25pbAUDbmlsAwkAAAIFB3Vuc3Rha2UFB3Vuc3Rha2UEEGRlcG9zaXRJbnN1cmFuY2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACB2FkZEZyZWUFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABQpmZWVUb1ZhdWx0BQNuaWwDCQAAAgUQZGVwb3NpdEluc3VyYW5jZQUQZGVwb3NpdEluc3VyYW5jZQQObm90aWZ5Tm90aW9uYWwJAPwHBAkBDG1pbmVyQWRkcmVzcwACDm5vdGlmeU5vdGlvbmFsCQDMCAIFB190cmFkZXIJAMwIAgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFA25pbAUDbmlsAwkAAAIFDm5vdGlmeU5vdGlvbmFsBQ5ub3RpZnlOb3Rpb25hbAkAzggCCQDOCAIJAM4IAgkBDnVwZGF0ZVBvc2l0aW9uBQUHX3RyYWRlcgUPbmV3UG9zaXRpb25TaXplBRFuZXdQb3NpdGlvbk1hcmdpbgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFFG5ld1Bvc2l0aW9uTHN0VXBkQ1BGCQEJdXBkYXRlQW1tCAUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCQBlAgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQADCQBmAgUPbmV3UG9zaXRpb25TaXplAAAJAQNhYnMBBRVleGNoYW5nZWRQb3NpdGlvblNpemUAAAkAZQIJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAMJAGYCAAAFD25ld1Bvc2l0aW9uU2l6ZQkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQAACQBlAgkBEG9wZW5JbnRlcmVzdExvbmcAAwkAZgIFD25ld1Bvc2l0aW9uU2l6ZQAABRFvcGVuTm90aW9uYWxEZWx0YQAACQBlAgkBEW9wZW5JbnRlcmVzdFNob3J0AAMJAGYCAAAFD25ld1Bvc2l0aW9uU2l6ZQURb3Blbk5vdGlvbmFsRGVsdGEAAAkBCHdpdGhkcmF3AggFAWkGY2FsbGVyBQ9mZWVUb0xpcXVpZGF0b3IJAQ11cGRhdGVCYWxhbmNlAQUNbmV3QW1tQmFsYW5jZQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgQNJHQwNzc5MTY3ODQxMQkBFWludGVybmFsQ2xvc2VQb3NpdGlvbgIFB190cmFkZXIHBAJ4MQgFDSR0MDc3OTE2Nzg0MTECXzEEB2JhZERlYnQIBQ0kdDA3NzkxNjc4NDExAl8yBAJ4MggFDSR0MDc3OTE2Nzg0MTECXzMEAngzCAUNJHQwNzc5MTY3ODQxMQJfNAQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDc3OTE2Nzg0MTECXzUEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDc3OTE2Nzg0MTECXzYEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA3NzkxNjc4NDExAl83BBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCAUNJHQwNzc5MTY3ODQxMQJfOAQZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAgFDSR0MDc3OTE2Nzg0MTECXzkEDnRvdGFsTG9uZ0FmdGVyCAUNJHQwNzc5MTY3ODQxMQNfMTAED3RvdGFsU2hvcnRBZnRlcggFDSR0MDc3OTE2Nzg0MTEDXzExBBp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDc3OTE2Nzg0MTEDXzEyBBt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA3NzkxNjc4NDExA18xMwQSbGlxdWlkYXRpb25QZW5hbHR5CQEEbXVsZAIFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQJARNsaXF1aWRhdGlvbkZlZVJhdGlvAAQPZmVlVG9MaXF1aWRhdG9yCQBpAgUSbGlxdWlkYXRpb25QZW5hbHR5AAIECmZlZVRvVmF1bHQJAGUCBRJsaXF1aWRhdGlvblBlbmFsdHkFD2ZlZVRvTGlxdWlkYXRvcgQKYW1tQmFsYW5jZQkAZQIJAQhjYmFsYW5jZQAFEmxpcXVpZGF0aW9uUGVuYWx0eQQNJHQwNzg4MTk3ODk0OAMJAGYCAAAFCmFtbUJhbGFuY2UJAJQKAgAACQEDYWJzAQUKYW1tQmFsYW5jZQkAlAoCBQphbW1CYWxhbmNlAAAEDW5ld0FtbUJhbGFuY2UIBQ0kdDA3ODgxOTc4OTQ4Al8xBAN4MTEIBQ0kdDA3ODgxOTc4OTQ4Al8yBA0kdDA3ODk1Njc5MDEwCQETZ2V0Qm9ycm93ZWRCeVRyYWRlcgEFB190cmFkZXIECGJvcnJvd2VkCAUNJHQwNzg5NTY3OTAxMAJfMQQHYXNzZXRJZAgFDSR0MDc4OTU2NzkwMTACXzIEFWRvTGlxdWlkYXRlQ29sbGF0ZXJhbAMJAGYCBQhib3Jyb3dlZAAABA9yZWFsaXplQW5kQ2xvc2UJAPwHBAkBEWNvbGxhdGVyYWxBZGRyZXNzAAIYcmVhbGl6ZVBhcnRpYWxseUFuZENsb3NlCQDMCAIFB190cmFkZXIJAMwIAgAACQDMCAIFB2Fzc2V0SWQFA25pbAUDbmlsAwkAAAIFD3JlYWxpemVBbmRDbG9zZQUPcmVhbGl6ZUFuZENsb3NlBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBRVkb0xpcXVpZGF0ZUNvbGxhdGVyYWwFFWRvTGlxdWlkYXRlQ29sbGF0ZXJhbAQBeAMJAGYCBQdiYWREZWJ0AAAEC2xvY2tCYWREZWJ0CQD8BwQJAQx2YXVsdEFkZHJlc3MAAhVleGNoYW5nZUZyZWVBbmRMb2NrZWQJAMwIAgUHYmFkRGVidAUDbmlsBQNuaWwDCQAAAgULbG9ja0JhZERlYnQFC2xvY2tCYWREZWJ0BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBQF4BQF4BAd1bnN0YWtlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAg53aXRoZHJhd0xvY2tlZAkAzAgCBRJsaXF1aWRhdGlvblBlbmFsdHkFA25pbAUDbmlsAwkAAAIFB3Vuc3Rha2UFB3Vuc3Rha2UEEGRlcG9zaXRJbnN1cmFuY2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACB2FkZEZyZWUFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABQpmZWVUb1ZhdWx0BQNuaWwDCQAAAgUQZGVwb3NpdEluc3VyYW5jZQUQZGVwb3NpdEluc3VyYW5jZQQObm90aWZ5Tm90aW9uYWwJAPwHBAkBDG1pbmVyQWRkcmVzcwACDm5vdGlmeU5vdGlvbmFsCQDMCAIFB190cmFkZXIJAMwIAgAABQNuaWwFA25pbAMJAAACBQ5ub3RpZnlOb3Rpb25hbAUObm90aWZ5Tm90aW9uYWwJAM4IAgkAzggCCQDOCAIJAQ5kZWxldGVQb3NpdGlvbgEFB190cmFkZXIJAQl1cGRhdGVBbW0IBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIFDnRvdGFsTG9uZ0FmdGVyBQ90b3RhbFNob3J0QWZ0ZXIFGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyBRt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIJAQh3aXRoZHJhdwIIBQFpBmNhbGxlcgUPZmVlVG9MaXF1aWRhdG9yCQENdXBkYXRlQmFsYW5jZQEFDW5ld0FtbUJhbGFuY2UJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEKcGF5RnVuZGluZwAEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQVZnVuZGluZ0Jsb2NrVGltZXN0YW1wCQEZbmV4dEZ1bmRpbmdCbG9ja1RpbWVzdGFtcAADAwMJAGYCBRVmdW5kaW5nQmxvY2tUaW1lc3RhbXAIBQlsYXN0QmxvY2sJdGltZXN0YW1wBgkBASEBCQELaW5pdGlhbGl6ZWQABgkBBnBhdXNlZAAJAAIBCQCsAgIJAKwCAgkArAICAiFJbnZhbGlkIGZ1bmRpbmcgYmxvY2sgdGltZXN0YW1wOiAJAKQDAQgFCWxhc3RCbG9jawl0aW1lc3RhbXACAyA8IAkApAMBBRVmdW5kaW5nQmxvY2tUaW1lc3RhbXAED3VuZGVybHlpbmdQcmljZQkBDmdldE9yYWNsZVByaWNlAAQNJHQwODA4ODI4MDk0NAkBCmdldEZ1bmRpbmcABBRzaG9ydFByZW1pdW1GcmFjdGlvbggFDSR0MDgwODgyODA5NDQCXzEEE2xvbmdQcmVtaXVtRnJhY3Rpb24IBQ0kdDA4MDg4MjgwOTQ0Al8yCQENdXBkYXRlRnVuZGluZwUJAGQCBRVmdW5kaW5nQmxvY2tUaW1lc3RhbXAJARRmdW5kaW5nUGVyaW9kU2Vjb25kcwAJAGQCCQEjbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24ABRNsb25nUHJlbWl1bUZyYWN0aW9uCQBkAgkBJGxhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAFFHNob3J0UHJlbWl1bUZyYWN0aW9uCQEEZGl2ZAIFE2xvbmdQcmVtaXVtRnJhY3Rpb24FD3VuZGVybHlpbmdQcmljZQkBBGRpdmQCBRRzaG9ydFByZW1pdW1GcmFjdGlvbgUPdW5kZXJseWluZ1ByaWNlCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUABAdfcXRBc3RSCQEGcXRBc3RSAAQHX2JzQXN0UgkBBmJzQXN0UgAEDSR0MDgxMzc2ODE1MTEJARRnZXRTeW5jVGVybWluYWxQcmljZQMJAQ5nZXRPcmFjbGVQcmljZQAFB19xdEFzdFIFB19ic0FzdFIEE25ld1F1b3RlQXNzZXRXZWlnaHQIBQ0kdDA4MTM3NjgxNTExAl8xBBJuZXdCYXNlQXNzZXRXZWlnaHQIBQ0kdDA4MTM3NjgxNTExAl8yBA1tYXJnaW5Ub1ZhdWx0CAUNJHQwODEzNzY4MTUxMQJfMwQNZG9FeGNoYW5nZVBuTAMJAQIhPQIFDW1hcmdpblRvVmF1bHQAAAQNZG9FeGNoYW5nZVBuTAkA/AcECQEMdmF1bHRBZGRyZXNzAAIVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkCQDMCAIFDW1hcmdpblRvVmF1bHQFA25pbAUDbmlsAwkAAAIFDWRvRXhjaGFuZ2VQbkwFDWRvRXhjaGFuZ2VQbkwFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFDWRvRXhjaGFuZ2VQbkwFDWRvRXhjaGFuZ2VQbkwJAM4IAgkBEHVwZGF0ZUFtbVdlaWdodHMCBRNuZXdRdW90ZUFzc2V0V2VpZ2h0BRJuZXdCYXNlQXNzZXRXZWlnaHQJAQphcHBlbmRUd2FwAQkBBGRpdmQCCQEEbXVsZAIFB19xdEFzdFIFE25ld1F1b3RlQXNzZXRXZWlnaHQJAQRtdWxkAgUHX2JzQXN0UgUSbmV3QmFzZUFzc2V0V2VpZ2h0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBJ3ZpZXdfY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudAEHX3RyYWRlcgQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBA0kdDA4MjA4MDgyMTgxCQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBAxwb3NpdGlvblNpemUIBQ0kdDA4MjA4MDgyMTgxAl8xBA5wb3NpdGlvbk1hcmdpbggFDSR0MDgyMDgwODIxODECXzIEA3BvbggFDSR0MDgyMDgwODIxODECXzMEEXBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwODIwODA4MjE4MQJfNAQNJHQwODIxODQ4MjI4NQkBI2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sAgUHX3RyYWRlcgUPUE5MX09QVElPTl9TUE9UBBBwb3NpdGlvbk5vdGlvbmFsCAUNJHQwODIxODQ4MjI4NQJfMQQNdW5yZWFsaXplZFBubAgFDSR0MDgyMTg0ODIyODUCXzIEDSR0MDgyMjg4ODI0NjAJASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BAUMcG9zaXRpb25TaXplBQ5wb3NpdGlvbk1hcmdpbgURcG9zaXRpb25Mc3RVcGRDUEYFDXVucmVhbGl6ZWRQbmwEDHJlbWFpbk1hcmdpbggFDSR0MDgyMjg4ODI0NjACXzEEB2JhZERlYnQIBQ0kdDA4MjI4ODgyNDYwAl8yBA5mdW5kaW5nUGF5bWVudAgFDSR0MDgyMjg4ODI0NjACXzMJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkBAXMBBQxyZW1haW5NYXJnaW4JAQFzAQUOZnVuZGluZ1BheW1lbnQJAQFzAQkBDmdldE1hcmdpblJhdGlvAQUHX3RyYWRlcgkBAXMBBQ11bnJlYWxpemVkUG5sCQEBcwEFB2JhZERlYnQJAQFzAQUQcG9zaXRpb25Ob3Rpb25hbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARV2aWV3X2dldFBlZ0FkanVzdENvc3QBBl9wcmljZQQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABAZyZXN1bHQJARRnZXRTeW5jVGVybWluYWxQcmljZQMFBl9wcmljZQUHX3F0QXN0UgUHX2JzQXN0UgkAAgEJAKQDAQgFBnJlc3VsdAJfMwFpARh2aWV3X2dldFRlcm1pbmFsQW1tUHJpY2UABA0kdDA4Mjg3NjgyOTU3CQETZ2V0VGVybWluYWxBbW1TdGF0ZQAEGXRlcm1pbmFsUXVvdGVBc3NldFJlc2VydmUIBQ0kdDA4Mjg3NjgyOTU3Al8xBBh0ZXJtaW5hbEJhc2VBc3NldFJlc2VydmUIBQ0kdDA4Mjg3NjgyOTU3Al8yBAVwcmljZQkBBGRpdmQCCQEEbXVsZAIFGXRlcm1pbmFsUXVvdGVBc3NldFJlc2VydmUJAQZxdEFzdFcACQEEbXVsZAIFGHRlcm1pbmFsQmFzZUFzc2V0UmVzZXJ2ZQkBBmJzQXN0VwAJAAIBCQCkAwEFBXByaWNlAWkBD3ZpZXdfZ2V0RnVuZGluZwAED3VuZGVybHlpbmdQcmljZQkBDmdldE9yYWNsZVByaWNlAAQNJHQwODMxNzI4MzIzNAkBCmdldEZ1bmRpbmcABBRzaG9ydFByZW1pdW1GcmFjdGlvbggFDSR0MDgzMTcyODMyMzQCXzEEE2xvbmdQcmVtaXVtRnJhY3Rpb24IBQ0kdDA4MzE3MjgzMjM0Al8yBAtsb25nRnVuZGluZwkBBGRpdmQCBRNsb25nUHJlbWl1bUZyYWN0aW9uBQ91bmRlcmx5aW5nUHJpY2UEDHNob3J0RnVuZGluZwkBBGRpdmQCBRRzaG9ydFByZW1pdW1GcmFjdGlvbgUPdW5kZXJseWluZ1ByaWNlCQACAQkArAICCQCsAgIJAKwCAgkBAXMBBQtsb25nRnVuZGluZwkBAXMBBQxzaG9ydEZ1bmRpbmcJAQFzAQkBEGdldFR3YXBTcG90UHJpY2UACQEBcwEJAQ5nZXRPcmFjbGVQcmljZQABaQEYdmlld19nZXRCb3Jyb3dlZEJ5VHJhZGVyAQdfdHJhZGVyBA0kdDA4MzUyMDgzNTc0CQETZ2V0Qm9ycm93ZWRCeVRyYWRlcgEFB190cmFkZXIECGJvcnJvd2VkCAUNJHQwODM1MjA4MzU3NAJfMQQHYXNzZXRJZAgFDSR0MDgzNTIwODM1NzQCXzIJAAIBCQCsAgIJAQFzAQUIYm9ycm93ZWQFB2Fzc2V0SWQBaQEQY29tcHV0ZVNwb3RQcmljZQAEBnJlc3VsdAkBDGdldFNwb3RQcmljZQAJAJQKAgUDbmlsBQZyZXN1bHQBaQEfY29tcHV0ZUZlZUZvclRyYWRlcldpdGhBcnRpZmFjdAIHX3RyYWRlcgtfYXJ0aWZhY3RJZAQGcmVzdWx0CQEYZ2V0Rm9yVHJhZGVyV2l0aEFydGlmYWN0AgUHX3RyYWRlcgULX2FydGlmYWN0SWQJAJQKAgUDbmlsBQZyZXN1bHQBAnR4AQZ2ZXJpZnkACQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwAACQEOYWRtaW5QdWJsaWNLZXkA/FC08g==", "height": 2410474, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: GjhcU9KVRJpKdsqBfBHbezpmwHDGgW694LjeTX9hSyTo Next: HE2bhp5n4Epia62RFBNuYtJJj73D4VzvcSErugDm119V Diff:
OldNewDifferences
2424 let k_positionSequence = "k_positionSequence"
2525
2626 let k_positionAsset = "k_positionAsset"
27+
28+let k_positionFee = "k_positionFee"
2729
2830 let k_initialized = "k_initialized"
2931
415417 positionAsset
416418 case _ =>
417419 toBase58String(quoteAsset())
420+ }
421+ }
422+
423+
424+func getPositionFee (_trader) = {
425+ let positionFeeOpt = getInteger(this, toCompositeKey(k_positionFee, _trader))
426+ match positionFeeOpt {
427+ case positionFee: Int =>
428+ positionFee
429+ case _ =>
430+ fee()
418431 }
419432 }
420433
470483 let amountBaseAssetBought = if (_isAdd)
471484 then amountBaseAssetBoughtAbs
472485 else -(amountBaseAssetBoughtAbs)
473- let $t01684317013 = updateReserve(_isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
474- let quoteAssetReserveAfter1 = $t01684317013._1
475- let baseAssetReserveAfter1 = $t01684317013._2
476- let totalPositionSizeAfter1 = $t01684317013._3
486+ let $t01713817308 = updateReserve(_isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
487+ let quoteAssetReserveAfter1 = $t01713817308._1
488+ let baseAssetReserveAfter1 = $t01713817308._2
489+ let totalPositionSizeAfter1 = $t01713817308._3
477490 let priceBefore = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
478491 let marketPrice = divd(_quoteAssetAmount, amountBaseAssetBoughtAbs)
479492 let priceDiff = abs((priceBefore - marketPrice))
493506 }
494507 else 0
495508 let signedMargin = ((_marginDelta - fundingPayment) + _oldPositionMargin)
496- let $t01850018627 = if ((0 > signedMargin))
509+ let $t01879518922 = if ((0 > signedMargin))
497510 then $Tuple2(0, abs(signedMargin))
498511 else $Tuple2(abs(signedMargin), 0)
499- let remainMargin = $t01850018627._1
500- let badDebt = $t01850018627._2
512+ let remainMargin = $t01879518922._1
513+ let badDebt = $t01879518922._2
501514 $Tuple3(remainMargin, badDebt, fundingPayment)
502515 }
503516
515528 let quoteAssetDelta = abs((quoteAssetAfter - _quoteAssetReserve))
516529 let quoteAssetSold = muld(quoteAssetDelta, _quoteAssetWeight)
517530 let maxPriceImpactValue = maxPriceImpact()
518- let $t01979719959 = updateReserve(!(_isAdd), quoteAssetDelta, _baseAssetAmount)
519- let quoteAssetReserveAfter1 = $t01979719959._1
520- let baseAssetReserveAfter1 = $t01979719959._2
521- let totalPositionSizeAfter1 = $t01979719959._3
531+ let $t02009220254 = updateReserve(!(_isAdd), quoteAssetDelta, _baseAssetAmount)
532+ let quoteAssetReserveAfter1 = $t02009220254._1
533+ let baseAssetReserveAfter1 = $t02009220254._2
534+ let totalPositionSizeAfter1 = $t02009220254._3
522535 let marketPrice = divd(quoteAssetSold, _baseAssetAmount)
523536 let priceDiff = abs((priceBefore - marketPrice))
524537 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
620633 let isShort = (0 > _positionSize)
621634 let positionNotional = if ((_option == PNL_OPTION_SPOT))
622635 then {
623- let $t02491025130 = swapOutputWithReserves(!(isShort), positionSizeAbs, false, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
624- let outPositionNotional = $t02491025130._1
625- let x1 = $t02491025130._2
626- let x2 = $t02491025130._3
627- let x3 = $t02491025130._4
636+ let $t02520525425 = swapOutputWithReserves(!(isShort), positionSizeAbs, false, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
637+ let outPositionNotional = $t02520525425._1
638+ let x1 = $t02520525425._2
639+ let x2 = $t02520525425._3
640+ let x3 = $t02520525425._4
628641 outPositionNotional
629642 }
630643 else muld(positionSizeAbs, getOraclePrice())
645658
646659
647660 func getPositionNotionalAndUnrealizedPnl (_trader,_option) = {
648- let $t02655126679 = getPosition(_trader)
649- let positionSize = $t02655126679._1
650- let positionMargin = $t02655126679._2
651- let positionOpenNotional = $t02655126679._3
652- let positionLstUpdCPF = $t02655126679._4
661+ let $t02684626974 = getPosition(_trader)
662+ let positionSize = $t02684626974._1
663+ let positionMargin = $t02684626974._2
664+ let positionOpenNotional = $t02684626974._3
665+ let positionLstUpdCPF = $t02684626974._4
653666 getPositionNotionalAndUnrealizedPnlByValues(positionSize, positionOpenNotional, qtAstR(), qtAstW(), bsAstR(), bsAstW(), _option)
654667 }
655668
658671
659672
660673 func getMarginRatioByOption (_trader,_option) = {
661- let $t02719227303 = getPosition(_trader)
662- let positionSize = $t02719227303._1
663- let positionMargin = $t02719227303._2
664- let pon = $t02719227303._3
665- let positionLstUpdCPF = $t02719227303._4
666- let $t02730927402 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
667- let positionNotional = $t02730927402._1
668- let unrealizedPnl = $t02730927402._2
669- let $t02740727573 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
670- let remainMargin = $t02740727573._1
671- let badDebt = $t02740727573._2
674+ let $t02748727598 = getPosition(_trader)
675+ let positionSize = $t02748727598._1
676+ let positionMargin = $t02748727598._2
677+ let pon = $t02748727598._3
678+ let positionLstUpdCPF = $t02748727598._4
679+ let $t02760427697 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
680+ let positionNotional = $t02760427697._1
681+ let unrealizedPnl = $t02760427697._2
682+ let $t02770227868 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
683+ let remainMargin = $t02770227868._1
684+ let badDebt = $t02770227868._2
672685 calcMarginRatio(remainMargin, badDebt, positionNotional)
673686 }
674687
693706
694707
695708 func internalClosePosition (_trader,_checkMaxPriceImpact) = {
696- let $t02881328941 = getPosition(_trader)
697- let positionSize = $t02881328941._1
698- let positionMargin = $t02881328941._2
699- let positionOpenNotional = $t02881328941._3
700- let positionLstUpdCPF = $t02881328941._4
709+ let $t02910829236 = getPosition(_trader)
710+ let positionSize = $t02910829236._1
711+ let positionMargin = $t02910829236._2
712+ let positionOpenNotional = $t02910829236._3
713+ let positionLstUpdCPF = $t02910829236._4
701714 let unrealizedPnl = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)._2
702- let $t02903629204 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
703- let remainMargin = $t02903629204._1
704- let badDebt = $t02903629204._2
715+ let $t02933129499 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
716+ let remainMargin = $t02933129499._1
717+ let badDebt = $t02933129499._2
705718 let exchangedPositionSize = -(positionSize)
706719 let realizedPnl = unrealizedPnl
707720 let marginToVault = -(remainMargin)
708- let $t02933129605 = swapOutput((positionSize > 0), abs(positionSize), _checkMaxPriceImpact)
709- let exchangedQuoteAssetAmount = $t02933129605._1
710- let quoteAssetReserveAfter = $t02933129605._2
711- let baseAssetReserveAfter = $t02933129605._3
712- let totalPositionSizeAfter = $t02933129605._4
713- let totalLongAfter = $t02933129605._5
714- let totalShortAfter = $t02933129605._6
721+ let $t02962629900 = swapOutput((positionSize > 0), abs(positionSize), _checkMaxPriceImpact)
722+ let exchangedQuoteAssetAmount = $t02962629900._1
723+ let quoteAssetReserveAfter = $t02962629900._2
724+ let baseAssetReserveAfter = $t02962629900._3
725+ let totalPositionSizeAfter = $t02962629900._4
726+ let totalLongAfter = $t02962629900._5
727+ let totalShortAfter = $t02962629900._6
715728 let openInterestNotionalAfter = (openInterestNotional() - positionOpenNotional)
716729 $Tuple13(exchangedPositionSize, badDebt, realizedPnl, marginToVault, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, exchangedQuoteAssetAmount, totalLongAfter, totalShortAfter, (openInterestLong() - (if ((positionSize > 0))
717730 then positionOpenNotional
764777 then $Tuple2(qtAstR(), bsAstR())
765778 else {
766779 let direction = (_positionSize > 0)
767- let $t03172831907 = swapOutput(direction, abs(_positionSize), false)
768- let currentNetMarketValue = $t03172831907._1
769- let terminalQuoteAssetReserve = $t03172831907._2
770- let terminalBaseAssetReserve = $t03172831907._3
780+ let $t03202332202 = swapOutput(direction, abs(_positionSize), false)
781+ let currentNetMarketValue = $t03202332202._1
782+ let terminalQuoteAssetReserve = $t03202332202._2
783+ let terminalBaseAssetReserve = $t03202332202._3
771784 $Tuple2(terminalQuoteAssetReserve, terminalBaseAssetReserve)
772785 }
773786 }
832845 func getAdjustedFee (_artifactId,_baseFeeDiscount) = {
833846 let baseFeeRaw = fee()
834847 let baseFee = muld(baseFeeRaw, _baseFeeDiscount)
835- let $t03476835263 = if ((_artifactId != ""))
848+ let $t03506335558 = if ((_artifactId != ""))
836849 then {
837850 let artifactKind = strA(nftManagerAddress(), toCompositeKey(k_token_type, _artifactId))
838851 if ((artifactKind == FEE_REDUCTION_TOKEN_TYPE))
844857 else throw("Invalid attached artifact")
845858 }
846859 else $Tuple2(baseFee, false)
847- let adjustedFee = $t03476835263._1
848- let burnArtifact = $t03476835263._2
860+ let adjustedFee = $t03506335558._1
861+ let burnArtifact = $t03506335558._2
849862 $Tuple2(adjustedFee, burnArtifact)
850863 }
851864
886899 case _ =>
887900 throw("Invalid computeFeeDiscount result")
888901 }
889- let $t03649436568 = getAdjustedFee(_artifactId, feeDiscount)
890- let adjustedFee = $t03649436568._1
891- let burnArtifact = $t03649436568._2
902+ let $t03678936863 = getAdjustedFee(_artifactId, feeDiscount)
903+ let adjustedFee = $t03678936863._1
904+ let burnArtifact = $t03678936863._2
892905 $Tuple2(adjustedFee, burnArtifact)
893906 }
894907 else throw("Strict value is not equal to itself.")
919932 func updatePositionAsset (_address,_assetId) = [StringEntry(toCompositeKey(k_positionAsset, _address), _assetId)]
920933
921934
922-func incrementPositionSequenceNumber (isNewPosition,_address) = if (isNewPosition)
935+func incrementPositionSequenceNumber (_isNewPosition,_address) = if (_isNewPosition)
923936 then {
924937 let currentSequence = lastSequence()
925938 [IntegerEntry(toCompositeKey(k_positionSequence, _address), (currentSequence + 1)), IntegerEntry(k_sequence, (currentSequence + 1))]
926939 }
940+ else nil
941+
942+
943+func updatePositionFee (_isNewPosition,_address,_fee) = if (_isNewPosition)
944+ then [IntegerEntry(toCompositeKey(k_positionFee, _address), _fee)]
927945 else nil
928946
929947
10391057 let qtAstRAfter = (_qtAstR + _quoteAssetAmount)
10401058 let baseAssetAmountToAdd = (divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR)
10411059 let bsAstRAfter = (_bsAstR + baseAssetAmountToAdd)
1042- let $t04559045741 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1043- let newQuoteAssetWeight = $t04559045741._1
1044- let newBaseAssetWeight = $t04559045741._2
1045- let marginToVault = $t04559045741._3
1060+ let $t04610746258 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1061+ let newQuoteAssetWeight = $t04610746258._1
1062+ let newBaseAssetWeight = $t04610746258._2
1063+ let marginToVault = $t04610746258._3
10461064 let doExchangePnL = if ((marginToVault != 0))
10471065 then {
10481066 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
10611079 @Callable(i)
10621080 func removeLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
10631081 then true
1064- else (0 >= _quoteAssetAmount))
1082+ else (_quoteAssetAmount >= 0))
10651083 then throw("Invalid removeLiquidity params")
10661084 else {
10671085 let _qtAstR = qtAstR()
10691087 let _qtAstW = qtAstW()
10701088 let _bsAstW = bsAstW()
10711089 let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
1072- let baseAssetAmountToRemove = divd(_quoteAssetAmount, price)
10731090 let qtAstRAfter = (_qtAstR - _quoteAssetAmount)
1091+ let baseAssetAmountToRemove = abs((divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR))
10741092 let bsAstRAfter = (_bsAstR - baseAssetAmountToRemove)
1075- updateAmmReserves(qtAstRAfter, bsAstRAfter)
1093+ let $t04719047341 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1094+ let newQuoteAssetWeight = $t04719047341._1
1095+ let newBaseAssetWeight = $t04719047341._2
1096+ let marginToVault = $t04719047341._3
1097+ let doExchangePnL = if ((marginToVault != 0))
1098+ then {
1099+ let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
1100+ if ((doExchangePnL == doExchangePnL))
1101+ then nil
1102+ else throw("Strict value is not equal to itself.")
1103+ }
1104+ else nil
1105+ if ((doExchangePnL == doExchangePnL))
1106+ then (updateAmmReserves(qtAstRAfter, bsAstRAfter) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
1107+ else throw("Strict value is not equal to itself.")
10761108 }
10771109
10781110
11221154
11231155
11241156 @Callable(i)
1125-func decreasePosition (_amount,_leverage,_minBaseAssetAmount) = {
1126- let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
1127- if ((sync == sync))
1128- then {
1129- let _trader = getActualCaller(i)
1130- if (if (if (if (if (if ((0 >= _amount))
1131- then true
1132- else !(initialized()))
1133- then true
1134- else !(requireMoreMarginRatio(divd(DECIMAL_UNIT, _leverage), initMarginRatio(), true)))
1135- then true
1136- else !(requireOpenPosition(_trader)))
1137- then true
1138- else paused())
1139- then true
1140- else isMarketClosed())
1141- then throw("Invalid decreasePosition parameters")
1142- else {
1143- let $t04960849748 = getPosition(_trader)
1144- let oldPositionSize = $t04960849748._1
1145- let oldPositionMargin = $t04960849748._2
1146- let oldPositionOpenNotional = $t04960849748._3
1147- let oldPositionLstUpdCPF = $t04960849748._4
1148- let _direction = if ((oldPositionSize > 0))
1149- then DIR_SHORT
1150- else DIR_LONG
1151- let isAdd = (_direction == DIR_LONG)
1152- let openNotional = muld(_amount, _leverage)
1153- let $t04992150025 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1154- let oldPositionNotional = $t04992150025._1
1155- let unrealizedPnl = $t04992150025._2
1156- let $t05003152673 = if ((oldPositionNotional > openNotional))
1157- then {
1158- let $t05044650630 = swapInput(isAdd, openNotional)
1159- let exchangedPositionSize = $t05044650630._1
1160- let quoteAssetReserveAfter = $t05044650630._2
1161- let baseAssetReserveAfter = $t05044650630._3
1162- let totalPositionSizeAfter = $t05044650630._4
1163- let exchangedPositionSizeAbs = abs(exchangedPositionSize)
1164- if (if ((_minBaseAssetAmount != 0))
1165- then (_minBaseAssetAmount > exchangedPositionSizeAbs)
1166- else false)
1167- then throw(((("Too little base asset exchanged, got " + toString(exchangedPositionSizeAbs)) + " expected ") + toString(_minBaseAssetAmount)))
1168- else {
1169- let realizedPnl = divd(muld(unrealizedPnl, exchangedPositionSizeAbs), abs(oldPositionSize))
1170- let $t05106751296 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1171- let remainMargin = $t05106751296._1
1172- let badDebt = $t05106751296._2
1173- let exchangedQuoteAssetAmount = openNotional
1174- let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
1175- let remainOpenNotional = if ((oldPositionSize > 0))
1176- then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
1177- else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
1178- let newPositionSize = (oldPositionSize + exchangedPositionSize)
1179- $Tuple12(newPositionSize, remainMargin, abs(remainOpenNotional), latestCumulativePremiumFraction(newPositionSize), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, (openInterestNotional() - openNotional), (totalLongPositionSize() - (if ((newPositionSize > 0))
1180- then abs(exchangedPositionSize)
1181- else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
1182- then abs(exchangedPositionSize)
1183- else 0)), (openInterestLong() - (if ((newPositionSize > 0))
1184- then openNotional
1185- else 0)), (openInterestShort() - (if ((0 > newPositionSize))
1186- then openNotional
1187- else 0)))
1188- }
1189- }
1190- else throw("Close position first")
1191- let newPositionSize = $t05003152673._1
1192- let newPositionRemainMargin = $t05003152673._2
1193- let newPositionOpenNotional = $t05003152673._3
1194- let newPositionLatestCPF = $t05003152673._4
1195- let baseAssetReserveAfter = $t05003152673._5
1196- let quoteAssetReserveAfter = $t05003152673._6
1197- let totalPositionSizeAfter = $t05003152673._7
1198- let openInterestNotionalAfter = $t05003152673._8
1199- let totalLongAfter = $t05003152673._9
1200- let totalShortAfter = $t05003152673._10
1201- let totalLongOpenInterestAfter = $t05003152673._11
1202- let totalShortOpenInterestAfter = $t05003152673._12
1203- let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
1204- if ((notifyNotional == notifyNotional))
1205- then (updatePosition(_trader, newPositionSize, newPositionRemainMargin, newPositionOpenNotional, newPositionLatestCPF) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter))
1206- else throw("Strict value is not equal to itself.")
1207- }
1208- }
1209- else throw("Strict value is not equal to itself.")
1210- }
1211-
1212-
1213-
1214-@Callable(i)
12151157 func increasePosition (_direction,_leverage,_minBaseAssetAmount,_refLink) = {
12161158 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
12171159 if ((sync == sync))
12451187 else isMarketClosed())
12461188 then throw("Invalid increasePosition parameters")
12471189 else {
1248- let $t05413554220 = getForTraderWithArtifact(_trader, getArtifactId(i))
1249- let adjustedFee = $t05413554220._1
1250- let burnArtifact = $t05413554220._2
1251- let rawFeeAmount = muld(_rawAmount, adjustedFee)
1252- let _amount = (_rawAmount - rawFeeAmount)
1190+ let $t05100951158 = getForTraderWithArtifact(_trader, getArtifactId(i))
1191+ let adjustedFee = $t05100951158._1
1192+ let burnArtifact = $t05100951158._2
1193+ let _amount = divd(_rawAmount, (muld(adjustedFee, _leverage) + DECIMAL_UNIT))
1194+ let rawFeeAmount = (_rawAmount - _amount)
12531195 let distributeFeeAmount = if (isCollateralAsset)
12541196 then {
12551197 let doBorrow = invoke(collateralAddress(), "borrow", [_trader], [AttachedPayment(_assetId, _amount)])
12901232 throw("Invalid referrerFee")
12911233 }
12921234 let feeAmount = (distributeFeeAmount - referrerFee)
1293- let $t05553655676 = getPosition(_trader)
1294- let oldPositionSize = $t05553655676._1
1295- let oldPositionMargin = $t05553655676._2
1296- let oldPositionOpenNotional = $t05553655676._3
1297- let oldPositionLstUpdCPF = $t05553655676._4
1235+ let $t05250052640 = getPosition(_trader)
1236+ let oldPositionSize = $t05250052640._1
1237+ let oldPositionMargin = $t05250052640._2
1238+ let oldPositionOpenNotional = $t05250052640._3
1239+ let oldPositionLstUpdCPF = $t05250052640._4
12981240 let isNewPosition = (oldPositionSize == 0)
12991241 let isSameDirection = if ((oldPositionSize > 0))
13001242 then (_direction == DIR_LONG)
13031245 then isSameDirection
13041246 else false
13051247 let isAdd = (_direction == DIR_LONG)
1306- let $t05596558927 = if (if (isNewPosition)
1248+ let $t05292955891 = if (if (isNewPosition)
13071249 then true
13081250 else expandExisting)
13091251 then {
13101252 let openNotional = muld(_amount, _leverage)
1311- let $t05642756600 = swapInput(isAdd, openNotional)
1312- let amountBaseAssetBought = $t05642756600._1
1313- let quoteAssetReserveAfter = $t05642756600._2
1314- let baseAssetReserveAfter = $t05642756600._3
1315- let totalPositionSizeAfter = $t05642756600._4
1253+ let $t05339153564 = swapInput(isAdd, openNotional)
1254+ let amountBaseAssetBought = $t05339153564._1
1255+ let quoteAssetReserveAfter = $t05339153564._2
1256+ let baseAssetReserveAfter = $t05339153564._3
1257+ let totalPositionSizeAfter = $t05339153564._4
13161258 if (if ((_minBaseAssetAmount != 0))
13171259 then (_minBaseAssetAmount > abs(amountBaseAssetBought))
13181260 else false)
13251267 let totalShortOpenInterestAfter = (openInterestShort() + (if ((0 > newPositionSize))
13261268 then openNotional
13271269 else 0))
1328- let $t05714657367 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, _amount)
1329- let remainMargin = $t05714657367._1
1330- let x1 = $t05714657367._2
1331- let x2 = $t05714657367._3
1270+ let $t05411054331 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, _amount)
1271+ let remainMargin = $t05411054331._1
1272+ let x1 = $t05411054331._2
1273+ let x2 = $t05411054331._3
13321274 if (!(requireNotOverSpreadLimit(quoteAssetReserveAfter, baseAssetReserveAfter)))
13331275 then throw("Over max spread limit")
13341276 else if (!(requireNotOverMaxOpenNotional(totalLongOpenInterestAfter, totalShortOpenInterestAfter)))
13421284 }
13431285 else {
13441286 let openNotional = muld(_amount, _leverage)
1345- let $t05862758743 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1346- let oldPositionNotional = $t05862758743._1
1347- let unrealizedPnl = $t05862758743._2
1287+ let $t05559155707 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1288+ let oldPositionNotional = $t05559155707._1
1289+ let unrealizedPnl = $t05559155707._2
13481290 if ((oldPositionNotional > openNotional))
13491291 then throw("Use decreasePosition to decrease position size")
13501292 else throw("Close position first")
13511293 }
1352- let newPositionSize = $t05596558927._1
1353- let newPositionRemainMargin = $t05596558927._2
1354- let newPositionOpenNotional = $t05596558927._3
1355- let newPositionLatestCPF = $t05596558927._4
1356- let baseAssetReserveAfter = $t05596558927._5
1357- let quoteAssetReserveAfter = $t05596558927._6
1358- let totalPositionSizeAfter = $t05596558927._7
1359- let openInterestNotionalAfter = $t05596558927._8
1360- let totalLongAfter = $t05596558927._9
1361- let totalShortAfter = $t05596558927._10
1362- let totalLongOpenInterestAfter = $t05596558927._11
1363- let totalShortOpenInterestAfter = $t05596558927._12
1364- let $t05893358990 = distributeFee(feeAmount)
1365- let feeToStakers = $t05893358990._1
1366- let feeToVault = $t05893358990._2
1294+ let newPositionSize = $t05292955891._1
1295+ let newPositionRemainMargin = $t05292955891._2
1296+ let newPositionOpenNotional = $t05292955891._3
1297+ let newPositionLatestCPF = $t05292955891._4
1298+ let baseAssetReserveAfter = $t05292955891._5
1299+ let quoteAssetReserveAfter = $t05292955891._6
1300+ let totalPositionSizeAfter = $t05292955891._7
1301+ let openInterestNotionalAfter = $t05292955891._8
1302+ let totalLongAfter = $t05292955891._9
1303+ let totalShortAfter = $t05292955891._10
1304+ let totalLongOpenInterestAfter = $t05292955891._11
1305+ let totalShortOpenInterestAfter = $t05292955891._12
1306+ let $t05589755954 = distributeFee(feeAmount)
1307+ let feeToStakers = $t05589755954._1
1308+ let feeToVault = $t05589755954._2
13671309 let stake = if (isQuoteAsset)
13681310 then {
13691311 let stake = invoke(vaultAddress(), "addLocked", [false], [AttachedPayment(quoteAsset(), _amount)])
13741316 else nil
13751317 if ((stake == stake))
13761318 then {
1377- let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
1378- if ((depositInsurance == depositInsurance))
1319+ let depositVault = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
1320+ if ((depositVault == depositVault))
13791321 then {
13801322 let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, feeAmount], nil)
13811323 if ((notifyFee == notifyFee))
13821324 then {
13831325 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
13841326 if ((notifyNotional == notifyNotional))
1385- 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))
1327+ then (((((((updatePosition(_trader, newPositionSize, newPositionRemainMargin, newPositionOpenNotional, newPositionLatestCPF) ++ incrementPositionSequenceNumber(isNewPosition, _trader)) ++ updatePositionFee(isNewPosition, _trader, adjustedFee)) ++ updatePositionAsset(_trader, _assetIdStr)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ transferFee(feeToStakers)) ++ updateBalance((cbalance() + _amount))) ++ doBurnArtifact(burnArtifact, i))
13861328 else throw("Strict value is not equal to itself.")
13871329 }
13881330 else throw("Strict value is not equal to itself.")
14071349 if ((sync == sync))
14081350 then {
14091351 let _trader = toString(i.caller)
1410- let _rawAmount = i.payments[0].amount
1352+ let _amount = i.payments[0].amount
14111353 let _assetId = i.payments[0].assetId
14121354 let _assetIdStr = toBase58String(value(_assetId))
14131355 let isQuoteAsset = (_assetId == quoteAsset())
14291371 else isMarketClosed())
14301372 then throw("Invalid addMargin parameters")
14311373 else {
1432- let $t06096261047 = getForTraderWithArtifact(_trader, getArtifactId(i))
1433- let adjustedFee = $t06096261047._1
1434- let burnArtifact = $t06096261047._2
1435- let rawFeeAmount = muld(_rawAmount, adjustedFee)
1436- let _amount = (_rawAmount - rawFeeAmount)
1437- let distributeFeeAmount = if (isCollateralAsset)
1374+ let $t05798558125 = getPosition(_trader)
1375+ let oldPositionSize = $t05798558125._1
1376+ let oldPositionMargin = $t05798558125._2
1377+ let oldPositionOpenNotional = $t05798558125._3
1378+ let oldPositionLstUpdCPF = $t05798558125._4
1379+ let stake = if (isQuoteAsset)
14381380 then {
1439- let doBorrow = invoke(collateralAddress(), "borrow", [_trader], [AttachedPayment(_assetId, _amount)])
1440- if ((doBorrow == doBorrow))
1441- then {
1442- let balanceBefore = assetBalance(this, quoteAsset())
1443- if ((balanceBefore == balanceBefore))
1444- then {
1445- let doSwap = invoke(swapAddress(), "swap", [toBase58String(quoteAsset()), 0], [AttachedPayment(_assetId, rawFeeAmount)])
1446- if ((doSwap == doSwap))
1447- then {
1448- let balanceAfter = assetBalance(this, quoteAsset())
1449- if ((balanceAfter == balanceAfter))
1450- then {
1451- let exchangedAmount = (balanceAfter - balanceBefore)
1452- if ((exchangedAmount == exchangedAmount))
1453- then exchangedAmount
1454- else throw("Strict value is not equal to itself.")
1455- }
1456- else throw("Strict value is not equal to itself.")
1457- }
1458- else throw("Strict value is not equal to itself.")
1459- }
1460- else throw("Strict value is not equal to itself.")
1461- }
1381+ let stake = invoke(vaultAddress(), "addLocked", [false], [AttachedPayment(quoteAsset(), _amount)])
1382+ if ((stake == stake))
1383+ then nil
14621384 else throw("Strict value is not equal to itself.")
14631385 }
1464- else rawFeeAmount
1465- if ((distributeFeeAmount == distributeFeeAmount))
1466- then {
1467- let referrerFeeAny = invoke(referralAddress(), "acceptPayment", [_trader], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
1468- if ((referrerFeeAny == referrerFeeAny))
1469- then {
1470- let referrerFee = match referrerFeeAny {
1471- case x: Int =>
1472- x
1473- case _ =>
1474- throw("Invalid referrerFee")
1475- }
1476- let feeAmount = (distributeFeeAmount - referrerFee)
1477- let $t06234662486 = getPosition(_trader)
1478- let oldPositionSize = $t06234662486._1
1479- let oldPositionMargin = $t06234662486._2
1480- let oldPositionOpenNotional = $t06234662486._3
1481- let oldPositionLstUpdCPF = $t06234662486._4
1482- let $t06249262549 = distributeFee(feeAmount)
1483- let feeToStakers = $t06249262549._1
1484- let feeToVault = $t06249262549._2
1485- let stake = if (isQuoteAsset)
1486- then {
1487- let stake = invoke(vaultAddress(), "addLocked", [false], [AttachedPayment(quoteAsset(), _amount)])
1488- if ((stake == stake))
1489- then nil
1490- else throw("Strict value is not equal to itself.")
1491- }
1492- else nil
1493- if ((stake == stake))
1494- then {
1495- let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
1496- if ((depositInsurance == depositInsurance))
1497- then {
1498- let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, feeAmount], nil)
1499- if ((notifyFee == notifyFee))
1500- then (((updatePosition(_trader, oldPositionSize, (oldPositionMargin + _amount), oldPositionOpenNotional, oldPositionLstUpdCPF) ++ transferFee(feeToStakers)) ++ updateBalance((cbalance() + _amount))) ++ doBurnArtifact(burnArtifact, i))
1501- else throw("Strict value is not equal to itself.")
1502- }
1503- else throw("Strict value is not equal to itself.")
1504- }
1505- else throw("Strict value is not equal to itself.")
1506- }
1507- else throw("Strict value is not equal to itself.")
1508- }
1386+ else nil
1387+ if ((stake == stake))
1388+ then (updatePosition(_trader, oldPositionSize, (oldPositionMargin + _amount), oldPositionOpenNotional, oldPositionLstUpdCPF) ++ updateBalance((cbalance() + _amount)))
15091389 else throw("Strict value is not equal to itself.")
15101390 }
15111391 }
15311411 else isMarketClosed())
15321412 then throw("Invalid removeMargin parameters")
15331413 else {
1534- let $t06368563825 = getPosition(_trader)
1535- let oldPositionSize = $t06368563825._1
1536- let oldPositionMargin = $t06368563825._2
1537- let oldPositionOpenNotional = $t06368563825._3
1538- let oldPositionLstUpdCPF = $t06368563825._4
1414+ let $t05892059060 = getPosition(_trader)
1415+ let oldPositionSize = $t05892059060._1
1416+ let oldPositionMargin = $t05892059060._2
1417+ let oldPositionOpenNotional = $t05892059060._3
1418+ let oldPositionLstUpdCPF = $t05892059060._4
15391419 let marginDelta = -(_amount)
1540- let $t06386264041 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, marginDelta)
1541- let remainMargin = $t06386264041._1
1542- let badDebt = $t06386264041._2
1420+ let $t05909759276 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, marginDelta)
1421+ let remainMargin = $t05909759276._1
1422+ let badDebt = $t05909759276._2
15431423 if ((badDebt != 0))
15441424 then throw("Invalid removed margin amount")
15451425 else {
15481428 then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
15491429 else {
15501430 let quoteAssetStr = toBase58String(quoteAsset())
1551- let $t06448564539 = getBorrowedByTrader(_trader)
1552- let borrowed = $t06448564539._1
1553- let assetId = $t06448564539._2
1431+ let $t05972059774 = getBorrowedByTrader(_trader)
1432+ let borrowed = $t05972059774._1
1433+ let assetId = $t05972059774._2
15541434 let toRepay = if ((_amount > borrowed))
15551435 then borrowed
15561436 else _amount
16031483
16041484
16051485 @Callable(i)
1606-func closePosition (_size,_minQuoteAssetAmount) = {
1486+func closePosition (_size,_minQuoteAssetAmount,_addToMargin) = {
16071487 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
16081488 if ((sync == sync))
16091489 then {
16101490 let _trader = getActualCaller(i)
16111491 let _traderAddress = valueOrErrorMessage(addressFromString(_trader), "Invalid caller")
1492+ let positionFee = getPositionFee(_trader)
16121493 if (if (if (if (if (if (!(requireOpenPosition(_trader)))
16131494 then true
16141495 else !(initialized()))
16221503 else isMarketClosed())
16231504 then throw("Invalid closePosition parameters")
16241505 else {
1625- let $t06672366863 = getPosition(_trader)
1626- let oldPositionSize = $t06672366863._1
1627- let oldPositionMargin = $t06672366863._2
1628- let oldPositionOpenNotional = $t06672366863._3
1629- let oldPositionLstUpdCPF = $t06672366863._4
1630- let $t06686971999 = if ((abs(oldPositionSize) > _size))
1506+ let $t06201162151 = getPosition(_trader)
1507+ let oldPositionSize = $t06201162151._1
1508+ let oldPositionMargin = $t06201162151._2
1509+ let oldPositionOpenNotional = $t06201162151._3
1510+ let oldPositionLstUpdCPF = $t06201162151._4
1511+ let $t06215768035 = if ((abs(oldPositionSize) > _size))
16311512 then {
16321513 let _direction = if ((oldPositionSize > 0))
16331514 then DIR_SHORT
16341515 else DIR_LONG
16351516 let isAdd = (_direction == DIR_LONG)
1636- let $t06746067682 = swapOutput((oldPositionSize > 0), _size, true)
1637- let exchangedQuoteAssetAmount = $t06746067682._1
1638- let quoteAssetReserveAfter = $t06746067682._2
1639- let baseAssetReserveAfter = $t06746067682._3
1640- let totalPositionSizeAfter = $t06746067682._4
1517+ let $t06276862990 = swapOutput((oldPositionSize > 0), _size, true)
1518+ let exchangedQuoteAssetAmount = $t06276862990._1
1519+ let quoteAssetReserveAfter = $t06276862990._2
1520+ let baseAssetReserveAfter = $t06276862990._3
1521+ let totalPositionSizeAfter = $t06276862990._4
16411522 let exchangedPositionSize = if ((oldPositionSize > 0))
16421523 then -(_size)
16431524 else _size
1644- let $t06777367927 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1645- let oldPositionNotional = $t06777367927._1
1646- let unrealizedPnl = $t06777367927._2
1525+ let $t06308163235 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1526+ let oldPositionNotional = $t06308163235._1
1527+ let unrealizedPnl = $t06308163235._2
16471528 let mr = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
16481529 let realizedRatio = divd(abs(exchangedPositionSize), abs(oldPositionSize))
16491530 let realizedPnl = muld(unrealizedPnl, realizedRatio)
1531+ let realizedFee = muld(muld(oldPositionNotional, realizedRatio), positionFee)
16501532 let remainMarginBefore = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, unrealizedPnl)._1
1651- let $t06842868656 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1652- let x1 = $t06842868656._1
1653- let positionBadDebt = $t06842868656._2
1654- let fundingPayment = $t06842868656._3
1533+ let positionBadDebt = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)._2
16551534 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
16561535 let remainOpenNotional = if ((oldPositionSize > 0))
16571536 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
16581537 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
16591538 let newPositionOpenNotional = abs(remainOpenNotional)
1539+ let newPositionSize = (oldPositionSize + exchangedPositionSize)
1540+ let newPositionLstUpdCPF = latestCumulativePremiumFraction(newPositionSize)
1541+ let openNotionalDelta = (oldPositionOpenNotional - newPositionOpenNotional)
1542+ let openInterestNotionalAfter = (openInterestNotional() - openNotionalDelta)
16601543 let newPositionMargin = if ((oldPositionSize > 0))
16611544 then (muld((newPositionOpenNotional + unrealizedPnlAfter), mr) - unrealizedPnlAfter)
16621545 else (muld((newPositionOpenNotional - unrealizedPnlAfter), mr) - unrealizedPnlAfter)
1663- let openNotionalDelta = (oldPositionOpenNotional - newPositionOpenNotional)
1664- let newPositionSize = (oldPositionSize + exchangedPositionSize)
1665- let newPositionLstUpdCPF = latestCumulativePremiumFraction(newPositionSize)
1666- let openInterestNotionalAfter = (openInterestNotional() - openNotionalDelta)
1546+ let marginToTraderRaw = ((remainMarginBefore - (newPositionMargin + unrealizedPnlAfter)) - realizedFee)
1547+ let marginToTrader = if ((0 > marginToTraderRaw))
1548+ then throw("Margin error: unable to pay close fee")
1549+ else marginToTraderRaw
16671550 if (if ((_minQuoteAssetAmount != 0))
16681551 then (_minQuoteAssetAmount > exchangedQuoteAssetAmount)
16691552 else false)
16701553 then throw(((("Limit error: " + toString(exchangedQuoteAssetAmount)) + " < ") + toString(_minQuoteAssetAmount)))
1671- else $Tuple15(newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, positionBadDebt, realizedPnl, (remainMarginBefore - (newPositionMargin + unrealizedPnlAfter)), quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, (totalLongPositionSize() - (if ((newPositionSize > 0))
1554+ else $Tuple16(newPositionSize, if (_addToMargin)
1555+ then (newPositionMargin + marginToTrader)
1556+ else newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, positionBadDebt, realizedPnl, if (_addToMargin)
1557+ then 0
1558+ else marginToTrader, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, (totalLongPositionSize() - (if ((newPositionSize > 0))
16721559 then abs(exchangedPositionSize)
16731560 else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
16741561 then abs(exchangedPositionSize)
16761563 then openNotionalDelta
16771564 else 0)), (openInterestShort() - (if ((0 > newPositionSize))
16781565 then openNotionalDelta
1679- else 0)))
1566+ else 0)), realizedFee)
16801567 }
16811568 else if ((_size > abs(oldPositionSize)))
16821569 then throw("Invalid closePosition parameters")
16831570 else {
1684- let $t07094071359 = internalClosePosition(_trader, true)
1685- let exchangedQuoteAssetAmount = $t07094071359._1
1686- let positionBadDebt = $t07094071359._2
1687- let realizedPnl = $t07094071359._3
1688- let marginToVault = $t07094071359._4
1689- let quoteAssetReserveAfter = $t07094071359._5
1690- let baseAssetReserveAfter = $t07094071359._6
1691- let totalPositionSizeAfter = $t07094071359._7
1692- let openInterestNotionalAfter = $t07094071359._8
1693- let x2 = $t07094071359._9
1694- let totalLongAfter = $t07094071359._10
1695- let totalShortAfter = $t07094071359._11
1696- let totalLongOpenInterestAfter = $t07094071359._12
1697- let totalShortOpenInterestAfter = $t07094071359._13
1571+ let $t06645466884 = internalClosePosition(_trader, true)
1572+ let x2 = $t06645466884._1
1573+ let positionBadDebt = $t06645466884._2
1574+ let realizedPnl = $t06645466884._3
1575+ let marginToTraderWithoutFee = $t06645466884._4
1576+ let quoteAssetReserveAfter = $t06645466884._5
1577+ let baseAssetReserveAfter = $t06645466884._6
1578+ let totalPositionSizeAfter = $t06645466884._7
1579+ let openInterestNotionalAfter = $t06645466884._8
1580+ let exchangedQuoteAssetAmount = $t06645466884._9
1581+ let totalLongAfter = $t06645466884._10
1582+ let totalShortAfter = $t06645466884._11
1583+ let totalLongOpenInterestAfter = $t06645466884._12
1584+ let totalShortOpenInterestAfter = $t06645466884._13
1585+ let realizedFee = muld(exchangedQuoteAssetAmount, positionFee)
1586+ let marginToTraderRaw = (abs(marginToTraderWithoutFee) - realizedFee)
1587+ let marginToTrader = if ((0 > marginToTraderRaw))
1588+ then throw(((((((("Margin error: unable to pay close fee: " + toString(realizedFee)) + " margin: ") + toString(marginToTraderWithoutFee)) + " fee percent: ") + toString(positionFee)) + " notional: ") + toString(exchangedQuoteAssetAmount)))
1589+ else marginToTraderRaw
16981590 if (if ((_minQuoteAssetAmount != 0))
16991591 then (_minQuoteAssetAmount > exchangedQuoteAssetAmount)
17001592 else false)
17011593 then throw(((("Limit error: " + toString(exchangedQuoteAssetAmount)) + " < ") + toString(_minQuoteAssetAmount)))
1702- else $Tuple15(0, 0, 0, 0, positionBadDebt, realizedPnl, marginToVault, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)
1594+ else $Tuple16(0, 0, 0, 0, positionBadDebt, realizedPnl, marginToTrader, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter, realizedFee)
17031595 }
1704- let newPositionSize = $t06686971999._1
1705- let newPositionMargin = $t06686971999._2
1706- let newPositionOpenNotional = $t06686971999._3
1707- let newPositionLstUpdCPF = $t06686971999._4
1708- let positionBadDebt = $t06686971999._5
1709- let realizedPnl = $t06686971999._6
1710- let marginToVault = $t06686971999._7
1711- let quoteAssetReserveAfter = $t06686971999._8
1712- let baseAssetReserveAfter = $t06686971999._9
1713- let totalPositionSizeAfter = $t06686971999._10
1714- let openInterestNotionalAfter = $t06686971999._11
1715- let totalLongAfter = $t06686971999._12
1716- let totalShortAfter = $t06686971999._13
1717- let totalLongOpenInterestAfter = $t06686971999._14
1718- let totalShortOpenInterestAfter = $t06686971999._15
1596+ let newPositionSize = $t06215768035._1
1597+ let newPositionMargin = $t06215768035._2
1598+ let newPositionOpenNotional = $t06215768035._3
1599+ let newPositionLstUpdCPF = $t06215768035._4
1600+ let positionBadDebt = $t06215768035._5
1601+ let realizedPnl = $t06215768035._6
1602+ let marginToTrader = $t06215768035._7
1603+ let quoteAssetReserveAfter = $t06215768035._8
1604+ let baseAssetReserveAfter = $t06215768035._9
1605+ let totalPositionSizeAfter = $t06215768035._10
1606+ let openInterestNotionalAfter = $t06215768035._11
1607+ let totalLongAfter = $t06215768035._12
1608+ let totalShortAfter = $t06215768035._13
1609+ let totalLongOpenInterestAfter = $t06215768035._14
1610+ let totalShortOpenInterestAfter = $t06215768035._15
1611+ let realizedFee = $t06215768035._16
17191612 if ((positionBadDebt > 0))
17201613 then throw("Unable to close position with bad debt")
17211614 else {
1722- let withdrawAmount = abs(marginToVault)
1615+ let isPartialClose = (newPositionSize != 0)
1616+ let withdrawAmount = (marginToTrader + realizedFee)
17231617 let ammBalance = (cbalance() - withdrawAmount)
1724- let $t07220872415 = if ((0 > ammBalance))
1618+ let $t06830268509 = if ((0 > ammBalance))
17251619 then $Tuple2(0, abs(ammBalance))
17261620 else $Tuple2(ammBalance, 0)
1727- let ammNewBalance = $t07220872415._1
1728- let x11 = $t07220872415._2
1729- let $t07242272476 = getBorrowedByTrader(_trader)
1730- let borrowed = $t07242272476._1
1731- let assetId = $t07242272476._2
1732- let $t07249173350 = if ((borrowed > 0))
1621+ let ammNewBalance = $t06830268509._1
1622+ let x11 = $t06830268509._2
1623+ let $t06851668570 = getBorrowedByTrader(_trader)
1624+ let borrowed = $t06851668570._1
1625+ let assetId = $t06851668570._2
1626+ let $t06857869438 = if ((borrowed > 0))
17331627 then if ((withdrawAmount >= borrowed))
17341628 then {
17351629 let doRepay = invoke(collateralAddress(), "repay", [_trader, borrowed, assetId], nil)
17361630 if ((doRepay == doRepay))
1737- then $Tuple2([ScriptTransfer(_traderAddress, borrowed, fromBase58String(assetId))], (withdrawAmount - borrowed))
1631+ then $Tuple3(borrowed, (withdrawAmount - borrowed), isPartialClose)
17381632 else throw("Strict value is not equal to itself.")
17391633 }
17401634 else {
1741- let realizeAndClose = invoke(collateralAddress(), "realizePartiallyAndClose", [_trader, withdrawAmount, assetId], nil)
1635+ let realizeAndClose = invoke(collateralAddress(), if (isPartialClose)
1636+ then "repay"
1637+ else "realizePartiallyAndClose", [_trader, withdrawAmount, assetId], nil)
17421638 if ((realizeAndClose == realizeAndClose))
1743- then $Tuple2([ScriptTransfer(_traderAddress, withdrawAmount, fromBase58String(assetId))], 0)
1639+ then $Tuple3(withdrawAmount, 0, false)
17441640 else throw("Strict value is not equal to itself.")
17451641 }
1746- else $Tuple2(nil, withdrawAmount)
1747- if (($t07249173350 == $t07249173350))
1642+ else $Tuple3(0, withdrawAmount, false)
1643+ if (($t06857869438 == $t06857869438))
17481644 then {
1749- let quoteWithdrawAmount = $t07249173350._2
1750- let sendCollateralAction = $t07249173350._1
1751- let unstake = if ((quoteWithdrawAmount > 0))
1752- then {
1753- let unstake = invoke(vaultAddress(), "withdrawLocked", [quoteWithdrawAmount], nil)
1754- if ((unstake == unstake))
1755- then nil
1645+ let switchToQuote = $t06857869438._3
1646+ let quoteWithdrawAmountBeforeFee = $t06857869438._2
1647+ let assetWithdrawAmountBeforeFee = $t06857869438._1
1648+ let $t06944670513 = if ((quoteWithdrawAmountBeforeFee >= realizedFee))
1649+ then $Tuple3(assetWithdrawAmountBeforeFee, (quoteWithdrawAmountBeforeFee - realizedFee), realizedFee)
1650+ else {
1651+ let feeLeftToWithdrawFromAsset = (realizedFee - quoteWithdrawAmountBeforeFee)
1652+ let assetWithdrawAmountAfterFee = (assetWithdrawAmountBeforeFee - feeLeftToWithdrawFromAsset)
1653+ let balanceBefore = assetBalance(this, quoteAsset())
1654+ if ((balanceBefore == balanceBefore))
1655+ then {
1656+ let doSwap = invoke(swapAddress(), "swap", [toBase58String(quoteAsset()), 0], [AttachedPayment(fromBase58String(assetId), feeLeftToWithdrawFromAsset)])
1657+ if ((doSwap == doSwap))
1658+ then {
1659+ let balanceAfter = assetBalance(this, quoteAsset())
1660+ if ((balanceAfter == balanceAfter))
1661+ then {
1662+ let exchangedAmount = (balanceAfter - balanceBefore)
1663+ if ((exchangedAmount == exchangedAmount))
1664+ then $Tuple3(assetWithdrawAmountAfterFee, 0, (quoteWithdrawAmountBeforeFee + exchangedAmount))
1665+ else throw("Strict value is not equal to itself.")
1666+ }
1667+ else throw("Strict value is not equal to itself.")
1668+ }
1669+ else throw("Strict value is not equal to itself.")
1670+ }
17561671 else throw("Strict value is not equal to itself.")
17571672 }
1758- else nil
1759- if ((unstake == unstake))
1673+ if (($t06944670513 == $t06944670513))
17601674 then {
1761- let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, 0], nil)
1762- if ((notifyNotional == notifyNotional))
1763- then (((((if ((newPositionSize == 0))
1764- then deletePosition(_trader)
1765- else updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ (if ((quoteWithdrawAmount > 0))
1766- then withdraw(_traderAddress, quoteWithdrawAmount)
1767- else nil)) ++ updateBalance(ammNewBalance)) ++ sendCollateralAction)
1675+ let actualFeeInQuoteAsset = $t06944670513._3
1676+ let quoteWithdrawAmountAfterFee = $t06944670513._2
1677+ let assetWithdrawAmountAfterFee = $t06944670513._1
1678+ let unstake = if ((quoteWithdrawAmountBeforeFee > 0))
1679+ then {
1680+ let unstake = invoke(vaultAddress(), "withdrawLocked", [quoteWithdrawAmountBeforeFee], nil)
1681+ if ((unstake == unstake))
1682+ then nil
1683+ else throw("Strict value is not equal to itself.")
1684+ }
1685+ else nil
1686+ if ((unstake == unstake))
1687+ then {
1688+ let $t07078770856 = distributeFee(actualFeeInQuoteAsset)
1689+ let feeToStakers = $t07078770856._1
1690+ let feeToVault = $t07078770856._2
1691+ let depositVault = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
1692+ if ((depositVault == depositVault))
1693+ then {
1694+ let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, realizedFee], nil)
1695+ if ((notifyFee == notifyFee))
1696+ then {
1697+ let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
1698+ if ((notifyNotional == notifyNotional))
1699+ then (((((((if (isPartialClose)
1700+ then updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF)
1701+ else deletePosition(_trader)) ++ (if (switchToQuote)
1702+ then {
1703+ let quoteAssetStr = toBase58String(quoteAsset())
1704+ updatePositionAsset(_trader, quoteAssetStr)
1705+ }
1706+ else nil)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ transferFee(feeToStakers)) ++ (if ((quoteWithdrawAmountAfterFee > 0))
1707+ then withdraw(_traderAddress, quoteWithdrawAmountAfterFee)
1708+ else nil)) ++ updateBalance(ammNewBalance)) ++ (if ((assetWithdrawAmountAfterFee > 0))
1709+ then [ScriptTransfer(_traderAddress, assetWithdrawAmountAfterFee, fromBase58String(assetId))]
1710+ else nil))
1711+ else throw("Strict value is not equal to itself.")
1712+ }
1713+ else throw("Strict value is not equal to itself.")
1714+ }
1715+ else throw("Strict value is not equal to itself.")
1716+ }
17681717 else throw("Strict value is not equal to itself.")
17691718 }
17701719 else throw("Strict value is not equal to itself.")
18061755 then (DECIMAL_UNIT > partialLiquidationRatio())
18071756 else false)
18081757 then {
1809- let $t07567175821 = getPosition(_trader)
1810- let oldPositionSize = $t07567175821._1
1811- let oldPositionMargin = $t07567175821._2
1812- let oldPositionOpenNotional = $t07567175821._3
1813- let oldPositionLstUpdCPF = $t07567175821._4
1758+ let $t07360973759 = getPosition(_trader)
1759+ let oldPositionSize = $t07360973759._1
1760+ let oldPositionMargin = $t07360973759._2
1761+ let oldPositionOpenNotional = $t07360973759._3
1762+ let oldPositionLstUpdCPF = $t07360973759._4
18141763 let _direction = if ((oldPositionSize > 0))
18151764 then DIR_SHORT
18161765 else DIR_LONG
18171766 let isAdd = (_direction == DIR_LONG)
18181767 let exchangedQuoteAssetAmount = getPartialLiquidationAmount(_trader, oldPositionSize)
1819- let $t07604676150 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1820- let oldPositionNotional = $t07604676150._1
1821- let unrealizedPnl = $t07604676150._2
1822- let $t07615876345 = swapInput(isAdd, exchangedQuoteAssetAmount)
1823- let exchangedPositionSize = $t07615876345._1
1824- let quoteAssetReserveAfter = $t07615876345._2
1825- let baseAssetReserveAfter = $t07615876345._3
1826- let totalPositionSizeAfter = $t07615876345._4
1768+ let $t07398474088 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1769+ let oldPositionNotional = $t07398474088._1
1770+ let unrealizedPnl = $t07398474088._2
1771+ let $t07409674283 = swapInput(isAdd, exchangedQuoteAssetAmount)
1772+ let exchangedPositionSize = $t07409674283._1
1773+ let quoteAssetReserveAfter = $t07409674283._2
1774+ let baseAssetReserveAfter = $t07409674283._3
1775+ let totalPositionSizeAfter = $t07409674283._4
18271776 let liquidationRatio = divd(abs(exchangedPositionSize), abs(oldPositionSize))
18281777 let realizedPnl = muld(unrealizedPnl, liquidationRatio)
1829- let $t07663476867 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1830- let remainMargin = $t07663476867._1
1831- let badDebt = $t07663476867._2
1832- let fundingPayment = $t07663476867._3
1778+ let $t07457274805 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1779+ let remainMargin = $t07457274805._1
1780+ let badDebt = $t07457274805._2
1781+ let fundingPayment = $t07457274805._3
18331782 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
18341783 let remainOpenNotional = if ((oldPositionSize > 0))
18351784 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
18441793 let newPositionLstUpdCPF = latestCumulativePremiumFraction(newPositionSize)
18451794 let openInterestNotionalAfter = (openInterestNotional() - openNotionalDelta)
18461795 let ammBalance = (cbalance() - liquidationPenalty)
1847- let $t07810878237 = if ((0 > ammBalance))
1796+ let $t07604676175 = if ((0 > ammBalance))
18481797 then $Tuple2(0, abs(ammBalance))
18491798 else $Tuple2(ammBalance, 0)
1850- let newAmmBalance = $t07810878237._1
1851- let x11 = $t07810878237._2
1852- let $t07824578299 = getBorrowedByTrader(_trader)
1853- let borrowed = $t07824578299._1
1854- let assetId = $t07824578299._2
1799+ let newAmmBalance = $t07604676175._1
1800+ let x11 = $t07604676175._2
1801+ let $t07618376237 = getBorrowedByTrader(_trader)
1802+ let borrowed = $t07618376237._1
1803+ let assetId = $t07618376237._2
18551804 let doLiquidateCollateral = if ((borrowed > 0))
18561805 then {
18571806 let collateralToSell = muld(borrowed, liquidationRatio)
18891838 else throw("Strict value is not equal to itself.")
18901839 }
18911840 else {
1892- let $t07997880473 = internalClosePosition(_trader, false)
1893- let x1 = $t07997880473._1
1894- let badDebt = $t07997880473._2
1895- let x2 = $t07997880473._3
1896- let x3 = $t07997880473._4
1897- let quoteAssetReserveAfter = $t07997880473._5
1898- let baseAssetReserveAfter = $t07997880473._6
1899- let totalPositionSizeAfter = $t07997880473._7
1900- let openInterestNotionalAfter = $t07997880473._8
1901- let exchangedQuoteAssetAmount = $t07997880473._9
1902- let totalLongAfter = $t07997880473._10
1903- let totalShortAfter = $t07997880473._11
1904- let totalLongOpenInterestAfter = $t07997880473._12
1905- let totalShortOpenInterestAfter = $t07997880473._13
1841+ let $t07791678411 = internalClosePosition(_trader, false)
1842+ let x1 = $t07791678411._1
1843+ let badDebt = $t07791678411._2
1844+ let x2 = $t07791678411._3
1845+ let x3 = $t07791678411._4
1846+ let quoteAssetReserveAfter = $t07791678411._5
1847+ let baseAssetReserveAfter = $t07791678411._6
1848+ let totalPositionSizeAfter = $t07791678411._7
1849+ let openInterestNotionalAfter = $t07791678411._8
1850+ let exchangedQuoteAssetAmount = $t07791678411._9
1851+ let totalLongAfter = $t07791678411._10
1852+ let totalShortAfter = $t07791678411._11
1853+ let totalLongOpenInterestAfter = $t07791678411._12
1854+ let totalShortOpenInterestAfter = $t07791678411._13
19061855 let liquidationPenalty = muld(exchangedQuoteAssetAmount, liquidationFeeRatio())
19071856 let feeToLiquidator = (liquidationPenalty / 2)
19081857 let feeToVault = (liquidationPenalty - feeToLiquidator)
19091858 let ammBalance = (cbalance() - liquidationPenalty)
1910- let $t08088181010 = if ((0 > ammBalance))
1859+ let $t07881978948 = if ((0 > ammBalance))
19111860 then $Tuple2(0, abs(ammBalance))
19121861 else $Tuple2(ammBalance, 0)
1913- let newAmmBalance = $t08088181010._1
1914- let x11 = $t08088181010._2
1915- let $t08101881072 = getBorrowedByTrader(_trader)
1916- let borrowed = $t08101881072._1
1917- let assetId = $t08101881072._2
1862+ let newAmmBalance = $t07881978948._1
1863+ let x11 = $t07881978948._2
1864+ let $t07895679010 = getBorrowedByTrader(_trader)
1865+ let borrowed = $t07895679010._1
1866+ let assetId = $t07895679010._2
19181867 let doLiquidateCollateral = if ((borrowed > 0))
19191868 then {
19201869 let realizeAndClose = invoke(collateralAddress(), "realizePartiallyAndClose", [_trader, 0, assetId], nil)
19741923 then throw(((("Invalid funding block timestamp: " + toString(lastBlock.timestamp)) + " < ") + toString(fundingBlockTimestamp)))
19751924 else {
19761925 let underlyingPrice = getOraclePrice()
1977- let $t08294483006 = getFunding()
1978- let shortPremiumFraction = $t08294483006._1
1979- let longPremiumFraction = $t08294483006._2
1926+ let $t08088280944 = getFunding()
1927+ let shortPremiumFraction = $t08088280944._1
1928+ let longPremiumFraction = $t08088280944._2
19801929 updateFunding((fundingBlockTimestamp + fundingPeriodSeconds()), (latestLongCumulativePremiumFraction() + longPremiumFraction), (latestShortCumulativePremiumFraction() + shortPremiumFraction), divd(longPremiumFraction, underlyingPrice), divd(shortPremiumFraction, underlyingPrice))
19811930 }
19821931 }
19891938 func syncTerminalPriceToOracle () = {
19901939 let _qtAstR = qtAstR()
19911940 let _bsAstR = bsAstR()
1992- let $t08343883573 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1993- let newQuoteAssetWeight = $t08343883573._1
1994- let newBaseAssetWeight = $t08343883573._2
1995- let marginToVault = $t08343883573._3
1941+ let $t08137681511 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1942+ let newQuoteAssetWeight = $t08137681511._1
1943+ let newBaseAssetWeight = $t08137681511._2
1944+ let marginToVault = $t08137681511._3
19961945 let doExchangePnL = if ((marginToVault != 0))
19971946 then {
19981947 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
20131962 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
20141963 if ((sync == sync))
20151964 then {
2016- let $t08414284243 = getPosition(_trader)
2017- let positionSize = $t08414284243._1
2018- let positionMargin = $t08414284243._2
2019- let pon = $t08414284243._3
2020- let positionLstUpdCPF = $t08414284243._4
2021- let $t08424684347 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
2022- let positionNotional = $t08424684347._1
2023- let unrealizedPnl = $t08424684347._2
2024- let $t08435084522 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
2025- let remainMargin = $t08435084522._1
2026- let badDebt = $t08435084522._2
2027- let fundingPayment = $t08435084522._3
1965+ let $t08208082181 = getPosition(_trader)
1966+ let positionSize = $t08208082181._1
1967+ let positionMargin = $t08208082181._2
1968+ let pon = $t08208082181._3
1969+ let positionLstUpdCPF = $t08208082181._4
1970+ let $t08218482285 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1971+ let positionNotional = $t08218482285._1
1972+ let unrealizedPnl = $t08218482285._2
1973+ let $t08228882460 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
1974+ let remainMargin = $t08228882460._1
1975+ let badDebt = $t08228882460._2
1976+ let fundingPayment = $t08228882460._3
20281977 throw((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)))
20291978 }
20301979 else throw("Strict value is not equal to itself.")
20441993
20451994 @Callable(i)
20461995 func view_getTerminalAmmPrice () = {
2047- let $t08493885019 = getTerminalAmmState()
2048- let terminalQuoteAssetReserve = $t08493885019._1
2049- let terminalBaseAssetReserve = $t08493885019._2
1996+ let $t08287682957 = getTerminalAmmState()
1997+ let terminalQuoteAssetReserve = $t08287682957._1
1998+ let terminalBaseAssetReserve = $t08287682957._2
20501999 let price = divd(muld(terminalQuoteAssetReserve, qtAstW()), muld(terminalBaseAssetReserve, bsAstW()))
20512000 throw(toString(price))
20522001 }
20562005 @Callable(i)
20572006 func view_getFunding () = {
20582007 let underlyingPrice = getOraclePrice()
2059- let $t08523485296 = getFunding()
2060- let shortPremiumFraction = $t08523485296._1
2061- let longPremiumFraction = $t08523485296._2
2008+ let $t08317283234 = getFunding()
2009+ let shortPremiumFraction = $t08317283234._1
2010+ let longPremiumFraction = $t08317283234._2
20622011 let longFunding = divd(longPremiumFraction, underlyingPrice)
20632012 let shortFunding = divd(shortPremiumFraction, underlyingPrice)
20642013 throw((((s(longFunding) + s(shortFunding)) + s(getTwapSpotPrice())) + s(getOraclePrice())))
20682017
20692018 @Callable(i)
20702019 func view_getBorrowedByTrader (_trader) = {
2071- let $t08558285636 = getBorrowedByTrader(_trader)
2072- let borrowed = $t08558285636._1
2073- let assetId = $t08558285636._2
2020+ let $t08352083574 = getBorrowedByTrader(_trader)
2021+ let borrowed = $t08352083574._1
2022+ let assetId = $t08352083574._2
20742023 throw((s(borrowed) + assetId))
20752024 }
20762025
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"
27+
28+let k_positionFee = "k_positionFee"
2729
2830 let k_initialized = "k_initialized"
2931
3032 let k_paused = "k_paused"
3133
3234 let k_closeOnly = "k_closeOnly"
3335
3436 let k_fee = "k_fee"
3537
3638 let k_fundingPeriod = "k_fundingPeriod"
3739
3840 let k_initMarginRatio = "k_initMarginRatio"
3941
4042 let k_maintenanceMarginRatio = "k_mmr"
4143
4244 let k_liquidationFeeRatio = "k_liquidationFeeRatio"
4345
4446 let k_partialLiquidationRatio = "k_partLiquidationRatio"
4547
4648 let k_spreadLimit = "k_spreadLimit"
4749
4850 let k_maxPriceImpact = "k_maxPriceImpact"
4951
5052 let k_maxPriceSpread = "k_maxPriceSpread"
5153
5254 let k_maxOpenNotional = "k_maxOpenNotional"
5355
5456 let k_feeToStakersPercent = "k_feeToStakersPercent"
5557
5658 let k_maxOracleDelay = "k_maxOracleDelay"
5759
5860 let k_lastDataStr = "k_lastDataStr"
5961
6062 let k_lastMinuteId = "k_lastMinuteId"
6163
6264 let k_twapDataLastCumulativePrice = "k_twapDataLastCumulativePrice"
6365
6466 let k_twapDataLastPrice = "k_twapDataLastPrice"
6567
6668 let k_twapDataPreviousMinuteId = "k_twapDataPreviousMinuteId"
6769
6870 let k_latestLongCumulativePremiumFraction = "k_latestLongPremiumFraction"
6971
7072 let k_latestShortCumulativePremiumFraction = "k_latestShortPremiumFraction"
7173
7274 let k_nextFundingBlock = "k_nextFundingBlockMinTimestamp"
7375
7476 let k_longFundingRate = "k_longFundingRate"
7577
7678 let k_shortFundingRate = "k_shortFundingRate"
7779
7880 let k_quoteAssetReserve = "k_qtAstR"
7981
8082 let k_baseAssetReserve = "k_bsAstR"
8183
8284 let k_quoteAssetWeight = "k_qtAstW"
8385
8486 let k_baseAssetWeight = "k_bsAstW"
8587
8688 let k_totalPositionSize = "k_totalPositionSize"
8789
8890 let k_totalLongPositionSize = "k_totalLongPositionSize"
8991
9092 let k_totalShortPositionSize = "k_totalShortPositionSize"
9193
9294 let k_openInterestNotional = "k_openInterestNotional"
9395
9496 let k_openInterestShort = "k_openInterestShort"
9597
9698 let k_openInterestLong = "k_openInterestLong"
9799
98100 let k_coordinatorAddress = "k_coordinatorAddress"
99101
100102 let k_vault_address = "k_vault_address"
101103
102104 let k_admin_address = "k_admin_address"
103105
104106 let k_admin_public_key = "k_admin_public_key"
105107
106108 let k_quote_asset = "k_quote_asset"
107109
108110 let k_quote_staking = "k_quote_staking"
109111
110112 let k_staking_address = "k_staking_address"
111113
112114 let k_miner_address = "k_miner_address"
113115
114116 let k_orders_address = "k_orders_address"
115117
116118 let k_referral_address = "k_referral_address"
117119
118120 let k_collateral_address = "k_collateral_address"
119121
120122 let k_exchange_address = "k_exchange_address"
121123
122124 let k_nft_manager_address = "k_nft_manager_address"
123125
124126 let k_trader_market_asset_collateral = "k_trader_market_asset_collateral"
125127
126128 func toCompositeKey (_key,_address) = ((_key + "_") + _address)
127129
128130
129131 func coordinator () = valueOrErrorMessage(addressFromString(getStringValue(this, k_coordinatorAddress)), "Coordinator not set")
130132
131133
132134 func adminAddress () = addressFromString(getStringValue(coordinator(), k_admin_address))
133135
134136
135137 func adminPublicKey () = fromBase58String(getStringValue(coordinator(), k_admin_public_key))
136138
137139
138140 func quoteAsset () = fromBase58String(getStringValue(coordinator(), k_quote_asset))
139141
140142
141143 func quoteAssetStaking () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_quote_staking)), "Quote asset staking not set")
142144
143145
144146 func stakingAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_staking_address)), "Staking not set")
145147
146148
147149 func vaultAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_vault_address)), "Vault not set")
148150
149151
150152 func minerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_miner_address)), "Miner not set")
151153
152154
153155 func ordersAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_orders_address)), "Orders not set")
154156
155157
156158 func referralAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_referral_address)), "Referral not set")
157159
158160
159161 func nftManagerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_nft_manager_address)), "NFT Manager not set")
160162
161163
162164 func collateralAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_collateral_address)), "Collateral Manager not set")
163165
164166
165167 func swapAddress () = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(coordinator(), k_exchange_address), "No swap address")), "Invalid swap address")
166168
167169
168170 let k_whitelist_asset = "k_whitelist_asset"
169171
170172 func isWhitelistAsset (_assetId) = valueOrElse(getBoolean(collateralAddress(), toCompositeKey(k_whitelist_asset, _assetId)), false)
171173
172174
173175 let k_token_param = "k_token_param"
174176
175177 let k_token_type = "k_token_type"
176178
177179 let FEE_REDUCTION_TOKEN_TYPE = "fee_reduction"
178180
179181 let DIR_LONG = 1
180182
181183 let DIR_SHORT = 2
182184
183185 let TWAP_INTERVAL = 15
184186
185187 let ORACLE_INTERVAL = 15
186188
187189 let SECONDS = 1000
188190
189191 let DECIMAL_NUMBERS = 6
190192
191193 let DECIMAL_UNIT = (1 * (((((10 * 10) * 10) * 10) * 10) * 10))
192194
193195 let ONE_DAY = (86400 * DECIMAL_UNIT)
194196
195197 let ALL_FEES = 100
196198
197199 let PNL_OPTION_SPOT = 1
198200
199201 let PNL_OPTION_ORACLE = 2
200202
201203 func s (_x) = (toString(_x) + ",")
202204
203205
204206 func divd (_x,_y) = fraction(_x, DECIMAL_UNIT, _y, HALFEVEN)
205207
206208
207209 func muld (_x,_y) = fraction(_x, _y, DECIMAL_UNIT, HALFEVEN)
208210
209211
210212 func sqrtd (_x) = sqrt(_x, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
211213
212214
213215 func powd (_x,_y) = pow(_x, DECIMAL_NUMBERS, _y, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
214216
215217
216218 func bdivd (_x,_y) = fraction(_x, toBigInt(DECIMAL_UNIT), _y, HALFEVEN)
217219
218220
219221 func bmuld (_x,_y) = fraction(_x, _y, toBigInt(DECIMAL_UNIT), HALFEVEN)
220222
221223
222224 func bsqrtd (_x) = sqrtBigInt(_x, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
223225
224226
225227 func bpowd (_x,_y) = pow(_x, DECIMAL_NUMBERS, _y, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
226228
227229
228230 func abs (_x) = if ((_x > 0))
229231 then _x
230232 else -(_x)
231233
232234
233235 func vmax (_x,_y) = if ((_x >= _y))
234236 then _x
235237 else _y
236238
237239
238240 func listToStr (_list) = {
239241 func _join (accumulator,val) = ((accumulator + val) + ",")
240242
241243 let newListStr = {
242244 let $l = _list
243245 let $s = size($l)
244246 let $acc0 = ""
245247 func $f0_1 ($a,$i) = if (($i >= $s))
246248 then $a
247249 else _join($a, $l[$i])
248250
249251 func $f0_2 ($a,$i) = if (($i >= $s))
250252 then $a
251253 else throw("List size exceeds 20")
252254
253255 $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)
254256 }
255257 let newListStrU = dropRight(newListStr, 1)
256258 let newListStrR = if ((take(newListStrU, 1) == ","))
257259 then drop(newListStrU, 1)
258260 else newListStrU
259261 newListStrR
260262 }
261263
262264
263265 func strToList (_str) = split(_str, ",")
264266
265267
266268 func pushToQueue (_list,_maxSize,_value) = if ((size(_list) > _maxSize))
267269 then (removeByIndex(_list, 0) :+ _value)
268270 else (_list :+ _value)
269271
270272
271273 func int (k) = valueOrErrorMessage(getInteger(this, k), ("no value for " + k))
272274
273275
274276 func intOr (k,def) = valueOrElse(getInteger(this, k), def)
275277
276278
277279 func strA (_address,_key) = {
278280 let val = valueOrErrorMessage(getString(_address, _key), ("No value for key " + _key))
279281 val
280282 }
281283
282284
283285 func intA (_address,_key) = {
284286 let val = valueOrErrorMessage(getInteger(_address, _key), ("No value for key " + _key))
285287 val
286288 }
287289
288290
289291 func cbalance () = int(k_balance)
290292
291293
292294 func fee () = int(k_fee)
293295
294296
295297 func initMarginRatio () = int(k_initMarginRatio)
296298
297299
298300 func qtAstR () = int(k_quoteAssetReserve)
299301
300302
301303 func bsAstR () = int(k_baseAssetReserve)
302304
303305
304306 func qtAstW () = intOr(k_quoteAssetWeight, DECIMAL_UNIT)
305307
306308
307309 func bsAstW () = intOr(k_baseAssetWeight, DECIMAL_UNIT)
308310
309311
310312 func totalPositionSize () = int(k_totalPositionSize)
311313
312314
313315 func openInterestNotional () = int(k_openInterestNotional)
314316
315317
316318 func openInterestShort () = int(k_openInterestShort)
317319
318320
319321 func openInterestLong () = int(k_openInterestLong)
320322
321323
322324 func nextFundingBlockTimestamp () = int(k_nextFundingBlock)
323325
324326
325327 func fundingPeriodRaw () = int(k_fundingPeriod)
326328
327329
328330 func fundingPeriodDecimal () = (fundingPeriodRaw() * DECIMAL_UNIT)
329331
330332
331333 func fundingPeriodSeconds () = (fundingPeriodRaw() * SECONDS)
332334
333335
334336 func maintenanceMarginRatio () = int(k_maintenanceMarginRatio)
335337
336338
337339 func liquidationFeeRatio () = int(k_liquidationFeeRatio)
338340
339341
340342 func partialLiquidationRatio () = int(k_partialLiquidationRatio)
341343
342344
343345 func spreadLimit () = int(k_spreadLimit)
344346
345347
346348 func maxPriceImpact () = int(k_maxPriceImpact)
347349
348350
349351 func maxPriceSpread () = int(k_maxPriceSpread)
350352
351353
352354 func maxOpenNotional () = int(k_maxOpenNotional)
353355
354356
355357 func latestLongCumulativePremiumFraction () = int(k_latestLongCumulativePremiumFraction)
356358
357359
358360 func latestShortCumulativePremiumFraction () = int(k_latestShortCumulativePremiumFraction)
359361
360362
361363 func totalShortPositionSize () = int(k_totalShortPositionSize)
362364
363365
364366 func totalLongPositionSize () = int(k_totalLongPositionSize)
365367
366368
367369 func lastSequence () = intOr(k_sequence, 0)
368370
369371
370372 func feeToStakersPercent () = int(k_feeToStakersPercent)
371373
372374
373375 func maxOracleDelay () = int(k_maxOracleDelay)
374376
375377
376378 func getActualCaller (i) = valueOrElse(getString(ordersAddress(), "k_sender"), toString(i.caller))
377379
378380
379381 func requireMoreMarginRatio (_marginRatio,_baseMarginRatio,_largerThanOrEqualTo) = {
380382 let remainingMarginRatio = (_marginRatio - _baseMarginRatio)
381383 if (if (_largerThanOrEqualTo)
382384 then (0 > remainingMarginRatio)
383385 else false)
384386 then throw(((("Invalid margin: " + toString(_marginRatio)) + " < ") + toString(_baseMarginRatio)))
385387 else if (if (!(_largerThanOrEqualTo))
386388 then (remainingMarginRatio >= 0)
387389 else false)
388390 then throw(((("Invalid margin: " + toString(_marginRatio)) + " > ") + toString(_baseMarginRatio)))
389391 else true
390392 }
391393
392394
393395 func latestCumulativePremiumFraction (_positionSize) = if ((_positionSize == 0))
394396 then throw("Should not be called with _positionSize == 0")
395397 else if ((_positionSize > 0))
396398 then latestLongCumulativePremiumFraction()
397399 else latestShortCumulativePremiumFraction()
398400
399401
400402 func getPosition (_trader) = {
401403 let positionSizeOpt = getInteger(this, toCompositeKey(k_positionSize, _trader))
402404 match positionSizeOpt {
403405 case positionSize: Int =>
404406 $Tuple4(positionSize, getIntegerValue(this, toCompositeKey(k_positionMargin, _trader)), getIntegerValue(this, toCompositeKey(k_positionOpenNotional, _trader)), getIntegerValue(this, toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, _trader)))
405407 case _ =>
406408 $Tuple4(0, 0, 0, 0)
407409 }
408410 }
409411
410412
411413 func getPositionAsset (_trader) = {
412414 let positionAssetOpt = getString(this, toCompositeKey(k_positionAsset, _trader))
413415 match positionAssetOpt {
414416 case positionAsset: String =>
415417 positionAsset
416418 case _ =>
417419 toBase58String(quoteAsset())
420+ }
421+ }
422+
423+
424+func getPositionFee (_trader) = {
425+ let positionFeeOpt = getInteger(this, toCompositeKey(k_positionFee, _trader))
426+ match positionFeeOpt {
427+ case positionFee: Int =>
428+ positionFee
429+ case _ =>
430+ fee()
418431 }
419432 }
420433
421434
422435 func requireOpenPosition (_trader) = if ((getPosition(_trader)._1 == 0))
423436 then throw("No open position")
424437 else true
425438
426439
427440 func initialized () = valueOrElse(getBoolean(this, k_initialized), false)
428441
429442
430443 func paused () = valueOrElse(getBoolean(this, k_paused), false)
431444
432445
433446 func closeOnly () = valueOrElse(getBoolean(this, k_closeOnly), false)
434447
435448
436449 func updateReserve (_isAdd,_quoteAssetAmount,_baseAssetAmount) = if (_isAdd)
437450 then {
438451 let newBase = (bsAstR() - _baseAssetAmount)
439452 if ((0 >= newBase))
440453 then throw("Tx lead to base asset reserve <= 0, revert")
441454 else $Tuple3((qtAstR() + _quoteAssetAmount), newBase, (totalPositionSize() + _baseAssetAmount))
442455 }
443456 else {
444457 let newQuote = (qtAstR() - _quoteAssetAmount)
445458 if ((0 >= newQuote))
446459 then throw("Tx lead to base quote reserve <= 0, revert")
447460 else $Tuple3(newQuote, (bsAstR() + _baseAssetAmount), (totalPositionSize() - _baseAssetAmount))
448461 }
449462
450463
451464 func calcInvariant (_qtAstR,_bsAstR) = {
452465 let bqtAstR = toBigInt(_qtAstR)
453466 let bbsAstR = toBigInt(_bsAstR)
454467 bmuld(bqtAstR, bbsAstR)
455468 }
456469
457470
458471 func swapInput (_isAdd,_quoteAssetAmount) = {
459472 let _qtAstR = qtAstR()
460473 let _bsAstR = bsAstR()
461474 let _qtAstW = qtAstW()
462475 let _bsAstW = bsAstW()
463476 let quoteAssetAmountAdjusted = divd(_quoteAssetAmount, _qtAstW)
464477 let k = calcInvariant(_qtAstR, _bsAstR)
465478 let quoteAssetReserveAfter = if (_isAdd)
466479 then (_qtAstR + quoteAssetAmountAdjusted)
467480 else (_qtAstR - quoteAssetAmountAdjusted)
468481 let baseAssetReserveAfter = toInt(bdivd(k, toBigInt(quoteAssetReserveAfter)))
469482 let amountBaseAssetBoughtAbs = abs((baseAssetReserveAfter - _bsAstR))
470483 let amountBaseAssetBought = if (_isAdd)
471484 then amountBaseAssetBoughtAbs
472485 else -(amountBaseAssetBoughtAbs)
473- let $t01684317013 = updateReserve(_isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
474- let quoteAssetReserveAfter1 = $t01684317013._1
475- let baseAssetReserveAfter1 = $t01684317013._2
476- let totalPositionSizeAfter1 = $t01684317013._3
486+ let $t01713817308 = updateReserve(_isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
487+ let quoteAssetReserveAfter1 = $t01713817308._1
488+ let baseAssetReserveAfter1 = $t01713817308._2
489+ let totalPositionSizeAfter1 = $t01713817308._3
477490 let priceBefore = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
478491 let marketPrice = divd(_quoteAssetAmount, amountBaseAssetBoughtAbs)
479492 let priceDiff = abs((priceBefore - marketPrice))
480493 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
481494 let maxPriceImpactValue = maxPriceImpact()
482495 if ((priceImpact > maxPriceImpactValue))
483496 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)))
484497 else $Tuple4(amountBaseAssetBought, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1)
485498 }
486499
487500
488501 func calcRemainMarginWithFundingPayment (_oldPositionSize,_oldPositionMargin,_oldPositionCumulativePremiumFraction,_marginDelta) = {
489502 let fundingPayment = if ((_oldPositionSize != 0))
490503 then {
491504 let _latestCumulativePremiumFraction = latestCumulativePremiumFraction(_oldPositionSize)
492505 muld((_latestCumulativePremiumFraction - _oldPositionCumulativePremiumFraction), _oldPositionSize)
493506 }
494507 else 0
495508 let signedMargin = ((_marginDelta - fundingPayment) + _oldPositionMargin)
496- let $t01850018627 = if ((0 > signedMargin))
509+ let $t01879518922 = if ((0 > signedMargin))
497510 then $Tuple2(0, abs(signedMargin))
498511 else $Tuple2(abs(signedMargin), 0)
499- let remainMargin = $t01850018627._1
500- let badDebt = $t01850018627._2
512+ let remainMargin = $t01879518922._1
513+ let badDebt = $t01879518922._2
501514 $Tuple3(remainMargin, badDebt, fundingPayment)
502515 }
503516
504517
505518 func swapOutputWithReserves (_isAdd,_baseAssetAmount,_checkMaxPriceImpact,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
506519 let priceBefore = divd(muld(_quoteAssetReserve, _quoteAssetWeight), muld(_baseAssetReserve, _baseAssetWeight))
507520 if ((_baseAssetAmount == 0))
508521 then throw("Invalid base asset amount")
509522 else {
510523 let k = calcInvariant(_quoteAssetReserve, _baseAssetReserve)
511524 let baseAssetPoolAmountAfter = if (_isAdd)
512525 then (_baseAssetReserve + _baseAssetAmount)
513526 else (_baseAssetReserve - _baseAssetAmount)
514527 let quoteAssetAfter = toInt(bdivd(k, toBigInt(baseAssetPoolAmountAfter)))
515528 let quoteAssetDelta = abs((quoteAssetAfter - _quoteAssetReserve))
516529 let quoteAssetSold = muld(quoteAssetDelta, _quoteAssetWeight)
517530 let maxPriceImpactValue = maxPriceImpact()
518- let $t01979719959 = updateReserve(!(_isAdd), quoteAssetDelta, _baseAssetAmount)
519- let quoteAssetReserveAfter1 = $t01979719959._1
520- let baseAssetReserveAfter1 = $t01979719959._2
521- let totalPositionSizeAfter1 = $t01979719959._3
531+ let $t02009220254 = updateReserve(!(_isAdd), quoteAssetDelta, _baseAssetAmount)
532+ let quoteAssetReserveAfter1 = $t02009220254._1
533+ let baseAssetReserveAfter1 = $t02009220254._2
534+ let totalPositionSizeAfter1 = $t02009220254._3
522535 let marketPrice = divd(quoteAssetSold, _baseAssetAmount)
523536 let priceDiff = abs((priceBefore - marketPrice))
524537 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
525538 if (if ((priceImpact > maxPriceImpactValue))
526539 then _checkMaxPriceImpact
527540 else false)
528541 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)))
529542 else $Tuple7(quoteAssetSold, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1, (totalLongPositionSize() - (if (_isAdd)
530543 then abs(_baseAssetAmount)
531544 else 0)), (totalShortPositionSize() - (if (!(_isAdd))
532545 then abs(_baseAssetAmount)
533546 else 0)), priceImpact)
534547 }
535548 }
536549
537550
538551 func swapOutput (_isAdd,_baseAssetAmount,_checkMaxPriceImpact) = swapOutputWithReserves(_isAdd, _baseAssetAmount, _checkMaxPriceImpact, qtAstR(), qtAstW(), bsAstR(), bsAstW())
539552
540553
541554 func getOraclePrice () = {
542555 let oracle = valueOrErrorMessage(addressFromString(getStringValue(this, k_ora)), "")
543556 let priceKey = getStringValue(this, k_ora_key)
544557 let lastValue = valueOrErrorMessage(getInteger(oracle, priceKey), ((("Can not get oracle price. Oracle: " + toString(oracle)) + " key: ") + priceKey))
545558 let blockKey = valueOrElse(getString(this, k_ora_block_key), "")
546559 if ((blockKey != ""))
547560 then {
548561 let currentBlock = lastBlock.height
549562 let lastOracleBlock = valueOrErrorMessage(getInteger(oracle, blockKey), ((("Can not get oracle block. Oracle: " + toString(oracle)) + " key: ") + blockKey))
550563 if (((currentBlock - lastOracleBlock) > maxOracleDelay()))
551564 then throw(((("Oracle stale data. Last oracle block: " + toString(lastOracleBlock)) + " current block: ") + toString(currentBlock)))
552565 else lastValue
553566 }
554567 else lastValue
555568 }
556569
557570
558571 func isMarketClosed () = {
559572 let oracle = valueOrErrorMessage(addressFromString(getStringValue(this, k_ora)), "")
560573 let openKey = valueOrElse(getString(this, k_ora_open_key), "")
561574 if ((openKey != ""))
562575 then {
563576 let isOpen = valueOrErrorMessage(getBoolean(oracle, openKey), ((("Can not get oracle is open/closed. Oracle: " + toString(oracle)) + " key: ") + openKey))
564577 !(isOpen)
565578 }
566579 else false
567580 }
568581
569582
570583 func absPriceDiff (_oraclePrice,_quoteAssetReserve,_baseAssetReserve,_qtAstW,_bsAstW) = {
571584 let priceAfter = divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
572585 let averagePrice = divd((_oraclePrice + priceAfter), (2 * DECIMAL_UNIT))
573586 let absPriceDiff = divd(abs((_oraclePrice - priceAfter)), averagePrice)
574587 absPriceDiff
575588 }
576589
577590
578591 func requireNotOverSpreadLimit (_quoteAssetReserve,_baseAssetReserve) = {
579592 let oraclePrice = getOraclePrice()
580593 let _qtAstW = qtAstW()
581594 let _bsAstW = bsAstW()
582595 let absPriceDiffBefore = absPriceDiff(oraclePrice, qtAstR(), bsAstR(), _qtAstW, _bsAstW)
583596 let absPriceDiffAfter = absPriceDiff(oraclePrice, _quoteAssetReserve, _baseAssetReserve, _qtAstW, _bsAstW)
584597 if (if ((absPriceDiffAfter > maxPriceSpread()))
585598 then (absPriceDiffAfter > absPriceDiffBefore)
586599 else false)
587600 then throw(((("Price spread " + toString(absPriceDiffAfter)) + " > max price spread ") + toString(maxPriceSpread())))
588601 else true
589602 }
590603
591604
592605 func requireNotOverMaxOpenNotional (_longOpenNotional,_shortOpenNotional) = {
593606 let _maxOpenNotional = maxOpenNotional()
594607 if ((_longOpenNotional > _maxOpenNotional))
595608 then throw(((("Long open notional " + toString(_longOpenNotional)) + " > max open notional ") + toString(_maxOpenNotional)))
596609 else if ((_shortOpenNotional > _maxOpenNotional))
597610 then throw(((("Short open notional " + toString(_shortOpenNotional)) + " > max open notional ") + toString(_maxOpenNotional)))
598611 else true
599612 }
600613
601614
602615 func getSpotPrice () = {
603616 let _quoteAssetReserve = qtAstR()
604617 let _baseAssetReserve = bsAstR()
605618 let _qtAstW = qtAstW()
606619 let _bsAstW = bsAstW()
607620 divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
608621 }
609622
610623
611624 func isOverFluctuationLimit () = {
612625 let oraclePrice = getOraclePrice()
613626 let currentPrice = getSpotPrice()
614627 (divd(abs((oraclePrice - currentPrice)), oraclePrice) > spreadLimit())
615628 }
616629
617630
618631 func getPositionAdjustedOpenNotional (_positionSize,_option,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
619632 let positionSizeAbs = abs(_positionSize)
620633 let isShort = (0 > _positionSize)
621634 let positionNotional = if ((_option == PNL_OPTION_SPOT))
622635 then {
623- let $t02491025130 = swapOutputWithReserves(!(isShort), positionSizeAbs, false, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
624- let outPositionNotional = $t02491025130._1
625- let x1 = $t02491025130._2
626- let x2 = $t02491025130._3
627- let x3 = $t02491025130._4
636+ let $t02520525425 = swapOutputWithReserves(!(isShort), positionSizeAbs, false, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
637+ let outPositionNotional = $t02520525425._1
638+ let x1 = $t02520525425._2
639+ let x2 = $t02520525425._3
640+ let x3 = $t02520525425._4
628641 outPositionNotional
629642 }
630643 else muld(positionSizeAbs, getOraclePrice())
631644 positionNotional
632645 }
633646
634647
635648 func getPositionNotionalAndUnrealizedPnlByValues (_positionSize,_positionOpenNotional,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight,_option) = if ((_positionSize == 0))
636649 then throw("Invalid position size")
637650 else {
638651 let isShort = (0 > _positionSize)
639652 let positionNotional = getPositionAdjustedOpenNotional(_positionSize, _option, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
640653 let unrealizedPnl = if (isShort)
641654 then (_positionOpenNotional - positionNotional)
642655 else (positionNotional - _positionOpenNotional)
643656 $Tuple2(positionNotional, unrealizedPnl)
644657 }
645658
646659
647660 func getPositionNotionalAndUnrealizedPnl (_trader,_option) = {
648- let $t02655126679 = getPosition(_trader)
649- let positionSize = $t02655126679._1
650- let positionMargin = $t02655126679._2
651- let positionOpenNotional = $t02655126679._3
652- let positionLstUpdCPF = $t02655126679._4
661+ let $t02684626974 = getPosition(_trader)
662+ let positionSize = $t02684626974._1
663+ let positionMargin = $t02684626974._2
664+ let positionOpenNotional = $t02684626974._3
665+ let positionLstUpdCPF = $t02684626974._4
653666 getPositionNotionalAndUnrealizedPnlByValues(positionSize, positionOpenNotional, qtAstR(), qtAstW(), bsAstR(), bsAstW(), _option)
654667 }
655668
656669
657670 func calcMarginRatio (_remainMargin,_badDebt,_positionNotional) = divd((_remainMargin - _badDebt), _positionNotional)
658671
659672
660673 func getMarginRatioByOption (_trader,_option) = {
661- let $t02719227303 = getPosition(_trader)
662- let positionSize = $t02719227303._1
663- let positionMargin = $t02719227303._2
664- let pon = $t02719227303._3
665- let positionLstUpdCPF = $t02719227303._4
666- let $t02730927402 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
667- let positionNotional = $t02730927402._1
668- let unrealizedPnl = $t02730927402._2
669- let $t02740727573 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
670- let remainMargin = $t02740727573._1
671- let badDebt = $t02740727573._2
674+ let $t02748727598 = getPosition(_trader)
675+ let positionSize = $t02748727598._1
676+ let positionMargin = $t02748727598._2
677+ let pon = $t02748727598._3
678+ let positionLstUpdCPF = $t02748727598._4
679+ let $t02760427697 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
680+ let positionNotional = $t02760427697._1
681+ let unrealizedPnl = $t02760427697._2
682+ let $t02770227868 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
683+ let remainMargin = $t02770227868._1
684+ let badDebt = $t02770227868._2
672685 calcMarginRatio(remainMargin, badDebt, positionNotional)
673686 }
674687
675688
676689 func getMarginRatio (_trader) = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
677690
678691
679692 func getPartialLiquidationAmount (_trader,_positionSize) = {
680693 let maximumRatio = vmax(partialLiquidationRatio(), (DECIMAL_UNIT - divd(getMarginRatio(_trader), maintenanceMarginRatio())))
681694 let maxExchangedPositionSize = muld(abs(_positionSize), maximumRatio)
682695 let swapResult = swapOutput((_positionSize > 0), maxExchangedPositionSize, false)
683696 let maxExchangedQuoteAssetAmount = swapResult._1
684697 let priceImpact = swapResult._7
685698 if ((maxPriceImpact() > priceImpact))
686699 then maxExchangedQuoteAssetAmount
687700 else {
688701 let exchangedPositionSize = muld(abs(_positionSize), partialLiquidationRatio())
689702 let exchangedQuoteAssetAmount = swapOutput((_positionSize > 0), exchangedPositionSize, false)._1
690703 exchangedQuoteAssetAmount
691704 }
692705 }
693706
694707
695708 func internalClosePosition (_trader,_checkMaxPriceImpact) = {
696- let $t02881328941 = getPosition(_trader)
697- let positionSize = $t02881328941._1
698- let positionMargin = $t02881328941._2
699- let positionOpenNotional = $t02881328941._3
700- let positionLstUpdCPF = $t02881328941._4
709+ let $t02910829236 = getPosition(_trader)
710+ let positionSize = $t02910829236._1
711+ let positionMargin = $t02910829236._2
712+ let positionOpenNotional = $t02910829236._3
713+ let positionLstUpdCPF = $t02910829236._4
701714 let unrealizedPnl = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)._2
702- let $t02903629204 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
703- let remainMargin = $t02903629204._1
704- let badDebt = $t02903629204._2
715+ let $t02933129499 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
716+ let remainMargin = $t02933129499._1
717+ let badDebt = $t02933129499._2
705718 let exchangedPositionSize = -(positionSize)
706719 let realizedPnl = unrealizedPnl
707720 let marginToVault = -(remainMargin)
708- let $t02933129605 = swapOutput((positionSize > 0), abs(positionSize), _checkMaxPriceImpact)
709- let exchangedQuoteAssetAmount = $t02933129605._1
710- let quoteAssetReserveAfter = $t02933129605._2
711- let baseAssetReserveAfter = $t02933129605._3
712- let totalPositionSizeAfter = $t02933129605._4
713- let totalLongAfter = $t02933129605._5
714- let totalShortAfter = $t02933129605._6
721+ let $t02962629900 = swapOutput((positionSize > 0), abs(positionSize), _checkMaxPriceImpact)
722+ let exchangedQuoteAssetAmount = $t02962629900._1
723+ let quoteAssetReserveAfter = $t02962629900._2
724+ let baseAssetReserveAfter = $t02962629900._3
725+ let totalPositionSizeAfter = $t02962629900._4
726+ let totalLongAfter = $t02962629900._5
727+ let totalShortAfter = $t02962629900._6
715728 let openInterestNotionalAfter = (openInterestNotional() - positionOpenNotional)
716729 $Tuple13(exchangedPositionSize, badDebt, realizedPnl, marginToVault, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, exchangedQuoteAssetAmount, totalLongAfter, totalShortAfter, (openInterestLong() - (if ((positionSize > 0))
717730 then positionOpenNotional
718731 else 0)), (openInterestShort() - (if ((0 > positionSize))
719732 then positionOpenNotional
720733 else 0)))
721734 }
722735
723736
724737 func getTwapSpotPrice () = {
725738 let minuteId = ((lastBlock.timestamp / 1000) / 60)
726739 let startMinuteId = (minuteId - TWAP_INTERVAL)
727740 let listStr = valueOrElse(getString(this, k_lastDataStr), "")
728741 let list = split(listStr, ",")
729742 func filterFn (accumulator,next) = if ((startMinuteId >= parseIntValue(next)))
730743 then (accumulator :+ parseIntValue(next))
731744 else accumulator
732745
733746 let listF = {
734747 let $l = list
735748 let $s = size($l)
736749 let $acc0 = nil
737750 func $f0_1 ($a,$i) = if (($i >= $s))
738751 then $a
739752 else filterFn($a, $l[$i])
740753
741754 func $f0_2 ($a,$i) = if (($i >= $s))
742755 then $a
743756 else throw("List size exceeds 20")
744757
745758 $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)
746759 }
747760 let maxIndex = if ((size(listF) > 0))
748761 then max(listF)
749762 else parseIntValue(list[0])
750763 let lastMinuteId = valueOrElse(getInteger(this, k_lastMinuteId), 0)
751764 let endLastCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(lastMinuteId))), 0)
752765 let endLastPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(lastMinuteId))), 0)
753766 let nowCumulativePrice = (endLastCumulativePrice + ((minuteId - lastMinuteId) * endLastPrice))
754767 let startLastCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(maxIndex))), 0)
755768 let startLastPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(maxIndex))), 0)
756769 let startCumulativePrice = (startLastCumulativePrice + ((startMinuteId - maxIndex) * startLastPrice))
757770 ((nowCumulativePrice - startCumulativePrice) / TWAP_INTERVAL)
758771 }
759772
760773
761774 func getTerminalAmmState () = {
762775 let _positionSize = totalPositionSize()
763776 if ((_positionSize == 0))
764777 then $Tuple2(qtAstR(), bsAstR())
765778 else {
766779 let direction = (_positionSize > 0)
767- let $t03172831907 = swapOutput(direction, abs(_positionSize), false)
768- let currentNetMarketValue = $t03172831907._1
769- let terminalQuoteAssetReserve = $t03172831907._2
770- let terminalBaseAssetReserve = $t03172831907._3
780+ let $t03202332202 = swapOutput(direction, abs(_positionSize), false)
781+ let currentNetMarketValue = $t03202332202._1
782+ let terminalQuoteAssetReserve = $t03202332202._2
783+ let terminalBaseAssetReserve = $t03202332202._3
771784 $Tuple2(terminalQuoteAssetReserve, terminalBaseAssetReserve)
772785 }
773786 }
774787
775788
776789 func getQuoteAssetWeight (baseAssetReserve,totalPositionSize,quoteAssetReserve,targetPrice) = {
777790 let b = toBigInt(baseAssetReserve)
778791 let sz = toBigInt(totalPositionSize)
779792 let q = toBigInt(quoteAssetReserve)
780793 let p = toBigInt(targetPrice)
781794 let k = bmuld(q, b)
782795 let newB = (b + sz)
783796 let newQ = bdivd(k, newB)
784797 let z = bdivd(newQ, newB)
785798 let result = bdivd(p, z)
786799 toInt(result)
787800 }
788801
789802
790803 func getSyncTerminalPrice (_terminalPrice,_qtAstR,_bsAstR) = {
791804 let _positionSize = totalPositionSize()
792805 if ((_positionSize == 0))
793806 then {
794807 let newQtAstW = divd(muld(_terminalPrice, _bsAstR), _qtAstR)
795808 $Tuple3(newQtAstW, DECIMAL_UNIT, 0)
796809 }
797810 else {
798811 let direction = (_positionSize > 0)
799812 let currentNetMarketValue = swapOutput(direction, abs(_positionSize), false)._1
800813 let newQtAstW = getQuoteAssetWeight(_bsAstR, _positionSize, _qtAstR, _terminalPrice)
801814 let newBsAstW = DECIMAL_UNIT
802815 let marginToVault = getPositionNotionalAndUnrealizedPnlByValues(_positionSize, currentNetMarketValue, _qtAstR, newQtAstW, _bsAstR, newBsAstW, PNL_OPTION_SPOT)._2
803816 $Tuple3(newQtAstW, newBsAstW, marginToVault)
804817 }
805818 }
806819
807820
808821 func getFunding () = {
809822 let underlyingPrice = getOraclePrice()
810823 let spotTwapPrice = getTwapSpotPrice()
811824 let premium = (spotTwapPrice - underlyingPrice)
812825 if (if (if ((totalShortPositionSize() == 0))
813826 then true
814827 else (totalLongPositionSize() == 0))
815828 then true
816829 else isMarketClosed())
817830 then $Tuple2(0, 0)
818831 else if ((0 > premium))
819832 then {
820833 let shortPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
821834 let longPremiumFraction = divd(muld(shortPremiumFraction, totalShortPositionSize()), totalLongPositionSize())
822835 $Tuple2(shortPremiumFraction, longPremiumFraction)
823836 }
824837 else {
825838 let longPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
826839 let shortPremiumFraction = divd(muld(longPremiumFraction, totalLongPositionSize()), totalShortPositionSize())
827840 $Tuple2(shortPremiumFraction, longPremiumFraction)
828841 }
829842 }
830843
831844
832845 func getAdjustedFee (_artifactId,_baseFeeDiscount) = {
833846 let baseFeeRaw = fee()
834847 let baseFee = muld(baseFeeRaw, _baseFeeDiscount)
835- let $t03476835263 = if ((_artifactId != ""))
848+ let $t03506335558 = if ((_artifactId != ""))
836849 then {
837850 let artifactKind = strA(nftManagerAddress(), toCompositeKey(k_token_type, _artifactId))
838851 if ((artifactKind == FEE_REDUCTION_TOKEN_TYPE))
839852 then {
840853 let reduction = intA(nftManagerAddress(), toCompositeKey(k_token_param, _artifactId))
841854 let adjustedFee = muld(baseFee, reduction)
842855 $Tuple2(adjustedFee, true)
843856 }
844857 else throw("Invalid attached artifact")
845858 }
846859 else $Tuple2(baseFee, false)
847- let adjustedFee = $t03476835263._1
848- let burnArtifact = $t03476835263._2
860+ let adjustedFee = $t03506335558._1
861+ let burnArtifact = $t03506335558._2
849862 $Tuple2(adjustedFee, burnArtifact)
850863 }
851864
852865
853866 func isSameAssetOrNoPosition (_trader,_assetId) = {
854867 let oldPositionSize = getPosition(_trader)._1
855868 if ((oldPositionSize == 0))
856869 then true
857870 else (getPositionAsset(_trader) == _assetId)
858871 }
859872
860873
861874 func isSameAsset (_trader,_assetId) = (getPositionAsset(_trader) == _assetId)
862875
863876
864877 func getBorrowedByTraderInMarketKey (_amm,_assetId,_trader) = ((((((k_trader_market_asset_collateral + "_") + _amm) + "_") + _assetId) + "_") + _trader)
865878
866879
867880 func getBorrowedByTrader (_trader) = {
868881 let positionAsset = getPositionAsset(_trader)
869882 if ((positionAsset == toBase58String(quoteAsset())))
870883 then $Tuple2(0, positionAsset)
871884 else {
872885 let key = getBorrowedByTraderInMarketKey(toString(this), positionAsset, _trader)
873886 let borrow = valueOrElse(getInteger(collateralAddress(), key), 0)
874887 $Tuple2(borrow, positionAsset)
875888 }
876889 }
877890
878891
879892 func getForTraderWithArtifact (_trader,_artifactId) = {
880893 let doGetFeeDiscount = invoke(minerAddress(), "computeFeeDiscount", [_trader], nil)
881894 if ((doGetFeeDiscount == doGetFeeDiscount))
882895 then {
883896 let feeDiscount = match doGetFeeDiscount {
884897 case x: Int =>
885898 x
886899 case _ =>
887900 throw("Invalid computeFeeDiscount result")
888901 }
889- let $t03649436568 = getAdjustedFee(_artifactId, feeDiscount)
890- let adjustedFee = $t03649436568._1
891- let burnArtifact = $t03649436568._2
902+ let $t03678936863 = getAdjustedFee(_artifactId, feeDiscount)
903+ let adjustedFee = $t03678936863._1
904+ let burnArtifact = $t03678936863._2
892905 $Tuple2(adjustedFee, burnArtifact)
893906 }
894907 else throw("Strict value is not equal to itself.")
895908 }
896909
897910
898911 func getArtifactId (i) = {
899912 let artifactId = if ((size(i.payments) > 1))
900913 then toBase58String(valueOrErrorMessage(i.payments[1].assetId, "Invalid artifactId"))
901914 else ""
902915 artifactId
903916 }
904917
905918
906919 func distributeFee (_feeAmount) = {
907920 let feeToStakers = muld(_feeAmount, feeToStakersPercent())
908921 let feeToVault = (_feeAmount - feeToStakers)
909922 $Tuple2(feeToStakers, feeToVault)
910923 }
911924
912925
913926 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)]
914927
915928
916929 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)]
917930
918931
919932 func updatePositionAsset (_address,_assetId) = [StringEntry(toCompositeKey(k_positionAsset, _address), _assetId)]
920933
921934
922-func incrementPositionSequenceNumber (isNewPosition,_address) = if (isNewPosition)
935+func incrementPositionSequenceNumber (_isNewPosition,_address) = if (_isNewPosition)
923936 then {
924937 let currentSequence = lastSequence()
925938 [IntegerEntry(toCompositeKey(k_positionSequence, _address), (currentSequence + 1)), IntegerEntry(k_sequence, (currentSequence + 1))]
926939 }
940+ else nil
941+
942+
943+func updatePositionFee (_isNewPosition,_address,_fee) = if (_isNewPosition)
944+ then [IntegerEntry(toCompositeKey(k_positionFee, _address), _fee)]
927945 else nil
928946
929947
930948 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)]
931949
932950
933951 func appendTwap (_price) = {
934952 let minuteId = ((lastBlock.timestamp / 1000) / 60)
935953 let previousMinuteId = valueOrElse(getInteger(this, k_lastMinuteId), 0)
936954 if ((previousMinuteId > minuteId))
937955 then throw("TWAP out-of-order")
938956 else {
939957 let lastMinuteId = if ((previousMinuteId == 0))
940958 then minuteId
941959 else previousMinuteId
942960 if ((minuteId > previousMinuteId))
943961 then {
944962 let prevCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(previousMinuteId))), 0)
945963 let prevPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(previousMinuteId))), _price)
946964 let lastCumulativePrice = (prevCumulativePrice + ((minuteId - lastMinuteId) * prevPrice))
947965 let list = pushToQueue(strToList(valueOrElse(getString(this, k_lastDataStr), "")), TWAP_INTERVAL, toString(minuteId))
948966 [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))]
949967 }
950968 else {
951969 let twapDataPreviousMinuteId = valueOrElse(getInteger(this, toCompositeKey(k_twapDataPreviousMinuteId, toString(minuteId))), 0)
952970 let prevCumulativePrice = valueOrElse(getInteger(this, toCompositeKey(k_twapDataLastCumulativePrice, toString(twapDataPreviousMinuteId))), 0)
953971 let prevPrice = valueOrElse(getInteger(this, toCompositeKey(k_twapDataLastPrice, toString(twapDataPreviousMinuteId))), _price)
954972 let lastCumulativePrice = (prevCumulativePrice + ((minuteId - twapDataPreviousMinuteId) * prevPrice))
955973 [IntegerEntry(toCompositeKey(k_twapDataLastCumulativePrice, toString(minuteId)), lastCumulativePrice), IntegerEntry(toCompositeKey(k_twapDataLastPrice, toString(minuteId)), _price)]
956974 }
957975 }
958976 }
959977
960978
961979 func updateAmmReserves (_qtAstR,_bsAstR) = [IntegerEntry(k_quoteAssetReserve, _qtAstR), IntegerEntry(k_baseAssetReserve, _bsAstR)]
962980
963981
964982 func updateAmmWeights (_qtAstW,_bsAstW) = [IntegerEntry(k_quoteAssetWeight, _qtAstW), IntegerEntry(k_baseAssetWeight, _bsAstW)]
965983
966984
967985 func updateAmm (_qtAstR,_bsAstR,_totalPositionSizeAfter,_openInterestNotional,_totalLongPositionSize,_totalShortPositionSize,_totalLongOpenNotional,_totalShortOpenNotional) = {
968986 let _qtAstW = qtAstW()
969987 let _bsAstW = bsAstW()
970988 if (((_totalLongPositionSize - _totalShortPositionSize) != _totalPositionSizeAfter))
971989 then throw(((((("Invalid AMM state data: " + toString(_totalLongPositionSize)) + " + ") + toString(_totalShortPositionSize)) + " != ") + toString(_totalPositionSizeAfter)))
972990 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))))
973991 }
974992
975993
976994 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))]
977995
978996
979997 func withdraw (_address,_amount) = {
980998 let balance = assetBalance(this, quoteAsset())
981999 if ((_amount > balance))
9821000 then throw(((("Unable to withdraw " + toString(_amount)) + " from contract balance ") + toString(balance)))
9831001 else [ScriptTransfer(_address, _amount, quoteAsset())]
9841002 }
9851003
9861004
9871005 func updateBalance (i) = if ((0 > i))
9881006 then throw("Balance")
9891007 else [IntegerEntry(k_balance, i)]
9901008
9911009
9921010 func transferFee (i) = [ScriptTransfer(stakingAddress(), i, quoteAsset())]
9931011
9941012
9951013 func doBurnArtifact (_burnArtifact,i) = if (_burnArtifact)
9961014 then [Burn(valueOrErrorMessage(i.payments[1].assetId, "Invalid artifact"), 1)]
9971015 else nil
9981016
9991017
10001018 @Callable(i)
10011019 func pause () = if ((i.caller != adminAddress()))
10021020 then throw("Invalid pause params")
10031021 else [BooleanEntry(k_paused, true)]
10041022
10051023
10061024
10071025 @Callable(i)
10081026 func unpause () = if ((i.caller != adminAddress()))
10091027 then throw("Invalid unpause params")
10101028 else [BooleanEntry(k_paused, false)]
10111029
10121030
10131031
10141032 @Callable(i)
10151033 func setCloseOnly () = if ((i.caller != adminAddress()))
10161034 then throw("Invalid setCloseOnly params")
10171035 else [BooleanEntry(k_closeOnly, true)]
10181036
10191037
10201038
10211039 @Callable(i)
10221040 func unsetCloseOnly () = if ((i.caller != adminAddress()))
10231041 then throw("Invalid unsetCloseOnly params")
10241042 else [BooleanEntry(k_closeOnly, false)]
10251043
10261044
10271045
10281046 @Callable(i)
10291047 func addLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
10301048 then true
10311049 else (0 >= _quoteAssetAmount))
10321050 then throw("Invalid addLiquidity params")
10331051 else {
10341052 let _qtAstR = qtAstR()
10351053 let _bsAstR = bsAstR()
10361054 let _qtAstW = qtAstW()
10371055 let _bsAstW = bsAstW()
10381056 let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
10391057 let qtAstRAfter = (_qtAstR + _quoteAssetAmount)
10401058 let baseAssetAmountToAdd = (divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR)
10411059 let bsAstRAfter = (_bsAstR + baseAssetAmountToAdd)
1042- let $t04559045741 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1043- let newQuoteAssetWeight = $t04559045741._1
1044- let newBaseAssetWeight = $t04559045741._2
1045- let marginToVault = $t04559045741._3
1060+ let $t04610746258 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1061+ let newQuoteAssetWeight = $t04610746258._1
1062+ let newBaseAssetWeight = $t04610746258._2
1063+ let marginToVault = $t04610746258._3
10461064 let doExchangePnL = if ((marginToVault != 0))
10471065 then {
10481066 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
10491067 if ((doExchangePnL == doExchangePnL))
10501068 then nil
10511069 else throw("Strict value is not equal to itself.")
10521070 }
10531071 else nil
10541072 if ((doExchangePnL == doExchangePnL))
10551073 then (updateAmmReserves(qtAstRAfter, bsAstRAfter) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
10561074 else throw("Strict value is not equal to itself.")
10571075 }
10581076
10591077
10601078
10611079 @Callable(i)
10621080 func removeLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
10631081 then true
1064- else (0 >= _quoteAssetAmount))
1082+ else (_quoteAssetAmount >= 0))
10651083 then throw("Invalid removeLiquidity params")
10661084 else {
10671085 let _qtAstR = qtAstR()
10681086 let _bsAstR = bsAstR()
10691087 let _qtAstW = qtAstW()
10701088 let _bsAstW = bsAstW()
10711089 let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
1072- let baseAssetAmountToRemove = divd(_quoteAssetAmount, price)
10731090 let qtAstRAfter = (_qtAstR - _quoteAssetAmount)
1091+ let baseAssetAmountToRemove = abs((divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR))
10741092 let bsAstRAfter = (_bsAstR - baseAssetAmountToRemove)
1075- updateAmmReserves(qtAstRAfter, bsAstRAfter)
1093+ let $t04719047341 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1094+ let newQuoteAssetWeight = $t04719047341._1
1095+ let newBaseAssetWeight = $t04719047341._2
1096+ let marginToVault = $t04719047341._3
1097+ let doExchangePnL = if ((marginToVault != 0))
1098+ then {
1099+ let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
1100+ if ((doExchangePnL == doExchangePnL))
1101+ then nil
1102+ else throw("Strict value is not equal to itself.")
1103+ }
1104+ else nil
1105+ if ((doExchangePnL == doExchangePnL))
1106+ then (updateAmmReserves(qtAstRAfter, bsAstRAfter) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
1107+ else throw("Strict value is not equal to itself.")
10761108 }
10771109
10781110
10791111
10801112 @Callable(i)
10811113 func changeSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay) = if ((i.caller != adminAddress()))
10821114 then throw("Invalid changeSettings params")
10831115 else updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact, _partialLiquidationRatio, _maxPriceSpread, _maxOpenNotional, _feeToStakersPercent, _maxOracleDelay)
10841116
10851117
10861118
10871119 @Callable(i)
10881120 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))
10891121 then true
10901122 else (0 >= _bsAstR))
10911123 then true
10921124 else (0 >= _fundingPeriod))
10931125 then true
10941126 else (0 >= _initMarginRatio))
10951127 then true
10961128 else (0 >= _mmr))
10971129 then true
10981130 else (0 >= _liquidationFeeRatio))
10991131 then true
11001132 else (0 >= _fee))
11011133 then true
11021134 else (0 >= _spreadLimit))
11031135 then true
11041136 else (0 >= _maxPriceImpact))
11051137 then true
11061138 else (0 >= _partialLiquidationRatio))
11071139 then true
11081140 else (0 >= _maxPriceSpread))
11091141 then true
11101142 else (0 >= _maxOpenNotional))
11111143 then true
11121144 else (0 >= _feeToStakersPercent))
11131145 then true
11141146 else (_feeToStakersPercent > DECIMAL_UNIT))
11151147 then true
11161148 else (0 >= _maxOracleDelay))
11171149 then true
11181150 else initialized())
11191151 then throw("Invalid initialize parameters")
11201152 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)])
11211153
11221154
11231155
11241156 @Callable(i)
1125-func decreasePosition (_amount,_leverage,_minBaseAssetAmount) = {
1126- let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
1127- if ((sync == sync))
1128- then {
1129- let _trader = getActualCaller(i)
1130- if (if (if (if (if (if ((0 >= _amount))
1131- then true
1132- else !(initialized()))
1133- then true
1134- else !(requireMoreMarginRatio(divd(DECIMAL_UNIT, _leverage), initMarginRatio(), true)))
1135- then true
1136- else !(requireOpenPosition(_trader)))
1137- then true
1138- else paused())
1139- then true
1140- else isMarketClosed())
1141- then throw("Invalid decreasePosition parameters")
1142- else {
1143- let $t04960849748 = getPosition(_trader)
1144- let oldPositionSize = $t04960849748._1
1145- let oldPositionMargin = $t04960849748._2
1146- let oldPositionOpenNotional = $t04960849748._3
1147- let oldPositionLstUpdCPF = $t04960849748._4
1148- let _direction = if ((oldPositionSize > 0))
1149- then DIR_SHORT
1150- else DIR_LONG
1151- let isAdd = (_direction == DIR_LONG)
1152- let openNotional = muld(_amount, _leverage)
1153- let $t04992150025 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1154- let oldPositionNotional = $t04992150025._1
1155- let unrealizedPnl = $t04992150025._2
1156- let $t05003152673 = if ((oldPositionNotional > openNotional))
1157- then {
1158- let $t05044650630 = swapInput(isAdd, openNotional)
1159- let exchangedPositionSize = $t05044650630._1
1160- let quoteAssetReserveAfter = $t05044650630._2
1161- let baseAssetReserveAfter = $t05044650630._3
1162- let totalPositionSizeAfter = $t05044650630._4
1163- let exchangedPositionSizeAbs = abs(exchangedPositionSize)
1164- if (if ((_minBaseAssetAmount != 0))
1165- then (_minBaseAssetAmount > exchangedPositionSizeAbs)
1166- else false)
1167- then throw(((("Too little base asset exchanged, got " + toString(exchangedPositionSizeAbs)) + " expected ") + toString(_minBaseAssetAmount)))
1168- else {
1169- let realizedPnl = divd(muld(unrealizedPnl, exchangedPositionSizeAbs), abs(oldPositionSize))
1170- let $t05106751296 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1171- let remainMargin = $t05106751296._1
1172- let badDebt = $t05106751296._2
1173- let exchangedQuoteAssetAmount = openNotional
1174- let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
1175- let remainOpenNotional = if ((oldPositionSize > 0))
1176- then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
1177- else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
1178- let newPositionSize = (oldPositionSize + exchangedPositionSize)
1179- $Tuple12(newPositionSize, remainMargin, abs(remainOpenNotional), latestCumulativePremiumFraction(newPositionSize), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, (openInterestNotional() - openNotional), (totalLongPositionSize() - (if ((newPositionSize > 0))
1180- then abs(exchangedPositionSize)
1181- else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
1182- then abs(exchangedPositionSize)
1183- else 0)), (openInterestLong() - (if ((newPositionSize > 0))
1184- then openNotional
1185- else 0)), (openInterestShort() - (if ((0 > newPositionSize))
1186- then openNotional
1187- else 0)))
1188- }
1189- }
1190- else throw("Close position first")
1191- let newPositionSize = $t05003152673._1
1192- let newPositionRemainMargin = $t05003152673._2
1193- let newPositionOpenNotional = $t05003152673._3
1194- let newPositionLatestCPF = $t05003152673._4
1195- let baseAssetReserveAfter = $t05003152673._5
1196- let quoteAssetReserveAfter = $t05003152673._6
1197- let totalPositionSizeAfter = $t05003152673._7
1198- let openInterestNotionalAfter = $t05003152673._8
1199- let totalLongAfter = $t05003152673._9
1200- let totalShortAfter = $t05003152673._10
1201- let totalLongOpenInterestAfter = $t05003152673._11
1202- let totalShortOpenInterestAfter = $t05003152673._12
1203- let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
1204- if ((notifyNotional == notifyNotional))
1205- then (updatePosition(_trader, newPositionSize, newPositionRemainMargin, newPositionOpenNotional, newPositionLatestCPF) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter))
1206- else throw("Strict value is not equal to itself.")
1207- }
1208- }
1209- else throw("Strict value is not equal to itself.")
1210- }
1211-
1212-
1213-
1214-@Callable(i)
12151157 func increasePosition (_direction,_leverage,_minBaseAssetAmount,_refLink) = {
12161158 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
12171159 if ((sync == sync))
12181160 then {
12191161 let _trader = getActualCaller(i)
12201162 let _rawAmount = i.payments[0].amount
12211163 let _assetId = i.payments[0].assetId
12221164 let _assetIdStr = toBase58String(value(_assetId))
12231165 let isQuoteAsset = (_assetId == quoteAsset())
12241166 let isCollateralAsset = isWhitelistAsset(_assetIdStr)
12251167 if (if (if (if (if (if (if (if (if (if ((_direction != DIR_LONG))
12261168 then (_direction != DIR_SHORT)
12271169 else false)
12281170 then true
12291171 else (0 >= _rawAmount))
12301172 then true
12311173 else !(initialized()))
12321174 then true
12331175 else if (!(isQuoteAsset))
12341176 then !(isCollateralAsset)
12351177 else false)
12361178 then true
12371179 else !(isSameAssetOrNoPosition(_trader, _assetIdStr)))
12381180 then true
12391181 else !(requireMoreMarginRatio(divd(DECIMAL_UNIT, _leverage), initMarginRatio(), true)))
12401182 then true
12411183 else paused())
12421184 then true
12431185 else closeOnly())
12441186 then true
12451187 else isMarketClosed())
12461188 then throw("Invalid increasePosition parameters")
12471189 else {
1248- let $t05413554220 = getForTraderWithArtifact(_trader, getArtifactId(i))
1249- let adjustedFee = $t05413554220._1
1250- let burnArtifact = $t05413554220._2
1251- let rawFeeAmount = muld(_rawAmount, adjustedFee)
1252- let _amount = (_rawAmount - rawFeeAmount)
1190+ let $t05100951158 = getForTraderWithArtifact(_trader, getArtifactId(i))
1191+ let adjustedFee = $t05100951158._1
1192+ let burnArtifact = $t05100951158._2
1193+ let _amount = divd(_rawAmount, (muld(adjustedFee, _leverage) + DECIMAL_UNIT))
1194+ let rawFeeAmount = (_rawAmount - _amount)
12531195 let distributeFeeAmount = if (isCollateralAsset)
12541196 then {
12551197 let doBorrow = invoke(collateralAddress(), "borrow", [_trader], [AttachedPayment(_assetId, _amount)])
12561198 if ((doBorrow == doBorrow))
12571199 then {
12581200 let balanceBefore = assetBalance(this, quoteAsset())
12591201 if ((balanceBefore == balanceBefore))
12601202 then {
12611203 let doSwap = invoke(swapAddress(), "swap", [toBase58String(quoteAsset()), 0], [AttachedPayment(_assetId, rawFeeAmount)])
12621204 if ((doSwap == doSwap))
12631205 then {
12641206 let balanceAfter = assetBalance(this, quoteAsset())
12651207 if ((balanceAfter == balanceAfter))
12661208 then {
12671209 let exchangedAmount = (balanceAfter - balanceBefore)
12681210 if ((exchangedAmount == exchangedAmount))
12691211 then exchangedAmount
12701212 else throw("Strict value is not equal to itself.")
12711213 }
12721214 else throw("Strict value is not equal to itself.")
12731215 }
12741216 else throw("Strict value is not equal to itself.")
12751217 }
12761218 else throw("Strict value is not equal to itself.")
12771219 }
12781220 else throw("Strict value is not equal to itself.")
12791221 }
12801222 else rawFeeAmount
12811223 if ((distributeFeeAmount == distributeFeeAmount))
12821224 then {
12831225 let referrerFeeAny = invoke(referralAddress(), "acceptPaymentWithLink", [_trader, _refLink], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
12841226 if ((referrerFeeAny == referrerFeeAny))
12851227 then {
12861228 let referrerFee = match referrerFeeAny {
12871229 case x: Int =>
12881230 x
12891231 case _ =>
12901232 throw("Invalid referrerFee")
12911233 }
12921234 let feeAmount = (distributeFeeAmount - referrerFee)
1293- let $t05553655676 = getPosition(_trader)
1294- let oldPositionSize = $t05553655676._1
1295- let oldPositionMargin = $t05553655676._2
1296- let oldPositionOpenNotional = $t05553655676._3
1297- let oldPositionLstUpdCPF = $t05553655676._4
1235+ let $t05250052640 = getPosition(_trader)
1236+ let oldPositionSize = $t05250052640._1
1237+ let oldPositionMargin = $t05250052640._2
1238+ let oldPositionOpenNotional = $t05250052640._3
1239+ let oldPositionLstUpdCPF = $t05250052640._4
12981240 let isNewPosition = (oldPositionSize == 0)
12991241 let isSameDirection = if ((oldPositionSize > 0))
13001242 then (_direction == DIR_LONG)
13011243 else (_direction == DIR_SHORT)
13021244 let expandExisting = if (!(isNewPosition))
13031245 then isSameDirection
13041246 else false
13051247 let isAdd = (_direction == DIR_LONG)
1306- let $t05596558927 = if (if (isNewPosition)
1248+ let $t05292955891 = if (if (isNewPosition)
13071249 then true
13081250 else expandExisting)
13091251 then {
13101252 let openNotional = muld(_amount, _leverage)
1311- let $t05642756600 = swapInput(isAdd, openNotional)
1312- let amountBaseAssetBought = $t05642756600._1
1313- let quoteAssetReserveAfter = $t05642756600._2
1314- let baseAssetReserveAfter = $t05642756600._3
1315- let totalPositionSizeAfter = $t05642756600._4
1253+ let $t05339153564 = swapInput(isAdd, openNotional)
1254+ let amountBaseAssetBought = $t05339153564._1
1255+ let quoteAssetReserveAfter = $t05339153564._2
1256+ let baseAssetReserveAfter = $t05339153564._3
1257+ let totalPositionSizeAfter = $t05339153564._4
13161258 if (if ((_minBaseAssetAmount != 0))
13171259 then (_minBaseAssetAmount > abs(amountBaseAssetBought))
13181260 else false)
13191261 then throw(((("Limit error: " + toString(abs(amountBaseAssetBought))) + " < ") + toString(_minBaseAssetAmount)))
13201262 else {
13211263 let newPositionSize = (oldPositionSize + amountBaseAssetBought)
13221264 let totalLongOpenInterestAfter = (openInterestLong() + (if ((newPositionSize > 0))
13231265 then openNotional
13241266 else 0))
13251267 let totalShortOpenInterestAfter = (openInterestShort() + (if ((0 > newPositionSize))
13261268 then openNotional
13271269 else 0))
1328- let $t05714657367 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, _amount)
1329- let remainMargin = $t05714657367._1
1330- let x1 = $t05714657367._2
1331- let x2 = $t05714657367._3
1270+ let $t05411054331 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, _amount)
1271+ let remainMargin = $t05411054331._1
1272+ let x1 = $t05411054331._2
1273+ let x2 = $t05411054331._3
13321274 if (!(requireNotOverSpreadLimit(quoteAssetReserveAfter, baseAssetReserveAfter)))
13331275 then throw("Over max spread limit")
13341276 else if (!(requireNotOverMaxOpenNotional(totalLongOpenInterestAfter, totalShortOpenInterestAfter)))
13351277 then throw("Over max open notional")
13361278 else $Tuple12(newPositionSize, remainMargin, (oldPositionOpenNotional + openNotional), latestCumulativePremiumFraction(newPositionSize), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, (openInterestNotional() + openNotional), (totalLongPositionSize() + (if ((newPositionSize > 0))
13371279 then abs(amountBaseAssetBought)
13381280 else 0)), (totalShortPositionSize() + (if ((0 > newPositionSize))
13391281 then abs(amountBaseAssetBought)
13401282 else 0)), totalLongOpenInterestAfter, totalShortOpenInterestAfter)
13411283 }
13421284 }
13431285 else {
13441286 let openNotional = muld(_amount, _leverage)
1345- let $t05862758743 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1346- let oldPositionNotional = $t05862758743._1
1347- let unrealizedPnl = $t05862758743._2
1287+ let $t05559155707 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1288+ let oldPositionNotional = $t05559155707._1
1289+ let unrealizedPnl = $t05559155707._2
13481290 if ((oldPositionNotional > openNotional))
13491291 then throw("Use decreasePosition to decrease position size")
13501292 else throw("Close position first")
13511293 }
1352- let newPositionSize = $t05596558927._1
1353- let newPositionRemainMargin = $t05596558927._2
1354- let newPositionOpenNotional = $t05596558927._3
1355- let newPositionLatestCPF = $t05596558927._4
1356- let baseAssetReserveAfter = $t05596558927._5
1357- let quoteAssetReserveAfter = $t05596558927._6
1358- let totalPositionSizeAfter = $t05596558927._7
1359- let openInterestNotionalAfter = $t05596558927._8
1360- let totalLongAfter = $t05596558927._9
1361- let totalShortAfter = $t05596558927._10
1362- let totalLongOpenInterestAfter = $t05596558927._11
1363- let totalShortOpenInterestAfter = $t05596558927._12
1364- let $t05893358990 = distributeFee(feeAmount)
1365- let feeToStakers = $t05893358990._1
1366- let feeToVault = $t05893358990._2
1294+ let newPositionSize = $t05292955891._1
1295+ let newPositionRemainMargin = $t05292955891._2
1296+ let newPositionOpenNotional = $t05292955891._3
1297+ let newPositionLatestCPF = $t05292955891._4
1298+ let baseAssetReserveAfter = $t05292955891._5
1299+ let quoteAssetReserveAfter = $t05292955891._6
1300+ let totalPositionSizeAfter = $t05292955891._7
1301+ let openInterestNotionalAfter = $t05292955891._8
1302+ let totalLongAfter = $t05292955891._9
1303+ let totalShortAfter = $t05292955891._10
1304+ let totalLongOpenInterestAfter = $t05292955891._11
1305+ let totalShortOpenInterestAfter = $t05292955891._12
1306+ let $t05589755954 = distributeFee(feeAmount)
1307+ let feeToStakers = $t05589755954._1
1308+ let feeToVault = $t05589755954._2
13671309 let stake = if (isQuoteAsset)
13681310 then {
13691311 let stake = invoke(vaultAddress(), "addLocked", [false], [AttachedPayment(quoteAsset(), _amount)])
13701312 if ((stake == stake))
13711313 then nil
13721314 else throw("Strict value is not equal to itself.")
13731315 }
13741316 else nil
13751317 if ((stake == stake))
13761318 then {
1377- let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
1378- if ((depositInsurance == depositInsurance))
1319+ let depositVault = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
1320+ if ((depositVault == depositVault))
13791321 then {
13801322 let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, feeAmount], nil)
13811323 if ((notifyFee == notifyFee))
13821324 then {
13831325 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
13841326 if ((notifyNotional == notifyNotional))
1385- 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))
1327+ then (((((((updatePosition(_trader, newPositionSize, newPositionRemainMargin, newPositionOpenNotional, newPositionLatestCPF) ++ incrementPositionSequenceNumber(isNewPosition, _trader)) ++ updatePositionFee(isNewPosition, _trader, adjustedFee)) ++ updatePositionAsset(_trader, _assetIdStr)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ transferFee(feeToStakers)) ++ updateBalance((cbalance() + _amount))) ++ doBurnArtifact(burnArtifact, i))
13861328 else throw("Strict value is not equal to itself.")
13871329 }
13881330 else throw("Strict value is not equal to itself.")
13891331 }
13901332 else throw("Strict value is not equal to itself.")
13911333 }
13921334 else throw("Strict value is not equal to itself.")
13931335 }
13941336 else throw("Strict value is not equal to itself.")
13951337 }
13961338 else throw("Strict value is not equal to itself.")
13971339 }
13981340 }
13991341 else throw("Strict value is not equal to itself.")
14001342 }
14011343
14021344
14031345
14041346 @Callable(i)
14051347 func addMargin () = {
14061348 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
14071349 if ((sync == sync))
14081350 then {
14091351 let _trader = toString(i.caller)
1410- let _rawAmount = i.payments[0].amount
1352+ let _amount = i.payments[0].amount
14111353 let _assetId = i.payments[0].assetId
14121354 let _assetIdStr = toBase58String(value(_assetId))
14131355 let isQuoteAsset = (_assetId == quoteAsset())
14141356 let isCollateralAsset = isWhitelistAsset(_assetIdStr)
14151357 if (if (if (if (if (if (if (if (!(isQuoteAsset))
14161358 then !(isCollateralAsset)
14171359 else false)
14181360 then true
14191361 else !(requireOpenPosition(toString(i.caller))))
14201362 then true
14211363 else !(isSameAsset(_trader, _assetIdStr)))
14221364 then true
14231365 else !(initialized()))
14241366 then true
14251367 else paused())
14261368 then true
14271369 else closeOnly())
14281370 then true
14291371 else isMarketClosed())
14301372 then throw("Invalid addMargin parameters")
14311373 else {
1432- let $t06096261047 = getForTraderWithArtifact(_trader, getArtifactId(i))
1433- let adjustedFee = $t06096261047._1
1434- let burnArtifact = $t06096261047._2
1435- let rawFeeAmount = muld(_rawAmount, adjustedFee)
1436- let _amount = (_rawAmount - rawFeeAmount)
1437- let distributeFeeAmount = if (isCollateralAsset)
1374+ let $t05798558125 = getPosition(_trader)
1375+ let oldPositionSize = $t05798558125._1
1376+ let oldPositionMargin = $t05798558125._2
1377+ let oldPositionOpenNotional = $t05798558125._3
1378+ let oldPositionLstUpdCPF = $t05798558125._4
1379+ let stake = if (isQuoteAsset)
14381380 then {
1439- let doBorrow = invoke(collateralAddress(), "borrow", [_trader], [AttachedPayment(_assetId, _amount)])
1440- if ((doBorrow == doBorrow))
1441- then {
1442- let balanceBefore = assetBalance(this, quoteAsset())
1443- if ((balanceBefore == balanceBefore))
1444- then {
1445- let doSwap = invoke(swapAddress(), "swap", [toBase58String(quoteAsset()), 0], [AttachedPayment(_assetId, rawFeeAmount)])
1446- if ((doSwap == doSwap))
1447- then {
1448- let balanceAfter = assetBalance(this, quoteAsset())
1449- if ((balanceAfter == balanceAfter))
1450- then {
1451- let exchangedAmount = (balanceAfter - balanceBefore)
1452- if ((exchangedAmount == exchangedAmount))
1453- then exchangedAmount
1454- else throw("Strict value is not equal to itself.")
1455- }
1456- else throw("Strict value is not equal to itself.")
1457- }
1458- else throw("Strict value is not equal to itself.")
1459- }
1460- else throw("Strict value is not equal to itself.")
1461- }
1381+ let stake = invoke(vaultAddress(), "addLocked", [false], [AttachedPayment(quoteAsset(), _amount)])
1382+ if ((stake == stake))
1383+ then nil
14621384 else throw("Strict value is not equal to itself.")
14631385 }
1464- else rawFeeAmount
1465- if ((distributeFeeAmount == distributeFeeAmount))
1466- then {
1467- let referrerFeeAny = invoke(referralAddress(), "acceptPayment", [_trader], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
1468- if ((referrerFeeAny == referrerFeeAny))
1469- then {
1470- let referrerFee = match referrerFeeAny {
1471- case x: Int =>
1472- x
1473- case _ =>
1474- throw("Invalid referrerFee")
1475- }
1476- let feeAmount = (distributeFeeAmount - referrerFee)
1477- let $t06234662486 = getPosition(_trader)
1478- let oldPositionSize = $t06234662486._1
1479- let oldPositionMargin = $t06234662486._2
1480- let oldPositionOpenNotional = $t06234662486._3
1481- let oldPositionLstUpdCPF = $t06234662486._4
1482- let $t06249262549 = distributeFee(feeAmount)
1483- let feeToStakers = $t06249262549._1
1484- let feeToVault = $t06249262549._2
1485- let stake = if (isQuoteAsset)
1486- then {
1487- let stake = invoke(vaultAddress(), "addLocked", [false], [AttachedPayment(quoteAsset(), _amount)])
1488- if ((stake == stake))
1489- then nil
1490- else throw("Strict value is not equal to itself.")
1491- }
1492- else nil
1493- if ((stake == stake))
1494- then {
1495- let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
1496- if ((depositInsurance == depositInsurance))
1497- then {
1498- let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, feeAmount], nil)
1499- if ((notifyFee == notifyFee))
1500- then (((updatePosition(_trader, oldPositionSize, (oldPositionMargin + _amount), oldPositionOpenNotional, oldPositionLstUpdCPF) ++ transferFee(feeToStakers)) ++ updateBalance((cbalance() + _amount))) ++ doBurnArtifact(burnArtifact, i))
1501- else throw("Strict value is not equal to itself.")
1502- }
1503- else throw("Strict value is not equal to itself.")
1504- }
1505- else throw("Strict value is not equal to itself.")
1506- }
1507- else throw("Strict value is not equal to itself.")
1508- }
1386+ else nil
1387+ if ((stake == stake))
1388+ then (updatePosition(_trader, oldPositionSize, (oldPositionMargin + _amount), oldPositionOpenNotional, oldPositionLstUpdCPF) ++ updateBalance((cbalance() + _amount)))
15091389 else throw("Strict value is not equal to itself.")
15101390 }
15111391 }
15121392 else throw("Strict value is not equal to itself.")
15131393 }
15141394
15151395
15161396
15171397 @Callable(i)
15181398 func removeMargin (_amount) = {
15191399 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
15201400 if ((sync == sync))
15211401 then {
15221402 let _trader = toString(i.caller)
15231403 if (if (if (if (if ((0 >= _amount))
15241404 then true
15251405 else !(requireOpenPosition(_trader)))
15261406 then true
15271407 else !(initialized()))
15281408 then true
15291409 else paused())
15301410 then true
15311411 else isMarketClosed())
15321412 then throw("Invalid removeMargin parameters")
15331413 else {
1534- let $t06368563825 = getPosition(_trader)
1535- let oldPositionSize = $t06368563825._1
1536- let oldPositionMargin = $t06368563825._2
1537- let oldPositionOpenNotional = $t06368563825._3
1538- let oldPositionLstUpdCPF = $t06368563825._4
1414+ let $t05892059060 = getPosition(_trader)
1415+ let oldPositionSize = $t05892059060._1
1416+ let oldPositionMargin = $t05892059060._2
1417+ let oldPositionOpenNotional = $t05892059060._3
1418+ let oldPositionLstUpdCPF = $t05892059060._4
15391419 let marginDelta = -(_amount)
1540- let $t06386264041 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, marginDelta)
1541- let remainMargin = $t06386264041._1
1542- let badDebt = $t06386264041._2
1420+ let $t05909759276 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, marginDelta)
1421+ let remainMargin = $t05909759276._1
1422+ let badDebt = $t05909759276._2
15431423 if ((badDebt != 0))
15441424 then throw("Invalid removed margin amount")
15451425 else {
15461426 let marginRatio = calcMarginRatio(remainMargin, badDebt, oldPositionOpenNotional)
15471427 if (!(requireMoreMarginRatio(marginRatio, initMarginRatio(), true)))
15481428 then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
15491429 else {
15501430 let quoteAssetStr = toBase58String(quoteAsset())
1551- let $t06448564539 = getBorrowedByTrader(_trader)
1552- let borrowed = $t06448564539._1
1553- let assetId = $t06448564539._2
1431+ let $t05972059774 = getBorrowedByTrader(_trader)
1432+ let borrowed = $t05972059774._1
1433+ let assetId = $t05972059774._2
15541434 let toRepay = if ((_amount > borrowed))
15551435 then borrowed
15561436 else _amount
15571437 let toWithdraw = if ((borrowed > _amount))
15581438 then 0
15591439 else (_amount - borrowed)
15601440 let finalBorrow = (borrowed - toRepay)
15611441 let switchPositionToQuote = if ((finalBorrow > 0))
15621442 then nil
15631443 else updatePositionAsset(_trader, quoteAssetStr)
15641444 let doSanityCheck = if (((toRepay + toWithdraw) != _amount))
15651445 then throw(((((("toRepay=" + toString(toRepay)) + " + toWithdraw=") + toString(toWithdraw)) + " != ") + toString(_amount)))
15661446 else nil
15671447 if ((doSanityCheck == doSanityCheck))
15681448 then {
15691449 let doUnstake = if ((toWithdraw > 0))
15701450 then {
15711451 let doUnstake = invoke(vaultAddress(), "withdrawLocked", [toWithdraw], nil)
15721452 if ((doUnstake == doUnstake))
15731453 then nil
15741454 else throw("Strict value is not equal to itself.")
15751455 }
15761456 else nil
15771457 if ((doUnstake == doUnstake))
15781458 then {
15791459 let returnCollateralAction = if ((toRepay > 0))
15801460 then {
15811461 let doRepay = invoke(collateralAddress(), "repay", [_trader, toRepay, assetId], nil)
15821462 if ((doRepay == doRepay))
15831463 then [ScriptTransfer(i.caller, toRepay, fromBase58String(assetId))]
15841464 else throw("Strict value is not equal to itself.")
15851465 }
15861466 else nil
15871467 if ((returnCollateralAction == returnCollateralAction))
15881468 then ((((updatePosition(_trader, oldPositionSize, remainMargin, oldPositionOpenNotional, latestCumulativePremiumFraction(oldPositionSize)) ++ (if ((toWithdraw > 0))
15891469 then withdraw(i.caller, toWithdraw)
15901470 else nil)) ++ updateBalance((cbalance() - _amount))) ++ switchPositionToQuote) ++ returnCollateralAction)
15911471 else throw("Strict value is not equal to itself.")
15921472 }
15931473 else throw("Strict value is not equal to itself.")
15941474 }
15951475 else throw("Strict value is not equal to itself.")
15961476 }
15971477 }
15981478 }
15991479 }
16001480 else throw("Strict value is not equal to itself.")
16011481 }
16021482
16031483
16041484
16051485 @Callable(i)
1606-func closePosition (_size,_minQuoteAssetAmount) = {
1486+func closePosition (_size,_minQuoteAssetAmount,_addToMargin) = {
16071487 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
16081488 if ((sync == sync))
16091489 then {
16101490 let _trader = getActualCaller(i)
16111491 let _traderAddress = valueOrErrorMessage(addressFromString(_trader), "Invalid caller")
1492+ let positionFee = getPositionFee(_trader)
16121493 if (if (if (if (if (if (!(requireOpenPosition(_trader)))
16131494 then true
16141495 else !(initialized()))
16151496 then true
16161497 else paused())
16171498 then true
16181499 else (0 >= _size))
16191500 then true
16201501 else (0 > _minQuoteAssetAmount))
16211502 then true
16221503 else isMarketClosed())
16231504 then throw("Invalid closePosition parameters")
16241505 else {
1625- let $t06672366863 = getPosition(_trader)
1626- let oldPositionSize = $t06672366863._1
1627- let oldPositionMargin = $t06672366863._2
1628- let oldPositionOpenNotional = $t06672366863._3
1629- let oldPositionLstUpdCPF = $t06672366863._4
1630- let $t06686971999 = if ((abs(oldPositionSize) > _size))
1506+ let $t06201162151 = getPosition(_trader)
1507+ let oldPositionSize = $t06201162151._1
1508+ let oldPositionMargin = $t06201162151._2
1509+ let oldPositionOpenNotional = $t06201162151._3
1510+ let oldPositionLstUpdCPF = $t06201162151._4
1511+ let $t06215768035 = if ((abs(oldPositionSize) > _size))
16311512 then {
16321513 let _direction = if ((oldPositionSize > 0))
16331514 then DIR_SHORT
16341515 else DIR_LONG
16351516 let isAdd = (_direction == DIR_LONG)
1636- let $t06746067682 = swapOutput((oldPositionSize > 0), _size, true)
1637- let exchangedQuoteAssetAmount = $t06746067682._1
1638- let quoteAssetReserveAfter = $t06746067682._2
1639- let baseAssetReserveAfter = $t06746067682._3
1640- let totalPositionSizeAfter = $t06746067682._4
1517+ let $t06276862990 = swapOutput((oldPositionSize > 0), _size, true)
1518+ let exchangedQuoteAssetAmount = $t06276862990._1
1519+ let quoteAssetReserveAfter = $t06276862990._2
1520+ let baseAssetReserveAfter = $t06276862990._3
1521+ let totalPositionSizeAfter = $t06276862990._4
16411522 let exchangedPositionSize = if ((oldPositionSize > 0))
16421523 then -(_size)
16431524 else _size
1644- let $t06777367927 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1645- let oldPositionNotional = $t06777367927._1
1646- let unrealizedPnl = $t06777367927._2
1525+ let $t06308163235 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1526+ let oldPositionNotional = $t06308163235._1
1527+ let unrealizedPnl = $t06308163235._2
16471528 let mr = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
16481529 let realizedRatio = divd(abs(exchangedPositionSize), abs(oldPositionSize))
16491530 let realizedPnl = muld(unrealizedPnl, realizedRatio)
1531+ let realizedFee = muld(muld(oldPositionNotional, realizedRatio), positionFee)
16501532 let remainMarginBefore = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, unrealizedPnl)._1
1651- let $t06842868656 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1652- let x1 = $t06842868656._1
1653- let positionBadDebt = $t06842868656._2
1654- let fundingPayment = $t06842868656._3
1533+ let positionBadDebt = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)._2
16551534 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
16561535 let remainOpenNotional = if ((oldPositionSize > 0))
16571536 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
16581537 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
16591538 let newPositionOpenNotional = abs(remainOpenNotional)
1539+ let newPositionSize = (oldPositionSize + exchangedPositionSize)
1540+ let newPositionLstUpdCPF = latestCumulativePremiumFraction(newPositionSize)
1541+ let openNotionalDelta = (oldPositionOpenNotional - newPositionOpenNotional)
1542+ let openInterestNotionalAfter = (openInterestNotional() - openNotionalDelta)
16601543 let newPositionMargin = if ((oldPositionSize > 0))
16611544 then (muld((newPositionOpenNotional + unrealizedPnlAfter), mr) - unrealizedPnlAfter)
16621545 else (muld((newPositionOpenNotional - unrealizedPnlAfter), mr) - unrealizedPnlAfter)
1663- let openNotionalDelta = (oldPositionOpenNotional - newPositionOpenNotional)
1664- let newPositionSize = (oldPositionSize + exchangedPositionSize)
1665- let newPositionLstUpdCPF = latestCumulativePremiumFraction(newPositionSize)
1666- let openInterestNotionalAfter = (openInterestNotional() - openNotionalDelta)
1546+ let marginToTraderRaw = ((remainMarginBefore - (newPositionMargin + unrealizedPnlAfter)) - realizedFee)
1547+ let marginToTrader = if ((0 > marginToTraderRaw))
1548+ then throw("Margin error: unable to pay close fee")
1549+ else marginToTraderRaw
16671550 if (if ((_minQuoteAssetAmount != 0))
16681551 then (_minQuoteAssetAmount > exchangedQuoteAssetAmount)
16691552 else false)
16701553 then throw(((("Limit error: " + toString(exchangedQuoteAssetAmount)) + " < ") + toString(_minQuoteAssetAmount)))
1671- else $Tuple15(newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, positionBadDebt, realizedPnl, (remainMarginBefore - (newPositionMargin + unrealizedPnlAfter)), quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, (totalLongPositionSize() - (if ((newPositionSize > 0))
1554+ else $Tuple16(newPositionSize, if (_addToMargin)
1555+ then (newPositionMargin + marginToTrader)
1556+ else newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, positionBadDebt, realizedPnl, if (_addToMargin)
1557+ then 0
1558+ else marginToTrader, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, (totalLongPositionSize() - (if ((newPositionSize > 0))
16721559 then abs(exchangedPositionSize)
16731560 else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
16741561 then abs(exchangedPositionSize)
16751562 else 0)), (openInterestLong() - (if ((newPositionSize > 0))
16761563 then openNotionalDelta
16771564 else 0)), (openInterestShort() - (if ((0 > newPositionSize))
16781565 then openNotionalDelta
1679- else 0)))
1566+ else 0)), realizedFee)
16801567 }
16811568 else if ((_size > abs(oldPositionSize)))
16821569 then throw("Invalid closePosition parameters")
16831570 else {
1684- let $t07094071359 = internalClosePosition(_trader, true)
1685- let exchangedQuoteAssetAmount = $t07094071359._1
1686- let positionBadDebt = $t07094071359._2
1687- let realizedPnl = $t07094071359._3
1688- let marginToVault = $t07094071359._4
1689- let quoteAssetReserveAfter = $t07094071359._5
1690- let baseAssetReserveAfter = $t07094071359._6
1691- let totalPositionSizeAfter = $t07094071359._7
1692- let openInterestNotionalAfter = $t07094071359._8
1693- let x2 = $t07094071359._9
1694- let totalLongAfter = $t07094071359._10
1695- let totalShortAfter = $t07094071359._11
1696- let totalLongOpenInterestAfter = $t07094071359._12
1697- let totalShortOpenInterestAfter = $t07094071359._13
1571+ let $t06645466884 = internalClosePosition(_trader, true)
1572+ let x2 = $t06645466884._1
1573+ let positionBadDebt = $t06645466884._2
1574+ let realizedPnl = $t06645466884._3
1575+ let marginToTraderWithoutFee = $t06645466884._4
1576+ let quoteAssetReserveAfter = $t06645466884._5
1577+ let baseAssetReserveAfter = $t06645466884._6
1578+ let totalPositionSizeAfter = $t06645466884._7
1579+ let openInterestNotionalAfter = $t06645466884._8
1580+ let exchangedQuoteAssetAmount = $t06645466884._9
1581+ let totalLongAfter = $t06645466884._10
1582+ let totalShortAfter = $t06645466884._11
1583+ let totalLongOpenInterestAfter = $t06645466884._12
1584+ let totalShortOpenInterestAfter = $t06645466884._13
1585+ let realizedFee = muld(exchangedQuoteAssetAmount, positionFee)
1586+ let marginToTraderRaw = (abs(marginToTraderWithoutFee) - realizedFee)
1587+ let marginToTrader = if ((0 > marginToTraderRaw))
1588+ then throw(((((((("Margin error: unable to pay close fee: " + toString(realizedFee)) + " margin: ") + toString(marginToTraderWithoutFee)) + " fee percent: ") + toString(positionFee)) + " notional: ") + toString(exchangedQuoteAssetAmount)))
1589+ else marginToTraderRaw
16981590 if (if ((_minQuoteAssetAmount != 0))
16991591 then (_minQuoteAssetAmount > exchangedQuoteAssetAmount)
17001592 else false)
17011593 then throw(((("Limit error: " + toString(exchangedQuoteAssetAmount)) + " < ") + toString(_minQuoteAssetAmount)))
1702- else $Tuple15(0, 0, 0, 0, positionBadDebt, realizedPnl, marginToVault, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)
1594+ else $Tuple16(0, 0, 0, 0, positionBadDebt, realizedPnl, marginToTrader, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter, realizedFee)
17031595 }
1704- let newPositionSize = $t06686971999._1
1705- let newPositionMargin = $t06686971999._2
1706- let newPositionOpenNotional = $t06686971999._3
1707- let newPositionLstUpdCPF = $t06686971999._4
1708- let positionBadDebt = $t06686971999._5
1709- let realizedPnl = $t06686971999._6
1710- let marginToVault = $t06686971999._7
1711- let quoteAssetReserveAfter = $t06686971999._8
1712- let baseAssetReserveAfter = $t06686971999._9
1713- let totalPositionSizeAfter = $t06686971999._10
1714- let openInterestNotionalAfter = $t06686971999._11
1715- let totalLongAfter = $t06686971999._12
1716- let totalShortAfter = $t06686971999._13
1717- let totalLongOpenInterestAfter = $t06686971999._14
1718- let totalShortOpenInterestAfter = $t06686971999._15
1596+ let newPositionSize = $t06215768035._1
1597+ let newPositionMargin = $t06215768035._2
1598+ let newPositionOpenNotional = $t06215768035._3
1599+ let newPositionLstUpdCPF = $t06215768035._4
1600+ let positionBadDebt = $t06215768035._5
1601+ let realizedPnl = $t06215768035._6
1602+ let marginToTrader = $t06215768035._7
1603+ let quoteAssetReserveAfter = $t06215768035._8
1604+ let baseAssetReserveAfter = $t06215768035._9
1605+ let totalPositionSizeAfter = $t06215768035._10
1606+ let openInterestNotionalAfter = $t06215768035._11
1607+ let totalLongAfter = $t06215768035._12
1608+ let totalShortAfter = $t06215768035._13
1609+ let totalLongOpenInterestAfter = $t06215768035._14
1610+ let totalShortOpenInterestAfter = $t06215768035._15
1611+ let realizedFee = $t06215768035._16
17191612 if ((positionBadDebt > 0))
17201613 then throw("Unable to close position with bad debt")
17211614 else {
1722- let withdrawAmount = abs(marginToVault)
1615+ let isPartialClose = (newPositionSize != 0)
1616+ let withdrawAmount = (marginToTrader + realizedFee)
17231617 let ammBalance = (cbalance() - withdrawAmount)
1724- let $t07220872415 = if ((0 > ammBalance))
1618+ let $t06830268509 = if ((0 > ammBalance))
17251619 then $Tuple2(0, abs(ammBalance))
17261620 else $Tuple2(ammBalance, 0)
1727- let ammNewBalance = $t07220872415._1
1728- let x11 = $t07220872415._2
1729- let $t07242272476 = getBorrowedByTrader(_trader)
1730- let borrowed = $t07242272476._1
1731- let assetId = $t07242272476._2
1732- let $t07249173350 = if ((borrowed > 0))
1621+ let ammNewBalance = $t06830268509._1
1622+ let x11 = $t06830268509._2
1623+ let $t06851668570 = getBorrowedByTrader(_trader)
1624+ let borrowed = $t06851668570._1
1625+ let assetId = $t06851668570._2
1626+ let $t06857869438 = if ((borrowed > 0))
17331627 then if ((withdrawAmount >= borrowed))
17341628 then {
17351629 let doRepay = invoke(collateralAddress(), "repay", [_trader, borrowed, assetId], nil)
17361630 if ((doRepay == doRepay))
1737- then $Tuple2([ScriptTransfer(_traderAddress, borrowed, fromBase58String(assetId))], (withdrawAmount - borrowed))
1631+ then $Tuple3(borrowed, (withdrawAmount - borrowed), isPartialClose)
17381632 else throw("Strict value is not equal to itself.")
17391633 }
17401634 else {
1741- let realizeAndClose = invoke(collateralAddress(), "realizePartiallyAndClose", [_trader, withdrawAmount, assetId], nil)
1635+ let realizeAndClose = invoke(collateralAddress(), if (isPartialClose)
1636+ then "repay"
1637+ else "realizePartiallyAndClose", [_trader, withdrawAmount, assetId], nil)
17421638 if ((realizeAndClose == realizeAndClose))
1743- then $Tuple2([ScriptTransfer(_traderAddress, withdrawAmount, fromBase58String(assetId))], 0)
1639+ then $Tuple3(withdrawAmount, 0, false)
17441640 else throw("Strict value is not equal to itself.")
17451641 }
1746- else $Tuple2(nil, withdrawAmount)
1747- if (($t07249173350 == $t07249173350))
1642+ else $Tuple3(0, withdrawAmount, false)
1643+ if (($t06857869438 == $t06857869438))
17481644 then {
1749- let quoteWithdrawAmount = $t07249173350._2
1750- let sendCollateralAction = $t07249173350._1
1751- let unstake = if ((quoteWithdrawAmount > 0))
1752- then {
1753- let unstake = invoke(vaultAddress(), "withdrawLocked", [quoteWithdrawAmount], nil)
1754- if ((unstake == unstake))
1755- then nil
1645+ let switchToQuote = $t06857869438._3
1646+ let quoteWithdrawAmountBeforeFee = $t06857869438._2
1647+ let assetWithdrawAmountBeforeFee = $t06857869438._1
1648+ let $t06944670513 = if ((quoteWithdrawAmountBeforeFee >= realizedFee))
1649+ then $Tuple3(assetWithdrawAmountBeforeFee, (quoteWithdrawAmountBeforeFee - realizedFee), realizedFee)
1650+ else {
1651+ let feeLeftToWithdrawFromAsset = (realizedFee - quoteWithdrawAmountBeforeFee)
1652+ let assetWithdrawAmountAfterFee = (assetWithdrawAmountBeforeFee - feeLeftToWithdrawFromAsset)
1653+ let balanceBefore = assetBalance(this, quoteAsset())
1654+ if ((balanceBefore == balanceBefore))
1655+ then {
1656+ let doSwap = invoke(swapAddress(), "swap", [toBase58String(quoteAsset()), 0], [AttachedPayment(fromBase58String(assetId), feeLeftToWithdrawFromAsset)])
1657+ if ((doSwap == doSwap))
1658+ then {
1659+ let balanceAfter = assetBalance(this, quoteAsset())
1660+ if ((balanceAfter == balanceAfter))
1661+ then {
1662+ let exchangedAmount = (balanceAfter - balanceBefore)
1663+ if ((exchangedAmount == exchangedAmount))
1664+ then $Tuple3(assetWithdrawAmountAfterFee, 0, (quoteWithdrawAmountBeforeFee + exchangedAmount))
1665+ else throw("Strict value is not equal to itself.")
1666+ }
1667+ else throw("Strict value is not equal to itself.")
1668+ }
1669+ else throw("Strict value is not equal to itself.")
1670+ }
17561671 else throw("Strict value is not equal to itself.")
17571672 }
1758- else nil
1759- if ((unstake == unstake))
1673+ if (($t06944670513 == $t06944670513))
17601674 then {
1761- let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, 0], nil)
1762- if ((notifyNotional == notifyNotional))
1763- then (((((if ((newPositionSize == 0))
1764- then deletePosition(_trader)
1765- else updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ (if ((quoteWithdrawAmount > 0))
1766- then withdraw(_traderAddress, quoteWithdrawAmount)
1767- else nil)) ++ updateBalance(ammNewBalance)) ++ sendCollateralAction)
1675+ let actualFeeInQuoteAsset = $t06944670513._3
1676+ let quoteWithdrawAmountAfterFee = $t06944670513._2
1677+ let assetWithdrawAmountAfterFee = $t06944670513._1
1678+ let unstake = if ((quoteWithdrawAmountBeforeFee > 0))
1679+ then {
1680+ let unstake = invoke(vaultAddress(), "withdrawLocked", [quoteWithdrawAmountBeforeFee], nil)
1681+ if ((unstake == unstake))
1682+ then nil
1683+ else throw("Strict value is not equal to itself.")
1684+ }
1685+ else nil
1686+ if ((unstake == unstake))
1687+ then {
1688+ let $t07078770856 = distributeFee(actualFeeInQuoteAsset)
1689+ let feeToStakers = $t07078770856._1
1690+ let feeToVault = $t07078770856._2
1691+ let depositVault = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
1692+ if ((depositVault == depositVault))
1693+ then {
1694+ let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, realizedFee], nil)
1695+ if ((notifyFee == notifyFee))
1696+ then {
1697+ let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
1698+ if ((notifyNotional == notifyNotional))
1699+ then (((((((if (isPartialClose)
1700+ then updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF)
1701+ else deletePosition(_trader)) ++ (if (switchToQuote)
1702+ then {
1703+ let quoteAssetStr = toBase58String(quoteAsset())
1704+ updatePositionAsset(_trader, quoteAssetStr)
1705+ }
1706+ else nil)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ transferFee(feeToStakers)) ++ (if ((quoteWithdrawAmountAfterFee > 0))
1707+ then withdraw(_traderAddress, quoteWithdrawAmountAfterFee)
1708+ else nil)) ++ updateBalance(ammNewBalance)) ++ (if ((assetWithdrawAmountAfterFee > 0))
1709+ then [ScriptTransfer(_traderAddress, assetWithdrawAmountAfterFee, fromBase58String(assetId))]
1710+ else nil))
1711+ else throw("Strict value is not equal to itself.")
1712+ }
1713+ else throw("Strict value is not equal to itself.")
1714+ }
1715+ else throw("Strict value is not equal to itself.")
1716+ }
17681717 else throw("Strict value is not equal to itself.")
17691718 }
17701719 else throw("Strict value is not equal to itself.")
17711720 }
17721721 else throw("Strict value is not equal to itself.")
17731722 }
17741723 }
17751724 }
17761725 else throw("Strict value is not equal to itself.")
17771726 }
17781727
17791728
17801729
17811730 @Callable(i)
17821731 func liquidate (_trader) = {
17831732 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
17841733 if ((sync == sync))
17851734 then {
17861735 let spotMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
17871736 let marginRatio = if (isOverFluctuationLimit())
17881737 then {
17891738 let oracleMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_ORACLE)
17901739 vmax(spotMarginRatio, oracleMarginRatio)
17911740 }
17921741 else spotMarginRatio
17931742 if (if (if (if (if (!(requireMoreMarginRatio(marginRatio, maintenanceMarginRatio(), false)))
17941743 then true
17951744 else !(requireOpenPosition(_trader)))
17961745 then true
17971746 else !(initialized()))
17981747 then true
17991748 else paused())
18001749 then true
18011750 else isMarketClosed())
18021751 then throw("Unable to liquidate")
18031752 else if (if (if ((spotMarginRatio > liquidationFeeRatio()))
18041753 then (partialLiquidationRatio() > 0)
18051754 else false)
18061755 then (DECIMAL_UNIT > partialLiquidationRatio())
18071756 else false)
18081757 then {
1809- let $t07567175821 = getPosition(_trader)
1810- let oldPositionSize = $t07567175821._1
1811- let oldPositionMargin = $t07567175821._2
1812- let oldPositionOpenNotional = $t07567175821._3
1813- let oldPositionLstUpdCPF = $t07567175821._4
1758+ let $t07360973759 = getPosition(_trader)
1759+ let oldPositionSize = $t07360973759._1
1760+ let oldPositionMargin = $t07360973759._2
1761+ let oldPositionOpenNotional = $t07360973759._3
1762+ let oldPositionLstUpdCPF = $t07360973759._4
18141763 let _direction = if ((oldPositionSize > 0))
18151764 then DIR_SHORT
18161765 else DIR_LONG
18171766 let isAdd = (_direction == DIR_LONG)
18181767 let exchangedQuoteAssetAmount = getPartialLiquidationAmount(_trader, oldPositionSize)
1819- let $t07604676150 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1820- let oldPositionNotional = $t07604676150._1
1821- let unrealizedPnl = $t07604676150._2
1822- let $t07615876345 = swapInput(isAdd, exchangedQuoteAssetAmount)
1823- let exchangedPositionSize = $t07615876345._1
1824- let quoteAssetReserveAfter = $t07615876345._2
1825- let baseAssetReserveAfter = $t07615876345._3
1826- let totalPositionSizeAfter = $t07615876345._4
1768+ let $t07398474088 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1769+ let oldPositionNotional = $t07398474088._1
1770+ let unrealizedPnl = $t07398474088._2
1771+ let $t07409674283 = swapInput(isAdd, exchangedQuoteAssetAmount)
1772+ let exchangedPositionSize = $t07409674283._1
1773+ let quoteAssetReserveAfter = $t07409674283._2
1774+ let baseAssetReserveAfter = $t07409674283._3
1775+ let totalPositionSizeAfter = $t07409674283._4
18271776 let liquidationRatio = divd(abs(exchangedPositionSize), abs(oldPositionSize))
18281777 let realizedPnl = muld(unrealizedPnl, liquidationRatio)
1829- let $t07663476867 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1830- let remainMargin = $t07663476867._1
1831- let badDebt = $t07663476867._2
1832- let fundingPayment = $t07663476867._3
1778+ let $t07457274805 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1779+ let remainMargin = $t07457274805._1
1780+ let badDebt = $t07457274805._2
1781+ let fundingPayment = $t07457274805._3
18331782 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
18341783 let remainOpenNotional = if ((oldPositionSize > 0))
18351784 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
18361785 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
18371786 let liquidationPenalty = muld(exchangedQuoteAssetAmount, liquidationFeeRatio())
18381787 let feeToLiquidator = (liquidationPenalty / 2)
18391788 let feeToVault = (liquidationPenalty - feeToLiquidator)
18401789 let newPositionMargin = (remainMargin - liquidationPenalty)
18411790 let newPositionSize = (oldPositionSize + exchangedPositionSize)
18421791 let newPositionOpenNotional = abs(remainOpenNotional)
18431792 let openNotionalDelta = (oldPositionOpenNotional - newPositionOpenNotional)
18441793 let newPositionLstUpdCPF = latestCumulativePremiumFraction(newPositionSize)
18451794 let openInterestNotionalAfter = (openInterestNotional() - openNotionalDelta)
18461795 let ammBalance = (cbalance() - liquidationPenalty)
1847- let $t07810878237 = if ((0 > ammBalance))
1796+ let $t07604676175 = if ((0 > ammBalance))
18481797 then $Tuple2(0, abs(ammBalance))
18491798 else $Tuple2(ammBalance, 0)
1850- let newAmmBalance = $t07810878237._1
1851- let x11 = $t07810878237._2
1852- let $t07824578299 = getBorrowedByTrader(_trader)
1853- let borrowed = $t07824578299._1
1854- let assetId = $t07824578299._2
1799+ let newAmmBalance = $t07604676175._1
1800+ let x11 = $t07604676175._2
1801+ let $t07618376237 = getBorrowedByTrader(_trader)
1802+ let borrowed = $t07618376237._1
1803+ let assetId = $t07618376237._2
18551804 let doLiquidateCollateral = if ((borrowed > 0))
18561805 then {
18571806 let collateralToSell = muld(borrowed, liquidationRatio)
18581807 let realizeAndClose = invoke(collateralAddress(), "realizePartially", [_trader, assetId, collateralToSell], nil)
18591808 if ((realizeAndClose == realizeAndClose))
18601809 then nil
18611810 else throw("Strict value is not equal to itself.")
18621811 }
18631812 else nil
18641813 if ((doLiquidateCollateral == doLiquidateCollateral))
18651814 then {
18661815 let unstake = invoke(vaultAddress(), "withdrawLocked", [liquidationPenalty], nil)
18671816 if ((unstake == unstake))
18681817 then {
18691818 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
18701819 if ((depositInsurance == depositInsurance))
18711820 then {
18721821 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
18731822 if ((notifyNotional == notifyNotional))
18741823 then (((updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, (totalLongPositionSize() - (if ((newPositionSize > 0))
18751824 then abs(exchangedPositionSize)
18761825 else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
18771826 then abs(exchangedPositionSize)
18781827 else 0)), (openInterestLong() - (if ((newPositionSize > 0))
18791828 then openNotionalDelta
18801829 else 0)), (openInterestShort() - (if ((0 > newPositionSize))
18811830 then openNotionalDelta
18821831 else 0)))) ++ withdraw(i.caller, feeToLiquidator)) ++ updateBalance(newAmmBalance))
18831832 else throw("Strict value is not equal to itself.")
18841833 }
18851834 else throw("Strict value is not equal to itself.")
18861835 }
18871836 else throw("Strict value is not equal to itself.")
18881837 }
18891838 else throw("Strict value is not equal to itself.")
18901839 }
18911840 else {
1892- let $t07997880473 = internalClosePosition(_trader, false)
1893- let x1 = $t07997880473._1
1894- let badDebt = $t07997880473._2
1895- let x2 = $t07997880473._3
1896- let x3 = $t07997880473._4
1897- let quoteAssetReserveAfter = $t07997880473._5
1898- let baseAssetReserveAfter = $t07997880473._6
1899- let totalPositionSizeAfter = $t07997880473._7
1900- let openInterestNotionalAfter = $t07997880473._8
1901- let exchangedQuoteAssetAmount = $t07997880473._9
1902- let totalLongAfter = $t07997880473._10
1903- let totalShortAfter = $t07997880473._11
1904- let totalLongOpenInterestAfter = $t07997880473._12
1905- let totalShortOpenInterestAfter = $t07997880473._13
1841+ let $t07791678411 = internalClosePosition(_trader, false)
1842+ let x1 = $t07791678411._1
1843+ let badDebt = $t07791678411._2
1844+ let x2 = $t07791678411._3
1845+ let x3 = $t07791678411._4
1846+ let quoteAssetReserveAfter = $t07791678411._5
1847+ let baseAssetReserveAfter = $t07791678411._6
1848+ let totalPositionSizeAfter = $t07791678411._7
1849+ let openInterestNotionalAfter = $t07791678411._8
1850+ let exchangedQuoteAssetAmount = $t07791678411._9
1851+ let totalLongAfter = $t07791678411._10
1852+ let totalShortAfter = $t07791678411._11
1853+ let totalLongOpenInterestAfter = $t07791678411._12
1854+ let totalShortOpenInterestAfter = $t07791678411._13
19061855 let liquidationPenalty = muld(exchangedQuoteAssetAmount, liquidationFeeRatio())
19071856 let feeToLiquidator = (liquidationPenalty / 2)
19081857 let feeToVault = (liquidationPenalty - feeToLiquidator)
19091858 let ammBalance = (cbalance() - liquidationPenalty)
1910- let $t08088181010 = if ((0 > ammBalance))
1859+ let $t07881978948 = if ((0 > ammBalance))
19111860 then $Tuple2(0, abs(ammBalance))
19121861 else $Tuple2(ammBalance, 0)
1913- let newAmmBalance = $t08088181010._1
1914- let x11 = $t08088181010._2
1915- let $t08101881072 = getBorrowedByTrader(_trader)
1916- let borrowed = $t08101881072._1
1917- let assetId = $t08101881072._2
1862+ let newAmmBalance = $t07881978948._1
1863+ let x11 = $t07881978948._2
1864+ let $t07895679010 = getBorrowedByTrader(_trader)
1865+ let borrowed = $t07895679010._1
1866+ let assetId = $t07895679010._2
19181867 let doLiquidateCollateral = if ((borrowed > 0))
19191868 then {
19201869 let realizeAndClose = invoke(collateralAddress(), "realizePartiallyAndClose", [_trader, 0, assetId], nil)
19211870 if ((realizeAndClose == realizeAndClose))
19221871 then nil
19231872 else throw("Strict value is not equal to itself.")
19241873 }
19251874 else nil
19261875 if ((doLiquidateCollateral == doLiquidateCollateral))
19271876 then {
19281877 let x = if ((badDebt > 0))
19291878 then {
19301879 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [badDebt], nil)
19311880 if ((lockBadDebt == lockBadDebt))
19321881 then nil
19331882 else throw("Strict value is not equal to itself.")
19341883 }
19351884 else nil
19361885 if ((x == x))
19371886 then {
19381887 let unstake = invoke(vaultAddress(), "withdrawLocked", [liquidationPenalty], nil)
19391888 if ((unstake == unstake))
19401889 then {
19411890 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
19421891 if ((depositInsurance == depositInsurance))
19431892 then {
19441893 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, 0], nil)
19451894 if ((notifyNotional == notifyNotional))
19461895 then (((deletePosition(_trader) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ withdraw(i.caller, feeToLiquidator)) ++ updateBalance(newAmmBalance))
19471896 else throw("Strict value is not equal to itself.")
19481897 }
19491898 else throw("Strict value is not equal to itself.")
19501899 }
19511900 else throw("Strict value is not equal to itself.")
19521901 }
19531902 else throw("Strict value is not equal to itself.")
19541903 }
19551904 else throw("Strict value is not equal to itself.")
19561905 }
19571906 }
19581907 else throw("Strict value is not equal to itself.")
19591908 }
19601909
19611910
19621911
19631912 @Callable(i)
19641913 func payFunding () = {
19651914 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
19661915 if ((sync == sync))
19671916 then {
19681917 let fundingBlockTimestamp = nextFundingBlockTimestamp()
19691918 if (if (if ((fundingBlockTimestamp > lastBlock.timestamp))
19701919 then true
19711920 else !(initialized()))
19721921 then true
19731922 else paused())
19741923 then throw(((("Invalid funding block timestamp: " + toString(lastBlock.timestamp)) + " < ") + toString(fundingBlockTimestamp)))
19751924 else {
19761925 let underlyingPrice = getOraclePrice()
1977- let $t08294483006 = getFunding()
1978- let shortPremiumFraction = $t08294483006._1
1979- let longPremiumFraction = $t08294483006._2
1926+ let $t08088280944 = getFunding()
1927+ let shortPremiumFraction = $t08088280944._1
1928+ let longPremiumFraction = $t08088280944._2
19801929 updateFunding((fundingBlockTimestamp + fundingPeriodSeconds()), (latestLongCumulativePremiumFraction() + longPremiumFraction), (latestShortCumulativePremiumFraction() + shortPremiumFraction), divd(longPremiumFraction, underlyingPrice), divd(shortPremiumFraction, underlyingPrice))
19811930 }
19821931 }
19831932 else throw("Strict value is not equal to itself.")
19841933 }
19851934
19861935
19871936
19881937 @Callable(i)
19891938 func syncTerminalPriceToOracle () = {
19901939 let _qtAstR = qtAstR()
19911940 let _bsAstR = bsAstR()
1992- let $t08343883573 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1993- let newQuoteAssetWeight = $t08343883573._1
1994- let newBaseAssetWeight = $t08343883573._2
1995- let marginToVault = $t08343883573._3
1941+ let $t08137681511 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1942+ let newQuoteAssetWeight = $t08137681511._1
1943+ let newBaseAssetWeight = $t08137681511._2
1944+ let marginToVault = $t08137681511._3
19961945 let doExchangePnL = if ((marginToVault != 0))
19971946 then {
19981947 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
19991948 if ((doExchangePnL == doExchangePnL))
20001949 then nil
20011950 else throw("Strict value is not equal to itself.")
20021951 }
20031952 else nil
20041953 if ((doExchangePnL == doExchangePnL))
20051954 then (updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight) ++ appendTwap(divd(muld(_qtAstR, newQuoteAssetWeight), muld(_bsAstR, newBaseAssetWeight))))
20061955 else throw("Strict value is not equal to itself.")
20071956 }
20081957
20091958
20101959
20111960 @Callable(i)
20121961 func view_calcRemainMarginWithFundingPayment (_trader) = {
20131962 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
20141963 if ((sync == sync))
20151964 then {
2016- let $t08414284243 = getPosition(_trader)
2017- let positionSize = $t08414284243._1
2018- let positionMargin = $t08414284243._2
2019- let pon = $t08414284243._3
2020- let positionLstUpdCPF = $t08414284243._4
2021- let $t08424684347 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
2022- let positionNotional = $t08424684347._1
2023- let unrealizedPnl = $t08424684347._2
2024- let $t08435084522 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
2025- let remainMargin = $t08435084522._1
2026- let badDebt = $t08435084522._2
2027- let fundingPayment = $t08435084522._3
1965+ let $t08208082181 = getPosition(_trader)
1966+ let positionSize = $t08208082181._1
1967+ let positionMargin = $t08208082181._2
1968+ let pon = $t08208082181._3
1969+ let positionLstUpdCPF = $t08208082181._4
1970+ let $t08218482285 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1971+ let positionNotional = $t08218482285._1
1972+ let unrealizedPnl = $t08218482285._2
1973+ let $t08228882460 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
1974+ let remainMargin = $t08228882460._1
1975+ let badDebt = $t08228882460._2
1976+ let fundingPayment = $t08228882460._3
20281977 throw((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)))
20291978 }
20301979 else throw("Strict value is not equal to itself.")
20311980 }
20321981
20331982
20341983
20351984 @Callable(i)
20361985 func view_getPegAdjustCost (_price) = {
20371986 let _qtAstR = qtAstR()
20381987 let _bsAstR = bsAstR()
20391988 let result = getSyncTerminalPrice(_price, _qtAstR, _bsAstR)
20401989 throw(toString(result._3))
20411990 }
20421991
20431992
20441993
20451994 @Callable(i)
20461995 func view_getTerminalAmmPrice () = {
2047- let $t08493885019 = getTerminalAmmState()
2048- let terminalQuoteAssetReserve = $t08493885019._1
2049- let terminalBaseAssetReserve = $t08493885019._2
1996+ let $t08287682957 = getTerminalAmmState()
1997+ let terminalQuoteAssetReserve = $t08287682957._1
1998+ let terminalBaseAssetReserve = $t08287682957._2
20501999 let price = divd(muld(terminalQuoteAssetReserve, qtAstW()), muld(terminalBaseAssetReserve, bsAstW()))
20512000 throw(toString(price))
20522001 }
20532002
20542003
20552004
20562005 @Callable(i)
20572006 func view_getFunding () = {
20582007 let underlyingPrice = getOraclePrice()
2059- let $t08523485296 = getFunding()
2060- let shortPremiumFraction = $t08523485296._1
2061- let longPremiumFraction = $t08523485296._2
2008+ let $t08317283234 = getFunding()
2009+ let shortPremiumFraction = $t08317283234._1
2010+ let longPremiumFraction = $t08317283234._2
20622011 let longFunding = divd(longPremiumFraction, underlyingPrice)
20632012 let shortFunding = divd(shortPremiumFraction, underlyingPrice)
20642013 throw((((s(longFunding) + s(shortFunding)) + s(getTwapSpotPrice())) + s(getOraclePrice())))
20652014 }
20662015
20672016
20682017
20692018 @Callable(i)
20702019 func view_getBorrowedByTrader (_trader) = {
2071- let $t08558285636 = getBorrowedByTrader(_trader)
2072- let borrowed = $t08558285636._1
2073- let assetId = $t08558285636._2
2020+ let $t08352083574 = getBorrowedByTrader(_trader)
2021+ let borrowed = $t08352083574._1
2022+ let assetId = $t08352083574._2
20742023 throw((s(borrowed) + assetId))
20752024 }
20762025
20772026
20782027
20792028 @Callable(i)
20802029 func computeSpotPrice () = {
20812030 let result = getSpotPrice()
20822031 $Tuple2(nil, result)
20832032 }
20842033
20852034
20862035
20872036 @Callable(i)
20882037 func computeFeeForTraderWithArtifact (_trader,_artifactId) = {
20892038 let result = getForTraderWithArtifact(_trader, _artifactId)
20902039 $Tuple2(nil, result)
20912040 }
20922041
20932042
20942043 @Verifier(tx)
20952044 func verify () = sigVerify(tx.bodyBytes, tx.proofs[0], adminPublicKey())
20962045

github/deemru/w8io/169f3d6 
264.35 ms